/// <summary>
        /// Loads all <see cref="Vertex"/> objects references by <paramref name="face"/> and loads their
        /// data into a <see cref="Mesh"/>, along with triangles, and returns the result.
        /// </summary>
        /// <param name="bsp">The <see cref="BSP"/> which <paramref name="face"/> comes from.</param>
        /// <param name="face">The <see cref="Face"/> to build a <see cref="Mesh"/> from.</param>
        /// <returns>A <see cref="Mesh"/> built from the data given by <paramref name="face"/>.</returns>
        public static Mesh CreateFaceMesh(BSP bsp, Face face, Vector2 dims, int curveTessellationLevel)
        {
            Mesh mesh = null;

            if (face.numVertices > 0)
            {
                if (face.firstIndex == 0 && face.numIndices == 0 && face.flags == 2)
                {
                    mesh = CreatePatchMesh(bsp, face, curveTessellationLevel);
                }
                else
                {
                    mesh = LoadVerticesFromFace(bsp, face);
                }
            }
            else if (face.numEdges > 0)
            {
                mesh = LoadVerticesFromEdges(bsp, face);
            }
            if (mesh != null)
            {
                TextureInfo textureInfo = bsp.GetTextureInfo(face);
                if (textureInfo.Data != null && textureInfo.Data.Length > 0)
                {
                    mesh.CalculateUVs(textureInfo, dims);
                }
                mesh.NegateVs();
            }
            return(mesh);
        }
        /// <summary>
        /// Builds a Displacement <see cref="Mesh"/> from the <see cref="DisplacementInfo"/> referenced by
        /// <paramref name="face"/>, with UVs calculated from <see cref="Face.textureInfo"/> using
        /// <paramref name="dims"/> as the <see cref="Texture2D"/> width and height.
        /// </summary>
        /// <param name="bsp">The <see cref="BSP"/> object which <paramref name="face"/> came from.</param>
        /// <param name="face">A face referencing a <see cref="DisplacementInfo"/> and a <see cref="TextureInfo"/>.</param>
        /// <param name="dims">The dimensions of the <see cref="Texture2D"/> to map onto the resulting <see cref="Mesh"/>.</param>
        /// <returns>The <see cref="Mesh"/> created from the <see cref="DisplacementInfo"/>.</returns>
        public static Mesh CreateDisplacementMesh(BSP bsp, Face face, Vector2 dims)
        {
            Mesh mesh = null;

            if (face.numEdges > 0)
            {
                mesh = LoadVerticesFromEdges(bsp, face);
            }
            else
            {
                Debug.LogWarning("Cannot create displacement, face contains no edges.");
                return(null);
            }

            Vector3[] faceCorners   = mesh.vertices;
            int[]     faceTriangles = mesh.triangles;
            if (faceCorners.Length != 4 || faceTriangles.Length != 6)
            {
                Debug.LogWarning("Cannot create displacement mesh because " + faceCorners.Length + " corners and " + faceTriangles.Length + " triangle indices.");
                return(null);
            }

            DisplacementInfo displacementInfo = bsp.dispInfos[face.displacement];
            int numSideTriangles = (int)Mathf.Pow(2, displacementInfo.power);

            DisplacementVertex[] displacementVertices = bsp.dispVerts.GetVerticesInDisplacement(displacementInfo.dispVertStart, displacementInfo.power);

            Vector3[] corners = new Vector3[4];
            Vector3   start   = displacementInfo.startPosition.SwizzleYZ() * inch2MeterScale;

            if ((faceCorners[faceTriangles[0]] - start).sqrMagnitude < .01f)
            {
                corners[0] = faceCorners[faceTriangles[0]];
                corners[1] = faceCorners[faceTriangles[1]];
                corners[2] = faceCorners[faceTriangles[5]];
                corners[3] = faceCorners[faceTriangles[4]];
            }
            else if ((faceCorners[faceTriangles[1]] - start).sqrMagnitude < .01f)
            {
                corners[0] = faceCorners[faceTriangles[1]];
                corners[1] = faceCorners[faceTriangles[4]];
                corners[2] = faceCorners[faceTriangles[0]];
                corners[3] = faceCorners[faceTriangles[5]];
            }
            else if ((faceCorners[faceTriangles[5]] - start).sqrMagnitude < .01f)
            {
                corners[0] = faceCorners[faceTriangles[5]];
                corners[1] = faceCorners[faceTriangles[0]];
                corners[2] = faceCorners[faceTriangles[4]];
                corners[3] = faceCorners[faceTriangles[1]];
            }
            else if ((faceCorners[faceTriangles[4]] - start).sqrMagnitude < .01f)
            {
                corners[0] = faceCorners[faceTriangles[4]];
                corners[1] = faceCorners[faceTriangles[5]];
                corners[2] = faceCorners[faceTriangles[1]];
                corners[3] = faceCorners[faceTriangles[0]];
            }
            else
            {
                Debug.LogWarning("Cannot create displacement mesh because start position isn't one of the face corners.\n" +
                                 "Start position: " + start + "\n" +
                                 "Corners: " + faceCorners[faceTriangles[0]] + " " + faceCorners[faceTriangles[1]] + " " + faceCorners[faceTriangles[5]] + " " + faceCorners[faceTriangles[4]]);
                return(null);
            }

            Vector3[] offsets = new Vector3[displacementVertices.Length];
            for (int i = 0; i < displacementVertices.Length; ++i)
            {
                offsets[i] = displacementVertices[i].normal.SwizzleYZ() * displacementVertices[i].dist * inch2MeterScale;
            }
            Vector2[] uv  = new Vector2[4];
            Vector2[] uv2 = new Vector2[4];

            mesh.vertices = corners;
            mesh.uv       = uv;
            mesh.uv2      = uv2;
            mesh.CalculateUVs(bsp.GetTextureInfo(face), dims);
            mesh.CalculateTerrainVertices(offsets, numSideTriangles);
            mesh.triangles = BuildDisplacementTriangles(numSideTriangles);
            mesh.NegateVs();
            mesh.RecalculateNormals();
            mesh.RecalculateBounds();

            return(mesh);
        }