public override ModelBase LoadModel(float scale) { ModelBase.BoneDef rootBone = new ModelBase.BoneDef("CollisionMap"); m_Model.m_BoneTree.AddRootBone(rootBone); rootBone.CalculateBranchTransformations(); m_Model.m_BoneTransformsMap.Add(rootBone.m_ID, m_Model.m_BoneTransformsMap.Count); ModelBase.GeometryDef geometry = new ModelBase.GeometryDef("geometry-0"); rootBone.m_Geometries.Add(geometry.m_ID, geometry); List <int> uniqueCollisionTypes = new List <int>(); foreach (KCL.ColFace plane in m_KCL.m_Planes) { if (!uniqueCollisionTypes.Contains(plane.type)) { uniqueCollisionTypes.Add(plane.type); } } uniqueCollisionTypes.Sort(); CollisionMapColours collisionMapColours = new CollisionMapColours(); foreach (int type in uniqueCollisionTypes) { ModelBase.MaterialDef material = new ModelBase.MaterialDef("material-" + type); material.m_Diffuse = collisionMapColours[type]; m_Model.m_Materials.Add(material.m_ID, material); rootBone.m_MaterialsInBranch.Add(material.m_ID); ModelBase.PolyListDef tmp = new ModelBase.PolyListDef("polylist-" + type, material.m_ID); tmp.m_FaceLists.Add(new ModelBase.FaceListDef(ModelBase.PolyListType.Triangles)); rootBone.m_Geometries[geometry.m_ID].m_PolyLists.Add("polylist-" + type, tmp); } foreach (KCL.ColFace plane in m_KCL.m_Planes) { ModelBase.FaceDef face = new ModelBase.FaceDef(3); face.m_Vertices[0].m_Position = plane.point1; face.m_Vertices[1].m_Position = plane.point2; face.m_Vertices[2].m_Position = plane.point3; for (int vert = 0; vert < face.m_Vertices.Length; vert++) { face.m_Vertices[vert].m_TextureCoordinate = null; face.m_Vertices[vert].m_Normal = null; face.m_Vertices[vert].m_VertexColour = Color.White; face.m_Vertices[vert].m_VertexBoneIndex = 0; } geometry.m_PolyLists["polylist-" + plane.type].m_FaceLists[0].m_Faces.Add(face); } return(m_Model); }
public override ModelBase LoadModel(OpenTK.Vector3 scale) { ModelBase.BoneDef rootBone = new ModelBase.BoneDef("CollisionMap"); m_Model.m_BoneTree.AddRootBone(rootBone); ModelBase.GeometryDef geometry = new ModelBase.GeometryDef("geometry-0"); rootBone.m_Geometries.Add(geometry.m_ID, geometry); List<int> uniqueCollisionTypes = new List<int>(); foreach (KCL.ColFace plane in m_KCL.m_Planes) { if (!uniqueCollisionTypes.Contains(plane.type)) uniqueCollisionTypes.Add(plane.type); } uniqueCollisionTypes.Sort(); List<Color> uniqueColours = GetColours(uniqueCollisionTypes[uniqueCollisionTypes.Count - 1] + 1); foreach (int type in uniqueCollisionTypes) { ModelBase.MaterialDef material = new ModelBase.MaterialDef("material-" + type, m_Model.m_Materials.Count); material.m_Diffuse = uniqueColours[type]; m_Model.m_Materials.Add(material.m_ID, material); rootBone.m_MaterialsInBranch.Add(material.m_ID); ModelBase.PolyListDef tmp = new ModelBase.PolyListDef("polylist-" + type, material.m_ID); tmp.m_FaceLists.Add(new ModelBase.FaceListDef()); rootBone.m_Geometries[geometry.m_ID].m_PolyLists.Add("polylist-" + type, tmp); } foreach (KCL.ColFace plane in m_KCL.m_Planes) { ModelBase.FaceDef face = new ModelBase.FaceDef(3); face.m_Vertices[0].m_Position = plane.point1; face.m_Vertices[1].m_Position = plane.point2; face.m_Vertices[2].m_Position = plane.point3; for (int vert = 0; vert < face.m_Vertices.Length; vert++) { face.m_Vertices[vert].m_TextureCoordinate = Vector2.Zero; face.m_Vertices[vert].m_Normal = null; face.m_Vertices[vert].m_VertexColour = Color.White; face.m_Vertices[vert].m_VertexBoneID = 0; } geometry.m_PolyLists["polylist-" + plane.type].m_FaceLists[0].m_Faces.Add(face); } return m_Model; }
private ModelBase.GeometryDef ReadGeometry(string id, string boneID, Dictionary<string, string> bindMaterials, int[] vertexBoneIDs) { ModelBase.GeometryDef geomDef = new ModelBase.GeometryDef(id); int boneIndex = m_Model.m_BoneTree.GetBoneIndex(boneID); geometry geom = library_geometries.geometry.Where(geom0 => geom0.id.Equals(id)).ElementAt(0); Dictionary<string, source> sources = new Dictionary<string, source>(); if (geom.Item as mesh != null) { mesh geomMesh = geom.Item as mesh; Dictionary<string, string> geometryVertices = new Dictionary<string,string>(); geometryVertices.Add(geomMesh.vertices.id, geomMesh.vertices.input.Where(input0 => input0.semantic.Equals("POSITION")).ElementAt(0).source.Replace("#", "")); foreach (source src in geomMesh.source) { string sourceID = src.id; if (src.Item as float_array != null) sources.Add(sourceID, src); } foreach (var item in geomMesh.Items) { if ((item as triangles != null) || (item as polylist != null) || (item as polygons != null) || (item as tristrips != null)) { ModelBase.PolyListDef polyListDef; string material = null; ulong count; InputLocalOffset[] inputs = new InputLocalOffset[0]; int[] vcount = new int[0]; List<int[]> p = new List<int[]>(); ModelBase.PolyListType polyListType = ModelBase.PolyListType.Polygons; if (item as triangles != null) { triangles tris = item as triangles; polyListType = ModelBase.PolyListType.Triangles; string matAttr = (tris.material != null) ? tris.material : "default_white"; material = (bindMaterials != null && bindMaterials.Count > 0 && bindMaterials.ContainsKey(matAttr)) ? bindMaterials[matAttr] : matAttr; count = tris.count; inputs = tris.input; vcount = new int[] { 3 }; p.Add(Array.ConvertAll<string, int> (tris.p.Split(new string[] { " ", "\n", "\r\n" }, StringSplitOptions.RemoveEmptyEntries), Convert.ToInt32)); } else if (item as polylist != null) { polylist plist = item as polylist; polyListType = ModelBase.PolyListType.Polygons; string matAttr = (plist.material != null) ? plist.material : "default_white"; material = (bindMaterials != null && bindMaterials.Count > 0 && bindMaterials.ContainsKey(matAttr)) ? bindMaterials[matAttr] : matAttr; count = plist.count; inputs = plist.input; vcount = Array.ConvertAll<string, int> (plist.vcount.Split(new string[] { " ", "\n", "\r\n" }, StringSplitOptions.RemoveEmptyEntries), Convert.ToInt32); p.Add(Array.ConvertAll<string, int> (plist.p.Split(new string[] { " ", "\n", "\r\n" }, StringSplitOptions.RemoveEmptyEntries), Convert.ToInt32)); } else if (item as polygons != null) { polygons pgons = item as polygons; polyListType = ModelBase.PolyListType.Polygons; string matAttr = (pgons.material != null) ? pgons.material : "default_white"; material = (bindMaterials != null && bindMaterials.Count > 0 && bindMaterials.ContainsKey(matAttr)) ? bindMaterials[matAttr] : matAttr; count = pgons.count; inputs = pgons.input; vcount = new int[count]; int[] pTmp = new int[0]; int counter = 0; for (int i = 0; i < pgons.Items.Length; i++) { var element = pgons.Items[i]; if (element as string != null) { int[] tmp = Array.ConvertAll<string, int> ((element as string).Split(new string[] { " ", "\n", "\r\n" }, StringSplitOptions.RemoveEmptyEntries), Convert.ToInt32); vcount[i] = tmp.Length / inputs.Length; Array.Resize(ref pTmp, pTmp.Length + (vcount[i] * inputs.Length)); Array.Copy(tmp, 0, pTmp, counter, tmp.Length); counter += tmp.Length; } } p.Add(pTmp); } else if (item as tristrips != null) { tristrips tristrips = item as tristrips; polyListType = ModelBase.PolyListType.TriangleStrip; string matAttr = (tristrips.material != null) ? tristrips.material : "default_white"; material = (bindMaterials != null && bindMaterials.Count > 0 && bindMaterials.ContainsKey(matAttr)) ? bindMaterials[matAttr] : matAttr; count = tristrips.count; inputs = tristrips.input; vcount = new int[] { 3 }; // Go through <p> elements and convert it so the format is similar to <polylist> for parsing below // Eg. given: (0,(1,(2),(3),4),5) // convert to separate triangles: (0,1,2),(1,2,3),(2,3,4),(3,4,5) // These will be converted back to triangle strips when writing the BMD model for (int i = 0; i < tristrips.p.Length; i++) { var element = tristrips.p[i]; if (element as string != null) { int[] tmp = Array.ConvertAll<string, int> ((element as string).Split(new string[] { " ", "\n", "\r\n" }, StringSplitOptions.RemoveEmptyEntries), Convert.ToInt32); int numTris = ((tmp.Length / inputs.Length) - 3) + 1; int numVertsToTris = numTris * 3; int[] tmpConv = new int[numVertsToTris * inputs.Length]; Array.Copy(tmp, tmpConv, (3 * inputs.Length)); if (tmp.Length > (3 * inputs.Length)) { int startInd = 3 * inputs.Length; for (int sourceInd = startInd, destInd = startInd; sourceInd < tmp.Length; sourceInd += inputs.Length, destInd += (3 * inputs.Length)) { Array.Copy(tmp, sourceInd - (2 * inputs.Length), tmpConv, destInd, (3 * inputs.Length)); } } p.Add(tmpConv); } } } polyListDef = new ModelBase.PolyListDef(id + "." + material, material); // The parent (root) bone should have a list of all materials used by itself and its children if (!m_Model.m_BoneTree.GetBoneByID(boneID).GetRoot().m_MaterialsInBranch.Contains(material)) m_Model.m_BoneTree.GetBoneByID(boneID).GetRoot().m_MaterialsInBranch.Add(material); if (!m_Model.m_BoneTree.GetBoneByID(boneID).m_MaterialsInBranch.Contains(material)) m_Model.m_BoneTree.GetBoneByID(boneID).m_MaterialsInBranch.Add(material); int inputCount = inputs.Length; int vertexOffset = -1, normalOffset = -1, texCoordOffset = -1, colourOffset = -1; string vertexSource = "", normalSource = "", texCoordSource = "", colourSource = ""; foreach (InputLocalOffset input in inputs) { if (input.semantic.Equals("VERTEX")) { vertexOffset = (int)input.offset; vertexSource = geometryVertices[input.source.Replace("#", "")]; } else if (input.semantic.Equals("NORMAL")) { normalOffset = (int)input.offset; normalSource = input.source.Replace("#", ""); } else if (input.semantic.Equals("TEXCOORD")) { texCoordOffset = (int)input.offset; texCoordSource = input.source.Replace("#", ""); } else if (input.semantic.Equals("COLOR")) { colourOffset = (int)input.offset; colourSource = input.source.Replace("#", ""); } } foreach (int[] pArr in p) { ModelBase.FaceListDef faceList = new ModelBase.FaceListDef(polyListType); bool even = true; for (ulong pIndex = 0, vcountInd = 0; pIndex < (ulong)pArr.Length; vcountInd++) { ModelBase.FaceDef faceDef = new ModelBase.FaceDef( vcount[(polyListType.Equals(ModelBase.PolyListType.Triangles) || polyListType.Equals(ModelBase.PolyListType.TriangleStrip)) ? 0 : vcountInd]); List<ModelBase.VertexDef> vertices = new List<ModelBase.VertexDef>(); for (int i = 0; i < faceDef.m_NumVertices; i++) { ModelBase.VertexDef vert = ModelBase.EMPTY_VERTEX; int vertexIndex = pArr[pIndex + (ulong)vertexOffset]; float[] tmp = GetValueFromFloatArraySource(sources[vertexSource], vertexIndex); vert.m_Position = new Vector3(tmp[0], tmp[1], tmp[2]); /*if (normalOffset != -1) { tmp = GetValueFromFloatArraySource(sources[normalSource], pArr[pIndex + (ulong)normalOffset]); vert.m_Normal = new Vector3(tmp[0], tmp[1], tmp[2]); ((Vector3)vert.m_Normal).Normalize(); } else*/ { vert.m_Normal = null; } if (texCoordOffset != -1 && m_Model.m_Materials[material].m_TextureDefID != null) { tmp = GetValueFromFloatArraySource(sources[texCoordSource], pArr[pIndex + (ulong)texCoordOffset]); if (m_Model.m_Materials[material].m_TexGenMode != ModelBase.TexGenMode.Normal) { vert.m_TextureCoordinate = new Vector2(tmp[0], tmp[1]); } else { vert.m_Normal = new Vector3( tmp[0] * m_Model.m_Textures[m_Model.m_Materials[material].m_TextureDefID].GetWidth(), tmp[1] * m_Model.m_Textures[m_Model.m_Materials[material].m_TextureDefID].GetHeight(), 0.0f); vert.m_TextureCoordinate = null; } } else { vert.m_TextureCoordinate = null; } if (colourOffset != -1) { tmp = GetValueFromFloatArraySource(sources[colourSource], pArr[pIndex + (ulong)colourOffset]); vert.m_VertexColour = Color.FromArgb((int)(tmp[0] * 255f), (int)(tmp[1] * 255f), (int)(tmp[2] * 255f)); } else { vert.m_VertexColour = Color.White; } vert.m_VertexBoneID = (vertexBoneIDs != null) ? vertexBoneIDs[vertexIndex] : boneIndex; vertices.Add(vert); pIndex += (ulong)inputCount; } if (polyListType.Equals(ModelBase.PolyListType.TriangleStrip)) { if (even) { for (int v = 0; v < vertices.Count; v++) faceDef.m_Vertices[v] = vertices[v]; } else { for (int v = 0; v < vertices.Count; v++) faceDef.m_Vertices[2 - v] = vertices[v]; } even = !even; } else { for (int v = 0; v < vertices.Count; v++) faceDef.m_Vertices[v] = vertices[v]; } faceList.m_Faces.Add(faceDef); } polyListDef.m_FaceLists.Add(faceList); } geomDef.m_PolyLists.Add(boneID + "." + material, polyListDef); } } } return geomDef; }
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 ReadNodes(XmlNode node_array, XmlNode polygon_array, XmlNode matrix_array) { if (node_array == null) { return; } int nodeArray_size = int.Parse(node_array.Attributes["size"].Value); if (nodeArray_size < 1) { return; } XmlNodeList nodes = node_array.SelectNodes("node"); foreach (XmlNode node in nodes) { m_OriginalNodeIndices.Add(int.Parse(node.Attributes["index"].Value), node.Attributes["name"].Value); } ReadMatrices(matrix_array, m_OriginalNodeIndices); var queue = new Queue <XmlNode>(); var geometryQueue = new Queue <XmlNode>(); queue.Enqueue(nodes[0]); while (queue.Count > 0) { XmlNode node = queue.Dequeue(); int index = int.Parse(node.Attributes["index"].Value); string name = node.Attributes["name"].Value; string kind = node.Attributes["kind"].Value; int parent = int.Parse(node.Attributes["parent"].Value); int child = int.Parse(node.Attributes["child"].Value); int brother_next = int.Parse(node.Attributes["brother_next"].Value); int brother_prev = int.Parse(node.Attributes["brother_prev"].Value); bool draw_mtx = node.Attributes["draw_mtx"].Value.Equals("on"); string scale_compensate = (node.Attributes["scale_compensate"] != null) ? node.Attributes["scale_compensate"].Value : null; string billboard = node.Attributes["billboard"].Value; // Either "on", "off" or "y_on" float[] scale = Array.ConvertAll( node.Attributes["scale"].Value.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries), Convert.ToSingle); float[] rotate = Array.ConvertAll( node.Attributes["rotate"].Value.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries), Convert.ToSingle); float[] translate = Array.ConvertAll( node.Attributes["translate"].Value.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries), Convert.ToSingle); bool visibility = node.Attributes["visibility"].Value.Equals("on"); int display_size = int.Parse(node.Attributes["display_size"].Value); int vertex_size = (kind.Equals("mesh")) ? int.Parse(node.Attributes["vertex_size"].Value) : -1; int polygon_size = (kind.Equals("mesh")) ? int.Parse(node.Attributes["polygon_size"].Value) : -1; int triangle_size = (kind.Equals("mesh")) ? int.Parse(node.Attributes["triangle_size"].Value) : -1; int quad_size = (kind.Equals("mesh")) ? int.Parse(node.Attributes["quad_size"].Value) : -1; float[] volume_min = (kind.Equals("mesh")) ? Array.ConvertAll( node.Attributes["volume_min"].Value.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries), Convert.ToSingle) : null; float[] volume_max = (kind.Equals("mesh")) ? Array.ConvertAll( node.Attributes["volume_max"].Value.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries), Convert.ToSingle) : null; float volume_r = (kind.Equals("mesh")) ? float.Parse(node.Attributes["volume_r"].Value) : -1; ModelBase.BoneDef boneDef = new ModelBase.BoneDef(name); boneDef.SetScale(new Vector3(scale[0], scale[1], scale[2])); boneDef.SetRotation(new Vector3(rotate[0] * Helper.Deg2Rad, rotate[1] * Helper.Deg2Rad, rotate[2] * Helper.Deg2Rad)); boneDef.SetTranslation(new Vector3(translate[0], translate[1], translate[2])); boneDef.CalculateBranchTransformations(); if (display_size > 0) { geometryQueue.Enqueue(node); } if (parent == -1) { m_Model.m_BoneTree.AddRootBone(boneDef); } else { m_Model.m_BoneTree.GetBoneByID(m_OriginalNodeIndices[parent]).AddChild(boneDef); } /* Child node takes priority and siblings are stored consecutively by name in alphanumerical order * (a→z and 0→9). The model root node must be the first <node> in <node_array> (index 0). * "child" attribute gives first child, alphanumerically. */ if (child != -1) { queue.Enqueue(nodes[child]); } if (brother_next != -1) { queue.Enqueue(nodes[brother_next]); } } // In oder to correctly read the geometry we need to already have the list of bones read in so that bone ID's // can be assigned to vertices while (geometryQueue.Count > 0) { XmlNode node = geometryQueue.Dequeue(); XmlNodeList displays = node.SelectNodes("display"); ModelBase.BoneDef boneDef = m_Model.m_BoneTree.GetBoneByID(node.Attributes["name"].Value); ModelBase.GeometryDef geometryDef = new ModelBase.GeometryDef("geometry-0"); foreach (XmlNode display in displays) { int display_index = int.Parse(display.Attributes["index"].Value); int display_material = int.Parse(display.Attributes["material"].Value); int display_polygon = int.Parse(display.Attributes["polygon"].Value); int display_priority = int.Parse(display.Attributes["priority"].Value); ReadPolygon(display_polygon, polygon_array, m_Model.m_Materials.ElementAt(display_material).Key, geometryDef); boneDef.m_MaterialsInBranch.Add(m_Model.m_Materials.ElementAt(display_material).Key); } boneDef.m_Geometries.Add(geometryDef.m_ID, geometryDef); } m_Model.ApplyTransformations(); }
public override ModelBase LoadModel(OpenTK.Vector3 scale) { foreach (BMD.ModelChunk mdchunk in m_BMD.m_ModelChunks) { ModelBase.BoneDef bone = new ModelBase.BoneDef(mdchunk.m_Name); bone.SetScale(mdchunk.m_20_12Scale); bone.SetRotation(mdchunk.m_4_12Rotation); bone.SetTranslation(mdchunk.m_20_12Translation); if (mdchunk.m_ParentOffset == 0) { m_Model.m_BoneTree.AddRootBone(bone); } else { List <ModelBase.BoneDef> listOfBones = m_Model.m_BoneTree.GetAsList(); listOfBones[listOfBones.Count + mdchunk.m_ParentOffset].AddChild(bone); } ModelBase.GeometryDef geomDef = null; if (mdchunk.m_MatGroups.Length > 0) { geomDef = new ModelBase.GeometryDef("geometry-0"); bone.m_Geometries.Add(geomDef.m_ID, geomDef); } foreach (BMD.MaterialGroup matgroup in mdchunk.m_MatGroups) { if (!geomDef.m_PolyLists.ContainsKey(matgroup.m_Name)) { ModelBase.PolyListDef pld = new ModelBase.PolyListDef("polylist-" + matgroup.m_Name, matgroup.m_Name); geomDef.m_PolyLists.Add(pld.m_MaterialName, pld); } ModelBase.PolyListDef polyListDef = geomDef.m_PolyLists[matgroup.m_Name]; ModelBase.MaterialDef material = new ModelBase.MaterialDef(matgroup.m_Name, m_Model.m_Materials.Count); material.m_Diffuse = matgroup.m_DiffuseColor; material.m_Ambient = matgroup.m_AmbientColor; material.m_Specular = matgroup.m_SpecularColor; material.m_Emission = matgroup.m_EmissionColor; bool hasTextures = (matgroup.m_Texture != null); if (hasTextures) { if (!m_Model.m_Textures.ContainsKey(matgroup.m_Texture.m_TexName)) { ModelBase.TextureDefBase texture = new ModelBase.TextureDefInMemoryBitmap( matgroup.m_Texture.m_TexName, ConvertBMDTextureToBitmap(matgroup.m_Texture)); m_Model.m_Textures.Add(texture.m_ID, texture); } material.m_TextureDefID = matgroup.m_Texture.m_TexName; } material.m_Alpha = matgroup.m_Alpha; if ((matgroup.m_PolyAttribs & 0xC0) == 0xC0) { material.m_PolygonDrawingFace = ModelBase.MaterialDef.PolygonDrawingFace.FrontAndBack; } else if ((matgroup.m_PolyAttribs & 0xC0) == 0x80) { material.m_PolygonDrawingFace = ModelBase.MaterialDef.PolygonDrawingFace.Front; } else if ((matgroup.m_PolyAttribs & 0xC0) == 0x40) { material.m_PolygonDrawingFace = ModelBase.MaterialDef.PolygonDrawingFace.Back; } if (!m_Model.m_Materials.ContainsKey(material.m_ID)) { m_Model.m_Materials.Add(material.m_ID, material); } bone.m_MaterialsInBranch.Add(matgroup.m_Name); ModelBase.BoneDef upToRoot = bone; while ((upToRoot = upToRoot.m_Parent) != null) { if (!upToRoot.m_MaterialsInBranch.Contains(matgroup.m_Name)) { upToRoot.m_MaterialsInBranch.Add(matgroup.m_Name); } } foreach (BMD.VertexList geometry in matgroup.m_Geometry) { uint polyType = geometry.m_PolyType; List <BMD.Vertex> vtxList = geometry.m_VertexList; switch (polyType) { case 0: //Separate Triangles { ModelBase.FaceListDef faceList = new ModelBase.FaceListDef(ModelBase.PolyListType.Triangles); if (vtxList.Count <= 3) //Just 1 triangle { ModelBase.FaceDef face = new ModelBase.FaceDef(3); face.m_Vertices[0] = new ModelBase.VertexDef(vtxList[0].m_Position, vtxList[0].m_TexCoord, vtxList[0].m_Normal, vtxList[0].m_Color, (int)matgroup.m_BoneIDs[vtxList[0].m_MatrixID]); face.m_Vertices[1] = new ModelBase.VertexDef(vtxList[1].m_Position, vtxList[1].m_TexCoord, vtxList[1].m_Normal, vtxList[1].m_Color, (int)matgroup.m_BoneIDs[vtxList[1].m_MatrixID]); face.m_Vertices[2] = new ModelBase.VertexDef(vtxList[2].m_Position, vtxList[2].m_TexCoord, vtxList[2].m_Normal, vtxList[2].m_Color, (int)matgroup.m_BoneIDs[vtxList[2].m_MatrixID]); faceList.m_Faces.Add(face); } else if (vtxList.Count > 3 && (float)vtxList.Count % 3 == 0.0f) //Eg. 9 vertices in 3 triangles { int numFaces = vtxList.Count / 3; for (int a = 0, b = 0; a < numFaces; a++, b = b + 3) { ModelBase.FaceDef face = new ModelBase.FaceDef(3); face.m_Vertices[0] = new ModelBase.VertexDef(vtxList[b + 0].m_Position, vtxList[b + 0].m_TexCoord, vtxList[b + 0].m_Normal, vtxList[b + 0].m_Color, (int)matgroup.m_BoneIDs[vtxList[b + 0].m_MatrixID]); face.m_Vertices[1] = new ModelBase.VertexDef(vtxList[b + 1].m_Position, vtxList[b + 1].m_TexCoord, vtxList[b + 1].m_Normal, vtxList[b + 1].m_Color, (int)matgroup.m_BoneIDs[vtxList[b + 1].m_MatrixID]); face.m_Vertices[2] = new ModelBase.VertexDef(vtxList[b + 2].m_Position, vtxList[b + 2].m_TexCoord, vtxList[b + 2].m_Normal, vtxList[b + 2].m_Color, (int)matgroup.m_BoneIDs[vtxList[b + 2].m_MatrixID]); faceList.m_Faces.Add(face); } } polyListDef.m_FaceLists.Add(faceList); break; } case 1: //Separate Quadrilaterals { ModelBase.FaceListDef faceList = new ModelBase.FaceListDef(ModelBase.PolyListType.Polygons); if (vtxList.Count <= 4) //Just 1 quadrilateral { ModelBase.FaceDef face = new ModelBase.FaceDef(4); face.m_Vertices[0] = new ModelBase.VertexDef(vtxList[0].m_Position, vtxList[0].m_TexCoord, vtxList[0].m_Normal, vtxList[0].m_Color, (int)matgroup.m_BoneIDs[vtxList[0].m_MatrixID]); face.m_Vertices[1] = new ModelBase.VertexDef(vtxList[1].m_Position, vtxList[1].m_TexCoord, vtxList[1].m_Normal, vtxList[1].m_Color, (int)matgroup.m_BoneIDs[vtxList[1].m_MatrixID]); face.m_Vertices[2] = new ModelBase.VertexDef(vtxList[2].m_Position, vtxList[2].m_TexCoord, vtxList[2].m_Normal, vtxList[2].m_Color, (int)matgroup.m_BoneIDs[vtxList[2].m_MatrixID]); face.m_Vertices[3] = new ModelBase.VertexDef(vtxList[3].m_Position, vtxList[3].m_TexCoord, vtxList[3].m_Normal, vtxList[3].m_Color, (int)matgroup.m_BoneIDs[vtxList[3].m_MatrixID]); faceList.m_Faces.Add(face); } else if (vtxList.Count > 4 && (float)vtxList.Count % 4 == 0.0f) //Eg. 8 vertices in 2 quadrilaterals { int numFaces = vtxList.Count / 4; for (int a = 0, b = 0; a < numFaces; a++, b = b + 4) { ModelBase.FaceDef face = new ModelBase.FaceDef(4); face.m_Vertices[0] = new ModelBase.VertexDef(vtxList[b + 0].m_Position, vtxList[b + 0].m_TexCoord, vtxList[b + 0].m_Normal, vtxList[b + 0].m_Color, (int)matgroup.m_BoneIDs[vtxList[b + 0].m_MatrixID]); face.m_Vertices[1] = new ModelBase.VertexDef(vtxList[b + 1].m_Position, vtxList[b + 1].m_TexCoord, vtxList[b + 1].m_Normal, vtxList[b + 1].m_Color, (int)matgroup.m_BoneIDs[vtxList[b + 1].m_MatrixID]); face.m_Vertices[2] = new ModelBase.VertexDef(vtxList[b + 2].m_Position, vtxList[b + 2].m_TexCoord, vtxList[b + 2].m_Normal, vtxList[b + 2].m_Color, (int)matgroup.m_BoneIDs[vtxList[b + 2].m_MatrixID]); face.m_Vertices[3] = new ModelBase.VertexDef(vtxList[b + 3].m_Position, vtxList[b + 3].m_TexCoord, vtxList[b + 3].m_Normal, vtxList[b + 3].m_Color, (int)matgroup.m_BoneIDs[vtxList[b + 3].m_MatrixID]); faceList.m_Faces.Add(face); } } polyListDef.m_FaceLists.Add(faceList); break; } case 2: //Triangle Strips { //3+(N-1) vertices per N triangles //(N-3)+1 Triangles per N Vertices int numFaces = vtxList.Count - 2; if (vtxList.Count < 3) //Should never be { break; } ModelBase.FaceListDef faceList = new ModelBase.FaceListDef(ModelBase.PolyListType.TriangleStrip); //Convert all faces with more than 3 vertices to ones with only 3 for (int n = 0; n < numFaces; n++) { if (n % 2 == 0) { ModelBase.FaceDef face = new ModelBase.FaceDef(3); face.m_Vertices[0] = new ModelBase.VertexDef(vtxList[n + 0].m_Position, vtxList[n + 0].m_TexCoord, vtxList[n + 0].m_Normal, vtxList[n + 0].m_Color, (int)matgroup.m_BoneIDs[vtxList[n + 0].m_MatrixID]); face.m_Vertices[1] = new ModelBase.VertexDef(vtxList[n + 1].m_Position, vtxList[n + 1].m_TexCoord, vtxList[n + 1].m_Normal, vtxList[n + 1].m_Color, (int)matgroup.m_BoneIDs[vtxList[n + 1].m_MatrixID]); face.m_Vertices[2] = new ModelBase.VertexDef(vtxList[n + 2].m_Position, vtxList[n + 2].m_TexCoord, vtxList[n + 2].m_Normal, vtxList[n + 2].m_Color, (int)matgroup.m_BoneIDs[vtxList[n + 2].m_MatrixID]); faceList.m_Faces.Add(face); } else { ModelBase.FaceDef face = new ModelBase.FaceDef(3); face.m_Vertices[0] = new ModelBase.VertexDef(vtxList[n + 2].m_Position, vtxList[n + 2].m_TexCoord, vtxList[n + 2].m_Normal, vtxList[n + 2].m_Color, (int)matgroup.m_BoneIDs[vtxList[n + 2].m_MatrixID]); face.m_Vertices[1] = new ModelBase.VertexDef(vtxList[n + 1].m_Position, vtxList[n + 1].m_TexCoord, vtxList[n + 2].m_Normal, vtxList[n + 1].m_Color, (int)matgroup.m_BoneIDs[vtxList[n + 1].m_MatrixID]); face.m_Vertices[2] = new ModelBase.VertexDef(vtxList[n + 0].m_Position, vtxList[n + 0].m_TexCoord, vtxList[n + 0].m_Normal, vtxList[n + 0].m_Color, (int)matgroup.m_BoneIDs[vtxList[n + 0].m_MatrixID]); faceList.m_Faces.Add(face); } //Because of how normals are defined in triangle strips, every 2nd triangle is clockwise, whereas all others are anti-clockwise } polyListDef.m_FaceLists.Add(faceList); break; } case 3: //Quadrilateral Strips { //4+(N-1)*2 vertices per N quads //((N-4)/2) + 1 Quads. per N Vertices int numFaces = ((vtxList.Count - 4) / 2) + 1; if (vtxList.Count < 4) //Should never be { break; } ModelBase.FaceListDef faceList = new ModelBase.FaceListDef(); for (int n = 0, p = 0; n < numFaces; n++, p = p + 2) { ModelBase.FaceDef face = new ModelBase.FaceDef(4); face.m_Vertices[0] = new ModelBase.VertexDef(vtxList[p + 0].m_Position, vtxList[p + 0].m_TexCoord, vtxList[p + 0].m_Normal, vtxList[p + 0].m_Color, (int)matgroup.m_BoneIDs[vtxList[p + 0].m_MatrixID]); face.m_Vertices[1] = new ModelBase.VertexDef(vtxList[p + 1].m_Position, vtxList[p + 1].m_TexCoord, vtxList[p + 1].m_Normal, vtxList[p + 1].m_Color, (int)matgroup.m_BoneIDs[vtxList[p + 1].m_MatrixID]); face.m_Vertices[2] = new ModelBase.VertexDef(vtxList[p + 3].m_Position, vtxList[p + 3].m_TexCoord, vtxList[p + 3].m_Normal, vtxList[p + 3].m_Color, (int)matgroup.m_BoneIDs[vtxList[p + 3].m_MatrixID]); face.m_Vertices[3] = new ModelBase.VertexDef(vtxList[p + 2].m_Position, vtxList[p + 2].m_TexCoord, vtxList[p + 2].m_Normal, vtxList[p + 2].m_Color, (int)matgroup.m_BoneIDs[vtxList[p + 2].m_MatrixID]); faceList.m_Faces.Add(face); } polyListDef.m_FaceLists.Add(faceList); break; } default: MessageBox.Show("Unknown polygon type."); break; }//End polyType switch } } bone.CalculateBranchTransformations(); } m_Model.ApplyTransformations(); return(m_Model); }
public override ModelBase LoadModel(float scale) { if (m_ModelFileName == null || "".Equals(m_ModelFileName)) { throw new SystemException("You must specify the filename of the model to load via the constructor before " + "calling LoadModel()"); } Stream fs = File.OpenRead(m_ModelFileName); StreamReader sr = new StreamReader(fs); string curmaterial = null; bool foundObjects = LoadDefaultBones(m_ModelFileName); string currentBone = null; int currentBoneIndex = -1; if (!foundObjects) { currentBone = "default_bone_name"; ModelBase.BoneDef defaultBone = new ModelBase.BoneDef(currentBone); defaultBone.m_Geometries.Add("geometry-0", new ModelBase.GeometryDef("geometry-0")); m_Model.m_BoneTree.AddRootBone(defaultBone); currentBoneIndex = m_Model.m_BoneTree.GetBoneIndex(defaultBone); } string curline; while ((curline = sr.ReadLine()) != null) { curline = curline.Trim(); // skip empty lines and comments if (curline.Length < 1) { continue; } if (curline[0] == '#') { continue; } string[] parts = curline.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (parts.Length < 1) { continue; } switch (parts[0]) { case "mtllib": // material lib file { string filename = curline.Substring(parts[0].Length + 1).Trim(); LoadMaterials(m_ModelPath + Path.DirectorySeparatorChar + filename); } break; case "bonelib": // bone definitions file { string filename = curline.Substring(parts[0].Length + 1).Trim(); LoadBoneDefinitionsForOBJ(m_ModelPath + Path.DirectorySeparatorChar + filename); } break; case "o": // object (bone) if (parts.Length < 2) { continue; } currentBone = parts[1]; m_Model.m_BoneTree.GetBoneByID(currentBone).m_Geometries.Add(currentBone, new ModelBase.GeometryDef(currentBone)); currentBoneIndex = m_Model.m_BoneTree.GetBoneIndex(currentBone); break; case "usemtl": // material name if (parts.Length < 2) { continue; } curmaterial = parts[1]; if (!m_Model.m_Materials.ContainsKey(curmaterial)) { curmaterial = "default_white"; AddWhiteMat(currentBone); } break; case "v": // vertex { if (parts.Length < 4) { continue; } float x = Helper.ParseFloat(parts[1]); float y = Helper.ParseFloat(parts[2]); float z = Helper.ParseFloat(parts[3]); float w = 1f; //(parts.Length < 5) ? 1f : Helper.ParseFloat(parts[4]); m_Vertices.Add(new Vector4(x, y, z, w)); m_VertexBoneIDs.Add(currentBoneIndex); } break; case "vt": // texcoord { if (parts.Length < 2) { continue; } float s = Helper.ParseFloat(parts[1]); float t = (parts.Length < 3) ? 0f : Helper.ParseFloat(parts[2]); m_TexCoords.Add(new Vector2(s, t)); } break; case "vn": // normal { if (parts.Length < 4) { continue; } float x = Helper.ParseFloat(parts[1]); float y = Helper.ParseFloat(parts[2]); float z = Helper.ParseFloat(parts[3]); Vector3 vec = new Vector3(x, y, z).Normalized(); m_Normals.Add(vec); } break; case "vc": // vertex colour (non-standard "Extended OBJ" Blender plugin only) { if (parts.Length < 4) { continue; } float r = Helper.ParseFloat(parts[1]); float g = Helper.ParseFloat(parts[2]); float b = Helper.ParseFloat(parts[3]); Color vcolour = Color.FromArgb((int)(r * 255.0f), (int)(g * 255.0f), (int)(b * 255.0f)); m_Colours.Add(vcolour); } break; case "f": // face { if (parts.Length < 4) { continue; } int nvtx = parts.Length - 1; if (curmaterial != null) { // If a new object is defined but a material to use not set, we need to use the previous one and add // it to the current bone and its parent if (!m_Model.m_BoneTree.GetBoneByID(currentBone).GetRoot().m_MaterialsInBranch.Contains(curmaterial)) { m_Model.m_BoneTree.GetBoneByID(currentBone).GetRoot().m_MaterialsInBranch.Add(curmaterial); } if (!m_Model.m_BoneTree.GetBoneByID(currentBone).m_MaterialsInBranch.Contains(curmaterial)) { m_Model.m_BoneTree.GetBoneByID(currentBone).m_MaterialsInBranch.Add(curmaterial); } } else { // No "usemtl" command before declaring face curmaterial = "default_white"; AddWhiteMat(currentBone); } ModelBase.BoneDef bone = m_Model.m_BoneTree.GetBoneByID(currentBone); ModelBase.GeometryDef geomDef = bone.m_Geometries.Values.ElementAt(0); string polyListKey = "polylist-" + curmaterial; ModelBase.PolyListDef polyList; if (!geomDef.m_PolyLists.TryGetValue(polyListKey, out polyList)) { polyList = new ModelBase.PolyListDef(polyListKey, curmaterial); polyList.m_FaceLists.Add(new ModelBase.FaceListDef()); geomDef.m_PolyLists.Add(polyList.m_ID, polyList); } ModelBase.FaceDef face = new ModelBase.FaceDef(nvtx); for (int i = 0; i < nvtx; i++) { string vtx = parts[i + 1]; string[] idxs = vtx.Split(new char[] { '/' }); ModelBase.VertexDef vert = ModelBase.EMPTY_VERTEX; vert.m_Position = new Vector3(m_Vertices[int.Parse(idxs[0]) - 1].Xyz); if (m_Model.m_Materials[curmaterial].m_TextureDefID != null && idxs.Length >= 2 && idxs[1].Length > 0) { vert.m_TextureCoordinate = m_TexCoords[int.Parse(idxs[1]) - 1]; } else { vert.m_TextureCoordinate = null; } if (m_Model.m_Materials[curmaterial].m_Lights.Contains(true) && idxs.Length >= 3 && idxs[2].Trim().Length > 0) { vert.m_Normal = new Vector3(m_Normals[int.Parse(idxs[2]) - 1]); } else { vert.m_Normal = null; } // Vertex colours (non-standard "Extended OBJ" Blender plugin only) if (idxs.Length >= 4 && !idxs[3].Equals("")) { Color tmp = m_Colours[int.Parse(idxs[3]) - 1]; vert.m_VertexColour = Color.FromArgb(tmp.A, tmp.R, tmp.G, tmp.B); } else { vert.m_VertexColour = Color.White; } vert.m_VertexBoneIndex = currentBoneIndex; face.m_Vertices[i] = vert; } polyList.m_FaceLists[0].m_Faces.Add(face); } break; } } int count = 0; foreach (ModelBase.BoneDef boneDef in m_Model.m_BoneTree) { m_Model.m_BoneTransformsMap.Add(boneDef.m_ID, count); count++; } sr.Close(); m_Model.ScaleModel(scale); return(m_Model); }
public override ModelBase LoadModel(float scale) { foreach (BMD.ModelChunk mdchunk in m_BMD.m_ModelChunks) { ModelBase.BoneDef bone = new ModelBase.BoneDef(mdchunk.m_Name); bone.SetScale(mdchunk.m_20_12Scale); bone.SetRotation(mdchunk.m_4_12Rotation); bone.SetTranslation(mdchunk.m_20_12Translation); bone.m_Billboard = mdchunk.m_Billboard; if (mdchunk.m_ParentOffset == 0) { m_Model.m_BoneTree.AddRootBone(bone); } else { List <ModelBase.BoneDef> listOfBones = m_Model.m_BoneTree.GetAsList(); listOfBones[listOfBones.Count + mdchunk.m_ParentOffset].AddChild(bone); } m_Model.m_BoneTransformsMap.Add(bone.m_ID, m_Model.m_BoneTransformsMap.Count); ModelBase.GeometryDef geomDef = null; if (mdchunk.m_MatGroups.Length > 0) { geomDef = new ModelBase.GeometryDef("geometry-0"); bone.m_Geometries.Add(geomDef.m_ID, geomDef); } foreach (BMD.MaterialGroup matgroup in mdchunk.m_MatGroups) { string polyListKey = "polylist-" + matgroup.m_Name; ModelBase.PolyListDef polyListDef; if (!geomDef.m_PolyLists.TryGetValue(polyListKey, out polyListDef)) { polyListDef = new ModelBase.PolyListDef(polyListKey, matgroup.m_Name); geomDef.m_PolyLists.Add(polyListDef.m_ID, polyListDef); } ModelBase.MaterialDef material = new ModelBase.MaterialDef(matgroup.m_Name); material.m_Diffuse = matgroup.m_DiffuseColor; material.m_Ambient = matgroup.m_AmbientColor; material.m_Specular = matgroup.m_SpecularColor; material.m_Emission = matgroup.m_EmissionColor; bool hasTextures = (matgroup.m_Texture != null); if (hasTextures) { if (!m_Model.m_Textures.ContainsKey(matgroup.m_Texture.m_TextureName)) { ModelBase.TextureDefBase texture = new ModelBase.TextureDefNitro(matgroup.m_Texture); m_Model.m_Textures.Add(texture.m_ID, texture); } material.m_TextureDefID = matgroup.m_Texture.m_TextureName; } material.m_Alpha = matgroup.m_Alpha; if ((matgroup.m_PolyAttribs & 0xC0) == 0xC0) { material.m_PolygonDrawingFace = ModelBase.MaterialDef.PolygonDrawingFace.FrontAndBack; } else if ((matgroup.m_PolyAttribs & 0xC0) == 0x80) { material.m_PolygonDrawingFace = ModelBase.MaterialDef.PolygonDrawingFace.Front; } else if ((matgroup.m_PolyAttribs & 0xC0) == 0x40) { material.m_PolygonDrawingFace = ModelBase.MaterialDef.PolygonDrawingFace.Back; } material.m_TexGenMode = (ModelBase.TexGenMode)(matgroup.m_TexParams >> 30); material.m_TextureScale = matgroup.m_TexCoordScale; material.m_TextureRotation = matgroup.m_TexCoordRot; material.m_TextureTranslation = matgroup.m_TexCoordTrans; byte sRepeat = (byte)((matgroup.m_TexParams & 0x10000) >> 0x10); byte tRepeat = (byte)((matgroup.m_TexParams & 0x20000) >> 0x11); byte sFlip = (byte)((matgroup.m_TexParams & 0x40000) >> 0x12); byte tFlip = (byte)((matgroup.m_TexParams & 0x80000) >> 0x13); material.m_TexTiling[0] = (sRepeat == 1) ? ModelBase.MaterialDef.TexTiling.Repeat : ModelBase.MaterialDef.TexTiling.Clamp; material.m_TexTiling[0] = (sFlip == 1) ? ModelBase.MaterialDef.TexTiling.Flip : material.m_TexTiling[0]; material.m_TexTiling[1] = (tRepeat == 1) ? ModelBase.MaterialDef.TexTiling.Repeat : ModelBase.MaterialDef.TexTiling.Clamp; material.m_TexTiling[1] = (tFlip == 1) ? ModelBase.MaterialDef.TexTiling.Flip : material.m_TexTiling[1]; material.m_FogFlag = (matgroup.m_PolyAttribs & 0x8000) > 0; byte lights = (byte)(matgroup.m_PolyAttribs & 0x0F); for (int i = 0; i < 4; i++) { byte value = (byte)(lights >> i); material.m_Lights[i] = (value == 1); } Console.WriteLine("Materials Start"); if (!m_Model.m_Materials.ContainsKey(material.m_ID)) { m_Model.m_Materials.Add(material.m_ID, material); } Console.WriteLine("Materials End"); if (!bone.m_MaterialsInBranch.Contains(matgroup.m_Name)) { bone.m_MaterialsInBranch.Add(matgroup.m_Name); } ModelBase.BoneDef upToRoot = bone; while ((upToRoot = upToRoot.m_Parent) != null) { if (!upToRoot.m_MaterialsInBranch.Contains(matgroup.m_Name)) { upToRoot.m_MaterialsInBranch.Add(matgroup.m_Name); } } foreach (BMD.VertexList geometry in matgroup.m_Geometry) { uint polyType = geometry.m_PolyType; List <BMD.Vertex> vtxList = geometry.m_VertexList; switch (polyType) { case 0: //Separate Triangles { ModelBase.FaceListDef faceList = new ModelBase.FaceListDef(ModelBase.PolyListType.Triangles); int numFaces = vtxList.Count / 3; for (int a = 0, b = 0; a < numFaces; a++, b = b + 3) { ModelBase.FaceDef face = new ModelBase.FaceDef(3); face.m_Vertices[0] = new ModelBase.VertexDef(vtxList[b + 0].m_Position, vtxList[b + 0].m_TexCoord, vtxList[b + 0].m_Normal, vtxList[b + 0].m_Color, (int)matgroup.m_BoneIDs[vtxList[b + 0].m_MatrixID]); face.m_Vertices[1] = new ModelBase.VertexDef(vtxList[b + 1].m_Position, vtxList[b + 1].m_TexCoord, vtxList[b + 1].m_Normal, vtxList[b + 1].m_Color, (int)matgroup.m_BoneIDs[vtxList[b + 1].m_MatrixID]); face.m_Vertices[2] = new ModelBase.VertexDef(vtxList[b + 2].m_Position, vtxList[b + 2].m_TexCoord, vtxList[b + 2].m_Normal, vtxList[b + 2].m_Color, (int)matgroup.m_BoneIDs[vtxList[b + 2].m_MatrixID]); faceList.m_Faces.Add(face); } polyListDef.m_FaceLists.Add(faceList); break; } case 1: //Separate Quadrilaterals { ModelBase.FaceListDef faceList = new ModelBase.FaceListDef(ModelBase.PolyListType.Polygons); int numFaces = vtxList.Count / 4; for (int a = 0, b = 0; a < numFaces; a++, b = b + 4) { ModelBase.FaceDef face = new ModelBase.FaceDef(4); face.m_Vertices[0] = new ModelBase.VertexDef(vtxList[b + 0].m_Position, vtxList[b + 0].m_TexCoord, vtxList[b + 0].m_Normal, vtxList[b + 0].m_Color, (int)matgroup.m_BoneIDs[vtxList[b + 0].m_MatrixID]); face.m_Vertices[1] = new ModelBase.VertexDef(vtxList[b + 1].m_Position, vtxList[b + 1].m_TexCoord, vtxList[b + 1].m_Normal, vtxList[b + 1].m_Color, (int)matgroup.m_BoneIDs[vtxList[b + 1].m_MatrixID]); face.m_Vertices[2] = new ModelBase.VertexDef(vtxList[b + 2].m_Position, vtxList[b + 2].m_TexCoord, vtxList[b + 2].m_Normal, vtxList[b + 2].m_Color, (int)matgroup.m_BoneIDs[vtxList[b + 2].m_MatrixID]); face.m_Vertices[3] = new ModelBase.VertexDef(vtxList[b + 3].m_Position, vtxList[b + 3].m_TexCoord, vtxList[b + 3].m_Normal, vtxList[b + 3].m_Color, (int)matgroup.m_BoneIDs[vtxList[b + 3].m_MatrixID]); faceList.m_Faces.Add(face); } polyListDef.m_FaceLists.Add(faceList); break; } case 2: //Triangle Strips { //3+(N-1) vertices per N triangles //(N-3)+1 Triangles per N Vertices int numFaces = vtxList.Count - 2; if (vtxList.Count < 3) //Should never be { break; } ModelBase.FaceListDef faceList = new ModelBase.FaceListDef(ModelBase.PolyListType.TriangleStrip); //Convert all faces with more than 3 vertices to ones with only 3 for (int n = 0; n < numFaces; n++) { if (n % 2 == 0) { ModelBase.FaceDef face = new ModelBase.FaceDef(3); face.m_Vertices[0] = new ModelBase.VertexDef(vtxList[n + 0].m_Position, vtxList[n + 0].m_TexCoord, vtxList[n + 0].m_Normal, vtxList[n + 0].m_Color, (int)matgroup.m_BoneIDs[vtxList[n + 0].m_MatrixID]); face.m_Vertices[1] = new ModelBase.VertexDef(vtxList[n + 1].m_Position, vtxList[n + 1].m_TexCoord, vtxList[n + 1].m_Normal, vtxList[n + 1].m_Color, (int)matgroup.m_BoneIDs[vtxList[n + 1].m_MatrixID]); face.m_Vertices[2] = new ModelBase.VertexDef(vtxList[n + 2].m_Position, vtxList[n + 2].m_TexCoord, vtxList[n + 2].m_Normal, vtxList[n + 2].m_Color, (int)matgroup.m_BoneIDs[vtxList[n + 2].m_MatrixID]); faceList.m_Faces.Add(face); } else { ModelBase.FaceDef face = new ModelBase.FaceDef(3); face.m_Vertices[0] = new ModelBase.VertexDef(vtxList[n + 2].m_Position, vtxList[n + 2].m_TexCoord, vtxList[n + 2].m_Normal, vtxList[n + 2].m_Color, (int)matgroup.m_BoneIDs[vtxList[n + 2].m_MatrixID]); face.m_Vertices[1] = new ModelBase.VertexDef(vtxList[n + 1].m_Position, vtxList[n + 1].m_TexCoord, vtxList[n + 1].m_Normal, vtxList[n + 1].m_Color, (int)matgroup.m_BoneIDs[vtxList[n + 1].m_MatrixID]); face.m_Vertices[2] = new ModelBase.VertexDef(vtxList[n + 0].m_Position, vtxList[n + 0].m_TexCoord, vtxList[n + 0].m_Normal, vtxList[n + 0].m_Color, (int)matgroup.m_BoneIDs[vtxList[n + 0].m_MatrixID]); faceList.m_Faces.Add(face); } //Because of how normals are defined in triangle strips, every 2nd triangle is clockwise, whereas all others are anti-clockwise } polyListDef.m_FaceLists.Add(faceList); break; } case 3: //Quadrilateral Strips { //4+(N-1)*2 vertices per N quads //((N-4)/2) + 1 Quads. per N Vertices int numFaces = ((vtxList.Count - 4) / 2) + 1; if (vtxList.Count < 4) //Should never be { break; } ModelBase.FaceListDef faceList = new ModelBase.FaceListDef(ModelBase.PolyListType.Polygons); for (int n = 0, p = 0; n < numFaces; n++, p = p + 2) { ModelBase.FaceDef face = new ModelBase.FaceDef(4); face.m_Vertices[0] = new ModelBase.VertexDef(vtxList[p + 0].m_Position, vtxList[p + 0].m_TexCoord, vtxList[p + 0].m_Normal, vtxList[p + 0].m_Color, (int)matgroup.m_BoneIDs[vtxList[p + 0].m_MatrixID]); face.m_Vertices[1] = new ModelBase.VertexDef(vtxList[p + 1].m_Position, vtxList[p + 1].m_TexCoord, vtxList[p + 1].m_Normal, vtxList[p + 1].m_Color, (int)matgroup.m_BoneIDs[vtxList[p + 1].m_MatrixID]); face.m_Vertices[2] = new ModelBase.VertexDef(vtxList[p + 3].m_Position, vtxList[p + 3].m_TexCoord, vtxList[p + 3].m_Normal, vtxList[p + 3].m_Color, (int)matgroup.m_BoneIDs[vtxList[p + 3].m_MatrixID]); face.m_Vertices[3] = new ModelBase.VertexDef(vtxList[p + 2].m_Position, vtxList[p + 2].m_TexCoord, vtxList[p + 2].m_Normal, vtxList[p + 2].m_Color, (int)matgroup.m_BoneIDs[vtxList[p + 2].m_MatrixID]); faceList.m_Faces.Add(face); } polyListDef.m_FaceLists.Add(faceList); break; } default: MessageBox.Show("Unknown polygon type."); break; }//End polyType switch } } bone.CalculateBranchTransformations(); } m_Model.ApplyTransformations(); return(m_Model); }
protected void ReadNodes(XmlNode node_array, XmlNode polygon_array, XmlNode matrix_array) { if (node_array == null) return; int nodeArray_size = int.Parse(node_array.Attributes["size"].Value); if (nodeArray_size < 1) return; XmlNodeList nodes = node_array.SelectNodes("node"); foreach (XmlNode node in nodes) m_OriginalNodeIndices.Add(int.Parse(node.Attributes["index"].Value), node.Attributes["name"].Value); ReadMatrices(matrix_array, m_OriginalNodeIndices); var queue = new Queue<XmlNode>(); var geometryQueue = new Queue<XmlNode>(); queue.Enqueue(nodes[0]); while (queue.Count > 0) { XmlNode node = queue.Dequeue(); int index = int.Parse(node.Attributes["index"].Value); string name = node.Attributes["name"].Value; string kind = node.Attributes["kind"].Value; int parent = int.Parse(node.Attributes["parent"].Value); int child = int.Parse(node.Attributes["child"].Value); int brother_next = int.Parse(node.Attributes["brother_next"].Value); int brother_prev = int.Parse(node.Attributes["brother_prev"].Value); bool draw_mtx = node.Attributes["draw_mtx"].Value.Equals("on"); string scale_compensate = (node.Attributes["scale_compensate"] != null) ? node.Attributes["scale_compensate"].Value : null; string billboard = node.Attributes["billboard"].Value; // Either "on", "off" or "y_on" float[] scale = Array.ConvertAll( node.Attributes["scale"].Value.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries), Convert.ToSingle); float[] rotate = Array.ConvertAll( node.Attributes["rotate"].Value.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries), Convert.ToSingle); float[] translate = Array.ConvertAll( node.Attributes["translate"].Value.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries), Convert.ToSingle); bool visibility = node.Attributes["visibility"].Value.Equals("on"); int display_size = int.Parse(node.Attributes["display_size"].Value); int vertex_size = (kind.Equals("mesh")) ? int.Parse(node.Attributes["vertex_size"].Value) : -1; int polygon_size = (kind.Equals("mesh")) ? int.Parse(node.Attributes["polygon_size"].Value) : -1; int triangle_size = (kind.Equals("mesh")) ? int.Parse(node.Attributes["triangle_size"].Value) : -1; int quad_size = (kind.Equals("mesh")) ? int.Parse(node.Attributes["quad_size"].Value) : -1; float[] volume_min = (kind.Equals("mesh")) ? Array.ConvertAll( node.Attributes["volume_min"].Value.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries), Convert.ToSingle) : null; float[] volume_max = (kind.Equals("mesh")) ? Array.ConvertAll( node.Attributes["volume_max"].Value.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries), Convert.ToSingle) : null; float volume_r = (kind.Equals("mesh")) ? float.Parse(node.Attributes["volume_r"].Value) : -1; ModelBase.BoneDef boneDef = new ModelBase.BoneDef(name); boneDef.SetScale(new Vector3(scale[0], scale[1], scale[2])); boneDef.SetRotation(new Vector3(rotate[0] * Helper.Deg2Rad, rotate[1] * Helper.Deg2Rad, rotate[2] * Helper.Deg2Rad)); boneDef.SetTranslation(new Vector3(translate[0], translate[1], translate[2])); boneDef.CalculateBranchTransformations(); if (display_size > 0) { geometryQueue.Enqueue(node); } if (parent == -1) m_Model.m_BoneTree.AddRootBone(boneDef); else m_Model.m_BoneTree.GetBoneByID(m_OriginalNodeIndices[parent]).AddChild(boneDef); /* Child node takes priority and siblings are stored consecutively by name in alphanumerical order * (a→z and 0→9). The model root node must be the first <node> in <node_array> (index 0). * "child" attribute gives first child, alphanumerically. */ if (child != -1) queue.Enqueue(nodes[child]); if (brother_next != -1) queue.Enqueue(nodes[brother_next]); } // In oder to correctly read the geometry we need to already have the list of bones read in so that bone ID's // can be assigned to vertices while (geometryQueue.Count > 0) { XmlNode node = geometryQueue.Dequeue(); XmlNodeList displays = node.SelectNodes("display"); ModelBase.BoneDef boneDef = m_Model.m_BoneTree.GetBoneByID(node.Attributes["name"].Value); ModelBase.GeometryDef geometryDef = new ModelBase.GeometryDef("geometry-0"); foreach (XmlNode display in displays) { int display_index = int.Parse(display.Attributes["index"].Value); int display_material = int.Parse(display.Attributes["material"].Value); int display_polygon = int.Parse(display.Attributes["polygon"].Value); int display_priority = int.Parse(display.Attributes["priority"].Value); ReadPolygon(display_polygon, polygon_array, m_Model.m_Materials.ElementAt(display_material).Key, geometryDef); boneDef.m_MaterialsInBranch.Add(m_Model.m_Materials.ElementAt(display_material).Key); } boneDef.m_Geometries.Add(geometryDef.m_ID, geometryDef); } m_Model.ApplyTransformations(); }
public override ModelBase LoadModel(OpenTK.Vector3 scale) { foreach (BMD.ModelChunk mdchunk in m_BMD.m_ModelChunks) { ModelBase.BoneDef bone = new ModelBase.BoneDef(mdchunk.m_Name); bone.SetScale(mdchunk.m_20_12Scale); bone.SetRotation(mdchunk.m_4_12Rotation); bone.SetTranslation(mdchunk.m_20_12Translation); if (mdchunk.m_ParentOffset == 0) { m_Model.m_BoneTree.AddRootBone(bone); } else { List<ModelBase.BoneDef> listOfBones = m_Model.m_BoneTree.GetAsList(); listOfBones[listOfBones.Count + mdchunk.m_ParentOffset].AddChild(bone); } ModelBase.GeometryDef geomDef = null; if (mdchunk.m_MatGroups.Length > 0) { geomDef = new ModelBase.GeometryDef("geometry-0"); bone.m_Geometries.Add(geomDef.m_ID, geomDef); } foreach (BMD.MaterialGroup matgroup in mdchunk.m_MatGroups) { if (!geomDef.m_PolyLists.ContainsKey(matgroup.m_Name)) { ModelBase.PolyListDef pld = new ModelBase.PolyListDef("polylist-" + matgroup.m_Name, matgroup.m_Name); geomDef.m_PolyLists.Add(pld.m_MaterialName, pld); } ModelBase.PolyListDef polyListDef = geomDef.m_PolyLists[matgroup.m_Name]; ModelBase.MaterialDef material = new ModelBase.MaterialDef(matgroup.m_Name, m_Model.m_Materials.Count); material.m_Diffuse = matgroup.m_DiffuseColor; material.m_Ambient = matgroup.m_AmbientColor; material.m_Specular = matgroup.m_SpecularColor; material.m_Emission = matgroup.m_EmissionColor; bool hasTextures = (matgroup.m_Texture != null); if (hasTextures) { if (!m_Model.m_Textures.ContainsKey(matgroup.m_Texture.m_TexName)) { ModelBase.TextureDefBase texture = new ModelBase.TextureDefInMemoryBitmap( matgroup.m_Texture.m_TexName, ConvertBMDTextureToBitmap(matgroup.m_Texture)); m_Model.m_Textures.Add(texture.m_ID, texture); } material.m_TextureDefID = matgroup.m_Texture.m_TexName; } material.m_Alpha = matgroup.m_Alpha; if ((matgroup.m_PolyAttribs & 0xC0) == 0xC0) material.m_PolygonDrawingFace = ModelBase.MaterialDef.PolygonDrawingFace.FrontAndBack; else if ((matgroup.m_PolyAttribs & 0xC0) == 0x80) material.m_PolygonDrawingFace = ModelBase.MaterialDef.PolygonDrawingFace.Front; else if ((matgroup.m_PolyAttribs & 0xC0) == 0x40) material.m_PolygonDrawingFace = ModelBase.MaterialDef.PolygonDrawingFace.Back; if (!m_Model.m_Materials.ContainsKey(material.m_ID)) m_Model.m_Materials.Add(material.m_ID, material); bone.m_MaterialsInBranch.Add(matgroup.m_Name); ModelBase.BoneDef upToRoot = bone; while ((upToRoot = upToRoot.m_Parent) != null) { if (!upToRoot.m_MaterialsInBranch.Contains(matgroup.m_Name)) upToRoot.m_MaterialsInBranch.Add(matgroup.m_Name); } foreach (BMD.VertexList geometry in matgroup.m_Geometry) { uint polyType = geometry.m_PolyType; List<BMD.Vertex> vtxList = geometry.m_VertexList; switch (polyType) { case 0://Separate Triangles { ModelBase.FaceListDef faceList = new ModelBase.FaceListDef(ModelBase.PolyListType.Triangles); if (vtxList.Count <= 3)//Just 1 triangle { ModelBase.FaceDef face = new ModelBase.FaceDef(3); face.m_Vertices[0] = new ModelBase.VertexDef(vtxList[0].m_Position, vtxList[0].m_TexCoord, vtxList[0].m_Normal, vtxList[0].m_Color, (int)matgroup.m_BoneIDs[vtxList[0].m_MatrixID]); face.m_Vertices[1] = new ModelBase.VertexDef(vtxList[1].m_Position, vtxList[1].m_TexCoord, vtxList[1].m_Normal, vtxList[1].m_Color, (int)matgroup.m_BoneIDs[vtxList[1].m_MatrixID]); face.m_Vertices[2] = new ModelBase.VertexDef(vtxList[2].m_Position, vtxList[2].m_TexCoord, vtxList[2].m_Normal, vtxList[2].m_Color, (int)matgroup.m_BoneIDs[vtxList[2].m_MatrixID]); faceList.m_Faces.Add(face); } else if (vtxList.Count > 3 && (float)vtxList.Count % 3 == 0.0f)//Eg. 9 vertices in 3 triangles { int numFaces = vtxList.Count / 3; for (int a = 0, b = 0; a < numFaces; a++, b = b + 3) { ModelBase.FaceDef face = new ModelBase.FaceDef(3); face.m_Vertices[0] = new ModelBase.VertexDef(vtxList[b + 0].m_Position, vtxList[b + 0].m_TexCoord, vtxList[b + 0].m_Normal, vtxList[b + 0].m_Color, (int)matgroup.m_BoneIDs[vtxList[b + 0].m_MatrixID]); face.m_Vertices[1] = new ModelBase.VertexDef(vtxList[b + 1].m_Position, vtxList[b + 1].m_TexCoord, vtxList[b + 1].m_Normal, vtxList[b + 1].m_Color, (int)matgroup.m_BoneIDs[vtxList[b + 1].m_MatrixID]); face.m_Vertices[2] = new ModelBase.VertexDef(vtxList[b + 2].m_Position, vtxList[b + 2].m_TexCoord, vtxList[b + 2].m_Normal, vtxList[b + 2].m_Color, (int)matgroup.m_BoneIDs[vtxList[b + 2].m_MatrixID]); faceList.m_Faces.Add(face); } } polyListDef.m_FaceLists.Add(faceList); break; } case 1://Separate Quadrilaterals { ModelBase.FaceListDef faceList = new ModelBase.FaceListDef(ModelBase.PolyListType.Polygons); if (vtxList.Count <= 4)//Just 1 quadrilateral { ModelBase.FaceDef face = new ModelBase.FaceDef(4); face.m_Vertices[0] = new ModelBase.VertexDef(vtxList[0].m_Position, vtxList[0].m_TexCoord, vtxList[0].m_Normal, vtxList[0].m_Color, (int)matgroup.m_BoneIDs[vtxList[0].m_MatrixID]); face.m_Vertices[1] = new ModelBase.VertexDef(vtxList[1].m_Position, vtxList[1].m_TexCoord, vtxList[1].m_Normal, vtxList[1].m_Color, (int)matgroup.m_BoneIDs[vtxList[1].m_MatrixID]); face.m_Vertices[2] = new ModelBase.VertexDef(vtxList[2].m_Position, vtxList[2].m_TexCoord, vtxList[2].m_Normal, vtxList[2].m_Color, (int)matgroup.m_BoneIDs[vtxList[2].m_MatrixID]); face.m_Vertices[3] = new ModelBase.VertexDef(vtxList[3].m_Position, vtxList[3].m_TexCoord, vtxList[3].m_Normal, vtxList[3].m_Color, (int)matgroup.m_BoneIDs[vtxList[3].m_MatrixID]); faceList.m_Faces.Add(face); } else if (vtxList.Count > 4 && (float)vtxList.Count % 4 == 0.0f)//Eg. 8 vertices in 2 quadrilaterals { int numFaces = vtxList.Count / 4; for (int a = 0, b = 0; a < numFaces; a++, b = b + 4) { ModelBase.FaceDef face = new ModelBase.FaceDef(4); face.m_Vertices[0] = new ModelBase.VertexDef(vtxList[b + 0].m_Position, vtxList[b + 0].m_TexCoord, vtxList[b + 0].m_Normal, vtxList[b + 0].m_Color, (int)matgroup.m_BoneIDs[vtxList[b + 0].m_MatrixID]); face.m_Vertices[1] = new ModelBase.VertexDef(vtxList[b + 1].m_Position, vtxList[b + 1].m_TexCoord, vtxList[b + 1].m_Normal, vtxList[b + 1].m_Color, (int)matgroup.m_BoneIDs[vtxList[b + 1].m_MatrixID]); face.m_Vertices[2] = new ModelBase.VertexDef(vtxList[b + 2].m_Position, vtxList[b + 2].m_TexCoord, vtxList[b + 2].m_Normal, vtxList[b + 2].m_Color, (int)matgroup.m_BoneIDs[vtxList[b + 2].m_MatrixID]); face.m_Vertices[3] = new ModelBase.VertexDef(vtxList[b + 3].m_Position, vtxList[b + 3].m_TexCoord, vtxList[b + 3].m_Normal, vtxList[b + 3].m_Color, (int)matgroup.m_BoneIDs[vtxList[b + 3].m_MatrixID]); faceList.m_Faces.Add(face); } } polyListDef.m_FaceLists.Add(faceList); break; } case 2://Triangle Strips { //3+(N-1) vertices per N triangles //(N-3)+1 Triangles per N Vertices int numFaces = vtxList.Count - 2; if (vtxList.Count < 3)//Should never be break; ModelBase.FaceListDef faceList = new ModelBase.FaceListDef(ModelBase.PolyListType.TriangleStrip); //Convert all faces with more than 3 vertices to ones with only 3 for (int n = 0; n < numFaces; n++) { if (n % 2 == 0) { ModelBase.FaceDef face = new ModelBase.FaceDef(3); face.m_Vertices[0] = new ModelBase.VertexDef(vtxList[n + 0].m_Position, vtxList[n + 0].m_TexCoord, vtxList[n + 0].m_Normal, vtxList[n + 0].m_Color, (int)matgroup.m_BoneIDs[vtxList[n + 0].m_MatrixID]); face.m_Vertices[1] = new ModelBase.VertexDef(vtxList[n + 1].m_Position, vtxList[n + 1].m_TexCoord, vtxList[n + 1].m_Normal, vtxList[n + 1].m_Color, (int)matgroup.m_BoneIDs[vtxList[n + 1].m_MatrixID]); face.m_Vertices[2] = new ModelBase.VertexDef(vtxList[n + 2].m_Position, vtxList[n + 2].m_TexCoord, vtxList[n + 2].m_Normal, vtxList[n + 2].m_Color, (int)matgroup.m_BoneIDs[vtxList[n + 2].m_MatrixID]); faceList.m_Faces.Add(face); } else { ModelBase.FaceDef face = new ModelBase.FaceDef(3); face.m_Vertices[0] = new ModelBase.VertexDef(vtxList[n + 2].m_Position, vtxList[n + 2].m_TexCoord, vtxList[n + 2].m_Normal, vtxList[n + 2].m_Color, (int)matgroup.m_BoneIDs[vtxList[n + 2].m_MatrixID]); face.m_Vertices[1] = new ModelBase.VertexDef(vtxList[n + 1].m_Position, vtxList[n + 1].m_TexCoord, vtxList[n + 2].m_Normal, vtxList[n + 1].m_Color, (int)matgroup.m_BoneIDs[vtxList[n + 1].m_MatrixID]); face.m_Vertices[2] = new ModelBase.VertexDef(vtxList[n + 0].m_Position, vtxList[n + 0].m_TexCoord, vtxList[n + 0].m_Normal, vtxList[n + 0].m_Color, (int)matgroup.m_BoneIDs[vtxList[n + 0].m_MatrixID]); faceList.m_Faces.Add(face); } //Because of how normals are defined in triangle strips, every 2nd triangle is clockwise, whereas all others are anti-clockwise } polyListDef.m_FaceLists.Add(faceList); break; } case 3://Quadrilateral Strips { //4+(N-1)*2 vertices per N quads //((N-4)/2) + 1 Quads. per N Vertices int numFaces = ((vtxList.Count - 4) / 2) + 1; if (vtxList.Count < 4)//Should never be break; ModelBase.FaceListDef faceList = new ModelBase.FaceListDef(); for (int n = 0, p = 0; n < numFaces; n++, p = p + 2) { ModelBase.FaceDef face = new ModelBase.FaceDef(4); face.m_Vertices[0] = new ModelBase.VertexDef(vtxList[p + 0].m_Position, vtxList[p + 0].m_TexCoord, vtxList[p + 0].m_Normal, vtxList[p + 0].m_Color, (int)matgroup.m_BoneIDs[vtxList[p + 0].m_MatrixID]); face.m_Vertices[1] = new ModelBase.VertexDef(vtxList[p + 1].m_Position, vtxList[p + 1].m_TexCoord, vtxList[p + 1].m_Normal, vtxList[p + 1].m_Color, (int)matgroup.m_BoneIDs[vtxList[p + 1].m_MatrixID]); face.m_Vertices[2] = new ModelBase.VertexDef(vtxList[p + 3].m_Position, vtxList[p + 3].m_TexCoord, vtxList[p + 3].m_Normal, vtxList[p + 3].m_Color, (int)matgroup.m_BoneIDs[vtxList[p + 3].m_MatrixID]); face.m_Vertices[3] = new ModelBase.VertexDef(vtxList[p + 2].m_Position, vtxList[p + 2].m_TexCoord, vtxList[p + 2].m_Normal, vtxList[p + 2].m_Color, (int)matgroup.m_BoneIDs[vtxList[p + 2].m_MatrixID]); faceList.m_Faces.Add(face); } polyListDef.m_FaceLists.Add(faceList); break; } default: MessageBox.Show("Unknown polygon type."); break; }//End polyType switch } } bone.CalculateBranchTransformations(); } m_Model.ApplyTransformations(); return m_Model; }