Recommended Posts

I am stuck on a math problem at the moment. I want to project 2D screen coordinates to a plane in 3D view space which is parallel to the view plane and has got a particular distance.
Let's suppose I have got a 2D point P[sub]2[/sub](x, y) on my view plane. My resolution is 800x600, so my x is ranging from 0 to 800 and my y from 0 to 600. I define a distance d[sub]z[/sub] which the plane in 3D view space and the view plane should have. Now I want to estimate the the 3D point P[sub]3[/sub] (x', y', z') in view space on that specific plane with distance d[sub]z[/sub] to my view plane.

The problem is, that due to perspective projection the plane in view space is bigger than the view plane itself and it gets bigger the bigger the distance d[sub]z[/sub] is between them. Thus when I got a big distance between those planes the projected plane on the on the view plane is very small and when I move my cursor to the right top corner to draw something for example it gets drawn somewhere in the middle of the screen.

I have to scale the x and y values somehow but I don't know how. Is there maybe another approach to solve this?

0

Share this post

Link to post

Share on other sites

Not exactly sure if this covers what you want but maybe it would work if you...

Travel down the 4 corners of your near plane in the view frustum a distance, d. This would provide you the width and height of your new plane. Then you could define a new frustum using those new dimensions and render to that.

The view frustum is a truncated pyramid (in perspective projection) so expect your width and height to increase.

0

Share this post

Link to post

Share on other sites

Yeah, this would be a great approach, but how do I estimate those 4 vectors and the 4 corners? I am aware that I can extract the 6 different planes which define the view frustum out of the projection matrix and thus just calculate their intersection line. But it seems quite elaborate and I am still missing those 4 corner points in 3D view space.

0

Share this post

Link to post

Share on other sites

Ok, now finally found a solution to solve this. I just post my approach so that everyone who has got the same problem can take this in consideration. ;)

I took a look at the initialization of my projection matrix. There i defined the field of view in angle, to be precisely it was PI/4 = 0.7853... defined by XM_PIDIV4:XMMATRIX projMatrix = XMMatrixPerspectiveFovLH(XM_PIDIV4, (float)(screenWidth) / (float)(screenHeight), 0.01f, 100.0f);

As far as I have understood the perspective projection this value defines the field of view in radian angle in horizontal and vertical direction. So everytime I rotate my camera the field of view is streched around my lookTo vector by the angle XM_PIDIV4 in radian. Therefore my lookTo vector intersects with the center of every plane wich lies in the frustum and is parallel to the view plane.
With those information I did the following:
I took my up and right vector of my view space and generated rotation matrices which rotate around each of them with the angle XM_PIDV/2.0, just the half of my field of view:XMMATRIX rotY = XMMatrixRotationAxis(up, XM_PIDIV4/1.3);
XMMATRIX rotX = XMMatrixRotationAxis(right, XM_PIDIV4/2.);
XMMATRIX rot_Y = XMMatrixRotationAxis(up, -XM_PIDIV4/1.3); //other direction
XMMATRIX rot_X = XMMatrixRotationAxis(right, -XM_PIDIV4/2.); //other direction

Now it was possible to travel down on those vectors to get to the new corners of the plane which is parallel to the view plane. I used the mouse wheel to define the distance between both planes:topright *= mouseZabsolute;
topleft *= mouseZabsolute;
bottomright *= mouseZabsolute;
bottomleft *= mouseZabsolute;

I haven't normalized the different vectors before, because my lookTo vector was already normalized.

In the next step I defined the right and up vector of the plane, so that their magnitudes are the width and height of the plane:right = topleft - topright;
up = topleft - bottomleft;

Then I normalized the mouse coordinates which are in screen spacefloat normMouseX = (float)(-mouseXabsolute)/((float)(_screenWidth));
float normMouseY = (float)(-mouseYabsolute)/((float)(_screenHeight));

and used them to move my cursor on that plane:cursor += camPos + topleft+normMouseX*right+normMouseY*up;

There is still one thing which bothers me. The rotation around the up vector must be adjusted everytime the aspect ratio changes. I found out that when the aspect ratio is 1.333 the somehow optimal rotation angle in radian is XM_PIDIV4/1.7 and when the aspect ratio is 1.777 the angle is XM_PIDIV4/1.3 . I can't figure out for now how to adjust this divisor properly.