Subversion Repositories AndroidProjects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
204 chris 1
/*
2
 *      twoView.c
3
 *
4
 *  Some code to demonstrate grabbing from two video sources.
5
 *  Press '?' while running for help.
6
 *
7
 *  Copyright (c) 2004-2006 Philip Lamb (PRL) phil@eden.net.nz. All rights reserved.
8
 *
9
 *      Rev             Date            Who             Changes
10
 *      1.0.0   2004-10-27      PRL             Initial version.
11
 *
12
 */
13
/*
14
 *
15
 * This file is part of ARToolKit.
16
 *
17
 * ARToolKit is free software; you can redistribute it and/or modify
18
 * it under the terms of the GNU General Public License as published by
19
 * the Free Software Foundation; either version 2 of the License, or
20
 * (at your option) any later version.
21
 *
22
 * ARToolKit is distributed in the hope that it will be useful,
23
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25
 * GNU General Public License for more details.
26
 *
27
 * You should have received a copy of the GNU General Public License
28
 * along with ARToolKit; if not, write to the Free Software
29
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
30
 *
31
 */
32
 
33
 
34
// ============================================================================
35
//      Includes
36
// ============================================================================
37
 
38
#include <stdio.h>                              // fprintf(), stderr
39
#include <stdlib.h>                             // malloc(), free(), atexit()
40
#ifndef __APPLE__
41
#  include <GL/glut.h>
42
#  ifdef GL_VERSION_1_2
43
#    include <GL/glext.h>
44
#  endif
45
#else
46
#  include <GLUT/glut.h>
47
#  include <OpenGL/glext.h>
48
#endif
49
#include <AR/config.h>
50
#include <AR/video.h>
51
#include <AR/param.h>                   // arParamDisp()
52
#include <AR/ar.h>
53
#include <AR/gsub_lite.h>
54
 
55
// ============================================================================
56
//      Constants and types.
57
// ============================================================================
58
 
59
#define VIEW_SCALEFACTOR                0.025           // 1.0 ARToolKit unit becomes 0.025 of my OpenGL units.
60
#define VIEW_DISTANCE_MIN               0.1                     // Objects closer to the camera than this will not be displayed.
61
#define VIEW_DISTANCE_MAX               100.0           // Objects further away from the camera than this will not be displayed.
62
 
63
// For cases in which we have multiple OpenGL contexts, never more than this many.
64
#define CONTEXTSACTIVECOUNT             2
65
#define CONTEXTSACTIVECOUNTMAX  CONTEXTSACTIVECOUNT
66
 
67
// Structure to keep track of per-camera variables.
68
typedef struct {
69
        int                                                     apiContextIndex;        // API-specific index into an array of display contexts.
70
        ARParam                                         ARTCparam;                      // Camera parameter.
71
        AR2VideoParamT                          *ARTVideo;                      // Video parameters
72
        ARUint8                                         *ARTImage;                      // Most recent image.
73
        int                                                     ARTThreshhold;          // Threshold for marker detection.
74
        long                                            callCountMarkerDetect;  // Frames received.
75
        double                                          patt_trans[3][4];       // Marker transformation.
76
        int                                             patt_found;                     // Whether marker transformation is valid.
77
        ARGL_CONTEXT_SETTINGS_REF       arglSettings;           // Settings from ARGL.
78
} CONTEXT_INFO;
79
 
80
// ============================================================================
81
//      Global variables.
82
// ============================================================================
83
 
84
static GLuint *gDrawListBox = NULL;
85
 
86
CONTEXT_INFO *gContextsActive;
87
int gContextsActiveCount = 0;
88
 
89
// ARToolKit globals.
90
static long                     gCallCountGetImage = 0;
91
static int                      gPatt_id;
92
static double           gPatt_width     = 80.0;
93
static double           gPatt_centre[2] = {0.0, 0.0};
94
 
95
// Other globals.
96
static int gDrawRotate = FALSE;
97
static float gDrawRotateAngle = 0;                      // For use in drawing.
98
 
