public void TestBvhTreePointSearches() { // for this shape imagine the 8 corners of a rubics cube and the center var data = new List <BvhTreeItemData <int> >(); // left, front, bottom data.Add(new BvhTreeItemData <int>(0, new AxisAlignedBoundingBox(0, 0, 0, 0, 0, 0))); // right, front, bottom data.Add(new BvhTreeItemData <int>(1, new AxisAlignedBoundingBox(2, 0, 0, 2, 0, 0))); // left, back, bottom data.Add(new BvhTreeItemData <int>(2, new AxisAlignedBoundingBox(0, 2, 0, 0, 2, 0))); // right, back, bottom data.Add(new BvhTreeItemData <int>(3, new AxisAlignedBoundingBox(2, 2, 0, 2, 2, 0))); // center, center, center data.Add(new BvhTreeItemData <int>(4, new AxisAlignedBoundingBox(1, 1, 1, 1, 1, 1))); // left, front, top data.Add(new BvhTreeItemData <int>(0, new AxisAlignedBoundingBox(0, 0, 2, 0, 0, 2))); // right, front, top data.Add(new BvhTreeItemData <int>(1, new AxisAlignedBoundingBox(2, 0, 2, 2, 0, 2))); // left, back, top data.Add(new BvhTreeItemData <int>(2, new AxisAlignedBoundingBox(0, 2, 2, 0, 2, 2))); // right, back, top data.Add(new BvhTreeItemData <int>(3, new AxisAlignedBoundingBox(2, 2, 2, 2, 2, 2))); var tree = BvhTree <int> .CreateNewHierachy(data); var results = new List <int>(); tree.SearchBounds(new AxisAlignedBoundingBox(0, 0, 0, 3, 3, 3), results); Assert.AreEqual(results.Count(), 9, "Found all items."); results.Clear(); tree.SearchPoint(1, 1, 1, results); Assert.AreEqual(1, results.Count(), "All or around this point."); Assert.AreEqual(4, results[0], "found the center point."); }
public void TestBvhAlongRay() { // for this shape imagine the 8 corners of a rubics cube and the center var data = new List <BvhTreeItemData <int> >(); // left, front, bottom data.Add(new BvhTreeItemData <int>(0, new AxisAlignedBoundingBox(0, 0, 0, 1, 1, 1))); // right, front, bottom data.Add(new BvhTreeItemData <int>(1, new AxisAlignedBoundingBox(2, 0, 0, 3, 1, 1))); // left, back, bottom data.Add(new BvhTreeItemData <int>(2, new AxisAlignedBoundingBox(0, 2, 0, 1, 3, 1))); // right, back, bottom data.Add(new BvhTreeItemData <int>(3, new AxisAlignedBoundingBox(2, 2, 0, 3, 3, 1))); // center, center, center data.Add(new BvhTreeItemData <int>(4, new AxisAlignedBoundingBox(1, 1, 1, 2, 2, 2))); // left, front, top data.Add(new BvhTreeItemData <int>(5, new AxisAlignedBoundingBox(0, 0, 2, 1, 1, 3))); // right, front, top data.Add(new BvhTreeItemData <int>(6, new AxisAlignedBoundingBox(2, 0, 2, 3, 1, 3))); // left, back, top data.Add(new BvhTreeItemData <int>(7, new AxisAlignedBoundingBox(0, 2, 2, 1, 3, 3))); // right, back, top data.Add(new BvhTreeItemData <int>(8, new AxisAlignedBoundingBox(2, 2, 2, 3, 3, 3))); var tree = BvhTree <int> .CreateNewHierachy(data); Assert.AreEqual(7, tree.CountBranches(), "these must be split up into multiple bounds"); var results = new List <int>(); tree.AlongRay(new Ray(new Vector3(-.5, .5, .5), Vector3.UnitX), results); Assert.AreEqual(results.Count(), 2, "Found all items."); Assert.IsTrue(results.Contains(0), "found the front left point."); Assert.IsTrue(results.Contains(1), "found the front right point."); results.Clear(); tree.AlongRay(new Ray(new Vector3(-.5, 1.5, 1.5), -Vector3.UnitX), results); Assert.AreEqual(results.Count(), 0, "Found no items."); results.Clear(); tree.AlongRay(new Ray(new Vector3(-.5, 1.5, 1.5), Vector3.UnitX), results); Assert.AreEqual(results.Count(), 1, "Found only center."); Assert.IsTrue(results.Contains(4), "found the center point."); results.Clear(); tree.AlongRay(new Ray(new Vector3(-.5, -.5, -.5), new Vector3(1, 1, 1).GetNormal()), results); Assert.AreEqual(results.Count(), 3, "Found all items."); Assert.IsTrue(results.Contains(0), "found the left front bottom."); Assert.IsTrue(results.Contains(4), "found the center."); Assert.IsTrue(results.Contains(8), "found the rigth back top."); results.Clear(); var shortRay = new Ray(new Vector3(-.5, -.5, -.5), new Vector3(1, 1, 1).GetNormal()) { maxDistanceToConsider = 1 }; tree.AlongRay(shortRay, results); Assert.AreEqual(results.Count(), 1, "Found all items."); Assert.IsTrue(results.Contains(0), "found the left front bottom."); }
public void TestBvhClosestIntersection() { // for this shape imagine the 8 corners of a rubics cube and the center var data = new List <BvhTreeItemData <int> >(); // left, front, bottom data.Add(new BvhTreeItemData <int>(0, new AxisAlignedBoundingBox(0, 0, 0, 1, 1, 1))); // right, front, bottom data.Add(new BvhTreeItemData <int>(1, new AxisAlignedBoundingBox(2, 0, 0, 3, 1, 1))); // left, back, bottom data.Add(new BvhTreeItemData <int>(2, new AxisAlignedBoundingBox(0, 2, 0, 1, 3, 1))); // right, back, bottom data.Add(new BvhTreeItemData <int>(3, new AxisAlignedBoundingBox(2, 2, 0, 3, 3, 1))); // center, center, center data.Add(new BvhTreeItemData <int>(4, new AxisAlignedBoundingBox(1, 1, 1, 2, 2, 2))); // left, front, top data.Add(new BvhTreeItemData <int>(5, new AxisAlignedBoundingBox(0, 0, 2, 1, 1, 3))); // right, front, top data.Add(new BvhTreeItemData <int>(6, new AxisAlignedBoundingBox(2, 0, 2, 3, 1, 3))); // left, back, top data.Add(new BvhTreeItemData <int>(7, new AxisAlignedBoundingBox(0, 2, 2, 1, 3, 3))); // right, back, top data.Add(new BvhTreeItemData <int>(8, new AxisAlignedBoundingBox(2, 2, 2, 3, 3, 3))); var tree = BvhTree <int> .CreateNewHierachy(data); Assert.AreEqual(7, tree.CountBranches(), "these must be split up into multiple bounds"); var hitInfo = tree.GetClosestIntersection(new Ray(new Vector3(-.5, .5, .5), Vector3.UnitX)); Assert.IsNotNull(hitInfo, "found a hit"); Assert.AreEqual(0, hitInfo.ClosestHitObject, "found the left front bottom"); Assert.AreEqual(.5, hitInfo.DistanceToHit); Assert.AreEqual(new Vector3(0, .5, .5), hitInfo.HitPosition); Assert.AreEqual(IntersectionType.FrontFace, hitInfo.HitType); Assert.AreEqual(new Vector3(-1, 0, 0), hitInfo.NormalAtHit); hitInfo = tree.GetClosestIntersection(new Ray(new Vector3(3.5, .5, .5), -Vector3.UnitX)); Assert.IsNotNull(hitInfo, "found a hit"); Assert.AreEqual(1, hitInfo.ClosestHitObject, "found the right front bottom"); Assert.AreEqual(.5, hitInfo.DistanceToHit); Assert.AreEqual(new Vector3(3, .5, .5), hitInfo.HitPosition); Assert.AreEqual(IntersectionType.FrontFace, hitInfo.HitType); Assert.AreEqual(new Vector3(1, 0, 0), hitInfo.NormalAtHit); hitInfo = tree.GetClosestIntersection(new Ray(new Vector3(-.5, 1.5, 1.5), -Vector3.UnitX)); Assert.IsNull(hitInfo, "Found no items."); hitInfo = tree.GetClosestIntersection(new Ray(new Vector3(-.5, 1.5, 1.5), Vector3.UnitX)); Assert.AreEqual(4, hitInfo.ClosestHitObject, "Found only center."); Assert.AreEqual(new Vector3(1, 1.5, 1.5), hitInfo.HitPosition); Assert.AreEqual(IntersectionType.FrontFace, hitInfo.HitType); Assert.AreEqual(new Vector3(-1, 0, 0), hitInfo.NormalAtHit); }
public void TestBvhTreeSearches() { // for this shape imagine the 8 corners of a rubics cube and the center var data = new List <BvhTreeItemData <int> >(); // left, front, bottom data.Add(new BvhTreeItemData <int>(0, new AxisAlignedBoundingBox(0, 0, 0, 1, 1, 1))); // right, front, bottom data.Add(new BvhTreeItemData <int>(1, new AxisAlignedBoundingBox(2, 0, 0, 3, 1, 1))); // left, back, bottom data.Add(new BvhTreeItemData <int>(2, new AxisAlignedBoundingBox(0, 2, 0, 1, 3, 1))); // right, back, bottom data.Add(new BvhTreeItemData <int>(3, new AxisAlignedBoundingBox(2, 2, 0, 3, 3, 1))); // center, center, center data.Add(new BvhTreeItemData <int>(4, new AxisAlignedBoundingBox(1, 1, 1, 2, 2, 2))); // left, front, top data.Add(new BvhTreeItemData <int>(5, new AxisAlignedBoundingBox(0, 0, 2, 1, 1, 3))); // right, front, top data.Add(new BvhTreeItemData <int>(6, new AxisAlignedBoundingBox(2, 0, 2, 3, 1, 3))); // left, back, top data.Add(new BvhTreeItemData <int>(7, new AxisAlignedBoundingBox(0, 2, 2, 1, 3, 3))); // right, back, top data.Add(new BvhTreeItemData <int>(8, new AxisAlignedBoundingBox(2, 2, 2, 3, 3, 3))); var tree = BvhTree <int> .CreateNewHierachy(data); Assert.AreEqual(7, tree.CountBranches(), "these must be split up into multiple bounds"); var results = new List <int>(); tree.SearchBounds(new AxisAlignedBoundingBox(0, 0, 0, 3, 3, 3), results); Assert.AreEqual(results.Count(), 9, "Found all items."); results.Clear(); tree.SearchPoint(1.5, 1.5, 1.5, results); Assert.AreEqual(1, results.Count(), "All or around this point."); Assert.AreEqual(4, results[0], "found the center point."); results.Clear(); tree.SearchBounds(new AxisAlignedBoundingBox(1.5, 1.5, 0, 3, 3, 3), results); Assert.AreEqual(3, results.Count(), "All or around this point."); Assert.IsTrue(results.Contains(4), "found the center point."); Assert.IsTrue(results.Contains(8), "found the center point."); Assert.IsTrue(results.Contains(3), "found the center point."); }
public void TestBvhSimpleTreeSearches() { var data = new List <BvhTreeItemData <int> >(); data.Add(new BvhTreeItemData <int>(1, new AxisAlignedBoundingBox(-10, -20, -30, 10, 20, 30))); data.Add(new BvhTreeItemData <int>(2, new AxisAlignedBoundingBox(-9, -18, -29, 9, 19, 29))); data.Add(new BvhTreeItemData <int>(3, new AxisAlignedBoundingBox(-9, -17, -29, 9, 19, 28))); data.Add(new BvhTreeItemData <int>(4, new AxisAlignedBoundingBox(-9, -16, -29, 9, 19, 27))); var tree = BvhTree <int> .CreateNewHierachy(data); Assert.IsTrue(tree.CountBranches() == 1, "all the bounds overlap, there is no value in splitting them up"); var results = new List <int>(); tree.SearchBounds(new AxisAlignedBoundingBox(-9, -19, -29, 9, 19, 29), results); Assert.AreEqual(results.Count(), 4, "Found all items."); results.Clear(); tree.SearchPoint(0, 0, 0, results); Assert.AreEqual(4, results.Count(), "All or around this point."); }
public void MergeVertices(double treatAsSameDistance) { if (Vertices.Count < 2) { return; } var sameDistance = new Vector3Float(treatAsSameDistance, treatAsSameDistance, treatAsSameDistance); var tinyDistance = new Vector3Float(.001, .001, .001); // build a bvh tree of all the vertices var bvhTree = BvhTree <int> .CreateNewHierachy(this.Vertices .Select((v, i) => new BvhTreeItemData <int>(i, new AxisAlignedBoundingBox(v - tinyDistance, v + tinyDistance))).ToList()); var newVertices = new List <Vector3Float>(Vertices.Count); var vertexIndexRemaping = Enumerable.Range(0, Vertices.Count).Select(i => - 1).ToList(); var searchResults = new List <int>(); // build up the list of index mapping for (int i = 0; i < Vertices.Count; i++) { // first check if we have already found this vertex if (vertexIndexRemaping[i] == -1) { var vertex = Vertices[i]; // remember the new index var newIndex = newVertices.Count; // add it to the vertices we will end up with newVertices.Add(vertex); // clear for new search searchResults.Clear(); // find everything close bvhTree.SearchBounds(new AxisAlignedBoundingBox(vertex - sameDistance, vertex + sameDistance), searchResults); // map them to this new vertex foreach (var result in searchResults) { // this vertex has not been mapped if (vertexIndexRemaping[result] == -1) { vertexIndexRemaping[result] = newIndex; } } } } // now make a new face list with the merge vertices int GetIndex(int originalIndex) { return(vertexIndexRemaping[originalIndex]); } var newFaces = new FaceList(); foreach (var face in Faces) { int iv0 = GetIndex(face.v0); int iv1 = GetIndex(face.v1); int iv2 = GetIndex(face.v2); if (iv0 != iv1 && iv1 != iv2 && iv2 != iv0) { newFaces.Add(iv0, iv1, iv2, newVertices); } } this.Faces = newFaces; this.Vertices = newVertices; }