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 00046 #include <jwsc++/config.h> 00047 00048 #include <cassert> 00049 #include <cmath> 00050 #include <iostream> 00051 #include <vector> 00052 00053 #include <inttypes.h> 00054 00055 #if defined JWSCXX_HAVE_OPENGL 00056 #include <GL/gl.h> 00057 #elif defined JWSCXX_HAVE_OPENGL_FRAMEWORK 00058 #include <OpenGL/gl.h> 00059 #endif 00060 00061 #include <jwsc/base/bits.h> 00062 #include <jwsc/vector/vector.h> 00063 #include <jwsc/vector/vector_math.h> 00064 #include <jwsc/matrix/matrix.h> 00065 #include <jwsc/matrix/matrix_math.h> 00066 00067 #include <jwsc++/base/exception.h> 00068 #include <jwsc++/graphics/polygon.h> 00069 #include <jwsc++/graphics/parapiped.h> 00070 00071 #ifdef JWSCXX_HAVE_DMALLOC 00072 #include <dmalloc.h> 00073 #endif 00074 00075 00076 using namespace jwscxx::base; 00077 using namespace jwscxx::graphics; 00078 00079 00080 static void create_adjacency(jwsc::Matrix_u32** adjacency_out) 00081 { 00082 using namespace jwsc; 00083 00084 create_matrix_u32(adjacency_out, 6, 4); 00085 Matrix_u32* adjacency = *adjacency_out; 00086 00087 adjacency->elts[5][0] = 1; 00088 adjacency->elts[5][1] = 2; 00089 adjacency->elts[5][2] = 0; 00090 adjacency->elts[5][3] = 3; 00091 00092 adjacency->elts[3][0] = 0; 00093 adjacency->elts[3][1] = 4; 00094 adjacency->elts[3][2] = 1; 00095 adjacency->elts[3][3] = 5; 00096 00097 adjacency->elts[0][0] = 2; 00098 adjacency->elts[0][1] = 4; 00099 adjacency->elts[0][2] = 3; 00100 adjacency->elts[0][3] = 5; 00101 00102 adjacency->elts[2][0] = 0; 00103 adjacency->elts[2][1] = 5; 00104 adjacency->elts[2][2] = 1; 00105 adjacency->elts[2][3] = 4; 00106 00107 adjacency->elts[4][0] = 2; 00108 adjacency->elts[4][1] = 1; 00109 adjacency->elts[4][2] = 3; 00110 adjacency->elts[4][3] = 0; 00111 00112 adjacency->elts[1][0] = 3; 00113 adjacency->elts[1][1] = 4; 00114 adjacency->elts[1][2] = 2; 00115 adjacency->elts[1][3] = 5; 00116 } 00117 00118 00165 Parapiped_f::Parapiped_f 00166 ( 00167 float x1, float y1, float z1, 00168 float x2, float y2, float z2, 00169 float x3, float y3, float z3, 00170 float x4, float y4, float z4 00171 ) 00172 : faces(6, (Polygon_f*)0), points(4, (jwsc::Vector_f*)0) 00173 { 00174 using namespace jwsc; 00175 00176 center = 0; 00177 adjacency = 0; 00178 00179 faces[5] = new Polygon_f(4); 00180 faces[5]->add_point(x1, y1, z1); 00181 faces[5]->add_point(x1 + (x3 - x2), y1 + (y3 - y2), z1 + (z3 - z2)); 00182 faces[5]->add_point(x3, y3, z3); 00183 faces[5]->add_point(x2, y2, z2); 00184 00185 faces[3] = new Polygon_f(4); 00186 faces[3]->add_point(x2, y2, z2); 00187 faces[3]->add_point(x2 + (x4 - x3), y2 + (y4 - y3), z2 + (z4 - z3)); 00188 faces[3]->add_point(x1 + (x4 - x3), y1 + (y4 - y3), z1 + (z4 - z3)); 00189 faces[3]->add_point(x1, y1, z1); 00190 00191 faces[0] = new Polygon_f(4); 00192 faces[0]->add_point(x3, y3, z3); 00193 faces[0]->add_point(x4, y4, z4); 00194 faces[0]->add_point(x2 + (x4 - x3), y2 + (y4 - y3), z2 + (z4 - z3)); 00195 faces[0]->add_point(x2, y2, z2); 00196 00197 faces[2] = new Polygon_f(4); 00198 faces[2]->add_point(x4, y4, z4); 00199 faces[2]->add_point(x3, y3, z3); 00200 faces[2]->add_point(x3 + (x1 - x2), y3 + (y1 - y2), z3 + (z1 - z2)); 00201 faces[2]->add_point(x4 + (x1 - x2), y4 + (y1 - y2), z4 + (z1 - z2)); 00202 00203 faces[4] = new Polygon_f(4); 00204 faces[4]->add_point(x4, y4, z4); 00205 faces[4]->add_point(x4 + (x1 - x2), y4 + (y1 - y2), z4 + (z1 - z2)); 00206 faces[4]->add_point(x1 + (x4 - x3), y1 + (y4 - y3), z1 + (z4 - z3)); 00207 faces[4]->add_point(x2 + (x4 - x3), y2 + (y4 - y3), z2 + (z4 - z3)); 00208 00209 faces[1] = new Polygon_f(4); 00210 faces[1]->add_point(x1, y1, z1); 00211 faces[1]->add_point(x1 + (x4 - x3), y1 + (y4 - y3), z1 + (z4 - z3)); 00212 faces[1]->add_point(x4 + (x1 - x2), y4 + (y1 - y2), z4 + (z1 - z2)); 00213 faces[1]->add_point(x3 + (x1 - x2), y3 + (y1 - y2), z3 + (z1 - z2)); 00214 00215 create_init_vector_f(&(points[0]), 4, 1); 00216 points[0]->elts[0] = x1; 00217 points[0]->elts[1] = y1; 00218 points[0]->elts[2] = z1; 00219 00220 create_init_vector_f(&(points[1]), 4, 1); 00221 points[1]->elts[0] = x2; 00222 points[1]->elts[1] = y2; 00223 points[1]->elts[2] = z2; 00224 00225 create_init_vector_f(&(points[2]), 4, 1); 00226 points[2]->elts[0] = x3; 00227 points[2]->elts[1] = y3; 00228 points[2]->elts[2] = z3; 00229 00230 create_init_vector_f(&(points[3]), 4, 1); 00231 points[3]->elts[0] = x4; 00232 points[3]->elts[1] = y4; 00233 points[3]->elts[2] = z4; 00234 00235 create_zero_vector_f(¢er, 4); 00236 create_adjacency(&adjacency); 00237 00238 for (size_t i = 0; i < 6; i++) 00239 { 00240 const Vector_f* centroid = faces[ i ]->get_centroid(); 00241 00242 // Ignore the homogeneous coordinate, since it must be 1. 00243 center->elts[0] += centroid->elts[0]; 00244 center->elts[1] += centroid->elts[1]; 00245 center->elts[2] += centroid->elts[2]; 00246 } 00247 00248 center->elts[0] /= 6.0f; 00249 center->elts[1] /= 6.0f; 00250 center->elts[2] /= 6.0f; 00251 center->elts[3] = 1.0f; 00252 } 00253 00254 00292 Parapiped_f::Parapiped_f 00293 ( 00294 const jwsc::Vector_f* p1, 00295 const jwsc::Vector_f* p2, 00296 const jwsc::Vector_f* p3, 00297 const jwsc::Vector_f* p4 00298 ) 00299 throw (jwscxx::base::Arg_error) 00300 : faces(6, (Polygon_f*)0), points(4, (jwsc::Vector_f*)0) 00301 { 00302 using namespace jwsc; 00303 00304 center = 0; 00305 adjacency = 0; 00306 00307 if (p1->num_elts != 3 || p2->num_elts != 3 || 00308 p3->num_elts != 3 || p4->num_elts != 3) 00309 { 00310 throw Arg_error("Vectors for parapiped not 3D"); 00311 } 00312 00313 float x1 = p1->elts[0]; float y1 = p1->elts[1]; float z1 = p1->elts[2]; 00314 float x2 = p2->elts[0]; float y2 = p2->elts[1]; float z2 = p2->elts[2]; 00315 float x3 = p3->elts[0]; float y3 = p3->elts[1]; float z3 = p3->elts[2]; 00316 float x4 = p4->elts[0]; float y4 = p4->elts[1]; float z4 = p4->elts[2]; 00317 00318 faces[5] = new Polygon_f(4); 00319 faces[5]->add_point(x1, y1, z1); 00320 faces[5]->add_point(x1 + (x3 - x2), y1 + (y3 - y2), z1 + (z3 - z2)); 00321 faces[5]->add_point(x3, y3, z3); 00322 faces[5]->add_point(x2, y2, z2); 00323 00324 faces[3] = new Polygon_f(4); 00325 faces[3]->add_point(x2, y2, z2); 00326 faces[3]->add_point(x2 + (x4 - x3), y2 + (y4 - y3), z2 + (z4 - z3)); 00327 faces[3]->add_point(x1 + (x4 - x3), y1 + (y4 - y3), z1 + (z4 - z3)); 00328 faces[3]->add_point(x1, y1, z1); 00329 00330 faces[0] = new Polygon_f(4); 00331 faces[0]->add_point(x3, y3, z3); 00332 faces[0]->add_point(x4, y4, z4); 00333 faces[0]->add_point(x2 + (x4 - x3), y2 + (y4 - y3), z2 + (z4 - z3)); 00334 faces[0]->add_point(x2, y2, z2); 00335 00336 faces[2] = new Polygon_f(4); 00337 faces[2]->add_point(x4, y4, z4); 00338 faces[2]->add_point(x3, y3, z3); 00339 faces[2]->add_point(x3 + (x1 - x2), y3 + (y1 - y2), z3 + (z1 - z2)); 00340 faces[2]->add_point(x4 + (x1 - x2), y4 + (y1 - y2), z4 + (z1 - z2)); 00341 00342 faces[4] = new Polygon_f(4); 00343 faces[4]->add_point(x4, y4, z4); 00344 faces[4]->add_point(x4 + (x1 - x2), y4 + (y1 - y2), z4 + (z1 - z2)); 00345 faces[4]->add_point(x1 + (x4 - x3), y1 + (y4 - y3), z1 + (z4 - z3)); 00346 faces[4]->add_point(x2 + (x4 - x3), y2 + (y4 - y3), z2 + (z4 - z3)); 00347 00348 faces[1] = new Polygon_f(4); 00349 faces[1]->add_point(x1, y1, z1); 00350 faces[1]->add_point(x1 + (x4 - x3), y1 + (y4 - y3), z1 + (z4 - z3)); 00351 faces[1]->add_point(x4 + (x1 - x2), y4 + (y1 - y2), z4 + (z1 - z2)); 00352 faces[1]->add_point(x3 + (x1 - x2), y3 + (y1 - y2), z3 + (z1 - z2)); 00353 00354 create_init_vector_f(&(points[0]), 4, 1); 00355 points[0]->elts[0] = x1; 00356 points[0]->elts[1] = y1; 00357 points[0]->elts[2] = z1; 00358 00359 create_init_vector_f(&(points[1]), 4, 1); 00360 points[1]->elts[0] = x2; 00361 points[1]->elts[1] = y2; 00362 points[1]->elts[2] = z2; 00363 00364 create_init_vector_f(&(points[2]), 4, 1); 00365 points[2]->elts[0] = x3; 00366 points[2]->elts[1] = y3; 00367 points[2]->elts[2] = z3; 00368 00369 create_init_vector_f(&(points[3]), 4, 1); 00370 points[3]->elts[0] = x4; 00371 points[3]->elts[1] = y4; 00372 points[3]->elts[2] = z4; 00373 00374 create_zero_vector_f(¢er, 4); 00375 create_adjacency(&adjacency); 00376 00377 for (size_t i = 0; i < 6; i++) 00378 { 00379 const Vector_f* centroid = faces[ i ]->get_centroid(); 00380 00381 // Ignore the homogeneous coordinate, since it must be 1. 00382 center->elts[0] += centroid->elts[0]; 00383 center->elts[1] += centroid->elts[1]; 00384 center->elts[2] += centroid->elts[2]; 00385 } 00386 00387 center->elts[0] /= 6.0f; 00388 center->elts[1] /= 6.0f; 00389 center->elts[2] /= 6.0f; 00390 center->elts[3] = 1.0f; 00391 } 00392 00393 00395 Parapiped_f::Parapiped_f(const Parapiped_f& p) 00396 : faces(6, (Polygon_f*)0), points(4, (jwsc::Vector_f*)0) 00397 { 00398 center = 0; 00399 00400 for (size_t i = 0; i < 6; i++) 00401 { 00402 faces[ i ] = p.faces[ i ]->clone(); 00403 } 00404 00405 for (size_t i = 0; i < 4; i++) 00406 { 00407 copy_vector_f(&(points[ i ]), p.points[ i ]); 00408 } 00409 00410 copy_vector_f(¢er, p.center); 00411 copy_matrix_u32(&adjacency, p.adjacency); 00412 } 00413 00414 00423 Parapiped_f::Parapiped_f(const char* fname) 00424 throw (jwscxx::base::Arg_error, jwscxx::base::IO_error) 00425 : faces(6, (Polygon_f*)0), points(4, (jwsc::Vector_f*)0) 00426 { 00427 center = 0; 00428 adjacency = 0; 00429 00430 jwscxx::base::Readable::read(fname); 00431 } 00432 00433 00442 Parapiped_f::Parapiped_f(std::istream& in) 00443 throw (jwscxx::base::Arg_error, jwscxx::base::IO_error) 00444 : faces(6, (Polygon_f*)0), points(4, (jwsc::Vector_f*)0) 00445 { 00446 center = 0; 00447 adjacency = 0; 00448 00449 read(in); 00450 } 00451 00452 00454 Parapiped_f::~Parapiped_f() 00455 { 00456 for (size_t i = 0; i < 6; i++) 00457 { 00458 delete faces[ i ]; 00459 } 00460 00461 for (size_t i = 0; i < 4; i++) 00462 { 00463 free_vector_f(points[ i ]); 00464 } 00465 00466 free_vector_f(center); 00467 free_matrix_u32(adjacency); 00468 } 00469 00470 00478 Parapiped_f& Parapiped_f::operator= (const Parapiped_f& p) 00479 { 00480 // Don't try to assign to self. 00481 if (points[0] == p.points[0]) 00482 return *this; 00483 00484 for (size_t i = 0; i < 6; i++) 00485 { 00486 *(faces[ i ]) = *(p.faces[ i ]); 00487 } 00488 00489 for (size_t i = 0; i < 4; i++) 00490 { 00491 copy_vector_f(&(points[ i ]), p.points[ i ]); 00492 } 00493 00494 copy_vector_f(¢er, p.center); 00495 copy_matrix_u32(&adjacency, p.adjacency); 00496 00497 return *this; 00498 } 00499 00500 00502 Parapiped_f* Parapiped_f::clone() const 00503 { 00504 return new Parapiped_f(*this); 00505 } 00506 00507 00508 size_t Parapiped_f::num_faces() const 00509 { 00510 return 6; 00511 } 00512 00513 00514 const jwsc::Vector_f* Parapiped_f::get_point(size_t i) const 00515 throw (jwscxx::base::Arg_error) 00516 { 00517 if (i >= 4) 00518 { 00519 throw jwscxx::base::Arg_error("Invalid point index"); 00520 } 00521 00522 return static_cast<const jwsc::Vector_f*>(points[ i ]); 00523 } 00524 00525 00530 const jwsc::Vector_f* Parapiped_f::get_center() const 00531 { 00532 return center; 00533 } 00534 00535 00543 const jwscxx::graphics::Polygon_f* Parapiped_f::get_face(size_t i) const 00544 throw (jwscxx::base::Arg_error) 00545 { 00546 if (i >= 6) 00547 { 00548 throw jwscxx::base::Arg_error("Invalid face index"); 00549 } 00550 00551 return static_cast<const jwscxx::graphics::Polygon_f*>(faces[ i ]); 00552 } 00553 00554 00556 const std::vector<const jwscxx::graphics::Polygon_f*>& Parapiped_f::get_faces() 00557 const 00558 { 00559 return (const std::vector<const jwscxx::graphics::Polygon_f*>&)(faces); 00560 } 00561 00562 00570 void Parapiped_f::set_face_id(size_t i, uint32_t id) 00571 throw (jwscxx::base::Arg_error) 00572 { 00573 if (i >= 6) 00574 { 00575 throw jwscxx::base::Arg_error("Invalid face index"); 00576 } 00577 00578 faces[ i ]->set_id(id); 00579 } 00580 00581 00588 void Parapiped_f::read(std::istream& in) throw (jwscxx::base::IO_error, 00589 jwscxx::base::Arg_error) 00590 { 00591 using namespace jwsc; 00592 00593 for (size_t i = 0; i < 6; i++) 00594 { 00595 if (faces[ i ] == 0) 00596 { 00597 faces[ i ] = new Polygon_f(4); 00598 } 00599 faces[ i ]->read(in); 00600 } 00601 00602 assert(sizeof(float) == sizeof(uint32_t)); 00603 00604 float x, y, z, w; 00605 00606 for (size_t i = 0; i < 4; i++) 00607 { 00608 in.read((char*)&x, sizeof(float)); 00609 in.read((char*)&y, sizeof(float)); 00610 in.read((char*)&z, sizeof(float)); 00611 in.read((char*)&w, sizeof(float)); 00612 if (in.fail() || in.eof()) 00613 { 00614 throw IO_error("Could not read point"); 00615 } 00616 00617 #ifndef JWSC_BIGENDIAN 00618 bswap_u32((uint32_t*)&(x)); 00619 bswap_u32((uint32_t*)&(y)); 00620 bswap_u32((uint32_t*)&(z)); 00621 bswap_u32((uint32_t*)&(w)); 00622 #endif 00623 00624 create_vector_f(&(points[ i ]), 4); 00625 points[ i ]->elts[0] = x; 00626 points[ i ]->elts[1] = y; 00627 points[ i ]->elts[2] = z; 00628 points[ i ]->elts[3] = w; 00629 } 00630 00631 in.read((char*)&x, sizeof(float)); 00632 in.read((char*)&y, sizeof(float)); 00633 in.read((char*)&z, sizeof(float)); 00634 in.read((char*)&w, sizeof(float)); 00635 if (in.fail() || in.eof()) 00636 { 00637 throw IO_error("Could not read center"); 00638 } 00639 00640 #ifndef JWSC_BIGENDIAN 00641 bswap_u32((uint32_t*)&(x)); 00642 bswap_u32((uint32_t*)&(y)); 00643 bswap_u32((uint32_t*)&(z)); 00644 bswap_u32((uint32_t*)&(w)); 00645 #endif 00646 00647 create_vector_f(¢er, 4); 00648 center->elts[0] = x; 00649 center->elts[1] = y; 00650 center->elts[2] = z; 00651 center->elts[3] = w; 00652 00653 create_adjacency(&adjacency); 00654 } 00655 00656 00664 void Parapiped_f::write(std::ostream& out) const throw (jwscxx::base::IO_error) 00665 { 00666 using namespace jwsc; 00667 00668 for (size_t i = 0; i < 6; i++) 00669 { 00670 faces[ i ]->write(out); 00671 } 00672 00673 assert(sizeof(float) == sizeof(uint32_t)); 00674 00675 for (size_t i = 0; i < 4; i++) 00676 { 00677 float x = points[ i ]->elts[0]; 00678 float y = points[ i ]->elts[1]; 00679 float z = points[ i ]->elts[2]; 00680 float w = points[ i ]->elts[3]; 00681 00682 #ifndef JWSC_BIGENDIAN 00683 bswap_u32((uint32_t*)&(x)); 00684 bswap_u32((uint32_t*)&(y)); 00685 bswap_u32((uint32_t*)&(z)); 00686 bswap_u32((uint32_t*)&(w)); 00687 #endif 00688 00689 out.write((char*)&x, sizeof(float)); 00690 out.write((char*)&y, sizeof(float)); 00691 out.write((char*)&z, sizeof(float)); 00692 out.write((char*)&w, sizeof(float)); 00693 if (out.fail() || out.eof()) 00694 { 00695 throw IO_error("Could not write point"); 00696 } 00697 } 00698 00699 float x = center->elts[0]; 00700 float y = center->elts[1]; 00701 float z = center->elts[2]; 00702 float w = center->elts[3]; 00703 00704 #ifndef JWSC_BIGENDIAN 00705 bswap_u32((uint32_t*)&(x)); 00706 bswap_u32((uint32_t*)&(y)); 00707 bswap_u32((uint32_t*)&(z)); 00708 bswap_u32((uint32_t*)&(w)); 00709 #endif 00710 00711 out.write((char*)&x, sizeof(float)); 00712 out.write((char*)&y, sizeof(float)); 00713 out.write((char*)&z, sizeof(float)); 00714 out.write((char*)&w, sizeof(float)); 00715 if (out.fail() || out.eof()) 00716 { 00717 throw IO_error("Could not write center"); 00718 } 00719 } 00720 00721 00729 void Parapiped_f::transform(const jwsc::Matrix_f* M) 00730 throw (jwscxx::base::Arg_error) 00731 { 00732 for (size_t i = 0; i < 6; i++) 00733 { 00734 faces[ i ]->transform(M); 00735 } 00736 00737 for (size_t i = 0; i < 4; i++) 00738 { 00739 multiply_matrix_and_vector_f(&(points[ i ]), M, points[ i ]); 00740 } 00741 00742 // Transform the center. 00743 multiply_matrix_and_vector_f(¢er, M, center); 00744 } 00745 00746 00748 void Parapiped_f::wire_render() const 00749 { 00750 for (size_t i = 0; i < 6; i++) 00751 { 00752 faces[ i ]->wire_render(); 00753 } 00754 } 00755 00756 00763 void Parapiped_f::wire_occlude_render() const 00764 { 00765 for (size_t i = 0; i < 6; i++) 00766 { 00767 faces[ i ]->wire_occlude_render(); 00768 } 00769 } 00770 00771 00773 void Parapiped_f::solid_render() const 00774 { 00775 for (size_t i = 0; i < 6; i++) 00776 { 00777 faces[ i ]->solid_render(); 00778 } 00779 } 00780 00781 00789 void Parapiped_f::project() 00790 { 00791 for (size_t i = 0; i < 6; i++) 00792 { 00793 faces[ i ]->project(); 00794 } 00795 } 00796 00797 00808 uint32_t Parapiped_f::adjacent_face(uint32_t i, uint32_t p) const 00809 throw (jwscxx::base::Arg_error) 00810 { 00811 if (i >= 6) 00812 { 00813 throw jwscxx::base::Arg_error("Invalid face index"); 00814 } 00815 if (p > 3) 00816 { 00817 throw jwscxx::base::Arg_error("Invalid face point index"); 00818 } 00819 00820 return adjacency->elts[ i ][ p ]; 00821 } 00822 00823 00870 Parapiped_d::Parapiped_d 00871 ( 00872 double x1, double y1, double z1, 00873 double x2, double y2, double z2, 00874 double x3, double y3, double z3, 00875 double x4, double y4, double z4 00876 ) 00877 : faces(6, (Polygon_d*)0), points(4, (jwsc::Vector_d*)0) 00878 { 00879 using namespace jwsc; 00880 00881 center = 0; 00882 adjacency = 0; 00883 00884 faces[5] = new Polygon_d(4); 00885 faces[5]->add_point(x1, y1, z1); 00886 faces[5]->add_point(x1 + (x3 - x2), y1 + (y3 - y2), z1 + (z3 - z2)); 00887 faces[5]->add_point(x3, y3, z3); 00888 faces[5]->add_point(x2, y2, z2); 00889 00890 faces[3] = new Polygon_d(4); 00891 faces[3]->add_point(x2, y2, z2); 00892 faces[3]->add_point(x2 + (x4 - x3), y2 + (y4 - y3), z2 + (z4 - z3)); 00893 faces[3]->add_point(x1 + (x4 - x3), y1 + (y4 - y3), z1 + (z4 - z3)); 00894 faces[3]->add_point(x1, y1, z1); 00895 00896 faces[0] = new Polygon_d(4); 00897 faces[0]->add_point(x3, y3, z3); 00898 faces[0]->add_point(x4, y4, z4); 00899 faces[0]->add_point(x2 + (x4 - x3), y2 + (y4 - y3), z2 + (z4 - z3)); 00900 faces[0]->add_point(x2, y2, z2); 00901 00902 faces[2] = new Polygon_d(4); 00903 faces[2]->add_point(x4, y4, z4); 00904 faces[2]->add_point(x3, y3, z3); 00905 faces[2]->add_point(x3 + (x1 - x2), y3 + (y1 - y2), z3 + (z1 - z2)); 00906 faces[2]->add_point(x4 + (x1 - x2), y4 + (y1 - y2), z4 + (z1 - z2)); 00907 00908 faces[4] = new Polygon_d(4); 00909 faces[4]->add_point(x4, y4, z4); 00910 faces[4]->add_point(x4 + (x1 - x2), y4 + (y1 - y2), z4 + (z1 - z2)); 00911 faces[4]->add_point(x1 + (x4 - x3), y1 + (y4 - y3), z1 + (z4 - z3)); 00912 faces[4]->add_point(x2 + (x4 - x3), y2 + (y4 - y3), z2 + (z4 - z3)); 00913 00914 faces[1] = new Polygon_d(4); 00915 faces[1]->add_point(x1, y1, z1); 00916 faces[1]->add_point(x1 + (x4 - x3), y1 + (y4 - y3), z1 + (z4 - z3)); 00917 faces[1]->add_point(x4 + (x1 - x2), y4 + (y1 - y2), z4 + (z1 - z2)); 00918 faces[1]->add_point(x3 + (x1 - x2), y3 + (y1 - y2), z3 + (z1 - z2)); 00919 00920 create_init_vector_d(&(points[0]), 4, 1); 00921 points[0]->elts[0] = x1; 00922 points[0]->elts[1] = y1; 00923 points[0]->elts[2] = z1; 00924 00925 create_init_vector_d(&(points[1]), 4, 1); 00926 points[1]->elts[0] = x2; 00927 points[1]->elts[1] = y2; 00928 points[1]->elts[2] = z2; 00929 00930 create_init_vector_d(&(points[2]), 4, 1); 00931 points[2]->elts[0] = x3; 00932 points[2]->elts[1] = y3; 00933 points[2]->elts[2] = z3; 00934 00935 create_init_vector_d(&(points[3]), 4, 1); 00936 points[3]->elts[0] = x4; 00937 points[3]->elts[1] = y4; 00938 points[3]->elts[2] = z4; 00939 00940 create_zero_vector_d(¢er, 4); 00941 create_adjacency(&adjacency); 00942 00943 for (size_t i = 0; i < 6; i++) 00944 { 00945 const Vector_d* centroid = faces[ i ]->get_centroid(); 00946 00947 // Ignore the homogeneous coordinate, since it must be 1. 00948 center->elts[0] += centroid->elts[0]; 00949 center->elts[1] += centroid->elts[1]; 00950 center->elts[2] += centroid->elts[2]; 00951 } 00952 00953 center->elts[0] /= 6.0; 00954 center->elts[1] /= 6.0; 00955 center->elts[2] /= 6.0; 00956 center->elts[3] = 1.0; 00957 } 00958 00959 00997 Parapiped_d::Parapiped_d 00998 ( 00999 const jwsc::Vector_d* p1, 01000 const jwsc::Vector_d* p2, 01001 const jwsc::Vector_d* p3, 01002 const jwsc::Vector_d* p4 01003 ) 01004 throw (jwscxx::base::Arg_error) 01005 : faces(6, (Polygon_d*)0), points(4, (jwsc::Vector_d*)0) 01006 { 01007 using namespace jwsc; 01008 01009 center = 0; 01010 adjacency = 0; 01011 01012 if (p1->num_elts != 3 || p2->num_elts != 3 || 01013 p3->num_elts != 3 || p4->num_elts != 3) 01014 { 01015 throw Arg_error("Vectors for parapiped not 3D"); 01016 } 01017 01018 double x1 = p1->elts[0]; double y1 = p1->elts[1]; double z1 = p1->elts[2]; 01019 double x2 = p2->elts[0]; double y2 = p2->elts[1]; double z2 = p2->elts[2]; 01020 double x3 = p3->elts[0]; double y3 = p3->elts[1]; double z3 = p3->elts[2]; 01021 double x4 = p4->elts[0]; double y4 = p4->elts[1]; double z4 = p4->elts[2]; 01022 01023 faces[5] = new Polygon_d(4); 01024 faces[5]->add_point(x1, y1, z1); 01025 faces[5]->add_point(x1 + (x3 - x2), y1 + (y3 - y2), z1 + (z3 - z2)); 01026 faces[5]->add_point(x3, y3, z3); 01027 faces[5]->add_point(x2, y2, z2); 01028 01029 faces[3] = new Polygon_d(4); 01030 faces[3]->add_point(x2, y2, z2); 01031 faces[3]->add_point(x2 + (x4 - x3), y2 + (y4 - y3), z2 + (z4 - z3)); 01032 faces[3]->add_point(x1 + (x4 - x3), y1 + (y4 - y3), z1 + (z4 - z3)); 01033 faces[3]->add_point(x1, y1, z1); 01034 01035 faces[0] = new Polygon_d(4); 01036 faces[0]->add_point(x3, y3, z3); 01037 faces[0]->add_point(x4, y4, z4); 01038 faces[0]->add_point(x2 + (x4 - x3), y2 + (y4 - y3), z2 + (z4 - z3)); 01039 faces[0]->add_point(x2, y2, z2); 01040 01041 faces[2] = new Polygon_d(4); 01042 faces[2]->add_point(x4, y4, z4); 01043 faces[2]->add_point(x3, y3, z3); 01044 faces[2]->add_point(x3 + (x1 - x2), y3 + (y1 - y2), z3 + (z1 - z2)); 01045 faces[2]->add_point(x4 + (x1 - x2), y4 + (y1 - y2), z4 + (z1 - z2)); 01046 01047 faces[4] = new Polygon_d(4); 01048 faces[4]->add_point(x4, y4, z4); 01049 faces[4]->add_point(x4 + (x1 - x2), y4 + (y1 - y2), z4 + (z1 - z2)); 01050 faces[4]->add_point(x1 + (x4 - x3), y1 + (y4 - y3), z1 + (z4 - z3)); 01051 faces[4]->add_point(x2 + (x4 - x3), y2 + (y4 - y3), z2 + (z4 - z3)); 01052 01053 faces[1] = new Polygon_d(4); 01054 faces[1]->add_point(x1, y1, z1); 01055 faces[1]->add_point(x1 + (x4 - x3), y1 + (y4 - y3), z1 + (z4 - z3)); 01056 faces[1]->add_point(x4 + (x1 - x2), y4 + (y1 - y2), z4 + (z1 - z2)); 01057 faces[1]->add_point(x3 + (x1 - x2), y3 + (y1 - y2), z3 + (z1 - z2)); 01058 01059 create_init_vector_d(&(points[0]), 4, 1); 01060 points[0]->elts[0] = x1; 01061 points[0]->elts[1] = y1; 01062 points[0]->elts[2] = z1; 01063 01064 create_init_vector_d(&(points[1]), 4, 1); 01065 points[1]->elts[0] = x2; 01066 points[1]->elts[1] = y2; 01067 points[1]->elts[2] = z2; 01068 01069 create_init_vector_d(&(points[2]), 4, 1); 01070 points[2]->elts[0] = x3; 01071 points[2]->elts[1] = y3; 01072 points[2]->elts[2] = z3; 01073 01074 create_init_vector_d(&(points[3]), 4, 1); 01075 points[3]->elts[0] = x4; 01076 points[3]->elts[1] = y4; 01077 points[3]->elts[2] = z4; 01078 01079 create_zero_vector_d(¢er, 4); 01080 create_adjacency(&adjacency); 01081 01082 for (size_t i = 0; i < 6; i++) 01083 { 01084 const Vector_d* centroid = faces[ i ]->get_centroid(); 01085 01086 // Ignore the homogeneous coordinate, since it must be 1. 01087 center->elts[0] += centroid->elts[0]; 01088 center->elts[1] += centroid->elts[1]; 01089 center->elts[2] += centroid->elts[2]; 01090 } 01091 01092 center->elts[0] /= 6.0; 01093 center->elts[1] /= 6.0; 01094 center->elts[2] /= 6.0; 01095 center->elts[3] = 1.0; 01096 } 01097 01098 01100 Parapiped_d::Parapiped_d(const Parapiped_d& p) 01101 : faces(6, (Polygon_d*)0), points(4, (jwsc::Vector_d*)0) 01102 { 01103 center = 0; 01104 adjacency = 0; 01105 01106 for (size_t i = 0; i < 6; i++) 01107 { 01108 faces[ i ] = p.faces[ i ]->clone(); 01109 } 01110 01111 for (size_t i = 0; i < 4; i++) 01112 { 01113 copy_vector_d(&(points[ i ]), p.points[ i ]); 01114 } 01115 01116 copy_vector_d(¢er, p.center); 01117 copy_matrix_u32(&adjacency, p.adjacency); 01118 } 01119 01120 01129 Parapiped_d::Parapiped_d(const char* fname) 01130 throw (jwscxx::base::Arg_error, jwscxx::base::IO_error) 01131 : faces(6, (Polygon_d*)0), points(4, (jwsc::Vector_d*)0) 01132 { 01133 center = 0; 01134 adjacency = 0; 01135 01136 jwscxx::base::Readable::read(fname); 01137 } 01138 01139 01148 Parapiped_d::Parapiped_d(std::istream& in) 01149 throw (jwscxx::base::Arg_error, jwscxx::base::IO_error) 01150 : faces(6, (Polygon_d*)0), points(4, (jwsc::Vector_d*)0) 01151 { 01152 center = 0; 01153 adjacency = 0; 01154 01155 read(in); 01156 } 01157 01158 01160 Parapiped_d::~Parapiped_d() 01161 { 01162 for (size_t i = 0; i < 6; i++) 01163 { 01164 delete faces[ i ]; 01165 } 01166 01167 for (size_t i = 0; i < 4; i++) 01168 { 01169 free_vector_d(points[ i ]); 01170 } 01171 01172 free_vector_d(center); 01173 free_matrix_u32(adjacency); 01174 } 01175 01176 01184 Parapiped_d& Parapiped_d::operator= (const Parapiped_d& p) 01185 { 01186 // Don't try to assign to self. 01187 if (points[0] == p.points[0]) 01188 return *this; 01189 01190 for (size_t i = 0; i < 6; i++) 01191 { 01192 *(faces[ i ]) = *(p.faces[ i ]); 01193 } 01194 01195 for (size_t i = 0; i < 4; i++) 01196 { 01197 copy_vector_d(&(points[ i ]), p.points[ i ]); 01198 } 01199 01200 copy_vector_d(¢er, p.center); 01201 copy_matrix_u32(&adjacency, p.adjacency); 01202 01203 return *this; 01204 } 01205 01206 01208 Parapiped_d* Parapiped_d::clone() const 01209 { 01210 return new Parapiped_d(*this); 01211 } 01212 01213 01214 size_t Parapiped_d::num_faces() const 01215 { 01216 return 6; 01217 } 01218 01219 01220 const jwsc::Vector_d* Parapiped_d::get_point(size_t i) const 01221 throw (jwscxx::base::Arg_error) 01222 { 01223 if (i >= 4) 01224 { 01225 throw jwscxx::base::Arg_error("Invalid point index"); 01226 } 01227 01228 return static_cast<const jwsc::Vector_d*>(points[ i ]); 01229 } 01230 01231 01236 const jwsc::Vector_d* Parapiped_d::get_center() const 01237 { 01238 return center; 01239 } 01240 01241 01249 const jwscxx::graphics::Polygon_d* Parapiped_d::get_face(size_t i) const 01250 throw (jwscxx::base::Arg_error) 01251 { 01252 if (i >= 6) 01253 { 01254 throw jwscxx::base::Arg_error("Invalid face index"); 01255 } 01256 01257 return static_cast<const jwscxx::graphics::Polygon_d*>(faces[ i ]); 01258 } 01259 01260 01262 const std::vector<const jwscxx::graphics::Polygon_d*>& Parapiped_d::get_faces() 01263 const 01264 { 01265 return (const std::vector<const jwscxx::graphics::Polygon_d*>&)(faces); 01266 } 01267 01268 01276 void Parapiped_d::set_face_id(size_t i, uint32_t id) 01277 throw (jwscxx::base::Arg_error) 01278 { 01279 if (i >= 6) 01280 { 01281 throw jwscxx::base::Arg_error("Invalid face index"); 01282 } 01283 01284 faces[ i ]->set_id(id); 01285 } 01286 01287 01294 void Parapiped_d::read(std::istream& in) throw (jwscxx::base::IO_error, 01295 jwscxx::base::Arg_error) 01296 { 01297 using namespace jwsc; 01298 01299 for (size_t i = 0; i < 6; i++) 01300 { 01301 if (faces[ i ] == 0) 01302 { 01303 faces[ i ] = new Polygon_d(4); 01304 } 01305 faces[ i ]->read(in); 01306 } 01307 01308 assert(sizeof(double) == sizeof(uint64_t)); 01309 01310 double x, y, z, w; 01311 01312 for (size_t i = 0; i < 4; i++) 01313 { 01314 in.read((char*)&x, sizeof(double)); 01315 in.read((char*)&y, sizeof(double)); 01316 in.read((char*)&z, sizeof(double)); 01317 in.read((char*)&w, sizeof(double)); 01318 if (in.fail() || in.eof()) 01319 { 01320 throw IO_error("Could not read point"); 01321 } 01322 01323 #ifndef JWSC_BIGENDIAN 01324 bswap_u64((uint64_t*)&(x)); 01325 bswap_u64((uint64_t*)&(y)); 01326 bswap_u64((uint64_t*)&(z)); 01327 bswap_u64((uint64_t*)&(w)); 01328 #endif 01329 01330 create_vector_d(&(points[ i ]), 4); 01331 points[ i ]->elts[0] = x; 01332 points[ i ]->elts[1] = y; 01333 points[ i ]->elts[2] = z; 01334 points[ i ]->elts[3] = w; 01335 } 01336 01337 in.read((char*)&x, sizeof(double)); 01338 in.read((char*)&y, sizeof(double)); 01339 in.read((char*)&z, sizeof(double)); 01340 in.read((char*)&w, sizeof(double)); 01341 if (in.fail() || in.eof()) 01342 { 01343 throw IO_error("Could not read center"); 01344 } 01345 01346 #ifndef JWSC_BIGENDIAN 01347 bswap_u64((uint64_t*)&(x)); 01348 bswap_u64((uint64_t*)&(y)); 01349 bswap_u64((uint64_t*)&(z)); 01350 bswap_u64((uint64_t*)&(w)); 01351 #endif 01352 01353 create_vector_d(¢er, 4); 01354 center->elts[0] = x; 01355 center->elts[1] = y; 01356 center->elts[2] = z; 01357 center->elts[3] = w; 01358 01359 create_adjacency(&adjacency); 01360 } 01361 01362 01370 void Parapiped_d::write(std::ostream& out) const throw (jwscxx::base::IO_error) 01371 { 01372 using namespace jwsc; 01373 01374 for (size_t i = 0; i < 6; i++) 01375 { 01376 faces[ i ]->write(out); 01377 } 01378 01379 assert(sizeof(double) == sizeof(uint64_t)); 01380 01381 for (size_t i = 0; i < 4; i++) 01382 { 01383 double x = points[ i ]->elts[0]; 01384 double y = points[ i ]->elts[1]; 01385 double z = points[ i ]->elts[2]; 01386 double w = points[ i ]->elts[3]; 01387 01388 #ifndef JWSC_BIGENDIAN 01389 bswap_u64((uint64_t*)&(x)); 01390 bswap_u64((uint64_t*)&(y)); 01391 bswap_u64((uint64_t*)&(z)); 01392 bswap_u64((uint64_t*)&(w)); 01393 #endif 01394 01395 out.write((char*)&x, sizeof(double)); 01396 out.write((char*)&y, sizeof(double)); 01397 out.write((char*)&z, sizeof(double)); 01398 out.write((char*)&w, sizeof(double)); 01399 if (out.fail() || out.eof()) 01400 { 01401 throw IO_error("Could not write point"); 01402 } 01403 } 01404 01405 double x = center->elts[0]; 01406 double y = center->elts[1]; 01407 double z = center->elts[2]; 01408 double w = center->elts[3]; 01409 01410 #ifndef JWSC_BIGENDIAN 01411 bswap_u64((uint64_t*)&(x)); 01412 bswap_u64((uint64_t*)&(y)); 01413 bswap_u64((uint64_t*)&(z)); 01414 bswap_u64((uint64_t*)&(w)); 01415 #endif 01416 01417 out.write((char*)&x, sizeof(double)); 01418 out.write((char*)&y, sizeof(double)); 01419 out.write((char*)&z, sizeof(double)); 01420 out.write((char*)&w, sizeof(double)); 01421 if (out.fail() || out.eof()) 01422 { 01423 throw IO_error("Could not write center"); 01424 } 01425 } 01426 01427 01435 void Parapiped_d::transform(const jwsc::Matrix_d* M) 01436 throw (jwscxx::base::Arg_error) 01437 { 01438 for (size_t i = 0; i < 6; i++) 01439 { 01440 faces[ i ]->transform(M); 01441 } 01442 01443 for (size_t i = 0; i < 4; i++) 01444 { 01445 multiply_matrix_and_vector_d(&(points[ i ]), M, points[ i ]); 01446 } 01447 01448 // Transform the center. 01449 multiply_matrix_and_vector_d(¢er, M, center); 01450 } 01451 01452 01454 void Parapiped_d::wire_render() const 01455 { 01456 for (size_t i = 0; i < 6; i++) 01457 { 01458 faces[ i ]->wire_render(); 01459 } 01460 } 01461 01462 01469 void Parapiped_d::wire_occlude_render() const 01470 { 01471 for (size_t i = 0; i < 6; i++) 01472 { 01473 faces[ i ]->wire_occlude_render(); 01474 } 01475 } 01476 01477 01479 void Parapiped_d::solid_render() const 01480 { 01481 for (size_t i = 0; i < 6; i++) 01482 { 01483 faces[ i ]->solid_render(); 01484 } 01485 } 01486 01487 01495 void Parapiped_d::project() 01496 { 01497 for (size_t i = 0; i < 6; i++) 01498 { 01499 faces[ i ]->project(); 01500 } 01501 } 01502 01503 01514 uint32_t Parapiped_d::adjacent_face(uint32_t i, uint32_t p) const 01515 throw (jwscxx::base::Arg_error) 01516 { 01517 if (i >= 6) 01518 { 01519 throw jwscxx::base::Arg_error("Invalid face index"); 01520 } 01521 if (p > 3) 01522 { 01523 throw jwscxx::base::Arg_error("Invalid face point index"); 01524 } 01525 01526 return adjacency->elts[ i ][ p ]; 01527 }