Jump to content

  • Log In with Google      Sign In   
  • Create Account

FREE SOFTWARE GIVEAWAY

We have 4 x Pro Licences (valued at $59 each) for 2d modular animation software Spriter to give away in this Thursday's GDNet Direct email newsletter.


Read more in this forum topic or make sure you're signed up (from the right-hand sidebar on the homepage) and read Thursday's newsletter to get in the running!


Reverse projection


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
3 replies to this topic

#1 StanLee   Members   -  Reputation: 117

Like
0Likes
Like

Posted 28 March 2012 - 02:08 PM

Hello!

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 P2(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 dz which the plane in 3D view space and the view plane should have. Now I want to estimate the the 3D point P3 (x', y', z') in view space on that specific plane with distance dz to my view plane.

A projection matrix is given:
XMMATRIX projMatrix = XMMatrixPerspectiveFovLH(XM_PIDIV4, (float)(screenWidth) / (float)(screenHeight), 0.1f, 1000.0f);

The camera position vector camPos, the lookTo-vector and the up-vector are also given.

How do I estimate P3 now? I tried to calculate the differen coordinates like that:
z' = camPos + lookTo*dz
x' = z' + cross(lookTo, up)*x
y = z' + up*y

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 dz 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?

Sponsor:

#2 Hornsj3   Members   -  Reputation: 191

Like
0Likes
Like

Posted 28 March 2012 - 03:43 PM

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.

#3 StanLee   Members   -  Reputation: 117

Like
0Likes
Like

Posted 29 March 2012 - 03:12 AM

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.

#4 StanLee   Members   -  Reputation: 117

Like
0Likes
Like

Posted 29 March 2012 - 05:46 AM

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

With those rotation matrices I took my lookTo vector and rotated him in such a way that I get all the four vectors which define the corners of my frustum:
XMVECTOR topleft, topright, bottomleft, bottomright;
topright = XMVector3Transform(lookTo, rotY);
topright = XMVector3Transform(topright, rot_X);
topleft = XMVector3Transform(lookTo, rot_Y);
topleft = XMVector3Transform(topleft, rot_X);
bottomright = XMVector3Transform(lookTo, rotY);
bottomright = XMVector3Transform(bottomright, rotX);
bottomleft = XMVector3Transform(lookTo, rot_Y);
bottomleft = XMVector3Transform(bottomleft, rotX);

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 space
float 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.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS