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; } }
/// <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); }
/// <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); }