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