Beispiel #1
0
        public void SerializationBinary()
        {
            var a = new TriangleMesh();

            a.Add(new Triangle(new Vector3(0, 1, 2), new Vector3(3, 4, 5), new Vector3(6, 7, 8)), false);
            a.Add(new Triangle(new Vector3(-0, -1, -2), new Vector3(-3, -4, -5), new Vector3(-6, -7, -8)), false);

            // Serialize object.
            var stream    = new MemoryStream();
            var formatter = new BinaryFormatter();

            formatter.Serialize(stream, a);

            // Deserialize object.
            stream.Position = 0;
            var deserializer = new BinaryFormatter();
            var b            = (TriangleMesh)deserializer.Deserialize(stream);

            Assert.AreEqual(a.NumberOfTriangles, b.NumberOfTriangles);
            for (int i = 0; i < a.Vertices.Count; i++)
            {
                Assert.AreEqual(a.Vertices[i], b.Vertices[i]);
            }
            for (int i = 0; i < a.Indices.Count; i++)
            {
                Assert.AreEqual(a.Indices[i], b.Indices[i]);
            }
        }
Beispiel #2
0
        public void SerializationXml()
        {
            var a = new TriangleMesh();

            a.Add(new Triangle(new Vector3(0, 1, 2), new Vector3(3, 4, 5), new Vector3(6, 7, 8)), true);
            a.Add(new Triangle(new Vector3(-0, -1, -2), new Vector3(-3, -4, -5), new Vector3(-6, -7, -8)), true);


            // Serialize object.
            var stream     = new MemoryStream();
            var serializer = new XmlSerializer(typeof(TriangleMesh));

            serializer.Serialize(stream, a);

            // Output generated xml. Can be manually checked in output window.
            stream.Position = 0;
            var xml = new StreamReader(stream).ReadToEnd();

            Trace.WriteLine("Serialized Object:\n" + xml);

            // Deserialize object.
            stream.Position = 0;
            var deserializer = new XmlSerializer(typeof(TriangleMesh));
            var b            = (TriangleMesh)deserializer.Deserialize(stream);

            Assert.AreEqual(a.NumberOfTriangles, b.NumberOfTriangles);
            for (int i = 0; i < a.Vertices.Count; i++)
            {
                Assert.AreEqual(a.Vertices[i], b.Vertices[i]);
            }
            for (int i = 0; i < a.Indices.Count; i++)
            {
                Assert.AreEqual(a.Indices[i], b.Indices[i]);
            }
        }
Beispiel #3
0
        public void ComputeCollision()
        {
            CollisionObject a    = new CollisionObject();
            TriangleMesh    mesh = new TriangleMesh();

            mesh.Add(new Triangle(new Vector3F(0, 0, 0), new Vector3F(0, 0, 1), new Vector3F(1, 0, 0)), false);
            mesh.Add(new Triangle(new Vector3F(1, 0, 0), new Vector3F(0, 0, 1), new Vector3F(1, 0, 1)), false);
            TriangleMeshShape meshShape = new TriangleMeshShape();

            meshShape.Mesh    = mesh;
            a.GeometricObject = new GeometricObject(meshShape, Pose.Identity);

            CollisionObject b = new CollisionObject(new GeometricObject
            {
                Shape = new SphereShape(1),
                Pose  = new Pose(new Vector3F(0, 0.9f, 0)),
            });

            ContactSet            set;
            TriangleMeshAlgorithm algo = new TriangleMeshAlgorithm(new CollisionDetection());

            set = algo.GetClosestPoints(a, b);
            Assert.AreEqual(true, algo.HaveContact(a, b));
            Assert.AreEqual(true, algo.HaveContact(b, a));
            Assert.AreEqual(1, set.Count);
            Assert.IsTrue(Numeric.AreEqual(0.1f, set[0].PenetrationDepth, 0.001f));
            //Assert.IsTrue(Vector3F.AreNumericallyEqual(new Vector3F(0, 0, 0), set[0].PositionALocal, 0.01f));  // MPR will not return the perfect contact point.
            Assert.IsTrue(Vector3F.AreNumericallyEqual(new Vector3F(0, 1, 0), set[0].Normal, 0.1f));

            ((GeometricObject)b.GeometricObject).Pose = new Pose(new Vector3F(0.1f, 0.9f, 0.1f));
            algo.UpdateContacts(set, 0);
            Assert.AreEqual(true, algo.HaveContact(a, b));
            Assert.AreEqual(true, algo.HaveContact(b, a));
            Assert.AreEqual(1, set.Count);
            Assert.IsTrue(Numeric.AreEqual(0.1f, set[0].PenetrationDepth, 0.001f));
            Assert.IsTrue(Vector3F.AreNumericallyEqual(new Vector3F(0.1f, 0, 0.1f), set[0].PositionALocal, 0.01f));
            Assert.IsTrue(Vector3F.AreNumericallyEqual(new Vector3F(0, 1, 0), set[0].Normal, 0.1f));

            // The same with a swapped set.
            set = set.Swapped;
            algo.UpdateContacts(set, 0);
            Assert.AreEqual(1, set.Count);
            Assert.IsTrue(Numeric.AreEqual(0.1f, set[0].PenetrationDepth, 0.001f));
            Assert.IsTrue(Vector3F.AreNumericallyEqual(new Vector3F(0.1f, 0, 0.1f), set[0].PositionBLocal, 0.01f));
            Assert.IsTrue(Vector3F.AreNumericallyEqual(new Vector3F(0, -1, 0), set[0].Normal, 0.1f));

            // Separation.
            ((GeometricObject)b.GeometricObject).Pose = new Pose(new Vector3F(0.2f, 1.2f, 0.3f));
            set = set.Swapped;
            Assert.AreEqual(false, algo.HaveContact(a, b));
            Assert.AreEqual(false, algo.HaveContact(b, a));
            algo.UpdateClosestPoints(set, 0);
            Assert.IsTrue(Numeric.AreEqual(-0.2f, set[0].PenetrationDepth, 0.001f));
            Assert.IsTrue(Vector3F.AreNumericallyEqual(new Vector3F(0.2f, 0, 0.3f), set[0].PositionALocal, 0.01f));
            Assert.IsTrue(Vector3F.AreNumericallyEqual(new Vector3F(0, 1, 0), set[0].Normal, 0.1f));
            algo.UpdateContacts(set, 0);
            Assert.AreEqual(0, set.Count);
        }
Beispiel #4
0
        public void AddMesh()
        {
            TriangleMesh mesh = new TriangleMesh();
              mesh.Add(new Triangle(new Vector3F(0, 0, 0), new Vector3F(1, 1, 1), new Vector3F(1, 0, 2)), true);
              mesh.Add(new Triangle(new Vector3F(0, 1, 0), new Vector3F(1, 2, 1), new Vector3F(1, 1, 1)), true);

              var mesh2 = new TriangleMesh();
              mesh2.Add(new Triangle(new Vector3F(0, 0, 0), new Vector3F(1, 1, 1), new Vector3F(1, 0, 1)), true);

              mesh2.Add(mesh, true);
              Assert.AreEqual(3, mesh2.NumberOfTriangles);
              Assert.AreEqual(new Triangle(new Vector3F(0, 1, 0), new Vector3F(1, 2, 1), new Vector3F(1, 1, 1)), mesh2.GetTriangle(2));
        }
Beispiel #5
0
        public void Transform()
        {
            var mesh = new TriangleMesh();

            mesh.Add(new Triangle(new Vector3(0, 1, 2), new Vector3(3, 4, 5), new Vector3(6, 7, 8)), true);
            mesh.Add(new Triangle(new Vector3(-0, -1, -2), new Vector3(-3, -4, -5), new Vector3(-6, -7, -8)), true);

            var trans = RandomHelper.Random.NextMatrix(-1, 1);

            mesh.Transform(trans);

            Assert.AreEqual(trans.TransformPosition(new Vector3(0, 1, 2)), mesh.Vertices[0]);
            Assert.AreEqual(trans.TransformPosition(new Vector3(-6, -7, -8)), mesh.Vertices[5]);
        }
