Mesh _AssembleMesh(ShapeStream shapeStream, Mesh.MeshEnum meshType)
        {
            if (meshType == Mesh.MeshEnum.StandardMeshType)
                return _AssembleStandardMesh(shapeStream, null);
            else if (meshType == Mesh.MeshEnum.SkinMeshType)
                return _AssembleSkinMesh(shapeStream);
            else if (meshType == Mesh.MeshEnum.SortedMeshType)
                return _AssembleSortedMesh(shapeStream);

            return null;
        }
        Mesh _AssembleStandardMesh(ShapeStream shapeStream, Mesh mesh)
        {
            try
            {
                if (mesh == null)
                    mesh = new Mesh();

                shapeStream.CheckGuard();

                mesh._numFrames = shapeStream.ReadS32();
                mesh._numMatFrames = shapeStream.ReadS32();
                mesh._parentMesh = shapeStream.ReadS32();
                shapeStream.ReadPoint3F(ref mesh._bounds.Min);
                shapeStream.ReadPoint3F(ref mesh._bounds.Max);
                shapeStream.ReadPoint3F(ref mesh._center);
                mesh._radius = shapeStream.ReadF32();

                int numVerts = shapeStream.ReadS32();
                mesh._verts = mesh._parentMesh < 0 ? shapeStream.ReadPoint3Fs(numVerts) : _shape.Meshes[mesh._parentMesh]._verts;

                int numTVerts = shapeStream.ReadS32();
                mesh._tverts = mesh._parentMesh < 0 ? shapeStream.ReadPoint2Fs(numTVerts) : _shape.Meshes[mesh._parentMesh]._tverts;

                // Version 26 added vertex color and texcoord2.
                if (Shape.ReadVersion > 25)
                {
                    int numTVerts2 = shapeStream.ReadS32();
                    if (numTVerts2 > 0)
                    {
                        if (mesh._parentMesh < 0)
                            mesh._tverts2 = shapeStream.ReadPoint2Fs(numTVerts2);
                        else
                            mesh._tverts2 = _shape.Meshes[mesh._parentMesh]._tverts2;
                    }

                    int numVColors = shapeStream.ReadS32();
                    if (numVColors > 0)
                    {
                        if (mesh._parentMesh < 0)
                            mesh._colors = shapeStream.ReadColors(numVColors);
                        else
                            mesh._colors = _shape.Meshes[mesh._parentMesh]._colors;
                    }
                }

                mesh._norms = mesh._parentMesh < 0 ? shapeStream.ReadPoint3Fs(numVerts) : _shape.Meshes[mesh._parentMesh]._norms;
                if (mesh._parentMesh < 0)
                    shapeStream.ReadU8s(numVerts); // Read past encoded normals

                int szPrim;
                ushort[] prim16;
                int[] prim32;
                int szInd;
                short[] ind16;

                // Version 26 has 32-bit indices.
                // We don't, so read them into our 16-bit buffers.
                if (Shape.ReadVersion > 25)
                {
                    szPrim = shapeStream.ReadS32();
                    int[] primIn = shapeStream.ReadS32s(szPrim * 3);

                    szInd = shapeStream.ReadS32();
                    int[] indIn = shapeStream.ReadS32s(szInd);

                    //
                    prim16 = new ushort[szPrim * 2];
                    prim32 = new int[szPrim];

                    int j = 0;
                    for (int i = 0; i < szPrim; i += 3)
                    {
                        prim16[j] = (ushort)primIn[i];
                        prim16[j + 1] = (ushort)primIn[i + 1];
                        prim32[j] = primIn[i + 2];

                        j++;
                    }

                    // Copy down the array of indices from 32-bit to 16.
                    ind16 = new short[szInd];
                    for (int i = 0; i < szInd; i++)
                        ind16[i] = (short)indIn[i];
                }
                else
                {
                    // Copy the _primitives and _indices...how we do this depends on what
                    // form we want them in when copied...first just get the data
                    szPrim = shapeStream.ReadS32();
                    prim16 = shapeStream.ReadU16s(szPrim * 2); // start, numElements
                    prim32 = shapeStream.ReadS32s(szPrim);     // matIndex

                    szInd = shapeStream.ReadS32();
                    ind16 = shapeStream.ReadS16s(szInd);
                }

                // count then Copy...
                int cpyPrim, cpyInd;
                if (_useTriangles)
                    _ConvertToTris(prim16, prim32, ind16, szPrim, out cpyPrim, out cpyInd, null, null);
                else if (_useOneStrip)
                    _ConvertToSingleStrip(prim16, prim32, ind16, szPrim, out cpyPrim, out cpyInd, null, null);
                else
                    _LeaveAsMultipleStrips(prim16, prim32, ind16, szPrim, out cpyPrim, out cpyInd, null, null);
                mesh._primitives = new DrawPrimitive[cpyPrim];
                mesh._indices = new short[cpyInd];

                // _primitives and _indices counted and allocated above, now Copy them in
                int chkPrim;
                int chkInd;
                if (_useTriangles)
                    _ConvertToTris(prim16, prim32, ind16, szPrim, out chkPrim, out chkInd, mesh._primitives, mesh._indices);
                else if (_useOneStrip)
                    _ConvertToSingleStrip(prim16, prim32, ind16, szPrim, out chkPrim, out chkInd, mesh._primitives, mesh._indices);
                else
                    _LeaveAsMultipleStrips(prim16, prim32, ind16, szPrim, out chkPrim, out chkInd, mesh._primitives, mesh._indices);

                Assert.Fatal(chkPrim == cpyPrim && chkInd == cpyInd, "TSShapeReader._AssembleStandardMesh - DrawPrimitive conversion error.");

                // Read in merge _indices...deprecated
                int numMerge = shapeStream.ReadS32();
                shapeStream.ReadS16s(numMerge);

                mesh._vertsPerFrame = shapeStream.ReadS32();
                mesh.SetFlags((Mesh.MeshEnum)shapeStream.ReadU32());

                shapeStream.CheckGuard();
            }
            catch
            { }

            return mesh;
        }
        void _RenderMesh(ref ObjectInstance obj, int objectDetail, Material[] materialList, SceneRenderState srs)
        {
            if (obj.Visibility > 0.01f)
            {
                mesh = _GetMesh(ref obj.Object, objectDetail);

                if (mesh != null)
                {
                    srs.World.Push();

                    if (obj.Object.NodeIndex >= 0)
                        srs.World.MultiplyMatrixLocal(_nodeTransforms[obj.Object.NodeIndex]);

                    mesh.Render(obj.Frame, obj.MaterialFrame, materialList, srs);

                    srs.World.Pop();
                }
            }
        }