コード例 #1
0
ファイル: MeshExData.cs プロジェクト: ctrget/MikuMikuLibrary
        internal override void ReadBody(EndianBinaryReader reader)
        {
            long nameOffset         = reader.ReadOffset();
            int  count              = reader.ReadInt32();
            long boneIDsOffset      = reader.ReadOffset();
            long boneMatricesOffset = reader.ReadOffset();

            BoneIDs.Capacity = BoneMatrices.Capacity = count;

            Name = reader.ReadStringAtOffset(nameOffset, StringBinaryFormat.NullTerminated);

            reader.ReadAtOffset(boneIDsOffset, () =>
            {
                for (int i = 0; i < count; i++)
                {
                    BoneIDs.Add(reader.ReadInt32());
                }
            });

            reader.ReadAtOffset(boneMatricesOffset, () =>
            {
                for (int i = 0; i < count; i++)
                {
                    BoneMatrices.Add(reader.ReadMatrix4x4());
                }
            });
        }
コード例 #2
0
 public void XfbinClose(int xfbinNo)
 {
     BoneIDs.Clear();
     BoneNames.Clear();
     bones1Label.Text = "No bones loaded";
     if (xfbinNo == 1)
     {
         mesh1Box.Items.Clear();
         xfbin1Box.Text        = "";
         mesh1IndexLabel.Text  = "";
         group1Label.Text      = "";
         groups1Label.Text     = "";
         mat1Label.Text        = "";
         formatByte1Label.Text = "";
         meshCount1            = 0;
         if (xfbin1Open)
         {
             file1Bytes.Clear();
             meshList1.Clear();
             xfbin1Groups.Clear();
             groupsBox.Items.Clear();
         }
         xfbin1Open = false;
     }
     else if (xfbinNo == 2)
     {
         mesh2Box.Items.Clear();
         xfbin2Box.Text        = "";
         mesh2IndexLabel.Text  = "";
         group2Label.Text      = "";
         groups2Label.Text     = "";
         mat2Label.Text        = "";
         formatByte2Label.Text = "";
         meshCount2            = 0;
         if (xfbin2Open)
         {
             file2Bytes.Clear();
             meshList2.Clear();
             xfbin2Groups.Clear();
         }
         xfbin2Open = false;
         nudOpen    = false;
     }
 }
コード例 #3
0
        public static bool XfbinOpen(int xfbinNo, string xfbinPath)
        {
            byte[]        fileBytes = File.ReadAllBytes(xfbinPath);
            List <NUD>    meshList  = new List <NUD>();
            List <string> Lines     = new List <string>();
            int           meshCount = 0;

            searchResults = SearchForByte("NDP3", fileBytes, 0, fileBytes.Length, 0);
            if (!searchResults.Any())
            {
                MessageBox.Show($"Xfbin doesn't contain any meshes. Please select a valid xfbin.", $"Error");
                return(false);
            }

            // Find the group names + arrange them
            if (SearchForByte("trall", fileBytes, 0, fileBytes.Length, 1).Any())
            {
                int    end       = SearchForByte("trall", fileBytes, 0, fileBytes.Length, 1)[0];
                string modelName = "";
                int    t         = 0x20;
                int    boneStart = 0;
                while (t <= 0x20 && t > 0)
                {
                    modelName = Encoding.Default.GetString(fileBytes, end - t, 0x20);
                    modelName = modelName.Remove(modelName.IndexOf("\0"));
                    if (modelName.Contains("trall"))
                    {
                        for (int n = 0; n <= 0x20; n++)
                        {
                            if (fileBytes[end - t - n] == 0x00)
                            {
                                boneStart = end - t - n + 1;
                                modelName = Encoding.Default.GetString(fileBytes, boneStart, 0x20);
                                modelName = modelName.Remove(modelName.IndexOf("t0 trall")) + "bod1"; // xchr01bod1
                                n         = 0x21;
                            }
                        }
                        t = 0x21;
                    }
                    else
                    {
                        t -= 0x08;
                    }
                }
                int  groupStart = 0;
                int  x          = 0;
                bool isStorm    = false;
                for (int n = 0; n >= 0; n++)
                {
                    try
                    {
                        groupStart = SearchForByte(modelName, fileBytes, boneStart - x, 0, 1)[0];
                    }
                    catch
                    {
                        isStorm    = true;
                        modelName  = modelName.Remove(4, 2); // hack for nsuns models, ex: xchrbod1
                        groupStart = SearchForByte(modelName, fileBytes, boneStart - x, 0, 1)[0];
                    }
                    x = boneStart - groupStart + 1;
                    if (fileBytes[groupStart + modelName.Length] == 0)
                    {
                        n = -2;
                    }
                }
                byte[] groupNames = new byte[boneStart - groupStart];
                Array.Copy(fileBytes, groupStart, groupNames, 0, boneStart - groupStart);
                for (int o = 0; o < groupNames.Length; o++)
                {
                    if (groupNames[o] == 0x00)
                    {
                        groupNames[o] = 0x0A;
                    }
                }
                string tx = Encoding.ASCII.GetString(groupNames);
                Lines = tx.Split('\n').ToList();
                Lines.RemoveAt(0);
                Lines.RemoveAt(Lines.Count - 1);
                foreach (string s in Lines.ToList())
                {
                    if (s.Contains(" "))
                    {
                        Lines.Remove(s);
                    }
                    else
                    {
                        if (isStorm)
                        {
                            Lines[Lines.IndexOf(s)] = s.Remove(0, modelName.Length - 4);
                        }
                        else
                        {
                            Lines[Lines.IndexOf(s)] = s.Remove(0, modelName.Length + 1);
                        }
                    }
                }
            }

            // Read each mesh in the xfbin
            for (int i = 0; i < searchResults.Count; i++)
            {
                meshList.Add(LoadNud(fileBytes, searchResults[i], true));
                meshCount++;
            }

            // Set each group name to its byte
            List <Group> groupBytes = new List <Group>();

            foreach (NUD mesh in meshList)
            {
                for (int a = 0; a < mesh.GroupCount; a++)
                {
                    if (!groupBytes.Any(g => g.EndByte == mesh.GroupBytes[a].EndByte))
                    {
                        groupBytes.Add(mesh.GroupBytes[a]);
                    }
                }
            }
            if (Lines.Any())
            {
                try
                {
                    foreach (Group g in groupBytes)
                    {
                        g.Name = Lines[groupBytes.IndexOf(g)];
                    }
                }
                catch { }
            }
            List <int> BoneIDs3 = BoneIDs;

            // Set the bone names obtained from the animation file
            if (BoneNames.Any())
            {
                List <string> names = new List <string>();
                for (int b = 0; b < BoneIDs.Last(); b++)
                {
                    names.Add(BoneNames[b]);
                }
                BoneNames = names;
            }

            // Dynamically set the properties for each xfbin
            if (xfbinNo == 1)
            {
                xfbin1Open   = true;
                xfbin1Path   = xfbinPath;
                file1Bytes   = fileBytes.ToList();
                meshCount1   = meshCount;
                meshList1    = meshList;
                xfbin1Groups = groupBytes;
            }
            else if (xfbinNo == 2)
            {
                xfbin2Open   = true;
                xfbin2Path   = xfbinPath;
                file2Bytes   = fileBytes.ToList();
                meshCount2   = meshCount;
                meshList2    = meshList;
                xfbin2Groups = groupBytes;
            }
            return(true);
        }
コード例 #4
0
        public static NUD LoadNud(byte[] fileBytes, int index, bool header)
        {
            int x          = index;
            int headerSize = 0;
            int fileStart  = index;
            int fileSize;
            int meshIndex  = 0;
            int ndp3Size   = fileBytes[x + 0x05] * 0x10000 + fileBytes[x + 0x06] * 0x100 + fileBytes[x + 0x07];
            int sec1Index  = x + 0x30;
            int groupCount = fileBytes[sec1Index + 0x2B];
            int vertCount  = 0;

            byte[]         nudFile;
            List <Group>   groupBytes = new List <Group>();
            List <Polygon> poly       = new List <Polygon>();

            if (header)
            {
                if (fileBytes[x - 4] != 0x00)
                {
                    headerSize = 0x40;
                    fileStart  = x - headerSize;
                }
                else
                {
                    headerSize = 0x28;
                    fileStart  = x - headerSize;
                }

                fileSize = headerSize + ndp3Size + 0x02 + (groupCount * 0x04);
                nudFile  = new byte[fileSize];
                Array.Copy(fileBytes, fileStart, nudFile, 0, fileSize);
                x         = headerSize;
                sec1Index = x + 0x30;
                meshIndex = nudFile[0x07];
            }
            else
            {
                fileSize = ndp3Size + 0x02;
                nudFile  = fileBytes;
            }
            for (int a = 0; a < groupCount; a++)
            {
                int    matIndexp = x + BigBitConverter.ToInt16(nudFile, sec1Index + 0x42 + (a * 0x30));
                string matNamep  = BitConverter.ToString(nudFile, matIndexp + 1, 3).Replace('-', ' ');
                if (matNamep[1] == '0')
                {
                    matNamep = matNamep.TrimStart('0', '0', ' ');
                }
                poly.Add(new Polygon
                {
                    VertCount  = BigBitConverter.ToInt16(nudFile, sec1Index + 0x3C + (a * 0x30)),
                    FormatByte = nudFile[sec1Index + 0x3E + (a * 0x30)],
                    MatName    = matNamep,
                    EndByte    = 0
                });
                vertCount += poly[a].VertCount;
                if (header)
                {
                    poly[a].EndByte = nudFile[(x - 1) + ndp3Size + 0x06 + (a * 4)];
                    groupBytes.Add(new Group
                    {
                        EndByte = poly[a].EndByte,
                        Name    = ""
                    });
                }
            }

            int  sec1Size    = BigBitConverter.ToInt32(nudFile, x + 0x10);
            int  triSize     = BigBitConverter.ToInt32(nudFile, x + 0x14);
            int  triIndex    = sec1Index + sec1Size;
            int  uvSize      = BigBitConverter.ToInt32(nudFile, x + 0x18);
            int  uvIndex     = triIndex + triSize;
            int  vertSize    = BigBitConverter.ToInt32(nudFile, x + 0x1C);
            int  vertIndex   = uvIndex + uvSize;
            int  vertFormat  = nudFile[sec1Index + 0x27]; // either 0x14 or 0x00, for stating if there are vertices or not
            int  matIndex    = x + BigBitConverter.ToInt16(nudFile, sec1Index + 0x42);
            bool mirrorState = false;
            int  mirrorByte  = BigBitConverter.ToInt16(nudFile, matIndex + 0x12); // mirrorState = CullMode

            if (mirrorByte == 0x00)
            {
                mirrorState = true;                     // true for ASB models with no bod1_f, else false
            }
            string matName = BitConverter.ToString(nudFile, matIndex + 1, 3).Replace('-', ' ');

            if (matName[1] == '0')
            {
                matName = matName.TrimStart('0', '0', ' ');
            }
            string meshName = Encoding.Default.GetString(nudFile.ToArray(), vertIndex + vertSize, 0x20);

            meshName = meshName.Remove(meshName.IndexOf("\0"));

            // Credit goes to the Smash Forge team for mesh formats
            string meshFormatName = "";

            foreach (Polygon p in poly)
            {
                switch (p.FormatByte)
                {
                case 0x06:     // Storm teeth/eyes
                    // NormalsHalfFloat
                    p.MeshFormat = 0x1C;
                    break;

                case 0x20:     // Storm effects (not ready)
                    p.MeshFormat = 0x20;
                    break;

                case 0x07:     // JoJo teeth
                    // NormalsTanBiTanHalfFloat
                    p.MeshFormat = 0x2C;
                    break;

                case 0x30:     // JoJo teeth (not ready)
                    p.MeshFormat = 0x30;
                    break;

                case 0x11:     // Storm most meshes + JoJo eyes
                    // NormalsFloat
                    p.MeshFormat = 0x40;
                    p.BoneOffset = 0x20;
                    break;

                case 0x13:     // JoJo most meshes
                    // NormalsTanBiTanFloat
                    p.MeshFormat = 0x60;
                    p.BoneOffset = 0x40;
                    break;

                default:
                    if (vertSize == 0)
                    {
                        p.MeshFormat = uvSize / vertCount;
                    }
                    else
                    {
                        p.MeshFormat = vertSize / vertCount;
                    }
                    break;
                }
                // Only last format for now
                meshFormatName = "0x" + BitConverter.ToString(BitConverter.GetBytes(p.MeshFormat)).Substring(0, 2);
            }

            int vertSum            = 0;
            int maxBone            = 0;
            List <BoneBytes> bones = new List <BoneBytes>();

            for (int a = 0; a < poly.Count; a++)
            {
                if (poly[a].BoneOffset != 0)
                {
                    for (int i = 0; i < poly[a].VertCount; i++)
                    {
                        BoneBytes bytes = new BoneBytes()
                        {
                            Id1 = nudFile[vertIndex + vertSum + poly[a].BoneOffset + 0x03 + (i * poly[a].MeshFormat)],
                            Id2 = nudFile[vertIndex + vertSum + poly[a].BoneOffset + 0x07 + (i * poly[a].MeshFormat)],
                            Id3 = nudFile[vertIndex + vertSum + poly[a].BoneOffset + 0x0B + (i * poly[a].MeshFormat)]
                        };
                        int IdMax1 = Math.Max(bytes.Id1, bytes.Id2);
                        int IdMax2 = Math.Max(bytes.Id3, IdMax1);
                        if (IdMax2 > maxBone)
                        {
                            maxBone = IdMax2;
                        }
                        if (!BoneIDs.Contains(bytes.Id1))
                        {
                            BoneIDs.Add(bytes.Id1);
                        }
                        if (!BoneIDs.Contains(bytes.Id2))
                        {
                            BoneIDs.Add(bytes.Id2);
                        }
                        if (!BoneIDs.Contains(bytes.Id3))
                        {
                            BoneIDs.Add(bytes.Id3);
                        }
                        bones.Add(bytes);
                    }
                    vertSum += poly[a].VertCount * poly[a].MeshFormat;
                }
            }
            BoneIDs = BoneIDs.OrderBy(l => l).ToList();

            return(new NUD
            {
                MeshName = meshName,
                MeshFormat = meshFormatName,
                NudIndex = fileStart + headerSize,
                FileStart = fileStart,
                HeaderSize = headerSize,
                FileSize = fileSize,
                NDP3Size = ndp3Size,
                MeshIndex = meshIndex,
                TriIndex = triIndex,
                TriSize = triSize,
                UVIndex = uvIndex,
                UVSize = uvSize,
                VertIndex = vertIndex,
                VertSize = vertSize,
                VertFormat = vertFormat,
                GroupCount = groupCount,
                Material = matName,
                Mirror = mirrorState,
                NudFile = nudFile.ToList(),
                GroupBytes = groupBytes,
                Bones = bones,
                MaxBone = maxBone,
                Polygons = poly
            });
        }