Beispiel #6
0
        public void AddMesh()
        {
            TriangleMesh mesh = new TriangleMesh();

            mesh.Add(new Triangle(new Vector3(0, 0, 0), new Vector3(1, 1, 1), new Vector3(1, 0, 2)), true);
            mesh.Add(new Triangle(new Vector3(0, 1, 0), new Vector3(1, 2, 1), new Vector3(1, 1, 1)), true);

            var mesh2 = new TriangleMesh();

            mesh2.Add(new Triangle(new Vector3(0, 0, 0), new Vector3(1, 1, 1), new Vector3(1, 0, 1)), true);

            mesh2.Add(mesh, true);
            Assert.AreEqual(3, mesh2.NumberOfTriangles);
            Assert.AreEqual(new Triangle(new Vector3(0, 1, 0), new Vector3(1, 2, 1), new Vector3(1, 1, 1)), mesh2.GetTriangle(2));
        }
Beispiel #7
0
        /// <summary>
        /// Called when a mesh should be generated for the shape.
        /// </summary>
        /// <param name="absoluteDistanceThreshold">The absolute distance threshold.</param>
        /// <param name="iterationLimit">The iteration limit.</param>
        /// <returns>The triangle mesh for this shape.</returns>
        protected override TriangleMesh OnGetMesh(float absoluteDistanceThreshold, int iterationLimit)
        {
            TriangleMesh mesh = new TriangleMesh();

            mesh.Add(new Triangle(this), true);
            return(mesh);
        }
        /// <summary>
        /// Called when a mesh should be generated for the shape.
        /// </summary>
        /// <param name="absoluteDistanceThreshold">The absolute distance threshold.</param>
        /// <param name="iterationLimit">The iteration limit.</param>
        /// <returns>The triangle mesh for this shape.</returns>
        protected override TriangleMesh OnGetMesh(float absoluteDistanceThreshold, int iterationLimit)
        {
            // Convert absolute error to relative error.
            float maxExtent         = GetAabb(Vector3.One, Pose.Identity).Extent.LargestComponent;
            float relativeThreshold = !Numeric.IsZero(maxExtent)
                                ? absoluteDistanceThreshold / maxExtent
                                : Numeric.EpsilonF;

            // Get meshes of children and add them to mesh in parent space.
            TriangleMesh mesh = new TriangleMesh();
            int          numberOfGeometries = Children.Count;

            for (int childIndex = 0; childIndex < numberOfGeometries; childIndex++)
            {
                IGeometricObject geometricObject = Children[childIndex];

                // Get child mesh.
                var childMesh = geometricObject.Shape.GetMesh(relativeThreshold, iterationLimit);

                // Transform child mesh into local space of this parent shape.
                childMesh.Transform(geometricObject.Pose.ToMatrix() * Matrix.CreateScale(geometricObject.Scale));

                // Add to parent mesh.
                mesh.Add(childMesh, false);
            }

            return(mesh);
        }
Beispiel #9
0
        /// <summary>
        /// Called when a mesh should be generated for the shape.
        /// </summary>
        /// <param name="absoluteDistanceThreshold">The absolute distance threshold.</param>
        /// <param name="iterationLimit">The iteration limit.</param>
        /// <returns>The triangle mesh for this shape.</returns>
        protected override TriangleMesh OnGetMesh(float absoluteDistanceThreshold, int iterationLimit)
        {
            // Estimate required segment angle for given accuracy.
            // (Easy to derive from simple drawing of a circle segment with a triangle used to represent
            // the segment.)
            float alpha            = (float)Math.Acos((_radius - absoluteDistanceThreshold) / _radius) * 2;
            int   numberOfSegments = (int)Math.Ceiling(ConstantsF.TwoPi / alpha);

            alpha = ConstantsF.TwoPi / numberOfSegments;

            Vector3    r0       = new Vector3(_radius, 0, 0);
            Quaternion rotation = Quaternion.CreateRotationZ(alpha);

            TriangleMesh mesh = new TriangleMesh();

            for (int i = 1; i <= numberOfSegments; i++)
            {
                Vector3 r1 = rotation.Rotate(r0);

                mesh.Add(new Triangle
                {
                    Vertex0 = Vector3.Zero,
                    Vertex1 = r0,
                    Vertex2 = r1,
                }, true);
                r0 = r1;
            }

            return(mesh);
        }
Beispiel #10
0
        public void ComputeCollisionBvh()
        {
            CollisionObject a     = new CollisionObject();
            TriangleMesh    meshA = new TriangleMesh();

            meshA.Add(new Triangle(new Vector3F(0, 0, 0), new Vector3F(0, 0, 1), new Vector3F(1, 0, 0)), false);
            var meshShapeA = new TriangleMeshShape();

            meshShapeA.Mesh      = meshA;
            meshShapeA.Partition = new AabbTree <int>();
            ((GeometricObject)a.GeometricObject).Shape = meshShapeA;

            CollisionObject b     = new CollisionObject();
            TriangleMesh    meshB = new TriangleMesh();

            meshB.Add(new Triangle(new Vector3F(2, 0, 0), new Vector3F(2, 0, 1), new Vector3F(3, 0, 0)), false);
            TriangleMeshShape meshShapeB = new TriangleMeshShape();

            meshShapeB.Mesh      = meshB;
            meshShapeB.Partition = new AabbTree <int>();
            ((GeometricObject)b.GeometricObject).Shape = meshShapeB;
            ((GeometricObject)b.GeometricObject).Pose  = new Pose(new Vector3F(-2, 0, 0));

            CollisionAlgorithm algo = new TriangleMeshAlgorithm(new CollisionDetection());

            Assert.AreEqual(true, algo.HaveContact(a, b));
        }
Beispiel #11
0
        public void AddTriangleShouldRemoveDegenerateTriangle2()
        {
            var mesh = new TriangleMesh();

            mesh.Add(new Triangle(new Vector3(1, 1, 1), new Vector3(1, 1, 1), new Vector3(1, 1, 1.000001f)), false, 0.001f, true);
            Assert.AreEqual(0, mesh.NumberOfTriangles);
        }
Beispiel #12
0
        public void GetTriangleException2()
        {
            TriangleMesh mesh = new TriangleMesh();

            mesh.Add(new Triangle(new Vector3(0, 0, 0), new Vector3(1, 1, 1), new Vector3(1, 0, 1)), false);
            mesh.GetTriangle(1);
        }
Beispiel #13
0
        public void WeldVertices()
        {
            TriangleMesh mesh = new TriangleMesh();

            Assert.AreEqual(0, mesh.WeldVertices());

            mesh.Add(new Triangle(new Vector3(1, 2, 3), new Vector3(3, 4, 5), new Vector3(1.00001f, 2.00001f, 3f)), false);

            Assert.AreEqual(3, mesh.Vertices.Count);

            Assert.Throws(typeof(ArgumentOutOfRangeException), () => mesh.WeldVertices(-0.1f));

            Assert.AreEqual(1, mesh.WeldVertices(0.0001f));
            Assert.AreEqual(2, mesh.Vertices.Count);

            var w = Stopwatch.StartNew();

            mesh = new SphereShape(0.5f).GetMesh(0.001f, 7);
            w.Stop();
            //Assert.AreEqual(0, w.Elapsed.TotalMilliseconds);

            for (int i = 0; i < mesh.Vertices.Count; i++)
            {
                for (int j = i + 1; j < mesh.Vertices.Count; j++)
                {
                    Assert.IsFalse(Vector3.AreNumericallyEqual(mesh.Vertices[i], mesh.Vertices[j]));
                }
            }

            // Second time does nothing.
            Assert.AreEqual(0, mesh.WeldVertices());
        }
