Exemple #1
0
 public TDRMatrix()
 {
     matrix = Matrix3D.Identity;
 }
Exemple #2
0
        public static MDL Load(string path)
        {
            FileInfo fi = new FileInfo(path);
            Logger.LogToFile(Logger.LogLevel.Info, "{0}", path);
            MDL mdl = new MDL();

            mdl.name = fi.Name.Replace(fi.Extension, "");

            using (MemoryStream ms = new MemoryStream(File.ReadAllBytes(path)))
            using (BinaryReader br = new BinaryReader(ms, Encoding.Default))
            {
                if (br.ReadByte() != 0x45||
                    br.ReadByte() != 0x23)
                {
                    Logger.LogToFile(Logger.LogLevel.Error, "{0} isn't a valid MDL file", path);
                    return null;
                }

                byte minor = br.ReadByte();
                byte major = br.ReadByte();

                mdl.version = new Version(major, minor);

                if (!MDL.SupportedVersions.ContainsKey(mdl.version.ToString()))
                {
                    Logger.LogToFile(Logger.LogLevel.Error, "Unsupported MDL version: v{0}", mdl.version.ToString());
                    return null;
                }

                Logger.LogToFile(Logger.LogLevel.Info, "MDL v{0}", mdl.version.ToString());

                // TODO: v5.6
                // Ref : Novadrome_Demo\WADs\data\DATA\SFX\CAR_EXPLOSION\DEBPOOL\DEBPOOL.MDL
                // Ref : Carmageddon Mobile\Data_IOS\DATA\CONTENT\SFX\SHRAPNEL.MDL
                // 01 00 00 00 EE 02 00 00 02 00 00 00 04 00 00 00 01 00 00 00 49 33 35 3F 89 41 00 BF 18 B7 51 BA 89 41 00 BF 00 00 00 3F 52 49 9D 3A 00 00 00 3F 00 12 03 BA 18 B7 51 39 00 12 03 BA 01 00 66 69 72 65 70 6F 6F 6C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 02 00 00 00 17 B7 51 39 17 B7 D1 38 00 00 80 3F 17 B7 D1 B8 00 00 00 00 03 00 00 00 02 00 00 00 01 00 00 00 17 B7 51 39 17 B7 D1 B8 00 00 80 3F 17 B7 D1 38 04 00 00 00 00 00 00 3F 17 B7 D1 38 00 00 00 BF 17 B7 D1 38 00 00 80 3F 17 B7 D1 B8 00 00 80 3F 00 00 80 3F 00 00 00 00 00 00 00 00 80 80 80 FF 00 00 00 BF 17 B7 51 39 00 00 00 BF 00 00 00 00 00 00 80 3F 00 00 00 00 00 00 00 00 00 00 80 3F 00 00 00 00 00 00 00 00 80 80 80 FF 00 00 00 3F 17 B7 51 39 00 00 00 3F 00 00 00 00 00 00 80 3F 00 00 00 00 00 00 80 3F 00 00 00 00 00 00 00 00 00 00 00 00 80 80 80 FF 00 00 00 BF 17 B7 D1 38 00 00 00 3F 17 B7 D1 B8 00 00 80 3F 17 B7 D1 38 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 80 80 FF 01 00 00 00 00 00 17 B7 D1 38 00 00 00 00 00 00 00 00 04 00 00 00 04 00 00 00 00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF FF FF

                mdl.checkSum = (int)br.ReadUInt32();

                mdl.flags = (Flags)br.ReadUInt32();
                Logger.LogToFile(Logger.LogLevel.Debug, "Flags {0}", (Flags)mdl.flags);

                mdl.prepDataSize = (int)br.ReadUInt32();    // PREP data size

                mdl.userFaceCount = (int)br.ReadUInt32();
                mdl.userVertexCount = (int)br.ReadUInt32();

                Logger.LogToFile(Logger.LogLevel.Debug, "USER Faces: {0}", mdl.userFaceCount);
                Logger.LogToFile(Logger.LogLevel.Debug, "USER Verts: {0}", mdl.userVertexCount);

                mdl.fileSize = (int)br.ReadUInt32();

                mdl.extents.Radius = br.ReadSingle();
                mdl.extents.Min = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle());
                mdl.extents.Max = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle());
                br.ReadBytes(12);   //  BoundingBox centre, Flummery auto calculates from min and max

                int materialCount = br.ReadInt16();

                Logger.LogToFile(Logger.LogLevel.Debug, "Material count: {0}", materialCount);

                for (int i = 0; i < materialCount; i++)
                {
                    string materialName;
                    int nameLength = -1;
                    int padding = -1;

                    if (mdl.version.Major < 6)
                    {
                        materialName = br.ReadBytes(32).ToName();
                    }
                    else
                    {
                        nameLength = (int)br.ReadInt32();
                        padding = (((nameLength / 4) + (nameLength % 4 > 0 ? 1 : 0)) * 4) - nameLength + (mdl.version.Major == 6 && mdl.version.Minor > 0 ? 4 : 0);
                        materialName = br.ReadString(nameLength);
                        br.ReadBytes(padding);
                    }

                    mdl.meshes.Add(new MDLMaterialGroup(i, materialName));
                }

                // START PREP DATA
                mdl.prepFaceCount = (int)br.ReadUInt32();

                Logger.LogToFile(Logger.LogLevel.Debug, "PREP Faces: {0}", mdl.prepFaceCount);

                for (int i = 0; i < mdl.prepFaceCount; i++)
                {
                    var face = new MDLFace(
                        br.ReadUInt16(),        // Material index
                        br.ReadUInt16(),        // Material Flags
                        (int)br.ReadUInt32(),   // Vert index A
                        (int)br.ReadUInt32(),   // Vert index B
                        (int)br.ReadUInt32()    // Vert index C
                    );

                    mdl.faces.Add(face);

                    Logger.LogToFile(Logger.LogLevel.Debug, "{0} : {1}", i, face);
                }

                mdl.prepVertexCount = (int)br.ReadUInt32();

                Logger.LogToFile(Logger.LogLevel.Debug, "PREP Verts: {0}", mdl.prepVertexCount);

                for (int i = 0; i < mdl.prepVertexCount; i++)
                {
                    var vert = new MDLVertex(
                        br.ReadSingle(),        // X
                        br.ReadSingle(),        // Y
                        br.ReadSingle(),        // Z
                        br.ReadSingle(),        // N.X
                        br.ReadSingle(),        // N.Y
                        br.ReadSingle(),        // N.Z
                        br.ReadSingle(),        // U
                        br.ReadSingle(),        // V
                        br.ReadSingle(),        // U2
                        br.ReadSingle(),        // V2
                        br.ReadByte(),          // R
                        br.ReadByte(),          // G
                        br.ReadByte(),          // B
                        br.ReadByte()           // A
                    );

                    mdl.verts.Add(vert);

                    Logger.LogToFile(Logger.LogLevel.Debug, "{0} : {1}", i, vert);
                }

                int materialGroups = br.ReadUInt16();

                for (int i = 0; i < materialGroups; i++)
                {
                    var mesh = mdl.meshes[i];

                    br.ReadBytes(12);   // BoundingBox Centre, we recalculate it from Min and Max
                    mesh.Extents.Radius = br.ReadSingle();
                    mesh.Extents.Min = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle());
                    mesh.Extents.Max = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle());

                    mesh.StripOffset = (int)br.ReadUInt32();
                    mesh.StripVertCount = (int)br.ReadUInt32();
                    int stripPointCount = (int)br.ReadUInt32();

                    Logger.LogToFile(Logger.LogLevel.Debug, "{0} : {1} : {2}", mesh.StripOffset, mesh.StripVertCount, stripPointCount);

                    for (int j = 0; j < stripPointCount; j++)
                    {
                        uint index = br.ReadUInt32();
                        bool bDegenerate = ((index & 0x80000000) != 0);
                        index &= ~0x80000000;

                        mesh.StripList.Add(new MDLPoint((int)index + mesh.StripOffset, bDegenerate));

                        Logger.LogToFile(Logger.LogLevel.Debug, "{0} ] {1} : {2}", j, index, bDegenerate);
                    }

                    mesh.TriListOffset = (int)br.ReadUInt32();
                    mesh.TriListVertCount = (int)br.ReadUInt32();
                    int listPointCount = (int)br.ReadUInt32();

                    Logger.LogToFile(Logger.LogLevel.Debug, "{0} : {1} : {2}", mesh.TriListOffset, mesh.TriListVertCount, listPointCount);

                    for (int j = 0; j < listPointCount; j++)
                    {
                        uint index = br.ReadUInt32();

                        mesh.TriList.Add(new MDLPoint((int)index + mesh.TriListOffset));

                        Logger.LogToFile(Logger.LogLevel.Debug, "{0} ] {1}", j, index);
                    }
                }

                if (mdl.flags.HasFlag(Flags.PREPSkinData))
                {
                    Logger.LogToFile(Logger.LogLevel.Debug, "Processing PREP skin data");

                    int bodyPartCount = br.ReadUInt16();
                    int maxBonesPerVertex = br.ReadUInt16();
                    int rootBoneIndex = br.ReadUInt16();
                    var boneNames = br.ReadStrings(bodyPartCount);

                    Logger.LogToFile(Logger.LogLevel.Debug, "Body Part Count: {0}. Max Bones per Vertex : {1}. Root Bone Index : {2}", bodyPartCount, maxBonesPerVertex, rootBoneIndex);

                    for (int i = 0; i < bodyPartCount; i++)
                    {
                        var bone = new MDLBone();

                        bone.Name = boneNames[i];
                        bone.MinExtents = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle());   // Min and Max bone local space
                        bone.MaxExtents = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle());
                        bone.Offset = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle());       // Offset is in parents local space

                        bone.Parent = br.ReadByte();
                        bone.Child = br.ReadByte();
                        bone.Sibling = br.ReadByte();

                        mdl.prepBoneList.Add(bone);
                    }

                    for (int i = 0; i < bodyPartCount; i++)
                    {
                        mdl.prepBoneList[i].Rotation = new Vector4(br.ReadSingle(), br.ReadSingle(), br.ReadSingle(), br.ReadSingle());
                        mdl.prepBoneList[i].Position = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle());
                        br.ReadBytes(4);

                        Logger.LogToFile(Logger.LogLevel.Debug, "{0}) {1}", i, mdl.prepBoneList[i].Name);
                        Logger.LogToFile(Logger.LogLevel.Debug, "P{0} C{1} S{2}", mdl.prepBoneList[i].Parent, mdl.prepBoneList[i].Child, mdl.prepBoneList[i].Sibling);
                        Logger.LogToFile(Logger.LogLevel.Debug, "{0}", mdl.prepBoneList[i].MinExtents);
                        Logger.LogToFile(Logger.LogLevel.Debug, "{0}", mdl.prepBoneList[i].MaxExtents);
                        Logger.LogToFile(Logger.LogLevel.Debug, "{0}", mdl.prepBoneList[i].Offset);
                        Logger.LogToFile(Logger.LogLevel.Debug, "{0}", mdl.prepBoneList[i].Rotation);
                        Logger.LogToFile(Logger.LogLevel.Debug, "{0}", mdl.prepBoneList[i].Position);
                        Logger.LogToFile(Logger.LogLevel.Debug, "");
                    }

                    Logger.LogToFile(Logger.LogLevel.Debug, "PREP skin vert weight table");

                    for (int i = 0; i < mdl.prepVertexCount; i++)
                    {
                        int weightCount = br.ReadUInt16();
                        br.ReadBytes(2);
                        int weightOffset = (int)br.ReadUInt32();

                        mdl.prepVertSkinWeightLookup.Add(new MDLPrepSkinWeightLookup { Count = weightCount, Index = weightOffset });

                        Logger.LogToFile(Logger.LogLevel.Debug, "{0,5}]  {1} @ {2}", i, weightCount, weightOffset);
                    }

                    int prepSkinWeightCount = (int)br.ReadUInt32();

                    Logger.LogToFile(Logger.LogLevel.Debug, "PREP Skin Weight Count: {0}", prepSkinWeightCount);

                    for (int i = 0; i < prepSkinWeightCount; i++)
                    {
                        int boneIndex = br.ReadUInt16();
                        Logger.LogToFile(Logger.LogLevel.Debug, "{0,5}] {1}", i, boneIndex);
                    }

                    for (int i = 0; i < prepSkinWeightCount; i++)
                    {
                        Single weight = br.ReadSingle();
                        Logger.LogToFile(Logger.LogLevel.Debug, "{0,5}] {1}", i, weight);
                    }
                }
                // END PREP DATA

                // START USER DATA
                if (mdl.flags.HasFlag(Flags.USERData))
                {
                    mdl.userFlags = (Flags)br.ReadUInt32();

                    // v5.6 successfully parses from this point down

                    Logger.LogToFile(Logger.LogLevel.Debug, "USER vertex list with index count");
                    for (int i = 0; i < mdl.userVertexCount; i++)
                    {
                        mdl.userVertexList.Add(new MDLUserVertexEntry(br.ReadSingle(), br.ReadSingle(), br.ReadSingle(), (int)br.ReadUInt32()));
                    }

                    Logger.LogToFile(Logger.LogLevel.Debug, "USER face data");
                    for (int i = 0; i < mdl.userFaceCount; i++)
                    {
                        if (mdl.version.Major == 5 && mdl.version.Minor == 6)
                        {
                            br.ReadBytes(133);
                        }
                        else
                        {
                            mdl.userFaceList.Add(
                                new MDLUserFaceEntry(
                                        br.ReadSingle(), br.ReadSingle(), br.ReadSingle(), br.ReadSingle(), // plane equation
                                        new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()),     // vertex[0] normal
                                        new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()),     // vertex[1] normal
                                        new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()),     // vertex[2] normal
                                        (int)br.ReadUInt32(),                                               // material index
                                        (int)br.ReadUInt32(),                                               // smoothing group
                                        (int)br.ReadUInt32(),                                               // vertex[0]
                                        (int)br.ReadUInt32(),                                               // vertex[1]
                                        (int)br.ReadUInt32(),                                               // vertex[2]
                                        br.ReadByte(), br.ReadByte(), br.ReadByte(), br.ReadByte(),         // colour[0] RGBA
                                        br.ReadByte(), br.ReadByte(), br.ReadByte(), br.ReadByte(),         // colour[1] RGBA
                                        br.ReadByte(), br.ReadByte(), br.ReadByte(), br.ReadByte(),         // colour[2] RGBA
                                        new Vector2(br.ReadSingle(), br.ReadSingle()),                      // uv[0]
                                        new Vector2(br.ReadSingle(), br.ReadSingle()),                      // uv2[0]
                                        new Vector2(br.ReadSingle(), br.ReadSingle()),                      // uv[1]
                                        new Vector2(br.ReadSingle(), br.ReadSingle()),                      // uv2[1]
                                        new Vector2(br.ReadSingle(), br.ReadSingle()),                      // uv[2]
                                        new Vector2(br.ReadSingle(), br.ReadSingle()),                      // uv2[2]
                                        br.ReadByte(),                                                      // flags
                                        (int)br.ReadUInt32()                                                // application specific flags
                                ) // 137 bytes
                            );
                        }
                    }

                    Logger.LogToFile(Logger.LogLevel.Debug, "PREP to USER face lookup");
                    for (int i = 0; i < mdl.prepFaceCount; i++)
                    {
                        mdl.ptouFaceLookup.Add((int)br.ReadUInt32());
                    }

                    int prepVertexMapCount = (int)br.ReadUInt32();
                    Logger.LogToFile(Logger.LogLevel.Debug, "PREP to USER vertex lookup");

                    for (int i = 0; i < prepVertexMapCount; i++)
                    {
                        mdl.ptouVertexLookup.Add((int)br.ReadUInt32());
                    }

                    if (mdl.userFlags.HasFlag(Flags.USERSkinData))
                    {
                        Logger.LogToFile(Logger.LogLevel.Debug, "Processing USER skin data");

                        int boneCount = br.ReadUInt16();

                        Logger.LogToFile(Logger.LogLevel.Debug, "Bone count: {0}", boneCount);
                        for (int i = 0; i < boneCount; i++)
                        {
                            string boneName = br.ReadString(32);
                            short parentBoneIndex = br.ReadInt16();
                            Matrix3D boneTransform = new Matrix3D(
                                                            br.ReadSingle(), br.ReadSingle(), br.ReadSingle(),
                                                            br.ReadSingle(), br.ReadSingle(), br.ReadSingle(),
                                                            br.ReadSingle(), br.ReadSingle(), br.ReadSingle(),
                                                            br.ReadSingle(), br.ReadSingle(), br.ReadSingle()
                                                        );

                            Logger.LogToFile(Logger.LogLevel.Debug, "{0}) {1}", i, boneName);
                            Logger.LogToFile(Logger.LogLevel.Debug, "{0}", parentBoneIndex);
                            Logger.LogToFile(Logger.LogLevel.Debug, "{0}", boneTransform);
                            Logger.LogToFile(Logger.LogLevel.Debug, "");
                        }

                        int userDataCount = (int)br.ReadUInt32();
                        Logger.LogToFile(Logger.LogLevel.Debug, "{0} == {1}", userDataCount, mdl.userVertexCount);

                        for (int i = 0; i < mdl.userVertexCount; i++)
                        {
                            int entryCount = br.ReadUInt16();

                            for (int j = 0; j < entryCount; j++)
                            {
                                int boneIndex = br.ReadUInt16();
                                Single weight = br.ReadSingle();
                                Vector3 vertexPosition = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle());
                                Logger.LogToFile(Logger.LogLevel.Debug, "{0}.{1}]  {2,2} : {3,6:0.00}% : {4}", i, j, boneIndex, (weight * 100.0f), vertexPosition);
                            }
                        }
                    }
                }
                else
                {
                    Console.WriteLine("no user data");
                }

                if (br.BaseStream.Position != br.BaseStream.Length) { Logger.LogToFile(Logger.LogLevel.Warning, "Still has data remaining (processed {0:x2} of {1:x2}", br.BaseStream.Position, br.BaseStream.Length); }
            }

            return mdl;
        }
