Skip to main content
GameDev.net gamedev.net
🔒 Locked 🎮 Unity

World - Screen Coordinates

Started by Oliver_zx Feb 25, 2007 at 7:35 AM 7 replies 1.8k views
Original Post
Oliver_zx
Oliver_zx
Hey there, im new on the board as well as within game-development. Im using Managed DX9 within C#. I'm in a need of a convert of the world/screen coordinates. Could someone maybe explain how that converting works. I mean how do i get the X,Y-Pos on the screen of a Vector3 within the world-space ? I guess its not this hard - just to get the idea. The other thing would be the creation of a vector3 that goes through the world-space just by one X,Y-coordinate on screen-space. Well i'd be glad if someone could help me out. The stuff i found on the net were'nt very helpfull to me. And yes, i already ordered a book about math/physics for game-programmers - its just that i dont want to wait and i dont know if that will be within the book as well. ok, thanks alot, oliver
CRACK123
CRACK123
Multiply the local coordinates by world view transformation and then by projection transformation to get to screen space.

position = world * view * projection (should get into screen space);
The more applications I write, more I find out how less I know
Oliver_zx
Oliver_zx
thanks for the fast reply. I got now this:


Vector3 _v =

//my view and projection-matrices takes from my camera-class
Matrix view = Camera.activeCam.ViewMatrix;
Matrix projection = Camera.activeCam.ProjectionMatrix;

//translation to screen-space
Vector3 screen = Vector3.TransformCoordinate(_v, view * projection);


OK, thats made up of your description or better said as far as i understood you right. Here is the result of a tryout:

_v
X: -19
Y: 0
Z: 0

screen
X: -0,1135003
Y: 0
Z: 0,9943276


Ahm obviously i have todo another transformation to the screen-vector as the values doesnt look like they make much sense. Are they relative to the actual screen-size ?
Namethatnobodyelsetook
Namethatnobodyelsetook
After world, view and projection you're in clip space.

X = -1..1 (outside this range is offscreen)
Y = -1..1
Z = 0..1

X +=1
X *= viewportwidth/2.0f;
Y += 1;
Y *= viewportheight/2.0f;

At the point, X,Y are a point relative to the corner of your D3D viewport.

If the viewport isn't at 0,0, you may want to add in the viewport's top,left coordinate to convert the point into a "client" coordinate (ie: client = drawable part of the window, not the frame, titlebar, etc.)

You can use ClientToScreen to convert that point into screen coordinates.
Oliver_zx
Oliver_zx
Ah great...its works. thanks alot.


Stays the problem with 2D -> 3D Coordinates. Maybe someone could help me out with that as well ?
Namethatnobodyelsetook
Namethatnobodyelsetook
Going from 2D to 3D can't produce a point, just a ray. Any point along that ray would be rasterized to the same on-screen 2D point.
void ECamera::CreateWorldRay(const EVec2 &clickpos, const EVec2 &tl, const EVec2 &br,  float fFar, EVec3 &origin, EVec3 &direction, float &fDistance) const{    EVec3 dir;    float fFarToUse = fFar ? fFar : m_oProj.GetFar();    float dx = br.x - tl.x;    float dy = br.y - tl.y;    // Click XY to clip (-1..1), (1..-1) of viewport area.    dir.x = (((clickpos.x - tl.x) / dx) * 2 - 1) / m_matProj.m11;    dir.y = (((clickpos.y - tl.y) / dy) * -2 + 1) / m_matProj.m22;    dir.z = 1;    EVec3 tdir = m_matCamWorld.TransformNormal(dir);    origin = m_matCamWorld.GetPos() + tdir * m_oProj.GetNear();    direction = (fFarToUse - m_oProj.GetNear()) * tdir;    fDistance = direction.Length();    direction /= fDistance;}
Where:
clickpos is where you clicked,
tl and br are the topleft/bottomright of the viewport,
fFar is an optional distance limit. If 0 we use the stored far plane used in the projection matrix.

outputs:
origin
direction
fDistance

endpoint = origin + direction * fDistance.
Oliver_zx
Oliver_zx
Ah thats great...thanks alot. Will try that tomorrow.

Just one question:

matCamWorld == ViewMatrix ?
m_oProj == ProjectionMatrix ?

Well thats what i thought of when i saw the names. But this wont make sense then:
m_matCamWorld.GetPos()


thanks!
oliver

[Edited by - Oliver_zx on February 25, 2007 2:08:12 PM]
Namethatnobodyelsetook
Namethatnobodyelsetook
In my camera I keep both the view matrix and the camera's world matrix.

view = camworld.Inverse();
or
camworld = view.Inverse();

m_oProj is an EProjection which contains the projection matrix, as well as all the components used to create it (perspective, aspect, fov VS. ortho, width, height, as well as near and far).

All my objects share the same method of having a world matrix, using a "frame". Lights, camera, bones, and meshes all work the same, though each is customizable. A frame consists of a local matrix, a world matrix, a parent frame, and a list of child frames, and a dirty flag. There's also a virtual function for re-updating the world matrix. This allows me to attach a camera, light, bone, or mesh to any other camera, light, bone, or mesh. I just make the local matrix be an "offset", and add this frame as a child of the other frame.

Normally, world = local * parent.world (or is that parent.world * local... I never remember), except when parent==0. For a bone frame I make a subclass that refers to the reference pose, in order to mix in the correct inverse reference pose matrix, and override the virtual function that makes the world matrix. Actually, my bone frames, are much more complex, but that's beside the point.

So yeah, I naturally have the camera as a world transform, and create a view matrix out of it when needed. The camera also stores a cached copy of view * proj, as it's needed all the time.
Oliver_zx
Oliver_zx
Ok, thats working now too. But i got a little offset.

When i use my resulting rayOrigin and rayDir on a Mesh within Intersect(...) the result is a bit unaccurate.

My camera looks on a sphere at (0,0,0) from (0,0,-150). So its all quite aligned.
When i decrease the distance from my click to the sphere on the y-axis the intersect returns true maybe at 5-screen-pixels within the sphere while its returns false just after i left the sphere on the negative y-axis after around 5 pixels.

Well the same applies on the other axis too.


May i have an error in the code or is that a normal inaccurracy ?



Thanks again. Greets,
oliver



[Edit: Ah forget it. I forgot to pay attention to the size of the menubar/limits of the frame. Guess thats it. At least it works now when i increased the framesize so the panel is as large as the backbuffer.]

[Edited by - Oliver_zx on February 26, 2007 2:02:19 PM]

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.