Beispiel #1
0
        /* Creates a list of bones based on object names found in OBJ file and assigns them
         * default values. These will be replaced if a bone definition file is found.
         * By default there is one root parent bone and every other bone is a child bone with one child (until the end)
         */
        protected bool LoadDefaultBones(string modelFileName)
        {
            Stream       fs = File.OpenRead(m_ModelFileName);
            StreamReader sr = new StreamReader(fs);

            bool foundObjects = false;

            ModelBase.BoneDef bone = null;

            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 "o":     // object (bone)
                {
                    bone = new ModelBase.BoneDef(parts[1]);

                    if (m_Model.m_BoneTree.Count == 0)
                    {
                        m_Model.m_BoneTree.AddRootBone(bone);
                    }
                    else
                    {
                        m_Model.m_BoneTree.GetAsList()[m_Model.m_BoneTree.Count - 1].AddChild(bone);
                    }

                    foundObjects = true;
                }
                break;
                }
            }

            sr.Close();

            return(foundObjects);
        }
Beispiel #2
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);
        }
Beispiel #3
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;
        }
Beispiel #4
0
        private void ReadNode(node joint, node parent, bool inSkeleton)
        {
            string id = (joint.id != null ? joint.id : (joint.name != null ? joint.name : m_Model.m_BoneTree.Count.ToString()));

            Vector3 nodeScale = Vector3.One;
            Vector3 nodeRotation = Vector3.Zero;
            Vector3 nodeTranslation = Vector3.Zero;

            ReadNodeTransformations(joint, ref nodeScale, ref nodeRotation, ref nodeTranslation);

            if (joint.instance_geometry != null && joint.instance_geometry.Length > 0)
            {
                // Making an assumption that <instance_geometry> will never appear within a skeleton, not sure if it can?

                ModelBase.BoneDef rootBone = new ModelBase.BoneDef(id);

                rootBone.SetScale(nodeScale);
                rootBone.SetRotation(nodeRotation);
                rootBone.SetTranslation(nodeTranslation);

                m_Model.m_BoneTree.AddRootBone(rootBone);

                m_Model.m_BoneTransformsMap.Add(id, m_Model.m_BoneTree.GetBoneIndex(id));

                foreach (instance_geometry instanceGeometry in joint.instance_geometry)
                {
                    string geometryID = instanceGeometry.url.Replace("#", "");

                    Dictionary<string, string> bindMaterials = new Dictionary<string, string>();

                    if (instanceGeometry.bind_material != null)
                    {
                        foreach (instance_material instanceMaterial in instanceGeometry.bind_material.technique_common)
                        {
                            bindMaterials.Add(instanceMaterial.symbol, instanceMaterial.target.Replace("#", ""));
                        }
                    }

                    ModelBase.GeometryDef geometry = ReadGeometry(geometryID, id, bindMaterials);
                    rootBone.m_Geometries.Add(geometryID, geometry);
                }
            }
            else if (joint.instance_controller != null && joint.instance_controller.Length > 0)
            {
                // Making an assumption that <instance_controller> will never appear within a skeleton, not sure if it can?

                instance_controller instanceController = joint.instance_controller[0];

                string controllerID = instanceController.url.Replace("#", "");
                if (instanceController.skeleton != null && instanceController.skeleton.Length > 0)
                {

                    /*string skeletonRoot = null;
                    foreach (string skel in instanceController.skeleton)
                    {
                        string skeleton = skel.Replace("#", "");
                        if (skeletonRoot == null) skeletonRoot = skeleton;
                        if (m_Model.m_BoneTree.GetBoneByID(skeleton) != null) continue;

                        ReadSkeleton(skeletonRoot);
                    }
                    // WRONG */

                    string skeletonRoot = instanceController.skeleton[0].Replace("#", "");
                    ReadSkeleton(skeletonRoot);

                    controller cntl = this.library_controllers.controller.Where(cntl0 => cntl0.id.Equals(controllerID)).ElementAt(0);
                    if (cntl.Item as skin != null)
                    {
                        // Currently there is only support for skin controllers. Where a skin uses as its source another
                        // controller eg. a morph, we'll just recursively go through until we find a skin with a geometry
                        // as the source and return the geometry's ID.
                        // I've seen a skin use a skin as a source where the first skin gave joint indices of -1 from 3DS Max and
                        // OpenCOLLAD, in cases like this, we do as above and just take the geometry ID and attach the skin being
                        // read to that.
                        string skinSourceID = null;
                        var queue = new Queue<controller>();
                        queue.Enqueue(cntl);
                        while (queue.Count > 0)
                        {
                            controller cont = queue.Dequeue();
                            string srcID = (cont.Item as skin).source1.Replace("#", "");
                            if (this.library_geometries != null &&
                                this.library_geometries.geometry.Where(geom0 => geom0.id.Equals(srcID)).Count() < 1)
                            {
                                IEnumerable<controller> res = this.library_controllers.controller.Where(cont0 => cont0.id.Equals(srcID));
                                if (res.Count() > 0)
                                {
                                    queue.Enqueue(res.ElementAt(0));
                                }
                            }
                            else
                            {
                                skinSourceID = srcID;
                            }
                        }

                        m_Model.m_BoneTransformsMap.Clear();

                        int[] vertexBoneIDs = ReadSkinController(controllerID, skeletonRoot, skinSourceID);

                        Dictionary<string, string> bindMaterials = new Dictionary<string, string>();
                        if (instanceController.bind_material != null)
                        {
                            foreach (instance_material instanceMaterial in instanceController.bind_material.technique_common)
                            {
                                bindMaterials.Add(instanceMaterial.symbol, instanceMaterial.target.Replace("#", ""));
                            }
                        }

                        ModelBase.GeometryDef geomDef = ReadGeometry(skinSourceID, skeletonRoot, bindMaterials, vertexBoneIDs);
                        m_Model.m_BoneTree.GetBoneByID(skeletonRoot).m_Geometries.Add(skinSourceID, geomDef);
                    }
                }
            }
            else if (inSkeleton)
            {
                ModelBase.BoneDef boneDef = new ModelBase.BoneDef(joint.id);

                if (joint == parent)
                {
                    m_Model.m_BoneTree.AddRootBone(boneDef);
                }
                else
                {
                    ModelBase.BoneDef parentBone = m_Model.m_BoneTree.GetBoneByID(parent.id);
                    parentBone.AddChild(boneDef);
                }

                boneDef.SetScale(nodeScale);
                boneDef.SetRotation(nodeRotation);
                boneDef.SetTranslation(nodeTranslation);

                if (joint.node1 == null || joint.node1.Length == 0)
                    return;
                foreach (node child in joint.node1)
                {
                    if (child.type.Equals(NodeType.NODE))
                    {
                        Console.WriteLine("Warning: node: " + joint.id + " has a child of type \"NODE\" within a skeleton, failure likely");
                    }

                    ReadNode(child, joint, true);
                }
            }
        }
        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();
        }
