Jump to content
  • Advertisement
Sign in to follow this  
zer0sum

Basic 3D Help Needed -- Top-down Rendering

This topic is 2858 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have a great 2D game right now where I am using sprites as spaceships. I want to upgrade my technology and start using 3d Models instead of sprites.

What I want to do is create a 3D world that exists on a plane, and I want to have a top-down camera view like so:

_____________ +x
|
|
|
|
|
|
+y

This will let me use all my existing code for ship movement and projectiles, etc. All I want to do is create a 3D world that mirrors my current 2D world, and I want to draw a model at the correct position and depth on the screen.

Here is my current draw function.

public void Draw(GameTime gameTime)
{

starfield.Draw(cam.Pos, cam.Zoom);

spriteBatch.Begin(SpriteSortMode.FrontToBack,
BlendState.NonPremultiplied,
null, null, null, null,
cam.get_transformation(device));


int camx = (int)cam.Pos.X;
int camy = (int)cam.Pos.Y;

//Rectangle blackRect = new Rectangle(-10000, -10000, 100000 + (int)WorldSize.X, 100000 + (int)WorldSize.Y);
//spriteBatch.Draw(MinimapTex, blackRect, Color.Black);
// this view rectangle shifts around with the camera to provide a bit of a parallax feel to the background image
Rectangle viewRectangle = new Rectangle(camx - (screenWidth / 2) - camx / 10, camy - (screenHeight / 2) - camy / 10, screenWidth + 200, screenWidth + 200);
spriteBatch.Draw(backgroundTexture, viewRectangle, null, Color.White, 0, Vector2.Zero, SpriteEffects.None, 0.01f);

viewRectangle = new Rectangle(camx - (screenWidth / 2) - camx / 8, camy - (screenHeight / 2) - camy / 8, screenWidth + 200, screenWidth + 200);
spriteBatch.Draw(debrisfield2Texture, viewRectangle, null, Color.White, 0, Vector2.Zero, SpriteEffects.None, 0.1f);

viewRectangle = new Rectangle(camx - (screenWidth / 2) - camx / 5, camy - (screenHeight / 2) - camy / 5, screenWidth + 200, screenWidth + 200);
spriteBatch.Draw(debrisfieldTexture, viewRectangle, null, Color.White, 0, Vector2.Zero, SpriteEffects.None, 0.1f);



foreach (Ship ship in ShipList)
{
DrawShipInfo(spriteBatch, ship);
ship.Draw(gameTime, spriteBatch);
}
// draw the alpha-blended particles
particleEffectManager.Draw(spriteBatch, "AlphaBlend", cam);
spriteBatch.End();

// draw the additive particles
spriteBatch.Begin(SpriteSortMode.Texture,
BlendState.Additive,
null, null, null, null,
cam.get_transformation(device));


particleEffectManager.Draw(spriteBatch, "Additive", cam);
spriteBatch.End();


debrisField.Draw(cam.Pos, cam.Zoom);

}



So I know that this is a broad question, but what do I need to do to set up a 3D world with a camera that is slaved to my 2D camera? I'm speaking in very general terms.

Here is what I have been trying: I have replaced my regular ship's draw function with this DrawModel:

private void DrawModel()
{

Vector3 world_Position = new Vector3(device.Viewport.Width / 2, -device.Viewport.Height / 2, 0);
Vector3 cameraPosition = new Vector3(world.GetCam().Pos, 1000);
// Copy any parent transforms.
Matrix[] transforms = new Matrix[xwingModel.Bones.Count];
xwingModel.CopyAbsoluteBoneTransformsTo(transforms);

// Draw the model. A model can have multiple meshes, so loop.
foreach (ModelMesh mesh in xwingModel.Meshes)
{
// This is where the mesh orientation is set, as well
// as our camera and projection.
foreach (BasicEffect effect in mesh.Effects)
{

effect.EnableDefaultLighting();
effect.World = transforms[mesh.ParentBone.Index] *
Matrix.CreateRotationZ(-this.rotation) * Matrix.CreateScale(.50f)
* Matrix.CreateTranslation(new Vector3(-Position.X, Position.Y, 400));
effect.View = Matrix.CreateLookAt(cameraPosition,
Vector3.Zero, new Vector3(0, -1, 0));
effect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f), aspectRatio, 1.0f, 10000.0f);
//effect.Projection = Matrix.CreateOrthographic(1280, 720, 1, 1000);
}
// Draw the mesh, using the effects set above.
mesh.Draw();
}

}


This function draws a model but it's just not right. I know that I'm not creating my 3D world properly.

So again, the real question here is:

1) How do I initialize a 3D world and set a camera up with a top-down perspective?

2) How do I ensure that my models are drawn onto the same Z-plane as my current 2D ships? If my 2D ship moves 50 pixels, I want to move my 3D ship 50 pixels.

Code examples appreciated.

Share this post


Link to post
Share on other sites
Advertisement
Some additional information:

My world right now is set up as a 5000x5000 area and the ships can move freely about inside this area. The ships all have a Vector2 "Position".

One of the issues I think I have is that I'm not creating a 3D world that is aware of my 2D world. When I tell a 3D model to draw at a position, it draws in Screen Space and not my world space.

I think that I need to create the world at a higher level that inside my draw code. I'm a real noob with 3D stuff, so again, lengthier explanations are appreciated.

Share this post


Link to post
Share on other sites
I would start by representing your positions as Vector3 with z=0;
Place your camera somewhere it can look at the XY plane ((0,0,50) for example);
Orient the camera so it is looking down the -z axis;
Set your projection matrix to an ortho projection;


Share this post


Link to post
Share on other sites
I'm not particularly familiar with C#, but I believe using Matrix.OrthoLH or OrthoOffCenterLH will be your starting point, for which you can google.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!