Example #1
0
        public override void ProcessShapeMotionVertexData(NJS_MOTION motion, float frame, int animindex)
        {
            if (!motion.Models.ContainsKey(animindex))
            {
                ProcessVertexData();
                return;
            }
#if modellog
            Extensions.Log("Processing Chunk Attach " + Name + Environment.NewLine);
#endif
            if (Vertex != null)
            {
                foreach (VertexChunk chunk in Vertex)
                {
#if modellog
                    Extensions.Log("Vertex Declaration: " + chunk.IndexOffset + "-" + (chunk.IndexOffset + chunk.VertexCount - 1) + Environment.NewLine);
#endif
                    if (VertexBuffer.Length < chunk.IndexOffset + chunk.VertexCount)
                    {
                        Array.Resize(ref VertexBuffer, chunk.IndexOffset + chunk.VertexCount);
                    }
                    Vertex[]      vertdata = chunk.Vertices.ToArray();
                    Vertex[]      normdata = chunk.Normals.ToArray();
                    AnimModelData data     = motion.Models[animindex];
                    if (data.Vertex.Count > 0)
                    {
                        vertdata = data.GetVertex(frame);
                    }
                    if (data.Normal.Count > 0)
                    {
                        normdata = data.GetNormal(frame);
                    }
                    for (int i = 0; i < chunk.VertexCount; i++)
                    {
                        VertexBuffer[i + chunk.IndexOffset] = new VertexData(vertdata[i]);
                        if (normdata.Length > 0)
                        {
                            VertexBuffer[i + chunk.IndexOffset].Normal = normdata[i];
                        }
                        if (chunk.Diffuse.Count > 0)
                        {
                            VertexBuffer[i + chunk.IndexOffset].Color = chunk.Diffuse[i];
                        }
                    }
                }
            }
            List <MeshInfo> result = new List <MeshInfo>();
            if (Poly != null)
            {
                result = ProcessPolyList(PolyName, Poly, 0);
            }
            MeshInfo = result.ToArray();
        }
