Anaglyph
display objects in 3-D
|
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 }