Ejemplo n.º 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);
        }
Ejemplo n.º 2
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;
        }
Ejemplo n.º 3
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);
            }
        }
        protected void ReadNodes(XmlNode node_array, XmlNode polygon_array, XmlNode matrix_array)
        {
            if (node_array == null)
            {
                return;
            }
            int nodeArray_size = int.Parse(node_array.Attributes["size"].Value);

            if (nodeArray_size < 1)
            {
                return;
            }

            XmlNodeList nodes = node_array.SelectNodes("node");

            foreach (XmlNode node in nodes)
            {
                m_OriginalNodeIndices.Add(int.Parse(node.Attributes["index"].Value), node.Attributes["name"].Value);
            }

            ReadMatrices(matrix_array, m_OriginalNodeIndices);

            var queue         = new Queue <XmlNode>();
            var geometryQueue = new Queue <XmlNode>();

            queue.Enqueue(nodes[0]);

            while (queue.Count > 0)
            {
                XmlNode node = queue.Dequeue();

                int     index            = int.Parse(node.Attributes["index"].Value);
                string  name             = node.Attributes["name"].Value;
                string  kind             = node.Attributes["kind"].Value;
                int     parent           = int.Parse(node.Attributes["parent"].Value);
                int     child            = int.Parse(node.Attributes["child"].Value);
                int     brother_next     = int.Parse(node.Attributes["brother_next"].Value);
                int     brother_prev     = int.Parse(node.Attributes["brother_prev"].Value);
                bool    draw_mtx         = node.Attributes["draw_mtx"].Value.Equals("on");
                string  scale_compensate = (node.Attributes["scale_compensate"] != null) ? node.Attributes["scale_compensate"].Value : null;
                string  billboard        = node.Attributes["billboard"].Value; // Either "on", "off" or "y_on"
                float[] scale            = Array.ConvertAll(
                    node.Attributes["scale"].Value.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries),
                    Convert.ToSingle);
                float[] rotate = Array.ConvertAll(
                    node.Attributes["rotate"].Value.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries),
                    Convert.ToSingle);
                float[] translate = Array.ConvertAll(
                    node.Attributes["translate"].Value.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries),
                    Convert.ToSingle);
                bool    visibility    = node.Attributes["visibility"].Value.Equals("on");
                int     display_size  = int.Parse(node.Attributes["display_size"].Value);
                int     vertex_size   = (kind.Equals("mesh")) ? int.Parse(node.Attributes["vertex_size"].Value) : -1;
                int     polygon_size  = (kind.Equals("mesh")) ? int.Parse(node.Attributes["polygon_size"].Value) : -1;
                int     triangle_size = (kind.Equals("mesh")) ? int.Parse(node.Attributes["triangle_size"].Value) : -1;
                int     quad_size     = (kind.Equals("mesh")) ? int.Parse(node.Attributes["quad_size"].Value) : -1;
                float[] volume_min    = (kind.Equals("mesh")) ? Array.ConvertAll(
                    node.Attributes["volume_min"].Value.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries),
                    Convert.ToSingle) : null;
                float[] volume_max = (kind.Equals("mesh")) ? Array.ConvertAll(
                    node.Attributes["volume_max"].Value.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries),
                    Convert.ToSingle) : null;
                float volume_r = (kind.Equals("mesh")) ? float.Parse(node.Attributes["volume_r"].Value) : -1;

                ModelBase.BoneDef boneDef = new ModelBase.BoneDef(name);
                boneDef.SetScale(new Vector3(scale[0], scale[1], scale[2]));
                boneDef.SetRotation(new Vector3(rotate[0] * Helper.Deg2Rad, rotate[1] * Helper.Deg2Rad, rotate[2] * Helper.Deg2Rad));
                boneDef.SetTranslation(new Vector3(translate[0], translate[1], translate[2]));
                boneDef.CalculateBranchTransformations();

                if (display_size > 0)
                {
                    geometryQueue.Enqueue(node);
                }

                if (parent == -1)
                {
                    m_Model.m_BoneTree.AddRootBone(boneDef);
                }
                else
                {
                    m_Model.m_BoneTree.GetBoneByID(m_OriginalNodeIndices[parent]).AddChild(boneDef);
                }

                /* Child node takes priority and siblings are stored consecutively by name in alphanumerical order
                 * (a→z and 0→9). The model root node must be the first <node> in <node_array> (index 0).
                 * "child" attribute gives first child, alphanumerically.
                 */

                if (child != -1)
                {
                    queue.Enqueue(nodes[child]);
                }
                if (brother_next != -1)
                {
                    queue.Enqueue(nodes[brother_next]);
                }
            }

            // In oder to correctly read the geometry we need to already have the list of bones read in so that bone ID's
            // can be assigned to vertices
            while (geometryQueue.Count > 0)
            {
                XmlNode node = geometryQueue.Dequeue();

                XmlNodeList displays = node.SelectNodes("display");

                ModelBase.BoneDef     boneDef     = m_Model.m_BoneTree.GetBoneByID(node.Attributes["name"].Value);
                ModelBase.GeometryDef geometryDef = new ModelBase.GeometryDef("geometry-0");

                foreach (XmlNode display in displays)
                {
                    int display_index    = int.Parse(display.Attributes["index"].Value);
                    int display_material = int.Parse(display.Attributes["material"].Value);
                    int display_polygon  = int.Parse(display.Attributes["polygon"].Value);
                    int display_priority = int.Parse(display.Attributes["priority"].Value);

                    ReadPolygon(display_polygon, polygon_array, m_Model.m_Materials.ElementAt(display_material).Key, geometryDef);

                    boneDef.m_MaterialsInBranch.Add(m_Model.m_Materials.ElementAt(display_material).Key);
                }

                boneDef.m_Geometries.Add(geometryDef.m_ID, geometryDef);
            }

            m_Model.ApplyTransformations();
        }