Beispiel #14
0
        /// <summary>
        /// Called when a mesh should be generated for the shape.
        /// </summary>
        /// <param name="absoluteDistanceThreshold">The absolute distance threshold.</param>
        /// <param name="iterationLimit">The iteration limit.</param>
        /// <returns>The triangle mesh for this shape.</returns>
        protected override TriangleMesh OnGetMesh(float absoluteDistanceThreshold, int iterationLimit)
        {
            // Estimate required segment angle for given accuracy.
            // (Easy to derive from simple drawing of a circle segment with a triangle used to represent
            // the segment.)
            float alpha            = (float)Math.Acos((_radius - absoluteDistanceThreshold) / _radius) * 2;
            int   numberOfSegments = (int)Math.Ceiling(ConstantsF.TwoPi / alpha);

            // Apply the iteration limit - in case absoluteDistanceThreshold is 0.
            // Lets say each iteration doubles the number of segments. This is an arbitrary interpretation
            // of the "iteration limit".
            numberOfSegments = Math.Min(numberOfSegments, 2 << iterationLimit);

            alpha = ConstantsF.TwoPi / numberOfSegments;

            Vector3    r0       = new Vector3(_radius, 0, 0);
            Vector3    tip      = new Vector3(0, _height, 0);
            Quaternion rotation = Quaternion.CreateRotationY(alpha);

            TriangleMesh mesh = new TriangleMesh();

            for (int i = 1; i <= numberOfSegments; i++)
            {
                Vector3 r1 = rotation.Rotate(r0);

                // Bottom triangle
                mesh.Add(new Triangle
                {
                    Vertex0 = Vector3.Zero,
                    Vertex1 = r1,
                    Vertex2 = r0,
                }, false);

                // Side triangle
                mesh.Add(new Triangle
                {
                    Vertex0 = r0,
                    Vertex1 = r1,
                    Vertex2 = tip,
                }, false);
                r0 = r1;
            }

            mesh.WeldVertices();

            return(mesh);
        }
Beispiel #15
0
        /// <summary>
        /// Converts mesh content to model content with a <see cref="TriangleMeshShape"/>.
        /// </summary>
        /// <param name="input">The root node content.</param>
        /// <param name="context">Context for the specified processor.</param>
        /// <returns>The <see cref="Shape"/>.</returns>
        public override DRModelNodeContent Process(NodeContent input, ContentProcessorContext context)
        {
            // ----- Process Model
            var model = base.Process(input, context);

            // ----- Extract Triangles
            var triangleMesh = new TriangleMesh();

            // The input node is usually a tree of nodes. We need to collect all MeshContent nodes
            // in the tree. The DigitalRune Helper library provides a TreeHelper that can be used
            // to traverse trees using LINQ.
            // The following returns an IEnumerable that returns all nodes of the tree.
            var nodes = TreeHelper.GetSubtree(input, n => n.Children);

            // We only need nodes of type MeshContent.
            var meshes = nodes.OfType <MeshContent>();

            foreach (var mesh in meshes)
            {
                // Apply any transformations to vertices.
                Matrix transform = mesh.AbsoluteTransform;
                for (int i = 0; i < mesh.Positions.Count; i++)
                {
                    mesh.Positions[i] = Vector3.Transform(mesh.Positions[i], transform);
                }

                // Extract triangles from submeshes.
                foreach (var geometry in mesh.Geometry)
                {
                    int numberOfTriangles = geometry.Indices.Count / 3;
                    for (int i = 0; i < numberOfTriangles; i++)
                    {
                        int index0 = geometry.Indices[3 * i + 0];
                        int index1 = geometry.Indices[3 * i + 2]; // Note: DigitalRune Geometry uses a different winding
                        int index2 = geometry.Indices[3 * i + 1]; // order. Therefore, the indices need to be swapped.

                        Vector3F vertex0 = (Vector3F)geometry.Vertices.Positions[index0];
                        Vector3F vertex1 = (Vector3F)geometry.Vertices.Positions[index1];
                        Vector3F vertex2 = (Vector3F)geometry.Vertices.Positions[index2];

                        triangleMesh.Add(new Triangle(vertex0, vertex1, vertex2), false, Numeric.EpsilonF, true);
                    }
                }
            }

            // Remove duplicate vertices.
            triangleMesh.WeldVertices();

            // ----- Create TriangleMeshShape
            // Create a TriangleMeshShape that can be used for collision detection.
            // Note:
            // - Contact-welding is enabled to improve the results of the collision detection.
            // - A CompressedAabbTree is used for spatial partitioning to speed up collision detection.
            var triangleMeshShape = new TriangleMeshShape(triangleMesh, true, new CompressedAabbTree());

            // Export the ModelNode together with the TriangleMeshShape.
            model.UserData = triangleMeshShape;
            return(model);
        }
Beispiel #16
0
        /// <summary>
        /// Called when a mesh should be generated for the shape.
        /// </summary>
        /// <param name="absoluteDistanceThreshold">The absolute distance threshold.</param>
        /// <param name="iterationLimit">The iteration limit.</param>
        /// <returns>The triangle mesh for this shape.</returns>
        protected override TriangleMesh OnGetMesh(float absoluteDistanceThreshold, int iterationLimit)
        {
            TriangleMesh mesh = new TriangleMesh();

            mesh.Add(new Triangle
            {
                Vertex0 = new Vector3F(_widthX / 2, _widthY / 2, 0),
                Vertex1 = new Vector3F(-_widthX / 2, _widthY / 2, 0),
                Vertex2 = new Vector3F(-_widthX / 2, -_widthY / 2, 0),
            }, true);
            mesh.Add(new Triangle
            {
                Vertex0 = new Vector3F(-_widthX / 2, -_widthY / 2, 0),
                Vertex1 = new Vector3F(_widthX / 2, -_widthY / 2, 0),
                Vertex2 = new Vector3F(_widthX / 2, _widthY / 2, 0),
            }, true);
            return(mesh);
        }
Beispiel #17
0
        public void Clone()
        {
            var mesh = new TriangleMesh();
              mesh.Add(new Triangle(new Vector3F(0, 1, 2), new Vector3F(3, 4, 5), new Vector3F(6, 7, 8)), true);
              mesh.Add(new Triangle(new Vector3F(-0, -1, -2), new Vector3F(-3, -4, -5), new Vector3F(-6, -7, -8)), true);
              mesh.Tag = new SphereShape(3);

              var clone = mesh.Clone();

              Assert.AreEqual(mesh.NumberOfTriangles, clone.NumberOfTriangles);
              Assert.AreEqual(mesh.GetTriangle(0), clone.GetTriangle(0));
              Assert.AreEqual(mesh.GetTriangle(1), clone.GetTriangle(1));
              Assert.AreSame(mesh.Tag, clone.Tag);

              mesh.Tag = new MemoryStream();
              clone = mesh.Clone();
              Assert.AreSame(mesh.Tag, clone.Tag);
        }
Beispiel #18
0
        public void Clone()
        {
            var mesh = new TriangleMesh();

            mesh.Add(new Triangle(new Vector3(0, 1, 2), new Vector3(3, 4, 5), new Vector3(6, 7, 8)), true);
            mesh.Add(new Triangle(new Vector3(-0, -1, -2), new Vector3(-3, -4, -5), new Vector3(-6, -7, -8)), true);
            mesh.Tag = new SphereShape(3);

            var clone = mesh.Clone();

            Assert.AreEqual(mesh.NumberOfTriangles, clone.NumberOfTriangles);
            Assert.AreEqual(mesh.GetTriangle(0), clone.GetTriangle(0));
            Assert.AreEqual(mesh.GetTriangle(1), clone.GetTriangle(1));
            Assert.AreSame(mesh.Tag, clone.Tag);

            mesh.Tag = new MemoryStream();
            clone    = mesh.Clone();
            Assert.AreSame(mesh.Tag, clone.Tag);
        }
