public SDATInfo(NitroFile sdat, uint offset)
            {
                m_Offset       = offset;
                m_Type         = sdat.ReadString(m_Offset + 0x00, 4).ToCharArray();
                m_Size         = sdat.Read32(m_Offset + 0x04);
                m_RecordOffset = new uint[8];
                for (int i = 0; i < 8; i++)
                {
                    m_RecordOffset[i] = sdat.Read32(m_Offset + 0x08 + (uint)(i * 4));
                }
                m_Reserved = sdat.ReadBlock(m_Offset + 0x28, 24);

                m_Records = new SDATInfoRecord[8];
                for (int i = 0; i < 8; i++)
                {
                    m_Records[i] = new SDATInfoRecord(sdat, m_Offset + m_RecordOffset[i]);
                }
                m_Records0SEQ = new SDATInfoSEQ[m_Records[0].m_Count];
                for (int i = 0; i < m_Records[0].m_Count; i++)
                {
                    m_Records0SEQ[i] = new SDATInfoSEQ(sdat, m_Offset + m_Records[0].m_EntryOffset[i]);
                }
                m_Records1SEQARC = new SDATInfoSEQARC[m_Records[1].m_Count];
                for (int i = 0; i < m_Records[1].m_Count; i++)
                {
                    m_Records1SEQARC[i] = new SDATInfoSEQARC(sdat, m_Offset + m_Records[1].m_EntryOffset[i]);
                }
                m_Records2BANK = new SDATInfoBANK[m_Records[2].m_Count];
                for (int i = 0; i < m_Records[2].m_Count; i++)
                {
                    m_Records2BANK[i] = new SDATInfoBANK(sdat, m_Offset + m_Records[2].m_EntryOffset[i]);
                }
                m_Records3WAVEARC = new SDATInfoWAVEARC[m_Records[3].m_Count];
                for (int i = 0; i < m_Records[3].m_Count; i++)
                {
                    m_Records3WAVEARC[i] = new SDATInfoWAVEARC(sdat, m_Offset + m_Records[3].m_EntryOffset[i]);
                }
                m_Records4PLAYER = new SDATInfoPLAYER[m_Records[4].m_Count];
                for (int i = 0; i < m_Records[4].m_Count; i++)
                {
                    m_Records4PLAYER[i] = new SDATInfoPLAYER(sdat, m_Offset + m_Records[4].m_EntryOffset[i]);
                }
                m_Records5GROUP = new SDATInfoGROUP[m_Records[5].m_Count];
                for (int i = 0; i < m_Records[5].m_Count; i++)
                {
                    m_Records5GROUP[i] = new SDATInfoGROUP(sdat, m_Offset + m_Records[5].m_EntryOffset[i]);
                }
                m_Records6PLAYER2 = new SDATInfoPLAYER2[m_Records[6].m_Count];
                for (int i = 0; i < m_Records[6].m_Count; i++)
                {
                    m_Records6PLAYER2[i] = new SDATInfoPLAYER2(sdat, m_Offset + m_Records[6].m_EntryOffset[i]);
                }
                m_Records7STREAM = new SDATInfoSTREAM[m_Records[7].m_Count];
                for (int i = 0; i < m_Records[7].m_Count; i++)
                {
                    m_Records7STREAM[i] = new SDATInfoSTREAM(sdat, m_Offset + m_Records[7].m_EntryOffset[i]);
                }
            }
Exemple #2
0
        public BMD(NitroFile file)
        {
            m_File     = file;
            m_FileName = file.m_Name;

            /* if (m_File.m_ID == 741)
             *   lolol = true;
             * else*/
            lolol = false;

            // Keep a list of pointers so it's easier to add/remove entries, space etc.
            m_PointerList = new List <PointerReference>();

            m_ScaleFactor = (float)(1 << (int)m_File.Read32(0x0));

            // ModelChunk refers to Bone
            m_NumModelChunks    = m_File.Read32(0x04);
            m_ModelChunksOffset = m_File.Read32(0x08);
            AddPointer(0x08);
            for (int i = 0; i < m_NumModelChunks; i++)
            {
                AddPointer((uint)(m_ModelChunksOffset + (i * 64) + 0x04));
                AddPointer((uint)(m_ModelChunksOffset + (i * 64) + 0x34));
                AddPointer((uint)(m_ModelChunksOffset + (i * 64) + 0x38));
            }

            // PolyChunk refers to Display List
            m_NumPolyChunks    = m_File.Read32(0x0C);
            m_PolyChunksOffset = m_File.Read32(0x10);
            AddPointer(0x10);
            for (int i = 0; i < m_NumPolyChunks; i++)
            {
                // Offset to Display List within Display List entries
                AddPointer((uint)(m_PolyChunksOffset + (i * 8) + 4));
                // Offsets within the Display List 16 byte headers
                AddPointer(m_File.Read32((uint)(m_PolyChunksOffset + (i * 8) + 4)) + 0x04);
                AddPointer(m_File.Read32((uint)(m_PolyChunksOffset + (i * 8) + 4)) + 0x0C);
            }
            m_NumTexChunks    = m_File.Read32(0x14);
            m_TexChunksOffset = m_File.Read32(0x18);
            m_TextureIDs      = new Dictionary <string, uint>();
            AddPointer(0x18);
            for (int i = 0; i < m_NumTexChunks; i++)
            {
                AddPointer((uint)(m_TexChunksOffset + (i * 20) + 0));
                AddPointer((uint)(m_TexChunksOffset + (i * 20) + 4));
                m_TextureIDs.Add(m_File.ReadString(m_File.Read32((uint)(m_TexChunksOffset + (20 * i))), 0), (uint)i);
            }
            m_NumPalChunks    = m_File.Read32(0x1C);
            m_PalChunksOffset = m_File.Read32(0x20);
            m_PaletteIDs      = new Dictionary <string, uint>();
            AddPointer(0x20);
            for (int i = 0; i < m_NumPalChunks; i++)
            {
                AddPointer((uint)(m_PalChunksOffset + (i * 16) + 0));
                AddPointer((uint)(m_PalChunksOffset + (i * 16) + 4));
                m_PaletteIDs.Add(m_File.ReadString(m_File.Read32((uint)(m_PalChunksOffset + (16 * i))), 0), (uint)i);
            }
            m_NumMatChunks    = m_File.Read32(0x24);
            m_MatChunksOffset = m_File.Read32(0x28);
            AddPointer(0x28);
            for (int i = 0; i < m_NumMatChunks; i++)
            {
                AddPointer((uint)(m_MatChunksOffset + (i * 48) + 0));
            }
            m_BoneMapOffset = m_File.Read32(0x2C);
            AddPointer(0x2C);

            m_Textures    = new Dictionary <string, NitroTexture>();
            m_ModelChunks = new ModelChunk[m_NumModelChunks];

            for (uint c = 0; c < m_NumModelChunks; c++)
            {
                ModelChunk mdchunk = new ModelChunk(this);
                m_ModelChunks[c] = mdchunk;

                uint mdchunkoffset = m_ModelChunksOffset + (c * 64);

                mdchunk.m_ID   = m_File.Read32(mdchunkoffset);
                mdchunk.m_Name = m_File.ReadString(m_File.Read32(mdchunkoffset + 0x04), 0);

                // transforms part
                {
                    int   xscale = (int)m_File.Read32(mdchunkoffset + 0x10);
                    int   yscale = (int)m_File.Read32(mdchunkoffset + 0x14);
                    int   zscale = (int)m_File.Read32(mdchunkoffset + 0x18);
                    short xrot   = (short)m_File.Read16(mdchunkoffset + 0x1C);
                    short yrot   = (short)m_File.Read16(mdchunkoffset + 0x1E);
                    short zrot   = (short)m_File.Read16(mdchunkoffset + 0x20);
                    int   xtrans = (int)m_File.Read32(mdchunkoffset + 0x24);
                    int   ytrans = (int)m_File.Read32(mdchunkoffset + 0x28);
                    int   ztrans = (int)m_File.Read32(mdchunkoffset + 0x2C);

                    mdchunk.m_Scale       = new Vector3((float)xscale / 4096.0f, (float)yscale / 4096.0f, (float)zscale / 4096.0f);
                    mdchunk.m_Rotation    = new Vector3(((float)xrot * (float)Math.PI) / 2048.0f, ((float)yrot * (float)Math.PI) / 2048.0f, ((float)zrot * (float)Math.PI) / 2048.0f);
                    mdchunk.m_Translation = new Vector3((float)xtrans / 4096.0f, (float)ytrans / 4096.0f, (float)ztrans / 4096.0f);
                    mdchunk.m_Transform   = Helper.SRTToMatrix(mdchunk.m_Scale, mdchunk.m_Rotation, mdchunk.m_Translation);

                    // Used when exporting bones
                    mdchunk.m_20_12Scale       = new uint[] { (uint)xscale, (uint)yscale, (uint)zscale };
                    mdchunk.m_4_12Rotation     = new ushort[] { (ushort)xrot, (ushort)yrot, (ushort)zrot };
                    mdchunk.m_20_12Translation = new uint[] { (uint)xtrans, (uint)ytrans, (uint)ztrans };

                    // if the chunk has a parent, apply the parent's transform to the chunk's transform.
                    // we don't need to go further than one level because the paren't transform already
                    // went through its parents' transforms.
                    short parent_offset = (short)m_File.Read16(mdchunkoffset + 0x8);
                    if (parent_offset < 0)
                    {
                        int parentchunkid = (int)(c + parent_offset);
                        Matrix4.Mult(ref mdchunk.m_Transform, ref m_ModelChunks[parentchunkid].m_Transform, out mdchunk.m_Transform);
                    }
                    mdchunk.m_ParentOffset = parent_offset;
                }
                // If 0x0A is set to 1 the bone has children, if 0 it doesn't
                mdchunk.m_HasChildren = (m_File.Read16(mdchunkoffset + 0x0A) == 1);

                mdchunk.m_SiblingOffset = (short)(m_File.Read16(mdchunkoffset + 0x0C));

                uint flags = m_File.Read32(mdchunkoffset + 0x3C);
                mdchunk.m_Billboard = ((flags & 0x1) == 0x1);

                uint numpairs = m_File.Read32(mdchunkoffset + 0x30);
                uint matlist  = m_File.Read32(mdchunkoffset + 0x34);
                uint polylist = m_File.Read32(mdchunkoffset + 0x38);

                mdchunk.m_MatGroups = new MaterialGroup[numpairs];

                for (uint i = 0; i < numpairs; i++)
                {
                    MaterialGroup matgroup = new MaterialGroup();
                    mdchunk.m_MatGroups[i] = matgroup;

                    byte matID  = m_File.Read8(matlist + i);
                    byte polyID = m_File.Read8(polylist + i);

                    uint mchunkoffset = (uint)(m_MatChunksOffset + (matID * 48));

                    matgroup.m_ID   = matID;
                    matgroup.m_Name = m_File.ReadString(m_File.Read32(mchunkoffset), 0);
                    uint texid = m_File.Read32(mchunkoffset + 0x04);
                    uint palid = m_File.Read32(mchunkoffset + 0x08);
                    matgroup.m_TexParams    = m_File.Read32(mchunkoffset + 0x20);
                    matgroup.m_PolyAttribs  = m_File.Read32(mchunkoffset + 0x24);
                    matgroup.m_DifAmbColors = m_File.Read32(mchunkoffset + 0x28);
                    matgroup.m_SpeEmiColors = m_File.Read32(mchunkoffset + 0x2C);

                    if ((matgroup.m_PolyAttribs & 0x30) == 0x10)
                    {
                        matgroup.m_TexEnvMode = TextureEnvMode.Decal;
                    }
                    else
                    {
                        matgroup.m_TexEnvMode = TextureEnvMode.Modulate;
                    }

                    switch (matgroup.m_PolyAttribs & 0xC0)
                    {
                    case 0x00: matgroup.m_CullMode = CullFaceMode.FrontAndBack; break;

                    case 0x40: matgroup.m_CullMode = CullFaceMode.Front; break;

                    case 0x80: matgroup.m_CullMode = CullFaceMode.Back; break;
                    }

                    matgroup.m_DiffuseColor  = Helper.BGR15ToColor((ushort)matgroup.m_DifAmbColors);
                    matgroup.m_AmbientColor  = Helper.BGR15ToColor((ushort)(matgroup.m_DifAmbColors >> 16));
                    matgroup.m_SpecularColor = Helper.BGR15ToColor((ushort)matgroup.m_SpeEmiColors);
                    matgroup.m_EmissionColor = Helper.BGR15ToColor((ushort)(matgroup.m_SpeEmiColors >> 16));

                    switch (matgroup.m_TexParams >> 30)
                    {
                    case 0:
                        matgroup.m_TexCoordScale = new Vector2(1.0f, 1.0f);
                        matgroup.m_TexCoordRot   = 0.0f;
                        matgroup.m_TexCoordTrans = new Vector2(0.0f, 0.0f);
                        break;

                    case 1:
                    {
                        int   sscale = (int)m_File.Read32(mchunkoffset + 0x0C);
                        int   tscale = (int)m_File.Read32(mchunkoffset + 0x10);
                        short trot   = (short)m_File.Read16(mchunkoffset + 0x14);
                        int   strans = (int)m_File.Read32(mchunkoffset + 0x18);
                        int   ttrans = (int)m_File.Read32(mchunkoffset + 0x1C);

                        matgroup.m_TexCoordScale = new Vector2((float)sscale / 4096.0f, (float)tscale / 4096.0f);
                        matgroup.m_TexCoordRot   = ((float)trot * (float)Math.PI) / 2048.0f;
                        matgroup.m_TexCoordTrans = new Vector2((float)strans / 4096.0f, (float)ttrans / 4096.0f);
                    }
                    break;

                    case 2:
                        goto case 1;

                    case 3:
                        goto case 1;

                    default:
                        break;
                        // throw new Exception(String.Format("BMD: unsupported texture coord transform mode {0}", matgroup.m_TexParams >> 30));
                    }

                    if (texid != 0xFFFFFFFF)
                    {
                        matgroup.m_Texture    = ReadTexture(texid, palid);
                        matgroup.m_TexParams |= matgroup.m_Texture.m_DSTexParam;
                    }
                    else
                    {
                        matgroup.m_Texture = null;
                    }

                    uint pchunkoffset = m_File.Read32((uint)(m_PolyChunksOffset + (polyID * 8) + 4));
                    uint dloffset     = m_File.Read32(pchunkoffset + 0x0C);
                    uint dlsize       = m_File.Read32(pchunkoffset + 0x08);
                    uint numbones     = m_File.Read32(pchunkoffset);
                    uint bonesoffset  = m_File.Read32(pchunkoffset + 0x04);

                    matgroup.m_BoneIDs = new ushort[numbones];
                    for (uint b = 0; b < numbones; b++)
                    {
                        byte idx1 = m_File.Read8(bonesoffset + b);
                        matgroup.m_BoneIDs[b] = m_File.Read16((uint)(m_BoneMapOffset + (2 * idx1)));
                    }

                    matgroup.m_Geometry = new List <VertexList>();

                    m_CurVertex.m_Position = new Vector3(0, 0, 0);
                    m_CurVertex.m_TexCoord = null;
                    m_CurVertex.m_Normal   = null;

                    if ((matgroup.m_PolyAttribs & 0x8000) != 0x8000)
                    {
                        byte alpha = (byte)((matgroup.m_PolyAttribs >> 16) & 0x1F);
                        alpha           |= (byte)(alpha >> 5);
                        matgroup.m_Alpha = alpha;
                    }

                    if ((matgroup.m_DifAmbColors & 0x8000) == 0x8000)
                    {
                        m_CurVertex.m_Color = Color.FromArgb(matgroup.m_Alpha << 3, matgroup.m_DiffuseColor);
                    }
                    else
                    {
                        m_CurVertex.m_Color = Color.Black;
                    }

                    m_CurVertex.m_MatrixID = 0;

                    uint dlend = dloffset + dlsize;
                    for (uint pos = dloffset; pos < dlend;)
                    {
                        byte cmd1 = m_File.Read8(pos++);
                        byte cmd2 = m_File.Read8(pos++);
                        byte cmd3 = m_File.Read8(pos++);
                        byte cmd4 = m_File.Read8(pos++);

                        ProcessGXCommand(matgroup, cmd1, ref pos);
                        ProcessGXCommand(matgroup, cmd2, ref pos);
                        ProcessGXCommand(matgroup, cmd3, ref pos);
                        ProcessGXCommand(matgroup, cmd4, ref pos);
                    }
                }
            }

            foreach (ModelChunk mdchunk in m_ModelChunks)
            {
                foreach (MaterialGroup matgroup in mdchunk.m_MatGroups)
                {
                    matgroup.m_BoneMatrices = new Matrix4[matgroup.m_BoneIDs.Length];
                    for (uint b = 0; b < matgroup.m_BoneIDs.Length; b++)
                    {
                        matgroup.m_BoneMatrices[b] = m_ModelChunks[matgroup.m_BoneIDs[b]].m_Transform;
                    }
                }
            }

            int index = 0;

            foreach (KeyValuePair <string, uint> entry in m_TextureIDs)
            {
                if (!m_Textures.ContainsKey(entry.Key))
                {
                    Console.WriteLine("NOT IN TEXTURES: " + entry.Key);
                    uint palID = Math.Min(m_PaletteIDs.ElementAt(index).Value, (uint)m_PaletteIDs.Count - 1);
                    ReadTexture(entry.Value, palID);
                }
                index++;
            }
        }
Exemple #3
0
        public BMD(NitroFile file)
        {
            m_File = file;
            m_FileName = file.m_Name;

            /* if (m_File.m_ID == 741)
                 lolol = true;
             else*/
            lolol = false;

            // Keep a list of pointers so it's easier to add/remove entries, space etc.
            m_PointerList = new List<PointerReference>();

            m_ScaleFactor = (float)(1 << (int)m_File.Read32(0x0));

            // ModelChunk refers to Bone
            m_NumModelChunks = m_File.Read32(0x04);
            m_ModelChunksOffset = m_File.Read32(0x08);
            AddPointer(0x08);
            for (int i = 0; i < m_NumModelChunks; i++)
            {
                AddPointer((uint)(m_ModelChunksOffset + (i * 64) + 0x04));
                AddPointer((uint)(m_ModelChunksOffset + (i * 64) + 0x34));
                AddPointer((uint)(m_ModelChunksOffset + (i * 64) + 0x38));
            }

            // PolyChunk refers to Display List
            m_NumPolyChunks = m_File.Read32(0x0C);
            m_PolyChunksOffset = m_File.Read32(0x10);
            AddPointer(0x10);
            for (int i = 0; i < m_NumPolyChunks; i++)
            {
                // Offset to Display List within Display List entries
                AddPointer((uint)(m_PolyChunksOffset + (i * 8) + 4));
                // Offsets within the Display List 16 byte headers
                AddPointer(m_File.Read32((uint)(m_PolyChunksOffset + (i * 8) + 4)) + 0x04);
                AddPointer(m_File.Read32((uint)(m_PolyChunksOffset + (i * 8) + 4)) + 0x0C);
            }
            m_NumTexChunks = m_File.Read32(0x14);
            m_TexChunksOffset = m_File.Read32(0x18);
            m_TextureIDs = new Dictionary<string, uint>();
            AddPointer(0x18);
            for (int i = 0; i < m_NumTexChunks; i++)
            {
                AddPointer((uint)(m_TexChunksOffset + (i * 20) + 0));
                AddPointer((uint)(m_TexChunksOffset + (i * 20) + 4));
                m_TextureIDs.Add(m_File.ReadString(m_File.Read32((uint)(m_TexChunksOffset + (20 * i))), 0), (uint)i);
            }
            m_NumPalChunks = m_File.Read32(0x1C);
            m_PalChunksOffset = m_File.Read32(0x20);
            m_PaletteIDs = new Dictionary<string, uint>();
            AddPointer(0x20);
            for (int i = 0; i < m_NumPalChunks; i++)
            {
                AddPointer((uint)(m_PalChunksOffset + (i * 16) + 0));
                AddPointer((uint)(m_PalChunksOffset + (i * 16) + 4));
                m_PaletteIDs.Add(m_File.ReadString(m_File.Read32((uint)(m_PalChunksOffset + (16 * i))), 0), (uint)i);
            }
            m_NumMatChunks = m_File.Read32(0x24);
            m_MatChunksOffset = m_File.Read32(0x28);
            AddPointer(0x28);
            for (int i = 0; i < m_NumMatChunks; i++)
            {
                AddPointer((uint)(m_MatChunksOffset + (i * 48) + 0));
            }
            m_BoneMapOffset = m_File.Read32(0x2C);
            AddPointer(0x2C);

            m_Textures = new Dictionary<string, Texture>();
            m_ModelChunks = new ModelChunk[m_NumModelChunks];

            for (uint c = 0; c < m_NumModelChunks; c++)
            {
                ModelChunk mdchunk = new ModelChunk(this);
                m_ModelChunks[c] = mdchunk;

                uint mdchunkoffset = m_ModelChunksOffset + (c * 64);

                mdchunk.m_ID = m_File.Read32(mdchunkoffset);
                mdchunk.m_Name = m_File.ReadString(m_File.Read32(mdchunkoffset + 0x04), 0);

                // transforms part
                {
                    int xscale = (int)m_File.Read32(mdchunkoffset + 0x10);
                    int yscale = (int)m_File.Read32(mdchunkoffset + 0x14);
                    int zscale = (int)m_File.Read32(mdchunkoffset + 0x18);
                    short xrot = (short)m_File.Read16(mdchunkoffset + 0x1C);
                    short yrot = (short)m_File.Read16(mdchunkoffset + 0x1E);
                    short zrot = (short)m_File.Read16(mdchunkoffset + 0x20);
                    int xtrans = (int)m_File.Read32(mdchunkoffset + 0x24);
                    int ytrans = (int)m_File.Read32(mdchunkoffset + 0x28);
                    int ztrans = (int)m_File.Read32(mdchunkoffset + 0x2C);

                    mdchunk.m_Scale = new Vector3((float)xscale / 4096.0f, (float)yscale / 4096.0f, (float)zscale / 4096.0f);
                    mdchunk.m_Rotation = new Vector3(((float)xrot * (float)Math.PI) / 2048.0f, ((float)yrot * (float)Math.PI) / 2048.0f, ((float)zrot * (float)Math.PI) / 2048.0f);
                    mdchunk.m_Translation = new Vector3((float)xtrans / 4096.0f, (float)ytrans / 4096.0f, (float)ztrans / 4096.0f);
                    mdchunk.m_Transform = Helper.SRTToMatrix(mdchunk.m_Scale, mdchunk.m_Rotation, mdchunk.m_Translation);

                    // Used when exporting bones
                    mdchunk.m_20_12Scale = new uint[] { (uint)xscale, (uint)yscale, (uint)zscale };
                    mdchunk.m_4_12Rotation = new ushort[] { (ushort)xrot, (ushort)yrot, (ushort)zrot };
                    mdchunk.m_20_12Translation = new uint[] { (uint)xtrans, (uint)ytrans, (uint)ztrans };

                    // if the chunk has a parent, apply the parent's transform to the chunk's transform.
                    // we don't need to go further than one level because the paren't transform already
                    // went through its parents' transforms.
                    short parent_offset = (short)m_File.Read16(mdchunkoffset + 0x8);
                    if (parent_offset < 0)
                    {
                        int parentchunkid = (int)(c + parent_offset);
                        Matrix4.Mult(ref mdchunk.m_Transform, ref m_ModelChunks[parentchunkid].m_Transform, out mdchunk.m_Transform);
                    }
                    mdchunk.m_ParentOffset = parent_offset;
                }
                // If 0x0A is set to 1 the bone has children, if 0 it doesn't
                mdchunk.m_HasChildren = (m_File.Read16(mdchunkoffset + 0x0A) == 1);

                mdchunk.m_SiblingOffset = (short)(m_File.Read16(mdchunkoffset + 0x0C));

                uint flags = m_File.Read32(mdchunkoffset + 0x3C);
                mdchunk.m_Billboard = ((flags & 0x1) == 0x1);

                uint numpairs = m_File.Read32(mdchunkoffset + 0x30);
                uint matlist = m_File.Read32(mdchunkoffset + 0x34);
                uint polylist = m_File.Read32(mdchunkoffset + 0x38);

                mdchunk.m_MatGroups = new MaterialGroup[numpairs];

                for (uint i = 0; i < numpairs; i++)
                {
                    MaterialGroup matgroup = new MaterialGroup();
                    mdchunk.m_MatGroups[i] = matgroup;

                    byte matID = m_File.Read8(matlist + i);
                    byte polyID = m_File.Read8(polylist + i);

                    uint mchunkoffset = (uint)(m_MatChunksOffset + (matID * 48));

                    matgroup.m_ID = matID;
                    matgroup.m_Name = m_File.ReadString(m_File.Read32(mchunkoffset), 0);
                    uint texid = m_File.Read32(mchunkoffset + 0x04);
                    uint palid = m_File.Read32(mchunkoffset + 0x08);
                    matgroup.m_TexParams = m_File.Read32(mchunkoffset + 0x20);
                    matgroup.m_PolyAttribs = m_File.Read32(mchunkoffset + 0x24);
                    matgroup.m_DifAmbColors = m_File.Read32(mchunkoffset + 0x28);
                    matgroup.m_SpeEmiColors = m_File.Read32(mchunkoffset + 0x2C);

                    if ((matgroup.m_PolyAttribs & 0x30) == 0x10)
                        matgroup.m_TexEnvMode = TextureEnvMode.Decal;
                    else
                        matgroup.m_TexEnvMode = TextureEnvMode.Modulate;

                    switch (matgroup.m_PolyAttribs & 0xC0)
                    {
                        case 0x00: matgroup.m_CullMode = CullFaceMode.FrontAndBack; break;
                        case 0x40: matgroup.m_CullMode = CullFaceMode.Front; break;
                        case 0x80: matgroup.m_CullMode = CullFaceMode.Back; break;
                    }

                    matgroup.m_DiffuseColor = Helper.BGR15ToColor((ushort)matgroup.m_DifAmbColors);
                    matgroup.m_AmbientColor = Helper.BGR15ToColor((ushort)(matgroup.m_DifAmbColors >> 16));
                    matgroup.m_SpecularColor = Helper.BGR15ToColor((ushort)matgroup.m_SpeEmiColors);
                    matgroup.m_EmissionColor = Helper.BGR15ToColor((ushort)(matgroup.m_SpeEmiColors >> 16));

                    switch (matgroup.m_TexParams >> 30)
                    {
                        case 0:
                            matgroup.m_TexCoordScale = new Vector2(1.0f, 1.0f);
                            matgroup.m_TexCoordTrans = new Vector2(0.0f, 0.0f);
                            break;

                        case 1:
                            {
                                int sscale = (int)m_File.Read32(mchunkoffset + 0x0C);
                                int tscale = (int)m_File.Read32(mchunkoffset + 0x10);
                                int strans = (int)m_File.Read32(mchunkoffset + 0x18);
                                int ttrans = (int)m_File.Read32(mchunkoffset + 0x1C);

                                matgroup.m_TexCoordScale = new Vector2((float)sscale / 4096.0f, (float)tscale / 4096.0f);
                                matgroup.m_TexCoordTrans = new Vector2((float)strans / 4096.0f, (float)ttrans / 4096.0f);
                                //matgroup.m_TexCoordTrans = new Vector2(0.0f, 16.0f);
                                /*System.Windows.Forms.MessageBox.Show(String.Format("textransform: scale:{0} trans:{1} rot:{2:X8}",
                                    matgroup.m_TexCoordScale, matgroup.m_TexCoordTrans,
                                    m_File.Read32(mchunkoffset + 0x1C)));*/
                            }
                            break;

                        case 2:
                            goto case 1;

                        case 3:
                            goto case 1;

                        default:
                            break;
                        // throw new Exception(String.Format("BMD: unsupported texture coord transform mode {0}", matgroup.m_TexParams >> 30));
                    }

                    if (texid != 0xFFFFFFFF)
                    {
                        matgroup.m_Texture = ReadTexture(texid, palid);
                        matgroup.m_TexParams |= matgroup.m_Texture.m_Params;
                    }
                    else
                        matgroup.m_Texture = null;

                    uint pchunkoffset = m_File.Read32((uint)(m_PolyChunksOffset + (polyID * 8) + 4));
                    uint dloffset = m_File.Read32(pchunkoffset + 0x0C);
                    uint dlsize = m_File.Read32(pchunkoffset + 0x08);
                    uint numbones = m_File.Read32(pchunkoffset);
                    uint bonesoffset = m_File.Read32(pchunkoffset + 0x04);

                    matgroup.m_BoneIDs = new ushort[numbones];
                    for (uint b = 0; b < numbones; b++)
                    {
                        byte idx1 = m_File.Read8(bonesoffset + b);
                        matgroup.m_BoneIDs[b] = m_File.Read16((uint)(m_BoneMapOffset + (2 * idx1)));
                    }

                    matgroup.m_Geometry = new List<VertexList>();

                    m_CurVertex.m_Position = new Vector3(0, 0, 0);
                    m_CurVertex.m_TexCoord = new Vector2(0, 0);
                    if ((matgroup.m_DifAmbColors & 0x8000) == 0x8000)
                    {
                        byte alpha = (byte)((matgroup.m_PolyAttribs >> 13) & 0xF8);
                        alpha |= (byte)(alpha >> 5);
                        matgroup.m_Alpha = alpha;

                        m_CurVertex.m_Color = Color.FromArgb(alpha, matgroup.m_DiffuseColor);
                    }
                    else
                        m_CurVertex.m_Color = Color.Black;

                    m_CurVertex.m_MatrixID = 0;

                    uint dlend = dloffset + dlsize;
                    for (uint pos = dloffset; pos < dlend; )
                    {
                        byte cmd1 = m_File.Read8(pos++);
                        byte cmd2 = m_File.Read8(pos++);
                        byte cmd3 = m_File.Read8(pos++);
                        byte cmd4 = m_File.Read8(pos++);

                        ProcessGXCommand(matgroup, cmd1, ref pos);
                        ProcessGXCommand(matgroup, cmd2, ref pos);
                        ProcessGXCommand(matgroup, cmd3, ref pos);
                        ProcessGXCommand(matgroup, cmd4, ref pos);
                    }
                }
            }

            foreach (ModelChunk mdchunk in m_ModelChunks)
            {
                foreach (MaterialGroup matgroup in mdchunk.m_MatGroups)
                {
                    matgroup.m_BoneMatrices = new Matrix4[matgroup.m_BoneIDs.Length];
                    for (uint b = 0; b < matgroup.m_BoneIDs.Length; b++)
                        matgroup.m_BoneMatrices[b] = m_ModelChunks[matgroup.m_BoneIDs[b]].m_Transform;
                }
            }
        }
