Esempio n. 1
0
        public static ValveTriangleFile FromProvider(string path, StudioModelFile mdl, ValveVertexFile vvd, params IResourceProvider[] providers)
        {
            var provider = providers.FirstOrDefault(x => x.ContainsFile(path));

            if (provider == null)
            {
                return(null);
            }

            using (var stream = provider.OpenFile(path))
            {
                return(new ValveTriangleFile(stream, mdl, vvd));
            }
        }
        public ValveTriangleFile(Stream stream, StudioModelFile mdl, ValveVertexFile vvd)
        {
            var outIndices  = new List <int>();
            var outVertices = new List <StudioVertex>();

            using (var reader = new BinaryReader(stream))
            {
                var version = reader.ReadInt32();

                Debug.Assert(version == 7);

                var vertCacheSize    = reader.ReadInt32();
                var maxBonesPerStrip = reader.ReadUInt16();
                var maxBonesPerTri   = reader.ReadUInt16();
                var maxBonesPerVert  = reader.ReadInt32();

                var checksum = reader.ReadInt32();

                var numLods = NumLods = reader.ReadInt32();
                var matReplacementListOffset = reader.ReadInt32();

                var origVerts = new StudioVertex[numLods][];

                for (var i = 0; i < numLods; ++i)
                {
                    origVerts[i] = new StudioVertex[vvd.GetVertexCount(i)];
                    vvd.GetVertices(i, origVerts[i]);
                }

                var numBodyParts   = reader.ReadInt32();
                var bodyPartOffset = reader.ReadInt32();

                var verts   = new List <OptimizedVertex>();
                var indices = new List <ushort>();

                _bodyParts = new BodyPartHeader[numBodyParts];

                var modelList    = new List <ModelHeader>();
                var modelLodList = new List <ModelLodHeader>();
                var meshList     = new List <MeshData>();

                reader.BaseStream.Seek(bodyPartOffset, SeekOrigin.Begin);
                LumpReader <BodyPartHeader> .ReadLumpFromStream(reader.BaseStream, numBodyParts, (bodyPartIndex, bodyPart) =>
                {
                    reader.BaseStream.Seek(bodyPart.ModelOffset, SeekOrigin.Current);

                    bodyPart.ModelOffset = modelList.Count;

                    LumpReader <ModelHeader> .ReadLumpFromStream(reader.BaseStream, bodyPart.NumModels, (modelIndex, model) =>
                    {
                        reader.BaseStream.Seek(model.LodOffset, SeekOrigin.Current);

                        model.LodOffset = modelLodList.Count;

                        LumpReader <ModelLodHeader> .ReadLumpFromStream(reader.BaseStream, model.NumLods, (lodIndex, lod) =>
                        {
                            // TODO
                            if (lodIndex > 0)
                            {
                                return;
                            }

                            reader.BaseStream.Seek(lod.MeshOffset, SeekOrigin.Current);

                            lod.MeshOffset = meshList.Count;

                            var lodVerts       = origVerts[lodIndex];
                            var firstLodIndex  = outVertices.Count;
                            var firstLodVertex = outVertices.Count;

                            LumpReader <MeshHeader> .ReadLumpFromStream(reader.BaseStream, lod.NumMeshes, (meshIndex, mesh) =>
                            {
                                var meshData = new MeshData
                                {
                                    LodIndexOffset  = firstLodIndex,
                                    LodVertexOffset = firstLodVertex,
                                    IndexOffset     = outIndices.Count,
                                    VertexOffset    = outVertices.Count
                                };

                                var meshInfo       = mdl.GetMesh(bodyPartIndex, modelIndex, meshIndex);
                                var origVertOffset = meshInfo.VertexOffset;

                                reader.BaseStream.Seek(mesh.StripGroupHeaderOffset, SeekOrigin.Current);
                                LumpReader <StripGroupHeader> .ReadLumpFromStream(reader.BaseStream, mesh.NumStripGroups, stripGroup =>
                                {
                                    verts.Clear();
                                    indices.Clear();

                                    var start = reader.BaseStream.Position;
                                    reader.BaseStream.Seek(start + stripGroup.VertOffset, SeekOrigin.Begin);
                                    LumpReader <OptimizedVertex> .ReadLumpFromStream(reader.BaseStream,
                                                                                     stripGroup.NumVerts, verts);

                                    var meshIndexOffset = outVertices.Count - firstLodVertex;
                                    for (var i = 0; i < verts.Count; ++i)
                                    {
                                        var vertIndex = origVertOffset + verts[i].OrigMeshVertId;
                                        if (vertIndex < 0 || vertIndex >= lodVerts.Length)
                                        {
                                            throw new IndexOutOfRangeException();
                                        }
                                        outVertices.Add(lodVerts[vertIndex]);
                                    }

                                    reader.BaseStream.Seek(start + stripGroup.IndexOffset, SeekOrigin.Begin);
                                    LumpReader <ushort> .ReadLumpFromStream(reader.BaseStream,
                                                                            stripGroup.NumIndices, indices);

                                    reader.BaseStream.Seek(start + stripGroup.StripOffset, SeekOrigin.Begin);
                                    LumpReader <StripHeader> .ReadLumpFromStream(reader.BaseStream, stripGroup.NumStrips, strip =>
                                    {
                                        Debug.Assert(strip.Flags != StripHeaderFlags.IsTriStrip);

                                        for (var i = 0; i < strip.NumIndices; ++i)
                                        {
                                            outIndices.Add(meshIndexOffset + indices[strip.IndexOffset + i]);
                                        }
                                    });
                                });

                                meshData.IndexCount  = outIndices.Count - meshData.IndexOffset;
                                meshData.VertexCount = outVertices.Count - meshData.VertexOffset;

                                meshList.Add(meshData);
                            });

                            modelLodList.Add(lod);
                        });

                        modelList.Add(model);
                    });

                    _bodyParts[bodyPartIndex] = bodyPart;
                });

                _models    = modelList.ToArray();
                _modelLods = modelLodList.ToArray();
                _meshes    = meshList.ToArray();

                _indices  = outIndices.ToArray();
                _vertices = outVertices.ToArray();
            }
        }