public static Transform LoadMdl(string ModelName) { Clear(); string OpenPath = string.Concat(WorldController.GamePath, WorldController.ModName, ModelName); ModelObject = new GameObject(ModelName); if (!File.Exists(OpenPath + ".mdl")) { return(ModelObject.transform); } // ----- BEGIN READ MDL, VVD, VTX ----- // CRead = new CustomReader(new BinaryReader(File.OpenRead(OpenPath + ".mdl"))); MDL_Header = CRead.ReadType <studiohdr_t>(0); ParseMdlFile(); CRead = new CustomReader(new BinaryReader(File.OpenRead(OpenPath + ".vvd"))); VVD_Header = CRead.ReadType <vertexFileHeader_t>(0); ParseVvdFile(); CRead = new CustomReader(new BinaryReader(File.OpenRead(OpenPath + ".dx90.vtx"))); VTX_Header = CRead.ReadType <FileHeader_t>(0); ParseVtxFile(); // ----- END READ MDL, VVD, VTX ----- // return(ModelObject.transform); }
public static Transform Load(string ModelName) { Clear(); string OpenPath = string.Concat(Configuration.GameFld, Configuration.Mod, ModelName); ModelObject = new GameObject(ModelName); if (!File.Exists(OpenPath + ".mdl")) return ModelObject.transform; CRead = new CustomReader(File.OpenRead(OpenPath + ".mdl")); MDL_Header = CRead.ReadType<studiohdr_t>(); ParseMdlFile(); CRead = new CustomReader(File.OpenRead(OpenPath + ".vvd")); VVD_Header = CRead.ReadType<vertexFileHeader_t>(); ParseVvdFile(); CRead = new CustomReader(File.OpenRead(OpenPath + ".dx90.vtx")); VTX_Header = CRead.ReadType<FileHeader_t>(); ParseVtxFile(); if (!Configuration.Models.ContainsKey(ModelObject.name)) Configuration.Models.Add(ModelName, ModelObject.transform); CRead.Dispose(); return ModelObject.transform; }
public void Dispose() { Header = new studiohdr_t(); Header2 = new studiohdr2_t(); BR.Dispose(); if (stream != null) { stream.Dispose(); } }
void ParseHeader() { //BR.BaseStream.Seek(0, SeekOrigin.Begin); //string c = Encoding.ASCII.GetString(BR.ReadBytes(4)); BR.BaseStream.Seek(0, SeekOrigin.Begin); Header = new studiohdr_t(); Header.id = BR.ReadInt32(); if (Header.id != IDMDLHEADER) { throw new Exception("Not an MDL file! (wrong id)"); } Header.version = BR.ReadInt32(); Header.checksum = BR.ReadInt32(); Header.name = BR.ReadString(64); Header.length = BR.ReadInt32(); Header.eyeposition = BR.ReadVector(); Header.illumposition = BR.ReadVector(); Header.hull_min = BR.ReadVector(); Header.hull_max = BR.ReadVector(); Header.view_bbmin = BR.ReadVector(); Header.view_bbmax = BR.ReadVector(); Header.flags = BR.ReadInt32(); Header.numbones = BR.ReadInt32(); Header.boneindex = BR.ReadInt32(); Header.numbonecontrollers = BR.ReadInt32(); Header.bonecontrollerindex = BR.ReadInt32(); Header.numhitboxsets = BR.ReadInt32(); Header.hitboxsetindex = BR.ReadInt32(); Header.numlocalanim = BR.ReadInt32(); Header.localanimindex = BR.ReadInt32(); Header.numlocalseq = BR.ReadInt32(); Header.localseqindex = BR.ReadInt32(); Header.activitylistversion = BR.ReadInt32(); Header.eventsindexed = BR.ReadInt32(); Header.numtextures = BR.ReadInt32(); Header.textureindex = BR.ReadInt32(); Header.numcdtextures = BR.ReadInt32(); Header.cdtextureindex = BR.ReadInt32(); Header.numskinref = BR.ReadInt32(); Header.numskinfamilies = BR.ReadInt32(); Header.skinindex = BR.ReadInt32(); Header.numbodyparts = BR.ReadInt32(); Header.bodypartindex = BR.ReadInt32(); Header.numlocalattachments = BR.ReadInt32(); Header.localattachmentindex = BR.ReadInt32(); Header.numlocalnodes = BR.ReadInt32(); Header.localnodeindex = BR.ReadInt32(); Header.localnodenameindex = BR.ReadInt32(); Header.numflexdesc = BR.ReadInt32(); Header.flexdescindex = BR.ReadInt32(); Header.numflexcontrollers = BR.ReadInt32(); Header.flexcontrollerindex = BR.ReadInt32(); Header.numflexrules = BR.ReadInt32(); Header.flexruleindex = BR.ReadInt32(); Header.numikchains = BR.ReadInt32(); Header.ikchainindex = BR.ReadInt32(); Header.nummouths = BR.ReadInt32(); Header.mouthindex = BR.ReadInt32(); Header.numlocalposeparameters = BR.ReadInt32(); Header.localposeparamindex = BR.ReadInt32(); Header.surfacepropindex = BR.ReadInt32(); Header.keyvalueindex = BR.ReadInt32(); Header.keyvaluesize = BR.ReadInt32(); Header.numlocalikautoplaylocks = BR.ReadInt32(); Header.localikautoplaylockindex = BR.ReadInt32(); Header.mass = BR.ReadSingle(); Header.contents = BR.ReadInt32(); Header.numincludemodels = BR.ReadInt32(); Header.includemodelindex = BR.ReadInt32(); //Header.unused_virtualModel = BR.ReadInt32(); BR.BaseStream.Seek(4, SeekOrigin.Current); Header.szanimblocknameindex = BR.ReadInt32(); Header.numanimblocks = BR.ReadInt32(); Header.animblockindex = BR.ReadInt32(); Header.unused_animblockModel = BR.ReadInt32(); Header.bonetablebynameindex = BR.ReadInt32(); //Header.unused_pVertexBase = BR.ReadInt32(); //Header.unused_pIndexBase = BR.ReadInt32(); BR.BaseStream.Seek(8, SeekOrigin.Current); Header.constdirectionallightdot = BR.ReadByte(); Header.rootLOD = BR.ReadByte(); Header.numAllowedRootLODs = BR.ReadByte(); //Header.unused = BR.ReadByte(); //Header.unused4 = BR.ReadInt32(); BR.BaseStream.Seek(5, SeekOrigin.Current); Header.numflexcontrollerui = BR.ReadInt32(); Header.flexcontrolleruiindex = BR.ReadInt32(); Header.flVertAnimFixedPointScale = BR.ReadSingle(); Header.surfacepropLookup = BR.ReadInt32(); Header.studiohdr2index = BR.ReadInt32(); //Header.unused2 = BR.ReadInt32(); BR.BaseStream.Seek(4, SeekOrigin.Current); }
public VTXFile(Stream FileInput, MDLFile StudioMDL, VVDFile StudioVVD) { using (uReader FileStream = new uReader(FileInput)) { studiohdr_t MDL_Header = StudioMDL.MDL_Header; FileStream.ReadTypeFixed(ref VTX_Header, 36); if (VTX_Header.checkSum != MDL_Header.checksum) { throw new FileLoadException(String.Format("{0}: Does not match the checksum in the .mdl", MDL_Header.Name)); } #region BodyParts Int32[] VertexLODOffsets = new Int32[8]; for (Int32 BodypartID = 0; BodypartID < MDL_Header.bodypart_count; BodypartID++) { BodyPartHeader_t BodyPart = new BodyPartHeader_t(); Int64 BodyPartOffset = VTX_Header.bodyPartOffset + (8 * BodypartID); FileStream.ReadTypeFixed(ref BodyPart, 8, BodyPartOffset); StudioBodyPart StudioBodyPart = StudioMDL.MDL_Bodyparts[BodypartID]; #region Models for (Int32 ModelID = 0; ModelID < BodyPart.numModels; ModelID++) { StudioModel StudioModel = StudioBodyPart.Models[ModelID]; if (StudioModel.isBlank) { Debug.Log(String.Format("Model ID - {0} in bodypart \"{1}\" is blank, skip", ModelID, StudioBodyPart.Name)); continue; } ModelHeader_t Model = new ModelHeader_t(); Int64 ModelOffset = BodyPartOffset + (8 * ModelID) + BodyPart.modelOffset; FileStream.ReadTypeFixed(ref Model, 8, ModelOffset); StudioBodyPart.Models[ModelID].NumLODs = Model.numLODs; StudioBodyPart.Models[ModelID].LODData = new ModelLODHeader_t[Model.numLODs]; #region LOD's //TODO: Strip unused vertexes on lower lod's ("first" lod is fine) for (Int32 LODID = 0; LODID < Model.numLODs; LODID++) { ModelLODHeader_t LOD = new ModelLODHeader_t(); Int64 LODOffset = ModelOffset + (12 * LODID) + Model.lodOffset; FileStream.ReadTypeFixed(ref LOD, 12, LODOffset); StudioBodyPart.Models[ModelID].LODData[LODID] = LOD; #region Mesh LOD //Temp remember verts count per lod model Int32 VertexOffset = 0; //List<mstudiovertex_t> VertexesPerLod = new List<mstudiovertex_t>(); for (Int32 MeshID = 0; MeshID < StudioModel.Model.nummeshes; MeshID++) { mstudiomesh_t StudioMesh = StudioBodyPart.Models[ModelID].Meshes[MeshID]; //TODO: StudioModel.Meshes[MeshID].VertexData.numlodvertices[LODID]; - we no longer need this?? VertexOffset += StudioMesh.numvertices; List <Int32> IndicesPerMesh = new List <Int32>(); MeshHeader_t Mesh = new MeshHeader_t(); Int64 MeshOffset = LODOffset + (9 * MeshID) + LOD.meshOffset; FileStream.ReadTypeFixed(ref Mesh, 9, MeshOffset); #region StripGroups for (Int32 StripGroupID = 0; StripGroupID < Mesh.numStripGroups; StripGroupID++) { StripGroupHeader_t StripGroup = new StripGroupHeader_t(); Int64 StripGroupOffset = MeshOffset + (25 * StripGroupID) + Mesh.stripGroupHeaderOffset; FileStream.ReadTypeFixed(ref StripGroup, 25, StripGroupOffset); Vertex_t[] Vertexes = new Vertex_t[StripGroup.numVerts]; FileStream.BaseStream.Position = StripGroupOffset + StripGroup.vertOffset; FileStream.ReadArrayFixed(ref Vertexes, 9); FileStream.BaseStream.Position = StripGroupOffset + StripGroup.indexOffset; Int16[] Indices = FileStream.ReadShortArray(StripGroup.numIndices); #region Strips for (Int32 StripID = 0; StripID < StripGroup.numStrips; StripID++) { StripHeader_t VTXStrip = new StripHeader_t(); Int64 VTXStripOffset = StripGroupOffset + (27 * StripID) + StripGroup.stripOffset; FileStream.ReadTypeFixed(ref VTXStrip, 27, VTXStripOffset); //TODO: //Strip / "Split" vertexes //Pseudo code: /*for (Int32 VertID = 0; VertID < maxVertsPerLod; VertID++) * { * Int32 Index = MeshID * VTXStrip.numVerts + VertID; * * if (Index < numStripVerts) * { * splitVerts.Add(verts[Index]); * splitIndices.Add(j); * } * }*/ //Hmmmmm... Well, it's looks what we want.... but still doesn't perfect (for lod's mesh) /*Int32 NumVerts = VTXStrip.indexOffset + VTXStrip.numVerts; * for (Int32 VertID = VTXStrip.indexOffset; VertID < NumVerts; VertID++) * { * Int32 Index0 = VertID + StudioMesh.vertexoffset + VertexLODOffsets[LODID]; * VertexesPerLod.Add(StudioVVD.tempVerts[Index0]); * }*/ if ((VTXStrip.flags & VTXStripGroupTriStripFlag) > 0) { for (Int32 TempIdx = VTXStrip.indexOffset; TempIdx < VTXStrip.indexOffset + VTXStrip.numIndices - 2; TempIdx++) { Int32[] add = TempIdx % 2 == 1 ? new[] { TempIdx + 1, TempIdx, TempIdx + 2 } : new[] { TempIdx, TempIdx + 1, TempIdx + 2 }; foreach (Int32 Index in add) { IndicesPerMesh.Add(Vertexes[Indices[Index]].origMeshVertId + StudioMesh.vertexoffset); } } } else { for (Int32 Index = VTXStrip.indexOffset; Index < VTXStrip.indexOffset + VTXStrip.numIndices; Index++) { IndicesPerMesh.Add(Vertexes[Indices[Index]].origMeshVertId + StudioMesh.vertexoffset); } } } #endregion } #endregion StudioMDL.SetIndices(BodypartID, ModelID, LODID, MeshID, IndicesPerMesh); } #endregion //StudioMDL.MDL_Bodyparts[BodypartID].Models[ModelID].VerticesPerLod[LODID] = VertexesPerLod.ToArray(); ///TODO: Strip unused vertexes in <seealso cref="VVDFile.VVD_Vertexes"/> per lod StudioMDL.SetVertices(BodypartID, ModelID, LODID, VertexOffset, VertexLODOffsets[LODID], StudioVVD.VVD_Vertexes[0]); VertexLODOffsets[LODID] += VertexOffset; } #endregion } #endregion } #endregion } }