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; }); } }
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); }
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()); }
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]); }