world to screen coordinates
Hi
I want to draw som debug text above my 3D models.
I need to get the screen position where I should draw the 2D text.
How do I go from World to Screen coordinates?
I guess I multiply the world position with the view and projection matrix...
but what after that?
thanks for any help
Quote:Original post by LazyThe short answer is that if you're using DirectX or OpenGL, you already have a function available to transform points from world space to screen space. The OpenGL function is gluProject() - I can't remember off the top of my head what the DX equivalent is.
Hi
I want to draw som debug text above my 3D models.
I need to get the screen position where I should draw the 2D text.
How do I go from World to Screen coordinates?
I guess I multiply the world position with the view and projection matrix...
but what after that?
thanks for any help
you can also calculate it yourself. if you are using a vector camera that uses the modelview matrix to handle the view transformation, use the look-at matrix to transform your 3D point that's above/below your model. then project that point onto the neear X-Y plane using similar triangles (use near-plane dimensions and near-plane distance). then transform the 2D point from world to screen coordinates (you should now have two rectangles of same aspect ratio with the windowed axis typically inverted... i'm sure u can figure this formula out).
[Edited by - yadango on January 6, 2007 11:19:04 PM]
[Edited by - yadango on January 6, 2007 11:19:04 PM]
0. Multiply NewPos = WorldPos * View * Proj
1. Make sure NewPos.z (in/out) is positive. Otherwise, it's behind the camera - so don't draw anything.
2. Add the near plane distance to the z value: NewPos.z += NearPlaneDistance.
3. Convert to 2D coordinates, in 0..1 range, for the x/y components:
NewPos.x = ((NewPos.x / NewPos.z) + 1.0f) * 0.5f;
NewPos.y = ((NewPos.y / NewPos.z) - 1.0f) * -0.5f;
4. Convert 0...1 to the screen size:
NewPos.x *= ScreenWidth;
NewPos.y *= ScreenHeight;
The z component is no longer needed beyond this point. The coordinates and negation of certain values may also change if you use a different coordinate system.
1. Make sure NewPos.z (in/out) is positive. Otherwise, it's behind the camera - so don't draw anything.
2. Add the near plane distance to the z value: NewPos.z += NearPlaneDistance.
3. Convert to 2D coordinates, in 0..1 range, for the x/y components:
NewPos.x = ((NewPos.x / NewPos.z) + 1.0f) * 0.5f;
NewPos.y = ((NewPos.y / NewPos.z) - 1.0f) * -0.5f;
4. Convert 0...1 to the screen size:
NewPos.x *= ScreenWidth;
NewPos.y *= ScreenHeight;
The z component is no longer needed beyond this point. The coordinates and negation of certain values may also change if you use a different coordinate system.
Thanks for the help!
Hm... I tried the code below...
Doesn't work... What have I done wrong?
I fly around with the camera looking towards pos = { 0, 10, 0 }
But new_pos is always outside the screen.
D3DXMATRIX world;D3DXMATRIX final;D3DXMatrixTranslation( &world, pos.x, pos.y, pos.z );final = world * view_matrix * proj_matrix;D3DXVECTOR3 new_pos( final._41, final._42, final._43 ); new_pos.z += 0.1f; //Near clipnew_pos.x = ((new_pos.x / new_pos.z) + 1.0f) * 0.5f;new_pos.y = ((new_pos.y / new_pos.z) - 1.0f) * -0.5f;new_pos.x *= screen_width;new_pos.y *= screen_height;new_pos.z = 0;
That code snippet is a little confusing. It looks like you're projecting twice.
You'd probably be better off using the tried, tested and optimised D3DXVec3Project (with IDirect3DDevice9::GetViewport) to do the transformation for you.
Admiral
You'd probably be better off using the tried, tested and optimised D3DXVec3Project (with IDirect3DDevice9::GetViewport) to do the transformation for you.
Admiral
Here's a couple functions that might come in handy. I can't remember if D3DX has such functions already. I'm pretty sure they don't have the inverse function. That one will save you from inverting matrices just for the operation.
Add that to your code, and this should work..
If not, try printing out the x and z coordinates before the *= screen_ code. If the position is anywhere near the camera, they should be pretty low digits (between -10 to +10).
edit: Sorry, I meant trying printing out the x and y coordinates. Used to working with ground planes.
// Transform a vector with a matrix.void TransformVector(D3DXVECTOR3 &out,const D3DXVECTOR3 &in,const D3DXMATRIX &mat){ out.x = mat._41 + (in.x * mat._11) + (in.y * mat._21) + (in.z * mat._31); out.y = mat._42 + (in.x * mat._12) + (in.y * mat._22) + (in.z * mat._32); out.z = mat._43 + (in.x * mat._13) + (in.y * mat._23) + (in.z * mat._33);}// Same as above, but the result is as though the matrix is invertedvoid TransformVectorInverse(D3DXVECTOR3 &out,const D3DXVECTOR3 &in,const D3DXMATRIX &mat){ D3DXVECTOR3 vd( in.x - mat._41, in.y - mat._42, in.z - mat._43 ); out.x = (vd.x * mat._11) + (vd.y * mat._12) + (vd.z * mat._13); out.y = (vd.x * mat._21) + (vd.y * mat._22) + (vd.z * mat._23); out.z = (vd.x * mat._31) + (vd.y * mat._32) + (vd.z * mat._33);}
Add that to your code, and this should work..
TransformVector( new_pos, pos, view_matrix * proj_matrix );new_pos.z += 0.1f; //Near clipnew_pos.x = ((new_pos.x / new_pos.z) + 1.0f) * 0.5f;new_pos.y = ((new_pos.y / new_pos.z) - 1.0f) * -0.5f;new_pos.x *= screen_width;new_pos.y *= screen_height;new_pos.z = 0;
If not, try printing out the x and z coordinates before the *= screen_ code. If the position is anywhere near the camera, they should be pretty low digits (between -10 to +10).
edit: Sorry, I meant trying printing out the x and y coordinates. Used to working with ground planes.
Quote:Original post by Kest
Here's a couple functions that might come in handy. I can't remember if D3DX has such functions already. I'm pretty sure they don't have the inverse function. That one will save you from inverting matrices just for the operation.
*** Source Snippet Removed ***
Add that to your code, and this should work..TransformVector( new_pos, pos, view_matrix * proj_matrix );new_pos.z += 0.1f; //Near clipnew_pos.x = ((new_pos.x / new_pos.z) + 1.0f) * 0.5f;new_pos.y = ((new_pos.y / new_pos.z) - 1.0f) * -0.5f;new_pos.x *= screen_width;new_pos.y *= screen_height;new_pos.z = 0;
If not, try printing out the x and z coordinates before the *= screen_ code. If the position is anywhere near the camera, they should be pretty low digits (between -10 to +10).
Thanks, that looks really helpful. I'll be bookmarking this. [grin]
I forgot to mention that TransformVector() can't be called with both the in and out vectors as the same variable. You should either catch that as an error inside the function (make sure &in != &out), or switch it with this safe one:
Sorry about that.
void TransformVector(D3DXVECTOR3 &out,const D3DXVECTOR3 &in,const D3DXMATRIX &mat){ float tx = in.x; float ty = in.y; out.x = mat._41 + (tx * mat._11) + (ty * mat._21) + (in.z * mat._31); out.y = mat._42 + (tx * mat._12) + (ty * mat._22) + (in.z * mat._32); out.z = mat._43 + (tx * mat._13) + (ty * mat._23) + (in.z * mat._33);}
Sorry about that.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement