diff --git a/Dendro.sln b/Dendro.sln new file mode 100644 index 0000000..a6a1daa --- /dev/null +++ b/Dendro.sln @@ -0,0 +1,49 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27130.2026 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DendroGH", "DendroGH\DendroGH.csproj", "{A45EBB63-85ED-4B96-BC3A-21221C1DC605}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DendroAPI", "DendroAPI\DendroAPI.vcxproj", "{FBDAB1F6-294A-4978-A8EA-5E4479D86E67}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A45EBB63-85ED-4B96-BC3A-21221C1DC605}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A45EBB63-85ED-4B96-BC3A-21221C1DC605}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A45EBB63-85ED-4B96-BC3A-21221C1DC605}.Debug|x64.ActiveCfg = Debug|Any CPU + {A45EBB63-85ED-4B96-BC3A-21221C1DC605}.Debug|x64.Build.0 = Debug|Any CPU + {A45EBB63-85ED-4B96-BC3A-21221C1DC605}.Debug|x86.ActiveCfg = Debug|Any CPU + {A45EBB63-85ED-4B96-BC3A-21221C1DC605}.Debug|x86.Build.0 = Debug|Any CPU + {A45EBB63-85ED-4B96-BC3A-21221C1DC605}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A45EBB63-85ED-4B96-BC3A-21221C1DC605}.Release|Any CPU.Build.0 = Release|Any CPU + {A45EBB63-85ED-4B96-BC3A-21221C1DC605}.Release|x64.ActiveCfg = Release|Any CPU + {A45EBB63-85ED-4B96-BC3A-21221C1DC605}.Release|x64.Build.0 = Release|Any CPU + {A45EBB63-85ED-4B96-BC3A-21221C1DC605}.Release|x86.ActiveCfg = Release|Any CPU + {A45EBB63-85ED-4B96-BC3A-21221C1DC605}.Release|x86.Build.0 = Release|Any CPU + {FBDAB1F6-294A-4978-A8EA-5E4479D86E67}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {FBDAB1F6-294A-4978-A8EA-5E4479D86E67}.Debug|x64.ActiveCfg = Debug|x64 + {FBDAB1F6-294A-4978-A8EA-5E4479D86E67}.Debug|x64.Build.0 = Debug|x64 + {FBDAB1F6-294A-4978-A8EA-5E4479D86E67}.Debug|x86.ActiveCfg = Debug|Win32 + {FBDAB1F6-294A-4978-A8EA-5E4479D86E67}.Debug|x86.Build.0 = Debug|Win32 + {FBDAB1F6-294A-4978-A8EA-5E4479D86E67}.Release|Any CPU.ActiveCfg = Release|Win32 + {FBDAB1F6-294A-4978-A8EA-5E4479D86E67}.Release|x64.ActiveCfg = Release|x64 + {FBDAB1F6-294A-4978-A8EA-5E4479D86E67}.Release|x64.Build.0 = Release|x64 + {FBDAB1F6-294A-4978-A8EA-5E4479D86E67}.Release|x86.ActiveCfg = Release|Win32 + {FBDAB1F6-294A-4978-A8EA-5E4479D86E67}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {F1437CD9-98E7-471F-B180-29A544082308} + EndGlobalSection +EndGlobal diff --git a/DendroAPI/DendroAPI.cpp b/DendroAPI/DendroAPI.cpp new file mode 100644 index 0000000..dff36e7 Binary files /dev/null and b/DendroAPI/DendroAPI.cpp differ diff --git a/DendroAPI/DendroAPI.h b/DendroAPI/DendroAPI.h new file mode 100644 index 0000000..54ced80 --- /dev/null +++ b/DendroAPI/DendroAPI.h @@ -0,0 +1,57 @@ +#pragma once +#pragma once + +#ifndef __DENDROAPI_H__ +#define __DENDROAPI_H__ + +#include "DendroGrid.h" + +#ifdef DENDROAPI_EXPORTS +#define DENDRO_API __declspec(dllexport) +#else +#define DENDRO_API __declspec(dllimport) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + // ovdb volume class constructors + extern DENDRO_API DendroGrid* DendroCreate(); + extern DENDRO_API void DendroDelete(DendroGrid* grid); + extern DENDRO_API DendroGrid* DendroDuplicate(DendroGrid * grid); + + extern DENDRO_API bool DendroRead(DendroGrid * grid, const char * filename); + extern DENDRO_API bool DendroWrite(DendroGrid * grid, const char * filename); + + // volume conversion methods + extern DENDRO_API bool DendroFromPoints(DendroGrid * grid, double *vPoints, int pCount, double *vRadius, int rCount, double voxelSize, double bandwidth); + extern DENDRO_API bool DendroFromMesh(DendroGrid * grid, float* vPoints, int vCount, int * vFaces, int fCount, double voxelSize, double bandwidth); + + // volume render methods + extern DENDRO_API void DendroToMesh(DendroGrid * grid); + extern DENDRO_API void DendroToMeshSettings(DendroGrid * grid, double isovalue, double adaptivity); + + extern DENDRO_API float* DendroVertexBuffer(DendroGrid * grid, int* size); + extern DENDRO_API int* DendroFaceBuffer(DendroGrid * grid, int* size); + + // volume transformation methods + extern DENDRO_API bool DendroTransform(DendroGrid * grid, double* matrix, int mCount); + + // volume csg methods + extern DENDRO_API void DendroUnion(DendroGrid * grid, DendroGrid * csgGrid); + extern DENDRO_API void DendroDifference(DendroGrid * grid, DendroGrid * csgGrid); + extern DENDRO_API void DendroIntersection(DendroGrid * grid, DendroGrid * csgGrid); + + // volume filter methods + extern DENDRO_API void DendroOffset(DendroGrid * grid, double amount); + extern DENDRO_API void DendroOffsetMask(DendroGrid * grid, double amount, DendroGrid * mask, double min, double max, bool invert); + extern DENDRO_API void DendroSmooth(DendroGrid * grid, int type, int iterations, int width); + extern DENDRO_API void DendroSmoothMask(DendroGrid * grid, int type, int iterations, int width, DendroGrid * mask, double min, double max, bool invert); + extern DENDRO_API void DendroBlend(DendroGrid * bGrid, DendroGrid * eGrid, double bPosition, double bEnd); + extern DENDRO_API void DendroBlendMask(DendroGrid * bGrid, DendroGrid * eGrid, double bPosition, double bEnd, DendroGrid * mask, double min, double max, bool invert); + +#ifdef __cplusplus +} +#endif + +#endif // __DENDROAPI_H__ \ No newline at end of file diff --git a/DendroAPI/DendroAPI.vcxproj b/DendroAPI/DendroAPI.vcxproj new file mode 100644 index 0000000..f13c335 --- /dev/null +++ b/DendroAPI/DendroAPI.vcxproj @@ -0,0 +1,208 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {FBDAB1F6-294A-4978-A8EA-5E4479D86E67} + Win32Proj + DendroAPI + 10.0.16299.0 + + + + DynamicLibrary + true + v141 + Unicode + + + DynamicLibrary + false + v141 + true + Unicode + + + DynamicLibrary + true + v141 + Unicode + + + DynamicLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + $(SolutionDir)$(Platform)\$(Configuration)\ + + + + Use + Level3 + Disabled + true + WIN32;_DEBUG;DENDROAPI_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + + + Windows + true + + + + + Use + Level3 + Disabled + false + OPENVDB_3_ABI_COMPATIBLE;OPENEXR_DLL;OPENVDB_STATICLIB;HALF_EXPORTS;NOMINMAX;_DEBUG;DENDROAPI_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + %(AdditionalIncludeDirectories) + /bigobj %(AdditionalOptions) + + + Windows + true + + + COPY "$(SolutionDir)packages\tbb.2018.6.18\build\native\bin\Debug" "$(TargetDir)" + + + + + Use + Level3 + MaxSpeed + true + true + true + WIN32;NDEBUG;DENDROAPI_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + + + + + Use + Level3 + MaxSpeed + true + true + false + OPENVDB_3_ABI_COMPATIBLE;OPENEXR_DLL;OPENVDB_STATICLIB;HALF_EXPORTS;NOMINMAX;NDEBUG;DENDROAPI_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + %(AdditionalIncludeDirectories) + false + + + Windows + true + true + true + %(AdditionalLibraryDirectories) + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + COPY "$(SolutionDir)packages\tbb.2018.6.18\build\native\bin\Release" "$(TargetDir)" + + + + + + + + + + + + + + + + + Create + Create + Create + Create + + + + + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + + + \ No newline at end of file diff --git a/DendroAPI/DendroAPI.vcxproj.filters b/DendroAPI/DendroAPI.vcxproj.filters new file mode 100644 index 0000000..d3ff318 --- /dev/null +++ b/DendroAPI/DendroAPI.vcxproj.filters @@ -0,0 +1,58 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + + + \ No newline at end of file diff --git a/DendroAPI/DendroGrid.cpp b/DendroAPI/DendroGrid.cpp new file mode 100644 index 0000000..751af1e --- /dev/null +++ b/DendroAPI/DendroGrid.cpp @@ -0,0 +1,430 @@ +#include "stdafx.h" +#include "DendroGrid.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +DendroGrid::DendroGrid() +{ + openvdb::initialize(); +} + +DendroGrid::DendroGrid(DendroGrid * grid) +{ + openvdb::initialize(); + mGrid = grid->Grid()->deepCopy(); + mDisplay = grid->Display().Duplicate(); +} + +DendroGrid::~DendroGrid() +{ +} + +openvdb::FloatGrid::Ptr DendroGrid::Grid() +{ + return mGrid; +} + +bool DendroGrid::Read(const char * vFile) +{ + openvdb::io::File file(vFile); + + file.open(); + + openvdb::io::File::NameIterator nameIter = file.beginName(); + if (nameIter == file.endName()) { + return false; + } + + mGrid = openvdb::gridPtrCast(file.readGrid(nameIter.gridName())); + + return true; +} + +bool DendroGrid::Write(const char * vFile) +{ + openvdb::GridPtrVec grids; + grids.push_back(mGrid); + + openvdb::io::File file(vFile); + file.write(grids); + file.close(); + + return true; +} + +bool DendroGrid::CreateFromMesh(DendroMesh vMesh, double voxelSize, double bandwidth) +{ + if (!vMesh.IsValid()) { + return false; + } + + openvdb::math::Transform xform; + xform.preScale(voxelSize); + + auto vertices = vMesh.Vertices(); + auto faces = vMesh.Faces(); + + openvdb::tools::QuadAndTriangleDataAdapter mesh(vertices, faces); + mGrid = openvdb::tools::meshToVolume(mesh, xform, static_cast(bandwidth), static_cast(bandwidth), 0, NULL); + + mDisplay = vMesh; + + return true; +} + +bool DendroGrid::CreateFromPoints(DendroParticle vPoints, double voxelSize, double bandwidth) +{ + if (!vPoints.IsValid()) { + return false; + } + + mGrid = openvdb::createLevelSet(voxelSize, bandwidth); + openvdb::tools::ParticlesToLevelSet raster(*mGrid); + + openvdb::math::Transform::Ptr xform = openvdb::math::Transform::createLinearTransform(voxelSize); + mGrid->setTransform(xform); + + raster.setGrainSize(1); + raster.rasterizeSpheres(vPoints); + raster.finalize(); + + return true; +} + +void DendroGrid::Transform(openvdb::math::Mat4d xform) +{ + mGrid->transform().postMult(xform); +} + +void DendroGrid::BooleanUnion(DendroGrid vAdd) +{ + auto csgGrid = vAdd.Grid(); + + // store current tranforms of both csg volumes + const openvdb::math::Transform + &sourceXform = csgGrid->transform(), + &targetXform = mGrid->transform(); + + // create a copy of the source grid for resampling + openvdb::FloatGrid::Ptr cGrid = openvdb::createLevelSet(mGrid->voxelSize()[0]); + cGrid->transform() = mGrid->transform(); + + // compute a source grid to target grid transform + openvdb::Mat4R xform = + sourceXform.baseMap()->getAffineMap()->getMat4() * + targetXform.baseMap()->getAffineMap()->getMat4().inverse(); + + // create the transformer + openvdb::tools::GridTransformer transformer(xform); + + // resample using trilinear interpolation + transformer.transformGrid(*csgGrid, *cGrid); + + // solve for the csg operation with result being stored in mGrid + openvdb::tools::csgUnion(*mGrid, *cGrid, true); +} + +void DendroGrid::BooleanIntersection(DendroGrid vIntersect) +{ + auto csgGrid = vIntersect.Grid(); + + // store current tranforms of both csg volumes + const openvdb::math::Transform + &sourceXform = csgGrid->transform(), + &targetXform = mGrid->transform(); + + // create a copy of the source grid for resampling + openvdb::FloatGrid::Ptr cGrid = openvdb::createLevelSet(mGrid->voxelSize()[0]); + cGrid->transform() = mGrid->transform(); + + // compute a source grid to target grid transform + openvdb::Mat4R xform = + sourceXform.baseMap()->getAffineMap()->getMat4() * + targetXform.baseMap()->getAffineMap()->getMat4().inverse(); + + // create the transformer + openvdb::tools::GridTransformer transformer(xform); + + // resample using trilinear interpolation + transformer.transformGrid(*csgGrid, *cGrid); + + // solve for the csg operation with result being stored in mGrid + openvdb::tools::csgIntersection(*mGrid, *cGrid, true); +} + +void DendroGrid::BooleanDifference(DendroGrid vSubtract) +{ + auto csgGrid = vSubtract.Grid(); + + // store current tranforms of both csg volumes + const openvdb::math::Transform + &sourceXform = csgGrid->transform(), + &targetXform = mGrid->transform(); + + // create a copy of the source grid for resampling + openvdb::FloatGrid::Ptr cGrid = openvdb::createLevelSet(mGrid->voxelSize()[0]); + cGrid->transform() = mGrid->transform(); + + // compute a source grid to target grid transform + openvdb::Mat4R xform = + sourceXform.baseMap()->getAffineMap()->getMat4() * + targetXform.baseMap()->getAffineMap()->getMat4().inverse(); + + // create the transformer + openvdb::tools::GridTransformer transformer(xform); + + // resample using trilinear interpolation + transformer.transformGrid(*csgGrid, *cGrid); + + // solve for the csg operation with result being stored in mGrid + openvdb::tools::csgDifference(*mGrid, *cGrid, true); +} + +void DendroGrid::Offset(double amount) +{ + // create a new filter to operate on grid with + openvdb::tools::LevelSetFilter filter(*mGrid); + + filter.setGrainSize(1); + + amount = amount * -1; + + // apply offset to grid of supplied amount + filter.offset((float)amount); +} + +void DendroGrid::Offset(double amount, DendroGrid vMask, double min, double max, bool invert) +{ + // create a new filter to operate on grid with + openvdb::tools::LevelSetFilter filter(*mGrid); + + filter.invertMask(invert); + filter.setMaskRange((float)min, (float)max); + filter.setGrainSize(1); + + // create filter mask + openvdb::Grid mMask(*vMask.Grid()); + + amount = amount * -1; + + // apply offset to grid of supplied amount + filter.offset((float)amount, &mMask); +} + +void DendroGrid::Smooth(int type, int iterations, int width) +{ + // create a new filter to operate on grid with + openvdb::tools::LevelSetFilter filter(*mGrid); + filter.setGrainSize(1); + + // apply filter for the number iterations supplied + for (int i = 0; i < iterations; i++) { + + // filter by desired type supplied + switch (type) { + case 0: + filter.gaussian(width); + break; + case 1: + filter.laplacian(); + break; + case 2: + filter.mean(width); + break; + case 3: + filter.median(width); + break; + default: + filter.laplacian(); + break; + } + } +} + +void DendroGrid::Smooth(int type, int iterations, int width, DendroGrid vMask, double min, double max, bool invert) +{ + // create a new filter to operate on grid with + openvdb::tools::LevelSetFilter filter(*mGrid); + + filter.invertMask(invert); + filter.setMaskRange((float)min, (float)max); + filter.setGrainSize(1); + + // create filter mask + openvdb::Grid mMask(*vMask.Grid()); + + // apply filter for the number iterations supplied + for (int i = 0; i < iterations; i++) { + + // filter by desired type supplied + switch (type) { + case 0: + filter.gaussian(width, &mMask); + break; + case 1: + filter.laplacian(&mMask); + break; + case 2: + filter.mean(width, &mMask); + break; + case 3: + filter.median(width, &mMask); + break; + default: + filter.laplacian(&mMask); + break; + } + } +} + +void DendroGrid::Blend(DendroGrid bGrid, double bPosition, double bEnd) +{ + openvdb::tools::LevelSetMorphing morph(*mGrid, *bGrid.Grid()); + morph.setSpatialScheme(openvdb::math::HJWENO5_BIAS); + morph.setTemporalScheme(openvdb::math::TVD_RK3); + morph.setTrackerSpatialScheme(openvdb::math::HJWENO5_BIAS); + morph.setTrackerTemporalScheme(openvdb::math::TVD_RK2); + morph.setGrainSize(1); + + double bStart = bPosition * bEnd; + morph.advect(bStart, bEnd); +} + +void DendroGrid::Blend(DendroGrid bGrid, double bPosition, double bEnd, DendroGrid vMask, double mMin, double mMax, bool invert) +{ + openvdb::tools::LevelSetMorphing morph(*mGrid, *bGrid.Grid()); + morph.setSpatialScheme(openvdb::math::HJWENO5_BIAS); + morph.setTemporalScheme(openvdb::math::TVD_RK3); + morph.setTrackerSpatialScheme(openvdb::math::HJWENO5_BIAS); + morph.setTrackerTemporalScheme(openvdb::math::TVD_RK2); + + morph.setAlphaMask(*vMask.Grid()); + morph.invertMask(invert); + morph.setMaskRange((float)mMin, (float)mMax); + morph.setGrainSize(1); + + double bStart = bPosition * bEnd; + morph.advect(bStart, bEnd); +} + +DendroMesh DendroGrid::Display() +{ + return mDisplay; +} + +void DendroGrid::UpdateDisplay() +{ + using openvdb::Index64; + + openvdb::tools::VolumeToMesh mesher(mGrid->getGridClass() == openvdb::GRID_LEVEL_SET ? 0.0 : 0.01); + mesher(*mGrid); + + mDisplay.Clear(); + + for (Index64 n = 0, i = 0, N = mesher.pointListSize(); n < N; ++n) + { + auto v = mesher.pointList()[n]; + mDisplay.AddVertice(v); + } + + openvdb::tools::PolygonPoolList &polygonPoolList = mesher.polygonPoolList(); + + for (Index64 n = 0, N = mesher.polygonPoolListSize(); n < N; ++n) + { + const openvdb::tools::PolygonPool &polygons = polygonPoolList[n]; + for (Index64 i = 0, I = polygons.numQuads(); i < I; ++i) + { + auto face = polygons.quad(i); + mDisplay.AddFace(face); + } + } +} + +void DendroGrid::UpdateDisplay(double isovalue, double adaptivity) +{ + isovalue /= mGrid->voxelSize().x(); + + std::vector points; + std::vector quads; + std::vector triangles; + + openvdb::tools::volumeToMesh(*mGrid, points, triangles, quads, isovalue, adaptivity); + + mDisplay.Clear(); + + mDisplay.AddVertice(points); + + auto begin = triangles.begin(); + auto end = triangles.end(); + + for (auto it = begin; it != end; ++it) { + int w = -1; + int x = it->x(); + int y = it->y(); + int z = it->z(); + + openvdb::Vec4I face(x,y,z,w); + + mDisplay.AddFace(face); + } + + mDisplay.AddFace(quads); +} + +float * DendroGrid::GetMeshVertices() +{ + auto vertices = mDisplay.Vertices(); + + mVertexCount = vertices.size() * 3; + + float *verticeArray = reinterpret_cast(malloc(mVertexCount * sizeof(float))); + + int i = 0; + for (auto it = vertices.begin(); it != vertices.end(); ++it) { + verticeArray[i] = it->x(); + verticeArray[i + 1] = it->y(); + verticeArray[i + 2] = it->z(); + i += 3; + } + + return verticeArray; +} + +int * DendroGrid::GetMeshFaces() +{ + auto faces = mDisplay.Faces(); + + mFaceCount = faces.size() * 4; + + int *faceArray = reinterpret_cast(malloc(mFaceCount * sizeof(int))); + + int i = 0; + for (auto it = faces.begin(); it != faces.end(); ++it) { + faceArray[i] = it->w(); + faceArray[i + 1] = it->x(); + faceArray[i + 2] = it->y(); + faceArray[i + 3] = it->z(); + i += 4; + } + + return faceArray; +} + +int DendroGrid::GetVertexCount() +{ + return mVertexCount; +} + +int DendroGrid::GetFaceCount() +{ + return mFaceCount; +} diff --git a/DendroAPI/DendroGrid.h b/DendroAPI/DendroGrid.h new file mode 100644 index 0000000..ea7ac07 --- /dev/null +++ b/DendroAPI/DendroGrid.h @@ -0,0 +1,59 @@ +#pragma once + +#ifndef __DENDROGRID_H__ +#define __DENDROGRID_H__ + +#include "DendroParticle.h" +#include "DendroMesh.h" +#include +#include +#include + +class DendroGrid +{ +public: + DendroGrid(); + DendroGrid(DendroGrid * grid); + ~DendroGrid(); + + openvdb::FloatGrid::Ptr Grid(); + + bool Read(const char *vFile); + bool Write(const char *vFile); + + bool CreateFromMesh(DendroMesh vMesh, double voxelSize, double bandwidth); + bool CreateFromPoints(DendroParticle vPoints, double voxelSize, double bandwidth); + + void Transform(openvdb::math::Mat4d xform); + + void BooleanUnion(DendroGrid vAdd); + void BooleanIntersection(DendroGrid vIntersect); + void BooleanDifference(DendroGrid vSubtract); + + void Offset(double amount); + void Offset(double amount, DendroGrid vMask, double min, double max, bool invert); + + void Smooth(int type, int iterations, int width); + void Smooth(int type, int iterations, int width, DendroGrid vMask, double min, double max, bool invert); + + void Blend(DendroGrid bGrid, double bPosition, double bEnd); + void Blend(DendroGrid bGrid, double bPosition, double bEnd, DendroGrid vMask, double min, double max, bool invert); + + DendroMesh Display(); + + void UpdateDisplay(); + void UpdateDisplay(double isovalue, double adaptivity); + + float * GetMeshVertices(); + int * GetMeshFaces(); + int GetVertexCount(); + int GetFaceCount(); + +private: + openvdb::FloatGrid::Ptr mGrid; + DendroMesh mDisplay; + int mFaceCount; + int mVertexCount; +}; + +#endif // __DENDROGRID_H__ \ No newline at end of file diff --git a/DendroAPI/DendroMesh.cpp b/DendroAPI/DendroMesh.cpp new file mode 100644 index 0000000..c982381 --- /dev/null +++ b/DendroAPI/DendroMesh.cpp @@ -0,0 +1,68 @@ +#include "stdafx.h" +#include "DendroMesh.h" + + +DendroMesh::DendroMesh() +{ + mVertices.clear(); + mFaces.clear(); +} + +DendroMesh DendroMesh::Duplicate() +{ + DendroMesh mesh; + mesh.AddVertice(mVertices); + mesh.AddFace(mFaces); + + return mesh; +} + +DendroMesh::~DendroMesh() +{ +} + +bool DendroMesh::IsValid() +{ + if (mFaces.size() > 0 && mVertices.size() > 0) { + return true; + } + + return false; +} + +std::vector DendroMesh::Vertices() +{ + return mVertices; +} + +std::vector DendroMesh::Faces() +{ + return mFaces; +} + +void DendroMesh::AddVertice(openvdb::Vec3s v) +{ + mVertices.push_back(v); +} + +void DendroMesh::AddVertice(std::vector v) +{ + mVertices.insert(mVertices.end(), v.begin(), v.end()); +} + +void DendroMesh::AddFace(openvdb::Vec4I f) +{ + mFaces.push_back(f); +} + +void DendroMesh::AddFace(std::vector f) +{ + mFaces.insert(mFaces.end(), f.begin(), f.end()); +} + +void DendroMesh::Clear() +{ + mVertices.clear(); + mFaces.clear(); +} + diff --git a/DendroAPI/DendroMesh.h b/DendroAPI/DendroMesh.h new file mode 100644 index 0000000..53d8e53 --- /dev/null +++ b/DendroAPI/DendroMesh.h @@ -0,0 +1,36 @@ +#pragma once + +#ifndef __DENDROMESH_H__ +#define __DENDROMESH_H__ + +#include +#include + +class DendroMesh { + +public: + + DendroMesh(); + ~DendroMesh(); + + DendroMesh Duplicate(); + + bool IsValid(); + + std::vector Vertices(); + std::vector Faces(); + + void AddVertice(openvdb::Vec3s v); + void AddVertice(std::vector v); + + void AddFace(openvdb::Vec4I f); + void AddFace(std::vector f); + + void Clear(); + +private: + std::vector mVertices; + std::vector mFaces; +}; + +#endif // __DENDROMESH_H__ \ No newline at end of file diff --git a/DendroAPI/DendroParticle.h b/DendroAPI/DendroParticle.h new file mode 100644 index 0000000..121aa08 --- /dev/null +++ b/DendroAPI/DendroParticle.h @@ -0,0 +1,92 @@ +#pragma once + +#ifndef __DENDROPARTICLE_H__ +#define __DENDROPARTICLE_H__ + +#include +#include + +class DendroParticle +{ +protected: + struct Particle { + openvdb::Vec3R p, v; + openvdb::Real r; + }; + openvdb::Real mRadiusScale; + openvdb::Real mVelocityScale; + std::vector mParticleList; +public: + + typedef openvdb::Vec3R PosType; + + DendroParticle(openvdb::Real rScale = 1, openvdb::Real vScale = 1) + : mRadiusScale(rScale), mVelocityScale(vScale) {} + + void add(const openvdb::Vec3R &p, const openvdb::Real &r, + const openvdb::Vec3R &v = openvdb::Vec3R(0, 0, 0)) + { + Particle pa; + pa.p = p; + pa.r = r; + pa.v = v; + mParticleList.push_back(pa); + } + + bool IsValid() { + return (mParticleList.size() > 0) ? true : false; + } + void clear() { mParticleList.clear(); } + + /// @return coordinate bbox in the space of the specified transfrom + openvdb::CoordBBox getBBox(const openvdb::GridBase& grid) { + openvdb::CoordBBox bbox; + openvdb::Coord &min = bbox.min(), &max = bbox.max(); + openvdb::Vec3R pos; + openvdb::Real rad, invDx = 1 / grid.voxelSize()[0]; + for (size_t n = 0, e = this->size(); ngetPosRad(n, pos, rad); + const openvdb::Vec3d xyz = grid.worldToIndex(pos); + const openvdb::Real r = rad * invDx; + for (int i = 0; i<3; ++i) { + min[i] = openvdb::math::Min(min[i], openvdb::math::Floor(xyz[i] - r)); + max[i] = openvdb::math::Max(max[i], openvdb::math::Ceil(xyz[i] + r)); + } + } + return bbox; + } + //typedef int AttributeType; + // The methods below are only required for the unit-tests + openvdb::Vec3R pos(int n) const { return mParticleList[n].p; } + openvdb::Vec3R vel(int n) const { return mVelocityScale * mParticleList[n].v; } + openvdb::Real radius(int n) const { return mRadiusScale * mParticleList[n].r; } + + ////////////////////////////////////////////////////////////////////////////// + /// The methods below are the only ones required by tools::ParticleToLevelSet + /// @note We return by value since the radius and velocities are modified + /// by the scaling factors! Also these methods are all assumed to + /// be thread-safe. + + /// Return the total number of particles in list. + /// Always required! + size_t size() const { return mParticleList.size(); } + + /// Get the world space position of n'th particle. + /// Required by ParticledToLevelSet::rasterizeSphere(*this,radius). + void getPos(size_t n, openvdb::Vec3R&pos) const { pos = mParticleList[n].p; } + + + void getPosRad(size_t n, openvdb::Vec3R& pos, openvdb::Real& rad) const { + pos = mParticleList[n].p; + rad = mRadiusScale * mParticleList[n].r; + } + void getPosRadVel(size_t n, openvdb::Vec3R& pos, openvdb::Real& rad, openvdb::Vec3R& vel) const { + pos = mParticleList[n].p; + rad = mRadiusScale * mParticleList[n].r; + vel = mVelocityScale * mParticleList[n].v; + } + // The method below is only required for attribute transfer + void getAtt(size_t n, openvdb::Index32& att) const { att = openvdb::Index32(n); } +}; + +#endif // __DENDROPARTICLE_H__ \ No newline at end of file diff --git a/DendroAPI/Nuget.config b/DendroAPI/Nuget.config new file mode 100644 index 0000000..8158de3 --- /dev/null +++ b/DendroAPI/Nuget.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/DendroAPI/dllmain.cpp b/DendroAPI/dllmain.cpp new file mode 100644 index 0000000..1637303 Binary files /dev/null and b/DendroAPI/dllmain.cpp differ diff --git a/DendroAPI/packages.config b/DendroAPI/packages.config new file mode 100644 index 0000000..3be02a9 --- /dev/null +++ b/DendroAPI/packages.config @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/DendroAPI/stdafx.cpp b/DendroAPI/stdafx.cpp new file mode 100644 index 0000000..170b73d Binary files /dev/null and b/DendroAPI/stdafx.cpp differ diff --git a/DendroAPI/stdafx.h b/DendroAPI/stdafx.h new file mode 100644 index 0000000..b937b12 Binary files /dev/null and b/DendroAPI/stdafx.h differ diff --git a/DendroAPI/targetver.h b/DendroAPI/targetver.h new file mode 100644 index 0000000..567cd34 Binary files /dev/null and b/DendroAPI/targetver.h differ diff --git a/DendroGH/Classes/DendroMask.cs b/DendroGH/Classes/DendroMask.cs new file mode 100644 index 0000000..a982da1 --- /dev/null +++ b/DendroGH/Classes/DendroMask.cs @@ -0,0 +1,186 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using Rhino.Geometry; + +namespace DendroGH { + /// + /// a DendroMask can be used to execute volume operations to isolated areas. + /// a DendroMask has its own volume which represents the masks area of influence. + /// operations this can be used with are blend, offset, and smooth. + /// + public class DendroMask : IDisposable { +#region Members + private DendroVolume mVolume; // volume representing the mask + private double mMin; // minimum value of the mask to be used for the derivation of a smooth alpha value + private double mMax; // maximum value of the mask to be used for the derivation of a smooth alpha value + private bool mInvert; // invert mask values +#endregion Members + +#region Constructors + /// + /// default constructor + /// + public DendroMask () { + this.Volume = new DendroVolume (); + this.Min = 0; + this.Max = 0; + this.Invert = false; + } + + /// + /// copy constructor + /// + /// mask to copy from + public DendroMask (DendroMask mask) { + this.Volume = new DendroVolume (mask.Volume); + this.Min = mask.Min; + this.Max = mask.Max; + this.Invert = mask.Invert; + } + + /// + /// volume constructor + /// + /// volume to copy from + public DendroMask (DendroVolume vCopy) { + this.Volume = new DendroVolume (vCopy); + this.Min = 0; + this.Max = 0; + this.Invert = false; + } + + /// + /// dispose of mask and release resources + /// + public void Dispose () { + Dispose (true); + } + + /// + /// protected implementation of dispose pattern + /// + /// holds value indicating if this was called from dispose or finalizer + protected virtual void Dispose (bool bDisposing) { + this.Volume.Dispose (); + + if (bDisposing) { + GC.SuppressFinalize (this); + } + } + + /// + /// destructor + /// + ~DendroMask () { + Dispose (false); + } +#endregion Constructors + +#region Properties + /// + /// mask volume property + /// + /// area/space where volume operations will be applied + /// volume representing the mask + public DendroVolume Volume { + get { + return this.mVolume; + } + private set + { + this.mVolume = value; + } + } + + /// + /// minimum mask property + /// + /// essentially this is the blending amount and is the lower limit of graidation + /// minimum value of the mask to be used for the derivation of a smooth alpha value + public double Min { + get { + return this.mMin; + } + set { + this.mMin = value; + } + } + + /// + /// maximum mask property + /// + /// essentially this is the blending amount and is the upper limit of graidation + /// maximum value of the mask to be used for the derivation of a smooth alpha value + public double Max { + get { + return this.mMax; + } + set { + this.mMax = value; + } + } + + /// + /// invert mask property + /// + /// invert value decides whether mask influences inside its volume or outside + /// invert mask value + public bool Invert { + get { + return this.mInvert; + } + set { + this.mInvert = value; + } + } + + /// + /// mask validity property + /// + /// boolean value of mask validity + public bool IsValid { + get { + return this.Volume.IsValid; + } + } + + /// + /// mask mesh represention for visualization + /// + /// mesh representation of mask + public Mesh Display { + get { + return this.Volume.Display; + } + } +#endregion Properties + + /// + /// gets the world axis aligned bounding box for the mask volume + /// + /// boundingbox of the geometry in world coordinates or BoundingBox.Empty if not bounding box could be found + public BoundingBox GetBoundingBox () { + return this.Volume.Display.GetBoundingBox (true); + } + + /// + /// gets the world axis aligned bounding box for the transformed mask volume + /// + /// transformation to apply to object prior to the bounding box computation + /// accurate boundingbox of the transformed geometry in world coordinates or BoundingBox.Empty if not bounding box could be found + public BoundingBox GetBoundingBox (Transform xform) { + return this.Volume.Display.GetBoundingBox (xform); + } + + /// + /// transform mask volume from supplied matrix + /// + /// transform to apply to mask volume + /// boolean value for whether transform was successful + public bool Transform (Transform xform) { + return this.Volume.Transform (xform); + } + } +} \ No newline at end of file diff --git a/DendroGH/Classes/DendroSettings.cs b/DendroGH/Classes/DendroSettings.cs new file mode 100644 index 0000000..9121d0b --- /dev/null +++ b/DendroGH/Classes/DendroSettings.cs @@ -0,0 +1,75 @@ +using System; + +namespace DendroGH { + /// + /// class containing all settings needed for converting different + /// geometry types to and from DendroVolume types. Implemented to + /// simplify working with multiple DendroVolume objects, allowing + /// you to create a single DendroSetting that can be applied to all + /// + public class DendroSettings { + +#region Members + private double mAdaptivity = 0.1; // higher adaptivity will allow more variation in polygon size, resulting in fewer polygons + private double mBandwidth = 1.0; // desired radius in voxel units around the surface + private double mIsovalue = 0.01; // crossing point of the volume that is considered the surface + private double mVoxelSize = 0.5; // size of voxels in the output volume +#endregion Members + +#region Constructors + /// + /// default constructor + /// + public DendroSettings () { } + + /// + /// copy constructor + /// + /// settings to copy from + public DendroSettings (DendroSettings ds) { + this.mAdaptivity = ds.Adaptivity; + this.mBandwidth = ds.Bandwidth; + this.mIsovalue = ds.IsoValue; + this.mVoxelSize = ds.VoxelSize; + } +#endregion Constructors + +#region Properties + /// + /// bandwidth property + /// + /// bandwidth amount for volume + public double Bandwidth { + get { return this.mBandwidth; } + set { this.mBandwidth = value; } + } + + /// + /// voxel size property + /// + /// voxel size for volume + public double VoxelSize { + get { return this.mVoxelSize; } + set { this.mVoxelSize = value; } + } + + /// + /// isovalue property + /// + /// isovalue for meshing + public double IsoValue { + get { return this.mIsovalue; } + set { this.mIsovalue = value; } + } + + /// + /// adaptivity property + /// + /// adaptivity value for meshing + public double Adaptivity { + get { return this.mAdaptivity; } + set { this.mAdaptivity = value; } + } +#endregion Properties + } +} \ No newline at end of file diff --git a/DendroGH/Classes/DendroVolume.cs b/DendroGH/Classes/DendroVolume.cs new file mode 100644 index 0000000..442a1e5 --- /dev/null +++ b/DendroGH/Classes/DendroVolume.cs @@ -0,0 +1,1010 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using Rhino.Geometry; + +namespace DendroGH { + /// + /// c# wrapper for c++ api. this holds all external dll calls and is + /// primary point of communication with all openvdb functions. the mGrid + /// member is a pointer to a c++ class and all DendroVolume methods operate + /// specific functions on that c++ mGrid class + /// + public class DendroVolume : IDisposable { + +#region PInvokes + [DllImport ("DendroAPI.dll", CallingConvention = CallingConvention.Cdecl)] + static private extern IntPtr DendroCreate (); + + [DllImport ("DendroAPI.dll", CallingConvention = CallingConvention.Cdecl)] + static private extern void DendroDelete (IntPtr grid); + + [DllImport ("DendroAPI.dll", CallingConvention = CallingConvention.Cdecl)] + static private extern IntPtr DendroDuplicate (IntPtr grid); + + [DllImport ("DendroAPI.dll", CallingConvention = CallingConvention.Cdecl)] + static private extern bool DendroRead (IntPtr grid, string filename); + + [DllImport ("DendroAPI.dll", CallingConvention = CallingConvention.Cdecl)] + static private extern bool DendroWrite (IntPtr grid, string filename); + + [DllImport ("DendroAPI.dll", CallingConvention = CallingConvention.Cdecl)] + static private extern bool DendroFromMesh(IntPtr grid, float[] vertices, int vCount, int[] faces, int fCount, double voxelSize, double bandwidth); + + [DllImport ("DendroAPI.dll", CallingConvention = CallingConvention.Cdecl)] + static private extern bool DendroFromPoints(IntPtr grid, double[] points, int pCount, double[] radii, int rCount, double voxelSize, double bandwidth); + + [DllImport ("DendroAPI.dll", CallingConvention = CallingConvention.Cdecl)] + static private extern bool DendroTransform (IntPtr grid, double[] matrix, int mCount); + + [DllImport ("DendroAPI.dll", CallingConvention = CallingConvention.Cdecl)] + static public extern void DendroUnion (IntPtr grid, IntPtr csgGrid); + + [DllImport ("DendroAPI.dll", CallingConvention = CallingConvention.Cdecl)] + static public extern void DendroDifference (IntPtr grid, IntPtr csgGrid); + + [DllImport ("DendroAPI.dll", CallingConvention = CallingConvention.Cdecl)] + static public extern void DendroIntersection (IntPtr grid, IntPtr csgGrid); + + [DllImport ("DendroAPI.dll", CallingConvention = CallingConvention.Cdecl)] + static public extern void DendroOffset (IntPtr grid, double amount); + + [DllImport ("DendroAPI.dll", CallingConvention = CallingConvention.Cdecl)] + static public extern void DendroOffsetMask (IntPtr grid, double amount, IntPtr mask, double min, double max, bool invert); + + [DllImport ("DendroAPI.dll", CallingConvention = CallingConvention.Cdecl)] + static public extern void DendroSmooth (IntPtr grid, int type, int iterations, int width); + + [DllImport ("DendroAPI.dll", CallingConvention = CallingConvention.Cdecl)] + static public extern void DendroSmoothMask (IntPtr grid, int type, int iterations, int width, IntPtr mask, double min, double max, bool invert); + + [DllImport ("DendroAPI.dll", CallingConvention = CallingConvention.Cdecl)] + static public extern void DendroBlend (IntPtr bGrid, IntPtr eGrid, double bPosition, double bEnd); + + [DllImport ("DendroAPI.dll", CallingConvention = CallingConvention.Cdecl)] + static public extern void DendroBlendMask (IntPtr bGrid, IntPtr eGrid, double bPosition, double bEnd, IntPtr mask, double min, double max, bool invert); + + [DllImport ("DendroAPI.dll", CallingConvention = CallingConvention.Cdecl)] + static private extern void DendroToMesh (IntPtr grid); + + [DllImport ("DendroAPI.dll", CallingConvention = CallingConvention.Cdecl)] + static private extern void DendroToMeshSettings (IntPtr grid, double isovalue, double adaptivity); + + [DllImport ("DendroAPI.dll", CallingConvention = CallingConvention.Cdecl)] + static private extern IntPtr DendroVertexBuffer (IntPtr grid, out int size); + + [DllImport ("DendroAPI.dll", CallingConvention = CallingConvention.Cdecl)] + static private extern IntPtr DendroFaceBuffer (IntPtr grid, out int size); +#endregion PInvokes + +#region Members + private IntPtr mGrid; // stores pointer to grid in c++ + private Mesh mDisplay; // mesh representation of volume used for visualization + private bool mValid; // volume validity +#endregion Members + +#region Constructors + /// + /// default constructor + /// + public DendroVolume () { + // pinvoke grid creation + this.Grid = DendroCreate (); + this.Display = new Mesh (); + + // volume is empty, so it is invalid + this.IsValid = false; + } + + /// + /// copy constructor + /// + /// volume to copy from + public DendroVolume (DendroVolume vCopy) { + if (vCopy.IsValid) { + this.Grid = vCopy.DuplicateGrid (); + this.Display = vCopy.Display.DuplicateMesh (); + + this.IsValid = true; + } + else { + // pinvoke grid creation + this.Grid = DendroCreate (); + this.Display = new Mesh (); + + // volume is empty, so it is invalid + this.IsValid = false; + } + } + + /// + /// create volume from a vdb file + /// + /// full path and name of vdb file to read (vdb extension) + public DendroVolume (string vFile) { + // create a new grid + this.Grid = DendroCreate (); + this.Display = new Mesh (); + + // read vdb file + this.IsValid = this.Read (vFile); + } + + /// + /// mesh constructor + /// + /// mesh to build volume from + /// voxelization settings to be used + public DendroVolume (Mesh vMesh, DendroSettings vSettings) { + // pinvoke grid creation + this.Grid = DendroCreate (); + this.Display = new Mesh (); + + this.IsValid = this.CreateFromMesh (vMesh, vSettings); + } + + /// + /// point constructor + /// + /// must supply a single radius value or a list of radii equal to the number of points supplied + /// point set to build volume from + /// radius values for each point + /// voxelization settings to be used + public DendroVolume (List vPoints, List vRadius, DendroSettings vSettings) { + // pinvoke grid creation + this.Grid = DendroCreate (); + this.Display = new Mesh (); + + this.IsValid = this.CreateFromPoints (vPoints, vRadius, vSettings); + } + + /// + /// curve constructor + /// + /// must supply a single radius value or a list of radii equal to the number of curves supplied + /// curves to build volume from + /// radius values for each curve + /// voxelization settings to be used + public DendroVolume (List vCurves, List vRadius, DendroSettings vSettings) { + // pinvoke grid creation + this.Grid = DendroCreate (); + this.Display = new Mesh (); + + this.IsValid = this.CreateFromCurves (vCurves, vRadius, vSettings); + } + + /// + /// dispose of volume and release resources + /// + public void Dispose () { + Dispose (true); + } + + /// + /// protected implementation of dispose pattern + /// + /// holds value indicating if this was called from dispose or finalizer + protected virtual void Dispose (bool bDisposing) { + if (this.Grid != IntPtr.Zero) { + // cleanup everything on the c++ side + DendroDelete (this.Grid); + + // clear grid pointer + this.Grid = IntPtr.Zero; + this.IsValid = false; + } + + // finalize garbage collection + if (bDisposing) { + GC.SuppressFinalize (this); + } + } + + /// + /// destructor + /// + ~DendroVolume () { + Dispose (false); + } + + /// + /// duplicate the volume grid + /// + /// + /// needed in addition to the copy contructor in order to duplicate just the c++ grid class + /// + /// returns pointer to c++ grid + public IntPtr DuplicateGrid () { + // pinvoke grid duplication + return DendroDuplicate (this.Grid); + } +#endregion Constructors + +#region Properties + /// + /// volume validity property + /// + /// boolean value of volume validity + public bool IsValid { + get { + if (this.Grid == IntPtr.Zero) return false; + return this.mValid; + } + private set { + this.mValid = value; + } + } + + /// + /// volume grid pointer property + /// + /// pointer to c++ grid + public IntPtr Grid { + get { + return this.mGrid; + } + private set { + this.mGrid = value; + } + } + + /// + /// volume mesh represention for visualization + /// + /// mesh representation of volume + public Mesh Display { + get { + return this.mDisplay; + } + private set { + this.mDisplay = value; + } + } +#endregion Properties + + #region Methods + /// + /// read a vdb file and build volume + /// + /// full path and name of vdb file to read (vdb extension) + /// boolean value for whether reading was successful + public bool Read (string vFile) { + if (!File.Exists (vFile)) { + return false; + } + + // pinvoke file read function + this.IsValid = DendroRead (this.Grid, vFile); + + if (!this.IsValid) { + return false; + } + + this.UpdateDisplay (); + + return true; + } + + /// + /// write volume to a vdb file + /// + /// full path and name of vdb file to write (vdb extension) + /// boolean value for whether file write was successful + public bool Write (string vFile) { + // pinvoke file writing function + DendroWrite (this.Grid, vFile); + + if (!File.Exists (vFile)) { + return false; + } + + return true; + } + + /// + /// build a volume from a mesh input + /// + /// mesh to build volume from + /// voxelization settings to be used + /// boolean value for whether volume was built successfully + public bool CreateFromMesh (Mesh vMesh, DendroSettings vSettings) { + if (!vMesh.IsValid) + return false; + + // check for invalid voxelsize settings + if (vSettings.VoxelSize < 0.01) + vSettings.VoxelSize = 0.01; + + // check for invalid bandwidth settings + if (vSettings.Bandwidth < 1) + vSettings.Bandwidth = 1; + + // create flattened vertex and face arrays from input mesh + float[] vertices = vMesh.Vertices.ToFloatArray (); + int[] faces = vMesh.Faces.ToIntArray (true); + + // pinvoke build volume from mesh + this.IsValid = DendroFromMesh(this.Grid, vertices, vertices.Length, faces, faces.Length, vSettings.VoxelSize, vSettings.Bandwidth); + + if (!this.IsValid) + return false; + + // use input mesh for the visualization mesh (saves us from computing it in c++) + this.Display = vMesh.DuplicateMesh (); + + return true; + } + + /// + /// build a volume from a supplied list of points + /// + /// must supply a single radius value or a list of radii equal to the number of points supplied + /// point set to build volume from + /// radius values for each point + /// voxelization settings to be used + /// boolean value for whether volume was built successfully + public bool CreateFromPoints (List vPoints, List vRadius, DendroSettings vSettings) { + // there were no points/radius supplied so exit + if (vPoints.Count == 0 || vRadius.Count == 0) + return false; + + // check for invalid voxelsize settings + if (vSettings.VoxelSize < 0.01) + vSettings.VoxelSize = 0.01; + + // check for invalid bandwidth settings + if (vSettings.Bandwidth < 1) + vSettings.Bandwidth = 1; + + // if one or equal radius values were supplied then build volume + if (vPoints.Count == vRadius.Count || vRadius.Count == 1) { + + // create point array from point3d list so we can pass to c++ + double[] points = new double[vPoints.Count * 3]; + + int i = 0; + foreach (Point3d pt in vPoints) { + points[i] = pt.X; + points[i + 1] = pt.Y; + points[i + 2] = pt.Z; + + i += 3; + } + + // create radius array from list so we can pass to c++ + double[] radius = vRadius.ToArray (); + + // pinvoke build volume from points + this.IsValid = DendroFromPoints(this.Grid, points, points.Length, radius, radius.Length, vSettings.VoxelSize, vSettings.Bandwidth); + + if (!this.IsValid) + return false; + + this.UpdateDisplay (); + } + else { + return false; + } + + return true; + } + + /// + /// build a volume from a supplied list of curves + /// + /// must supply a single radius value or a list of radii equal to the number of curves supplied + /// curves to build volume from + /// radius values for each curve + /// voxelization settings to be used + /// boolean value for whether volume was built successfully + public bool CreateFromCurves (List vCurves, List vRadius, DendroSettings vSettings) { + // there were no curves/radius supplied so exit + if (vCurves.Count == 0 || vRadius.Count == 0) + return false; + + // check for invalid voxelsize settings + if (vSettings.VoxelSize < 0.01) + vSettings.VoxelSize = 0.01; + + // check for invalid bandwidth settings + if (vSettings.Bandwidth < 1) + vSettings.Bandwidth = 1; + + // find out if we were supplied a single radius value or multiple values + int method = GetCurveSolverMethod (vCurves.Count, vRadius.Count); + + bool validInput = false; + List rValues = new List (); + List vPoints = new List (); + + switch (method) { + // only a single radius was supplied + case 1: + validInput = ResolveSingleRadius (vCurves, vRadius[0], out vPoints, out rValues); + break; + + // multiple radius values were supplied + case 2: + validInput = ResolveMultipleRadius (vCurves, vRadius, out vPoints, out rValues); + break; + default: + validInput = false; + break; + } + + // supplied values were not valid so exit + if (!validInput) + return false; + + // return results from point to volume function + return this.CreateFromPoints (vPoints, rValues, vSettings); + } + + /// + /// gets the world axis aligned boundingbox for the volume + /// + /// boundingbox of the geometry in world coordinates or BoundingBox.Empty if not bounding box could be found + public BoundingBox GetBoundingBox () { + return this.Display.GetBoundingBox (true); + } + + /// + /// gets the world axis aligned boundingbox for the transformed volume + /// + /// transformation to apply to object prior to the bounding box computation + /// accurate boundingbox of the transformed geometry in world coordinates or BoundingBox.Empty if not bounding box could be found + public BoundingBox GetBoundingBox (Transform xform) { + return this.Display.GetBoundingBox (xform); + } + + /// + /// transform volume from supplied matrix + /// + /// transform to apply to volume + /// boolean value for whether transform was successful + public bool Transform (Transform xform) { + if (!xform.IsValid) + return false; + + // convert transform to flat array + float[] floatMatrix = xform.ToFloatArray (false); + double[] matrix = Array.ConvertAll (floatMatrix, x => (double) x); + + // pinvoke transform on grid + this.IsValid = DendroTransform (this.Grid, matrix, matrix.Length); + + if (!this.IsValid) + return false; + + // transform display mesh directly instead of recomputing in c++ + this.Display.Transform (xform); + + return true; + } + + /// + /// compute a boolean difference of a volume + /// + /// volume to subtract with + /// new volume with the resulting difference + public DendroVolume BooleanDifference (DendroVolume vSubract) { + if (!this.IsValid) + return new DendroVolume (); + + if (!vSubract.IsValid) + return new DendroVolume (this); + + DendroVolume csg = new DendroVolume (this); + + // pinvoke difference function + DendroDifference (csg.Grid, vSubract.Grid); + csg.UpdateDisplay (); + + return csg; + } + + /// + /// compute a boolean difference of a set of volumes + /// + /// list of volumes to subtract with + /// new volume with the resulting difference + public DendroVolume BooleanDifference (List vSubtract) { + if (!this.IsValid) + return new DendroVolume (); + + DendroVolume csg = new DendroVolume (this); + + foreach (DendroVolume subtract in vSubtract) { + // pinvoke difference function + if (subtract.IsValid) + DendroDifference (csg.Grid, subtract.Grid); + } + + csg.UpdateDisplay (); + + return csg; + } + + /// + /// compute a boolean intersection of a volume + /// + /// volume to intersect + /// new volume with the resulting intersection + public DendroVolume BooleanIntersection (DendroVolume vIntersect) { + if (!this.IsValid) + return new DendroVolume (); + + if (!vIntersect.IsValid) + return new DendroVolume (this); + + DendroVolume csg = new DendroVolume (this); + + // pinvoke intersection function + DendroIntersection (csg.Grid, vIntersect.Grid); + csg.UpdateDisplay (); + + return csg; + } + + /// + /// compute a boolean intersection of a set of volumes + /// + /// list of volumes to intersect + /// new volume with the resulting intersection + public DendroVolume BooleanIntersection (List vIntersect) { + if (!this.IsValid) + return new DendroVolume (); + + DendroVolume csg = new DendroVolume (this); + + foreach (DendroVolume intersect in vIntersect) { + // pinvoke intersection function + if (intersect.IsValid) + DendroIntersection (csg.Grid, intersect.Grid); + } + + csg.UpdateDisplay (); + + return csg; + } + + /// + /// compute a boolean union of a volume + /// + /// volume to union + /// new volume with the resulting union + public DendroVolume BooleanUnion (DendroVolume vUnion) { + if (!this.IsValid) + return new DendroVolume (); + + if (!vUnion.IsValid) + return new DendroVolume (this); + + DendroVolume csg = new DendroVolume (this); + + // pinvoke union function + DendroUnion (csg.Grid, vUnion.Grid); + csg.UpdateDisplay (); + + return csg; + } + + /// + /// compute a boolean union of a set of volumes + /// + /// list of volumes to union + /// new volume with the resulting union + public DendroVolume BooleanUnion (List vUnion) { + if (!this.IsValid) + return new DendroVolume (); + + DendroVolume csg = new DendroVolume (this); + + foreach (DendroVolume union in vUnion) { + // pinvoke union function + if (union.IsValid) + DendroUnion (csg.Grid, union.Grid); + } + + csg.UpdateDisplay (); + + return csg; + } + + /// + /// apply an offset to the volume + /// + /// amount to offset volume + /// offset volume + public DendroVolume Offset (double amount) { + if (!this.IsValid) + return new DendroVolume (); + + DendroVolume offset = new DendroVolume (this); + + // pinvoke offset function + DendroOffset (offset.Grid, amount); + + offset.UpdateDisplay (); + + return offset; + } + + /// + /// apply an offset to the volume with a mask + /// + /// amount to offset volume + /// mask for offset operation + /// offset volume + public DendroVolume Offset (double amount, DendroMask vMask) { + if (!this.IsValid) + return new DendroVolume (); + + DendroVolume offset = new DendroVolume (this); + + // pinvoke offset function with mask + DendroOffsetMask (offset.Grid, amount, vMask.Volume.Grid, vMask.Min, vMask.Max, vMask.Invert); + + offset.UpdateDisplay (); + + return offset; + } + + /// + /// apply smoothing to a volume + /// + /// (optional) width of the mean-value filter is 2*width+1 voxels + /// 0 - gaussian, 1 - laplacian, 2 - mean, 3 - median + /// number of smoothing operations to perform + /// smoothed volume + public DendroVolume Smooth (int sType, int sIterations, int sWidth = 1) + { + if (!this.IsValid) + return new DendroVolume (); + + if (sType < 0 || sType > 3) + sType = 1; + + if (sWidth < 1) + sWidth = 1; + + if (sIterations < 1) + sIterations = 1; + + DendroVolume smooth = new DendroVolume(this); + + // pinvoke smoothing function + DendroSmooth (smooth.Grid, sType, sIterations, sWidth); + + smooth.UpdateDisplay (); + + return smooth; + } + + /// + /// apply smoothing to a volume + /// + /// (optional) width of the mean-value filter is 2*width+1 voxels + /// 0 - gaussian, 1 - laplacian, 2 - mean, 3 - median + /// number of smoothing operations to perform + /// mask for smoothing operation + /// smoothed volume + public DendroVolume Smooth (int sType, int sIterations, DendroMask vMask, int sWidth = 1) { + if (!this.IsValid) + return new DendroVolume (); + + if (sType < 0 || sType > 3) + sType = 1; + + if (sWidth < 1) + sWidth = 1; + + if (sIterations < 1) + sIterations = 1; + + DendroVolume smooth = new DendroVolume (this); + + // pinvoke smoothing function with mask + DendroSmoothMask (smooth.Grid, sType, sIterations, sWidth, vMask.Volume.Grid, vMask.Min, vMask.Max, vMask.Invert); + + smooth.UpdateDisplay (); + + return smooth; + } + + /// + /// blend two volumes + /// + /// volume to blend with + /// position parameter to sample blending at (normalized 0-1) + /// blended volume + public DendroVolume Blend (DendroVolume bVolume, double bPosition, double bEnd) { + if (!this.IsValid) + return new DendroVolume (); + + if (bPosition < 0) bPosition = 0; + if (bPosition > 1) bPosition = 1; + + if (bEnd < 1) bEnd = 1; + + bPosition = 1 - bPosition; + + DendroVolume blend = new DendroVolume(this); + + // pinvoke smoothing function + DendroBlend(blend.Grid, bVolume.Grid, bPosition, bEnd); + + blend.UpdateDisplay (); + + return blend; + } + + /// + /// blend two volumes using a mask + /// + /// volume to blend with + /// position parameter to sample blending at (normalized 0-1) + /// mask for blending operation + /// blended volume + public DendroVolume Blend (DendroVolume bVolume, double bPosition, double bEnd, DendroMask vMask) { + if (!this.IsValid) + return new DendroVolume (); + + if (bPosition < 0) bPosition = 0; + if (bPosition > 1) bPosition = 1; + + if (bEnd < 1) bEnd = 1; + + bPosition = 1 - bPosition; + + DendroVolume blend = new DendroVolume (this); + + // pinvoke smoothing function with mask + DendroBlendMask (blend.Grid, bVolume.Grid, bPosition, bEnd, vMask.Volume.Grid, vMask.Min, vMask.Max, vMask.Invert); + + blend.UpdateDisplay (); + + return blend; + } +#endregion Methods + +#region Display + /// + /// update the mesh representation of the volume + /// + public void UpdateDisplay () { + // pinvoke mesh update + DendroToMesh (this.Grid); + + // get update vertex and face arrays + float[] vertices = this.GetMeshVertices (); + int[] faces = this.GetMeshFaces (); + + this.Display = this.ConstructMesh (vertices, faces); + + // flip and rebuild + this.Display.Normals.ComputeNormals(); + } + + /// + /// update the mesh representation of the volume using voxel settings + /// + /// settings for meshing volume + public void UpdateDisplay (DendroSettings vSettings) { + // pinvoke mesh update + DendroToMeshSettings (this.Grid, vSettings.IsoValue, vSettings.Adaptivity); + + // get update vertex and face arrays + float[] vertices = this.GetMeshVertices (); + int[] faces = this.GetMeshFaces (); + + this.Display = this.ConstructMesh (vertices, faces); + + // flip and rebuild + this.Display.UnifyNormals(); + this.Display.Flip(true, true, true); + } + + /// + /// gets vertex buffer array over from c++ + /// + /// vertex array + private float[] GetMeshVertices () { + float[] result = null; + + IntPtr vertices = IntPtr.Zero; + + // pinvoke vertex buffer + vertices = DendroVertexBuffer (this.Grid, out int size); + if (vertices != IntPtr.Zero) { + result = new float[size]; + Marshal.Copy (vertices, result, 0, size); + } + + Marshal.FreeHGlobal (vertices); + + return result; + } + + /// + /// gets face buffer array over from c++ + /// + /// face array + private int[] GetMeshFaces () { + int[] result = null; + + IntPtr faces = IntPtr.Zero; + + // pinvoke face buffer + faces = DendroFaceBuffer (this.Grid, out int size); + if (faces != IntPtr.Zero) { + result = new int[size]; + Marshal.Copy (faces, result, 0, size); + } + + Marshal.FreeHGlobal (faces); + + return result; + } + + /// + /// build mesh from vertex and face array + /// + /// vertex array for mesh construction + /// face array for mesh construction + /// constructed mesh + private Mesh ConstructMesh (float[] vertices, int[] faces) { + Mesh constructed = new Mesh (); + + // add vertices to mesh + int i = 0; + while (i < vertices.Length) { + float x = vertices[i]; + float y = vertices[i + 1]; + float z = vertices[i + 2]; + + constructed.Vertices.Add (x, y, z); + + i += 3; + } + + // add faces to mesh + i = 0; + while (i < faces.Length) { + int w = faces[i]; + int x = faces[i + 1]; + int y = faces[i + 2]; + int z = faces[i + 3]; + + if (w == -1) { + constructed.Faces.AddFace (x, y, z); + } + else { + constructed.Faces.AddFace (w, x, y, z); + } + i += 4; + } + + return constructed; + } + +#endregion Display + +#region Helpers + /// + /// create a point set, with a corresponding radius value list, for every curve. each curve provided + /// is divided into points, using its supplied radius value and then added to the whole point set. + /// + /// called from CreateFromCurve when multiple radius values are supplied + /// curves to divide into points + /// desired radius value for the points of each curve + /// list to store all points for every curve + /// list to store all radius values for every point in vPoints + /// boolean with whether operation was successful + private bool ResolveMultipleRadius (List vCurves, List cRadius, out List vPoints, out List vRadius) { + vRadius = new List (); + vPoints = new List (); + + int rIndex = 0; + + foreach (Curve crv in vCurves) { + var radius = cRadius[rIndex]; + + if (radius > 0) { + + List vp = this.CurveToPoints (crv, radius); + List rv = Enumerable.Repeat (radius, vp.Count).ToList (); + vPoints.AddRange (vp); + vRadius.AddRange (rv); + } + else { + return false; + } + + rIndex++; + } + + return true; + } + + /// + /// create a point set, with a corresponding radius value list, for every curve. each curve provided + /// is divided into points, using its supplied radius value and then added to the whole point set. + /// + /// called from CreateFromCurve when a single radius value is supplied + /// curves to divide into points + /// desired radius value for the points of each curve + /// list to store all points for every curve + /// list to store all radius values for every point in vPoints + /// boolean with whether operation was successful + private bool ResolveSingleRadius (List vCurves, double cRadius, out List vPoints, out List vRadius) { + vRadius = new List (); + vPoints = new List (); + + if (cRadius > 0) { + // divide every curve provided into points + foreach (Curve crv in vCurves) { + List vp = this.CurveToPoints (crv, cRadius); + vPoints.AddRange (vp); + } + + // make a radius list which is the same size of point set + vRadius = Enumerable.Repeat (cRadius, vPoints.Count).ToList (); + + } + else { + return false; + } + + return true; + } + + /// + /// solves whether single or multiple radius values were provided to CreateFromCurve() + /// + /// this is used to tell CreateFromCurve how to proceed in dividing curves into points + /// curve count + /// radius count + /// method needed for breaking curves into point (1 - single radius provided, 2 - multiple radius provided) + private int GetCurveSolverMethod (int cCount, int rCount) { + // no radius provided + if (rCount == 0) { + return 0; + } + + // single radius provided + if (rCount == 1) { + return 1; + } + + // multiple radius provided (equal in amount to curves provided) + if (rCount == cCount) { + return 2; + } + + return 0; + } + + /// + /// divide a curve into point based on a desired radius value + /// + /// curve to divide + /// desired point radius value + /// list of divided points from curve + private List CurveToPoints (Curve crv, double radius) { + var cParams = crv.DivideByLength (radius * 0.25, true); + List cPoints = new List (); + + foreach (double param in cParams) { + Point3d pt = crv.PointAt (param); + cPoints.Add (pt); + } + + return cPoints; + } +#endregion Helpers + + } +} \ No newline at end of file diff --git a/DendroGH/Components/MaskCreate.cs b/DendroGH/Components/MaskCreate.cs new file mode 100644 index 0000000..99ae8ba --- /dev/null +++ b/DendroGH/Components/MaskCreate.cs @@ -0,0 +1,83 @@ +using System; +using System.Collections.Generic; +using Grasshopper.Kernel; +using Rhino.Geometry; + +namespace DendroGH { + public class MaskCreate : GH_Component { + /// + /// Initializes a new instance of the MaskFromVolume class. + /// + public MaskCreate () : base ("Create Mask", "Mask", + "Create a mask from a volume to be used in volume filter operations", + "Dendro", "Filters") { } + + /// + /// Registers all the input parameters for this component. + /// + protected override void RegisterInputParams (GH_Component.GH_InputParamManager pManager) { + pManager.AddGenericParameter ("Volume", "V", "Volume geometry", GH_ParamAccess.item); + pManager.AddNumberParameter ("Min Value", "A", "Minimum value of the mask to be used for the derivation of a smooth alpha value", GH_ParamAccess.item, 0.0); + pManager.AddNumberParameter ("Max Value", "B", "Maximum value of the mask to be used for the derivation of a smooth alpha value", GH_ParamAccess.item, 1.0); + pManager.AddBooleanParameter ("Mask Invert", "I", "Invert the mask values", GH_ParamAccess.item, true); + } + + /// + /// Registers all the output parameters for this component. + /// + protected override void RegisterOutputParams (GH_Component.GH_OutputParamManager pManager) { + pManager.AddGenericParameter ("Mask", "M", "Mask for volume filter operations", GH_ParamAccess.item); + } + + /// + /// This is the method that actually does the work. + /// + /// The DA object is used to retrieve from inputs and store in outputs. + protected override void SolveInstance (IGH_DataAccess DA) { + DendroVolume volume = new DendroVolume (); + double min = 0.0; + double max = 1.0; + bool invert = false; + + if (!DA.GetData (0, ref volume)) return; + if (!DA.GetData (1, ref min)) return; + if (!DA.GetData (2, ref max)) return; + if (!DA.GetData (3, ref invert)) return; + + if(max < min) + { + AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Max value must be larger than min value"); + return; + } + + DendroMask mask = new DendroMask (volume); + mask.Invert = invert; + mask.Min = min; + mask.Max = max; + + if (!mask.IsValid) { + AddRuntimeMessage (GH_RuntimeMessageLevel.Error, "Mask creation failed. Is your volume volid?"); + return; + } + + DA.SetData (0, new MaskGOO (mask)); + + } + + /// + /// Provides an Icon for the component. + /// + protected override System.Drawing.Bitmap Icon { + get { + return DendroGH.Properties.Resources.ico_mask; + } + } + + /// + /// Gets the unique ID for this component. Do not change this ID after release. + /// + public override Guid ComponentGuid { + get { return new Guid ("97e5d356-a481-4a1d-a11f-fb78bdcbb86f"); } + } + } +} \ No newline at end of file diff --git a/DendroGH/Components/MaskParam.cs b/DendroGH/Components/MaskParam.cs new file mode 100644 index 0000000..e146ee4 --- /dev/null +++ b/DendroGH/Components/MaskParam.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using Grasshopper.Kernel; +using Rhino.Geometry; + +namespace DendroGH { + public class MaskParam : GH_Param, IGH_PreviewObject { + /// + /// Initializes a new instance of the MaskParam class. + /// + public MaskParam () : base (new GH_InstanceDescription ("Mask Volume", "vMask", "Contains a collection of Volume Masks", "Dendro", "_Types")) { } + + /// + /// Provides an Icon for the component. + /// + protected override System.Drawing.Bitmap Icon { + get { + return DendroGH.Properties.Resources.ico_param_mask; + } + } + + /// + /// Gets the unique ID for this component. Do not change this ID after release. + /// + public override Guid ComponentGuid { + get { return new Guid ("f23f32df-3a90-4ff0-8b21-023b5f4f1175"); } + } + + bool _hidden; + public bool Hidden { + get { + return _hidden; + } + set { + _hidden = value; + } + } + + public bool IsPreviewCapable { + get { return true; } + } + + public BoundingBox ClippingBox { + get { return Preview_ComputeClippingBox (); } + } + + public void DrawViewportMeshes (IGH_PreviewArgs args) { + if (args.Document.PreviewMode == GH_PreviewMode.Shaded && + args.Display.SupportsShading) { + Preview_DrawMeshes (args); + } + } + + public void DrawViewportWires (IGH_PreviewArgs args) { + + } + } +} \ No newline at end of file diff --git a/DendroGH/Components/ReadFile.cs b/DendroGH/Components/ReadFile.cs new file mode 100644 index 0000000..3a3b413 --- /dev/null +++ b/DendroGH/Components/ReadFile.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using Grasshopper.Kernel; +using Rhino.Geometry; + +namespace DendroGH { + public class ReadFile : GH_Component { + /// + /// Initializes a new instance of the ReadFile class. + /// + public ReadFile () : base ("Read Volume", "vRead", + "Read a volume file and create a volume", + "Dendro", "IO") { } + + /// + /// Registers all the input parameters for this component. + /// + protected override void RegisterInputParams (GH_Component.GH_InputParamManager pManager) { + pManager.AddTextParameter ("File Path", "F", "Path of volume file (*.vdb files)", GH_ParamAccess.item); + pManager.AddBooleanParameter("Read?", "R", "Boolean toggle to read file", GH_ParamAccess.item); + + } + + /// + /// Registers all the output parameters for this component. + /// + protected override void RegisterOutputParams (GH_Component.GH_OutputParamManager pManager) { + pManager.AddGenericParameter ("Volume", "V", "Volume geometry", GH_ParamAccess.item); + } + + /// + /// This is the method that actually does the work. + /// + /// The DA object is used to retrieve from inputs and store in outputs. + protected override void SolveInstance (IGH_DataAccess DA) { + string filepath = ""; + bool isRead = false; + + if (!DA.GetData (0, ref filepath)) return; + if (!DA.GetData(1, ref isRead)) return; + + DendroVolume volume = new DendroVolume(); + + if (isRead) + { + volume = new DendroVolume(filepath); + + if (!volume.IsValid) + { + AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Read failed. Make sure you supplied valid *.VDB file. If file wasn't output from Dendro, make sure your source outputs volume as a float grid"); + return; + } + } + + DA.SetData (0, new VolumeGOO (volume)); + + } + + /// + /// Provides an Icon for the component. + /// + protected override System.Drawing.Bitmap Icon { + get { + return DendroGH.Properties.Resources.ico_io_in; + } + } + + /// + /// Gets the unique ID for this component. Do not change this ID after release. + /// + public override Guid ComponentGuid { + get { return new Guid ("053635d3-457b-4833-9560-128f2501de74"); } + } + } +} \ No newline at end of file diff --git a/DendroGH/Components/SettingsParam.cs b/DendroGH/Components/SettingsParam.cs new file mode 100644 index 0000000..6f73c26 --- /dev/null +++ b/DendroGH/Components/SettingsParam.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using Grasshopper.Kernel; +using Rhino.Geometry; + +namespace DendroGH { + public class SettingsParam : GH_Param { + /// + /// Initializes a new instance of the SettingsParam class. + /// + public SettingsParam () : base (new GH_InstanceDescription ("Volume Settings", "vSettings", "Contains a collection of volume settings", "Dendro", "_Types")) { } + + /// + /// Provides an Icon for the component. + /// + protected override System.Drawing.Bitmap Icon { + get { + return DendroGH.Properties.Resources.ico_param_set; + } + } + + /// + /// Gets the unique ID for this component. Do not change this ID after release. + /// + public override Guid ComponentGuid { + get { return new Guid ("5fe922b3-f95c-4ea6-8f0a-e7bb961b4d90"); } + } + } +} \ No newline at end of file diff --git a/DendroGH/Components/VolumeBlend.cs b/DendroGH/Components/VolumeBlend.cs new file mode 100644 index 0000000..43c286f --- /dev/null +++ b/DendroGH/Components/VolumeBlend.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections.Generic; +using Grasshopper.Kernel; +using Rhino.Geometry; + +namespace DendroGH { + public class VolumeBlend : GH_Component { + /// + /// Initializes a new instance of the VolumeBlend class. + /// + public VolumeBlend() : base ("Volume Blend", "vBlend", + "Blend between two volumes", + "Dendro", "Filters") { } + + /// + /// Registers all the input parameters for this component. + /// + protected override void RegisterInputParams (GH_Component.GH_InputParamManager pManager) { + pManager.AddGenericParameter ("Volume A", "A", "First Volume", GH_ParamAccess.item); + pManager.AddGenericParameter ("Volume B", "B", "Second Volume", GH_ParamAccess.item); + pManager.AddNumberParameter("Parameter", "t", "Parameter of blend domain to evaluate (normalized 0-1)", GH_ParamAccess.item, 0); + pManager.AddNumberParameter("End time", "E", "End time of evaluations", GH_ParamAccess.item, 10); + pManager.AddGenericParameter ("Mask", "M", "(Optional) Mask for filter operations", GH_ParamAccess.item); + pManager[4].Optional = true; + } + + /// + /// Registers all the output parameters for this component. + /// + protected override void RegisterOutputParams (GH_Component.GH_OutputParamManager pManager) { + pManager.AddGenericParameter("Result", "R", "Morph result", GH_ParamAccess.item); + } + + /// + /// This is the method that actually does the work. + /// + /// The DA object is used to retrieve from inputs and store in outputs. + protected override void SolveInstance (IGH_DataAccess DA) { + DendroVolume vBegin = new DendroVolume (); + DendroVolume vEnd = new DendroVolume (); + double vParam = 0.0; + double vTime = 0.0; + DendroMask vMask = new DendroMask (); + + if (!DA.GetData (0, ref vBegin)) return; + if (!DA.GetData (1, ref vEnd)) return; + if (!DA.GetData(2, ref vParam)) return; + if (!DA.GetData(3, ref vTime)) return; + DA.GetData (4, ref vMask); + + if (vMask == null) return; + + DendroVolume blend = new DendroVolume(); + + if (vMask.IsValid) + { + blend = vBegin.Blend(vEnd, vParam, vTime, vMask); + } + else + { + blend = vBegin.Blend(vEnd, vParam, vTime); + } + + if (!blend.IsValid) + { + AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Blend failed. Make sure all supplied volumes are valid"); + return; + } + + DA.SetData(0, new VolumeGOO(blend)); + } + + /// + /// Provides an Icon for the component. + /// + protected override System.Drawing.Bitmap Icon { + get { + return DendroGH.Properties.Resources.ico_morph; + } + } + + /// + /// Gets the unique ID for this component. Do not change this ID after release. + /// + public override Guid ComponentGuid { + get { return new Guid ("001791c1-b549-4282-b800-0de064a76d61"); } + } + } +} \ No newline at end of file diff --git a/DendroGH/Components/VolumeDifference.cs b/DendroGH/Components/VolumeDifference.cs new file mode 100644 index 0000000..a87d2c1 --- /dev/null +++ b/DendroGH/Components/VolumeDifference.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using Grasshopper.Kernel; +using Rhino.Geometry; + +namespace DendroGH { + public class VolumeDifference : GH_Component { + /// + /// Initializes a new instance of the VolumeDifference class. + /// + public VolumeDifference () : base ("Volume Difference", "vDiff", + "Perform a diference operation on a set of volumes", + "Dendro", "Intersect") { } + + /// + /// Registers all the input parameters for this component. + /// + protected override void RegisterInputParams (GH_Component.GH_InputParamManager pManager) { + pManager.AddGenericParameter ("Volume A", "A", "First Volume", GH_ParamAccess.item); + pManager.AddGenericParameter ("Volumes B", "B", "Second Volume set", GH_ParamAccess.list); + } + + /// + /// Registers all the output parameters for this component. + /// + protected override void RegisterOutputParams (GH_Component.GH_OutputParamManager pManager) { + pManager.AddGenericParameter ("Result", "R", "Difference result", GH_ParamAccess.item); + } + + /// + /// This is the method that actually does the work. + /// + /// The DA object is used to retrieve from inputs and store in outputs. + protected override void SolveInstance (IGH_DataAccess DA) { + DendroVolume vBase = new DendroVolume (); + List vSubtract = new List (); + + if (!DA.GetData (0, ref vBase)) return; + if (!DA.GetDataList (1, vSubtract)) return; + + DendroVolume csg = vBase.BooleanDifference (vSubtract); + + if (!csg.IsValid) { + AddRuntimeMessage (GH_RuntimeMessageLevel.Error, "CSG failed. Make sure all supplied volumes are valid"); + return; + } + + DA.SetData (0, new VolumeGOO (csg)); + } + + /// + /// Provides an Icon for the component. + /// + protected override System.Drawing.Bitmap Icon { + get { + //You can add image files to your project resources and access them like this: + // return Resources.IconForThisComponent; + return DendroGH.Properties.Resources.ico_bool_sub; + } + } + + /// + /// Gets the unique ID for this component. Do not change this ID after release. + /// + public override Guid ComponentGuid { + get { return new Guid ("538a2666-a714-4f34-a0a8-76097a8f0c11"); } + } + } +} \ No newline at end of file diff --git a/DendroGH/Components/VolumeFromCurve.cs b/DendroGH/Components/VolumeFromCurve.cs new file mode 100644 index 0000000..48d1c03 --- /dev/null +++ b/DendroGH/Components/VolumeFromCurve.cs @@ -0,0 +1,82 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Grasshopper.Kernel; +using Grasshopper.Kernel.Types; +using Rhino.Geometry; + +namespace DendroGH { + public class CurveToVolume : GH_Component { + /// + /// Initializes a new instance of the CurveToVolume class. + /// + public CurveToVolume () : base ("Curve To Volume", "vCurve", + "Create a volume from a list of curves", + "Dendro", "Convert") { } + + /// + /// Registers all the input parameters for this component. + /// + protected override void RegisterInputParams (GH_Component.GH_InputParamManager pManager) { + pManager.AddCurveParameter ("Curves", "C", "Curves", GH_ParamAccess.list); + pManager.AddNumberParameter ("Curve Radius", "R", "Supply one value or a list of values equal to the number of curves supplied", GH_ParamAccess.list); + pManager.AddGenericParameter ("Settings", "S", "Settings for converting different geometry types to and from volumes", GH_ParamAccess.item); + } + + /// + /// Registers all the output parameters for this component. + /// + protected override void RegisterOutputParams (GH_Component.GH_OutputParamManager pManager) { + pManager.AddGenericParameter ("Volume", "V", "Volume geometry", GH_ParamAccess.item); + } + + /// + /// This is the method that actually does the work. + /// + /// The DA object is used to retrieve from inputs and store in outputs. + protected override void SolveInstance (IGH_DataAccess DA) { + List vCurves = new List (); + List vRadius = new List (); + DendroSettings vSettings = new DendroSettings (); + + if (!DA.GetDataList (0, vCurves)) return; + if (!DA.GetDataList (1, vRadius)) return; + if (!DA.GetData (2, ref vSettings)) return; + + double minRadius = vSettings.VoxelSize / 0.6667; + + foreach (double radius in vRadius) + { + if(radius <= minRadius) + { + AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Radius must be at least 33% larger than voxel size. This will compute but no volume will be created."); + } + } + + DendroVolume volume = new DendroVolume (vCurves, vRadius, vSettings); + + if (!volume.IsValid) { + AddRuntimeMessage (GH_RuntimeMessageLevel.Error, "Conversion failed. Make sure you supplied valid radius values or valid settings"); + return; + } + + DA.SetData (0, new VolumeGOO (volume)); + } + + /// + /// Provides an Icon for the component. + /// + protected override System.Drawing.Bitmap Icon { + get { + return DendroGH.Properties.Resources.ico_curve_vox; + } + } + + /// + /// Gets the unique ID for this component. Do not change this ID after release. + /// + public override Guid ComponentGuid { + get { return new Guid ("5d75d6c9-f24d-4f1e-a77c-984ea78dd5b0"); } + } + } +} \ No newline at end of file diff --git a/DendroGH/Components/VolumeFromMesh.cs b/DendroGH/Components/VolumeFromMesh.cs new file mode 100644 index 0000000..2a8800b --- /dev/null +++ b/DendroGH/Components/VolumeFromMesh.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using Grasshopper.Kernel; +using Rhino.Geometry; + +namespace DendroGH { + public class VolumeFromMesh : GH_Component { + /// + /// Initializes a new instance of the VolumeFromMesh class. + /// + public VolumeFromMesh () : base ("Mesh to Volume", "vMesh", + "Create a volume that approximates mesh geometry", + "Dendro", "Convert") { } + + /// + /// Registers all the input parameters for this component. + /// + protected override void RegisterInputParams (GH_Component.GH_InputParamManager pManager) { + pManager.AddMeshParameter ("Mesh", "M", "Base mesh", GH_ParamAccess.item); + pManager.AddGenericParameter ("Settings", "S", "Settings for converting different geometry types to and from volumes", GH_ParamAccess.item); + } + + /// + /// Registers all the output parameters for this component. + /// + protected override void RegisterOutputParams (GH_Component.GH_OutputParamManager pManager) { + pManager.AddGenericParameter ("Volume", "V", "Volume geometry", GH_ParamAccess.item); + } + + /// + /// This is the method that actually does the work. + /// + /// The DA object is used to retrieve from inputs and store in outputs. + protected override void SolveInstance (IGH_DataAccess DA) { + Mesh vMesh = new Mesh (); + DendroSettings vSettings = new DendroSettings (); + + if (!DA.GetData (0, ref vMesh)) return; + if (!DA.GetData (1, ref vSettings)) return; + + DendroVolume volume = new DendroVolume (vMesh, vSettings); + + if (!volume.IsValid) { + AddRuntimeMessage (GH_RuntimeMessageLevel.Error, "Conversion failed. Make sure you supplied a valid mesh and correct settings"); + return; + } + + DA.SetData(0, new VolumeGOO(volume)); + } + + /// + /// Provides an Icon for the component. + /// + protected override System.Drawing.Bitmap Icon { + get { + return DendroGH.Properties.Resources.ico_mesh_vox; + } + } + + /// + /// Gets the unique ID for this component. Do not change this ID after release. + /// + public override Guid ComponentGuid { + get { return new Guid ("d6403738-1061-47a6-b143-1f9cd72d8188"); } + } + } +} \ No newline at end of file diff --git a/DendroGH/Components/VolumeFromPoints.cs b/DendroGH/Components/VolumeFromPoints.cs new file mode 100644 index 0000000..b1b9695 --- /dev/null +++ b/DendroGH/Components/VolumeFromPoints.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using Grasshopper.Kernel; +using Rhino.Geometry; + +namespace DendroGH { + public class PointsToVolume : GH_Component { + /// + /// Initializes a new instance of the PointsToVolume class. + /// + public PointsToVolume () : base ("Points To Volume", "vPoints", + "Create a volume from a point set", + "Dendro", "Convert") { } + + /// + /// Registers all the input parameters for this component. + /// + protected override void RegisterInputParams (GH_Component.GH_InputParamManager pManager) { + pManager.AddPointParameter ("Points", "P", "Points to convert into a volume", GH_ParamAccess.list); + pManager.AddNumberParameter ("Point Radius", "R", "Supply one value or a list of values equal to the number of curves supplied", GH_ParamAccess.list); + pManager.AddGenericParameter ("Settings", "S", "Settings for converting different geometry types to and from volumes", GH_ParamAccess.item); + } + + /// + /// Registers all the output parameters for this component. + /// + protected override void RegisterOutputParams (GH_Component.GH_OutputParamManager pManager) { + pManager.AddGenericParameter ("Volume", "V", "Volume geometry", GH_ParamAccess.item); + } + + /// + /// This is the method that actually does the work. + /// + /// The DA object is used to retrieve from inputs and store in outputs. + protected override void SolveInstance (IGH_DataAccess DA) { + List vPoints = new List (); + List vRadius = new List (); + DendroSettings vSettings = new DendroSettings (); + + if (!DA.GetDataList (0, vPoints)) return; + if (!DA.GetDataList (1, vRadius)) return; + if (!DA.GetData (2, ref vSettings)) return; + + double minRadius = vSettings.VoxelSize / 0.6667; + + foreach (double radius in vRadius) + { + if (radius <= minRadius) + { + AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Radius must be at least 33% larger than voxel size. This will compute but no volume will be created."); + } + } + + DendroVolume volume = new DendroVolume (vPoints, vRadius, vSettings); + + if (!volume.IsValid) { + AddRuntimeMessage (GH_RuntimeMessageLevel.Error, "Conversion failed. Make sure you supplied valid radius values or valid settings"); + return; + } + + DA.SetData (0, new VolumeGOO (volume)); + } + + /// + /// Provides an Icon for the component. + /// + protected override System.Drawing.Bitmap Icon { + get { + return DendroGH.Properties.Resources.ico_point_vox; + } + } + + /// + /// Gets the unique ID for this component. Do not change this ID after release. + /// + public override Guid ComponentGuid { + get { return new Guid ("fe8d2a29-8f2b-4952-ad70-bf8d3c23427a"); } + } + } +} \ No newline at end of file diff --git a/DendroGH/Components/VolumeIntersection.cs b/DendroGH/Components/VolumeIntersection.cs new file mode 100644 index 0000000..35207a2 --- /dev/null +++ b/DendroGH/Components/VolumeIntersection.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using Grasshopper.Kernel; +using Rhino.Geometry; + +namespace DendroGH { + public class VolumeIntersection : GH_Component { + /// + /// Initializes a new instance of the VolumeIntersection class. + /// + public VolumeIntersection () : base ("Volume Intersection", "vInt", + "Perform a intersection operation on a set of volumes", + "Dendro", "Intersect") { } + + /// + /// Registers all the input parameters for this component. + /// + protected override void RegisterInputParams (GH_Component.GH_InputParamManager pManager) { + pManager.AddGenericParameter ("Volume A", "A", "First Volume", GH_ParamAccess.item); + pManager.AddGenericParameter ("Volumes B", "B", "Second Volume set", GH_ParamAccess.list); + } + + /// + /// Registers all the output parameters for this component. + /// + protected override void RegisterOutputParams (GH_Component.GH_OutputParamManager pManager) { + pManager.AddGenericParameter ("Result", "R", "Intersection result", GH_ParamAccess.item); + } + + /// + /// This is the method that actually does the work. + /// + /// The DA object is used to retrieve from inputs and store in outputs. + protected override void SolveInstance (IGH_DataAccess DA) { + DendroVolume vBase = new DendroVolume (); + List vIntersect = new List (); + + if (!DA.GetData (0, ref vBase)) return; + if (!DA.GetDataList (1, vIntersect)) return; + + DendroVolume csg = vBase.BooleanIntersection (vIntersect); + + if (!csg.IsValid) { + AddRuntimeMessage (GH_RuntimeMessageLevel.Error, "CSG failed. Make sure all supplied volumes are valid"); + return; + } + + DA.SetData (0, new VolumeGOO (csg)); + } + + /// + /// Provides an Icon for the component. + /// + protected override System.Drawing.Bitmap Icon { + get { + return DendroGH.Properties.Resources.ico_bool_int; + } + } + + /// + /// Gets the unique ID for this component. Do not change this ID after release. + /// + public override Guid ComponentGuid { + get { return new Guid ("52335925-f117-419c-a3f4-7e6da9bf9366"); } + } + } +} \ No newline at end of file diff --git a/DendroGH/Components/VolumeOffset.cs b/DendroGH/Components/VolumeOffset.cs new file mode 100644 index 0000000..dfe2bfc --- /dev/null +++ b/DendroGH/Components/VolumeOffset.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using Grasshopper.Kernel; +using Rhino.Geometry; + +namespace DendroGH { + public class VolumeOffset : GH_Component { + /// + /// Initializes a new instance of the DendroOffset class. + /// + public VolumeOffset () : base ("Offset Volume", "vOffset", + "Offset a volume by a fixed amount", + "Dendro", "Filters") { } + + /// + /// Registers all the input parameters for this component. + /// + protected override void RegisterInputParams (GH_Component.GH_InputParamManager pManager) { + pManager.AddGenericParameter ("Volume", "V", "Volume geometry", GH_ParamAccess.item); + pManager.AddNumberParameter ("Distance", "D", "Offset distance", GH_ParamAccess.item); + pManager.AddGenericParameter ("Mask", "M", "(Optional) Mask for filter operations", GH_ParamAccess.item); + pManager[2].Optional = true; + } + + /// + /// Registers all the output parameters for this component. + /// + protected override void RegisterOutputParams (GH_Component.GH_OutputParamManager pManager) { + pManager.AddGenericParameter ("Volume", "V", "Offset volume", GH_ParamAccess.item); + } + + /// + /// This is the method that actually does the work. + /// + /// The DA object is used to retrieve from inputs and store in outputs. + protected override void SolveInstance (IGH_DataAccess DA) { + DendroVolume volume = new DendroVolume (); + DendroMask vMask = new DendroMask (); + double oAmount = 0.0; + + if (!DA.GetData (0, ref volume)) return; + if (!DA.GetData (1, ref oAmount)) return; + DA.GetData (2, ref vMask); + + if (vMask == null) return; + + DendroVolume offset = new DendroVolume(); + + if (vMask.IsValid) { + offset = volume.Offset (oAmount, vMask); + } + else { + offset = volume.Offset (oAmount); + } + + if (!offset.IsValid) { + AddRuntimeMessage (GH_RuntimeMessageLevel.Error, "Offset failed. Make sure all supplied volumes are valid"); + return; + } + + DA.SetData (0, new VolumeGOO (offset)); + } + + /// + /// Provides an Icon for the component. + /// + protected override System.Drawing.Bitmap Icon { + get { + return DendroGH.Properties.Resources.ico_offset; + } + } + + /// + /// Gets the unique ID for this component. Do not change this ID after release. + /// + public override Guid ComponentGuid { + get { return new Guid ("bff5520d-152a-4a1f-adda-2355f2478b9c"); } + } + } +} \ No newline at end of file diff --git a/DendroGH/Components/VolumeParam.cs b/DendroGH/Components/VolumeParam.cs new file mode 100644 index 0000000..2df1429 --- /dev/null +++ b/DendroGH/Components/VolumeParam.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using Grasshopper.Kernel; +using Rhino.Geometry; + +namespace DendroGH { + public class VolumeParam : GH_Param, IGH_PreviewObject { + /// + /// Initializes a new instance of the VolumeParam class. + /// + public VolumeParam () : base (new GH_InstanceDescription ("Volume", "Volume", "Contains a collection of Volumes", "Dendro", "_Types")) { } + + /// + /// Provides an Icon for the component. + /// + protected override System.Drawing.Bitmap Icon { + get { + return DendroGH.Properties.Resources.ico_param_vox; + } + } + + /// + /// Gets the unique ID for this component. Do not change this ID after release. + /// + public override Guid ComponentGuid { + get { return new Guid ("f363676f-3ae9-48ac-ab4d-258d8d09e2a7"); } + } + + bool _hidden; + public bool Hidden { + get { + return _hidden; + } + set { + _hidden = value; + } + } + + public bool IsPreviewCapable { + get { return true; } + } + + public BoundingBox ClippingBox { + get { return Preview_ComputeClippingBox (); } + } + + public void DrawViewportMeshes (IGH_PreviewArgs args) { + if (args.Document.PreviewMode == GH_PreviewMode.Shaded && + args.Display.SupportsShading) { + Preview_DrawMeshes (args); + } + } + + public void DrawViewportWires (IGH_PreviewArgs args) { + + } + } +} \ No newline at end of file diff --git a/DendroGH/Components/VolumeSettings.cs b/DendroGH/Components/VolumeSettings.cs new file mode 100644 index 0000000..ae6b1bb --- /dev/null +++ b/DendroGH/Components/VolumeSettings.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using Grasshopper.Kernel; +using Rhino.Geometry; + +namespace DendroGH { + public class VolumeSettings : GH_Component { + /// + /// Initializes a new instance of the VolumeSettings class. + /// + public VolumeSettings () : base ("Volume Settings", "vSettings", + "Settings for converting different geometry types to and from volumes", + "Dendro", "Convert") { } + + /// + /// Registers all the input parameters for this component. + /// + protected override void RegisterInputParams (GH_Component.GH_InputParamManager pManager) { + pManager.AddNumberParameter ("Voxel Size", "S", "Size of voxels in the output volume", GH_ParamAccess.item, 1); + pManager.AddNumberParameter ("Bandwidth", "B", "Desired radius in voxel units around the surface", GH_ParamAccess.item, 1); + pManager.AddNumberParameter ("Isovalue", "I", "Crossing point of the volume that is considered the surface", GH_ParamAccess.item, 0.0); + pManager.AddNumberParameter ("Adaptivity", "A", "Value range from 0-1. Higher adaptivities will allow more variation " + + "in polygon size, resulting in fewer polygons.", GH_ParamAccess.item, 0.1); + } + + /// + /// Registers all the output parameters for this component. + /// + protected override void RegisterOutputParams (GH_Component.GH_OutputParamManager pManager) { + pManager.AddGenericParameter ("Volume Settings", "S", "Global Volume Settings to be used", GH_ParamAccess.item); + } + + /// + /// This is the method that actually does the work. + /// + /// The DA object is used to retrieve from inputs and store in outputs. + protected override void SolveInstance (IGH_DataAccess DA) { + double bandwidth = 5.0; + double voxelSize = 1.0; + double isoValue = 0.0; + double adaptivity = 0.1; + + if (!DA.GetData (0, ref voxelSize)) return; + if (!DA.GetData (1, ref bandwidth)) return; + if (!DA.GetData (2, ref isoValue)) return; + if (!DA.GetData (3, ref adaptivity)) return; + + DendroSettings vs = new DendroSettings (); + + vs.Adaptivity = adaptivity; + vs.Bandwidth = bandwidth; + vs.IsoValue = isoValue; + vs.VoxelSize = voxelSize; + + DA.SetData (0, new SettingsGOO (vs)); + } + + /// + /// Provides an Icon for the component. + /// + protected override System.Drawing.Bitmap Icon { + get { + return DendroGH.Properties.Resources.ico_settings; + } + } + + /// + /// Gets the unique ID for this component. Do not change this ID after release. + /// + public override Guid ComponentGuid { + get { return new Guid ("6db84a8d-28e4-4ebe-bf2f-c954caf319b9"); } + } + } +} \ No newline at end of file diff --git a/DendroGH/Components/VolumeSmooth.cs b/DendroGH/Components/VolumeSmooth.cs new file mode 100644 index 0000000..52ff941 --- /dev/null +++ b/DendroGH/Components/VolumeSmooth.cs @@ -0,0 +1,90 @@ +using System; +using System.Collections.Generic; +using Grasshopper.Kernel; +using Rhino.Geometry; + +namespace DendroGH { + public class VolumeSmooth : GH_Component { + /// + /// Initializes a new instance of the ovdbSmooth class. + /// + public VolumeSmooth () : base ("Smooth Volume", "vSmooth", + "Apply smoothing to volume", + "Dendro", "Filters") { } + + /// + /// Registers all the input parameters for this component. + /// + protected override void RegisterInputParams (GH_Component.GH_InputParamManager pManager) { + pManager.AddGenericParameter ("Volume", "V", "Volume geometry", GH_ParamAccess.item); + pManager.AddIntegerParameter ("Width", "W", "(Optional) Width of smoothing. This value acts as a multiplier.", GH_ParamAccess.item, 1); + pManager.AddIntegerParameter ("Type", "T", "0 - gaussian, 1 - laplacian, 2 - mean, 3 - median", GH_ParamAccess.item, 1); + pManager.AddIntegerParameter ("Iterations", "I", "Number of smoothing iterations", GH_ParamAccess.item, 1); + pManager.AddGenericParameter ("Mask", "M", "(Optional) Mask for filter operations", GH_ParamAccess.item); + pManager[4].Optional = true; + } + + /// + /// Registers all the output parameters for this component. + /// + protected override void RegisterOutputParams (GH_Component.GH_OutputParamManager pManager) { + pManager.AddGenericParameter ("Volume", "V", "Smoothed volume", GH_ParamAccess.item); + } + + /// + /// This is the method that actually does the work. + /// + /// The DA object is used to retrieve from inputs and store in outputs. + protected override void SolveInstance (IGH_DataAccess DA) { + DendroVolume sVolume = new DendroVolume (); + DendroMask vMask = new DendroMask (); + int sType = 1; + int sIterations = 1; + int sWidth = 1; + + if (!DA.GetData (0, ref sVolume)) return; + if (!DA.GetData (1, ref sWidth)) return; + if (!DA.GetData (2, ref sType)) return; + if (!DA.GetData (3, ref sIterations)) return; + DA.GetData (4, ref vMask); + + if (vMask == null) return; + + DendroVolume smooth = new DendroVolume(); + + if (vMask.IsValid) + { + smooth = sVolume.Smooth(sType, sIterations, vMask, sWidth); + } + else + { + smooth = sVolume.Smooth(sType, sIterations, sWidth); + } + + if (!smooth.IsValid) + { + AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Smooth failed. Make sure all supplied volumes are valid"); + return; + } + + DA.SetData (0, new VolumeGOO (smooth)); + + } + + /// + /// Provides an Icon for the component. + /// + protected override System.Drawing.Bitmap Icon { + get { + return DendroGH.Properties.Resources.ico_smooth; + } + } + + /// + /// Gets the unique ID for this component. Do not change this ID after release. + /// + public override Guid ComponentGuid { + get { return new Guid ("cc7da05b-aea7-47ce-b74d-6d84d25ebac3"); } + } + } +} \ No newline at end of file diff --git a/DendroGH/Components/VolumeToMesh.cs b/DendroGH/Components/VolumeToMesh.cs new file mode 100644 index 0000000..e929da6 --- /dev/null +++ b/DendroGH/Components/VolumeToMesh.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using Grasshopper.Kernel; +using Rhino.Geometry; + +namespace DendroGH { + public class VolumeToMesh : GH_Component { + /// + /// Initializes a new instance of the VolumeToMesh class. + /// + public VolumeToMesh () : base ("Volume to Mesh", "mVolume", + "Create a mesh that approximates volume geometry", + "Dendro", "Convert") { } + + /// + /// Registers all the input parameters for this component. + /// + protected override void RegisterInputParams (GH_Component.GH_InputParamManager pManager) { + pManager.AddGenericParameter ("Volume", "V", "Volume geometry", GH_ParamAccess.item); + pManager.AddGenericParameter ("Volume Settings", "S", "Global Volume Settings to be used", GH_ParamAccess.item); + } + + /// + /// Registers all the output parameters for this component. + /// + protected override void RegisterOutputParams (GH_Component.GH_OutputParamManager pManager) { + pManager.AddMeshParameter ("Mesh", "M", "Mesh conversion of volume", GH_ParamAccess.item); + } + + /// + /// This is the method that actually does the work. + /// + /// The DA object is used to retrieve from inputs and store in outputs. + protected override void SolveInstance (IGH_DataAccess DA) { + DendroVolume mVolume = new DendroVolume (); + DendroSettings vSettings = new DendroSettings (); + + if (!DA.GetData (0, ref mVolume)) return; + if (!DA.GetData (1, ref vSettings)) return; + + if (!mVolume.IsValid) { + AddRuntimeMessage (GH_RuntimeMessageLevel.Error, "Volume is not valid"); + return; + } + + mVolume.UpdateDisplay (vSettings); + + DA.SetData (0, mVolume.Display); + } + + /// + /// Provides an Icon for the component. + /// + protected override System.Drawing.Bitmap Icon { + get { + return DendroGH.Properties.Resources.ico_vox_mesh; + } + } + + /// + /// Gets the unique ID for this component. Do not change this ID after release. + /// + public override Guid ComponentGuid { + get { return new Guid ("858d89ff-5854-4e5f-aeb2-0e43e580835e"); } + } + } +} \ No newline at end of file diff --git a/DendroGH/Components/VolumeUnion.cs b/DendroGH/Components/VolumeUnion.cs new file mode 100644 index 0000000..1619460 --- /dev/null +++ b/DendroGH/Components/VolumeUnion.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using Grasshopper.Kernel; +using Rhino.Geometry; + +namespace DendroGH { + public class VolumeUnion : GH_Component { + /// + /// Initializes a new instance of the ovdbUnion class. + /// + public VolumeUnion () : base ("Volume Union", "vUnion", + "Perform a union operation on a set of volumes", + "Dendro", "Intersect") { } + + /// + /// Registers all the input parameters for this component. + /// + protected override void RegisterInputParams (GH_Component.GH_InputParamManager pManager) { + pManager.AddGenericParameter ("Volumes", "V", "Volumes to union", GH_ParamAccess.list); + } + + /// + /// Registers all the output parameters for this component. + /// + protected override void RegisterOutputParams (GH_Component.GH_OutputParamManager pManager) { + pManager.AddGenericParameter ("Result", "R", "Union result", GH_ParamAccess.item); + } + + /// + /// This is the method that actually does the work. + /// + /// The DA object is used to retrieve from inputs and store in outputs. + protected override void SolveInstance (IGH_DataAccess DA) { + List vUnion = new List (); + + if (!DA.GetDataList (0, vUnion)) return; + + if (vUnion.Count < 1) { + AddRuntimeMessage (GH_RuntimeMessageLevel.Error, "Need to supply a value"); + return; + } + + DendroVolume csg = new DendroVolume(); + + if (vUnion.Count == 1) { + csg = new DendroVolume (vUnion[0]); + } + else { + csg = vUnion[0].BooleanUnion (vUnion); + } + + if (!csg.IsValid) { + AddRuntimeMessage (GH_RuntimeMessageLevel.Error, "CSG failed. Make sure all supplied volumes are valid"); + return; + } + + DA.SetData (0, new VolumeGOO (csg)); + } + + /// + /// Provides an Icon for the component. + /// + protected override System.Drawing.Bitmap Icon { + get { + return DendroGH.Properties.Resources.ico_bool_union; + } + } + + /// + /// Gets the unique ID for this component. Do not change this ID after release. + /// + public override Guid ComponentGuid { + get { return new Guid ("dc9d71b6-f859-4b95-ad2a-608bee0f6b23"); } + } + } +} \ No newline at end of file diff --git a/DendroGH/Components/WriteFile.cs b/DendroGH/Components/WriteFile.cs new file mode 100644 index 0000000..a7e0652 --- /dev/null +++ b/DendroGH/Components/WriteFile.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using Grasshopper.Kernel; +using Rhino.Geometry; + +namespace DendroGH { + public class WriteFile : GH_Component { + /// + /// Initializes a new instance of the WriteFile class. + /// + public WriteFile () : base ("Write Volume", "vWrite", + "Write a Volume to a file", + "Dendro", "IO") { } + + /// + /// Registers all the input parameters for this component. + /// + protected override void RegisterInputParams (GH_Component.GH_InputParamManager pManager) { + pManager.AddGenericParameter ("Volume", "V", "Volume geometry", GH_ParamAccess.item); + pManager.AddTextParameter("File Path", "F", "Path of volume file (*.vdb files)", GH_ParamAccess.item); + pManager.AddBooleanParameter("Write?", "W", "Boolean toggle to write file", GH_ParamAccess.item); + } + + /// + /// Registers all the output parameters for this component. + /// + protected override void RegisterOutputParams (GH_Component.GH_OutputParamManager pManager) { } + + /// + /// This is the method that actually does the work. + /// + /// The DA object is used to retrieve from inputs and store in outputs. + protected override void SolveInstance (IGH_DataAccess DA) { + DendroVolume volume = new DendroVolume (); + string filepath = ""; + bool isWrite = false; + + if (!DA.GetData (0, ref volume)) return; + if (!DA.GetData (1, ref filepath)) return; + if (!DA.GetData(2, ref isWrite)) return; + + if (isWrite) + { + bool success = volume.Write(filepath); + + if (!success) + { + AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Write failed. Make sure you supplied a path plus filename with the extension *.vdb"); + return; + } + } + + } + + /// + /// Provides an Icon for the component. + /// + protected override System.Drawing.Bitmap Icon { + get { + return DendroGH.Properties.Resources.ico_io_out; + } + } + + /// + /// Gets the unique ID for this component. Do not change this ID after release. + /// + public override Guid ComponentGuid { + get { return new Guid ("e0ee9551-254b-49d0-b4ec-53238c7e9668"); } + } + } +} \ No newline at end of file diff --git a/DendroGH/DendroGH.csproj b/DendroGH/DendroGH.csproj new file mode 100644 index 0000000..37ba8a9 --- /dev/null +++ b/DendroGH/DendroGH.csproj @@ -0,0 +1,175 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {A45EBB63-85ED-4B96-BC3A-21221C1DC605} + Library + Properties + DendroGH + DendroGH + v4.5 + 512 + false + + + + + true + full + false + $(SolutionDir)x64\$(Configuration)\ + DEBUG;TRACE + prompt + false + + + pdbonly + true + $(SolutionDir)x64\$(Configuration)\ + TRACE + prompt + 4 + + + + ..\packages\Grasshopper.0.9.76\lib\net35\GH_IO.dll + + + ..\packages\Grasshopper.0.9.76\lib\net35\Grasshopper.dll + + + ..\packages\RhinoCommon.5.12.50810.13095\lib\net35\RhinoCommon.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + True + True + Resources.resx + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Copy "$(TargetPath)" "$(TargetDir)$(ProjectName).gha" +Erase "$(TargetPath)" + + + en-US + + + C:\Program Files\Rhino 6\System\Rhino.exe + + + Program + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + \ No newline at end of file diff --git a/DendroGH/DendroGHComponent.cs b/DendroGH/DendroGHComponent.cs new file mode 100644 index 0000000..f4704d0 --- /dev/null +++ b/DendroGH/DendroGHComponent.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; + +using Grasshopper.Kernel; +using Rhino.Geometry; + +// In order to load the result of this wizard, you will also need to +// add the output bin/ folder of this project to the list of loaded +// folder in Grasshopper. +// You can use the _GrasshopperDeveloperSettings Rhino command for that. + +namespace DendroGH +{ + public class DendroGHComponent : GH_Component + { + /// + /// Each implementation of GH_Component must provide a public + /// constructor without any arguments. + /// Category represents the Tab in which the component will appear, + /// Subcategory the panel. If you use non-existing tab or panel names, + /// new tabs/panels will automatically be created. + /// + public DendroGHComponent() + : base("DendroGH", "Nickname", + "Description", + "Category", "Subcategory") + { + } + + /// + /// Registers all the input parameters for this component. + /// + protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager) + { + } + + /// + /// Registers all the output parameters for this component. + /// + protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager) + { + } + + /// + /// This is the method that actually does the work. + /// + /// The DA object can be used to retrieve data from input parameters and + /// to store data in output parameters. + protected override void SolveInstance(IGH_DataAccess DA) + { + } + + /// + /// Provides an Icon for every component that will be visible in the User Interface. + /// Icons need to be 24x24 pixels. + /// + protected override System.Drawing.Bitmap Icon + { + get + { + // You can add image files to your project resources and access them like this: + //return Resources.IconForThisComponent; + return null; + } + } + + /// + /// Each component must have a unique Guid to identify it. + /// It is vital this Guid doesn't change otherwise old ghx files + /// that use the old ID will partially fail during loading. + /// + public override Guid ComponentGuid + { + get { return new Guid("dc9baa94-6e90-4150-97d8-82796714f454"); } + } + } +} diff --git a/DendroGH/DendroGHInfo.cs b/DendroGH/DendroGHInfo.cs new file mode 100644 index 0000000..956fa11 --- /dev/null +++ b/DendroGH/DendroGHInfo.cs @@ -0,0 +1,56 @@ +using System; +using System.Drawing; +using Grasshopper.Kernel; + +namespace DendroGH +{ + public class DendroGHInfo : GH_AssemblyInfo + { + public override string Name + { + get + { + return "DendroGH"; + } + } + public override Bitmap Icon + { + get + { + //Return a 24x24 pixel bitmap to represent this GHA library. + return null; + } + } + public override string Description + { + get + { + //Return a short string describing the purpose of this GHA library. + return ""; + } + } + public override Guid Id + { + get + { + return new Guid("e355f38c-064c-4317-a17c-499c5a2fcded"); + } + } + public override string AuthorName + { + get + { + //Return a string identifying you or your company. + return "ecr labs"; + } + } + public override string AuthorContact + { + get + { + //Return a string representing your preferred contact details. + return "dev@ecrlabs.com"; + } + } + } +} diff --git a/DendroGH/Goo/MaskGOO.cs b/DendroGH/Goo/MaskGOO.cs new file mode 100644 index 0000000..76bd820 --- /dev/null +++ b/DendroGH/Goo/MaskGOO.cs @@ -0,0 +1,258 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Grasshopper; +using Grasshopper.Kernel; +using Grasshopper.Kernel.Types; +using Rhino.Geometry; + +namespace DendroGH { + /// + /// goo implementation for DendroMask data types + /// + /// mask object + public class MaskGOO : GH_GeometricGoo, IGH_BakeAwareData, IGH_PreviewData { +#region Constructors + /// + /// default constructor + /// + public MaskGOO () { + this.Value = new DendroMask (); + } + + /// + /// copy constructor + /// + /// mask to copy from + public MaskGOO (DendroMask vMask) { + if (vMask == null) { + vMask = new DendroMask (); + } + this.Value = new DendroMask (vMask); + } + + /// + /// make a complete duplicate of this instance + /// + /// duplicated MaskGOO + public MaskGOO DuplicateGoo () { + if (this.Value == null) { + return new MaskGOO (); + } + else { + DendroMask mask = new DendroMask (Value); + return new MaskGOO (mask); + } + } + + /// + /// make a complete duplicate of this instance + /// + /// duplicated MaskGOO + public override IGH_Goo Duplicate () { + return DuplicateGoo (); + } + + /// + /// make a complete duplicate of this geometry + /// + /// duplicated MaskGOO + public override IGH_GeometricGoo DuplicateGeometry () { + return DuplicateGoo (); + } +#endregion + +#region Properties + /// + /// gets a value indicating whether or not the current value is valid + /// + /// property value + public override bool IsValid { + get { + if (Value == null) { return false; } + return Value.IsValid; + } + } + + /// + /// gets a string describing the state of "invalidness". if the instance is valid, then this property should return Nothing or String.Empty + /// + /// property value + public override string IsValidWhyNot { + get { + if (Value.IsValid) { + return "Dendro Mask is valid"; + } + else { + return "Dendro Mask is not valid"; + } + } + } + + /// + /// creates a string description of the current instance value + /// + /// property value + public override string ToString () { + if (Value == null) + return "Invalid Dendro Mask"; + else return "Dendro Mask"; + } + + /// + /// gets a description of the type of the implementation + /// + /// property value + public override string TypeDescription { + get { return ("Container for Dendro Masks"); } + } + + /// + /// gets the name of the type of the implementation + /// + /// property value + public override string TypeName { + get { return "Dendro Mask"; } + } + + /// + /// gets the world axis aligned boundingbox for the mask + /// + /// boundingbox of the geometry in world coordinates or BoundingBox.Empty if not bounding box could be found + public override BoundingBox Boundingbox { + get { + return Value.GetBoundingBox (); + } + } + + /// + /// gets the world axis aligned boundingbox for the transformed mask + /// + /// transformation to apply to object prior to the bounding box computation + /// accurate boundingbox of the transformed geometry in world coordinates or BoundingBox.Empty if not bounding box could be found + public override BoundingBox GetBoundingBox (Transform xform) { + return Value.GetBoundingBox (xform); + } + + /// + /// bake an object in the given rhino document + /// + /// document to bake into + /// attributes to bake with (should not be null) + /// the id of the baked object + /// true on success. ifalse, obj_guid and obj_inst are not guaranteed to be valid pointers + public bool BakeGeometry (Rhino.RhinoDoc doc, Rhino.DocObjects.ObjectAttributes att, out Guid obj_guid) { + obj_guid = Guid.Empty; + + if (Value == null) + return false; + + if (!Value.IsValid) + return false; + + doc.Objects.AddMesh (Value.Display); + + return true; + } +#endregion + +#region Casting + /// + /// this function will be called when the local IGH_Goo instance disappears into a user script + /// + /// returns the DendroMask instance + public override object ScriptVariable () { + return Value; + } + + /// + /// attempt a cast to type Q + /// + /// pointer to target of cast + /// type to cast to + /// true on success, false on failure + public override bool CastTo (out Q target) { + if (typeof (Q).IsAssignableFrom (typeof (DendroMask))) { + if (Value == null) + target = default (Q); + else + target = (Q) (object) Value; + return true; + } + target = default (Q); + return false; + } + + /// + /// attempt a cast from generic object + /// + /// reference to source of cast + /// true on success, false on failure + public override bool CastFrom (object source) { + return false; + } +#endregion + +#region Transformation + /// + /// transforms the object or a deformable representation of the object + /// + /// transformation matrix + /// transformed geometry + public override IGH_GeometricGoo Transform (Transform xform) { + DendroMask mask = new DendroMask (Value); + + mask.Transform (xform); + + return new MaskGOO (mask); + } + + /// + /// morph the object or a deformable representation of the object + /// + /// spatial deform + /// deformed geometry + public override IGH_GeometricGoo Morph (SpaceMorph xmorph) { + throw new NotImplementedException (); + } +#endregion + +#region Display + /// + /// gets the clipping box for this data + /// + /// clipping box for this object + public BoundingBox ClippingBox { + get { + return Value.GetBoundingBox (); + } + } + + /// + /// draw all wire and point previews + /// + public void DrawViewportWires (GH_PreviewWireArgs args) { + + } + + /// + /// draw all shaded meshes + /// + public void DrawViewportMeshes (GH_PreviewMeshArgs args) { + + if (Value == null) + return; + + if (args.Pipeline.SupportsShading) { + var c = args.Material.Diffuse; + c = System.Drawing.Color.FromArgb ((int) (args.Material.Transparency * 255), c); + + args.Pipeline.DrawMeshShaded (Value.Display, args.Material); + } + } +#endregion + + } +} \ No newline at end of file diff --git a/DendroGH/Goo/SettingsGOO.cs b/DendroGH/Goo/SettingsGOO.cs new file mode 100644 index 0000000..b1f7589 --- /dev/null +++ b/DendroGH/Goo/SettingsGOO.cs @@ -0,0 +1,147 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Grasshopper; +using Grasshopper.Kernel; +using Grasshopper.Kernel.Types; + +namespace DendroGH { + /// + /// goo implementation for DendroSettings data types + /// + /// settings object + public class SettingsGOO : GH_Goo { +#region Constructors + /// + /// default constructor + /// + public SettingsGOO () { + this.Value = new DendroSettings (); + } + + /// + /// copy constructor + /// + /// settings to copy from + public SettingsGOO (DendroSettings ds) { + if (ds == null) { + ds = new DendroSettings (); + } + this.Value = new DendroSettings (ds); + } + + /// + /// make a complete duplicate of this instance + /// + /// duplicated SettingsGOO + public SettingsGOO DuplicateGoo () { + if (this.Value == null) { + return new SettingsGOO (); + } + else { + DendroSettings ds = new DendroSettings (this.Value); + return new SettingsGOO (ds); + } + } + + /// + /// make a complete duplicate of this instance + /// + /// duplicated SettingsGOO + public override IGH_Goo Duplicate () { + return DuplicateGoo (); + } +#endregion + +#region Properties + + /// + /// gets a value indicating whether or not the current value is valid + /// + /// property value + public override bool IsValid { + get { + return true; + } + } + + /// + /// gets a string describing the state of "invalidness". if the instance is valid, then this property should return Nothing or String.Empty + /// + /// property value + public override string IsValidWhyNot { + get { + return base.IsValidWhyNot; + } + } + + /// + /// creates a string description of the current instance value + /// + /// property value + public override string ToString () { + if (m_value == null) + return "Null Dendro Settings"; + else return "Dendro Settings"; + } + + /// + /// gets a description of the type of the implementation + /// + /// property value + public override string TypeDescription { + get { return ("Dendro Settings container"); } + } + + /// + /// gets the name of the type of the implementation + /// + /// property value + public override string TypeName { + get { return "Dendro Settings"; } + } +#endregion + +#region Casting + /// + /// this function will be called when the local IGH_Goo instance disappears into a user script + /// + /// returns the DendroMask instance + public override object ScriptVariable () { + return Value; + } + + /// + /// attempt a cast to type Q + /// + /// pointer to target of cast + /// type to cast to + /// true on success, false on failure + public override bool CastTo(ref Q target) + { + if (typeof(Q).IsAssignableFrom(typeof(DendroSettings))) + { + if (Value == null) + target = default(Q); + else + target = (Q)(object)Value; + return true; + } + target = default(Q); + return false; + } + + /// + /// attempt a cast from generic object + /// + /// reference to source of cast + /// true on success, false on failure + public override bool CastFrom (object source) { + return false; + } +#endregion + + } +} \ No newline at end of file diff --git a/DendroGH/Goo/VolumeGOO.cs b/DendroGH/Goo/VolumeGOO.cs new file mode 100644 index 0000000..6ef5998 --- /dev/null +++ b/DendroGH/Goo/VolumeGOO.cs @@ -0,0 +1,277 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Grasshopper; +using Grasshopper.Kernel; +using Grasshopper.Kernel.Types; +using Rhino; +using Rhino.DocObjects; +using Rhino.Geometry; + +namespace DendroGH { + /// + /// goo implementation for DendroMask data types + /// + /// + public class VolumeGOO : GH_GeometricGoo, IGH_PreviewData, IGH_BakeAwareData { +#region Constructors + /// + /// default constructor + /// + public VolumeGOO () { + this.Value = new DendroVolume (); + } + + /// + /// copy constructor + /// + /// volume to copy from + public VolumeGOO (DendroVolume volume) { + if (volume == null) { + this.Value = new DendroVolume (); + } + else { + this.Value = new DendroVolume (volume); + } + } + + /// + /// make a complete duplicate of this instance + /// + /// duplicated VolumeGOO + public VolumeGOO DuplicateGoo () { + if (this.Value == null) { + return new VolumeGOO (); + } + else { + DendroVolume volume = new DendroVolume (this.Value); + return new VolumeGOO (volume); + } + } + + /// + /// make a complete duplicate of this instance + /// + /// duplicated VolumeGOO + public override IGH_Goo Duplicate () { + return DuplicateGoo (); + } + + /// + /// make a complete duplicate of this geometry + /// + /// duplicated VolumeGOO + public override IGH_GeometricGoo DuplicateGeometry () { + return DuplicateGoo (); + } +#endregion + +#region Properties + /// + /// gets a value indicating whether or not the current value is valid + /// + /// property value + public override bool IsValid { + get { + if (Value == null) { return false; } + return Value.IsValid; + } + } + + /// + /// gets a string describing the state of "invalidness". if the instance is valid, then this property should return Nothing or String.Empty + /// + /// property value + public override string IsValidWhyNot { + get { + if (this.IsValid) { + return "Dendro Volume is valid"; + } + else { + return "Dendro Volume is not valid"; + } + } + } + + /// + /// creates a string description of the current instance value + /// + /// property value + public override string ToString () { + if (Value == null) + return "Null DendroVolume"; + else return "DendroVolume"; + } + + /// + /// gets a description of the type of the implementation + /// + /// property value + public override string TypeDescription { + get { return ("Container for Dendro Volumes"); } + } + + /// + /// gets the name of the type of the implementation + /// + /// property value + public override string TypeName { + get { return "Dendro Volume"; } + } + + /// + /// gets the world axis aligned boundingbox for the mask + /// + /// boundingbox of the geometry in world coordinates or BoundingBox.Empty if not bounding box could be found + public override BoundingBox Boundingbox { + get { + return Value.GetBoundingBox (); + } + } + + /// + /// gets the world axis aligned boundingbox for the transformed mask + /// + /// transformation to apply to object prior to the bounding box computation + /// accurate boundingbox of the transformed geometry in world coordinates or BoundingBox.Empty if not bounding box could be found + public override BoundingBox GetBoundingBox (Transform xform) { + return Value.GetBoundingBox (xform); + } + + /// + /// bake an object in the given rhino document + /// + /// document to bake into + /// attributes to bake with (should not be null) + /// the id of the baked object + /// true on success. ifalse, obj_guid and obj_inst are not guaranteed to be valid pointers + public bool BakeGeometry (Rhino.RhinoDoc doc, Rhino.DocObjects.ObjectAttributes att, out Guid obj_guid) { + + obj_guid = Guid.Empty; + + if (Value == null) + return false; + + if (!Value.IsValid) + return false; + + doc.Objects.AddMesh (Value.Display); + + return true; + } +#endregion + +#region Casting + /// + /// this function will be called when the local IGH_Goo instance disappears into a user script + /// + /// returns the DendroMask instance + public override object ScriptVariable () { + return Value; + } + + /// + /// attempt a cast to type Q + /// + /// pointer to target of cast + /// type to cast to + /// true on success, false on failure + public override bool CastTo (out Q target) { + if (typeof (Q).IsAssignableFrom (typeof (DendroVolume))) { + if (Value == null) + target = default (Q); + else + target = (Q) (object) Value; + return true; + } + + if (typeof(Q).IsAssignableFrom(typeof(GH_Mesh))) + { + target = (Q)(object)new GH_Mesh(Value.Display); + return true; + } + + if (typeof(Q) == typeof(Mesh) || typeof(Q) == typeof(GeometryBase)) + { + target = (Q)(object)Value.Display; + return true; + } + + target = default (Q); + return false; + } + + /// + /// attempt a cast from generic object + /// + /// reference to source of cast + /// true on success, false on failure + public override bool CastFrom(object source) + { + return false; + } + #endregion + + #region Transformation Methods + /// + /// transforms the object or a deformable representation of the object + /// + /// transformation matrix + /// transformed geometry + public override IGH_GeometricGoo Transform (Transform xform) { + DendroVolume vol = new DendroVolume (Value); + + vol.Transform (xform); + + return new VolumeGOO (vol); + } + + /// + /// morph the object or a deformable representation of the object + /// + /// spatial deform + /// deformed geometry + public override IGH_GeometricGoo Morph (SpaceMorph xmorph) { + throw new NotImplementedException (); + } +#endregion + +#region Display + /// + /// gets the clipping box for this data + /// + /// clipping box for this object + public BoundingBox ClippingBox { + get { + return Value.GetBoundingBox (); + } + } + + /// + /// draw all wire and point previews + /// + public void DrawViewportWires (GH_PreviewWireArgs args) { + + } + + /// + /// draw all shaded meshes + /// + public void DrawViewportMeshes (GH_PreviewMeshArgs args) { + + if (Value == null) + return; + + if (args.Pipeline.SupportsShading) { + var c = args.Material.Diffuse; + c = System.Drawing.Color.FromArgb ((int) (args.Material.Transparency * 255), c); + + args.Pipeline.DrawMeshShaded (Value.Display, args.Material); + } + } +#endregion + + } +} \ No newline at end of file diff --git a/DendroGH/Properties/AssemblyInfo.cs b/DendroGH/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..5cddc1c --- /dev/null +++ b/DendroGH/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("DendroGH")] +[assembly: AssemblyDescription("volumetric modeling plugin for grasshopper")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("ecr labs")] +[assembly: AssemblyProduct("DendroGH")] +[assembly: AssemblyCopyright("Copyright © ecr labs 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("fc118761-1af4-4758-ae2a-52a725143e8f")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/DendroGH/Properties/Resources.Designer.cs b/DendroGH/Properties/Resources.Designer.cs new file mode 100644 index 0000000..38ea59b --- /dev/null +++ b/DendroGH/Properties/Resources.Designer.cs @@ -0,0 +1,233 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace DendroGH.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("DendroGH.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ico_bool_int { + get { + object obj = ResourceManager.GetObject("ico_bool_int", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ico_bool_sub { + get { + object obj = ResourceManager.GetObject("ico_bool_sub", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ico_bool_union { + get { + object obj = ResourceManager.GetObject("ico_bool_union", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ico_curve_vox { + get { + object obj = ResourceManager.GetObject("ico_curve_vox", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ico_io_in { + get { + object obj = ResourceManager.GetObject("ico_io_in", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ico_io_out { + get { + object obj = ResourceManager.GetObject("ico_io_out", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ico_mask { + get { + object obj = ResourceManager.GetObject("ico_mask", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ico_mesh_vox { + get { + object obj = ResourceManager.GetObject("ico_mesh_vox", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ico_morph { + get { + object obj = ResourceManager.GetObject("ico_morph", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ico_offset { + get { + object obj = ResourceManager.GetObject("ico_offset", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ico_param_mask { + get { + object obj = ResourceManager.GetObject("ico_param_mask", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ico_param_set { + get { + object obj = ResourceManager.GetObject("ico_param_set", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ico_param_vox { + get { + object obj = ResourceManager.GetObject("ico_param_vox", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ico_point_vox { + get { + object obj = ResourceManager.GetObject("ico_point_vox", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ico_settings { + get { + object obj = ResourceManager.GetObject("ico_settings", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ico_smooth { + get { + object obj = ResourceManager.GetObject("ico_smooth", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ico_vox_mesh { + get { + object obj = ResourceManager.GetObject("ico_vox_mesh", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/DendroGH/Properties/Resources.resx b/DendroGH/Properties/Resources.resx new file mode 100644 index 0000000..da5a1d1 --- /dev/null +++ b/DendroGH/Properties/Resources.resx @@ -0,0 +1,172 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\Resources\ico_bool_int.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\ico_bool_sub.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\ico_bool_union.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\ico_curve_vox.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\ico_io_in.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\ico_io_out.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\ico_mask.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\ico_mesh_vox.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\ico_morph.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\ico_offset.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\ico_param_mask.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\ico_param_set.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\ico_param_vox.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\ico_point_vox.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\ico_settings.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\ico_smooth.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\ico_vox_mesh.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/DendroGH/Resources/ico_bool_int.png b/DendroGH/Resources/ico_bool_int.png new file mode 100644 index 0000000..53b1d49 Binary files /dev/null and b/DendroGH/Resources/ico_bool_int.png differ diff --git a/DendroGH/Resources/ico_bool_sub.png b/DendroGH/Resources/ico_bool_sub.png new file mode 100644 index 0000000..408d623 Binary files /dev/null and b/DendroGH/Resources/ico_bool_sub.png differ diff --git a/DendroGH/Resources/ico_bool_union.png b/DendroGH/Resources/ico_bool_union.png new file mode 100644 index 0000000..307aaf9 Binary files /dev/null and b/DendroGH/Resources/ico_bool_union.png differ diff --git a/DendroGH/Resources/ico_curve_vox.png b/DendroGH/Resources/ico_curve_vox.png new file mode 100644 index 0000000..e691669 Binary files /dev/null and b/DendroGH/Resources/ico_curve_vox.png differ diff --git a/DendroGH/Resources/ico_io_in.png b/DendroGH/Resources/ico_io_in.png new file mode 100644 index 0000000..525de77 Binary files /dev/null and b/DendroGH/Resources/ico_io_in.png differ diff --git a/DendroGH/Resources/ico_io_out.png b/DendroGH/Resources/ico_io_out.png new file mode 100644 index 0000000..dc9b810 Binary files /dev/null and b/DendroGH/Resources/ico_io_out.png differ diff --git a/DendroGH/Resources/ico_mask.png b/DendroGH/Resources/ico_mask.png new file mode 100644 index 0000000..1d02ab1 Binary files /dev/null and b/DendroGH/Resources/ico_mask.png differ diff --git a/DendroGH/Resources/ico_mesh_vox.png b/DendroGH/Resources/ico_mesh_vox.png new file mode 100644 index 0000000..62094be Binary files /dev/null and b/DendroGH/Resources/ico_mesh_vox.png differ diff --git a/DendroGH/Resources/ico_morph.png b/DendroGH/Resources/ico_morph.png new file mode 100644 index 0000000..c282bee Binary files /dev/null and b/DendroGH/Resources/ico_morph.png differ diff --git a/DendroGH/Resources/ico_offset.png b/DendroGH/Resources/ico_offset.png new file mode 100644 index 0000000..d7f580d Binary files /dev/null and b/DendroGH/Resources/ico_offset.png differ diff --git a/DendroGH/Resources/ico_param_mask.png b/DendroGH/Resources/ico_param_mask.png new file mode 100644 index 0000000..06248bb Binary files /dev/null and b/DendroGH/Resources/ico_param_mask.png differ diff --git a/DendroGH/Resources/ico_param_set.png b/DendroGH/Resources/ico_param_set.png new file mode 100644 index 0000000..fe7bfac Binary files /dev/null and b/DendroGH/Resources/ico_param_set.png differ diff --git a/DendroGH/Resources/ico_param_vox.png b/DendroGH/Resources/ico_param_vox.png new file mode 100644 index 0000000..7e2e6ab Binary files /dev/null and b/DendroGH/Resources/ico_param_vox.png differ diff --git a/DendroGH/Resources/ico_point_vox.png b/DendroGH/Resources/ico_point_vox.png new file mode 100644 index 0000000..9a4a4c4 Binary files /dev/null and b/DendroGH/Resources/ico_point_vox.png differ diff --git a/DendroGH/Resources/ico_settings.png b/DendroGH/Resources/ico_settings.png new file mode 100644 index 0000000..f932c40 Binary files /dev/null and b/DendroGH/Resources/ico_settings.png differ diff --git a/DendroGH/Resources/ico_smooth.png b/DendroGH/Resources/ico_smooth.png new file mode 100644 index 0000000..6e21d0c Binary files /dev/null and b/DendroGH/Resources/ico_smooth.png differ diff --git a/DendroGH/Resources/ico_vox_mesh.png b/DendroGH/Resources/ico_vox_mesh.png new file mode 100644 index 0000000..c0272f1 Binary files /dev/null and b/DendroGH/Resources/ico_vox_mesh.png differ diff --git a/DendroGH/app.config b/DendroGH/app.config new file mode 100644 index 0000000..594b953 --- /dev/null +++ b/DendroGH/app.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/DendroGH/packages.config b/DendroGH/packages.config new file mode 100644 index 0000000..07f285b --- /dev/null +++ b/DendroGH/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/README.md b/README.md index cec2f38..05e8c28 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,42 @@ -# dendro -volumetric modeling for grasshopper built on top on openvdb +# Dendro +Dendro is a volumetric modeling plug-in for Grasshopper built on top of the OpenVDB library. It provides multiple ways to wrap points, curves, and meshes as a volumetric data within Grasshopper, allowing you to perform various operations on those volumes. Dendro includes components for boolean, smoothing, offsets, and morphing operations. You can find out more details of its features [here](https://www.ecrlabs.com/dendro) + +## Design + +We have been using the OpenVDB library for a couple years, but needed something to prototype quicker with. We had built a rough version of this for Grasshopper, but decided to package it up nicer and put a release together. Hopefully it is something to build upon and our hope was it could serve as a starting point to add more features and functionality to. + +The goal was to make Dendro integrate into Grasshopper as seamlessly as possible. Whereas many voxel solutions require you to think of geometry as living with a bounding box, Dendro makes working with volumes no different than handling any other geometry in Grasshopper. Dendro works with many native Grasshopper components, avoiding the 'blocking' found in other plugins, and allowing you to move in and out of volume operations very quickly. + +## Installation + +Dendro contains two projects, a C++ project for working with OpenVDB and a C# project creating the Grasshopper plugin. + +##### DendroAPI (C++) +OpenVDB has multiple dependencies... + +* blosc (v1.14.3) +* boost (v1.66.0) +* ilmbase (v2.2.1) +* openexr (v2.2.1) +* tbb (v2018.06.18) +* zlib (v1.2.11) + +All these dependencies are packaged on a private nuget server which should automatically be downloaded and installed when loading the solution. If that is not the case, make sure that the dendro private server (http://dendro-nuget.azurewebsites.net/nuget) is listed as a package source. that information can be found at `Tools` > `Options` > `Package Manager` > `Package Sources`. You might need to `Restore Nuget packages` and `Rescan Solution` if they weren't found initially. + +##### DendroGH (C#) +Since there are multiple versions of Rhino, each with their specific SDK, we added the Rhinocommon and Grasshopper libraries as a nuget package in order to let you specifically target your desired Rhino version. That can be changed by `Right-clicking the C# project`, then selecting `Manage Nuget Packages`, clicking the `Installed` tab, `Selecting` your desired package, and finally, changing the `Version` in the right panel. + +It is targeted for Rhino 5 by default because that seems to be more universal and forward compatible in Rhino 6. + +## Building + +Dendro was built using Microsoft Visual Studio 2017, but you should be able to re-target for other versions. It will also copy all necessary dependency dlls into the output folder to provide an easy reference for where dependency dlls can be found. + +## More Info + +Dendro was using OpenVDB. For more information on the library, please visit [here](http://www.openvdb.org/). + +## Contributors + +* [ecr labs](https://www.ecrlabs.com) +* [MachineHistories](http://www.machinehistories.com) \ No newline at end of file