c++ - Off-axis projection with glFrustum -


i trying off-axis projection of scene opengl , gave read document robert kooima's off-axis projection , have better idea of has done there still pieces finding tricky here. got know of off-axis projection code opengl 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); 

had been normal perspective projection user @ center of screen, easy understand comprehend.

               screen                      |                    |  h = h/2                    |   x----- n -----------                    |                    |  h = h/2                    | 

with user @ x , distance screen being n, top, bottom coordinates glfrustum calculated as: (assume theta field of view (fov) suppose assumed 30 degrees)

h = n * tan (theta/2); tanvalue = deg_to_rad * theta/2; [edit line additon here>>]: ffov = tan(tanvalue); h = n * tan (tanvalue); 

hence, top , bottom (negating top's value) both obtained glfrustum arguments. left one's left/right now.

now, aspect ratio, r = ofgetwidth()/ofgetheight(); right = n * (ffov * r); , r aspect ratio [edit1>> written tanvalue*r earlier here] 

question 1) above (tanvalue*r) getting horizontal fov angle , applying same left/right value?

   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 projection off-axis , have headx , heady position computed (using mouse here instead of actual user's head):

question 2) how headx , y being computed , use subtracting -0.5 above? observed brings x-value (-0.5 0.5) , y-value (0.5 -0.5) msx , msy varying.

question 3) in above code (code 1), how heady being added calculated tan(fov/2) value?

-ffov + heady ffov + heady 

what value provide with? -ffov calculated tan of theta/2 how can heady added directly?

-ffov * ratio + headx -ffov * ratio + headx 

how abvoe give vlaue wehn multiplied n (near value) gives left , right assymetric glfrustum call off-axis projection?

question 4) understand gllookat has done view point shift apex of frustum eye of user (in case mouse is). notice line in above code:

glulookat(headx*headz, heady*headz, 0, headx*headz, heady*headz, -1, 0, 1, 0);

how headx*headz giving me xposition of eye, heady*headz giving me yposition of eye can use in glulookat() here?

edit: full problem description added here: pastebin.com/bishxspb

you have made nice picture of ascii art

               screen                      b                    |  h = h/2                    |   x----- n ----------a                    |                    |  h = h/2                    b' 

the field of view defined angle fov = angle((x,b), (x,b')) formed between 2 tips b, b' of screen "line" , point x. trigonometric function tangens (tan) defines as

h/n = tan( angle((x,a), (x,b)) ) 

and since length(a, b) == length(a, b') == h == h/2 know that

h/(2·n) == tan( fov ) == tan( angle((x,b), (x,b')) ) == tan( 2·angle((x,a), (x,b)) ) 

since in trigonometry angles given in radians, people more comfortable degrees may have convert degress radians.

so we're interested in half of screen span (= h) we've half angle. , if want accept degress convert radians. that's expression meant for.

tanvalue = deg_to_rad * theta/2; 

using calculate h by

h = tan(tanvalue) * n 

if fov horizontal or vertical span of screen depends on way how field span h scaled aspect ratio.

how headx , y being computed , use subtracting -0.5 above? observed brings x-value (-0.5 0.5) , y-value (0.5 -0.5) msx , msy varying.

the calculations gave assume screen space coordinates in range [0, screenwidth] × [0, screenheight]. since we're doing our frustum calculations in normalized range [-1, 1]² want bring device absolute mouse coordinates normalized center relative coordinates. allows specify axis offset relative normalized near plane size. how looks 0 offset (the grid has 0.1 units distance in picture):

frustum center projection

and x offset of -0.5 applied looks (orange outline), can see left edge of near plane has been shifted -0.5.

frustum shifted projection

now imagine grid screen, , mouse pointer drag around projection frustum near plane bounds that.

what value provide with? -ffov calculated tan of theta/2 how can heady added directly?

because ffov not angle span h/2 = h in ascii art picture. , headx , heady relative shifts in normalized near projection plane.

how headxheadz giving me xposition of eye, headyheadz giving me yposition of eye can use in glulookat() here?

the code you're quoted seems ad-hoc solution on account emphase effect. in real head tracking stereoscopic system different. technically headz should either used calculated near plane distance or derived it.

anyway main ideas is, head located @ distance projection plane, , center point shifted in relative units of projection. must scale relative headx, heady actual head distance projection plane make apex correction work.

update due comment/request

so far we've looked @ 1 dimension when converting field of view (fov) screen span. image undistorted aspect ratio of [left, right] / [bottom, top] extents of near clipping plane must match aspect ratio of viewport width/height.

if choose define fov angle vertical fov, horizontal size of near clipping plane extents size of vertical near clipping plane extents scaled with/height aspect ratio.

this nothing special off-axis projection, can found in every perspective projection helper function; compare source code of gluperspective 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 consider near clipping plane extents [-aspect, aspect]×[-1, 1] of course headx position not in normalized range [-1, 1] must given in range [-aspect, aspect] well.

if @ paper linked, you'll find each screen head position reported tracker transformed in absolute coordinates relative screen.


two weeks ago had opportunity test display system called "z space" polarized stereo display had been combined head tracker creating off-axis frustum / look-at combination matched physical head position in front of display. offers "pen" interact 3d scene in front of you. 1 of impressive things i've seen in last few years , i'm begging boss buy 1 :)


Comments

Popular posts from this blog

java - Jmockit String final length method mocking Issue -

asp.net - Razor Page Hosted on IIS 6 Fails Every Morning -

c++ - wxwidget compiling on windows command prompt -