private static void CheckAdjacent(HeroesTriangle triangle, int vertexOne, int vertexTwo, int triangleIndexSource, int triangleIndexDestination, int adjacentIndex)
        {
            // Check whether the triangle has any vertices which share the supplied vertices.
            // If so, set the adjacent triangle.
            if
            (
                triangle.VertexOne == vertexOne &&
                triangle.VertexTwo == vertexTwo
                ||
                triangle.VertexTwo == vertexOne &&
                triangle.VertexOne == vertexTwo

                ||

                triangle.VertexTwo == vertexOne &&
                triangle.VertexThree == vertexTwo
                ||
                triangle.VertexThree == vertexOne &&
                triangle.VertexTwo == vertexTwo

                ||

                triangle.VertexThree == vertexOne &&
                triangle.VertexOne == vertexTwo
                ||
                triangle.VertexOne == vertexOne &&
                triangle.VertexThree == vertexTwo
            )
            {
                // Assign the adjacent triangles.
                GeometryData.Triangles[triangleIndexSource].AdjacentTriangles[adjacentIndex] = (ushort)triangleIndexDestination;
            }
        }
Beispiel #2
0
 /// <summary>
 /// Returns true if the supplied vertex index is shared with another vertex in the passed in Triangle parameter.
 /// </summary>
 public static bool HasSharedVertex(ushort index, HeroesTriangle triangle)
 {
     if (index == triangle.VertexOne || index == triangle.VertexTwo || index == triangle.VertexThree)
     {
         return(true);
     }
     else
     {
         return(false);
     }
 }
        /// <summary>
        /// Splits a string which defines three vertices and adds a triangle onto the triangle list.
        /// </summary>
        private void AddTriangle(string triangleVertices)
        {
            // Separate each triangle entry
            string[] trianglesString = triangleVertices.Split(' ');

            // Increment array index. (Pre-decrement, value starts at -1)
            _triangleIndex += 1;

            // Check if it's face vertex index value only, if it contains texture coordinates or normals, strip them from the string.
            for (int x = 0; x < trianglesString.Length; x++)
            {
                if (trianglesString[x].Contains("/"))
                {
                    trianglesString[x] = trianglesString[x].Substring(0, trianglesString[x].IndexOf("/"));
                }
            }

            // Declare and assign the individual triangle vertices
            HeroesTriangle triangle = new HeroesTriangle();

            // Stores the individual vertex information.
            ushort vertexOne;
            ushort vertexTwo;
            ushort vertexThree;

            // NOTE: Our vertices array starts at 0, but the triangle vertices in the OBJ file start at 1, make sure this index subtraction is correct.
            // NOTE: Some OBJ Exporters may not assign a vertex to some faces, set them to 1 if that should turn to be so, try/catch.
            try { vertexOne = (ushort)(Convert.ToUInt16(trianglesString[0]) - 1); } catch { vertexOne = 1; }
            try { vertexTwo = (ushort)(Convert.ToUInt16(trianglesString[1]) - 1); } catch { vertexTwo = 1; }
            try { vertexThree = (ushort)(Convert.ToUInt16(trianglesString[2]) - 1); } catch { vertexThree = 1; }

            // Assign our vertices to the triangle.
            triangle.VertexOne   = vertexOne;
            triangle.VertexTwo   = vertexTwo;
            triangle.VertexThree = vertexThree;

            // Assign no collision flags
            triangle.FlagsPrimary   = new byte[] { 0x00, 0x00, 0x00, 0x00 };
            triangle.FlagsSecondary = new byte[] { 0x00, 0x00, 0x00, 0x00 };

            // Add onto triangles array
            GeometryData.Triangles.Add(triangle);
        }
