Beispiel #1
0
        public MdlFile(IResourceProvider loader, string filename)
        {
            _loader       = loader;
            _baseFilename = filename.Substring(0, filename.Length - ".mdl".Length);

            using (var stream = loader.OpenFile(filename))
            {
                _header = ReadLumpWrapper <Header> .ReadSingleFromStream(stream);

                _materials     = new StudioTexture[_header.NumTextures];
                _materialNames = new string[_header.NumTextures];

                stream.Seek(_header.TextureIndex, SeekOrigin.Begin);

                var index = 0;
                ReadLumpWrapper <StudioTexture> .ReadLumpFromStream(stream, _header.NumTextures, tex =>
                {
                    _materials[index] = tex;

                    stream.Seek(tex.NameIndex, SeekOrigin.Current);
                    _materialNames[index] = ReadNullTerminatedString(stream) + ".vmt";
                    ++index;
                });
            }
        }
Beispiel #2
0
        private Color[] ReadVertexSamples <TVertex>(Stream stream, int lodLevel, int meshCount)
            where TVertex : struct, IVertexData
        {
            var indexMap = GetVertIndexMap(lodLevel);
            var verts    = GetVertices(lodLevel);

            var meshHeaders = new List <VhvMeshHeader>();

            ReadLumpWrapper <VhvMeshHeader> .ReadLumpFromStream(stream, meshCount, meshHeaders);

            var sampleList = new List <TVertex>();
            var output     = new Color[verts.Length];

            var meshIndex = 0;

            foreach (var meshHeader in meshHeaders)
            {
                if (meshHeader.Lod != lodLevel)
                {
                    continue;
                }
                if (meshHeader.VertCount == 0)
                {
                    continue;
                }
                if (meshIndex >= indexMap.Length)
                {
                    break;
                }

                sampleList.Clear();

                stream.Seek(meshHeader.VertOffset, SeekOrigin.Begin);
                ReadLumpWrapper <TVertex> .ReadLumpFromStream(stream, meshHeader.VertCount, sampleList);

                var map = indexMap[meshIndex];

                for (var i = 0; i < sampleList.Count; ++i)
                {
                    output[map[i]] = sampleList[i].GetVertexColor();
                }

                meshIndex += 1;
            }

            return(output);
        }
Beispiel #3
0
        private int[][] GetTriangles(int lodLevel)
        {
            if (_triangles[lodLevel] != null)
            {
                return(_triangles[lodLevel]);
            }

            var filePath    = _baseFilename + ".dx90.vtx";
            var outIndices  = new List <List <int> >();
            var outIndexMap = new List <int[]>();

            using (var stream = _loader.OpenFile(filePath))
                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 = reader.ReadInt32();
                    var matReplacementListOffset = reader.ReadInt32();

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

                    var lodIndex = 0;

                    //var materialNameBuilder = new StringBuilder();

                    //reader.BaseStream.Seek(matReplacementListOffset, SeekOrigin.Begin);
                    //ReadLumpWrapper<MaterialReplacementListHeader>.ReadLumpFromStream(reader.BaseStream, numLods, materialList =>
                    //{
                    //    if (lodIndex++ != lodLevel) return;

                    //    reader.BaseStream.Seek(materialList.ReplacementOffset, SeekOrigin.Current);
                    //    ReadLumpWrapper<MaterialReplacementHeader>.ReadLumpFromStream(reader.BaseStream, numLods, material =>
                    //    {
                    //        if (material.ReplacementMaterialNameOffset == 0 || material.ReplacementMaterialNameOffset == 0xffff) return;

                    //        materialNameBuilder.Remove(0, materialNameBuilder.Length);

                    //        char ch;

                    //        reader.BaseStream.Seek(material.ReplacementMaterialNameOffset, SeekOrigin.Current);
                    //        while ((ch = reader.ReadChar()) != '\0') materialNameBuilder.Append(ch);

                    //        var materialName = materialNameBuilder.ToString();
                    //        Debug.Log(materialName);
                    //    });
                    //});

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

                    var meshIndex = 0;

                    reader.BaseStream.Seek(bodyPartOffset, SeekOrigin.Begin);
                    ReadLumpWrapper <BodyPartHeader> .ReadLumpFromStream(reader.BaseStream, numBodyParts, bodyPart =>
                    {
                        reader.BaseStream.Seek(bodyPart.ModelOffset, SeekOrigin.Current);
                        ReadLumpWrapper <ModelHeader> .ReadLumpFromStream(reader.BaseStream, bodyPart.NumModels, model =>
                        {
                            reader.BaseStream.Seek(model.LodOffset, SeekOrigin.Current);

                            lodIndex = 0;
                            ReadLumpWrapper <ModelLodHeader> .ReadLumpFromStream(reader.BaseStream, model.NumLods, lod =>
                            {
                                if (lodIndex++ != lodLevel)
                                {
                                    return;
                                }

                                var skip = 0;

                                reader.BaseStream.Seek(lod.MeshOffset, SeekOrigin.Current);
                                ReadLumpWrapper <MeshHeader> .ReadLumpFromStream(reader.BaseStream, lod.NumMeshes, mesh =>
                                {
                                    List <int> meshIndices;
                                    if (outIndices.Count <= meshIndex)
                                    {
                                        outIndices.Add(meshIndices = new List <int>());
                                    }
                                    else
                                    {
                                        meshIndices = outIndices[meshIndex];
                                    }

                                    Debug.Assert(mesh.NumStripGroups == 1);

                                    indexMap.Clear();

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

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

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

                                        for (var i = 0; i < verts.Count; ++i)
                                        {
                                            indexMap.Add(verts[i].OrigMeshVertId + skip);
                                        }

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

                                            for (var i = 0; i < strip.NumIndices; ++i)
                                            {
                                                var index = indices[strip.IndexOffset + i];
                                                var vert  = verts[index];

                                                meshIndices.Add(strip.VertOffset + vert.OrigMeshVertId + skip);
                                            }
                                        });

                                        // Why?
                                        skip += verts.Max(x => x.OrigMeshVertId) + 1;
                                    });

                                    outIndexMap.Add(indexMap.ToArray());

                                    meshIndex += 1;
                                });
                            });
                        });
                    });
                }

            _vertIndexMap[lodLevel] = outIndexMap.ToArray();
            return(_triangles[lodLevel] = outIndices.Select(x => x.ToArray()).ToArray());
        }