Example #2
0
        static NJS_MOTION ProcessMotion(byte[] file, int verbose = 0, int startaddress = 0)
        {
            int frames;
            InterpolationMode intmode;
            AnimFlags         animtype;
            int curaddr = 0;

            do
            {
                AnimSections section_type = (AnimSections)BitConverter.ToInt16(file, curaddr);
                int          section_size = BitConverter.ToInt32(file, curaddr + 4);
                int          section_addr = curaddr + 8;
                if (verbose > 1)
                {
                    Console.Write("Subsection type {0}, size {1}, data begins at {2}\n", section_type.ToString(), section_size, section_addr.ToString("X"));
                }
                switch (section_type)
                {
                case AnimSections.MKEY_F:
                    if (verbose > 1)
                    {
                        Console.Write(", calculated item count: {0}\n", (float)section_size / 16.0f);
                    }
                    break;

                case AnimSections.MKEY_A:
                    if (verbose > 1)
                    {
                        Console.Write(", calculated item count: {0}\n", (float)section_size / 16.0f);
                    }
                    break;

                case AnimSections.UNKNOWN:
                    if (verbose > 1)
                    {
                        Console.Write(", calculated item count: {0}\n", (float)section_size / 16.0f);
                    }
                    break;

                case AnimSections.MDATA2_HEADER:
                    if (verbose > 1)
                    {
                        Console.Write(", number of MDATA entries: {0}\n", BitConverter.ToInt32(file, section_addr) >> BitConverter.ToInt32(file, section_addr + 4));
                    }
                    break;

                case AnimSections.MOTION:
                    if (verbose > 0)
                    {
                        Console.WriteLine("Motion at {0}", (startaddress + section_addr).ToString("X"));
                    }
                    frames   = BitConverter.ToInt32(file, section_addr + 4);
                    intmode  = (InterpolationMode)BitConverter.ToInt16(file, section_addr + 10);
                    animtype = (AnimFlags)BitConverter.ToInt16(file, section_addr + 8);
                    int mdataaddr = BitConverter.ToInt32(file, section_addr);
                    if (verbose > 1)
                    {
                        Console.Write("\nMDATA header at: {0}, frames: {1}, flags: {2}, interpolation: {3}", mdataaddr.ToString("X"), frames, animtype.ToString(), intmode.ToString());
                    }
                    // Create motion stub
                    NJS_MOTION mot = new NJS_MOTION();
                    mot.Name              = "animation_" + section_addr.ToString("X8");
                    mot.MdataName         = mot.Name + "_mdat";
                    mot.Frames            = frames;
                    mot.InterpolationMode = intmode;
                    // Read the MDATA header and get the number of MDATA entries
                    mot.ModelParts = BitConverter.ToInt32(file, mdataaddr) >> BitConverter.ToInt32(file, mdataaddr + 4);
                    if (verbose > 1)
                    {
                        Console.WriteLine(", model parts: {0}", mot.ModelParts);
                    }
                    int tmpaddr = mdataaddr + 8;                             //Start of actual MDATA array
                    for (int u = 0; u < mot.ModelParts; u++)
                    {
                        //Console.Write("\nMotion data {0}", u.ToString());
                        AnimModelData data = new AnimModelData();
                        if (animtype.HasFlag(AnimFlags.Position))
                        {
                            uint posoff = ByteConverter.ToUInt32(file, tmpaddr + u * 16);
                            data.PositionName = mot.Name + "_mkey_" + u.ToString() + "_pos_" + posoff.ToString("X8");
                            int pos_count = ByteConverter.ToInt32(file, tmpaddr + u * 16 + 8);
                            //Console.Write(", position at: {0} ({1} entries)", posoff.ToString("X"), pos_count);
                            for (int p = 0; p < pos_count; p++)
                            {
                                int   index = ByteConverter.ToInt32(file, (int)posoff + p * 16);
                                float pos_x = ByteConverter.ToSingle(file, (int)posoff + p * 16 + 4);
                                float pos_y = ByteConverter.ToSingle(file, (int)posoff + p * 16 + 8);
                                float pos_z = ByteConverter.ToSingle(file, (int)posoff + p * 16 + 12);
                                //Console.WriteLine("\nAdded position index {3}: X: {0} Y: {1} Z: {2}", pos_x, pos_y, pos_z, index);
                                data.Position.Add(index, new Vertex(pos_x, pos_y, pos_z));
                            }
                        }
                        if (animtype.HasFlag(AnimFlags.Rotation))
                        {
                            uint rotoff = ByteConverter.ToUInt32(file, tmpaddr + u * 16 + 4);
                            data.RotationName = mot.Name + "_mkey_" + u.ToString() + "_rot_" + rotoff.ToString("X8");
                            int rot_count = ByteConverter.ToInt32(file, tmpaddr + u * 16 + 12);
                            //Console.Write(", rotation at: {0} ({1} entries)", rotoff.ToString("X"), rot_count);
                            for (int p = 0; p < rot_count; p++)
                            {
                                int index = ByteConverter.ToInt32(file, (int)rotoff + p * 16);
                                int rot_x = ByteConverter.ToInt32(file, (int)rotoff + p * 16 + 4);
                                int rot_y = ByteConverter.ToInt32(file, (int)rotoff + p * 16 + 8);
                                int rot_z = ByteConverter.ToInt32(file, (int)rotoff + p * 16 + 12);
                                //Console.WriteLine("\nAdded rotation index {3}: X: {0} Y: {1} Z: {2}", rot_x, rot_y, rot_z, index);
                                data.Rotation.Add(index, new Rotation(rot_x, rot_y, rot_z));
                            }
                        }
                        mot.Models.Add(u, data);
                    }
                    return(mot);
                }
                curaddr += 8 + section_size;
            }while (curaddr < file.Length);
            return(null);
        }
