Off-axis projection with glFrustum

I'm trying to do an off-axis projection of a scene with OpenGL, and I read the document in Offline Projection by Robert Koyamim and now there is a much better idea of ​​what really needs to be done, but there are still some parts that I find difficult here. I learned about off-axis projection code for OpenGL as follows:

Code 1:

glMatrixMode(GL_PROJECTION);  glLoadIdentity();       glFrustum(fNear*(-fFov * ratio + headX),   fNear*(fFov * ratio + headX),   fNear*(-fFov + headY),   fNear*(fFov + headY),   fNear, fFar);       glMatrixMode(GL_MODELVIEW);  glLoadIdentity();  gluLookAt(headX*headZ, headY*headZ, 0, headX*headZ, headY*headZ, -1, 0, 1, 0); glTranslatef(0.0,0.0,headZ); 

If it were a normal perspective projection with the user in the center of the screen, it is quite easy to understand, as I understand it.

         Screen          |         |  h = H/2         | x----- n -----------         |         |  h = H/2         | 

When the user at point x and the distance from the screen is n, the upper, lower coordinates for glFrustum will be calculated as: (suppose that theta is the field of view (fov), which I assume is assumed to be 30 degrees)

 h = n * tan (theta/2); tanValue = DEG_TO_RAD * theta/2; [EDIT Line additon here>>]: fFov = tan(tanValue); h = n * tan (tanValue); 

Therefore, the upper and lower (negation of the upper value) are obtained for the glFrustum arguments. At the moment, left / right.

 Now, Aspect Ratio, r = ofGetWidth()/ofGetHeight(); Right = n * (fFov * r); , where r is the aspect ratio [Edit1>> Was written tanValue*r earlier here] 

Question 1) Is the above (tanValue * r) value of the horizontal angle fow , and then applying it to get the value left / right?

double msX = (double) ofGetMouseX ();
double msY = (double) ofGetMouseY ();
double scrWidth = (double) ofGetWidth ();
double scrHeight = (double) ofGetHeight ();

headX = (msX / scrWidth) - 0.5;
headY = ((scrHeight - msY) / scrHeight) - 0.5;
headZ = -2.0;

Now consider the off-axis projection, and we calculate the position of headX and headY (using the mouse here instead of the actual user's head):

Question 2) How are headX and y calculated and that you use subtracting -0.5 from the above? I noticed that it brings the value of x (from -0.5 to 0.5) and the y-value (from 0.5 to -0.5) when msX and msY change.

Question 3) In the above code (code 1), how is headY added to the computed tan (fov / 2) value?

 -fFov + headY fFov + headY 

What gives this meaning? -fFov was a computed tan of theta / 2, but how can you add headY directly?

 -fFov * ratio + headX -fFov * ratio + headX 

How does the abbot give us a value that is multiplied by n (a close value), gives us left and right for an asymmetric call to glFrustum for off-axis projection?

Question 4) I understand that glLookAt needs to be done for the View Point in order to move the top of the truncated cone to where the user's eye is (in this case, where the mouse is). Notice the line in the code above:

gluLookAt (headX * headZ, headY * headZ, 0, headX * headZ, headY * headZ, -1, 0, 1, 0);

How does headX*headZ give me xPosition eyes, headY*headZ give me yPosition eyes, which can I use in gluLookAt() here?

EDIT: a full description of the problem has been added here: pastebin.com/BiSHXspb

+3
source share
1 answer

You made this nice picture of ASCII art

  Screen B | h = H/2 | x----- n ----------A | | h = H/2 B' 

