//    *
        //	 * Builds the mesh into the given TriangleBuffer
        //	 * @param buffer The TriangleBuffer on where to append the mesh.
        //	 * @exception Ogre::InvalidStateException Either shape or multishape must be defined!
        //	 * @exception Ogre::InvalidStateException Required parameter is zero!
        //
        //-----------------------------------------------------------------------
        //
        //ORIGINAL LINE: void addToTriangleBuffer(TriangleBuffer& buffer) const
        public override void addToTriangleBuffer(ref TriangleBuffer buffer)
        {
            if (mMultiShapeToExtrude.getShapeCount() == 0)
            {
                OGRE_EXCEPT("Ogre::Exception::ERR_INVALID_STATE", "At least one shape must be defined!", "Procedural::Extruder::addToTriangleBuffer(Procedural::TriangleBuffer)");
            }
            ;

            // Triangulate the begin and end caps
            if (mCapped && mMultiShapeToExtrude.isClosed())
            {
                GlobalMembers._extrudeCapImpl(ref buffer, mMultiShapeToExtrude, mMultiExtrusionPath, mScaleTracks, mRotationTracks);
            }

            // Extrude the paths contained in multiExtrusionPath
            for (uint j = 0; j < mMultiExtrusionPath.getPathCount(); ++j)
            {
                Path  extrusionPath = mMultiExtrusionPath.getPath((int)j);
                Track rotationTrack = null;
                if (mRotationTracks.find(j) != -1)                                        // mRotationTracks.end()) {
                {
                    rotationTrack = mRotationTracks[j];                                   //mRotationTracks.find(j).second;
                    extrusionPath = extrusionPath.mergeKeysWithTrack(mRotationTracks[j]); // (*mRotationTracks.find(j).second);
                }
                Track scaleTrack = null;
                if (mScaleTracks.find(j) != -1)                                        // mScaleTracks.end()) {
                {
                    rotationTrack = mScaleTracks[j];                                   //mScaleTracks.find(j).second;
                    extrusionPath = extrusionPath.mergeKeysWithTrack(mScaleTracks[j]); // (*mScaleTracks.find(j).second);
                }
                Track pathTextureTrack = null;
                if (mPathTextureTracks.find(j) != -1)                                           // mPathTextureTracks.end()) {
                {
                    pathTextureTrack = mPathTextureTracks[j];                                   //mPathTextureTracks.find(j).second;
                    extrusionPath    = extrusionPath.mergeKeysWithTrack(mPathTextureTracks[j]); //(*mPathTextureTracks.find(j).second);
                }

                std_vector <std_pair <uint, uint> > segs = mMultiExtrusionPath.getNoIntersectionParts(j);

                //for (List<std.pair<uint, uint>>.Enumerator it = segs.GetEnumerator(); it.MoveNext(); ++it) {
                foreach (var it in segs)
                {
                    for (uint i = 0; i < mMultiShapeToExtrude.getShapeCount(); i++)
                    {
                        Shape shapeToExtrude    = mMultiShapeToExtrude.getShape(i);
                        Track shapeTextureTrack = null;
                        if (mShapeTextureTracks.find(i) != -1)          // mShapeTextureTracks.end()) {
                        {
                            shapeTextureTrack = mShapeTextureTracks[i]; //mShapeTextureTracks.find(i).second;
                            shapeToExtrude.mergeKeysWithTrack(shapeTextureTrack);
                        }
                        GlobalMembers._extrudeBodyImpl(ref buffer, shapeToExtrude, extrusionPath, (int)it.first, (int)it.second, shapeTextureTrack, rotationTrack, scaleTrack, pathTextureTrack);
                    }
                }

                // Make the intersections
                //typedef std::vector<PathCoordinate> PathIntersection;
                std_vector <std_vector <MultiPath.PathCoordinate> > intersections = mMultiExtrusionPath.getIntersections();
                //for (List<MultiPath.PathIntersection>.Enumerator it = intersections.GetEnumerator(); it.MoveNext(); ++it) {
                foreach (var it in intersections)
                {
                    for (uint i = 0; i < mMultiShapeToExtrude.getShapeCount(); i++)
                    {
                        Track shapeTextureTrack = null;
                        if (mShapeTextureTracks.find(i) != -1)          // mShapeTextureTracks.end())
                        {
                            shapeTextureTrack = mShapeTextureTracks[i]; //mShapeTextureTracks.find(i).second;
                        }
                        GlobalMembers._extrudeIntersectionImpl(ref buffer, it, mMultiExtrusionPath, mMultiShapeToExtrude.getShape(i), shapeTextureTrack);
                    }
                }
            }
        }
        //-----------------------------------------------------------------------
        public static void _extrudeCapImpl(ref TriangleBuffer buffer, MultiShape multiShapeToExtrude, MultiPath extrusionMultiPath, TrackMap scaleTracks, TrackMap rotationTracks)
        {
            std_vector <int> indexBuffer = new std_vector <int>();
            // PointList pointList;
            std_vector <Vector2> pointList = new std_vector <Vector2>();

            Triangulator t = new Triangulator();

            t.setMultiShapeToTriangulate(multiShapeToExtrude);
            t.triangulate(indexBuffer, pointList);

            for (uint i = 0; i < extrusionMultiPath.getPathCount(); ++i)
            {
                Path  extrusionPath = extrusionMultiPath.getPath((int)i);
                Track scaleTrack    = null;
                Track rotationTrack = null;
                if (scaleTracks.find(i) != -1)         // scaleTracks.end())
                {
                    scaleTrack = scaleTracks[i];       //.find(i).second;
                }
                if (rotationTracks.find(i) != -1)      // rotationTracks.end())
                {
                    rotationTrack = rotationTracks[i]; //.find(i).second;
                }
                //begin cap
                //if (extrusionMultiPath.getIntersectionsMap().find(MultiPath.PathCoordinate(i, 0)) == extrusionMultiPath.getIntersectionsMap().end())
                if (extrusionMultiPath.getIntersectionsMap().find(new MultiPath.PathCoordinate(i, 0)) == -1)
                {
                    buffer.rebaseOffset();
                    buffer.estimateIndexCount((uint)indexBuffer.Count);
                    buffer.estimateVertexCount((uint)pointList.Count);

                    Quaternion qBegin = Utils._computeQuaternion(extrusionPath.getDirectionAfter(0));
                    if (rotationTrack != null)
                    {
                        float angle = rotationTrack.getFirstValue();
                        qBegin = qBegin * new Quaternion((Radian)angle, Vector3.UNIT_Z);
                    }
                    float scaleBegin = 1.0f;
                    if (scaleTrack != null)
                    {
                        scaleBegin = scaleTrack.getFirstValue();
                    }

                    for (int j = 0; j < pointList.size(); j++)
                    {
                        Vector2 vp2    = pointList[j];
                        Vector3 vp     = new Vector3(vp2.x, vp2.y, 0);
                        Vector3 normal = -Vector3.UNIT_Z;

                        Vector3 newPoint = extrusionPath.getPoint(0) + qBegin * (scaleBegin * vp);
                        buffer.vertex(newPoint, qBegin * normal, vp2);
                    }
                    for (int i2 = 0; i2 < indexBuffer.Count / 3; i2++)
                    {
                        buffer.index(indexBuffer[i2 * 3]);
                        buffer.index(indexBuffer[i2 * 3 + 2]);
                        buffer.index(indexBuffer[i2 * 3 + 1]);
                    }
                }

                //end cap
                //if (extrusionMultiPath.getIntersectionsMap().find(MultiPath.PathCoordinate(i, extrusionPath.getSegCount())) == extrusionMultiPath.getIntersectionsMap().end())
                if (extrusionMultiPath.getIntersectionsMap().find(new MultiPath.PathCoordinate(i, (uint)extrusionPath.getSegCount())) == -1)
                {
                    buffer.rebaseOffset();
                    buffer.estimateIndexCount((uint)indexBuffer.Count);
                    buffer.estimateVertexCount((uint)pointList.Count);

                    Quaternion qEnd = Utils._computeQuaternion(extrusionPath.getDirectionBefore(extrusionPath.getSegCount()));
                    if (rotationTrack != null)
                    {
                        float angle = rotationTrack.getLastValue();
                        qEnd = qEnd * new Quaternion((Radian)angle, Vector3.UNIT_Z);
                    }
                    float scaleEnd = 1.0f;
                    if (scaleTrack != null)
                    {
                        scaleEnd = scaleTrack.getLastValue();
                    }

                    for (int j = 0; j < pointList.Count; j++)
                    {
                        Vector2 vp2 = pointList[j];
                        Vector3 vp  = new Vector3(vp2.x, vp2.y, 0f);
                        //C++ TO C# CONVERTER WARNING: The following line was determined to be a copy constructor call - this should be verified and a copy constructor should be created if it does not yet exist:
                        //ORIGINAL LINE: Vector3 normal = Vector3::UNIT_Z;
                        Vector3 normal = (Vector3.UNIT_Z);

                        Vector3 newPoint = extrusionPath.getPoint(extrusionPath.getSegCount()) + qEnd * (scaleEnd * vp);
                        buffer.vertex(newPoint, qEnd * normal, vp2);
                    }
                    for (int ii = 0; ii < indexBuffer.Count / 3; ii++)
                    {
                        buffer.index(indexBuffer[ii * 3]);
                        buffer.index(indexBuffer[ii * 3 + 1]);
                        buffer.index(indexBuffer[ii * 3 + 2]);
                    }
                }
            }
        }