Beispiel #19
0
        public void Validate6()
        {
            GlobalSettings.ValidationLevel = 0xff;
            var scene = new Scene();
            // This is allowed.
            var n = new TestSceneNode {
                Shape = Shape.Empty
            };

            scene.Children.Add(n);

            // Invalid changes of already added node:
            var mesh = new TriangleMesh();

            mesh.Add(new Triangle(new Vector3F(1), new Vector3F(2), new Vector3F(3)));
            mesh.Add(new Triangle(new Vector3F(4), new Vector3F(float.NaN, 5, 5), new Vector3F(6)));
            var meshShape = new TriangleMeshShape(mesh);

            Assert.Throws <GraphicsException>(() => n.Shape = meshShape);
        }
Beispiel #20
0
        public void AddTriangleWithoutMergingAndWithDestroyedLists()
        {
            var mesh = new TriangleMesh();

            // Destroy lists.
            mesh.Vertices = null;
            mesh.Indices  = null;
            Assert.AreEqual(0, mesh.NumberOfTriangles);

            mesh.Add(new Triangle(new Vector3(1, 1, 1), new Vector3(1, 1, 1), new Vector3(1, 1, 1.000001f)), false, 0.001f, false);
            Assert.AreEqual(3, mesh.Vertices.Count);
        }
Beispiel #21
0
    public static Submesh CreateSubmesh(GraphicsDevice graphicsDevice, ITriangleMesh mesh, float angleLimit)
    {
      var tm = mesh as TriangleMesh;
      if (tm == null)
      {
        tm = new TriangleMesh();
        tm.Add(mesh);
        tm.WeldVertices();
      }

      return CreateSubmesh(graphicsDevice, tm, angleLimit);
    }
Beispiel #22
0
        public void AddTriangleWithoutMergingAndWithDestroyedLists()
        {
            var mesh = new TriangleMesh();

              // Destroy lists.
              mesh.Vertices = null;
              mesh.Indices = null;
              Assert.AreEqual(0, mesh.NumberOfTriangles);

              mesh.Add(new Triangle(new Vector3F(1, 1, 1), new Vector3F(1, 1, 1), new Vector3F(1, 1, 1.000001f)), false, 0.001f, false);
              Assert.AreEqual(3, mesh.Vertices.Count);
        }
Beispiel #23
0
        /// <summary>
        /// Called when a mesh should be generated for the shape.
        /// </summary>
        /// <param name="absoluteDistanceThreshold">The absolute distance threshold.</param>
        /// <param name="iterationLimit">The iteration limit.</param>
        /// <returns>The triangle mesh for this shape.</returns>
        /// <remarks>
        /// This method creates a triangle mesh that represents a square lying in the plane. The square
        /// has an edge length of <see cref="MeshSize"/>.
        /// </remarks>
        protected override TriangleMesh OnGetMesh(float absoluteDistanceThreshold, int iterationLimit)
        {
            Vector3 center       = Normal * DistanceFromOrigin;
            Vector3 orthoNormal1 = Normal.Orthonormal1;
            Vector3 orthoNormal2 = Normal.Orthonormal2;

            // Plane

            // Make 4 triangles around the center.
            TriangleMesh mesh = new TriangleMesh();

            mesh.Add(new Triangle
            {
                Vertex0 = center,
                Vertex1 = center + orthoNormal1 * MeshSize / 2 - orthoNormal2 * MeshSize / 2,
                Vertex2 = center + orthoNormal1 * MeshSize / 2 + orthoNormal2 * MeshSize / 2,
            }, true);
            mesh.Add(new Triangle
            {
                Vertex0 = center,
                Vertex1 = center + orthoNormal1 * MeshSize / 2 + orthoNormal2 * MeshSize / 2,
                Vertex2 = center - orthoNormal1 * MeshSize / 2 + orthoNormal2 * MeshSize / 2,
            }, true);
            mesh.Add(new Triangle
            {
                Vertex0 = center,
                Vertex1 = center - orthoNormal1 * MeshSize / 2 + orthoNormal2 * MeshSize / 2,
                Vertex2 = center - orthoNormal1 * MeshSize / 2 - orthoNormal2 * MeshSize / 2,
            }, true);
            mesh.Add(new Triangle
            {
                Vertex0 = center,
                Vertex1 = center - orthoNormal1 * MeshSize / 2 - orthoNormal2 * MeshSize / 2,
                Vertex2 = center + orthoNormal1 * MeshSize / 2 - orthoNormal2 * MeshSize / 2,
            }, true);

            return(mesh);
        }
Beispiel #24
0
        public void GetTriangle()
        {
            Triangle t1 = new Triangle(new Vector3(0, 0, 0), new Vector3(1, 1, 1), new Vector3(1, 0, 1));

            TriangleMesh mesh = new TriangleMesh();

            mesh.Add(t1, false);

            var t2 = mesh.GetTriangle(0);

            Assert.AreEqual(t1.Vertex0, t2.Vertex0);
            Assert.AreEqual(t1.Vertex1, t2.Vertex1);
            Assert.AreEqual(t1.Vertex2, t2.Vertex2);
        }
        private void CreateObjects()
        {
            // Create two collision objects with triangle mesh shapes.
            var meshA = new TriangleMesh();

            meshA.Add(new Triangle(new Vector3F(0, 1, 0), new Vector3F(0, 1, 0), new Vector3F(0, 1, 0)));
            meshA.Add(new Triangle(new Vector3F(0, 1, 0), new Vector3F(0, 1, 0), new Vector3F(0, 1, 0)));
            var shapeA = new TriangleMeshShape()
            {
                Partition = new CompressedAabbTree()
            };
            var poseA = new Pose(new Vector3F(-1, 0, 0));

            _objectA = new CollisionObject(new GeometricObject(shapeA, poseA));

            var meshB  = new BoxShape(0.2f, 2, 1f).GetMesh(0.05f, 4);
            var shapeB = new TriangleMeshShape(meshB, true)
            {
                Partition = new CompressedAabbTree()
            };
            var poseB = new Pose(new Vector3F(0.1f, 0, 0));

            _objectB = new CollisionObject(new GeometricObject(shapeB, poseB));
        }
Beispiel #26
0
        /// <summary>
        /// Called when a mesh should be generated for the shape.
        /// </summary>
        /// <param name="absoluteDistanceThreshold">The absolute distance threshold.</param>
        /// <param name="iterationLimit">The iteration limit.</param>
        /// <returns>The triangle mesh for this shape.</returns>
        /// <remarks>
        /// This method returns a mesh with a single degenerate triangle. The triangle represents a
        /// line with the length <see cref="MeshSize"/>. The triangle is centered on
        /// <see cref="PointOnLine"/>.
        /// </remarks>
        protected override TriangleMesh OnGetMesh(float absoluteDistanceThreshold, int iterationLimit)
        {
            Vector3F start = PointOnLine - Direction * (MeshSize / 2);
            Vector3F end   = PointOnLine + Direction * (MeshSize / 2);
            // Make a mesh with 1 degenerate triangle
            TriangleMesh mesh = new TriangleMesh();

            mesh.Add(new Triangle
            {
                Vertex0 = start,
                Vertex1 = start,
                Vertex2 = end,
            }, true, Numeric.EpsilonF, false);
            return(mesh);
        }
        /// <summary>
        /// Called when a mesh should be generated for the shape.
        /// </summary>
        /// <param name="absoluteDistanceThreshold">The absolute distance threshold.</param>
        /// <param name="iterationLimit">The iteration limit.</param>
        /// <returns>The triangle mesh for this shape.</returns>
        /// <remarks>
        /// This creates a mesh with a single degenerate triangle that represents the line segment.
        /// </remarks>
        protected override TriangleMesh OnGetMesh(float absoluteDistanceThreshold, int iterationLimit)
        {
            // Make a mesh with 1 degenerate triangle
            TriangleMesh mesh = new TriangleMesh();

            mesh.Add(
                new Triangle
            {
                Vertex0 = Start,
                Vertex1 = Start,
                Vertex2 = End,
            },
                true,
                Numeric.EpsilonF,
                false);
            return(mesh);
        }