Example #3
0
        static byte[] GetSections(NJS_MOTION motion, int verbose = 0)
        {
            List <byte> result = new List <byte>();

            int[] mkey_f_addr    = new int[motion.ModelParts];
            int[] mkey_a_addr    = new int[motion.ModelParts];
            int   mkey_f_section = 0;
            int   mkey_f_count   = 0;

            // Get MKEY_F
            foreach (var anim in motion.Models)
            {
                AnimModelData model = anim.Value;
                if (model.Position != null && model.Position.Count > 0)
                {
                    mkey_f_addr[anim.Key] = result.Count;
                    if (verbose > 1)
                    {
                        Console.WriteLine("MKEY_F: {0} at {1}", anim.Key, result.Count.ToString("X"));
                    }
                    foreach (var item in model.Position)
                    {
                        result.AddRange(BitConverter.GetBytes(item.Key));
                        result.AddRange(BitConverter.GetBytes(item.Value.X));
                        result.AddRange(BitConverter.GetBytes(item.Value.Y));
                        result.AddRange(BitConverter.GetBytes(item.Value.Z));
                        mkey_f_count++;
                    }
                }
            }
            if (mkey_f_count > 0)
            {
                result.InsertRange(mkey_f_section, BitConverter.GetBytes((uint)0));
                result.InsertRange(mkey_f_section + 4, BitConverter.GetBytes((uint)mkey_f_count * 16));
            }
            // Get MKEY_A
            int mkey_a_section = result.Count;
            int mkey_a_count   = 0;

            foreach (var anim in motion.Models)
            {
                AnimModelData model = anim.Value;
                if (model.Rotation != null && model.Rotation.Count > 0)
                {
                    mkey_a_addr[anim.Key] = result.Count;
                    if (verbose > 1)
                    {
                        Console.WriteLine("MKEY_A: {0} at {1}", anim.Key, result.Count.ToString("X"));
                    }
                    foreach (var item in model.Rotation)
                    {
                        result.AddRange(BitConverter.GetBytes(item.Key));
                        result.AddRange(BitConverter.GetBytes(item.Value.X));
                        result.AddRange(BitConverter.GetBytes(item.Value.Y));
                        result.AddRange(BitConverter.GetBytes(item.Value.Z));
                        mkey_a_count++;
                    }
                }
            }
            if (mkey_a_count > 0)
            {
                result.InsertRange(mkey_a_section, BitConverter.GetBytes((uint)1));
                result.InsertRange(mkey_a_section + 4, BitConverter.GetBytes((uint)mkey_a_count * 16));
            }
            // Get MDATA2 header
            int mdata_section = result.Count;

            for (int m = 0; m < motion.ModelParts; m++)
            {
                if (motion.Models.ContainsKey(m))
                {
                    AnimModelData model = motion.Models[m];
                    if (model.Position != null && model.Position.Count > 0)
                    {
                        result.AddRange(BitConverter.GetBytes((uint)(mkey_f_addr[m] + 8)));
                    }
                    else
                    {
                        result.AddRange(BitConverter.GetBytes((uint)0));
                    }
                    if (model.Rotation != null && model.Rotation.Count > 0)
                    {
                        result.AddRange(BitConverter.GetBytes((uint)(mkey_a_addr[m] + 8)));
                    }
                    else
                    {
                        result.AddRange(BitConverter.GetBytes((uint)0));
                    }
                    if (model.Position != null)
                    {
                        result.AddRange(BitConverter.GetBytes((uint)(model.Position.Count)));
                    }
                    else
                    {
                        result.AddRange(BitConverter.GetBytes((uint)0));
                    }
                    if (model.Rotation != null)
                    {
                        result.AddRange(BitConverter.GetBytes((uint)(model.Rotation.Count)));
                    }
                    else
                    {
                        result.AddRange(BitConverter.GetBytes((uint)0));
                    }
                }
                else
                {
                    result.AddRange(BitConverter.GetBytes((uint)0));
                    result.AddRange(BitConverter.GetBytes((uint)0));
                    result.AddRange(BitConverter.GetBytes((uint)0));
                    result.AddRange(BitConverter.GetBytes((uint)0));
                }
            }
            result.InsertRange(mdata_section, BitConverter.GetBytes((uint)3));
            result.InsertRange(mdata_section + 4, BitConverter.GetBytes((uint)(16 * motion.ModelParts + 8)));
            result.InsertRange(mdata_section + 8, BitConverter.GetBytes((uint)motion.ModelParts << 2));
            result.InsertRange(mdata_section + 12, BitConverter.GetBytes((uint)2));
            // Write motion header
            result.AddRange(BitConverter.GetBytes((uint)4));
            result.AddRange(BitConverter.GetBytes((uint)12));
            result.AddRange(BitConverter.GetBytes(mdata_section + 8));
            result.AddRange(BitConverter.GetBytes(motion.Frames));
            // It's MDATA2 so flags are hardcoded
            AnimFlags flags = 0;

            flags |= AnimFlags.Position;
            flags |= AnimFlags.Rotation;
            result.AddRange(BitConverter.GetBytes((short)flags));
            result.AddRange(BitConverter.GetBytes((short)motion.InterpolationMode));
            return(result.ToArray());
        }