Beispiel #4
0
        private StudioVertex[] GetVertices(int lod)
        {
            if (_vertices != null)
            {
                return(_vertices[lod]);
            }

            var filePath = _baseFilename + ".vvd";

            using (var stream = _loader.OpenFile(filePath))
                using (var reader = new BinaryReader(stream))
                {
                    var id      = reader.ReadInt32();
                    var version = reader.ReadInt32();

                    Debug.Assert(id == 0x56534449);
                    Debug.Assert(version == 4);

                    reader.ReadInt32();

                    var numLods     = reader.ReadInt32();
                    var numLodVerts = new int[8];

                    for (var i = 0; i < numLodVerts.Length; ++i)
                    {
                        numLodVerts[i] = reader.ReadInt32();
                    }

                    var numFixups        = reader.ReadInt32();
                    var fixupTableStart  = reader.ReadInt32();
                    var vertexDataStart  = reader.ReadInt32();
                    var tangentDataStart = reader.ReadInt32();

                    var fixupList = new List <VertexFixup>();
                    var vertList  = new List <StudioVertex>();

                    if (numFixups > 0)
                    {
                        reader.BaseStream.Seek(fixupTableStart, SeekOrigin.Begin);
                        ReadLumpWrapper <VertexFixup> .ReadLumpFromStream(reader.BaseStream, numFixups, fixupList);
                    }

                    reader.BaseStream.Seek(vertexDataStart, SeekOrigin.Begin);
                    ReadLumpWrapper <StudioVertex> .ReadLumpFromStream(reader.BaseStream, (tangentDataStart - vertexDataStart) / Marshal.SizeOf(typeof(StudioVertex)), vertList);

                    _vertices = new StudioVertex[numLods][];

                    var lodVerts = new List <StudioVertex>();

                    for (var i = 0; i < numLods; ++i)
                    {
                        if (numFixups == 0)
                        {
                            _vertices[i] = vertList.Take(numLodVerts[i]).ToArray();
                            continue;
                        }

                        lodVerts.Clear();

                        foreach (var vertexFixup in fixupList)
                        {
                            if (vertexFixup.Lod >= i)
                            {
                                lodVerts.AddRange(vertList.Skip(vertexFixup.SourceVertexId).Take(vertexFixup.NumVertices));
                            }
                        }

                        _vertices[i] = lodVerts.ToArray();
                    }
                }

            return(_vertices[lod]);
        }