Exemple #1
0
        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);
            }
        }
Exemple #2
0
        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 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 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;
		}