Example #1
0
        public GeoAnimData(byte[] file, int address, uint imageBase, LandTableFormat format, Dictionary <int, string> labels, Dictionary <int, Attach> attaches)
        {
            ModelFormat mfmt = 0;

            switch (format)
            {
            case LandTableFormat.SA1:
                mfmt = ModelFormat.Basic;
                break;

            case LandTableFormat.SADX:
                mfmt = ModelFormat.BasicDX;
                break;

            case LandTableFormat.SA2:
                mfmt = ModelFormat.Chunk;
                break;
            }
            AnimationFrame = ByteConverter.ToSingle(file, address);
            AnimationSpeed = ByteConverter.ToSingle(file, address + 4);
            MaxFrame       = ByteConverter.ToSingle(file, address + 8);
            Model          = new NJS_OBJECT(file, (int)(ByteConverter.ToUInt32(file, address + 0xC) - imageBase), imageBase, mfmt, labels, attaches);
            int actionaddr = (int)(ByteConverter.ToUInt32(file, address + 0x10) - imageBase);

            TexlistPointer = ByteConverter.ToUInt32(file, address + 0x14);
            NJS_ACTION action = new NJS_ACTION(file, actionaddr, imageBase, mfmt, labels, attaches);

            Animation = action.Animation;
        }
Example #2
0
        public NJS_OBJECT Clone()
        {
            NJS_OBJECT result = (NJS_OBJECT)MemberwiseClone();

            if (Attach != null)
            {
                result.Attach = Attach.Clone();
            }
            result.Position = Position.Clone();
            result.Rotation = Rotation.Clone();
            result.Scale    = Scale.Clone();
            result.children = new List <NJS_OBJECT>(children.Count);
            result.Children = new ReadOnlyCollection <NJS_OBJECT>(result.children);
            if (children.Count > 0)
            {
                NJS_OBJECT child = children[0].Clone();
                while (child != null)
                {
                    result.children.Add(child);
                    child = child.Sibling;
                }
            }
            if (Sibling != null)
            {
                result.Sibling = Sibling.Clone();
            }
            return(result);
        }
Example #3
0
        public void RemoveChildAt(int index)
        {
            NJS_OBJECT child = children[index];

            children.RemoveAt(index);
            child.Parent = null;
        }
Example #4
0
 public void AddChild(NJS_OBJECT child)
 {
     children.Add(child);
     child.Parent = this;
     if (child.Sibling != null)
     {
         AddChild(child.Sibling);
     }
 }
Example #5
0
 public GeoAnimData(NJS_OBJECT model, NJS_MOTION animation)
 {
     Model                = model;
     Animation            = animation;
     MaxFrame             = animation.Frames;
     AnimationSpeed       = 1.0f;
     Animation.ActionName = "action_" + Extensions.GenerateIdentifier();
     Animation.ObjectName = model.Name;
 }
Example #6
0
        public void ProcessShapeMotionVertexData(NJS_MOTION motion, float frame)
        {
            int        animindex = -1;
            NJS_OBJECT obj       = this;

            do
            {
                obj.ProcessShapeMotionVertexData(motion, frame, ref animindex);
                obj = obj.Sibling;
            } while (obj != null);
        }
