Picking Problem

Started by
3 comments, last by diegor82 18 years, 9 months ago
What is the problem in this code that does not work properly?

        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;

Advertisement
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.

www.marklightforunity.com | MarkLight: Markup Extension Framework for Unity

when I run the code,I can not pick any object on the screen.Or It does not respond.
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

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;


This topic is closed to new replies.

Advertisement