Beispiel #28
0
        private void CreateRigidBody()
        {
            var triangleMesh = new TriangleMesh();

            foreach (var meshNode in _modelNode.GetSubtree().OfType <MeshNode>())
            {
                // Extract the triangle mesh from the DigitalRune Graphics Mesh instance.
                var subTriangleMesh = new TriangleMesh();
                foreach (var submesh in meshNode.Mesh.Submeshes)
                {
                    submesh.ToTriangleMesh(subTriangleMesh);
                }

                // Apply the transformation of the mesh node.
                subTriangleMesh.Transform(meshNode.PoseWorld * Matrix.CreateScale(meshNode.ScaleWorld));

                // Combine into final triangle mesh.
                triangleMesh.Add(subTriangleMesh);
            }

            // Create a collision shape that uses the mesh.
            var triangleMeshShape = new TriangleMeshShape(triangleMesh);

            // Optional: Assign a spatial partitioning scheme to the triangle mesh. (A spatial partition
            // adds an additional memory overhead, but it improves collision detection speed tremendously!)
            triangleMeshShape.Partition = new CompressedAabbTree
            {
                // The tree is automatically built using a mixed top-down/bottom-up approach. Bottom-up
                // building is slower but produces better trees. If the tree building takes too long,
                // we can lower the BottomUpBuildThreshold (default is 128).
                BottomUpBuildThreshold = 0,
            };

            _rigidBody = new RigidBody(triangleMeshShape, new MassFrame(), null)
            {
                Pose       = _pose,
                Scale      = _scale,
                MotionType = MotionType.Static
            };

            // Add rigid body to physics simulation and model to scene.
            var simulation = _services.GetInstance <Simulation>();

            simulation.RigidBodies.Add(_rigidBody);
        }
Beispiel #29
0
        public ConvexDecompositionSample(Microsoft.Xna.Framework.Game game)
            : base(game)
        {
            SampleFramework.IsMouseVisible = false;
            GraphicsScreen.ClearBackground = true;
            GraphicsScreen.BackgroundColor = Color.CornflowerBlue;
            SetCamera(new Vector3F(3, 3, 3), 0.8f, -0.6f);

            // Load model.
            _modelNode = ContentManager.Load <ModelNode>("Saucer/Saucer").Clone();

            // Combine all meshes of the model into a single TriangleMesh.
            TriangleMesh mesh = new TriangleMesh();

            foreach (var meshNode in _modelNode.GetChildren().OfType <MeshNode>())
            {
                var childMesh = MeshHelper.ToTriangleMesh(meshNode.Mesh);
                childMesh.Transform(meshNode.PoseWorld * Matrix44F.CreateScale(meshNode.ScaleWorld));
                mesh.Add(childMesh);
            }

            // Start convex decomposition on another thread.
            _convexDecomposition = new ConvexDecomposition();
            _convexDecomposition.ProgressChanged        += OnProgressChanged;
            _convexDecomposition.AllowedConcavity        = 0.8f;
            _convexDecomposition.IntermediateVertexLimit = 65536;
            _convexDecomposition.VertexLimit             = 64;

            // 0 gives optimal results but is the slowest. Small positive values improve
            // speed but the result might be less optimal.
            _convexDecomposition.SmallIslandBoost = 0.02f;

            _convexDecomposition.SampleTriangleCenters  = true;
            _convexDecomposition.SampleTriangleVertices = true;

            // Experimental multithreading. Enable at own risk ;-)
            _convexDecomposition.EnableMultithreading = true;

            _convexDecomposition.DecomposeAsync(mesh);
        }
Beispiel #30
0
        /// <summary>
        /// Called when a mesh should be generated for the shape.
        /// </summary>
        /// <param name="absoluteDistanceThreshold">The absolute distance threshold.</param>
        /// <param name="iterationLimit">The iteration limit.</param>
        /// <returns>The triangle mesh for this shape.</returns>
        /// <remarks>
        /// A deep copy of the <see cref="Mesh"/> is returned.
        /// </remarks>
        protected override TriangleMesh OnGetMesh(float absoluteDistanceThreshold, int iterationLimit)
        {
            var triangleMesh = Mesh as TriangleMesh;

            if (triangleMesh != null)
            {
                return(triangleMesh.Clone());
            }

            // Return a copy of the mesh.
            TriangleMesh mesh = new TriangleMesh();
            int          numberOfTriangles = _mesh.NumberOfTriangles;

            for (int i = 0; i < numberOfTriangles; i++)
            {
                Triangle triangle = _mesh.GetTriangle(i);
                mesh.Add(triangle, false);
            }
            mesh.WeldVertices();

            return(mesh);
        }
Beispiel #31
0
 public void AddTriangleToleranceMustBeGreaterNull()
 {
     TriangleMesh mesh = new TriangleMesh();
       mesh.Add(new Triangle(), true, 0, true);
 }
Beispiel #32
0
 public void AddTriangleShouldRemoveDegenerateTriangle2()
 {
     var mesh = new TriangleMesh();
       mesh.Add(new Triangle(new Vector3F(1, 1, 1), new Vector3F(1, 1, 1), new Vector3F(1, 1, 1.000001f)), false, 0.001f, true);
       Assert.AreEqual(0, mesh.NumberOfTriangles);
 }
Beispiel #33
0
        public void WeldVertices()
        {
            TriangleMesh mesh = new TriangleMesh();
              Assert.AreEqual(0, mesh.WeldVertices());

              mesh.Add(new Triangle(new Vector3F(1, 2, 3), new Vector3F(3, 4, 5), new Vector3F(1.00001f, 2.00001f, 3f)), false);

              Assert.AreEqual(3, mesh.Vertices.Count);

              Assert.Throws(typeof(ArgumentOutOfRangeException), () => mesh.WeldVertices(-0.1f));

              Assert.AreEqual(1, mesh.WeldVertices(0.0001f));
              Assert.AreEqual(2, mesh.Vertices.Count);

              var w = Stopwatch.StartNew();
              mesh = new SphereShape(0.5f).GetMesh(0.001f, 7);
              w.Stop();
              //Assert.AreEqual(0, w.Elapsed.TotalMilliseconds);

              for (int i = 0; i < mesh.Vertices.Count; i++)
              {
            for (int j = i + 1; j < mesh.Vertices.Count; j++)
            {
              Assert.IsFalse(Vector3F.AreNumericallyEqual(mesh.Vertices[i], mesh.Vertices[j]));
            }
              }

              // Second time does nothing.
              Assert.AreEqual(0, mesh.WeldVertices());
        }
Beispiel #34
0
        public void SerializationBinary()
        {
            var a = new TriangleMesh();
              a.Add(new Triangle(new Vector3F(0, 1, 2), new Vector3F(3, 4, 5), new Vector3F(6, 7, 8)), false);
              a.Add(new Triangle(new Vector3F(-0, -1, -2), new Vector3F(-3, -4, -5), new Vector3F(-6, -7, -8)), false);

              // Serialize object.
              var stream = new MemoryStream();
              var formatter = new BinaryFormatter();
              formatter.Serialize(stream, a);

              // Deserialize object.
              stream.Position = 0;
              var deserializer = new BinaryFormatter();
              var b = (TriangleMesh)deserializer.Deserialize(stream);

              Assert.AreEqual(a.NumberOfTriangles, b.NumberOfTriangles);
              for (int i = 0; i < a.Vertices.Count; i++)
            Assert.AreEqual(a.Vertices[i], b.Vertices[i]);
              for (int i = 0; i < a.Indices.Count; i++)
            Assert.AreEqual(a.Indices[i], b.Indices[i]);
        }
