Translating world from unit to viewport

Started by
2 comments, last by NEXUSKill 13 years, 2 months ago
Hey guys,
I've been playing around with several projects to better understand the Matrix transforms but have been running into issues.

I created a simple program to bounce a primitive rectangle around the screen using simple collision detection.

I modified the code from our colored primitive lesson to create a ball class as a DrawableGameComponent:

----------------------------------------------------------------
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Sample
{
public class Ball : Microsoft.Xna.Framework.DrawableGameComponent
{
VertexPositionColor[] ballData;
Vector2 ballPosition;
Vector2 ballVelocity;
float ballSize;
float ballWidth;
float ballHeight;

public Ball(Game game)
: base(game)
{

}

public override void Initialize()
{
ballPosition = new Vector2(0.1f, 0.4f);
ballVelocity = new Vector2(0.5f, 0.5f);
ballSize = 0.1f;

base.Initialize();
}

protected override void LoadContent()
{
// Initialize ball vertices
ballData = new VertexPositionColor[4];
ballData[0] = new VertexPositionColor();
ballData[0].Position = new Vector3(-0.5f, -0.5f, 0);
ballData[0].Color = Color.Red;
ballData[1] = new VertexPositionColor();
ballData[1].Position = new Vector3(-0.5f, 0.5f, 0);
ballData[1].Color = Color.Red;
ballData[2] = new VertexPositionColor();
ballData[2].Position = new Vector3(0.5f, -0.5f, 0);
ballData[2].Color = Color.Red;
ballData[3] = new VertexPositionColor();
ballData[3].Position = new Vector3(0.5f, 0.5f, 0);
ballData[3].Color = Color.Red;

ballWidth = ballData[3].Position.X - ballData[0].Position.X;
ballHeight = ballData[3].Position.Y - ballData[0].Position.Y;

base.LoadContent();
}

public override void Update(GameTime gameTime)
{
ballPosition += ballVelocity * (float)gameTime.ElapsedGameTime.TotalSeconds;

// Check for collision
CheckCollision();

base.Update(gameTime);
}

public override void Draw(GameTime gameTime)
{
GraphicsDeviceManager graphics = Game.Services.GetService(
typeof(GraphicsDeviceManager)) as GraphicsDeviceManager;
BasicEffect effect = Game.Services.GetService(
typeof(BasicEffect)) as BasicEffect;

effect.World = Matrix.CreateScale(ballSize) * Matrix.CreateTranslation(ballPosition.X, ballPosition.Y, 0);
effect.CurrentTechnique.Passes[0].Apply();
graphics.GraphicsDevice.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.TriangleStrip,
ballData, 0, 2);

base.Draw(gameTime);
}

private void CheckCollision()
{
// Check for X collision
if (ballPosition.X < -2.0f)
{
ballPosition.X = -2.0f;
ballVelocity.X *= -1;
}

else if (ballPosition.X > 2.0f)
{
ballPosition.X = 2.0f;
ballVelocity.X *= -1;
}
// Check for Y collision
else if (ballPosition.Y < -1.2f)
{
ballPosition.Y = -1.2f;
ballVelocity.Y *= -1;
}

else if (ballPosition.Y > 1.2f)
{
ballPosition.Y = 1.2f;
ballVelocity.Y *= -1;
}
}
}
}

----------------------------------------------------------------

This code works just fine. The "ball" bounces around the screen but I had to hard code the collision detection boundaries from -2.0 to 2.0 and -1.2 to 1.2 instead of using the Viewport width and height properties.

Most of the various XNA sources talk about using unit values because it keeps the math simpler. This makes sense, but the piece I'm missing is how do I then transform the primitive position to regular screen coordinates? I could iterate through the VertexPositionColor array and multiply each Position vertex, but using that approach, I might as well just hard code the final screen coordinates to begin with.

I know there's something painfully obvious I'm overlooking but I'm just not catching it. Thanks in advance for any suggestions.
Advertisement
The Projection and View matrices, which are part of what should be you camera object (you did not post anything that indicates how you are using these matrices) are what translate world transformations (scale, orientation, and position) to screen coordinates, and vice versa, if you have screen coordinates and you swap the multiplication order of the matrices, you get world transformation back.

Piece of advice, your ball object is retrieving the graphics device manager and basic effect shader every frame, this is inefficient. You should find another way to do things.
One way would be to store permanently these two objects in your Render GameComponent and have it access the vertex buffers to be drawn directly.


Game making is godlike

LinkedIn profile: http://ar.linkedin.com/pub/andres-ricardo-chamarra/2a/28a/272


Thanks for the suggestions regarding the graphics device manager. These are the kinds of tips that I hope to pick up during this course. As far a the Perspective and View Matrices are concerned, I just did the standard assignment found in most of the samples and updated the references to them in my BasicEffect object which I access as a game service to avoid having to expose it globally or pass it around to each separate class as described in Ch 5 of the text. I'll post the additional code tonight, but here's basically what I did:

For the Perspective Matrix, I used Matrix.CreatePerspectiveFieldOfView passing in the PiOver4 MathHelper property to set the angle to 45 degrees, the Viewport AspectRatio, and set the near and far clipping planes to 1.0f and 100.0f.

For the View Matrix I set the camera reference to (0, 0, 3), target pointing at the origin, and up vector using Vector.Up.

I get how the perspective matrix works to create a viewing box that encompasses the size of the screen, but the piece I'm not seeing in any of the samples is the World matrix being multiplied by some Vector or Matrix that scales it from those smaller unit values we pass in when drawing the primitives to something that matches our standard 800x480 Viewport. So when I move the rectangle in the update method, it only takes fractional increments to move it from one side of the screen to the other.

Thanks again for any advice.
Well, just before calling draw on the effect, you set the world matrix of the object you are about to draw, the multiplication of the world matrix to the view and projection is done internally by the effect, this allows you to change the world matrix for each object while view is not likely to change more than once per frame (updating camera position) and projection is even less likely to change during gameplay.
Game making is godlike

LinkedIn profile: http://ar.linkedin.com/pub/andres-ricardo-chamarra/2a/28a/272


This topic is closed to new replies.

Advertisement