Пример #1
0
        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);
        }
Пример #2
0
        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);
            }
        }
Пример #4
0
        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);
        }
Пример #5
0
        public override void WriteModel(bool save = true)
        {
            StreamWriter objWriter    = new StreamWriter(m_ModelFileName);
            StreamWriter mtlWriter    = new StreamWriter(m_ModelFileName.Substring(0, m_ModelFileName.Length - 4) + ".mtl");
            string       dir          = Path.GetDirectoryName(m_ModelFileName);
            string       baseFileName = Path.GetFileNameWithoutExtension(m_ModelFileName);

            objWriter.Write("#" + Program.AppTitle + " " + Program.AppVersion + " " + Program.AppDate + "\n\n");
            objWriter.Write("mtllib " + baseFileName + ".mtl" + "\n\n");    // Specify name of material library
            objWriter.Write("bonelib " + baseFileName + ".bones" + "\n\n"); // Specify name of bones list

            // OBJ does not support skinning, bones or vertex-specific object assignment so instead we use the bone ID
            // specified in the first vertex of each face to assign that whole face to an object
            int boneIndex = 0;
            List <ModelBase.BoneDef> flatBoneList = m_Model.m_BoneTree.GetAsList();

            foreach (ModelBase.BoneDef bone in m_Model.m_BoneTree)
            {
                foreach (ModelBase.GeometryDef geometry in bone.m_Geometries.Values)
                {
                    foreach (ModelBase.PolyListDef polyList in geometry.m_PolyLists.Values)
                    {
                        int fl = 0;
                        while (fl < polyList.m_FaceLists.Count)
                        {
                            ModelBase.FaceListDef faceList = polyList.m_FaceLists[fl];

                            int f     = 0;
                            int count = faceList.m_Faces.Count;
                            while (f < faceList.m_Faces.Count)
                            {
                                ModelBase.FaceDef face = faceList.m_Faces[f];

                                int objSplitBoneID = face.m_Vertices[0].m_VertexBoneIndex;
                                if (objSplitBoneID != boneIndex)
                                {
                                    ModelBase.BoneDef newBone = flatBoneList[objSplitBoneID];
                                    // For models using "areas" (multiple-parent bones) the vertices all seem to be
                                    // assigned to the first parent bone. We don't want to move faces about in such
                                    // cases so only move faces between bones within the same branch.
                                    if (bone.GetBranch().Contains(newBone))
                                    {
                                        if (!newBone.m_Geometries.ContainsKey(geometry.m_ID))
                                        {
                                            newBone.m_Geometries.Add(geometry.m_ID, new ModelBase.GeometryDef(geometry.m_ID));
                                        }
                                        if (!newBone.m_Geometries[geometry.m_ID].m_PolyLists.ContainsKey(polyList.m_MaterialName))
                                        {
                                            ModelBase.PolyListDef tmp = new ModelBase.PolyListDef(polyList.m_ID, polyList.m_MaterialName);
                                            tmp.m_FaceLists.Add(new ModelBase.FaceListDef());
                                            newBone.m_Geometries[geometry.m_ID].m_PolyLists.Add(polyList.m_MaterialName, tmp);
                                        }
                                        if (!newBone.m_MaterialsInBranch.Contains(polyList.m_MaterialName))
                                        {
                                            newBone.m_MaterialsInBranch.Add(polyList.m_MaterialName);
                                        }

                                        newBone.m_Geometries[geometry.m_ID].m_PolyLists[polyList.m_MaterialName].m_FaceLists[0].m_Faces.Add(face);
                                        faceList.m_Faces.RemoveAt(f);
                                    }
                                }

                                f++;
                            }

                            fl++;
                        }
                    }
                }

                boneIndex++;
            }

            // Write mtllib
            foreach (ModelBase.MaterialDef material in m_Model.m_Materials.Values)
            {
                //For every texture,
                string textureName = (material.m_TextureDefID != null) ? m_Model.m_Textures[material.m_TextureDefID].m_ID : null;
                //Create new material
                mtlWriter.Write("newmtl " /*+ ((i * 2) + j)*/ + material.m_ID + "\n");
                //Specify ambient colour - RGB 0-1
                mtlWriter.Write("Ka " + Helper.ToString(material.m_Ambient.R / 255.0f) +
                                " " + Helper.ToString(material.m_Ambient.G / 255.0f) +
                                " " + Helper.ToString(material.m_Ambient.B / 255.0f) + "\n");
                //Specify diffuse colour - RGB 0-1
                mtlWriter.Write("Kd " + Helper.ToString(material.m_Diffuse.R / 255.0f) +
                                " " + Helper.ToString(material.m_Diffuse.G / 255.0f) +
                                " " + Helper.ToString(material.m_Diffuse.B / 255.0f) + "\n");
                //Specify specular colour - RGB 0-1
                mtlWriter.Write("Ks " + Helper.ToString(material.m_Specular.R / 255.0f) +
                                " " + Helper.ToString(material.m_Specular.G / 255.0f) +
                                " " + Helper.ToString(material.m_Specular.B / 255.0f) + "\n");
                //Specify specular colour co-efficient - RGB 0-1
                //mtllib += "Ns " + material.m_SpeEmiColors + "\n";
                //Specify transparency - RGB Alpha channel 0-1
                mtlWriter.Write("d " + Helper.ToString(material.m_Alpha / 31f) + "\n");
                //Specify texture type 0 - 10
                //uint textype = (currentTexture.m_Params >> 26) & 0x7;
                mtlWriter.Write("illum 2\n");
                if (textureName != null && !textureName.Equals(""))
                {
                    //Specify name of texture image
                    mtlWriter.Write("map_Kd " + textureName + ".png" + "\n\n");
                    ExportTextureToPNG(dir, m_Model.m_Textures[material.m_TextureDefID]);
                }
                else
                {
                    mtlWriter.Write("\n\n");
                }
            }

            WriteBonesFileOBJ(m_ModelFileName.Substring(0, m_ModelFileName.Length - 4) + ".bones", m_Model.m_BoneTree);

            // Write each bone to file as a separate mesh/object using o command
            List <Vector3> verts         = new List <Vector3>();
            List <Vector2> textureCoords = new List <Vector2>();
            List <Color>   vertexColours = new List <Color>();

            foreach (ModelBase.BoneDef bone in m_Model.m_BoneTree)
            {
                objWriter.Write("o " + bone.m_ID + "\n");

                // Get a list of all verices and texture co-ordinates for the current bone
                List <Vector3> vertsCurBone         = new List <Vector3>();
                List <Vector2> textureCoordsCurBone = new List <Vector2>();
                List <Color>   vertexColoursCurBone = new List <Color>();

                foreach (ModelBase.GeometryDef geometry in bone.m_Geometries.Values)
                {
                    foreach (ModelBase.PolyListDef polyList in geometry.m_PolyLists.Values)
                    {
                        foreach (ModelBase.FaceListDef faceList in polyList.m_FaceLists)
                        {
                            foreach (ModelBase.FaceDef face in faceList.m_Faces)
                            {
                                foreach (ModelBase.VertexDef vert in face.m_Vertices)
                                {
                                    if (!vertsCurBone.Contains(vert.m_Position))
                                    {
                                        vertsCurBone.Add(vert.m_Position);
                                        verts.Add(vert.m_Position);
                                    }
                                    if (vert.m_TextureCoordinate != null && !textureCoordsCurBone.Contains((Vector2)vert.m_TextureCoordinate))
                                    {
                                        textureCoordsCurBone.Add((Vector2)vert.m_TextureCoordinate);
                                        textureCoords.Add((Vector2)vert.m_TextureCoordinate);
                                    }
                                    if (vert.m_VertexColour != null && !vertexColoursCurBone.Contains((Color)vert.m_VertexColour))
                                    {
                                        vertexColoursCurBone.Add((Color)vert.m_VertexColour);
                                        vertexColours.Add((Color)vert.m_VertexColour);
                                    }
                                }
                            }
                        }
                    }
                }

                // Print a list of all vertices, texture co-ordinates and vertex colours
                foreach (Vector3 vert in vertsCurBone)
                {
                    objWriter.Write("v " + Helper.ToString(vert.X) + " " + Helper.ToString(vert.Y) + " " + Helper.ToString(vert.Z) + "\n");
                }
                foreach (Vector2 textureCoord in textureCoordsCurBone)
                {
                    objWriter.Write("vt " + Helper.ToString(textureCoord.X) + " " + Helper.ToString(textureCoord.Y) + "\n");
                }
                foreach (Color vColour in vertexColoursCurBone)
                {
                    objWriter.Write("vc " + Helper.ToString(vColour.R / 255.0f) + " " + Helper.ToString(vColour.G / 255.0f) + " " +
                                    Helper.ToString(vColour.B / 255.0f) + "\n");
                }

                // For each material used in the current bone, print all faces
                foreach (ModelBase.GeometryDef geometry in bone.m_Geometries.Values)
                {
                    foreach (ModelBase.PolyListDef polyList in geometry.m_PolyLists.Values)
                    {
                        objWriter.Write("usemtl " + polyList.m_MaterialName + "\n");

                        foreach (ModelBase.FaceListDef faceList in polyList.m_FaceLists)
                        {
                            foreach (ModelBase.FaceDef face in faceList.m_Faces)
                            {
                                // Each face is a triangle or a quad, as they have already been extracted individually from
                                // the vertex lists
                                // Note: Indices start at 1 in OBJ
                                int numVerticesInFace = face.m_NumVertices;

                                objWriter.Write("f ");
                                foreach (ModelBase.VertexDef vert in face.m_Vertices)
                                {
                                    objWriter.Write((verts.LastIndexOf(vert.m_Position) + 1) +
                                                    "/" + ((vert.m_TextureCoordinate != null) ?
                                                           (textureCoords.LastIndexOf((Vector2)vert.m_TextureCoordinate) + 1).ToString() : "") +
                                                    "//" + ((vert.m_VertexColour != null) ?
                                                            (vertexColours.LastIndexOf((Color)vert.m_VertexColour) + 1).ToString() : "") + " ");
                                }
                                objWriter.Write("\n");
                            }
                        }
                    }
                }
            }

            objWriter.Close();
            mtlWriter.Close();
        }
