예제 #1
0
        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 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
            });
        }