JWS C++ Library
C++ language utility library
|
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 }