예제 #1
0
        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
        }
예제 #2
0
        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]);
                }
            }
        }
예제 #3
0
        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]);
                }
            }
        }
예제 #4
0
        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);
        }
예제 #5
0
        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);
        }
예제 #6
0
        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));
                }
            }
        }
예제 #7
0
        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);
        }
예제 #8
0
        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");
            }
        }
예제 #9
0
        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);
        }
예제 #10
0
        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);
        }
예제 #11
0
        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]);
                    //}
                }
            }
        }
예제 #12
0
        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 = "";
                    }
                }
            }
        }
예제 #13
0
        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);
        }
예제 #14
0
        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);
        }