Ejemplo n.º 6
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);
        }
Ejemplo n.º 7
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);
        }
Ejemplo n.º 8
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);
        }
        protected void ReadNodes(XmlNode node_array, XmlNode polygon_array, XmlNode matrix_array)
        {
            if (node_array == null) return;
            int nodeArray_size = int.Parse(node_array.Attributes["size"].Value);

            if (nodeArray_size < 1) return;

            XmlNodeList nodes = node_array.SelectNodes("node");

            foreach (XmlNode node in nodes)
                m_OriginalNodeIndices.Add(int.Parse(node.Attributes["index"].Value), node.Attributes["name"].Value);

            ReadMatrices(matrix_array, m_OriginalNodeIndices);

            var queue = new Queue<XmlNode>();
            var geometryQueue = new Queue<XmlNode>();
            queue.Enqueue(nodes[0]);

            while (queue.Count > 0)
            {
                XmlNode node = queue.Dequeue();

                int index = int.Parse(node.Attributes["index"].Value);
                string name = node.Attributes["name"].Value;
                string kind = node.Attributes["kind"].Value;
                int parent = int.Parse(node.Attributes["parent"].Value);
                int child = int.Parse(node.Attributes["child"].Value);
                int brother_next = int.Parse(node.Attributes["brother_next"].Value);
                int brother_prev = int.Parse(node.Attributes["brother_prev"].Value);
                bool draw_mtx = node.Attributes["draw_mtx"].Value.Equals("on");
                string scale_compensate = (node.Attributes["scale_compensate"] != null) ? node.Attributes["scale_compensate"].Value : null;
                string billboard = node.Attributes["billboard"].Value; // Either "on", "off" or "y_on"
                float[] scale = Array.ConvertAll(
                    node.Attributes["scale"].Value.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries),
                    Convert.ToSingle);
                float[] rotate = Array.ConvertAll(
                    node.Attributes["rotate"].Value.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries),
                    Convert.ToSingle);
                float[] translate = Array.ConvertAll(
                    node.Attributes["translate"].Value.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries),
                    Convert.ToSingle);
                bool visibility = node.Attributes["visibility"].Value.Equals("on");
                int display_size = int.Parse(node.Attributes["display_size"].Value);
                int vertex_size = (kind.Equals("mesh")) ? int.Parse(node.Attributes["vertex_size"].Value) : -1;
                int polygon_size = (kind.Equals("mesh")) ? int.Parse(node.Attributes["polygon_size"].Value) : -1;
                int triangle_size = (kind.Equals("mesh")) ? int.Parse(node.Attributes["triangle_size"].Value) : -1;
                int quad_size = (kind.Equals("mesh")) ? int.Parse(node.Attributes["quad_size"].Value) : -1;
                float[] volume_min = (kind.Equals("mesh")) ? Array.ConvertAll(
                    node.Attributes["volume_min"].Value.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries),
                    Convert.ToSingle) : null;
                float[] volume_max = (kind.Equals("mesh")) ? Array.ConvertAll(
                    node.Attributes["volume_max"].Value.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries),
                    Convert.ToSingle) : null;
                float volume_r = (kind.Equals("mesh")) ? float.Parse(node.Attributes["volume_r"].Value) : -1;

                ModelBase.BoneDef boneDef = new ModelBase.BoneDef(name);
                boneDef.SetScale(new Vector3(scale[0], scale[1], scale[2]));
                boneDef.SetRotation(new Vector3(rotate[0] * Helper.Deg2Rad, rotate[1] * Helper.Deg2Rad, rotate[2] * Helper.Deg2Rad));
                boneDef.SetTranslation(new Vector3(translate[0], translate[1], translate[2]));
                boneDef.CalculateBranchTransformations();

                if (display_size > 0)
                {
                    geometryQueue.Enqueue(node);
                }

                if (parent == -1)
                    m_Model.m_BoneTree.AddRootBone(boneDef);
                else
                    m_Model.m_BoneTree.GetBoneByID(m_OriginalNodeIndices[parent]).AddChild(boneDef);

                /* Child node takes priority and siblings are stored consecutively by name in alphanumerical order
                 * (a→z and 0→9). The model root node must be the first <node> in <node_array> (index 0).
                 * "child" attribute gives first child, alphanumerically.
                 */

                if (child != -1)
                    queue.Enqueue(nodes[child]);
                if (brother_next != -1)
                    queue.Enqueue(nodes[brother_next]);
            }

            // In oder to correctly read the geometry we need to already have the list of bones read in so that bone ID's
            // can be assigned to vertices
            while (geometryQueue.Count > 0)
            {
                XmlNode node = geometryQueue.Dequeue();

                XmlNodeList displays = node.SelectNodes("display");

                ModelBase.BoneDef boneDef = m_Model.m_BoneTree.GetBoneByID(node.Attributes["name"].Value);
                ModelBase.GeometryDef geometryDef = new ModelBase.GeometryDef("geometry-0");

                foreach (XmlNode display in displays)
                {
                    int display_index = int.Parse(display.Attributes["index"].Value);
                    int display_material = int.Parse(display.Attributes["material"].Value);
                    int display_polygon = int.Parse(display.Attributes["polygon"].Value);
                    int display_priority = int.Parse(display.Attributes["priority"].Value);

                    ReadPolygon(display_polygon, polygon_array, m_Model.m_Materials.ElementAt(display_material).Key, geometryDef);

                    boneDef.m_MaterialsInBranch.Add(m_Model.m_Materials.ElementAt(display_material).Key);
                }

                boneDef.m_Geometries.Add(geometryDef.m_ID, geometryDef);
            }

            m_Model.ApplyTransformations();
        }
Ejemplo n.º 10
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;
        }