00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 #include <stdio.h>                              
00039 #include <stdlib.h>                             
00040 #ifndef __APPLE__
00041 #  include <GL/glut.h>
00042 #  ifdef GL_VERSION_1_2
00043 #    include <GL/glext.h>
00044 #  endif
00045 #else
00046 #  include <GLUT/glut.h>
00047 #  include <OpenGL/glext.h>
00048 #endif
00049 #include <AR/config.h>
00050 #include <AR/video.h>
00051 #include <AR/param.h>                   
00052 #include <AR/ar.h>
00053 #include <AR/gsub_lite.h>
00054 
00055 
00056 
00057 
00058 
00059 #define VIEW_SCALEFACTOR                0.025           // 1.0 ARToolKit unit becomes 0.025 of my OpenGL units.
00060 #define VIEW_DISTANCE_MIN               0.1                     // Objects closer to the camera than this will not be displayed.
00061 #define VIEW_DISTANCE_MAX               100.0           // Objects further away from the camera than this will not be displayed.
00062 
00063 
00064 #define CONTEXTSACTIVECOUNT             2
00065 #define CONTEXTSACTIVECOUNTMAX  CONTEXTSACTIVECOUNT
00066 
00067 
00068 typedef struct {
00069         int                                                     apiContextIndex;        
00070         ARParam                                         ARTCparam;                      
00071         AR2VideoParamT                          *ARTVideo;                      
00072         ARUint8                                         *ARTImage;                      
00073         int                                                     ARTThreshhold;          
00074         long                                            callCountMarkerDetect;  
00075         double                                          patt_trans[3][4];       
00076         int                                             patt_found;                     
00077         ARGL_CONTEXT_SETTINGS_REF       arglSettings;           
00078 } CONTEXT_INFO;
00079 
00080 
00081 
00082 
00083 
00084 static GLuint *gDrawListBox = NULL;
00085 
00086 CONTEXT_INFO *gContextsActive;
00087 int gContextsActiveCount = 0;
00088 
00089 
00090 static long                     gCallCountGetImage = 0;
00091 static int                      gPatt_id;
00092 static double           gPatt_width     = 80.0;
00093 static double           gPatt_centre[2] = {0.0, 0.0};
00094 
00095 
00096 static int gDrawRotate = FALSE;
00097 static float gDrawRotateAngle = 0;                      
00098 
00099 
00100 
00101 
00102 
00103 static int DrawCubeInit(int contextsActiveCountMax)
00104 {
00105         
00106         if (gDrawListBox) return (FALSE); 
00107         if ((gDrawListBox = (GLuint *)calloc(contextsActiveCountMax, sizeof(GLuint))) == NULL) {
00108                 return (FALSE);
00109         }       
00110         return (TRUE);
00111         
00112 }
00113 
00114 static int DrawCubeSetup(int contextIndex)
00115 {
00116         
00117         float fSize = 0.5f;
00118         long f, i;      
00119         const GLfloat cube_vertices [8][3] = {
00120         {1.0, 1.0, 1.0}, {1.0, -1.0, 1.0}, {-1.0, -1.0, 1.0}, {-1.0, 1.0, 1.0},
00121         {1.0, 1.0, -1.0}, {1.0, -1.0, -1.0}, {-1.0, -1.0, -1.0}, {-1.0, 1.0, -1.0} };
00122         const GLfloat cube_vertex_colors [8][3] = {
00123         {1.0, 1.0, 1.0}, {1.0, 1.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 1.0, 1.0},
00124         {1.0, 0.0, 1.0}, {1.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 1.0} };
00125         GLint cube_num_faces = 6;
00126         const short cube_faces [6][4] = { {3, 2, 1, 0}, {2, 3, 7, 6}, {0, 1, 5, 4}, {3, 0, 4, 7}, {1, 2, 6, 5}, {4, 5, 6, 7} };
00127         
00128         if (!gDrawListBox[contextIndex]) {
00129                 gDrawListBox[contextIndex] = glGenLists (1);
00130                 glNewList(gDrawListBox[contextIndex], GL_COMPILE);
00131                 glBegin (GL_QUADS);
00132                 for (f = 0; f < cube_num_faces; f++)
00133                         for (i = 0; i < 4; i++) {
00134                                 glColor3f (cube_vertex_colors[cube_faces[f][i]][0], cube_vertex_colors[cube_faces[f][i]][1], cube_vertex_colors[cube_faces[f][i]][2]);
00135                                 glVertex3f(cube_vertices[cube_faces[f][i]][0] * fSize, cube_vertices[cube_faces[f][i]][1] * fSize, cube_vertices[cube_faces[f][i]][2] * fSize);
00136                         }
00137                                 glEnd ();
00138                 glColor3f (0.0, 0.0, 0.0);
00139                 for (f = 0; f < cube_num_faces; f++) {
00140                         glBegin (GL_LINE_LOOP);
00141                         for (i = 0; i < 4; i++)
00142                                 glVertex3f(cube_vertices[cube_faces[f][i]][0] * fSize, cube_vertices[cube_faces[f][i]][1] * fSize, cube_vertices[cube_faces[f][i]][2] * fSize);
00143                         glEnd ();
00144                 }
00145                 glEndList ();
00146         }
00147         
00148         return (TRUE);
00149 }
00150 
00151 
00152 static void DrawCube(int contextIndex)
00153 {
00154         
00155         glPushMatrix(); 
00156         glTranslatef(0.0, 0.0, 0.5); 
00157         glRotatef(gDrawRotateAngle, 0.0, 0.0, 1.0); 
00158         glDisable(GL_LIGHTING); 
00159         glCallList(gDrawListBox[contextIndex]); 
00160         glPopMatrix();  
00161 }
00162 
00163 static void DrawCubeUpdate(float timeDelta)
00164 {
00165         if (gDrawRotate) {
00166                 gDrawRotateAngle += timeDelta * 45.0f; 
00167                 if (gDrawRotateAngle > 360.0f) gDrawRotateAngle -= 360.0f;
00168         }
00169 }
00170 
00171 static int DrawCubeCleanup(int contextIndex)
00172 {
00173         if (contextIndex >= gContextsActiveCount) return (FALSE); 
00174         
00175         
00176         if (gDrawListBox[contextIndex]) {
00177                 glDeleteLists(gDrawListBox[contextIndex], 1);
00178                 gDrawListBox[contextIndex] = 0;
00179         }
00180         
00181         return (TRUE);
00182 }
00183 
00184 static int DrawCubeFinal(void)
00185 {
00186         if (gDrawListBox) {
00187                 free(gDrawListBox);
00188                 gDrawListBox = NULL;
00189         }
00190         return (TRUE);  
00191 }
00192 
00193 
00194 static int setupCameras(const int cameraCount, const char *cparam_names[], char *vconfs[])
00195 {
00196         int i;
00197         ARParam wparam;
00198         int xsize, ysize;
00199         
00200         for (i = 0; i < cameraCount; i++) {
00201                 
00202                 
00203                 if ((gContextsActive[i].ARTVideo = ar2VideoOpen(vconfs[i])) == NULL) {
00204                         fprintf(stderr, "setupCameras(): Unable to open connection to camera %d.\n", i + 1);
00205                         return (FALSE);
00206                 }
00207                 
00208                 
00209                 if (ar2VideoInqSize(gContextsActive[i].ARTVideo, &xsize, &ysize) < 0) return (FALSE);
00210                 fprintf(stderr, "setupCameras(): Camera %d image size (x,y) = (%d,%d)\n", i + 1, xsize, ysize);
00211 
00212                 
00213                 if (arParamLoad(cparam_names[i], 1, &wparam) < 0) {
00214                         fprintf(stderr, "setupCameras(): Error loading parameter file %s for camera %d.\n", cparam_names[i], i + 1);
00215                         return (FALSE);
00216                 }
00217                 arParamChangeSize(&wparam, xsize, ysize, &(gContextsActive[i].ARTCparam));
00218                 arInitCparam(&(gContextsActive[i].ARTCparam));
00219                 fprintf(stderr, "*** Camera %d parameter ***\n", i + 1);
00220                 arParamDisp(&(gContextsActive[i].ARTCparam));
00221                 gContextsActive[i].ARTThreshhold = 100;
00222                 
00223                 
00224                 if (ar2VideoCapStart(gContextsActive[i].ARTVideo) != 0) {
00225                         fprintf(stderr, "setupCameras(): Unable to begin camera data capture for camera %d.\n", i + 1);
00226                         return (FALSE);         
00227                 }
00228                 
00229         }
00230         return (TRUE);
00231 }
00232 
00233 static int setupMarker(const char *patt_name, int *patt_id)
00234 {
00235         
00236     if ((*patt_id = arLoadPatt(patt_name)) < 0) {
00237         fprintf(stderr, "setupMarker(): pattern load error !!\n");
00238         return (FALSE);
00239     }
00240         
00241         return (TRUE);
00242 }
00243 
00244 
00245 
00246 static void debugReportMode(ARGL_CONTEXT_SETTINGS_REF   arglSettings)
00247 {
00248         if (arFittingMode == AR_FITTING_TO_INPUT) {
00249                 fprintf(stderr, "FittingMode (Z): INPUT IMAGE\n");
00250         } else {
00251                 fprintf(stderr, "FittingMode (Z): COMPENSATED IMAGE\n");
00252         }
00253         
00254         if (arImageProcMode == AR_IMAGE_PROC_IN_FULL) {
00255                 fprintf(stderr, "ProcMode (X)   : FULL IMAGE\n");
00256         } else {
00257                 fprintf(stderr, "ProcMode (X)   : HALF IMAGE\n");
00258         }
00259         
00260         if (arglDrawModeGet(arglSettings) == AR_DRAW_BY_GL_DRAW_PIXELS) {
00261                 fprintf(stderr, "DrawMode (C)   : GL_DRAW_PIXELS\n");
00262         } else if (arglTexmapModeGet(arglSettings) == AR_DRAW_TEXTURE_FULL_IMAGE) {
00263                 fprintf(stderr, "DrawMode (C)   : TEXTURE MAPPING (FULL RESOLUTION)\n");
00264         } else {
00265                 fprintf(stderr, "DrawMode (C)   : TEXTURE MAPPING (HALF RESOLUTION)\n");
00266         }
00267         
00268         if (arTemplateMatchingMode == AR_TEMPLATE_MATCHING_COLOR) {
00269                 fprintf(stderr, "TemplateMatchingMode (M)   : Color Template\n");
00270         } else {
00271                 fprintf(stderr, "TemplateMatchingMode (M)   : BW Template\n");
00272         }
00273         
00274         if (arMatchingPCAMode == AR_MATCHING_WITHOUT_PCA) {
00275                 fprintf(stderr, "MatchingPCAMode (P)   : Without PCA\n");
00276         } else {
00277                 fprintf(stderr, "MatchingPCAMode (P)   : With PCA\n");
00278         }
00279 #ifdef APPLE_TEXTURE_FAST_TRANSFER
00280         fprintf(stderr, "arglAppleClientStorage is %d.\n", arglAppleClientStorage);
00281         fprintf(stderr, "arglAppleTextureRange is %d.\n", arglAppleTextureRange);
00282 #endif // APPLE_TEXTURE_FAST_TRANSFER
00283 }
00284 
00285 
00286 
00287 static void Quit(void)
00288 {
00289         int i;
00290         
00291         fprintf(stdout, "Quitting...\n");
00292 
00293         
00294         for (i = 0; i < gContextsActiveCount; i++) {
00295                 if (gContextsActive[i].apiContextIndex) {
00296                         glutSetWindow(gContextsActive[i].apiContextIndex);
00297                         arglCleanup(gContextsActive[i].arglSettings);
00298                         DrawCubeCleanup(i);
00299                         glutDestroyWindow(gContextsActive[i].apiContextIndex);
00300                         gContextsActive[i].apiContextIndex = 0;
00301                 }
00302                 ar2VideoCapStop(gContextsActive[i].ARTVideo);
00303                 ar2VideoClose(gContextsActive[i].ARTVideo);
00304         }
00305         gContextsActiveCount = 0;
00306         
00307         
00308         DrawCubeFinal();
00309 }
00310 
00311 static void Keyboard(unsigned char key, int x, int y)
00312 {
00313         int i;
00314         int mode;
00315         
00316         switch (key) {
00317                 case 0x1B:                                              
00318                 case 'Q':
00319                 case 'q':
00320                         exit(0);
00321                         break;
00322                 case ' ':
00323                         gDrawRotate = !gDrawRotate;
00324                         break;
00325                 case 'C':
00326                 case 'c':
00327                         for (i = 0; i < gContextsActiveCount; i++) {
00328                                 mode = arglDrawModeGet(gContextsActive[i].arglSettings);
00329                                 if (mode == AR_DRAW_BY_GL_DRAW_PIXELS) {
00330                                         arglDrawModeSet(gContextsActive[i].arglSettings, AR_DRAW_BY_TEXTURE_MAPPING);
00331                                         arglTexmapModeSet(gContextsActive[i].arglSettings, AR_DRAW_TEXTURE_FULL_IMAGE);
00332                                 } else {
00333                                         mode = arglTexmapModeGet(gContextsActive[i].arglSettings);
00334                                         if (mode == AR_DRAW_TEXTURE_FULL_IMAGE) arglTexmapModeSet(gContextsActive[i].arglSettings, AR_DRAW_TEXTURE_HALF_IMAGE);
00335                                         else arglDrawModeSet(gContextsActive[i].arglSettings, AR_DRAW_BY_GL_DRAW_PIXELS);
00336                                 }                               
00337                                 fprintf(stderr, "*** Camera %2d - %f (frame/sec)\n", i + 1, (double)(gContextsActive[i].callCountMarkerDetect)/arUtilTimer());
00338                                 gContextsActive[i].callCountMarkerDetect = 0;
00339                                 debugReportMode(gContextsActive[i].arglSettings);
00340                         }
00341                         arUtilTimerReset();
00342                         gCallCountGetImage = 0;
00343                         break;
00344                 case 'D':
00345                 case 'd':
00346                         arDebug = !arDebug;
00347                         break;
00348                 case '?':
00349                 case '/':
00350                         printf("Keys:\n");
00351                         printf(" q or [esc]    Quit demo.\n");
00352                         printf(" c             Change arglDrawMode and arglTexmapMode.\n");
00353                         printf(" d             Activate / deactivate debug mode.\n");
00354                         printf(" ? or /        Show this help.\n");
00355                         printf("\nAdditionally, the ARVideo library supplied the following help text:\n");
00356                         arVideoDispOption();
00357                         break;
00358                 default:
00359                         break;
00360         }
00361 }
00362 
00363 static void Idle(void)
00364 {
00365         int i;
00366         static int ms_prev;
00367         int ms;
00368         float s_elapsed;
00369         ARUint8 *image;
00370 
00371         ARMarkerInfo    *marker_info;                                   
00372     int             marker_num;                                         
00373     int             j, k;
00374         
00375         
00376         ms = glutGet(GLUT_ELAPSED_TIME);
00377         s_elapsed = (float)(ms - ms_prev) * 0.001;
00378         if (s_elapsed < 0.01f) return; 
00379         ms_prev = ms;
00380         
00381         
00382         DrawCubeUpdate(s_elapsed);
00383         
00384         gCallCountGetImage++; 
00385         
00386         for (i = 0; i < gContextsActiveCount; i++) {
00387                 
00388                 
00389                 if ((image = ar2VideoGetImage(gContextsActive[i].ARTVideo)) != NULL) {
00390                         gContextsActive[i].ARTImage = image;    
00391                         
00392                         gContextsActive[i].callCountMarkerDetect++; 
00393                         
00394                         
00395                         
00396                         if (arDetectMarkerLite(gContextsActive[i].ARTImage, gContextsActive[i].ARTThreshhold, &marker_info, &marker_num) < 0) {
00397                                 exit(-1);
00398                         }
00399                         
00400                         
00401                         
00402                         k = -1;
00403                         for (j = 0; j < marker_num; j++) {
00404                                 if (marker_info[j].id == gPatt_id) {
00405                                         if (k == -1) k = j; 
00406                                         else if (marker_info[j].cf > marker_info[k].cf) k = j; 
00407                                 }
00408                         }
00409                         
00410                         if(k != -1) {
00411                                 
00412                                 arGetTransMat(&(marker_info[k]), gPatt_centre, gPatt_width, gContextsActive[i].patt_trans);
00413                                 gContextsActive[i].patt_found = TRUE;
00414                         } else {
00415                                 gContextsActive[i].patt_found = FALSE;
00416                         }
00417         
00418                         glutPostWindowRedisplay(gContextsActive[i].apiContextIndex);
00419                 }
00420                 
00421         }
00422 }
00423 
00424 
00425 
00426 
00427 
00428 static void Visibility(int visible)
00429 {
00430         if (visible == GLUT_VISIBLE) {
00431                 glutIdleFunc(Idle);
00432         } else {
00433                 glutIdleFunc(NULL);
00434         }
00435 }
00436 
00437 
00438 
00439 
00440 
00441 static void Reshape(int w, int h)
00442 {
00443         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00444         glViewport(0, 0, (GLsizei) w, (GLsizei) h);
00445         
00446         glMatrixMode(GL_PROJECTION);
00447         glLoadIdentity();
00448         glMatrixMode(GL_MODELVIEW);
00449         glLoadIdentity();
00450 
00451         
00452 }
00453 
00454 
00455 
00456 
00457 static void DisplayPerContext(const int drawContextIndex)
00458 {
00459     GLdouble p[16];
00460         GLdouble m[16];
00461         
00462         
00463         glDrawBuffer(GL_BACK);
00464         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);     
00465         
00466         arglDispImage(gContextsActive[drawContextIndex].ARTImage,
00467                                   &(gContextsActive[drawContextIndex].ARTCparam),
00468                                   1.0,
00469                                   gContextsActive[drawContextIndex].arglSettings);      
00470         ar2VideoCapNext(gContextsActive[drawContextIndex].ARTVideo);
00471         gContextsActive[drawContextIndex].ARTImage = NULL; 
00472         
00473         
00474         arglCameraFrustumRH(&(gContextsActive[drawContextIndex].ARTCparam), VIEW_DISTANCE_MIN, VIEW_DISTANCE_MAX, p);
00475         glMatrixMode(GL_PROJECTION);
00476         glLoadMatrixd(p);
00477         glMatrixMode(GL_MODELVIEW);
00478 
00479         
00480         glLoadIdentity();
00481         
00482         
00483         
00484 
00485         if (gContextsActive[drawContextIndex].patt_found) {
00486                 
00487                 
00488                 
00489                 arglCameraViewRH(gContextsActive[drawContextIndex].patt_trans, m, VIEW_SCALEFACTOR);
00490                 glLoadMatrixd(m);
00491                 
00492                 
00493                 DrawCube(drawContextIndex);
00494 
00495         } 
00496         
00497         
00498         
00499                                 
00500         
00501 }
00502 
00503 
00504 int getContextIndexForCurrentGLUTWindow(void)
00505 {
00506         int i, window;
00507         
00508         if ((window = glutGetWindow()) != 0) {
00509                 for (i = 0; i < gContextsActiveCount; i++) {
00510                         if (gContextsActive[i].apiContextIndex == window) return (i);
00511                 }
00512         }
00513         return (-1);            
00514 }
00515 
00516 static void Display(void)
00517 {
00518         int contextIndex;
00519         
00520         if ((contextIndex = getContextIndexForCurrentGLUTWindow()) != -1) {
00521                 DisplayPerContext(contextIndex);
00522                 glutSwapBuffers();
00523         }
00524 }
00525 
00526 int main(int argc, char** argv)
00527 {
00528         int i;
00529         char windowTitle[32] = {0};
00530         const char *cparam_names[] = { 
00531                 "Data/camera_para.dat",
00532                 "Data/camera_para.dat",
00533         };
00534         char *vconfs[] = {                                      
00535 #if defined(_WIN32)
00536                 "Data\\WDM_camera_flipV.xml",
00537                 "Data\\WDM_camera_flipV.xml",
00538 #elif defined(__APPLE__)
00539                 "",
00540                 "",
00541 #else
00542                 "-dev=/dev/video0 -channel=0 -palette=YUV420P -width=320 -height=240",
00543                 "-dev=/dev/video1 -channel=0 -palette=YUV420P -width=320 -height=240",
00544 #endif
00545         };
00546         const char *patt_name  = "Data/patt.hiro";
00547         
00548         
00549         
00550         
00551 
00552         glutInit(&argc, argv);
00553 
00554         
00555         if (atexit(Quit) < 0) {
00556                 fprintf(stderr, "main(): Unable to register exit function.\n");
00557                 exit(-1); 
00558         }
00559 
00560         
00561         if (!DrawCubeInit(CONTEXTSACTIVECOUNTMAX)) {
00562                 fprintf(stderr, "main(): DrawCubeInit returned error.\n");
00563                 exit(-1);
00564         }
00565         
00566         
00567         
00568         
00569         
00570 
00571         if ((gContextsActive = (CONTEXT_INFO *)calloc(CONTEXTSACTIVECOUNTMAX, sizeof(CONTEXT_INFO))) == NULL) exit(-1);
00572         if (!setupCameras(CONTEXTSACTIVECOUNT, cparam_names, vconfs)) {
00573                 fprintf(stderr, "main(): Unable to set up %d AR cameras.\n", CONTEXTSACTIVECOUNT);
00574                 exit(-1);
00575         }
00576         gContextsActiveCount = CONTEXTSACTIVECOUNT;
00577 
00578         
00579         
00580         
00581         
00582         
00583         for (i = 0; i < gContextsActiveCount; i++ ) {
00584                 
00585                 
00586                 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
00587                 glutInitWindowSize(gContextsActive[i].ARTCparam.xsize, gContextsActive[i].ARTCparam.ysize);
00588                 glutInitWindowPosition(10 + 10*i, 20 + 10*i); 
00589                 sprintf(windowTitle, "Video source %i", i);
00590                 if ((gContextsActive[i].apiContextIndex = glutCreateWindow(windowTitle)) < 1) {
00591                         fprintf(stderr, "main(): Unable to create window.\n");
00592                         exit(-1);
00593                 }
00594                 glutDisplayFunc(Display);
00595                 glutReshapeFunc(Reshape);
00596                 glutVisibilityFunc(Visibility);
00597                 glutKeyboardFunc(Keyboard);
00598                 
00599                 DrawCubeSetup(i);
00600 
00601                 if ((gContextsActive[i].arglSettings = arglSetupForCurrentContext()) == NULL) {
00602                         fprintf(stderr, "main(): arglSetupForCurrentContext() returned error.\n");
00603                         exit(-1);
00604                 }
00605                 debugReportMode(gContextsActive[i].arglSettings);
00606                 glEnable(GL_DEPTH_TEST);
00607         }
00608         arUtilTimerReset();
00609         
00610         if (!setupMarker(patt_name, &gPatt_id)) {
00611                 fprintf(stderr, "main(): Unable to set up AR marker in context %d.\n", i);
00612                 exit(-1);
00613         }       
00614                 
00615         
00616         
00617         glutMainLoop();
00618 
00619         return (0);
00620 }