Example #4
0
 private void UpdateWeightedModels()
 {
     if (scenenum > 0)
     {
         for (int i = 0; i < @event.Scenes[scenenum].Entities.Count; i++)
         {
             if (@event.Scenes[scenenum].Entities[i].Model != null)
             {
                 if (@event.Scenes[scenenum].Entities[i].Model.HasWeight)
                 {
                     if (animframe == -1 || @event.Scenes[scenenum].Entities[i].Motion == null)
                     {
                         @event.Scenes[scenenum].Entities[i].Model.UpdateWeightedModel(new MatrixStack(), meshes[scenenum][i]);
                     }
                     else
                     {
                         MatrixStack m = new MatrixStack();
                         m.NJTranslate([email protected][scenenum].Entities[i].Motion.Models[0].GetPosition(animframe));
                         @event.Scenes[scenenum].Entities[i].Model.UpdateWeightedModelAnimated(m, @event.Scenes[scenenum].Entities[i].Motion, animframe, meshes[scenenum][i]);
                     }
                 }
                 else if (@event.Scenes[scenenum].Entities[i].ShapeMotion != null)
                 {
                     if (animframe == -1)
                     {
                         @event.Scenes[scenenum].Entities[i].Model.ProcessVertexData();
                     }
                     else
                     {
                         @event.Scenes[scenenum].Entities[i].Model.ProcessShapeMotionVertexData(@event.Scenes[scenenum].Entities[i].ShapeMotion, animframe);
                     }
                     NJS_OBJECT[] models = @event.Scenes[scenenum].Entities[i].Model.GetObjects();
                     for (int j = 0; j < models.Length; j++)
                     {
                         if (models[j].Attach != null)
                         {
                             try { meshes[scenenum][i][j] = models[j].Attach.CreateD3DMesh(); }
                             catch { }
                         }
                     }
                 }
             }
         }
         if (@event.Scenes[scenenum].Big?.Model != null)
         {
             if (@event.Scenes[scenenum].Big.Model.HasWeight)
             {
                 if (animframe == -1)
                 {
                     @event.Scenes[scenenum].Big.Model.UpdateWeightedModel(new MatrixStack(), bigmeshes[scenenum]);
                 }
                 else
                 {
                     int an = 0;
                     int fr = animframe;
                     while (an < @event.Scenes[scenenum].Big.Motions.Count && @event.Scenes[scenenum].Big.Motions[an].a.Frames < fr)
                     {
                         fr -= @event.Scenes[scenenum].Big.Motions[an].a.Frames;
                         an++;
                     }
                     if (an < @event.Scenes[scenenum].Big.Motions.Count)
                     {
                         @event.Scenes[scenenum].Big.Model.UpdateWeightedModelAnimated(new MatrixStack(), @event.Scenes[scenenum].Big.Motions[an].a, fr, bigmeshes[scenenum]);
                     }
                 }
             }
         }
         if (eventcamera && animframe != -1 && @event.Scenes[scenenum].CameraMotions != null)
         {
             cam.mode = 2;
             int an = 0;
             int fr = animframe;
             while (@event.Scenes[scenenum].CameraMotions[an].Frames < fr)
             {
                 fr -= @event.Scenes[scenenum].CameraMotions[an].Frames;
                 an++;
             }
             AnimModelData data = @event.Scenes[scenenum].CameraMotions[an].Models[0];
             cam.Position = data.GetPosition(fr).ToVector3();
             Vector3 dir;
             if (data.Vector.Count > 0)
             {
                 dir = data.GetVector(fr).ToVector3();
             }
             else
             {
                 dir = Vector3.Normalize(cam.Position - data.GetTarget(fr).ToVector3());
             }
             cam.Direction = dir;
             cam.Roll      = data.GetRoll(fr);
             cam.FOV       = SonicRetro.SAModel.Direct3D.Extensions.BAMSToRad(@event.Scenes[scenenum].CameraMotions[an].Models[0].GetAngle(fr));
         }
         else
         {
             cam.mode = 0;
             cam.FOV  = (float)(Math.PI / 4);
             if (animframe != -1 && @event.Scenes[scenenum].CameraMotions != null)
             {
                 int an = 0;
                 int fr = animframe;
                 while (@event.Scenes[scenenum].CameraMotions[an].Frames < fr)
                 {
                     fr -= @event.Scenes[scenenum].CameraMotions[an].Frames;
                     an++;
                 }
                 AnimModelData data = @event.Scenes[scenenum].CameraMotions[an].Models[0];
                 Vector3       pos  = data.GetPosition(fr).ToVector3();
                 Vector3       dir;
                 if (data.Vector.Count > 0)
                 {
                     dir = data.GetVector(fr).ToVector3();
                 }
                 else
                 {
                     dir = Vector3.Normalize(pos - data.GetTarget(fr).ToVector3());
                 }
                 int    roll = data.GetRoll(fr);
                 float  bams_sin = SonicRetro.SAModel.Direct3D.Extensions.NJSin(roll);
                 float  bams_cos = SonicRetro.SAModel.Direct3D.Extensions.NJCos(-roll);
                 float  thing = dir.X * dir.X + dir.Z * dir.Z;
                 double sqrt = Math.Sqrt(thing);
                 float  v3 = dir.Y * dir.Y + thing;
                 double v4 = 1.0 / Math.Sqrt(v3);
                 double sqrt__ = sqrt * v4;
                 double sqrt___ = v4 * dir.Y;
                 double v7, v8;
                 if (thing <= 0.000001)
                 {
                     v7 = 1.0;
                     v8 = 0.0;
                 }
                 else
                 {
                     double v5 = 1.0 / Math.Sqrt(thing);
                     double v6 = v5;
                     v7 = v5 * dir.Z;
                     v8 = -(v6 * dir.X);
                 }
                 double v9 = sqrt___ * v8;
                 cammatrix.M14 = 0;
                 cammatrix.M23 = (float)sqrt___;
                 cammatrix.M24 = 0;
                 cammatrix.M34 = 0;
                 cammatrix.M11 = (float)(v7 * bams_cos - v9 * bams_sin);
                 cammatrix.M12 = (float)(v9 * bams_cos + v7 * bams_sin);
                 cammatrix.M13 = -(float)(sqrt__ * v8);
                 cammatrix.M21 = -(float)(sqrt__ * bams_sin);
                 cammatrix.M22 = (float)(sqrt__ * bams_cos);
                 double v10 = v7 * sqrt___;
                 cammatrix.M31 = (float)(bams_sin * v10 + v8 * bams_cos);
                 cammatrix.M32 = (float)(v8 * bams_sin - v10 * bams_cos);
                 cammatrix.M33 = (float)(v7 * sqrt__);
                 cammatrix.M41 = -(cammatrix.M31 * pos.Z) - cammatrix.M11 * pos.X - cammatrix.M21 * pos.Y;
                 cammatrix.M42 = -(cammatrix.M32 * pos.Z) - cammatrix.M12 * pos.X - cammatrix.M22 * pos.Y;
                 float  v12 = -(cammatrix.M33 * pos.Z) - cammatrix.M13 * pos.X;
                 double v13 = sqrt___ * pos.Y;
                 cammatrix.M44 = 1;
                 cammatrix.M43 = (float)(v12 - v13);
                 cammatrix.Invert();
             }
         }
     }
 }