Beispiel #35
0
 public void GetTriangleException2()
 {
     TriangleMesh mesh = new TriangleMesh();
       mesh.Add(new Triangle(new Vector3F(0, 0, 0), new Vector3F(1, 1, 1), new Vector3F(1, 0, 1)), false);
       mesh.GetTriangle(1);
 }
        private static Submesh CreateGeoClipmapMesh(GraphicsDevice graphicsDevice, int numberOfLevels,
                                                    int cellsPerLevel, bool useDiamondTessellation)
        {
            if (graphicsDevice == null)
            {
                throw new ArgumentNullException("graphicsDevice");
            }
            if (cellsPerLevel < 1)
            {
                throw new ArgumentOutOfRangeException("cellsPerLevel", "The number of cells per level must be greater than 0.");
            }

            // Round to even number of cells.
            if (cellsPerLevel % 2 != 0)
            {
                cellsPerLevel++;
            }

            // Allocate a mesh with conservative list capacities.
            int cellsPerLevelUpperBound    = (cellsPerLevel + 3) * (cellsPerLevel + 3);
            int verticesPerLevelUpperBound = useDiamondTessellation ? cellsPerLevelUpperBound * 9 : cellsPerLevelUpperBound * 4;
            int indicesPerLevelUpperBound  = useDiamondTessellation ? cellsPerLevelUpperBound * 8 * 3 : cellsPerLevelUpperBound * 2 * 3;
            var triangleMesh = new TriangleMesh(verticesPerLevelUpperBound * numberOfLevels, indicesPerLevelUpperBound * numberOfLevels);

            // The levels are created in a separate mesh and then combined into the final mesh.
            var triangleMeshes = new TriangleMesh[numberOfLevels];

            triangleMeshes[0] = triangleMesh;
            for (int i = 1; i < numberOfLevels; i++)
            {
                triangleMeshes[i] = new TriangleMesh(verticesPerLevelUpperBound, indicesPerLevelUpperBound);
            }

            //for (int level = 0; level < numberOfLevels; level++)
            Parallel.For(0, numberOfLevels, level =>
            {
                var levelTriangleMesh = triangleMeshes[level];
                int cellSize          = (1 << level);
                float y = level; // Store LOD in Y coordinate.

                Debug.Assert(cellsPerLevel % 2 == 0);

                int halfWidthInCells = cellsPerLevel / 2;
                int halfWidth        = cellSize * (halfWidthInCells);
                int minInclusive     = -halfWidth - cellSize; // We add an extra border on the top and left.
                int maxInclusive     = halfWidth - cellSize;  // Normal loop limit without extra border.

                int previousHalfWidth = (level > 0) ? halfWidth / 2 : -1;

                if (useDiamondTessellation)
                {
                    int index = 0;
                    for (int z = minInclusive; z <= maxInclusive; z += cellSize)
                    {
                        for (int x = minInclusive; x <= maxInclusive; x += cellSize)
                        {
                            // No triangles in the area which are covered by previous levels.
                            // (We compare cell centers with radius of last LOD.)
                            if (Math.Max(Math.Abs(x + cellSize / 2), Math.Abs(z + cellSize / 2)) < previousHalfWidth)
                            {
                                continue;
                            }

                            // Each cell will be tessellated like this:
                            //   A-----B-----C
                            //   | \   |   / |
                            //   |   \ | /   |
                            //   D-----E-----F
                            //   |   / | \   |
                            //   | /   |   \ |
                            //   G-----H-----I

                            var indexA = index++;
                            levelTriangleMesh.Vertices.Add(new Vector3(x, y, z));

                            var indexB = index++;
                            levelTriangleMesh.Vertices.Add(new Vector3(x + 0.5f * cellSize, y, z));

                            var indexC = index++;
                            levelTriangleMesh.Vertices.Add(new Vector3(x + cellSize, y, z));

                            var indexD = index++;
                            levelTriangleMesh.Vertices.Add(new Vector3(x, y, z + 0.5f * cellSize));

                            var indexE = index++;
                            levelTriangleMesh.Vertices.Add(new Vector3(x + 0.5f * cellSize, y, z + 0.5f * cellSize));

                            var indexF = index++;
                            levelTriangleMesh.Vertices.Add(new Vector3(x + cellSize, y, z + 0.5f * cellSize));

                            var indexG = index++;
                            levelTriangleMesh.Vertices.Add(new Vector3(x, y, z + cellSize));

                            var indexH = index++;
                            levelTriangleMesh.Vertices.Add(new Vector3(x + 0.5f * cellSize, y, z + cellSize));

                            var indexI = index++;
                            levelTriangleMesh.Vertices.Add(new Vector3(x + cellSize, y, z + cellSize));

                            // Triangles using ADEG:
                            if (x != minInclusive)
                            {
                                levelTriangleMesh.Indices.Add(indexE);
                                levelTriangleMesh.Indices.Add(indexD);
                                levelTriangleMesh.Indices.Add(indexA);

                                levelTriangleMesh.Indices.Add(indexE);
                                levelTriangleMesh.Indices.Add(indexG);
                                levelTriangleMesh.Indices.Add(indexD);
                            }
                            else
                            {
                                // The outer cells are tessellated differently to stitch to the next level.
                                //   A-----B-----C
                                //   | \   |   / |
                                //   |   \ | /   |
                                //   |     E-----F
                                //   |   / | \   |
                                //   | /   |   \ |
                                //   G-----H-----I
                                levelTriangleMesh.Indices.Add(indexE);
                                levelTriangleMesh.Indices.Add(indexG);
                                levelTriangleMesh.Indices.Add(indexA);
                            }

                            // Triangles using ABCE:
                            if (z != minInclusive)
                            {
                                levelTriangleMesh.Indices.Add(indexE);
                                levelTriangleMesh.Indices.Add(indexB);
                                levelTriangleMesh.Indices.Add(indexC);

                                levelTriangleMesh.Indices.Add(indexE);
                                levelTriangleMesh.Indices.Add(indexA);
                                levelTriangleMesh.Indices.Add(indexB);
                            }
                            else
                            {
                                levelTriangleMesh.Indices.Add(indexE);
                                levelTriangleMesh.Indices.Add(indexA);
                                levelTriangleMesh.Indices.Add(indexC);
                            }

                            // Triangles using CEFI:
                            if (x != maxInclusive)
                            {
                                levelTriangleMesh.Indices.Add(indexE);
                                levelTriangleMesh.Indices.Add(indexF);
                                levelTriangleMesh.Indices.Add(indexI);

                                levelTriangleMesh.Indices.Add(indexE);
                                levelTriangleMesh.Indices.Add(indexC);
                                levelTriangleMesh.Indices.Add(indexF);
                            }
                            else
                            {
                                levelTriangleMesh.Indices.Add(indexE);
                                levelTriangleMesh.Indices.Add(indexC);
                                levelTriangleMesh.Indices.Add(indexI);
                            }

                            // Triangles using EGHI:
                            if (z != maxInclusive)
                            {
                                levelTriangleMesh.Indices.Add(indexE);
                                levelTriangleMesh.Indices.Add(indexH);
                                levelTriangleMesh.Indices.Add(indexG);

                                levelTriangleMesh.Indices.Add(indexE);
                                levelTriangleMesh.Indices.Add(indexI);
                                levelTriangleMesh.Indices.Add(indexH);
                            }
                            else
                            {
                                levelTriangleMesh.Indices.Add(indexE);
                                levelTriangleMesh.Indices.Add(indexI);
                                levelTriangleMesh.Indices.Add(indexG);
                            }
                        }
                    }

                    Debug.Assert(levelTriangleMesh.Vertices.Count <= verticesPerLevelUpperBound, "Bad estimate for upper bound of vertices.");
                    Debug.Assert(levelTriangleMesh.Indices.Count <= indicesPerLevelUpperBound, "Bad estimate for upper bound of indices.");

                    levelTriangleMesh.WeldVertices(0.1f);
                }
                else
                {
                    // Add one extra border to hide gaps.
                    minInclusive -= cellSize;
                    maxInclusive += cellSize;

                    int index = 0;
                    for (int z = minInclusive; z <= maxInclusive; z += cellSize)
                    {
                        for (int x = minInclusive; x <= maxInclusive; x += cellSize)
                        {
                            // No triangles in the area which are covered by previous levels.
                            // (We compare cell centers with radius of last LOD.)
                            if (Math.Max(Math.Abs(x + cellSize / 2), Math.Abs(z + cellSize / 2)) < previousHalfWidth)
                            {
                                continue;
                            }

                            // Each 2x2 cells will be tessellated like this:
                            //   A-----B
                            //   |   / |
                            //   | /   |
                            //   C-----D

                            int indexA = index++;
                            levelTriangleMesh.Vertices.Add(new Vector3(x, y, z));

                            int indexB = index++;
                            levelTriangleMesh.Vertices.Add(new Vector3(x + cellSize, y, z));

                            int indexC = index++;
                            levelTriangleMesh.Vertices.Add(new Vector3(x, y, z + cellSize));

                            int indexD = index++;
                            levelTriangleMesh.Vertices.Add(new Vector3(x + cellSize, y, z + cellSize));

                            levelTriangleMesh.Indices.Add(indexA);
                            levelTriangleMesh.Indices.Add(indexB);
                            levelTriangleMesh.Indices.Add(indexC);

                            levelTriangleMesh.Indices.Add(indexC);
                            levelTriangleMesh.Indices.Add(indexB);
                            levelTriangleMesh.Indices.Add(indexD);
                        }
                    }

                    Debug.Assert(levelTriangleMesh.Vertices.Count <= verticesPerLevelUpperBound, "Bad estimate for upper bound of vertices.");
                    Debug.Assert(levelTriangleMesh.Indices.Count <= indicesPerLevelUpperBound, "Bad estimate for upper bound of indices.");

                    levelTriangleMesh.WeldVertices(0.1f);
                }
            });

            // Combine meshes.
            for (int i = 1; i < numberOfLevels; i++)
            {
                triangleMesh.Add(triangleMeshes[i]);
            }

            var vertices = new TerrainVertex[triangleMesh.Vertices.Count];
            {
                int index = 0;
                for (int i = 0; i < vertices.Length; i++)
                {
                    Vector3 v = triangleMesh.Vertices[i];
                    vertices[index++] = new TerrainVertex(new HalfVector4(v.X, v.Y, v.Z, 1));
                }
            }

            var submesh = CreateSubmesh(graphicsDevice, vertices, triangleMesh.Indices.ToArray());

            //Debug.WriteLine("Number of terrain vertices:" + vertices.Length);
            //Debug.WriteLine("Number of terrain triangles:" + triangleMesh.Indices.Count / 3);

            return(submesh);
        }