Beispiel #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);
        }
Beispiel #7
0
        public override void WriteModel(bool save = true)
        {
            StreamWriter objWriter    = new StreamWriter(m_ModelFileName);
            StreamWriter mtlWriter    = new StreamWriter(m_ModelFileName.Substring(0, m_ModelFileName.Length - 4) + ".mtl");
            string       dir          = Path.GetDirectoryName(m_ModelFileName);
            string       baseFileName = Path.GetFileNameWithoutExtension(m_ModelFileName);

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

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

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

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

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

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

                                f++;
                            }

                            fl++;
                        }
                    }
                }

                boneIndex++;
            }

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

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

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

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

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

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

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

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

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

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

            objWriter.Close();
            mtlWriter.Close();
        }
Beispiel #8
0
        protected void LoadBoneDefinitionsForOBJ(string filename)
        {
            Stream fs;

            try
            {
                fs = File.OpenRead(filename);
            }
            catch
            {
                MessageBox.Show("Specified Bone definitions not found:\n\n" + filename + "\n\nUsing default values.");
                return;
            }
            StreamReader sr = new StreamReader(fs);

            m_Model.m_BoneTree.Clear();

            ModelBase.BoneDef bone = null;

            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 "newbone":     // new bone definition
                {
                    if (parts.Length < 2)
                    {
                        continue;
                    }

                    bone = new ModelBase.BoneDef(parts[1]);
                }
                break;

                case "parent_offset":     // Offset in bones to parent bone (signed 16-bit. 0=no parent, -1=parent is the previous bone, ...)
                {
                    if (parts.Length < 2)
                    {
                        continue;
                    }
                    short parent_offset = short.Parse(parts[1]);

                    if ((parent_offset < 0 && m_Model.m_BoneTree.Count == 0) || parent_offset > 0)
                    {
                        throw new SystemException("Child bones cannot be defined before their parent in: " + filename);
                    }

                    if (parent_offset == 0)
                    {
                        m_Model.m_BoneTree.AddRootBone(bone);
                    }
                    else if (parent_offset < 0)
                    {
                        List <ModelBase.BoneDef> listOfBones = m_Model.m_BoneTree.GetAsList();
                        listOfBones[listOfBones.Count + parent_offset].AddChild(bone);
                    }
                }
                break;

                case "has_children":     // 1 if the bone has children, 0 otherwise
                {
                    if (parts.Length < 2)
                    {
                        continue;
                    }
                    bool has_children = (short.Parse(parts[1]) == 1);
                    // No longer needed
                }
                break;

                case "sibling_offset":     // Offset in bones to the next sibling bone (0=bone is last child of its parent)
                {
                    if (parts.Length < 2)
                    {
                        continue;
                    }
                    short sibling_offset = short.Parse(parts[1]);
                    // No longer needed
                }
                break;

                case "scale":     // Scale transformation
                {
                    if (parts.Length < 4)
                    {
                        continue;
                    }
                    uint[] scale = new uint[] { uint.Parse(parts[1], System.Globalization.NumberStyles.HexNumber),
                                                uint.Parse(parts[2], System.Globalization.NumberStyles.HexNumber),
                                                uint.Parse(parts[3], System.Globalization.NumberStyles.HexNumber) };

                    bone.SetScale(scale);
                }
                break;

                case "rotation":     // Rotation transformation
                {
                    if (parts.Length < 4)
                    {
                        continue;
                    }
                    ushort[] rotation = new ushort[] { ushort.Parse(parts[1], System.Globalization.NumberStyles.HexNumber),
                                                       ushort.Parse(parts[2], System.Globalization.NumberStyles.HexNumber),
                                                       ushort.Parse(parts[3], System.Globalization.NumberStyles.HexNumber) };

                    bone.SetRotation(rotation);
                }
                break;

                case "translation":     // Scale transformation
                {
                    if (parts.Length < 4)
                    {
                        continue;
                    }
                    uint[] translation = new uint[] { uint.Parse(parts[1], System.Globalization.NumberStyles.HexNumber),
                                                      uint.Parse(parts[2], System.Globalization.NumberStyles.HexNumber),
                                                      uint.Parse(parts[3], System.Globalization.NumberStyles.HexNumber) };

                    bone.SetTranslation(translation);
                }
                break;

                case "billboard":     // Always rendered facing camera
                {
                    if (parts.Length < 2)
                    {
                        continue;
                    }
                    bool billboard = (short.Parse(parts[1]) == 1);

                    bone.m_Billboard = billboard;
                }
                break;
                }
            }

            // Calculate transformations and inverse transformations
            foreach (ModelBase.BoneDef boneDef in m_Model.m_BoneTree.GetRootBones())
            {
                boneDef.CalculateBranchTransformations();
            }

            sr.Close();
        }
