Example #1
0
 protected static void ExportTextureToPNG(string destDir, ModelBase.TextureDefBase texture)
 {
     try
     {
         ExportTextureToPNG(destDir, texture.m_ID, texture.GetBitmap());
     }
     catch (IOException)
     {
         Console.Write("Cannot write image for texture: " + texture.m_ID);
     }
 }
Example #2
0
        protected void AddTexture(ModelBase.TextureDefBase texture, ModelBase.MaterialDef matDef)
        {
            matDef.m_TextureDefID = texture.m_ID;

            IEnumerable <ModelBase.TextureDefBase> matchingHash = m_Model.m_Textures.Values.Where(
                tex0 => tex0.m_ImgHash.Equals(texture.m_ImgHash));

            if (matchingHash.Count() > 0)
            {
                matDef.m_TextureDefID = matchingHash.ElementAt(0).m_ID;
                return;
            }

            m_Model.m_Textures.Add(texture.m_ID, texture);
        }
        protected void ReadPolygon(int polygonIndex, XmlNode polygon_array, string materialID, ModelBase.GeometryDef geometryDef)
        {
            if (polygon_array == null)
            {
                return;
            }
            int polygonArray_size = int.Parse(polygon_array.Attributes["size"].Value);

            if (polygonArray_size < 1)
            {
                return;
            }

            XmlNodeList polygons = polygon_array.SelectNodes("polygon");
            XmlNode     polygon  = polygons[polygonIndex];

            int    index         = int.Parse(polygon.Attributes["index"].Value);
            string name          = polygon.Attributes["name"].Value;
            int    vertex_size   = int.Parse(polygon.Attributes["vertex_size"].Value);
            int    polygon_size  = int.Parse(polygon.Attributes["polygon_size"].Value);
            int    triangle_size = int.Parse(polygon.Attributes["triangle_size"].Value);
            int    quad_size     = int.Parse(polygon.Attributes["quad_size"].Value);

            float[] volume_min = Array.ConvertAll(
                polygon.Attributes["volume_min"].Value.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries),
                Convert.ToSingle);
            float[] volume_max = Array.ConvertAll(
                polygon.Attributes["volume_max"].Value.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries),
                Convert.ToSingle);
            float volume_r      = float.Parse(polygon.Attributes["volume_r"].Value);
            int   mtx_prim_size = int.Parse(polygon.Attributes["mtx_prim_size"].Value);
            bool  nrm_flag      = polygon.Attributes["nrm_flag"].Value.Equals("on");
            bool  clr_flag      = polygon.Attributes["clr_flag"].Value.Equals("on");
            bool  tex_flag      = polygon.Attributes["tex_flag"].Value.Equals("on");

            XmlNodeList mtx_prims = polygon.SelectNodes("mtx_prim");

            foreach (XmlNode mtx_prim in mtx_prims)
            {
                int mtxPrim_index = int.Parse(mtx_prim.Attributes["index"].Value);

                ModelBase.PolyListDef polyListDef = new ModelBase.PolyListDef(name + mtxPrim_index, materialID);

                XmlNode mtx_list     = mtx_prim.SelectSingleNode("mtx_list");
                int     mtxList_size = int.Parse(mtx_list.Attributes["size"].Value);
                Dictionary <int, int> localToGlobalMatrixIDMap = new Dictionary <int, int>();
                int[] mtxList_data = Array.ConvertAll(
                    mtx_list.InnerText.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries),
                    Convert.ToInt32);
                for (int i = 0; i < mtxList_size; i++)
                {
                    localToGlobalMatrixIDMap.Add(i, mtxList_data[i]);
                }

                XmlNode primitive_array     = mtx_prim.SelectSingleNode("primitive_array");
                int     primitiveArray_size = int.Parse(primitive_array.Attributes["size"].Value);

                XmlNodeList primitives = primitive_array.SelectNodes("primitive");

                int     mtx    = -1;
                int     boneID = -1;
                Vector2?tex    = null;
                Vector3?nrm    = null;
                Vector3 pos    = Vector3.Zero;
                Color   clr    = Color.White;
                foreach (XmlNode primitive in primitives)
                {
                    int    primitive_index       = int.Parse(primitive.Attributes["index"].Value);
                    string primitive_type        = primitive.Attributes["type"].Value;
                    int    primitive_vertex_size = int.Parse(primitive.Attributes["vertex_size"].Value);

                    ModelBase.PolyListType polyListType;
                    switch (primitive_type)
                    {
                    case "triangles": polyListType = ModelBase.PolyListType.Triangles; break;

                    case "quads": polyListType = ModelBase.PolyListType.Polygons; break;

                    case "triangle_strip": polyListType = ModelBase.PolyListType.TriangleStrip; break;

                    case "quad_strip": polyListType = ModelBase.PolyListType.QuadrilateralStrip; break;

                    default: goto case "triangles";
                    }

                    ModelBase.FaceListDef faceListDef = new ModelBase.FaceListDef(polyListType);

                    List <ModelBase.VertexDef> vertexList = new List <ModelBase.VertexDef>();
                    foreach (XmlNode child in primitive.ChildNodes)
                    {
                        switch (child.LocalName)
                        {
                        case "mtx":
                        {
                            mtx    = int.Parse(child.Attributes["idx"].Value);
                            boneID = m_Model.m_BoneTree.GetBoneIndex(
                                m_Model.m_BoneTransformsMap.GetBySecond(localToGlobalMatrixIDMap[mtx]));
                        }
                        break;

                        case "tex":
                        {
                            float[] texArr = Array.ConvertAll(
                                child.Attributes["st"].Value.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries),
                                Convert.ToSingle);
                            ModelBase.TextureDefBase texture = m_Model.m_Textures[m_Model.m_Materials[materialID].m_TextureDefID];
                            tex = new Vector2((float)(texArr[0] / texture.GetWidth()), (float)(texArr[1] / texture.GetHeight()));
                        }
                        break;

                        case "nrm":
                        {
                            float[] nrmArr = Array.ConvertAll(
                                child.Attributes["xyz"].Value.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries),
                                Convert.ToSingle);
                            nrm = new Vector3(nrmArr[0], nrmArr[1], nrmArr[2]);
                        }
                        break;

                        case "clr":
                        {
                            int[] clrArr = Array.ConvertAll(
                                child.Attributes["rgb"].Value.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries),
                                Convert.ToInt32);
                            clr = Color.FromArgb(
                                (int)(clrArr[0] / 31f * 255f), (int)(clrArr[1] / 31f * 255f), (int)(clrArr[2] / 31f * 255f));
                        }
                        break;

                        case "clr_idx":
                        {
                            int idx = int.Parse(child.Attributes["idx"].Value);

                            clr = vtx_color_data[idx];
                        }
                        break;

                        case "pos_xyz":
                        {
                            float[] pos_xyz = Array.ConvertAll(
                                child.Attributes["xyz"].Value.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries),
                                Convert.ToSingle);
                            pos = new Vector3(pos_xyz[0], pos_xyz[1], pos_xyz[2]);

                            AddVertexToList(boneID, tex, nrm, pos, this.model_info.pos_scale, clr, vertexList);
                        }
                        break;

                        case "pos_s": goto case "pos_xyz";

                        case "pos_xy":
                        {
                            float[] pos_xy = Array.ConvertAll(
                                child.Attributes["xy"].Value.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries),
                                Convert.ToSingle);
                            pos = new Vector3(pos_xy[0], pos_xy[1], pos.Z);

                            AddVertexToList(boneID, tex, nrm, pos, this.model_info.pos_scale, clr, vertexList);
                        }
                        break;

                        case "pos_xz":
                        {
                            float[] pos_xz = Array.ConvertAll(
                                child.Attributes["xz"].Value.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries),
                                Convert.ToSingle);
                            pos = new Vector3(pos_xz[0], pos.Y, pos_xz[1]);

                            AddVertexToList(boneID, tex, nrm, pos, this.model_info.pos_scale, clr, vertexList);
                        }
                        break;

                        case "pos_yz":
                        {
                            float[] pos_yz = Array.ConvertAll(
                                child.Attributes["yz"].Value.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries),
                                Convert.ToSingle);
                            pos = new Vector3(pos.X, pos_yz[0], pos_yz[1]);

                            AddVertexToList(boneID, tex, nrm, pos, this.model_info.pos_scale, clr, vertexList);
                        }
                        break;

                        case "pos_diff":
                        {
                            // (-0.125 ≤ real numbers ≤ 0.125) (x3)
                            float[] pos_diff = Array.ConvertAll(
                                child.Attributes["xyz"].Value.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries),
                                Convert.ToSingle);

                            pos = new Vector3(pos.X + pos_diff[0], pos.Y + pos_diff[1], pos.Z + pos_diff[2]);

                            AddVertexToList(boneID, tex, nrm, pos, this.model_info.pos_scale, clr, vertexList);
                        }
                        break;

                        case "pos_idx":
                        {
                            int idx = int.Parse(child.Attributes["idx"].Value);

                            pos = this.vtx_pos_data[idx];

                            AddVertexToList(boneID, tex, nrm, pos, this.model_info.pos_scale, clr, vertexList);
                        }
                        break;
                        }
                    }

                    switch (polyListType)
                    {
                    case ModelBase.PolyListType.Triangles:
                    {
                        int numVertsPerFace = 3;
                        int numFaces        = primitive_vertex_size / numVertsPerFace;
                        for (int i = 0; i < numFaces; i++)
                        {
                            ModelBase.FaceDef face = new ModelBase.FaceDef(numVertsPerFace);
                            for (int j = 0; j < numVertsPerFace; j++)
                            {
                                face.m_Vertices[j] = vertexList[(i * numVertsPerFace) + j];
                            }
                            faceListDef.m_Faces.Add(face);
                        }
                    }
                    break;

                    case ModelBase.PolyListType.Polygons:
                    {
                        int numVertsPerFace = 4;
                        int numFaces        = primitive_vertex_size / numVertsPerFace;
                        for (int i = 0; i < numFaces; i++)
                        {
                            ModelBase.FaceDef face = new ModelBase.FaceDef(numVertsPerFace);
                            for (int j = 0; j < numVertsPerFace; j++)
                            {
                                face.m_Vertices[j] = vertexList[(i * numVertsPerFace) + j];
                            }
                            faceListDef.m_Faces.Add(face);
                        }
                    }
                    break;

                    case ModelBase.PolyListType.TriangleStrip:
                    {
                        //3+(N-1) vertices per N triangles
                        //(N-3)+1 Triangles per N Vertices
                        int numFaces        = primitive_vertex_size - 2;
                        int numVertsPerFace = 3;
                        for (int i = 0; i < numFaces; i++)
                        {
                            ModelBase.FaceDef face = new ModelBase.FaceDef(3);
                            if ((i & 1) == 0)
                            {
                                face.m_Vertices[0] = vertexList[i + 0];
                                face.m_Vertices[1] = vertexList[i + 1];
                                face.m_Vertices[2] = vertexList[i + 2];
                            }
                            else
                            {
                                face.m_Vertices[0] = vertexList[i + 2];
                                face.m_Vertices[1] = vertexList[i + 1];
                                face.m_Vertices[2] = vertexList[i + 0];
                            }
                            faceListDef.m_Faces.Add(face);
                            //Because of how normals are defined in triangle strips, every 2nd triangle is clockwise, whereas all others are anti-clockwise
                        }
                    }
                    break;

                    case ModelBase.PolyListType.QuadrilateralStrip:
                    {
                        //4+(N-1)*2 vertices per N quads
                        //((N-4)/2) + 1 Quads. per N Vertices
                        int numFaces        = ((primitive_vertex_size - 4) / 2) + 1;
                        int numVertsPerFace = 4;
                        for (int n = 0, p = 0; n < numFaces; n++, p = p + 2)
                        {
                            ModelBase.FaceDef face = new ModelBase.FaceDef(numVertsPerFace);
                            face.m_Vertices[0] = vertexList[p + 0];
                            face.m_Vertices[1] = vertexList[p + 1];
                            face.m_Vertices[2] = vertexList[p + 3];
                            face.m_Vertices[3] = vertexList[p + 2];
                            faceListDef.m_Faces.Add(face);
                        }
                    }
                    break;
                    }

                    polyListDef.m_FaceLists.Add(faceListDef);
                }

                geometryDef.m_PolyLists.Add("PolyList-" + geometryDef.m_PolyLists.Count, polyListDef);
            }
        }
        protected void ReadTextures(XmlNode tex_image_array, XmlNode tex_palette_array)
        {
            if (tex_image_array == null)
            {
                return;
            }
            int texImageArray_size   = int.Parse(tex_image_array.Attributes["size"].Value);
            int texPaletteArray_size = int.Parse(tex_palette_array.Attributes["size"].Value);

            if (texImageArray_size < 1)
            {
                return;
            }

            XmlNodeList tex_images   = tex_image_array.SelectNodes("tex_image");
            XmlNodeList tex_palettes = tex_palette_array.SelectNodes("tex_palette");

            foreach (XmlNode tex_image in tex_images)
            {
                int    index           = int.Parse(tex_image.Attributes["index"].Value);
                string name            = tex_image.Attributes["name"].Value;
                int    width           = int.Parse(tex_image.Attributes["width"].Value);
                int    height          = int.Parse(tex_image.Attributes["height"].Value);
                int    original_width  = int.Parse(tex_image.Attributes["original_width"].Value);
                int    original_height = int.Parse(tex_image.Attributes["original_height"].Value);
                string format          = tex_image.Attributes["format"].Value;
                ModelBase.TextureFormat textureFormat;
                switch (format)
                {
                case "palette4": textureFormat = ModelBase.TextureFormat.Nitro_Palette4; break;

                case "palette16": textureFormat = ModelBase.TextureFormat.Nitro_Palette16; break;

                case "palette256": textureFormat = ModelBase.TextureFormat.Nitro_Palette256; break;

                case "tex4x4": textureFormat = ModelBase.TextureFormat.Nitro_Tex4x4; break;

                case "a3i5": textureFormat = ModelBase.TextureFormat.Nitro_A3I5; break;

                case "a5i3": textureFormat = ModelBase.TextureFormat.Nitro_A5I3; break;

                case "direct": textureFormat = ModelBase.TextureFormat.Nitro_Direct; break;

                default: goto case "direct";
                }
                string color0_mode = (textureFormat == ModelBase.TextureFormat.Nitro_Palette4 ||
                                      textureFormat == ModelBase.TextureFormat.Nitro_Palette16 ||
                                      textureFormat == ModelBase.TextureFormat.Nitro_Palette256) ?
                                     tex_image.Attributes["color0_mode"].Value : null;
                string palette_name = (textureFormat != ModelBase.TextureFormat.Nitro_Direct) ?
                                      tex_image.Attributes["palette_name"].Value : null;
                string path = (tex_image.Attributes["path"] != null) ? tex_image.Attributes["path"].Value : null;

                XmlNode bitmap       = tex_image.SelectSingleNode("bitmap");
                int     bitmap_size  = int.Parse(bitmap.Attributes["size"].Value);
                int     numBytesWord = (textureFormat != ModelBase.TextureFormat.Nitro_Tex4x4) ? 2 : 4;
                byte[]  dataTex      = UShortStringArrayToByteArray(bitmap.InnerText, bitmap_size, numBytesWord);

                ModelBase.TextureDefBase texture = null;

                if (textureFormat != ModelBase.TextureFormat.Nitro_Direct && palette_name != null)
                {
                    byte[] dataPal = null;

                    if (textureFormat != ModelBase.TextureFormat.Nitro_Tex4x4)
                    {
                        dataPal = ReadPaletteData(palette_name, tex_palettes);
                    }
                    else
                    {
                        XmlNode tex4x4_palette_idx    = tex_image.SelectSingleNode("tex4x4_palette_idx");
                        int     tex4x4PaletteIdx_size = int.Parse(tex4x4_palette_idx.Attributes["size"].Value);
                        dataPal = UShortStringArrayToByteArray(tex4x4_palette_idx.InnerText, tex4x4PaletteIdx_size, 2);
                    }

                    texture = new ModelBase.TextureDefNitro(name, dataTex, palette_name, dataPal,
                                                            (uint)width, (uint)height,
                                                            (byte)((color0_mode != null && color0_mode.Equals("transparency")) ? 1 : 0),
                                                            textureFormat);
                }
                else
                {
                    texture = new ModelBase.TextureDefNitro(name, dataTex, (uint)width, (uint)height,
                                                            1, textureFormat);
                }

                m_Model.m_Textures.Add(name, texture);
            }
        }