• Advertisement
Sign in to follow this  

Intersecting mouse and plane

This topic is 3453 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have known camera position and a infinite plane defined by 3 points in space... what is the easiest and most accurate way to get exact 3d coordinates where the mouse cursor intersects with plane. I have read on many places how buggy and inaccurate unproject function is, is there alternative? Thanks

Share this post


Link to post
Share on other sites
Advertisement
I've never had a problem with unprojecting myself. I know of no bugs. However, use your favorite method of unprojecting the mouse.

I use:

// return direction vector and set "position" if not null
D3DXVECTOR3 CD3DApp::Unproject(POINT pt, D3DXVECTOR3 *position)
{
D3DXMATRIX projMat, viewMat, worldMat;
D3DVIEWPORT9 vp;

D3DXVECTOR3 pOut0, pOut1, pV1((float)pt.x,(float)pt.y,1.0),pV0((float)pt.x,(float)pt.y,0.0f),normDir;

m_pDevice->GetTransform(D3DTS_PROJECTION,&projMat);
m_pDevice->GetTransform(D3DTS_VIEW,&viewMat);
m_pDevice->GetTransform(D3DTS_WORLD,&worldMat);
m_pDevice->GetViewport(&vp);
D3DXVec3Unproject(&pOut0, &pV0, &vp, &projMat, &viewMat, &worldMat);
D3DXVec3Unproject(&pOut1, &pV1, &vp, &projMat, &viewMat, &worldMat);
if( position ) *position = pOut0;
D3DXVec3Normalize(&normDir,&D3DXVECTOR3(pOut1-pOut0));
return normDir;
}

Given the mouse point in pt (client coordinates), I return the direction of the vector under the mouse. If position is not null, I return the mouse point at the screen (near-plane).

Given a plane of three vertices, calculate the normal to that plane = D3DXVec3Cross(&norm,&D3DXVECTOR3(v[2]-v[0]),&D3DXVECTOR3(v[1]-v[0]));

With the mouse position P (from position in Unproject above), and the mouse direction D (return value of Unproject above), call the following function.

float VPlane::TParam(D3DXVECTOR3 P, D3DXVECTOR3 D)
{
float nDot, pnDot;
if( (nDot=D3DXVec3Dot(&D,&norm))==0 ) return FLT_MAX;
pnDot = D3DXVec3Dot(&D3DXVECTOR3(v[0]-P),&norm);
return pnDot/nDot;
}

By example, call the return value from TParam "t".

The world position in the plane under the mouse position is P+t*D. If t==FLT_MAX, then the mouse vector is parallel with the plane and doesn't intersect it.

If t > 0, you're "above" the plane; if t < 0, you're "below" the plane.

Share this post


Link to post
Share on other sites
This is very confusing

Can someone help me modify Tutorial 3: Matrices example from DXSDK in c++ od c# please
I would just need to have printed on the screen where the mouse ray intersected the rotating triangle (world x,y,z coordinates of intersection)

thanks

[Edited by - jakovn on August 25, 2008 7:45:59 AM]

Share this post


Link to post
Share on other sites
This is the modified code from DX picking example from SDK

D3DXVECTOR3 v0 = pVertices[pIndices[3 * i + 0]].p;
D3DXVECTOR3 v1 = pVertices[pIndices[3 * i + 1]].p;
D3DXVECTOR3 v2 = pVertices[pIndices[3 * i + 2]].p;

// Check if the Pick3 ray passes through this point
if( IntersectTriangle( vPick3RayOrig, vPick3RayDir, v0, v1, v2,
&fDist, &fBary1, &fBary2 ) )
{

//I added this

D3DXVECTOR3 start(vPick3RayOrig.x,vPick3RayOrig.y,vPick3RayOrig.z);// ray start position
D3DXVECTOR3 ray=vPick3RayDir;

// create infinite plane
D3DXPLANE vPlane;
D3DXPlaneFromPoints(&vPlane,
&D3DXVECTOR3(v0.x,v0.y,v0.z),
&D3DXVECTOR3(v1.x,v1.y,v1.z),
&D3DXVECTOR3(v2.x,v2.y,v2.z));

// infinite plane normal
D3DXVECTOR3 vPlaneNormal(vPlane.a,vPlane.b,vPlane.c);

if(D3DXVec3Dot(&vPlaneNormal,&ray)==0)
{
// parallel to plane
} else {
float amount = -(D3DXPlaneDotCoord(&vPlane,&start))
/ D3DXVec3Dot(&vPlaneNormal,&ray);

D3DXVECTOR3 iPoint = start+(ray*amount);
}


And I thought I will in ipoint.x, ipoint.y, ipoint.z get world coordinates but I get some strange small numbers independent where I clicked
What is wrong?

Share this post


Link to post
Share on other sites
I can't help you specifically with that code but this is how I intersect a plane in C++, very simple:

BOOL PlaneIntersect(Ray ray, Point3 normal, Point3 planepos, Point3 &pos)
{
float bup = normal % (planepos - ray.pos);
float hup = ray.dir % normal;
if (hup == 0) return FALSE; //ray and plane are paralell
pos = ray.pos + (ray.dir * (bup / hup));
return TRUE;
}






% means the dot product here. "normal" is the normal of the plane and "planepos" is any positon on that plane. The Point3 class holds 3 floats for x,y and z. "ray.pos" and "ray.dir" are also class Point3.

Share this post


Link to post
Share on other sites
OK, I used D3DXVECTOR3 instead of Point3
I get this error:
Error 2 error C2676: binary '%' : 'D3DXVECTOR3' does not define this operator or a conversion to a type acceptable to the predefined operator

Share this post


Link to post
Share on other sites
Quote:
Original post by jakovn
OK, I used D3DXVECTOR3 instead of Point3
I get this error:
Error 2 error C2676: binary '%' : 'D3DXVECTOR3' does not define this operator or a conversion to a type acceptable to the predefined operator

Ok, from your example in the previous post this is the way to do the dot product with D3DXVECTOR3:

float theDot = D3DXVec3Dot(&vPlaneNormal,&ray);


Does the same thing as...

float theDot = vPlaneNormal % ray;


...in my example.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement