c++ - Setting up an asymmetric frustum -
i have program in tracking user's position , setting frustum (setting camera @ user's position) change perspective of scene per user's position. until right now, had 4 corners of display screen @ same z , able set asymmetric frustum , change scene according user's perspective.
the current code looks following:
usercam::begin(){ saveglobalmatrices(); glmatrixmode(gl_projection); glloadidentity(); glfrustum(_topleftnear.x, _bottomrightnear.x, _bottomrightnear.y, _topleftnear.y, _camznear, _camzfar); glmatrixmode(gl_modelview); glloadidentity(); glulookat(_wcuserhead.x, _wcuserhead.y, _topleftscreen.z, _wcuserhead.x, _wcuserhead.y, _topleftscreen.z-1, 0, 1, 0); } usercam::end(){ loadglobalmatrices(); } usercam::setupcam(){ this->_topleftscreen = _wctopleftscreen - _wcuserhead; //wctopleftscreen, wcbottomrightscreen , wcuserhead in same frame of reference this->_bottomrightscreen = _wcbottomrightscreen - _wcuserhead; this->_topleftnear = (_topleftscreen/ _topleftscreen.z) * _camznear; this->_bottomrightnear = (_bottomrightscreen/_bottomrightscreen.z )) * _camznear; }
however, want able same display kept tilted user and/or not have vertices @ same z
.
above can imagined sort of tilted window, vertices of have frustum defined user's position. how such frustum possible display not have vertices @ same z
?
edit
there 3 planes in setup considering. middle 1 give correct asymmetric frustum since vertices @ same z, whereas left , right planes have 2 vertices each @ different z. vertices of same follows:
plane1: tl : (-426.66, 0, 200), tr: (0, 0, 0), bl : (-426.66, 320.79, 200), br : (0, 320.79, 0) plane2: tl : (0, 0, 0), tr: (426.66, 0, 0), bl : (0, 320.79, 0), br: (426.66, 320.79, 0) plane3: tl: (426.66, 0, 0), tr: (853.32, 0, 200), bl : (426.66, 320.79, 0), br : (853.32, 320.79, 200)
the idea in setup transform case corners have same z-coordinate. done view matrix , get:
overall_transform = (projection) * (view * world)
or in opengl wording
overall_transform = projection * modelview
if don't want tamper original modelview matrix, should introduce matrix in between:
overall_transform = (projection * adaption) * (view * world)
where adaption
rotation matrix maps screen's corners plane constant z-coordinate.
in order find correct parameters projection
have transform screen adaption
.
edit
we start arbitrary scene camera's position, direction , screen known. consider model matrices there each object:
we need view transformation v
aligns camera origin. matrix can calculated glulookat
. overall matrix t = v * m
:
up step matrices same 3 screens. part should in modelview matrix. add goes projection matrix because differs per screen.
we need apply rotation r
aligns screen perpendicular z-axis. position of camera must not change @ step because represents projection center. overall transformation t = r * v * m
.
in order calculate angle, can use e.g. atan2
:
dx = right.x - left.x dz = right.z - left.z angle = atan2(dz, dx)
it might necessary adapt calculation actual needs.
now time apply actual perspective transform, can done glfrustum
.
we need find local edges of screen. transform screen coordinates current transform (r * v
).
tl' = r * v * tl bl' = r * v * bl br' = r * v * br
now 3 coordinates should have same z-coordinate. can use these follows:
common_z = tl'.z = bl'.z = br'.z glfrustum(tl'.x / common_z * z_near, br'.x / common_z * z_near, bl'.y / common_z * z_near, tl'.y / common_z * z_near, z_near, z_far)
so overall t = glfrustum * r * v * m
:
glmatrixmode(gl_modelview); glloadidentity(); glulookat(...); //any further model transforms glmatrixmode(gl_projection); glfrustum(...); glrotate(...);
Comments
Post a Comment