Advertisement

Pseudo 3D screen projection issue

Started by December 02, 2014 12:00 AM
12 comments, last by Kugelschreiber 10 years, 2 months ago

Hi there!

I'm in need of assistance in calculating display-coordinates. The problem I've run into is trying to get the illusion of 3d. To be exact, projecting sprites on a 3d-rendered image based on the characters "real world" locations in a 1600x1600 game world. I don't know much about trigonometry and I got my current results pretty much just by dumb luck. I even thought I'd gotten it right the first time before I noticed that the sprite locations didn't match the objects real world coordinates.

I created a chessboard scene and an overhead minimap, displaying the objects real world location, to make sure the coordinates matched. It was quite a bit off. Here's a video showing the problem (there's also some further info in the vid descripion):

I've since had the problem explained to me and now realise the depth is wrong and also that the x-coordinates of the sprites just appear to be correct, due to the squares having the same width.

In my game world, the coordinates start in the top left corner, while in a 3d scene they would be in the center of the scene, so I've adjusted that. I also looked up a guide on using trigonometry to get the correct 3d effect. While I managed to follow it and made the sprites display as in the guide, I couldn't figure out how to apply it to my scene.

The effect I want is for the chessboard surface to act as the full 3d world, and for the sprites to be displayed on it exactly corresponding to the real world coordinates. The camera in this scene was rotated slightly downward when I rendered the image, which might have been dumb as I guess I'll have to account for that angle too.

Thanks for reading! Hoping someone can guide me through this.

There's a chance I misunderstood your problem, but I get feeling you're trying to over engineer this.

Why not to simply render your 2D image in 3D world, right on top of board, and just rotate 2D image so it faces camera?

If I remember correctly you take view matrix, set it's last row (or column) to 0 (the translation part), take inverse and apply to the 2D image (this cancels camera rotation), rest of maths is identical to 3D object: world matrix to position it, etc...

Advertisement

I'm afraid I'm not sure what you mean. The game isn't real 3d. Also, disregard the rotation, as that was just something I figured would affect the perspective. I started over and rendered the image again without the camera rotated (see example below). As you say though, I wonder if I'm not trying to overdo it as well and if I actually have to use trigonometry here.

My previous code for positioning the sprite on the board, when coordinates x:0,y:0 were counting from top-left, looked like this (roughly):

Sprite Y = Chessboard Top-Edge Y + (Chessboard Surface Height * (Character.Y / World Y-Size))

Sprite Scale = Sprite Minimum Scale + (Sprite Max Scale * (Character.Y / World Y-Size))

Sprite X = Screen Center -(World X-Size / 2) * Sprite Scale) +((World X-Size * Sprite Scale) * (Character.X / World X-Size ))

Here's what the new screen looks like.

[attachment=24910:chessboard3Dworld.png]

The Red lines would be X, Green Y and Blue Z, the depth.

How did you draw the board? Just make sure you use the same computations to draw the board and to compute the position of the sprite, and they'll match.

Well, I rendered the image in blender and use it as a background, so the chessboard isn't drawn in code.

After initially giving up, I decided to just focus on the screen Y-position. I broke things down to find out what the result of my calculation needed to be, to show I was on the right track. I measured the height of each square and drew a triangle showing where each square on the screen is, and where the player should appear on the screen depending on where he is in the game world. Drawing the red line inside the triangle shows that it checks out, but I'll be damned if I can get my malfunctioning brain around how to calculate it. Here's the triangle:

[attachment=24925:stoopid.png]

The triangle's sides can't change I assume. So, what I need to figure out is how to get the height between the "adjacent" and "hypoteneuse" from this triangle, depending on where the player is in the real world.

Advertisement

I took the image you posted and I measured on it that the bottom of the board is at y=394, the top is at y=323 and the middle is at y=348. If I think of those points as having z=0, z=3200 and z=1600 respectively, I know that the mapping from z to y has to be a homography, which basically means it has to be of the form

y = (z + A) / (B * z + C)

By plugging in the three points I measured into that formula, we get a system of linear equations in A,B,C, which you can solve using Wolfram Alpha.


double y_from_z(double z) {
  const double A = 1970000.0 / 313.0;
  const double B = 21.0 / 5800.0;
  const double C = 5000.0 / 313.0;
 
  return (z + A) / (B * z + C);
}

Can you check if that part works? If it does, we can then figure out how to change the x coordinate with depth.

Edit: Nevermind, I was using the old background. I'll try again and see how it goes.

I am guessing I didn't understand your coordinate conventions, then. Try this:

const double A = -1485800.0 / 313.0;
const double B = 21.0 / 5008.0;
const double C = -4600.0 / 313.0;

I need to apologize for goofing around about this so much. I was so eager to try your method, not reading the post properly, and I originally tried it on the background shown in the video, as I've been jumping between the two.

So, the first method ended up inverted, and the character started from the bottom of the chessboard surface and moved to the top.

The new one gets the direction right, but when he's midway through the world (at 1600), he's already at the bottom of the surface and moves out of the screen.

This topic is closed to new replies.

Advertisement