The field of view is defined as the angle fov = angle((x,B), (x,B')) , formed between the two ends B, B' of the screen "line" and the point x. The trigonometric function Tangens (tan) is defined as

 h/n = tan( angle((x,A), (x,B)) ) 

And since length(A, B) == length(A, B') == h == H/2 we know that

 H/(2·n) == tan( fov ) == tan( angle((x,B), (x,B')) ) == tan( 2·angle((x,A), (x,B)) ) 

Since in trigonometry, angles are given in radians, but most people are more comfortable with degrees, which you may have to convert from degregate to radians.

So, we are only interested in half the screen (= h), we have half the angle. And if we want to accept degress, we will also transform it into radians. This is what this expression is for.

 tanValue = DEG_TO_RAD * theta/2; 

Using this, we then calculate h on

 h = tan(tanValue) * n 

If the FOV for the horizontal or vertical spacing of the screen depends on how you scale the H field with aspect ratio.

How are headX and y calculated and that you use subtracting -0.5 from the above? I noticed that it brings the value of x (from -0.5 to 0.5) and the y-value (from 0.5 to -0.5) when msX and msY change.

Your calculations assume that the coordinates of the screen space are in the range [0, screenWidth] × [0, screenHeight]. However, since we are doing truncated cone calculations in the normalized range [-1, 1] ², we want to bring the device to the absolute coordinates of the mouse to the normalized central relative coordinates. This then allows you to specify the offset of the axis relative to the normalized size near the plane. It looks like this with 0 offset (the grid has 0.1 units of distance in this image):

frustum center projection

And at an offset of X -0.5 it looks like this (orange outline), since you can see that the left edge of the near plane is offset by -0.5.

frustum shifted projection

Now just imagine that the grid was your screen, and your mouse would drag around the projection slope near the borders of the plane.

What gives this meaning? -fFov was a computed tan of theta / 2, but how can you add headY directly?

Because fFov is not an angle, but the range H / 2 = h in the ASCII picture. And headX and headY are relative shifts in the normalized projection plane.

How does headXheadZ give me xPosition eyes, headYheadZ gives me yPosition eyes, which can I use in gluLookAt () here?

The code you are quoting is a special solution for this account to emphasize the effect. In a real stereoscopic head tracking system, you are a little different. Technically, headZ should either be used to calculate the distance near or away from the plane.

In any case, the main ideas are that the head is located at some distance from the projection plane, and the center point is shifted in relative units of projection. Thus, you must scale the relative headX, headY with the actual distance to the projection plane to perform vertex correction.

Update due to comment / request

So far, we have considered only one dimension when converting a field of view (fov) to a screen. For an undistorted image, the aspect ratio of the [left, right] / [lower, upper] extent of the near clipping plane should correspond to the width / height format of the viewport.

If we define the FoV angle as the vertical FoV, then the horizontal size of the near crop extents is the size of the vertical planes close to the clipping width, scaled using the aspect ratio / height.

This is nothing special with respect to off-axis projection, but can be found in every auxiliary function of perspective projection; compare gluPerspective source code for reference:

 void GLAPIENTRY gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar) { GLdouble xmin, xmax, ymin, ymax; ymax = zNear * tan(fovy * M_PI / 360.0); // M_PI / 360.0 == DEG_TO_RAD ymin = -ymax; xmin = ymin * aspect; xmax = ymax * aspect; glFrustum(xmin, xmax, ymin, ymax, zNear, zFar); } 

And if we consider the extents of the near cropping of the plane [-spectivity, aspect] × [-1, 1], then, of course, the position of headX is not in the normalized range [-1, 1], but should be indicated in the range [-spectrum, aspect].

If you look at the paper you linked, you will find that for each screen the position of the head reported by the tracker is converted in absolute coordinates relative to the screen.


Two weeks ago, I had the opportunity to test a display system called "Z-space", where the polarized stereo display was combined with a head tracker that creates an off-axis truncated / reverse lookup combination that matches your physical head position in front of the display. He also offers a “pen” for interacting with the 3D scene in front of you. This is one of the most impressive things I've seen in the last few years, and now I ask my boss to buy us :)

+5
source

Source: https://habr.com/ru/post/945734/


All Articles