99
// ============================================================================
100
//      Functions
101
// ============================================================================
102
 
103
static int DrawCubeInit(int contextsActiveCountMax)
104
{
105
        // Allocate room for display lists for all contexts.
106
        if (gDrawListBox) return (FALSE); // Sanity check.
107
        if ((gDrawListBox = (GLuint *)calloc(contextsActiveCountMax, sizeof(GLuint))) == NULL) {
108
                return (FALSE);
109
        }      
110
        return (TRUE);
111
 
112
}
113
 
114
static int DrawCubeSetup(int contextIndex)
115
{
116
        // Colour cube data.
117
        float fSize = 0.5f;
118
        long f, i;     
119
        const GLfloat cube_vertices [8][3] = {
120
        {1.0, 1.0, 1.0}, {1.0, -1.0, 1.0}, {-1.0, -1.0, 1.0}, {-1.0, 1.0, 1.0},
121
        {1.0, 1.0, -1.0}, {1.0, -1.0, -1.0}, {-1.0, -1.0, -1.0}, {-1.0, 1.0, -1.0} };
122
        const GLfloat cube_vertex_colors [8][3] = {
123
        {1.0, 1.0, 1.0}, {1.0, 1.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 1.0, 1.0},
124
        {1.0, 0.0, 1.0}, {1.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 1.0} };
125
        GLint cube_num_faces = 6;
126
        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} };
127
 
128
        if (!gDrawListBox[contextIndex]) {
129
                gDrawListBox[contextIndex] = glGenLists (1);
130
                glNewList(gDrawListBox[contextIndex], GL_COMPILE);
131
                glBegin (GL_QUADS);
132
                for (f = 0; f < cube_num_faces; f++)
133
                        for (i = 0; i < 4; i++) {
134
                                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]);
135
                                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);
136
                        }
137
                                glEnd ();
138
                glColor3f (0.0, 0.0, 0.0);
139
                for (f = 0; f < cube_num_faces; f++) {
140
                        glBegin (GL_LINE_LOOP);
141
                        for (i = 0; i < 4; i++)
142
                                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);
143
                        glEnd ();
144
                }
145
                glEndList ();
146
        }
147
 
148
        return (TRUE);
149
}
150
 
151
// Something to look at, draw a rotating colour cube.
152
static void DrawCube(int contextIndex)
153
{
154
        // Draw the colour cube.
155
        glPushMatrix(); // Save world coordinate system.
156
        glTranslatef(0.0, 0.0, 0.5); // Place base of cube on marker surface.
157
        glRotatef(gDrawRotateAngle, 0.0, 0.0, 1.0); // Rotate about z axis.
158
        glDisable(GL_LIGHTING); // Just use colours.
159
        glCallList(gDrawListBox[contextIndex]); // Draw the cube.
160
        glPopMatrix();  // Restore world coordinate system.
161
}
162
 
163
static void DrawCubeUpdate(float timeDelta)
164
{
165
        if (gDrawRotate) {
166
                gDrawRotateAngle += timeDelta * 45.0f; // Rotate cube at 45 degrees per second.
167
                if (gDrawRotateAngle > 360.0f) gDrawRotateAngle -= 360.0f;
168
        }
169
}
170
 
171
static int DrawCubeCleanup(int contextIndex)
172
{
173
        if (contextIndex >= gContextsActiveCount) return (FALSE); // Sanity check.
174
 
175
        // Destroy display lists...
176
        if (gDrawListBox[contextIndex]) {
177
                glDeleteLists(gDrawListBox[contextIndex], 1);
178
                gDrawListBox[contextIndex] = 0;
179
        }
180
 
181
        return (TRUE);
182
}
183
 
184
static int DrawCubeFinal(void)
185
{
186
        if (gDrawListBox) {
187
                free(gDrawListBox);
188
                gDrawListBox = NULL;
189
        }
190
        return (TRUE); 
191
}
192
 
193
// Sets up fields ARTVideo, ARTCparam of gContextsActive[0] through gContextsActive[cameraCount - 1].
194
static int setupCameras(const int cameraCount, const char *cparam_names[], char *vconfs[])
195
{
196
        int i;
197
        ARParam wparam;
198
        int xsize, ysize;
199
 
200
        for (i = 0; i < cameraCount; i++) {
201
 
202
                // Open the video path.
203
                if ((gContextsActive[i].ARTVideo = ar2VideoOpen(vconfs[i])) == NULL) {
204
                        fprintf(stderr, "setupCameras(): Unable to open connection to camera %d.\n", i + 1);
205
                        return (FALSE);
206
                }
207
 
208
                // Find the size of the window.
209
                if (ar2VideoInqSize(gContextsActive[i].ARTVideo, &xsize, &ysize) < 0) return (FALSE);
210
                fprintf(stderr, "setupCameras(): Camera %d image size (x,y) = (%d,%d)\n", i + 1, xsize, ysize);
211
 
212
                // Load the camera parameters, resize for the window and init.
213
                if (arParamLoad(cparam_names[i], 1, &wparam) < 0) {
214
                        fprintf(stderr, "setupCameras(): Error loading parameter file %s for camera %d.\n", cparam_names[i], i + 1);
215
                        return (FALSE);
216
                }
217
                arParamChangeSize(&wparam, xsize, ysize, &(gContextsActive[i].ARTCparam));
218
                arInitCparam(&(gContextsActive[i].ARTCparam));
219
                fprintf(stderr, "*** Camera %d parameter ***\n", i + 1);
220
                arParamDisp(&(gContextsActive[i].ARTCparam));
221
                gContextsActive[i].ARTThreshhold = 100;
222
 
223
                // Start the video capture for this camera.
224
                if (ar2VideoCapStart(gContextsActive[i].ARTVideo) != 0) {
225
                        fprintf(stderr, "setupCameras(): Unable to begin camera data capture for camera %d.\n", i + 1);
226
                        return (FALSE);        
227
                }
228
 
229
        }
230
        return (TRUE);
231
}
232
 
233
static int setupMarker(const char *patt_name, int *patt_id)
234
{
235
 
236
    if((*patt_id = arLoadPatt(patt_name)) < 0) {
237
        fprintf(stderr, "setupMarker(): pattern load error !!\n");
238
        return (FALSE);
239
    }
240
 
241
        return (TRUE);
242
}
243
 
244
// Report state of ARToolKit global variables arFittingMode,
245
// arImageProcMode, arglDrawMode, arTemplateMatchingMode, arMatchingPCAMode.
246
static void debugReportMode(ARGL_CONTEXT_SETTINGS_REF   arglSettings)
247
{
248
        if (arFittingMode == AR_FITTING_TO_INPUT) {
249
                fprintf(stderr, "FittingMode (Z): INPUT IMAGE\n");
250
        } else {
251
                fprintf(stderr, "FittingMode (Z): COMPENSATED IMAGE\n");
252
        }
253
 
254
        if (arImageProcMode == AR_IMAGE_PROC_IN_FULL) {
255
                fprintf(stderr, "ProcMode (X)   : FULL IMAGE\n");
256
        } else {
257
                fprintf(stderr, "ProcMode (X)   : HALF IMAGE\n");
258
        }
259
 
260
        if (arglDrawModeGet(arglSettings) == AR_DRAW_BY_GL_DRAW_PIXELS) {
261
                fprintf(stderr, "DrawMode (C)   : GL_DRAW_PIXELS\n");
262
        } else if (arglTexmapModeGet(arglSettings) == AR_DRAW_TEXTURE_FULL_IMAGE) {
263
                fprintf(stderr, "DrawMode (C)   : TEXTURE MAPPING (FULL RESOLUTION)\n");
264
        } else {
265
                fprintf(stderr, "DrawMode (C)   : TEXTURE MAPPING (HALF RESOLUTION)\n");
266
        }
267
 
268
        if (arTemplateMatchingMode == AR_TEMPLATE_MATCHING_COLOR) {
269
                fprintf(stderr, "TemplateMatchingMode (M)   : Color Template\n");
270
        } else {
271
                fprintf(stderr, "TemplateMatchingMode (M)   : BW Template\n");
272
        }
273
 
274
        if (arMatchingPCAMode == AR_MATCHING_WITHOUT_PCA) {
275
                fprintf(stderr, "MatchingPCAMode (P)   : Without PCA\n");
276
        } else {
277
                fprintf(stderr, "MatchingPCAMode (P)   : With PCA\n");
278
        }
279
#ifdef APPLE_TEXTURE_FAST_TRANSFER
280
#  ifdef GL_APPLE_client_storage
281
        fprintf(stderr, "arglAppleClientStorage is %d.\n", arglAppleClientStorage);
282
#  endif // GL_APPLE_client_storage
283
#  ifdef GL_APPLE_texture_range
284
        fprintf(stderr, "arglAppleTextureRange is %d.\n", arglAppleTextureRange);
285
        fprintf(stderr, "arglAppleTextureRangeStorageHint is ");
286
        switch (arglAppleTextureRangeStorageHint) {
287
                case GL_STORAGE_SHARED_APPLE:
288
                        fprintf(stderr, "GL_STORAGE_SHARED_APPLE.\n");
289
                        break;
290
                case GL_STORAGE_CACHED_APPLE:
291
                        fprintf(stderr, "GL_STORAGE_CACHED_APPLE.\n");
292
                        break;
293
                default:
294
                case GL_STORAGE_PRIVATE_APPLE:
295
                        fprintf(stderr, "GL_STORAGE_PRIVATE_APPLE.\n");
296
                        break;
297
        }
298
#  endif // GL_APPLE_texture_range
299
#endif // APPLE_TEXTURE_FAST_TRANSFER
300
}
301
 
302
// Function to clean up and then exit. Will be
303
// installed by atexit() and called when program exit()s.
304
static void Quit(void)
305
{
306
        int i;
307
 
308
        fprintf(stdout, "Quitting...\n");
309
 
310
        // OpenGL per-context cleanup.
311
        for (i = 0; i < gContextsActiveCount; i++) {
312
                if (gContextsActive[i].apiContextIndex) {
313
                        glutSetWindow(gContextsActive[i].apiContextIndex);
314
                        arglCleanup(gContextsActive[i].arglSettings);
315
                        DrawCubeCleanup(i);
316
                        glutDestroyWindow(gContextsActive[i].apiContextIndex);
317
                        gContextsActive[i].apiContextIndex = 0;
318
                }
319
                ar2VideoCapStop(gContextsActive[i].ARTVideo);
320
                ar2VideoClose(gContextsActive[i].ARTVideo);
321
        }
322
        gContextsActiveCount = 0;
323
 
324
        // Library finals (in reverse order to inits.)
325
        DrawCubeFinal();
326
}
327
 
