Beispiel #1
0
    // Split any edges the given point lies on.
    private static void SplitEdgesWithPoint(List <Vector2> vertexes, List <IntTuple2> edges, int pointIndex)
    {
        Vector2          point    = vertexes[pointIndex];
        List <IntTuple2> newEdges = new List <IntTuple2>();

        foreach (IntTuple2 edge in edges)
        {
            if (IsOnLine(vertexes[edge.e0], vertexes[edge.e1], point))
            {
                int endIndex = edge.e1;
                edge.e1 = pointIndex;
                IntTuple2 newEdge = new IntTuple2(pointIndex, endIndex);
                newEdges.Add(newEdge);
            }
        }
        edges.AddRange(newEdges);
    }
    public void CreateNodes()
    {
        _nodes.Clear();

        // Create nodes
        for (int i = 0; i < NodeGridSize.x * NodeGridSize.y; i++)
        {
            int col = (i % NodeGridSize.x);
            int row = Mathf.FloorToInt(i / NodeGridSize.x);

            Node node = Instantiate <Node>(NodePrefab);
            node.transform.SetParent(this.transform);
            node.transform.position = new Vector3(col * NodeSpace.x, 0, (row * -NodeSpace.y));

            node.name   = i.ToString();
            node.Closed = false;

            if (StartNodePosition.x == col && StartNodePosition.y == row)
            {
                node.SetColor(Color.magenta);
                StartNode = node;
            }
            else if (EndNodePosition.x == col && EndNodePosition.y == row)
            {
                node.SetColor(Color.yellow);
                EndNode = node;
            }
            else
            {
                for (int j = 0; j < BlockNodes.Length; j++)
                {
                    IntTuple2 blockNode = BlockNodes[j];
                    if (blockNode.x == col && blockNode.y == row)
                    {
                        node.SetColor(Color.black);
                        node.IsBlock = true;
                    }
                }
            }

            _nodes.Add(node);
        }
    }
Beispiel #3
0
 private static bool IsOnLine(List <Vector2> vertexes, IntTuple2 line, int point)
 {
     return(IsOnLine(vertexes[line.e0], vertexes[line.e1], vertexes[point]));
 }
Beispiel #4
0
    private static int MakeIntersection(List <Vector2> vertexes, IntTuple2 line1, IntTuple2 line2)
    {
        Vector2 p1 = vertexes[line1.e0];
        Vector2 q1 = vertexes[line1.e1];
        Vector2 p2 = vertexes[line2.e0];
        Vector2 q2 = vertexes[line2.e1];

        // Lines with shared endpoints do not intersect.
        if (p1.Approximately(ref p2) || p1.Approximately(ref q2) || q1.Approximately(ref p2) || q1.Approximately(ref q2))
        {
            return(-1);
        }

        // Parallel lines do not intersect.
        float slope1 = GetSlope(p1, q1);
        float slope2 = GetSlope(p2, q2);

        if (Mathf.Approximately(slope1, slope2))
        {
            return(-1);
        }

        // Check if the lines end on each other.

        /*if (IsOnLine(vertexes, line1, line2.e0))
         * {
         *      return line2.e0;
         * }
         * if (IsOnLine(vertexes, line1, line2.e1))
         * {
         *      return line2.e1;
         * }
         * if (IsOnLine(vertexes, line2, line1.e0))
         * {
         *      return line1.e0;
         * }
         * if (IsOnLine(vertexes, line2, line1.e1))
         * {
         *      return line1.e1;
         * }*/

        // Calculate the intersection.
        float yInt1 = p1.y - slope1 * p1.x;
        float yInt2 = p2.y - slope2 * p2.x;

        float intersectionX = (yInt2 - yInt1) / (slope1 - slope2);
        float intersectionY = (slope1 * yInt2 - slope2 * yInt1) / (slope1 - slope2);

        // Check to see that the intersection point is in the bounding box.
        Vector2[] boundPoints = new Vector2[] { q1, p2, q2 };
        float     top         = p1.y;
        float     bottom      = p1.y;
        float     left        = p1.x;
        float     right       = p1.x;

        foreach (Vector2 point in boundPoints)
        {
            if (point.y < top)
            {
                top = point.y;
            }
            else if (point.y > bottom)
            {
                bottom = point.y;
            }
            if (point.x < left)
            {
                left = point.x;
            }
            else if (point.x > right)
            {
                right = point.x;
            }
        }

        if (intersectionX <= left || intersectionX >= right || intersectionY <= top || intersectionY >= bottom)
        {
            return(-1);
        }

        // The intersection is valid. See if we already have the vertex, or add it if we don't.
        Vector2 intersection  = new Vector2(intersectionX, intersectionY);
        int     existingIndex = vertexes.FindIndex(v => v.Approximately(intersection));

        if (existingIndex != -1)
        {
            return(existingIndex);
        }

        if (intersection.Approximately(ref p1) || intersection.Approximately(ref p2) || intersection.Approximately(ref q1) || intersection.Approximately(ref q2))
        {
            Debug.LogWarning("Created invalid vertex.");
        }
        vertexes.Add(intersection);
        return(vertexes.Count - 1);
    }
