00001 /*!@file GUI/Viewport.C test opengl viewport */ 00002 00003 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2003 // 00004 // by the University of Southern California (USC) and the iLab at USC. // 00005 // See http://iLab.usc.edu for information about this project. // 00006 // //////////////////////////////////////////////////////////////////// // 00007 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00008 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00009 // in Visual Environments, and Applications'' by Christof Koch and // 00010 // Laurent Itti, California Institute of Technology, 2001 (patent // 00011 // pending; application number 09/912,225 filed July 23, 2001; see // 00012 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00013 // //////////////////////////////////////////////////////////////////// // 00014 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00015 // // 00016 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00017 // redistribute it and/or modify it under the terms of the GNU General // 00018 // Public License as published by the Free Software Foundation; either // 00019 // version 2 of the License, or (at your option) any later version. // 00020 // // 00021 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00022 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00023 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00024 // PURPOSE. See the GNU General Public License for more details. // 00025 // // 00026 // You should have received a copy of the GNU General Public License // 00027 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00028 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00029 // Boston, MA 02111-1307 USA. // 00030 // //////////////////////////////////////////////////////////////////// // 00031 // Primary maintainer for this file: Lior Elazary <elazary@usc.edu> 00032 // Originally obtained from ode 00033 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/GUI/ViewPort.C $ 00034 // $Id: ViewPort.C 14563 2011-03-02 01:09:49Z dberg $ 00035 00036 00037 #include "GUI/ViewPort.H" 00038 #include <math.h> 00039 #include <pthread.h> 00040 #include <sys/stat.h> 00041 00042 //TODO: we need to only draw a new camera position of the current rendering. NOt rander the whole thing. Can Use glViewPort 00043 00044 ViewPort::ViewPort(const char *winname, 00045 const char* ground, const char* sky, bool useFog, 00046 bool drawWorld, 00047 int w, int h, 00048 const double cameraParam[3][4] ) : 00049 itsWidth(w), 00050 itsHeight(h), 00051 run(0), 00052 display(0), 00053 visual(0), 00054 colormap(0), 00055 win(0), 00056 glx_context(0), 00057 last_key_pressed(0), 00058 wm_protocols_atom(0), 00059 wm_delete_window_atom(0), 00060 screen(0), 00061 sky_texture(0), 00062 ground_texture(0), 00063 wood_texture(0), 00064 tree_texture(0), 00065 other_texture(0), 00066 listnum(0), 00067 itsDrawWorld(drawWorld), 00068 itsUseFog(useFog), 00069 itsWireframe(false), 00070 itsZoomFactor(0.8) 00071 { 00072 createMainWindow (winname); 00073 00074 glXMakeCurrent (display,win,glx_context); 00075 startGraphics("./etc/textures/", ground, sky); 00076 00077 for(int i=0; i<4; i++) 00078 color[i] = 0; 00079 tnum = 0; // current texture number 00080 00081 ground_scale = 1.0f/20.0f; // ground texture scale (1/size) 00082 ground_ofsx = 0.5; // offset of ground texture 00083 ground_ofsy = 0.5; 00084 sky_scale = 1.0f/4.0f; // sky texture scale (1/size) 00085 sky_height = 1.0f; // sky height above viewpoint 00086 00087 sphere_quality = 1; 00088 capped_cylinder_quality = 3; 00089 00090 if (itsDrawWorld) 00091 { 00092 use_textures=1; // 1 if textures to be drawn 00093 use_shadows=1; // 1 if shadows to be drawn 00094 } else { 00095 use_textures=0; // 1 if textures to be drawn 00096 use_shadows=0; // 1 if shadows to be drawn 00097 } 00098 00099 00100 initCamera(); //set the camera to initail position 00101 00102 if (cameraParam != NULL) 00103 buildProjectionMatrix(cameraParam, itsProjMatrix); 00104 00105 run = 1; 00106 //int rc = pthread_create(&win_thread, NULL, ViewPort::mainWindowThread, this); 00107 //if (rc){ 00108 // LFATAL("Error creating main window thread\n"); 00109 //} 00110 //mainWindowThread(this); 00111 } 00112 00113 ViewPort::~ViewPort(){ 00114 stopGraphics(); 00115 00116 destroyMainWindow(); 00117 } 00118 00119 void ViewPort::setTextures(bool val) 00120 { 00121 if (val) 00122 use_textures=1; 00123 else 00124 use_textures=0; 00125 } 00126 00127 void ViewPort::setShadows(bool val) 00128 { 00129 if (val) 00130 use_shadows=1; 00131 else 00132 use_shadows=0; 00133 } 00134 00135 00136 void ViewPort::createMainWindow (const char *winname){ 00137 00138 display = XOpenDisplay (NULL); 00139 if (!display) LFATAL("can not open X11 display"); 00140 00141 screen = DefaultScreen(display); 00142 00143 00144 // get GL visual 00145 static int attribList[] = {GLX_RGBA, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE,16, 00146 GLX_RED_SIZE,4, GLX_GREEN_SIZE,4, 00147 GLX_BLUE_SIZE,4, None}; 00148 visual = glXChooseVisual (display,screen,attribList); 00149 if (!visual) LFATAL("no good X11 visual found for OpenGL"); 00150 00151 // create colormap 00152 colormap = XCreateColormap (display,RootWindow(display,screen), 00153 visual->visual,AllocNone); 00154 00155 // initialize variables 00156 win = 0; 00157 //glx_context = 0; 00158 last_key_pressed = 0; 00159 00160 if (itsWidth < 1 || itsHeight < 1) LDEBUG ("bad window width or height"); 00161 00162 // create the window 00163 XSetWindowAttributes attributes; 00164 attributes.background_pixel = BlackPixel(display,screen); 00165 attributes.colormap = colormap; 00166 attributes.event_mask = ButtonPressMask | ButtonReleaseMask | 00167 KeyPressMask | KeyReleaseMask | ButtonMotionMask | PointerMotionHintMask | 00168 StructureNotifyMask; 00169 win = XCreateWindow (display,RootWindow(display,screen),50,50,itsWidth,itsHeight, 00170 0,visual->depth, InputOutput,visual->visual, 00171 CWBackPixel | CWColormap | CWEventMask,&attributes); 00172 00173 // associate a GLX context with the window 00174 glx_context = glXCreateContext (display,visual,0,GL_TRUE); 00175 if (!glx_context) LFATAL ("can't make an OpenGL context"); 00176 00177 // set the window title 00178 XTextProperty window_name; 00179 window_name.value = (unsigned char *)winname; //(unsigned char *) "Simulation"; 00180 window_name.encoding = XA_STRING; 00181 window_name.format = 8; 00182 window_name.nitems = strlen((char *) window_name.value); 00183 XSetWMName (display,win,&window_name); 00184 00185 // participate in the window manager 'delete yourself' protocol 00186 wm_protocols_atom = XInternAtom (display,"WM_PROTOCOLS",False); 00187 wm_delete_window_atom = XInternAtom (display,"WM_DELETE_WINDOW",False); 00188 if (XSetWMProtocols (display,win,&wm_delete_window_atom,1)==0) 00189 LFATAL ("XSetWMProtocols() call failed"); 00190 00191 // pop up the window 00192 XMapWindow (display,win); 00193 XSync (display,win); 00194 00195 } 00196 00197 void ViewPort::destroyMainWindow() 00198 { 00199 glXDestroyContext (display,glx_context); 00200 XDestroyWindow (display,win); 00201 XSync (display,0); 00202 display = 0; 00203 win = 0; 00204 glx_context = NULL; 00205 } 00206 00207 00208 void ViewPort::startGraphics (const char *prefix, const char *ground, const char *sky){ 00209 // All examples build into the same dir 00210 char *s = new char[strlen(prefix) + 20]; 00211 00212 strcpy (s,prefix); 00213 strcat (s,sky); 00214 sky_texture = new Texture (s); 00215 00216 strcpy (s,prefix); 00217 strcat (s,ground); 00218 ground_texture = new Texture (s); 00219 00220 strcpy (s,prefix); 00221 strcat (s,"wood.ppm"); 00222 wood_texture = new Texture (s); 00223 00224 strcpy (s,prefix); 00225 strcat (s,"tree.ppm"); 00226 tree_texture = new Texture (s); 00227 } 00228 00229 void ViewPort::stopGraphics() 00230 { 00231 if (sky_texture) delete sky_texture; 00232 if (ground_texture) delete ground_texture; 00233 if (wood_texture) delete wood_texture; 00234 if (tree_texture) delete tree_texture; 00235 if (other_texture) delete other_texture; 00236 sky_texture = 0; 00237 ground_texture = 0; 00238 tree_texture = 0; 00239 other_texture = 0; 00240 } 00241 00242 void ViewPort::handleEvent (XEvent &event) 00243 { 00244 static int mx=0,my=0; // mouse position 00245 static int mode = 0; // mouse button bits 00246 00247 //LDEBUG("Handeling event %i\n", event.type); 00248 00249 switch (event.type) { 00250 00251 case ButtonPress: { 00252 if (event.xbutton.button == Button1) mode |= 1; 00253 if (event.xbutton.button == Button2) mode |= 2; 00254 if (event.xbutton.button == Button3) mode |= 4; 00255 mx = event.xbutton.x; 00256 my = event.xbutton.y; 00257 } 00258 return; 00259 00260 case ButtonRelease: { 00261 if (event.xbutton.button == Button1) mode &= (~1); 00262 if (event.xbutton.button == Button2) mode &= (~2); 00263 if (event.xbutton.button == Button3) mode &= (~4); 00264 mx = event.xbutton.x; 00265 my = event.xbutton.x; 00266 } 00267 return; 00268 00269 case MotionNotify: { 00270 if (event.xmotion.is_hint) { 00271 Window root,child; 00272 unsigned int mask; 00273 XQueryPointer (display,win,&root,&child,&event.xbutton.x_root, 00274 &event.xbutton.y_root,&event.xbutton.x,&event.xbutton.y, 00275 &mask); 00276 } 00277 dsMotion (mode, event.xmotion.x - mx, event.xmotion.y - my); 00278 mx = event.xmotion.x; 00279 my = event.xmotion.y; 00280 } 00281 return; 00282 00283 case ClientMessage: 00284 if (event.xclient.message_type == wm_protocols_atom && 00285 event.xclient.format == 32 && 00286 Atom(event.xclient.data.l[0]) == wm_delete_window_atom) { 00287 run = 0; 00288 return; 00289 } 00290 return; 00291 00292 case ConfigureNotify: 00293 itsWidth = event.xconfigure.width; 00294 itsHeight = event.xconfigure.height; 00295 return; 00296 } 00297 } 00298 00299 void ViewPort::initCamera() 00300 { 00301 view_xyz[0] = 0; 00302 view_xyz[1] = 5; 00303 view_xyz[2] = 5; 00304 view_hpr[0] = -100; 00305 view_hpr[1] = -30; 00306 view_hpr[2] = 0; 00307 } 00308 00309 00310 //!init the frame and process window events before drawing stuff 00311 XEvent ViewPort::initFrame(const double* cameraParam){ 00312 00313 ////process enevent for the window 00314 XEvent event; 00315 while (run && XPending (display)) { 00316 XNextEvent (display,&event); 00317 handleEvent (event); 00318 } 00319 00320 dsDrawFrame (cameraParam); 00321 00322 return event; 00323 } 00324 00325 00326 //! update the frame and return if we are running or not 00327 int ViewPort::updateFrame(){ 00328 00329 glFlush(); 00330 glXSwapBuffers (display,win); 00331 XSync (display,0); 00332 00333 return run; 00334 00335 } 00336 00337 void ViewPort::getFrame(unsigned char *img){ 00338 glXMakeCurrent (display,win,glx_context); 00339 glPixelStorei(GL_PACK_ALIGNMENT,1); 00340 glReadBuffer(GL_BACK_LEFT); 00341 glReadPixels (0, 0, itsWidth, itsHeight, GL_RGB, GL_UNSIGNED_BYTE, img); 00342 } 00343 00344 Image<PixRGB<byte> > ViewPort::getFrame(){ 00345 00346 Image<PixRGB<byte> > retImg(itsWidth, itsHeight, NO_INIT); 00347 glXMakeCurrent (display,win,glx_context); 00348 glPixelStorei(GL_PACK_ALIGNMENT,1); 00349 glReadBuffer(GL_BACK_LEFT); 00350 glReadPixels (0, 0, itsWidth, itsHeight, GL_RGB, GL_UNSIGNED_BYTE, (unsigned char*)retImg.getArrayPtr()); 00351 00352 return retImg; 00353 } 00354 00355 void ViewPort::mainWindowThread(void *data){ 00356 ViewPort *vp = (ViewPort *)data; 00357 vp->run = 1; 00358 while(vp->run){ 00359 XEvent event; 00360 while (vp->run && XPending (vp->display)) { 00361 XNextEvent (vp->display,&event); 00362 vp->handleEvent (event); 00363 } 00364 00365 //vp->dsDrawFrame (); 00366 00367 glFlush(); 00368 glXSwapBuffers (vp->display,vp->win); 00369 XSync (vp->display,0); 00370 00371 // capture frames if necessary 00372 if (vp->writeframes) { 00373 //captureFrame (frame); 00374 //frame++; 00375 } 00376 } 00377 00378 } 00379 00380 inline double ViewPort::dDOT (const double *a, const double *b) 00381 { return ((a)[0]*(b)[0] + (a)[1]*(b)[1] + (a)[2]*(b)[2]); } 00382 00383 00384 void ViewPort::normalizeVector3 (float v[3]) 00385 { 00386 double len = v[0]*v[0] + v[1]*v[1] + v[2]*v[2]; 00387 if (len <= 0.0f) { 00388 v[0] = 1; 00389 v[1] = 0; 00390 v[2] = 0; 00391 } 00392 else { 00393 len = 1.0f / (double)sqrt(len); 00394 v[0] *= len; 00395 v[1] *= len; 00396 v[2] *= len; 00397 } 00398 } 00399 00400 //*************************************************************************** 00401 // OpenGL utility stuff 00402 00403 void ViewPort::buildProjectionMatrix(const double cameraParam[3][4], double projMatrix[16]) 00404 { 00405 //Borrowed from ARTToolkit 00406 00407 double icpara[3][4]; 00408 double trans[3][4]; 00409 double p[3][3], q[4][4]; 00410 int i, j; 00411 double gnear = 50; 00412 double gfar = 5000; 00413 00414 if( paramDecompMat(cameraParam, icpara, trans) < 0 ) 00415 LFATAL("Camera Parameter error!!\n"); 00416 00417 for( i = 0; i < 3; i++ ) { 00418 for( j = 0; j < 3; j++ ) { 00419 p[i][j] = icpara[i][j] / icpara[2][2]; 00420 } 00421 } 00422 q[0][0] = (2.0 * p[0][0] / itsWidth); 00423 q[0][1] = (2.0 * p[0][1] / itsWidth); 00424 q[0][2] = ((2.0 * p[0][2] / itsWidth) - 1.0); 00425 q[0][3] = 0.0; 00426 00427 q[1][0] = 0.0; 00428 q[1][1] = (2.0 * p[1][1] / itsHeight); 00429 q[1][2] = ((2.0 * p[1][2] / itsHeight) - 1.0); 00430 q[1][3] = 0.0; 00431 00432 q[2][0] = 0.0; 00433 q[2][1] = 0.0; 00434 q[2][2] = (gfar + gnear)/(gfar - gnear); 00435 q[2][3] = -2.0 * gfar * gnear / (gfar - gnear); 00436 00437 q[3][0] = 0.0; 00438 q[3][1] = 0.0; 00439 q[3][2] = 1.0; 00440 q[3][3] = 0.0; 00441 00442 for( i = 0; i < 4; i++ ) { 00443 for( j = 0; j < 3; j++ ) { 00444 projMatrix[i+j*4] = q[i][0] * trans[0][j] 00445 + q[i][1] * trans[1][j] 00446 + q[i][2] * trans[2][j]; 00447 } 00448 projMatrix[i+3*4] = q[i][0] * trans[0][3] 00449 + q[i][1] * trans[1][3] 00450 + q[i][2] * trans[2][3] 00451 + q[i][3]; 00452 } 00453 00454 } 00455 00456 #define NORM(a,b,c) sqrt(a*a + b*b + c*c) 00457 #define DOT(a1,a2,a3,b1,b2,b3) (a1*b1 + a2*b2 + a3*b3) 00458 00459 int ViewPort::paramDecompMat(const double source[3][4], double cpara[3][4], double trans[3][4] ) 00460 { 00461 int r, c; 00462 double Cpara[3][4]; 00463 double rem1, rem2, rem3; 00464 00465 if( source[2][3] >= 0 ) { 00466 for( r = 0; r < 3; r++ ){ 00467 for( c = 0; c < 4; c++ ){ 00468 Cpara[r][c] = source[r][c]; 00469 } 00470 } 00471 } 00472 else { 00473 for( r = 0; r < 3; r++ ){ 00474 for( c = 0; c < 4; c++ ){ 00475 Cpara[r][c] = -(source[r][c]); 00476 } 00477 } 00478 } 00479 00480 for( r = 0; r < 3; r++ ){ 00481 for( c = 0; c < 4; c++ ){ 00482 cpara[r][c] = 0.0; 00483 } 00484 } 00485 cpara[2][2] = NORM( Cpara[2][0], Cpara[2][1], Cpara[2][2] ); 00486 trans[2][0] = Cpara[2][0] / cpara[2][2]; 00487 trans[2][1] = Cpara[2][1] / cpara[2][2]; 00488 trans[2][2] = Cpara[2][2] / cpara[2][2]; 00489 trans[2][3] = Cpara[2][3] / cpara[2][2]; 00490 00491 cpara[1][2] = DOT( trans[2][0], trans[2][1], trans[2][2], 00492 Cpara[1][0], Cpara[1][1], Cpara[1][2] ); 00493 rem1 = Cpara[1][0] - cpara[1][2] * trans[2][0]; 00494 rem2 = Cpara[1][1] - cpara[1][2] * trans[2][1]; 00495 rem3 = Cpara[1][2] - cpara[1][2] * trans[2][2]; 00496 cpara[1][1] = NORM( rem1, rem2, rem3 ); 00497 trans[1][0] = rem1 / cpara[1][1]; 00498 trans[1][1] = rem2 / cpara[1][1]; 00499 trans[1][2] = rem3 / cpara[1][1]; 00500 00501 cpara[0][2] = DOT( trans[2][0], trans[2][1], trans[2][2], 00502 Cpara[0][0], Cpara[0][1], Cpara[0][2] ); 00503 cpara[0][1] = DOT( trans[1][0], trans[1][1], trans[1][2], 00504 Cpara[0][0], Cpara[0][1], Cpara[0][2] ); 00505 rem1 = Cpara[0][0] - cpara[0][1]*trans[1][0] - cpara[0][2]*trans[2][0]; 00506 rem2 = Cpara[0][1] - cpara[0][1]*trans[1][1] - cpara[0][2]*trans[2][1]; 00507 rem3 = Cpara[0][2] - cpara[0][1]*trans[1][2] - cpara[0][2]*trans[2][2]; 00508 cpara[0][0] = NORM( rem1, rem2, rem3 ); 00509 trans[0][0] = rem1 / cpara[0][0]; 00510 trans[0][1] = rem2 / cpara[0][0]; 00511 trans[0][2] = rem3 / cpara[0][0]; 00512 00513 trans[1][3] = (Cpara[1][3] - cpara[1][2]*trans[2][3]) / cpara[1][1]; 00514 trans[0][3] = (Cpara[0][3] - cpara[0][1]*trans[1][3] 00515 - cpara[0][2]*trans[2][3]) / cpara[0][0]; 00516 00517 for( r = 0; r < 3; r++ ){ 00518 for( c = 0; c < 3; c++ ){ 00519 cpara[r][c] /= cpara[2][2]; 00520 } 00521 } 00522 00523 return 0; 00524 } 00525 00526 00527 00528 void ViewPort::setCamera (double x, double y, double z, double h, double p, double r) 00529 { 00530 glMatrixMode (GL_MODELVIEW); 00531 glLoadIdentity(); 00532 glRotatef (90, 0,0,1); 00533 glRotatef (90, 0,1,0); 00534 glRotatef (r, 1,0,0); 00535 glRotatef (p, 0,1,0); 00536 glRotatef (-h, 0,0,1); 00537 glTranslatef (-x,-y,-z); 00538 } 00539 00540 00541 // sets the material color, not the light color 00542 00543 void ViewPort::setColor (double r, double g, double b, double alpha) 00544 { 00545 GLfloat light_ambient[4],light_diffuse[4],light_specular[4]; 00546 light_ambient[0] = r*0.3f; 00547 light_ambient[1] = g*0.3f; 00548 light_ambient[2] = b*0.3f; 00549 light_ambient[3] = alpha; 00550 light_diffuse[0] = r*0.7f; 00551 light_diffuse[1] = g*0.7f; 00552 light_diffuse[2] = b*0.7f; 00553 light_diffuse[3] = alpha; 00554 light_specular[0] = r*0.2f; 00555 light_specular[1] = g*0.2f; 00556 light_specular[2] = b*0.2f; 00557 light_specular[3] = alpha; 00558 glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, light_ambient); 00559 glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, light_diffuse); 00560 glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, light_specular); 00561 glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, 5.0f); 00562 } 00563 00564 00565 void ViewPort::setTransform (const double pos[3], const double R[12]) 00566 { 00567 GLfloat matrix[16]; 00568 matrix[0]=R[0]; 00569 matrix[1]=R[4]; 00570 matrix[2]=R[8]; 00571 matrix[3]=0; 00572 matrix[4]=R[1]; 00573 matrix[5]=R[5]; 00574 matrix[6]=R[9]; 00575 matrix[7]=0; 00576 matrix[8]=R[2]; 00577 matrix[9]=R[6]; 00578 matrix[10]=R[10]; 00579 matrix[11]=0; 00580 matrix[12]=pos[0]; 00581 matrix[13]=pos[1]; 00582 matrix[14]=pos[2]; 00583 matrix[15]=1; 00584 glPushMatrix(); 00585 glMultMatrixf (matrix); 00586 } 00587 00588 void ViewPort::unProjectPoint(const int x, const int y, double objLoc[3]) 00589 { 00590 00591 //From http://nehe.gamedev.net/data/articles/article.asp?article=13 00592 GLint viewport[4]; 00593 GLdouble modelview[16]; 00594 GLdouble projection[16]; 00595 GLfloat winX=0, winY=0, winZ=0; 00596 GLdouble posX=0, posY=0, posZ=0; 00597 00598 glGetDoublev( GL_MODELVIEW_MATRIX, modelview ); 00599 glGetDoublev( GL_PROJECTION_MATRIX, projection ); 00600 glGetIntegerv( GL_VIEWPORT, viewport ); 00601 00602 winX = (float)x; 00603 winY = (float)viewport[3] - (float)y; 00604 glReadPixels( x, int(winY), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ ); 00605 00606 00607 #ifdef INVT_HAVE_LIBGLUT 00608 gluUnProject( winX, winY, winZ, modelview, projection, viewport, &posX, &posY, &posZ); 00609 #endif 00610 00611 objLoc[0] = posX; 00612 objLoc[1] = posY; 00613 objLoc[2] = posZ; 00614 00615 } 00616 00617 // set shadow projection transform 00618 00619 void ViewPort::setShadowTransform() 00620 { 00621 GLfloat matrix[16]; 00622 for (int i=0; i<16; i++) matrix[i] = 0; 00623 matrix[0]=1; 00624 matrix[5]=1; 00625 matrix[8]=-LIGHTX; 00626 matrix[9]=-LIGHTY; 00627 matrix[15]=1; 00628 glPushMatrix(); 00629 glMultMatrixf (matrix); 00630 } 00631 00632 00633 void ViewPort::drawBox (const double sides[3]) 00634 { 00635 double lx = sides[0]*0.5f; 00636 double ly = sides[1]*0.5f; 00637 double lz = sides[2]*0.5f; 00638 00639 glBegin(GL_QUADS); 00640 glNormal3f(0,1,0); 00641 glVertex3f( lx, ly,-lz); // Top Right Of The Quad (Top) 00642 glVertex3f(-lx, ly,-lz); // Top Left Of The Quad (Top) 00643 glVertex3f(-lx, ly, lz); // Bottom Left Of The Quad (Top) 00644 glVertex3f( lx, ly, lz); // Bottom Right Of The Quad (Top) 00645 00646 glNormal3f(0,-1,0); 00647 glVertex3f( lx,-ly, lz); // Top Right Of The Quad (Bottom) 00648 glVertex3f(-lx,-ly, lz); // Top Left Of The Quad (Bottom) 00649 glVertex3f(-lx,-ly,-lz); // Bottom Left Of The Quad (Bottom) 00650 glVertex3f( lx,-ly,-lz); // Bottom Right Of The Quad (Bottom) 00651 00652 glNormal3f(0,0,1); 00653 glVertex3f( lx, ly, lz); // Top Right Of The Quad (Front) 00654 glVertex3f(-lx, ly, lz); // Top Left Of The Quad (Front) 00655 glVertex3f(-lx,-ly, lz); // Bottom Left Of The Quad (Front) 00656 glVertex3f( lx,-ly, lz); // Bottom Right Of The Quad (Front) 00657 00658 glNormal3f(0,0,-1); 00659 glVertex3f( lx,-ly,-lz); // Bottom Left Of The Quad (Back) 00660 glVertex3f(-lx,-ly,-lz); // Bottom Right Of The Quad (Back) 00661 glVertex3f(-lx, ly,-lz); // Top Right Of The Quad (Back) 00662 glVertex3f( lx, ly,-lz); // Top Left Of The Quad (Back) 00663 00664 glNormal3f(-1,0,0); 00665 glVertex3f(-lx, ly, lz); // Top Right Of The Quad (Left) 00666 glVertex3f(-lx, ly,-lz); // Top Left Of The Quad (Left) 00667 glVertex3f(-lx,-ly,-lz); // Bottom Left Of The Quad (Left) 00668 glVertex3f(-lx,-ly, lz); // Bottom Right Of The Quad (Left) 00669 00670 glNormal3f(1,0,0); 00671 glVertex3f( lx, ly,-lz); // Top Right Of The Quad (Right) 00672 glVertex3f( lx, ly, lz); // Top Left Of The Quad (Right) 00673 glVertex3f( lx,-ly, lz); // Bottom Left Of The Quad (Right) 00674 glVertex3f( lx,-ly,-lz); // Bottom Right Of The Quad (Right) 00675 glEnd(); // Done Drawing The Quad 00676 00677 } 00678 00679 00680 // This is recursively subdivides a triangular area (vertices p1,p2,p3) into 00681 // smaller triangles, and then draws the triangles. All triangle vertices are 00682 // normalized to a distance of 1.0 from the origin (p1,p2,p3 are assumed 00683 // to be already normalized). Note this is not super-fast because it draws 00684 // triangles rather than triangle strips. 00685 00686 void ViewPort::drawPatch (double p1[3], double p2[3], double p3[3], int level) 00687 { 00688 int i; 00689 if (level > 0) { 00690 double q1[3],q2[3],q3[3]; // sub-vertices 00691 for (i=0; i<3; i++) { 00692 q1[i] = 0.5f*(p1[i]+p2[i]); 00693 q2[i] = 0.5f*(p2[i]+p3[i]); 00694 q3[i] = 0.5f*(p3[i]+p1[i]); 00695 } 00696 double length1 = (double)(1.0/sqrt(q1[0]*q1[0]+q1[1]*q1[1]+q1[2]*q1[2])); 00697 double length2 = (double)(1.0/sqrt(q2[0]*q2[0]+q2[1]*q2[1]+q2[2]*q2[2])); 00698 double length3 = (double)(1.0/sqrt(q3[0]*q3[0]+q3[1]*q3[1]+q3[2]*q3[2])); 00699 for (i=0; i<3; i++) { 00700 q1[i] *= length1; 00701 q2[i] *= length2; 00702 q3[i] *= length3; 00703 } 00704 drawPatch (p1,q1,q3,level-1); 00705 drawPatch (q1,p2,q2,level-1); 00706 drawPatch (q1,q2,q3,level-1); 00707 drawPatch (q3,q2,p3,level-1); 00708 } 00709 else { 00710 glNormal3f (p1[0],p1[1],p1[2]); 00711 glVertex3f (p1[0],p1[1],p1[2]); 00712 glNormal3f (p2[0],p2[1],p2[2]); 00713 glVertex3f (p2[0],p2[1],p2[2]); 00714 glNormal3f (p3[0],p3[1],p3[2]); 00715 glVertex3f (p3[0],p3[1],p3[2]); 00716 } 00717 } 00718 00719 // draw a sphere of radius 1 00720 00721 void ViewPort::drawSphere() 00722 { 00723 // icosahedron data for an icosahedron of radius 1.0 00724 # define ICX 0.525731112119133606f 00725 # define ICZ 0.850650808352039932f 00726 static GLdouble idata[12][3] = { 00727 {-ICX, 0, ICZ}, 00728 {ICX, 0, ICZ}, 00729 {-ICX, 0, -ICZ}, 00730 {ICX, 0, -ICZ}, 00731 {0, ICZ, ICX}, 00732 {0, ICZ, -ICX}, 00733 {0, -ICZ, ICX}, 00734 {0, -ICZ, -ICX}, 00735 {ICZ, ICX, 0}, 00736 {-ICZ, ICX, 0}, 00737 {ICZ, -ICX, 0}, 00738 {-ICZ, -ICX, 0} 00739 }; 00740 00741 static int index[20][3] = { 00742 {0, 4, 1}, {0, 9, 4}, 00743 {9, 5, 4}, {4, 5, 8}, 00744 {4, 8, 1}, {8, 10, 1}, 00745 {8, 3, 10}, {5, 3, 8}, 00746 {5, 2, 3}, {2, 7, 3}, 00747 {7, 10, 3}, {7, 6, 10}, 00748 {7, 11, 6}, {11, 0, 6}, 00749 {0, 1, 6}, {6, 1, 10}, 00750 {9, 0, 11}, {9, 11, 2}, 00751 {9, 2, 5}, {7, 2, 11}, 00752 }; 00753 00754 if (listnum==0) { 00755 listnum = glGenLists (1); 00756 glNewList (listnum,GL_COMPILE); 00757 glBegin (GL_TRIANGLES); 00758 for (int i=0; i<20; i++) { 00759 drawPatch (&idata[index[i][2]][0],&idata[index[i][1]][0], 00760 &idata[index[i][0]][0],sphere_quality); 00761 } 00762 glEnd(); 00763 glEndList(); 00764 } 00765 glCallList (listnum); 00766 } 00767 00768 00769 00770 void ViewPort::drawSphereShadow (double px, double py, double pz, double radius) 00771 { 00772 // calculate shadow constants based on light vector 00773 static int init=0; 00774 static double len2,len1,scale; 00775 if (!init) { 00776 len2 = LIGHTX*LIGHTX + LIGHTY*LIGHTY; 00777 len1 = 1.0f/(double)sqrt(len2); 00778 scale = (double) sqrt(len2 + 1); 00779 init = 1; 00780 } 00781 00782 // map sphere center to ground plane based on light vector 00783 px -= LIGHTX*pz; 00784 py -= LIGHTY*pz; 00785 00786 const double kx = 0.96592582628907f; 00787 const double ky = 0.25881904510252f; 00788 double x=radius, y=0; 00789 00790 glBegin (GL_TRIANGLE_FAN); 00791 for (int i=0; i<24; i++) { 00792 // for all points on circle, scale to elongated rotated shadow and draw 00793 double x2 = (LIGHTX*x*scale - LIGHTY*y)*len1 + px; 00794 double y2 = (LIGHTY*x*scale + LIGHTX*y)*len1 + py; 00795 glTexCoord2f (x2*ground_scale+ground_ofsx,y2*ground_scale+ground_ofsy); 00796 glVertex3f (x2,y2,0); 00797 00798 // rotate [x,y] vector 00799 double xtmp = kx*x - ky*y; 00800 y = ky*x + kx*y; 00801 x = xtmp; 00802 } 00803 glEnd(); 00804 } 00805 00806 00807 void ViewPort::drawTriangle (const double *v0, const double *v1, const double *v2, int solid) 00808 { 00809 float u[3],v[3],normal[3]; 00810 u[0] = v1[0] - v0[0]; 00811 u[1] = v1[1] - v0[1]; 00812 u[2] = v1[2] - v0[2]; 00813 v[0] = v2[0] - v0[0]; 00814 v[1] = v2[1] - v0[1]; 00815 v[2] = v2[2] - v0[2]; 00816 00817 normal[0] = (u[1]*v[2] - u[2]*v[1]); 00818 normal[1] = (u[2]*v[0] - u[0]*v[2]); 00819 normal[2] = (u[0]*v[1] - u[1]*v[0]); 00820 00821 normalizeVector3 (normal); 00822 00823 glBegin(solid ? GL_TRIANGLES : GL_LINE_STRIP); 00824 glNormal3fv (normal); 00825 glVertex3dv (v0); 00826 glVertex3dv (v1); 00827 glVertex3dv (v2); 00828 glEnd(); 00829 } 00830 00831 void ViewPort::drawTriangleD (const double *v0, const double *v1, const double *v2, int solid) 00832 { 00833 float u[3],v[3],normal[3]; 00834 u[0] = double( v1[0] - v0[0] ); 00835 u[1] = double( v1[1] - v0[1] ); 00836 u[2] = double( v1[2] - v0[2] ); 00837 v[0] = double( v2[0] - v0[0] ); 00838 v[1] = double( v2[1] - v0[1] ); 00839 v[2] = double( v2[2] - v0[2] ); 00840 00841 normal[0] = (u[1]*v[2] - u[2]*v[1]); 00842 normal[1] = (u[2]*v[0] - u[0]*v[2]); 00843 normal[2] = (u[0]*v[1] - u[1]*v[0]); 00844 00845 normalizeVector3 (normal); 00846 00847 glBegin(solid ? GL_TRIANGLES : GL_LINE_STRIP); 00848 glNormal3fv (normal); 00849 glVertex3dv (v0); 00850 glVertex3dv (v1); 00851 glVertex3dv (v2); 00852 glEnd(); 00853 } 00854 00855 00856 // draw a capped cylinder of length l and radius r, aligned along the x axis 00857 00858 void ViewPort::drawCappedCylinder (double l, double r) 00859 { 00860 int i,j; 00861 double tmp,nx,ny,nz,start_nx,start_ny,a,ca,sa; 00862 // number of sides to the cylinder (divisible by 4): 00863 const int n = capped_cylinder_quality*4; 00864 00865 l *= 0.5; 00866 a = double(M_PI*2.0)/double(n); 00867 sa = (double) sin(a); 00868 ca = (double) cos(a); 00869 00870 // draw cylinder body 00871 ny=1; nz=0; // normal vector = (0,ny,nz) 00872 glBegin (GL_TRIANGLE_STRIP); 00873 for (i=0; i<=n; i++) { 00874 glNormal3d (ny,nz,0); 00875 glVertex3d (ny*r,nz*r,l); 00876 glNormal3d (ny,nz,0); 00877 glVertex3d (ny*r,nz*r,-l); 00878 // rotate ny,nz 00879 tmp = ca*ny - sa*nz; 00880 nz = sa*ny + ca*nz; 00881 ny = tmp; 00882 } 00883 glEnd(); 00884 00885 // draw first cylinder cap 00886 start_nx = 0; 00887 start_ny = 1; 00888 for (j=0; j<(n/4); j++) { 00889 // get start_n2 = rotated start_n 00890 double start_nx2 = ca*start_nx + sa*start_ny; 00891 double start_ny2 = -sa*start_nx + ca*start_ny; 00892 // get n=start_n and n2=start_n2 00893 nx = start_nx; ny = start_ny; nz = 0; 00894 double nx2 = start_nx2, ny2 = start_ny2, nz2 = 0; 00895 glBegin (GL_TRIANGLE_STRIP); 00896 for (i=0; i<=n; i++) { 00897 glNormal3d (ny2,nz2,nx2); 00898 glVertex3d (ny2*r,nz2*r,l+nx2*r); 00899 glNormal3d (ny,nz,nx); 00900 glVertex3d (ny*r,nz*r,l+nx*r); 00901 // rotate n,n2 00902 tmp = ca*ny - sa*nz; 00903 nz = sa*ny + ca*nz; 00904 ny = tmp; 00905 tmp = ca*ny2- sa*nz2; 00906 nz2 = sa*ny2 + ca*nz2; 00907 ny2 = tmp; 00908 } 00909 glEnd(); 00910 start_nx = start_nx2; 00911 start_ny = start_ny2; 00912 } 00913 00914 // draw second cylinder cap 00915 start_nx = 0; 00916 start_ny = 1; 00917 for (j=0; j<(n/4); j++) { 00918 // get start_n2 = rotated start_n 00919 double start_nx2 = ca*start_nx - sa*start_ny; 00920 double start_ny2 = sa*start_nx + ca*start_ny; 00921 // get n=start_n and n2=start_n2 00922 nx = start_nx; ny = start_ny; nz = 0; 00923 double nx2 = start_nx2, ny2 = start_ny2, nz2 = 0; 00924 glBegin (GL_TRIANGLE_STRIP); 00925 for (i=0; i<=n; i++) { 00926 glNormal3d (ny,nz,nx); 00927 glVertex3d (ny*r,nz*r,-l+nx*r); 00928 glNormal3d (ny2,nz2,nx2); 00929 glVertex3d (ny2*r,nz2*r,-l+nx2*r); 00930 // rotate n,n2 00931 tmp = ca*ny - sa*nz; 00932 nz = sa*ny + ca*nz; 00933 ny = tmp; 00934 tmp = ca*ny2- sa*nz2; 00935 nz2 = sa*ny2 + ca*nz2; 00936 ny2 = tmp; 00937 } 00938 glEnd(); 00939 start_nx = start_nx2; 00940 start_ny = start_ny2; 00941 } 00942 00943 glPopMatrix(); 00944 } 00945 00946 00947 // draw a cylinder of length l and radius r, aligned along the z axis 00948 00949 void ViewPort::drawCylinder (double l, double r, double zoffset) 00950 { 00951 int i; 00952 double tmp,ny,nz,a,ca,sa; 00953 const int n = 24; // number of sides to the cylinder (divisible by 4) 00954 00955 l *= 0.5; 00956 a = double(M_PI*2.0)/double(n); 00957 sa = (double) sin(a); 00958 ca = (double) cos(a); 00959 00960 // draw cylinder body 00961 ny=1; nz=0; // normal vector = (0,ny,nz) 00962 glBegin (GL_TRIANGLE_STRIP); 00963 for (i=0; i<=n; i++) { 00964 glNormal3d (ny,nz,0); 00965 glVertex3d (ny*r,nz*r,l+zoffset); 00966 glNormal3d (ny,nz,0); 00967 glVertex3d (ny*r,nz*r,-l+zoffset); 00968 // rotate ny,nz 00969 tmp = ca*ny - sa*nz; 00970 nz = sa*ny + ca*nz; 00971 ny = tmp; 00972 } 00973 glEnd(); 00974 00975 // draw top cap 00976 glShadeModel (GL_FLAT); 00977 ny=1; nz=0; // normal vector = (0,ny,nz) 00978 glBegin (GL_TRIANGLE_FAN); 00979 glNormal3d (0,0,1); 00980 glVertex3d (0,0,l+zoffset); 00981 for (i=0; i<=n; i++) { 00982 if (i==1 || i==n/2+1) 00983 setColor (color[0]*0.75f,color[1]*0.75f,color[2]*0.75f,color[3]); 00984 glNormal3d (0,0,1); 00985 glVertex3d (ny*r,nz*r,l+zoffset); 00986 if (i==1 || i==n/2+1) 00987 setColor (color[0],color[1],color[2],color[3]); 00988 00989 // rotate ny,nz 00990 tmp = ca*ny - sa*nz; 00991 nz = sa*ny + ca*nz; 00992 ny = tmp; 00993 } 00994 glEnd(); 00995 00996 // draw bottom cap 00997 ny=1; nz=0; // normal vector = (0,ny,nz) 00998 glBegin (GL_TRIANGLE_FAN); 00999 glNormal3d (0,0,-1); 01000 glVertex3d (0,0,-l+zoffset); 01001 for (i=0; i<=n; i++) { 01002 if (i==1 || i==n/2+1) 01003 setColor (color[0]*0.75f,color[1]*0.75f,color[2]*0.75f,color[3]); 01004 glNormal3d (0,0,-1); 01005 glVertex3d (ny*r,nz*r,-l+zoffset); 01006 if (i==1 || i==n/2+1) 01007 setColor (color[0],color[1],color[2],color[3]); 01008 01009 // rotate ny,nz 01010 tmp = ca*ny + sa*nz; 01011 nz = -sa*ny + ca*nz; 01012 ny = tmp; 01013 } 01014 glEnd(); 01015 } 01016 01017 //*************************************************************************** 01018 // motion model 01019 01020 // initialize the above variables 01021 01022 void ViewPort::initMotionModel() 01023 { 01024 view_xyz[0] = 2; 01025 view_xyz[1] = 0; 01026 view_xyz[2] = 1; 01027 view_hpr[0] = 180; 01028 view_hpr[1] = 0; 01029 view_hpr[2] = 0; 01030 } 01031 01032 01033 void ViewPort::wrapCameraAngles() 01034 { 01035 for (int i=0; i<3; i++) { 01036 while (view_hpr[i] > 180) view_hpr[i] -= 360; 01037 while (view_hpr[i] < -180) view_hpr[i] += 360; 01038 } 01039 } 01040 01041 01042 // call this to update the current camera position. the bits in `mode' say 01043 // if the left (1), middle (2) or right (4) mouse button is pressed, and 01044 // (deltax,deltay) is the amount by which the mouse pointer has moved. 01045 01046 void ViewPort::dsMotion (int mode, int deltax, int deltay) 01047 { 01048 double side = 0.01f * double(deltax); 01049 double fwd = (mode==4) ? (0.01f * double(deltay)) : 0.0f; 01050 double s = (double) sin (view_hpr[0]*DEG_TO_RAD); 01051 double c = (double) cos (view_hpr[0]*DEG_TO_RAD); 01052 01053 LINFO("Movde %i", mode); 01054 switch(mode) 01055 { 01056 case 1: 01057 view_hpr[0] += double (deltax) * 0.5f; 01058 view_hpr[1] += double (deltay) * 0.5f; 01059 break; 01060 case 2: 01061 case 5: 01062 view_xyz[2] += 0.01f * double(deltay); 01063 view_hpr[2] += double (deltax) * 0.5f; 01064 break; 01065 case 4: 01066 view_xyz[0] += -s*side + c*fwd; 01067 view_xyz[1] += c*side + s*fwd; 01068 break; 01069 01070 } 01071 wrapCameraAngles(); 01072 01073 LINFO("Camera pos:(%f,%f,%f) Rot:(%f,%f,%f)", 01074 view_xyz[0], view_xyz[1], view_xyz[2], 01075 view_hpr[0], view_hpr[1], view_hpr[2]); 01076 01077 } 01078 01079 //*************************************************************************** 01080 // drawing loop stuff 01081 01082 void ViewPort::drawSky (double view_xyz[3]) 01083 { 01084 glDisable (GL_LIGHTING); 01085 if (use_textures && sky_texture->initialized()) { 01086 glEnable (GL_TEXTURE_2D); 01087 sky_texture->bind (0); 01088 } 01089 else { 01090 glDisable (GL_TEXTURE_2D); 01091 glColor3f (0,0.5,1.0); 01092 } 01093 01094 // make sure sky depth is as far back as possible 01095 glShadeModel (GL_FLAT); 01096 glEnable (GL_DEPTH_TEST); 01097 glDepthFunc (GL_LEQUAL); 01098 glDepthRange (1,1); 01099 01100 const double ssize = 1000.0f; 01101 static double offset = 0.0f; 01102 01103 double x = ssize*sky_scale; 01104 double z = view_xyz[2] + sky_height; 01105 01106 glBegin (GL_QUADS); 01107 glNormal3f (0,0,-1); 01108 glTexCoord2f (-x+offset,-x+offset); 01109 glVertex3f (-ssize+view_xyz[0],-ssize+view_xyz[1],z); 01110 glTexCoord2f (-x+offset,x+offset); 01111 glVertex3f (-ssize+view_xyz[0],ssize+view_xyz[1],z); 01112 glTexCoord2f (x+offset,x+offset); 01113 glVertex3f (ssize+view_xyz[0],ssize+view_xyz[1],z); 01114 glTexCoord2f (x+offset,-x+offset); 01115 glVertex3f (ssize+view_xyz[0],-ssize+view_xyz[1],z); 01116 glEnd(); 01117 01118 offset = offset + 0.001f; 01119 if (offset > 1) offset -= 1; 01120 01121 glDepthFunc (GL_LESS); 01122 glDepthRange (0,1); 01123 } 01124 01125 01126 void ViewPort::drawGround() 01127 { 01128 glDisable (GL_LIGHTING); 01129 glShadeModel (GL_FLAT); 01130 glEnable (GL_DEPTH_TEST); 01131 glDepthFunc (GL_LESS); 01132 // glDepthRange (1,1); 01133 01134 if (use_textures) { 01135 glEnable (GL_TEXTURE_2D); 01136 ground_texture->bind (0); 01137 } 01138 else { 01139 glDisable (GL_TEXTURE_2D); 01140 glColor3f (GROUND_R,GROUND_G,GROUND_B); 01141 } 01142 01143 if (itsUseFog) 01144 { 01145 // ground fog seems to cause problems with TNT2 under windows 01146 01147 GLfloat fogColor[4] = {0.0, 0.2, 0.1, 1}; 01148 glEnable (GL_FOG); 01149 glFogi (GL_FOG_MODE, GL_LINEAR); 01150 glFogfv (GL_FOG_COLOR, fogColor); 01151 glFogf (GL_FOG_DENSITY, 0.07f); 01152 glHint (GL_FOG_HINT, GL_NICEST); // GL_DONT_CARE); 01153 glFogf (GL_FOG_START, 0.0); 01154 glFogf (GL_FOG_END, 10.0); 01155 } 01156 01157 01158 const double gsize = 100.0f; 01159 const double offset = 0; // -0.001f; ... polygon offsetting doesn't work well 01160 01161 glBegin (GL_QUADS); 01162 glNormal3f (0,0,1); 01163 01164 glTexCoord2f (-gsize*ground_scale + ground_ofsx, 01165 -gsize*ground_scale + ground_ofsy); 01166 glVertex3f (-gsize,-gsize,offset); 01167 01168 glTexCoord2f (gsize*ground_scale + ground_ofsx, 01169 -gsize*ground_scale + ground_ofsy); 01170 glVertex3f (gsize,-gsize,offset); 01171 01172 glTexCoord2f (gsize*ground_scale + ground_ofsx, 01173 gsize*ground_scale + ground_ofsy); 01174 glVertex3f (gsize,gsize,offset); 01175 01176 glTexCoord2f (-gsize*ground_scale + ground_ofsx, 01177 gsize*ground_scale + ground_ofsy); 01178 glVertex3f (-gsize,gsize,offset); 01179 glEnd(); 01180 01181 // if (itsUseFog) 01182 // glDisable (GL_FOG); 01183 } 01184 01185 01186 void ViewPort::drawPyramidGrid() 01187 { 01188 // setup stuff 01189 glEnable (GL_LIGHTING); 01190 glDisable (GL_TEXTURE_2D); 01191 glShadeModel (GL_FLAT); 01192 glEnable (GL_DEPTH_TEST); 01193 glDepthFunc (GL_LESS); 01194 01195 // draw the pyramid grid 01196 for (int i=-1; i<=1; i++) { 01197 for (int j=-1; j<=1; j++) { 01198 glPushMatrix(); 01199 glTranslatef ((double)i,(double)j,(double)0); 01200 if (i==1 && j==0) setColor (1,0,0,1); 01201 else if (i==0 && j==1) setColor (0,0,1,1); 01202 else setColor (1,1,0,1); 01203 const double k = 0.03f; 01204 glBegin (GL_TRIANGLE_FAN); 01205 glNormal3f (0,-1,1); 01206 glVertex3f (0,0,k); 01207 glVertex3f (-k,-k,0); 01208 glVertex3f ( k,-k,0); 01209 glNormal3f (1,0,1); 01210 glVertex3f ( k, k,0); 01211 glNormal3f (0,1,1); 01212 glVertex3f (-k, k,0); 01213 glNormal3f (-1,0,1); 01214 glVertex3f (-k,-k,0); 01215 glEnd(); 01216 glPopMatrix(); 01217 } 01218 } 01219 } 01220 01221 01222 void ViewPort::dsDrawFrame (const double cameraParam[16]) 01223 { 01224 glXMakeCurrent (display,win,glx_context); 01225 // setup stuff 01226 glEnable (GL_LIGHTING); 01227 glEnable (GL_LIGHT0); 01228 glDisable (GL_TEXTURE_2D); 01229 glDisable (GL_TEXTURE_GEN_S); 01230 glDisable (GL_TEXTURE_GEN_T); 01231 glShadeModel (GL_FLAT); 01232 glEnable (GL_DEPTH_TEST); 01233 glDepthFunc (GL_LESS); 01234 glEnable (GL_CULL_FACE); 01235 glCullFace (GL_BACK); 01236 glFrontFace (GL_CCW); 01237 01238 if (itsWireframe) 01239 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); //wireframe mode 01240 01241 // setup viewport 01242 glMatrixMode(GL_MODELVIEW); 01243 glLoadIdentity(); 01244 01245 glViewport (0,0,itsWidth,itsHeight); 01246 01247 glMatrixMode (GL_PROJECTION); 01248 01249 if (itsProjMatrix==NULL) //Load from current view 01250 { 01251 glLoadIdentity(); 01252 const double vnear = 50.1f; 01253 const double vfar = 5000.0f; 01254 const double k = itsZoomFactor; // view scale, 1 = +/- 45 degrees 01255 01256 01257 if (itsWidth >= itsHeight) { 01258 double k2 = double(itsHeight)/double(itsWidth); 01259 glFrustum (-vnear*k,vnear*k,-vnear*k*k2,vnear*k*k2,vnear,vfar); 01260 } 01261 else { 01262 double k2 = double(itsWidth)/double(itsHeight); 01263 glFrustum (-vnear*k*k2,vnear*k*k2,-vnear*k,vnear*k,vnear,vfar); 01264 } 01265 } else { //Load the camera params 01266 glLoadMatrixd(itsProjMatrix); 01267 } 01268 01269 // setup lights. it makes a difference whether this is done in the 01270 // GL_PROJECTION matrix mode (lights are scene relative) or the 01271 // GL_MODELVIEW matrix mode (lights are camera relative, bad!). 01272 static GLfloat light_ambient[] = { 0.2, 0.2, 0.2, 1.0 }; 01273 static GLfloat light_diffuse[] = { 0.0, 0.0, 0.0, 0.0 }; 01274 static GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 }; 01275 glLightfv (GL_LIGHT0, GL_AMBIENT, light_ambient); 01276 glLightfv (GL_LIGHT0, GL_DIFFUSE, light_diffuse); 01277 glLightfv (GL_LIGHT0, GL_SPECULAR, light_specular); 01278 glColor3f (0.0, 0.0, 0.0); 01279 01280 // clear the window 01281 glClearColor (0.0,0.0,0.0,0); 01282 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 01283 01284 // go to GL_MODELVIEW matrix mode and set the camera 01285 glMatrixMode (GL_MODELVIEW); 01286 01287 if (cameraParam==NULL) 01288 { 01289 glLoadIdentity(); 01290 setCamera (view_xyz[0],view_xyz[1],view_xyz[2], 01291 view_hpr[0],view_hpr[1],view_hpr[2]); 01292 } else { 01293 glLoadMatrixd(cameraParam ); 01294 } 01295 01296 01297 // set the light position (for some reason we have to do this in model view. 01298 static GLfloat light_position[] = { LIGHTX, LIGHTY, 5.0 }; 01299 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, light_position); 01300 glLightfv (GL_LIGHT0, GL_POSITION, light_position); 01301 01302 // draw the background (ground, sky etc) 01303 if (itsDrawWorld) 01304 { 01305 drawSky (view_xyz); 01306 drawGround(); 01307 } 01308 01309 // draw the little markers on the ground 01310 //drawPyramidGrid(); 01311 01312 // leave openGL in a known state - flat shaded white, no textures 01313 glEnable (GL_LIGHTING); 01314 glDisable (GL_TEXTURE_2D); 01315 glShadeModel (GL_FLAT); 01316 glEnable (GL_DEPTH_TEST); 01317 glDepthFunc (GL_LESS); 01318 glColor3f (1,1,1); 01319 setColor (1,1,1,1); 01320 01321 // draw the rest of the objects. set drawing state first. 01322 color[0] = 1; 01323 color[1] = 1; 01324 color[2] = 1; 01325 color[3] = 1; 01326 tnum = 0; 01327 } 01328 01329 int ViewPort::dsGetShadows() 01330 { 01331 return use_shadows; 01332 } 01333 01334 01335 void ViewPort::dsSetShadows (int a) 01336 { 01337 use_shadows = (a != 0); 01338 } 01339 01340 01341 int ViewPort::dsGetTextures() 01342 { 01343 return use_textures; 01344 } 01345 01346 01347 void ViewPort::dsSetTextures (int a) 01348 { 01349 use_textures = (a != 0); 01350 } 01351 01352 //*************************************************************************** 01353 // C interface 01354 01355 // sets lighting and texture modes, sets current color 01356 void ViewPort::setupDrawingMode() 01357 { 01358 glXMakeCurrent (display,win,glx_context); 01359 01360 glEnable (GL_LIGHTING); 01361 bool enableWrap = true; 01362 if (tnum) { 01363 if (use_textures) { 01364 glEnable (GL_TEXTURE_2D); 01365 01366 switch (tnum) 01367 { 01368 case SKY: 01369 sky_texture->bind (1); 01370 enableWrap = true; 01371 break; 01372 case GROUND: 01373 ground_texture->bind (1); 01374 enableWrap = true; 01375 break; 01376 case WOOD: 01377 wood_texture->bind (1); 01378 enableWrap = true; 01379 break; 01380 case TREE: 01381 tree_texture->bind (1); 01382 enableWrap = true; 01383 break; 01384 case OTHER: 01385 if (other_texture) 01386 other_texture->bind (1); 01387 //enableWrap = true; 01388 //glBindTexture(GL_TEXTURE_2D, tnum); 01389 enableWrap = false; 01390 break; 01391 default: 01392 LINFO("Unknown Texture %i", tnum); 01393 break; 01394 } 01395 01396 if (enableWrap) 01397 { 01398 glEnable (GL_TEXTURE_GEN_S); 01399 glEnable (GL_TEXTURE_GEN_T); 01400 glTexGeni (GL_S,GL_TEXTURE_GEN_MODE,GL_OBJECT_LINEAR); 01401 glTexGeni (GL_T,GL_TEXTURE_GEN_MODE,GL_OBJECT_LINEAR); 01402 static GLfloat s_params[4] = {1.0f,1.0f,0.0f,1}; 01403 static GLfloat t_params[4] = {0.817f,-0.817f,0.817f,1}; 01404 glTexGenfv (GL_S,GL_OBJECT_PLANE,s_params); 01405 glTexGenfv (GL_T,GL_OBJECT_PLANE,t_params); 01406 } 01407 } 01408 else { 01409 glDisable (GL_TEXTURE_2D); 01410 } 01411 } 01412 else { 01413 glDisable (GL_TEXTURE_2D); 01414 } 01415 setColor (color[0],color[1],color[2],color[3]); 01416 01417 if (color[3] < 1) { 01418 glEnable (GL_BLEND); 01419 glBlendFunc (GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); 01420 } 01421 else { 01422 glDisable (GL_BLEND); 01423 } 01424 } 01425 01426 01427 void ViewPort::setShadowDrawingMode() 01428 { 01429 glDisable (GL_LIGHTING); 01430 if (use_textures) { 01431 glEnable (GL_TEXTURE_2D); 01432 ground_texture->bind (1); 01433 glColor3f (SHADOW_INTENSITY,SHADOW_INTENSITY,SHADOW_INTENSITY); 01434 glEnable (GL_TEXTURE_2D); 01435 glEnable (GL_TEXTURE_GEN_S); 01436 glEnable (GL_TEXTURE_GEN_T); 01437 glTexGeni (GL_S,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR); 01438 glTexGeni (GL_T,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR); 01439 static GLfloat s_params[4] = {(GLfloat)ground_scale,0,0,(GLfloat)ground_ofsx}; 01440 static GLfloat t_params[4] = {0,(GLfloat)ground_scale,0,(GLfloat)ground_ofsy}; 01441 glTexGenfv (GL_S,GL_EYE_PLANE,s_params); 01442 glTexGenfv (GL_T,GL_EYE_PLANE,t_params); 01443 } 01444 else { 01445 glDisable (GL_TEXTURE_2D); 01446 glColor3f (GROUND_R*SHADOW_INTENSITY,GROUND_G*SHADOW_INTENSITY, 01447 GROUND_B*SHADOW_INTENSITY); 01448 } 01449 glDepthRange (0,0.9999); 01450 } 01451 01452 01453 void ViewPort::dsSetViewpoint (double xyz[3], double hpr[3]) 01454 { 01455 if (xyz) { 01456 view_xyz[0] = xyz[0]; 01457 view_xyz[1] = xyz[1]; 01458 view_xyz[2] = xyz[2]; 01459 } 01460 if (hpr) { 01461 view_hpr[0] = hpr[0]; 01462 view_hpr[1] = hpr[1]; 01463 view_hpr[2] = hpr[2]; 01464 wrapCameraAngles(); 01465 } 01466 } 01467 01468 01469 void ViewPort::dsGetViewpoint (double xyz[3], double hpr[3]) 01470 { 01471 if (xyz) { 01472 xyz[0] = view_xyz[0]; 01473 xyz[1] = view_xyz[1]; 01474 xyz[2] = view_xyz[2]; 01475 } 01476 if (hpr) { 01477 hpr[0] = view_hpr[0]; 01478 hpr[1] = view_hpr[1]; 01479 hpr[2] = view_hpr[2]; 01480 } 01481 } 01482 01483 01484 void ViewPort::dsSetTexture (TEXTURES texture_number, Texture* texturePtr) 01485 { 01486 tnum = texture_number; 01487 if (texturePtr) 01488 other_texture = texturePtr; 01489 } 01490 01491 01492 void ViewPort::dsSetColor (double red, double green, double blue) 01493 { 01494 color[0] = red; 01495 color[1] = green; 01496 color[2] = blue; 01497 color[3] = 1; 01498 } 01499 01500 01501 void ViewPort::dsSetColorAlpha (double red, double green, double blue, 01502 double alpha) 01503 { 01504 color[0] = red; 01505 color[1] = green; 01506 color[2] = blue; 01507 color[3] = alpha; 01508 } 01509 01510 01511 void ViewPort::dsDrawBox (const double pos[3], const double R[12], 01512 const double sides[3]) 01513 { 01514 01515 setupDrawingMode(); 01516 glShadeModel (GL_FLAT); 01517 setTransform (pos,R); 01518 drawBox (sides); 01519 glPopMatrix(); 01520 01521 if (use_shadows) { 01522 setShadowDrawingMode(); 01523 setShadowTransform(); 01524 setTransform (pos,R); 01525 drawBox (sides); 01526 glPopMatrix(); 01527 glPopMatrix(); 01528 glDepthRange (0,1); 01529 } 01530 } 01531 01532 01533 void ViewPort::dsDrawSphere (const double pos[3], const double R[12], 01534 double radius) 01535 { 01536 setupDrawingMode(); 01537 glEnable (GL_NORMALIZE); 01538 glShadeModel (GL_SMOOTH); 01539 setTransform (pos,R); 01540 glScaled (radius,radius,radius); 01541 drawSphere(); 01542 glPopMatrix(); 01543 glDisable (GL_NORMALIZE); 01544 01545 // draw shadows 01546 if (use_shadows) { 01547 glDisable (GL_LIGHTING); 01548 if (use_textures) { 01549 ground_texture->bind (1); 01550 glEnable (GL_TEXTURE_2D); 01551 glDisable (GL_TEXTURE_GEN_S); 01552 glDisable (GL_TEXTURE_GEN_T); 01553 glColor3f (SHADOW_INTENSITY,SHADOW_INTENSITY,SHADOW_INTENSITY); 01554 } 01555 else { 01556 glDisable (GL_TEXTURE_2D); 01557 glColor3f (GROUND_R*SHADOW_INTENSITY,GROUND_G*SHADOW_INTENSITY, 01558 GROUND_B*SHADOW_INTENSITY); 01559 } 01560 glShadeModel (GL_FLAT); 01561 glDepthRange (0,0.9999); 01562 drawSphereShadow (pos[0],pos[1],pos[2],radius); 01563 glDepthRange (0,1); 01564 } 01565 } 01566 01567 void ViewPort::dsDrawTriangle (const double pos[3], const double R[12], 01568 const double *v0, const double *v1, 01569 const double *v2, int solid) 01570 { 01571 setupDrawingMode(); 01572 glShadeModel (GL_FLAT); 01573 setTransform (pos,R); 01574 drawTriangle (v0, v1, v2, solid); 01575 glPopMatrix(); 01576 } 01577 01578 01579 void ViewPort::dsDrawCylinder (const double pos[3], const double R[12], 01580 double length, double radius) 01581 { 01582 setupDrawingMode(); 01583 glShadeModel (GL_SMOOTH); 01584 setTransform (pos,R); 01585 drawCylinder (length,radius,0); 01586 glPopMatrix(); 01587 01588 if (use_shadows) { 01589 setShadowDrawingMode(); 01590 setShadowTransform(); 01591 setTransform (pos,R); 01592 drawCylinder (length,radius,0); 01593 glPopMatrix(); 01594 glPopMatrix(); 01595 glDepthRange (0,1); 01596 } 01597 } 01598 01599 01600 void ViewPort::dsDrawCappedCylinder (const double pos[3], const double R[12], 01601 double length, double radius) 01602 { 01603 setupDrawingMode(); 01604 glShadeModel (GL_SMOOTH); 01605 setTransform (pos,R); 01606 drawCappedCylinder (length,radius); 01607 glPopMatrix(); 01608 01609 if (use_shadows) { 01610 setShadowDrawingMode(); 01611 setShadowTransform(); 01612 setTransform (pos,R); 01613 drawCappedCylinder (length,radius); 01614 glPopMatrix(); 01615 glPopMatrix(); 01616 glDepthRange (0,1); 01617 } 01618 } 01619 01620 01621 void ViewPort::dsDrawLine (const double pos1[3], const double pos2[3]) 01622 { 01623 setupDrawingMode(); 01624 glColor3f (color[0],color[1],color[2]); 01625 glDisable (GL_LIGHTING); 01626 glLineWidth (2); 01627 glShadeModel (GL_FLAT); 01628 glBegin (GL_LINES); 01629 glVertex3f (pos1[0],pos1[1],pos1[2]); 01630 glVertex3f (pos2[0],pos2[1],pos2[2]); 01631 glVertex3f (pos1[0],pos1[1],pos1[2]); 01632 glVertex3f (pos2[0],pos2[1],pos2[2]); 01633 glEnd(); 01634 } 01635 01636 01637 void ViewPort::dsDrawBoxD (const double pos[3], const double R[12], 01638 const double sides[3]) 01639 { 01640 int i; 01641 double pos2[3],R2[12],fsides[3]; 01642 for (i=0; i<3; i++) pos2[i]=(double)pos[i]; 01643 for (i=0; i<12; i++) R2[i]=(double)R[i]; 01644 for (i=0; i<3; i++) fsides[i]=(double)sides[i]; 01645 dsDrawBox (pos2,R2,fsides); 01646 } 01647 01648 01649 void ViewPort::dsDrawSphereD (const double pos[3], const double R[12], double radius) 01650 { 01651 int i; 01652 double pos2[3],R2[12]; 01653 for (i=0; i<3; i++) pos2[i]=(double)pos[i]; 01654 for (i=0; i<12; i++) R2[i]=(double)R[i]; 01655 dsDrawSphere (pos2,R2,radius); 01656 } 01657 01658 01659 void ViewPort::dsDrawTriangleD (const double pos[3], const double R[12], 01660 const double *v0, const double *v1, 01661 const double *v2, int solid) 01662 { 01663 int i; 01664 double pos2[3],R2[12]; 01665 for (i=0; i<3; i++) pos2[i]=(double)pos[i]; 01666 for (i=0; i<12; i++) R2[i]=(double)R[i]; 01667 01668 setupDrawingMode(); 01669 glShadeModel (GL_FLAT); 01670 setTransform (pos2,R2); 01671 drawTriangleD (v0, v1, v2, solid); 01672 glPopMatrix(); 01673 } 01674 01675 01676 void ViewPort::dsDrawCylinderD (const double pos[3], const double R[12], 01677 double length, double radius) 01678 { 01679 int i; 01680 double pos2[3],R2[12]; 01681 for (i=0; i<3; i++) pos2[i]=(double)pos[i]; 01682 for (i=0; i<12; i++) R2[i]=(double)R[i]; 01683 dsDrawCylinder (pos2,R2,length,radius); 01684 } 01685 01686 01687 void ViewPort::dsDrawCappedCylinderD (const double pos[3], const double R[12], 01688 double length, double radius) 01689 { 01690 int i; 01691 double pos2[3],R2[12]; 01692 for (i=0; i<3; i++) pos2[i]=(double)pos[i]; 01693 for (i=0; i<12; i++) R2[i]=(double)R[i]; 01694 dsDrawCappedCylinder (pos2,R2,length,radius); 01695 } 01696 01697 01698 void ViewPort::dsDrawLineD (const double _pos1[3], const double _pos2[3]) 01699 { 01700 int i; 01701 double pos1[3],pos2[3]; 01702 for (i=0; i<3; i++) pos1[i]=(double)_pos1[i]; 01703 for (i=0; i<3; i++) pos2[i]=(double)_pos2[i]; 01704 dsDrawLine (pos1,pos2); 01705 } 01706 01707 01708 void ViewPort::dsSetSphereQuality (int n) 01709 { 01710 sphere_quality = n; 01711 } 01712 01713 01714 void ViewPort::dsSetCappedCylinderQuality (int n) 01715 { 01716 capped_cylinder_quality = n; 01717 } 01718 01719 //THis function was obtained from a sample online. 01720 // http://www.spacesimulator.net/tut4_3dsloader.html 01721 // TODO rewrite this function 01722 ViewPort::DSObject ViewPort::load3DSObject(const char*filename, const char* textureFile) 01723 { 01724 01725 DSObject p_object; 01726 int i; //Index variable 01727 01728 //load the texture 01729 if (textureFile) 01730 { 01731 p_object.texture = new Texture(textureFile); 01732 } else { 01733 p_object.texture = NULL; 01734 } 01735 01736 01737 01738 FILE *l_file; //File pointer 01739 01740 unsigned short l_chunk_id; //Chunk identifier 01741 unsigned int l_chunk_lenght; //Chunk lenght 01742 01743 unsigned char l_char; //Char variable 01744 unsigned short l_qty; //Number of elements in each chunk 01745 01746 unsigned short l_face_flags; //Flag that stores some face information 01747 01748 if ((l_file=fopen (filename, "rb"))== NULL) 01749 { 01750 LINFO("Can not open file %s", filename); 01751 return p_object; //Open the file 01752 } 01753 01754 //Get the file length 01755 struct stat buf; 01756 fstat(fileno(l_file), &buf); 01757 long filelength = buf.st_size; 01758 01759 while (ftell (l_file) < filelength) //Loop to scan the whole file 01760 { 01761 //getch(); //Insert this command for debug (to wait for keypress for each chuck reading) 01762 01763 if(fread (&l_chunk_id, 2, 1, l_file) != 1) LFATAL("fread failed"); //Read the chunk header 01764 //printf("ChunkID: %x\n",l_chunk_id); 01765 if(fread (&l_chunk_lenght, 4, 1, l_file) != 1) LFATAL("fread failed"); //Read the lenght of the chunk 01766 //printf("ChunkLenght: %x\n",l_chunk_lenght); 01767 01768 switch (l_chunk_id) 01769 { 01770 //----------------- MAIN3DS ----------------- 01771 // Description: Main chunk, contains all the other chunks 01772 // Chunk ID: 4d4d 01773 // Chunk Lenght: 0 + sub chunks 01774 //------------------------------------------- 01775 case 0x4d4d: 01776 break; 01777 01778 //----------------- EDIT3DS ----------------- 01779 // Description: 3D Editor chunk, objects layout info 01780 // Chunk ID: 3d3d (hex) 01781 // Chunk Lenght: 0 + sub chunks 01782 //------------------------------------------- 01783 case 0x3d3d: 01784 break; 01785 01786 //--------------- EDIT_OBJECT --------------- 01787 // Description: Object block, info for each object 01788 // Chunk ID: 4000 (hex) 01789 // Chunk Lenght: len(object name) + sub chunks 01790 //------------------------------------------- 01791 case 0x4000: 01792 i=0; 01793 do 01794 { 01795 if(fread (&l_char, 1, 1, l_file) != 1) LFATAL("fread faile"); 01796 p_object.name[i]=l_char; 01797 i++; 01798 }while(l_char != '\0' && i<20); 01799 break; 01800 01801 //--------------- OBJ_TRIMESH --------------- 01802 // Description: Triangular mesh, contains chunks for 3d mesh info 01803 // Chunk ID: 4100 (hex) 01804 // Chunk Lenght: 0 + sub chunks 01805 //------------------------------------------- 01806 case 0x4100: 01807 break; 01808 01809 //--------------- TRI_VERTEXL --------------- 01810 // Description: Vertices list 01811 // Chunk ID: 4110 (hex) 01812 // Chunk Lenght: 1 x unsigned short (number of vertices) 01813 // + 3 x float (vertex coordinates) x (number of vertices) 01814 // + sub chunks 01815 //------------------------------------------- 01816 case 0x4110: 01817 if(fread (&l_qty, sizeof (unsigned short), 1, l_file) != 1) LFATAL("fread failed"); 01818 p_object.vertices_qty = l_qty; 01819 //printf("Number of vertices: %d\n",l_qty); 01820 p_object.vertex.resize(l_qty); 01821 for (i=0; i<l_qty; i++) 01822 { 01823 if(fread (&p_object.vertex[i].x, sizeof(float), 1, l_file) != 1) LFATAL("fread failed"); 01824 //printf("Vertices list x: %f\n",p_object.vertex[i].x); 01825 if(fread (&p_object.vertex[i].y, sizeof(float), 1, l_file) != 1) LFATAL("fread failed"); 01826 //printf("Vertices list y: %f\n",p_object.vertex[i].y); 01827 if(fread (&p_object.vertex[i].z, sizeof(float), 1, l_file) != 1) LFATAL("fread failed"); 01828 //printf("Vertices list z: %f\n",p_object.vertex[i].z); 01829 } 01830 break; 01831 01832 //--------------- TRI_FACEL1 ---------------- 01833 // Description: Polygons (faces) list 01834 // Chunk ID: 4120 (hex) 01835 // Chunk Lenght: 1 x unsigned short (number of polygons) 01836 // + 3 x unsigned short (polygon points) x (number of polygons) 01837 // + sub chunks 01838 //------------------------------------------- 01839 case 0x4120: 01840 if(fread (&l_qty, sizeof (unsigned short), 1, l_file) != 1) LFATAL("fread failed"); 01841 p_object.polygons_qty = l_qty; 01842 p_object.polygon.resize(l_qty); 01843 printf("Number of polygons: %d\n",l_qty); 01844 for (i=0; i<l_qty; i++) 01845 { 01846 if(fread (&p_object.polygon[i].a, sizeof (unsigned short), 1, l_file) != 1) LFATAL("fread failed"); 01847 //printf("Polygon point a: %d\n",p_object.polygon[i].a); 01848 if(fread (&p_object.polygon[i].b, sizeof (unsigned short), 1, l_file) != 1) LFATAL("fread failed"); 01849 //printf("Polygon point b: %d\n",p_object.polygon[i].b); 01850 if(fread (&p_object.polygon[i].c, sizeof (unsigned short), 1, l_file) != 1) LFATAL("fread failed"); 01851 //printf("Polygon point c: %d\n",p_object.polygon[i].c); 01852 if(fread (&l_face_flags, sizeof (unsigned short), 1, l_file) != 1) LFATAL("fread failed"); 01853 //printf("Face flags: %x\n",l_face_flags); 01854 } 01855 break; 01856 01857 //------------- TRI_MAPPINGCOORS ------------ 01858 // Description: Vertices list 01859 // Chunk ID: 4140 (hex) 01860 // Chunk Lenght: 1 x unsigned short (number of mapping points) 01861 // + 2 x float (mapping coordinates) x (number of mapping points) 01862 // + sub chunks 01863 //------------------------------------------- 01864 case 0x4140: 01865 if(fread (&l_qty, sizeof (unsigned short), 1, l_file) != 1) LFATAL("fread failed"); 01866 p_object.mapcoord.resize(l_qty); 01867 for (i=0; i<l_qty; i++) 01868 { 01869 if(fread (&p_object.mapcoord[i].u, sizeof (float), 1, l_file) != 1) LFATAL("fread failed"); 01870 //printf("Mapping list u: %f\n",p_object.mapcoord[i].u); 01871 if(fread (&p_object.mapcoord[i].v, sizeof (float), 1, l_file) != 1) LFATAL("fread failed"); 01872 //printf("Mapping list v: %f\n",p_object.mapcoord[i].v); 01873 } 01874 break; 01875 01876 //----------- Skip unknow chunks ------------ 01877 //We need to skip all the chunks that currently we don't use 01878 //We use the chunk lenght information to set the file pointer 01879 //to the same level next chunk 01880 //------------------------------------------- 01881 default: 01882 fseek(l_file, l_chunk_lenght-6, SEEK_CUR); 01883 } 01884 } 01885 fclose (l_file); // Closes the file stream 01886 01887 return p_object; 01888 } 01889 01890 01891 int ViewPort::loadBitmap(const char*filename) 01892 { 01893 FILE * file; 01894 char temp; 01895 long i; 01896 int num_texture = 10; 01897 01898 BITMAPINFOHEADER infoheader; 01899 01900 if( (file = fopen(filename, "rb"))==NULL) return (-1); // Open the file for reading 01901 01902 fseek(file, 18, SEEK_CUR); /* start reading width & height */ 01903 if(fread(&infoheader.biWidth, sizeof(int), 1, file) != 1) LFATAL("fread failed"); 01904 01905 if(fread(&infoheader.biHeight, sizeof(int), 1, file) != 1) LFATAL("fread failed"); 01906 01907 if(fread(&infoheader.biPlanes, sizeof(short int), 1, file) != 1) LFATAL("fread failed"); 01908 if (infoheader.biPlanes != 1) { 01909 //printf("Planes from %s is not 1: %u\n", filename, infoheader.biPlanes); 01910 return 0; 01911 } 01912 01913 // read the bpp 01914 if(fread(&infoheader.biBitCount, sizeof(unsigned short int), 1, file) != 1) LFATAL("fread failed"); 01915 if (infoheader.biBitCount != 24) { 01916 //printf("Bpp from %s is not 24: %d\n", filename, infoheader.biBitCount); 01917 return 0; 01918 } 01919 01920 fseek(file, 24, SEEK_CUR); 01921 01922 // read the data. 01923 infoheader.data = (char *) malloc(infoheader.biWidth * infoheader.biHeight * 3); 01924 if (infoheader.data == NULL) { 01925 //printf("Error allocating memory for color-corrected image data\n"); 01926 return 0; 01927 } 01928 01929 if ((i = fread(infoheader.data, infoheader.biWidth * infoheader.biHeight * 3, 1, file)) != 1) { 01930 //printf("Error reading image data from %s.\n", filename); 01931 return 0; 01932 } 01933 01934 for (i=0; i<(infoheader.biWidth * infoheader.biHeight * 3); i+=3) { // reverse all of the colors. (bgr -> rgb) 01935 temp = infoheader.data[i]; 01936 infoheader.data[i] = infoheader.data[i+2]; 01937 infoheader.data[i+2] = temp; 01938 } 01939 01940 01941 fclose(file); // Closes the file stream 01942 01943 01944 glBindTexture(GL_TEXTURE_2D, num_texture); // Bind the ID texture specified by the 2nd parameter 01945 01946 // The next commands sets the texture parameters 01947 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // If the u,v coordinates overflow the range 0,1 the image is repeated 01948 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 01949 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // The magnification function ("linear" produces better results) 01950 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); //The minifying function 01951 01952 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); // We don't combine the color with the original surface color, use only the texture map. 01953 01954 // Finally we define the 2d texture 01955 glTexImage2D(GL_TEXTURE_2D, 0, 3, infoheader.biWidth, infoheader.biHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, infoheader.data); 01956 01957 // And create 2d mipmaps for the minifying function 01958 #ifdef INVT_HAVE_LIBGLUT 01959 gluBuild2DMipmaps(GL_TEXTURE_2D, 3, infoheader.biWidth, infoheader.biHeight, GL_RGB, GL_UNSIGNED_BYTE, infoheader.data); 01960 #endif 01961 01962 free(infoheader.data); // Free the memory we used to load the texture 01963 01964 return (num_texture); // Returns the current texture OpenGL ID 01965 } 01966 01967 01968 void ViewPort::dsDraw3DSObject(const double pos[3], const double R[12], DSObject& object) 01969 { 01970 if (object.texture != NULL) 01971 dsSetTexture (ViewPort::OTHER, object.texture); 01972 01973 setupDrawingMode(); 01974 glEnable (GL_NORMALIZE); 01975 glShadeModel (GL_SMOOTH); 01976 01977 setTransform (pos,R); 01978 glScaled (object.scale,object.scale,object.scale); 01979 draw3dsObject(object); 01980 glPopMatrix(); 01981 glDisable (GL_NORMALIZE); 01982 01983 } 01984 01985 void ViewPort::draw3dsObject(DSObject& object) 01986 { 01987 glBegin(GL_TRIANGLES); // glBegin and glEnd delimit the vertices that define a primitive (in our case triangles) 01988 //glBegin (GL_TRIANGLE_FAN); 01989 //glBegin (GL_TRIANGLE_STRIP); 01990 for (int l_index=0;l_index<object.polygons_qty;l_index++) 01991 { 01992 //----------------- FIRST VERTEX ----------------- 01993 // Texture coordinates of the first vertex 01994 glTexCoord2f( object.mapcoord[ object.polygon[l_index].a ].u, 01995 object.mapcoord[ object.polygon[l_index].a ].v); 01996 // Coordinates of the first vertex 01997 glVertex3f( object.vertex[ object.polygon[l_index].a ].x, 01998 object.vertex[ object.polygon[l_index].a ].y, 01999 object.vertex[ object.polygon[l_index].a ].z); //Vertex definition 02000 02001 //----------------- SECOND VERTEX ----------------- 02002 // Texture coordinates of the second vertex 02003 glTexCoord2f( object.mapcoord[ object.polygon[l_index].b ].u, 02004 object.mapcoord[ object.polygon[l_index].b ].v); 02005 // Coordinates of the second vertex 02006 glVertex3f( object.vertex[ object.polygon[l_index].b ].x, 02007 object.vertex[ object.polygon[l_index].b ].y, 02008 object.vertex[ object.polygon[l_index].b ].z); 02009 02010 //----------------- THIRD VERTEX ----------------- 02011 // Texture coordinates of the third vertex 02012 glTexCoord2f( object.mapcoord[ object.polygon[l_index].c ].u, 02013 object.mapcoord[ object.polygon[l_index].c ].v); 02014 // Coordinates of the Third vertex 02015 glVertex3f( object.vertex[ object.polygon[l_index].c ].x, 02016 object.vertex[ object.polygon[l_index].c ].y, 02017 object.vertex[ object.polygon[l_index].c ].z); 02018 } 02019 glEnd(); 02020 glFlush(); 02021 02022 }