Example #5
0
        static void Main(string[] args)
        {
            string path;

            if (args.Length > 0)
            {
                path = args[0];
            }
            else
            {
                Console.Write("Path: ");
                path = Console.ReadLine().Trim('"');
            }
            path = Path.GetFullPath(path);
            if (path.EndsWith(".ini"))
            {
                path = Path.GetDirectoryName(path);
            }
            string  mtnfn = new DirectoryInfo(path).Name;
            MTNInfo info  = IniSerializer.Deserialize <MTNInfo>(Path.Combine(path, mtnfn + ".ini"));
            string  fext  = null;

            switch (info.ModelFormat)
            {
            case ModelFormat.Basic:
            case ModelFormat.BasicDX:
                fext = "*.sa1mdl";
                break;

            case ModelFormat.Chunk:
                fext = "*.sa2mdl";
                break;

            case ModelFormat.GC:
                fext = "*.sa2bmdl";
                break;
            }
            SortedDictionary <int, NJS_OBJECT> mdls = new SortedDictionary <int, NJS_OBJECT>();

            foreach (string fn in Directory.EnumerateFiles(path, fext))
            {
                if (int.TryParse(Path.GetFileNameWithoutExtension(fn), out int i) && i >= 0 && i < info.Frames)
                {
                    mdls[i] = new ModelFile(fn).Model;
                }
            }
            NJS_OBJECT first   = mdls.First().Value;
            int        nodecnt = first.CountMorph();

            int[]        vcnt  = new int[nodecnt];
            ushort[][]   polys = new ushort[nodecnt][];
            NJS_OBJECT[] nodes = first.GetObjects().Where(a => a.Morph).ToArray();
            for (int i = 0; i < nodecnt; i++)
            {
                switch (nodes[i].Attach)
                {
                case BasicAttach batt:
                    vcnt[i] = batt.Vertex.Length;
                    List <ushort> plist = new List <ushort>();
                    foreach (NJS_MESHSET mesh in batt.Mesh)
                    {
                        foreach (Poly p in mesh.Poly)
                        {
                            plist.AddRange(p.Indexes);
                        }
                    }
                    polys[i] = plist.ToArray();
                    break;

                case ChunkAttach catt:
                    if (catt.Vertex != null)
                    {
                        vcnt[i] = catt.Vertex.Sum(a => a.VertexCount);
                    }
                    plist = new List <ushort>();
                    foreach (PolyChunkStrip pcs in catt.Poly.OfType <PolyChunkStrip>())
                    {
                        foreach (PolyChunkStrip.Strip s in pcs.Strips)
                        {
                            plist.AddRange(s.Indexes);
                        }
                    }
                    polys[i] = plist.ToArray();
                    break;
                }
            }
            NJS_MOTION mtn = new NJS_MOTION()
            {
                Name = info.Name, Frames = info.Frames, InterpolationMode = info.InterpolationMode, ModelParts = nodecnt
            };

            foreach ((int frame, NJS_OBJECT mdl) in mdls)
            {
                NJS_OBJECT[] nodes2 = mdl.GetObjects().Where(a => a.Morph).ToArray();
                if (nodes2.Length != nodecnt)
                {
                    Console.WriteLine("Warning: Model {0} skeleton does not match first file!", frame);
                    if (nodes2.Length > mtn.ModelParts)
                    {
                        mtn.ModelParts = nodes2.Length;
                    }
                }
                for (int i = 0; i < nodes2.Length; i++)
                {
                    switch (nodes2[i].Attach)
                    {
                    case BasicAttach batt:
                        if (batt.Vertex.Length != vcnt[i])
                        {
                            Console.WriteLine("Warning: Model {0} node {1} vertex count does not match first file!", frame, i);
                        }
                        AnimModelData amd;
                        if (!mtn.Models.TryGetValue(i, out amd))
                        {
                            amd = new AnimModelData()
                            {
                                VertexName = mtn.MdataName + "_vtx_" + i, NormalName = mtn.MdataName + "_nor_" + i
                            };
                            mtn.Models[i] = amd;
                        }
                        amd.Vertex[frame] = batt.Vertex;
                        if (batt.Normal != null)
                        {
                            amd.Normal[frame] = batt.Normal;
                        }
                        List <ushort> plist = new List <ushort>();
                        foreach (NJS_MESHSET mesh in batt.Mesh)
                        {
                            foreach (Poly p in mesh.Poly)
                            {
                                plist.AddRange(p.Indexes);
                            }
                        }
                        if (!polys[i].SequenceEqual(plist))
                        {
                            Console.WriteLine("Warning: Model {0} node {1} poly data does not match first file!", frame, i);
                        }
                        break;

                    case ChunkAttach catt:
                        if (catt.Vertex != null)
                        {
                            if (catt.Vertex.Sum(a => a.VertexCount) != vcnt[i])
                            {
                                Console.WriteLine("Warning: Model {0} node {1} vertex count does not match first file!", frame, i);
                            }
                            if (!mtn.Models.TryGetValue(i, out amd))
                            {
                                amd = new AnimModelData()
                                {
                                    VertexName = mtn.MdataName + "_vtx_" + i, NormalName = mtn.MdataName + "_nor_" + i
                                };
                                mtn.Models[i] = amd;
                            }
                            amd.Vertex[frame] = catt.Vertex.SelectMany(a => a.Vertices).ToArray();
                            if (catt.Vertex.All(a => a.Normals != null))
                            {
                                amd.Normal[frame] = catt.Vertex.SelectMany(a => a.Normals).ToArray();
                            }
                        }
                        plist = new List <ushort>();
                        foreach (PolyChunkStrip pcs in catt.Poly.OfType <PolyChunkStrip>())
                        {
                            foreach (PolyChunkStrip.Strip s in pcs.Strips)
                            {
                                plist.AddRange(s.Indexes);
                            }
                        }
                        polys[i] = plist.ToArray();
                        break;
                    }
                }
            }
            foreach ((int _, AnimModelData amd) in mtn.Models)
            {
                amd.VertexItemName = Enumerable.Range(0, amd.Vertex.Count).Select(a => amd.VertexName + "_" + a).ToArray();
                if (amd.Normal.Count > 0)
                {
                    amd.NormalItemName = Enumerable.Range(0, amd.Normal.Count).Select(a => amd.NormalName + "_" + a).ToArray();
                }
            }
            mtn.Save(Path.Combine(path, $"{mtnfn}.saanim"));
        }
Example #6
0
        public override void ProcessShapeMotionVertexData(NJS_MOTION motion, float frame, int animindex)
        {
            if (!motion.Models.ContainsKey(animindex))
            {
                ProcessVertexData();
                return;
            }
            Vertex[]      vertdata = Vertex;
            Vertex[]      normdata = Normal;
            AnimModelData data     = motion.Models[animindex];

            if (data.Vertex.Count > 0)
            {
                vertdata = data.GetVertex(frame);
            }
            if (data.Normal.Count > 0)
            {
                normdata = data.GetNormal(frame);
            }
            List <MeshInfo> result = new List <MeshInfo>();

            foreach (NJS_MESHSET mesh in Mesh)
            {
                bool              hasVColor = mesh.VColor != null;
                bool              hasUV     = mesh.UV != null;
                List <Poly>       polys     = new List <Poly>();
                List <VertexData> verts     = new List <VertexData>();
                int currentstriptotal       = 0;
                foreach (Poly poly in mesh.Poly)
                {
                    Poly newpoly = null;
                    switch (mesh.PolyType)
                    {
                    case Basic_PolyType.Triangles:
                        newpoly = new Triangle();
                        break;

                    case Basic_PolyType.Quads:
                        newpoly = new Quad();
                        break;

                    case Basic_PolyType.NPoly:
                    case Basic_PolyType.Strips:
                        newpoly = new Strip(poly.Indexes.Length, ((Strip)poly).Reversed);
                        break;
                    }
                    for (int i = 0; i < poly.Indexes.Length; i++)
                    {
                        newpoly.Indexes[i] = (ushort)verts.Count;
                        verts.Add(new VertexData(
                                      vertdata[poly.Indexes[i]],
                                      normdata[poly.Indexes[i]],
                                      hasVColor ? (Color?)mesh.VColor[currentstriptotal] : null,
                                      hasUV ? mesh.UV[currentstriptotal++] : null));
                    }
                    polys.Add(newpoly);
                }
                NJS_MATERIAL mat = null;
                if (Material != null && mesh.MaterialID < Material.Count)
                {
                    mat = Material[mesh.MaterialID];
                }
                result.Add(new MeshInfo(mat, polys.ToArray(), verts.ToArray(), hasUV, hasVColor));
            }
            MeshInfo = result.ToArray();
        }