12th flight of 3D development in Windows Phone

Source: Internet
Author: User

After completing the two elements of the spacecraft and the sky, what we need to do now is to combine them so that the spacecraft can fly freely in the sky.

Now we are faced with the following two problems: first, the positional relationship in the space, and second, the collision or traversing between the spacecraft and the sky box.

First, let's look at the first problem. When we draw a ship, we draw on the origin, and when we draw the sky, we also draw on the origin. The coordinates of the spacecraft are so large that the-0.02 zoom matrix is used to narrow down the spacecraft while the side length of the sky box is only two coordinate units, how do we deal with this coordinate relationship? In addition, when rendering the sky box, the camera is located in the box, while when rendering the ship, the camera is located outside the ship, so it is also troublesome to choose the camera position.

Another problem is that if we can draw a ship in a sky box and place a camera correctly, when the ship is flying, the sky will get closer and closer, and it will always reach the border of the sky box, at this time, it will collide with the sky box, and the next moment will be crossed, and it will go out of the sky box. This problem does not seem easy to solve.

In fact, you can solve these two problems by controlling the deep buffer of the Renderer.


We know that the biggest difference between 3D and 2D is that there is a deep relationship, so the Renderer uses the depth buffer for processing in this aspect, using different Z axis coordinates, tracking the frontend and backend relationships of multiple objects in the depth buffer. Simply put, we use a piece of memory to save the depth data of each vertex to the camera, so as to determine the visible rendering, invisible non-rendering, and visually produce depth effects such as occlusion.

Currently, both the sky box and the spacecraft have deep information for rendering, so there will be a sense of position and a possibility of collision. If we can control this depth so that the sky box does not have depth, and only the depth information of the spacecraft and the camera is retained, the above two problems will be solved.

We can still reflect the code. First, an object is generated for skybox and ship respectively in mainscene and added to components. Then, the coordinates of the camera and two objects are determined in loadcontent

protected override void LoadContent ()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch (GraphicsDevice);

            camera = new Camera (this, new Vector3 (100,100,100), new Vector3 (0, 0, -1), Vector3.Up, MathHelper.PiOver4, GraphicsDevice.Viewport.AspectRatio, 0.1f, 500);

            basicEffect = new BasicEffect (GraphicsDevice);

            skyBox.projectionMatrix = camera.projection;
            skyBox.viewMatrix = Matrix.CreateWorld (new Vector3 (0,0,0), new Vector3 (0,0, -1), Vector3.Up);

            ship.projectionMatrix = camera.projection;
            ship.viewMatrix = camera.view * Matrix.CreateTranslation (new Vector3 (4, 0, 10));
            ship.worldMatrix = Matrix.CreateScale (-0.02f) * Matrix.CreateRotationZ (MathHelper.ToRadians (180)) * Matrix.CreateTranslation (new Vector3 (20,0,0));
        }
        In the above code, the camera is first created and placed at (100,100,100) coordinate position, which can better observe the spacecraft.

         In the transformation matrix of the sky box, the projection matrix uses the camera matrix, but the view matrix uses a separate view matrix, that is, the camera is placed at the origin position, and is rendered under the view transformation. This is the same as the camera position in the sky box in the previous section, so only for the sky box, it is not affected by the camera.

        The spacecraft's projection transformation uses a camera matrix, the view transformation uses a camera matrix, and the world matrix uses a matrix transformation, that is, the spaceship is first reduced, then rotated on the z axis by 180 degrees, and then translated 20 times forward to the x axis Coordinate unit. In order to get the proper spaceship direction and ratio.

        In the Update () method, continue to use the previous processing method of rotating the sky box by responding to the screen click.

Next, open the code of the SkyBox class. This time we need to modify the Draw () method. According to the previous solution, we need to remove the depth information when the sky box is rendered. Therefore, the current code becomes:


        public override void Draw (GameTime gameTime)
        {
            GraphicsDevice.SamplerStates [0] = SamplerState.LinearClamp;
            DepthStencilState depthState = new DepthStencilState ();
            depthState.DepthBufferWriteEnable = false;
            GraphicsDevice.DepthStencilState = depthState;
            RasterizerState rasterizerState = new RasterizerState ();
            rasterizerState.CullMode = CullMode.CullClockwiseFace;
            GraphicsDevice.RasterizerState = rasterizerState;
            basicEffect.TextureEnabled = true;
            basicEffect.Texture = texture;
            basicEffect.World = worldMatrix;
            basicEffect.View = viewMatrix;
            basicEffect.Projection = projectionMatrix;
            foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes)
            {
                pass.Apply ();
                Game.GraphicsDevice.DrawUserPrimitives <VertexPositionNormalTexture> (PrimitiveType.TriangleList, box, 0, box.Length / 3);
            }
            base.Draw (gameTime);
            DepthStencilState depthState2 = new DepthStencilState ();
            depthState2.DepthBufferWriteEnable = true;
            GraphicsDevice.DepthStencilState = depthState2;
        }
        In the above code, the drawing part is the same as the original, but there is more use of DepthStencilState object. Before drawing the object, by setting DepthBufferWriteEnable = false, you can prevent the depth information of the object from being written into the depth buffer. Set the property to true to resume operations on the depth buffer.

        Because of this, the renderer ignores the depth of the sky box, so no matter how the depth changes during the flight of the spacecraft, it will not collide with the sky box. The sky box is only used as a background.

        The effect of the program running.


        Of course, you can continue to apply other transformations to the spacecraft, such as the transformation of the hull tilt according to the turning radius, to achieve a more realistic visual effect.



