Alternaria
fit cylinders and ellipsoids to fungus
alternaria_viewer.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 
00046 #include <config.h>
00047 
00048 #include <cstdlib>
00049 #include <cstdio>
00050 #include <cstring>
00051 #include <cassert>
00052 #include <iostream>
00053 #include <sstream>
00054 #include <vector>
00055 
00056 #include <inttypes.h>
00057 
00058 #if defined ALTERNARIA_HAVE_OPENGL_FRAMEWORK
00059 #include <OpenGL/gl.h>
00060 #include <OpenGL/glu.h>
00061 #elif defined ALTERNARIA_HAVE_OPENGL
00062 #include <GL/gl.h>
00063 #include <GL/glu.h>
00064 #endif
00065 
00066 #if defined ALTERNARIA_HAVE_GLUT_FRAMEWORK
00067 #include <GLUT/glut.h>
00068 #elif defined ALTERNARIA_HAVE_GLUT
00069 #include <GL/glut.h>
00070 #endif
00071 
00072 #include <jwsc/math/constants.h>
00073 #include <jwsc/vector/vector.h>
00074 #include <jwsc/vector/vector_math.h>
00075 #include <jwsc/matrix/matrix.h>
00076 #include <jwsc/matrix/matrix_math.h>
00077 #include <jwsc/image/image.h>
00078 #include <jwsc/image/image_io.h>
00079 #include <jwsc/imgblock/imgblock.h>
00080 #include <jwsc/imgblock/imgblock_io.h>
00081 #include <jwsc/imgblock/surface.h>
00082 
00083 #include <jwsc++/base/option.h>
00084 #include <jwsc++/base/exception.h>
00085 #include <jwsc++/graphics/camera.h>
00086 
00087 #include "imaging_model.h"
00088 #include "psf_model.h"
00089 #include "structure.h"
00090 #include "spore.h"
00091 #include "hypha.h"
00092 #include "alternaria_model.h"
00093 
00094 
00095 /* Anaglyph glasses filter types. */
00096 #define REDBLUE  1
00097 #define REDGREEN 2
00098 #define REDCYAN  3
00099 #define BLUERED  4
00100 #define GREENRED 5
00101 #define CYANRED  6
00102 
00103 /* Program defaults. */
00104 #define  VIEW_WIDTH      800
00105 #define  VIEW_HEIGHT     800
00106 #define  APERTURE        60.0f
00107 #define  CLIP_NEAR       10.0f
00108 #define  CLIP_FAR        3000.0f
00109 #define  GLASSES_TYPE    REDCYAN
00110 #define  CAPTURE_FMT     "capture-%04u.tiff"
00111 #define  MODEL_COMPARE_FNAME  0
00112 #define  SURF_COMPARE_FNAME   0
00113 #define  SURF_PATCH_SIZE 2.0
00114 #define  OBJECT_SCALE    1.0
00115 
00116 #define  CENTROID_MIN    -5000.0f
00117 #define  CENTROID_MAX    5000.0f
00118 #define  LENGTH_MU       40.0f
00119 #define  LENGTH_SIGMA    4.0f
00120 #define  LENGTH_MIN      1.f
00121 #define  LENGTH_MAX      1000.0f
00122 #define  WIDTH_MU        15.0f
00123 #define  WIDTH_SIGMA     1.0f
00124 #define  WIDTH_MIN       1.0f
00125 #define  WIDTH_MAX       1000.0f
00126 #define  DWIDTH_SIGMA    0.05f
00127 #define  DWIDTH_MIN      -100.0f
00128 #define  DWIDTH_MAX      100.0f
00129 #define  THETA_MU        0
00130 #define  THETA_SIGMA     0.2f
00131 #define  THETA_MIN       0
00132 #define  THETA_MAX       JWSC_PI
00133 #define  PSI_MIN         -JWSC_PI
00134 #define  PSI_MAX         JWSC_PI
00135 #define  OPACITY_MU      0.9f
00136 #define  OPACITY_SIGMA   0.2f
00137 #define  OPACITY_MIN     0.0f
00138 #define  OPACITY_MAX     1.0f
00139 #define  DIST_MU         0.5f
00140 #define  DIST_SIGMA      0.1f
00141 #define  DIST_MIN        0
00142 #define  DIST_MAX        1.0f
00143 
00144 
00145 
00146 using std::cout;
00147 using std::cerr;
00148 using std::ostringstream;
00149 using std::sscanf;
00150 using std::sprintf;
00151 using std::vector;
00152 using namespace jwsc;
00153 using jwscxx::base::Options;
00154 using jwscxx::base::Exception;
00155 using jwscxx::base::Arg_error;
00156 using jwscxx::graphics::Stereo_camera_f;
00157 
00158 
00159 
00161 Options* opts = 0;
00162 
00164 uint32_t view_width = VIEW_WIDTH;
00165 
00167 uint32_t view_height = VIEW_HEIGHT;
00168 
00170 float aperture = APERTURE;
00171 
00173 float clip_near = CLIP_NEAR;
00174 
00176 float clip_far = CLIP_FAR;
00177 
00179 int glasses_type = GLASSES_TYPE;
00180 
00182 const char* capture_fmt = CAPTURE_FMT;
00183 
00185 const char* model_compare_fname = MODEL_COMPARE_FNAME;
00186 
00188 const char* surface_compare_fname = SURF_COMPARE_FNAME;
00189 
00191 float object_scale = OBJECT_SCALE;
00192 
00194 Stereo_camera_f* camera = 0;
00195 
00197 GLUquadric* quad_fill = 0;
00198 
00200 GLUquadric* quad_wire = 0;
00201 
00203 PSF_model* psf = 0;
00204 
00206 Alternaria* alternaria = 0;
00207 
00209 Alternaria* model_compare = 0;
00210 
00212 list<Surface_patch_f*>* surface_compare = 0;
00213 
00215 Imaging_scale* surface_scale = 0;
00216 
00218 float surface_patch_size = SURF_PATCH_SIZE;
00219 
00221 Imaging_model_density* imaging_d = 0;
00222 
00224 PSF_model_density* psf_d = 0;
00225 
00227 Apical_hypha_density* apical_hypha_d = 0;
00228 
00230 Lateral_hypha_density* lateral_hypha_d = 0;
00231 
00233 Spore_density* spore_d = 0;
00234 
00236 Alternaria_density* alt_d = 0;
00237 
00242 Structure* highlight = 0;
00243 
00249 struct Alternaria_viewer_modes
00250 {
00252     bool translate_camera;
00253 
00255     bool rotate_camera;
00256 
00258     bool capture_view;
00259 
00264     bool anaglyph;
00265 
00267     bool render_focal_plane;
00268 
00270     bool render_world_axis;
00271 
00273     bool focal_prp;
00274 
00276     bool focal_vrp;
00277 
00279     bool clip_near;
00280 }
00281 modes;
00282 
00284 void init_modes()
00285 {
00286     modes.translate_camera   = false;
00287     modes.rotate_camera      = true;
00288     modes.capture_view       = false;
00289     modes.anaglyph           = false;
00290     modes.render_focal_plane = false;
00291     modes.render_world_axis  = true;
00292     modes.focal_prp          = false;
00293     modes.focal_vrp          = true;
00294     modes.clip_near          = true;
00295 }
00296 
00298 void init_camera() throw (Arg_error)
00299 {
00300     delete camera;
00301 
00302     // Generic
00303     camera = new Stereo_camera_f(0, 50, 300, 0, 50, 0, 0, 1, 0,
00304             aperture, clip_near, clip_far);
00305 
00306     // B
00307     //camera = new Stereo_camera_f(0,340,750, 0,340,450, 0, 1, 0,
00308     //        aperture, clip_near, clip_far);
00309 
00310     // A
00311     //camera = new Stereo_camera_f(-20,240,-490, -20,240,-190, 0, 1, 0,
00312 }
00313 
00319 void clean_up()
00320 {
00321     if (surface_compare)
00322     {
00323         list<Surface_patch_f*>::iterator it;
00324         for (it = surface_compare->begin(); it != surface_compare->end(); it++)
00325         {
00326             delete *it;
00327         }
00328         delete surface_compare;
00329     }
00330 
00331     delete surface_scale;
00332     delete alternaria;
00333     delete model_compare;
00334     delete psf;
00335     delete imaging_d;
00336     delete psf_d;
00337     delete spore_d;
00338     delete apical_hypha_d;
00339     delete lateral_hypha_d;
00340     delete alt_d;
00341     delete camera;
00342     delete opts;
00343     gluDeleteQuadric(quad_fill);
00344     gluDeleteQuadric(quad_wire);
00345 }
00346 
00348 void reset()
00349 {
00350     object_scale = OBJECT_SCALE;
00351     aperture     = APERTURE;
00352     highlight    = 0;
00353     init_camera();
00354     init_modes();
00355 }
00356 
00358 void render_world_axis()
00359 {
00360     static GLfloat amb_dif[4] = {0, 0, 0, 1.0f};
00361 
00362     glMatrixMode(GL_MODELVIEW);
00363 
00364     glPushMatrix();
00365 
00366     float axis_length  = 100.0f;
00367     float arrow_radius = axis_length / 10.0f;
00368     float arrow_height = axis_length / 5.0f;
00369 
00370     /* X */
00371     amb_dif[0] = 0.9f;  amb_dif[1] = 1.0f;  amb_dif[2] = 0.3f;
00372     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, amb_dif);
00373     glPushMatrix();
00374       glRotatef(90, 0, 1.0f, 0);
00375       gluCylinder(quad_fill, 1, 1, axis_length - 0.5f*arrow_height, 8, 1);
00376     glPopMatrix();
00377     glPushMatrix();
00378       glTranslatef(axis_length - arrow_height, 0, 0);
00379       glRotatef(90, 0, 1.0f, 0);
00380       gluCylinder(quad_fill, arrow_radius, 0, arrow_height, 16, 8);
00381     glPopMatrix();
00382 
00383     /* Y */
00384     amb_dif[0] = 0.9f;  amb_dif[1] = 1.0f;  amb_dif[2] = 0.3f;
00385     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, amb_dif);
00386     glPushMatrix();
00387       glRotatef(-90, 1.0f, 0, 0);
00388       gluCylinder(quad_fill, 1, 1, axis_length - 0.5f*arrow_height, 8, 1);
00389     glPopMatrix();
00390     glPushMatrix();
00391       glTranslatef(0, axis_length - arrow_height, 0);
00392       glRotatef(-90, 1.0f, 0, 0);
00393       gluCylinder(quad_fill, arrow_radius, 0, arrow_height, 16, 8);
00394     glPopMatrix();
00395 
00396     /* Z */
00397     amb_dif[0] = 0.9f;  amb_dif[1] = 1.0f;  amb_dif[2] = 0.3f;
00398     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, amb_dif);
00399     gluCylinder(quad_fill, 1, 1, axis_length - 0.5f*arrow_height, 8, 1);
00400     glPushMatrix();
00401       glTranslatef(0, 0, axis_length - arrow_height);
00402       gluCylinder(quad_fill, arrow_radius, 0, arrow_height, 16, 8);
00403     glPopMatrix();
00404 
00405     glPopMatrix();
00406 }
00407 
00409 void render_focal_plane()
00410 {
00411     static GLfloat amb_dif[4] = {0.7f, 0.6f, 0.5f, 0.2f};
00412     GLboolean prev_blend;
00413     GLint     prev_blend_src;
00414     GLint     prev_blend_dst;
00415 
00416     if ((prev_blend = glIsEnabled(GL_BLEND)))
00417     {
00418         glGetIntegerv(GL_BLEND_SRC, &prev_blend_src);
00419         glGetIntegerv(GL_BLEND_DST, &prev_blend_dst);
00420     }
00421     else
00422     {
00423         glEnable(GL_BLEND);
00424     }
00425     glBlendFunc(GL_SRC_ALPHA, GL_SRC_ALPHA);
00426 
00427     glMatrixMode(GL_MODELVIEW);
00428 
00429     glPushMatrix();
00430     glLoadIdentity();
00431 
00432     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, amb_dif);
00433 
00434     float x = 200.0f;
00435     float y = 200.0f;
00436     float z = -camera->get_focal_length();
00437 
00438     glBegin(GL_POLYGON);
00439     glNormal3f( 0,  0, 1);
00440     glVertex3f( x,  y, z);
00441     glVertex3f(-x,  y, z);
00442     glVertex3f(-x, -y, z);
00443     glVertex3f( x, -y, z);
00444     glEnd();
00445 
00446     glPopMatrix();
00447 
00448     if (prev_blend)
00449     {
00450         glBlendFunc(prev_blend_src, prev_blend_dst);
00451     }
00452     else
00453     {
00454         glDisable(GL_BLEND);
00455     }
00456 }
00457 
00459 void render_model_compare()
00460 {
00461     if (!model_compare)
00462     {
00463         return;
00464     }
00465 
00466     model_compare->get_root()->recursively_draw_in_opengl(quad_wire, 
00467             object_scale);
00468 }
00469 
00471 void render_surface_compare()
00472 {
00473     static GLfloat amb_dif[4] = {0, 0, 0, 1.0f};
00474 
00475     if (!surface_compare)
00476     {
00477         return;
00478     }
00479 
00480     glMatrixMode(GL_MODELVIEW);
00481 
00482     glPushMatrix();
00483 
00484     glDisable(GL_LIGHT0);
00485     glEnable(GL_LIGHT2);
00486 
00487     /* Render the surface patches. */
00488     list<Surface_patch_f*>::iterator it;
00489     for (it = surface_compare->begin(); it != surface_compare->end(); it++)
00490     {
00491         const Surface_patch_f* patch = *it;
00492 
00493         amb_dif[0] = patch->albedo*0.78f; 
00494         amb_dif[1] = patch->albedo*0.6f; 
00495         amb_dif[2] = patch->albedo*0.2f;
00496 
00497         glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, amb_dif);
00498 
00499         glNormal3f(patch->normal->elts[0], patch->normal->elts[1],
00500                 patch->normal->elts[2]);
00501 
00502         glBegin(GL_POLYGON);
00503         for (int i = 0; i < 4; i++)
00504         {
00505             const Vector_f* point = patch->pts[ i ];
00506             glVertex3f(point->elts[0], point->elts[1], point->elts[2]);
00507         }
00508         glEnd();
00509     }
00510 
00511     glDisable(GL_LIGHT2);
00512     glEnable(GL_LIGHT0);
00513 
00514     glPopMatrix();
00515 }
00516 
00518 void render_scene()
00519 {
00520     glMatrixMode(GL_MODELVIEW);
00521 
00522     glPushMatrix();
00523 
00524     float x = object_scale*alternaria->get_root()->get_centroid()->elts[0];
00525     float y = object_scale*alternaria->get_root()->get_centroid()->elts[1];
00526     float z = object_scale*alternaria->get_root()->get_centroid()->elts[2];
00527     glTranslatef(-x, -y, -z);
00528 
00529     if (highlight)
00530     {
00531         glDisable(GL_LIGHT0);
00532         glEnable(GL_LIGHT1);
00533         highlight->draw_in_opengl(quad_fill, object_scale);
00534         glDisable(GL_LIGHT1);
00535         glEnable(GL_LIGHT0);
00536     }
00537 
00538     alternaria->get_root()->recursively_draw_in_opengl(quad_fill, object_scale);
00539 
00540     render_model_compare();
00541 
00542     render_surface_compare();
00543 
00544     glPopMatrix();
00545 }
00546 
00548 void display_glut_anaglyph()
00549 {
00550     /* Set the buffer for reading and writing. Using double buffering. */
00551     glDrawBuffer(GL_BACK);
00552     glReadBuffer(GL_BACK);
00553 
00554     /* Clear things */
00555     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT);
00556 
00557     /* Left camera filter. */
00558     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
00559     switch (glasses_type) 
00560     {
00561         case REDBLUE:
00562         case REDGREEN:
00563         case REDCYAN:
00564             glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE);
00565             break;
00566         case BLUERED:
00567             glColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_TRUE);
00568             break;
00569         case GREENRED:
00570             glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE);
00571             break;
00572         case CYANRED:
00573             glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_TRUE);
00574             break;
00575     } 
00576 
00577     /* Set the left camera projection. */
00578     camera->set_left_gl_projection();
00579 
00580     /* Set the camera model view. */
00581     camera->set_left_gl_modelview();
00582 
00583     /* Render the world axis. */
00584     if (modes.render_world_axis)
00585     {
00586         render_world_axis();
00587     }
00588 
00589     render_scene();
00590 
00591     /* Render the focal plane if in that mode. */
00592     if (modes.render_focal_plane)
00593     {
00594         render_focal_plane();
00595     }
00596 
00597     glFlush();
00598 
00599     glAccum(GL_LOAD, 0.5f);
00600     glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
00601 
00602     /* Right camera filter. */
00603     switch (glasses_type) 
00604     {
00605         case REDBLUE:
00606             glColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_TRUE);
00607             break;
00608         case REDGREEN:
00609             glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE);
00610             break;
00611         case REDCYAN:
00612             glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_TRUE);
00613             break;
00614         case BLUERED:
00615         case GREENRED:
00616         case CYANRED:
00617             glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE);
00618             break;
00619     } 
00620 
00621     /* Set the right camera projection. */
00622     camera->set_right_gl_projection();
00623 
00624     /* Set the camera model view. */
00625     camera->set_right_gl_modelview();
00626 
00627     /* Render the world axis. */
00628     if (modes.render_world_axis)
00629     {
00630         render_world_axis();
00631     }
00632 
00633     render_scene();
00634 
00635     /* Render the focal plane if in that mode. */
00636     if (modes.render_focal_plane)
00637     {
00638         render_focal_plane();
00639     }
00640 
00641     glFlush();
00642 
00644     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
00645 
00646     glAccum(GL_ACCUM, 0.5f);
00647     glAccum(GL_RETURN, 2.0f);
00648 }
00649 
00653 void display_glut_regular()
00654 {
00655     /* Set the buffer for writing. Using double buffering. */
00656     glDrawBuffer(GL_BACK);
00657     glReadBuffer(GL_BACK);
00658 
00659     /* Clear things */
00660     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00661 
00662     /* Set the camera projection. */
00663     camera->set_gl_projection();
00664 
00665     /* Set the camera model view. */
00666     camera->set_gl_modelview();
00667 
00668     /* Render the world axis. */
00669     if (modes.render_world_axis)
00670     {
00671         render_world_axis();
00672     }
00673 
00674     render_scene();
00675 
00676     /* Render the focal plane if in that mode. */
00677     if (modes.render_focal_plane)
00678     {
00679         render_focal_plane();
00680     }
00681 
00682     glFlush();
00683 }
00684 
00686 void display_glut()
00687 {
00688     static uint32_t N = 1;
00689 
00690     if (modes.anaglyph)
00691     {
00692         display_glut_anaglyph();
00693     }
00694     else
00695     {
00696         display_glut_regular();
00697     }
00698 
00699     glutSwapBuffers();
00700 
00701     if (modes.capture_view)
00702     {
00703         Stereo_camera_f::capture_gl_view(capture_fmt, N++);
00704         modes.capture_view = 0;
00705     }
00706 }
00707 
00709 void reshape_glut(int w, int h)
00710 {
00711     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00712     glViewport(0, 0, (GLsizei)w, (GLsizei)h); 
00713     view_width = w;
00714     view_height = h;
00715 }
00716 
00718 void keyboard_glut(unsigned char key, int a, int b)
00719 {
00720     float translate_delta = 10;
00721     float rotate_delta    = 10*JWSC_DEG_TO_RAD;
00722     float focal_length;
00723     float theta;
00724 
00725     Vector_f* v_tmp = 0;
00726 
00727     switch (key) {
00728         case 't':
00729             modes.translate_camera = 1;
00730             modes.rotate_camera = 0;
00731             break;
00732         case 'r':
00733             modes.rotate_camera = 1;
00734             modes.translate_camera = 0;
00735             break;
00736         case 'l':
00737             if (modes.translate_camera)
00738             {
00739                 const Vector_f* right = camera->get_u();
00740                 camera->translate(
00741                         translate_delta * right->elts[0],
00742                         translate_delta * right->elts[1],
00743                         translate_delta * right->elts[2]);
00744             }
00745             else if (modes.rotate_camera)
00746             {
00747                 camera->rotate(-rotate_delta, 0, 1, 0);
00748             }
00749             glutPostRedisplay();
00750             break;
00751         case 'h':
00752             if (modes.translate_camera)
00753             {
00754                 const Vector_f* right = camera->get_u();
00755                 camera->translate(
00756                         -translate_delta * right->elts[0],
00757                         -translate_delta * right->elts[1],
00758                         -translate_delta * right->elts[2]);
00759             }
00760             else if (modes.rotate_camera)
00761             {
00762                 camera->rotate(rotate_delta, 0, 1, 0);
00763             }
00764             glutPostRedisplay();
00765             break;
00766         case 'L':
00767             if (modes.translate_camera)
00768             {
00769                 const Vector_f* right = camera->get_u();
00770                 camera->translate(
00771                         translate_delta * right->elts[0],
00772                         translate_delta * right->elts[1],
00773                         translate_delta * right->elts[2]);
00774             }
00775             else if (modes.rotate_camera)
00776             {
00777                 copy_vector_f(&v_tmp, camera->get_prp());
00778                 multiply_vector_by_scalar_f(&v_tmp, v_tmp, -1);
00779                 camera->translate(v_tmp);
00780                 camera->rotate(rotate_delta, camera->get_v());
00781                 multiply_vector_by_scalar_f(&v_tmp, v_tmp, -1);
00782                 camera->translate(v_tmp);
00783             }
00784             glutPostRedisplay();
00785             break;
00786         case 'H':
00787             if (modes.translate_camera)
00788             {
00789                 const Vector_f* right = camera->get_u();
00790                 camera->translate(
00791                         -translate_delta * right->elts[0],
00792                         -translate_delta * right->elts[1],
00793                         -translate_delta * right->elts[2]);
00794             }
00795             else if (modes.rotate_camera)
00796             {
00797                 copy_vector_f(&v_tmp, camera->get_prp());
00798                 multiply_vector_by_scalar_f(&v_tmp, v_tmp, -1);
00799                 camera->translate(v_tmp);
00800                 camera->rotate(-rotate_delta, camera->get_v());
00801                 multiply_vector_by_scalar_f(&v_tmp, v_tmp, -1);
00802                 camera->translate(v_tmp);
00803             }
00804             glutPostRedisplay();
00805             break;
00806         case 'k':
00807             if (modes.translate_camera)
00808             {
00809                 const Vector_f* up = camera->get_v();
00810                 camera->translate(
00811                         translate_delta * up->elts[0],
00812                         translate_delta * up->elts[1],
00813                         translate_delta * up->elts[2]);
00814             }
00815             else if (modes.rotate_camera)
00816             {
00817                 camera->rotate(rotate_delta, camera->get_u());
00818             }
00819             glutPostRedisplay();
00820             break;
00821         case 'j':
00822             if (modes.translate_camera)
00823             {
00824                 const Vector_f* up = camera->get_v();
00825                 camera->translate(
00826                         -translate_delta * up->elts[0],
00827                         -translate_delta * up->elts[1],
00828                         -translate_delta * up->elts[2]);
00829             }
00830             else if (modes.rotate_camera)
00831             {
00832                 camera->rotate(-rotate_delta, camera->get_u());
00833             }
00834             glutPostRedisplay();
00835             break;
00836         case 'K':
00837             if (modes.translate_camera)
00838             {
00839                 const Vector_f* view = camera->get_n();
00840                 camera->translate(
00841                         -translate_delta * view->elts[0],
00842                         -translate_delta * view->elts[1],
00843                         -translate_delta * view->elts[2]);
00844             }
00845             else if (modes.rotate_camera)
00846             {
00847                 copy_vector_f(&v_tmp, camera->get_prp());
00848                 multiply_vector_by_scalar_f(&v_tmp, v_tmp, -1);
00849                 camera->translate(v_tmp);
00850                 camera->rotate(-rotate_delta, camera->get_u());
00851                 multiply_vector_by_scalar_f(&v_tmp, v_tmp, -1);
00852                 camera->translate(v_tmp);
00853             }
00854             glutPostRedisplay();
00855             break;
00856         case 'J':
00857             if (modes.translate_camera)
00858             {
00859                 const Vector_f* view = camera->get_n();
00860                 camera->translate(
00861                         translate_delta * view->elts[0],
00862                         translate_delta * view->elts[1],
00863                         translate_delta * view->elts[2]);
00864             }
00865             else if (modes.rotate_camera)
00866             {
00867                 copy_vector_f(&v_tmp, camera->get_prp());
00868                 multiply_vector_by_scalar_f(&v_tmp, v_tmp, -1);
00869                 camera->translate(v_tmp);
00870                 camera->rotate(rotate_delta, camera->get_u());
00871                 multiply_vector_by_scalar_f(&v_tmp, v_tmp, -1);
00872                 camera->translate(v_tmp);
00873             }
00874             glutPostRedisplay();
00875             break;
00876         case 'F':
00877             if (modes.focal_prp)
00878             {
00879                 focal_length = camera->get_focal_length() + 20;
00880                 camera->set_f_with_same_aperture_using_prp(focal_length);
00881             }
00882             else if (modes.focal_vrp)
00883             {
00884                 focal_length = camera->get_focal_length() + 20;
00885                 camera->set_f_with_same_aperture_using_vrp(focal_length);
00886             }
00887             glutPostRedisplay();
00888             break;
00889         case 'f':
00890             if (modes.focal_prp)
00891             {
00892                 focal_length = camera->get_focal_length();
00893                 if (focal_length >= 22)
00894                 {
00895                     focal_length -= 20;
00896                     camera->set_f_with_same_aperture_using_prp(focal_length);
00897                 }
00898             }
00899             else if (modes.focal_vrp)
00900             {
00901                 focal_length = camera->get_focal_length();
00902                 if (focal_length >= 22)
00903                 {
00904                     focal_length -= 20;
00905                     camera->set_f_with_same_aperture_using_vrp(focal_length);
00906                 }
00907             }
00908             glutPostRedisplay();
00909             break;
00910         case 'S':
00911             if (object_scale >= 2.99f)
00912             {
00913                 object_scale = 3.0f;
00914             }
00915             else
00916             {
00917                 object_scale += 0.01f;
00918             }
00919             glutPostRedisplay();
00920             break;
00921         case 's':
00922             if (object_scale > 0.01f)
00923             {
00924                 object_scale -= 0.01f;
00925             }
00926             glutPostRedisplay();
00927             break;
00928         case 'A':
00929             aperture += JWSC_PI_8;
00930             camera->set_aperture(aperture);
00931             glutPostRedisplay();
00932             break;
00933         case 'a':
00934             theta = aperture - JWSC_PI_8;
00935             if (theta >= 0)
00936             {
00937                 aperture = theta;
00938                 camera->set_aperture(theta);
00939             }
00940             glutPostRedisplay();
00941             break;
00942         case 'P':
00943             if (modes.clip_near)
00944             {
00945                 clip_near += 1;
00946             }
00947             else
00948             {
00949                 clip_far += 1;
00950             }
00951             camera->set_clipping(clip_near, clip_far);
00952             glutPostRedisplay();
00953             break;
00954         case 'p':
00955             if (clip_near > 0 && clip_far > 0)
00956             {
00957                 if (modes.clip_near)
00958                 {
00959                     clip_near -= 1;
00960                 }
00961                 else
00962                 {
00963                     clip_far -= 1;
00964                 }
00965                 camera->set_clipping(clip_near, clip_far);
00966                 glutPostRedisplay();
00967             }
00968             break;
00969         case 'c':
00970             modes.capture_view = 1;
00971             glutPostRedisplay();
00972             break;
00973         case 'o':
00974             reset();
00975             glutPostRedisplay();
00976             break;
00977         case 'q':
00978             std::cerr << "VRP: " 
00979                       << camera->get_vrp()->elts[0] << ", "
00980                       << camera->get_vrp()->elts[1] << ", "
00981                       << camera->get_vrp()->elts[2] << '\n';
00982             std::cerr << "PRP: " 
00983                       << camera->get_prp()->elts[0] << ", "
00984                       << camera->get_prp()->elts[1] << ", "
00985                       << camera->get_prp()->elts[2] << '\n';
00986             //free_vector_f(v_tmp);
00987             //clean_up();
00988             exit(EXIT_SUCCESS);
00989     }
00990 
00991     free_vector_f(v_tmp);
00992 }
00993 
00995 void mouse_glut(int button, int state, int x, int y)
00996 {
00997     Vector_f* near_pt  = 0;
00998     Vector_f* far_pt   = 0;
00999     Vector_f* isect_pt = 0;
01000 
01001     if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
01002     {
01003         float u = (float)x - (float)view_width / 2.0f;
01004         float v = (float)view_height / 2.0f - (float)y;
01005         camera->get_image_pt_on_near_clipping_plane(&near_pt, u, v);
01006         camera->get_image_pt_on_far_clipping_plane(&far_pt, u, v);
01007 
01008         // Undo the transformation of the view in render_scene().
01009         multiply_vector_by_scalar_f(&near_pt, near_pt, 1.0f/object_scale);
01010         multiply_vector_by_scalar_f(&far_pt, far_pt, 1.0f/object_scale);
01011 
01012         float x = alternaria->get_root()->get_centroid()->elts[0];
01013         float y = alternaria->get_root()->get_centroid()->elts[1];
01014         float z = alternaria->get_root()->get_centroid()->elts[2];
01015         Vector_f* V = 0;
01016         create_vector_f(&V, 3);
01017         V->elts[0] = x; V->elts[1] = y; V->elts[2] = z;
01018         add_vectors_f(&near_pt, near_pt, V);
01019         add_vectors_f(&far_pt, far_pt, V);
01020         free_vector_f(V);
01021 
01022         highlight = 0;
01023         float t_min = 1.0f;
01024 
01025         vector<Structure*>* structs = alternaria->get_root()->get_descendants();
01026 
01027         for (size_t i = 0; i < structs->size(); i++)
01028         {
01029             float t = structs->at(i)->get_intersection(&isect_pt, 1, near_pt, 
01030                     far_pt);
01031             if (t >= 0 && t <= t_min)
01032             {
01033                 t_min = t;
01034                 highlight = structs->at(i);
01035                 highlight->print();
01036             }
01037         }
01038 
01039         delete structs;
01040 
01041         glutPostRedisplay();
01042     }
01043 
01044     free_vector_f(near_pt);
01045     free_vector_f(far_pt);
01046     free_vector_f(isect_pt);
01047 }
01048 
01050 void main_menu_glut(int id)
01051 {
01052     switch (id)
01053     {
01054         case 0:
01055             modes.capture_view = 1;
01056             glutPostRedisplay();
01057             break;
01058         case 1:
01059             reset();
01060             glutPostRedisplay();
01061             break;
01062         case 2:
01063             exit(EXIT_SUCCESS);
01064     }
01065 }
01066 
01068 void option_menu_glut(int id)
01069 {
01070     switch (id)
01071     {
01072         case 0:
01073             modes.anaglyph = !modes.anaglyph;
01074             glutPostRedisplay();
01075             break;
01076         case 1:
01077             modes.render_focal_plane = !modes.render_focal_plane;
01078             glutPostRedisplay();
01079             break;
01080         case 2:
01081             modes.render_world_axis = !modes.render_world_axis;
01082             glutPostRedisplay();
01083             break;
01084     }
01085 }
01086 
01088 void navigation_menu_glut(int id)
01089 {
01090     switch (id)
01091     {
01092         case 0:
01093             modes.rotate_camera    = true;
01094             modes.translate_camera = false;
01095             break;
01096         case 1:
01097             modes.rotate_camera    = false;
01098             modes.translate_camera = true;
01099             break;
01100         case 2:
01101             modes.rotate_camera    = false;
01102             modes.translate_camera = false;
01103             break;
01104     }
01105 }
01106 
01108 void focal_length_menu_glut(int id)
01109 {
01110     switch (id)
01111     {
01112         case 0:
01113             modes.focal_prp = true;
01114             modes.focal_vrp = false;
01115             break;
01116         case 1:
01117             modes.focal_prp = false;
01118             modes.focal_vrp = true;
01119             break;
01120     }
01121 }
01122 
01124 void clipping_menu_glut(int id)
01125 {
01126     switch (id)
01127     {
01128         case 0:
01129             modes.clip_near = true;
01130             break;
01131         case 1:
01132             modes.clip_near = false;
01133             break;
01134     }
01135 }
01136 
01138 void init_glut(int argc, char** argv)
01139 {
01140     glutInit(&argc, argv);
01141     glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_ACCUM
01142                                     | GLUT_ALPHA);
01143     glutInitWindowSize(view_width, view_height);
01144     glutCreateWindow("Alternaria Structure Tester");
01145     glutDisplayFunc(display_glut); 
01146     glutReshapeFunc(reshape_glut);
01147     glutKeyboardFunc(keyboard_glut);
01148     glutMouseFunc(mouse_glut);
01149 
01150     int navigation = glutCreateMenu(navigation_menu_glut);
01151     glutAddMenuEntry("Rotate Camera", 0);
01152     glutAddMenuEntry("Translate Camera", 1);
01153     glutAddMenuEntry("Modify Structure", 2);
01154 
01155     int focal_length = glutCreateMenu(focal_length_menu_glut);
01156     glutAddMenuEntry("PRP", 0);
01157     glutAddMenuEntry("VRP", 1);
01158 
01159     int clipping = glutCreateMenu(clipping_menu_glut);
01160     glutAddMenuEntry("Near", 0);
01161     glutAddMenuEntry("Far", 1);
01162 
01163     int options = glutCreateMenu(option_menu_glut);
01164     glutAddMenuEntry("Anaglyph", 0);
01165     glutAddMenuEntry("Focal Plane", 1);
01166     glutAddMenuEntry("Axis", 2);
01167 
01168     glutCreateMenu(main_menu_glut);
01169     glutAddSubMenu("Navigation", navigation);
01170     glutAddSubMenu("Focal Length", focal_length);
01171     glutAddSubMenu("Clipping", clipping);
01172     glutAddSubMenu("Options", options);
01173     glutAddMenuEntry("Capture", 1);
01174     glutAddMenuEntry("Reset", 2);
01175     glutAddMenuEntry("Quit", 3);
01176 
01177     glutAttachMenu(GLUT_RIGHT_BUTTON);
01178 }
01179 
01181 void init_gl() 
01182 {
01183     glEnable(GL_DEPTH_TEST);
01184     glEnable(GL_NORMALIZE);
01185     glEnable(GL_LIGHTING);
01186 
01187     static GLfloat base_amb[] = {0.0f, 0.0f, 0.0f, 0.0f};
01188     glLightModelfv(GL_LIGHT_MODEL_AMBIENT, base_amb);
01189 
01190     static GLfloat ambient0  [] = {0.2f, 0.2f, 0.2f, 1.0f};
01191     static GLfloat diffuse0  [] = {0.8f, 0.8f, 0.8f, 1.0f};
01192     static GLfloat specular0 [] = {0.9f, 0.9f, 0.9f, 1.0f};
01193     static GLfloat direction0[] = {500.0f, 500.0f, 2000.0f, 1.0f};
01194 
01195     glEnable(GL_LIGHT0);
01196     glLightfv(GL_LIGHT0, GL_AMBIENT, ambient0);
01197     glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse0);
01198     glLightfv(GL_LIGHT0, GL_SPECULAR, specular0);
01199     glLightfv(GL_LIGHT0, GL_POSITION, direction0);
01200 
01201     static GLfloat ambient1  [] = {0.1f, 0.1f, 0.1f, 1.0f};
01202     static GLfloat diffuse1  [] = {0.4f, 0.4f, 0.4f, 1.0f};
01203     static GLfloat specular1 [] = {0.5f, 0.5f, 0.5f, 1.0f};
01204     static GLfloat direction1[] = {500.0f, 500.0f, 2000.0f, 1.0f};
01205 
01206     glDisable(GL_LIGHT1);
01207     glLightfv(GL_LIGHT1, GL_AMBIENT, ambient1);
01208     glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse1);
01209     glLightfv(GL_LIGHT1, GL_SPECULAR, specular1);
01210     glLightfv(GL_LIGHT1, GL_POSITION, direction1);
01211 
01212     static GLfloat ambient2  [] = {0.2f, 0.2f, 0.2f, 1.0f};
01213     static GLfloat diffuse2  [] = {0.9f, 0.9f, 0.9f, 1.0f};
01214     static GLfloat specular2 [] = {0.0f, 0.0f, 0.0f, 1.0f};
01215     static GLfloat direction2[] = {500.0f, 500.0f, 2000.0f, 1.0f};
01216 
01217     glDisable(GL_LIGHT2);
01218     glLightfv(GL_LIGHT2, GL_AMBIENT, ambient2);
01219     glLightfv(GL_LIGHT2, GL_DIFFUSE, diffuse2);
01220     glLightfv(GL_LIGHT2, GL_SPECULAR, specular2);
01221     glLightfv(GL_LIGHT2, GL_POSITION, direction2);
01222 
01223 
01224     if (!quad_fill)
01225     {
01226         quad_fill = gluNewQuadric();
01227         gluQuadricDrawStyle(quad_fill, GLU_FILL);
01228     }
01229 
01230     if (!quad_wire)
01231     {
01232         quad_wire = gluNewQuadric();
01233         gluQuadricDrawStyle(quad_wire, GLU_LINE);
01234     }
01235 
01236     glLineWidth(1.0);
01237     glPointSize(1.0);
01238     glClearColor(0.0, 0.0, 0.0, 0.0);
01239     glClearAccum(0.0, 0.0, 0.0, 0.0);
01240 
01241     glViewport(0, 0, view_width, view_height);
01242 }
01243 
01245 void print_usage(void)
01246 {
01247     cerr << "usage: alternaria_viewer OPTIONS [model]\n";
01248     cerr << "where OPTIONS is one or more of the following:\n";
01249     opts->print(cerr, 30);
01250 }
01251 
01253 void process_help_opt(void)
01254 {   
01255     print_usage();
01256     exit(EXIT_SUCCESS);
01257 }
01258 
01260 void process_version_opt(void)
01261 {
01262     cout << ALTERNARIA_PACKAGE_STRING << "\n";
01263     exit(EXIT_SUCCESS);
01264 }
01265 
01267 void process_view_size_opt(const char* arg) throw (Arg_error)
01268 {
01269     int32_t w, h;
01270 
01271     if (!arg)
01272     {
01273         throw Arg_error("Option 'view-size' requires an argument");
01274     }
01275     if (sscanf(arg, "%d,%d", &w, &h) != 2)
01276     {
01277         throw Arg_error("Option 'view-size' has format width,height");
01278     }
01279     if (w <= 0 || h <= 0)
01280     {
01281         throw Arg_error("Option 'view-size' must have width,height > 0");
01282     }
01283     view_width = (uint32_t)w;
01284     view_height = (uint32_t)h;
01285 }
01286 
01288 void process_glasses_opt(const char* arg) throw (Arg_error)
01289 {
01290     if (!arg)
01291     {
01292         throw Arg_error("Option 'glasses' requires an argument");
01293     }
01294     if (strcmp("red-blue", arg) == 0)
01295         glasses_type = REDBLUE;
01296     else if (strcmp("red-green", arg) == 0)
01297         glasses_type = REDGREEN;
01298     else if (strcmp("red-cyan", arg) == 0)
01299         glasses_type = REDCYAN;
01300     else if (strcmp("blue-red", arg) == 0)
01301         glasses_type = BLUERED;
01302     else if (strcmp("green-red", arg) == 0)
01303         glasses_type = GREENRED;
01304     else if (strcmp("cyan-red", arg) == 0)
01305         glasses_type = CYANRED;
01306     else
01307     {
01308         throw Arg_error("Invalid 'glasses' type");
01309     }
01310 }
01311 
01313 void process_capture_opt(const char* arg) throw (Arg_error)
01314 {
01315     if (!arg)
01316     {
01317         throw Arg_error("Option 'capture' requires an argument");
01318     }
01319     capture_fmt = arg;
01320 }
01321 
01323 void process_surf_compare_opt(const char* arg) throw (Arg_error)
01324 {
01325     if (!arg)
01326     {
01327         throw Arg_error("Option 'surf-compare' requires an argument");
01328     }
01329     surface_compare_fname = arg;
01330 }
01331 
01333 void process_surf_scale_opt(const char* arg) throw (Arg_error)
01334 {
01335     float x, y, z;
01336 
01337     if (!arg)
01338     {
01339         throw Arg_error("Option 'surf-scale' requires an argument");
01340     }
01341     if (sscanf(arg, "%f,%f,%f", &x, &y, &z) != 3)
01342     {
01343         throw Arg_error("Option 'surf-scale' has format x,y,z");
01344     }
01345     try
01346     {
01347         surface_scale->set(x, y, z);
01348     }
01349     catch (Arg_error e)
01350     {
01351         ostringstream ost;
01352         ost << "Option 'surf-scale': " << e.get_msg();
01353         throw Arg_error(ost.str());
01354     }
01355 }
01356 
01358 void process_patch_size_opt(const char* arg) throw (Arg_error)
01359 {
01360     if (!arg)
01361     {
01362         throw Arg_error("Option 'patch-size' requires an argument");
01363     }
01364     if (sscanf(arg, "%f", &surface_patch_size) != 1 || surface_patch_size <= 0)
01365     {
01366         throw Arg_error("Option 'patch-size' must be > 0");
01367     }
01368 }
01369 
01371 void process_model_compare_opt(const char* arg) throw (Arg_error)
01372 {
01373     if (!arg)
01374     {
01375         throw Arg_error("Option 'model-compare' requires an argument");
01376     }
01377     model_compare_fname = arg;
01378 }
01379 
01381 void init_options()
01382 {
01383     using jwscxx::base::Option_no_arg;
01384     using jwscxx::base::Option_with_arg;
01385 
01386     const char* l_name;
01387     const char* desc;
01388 
01389     opts = new Options();
01390 
01391     l_name = "help";
01392     desc   = "Program usage";
01393     opts->add(new Option_no_arg('h', l_name, desc, process_help_opt));
01394 
01395     l_name = "version";
01396     desc   = "Program version.";
01397     opts->add(new Option_no_arg('v', l_name, desc, process_version_opt));
01398 
01399     l_name = "view-size";
01400     desc   = "Interactive window View size with format width,height. Default is 400,400.";
01401     opts->add(new Option_with_arg(0, l_name, desc, process_view_size_opt));
01402 
01403     l_name = "glasses";
01404     desc   = "Type of colored glasses for anaglyph mode in the interactive window. Possible left-right filter types include include red-blue, red-green, red-cyan, blue-red, green-red, cyan-red. Default is cyan-red.";
01405     opts->add(new Option_with_arg(0, l_name, desc, process_glasses_opt));
01406 
01407     l_name = "capture";
01408     desc   = "Printf-formatted file write captured view images to.";
01409     opts->add(new Option_with_arg(0, l_name, desc, process_capture_opt));
01410 
01411     l_name = "model-compare";
01412     desc   = "Alternaria model to compare with. Rendered as a wireframe.";
01413     opts->add(new Option_with_arg(0, l_name, desc, process_model_compare_opt));
01414 
01415     l_name = "surf-compare";
01416     desc   = "Alternaria surface to compare with.";
01417     opts->add(new Option_with_arg(0, l_name, desc, process_surf_compare_opt));
01418 
01419     l_name = "surf-scale";
01420     desc   = "Number of world units per image pixel. Has format x,y,z.";
01421     opts->add(new Option_with_arg(0, l_name, desc, process_surf_scale_opt));
01422 
01423     l_name = "patch-size";
01424     desc   = "Surface patch size. Must be > 0.";
01425     opts->add(new Option_with_arg(0, l_name, desc, process_patch_size_opt));
01426 }
01427 
01428 
01430 void init_densities()
01431 {
01432     spore_d->set_centroid_x(CENTROID_MIN, CENTROID_MAX);
01433     spore_d->set_centroid_y(CENTROID_MIN, CENTROID_MAX);
01434     spore_d->set_centroid_z(CENTROID_MIN, CENTROID_MAX);
01435     spore_d->set_length(LENGTH_MU, LENGTH_SIGMA, LENGTH_MIN, LENGTH_MAX);
01436     spore_d->set_width(WIDTH_MU, WIDTH_SIGMA, WIDTH_MIN, WIDTH_MAX);
01437     spore_d->set_theta(THETA_MU, THETA_SIGMA, THETA_MIN, THETA_MAX);
01438     spore_d->set_psi(PSI_MIN, PSI_MAX);
01439     spore_d->set_opacity(OPACITY_MU, OPACITY_SIGMA, OPACITY_MIN, OPACITY_MAX);
01440 
01441     apical_hypha_d->set_centroid_x(CENTROID_MIN, CENTROID_MAX);
01442     apical_hypha_d->set_centroid_y(CENTROID_MIN, CENTROID_MAX);
01443     apical_hypha_d->set_centroid_z(CENTROID_MIN, CENTROID_MAX);
01444     apical_hypha_d->set_length(LENGTH_MU, LENGTH_SIGMA, LENGTH_MIN, LENGTH_MAX);
01445     apical_hypha_d->set_width(WIDTH_MU, WIDTH_SIGMA, WIDTH_MIN, WIDTH_MAX);
01446     apical_hypha_d->set_theta(THETA_MU, THETA_SIGMA, THETA_MIN, THETA_MAX);
01447     apical_hypha_d->set_psi(PSI_MIN, PSI_MAX);
01448     apical_hypha_d->set_opacity(OPACITY_MU, OPACITY_SIGMA, OPACITY_MIN, OPACITY_MAX);
01449     apical_hypha_d->set_dwidth(DWIDTH_SIGMA, DWIDTH_MIN, DWIDTH_MAX);
01450 
01451     lateral_hypha_d->set_centroid_x(CENTROID_MIN, CENTROID_MAX);
01452     lateral_hypha_d->set_centroid_y(CENTROID_MIN, CENTROID_MAX);
01453     lateral_hypha_d->set_centroid_z(CENTROID_MIN, CENTROID_MAX);
01454     lateral_hypha_d->set_length(LENGTH_MU, LENGTH_SIGMA, LENGTH_MIN, LENGTH_MAX);
01455     lateral_hypha_d->set_width(WIDTH_MU, WIDTH_SIGMA, WIDTH_MIN, WIDTH_MAX);
01456     lateral_hypha_d->set_theta(THETA_MU, THETA_SIGMA, THETA_MIN, THETA_MAX);
01457     lateral_hypha_d->set_psi(PSI_MIN, PSI_MAX);
01458     lateral_hypha_d->set_opacity(OPACITY_MU, OPACITY_SIGMA, OPACITY_MIN, OPACITY_MAX);
01459     lateral_hypha_d->set_lat_dist(DIST_MU, DIST_SIGMA, DIST_MIN, DIST_MAX);
01460 }
01461 
01462 
01464 void read_model_compare() throw (Exception)
01465 {
01466     if (!model_compare_fname)
01467     {
01468         return;
01469     }
01470 
01471     assert(model_compare == 0);
01472 
01473     model_compare = new Alternaria(model_compare_fname, alt_d, spore_d, 
01474             apical_hypha_d, lateral_hypha_d, lateral_hypha_d);
01475 }
01476 
01477 
01479 void read_surface_compare() throw (Exception)
01480 {
01481     if (!surface_compare_fname)
01482     {
01483         return;
01484     }
01485 
01486     assert(surface_compare == 0);
01487 
01488     Surface_point_f* points = 0;
01489     uint32_t num_pts;
01490     Error* err;
01491     if ((err = read_surface_points_f(&points, &num_pts, 
01492                     surface_compare_fname)))
01493     {
01494         ostringstream ost;
01495         ost << surface_compare_fname << ": " << err->msg;
01496         free(err);
01497         throw Arg_error(ost.str());
01498     }
01499 
01500     if (num_pts == 0)
01501     {
01502         ostringstream ost;
01503         ost << surface_compare_fname << ": doesn't contain any surface points";
01504         throw Arg_error(ost.str());
01505     }
01506 
01507 
01508     surface_compare = new list<Surface_patch_f*>();
01509 
01510     for (uint32_t i = 0; i < num_pts; i++)
01511     {
01512         Surface_patch_f* patch = 0;
01513         create_surface_patch_f(&patch, &(points[ i ]), 
01514                 surface_patch_size, surface_scale->get_x(), 
01515                 surface_scale->get_y(), surface_scale->get_z());
01516         surface_compare->push_back(patch);
01517     }
01518 
01519     free(points);
01520 }
01521 
01522 
01523 
01524 
01526 int main(int argc, char** argv)
01527 {
01528     init_options();
01529 
01530     try
01531     {
01532         surface_scale   = new Imaging_scale();
01533         spore_d         = new Spore_density();
01534         apical_hypha_d  = new Apical_hypha_density();
01535         lateral_hypha_d = new Lateral_hypha_density();
01536         alt_d           = new Alternaria_density();
01537 
01538         init_densities();
01539 
01540         int nargs = opts->process(argc, argv); 
01541 
01542         if (nargs < 2)
01543         {
01544             throw Arg_error("No input model");
01545         }
01546 
01547         alternaria = new Alternaria(argv[ argc - nargs + 1], alt_d, spore_d,
01548                 apical_hypha_d, lateral_hypha_d, lateral_hypha_d);
01549 
01550         read_model_compare();
01551         read_surface_compare();
01552 
01553         init_glut(argc, argv);
01554         init_gl();
01555         init_camera();
01556         init_modes();
01557 
01558         glutMainLoop();
01559     }
01560     catch (Exception e)
01561     {
01562         cerr << "alternaria_viewer: ";
01563         e.print();
01564     }
01565 
01566     return EXIT_FAILURE;
01567 }