[SOLVED] Move 3D object with 2D mouse

Started by
21 comments, last by donlucacorleone 14 years, 6 months ago
Ok, I know it's a common question. I want to move a DirectX object with the mouse cursor. But I'm missing something (maybe basic 3D math). On mouse click I want to move an object, previously rendered somewhere, to a NewX, NewY, SameZ values. The Z is the same of the actual Z of the object, so I don't need to calculate it. But I need to compute the NewX and NewY values... This is what I've done ( I use this for picking, see: http://www.gamedev.net/community/forums/topic.asp?topic_id=547663).

D3DXVECTOR3 get3dWorldCoordFrom2dPoint(float point2dX, float point2dY, float objectZCoord, D3DXMATRIX worldMatrix)
{
	//Get the Viewport
	D3D10_VIEWPORT viewport;
	UINT numOfVP = 1;
	G_Direct3D->device->RSGetViewports(&numOfVP, &viewport);

	//First point of a ray
	D3DXVECTOR3 point3d;
	point3d.x = (float) point2dX;
	point3d.y = (float) point2dY;
	point3d.z = -100.0f;

	//Translate from 2d to 3d World
	D3DXVECTOR3 rayStart;
	D3DXVec3Unproject(&rayStart, &point3d, &viewport, &G_Direct3D->projectionMatrix, &G_Direct3D->viewMatrix, &worldMatrix);

	//Second point of a ray
	point3d.z = 100.0f;

	//Translate from 2d to 3d World
	D3DXVECTOR3 rayEnd;
	D3DXVec3Unproject(&rayEnd, &point3d, &viewport, &G_Direct3D->projectionMatrix, &G_Direct3D->viewMatrix, &worldMatrix);

// --- And now ???
//I've copied this code from the web, but I really don't understand it
	float point3dX = ( ( 0.0f - rayStart.z ) * ( rayEnd.x - rayStart.x ) ) / ( rayEnd.z - rayStart.z ) + rayStart.x;
	float point3dY = ( ( 0.0f - rayStart.z ) * ( rayEnd.y - rayStart.y ) ) / ( rayEnd.z - rayStart.z ) + rayStart.y;
	float point3dZ = objectZCoord;


	return D3DXVECTOR3 (point3dX, point3dY, point3dZ);
}
As you can see, I don't exactly know how to get the 3D point from the ray. Perhaps I've to get the intersection between the ray and the plane, but I don't know the equation of the plane... I'm a bit confused, especially with the math beyond all that stuff. Could you please help me? Thank you. [Edited by - donlucacorleone on September 28, 2009 8:18:40 AM]
Advertisement
Let's see if I understand this right: You want to click on a point on a level plane with height SameZ and get the 3D coordinates of this point?

If so, the two lines
float point3dX = ( ( 0.0f - rayStart.z ) * ( rayEnd.x - rayStart.x ) ) / ( rayEnd.z - rayStart.z ) + rayStart.x;float point3dY = ( ( 0.0f - rayStart.z ) * ( rayEnd.y - rayStart.y ) ) / ( rayEnd.z - rayStart.z ) + rayStart.y;

are almost right. You see, the normal of your plane is n=(0,0,1), its distance d to the origin is "objectZCoord". The formula you used can be looked up at Line-plane intersection (section: "Algebraic form"). Just replace the 0.0f by -objectZCoord and you should be good to go (I think).
Thank you Nimbal for your response.

Let me explain better:
When I click the mouse, I want to re-render an object in that position ("under" the mouse cursor).
The new Z of the object is the same that was previously setted.
I need to get the NewX and NewY, in World coordinates obviously.

Making your changes, it doesn't work. It works only when the SameZ is at 0.0f :-(

I've tried a lot of plane-line intersection forumulas, but I can't catch the right way to implement it in my scenario.


--- EDIT ---
After reading this topic: http://www.gamedev.net/community/forums/topic.asp?topic_id=321357&whichpage=1�

I rewrite my function with this piece of code:
float t = - ( D3DXVec3Dot(&n, &rayStart) + d ) / ( D3DXVec3Dot(&n, &normalizedRayDir) );D3DXVECTOR3 new3dPoint = rayStart + t * normalizedRayDir;

where "n" is the normal (that is (0,0,1)) and "d" is equal to "objectZCoord".

Again, it works only if the objectZCoord is 0 (zero)...

[Edited by - donlucacorleone on September 22, 2009 8:04:02 AM]
What happens when d is not zero (or rather near zero, but not quite)? In which direction is the object misplaced?
When Z is not zero, the object is rendered near the mouse icon, but not "under" it.
Especially: if the mouse is at the top left corner of the window, then the render of the object starts at a negative offset on the X and at a positive offset on the Y.
In the bottom right corner, these offsets are reversed...

Maybe it's due to the FOV of the Projection matrix ??
Are you sure that setting point3d.z (the depth of the mouse cursor position) to plus/minus 100 is right? As far as I know, 0.0 and 1.0 are the values for near and far plane respectively. Try those and see if anything changes.
You're right! Thank you Nimbal.

I was using these values because the picking function doesn't work with 0.0f and 1.0f.
Now I'll correct and analyze both functions.

Thank you again, you solved it.

Ah, just to be as clear as possible, in this piece of code
float point3dX = ( ( 0.0f - rayStart.z ) * ( rayEnd.x - rayStart.x ) ) / ( rayEnd.z - rayStart.z ) + rayStart.x;float point3dY = ( ( 0.0f - rayStart.z ) * ( rayEnd.y - rayStart.y ) ) / ( rayEnd.z - rayStart.z ) + rayStart.y;

the 0.0f means the origin. Am i right?

--- EDIT ---
Another information: you should substitute the 0.0f and 1.0f values with viewport.MinDepth and viewport.MaxDepth respectively
It should be the distance between the plane and the origin (so, in your case objectZCoord).
Are you sure?
Removing 0.0f and setting objectZCoord it'll not work anymore except when objectZCoord = 0.0f ...
http://www.siggraph.org/education/materials/HyperGraph/raytrace/rayplane_intersection.htm

This topic is closed to new replies.

Advertisement