Sign in to follow this  
Aiursrage2k

Mouse Pick

Recommended Posts

I am trying to pick the closest face of my terrain using the mouse. I know there is the Pick200# example that does this, but it uses a mesh which I am not using. My terrain class, has all the verticies/indicies data, which I can use to form triangles. Ultimately preforming a ray-triangle test. The terrain data is in local space, and I am not sure what space the ray is in. I think I am looking to put them into a common space so that I can do the ray-triangle test, but I cant figure it out. I use the code below (from the Pick200% example) to get a ray.
        POINT ptCursor;
        GetCursorPos( &ptCursor );
        ScreenToClient( DXUTGetHWND(), &ptCursor );

        // Compute the vector of the Pick ray in screen space
        D3DXVECTOR3 v;
        v.x =  ( ( ( 2.0f * ptCursor.x ) / pd3dsdBackBuffer->Width  ) - 1 ) / pmatProj->_11;
        v.y = -( ( ( 2.0f * ptCursor.y ) / pd3dsdBackBuffer->Height ) - 1 ) / pmatProj->_22;
        v.z =  1.0f;

        // Get the inverse view matrix
        const D3DXMATRIX matView = *g_Camera.GetViewMatrix();
        const D3DXMATRIX matWorld = *g_Camera.GetWorldMatrix();
        D3DXMATRIX mWorldView = matWorld * matView;
        D3DXMATRIX m;
        D3DXMatrixInverse( &m, NULL, &mWorldView );

        // 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;

Share this post


Link to post
Share on other sites
The code you posted undoes that view and world transforms, so puts the ray into object space.

The pick sample has a code path that uses its own function to test a ray against a triangle, instead of using the mesh function, so you can use that.

Though in case of the terrain what I did was just traverse the ray and see where it hit the ground. Assuming that your terrain is a grid, that's a lot more efficient than testing triangles. If you keep for each NxN terrain tiles the maximum and minimum height it's easy to speed this even further. (Using a quadtree should be even more efficient, though as I stated elsewhere I always prefer the simplest solution that's fast enough.)

Share this post


Link to post
Share on other sites
You should break it up into steps. Step 1: Convert the mouse screen point into a picking ray that is in World Space. Step 2: Transform the ray's starting point and direction vector into model space.

Step 1:

POINT ptCursor;
GetCursorPos( &ptCursor );
ScreenToClient( DXUTGetHWND(), &ptCursor );

// Convert from screen to view space:
D3DXVECTOR3 RayDirection;
RayDirection.x = ( ( ( 2.0f * ptCursor.x ) / pd3dsdBackBuffer->Width ) - 1 ) / pmatProj->_11;
RayDirection.y = -( ( ( 2.0f * ptCursor.y ) / pd3dsdBackBuffer->Height ) - 1 ) / pmatProj->_22;
RayDirection.z = 1.0f;

// Convert from view to world space:
const D3DXMATRIX matView = *g_Camera.GetViewMatrix();
D3DXMATRIX m;
D3DXMatrixInverse( &m, NULL, &matView );

// transform the ray's direction, w = 0.
D3DXVec3TransformNormal(
&RayDirection,
&RayDirection,
&m);
// normalize the direction
D3DXVec3Normalize(&RayDirection, &RayDirection);

// I am improvising here, since you don't have this code.
// Set the picking ray's starting point to your camera's position:

D3DXVECTOR3 RayPos = *g_Camera.GetPosition();





Step 2:

// Convert the picking ray direction and position into the local space of the object to be tested using the world matrix of the object (note this is not the inverse!!):

const D3DXMATRIX matWorld = *g_Camera.GetWorldMatrix();
D3DXVECTOR3 RayDirectionLocal, RayPosLocal;
D3DXVec3TransformCoord(&RayPosLocal, &RayPos, &matWorld);
D3DXVec3TransformNormal(&RayDirectionLocal, &RayDirection, &matWorld);




Now the ray's position and direction are in the same space as the object.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this