Camera.cpp

00001 #include "Camera.h"
00002 #include "Utility.h"
00003 
00004 #define PLANE_FRONT             0
00005 #define PLANE_BACK              1
00006 #define PLANE_LEFT              2
00007 #define PLANE_RIGHT             3
00008 #define PLANE_BOTTOM    4
00009 #define PLANE_TOP               5
00010 
00011 Camera::Camera ()
00012 {
00013         angle = CAMERA_STANDARD_ANGLE;
00014         aspect_ratio = CAMERA_STANDARD_RATIO;
00015         near_cutoff = CAMERA_STANDARD_NEAR;
00016         far_cutoff = CAMERA_STANDARD_FAR;
00017 
00018         position = new PositionPath ();
00019 }
00020 
00021 Camera::~Camera ()
00022 {
00023         // do not do anything
00024 }
00025 
00026 void Camera::SetAttributes (double a, double a_r, double n, double f)
00027 {
00028         angle = a;
00029         aspect_ratio = a_r;
00030         near_cutoff = n;
00031         far_cutoff = f;
00032 }
00033 
00034 void Camera::ApplyAttributes ()
00035 {
00036         int previous_mode;
00037 
00038         glGetIntegerv (GL_MATRIX_MODE, &previous_mode);
00039         glMatrixMode (GL_PROJECTION);
00040         glLoadIdentity ();
00041         gluPerspective (angle, aspect_ratio, near_cutoff, far_cutoff);
00042         glMatrixMode (previous_mode);
00043 }
00044 
00045 void Camera::ApplyPosition (int time)
00046 {
00047         Position pos;
00048 
00049         pos = position->GetPosition (time);
00050 
00051         // since our camera does look along the positive x direction (not positive z as in OpenGL),
00052         //we have to rotate a bit first.
00053         glRotatef (90, 0.0f, 1.0f, 0.0f);
00054         glRotatef (-90, 1.0f, 0.0f, 0.0f);
00055 
00056         // applying the camera position is the exact same as shifting the world with the inverse transformation
00057         glRotatef (-pos.roll, 1.0f, 0.0f, 0.0f); 
00058         glRotatef (-pos.pitch, 0.0f, 1.0f, 0.0f);
00059         glRotatef (-pos.yaw, 0.0f, 0.0f, 1.0f);
00060         glTranslatef (-pos.x, -pos.y, -pos.z);
00061 }
00062 
00063 void Camera::ComputeInverseView (int time)
00064 {
00065         Position pos;
00066         float view[16];
00067 
00068         pos = position->GetPosition (time);
00069 
00070         // retrieve the matrix that corresponds to the viewpoint transformation
00071         glPushMatrix ();
00072         glLoadIdentity ();
00073 
00074                 glRotatef (90, 0.0f, 1.0f, 0.0f);
00075                 glRotatef (-90, 1.0f, 0.0f, 0.0f);
00076 
00077                 glRotatef (-pos.roll, 1.0f, 0.0f, 0.0f); 
00078                 glRotatef (-pos.pitch, 0.0f, 1.0f, 0.0f); 
00079                 glRotatef (-pos.yaw, 0.0f, 0.0f, 1.0f);
00080                 glTranslatef (-pos.x, -pos.y, -pos.z);
00081 
00082                 glGetFloatv (GL_MODELVIEW_MATRIX, view);
00083 
00084         glPopMatrix ();
00085 
00086         // and invert it (no problem since a sequence of rotations and translations always yields a
00087         // homogenous matrix
00088         Geometry::InvertHomogenousMatrix (view, inverse_view);
00089 }
00090 
00091 float * Camera::GetInverseView ()
00092 {
00093         return inverse_view;
00094 }
00095 
00096 void Camera::BuildPlanes (int time)
00097 {
00098         double res[16];
00099         double mod[16];
00100 
00101         Position pos;
00102         pos = position->GetPosition (time);
00103         
00104         // set up and retrieve modelview matrix
00105         glPushMatrix ();
00106                 glLoadIdentity ();
00107 
00108                 glRotatef (90, 0.0f, 1.0f, 0.0f);
00109                 glRotatef (-90, 1.0f, 0.0f, 0.0f);
00110 
00111                 glRotatef (-pos.roll, 1.0f, 0.0f, 0.0f); 
00112                 glRotatef (-pos.pitch, 0.0f, 1.0f, 0.0f); 
00113                 glRotatef (-pos.yaw, 0.0f, 0.0f, 1.0f); 
00114                 glTranslatef (-pos.x, -pos.y, -pos.z);
00115 
00116                 glGetDoublev (GL_MODELVIEW_MATRIX, mod);
00117         glPopMatrix ();
00118         
00119         // set up projection matrix and postmultiply with modelview matrix, retrieve result
00120         glMatrixMode (GL_PROJECTION);
00121         glPushMatrix ();
00122         glLoadIdentity ();
00123                 ApplyAttributes ();
00124                 glMultMatrixd (mod);
00125                 glGetDoublev (GL_PROJECTION_MATRIX, res);
00126         glPopMatrix ();
00127         glMatrixMode (GL_MODELVIEW);
00128 
00129         // frustum now transformed to a box...
00130         front.n.x = res[3] + res[2];
00131         front.n.y = res[7] + res[6];
00132         front.n.z = res[11] + res[10];
00133         front.d = res[15] + res[14];
00134 
00135         back.n.x = res[3] - res[2];
00136         back.n.y = res[7] - res[6];
00137         back.n.z = res[11] - res[10];
00138         back.d = res[15] - res[14];
00139 
00140         left.n.x = res[3] + res[0];
00141         left.n.y = res[7] + res[4];
00142         left.n.z = res[11] + res[8];
00143         left.d = res[15] + res[12];
00144 
00145         right.n.x = res[3] - res[0];
00146         right.n.y = res[7] - res[4];
00147         right.n.z = res[11] - res[8];
00148         right.d = res[15] - res[12];
00149 
00150         bottom.n.x = res[3] + res[1];
00151         bottom.n.y = res[7] + res[5];
00152         bottom.n.z = res[11] + res[9];
00153         bottom.d = res[15] + res[13];
00154 
00155         top.n.x = res[3] - res[1];
00156         top.n.y = res[7] - res[5];
00157         top.n.z = res[11] - res[9];
00158         top.d = res[15] - res[13];
00159 
00160         /* normalize */
00161         float temp;
00162 
00163         temp = sqrt (front.n.x * front.n.x + front.n.y * front.n.y + front.n.z * front.n.z);
00164         front.n.x /= temp;
00165         front.n.y /= temp;
00166         front.n.z /= temp;
00167         front.d /= temp;
00168 
00169         temp = sqrt (back.n.x * back.n.x + back.n.y * back.n.y + back.n.z * back.n.z);
00170         back.n.x /= temp;
00171         back.n.y /= temp;
00172         back.n.z /= temp;
00173         back.d /= temp;
00174 
00175         temp = sqrt (left.n.x * left.n.x + left.n.y * left.n.y + left.n.z * left.n.z);
00176         left.n.x /= temp;
00177         left.n.y /= temp;
00178         left.n.z /= temp;
00179         left.d /= temp;
00180 
00181         temp = sqrt (right.n.x * right.n.x + right.n.y * right.n.y + right.n.z * right.n.z);
00182         right.n.x /= temp;
00183         right.n.y /= temp;
00184         right.n.z /= temp;
00185         right.d /= temp;
00186 
00187         temp = sqrt (bottom.n.x * bottom.n.x + bottom.n.y * bottom.n.y + bottom.n.z * bottom.n.z);
00188         bottom.n.x /= temp;
00189         bottom.n.y /= temp;
00190         bottom.n.z /= temp;
00191         bottom.d /= temp;
00192 
00193         temp = sqrt (top.n.x * top.n.x + top.n.y * top.n.y + top.n.z * top.n.z);
00194         top.n.x /= temp;
00195         top.n.y /= temp;
00196         top.n.z /= temp;
00197         top.d /= temp;
00198 }
00199 
00200 void Camera::DrawFrustum ()
00201 {
00202         Point corner[8];
00203 
00204         // get the corners of the viewing frustum
00205         corner[0] = Geometry::PlaneIntersection (front, left, top);
00206         corner[1] = Geometry::PlaneIntersection (front, left, bottom);
00207         corner[2] = Geometry::PlaneIntersection (front, right, top);
00208         corner[3] = Geometry::PlaneIntersection (front, right, bottom);
00209         corner[4] = Geometry::PlaneIntersection (back, left, top);
00210         corner[5] = Geometry::PlaneIntersection (back, left, bottom);
00211         corner[6] = Geometry::PlaneIntersection (back, right, top);
00212         corner[7] = Geometry::PlaneIntersection (back, right, bottom);
00213 
00214         Utility::SetColor (0.2f, 0.2f, 0.8f, 1.0f);
00215 
00216         // draw front
00217         Utility::DrawQuad (corner[0], corner[2], corner[3], corner[1]);
00218         // draw back
00219         Utility::DrawQuad (corner[6], corner[4], corner[5], corner[7]);
00220         // draw left
00221         Utility::DrawQuad (corner[4], corner[0], corner[1], corner[5]);
00222         // draw right
00223         Utility::DrawQuad (corner[2], corner[6], corner[7], corner[3]);
00224         // draw bottom
00225         Utility::DrawQuad (corner[1], corner[3], corner[7], corner[5]);
00226         // draw top
00227         Utility::DrawQuad (corner[4], corner[6], corner[2], corner[0]);
00228 }
00229 
00230 void Camera::DrawFrustum2 (int time)
00231 {
00232         Point corner[8];
00233         Point c[8];     
00234         double mod[16];
00235         double inv[16];
00236 
00237         // retrieve the corners of the frustum from the planes
00238         corner[0] = Geometry::PlaneIntersection (planes[PLANE_FRONT], planes[PLANE_LEFT], planes[PLANE_TOP]);
00239         corner[1] = Geometry::PlaneIntersection (planes[PLANE_FRONT], planes[PLANE_LEFT], planes[PLANE_BOTTOM]);
00240         corner[2] = Geometry::PlaneIntersection (planes[PLANE_FRONT], planes[PLANE_RIGHT], planes[PLANE_TOP]);
00241         corner[3] = Geometry::PlaneIntersection (planes[PLANE_FRONT], planes[PLANE_RIGHT], planes[PLANE_BOTTOM]);
00242         corner[4] = Geometry::PlaneIntersection (planes[PLANE_BACK], planes[PLANE_LEFT], planes[PLANE_TOP]);
00243         corner[5] = Geometry::PlaneIntersection (planes[PLANE_BACK], planes[PLANE_LEFT], planes[PLANE_BOTTOM]);
00244         corner[6] = Geometry::PlaneIntersection (planes[PLANE_BACK], planes[PLANE_RIGHT], planes[PLANE_TOP]);
00245         corner[7] = Geometry::PlaneIntersection (planes[PLANE_BACK], planes[PLANE_RIGHT], planes[PLANE_BOTTOM]);
00246 
00247         // but since they are not in our global world coordinates, we have to transform them back manually
00248         glPushMatrix ();
00249         glLoadIdentity ();
00250         
00251                 ApplyPosition (time);
00252                 glGetDoublev (GL_MODELVIEW_MATRIX, mod);
00253 
00254         glPopMatrix ();
00255 
00256         Geometry::InvertHomogenousMatrix (mod, inv);
00257 
00258         c[0].x = corner[0].x * inv[0] + corner[0].y * inv[4] + corner[0].z * inv[8] + inv[12];
00259         c[0].y = corner[0].x * inv[1] + corner[0].y * inv[5] + corner[0].z * inv[9] + inv[13];
00260         c[0].z = corner[0].x * inv[2] + corner[0].y * inv[6] + corner[0].z * inv[10] + inv[14];
00261 
00262         c[1].x = corner[1].x * inv[0] + corner[1].y * inv[4] + corner[1].z * inv[8] + inv[12];
00263         c[1].y = corner[1].x * inv[1] + corner[1].y * inv[5] + corner[1].z * inv[9] + inv[13];
00264         c[1].z = corner[1].x * inv[2] + corner[1].y * inv[6] + corner[1].z * inv[10] + inv[14];
00265 
00266         c[2].x = corner[2].x * inv[0] + corner[2].y * inv[4] + corner[2].z * inv[8] + inv[12];
00267         c[2].y = corner[2].x * inv[1] + corner[2].y * inv[5] + corner[2].z * inv[9] + inv[13];
00268         c[2].z = corner[2].x * inv[2] + corner[2].y * inv[6] + corner[2].z * inv[10] + inv[14];
00269 
00270         c[3].x = corner[3].x * inv[0] + corner[3].y * inv[4] + corner[3].z * inv[8] + inv[12];
00271         c[3].y = corner[3].x * inv[1] + corner[3].y * inv[5] + corner[3].z * inv[9] + inv[13];
00272         c[3].z = corner[3].x * inv[2] + corner[3].y * inv[6] + corner[3].z * inv[10] + inv[14];
00273 
00274         c[4].x = corner[4].x * inv[0] + corner[4].y * inv[4] + corner[4].z * inv[8] + inv[12];
00275         c[4].y = corner[4].x * inv[1] + corner[4].y * inv[5] + corner[4].z * inv[9] + inv[13];
00276         c[4].z = corner[4].x * inv[2] + corner[4].y * inv[6] + corner[4].z * inv[10] + inv[14];
00277 
00278         c[5].x = corner[5].x * inv[0] + corner[5].y * inv[4] + corner[5].z * inv[8] + inv[12];
00279         c[5].y = corner[5].x * inv[1] + corner[5].y * inv[5] + corner[5].z * inv[9] + inv[13];
00280         c[5].z = corner[5].x * inv[2] + corner[5].y * inv[6] + corner[5].z * inv[10] + inv[14];
00281 
00282         c[6].x = corner[6].x * inv[0] + corner[6].y * inv[4] + corner[6].z * inv[8] + inv[12];
00283         c[6].y = corner[6].x * inv[1] + corner[6].y * inv[5] + corner[6].z * inv[9] + inv[13];
00284         c[6].z = corner[6].x * inv[2] + corner[6].y * inv[6] + corner[6].z * inv[10] + inv[14];
00285 
00286         c[7].x = corner[7].x * inv[0] + corner[7].y * inv[4] + corner[7].z * inv[8] + inv[12];
00287         c[7].y = corner[7].x * inv[1] + corner[7].y * inv[5] + corner[7].z * inv[9] + inv[13];
00288         c[7].z = corner[7].x * inv[2] + corner[7].y * inv[6] + corner[7].z * inv[10] + inv[14];
00289 
00290         Utility::SetColor (0.2f, 0.2f, 0.8f, 1.0f);
00291 
00292         Utility::DrawQuad (c[0], c[2], c[3], c[1]);
00293         Utility::DrawQuad (c[6], c[4], c[5], c[7]);
00294         Utility::DrawQuad (c[4], c[0], c[1], c[5]);
00295         Utility::DrawQuad (c[2], c[6], c[7], c[3]);
00296         Utility::DrawQuad (c[1], c[3], c[7], c[5]);
00297         Utility::DrawQuad (c[4], c[6], c[2], c[0]);
00298 }
00299 
00300 void Camera::BuildPlanes2 ()
00301 {
00302         double pro[16];
00303         
00304         glMatrixMode (GL_PROJECTION);
00305         glPushMatrix ();
00306         glLoadIdentity ();
00307                 ApplyAttributes ();
00308                 glGetDoublev (GL_PROJECTION_MATRIX, pro);
00309         glPopMatrix ();
00310         glMatrixMode (GL_MODELVIEW);
00311 
00312         // frustum now transformed to a box...
00313         planes[PLANE_FRONT].n.x = pro[3] + pro[2];
00314         planes[PLANE_FRONT].n.y = pro[7] + pro[6];
00315         planes[PLANE_FRONT].n.z = pro[11] + pro[10];
00316         planes[PLANE_FRONT].d = pro[15] + pro[14];
00317 
00318         planes[PLANE_BACK].n.x = pro[3] - pro[2];
00319         planes[PLANE_BACK].n.y = pro[7] - pro[6];
00320         planes[PLANE_BACK].n.z = pro[11] - pro[10];
00321         planes[PLANE_BACK].d = pro[15] - pro[14];
00322 
00323         planes[PLANE_LEFT].n.x = pro[3] + pro[0];
00324         planes[PLANE_LEFT].n.y = pro[7] + pro[4];
00325         planes[PLANE_LEFT].n.z = pro[11] + pro[8];
00326         planes[PLANE_LEFT].d = pro[15] + pro[12];
00327 
00328         planes[PLANE_RIGHT].n.x = pro[3] - pro[0];
00329         planes[PLANE_RIGHT].n.y = pro[7] - pro[4];
00330         planes[PLANE_RIGHT].n.z = pro[11] - pro[8];
00331         planes[PLANE_RIGHT].d = pro[15] - pro[12];
00332 
00333         planes[PLANE_BOTTOM].n.x = pro[3] + pro[1];
00334         planes[PLANE_BOTTOM].n.y = pro[7] + pro[5];
00335         planes[PLANE_BOTTOM].n.z = pro[11] + pro[9];
00336         planes[PLANE_BOTTOM].d = pro[15] + pro[13];
00337 
00338         planes[PLANE_TOP].n.x = pro[3] - pro[1];
00339         planes[PLANE_TOP].n.y = pro[7] - pro[5];
00340         planes[PLANE_TOP].n.z = pro[11] - pro[9];
00341         planes[PLANE_TOP].d = pro[15] - pro[13];
00342 
00343         /* normalize */
00344         for (int index = 0; index < 6; index++)
00345         {
00346                 float temp;
00347 
00348                 temp = sqrt (planes[index].n.x * planes[index].n.x + planes[index].n.y * planes[index].n.y + planes[index].n.z * planes[index].n.z);
00349                 planes[index].n.x /= temp;
00350                 planes[index].n.y /= temp;
00351                 planes[index].n.z /= temp;
00352                 planes[index].d /= temp;
00353         }
00354 }
00355 
00356 void Camera::MoveForward (double amount)
00357 {
00358         Position p;
00359         Vector delta;
00360 
00361         p = position->GetPosition (0);
00362 
00363         delta.x = cos(DEG2RAD(p.pitch)) * cos (DEG2RAD(p.yaw)) * amount;
00364         delta.y = cos(DEG2RAD(p.pitch)) * sin (DEG2RAD(p.yaw)) * amount;
00365         delta.z = - sin (DEG2RAD(p.pitch)) * amount;
00366 
00367         position->SetConstantPosition (p.x + delta.x, p.y + delta.y , p.z + delta.z, p.roll, p.pitch, p.yaw);
00368 }
00369 
00370 void Camera::MoveRight (double amount)
00371 {
00372         Position p;
00373         Vector delta;
00374 
00375         p = position->GetPosition (0);
00376 
00377         delta.x = (-cos(DEG2RAD(p.roll))*sin(DEG2RAD(p.yaw)) + sin(DEG2RAD(p.roll))*sin(DEG2RAD(p.pitch))*cos(DEG2RAD(p.yaw))) * amount;
00378         delta.y = (sin(DEG2RAD(p.roll))*sin(DEG2RAD(p.pitch))*sin(DEG2RAD(p.yaw)) + cos(DEG2RAD(p.roll))*cos(DEG2RAD(p.yaw))) * amount;
00379         delta.z = sin(DEG2RAD(p.roll))*cos(DEG2RAD(p.pitch))*amount;
00380 
00381         position->SetConstantPosition (p.x + delta.x, p.y + delta.y, p.z + delta.z, p.roll, p.pitch, p.yaw);
00382 }
00383 
00384 void Camera::MoveUp (double amount)
00385 {
00386         Position p;
00387         Vector delta;
00388 
00389         p = position->GetPosition (0);
00390 
00391         delta.x = (cos(DEG2RAD(p.roll))*sin(DEG2RAD(p.pitch))*cos(DEG2RAD(p.yaw)) + sin(DEG2RAD (p.roll))*sin(DEG2RAD(p.yaw))) * amount;
00392         delta.y = (-sin(DEG2RAD(p.roll))*cos(DEG2RAD(p.yaw)) + cos(DEG2RAD(p.roll))*sin(DEG2RAD(p.pitch))*sin(DEG2RAD(p.yaw))) * amount;
00393         delta.z = cos(DEG2RAD(p.roll))* cos(DEG2RAD(p.pitch)) * amount;
00394 
00395         position->SetConstantPosition (p.x + delta.x, p.y + delta.y, p.z + delta.z, p.roll, p.pitch, p.yaw);
00396 }

Generated on Sun Jul 2 13:20:38 2006 for Demo by  doxygen 1.4.6-NO