//TO DO: probably replace this method
        //TO DO: Add binary reader
        /// <summary>
        /// Loads a convex hull file made up of several convex segments from a .hull file generated in .obj format by
        /// ConvexDecomposition utility.
        /// </summary>
        /// <param name="reader">The stream from which to load the convex hulls.</param>
        /// <returns>An array containing the loaded ConvexSegment's.</returns>
        public static ConvexSegment[] LoadMultipleConvexHulls(StreamReader reader)
        {
            // 32 is the default number of hulls generated
            const int NumHulls = 32;

            string line;
            int    verticesSoFar = 0;

            ConvexSegment[] hulls = new ConvexSegment[NumHulls];

            // Read through unnecessary lines
            for (int i = 1; i <= 10; i++)
            {
                line = reader.ReadLine();
            }

            for (int currentHull = 0; currentHull < NumHulls; ++currentHull)
            {
                line = reader.ReadLine();
                line = reader.ReadLine();

                string[] lineSplit    = Split(line, ' ');
                int      numVerts     = int.Parse(lineSplit[5]);
                int      numTriangles = int.Parse(lineSplit[8]);

                line = reader.ReadLine();
                Vector3[] vertices  = LoadObjVertices(reader, numVerts, 1);
                int[]     triangles = LoadObjTriangles(reader, numTriangles, verticesSoFar, 1);
                verticesSoFar += vertices.Length;

                hulls[currentHull] = new ConvexSegment(vertices, triangles);
            }

            return(hulls);
        }
Exemple #2
0
        /// <summary>
        /// Test if two convex hulls are intersecting.
        /// </summary>
        /// <param name="left">The first hull to test for collisions.</param>
        /// <param name="leftEntitySpace">The transform which takes the first hull from object to world space.</param>
        /// <param name="right">The second hull to test for collisions with the first.</param>
        /// <param name="rightEntitySpace">The transform which takes the second hull from object to world space.</param>
        /// <returns>A CollisionResult if a collision was found otherwise null.</returns>
        public static CollisionResult <ConvexHull> Collided(ConvexHull left, Matrix leftEntitySpace, ConvexHull right, Matrix rightEntitySpace)
        {
            Vector3 furthestFaceNormal = new Vector3();
            Vector3 furthestVertex     = new Vector3();
            float   furthestDistance   = 0.0f;
            bool    collided           = false;
            Matrix  leftTransform      =
                left.Transform *    // from right hull object space to right entity object space
                leftEntitySpace;    // from right entity object space to world space
            Matrix rightTransform =
                right.Transform *   // from left hull object space to left entity object space
                rightEntitySpace;   // from left entity object space to world space

            // Convert the convex segments from hull object space to world space.
            ConvexSegment leftSeg  = left.Hull.Transform(leftTransform);
            ConvexSegment rightSeg = right.Hull.Transform(rightTransform);

            // Test if any points in the right hull lie within the left hull.
            foreach (Vector3 v in rightSeg.Vertices)
            {
                Vector3 normal;
                float   distance;
                if (ConvexSegment.IsPointInHull(leftSeg, v, out normal, out distance))
                {
                    if (distance > furthestDistance)
                    {
                        collided           = true;
                        furthestDistance   = distance;
                        furthestVertex     = v;
                        furthestFaceNormal = normal;
                    }
                }
            }

            if (collided)
            {
                return(new CollisionResult <ConvexHull>(left, right, furthestFaceNormal, furthestVertex, furthestDistance));
            }
            else
            {
                return(null);
            }
        }
        /// <summary>
        /// Tests if p is inside hull and returns the closestFace to p and the distance to that face. The point must be inside all
        /// faces of the convex hull.
        /// </summary>
        /// <param name="hull">The hull to test the point against.</param>
        /// <param name="p">The point being tested.</param>
        /// <param name="closestFaceNormal">If the point is in the hull this value is set to the normal of the closest face to the point.</param>
        /// <param name="closestDistance">If the point is in the hull this value is set to the distance to the closest face to
        /// the point.</param>
        /// <returns>True if p is inside hull.</returns>
        public static bool IsPointInHull(ConvexSegment hull, Vector3 p, out Vector3 closestFaceNormal, out float closestDistance)
        {
            closestFaceNormal = new Vector3();
            closestDistance   = float.PositiveInfinity;
            bool inside = true;

            // triStart is the starting point of a triangle in the list of triangles
            for (int triStart = 0; triStart < hull.triangles.Length / 3; ++triStart)
            {
                Vector3 a = hull.vertices[hull.triangles[3 * triStart]];
                Vector3 n = hull.normals[triStart];

                // If the angle between n and AP is larger then pi/2 then AP must be behind ABC
                Vector3 ap = p - a;

                // cosTheta is really |n||AP|cos(theta) but since |n| and |AP| are both positive it won't effect the result.
                float cosTheta = Vector3.Dot(n, ap);

                // distance = |<n, AP> n| = |<n, AP>||n| = |n||AP||cos(theta)|
                // However, since the point is outside the hull if cos(theta) < 0
                // distance = |n||AP|cos(theta)
                float distance = -cosTheta;

                inside &= cosTheta < 0;
                if (distance < closestDistance)
                {
                    closestFaceNormal = n;
                    closestDistance   = distance;
                }

                if (!inside)
                {
                    break;
                }
            }

            return(inside);
        }
Exemple #4
0
 /// <summary>
 /// Create a convex hull from its position and orientation.
 /// </summary>
 /// <param name="hull">The underlying convex segment.</param>
 /// <param name="position">The position of the convex segment.</param>
 /// <param name="orientation">The orientation of the convex segment.</param>
 public ConvexHull(ConvexSegment hull, Vector3 position, Matrix orientation)
     : this(hull, orientation *Matrix.CreateTranslation(position))
 {
 }
Exemple #5
0
 /// <summary>
 /// Construct a convex hull from a ConvexSegment and a corresponding transform.
 /// </summary>
 /// <param name="hull">The underlying convex segment.</param>
 /// <param name="transform">The transform which positions and orients the convex segment.</param>
 public ConvexHull(ConvexSegment hull, Matrix transform)
 {
     this.hull      = hull;
     this.transform = transform;
 }