private void ParseHeader(Stream stream) { header = new vertexFileHeader_t(); stream.Position = fileOffsetPosition; header.id = DataParser.ReadInt(stream); header.version = DataParser.ReadInt(stream); // MODEL_VERTEX_FILE_VERSION header.checksum = DataParser.ReadLong(stream); // same as studiohdr_t, ensures sync header.numLODs = DataParser.ReadInt(stream); // num of valid lods header.numLODVertices = new int[MAX_NUM_LODS]; // num verts for desired root lod (size is MAX_NUM_LODS = 8) for (int i = 0; i < header.numLODVertices.Length; i++) { header.numLODVertices[i] = DataParser.ReadInt(stream); } header.numFixups = DataParser.ReadInt(stream); // num of vertexFileFixup_t header.fixupTableStart = DataParser.ReadInt(stream); // offset from base to fixup table header.vertexDataStart = DataParser.ReadInt(stream); // offset from base to vertex block header.tangentDataStart = DataParser.ReadInt(stream); // offset from base to tangent block }
private void ReadSourceVtxBodyParts(Stream stream) { if (header.numBodyParts > 0 && header.version <= 7) { long[] bodyPartOffsets = new long[header.numBodyParts]; stream.Position = fileOffsetPosition + header.bodyPartOffset; bodyParts = new SourceVtxBodyPart[header.numBodyParts]; for (int i = 0; i < bodyParts.Length; i++) { bodyPartOffsets[i] = stream.Position; bodyParts[i] = new SourceVtxBodyPart(); bodyParts[i].modelCount = DataParser.ReadInt(stream); bodyParts[i].modelOffset = DataParser.ReadInt(stream); } for (int i = 0; i < bodyParts.Length; i++) { ReadSourceVtxModels(stream, bodyPartOffsets[i], bodyParts[i]); } } }
private void ReadSourceVtxModelLods(Stream stream, long modelOffset, SourceVtxModel model) { if (model.lodCount > 0 && model.lodOffset != 0) { long[] modelLodOffsets = new long[model.lodCount]; stream.Position = modelOffset + model.lodOffset; model.theVtxModelLods = new SourceVtxModelLod[model.lodCount]; for (int i = 0; i < model.theVtxModelLods.Length; i++) { modelLodOffsets[i] = stream.Position; model.theVtxModelLods[i] = new SourceVtxModelLod(); model.theVtxModelLods[i].meshCount = DataParser.ReadInt(stream); model.theVtxModelLods[i].meshOffset = DataParser.ReadInt(stream); model.theVtxModelLods[i].switchPoint = DataParser.ReadFloat(stream); } for (int i = 0; i < model.theVtxModelLods.Length; i++) { ReadSourceVtxMeshes(stream, modelLodOffsets[i], model.theVtxModelLods[i]); } } }
private studiohdr2_t ParseHeader2(Stream stream) { header2 = new studiohdr2_t(); header2.srcbonetransform_count = DataParser.ReadInt(stream); header2.srcbonetransform_index = DataParser.ReadInt(stream); header2.illumpositionattachmentindex = DataParser.ReadInt(stream); header2.flMaxEyeDeflection = DataParser.ReadFloat(stream); header2.linearbone_index = DataParser.ReadInt(stream); header2.sznameindex = DataParser.ReadInt(stream); header2.m_nBoneFlexDriverCount = DataParser.ReadInt(stream); header2.m_nBoneFlexDriverIndex = DataParser.ReadInt(stream); int[] reserved = new int[56]; for (int i = 0; i < reserved.Length; i++) { reserved[i] = DataParser.ReadInt(stream); } header2.reserved = reserved; return(header2); }
private mstudiobodyparts_t[] ParseBodyParts(Stream stream) { if (header1.bodypart_count >= 0) { long nextBodyPartPosition = fileBeginOffset + header1.bodypart_offset; bodyParts = new mstudiobodyparts_t[header1.bodypart_count]; for (int i = 0; i < bodyParts.Length; i++) { stream.Position = nextBodyPartPosition; long bodyPartPosition = nextBodyPartPosition; bodyParts[i] = new mstudiobodyparts_t(); bodyParts[i].nameOffset = DataParser.ReadInt(stream); bodyParts[i].modelCount = DataParser.ReadInt(stream); bodyParts[i].theBase = DataParser.ReadInt(stream); bodyParts[i].modelOffset = DataParser.ReadInt(stream); nextBodyPartPosition = stream.Position; if (bodyParts[i].nameOffset != 0) { stream.Position = bodyPartPosition + bodyParts[i].nameOffset; bodyParts[i].name = DataParser.ReadNullTerminatedString(stream); } else { bodyParts[i].name = ""; } ParseModels(stream, bodyPartPosition, bodyParts[i]); } } return(bodyParts); }
private void ParseTree(Stream currentStream) { while (currentStream.Position < header.TreeSize) { string extension = DataParser.ReadNullTerminatedString(currentStream).ToLower(); if (extension.Length <= 0) { extension = tree.Keys.ElementAt(tree.Count - 1); } else { if (!tree.ContainsKey(extension)) { tree.Add(extension, new Dictionary <string, Dictionary <string, VPKDirectoryEntry> >()); } } while (true) { string directory = DataParser.ReadNullTerminatedString(currentStream).ToLower(); if (directory.Length <= 0) { break; } if (!tree[extension].ContainsKey(directory)) { tree[extension].Add(directory, new Dictionary <string, VPKDirectoryEntry>()); } string fileName; do { fileName = DataParser.ReadNullTerminatedString(currentStream).ToLower(); if (!string.IsNullOrEmpty(fileName)) { VPKDirectoryEntry dirEntry = new VPKDirectoryEntry(); dirEntry.CRC = DataParser.ReadUInt(currentStream); dirEntry.PreloadBytes = DataParser.ReadUShort(currentStream); dirEntry.ArchiveIndex = DataParser.ReadUShort(currentStream); dirEntry.EntryOffset = DataParser.ReadUInt(currentStream); dirEntry.EntryLength = DataParser.ReadUInt(currentStream); ushort terminator = DataParser.ReadUShort(currentStream); if (dirEntry.EntryOffset == 0 && dirEntry.ArchiveIndex == DIR_PAK) { dirEntry.EntryOffset = Convert.ToUInt32(currentStream.Position); } if (dirEntry.EntryLength == 0) { dirEntry.EntryLength = dirEntry.PreloadBytes; } currentStream.Position += dirEntry.PreloadBytes; if (!tree[extension][directory].ContainsKey(fileName)) { tree[extension][directory].Add(fileName, dirEntry); } } }while (!string.IsNullOrEmpty(fileName)); } } }
public static Color[] LoadVTFFile(Stream stream, long vtfBytePosition, out int width, out int height) { //Texture2D extracted = null; Color[] extracted = null; width = 0; height = 0; if (stream != null) { stream.Position = vtfBytePosition; int signature = DataParser.ReadInt(stream); if (signature == VTFHeader.signature) { #region Read Header VTFHeader vtfHeader; uint[] version = new uint[] { DataParser.ReadUInt(stream), DataParser.ReadUInt(stream) }; vtfHeader.version = (version[0]) + (version[1] / 10f); vtfHeader.headerSize = DataParser.ReadUInt(stream); vtfHeader.width = DataParser.ReadUShort(stream); vtfHeader.height = DataParser.ReadUShort(stream); vtfHeader.flags = DataParser.ReadUInt(stream); vtfHeader.frames = DataParser.ReadUShort(stream); vtfHeader.firstFrame = DataParser.ReadUShort(stream); vtfHeader.padding0 = new byte[4]; stream.Read(vtfHeader.padding0, 0, 4); vtfHeader.reflectivity = new float[] { DataParser.ReadFloat(stream), DataParser.ReadFloat(stream), DataParser.ReadFloat(stream) }; vtfHeader.padding1 = new byte[4]; stream.Read(vtfHeader.padding1, 0, 4); vtfHeader.bumpmapScale = DataParser.ReadFloat(stream); vtfHeader.highResImageFormat = (VTFImageFormat)DataParser.ReadUInt(stream); vtfHeader.mipmapCount = DataParser.ReadByte(stream); vtfHeader.lowResImageFormat = (VTFImageFormat)DataParser.ReadUInt(stream); vtfHeader.lowResImageWidth = DataParser.ReadByte(stream); vtfHeader.lowResImageHeight = DataParser.ReadByte(stream); vtfHeader.depth = 1; vtfHeader.resourceCount = 0; vtfHeader.resources = new VTFResource[0]; if (vtfHeader.version >= 7.2f) { vtfHeader.depth = DataParser.ReadUShort(stream); if (vtfHeader.version >= 7.3) { vtfHeader.padding2 = new byte[3]; stream.Read(vtfHeader.padding2, 0, 3); vtfHeader.resourceCount = DataParser.ReadUInt(stream); if (vtfHeader.version >= 7.4) { vtfHeader.padding3 = new byte[8]; stream.Read(vtfHeader.padding3, 0, 8); vtfHeader.resources = new VTFResource[vtfHeader.resourceCount]; for (int i = 0; i < vtfHeader.resources.Length; i++) { vtfHeader.resources[i].type = DataParser.ReadUInt(stream); vtfHeader.resources[i].data = DataParser.ReadUInt(stream); } } } } #endregion int thumbnailBufferSize = 0; int imageBufferSize = (int)ComputeImageBufferSize(vtfHeader.width, vtfHeader.height, vtfHeader.depth, vtfHeader.mipmapCount, vtfHeader.highResImageFormat) * vtfHeader.frames; if (vtfHeader.lowResImageFormat != VTFImageFormat.IMAGE_FORMAT_NONE) { thumbnailBufferSize = (int)ComputeImageBufferSize(vtfHeader.lowResImageWidth, vtfHeader.lowResImageHeight, 1, vtfHeader.lowResImageFormat); } int thumbnailBufferOffset = 0, imageBufferOffset = 0; #region Read Resource Directories if (vtfHeader.resources.Length > 0) { for (int i = 0; i < vtfHeader.resources.Length; i++) { if ((VTFResourceEntryType)vtfHeader.resources[i].type == VTFResourceEntryType.VTF_LEGACY_RSRC_LOW_RES_IMAGE) { thumbnailBufferOffset = (int)vtfHeader.resources[i].data; } if ((VTFResourceEntryType)vtfHeader.resources[i].type == VTFResourceEntryType.VTF_LEGACY_RSRC_IMAGE) { imageBufferOffset = (int)vtfHeader.resources[i].data; } } } else { thumbnailBufferOffset = (int)vtfHeader.headerSize; imageBufferOffset = thumbnailBufferOffset + thumbnailBufferSize; } #endregion if (vtfHeader.highResImageFormat != VTFImageFormat.IMAGE_FORMAT_NONE) { int mipmapBufferOffset = 0; for (uint i = 1; i <= vtfHeader.mipmapCount; i++) { mipmapBufferOffset += (int)ComputeMipmapSize(vtfHeader.width, vtfHeader.height, vtfHeader.depth, i, vtfHeader.highResImageFormat); } stream.Position = vtfBytePosition + imageBufferOffset + mipmapBufferOffset; extracted = DecompressImage(stream, vtfHeader.width, vtfHeader.height, vtfHeader.highResImageFormat); width = vtfHeader.width; height = vtfHeader.height; } else { Debug.LogError("SourceTexture: Image format given was none"); } } else { Debug.LogError("SourceTexture: Signature mismatch " + signature + " != " + VTFHeader.signature); } } else { Debug.LogError("SourceTexture: Missing VTF data"); } return(extracted); }
private void ParseVertices(Stream stream, int rootLod) { for (int i = 0; i < rootLod; i++) { header.numLODVertices[i] = header.numLODVertices[rootLod]; } //int lodIndex = 0; if (header.numLODs > 0) { Func <Stream, mstudiovertex_t> ReadVertexFromStream = (innerStream) => { mstudiovertex_t vertex = new mstudiovertex_t(); vertex.m_BoneWeights.weight = new float[MAX_NUM_BONES_PER_VERT]; //0 + 12 = 12 for (int k = 0; k < vertex.m_BoneWeights.weight.Length; k++) { vertex.m_BoneWeights.weight[k] = DataParser.ReadFloat(innerStream); } vertex.m_BoneWeights.bone = new char[MAX_NUM_BONES_PER_VERT]; //12 + 12 = 24 for (int k = 0; k < vertex.m_BoneWeights.bone.Length; k++) { vertex.m_BoneWeights.bone[k] = DataParser.ReadChar(innerStream); } vertex.m_BoneWeights.numbones = DataParser.ReadByte(innerStream); //24 + 1 = 25 float ex = DataParser.ReadFloat(innerStream); //25 + 4 = 29 float why = DataParser.ReadFloat(innerStream); //33 + 4 = 37 float zee = DataParser.ReadFloat(innerStream); //29 + 4 = 33 vertex.m_vecPosition = new Vector3(ex, why, zee); ex = DataParser.ReadFloat(innerStream); //37 + 4 = 41 why = DataParser.ReadFloat(innerStream); //45 + 4 = 49 zee = DataParser.ReadFloat(innerStream); //41 + 4 = 45 vertex.m_vecNormal = new Vector3(ex, why, zee); ex = DataParser.ReadFloat(innerStream); //49 + 4 = 53 why = DataParser.ReadFloat(innerStream); //53 + 4 = 57 vertex.m_vecTexCoord = new Vector2(ex, 1 - why); return(vertex); }; stream.Position = fileOffsetPosition + header.vertexDataStart; //int vertexCount = header.numLODVertices[0]; int vertexCount = 0; for (int i = 0; i < header.numLODVertices.Length; i++) { vertexCount += header.numLODVertices[i]; } vertices = new mstudiovertex_t[vertexCount]; for (int i = 0; i < vertices.Length; i++) { vertices[i] = ReadVertexFromStream(stream); } if (header.numFixups > 0) { vertexCount = 0; for (int fixupIndex = 0; fixupIndex < header.numFixups; fixupIndex++) { if (fileFixup[fixupIndex].lod < rootLod) { continue; } vertexCount += fileFixup[fixupIndex].numVertices; } mstudiovertex_t[] oldVertices = vertices; vertices = new mstudiovertex_t[vertexCount]; int currentIndex = 0; for (int fixupIndex = 0; fixupIndex < header.numFixups; fixupIndex++) { if (fileFixup[fixupIndex].lod < rootLod) { continue; } Array.Copy(oldVertices, fileFixup[fixupIndex].sourceVertexID, vertices, currentIndex, fileFixup[fixupIndex].numVertices); currentIndex += fileFixup[fixupIndex].numVertices; } } } else { Debug.LogError("VVDParser: Header's numLODs less than or equal to zero"); } }
private mstudioanimdesc_t[] ParseAnimationDescs(Stream stream) { if (header1.localanim_count >= 0) { long animDescFileByteSize = 0; long nextAnimDescPosition = fileBeginOffset + header1.localanim_offset; animDescs = new mstudioanimdesc_t[header1.localanim_count]; for (int i = 0; i < animDescs.Length; i++) { stream.Position = nextAnimDescPosition; long animDescPosition = nextAnimDescPosition; animDescs[i].baseHeaderOffset = DataParser.ReadInt(stream); animDescs[i].nameOffset = DataParser.ReadInt(stream); animDescs[i].fps = DataParser.ReadFloat(stream); animDescs[i].flags = DataParser.ReadInt(stream); animDescs[i].frameCount = DataParser.ReadInt(stream); animDescs[i].movementCount = DataParser.ReadInt(stream); animDescs[i].movementOffset = DataParser.ReadInt(stream); animDescs[i].ikRuleZeroFrameOffset = DataParser.ReadInt(stream); animDescs[i].unused1 = new int[5]; for (int j = 0; j < animDescs[i].unused1.Length; j++) { animDescs[i].unused1[j] = DataParser.ReadInt(stream); } animDescs[i].animBlock = DataParser.ReadInt(stream); animDescs[i].animOffset = DataParser.ReadInt(stream); animDescs[i].ikRuleCount = DataParser.ReadInt(stream); animDescs[i].ikRuleOffset = DataParser.ReadInt(stream); animDescs[i].animblockIkRuleOffset = DataParser.ReadInt(stream); animDescs[i].localHierarchyCount = DataParser.ReadInt(stream); animDescs[i].localHierarchyOffset = DataParser.ReadInt(stream); animDescs[i].sectionOffset = DataParser.ReadInt(stream); animDescs[i].sectionFrameCount = DataParser.ReadInt(stream); animDescs[i].spanFrameCount = DataParser.ReadShort(stream); animDescs[i].spanCount = DataParser.ReadShort(stream); animDescs[i].spanOffset = DataParser.ReadInt(stream); animDescs[i].spanStallTime = DataParser.ReadFloat(stream); nextAnimDescPosition = stream.Position; if (i == 0) { animDescFileByteSize = nextAnimDescPosition - animDescPosition; } if (animDescs[i].nameOffset != 0) { stream.Position = animDescPosition + animDescs[i].nameOffset; animDescs[i].name = DataParser.ReadNullTerminatedString(stream); } else { animDescs[i].name = ""; } } for (int i = 0; i < animDescs.Length; i++) { long animDescPosition = fileBeginOffset + header1.localanim_offset + (i * animDescFileByteSize); stream.Position = animDescPosition; if ((((animdesc_flags)animDescs[i].flags) & animdesc_flags.STUDIO_ALLZEROS) == 0) { animDescs[i].sectionsOfAnimations = new List <List <mstudioanim_t> >(); //List<mstudioanim_t> animationSection = new List<mstudioanim_t>(); //animDescs[i].sectionsOfAnimations.Add(animationSection); animDescs[i].sectionsOfAnimations.Add(new List <mstudioanim_t>()); if ((((animdesc_flags)animDescs[i].flags) & animdesc_flags.STUDIO_FRAMEANIM) != 0) { //if (animDescs[i].sectionOffset != 0 && animDescs[i].sectionFrameCount > 0) ; //else if (animDescs[i].animBlock == 0) ; } else { if (animDescs[i].sectionOffset != 0 && animDescs[i].sectionFrameCount > 0) { int sectionCount = (animDescs[i].frameCount / animDescs[i].sectionFrameCount) + 2; for (int j = 1; j < sectionCount; j++) { animDescs[i].sectionsOfAnimations.Add(new List <mstudioanim_t>()); } animDescs[i].sections = new List <mstudioanimsections_t>(); for (int j = 0; j < sectionCount; j++) { ParseMdlAnimationSection(stream, animDescPosition + animDescs[i].sectionOffset, animDescs[i]); } if (animDescs[i].animBlock == 0) { for (int j = 0; j < sectionCount; j++) { int sectionFrameCount = 0; if (j < sectionCount - 2) { sectionFrameCount = animDescs[i].sectionFrameCount; } else { sectionFrameCount = animDescs[i].frameCount - ((sectionCount - 2) * animDescs[i].sectionFrameCount); } ParseMdlAnimation(animDescPosition + animDescs[i].sections[j].animOffset, animDescs[i], sectionFrameCount, animDescs[i].sectionsOfAnimations[j]); } } } } } } } return(animDescs); }
private mstudioattachment_t[] ParseAttachments(Stream stream) { if (header1.attachment_count >= 0) { long nextAttachmentPosition = fileBeginOffset + header1.attachment_offset; attachments = new mstudioattachment_t[header1.attachment_count]; for (int i = 0; i < attachments.Length; i++) { stream.Position = nextAttachmentPosition; long attachmentPosition = nextAttachmentPosition; if (header1.version == 10) { attachments[i].builtName = new char[32]; for (int j = 0; j < attachments[i].builtName.Length; j++) { attachments[i].builtName[j] = DataParser.ReadChar(stream); } attachments[i].type = DataParser.ReadInt(stream); attachments[i].bone = DataParser.ReadInt(stream); attachments[i].attachmentPoint = new Vector3(DataParser.ReadFloat(stream), DataParser.ReadFloat(stream), DataParser.ReadFloat(stream)); attachments[i].vectors = new Vector3[3]; for (int j = 0; j < attachments[i].vectors.Length; j++) { attachments[i].vectors[j] = new Vector3(DataParser.ReadFloat(stream), DataParser.ReadFloat(stream), DataParser.ReadFloat(stream)); } } else { attachments[i].nameOffset = DataParser.ReadInt(stream); attachments[i].flags = DataParser.ReadInt(stream); attachments[i].localBoneIndex = DataParser.ReadInt(stream); attachments[i].localM11 = DataParser.ReadFloat(stream); attachments[i].localM12 = DataParser.ReadFloat(stream); attachments[i].localM13 = DataParser.ReadFloat(stream); attachments[i].localM14 = DataParser.ReadFloat(stream); attachments[i].localM21 = DataParser.ReadFloat(stream); attachments[i].localM22 = DataParser.ReadFloat(stream); attachments[i].localM23 = DataParser.ReadFloat(stream); attachments[i].localM24 = DataParser.ReadFloat(stream); attachments[i].localM31 = DataParser.ReadFloat(stream); attachments[i].localM32 = DataParser.ReadFloat(stream); attachments[i].localM33 = DataParser.ReadFloat(stream); attachments[i].localM34 = DataParser.ReadFloat(stream); attachments[i].unused = new int[8]; for (int j = 0; j < attachments[i].unused.Length; j++) { attachments[i].unused[j] = DataParser.ReadInt(stream); } } nextAttachmentPosition = stream.Position; if (attachments[i].nameOffset != 0) { stream.Position = attachmentPosition + attachments[i].nameOffset; attachments[i].name = DataParser.ReadNullTerminatedString(stream); } } } return(attachments); }
private void ParseMeshes(Stream stream, long modelPosition, mstudiomodel_t model) { if (model.meshCount >= 0) { long nextMeshPosition = modelPosition + model.meshOffset; model.theMeshes = new mstudiomesh_t[model.meshCount]; for (int i = 0; i < model.theMeshes.Length; i++) { stream.Position = nextMeshPosition; long meshPosition = nextMeshPosition; model.theMeshes[i] = new mstudiomesh_t(); model.theMeshes[i].materialIndex = DataParser.ReadInt(stream); model.theMeshes[i].modelOffset = DataParser.ReadInt(stream); model.theMeshes[i].vertexCount = DataParser.ReadInt(stream); model.theMeshes[i].vertexIndexStart = DataParser.ReadInt(stream); model.theMeshes[i].flexCount = DataParser.ReadInt(stream); model.theMeshes[i].flexOffset = DataParser.ReadInt(stream); model.theMeshes[i].materialType = DataParser.ReadInt(stream); model.theMeshes[i].materialParam = DataParser.ReadInt(stream); model.theMeshes[i].id = DataParser.ReadInt(stream); model.theMeshes[i].center = new Vector3(DataParser.ReadFloat(stream), DataParser.ReadFloat(stream), DataParser.ReadFloat(stream)); model.theMeshes[i].vertexData = new mstudio_meshvertexdata_t(); model.theMeshes[i].vertexData.modelVertexDataP = DataParser.ReadInt(stream); model.theMeshes[i].vertexData.lodVertexCount = new int[8]; for (int j = 0; j < model.theMeshes[i].vertexData.lodVertexCount.Length; j++) { model.theMeshes[i].vertexData.lodVertexCount[j] = DataParser.ReadInt(stream); } model.theMeshes[i].unused = new int[8]; for (int j = 0; j < model.theMeshes[i].unused.Length; j++) { model.theMeshes[i].unused[j] = DataParser.ReadInt(stream); } if (model.theMeshes[i].materialType == 1) { model.theEyeballs[model.theMeshes[i].materialParam].theTextureIndex = model.theMeshes[i].materialIndex; } nextMeshPosition = stream.Position; if (model.theMeshes[i].flexCount > 0 && model.theMeshes[i].flexOffset != 0) { ParseFlexes(meshPosition, model.theMeshes[i]); } //stream.Position = model.theMeshes[i].vertexData.modelVertexDataP + model.theMeshes[i].vertexIndexStart; //model.theMeshes[i].vertices = new Vector3[model.theMeshes[i].vertexCount]; //for (int j = 0; j < model.theMeshes[i].vertices.Length; j++) //{ // model.theMeshes[i].vertices[j] = new Vector3(FileReader.readFloat(stream), FileReader.readFloat(stream), FileReader.readFloat(stream)); // if (j >= 0 && j < 100) Debug.Log("Mesh " + i + ": V" + j + " " + model.theMeshes[i].vertices[j]); //} } } }
private void ParseEyeballs(Stream stream, long modelPosition, mstudiomodel_t model) { if (model.eyeballCount >= 0 && model.eyeballOffset != 0) { model.theEyeballs = new mstudioeyeball_t[model.eyeballCount]; long nextEyeballPosition = modelPosition + model.eyeballOffset; for (int i = 0; i < model.theEyeballs.Length; i++) { stream.Position = nextEyeballPosition; long eyeballPosition = nextEyeballPosition; model.theEyeballs[i] = new mstudioeyeball_t(); model.theEyeballs[i].nameOffset = DataParser.ReadInt(stream); model.theEyeballs[i].boneIndex = DataParser.ReadInt(stream); model.theEyeballs[i].org = new Vector3(DataParser.ReadFloat(stream), DataParser.ReadFloat(stream), DataParser.ReadFloat(stream)); model.theEyeballs[i].zOffset = DataParser.ReadFloat(stream); model.theEyeballs[i].radius = DataParser.ReadFloat(stream); model.theEyeballs[i].up = new Vector3(DataParser.ReadFloat(stream), DataParser.ReadFloat(stream), DataParser.ReadFloat(stream)); model.theEyeballs[i].forward = new Vector3(DataParser.ReadFloat(stream), DataParser.ReadFloat(stream), DataParser.ReadFloat(stream)); model.theEyeballs[i].texture = DataParser.ReadInt(stream); model.theEyeballs[i].unused1 = DataParser.ReadInt(stream); model.theEyeballs[i].irisScale = DataParser.ReadFloat(stream); model.theEyeballs[i].unused2 = DataParser.ReadInt(stream); model.theEyeballs[i].upperFlexDesc = new int[3]; model.theEyeballs[i].lowerFlexDesc = new int[3]; model.theEyeballs[i].upperTarget = new double[3]; model.theEyeballs[i].lowerTarget = new double[3]; model.theEyeballs[i].upperFlexDesc[0] = DataParser.ReadInt(stream); model.theEyeballs[i].upperFlexDesc[1] = DataParser.ReadInt(stream); model.theEyeballs[i].upperFlexDesc[2] = DataParser.ReadInt(stream); model.theEyeballs[i].lowerFlexDesc[0] = DataParser.ReadInt(stream); model.theEyeballs[i].lowerFlexDesc[1] = DataParser.ReadInt(stream); model.theEyeballs[i].lowerFlexDesc[2] = DataParser.ReadInt(stream); model.theEyeballs[i].upperTarget[0] = DataParser.ReadFloat(stream); model.theEyeballs[i].upperTarget[1] = DataParser.ReadFloat(stream); model.theEyeballs[i].upperTarget[2] = DataParser.ReadFloat(stream); model.theEyeballs[i].lowerTarget[0] = DataParser.ReadFloat(stream); model.theEyeballs[i].lowerTarget[1] = DataParser.ReadFloat(stream); model.theEyeballs[i].lowerTarget[2] = DataParser.ReadFloat(stream); model.theEyeballs[i].upperLidFlexDesc = DataParser.ReadInt(stream); model.theEyeballs[i].lowerLidFlexDesc = DataParser.ReadInt(stream); model.theEyeballs[i].unused = new int[4]; for (int j = 0; j < model.theEyeballs[i].unused.Length; j++) { model.theEyeballs[i].unused[j] = DataParser.ReadInt(stream); } model.theEyeballs[i].eyeballIsNonFacs = DataParser.ReadByte(stream); model.theEyeballs[i].unused3 = new char[3]; for (int j = 0; j < model.theEyeballs[i].unused3.Length; j++) { model.theEyeballs[i].unused3[j] = DataParser.ReadChar(stream); } model.theEyeballs[i].unused4 = new int[7]; for (int j = 0; j < model.theEyeballs[i].unused4.Length; j++) { model.theEyeballs[i].unused4[j] = DataParser.ReadInt(stream); } //Set the default value to -1 to distinguish it from value assigned to it by ReadMeshes() model.theEyeballs[i].theTextureIndex = -1; nextEyeballPosition = stream.Position; if (model.theEyeballs[i].nameOffset != 0) { stream.Position = eyeballPosition + model.theEyeballs[i].nameOffset; model.theEyeballs[i].name = DataParser.ReadNullTerminatedString(stream); } else { model.theEyeballs[i].name = ""; } } } }
private mstudiobone_t[] ParseBones(Stream stream) { if (header1.bone_count >= 0) { long savePosition = fileBeginOffset + header1.bone_offset; bones = new mstudiobone_t[header1.bone_count]; for (int i = 0; i < bones.Length; i++) { stream.Position = savePosition; long bonePosition = savePosition; bones[i] = new mstudiobone_t(); bones[i].nameOffset = DataParser.ReadInt(stream); bones[i].parentBoneIndex = DataParser.ReadInt(stream); //stream.Position += 150; bones[i].boneControllerIndex = new int[6]; for (int j = 0; j < bones[i].boneControllerIndex.Length; j++) { bones[i].boneControllerIndex[j] = DataParser.ReadInt(stream); } //FileReader.readInt(stream); bones[i].position = new Vector3(DataParser.ReadFloat(stream), DataParser.ReadFloat(stream), DataParser.ReadFloat(stream)); bones[i].quat = new Quaternion(DataParser.ReadFloat(stream), DataParser.ReadFloat(stream), DataParser.ReadFloat(stream), DataParser.ReadFloat(stream)); if (header1.version != 2531) { bones[i].rotation = new Vector3(DataParser.ReadFloat(stream), DataParser.ReadFloat(stream), DataParser.ReadFloat(stream)); bones[i].positionScale = new Vector3(DataParser.ReadFloat(stream), DataParser.ReadFloat(stream), DataParser.ReadFloat(stream)); bones[i].rotationScale = new Vector3(DataParser.ReadFloat(stream), DataParser.ReadFloat(stream), DataParser.ReadFloat(stream)); } //FileReader.readInt(stream); float[] columnExes = new float[4] { DataParser.ReadFloat(stream), DataParser.ReadFloat(stream), DataParser.ReadFloat(stream), DataParser.ReadFloat(stream) }; float[] columnWise = new float[4] { DataParser.ReadFloat(stream), DataParser.ReadFloat(stream), DataParser.ReadFloat(stream), DataParser.ReadFloat(stream) }; float[] columnZees = new float[4] { DataParser.ReadFloat(stream), DataParser.ReadFloat(stream), DataParser.ReadFloat(stream), DataParser.ReadFloat(stream) }; bones[i].poseToBoneColumn0 = new Vector3(columnExes[0], columnWise[0], columnZees[0]); bones[i].poseToBoneColumn1 = new Vector3(columnExes[1], columnWise[1], columnZees[1]); bones[i].poseToBoneColumn2 = new Vector3(columnExes[2], columnWise[2], columnZees[2]); bones[i].poseToBoneColumn3 = new Vector3(columnExes[3], columnWise[3], columnZees[3]); if (header1.version != 2531) { bones[i].qAlignment = new Quaternion(DataParser.ReadFloat(stream), DataParser.ReadFloat(stream), DataParser.ReadFloat(stream), DataParser.ReadFloat(stream)); } bones[i].flags = DataParser.ReadInt(stream); bones[i].proceduralRuleType = DataParser.ReadInt(stream); bones[i].proceduralRuleOffset = DataParser.ReadInt(stream); bones[i].physicsBoneIndex = DataParser.ReadInt(stream); bones[i].surfacePropNameOffset = DataParser.ReadInt(stream); bones[i].contents = DataParser.ReadInt(stream); if (header1.version != 2531) { for (int j = 0; j < 8; j++) { DataParser.ReadInt(stream); } } savePosition = stream.Position; if (bones[i].nameOffset != 0) { stream.Position = bonePosition + bones[i].nameOffset; bones[i].name = DataParser.ReadNullTerminatedString(stream); } else { bones[i].name = ""; } if (bones[i].surfacePropNameOffset != 0) { stream.Position = bonePosition + bones[i].surfacePropNameOffset; bones[i].theSurfacePropName = DataParser.ReadNullTerminatedString(stream); } else { bones[i].theSurfacePropName = ""; } } } return(bones); }
private studiohdr_t ParseHeader1(Stream stream) { header1 = new studiohdr_t(); stream.Position = fileBeginOffset; header1.id = DataParser.ReadInt(stream); // Model format ID, such as "IDST" (0x49 0x44 0x53 0x54) header1.version = DataParser.ReadInt(stream); // Format version number, such as 48 (0x30,0x00,0x00,0x00) header1.checkSum = DataParser.ReadInt(stream); // this has to be the same in the phy and vtx files to load! char[] name = new char[64]; for (int i = 0; i < name.Length; i++) { name[i] = DataParser.ReadChar(stream); } header1.name = name; // The internal name of the model, padding with null bytes. // Typically "my_model.mdl" will have an internal name of "my_model" this.name = new string(name).Replace("\0", ""); header1.dataLength = DataParser.ReadInt(stream); // Data size of MDL file in bytes. // A vector is 12 bytes, three 4-byte float-values in a row. header1.eyeposition = new Vector3(DataParser.ReadFloat(stream), DataParser.ReadFloat(stream), DataParser.ReadFloat(stream)); // Position of player viewpoint relative to model origin header1.illumposition = new Vector3(DataParser.ReadFloat(stream), DataParser.ReadFloat(stream), DataParser.ReadFloat(stream)); // ?? Presumably the point used for lighting when per-vertex lighting is not enabled. header1.hull_min = new Vector3(DataParser.ReadFloat(stream), DataParser.ReadFloat(stream), DataParser.ReadFloat(stream)); // Corner of model hull box with the least X/Y/Z values header1.hull_max = new Vector3(DataParser.ReadFloat(stream), DataParser.ReadFloat(stream), DataParser.ReadFloat(stream)); // Opposite corner of model hull box header1.view_bbmin = new Vector3(DataParser.ReadFloat(stream), DataParser.ReadFloat(stream), DataParser.ReadFloat(stream)); // View Bounding Box Minimum Position header1.view_bbmax = new Vector3(DataParser.ReadFloat(stream), DataParser.ReadFloat(stream), DataParser.ReadFloat(stream)); // View Bounding Box Maximum Position header1.flags = DataParser.ReadInt(stream); // Binary flags in little-endian order. // ex (00000001,00000000,00000000,11000000) means flags for position 0, 30, and 31 are set. // Set model flags section for more information //Debug.Log("ID: " + header1.id + ", \nVersion: " + header1.version + ", \nCheckSum: " + header1.checkSum + ", \nName: " + this.name + ", \nLength: " + header1.dataLength); //Debug.Log("EyePos: " + header1.eyeposition + ", \nIllumPos: " + header1.illumposition + ", \nHullMin: " + header1.hull_min + ", \nHullMax: " + header1.hull_max + ", \nViewBBMin: " + header1.view_bbmin + ", \nViewBBMax: " + header1.view_bbmax); /* * After this point, the header contains many references to offsets * within the MDL file and the number of items at those offsets. * * Offsets are from the very beginning of the file. * * Note that indexes/counts are not always paired and ordered consistently. */ // mstudiobone_t header1.bone_count = DataParser.ReadInt(stream); // Number of data sections (of type mstudiobone_t) header1.bone_offset = DataParser.ReadInt(stream); // Offset of first data section // mstudiobonecontroller_t header1.bonecontroller_count = DataParser.ReadInt(stream); header1.bonecontroller_offset = DataParser.ReadInt(stream); // mstudiohitboxset_t header1.hitbox_count = DataParser.ReadInt(stream); header1.hitbox_offset = DataParser.ReadInt(stream); // mstudioanimdesc_t header1.localanim_count = DataParser.ReadInt(stream); header1.localanim_offset = DataParser.ReadInt(stream); // mstudioseqdesc_t header1.localseq_count = DataParser.ReadInt(stream); header1.localseq_offset = DataParser.ReadInt(stream); header1.activitylistversion = DataParser.ReadInt(stream); // ?? header1.eventsindexed = DataParser.ReadInt(stream); // ?? // VMT texture filenames // mstudiotexture_t header1.texture_count = DataParser.ReadInt(stream); header1.texture_offset = DataParser.ReadInt(stream); // This offset points to a series of ints. // Each int value, in turn, is an offset relative to the start of this header/the-file, // At which there is a null-terminated string. header1.texturedir_count = DataParser.ReadInt(stream); header1.texturedir_offset = DataParser.ReadInt(stream); // Each skin-family assigns a texture-id to a skin location header1.skinreference_count = DataParser.ReadInt(stream); header1.skinrfamily_count = DataParser.ReadInt(stream); header1.skinreference_index = DataParser.ReadInt(stream); // mstudiobodyparts_t header1.bodypart_count = DataParser.ReadInt(stream); header1.bodypart_offset = DataParser.ReadInt(stream); // Local attachment points // mstudioattachment_t header1.attachment_count = DataParser.ReadInt(stream); header1.attachment_offset = DataParser.ReadInt(stream); // Node values appear to be single bytes, while their names are null-terminated strings. header1.localnode_count = DataParser.ReadInt(stream); header1.localnode_index = DataParser.ReadInt(stream); header1.localnode_name_index = DataParser.ReadInt(stream); // mstudioflexdesc_t header1.flexdesc_count = DataParser.ReadInt(stream); header1.flexdesc_index = DataParser.ReadInt(stream); // mstudioflexcontroller_t header1.flexcontroller_count = DataParser.ReadInt(stream); header1.flexcontroller_index = DataParser.ReadInt(stream); // mstudioflexrule_t header1.flexrules_count = DataParser.ReadInt(stream); header1.flexrules_index = DataParser.ReadInt(stream); // IK probably referse to inverse kinematics // mstudioikchain_t header1.ikchain_count = DataParser.ReadInt(stream); header1.ikchain_index = DataParser.ReadInt(stream); // Information about any "mouth" on the model for speech animation // More than one sounds pretty creepy. // mstudiomouth_t header1.mouths_count = DataParser.ReadInt(stream); header1.mouths_index = DataParser.ReadInt(stream); // mstudioposeparamdesc_t header1.localposeparam_count = DataParser.ReadInt(stream); header1.localposeparam_index = DataParser.ReadInt(stream); /* * For anyone trying to follow along, as of this writing, * the next "surfaceprop_index" value is at position 0x0134 (308) * from the start of the file. */ //stream.Position = 308; // Surface property value (single null-terminated string) header1.surfaceprop_index = DataParser.ReadInt(stream); // Unusual: In this one index comes first, then count. // Key-value data is a series of strings. If you can't find // what you're interested in, check the associated PHY file as well. header1.keyvalue_index = DataParser.ReadInt(stream); header1.keyvalue_count = DataParser.ReadInt(stream); // More inverse-kinematics // mstudioiklock_t header1.iklock_count = DataParser.ReadInt(stream); header1.iklock_index = DataParser.ReadInt(stream); header1.mass = DataParser.ReadFloat(stream); // Mass of object (4-bytes) header1.contents = DataParser.ReadInt(stream); // ?? // Other models can be referenced for re-used sequences and animations // (See also: The $includemodel QC option.) // mstudiomodelgroup_t header1.includemodel_count = DataParser.ReadInt(stream); header1.includemodel_index = DataParser.ReadInt(stream); header1.virtualModel = DataParser.ReadInt(stream); // Placeholder for mutable-void* // mstudioanimblock_t header1.animblocks_name_index = DataParser.ReadInt(stream); header1.animblocks_count = DataParser.ReadInt(stream); header1.animblocks_index = DataParser.ReadInt(stream); header1.animblockModel = DataParser.ReadInt(stream); // Placeholder for mutable-void* // Points to a series of bytes? header1.bonetablename_index = DataParser.ReadInt(stream); header1.vertex_base = DataParser.ReadInt(stream); // Placeholder for void* header1.offset_base = DataParser.ReadInt(stream); // Placeholder for void* // Used with $constantdirectionallight from the QC // Model should have flag #13 set if enabled header1.directionaldotproduct = DataParser.ReadByte(stream); header1.rootLod = DataParser.ReadByte(stream); // Preferred rather than clamped // 0 means any allowed, N means Lod 0 -> (N-1) header1.numAllowedRootLods = DataParser.ReadByte(stream); //header.unused; // ?? header1.unused1 = DataParser.ReadByte(stream); //header.unused; // ?? header1.unused2 = DataParser.ReadInt(stream); // mstudioflexcontrollerui_t header1.flexcontrollerui_count = DataParser.ReadInt(stream); header1.flexcontrollerui_index = DataParser.ReadInt(stream); header1.vertAnimFixedPointScale = DataParser.ReadFloat(stream); header1.surfacePropLookup = DataParser.ReadInt(stream); /** * Offset for additional header information. * May be zero if not present, or also 408 if it immediately * follows this studiohdr_t */ // studiohdr2_t header1.studiohdr2index = DataParser.ReadInt(stream); //header.unused; // ?? header1.unused3 = DataParser.ReadInt(stream); return(header1); }