D3DXMATRIXA16 matProj;
pDevice->GetTransform( D3DTS_PROJECTION, &matProj );
POINT ptCursor;
GetCursorPos( &ptCursor );
ScreenToClient( Application.GetWindowHandle(), &ptCursor );
// Compute the vector of the pick ray in screen space
D3DXVECTOR3 v;
v.x = ( ( ( 2.0f * ptCursor.x ) / SCREEN_WIDTH ) - 1 ) / matProj._11;
v.y = -( ( ( 2.0f * ptCursor.y ) / SCREEN_HEIGHT ) - 1 ) / matProj._22;
v.z = 1.0f;
// Get the inverse of the composite view and world matrix
D3DXMATRIXA16 matView, matWorld, m;
pDevice->GetTransform( D3DTS_VIEW, &matView );
pDevice->GetTransform( D3DTS_WORLD, &matWorld );
m = matWorld * matView;
D3DXMatrixInverse( &m, NULL, &m );
// Transform the screen space pick ray into 3D space
vPickRayDir.x = v.x*m._11 + v.y*m._21 + v.z*m._31;
vPickRayDir.y = v.x*m._12 + v.y*m._22 + v.z*m._32;
vPickRayDir.z = v.x*m._13 + v.y*m._23 + v.z*m._33;
vPickRayOrig.x = m._41;
vPickRayOrig.y = m._42;
vPickRayOrig.z = m._43;
Picking Problem
What is the problem in this code that does not work properly?
What results are you getting? The calculations of screen space -> clip coordinates looks correct. The transform into view space seems right.. but you might need to normalize the pick-ray direction vector.
Hi,
Basically you did a parametrization error:
The v should be
D3DXVECTOR4 v;
v.x = ... right;
v.y = ... right;
v.z = "t";
v.w = 1.0;
then multiply v with the inverse Projection Matrix (not just a division, since w!=0).
Then multiply as you did (from eye to local coordinates via inv-view and inv-world).
There are several methods to compute the 'ray', here it is shown the most easy one:
set "t" to 0.0 and compute the relative local position(let say vertex 'A').
set "t" to 1.0 and compute the relative local position(let say vertex 'B').
Now the ray is
r(t) = t*(B-A) + A
this ray goes from near to far.
The w cannot be ignored...
Diego
Basically you did a parametrization error:
The v should be
D3DXVECTOR4 v;
v.x = ... right;
v.y = ... right;
v.z = "t";
v.w = 1.0;
then multiply v with the inverse Projection Matrix (not just a division, since w!=0).
Then multiply as you did (from eye to local coordinates via inv-view and inv-world).
There are several methods to compute the 'ray', here it is shown the most easy one:
set "t" to 0.0 and compute the relative local position(let say vertex 'A').
set "t" to 1.0 and compute the relative local position(let say vertex 'B').
Now the ray is
r(t) = t*(B-A) + A
this ray goes from near to far.
The w cannot be ignored...
Diego
Another solution (more efficient from a computational perspective)
matWVP := ((matWorld * matView) * matProj)
invWVP := Inverse(matWVP)
ray direction:
d.x := invWVP._31
d.y := invWVP._32
d.z := invWVP._33
d.w := invWVP._34
ray initial position:
p.x := x0*invWVP._11 + y0*invWVP._21 + invWVP._41
p.y := x0*invWVP._12 + y0*invWVP._22 + invWVP._42
p.z := x0*invWVP._13 + y0*invWVP._23 + invWVP._43
p.w := x0*invWVP._14 + y0*invWVP._24 + invWVP._44
where x0 and y0 are device independent coordinates:
x0 = ( ( ( 2.0f * ptCursor.x ) / SCREEN_WIDTH ) - 1.0 )
y0 = -( ( ( 2.0f * ptCursor.y ) / SCREEN_HEIGHT ) - 1.0 )
at the end, if you want forget the fourth component, you have to do
d := d/d.w;
p := p/p.w;
matWVP := ((matWorld * matView) * matProj)
invWVP := Inverse(matWVP)
ray direction:
d.x := invWVP._31
d.y := invWVP._32
d.z := invWVP._33
d.w := invWVP._34
ray initial position:
p.x := x0*invWVP._11 + y0*invWVP._21 + invWVP._41
p.y := x0*invWVP._12 + y0*invWVP._22 + invWVP._42
p.z := x0*invWVP._13 + y0*invWVP._23 + invWVP._43
p.w := x0*invWVP._14 + y0*invWVP._24 + invWVP._44
where x0 and y0 are device independent coordinates:
x0 = ( ( ( 2.0f * ptCursor.x ) / SCREEN_WIDTH ) - 1.0 )
y0 = -( ( ( 2.0f * ptCursor.y ) / SCREEN_HEIGHT ) - 1.0 )
at the end, if you want forget the fourth component, you have to do
d := d/d.w;
p := p/p.w;
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement