XNA for C#
DirectX 9 for C#
DirectX 9 for C++
DirectX 9 for VB
Forum
   
My XNA Book
      
       Go to section on this site

Additional info


Latest Forum posts

 Account settings
  Posted by: igthorn
  When: 21/04/2014 at 10:20:00

 Pavtube 2014 Easter Deals with 20% off
  Posted by: igthorn
  When: 21/04/2014 at 10:16:23

 20% off on iMedia Converter for Mac
  Posted by: VIKIVannessa
  When: 20/04/2014 at 01:35:54

 Pavtube Video Converter Ultimate Deal
  Posted by: VIKIVannessa
  When: 20/04/2014 at 01:35:50

 Easter Day Deals
  Posted by: Applefly
  When: 19/04/2014 at 22:18:14

 40% OFF Pavtube DVD Ripper for Mac
  Posted by: VIKIVannessa
  When: 19/04/2014 at 02:02:54

 DVD Ripper with 40% off
  Posted by: VIKIVannessa
  When: 19/04/2014 at 02:02:22

 Get DVD Ripper Wind/Mac + $14 Coupon
  Posted by: VIKIVannessa
  When: 19/04/2014 at 02:02:03

 Backup DVD Escape Plan
  Posted by: Applefly
  When: 17/04/2014 at 06:00:12

 Disney DVDs to MP4
  Posted by: Applefly
  When: 17/04/2014 at 05:56:07


Ads

World Space coordinates and the camera

Last chapter we drew a triangle, using 'pretransformed' coordinates. These coordinates allow you to directly specify their position on the screen. However, you will usually use the untransformed coordinates, the so called World space coordinates, which we specify in 3D coordinates. These allow you to create a whole scene using simple 3D coordinates, and, also very important, to position a camera through which the user will look at the scene.

Let’s start by redefining our triangle coordinates in 3D World space. Replace the code in our SetUpVertices method with this code:

 private void SetUpVertices()
 {
     vertices = new VertexPositionColor[3];
 
     vertices[0].Position = new Vector3(0f, 0f, 0f);
     vertices[0].Color = Color.Red;
     vertices[1].Position = new Vector3(10f, 10f, 0f);
     vertices[1].Color = Color.Yellow;
     vertices[2].Position = new Vector3(10f, 0f, -5f);
     vertices[2].Color = Color.Green;
 }

As you can see, from here on we’ll be using the Z-coordinate as well.

Because we are no longer using pretransformed screen coordinates (where x and y coordinate should be in the [-1, 1] region), we need to select a different technique from our effect file. I called the technique ‘ColoredNoShading’, to reflect that we’ll be rendering a Colored 3D image, but did not yet specify any lighting/shading information. So make this adjustment in our Draw method:

 effect.CurrentTechnique = effect.Techniques["ColoredNoShading"];

Let's run this code.

Very nice, your triangle has disappeared again. Why's that? Easy, because you haven't told XNA yet where to position the camera in your 3D World, and where to look at!

To position our camera, we need to define some matrices. Stop!! matrices?!?

First a small word about matrices. We define our points in 3D space. Because our screen is 2D, it is only logical that our 3D points somehow need to be ‘transformed’ to 2D space. This is done by multiplying our 3D positions with a matrix. So in short, you should see a matrix simply as a mathematical element that holds a transformation. If you multiply a 3D position with such a matrix, you get the transformed position. (If you want to know more about matrices, you can find more info in the Extra Reading section of this site)

Because there are a lot of properties that need to be defined when transforming our points from 3D world space to our 2D screen, this transformation is split in 2 steps, so we get 2 matrices. First add these variables to the top of your class:

 Matrix viewMatrix;
 Matrix projectionMatrix;

To initialize them ,add this code to our program:

 private void SetUpCamera()
 {
     viewMatrix = Matrix.CreateLookAt(new Vector3(0, 0, 50), new Vector3(0, 0, 0), new Vector3(0, 1, 0));
     projectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, device.Viewport.AspectRatio, 1.0f, 300.0f);
 }

These 2 lines seem complicated, but all they do is defining the position and the lens of the camera.

The first line creates a matrix that stores the position and orientation of the camera, through which we look at the scene. The first argument defines the position of the camera. We position it 50 units on the positive Z axis. The next parameter sets the target point the camera is looking at. We will be looking at our (0,0,0) 3D origin. At this point, we have defined the viewing axis of our camera, but we can still rotate our camera around this axe. So we still need to define which vector will be considered as 'up'.

The second line creates a matrix which stores how the camera looks at the scene, much like defining the lens if you will. The first argument sets the view angle, 45 degrees in our case. Then we set the view aspect ratio, the ratio between the width and height of your screen. In our case of a 500x500 window this will equal 1, but this will be different for other resolutions. The last parameters define the view range. Any objects closer to the camera than 1f will not be shown. Any object further away than 300.0f won't be shown either. These distances are called the near and the far clipping planes, since all objects not between these planes will be clipped (=not drawn).

Recipe 2-1 explains how to create a camera in much more detail.

Now we have these matrices, we need to pass it to our technique, where they will be combined. This is done by the next lines of code, which we need to add to our Draw method:

 effect.Parameters["xView"].SetValue(viewMatrix);
 effect.Parameters["xProjection"].SetValue(projectionMatrix);
 effect.Parameters["xWorld"].SetValue(Matrix.Identity);

Although the first 2 lines are explained above, they are discussed in much more detail in Series 3. The third line sets another parameter, which is discussed in the next chapter.

Don’t forget to call this method from within the LoadContent method:

 SetUpCamera();

Now run the code. You should see the image below: a triangle, of which the bottom-right corner is not exactly below the top-right corner. This is because you have assigned the bottom-right corner a negative Z coordinate, positioning it a bit further away from the camera than the other corners.

One important thing you should notice before you start experimenting: you'll see the green corner of the triangle is on the right side of the window, which seems normal because you defined it on the positive x-axis. So, if you would position your camera on the negative z-axis:

 viewMatrix = Matrix.CreateLookAt(new Vector3(0, 0, -50), new Vector3(0, 0, 0), new Vector3(0, 1, 0));

you would expect to see the green point in the left half of the window. Try to run this now.

This might not be exactly what you expected. Something very important has happened. XNA only draws triangles that are facing the camera. XNA specifies that triangles facing the camera should be defined clockwise relative to the camera. If you position the camera on the negative z-axis, the corner points of the triangle in our vertices array will be defined counter-clockwise relative to the camera, and thus will not be drawn!

See Recipe 5-6 for a more detailed explanation on backface culling and some examples.

Culling can greatly improve performance, as it can reduce the number of triangles to be drawn. However, when designing an application, it’s better to turn culling off by putting these lines of code in the beginning of your Draw method:

 RasterizerState rs = new RasterizerState();
 rs.CullMode = CullMode.None;
 device.RasterizerState = rs;

This will simply draw all triangles, even those not facing the camera. You should note that this should never be done in a final product, because it slows down the drawing process, as all triangles will be drawn, even those not facing the camera! (Except for some cases where you intend to achieve this effect). Now put the camera back to the positive part of the Z axis.




DirectX Tutorial 4 - World space

If you appreciate the amount of time I spend creating and updating
these pages, feel free to donate -- any amount is welcome !



Click here to go to the forum on this chapter!

Or click on one of the topics on this chapter to go there:
  • ArgumentNullException
          I get an ArgumentNullException in line 112 (line ...
  • World Space - Normal0 is missing
          Ive been following the XNA tutorials using VS 2010...
  • XNA triangle - camera problem
          my problem is the line: device.DrawUserPrimitives...
  • Vertices in a class
          I have gotten the vertice procedure down and wante...
  • FX Bug/problem
          well i ame working withe VS 2008 and xna beta and ...
  • Negative Z
          Hello, This tutorials are really helpful, thank...
  • Viewing Angle question
          I don't understand what is meant by "viewing Ang...
  • Game1 invalid namespace?
          I have no idea whats going on here, I was having a...
  • 3D vs 2D
          Hi, first of all I'd like to add myself to the li...
  • Viewport sans AspectRatio
          Viewport does not contain a definition for 'Aspec...
  • Black Triangle
          Hey, When I render the scene, I see the triangl...
  • InvalidOperationException
           Thanks for this amazing tutorial. I have a probl...
  • Error in program
          device.DrawIndexedPrimitives(PrimitiveType.Triangl...
  • Aspect Ratio (minor?) bug
          Hi I don't know if anyone noticed this but the...
  • No Triangle?
          I have completed the "drawing a triangle" chapte...
  • Problem Running this Chapter
          Yah, Thanks for this amazing tutorial. I have a p...
  • viewing axis
          Hi, I have a question about the viewing axis. At s...
  • Camera Question
          I was wondering how you gotten these points? Ma...
  • PiOver4 should be 45°
          In the code: Matrix.CreatePerspectiveFieldOfVie...
  • Set up camera
          Hi riemer, I went through your tutorials and I ...
  • Instance Members and Static Class
          Hey, Just want to say thanks for making these t...
  • The World Is Spinning! =D
          First off I'd like to thank you for these tutoria...
  • Culling
          Wouldnt it be more efficient to put the device.ren...
  • Problem with drawing triangle
          I just finished the Drawing a Triangle tutorial an...
  • Null expception
          when compiling and running (F5). I get a NullRe...
  • Issue & Workaround
          Just wanted to input a problem I encounterd & a wo...
  • It doesn't want to run
          Hi! Please help, what can be the problem. I copied...
  • World Space Minor Confusion
          Hi Riemer, Great Tutorial. I just thought I wou...
  • Invalid Function Call
          I have copied the code from what you had at the bo...
  • Can't work?
          Wow this is a great set of tutorials i just have 1...



    You can try these exercises to practice what you've learned:
  • Experiment with different positions for your 3D vertices and camera position.
    Here's the complete code for this chapter :

     using System;
     using System.Collections.Generic;
     using System.Linq;
     using Microsoft.Xna.Framework;
     using Microsoft.Xna.Framework.Audio;
     using Microsoft.Xna.Framework.Content;
     using Microsoft.Xna.Framework.GamerServices;
     using Microsoft.Xna.Framework.Graphics;
     using Microsoft.Xna.Framework.Input;
     using Microsoft.Xna.Framework.Media;
     
     namespace Series3D1
     {
         public class Game1 : Microsoft.Xna.Framework.Game
         {
             GraphicsDeviceManager graphics;
             SpriteBatch spriteBatch;
             GraphicsDevice device;
     
             Effect effect;
             VertexPositionColor[] vertices;
             Matrix viewMatrix;
             Matrix projectionMatrix;
     
             public Game1()
             {
                 graphics = new GraphicsDeviceManager(this);
                 Content.RootDirectory = "Content";
             }
     
             protected override void Initialize()
             {
                 graphics.PreferredBackBufferWidth = 500;
                 graphics.PreferredBackBufferHeight = 500;
                 graphics.IsFullScreen = false;
                 graphics.ApplyChanges();
                 Window.Title = "Riemer's XNA Tutorials -- 3D Series 1";
     
                 base.Initialize();
             }
     
             protected override void LoadContent()
             {
                 spriteBatch = new SpriteBatch(GraphicsDevice);
     
                 device = graphics.GraphicsDevice;

                effect = Content.Load<Effect> ("effects");
                 SetUpCamera();
     
                 SetUpVertices();
             }
     
             protected override void UnloadContent()
             {
             }
     
             private void SetUpVertices()
             {
                 vertices = new VertexPositionColor[3];
     
                 vertices[0].Position = new Vector3(0f, 0f, 0f);
                 vertices[0].Color = Color.Red;
                 vertices[1].Position = new Vector3(10f, 10f, 0f);
                 vertices[1].Color = Color.Yellow;
                 vertices[2].Position = new Vector3(10f, 0f, -5f);
                 vertices[2].Color = Color.Green;
             }
     
             private void SetUpCamera()
             {
                 viewMatrix = Matrix.CreateLookAt(new Vector3(0, 0, 50), new Vector3(0, 0, 0), new Vector3(0, 1, 0));
                 projectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, device.Viewport.AspectRatio, 1.0f, 300.0f);
             }
     
             protected override void Update(GameTime gameTime)
             {
                 if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                     this.Exit();
     
                 base.Update(gameTime);
             }
     
             protected override void Draw(GameTime gameTime)
             {
                 device.Clear(Color.DarkSlateBlue);
     
                 RasterizerState rs = new RasterizerState();
                 rs.CullMode = CullMode.None;
                 device.RasterizerState = rs;
     
                 effect.CurrentTechnique = effect.Techniques["ColoredNoShading"];
                 effect.Parameters["xView"].SetValue(viewMatrix);
                 effect.Parameters["xProjection"].SetValue(projectionMatrix);
                 effect.Parameters["xWorld"].SetValue(Matrix.Identity);
                 foreach (EffectPass pass in effect.CurrentTechnique.Passes)
                 {
                     pass.Apply();
     
                     device.DrawUserPrimitives(PrimitiveType.TriangleList, vertices, 0, 1, VertexPositionColor.VertexDeclaration);
                 }
     
                 base.Draw(gameTime);
             }
         }
     }
     
     


    Google
     
    Webwww.riemers.net


    If you appreciate the amount of time I spend creating and updating
    these pages, feel free to donate -- any amount is welcome !



    - Website design & XNA + DirectX code : Riemer Grootjans -
    ©2003 - 2011 Riemer Grootjans
  • Translations

    This site in English
    This site in Korean
    This site in Czech

    Microsoft MVP Award



    2007 - 2011 MVP Award
    DirectX - XNA

    Contents

    News
    Home
    Forum
    XNA 2.0 Recipes Book (8)
    XNA 3.0 Recipes Book (8)
    Downloads
    Extra Reading (3)
    Matrices: geometrical
    Matrix Mathematics
    Homogenous matrices
    Community Projects (1)
    Tutorials (160)
    XNA 4.0 using C# (89)
    2D Series: Shooters (22)
    3D Series 1: Terrain (13)
    Starting a project
    The effect file
    The first triangle
    World space
    Rotation - translation
    Indices
    Terrain basics
    Terrain from file
    Keyboard
    Adding colors
    Lighting basics
    Terrain lighting
    VertexBuffer & IndexBuffer
    3D Series 2: Flightsim (14)
    3D Series 3: HLSL (18)
    3D Series 4: Adv. terrain (19)
    Short Tuts (3)
    DirectX using C# (54)
    DirectX using C++ (15)
    DirectX using VB (2)
    -- Expand all --


    Thank you!

    Support this site --
    any amount is welcome !

    Stay up-to-date

    I don't have the time to keep a News section, so stay informed about the updates by clicking on this RSS file!