Beispiel #4
0
        /// <summary>
        /// Accurately checks node-triangle collisions, down to the individual vertices.
        /// </summary>
        /// <param name="triangle">The triangle to check passed in node collision against.</param>
        /// <param name="nodeRectangle">The bounding box square representing the current node (performance optimization).</param>
        /// <returns>True if there is an intersection, otherwise false.</returns>
        public static bool CheckCollision(HeroesTriangle triangle, Rectangle nodeRectangle)
        {
            // First check if the bounding boxes intersect, if they don't, discard the operation.
            if (!BoundingBoxIntersect(nodeRectangle, GeometryData.TriangleBoxes[triangle.TriangleIndex]))
            {
                return(false);
            }

            // Check all vertices for presence in rectangle for possible fast return.
            // If any of the vertices is inside the node, then there must be a collision.
            if (IsVertexInRectangle(GeometryData.Vertices[triangle.VertexOne], nodeRectangle))
            {
                return(true);
            }
            if (IsVertexInRectangle(GeometryData.Vertices[triangle.VertexTwo], nodeRectangle))
            {
                return(true);
            }
            if (IsVertexInRectangle(GeometryData.Vertices[triangle.VertexThree], nodeRectangle))
            {
                return(true);
            }

            // Define vertices of the Rectangles.
            Vertex topLeftNodeEdge     = new Vertex(nodeRectangle.MinX, 0, nodeRectangle.MinZ);
            Vertex topRightNodeEdge    = new Vertex(nodeRectangle.MaxX, 0, nodeRectangle.MinZ);
            Vertex bottomRightNodeEdge = new Vertex(nodeRectangle.MaxX, 0, nodeRectangle.MaxZ);
            Vertex bottomLeftNodeEdge  = new Vertex(nodeRectangle.MaxX, 0, nodeRectangle.MaxZ);

            // Define triangle vertices.
            Vertex triangleVertexOne   = GeometryData.Vertices[triangle.VertexOne];
            Vertex triangleVertexTwo   = GeometryData.Vertices[triangle.VertexTwo];
            Vertex triangleVertexThree = GeometryData.Vertices[triangle.VertexThree];

            // Then check if any of the node line segments intersect the triangle line segments.
            // We basically check if there are intersections between any of the three line segments of the triangle
            // i.e. A=>B, B=>C and C=>A and the four edges of the rectangle.
            #region Line Intersection Tests: Triangle line segments (vertex X to vertex Y) against node up down left right edges.

            // Check the top edge of the against the triangle line segments.
            if (LineIntersectionTest(triangleVertexOne, triangleVertexTwo, topLeftNodeEdge, topRightNodeEdge))
            {
                return(true);
            }
            if (LineIntersectionTest(triangleVertexTwo, triangleVertexThree, topLeftNodeEdge, topRightNodeEdge))
            {
                return(true);
            }
            if (LineIntersectionTest(triangleVertexThree, triangleVertexOne, topLeftNodeEdge, topRightNodeEdge))
            {
                return(true);
            }

            // Check the left edge of the against the triangle line segments.
            if (LineIntersectionTest(triangleVertexOne, triangleVertexTwo, topLeftNodeEdge, bottomLeftNodeEdge))
            {
                return(true);
            }
            if (LineIntersectionTest(triangleVertexTwo, triangleVertexThree, topLeftNodeEdge, bottomLeftNodeEdge))
            {
                return(true);
            }
            if (LineIntersectionTest(triangleVertexThree, triangleVertexOne, topLeftNodeEdge, bottomLeftNodeEdge))
            {
                return(true);
            }

            // Check the bottom edge of the against the triangle line segments.
            if (LineIntersectionTest(triangleVertexOne, triangleVertexTwo, bottomLeftNodeEdge, bottomRightNodeEdge))
            {
                return(true);
            }
            if (LineIntersectionTest(triangleVertexTwo, triangleVertexThree, bottomLeftNodeEdge, bottomRightNodeEdge))
            {
                return(true);
            }
            if (LineIntersectionTest(triangleVertexThree, triangleVertexOne, bottomLeftNodeEdge, bottomRightNodeEdge))
            {
                return(true);
            }

            // Check the right edge of the against the triangle line segments.
            if (LineIntersectionTest(triangleVertexOne, triangleVertexTwo, topRightNodeEdge, bottomRightNodeEdge))
            {
                return(true);
            }
            if (LineIntersectionTest(triangleVertexTwo, triangleVertexThree, topRightNodeEdge, bottomRightNodeEdge))
            {
                return(true);
            }
            if (LineIntersectionTest(triangleVertexThree, triangleVertexOne, topRightNodeEdge, bottomRightNodeEdge))
            {
                return(true);
            }

            #endregion Line Intersection Tests: Triangle line segments (vertex X to vertex Y) against node up down left right edges.

            // Understanding the code below:
            // Consider the triangle as three vectors, in a fixed rotation order A=>B, B=>C, C=>A
            // Now consider each vertex of the triangle and each square vertex, compute the cross product between each triangle edge and rectangle
            // vector (3*4=12 comparisons in total). If all of the cross products are of the same sign, or zero, the triangle is inside.

            // Conceptually we are determining whether the vertices are on the left or right side of the line, albeit the side is not cared.
            // We do not care whether it is left or right specifically, or whether it is in clockwise or anticlockwise order, only that all of the vertices
            // of the square are on the same side of the lines.
            // i.e. if all of the vertices are on the same side of each line, the vertices are "trapped" between the 3 lines, meaning that they must be
            // inside the triangle.
            #region Node Inside Triangle Tests: Determine if all of the node vertices are on the right side of the line, with vertices going clockwise.

            // Vertex One   = A
            // Vertex Two   = B
            // Vertex Three = C
            // Note: Variable names are completely arbitrary, to make code less confusing/long

            // Compare line A=>B with all edge vertices.
            bool v1 = IsPointRightOfLine(triangleVertexOne, triangleVertexTwo, topLeftNodeEdge);
            bool v2 = IsPointRightOfLine(triangleVertexOne, triangleVertexTwo, topRightNodeEdge);
            bool v3 = IsPointRightOfLine(triangleVertexOne, triangleVertexTwo, bottomRightNodeEdge);
            bool v4 = IsPointRightOfLine(triangleVertexOne, triangleVertexTwo, bottomLeftNodeEdge);

            // Compare line B=>C with all edge vertices.
            bool v5 = IsPointRightOfLine(triangleVertexTwo, triangleVertexThree, topLeftNodeEdge);
            bool v6 = IsPointRightOfLine(triangleVertexTwo, triangleVertexThree, topRightNodeEdge);
            bool v7 = IsPointRightOfLine(triangleVertexTwo, triangleVertexThree, bottomRightNodeEdge);
            bool v8 = IsPointRightOfLine(triangleVertexTwo, triangleVertexThree, bottomLeftNodeEdge);

            // Compare line C=>A with all edge vertices.
            bool v9  = IsPointRightOfLine(triangleVertexThree, triangleVertexOne, topLeftNodeEdge);
            bool v10 = IsPointRightOfLine(triangleVertexThree, triangleVertexOne, topRightNodeEdge);
            bool v11 = IsPointRightOfLine(triangleVertexThree, triangleVertexOne, bottomRightNodeEdge);
            bool v12 = IsPointRightOfLine(triangleVertexThree, triangleVertexOne, bottomLeftNodeEdge);

            // Check whether the node is inside the triangle.
            if (v1.AllEqual(v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12))
            {
                return(true);
            }

            #endregion Node Inside Triangle Tests: Determine if all of the node vertices are on the right side of the line, with vertices going clockwise.

            // Else return false;
            return(false);
        }