Hi!
I am working on developing a 3D rendering engine base both DirectX8.0 and OpenGL,which allow user to select between the two 3D API. I am programing on Win2K+VC++6.0 environment.Now I want to implement ray picking objects by mouse and the objects would be transformed in world space.I known there is a sample about Ray Picking with Object Transformations base DirectX8.0,following as: http://www.mvps.org/directx/articles/improved_ray_picking.htm
code section:
void CMyD3DApplication::Pick()
{
D3DXVECTOR3 vPickRayDir;
D3DXVECTOR3 vPickRayOrig;
// Get the pick ray from the mouse position
if( GetCapture() )
{
POINT ptCursor;
GetCursorPos( &ptCursor );
ScreenToClient( m_hWnd, &ptCursor );
// Compute the vector of the pick ray in screen space
D3DXVECTOR3 v;
v.x = ( ( ( 2.0f * ptCursor.x ) / m_d3dsdBackBuffer.Width ) - 1 ) / m_matProj._11;
v.y = -( ( ( 2.0f * ptCursor.y ) / m_d3dsdBackBuffer.Height ) - 1 ) / m_matProj._22;
v.z = 1.0f;
// Get the inverse view matrix
D3DXMATRIX m;
D3DXMatrixInverse( &m, NULL, &m_matView );
// 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;
D3DXVec3Normalize(&vPickRayDir,&vPickRayDir);
vPickRayOrig.x = m._41;
vPickRayOrig.y = m._42;
vPickRayOrig.z = m._43;
// calc origin as intersection with near frustum
vPickRayOrig+=vPickRayDir*NEAR_Z;
// iterate through the scne and find closest match
CObj *hitObj=m_pScene->Pick(&vPickRayOrig,&vPickRayDir,FAR_Z-NEAR_Z);
}
}
CObj *CObj::Pick(D3DXVECTOR3 *pvNear, D3DXVECTOR3 *pvDir, float maxDist, CObj *pObj)
{
// clear the hit flag
m_bHit=FALSE;
// do we have a mesh?
if (m_pMesh) {
// yes, convert ray to model space
D3DXVECTOR3 vNear,vDir;
D3DXMATRIX invMat;
D3DXMatrixInverse(&invMat,NULL,&m_combinedMat);
D3DXVec3TransformCoord(&vNear,pvNear,&invMat);
D3DXVec3TransformNormal(&vDir,pvDir,&invMat);
// test for intersection
BOOL bHit;
DWORD dwIndex;
float u,v;
float dist;
D3DXIntersect(m_pMesh,&vNear,&vDir,&bHit,&dwIndex,&u,&v,&dist,NULL,NULL);
// is there an intersection?
if (bHit) {
// yes, is it beyond the far plane?
if (dist<maxDist) {
// no, have we previously found a hit?
if (pObj) {
// yes, but is this one closer?
if (pObj->m_fHitDist>dist) {
// yes, clear hit flag of object with previously detected intersection
pObj->m_bHit=FALSE;
// set our hit flag
m_bHit=TRUE;
// store distance to the hit
m_fHitDist=dist;
// set hit object pointer to point to this object
pObj=this;
}
// no, this is the first hit
} else {
// set the hit flag
m_bHit=TRUE;
// save distance to intersection
m_fHitDist=dist;
// set hit object pointer to point to this object
pObj=this;
}
}
}
}
// perform pick operation on children and siblings
if (m_pChild)
pObj=m_pChild->Pick(pvNear,pvDir,maxDist,pObj);
if (m_pSibling)
pObj=m_pSibling->Pick(pvNear,pvDir,maxDist,pObj);
// return hit object pointer to caller
return pObj;
}
But I don’t known how I can implement same function base OpenGL because there is no independent world and view transformation matrix can be get.Can anybody give me some hints about this?The key problem I want to solve is how to convert 2D mouse to a 3D ray.
Then I can test intersection between the objects of scene and the ray and determine the selected objects.
Thanks in advance
Best Regards
Herbert