328
static void Keyboard(unsigned char key, int x, int y)
329
{
330
        int i;
331
        int mode;
332
 
333
        switch (key) {
334
                case 0x1B:                                              // Quit.
335
                case 'Q':
336
                case 'q':
337
                        exit(0);
338
                        break;
339
                case ' ':
340
                        gDrawRotate = !gDrawRotate;
341
                        break;
342
                case 'C':
343
                case 'c':
344
                        for (i = 0; i < gContextsActiveCount; i++) {
345
                                mode = arglDrawModeGet(gContextsActive[i].arglSettings);
346
                                if (mode == AR_DRAW_BY_GL_DRAW_PIXELS) {
347
                                        arglDrawModeSet(gContextsActive[i].arglSettings, AR_DRAW_BY_TEXTURE_MAPPING);
348
                                        arglTexmapModeSet(gContextsActive[i].arglSettings, AR_DRAW_TEXTURE_FULL_IMAGE);
349
                                } else {
350
                                        mode = arglTexmapModeGet(gContextsActive[i].arglSettings);
351
                                        if (mode == AR_DRAW_TEXTURE_FULL_IMAGE) arglTexmapModeSet(gContextsActive[i].arglSettings, AR_DRAW_TEXTURE_HALF_IMAGE);
352
                                        else arglDrawModeSet(gContextsActive[i].arglSettings, AR_DRAW_BY_GL_DRAW_PIXELS);
353
                                }                              
354
                                fprintf(stderr, "*** Camera %2d - %f (frame/sec)\n", i + 1, (double)(gContextsActive[i].callCountMarkerDetect)/arUtilTimer());
355
                                gContextsActive[i].callCountMarkerDetect = 0;
356
                                debugReportMode(gContextsActive[i].arglSettings);
357
                        }
358
                        arUtilTimerReset();
359
                        gCallCountGetImage = 0;
360
                        break;
361
                case 'D':
362
                case 'd':
363
                        arDebug = !arDebug;
364
                        break;
365
                case '?':
366
                case '/':
367
                        printf("Keys:\n");
368
                        printf(" q or [esc]    Quit demo.\n");
369
                        printf(" c             Change arglDrawMode and arglTexmapMode.\n");
370
                        printf(" d             Activate / deactivate debug mode.\n");
371
                        printf(" ? or /        Show this help.\n");
372
                        printf("\nAdditionally, the ARVideo library supplied the following help text:\n");
373
                        arVideoDispOption();
374
                        break;
375
                default:
376
                        break;
377
        }
378
}
379
 
380
static void Idle(void)
381
{
382
        int i;
383
        static int ms_prev;
384
        int ms;
385
        float s_elapsed;
386
        ARUint8 *image;
387
 
388
        ARMarkerInfo    *marker_info;                                   // Pointer to array holding the details of detected markers.
389
    int             marker_num;                                         // Count of number of markers detected.
390
    int             j, k;
391
 
392
        // Find out how long since Idle() last ran.
393
        ms = glutGet(GLUT_ELAPSED_TIME);
394
        s_elapsed = (float)(ms - ms_prev) * 0.001;
395
        if (s_elapsed < 0.01f) return; // Don't update more often than 100 Hz.
396
        ms_prev = ms;
397
 
398
        // Update drawing.
399
        DrawCubeUpdate(s_elapsed);
400
 
401
        gCallCountGetImage++; // Increment Idle() counter.
402
 
403
        for (i = 0; i < gContextsActiveCount; i++) {
404
 
405
                // Grab a video frame.
406
                if ((image = ar2VideoGetImage(gContextsActive[i].ARTVideo)) != NULL) {
407
                        gContextsActive[i].ARTImage = image;    // Save the fetched image.
408
                        gContextsActive[i].patt_found = FALSE;  // Invalidate any previous detected markers.
409
 
410
                        gContextsActive[i].callCountMarkerDetect++; // Increment ARToolKit FPS counter.
411
                        //fprintf(stderr, "Idle(): Got image #%ld from cam %d on attempt #%ld.\n", gContextsActive[i].callCountMarkerDetect, i + 1, gCallCountGetImage);
412
 
413
                        // Detect the markers in the video frame.
414
                        if (arDetectMarkerLite(gContextsActive[i].ARTImage, gContextsActive[i].ARTThreshhold, &marker_info, &marker_num) < 0) {
415
                                exit(-1);
416
                        }
417
 
418
                        // Check through the marker_info array for highest confidence
419
                        // visible marker matching our preferred pattern.
420
                        k = -1;
421
                        for (j = 0; j < marker_num; j++) {
422
                                if (marker_info[j].id == gPatt_id) {
423
                                        if (k == -1) k = j; // First marker detected.
424
                                        else if(marker_info[j].cf > marker_info[k].cf) k = j; // Higher confidence marker detected.
425
                                }
426
                        }
427
 
428
                        if(k != -1) {
429
                                // Get the transformation between the marker and the real camera into gPatt_trans1.
430
                                arGetTransMat(&(marker_info[k]), gPatt_centre, gPatt_width, gContextsActive[i].patt_trans);
431
                                gContextsActive[i].patt_found = TRUE;
432
                        }
433
 
434
                        glutPostWindowRedisplay(gContextsActive[i].apiContextIndex);
435
                }
436
 
437
        }
438
}
439
 