Example #7
0
        public ModelFile(byte[] file, string filename = null)
        {
            int  tmpaddr;
            bool be = ByteConverter.BigEndian;

            ByteConverter.BigEndian = false;
            ulong magic   = ByteConverter.ToUInt64(file, 0) & FormatMask;
            byte  version = file[7];

            if (version > CurrentVersion)
            {
                throw new FormatException("Not a valid SA1MDL/SA2MDL file.");
            }
            Metadata = new Dictionary <uint, byte[]>();
            Dictionary <int, string> labels   = new Dictionary <int, string>();
            Dictionary <int, Attach> attaches = new Dictionary <int, Attach>();

            if (version < 2)
            {
                if (version == 1)
                {
                    tmpaddr = ByteConverter.ToInt32(file, 0x14);
                    if (tmpaddr != 0)
                    {
                        int addr = ByteConverter.ToInt32(file, tmpaddr);
                        while (addr != -1)
                        {
                            labels.Add(addr, file.GetCString(ByteConverter.ToInt32(file, tmpaddr + 4)));
                            tmpaddr += 8;
                            addr     = ByteConverter.ToInt32(file, tmpaddr);
                        }
                    }
                }
                switch (magic)
                {
                case SA1MDL:
                    Format = ModelFormat.Basic;
                    break;

                case SA2MDL:
                    Format = ModelFormat.Chunk;
                    break;

                default:
                    throw new FormatException("Not a valid SA1MDL/SA2MDL file.");
                }
                Model = new NJS_OBJECT(file, ByteConverter.ToInt32(file, 8), 0, Format, labels, attaches);
                if (filename != null)
                {
                    tmpaddr = ByteConverter.ToInt32(file, 0xC);
                    if (tmpaddr != 0)
                    {
                        List <string> animfiles = new List <string>();
                        int           addr      = ByteConverter.ToInt32(file, tmpaddr);
                        while (addr != -1)
                        {
                            animfiles.Add(file.GetCString(addr));
                            tmpaddr += 4;
                            addr     = ByteConverter.ToInt32(file, tmpaddr);
                        }
                        animationFiles = animfiles.ToArray();
                    }
                    else
                    {
                        animationFiles = new string[0];
                    }
                    string            path  = Path.GetDirectoryName(filename);
                    List <NJS_MOTION> anims = new List <NJS_MOTION>();
                    try
                    {
                        foreach (string item in animationFiles)
                        {
                            anims.Add(NJS_MOTION.Load(Path.Combine(path, item), Model.CountAnimated()));
                        }
                    }
                    catch
                    {
                        anims.Clear();
                    }
                    Animations = anims.AsReadOnly();
                }
            }
            else
            {
                animationFiles = new string[0];
                tmpaddr        = ByteConverter.ToInt32(file, 0xC);
                if (tmpaddr != 0)
                {
                    bool finished = false;
                    while (!finished)
                    {
                        ChunkTypes type      = (ChunkTypes)ByteConverter.ToUInt32(file, tmpaddr);
                        int        chunksz   = ByteConverter.ToInt32(file, tmpaddr + 4);
                        int        nextchunk = tmpaddr + 8 + chunksz;
                        tmpaddr += 8;
                        if (version == 2)
                        {
                            switch (type)
                            {
                            case ChunkTypes.Label:
                                while (ByteConverter.ToInt64(file, tmpaddr) != -1)
                                {
                                    labels.Add(ByteConverter.ToInt32(file, tmpaddr), file.GetCString(ByteConverter.ToInt32(file, tmpaddr + 4)));
                                    tmpaddr += 8;
                                }
                                break;

                            case ChunkTypes.Animation:
                                List <string> animfiles = new List <string>();
                                while (ByteConverter.ToInt32(file, tmpaddr) != -1)
                                {
                                    animfiles.Add(file.GetCString(ByteConverter.ToInt32(file, tmpaddr)));
                                    tmpaddr += 4;
                                }
                                animationFiles = animfiles.ToArray();
                                break;

                            case ChunkTypes.Morph:
                                break;

                            case ChunkTypes.Author:
                                Author = file.GetCString(tmpaddr);
                                break;

                            case ChunkTypes.Tool:
                                break;

                            case ChunkTypes.Description:
                                Description = file.GetCString(tmpaddr);
                                break;

                            case ChunkTypes.Texture:
                                break;

                            case ChunkTypes.End:
                                finished = true;
                                break;
                            }
                        }
                        else
                        {
                            byte[] chunk = new byte[chunksz];
                            Array.Copy(file, tmpaddr, chunk, 0, chunksz);
                            int chunkaddr = 0;
                            switch (type)
                            {
                            case ChunkTypes.Label:
                                while (ByteConverter.ToInt64(chunk, chunkaddr) != -1)
                                {
                                    labels.Add(ByteConverter.ToInt32(chunk, chunkaddr),
                                               chunk.GetCString(ByteConverter.ToInt32(chunk, chunkaddr + 4)));
                                    chunkaddr += 8;
                                }
                                break;

                            case ChunkTypes.Animation:
                                List <string> animchunks = new List <string>();
                                while (ByteConverter.ToInt32(chunk, chunkaddr) != -1)
                                {
                                    animchunks.Add(chunk.GetCString(ByteConverter.ToInt32(chunk, chunkaddr)));
                                    chunkaddr += 4;
                                }
                                animationFiles = animchunks.ToArray();
                                break;

                            case ChunkTypes.Morph:
                                break;

                            case ChunkTypes.Author:
                                Author = chunk.GetCString(chunkaddr);
                                break;

                            case ChunkTypes.Tool:
                                break;

                            case ChunkTypes.Description:
                                Description = chunk.GetCString(chunkaddr);
                                break;

                            case ChunkTypes.End:
                                finished = true;
                                break;

                            default:
                                Metadata.Add((uint)type, chunk);
                                break;
                            }
                        }
                        tmpaddr = nextchunk;
                    }
                }
                switch (magic)
                {
                case SA1MDL:
                    Format = ModelFormat.Basic;
                    break;

                case SA2MDL:
                    Format = ModelFormat.Chunk;
                    break;

                case SA2BMDL:
                    Format = ModelFormat.GC;
                    break;

                case XJMDL:
                    Format = ModelFormat.XJ;
                    break;

                default:
                    throw new FormatException("Not a valid SA1MDL/SA2MDL file.");
                }
                Model = new NJS_OBJECT(file, ByteConverter.ToInt32(file, 8), 0, Format, labels, attaches);
                if (filename != null)
                {
                    string path = Path.GetDirectoryName(filename);
                    if (File.Exists(Path.GetFileNameWithoutExtension(filename) + ".action"))
                    {
                        using (TextReader tr = File.OpenText(Path.GetFileNameWithoutExtension(filename) + ".action"))
                        {
                            List <string> animlist = new List <string>();
                            int           count    = File.ReadLines(Path.GetFileNameWithoutExtension(filename) + ".action").Count();
                            for (int i = 0; i < count; i++)
                            {
                                string line = tr.ReadLine();
                                if (File.Exists(Path.Combine(path, line)))
                                {
                                    animlist.Add(line);
                                }
                            }
                            animationFiles = animlist.ToArray();
                        }
                    }
                    List <NJS_MOTION> anims = new List <NJS_MOTION>();
                    try
                    {
                        foreach (string item in animationFiles)
                        {
                            if (Path.GetExtension(item).ToLowerInvariant() == ".json")
                            {
                                JsonSerializer js = new JsonSerializer()
                                {
                                    Culture = System.Globalization.CultureInfo.InvariantCulture
                                };
                                using (TextReader tr = File.OpenText(Path.Combine(path, item)))
                                {
                                    using (JsonTextReader jtr = new JsonTextReader(tr))
                                        anims.Add(js.Deserialize <NJS_MOTION>(jtr));
                                }
                            }
                            else
                            {
                                anims.Add(NJS_MOTION.Load(Path.Combine(path, item), Model.CountAnimated()));
                            }
                        }
                    }
                    catch
                    {
                        anims.Clear();
                    }
                    Animations = anims.AsReadOnly();
                }
            }
            ByteConverter.BigEndian = be;
        }
