hv_ARtk_demo.cpp
上传用户:lijia5631
上传日期:2008-11-10
资源大小:1214k
文件大小:17k
源码类别:

视频捕捉/采集

开发平台:

MultiPlatform

  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <GL/glut.h>
  4. #include <vector>
  5. #include <float.h>
  6. #include "hv_ARtk_demo.h"
  7. #include <math.h>
  8. bool render_select( int x, int y, int* selected,  
  9.     d3* selected_win);
  10. //void unproject(double winx, double winy, double winz,
  11. //        double* objx, double* objy, double* objz);
  12. void drawBullseye( double radius, int rings );
  13. /*
  14.  * store OpenGL state matrices
  15.  */
  16. extern GLint viewport[ 4 ];
  17. // for unproject
  18. GLdouble modelview[ 16 ];
  19. GLdouble projection[ 16 ];
  20. GLdouble selected_view[16];
  21. /*
  22.  * UI state
  23.  */
  24. bool dragging = false;
  25. bool rotating = false;
  26. bool hovering = false;
  27. bool show_ptr = false;
  28.  
  29. /*
  30.  * information about selected point - id of object,
  31.  * window coordinates and coordinates relative to the multi-marker
  32.  * (anchor)
  33.  */
  34. int selected = -1;
  35. d3 selected_win;
  36. d3 selected_rel;
  37. d3 selected_world; // relative to modelview
  38. double anchor[16];
  39. bool anchor_visible = false;
  40. std::vector<bool> floater_visible;
  41. typedef std::vector<double> dvec;
  42. typedef std::vector<dvec> dmat;
  43. dmat floaterpositions;
  44. const unsigned int IDX_ANCHORED_LIGHT = 1;
  45. const unsigned int IDX_FLOATER_LIGHT = 3;
  46. //----------------------------------------------------------------------
  47. /*
  48.  * information about a set of objects
  49.  */
  50. std::vector< d3 > positions;
  51. std::vector< d3 > rotations;
  52. std::vector< d3 > colors;
  53. // the first num_anchored objects are positioned relative to
  54. // the "anchor" (multiMarker), the others on one floater each
  55. unsigned int num_anchored = 0; 
  56. d3 ptr_col;
  57. int ptr_x, ptr_y;
  58. int hv_pointer_dist = 120;
  59. /*
  60.  * assign positions and colors of objects and lights
  61.  */
  62. void initObjs ()
  63. {
  64.   positions.clear(); 
  65.   rotations.clear();
  66.   colors.clear();
  67.   // anchored object
  68.   d3 p;
  69.   p.x = 50; p.y = -50; p.z = 30;
  70.   positions.push_back( p );
  71.   // object representing the anchored light
  72.   p.x = 0; p.y = 200; p.z = 80;
  73.   positions.push_back( p );
  74.   num_anchored = positions.size();
  75.   // floating object
  76.   p.x = 70; p.y = -80; p.z = 30;
  77.   positions.push_back( p );
  78.   // object representing the floating light
  79.   p.x = 0; p.y = 0; p.z = 40;
  80.   positions.push_back( p );
  81.   positions.push_back( p );
  82.   positions.push_back( p );
  83.   positions.push_back( p );
  84.   positions.push_back( p );
  85.   positions.push_back( p );
  86.   positions.push_back( p );
  87.   // we're being lazy - these are too many vector entries for
  88.   // floaters, but that way we don't have to translate indices
  89.   floaterpositions.reserve(positions.size());
  90.   floater_visible.reserve(positions.size());
  91.   //  srand((unsigned)time(NULL));
  92.   for( unsigned int i = 0 ; i < positions.size() ; ++i )
  93.   {
  94.     d3 c;
  95.     c.x = (float)rand() / ( float )RAND_MAX;
  96.     c.y = (float)rand() / ( float )RAND_MAX;
  97.     c.z = (float)rand() / ( float )RAND_MAX;
  98.     colors.push_back( c );
  99.     d3 r;
  100.     r.x = r.y = r.z = 0;
  101.     rotations.push_back( r );
  102.     dvec d16( 16 );
  103.     floaterpositions.push_back( d16 );
  104.     floater_visible.push_back(false);
  105.   }
  106.   // pointer
  107.   ptr_col.x = 0;
  108.   ptr_col.y = 0;
  109.   ptr_col.z = 255;
  110. }
  111. /*
  112.  * draw teapots (with names for selection)
  113.  */
  114. void drawObjs ()
  115. {
  116.   glMatrixMode( GL_MODELVIEW );
  117.   // for unproject
  118.   glGetDoublev( GL_MODELVIEW_MATRIX, modelview );
  119.   glGetDoublev( GL_PROJECTION_MATRIX, projection );
  120.   
  121.   float spec[] = {1, 1, 1, 1};
  122.   float shine[] = {70};
  123.   glMaterialfv(GL_FRONT, GL_SPECULAR, spec);
  124.   glMaterialfv(GL_FRONT, GL_SHININESS, shine);
  125.   if (anchor_visible) {
  126.     glPushMatrix();
  127.     glMultMatrixd(anchor);
  128.     
  129.     for( unsigned int i = 0 ; i < num_anchored ; ++i )
  130.     {
  131.       glPushMatrix();
  132.         if (selected==(int)i) {
  133.   glGetDoublev( GL_MODELVIEW_MATRIX, selected_view );
  134. }
  135. float col[] = {colors[ i ].x, colors[ i ].y, colors[ i ].z, 1};
  136. glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col);
  137. glLoadName( i + 1 );
  138. if (i==IDX_ANCHORED_LIGHT) {
  139.   // direct lamp shade towards teapot
  140.   glTranslated( positions[i].x, positions[i].y, positions[i].z );
  141. #if 0
  142.   double upx = 0, upy = 1, upz = 1;
  143.   // todo : should check for singularity here
  144.   GLdouble curr[16];
  145.   glGetDoublev( GL_MODELVIEW_MATRIX, curr );
  146.   double w0x, w0y, w0z;
  147.   {  // world coordinates for object 0
  148.     double x = positions[0].x;
  149.     double y = positions[0].y;
  150.     double z = positions[0].z;
  151.     w0x = curr[0]*x + curr[4]*y + curr[8]*z + curr[12]*1;
  152.     w0y = curr[1]*x + curr[5]*y + curr[9]*z + curr[13]*1;
  153.     w0z = curr[2]*x + curr[6]*y + curr[10]*z + curr[14]*1;
  154.   }
  155.   //w0x = curr[13]+positions[0].x;
  156.   //w0y = curr[14]+positions[0].y;
  157.   //w0z = curr[15]+positions[0].z;
  158.   //glLoadIdentity();
  159.   double wLx = curr[13]+positions[i].x;
  160.   double wLy = curr[14]+positions[i].y;
  161.   double wLz = curr[15]+positions[i].z;
  162.   {  // world coordinates for object i
  163.     double x = positions[i].x;
  164.     double y = positions[i].y;
  165.     double z = positions[i].z;
  166.     wLx = curr[0]*x + curr[4]*y + curr[8]*z + curr[12]*1;
  167.     wLy = curr[1]*x + curr[5]*y + curr[9]*z + curr[13]*1;
  168.     wLz = curr[2]*x + curr[6]*y + curr[10]*z + curr[14]*1;
  169.   }
  170.   /*
  171.   gluLookAt(wLx, wLy, wLz,
  172.     w0x, w0y, w0z,
  173.     upx, upy, upz);
  174.          -positions[0].x, 
  175.     -positions[0].y, 
  176.     -positions[0].z, 
  177.     upx, upy, upz);
  178.      gluLookAt(positions[IDX_ANCHORED_LIGHT].x, 
  179.     positions[IDX_ANCHORED_LIGHT].y, 
  180.     positions[IDX_ANCHORED_LIGHT].z,
  181.     positions[0].x, positions[0].y, positions[0].z,
  182.     upx, upy, upz);*/
  183. #endif
  184.   double cx, cy, cz;
  185.   double angle;
  186.   {
  187.     double x = positions[0].x-positions[i].x;
  188.     double y = positions[0].y-positions[i].y;
  189.     double z = positions[0].z-positions[i].z;
  190.     double a = 0; //positions[i].x;
  191.     double b = 0; //positions[i].y;
  192.     double c = 1; //positions[i].z;
  193.     cx = y*c - z*b;
  194.     cy = z*a - x*c;
  195.     cz = x*b - y*a;
  196.     double len0 = sqrt(x*x+y*y+z*z);
  197.     double leni = sqrt(a*a+b*b+c*c);
  198.     double dot = (a*x + b*y + c*z)/len0/leni;
  199.     angle = acos(dot)*180/M_PI;
  200.   }
  201.   glRotated(angle, cx, cy, cz);
  202.   //   glutSolidTeapot(40);
  203.   glutSolidSphere(40, 60, 60);
  204. } else {
  205.   glTranslated( positions[i].x, positions[i].y, positions[i].z );
  206.   glRotated(90+rotations[i].x, 1, 0, 0);
  207.   glRotated(90+rotations[i].y, 0, 1, 0);
  208.   glRotated(rotations[i].z, 0, 0, 1);
  209.   glutSolidTeapot(70);
  210.   //   glutSolidSphere(50, 100, 100);
  211. }
  212.       glPopMatrix();
  213.     }
  214.     glPopMatrix();
  215.   }
  216.   for( unsigned int i = num_anchored ; i < positions.size() ; ++i )
  217.   {
  218.     if (floater_visible[i]) {
  219.       glPushMatrix();
  220.         glMultMatrixd(&floaterpositions[ i ][0]);
  221. if (selected==(int)i) {
  222.   glGetDoublev( GL_MODELVIEW_MATRIX, selected_view );
  223. }
  224. float col[] = {colors[ i ].x, colors[ i ].y, colors[ i ].z, 1};
  225. glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col);
  226. glLoadName( i + 1 );
  227. glTranslated( positions[i].x, positions[i].y, positions[i].z );
  228. if (i==IDX_FLOATER_LIGHT) {
  229.   glutWireSphere(20, 10, 10);
  230. } else {
  231.   glRotated(90+rotations[i].x, 1, 0, 0);
  232.   glRotated(90+rotations[i].y, 0, 1, 0);
  233.   glRotated(rotations[i].z, 0, 0, 1);
  234.   glutSolidTeapot(60);
  235. }
  236.       glPopMatrix();
  237.     }
  238.   }
  239. }
  240. void drawPointer()
  241. {
  242.   if (!show_ptr) return;
  243.   glDisable(GL_LIGHTING);
  244.   d3 ptr_win;
  245.   ptr_win.x = ptr_x;
  246.   ptr_win.y = viewport[ 3 ] - ptr_y - 1;
  247.   ptr_win.z = .1;
  248.   /*
  249.    * calculate new world coordinates
  250.    */
  251.   d3 ptr_start;
  252.   gluUnProject(ptr_win.x, ptr_win.y, ptr_win.z,
  253.        modelview, projection, viewport,
  254.        &ptr_start.x, &ptr_start.y, &ptr_start.z );
  255.   d3 ptr_end;
  256.   if (true || selected==-1) {
  257.     gluUnProject(ptr_win.x, ptr_win.y-hv_pointer_dist, ptr_win.z,
  258.  modelview, projection, viewport,
  259.  &ptr_end.x, &ptr_end.y, &ptr_end.z );
  260.   } else {
  261.     ptr_end = selected_world;
  262.   }
  263.   glColor4d( ptr_col.x, ptr_col.y, ptr_col.z, 0.5 );
  264.   glEnable(GL_BLEND);
  265.   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  266.   glMatrixMode( GL_MODELVIEW );
  267.   glPushMatrix();
  268.   glTranslated( ptr_start.x, ptr_start.y, ptr_start.z );
  269.   glBegin( GL_QUADS );
  270.     const double w = 1;
  271.     double x = ptr_end.x-ptr_start.x;
  272.     double y = ptr_end.y-ptr_start.y;
  273.     double z = ptr_end.z-ptr_start.z;
  274.     glVertex3d(w, 0, 0);
  275.     glVertex3d(x+w, -y/2, z/2);
  276.     glVertex3d(x-w, -y/2, z/2);
  277.     glVertex3d(-w, 0, 0);
  278.   
  279.     if (dragging || hovering) {
  280.       // draw first links of claws
  281.       glVertex3d(x+w, -y/2, z/2);
  282.       glVertex3d(x+w*2, -y/1.5, z/1.5);
  283.       glVertex3d(x+w, -y/1.5, z/1.5);
  284.       glVertex3d(x, -y/2, z/2);
  285.       glVertex3d(x-w, -y/2, z/2);
  286.       glVertex3d(x-w*2, -y/1.5, z/1.5);
  287.       glVertex3d(x-w, -y/1.5, z/1.5);
  288.       glVertex3d(x, -y/2, z/2);
  289.     }
  290.     if (dragging) {
  291.       // draw closed claws
  292.       glVertex3d(x+w*2, -y/1.5, z/1.5);
  293.       glVertex3d(x+w, -y, z);
  294.       glVertex3d(x, -y, z);
  295.       glVertex3d(x+w, -y/1.5, z/1.5);
  296.       glVertex3d(x-w*2, -y/1.5, z/1.5);
  297.       glVertex3d(x-w, -y, z);
  298.       glVertex3d(x, -y, z);
  299.       glVertex3d(x-w, -y/1.5, z/1.5);
  300.     } else if (hovering) {
  301.       // draw open claws
  302.       glVertex3d(x+w*2, -y/1.5, z/1.5);
  303.       glVertex3d(x+w*2, -y, z);
  304.       glVertex3d(x+w, -y, z);
  305.       glVertex3d(x+w, -y/1.5, z/1.5);
  306.       glVertex3d(x-w*2, -y/1.5, z/1.5);
  307.       glVertex3d(x-w*2, -y, z);
  308.       glVertex3d(x-w, -y, z);
  309.       glVertex3d(x-w, -y/1.5, z/1.5);
  310.     } else if (rotating) {
  311.       // draw little points in 3 directions
  312.       glVertex3d(x+w, -y/2, z/2);
  313.       glVertex3d(x, -y, z);
  314.       glVertex3d(x, -y, z);
  315.       glVertex3d(x-w, -y/2, z/2);
  316.       glVertex3d(x, -y/2, z/2);
  317.       glVertex3d(x+y/2, -y, z);
  318.       glVertex3d(x+y/2, -y, z);
  319.       glVertex3d(x, -y/2-w, z/2);
  320.       glVertex3d(x, -y/2, z/2);
  321.       glVertex3d(x-y/2, -y, z);
  322.       glVertex3d(x-y/2, -y, z);
  323.       glVertex3d(x, -y/2-w, z/2);
  324.     } else {
  325.       // draw pointy top
  326.       glVertex3d(x+w, -y/2, z/2);
  327.       glVertex3d(x, -y, z);
  328.       glVertex3d(x, -y, z);
  329.       glVertex3d(x-w, -y/2, z/2);
  330.     }
  331.   glEnd();
  332.   glDisable(GL_BLEND);
  333.   glPopMatrix();
  334. }
  335. void drawLights() {
  336.   glMatrixMode(GL_MODELVIEW);
  337.   // "ambient" light from behind
  338.   GLenum use_light = GL_LIGHT0;
  339.   {
  340.     glEnable(use_light);
  341.     float diffuse[] = {.8, .8, .8, .8};
  342.     float specular[] = {0, 0, 0, 1};
  343.     float ambient[] = {0.2, 0.2, 0.2, 1};
  344.     glLightfv(use_light, GL_DIFFUSE, diffuse);
  345.     glLightfv(use_light, GL_SPECULAR, specular);
  346.     glLightfv(use_light, GL_AMBIENT, ambient);
  347.     //    float pos[4] = {0, 0, -1, 0};
  348.     //    glLightfv(use_light, GL_POSITION, pos);
  349.   }  
  350.   use_light = GL_LIGHT1;
  351.   if (anchor_visible) {
  352.     glPushMatrix();
  353.     {
  354.       glEnable(use_light);
  355.       float diffuse[] = {1, 1, 1, 1};
  356.       float specular[] = {1, 1, 1, 1};
  357.       float ambient[] = {0, 0, 0, 1};
  358.       glLightfv(use_light, GL_DIFFUSE, diffuse);
  359.       glLightfv(use_light, GL_SPECULAR, specular);
  360.       glLightfv(use_light, GL_AMBIENT, ambient);
  361.       glMultMatrixd(anchor);
  362.       glTranslated(positions[IDX_ANCHORED_LIGHT].x,
  363.    positions[IDX_ANCHORED_LIGHT].y,
  364.    positions[IDX_ANCHORED_LIGHT].z);
  365.       float pos[4] = {0, 0, 0, 1};
  366.       glLightfv(use_light, GL_POSITION, pos);
  367.       //    glLightf(use_light, GL_CONSTANT_ATTENUATION, 2.0);
  368.       //    glLightf(use_light, GL_LINEAR_ATTENUATION, 2.0);
  369.       //    glLightf(use_light, GL_QUADRATIC_ATTENUATION, 2.0);
  370.       float dir[3];
  371.       dir[0] = positions[0].x-positions[IDX_ANCHORED_LIGHT].x;
  372.       dir[1] = positions[0].y-positions[IDX_ANCHORED_LIGHT].y;
  373.       dir[2] = positions[0].z-positions[IDX_ANCHORED_LIGHT].z;
  374.       glLightfv(use_light, GL_SPOT_DIRECTION, dir);
  375.       glLightf(use_light, GL_SPOT_CUTOFF, 45);
  376.       //    glLightf(use_light, GL_SPOT_EXPONENT, 3);
  377.       //    glRotatef(dir);
  378.     }
  379.     glPopMatrix();
  380.   } else {
  381.     glDisable(use_light);
  382.   }
  383.   use_light = GL_LIGHT2;
  384.   if (floater_visible[IDX_FLOATER_LIGHT]) {
  385.     glPushMatrix();
  386.     {
  387.       glEnable(use_light);
  388.       float diffuse[] = {.5, .5, 1, 1};
  389.       float specular[] = {.5, .5, 1, 1};
  390.       float ambient[] = {0, 0, 0, 1};
  391.       glLightfv(use_light, GL_DIFFUSE, diffuse);
  392.       glLightfv(use_light, GL_SPECULAR, specular);
  393.       glLightfv(use_light, GL_AMBIENT, ambient);
  394.       glMultMatrixd(&floaterpositions[IDX_FLOATER_LIGHT][0]);
  395.       glTranslated( positions[IDX_FLOATER_LIGHT].x, 
  396.     positions[IDX_FLOATER_LIGHT].y, 
  397.     positions[IDX_FLOATER_LIGHT].z );
  398.       float pos[4] = {0, 0, 0, 1};
  399.       glLightfv(use_light, GL_POSITION, pos);
  400.       float dir[3];
  401.       dir[0] = positions[2].x-positions[IDX_FLOATER_LIGHT].x;
  402.       dir[1] = positions[2].y-positions[IDX_FLOATER_LIGHT].y;
  403.       dir[2] = positions[2].z-positions[IDX_FLOATER_LIGHT].z;
  404.       glLightfv(use_light, GL_SPOT_DIRECTION, dir);
  405.       //      glLightf(use_light, GL_SPOT_CUTOFF, 45);
  406.     }
  407.     glPopMatrix();
  408.   } else {
  409.     glDisable(use_light);
  410.   }
  411. }
  412. void hv_draw(bool rendering)
  413. {
  414.   drawObjs();
  415.   if (rendering) {
  416.     drawLights();
  417.     drawPointer();
  418.   }
  419. }
  420. void hv_set_anchor_transform(bool visible, double m[16])
  421. {
  422.   anchor_visible = visible;
  423.   if (visible && m!=NULL) {
  424.     memcpy(anchor, m, 16*sizeof(double));
  425.     //for (int i = 0; i<16; i++) printf("%e, ", anchor[i]); printf("n");
  426.   }
  427. }
  428. void hv_set_floater_transform(int id, bool visible, double m[16])
  429. {
  430.   id += num_anchored;
  431.   if (id>=(int) floater_visible.size()) {
  432.     fprintf(stderr, "invalid floater id: %dn", id);
  433.     exit(-1);
  434.   }
  435.   floater_visible[id] = visible;
  436.   if (visible && m!=NULL) {
  437.     memcpy(&floaterpositions[id][0], m, 16*sizeof(double));
  438.   }
  439. }
  440. //----------------------------------------------------------------------
  441. static const int SELECT_BUF_SIZE = 1024 * 10;
  442. void drag( int x, int y )
  443. {
  444.   /*
  445.    * new window coords are x,y plus old z
  446.    */
  447.   d3 new_win = selected_win;
  448.   new_win.x = x;
  449.   new_win.y = viewport[ 3 ] - y - 1;
  450.   /*
  451.    * calculate new world coordinates
  452.    */
  453.   d3 new_world;
  454.   gluUnProject(new_win.x, new_win.y, new_win.z,
  455.        selected_view, projection, viewport,        
  456.        &new_world.x, &new_world.y, &new_world.z );
  457.   /*
  458.    * delta vector is new world minus old world
  459.    */
  460.   d3 offset;
  461.   offset.x = new_world.x - selected_rel.x;
  462.   offset.y = new_world.y - selected_rel.y;
  463.   offset.z = new_world.z - selected_rel.z;
  464.   /*
  465.    * update selected teapot position with delta vector
  466.    */
  467.   positions[ selected ].x += offset.x;
  468.   positions[ selected ].y += offset.y;
  469.   positions[ selected ].z += offset.z;
  470.   selected_win   = new_win;
  471.   selected_rel = new_world;
  472. }
  473. void rotate( int x, int y )
  474. {
  475.   /*
  476.    * new window coords are x,y plus old z
  477.    */
  478.   rotations[ selected ].x = x - selected_win.x;
  479.   rotations[ selected ].y = (viewport[3]-y-1) - selected_win.y;
  480. }
  481. void hv_pointer_update(bool show, int button, int x, int y)
  482. {
  483.   ptr_x = x;
  484.   ptr_y = y;
  485.   show_ptr = show;
  486.   if (!show) {
  487.     dragging = false;
  488.     rotating = false;
  489.     selected = -1;
  490.     return;
  491.   }
  492.   if (button == HV_PTR_LBUTTON_PRESSED) {
  493.     if (!dragging) {
  494.       if( render_select( x, y-hv_pointer_dist, &selected, &selected_win ) ) 
  495.       {
  496. gluUnProject(selected_win.x, selected_win.y, selected_win.z,
  497.      selected_view, projection, viewport,
  498.      &selected_rel.x, &selected_rel.y, &selected_rel.z);
  499. gluUnProject(selected_win.x, selected_win.y-hv_pointer_dist, selected_win.z,
  500.      modelview, projection, viewport,
  501.      &selected_world.x, &selected_world.y, &selected_world.z);
  502. dragging = true;
  503. rotating = false;
  504.       }
  505.     } else {
  506.       drag( x, y-hv_pointer_dist );
  507.     }
  508.   } else if (button == HV_PTR_RBUTTON_PRESSED) {
  509.     if (!rotating) {
  510.       if( render_select( x, y-hv_pointer_dist, &selected, &selected_win ) ) 
  511.       {
  512. gluUnProject(selected_win.x, selected_win.y, selected_win.z,
  513.      selected_view, projection, viewport,
  514.      &selected_rel.x, &selected_rel.y, &selected_rel.z);
  515. gluUnProject(selected_win.x, selected_win.y-hv_pointer_dist, selected_win.z,
  516.      modelview, projection, viewport,
  517.      &selected_world.x, &selected_world.y, &selected_world.z);
  518. rotating = true;
  519. dragging = false; 
  520.      }
  521.     } else {
  522.       rotate( x, y-hv_pointer_dist );
  523.     }
  524.   } else if (button == HV_PTR_BUTTON_RELEASED) {
  525.     dragging = false;
  526.     rotating = false;
  527.     selected = -1;
  528.   } else if (button == HV_PTR_NO_BUTTON_ACTION) {
  529.     if (dragging) {
  530.       drag( x, y-hv_pointer_dist );
  531.     }
  532.     if (rotating) {
  533.       rotate( x, y-hv_pointer_dist );
  534.     }
  535.   } else {
  536.     fprintf(stderr, "wrong 'button' value in hv_pointer_updaten");
  537.     exit(-1);
  538.   }
  539.   //  printf("selected: %dn", selected);
  540.   if (!dragging && !rotating && 
  541.       render_select( x, y-hv_pointer_dist, &selected, &selected_win ) ) 
  542.   {
  543.     gluUnProject(selected_win.x, selected_win.y, selected_win.z,
  544.  selected_view, projection, viewport,
  545.  &selected_rel.x, &selected_rel.y, &selected_rel.z);
  546.     
  547.     gluUnProject(selected_win.x, selected_win.y-hv_pointer_dist, selected_win.z,
  548.  modelview, projection, viewport,
  549.  &selected_world.x, &selected_world.y, &selected_world.z);
  550.     hovering = true;
  551.   } else {
  552.     hovering = false;
  553.   }
  554. }
  555. void ChangeObjectColor()
  556. {
  557.   if (selected!=-1) {
  558.     colors[selected].x = (float)rand() / ( float )RAND_MAX;
  559.     colors[selected].y = (float)rand() / ( float )RAND_MAX;
  560.     colors[selected].z = (float)rand() / ( float )RAND_MAX;
  561.   }
  562. }