440
//
441
//      The function is called on events when the visibility of a
442
//      GLUT window changes (including when it first becomes visible).
443
//
444
static void Visibility(int visible)
445
{
446
        if (visible == GLUT_VISIBLE) {
447
                glutIdleFunc(Idle);
448
        } else {
449
                glutIdleFunc(NULL);
450
        }
451
}
452
 
453
//
454
//      This function is called when the
455
//      GLUT window is resized.
456
//
457
static void Reshape(int w, int h)
458
{
459
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
460
        glViewport(0, 0, (GLsizei) w, (GLsizei) h);
461
 
462
        glMatrixMode(GL_PROJECTION);
463
        glLoadIdentity();
464
        glMatrixMode(GL_MODELVIEW);
465
        glLoadIdentity();
466
 
467
        // Call through to anyone else who needs to know about window sizing here.
468
}
469
 
470
//
471
// This function is called when a window needs redrawing.
472
//
473
static void DisplayPerContext(const int drawContextIndex)
474
{
475
    GLdouble p[16];
476
        GLdouble m[16];
477
 
478
        // Select correct buffer for this context.
479
        glDrawBuffer(GL_BACK);
480
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);     // Clear the buffers for new frame.
481
 
482
        arglDispImage(gContextsActive[drawContextIndex].ARTImage,
483
                                  &(gContextsActive[drawContextIndex].ARTCparam),
484
                                  1.0,
485
                                  gContextsActive[drawContextIndex].arglSettings);      // zoom = 1.0.
486
        ar2VideoCapNext(gContextsActive[drawContextIndex].ARTVideo);
487
        gContextsActive[drawContextIndex].ARTImage = NULL; // Image data is no longer valid after calling ar2VideoCapNext().
488
 
489
        if (gContextsActive[drawContextIndex].patt_found) {
490
 
491
                // Projection transformation.
492
                arglCameraFrustumRH(&(gContextsActive[drawContextIndex].ARTCparam), VIEW_DISTANCE_MIN, VIEW_DISTANCE_MAX, p);
493
                glMatrixMode(GL_PROJECTION);
494
                glLoadMatrixd(p);
495
                glMatrixMode(GL_MODELVIEW);
496
 
497
                // Viewing transformation.
498
                glLoadIdentity();
499
                // Lighting and geometry that moves with the camera should go here.
500
                // (I.e. must be specified before viewing transformations.)
501
                //none
502
 
503
                // ARToolKit supplied distance in millimetres, but I want OpenGL to work in my units.
504
                arglCameraViewRH(gContextsActive[drawContextIndex].patt_trans, m, VIEW_SCALEFACTOR);
505
                glLoadMatrixd(m);
506
 
507
                // All other lighting and geometry goes here.
508
                DrawCube(drawContextIndex);
509
        } // patt_found
510
 
511
        // Any 2D overlays go here.
512
        //none
513
 
514
        // Drawing for this context complete.
515
}
516
 
517
// Linear search through all active contexts to find context index for the current glut window.
518
int getContextIndexForCurrentGLUTWindow(void)
519
{
520
        int i, window;
521
 
522
        if ((window = glutGetWindow()) != 0) {
523
                for (i = 0; i < gContextsActiveCount; i++) {
524
                        if (gContextsActive[i].apiContextIndex == window) return (i);
525
                }
526
        }
527
        return (-1);           
528
}
529
 
530
static void Display(void)
531
{
532
        int contextIndex;
533
 
534
        if ((contextIndex = getContextIndexForCurrentGLUTWindow()) != -1) {
535
                DisplayPerContext(contextIndex);
536
                glutSwapBuffers();
537
        }
538
}
539
 