Example #8
0
        public static void CreateFile(string filename, NJS_OBJECT model, string[] animationFiles, string author,
                                      string description, Dictionary <uint, byte[]> metadata, ModelFormat format, bool nometa = false, bool useNinjaMetaData = false)
        {
            uint ninjaMagic;
            uint imageBase = (uint)(useNinjaMetaData ? 0 : 0x10);
            bool be        = ByteConverter.BigEndian;

            if (useNinjaMetaData == false)
            {
                ByteConverter.BigEndian = false;
            }
            if (format == ModelFormat.BasicDX)
            {
                format = ModelFormat.Basic;
            }
            List <byte> file = new List <byte>();
            ulong       magic;

            switch (format)
            {
            case ModelFormat.Basic:
            case ModelFormat.BasicDX:
                magic      = SA1MDLVer;
                ninjaMagic = NJBMMagic;
                break;

            case ModelFormat.Chunk:
                magic      = SA2MDLVer;
                ninjaMagic = NJCMMagic;
                break;

            case ModelFormat.GC:
                magic      = SA2BMDLVer;
                ninjaMagic = GJCMMagic;
                break;

            case ModelFormat.XJ:
                magic      = XJMDLVer;
                ninjaMagic = NJCMMagic;                         //XJ uses Chunk's magic
                break;

            default:
                throw new ArgumentException("Cannot save " + format.ToString() + " format models to file!", "format");
            }
            Dictionary <string, uint> labels = new Dictionary <string, uint>();
            List <uint> njOffsets            = new List <uint>();

            byte[] mdl;
            uint   addr;

            if (useNinjaMetaData == true)
            {
                mdl = model.NJGetBytes(imageBase, false, labels, njOffsets, out addr);
                //***Ninja metadata should always be little endian!***
                file.AddRange(BitConverter.GetBytes(ninjaMagic));
                file.AddRange(BitConverter.GetBytes(mdl.Length));
                //***Ninja metadata should always be little endian!***
            }
            else
            {
                mdl = model.GetBytes(imageBase, false, labels, njOffsets, out addr);
                file.AddRange(ByteConverter.GetBytes(magic));
                file.AddRange(ByteConverter.GetBytes(addr + 0x10));
                file.AddRange(ByteConverter.GetBytes(mdl.Length + 0x10));
            }
            file.AddRange(mdl);
            if (!nometa)
            {
                if (labels.Count > 0)
                {
                    List <byte> chunk    = new List <byte>((labels.Count * 8) + 8);
                    int         straddr  = (labels.Count * 8) + 8;
                    List <byte> strbytes = new List <byte>();
                    foreach (KeyValuePair <string, uint> label in labels)
                    {
                        chunk.AddRange(ByteConverter.GetBytes(label.Value));
                        chunk.AddRange(ByteConverter.GetBytes(straddr + strbytes.Count));
                        strbytes.AddRange(Encoding.UTF8.GetBytes(label.Key));
                        strbytes.Add(0);
                        strbytes.Align(4);
                    }
                    chunk.AddRange(ByteConverter.GetBytes(-1L));
                    chunk.AddRange(strbytes);
                    file.AddRange(ByteConverter.GetBytes((uint)ChunkTypes.Label));
                    file.AddRange(ByteConverter.GetBytes(chunk.Count));
                    file.AddRange(chunk);
                }
                if (animationFiles != null && animationFiles.Length > 0)
                {
                    using (TextWriter tw = File.CreateText(Path.ChangeExtension(filename, ".action")))
                    {
                        for (int a = 0; a < animationFiles.Count(); a++)
                        {
                            tw.WriteLine(animationFiles[a]);
                        }
                        tw.Flush();
                        tw.Close();
                    }

                    /*
                     * //Old animation code
                     * List<byte> chunk = new List<byte>((animationFiles.Length + 1) * 4);
                     * int straddr = (animationFiles.Length + 1) * 4;
                     * List<byte> strbytes = new List<byte>();
                     * for (int i = 0; i < animationFiles.Length; i++)
                     * {
                     *      chunk.AddRange(ByteConverter.GetBytes(straddr + strbytes.Count));
                     *      strbytes.AddRange(Encoding.UTF8.GetBytes(animationFiles[i]));
                     *      strbytes.Add(0);
                     *      strbytes.Align(4);
                     * }
                     * chunk.AddRange(ByteConverter.GetBytes(-1));
                     * chunk.AddRange(strbytes);
                     * file.AddRange(ByteConverter.GetBytes((uint)ChunkTypes.Animation));
                     * file.AddRange(ByteConverter.GetBytes(chunk.Count));
                     * file.AddRange(chunk);
                     */
                }
                if (!string.IsNullOrEmpty(author))
                {
                    List <byte> chunk = new List <byte>(author.Length + 1);
                    chunk.AddRange(Encoding.UTF8.GetBytes(author));
                    chunk.Add(0);
                    chunk.Align(4);
                    file.AddRange(ByteConverter.GetBytes((uint)ChunkTypes.Author));
                    file.AddRange(ByteConverter.GetBytes(chunk.Count));
                    file.AddRange(chunk);
                }
                if (!string.IsNullOrEmpty(description))
                {
                    List <byte> chunk = new List <byte>(description.Length + 1);
                    chunk.AddRange(Encoding.UTF8.GetBytes(description));
                    chunk.Add(0);
                    chunk.Align(4);
                    file.AddRange(ByteConverter.GetBytes((uint)ChunkTypes.Description));
                    file.AddRange(ByteConverter.GetBytes(chunk.Count));
                    file.AddRange(chunk);
                }
                if (metadata != null)
                {
                    foreach (KeyValuePair <uint, byte[]> item in metadata)
                    {
                        file.AddRange(ByteConverter.GetBytes(item.Key));
                        file.AddRange(ByteConverter.GetBytes(item.Value.Length));
                        file.AddRange(item.Value);
                    }
                }
            }
            if (useNinjaMetaData == true)
            {
                /*
                 * List<uint> addresses = new List<uint>();
                 * foreach(var pair in labels)
                 * {
                 *      if(pair.Value != 0)
                 *      {
                 *              addresses.Add(pair.Value);
                 *      }
                 * }
                 * addresses.Insert(0, 0x4);
                 * addresses.Sort();*/
                njOffsets = njOffsets.Distinct().ToList();
                njOffsets.Sort();
                List <byte> pof0 = new List <byte>();
                pof0.Add(0x41);
                for (int i = 1; i < njOffsets.Count; i++)
                {
                    pof0.AddRange(POF0Helper.calcPOF0Pointer(njOffsets[i - 1], njOffsets[i]));
                }
                POF0Helper.finalizePOF0(pof0);
                file.AddRange(pof0);

                if (metadata.Count != 0 && metadata.ContainsKey(uint.MaxValue))
                {
                    file.InsertRange(0, metadata[uint.MaxValue]);
                }
            }
            else
            {
                file.AddRange(ByteConverter.GetBytes((uint)ChunkTypes.End));
                file.AddRange(new byte[4]);
            }
            File.WriteAllBytes(filename, file.ToArray());
            ByteConverter.BigEndian = be;
        }
Example #9
0
        public COL(byte[] file, int address, uint imageBase, LandTableFormat format, Dictionary <int, string> labels, bool?forceBasic, Dictionary <int, Attach> attaches)
        {
            Bounds = new BoundingSphere(file, address);
            ModelFormat mfmt = 0;

            switch (format)
            {
            case LandTableFormat.SA1:
                mfmt = ModelFormat.Basic;
                break;

            case LandTableFormat.SADX:
                mfmt = ModelFormat.BasicDX;
                break;

            case LandTableFormat.SA2:
                if (forceBasic.HasValue && forceBasic.Value)
                {
                    mfmt = ModelFormat.Basic;
                }
                else
                {
                    mfmt = ModelFormat.Chunk;
                }
                break;

            case LandTableFormat.SA2B:
                if (forceBasic.HasValue && forceBasic.Value)
                {
                    mfmt = ModelFormat.Basic;
                }
                else
                {
                    mfmt = ModelFormat.GC;
                }
                break;
            }
            switch (format)
            {
            case LandTableFormat.SA1:
            case LandTableFormat.SADX:
                WidthY = ByteConverter.ToSingle(file, address + 0x10);
                WidthZ = ByteConverter.ToSingle(file, address + 0x14);
                uint tmpaddr = ByteConverter.ToUInt32(file, address + 0x18) - imageBase;
                Model     = new NJS_OBJECT(file, (int)tmpaddr, imageBase, mfmt, labels, attaches);
                BlockBits = ByteConverter.ToUInt32(file, address + 0x1C);
                Flags     = ByteConverter.ToInt32(file, address + 0x20);
                break;

            case LandTableFormat.SA2:
            case LandTableFormat.SA2B:
                Flags = ByteConverter.ToInt32(file, address + 0x1C);
                if (!forceBasic.HasValue && Flags >= 0)
                {
                    mfmt = ModelFormat.Basic;
                }
                tmpaddr   = ByteConverter.ToUInt32(file, address + 0x10) - imageBase;
                Model     = new NJS_OBJECT(file, (int)tmpaddr, imageBase, mfmt, labels, attaches);
                WidthZ    = ByteConverter.ToInt32(file, address + 0x14);
                BlockBits = ByteConverter.ToUInt32(file, address + 0x18);
                break;
            }
        }
Example #10
0
 public void RemoveChild(NJS_OBJECT child)
 {
     children.Remove(child);
     child.Parent = null;
 }
Example #11
0
 public void InsertChild(int index, NJS_OBJECT child)
 {
     children.Insert(index, child);
     child.Parent = this;
 }
Example #12
0
        private NJS_OBJECT(byte[] file, int address, uint imageBase, ModelFormat format, NJS_OBJECT parent, Dictionary <int, string> labels, Dictionary <int, Attach> attaches)
        {
            if (labels.ContainsKey(address))
            {
                Name = labels[address];
            }
            else
            {
                Name = "object_" + address.ToString("X8");
            }
            if (address > file.Length - 52)
            {
                Position = new Vertex();
                Rotation = new Rotation();
                Scale    = new Vertex(1, 1, 1);
                children = new List <NJS_OBJECT>();
                Children = new ReadOnlyCollection <NJS_OBJECT>(children);
                return;
            }
            ObjectFlags flags = (ObjectFlags)ByteConverter.ToInt32(file, address);

            RotateZYX      = (flags & ObjectFlags.RotateZYX) == ObjectFlags.RotateZYX;
            SkipDraw       = (flags & ObjectFlags.NoDisplay) == ObjectFlags.NoDisplay;
            SkipChildren   = (flags & ObjectFlags.NoChildren) == ObjectFlags.NoChildren;
            IgnorePosition = (flags & ObjectFlags.NoPosition) == ObjectFlags.NoPosition;
            IgnoreRotation = (flags & ObjectFlags.NoRotate) == ObjectFlags.NoRotate;
            IgnoreScale    = (flags & ObjectFlags.NoScale) == ObjectFlags.NoScale;
            Animate        = (flags & ObjectFlags.NoAnimate) == 0;
            Morph          = (flags & ObjectFlags.NoMorph) == 0;
            int tmpaddr = ByteConverter.ToInt32(file, address + 4);

            if (tmpaddr != 0)
            {
                tmpaddr = (int)unchecked ((uint)tmpaddr - imageBase);
                if (attaches != null && attaches.ContainsKey(tmpaddr))
                {
                    Attach = attaches[tmpaddr];
                }
                else
                {
                    Attach = Attach.Load(file, tmpaddr, imageBase, format, labels);
                    if (attaches != null)
                    {
                        attaches.Add(tmpaddr, Attach);
                    }
                }
            }
            Position = new Vertex(file, address + 8);
            Rotation = new Rotation(file, address + 0x14);
            Scale    = new Vertex(file, address + 0x20);
            Parent   = parent;
            children = new List <NJS_OBJECT>();
            Children = new ReadOnlyCollection <NJS_OBJECT>(children);
            NJS_OBJECT child = null;

            tmpaddr = ByteConverter.ToInt32(file, address + 0x2C);
            if (tmpaddr != 0)
            {
                tmpaddr = (int)unchecked ((uint)tmpaddr - imageBase);
                child   = new NJS_OBJECT(file, tmpaddr, imageBase, format, this, labels, attaches);
            }
            while (child != null)
            {
                children.Add(child);
                child = child.Sibling;
            }
            tmpaddr = ByteConverter.ToInt32(file, address + 0x30);
            if (tmpaddr != 0)
            {
                tmpaddr = (int)unchecked ((uint)tmpaddr - imageBase);
                Sibling = new NJS_OBJECT(file, tmpaddr, imageBase, format, parent, labels, attaches);
            }

            //Assimp.AssimpContext context = new AssimpContext();
            //Scene scene = context.ImportFile("F:\\untitled.obj", PostProcessSteps.Triangulate);
            //AssimpLoad(scene, scene.RootNode);
        }