public static DMeshAABBTree3 AABBTree(this DMesh3 mesh) { var tree = new DMeshAABBTree3(mesh); tree.Build(); return(tree); }
internal bool CheckIntersection(DMesh3 mesh, Triangle3d triangle) { var spatial = new DMeshAABBTree3(mesh); spatial.Build(); return(spatial.TestIntersection(triangle)); }
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(); } } }
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 static void test_AABBTree_basic() { List <int> cases = new List <int>() { 0, 1, 2, 3, 4, 7, 8 }; foreach (int meshCase in cases) { DMesh3 mesh = MakeSpatialTestMesh(meshCase); DMeshAABBTree3 treeMedian = new DMeshAABBTree3(mesh); treeMedian.Build(DMeshAABBTree3.BuildStrategy.TopDownMedian); treeMedian.TestCoverage(); treeMedian.TotalVolume(); DMeshAABBTree3 treeMidpoint = new DMeshAABBTree3(mesh); treeMidpoint.Build(DMeshAABBTree3.BuildStrategy.TopDownMidpoint); treeMidpoint.TestCoverage(); treeMidpoint.TotalVolume(); DMeshAABBTree3 treeUpFast = new DMeshAABBTree3(mesh); treeUpFast.Build(DMeshAABBTree3.BuildStrategy.BottomUpFromOneRings, DMeshAABBTree3.ClusterPolicy.Fastest); treeUpFast.TestCoverage(); treeUpFast.TotalVolume(); DMeshAABBTree3 treeUpN = new DMeshAABBTree3(mesh); treeUpN.Build(DMeshAABBTree3.BuildStrategy.BottomUpFromOneRings, DMeshAABBTree3.ClusterPolicy.FastVolumeMetric); treeUpN.TestCoverage(); treeUpN.TotalVolume(); } }
void Start() { if (model != null) { mesh = model.sharedMesh; meshVertices = mesh.vertices; meshTriangles = mesh.triangles; for (int i = 0; i < meshVertices.Length; i++) { meshVertices[i] = model.transform.TransformPoint(meshVertices[i]); } binarySpacePartition = new BSP(mesh, 14); #if G3_USING_UNITY DMesh3Builder dMeshBuilder = new DMesh3Builder(); dMeshBuilder.AppendNewMesh(false, false, false, false); foreach (Vector3 vertex in meshVertices) { dMeshBuilder.AppendVertex(vertex.x, vertex.y, vertex.z); } for (int i = 0; i < meshTriangles.Length; i += 3) { dMeshBuilder.AppendTriangle(meshTriangles[i], meshTriangles[i + 1], meshTriangles[i + 2]); } g3MeshTree = new DMeshAABBTree3(dMeshBuilder.Meshes[0]); g3MeshTree.Build(); #endif } }
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); }
void validate_spatial() { if (enable_spatial && spatial == null) { spatial = new DMeshAABBTree3(mesh); spatial.Build(); } }
/// <summary> /// Checks if a point is inside of a mesh. This function is slow due to the need to build a spatial data structure using geometry3Sharp. /// </summary> /// <param name="mesh">The mesh to be checked.</param> /// <param name="point">The point in question.</param> /// <returns>Whether the point is inside the mesh.</returns> public static bool IsPointInside(this Mesh mesh, Vector3 point) { var mesh3 = GenerateDynamicMesh(mesh.vertices, mesh.triangles, mesh.normals); var spatial = new DMeshAABBTree3(mesh3); spatial.Build(); return(spatial.IsInside(new Vector3d(point.x, point.y, point.z))); }
public DMesh3 remesh_constraints_fixedverts(int iterations, DMesh3 mesh, double min, double max, double angle) { AxisAlignedBox3d bounds = mesh.CachedBounds; // construct mesh projection target DMesh3 meshCopy = new DMesh3(mesh); meshCopy.CheckValidity(); DMeshAABBTree3 tree = new DMeshAABBTree3(meshCopy); tree.Build(); MeshProjectionTarget target = new MeshProjectionTarget() { Mesh = meshCopy, Spatial = tree }; // construct constraint set MeshConstraints cons = new MeshConstraints(); //EdgeRefineFlags useFlags = EdgeRefineFlags.NoFlip | EdgeRefineFlags.NoCollapse; EdgeRefineFlags useFlags = EdgeRefineFlags.NoFlip; foreach (int eid in mesh.EdgeIndices()) { double fAngle = MeshUtil.OpeningAngleD(mesh, eid); if (fAngle > angle) { cons.SetOrUpdateEdgeConstraint(eid, new EdgeConstraint(useFlags)); Index2i ev = mesh.GetEdgeV(eid); int nSetID0 = (mesh.GetVertex(ev[0]).y > bounds.Center.y) ? 1 : 2; int nSetID1 = (mesh.GetVertex(ev[1]).y > bounds.Center.y) ? 1 : 2; cons.SetOrUpdateVertexConstraint(ev[0], new VertexConstraint(true, nSetID0)); cons.SetOrUpdateVertexConstraint(ev[1], new VertexConstraint(true, nSetID1)); } } Remesher r = new Remesher(mesh); r.Precompute(); r.SetExternalConstraints(cons); r.SetProjectionTarget(target); r.EnableFlips = r.EnableSplits = r.EnableCollapses = true; r.MinEdgeLength = min; r.MaxEdgeLength = max; r.EnableSmoothing = true; r.SmoothSpeedT = 1; for (int k = 0; k < iterations; ++k) { r.BasicRemeshPass(); mesh.CheckValidity(); } return(mesh); }
public ConstantMeshSourceOp(DMesh3 meshIn, bool buildSpatial, bool bTakeOwnership) { mesh = (bTakeOwnership) ? meshIn : new DMesh3(meshIn); if (buildSpatial) { spatial = new DMeshAABBTree3(mesh); spatial.Build(); } }
/// <summary> /// Generates a mesh for the ground that we can work with. /// </summary> private void LoadGroundMesh() { var vertices = _data.Vertices.Select(a => new Vector3f(a.X, a.Z, a.Y)); var triangles = _data.Triangles.Select(a => new Index3i(a.Indices[0], a.Indices[1], a.Indices[2])); _mesh = DMesh3Builder.Build <Vector3f, Index3i, Vector3f>(vertices, triangles, null, null); _spatial = new DMeshAABBTree3(_mesh); _spatial.Build(); }
public void UpdateCollision() { for (int i = 0; i < numXVerts * numXVerts; i++) { if (vertNeedsCollisionUpdate[i]) { dMesh.SetVertex(i, new Vector3d(vertices[i].x, vertices[i].y, vertices[i].z)); vertNeedsCollisionUpdate[i] = false; } } dMeshAABB.Build(); }
public void MyInit(DMesh3 mesh, bool isImported = false) { this.mesh = mesh; spatial = new DMeshAABBTree3(mesh); spatial.Build(); this.isImported = isImported; if (isImported) { originalMesh = new DMesh3(mesh); } center = transform.TransformPoint(mesh.GetBounds().Center.toVector3()); }
public void SetMesh(DMesh3 meshIn, bool buildSpatial, bool bTakeOwnership) { mesh = (bTakeOwnership) ? meshIn : new DMesh3(meshIn); spatial = null; if (buildSpatial) { spatial = new DMeshAABBTree3(mesh); spatial.Build(); } PostOnOperatorModified(); }
public static DMesh3 MakeRemeshedCappedCylinder(double fResFactor = 1.0) { DMesh3 mesh = MakeCappedCylinder(false, 128); MeshUtil.ScaleMesh(mesh, Frame3f.Identity, new g3.Vector3f(1, 2, 1)); // construct mesh projection target DMesh3 meshCopy = new DMesh3(mesh); DMeshAABBTree3 tree = new DMeshAABBTree3(meshCopy); tree.Build(); MeshProjectionTarget target = new MeshProjectionTarget() { Mesh = meshCopy, Spatial = tree }; MeshConstraints cons = new MeshConstraints(); EdgeRefineFlags useFlags = EdgeRefineFlags.NoFlip; foreach (int eid in mesh.EdgeIndices()) { double fAngle = MeshUtil.OpeningAngleD(mesh, eid); if (fAngle > 30.0f) { cons.SetOrUpdateEdgeConstraint(eid, new EdgeConstraint(useFlags)); Index2i ev = mesh.GetEdgeV(eid); int nSetID0 = (mesh.GetVertex(ev[0]).y > 1) ? 1 : 2; int nSetID1 = (mesh.GetVertex(ev[1]).y > 1) ? 1 : 2; cons.SetOrUpdateVertexConstraint(ev[0], new VertexConstraint(true, nSetID0)); cons.SetOrUpdateVertexConstraint(ev[1], new VertexConstraint(true, nSetID1)); } } Remesher r = new Remesher(mesh); r.SetExternalConstraints(cons); r.SetProjectionTarget(target); r.Precompute(); r.EnableFlips = r.EnableSplits = r.EnableCollapses = true; r.MinEdgeLength = 0.1f * fResFactor; r.MaxEdgeLength = 0.2f * fResFactor; r.EnableSmoothing = true; r.SmoothSpeedT = 0.5f; for (int k = 0; k < 20; ++k) { r.BasicRemeshPass(); } return(mesh); }
public Task BuildTreeAsync(Vector3[] positions, Vector3[] normals, int[] indices) { return(Task.Run(() => { var norm = ConvertToVector3f(normals); DMeshLocal = DMesh3Builder.Build(ConvertToVector3f(positions), indices, norm); TreeLocal = new DMeshAABBTree3(DMeshLocal); TreeLocal.Build(); box = new BoundingBox(DMeshLocal.GetBounds()); IsBuilt = true; return this; })); }
public static void test_local_param() { //DMesh3 mesh = TestUtil.LoadTestInputMesh("plane_250v.obj"); //DMesh3 mesh = TestUtil.LoadTestInputMesh("hemisphere_nicemesh_3k.obj"); DMesh3 mesh = TestUtil.LoadTestInputMesh("bunny_open_base.obj"); mesh.EnableVertexUVs(Vector2f.Zero); DMeshAABBTree3 spatial = new DMeshAABBTree3(mesh); spatial.Build(); //int tid = spatial.FindNearestTriangle(Vector3d.Zero); //Frame3f seedF = new Frame3f(Vector3d.Zero, Vector3d.AxisY); int tid = 3137; Frame3f seedF = mesh.GetTriFrame(tid); Index3i seedNbrs = mesh.GetTriangle(tid); MeshLocalParam param = new MeshLocalParam(mesh.MaxVertexID, mesh.GetVertexf, mesh.GetVertexNormal, mesh.VtxVerticesItr); param.ComputeToMaxDistance(seedF, seedNbrs, float.MaxValue); float fR = param.MaxUVDistance; param.TransformUV(0.5f / fR, 0.5f * Vector2f.One); param.ApplyUVs((vid, uv) => { mesh.SetVertexUV(vid, uv); }); TestUtil.SetColorsFromScalarF(mesh, (vid) => { return(param.GetUV(vid).Distance(0.5f * Vector2f.One)); }, new Vector2f(0, 0.5f)); OBJWriter writer = new OBJWriter(); var s = new System.IO.StreamWriter(Program.TEST_OUTPUT_PATH + "mesh_local_param.obj", false); List <WriteMesh> wm = new List <WriteMesh>() { new WriteMesh(mesh) }; WriteOptions opt = new WriteOptions() { bCombineMeshes = false, bWriteGroups = false, bPerVertexColors = true, bPerVertexUVs = true, AsciiHeaderFunc = () => { return("mttllib checkerboard.mtl\r\nusemtl checkerboard\r\n"); } }; writer.Write(s, wm, opt); s.Close(); }
internal bool CheckPositionValid(DMesh3 mesh, Vector3d position, int colorToExclude) { var spatial = new DMeshAABBTree3(mesh); spatial.Build(); spatial.TriangleFilterF = i => mesh.GetTriangleGroup(i) != colorToExclude; int near_tid = spatial.FindNearestTriangle(position, 9f); if (near_tid != DMesh3.InvalidID) { return(false); } return(true); }
public Mesh Reduce(Mesh inMesh, int targetCount) { var mesh = inMesh.ToDMesh3(); var reducer = new Reducer(mesh); if (MaintainSurface) { var tree = new DMeshAABBTree3(new DMesh3(mesh)); tree.Build(); var target = new MeshProjectionTarget(tree.Mesh, tree); reducer.SetProjectionTarget(target); reducer.ProjectionMode = Reducer.TargetProjectionMode.Inline; } reducer.ReduceToTriangleCount(Math.Max(4, targetCount)); return(reducer.Mesh.ToMesh()); }
void Start() { if (model != null) { mesh = model.sharedMesh; meshVertices = mesh.vertices; meshTriangles = mesh.triangles; for (int i = 0; i < meshVertices.Length; i++) { meshVertices[i] = model.transform.TransformPoint(meshVertices[i]); } binarySpacePartition = new BSP(mesh, 14); if (diskMaterial) { int numDisksToDraw = Mathf.Min(binarySpacePartition.splittingDisks.Length, 15); diskMatrices = new Matrix4x4[numDisksToDraw]; for (int i = 0; i < numDisksToDraw; i++) { diskMatrices[i] = Matrix4x4.TRS( binarySpacePartition.splittingDisks[i].average, Quaternion.LookRotation(binarySpacePartition.splittingDisks[i].plane), new Vector3(1f, 1f, 0.0001f) * Mathf.Sqrt(binarySpacePartition.splittingDisks[i].sqRadius)); } } #if G3_USING_UNITY DMesh3Builder dMeshBuilder = new DMesh3Builder(); dMeshBuilder.AppendNewMesh(false, false, false, false); foreach (Vector3 vertex in meshVertices) { dMeshBuilder.AppendVertex(vertex.x, vertex.y, vertex.z); } for (int i = 0; i < meshTriangles.Length; i += 3) { dMeshBuilder.AppendTriangle(meshTriangles[i], meshTriangles[i + 1], meshTriangles[i + 2]); } g3MeshTree = new DMeshAABBTree3(dMeshBuilder.Meshes[0]); g3MeshTree.Build(); #endif } }
public virtual bool FindNearest(Vector3d point, double maxDist, out SORayHit nearest, CoordSpace eInCoords) { nearest = null; if (enable_spatial == false) { return(false); } if (spatial == null) { spatial = new DMeshAABBTree3(mesh); spatial.Build(); } // convert to local Vector3f local_pt = SceneTransforms.TransformTo((Vector3f)point, this, eInCoords, CoordSpace.ObjectCoords); if (mesh.CachedBounds.Distance(local_pt) > maxDist) { return(false); } int tid = spatial.FindNearestTriangle(local_pt); if (tid != DMesh3.InvalidID) { DistPoint3Triangle3 dist = MeshQueries.TriangleDistance(mesh, tid, local_pt); nearest = new SORayHit(); nearest.fHitDist = (float)Math.Sqrt(dist.DistanceSquared); Frame3f f_local = new Frame3f(dist.TriangleClosest, mesh.GetTriNormal(tid)); Frame3f f = SceneTransforms.TransformTo(f_local, this, CoordSpace.ObjectCoords, eInCoords); nearest.hitPos = f.Origin; nearest.hitNormal = f.Z; nearest.hitGO = RootGameObject; nearest.hitSO = this; return(true); } return(false); }
/// <summary> /// Find intersection of *WORLD* ray with Mesh /// </summary> override public bool FindRayIntersection(Ray3f rayW, out SORayHit hit) { hit = null; if (enable_spatial == false) { return(false); } if (spatial == null) { spatial = new DMeshAABBTree3(mesh); spatial.Build(); } // convert ray to local Frame3f f = new Frame3f(rayW.Origin, rayW.Direction); f = SceneTransforms.TransformTo(f, this, CoordSpace.WorldCoords, CoordSpace.ObjectCoords); Ray3d local_ray = new Ray3d(f.Origin, f.Z); int hit_tid = spatial.FindNearestHitTriangle(local_ray); if (hit_tid != DMesh3.InvalidID) { IntrRay3Triangle3 intr = MeshQueries.TriangleIntersection(mesh, hit_tid, local_ray); Frame3f hitF = new Frame3f(local_ray.PointAt(intr.RayParameter), mesh.GetTriNormal(hit_tid)); hitF = SceneTransforms.TransformTo(hitF, this, CoordSpace.ObjectCoords, CoordSpace.WorldCoords); hit = new SORayHit(); hit.hitPos = hitF.Origin; hit.hitNormal = hitF.Z; hit.hitIndex = hit_tid; hit.fHitDist = hit.hitPos.Distance(rayW.Origin); // simpler than transforming! hit.hitGO = RootGameObject; hit.hitSO = this; return(true); } return(false); }
// [RMS] this is not working right now... override public bool FindRayIntersection(Ray3f ray, out SORayHit hit) { hit = null; if (enable_spatial == false) { return(false); } if (spatial == null) { spatial = new DMeshAABBTree3(mesh); spatial.Build(); } Transform xform = ((GameObject)RootGameObject).transform; // convert ray to local Ray3d local_ray = new Ray3d(); local_ray.Origin = xform.InverseTransformPoint(ray.Origin); local_ray.Direction = xform.InverseTransformDirection(ray.Direction); local_ray.Direction.Normalize(); int hit_tid = spatial.FindNearestHitTriangle(local_ray); if (hit_tid != DMesh3.InvalidID) { IntrRay3Triangle3 intr = MeshQueries.TriangleIntersection(mesh, hit_tid, local_ray); hit = new SORayHit(); hit.fHitDist = (float)intr.RayParameter; hit.hitPos = xform.TransformPoint((Vector3f)local_ray.PointAt(intr.RayParameter)); hit.hitNormal = xform.TransformDirection((Vector3f)mesh.GetTriNormal(hit_tid)); hit.hitGO = RootGameObject; hit.hitSO = this; return(true); } return(false); }
public static bool ReduceMesh(DMesh3 mesh, float edgeLength, int triangleCount) { Reducer r = new Reducer(mesh); DMeshAABBTree3 tree = new DMeshAABBTree3(new DMesh3(mesh)); tree.Build(); /* * MeshConstraints cons = new MeshConstraints(); * EdgeRefineFlags useFlags = EdgeRefineFlags.NoFlip; * foreach (int eid in mesh.EdgeIndices()) * { * double fAngle = MeshUtil.OpeningAngleD(mesh, eid); * if (fAngle > contraintAngle) * { * cons.SetOrUpdateEdgeConstraint(eid, new EdgeConstraint(useFlags)); * Index2i ev = mesh.GetEdgeV(eid); * int nSetID0 = (mesh.GetVertex(ev[0]).y > 1) ? 1 : 2; * int nSetID1 = (mesh.GetVertex(ev[1]).y > 1) ? 1 : 2; * cons.SetOrUpdateVertexConstraint(ev[0], new VertexConstraint(true, nSetID0)); * cons.SetOrUpdateVertexConstraint(ev[1], new VertexConstraint(true, nSetID1)); * } * } */ if (triangleCount > 0) { r.ReduceToTriangleCount(3000); } else { r.ReduceToEdgeLength(edgeLength); } return(true); }
protected override void SolveInstance(IGH_DataAccess DA) { DMesh3_goo dMsh_goo = null; int numF = 0; bool fixB = false; bool projBack = false; DA.GetData(0, ref dMsh_goo); DA.GetData(1, ref numF); DA.GetData(2, ref fixB); DA.GetData(3, ref projBack); DMesh3 dMsh_copy = new DMesh3(dMsh_goo.Value); Reducer r = new Reducer(dMsh_copy); if (fixB) { r.SetExternalConstraints(new MeshConstraints()); MeshConstraintUtil.PreserveBoundaryLoops(r.Constraints, dMsh_copy); } if (projBack) { DMeshAABBTree3 tree = new DMeshAABBTree3(new DMesh3(dMsh_copy)); tree.Build(); MeshProjectionTarget target = new MeshProjectionTarget(tree.Mesh, tree); r.SetProjectionTarget(target); } r.ReduceToTriangleCount(numF); bool isValid = dMsh_copy.CheckValidity(); if (!isValid) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Mesh seems to have been corrupted during reduction. Please check..."); } DA.SetData(0, dMsh_copy); }
public Task BuildTreeAsync(IGeometryComponent geo) { if (!geo.IsValid) { return(Task.FromResult(0)); } return(Task.Run(() => { var norm = geo.Normals.IsDefaultOrEmpty ? null : ConvertToVector3f(geo.Normals); DMeshLocal = DMesh3Builder.Build(ConvertToVector3f(geo.Positions), geo.Indices, norm); //var sm = new LaplacianMeshSmoother(DMesh); //sm.Initialize(); //sm.SolveAndUpdateMesh(); //DMesh = sm.Mesh; TreeLocal = new DMeshAABBTree3(DMeshLocal); TreeLocal.Build(); box = new BoundingBox(DMeshLocal.GetBounds()); IsBuilt = true; return this; })); }
public static void test_AABBTree_profile() { System.Console.WriteLine("Building test meshes"); DMesh3[] meshes = new DMesh3[NumTestCases]; for (int i = 0; i < NumTestCases; ++i) { meshes[i] = MakeSpatialTestMesh(i); } System.Console.WriteLine("done!"); int N = 10; // avoid garbage collection List <DMeshAABBTree3> trees = new List <DMeshAABBTree3>(); DMeshAABBTree3 tree = null; for (int i = 0; i < NumTestCases; ++i) { Stopwatch w = new Stopwatch(); for (int j = 0; j < N; ++j) { tree = new DMeshAABBTree3(meshes[i]); w.Start(); tree.Build(DMeshAABBTree3.BuildStrategy.TopDownMidpoint); //tree.Build(DMeshAABBTree3.BuildStrategy.TopDownMedian); //tree.Build(DMeshAABBTree3.BuildStrategy.BottomUpFromOneRings, DMeshAABBTree3.ClusterPolicy.FastVolumeMetric); w.Stop(); trees.Add(tree); } double avg_time = w.ElapsedTicks / (double)N; System.Console.WriteLine(string.Format("Case {0}: time {1} tris {2} vol {3} len {4}", i, avg_time, tree.Mesh.TriangleCount, tree.TotalVolume(), tree.TotalExtentSum())); } }
public static void test_AABBTree_RayHit(int meshCase = 8) { DMesh3 mesh = MakeSpatialTestMesh(meshCase); DMeshAABBTree3 tree = new DMeshAABBTree3(mesh); tree.Build(); tree.TestCoverage(); AxisAlignedBox3d bounds = mesh.CachedBounds; Vector3d ext = bounds.Extents; Vector3d c = bounds.Center; double r = bounds.DiagonalLength / 4; Random rand = new Random(316136327); tree.FindNearestHitTriangle( new Ray3f(100 * Vector3f.One, Vector3f.One)); // test rays out from center of box, and rays in towards it // (should all hit for standard test cases) int hits = 0; int N = (meshCase > 7) ? 1000 : 10000; #if true for (int ii = 0; ii < N; ++ii) { if (ii % 100 == 0) { System.Console.WriteLine("{0} / {1}", ii, N); } Vector3d p = (ii < N / 2) ? c : c + 2 * r * rand.Direction(); Vector3d d = (ii < N / 2) ? rand.Direction() : (c - p).Normalized; Ray3d ray = new Ray3d(p, d); int tNearBrute = MeshQueries.FindHitTriangle_LinearSearch(mesh, ray); int tNearTree = tree.FindNearestHitTriangle(ray); //System.Console.WriteLine("{0} - {1}", tNearBrute, tree.TRI_TEST_COUNT); if (tNearBrute == DMesh3.InvalidID) { Debug.Assert(tNearBrute == tNearTree); continue; } ++hits; IntrRay3Triangle3 qBrute = MeshQueries.TriangleIntersection(mesh, tNearBrute, ray); IntrRay3Triangle3 qTree = MeshQueries.TriangleIntersection(mesh, tNearTree, ray); double dotBrute = mesh.GetTriNormal(tNearBrute).Dot(ray.Direction); double dotTree = mesh.GetTriNormal(tNearTree).Dot(ray.Direction); Debug.Assert(Math.Abs(qBrute.RayParameter - qTree.RayParameter) < MathUtil.ZeroTolerance); } Debug.Assert(hits == N); System.Console.WriteLine("in/out rays: {0} hits out of {1} rays", hits, N); #endif // random rays hits = 0; for (int ii = 0; ii < N; ++ii) { if (ii % 100 == 0) { System.Console.WriteLine("{0} / {1}", ii, N); } Vector3d target = c + rand.PointInRange(r); Vector3d o = c + rand.PointInRange(10 * r); Ray3d ray = new Ray3d(o, (target - o).Normalized); int tNearBrute = MeshQueries.FindHitTriangle_LinearSearch(mesh, ray); int tNearTree = tree.FindNearestHitTriangle(ray); //System.Console.WriteLine("{0} - {1}", tNearBrute, tree.TRI_TEST_COUNT); if (tNearBrute == DMesh3.InvalidID) { Debug.Assert(tNearBrute == tNearTree); continue; } ++hits; IntrRay3Triangle3 qBrute = MeshQueries.TriangleIntersection(mesh, tNearBrute, ray); IntrRay3Triangle3 qTree = MeshQueries.TriangleIntersection(mesh, tNearTree, ray); double dotBrute = mesh.GetTriNormal(tNearBrute).Dot(ray.Direction); double dotTree = mesh.GetTriNormal(tNearTree).Dot(ray.Direction); Debug.Assert(Math.Abs(qBrute.RayParameter - qTree.RayParameter) < MathUtil.ZeroTolerance); } System.Console.WriteLine("random rays: hit {0} of {1} rays", hits, N); }
public static void test_reduce_constraints_fixedverts() { int Slices = 128; DMesh3 mesh = TestUtil.MakeCappedCylinder(false, Slices); MeshUtil.ScaleMesh(mesh, Frame3f.Identity, new Vector3f(1, 2, 1)); mesh.CheckValidity(); AxisAlignedBox3d bounds = mesh.CachedBounds; // construct mesh projection target DMesh3 meshCopy = new DMesh3(mesh); meshCopy.CheckValidity(); DMeshAABBTree3 tree = new DMeshAABBTree3(meshCopy); tree.Build(); MeshProjectionTarget target = new MeshProjectionTarget() { Mesh = meshCopy, Spatial = tree }; if (WriteDebugMeshes) { TestUtil.WriteTestOutputMesh(mesh, "reduce_fixed_constraints_test_before.obj"); } // construct constraint set MeshConstraints cons = new MeshConstraints(); //EdgeRefineFlags useFlags = EdgeRefineFlags.NoCollapse; EdgeRefineFlags useFlags = EdgeRefineFlags.PreserveTopology; foreach (int eid in mesh.EdgeIndices()) { double fAngle = MeshUtil.OpeningAngleD(mesh, eid); if (fAngle > 30.0f) { cons.SetOrUpdateEdgeConstraint(eid, new EdgeConstraint(useFlags) { TrackingSetID = 1 }); Index2i ev = mesh.GetEdgeV(eid); int nSetID0 = (mesh.GetVertex(ev[0]).y > bounds.Center.y) ? 1 : 2; int nSetID1 = (mesh.GetVertex(ev[1]).y > bounds.Center.y) ? 1 : 2; cons.SetOrUpdateVertexConstraint(ev[0], new VertexConstraint(true, nSetID0)); cons.SetOrUpdateVertexConstraint(ev[1], new VertexConstraint(true, nSetID1)); } } Reducer r = new Reducer(mesh); r.SetExternalConstraints(cons); r.SetProjectionTarget(target); r.ReduceToTriangleCount(50); mesh.CheckValidity(); if (WriteDebugMeshes) { TestUtil.WriteTestOutputMesh(mesh, "reduce_fixed_constraints_test_after.obj"); } }