/// <summary>
        /// DrawScene is our main rendering method. By rendering the entire scene inside of this method,
        /// we enable ourselves to be able to render the scene using any viewport we may want.
        /// </summary>
        private void DrawScene(GameTime gameTime, Viewport viewport, Matrix view, Matrix projection, ChaseCamera camera, string technique)
        {
            // Set our viewport. We store the old viewport so we can restore it when we're done in case
            // we want to render to the full viewport at some point.
            Viewport oldViewport = ScreenManager.GraphicsDevice.Viewport;
            ScreenManager.GraphicsDevice.Viewport = viewport;
            ScreenManager.GraphicsDevice.BlendState = BlendState.Opaque;
            ScreenManager.GraphicsDevice.DepthStencilState = DepthStencilState.Default;
            ScreenManager.GraphicsDevice.SamplerStates[0] = SamplerState.LinearWrap;

            // Here we'd want to draw our entire scene. For this sample, that's just the tank.
            //tank.Draw(Matrix.Identity, view, projection);
            if (shipOne.life > 0)
            {
                DrawModel(playerOneModel, shipOne.World, camera, technique);
            }
            if (shipTwo.life > 0)
            {
                DrawModel(playerTwoModel, shipTwo.World, camera, technique);
            }
            DrawModel(groundModel, Matrix.Identity, camera);

            DrawModel(skyModel, Matrix.Identity, camera);

            //DrawOverlayText();

            DrawAmmo(shipOne, camera);
            DrawAmmo(shipTwo, camera);

            //for (int i = 0; i < bulletOneList.Count; i++)
            //{
            //    DrawModel(bulletModel, bulletOneList[i].World, camera);
            //    DebugShapeRenderer.AddBoundingSphere(bulletOneList[i].bulletSphere, Color.Yellow);
            //}

            //for (int i = 0; i < missileOneList.Count; i++)
            //{
            //    DrawModel(missileModel, missileOneList[i].World, camera);
            //    DebugShapeRenderer.AddBoundingSphere(missileOneList[i].missileSphere, Color.Yellow);
            //}

            //for (int i = 0; i < bulletTwoList.Count; i++)
            //{
            //    DrawModel(bulletModel, bulletTwoList[i].World, camera);
            //    DebugShapeRenderer.AddBoundingSphere(bulletTwoList[i].bulletSphere, Color.Yellow);
            //}

            //for (int i = 0; i < missileTwoList.Count; i++)
            //{
            //    DrawModel(missileModel, missileTwoList[i].World, camera);
            //    DebugShapeRenderer.AddBoundingSphere(missileTwoList[i].missileSphere, Color.Yellow);
            //}

            for (int i = 0; i < buildingArray.Count; i++)
            {
                DrawModel(buildingArray[i].model, buildingArray[i].World, camera, technique);
                DebugShapeRenderer.AddBoundingBox(buildingArray[i].boundingBox, Color.Yellow);
            }

            for (int i = 0; i < powerUpList.Count; i++)
            {
                DrawModel(powerUpList[i].model, powerUpList[i].World, camera, technique);
                DebugShapeRenderer.AddBoundingSphere(powerUpList[i].boundingSphere, Color.Yellow);
            }

            DebugShapeRenderer.AddBoundingSphere(shipOne.boundingSphere, Color.Yellow);
            DebugShapeRenderer.AddBoundingSphere(shipTwo.boundingSphere, Color.Yellow);

            DebugShapeRenderer.AddBoundingBox(runway01_bounding, Color.Yellow);
            DebugShapeRenderer.AddBoundingBox(runway02_bounding, Color.Yellow);

            DebugShapeRenderer.Draw(gameTime, camera.View, camera.Projection);

            missileTrailParticles.SetCamera(camera.View, camera.Projection);
            explosionParticles.SetCamera(camera.View, camera.Projection);
            explosionSmokeParticles.SetCamera(camera.View, camera.Projection);

            missileTrailParticles.Draw(gameTime);
            explosionParticles.Draw(gameTime);
            explosionSmokeParticles.Draw(gameTime);

            // Now that we're done, set our old viewport back on the device
            ScreenManager.GraphicsDevice.Viewport = oldViewport;
        }
        void DrawModel(Model model, Matrix world, ChaseCamera camera,
                       string effectTechniqueName)
        {
            // Look up the bone transform matrices.
            Matrix[] transforms = new Matrix[model.Bones.Count];

            model.CopyAbsoluteBoneTransformsTo(transforms);

            // Draw the model.
            foreach (ModelMesh mesh in model.Meshes)
            {
                foreach (Effect effect in mesh.Effects)
                {
                    // Specify which effect technique to use.
                    effect.CurrentTechnique = effect.Techniques[effectTechniqueName];

                    Matrix localWorld = transforms[mesh.ParentBone.Index] * world;

                    effect.Parameters["World"].SetValue(localWorld);
                    effect.Parameters["View"].SetValue(camera.View);
                    effect.Parameters["Projection"].SetValue(camera.Projection);
                }

                mesh.Draw();
            }
        }
        private void DrawAmmo(Ship ship, ChaseCamera camera)
        {
            // Draw bullets
            for (int i = 0; i < ship.bullets.Count; i++)
            {
                DrawModel(bulletModel, ship.bullets[i].World, camera);
                DebugShapeRenderer.AddBoundingSphere(ship.bullets[i].bulletSphere, Color.Yellow);
            }

            // Draw missiles
            for (int i = 0; i < ship.missiles.Count; i++)
            {
                DrawModel(missileModel, ship.missiles[i].World, camera);
                DebugShapeRenderer.AddBoundingSphere(ship.missiles[i].missileSphere, Color.Yellow);
            }
        }
        /// <summary>
        /// Simple model drawing method. The interesting part here is that
        /// the view and projection matrices are tak    en from the camera object.
        /// </summary>        
        private void DrawModel(Model model, Matrix world, ChaseCamera camera)
        {
            Matrix[] transforms = new Matrix[model.Bones.Count];
            model.CopyAbsoluteBoneTransformsTo(transforms);

            foreach (ModelMesh mesh in model.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.EnableDefaultLighting();
                    effect.World = transforms[mesh.ParentBone.Index] * world;
                    effect.DirectionalLight0.Enabled = true;
                    effect.DirectionalLight0.DiffuseColor = Color.White.ToVector3();
                    //effect.DirectionalLight0.SpecularColor = Color.White.ToVector3();
                    effect.DirectionalLight0.Direction = Vector3.Normalize(new Vector3(-1, -1.5f, 0));
                    effect.DirectionalLight1.Enabled = true;
                    effect.DirectionalLight1.DiffuseColor = Color.LightGray.ToVector3();
                    effect.DirectionalLight1.Direction = Vector3.Normalize(new Vector3(1, -1.5f, -1));
                    effect.DirectionalLight2.Enabled = true;
                    effect.DirectionalLight2.DiffuseColor = Color.Orange.ToVector3();
                    effect.DirectionalLight2.Direction = Vector3.Normalize(new Vector3(0, -1.5f, -1));

                    effect.SpecularColor = Vector3.Zero;
                    effect.FogColor = Color.LightGoldenrodYellow.ToVector3();
                    effect.FogEnabled = true;
                    effect.FogStart = 100000.0f;
                    effect.FogEnd = 1000000.0f;

                    // Use the matrices provided by the chase camera
                    effect.View = camera.View;
                    effect.Projection = camera.Projection;
                }
                mesh.Draw();
            }
        }
        /// <summary>
        /// Load graphics content for the game.
        /// </summary>
        public override void Activate(bool instancePreserved)
        {
            if (!instancePreserved)
            {
                if (Content == null)
                    Content = new ContentManager(ScreenManager.Game.Services, "Content");

                // collision debugging
                DebugShapeRenderer.Initialize(ScreenManager.GraphicsDevice);

                #region SplitScreen

                // Create the texture we'll use to draw our viewport edges.
                blank = new Texture2D(ScreenManager.GraphicsDevice, 1, 1);
                blank.SetData(new[] { Color.White });

                if (OptionsMenuScreen.currentSplitScreen == OptionsMenuScreen.SplitScreen.Horizontal)
                {
                    // Create the viewports
                    playerOneViewport = new Viewport
                    {
                        MinDepth = 0,
                        MaxDepth = 1,
                        X = 0,
                        Y = 0,
                        Width = ScreenManager.GraphicsDevice.Viewport.Width,
                        Height = ScreenManager.GraphicsDevice.Viewport.Height / 2,
                    };
                    playerTwoViewport = new Viewport
                    {
                        MinDepth = 0,
                        MaxDepth = 1,
                        X = 0,
                        Y = ScreenManager.GraphicsDevice.Viewport.Height / 2,
                        Width = ScreenManager.GraphicsDevice.Viewport.Width,
                        Height = ScreenManager.GraphicsDevice.Viewport.Height / 2,
                    };
                }
                else
                {
                    // Create the viewports
                    playerOneViewport = new Viewport
                    {
                        MinDepth = 0,
                        MaxDepth = 1,
                        X = 0,
                        Y = 0,
                        Width = ScreenManager.GraphicsDevice.Viewport.Width / 2,
                        Height = ScreenManager.GraphicsDevice.Viewport.Height,
                    };
                    playerTwoViewport = new Viewport
                    {
                        MinDepth = 0,
                        MaxDepth = 1,
                        X = ScreenManager.GraphicsDevice.Viewport.Width / 2,
                        Y = 0,
                        Width = ScreenManager.GraphicsDevice.Viewport.Width / 2,
                        Height = ScreenManager.GraphicsDevice.Viewport.Height,
                    };
                }

                // Create the view and projection matrix for each of the viewports
                playerOneView = Matrix.CreateLookAt(
                    new Vector3(400f, 900f, 200f),
                    new Vector3(-100f, 0f, 0f),
                    Vector3.Up);
                playerOneProjection = Matrix.CreatePerspectiveFieldOfView(
                    MathHelper.PiOver4, playerOneViewport.AspectRatio, 10f, 5000f);

                playerTwoView = Matrix.CreateLookAt(
                    new Vector3(0f, 800f, 800f),
                    Vector3.Zero,
                    Vector3.Up);
                playerTwoProjection = Matrix.CreatePerspectiveFieldOfView(
                    MathHelper.PiOver4, playerTwoViewport.AspectRatio, 10f, 5000f);

                #endregion

                #region ChaseCamera

                gameFont = Content.Load<SpriteFont>("Fonts/gamefont");
                if (SelectionScreen.playerOneSelect == 1)
                    playerOneModel = Content.Load<Model>("Models/F-16/F-16_Game");
                else
                    playerOneModel = Content.Load<Model>("Models/MiG-29/MiG-29_Game");
                if (SelectionScreen.playerTwoSelect == 1)
                    playerTwoModel = Content.Load<Model>("Models/F-16/F-16_Game");
                else
                    playerTwoModel = Content.Load<Model>("Models/MiG-29/MiG-29_Game");
                groundModel = Content.Load<Model>("Models/Terrain/terrain");
                bulletModel = Content.Load<Model>("Models/Bullet/bullet");
                missileModel = Content.Load<Model>("Models/Missile/missile");
                skyModel = Content.Load<Model>("Models/SkyDome/skydome");

                if (SelectionScreen.playerOneSelect == 1)
                    shipOne = new Ship(ScreenManager.GraphicsDevice, (PlayerIndex)ControllingPlayer, new Vector3(-74000, 0, 400000), new Vector3(0, 0, -1));
                else
                    shipOne = new Ship(ScreenManager.GraphicsDevice, (PlayerIndex)ControllingPlayer, new Vector3(-74000, 0, 400000), new Vector3(0, 0, -1));

                if (SelectionScreen.playerTwoSelect == 1)
                    shipTwo = new Ship(ScreenManager.GraphicsDevice, (PlayerIndex)ScreenManager.ControllingPlayerTwo, new Vector3(18000, 0, -400000), new Vector3(0, 0, 1));
                else
                    shipTwo = new Ship(ScreenManager.GraphicsDevice, (PlayerIndex)ScreenManager.ControllingPlayerTwo, new Vector3(18000, 0, -400000), new Vector3(0, 0, 1));

                // Create the chase camera
                cameraOne = new ChaseCamera();
                cameraTwo = new ChaseCamera();

                // Set the camera offsets
                cameraOne.DesiredPositionOffset = new Vector3(0.0f, 2000.0f, 3500.0f);
                cameraOne.LookAtOffset = new Vector3(0.0f, 150.0f, 0.0f);
                cameraTwo.DesiredPositionOffset = new Vector3(0.0f, 2000.0f, 3500.0f);
                cameraTwo.LookAtOffset = new Vector3(0.0f, 150.0f, 0.0f);

                // Set camera perspective
                cameraOne.NearPlaneDistance = 1.0f;
                cameraOne.FarPlaneDistance = 1550000.0f;
                cameraTwo.NearPlaneDistance = 1.0f;
                cameraTwo.FarPlaneDistance = 1550000.0f;

                // Set the camera aspect ratio
                // This must be done after the class to base.Initalize() which will
                // initialize the graphics device.
                cameraOne.AspectRatio = (float)playerOneViewport.Width / playerOneViewport.Height;
                cameraTwo.AspectRatio = (float)playerTwoViewport.Width / playerTwoViewport.Height;

                // Perform an inital reset on the camera so that it starts at the resting
                // position. If we don't do this, the camera will start at the origin and
                // race across the world to get behind the chased object.
                // This is performed here because the aspect ratio is needed by Reset.
                UpdateCameraChaseTarget();
                cameraOne.Reset();
                cameraTwo.Reset();

                #endregion

                #region HUD
                pOneHUD = new HUD(ScreenManager.Game, playerOneViewport, PlayerIndex.One);
                pTwoHUD = new HUD(ScreenManager.Game, playerTwoViewport, PlayerIndex.Two);
                #endregion

                #region Particles

                explosionParticles = new ParticleSystem(ScreenManager.Game, Content, "Particles/ExplosionSettings");
                explosionSmokeParticles = new ParticleSystem(ScreenManager.Game, Content, "Particles/ExplosionSmokeSettings");
                missileTrailParticles = new ParticleSystem(ScreenManager.Game, Content, "Particles/ProjectileTrailSettings");

                explosionSmokeParticles.DrawOrder = 200;
                missileTrailParticles.DrawOrder = 300;
                explosionParticles.DrawOrder = 400;

                explosionParticles.Visible = false;
                explosionSmokeParticles.Visible = false;
                missileTrailParticles.Visible = false;

                ScreenManager.Game.Components.Add(missileTrailParticles);
                ScreenManager.Game.Components.Add(explosionParticles);
                ScreenManager.Game.Components.Add(explosionSmokeParticles);

                #endregion

                #region CartoonShader

                postprocessEffect = Content.Load<Effect>("CartoonShader/PostprocessEffect");
                sketchTexture = Content.Load<Texture2D>("CartoonShader/SketchTexture");
                Effect cartoonEffect = Content.Load<Effect>("CartoonShader/CartoonEffect");

                ChangeEffectUsedByModel(playerOneModel, cartoonEffect);
                ChangeEffectUsedByModel(playerTwoModel, cartoonEffect);

                // Create two custom rendertargets.
                PresentationParameters pp = ScreenManager.GraphicsDevice.PresentationParameters;

                sceneRenderTarget = new RenderTarget2D(ScreenManager.GraphicsDevice,
                                                       pp.BackBufferWidth, pp.BackBufferHeight, false,
                                                       pp.BackBufferFormat, pp.DepthStencilFormat);

                normalDepthRenderTarget = new RenderTarget2D(ScreenManager.GraphicsDevice,
                                                             pp.BackBufferWidth, pp.BackBufferHeight, false,
                                                             pp.BackBufferFormat, pp.DepthStencilFormat);

                #endregion

                // Initalise the motor
                //pOneVibrateRight = 0;
                //pOneVibrateLeft = 0;
                //pTwoVibrateRight = 0;
                //pTwoVibrateLeft = 0;

                // Initalise player's warning when out of battlezone
                pOneWarning = false;
                pTwoWarning = false;

                for (int i = 0; i < 100; i++)
                {
                    Building building = new Building(ScreenManager.Game);
                    buildingArray.Add(building);
                }

                for (int i = 0; i < 20; i++)
                {
                    PowerUp powerup = new PowerUp(ScreenManager.Game);
                    powerUpList.Add(powerup);
                }

                int width_Z = 170000;
                int width_X = 45000;

                runway01_bounding = new BoundingBox(new Vector3(-74000 - width_X, 0, 400000 - width_Z),
                   new Vector3(-74000 + width_X, 10000, 400000 + width_Z));

                runway02_bounding = new BoundingBox(new Vector3(18000 - width_X, 0, -400000 - width_Z),
                    new Vector3(18000 + width_X, 10000, -400000 + width_Z));

                //remove buildings if collide with runway
                for (int i = buildingArray.Count - 1; i >= 0; i--)
                {
                    if (buildingArray[i].boundingBox.Intersects(runway01_bounding) ||
                        buildingArray[i].boundingBox.Intersects(runway02_bounding))
                    {
                        buildingArray.RemoveAt(i);
                    }
                }

                //remove buildings when collide with each other.
                for (int i = buildingArray.Count - 1; i >= 1; i--)
                {
                    if (buildingArray[i].boundingBox.Intersects(buildingArray[i - 1].boundingBox))
                    {
                        buildingArray.RemoveAt(i);
                    }
                }

                //re-position powerups when collide with buildings
                for (int i = powerUpList.Count - 1; i >= 0; i--)
                {
                    for (int k = buildingArray.Count - 1; k >= 0; k--)
                    {
                        while(powerUpList[i].boundingSphere.Intersects(buildingArray[k].boundingBox))
                        {
                            powerUpList[i].position = new Vector3(randomiser.Next(-460000, 500000),
                                                                randomiser.Next(5000, 450000),
                                                                randomiser.Next(-460000, 500000));
                        }
                    }
                }

                //re-position powerups when collide with runways
                for (int i = powerUpList.Count - 1; i >= 0; i--)
                {
                    while (powerUpList[i].boundingSphere.Intersects(runway01_bounding) ||
                        powerUpList[i].boundingSphere.Intersects(runway02_bounding))
                    {
                        powerUpList[i].position = new Vector3(randomiser.Next(-460000, 500000),
                                                            randomiser.Next(5000, 450000),
                                                            randomiser.Next(-460000, 500000));
                    }
                }

                textFader = (TextFader)ScreenManager.Game.Services.GetService(typeof(TextFader));

                // once the load has finished, we use ResetElapsedTime to tell the game's
                // timing mechanism that we have just finished a very long frame, and that
                // it should not try to catch up.
                ScreenManager.Game.ResetElapsedTime();
            }
        }