Jump to content

  • Log In with Google      Sign In   
  • Create Account

3d position to 2d position


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
8 replies to this topic

#1 vivendi   Members   -  Reputation: 123

Like
0Likes
Like

Posted 04 January 2012 - 04:08 PM

I want to convert a 3d position to a 2d screen coordinate. But i'm not really sure how to do that.

I know i need the view, projection and world matrix for the calculations. So i managed to get those. But what next? How can i calculate the 3d position of an object to a 2d screen position?

This is how i get the matrices:
[size="2"]D3DXVECTOR3 vector_2d, vector_3d(0,0,0);[/size]
[size="2"]D3DXMATRIX view_matrix, proj_matrix, world_matrix;[/size]
[size="2"]D3DVIEWPORT9 d3dvp;[/size]

[size="2"]dev->GetTransform( D3DTS_VIEW, &view_matrix );[/size]
[size="2"]dev->GetTransform( D3DTS_PROJECTION, &proj_matrix );[/size]
[size="2"]dev->GetTransform( D3DTS_WORLD, &world_matrix );[/size]
[size="2"]dev->GetViewport( &d3dvp );[/size]
[size="2"]D3DXVec3Project( &vector_2d, &vector_3d, &d3dvp, &proj_matrix, &view_matrix, &world_matrix );[/size]
[size="2"]D3DXVec3Unproject( &vector_3d, &vector_2d, &d3dvp, &proj_matrix, &view_matrix, &world_matrix );[/size]
[size="2"]
[/size]

Sponsor:

#2 iedoc   Members   -  Reputation: 976

Like
4Likes
Like

Posted 04 January 2012 - 10:31 PM

The WordViewProjection matrix is what your looking for. that is the objects position in screen space, where x is -1 to 1, y is -1 to 1 and z is (assuming it's actually on the screen) 0 to 1, which is the depth.

to get the WVP, you just have to multiply the objects world space matrix with the view matrix, then with the projection matrix (in that order, World * View * Projection)

The world matrix stores the objects position (translation), orientation (rotation), and size (scale) in world space, or in other words, all the transformations you do on the model.

The View matrix stores the cameras position, target (what its looking at, or direction it's facing), and up (which is the direction that should be orthogonal to the target, so they make a right angle. it's the cameras "up" direction, and not the worlds up direction) You can get the view matrix from 3 vectors describing it like this:


D3DXMATRIX View;
D3DXVECTOR3 Position = D3DXVECTOR3(0.0f, 0.0f, 0.0f); // Position of your camera
D3DXVECTOR3 Target = D3DXVECTOR3(0.0f, 0.0f, 1.0f);   // Cameras target
D3DXVECTOR3 Up = D3DXVECTOR3(0.0f, 1.0f, 0.0f);	   // Cameras up, should be a unit vector, and orthogonal to Target

D3DXMatrixLookAtLH( &View, &Position, &Target, &Up );

The projection matrix is like a pyramid, where the camera is the point or top of the pyramid, and everything inside the pyramid is what the camera sees. The near and far planes decide how close to the camera and how far away from the camera objects should be clipped, or not rendered. You could look at the far plane as the base of the pyramid and the near plane like cutting the tip off of the pyramid, so that anything that's left inside the pyramid is rendered to the screen. The projection is defined by two floats that describe the near and far planes, an aspect ratio (width/height) and a vertical field of view (FOV, in radians). We can get the projection matrix like this: (notice the (float) next to Width/Height. This is because Width and Height are most likely integers, so without the (float) this would be an integer division, and the result would most likely be a 1 instead of a real aspect ratio)

D3DXMATRIX Projection;
D3DXMatrixPerspectiveFovLH(&Projection, 0.4f*3.14f, (float)Width/Height, 1.0f, 1000.0f);

Finally, after you have all three matrices, you can create the WVP, or world view projection matrix:

D3DXMATRIX WVP;
WVP = World * View * Projection;

The WVP matrix is the objects position in screen space. As i mentioned,above, screen space's x and y are between -1 and 1, and z is 0 to 1. If your looking to turn this into 0 to the width and height of your screen, you will have to do an extra calculation, which i will show you in a minute. Now that we have the WVP, we can get the objects screen space position like this:

D3DXVECTOR3 screenCoord = D3DXVECTOR3(0.0f, 0.0f, 0.0f); // Position of object in screen space
D3DVec3TransformCoord(&screenCoord, &screenCoord, &WVP);

So now how do we turn the screen space from -1 to 1, to 0 to the width and height of your window? easy, just add 1 to x and y, divide it by two, and multiply it by the screen width or height, like this:

screenCoord.x = ((screenCoord.x + 1.0f) / 2.0f) * Width;
screenCoord.y = ((screenCoord.y + 1.0f) / 2.0f) * Height;

Maybe you already knew how to get the world, view, and projection matrices, but i thought i would be thorough and make sure you understand exactly how to do what you want ;)

hope this helps! good luck!
Braynzar Soft - DirectX Lessons & Game Programming Resources!

#3 Tsus   Members   -  Reputation: 1040

Like
2Likes
Like

