virtual public void CutMesh() { Frame3f frameL = SceneTransforms.SceneToObject(target, cut_plane); Action <DMesh3> editF = (mesh) => { MeshPlaneCut cut = new MeshPlaneCut(mesh, frameL.Origin, frameL.Y); cut.Cut(); PlaneProjectionTarget planeTarget = new PlaneProjectionTarget() { Origin = frameL.Origin, Normal = frameL.Y }; if (GenerateFillSurface) { double min, max, avg; MeshQueries.EdgeLengthStats(mesh, out min, out max, out avg); cut.FillHoles(); MeshFaceSelection selection = new MeshFaceSelection(mesh); foreach (var tris in cut.LoopFillTriangles) { selection.Select(tris); } RegionRemesher.QuickRemesh(mesh, selection.ToArray(), 2 * avg, 1.0f, 25, planeTarget); MeshNormals normals = new MeshNormals(mesh); normals.Compute(); normals.CopyTo(mesh); } }; target.EditAndUpdateMesh(editF, GeometryEditTypes.ArbitraryEdit); }
/// <summary> /// compute offset meshes as simple extrusions /// </summary> void compute_offset_meshes_nosdf() { if (cached_inner_sdf_offset != inner_offset) { InnerOffsetMesh = new DMesh3(cachedInputMesh); MeshTransforms.FromFrame(InnerOffsetMesh, cachedInputsTransform); MeshNormals.QuickCompute(InnerOffsetMesh); MeshTransforms.VertexNormalOffset(InnerOffsetMesh, inner_offset); Reducer reducer = new Reducer(InnerOffsetMesh); reducer.ReduceToTriangleCount(5000); InnerOffsetMeshSpatial = new DMeshAABBTree3(InnerOffsetMesh, true); cached_inner_sdf_offset = inner_offset; } double max_offset = inner_offset + thickness; if (cached_outer_sdf_offset != max_offset) { OuterOffsetMesh = new DMesh3(cachedInputMesh); MeshTransforms.FromFrame(OuterOffsetMesh, cachedInputsTransform); MeshNormals.QuickCompute(OuterOffsetMesh); MeshTransforms.VertexNormalOffset(OuterOffsetMesh, max_offset); Reducer reducer = new Reducer(OuterOffsetMesh); reducer.ReduceToTriangleCount(5000); OuterOffsetMeshSpatial = new DMeshAABBTree3(OuterOffsetMesh, true); cached_outer_sdf_offset = max_offset; } //Util.WriteDebugMesh(MeshSource.GetIMesh(), "c:\\scratch\\__OFFESTS_orig.obj"); //Util.WriteDebugMesh(InnerOffsetMesh, "c:\\scratch\\__OFFESTS_inner.obj"); //Util.WriteDebugMesh(OuterOffsetMesh, "c:\\scratch\\__OFFESTS_outer.obj"); }
private static DMesh3 BooleanIntersection(DMesh3 mesh1, DMesh3 mesh2) { BoundedImplicitFunction3d meshA = meshToImplicitF(mesh1, 64, 0.2f); BoundedImplicitFunction3d meshB = meshToImplicitF(mesh2, 64, 0.2f); //take the intersection of the meshes minus the tools ImplicitIntersection3d mesh = new ImplicitIntersection3d() { A = meshA, B = meshB }; //calculate the boolean mesh MarchingCubes c = new MarchingCubes(); c.Implicit = mesh; c.RootMode = MarchingCubes.RootfindingModes.LerpSteps; c.RootModeSteps = 5; c.Bounds = mesh.Bounds(); c.CubeSize = c.Bounds.MaxDim / 128; c.Bounds.Expand(3 * c.CubeSize); c.Generate(); MeshNormals.QuickCompute(c.Mesh); int triangleCount = c.Mesh.TriangleCount / 2; Reducer r = new Reducer(c.Mesh); r.ReduceToTriangleCount(triangleCount); return(c.Mesh); }
protected override void SolveInstance(IGH_DataAccess DA) { List <DMesh3_goo> goo = new List <DMesh3_goo>(); int numCells = 64; DA.GetDataList(0, goo); DA.GetData(1, ref numCells); ImplicitNaryUnion3d diff2 = new ImplicitNaryUnion3d(); diff2.Children = goo.Select(x => g3ghUtil.MeshToImplicit(x.Value, numCells, 0.2f)).ToList(); g3.MarchingCubes c = new g3.MarchingCubes(); c.Implicit = diff2; c.RootMode = g3.MarchingCubes.RootfindingModes.Bisection; c.RootModeSteps = 5; c.Bounds = diff2.Bounds(); c.CubeSize = c.Bounds.MaxDim / numCells; c.Bounds.Expand(3 * c.CubeSize); c.Generate(); MeshNormals.QuickCompute(c.Mesh); DA.SetData(0, c.Mesh); }
void update_warp() { if (warp_dirty == false) { return; } DMesh3 mesh = PreviewSO.Mesh; foreach (int vid in mesh.VertexIndices()) { mesh.SetVertex(vid, VertexPositions[vid]); } Frame3f f = bendPlaneGizmoSO.GetLocalFrame(CoordSpace.SceneCoords); f = SceneTransforms.SceneToObject(PreviewSO, f); BendWarp warp = new BendWarp() { Mesh = mesh, BendPlane = f, BendAngle = bend_angle }; warp.Apply(); MeshNormals.QuickCompute(mesh); PreviewSO.NotifyMeshEdited(true); warp_dirty = false; }
private UnityMesh CreateMesh(List <Vector3d> lPath) { DMesh3 dMesh = meshGen.CreateMesh(lPath, qPoly.ToList(), tmpSeam); // Defer normal calculation if we reduce smoothing later. if (triangleReductionFactor > 1f) { dMesh.ReduceTriangles(triangleReductionFactor, !reduceSmoothing); } else if (!reduceSmoothing) { MeshNormals.QuickCompute(dMesh); } UnityMesh uMesh = dMesh.ToUnityMesh(); uMesh.seam = meshGen.Seam; // TODO if (reduceSmoothing) { uMesh.IncreaseVertexCount(smoothingThresholdAngle); } return(uMesh); }
public virtual void Update() { base.begin_update(); if (MeshSource == null) { throw new Exception("MeshDeformationOp: must set valid MeshSource to compute!"); } IMesh meshIn = MeshSource.GetIMesh(); DMesh3 mesh = new DMesh3(meshIn, MeshHints.None); MeshNormals.QuickCompute(mesh); foreach (int vid in mesh.VertexIndices()) { Vector3d v = mesh.GetVertex(vid); Vector3f n = mesh.GetVertexNormal(vid); Vector3d newPos = deformF(v, n, vid); mesh.SetVertex(vid, newPos); } MeshNormals.QuickCompute(mesh); DisplacedMesh = mesh; base.complete_update(); }
public override fMesh MakeGeometry(AxisGizmoFlags widget) { switch (widget) { case AxisGizmoFlags.AxisTranslateY: if (MyAxisTranslateY == null) { Radial3DArrowGenerator arrowGen = new Radial3DArrowGenerator() { HeadLength = 2.0f, TipRadius = 0.1f, StickLength = 1.5f, Clockwise = true }; DMesh3 mesh = arrowGen.Generate().MakeDMesh(); MeshNormals.QuickCompute(mesh); MeshTransforms.Translate(mesh, 0.5 * Vector3d.AxisY); DMesh3 flip = new DMesh3(mesh); MeshTransforms.Rotate(flip, Vector3d.Zero, Quaterniond.AxisAngleD(Vector3d.AxisX, 180)); MeshEditor.Append(mesh, flip); MyAxisTranslateY = new fMesh(mesh); } return(MyAxisTranslateY); default: return(null); } }
//experimental public List <DMesh3> SliceMold(DMesh3 mesh_to_slice, int number_of_slices) { var meshes = new List <MeshGeometry3D>(); //convert mesh to DMesh DMesh3 mesh = mesh_to_slice; //create cube for slicing double z_height = mesh.GetBounds().Max.z - mesh.GetBounds().Min.z; double slice_interval = (double)(z_height / number_of_slices); double x_size = mesh.GetBounds().Depth; double y_size = mesh.GetBounds().Width; double low_z = mesh.GetBounds().Min.z; //boolean intersection each mesh var sliced_meshes = new List <DMesh3>(); for (int i = 0; i < number_of_slices; i++) { //create box Vector3d centre = new Vector3d(0, 0, low_z + slice_interval / 2 + i * (slice_interval)); Vector3d extend = new Vector3d( x_size, y_size, slice_interval / 2); ImplicitBox3d box = new ImplicitBox3d() { Box = new Box3d(centre, extend) }; //boolean overlap BoundedImplicitFunction3d meshA = meshToImplicitF(mesh, 64, 0.2f); //take the difference of the bolus mesh minus the tools ImplicitIntersection3d mesh_result = new ImplicitIntersection3d { A = meshA, B = box }; //calculate the boolean mesh MarchingCubes c = new MarchingCubes(); c.Implicit = mesh_result; c.RootMode = MarchingCubes.RootfindingModes.LerpSteps; c.RootModeSteps = 5; c.Bounds = mesh_result.Bounds(); c.CubeSize = c.Bounds.MaxDim / 256; c.Bounds.Expand(3 * c.CubeSize); c.Generate(); MeshNormals.QuickCompute(c.Mesh); int triangleCount = c.Mesh.TriangleCount / 3; Reducer r = new Reducer(c.Mesh); r.ReduceToTriangleCount(triangleCount); sliced_meshes.Add(c.Mesh); } return(sliced_meshes); }
protected override void SolveInstance(IGH_DataAccess DA) { DMesh3_goo gooA = null; List <DMesh3_goo> gooB = new List <DMesh3_goo>(); int numCells = 64; DA.GetData(0, ref gooA); DA.GetDataList(1, gooB); DA.GetData(2, ref numCells); DMesh3 A = new DMesh3(gooA.Value); List <DMesh3> B = gooB.Select(x => x.Value).ToList(); ImplicitNaryDifference3d diff2 = new ImplicitNaryDifference3d(); diff2.A = g3ghUtil.MeshToImplicit(A, numCells, 0.2f); diff2.BSet = B.Select(x => g3ghUtil.MeshToImplicit(x, numCells, 0.2f)).ToList(); g3.MarchingCubes c = new g3.MarchingCubes(); c.Implicit = diff2; c.RootMode = g3.MarchingCubes.RootfindingModes.Bisection; c.RootModeSteps = 5; c.Bounds = diff2.Bounds(); c.CubeSize = c.Bounds.MaxDim / numCells; c.Bounds.Expand(3 * c.CubeSize); c.Generate(); MeshNormals.QuickCompute(c.Mesh); DA.SetData(0, c.Mesh); }
public DMesh3 BooleanUnion(DMesh3 mesh1, DMesh3 mesh2) { BoundedImplicitFunction3d meshA = meshToImplicitF(mesh1, 128, 0.2f); BoundedImplicitFunction3d meshB = meshToImplicitF(mesh2, 128, 0.2f); //take the difference of the bolus mesh minus the tools var mesh = new ImplicitUnion3d() { A = meshA, B = meshB }; //calculate the boolean mesh MarchingCubes c = new MarchingCubes(); c.Implicit = mesh; c.RootMode = MarchingCubes.RootfindingModes.LerpSteps; c.RootModeSteps = 5; c.Bounds = mesh.Bounds(); c.CubeSize = c.Bounds.MaxDim / 96; c.Bounds.Expand(3 * c.CubeSize); c.Generate(); MeshNormals.QuickCompute(c.Mesh); //int triangleCount = c.Mesh.TriangleCount / 2; //Reducer r = new Reducer(c.Mesh); //r.ReduceToTriangleCount(triangleCount); return(c.Mesh); }
// Use this for initialization void Start() { meshGO = GameObject.Find("sample_mesh"); Mesh unityMesh = meshGO.GetComponent <MeshFilter>().mesh; startMesh = g3UnityUtils.UnityMeshToDMesh(unityMesh); double height = startMesh.CachedBounds.Height; // find path to sample file if (LoadSampleMesh) { string curPath = Application.dataPath; string filePath = Path.Combine(curPath, Path.Combine("..\\sample_files", SampleFileName)); // load sample file, convert to unity coordinate system, translate and scale to origin startMesh = StandardMeshReader.ReadMesh(filePath); if (startMesh == null) { startMesh = new Sphere3Generator_NormalizedCube().Generate().MakeDMesh(); } if (FlipLeftRight) { MeshTransforms.FlipLeftRightCoordSystems(startMesh); } MeshTransforms.Scale(startMesh, height / startMesh.CachedBounds.Height); MeshTransforms.Translate(startMesh, -startMesh.CachedBounds.Center); MeshNormals.QuickCompute(startMesh); g3UnityUtils.SetGOMesh(meshGO, startMesh); } }
void compute_inner_wall() { if (DebugStep <= 0) { SocketMesh = new DMesh3(TrimmedMesh); return; } InnerMesh = new DMesh3(TrimmedMesh); // compute flare band Func <int, double> flareOffsetF = (vid) => { return(0); }; if (flare_offset > 0 && flare_band_width > 0) { MeshBoundaryLoops loops = new MeshBoundaryLoops(InnerMesh); if (loops.Count != 1) { goto done_inner_wall; } DijkstraGraphDistance dist = DijkstraGraphDistance.MeshVertices(InnerMesh); dist.TrackOrder = true; foreach (int vid in loops[0].Vertices) { dist.AddSeed(vid, 0); } dist.ComputeToMaxDistance(1.25f * (float)flare_band_width); flareOffsetF = (viD) => { float d = dist.GetDistance(viD); if (d < flare_band_width) { double t = d / flare_band_width; t = 1 - t * t; t = t * t * t; return(t * flare_offset); } return(0); }; } gParallel.ForEach(InnerMesh.VertexIndices(), (vid) => { Vector3d v = InnerMesh.GetVertex(vid); Vector3d n = InnerMesh.GetVertexNormal(vid); double offset = inner_offset + flareOffsetF(vid); InnerMesh.SetVertex(vid, v + offset * n); }); done_inner_wall: MeshNormals.QuickCompute(InnerMesh); }
public virtual void BakeDisplacements(DMeshSO so, VertexChangeBuilder changeBuilder) { so.EditAndUpdateMesh((mesh) => { foreach (int vid in ModifiedV) { changeBuilder.SetPosition(vid, Displacements[vid]); } gParallel.ForEach(ModifiedV, (vid) => { MeshNormals.QuickCompute(Mesh, vid); }); }, GeometryEditTypes.VertexDeformation); }
private DMesh3 GenerateMeshBase(BoundedImplicitFunction3d root, AxisAlignedBox3d filterBox) { MarchingCubes c = new MarchingCubes(); c.Implicit = root; c.RootMode = MarchingCubes.RootfindingModes.LerpSteps; // cube-edge convergence method c.RootModeSteps = 5; // number of iterations c.Bounds = filterBox; //_sideFilterBox; c.CubeSize = _cubeSize / 4.0; c.Generate(); MeshNormals.QuickCompute(c.Mesh); // generate normals return(c.Mesh); }
// generateMeshF() meshes the input implicit function at // the given cell resolution, and writes out the resulting mesh DMesh3 generatMeshF(BoundedImplicitFunction3d root, int numcells) { MarchingCubes c = new MarchingCubes(); c.Implicit = root; c.RootMode = MarchingCubes.RootfindingModes.LerpSteps; // cube-edge convergence method c.RootModeSteps = 5; // number of iterations c.Bounds = root.Bounds(); c.CubeSize = c.Bounds.MaxDim / numcells; c.Bounds.Expand(3 * c.CubeSize); // leave a buffer of cells c.Generate(); MeshNormals.QuickCompute(c.Mesh); // generate normals return(c.Mesh); // write mesh }
public override Task Rebuild() { this.DebugDepth("Rebuild"); return(Task.Run(() => { using (RebuildLock()) { using (new CenterAndHeightMaintainer(this)) { #if true ISdf shape = new Sphere() { Radius = Size }; if (Shape == Shapes.Box) { shape = new Box() { Size = new Vector3(Size, Size, Size) }; } var bounds = shape.Bounds; bounds.Expand(.1); if (Iterations > 7) { Iterations = 7; } var root = Octree.BuildOctree(shape.Sdf, bounds.MinXYZ, bounds.Size, Iterations, Threshold); Mesh = Octree.GenerateMeshFromOctree(root); #else var c = new MarchingCubes(); c.Generate(); MeshNormals.QuickCompute(c.Mesh); // generate normals Mesh = c.Mesh.ToMesh(); #endif } } Invalidate(InvalidateType.DisplayValues); Parent?.Invalidate(new InvalidateArgs(this, InvalidateType.Mesh)); return Task.CompletedTask; })); }
public static void test_normals() { // check that frames are ok DMesh3 mesh = TestUtil.LoadTestInputMesh("bunny_solid.obj"); foreach (int tid in mesh.TriangleIndices()) { Vector3f n = (Vector3f)mesh.GetTriNormal(tid); for (int j = 0; j < 3; ++j) { Frame3f f = mesh.GetTriFrame(tid, j); if (Math.Abs(f.X.Dot(f.Y)) > MathUtil.ZeroTolerancef || Math.Abs(f.X.Dot(f.Z)) > MathUtil.ZeroTolerancef || Math.Abs(f.Y.Dot(f.Z)) > MathUtil.ZeroTolerancef) { throw new Exception("argh"); } Vector3f fn = f.Z; if (fn.Dot(n) < 0.99) { throw new Exception("shit"); } } } MeshNormals.QuickCompute(mesh); foreach (int vid in mesh.VertexIndices()) { Vector3f n = mesh.GetVertexNormal(vid); for (int j = 1; j <= 2; ++j) { Frame3f f = mesh.GetVertexFrame(vid, (j == 1) ? true : false); Vector3f fn = f.GetAxis(j); if (Math.Abs(f.X.Dot(f.Y)) > MathUtil.ZeroTolerancef || Math.Abs(f.X.Dot(f.Z)) > MathUtil.ZeroTolerancef || Math.Abs(f.Y.Dot(f.Z)) > MathUtil.ZeroTolerancef) { throw new Exception("argh"); } if (fn.Dot(n) < 0.99) { throw new Exception("shit2"); } } } }
public static DMesh3 GenerateMeshF(BoundedImplicitFunction3d mesh, int num_cells) { MarchingCubes c = new MarchingCubes(); c.Implicit = mesh; c.RootMode = MarchingCubes.RootfindingModes.LerpSteps; // cube-edge convergence method c.RootModeSteps = 5; // number of iterations c.Bounds = mesh.Bounds(); c.CubeSize = c.Bounds.MaxDim / num_cells; c.Bounds.Expand(3 * c.CubeSize); // leave a buffer of cells c.Generate(); MeshNormals.QuickCompute(c.Mesh); // generate normals DMesh3 outputMesh = c.Mesh; return(outputMesh); }
protected override void on_curve_validated() { if (previewGO != null) { RemoveGO((fGameObject)previewGO); previewGO.Destroy(); } if (EnableRegionOverlay) { if (TargetModelSO == null) { throw new InvalidOperationException("EnclosedPatchSO.on_curve_validated: curve is not connected to a Target"); } if (TransformMode != OutputCurveTransform.ToTargetSO) { throw new InvalidOperationException("EnclosedPatchSO.on_curve_validated: curve is not transformed to TargetSO"); } DCurve3 target_curve = RequestCurveCopyFromMainThread(); MeshFacesFromLoop loop = new MeshFacesFromLoop(TargetModel.SourceMesh, target_curve, TargetModel.SourceSpatial); MeshFaceSelection face_selection = loop.ToSelection(); DSubmesh3 submesh = new DSubmesh3(TargetModel.SourceMesh, face_selection, face_selection.Count); MeshNormals normals = new MeshNormals(submesh.SubMesh); normals.Compute(); foreach (int vid in submesh.SubMesh.VertexIndices()) { Vector3d n = normals.Normals[vid]; Vector3d v = submesh.SubMesh.GetVertex(vid); v += 0.1 * n; v = SceneTransforms.TransformTo(v, TargetModelSO, this); submesh.SubMesh.SetVertex(vid, v); } previewGO = GameObjectFactory.CreateMeshGO("patch", new fMesh(submesh.SubMesh), false, true); previewGO.SetMaterial(previewMaterial, true); previewGO.SetLayer(FPlatform.WidgetOverlayLayer); previewGO.SetIgnoreMaterialChanges(); AppendNewGO(previewGO, root, false); } }
protected override void Recompute(DGArguments args) { OffsetMesh.Copy(CachedValue <DMesh3>(0, args)); double dist = CachedValue <double>(1, args); if (!OffsetMesh.HasVertexNormals) { MeshNormals.QuickCompute(OffsetMesh); } foreach (int vid in OffsetMesh.VertexIndices()) { Vector3d v = OffsetMesh.GetVertex(vid); Vector3d n = OffsetMesh.GetVertexNormal(vid); v += dist * n; OffsetMesh.SetVertex(vid, v); } }
public bool Compute() { DMesh3 copy = new DMesh3(Mesh); //Frame3f PlaneO = SceneTransforms.SceneToObject(TargetSO, PlaneS); Vector3f PlaneNormal = Plane.GetAxis(nPlaneAxis); MeshPlaneCut cut = new MeshPlaneCut(copy, Plane.Origin, PlaneNormal); cut.Cut(); Loops = new DCurve3[cut.CutLoops.Count]; for (int li = 0; li < cut.CutLoops.Count; ++li) { EdgeLoop edgeloop = cut.CutLoops[li]; DCurve3 loop = MeshUtil.ExtractLoopV(copy, edgeloop.Vertices); // [TODO] collapse degenerate points... if (NormalOffset > 0) { for (int i = 0; i < loop.VertexCount; ++i) { Vector3f n = Vector3f.Zero; if (copy.HasVertexNormals) { n = (Vector3f)copy.GetVertexNormal(edgeloop.Vertices[i]); } else { n = (Vector3f)MeshNormals.QuickCompute(Mesh, edgeloop.Vertices[i]); } n -= n.Dot(PlaneNormal) * PlaneNormal; n.Normalize(); loop[i] += NormalOffset * (Vector3d)n; } } Loops[li] = loop; } return(Loops.Length > 0); }
void MeshReplace() { Mesh newMesh = new Mesh(); //The triangles tend to come out reversed, so we need to fix them DMesh3 dmesh3 = DMesh3Builder.Build <float, int, float>(verticies, faces); MeshNormals.QuickCompute(dmesh3); dmesh3.ReverseOrientation(false); newMesh.vertices = verticies.ToVectors().ToArray(); newMesh.triangles = dmesh3.TrianglesBuffer.ToArray(); for (int i = 0; i < mesh.uv.Length; i++) { newMesh.uv[i] = mesh.uv[i]; } newMesh.MarkDynamic(); GetComponent <MeshFilter>().mesh = newMesh; }
private static DMesh3 GenerateMeshF(BoundedImplicitFunction3d root, int numcells) { var bounds = root.Bounds(); var c = new MarchingCubes() { Implicit = root, RootMode = MarchingCubes.RootfindingModes.LerpSteps, // cube-edge convergence method RootModeSteps = 5, // number of iterations Bounds = bounds, CubeSize = bounds.MaxDim / numcells, }; c.Bounds.Expand(3 * c.CubeSize); // leave a buffer of cells c.Generate(); MeshNormals.QuickCompute(c.Mesh); // generate normals return(c.Mesh); }
public static void TestMarchingCubes() { MarchingCubes mc = new MarchingCubes(); LocalProfiler p = new LocalProfiler(); p.Start("GENERATE"); mc.ParallelCompute = true; mc.Generate(); p.Stop("GENERATE"); DebugUtil.Log(2, p.AllTimes()); MeshNormals.QuickCompute(mc.Mesh); DebugUtil.WriteDebugMesh(mc.Mesh, "c:\\scratch\\MARCHING_CUBES.obj"); DMeshSO meshSO = new DMeshSO(); meshSO.Create(mc.Mesh, CC.ActiveScene.DefaultMeshSOMaterial); CC.ActiveScene.AddSceneObject(meshSO, false); }
public static DMesh3 ReduceTriangles(this DMesh3 dMesh, int triangleCount, bool computeNormals = true, bool fixAllBoundaryEdges = true) { Reducer reducer = new Reducer(dMesh); if (fixAllBoundaryEdges) { reducer.SetExternalConstraints(meshConstraints); MeshConstraintUtil.FixAllBoundaryEdges(reducer.Constraints, dMesh); } reducer.ReduceToTriangleCount(triangleCount); if (computeNormals) { MeshNormals.QuickCompute(dMesh); } return(dMesh); }
protected override void SolveInstance(IGH_DataAccess DA) { DMesh3_goo goo = null; DA.GetData(0, ref goo); DMesh3 mesh = new DMesh3(goo.Value); List <Rhino.Geometry.Vector3d> vecs = new List <Rhino.Geometry.Vector3d>(); if (!mesh.HasVertexNormals) { var normals = new MeshNormals(mesh); normals.Compute(); } foreach (var ind in mesh.VertexIndices()) { vecs.Add(mesh.GetVertexNormal(ind).ToRhinoVec()); } DA.SetDataList(0, vecs); }
public static void test_marching_cubes() { MarchingCubes c = new MarchingCubes(); LocalProfiler profiler = new LocalProfiler(); profiler.Start("Generate"); c.ParallelCompute = true; c.Generate(); profiler.Stop("Generate"); System.Console.WriteLine("Tris: {0} Times: {1}", c.Mesh.TriangleCount, profiler.AllTimes()); Reducer r = new Reducer(c.Mesh); r.ReduceToEdgeLength(c.CubeSize * 0.25); System.Console.WriteLine("after reduce: {0}", c.Mesh.TriangleCount); MeshNormals.QuickCompute(c.Mesh); TestUtil.WriteTestOutputMesh(c.Mesh, "marching_cubes.obj"); }
public virtual bool Apply() { DMesh3 testAgainstMesh = Mesh; if (InsideMode == CalculationMode.RayParity) { MeshBoundaryLoops loops = new MeshBoundaryLoops(testAgainstMesh); if (loops.Count > 0) { testAgainstMesh = new DMesh3(Mesh); foreach (var loop in loops) { if (Cancelled()) { return(false); } SimpleHoleFiller filler = new SimpleHoleFiller(testAgainstMesh, loop); filler.Fill(); } } } DMeshAABBTree3 spatial = (Spatial != null && testAgainstMesh == Mesh) ? Spatial : new DMeshAABBTree3(testAgainstMesh, true); if (InsideMode == CalculationMode.AnalyticWindingNumber) { spatial.WindingNumber(Vector3d.Zero); } else if (InsideMode == CalculationMode.FastWindingNumber) { spatial.FastWindingNumber(Vector3d.Zero); } if (Cancelled()) { return(false); } // ray directions List <Vector3d> ray_dirs = null; int NR = 0; if (InsideMode == CalculationMode.SimpleOcclusionTest) { ray_dirs = new List <Vector3d>(); ray_dirs.Add(Vector3d.AxisX); ray_dirs.Add(-Vector3d.AxisX); ray_dirs.Add(Vector3d.AxisY); ray_dirs.Add(-Vector3d.AxisY); ray_dirs.Add(Vector3d.AxisZ); ray_dirs.Add(-Vector3d.AxisZ); NR = ray_dirs.Count; } Func <Vector3d, bool> isOccludedF = (pt) => { if (InsideMode == CalculationMode.RayParity) { return(spatial.IsInside(pt)); } else if (InsideMode == CalculationMode.AnalyticWindingNumber) { return(spatial.WindingNumber(pt) > WindingIsoValue); } else if (InsideMode == CalculationMode.FastWindingNumber) { return(spatial.FastWindingNumber(pt) > WindingIsoValue); } else { for (int k = 0; k < NR; ++k) { int hit_tid = spatial.FindNearestHitTriangle(new Ray3d(pt, ray_dirs[k])); if (hit_tid == DMesh3.InvalidID) { return(false); } } return(true); } }; bool cancel = false; BitArray vertices = null; if (PerVertex) { vertices = new BitArray(Mesh.MaxVertexID); MeshNormals normals = null; if (Mesh.HasVertexNormals == false) { normals = new MeshNormals(Mesh); normals.Compute(); } gParallel.ForEach(Mesh.VertexIndices(), (vid) => { if (cancel) { return; } if (vid % 10 == 0) { cancel = Cancelled(); } Vector3d c = Mesh.GetVertex(vid); Vector3d n = (normals == null) ? Mesh.GetVertexNormal(vid) : normals[vid]; c += n * NormalOffset; vertices[vid] = isOccludedF(c); }); } if (Cancelled()) { return(false); } RemovedT = new List <int>(); SpinLock removeLock = new SpinLock(); gParallel.ForEach(Mesh.TriangleIndices(), (tid) => { if (cancel) { return; } if (tid % 10 == 0) { cancel = Cancelled(); } bool inside = false; if (PerVertex) { Index3i tri = Mesh.GetTriangle(tid); inside = vertices[tri.a] || vertices[tri.b] || vertices[tri.c]; } else { Vector3d c = Mesh.GetTriCentroid(tid); Vector3d n = Mesh.GetTriNormal(tid); c += n * NormalOffset; inside = isOccludedF(c); } if (inside) { bool taken = false; removeLock.Enter(ref taken); RemovedT.Add(tid); removeLock.Exit(); } }); if (Cancelled()) { return(false); } if (RemovedT.Count > 0) { MeshEditor editor = new MeshEditor(Mesh); bool bOK = editor.RemoveTriangles(RemovedT, true); RemoveFailed = (bOK == false); } return(true); }
public static void test_marching_cubes_demos() { // generateMeshF() meshes the input implicit function at // the given cell resolution, and writes out the resulting mesh Action <BoundedImplicitFunction3d, int, string> generateMeshF = (root, numcells, path) => { MarchingCubes c = new MarchingCubes(); c.Implicit = root; c.RootMode = MarchingCubes.RootfindingModes.LerpSteps; // cube-edge convergence method c.RootModeSteps = 5; // number of iterations c.Bounds = root.Bounds(); c.CubeSize = c.Bounds.MaxDim / numcells; c.Bounds.Expand(3 * c.CubeSize); // leave a buffer of cells c.Generate(); MeshNormals.QuickCompute(c.Mesh); // generate normals StandardMeshWriter.WriteMesh(path, c.Mesh, WriteOptions.Defaults); // write mesh }; // meshToImplicitF() generates a narrow-band distance-field and // returns it as an implicit surface, that can be combined with other implicits Func <DMesh3, int, double, BoundedImplicitFunction3d> meshToImplicitF = (meshIn, numcells, max_offset) => { double meshCellsize = meshIn.CachedBounds.MaxDim / numcells; MeshSignedDistanceGrid levelSet = new MeshSignedDistanceGrid(meshIn, meshCellsize); levelSet.ExactBandWidth = (int)(max_offset / meshCellsize) + 1; levelSet.Compute(); return(new DenseGridTrilinearImplicit(levelSet.Grid, levelSet.GridOrigin, levelSet.CellSize)); }; // meshToBlendImplicitF() computes the full distance-field grid for the input // mesh. The bounds are expanded quite a bit to allow for blending, // probably more than necessary in most cases Func <DMesh3, int, BoundedImplicitFunction3d> meshToBlendImplicitF = (meshIn, numcells) => { double meshCellsize = meshIn.CachedBounds.MaxDim / numcells; MeshSignedDistanceGrid levelSet = new MeshSignedDistanceGrid(meshIn, meshCellsize); levelSet.ExpandBounds = meshIn.CachedBounds.Diagonal * 0.25; // need some values outside mesh levelSet.ComputeMode = MeshSignedDistanceGrid.ComputeModes.FullGrid; levelSet.Compute(); return(new DenseGridTrilinearImplicit(levelSet.Grid, levelSet.GridOrigin, levelSet.CellSize)); }; // generate union/difference/intersection of sphere and cube ImplicitSphere3d sphere = new ImplicitSphere3d() { Origin = Vector3d.Zero, Radius = 1.0 }; ImplicitBox3d box = new ImplicitBox3d() { Box = new Box3d(new Frame3f(Vector3f.AxisX), 0.5 * Vector3d.One) }; generateMeshF(new ImplicitUnion3d() { A = sphere, B = box }, 128, "c:\\demo\\union.obj"); generateMeshF(new ImplicitDifference3d() { A = sphere, B = box }, 128, "c:\\demo\\difference.obj"); generateMeshF(new ImplicitIntersection3d() { A = sphere, B = box }, 128, "c:\\demo\\intersection.obj"); // generate bunny offset surfaces //double offset = 0.2f; //DMesh3 mesh = TestUtil.LoadTestInputMesh("bunny_solid.obj"); //MeshTransforms.Scale(mesh, 3.0 / mesh.CachedBounds.MaxDim); //BoundedImplicitFunction3d meshImplicit = meshToImplicitF(mesh, 64, offset); //generateMeshF(meshImplicit, 128, "c:\\demo\\mesh.obj"); //generateMeshF(new ImplicitOffset3d() { A = meshImplicit, Offset = offset }, 128, "c:\\demo\\mesh_outset.obj"); //generateMeshF(new ImplicitOffset3d() { A = meshImplicit, Offset = -offset }, 128, "c:\\demo\\mesh_inset.obj"); // compare offset of sharp and smooth union //var smooth_union = new ImplicitSmoothDifference3d() { A = sphere, B = box }; //generateMeshF(smooth_union, 128, "c:\\demo\\smooth_union.obj"); //generateMeshF(new ImplicitOffset3d() { A = smooth_union, Offset = 0.2 }, 128, "c:\\demo\\smooth_union_offset.obj"); //var union = new ImplicitUnion3d() { A = sphere, B = box }; //generateMeshF(new ImplicitOffset3d() { A = union, Offset = offset }, 128, "c:\\demo\\union_offset.obj"); // blending //ImplicitSphere3d sphere1 = new ImplicitSphere3d() { // Origin = Vector3d.Zero, Radius = 1.0 //}; //ImplicitSphere3d sphere2 = new ImplicitSphere3d() { // Origin = 1.5 * Vector3d.AxisX, Radius = 1.0 //}; //generateMeshF(new ImplicitBlend3d() { A = sphere1, B = sphere2, Blend = 1.0 }, 128, "c:\\demo\\blend_1.obj"); //generateMeshF(new ImplicitBlend3d() { A = sphere1, B = sphere2, Blend = 4.0 }, 128, "c:\\demo\\blend_4.obj"); //generateMeshF(new ImplicitBlend3d() { A = sphere1, B = sphere2, Blend = 16.0 }, 128, "c:\\demo\\blend_16.obj"); //generateMeshF(new ImplicitBlend3d() { A = sphere1, B = sphere2, Blend = 64.0 }, 128, "c:\\demo\\blend_64.obj"); //sphere1.Radius = sphere2.Radius = 2.0f; //sphere2.Origin = 1.5 * sphere1.Radius * Vector3d.AxisX; //generateMeshF(new ImplicitBlend3d() { A = sphere1, B = sphere2, Blend = 1.0 }, 128, "c:\\demo\\blend_2x_1.obj"); //generateMeshF(new ImplicitBlend3d() { A = sphere1, B = sphere2, Blend = 4.0 }, 128, "c:\\demo\\blend_2x_4.obj"); //generateMeshF(new ImplicitBlend3d() { A = sphere1, B = sphere2, Blend = 16.0 }, 128, "c:\\demo\\blend_2x_16.obj"); //generateMeshF(new ImplicitBlend3d() { A = sphere1, B = sphere2, Blend = 64.0 }, 128, "c:\\demo\\blend_2x_64.obj"); // mesh blending //DMesh3 mesh1 = TestUtil.LoadTestInputMesh("bunny_solid.obj"); //MeshTransforms.Scale(mesh1, 3.0 / mesh1.CachedBounds.MaxDim); //DMesh3 mesh2 = new DMesh3(mesh1); //MeshTransforms.Rotate(mesh2, mesh2.CachedBounds.Center, Quaternionf.AxisAngleD(Vector3f.OneNormalized, 45.0f)); //var meshImplicit1 = meshToImplicitF(mesh1, 64, 0); //var meshImplicit2 = meshToImplicitF(mesh2, 64, 0); //generateMeshF(new ImplicitBlend3d() { A = meshImplicit1, B = meshImplicit2, Blend = 0.0 }, 256, "c:\\demo\\blend_mesh_union.obj"); //generateMeshF(new ImplicitBlend3d() { A = meshImplicit1, B = meshImplicit2, Blend = 10.0 }, 256, "c:\\demo\\blend_mesh_bad.obj"); //var meshFullImplicit1 = meshToBlendImplicitF(mesh1, 64); //var meshFullImplicit2 = meshToBlendImplicitF(mesh2, 64); //generateMeshF(new ImplicitBlend3d() { A = meshFullImplicit1, B = meshFullImplicit2, Blend = 0.0 }, 256, "c:\\demo\\blend_mesh_union.obj"); //generateMeshF(new ImplicitBlend3d() { A = meshFullImplicit1, B = meshFullImplicit2, Blend = 1.0 }, 256, "c:\\demo\\blend_mesh_1.obj"); //generateMeshF(new ImplicitBlend3d() { A = meshFullImplicit1, B = meshFullImplicit2, Blend = 10.0 }, 256, "c:\\demo\\blend_mesh_10.obj"); //generateMeshF(new ImplicitBlend3d() { A = meshFullImplicit1, B = meshFullImplicit2, Blend = 50.0 }, 256, "c:\\demo\\blend_mesh_100.obj"); //DMesh3 mesh = TestUtil.LoadTestInputMesh("bunny_solid.obj"); //MeshTransforms.Scale(mesh, 3.0 / mesh.CachedBounds.MaxDim); //MeshTransforms.Translate(mesh, -mesh.CachedBounds.Center); //Reducer r = new Reducer(mesh); //r.ReduceToTriangleCount(100); //double radius = 0.1; //List<BoundedImplicitFunction3d> Lines = new List<BoundedImplicitFunction3d>(); //foreach (Index4i edge_info in mesh.Edges()) { // var segment = new Segment3d(mesh.GetVertex(edge_info.a), mesh.GetVertex(edge_info.b)); // Lines.Add(new ImplicitLine3d() { Segment = segment, Radius = radius }); //} //ImplicitNaryUnion3d unionN = new ImplicitNaryUnion3d() { Children = Lines }; //generateMeshF(unionN, 128, "c:\\demo\\mesh_edges.obj"); //radius = 0.05; //List<BoundedImplicitFunction3d> Elements = new List<BoundedImplicitFunction3d>(); //foreach (int eid in mesh.EdgeIndices()) { // var segment = new Segment3d(mesh.GetEdgePoint(eid, 0), mesh.GetEdgePoint(eid, 1)); // Elements.Add(new ImplicitLine3d() { Segment = segment, Radius = radius }); //} //foreach (Vector3d v in mesh.Vertices()) // Elements.Add(new ImplicitSphere3d() { Origin = v, Radius = 2 * radius }); //generateMeshF(new ImplicitNaryUnion3d() { Children = Elements }, 256, "c:\\demo\\mesh_edges_and_vertices.obj"); //double lattice_radius = 0.05; //double lattice_spacing = 0.4; //double shell_thickness = 0.05; //int mesh_resolution = 64; // set to 256 for image quality //var shellMeshImplicit = meshToImplicitF(mesh, 128, shell_thickness); //double max_dim = mesh.CachedBounds.MaxDim; //AxisAlignedBox3d bounds = new AxisAlignedBox3d(mesh.CachedBounds.Center, max_dim / 2); //bounds.Expand(2 * lattice_spacing); //AxisAlignedBox2d element = new AxisAlignedBox2d(lattice_spacing); //AxisAlignedBox2d bounds_xy = new AxisAlignedBox2d(bounds.Min.xy, bounds.Max.xy); //AxisAlignedBox2d bounds_xz = new AxisAlignedBox2d(bounds.Min.xz, bounds.Max.xz); //AxisAlignedBox2d bounds_yz = new AxisAlignedBox2d(bounds.Min.yz, bounds.Max.yz); //List<BoundedImplicitFunction3d> Tiling = new List<BoundedImplicitFunction3d>(); //foreach (Vector2d uv in TilingUtil.BoundedRegularTiling2(element, bounds_xy, 0)) { // Segment3d seg = new Segment3d(new Vector3d(uv.x, uv.y, bounds.Min.z), new Vector3d(uv.x, uv.y, bounds.Max.z)); // Tiling.Add(new ImplicitLine3d() { Segment = seg, Radius = lattice_radius }); //} //foreach (Vector2d uv in TilingUtil.BoundedRegularTiling2(element, bounds_xz, 0)) { // Segment3d seg = new Segment3d(new Vector3d(uv.x, bounds.Min.y, uv.y), new Vector3d(uv.x, bounds.Max.y, uv.y)); // Tiling.Add(new ImplicitLine3d() { Segment = seg, Radius = lattice_radius }); //} //foreach (Vector2d uv in TilingUtil.BoundedRegularTiling2(element, bounds_yz, 0)) { // Segment3d seg = new Segment3d(new Vector3d(bounds.Min.x, uv.x, uv.y), new Vector3d(bounds.Max.x, uv.x, uv.y)); // Tiling.Add(new ImplicitLine3d() { Segment = seg, Radius = lattice_radius }); //} //ImplicitNaryUnion3d lattice = new ImplicitNaryUnion3d() { Children = Tiling }; //generateMeshF(lattice, 128, "c:\\demo\\lattice.obj"); //ImplicitIntersection3d lattice_clipped = new ImplicitIntersection3d() { A = lattice, B = shellMeshImplicit }; //generateMeshF(lattice_clipped, mesh_resolution, "c:\\demo\\lattice_clipped.obj"); //var shell = new ImplicitDifference3d() { // A = shellMeshImplicit, B = new ImplicitOffset3d() { A = shellMeshImplicit, Offset = -shell_thickness } //}; //var shell_cut = new ImplicitDifference3d() { // A = shell, B = new ImplicitAxisAlignedBox3d() { AABox = new AxisAlignedBox3d(Vector3d.Zero, max_dim / 2, 0.4, max_dim / 2) } //}; //generateMeshF(new ImplicitUnion3d() { A = lattice_clipped, B = shell_cut }, mesh_resolution, "c:\\demo\\lattice_result.obj"); }