Beispiel #9
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);
        }
        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 ModelBase.AnimationComponentDataDef ReadAnimationComponent(XmlNode descriptor, ModelBase.AnimationComponentType componentType,
                                                                             int boneIndex)
        {
            int  frame_step  = int.Parse(descriptor.Attributes["frame_step"].Value);
            int  data_size   = int.Parse(descriptor.Attributes["data_size"].Value);
            int  data_head   = int.Parse(descriptor.Attributes["data_head"].Value);
            bool isConstant  = (data_size == 1);
            bool useIdentity = (isConstant && data_head == 0);

            float[] values = new float[data_size];
            if (!useIdentity)
            {
                switch (componentType)
                {
                case ModelBase.AnimationComponentType.ScaleX:
                    Array.Copy(this.node_scale_data, data_head, values, 0, data_size);
                    break;

                case ModelBase.AnimationComponentType.ScaleY: goto case ModelBase.AnimationComponentType.ScaleX;

                case ModelBase.AnimationComponentType.ScaleZ: goto case ModelBase.AnimationComponentType.ScaleX;

                case ModelBase.AnimationComponentType.RotateX:
                    Array.Copy(this.node_rotate_data, data_head, values, 0, data_size);
                    break;

                case ModelBase.AnimationComponentType.RotateY: goto case ModelBase.AnimationComponentType.RotateX;

                case ModelBase.AnimationComponentType.RotateZ: goto case ModelBase.AnimationComponentType.RotateX;

                case ModelBase.AnimationComponentType.TranslateX:
                    Array.Copy(this.node_translate_data, data_head, values, 0, data_size);
                    break;

                case ModelBase.AnimationComponentType.TranslateY: goto case ModelBase.AnimationComponentType.TranslateX;

                case ModelBase.AnimationComponentType.TranslateZ: goto case ModelBase.AnimationComponentType.TranslateX;
                }
            }
            else
            {
                ModelBase.BoneDef boneDef = m_Model.m_BoneTree.GetBoneByIndex(boneIndex);
                switch (componentType)
                {
                case ModelBase.AnimationComponentType.ScaleX:
                    values[0] = boneDef.m_Scale.X; break;

                case ModelBase.AnimationComponentType.ScaleY:
                    values[0] = boneDef.m_Scale.Y; break;

                case ModelBase.AnimationComponentType.ScaleZ:
                    values[0] = boneDef.m_Scale.Z; break;

                case ModelBase.AnimationComponentType.RotateX:
                    values[0] = boneDef.m_Rotation.X; break;

                case ModelBase.AnimationComponentType.RotateY:
                    values[0] = boneDef.m_Rotation.Y; break;

                case ModelBase.AnimationComponentType.RotateZ:
                    values[0] = boneDef.m_Rotation.Z; break;

                case ModelBase.AnimationComponentType.TranslateX:
                    values[0] = boneDef.m_Translation.X; break;

                case ModelBase.AnimationComponentType.TranslateY:
                    values[0] = boneDef.m_Translation.Y; break;

                case ModelBase.AnimationComponentType.TranslateZ:
                    values[0] = boneDef.m_Translation.Z; break;
                }
            }

            return(new ModelBase.AnimationComponentDataDef(values, this.node_anm_info.frame_size, isConstant, frame_step,
                                                           useIdentity, componentType));
        }
        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();
        }
Beispiel #13
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;
        }