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 }