540
int main(int argc, char** argv)
541
{
542
        int i;
543
        char windowTitle[32] = {0};
544
        const char *cparam_names[] = { // Camera parameter names.
545
                "Data/camera_para.dat",
546
                "Data/camera_para.dat",
547
        };
548
        char *vconfs[] = {                                      // Camera configuration.
549
#if defined(_WIN32)
550
                "Data\\WDM_camera_flipV.xml",
551
                "Data\\WDM_camera_flipV.xml",
552
#elif defined(__APPLE__)
553
                "",
554
                "",
555
#else
556
                "-dev=/dev/video0 -channel=0 -palette=YUV420P -width=320 -height=240",
557
                "-dev=/dev/video1 -channel=0 -palette=YUV420P -width=320 -height=240",
558
#endif
559
        };
560
        const char *patt_name  = "Data/patt.hiro";
561
 
562
        // ----------------------------------------------------------------------------
563
        // Library inits.
564
        //
565
 
566
        glutInit(&argc, argv);
567
 
568
        // Register a cleanup function to be called upon exit().
569
        if (atexit(Quit) < 0) {
570
                fprintf(stderr, "main(): Unable to register exit function.\n");
571
                exit(-1); // Bail out if we can't even register our exit function.
572
        }
573
 
574
        // Initialise drawing libraries.
575
        if (!DrawCubeInit(CONTEXTSACTIVECOUNTMAX)) {
576
                fprintf(stderr, "main(): DrawCubeInit returned error.\n");
577
                exit(-1);
578
        }
579
 
580
 
581
        // ----------------------------------------------------------------------------
582
        // Hardware setup.
583
        //
584
 
585
        if ((gContextsActive = (CONTEXT_INFO *)calloc(CONTEXTSACTIVECOUNTMAX, sizeof(CONTEXT_INFO))) == NULL) exit(-1);
586
        if (!setupCameras(CONTEXTSACTIVECOUNT, cparam_names, vconfs)) {
587
                fprintf(stderr, "main(): Unable to set up %d AR cameras.\n", CONTEXTSACTIVECOUNT);
588
                exit(-1);
589
        }
590
        gContextsActiveCount = CONTEXTSACTIVECOUNT;
591
        for (i = 0; i < gContextsActiveCount; i++)      if (!setupMarker(patt_name, &gPatt_id)) {
592
                fprintf(stderr, "main(): Unable to set up AR marker.\n");
593
                exit(-1);
594
        }
595
 
596
        // ----------------------------------------------------------------------------
597
        // Library setup.
598
        //
599
 
600
        // Per- GL context setup.
601
        for (i = 0; i < gContextsActiveCount; i++ ) {
602
 
603
                // Set up GL context(s) for OpenGL to draw into.
604
                glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
605
                glutInitWindowSize(gContextsActive[i].ARTCparam.xsize, gContextsActive[i].ARTCparam.ysize);
606
                glutInitWindowPosition(10 + 10*i, 20 + 10*i); // First window at 20,10, subsequent windows staggered.
607
                sprintf(windowTitle, "Video source %i", i);
608
                if ((gContextsActive[i].apiContextIndex = glutCreateWindow(windowTitle)) < 1) {
609
                        fprintf(stderr, "main(): Unable to create window.\n");
610
                        exit(-1);
611
                }
612
                glutDisplayFunc(Display);
613
                glutReshapeFunc(Reshape);
614
                glutVisibilityFunc(Visibility);
615
                glutKeyboardFunc(Keyboard);
616
 
617
                DrawCubeSetup(i);
618
 
619
                if ((gContextsActive[i].arglSettings = arglSetupForCurrentContext()) == NULL) {
620
                        fprintf(stderr, "main(): arglSetupForCurrentContext() returned error.\n");
621
                        exit(-1);
622
                }
623
                debugReportMode(gContextsActive[i].arglSettings);
624
                glEnable(GL_DEPTH_TEST);
625
        }
626
        arUtilTimerReset();
627
 
628
        // Register GLUT event-handling callbacks.
629
        // NB: Idle() is registered by Visibility.
630
        glutMainLoop();
631
 
632
        return (0);
633
}