JWS C++ Library
C++ language utility library
camera.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 
00049 #include <jwsc++/config.h>
00050 
00051 #include <iostream>
00052 #include <sstream>
00053 #include <typeinfo>
00054 #include <cstring>
00055 #include <cmath>
00056 #include <cassert>
00057 
00058 #if defined JWSCXX_HAVE_OPENGL
00059 #include <GL/gl.h>
00060 #elif defined JWSCXX_HAVE_OPENGL_FRAMEWORK
00061 #include <OpenGL/gl.h>
00062 #endif
00063 
00064 #include <jwsc/base/file_io.h>
00065 #include <jwsc/math/constants.h>
00066 #include <jwsc/vector/vector.h>
00067 #include <jwsc/vector/vector_math.h>
00068 #include <jwsc/matrix/matrix.h>
00069 #include <jwsc/matrix/matrix_math.h>
00070 #include <jwsc/image/image.h>
00071 #include <jwsc/image/image_io.h>
00072 
00073 #include <jwsc++/base/exception.h>
00074 #include <jwsc++/base/readable.h>
00075 #include <jwsc++/graphics/camera.h>
00076 
00077 #ifdef JWSCXX_HAVE_DMALLOC
00078 #include <dmalloc.h>
00079 #endif
00080 
00081 
00082 using namespace jwsc;
00083 using namespace jwscxx::base;
00084 using namespace jwscxx::graphics;
00085 
00086 
00104 Camera_f::Camera_f
00105 (
00106     float focal_pt_x,
00107     float focal_pt_y,
00108     float focal_pt_z,
00109     float ref_pt_x,
00110     float ref_pt_y,
00111     float ref_pt_z,
00112     float up_x,
00113     float up_y,
00114     float up_z,
00115     float aperture, 
00116     float clip_near, 
00117     float clip_far
00118 )
00119 throw (Arg_error)
00120 {
00121     if (aperture <= 0)
00122     {
00123         throw Arg_error("Aperture <= 0");
00124     }
00125     this->aperture = aperture;
00126 
00127     if (clip_near < 0 || clip_far <= 0 || clip_near > clip_far)
00128     {
00129         throw Arg_error("Invalid clipping planes");
00130     }
00131     near = clip_near;
00132     far  = clip_far;
00133 
00134     prp     = 0;
00135     vrp     = 0;
00136     n       = 0;
00137     v       = 0;
00138     u       = 0;
00139     R_phi   = 0;
00140     R_theta = 0;
00141     R_psi   = 0;
00142     R       = 0;
00143 
00144     look_at(focal_pt_x, focal_pt_y, focal_pt_z, ref_pt_x, ref_pt_y, ref_pt_z,
00145             up_x, up_y, up_z);
00146 
00147     float tan_theta = std::tan(JWSC_DEG_TO_RAD * aperture / 2.0f);
00148     half_near_height = clip_near * tan_theta;
00149 }
00150 
00151 
00163 Camera_f::Camera_f
00164 (
00165     const jwsc::Vector_f* focal_pt,
00166     const jwsc::Vector_f* ref_pt,
00167     const jwsc::Vector_f* up,
00168     float           aperture, 
00169     float           clip_near, 
00170     float           clip_far
00171 )
00172 throw (Arg_error)
00173 {
00174     if (aperture <= 0)
00175     {
00176         throw Arg_error("Aperture <= 0");
00177     }
00178     this->aperture = aperture;
00179 
00180     if (clip_near < 0 || clip_far <= 0 || clip_near > clip_far)
00181     {
00182         throw Arg_error("Invalid clipping planes");
00183     }
00184     near = clip_near;
00185     far  = clip_far;
00186 
00187     prp     = 0;
00188     vrp     = 0;
00189     n       = 0;
00190     v       = 0;
00191     u       = 0;
00192     R_phi   = 0;
00193     R_theta = 0;
00194     R_psi   = 0;
00195     R       = 0;
00196 
00197     look_at(focal_pt, ref_pt, up);
00198 
00199     float tan_theta = std::tan(JWSC_DEG_TO_RAD * aperture / 2.0f);
00200     half_near_height = clip_near * tan_theta;
00201 }
00202 
00203 
00205 Camera_f::Camera_f(const Camera_f& c)
00206 {
00207     prp     = 0;
00208     vrp     = 0;
00209     n       = 0;
00210     v       = 0;
00211     u       = 0;
00212     R_phi   = 0;
00213     R_theta = 0;
00214     R_psi   = 0;
00215     R       = 0;
00216 
00217     *this = c;
00218 }
00219 
00220 
00242 Camera_f::Camera_f(const char* fname) throw (jwscxx::base::Arg_error,
00243         jwscxx::base::IO_error)
00244 {
00245     vrp     = 0;
00246     prp     = 0;
00247     u       = 0;
00248     v       = 0;
00249     n       = 0;
00250     R_phi   = 0;
00251     R_theta = 0;
00252     R_psi   = 0;
00253     R       = 0;
00254 
00255     jwscxx::base::Readable::read(fname);
00256 }
00257 
00258 
00280 Camera_f::Camera_f(std::istream& in) throw (jwscxx::base::Arg_error,
00281         jwscxx::base::IO_error)
00282 {
00283     vrp     = 0;
00284     prp     = 0;
00285     u       = 0;
00286     v       = 0;
00287     n       = 0;
00288     R_phi   = 0;
00289     R_theta = 0;
00290     R_psi   = 0;
00291     R       = 0;
00292 
00293     read(in);
00294 }
00295 
00296 
00297 Camera_f::~Camera_f()
00298 {
00299     free_vector_f(vrp);
00300     free_vector_f(prp);
00301     free_vector_f(u);
00302     free_vector_f(v);
00303     free_vector_f(n);
00304     free_matrix_f(R_phi);
00305     free_matrix_f(R_theta);
00306     free_matrix_f(R_psi);
00307     free_matrix_f(R);
00308 }
00309 
00310 
00318 Camera_f& Camera_f::operator=(const Camera_f &c)
00319 {
00320     copy_vector_f(&vrp, c.vrp);
00321     copy_vector_f(&prp, c.prp);
00322     copy_vector_f(&u, c.u);
00323     copy_vector_f(&v, c.v);
00324     copy_vector_f(&n, c.n);
00325 
00326     aperture = c.aperture;
00327     focal_length = c.focal_length;
00328     half_focal_height = c.half_focal_height;
00329     half_near_height = c.half_near_height;
00330     near = c.near;
00331     far = c.far;
00332 
00333     if (c.R_phi   != 0)  copy_matrix_f(&R_phi, c.R_phi);
00334     if (c.R_theta != 0)  copy_matrix_f(&R_theta, c.R_theta);
00335     if (c.R_psi   != 0)  copy_matrix_f(&R_psi, c.R_psi);
00336     if (c.R       != 0)  copy_matrix_f(&R, c.R);
00337 
00338     return *this;
00339 }
00340 
00341 
00343 Camera_f* Camera_f::clone() const
00344 {
00345     return new Camera_f(*this);
00346 }
00347 
00348 
00349 const jwsc::Vector_f* Camera_f::get_u() const 
00350 { 
00351     return (const jwsc::Vector_f*)u; 
00352 }
00353 
00354 
00355 const jwsc::Vector_f* Camera_f::get_v() const 
00356 { 
00357     return (const jwsc::Vector_f*)v; 
00358 }
00359 
00360 
00364 const jwsc::Vector_f* Camera_f::get_n() const 
00365 { 
00366     return (const jwsc::Vector_f*)n; 
00367 }
00368 
00369 
00370 const jwsc::Vector_f* Camera_f::get_prp() const 
00371 { 
00372     return (const jwsc::Vector_f*)prp; 
00373 }
00374 
00375 
00376 const jwsc::Vector_f* Camera_f::get_vrp() const 
00377 { 
00378     return (const jwsc::Vector_f*)vrp; 
00379 }
00380 
00381 
00382 float Camera_f::get_clipping_near() const 
00383 { 
00384     return near; 
00385 }
00386 
00387 
00388 float Camera_f::get_clipping_far() const 
00389 { 
00390     return far; 
00391 }
00392 
00393 
00394 float Camera_f::get_focal_length() const 
00395 { 
00396     return focal_length; 
00397 }
00398 
00399 
00400 float Camera_f::get_aperture() const 
00401 { 
00402     return aperture; 
00403 }
00404 
00405 
00407 float Camera_f::get_half_focal_height() const
00408 {
00409     return half_focal_height;
00410 }       
00411 
00412 
00418 void Camera_f::set_aperture(float aperture) throw (Arg_error)
00419 {
00420     if (aperture <= 0)
00421     {
00422         throw Arg_error("Aperture <= 0");
00423     }
00424     this->aperture = aperture;
00425 
00426     float tan_theta = std::tan(JWSC_DEG_TO_RAD * aperture / 2.0f);
00427     half_near_height = near * tan_theta;
00428     half_focal_height = focal_length * tan_theta;
00429 }
00430 
00431 
00440 void Camera_f::set_f_with_new_aperture_using_prp(float f) throw (Arg_error)
00441 {
00442     if (f <= 0)
00443     {
00444         throw Arg_error("Focal length <= 0");
00445     }
00446 
00447     focal_length = f;
00448 
00449     multiply_vector_by_scalar_f(&prp, n, focal_length);
00450     add_vectors_f(&prp, prp, vrp);
00451 
00452     half_near_height = near * half_focal_height / focal_length;
00453 
00454     float theta = std::atan(half_focal_height / focal_length);
00455     aperture = JWSC_RAD_TO_DEG * 2.0f * theta;
00456 }
00457 
00458 
00467 void Camera_f::set_f_with_same_aperture_using_prp(float f) throw (Arg_error)
00468 {
00469     if (f <= 0)
00470     {
00471         throw Arg_error("Focal length <= 0");
00472     }
00473 
00474     focal_length = f;
00475 
00476     multiply_vector_by_scalar_f(&prp, n, focal_length);
00477     add_vectors_f(&prp, prp, vrp);
00478 
00479     float tan_theta = std::tan(JWSC_DEG_TO_RAD * aperture / 2.0f);
00480     half_focal_height = focal_length * tan_theta;
00481 }
00482 
00483 
00492 void Camera_f::set_f_with_new_aperture_using_vrp(float f) throw (Arg_error)
00493 {
00494     if (f <= 0)
00495     {
00496         throw Arg_error("Focal length <= 0");
00497     }
00498 
00499     focal_length = f;
00500 
00501     multiply_vector_by_scalar_f(&vrp, n, -focal_length);
00502     add_vectors_f(&vrp, vrp, prp);
00503 
00504     half_near_height = near * half_focal_height / focal_length;
00505 
00506     float theta = std::atan(half_focal_height / focal_length);
00507     aperture = JWSC_RAD_TO_DEG * 2.0f * theta;
00508 }
00509 
00510 
00519 void Camera_f::set_f_with_same_aperture_using_vrp(float f) throw (Arg_error)
00520 {
00521     if (f <= 0)
00522     {
00523         throw Arg_error("Focal length <= 0");
00524     }
00525 
00526     focal_length = f;
00527 
00528     multiply_vector_by_scalar_f(&vrp, n, -focal_length);
00529     add_vectors_f(&vrp, vrp, prp);
00530 
00531     float tan_theta = std::tan(JWSC_DEG_TO_RAD * aperture / 2.0f);
00532     half_focal_height = focal_length * tan_theta;
00533 }
00534 
00535 
00542 void Camera_f::set_clipping(float clip_near, float clip_far) throw (Arg_error)
00543 {
00544     if (clip_near < 0 || clip_far <= 0 || clip_near > clip_far)
00545     {
00546         throw Arg_error("Invalid clipping planes");
00547     }
00548     near = clip_near;
00549     far  = clip_far;
00550 
00551     float tan_theta   = std::tan(JWSC_DEG_TO_RAD * aperture / 2.0f);
00552     half_near_height  = near * tan_theta;
00553 }
00554 
00555 
00565 void Camera_f::rotate(float phi, float x, float y, float z) throw (Arg_error)
00566 {
00567     float cos_phi, cos_theta, cos_psi;
00568     float sin_phi, sin_theta, sin_psi;
00569     float mag_xyz, mag_xy;
00570 
00571     mag_xyz = std::sqrt(x*x + y*y + z*z);
00572 
00573     if (mag_xyz < 1.0e-8)
00574     {
00575         throw Arg_error("Magnitude of rotation vector too small");
00576     }
00577 
00578 
00579     /* psi used to rotate around z-axis to put vector on the yz-plane. */
00580     mag_xy = std::sqrt(x*x + y*y);
00581     if (mag_xy > 1.0e-8)
00582     {
00583         cos_psi = y / mag_xy;
00584         sin_psi = x / mag_xy;
00585     }
00586     else
00587     {
00588         cos_psi = 0.0;
00589         sin_psi = 1.0;
00590     }
00591 
00592     /* theta used to rotate around x-axis to put vector onto the z-axis. */
00593     cos_theta = z / mag_xyz;
00594     sin_theta = mag_xy / mag_xyz;
00595 
00596     /* phi used to rotate around z-axis. This is actually the angle to rotate
00597      * around the vector. */
00598     cos_phi = std::cos(phi);
00599     sin_phi = std::sin(phi);
00600 
00601     create_zero_matrix_f(&R_phi, 3, 3);
00602     R_phi->elts[ 0 ][ 0 ] = cos_phi;
00603     R_phi->elts[ 0 ][ 1 ] = sin_phi;
00604     R_phi->elts[ 1 ][ 0 ] = -sin_phi;
00605     R_phi->elts[ 1 ][ 1 ] = cos_phi;
00606     R_phi->elts[ 2 ][ 2 ] = 1;
00607 
00608     create_zero_matrix_f(&R_theta, 3, 3);
00609     R_theta->elts[ 0 ][ 0 ] = 1;
00610     R_theta->elts[ 1 ][ 1 ] = cos_theta;
00611     R_theta->elts[ 1 ][ 2 ] = sin_theta;
00612     R_theta->elts[ 2 ][ 1 ] = -sin_theta;
00613     R_theta->elts[ 2 ][ 2 ] = cos_theta;
00614 
00615     create_zero_matrix_f(&R_psi, 3, 3);
00616     R_psi->elts[ 0 ][ 0 ] = cos_psi;
00617     R_psi->elts[ 0 ][ 1 ] = sin_psi;
00618     R_psi->elts[ 1 ][ 0 ] = -sin_psi;
00619     R_psi->elts[ 1 ][ 1 ] = cos_psi;
00620     R_psi->elts[ 2 ][ 2 ] = 1;
00621 
00622     /* R = R_psi * R_theta * R_phi * R_theta^T * R_psi^T */
00623     multiply_matrices_f(&R, R_psi, R_theta);
00624     multiply_matrices_f(&R, R, R_phi);
00625     transpose_matrix_f(&R_theta, R_theta);
00626     transpose_matrix_f(&R_psi, R_psi);
00627     multiply_matrices_f(&R, R, R_theta);
00628     multiply_matrices_f(&R, R, R_psi);
00629 
00630     multiply_matrix_and_vector_f(&vrp, R, vrp);
00631     multiply_matrix_and_vector_f(&prp, R, prp);
00632     multiply_matrix_and_vector_f(&u, R, u);
00633     multiply_matrix_and_vector_f(&v, R, v);
00634     multiply_matrix_and_vector_f(&n, R, n);
00635 }
00636 
00637 
00645 void Camera_f::rotate(float phi, const jwsc::Vector_f* r) throw (Arg_error)
00646 {
00647     if (r->num_elts < 3)
00648     {
00649         throw Arg_error("Vector to rotate around must be in R^3");
00650     }
00651 
00652     rotate(phi, r->elts[0], r->elts[1], r->elts[2]);
00653 }
00654 
00655 
00661 void Camera_f::translate(float x, float y, float z)
00662 {
00663     prp->elts[0] += x;  vrp->elts[0] += x;
00664     prp->elts[1] += y;  vrp->elts[1] += y;
00665     prp->elts[2] += z;  vrp->elts[2] += z;
00666 }
00667 
00668 
00672 void Camera_f::translate(const jwsc::Vector_f* t) throw (Arg_error)
00673 {
00674     if (t->num_elts < 3)
00675     {
00676         throw Arg_error("Vector to translate by must be in R^3");
00677     }
00678 
00679     add_vectors_f(&vrp, vrp, t);
00680     add_vectors_f(&prp, prp, t);
00681 }
00682 
00683 
00697 void Camera_f::look_at
00698 (
00699     float focal_pt_x,
00700     float focal_pt_y,
00701     float focal_pt_z,
00702     float ref_pt_x,
00703     float ref_pt_y,
00704     float ref_pt_z,
00705     float up_x,
00706     float up_y,
00707     float up_z
00708 )
00709 throw (jwscxx::base::Arg_error)
00710 {
00711     float n_x = focal_pt_x - ref_pt_x;
00712     float n_y = focal_pt_y - ref_pt_y;
00713     float n_z = focal_pt_z - ref_pt_z;
00714 
00715     float n_mag = sqrt(n_x*n_x + n_y*n_y + n_z*n_z);
00716     if (n_mag < 1.0e-8)
00717     {
00718         throw Arg_error("Focal length is zero");
00719     }
00720 
00721     float up_mag = sqrt(up_x*up_x + up_y*up_y + up_z*up_z);
00722     if (up_mag < 1.0e-8)
00723     {
00724         throw Arg_error("Up vector has no magnitude");
00725     }
00726 
00727     float dp = up_x*n_x + up_y*n_y + up_z*n_z;
00728     if ((n_mag*up_mag - fabs(dp)) < 1.0e-8)
00729     {
00730         throw Arg_error("Up vector parallel to view direction");
00731     }
00732 
00733     create_vector_f(&prp, 3);
00734     prp->elts[0] = focal_pt_x;
00735     prp->elts[1] = focal_pt_y;
00736     prp->elts[2] = focal_pt_z;
00737 
00738     create_vector_f(&vrp, 3);
00739     vrp->elts[0] = ref_pt_x;
00740     vrp->elts[1] = ref_pt_y;
00741     vrp->elts[2] = ref_pt_z;
00742 
00743     focal_length = n_mag;
00744     n_mag = 1.0f / n_mag;
00745     create_vector_f(&n, 3);
00746     n->elts[0] = n_x * n_mag;
00747     n->elts[1] = n_y * n_mag;
00748     n->elts[2] = n_z * n_mag;
00749 
00750     create_vector_f(&v, 3);
00751     v->elts[0] = up_x / up_mag;
00752     v->elts[1] = up_y / up_mag;
00753     v->elts[2] = up_z / up_mag;
00754 
00755     calc_3d_vector_cross_prod_f(&u, v, n);
00756 
00757     calc_3d_vector_cross_prod_f(&v, n, u);
00758 
00759     float tan_theta = std::tan(JWSC_DEG_TO_RAD * aperture / 2.0f);
00760     half_focal_height = focal_length * tan_theta;
00761 }
00762 
00763 
00771 void Camera_f::look_at
00772 (
00773     const jwsc::Vector_f* focal_pt,
00774     const jwsc::Vector_f* ref_pt,
00775     const jwsc::Vector_f* up
00776 )
00777 throw (Arg_error)
00778 {
00779     if (focal_pt->num_elts != 3 ||
00780         ref_pt->num_elts   != 3 ||
00781         up->num_elts       != 3)
00782     {
00783         throw Arg_error("Camera look vectors not in R^3");
00784     }
00785 
00786     look_at(focal_pt->elts[0], focal_pt->elts[1], focal_pt->elts[2],
00787             ref_pt->elts[0], ref_pt->elts[1], ref_pt->elts[2],
00788             up->elts[0], up->elts[1], up->elts[2]);
00789 }
00790 
00791 
00796 void Camera_f::set_gl_modelview() const
00797 {
00798     GLfloat M[16] = {0};
00799 
00800     glMatrixMode(GL_MODELVIEW);
00801 
00802     glLoadIdentity();
00803 
00804     M[0] = u->elts[0];  M[4] = u->elts[1];  M[8]  = u->elts[2];
00805     M[1] = v->elts[0];  M[5] = v->elts[1];  M[9]  = v->elts[2];
00806     M[2] = n->elts[0];  M[6] = n->elts[1];  M[10] = n->elts[2];
00807     M[15] = 1;
00808     glMultMatrixf(M);
00809 
00810     glTranslatef(-prp->elts[0], -prp->elts[1], -prp->elts[2]);
00811 }
00812 
00813 
00818 void Camera_f::set_gl_projection() const
00819 {
00820     glMatrixMode(GL_PROJECTION);
00821 
00822     glLoadIdentity();
00823 
00824     float aspect = get_gl_viewport_aspect();
00825     float left   = -aspect*half_near_height;
00826     float right  =  aspect*half_near_height;
00827     float top    =  half_near_height;
00828     float bottom = -half_near_height;
00829 
00830     glFrustum(left, right, bottom, top, near, far);
00831 }
00832 
00833 
00846 void Camera_f::get_image_pt_on_focal_plane
00847 (
00848     jwsc::Vector_f** pt_out, 
00849     float            x, 
00850     float            y
00851 )
00852 {
00853     float half_view_height = 0.5f*get_gl_viewport_height();
00854     float focal_x = x * (half_focal_height / half_view_height);
00855     float focal_y = y * (half_focal_height / half_view_height);
00856 
00857     create_vector_f(pt_out, 3);
00858     Vector_f* pt = *pt_out;
00859 
00860     pt->elts[0] = focal_x;
00861     pt->elts[1] = focal_y;
00862     pt->elts[2] = -focal_length;
00863 
00864     create_matrix_f(&R, 3, 3);
00865     R->elts[0][0] = u->elts[0];
00866     R->elts[1][0] = u->elts[1];
00867     R->elts[2][0] = u->elts[2];
00868 
00869     R->elts[0][1] = v->elts[0];
00870     R->elts[1][1] = v->elts[1];
00871     R->elts[2][1] = v->elts[2];
00872 
00873     R->elts[0][2] = n->elts[0];
00874     R->elts[1][2] = n->elts[1];
00875     R->elts[2][2] = n->elts[2];
00876 
00877     multiply_matrix_and_vector_f(&pt, R, pt);
00878 
00879     add_vectors_f(&pt, pt, prp);
00880 }
00881 
00882 
00896 void Camera_f::get_image_pt_on_focal_plane
00897 (
00898     jwsc::Vector_f**      pt_out, 
00899     const jwsc::Vector_f* pt_in
00900 )
00901 throw (Arg_error)
00902 {
00903     if (pt_in->num_elts != 2)
00904     {
00905         throw Arg_error("Invalid image pt vector");
00906     }
00907 
00908     get_image_pt_on_focal_plane(pt_out, pt_in->elts[0], pt_in->elts[1]);
00909 }
00910 
00911 
00925 void Camera_f::get_image_pt_on_near_clipping_plane
00926 (
00927     jwsc::Vector_f** pt_out, 
00928     float            x, 
00929     float            y
00930 )
00931 {
00932     float half_view_height = 0.5f*get_gl_viewport_height();
00933     float near_x = x * (half_near_height / half_view_height);
00934     float near_y = y * (half_near_height / half_view_height);
00935 
00936     create_vector_f(pt_out, 3);
00937     Vector_f* pt = *pt_out;
00938 
00939     pt->elts[0] = near_x;
00940     pt->elts[1] = near_y;
00941     pt->elts[2] = -near;
00942 
00943     create_matrix_f(&R, 3, 3);
00944     R->elts[0][0] = u->elts[0];
00945     R->elts[1][0] = u->elts[1];
00946     R->elts[2][0] = u->elts[2];
00947 
00948     R->elts[0][1] = v->elts[0];
00949     R->elts[1][1] = v->elts[1];
00950     R->elts[2][1] = v->elts[2];
00951 
00952     R->elts[0][2] = n->elts[0];
00953     R->elts[1][2] = n->elts[1];
00954     R->elts[2][2] = n->elts[2];
00955 
00956     multiply_matrix_and_vector_f(&pt, R, pt);
00957 
00958     add_vectors_f(&pt, pt, prp);
00959 }
00960 
00961 
00976 void Camera_f::get_image_pt_on_near_clipping_plane
00977 (
00978     jwsc::Vector_f**      pt_out,
00979     const jwsc::Vector_f* pt_in
00980 )
00981 throw (Arg_error)
00982 {
00983     if (pt_in->num_elts != 2)
00984     {
00985         throw Arg_error("invalid image pt vector");
00986     }
00987 
00988     get_image_pt_on_near_clipping_plane(pt_out, pt_in->elts[0], pt_in->elts[1]);
00989 }
00990 
00991 
01005 void Camera_f::get_image_pt_on_far_clipping_plane
01006 (
01007     jwsc::Vector_f** pt_out, 
01008     float            x, 
01009     float            y
01010 )
01011 {
01012     float half_view_height = 0.5f*get_gl_viewport_height();
01013     float half_far_height = far * half_near_height / near;
01014     float far_x = x * (half_far_height / half_view_height);
01015     float far_y = y * (half_far_height / half_view_height);
01016 
01017     create_vector_f(pt_out, 3);
01018     Vector_f* pt = *pt_out;
01019 
01020     pt->elts[0] = far_x;
01021     pt->elts[1] = far_y;
01022     pt->elts[2] = -far;
01023 
01024     create_matrix_f(&R, 3, 3);
01025     R->elts[0][0] = u->elts[0];
01026     R->elts[1][0] = u->elts[1];
01027     R->elts[2][0] = u->elts[2];
01028 
01029     R->elts[0][1] = v->elts[0];
01030     R->elts[1][1] = v->elts[1];
01031     R->elts[2][1] = v->elts[2];
01032 
01033     R->elts[0][2] = n->elts[0];
01034     R->elts[1][2] = n->elts[1];
01035     R->elts[2][2] = n->elts[2];
01036 
01037     multiply_matrix_and_vector_f(&pt, R, pt);
01038 
01039     add_vectors_f(&pt, pt, prp);
01040 }
01041 
01042 
01057 void Camera_f::get_image_pt_on_far_clipping_plane
01058 (
01059     jwsc::Vector_f**      pt_out,
01060     const jwsc::Vector_f* pt_in
01061 )
01062 throw (Arg_error)
01063 {
01064     if (pt_in->num_elts != 2)
01065     {
01066         throw Arg_error("invalid image pt vector");
01067     }
01068 
01069     get_image_pt_on_far_clipping_plane(pt_out, pt_in->elts[0], pt_in->elts[1]);
01070 }
01071 
01072 
01074 float Camera_f::get_gl_viewport_aspect()
01075 {
01076     GLfloat viewport[4] = {0};
01077 
01078     glGetFloatv(GL_VIEWPORT, viewport);
01079     return viewport[2] / viewport[3];
01080 }
01081 
01082 
01084 float Camera_f::get_gl_viewport_width()
01085 {
01086     GLfloat viewport[4] = {0};
01087 
01088     glGetFloatv(GL_VIEWPORT, viewport);
01089     return viewport[2];
01090 }
01091 
01092 
01094 float Camera_f::get_gl_viewport_height()
01095 {
01096     GLfloat viewport[4] = {0};
01097 
01098     glGetFloatv(GL_VIEWPORT, viewport);
01099     return viewport[3];
01100 }
01101 
01102 
01109 void Camera_f::capture_gl_view(jwsc::Image_f** img_out)
01110 {
01111     uint32_t num_cols = (uint32_t)Camera_f::get_gl_viewport_width();
01112     uint32_t num_rows = (uint32_t)Camera_f::get_gl_viewport_height();
01113 
01114     float* img_buf = (float*)malloc(3*num_cols*num_rows*sizeof(float));
01115     assert(img_buf);
01116 
01117     glPixelStorei(GL_PACK_ALIGNMENT, 1);
01118 
01119     glReadPixels(0, 0, num_cols, num_rows, GL_RGB, GL_FLOAT, img_buf);
01120 
01121     create_image_f(img_out, num_rows, num_cols);
01122     Image_f* img = *img_out;
01123 
01124     for (uint32_t row = 0; row < num_rows; row++)
01125     {
01126         for (uint32_t col = 0; col < 3*num_cols; col += 3)
01127         {
01128             uint32_t r = num_rows - row - 1;
01129 
01130             img->pxls[ r ][ col/3 ].r = img_buf[ col+0 + row*3*num_cols ];
01131             img->pxls[ r ][ col/3 ].g = img_buf[ col+1 + row*3*num_cols ];
01132             img->pxls[ r ][ col/3 ].b = img_buf[ col+2 + row*3*num_cols ];
01133         }
01134     }
01135 
01136     free(img_buf);
01137 }
01138 
01139 
01145 void Camera_f::capture_gl_view(const char* fname) throw (jwscxx::base::IO_error)
01146 {
01147     Image_f* img = 0;
01148     capture_gl_view(&img);
01149 
01150     Error* err;
01151     if ((err = write_image_f(img, fname)) != 0)
01152     {
01153         std::ostringstream ost(err->msg);
01154         free_error(err);
01155         throw IO_error(ost.str());
01156     }
01157 
01158     free_image_f(img);
01159 }
01160 
01161 
01173 void Camera_f::capture_gl_view(const char* fname_fmt, uint32_t N)
01174     throw (jwscxx::base::IO_error)
01175 {
01176     char fname[256] = {0};
01177 
01178     snprintf(fname, 255, fname_fmt, N);
01179 
01180     capture_gl_view(fname);
01181 }
01182 
01183 
01205 void Camera_f::read(std::istream& in) throw (jwscxx::base::IO_error,
01206         jwscxx::base::Arg_error)
01207 {
01208     using std::ostringstream;
01209     using std::istringstream;
01210 
01211     const char* type_name = typeid(*this).name();
01212     const char* field_value;
01213 
01214     // Type
01215     if (!(field_value = read_field_value(in, "Type")))
01216     {
01217         throw Arg_error("Missing Type field");
01218     }
01219     if (strncmp(field_value, type_name, strlen(type_name)) != 0)
01220     {
01221         ostringstream ost;
01222         ost << "Tried to read a '" << field_value << "' as a '"
01223             << type_name << "'";
01224         throw Arg_error(ost.str());
01225     }
01226 
01227 
01228     // VRP
01229     if (!(field_value = read_field_value(in, "VRP")))
01230     {
01231         throw Arg_error("Missing VRP fields");
01232     }
01233     istringstream ist(field_value);
01234     ist >> vrp->elts[0] >> vrp->elts[1] >> vrp->elts[2];
01235     if (ist.fail())
01236     {
01237         throw Arg_error("Invalid VRP");
01238     }
01239     ist.clear(std::ios_base::goodbit);
01240 
01241 
01242     // PRP
01243     if (!(field_value = read_field_value(in, "PRP")))
01244     {
01245         throw Arg_error("Missing PRP fields");
01246     }
01247     ist.str(field_value);
01248     ist >> prp->elts[0] >> prp->elts[1] >> prp->elts[2];
01249     if (ist.fail())
01250     {
01251         throw Arg_error("Invalid PRP");
01252     }
01253     ist.clear(std::ios_base::goodbit);
01254 
01255 
01256     // U
01257     if (!(field_value = read_field_value(in, "U")))
01258     {
01259         throw Arg_error("Missing U fields");
01260     }
01261     ist.str(field_value);
01262     ist >> u->elts[ 0 ] >> u->elts[1] >> u->elts[2];
01263     if (ist.fail())
01264     {
01265         throw Arg_error("Invalid U");
01266     }
01267     ist.clear(std::ios_base::goodbit);
01268 
01269 
01270     // V
01271     if (!(field_value = read_field_value(in, "V")))
01272     {
01273         throw Arg_error("Missing V fields");
01274     }
01275     ist.str(field_value);
01276     ist >> v->elts[ 0 ] >> v->elts[1] >> v->elts[2];
01277     if (ist.fail())
01278     {
01279         throw Arg_error("Invalid V");
01280     }
01281     ist.clear(std::ios_base::goodbit);
01282 
01283 
01284     // N
01285     if (!(field_value = read_field_value(in, "N")))
01286     {
01287         throw Arg_error("Missing N fields");
01288     }
01289     ist.str(field_value);
01290     ist >> n->elts[ 0 ] >> n->elts[1] >> n->elts[2];
01291     if (ist.fail())
01292     {
01293         throw Arg_error("Invalid N");
01294     }
01295     ist.clear(std::ios_base::goodbit);
01296 
01297 
01298     // F
01299     if (!(field_value = read_field_value(in, "F")))
01300     {
01301         throw Arg_error("Missing F field");
01302     }
01303     ist.str(field_value);
01304     ist >> focal_length;
01305     if (ist.fail())
01306     {
01307         throw Arg_error("Invalid focal length");
01308     }
01309     ist.clear(std::ios_base::goodbit);
01310 
01311 
01312     // Aperture
01313     if (!(field_value = read_field_value(in, "Aperture")))
01314     {
01315         throw Arg_error("Missing Aperture field");
01316     }
01317     ist.str(field_value);
01318     ist >> aperture;
01319     if (ist.fail())
01320     {
01321         throw Arg_error("Invalid aperture");
01322     }
01323     ist.clear(std::ios_base::goodbit);
01324     if (aperture <= 0)
01325     {
01326         throw Arg_error("Aperture <= 0");
01327     }
01328 
01329 
01330     // Near
01331     if (!(field_value = read_field_value(in, "Near")))
01332     {
01333         throw Arg_error("Missing Near field");
01334     }
01335     ist.str(field_value);
01336     ist >> near;
01337     if (ist.fail())
01338     {
01339         throw Arg_error("Invalid near clipping distance");
01340     }
01341     ist.clear(std::ios_base::goodbit);
01342 
01343 
01344     // Far
01345     if (!(field_value = read_field_value(in, "Far")))
01346     {
01347         throw Arg_error("Missing Far field");
01348     }
01349     ist.str(field_value);
01350     ist >> far;
01351     if (ist.fail())
01352     {
01353         throw Arg_error("Invalid far clipping distance");
01354     }
01355     ist.clear(std::ios_base::goodbit);
01356     if (near < 0 || far <= 0 || near > far)
01357     {
01358         throw Arg_error("Invalid clipping planes");
01359     }
01360 
01361 
01362     // Derived...
01363     float tan_theta = std::tan(JWSC_DEG_TO_RAD * aperture / 2.0f);
01364     half_near_height = near * tan_theta;
01365     half_focal_height = focal_length * tan_theta;
01366 }
01367 
01368 
01389 void Camera_f::write(std::ostream& out) const throw (jwscxx::base::IO_error)
01390 {
01391     out << "     Type: " << typeid(*this).name() << '\n'
01392         << "      VRP: " << vrp->elts[0] << ' '
01393                          << vrp->elts[1] << ' '
01394                          << vrp->elts[2] << '\n'
01395         << "      PRP: " << prp->elts[0] << ' '
01396                          << prp->elts[1] << ' '
01397                          << prp->elts[2] << '\n'
01398         << "        U: " << u->elts[0] << ' '
01399                          << u->elts[1] << ' '
01400                          << u->elts[2] << '\n'
01401         << "        V: " << v->elts[0] << ' '
01402                          << v->elts[1] << ' '
01403                          << v->elts[2] << '\n'
01404         << "        N: " << n->elts[0] << ' '
01405                          << n->elts[1] << ' '
01406                          << n->elts[2] << '\n'
01407         << "        F: " << focal_length << '\n'
01408         << " Aperture: " << aperture << '\n'
01409         << "     Near: " << near << '\n'
01410         << "      Far: " << far << '\n';
01411 }
01412 
01413 
01431 Camera_d::Camera_d
01432 (
01433     double focal_pt_x,
01434     double focal_pt_y,
01435     double focal_pt_z,
01436     double ref_pt_x,
01437     double ref_pt_y,
01438     double ref_pt_z,
01439     double up_x,
01440     double up_y,
01441     double up_z,
01442     double aperture, 
01443     double clip_near, 
01444     double clip_far
01445 )
01446 throw (Arg_error)
01447 {
01448     if (aperture <= 0)
01449     {
01450         throw Arg_error("Aperture <= 0");
01451     }
01452     this->aperture = aperture;
01453 
01454     if (clip_near < 0 || clip_far <= 0 || clip_near > clip_far)
01455     {
01456         throw Arg_error("Invalid clipping planes");
01457     }
01458     near = clip_near;
01459     far  = clip_far;
01460 
01461     prp     = 0;
01462     vrp     = 0;
01463     n       = 0;
01464     v       = 0;
01465     u       = 0;
01466     R_phi   = 0;
01467     R_theta = 0;
01468     R_psi   = 0;
01469     R       = 0;
01470 
01471     look_at(focal_pt_x, focal_pt_y, focal_pt_z, ref_pt_x, ref_pt_y, ref_pt_z,
01472             up_x, up_y, up_z);
01473 
01474     double tan_theta = std::tan(JWSC_DEG_TO_RAD * aperture / 2.0);
01475     half_near_height = clip_near * tan_theta;
01476 }
01477 
01478 
01490 Camera_d::Camera_d
01491 (
01492     const jwsc::Vector_d* focal_pt,
01493     const jwsc::Vector_d* ref_pt,
01494     const jwsc::Vector_d* up,
01495     double                aperture, 
01496     double                clip_near, 
01497     double                clip_far
01498 )
01499 throw (Arg_error)
01500 {
01501     if (aperture <= 0)
01502     {
01503         throw Arg_error("Aperture <= 0");
01504     }
01505     this->aperture = aperture;
01506 
01507     if (clip_near < 0 || clip_far <= 0 || clip_near > clip_far)
01508     {
01509         throw Arg_error("Invalid clipping planes");
01510     }
01511     near = clip_near;
01512     far  = clip_far;
01513 
01514     prp     = 0;
01515     vrp     = 0;
01516     n       = 0;
01517     v       = 0;
01518     u       = 0;
01519     R_phi   = 0;
01520     R_theta = 0;
01521     R_psi   = 0;
01522     R       = 0;
01523 
01524     look_at(focal_pt, ref_pt, up);
01525 
01526     double tan_theta = std::tan(JWSC_DEG_TO_RAD * aperture / 2.0);
01527     half_near_height = clip_near * tan_theta;
01528 }
01529 
01530 
01532 Camera_d::Camera_d(const Camera_d& c)
01533 {
01534     prp     = 0;
01535     vrp     = 0;
01536     n       = 0;
01537     v       = 0;
01538     u       = 0;
01539     R_phi   = 0;
01540     R_theta = 0;
01541     R_psi   = 0;
01542     R       = 0;
01543 
01544     *this = c;
01545 }
01546 
01547 
01569 Camera_d::Camera_d(const char* fname) throw (jwscxx::base::Arg_error,
01570         jwscxx::base::IO_error)
01571 {
01572     vrp     = 0;
01573     prp     = 0;
01574     u       = 0;
01575     v       = 0;
01576     n       = 0;
01577     R_phi   = 0;
01578     R_theta = 0;
01579     R_psi   = 0;
01580     R       = 0;
01581 
01582     jwscxx::base::Readable::read(fname);
01583 }
01584 
01585 
01607 Camera_d::Camera_d(std::istream& in) throw (jwscxx::base::Arg_error,
01608         jwscxx::base::IO_error)
01609 {
01610     vrp     = 0;
01611     prp     = 0;
01612     u       = 0;
01613     v       = 0;
01614     n       = 0;
01615     R_phi   = 0;
01616     R_theta = 0;
01617     R_psi   = 0;
01618     R       = 0;
01619 
01620     read(in);
01621 }
01622 
01623 
01624 Camera_d::~Camera_d()
01625 {
01626     free_vector_d(vrp);
01627     free_vector_d(prp);
01628     free_vector_d(u);
01629     free_vector_d(v);
01630     free_vector_d(n);
01631     free_matrix_d(R_phi);
01632     free_matrix_d(R_theta);
01633     free_matrix_d(R_psi);
01634     free_matrix_d(R);
01635 }
01636 
01637 
01645 Camera_d& Camera_d::operator=(const Camera_d &c)
01646 {
01647     copy_vector_d(&vrp, c.vrp);
01648     copy_vector_d(&prp, c.prp);
01649     copy_vector_d(&u, c.u);
01650     copy_vector_d(&v, c.v);
01651     copy_vector_d(&n, c.n);
01652 
01653     aperture = c.aperture;
01654     focal_length = c.focal_length;
01655     half_focal_height = c.half_focal_height;
01656     half_near_height = c.half_near_height;
01657     near = c.near;
01658     far = c.far;
01659 
01660     if (c.R_phi   != 0)  copy_matrix_d(&R_phi, c.R_phi);
01661     if (c.R_theta != 0)  copy_matrix_d(&R_theta, c.R_theta);
01662     if (c.R_psi   != 0)  copy_matrix_d(&R_psi, c.R_psi);
01663     if (c.R       != 0)  copy_matrix_d(&R, c.R);
01664 
01665     return *this;
01666 }
01667 
01668 
01670 Camera_d* Camera_d::clone() const
01671 {
01672     return new Camera_d(*this);
01673 }
01674 
01675 
01676 const jwsc::Vector_d* Camera_d::get_u() const 
01677 { 
01678     return (const jwsc::Vector_d*)u; 
01679 }
01680 
01681 
01682 const jwsc::Vector_d* Camera_d::get_v() const 
01683 { 
01684     return (const jwsc::Vector_d*)v; 
01685 }
01686 
01687 
01691 const jwsc::Vector_d* Camera_d::get_n() const 
01692 { 
01693     return (const jwsc::Vector_d*)n; 
01694 }
01695 
01696 
01697 const jwsc::Vector_d* Camera_d::get_prp() const 
01698 { 
01699     return (const jwsc::Vector_d*)prp; 
01700 }
01701 
01702 
01703 const jwsc::Vector_d* Camera_d::get_vrp() const 
01704 { 
01705     return (const jwsc::Vector_d*)vrp; 
01706 }
01707 
01708 
01709 double Camera_d::get_clipping_near() const 
01710 { 
01711     return near; 
01712 }
01713 
01714 
01715 double Camera_d::get_clipping_far() const 
01716 { 
01717     return far; 
01718 }
01719 
01720 
01721 double Camera_d::get_focal_length() const 
01722 { 
01723     return focal_length; 
01724 }
01725 
01726 
01727 double Camera_d::get_aperture() const 
01728 { 
01729     return aperture; 
01730 }
01731 
01732 
01734 double Camera_d::get_half_focal_height() const
01735 {
01736     return half_focal_height;
01737 }       
01738 
01739 
01745 void Camera_d::set_aperture(double aperture) throw (Arg_error)
01746 {
01747     if (aperture <= 0)
01748     {
01749         throw Arg_error("Aperture <= 0");
01750     }
01751     this->aperture = aperture;
01752 
01753     double tan_theta = std::tan(JWSC_DEG_TO_RAD * aperture / 2.0);
01754     half_near_height = near * tan_theta;
01755     half_focal_height = focal_length * tan_theta;
01756 }
01757 
01758 
01767 void Camera_d::set_f_with_new_aperture_using_prp(double f) throw (Arg_error)
01768 {
01769     if (f <= 0)
01770     {
01771         throw Arg_error("Focal length <= 0");
01772     }
01773 
01774     focal_length = f;
01775 
01776     multiply_vector_by_scalar_d(&prp, n, focal_length);
01777     add_vectors_d(&prp, prp, vrp);
01778 
01779     half_near_height = near * half_focal_height / focal_length;
01780 
01781     double theta = std::atan(half_focal_height / focal_length);
01782     aperture = JWSC_RAD_TO_DEG * 2.0 * theta;
01783 }
01784 
01785 
01794 void Camera_d::set_f_with_same_aperture_using_prp(double f) throw (Arg_error)
01795 {
01796     if (f <= 0)
01797     {
01798         throw Arg_error("Focal length <= 0");
01799     }
01800 
01801     focal_length = f;
01802 
01803     multiply_vector_by_scalar_d(&prp, n, focal_length);
01804     add_vectors_d(&prp, prp, vrp);
01805 
01806     double tan_theta = std::tan(JWSC_DEG_TO_RAD * aperture / 2.0);
01807     half_focal_height = focal_length * tan_theta;
01808 }
01809 
01810 
01819 void Camera_d::set_f_with_new_aperture_using_vrp(double f) throw (Arg_error)
01820 {
01821     if (f <= 0)
01822     {
01823         throw Arg_error("Focal length <= 0");
01824     }
01825 
01826     focal_length = f;
01827 
01828     multiply_vector_by_scalar_d(&vrp, n, -focal_length);
01829     add_vectors_d(&vrp, vrp, prp);
01830 
01831     half_near_height = near * half_focal_height / focal_length;
01832 
01833     double theta = std::atan(half_focal_height / focal_length);
01834     aperture = JWSC_RAD_TO_DEG * 2.0 * theta;
01835 }
01836 
01837 
01846 void Camera_d::set_f_with_same_aperture_using_vrp(double f) throw (Arg_error)
01847 {
01848     if (f <= 0)
01849     {
01850         throw Arg_error("Focal length <= 0");
01851     }
01852 
01853     focal_length = f;
01854 
01855     multiply_vector_by_scalar_d(&vrp, n, -focal_length);
01856     add_vectors_d(&vrp, vrp, prp);
01857 
01858     double tan_theta = std::tan(JWSC_DEG_TO_RAD * aperture / 2.0);
01859     half_focal_height = focal_length * tan_theta;
01860 }
01861 
01862 
01869 void Camera_d::set_clipping(double clip_near, double clip_far) throw (Arg_error)
01870 {
01871     if (clip_near < 0 || clip_far <= 0 || clip_near > clip_far)
01872     {
01873         throw Arg_error("Invalid clipping planes");
01874     }
01875     near = clip_near;
01876     far  = clip_far;
01877 
01878     double tan_theta = std::tan(JWSC_DEG_TO_RAD * aperture / 2.0);
01879     half_near_height = near * tan_theta;
01880 }
01881 
01882 
01892 void Camera_d::rotate(double phi, double x, double y, double z) 
01893     throw (Arg_error)
01894 {
01895     double cos_phi, cos_theta, cos_psi;
01896     double sin_phi, sin_theta, sin_psi;
01897     double mag_xyz, mag_xy;
01898 
01899     mag_xyz = std::sqrt(x*x + y*y + z*z);
01900 
01901     if (mag_xyz < 1.0e-8)
01902     {
01903         throw Arg_error("Magnitude of rotation vector too small");
01904     }
01905 
01906 
01907     /* psi used to rotate around z-axis to put vector on the yz-plane. */
01908     mag_xy = std::sqrt(x*x + y*y);
01909     if (mag_xy > 1.0e-8)
01910     {
01911         cos_psi = y / mag_xy;
01912         sin_psi = x / mag_xy;
01913     }
01914     else
01915     {
01916         cos_psi = 0.0;
01917         sin_psi = 1.0;
01918     }
01919 
01920     /* theta used to rotate around x-axis to put vector onto the z-axis. */
01921     cos_theta = z / mag_xyz;
01922     sin_theta = mag_xy / mag_xyz;
01923 
01924     /* phi used to rotate around z-axis. This is actually the angle to rotate
01925      * around the vector. */
01926     cos_phi = std::cos(phi);
01927     sin_phi = std::sin(phi);
01928 
01929     create_zero_matrix_d(&R_phi, 3, 3);
01930     R_phi->elts[ 0 ][ 0 ] = cos_phi;
01931     R_phi->elts[ 0 ][ 1 ] = sin_phi;
01932     R_phi->elts[ 1 ][ 0 ] = -sin_phi;
01933     R_phi->elts[ 1 ][ 1 ] = cos_phi;
01934     R_phi->elts[ 2 ][ 2 ] = 1;
01935 
01936     create_zero_matrix_d(&R_theta, 3, 3);
01937     R_theta->elts[ 0 ][ 0 ] = 1;
01938     R_theta->elts[ 1 ][ 1 ] = cos_theta;
01939     R_theta->elts[ 1 ][ 2 ] = sin_theta;
01940     R_theta->elts[ 2 ][ 1 ] = -sin_theta;
01941     R_theta->elts[ 2 ][ 2 ] = cos_theta;
01942 
01943     create_zero_matrix_d(&R_psi, 3, 3);
01944     R_psi->elts[ 0 ][ 0 ] = cos_psi;
01945     R_psi->elts[ 0 ][ 1 ] = sin_psi;
01946     R_psi->elts[ 1 ][ 0 ] = -sin_psi;
01947     R_psi->elts[ 1 ][ 1 ] = cos_psi;
01948     R_psi->elts[ 2 ][ 2 ] = 1;
01949 
01950     /* R = R_psi * R_theta * R_phi * R_theta^T * R_psi^T */
01951     multiply_matrices_d(&R, R_psi, R_theta);
01952     multiply_matrices_d(&R, R, R_phi);
01953     transpose_matrix_d(&R_theta, R_theta);
01954     transpose_matrix_d(&R_psi, R_psi);
01955     multiply_matrices_d(&R, R, R_theta);
01956     multiply_matrices_d(&R, R, R_psi);
01957 
01958     multiply_matrix_and_vector_d(&vrp, R, vrp);
01959     multiply_matrix_and_vector_d(&prp, R, prp);
01960     multiply_matrix_and_vector_d(&u, R, u);
01961     multiply_matrix_and_vector_d(&v, R, v);
01962     multiply_matrix_and_vector_d(&n, R, n);
01963 }
01964 
01965 
01973 void Camera_d::rotate(double phi, const jwsc::Vector_d* r) throw (Arg_error)
01974 {
01975     if (r->num_elts < 3)
01976     {
01977         throw Arg_error("Vector to rotate around must be in R^3");
01978     }
01979 
01980     rotate(phi, r->elts[0], r->elts[1], r->elts[2]);
01981 }
01982 
01983 
01989 void Camera_d::translate(double x, double y, double z)
01990 {
01991     prp->elts[0] += x;  vrp->elts[0] += x;
01992     prp->elts[1] += y;  vrp->elts[1] += y;
01993     prp->elts[2] += z;  vrp->elts[2] += z;
01994 }
01995 
01996 
02000 void Camera_d::translate(const jwsc::Vector_d* t) throw (Arg_error)
02001 {
02002     if (t->num_elts < 3)
02003     {
02004         throw Arg_error("Vector to translate by must be in R^3");
02005     }
02006 
02007     add_vectors_d(&vrp, vrp, t);
02008     add_vectors_d(&prp, prp, t);
02009 }
02010 
02011 
02025 void Camera_d::look_at
02026 (
02027     double focal_pt_x,
02028     double focal_pt_y,
02029     double focal_pt_z,
02030     double ref_pt_x,
02031     double ref_pt_y,
02032     double ref_pt_z,
02033     double up_x,
02034     double up_y,
02035     double up_z
02036 )
02037 throw (jwscxx::base::Arg_error)
02038 {
02039     double n_x = focal_pt_x - ref_pt_x;
02040     double n_y = focal_pt_y - ref_pt_y;
02041     double n_z = focal_pt_z - ref_pt_z;
02042 
02043     double n_mag = sqrt(n_x*n_x + n_y*n_y + n_z*n_z);
02044     if (n_mag < 1.0e-8)
02045     {
02046         throw Arg_error("Focal length is zero");
02047     }
02048 
02049     double up_mag = sqrt(up_x*up_x + up_y*up_y + up_z*up_z);
02050     if (up_mag < 1.0e-8)
02051     {
02052         throw Arg_error("Up vector has no magnitude");
02053     }
02054 
02055     double dp = up_x*n_x + up_y*n_y + up_z*n_z;
02056     if ((n_mag*up_mag - fabs(dp)) < 1.0e-8)
02057     {
02058         throw Arg_error("Up vector parallel to view direction");
02059     }
02060 
02061     create_vector_d(&prp, 3);
02062     prp->elts[0] = focal_pt_x;
02063     prp->elts[1] = focal_pt_y;
02064     prp->elts[2] = focal_pt_z;
02065 
02066     create_vector_d(&vrp, 3);
02067     vrp->elts[0] = ref_pt_x;
02068     vrp->elts[1] = ref_pt_y;
02069     vrp->elts[2] = ref_pt_z;
02070 
02071     focal_length = n_mag;
02072     n_mag = 1.0 / n_mag;
02073     create_vector_d(&n, 3);
02074     n->elts[0] = n_x * n_mag;
02075     n->elts[1] = n_y * n_mag;
02076     n->elts[2] = n_z * n_mag;
02077 
02078     create_vector_d(&v, 3);
02079     v->elts[0] = up_x / up_mag;
02080     v->elts[1] = up_y / up_mag;
02081     v->elts[2] = up_z / up_mag;
02082 
02083     calc_3d_vector_cross_prod_d(&u, v, n);
02084 
02085     calc_3d_vector_cross_prod_d(&v, n, u);
02086 
02087     double tan_theta = std::tan(JWSC_DEG_TO_RAD * aperture / 2.0);
02088     half_focal_height = focal_length * tan_theta;
02089 }
02090 
02091 
02099 void Camera_d::look_at
02100 (
02101     const jwsc::Vector_d* focal_pt,
02102     const jwsc::Vector_d* ref_pt,
02103     const jwsc::Vector_d* up
02104 )
02105 throw (Arg_error)
02106 {
02107     if (focal_pt->num_elts != 3 ||
02108         ref_pt->num_elts   != 3 ||
02109         up->num_elts       != 3)
02110     {
02111         throw Arg_error("Camera look vectors not in R^3");
02112     }
02113 
02114     look_at(focal_pt->elts[0], focal_pt->elts[1], focal_pt->elts[2],
02115             ref_pt->elts[0], ref_pt->elts[1], ref_pt->elts[2],
02116             up->elts[0], up->elts[1], up->elts[2]);
02117 }
02118 
02119 
02124 void Camera_d::set_gl_modelview() const
02125 {
02126     GLdouble M[16] = {0};
02127 
02128     glMatrixMode(GL_MODELVIEW);
02129 
02130     glLoadIdentity();
02131 
02132     M[0] = u->elts[0];  M[4] = u->elts[1];  M[8]  = u->elts[2];
02133     M[1] = v->elts[0];  M[5] = v->elts[1];  M[9]  = v->elts[2];
02134     M[2] = n->elts[0];  M[6] = n->elts[1];  M[10] = n->elts[2];
02135     M[15] = 1;
02136     glMultMatrixd(M);
02137 
02138     glTranslated(-prp->elts[0], -prp->elts[1], -prp->elts[2]);
02139 }
02140 
02141 
02146 void Camera_d::set_gl_projection() const
02147 {
02148     glMatrixMode(GL_PROJECTION);
02149 
02150     glLoadIdentity();
02151 
02152     double aspect = get_gl_viewport_aspect();
02153     double left   = -aspect*half_near_height;
02154     double right  =  aspect*half_near_height;
02155     double top    =  half_near_height;
02156     double bottom = -half_near_height;
02157 
02158     glFrustum(left, right, bottom, top, near, far);
02159 }
02160 
02161 
02174 void Camera_d::get_image_pt_on_focal_plane
02175 (
02176     jwsc::Vector_d** pt_out, 
02177     double           x, 
02178     double           y
02179 )
02180 {
02181     double half_view_height = 0.5*get_gl_viewport_height();
02182     double focal_x = x * (half_focal_height / half_view_height);
02183     double focal_y = y * (half_focal_height / half_view_height);
02184 
02185     create_vector_d(pt_out, 3);
02186     Vector_d* pt = *pt_out;
02187 
02188     pt->elts[0] = focal_x;
02189     pt->elts[1] = focal_y;
02190     pt->elts[2] = -focal_length;
02191 
02192     create_matrix_d(&R, 3, 3);
02193     R->elts[0][0] = u->elts[0];
02194     R->elts[1][0] = u->elts[1];
02195     R->elts[2][0] = u->elts[2];
02196 
02197     R->elts[0][1] = v->elts[0];
02198     R->elts[1][1] = v->elts[1];
02199     R->elts[2][1] = v->elts[2];
02200 
02201     R->elts[0][2] = n->elts[0];
02202     R->elts[1][2] = n->elts[1];
02203     R->elts[2][2] = n->elts[2];
02204 
02205     multiply_matrix_and_vector_d(&pt, R, pt);
02206 
02207     add_vectors_d(&pt, pt, prp);
02208 }
02209 
02210 
02224 void Camera_d::get_image_pt_on_focal_plane
02225 (
02226     jwsc::Vector_d**      pt_out, 
02227     const jwsc::Vector_d* pt_in
02228 )
02229 throw (Arg_error)
02230 {
02231     if (pt_in->num_elts != 2)
02232     {
02233         throw Arg_error("Invalid image pt vector");
02234     }
02235 
02236     get_image_pt_on_focal_plane(pt_out, pt_in->elts[0], pt_in->elts[1]);
02237 }
02238 
02239 
02253 void Camera_d::get_image_pt_on_near_clipping_plane
02254 (
02255     jwsc::Vector_d** pt_out, 
02256     double           x, 
02257     double           y
02258 )
02259 {
02260     double half_view_height = 0.5*get_gl_viewport_height();
02261     double near_x = x * (half_near_height / half_view_height);
02262     double near_y = y * (half_near_height / half_view_height);
02263 
02264     create_vector_d(pt_out, 3);
02265     Vector_d* pt = *pt_out;
02266 
02267     pt->elts[0] = near_x;
02268     pt->elts[1] = near_y;
02269     pt->elts[2] = -near;
02270 
02271     create_matrix_d(&R, 3, 3);
02272     R->elts[0][0] = u->elts[0];
02273     R->elts[1][0] = u->elts[1];
02274     R->elts[2][0] = u->elts[2];
02275 
02276     R->elts[0][1] = v->elts[0];
02277     R->elts[1][1] = v->elts[1];
02278     R->elts[2][1] = v->elts[2];
02279 
02280     R->elts[0][2] = n->elts[0];
02281     R->elts[1][2] = n->elts[1];
02282     R->elts[2][2] = n->elts[2];
02283 
02284     multiply_matrix_and_vector_d(&pt, R, pt);
02285 
02286     add_vectors_d(&pt, pt, prp);
02287 }
02288 
02289 
02304 void Camera_d::get_image_pt_on_near_clipping_plane
02305 (
02306     jwsc::Vector_d**      pt_out,
02307     const jwsc::Vector_d* pt_in
02308 )
02309 throw (Arg_error)
02310 {
02311     if (pt_in->num_elts != 2)
02312     {
02313         throw Arg_error("invalid image pt vector");
02314     }
02315 
02316     get_image_pt_on_near_clipping_plane(pt_out, pt_in->elts[0], pt_in->elts[1]);
02317 }
02318 
02319 
02333 void Camera_d::get_image_pt_on_far_clipping_plane
02334 (
02335     jwsc::Vector_d** pt_out, 
02336     double           x, 
02337     double           y
02338 )
02339 {
02340     double half_view_height = 0.5*get_gl_viewport_height();
02341     double half_far_height = far * half_near_height / near;
02342     double far_x = x * (half_far_height / half_view_height);
02343     double far_y = y * (half_far_height / half_view_height);
02344 
02345     create_vector_d(pt_out, 3);
02346     Vector_d* pt = *pt_out;
02347 
02348     pt->elts[0] = far_x;
02349     pt->elts[1] = far_y;
02350     pt->elts[2] = -far;
02351 
02352     create_matrix_d(&R, 3, 3);
02353     R->elts[0][0] = u->elts[0];
02354     R->elts[1][0] = u->elts[1];
02355     R->elts[2][0] = u->elts[2];
02356 
02357     R->elts[0][1] = v->elts[0];
02358     R->elts[1][1] = v->elts[1];
02359     R->elts[2][1] = v->elts[2];
02360 
02361     R->elts[0][2] = n->elts[0];
02362     R->elts[1][2] = n->elts[1];
02363     R->elts[2][2] = n->elts[2];
02364 
02365     multiply_matrix_and_vector_d(&pt, R, pt);
02366 
02367     add_vectors_d(&pt, pt, prp);
02368 }
02369 
02370 
02385 void Camera_d::get_image_pt_on_far_clipping_plane
02386 (
02387     jwsc::Vector_d**      pt_out,
02388     const jwsc::Vector_d* pt_in
02389 )
02390 throw (Arg_error)
02391 {
02392     if (pt_in->num_elts != 2)
02393     {
02394         throw Arg_error("invalid image pt vector");
02395     }
02396 
02397     get_image_pt_on_far_clipping_plane(pt_out, pt_in->elts[0], pt_in->elts[1]);
02398 }
02399 
02400 
02402 double Camera_d::get_gl_viewport_aspect()
02403 {
02404     GLdouble viewport[4] = {0};
02405 
02406     glGetDoublev(GL_VIEWPORT, viewport);
02407     return viewport[2] / viewport[3];
02408 }
02409 
02410 
02412 double Camera_d::get_gl_viewport_width()
02413 {
02414     GLdouble viewport[4] = {0};
02415 
02416     glGetDoublev(GL_VIEWPORT, viewport);
02417     return viewport[2];
02418 }
02419 
02420 
02422 double Camera_d::get_gl_viewport_height()
02423 {
02424     GLdouble viewport[4] = {0};
02425 
02426     glGetDoublev(GL_VIEWPORT, viewport);
02427     return viewport[3];
02428 }
02429 
02430 
02437 void Camera_d::capture_gl_view(jwsc::Image_f** img_out)
02438 {
02439     uint32_t num_cols = (uint32_t)Camera_d::get_gl_viewport_width();
02440     uint32_t num_rows = (uint32_t)Camera_d::get_gl_viewport_height();
02441 
02442     float* img_buf = (float*)malloc(3*num_cols*num_rows*sizeof(float));
02443     assert(img_buf);
02444 
02445     glPixelStorei(GL_PACK_ALIGNMENT, 1);
02446 
02447     glReadPixels(0, 0, num_cols, num_rows, GL_RGB, GL_FLOAT, img_buf);
02448 
02449     create_image_f(img_out, num_rows, num_cols);
02450     Image_f* img = *img_out;
02451 
02452     for (uint32_t row = 0; row < num_rows; row++)
02453     {
02454         for (uint32_t col = 0; col < 3*num_cols; col += 3)
02455         {
02456             uint32_t r = num_rows - row - 1;
02457 
02458             img->pxls[ r ][ col/3 ].r = img_buf[ col+0 + row*3*num_cols ];
02459             img->pxls[ r ][ col/3 ].g = img_buf[ col+1 + row*3*num_cols ];
02460             img->pxls[ r ][ col/3 ].b = img_buf[ col+2 + row*3*num_cols ];
02461         }
02462     }
02463 
02464     free(img_buf);
02465 }
02466 
02467 
02473 void Camera_d::capture_gl_view(const char* fname) throw (jwscxx::base::IO_error)
02474 {
02475     Image_f* img = 0;
02476     capture_gl_view(&img);
02477 
02478     Error* err;
02479     if ((err = write_image_f(img, fname)) != 0)
02480     {
02481         std::ostringstream ost(err->msg);
02482         free_error(err);
02483         throw IO_error(ost.str());
02484     }
02485 
02486     free_image_f(img);
02487 }
02488 
02489 
02501 void Camera_d::capture_gl_view(const char* fname_fmt, uint32_t N)
02502     throw (jwscxx::base::IO_error)
02503 {
02504     char fname[256] = {0};
02505 
02506     snprintf(fname, 255, fname_fmt, N);
02507 
02508     capture_gl_view(fname);
02509 }
02510 
02511 
02533 void Camera_d::read(std::istream& in) throw (jwscxx::base::IO_error,
02534         jwscxx::base::Arg_error)
02535 {
02536     using std::ostringstream;
02537     using std::istringstream;
02538 
02539     const char* type_name = typeid(*this).name();
02540     const char* field_value;
02541 
02542     // Type
02543     if (!(field_value = read_field_value(in, "Type")))
02544     {
02545         throw Arg_error("Missing Type field");
02546     }
02547     if (strncmp(field_value, type_name, strlen(type_name)) != 0)
02548     {
02549         ostringstream ost;
02550         ost << "Tried to read a '" << field_value << "' as a '"
02551             << type_name << "'";
02552         throw Arg_error(ost.str());
02553     }
02554 
02555 
02556     // VRP
02557     if (!(field_value = read_field_value(in, "VRP")))
02558     {
02559         throw Arg_error("Missing VRP fields");
02560     }
02561     istringstream ist(field_value);
02562     ist >> vrp->elts[0] >> vrp->elts[1] >> vrp->elts[2];
02563     if (ist.fail())
02564     {
02565         throw Arg_error("Invalid VRP");
02566     }
02567     ist.clear(std::ios_base::goodbit);
02568 
02569 
02570     // PRP
02571     if (!(field_value = read_field_value(in, "PRP")))
02572     {
02573         throw Arg_error("Missing PRP fields");
02574     }
02575     ist.str(field_value);
02576     ist >> prp->elts[0] >> prp->elts[1] >> prp->elts[2];
02577     if (ist.fail())
02578     {
02579         throw Arg_error("Invalid PRP");
02580     }
02581     ist.clear(std::ios_base::goodbit);
02582 
02583 
02584     // U
02585     if (!(field_value = read_field_value(in, "U")))
02586     {
02587         throw Arg_error("Missing U fields");
02588     }
02589     ist.str(field_value);
02590     ist >> u->elts[ 0 ] >> u->elts[1] >> u->elts[2];
02591     if (ist.fail())
02592     {
02593         throw Arg_error("Invalid U");
02594     }
02595     ist.clear(std::ios_base::goodbit);
02596 
02597 
02598     // V
02599     if (!(field_value = read_field_value(in, "V")))
02600     {
02601         throw Arg_error("Missing V fields");
02602     }
02603     ist.str(field_value);
02604     ist >> v->elts[ 0 ] >> v->elts[1] >> v->elts[2];
02605     if (ist.fail())
02606     {
02607         throw Arg_error("Invalid V");
02608     }
02609     ist.clear(std::ios_base::goodbit);
02610 
02611 
02612     // N
02613     if (!(field_value = read_field_value(in, "N")))
02614     {
02615         throw Arg_error("Missing N fields");
02616     }
02617     ist.str(field_value);
02618     ist >> n->elts[ 0 ] >> n->elts[1] >> n->elts[2];
02619     if (ist.fail())
02620     {
02621         throw Arg_error("Invalid N");
02622     }
02623     ist.clear(std::ios_base::goodbit);
02624 
02625 
02626     // F
02627     if (!(field_value = read_field_value(in, "F")))
02628     {
02629         throw Arg_error("Missing F field");
02630     }
02631     ist.str(field_value);
02632     ist >> focal_length;
02633     if (ist.fail())
02634     {
02635         throw Arg_error("Invalid focal length");
02636     }
02637     ist.clear(std::ios_base::goodbit);
02638 
02639 
02640     // Aperture
02641     if (!(field_value = read_field_value(in, "Aperture")))
02642     {
02643         throw Arg_error("Missing Aperture field");
02644     }
02645     ist.str(field_value);
02646     ist >> aperture;
02647     if (ist.fail())
02648     {
02649         throw Arg_error("Invalid aperture");
02650     }
02651     ist.clear(std::ios_base::goodbit);
02652     if (aperture <= 0)
02653     {
02654         throw Arg_error("Aperture <= 0");
02655     }
02656 
02657 
02658     // Near
02659     if (!(field_value = read_field_value(in, "Near")))
02660     {
02661         throw Arg_error("Missing Near field");
02662     }
02663     ist.str(field_value);
02664     ist >> near;
02665     if (ist.fail())
02666     {
02667         throw Arg_error("Invalid near clipping distance");
02668     }
02669     ist.clear(std::ios_base::goodbit);
02670 
02671 
02672     // Far
02673     if (!(field_value = read_field_value(in, "Far")))
02674     {
02675         throw Arg_error("Missing Far field");
02676     }
02677     ist.str(field_value);
02678     ist >> far;
02679     if (ist.fail())
02680     {
02681         throw Arg_error("Invalid far clipping distance");
02682     }
02683     ist.clear(std::ios_base::goodbit);
02684     if (near < 0 || far <= 0 || near > far)
02685     {
02686         throw Arg_error("Invalid clipping planes");
02687     }
02688 
02689 
02690     // Derived...
02691     double tan_theta = std::tan(JWSC_DEG_TO_RAD * aperture / 2.0);
02692     half_near_height = near * tan_theta;
02693     half_focal_height = focal_length * tan_theta;
02694 }
02695 
02696 
02717 void Camera_d::write(std::ostream& out) const throw (jwscxx::base::IO_error)
02718 {
02719     out << "     Type: " << typeid(*this).name() << '\n'
02720         << "      VRP: " << vrp->elts[0] << ' '
02721                          << vrp->elts[1] << ' '
02722                          << vrp->elts[2] << '\n'
02723         << "      PRP: " << prp->elts[0] << ' '
02724                          << prp->elts[1] << ' '
02725                          << prp->elts[2] << '\n'
02726         << "        U: " << u->elts[0] << ' '
02727                          << u->elts[1] << ' '
02728                          << u->elts[2] << '\n'
02729         << "        V: " << v->elts[0] << ' '
02730                          << v->elts[1] << ' '
02731                          << v->elts[2] << '\n'
02732         << "        N: " << n->elts[0] << ' '
02733                          << n->elts[1] << ' '
02734                          << n->elts[2] << '\n'
02735         << "        F: " << focal_length << '\n'
02736         << " Aperture: " << aperture << '\n'
02737         << "     Near: " << near << '\n'
02738         << "      Far: " << far << '\n';
02739 }
02740 
02741 
02742 
02743 
02744 
02766 Stereo_camera_f::Stereo_camera_f
02767 (
02768     float focal_pt_x,
02769     float focal_pt_y,
02770     float focal_pt_z,
02771     float ref_pt_x,
02772     float ref_pt_y,
02773     float ref_pt_z,
02774     float up_x,
02775     float up_y,
02776     float up_z,
02777     float aperture, 
02778     float clip_near, 
02779     float clip_far
02780 )
02781 throw (Arg_error)
02782     : Camera_f(focal_pt_x, focal_pt_y, focal_pt_z, ref_pt_x, ref_pt_y, ref_pt_z,
02783             up_x, up_y, up_z, aperture, clip_near, clip_far)
02784 {
02785     left_prp  = 0;
02786     left_vrp  = 0;
02787     right_prp = 0;
02788     right_vrp = 0;
02789 
02790     look_at(focal_pt_x, focal_pt_y, focal_pt_z, ref_pt_x, ref_pt_y, ref_pt_z,
02791             up_x, up_y, up_z);
02792 }
02793 
02794 
02810 Stereo_camera_f::Stereo_camera_f
02811 (
02812     const jwsc::Vector_f* focal_pt,
02813     const jwsc::Vector_f* ref_pt,
02814     const jwsc::Vector_f* up,
02815     float                 aperture, 
02816     float                 clip_near, 
02817     float                 clip_far
02818 )
02819 throw (Arg_error)
02820     : Camera_f(focal_pt, ref_pt, up, aperture, clip_near, clip_far)
02821 {
02822     left_prp  = 0;
02823     left_vrp  = 0;
02824     right_prp = 0;
02825     right_vrp = 0;
02826 
02827     Camera_f::look_at(focal_pt, ref_pt, up);
02828 }
02829 
02830 
02832 Stereo_camera_f::Stereo_camera_f(const Stereo_camera_f& c)
02833     : Camera_f(c)
02834 {
02835     left_prp  = 0;
02836     right_prp = 0;
02837     left_vrp  = 0;
02838     right_vrp = 0;
02839 
02840     *this = c;
02841 }
02842 
02843 
02869 Stereo_camera_f::Stereo_camera_f(const char* fname) 
02870     throw (jwscxx::base::Arg_error, jwscxx::base::IO_error)
02871     : Camera_f(0,0,0, 0,0,-1, 0,1,0, 60.0f, 0, 1)
02872 {
02873     left_prp  = 0;
02874     right_prp = 0;
02875     left_vrp  = 0;
02876     right_vrp = 0;
02877 
02878     jwscxx::base::Readable::read(fname);
02879 }
02880 
02881 
02907 Stereo_camera_f::Stereo_camera_f(std::istream& in) 
02908     throw (jwscxx::base::Arg_error, jwscxx::base::IO_error)
02909     : Camera_f(0,0,0, 0,0,-1, 0,1,0, 60.0f, 0, 1)
02910 {
02911     left_prp  = 0;
02912     right_prp = 0;
02913     left_vrp  = 0;
02914     right_vrp = 0;
02915 
02916     read(in);
02917 }
02918 
02919 
02920 Stereo_camera_f::~Stereo_camera_f()
02921 {
02922     free_vector_f(left_vrp);
02923     free_vector_f(left_prp);
02924     free_vector_f(right_vrp);
02925     free_vector_f(right_prp);
02926 }
02927 
02928 
02936 Stereo_camera_f& Stereo_camera_f::operator=(const Stereo_camera_f &c)
02937 {
02938     Camera_f::operator=(c);
02939 
02940     copy_vector_f(&left_vrp, c.left_vrp);
02941     copy_vector_f(&right_vrp, c.right_vrp);
02942     copy_vector_f(&left_prp, c.left_prp);
02943     copy_vector_f(&right_prp, c.right_prp);
02944 
02945     separation = c.separation;
02946     ndfl = c.ndfl;
02947 
02948     return *this;
02949 }
02950 
02951 
02953 Stereo_camera_f* Stereo_camera_f::clone() const
02954 {
02955     return new Stereo_camera_f(*this);
02956 }
02957 
02958 
02959 const jwsc::Vector_f* Stereo_camera_f::get_left_prp() const 
02960 { 
02961     return (const jwsc::Vector_f*)left_prp; 
02962 }
02963 
02964 
02965 const jwsc::Vector_f* Stereo_camera_f::get_right_prp() const 
02966 { 
02967     return (const jwsc::Vector_f*)right_prp; 
02968 }
02969 
02970 
02971 const jwsc::Vector_f* Stereo_camera_f::get_left_vrp() const 
02972 { 
02973     return (const jwsc::Vector_f*)left_vrp; 
02974 }
02975 
02976 
02977 const jwsc::Vector_f* Stereo_camera_f::get_right_vrp() const 
02978 { 
02979     return (const jwsc::Vector_f*)right_vrp; 
02980 }
02981 
02982 
02988 void Stereo_camera_f::set_aperture(float aperture) throw (Arg_error)
02989 {
02990     Camera_f::set_aperture(aperture);
02991 
02992     ndfl = near / focal_length;
02993 }
02994 
02995 
03004 void Stereo_camera_f::set_f_with_new_aperture_using_prp(float f) 
03005     throw (Arg_error)
03006 {
03007     Camera_f::set_f_with_new_aperture_using_prp(f);
03008 
03009     separation = focal_length / 30.0f;
03010     ndfl = near / focal_length;
03011 
03012     assert(copy_vector_f(&left_prp, prp) == 0);
03013     assert(copy_vector_f(&left_vrp, vrp) == 0);
03014 
03015     assert(copy_vector_f(&right_prp, prp) == 0);
03016     assert(copy_vector_f(&right_vrp, vrp) == 0);
03017 
03018     float t_x = 0.5f*separation*u->elts[0];
03019     float t_y = 0.5f*separation*u->elts[1];
03020     float t_z = 0.5f*separation*u->elts[2];
03021 
03022     left_prp->elts[0] -= t_x;  left_vrp->elts[0] -= t_x;
03023     left_prp->elts[1] -= t_y;  left_vrp->elts[1] -= t_y;
03024     left_prp->elts[2] -= t_z;  left_vrp->elts[2] -= t_z;
03025 
03026     right_prp->elts[0] += t_x;  right_vrp->elts[0] += t_x;
03027     right_prp->elts[1] += t_y;  right_vrp->elts[1] += t_y;
03028     right_prp->elts[2] += t_z;  right_vrp->elts[2] += t_z;
03029 }
03030 
03031 
03040 void Stereo_camera_f::set_f_with_same_aperture_using_prp(float f) 
03041     throw (Arg_error)
03042 {
03043     Camera_f::set_f_with_same_aperture_using_prp(f);
03044 
03045     separation = focal_length / 30.0f;
03046     ndfl = near / focal_length;
03047 
03048     assert(copy_vector_f(&left_prp, prp) == 0);
03049     assert(copy_vector_f(&left_vrp, vrp) == 0);
03050 
03051     assert(copy_vector_f(&right_prp, prp) == 0);
03052     assert(copy_vector_f(&right_vrp, vrp) == 0);
03053 
03054     float t_x = 0.5f*separation*u->elts[0];
03055     float t_y = 0.5f*separation*u->elts[1];
03056     float t_z = 0.5f*separation*u->elts[2];
03057 
03058     left_prp->elts[0] -= t_x;  left_vrp->elts[0] -= t_x;
03059     left_prp->elts[1] -= t_y;  left_vrp->elts[1] -= t_y;
03060     left_prp->elts[2] -= t_z;  left_vrp->elts[2] -= t_z;
03061 
03062     right_prp->elts[0] += t_x;  right_vrp->elts[0] += t_x;
03063     right_prp->elts[1] += t_y;  right_vrp->elts[1] += t_y;
03064     right_prp->elts[2] += t_z;  right_vrp->elts[2] += t_z;
03065 }
03066 
03067 
03076 void Stereo_camera_f::set_f_with_new_aperture_using_vrp(float f) 
03077     throw (Arg_error)
03078 {
03079     Camera_f::set_f_with_new_aperture_using_vrp(f);
03080 
03081     separation = focal_length / 30.0f;
03082     ndfl = near / focal_length;
03083 
03084     assert(copy_vector_f(&left_prp, prp) == 0);
03085     assert(copy_vector_f(&left_vrp, vrp) == 0);
03086 
03087     assert(copy_vector_f(&right_prp, prp) == 0);
03088     assert(copy_vector_f(&right_vrp, vrp) == 0);
03089 
03090     float t_x = 0.5f*separation*u->elts[0];
03091     float t_y = 0.5f*separation*u->elts[1];
03092     float t_z = 0.5f*separation*u->elts[2];
03093 
03094     left_prp->elts[0] -= t_x;  left_vrp->elts[0] -= t_x;
03095     left_prp->elts[1] -= t_y;  left_vrp->elts[1] -= t_y;
03096     left_prp->elts[2] -= t_z;  left_vrp->elts[2] -= t_z;
03097 
03098     right_prp->elts[0] += t_x;  right_vrp->elts[0] += t_x;
03099     right_prp->elts[1] += t_y;  right_vrp->elts[1] += t_y;
03100     right_prp->elts[2] += t_z;  right_vrp->elts[2] += t_z;
03101 }
03102 
03103 
03112 void Stereo_camera_f::set_f_with_same_aperture_using_vrp(float f) 
03113     throw (Arg_error)
03114 {
03115     Camera_f::set_f_with_same_aperture_using_vrp(f);
03116 
03117     separation = focal_length / 30.0f;
03118     ndfl = near / focal_length;
03119 
03120     assert(copy_vector_f(&left_prp, prp) == 0);
03121     assert(copy_vector_f(&left_vrp, vrp) == 0);
03122 
03123     assert(copy_vector_f(&right_prp, prp) == 0);
03124     assert(copy_vector_f(&right_vrp, vrp) == 0);
03125 
03126     float t_x = 0.5f*separation*u->elts[0];
03127     float t_y = 0.5f*separation*u->elts[1];
03128     float t_z = 0.5f*separation*u->elts[2];
03129 
03130     left_prp->elts[0] -= t_x;  left_vrp->elts[0] -= t_x;
03131     left_prp->elts[1] -= t_y;  left_vrp->elts[1] -= t_y;
03132     left_prp->elts[2] -= t_z;  left_vrp->elts[2] -= t_z;
03133 
03134     right_prp->elts[0] += t_x;  right_vrp->elts[0] += t_x;
03135     right_prp->elts[1] += t_y;  right_vrp->elts[1] += t_y;
03136     right_prp->elts[2] += t_z;  right_vrp->elts[2] += t_z;
03137 }
03138 
03139 
03146 void Stereo_camera_f::set_clipping(float clip_near, float clip_far) 
03147     throw (Arg_error)
03148 {
03149     Camera_f::set_clipping(clip_near, clip_far);
03150 
03151     ndfl = near / focal_length;
03152 }
03153 
03154 
03164 void Stereo_camera_f::rotate(float phi, float x, float y, float z) 
03165     throw (Arg_error)
03166 {
03167     Camera_f::rotate(phi, x, y, z);
03168 
03169     multiply_matrix_and_vector_f(&left_vrp, R, left_vrp);
03170     multiply_matrix_and_vector_f(&left_prp, R, left_prp);
03171     multiply_matrix_and_vector_f(&right_vrp, R, right_vrp);
03172     multiply_matrix_and_vector_f(&right_prp, R, right_prp);
03173 }
03174 
03175 
03176 void Stereo_camera_f::rotate(float angle, const jwsc::Vector_f* r) 
03177     throw (jwscxx::base::Arg_error) 
03178 { 
03179     Camera_f::rotate(angle, r); 
03180 }
03181 
03182 
03188 void Stereo_camera_f::translate(float x, float y, float z)
03189 {
03190     Camera_f::translate(x, y, z);
03191 
03192     left_prp->elts[0] += x;  left_vrp->elts[0] += x;
03193     left_prp->elts[1] += y;  left_vrp->elts[1] += y;
03194     left_prp->elts[2] += z;  left_vrp->elts[2] += z;
03195 
03196     right_prp->elts[0] += x;  right_vrp->elts[0] += x;
03197     right_prp->elts[1] += y;  right_vrp->elts[1] += y;
03198     right_prp->elts[2] += z;  right_vrp->elts[2] += z;
03199 }
03200 
03201 
03205 void Stereo_camera_f::translate(const jwsc::Vector_f* t) throw (Arg_error)
03206 {
03207     Camera_f::translate(t);
03208 
03209     add_vectors_f(&left_vrp, left_vrp, t);
03210     add_vectors_f(&left_prp, left_prp, t);
03211 
03212     add_vectors_f(&right_vrp, right_vrp, t);
03213     add_vectors_f(&right_prp, right_prp, t);
03214 }
03215 
03216 
03230 void Stereo_camera_f::look_at
03231 (
03232     float focal_pt_x,
03233     float focal_pt_y,
03234     float focal_pt_z,
03235     float ref_pt_x,
03236     float ref_pt_y,
03237     float ref_pt_z,
03238     float up_x,
03239     float up_y,
03240     float up_z
03241 )
03242 throw (jwscxx::base::Arg_error)
03243 {
03244     Camera_f::look_at(focal_pt_x, focal_pt_y, focal_pt_z,
03245             ref_pt_x, ref_pt_y, ref_pt_z, up_x, up_y, up_z);
03246 
03247     separation = focal_length / 30.0f;
03248     ndfl = near / focal_length;
03249 
03250     copy_vector_f(&left_prp, prp);
03251     copy_vector_f(&left_vrp, vrp);
03252 
03253     copy_vector_f(&right_prp, prp);
03254     copy_vector_f(&right_vrp, vrp);
03255 
03256     float t_x = 0.5f*separation*u->elts[0];
03257     float t_y = 0.5f*separation*u->elts[1];
03258     float t_z = 0.5f*separation*u->elts[2];
03259 
03260     left_prp->elts[0] -= t_x;  left_vrp->elts[0] -= t_x;
03261     left_prp->elts[1] -= t_y;  left_vrp->elts[1] -= t_y;
03262     left_prp->elts[2] -= t_z;  left_vrp->elts[2] -= t_z;
03263 
03264     right_prp->elts[0] += t_x;  right_vrp->elts[0] += t_x;
03265     right_prp->elts[1] += t_y;  right_vrp->elts[1] += t_y;
03266     right_prp->elts[2] += t_z;  right_vrp->elts[2] += t_z;
03267 }
03268 
03269 
03274 void Stereo_camera_f::set_left_gl_modelview()
03275 {
03276     GLfloat M[16] = {0};
03277 
03278     glMatrixMode(GL_MODELVIEW);
03279 
03280     glLoadIdentity();
03281 
03282     M[0] = u->elts[0];  M[4] = u->elts[1];  M[8]  = u->elts[2];
03283     M[1] = v->elts[0];  M[5] = v->elts[1];  M[9]  = v->elts[2];
03284     M[2] = n->elts[0];  M[6] = n->elts[1];  M[10] = n->elts[2];
03285     M[15] = 1;
03286     glMultMatrixf(M);
03287 
03288     glTranslatef(-left_prp->elts[0], -left_prp->elts[1], -left_prp->elts[2]);
03289 }
03290 
03291 
03296 void Stereo_camera_f::set_right_gl_modelview()
03297 {
03298     GLfloat M[16] = {0};
03299 
03300     glMatrixMode(GL_MODELVIEW);
03301 
03302     glLoadIdentity();
03303 
03304     M[0] = u->elts[0];  M[4] = u->elts[1];  M[8]  = u->elts[2];
03305     M[1] = v->elts[0];  M[5] = v->elts[1];  M[9]  = v->elts[2];
03306     M[2] = n->elts[0];  M[6] = n->elts[1];  M[10] = n->elts[2];
03307     M[15] = 1;
03308     glMultMatrixf(M);
03309 
03310     glTranslatef(-right_prp->elts[0], -right_prp->elts[1], -right_prp->elts[2]);
03311 }
03312 
03313 
03318 void Stereo_camera_f::set_left_gl_projection()
03319 {
03320     glMatrixMode(GL_PROJECTION);
03321 
03322     glLoadIdentity();
03323 
03324     float aspect = get_gl_viewport_aspect();
03325     float left   = -aspect*half_near_height + 0.5f*separation*ndfl;
03326     float right  =  aspect*half_near_height + 0.5f*separation*ndfl;
03327     float top    =  half_near_height;
03328     float bottom = -half_near_height;
03329 
03330     glFrustum(left, right, bottom, top, near, far);
03331 }
03332 
03333 
03338 void Stereo_camera_f::set_right_gl_projection()
03339 {
03340     glMatrixMode(GL_PROJECTION);
03341 
03342     glLoadIdentity();
03343 
03344     float aspect = get_gl_viewport_aspect();
03345     float left   = -aspect*half_near_height - 0.5f*separation*ndfl;
03346     float right  =  aspect*half_near_height - 0.5f*separation*ndfl;
03347     float top    =  half_near_height;
03348     float bottom = -half_near_height;
03349 
03350     glFrustum(left, right, bottom, top, near, far);
03351 }
03352 
03353 
03379 void Stereo_camera_f::read(std::istream& in) throw (jwscxx::base::IO_error,
03380         jwscxx::base::Arg_error)
03381 {
03382     using std::ostringstream;
03383     using std::istringstream;
03384 
03385     const char* field_value;
03386 
03387     Camera_f::read(in);
03388 
03389 
03390     // Left VRP
03391     if (!(field_value = read_field_value(in, "Left VRP")))
03392     {
03393         throw Arg_error("Missing Left VRP fields");
03394     }
03395     istringstream ist(field_value);
03396     ist >> left_vrp->elts[0] >> left_vrp->elts[1] >> left_vrp->elts[2];
03397     if (ist.fail())
03398     {
03399         throw Arg_error("Invalid Left VRP");
03400     }
03401     ist.clear(std::ios_base::goodbit);
03402 
03403 
03404     // Right VRP
03405     if (!(field_value = read_field_value(in, "Right VRP")))
03406     {
03407         throw Arg_error("Missing Right VRP fields");
03408     }
03409     ist.str(field_value);
03410     ist >> right_vrp->elts[0] >> right_vrp->elts[1] >> right_vrp->elts[2];
03411     if (ist.fail())
03412     {
03413         throw Arg_error("Invalid Right VRP");
03414     }
03415     ist.clear(std::ios_base::goodbit);
03416 
03417 
03418     // Left PRP
03419     if (!(field_value = read_field_value(in, "Left PRP")))
03420     {
03421         throw Arg_error("Missing Left PRP fields");
03422     }
03423     ist.str(field_value);
03424     ist >> left_prp->elts[0] >> left_prp->elts[1] >> left_prp->elts[2];
03425     if (ist.fail())
03426     {
03427         throw Arg_error("Invalid Left PRP");
03428     }
03429     ist.clear(std::ios_base::goodbit);
03430 
03431 
03432     // Right PRP
03433     if (!(field_value = read_field_value(in, "Right PRP")))
03434     {
03435         throw Arg_error("Missing Right PRP fields");
03436     }
03437     ist.str(field_value);
03438     ist >> right_prp->elts[0] >> right_prp->elts[1] >> right_prp->elts[2];
03439     if (ist.fail())
03440     {
03441         throw Arg_error("Invalid Right PRP");
03442     }
03443     ist.clear(std::ios_base::goodbit);
03444 
03445 
03446     // Derived...
03447     separation = focal_length / 30.0f;
03448     ndfl = near / focal_length;
03449 }
03450 
03451 
03476 void Stereo_camera_f::write(std::ostream& out) const 
03477     throw (jwscxx::base::IO_error)
03478 {
03479     Camera_f::write(out);
03480 
03481     out << "   Left VRP: " << left_vrp->elts[0] << ' '
03482                            << left_vrp->elts[1] << ' '
03483                            << left_vrp->elts[2] << '\n'
03484         << "  Right VRP: " << right_vrp->elts[0] << ' '
03485                            << right_vrp->elts[1] << ' '
03486                            << right_vrp->elts[2] << '\n'
03487         << "   Left PRP: " << left_prp->elts[0] << ' '
03488                            << left_prp->elts[1] << ' '
03489                            << left_prp->elts[2] << '\n'
03490         << "  Right PRP: " << right_prp->elts[0] << ' '
03491                            << right_prp->elts[1] << ' '
03492                            << right_prp->elts[2] << '\n';
03493 }
03494 
03495 
03496 
03518 Stereo_camera_d::Stereo_camera_d
03519 (
03520     double focal_pt_x,
03521     double focal_pt_y,
03522     double focal_pt_z,
03523     double ref_pt_x,
03524     double ref_pt_y,
03525     double ref_pt_z,
03526     double up_x,
03527     double up_y,
03528     double up_z,
03529     double aperture, 
03530     double clip_near, 
03531     double clip_far
03532 )
03533 throw (Arg_error)
03534     : Camera_d(focal_pt_x, focal_pt_y, focal_pt_z, ref_pt_x, ref_pt_y, ref_pt_z,
03535             up_x, up_y, up_z, aperture, clip_near, clip_far)
03536 {
03537     left_prp  = 0;
03538     left_vrp  = 0;
03539     right_prp = 0;
03540     right_vrp = 0;
03541 
03542     look_at(focal_pt_x, focal_pt_y, focal_pt_z, ref_pt_x, ref_pt_y, ref_pt_z,
03543             up_x, up_y, up_z);
03544 }
03545 
03546 
03562 Stereo_camera_d::Stereo_camera_d
03563 (
03564     const jwsc::Vector_d* focal_pt,
03565     const jwsc::Vector_d* ref_pt,
03566     const jwsc::Vector_d* up,
03567     double                aperture, 
03568     double                clip_near, 
03569     double                clip_far
03570 )
03571 throw (Arg_error)
03572     : Camera_d(focal_pt, ref_pt, up, aperture, clip_near, clip_far)
03573 {
03574     left_prp  = 0;
03575     left_vrp  = 0;
03576     right_prp = 0;
03577     right_vrp = 0;
03578 
03579     Camera_d::look_at(focal_pt, ref_pt, up);
03580 }
03581 
03582 
03584 Stereo_camera_d::Stereo_camera_d(const Stereo_camera_d& c)
03585     : Camera_d(c)
03586 {
03587     left_prp  = 0;
03588     right_prp = 0;
03589     left_vrp  = 0;
03590     right_vrp = 0;
03591 
03592     *this = c;
03593 }
03594 
03595 
03621 Stereo_camera_d::Stereo_camera_d(const char* fname) 
03622     throw (jwscxx::base::Arg_error, jwscxx::base::IO_error)
03623     : Camera_d(0,0,0, 0,0,-1, 0,1,0, 60.0, 0, 1)
03624 {
03625     left_prp  = 0;
03626     right_prp = 0;
03627     left_vrp  = 0;
03628     right_vrp = 0;
03629 
03630     jwscxx::base::Readable::read(fname);
03631 }
03632 
03633 
03659 Stereo_camera_d::Stereo_camera_d(std::istream& in) 
03660     throw (jwscxx::base::Arg_error, jwscxx::base::IO_error)
03661     : Camera_d(0,0,0, 0,0,-1, 0,1,0, 60.0, 0, 1)
03662 {
03663     left_prp  = 0;
03664     right_prp = 0;
03665     left_vrp  = 0;
03666     right_vrp = 0;
03667 
03668     read(in);
03669 }
03670 
03671 
03672 Stereo_camera_d::~Stereo_camera_d()
03673 {
03674     free_vector_d(left_vrp);
03675     free_vector_d(left_prp);
03676     free_vector_d(right_vrp);
03677     free_vector_d(right_prp);
03678 }
03679 
03680 
03688 Stereo_camera_d& Stereo_camera_d::operator=(const Stereo_camera_d &c)
03689 {
03690     Camera_d::operator=(c);
03691 
03692     copy_vector_d(&left_vrp, c.left_vrp);
03693     copy_vector_d(&right_vrp, c.right_vrp);
03694     copy_vector_d(&left_prp, c.left_prp);
03695     copy_vector_d(&right_prp, c.right_prp);
03696 
03697     separation = c.separation;
03698     ndfl = c.ndfl;
03699 
03700     return *this;
03701 }
03702 
03703 
03705 Stereo_camera_d* Stereo_camera_d::clone() const
03706 {
03707     return new Stereo_camera_d(*this);
03708 }
03709 
03710 
03711 const jwsc::Vector_d* Stereo_camera_d::get_left_prp() const 
03712 { 
03713     return (const jwsc::Vector_d*)left_prp; 
03714 }
03715 
03716 
03717 const jwsc::Vector_d* Stereo_camera_d::get_right_prp() const 
03718 { 
03719     return (const jwsc::Vector_d*)right_prp; 
03720 }
03721 
03722 
03723 const jwsc::Vector_d* Stereo_camera_d::get_left_vrp() const 
03724 { 
03725     return (const jwsc::Vector_d*)left_vrp; 
03726 }
03727 
03728 
03729 const jwsc::Vector_d* Stereo_camera_d::get_right_vrp() const 
03730 { 
03731     return (const jwsc::Vector_d*)right_vrp; 
03732 }
03733 
03734 
03740 void Stereo_camera_d::set_aperture(double aperture) throw (Arg_error)
03741 {
03742     Camera_d::set_aperture(aperture);
03743 
03744     ndfl = near / focal_length;
03745 }
03746 
03747 
03756 void Stereo_camera_d::set_f_with_new_aperture_using_prp(double f) 
03757     throw (Arg_error)
03758 {
03759     Camera_d::set_f_with_new_aperture_using_prp(f);
03760 
03761     separation = focal_length / 30.0;
03762     ndfl = near / focal_length;
03763 
03764     assert(copy_vector_d(&left_prp, prp) == 0);
03765     assert(copy_vector_d(&left_vrp, vrp) == 0);
03766 
03767     assert(copy_vector_d(&right_prp, prp) == 0);
03768     assert(copy_vector_d(&right_vrp, vrp) == 0);
03769 
03770     double t_x = 0.5*separation*u->elts[0];
03771     double t_y = 0.5*separation*u->elts[1];
03772     double t_z = 0.5*separation*u->elts[2];
03773 
03774     left_prp->elts[0] -= t_x;  left_vrp->elts[0] -= t_x;
03775     left_prp->elts[1] -= t_y;  left_vrp->elts[1] -= t_y;
03776     left_prp->elts[2] -= t_z;  left_vrp->elts[2] -= t_z;
03777 
03778     right_prp->elts[0] += t_x;  right_vrp->elts[0] += t_x;
03779     right_prp->elts[1] += t_y;  right_vrp->elts[1] += t_y;
03780     right_prp->elts[2] += t_z;  right_vrp->elts[2] += t_z;
03781 }
03782 
03783 
03792 void Stereo_camera_d::set_f_with_same_aperture_using_prp(double f) 
03793     throw (Arg_error)
03794 {
03795     Camera_d::set_f_with_same_aperture_using_prp(f);
03796 
03797     separation = focal_length / 30.0;
03798     ndfl = near / focal_length;
03799 
03800     assert(copy_vector_d(&left_prp, prp) == 0);
03801     assert(copy_vector_d(&left_vrp, vrp) == 0);
03802 
03803     assert(copy_vector_d(&right_prp, prp) == 0);
03804     assert(copy_vector_d(&right_vrp, vrp) == 0);
03805 
03806     double t_x = 0.5*separation*u->elts[0];
03807     double t_y = 0.5*separation*u->elts[1];
03808     double t_z = 0.5*separation*u->elts[2];
03809 
03810     left_prp->elts[0] -= t_x;  left_vrp->elts[0] -= t_x;
03811     left_prp->elts[1] -= t_y;  left_vrp->elts[1] -= t_y;
03812     left_prp->elts[2] -= t_z;  left_vrp->elts[2] -= t_z;
03813 
03814     right_prp->elts[0] += t_x;  right_vrp->elts[0] += t_x;
03815     right_prp->elts[1] += t_y;  right_vrp->elts[1] += t_y;
03816     right_prp->elts[2] += t_z;  right_vrp->elts[2] += t_z;
03817 }
03818 
03819 
03828 void Stereo_camera_d::set_f_with_new_aperture_using_vrp(double f) 
03829     throw (Arg_error)
03830 {
03831     Camera_d::set_f_with_new_aperture_using_vrp(f);
03832 
03833     separation = focal_length / 30.0;
03834     ndfl = near / focal_length;
03835 
03836     assert(copy_vector_d(&left_prp, prp) == 0);
03837     assert(copy_vector_d(&left_vrp, vrp) == 0);
03838 
03839     assert(copy_vector_d(&right_prp, prp) == 0);
03840     assert(copy_vector_d(&right_vrp, vrp) == 0);
03841 
03842     double t_x = 0.5*separation*u->elts[0];
03843     double t_y = 0.5*separation*u->elts[1];
03844     double t_z = 0.5*separation*u->elts[2];
03845 
03846     left_prp->elts[0] -= t_x;  left_vrp->elts[0] -= t_x;
03847     left_prp->elts[1] -= t_y;  left_vrp->elts[1] -= t_y;
03848     left_prp->elts[2] -= t_z;  left_vrp->elts[2] -= t_z;
03849 
03850     right_prp->elts[0] += t_x;  right_vrp->elts[0] += t_x;
03851     right_prp->elts[1] += t_y;  right_vrp->elts[1] += t_y;
03852     right_prp->elts[2] += t_z;  right_vrp->elts[2] += t_z;
03853 }
03854 
03855 
03864 void Stereo_camera_d::set_f_with_same_aperture_using_vrp(double f) 
03865     throw (Arg_error)
03866 {
03867     Camera_d::set_f_with_same_aperture_using_vrp(f);
03868 
03869     separation = focal_length / 30.0;
03870     ndfl = near / focal_length;
03871 
03872     assert(copy_vector_d(&left_prp, prp) == 0);
03873     assert(copy_vector_d(&left_vrp, vrp) == 0);
03874 
03875     assert(copy_vector_d(&right_prp, prp) == 0);
03876     assert(copy_vector_d(&right_vrp, vrp) == 0);
03877 
03878     double t_x = 0.5*separation*u->elts[0];
03879     double t_y = 0.5*separation*u->elts[1];
03880     double t_z = 0.5*separation*u->elts[2];
03881 
03882     left_prp->elts[0] -= t_x;  left_vrp->elts[0] -= t_x;
03883     left_prp->elts[1] -= t_y;  left_vrp->elts[1] -= t_y;
03884     left_prp->elts[2] -= t_z;  left_vrp->elts[2] -= t_z;
03885 
03886     right_prp->elts[0] += t_x;  right_vrp->elts[0] += t_x;
03887     right_prp->elts[1] += t_y;  right_vrp->elts[1] += t_y;
03888     right_prp->elts[2] += t_z;  right_vrp->elts[2] += t_z;
03889 }
03890 
03891 
03898 void Stereo_camera_d::set_clipping(double clip_near, double clip_far) 
03899     throw (Arg_error)
03900 {
03901     Camera_d::set_clipping(clip_near, clip_far);
03902 
03903     ndfl = near / focal_length;
03904 }
03905 
03906 
03916 void Stereo_camera_d::rotate(double phi, double x, double y, double z) 
03917     throw (Arg_error)
03918 {
03919     Camera_d::rotate(phi, x, y, z);
03920 
03921     multiply_matrix_and_vector_d(&left_vrp, R, left_vrp);
03922     multiply_matrix_and_vector_d(&left_prp, R, left_prp);
03923     multiply_matrix_and_vector_d(&right_vrp, R, right_vrp);
03924     multiply_matrix_and_vector_d(&right_prp, R, right_prp);
03925 }
03926 
03927 
03928 void Stereo_camera_d::rotate(double angle, const jwsc::Vector_d* r) 
03929     throw (jwscxx::base::Arg_error) 
03930 { 
03931     Camera_d::rotate(angle, r); 
03932 }
03933 
03934 
03940 void Stereo_camera_d::translate(double x, double y, double z)
03941 {
03942     Camera_d::translate(x, y, z);
03943 
03944     left_prp->elts[0] += x;  left_vrp->elts[0] += x;
03945     left_prp->elts[1] += y;  left_vrp->elts[1] += y;
03946     left_prp->elts[2] += z;  left_vrp->elts[2] += z;
03947 
03948     right_prp->elts[0] += x;  right_vrp->elts[0] += x;
03949     right_prp->elts[1] += y;  right_vrp->elts[1] += y;
03950     right_prp->elts[2] += z;  right_vrp->elts[2] += z;
03951 }
03952 
03953 
03957 void Stereo_camera_d::translate(const jwsc::Vector_d* t) throw (Arg_error)
03958 {
03959     Camera_d::translate(t);
03960 
03961     add_vectors_d(&left_vrp, left_vrp, t);
03962     add_vectors_d(&left_prp, left_prp, t);
03963 
03964     add_vectors_d(&right_vrp, right_vrp, t);
03965     add_vectors_d(&right_prp, right_prp, t);
03966 }
03967 
03968 
03982 void Stereo_camera_d::look_at
03983 (
03984     double focal_pt_x,
03985     double focal_pt_y,
03986     double focal_pt_z,
03987     double ref_pt_x,
03988     double ref_pt_y,
03989     double ref_pt_z,
03990     double up_x,
03991     double up_y,
03992     double up_z
03993 )
03994 throw (jwscxx::base::Arg_error)
03995 {
03996     Camera_d::look_at(focal_pt_x, focal_pt_y, focal_pt_z,
03997             ref_pt_x, ref_pt_y, ref_pt_z, up_x, up_y, up_z);
03998 
03999     separation = focal_length / 30.0;
04000     ndfl = near / focal_length;
04001 
04002     copy_vector_d(&left_prp, prp);
04003     copy_vector_d(&left_vrp, vrp);
04004 
04005     copy_vector_d(&right_prp, prp);
04006     copy_vector_d(&right_vrp, vrp);
04007 
04008     double t_x = 0.5*separation*u->elts[0];
04009     double t_y = 0.5*separation*u->elts[1];
04010     double t_z = 0.5*separation*u->elts[2];
04011 
04012     left_prp->elts[0] -= t_x;  left_vrp->elts[0] -= t_x;
04013     left_prp->elts[1] -= t_y;  left_vrp->elts[1] -= t_y;
04014     left_prp->elts[2] -= t_z;  left_vrp->elts[2] -= t_z;
04015 
04016     right_prp->elts[0] += t_x;  right_vrp->elts[0] += t_x;
04017     right_prp->elts[1] += t_y;  right_vrp->elts[1] += t_y;
04018     right_prp->elts[2] += t_z;  right_vrp->elts[2] += t_z;
04019 }
04020 
04021 
04026 void Stereo_camera_d::set_left_gl_modelview()
04027 {
04028     GLdouble M[16] = {0};
04029 
04030     glMatrixMode(GL_MODELVIEW);
04031 
04032     glLoadIdentity();
04033 
04034     M[0] = u->elts[0];  M[4] = u->elts[1];  M[8]  = u->elts[2];
04035     M[1] = v->elts[0];  M[5] = v->elts[1];  M[9]  = v->elts[2];
04036     M[2] = n->elts[0];  M[6] = n->elts[1];  M[10] = n->elts[2];
04037     M[15] = 1;
04038     glMultMatrixd(M);
04039 
04040     glTranslated(-left_prp->elts[0], -left_prp->elts[1], -left_prp->elts[2]);
04041 }
04042 
04043 
04048 void Stereo_camera_d::set_right_gl_modelview()
04049 {
04050     GLdouble M[16] = {0};
04051 
04052     glMatrixMode(GL_MODELVIEW);
04053 
04054     glLoadIdentity();
04055 
04056     M[0] = u->elts[0];  M[4] = u->elts[1];  M[8]  = u->elts[2];
04057     M[1] = v->elts[0];  M[5] = v->elts[1];  M[9]  = v->elts[2];
04058     M[2] = n->elts[0];  M[6] = n->elts[1];  M[10] = n->elts[2];
04059     M[15] = 1;
04060     glMultMatrixd(M);
04061 
04062     glTranslated(-right_prp->elts[0], -right_prp->elts[1], -right_prp->elts[2]);
04063 }
04064 
04065 
04070 void Stereo_camera_d::set_left_gl_projection()
04071 {
04072     glMatrixMode(GL_PROJECTION);
04073 
04074     glLoadIdentity();
04075 
04076     double aspect = get_gl_viewport_aspect();
04077     double left   = -aspect*half_near_height + 0.5*separation*ndfl;
04078     double right  =  aspect*half_near_height + 0.5*separation*ndfl;
04079     double top    =  half_near_height;
04080     double bottom = -half_near_height;
04081 
04082     glFrustum(left, right, bottom, top, near, far);
04083 }
04084 
04085 
04090 void Stereo_camera_d::set_right_gl_projection()
04091 {
04092     glMatrixMode(GL_PROJECTION);
04093 
04094     glLoadIdentity();
04095 
04096     double aspect = get_gl_viewport_aspect();
04097     double left   = -aspect*half_near_height - 0.5*separation*ndfl;
04098     double right  =  aspect*half_near_height - 0.5*separation*ndfl;
04099     double top    =  half_near_height;
04100     double bottom = -half_near_height;
04101 
04102     glFrustum(left, right, bottom, top, near, far);
04103 }
04104 
04105 
04131 void Stereo_camera_d::read(std::istream& in) throw (jwscxx::base::IO_error,
04132         jwscxx::base::Arg_error)
04133 {
04134     using std::ostringstream;
04135     using std::istringstream;
04136 
04137     const char* field_value;
04138 
04139     Camera_d::read(in);
04140 
04141 
04142     // Left VRP
04143     if (!(field_value = read_field_value(in, "Left VRP")))
04144     {
04145         throw Arg_error("Missing Left VRP fields");
04146     }
04147     istringstream ist(field_value);
04148     ist >> left_vrp->elts[0] >> left_vrp->elts[1] >> left_vrp->elts[2];
04149     if (ist.fail())
04150     {
04151         throw Arg_error("Invalid Left VRP");
04152     }
04153     ist.clear(std::ios_base::goodbit);
04154 
04155 
04156     // Right VRP
04157     if (!(field_value = read_field_value(in, "Right VRP")))
04158     {
04159         throw Arg_error("Missing Right VRP fields");
04160     }
04161     ist.str(field_value);
04162     ist >> right_vrp->elts[0] >> right_vrp->elts[1] >> right_vrp->elts[2];
04163     if (ist.fail())
04164     {
04165         throw Arg_error("Invalid Right VRP");
04166     }
04167     ist.clear(std::ios_base::goodbit);
04168 
04169 
04170     // Left PRP
04171     if (!(field_value = read_field_value(in, "Left PRP")))
04172     {
04173         throw Arg_error("Missing Left PRP fields");
04174     }
04175     ist.str(field_value);
04176     ist >> left_prp->elts[0] >> left_prp->elts[1] >> left_prp->elts[2];
04177     if (ist.fail())
04178     {
04179         throw Arg_error("Invalid Left PRP");
04180     }
04181     ist.clear(std::ios_base::goodbit);
04182 
04183 
04184     // Right PRP
04185     if (!(field_value = read_field_value(in, "Right PRP")))
04186     {
04187         throw Arg_error("Missing Right PRP fields");
04188     }
04189     ist.str(field_value);
04190     ist >> right_prp->elts[0] >> right_prp->elts[1] >> right_prp->elts[2];
04191     if (ist.fail())
04192     {
04193         throw Arg_error("Invalid Right PRP");
04194     }
04195     ist.clear(std::ios_base::goodbit);
04196 
04197 
04198     // Derived...
04199     separation = focal_length / 30.0;
04200     ndfl = near / focal_length;
04201 }
04202 
04203 
04228 void Stereo_camera_d::write(std::ostream& out) const 
04229     throw (jwscxx::base::IO_error)
04230 {
04231     Camera_d::write(out);
04232 
04233     out << "   Left VRP: " << left_vrp->elts[0] << ' '
04234                            << left_vrp->elts[1] << ' '
04235                            << left_vrp->elts[2] << '\n'
04236         << "  Right VRP: " << right_vrp->elts[0] << ' '
04237                            << right_vrp->elts[1] << ' '
04238                            << right_vrp->elts[2] << '\n'
04239         << "   Left PRP: " << left_prp->elts[0] << ' '
04240                            << left_prp->elts[1] << ' '
04241                            << left_prp->elts[2] << '\n'
04242         << "  Right PRP: " << right_prp->elts[0] << ' '
04243                            << right_prp->elts[1] << ' '
04244                            << right_prp->elts[2] << '\n';
04245 }