Beispiel #5
0
    // Split any edges that intersect with the given edge at their midpoint.
    private static void SplitEdgesWithEdge(List <Vector2> vertexes, List <IntTuple2> edges, IntTuple2 splitterEdge)
    {
        // Gather edge split data. These are tuples in the form (splitter vertex index, split edge index).
        List <IntTuple2> edgeSplitData     = new List <IntTuple2>();
        HashSet <int>    splitEdgeVertsSet = new HashSet <int>();

        splitEdgeVertsSet.Add(splitterEdge.e0);
        splitEdgeVertsSet.Add(splitterEdge.e1);
        for (int i = 0; i < edges.Count; ++i)
        {
            IntTuple2 curEdge           = edges[i];
            int       intersectionIndex = MakeIntersection(vertexes, splitterEdge, curEdge);

            // If the current edge had a vertex on the splitter edge, split the splitter edge but leave the current egde alone.
            if (curEdge.e0 == intersectionIndex || curEdge.e1 == intersectionIndex)
            {
                Debug.Log("Will split edge [" + vertexes[splitterEdge.e0] + ", " + vertexes[splitterEdge.e1] + "] at " + vertexes[intersectionIndex]);
                splitEdgeVertsSet.Add(intersectionIndex);
            }
            // If the splitter edge had a vertex on the current edge, split the current edge but leave the splitter edge alone.
            else if (splitterEdge.e0 == intersectionIndex || splitterEdge.e1 == intersectionIndex)
            {
                Debug.Log("Will split edge [" + vertexes[curEdge.e0] + ", " + vertexes[curEdge.e1] + "] at " + vertexes[intersectionIndex]);
                edgeSplitData.Add(new IntTuple2(intersectionIndex, i));
            }
            // If the edges met in the middle, split them both.
            else if (intersectionIndex != -1)
            {
                Debug.Log("Will split edge [" + vertexes[splitterEdge.e0] + ", " + vertexes[splitterEdge.e1] + "] at " + vertexes[intersectionIndex]);
                Debug.Log("Will split edge [" + vertexes[curEdge.e0] + ", " + vertexes[curEdge.e1] + "] at " + vertexes[intersectionIndex]);
                splitEdgeVertsSet.Add(intersectionIndex);
                edgeSplitData.Add(new IntTuple2(intersectionIndex, i));
            }
        }

        // DEBUG: Log stuff to figure out why splitting doesn't work as expected.

        /*if (edgeSplitData.Count > 0)
         * {
         *      string debugText = "Edge split data:\n";
         *      foreach (IntTuple2 splitData in edgeSplitData)
         *      {
         *              int vertexIndex = splitData.e0;
         *              int edgeIndex = splitData.e1;
         *
         *              Vector2 vertex = vertexes[vertexIndex];
         *              IntTuple2 edge = edges[edgeIndex];
         *
         *              debugText += ("[" + vertexes[edge.e0] + ", " + vertexes[edge.e1] + "] was split at " + vertex + "\n");
         *      }
         *      Debug.Log(debugText);
         * }
         *
         * if (splitEdgeVertsSet.Count > 0)
         * {
         *      string debugText = "Split edge verts set:\n";
         *      foreach (int vert in splitEdgeVertsSet)
         *      {
         *              debugText += vertexes[vert];
         *      }
         *      Debug.Log(debugText);
         * }*/

        // Split the edges.
        foreach (IntTuple2 splitData in edgeSplitData)
        {
            int intersectionIndex = splitData.e0;
            int edgeIndex         = splitData.e1;

            IntTuple2 edge = edges[edgeIndex];

            // Split the old edge in two.
            int oldEnd = edge.e1;
            edge.e1 = intersectionIndex;

            IntTuple2 newEdge = new IntTuple2(intersectionIndex, oldEnd);
            if (!edges.Contains(newEdge))
            {
                edges.Add(newEdge);
            }

            Debug.Log("Edge split into " + vertexes[edge.e0] + ", " + vertexes[intersectionIndex] + ", " + vertexes[newEdge.e1]);
        }

        // Make the new, split up edge to replace the old splitter edge from the vertexes.
        int[] splitEdgeVerts = new int[splitEdgeVertsSet.Count];
        splitEdgeVertsSet.CopyTo(splitEdgeVerts);
        Vector2 mostNegative = vertexes[splitEdgeVertsSet.MinBy(v => vertexes[v].x + vertexes[v].y)];

        System.Array.Sort <int>(splitEdgeVerts, (a, b) =>
        {
            Vector2 vA = vertexes[a] - mostNegative;
            Vector2 vB = vertexes[b] - mostNegative;
            return(vA.sqrMagnitude.CompareTo(vB.sqrMagnitude));
        }
                                );

        // DEBUG: Log the split edge verts.
        string debugText = "Split edge verts: ";

        foreach (int vertexIndex in splitEdgeVerts)
        {
            debugText += vertexes[vertexIndex] + ", ";
        }
        Debug.Log(debugText);

        // Create the new edges from the splitter edge data.
        for (int i = 1; i < splitEdgeVerts.Length; ++i)
        {
            int       vA      = splitEdgeVerts[i - 1];
            int       vB      = splitEdgeVerts[i];
            IntTuple2 newEdge = new IntTuple2(vA, vB);
            if (!edges.Contains(newEdge))
            {
                edges.Add(newEdge);
            }
        }
    }
