/// <summary>
        /// Draw a BuildingObjectLib3DS object.
        /// </summary>
        /// <param name="gl">Opengl handler.</param>
        /// <param name="buildingObj">The BuildingObjectLib3DS object.</param>
        public void DrawBuildingPart(OpenGL gl, BuildingObjectLib3DS buildingObj, DrawType type)
        {
            // Return when the input object is null
            if (buildingObj == null)
            {
                return;
            }

            // Draw all the children when type is Building, Floor or room. Or draw a Object.
            switch (buildingObj.GetBuildingType())
            {
            case BuildingObjectType.Building:
            case BuildingObjectType.Floor:
            case BuildingObjectType.Room:
                foreach (BuildingObjectLib3DS child in buildingObj.GetChilds().Values)
                {
                    DrawBuildingPart(gl, child, type);
                }
                break;

            case BuildingObjectType.Outside:
            case BuildingObjectType.Object:
                DrawObject(gl, buildingObj, type);
                break;

            default:
                break;
            }
        }
        public BuildingObjectLib3DS CreateBuildingModel()
        {
            BuildingObjectLib3DS Building;
            Hashtable            Textures  = new Hashtable();
            Lib3dsMesh           test      = new Lib3dsMesh();
            OpenGLControl        openglCtr = new SharpGL.OpenGLControl();

            foreach (Lib3dsMaterial material in MyModel.materials)
            {
                Texture texture = new Texture();
                try
                {
                    texture.Create(openglCtr.OpenGL, "..\\Model\\" + material.name + ".jpg");
                    Textures.Add(material.name, texture);
                }
                catch
                {
                    // Do not find the texture file
                }
            }

            Building = new BuildingObjectLib3DS(null, BuildingObjectType.Building, 0,
                                                MyModel, Textures);

            foreach (Lib3dsMeshInstanceNode node in MyModel.nodes)
            {
                if (node.type != Lib3dsNodeType.LIB3DS_NODE_MESH_INSTANCE || node.childs == null)
                {
                    continue;
                }
                Building.AddNewChild(node);
            }

            return(Building);
        }
        /// <summary>
        /// Draw a BuildingObjectLib3DS object.
        /// </summary>
        /// <param name="gl">Opengl handler.</param>
        /// <param name="buildingObj">The BuildingObjectLib3DS object.</param>
        public void DrawBuildingPart(OpenGL gl, BuildingObjectLib3DS buildingObj, DrawType type)
        {
            // Return when the input object is null
            if (buildingObj == null)
                return;

            // Draw all the children when type is Building, Floor or room. Or draw a Object.
            switch (buildingObj.GetBuildingType())
            {
                case BuildingObjectType.Building:
                case BuildingObjectType.Floor:
                case BuildingObjectType.Room:
                    foreach (BuildingObjectLib3DS child in buildingObj.GetChilds().Values)
                    {
                        DrawBuildingPart(gl, child, type);
                    }
                    break;
                case BuildingObjectType.Outside:
                case BuildingObjectType.Object:
                    DrawObject(gl, buildingObj, type);
                    break;
                default:
                    break;
            }
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="ProjectorWin"/> class.
        /// </summary>
        public ProjectorWin()
        {
            // Initial something.
            this.drawer = null;
            this.buildingModelCursor = null;
            texture_name = new uint[1];
            renderbuffer_name = new uint[1];
            framebuffer_name = new uint[1];

            // Initial texture size.
            if (Screen.AllScreens.Count() >= 2)
            {
                this.TEXTURE_WIDTH = Screen.AllScreens[1].Bounds.Width;
                this.TEXTURE_HEIGHT = Screen.AllScreens[1].Bounds.Height;
            }
            else
            {
                this.TEXTURE_WIDTH = Screen.AllScreens[0].Bounds.Width;
                this.TEXTURE_HEIGHT = Screen.AllScreens[0].Bounds.Height;
            }
            fovy = 45.0f;

            System.Timers.Timer t = new System.Timers.Timer(10000);
            t.Elapsed +=
                new System.Timers.ElapsedEventHandler(this.CalculateFPS);

            t.AutoReset = true;
            t.Enabled = true;
            fps = 0;

            // Initial form components.
            InitializeComponent();
        }
        /// <summary>
        /// Create a new BuildingObjectLib3DS object.
        /// </summary>
        /// <param name="father">Father node</param>
        /// <param name="type">Type of this object</param>
        /// <param name="id">Id of this object</param>
        /// <param name="model">All models information</param>
        /// <param name="textures">All textures information</param>
        public BuildingObjectLib3DS(BuildingObjectLib3DS father, BuildingObjectType type, uint id,
                                    Lib3dsFile model, Hashtable textures)
        {
            this.Father   = father;
            this.Type     = type;
            this.Id       = id;
            this.Model    = model;
            this.Textures = textures;

            // Initialization
            this.Childs     = new Hashtable();
            this.Coordinate = new Vertex();
        }
        /// <summary>
        /// Draw a object.
        /// </summary>
        /// <param name="gl">OpenGL handler.</param>
        /// <param name="buildingObj">The object.</param>
        private void DrawObject(OpenGL gl, BuildingObjectLib3DS buildingObj, DrawType type)
        {
            Lib3dsMeshInstanceNode thisMeshInst = buildingObj.Object;

            if (thisMeshInst.childs.Count == 0)
            {
                // Maybe this object only have one mesh.
                Lib3dsMesh thisMesh = FindLib3dsMeshByName(thisMeshInst.name, buildingObj.Model.meshes);
                DrawMesh(gl, thisMesh, buildingObj.Textures, buildingObj.Model.materials, type);
            }
            else
            {
                // Draw all the meshes in this object.
                foreach (Lib3dsNode node in thisMeshInst.childs)
                {
                    Lib3dsMesh thisMesh = FindLib3dsMeshByName(node.name, buildingObj.Model.meshes);
                    DrawMesh(gl, thisMesh, buildingObj.Textures, buildingObj.Model.materials, type);
                }
            }
        }
        public DrawingController()
        {
            projectorWin = new ProjectorWin();
            projectorWin.status = new DrawingStatus();

            loader = new _3DSLoaderByLib3DS();
            loaderForFun = new _3DSLoaderByLib3DS();
            loader.OpenFile("..\\Model\\Untitled.3ds");
            loaderForFun.OpenFile("..\\Model\\miku.3ds");

            buildingModel = loader.CreateBuildingModel();
            buildingModel.CalculateLocation();
            modelForFun = loaderForFun.CreateBuildingModel();
            modelForFun.CalculateLocation();

            drawer = new _3DSDrawerByLib3DS();

            projectorWin.buildingModelCursor = buildingModel;
            projectorWin.buildingOutsideModel = buildingModel.GetChilds()["0"] as BuildingObjectLib3DS;
            projectorWin.modelForFun = modelForFun;
            projectorWin.drawer = drawer;
            projectorWin.Show();
        }
        public BuildingObjectLib3DS CreateBuildingModel()
        {
            BuildingObjectLib3DS Building;
            Hashtable Textures = new Hashtable();
            Lib3dsMesh test = new Lib3dsMesh();
            OpenGLControl openglCtr = new SharpGL.OpenGLControl();

            foreach (Lib3dsMaterial material in MyModel.materials)
            {
                Texture texture = new Texture();
                try
                {
                    texture.Create(openglCtr.OpenGL, "..\\Model\\" + material.name + ".jpg");
                    Textures.Add(material.name, texture);
                }
                catch
                {
                    // Do not find the texture file
                }
            }

            Building = new BuildingObjectLib3DS(null, BuildingObjectType.Building, 0,
                MyModel, Textures);

            foreach (Lib3dsMeshInstanceNode node in MyModel.nodes)
            {
                if (node.type != Lib3dsNodeType.LIB3DS_NODE_MESH_INSTANCE || node.childs == null)
                    continue;
                Building.AddNewChild(node);
            }

            return Building;
        }
        /// <summary>
        /// Draw a object.
        /// </summary>
        /// <param name="gl">OpenGL handler.</param>
        /// <param name="buildingObj">The object.</param>
        private void DrawObject(OpenGL gl, BuildingObjectLib3DS buildingObj, DrawType type)
        {
            Lib3dsMeshInstanceNode thisMeshInst = buildingObj.Object;

            if (thisMeshInst.childs.Count == 0)
            {
                // Maybe this object only have one mesh.
                Lib3dsMesh thisMesh = FindLib3dsMeshByName(thisMeshInst.name, buildingObj.Model.meshes);
                DrawMesh(gl, thisMesh, buildingObj.Textures, buildingObj.Model.materials, type);
            }
            else
            {
                // Draw all the meshes in this object.
                foreach (Lib3dsNode node in thisMeshInst.childs)
                {
                    Lib3dsMesh thisMesh = FindLib3dsMeshByName(node.name, buildingObj.Model.meshes);
                    DrawMesh(gl, thisMesh, buildingObj.Textures, buildingObj.Model.materials, type);
                }
            }
        }
        /// <summary>
        /// Parallel move from focused object to others.
        /// </summary>
        /// <param name="move">Which direction</param>
        /// <param name="status">Status of eye or kinect..etc..</param>
        /// <returns>New focused object</returns>
        private BuildingObjectLib3DS GetObjectByParallelMovement(DrawingEnumTypes.Movement move, DrawingStatus status)
        {
            XmlTextWriter writer = null;

            writer = new XmlTextWriter(Console.Out);

            if (this.Father.Childs.Count <= 1)
            {
                return(this);
            }

            int count = Father.Childs.Count - 1;
            BuildingObjectLib3DS rnt = null;

            double          shita  = Math.Atan((status.eye.x - this.Coordinate.x) / (status.eye.z + this.Coordinate.y));
            Matrix <double> matrix = new Matrix <double>(1, 2);

            matrix.SetValue(0);
            matrix.Data[0, 0] = this.Coordinate.x;
            matrix.Data[0, 1] = -this.Coordinate.y;
            Matrix <double> _matrix = new Matrix <double>(2, 2);

            _matrix.SetValue(0);
            _matrix.Data[0, 0] = Math.Cos(shita);
            _matrix.Data[0, 1] = -Math.Sin(shita);
            _matrix.Data[1, 0] = Math.Sin(shita);
            _matrix.Data[1, 1] = Math.Cos(shita);

            Matrix <double> otherChilds = new Matrix <double>(1, 2);

            otherChilds.SetValue(0);
            double MinIn    = 99999.0f;
            double MinOut   = 99999.0f;
            double MinLeft  = 99999.0f;
            double MinRight = 99999.0f;

            foreach (BuildingObjectLib3DS ThisObj in Father.Childs.Values)
            {
                if (ThisObj.Equals(this))
                {
                    continue;
                }

                otherChilds.Data[0, 0] = ThisObj.Coordinate.x;
                otherChilds.Data[0, 1] = -ThisObj.Coordinate.y;
                otherChilds            = (otherChilds - matrix) * _matrix;
                switch (move)
                {
                case DrawingEnumTypes.Movement.MoveIn:
                    if (otherChilds.Data[0, 1] < 0 &&
                        Math.Abs(otherChilds.Data[0, 1]) < MinIn)
                    {
                        rnt   = ThisObj;
                        MinIn = Math.Abs(otherChilds.Data[0, 1]);
                    }
                    break;

                case DrawingEnumTypes.Movement.MoveOut:
                    if (otherChilds.Data[0, 1] > 0 &&
                        Math.Abs(otherChilds.Data[0, 1]) < MinOut)
                    {
                        rnt    = ThisObj;
                        MinOut = Math.Abs(otherChilds.Data[0, 1]);
                    }
                    break;

                case DrawingEnumTypes.Movement.MoveLeft:
                    if (otherChilds.Data[0, 0] < 0 &&
                        Math.Abs(otherChilds.Data[0, 0]) < MinLeft)
                    {
                        rnt     = ThisObj;
                        MinLeft = Math.Abs(otherChilds.Data[0, 0]);
                    }
                    break;

                case DrawingEnumTypes.Movement.MoveRight:
                    if (otherChilds.Data[0, 0] > 0 &&
                        Math.Abs(otherChilds.Data[0, 0]) < MinRight)
                    {
                        rnt      = ThisObj;
                        MinRight = Math.Abs(otherChilds.Data[0, 0]);
                    }
                    break;

                default:
                    return(this);
                }
            }

            // If we find the object
            if (rnt != null)
            {
                return(rnt);
            }

            // Do not find....
            return(this);
        }
        /// <summary>
        /// Insert a new child into this object.
        /// </summary>
        /// <param name="newObj">New child</param>
        public void AddNewChild(Lib3dsMeshInstanceNode newObj)
        {
            string[] newObjectLoca = null;

            // Return if location info is illegal
            if ((newObjectLoca = GetLocation(newObj.name)) == null)
            {
                return;
            }

            switch (this.Type)
            {
            case BuildingObjectType.Building:
                if (this.Childs.Contains(newObjectLoca[0]) == false)
                {
                    BuildingObjectType childType;
                    if (newObjectLoca[0] == "0")
                    {
                        childType = BuildingObjectType.Outside;
                    }
                    else
                    {
                        childType = BuildingObjectType.Floor;
                    }

                    BuildingObjectLib3DS bObj = new BuildingObjectLib3DS(this, childType,
                                                                         (uint)System.Convert.ToInt32(newObjectLoca[0]), Model, Textures);
                    this.Childs.Add(newObjectLoca[0], bObj);
                    bObj.AddNewChild(newObj);
                }
                else
                {
                    (this.Childs[(newObjectLoca[0])] as BuildingObjectLib3DS).AddNewChild(newObj);
                }
                break;

            case BuildingObjectType.Floor:
                if (this.Childs.Contains(newObjectLoca[1]) == false)
                {
                    BuildingObjectLib3DS bObj = new BuildingObjectLib3DS(this, BuildingObjectType.Room,
                                                                         (uint)System.Convert.ToInt32(newObjectLoca[1]), Model, Textures);
                    this.Childs.Add(newObjectLoca[1], bObj);
                    bObj.AddNewChild(newObj);
                }
                else
                {
                    (this.Childs[(newObjectLoca[1])] as BuildingObjectLib3DS).AddNewChild(newObj);
                }
                break;

            case BuildingObjectType.Room:
                if (this.Childs.Contains(newObjectLoca[2]) == false)
                {
                    BuildingObjectLib3DS bObj = new BuildingObjectLib3DS(this, BuildingObjectType.Object,
                                                                         (uint)System.Convert.ToInt32(newObjectLoca[2]), Model, Textures);
                    this.Childs.Add(newObjectLoca[2], bObj);
                    bObj.AddNewChild(newObj);
                }
                else
                {
                    // Same Name... ??? Do not insert it...
                }
                break;

            case BuildingObjectType.Outside:
            case BuildingObjectType.Object:
                this.Object = newObj;
                //if (this.Object.childs.Count == 0)
                //{
                //    Lib3dsMesh ThisMesh = FindLib3dsMeshByName(this.Object.name, this.Model.meshes);
                //    if (ThisMesh != null)
                //    {
                //        this.Normalizes = new Lib3dsVertex[1][];
                //        this.Normalizes[0] = new Lib3dsVertex[ThisMesh.faces.Count];
                //        for (int i = 0; i < ThisMesh.faces.Count; i++)
                //        {
                //            Lib3dsFace face = ThisMesh.faces[i];
                //            Lib3dsVertex Point1 = ThisMesh.vertices[face.index[0]];
                //            Lib3dsVertex Point2 = ThisMesh.vertices[face.index[1]];
                //            Lib3dsVertex Point3 = ThisMesh.vertices[face.index[2]];
                //            this.Normalizes[0][i] = CreateNormalize(Point1, Point2, Point3);
                //        }
                //    }
                //}
                //else
                //{
                //    this.Normalizes = new Lib3dsVertex[newObj.childs.Count][];
                //    int cnt = 0;
                //    foreach (Lib3dsNode node in newObj.childs)
                //    {
                //        Lib3dsMesh ThisMesh = FindLib3dsMeshByName(node.name, this.Model.meshes);
                //        if (ThisMesh == null)
                //        {
                //            continue;
                //        }

                //        this.Normalizes[cnt] = new Lib3dsVertex[ThisMesh.faces.Count];

                //        for (int i = 0; i < ThisMesh.faces.Count; i++)
                //        {
                //            Lib3dsFace face = ThisMesh.faces[i];
                //            Lib3dsVertex Point1 = ThisMesh.vertices[face.index[0]];
                //            Lib3dsVertex Point2 = ThisMesh.vertices[face.index[1]];
                //            Lib3dsVertex Point3 = ThisMesh.vertices[face.index[2]];
                //            this.Normalizes[cnt][i] = CreateNormalize(Point1, Point2, Point3);
                //        }
                //        cnt++;
                //    }
                //}
                break;

            default:
                break;
            }
        }
        /// <summary>
        /// Create a new BuildingObjectLib3DS object.
        /// </summary>
        /// <param name="father">Father node</param>
        /// <param name="type">Type of this object</param>
        /// <param name="id">Id of this object</param>
        /// <param name="model">All models information</param>
        /// <param name="textures">All textures information</param>
        public BuildingObjectLib3DS(BuildingObjectLib3DS father, BuildingObjectType type, uint id,
            Lib3dsFile model, Hashtable textures)
        {
            this.Father = father;
            this.Type = type;
            this.Id = id;
            this.Model = model;
            this.Textures = textures;

            // Initialization
            this.Childs = new Hashtable();
            this.Coordinate = new Vertex();
        }
        /// <summary>
        /// Insert a new child into this object.
        /// </summary>
        /// <param name="newObj">New child</param>
        public void AddNewChild(Lib3dsMeshInstanceNode newObj)
        {
            string[] newObjectLoca = null;

            // Return if location info is illegal
            if ((newObjectLoca = GetLocation(newObj.name)) == null)
                return;

            switch (this.Type)
            {
                case BuildingObjectType.Building:
                    if (this.Childs.Contains(newObjectLoca[0]) == false)
                    {
                        BuildingObjectType childType;
                        if (newObjectLoca[0] == "0")
                        {
                            childType = BuildingObjectType.Outside;
                        }
                        else
                        {
                            childType = BuildingObjectType.Floor;
                        }

                        BuildingObjectLib3DS bObj = new BuildingObjectLib3DS(this, childType,
                            (uint)System.Convert.ToInt32(newObjectLoca[0]), Model, Textures);
                        this.Childs.Add(newObjectLoca[0], bObj);
                        bObj.AddNewChild(newObj);
                    }
                    else
                    {
                        (this.Childs[(newObjectLoca[0])] as BuildingObjectLib3DS).AddNewChild(newObj);
                    }
                    break;
                case BuildingObjectType.Floor:
                    if (this.Childs.Contains(newObjectLoca[1]) == false)
                    {
                        BuildingObjectLib3DS bObj = new BuildingObjectLib3DS(this, BuildingObjectType.Room,
                            (uint)System.Convert.ToInt32(newObjectLoca[1]), Model, Textures);
                        this.Childs.Add(newObjectLoca[1], bObj);
                        bObj.AddNewChild(newObj);
                    }
                    else
                    {
                        (this.Childs[(newObjectLoca[1])] as BuildingObjectLib3DS).AddNewChild(newObj);
                    }
                    break;
                case BuildingObjectType.Room:
                    if (this.Childs.Contains(newObjectLoca[2]) == false)
                    {
                        BuildingObjectLib3DS bObj = new BuildingObjectLib3DS(this, BuildingObjectType.Object,
                            (uint)System.Convert.ToInt32(newObjectLoca[2]), Model, Textures);
                        this.Childs.Add(newObjectLoca[2], bObj);
                        bObj.AddNewChild(newObj);
                    }
                    else
                    {
                        // Same Name... ??? Do not insert it...
                    }
                    break;
                case BuildingObjectType.Outside:
                case BuildingObjectType.Object:
                    this.Object = newObj;
                    //if (this.Object.childs.Count == 0)
                    //{
                    //    Lib3dsMesh ThisMesh = FindLib3dsMeshByName(this.Object.name, this.Model.meshes);
                    //    if (ThisMesh != null)
                    //    {
                    //        this.Normalizes = new Lib3dsVertex[1][];
                    //        this.Normalizes[0] = new Lib3dsVertex[ThisMesh.faces.Count];
                    //        for (int i = 0; i < ThisMesh.faces.Count; i++)
                    //        {
                    //            Lib3dsFace face = ThisMesh.faces[i];
                    //            Lib3dsVertex Point1 = ThisMesh.vertices[face.index[0]];
                    //            Lib3dsVertex Point2 = ThisMesh.vertices[face.index[1]];
                    //            Lib3dsVertex Point3 = ThisMesh.vertices[face.index[2]];
                    //            this.Normalizes[0][i] = CreateNormalize(Point1, Point2, Point3);
                    //        }
                    //    }
                    //}
                    //else
                    //{
                    //    this.Normalizes = new Lib3dsVertex[newObj.childs.Count][];
                    //    int cnt = 0;
                    //    foreach (Lib3dsNode node in newObj.childs)
                    //    {
                    //        Lib3dsMesh ThisMesh = FindLib3dsMeshByName(node.name, this.Model.meshes);
                    //        if (ThisMesh == null)
                    //        {
                    //            continue;
                    //        }

                    //        this.Normalizes[cnt] = new Lib3dsVertex[ThisMesh.faces.Count];

                    //        for (int i = 0; i < ThisMesh.faces.Count; i++)
                    //        {
                    //            Lib3dsFace face = ThisMesh.faces[i];
                    //            Lib3dsVertex Point1 = ThisMesh.vertices[face.index[0]];
                    //            Lib3dsVertex Point2 = ThisMesh.vertices[face.index[1]];
                    //            Lib3dsVertex Point3 = ThisMesh.vertices[face.index[2]];
                    //            this.Normalizes[cnt][i] = CreateNormalize(Point1, Point2, Point3);
                    //        }
                    //        cnt++;
                    //    }
                    //}
                    break;
                default:
                    break;
            }
        }
 /// <summary>
 /// For test...
 /// </summary>
 /// <param name="sender"></param>
 /// <param name="e"></param>
 private void openGLControl_KeyPress(object sender, KeyPressEventArgs e)
 {
     switch (e.KeyChar)
     {
         case 'i':
         case 'I':
             status.eye.z += 5.0f;
             break;
         case 'o':
         case 'O':
             status.eye.z -= 5.0f;
             break;
         case 'a':
         case 'A':
             status.eye.x += 5.0f;
             break;
         case 'D':
         case 'd':
             status.eye.x -= 5.0f;
             break;
         case 'W':
         case 'w':
             status.eye.y += 5.0f;
             break;
         case 's':
         case 'S':
             status.eye.y -= 5.0f;
             break;
         case 'K':
         case 'k':
             this.buildingModelCursor = buildingModelCursor.Move(DrawingEnumTypes.Movement.MenuOut, this.status);
             break;
         case 'L':
         case 'l':
             this.buildingModelCursor = buildingModelCursor.Move(DrawingEnumTypes.Movement.MenuIn, this.status);
             break;
         case 'Y':
         case 'y':
             this.buildingModelCursor = buildingModelCursor.Move(DrawingEnumTypes.Movement.MoveIn, this.status);
             break;
         case 'H':
         case 'h':
             this.buildingModelCursor = buildingModelCursor.Move(DrawingEnumTypes.Movement.MoveOut, this.status);
             break;
         case 'G':
         case 'g':
             this.buildingModelCursor = buildingModelCursor.Move(DrawingEnumTypes.Movement.MoveLeft, this.status);
             break;
         case 'J':
         case 'j':
             this.buildingModelCursor = buildingModelCursor.Move(DrawingEnumTypes.Movement.MoveRight, this.status);
             break;
     }
 }