/// <summary>
    /// @TODO - Could split this function up to run over multiple frames by turning it into a Coroutine
    /// and calling 'yield return null'
    ///     Could also use Threading
    /// @TODO - Could also set the # of vertices on each bend to a constant value so that we can
    /// avoid reallocating new vertices each time.
    /// </summary>
    public static void GenerateConduit(Conduit conduit)
    {
#if UNITY_EDITOR
        if (conduit.bend.conduitOrder.Count < 2)
        {
            Debug.LogError("ConduitGenerator: GenerateConduit() Invalid Conduit Order.");
            return;
        }
#endif
        // Start Fresh
        conduit.Clear();

        var conduitOrder   = conduit.bend.conduitOrder;
        var bentCenterline = conduit.centerline;
        var bentCenterlineBendStartIndices = conduit.centerlineBendIndices;
        //var straightCenterline = conduit.centerline;
        //var straightCenterlineBendStartIndices = conduit.centerlineBendIndices;

        Vector3 startPosition = Vector3.zero;
        Vector3 radialCenter;
        Vector3 reverseRadial;

        Quaternion       rot;
        Marker           currConduitMark = null;
        CenterlineMarker prevCenterMark  = new CenterlineMarker(startPosition, conduitOrder[0].forwardDir, conduitOrder[0].radialDir, 0f);
        CenterlineMarker currCenterMark  = new CenterlineMarker();

        float distSoFar = 0f;
        float degPerRotate;
        int   numRotations;

        // Record starting centerline point
        bentCenterline.Add(prevCenterMark);

        //----------------------------------------------------
        // Build the 'Bent' and 'Straight' Conduit Centerline
        //----------------------------------------------------
        for (int i = 1; i < conduitOrder.Count; ++i)
        {
            currConduitMark = conduitOrder[i];

            // ConduitMarker (Calculate next 'straight segment' centerline vertice)
            currCenterMark.Set(
                prevCenterMark.point + (currConduitMark.distFromStartM - distSoFar) * prevCenterMark.forwardDir,
                currConduitMark.forwardDir,
                currConduitMark.radialDir,
                currConduitMark.distFromStartM
                );
            prevCenterMark.Set(currCenterMark.point, currCenterMark.forwardDir, currCenterMark.radialDir, currCenterMark.distFromStartM);
            distSoFar = currConduitMark.distFromStartM;


            if (currConduitMark is BendMarker)
            {
                // BendMarker
                BendMarker currBendMark = (BendMarker)currConduitMark;

                // Add new Centerline Marker
                bentCenterline.Add(currCenterMark);
                bentCenterlineBendStartIndices.Add(new CenterlineIndice(BendMarkType.Start, bentCenterline.Count - 1));

                radialCenter  = (currCenterMark.point + currBendMark.radialDir * currBendMark.radiusM);
                reverseRadial = Vector3.Normalize(currCenterMark.point - radialCenter);
                numRotations  = (int)Mathf.Ceil(currBendMark.angleDeg / s_DegreesPerVerticeSet);
                degPerRotate  = currBendMark.angleDeg / numRotations;

                // Negative angle results in counterclockwise rotation (which is what we want for our Bender)
                // Positive angle results in clockwise rotation
                rot = Quaternion.AngleAxis(-degPerRotate, Vector3.Cross(currBendMark.radialDir, currBendMark.forwardDir));
                float lbPerRotate = Lb(currBendMark.radiusM, degPerRotate * Mathf.Deg2Rad);

                // Iterate through entire rotation
                for (int r = 0; r < numRotations; ++r)
                {
                    reverseRadial = rot * reverseRadial;

                    currCenterMark.Set(
                        radialCenter + reverseRadial * currBendMark.radiusM,
                        rot * prevCenterMark.forwardDir,
                        rot * prevCenterMark.radialDir,
                        (distSoFar + lbPerRotate * (r + 1))
                        );
                    prevCenterMark.Set(currCenterMark.point, currCenterMark.forwardDir, currCenterMark.radialDir, currCenterMark.distFromStartM);

                    // Record Centerline Vertices
                    bentCenterline.Add(currCenterMark);
                }
                bentCenterlineBendStartIndices.Add(new CenterlineIndice(BendMarkType.End, bentCenterline.Count - 1));

                // Update centerline distance so far
                distSoFar += Lb(currBendMark.radiusM, currBendMark.angleDeg * Mathf.Deg2Rad);
            }
            else
            {
                // Add new Centerline Marker
                bentCenterline.Add(currCenterMark);
            }
        }

        //-------------------------------------------
        // Build the bent 'Mesh'
        //-------------------------------------------
        // To Create SubMeshes:
        // Use Mesh.subMeshCount to set the number of submeshes, then SetTriangles() to set the triangle list for each submesh.
        // There isn't a "main" mesh in this case. Then, make a Material array (where each material corresponds to each submesh),
        // and set renderer.materials to that Material array.

        // Make Conduit Vertices
        Vector3[] conduitVerts     = new Vector3[s_NumberOfSides * bentCenterline.Count];
        Vector2[] conduitUVs       = new Vector2[s_NumberOfSides * bentCenterline.Count];
        int[]     conduitTriangles = new int[s_NumberOfSides * 6 * (bentCenterline.Count - 1)]; // Indices

        // Get Reference to Circle Mesh Vertices
        var circleVerts = s_CircleVertices;

        // Move Circle Mesh Along Centerline, Rotate, and Record Vertice Positions
        Vector3 prevForwardDir = Vector3.forward;
        for (int v = 0; v < bentCenterline.Count; ++v)
        {
            // @TODO - Could make this more efficient by caching the rotation from the centerline calculations
            // @TODO - Could also use the SetFromToRotation instead of allocating new Quaternion each time
            rot = Quaternion.FromToRotation(prevForwardDir, bentCenterline[v].forwardDir);

            for (int s = 0; s < s_NumberOfSides; ++s)
            {
                conduitVerts[v * s_NumberOfSides + s] = (rot * circleVerts[s + 1]) + (bentCenterline[v].point - bentCenterline[0].point);
            }
        }
        // B   D
        // |\``|
        // | \ |
        // |__\|
        // A   C
        int C;
        int totalSides = s_NumberOfSides * (bentCenterline.Count - 1);
        for (int s = 0, t; s < totalSides; ++s)
        {
            //int sideStartI = (s % m_NumberOfSides) + (s / m_NumberOfSides) * m_NumberOfSides; // 4 vertices per side
            t = s * 6;

            if ((s + 1) % s_NumberOfSides == 0)
            {
                C = (s / s_NumberOfSides) * s_NumberOfSides;
            }
            else
            {
                C = s + 1;
            }
            // Bottom Triangle
            conduitTriangles[t]     = s;                              // A
            conduitTriangles[t + 1] = s + s_NumberOfSides;            // B
            conduitTriangles[t + 2] = C;                              // C

            // Top Triangle
            conduitTriangles[t + 3] = C;                              // C
            conduitTriangles[t + 4] = s + s_NumberOfSides;            // B
            conduitTriangles[t + 5] = C + s_NumberOfSides;            // D
        }
        // Calculate UVs
        // TODO: (Currently these UVs are stretched/compressed along the bent areas - i.e. inaccurate)
        for (int i = 0; i < conduitUVs.Length; ++i)
        {
            conduitUVs[i] = new Vector2(circleVerts[i % s_NumberOfSides].x, (i % s_NumberOfSides) / (float)bentCenterline.Count);
        }

        conduit.SetMesh(conduitVerts, conduitUVs, conduitTriangles);
        conduit.conduitDiameterM = conduitDiameterM;

        // Remember Conduit Data
        s_LastConduitVerts = conduitVerts;
        s_LastConduitUVs   = conduitUVs;
        s_LastConduitTris  = conduitTriangles;

        //Debug.Log( "ConduitGenerator: GenerateConduit() Model Name: " + conduit.bend.modelName );
    }  // End GenConduitMesh()