Sign in to follow this  
r_bewick

C++ directx9 finding 3d mouse position

Recommended Posts

Hi I am trying to find the 3d mouse position in my game. I am making a large box and then picking it to find the distance the mouse is away from the box to get my mouse positions and I add the camera position to that. But something is wrong. I draw a cube where my mouse is and when I move my mouse away from the centre, the cube moves away a lot faster than my mouse does. And when I change camera position this changes the cubes position as well. I just want to make the cube follow my mouse perfectly. I have no idea what I am doing wrong.
D3DXVECTOR3 v;
	v.x =  ( ( ( 2.0f * m_ptCursorPos.x ) / static_cast<float>(1024.0f)  ) - 1 ) / CAMERA.GetProj()->_11;
	v.y = -( ( ( 2.0f * m_ptCursorPos.y ) / static_cast<float>(768.0f) ) - 1 ) / CAMERA.GetProj()->_22;
	v.z =  1.0f;

	D3DXMATRIX m;
	D3DXVECTOR3 rayOrigin,rayDir;

	D3DXMatrixInverse( &m, NULL, CAMERA.GetView() );

	// Transform the screen space pick ray into 3D space
	rayDir.x  = v.x*m._11 + v.y*m._21 + v.z*m._31;
	rayDir.y  = v.x*m._12 + v.y*m._22 + v.z*m._32;
	rayDir.z  = v.x*m._13 + v.y*m._23 + v.z*m._33;
	rayOrigin.x = m._41;
	rayOrigin.y = m._42;
	rayOrigin.z = m._43;

	// Use inverse of matrix
	D3DXMATRIX matInverse;
	D3DXMatrixInverse(&matInverse,NULL,m_pickEntity.GetWorld());

	// Transform ray origin and direction by inv matrix
	D3DXVECTOR3 rayObjOrigin,rayObjDirection;

	D3DXVec3TransformCoord(&rayObjOrigin,&rayOrigin,&matInverse);
	D3DXVec3TransformNormal(&rayObjDirection,&rayDir,&matInverse);
	D3DXVec3Normalize(&rayObjDirection,&rayObjDirection);

	D3DXIntersect(m_pPickMesh.GetMesh(), &rayObjOrigin, &rayObjDirection, &m_pickEntity.GetRayHit(), NULL, NULL, NULL, &m_pickEntity.GetRayDistance(), NULL, NULL);
	
	D3DXVec3Normalize(&rayObjDirection,&rayObjDirection);
	
	rayObjDirection *= m_pickEntity.GetRayDistance();
	rayObjDirection += CAMERA.GetCameraPos();
	m_vec3MousePosition = rayObjDirection;
	m_pickEntity.SetPosition(m_vec3MousePosition);
        //m_pickEntity is the box and it moves to the mouse position so that the mouse always intersects it.

Can anyone see what is wrong? thanks, r_bewick

Share this post


Link to post
Share on other sites
The box moving faster than your mouse is probably due to the mouse being in screen space coordinates and your object being in world space coordinates. If you move 5 pixels right, then your box moves five world space units to the right. Depending on how your world space is set up, this could make the translation look much faster than it really is.

I'm not really sure how you are doing the picking since I do it totally differently, so I can't really comment. However, have you tried checking in the debugger that your picked point is correct in consecutive frames? For example, once you have done some translation is the new picked point what you expect it to be?

Share this post


Link to post
Share on other sites
I do picking the same way you do here is my 'picking' ray

Note that the first vector is just the origin. I shoot from the origin to a point on the projection screen at the mouslocation. Using the focal point as Z-Location for the projection screen and of course taking the aspect ratio into account. (since the screen is 'squeezed' so squares remain squares).



CamRay = FRay(
FVector( 0.0f, 0.0f, 0.0f ),
FVector( ( (float)MouseLocation.Global2D.X - Effect->GetWidth() /2 ) / (float)Effect->GetHeight() * 2.0f, - ( (float)MouseLocation.Global2D.Y / (float)Effect->GetHeight() - 0.5f ) * 2.0f , Effect->GetZScreenLocation() )
);


// WorldRay is camera ray tranformed to world coordinates
WorldRay = CamRay * Effect->GetView().Matrix;






