2D to 3D transforms.

Started by
4 comments, last by Bacardi34 20 years, 6 months ago
Hi, Say you have a 2D object that a camera is looking at. You know how far the camera is from the 2D object, and where the camera is in 3D space and there is a box that outtlines the 2D object in 2D space. I need to figure out how you transform the 4 points of the outline box into 3D space. So basicly you end up with a vertical box in 3D space relative to the camera. Here is a crude diagram of my problem http://members.cox.net/dcmann/programming/crude_camera_diagram.bmp [edit: Is there a way to make this image show up here? Or atleast make it a link? i tride [img][/img] and [/link]... thx ] Having the cameras xyz in world space I need to get the xyz of p1 and p2 in world space assuming that d is a constant for all cameras. I have looked in a few of the books I have and cant find an answer. Also most of the examples and articles I have come across talk about DirectX or OpenGL terms and functions and that is not what I need. Can anyone point me to an article that describes these types of transforms, or maybe give me a hint themselves? Thanks much! [edited by - Bacardi34 on September 24, 2003 9:29:24 PM] [edited by - Bacardi34 on September 24, 2003 9:36:21 PM]
Advertisement
The basic worldspace to screenspace transform looks something like this:

screenX = zoomFactor*( worldX/worldZ ) + screenWidth/2
screenY = zoomFactor*( worldY/worldZ ) + screenHeight/2

This applies if your camrea is looking down the z axis, or after rotation and translation of the objects in the world to account for the camera''s direction relative to the z-axis and location relative to the origin.

Since this is a mapping of three variables onto two, you normally lose some information when projecting into screenspace. As such, when you try to convert back to worldspace from screenspace, you end up with rays in worldspace, instead of points (lines of the form worldX = worldZ*constant). Since you know the z-distance from the camera of the points, however, you can correct for this.

screenX = zoomFactor*( worldX/worldZ ) + screenWidth/2
screenY = zoomFactor*( worldY/worldZ ) + screenHeight/2

are rearranged to

worldX = worldZ*( screenX - screenWidth/2 )/zoomFactor
worldY = worldZ*( screenY - screenHeight/2 )/zoomFactor

where worldZ is now the distance you know your object to be from the screen. After this, you''ll need to do the inverse transform and rotations to get the real world coordinates, instead of just coordinates relative to the camera (which is what the world X, Y and Z above are).
Geoff thanks alot for your help! I figured out another way to do it, but your way is MUCH easier .
Now that I have been playing with these equations for a bit, I''m not sure if they are right, or perhaps I am just not fully understanding what they are doing.
Here is the examples I have been playing with.
Width = 15
Height = 12
zDistance = 8

0,0 is the upper left corner of the screen

P1, 2,2 on the screen maps to -44,-32,8 in the world
WorldX = 8*(2 - 15/2)/1 = -44
WorldY = 8*(2 - 12/2)/1 = -32

P2, 11,9 on screen = 28,12,8
WorldX = 8*(11 - 15/2)/1 = 28
WorldY = 8*(9 - 12/2)/1 = 12

These points just do not seem right to me. The X points seem to be ok, because I understand that objects are outside the screen width because of the field of view. However the Y values are giving me the most confusion because while P1 is above the center point of the screen ( which would be the center point of the camera correct? ) it is below the y axis, and for P2 which is below the center of the screen, it is above the y axis.

The values also seem a bit extreme based on the Z distance of only 8. I am using 1 as the zoomfactor because the cameras in question do not have a zoom option.

Maybe I am doing something wrong?

If (0,0) on the screen is at the top left, then screen y values increased downards, whereas your mental image of y values is increasing in the "up" direction of the view, which is the up direction on the screen. You can fix this by just adding a - sign like so:

screenY = -zoomFactor*( worldY/worldZ ) + screenHeight/2
(or)
worldY = -worldZ*( screenY - screenHeight/2 )/zoomFactor

Regarding the scale of world coordinates to screen coordinates, your chosen zoomFactor is the problem.

For example, if you were doing a projection from 3D -> 2D of the point (1,1,1) using using zoomFactor = 1, and screenWidth = 10,

screenX = zoomFactor*( worldX/worldZ ) + screenWidth/2

screenX = 1*(1/1) + 5 = 6, which is right near the centre of the screen

I could just as easily pick zoomFactor = 5

screenX = 5*(1/1) + 5 = 10, which is right at the edge of the screen.

Conversely, a larger zoomFactor means objects on the edge of the screen will be closer to the z axis when backprojected.

In your case, (2,2), using a zoomFactor of 3

WorldX = 8*(2 - 15/2)/3 = -14.67
WorldY = -8*(2 - 12/2)/3 = 10.67

or, using zoomFactor of 10

WorldX = 8*(2 - 15/2)/10 = -4.4
WorldY = -8*(2 - 12/2)/10 = 3.2

The "zoom" effect of a given zoomFactor is dependent on the size (usually width or the larger direction, if asymmetrical) of the screen as well. It''s really the ratio of the screensize to the zoomfactor that determines the apparent zoom, independent of resolution or screen size. You can work out the view angle that a given screen size and zoomfactor correspond to, if so inclined.
Awsome, thanks alot Geoff!
I was taking a shower this morning and figured out the problem with the y values decreasing on the screen, but thanks verifying my thought about that.
I will play with the equation to get a zoom factor that is acceptable for my project.
Thanks alot for you help!

This topic is closed to new replies.

Advertisement