Beispiel #6
0
    private static Mesh CreateLevelMesh(BuildingBlueprint.Level levelPlan)
    {
        // Set up.
        float wallHeight     = levelPlan._wallHeight;
        float wallHeightSqr  = wallHeight * wallHeight;
        float wallThickness  = levelPlan._wallThickness;
        float floorThickness = levelPlan._floorThickness;

        // Eliminate duplicate vertexes, split edges with vertexes in them, etc.
        List <Vector2>   vertexes = new List <Vector2>();     // Each is a point (x, z)
        List <IntTuple2> edges    = new List <IntTuple2>();   // Each is an edge (index1, index2) that indexes into vertexes.

        foreach (BuildingBlueprint.Wall wallPlan in levelPlan._walls)
        {
            for (int i = 1; i < wallPlan._points.Count; ++i)
            {
                IntTuple2 w1 = wallPlan._points[i - 1];
                IntTuple2 w2 = wallPlan._points[i];

                // Add the vertexes if we don't already have them.
                Vector2 p1 = new Vector2(w1.e0, w1.e1);
                Vector2 p2 = new Vector2(w2.e0, w2.e1);

                int  p1Index = vertexes.FindIndex(v => v.Approximately(p1));
                bool p1IsNew = false;
                if (p1Index == -1)
                {
                    p1Index = vertexes.Count;
                    vertexes.Add(p1);
                    p1IsNew = true;
                }

                int  p2Index = vertexes.FindIndex(v => v.Approximately(p2));
                bool p2IsNew = false;
                if (p2Index == -1)
                {
                    p2Index = vertexes.Count;
                    vertexes.Add(p2);
                    p2IsNew = true;
                }

                // DEBUG: Detect invalid walls.
                if (p1Index != -1 && p2Index != -1 && p1Index == p2Index)
                {
                    Debug.LogWarning("Invalid wall.");
                }

                // Split any edges p1 and p2 are on.
                if (p1IsNew)
                {
                    SplitEdgesWithPoint(vertexes, edges, p1Index);
                }
                if (p2IsNew)
                {
                    SplitEdgesWithPoint(vertexes, edges, p2Index);
                }

                // Don't add the edge if we already have it.
                IntTuple2 curEdge = new IntTuple2(p1Index, p2Index);
                if (edges.IndexOf(curEdge) == -1)
                {
                    // Resolve intersections by splitting the two edges at their midpoint.
                    SplitEdgesWithEdge(vertexes, edges, curEdge);
                }
            }
        }

        // DEBUG: Detect dupliacte vertexes.
        vertexes.DetectDuplicates("Detected duplicate vertex.");

        // DEBUG: Detect duplicate edges.
        edges.DetectDuplicates((left, right) => (left.e0 == right.e0 && left.e1 == right.e1) || (left.e1 == right.e0 && left.e0 == right.e1), "Detected duplicate edge.");

        // DEBUG: Detect invalid edges.
        foreach (IntTuple2 edge in edges)
        {
            if (edge.e0 == edge.e1)
            {
                Debug.LogWarning("Detected invalid edge.");
            }
        }

        // DEBUG: Log the edges.
        foreach (IntTuple2 edge in edges)
        {
            Vector2 a = vertexes[edge.e0];
            Vector2 b = vertexes[edge.e1];

            Debug.Log("[" + a + ", " + b + "]");
        }

        // Map the vertexes to the edges that contain them and the angle of each edge around the vertex.
        List <GenTuple2 <int, float> >[] vertsToEdges = new List <GenTuple2 <int, float> > [vertexes.Count];
        for (int i = 0; i < vertsToEdges.Length; ++i)
        {
            vertsToEdges[i] = new List <GenTuple2 <int, float> >();
        }
        for (int i = 0; i < edges.Count; ++i)
        {
            IntTuple2 edge = edges[i];
            vertsToEdges[edge.e0].Add(new GenTuple2 <int, float>(i, 0.0f));
            vertsToEdges[edge.e1].Add(new GenTuple2 <int, float>(i, 0.0f));
        }

        // Sort the edges in vertsToEdges by angle around the each vertex.
        for (int i = 0; i < vertsToEdges.Length; ++i)
        {
            Vector2 vertex = vertexes[i];

            List <GenTuple2 <int, float> > containingEdges = vertsToEdges[i];
            foreach (GenTuple2 <int, float> edgeAndAngle in containingEdges)
            {
                IntTuple2 edge           = edges[edgeAndAngle.e0];
                int       otherVertIndex = (edge.e0 == i) ? edge.e1 : edge.e0;
                Vector2   realEdge       = vertexes[otherVertIndex] - vertex;
                float     angle          = MathUtil.CounterClockwiseAngle(realEdge.y, realEdge.x);
                edgeAndAngle.e1 = angle;
            }

            containingEdges.Sort((left, right) => left.e1.CompareTo(right.e1));
        }

        // Extrude the vertexes into the wall cross-section.
        List <ExtrudedVertex> extrudedVertexes = new List <ExtrudedVertex>();

        for (int i = 0; i < vertexes.Count; ++i)
        {
            Vector2 vertex = vertexes[i];
            List <GenTuple2 <int, float> > containingEdges = vertsToEdges[i];
            Debug.Log("Extruding vertex " + vertex + " between " + containingEdges.Count + " edges.");

            if (containingEdges.Count > 1)
            {
                for (int j = 0, k = containingEdges.Count - 1; j < containingEdges.Count; k = j, ++j)
                {
                    GenTuple2 <int, float> edgeAndAngleJ = containingEdges[j];
                    IntTuple2 edgeJ      = edges[edgeAndAngleJ.e0];
                    float     edgeJAngle = edgeAndAngleJ.e1;

                    GenTuple2 <int, float> edgeAndAngleK = containingEdges[k];
                    IntTuple2 edgeK      = edges[edgeAndAngleK.e0];
                    float     edgeKAngle = edgeAndAngleK.e1;

                    if (edgeJAngle < edgeKAngle)
                    {
                        edgeJAngle += MathUtil.TWOPI;
                    }

                    float offsetAngle = (edgeJAngle + edgeKAngle) * 0.5f;
                    if (offsetAngle > MathUtil.TWOPI)
                    {
                        offsetAngle -= MathUtil.TWOPI;
                    }

                    Vector2 offset;
                    offset.x = Mathf.Cos(offsetAngle);
                    offset.y = Mathf.Sin(offsetAngle);

                    float interiorAngle   = Mathf.Abs(edgeJAngle - edgeKAngle);
                    float extrusionAmount = (wallThickness * 0.5f) / Mathf.Sin(interiorAngle * 0.5f);
                    offset *= extrusionAmount;

                    ExtrudedVertex newVert;
                    newVert.position              = vertex + offset;
                    newVert.parentVertex          = i;
                    newVert.parentAdjacentVertex0 = (edgeJ.e1 == i) ? edgeJ.e0 : edgeJ.e1;
                    newVert.parentAdjacentVertex1 = (edgeK.e1 == i) ? edgeK.e1 : edgeK.e0;

                    extrudedVertexes.Add(newVert);
                }
            }
            else if (containingEdges.Count == 1)
            {
                GenTuple2 <int, float> edgeAndAngle = containingEdges[0];
                IntTuple2 containingEdge            = edges[edgeAndAngle.e0];
                Vector3   edgeDirection;
                edgeDirection.x = Mathf.Cos(edgeAndAngle.e1);
                edgeDirection.y = 0.0f;
                edgeDirection.z = Mathf.Sin(edgeAndAngle.e1);

                Vector2 offset = (Quaternion.Euler(0.0f, 90.0f, 0.0f) * edgeDirection).SwizzleXZ();
                offset *= wallThickness * 0.5f;

                ExtrudedVertex newVert0;
                newVert0.position              = vertex + offset;
                newVert0.parentVertex          = i;
                newVert0.parentAdjacentVertex0 = (containingEdge.e0 == i) ? containingEdge.e1 : containingEdge.e0;
                newVert0.parentAdjacentVertex1 = -1;

                ExtrudedVertex newVert1 = newVert0;
                newVert1.position = vertex - offset;
                newVert1.parentAdjacentVertex0 = i;                 // Cap off ends.
                newVert1.parentAdjacentVertex1 = newVert0.parentAdjacentVertex0;

                extrudedVertexes.Add(newVert0);
                extrudedVertexes.Add(newVert1);
            }
        }

        // Find the edges between the extruded vertexes.
        List <IntTuple2> extrudedEdges = new List <IntTuple2>();

        for (int i = 0; i < extrudedVertexes.Count; ++i)
        {
            ExtrudedVertex eVertex      = extrudedVertexes[i];
            Vector2        parentVertex = vertexes[eVertex.parentVertex];

            if (eVertex.parentAdjacentVertex0 != -1)
            {
                Vector2 parentAdjacentVertex0 = vertexes[eVertex.parentAdjacentVertex0];
                Vector2 parentAdjacentEdgeDir = (parentAdjacentVertex0 - parentVertex).normalized;

                List <int> potentialEdgeMates = extrudedVertexes.FindAllIndexes(v => v.parentVertex == eVertex.parentAdjacentVertex0);
                potentialEdgeMates.Sort((left, right) =>
                {
                    ExtrudedVertex leftVert  = extrudedVertexes[left];
                    ExtrudedVertex rightVert = extrudedVertexes[right];
                    Vector2 leftEdgeDir      = (leftVert.position - eVertex.position).normalized;
                    Vector2 rightEdgeDir     = (rightVert.position - eVertex.position).normalized;
                    float leftDot            = Vector2.Dot(leftEdgeDir, parentAdjacentEdgeDir);
                    float rightDot           = Vector2.Dot(rightEdgeDir, parentAdjacentEdgeDir);
                    return(leftDot.CompareTo(rightDot));
                });

                int            edgeMateIndex = potentialEdgeMates[potentialEdgeMates.Count - 1];
                ExtrudedVertex edgeMate      = extrudedVertexes[edgeMateIndex];
                if (edgeMate.parentAdjacentVertex0 == eVertex.parentVertex)
                {
                    edgeMate.parentAdjacentVertex0 = -1;
                }
                else
                {
                    edgeMate.parentAdjacentVertex1 = -1;
                }
                extrudedVertexes[edgeMateIndex] = edgeMate;

                IntTuple2 newEdge = new IntTuple2(i, edgeMateIndex);
                extrudedEdges.Add(newEdge);
            }
            // Each vertex is only responsible for one edge, hence the "else".
            else if (eVertex.parentAdjacentVertex1 != -1)
            {
                Vector2 parentAdjacentVertex1 = vertexes[eVertex.parentAdjacentVertex1];
                Vector2 parentAdjacentEdgeDir = (parentAdjacentVertex1 - parentVertex).normalized;

                List <int> potentialEdgeMates = extrudedVertexes.FindAllIndexes(v => v.parentVertex == eVertex.parentAdjacentVertex1);
                potentialEdgeMates.Sort((left, right) =>
                {
                    ExtrudedVertex leftVert  = extrudedVertexes[left];
                    ExtrudedVertex rightVert = extrudedVertexes[right];
                    Vector2 leftEdgeDir      = (leftVert.position - eVertex.position).normalized;
                    Vector2 rightEdgeDir     = (rightVert.position - eVertex.position).normalized;
                    float leftDot            = Vector2.Dot(leftEdgeDir, parentAdjacentEdgeDir);
                    float rightDot           = Vector2.Dot(rightEdgeDir, parentAdjacentEdgeDir);
                    return(leftDot.CompareTo(rightDot));
                });

                int            edgeMateIndex = potentialEdgeMates[potentialEdgeMates.Count - 1];
                ExtrudedVertex edgeMate      = extrudedVertexes[edgeMateIndex];
                if (edgeMate.parentAdjacentVertex0 == eVertex.parentVertex)
                {
                    edgeMate.parentAdjacentVertex0 = -1;
                }
                else
                {
                    edgeMate.parentAdjacentVertex1 = -1;
                }
                extrudedVertexes[edgeMateIndex] = edgeMate;

                IntTuple2 newEdge = new IntTuple2(edgeMateIndex, i);
                extrudedEdges.Add(newEdge);
            }
        }

        // DEBUG: Detect duplicate extruded edges.
        extrudedEdges.DetectDuplicates((left, right) => (left.e0 == right.e0 && left.e1 == right.e1) || (left.e1 == right.e0 && left.e0 == right.e1), "Detected duplicate extruded edge.");

        // DEBUG: Log the extruded extrudedEdges.
        foreach (IntTuple2 edge in extrudedEdges)
        {
            Vector2 a = extrudedVertexes[edge.e0].position;
            Vector2 b = extrudedVertexes[edge.e1].position;

            Debug.Log("[" + a + ", " + b + "]");
        }

        // Break up the extruded edges so that, when raised into the wall mesh, they form squares.
        for (int i = 0, end = extrudedEdges.Count; i < end; ++i)         // Grab the end at the beginning so we can just add stuff onto the end but not loop over it.
        {
            IntTuple2 edge = extrudedEdges[i];
            Vector2   a    = extrudedVertexes[edge.e0].position;
            Vector2   b    = extrudedVertexes[edge.e1].position;

            float edgeLengthSqr = (b - a).sqrMagnitude;
            if (edgeLengthSqr > wallHeightSqr)
            {
                float edgeLength  = Mathf.Sqrt(edgeLengthSqr);
                int   numSegments = (int)(edgeLength / wallHeight);

                Vector2 edgeDir = (b - a);
                edgeDir.Normalize();

                IntTuple2 prevSegment  = edge;
                int       edgeEndIndex = edge.e1;
                for (int s = 1; s <= numSegments; ++s)
                {
                    Vector2 segmentStartPos = a + (s * wallHeight * edgeDir);

                    ExtrudedVertex segmentStartVert;
                    segmentStartVert.position              = segmentStartPos;
                    segmentStartVert.parentVertex          = -1;
                    segmentStartVert.parentAdjacentVertex0 = -1;
                    segmentStartVert.parentAdjacentVertex1 = -1;

                    extrudedVertexes.Add(segmentStartVert);
                    prevSegment.e1 = extrudedVertexes.Count - 1;

                    prevSegment = new IntTuple2(prevSegment.e1, edgeEndIndex);
                    extrudedEdges.Add(prevSegment);
                }
            }
        }

        // Use the extruded edges to make the wall mesh.
        List <Vector3> meshVerts = new List <Vector3>();
        List <Vector2> meshUVs   = new List <Vector2>();
        List <int>     meshTris  = new List <int>();

        foreach (IntTuple2 edge in extrudedEdges)
        {
            Vector3 a = extrudedVertexes[edge.e0].position.SwizzleX0Y();
            Vector3 b = extrudedVertexes[edge.e1].position.SwizzleX0Y();

            Vector3 c = a;
            c.y = wallHeight;
            Vector3 d = b;
            d.y = wallHeight;

            int iA = meshVerts.Count;
            meshVerts.Add(a);
            meshVerts.Add(b);
            meshVerts.Add(c);
            meshVerts.Add(d);

            float uvWidth = (b - a).magnitude / wallHeight;
            meshUVs.AddRange(new Vector2[] { new Vector2(0, 0), new Vector2(uvWidth, 0), new Vector2(0, 1), new Vector2(uvWidth, 1) });

            meshTris.AddRange(new int[] { iA, iA + 2, iA + 1 });             // A C B
            meshTris.AddRange(new int[] { iA + 2, iA + 3, iA + 1 });         // C D B
        }

        // Create the floor mesh by computing a constrained Delaunay triangulation of each floor polygon.
        foreach (BuildingBlueprint.Floor floorSection in levelPlan._floors)
        {
            // TODO(jwerner)
        }

        Mesh levelMesh = new Mesh();

        levelMesh.vertices  = meshVerts.ToArray();
        levelMesh.uv        = meshUVs.ToArray();
        levelMesh.triangles = meshTris.ToArray();
        levelMesh.RecalculateNormals();

        return(levelMesh);
    }