Anaglyph
display objects in 3-D
anaglyph.cpp
Go to the documentation of this file.
00001 /*
00002  * This work is licensed under a Creative Commons 
00003  * Attribution-Noncommercial-Share Alike 3.0 United States License.
00004  * 
00005  *    http://creativecommons.org/licenses/by-nc-sa/3.0/us/
00006  * 
00007  * You are free:
00008  * 
00009  *    to Share - to copy, distribute, display, and perform the work
00010  *    to Remix - to make derivative works
00011  * 
00012  * Under the following conditions:
00013  * 
00014  *    Attribution. You must attribute the work in the manner specified by the
00015  *    author or licensor (but not in any way that suggests that they endorse you
00016  *    or your use of the work).
00017  * 
00018  *    Noncommercial. You may not use this work for commercial purposes.
00019  * 
00020  *    Share Alike. If you alter, transform, or build upon this work, you may
00021  *    distribute the resulting work only under the same or similar license to
00022  *    this one.
00023  * 
00024  * For any reuse or distribution, you must make clear to others the license
00025  * terms of this work. The best way to do this is by including this header.
00026  * 
00027  * Any of the above conditions can be waived if you get permission from the
00028  * copyright holder.
00029  * 
00030  * Apart from the remix rights granted under this license, nothing in this
00031  * license impairs or restricts the author's moral rights.
00032  */
00033 
00034 
00074 #include <config.h>
00075 
00076 #include <cstdlib>
00077 #include <cstdio>
00078 #include <cassert>
00079 #include <cmath>
00080 #include <cstring>
00081 
00082 #include <inttypes.h>
00083 
00084 #if defined ANAGLYPH_HAVE_OPENGL
00085 #include <GL/gl.h>
00086 #include <GL/glu.h>
00087 #endif
00088 
00089 #if defined ANAGLYPH_HAVE_GLUT_FRAMEWORK
00090 #include <GLUT/glut.h>
00091 #elif defined ANAGLYPH_HAVE_GLUT
00092 #include <GL/glut.h>
00093 #endif
00094 
00095 #include <jwsc/math/constants.h>
00096 #include <jwsc/vector/vector.h>
00097 #include <jwsc/vector/vector_math.h>
00098 #include <jwsc/matrix/matrix.h>
00099 #include <jwsc/matrix/matrix_math.h>
00100 #include <jwsc/image/image.h>
00101 #include <jwsc/image/image_io.h>
00102 
00103 #include <jwsc++/base/option.h>
00104 #include <jwsc++/base/exception.h>
00105 #include <jwsc++/graphics/camera.h>
00106 
00107 #ifdef ANAGLYPH_HAVE_DMALLOC
00108 #include <dmalloc.h>
00109 #endif
00110 
00111 
00112 /* Anaglyph glasses filter types. */
00113 #define REDBLUE  1
00114 #define REDGREEN 2
00115 #define REDCYAN  3
00116 #define BLUERED  4
00117 #define GREENRED 5
00118 #define CYANRED  6
00119 
00120 /* Program defaults. */
00121 #define  DEFAULT_VIEW_WIDTH      400
00122 #define  DEFAULT_VIEW_HEIGHT     400
00123 #define  DEFAULT_APERTURE        60.0f
00124 #define  DEFAULT_CLIP_NEAR       10.0f
00125 #define  DEFAULT_CLIP_FAR        3000.0f
00126 #define  DEFAULT_GLASSES_TYPE    REDCYAN
00127 #define  DEFAULT_SCALE           1.0
00128 #define  DEFAULT_SEED            2537984
00129 #define  DEFAULT_CAPTURE_NAME    "capture.tiff"
00130 
00131 
00132 using std::cout;
00133 using std::cerr;
00134 using std::sscanf;
00135 using std::sprintf;
00136 using namespace jwsc;
00137 using namespace jwscxx::base;
00138 using namespace jwscxx::graphics;
00139 
00140 
00142 Options* opts = 0;
00143 
00145 uint32_t view_width = DEFAULT_VIEW_WIDTH;
00146 
00148 uint32_t view_height = DEFAULT_VIEW_HEIGHT;
00149 
00151 float aperture = DEFAULT_APERTURE;
00152 
00154 float clip_near = DEFAULT_CLIP_NEAR;
00155 
00157 float clip_far = DEFAULT_CLIP_FAR;
00158 
00160 int glasses_type = DEFAULT_GLASSES_TYPE;
00161 
00163 float scale = DEFAULT_SCALE;
00164 
00166 uint32_t seed = DEFAULT_SEED;
00167 
00169 const char* capture_fname = DEFAULT_CAPTURE_NAME;
00170 
00172 Stereo_camera_f* camera = 0;
00173 
00175 GLUquadric* quad_fill = 0;
00176 
00178 GLUquadric* quad_wire = 0;
00179 
00181 enum Object_type
00182 {
00183     SOLID_SPHERE, SOLID_CUBE, SOLID_TORUS, SOLID_TEAPOT,
00184     WIRE_SPHERE, WIRE_CUBE, WIRE_TORUS, WIRE_TEAPOT
00185 };
00186 
00187 
00193 struct Modes
00194 {
00196     bool translate_camera;
00197 
00199     bool rotate_camera;
00200 
00202     bool capture_view;
00203 
00208     bool anaglyph;
00209 
00211     bool render_focal_plane;
00212 
00214     bool render_world_axis;
00215 
00217     bool focal_prp;
00218 
00220     bool focal_vrp;
00221 
00222     enum Object_type object;
00223 }
00224 modes;
00225 
00226 
00228 void init_modes()
00229 {
00230     modes.translate_camera   = false;
00231     modes.rotate_camera      = true;
00232     modes.capture_view       = false;
00233     modes.anaglyph           = false;
00234     modes.render_focal_plane = true;
00235     modes.render_world_axis  = true;
00236     modes.focal_prp          = false;
00237     modes.focal_vrp          = true;
00238     modes.object             = SOLID_TEAPOT;
00239 }
00240 
00241 
00243 void init_camera() throw (Arg_error)
00244 {
00245     delete camera;
00246 
00247     camera = new Stereo_camera_f(0, 0, 1000, 0, 0, 0, 0, 1, 0, aperture, 
00248             clip_near, clip_far);
00249 }
00250 
00251 
00253 void clean_up()
00254 {
00255     delete camera;
00256     delete opts;
00257     gluDeleteQuadric(quad_fill);
00258     gluDeleteQuadric(quad_wire);
00259 }
00260 
00261 
00263 void reset()
00264 {
00265     scale    = DEFAULT_SCALE;
00266     aperture = DEFAULT_APERTURE;
00267     init_camera();
00268     init_modes();
00269 }
00270 
00271 
00273 void capture_view()
00274 {
00275     static uint32_t capture_num = 1;
00276 
00277     char  fname_buf       [ 256 ] = { 0 };
00278     char  fname_suffix_buf[ 256 ] = { 0 };
00279     char* fname_suffix;
00280 
00281     strncpy(fname_buf, capture_fname, 250);
00282 
00283     if ((fname_suffix = strstr(fname_buf, ".")) != NULL)
00284     {
00285         strncpy(fname_suffix_buf, fname_suffix, 250);
00286     }
00287     else
00288     {
00289         fname_suffix = fname_buf + strlen(fname_buf);
00290     }
00291 
00292     sprintf(fname_suffix, "-%04d%s", capture_num, fname_suffix_buf);
00293 
00294     camera->capture_gl_view(fname_buf, capture_num);
00295 
00296     capture_num++;
00297 }
00298 
00299 
00301 void render_world_axis()
00302 {
00303     static GLfloat amb_dif[4] = {0, 0, 0, 1.0f};
00304 
00305     glMatrixMode(GL_MODELVIEW);
00306 
00307     glPushMatrix();
00308 
00309     float axis_length  = 100.0f;
00310     float arrow_radius = axis_length / 10.0f;
00311     float arrow_height = axis_length / 5.0f;
00312 
00313     /* X */
00314     amb_dif[0] = 0.9f;  amb_dif[1] = 1.0f;  amb_dif[2] = 0.3f;
00315     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, amb_dif);
00316     glPushMatrix();
00317       glRotatef(90, 0, 1.0f, 0);
00318       gluCylinder(quad_fill, 1, 1, axis_length - 0.5f*arrow_height, 8, 1);
00319     glPopMatrix();
00320     glPushMatrix();
00321       glTranslatef(axis_length - arrow_height, 0, 0);
00322       glRotatef(90, 0, 1.0f, 0);
00323       gluCylinder(quad_fill, arrow_radius, 0, arrow_height, 16, 8);
00324     glPopMatrix();
00325 
00326     /* Y */
00327     amb_dif[0] = 0.9f;  amb_dif[1] = 1.0f;  amb_dif[2] = 0.3f;
00328     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, amb_dif);
00329     glPushMatrix();
00330       glRotatef(-90, 1.0f, 0, 0);
00331       gluCylinder(quad_fill, 1, 1, axis_length - 0.5f*arrow_height, 8, 1);
00332     glPopMatrix();
00333     glPushMatrix();
00334       glTranslatef(0, axis_length - arrow_height, 0);
00335       glRotatef(-90, 1.0f, 0, 0);
00336       gluCylinder(quad_fill, arrow_radius, 0, arrow_height, 16, 8);
00337     glPopMatrix();
00338 
00339     /* Z */
00340     amb_dif[0] = 0.9f;  amb_dif[1] = 1.0f;  amb_dif[2] = 0.3f;
00341     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, amb_dif);
00342     gluCylinder(quad_fill, 1, 1, axis_length - 0.5f*arrow_height, 8, 1);
00343     glPushMatrix();
00344       glTranslatef(0, 0, axis_length - arrow_height);
00345       gluCylinder(quad_fill, arrow_radius, 0, arrow_height, 16, 8);
00346     glPopMatrix();
00347 
00348     glPopMatrix();
00349 }
00350 
00351 
00353 void render_focal_plane()
00354 {
00355     static GLfloat amb_dif[4] = {0.7f, 0.6f, 0.5f, 0.2f};
00356     GLboolean prev_blend;
00357     GLint     prev_blend_src;
00358     GLint     prev_blend_dst;
00359 
00360     if ((prev_blend = glIsEnabled(GL_BLEND)))
00361     {
00362         glGetIntegerv(GL_BLEND_SRC, &prev_blend_src);
00363         glGetIntegerv(GL_BLEND_DST, &prev_blend_dst);
00364     }
00365     else
00366     {
00367         glEnable(GL_BLEND);
00368     }
00369     glBlendFunc(GL_SRC_ALPHA, GL_SRC_ALPHA);
00370 
00371     glMatrixMode(GL_MODELVIEW);
00372 
00373     glPushMatrix();
00374     glLoadIdentity();
00375 
00376     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, amb_dif);
00377 
00378     float x = 200.0f;
00379     float y = 200.0f;
00380     float z = -camera->get_focal_length();
00381 
00382     glBegin(GL_POLYGON);
00383     glNormal3f( 0,  0, 1);
00384     glVertex3f( x,  y, z);
00385     glVertex3f(-x,  y, z);
00386     glVertex3f(-x, -y, z);
00387     glVertex3f( x, -y, z);
00388     glEnd();
00389 
00390     glPopMatrix();
00391 
00392     if (prev_blend)
00393     {
00394         glBlendFunc(prev_blend_src, prev_blend_dst);
00395     }
00396     else
00397     {
00398         glDisable(GL_BLEND);
00399     }
00400 }
00401 
00402 
00404 void render_scene()
00405 {
00406     static GLfloat M_scale[16]  = {0};
00407     static GLfloat amb_dif[4]   = {0, 0, 0, 1.0f};
00408     static GLfloat shininess[1] = {0};
00409 
00410     glMatrixMode(GL_MODELVIEW);
00411 
00412     glPushMatrix();
00413 
00414     M_scale[0] = M_scale[5] = M_scale[10] = scale;
00415     M_scale[15] = 1.0f;
00416     glMultMatrixf(M_scale);
00417 
00418     amb_dif[0] = 0.8f;  amb_dif[1] = 0.7f;  amb_dif[2] = 0.4f;
00419     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, amb_dif);
00420     glMaterialfv(GL_FRONT, GL_SPECULAR, amb_dif);
00421     shininess[0] = 120;
00422     glMaterialfv(GL_FRONT, GL_SHININESS, shininess);
00423 
00424     switch (modes.object)
00425     {
00426         case SOLID_SPHERE:
00427             glutSolidSphere(100, 30, 30);
00428             break;
00429         case WIRE_SPHERE:
00430             glutWireSphere(100, 30, 30);
00431             break;
00432         case SOLID_CUBE:
00433             glutSolidCube(150);
00434             break;
00435         case WIRE_CUBE:
00436             glutWireCube(150);
00437             break;
00438         case SOLID_TORUS:
00439             glutSolidTorus(25, 100, 25, 50);
00440             break;
00441         case WIRE_TORUS:
00442             glutWireTorus(25, 100, 25, 50);
00443             break;
00444         case SOLID_TEAPOT:
00445             glutSolidTeapot(100);
00446             break;
00447         case WIRE_TEAPOT:
00448             glutWireTeapot(100);
00449             break;
00450     }
00451 
00452     glPopMatrix();
00453 }
00454 
00455 
00457 void display_glut_anaglyph()
00458 {
00459     /* Set the buffer for reading and writing. Using double buffering. */
00460     glDrawBuffer(GL_BACK);
00461     glReadBuffer(GL_BACK);
00462 
00463     /* Clear things */
00464     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT);
00465 
00466     /* Left camera filter. */
00467     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
00468     switch (glasses_type) 
00469     {
00470         case REDBLUE:
00471         case REDGREEN:
00472         case REDCYAN:
00473             glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE);
00474             break;
00475         case BLUERED:
00476             glColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_TRUE);
00477             break;
00478         case GREENRED:
00479             glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE);
00480             break;
00481         case CYANRED:
00482             glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_TRUE);
00483             break;
00484     } 
00485 
00486     /* Set the left camera projection. */
00487     camera->set_left_gl_projection();
00488 
00489     /* Set the camera model view. */
00490     camera->set_left_gl_modelview();
00491 
00492     /* Render the world axis. */
00493     if (modes.render_world_axis)
00494     {
00495         render_world_axis();
00496     }
00497 
00498     render_scene();
00499 
00500     /* Render the focal plane if in that mode. */
00501     if (modes.render_focal_plane)
00502     {
00503         render_focal_plane();
00504     }
00505 
00506     glFlush();
00507 
00508     glAccum(GL_LOAD, 0.5f);
00509     glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
00510 
00511     /* Right camera filter. */
00512     switch (glasses_type) 
00513     {
00514         case REDBLUE:
00515             glColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_TRUE);
00516             break;
00517         case REDGREEN:
00518             glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE);
00519             break;
00520         case REDCYAN:
00521             glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_TRUE);
00522             break;
00523         case BLUERED:
00524         case GREENRED:
00525         case CYANRED:
00526             glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE);
00527             break;
00528     } 
00529 
00530     /* Set the right camera projection. */
00531     camera->set_right_gl_projection();
00532 
00533     /* Set the camera model view. */
00534     camera->set_right_gl_modelview();
00535 
00536     /* Render the world axis. */
00537     if (modes.render_world_axis)
00538     {
00539         render_world_axis();
00540     }
00541 
00542     render_scene();
00543 
00544     /* Render the focal plane if in that mode. */
00545     if (modes.render_focal_plane)
00546     {
00547         render_focal_plane();
00548     }
00549 
00550     glFlush();
00551 
00553     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
00554 
00555     glAccum(GL_ACCUM, 0.5f);
00556     glAccum(GL_RETURN, 2.0f);
00557 }
00558 
00559 
00563 void display_glut_regular()
00564 {
00565     /* Set the buffer for writing. Using double buffering. */
00566     glDrawBuffer(GL_BACK);
00567     glReadBuffer(GL_BACK);
00568 
00569     /* Clear things */
00570     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00571 
00572     /* Set the camera projection. */
00573     camera->set_gl_projection();
00574 
00575     /* Set the camera model view. */
00576     camera->set_gl_modelview();
00577 
00578     /* Render the world axis. */
00579     if (modes.render_world_axis)
00580     {
00581         render_world_axis();
00582     }
00583 
00584     render_scene();
00585 
00586     /* Render the focal plane if in that mode. */
00587     if (modes.render_focal_plane)
00588     {
00589         render_focal_plane();
00590     }
00591 
00592     glFlush();
00593 }
00594 
00595 
00597 void display_glut()
00598 {
00599     if (modes.anaglyph)
00600     {
00601         display_glut_anaglyph();
00602     }
00603     else
00604     {
00605         display_glut_regular();
00606     }
00607 
00608     glutSwapBuffers();
00609 
00610     if (modes.capture_view)
00611     {
00612         capture_view();
00613         modes.capture_view = 0;
00614     }
00615 }
00616 
00617 
00619 void reshape_glut(int w, int h)
00620 {
00621     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00622     glViewport(0, 0, (GLsizei)w, (GLsizei)h); 
00623     view_width = w;
00624     view_height = h;
00625 }
00626 
00627 
00629 void keyboard_glut(unsigned char key, int a, int b)
00630 {
00631     float translate_delta = 10;
00632     float rotate_delta    = 10*JWSC_DEG_TO_RAD;
00633     float focal_length;
00634     float theta;
00635 
00636     Vector_f* v_tmp = 0;
00637 
00638     switch (key) {
00639         case 't':
00640             modes.translate_camera = 1;
00641             modes.rotate_camera = 0;
00642             break;
00643         case 'r':
00644             modes.rotate_camera = 1;
00645             modes.translate_camera = 0;
00646             break;
00647         case 'l':
00648             if (modes.translate_camera)
00649             {
00650                 const Vector_f* right = camera->get_u();
00651                 camera->translate(
00652                         translate_delta * right->elts[0],
00653                         translate_delta * right->elts[1],
00654                         translate_delta * right->elts[2]);
00655             }
00656             else if (modes.rotate_camera)
00657             {
00658                 camera->rotate(-rotate_delta, 0, 1, 0);
00659             }
00660             glutPostRedisplay();
00661             break;
00662         case 'h':
00663             if (modes.translate_camera)
00664             {
00665                 const Vector_f* right = camera->get_u();
00666                 camera->translate(
00667                         -translate_delta * right->elts[0],
00668                         -translate_delta * right->elts[1],
00669                         -translate_delta * right->elts[2]);
00670             }
00671             else if (modes.rotate_camera)
00672             {
00673                 camera->rotate(rotate_delta, 0, 1, 0);
00674             }
00675             glutPostRedisplay();
00676             break;
00677         case 'L':
00678             if (modes.translate_camera)
00679             {
00680                 const Vector_f* right = camera->get_u();
00681                 camera->translate(
00682                         translate_delta * right->elts[0],
00683                         translate_delta * right->elts[1],
00684                         translate_delta * right->elts[2]);
00685             }
00686             else if (modes.rotate_camera)
00687             {
00688                 copy_vector_f(&v_tmp, camera->get_prp());
00689                 multiply_vector_by_scalar_f(&v_tmp, v_tmp, -1);
00690                 camera->translate(v_tmp);
00691                 camera->rotate(rotate_delta, camera->get_v());
00692                 multiply_vector_by_scalar_f(&v_tmp, v_tmp, -1);
00693                 camera->translate(v_tmp);
00694             }
00695             glutPostRedisplay();
00696             break;
00697         case 'H':
00698             if (modes.translate_camera)
00699             {
00700                 const Vector_f* right = camera->get_u();
00701                 camera->translate(
00702                         -translate_delta * right->elts[0],
00703                         -translate_delta * right->elts[1],
00704                         -translate_delta * right->elts[2]);
00705             }
00706             else if (modes.rotate_camera)
00707             {
00708                 copy_vector_f(&v_tmp, camera->get_prp());
00709                 multiply_vector_by_scalar_f(&v_tmp, v_tmp, -1);
00710                 camera->translate(v_tmp);
00711                 camera->rotate(-rotate_delta, camera->get_v());
00712                 multiply_vector_by_scalar_f(&v_tmp, v_tmp, -1);
00713                 camera->translate(v_tmp);
00714             }
00715             glutPostRedisplay();
00716             break;
00717         case 'k':
00718             if (modes.translate_camera)
00719             {
00720                 const Vector_f* up = camera->get_v();
00721                 camera->translate(
00722                         translate_delta * up->elts[0],
00723                         translate_delta * up->elts[1],
00724                         translate_delta * up->elts[2]);
00725             }
00726             else if (modes.rotate_camera)
00727             {
00728                 camera->rotate(rotate_delta, camera->get_u());
00729             }
00730             glutPostRedisplay();
00731             break;
00732         case 'j':
00733             if (modes.translate_camera)
00734             {
00735                 const Vector_f* up = camera->get_v();
00736                 camera->translate(
00737                         -translate_delta * up->elts[0],
00738                         -translate_delta * up->elts[1],
00739                         -translate_delta * up->elts[2]);
00740             }
00741             else if (modes.rotate_camera)
00742             {
00743                 camera->rotate(-rotate_delta, camera->get_u());
00744             }
00745             glutPostRedisplay();
00746             break;
00747         case 'K':
00748             if (modes.translate_camera)
00749             {
00750                 const Vector_f* view = camera->get_n();
00751                 camera->translate(
00752                         -translate_delta * view->elts[0],
00753                         -translate_delta * view->elts[1],
00754                         -translate_delta * view->elts[2]);
00755             }
00756             else if (modes.rotate_camera)
00757             {
00758                 copy_vector_f(&v_tmp, camera->get_prp());
00759                 multiply_vector_by_scalar_f(&v_tmp, v_tmp, -1);
00760                 camera->translate(v_tmp);
00761                 camera->rotate(-rotate_delta, camera->get_u());
00762                 multiply_vector_by_scalar_f(&v_tmp, v_tmp, -1);
00763                 camera->translate(v_tmp);
00764             }
00765             glutPostRedisplay();
00766             break;
00767         case 'J':
00768             if (modes.translate_camera)
00769             {
00770                 const Vector_f* view = camera->get_n();
00771                 camera->translate(
00772                         translate_delta * view->elts[0],
00773                         translate_delta * view->elts[1],
00774                         translate_delta * view->elts[2]);
00775             }
00776             else if (modes.rotate_camera)
00777             {
00778                 copy_vector_f(&v_tmp, camera->get_prp());
00779                 multiply_vector_by_scalar_f(&v_tmp, v_tmp, -1);
00780                 camera->translate(v_tmp);
00781                 camera->rotate(rotate_delta, camera->get_u());
00782                 multiply_vector_by_scalar_f(&v_tmp, v_tmp, -1);
00783                 camera->translate(v_tmp);
00784             }
00785             glutPostRedisplay();
00786             break;
00787         case 'F':
00788             if (modes.focal_prp)
00789             {
00790                 focal_length = camera->get_focal_length() + 20;
00791                 //camera->set_f_with_same_aperture_using_prp(focal_length);
00792                 camera->set_f_with_new_aperture_using_prp(focal_length);
00793             }
00794             else if (modes.focal_vrp)
00795             {
00796                 focal_length = camera->get_focal_length() + 20;
00797                 camera->set_f_with_same_aperture_using_vrp(focal_length);
00798                 //camera->set_f_with_new_aperture_using_vrp(focal_length);
00799             }
00800             glutPostRedisplay();
00801             break;
00802         case 'f':
00803             if (modes.focal_prp)
00804             {
00805                 focal_length = camera->get_focal_length();
00806                 if (focal_length >= 22)
00807                 {
00808                     focal_length -= 20;
00809                     //camera->set_f_with_same_aperture_using_prp(focal_length);
00810                     camera->set_f_with_new_aperture_using_prp(focal_length);
00811                 }
00812             }
00813             else if (modes.focal_vrp)
00814             {
00815                 focal_length = camera->get_focal_length();
00816                 if (focal_length >= 22)
00817                 {
00818                     focal_length -= 20;
00819                     camera->set_f_with_same_aperture_using_vrp(focal_length);
00820                     //camera->set_f_with_new_aperture_using_vrp(focal_length);
00821                 }
00822             }
00823             glutPostRedisplay();
00824             break;
00825         case 'S':
00826             if (scale >= 2.99f)
00827             {
00828                 scale = 3.0f;
00829             }
00830             else
00831             {
00832                 scale += 0.01f;
00833             }
00834             glutPostRedisplay();
00835             break;
00836         case 's':
00837             if (scale > 0.01f)
00838             {
00839                 scale -= 0.01f;
00840             }
00841             glutPostRedisplay();
00842             break;
00843         case 'A':
00844             aperture += JWSC_PI_8;
00845             camera->set_aperture(aperture);
00846             glutPostRedisplay();
00847             break;
00848         case 'a':
00849             theta = aperture - JWSC_PI_8;
00850             if (theta >= 0)
00851             {
00852                 aperture = theta;
00853                 camera->set_aperture(theta);
00854             }
00855             glutPostRedisplay();
00856             break;
00857         case 'c':
00858             modes.capture_view = 1;
00859             glutPostRedisplay();
00860             break;
00861         case 'o':
00862             reset();
00863             glutPostRedisplay();
00864             break;
00865         case 'q':
00866             free_vector_f(v_tmp);
00867             clean_up();
00868             exit(EXIT_SUCCESS);
00869     }
00870 
00871     free_vector_f(v_tmp);
00872 }
00873 
00874 
00876 void main_menu_glut(int id)
00877 {
00878     switch (id)
00879     {
00880         case 0:
00881             modes.anaglyph = !modes.anaglyph;
00882             glutPostRedisplay();
00883             break;
00884         case 1:
00885             modes.capture_view = 1;
00886             glutPostRedisplay();
00887             break;
00888         case 2:
00889             reset();
00890             glutPostRedisplay();
00891             break;
00892         case 3:
00893             clean_up();
00894             exit(EXIT_SUCCESS);
00895     }
00896 }
00897 
00898 
00900 void option_menu_glut(int id)
00901 {
00902     switch (id)
00903     {
00904         case 0:
00905             modes.render_focal_plane = !modes.render_focal_plane;
00906             glutPostRedisplay();
00907             break;
00908         case 1:
00909             modes.render_world_axis = !modes.render_world_axis;
00910             glutPostRedisplay();
00911             break;
00912     }
00913 }
00914 
00915 
00917 void navigation_menu_glut(int id)
00918 {
00919     switch (id)
00920     {
00921         case 0:
00922             modes.rotate_camera    = true;
00923             modes.translate_camera = false;
00924             break;
00925         case 1:
00926             modes.rotate_camera    = false;
00927             modes.translate_camera = true;
00928             break;
00929     }
00930 }
00931 
00932 
00934 void solid_objects_menu_glut(int id)
00935 {
00936     switch (id)
00937     {
00938         case 0:
00939             modes.object = SOLID_SPHERE;
00940             glutPostRedisplay();
00941             break;
00942         case 1:
00943             modes.object = SOLID_CUBE;
00944             glutPostRedisplay();
00945             break;
00946         case 2:
00947             modes.object = SOLID_TORUS;
00948             glutPostRedisplay();
00949             break;
00950         case 3:
00951             modes.object = SOLID_TEAPOT;
00952             glutPostRedisplay();
00953             break;
00954     }
00955 }
00956 
00957 
00959 void wire_objects_menu_glut(int id)
00960 {
00961     switch (id)
00962     {
00963         case 0:
00964             modes.object = WIRE_SPHERE;
00965             glutPostRedisplay();
00966             break;
00967         case 1:
00968             modes.object = WIRE_CUBE;
00969             glutPostRedisplay();
00970             break;
00971         case 2:
00972             modes.object = WIRE_TORUS;
00973             glutPostRedisplay();
00974             break;
00975         case 3:
00976             modes.object = WIRE_TEAPOT;
00977             glutPostRedisplay();
00978             break;
00979     }
00980 }
00981 
00982 
00984 void objects_menu_glut(int id)
00985 {
00986     ;
00987 }
00988 
00989 
00991 void focal_length_menu_glut(int id)
00992 {
00993     switch (id)
00994     {
00995         case 0:
00996             modes.focal_prp = true;
00997             modes.focal_vrp = false;
00998             break;
00999         case 1:
01000             modes.focal_prp = false;
01001             modes.focal_vrp = true;
01002             break;
01003     }
01004 }
01005 
01006 
01008 void init_glut(int argc, char** argv)
01009 {
01010     glutInit(&argc, (char**)argv);
01011     glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_ACCUM
01012                                     | GLUT_ALPHA);
01013     glutInitWindowSize(view_width, view_height);
01014     glutCreateWindow("Anaglyph");
01015     glutDisplayFunc(display_glut); 
01016     glutReshapeFunc(reshape_glut);
01017     glutKeyboardFunc(keyboard_glut);
01018 
01019     int solid = glutCreateMenu(solid_objects_menu_glut);
01020     glutAddMenuEntry("Sphere", 0);
01021     glutAddMenuEntry("Cube", 1);
01022     glutAddMenuEntry("Torus", 2);
01023     glutAddMenuEntry("Teapot", 3);
01024 
01025     int wire = glutCreateMenu(wire_objects_menu_glut);
01026     glutAddMenuEntry("Sphere", 0);
01027     glutAddMenuEntry("Cube", 1);
01028     glutAddMenuEntry("Torus", 2);
01029     glutAddMenuEntry("Teapot", 3);
01030 
01031     int objects = glutCreateMenu(objects_menu_glut);
01032     glutAddSubMenu("Wire", wire);
01033     glutAddSubMenu("Solid", solid);
01034 
01035     int navigation = glutCreateMenu(navigation_menu_glut);
01036     glutAddMenuEntry("Rotate Camera", 0);
01037     glutAddMenuEntry("Translate Camera", 1);
01038 
01039     int focal_length = glutCreateMenu(focal_length_menu_glut);
01040     glutAddMenuEntry("PRP", 0);
01041     glutAddMenuEntry("VRP", 1);
01042 
01043     int options = glutCreateMenu(option_menu_glut);
01044     glutAddMenuEntry("Focal Plane", 0);
01045     glutAddMenuEntry("Axis", 1);
01046 
01047     glutCreateMenu(main_menu_glut);
01048     glutAddMenuEntry("Anaglyph", 0);
01049     glutAddSubMenu("Objects", objects);
01050     glutAddSubMenu("Navigation", navigation);
01051     glutAddSubMenu("Focal Length", focal_length);
01052     glutAddSubMenu("Options", options);
01053     glutAddMenuEntry("Capture", 1);
01054     glutAddMenuEntry("Reset", 2);
01055     glutAddMenuEntry("Quit", 3);
01056 
01057     glutAttachMenu(GLUT_RIGHT_BUTTON);
01058 }
01059 
01060 
01062 void init_gl() 
01063 {
01064     static GLfloat base_amb [] = {0.0f, 0.0f, 0.0f, 1.0f};
01065     static GLfloat ambient  [] = {0.1f, 0.1f, 0.1f, 1.0f};
01066     static GLfloat diffuse  [] = {0.9f, 0.9f, 0.9f, 1.0f};
01067     static GLfloat specular [] = {1.0f, 1.0f, 1.0f, 1.0f};
01068     static GLfloat direction[] = {1000.0f, 1000.0f, 1000.0f, 1.0f};
01069 
01070     glEnable(GL_DEPTH_TEST);
01071     glEnable(GL_NORMALIZE);
01072     glEnable(GL_LIGHTING);
01073 
01074     glLightModelfv(GL_LIGHT_MODEL_AMBIENT, base_amb);
01075 
01076     glEnable(GL_LIGHT0);
01077     glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
01078     glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
01079     glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
01080     glLightfv(GL_LIGHT0, GL_POSITION, direction);
01081 
01082     if (!quad_fill)
01083     {
01084         quad_fill = gluNewQuadric();
01085         gluQuadricDrawStyle(quad_fill, GLU_FILL);
01086     }
01087 
01088     if (!quad_wire)
01089     {
01090         quad_wire = gluNewQuadric();
01091         gluQuadricDrawStyle(quad_wire, GLU_LINE);
01092     }
01093 
01094     glLineWidth(1.0);
01095     glPointSize(1.0);
01096     glClearColor(1.0, 1.0, 1.0, 0.0);
01097     glClearAccum(0.0, 0.0, 0.0, 0.0);
01098 
01099     glViewport(0, 0, view_width, view_height);
01100 }
01101 
01102 
01104 void print_usage(void)
01105 {
01106     cerr << "usage: anaglyph OPTIONS\n";
01107     cerr << "where OPTIONS is one or more of the following:\n";
01108     opts->print();
01109 }
01110 
01111 
01113 void process_help_opt(void)
01114 {   
01115     print_usage();
01116     clean_up();
01117     exit(EXIT_SUCCESS);
01118 }
01119 
01120 
01122 void process_version_opt(void)
01123 {
01124     cout << ANAGLYPH_PACKAGE_STRING << "\n";
01125     clean_up();
01126     exit(EXIT_SUCCESS);
01127 }
01128 
01130 void process_window_size_opt(const char* arg) throw (Arg_error)
01131 {
01132     int32_t w, h;
01133 
01134     if (!arg)
01135     {
01136         throw Arg_error("Option 'window-size' requires an argument");
01137     }
01138     if (sscanf(arg, "%d,%d", &w, &h) != 2)
01139     {
01140         throw Arg_error("Option 'window-size' has format width,height");
01141     }
01142     if (w <= 0 || h <= 0)
01143     {
01144         throw Arg_error("Option 'window-size' must have width,height > 0");
01145     }
01146     view_width = (uint32_t)w;
01147     view_height = (uint32_t)h;
01148 }
01149 
01151 void process_seed_opt(const char* arg) throw (Arg_error)
01152 {
01153     if (!arg)
01154     {
01155         throw Arg_error("Option 'seed' requires an argument");
01156     }
01157     if (sscanf(arg, "%u", &seed) != 1)
01158     {
01159         throw Arg_error("Option 'seed' must be a non-negative integer");
01160     }
01161 }
01162 
01164 void process_capture_opt(const char* arg) throw (Arg_error)
01165 {
01166     if (!arg)
01167     {
01168         throw Arg_error("Option 'capture' requires an argument");
01169     }
01170     capture_fname = arg;
01171 }
01172 
01174 void process_glasses_opt(const char* arg) throw (Arg_error)
01175 {
01176     if (!arg)
01177     {
01178         throw Arg_error("Option 'glasses' requires an argument");
01179     }
01180     if (strcmp("red-blue", arg) == 0)
01181         glasses_type = REDBLUE;
01182     else if (strcmp("red-green", arg) == 0)
01183         glasses_type = REDGREEN;
01184     else if (strcmp("red-cyan", arg) == 0)
01185         glasses_type = REDCYAN;
01186     else if (strcmp("blue-red", arg) == 0)
01187         glasses_type = BLUERED;
01188     else if (strcmp("green-red", arg) == 0)
01189         glasses_type = GREENRED;
01190     else if (strcmp("cyan-red", arg) == 0)
01191         glasses_type = CYANRED;
01192     else
01193     {
01194         throw Arg_error("Invalid 'glasses' type");
01195     }
01196 
01197     capture_fname = arg;
01198 }
01199 
01200 
01201 void* operator new (size_t s) throw (std::bad_alloc)
01202 {
01203     return malloc(s);
01204 }
01205 
01206 
01207 void operator delete (void* ptr) throw ()
01208 {
01209     if (ptr)
01210         free(ptr);
01211 }
01212 
01213 
01214 
01216 int main(int argc, char** argv)
01217 {
01218     using jwscxx::base::Option_no_arg;
01219     using jwscxx::base::Option_with_arg;
01220 
01221     const char* l_name;
01222     const char* desc;
01223 
01224     opts = new Options();
01225 
01226     l_name = "help";
01227     desc   = "Program usage";
01228     opts->add(new Option_no_arg('h', l_name, desc, process_help_opt));
01229 
01230     l_name = "version";
01231     desc   = "Program version.";
01232     opts->add(new Option_no_arg('v', l_name, desc, process_version_opt));
01233 
01234     l_name = "window-size";
01235     desc   = "Window size with format width,height. Default is 400,400.";
01236     opts->add(new Option_with_arg(0, l_name, desc, process_window_size_opt));
01237 
01238     l_name = "seed";
01239     desc   = "Random seed to use in srand(). Must be a non-negative integer.";
01240     opts->add(new Option_with_arg(0, l_name, desc, process_seed_opt));
01241 
01242     l_name = "capture";
01243     desc   = "View capture name.";
01244     opts->add(new Option_with_arg(0, l_name, desc, process_capture_opt));
01245 
01246     l_name = "glasses";
01247     desc   = "Type of colored glasses. Possible left-right filter types include include red-blue, red-green, red-cyan, blue-red, green-red, cyan-red. Default is cyan-red.";
01248     opts->add(new Option_with_arg(0, l_name, desc, process_capture_opt));
01249 
01250     try
01251     {
01252         opts->process(argc, argv);
01253 
01254         init_glut(argc, argv);
01255         init_gl();
01256         init_camera();
01257         init_modes();
01258 
01259         std::srand(seed);
01260 
01261         glutMainLoop();
01262     }
01263     catch (Arg_error e)
01264     {
01265         cerr << "anaglyph: ";
01266         e.print();
01267     }
01268 
01269     clean_up();
01270 
01271     return EXIT_SUCCESS;
01272 }