Herbert

04-23-2003, 04:18 PM

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

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