public static void TravelTree(ModelBone bone, ref CNT parent, bool root = false)
        {
            var cnt = new CNT();
            if (root) { cnt = parent; }

            cnt.Name = bone.Name;
            cnt.Transform = new Matrix3D(
                                bone.Transform.M11, bone.Transform.M12, bone.Transform.M13,
                                bone.Transform.M21, bone.Transform.M22, bone.Transform.M23,
                                bone.Transform.M31, bone.Transform.M32, bone.Transform.M33,
                                bone.Transform.M41, bone.Transform.M42, bone.Transform.M43
                            );

            switch (bone.Type)
            {
                case BoneType.Mesh:
                    cnt.Section = CNT.NodeType.MODL;
                    cnt.Model = bone.Mesh.Name;
                    break;

                case BoneType.Light:
                    cnt.Section = CNT.NodeType.LITg;

                    cnt.EmbeddedLight = (bone.AttachmentFile == null);

                    if (cnt.EmbeddedLight)
                    {
                        cnt.Light = (ToxicRagers.CarmageddonReincarnation.Formats.LIGHT)bone.Attachment;
                    }
                    else
                    {
                        cnt.LightName = bone.AttachmentFile;

                        var light = bone.Attachment as ToxicRagers.CarmageddonReincarnation.Formats.LIGHT;
                        if (light != null)
                        {
                            light.Save(Path.Combine(rootPath, cnt.LightName + ".light"));
                        }
                    }
                    break;

                case BoneType.VFX:
                    cnt.Section = CNT.NodeType.VFXI;
                    cnt.VFXFile = bone.AttachmentFile;
                    break;

                default:
                    cnt.Section = CNT.NodeType.NULL;
                    break;
            }

            foreach (var b in bone.Children)
            {
                TravelTree(b, ref cnt);
            }

            if (!root) { parent.Children.Add(cnt); }
        }
        public override void Export(Asset asset, string path)
        {
            rootPath = Path.GetDirectoryName(path);

            var model = (asset as Model);
            var cnt = new CNT();

            TravelTree(model.Root, ref cnt, true);

            cnt.Save(path);
        }
        static void ProcessCNT(CNT cnt, Model model, int ParentBoneIndex = 0)
        {
            int boneIndex;

            SceneManager.Current.UpdateProgress(string.Format("Processing {0}", cnt.Name));

            if (cnt.Section == CNT.NodeType.MODL || cnt.Section == CNT.NodeType.SKIN)
            {
                var m = SceneManager.Current.Content.Load<Model, MDLImporter>(cnt.Model, rootPath);
                boneIndex = model.AddMesh(m.Meshes[0], ParentBoneIndex);
            }
            else
            {
                boneIndex = model.AddMesh(null, ParentBoneIndex);

                switch (cnt.Section)
                {
                    case CNT.NodeType.LITg:
                        model.Bones[boneIndex].Type = BoneType.Light;
                        if (cnt.EmbeddedLight)
                        {
                            model.Bones[boneIndex].Attachment = cnt.Light;
                        }
                        else
                        {
                            model.Bones[boneIndex].Attachment = SceneManager.Current.Content.Load<Model, LIGHTImporter>(cnt.LightName, rootPath).Bones[0].Attachment;
                            model.Bones[boneIndex].AttachmentFile = cnt.LightName;
                        }
                        break;

                    case CNT.NodeType.VFXI:
                        model.Bones[boneIndex].Type = BoneType.VFX;
                        model.Bones[boneIndex].AttachmentFile = cnt.VFXFile;
                        break;
                }
            }

            model.SetName(cnt.Name, boneIndex);
            model.SetTransform(
                new Matrix4 (
                    cnt.Transform.M11, cnt.Transform.M12, cnt.Transform.M13, 0,
                    cnt.Transform.M21, cnt.Transform.M22, cnt.Transform.M23, 0,
                    cnt.Transform.M31, cnt.Transform.M32, cnt.Transform.M33, 0,
                    cnt.Transform.M41, cnt.Transform.M42, cnt.Transform.M43, 1
                ), boneIndex);

            foreach (CNT subcnt in cnt.Children)
            {
                ProcessCNT(subcnt, model, boneIndex);
            }
        }
Exemple #4
0
        private static void Save(BinaryWriter bw, CNT cnt)
        {
            int nameLength = cnt.Name.Length;
            int padding = (((nameLength / 4) + (nameLength % 4 > 0 ? 1 : 0)) * 4) - nameLength;

            bw.Write(nameLength);
            bw.WriteString(cnt.Name);
            bw.Write(new byte[padding]);

            bw.Write((byte)0);

            bw.Write((int)0);

            bw.Write(cnt.Transform.M11);
            bw.Write(cnt.Transform.M12);
            bw.Write(cnt.Transform.M13);
            bw.Write(cnt.Transform.M21);
            bw.Write(cnt.Transform.M22);
            bw.Write(cnt.Transform.M23);
            bw.Write(cnt.Transform.M31);
            bw.Write(cnt.Transform.M32);
            bw.Write(cnt.Transform.M33);
            bw.Write(cnt.Transform.M41);
            bw.Write(cnt.Transform.M42);
            bw.Write(cnt.Transform.M43);

            bw.WriteString(cnt.Section.ToString());

            switch (cnt.Section)
            {
                case NodeType.LITg:
                    if (cnt.EmbeddedLight)
                    {
                        bw.Write(2);
                        LIGHT.Save(bw, cnt.Light);
                    }
                    else
                    {
                        bw.Write(3);
                        nameLength = cnt.LightName.Length;
                        padding = (((nameLength / 4) + (nameLength % 4 > 0 ? 1 : 0)) * 4) - nameLength;

                        bw.Write(cnt.LightName.Length);
                        bw.WriteString(cnt.LightName);
                        bw.Write(new byte[padding]);
                    }
                    break;

                case NodeType.MODL:
                case NodeType.SKIN:
                    nameLength = cnt.Model.Length;
                    padding = (((nameLength / 4) + (nameLength % 4 > 0 ? 1 : 0)) * 4) - nameLength;

                    bw.Write(nameLength);
                    bw.WriteString(cnt.Model);
                    bw.Write(new byte[padding]);
                    break;

                case NodeType.NULL:
                    break;

                default:
                    throw new NotImplementedException(string.Format("Save code for CNT section {0} does not exist!", cnt.Section));
            }

            bw.Write(cnt.Children.Count);
            foreach (CNT c in cnt.Children) { Save(bw, c); }
            bw.Write((int)0);
        }
Exemple #5
0
        // The Load(BinaryReader) version skips the header check and is used for recursive loading
        private static CNT Load(BinaryReader br, Version version, CNT parent = null)
        {
            CNT cnt = new CNT();
            int nameLength, padding;
            if (parent != null) { cnt.parent = parent; }

            cnt.version = version;

            if (version.Major == 3)
            {
                cnt.name = br.ReadBytes(16).ToName();

                Logger.LogToFile(Logger.LogLevel.Debug, "Name: \"{0}\"", cnt.Name);
            }
            else
            {
                nameLength = (int)br.ReadUInt32();
                padding = (((nameLength / 4) + (nameLength % 4 > 0 ? 1 : 0)) * 4) - nameLength;

                cnt.name = br.ReadString(nameLength);
                br.ReadBytes(padding);

                Logger.LogToFile(Logger.LogLevel.Debug, "Name: \"{0}\" of length {1}, padding of {2}", cnt.Name, nameLength, padding);
            }

            byte flags = br.ReadByte();
            while (flags != 0)
            {
                Logger.LogToFile(Logger.LogLevel.Debug, "Flags: {0}", flags);
                flags = br.ReadByte();
            }

            br.ReadUInt32();    // zero terminator?

            cnt.transform = 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()
                            );

            cnt.section = br.ReadString(4).ToEnum<NodeType>();
            switch (cnt.section)
            {
                case NodeType.LITg:
                    int resourceType = (int)br.ReadUInt32();
                    switch (resourceType)
                    {
                        case 2: // Embedded
                            cnt.bEmbeddedLight = true;
                            cnt.light = LIGHT.Load(br);
                            break;

                        case 3: // External
                            nameLength = (int)br.ReadUInt32();
                            padding = (((nameLength / 4) + (nameLength % 4 > 0 ? 1 : 0)) * 4) - nameLength;

                            cnt.lightName = br.ReadString(nameLength);
                            br.ReadBytes(padding);

                            Logger.LogToFile(Logger.LogLevel.Debug, "LITg: \"{0}\" of length {1}, padding of {2}", cnt.lightName, nameLength, padding);
                            break;

                        default:
                            throw new NotImplementedException(string.Format("Unknown resource type: {0}.  Aborting", resourceType));
                    }
                    break;

                case NodeType.MODL:
                case NodeType.SKIN:
                    if (version.Major == 3)
                    {
                        cnt.modelName = br.ReadBytes(16).ToName();

                        Logger.LogToFile(Logger.LogLevel.Debug, "MODL: \"{0}\"", cnt.Name);
                        br.ReadBytes(16);
                    }
                    else
                    {
                        nameLength = (int)br.ReadUInt32();
                        padding = (((nameLength / 4) + (nameLength % 4 > 0 ? 1 : 0)) * 4) - nameLength;

                        cnt.modelName = br.ReadString(nameLength);
                        br.ReadBytes(padding);

                        Logger.LogToFile(Logger.LogLevel.Debug, "{0}: \"{1}\" of length {2}, padding of {3}", cnt.section, cnt.modelName, nameLength, padding);
                    }

                    break;

                case NodeType.VFXI:
                    nameLength = (int)br.ReadUInt32();

                    cnt.effectName = br.ReadString(nameLength);

                    Logger.LogToFile(Logger.LogLevel.Debug, "VFXI: \"{0}\" of length {1}, padding of {2}", cnt.effectName, nameLength, 0);
                    break;

                case NodeType.SPLN:
                    Logger.LogToFile(Logger.LogLevel.Warning, "SPLN, skipping 88 bytes");
                    br.ReadBytes(88);
                    break;

                case NodeType.NULL:
                    break;

                // EMIT, EMT2 and LITd no longer occur in C:R
                case NodeType.LITd:
                    Logger.LogToFile(Logger.LogLevel.Debug, "LITd, skipping 16 bytes");
                    br.ReadBytes(16);
                    break;

                case NodeType.EMIT:    // <= v4.0
                    int emitVersion = br.ReadByte();
                    int toSkip = (emitVersion == 6 ? 128 : 136);

                    br.ReadBytes(25);
                    Logger.LogToFile(Logger.LogLevel.Debug, "EMIT v{0}, skipping 26 bytes, reading a name (\"{1}\") and then skipping {2} bytes", emitVersion, br.ReadString((int)br.ReadUInt32()), toSkip);
                    br.ReadBytes(toSkip);
                    break;

                case NodeType.EMT2:    // no longer in C:R
                    br.ReadBytes(34);
                    Logger.LogToFile(Logger.LogLevel.Debug, "EMT2, skipping 34 bytes, reading a name (\"{0}\") and then skipping 612 bytes", br.ReadString((int)br.ReadUInt32()));
                    br.ReadBytes(612);
                    break;

                default:
                    Logger.LogToFile(Logger.LogLevel.Error, "Unknown section \"{0}\"; Aborting", cnt.section);
                    return null;
            }

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

            for (int i = 0; i < childNodes; i++)
            {
                Logger.LogToFile(Logger.LogLevel.Debug, "Loading child {0} of {1}", (i + 1), childNodes);
                cnt.childNodes.Add(Load(br, version, cnt));
            }

            br.ReadUInt32();    // Terminator

            return cnt;
        }