The GetHeight and GetWidth just return the screen height and width in pixels the GetZScreenlocation is where the projection screen is (== the arctan of the viewing angle of the cam).


Share this post


Link to post
Share on other sites
When you created the window, did you use AdjustWindowRectEx? If not, your backbuffer and window sizes probably don't match, so your mouse coordinates will be in window coordinates, not backbuffer coordinates.

Share this post


Link to post
Share on other sites
As a side note. If you do like me and return a position on the ray from your intersection routine, then if your matrices contains scaling (i.e. the |length| of the base vectors aren't all 1.0) you have to take that into account when returning the distance on the ray.

Share this post


Link to post
Share on other sites
thanks everyone for your replies :D

Quote:

The box moving faster than your mouse is probably due to the mouse being in screen space coordinates and your object being in world space coordinates. If you move 5 pixels right, then your box moves five world space units to the right. Depending on how your world space is set up, this could make the translation look much faster than it really is.


My box position I think is OK, because if it does not intersect with my mouse then I don't get valid mouse coordinates. But something like this might be wrong since the cube I am drawing at the mouse moves faster than my mouse does as 50 world units = about 400 pixels


Ron AF Greve, I don't really get what you are doing, so I can't see what I am doing wrong. Sorry. I don't understand what FVector and FRay and Effect are.


Quote:

When you created the window, did you use AdjustWindowRectEx? If not, your backbuffer and window sizes probably don't match, so your mouse coordinates will be in window coordinates, not backbuffer coordinates.

I did not use this. I just created a window 800 by 600 pixels and put it in the centre of the screen. What is the difference between backbuffer coordinates and window coordinates?

[Edited by - r_bewick on September 15, 2009 1:41:55 AM]

Share this post


Link to post
Share on other sites
The window coordinates include the frame around the window's 'client' area. If your back buffer is 800x600, then your actual window size when you create it should be slightly larger. This let's the title bar of the window and the resize bars along the sides and bottom be there without making you change your back buffer size unnecessarily. If you don't size the back buffer accordingly and you make your window size 800x600, then you'll see some stretching artifacts when the back buffer is presented.

I think you can find a tutorial in Evil Steve's journal about this very topic if you want more details.

Share this post


Link to post
Share on other sites
oh, thanks Jason Z that is good to know. I had a problem with that before and decided to get rid of the window bar and border now I can add them with this and my mouse co-ords will still be right. But The difference isnt that much and my cube drawn at the mouse is moving away from the centre 10x faster than my mouse icon.

Share this post


Link to post
Share on other sites
Quote:
Original post by r_bewick
oh, thanks Jason Z that is good to know. I had a problem with that before and decided to get rid of the window bar and border now I can add them with this and my mouse co-ords will still be right. But The difference isnt that much and my cube drawn at the mouse is moving away from the centre 10x faster than my mouse icon.
Did you try scaling the mouse delta by a factor to correlate with the world coordinates? Take your mouse movement (say 10 pixels) multiplied by a scaling factor (say 0.5) and see if it works correctly.

If you want to be more precise, you would have to find your mouses world space position each time it moves and then translate your mesh by that amount. That seems like a bunch of work to get it implemented, but its really not that bad.

Share this post


Link to post
Share on other sites
Quote:

If you want to be more precise, you would have to find your mouses world space position each time it moves and then translate your mesh by that amount. That seems like a bunch of work to get it implemented, but its really not that bad.

Yes I would like to do this. Could you give me an example? thanks

Share this post


Link to post
Share on other sites
I don't have sample code or anything like that, but you already have the basic parts implemented. Do something like this:

1. Use picking to find the object being clicked on. Calculate and save the 3D world space position of the intersection point.

2. As long as the mouse button is down you are in 'dragging' mode. For each time step that you check this, find the new 3D world space position of the mouse if you assume the same depth as the initial point.

3. Subtract the two points to find the needed translation vector (which is in world space). Then translate by that amount.

That should get you in the ball park I think...

Share this post


Link to post
Share on other sites
WOW - thanks Jason Z I will definitely follow that.
Edit: I have got it working except that when I change the camera position my mouse position stuffs up. How can I fix this?

[Edited by - r_bewick on September 20, 2009 4:34:22 AM]

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