Posted 05 January 2012 - 03:13 AM

Aloha,

Finally, after you have all three matrices, you can create the WVP, or world view projection matrix:

D3DXMATRIX WVP;
WVP = World * View * Projection;

The WVP matrix is the objects position in screen space. As i mentioned,above, screen space's x and y are between -1 and 1, and z is 0 to 1. If your looking to turn this into 0 to the width and height of your screen, you will have to do an extra calculation, which i will show you in a minute. Now that we have the WVP, we can get the objects screen space position like this:

D3DXVECTOR3 screenCoord = D3DXVECTOR3(0.0f, 0.0f, 0.0f); // Position of object in screen space
D3DVec3TransformCoord(&screenCoord, &screenCoord, &WVP);

So now how do we turn the screen space from -1 to 1, to 0 to the width and height of your window? easy, just add 1 to x and y, divide it by two, and multiply it by the screen width or height, like this:

screenCoord.x = ((screenCoord.x + 1.0f) / 2.0f) * Width;
screenCoord.y = ((screenCoord.y + 1.0f) / 2.0f) * Height;


This is exactly what D3DXVec3Project does. But for starters it is nice to see what is actually going on behind the scenes, so thumbs up for the time you spend. Posted Image Besides, if you do those transformations in shaders you have to do it manually anyway.

Oh, and don't forget the flipping of the y coordinate, since the origin of the window is in a different corner:
screenCoord.y = ((-screenCoord.y + 1.0f) / 2.0f) * Height;
(Only necessary in D3D, not in GL as a side note...)

Greetings!

#4 iedoc   Members   -  Reputation: 976

Like
0Likes
Like

Posted 05 January 2012 - 03:56 AM

oh my bad! thanks for mentioning the flipping of y in screenspace!

i'm not going to lie, i wasn't even aware of D3DXVec3Project, haha, so thanks for that too, i'm pretty sure that's exactly what he's looking for, no sense recreating the wheel ;)
Braynzar Soft - DirectX Lessons & Game Programming Resources!

#5 vivendi   Members   -  Reputation: 123

Like
0Likes
Like

Posted 05 January 2012 - 12:01 PM

Thanks alot guys. Thanks for the indept explanation, very much appreciated! :)

#6 vivendi   Members   -  Reputation: 123

Like
0Likes
Like

Posted 05 January 2012 - 02:09 PM

Hi i still have a question. I though i had everything working but for some reason the screen coordinates are wrong.

This is my function:
D3DXMATRIX view_matrix, proj_matrix, world_matrix;
D3DVIEWPORT9 d3dvp;
D3DXVECTOR2 screen;

m_pD3Ddev->GetTransform( D3DTS_VIEW, &view_matrix );
m_pD3Ddev->GetTransform( D3DTS_PROJECTION, &proj_matrix );
m_pD3Ddev->GetTransform( D3DTS_WORLD, &world_matrix );
m_pD3Ddev->GetViewport( &d3dvp );
D3DXMATRIX WVP;
WVP = world_matrix * proj_matrix * view_matrix;

// Position of object in world
D3DXVECTOR3 screenCoord = D3DXVECTOR3(pos.x, pos.y, pos.z);

// Position of object in screen space
D3DXVec3TransformCoord(&screenCoord, &screenCoord, &WVP);

screenCoord.x = ((screenCoord.x + 1.0f) / 2.0f) * d3dvp.Width;
//screenCoord.y = ((screenCoord.y + 1.0f) / 2.0f) * d3dvp.Height;s
creenCoord.y = ((-screenCoord.y + 1.0f) / 2.0f) * d3dvp.Height;

// Put coords back in vector2s
creen.x = screenCoord.x;
screen.y = screenCoord.y;

return screen;

I position in my game is:
x:1211.037354 y:-411.112854 z:232.125015

The screen result is:
620563.125000 y:158251.343750


Which i weird, because the object was exactly infront of me. Any idea where it goes wrong?

#7 Tsus   Members   -  Reputation: 1040

Like
0Likes
Like

Posted 05 January 2012 - 03:26 PM

The transformation order should be:
WVP = world_matrix * view_matrix * proj_matrix;

You can compare the result to what D3DXVec3Project is giving you. It should yield the same.

#8 AngryWill   Members   -  Reputation: 109

Like
0Likes
Like

Posted 12 April 2012 - 12:17 AM

need to divide by the w coordinate also, as in:



vec4f v4Position(v3ObjectPos.x, v3ObjectPos.y, v3ObjectPos.z, 1.f);
v4ScreenPosition = v4Position * WorldViewProjectionMatrix;
v4ScreenPosition.x /= v4ScreenPosition.w;
v4ScreenPosition.y /= v4ScreenPosition.w;
v4ScreenPosition.x = fScreenWidth * (v4ScreenPosition.x+1.0f)/2.f;
v4ScreenPosition.y = fSreenHeight * (1.0f-((v4ScreenPosition.y+1.f)/2.f));


#9 Anddos   Members   -  Reputation: 501

Like
0Likes
Like

Posted 12 April 2012 - 03:05 AM

try setting the world matrix to the indentity
:)




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS