I have mapped the red ball of the bottom top-view 2D table onto the top pseudo-3D table using essentially linear interpolation of the points. The red ball's X position on the 3D table is accurate. The *y* coordinate however is very wrong. See the ball on the 3D table isn't nowhere near the pharaoh's feet.

From what I gather, I need to take Z into account somehow, but I don't know how.

If anyone ( R0J0hound ?) has any ideas? I don't need texture mapping, just coordinate mapping.

it's hard to describe this in text, but you need to define you angle of perspective... then by trigonometry you'll be able to map your points.

the x co-ordinate in your example is fine as it does not change no matter what you do, but as you said y/z are a different. it is called 3D projections so feel free to google that term.

so think of it this way ... look at a wire-frame box.. as you move your perspective from looking in at the box on one face and up and over.. x doesn't change, but you'll see some combination of the original face and now another face.. that gives you a bigger space.. and how it contributes to a final co-ordinate depends on the degree of rotation you've done.

if I may suggest Wikipedia... it has a good description, just remember you're keeping one axis constant, so it becomes a lot simpler than what is described here/

Unfortunately I haven't been able to understand vector math too well, and the wikipedia article is way above my league. I just intuitively know I should factor in Z somewhere in my calculations of the Y' coordinate of the ball on the 3D table.

Just think of z as another y, another plane, that works just like the y, except it intersects x, and y, ...oh and scales in size as it gets larger, and closer to the center.

In it's basic form a perspective projection in just dividing x and y by z.

This is the 2d map.
o1 is the top-left corner and p is a point to project.
w
o1----+
| |
| p |h
| |
+-----+
Convert them to u and v to get coordinates from 0-1
u=(p.x-o1.x)/w
v=(p.y-o1.y)/h
Next we have the perspective sprite. w1 and w2 are the widths of the top and bottom. o2 is the top-left and h2 is the height.
w1
o2 ______ -+
/ \ |
/ \ | h2
/ \ |
/____________\ -+
w2
We find the z from v with:
z = w2/lerp(w1, w2, v)
Then we can do the perspective transform with:
screenx = ((u-0.5)/z + 0.5)*w2 + o2.x
screeny = ((v-0.5)/z + 0.5)*h2 + o2.y
[/code:1ikwzr29]

I didn't test it so there may be errors. Also I can't look at the capx till tomorrow.

Z is the distance from the eye, which is at z=0. The camera is at z=1. Anything further will have a greater z which in turn will look smaller since the perspective is calculated with x/z, y/z. Basically the bottom width divided by 1.7 should equal the top width.

1. The idea I had was to find how far away the back edge would have to be if it was that width. Without perspective the top edge should be just as wide as the bottom. With perspective the same projection formula can be used proj_width=width/z. Sovlving for z it come out to z=proj_width/width, and then it's just a matter of interpolating by y or v.

2. The 0.5 is so we're scaling at the center instead of the left edge. U and v are in the range of 0 to 1, so 0.5 is halfway. Also /z is scaling.

As a simple example say you wanted to double the x distance from 320 you'd do:

X=(x-320)*2+320 if instead we wanted to just scale from 0 it would be

Here is a capx with the idea I posted. The only error was "screeny = ((v-0.5)/z + 0.5)*h2 + o2.y" needed to be changed into "screeny = (v/z)*h2 + o2.y".

I tested it with a plane rendered with two different field of views and it seems to become less accurate if I use a fov other than 60. It probably needs to account for that somehow.

Your last capx isn't working right because it's it's scaling from the left instead of the center. See 2 above^

Also for your original capx changing the set y expression to "board.Y + (relativeY*board.Height) /lerp(2,1,relativeY)" seems to get the y working better. You can adjust 2 to change the strength of the effect.

R0J0hound I just logged in to tell you you're absolutely right about the Y axis, that's totally the way to go! And I fixed the X axis calculation like you did.

And thank you *so* much for taking the time to make a capx <3

I think we need a more precise approach. So instead we could use this equation:

screenx = x /(z/d - cz)[/code:3lrqao82]
cz is the z of the camera
and d is the distance from the screen which is the same as tan(fov_angle/2).
Then instead of finding the z of the back edge we'll assume it's 2 and solve for cz and d.
The math worked out to be:
screenx = x/((z-1)*(BottomWidth/TopWidth)+1)
Actually I had a -1 in there so some reason which was throwing it off until I removed it.
I updated my example in my first post. Click to switch between the old method and the new. The new matches the grid much better when the fov is different.

R0J0hound , R0j0 assuming the z of the back edge is "2" seems to have a strange effect: these pairs of rectangles now only work if they are the same relative size.

If I resize the perspective rectangle without resizing the top-down rectangle, the equations don't work at all.

If the top-down rect is 400x400, the perspective rect has to be 970x330. I don't know what this ratio means. Do you?

I don't mind working with this limitation, I just thought I'd make a note of it. Thanks again <3

Um. I've lost track of the math again, but your prototype only worked for a specific ratio.

I tried to change that ratio to something more useful. So, if the world width and the perspective rectangle bottom width are equal, the ratio comes out as 2.425

Did you use actual pixel dimensions when you made the assumption that Z=2 ?? Is that where this number comes from?

Anyhow, it works well for now and until I can go back and re-check your genius math. <3