proj home

Files   Classes   Functions   Hierarchy  

zpr.cpp

Go to the documentation of this file.
00001 #include <cassert>
00002 #include <cstdlib>
00003 #include <cmath>
00004 #include <memory>
00005 #include <cstring>
00006 #include <iostream>
00007 using namespace std;
00008 
00009 #include <GL/glut.h>
00010 
00011 #include <zpr.h>
00012 
00013 #include <graphmisc.h>
00014 
00015 
00017 GLdouble zprGLmatrix::zero = 1.0E-15;
00018 
00020 zpr* zpr::global = 0;
00021 
00022 #define SHOW(x) #x << '=' << (x)
00023 
00024 
00025 //
00026 // From Mesa-2.2\src\glu\project.c
00027 //
00028 
00029 //
00030 // Compute the inverse of a 4x4 matrix.  Contributed by scotter@lafn.org
00031 //
00032 
00033 void zprGLmatrix::invertMatrix(GLdouble *out, GLdouble const *m )
00034 {
00035 
00036 /* NB. OpenGL Matrices are COLUMN major. */
00037 #define MAT(m,r,c) (m)[(c)*4+(r)]
00038 
00039 // <TODO> Renaming the indexes??? Do they have a problem counting from 0? Why?
00040 /* Here's some shorthand converting standard (row,column) to index. */
00041 #define m11 MAT(m,0,0)
00042 #define m12 MAT(m,0,1)
00043 #define m13 MAT(m,0,2)
00044 #define m14 MAT(m,0,3)
00045 #define m21 MAT(m,1,0)
00046 #define m22 MAT(m,1,1)
00047 #define m23 MAT(m,1,2)
00048 #define m24 MAT(m,1,3)
00049 #define m31 MAT(m,2,0)
00050 #define m32 MAT(m,2,1)
00051 #define m33 MAT(m,2,2)
00052 #define m34 MAT(m,2,3)
00053 #define m41 MAT(m,3,0)
00054 #define m42 MAT(m,3,1)
00055 #define m43 MAT(m,3,2)
00056 #define m44 MAT(m,3,3)
00057 
00058   static GLdouble temporary[16]; /* Allow out == in. */
00059   GLdouble * tmp = out;
00060 
00061   bool const outin(m==out);
00062   if (outin)
00063     tmp = & temporary[0];
00064 
00065   /* Inverse = adjoint / det. (See linear algebra texts.)*/
00066 
00067   /* pre-compute 2x2 dets for last two rows when computing */
00068   /* cofactors of first two rows. */
00069   GLdouble d12(m31*m42-m41*m32);
00070   GLdouble d13(m31*m43-m41*m33);
00071   GLdouble d23(m32*m43-m42*m33);
00072   GLdouble d24(m32*m44-m42*m34);
00073   GLdouble d34(m33*m44-m43*m34);
00074   GLdouble d41(m34*m41-m44*m31);
00075 
00076   tmp[0] =  (m22 * d34 - m23 * d24 + m24 * d23);
00077   tmp[1] = -(m21 * d34 + m23 * d41 + m24 * d13);
00078   tmp[2] =  (m21 * d24 + m22 * d41 + m24 * d12);
00079   tmp[3] = -(m21 * d23 - m22 * d13 + m23 * d12);
00080 
00081   /* Compute determinant as early as possible using these cofactors. */
00082   GLdouble det(m11 * tmp[0] + m12 * tmp[1] + m13 * tmp[2] + m14 * tmp[3]);
00083 
00084   /* Singularity test. */
00085   if (abs(det)>zero)
00086   {
00087     GLdouble invDet(1.0 / det);
00088     /* Compute rest of inverse. */
00089     tmp[0] *= invDet;
00090     tmp[1] *= invDet;
00091     tmp[2] *= invDet;
00092     tmp[3] *= invDet;
00093 
00094     tmp[4] = -(m12 * d34 - m13 * d24 + m14 * d23) * invDet;
00095     tmp[5] =  (m11 * d34 + m13 * d41 + m14 * d13) * invDet;
00096     tmp[6] = -(m11 * d24 + m12 * d41 + m14 * d12) * invDet;
00097     tmp[7] =  (m11 * d23 - m12 * d13 + m13 * d12) * invDet;
00098 
00099     /* Pre-compute 2x2 dets for first two rows when computing */
00100     /* cofactors of last two rows. */
00101     d12 = m11*m22-m21*m12;
00102     d13 = m11*m23-m21*m13;
00103     d23 = m12*m23-m22*m13;
00104     d24 = m12*m24-m22*m14;
00105     d34 = m13*m24-m23*m14;
00106     d41 = m14*m21-m24*m11;
00107 
00108     tmp[8] =  (m42 * d34 - m43 * d24 + m44 * d23) * invDet;
00109     tmp[9] = -(m41 * d34 + m43 * d41 + m44 * d13) * invDet;
00110     tmp[10] =  (m41 * d24 + m42 * d41 + m44 * d12) * invDet;
00111     tmp[11] = -(m41 * d23 - m42 * d13 + m43 * d12) * invDet;
00112     tmp[12] = -(m32 * d34 - m33 * d24 + m34 * d23) * invDet;
00113     tmp[13] =  (m31 * d34 + m33 * d41 + m34 * d13) * invDet;
00114     tmp[14] = -(m31 * d24 + m32 * d41 + m34 * d12) * invDet;
00115     tmp[15] =  (m31 * d23 - m32 * d13 + m33 * d12) * invDet;
00116 
00117     if (outin)
00118       memcpy(out, tmp, 16*sizeof(GLdouble));
00119   }
00120 
00121 #undef m11
00122 #undef m12
00123 #undef m13
00124 #undef m14
00125 #undef m21
00126 #undef m22
00127 #undef m23
00128 #undef m24
00129 #undef m31
00130 #undef m32
00131 #undef m33
00132 #undef m34
00133 #undef m41
00134 #undef m42
00135 #undef m43
00136 #undef m44
00137 #undef MAT
00138 }
00139 
00140 
00141 
00142 void zpr::readModelView()
00143 {
00144   glGetDoublev(GL_MODELVIEW_MATRIX,matrix);
00145   zprGLmatrix::invertMatrix(matrixI,matrix);
00146 }
00147 
00148 void zpr::reshape(int width_,int height_)
00149 {
00150   assert(zpr::global!=0);
00151   global->reshapezpr(width_,height_);
00152 }
00153 
00154 void zpr::write()
00155 {
00156   glViewport(0,0,width,height);
00157 
00158   glMatrixMode(GL_PROJECTION);
00159   glLoadIdentity();
00160   assert(zNear>0.0);
00161   assert(zFar>zNear);
00162   glFrustum(left,right,bottom,top,zNear,zFar);
00163   glMatrixMode(GL_MODELVIEW);
00164 
00165   glerrordisplay();
00166 }
00167 
00168 void zpr::reshapezpr(intc width_,intc height_)
00169 {
00170   width = width_;
00171   height = height_;
00172 
00173 //cout << "width=" << width << endl;
00174 //cout << "height=" << height << endl;
00175 
00176   //glViewport(0, 0, (GLsizei) width_, (GLsizei) height_);
00177 
00178   writeDefault();
00179 }
00180 
00181 void zpr::writeDefault()
00182 {
00183   assert( height>0.0);
00184   assert( width>0.0);
00185 
00186   left=-1.0;
00187   right=1.0;
00188 
00189   double dy = (double) height / (double)width;
00190   bottom=-dy;
00191   top=dy;
00192 
00193   zNear=1.0;
00194   zFar=6.0;
00195   write();
00196 }
00197 
00198 void zpr::mouse(int button, int state, int x, int y)
00199 {
00200   assert(global!=0);
00201 
00202   global->mousezpr(button,state,x,y);
00203 }
00204 
00205 void zpr::readMouse
00206 (
00207   GLdouble *px,
00208   GLdouble *py,
00209   GLdouble *pz,
00210   intc x,
00211   intc y
00212 ) const 
00213 {
00214 //    Use the ortho projection and viewport information
00215 //    to map from mouse co-ordinates back into world 
00216 //    co-ordinates
00217 
00218   int viewport[4];
00219   glGetIntegerv(GL_VIEWPORT,viewport);
00220 
00221   *px = (GLdouble)(x-viewport[0])/(GLdouble)(viewport[2]);
00222   *py = (GLdouble)(y-viewport[1])/(GLdouble)(viewport[3]);
00223 
00224   *px = left + (*px)*(right-left);
00225   *py = top  + (*py)*(bottom-top);
00226   *pz = zNear;
00227 }
00228 
00229 
00230 
00231 void zpr::mousezpr(intc button, intc state, intc x, intc y)
00232 {
00233   mouseX = x;
00234   mouseY = y;
00235 
00236   if (state==GLUT_UP)
00237   switch (button)
00238   {
00239     case GLUT_LEFT_BUTTON:   mouseLeft   = false; break;
00240     case GLUT_MIDDLE_BUTTON: mouseMiddle = false; break;
00241     case GLUT_RIGHT_BUTTON:  mouseRight  = false; break;
00242   }
00243   else
00244   switch (button)
00245   {
00246     case GLUT_LEFT_BUTTON:    mouseLeft   = true; break;
00247     case GLUT_MIDDLE_BUTTON:  mouseMiddle = true; break;
00248     case GLUT_RIGHT_BUTTON:   mouseRight  = true; break;
00249   }
00250 
00251   readMouse(&mouseXworld,&mouseYworld,&mouseZworld,x,y);
00252 
00253   //if (mousecallback)
00254   //  (*mousecallback)(*this);
00255   if (mousecallback)
00256     (*mousecallback)();
00257 }
00258 
00259 void zpr::motion(int x, int y)
00260 {
00261   assert(global!=0);
00262   global->motionzpr(x,y);
00263 }
00264 
00265 void zpr::motionzpr(intc x, intc y)
00266 {
00267   bool changed = false;
00268 
00269   intc dx = x - mouseX;
00270   intc dy = y - mouseY;
00271 
00272   if (dx==0 && dy==0)
00273     return;
00274 
00275   if (mouseMiddle || (mouseLeft && mouseRight))
00276   {
00277     GLdouble s = exp((GLdouble)dy*0.01);
00278     glScalef(s,s,s);
00279     changed = true;
00280   }
00281   else
00282   if (mouseLeft)
00283   {
00284     GLdouble ax,ay,az;
00285     GLdouble bx,by,bz;
00286     GLdouble angle;
00287 
00288     ax = dy;
00289     ay = dx;
00290     az = 0.0;
00291     angle = vlen(ax,ay,az)/(GLdouble)(width+1)*180.0;
00292 
00293     /* Use inverse matrix to determine local axis of rotation */
00294 
00295     bx = matrixI[0]*ax + matrixI[4]*ay + matrixI[8]*az;
00296     by = matrixI[1]*ax + matrixI[5]*ay + matrixI[9]*az;
00297     bz = matrixI[2]*ax + matrixI[6]*ay + matrixI[10]*az;
00298 
00299     glRotatef(angle,bx,by,bz);
00300   
00301     changed = true;
00302   }
00303   else
00304   if (mouseRight)
00305   {
00306     GLdouble px,py,pz;
00307 
00308     readMouse(&px,&py,&pz,x,y);
00309 
00310     glLoadIdentity();
00311     glTranslatef(px-mouseXworld,py-mouseYworld,pz-mouseZworld);
00312     glMultMatrixd(matrix);
00313 
00314     mouseXworld = px;
00315     mouseYworld = py;
00316     mouseZworld = pz;
00317 
00318     changed = true;
00319   }
00320 
00321   mouseX = x;
00322   mouseY = y;
00323 
00324   if (changed)
00325   { 
00326     readModelView();
00327     glutPostRedisplay();
00328   }
00329 }
00330 
00331 zpr::zpr()
00332 {
00333   global = this;
00334 
00335   mouseX = 0;
00336   mouseY = 0;
00337  
00338   mouseLeft   = false;
00339   mouseRight  = false;
00340   mouseMiddle = false;
00341 
00342   mouseXworld = 0.0;
00343   mouseYworld = 0.0;
00344   mouseZworld = 0.0;
00345 
00346   mousecallback = 0;
00347 
00348   //glMatrixMode(GL_MODELVIEW);
00349   //glLoadIdentity();
00350  
00351   readScreenDimensions();
00352 
00353   glMatrixMode(GL_PROJECTION);
00354   glLoadIdentity();
00355 
00356   zNear=1.0;
00357   zFar=10.0;
00358   gluPerspective(30, (GLfloat) width/(GLfloat) height, zNear, zFar);
00359 
00360   glMatrixMode(GL_MODELVIEW);
00361 
00362   glLoadIdentity();
00363   gluLookAt
00364   (
00365     0.0, 0.0, 2.0,  // Eye  - creates a x: [-2,2] y: [-2,2] screen.
00366     0.0, 0.0, 0.0,  // Center
00367     0.0, 1.0, 0.0   // Up
00368   );
00369 
00370 
00371   glerrordisplay();
00372   update();
00373 
00374   glutReshapeFunc(reshape);
00375   glutMouseFunc(mouse);
00376   glutMotionFunc(motion);
00377 }
00378 
00379 void zpr::printInfo() const 
00380 {
00381 cout << SHOW(left) << endl;
00382 cout << SHOW(right) << endl;
00383 cout << SHOW(bottom) << endl;
00384 cout << SHOW(top) << endl;
00385 cout << SHOW(zNear) << endl;
00386 cout << SHOW(zFar) << endl;
00387 cout << SHOW(width) << endl;
00388 cout << SHOW(height) << endl;
00389 }
00390 
00391 void zpr::writefromXaxis()
00392 {
00393   GLdouble const xlen = right - left;
00394   GLdouble const ylen = xlen * (GLdouble) height / (GLdouble) width;
00395   top = bottom + ylen;
00396 
00397   write();
00398 }
00399 
00400 /*
00401 
00402 void zpr::setViewVolumeFromXaxis
00403 (
00404   int const width_,
00405   int const height_,
00406   GLdouble const left_,
00407   GLdouble const right_,
00408   GLdouble const bottom_,
00409   GLdouble const zNear_,
00410   GLdouble const zFar_
00411 )
00412 {
00413   width  = width_;
00414   height = height_;
00415 
00416   GLdouble const xlen = right_ - left_;
00417   GLdouble const ylen = xlen * (GLdouble) height / (GLdouble) width;
00418   GLdouble top_ = bottom_ + ylen;
00419 
00420 
00421 //cout << "left_=" << left_;
00422 //cout << " right_=" << right_;
00423 //cout << " bottom_=" << bottom_;
00424 //cout << " top_=" << top_;
00425 //cout << endl << endl;
00426 
00427 //cout << "xlen=" << xlen << " " << "ylen=" << ylen << endl;
00428 //cout << "top_=" << top_ << endl;
00429 
00430 
00431   setViewVolume(left_,right_,bottom_,top_,zNear_,zFar_);
00432 }
00433 
00434 */
00435 
00436 
00437 
00438 
00439 void zprGLmatrix::print() const
00440 {
00441   uint i;
00442   uint k;
00443   uint i2=0;
00444   for ( i=0; i<4; ++i)
00445   {
00446     for (k=0; k<4; ++k)
00447     {
00448       cout << matrix[i2] << " ";
00449       ++i2;
00450     }
00451     cout << endl;
00452   }
00453 }
00454 
00455 void zprGLmatrix::printTranspose() const
00456 {
00457   uint i;
00458   uint k;
00459   for ( i=0; i<4; ++i)
00460   {
00461     for (k=0; k<4; ++k)
00462     {
00463       cout << access(i,k) << " ";
00464     }
00465     cout << endl;
00466   }
00467 }
00468 
00469 void zpr::readScreenDimensions()
00470 {
00471   GLint viewport[4];
00472   glGetIntegerv( GL_VIEWPORT, viewport );
00473 
00474   glerrordisplay();
00475 
00476   width = viewport[2];
00477   height = viewport[3];
00478 }
00479 
00480 void zpr::readProjection()
00481 {
00482   static GLdouble pmatrix[16];
00483 
00484   glerrordisplay();
00485 
00486   glGetDoublev(GL_PROJECTION_MATRIX,pmatrix);
00487 
00488   glerrordisplay();
00489 
00490   zprGLmatrix mat(pmatrix);
00491 
00492   GLdouble a[6];
00493   a[0] = mat.access(0,0);
00494   a[1] = mat.access(1,1);
00495   a[2] = mat.access(0,2);
00496   a[3] = mat.access(1,2);
00497   a[4] = mat.access(2,2);
00498   a[5] = mat.access(2,3);
00499 
00500   // This is essentially an inverse of a glFrustrum(...) call.
00501   // Here the input parameters to the glFrustrum call are
00502   // calculated from the projection matrix.
00503   GLdouble c0 = (1.0-a[4])/(1.0+a[4]);
00504   //GLdouble z0 = a[5]*(c0+1.0)*-0.5/c0;
00505   GLdouble z0 = a[5]*(1.0+1.0/c0)*-0.50;
00506   GLdouble z1 = -c0*z0;
00507   GLdouble x0 = z0*(a[2]-1.0)/a[0];
00508   GLdouble x1 = (z0*2.0+a[0]*x0)/a[0];
00509   GLdouble y0 = z0*(a[3]-1.0)/a[1];
00510   GLdouble y1 = (z0*2.0+a[1]*y0)/a[1];
00511 
00512   left = x0;
00513   right = x1;
00514   bottom = y0;
00515   top = y1;
00516   zNear = z0;
00517   zFar = z1;
00518 
00519   glerrordisplay();
00520 }
00521 
00522 
00523 

Generated on Fri Mar 4 00:49:32 2011 for Chelton Evans Source by  doxygen 1.5.8