Exemple #4
0
            char[] m_Type; // 'INFO'

            #endregion Fields

            #region Constructors

            public SDATInfo(NitroFile sdat, uint offset)
            {
                m_Offset = offset;
                m_Type = sdat.ReadString(m_Offset + 0x00, 4).ToCharArray();
                m_Size = sdat.Read32(m_Offset + 0x04);
                m_RecordOffset = new uint[8];
                for (int i = 0; i < 8; i++)
                    m_RecordOffset[i] = sdat.Read32(m_Offset + 0x08 + (uint)(i * 4));
                m_Reserved = sdat.ReadBlock(m_Offset + 0x28, 24);

                m_Records = new SDATInfoRecord[8];
                for (int i = 0; i < 8; i++)
                {
                    m_Records[i] = new SDATInfoRecord(sdat, m_Offset + m_RecordOffset[i]);
                }
                m_Records0SEQ = new SDATInfoSEQ[m_Records[0].m_Count];
                for (int i = 0; i < m_Records[0].m_Count; i++)
                {
                    m_Records0SEQ[i] = new SDATInfoSEQ(sdat, m_Offset + m_Records[0].m_EntryOffset[i]);
                }
                m_Records1SEQARC = new SDATInfoSEQARC[m_Records[1].m_Count];
                for (int i = 0; i < m_Records[1].m_Count; i++)
                {
                    m_Records1SEQARC[i] = new SDATInfoSEQARC(sdat, m_Offset + m_Records[1].m_EntryOffset[i]);
                }
                m_Records2BANK = new SDATInfoBANK[m_Records[2].m_Count];
                for (int i = 0; i < m_Records[2].m_Count; i++)
                {
                    m_Records2BANK[i] = new SDATInfoBANK(sdat, m_Offset + m_Records[2].m_EntryOffset[i]);
                }
                m_Records3WAVEARC = new SDATInfoWAVEARC[m_Records[3].m_Count];
                for (int i = 0; i < m_Records[3].m_Count; i++)
                {
                    m_Records3WAVEARC[i] = new SDATInfoWAVEARC(sdat, m_Offset + m_Records[3].m_EntryOffset[i]);
                }
                m_Records4PLAYER = new SDATInfoPLAYER[m_Records[4].m_Count];
                for (int i = 0; i < m_Records[4].m_Count; i++)
                {
                    m_Records4PLAYER[i] = new SDATInfoPLAYER(sdat, m_Offset + m_Records[4].m_EntryOffset[i]);
                }
                m_Records5GROUP = new SDATInfoGROUP[m_Records[5].m_Count];
                for (int i = 0; i < m_Records[5].m_Count; i++)
                {
                    m_Records5GROUP[i] = new SDATInfoGROUP(sdat, m_Offset + m_Records[5].m_EntryOffset[i]);
                }
                m_Records6PLAYER2 = new SDATInfoPLAYER2[m_Records[6].m_Count];
                for (int i = 0; i < m_Records[6].m_Count; i++)
                {
                    m_Records6PLAYER2[i] = new SDATInfoPLAYER2(sdat, m_Offset + m_Records[6].m_EntryOffset[i]);
                }
                m_Records7STREAM = new SDATInfoSTREAM[m_Records[7].m_Count];
                for (int i = 0; i < m_Records[7].m_Count; i++)
                {
                    m_Records7STREAM[i] = new SDATInfoSTREAM(sdat, m_Offset + m_Records[7].m_EntryOffset[i]);
                }
            }