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

视频捕捉/采集

开发平台:

MultiPlatform

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <math.h>
  4. #include <GL/glut.h>
  5. #include <AR/ar.h>
  6. #include <AR/arMulti.h>
  7. #include <AR/video.h>
  8. #include <float.h>
  9. #include "gsub.h"
  10. #include "sdlut.h"
  11. #include "main.h"
  12. #include "callbacks.h"
  13. #include "drawing.h"
  14. #include "hv_ARtk_demo.h"
  15. using namespace std;
  16. #define KMOD_ALL ( KMOD_CTRL | KMOD_ALT | KMOD_SHIFT | KMOD_META )
  17. static const int SELECT_BUF_SIZE = 1024 * 10;
  18. //#define PROX_THRESH 135.0
  19. static const int MAX_NAME_STACK = 32;
  20. static const unsigned int NAME_END = UINT_MAX;
  21. static const int MOUSE_SQR_DIST_THRESH = 16;
  22. static const unsigned int MOUSE_TICKS_THRESH = 500;
  23. int DrawMode = RENDER_MODE;
  24. texture_info videoTex;
  25. static bool multiVisible = false;
  26. static bool mouse_moved = false;
  27. int mouse_x, mouse_y;
  28. bool show_markers = true;
  29. extern bool fixed_world;
  30. extern bool take_snapshots;
  31. extern bool fullsize_snapshots;
  32. unsigned char *framePixels = NULL;
  33. static GLUquadric *quadric = gluNewQuadric();
  34. static void selectDraw();
  35. bool render_select( int x, int y, int* selected,  
  36. d3* selected_win, d3* selected_world);
  37. bool process_selection ( GLint hits, GLuint *buffer, int x, int y,
  38.  int* selected,  
  39.  d3* selected_win);
  40. void initObjs();
  41. //-------------------------------------------------------------------------
  42. // regular event callback functions
  43. //-------------------------------------------------------------------------
  44. void displayFunc()
  45. {
  46.   if (mouse_moved) {
  47.     mouse_moved = false;
  48.     // this in turn might call selectDraw()
  49.     hv_pointer_update(HV_PTR_SHOW, HV_PTR_NO_BUTTON_ACTION, 
  50.       mouse_x, mouse_y);
  51.   }
  52.   glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
  53.   ARUint8 *dataPtr = NULL;
  54.   arVideoCapNext();
  55.   dataPtr = (ARUint8 *)arVideoGetImage();
  56.   if( dataPtr == NULL )
  57.     return;
  58.   hv_process_frame((char*)dataPtr, xsize, ysize);
  59.   if (take_snapshots && !fullsize_snapshots) {
  60.     hv_save_frame((char*) dataPtr, xsize, ysize, fullsize_snapshots);
  61.   }
  62.   
  63.   makeTexture( dataPtr, 640, 480, &videoTex );
  64.   glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
  65.   argDrawMode2D();
  66.   if( videopassthrough )
  67.     argDispImage( dataPtr, 0, 0 );
  68.   if (fixed_world) {
  69.     // show whereever it was last
  70.     hv_set_anchor_transform(true, NULL);
  71.   }
  72.    
  73.  // find makers
  74.   ARMarkerInfo *found;
  75.   int found_num;
  76.   
  77.   // detect markers in the scene
  78.   if( arDetectMarker( dataPtr, threshold, &found, &found_num ) < 0 ) {
  79.     fprintf( stderr, "ERROR: arDetectMarkern" );
  80.     fflush( stderr );
  81.     cleanup();
  82.     exit( 1 );
  83.   }
  84.   
  85.   if (!fixed_world) {
  86.     // process the detected floater markers - there is only the
  87.     // anchor marker in fixed_world
  88.     current_marker = NULL;
  89.     for( vector< Marker * >::iterator i = floater_markers.begin() ;
  90.  i != floater_markers.end() ; ++i )
  91.     {
  92.       int k = -1;
  93.       for( int j = 0 ; j < found_num ; ++j )
  94. if( found[ j ].id == ( *i )->id )
  95.   k = j;
  96.       
  97.       if( k != -1 ) {
  98. arGetTransMat( &found[ k ], ( *i )->center, 
  99.        ( *i )->width, ( *i )->trans );
  100. double gl_para[16];
  101. argConvGlparad((*i)->trans, gl_para);
  102. hv_set_floater_transform((*i)->id, true, gl_para);
  103.       }
  104.       else
  105.       {
  106. hv_set_floater_transform((*i)->id, false, NULL);
  107.       }
  108.     }
  109.   }
  110.   
  111.   // process the detected anchored markers
  112.   double multiError = arMultiGetTransMat( found, found_num, multi_markers );
  113.   multiVisible = ( multiError >= 0.0 && multiError < 100.0 );
  114.   
  115.   if( multiVisible ) {
  116.     double gl_para[16];
  117.     argConvGlparad(multi_markers->trans, gl_para);
  118.     if (fixed_world) {
  119.       hv_set_floater_transform(0, true, gl_para);
  120.     } else {
  121.       hv_set_anchor_transform(true, gl_para);
  122.     }
  123.   }
  124.   argDrawMode3D();
  125.   argDraw3dCamera( 0, 0 );  
  126.   
  127.   glDepthFunc( GL_LEQUAL );
  128.   glEnable( GL_DEPTH_TEST );
  129.   glEnable( GL_NORMALIZE );
  130.   glEnable( GL_LIGHTING );
  131.   glDisable( GL_TEXTURE_2D );
  132.   glDisable( GL_CULL_FACE );
  133.   glMatrixMode( GL_MODELVIEW );
  134.   hv_draw(true);
  135.   // draw markers
  136.   if( show_markers ) {
  137.     if( multiVisible )
  138.       drawMulti( multi_markers );
  139.     for( vector< Marker * >::iterator i = floater_markers.begin() ;
  140.  i != floater_markers.end() ; ++i ) {
  141.       if( ( *i )->visible ) {
  142. glColor4d(0, 0, 0, 0.4);
  143. drawMarker( *i );
  144.       }
  145.     }
  146.   }
  147.   /*
  148.     if (floater_visible[i]) {
  149.       glPushMatrix();
  150.         glMultMatrixd(&floaterpositions[ i ][0]);
  151. glDisable(GL_LIGHTING);
  152. drawBullseye(40, 3);
  153. glEnable(GL_LIGHTING);
  154.       glPopMatrix();
  155.     }
  156.   }
  157. }
  158.   */
  159.   if (take_snapshots && fullsize_snapshots) {
  160.     if (!framePixels) {
  161.       fprintf( stderr, "error: framePixels not setn");
  162.       exit(-1);
  163.     }
  164.     glReadBuffer( GL_BACK );
  165.     glReadPixels( 0, 0, xsize, ysize, GL_BGR, GL_UNSIGNED_BYTE, 
  166.   framePixels );
  167.     hv_save_frame((char*) framePixels, xsize, ysize, 
  168.   fullsize_snapshots);
  169.   }
  170.   sdlutSwapBuffers();
  171. }
  172. /* turn off all displays, reset the anchored object to a nice
  173.  * default location
  174.  */
  175. void ResetWorld()
  176. {
  177.   double gl_para[] = 
  178.     {7.275137e-03, 6.592478e-01, -7.518906e-01, 0.000000e+00, 9.997167e-01, -2.183459e-02, -9.471231e-03, 0.000000e+00, -2.266111e-02, -7.516087e-01, -6.592199e-01, 0.000000e+00, 4.982944e+01, -3.182761e+01, 1.200848e+03, 1.000000e+00};
  179.   hv_set_anchor_transform(true, gl_para);
  180.   for( vector< Marker * >::iterator i = floater_markers.begin() ;
  181.        i != floater_markers.end() ; ++i ) {
  182.     hv_set_floater_transform((*i)->id, false, NULL);
  183.   }
  184.   initObjs();
  185. }
  186. void keyboardFunc( SDL_KeyboardEvent *e )
  187. {
  188.   switch( e->keysym.sym )
  189.   {
  190.   case SDLK_ESCAPE:
  191.   case 'q':
  192.     if( e->type == SDL_KEYUP )
  193.     {
  194.       quit();
  195.     }
  196.     return;
  197.     break;
  198.   case 'm':
  199.     if ( e->type == SDL_KEYDOWN ) {
  200.       show_markers = !show_markers;
  201.       char buf[256];
  202.       sprintf( buf, "INFO: %sshowing markers", 
  203.        show_markers ? "" : "not " );
  204.       hv_show_message(buf);
  205.     }
  206.     break;
  207.   case 'e':
  208.     if ( e->type == SDL_KEYDOWN ) {
  209.       hv_toggle_adjust_exposure();
  210.     }
  211.     break;
  212.   case 'f':
  213.     if ( e->type == SDL_KEYDOWN ) {
  214.       fixed_world = !fixed_world;
  215.       char buf[256];
  216.       sprintf( buf, "INFO: fixed world is now %s", 
  217.        fixed_world ? "on" : "off" );
  218.       hv_show_message(buf);
  219.     }
  220.     break;
  221.   case 'w':
  222.     if ( e->type == SDL_KEYDOWN ) {
  223.       ResetWorld();
  224.       hv_show_message("INFO: world reset");
  225.     }
  226.     break;
  227.   case 's':
  228.     if( e->type == SDL_KEYDOWN )
  229.       {
  230. take_snapshots = !take_snapshots;
  231. char buf[256];
  232. sprintf( buf, "INFO: %staking %ssnapshots", 
  233.  take_snapshots ? "" : "not ",
  234.  fullsize_snapshots ? "fullsize " : "");
  235. hv_show_message(buf);
  236.       }
  237.     break;
  238.   case '=':
  239.     if (e->type == SDL_KEYDOWN) {// && e->keysym.mod & KMOD_SHIFT) {
  240.       threshold = min(255, threshold+10);
  241.       char buf[256];
  242.       sprintf(buf, "INFO: threshold now %d", threshold);
  243.       hv_show_message(buf);
  244.     }
  245.     break;
  246.   case '-':
  247.     if (e->type == SDL_KEYDOWN) {
  248.       threshold = max(0, threshold-10);
  249.       char buf[256];
  250.       sprintf(buf, "INFO: threshold now %d", threshold);
  251.       hv_show_message(buf);
  252.     }
  253.     break;
  254.   default:
  255.     if (e->type == SDL_KEYDOWN && e->keysym.mod==0) {
  256.       // hand to HandVu
  257.       hv_key_pressed(e->keysym.sym);
  258.       break;
  259.     }
  260.   }
  261. }
  262. void mouseFunc( SDL_MouseButtonEvent *e )
  263. {
  264.   if( e->state == SDL_PRESSED )
  265.   {
  266.     if (e->button==1) {  // left button
  267.       hv_pointer_update(HV_PTR_SHOW, HV_PTR_LBUTTON_PRESSED, 
  268. e->x, e->y);
  269.     } else if (e->button==3 ) {  // right button
  270.       hv_pointer_update(HV_PTR_SHOW, HV_PTR_RBUTTON_PRESSED, 
  271. e->x, e->y);
  272.     }
  273.   }
  274.   else if( e->state == SDL_RELEASED ) { 
  275.     hv_pointer_update(HV_PTR_SHOW, HV_PTR_BUTTON_RELEASED, 
  276.       e->x, e->y);
  277.   } 
  278. }
  279. void motionFunc( SDL_MouseMotionEvent *e )
  280. {
  281.   mouse_moved = true;
  282.   mouse_x = e->x;
  283.   mouse_y = e->y;
  284.   // pointer update happens in displayFunc to avoid a 
  285.   // large lag between the two and too many updates
  286. }
  287. void idleFunc()
  288. {
  289.   sdlutPostRedisplay();
  290. }
  291. //-------------------------------------------------------------------------
  292. // picking helper functions
  293. //-------------------------------------------------------------------------
  294. static void selectDraw()
  295. {
  296.   argDrawMode3D();
  297.   argMult3dCamera( 0, 0 );  
  298.   
  299.   glDepthFunc( GL_LEQUAL );
  300.   glEnable( GL_DEPTH_TEST );
  301.   glDisable( GL_LIGHTING );
  302.   glDisable( GL_NORMALIZE );
  303.   glDisable( GL_TEXTURE_2D );
  304.   glDisable( GL_CULL_FACE );
  305.   glMatrixMode( GL_MODELVIEW );
  306.   glPushMatrix();
  307.   DrawMode = SELECT_MODE;
  308.   //server->draw();
  309.   hv_draw(false);
  310.   glMatrixMode( GL_MODELVIEW );
  311.   glPopMatrix();
  312. }
  313. /*
  314.  * do selection render pass.  call process_selection to determine
  315.  * results of selection.  return true if hit, false if miss.
  316.  */
  317. bool render_select( int x, int y, int* selected,  
  318.    d3* selected_win)
  319. {
  320.   GLuint selectBuffer[ SELECT_BUF_SIZE ];
  321.   GLint hits;
  322.   glSelectBuffer( SELECT_BUF_SIZE, selectBuffer );
  323.   glRenderMode( GL_SELECT );
  324.   glInitNames();
  325.   glPushName(0);
  326.   /*
  327.    * set up pick matrix as 5x5 window around cursor
  328.    */
  329.   glMatrixMode( GL_PROJECTION );
  330.   glPushMatrix();
  331.   glLoadIdentity();
  332.   gluPickMatrix( ( GLdouble )x, ( GLdouble )( viewport[ 3 ] - y ),
  333.                  5.0, 5.0, viewport );
  334.   glMatrixMode( GL_MODELVIEW );
  335.   *selected = -1;        
  336.   selectDraw();
  337.   glMatrixMode( GL_PROJECTION );
  338.   glPopMatrix();
  339.   glMatrixMode( GL_MODELVIEW );
  340.   glFlush();
  341.   /*
  342.    * check selection buffer for hits
  343.    */
  344.   hits = glRenderMode( GL_RENDER );
  345.   return process_selection( hits, selectBuffer, x, y,
  346.     selected, selected_win);
  347. }
  348. /*
  349.  * once hits are recorded from selection pass, process selection
  350.  * buffer to determine what was selected
  351.  */
  352. bool process_selection ( GLint hits, GLuint *buffer, int x, int y,
  353.  int* selected,  
  354.  d3* selected_win)
  355. {
  356.   float min_depth = FLT_MAX;
  357.   GLuint *ptr = buffer;
  358.   GLint names;
  359.   float depth;
  360.   unsigned int name = 0, tempname = 0;
  361.   if( hits == -1 )
  362.   {
  363.     fprintf( stderr, "WARNING: selection namestack overflown" );
  364.     return false;
  365.   }
  366.   for( int i = 0 ; i < hits ; ++i )
  367.   {
  368.     names = *ptr;                          ++ptr;
  369.     depth = ( float )*ptr / 0xffffffff;    ++ptr;  ++ptr;
  370. /*
  371.  * note - redbook says to divide by 0x7fffffff but that clearly wasn't
  372.  * working, as reported depth was twice actual value.  so, changing
  373.  * to 0xffffffff fixes the problem.
  374.  */
  375.     if( names != 1 )
  376.     {
  377.       fprintf( stderr, "WARNING: unexpected name length %dn", names );
  378.       for( int j = 0 ; j < names ; ++j )
  379.         ++ptr;
  380.     }
  381.     else
  382.     {
  383.       tempname = *ptr; ++ptr;
  384.     }
  385.     /*
  386.      * after extracting depth and name of hit record, store if it's
  387.      * the closest to the camera
  388.      */
  389.     if( depth < min_depth )
  390.     {
  391.       min_depth = depth;
  392.       name = tempname;
  393.     }
  394.   }
  395.   /*
  396.    * 0 is the default name - a miss
  397.    */
  398.   if( name == 0 )
  399.     return false;
  400.   /*
  401.    * id of teapot is name - 1 (starts at index 0)
  402.    * store selected coordinates
  403.    */
  404.   *selected = name - 1;
  405.   selected_win->x = x;
  406.   selected_win->y = viewport[ 3 ] - y - 1;
  407.   selected_win->z = min_depth;
  408.   return true;
  409. }
  410. int nextpowerof2 ( int x )
  411. {
  412.   if( x <= 2 ) return 2;
  413.   if( x <= 4 ) return 4;
  414.   if( x <= 8 ) return 8;
  415.   if( x <= 16 ) return 16;
  416.   if( x <= 32 ) return 32;
  417.   if( x <= 64 ) return 64;
  418.   if( x <= 128 ) return 128;
  419.   if( x <= 256 ) return 256;
  420.   if( x <= 512 ) return 512;
  421.   if( x <= 1024 ) return 1024;
  422.   if( x <= 2048 ) return 2048;
  423.   return 4096;
  424. }
  425. void makeTexture ( unsigned char *pixels, int width, int height,
  426.                    texture_info *tex )
  427. {
  428.   if( ! pixels )
  429.   {
  430.     fprintf( stderr, "null pixels!n" );
  431.     return;
  432.   }
  433.   if( tex->id == 0 )
  434.   {
  435.     tex->iw = width;
  436.     tex->ih = height;
  437.     tex->tw = nextpowerof2( width );
  438.     tex->th = nextpowerof2( height );
  439.     tex->s = tex->iw / ( float )tex->tw;
  440.     tex->t = tex->ih / ( float )tex->th;
  441.     glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
  442.     unsigned char *zeros = new unsigned char[ tex->tw * tex->th * 3 ];
  443.     memset( zeros, 0, tex->tw * tex->th * 3 );
  444.     glGenTextures( 1, &tex->id );
  445.     glBindTexture( GL_TEXTURE_2D, tex->id );
  446.     glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
  447.     glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
  448.     glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
  449.     glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
  450.     glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, tex->tw, tex->th, 0, GL_RGB, 
  451.                   GL_UNSIGNED_BYTE, zeros );
  452.     glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, tex->iw, tex->ih, GL_RGB, 
  453.                      GL_UNSIGNED_BYTE, pixels );
  454.     glBindTexture( GL_TEXTURE_2D, 0 );
  455.     delete[] zeros;
  456.   }
  457.   else
  458.   {
  459.     glBindTexture( GL_TEXTURE_2D, tex->id );
  460.     glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, tex->iw, tex->ih, GL_RGB, 
  461.                      GL_UNSIGNED_BYTE, pixels );
  462.     glBindTexture( GL_TEXTURE_2D, 0 );
  463.   }
  464. }