Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on Aug 3rd, 2012  |  syntax: None  |  size: 16.20 KB  |  hits: 9  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. // Second Partial Exam
  2. // Fernando Dingler - A01127501
  3. // June 15, 2011
  4.  
  5. #include <cmath>
  6. #include <iostream>
  7. #include <stdio.h>
  8. #include "GlutWin.h"
  9. #include "Camera.h"
  10. #include "Vector3.h"
  11. #include <fstream>
  12. #include <assert.h>
  13. #include <windows.h>
  14. #include <math.h>
  15. #include <GL/gl.h>
  16. #include <GL/glut.h>
  17. #include <string.h>
  18.  
  19. using namespace std;
  20.  
  21. typedef unsigned short ushort;
  22. typedef unsigned long ulong;
  23. typedef unsigned char uchar;
  24.  
  25. fstream inf; // global in this file for convenience
  26.  
  27. // Texture variables
  28. static GLuint textures[1];
  29. bool applyTexture = false;
  30.  
  31. GlutWin         *win;
  32. Camera          *camera;
  33.  
  34. // mouse cursor position
  35. float           mouse_x,
  36.                         mouse_y;
  37.  
  38. bool            mouse_updated = false;
  39.  
  40. // describe the section of the curve, and how often to sample
  41. float           t_0 = 0.0;
  42. float           t_end = 0.1;
  43. float           t_incr = 0.5;
  44.  
  45. // describes shape of polygon extruded along curve
  46. // and which is a common n-gon
  47. int                     n_gon = 4;
  48.  
  49. // Light Components
  50. static float globAmb = 0.3;
  51. static float globDif = 0.4;
  52. static float globSpe = 0.7;
  53.  
  54. // Materials
  55. int material_index = 1;
  56. // Material Components
  57. static float globMatAmb = 0.5;
  58. static float globMatDif = 0.5;
  59. static float globMatSpe = 0.5;
  60. static float globExp = 4.0;
  61.  
  62. float max_radius;
  63. float min_radius;
  64.  
  65. float aux = 1.0;
  66.  
  67. // For objects with fixed material properties
  68. // Four arrays, each containing the corresponding material
  69. // properties for:
  70. // row 0: Black plastic
  71. // row 1: Brass
  72. // row 2: Bronze
  73. // row 3: Chrome
  74. // row 4: Copper
  75. // row 5: Gold
  76. // row 6: Pewter
  77. // row 7: Silver
  78. // row 8: Polished Silver
  79. static float matAmb[9][3] = {{0.0, 0.0, 0.0},
  80.                                                         {0.329412, 0.223529, 0.027451},
  81.                                                         {0.2125, 0.1275, 0.054},
  82.                                                         {0.25, 0.25, 0.25},
  83.                                                         {0.19125, 0.0735, 0.0225},
  84.                                                         {0.24725, 0.1995, 0.0745},
  85.                                                         {0.10588, 0.058824, 0.113725},
  86.                                                         {0.19225, 0.19225, 0.19225},
  87.                                                         {0.23125, 0.23125, 0.23125} };
  88. static float matDif[9][3] = {{0.01, 0.01, 0.01},
  89.                                                         {0.780392, 0.568627, 0.113725},
  90.                                                         {0.714, 0.4284, 0.18144},
  91.                                                         {0.4, 0.4, 0.4},
  92.                                                         {0.7038, 0.27048, 0.0828},
  93.                                                         {0.75164, 0.60648, 0.22648},
  94.                                                         {0.427451, 0.470588, 0.541176},
  95.                                                         {0.50754, 0.50754, 0.50754},
  96.                                                         {0.2775, 0.2775, 0.2775} };
  97. static float matSpe[9][3] = {{0.50, 0.50, 0.50},
  98.                                                         {0.992157, 0.941176, 0.807843},
  99.                                                         {0.393548, 0.271906, 0.166721},
  100.                                                         {0.774597, 0.774597, 0.774597},
  101.                                                         {0.256777, 0.137622, 0.086014},
  102.                                                         {0.628281, 0.555802, 0.366065},
  103.                                                         {0.3333, 0.3333, 0.521569},
  104.                                                         {0.508273, 0.508273, 0.508273},
  105.                                                         {0.773911, 0.773911, 0.773911} };
  106. static float matExp[9] = {32.0, 27.8974, 25.6, 76.8, 12.8, 51.2, 9.84615, 51.2, 89.6};
  107.  
  108.  
  109. // Class for textures
  110. // A few class definitions
  111. class mRGB {
  112. public:
  113.         unsigned char r,g,b;
  114.  
  115.         mRGB(){r = g = b = 0;}
  116.         mRGB(mRGB& p){r = p.r; g = p.g; b = p.b;}
  117.         mRGB(uchar rr, uchar gg, uchar bb){r = rr; g = gg; b = bb;}
  118.         void set(uchar rr, uchar gg, uchar bb){r = rr; g = gg; b = bb;}
  119. };
  120.  
  121. ushort getShort() //helper function
  122. { //BMP format uses little-endian integer types
  123.   // get a 2-byte integer stored in little-endian form
  124.         char ic;
  125.         ushort ip;
  126.         inf.get(ic); ip = ic;  //first byte is little one
  127.         inf.get(ic);  ip |= ((ushort)ic << 8); // or in high order byte
  128.         return ip;
  129. }
  130.  
  131. //<<<<<<<<<<<<<<<<<<<< getLong >>>>>>>>>>>>>>>>>>>
  132. ulong getLong() //helper function
  133. {  //BMP format uses little-endian integer types
  134.         // get a 4-byte integer stored in little-endian form
  135.         ulong ip = 0;
  136.         char ic = 0;
  137.         unsigned char uc = ic;
  138.         inf.get(ic); uc = ic; ip = uc;
  139.         inf.get(ic); uc = ic; ip |=((ulong)uc << 8);
  140.         inf.get(ic); uc = ic; ip |=((ulong)uc << 16);
  141.         inf.get(ic); uc = ic; ip |=((ulong)uc << 24);
  142.         return ip;
  143. }
  144.  
  145. class RGBpixmap {
  146. public:
  147.         int nRows, nCols;
  148.         mRGB *pixel;
  149.         float gr, gg, gb;
  150.  
  151.         int readBMPFile(char *fname);
  152.         void SetTexColor(float rin, float gin, float bin);
  153.         void SetTexture(GLuint textureName);
  154. };
  155.  
  156. void RGBpixmap::SetTexColor(float rin, float gin, float bin)
  157. {
  158.         // Set multipliers to set the color of the parameterized textures
  159.         gg = gin;
  160.         gr = rin;
  161.         gb = bin;
  162. }
  163.  
  164. int RGBpixmap:: readBMPFile(char *fname)
  165. {  
  166.         // Read into memory an mRGB image from an uncompressed BMP file.
  167.         // return 0 on failure, 1 on success
  168.         inf.open(fname, ios::in|ios::binary); //read binary char's
  169.         if(!inf){ cout << " can't open file: " << fname << endl; return 0;}
  170.         int k, row, col, numPadBytes, nBytesInRow;
  171.         // read the file header information
  172.         char ch1, ch2;
  173.         inf.get(ch1); inf.get(ch2); //type: always 'BM'
  174.         ulong fileSize =      getLong();
  175.         ushort reserved1 =    getShort();    // always 0
  176.         ushort reserved2=       getShort();     // always 0
  177.         ulong offBits =         getLong(); // offset to image - unreliable
  178.         ulong headerSize =     getLong();     // always 40
  179.         ulong numCols =         getLong(); // number of columns in image
  180.         ulong numRows =                 getLong(); // number of rows in image
  181.         ushort planes=          getShort();      // always 1
  182.         ushort bitsPerPixel=   getShort();    //8 or 24; allow 24 here
  183.         ulong compression =    getLong();      // must be 0 for uncompressed
  184.         ulong imageSize =       getLong();       // total bytes in imag
  185.         ulong xPels =           getLong();    // always 0
  186.         ulong yPels =           getLong();    // always 0
  187.         ulong numLUTentries = getLong();    // 256 for 8 bit, otherwise 0
  188.         ulong impColors =       getLong();       // always 0
  189.        
  190.         if(bitsPerPixel != 24)
  191.         { // error - must be a 24 bit uncompressed image
  192.                 cout << "not a 24 bit/pixelimage, or is compressed!\n";
  193.                 inf.close(); return 0;
  194.         }
  195.  
  196.         //add bytes at end of each row so total # is a multiple of 4
  197.         // round up 3*numCols to next mult. of 4
  198.         nBytesInRow = ((3 * numCols + 3)/4) * 4;
  199.         numPadBytes = nBytesInRow - 3 * numCols; // need this many
  200.         nRows = numRows; // set class's data members
  201.         nCols = numCols;
  202.     pixel = new mRGB[nRows * nCols]; //make space for array
  203.  
  204.         if(!pixel) return 0; // out of memory!
  205.         long count = 0;
  206.         char dum;
  207.         for(row = 0; row < nRows; row++) // read pixel values
  208.         {
  209.                 for(col = 0; col < nCols; col++)
  210.                 {
  211.                         char r,g,b;
  212.                         inf.get(b); inf.get(g); inf.get(r); //read bytes
  213.                         pixel[count].r = r; //place them in colors
  214.                         pixel[count].g = g;
  215.                         pixel[count++].b = b;
  216.                 }
  217.                 for(k = 0; k < numPadBytes ; k++) //skip pad bytes at row's end
  218.                         inf >> dum;
  219.         }
  220.         inf.close(); return 1; // success
  221. }
  222.  
  223. void RGBpixmap::SetTexture(GLuint textureName)
  224. {
  225.         // Set texture parameters to initial values
  226.         // Set wrapping and interpolation
  227.         glBindTexture(GL_TEXTURE_2D, textureName);
  228.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  229.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  230.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  231.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  232.         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, nCols, nRows, 0, GL_RGB, GL_UNSIGNED_BYTE, pixel);
  233. }
  234. RGBpixmap myTexs[1];
  235.  
  236.  
  237. // Function that describes the curve
  238. // Parametric representation
  239. Vector3 C( float t ) {
  240.         return( Vector3( 2.0 * sin(t), 2.0 * cos(t), 0.5 * t ) );
  241. }
  242.  
  243. // Generate the matrix transformation that corresponds to the
  244. // Frenet frame for the current t.
  245. // The output is an array (mat[]) with 16 elements, in
  246. // column major order. See hint for output below
  247. void create_frenet_frame( double t, float mat[] ) {
  248.  
  249.         Vector3 N, B, T, C2, C1, C0;
  250.  
  251.         // Numerically calculate deriv and 2nd deriv
  252.         // Approximation for this function is too unstable
  253.         C0 = Vector3( 2.0*sin(t), 2.0*cos(t), t * 0.5); // evaluation of parametric function
  254.         // Can also do
  255.         // C0 = C(t);
  256.         // CHANGE THE PARAMETRIC FUNCTION
  257.         // FOR EXAMPLE, PG 295 HILL & KELLEY
  258.  
  259.         C1 = Vector3( 2.0*cos(t), 2.0*(-sin(t)),0.5);// TO DO - First derivative: Obtain analytically (by hand)
  260.         C2 = Vector3( 2.0*(-sin(t)), 2.0*(-cos(t)),0.0);// TO DO - Second derivative: Obtain analytically (by hand)
  261.  
  262.         // calculate vectors that define the frenet frame
  263.         // at this point on the curve
  264.         T = C1;
  265.         T.normalize();
  266.  
  267.         B = C2;
  268.         B.normalize();
  269.  
  270.         N = B.cross( T );
  271.  
  272.         // create affine transform matrix
  273.         // assume mat has 16 elems
  274.         mat[ 0] = N.x; mat[ 4] = B.x; mat[ 8] = T.x; mat[12] = C0.x;
  275.         mat[ 1] = N.y; mat[ 5] = B.y; mat[ 9] = T.y; mat[13] = C0.y;
  276.         mat[ 2] = N.z; mat[ 6] = B.z; mat[10] = T.z; mat[14] = C0.z;
  277.         mat[ 3] = 0.0; mat[ 7] = 0.0; mat[11] = 0.0; mat[15] = 1.00;
  278.  
  279. }
  280.  
  281. void updateLights( void )
  282. {
  283.         // Update LIGHT properties
  284.         GLfloat myAmb[] = {globAmb, globAmb, globAmb, 1.0};
  285.         GLfloat myDif[] = {globDif, globDif, globDif, 1.0};
  286.         GLfloat mySpe[] = {globSpe, globSpe, globSpe, 1.0};
  287.         glLightfv(GL_LIGHT0, GL_AMBIENT, myAmb);
  288.         glLightfv(GL_LIGHT0, GL_DIFFUSE, myDif);
  289.         glLightfv(GL_LIGHT0, GL_SPECULAR, mySpe);
  290. }
  291.  
  292. bool initdemo() {
  293.  
  294.         // initialize GLUT class
  295.         win = new GlutWin( 600, 800, 100, 100, GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH, "Extrusion Demo" );
  296.  
  297.         camera = new Camera();
  298.         camera->set( 5, 5, 5, 0, 5, 5, 0, 1, 0 );
  299.  
  300.         glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
  301.         glHint( GL_POLYGON_SMOOTH_HINT, GL_NICEST );
  302.  
  303.         // enable depth testing
  304.         glEnable( GL_DEPTH_TEST );
  305.  
  306.         // enable textures
  307.         glEnable(GL_TEXTURE_2D);
  308.  
  309.         // set up lighting in ogl
  310.         glEnable( GL_LIGHTING );
  311.  
  312.         float light_amb[] = { 0.5, 0.5, 0.5, 1.0 };
  313.         float light_dif[] = { 0.25, 0.25, 0.25, 1.0 };
  314.         float light_pos[] = { 0.0, 0.0, 0.0, 1.0 };
  315.  
  316.         float material_amb[] = { 1.0, 1.0, 1.0, 1.0 };
  317.         float material_dif[] = { 1.0, 1.0, 1.0, 1.0 };
  318.  
  319.         glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT, material_amb );
  320.         glMaterialfv( GL_FRONT_AND_BACK, GL_DIFFUSE, material_dif );
  321.  
  322.         glLightfv( GL_LIGHT0, GL_AMBIENT, light_amb );
  323.         glLightfv( GL_LIGHT0, GL_DIFFUSE, light_dif );
  324.         glLightfv( GL_LIGHT0, GL_POSITION, light_pos );
  325.  
  326.         glEnable( GL_LIGHT0 );
  327.  
  328.         // Generate textures
  329.         glGenTextures(1, textures);
  330.         myTexs[0].SetTexColor(1.0, 0.2, 0.2);
  331.         myTexs[0].readBMPFile("yugioh.bmp");
  332.         myTexs[0].SetTexture(textures[0]);
  333.  
  334.         return( true );
  335.  
  336. }
  337.  
  338. Vector3 matrixmult( float mat[], Vector3 v, float t ) {
  339.   return( Vector3( mat[ 0]*v.x*t + mat[ 4]*v.y*t + mat[ 8] *v.z*t + mat[12],
  340.            mat[ 1]*v.x*t + mat[ 5]*v.y*t + mat[ 9] *v.z*t + mat[13],
  341.            mat[ 2]*v.x*t + mat[ 6]*v.y*t + mat[10] *v.z*t + mat[14] ) );
  342. }
  343.  
  344. void render() {
  345.         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the screen
  346.         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
  347.  
  348.         // Update lights so the user can see the changes in the parameters modified by the keyboard
  349.         updateLights();
  350.  
  351.         glMaterialfv(GL_FRONT, GL_AMBIENT, matAmb[material_index]);
  352.         glMaterialfv(GL_FRONT, GL_DIFFUSE, matDif[material_index]);
  353.         glMaterialfv(GL_FRONT, GL_SPECULAR, matSpe[material_index]);
  354.         glMaterialf(GL_FRONT, GL_SHININESS, matExp[material_index]);
  355.  
  356.         float mat1[16], mat2[16];
  357.  
  358.         glPointSize( 3.0 );
  359.  
  360.         // Auxiliar variables to subdive the texture image.
  361.         float b = 0.0;
  362.         float d = 0.0;
  363.         float c = 1.0/aux;
  364.  
  365.         // Define max and minimun size of the radius
  366.         max_radius = 1.5;
  367.         min_radius = 0.5;
  368.  
  369.         for( float t = t_0; t <= t_end; t += t_incr ) {
  370.  
  371.                 c = 1.0/aux;
  372.  
  373.                 // calculate frenet frames for this waist and the next one
  374.                 create_frenet_frame( t, mat1 );
  375.                 create_frenet_frame( t+t_incr, mat2 );
  376.  
  377.                 glMatrixMode( GL_MODELVIEW );
  378.                 glPushMatrix();
  379.  
  380.                 // calc vertices for this "waist" -
  381.                 // the points located at each Frenet frame
  382.                 // These points will be the vertices used to create the polygons
  383.                 Vector3 waist1[25], waist2[25], norm[25];
  384.  
  385.                 // create polygon - approximation of a circle
  386.                 double anginc = ( 2.0 * 3.14159 / double( n_gon ) );
  387.                 double ang = 0.0;
  388.  
  389.                 for( int k = 0; k < n_gon; k++ ) {
  390.                
  391.                         // This function approximates a circle (r = 0.4) using a N-gon
  392.                         // Therefore, each polygon vertex is defined in this manner
  393.                         // The larger n_gon, the smoother the circle approximation
  394.                         Vector3 pos = Vector3( 0.4 * cos( ang ), 0.4 * sin( ang ), 0.0 );
  395.  
  396.                         ang += anginc;
  397.  
  398.                         // Add different scaling to a given waist
  399.                         waist1[k] = matrixmult( mat1, pos, min_radius );
  400.                         waist2[k] = matrixmult( mat2, pos, max_radius );
  401.                 }
  402.  
  403.                 // calc normal vectors per surface
  404.                 // based on Newell Method
  405.                 for( int j = 0; j < n_gon; j++ ) {
  406.  
  407.                         Vector3 t1 = ( waist1[j] - waist2[j] );
  408.                         Vector3 t2 = ( waist1[j] + waist2[j] );
  409.  
  410.                         norm[j].x = t1.y * t2.z;
  411.                         norm[j].y = t1.z * t2.x;
  412.                         norm[j].z = t1.x * t2.y;
  413.  
  414.                         t1 = ( waist2[j] - waist2[(j+1)%n_gon] );
  415.                         t2 = ( waist2[j] + waist2[(j+1)%n_gon] );
  416.  
  417.                         norm[j].x += t1.y * t2.z;
  418.                         norm[j].y += t1.z * t2.x;
  419.                         norm[j].z += t1.x * t2.y;
  420.  
  421.                         t1 = ( waist2[(j+1)%n_gon] - waist1[(j+1)%n_gon] );
  422.                         t2 = ( waist2[(j+1)%n_gon] + waist1[(j+1)%n_gon] );
  423.  
  424.                         norm[j].x += t1.y * t2.z;
  425.                         norm[j].y += t1.z * t2.x;
  426.                         norm[j].z += t1.x * t2.y;
  427.  
  428.                         norm[j].normalize();
  429.                 }
  430.  
  431.                 // Calculate range for applying texture based on n_gon
  432.                 float af = 1.0/n_gon;
  433.  
  434.                 // render face
  435.                 glBegin( GL_QUADS );
  436.  
  437.                 // Create a quad for each edge of two adyacent n-gons
  438.                 // DON'T FORGET TO LINK THE FIRST WITH THE LAST ONE (index = 0 and index = n_gon - 1)
  439.                 for( int a = 0; a < n_gon; a++ ){
  440.  
  441.                         // Add different color to faces
  442.                         glNormal3f( norm[a].x,norm[a].y,norm[a].z);
  443.  
  444.                         // Apply texture
  445.                         glBindTexture(GL_TEXTURE_2D, textures[0]);
  446.  
  447.                         // Vertices from "first" n-gon index, for both waists. Hint: a
  448.                         glTexCoord2f(0.0 + d, 0.0 + b);  glVertex3f(waist1[a].x,waist1[a].y,waist1[a].z);
  449.                         glTexCoord2f(0.0 + d, af + b);  glVertex3f(waist2[a].x,waist2[a].y,waist2[a].z);
  450.  
  451.                         // Same vertices from "second" n-gon index, for both waists. Hint: a+1
  452.                         glTexCoord2f(c + d, af + b);            glVertex3f( waist2[(a+1)%n_gon].x,waist2[(a+1)%n_gon].y,waist2[(a+1)%n_gon].z);
  453.                         glTexCoord2f(c + d, 0 + b);             glVertex3f( waist1[(a+1)%n_gon].x,waist1[(a+1)%n_gon].y,waist1[(a+1)%n_gon].z);
  454.  
  455.                         // increment the auxiliar variable to subdivide the image
  456.                         b += af;
  457.  
  458.                         if(b >= 1.0){
  459.                                 b=0.0;
  460.                         }
  461.                 }
  462.                 glEnd();
  463.                 glPopMatrix();
  464.  
  465.                 // Reset the radius factors to create the effect of a crushed shape
  466.                 min_radius = (max_radius <= 0.5)? 0.5 : 1.5;
  467.                 max_radius = (max_radius <= 0.5)? 1.5 : 0.5;
  468.  
  469.                 d += c;
  470.         }
  471.         // refresh image
  472.         glutSwapBuffers();
  473.         glutPostRedisplay();
  474. }
  475.  
  476.  
  477. void kb_input( unsigned char key, int x, int y ) {
  478.         switch( key ) {
  479.                 // light controls
  480.                 case 'j': globAmb = min(1.0,globAmb+0.1); break;
  481.                 case 'k': globDif = min(1.0,globDif+0.1); break;
  482.                 case 'l': globSpe = min(1.0,globSpe+0.1); break;
  483.                 case 'J': globAmb = max(0.0,globAmb-0.1); break;
  484.                 case 'K': globDif = max(0.0,globDif-0.1); break;
  485.                 case 'L': globSpe = max(0.0,globSpe-0.1); break;
  486.                 // camera and navigation controls
  487.                 case 'a': camera->slide( -1.0, 0.0, 0.0 ); break;
  488.                 case 'd': camera->slide( 1.0, 0.0, 0.0 ); break;
  489.                 case 's': camera->slide( 0.0, 0.0, 1.0 ); break;
  490.                 case 'w': camera->slide( 0.0, 0.0, -1.0 ); break;
  491.                 case '[': if( t_incr >= 0.01 ) t_incr /= 2.0; break;
  492.                 case ']': if( t_incr < 0.5 )     t_incr *= 2.0; break;
  493.                 case '+': t_end  += 1.0; aux += 2.0; break;
  494.                 case '-': t_end  -= 1.0; aux -= 2.0; break;
  495.                 case '/': if( n_gon < 20) n_gon++; break;
  496.                 case '*': if( n_gon > 3 ) n_gon--; break;
  497.                 // material controls
  498.                 case '1': material_index = 1; glDisable(GL_TEXTURE_2D); break;
  499.                 case '2': material_index = 2; glDisable(GL_TEXTURE_2D); break;
  500.                 case '3': material_index = 3; glDisable(GL_TEXTURE_2D); break;
  501.                 case '4': material_index = 4; glDisable(GL_TEXTURE_2D); break;
  502.                 case '5': material_index = 5; glDisable(GL_TEXTURE_2D); break;
  503.                 case '6': material_index = 6; glDisable(GL_TEXTURE_2D); break;
  504.                 case '7': material_index = 7; glDisable(GL_TEXTURE_2D); break;
  505.                 case '8': material_index = 8; glDisable(GL_TEXTURE_2D); break;
  506.                 case '9': material_index = 0; glDisable(GL_TEXTURE_2D); break;
  507.                 // enable texture
  508.                 case '0': glEnable(GL_TEXTURE_2D); break;
  509.                 // exit keys
  510.                 case 'q':
  511.                 case 'Q':
  512.                 case 27:
  513.                         exit( 0 );
  514.                 default:        break;
  515.         }
  516.         glutPostRedisplay();
  517. }
  518.  
  519. void mouse_motion( int x, int y ) {
  520.  
  521.         float dx, dy;
  522.  
  523.         if( ! mouse_updated) {
  524.                 mouse_x = x;
  525.                 mouse_y = y;
  526.                 mouse_updated = true;
  527.         }else{
  528.  
  529.                 // calc delta
  530.                 dx = x - mouse_x;
  531.                 dy = y - mouse_y;
  532.  
  533.                 mouse_x = x;
  534.                 mouse_y = y;
  535.  
  536.                 // determine rotation amount
  537.                 camera->pitch( dy / 5.0 );
  538.                 camera->yaw( dx );
  539.         }
  540. }
  541.  
  542. int main() {
  543.  
  544.         if( initdemo() ) {
  545.                 glutDisplayFunc( render );
  546.                 glutKeyboardFunc( kb_input );
  547.                 glutPassiveMotionFunc( mouse_motion );
  548.  
  549.                 glutMainLoop();
  550.  
  551.                 delete win;
  552.                 delete camera;
  553.         }
  554. }