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 00047 #include <jwsc++/config.h> 00048 #include <jwsc/config.h> 00049 00050 #include <cassert> 00051 #include <cmath> 00052 #include <iostream> 00053 #include <vector> 00054 00055 #include <inttypes.h> 00056 00057 #if defined JWSCXX_HAVE_OPENGL 00058 #include <GL/gl.h> 00059 #elif defined JWSCXX_HAVE_OPENGL_FRAMEWORK 00060 #include <OpenGL/gl.h> 00061 #endif 00062 00063 #include <jwsc/base/bits.h> 00064 #include <jwsc/vector/vector.h> 00065 #include <jwsc/vector/vector_math.h> 00066 #include <jwsc/matrix/matrix.h> 00067 #include <jwsc/matrix/matrix_math.h> 00068 00069 #include "jwsc++/base/exception.h" 00070 #include "jwsc++/graphics/camera.h" 00071 #include "jwsc++/graphics/polygon.h" 00072 00073 #ifdef JWSCXX_HAVE_DMALLOC 00074 #include <dmalloc.h> 00075 #endif 00076 00077 00078 using namespace jwscxx::base; 00079 using namespace jwscxx::graphics; 00080 00081 00083 Polygon_f::Polygon_f() 00084 { 00085 normal = 0; 00086 centroid = 0; 00087 normal_flipped = 0; 00088 id = generate_id(); 00089 } 00090 00091 00098 Polygon_f::Polygon_f(uint32_t N) 00099 { 00100 pts.reserve(N); 00101 normal = 0; 00102 centroid = 0; 00103 normal_flipped = 0; 00104 id = generate_id(); 00105 } 00106 00107 00109 Polygon_f::Polygon_f(const Polygon_f& p) 00110 : pts(p.pts.capacity()) 00111 { 00112 normal = 0; 00113 centroid = 0; 00114 *this = p; 00115 } 00116 00117 00126 Polygon_f::Polygon_f(const char* fname) 00127 throw (jwscxx::base::Arg_error, jwscxx::base::IO_error) 00128 { 00129 normal = 0; 00130 centroid = 0; 00131 normal_flipped = 0; 00132 00133 jwscxx::base::Readable::read(fname); 00134 } 00135 00136 00145 Polygon_f::Polygon_f(std::istream& in) 00146 throw (jwscxx::base::Arg_error, jwscxx::base::IO_error) 00147 { 00148 normal = 0; 00149 centroid = 0; 00150 normal_flipped = 0; 00151 00152 read(in); 00153 } 00154 00155 00157 Polygon_f::~Polygon_f() 00158 { 00159 free_vector_f(normal); 00160 free_vector_f(centroid); 00161 00162 for (size_t i = 0; i < pts.size(); i++) 00163 { 00164 free_vector_f(pts[ i ]); 00165 } 00166 } 00167 00168 00176 Polygon_f& Polygon_f::operator= (const Polygon_f& p) 00177 { 00178 using namespace std; 00179 using namespace jwsc; 00180 00181 size_t n = pts.size(); 00182 size_t N = p.pts.size(); 00183 00184 if (n > N) 00185 { 00186 for (size_t i = N; i < n; i++) 00187 { 00188 free_vector_f(pts[ i ]); 00189 } 00190 pts.erase(pts.begin() + N, pts.end()); 00191 } 00192 else 00193 { 00194 pts.reserve(N); 00195 } 00196 00197 for (size_t i = 0; i < N; i++) 00198 { 00199 if (i < n) 00200 { 00201 copy_vector_f(&(pts[ i ]), p.pts[ i ]); 00202 } 00203 else 00204 { 00205 Vector_f* pt = 0; 00206 copy_vector_f(&pt, p.pts[ i ]); 00207 pts.push_back(pt); 00208 } 00209 } 00210 00211 if (p.normal) 00212 { 00213 copy_vector_f(&normal, p.normal); 00214 } 00215 if (p.centroid) 00216 { 00217 copy_vector_f(¢roid, p.centroid); 00218 } 00219 00220 normal_flipped = p.normal_flipped; 00221 00222 id = p.id; 00223 00224 return *this; 00225 } 00226 00227 00229 Polygon_f* Polygon_f::clone() const 00230 { 00231 return new Polygon_f(*this); 00232 } 00233 00234 00241 void Polygon_f::read(std::istream& in) throw (jwscxx::base::IO_error, 00242 jwscxx::base::Arg_error) 00243 { 00244 using namespace jwsc; 00245 00246 in.read((char*)&id, sizeof(uint32_t)); 00247 if (in.fail() || in.eof()) 00248 { 00249 throw IO_error("Could not read id"); 00250 } 00251 #ifndef JWSC_BIGENDIAN 00252 bswap_u32(&(id)); 00253 #endif 00254 00255 assert(sizeof(float) == sizeof(uint32_t)); 00256 00257 float x, y, z, w; 00258 00259 // Number of points. 00260 uint32_t N; 00261 00262 in.read((char*)&N, sizeof(uint32_t)); 00263 if (in.fail() || in.eof()) 00264 { 00265 throw IO_error("Could not read number of points"); 00266 } 00267 00268 #ifndef JWSC_BIGENDIAN 00269 bswap_u32(&(N)); 00270 #endif 00271 00272 // Reserve space in the pts vector. 00273 size_t n = pts.size(); 00274 00275 if (n > N) 00276 { 00277 for (size_t i = N; i < n; i++) 00278 { 00279 free_vector_f(pts[ i ]); 00280 } 00281 pts.erase(pts.begin() + N, pts.end()); 00282 } 00283 else 00284 { 00285 pts.reserve(N); 00286 } 00287 00288 00289 // Points. 00290 for (size_t i = 0; i < N; i++) 00291 { 00292 in.read((char*)&x, sizeof(float)); 00293 in.read((char*)&y, sizeof(float)); 00294 in.read((char*)&z, sizeof(float)); 00295 in.read((char*)&w, sizeof(float)); 00296 if (in.fail() || in.eof()) 00297 { 00298 throw IO_error("Could not read points"); 00299 } 00300 00301 #ifndef JWSC_BIGENDIAN 00302 bswap_u32((uint32_t*)&(x)); 00303 bswap_u32((uint32_t*)&(y)); 00304 bswap_u32((uint32_t*)&(z)); 00305 bswap_u32((uint32_t*)&(w)); 00306 #endif 00307 00308 if (i < n) 00309 { 00310 pts[ i ]->elts[0] = x; 00311 pts[ i ]->elts[1] = y; 00312 pts[ i ]->elts[2] = z; 00313 pts[ i ]->elts[3] = w; 00314 } 00315 else 00316 { 00317 Vector_f* pt = 0; 00318 create_vector_f(&pt, 4); 00319 00320 pt->elts[0] = x; 00321 pt->elts[1] = y; 00322 pt->elts[2] = z; 00323 pt->elts[3] = w; 00324 00325 pts.push_back(pt); 00326 } 00327 } 00328 00329 00330 // Normal. 00331 if (N >= 3) 00332 { 00333 in.read((char*)&x, sizeof(float)); 00334 in.read((char*)&y, sizeof(float)); 00335 in.read((char*)&z, sizeof(float)); 00336 in.read((char*)&w, sizeof(float)); 00337 if (in.fail() || in.eof()) 00338 { 00339 throw IO_error("Could not read normal"); 00340 } 00341 00342 #ifndef JWSC_BIGENDIAN 00343 bswap_u32((uint32_t*)&(x)); 00344 bswap_u32((uint32_t*)&(y)); 00345 bswap_u32((uint32_t*)&(z)); 00346 bswap_u32((uint32_t*)&(w)); 00347 #endif 00348 00349 create_vector_f(&normal, 4); 00350 normal->elts[0] = x; 00351 normal->elts[1] = y; 00352 normal->elts[2] = z; 00353 normal->elts[3] = w; 00354 } 00355 00356 00357 // Centroid. 00358 if (N > 0) 00359 { 00360 in.read((char*)&x, sizeof(float)); 00361 in.read((char*)&y, sizeof(float)); 00362 in.read((char*)&z, sizeof(float)); 00363 in.read((char*)&w, sizeof(float)); 00364 if (in.fail() || in.eof()) 00365 { 00366 throw IO_error("Could not read centroid"); 00367 } 00368 00369 #ifndef JWSC_BIGENDIAN 00370 bswap_u32((uint32_t*)&(x)); 00371 bswap_u32((uint32_t*)&(y)); 00372 bswap_u32((uint32_t*)&(z)); 00373 bswap_u32((uint32_t*)&(w)); 00374 #endif 00375 00376 create_vector_f(¢roid, 4); 00377 centroid->elts[0] = x; 00378 centroid->elts[1] = y; 00379 centroid->elts[2] = z; 00380 centroid->elts[3] = w; 00381 } 00382 00383 in.read((char*)&normal_flipped, sizeof(uint8_t)); 00384 } 00385 00386 00394 void Polygon_f::write(std::ostream& out) const throw (jwscxx::base::IO_error) 00395 { 00396 using namespace jwsc; 00397 00398 uint32_t id_cp = id; 00399 #ifndef JWSC_BIGENDIAN 00400 bswap_u32(&(id_cp)); 00401 #endif 00402 out.write((char*)&id_cp, sizeof(uint32_t)); 00403 if (out.fail() || out.eof()) 00404 { 00405 throw IO_error("Could not write id"); 00406 } 00407 00408 assert(sizeof(float) == sizeof(uint32_t)); 00409 00410 float x, y, z, w; 00411 00412 // Number of points. 00413 uint32_t N = pts.size(); 00414 00415 #ifndef JWSC_BIGENDIAN 00416 bswap_u32(&(N)); 00417 #endif 00418 00419 out.write((char*)&N, sizeof(uint32_t)); 00420 if (out.fail() || out.eof()) 00421 { 00422 throw IO_error("Could not write number of points"); 00423 } 00424 00425 00426 // Points. 00427 for (size_t i = 0; i < pts.size(); i++) 00428 { 00429 Vector_f* pt = pts[ i ]; 00430 00431 x = pt->elts[0]; 00432 y = pt->elts[1]; 00433 z = pt->elts[2]; 00434 w = pt->elts[3]; 00435 00436 #ifndef JWSC_BIGENDIAN 00437 bswap_u32((uint32_t*)&(x)); 00438 bswap_u32((uint32_t*)&(y)); 00439 bswap_u32((uint32_t*)&(z)); 00440 bswap_u32((uint32_t*)&(w)); 00441 #endif 00442 00443 out.write((char*)&x, sizeof(float)); 00444 out.write((char*)&y, sizeof(float)); 00445 out.write((char*)&z, sizeof(float)); 00446 out.write((char*)&w, sizeof(float)); 00447 if (out.fail() || out.eof()) 00448 { 00449 throw IO_error("Could not write points"); 00450 } 00451 } 00452 00453 00454 // Normal. 00455 if (N >= 3) 00456 { 00457 assert(normal); 00458 00459 x = normal->elts[0]; 00460 y = normal->elts[1]; 00461 z = normal->elts[2]; 00462 w = normal->elts[3]; 00463 00464 #ifndef JWSC_BIGENDIAN 00465 bswap_u32((uint32_t*)&(x)); 00466 bswap_u32((uint32_t*)&(y)); 00467 bswap_u32((uint32_t*)&(z)); 00468 bswap_u32((uint32_t*)&(w)); 00469 #endif 00470 00471 out.write((char*)&x, sizeof(float)); 00472 out.write((char*)&y, sizeof(float)); 00473 out.write((char*)&z, sizeof(float)); 00474 out.write((char*)&w, sizeof(float)); 00475 if (out.fail() || out.eof()) 00476 { 00477 throw IO_error("Could not write normal"); 00478 } 00479 } 00480 00481 00482 // Centroid. 00483 if (N > 0) 00484 { 00485 assert(centroid); 00486 00487 x = centroid->elts[0]; 00488 y = centroid->elts[1]; 00489 z = centroid->elts[2]; 00490 w = centroid->elts[3]; 00491 00492 #ifndef JWSC_BIGENDIAN 00493 bswap_u32((uint32_t*)&(x)); 00494 bswap_u32((uint32_t*)&(y)); 00495 bswap_u32((uint32_t*)&(z)); 00496 bswap_u32((uint32_t*)&(w)); 00497 #endif 00498 00499 out.write((char*)&x, sizeof(float)); 00500 out.write((char*)&y, sizeof(float)); 00501 out.write((char*)&z, sizeof(float)); 00502 out.write((char*)&w, sizeof(float)); 00503 if (out.fail() || out.eof()) 00504 { 00505 throw IO_error("Could not write centroid"); 00506 } 00507 } 00508 00509 out.write((char*)&normal_flipped, sizeof(uint8_t)); 00510 } 00511 00512 00519 void Polygon_f::transform(const jwsc::Matrix_f* M) 00520 throw (jwscxx::base::Arg_error) 00521 { 00522 using namespace jwsc; 00523 00524 if (M->num_rows != 4 && M->num_cols != 4) 00525 { 00526 throw Arg_error("Transformation matrix not homogeneous"); 00527 } 00528 00529 size_t N = pts.size(); 00530 00531 // Transform the points. 00532 for (size_t i = 0; i < N; i++) 00533 { 00534 Vector_f* pt = pts[ i ]; 00535 00536 multiply_matrix_and_vector_f(&pt, M, pt); 00537 } 00538 00539 // Transform the centroid. 00540 multiply_matrix_and_vector_f(¢roid, M, centroid); 00541 00542 update_normal(); 00543 } 00544 00545 00547 void Polygon_f::wire_render() const 00548 { 00549 using namespace jwsc; 00550 00551 if (normal) 00552 { 00553 assert(fabs(normal->elts[3] - 1.0f) < 1.0e-8f); 00554 glNormal3f(normal->elts[0], normal->elts[1], normal->elts[2]); 00555 } 00556 00557 Vector_f* pt; 00558 00559 glBegin(GL_LINE_STRIP); 00560 for (size_t i = 0; i < pts.size(); i++) 00561 { 00562 pt = pts[ i ]; 00563 00564 glVertex4f(pt->elts[0], pt->elts[1], pt->elts[2], pt->elts[3]); 00565 } 00566 if (pts.size() > 0) 00567 { 00568 pt = pts[0]; 00569 glVertex4f(pt->elts[0], pt->elts[1], pt->elts[2], pt->elts[3]); 00570 } 00571 glEnd(); 00572 } 00573 00574 00581 void Polygon_f::wire_occlude_render() const 00582 { 00583 using namespace jwsc; 00584 00585 glDisable(GL_DEPTH_TEST); 00586 glEnable(GL_STENCIL_TEST); 00587 glClear(GL_STENCIL_BUFFER_BIT); 00588 glStencilFunc(GL_ALWAYS, 1, 1); 00589 glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); 00590 00591 GLboolean color_mask[4]; 00592 glGetBooleanv(GL_COLOR_WRITEMASK, color_mask); 00593 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); 00594 00595 00596 Vector_f* pt; 00597 00598 glBegin(GL_LINE_STRIP); 00599 for (size_t i = 0; i < pts.size(); i++) 00600 { 00601 pt = pts[ i ]; 00602 00603 glVertex4f(pt->elts[0], pt->elts[1], pt->elts[2], pt->elts[3]); 00604 } 00605 if (pts.size() > 0) 00606 { 00607 pt = pts[0]; 00608 glVertex4f(pt->elts[0], pt->elts[1], pt->elts[2], pt->elts[3]); 00609 } 00610 glEnd(); 00611 00612 00613 glStencilFunc(GL_NOTEQUAL, 1, 1); 00614 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); 00615 00616 glEnable(GL_DEPTH_TEST); 00617 00618 glBegin(GL_POLYGON); 00619 for (size_t i = 0; i < pts.size(); i++) 00620 { 00621 pt = pts[ i ]; 00622 00623 glVertex4f(pt->elts[0], pt->elts[1], pt->elts[2], pt->elts[3]); 00624 } 00625 glEnd(); 00626 00627 glDisable(GL_STENCIL_TEST); 00628 00629 glColorMask(color_mask[0], color_mask[1], color_mask[2], color_mask[3]); 00630 } 00631 00640 void Polygon_f::wire_occluded_silhouette_render(std::vector<bool> & iVector, bool &iVisible) const 00641 { 00642 using namespace jwsc; 00643 00644 assert(iVector.size() == pts.size()); 00645 00646 Vector_f* pt; 00647 00648 glDisable(GL_DEPTH_TEST); 00649 glEnable(GL_STENCIL_TEST); 00650 glClear(GL_STENCIL_BUFFER_BIT); 00651 glStencilFunc(GL_ALWAYS, 1, 1); 00652 glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); 00653 00654 GLboolean color_mask[4]; 00655 glGetBooleanv(GL_COLOR_WRITEMASK, color_mask); 00656 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); 00657 00658 glBegin(GL_LINES); 00659 uint32_t i = 0; 00660 for(std::vector<bool>::const_iterator it = iVector.begin(); it != iVector.end(); it++,i++) 00661 { 00662 if(*it) 00663 { 00664 //If it is the last edge, we need to render the last and the first point of the polygon 00665 int j = ( (i+1) == pts.size()) ? 0 : (i+1); 00666 glVertex4d(pts[i]->elts[0], pts[i]->elts[1], pts[i]->elts[2], pts[i]->elts[3]); 00667 glVertex4d(pts[j]->elts[0], pts[j]->elts[1], pts[j]->elts[2], pts[j]->elts[3]); 00668 } 00669 } 00670 glEnd(); 00671 00672 00673 glStencilFunc(GL_NOTEQUAL, 1, 1); 00674 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); 00675 glEnable(GL_DEPTH_TEST); 00676 00677 glBegin(GL_POLYGON); 00678 if(iVisible) 00679 { 00680 for (size_t i = 0; i < pts.size(); i++) 00681 { 00682 pt = pts[ i ]; 00683 glVertex4d(pt->elts[0], pt->elts[1], pt->elts[2], pt->elts[3]); 00684 } 00685 } 00686 glEnd(); 00687 00688 glDisable(GL_STENCIL_TEST); 00689 00690 glColorMask(color_mask[0], color_mask[1], color_mask[2], color_mask[3]); 00691 } 00692 00694 void Polygon_f::solid_render() const 00695 { 00696 using namespace jwsc; 00697 00698 if (normal) 00699 { 00700 assert(fabs(normal->elts[3] - 1.0f) < 1.0e-8f); 00701 glNormal3f(normal->elts[0], normal->elts[1], normal->elts[2]); 00702 } 00703 00704 glBegin(GL_POLYGON); 00705 for (size_t i = 0; i < pts.size(); i++) 00706 { 00707 Vector_f* pt = pts[ i ]; 00708 00709 glVertex4f(pt->elts[0], pt->elts[1], pt->elts[2], pt->elts[3]); 00710 } 00711 glEnd(); 00712 } 00713 00714 00726 void Polygon_f::add_point(float x, float y, float z) 00727 throw (jwscxx::base::Arg_error) 00728 { 00729 using namespace jwsc; 00730 00731 Vector_f* pt = 0; 00732 00733 create_vector_f(&pt, 4); 00734 pt->elts[0] = x; 00735 pt->elts[1] = y; 00736 pt->elts[2] = z; 00737 pt->elts[3] = 1.0f; 00738 00739 add_point(pt); 00740 } 00741 00742 00753 void Polygon_f::add_point(jwsc::Vector_f* pt) throw (jwscxx::base::Arg_error) 00754 { 00755 using namespace jwsc; 00756 00757 if (pt->num_elts != 4) 00758 { 00759 throw Arg_error("Point to add not homogeneous"); 00760 } 00761 else if (fabs(pt->elts[3]) < 1.0e-10) 00762 { 00763 throw Arg_error("Homogeneous coordinate is zero"); 00764 } 00765 00766 size_t N = pts.size(); 00767 00768 pts.push_back(pt); 00769 00770 if (N >= 3) 00771 { 00772 assert(normal); 00773 00774 float dp1, dp2; 00775 00776 calc_vector_dot_prod_f(&dp1, normal, pts[0]); 00777 calc_vector_dot_prod_f(&dp2, normal, pt); 00778 00779 if (fabs(dp1 - dp2) > 1.0e-4) 00780 { 00781 throw Arg_error("Point to add not in the polygon's plane"); 00782 } 00783 } 00784 else if (N == 2) 00785 { 00786 update_normal(); 00787 } 00788 00789 update_centroid(); 00790 } 00791 00792 00797 const jwsc::Vector_f* Polygon_f::get_normal() const 00798 { 00799 return normal; 00800 } 00801 00802 00806 const jwsc::Vector_f* Polygon_f::get_centroid() const 00807 { 00808 return centroid; 00809 } 00810 00811 00812 size_t Polygon_f::get_num_points() const 00813 { 00814 return pts.size(); 00815 } 00816 00817 00825 const jwsc::Vector_f* Polygon_f::get_point(size_t i) const 00826 throw (jwscxx::base::Arg_error) 00827 { 00828 if (i >= pts.size()) 00829 { 00830 throw jwscxx::base::Arg_error("Invalid point index"); 00831 } 00832 00833 return static_cast<const jwsc::Vector_f*>(pts[ i ]); 00834 } 00835 00836 00843 void Polygon_f::flip_normal() 00844 { 00845 normal_flipped = !normal_flipped; 00846 update_normal(); 00847 } 00848 00849 00857 void Polygon_f::project() 00858 { 00859 using namespace jwsc; 00860 00861 GLfloat glM[16] = {0}; 00862 00863 glGetFloatv(GL_MODELVIEW_MATRIX, glM); 00864 00865 glMatrixMode(GL_PROJECTION); 00866 glPushMatrix(); 00867 glMultMatrixf(glM); 00868 glGetFloatv(GL_PROJECTION_MATRIX, glM); 00869 glPopMatrix(); 00870 glMatrixMode(GL_MODELVIEW); 00871 00872 Matrix_f* M = 0; 00873 create_matrix_f(&M, 4, 4); 00874 for (size_t row = 0; row < 4; row++) 00875 { 00876 for (size_t col = 0; col < 4; col++) 00877 { 00878 M->elts[ row ][ col ] = glM[ col*4 + row ]; 00879 } 00880 } 00881 00882 float width = Camera_f::get_gl_viewport_width(); 00883 float height = Camera_f::get_gl_viewport_height(); 00884 00885 for (size_t i = 0; i < pts.size(); i++) 00886 { 00887 Vector_f* pt = pts[ i ]; 00888 00889 multiply_matrix_and_vector_f(&pt, M, pt); 00890 00891 float w = 1.0f / pt->elts[ 3 ]; 00892 pt->elts[ 0 ] = 0.5f*width* (pt->elts[ 0 ]*w + 1.0f); 00893 pt->elts[ 1 ] = 0.5f*height*(pt->elts[ 1 ]*w + 1.0f); 00894 pt->elts[ 2 ] = 0; 00895 pt->elts[ 3 ] = 1.0f; 00896 } 00897 00898 free_matrix_f(M); 00899 } 00900 00901 00907 uint8_t Polygon_f::is_visible(const Camera_f* camera) const 00908 { 00909 if (!normal) 00910 return 0; 00911 00912 const jwsc::Vector_f* prp = camera->get_prp(); 00913 00914 float x = prp->elts[0] - centroid->elts[0]; 00915 float y = prp->elts[1] - centroid->elts[1]; 00916 float z = prp->elts[2] - centroid->elts[2]; 00917 00918 if ((x*normal->elts[0] + y*normal->elts[1] + z*normal->elts[2]) > 0) 00919 return 1; 00920 return 0; 00921 } 00922 00930 uint8_t Polygon_f::is_visible_up_to_epsilon(const Camera_d* camera, float & epsilon) const 00931 { 00932 if (!normal) 00933 return 0; 00934 00935 const jwsc::Vector_d* prp = camera->get_prp(); 00936 00937 float x = prp->elts[0] - centroid->elts[0]; 00938 float y = prp->elts[1] - centroid->elts[1]; 00939 float z = prp->elts[2] - centroid->elts[2]; 00940 00941 float dp = ((float)(x*normal->elts[0] + y*normal->elts[1] + z*normal->elts[2])); 00942 00943 return ( dp > epsilon); 00944 } 00945 00946 00947 uint32_t Polygon_f::get_id() const 00948 { 00949 return id; 00950 } 00951 00952 00953 void Polygon_f::set_id(uint32_t id) 00954 { 00955 this->id = id; 00956 } 00957 00958 00964 void Polygon_f::update_normal() 00965 { 00966 using namespace jwsc; 00967 00968 size_t N = pts.size(); 00969 00970 if (N < 3) 00971 return; 00972 00973 Vector_f* p1 = pts[0]; 00974 Vector_f* p2 = pts[1]; 00975 Vector_f* pN = pts[N-1]; 00976 00977 float w1 = pts[0]->elts[3]; 00978 float w2 = pts[1]->elts[3]; 00979 float wN = pts[N-1]->elts[3]; 00980 00981 assert(fabs(w1) >= 1.0e-10); 00982 assert(fabs(w2) >= 1.0e-10); 00983 assert(fabs(wN) >= 1.0e-10); 00984 00985 w1 = 1.0f / w1; 00986 w2 = 1.0f / w2; 00987 wN = 1.0f / wN; 00988 00989 // p2 - p1 00990 float v1_x = p2->elts[0]*w2 - p1->elts[0]*w1; 00991 float v1_y = p2->elts[1]*w2 - p1->elts[1]*w1; 00992 float v1_z = p2->elts[2]*w2 - p1->elts[2]*w1; 00993 00994 // pN - p1 00995 float v2_x = pN->elts[0]*wN - p1->elts[0]*w1; 00996 float v2_y = pN->elts[1]*wN - p1->elts[1]*w1; 00997 float v2_z = pN->elts[2]*wN - p1->elts[2]*w1; 00998 00999 // v1 x v2 01000 create_vector_f(&normal, 4); 01001 normal->elts[0] = v1_y*v2_z - v1_z*v2_y; 01002 normal->elts[1] = v1_z*v2_x - v1_x*v2_z; 01003 normal->elts[2] = v1_x*v2_y - v1_y*v2_x; 01004 normal->elts[3] = 0.0f; 01005 01006 if (normal_flipped) 01007 { 01008 normal->elts[0] *= -1; 01009 normal->elts[1] *= -1; 01010 normal->elts[2] *= -1; 01011 } 01012 01013 normalize_vector_mag_f(&normal, normal); 01014 normal->elts[3] = 1.0f; 01015 } 01016 01017 01026 void Polygon_f::update_centroid() 01027 { 01028 using namespace jwsc; 01029 01030 size_t N = pts.size(); 01031 float area = 0; 01032 01033 if (N == 0) 01034 { 01035 return; 01036 } 01037 else if (N == 1) 01038 { 01039 copy_vector_f(¢roid, pts[0]); 01040 return; 01041 } 01042 else if (N == 2) 01043 { 01044 float x = (pts[0]->elts[0]/pts[0]->elts[3] + 01045 pts[1]->elts[0]/pts[1]->elts[3]) * 0.5f; 01046 float y = (pts[0]->elts[1]/pts[0]->elts[3] + 01047 pts[1]->elts[1]/pts[1]->elts[3]) * 0.5f; 01048 float z = (pts[0]->elts[2]/pts[0]->elts[3] + 01049 pts[1]->elts[2]/pts[1]->elts[3]) * 0.5f; 01050 create_zero_vector_f(¢roid, 4); 01051 centroid->elts[0] = x; 01052 centroid->elts[1] = y; 01053 centroid->elts[2] = z; 01054 centroid->elts[3] = 1.0f; 01055 return; 01056 } 01057 01058 float x3 = pts[N-1]->elts[0]; 01059 float y3 = pts[N-1]->elts[1]; 01060 float z3 = pts[N-1]->elts[2]; 01061 01062 for (size_t i = 0; i < N - 2; i++) 01063 { 01064 float x1 = pts[i]->elts[0]; 01065 float y1 = pts[i]->elts[1]; 01066 float z1 = pts[i]->elts[2]; 01067 01068 float x2 = pts[i+1]->elts[0]; 01069 float y2 = pts[i+1]->elts[1]; 01070 float z2 = pts[i+1]->elts[2]; 01071 01072 float dot = (x2 - x1)*(x3 - x1) + 01073 (y2 - y1)*(y3 - y1) + 01074 (z2 - z1)*(z3 - z1); 01075 01076 float base = sqrt((x2 - x1)*(x2 - x1) + 01077 (y2 - y1)*(y2 - y1) + 01078 (z2 - z1)*(z2 - z1)); 01079 01080 float height; 01081 01082 if (base < 1.0e-8f) 01083 { 01084 height = 0; 01085 } 01086 else 01087 { 01088 float alpha = dot / (base*base); 01089 01090 float a = x3 - x1 - alpha*(x2 - x1); 01091 float b = y3 - y1 - alpha*(y2 - y1); 01092 float c = z3 - z1 - alpha*(z2 - z1); 01093 01094 height = sqrt(a*a + b*b + c*c); 01095 } 01096 01097 float tri_area = 0.5f * base * height; 01098 01099 area += tri_area; 01100 centroid->elts[0] += tri_area * (x1 + x2 + x3) / 3.0f; 01101 centroid->elts[1] += tri_area * (y1 + y2 + y3) / 3.0f; 01102 centroid->elts[2] += tri_area * (z1 + z2 + z3) / 3.0f; 01103 } 01104 01105 if (area > 1.0e-8f) 01106 { 01107 centroid->elts[0] /= area; 01108 centroid->elts[1] /= area; 01109 centroid->elts[2] /= area; 01110 centroid->elts[3] = 1.0f; 01111 } 01112 else 01113 { 01114 copy_vector_f(¢roid, pts[0]); 01115 } 01116 } 01117 01118 01119 uint32_t Polygon_f::generate_id() 01120 { 01121 static uint32_t next_id = 1; 01122 return next_id++; 01123 } 01124 01125 01127 Polygon_d::Polygon_d() 01128 { 01129 normal = 0; 01130 centroid = 0; 01131 normal_flipped = 0; 01132 id = generate_id(); 01133 } 01134 01135 01142 Polygon_d::Polygon_d(uint32_t N) 01143 { 01144 pts.reserve(N); 01145 normal = 0; 01146 centroid = 0; 01147 normal_flipped = 0; 01148 id = generate_id(); 01149 } 01150 01151 01153 Polygon_d::Polygon_d(const Polygon_d& p) 01154 : pts(p.pts.capacity()) 01155 { 01156 normal = 0; 01157 centroid = 0; 01158 *this = p; 01159 } 01160 01161 01170 Polygon_d::Polygon_d(const char* fname) 01171 throw (jwscxx::base::Arg_error, jwscxx::base::IO_error) 01172 { 01173 normal = 0; 01174 centroid = 0; 01175 normal_flipped = 0; 01176 01177 jwscxx::base::Readable::read(fname); 01178 } 01179 01180 01189 Polygon_d::Polygon_d(std::istream& in) 01190 throw (jwscxx::base::Arg_error, jwscxx::base::IO_error) 01191 { 01192 normal = 0; 01193 centroid = 0; 01194 normal_flipped = 0; 01195 01196 read(in); 01197 } 01198 01199 01201 Polygon_d::~Polygon_d() 01202 { 01203 free_vector_d(normal); 01204 free_vector_d(centroid); 01205 01206 for (size_t i = 0; i < pts.size(); i++) 01207 { 01208 free_vector_d(pts[ i ]); 01209 } 01210 } 01211 01212 01220 Polygon_d& Polygon_d::operator= (const Polygon_d& p) 01221 { 01222 using namespace std; 01223 using namespace jwsc; 01224 01225 size_t n = pts.size(); 01226 size_t N = p.pts.size(); 01227 01228 if (n > N) 01229 { 01230 for (size_t i = N; i < n; i++) 01231 { 01232 free_vector_d(pts[ i ]); 01233 } 01234 pts.erase(pts.begin() + N, pts.end()); 01235 } 01236 else 01237 { 01238 pts.reserve(N); 01239 } 01240 01241 for (size_t i = 0; i < N; i++) 01242 { 01243 if (i < n) 01244 { 01245 copy_vector_d(&(pts[ i ]), p.pts[ i ]); 01246 } 01247 else 01248 { 01249 Vector_d* pt = 0; 01250 copy_vector_d(&pt, p.pts[ i ]); 01251 pts.push_back(pt); 01252 } 01253 } 01254 01255 if (p.normal) 01256 { 01257 copy_vector_d(&normal, p.normal); 01258 } 01259 if (p.centroid) 01260 { 01261 copy_vector_d(¢roid, p.centroid); 01262 } 01263 01264 normal_flipped = p.normal_flipped; 01265 01266 id = p.id; 01267 01268 return *this; 01269 } 01270 01271 01273 Polygon_d* Polygon_d::clone() const 01274 { 01275 return new Polygon_d(*this); 01276 } 01277 01278 01285 void Polygon_d::read(std::istream& in) throw (jwscxx::base::IO_error, 01286 jwscxx::base::Arg_error) 01287 { 01288 using namespace jwsc; 01289 01290 in.read((char*)&id, sizeof(uint32_t)); 01291 if (in.fail() || in.eof()) 01292 { 01293 throw IO_error("Could not read id"); 01294 } 01295 #ifndef JWSC_BIGENDIAN 01296 bswap_u32(&(id)); 01297 #endif 01298 01299 assert(sizeof(double) == sizeof(uint64_t)); 01300 01301 double x, y, z, w; 01302 01303 // Number of points. 01304 uint32_t N; 01305 01306 in.read((char*)&N, sizeof(uint32_t)); 01307 if (in.fail() || in.eof()) 01308 { 01309 throw IO_error("Could not read number of points"); 01310 } 01311 01312 #ifndef JWSC_BIGENDIAN 01313 bswap_u32(&(N)); 01314 #endif 01315 01316 // Reserve space in the pts vector. 01317 size_t n = pts.size(); 01318 01319 if (n > N) 01320 { 01321 for (size_t i = N; i < n; i++) 01322 { 01323 free_vector_d(pts[ i ]); 01324 } 01325 pts.erase(pts.begin() + N, pts.end()); 01326 } 01327 else 01328 { 01329 pts.reserve(N); 01330 } 01331 01332 01333 // Points. 01334 for (size_t i = 0; i < N; i++) 01335 { 01336 in.read((char*)&x, sizeof(double)); 01337 in.read((char*)&y, sizeof(double)); 01338 in.read((char*)&z, sizeof(double)); 01339 in.read((char*)&w, sizeof(double)); 01340 if (in.fail() || in.eof()) 01341 { 01342 throw IO_error("Could not read points"); 01343 } 01344 01345 #ifndef JWSC_BIGENDIAN 01346 bswap_u64((uint64_t*)&(x)); 01347 bswap_u64((uint64_t*)&(y)); 01348 bswap_u64((uint64_t*)&(z)); 01349 bswap_u64((uint64_t*)&(w)); 01350 #endif 01351 01352 if (i < n) 01353 { 01354 pts[ i ]->elts[0] = x; 01355 pts[ i ]->elts[1] = y; 01356 pts[ i ]->elts[2] = z; 01357 pts[ i ]->elts[3] = w; 01358 } 01359 else 01360 { 01361 Vector_d* pt = 0; 01362 create_vector_d(&pt, 4); 01363 01364 pt->elts[0] = x; 01365 pt->elts[1] = y; 01366 pt->elts[2] = z; 01367 pt->elts[3] = w; 01368 01369 pts.push_back(pt); 01370 } 01371 } 01372 01373 01374 // Normal. 01375 if (N >= 3) 01376 { 01377 in.read((char*)&x, sizeof(double)); 01378 in.read((char*)&y, sizeof(double)); 01379 in.read((char*)&z, sizeof(double)); 01380 in.read((char*)&w, sizeof(double)); 01381 if (in.fail() || in.eof()) 01382 { 01383 throw IO_error("Could not read normal"); 01384 } 01385 01386 #ifndef JWSC_BIGENDIAN 01387 bswap_u64((uint64_t*)&(x)); 01388 bswap_u64((uint64_t*)&(y)); 01389 bswap_u64((uint64_t*)&(z)); 01390 bswap_u64((uint64_t*)&(w)); 01391 #endif 01392 01393 create_vector_d(&normal, 4); 01394 normal->elts[0] = x; 01395 normal->elts[1] = y; 01396 normal->elts[2] = z; 01397 normal->elts[3] = w; 01398 } 01399 01400 01401 // Centroid. 01402 if (N > 0) 01403 { 01404 in.read((char*)&x, sizeof(double)); 01405 in.read((char*)&y, sizeof(double)); 01406 in.read((char*)&z, sizeof(double)); 01407 in.read((char*)&w, sizeof(double)); 01408 if (in.fail() || in.eof()) 01409 { 01410 throw IO_error("Could not read centroid"); 01411 } 01412 01413 #ifndef JWSC_BIGENDIAN 01414 bswap_u64((uint64_t*)&(x)); 01415 bswap_u64((uint64_t*)&(y)); 01416 bswap_u64((uint64_t*)&(z)); 01417 bswap_u64((uint64_t*)&(w)); 01418 #endif 01419 01420 create_vector_d(¢roid, 4); 01421 centroid->elts[0] = x; 01422 centroid->elts[1] = y; 01423 centroid->elts[2] = z; 01424 centroid->elts[3] = w; 01425 } 01426 01427 in.read((char*)&normal_flipped, sizeof(uint8_t)); 01428 } 01429 01430 01438 void Polygon_d::write(std::ostream& out) const throw (jwscxx::base::IO_error) 01439 { 01440 using namespace jwsc; 01441 01442 uint32_t id_cp = id; 01443 #ifndef JWSC_BIGENDIAN 01444 bswap_u32(&(id_cp)); 01445 #endif 01446 out.write((char*)&id_cp, sizeof(uint32_t)); 01447 if (out.fail() || out.eof()) 01448 { 01449 throw IO_error("Could not write id"); 01450 } 01451 01452 assert(sizeof(double) == sizeof(uint64_t)); 01453 01454 double x, y, z, w; 01455 01456 // Number of points. 01457 uint32_t N = pts.size(); 01458 01459 #ifndef JWSC_BIGENDIAN 01460 bswap_u32(&(N)); 01461 #endif 01462 01463 out.write((char*)&N, sizeof(uint32_t)); 01464 if (out.fail() || out.eof()) 01465 { 01466 throw IO_error("Could not write number of points"); 01467 } 01468 01469 01470 // Points. 01471 for (size_t i = 0; i < pts.size(); i++) 01472 { 01473 Vector_d* pt = pts[ i ]; 01474 01475 x = pt->elts[0]; 01476 y = pt->elts[1]; 01477 z = pt->elts[2]; 01478 w = pt->elts[3]; 01479 01480 #ifndef JWSC_BIGENDIAN 01481 bswap_u64((uint64_t*)&(x)); 01482 bswap_u64((uint64_t*)&(y)); 01483 bswap_u64((uint64_t*)&(z)); 01484 bswap_u64((uint64_t*)&(w)); 01485 #endif 01486 01487 out.write((char*)&x, sizeof(double)); 01488 out.write((char*)&y, sizeof(double)); 01489 out.write((char*)&z, sizeof(double)); 01490 out.write((char*)&w, sizeof(double)); 01491 if (out.fail() || out.eof()) 01492 { 01493 throw IO_error("Could not write points"); 01494 } 01495 } 01496 01497 01498 // Normal. 01499 if (N >= 3) 01500 { 01501 assert(normal); 01502 01503 x = normal->elts[0]; 01504 y = normal->elts[1]; 01505 z = normal->elts[2]; 01506 w = normal->elts[3]; 01507 01508 #ifndef JWSC_BIGENDIAN 01509 bswap_u64((uint64_t*)&(x)); 01510 bswap_u64((uint64_t*)&(y)); 01511 bswap_u64((uint64_t*)&(z)); 01512 bswap_u64((uint64_t*)&(w)); 01513 #endif 01514 01515 out.write((char*)&x, sizeof(double)); 01516 out.write((char*)&y, sizeof(double)); 01517 out.write((char*)&z, sizeof(double)); 01518 out.write((char*)&w, sizeof(double)); 01519 if (out.fail() || out.eof()) 01520 { 01521 throw IO_error("Could not write normal"); 01522 } 01523 } 01524 01525 01526 // Centroid. 01527 if (N > 0) 01528 { 01529 assert(centroid); 01530 01531 x = centroid->elts[0]; 01532 y = centroid->elts[1]; 01533 z = centroid->elts[2]; 01534 w = centroid->elts[3]; 01535 01536 #ifndef JWSC_BIGENDIAN 01537 bswap_u64((uint64_t*)&(x)); 01538 bswap_u64((uint64_t*)&(y)); 01539 bswap_u64((uint64_t*)&(z)); 01540 bswap_u64((uint64_t*)&(w)); 01541 #endif 01542 01543 out.write((char*)&x, sizeof(double)); 01544 out.write((char*)&y, sizeof(double)); 01545 out.write((char*)&z, sizeof(double)); 01546 out.write((char*)&w, sizeof(double)); 01547 if (out.fail() || out.eof()) 01548 { 01549 throw IO_error("Could not write centroid"); 01550 } 01551 } 01552 01553 out.write((char*)&normal_flipped, sizeof(uint8_t)); 01554 } 01555 01556 01563 void Polygon_d::transform(const jwsc::Matrix_d* M) 01564 throw (jwscxx::base::Arg_error) 01565 { 01566 using namespace jwsc; 01567 01568 if (M->num_rows != 4 && M->num_cols != 4) 01569 { 01570 throw Arg_error("Transformation matrix not homogeneous"); 01571 } 01572 01573 size_t N = pts.size(); 01574 01575 // Transform the points. 01576 for (size_t i = 0; i < N; i++) 01577 { 01578 Vector_d* pt = pts[ i ]; 01579 01580 multiply_matrix_and_vector_d(&pt, M, pt); 01581 } 01582 01583 // Transform the centroid. 01584 multiply_matrix_and_vector_d(¢roid, M, centroid); 01585 01586 update_normal(); 01587 } 01588 01589 01591 void Polygon_d::wire_render() const 01592 { 01593 using namespace jwsc; 01594 01595 if (normal) 01596 { 01597 assert(fabs(normal->elts[3] - 1.0) < 1.0e-8); 01598 glNormal3d(normal->elts[0], normal->elts[1], normal->elts[2]); 01599 } 01600 01601 Vector_d* pt; 01602 01603 glBegin(GL_LINE_STRIP); 01604 for (size_t i = 0; i < pts.size(); i++) 01605 { 01606 pt = pts[ i ]; 01607 01608 glVertex4d(pt->elts[0], pt->elts[1], pt->elts[2], pt->elts[3]); 01609 } 01610 if (pts.size() > 0) 01611 { 01612 pt = pts[0]; 01613 glVertex4d(pt->elts[0], pt->elts[1], pt->elts[2], pt->elts[3]); 01614 } 01615 glEnd(); 01616 } 01617 01618 01625 void Polygon_d::wire_occlude_render() const 01626 { 01627 using namespace jwsc; 01628 01629 glDisable(GL_DEPTH_TEST); 01630 glEnable(GL_STENCIL_TEST); 01631 glClear(GL_STENCIL_BUFFER_BIT); 01632 glStencilFunc(GL_ALWAYS, 1, 1); 01633 glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); 01634 01635 GLboolean color_mask[4]; 01636 glGetBooleanv(GL_COLOR_WRITEMASK, color_mask); 01637 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); 01638 01639 Vector_d* pt; 01640 01641 glBegin(GL_LINE_STRIP); 01642 for (size_t i = 0; i < pts.size(); i++) 01643 { 01644 pt = pts[ i ]; 01645 01646 glVertex4d(pt->elts[0], pt->elts[1], pt->elts[2], pt->elts[3]); 01647 } 01648 if (pts.size() > 0) 01649 { 01650 pt = pts[0]; 01651 glVertex4d(pt->elts[0], pt->elts[1], pt->elts[2], pt->elts[3]); 01652 } 01653 glEnd(); 01654 01655 01656 glStencilFunc(GL_NOTEQUAL, 1, 1); 01657 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); 01658 01659 glEnable(GL_DEPTH_TEST); 01660 01661 glBegin(GL_POLYGON); 01662 for (size_t i = 0; i < pts.size(); i++) 01663 { 01664 pt = pts[ i ]; 01665 01666 glVertex4d(pt->elts[0], pt->elts[1], pt->elts[2], pt->elts[3]); 01667 } 01668 glEnd(); 01669 01670 glDisable(GL_STENCIL_TEST); 01671 01672 glColorMask(color_mask[0], color_mask[1], color_mask[2], color_mask[3]); 01673 } 01674 01683 void Polygon_d::wire_occluded_silhouette_render(std::vector<bool> & iVector, bool &visible) const 01684 { 01685 using namespace jwsc; 01686 01687 assert(iVector.size() == pts.size()); 01688 01689 Vector_d* pt; 01690 01691 glDisable(GL_DEPTH_TEST); 01692 glEnable(GL_STENCIL_TEST); 01693 glClear(GL_STENCIL_BUFFER_BIT); 01694 glStencilFunc(GL_ALWAYS, 1, 1); 01695 glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); 01696 01697 GLboolean color_mask[4]; 01698 glGetBooleanv(GL_COLOR_WRITEMASK, color_mask); 01699 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); 01700 01701 glBegin(GL_LINES); 01702 uint32_t i = 0; 01703 for(std::vector<bool>::const_iterator it = iVector.begin(); it != iVector.end(); it++,i++) 01704 { 01705 if(*it) 01706 { 01707 //If it is the last edge, we need to render the last and the first point of the polygon 01708 int j = ( (i+1) == pts.size()) ? 0 : (i+1); 01709 glVertex4d(pts[i]->elts[0], pts[i]->elts[1], pts[i]->elts[2], pts[i]->elts[3]); 01710 glVertex4d(pts[j]->elts[0], pts[j]->elts[1], pts[j]->elts[2], pts[j]->elts[3]); 01711 } 01712 } 01713 glEnd(); 01714 01715 01716 glStencilFunc(GL_NOTEQUAL, 1, 1); 01717 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); 01718 glEnable(GL_DEPTH_TEST); 01719 01720 glBegin(GL_POLYGON); 01721 if(visible) 01722 { 01723 for (size_t i = 0; i < pts.size(); i++) 01724 { 01725 pt = pts[ i ]; 01726 glVertex4d(pt->elts[0], pt->elts[1], pt->elts[2], pt->elts[3]); 01727 } 01728 } 01729 glEnd(); 01730 01731 glDisable(GL_STENCIL_TEST); 01732 01733 glColorMask(color_mask[0], color_mask[1], color_mask[2], color_mask[3]); 01734 } 01735 01736 01738 void Polygon_d::solid_render() const 01739 { 01740 using namespace jwsc; 01741 01742 if (normal) 01743 { 01744 assert(fabs(normal->elts[3] - 1.0) < 1.0e-8); 01745 glNormal3d(normal->elts[0], normal->elts[1], normal->elts[2]); 01746 } 01747 01748 glBegin(GL_POLYGON); 01749 for (size_t i = 0; i < pts.size(); i++) 01750 { 01751 Vector_d* pt = pts[ i ]; 01752 01753 glVertex4d(pt->elts[0], pt->elts[1], pt->elts[2], pt->elts[3]); 01754 } 01755 glEnd(); 01756 } 01757 01758 01770 void Polygon_d::add_point(double x, double y, double z) 01771 throw (jwscxx::base::Arg_error) 01772 { 01773 using namespace jwsc; 01774 01775 Vector_d* pt = 0; 01776 01777 create_vector_d(&pt, 4); 01778 pt->elts[0] = x; 01779 pt->elts[1] = y; 01780 pt->elts[2] = z; 01781 pt->elts[3] = 1.0; 01782 01783 add_point(pt); 01784 } 01785 01786 01797 void Polygon_d::add_point(jwsc::Vector_d* pt) throw (jwscxx::base::Arg_error) 01798 { 01799 using namespace jwsc; 01800 01801 if (pt->num_elts != 4) 01802 { 01803 throw Arg_error("Point to add not homogeneous"); 01804 } 01805 else if (fabs(pt->elts[3]) < 1.0e-10) 01806 { 01807 throw Arg_error("Homogeneous coordinate is zero"); 01808 } 01809 01810 size_t N = pts.size(); 01811 01812 pts.push_back(pt); 01813 01814 if (N >= 3) 01815 { 01816 assert(normal); 01817 01818 double dp1, dp2; 01819 01820 calc_vector_dot_prod_d(&dp1, normal, pts[0]); 01821 calc_vector_dot_prod_d(&dp2, normal, pt); 01822 01823 if (fabs(dp1 - dp2) > 1.0e-4) 01824 { 01825 throw Arg_error("Point to add not in the polygon's plane"); 01826 } 01827 } 01828 else if (N == 2) 01829 { 01830 update_normal(); 01831 } 01832 01833 update_centroid(); 01834 } 01835 01836 01841 const jwsc::Vector_d* Polygon_d::get_normal() const 01842 { 01843 return normal; 01844 } 01845 01846 01850 const jwsc::Vector_d* Polygon_d::get_centroid() const 01851 { 01852 return centroid; 01853 } 01854 01855 01856 size_t Polygon_d::get_num_points() const 01857 { 01858 return pts.size(); 01859 } 01860 01861 01869 const jwsc::Vector_d* Polygon_d::get_point(size_t i) const 01870 throw (jwscxx::base::Arg_error) 01871 { 01872 if (i >= pts.size()) 01873 { 01874 throw jwscxx::base::Arg_error("Invalid point index"); 01875 } 01876 01877 return static_cast<const jwsc::Vector_d*>(pts[ i ]); 01878 } 01879 01880 01887 void Polygon_d::flip_normal() 01888 { 01889 normal_flipped = !normal_flipped; 01890 update_normal(); 01891 } 01892 01893 01901 void Polygon_d::project() 01902 { 01903 using namespace jwsc; 01904 01905 GLdouble glM[16] = {0}; 01906 01907 glGetDoublev(GL_MODELVIEW_MATRIX, glM); 01908 01909 glMatrixMode(GL_PROJECTION); 01910 glPushMatrix(); 01911 glMultMatrixd(glM); 01912 glGetDoublev(GL_PROJECTION_MATRIX, glM); 01913 glPopMatrix(); 01914 glMatrixMode(GL_MODELVIEW); 01915 01916 Matrix_d* M = 0; 01917 create_matrix_d(&M, 4, 4); 01918 for (size_t row = 0; row < 4; row++) 01919 { 01920 for (size_t col = 0; col < 4; col++) 01921 { 01922 M->elts[ row ][ col ] = glM[ col*4 + row ]; 01923 } 01924 } 01925 01926 double width = Camera_d::get_gl_viewport_width(); 01927 double height = Camera_d::get_gl_viewport_height(); 01928 01929 for (size_t i = 0; i < pts.size(); i++) 01930 { 01931 Vector_d* pt = pts[ i ]; 01932 01933 multiply_matrix_and_vector_d(&pt, M, pt); 01934 01935 double w = 1.0 / pt->elts[ 3 ]; 01936 pt->elts[ 0 ] = 0.5*width* (pt->elts[ 0 ]*w + 1.0); 01937 pt->elts[ 1 ] = 0.5*height*(pt->elts[ 1 ]*w + 1.0); 01938 pt->elts[ 2 ] = 0; 01939 pt->elts[ 3 ] = 1.0; 01940 } 01941 01942 free_matrix_d(M); 01943 } 01944 01945 01951 uint8_t Polygon_d::is_visible(const Camera_d* camera) const 01952 { 01953 if (!normal) 01954 return 0; 01955 01956 const jwsc::Vector_d* prp = camera->get_prp(); 01957 01958 double x = prp->elts[0] - centroid->elts[0]; 01959 double y = prp->elts[1] - centroid->elts[1]; 01960 double z = prp->elts[2] - centroid->elts[2]; 01961 01962 if ((x*normal->elts[0] + y*normal->elts[1] + z*normal->elts[2]) > 0) 01963 return 1; 01964 return 0; 01965 } 01966 01974 uint8_t Polygon_d::is_visible_up_to_epsilon(const Camera_d* camera, double & epsilon) const 01975 { 01976 if (!normal) 01977 return 0; 01978 01979 const jwsc::Vector_d* prp = camera->get_prp(); 01980 01981 double x = prp->elts[0] - centroid->elts[0]; 01982 double y = prp->elts[1] - centroid->elts[1]; 01983 double z = prp->elts[2] - centroid->elts[2]; 01984 01985 double dp = ((double)(x*normal->elts[0] + y*normal->elts[1] + z*normal->elts[2])); 01986 01987 return (dp > epsilon); 01988 } 01989 01990 01991 uint32_t Polygon_d::get_id() const 01992 { 01993 return id; 01994 } 01995 01996 01997 void Polygon_d::set_id(uint32_t id) 01998 { 01999 this->id = id; 02000 } 02001 02002 02008 void Polygon_d::update_normal() 02009 { 02010 using namespace jwsc; 02011 02012 size_t N = pts.size(); 02013 02014 if (N < 3) 02015 return; 02016 02017 Vector_d* p1 = pts[0]; 02018 Vector_d* p2 = pts[1]; 02019 Vector_d* pN = pts[N-1]; 02020 02021 double w1 = pts[0]->elts[3]; 02022 double w2 = pts[1]->elts[3]; 02023 double wN = pts[N-1]->elts[3]; 02024 02025 assert(fabs(w1) >= 1.0e-10); 02026 assert(fabs(w2) >= 1.0e-10); 02027 assert(fabs(wN) >= 1.0e-10); 02028 02029 w1 = 1.0 / w1; 02030 w2 = 1.0 / w2; 02031 wN = 1.0 / wN; 02032 02033 // p2 - p1 02034 double v1_x = p2->elts[0]*w2 - p1->elts[0]*w1; 02035 double v1_y = p2->elts[1]*w2 - p1->elts[1]*w1; 02036 double v1_z = p2->elts[2]*w2 - p1->elts[2]*w1; 02037 02038 // pN - p1 02039 double v2_x = pN->elts[0]*wN - p1->elts[0]*w1; 02040 double v2_y = pN->elts[1]*wN - p1->elts[1]*w1; 02041 double v2_z = pN->elts[2]*wN - p1->elts[2]*w1; 02042 02043 // v1 x v2 02044 create_vector_d(&normal, 4); 02045 normal->elts[0] = v1_y*v2_z - v1_z*v2_y; 02046 normal->elts[1] = v1_z*v2_x - v1_x*v2_z; 02047 normal->elts[2] = v1_x*v2_y - v1_y*v2_x; 02048 normal->elts[3] = 0.0; 02049 02050 if (normal_flipped) 02051 { 02052 normal->elts[0] *= -1; 02053 normal->elts[1] *= -1; 02054 normal->elts[2] *= -1; 02055 } 02056 02057 normalize_vector_mag_d(&normal, normal); 02058 normal->elts[3] = 1.0; 02059 } 02060 02061 02070 void Polygon_d::update_centroid() 02071 { 02072 using namespace jwsc; 02073 02074 size_t N = pts.size(); 02075 double area = 0; 02076 02077 if (N == 0) 02078 { 02079 return; 02080 } 02081 else if (N == 1) 02082 { 02083 copy_vector_d(¢roid, pts[0]); 02084 return; 02085 } 02086 else if (N == 2) 02087 { 02088 double x = (pts[0]->elts[0]/pts[0]->elts[3] + 02089 pts[1]->elts[0]/pts[1]->elts[3]) * 0.5; 02090 double y = (pts[0]->elts[1]/pts[0]->elts[3] + 02091 pts[1]->elts[1]/pts[1]->elts[3]) * 0.5; 02092 double z = (pts[0]->elts[2]/pts[0]->elts[3] + 02093 pts[1]->elts[2]/pts[1]->elts[3]) * 0.5; 02094 create_zero_vector_d(¢roid, 4); 02095 centroid->elts[0] = x; 02096 centroid->elts[1] = y; 02097 centroid->elts[2] = z; 02098 centroid->elts[3] = 1.0; 02099 return; 02100 } 02101 02102 double x3 = pts[N-1]->elts[0]; 02103 double y3 = pts[N-1]->elts[1]; 02104 double z3 = pts[N-1]->elts[2]; 02105 02106 for (size_t i = 0; i < N - 2; i++) 02107 { 02108 double x1 = pts[i]->elts[0]; 02109 double y1 = pts[i]->elts[1]; 02110 double z1 = pts[i]->elts[2]; 02111 02112 double x2 = pts[i+1]->elts[0]; 02113 double y2 = pts[i+1]->elts[1]; 02114 double z2 = pts[i+1]->elts[2]; 02115 02116 double dot = (x2 - x1)*(x3 - x1) + 02117 (y2 - y1)*(y3 - y1) + 02118 (z2 - z1)*(z3 - z1); 02119 02120 double base = sqrt((x2 - x1)*(x2 - x1) + 02121 (y2 - y1)*(y2 - y1) + 02122 (z2 - z1)*(z2 - z1)); 02123 02124 double height; 02125 02126 if (base < 1.0e-8) 02127 { 02128 height = 0; 02129 } 02130 else 02131 { 02132 double alpha = dot / (base*base); 02133 02134 double a = x3 - x1 - alpha*(x2 - x1); 02135 double b = y3 - y1 - alpha*(y2 - y1); 02136 double c = z3 - z1 - alpha*(z2 - z1); 02137 02138 height = sqrt(a*a + b*b + c*c); 02139 } 02140 02141 double tri_area = 0.5 * base * height; 02142 02143 area += tri_area; 02144 centroid->elts[0] += tri_area * (x1 + x2 + x3) / 3.0; 02145 centroid->elts[1] += tri_area * (y1 + y2 + y3) / 3.0; 02146 centroid->elts[2] += tri_area * (z1 + z2 + z3) / 3.0; 02147 } 02148 02149 if (area > 1.0e-8) 02150 { 02151 centroid->elts[0] /= area; 02152 centroid->elts[1] /= area; 02153 centroid->elts[2] /= area; 02154 centroid->elts[3] = 1.0; 02155 } 02156 else 02157 { 02158 copy_vector_d(¢roid, pts[0]); 02159 } 02160 } 02161 02162 02163 uint32_t Polygon_d::generate_id() 02164 { 02165 static uint32_t next_id = 1; 02166 return next_id++; 02167 }