• Advertisement
Sign in to follow this  

Basic 3D Help Needed -- Top-down Rendering

This topic is 2679 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