Пример #6
0
        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);
        }
Пример #7
0
        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);
        }
Пример #8
0
        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;
        }
Пример #9
0
        Tuple<ModelBase.FaceListDef, List<int>> GetStripAndIndicesForStartingEvenEdge(
            TriangleLinked start, TriangleEdge startForwardEdge)
        {
            List<int> stripIndices = new List<int>();
            List<TriangleRotation> stripRotations = new List<TriangleRotation>();

            List<TriangleLinked> linked = GetLinked(start)[(int)startForwardEdge];
            TriangleLinked bestNeighbour = DetermineBestNextNeighbour(start, linked, startForwardEdge);

            if (bestNeighbour == null)
                return new Tuple<ModelBase.FaceListDef, List<int>>(new ModelBase.FaceListDef(), new List<int>());

            TriangleRotation startRotation = (TriangleRotation)((int)(startForwardEdge - TriangleEdge.Edge_BC + 3) % 3);

            TriangleLinked t = start;
            TriangleEdge currentEdge = startForwardEdge;
            TriangleRotation currentRotation = startRotation;
            bool even = true;
            int index_t = -1;
            while (t != null && !stripIndices.Contains((index_t = m_Triangles.IndexOf(t))))
            {
                stripIndices.Add(index_t);
                stripRotations.Add(currentRotation);

                linked = GetLinked(t)[(int)currentEdge];
                bestNeighbour = DetermineBestNextNeighbour(t, linked, currentEdge);

                t = bestNeighbour;

                even = !even;

                if (t != null)
                {
                    // Determine rotation and the edge to be used to get the next face

                    ModelBase.FaceDef triangleC_CW = new ModelBase.FaceDef(3);
                    if (even)
                    {
                        triangleC_CW.m_Vertices[0] = t.m_Triangle.m_Vertices[0];
                        triangleC_CW.m_Vertices[1] = t.m_Triangle.m_Vertices[1];
                        triangleC_CW.m_Vertices[2] = t.m_Triangle.m_Vertices[2];
                    }
                    else
                    {
                        triangleC_CW.m_Vertices[0] = t.m_Triangle.m_Vertices[2];
                        triangleC_CW.m_Vertices[1] = t.m_Triangle.m_Vertices[1];
                        triangleC_CW.m_Vertices[2] = t.m_Triangle.m_Vertices[0];
                    }

                    // The edge of the vertices which match the preceding triangle's
                    TriangleEdge linkBackEdge = TriangleEdge.Edge_AB;
                    // The vertices which match the preceding triangle's
                    ModelBase.VertexDef[] currentMatchedEdge = new ModelBase.VertexDef[2];
                    TriangleLinked previous = m_Triangles[stripIndices[stripIndices.Count - 1]];
                    currentMatchedEdge[0] = previous.m_Triangle.m_Vertices[(int)(currentEdge + 0) % 3];
                    currentMatchedEdge[1] = previous.m_Triangle.m_Vertices[(int)(currentEdge + 1) % 3];
                    // Find the edge in the current triangle which if odd has been made CW which matches
                    // that from the preceding triangle. This will be set as the current triangle's first,
                    // or 'AB' edge and the next edge (next two vertices) will be used to match the next
                    // triangle.
                    for (int i = 0; i < 3; i++)
                    {
                        ModelBase.VertexDef[] edge = new ModelBase.VertexDef[2];
                        edge[0] = triangleC_CW.m_Vertices[(i + 0) % 3];
                        edge[1] = triangleC_CW.m_Vertices[(i + 1) % 3];
                        if (edge.Except(currentMatchedEdge).Count() == 0)
                        {
                            linkBackEdge = (TriangleEdge)i;
                            break;
                        }
                    }

                    TriangleEdge nextEdgeNoC_CW = (TriangleEdge)((int)(linkBackEdge + 1) % 3);

                    TriangleEdge nextEdge = nextEdgeNoC_CW;
                    if (!even)
                    {
                        // If odd, nextEdgeNoC_CW points to the edge to be used if written CW, however
                        // all triangles have been read in as CCW so need to get the corresponding edge
                        // in CCW version.
                        ModelBase.VertexDef[] nextEdgeNoC_CW_Vertices = new ModelBase.VertexDef[2];
                        nextEdgeNoC_CW_Vertices[0] = triangleC_CW.m_Vertices[(int)(nextEdgeNoC_CW + 0) % 3];
                        nextEdgeNoC_CW_Vertices[1] = triangleC_CW.m_Vertices[(int)(nextEdgeNoC_CW + 1) % 3];
                        for (int i = 0; i < 3; i++)
                        {
                            ModelBase.VertexDef[] ccwEdge = new ModelBase.VertexDef[2];
                            ccwEdge[0] = t.m_Triangle.m_Vertices[(i + 0) % 3];
                            ccwEdge[1] = t.m_Triangle.m_Vertices[(i + 1) % 3];
                            if (nextEdgeNoC_CW_Vertices.Except(ccwEdge).Count() == 0)
                            {
                                nextEdge = (TriangleEdge)i;
                                break;
                            }
                        }
                    }

                    // Now we need to determine the required rotation of the current triangle so that for
                    // even triangles the new vertex in at index 0 and for odd triangles it occurs at
                    // index 2.
                    ModelBase.VertexDef uniqueVertex = t.m_Triangle.m_Vertices.Except(previous.m_Triangle.m_Vertices).ElementAt(0);
                    int uniqueVertexIndex = Array.IndexOf(t.m_Triangle.m_Vertices, uniqueVertex);
                    TriangleRotation requiredRotation =
                        (even) ? (TriangleRotation)((uniqueVertexIndex - 2 + 3) % 3) :
                        (TriangleRotation)(uniqueVertexIndex);

                    currentRotation = requiredRotation;
                    currentEdge = nextEdge;

                    // To best understand how this works, debug and step-through how the following model is handled:
                    //
                    // An example:
                    // Faces as defined in model (all Counter-Clockwise (CCW)):
                    // f 1 2 3
                    // f 4 1 3
                    // f 4 5 1
                    // Build strip from edge CA.
                    // # 2 3 1 (LS)      <- Need to Left Shift vertices so that CA is the second edge.
                    // #   3 1 4 (4 1 3) <- For odd faces the new vertex must be at index [0]
                    //                      No Rot required, link-back CW: AB, CW forward: AB + 1 = BC,
                    //                      CCW forward: edge in CCW that contains vertices in (CW forward) = AB
                    //                      The next triangle is the one that shares the CCW edge AB (vertices 1 and 4)
                    // #     1 4 5 (RS)  <- Even face the new vertex needs to be in index [2] so need to Right Shift vertices
                    //                      Repeat steps as for above face but don't need to worry about converting between CCW and CW order
                }

            }

            ModelBase.FaceListDef tStrip = new ModelBase.FaceListDef(ModelBase.PolyListType.TriangleStrip);

            even = true;
            for (int i = 0; i < stripIndices.Count; i++)
            {
                TriangleRotation requiredRotation = (TriangleRotation)stripRotations[i];

                ModelBase.FaceDef rotated = new ModelBase.FaceDef(3);
                rotated.m_Vertices[0] = m_Triangles[stripIndices[i]].m_Triangle.m_Vertices[((int)(0 + requiredRotation) % 3)];
                rotated.m_Vertices[1] = m_Triangles[stripIndices[i]].m_Triangle.m_Vertices[((int)(1 + requiredRotation) % 3)];
                rotated.m_Vertices[2] = m_Triangles[stripIndices[i]].m_Triangle.m_Vertices[((int)(2 + requiredRotation) % 3)];

                tStrip.m_Faces.Add(rotated);

                even = !even;
            }

            return new Tuple<ModelBase.FaceListDef, List<int>>(tStrip, stripIndices);
        }
        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);
            }
        }
Пример #11
0
        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;
        }