Esempio n. 1
0
        // Token: 0x0600015D RID: 349 RVA: 0x00009E84 File Offset: 0x00008084
        private void UpdateSkeleton()
        {
            int num = 0;

            for (int i = 0; i < this.StudioHitBoxSet.numhitboxes; i++)
            {
                mstudiobbox_t mstudiobbox_t = this.StudioHitBoxes[i];
                mstudiobone_t mstudiobone_t = this.StudioBones[mstudiobbox_t.bone];
                if (mstudiobone_t.parent >= 0 && mstudiobone_t.parent < this.StudioHdr.numbones)
                {
                    this.Skeleton[num] = new ValueTuple <int, int>(mstudiobbox_t.bone, mstudiobone_t.parent);
                    num++;
                }
            }
            this.SkeletonCount = num;
        }
Esempio n. 2
0
        public MDLFile(Stream FileInput, Boolean parseAnims = false, Boolean parseHitboxes = false)
        {
            using (uReader FileStream = new uReader(FileInput))
            {
                FileStream.ReadTypeFixed(ref MDL_Header, 392);

                if (MDL_Header.id != 0x54534449)
                {
                    throw new FileLoadException("File signature does not match 'IDST'");
                }

                //Bones
                #region Bones
                //Bones
                MDL_StudioBones = new mstudiobone_t[MDL_Header.bone_count];
                MDL_BoneNames   = new String[MDL_Header.bone_count];
                for (Int32 BoneID = 0; BoneID < MDL_Header.bone_count; BoneID++)
                {
                    Int32 boneOffset = MDL_Header.bone_offset + (216 * BoneID);
                    FileStream.ReadTypeFixed(ref MDL_StudioBones[BoneID], 216, boneOffset);
                    MDL_BoneNames[BoneID] = FileStream.ReadNullTerminatedString(boneOffset + MDL_StudioBones[BoneID].sznameindex);
                }
                //Bones
                #endregion

                #region Hitboxes
                if (parseHitboxes)
                {
                    MDL_Hitboxsets = new mstudiohitboxset_t[MDL_Header.hitbox_count];
                    Hitboxes       = new Hitbox[MDL_Header.hitbox_count][];
                    for (Int32 HitboxsetID = 0; HitboxsetID < MDL_Header.hitbox_count; HitboxsetID++)
                    {
                        Int32 HitboxsetOffset = MDL_Header.hitbox_offset + (12 * HitboxsetID);
                        FileStream.ReadTypeFixed(ref MDL_Hitboxsets[HitboxsetID], 12, HitboxsetOffset);
                        Hitboxes[HitboxsetID] = new Hitbox[MDL_Hitboxsets[HitboxsetID].numhitboxes];

                        for (Int32 HitboxID = 0; HitboxID < MDL_Hitboxsets[HitboxsetID].numhitboxes; HitboxID++)
                        {
                            Int32 HitboxOffset = HitboxsetOffset + (68 * HitboxID) + MDL_Hitboxsets[HitboxsetID].hitboxindex;
                            Hitboxes[HitboxsetID][HitboxID].BBox = new mstudiobbox_t();

                            FileStream.ReadTypeFixed(ref Hitboxes[HitboxsetID][HitboxID].BBox, 68, HitboxOffset);
                        }
                    }
                }
                #endregion

                #region Animations
                if (parseAnims)
                {
                    try
                    {
                        //Animations
                        MDL_AniDescriptions = new mstudioanimdesc_t[MDL_Header.localanim_count];
                        Animations          = new AniInfo[MDL_Header.localanim_count];

                        for (Int32 AnimID = 0; AnimID < MDL_Header.localanim_count; AnimID++)
                        {
                            Int32 AnimOffset = MDL_Header.localanim_offset + (100 * AnimID);
                            FileStream.ReadTypeFixed(ref MDL_AniDescriptions[AnimID], 100, AnimOffset);
                            mstudioanimdesc_t StudioAnim = MDL_AniDescriptions[AnimID];

                            String StudioAnimName = FileStream.ReadNullTerminatedString(AnimOffset + StudioAnim.sznameindex);
                            Animations[AnimID] = new AniInfo {
                                name = StudioAnimName, studioAnim = StudioAnim
                            };
                            Animations[AnimID].AnimationBones = new List <AnimationBone>();

                            //mstudioanim_t
                            FileStream.BaseStream.Position = AnimOffset;

                            Int64 StartOffset = FileStream.BaseStream.Position;

                            Int32 CurrentOffset = MDL_AniDescriptions[AnimID].animindex;
                            Int16 NextOffset;
                            do
                            {
                                FileStream.BaseStream.Position = StartOffset + CurrentOffset;
                                Byte BoneIndex = FileStream.ReadByte();
                                Byte BoneFlag  = FileStream.ReadByte();
                                NextOffset     = FileStream.ReadInt16();
                                CurrentOffset += NextOffset;

                                AnimationBone AnimatedBone = new AnimationBone(BoneIndex, BoneFlag, MDL_AniDescriptions[AnimID].numframes);
                                AnimatedBone.ReadData(FileStream);
                                Animations[AnimID].AnimationBones.Add(AnimatedBone);
                            } while (NextOffset != 0);
                            //mstudioanim_t

                            List <AnimationBone> AnimationBones = Animations[AnimID].AnimationBones;
                            Int32 NumBones  = MDL_Header.bone_count;
                            Int32 NumFrames = StudioAnim.numframes;

                            //Used to avoid "Assertion failed" key count in Unity (if frames less than 2)
                            Boolean FramesLess = NumFrames < 2;
                            if (FramesLess)
                            {
                                NumFrames += 1;
                            }

                            Animations[AnimID].PosX = new Keyframe[NumFrames][];
                            Animations[AnimID].PosY = new Keyframe[NumFrames][];
                            Animations[AnimID].PosZ = new Keyframe[NumFrames][];

                            Animations[AnimID].RotX = new Keyframe[NumFrames][];
                            Animations[AnimID].RotY = new Keyframe[NumFrames][];
                            Animations[AnimID].RotZ = new Keyframe[NumFrames][];
                            Animations[AnimID].RotW = new Keyframe[NumFrames][];
                            for (Int32 FrameID = 0; FrameID < NumFrames; FrameID++)
                            {
                                Animations[AnimID].PosX[FrameID] = new Keyframe[NumBones];
                                Animations[AnimID].PosY[FrameID] = new Keyframe[NumBones];
                                Animations[AnimID].PosZ[FrameID] = new Keyframe[NumBones];

                                Animations[AnimID].RotX[FrameID] = new Keyframe[NumBones];
                                Animations[AnimID].RotY[FrameID] = new Keyframe[NumBones];
                                Animations[AnimID].RotZ[FrameID] = new Keyframe[NumBones];
                                Animations[AnimID].RotW[FrameID] = new Keyframe[NumBones];
                            }

                            for (Int32 boneID = 0; boneID < NumBones; boneID++)
                            {
                                AnimationBone AnimBone = AnimationBones.FirstOrDefault(x => x.Bone == boneID);

                                //frameIndex < 30 && studioAnimName == "@ak47_reload"
                                for (Int32 frameID = 0; frameID < NumFrames; frameID++)
                                {
                                    //get current animation time (length) by divide frame index on "fps"
                                    Single time = frameID / StudioAnim.fps;

                                    mstudiobone_t StudioBone = MDL_StudioBones[boneID];
                                    //Transform bone = Bones[boneIndex];

                                    Vector3 Position = StudioBone.pos;
                                    Vector3 Rotation = StudioBone.rot;

                                    //BINGO! All animations are corrected :p
                                    if (AnimBone != null)
                                    {
                                        if ((AnimBone.Flags & STUDIO_ANIM_RAWROT) > 0)
                                        {
                                            Rotation = MathLibrary.ToEulerAngles(AnimBone.pQuat48);
                                        }

                                        if ((AnimBone.Flags & STUDIO_ANIM_RAWROT2) > 0)
                                        {
                                            Rotation = MathLibrary.ToEulerAngles(AnimBone.pQuat64);
                                        }

                                        if ((AnimBone.Flags & STUDIO_ANIM_RAWPOS) > 0)
                                        {
                                            Position = AnimBone.pVec48;
                                        }

                                        if ((AnimBone.Flags & STUDIO_ANIM_ANIMROT) > 0)
                                        {
                                            Rotation += AnimBone.FrameAngles[(FramesLess && frameID != 0) ? frameID - 1 : frameID].Multiply(StudioBone.rotscale);
                                        }

                                        if ((AnimBone.Flags & STUDIO_ANIM_ANIMPOS) > 0)
                                        {
                                            Position += AnimBone.FramePositions[(FramesLess && frameID != 0) ? frameID - 1 : frameID].Multiply(StudioBone.posscale);
                                        }

                                        if ((AnimBone.Flags & STUDIO_ANIM_DELTA) > 0)
                                        {
                                            Position = Vector3.zero;
                                            Rotation = Vector3.zero;
                                        }
                                    }

                                    //Invert right-handed position to left-handed
                                    if (StudioBone.parent == -1)
                                    {
                                        Position = MathLibrary.SwapY(Position);
                                    }
                                    else
                                    {
                                        Position.x = -Position.x;
                                    }

                                    //Corrects global scale and convert radians to degrees
                                    Position *= uLoader.UnitScale;
                                    Rotation *= Mathf.Rad2Deg;
                                    Quaternion quat;

                                    //Fix up bone rotations from right-handed to left-handed
                                    if (StudioBone.parent == -1)
                                    {
                                        quat = Quaternion.Euler(-90, 180, -90) * MathLibrary.AngleQuaternion(Rotation);
                                    }
                                    else
                                    {
                                        quat = MathLibrary.AngleQuaternion(Rotation);
                                    }

                                    Animations[AnimID].PosX[frameID][boneID] = new Keyframe(time, Position.x);
                                    Animations[AnimID].PosY[frameID][boneID] = new Keyframe(time, Position.y);
                                    Animations[AnimID].PosZ[frameID][boneID] = new Keyframe(time, Position.z);

                                    Animations[AnimID].RotX[frameID][boneID] = new Keyframe(time, quat.x);
                                    Animations[AnimID].RotY[frameID][boneID] = new Keyframe(time, quat.y);
                                    Animations[AnimID].RotZ[frameID][boneID] = new Keyframe(time, quat.z);
                                    Animations[AnimID].RotW[frameID][boneID] = new Keyframe(time, quat.w);
                                }
                            }
                        }
                        //Animations

                        //Sequences
                        MDL_SeqDescriptions = new mstudioseqdesc_t[MDL_Header.localseq_count];
                        Sequences           = new SeqInfo[MDL_Header.localseq_count];

                        for (Int32 seqID = 0; seqID < MDL_Header.localseq_count; seqID++)
                        {
                            Int32 sequenceOffset = MDL_Header.localseq_offset + (212 * seqID);
                            FileStream.ReadTypeFixed(ref MDL_SeqDescriptions[seqID], 212, sequenceOffset);
                            mstudioseqdesc_t Sequence = MDL_SeqDescriptions[seqID];
                            Sequences[seqID] = new SeqInfo {
                                name = FileStream.ReadNullTerminatedString(sequenceOffset + Sequence.szlabelindex), seq = Sequence
                            };

                            FileStream.BaseStream.Position = sequenceOffset + Sequence.animindexindex;

                            var animID = FileStream.ReadShortArray(Sequence.groupsize[0] * Sequence.groupsize[1]);
                            //Debug.LogWarning(animIndices[0]);
                            // Just use the first animation for now
                            Sequences[seqID].ani = Animations[animID[0]];
                        }
                        //Sequences
                    }
                    catch (Exception ex)
                    {
                        Debug.LogError(String.Format("\"{0}\" Parse animation failed: {1}", MDL_Header.Name, ex));
                    }
                }
                #endregion

                #region Materials
                //Materials
                MDL_TexturesInfo = new mstudiotexture_t[MDL_Header.texture_count];
                MDL_Textures     = new String[MDL_Header.texture_count];
                for (Int32 TexID = 0; TexID < MDL_Header.texture_count; TexID++)
                {
                    Int32 TextureOffset = MDL_Header.texture_offset + (64 * TexID);
                    FileStream.ReadTypeFixed(ref MDL_TexturesInfo[TexID], 64, TextureOffset);
                    MDL_Textures[TexID] = FileStream.ReadNullTerminatedString(TextureOffset + MDL_TexturesInfo[TexID].sznameindex);
                }

                Int32[] TDirOffsets = new Int32[MDL_Header.texturedir_count];
                MDL_TDirectories = new String[MDL_Header.texturedir_count];
                for (Int32 DirID = 0; DirID < MDL_Header.texturedir_count; DirID++)
                {
                    FileStream.ReadTypeFixed(ref TDirOffsets[DirID], 4, MDL_Header.texturedir_offset + (4 * DirID));
                    MDL_TDirectories[DirID] = FileStream.ReadNullTerminatedString(TDirOffsets[DirID]);
                }
                //Materials
                #endregion

                #region BodyParts
                //Bodyparts
                MDL_Bodyparts = new StudioBodyPart[MDL_Header.bodypart_count];
                for (Int32 BodypartID = 0; BodypartID < MDL_Header.bodypart_count; BodypartID++)
                {
                    mstudiobodyparts_t BodyPart = new mstudiobodyparts_t();
                    Int32 BodyPartOffset        = MDL_Header.bodypart_offset + (16 * BodypartID);
                    FileStream.ReadTypeFixed(ref BodyPart, 16, BodyPartOffset);

                    if (BodyPart.sznameindex != 0)
                    {
                        MDL_Bodyparts[BodypartID].Name = FileStream.ReadNullTerminatedString(BodyPartOffset + BodyPart.sznameindex);
                    }
                    else
                    {
                        MDL_Bodyparts[BodypartID].Name = String.Empty;
                    }

                    MDL_Bodyparts[BodypartID].Models = new StudioModel[BodyPart.nummodels];

                    for (Int32 ModelID = 0; ModelID < BodyPart.nummodels; ModelID++)
                    {
                        mstudiomodel_t Model       = new mstudiomodel_t();
                        Int64          ModelOffset = BodyPartOffset + (148 * ModelID) + BodyPart.modelindex;
                        FileStream.ReadTypeFixed(ref Model, 148, ModelOffset);

                        MDL_Bodyparts[BodypartID].Models[ModelID].isBlank = (Model.numvertices <= 0 || Model.nummeshes <= 0);
                        MDL_Bodyparts[BodypartID].Models[ModelID].Model   = Model;

                        MDL_Bodyparts[BodypartID].Models[ModelID].Meshes = new mstudiomesh_t[Model.nummeshes];
                        for (Int32 MeshID = 0; MeshID < Model.nummeshes; MeshID++)
                        {
                            mstudiomesh_t Mesh       = new mstudiomesh_t();
                            Int64         MeshOffset = ModelOffset + (116 * MeshID) + Model.meshindex;
                            FileStream.ReadTypeFixed(ref Mesh, 116, MeshOffset);

                            MDL_Bodyparts[BodypartID].Models[ModelID].Meshes[MeshID] = Mesh;
                        }

                        MDL_Bodyparts[BodypartID].Models[ModelID].IndicesPerLod = new Dictionary <Int32, List <Int32> > [8];

                        for (Int32 i = 0; i < 8; i++)
                        {
                            MDL_Bodyparts[BodypartID].Models[ModelID].IndicesPerLod[i] = new Dictionary <Int32, List <Int32> >();
                        }

                        MDL_Bodyparts[BodypartID].Models[ModelID].VerticesPerLod = new mstudiovertex_t[8][];
                    }
                }
                //BodyParts
                #endregion
            }
        }
        static void ParseMdlFile()
        {
            if (MDL_Header.id != 0x54534449)
            {
                throw new FileLoadException(String.Format("{0}: File signature does not match 'IDST'", ModelObject.name + ".mdl"));
            }

            MDL_BodyParts = new mstudiobodyparts_t[MDL_Header.bodypart_count];
            ModelFileLoader.ReadArray(ref MDL_BodyParts, MDL_Header.bodypart_offset);

            Int32 ModelInputFilePosition = MDL_Header.bodypart_offset + MDL_BodyParts[0].modelindex;

            MDL_Models = new mstudiomodel_t[MDL_BodyParts[0].nummodels];
            ModelFileLoader.ReadArray(ref MDL_Models, ModelInputFilePosition);

            Int32 MeshInputFilePosition = ModelInputFilePosition + MDL_Models[0].meshindex;

            MDL_Meshes = new mstudiomesh_t[MDL_Models[0].nummeshes];
            ModelFileLoader.ReadArray(ref MDL_Meshes, MeshInputFilePosition);

            mstudiotexture_t[] MDL_TexturesInfo = new mstudiotexture_t[MDL_Header.texture_count];
            ModelFileLoader.ReadArray(ref MDL_TexturesInfo, MDL_Header.texture_offset);

            MDL_Textures = new String[MDL_Header.texture_count];
            for (Int32 i = 0; i < MDL_Header.texture_count; i++)
            {
                Int32 StringInputFilePosition = MDL_Header.texture_offset + (Marshal.SizeOf(typeof(mstudiotexture_t)) * i) + MDL_TexturesInfo[i].sznameindex;
                MDL_Textures[i] = ModelFileLoader.ReadNullTerminatedString(StringInputFilePosition);
            }

            Int32[] TDirOffsets = new Int32[MDL_Header.texturedir_count];
            ModelFileLoader.ReadArray(ref TDirOffsets, MDL_Header.texturedir_offset);

            MDL_TDirectories = new String[MDL_Header.texturedir_count];
            for (Int32 i = 0; i < MDL_Header.texturedir_count; i++)
            {
                MDL_TDirectories[i] = ModelFileLoader.ReadNullTerminatedString(TDirOffsets[i]);
            }

            mstudiobone_t[] MDL_BonesInfo = new mstudiobone_t[MDL_Header.bone_count];
            ModelFileLoader.ReadArray(ref MDL_BonesInfo, MDL_Header.bone_offset);

            for (Int32 i = 0; i < MDL_Header.bone_count; i++)
            {
                Int32 StringInputFilePosition = MDL_Header.bone_offset + (Marshal.SizeOf(typeof(mstudiobone_t)) * i) + MDL_BonesInfo[i].sznameindex;

                GameObject BoneObject = new GameObject(ModelFileLoader.ReadNullTerminatedString(StringInputFilePosition));
                MDL_Bones.Add(BoneObject.transform);
                Transform FixUp = null;

                // WIP - It works incorrectly (nearly)
                //Temporary "Fix" Bone Transform
                //TODO: Remove this sh*t code, rly :D
                if (MDL_BonesInfo[i].parent >= 0)
                {
                    MDL_Bones[i].parent = MDL_Bones[MDL_BonesInfo[i].parent];
                    MDL_Bones[i].transform.localPosition = -MDL_BonesInfo[i].pos * ConfigLoader.WorldScale;
                    MDL_Bones[i].transform.localRotation = MDL_BonesInfo[i].quat;
                }
                else
                {
                    FixUp = new GameObject("FIXUP").transform;
                    FixUp.transform.rotation             = Quaternion.Euler(new Vector3(-270, 0, 0));
                    MDL_Bones[i].parent                  = FixUp;
                    MDL_Bones[i].transform.localPosition = -MDL_BonesInfo[i].pos * ConfigLoader.WorldScale;
                    MDL_Bones[i].transform.localRotation = MDL_BonesInfo[i].quat;
                    MDL_Bones[i].parent                  = ModelObject.transform;
                    UnityEngine.Object.DestroyImmediate(FixUp.gameObject);
                }
            }
        }