public void PolygonHitTests() { SolidMaterial redStuff = new SolidMaterial(new RGBA_Floats(1, 0, 0), 0, 0, 2); { TriangleShape facingPositiveX = new TriangleShape(new Vector3(0, 1, -1), new Vector3(0, 0, 1), new Vector3(0, -1, -1), redStuff); IntersectInfo positiveXInfo = facingPositiveX.GetClosestIntersection(new Ray(new Vector3(1, 0, 0), new Vector3(-1, 0, 0))); Assert.IsTrue(positiveXInfo.hitPosition == new Vector3(0, 0, 0)); Assert.IsTrue(positiveXInfo.hitType == IntersectionType.FrontFace); Assert.IsTrue(positiveXInfo.closestHitObject == facingPositiveX); Assert.IsTrue(positiveXInfo.distanceToHit == 1); IntersectInfo negativeXInfo = facingPositiveX.GetClosestIntersection(new Ray(new Vector3(-1, 0, 0), new Vector3(1, 0, 0))); Assert.IsTrue(negativeXInfo == null); } { TriangleShape facingNegativeX = new TriangleShape(new Vector3(0, -1, -1), new Vector3(0, 0, 1), new Vector3(0, 1, -1), redStuff); IntersectInfo positiveXInfo = facingNegativeX.GetClosestIntersection(new Ray(new Vector3(1, 0, 0), new Vector3(-1, 0, 0))); Assert.IsTrue(positiveXInfo == null); IntersectInfo negativeXInfo = facingNegativeX.GetClosestIntersection(new Ray(new Vector3(-1, 0, 0), new Vector3(1, 0, 0))); Assert.IsTrue(negativeXInfo.hitPosition == new Vector3(0, 0, 0)); Assert.IsTrue(negativeXInfo.hitType == IntersectionType.FrontFace); Assert.IsTrue(negativeXInfo.closestHitObject == facingNegativeX); Assert.IsTrue(negativeXInfo.distanceToHit == 1); } }
public void TriangleMajorAxis() { var triangle0 = new TriangleShape( new Vector3(-47.06726, 16.94526, 1.143421), new Vector3(-30.66048, 39.52726, 1.143422), new Vector3(-45.91038, 19.8672, 1.143422), null); Assert.AreEqual(2, triangle0.MajorAxis); var triangle1 = new TriangleShape( new Vector3(0, 1, 0), new Vector3(0, 0, 1), new Vector3(0, 0, 0), null); Assert.AreEqual(0, triangle1.MajorAxis); var triangle2 = new TriangleShape( new Vector3(1, 0, 0), new Vector3(0, 0, 1), new Vector3(0, 0, 0), null); Assert.AreEqual(1, triangle2.MajorAxis); }
public void EnumerateBvh() { // create a bvh hierarchy var level4_a = new TriangleShape(new Vector3(0, 0, 1), new Vector3(0, 0, 3), new Vector3(0, 1, 2), null); var level4_b = new TriangleShape(new Vector3(0, 0, 11), new Vector3(0, 0, 13), new Vector3(0, 1, 12), null); var level4_c = new TriangleShape(new Vector3(3, 0, 1), new Vector3(3, 0, 3), new Vector3(3, 1, 2), null); var level3_a = new UnboundCollection(new List <ITraceable>() { level4_a, level4_b, level4_c }); var level3_b = new TriangleShape(new Vector3(43, 0, 1), new Vector3(43, 0, 3), new Vector3(43, 1, 2), null); var level2_a = new Transform(level3_a, Matrix4X4.CreateTranslation(0, 0, 40)); var level2_b = new Transform(level3_b, Matrix4X4.CreateTranslation(0, 40, 0)); var level1 = new UnboundCollection(new List <ITraceable>() { level2_a, level2_b }); var root = new Transform(level1); // enumerate it and check it Assert.AreEqual(9, new BvhIterator(root).Count()); int count = 0; foreach (var item in new BvhIterator(root)) { switch (count++) { case 0: Assert.IsTrue(item.Bvh is Transform); Assert.AreEqual(0, item.Depth); Assert.AreEqual(Matrix4X4.CreateTranslation(0, 0, 0), item.TransformToWorld); break; case 1: Assert.IsTrue(item.Bvh is UnboundCollection); Assert.AreEqual(1, item.Depth); Assert.AreEqual(Matrix4X4.CreateTranslation(0, 0, 0), item.TransformToWorld); break; case 2: Assert.IsTrue(item.Bvh is Transform); Assert.AreEqual(2, item.Depth); Assert.AreEqual(Matrix4X4.CreateTranslation(0, 0, 0), item.TransformToWorld); break; case 3: Assert.IsTrue(item.Bvh is UnboundCollection); Assert.AreEqual(3, item.Depth); Assert.AreEqual(Matrix4X4.CreateTranslation(0, 0, 40), item.TransformToWorld); break; case 4: Assert.IsTrue(item.Bvh is TriangleShape); Assert.AreEqual(4, item.Depth); Assert.AreEqual(Matrix4X4.CreateTranslation(0, 0, 40), item.TransformToWorld); break; case 5: Assert.IsTrue(item.Bvh is TriangleShape); Assert.AreEqual(4, item.Depth); Assert.AreEqual(Matrix4X4.CreateTranslation(0, 0, 40), item.TransformToWorld); break; case 6: Assert.IsTrue(item.Bvh is TriangleShape); Assert.AreEqual(4, item.Depth); Assert.AreEqual(Matrix4X4.CreateTranslation(0, 0, 40), item.TransformToWorld); break; case 7: Assert.IsTrue(item.Bvh is Transform); Assert.AreEqual(2, item.Depth); Assert.AreEqual(Matrix4X4.CreateTranslation(0, 0, 0), item.TransformToWorld); break; case 8: Assert.IsTrue(item.Bvh is TriangleShape); Assert.AreEqual(3, item.Depth); Assert.AreEqual(Matrix4X4.CreateTranslation(0, 40, 0), item.TransformToWorld); break; } } }
public static void CreateITraceableForMesh(List<PlatingMeshData> perMeshInfo, List<Mesh> meshes, int i) { if (meshes[i] != null) { List<IRayTraceable> allPolys = new List<IRayTraceable>(); List<Vector3> positions = new List<Vector3>(); foreach (Face face in meshes[i].Faces) { positions.Clear(); foreach (Vertex vertex in face.Vertices()) { positions.Add(vertex.Position); } // We should use the teselator for this if it is greater than 3. Vector3 next = positions[1]; for (int positionIndex = 2; positionIndex < positions.Count; positionIndex++) { TriangleShape triangel = new TriangleShape(positions[0], next, positions[positionIndex], null); allPolys.Add(triangel); next = positions[positionIndex]; } } perMeshInfo[i].traceableData = BoundingVolumeHierarchy.CreateNewHierachy(allPolys); } }
private void CalculateIntersectCostsAndSaveToFile() { int numInterations = 5000000; AxisAlignedBoundingBox referenceCostObject = new AxisAlignedBoundingBox(new Vector3(-.5, -.5, -.5), new Vector3(.5, .5, .5)); Stopwatch timer = new Stopwatch(); Vector3 accumulation = new Vector3(); timer.Start(); for (int i = 0; i < numInterations; i++) { accumulation += GetRandomIntersectingRay().directionNormal; } long notIntersectStuff = timer.ElapsedMilliseconds; timer.Restart(); for (int i = 0; i < numInterations; i++) { GetRandomIntersectingRay().Intersection(referenceCostObject); } long referenceMiliseconds = timer.ElapsedMilliseconds; SolidMaterial material = new SolidMaterial(RGBA_Floats.Black, 0, 0, 1); long sphereMiliseconds = CalculateIntersectCostsForItem(new SphereShape(new Vector3(), .5, material), numInterations); long cylinderMiliseconds = CalculateIntersectCostsForItem(new CylinderShape(.5, 1, material), numInterations); long boxMiliseconds = CalculateIntersectCostsForItem(new BoxShape(new Vector3(-.5, -.5, -.5), new Vector3(.5, .5, .5), material), numInterations); long planeMiliseconds = CalculateIntersectCostsForItem(new PlaneShape(new Vector3(0, 0, 1), 0, material), numInterations); BaseShape triangleTest = new TriangleShape(new Vector3(-1, 0, 0), new Vector3(0, 1, 0), new Vector3(0, 0, 0), material); long triangleMiliseconds = CalculateIntersectCostsForItem(triangleTest, numInterations); System.IO.File.WriteAllText("Cost Of Primitive.txt", "Cost of Primitives" + "\r\n" + numInterations.ToString("N0") + " intersections per primitive." + "\r\nTest Overhead: " + notIntersectStuff.ToString() + GetStringForFile("AABB", referenceMiliseconds, notIntersectStuff) + GetStringForFile("Sphere", sphereMiliseconds, notIntersectStuff) + GetStringForFile("Cylider", cylinderMiliseconds, notIntersectStuff) + GetStringForFile("Box", boxMiliseconds, notIntersectStuff) + GetStringForFile("Plane", planeMiliseconds, notIntersectStuff) + GetStringForFile("Triangle", triangleMiliseconds, notIntersectStuff) ); }
private static List<IPrimitive> AddTraceDataForMesh(Mesh mesh, int totalActionCount, ref int currentAction, ref bool needToUpdateProgressReport, ReportProgressRatio reportProgress) { bool continueProcessing; List<IPrimitive> allPolys = new List<IPrimitive>(); List<Vector3> positions = new List<Vector3>(); foreach (Face face in mesh.Faces) { positions.Clear(); foreach (Vertex vertex in face.Vertices()) { positions.Add(vertex.Position); } // We should use the teselator for this if it is greater than 3. Vector3 next = positions[1]; for (int positionIndex = 2; positionIndex < positions.Count; positionIndex++) { TriangleShape triangel = new TriangleShape(positions[0], next, positions[positionIndex], null); allPolys.Add(triangel); next = positions[positionIndex]; } if (reportProgress != null) { if ((currentAction % 256) == 0 || needToUpdateProgressReport) { reportProgress(currentAction / (double)totalActionCount, "Creating Trace Polygons", out continueProcessing); needToUpdateProgressReport = false; } currentAction++; } } return allPolys; }