Beispiel #37
0
        /// <summary>
        /// Called when a mesh should be generated for the shape.
        /// </summary>
        /// <param name="absoluteDistanceThreshold">The absolute distance threshold.</param>
        /// <param name="iterationLimit">The iteration limit.</param>
        /// <returns>The triangle mesh for this shape.</returns>
        protected override TriangleMesh OnGetMesh(float absoluteDistanceThreshold, int iterationLimit)
        {
            // Get coordinates of corners:
            float near       = -Math.Min(Near, Far);
            float far        = -Math.Max(Near, Far);
            float leftNear   = Math.Min(Left, Right);
            float rightNear  = Math.Max(Left, Right);
            float topNear    = Math.Max(Top, Bottom);
            float bottomNear = Math.Min(Top, Bottom);
            float farFactor  = 1 / near * far; // Multiply near-values by this factor to get far-values.
            float leftFar    = leftNear * farFactor;
            float rightFar   = rightNear * farFactor;
            float topFar     = topNear * farFactor;
            float bottomFar  = bottomNear * farFactor;

            TriangleMesh mesh = new TriangleMesh();

            // -y face
            mesh.Add(new Triangle
            {
                Vertex0 = new Vector3F(leftNear, bottomNear, near),
                Vertex1 = new Vector3F(leftFar, bottomFar, far),
                Vertex2 = new Vector3F(rightFar, bottomFar, far),
            }, true);
            mesh.Add(new Triangle
            {
                Vertex0 = new Vector3F(rightFar, bottomFar, far),
                Vertex1 = new Vector3F(rightNear, bottomNear, near),
                Vertex2 = new Vector3F(leftNear, bottomNear, near),
            }, true);

            // +x face
            mesh.Add(new Triangle
            {
                Vertex0 = new Vector3F(rightNear, topNear, near),
                Vertex1 = new Vector3F(rightNear, bottomNear, near),
                Vertex2 = new Vector3F(rightFar, bottomFar, far),
            }, true);
            mesh.Add(new Triangle
            {
                Vertex0 = new Vector3F(rightFar, bottomFar, far),
                Vertex1 = new Vector3F(rightFar, topFar, far),
                Vertex2 = new Vector3F(rightNear, topNear, near),
            }, true);

            // -z face
            mesh.Add(new Triangle
            {
                Vertex0 = new Vector3F(rightFar, topFar, far),
                Vertex1 = new Vector3F(rightFar, bottomFar, far),
                Vertex2 = new Vector3F(leftFar, bottomFar, far),
            }, true);
            mesh.Add(new Triangle
            {
                Vertex0 = new Vector3F(leftFar, bottomFar, far),
                Vertex1 = new Vector3F(leftFar, topFar, far),
                Vertex2 = new Vector3F(rightFar, topFar, far),
            }, true);

            // -x face
            mesh.Add(new Triangle
            {
                Vertex0 = new Vector3F(leftFar, topFar, far),
                Vertex1 = new Vector3F(leftFar, bottomFar, far),
                Vertex2 = new Vector3F(leftNear, bottomNear, near),
            }, true);
            mesh.Add(new Triangle
            {
                Vertex0 = new Vector3F(leftNear, bottomNear, near),
                Vertex1 = new Vector3F(leftNear, topNear, near),
                Vertex2 = new Vector3F(leftFar, topFar, far),
            }, true);

            // +z face
            mesh.Add(new Triangle
            {
                Vertex0 = new Vector3F(leftNear, topNear, near),
                Vertex1 = new Vector3F(leftNear, bottomNear, near),
                Vertex2 = new Vector3F(rightNear, bottomNear, near),
            }, true);
            mesh.Add(new Triangle
            {
                Vertex0 = new Vector3F(rightNear, bottomNear, near),
                Vertex1 = new Vector3F(rightNear, topNear, near),
                Vertex2 = new Vector3F(leftNear, topNear, near),
            }, true);

            // +y face
            mesh.Add(new Triangle
            {
                Vertex0 = new Vector3F(leftFar, topFar, far),
                Vertex1 = new Vector3F(leftNear, topNear, near),
                Vertex2 = new Vector3F(rightNear, topNear, near),
            }, true);
            mesh.Add(new Triangle
            {
                Vertex0 = new Vector3F(rightNear, topNear, near),
                Vertex1 = new Vector3F(rightFar, topFar, far),
                Vertex2 = new Vector3F(leftFar, topFar, far),
            }, true);

            return(mesh);
        }
