Sign in to follow this  

Pseudo 3D screen projection issue

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

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):

 

https://www.youtube.com/watch?v=EDgnHJP30hk

 

 

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.

Share this post


Link to post
Share on other sites

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...

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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.

 

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

I think you are changing your mind as to whether the board is 1600 units long or 3200 units long.

 

Here we go again:

 

const double A = -2971600.0 / 313.0;
const double B = 21.0 / 5008.0;
const double C = -9200.0 / 313.0;

Share this post


Link to post
Share on other sites

That too! Originally the world size was 1600 and I forgot to mention it, but it seems I did got the range right when I drew the triangle somehow.

 

Anyway, it works perfectly now. I couldn't have done this myself obviously. Thanks!


How would the equivalent look in Wolfram Alpha after you adjusted it according to my coordinates?

Edited by Kugelschreiber

Share this post


Link to post
Share on other sites

Such an incredible relief to finally have this sorted. I don't think I can thank you enough.

Works perfectly with my other scenes as well, of course (that is, after I noticed the numerators for A & C had to be negated).

Share this post


Link to post
Share on other sites

This topic is 1111 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.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this