The source code of the sky box is attached:


    public class SkyBox: Microsoft.Xna.Framework.DrawableGameComponent
    {
        Texture2D texture;
        VertexPositionNormalTexture [] box;
        BasicEffect basicEffect;
        // Game game;
        public Matrix worldMatrix {set; get;}
        public Matrix viewMatrix {set; get;}
        public Matrix projectionMatrix {set; get;}

        public SkyBox (Game game)
            : base (game)
        {
            worldMatrix = Matrix.Identity;
            viewMatrix = Matrix.Identity;
            projectionMatrix = Matrix.Identity;
        }

        /// <summary>
        /// Allows the game component to perform any initialization it needs to before starting
        /// to run. This is where it can query for any required services and load content.
        /// </ summary>
        public override void Initialize ()
        {
            Vector3 topLeftFront = new Vector3 (-1,1,1);
            Vector3 topRightFront = new Vector3 (1, 1, 1);
            Vector3 bottomLeftFront = new Vector3 (-1, -1, 1);
            Vector3 bottomRightFront = new Vector3 (1, -1, 1);
            Vector3 topLeftBack = new Vector3 (-1, 1, -1);
            Vector3 topRightBack = new Vector3 (1, 1, -1);
            Vector3 bottomLeftBack = new Vector3 (-1, -1, -1);
            Vector3 bottomRightBack = new Vector3 (1, -1, -1);

            box = new VertexPositionNormalTexture [] {
                new VertexPositionNormalTexture (topLeftFront, new Vector3 (0,0, -1), new Vector2 (0.33f, 0.25f)), // front
                new VertexPositionNormalTexture (topRightFront, new Vector3 (0,0, -1), new Vector2 (0.66f, 0.25f)),
                new VertexPositionNormalTexture (bottomLeftFront, new Vector3 (0,0, -1), new Vector2 (0.33f, 0.5f)),
                new VertexPositionNormalTexture (bottomLeftFront, new Vector3 (0,0, -1), new Vector2 (0.33f, 0.5f)),
                new VertexPositionNormalTexture (topRightFront, new Vector3 (0,0, -1), new Vector2 (0.66f, 0.25f)),
                new VertexPositionNormalTexture (bottomRightFront, new Vector3 (0,0, -1), new Vector2 (0.66f, 0.5f)),

                new VertexPositionNormalTexture (bottomRightFront, new Vector3 (0,0, -1), new Vector2 (0.66f, 0.5f)), // bottom
                new VertexPositionNormalTexture (bottomRightBack, new Vector3 (0,0, -1), new Vector2 (0.66f, 0.75f)),
                new VertexPositionNormalTexture (bottomLeftBack, new Vector3 (0,0, -1), new Vector2 (0.33f, 0.75f)),
                new VertexPositionNormalTexture (bottomLeftBack, new Vector3 (0,0, -1), new Vector2 (0.33f, 0.75f)),
                new VertexPositionNormalTexture (bottomLeftFront, new Vector3 (0,0, -1), new Vector2 (0.33f, 0.5f)),
                new VertexPositionNormalTexture (bottomRightFront, new Vector3 (0,0, -1), new Vector2 (0.66f, 0.5f)),

                new VertexPositionNormalTexture (bottomRightFront, new Vector3 (0,0, -1), new Vector2 (0.66f, 0.5f)), // right
                new VertexPositionNormalTexture (topRightFront, new Vector3 (0,0, -1), new Vector2 (0.66f, 0.25f)),
                new VertexPositionNormalTexture (topRightBack, new Vector3 (0,0, -1), new Vector2 (1.0f, 0.25f)),
                new VertexPositionNormalTexture (topRightBack, new Vector3 (0,0, -1), new Vector2 (1.0f, 0.25f)),
                new VertexPositionNormalTexture (bottomRightBack, new Vector3 (0,0, -1), new Vector2 (1.0f, 0.5f)),
                new VertexPositionNormalTexture (bottomRightFront, new Vector3 (0,0, -1), new Vector2 (0.66f, 0.5f)),

                new VertexPositionNormalTexture (bottomRightBack, new Vector3 (0,0, -1), new Vector2 (0.66f, 0.75f)), // back
                new VertexPositionNormalTexture (topRightBack, new Vector3 (0,0, -1), new Vector2 (0.66f, 1.0f)),
                new VertexPositionNormalTexture (topLeftBack, new Vector3 (0,0, -1), new Vector2 (0.33f, 1.0f)),
                new VertexPositionNormalTexture (topLeftBack, new Vector3 (0,0, -1), new Vector2 (0.33f, 1.0f)),
                new VertexPositionNormalTexture (bottomLeftBack, new Vector3 (0,0, -1), new Vector2 (0.33f, 0.75f)),
                new VertexPositionNormalTexture (bottomRightBack, new Vector3 (0,0, -1), new Vector2 (0.66f, 0.75f)),

                new VertexPositionNormalTexture (bottomLeftBack, new Vector3 (0,0, -1), new Vector2 (0.0f, 0.5f)), // left
                new VertexPositionNormalTexture (topLeftBack, new Vector3 (0,0, -1), new Vector2 (0.0f, 0.25f)),
                new VertexPositionNormalTexture (topLeftFront, new Vector3 (0,0, -1), new Vector2 (0.33f, 0.25f)),
                new VertexPositionNormalTexture (topLeftFront, new Vector3 (0,0, -1), new Vector2 (0.33f, 0.25f)),
                new VertexPositionNormalTexture (bottomLeftFront, new Vector3 (0,0, -1), new Vector2 (0.33f, 0.5f)),
                new VertexPositionNormalTexture (bottomLeftBack, new Vector3 (0,0, -1), new Vector2 (0.0f, 0.5f)),

                new VertexPositionNormalTexture (topLeftFront, new Vector3 (0,0, -1), new Vector2 (0.33f, 0.25f)), // top
                new VertexPositionNormalTexture (topLeftBack, new Vector3 (0,0, -1), new Vector2 (0.33f, 0.0f)),
                new VertexPositionNormalTexture (topRightBack, new Vector3 (0,0, -1), new Vector2 (0.66f, 0.0f)),
                new VertexPositionNormalTexture (topRightBack, new Vector3 (0,0, -1), new Vector2 (0.66f, 0.0f)),
                new VertexPositionNormalTexture (topRightFront, new Vector3 (0,0, -1), new Vector2 (0.66f, 0.25f)),
                new VertexPositionNormalTexture (topLeftFront, new Vector3 (0,0, -1), new Vector2 (0.33f, 0.25f))
            };
            basicEffect = new BasicEffect (Game.GraphicsDevice);

            texture = Game.Content.Load <Texture2D> (@ "Images \ skybox");

            base.Initialize ();
        }

        /// <summary>
        /// Allows the game component to update itself.
        /// </ summary>
        /// <param name = "gameTime"> Provides a snapshot of timing values. </ param>
        public override void Update (GameTime gameTime)
        {
            base.Update (gameTime);
        }

        public override void Draw (GameTime gameTime)
        {
            GraphicsDevice.SamplerStates [0] = SamplerState.LinearClamp;
            DepthStencilState depthState = new DepthStencilState ();
            depthState.DepthBufferWriteEnable = false;
            GraphicsDevice.DepthStencilState = depthState;
            RasterizerState rasterizerState = new RasterizerState ();
            rasterizerState.CullMode = CullMode.CullClockwiseFace;
            GraphicsDevice.RasterizerState = rasterizerState;
            basicEffect.TextureEnabled = true;
            basicEffect.Texture = texture;
            basicEffect.World = worldMatrix;
            basicEffect.View = viewMatrix;
            basicEffect.Projection = projectionMatrix;
            foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes)
            {
                pass.Apply ();
                Game.GraphicsDevice.DrawUserPrimitives <VertexPositionNormalTexture> (PrimitiveType.TriangleList, box, 0, box.Length / 3);
            }
            base.Draw (gameTime);
            DepthStencilState depthState2 = new DepthStencilState ();
            depthState2.DepthBufferWriteEnable = true;
            GraphicsDevice.DepthStencilState = depthState2;
        }
    }
——Welcome to reprint, please indicate the source http://blog.csdn.net/caowenbin ——

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.