/// <summary> /// Returns the height of the ground at the given 2D position via /// out. Returns false if there is no ground at the position. /// </summary> /// <remarks> /// Only X and Z are used by this function. /// </remarks> /// <param name="pos"></param> /// <returns></returns> public bool TryGetHeightAt(Position pos, out float height) { if (_spatial == null) { height = -1; return(false); } var origin = new Vector3f(pos.X, 1000, pos.Z); var ray = new Ray3f(origin, new Vector3f(0, -1, 0)); var hitId = _spatial.FindNearestHitTriangle(ray); if (hitId == DMesh3.InvalidID) { height = float.NaN; return(false); } var intersection = MeshQueries.TriangleIntersection(_mesh, hitId, ray); var hitDistance = origin.Distance(ray.PointAt((float)intersection.RayParameter)); height = (1000 - hitDistance); return(true); }
public static void test_basic_closed_reduce() { //DMesh3 mesh = TestUtil.MakeCappedCylinder(false); //DMesh3 mesh = TestUtil.LoadTestInputMesh("sphere_bowtie_groups.obj"); DMesh3 mesh = TestUtil.LoadTestInputMesh("bunny_solid.obj"); //MeshUtil.ScaleMesh(mesh, Frame3f.Identity, new Vector3f(1,2,1)); //DMesh3 mesh = TestUtil.MakeOpenCylinder(false); mesh.CheckValidity(); if (WriteDebugMeshes) { TestUtil.WriteTestOutputMesh(mesh, "basic_closed_reduce_before.obj"); } Reducer r = new Reducer(mesh); DMeshAABBTree3 tree = new DMeshAABBTree3(new DMesh3(mesh)); tree.Build(); //r.SetProjectionTarget(new MeshProjectionTarget() { Mesh = tree.Mesh, Spatial = tree }); r.ReduceToTriangleCount(3000); //r.ReduceToEdgeLength(2.0); double mine, maxe, avge; MeshQueries.EdgeLengthStats(mesh, out mine, out maxe, out avge); System.Console.WriteLine("Edge length stats: {0} {1} {2}", mine, maxe, avge); if (WriteDebugMeshes) { TestUtil.WriteTestOutputMesh(mesh, "basic_closed_reduce_after.obj"); } }
public void Initialize_AutoFitBox() { DMeshSO TargetMeshSO = TargetSO as DMeshSO; // initialize w/ auto-fit box DMesh3 mesh = TargetMeshSO.Mesh; DMeshAABBTree3 spatial = TargetMeshSO.Spatial; meshBounds = mesh.CachedBounds; create_preview_so(); ContOrientedBox3 boxFitter = new ContOrientedBox3( new RemapItr <Vector3d, int>(mesh.TriangleIndices(), (tid) => { return(mesh.GetTriCentroid(tid)); }), new RemapItr <double, int>(mesh.TriangleIndices(), (tid) => { return(mesh.GetTriArea(tid)); })); //DebugUtil.EmitDebugBox("fitbox", boxFitter.Box, Colorf.Red, TargetSO.RootGameObject, false); Box3d fitBox = boxFitter.Box; int longest = 0; if (fitBox.Extent.y > fitBox.Extent.x) { longest = 1; } if (fitBox.Extent.z > fitBox.Extent[longest]) { longest = 2; } Vector3d vTop = fitBox.Center + fitBox.Extent[longest] * fitBox.Axis(longest); Vector3d vBottom = fitBox.Center - fitBox.Extent[longest] * fitBox.Axis(longest); int base_tid = spatial.FindNearestTriangle(vBottom); int top_tid = spatial.FindNearestTriangle(vTop); if (vTop.y < vBottom.y) { int tmp = base_tid; base_tid = top_tid; top_tid = tmp; } Vector3d vBasePt = mesh.GetTriCentroid(base_tid); Vector3d vTopPt = mesh.GetTriCentroid(top_tid); int other1 = (longest + 1) % 3, other2 = (longest + 2) % 3; int front_tid = spatial.FindNearestHitTriangle(new Ray3d(fitBox.Center, fitBox.Axis(other1))); Vector3d vFrontPt = mesh.GetTriCentroid(front_tid); int back_tid = spatial.FindNearestHitTriangle(new Ray3d(fitBox.Center, -fitBox.Axis(other1))); Vector3d vBackPt = mesh.GetTriCentroid(back_tid); int right_tid = spatial.FindNearestHitTriangle(new Ray3d(fitBox.Center, fitBox.Axis(other2))); Vector3d vRightPt = mesh.GetTriCentroid(right_tid); int left_tid = spatial.FindNearestHitTriangle(new Ray3d(fitBox.Center, -fitBox.Axis(other2))); Vector3d vLeftPt = mesh.GetTriCentroid(left_tid); initialFrontPt = (Vector3f)vFrontPt; SetPointPosition_Internal(BasePointID, MeshQueries.SurfaceFrame(mesh, base_tid, vBasePt), CoordSpace.ObjectCoords); SetPointPosition_Internal(FrontPointID, MeshQueries.SurfaceFrame(mesh, front_tid, vFrontPt), CoordSpace.ObjectCoords); SetPointPosition(TopPointID, MeshQueries.SurfaceFrame(mesh, top_tid, vTopPt), CoordSpace.ObjectCoords); }
public bool FindHitTriangle(Ray3f sceneRay, bool snap_to_center, ref Frame3f hitFrameS, ref int hitTID) { Ray3f objRay = SceneTransforms.SceneToObject(Target, sceneRay); hitTID = PreviewSpatial.FindNearestHitTriangle(objRay); if (hitTID == DMesh3.InvalidID) { return(false); } if (allow_backface_hits == false && is_back_facing(hitTID)) { return(false); } var intr = MeshQueries.TriangleIntersection(PreviewMesh, hitTID, objRay); if (snap_to_center) { Frame3f hitFrameL = new Frame3f(PreviewMesh.GetTriCentroid(hitTID), PreviewMesh.GetTriNormal(hitTID)); hitFrameS = SceneTransforms.ObjectToScene(previewSO, hitFrameL); } else { Vector3f hitPoint = objRay.PointAt((float)intr.RayParameter); Frame3f hitFrameL = new Frame3f(hitPoint, PreviewMesh.GetTriNormal(hitTID)); hitFrameS = SceneTransforms.ObjectToScene(previewSO, hitFrameL); } return(true); }
public static void test_planar_fill() { //DMesh3 mesh = TestUtil.LoadTestInputMesh("bunny_solid.obj"); //DMesh3 mesh = TestUtil.LoadTestInputMesh("bunny_hollow.obj"); DMesh3 mesh = TestUtil.LoadTestInputMesh("local\\__LAST_FAILED_CUT_MESH.obj"); double mine, maxe, avge; MeshQueries.EdgeLengthStats(mesh, out mine, out maxe, out avge); AxisAlignedBox3d bounds = mesh.CachedBounds; Vector3d origin = bounds.Center; Vector3d axis = Vector3d.AxisY; double targetLen = avge; origin = new Vector3d(-7.53203300, -39.50826000, -4.22260500); axis = new Vector3d(0.00000007, 0.00000007, -0.99999960); targetLen = 3.0; MeshPlaneCut cut = new MeshPlaneCut(mesh, origin, axis); cut.Cut(); PlanarHoleFiller fill = new PlanarHoleFiller(cut) { FillTargetEdgeLen = targetLen }; if (fill.Fill() == false) { System.Console.WriteLine("test_meshEdits.test_planar_fill: Fill() failed!"); } TestUtil.WriteTestOutputMesh(mesh, "planar_filled.obj"); }
public Vector3D Project(Vector3D vPoint, int identifier = -1) { int tNearestID = Spatial.FindNearestTriangle(vPoint); DistPoint3Triangle3 q = MeshQueries.TriangleDistance(Mesh, tNearestID, vPoint); return(q.TriangleClosest); }
InteractiveRemesher make_remesher(DMesh3 mesh) { var m = new InteractiveRemesher(mesh); m.PreventNormalFlips = true; double mine, maxe, avge; MeshQueries.EdgeLengthStats(mesh, out mine, out avge, out maxe); m.SetTargetEdgeLength(avge * EdgeLengthMultiplier); m.SmoothSpeedT = SmoothSpeed; if (Reproject) { m.SetProjectionTarget(MeshProjectionTarget.Auto(mesh)); } if (RemeshBoundary) { MeshBoundaryLoops loops = new MeshBoundaryLoops(mesh); int k = 1; foreach (var loop in loops) { MeshConstraintUtil.ConstrainVtxLoopTo(m, loop.Vertices, new DCurveProjectionTarget(loop.ToCurve()), k++); } } else if (PreserveBoundary) { MeshConstraintUtil.FixAllBoundaryEdges(m); } return(m); }
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); }
public AddTrianglesMeshChange fill_smooth(DMesh3 mesh, EdgeLoop loop) { AddTrianglesMeshChange addChange = null; SmoothedHoleFill filler = new SmoothedHoleFill(mesh, loop); filler.ConstrainToHoleInterior = true; if (this.AutoTargetEdgeLength) { double mine, maxe, avge; MeshQueries.EdgeLengthStatsFromEdges(mesh, loop.Edges, out mine, out maxe, out avge); filler.TargetEdgeLength = avge; } else { filler.TargetEdgeLength = this.TargetEdgeLength; } filler.SmoothSolveIterations = this.SmoothOptimizeRounds; bool fill_ok = filler.Apply(); if (fill_ok) { addChange = new AddTrianglesMeshChange(); addChange.InitializeFromExisting(mesh, filler.FillVertices, filler.FillTriangles); } return(addChange); }
DMesh3 GenerateRemesh(DMesh3 mesh) { DMesh3 remeshed = new DMesh3(mesh); DMeshAABBTree3 project = new DMeshAABBTree3(mesh); project.Build(); MeshProjectionTarget Target = new MeshProjectionTarget(project.Mesh, project); double minlen, maxlen, avglen; MeshQueries.EdgeLengthStats(mesh, out minlen, out maxlen, out avglen); double edge_len = (TargetEdgeLength == 0) ? Loop.AverageEdgeLength : avglen; Remesher r = new Remesher(remeshed); r.SetTargetEdgeLength(edge_len); r.SetProjectionTarget(Target); MeshConstraintUtil.FixAllBoundaryEdges(r); for (int k = 0; k < 20; ++k) { r.BasicRemeshPass(); } return(remeshed); }
public int FindNearestHitTriangle(Ray3d ray, double fMaxDist = double.MaxValue) { var save_filter = SourceSpatial.TriangleFilterF; SourceSpatial.TriangleFilterF = source_filter; int hit_source_tid = SourceSpatial.FindNearestHitTriangle(ray); SourceSpatial.TriangleFilterF = save_filter; int hit_edit_tid; IntrRay3Triangle3 edit_hit = find_added_hit(ref ray, out hit_edit_tid); if (hit_source_tid == DMesh3.InvalidID && hit_edit_tid == DMesh3.InvalidID) { return(DMesh3.InvalidID); } else if (hit_source_tid == DMesh3.InvalidID) { return(hit_edit_tid); } else if (hit_edit_tid == DMesh3.InvalidID) { return(hit_source_tid); } IntrRay3Triangle3 source_hit = (hit_source_tid != -1) ? MeshQueries.TriangleIntersection(SourceMesh, hit_source_tid, ray) : null; return((edit_hit.RayParameter < source_hit.RayParameter) ? hit_edit_tid : hit_source_tid); }
public void Precompute_SingleVectorBarycentric() { int N = DisplaceMesh.MaxTriangleID; BaryFaceDisplacements = new BaryDisplace[N]; //foreach ( int vid in DisplaceMesh.VertexIndices() ) { gParallel.ForEach <int>(DisplaceMesh.VertexIndices(), (vid) => { Vector3d pos = DisplaceMesh.GetVertex(vid); int tid = BaseSpatial.FindNearestTriangle(pos); DistPoint3Triangle3 dist = MeshQueries.TriangleDistance(BaseMesh, tid, pos); Vector3f dv = (Vector3f)(pos - dist.TriangleClosest); Frame3f triFrame = BaseMesh.GetTriFrame(tid); Vector3f relVec = triFrame.ToFrameV(dv); BaryFaceDisplacements[vid] = new BaryDisplace() { tID = tid, a = (float)dist.TriangleBaryCoords.x, b = (float)dist.TriangleBaryCoords.y, c = (float)dist.TriangleBaryCoords.z, dv = relVec }; }); }
public Vector3d Project(Vector3d vSourcePt, int identifier = -1) { Vector3d vTargetPt = SourceToTargetXForm.TransformP(vSourcePt); int tNearestID = TargetSpatial.FindNearestTriangle(vTargetPt); DistPoint3Triangle3 q = MeshQueries.TriangleDistance(Target, tNearestID, vTargetPt); double d = q.DistanceSquared; Vector3d vTargetNearestInSource = TargetToSourceXForm.TransformP(q.TriangleClosest); if (MaxDistance == double.MaxValue) { return(vTargetNearestInSource); } if (TargetSpatial.IsInside(vTargetPt)) { return(vTargetNearestInSource); } tNearestID = SourceSpatial.FindNearestTriangle(vSourcePt); DistPoint3Triangle3 qSource = MeshQueries.TriangleDistance(Source, tNearestID, vSourcePt); d = Math.Sqrt(d); if (d < MaxDistance) { double min = (1.0 - Smoothness) * MaxDistance; double t = MathUtil.WyvillFalloff(d, min, MaxDistance); t = 1.0 - t; return(Vector3d.Lerp(vTargetNearestInSource, qSource.TriangleClosest, t)); } else { return(qSource.TriangleClosest); } }
public Vector3d GetHitLocationFromRay(Ray3d ray) { Vector3d vout = new Vector3d(0, 0, 0); int currHitTri = -1; IntrRay3Triangle3 hitInfo; int x = 0, y = 0; foreach (TerrainChunk t in terrainChunks) { currHitTri = t.dMeshAABB.FindNearestHitTriangle(ray); if (currHitTri != -1) { x = t.arrayX; y = t.arrayY; break; } } if (currHitTri != -1) { hitInfo = MeshQueries.TriangleIntersection(terrainChunks[x, y].dMesh, currHitTri, ray); vout = hitInfo.Ray.PointAt(hitInfo.RayParameter); } return(vout); }
public static void test_AABBTree_TriDist(int meshCase = 0) { DMesh3 mesh = MakeSpatialTestMesh(meshCase); DMeshAABBTree3 tree = new DMeshAABBTree3(mesh); tree.Build(); AxisAlignedBox3d bounds = mesh.CachedBounds; Vector3d ext = bounds.Extents; Vector3d c = bounds.Center; Random rand = new Random(316136327); int N = 10000; for (int ii = 0; ii < N; ++ii) { Vector3d p = new Vector3d( c.x + (4 * ext.x * (2 * rand.NextDouble() - 1)), c.y + (4 * ext.y * (2 * rand.NextDouble() - 1)), c.z + (4 * ext.z * (2 * rand.NextDouble() - 1))); int tNearBrute = MeshQueries.FindNearestTriangle_LinearSearch(mesh, p); int tNearTree = tree.FindNearestTriangle(p); DistPoint3Triangle3 qBrute = MeshQueries.TriangleDistance(mesh, tNearBrute, p); DistPoint3Triangle3 qTree = MeshQueries.TriangleDistance(mesh, tNearTree, p); if (Math.Abs(qBrute.DistanceSquared - qTree.DistanceSquared) > MathUtil.ZeroTolerance) { Util.gBreakToDebugger(); } } }
internal void MoveAllPointsDepthDependant(CuttingInfo info, DMesh3 newMesh, Dictionary <int, BacksideAlgorithm.PeprStatusVert> stati) { var tree = new DMeshAABBTree3(info.oldMesh, true); tree.TriangleFilterF = i => tree.Mesh.GetTriangleGroup(i) != info.data.ColorNum; foreach (var status in stati) { var shellPoint = newMesh.GetVertex(status.Value.idNewMeshOuter.Value); var normal = info.oldMesh.CalcVertexNormal(status.Value.idOldMeshOuter); var position = shellPoint + info.data.minDepth * normal; Ray3d ray = new Ray3d(shellPoint - normal * info.data.minDepth, -normal); //tiny shift to make sure it's not hitting itself int hit_tid = tree.FindNearestHitTriangle(ray); Debug.Log("Hit " + hit_tid); if (hit_tid != DMesh3.InvalidID) { IntrRay3Triangle3 intr = MeshQueries.TriangleIntersection(info.oldMesh, hit_tid, ray); double hit_dist = shellPoint.Distance(ray.PointAt(intr.RayParameter)); position = shellPoint - normal * hit_dist * (info.data.depth / 100); Debug.Log($"Hit Dist: {hit_dist}"); } else { StaticFunctions.ErrorMessage("Depth Dependant Calculation has encountered an error"); } info.mesh.SetVertex(status.Value.idOldMeshInner.Value, position); newMesh.SetVertex(status.Value.idNewMeshInner.Value, position); } }
public static void test_auto_fill() { DMesh3 mesh = TestUtil.LoadTestInputMesh("autofill_cases.obj"); //DMesh3 mesh = TestUtil.LoadTestInputMesh("autofill_tempcase1.obj"); //DMesh3 mesh = TestUtil.LoadTestInputMesh("autofill_planarcase.obj"); //DMesh3 mesh = TestUtil.LoadTestInputMesh("autofill_box_edge_strip.obj"); //DMesh3 mesh = TestUtil.LoadTestInputMesh("autofill_box_edge_strip_2.obj"); //DMesh3 mesh = TestUtil.LoadTestInputMesh("crazyhole.obj"); double mine, maxe, avge; MeshQueries.EdgeLengthStats(mesh, out mine, out maxe, out avge); int ROUNDS = 1; for (int k = 0; k < ROUNDS; ++k) { MeshBoundaryLoops loops = new MeshBoundaryLoops(mesh); foreach (EdgeLoop loop in loops) { AutoHoleFill fill = new AutoHoleFill(mesh, loop); fill.TargetEdgeLength = avge; fill.Apply(); } if (k == ROUNDS - 1) { continue; } RemesherPro r = new RemesherPro(mesh); r.SetTargetEdgeLength(avge); for (int j = 0; j < 10; ++j) { r.FastSplitIteration(); } MergeCoincidentEdges merge = new MergeCoincidentEdges(mesh); merge.Apply(); } TestUtil.WriteTestOutputMesh(mesh, "autofill_result.obj"); //DMesh3 mesh = new DMesh3(); //SphericalFibonacciPointSet ps = new SphericalFibonacciPointSet(); //for (int k = 0; k < ps.N; ++k) { // MeshEditor.AppendBox(mesh, ps[k], ps[k], 0.05f); //} //Random r = new Random(31337); //Vector3d[] pts = TestUtil.RandomPoints3(10000, r, Vector3d.Zero); //foreach ( Vector3d pt in pts ) { // pt.Normalize(); // int nearest = ps.NearestPoint(pt, true); // Vector3d p = ps[nearest]; // MeshEditor.AppendLine(mesh, new Segment3d(p, p + 0.25f * pt), 0.01f); //} //TestUtil.WriteTestOutputMesh(mesh, "fibonacci.obj"); }
public bool FindHitEdge(Ray3f sceneRay, MeshEditorOpType.BoundaryType boundaryMode, bool snap_to_center, ref Frame3f hitFrameS, ref int hitEID) { Ray3f objRay = SceneTransforms.SceneToObject(Target, sceneRay); int hit_tri = PreviewSpatial.FindNearestHitTriangle(objRay); if (hit_tri == DMesh3.InvalidID) { return(false); } if (allow_backface_hits == false && is_back_facing(hit_tri)) { return(false); } var intr = MeshQueries.TriangleIntersection(PreviewMesh, hit_tri, objRay); int e_idx = -1; double near_sqr = double.MaxValue; DistRay3Segment3 near_dist = null; for (int j = 0; j < 3; ++j) { Segment3d seg = new Segment3d(intr.Triangle[j], intr.Triangle[(j + 1) % 3]); DistRay3Segment3 dist = new DistRay3Segment3(objRay, seg); if (dist.GetSquared() < near_sqr) { near_sqr = dist.GetSquared(); near_dist = dist; e_idx = j; } } int eid = PreviewMesh.GetTriEdge(hit_tri, e_idx); if (boundaryMode != MeshEditorOpType.BoundaryType.Any) { bool is_boundary = PreviewMesh.IsBoundaryEdge(eid); if ((is_boundary && boundaryMode == MeshEditorOpType.BoundaryType.OnlyInternal) || (is_boundary == false && boundaryMode == MeshEditorOpType.BoundaryType.OnlyBoundary)) { return(false); } } if (snap_to_center) { Frame3f hitFrameL = new Frame3f(PreviewMesh.GetEdgePoint(eid, 0.5), PreviewMesh.GetTriNormal(hit_tri)); hitFrameS = SceneTransforms.ObjectToScene(previewSO, hitFrameL); } else { Frame3f hitFrameL = new Frame3f(near_dist.SegmentClosest, PreviewMesh.GetTriNormal(hit_tri)); hitFrameS = SceneTransforms.ObjectToScene(previewSO, hitFrameL); } hitEID = eid; return(true); }
public Vector3d Project(Vector3d vPoint, int identifier) { if (Spatial.IsInside(vPoint)) { return(MeshQueries.NearestPointFrame(Spatial.Mesh, Spatial, vPoint).Origin); } else { return(vPoint); } }
public Vector3D FindNearestAndOffset(Vector3D pos) { int tNearestID = Spatial.FindNearestTriangle(pos); DistPoint3Triangle3 q = MeshQueries.TriangleDistance(Mesh, tNearestID, pos); Vector3D vHitNormal = (UseFaceNormal == false && Mesh.HasVertexNormals) ? Mesh.GetTriBaryNormal(tNearestID, q.TriangleBaryCoords.x, q.TriangleBaryCoords.y, q.TriangleBaryCoords.z) : Mesh.GetTriNormal(tNearestID); return(q.TriangleClosest + Distance * vHitNormal); }
public static double?DistanceToTree(this DMeshAABBTree3 tree, Ray3d ray) { var hit_tid = tree.FindNearestHitTriangle(ray); if (hit_tid == DMesh3.InvalidID) { return(null); } var intr = MeshQueries.TriangleIntersection(tree.Mesh, hit_tid, ray); return(ray.Origin.Distance(ray.PointAt(intr.RayParameter))); }
public static void test_AABBTree_TriTriDist() { System.Console.WriteLine("test_AABBTree_TriTriDist()"); Sphere3Generator_NormalizedCube gen = new Sphere3Generator_NormalizedCube() { Radius = 1, EdgeVertices = 6 }; DMesh3 sphereMesh = gen.Generate().MakeDMesh(); Reducer reducer = new Reducer(sphereMesh); reducer.ReduceToTriangleCount(77); Random r = new Random(31337); for (int iter = 0; iter < 1000; ++iter) { DMesh3 sphere1 = new DMesh3(sphereMesh), sphere2 = new DMesh3(sphereMesh); Vector3d[] pts = TestUtil.RandomPoints3(3, r, Vector3d.Zero, 100); Vector3d p1 = pts[0], p2 = pts[1]; double r1 = 5, r2 = 10; MeshTransforms.Scale(sphere1, r1); MeshTransforms.Translate(sphere1, p1); MeshTransforms.Scale(sphere2, r2); MeshTransforms.Translate(sphere2, p2); DMeshAABBTree3 tree1 = new DMeshAABBTree3(sphere1, true); DMeshAABBTree3 tree2 = new DMeshAABBTree3(sphere2, true); double sphere_dist = p1.Distance(p2) - (r1 + r2); double distBrute = double.MaxValue; Index2i nearestBrute = MeshQueries.FindNearestTriangles_LinearSearch(sphere1, sphere2, out distBrute); DistTriangle3Triangle3 qBrute = MeshQueries.TrianglesDistance(sphere1, nearestBrute.a, sphere2, nearestBrute.b); double distTree = double.MaxValue; Index2i nearestTree = tree1.FindNearestTriangles(tree2, null, out distTree); DistTriangle3Triangle3 qTree = MeshQueries.TrianglesDistance(sphere1, nearestTree.a, sphere2, nearestTree.b); double distTree2 = double.MaxValue; Index2i nearestTree2 = tree2.FindNearestTriangles(tree1, null, out distTree2); // pairs are unstable if we are on an edge if (qBrute.Triangle0BaryCoords.x < 0.99 && qBrute.Triangle0BaryCoords.y < 0.99 && qBrute.Triangle0BaryCoords.z < 0.99 && qBrute.Triangle1BaryCoords.x < 0.99 && qBrute.Triangle1BaryCoords.y < 0.99 && qBrute.Triangle1BaryCoords.z < 0.99) { Util.gDevAssert(nearestBrute.a == nearestTree.a && nearestBrute.b == nearestTree.b); Util.gDevAssert(nearestBrute.b == nearestTree2.a && nearestBrute.a == nearestTree.b); } Util.gDevAssert(Math.Abs(distBrute - distTree) < MathUtil.Epsilonf && Math.Abs(distBrute - distTree2) < MathUtil.Epsilonf); } }
public static void test_AABBTree_TriTriIntr() { System.Console.WriteLine("test_AABBTree_TriTriIntr()"); Sphere3Generator_NormalizedCube gen = new Sphere3Generator_NormalizedCube() { Radius = 1, EdgeVertices = 25 }; DMesh3 sphereMesh = gen.Generate().MakeDMesh(); Reducer reducer = new Reducer(sphereMesh); reducer.ReduceToTriangleCount(77); int hit_count = 0; Random r = new Random(31337); for (int iter = 0; iter < 5000; ++iter) { DMesh3 sphere1 = new DMesh3(sphereMesh), sphere2 = new DMesh3(sphereMesh); Vector3d[] pts = TestUtil.RandomPoints3(3, r, Vector3d.Zero, 10); // at 10, about half of the spheres intersect Vector3d p1 = pts[0], p2 = pts[1]; double r1 = 5, r2 = 10; double eps = (r1 + r2) * 0.5 * 0.001; MeshTransforms.Scale(sphere1, r1); MeshTransforms.Translate(sphere1, p1); MeshTransforms.Scale(sphere2, r2); MeshTransforms.Translate(sphere2, p2); DMeshAABBTree3 tree1 = new DMeshAABBTree3(sphere1, true); DMeshAABBTree3 tree2 = new DMeshAABBTree3(sphere2, true); bool spheres_intersect = p1.Distance(p2) < (r1 + r2 + 2 * eps); if (spheres_intersect && p1.Distance(p2) + Math.Min(r1, r2) < Math.Max(r1, r2) * 0.9) { spheres_intersect = false; } Index2i hitBrute = MeshQueries.FindIntersectingTriangles_LinearSearch(sphere1, sphere2); bool bHitBrute = hitBrute != Index2i.Max; if (bHitBrute) { hit_count++; } // [RMS] not reliable because of tesselation //Util.gDevAssert(bHitBrute == spheres_intersect); bool bHitTree1 = tree1.TestIntersection(tree2); bool bHitTree2 = tree2.TestIntersection(tree1); Util.gDevAssert(bHitBrute == bHitTree1 && bHitTree1 == bHitTree2); } System.Console.WriteLine(hit_count.ToString()); }
public virtual void Update() { base.begin_update(); int start_timestamp = this.CurrentInputTimestamp; if (MeshSource == null) { throw new Exception("GenerateClosedMeshOp: must set valid MeshSource to compute!"); } try { ResultMesh = null; DMesh3 meshIn = MeshSource.GetDMeshUnsafe(); input_spatial = MeshSource.GetSpatial() as DMeshAABBTree3; if (meshIn.ShapeTimestamp != input_mesh_cache_timestamp) { cached_is_closed = meshIn.IsClosed(); MeshQueries.EdgeLengthStats(meshIn, out input_mesh_edge_stats.x, out input_mesh_edge_stats.y, out input_mesh_edge_stats.z); if (input_spatial == null) { input_spatial = new DMeshAABBTree3(meshIn, false); } input_mesh_cache_timestamp = meshIn.ShapeTimestamp; } if (closing_type == ClosingTypes.LevelSet) { update_level_set(); } else if (closing_type == ClosingTypes.WindingNumberGrid) { if (cached_is_closed) { update_winding(); } else { update_winding_fast(); } } else { update_winding_exact(); } base.complete_update(); } catch (Exception e) { PostOnOperatorException(e); ResultMesh = base.make_failure_output(MeshSource.GetDMeshUnsafe()); base.complete_update(); } }
public virtual void Setup() { // turn on xform gizmo Scene.Context.TransformManager.PushOverrideGizmoType(BendPlanePivotGizmo.DefaultTypeName); Vector3d ctrPt = TargetSO.Mesh.CachedBounds.Center; Frame3f nearestF = MeshQueries.NearestPointFrame(TargetSO.Mesh, TargetSO.Spatial, ctrPt, true); BendPlaneOriginS = SceneTransforms.ObjectToSceneP(TargetSO, nearestF.Origin); BendPlaneNormalS = Vector3d.AxisY; bendPlaneGizmoSO = new BendPlanePivotSO(); bendPlaneGizmoSO.Create(Scene.PivotSOMaterial, Scene.FrameSOMaterial); bendPlaneGizmoSO.OnTransformModified += OnBendPlaneTransformModified; Scene.AddSceneObject(bendPlaneGizmoSO); Frame3f cutFrameS = new Frame3f(BendPlaneOriginS); cutFrameS.AlignAxis(1, (Vector3f)BendPlaneNormalS); bendPlaneGizmoSO.SetLocalFrame(cutFrameS, CoordSpace.SceneCoords); allow_selection_changes = true; Scene.Select(bendPlaneGizmoSO, true); allow_selection_changes = false; StandardIndicatorFactory factory = new StandardIndicatorFactory(); SectionPlaneIndicator bendPlane = factory.MakeSectionPlaneIndicator( 100, "bendPlane", fDimension.Scene(100), () => { return(new Frame3f(BendPlaneOriginS, BendPlaneNormalS)); }, () => { return(new Colorf(Colorf.LightGreen, 0.5f)); }, () => { return(true); } ); Indicators.AddIndicator(bendPlane); // save initial vtx positions VertexPositions = new Vector3d[TargetSO.Mesh.MaxVertexID]; foreach (int vid in TargetSO.Mesh.VertexIndices()) { VertexPositions[vid] = TargetSO.Mesh.GetVertex(vid); } PreviewSO = TargetSO.Duplicate() as DMeshSO; Scene.AddSceneObject(PreviewSO); //PreviewSO.AssignSOMaterial(Scene.TransparentNewSOMaterial); fMaterial transMat = MaterialUtil.CreateTransparentMaterial(Colorf.BlueMetal.SetAlpha(0.1f)); TargetSO.PushOverrideMaterial(transMat); TargetSO.SetLayer(FPlatform.WidgetOverlayLayer); }
public static Vector3d NearestPoint(this DMeshAABBTree3 tree, Vector3d point) { var tid = tree.FindNearestTriangle(point); if (tid == DMesh3.InvalidID) { return(new Vector3d()); } var dist = MeshQueries.TriangleDistance(tree.Mesh, tid, point); return(dist.TriangleClosest); }
protected override void OnPointUpdated(ControlPoint pt, Frame3f prevFrameS, bool isFirst) { DMesh3 mesh = InputMeshSO.Mesh; DMeshAABBTree3 spatial = InputMeshSO.Spatial; Vector3f ptO = SceneTransforms.SceneToObjectP(InputMeshSO, pt.currentFrameS.Origin); Frame3f frameO = MeshQueries.NearestPointFrame(mesh, spatial, ptO, true); Vector3d dir = -frameO.Z; if (hole_direction != HoleDirections.Normal) { Vector3f axis = Vector3f.AxisX; if (hole_direction == HoleDirections.AxisY) { axis = Vector3f.AxisY; } else if (hole_direction == HoleDirections.AxisZ) { axis = Vector3f.AxisZ; } axis = SceneTransforms.SceneToObjectN(InputMeshSO, axis); dir = (dir.Dot(axis) < 0) ? -axis : axis; } //dir.Normalize(); LastUpdateRay = new Ray3d(frameO.Origin, dir); List <int> hitTris = new List <int>(); int hit_tris = spatial.FindAllHitTriangles(LastUpdateRay, hitTris); double max_t = 0; foreach (int tid in hitTris) { Vector3d n = mesh.GetTriNormal(tid); if (n.Dot(LastUpdateRay.Direction) < 0) { continue; } IntrRay3Triangle3 rayhit = MeshQueries.TriangleIntersection(InputMeshSO.Mesh, tid, LastUpdateRay); max_t = rayhit.RayParameter; break; } if (max_t <= 0) { return; } LastThroughDepth = max_t; update_current_hole_type(); }
protected override void SolveInstance(IGH_DataAccess DA) { DMesh3_goo goo = null; DA.GetData(0, ref goo); DMesh3 mesh = new DMesh3(goo.Value); MeshQueries.EdgeLengthStats(mesh, out double min, out double max, out double avg); DA.SetData(0, max); DA.SetData(1, min); DA.SetData(2, avg); }
// [RMS] this only tests some basic cases... public static void test_Laplacian_deformer() { // compact version DMesh3 mesh = new DMesh3(TestUtil.MakeRemeshedCappedCylinder(1.0), true); Debug.Assert(mesh.IsCompact); AxisAlignedBox3d bounds = mesh.GetBounds(); TestUtil.WriteTestOutputMesh(mesh, "laplacian_deformer_before.obj"); List <IMesh> result_meshes = new List <IMesh>(); LaplacianMeshDeformer deformer = new LaplacianMeshDeformer(mesh); int ti = MeshQueries.FindNearestTriangle_LinearSearch(mesh, new Vector3d(2, 5, 2)); int v_pin = mesh.GetTriangle(ti).a; List <int> constraints = new List <int>() { v_pin }; double consPin = 10; double consBottom = 10; foreach (int vid in constraints) { result_meshes.Add(TestUtil.MakeMarker(mesh.GetVertex(vid), (vid == 0) ? 0.2f : 0.1f, Colorf.Red)); } foreach (int vid in mesh.VertexIndices()) { Vector3d v = mesh.GetVertex(vid); bool bottom = (v.y - bounds.Min.y) < 0.01f; if (constraints.Contains(vid)) { deformer.SetConstraint(vid, v + Vector3f.AxisY, consPin, false); } if (bottom) { deformer.SetConstraint(vid, v, consBottom, false); } } deformer.SolveAndUpdateMesh(); result_meshes.Add(mesh); TestUtil.WriteTestOutputMeshes(result_meshes, "laplacian_deformer_after.obj"); }
void remove_old_vertices(int[] MapV, DMesh3 mesh) { HashSet <int> keepV = new HashSet <int>(); for (int k = 0; k < MapV.Length; ++k) { if (MapV[k] != DMesh3.InvalidID) { keepV.Add(MapV[k]); } } Remesher r = new Remesher(mesh); //r.EnableCollapses = false; //r.EnableSplits = false; //r.EnableFlips = false; r.SmoothSpeedT = 1.0; //r.EnableSmoothing = false; r.PreventNormalFlips = true; r.SetTargetEdgeLength(1.0); //r.EnableSmoothing = false; MeshConstraints c = new MeshConstraints(); foreach (int vid in keepV) { c.SetOrUpdateVertexConstraint(vid, VertexConstraint.Pinned); } r.SetExternalConstraints(c); double minE, maxE, avgE; MeshQueries.EdgeLengthStats(mesh, out minE, out maxE, out avgE); r.SetTargetEdgeLength(avgE * .3); for (int k = 0; k < 10; ++k) { r.BasicRemeshPass(); } //int iter = 0; //while (iter++ < 10) { // r.SetTargetEdgeLength(iter * 1.0); // for (int k = 0; k < 10; ++k) // r.BasicRemeshPass(); //} }