Exemple #3
0
        public void AddPivot(string PivotName, string ActorName, string ActorModel, Matrix3D Transform)
        {
            sections.Add(new ACTNode(Section.Name, PivotName)); //, false, 0, 0
            sections.Add(new ACTNode(Transform));
            sections.Add(new ACTNode(Section.Section37));

            sections.Add(new ACTNode(Section.Name, ActorName)); //, false, 1, 4
            sections.Add(new ACTNode(Matrix3D.Identity));
            sections.Add(new ACTNode(Section.Section37));
            sections.Add(new ACTNode(Section.Model, ActorModel));
            sections.Add(new ACTNode(Section.SubLevelEnd));

            sections.Add(new ACTNode(Section.SubLevelEnd));
        }
Exemple #4
0
 public ACTNode(Matrix3D transform)
 {
     this.section = Section.Matrix;
     this.transform = transform;
 }
Exemple #5
0
 public void AddActor(string ActorName, string Model, Matrix3D Transform, bool Parent)
 {
     sections.Add(new ACTNode(Section.Name, ActorName) { ActorType = (Model != null ? ActorType.BR_ACTOR_MODEL : ActorType.BR_ACTOR_NONE) });
     sections.Add(new ACTNode(Transform));
     sections.Add(new ACTNode(Section.Section37));
     if (Model != null) { sections.Add(new ACTNode(Section.Model, Model)); }
     if (!Parent) { sections.Add(new ACTNode(Section.SubLevelEnd)); }
 }