Beispiel #38
0
        public void GetTriangle()
        {
            Triangle t1 = new Triangle(new Vector3F(0, 0, 0), new Vector3F(1, 1, 1), new Vector3F(1, 0, 1));

              TriangleMesh mesh = new TriangleMesh();
              mesh.Add(t1, false);

              var t2 = mesh.GetTriangle(0);
              Assert.AreEqual(t1.Vertex0, t2.Vertex0);
              Assert.AreEqual(t1.Vertex1, t2.Vertex1);
              Assert.AreEqual(t1.Vertex2, t2.Vertex2);
        }
Beispiel #39
0
        public void SerializationXml()
        {
            var a = new TriangleMesh();
              a.Add(new Triangle(new Vector3F(0, 1, 2), new Vector3F(3, 4, 5), new Vector3F(6, 7, 8)), true);
              a.Add(new Triangle(new Vector3F(-0, -1, -2), new Vector3F(-3, -4, -5), new Vector3F(-6, -7, -8)), true);

              // Serialize object.
              var stream = new MemoryStream();
              var serializer = new XmlSerializer(typeof(TriangleMesh));
              serializer.Serialize(stream, a);

              // Output generated xml. Can be manually checked in output window.
              stream.Position = 0;
              var xml = new StreamReader(stream).ReadToEnd();
              Trace.WriteLine("Serialized Object:\n" + xml);

              // Deserialize object.
              stream.Position = 0;
              var deserializer = new XmlSerializer(typeof(TriangleMesh));
              var b = (TriangleMesh)deserializer.Deserialize(stream);

              Assert.AreEqual(a.NumberOfTriangles, b.NumberOfTriangles);
              for (int i = 0; i < a.Vertices.Count; i++)
            Assert.AreEqual(a.Vertices[i], b.Vertices[i]);
              for (int i = 0; i < a.Indices.Count; i++)
            Assert.AreEqual(a.Indices[i], b.Indices[i]);
        }
Beispiel #40
0
        public void Transform()
        {
            var mesh = new TriangleMesh();
              mesh.Add(new Triangle(new Vector3F(0, 1, 2), new Vector3F(3, 4, 5), new Vector3F(6, 7, 8)), true);
              mesh.Add(new Triangle(new Vector3F(-0, -1, -2), new Vector3F(-3, -4, -5), new Vector3F(-6, -7, -8)), true);

              var trans = RandomHelper.Random.NextMatrix44F(-1, 1);
              mesh.Transform(trans);

              Assert.AreEqual(trans.TransformPosition(new Vector3F(0, 1, 2)), mesh.Vertices[0]);
              Assert.AreEqual(trans.TransformPosition(new Vector3F(-6, -7, -8)), mesh.Vertices[5]);
        }
Beispiel #41
0
        /// <summary>
        /// Called when a mesh should be generated for the shape.
        /// </summary>
        /// <param name="absoluteDistanceThreshold">The absolute distance threshold.</param>
        /// <param name="iterationLimit">The iteration limit.</param>
        /// <returns>The triangle mesh for this shape.</returns>
        protected override TriangleMesh OnGetMesh(float absoluteDistanceThreshold, int iterationLimit)
        {
            // Half extent:
            float halfExtentX = _widthX / 2;
            float halfExtentY = _widthY / 2;
            float halfExtentZ = _widthZ / 2;

            TriangleMesh mesh = new TriangleMesh();

            // -y face
            mesh.Add(new Triangle
            {
                Vertex0 = new Vector3(-halfExtentX, -halfExtentY, halfExtentZ),
                Vertex1 = new Vector3(-halfExtentX, -halfExtentY, -halfExtentZ),
                Vertex2 = new Vector3(halfExtentX, -halfExtentY, -halfExtentZ),
            }, true);
            mesh.Add(new Triangle
            {
                Vertex0 = new Vector3(halfExtentX, -halfExtentY, -halfExtentZ),
                Vertex1 = new Vector3(halfExtentX, -halfExtentY, halfExtentZ),
                Vertex2 = new Vector3(-halfExtentX, -halfExtentY, halfExtentZ),
            }, true);

            // +x face
            mesh.Add(new Triangle
            {
                Vertex0 = new Vector3(halfExtentX, halfExtentY, halfExtentZ),
                Vertex1 = new Vector3(halfExtentX, -halfExtentY, halfExtentZ),
                Vertex2 = new Vector3(halfExtentX, -halfExtentY, -halfExtentZ),
            }, true);
            mesh.Add(new Triangle
            {
                Vertex0 = new Vector3(halfExtentX, -halfExtentY, -halfExtentZ),
                Vertex1 = new Vector3(halfExtentX, halfExtentY, -halfExtentZ),
                Vertex2 = new Vector3(halfExtentX, halfExtentY, halfExtentZ),
            }, true);

            // -z face
            mesh.Add(new Triangle
            {
                Vertex0 = new Vector3(halfExtentX, halfExtentY, -halfExtentZ),
                Vertex1 = new Vector3(halfExtentX, -halfExtentY, -halfExtentZ),
                Vertex2 = new Vector3(-halfExtentX, -halfExtentY, -halfExtentZ),
            }, true);
            mesh.Add(new Triangle
            {
                Vertex0 = new Vector3(-halfExtentX, -halfExtentY, -halfExtentZ),
                Vertex1 = new Vector3(-halfExtentX, halfExtentY, -halfExtentZ),
                Vertex2 = new Vector3(halfExtentX, halfExtentY, -halfExtentZ),
            }, true);

            // -x face
            mesh.Add(new Triangle
            {
                Vertex0 = new Vector3(-halfExtentX, halfExtentY, -halfExtentZ),
                Vertex1 = new Vector3(-halfExtentX, -halfExtentY, -halfExtentZ),
                Vertex2 = new Vector3(-halfExtentX, -halfExtentY, halfExtentZ),
            }, true);
            mesh.Add(new Triangle
            {
                Vertex0 = new Vector3(-halfExtentX, -halfExtentY, halfExtentZ),
                Vertex1 = new Vector3(-halfExtentX, halfExtentY, halfExtentZ),
                Vertex2 = new Vector3(-halfExtentX, halfExtentY, -halfExtentZ),
            }, true);

            // +z face
            mesh.Add(new Triangle
            {
                Vertex0 = new Vector3(-halfExtentX, halfExtentY, halfExtentZ),
                Vertex1 = new Vector3(-halfExtentX, -halfExtentY, halfExtentZ),
                Vertex2 = new Vector3(halfExtentX, -halfExtentY, halfExtentZ),
            }, true);
            mesh.Add(new Triangle
            {
                Vertex0 = new Vector3(halfExtentX, -halfExtentY, halfExtentZ),
                Vertex1 = new Vector3(halfExtentX, halfExtentY, halfExtentZ),
                Vertex2 = new Vector3(-halfExtentX, halfExtentY, halfExtentZ),
            }, true);

            // +y face
            mesh.Add(new Triangle
            {
                Vertex0 = new Vector3(-halfExtentX, halfExtentY, -halfExtentZ),
                Vertex1 = new Vector3(-halfExtentX, halfExtentY, halfExtentZ),
                Vertex2 = new Vector3(halfExtentX, halfExtentY, halfExtentZ),
            }, true);
            mesh.Add(new Triangle
            {
                Vertex0 = new Vector3(halfExtentX, halfExtentY, halfExtentZ),
                Vertex1 = new Vector3(halfExtentX, halfExtentY, -halfExtentZ),
                Vertex2 = new Vector3(-halfExtentX, halfExtentY, -halfExtentZ),
            }, true);

            return(mesh);
        }