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); } }
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); } }