1 // Copyright (c) 1997-2002 Max-Planck-Institute Saarbruecken (Germany). 2 // All rights reserved. 3 // 4 // This file is part of CGAL (www.cgal.org); you may redistribute it under 5 // the terms of the Q Public License version 1.0. 6 // See the file LICENSE.QPL distributed with CGAL. 7 // 8 // Licensees holding a valid commercial license may use this file in 9 // accordance with the commercial license agreement provided with the software. 10 // 11 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 12 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 13 // 14 // $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/trunk/Nef_3/include/CGAL/Nef_3/OGL_helper.h $ 15 // $Id: OGL_helper.h 56667 2010-06-09 07:37:13Z sloriot $ 16 // 17 // 18 // Author(s) : Peter Hachenberger <hachenberger@mpi-sb.mpg.de> 19 20 // Modified for OpenSCAD 21 22 #pragma once 23 24 #pragma push_macro("NDEBUG") 25 #undef NDEBUG 26 #include <CGAL/Nef_S2/OGL_base_object.h> 27 #include <CGAL/Simple_cartesian.h> 28 #include <CGAL/Nef_3/SNC_decorator.h> 29 #pragma pop_macro("NDEBUG") 30 31 #include "system-gl.h" 32 #include <cstdlib> 33 34 // Overridden in CGAL_renderer 35 /* 36 #define CGAL_NEF3_OGL_MARKED_VERTEX_COLOR 183,232,92 37 #define CGAL_NEF3_OGL_MARKED_EDGE_COLOR 171,216,86 38 #define CGAL_NEF3_OGL_MARKED_FACET_COLOR 157,203,81 39 #define CGAL_NEF3_OGL_MARKED_BACK_FACET_COLOR 157,103,181 40 41 #define CGAL_NEF3_OGL_UNMARKED_VERTEX_COLOR 255,246,124 42 #define CGAL_NEF3_OGL_UNMARKED_EDGE_COLOR 255,236,94 43 #define CGAL_NEF3_OGL_UNMARKED_FACET_COLOR 249,215,44 44 #define CGAL_NEF3_OGL_UNMARKED_BACK_FACET_COLOR 249,115,144 45 */ 46 47 const bool cull_backfaces = false; 48 const bool color_backfaces = false; 49 50 #ifdef _WIN32 51 #include <windows.h> // For the CALLBACK macro 52 #define CGAL_GLU_TESS_CALLBACK CALLBACK 53 #else 54 #define CGAL_GLU_TESS_CALLBACK 55 #endif 56 57 #ifdef __APPLE__ 58 # include <AvailabilityMacros.h> 59 #endif 60 61 #if defined __APPLE__ && !defined MAC_OS_X_VERSION_10_5 62 #define CGAL_GLU_TESS_DOTS ... 63 #else 64 #define CGAL_GLU_TESS_DOTS 65 #endif 66 67 68 namespace CGAL { 69 70 namespace OGL { 71 72 // ---------------------------------------------------------------------------- 73 // Drawable double types: 74 // ---------------------------------------------------------------------------- 75 76 typedef CGAL::Simple_cartesian<double> DKernel; 77 typedef DKernel::Point_3 Double_point; 78 typedef DKernel::Vector_3 Double_vector; 79 typedef DKernel::Segment_3 Double_segment; 80 typedef DKernel::Aff_transformation_3 Affine_3; 81 82 // DPoint = a double point including a mark 83 class DPoint : public Double_point { 84 bool m_; 85 public: DPoint()86 DPoint() {} DPoint(const Double_point & p,bool m)87 DPoint(const Double_point& p, bool m) : Double_point(p) { m_ = m; } DPoint(const DPoint & p)88 DPoint(const DPoint& p) : Double_point(p) { m_ = p.m_; } 89 DPoint& operator=(const DPoint& p) 90 { Double_point::operator=(p); m_ = p.m_; return *this; } mark()91 bool mark() const { return m_; } 92 }; 93 94 // DSegment = a double segment including a mark 95 class DSegment : public Double_segment { 96 bool m_; 97 public: DSegment()98 DSegment() {} DSegment(const Double_segment & s,bool m)99 DSegment(const Double_segment& s, bool m) : Double_segment(s) { m_ = m; } DSegment(const DSegment & s)100 DSegment(const DSegment& s) : Double_segment(s) { m_ = s.m_; } 101 DSegment& operator=(const DSegment& s) 102 { Double_segment::operator=(s); m_ = s.m_; return *this; } mark()103 bool mark() const { return m_; } 104 }; 105 106 // Double_triple = a class that stores a triple of double 107 // coordinates; we need a pointer to the coordinates in a C array 108 // for OpenGL 109 class Double_triple { 110 typedef double* double_ptr; 111 typedef const double* const_double_ptr; 112 double coords_[3]; 113 public: Double_triple()114 Double_triple() 115 { coords_[0]=coords_[1]=coords_[2]=0.0; } Double_triple(double x,double y,double z)116 Double_triple(double x, double y, double z) 117 { coords_[0]=x; coords_[1]=y; coords_[2]=z; } Double_triple(const Double_triple & t)118 Double_triple(const Double_triple& t) 119 { coords_[0]=t.coords_[0]; 120 coords_[1]=t.coords_[1]; 121 coords_[2]=t.coords_[2]; 122 } 123 Double_triple& operator=(const Double_triple& t) 124 { coords_[0]=t.coords_[0]; 125 coords_[1]=t.coords_[1]; 126 coords_[2]=t.coords_[2]; 127 return *this; } double_ptr()128 operator double_ptr() const 129 { return const_cast<Double_triple&>(*this).coords_; } 130 double operator[](unsigned i) 131 { CGAL_assertion(i<3); return coords_[i]; } 132 }; // Double_triple 133 134 static std::ostream& operator << (std::ostream& os, 135 const Double_triple& t) 136 { os << "(" << t[0] << "," << t[1] << "," << t[2] << ")"; 137 return os; } 138 139 140 // DFacet stores the facet cycle vertices in a continuus C array 141 // of three double components, this is necessary due to the OpenGL 142 // tesselator input format ! 143 class DFacet { 144 typedef std::vector<Double_triple> Coord_vector; 145 typedef std::vector<unsigned> Cycle_vector; 146 Coord_vector coords_; // stores all vertex coordinates 147 Cycle_vector fc_ends_; // stores entry points of facet cycles 148 Double_triple normal_; // stores normal and mark of facet 149 bool mark_; 150 151 public: 152 typedef Coord_vector::iterator Coord_iterator; 153 typedef Coord_vector::const_iterator Coord_const_iterator; 154 DFacet()155 DFacet() {} 156 push_back_vertex(double x,double y,double z)157 void push_back_vertex(double x, double y, double z) 158 { coords_.push_back(Double_triple(x,y,z)); } 159 DFacet(const DFacet & f)160 DFacet(const DFacet& f) 161 { coords_ = f.coords_; 162 fc_ends_ = f.fc_ends_; 163 normal_ = f.normal_; 164 mark_ = f.mark_; 165 } 166 167 DFacet& operator=(const DFacet& f) 168 { coords_ = f.coords_; 169 fc_ends_ = f.fc_ends_; 170 normal_ = f.normal_; 171 mark_ = f.mark_; 172 return *this; 173 } 174 ~DFacet()175 ~DFacet() 176 { coords_.clear(); fc_ends_.clear(); } 177 push_back_vertex(const Double_point & p)178 void push_back_vertex(const Double_point& p) 179 { push_back_vertex(p.x(),p.y(),p.z()); } 180 set_normal(double x,double y,double z,bool m)181 void set_normal(double x, double y, double z, bool m) 182 { double l = sqrt(x*x + y*y + z*z); 183 normal_ = Double_triple(x/l,y/l,z/l); mark_ = m; } 184 dx()185 double dx() const { return normal_[0]; } dy()186 double dy() const { return normal_[1]; } dz()187 double dz() const { return normal_[2]; } mark()188 bool mark() const { return mark_; } normal()189 double* normal() const 190 { return static_cast<double*>(normal_); } 191 new_facet_cycle()192 void new_facet_cycle() 193 { fc_ends_.push_back(coords_.size()); } 194 number_of_facet_cycles()195 unsigned number_of_facet_cycles() const 196 { return fc_ends_.size(); } 197 facet_cycle_begin(unsigned i)198 Coord_iterator facet_cycle_begin(unsigned i) 199 { CGAL_assertion(i<number_of_facet_cycles()); 200 if (i==0) return coords_.begin(); 201 else return coords_.begin()+fc_ends_[i]; } 202 facet_cycle_end(unsigned i)203 Coord_iterator facet_cycle_end(unsigned i) 204 { CGAL_assertion(i<number_of_facet_cycles()); 205 if (i<fc_ends_.size()-1) return coords_.begin()+fc_ends_[i+1]; 206 else return coords_.end(); } 207 facet_cycle_begin(unsigned i)208 Coord_const_iterator facet_cycle_begin(unsigned i) const 209 { CGAL_assertion(i<number_of_facet_cycles()); 210 if (i==0) return coords_.begin(); 211 else return coords_.begin()+fc_ends_[i]; } 212 facet_cycle_end(unsigned i)213 Coord_const_iterator facet_cycle_end(unsigned i) const 214 { CGAL_assertion(i<number_of_facet_cycles()); 215 if (i<fc_ends_.size()-1) return coords_.begin()+fc_ends_[i+1]; 216 else return coords_.end(); } 217 218 void debug(std::ostream& os = std::cerr) const 219 { os << "DFacet, normal=" << normal_ << ", mark=" << mark() << std::endl; 220 for(unsigned i=0; i<number_of_facet_cycles(); ++i) { 221 os << " facet cycle "; 222 // put all vertices in facet cycle into contour: 223 Coord_const_iterator cit; 224 for(cit = facet_cycle_begin(i); cit != facet_cycle_end(i); ++cit) 225 os << *cit; 226 os << std::endl; 227 } 228 } 229 230 }; // DFacet 231 232 233 // ---------------------------------------------------------------------------- 234 // OGL Drawable Polyhedron: 235 // ---------------------------------------------------------------------------- 236 beginCallback(GLenum which)237 inline void CGAL_GLU_TESS_CALLBACK beginCallback(GLenum which) 238 { glBegin(which); } 239 endCallback(void)240 inline void CGAL_GLU_TESS_CALLBACK endCallback(void) 241 { glEnd(); } 242 errorCallback(GLenum errorCode)243 inline void CGAL_GLU_TESS_CALLBACK errorCallback(GLenum errorCode) 244 { const GLubyte *estring; 245 estring = gluErrorString(errorCode); 246 fprintf(stderr, "Tessellation Error: %s\n", estring); 247 std::exit (0); 248 } 249 vertexCallback(GLvoid * vertex,GLvoid * user)250 inline void CGAL_GLU_TESS_CALLBACK vertexCallback(GLvoid* vertex, 251 GLvoid* user) 252 { GLdouble* pc(static_cast<GLdouble*>(vertex)); 253 GLdouble* pu(static_cast<GLdouble*>(user)); 254 // CGAL_NEF_TRACEN("vertexCallback coord "<<pc[0]<<","<<pc[1]<<","<<pc[2]); 255 // CGAL_NEF_TRACEN("vertexCallback normal "<<pu[0]<<","<<pu[1]<<","<<pu[2]); 256 glNormal3dv(pu); 257 glVertex3dv(pc); 258 } 259 combineCallback(GLdouble coords[3],GLvoid * [4],GLfloat[4],GLvoid ** dataOut)260 inline void CGAL_GLU_TESS_CALLBACK combineCallback(GLdouble coords[3], GLvoid *[4], GLfloat [4], GLvoid **dataOut) 261 { static std::list<GLdouble*> pcache; 262 if (dataOut) { 263 GLdouble *n = new GLdouble[3]; 264 n[0] = coords[0]; 265 n[1] = coords[1]; 266 n[2] = coords[2]; 267 pcache.push_back(n); 268 *dataOut = n; 269 } else { 270 for (std::list<GLdouble*>::const_iterator i = pcache.begin(); i != pcache.end(); i++) 271 delete[] *i; 272 pcache.clear(); 273 } 274 } 275 276 277 enum { SNC_AXES}; 278 enum { SNC_BOUNDARY, SNC_SKELETON }; 279 280 class Polyhedron : public OGL_base_object { 281 protected: 282 std::list<DPoint> vertices_; 283 std::list<DSegment> edges_; 284 std::list<DFacet> halffacets_; 285 286 GLuint object_list_; 287 bool init_; 288 289 Bbox_3 bbox_; 290 291 int style; 292 std::vector<bool> switches; 293 294 typedef std::list<DPoint>::const_iterator Vertex_iterator; 295 typedef std::list<DSegment>::const_iterator Edge_iterator; 296 typedef std::list<DFacet>::const_iterator Halffacet_iterator; 297 298 public: Polyhedron()299 Polyhedron() : bbox_(-1,-1,-1,1,1,1), switches(1) { 300 object_list_ = 0; 301 init_ = false; 302 style = SNC_BOUNDARY; 303 switches[SNC_AXES] = false; 304 } 305 306 /* 307 Polyhedron(const Polyhedron& P) : 308 object_list_(0), 309 init_(false), 310 bbox_(P.bbox_), 311 style(P.style), 312 switches(2) { 313 314 switches[SNC_AXES] = P.switches[SNC_AXES]; 315 316 Vertex_iterator v; 317 for(v=P.vertices_.begin();v!=P.vertices_.end();++v) 318 vertices_.push_back(*v); 319 Edge_iterator e; 320 for(e=P.edges_.begin();e!=P.edges_.end();++e) 321 edges_.push_back(*e); 322 Halffacet_iterator f; 323 for(f=P.halffacets_.begin();f!=P.halffacets_.end();++f) 324 halffacets_.push_back(*f); 325 } 326 327 Polyhedron& operator=(const Polyhedron& P) { 328 if (object_list_) glDeleteLists(object_list_, 4); 329 object_list_ = 0; 330 init_ = false; 331 style = P.style; 332 switches[SNC_AXES] = P.switches[SNC_AXES]; 333 334 Vertex_iterator v; 335 vertices_.clear(); 336 for(v=P.vertices_.begin();v!=P.vertices_.end();++v) 337 vertices_.push_back(*v); 338 Edge_iterator e; 339 edges_.clear(); 340 for(e=P.edges_.begin();e!=P.edges_.end();++e) 341 edges_.push_back(*e); 342 Halffacet_iterator f; 343 halffacets_.clear(); 344 for(f=P.halffacets_.begin();f!=P.halffacets_.end();++f) 345 halffacets_.push_back(*f); 346 init(); 347 return *this; 348 } 349 */ ~Polyhedron()350 ~Polyhedron() 351 { if (object_list_) glDeleteLists(object_list_, 4); } 352 push_back(const Double_point & p,bool m)353 void push_back(const Double_point& p, bool m) { 354 vertices_.push_back(DPoint(p,m)); 355 } push_back(const Double_segment & s,bool m)356 void push_back(const Double_segment& s, bool m) 357 { edges_.push_back(DSegment(s,m)); } push_back(const DFacet & f)358 void push_back(const DFacet& f) 359 { halffacets_.push_back(f); } 360 toggle(int index)361 void toggle(int index) override { 362 switches[index] = !switches[index]; 363 } 364 set_style(int index)365 void set_style(int index) override { 366 style = index; 367 } 368 is_initialized()369 bool is_initialized() const { return init_; } 370 bbox()371 Bbox_3 bbox() const { return bbox_; } bbox()372 Bbox_3& bbox() { return bbox_; } 373 374 // Overridden in CGAL_renderer getVertexColor(Vertex_iterator v)375 virtual CGAL::Color getVertexColor(Vertex_iterator v) const 376 { 377 PRINTD("getVertexColor()"); 378 (void)v; 379 // CGAL::Color cf(CGAL_NEF3_OGL_MARKED_VERTEX_COLOR), 380 // ct(CGAL_NEF3_OGL_UNMARKED_VERTEX_COLOR); // more blue-ish 381 // CGAL::Color c = v->mark() ? ct : cf; 382 CGAL::Color c(0,0,200); 383 return c; 384 } 385 386 virtual void draw(bool) const = 0; 387 draw(Vertex_iterator v)388 void draw(Vertex_iterator v) const { 389 PRINTD("draw( Vertex_iterator )"); 390 // CGAL_NEF_TRACEN("drawing vertex "<<*v); 391 CGAL::Color c = getVertexColor(v); 392 glPointSize(10); 393 //glPointSize(1); 394 glColor3ub(c.red(), c.green(), c.blue()); 395 glBegin(GL_POINTS); 396 glVertex3d(v->x(),v->y(),v->z()); 397 #ifdef CGAL_NEF_EMPHASIZE_VERTEX 398 glColor3ub(255,0,0); 399 glVertex3d(CGAL_NEF_EMPHASIZE_VERTEX); 400 #endif 401 glEnd(); 402 } 403 404 // Overridden in CGAL_renderer getEdgeColor(Edge_iterator e)405 virtual CGAL::Color getEdgeColor(Edge_iterator e) const 406 { 407 PRINTD("getEdgeColor)"); 408 (void)e; 409 // CGAL::Color cf(CGAL_NEF3_OGL_MARKED_EDGE_COLOR), 410 // ct(CGAL_NEF3_OGL_UNMARKED_EDGE_COLOR); // more blue-ish 411 // CGAL::Color c = e->mark() ? ct : cf; 412 // Overridden in CGAL_renderer 413 CGAL::Color c(200,0,0); 414 return c; 415 } 416 draw(Edge_iterator e)417 void draw(Edge_iterator e) const { 418 PRINTD("draw(Edge_iterator)"); 419 // CGAL_NEF_TRACEN("drawing edge "<<*e); 420 Double_point p = e->source(), q = e->target(); 421 CGAL::Color c = getEdgeColor(e); 422 glLineWidth(5); 423 //glLineWidth(1); 424 glColor3ub(c.red(),c.green(),c.blue()); 425 glBegin(GL_LINE_STRIP); 426 glVertex3d(p.x(), p.y(), p.z()); 427 glVertex3d(q.x(), q.y(), q.z()); 428 glEnd(); 429 } 430 431 432 // Overridden in CGAL_renderer getFacetColor(Halffacet_iterator,bool)433 virtual CGAL::Color getFacetColor(Halffacet_iterator /*f*/, bool /*is_back_facing*/) const 434 { 435 PRINTD("getFacetColor"); 436 /* 437 (void)f; 438 // CGAL::Color cf(CGAL_NEF3_OGL_MARKED_FACET_COLOR), 439 // ct(CGAL_NEF3_OGL_UNMARKED_FACET_COLOR); // more blue-ish 440 // CGAL::Color c = (f->mark() ? ct : cf); 441 */ 442 CGAL::Color c(0,200,0); 443 return c; 444 445 /* 446 if (is_back_facing) return !f->mark() 447 ? CGAL::Color(CGAL_NEF3_OGL_MARKED_BACK_FACET_COLOR) 448 : CGAL::Color(CGAL_NEF3_OGL_UNMARKED_BACK_FACET_COLOR); 449 else return !f->mark() 450 ? CGAL::Color(CGAL_NEF3_OGL_MARKED_FACET_COLOR) 451 : CGAL::Color(CGAL_NEF3_OGL_UNMARKED_FACET_COLOR); 452 */ 453 } 454 draw(Halffacet_iterator f,bool is_back_facing)455 void draw(Halffacet_iterator f, bool is_back_facing) const { 456 PRINTD("draw(Halffacet_iterator)"); 457 // CGAL_NEF_TRACEN("drawing facet "<<(f->debug(),"")); 458 GLUtesselator* tess_ = gluNewTess(); 459 gluTessCallback(tess_, GLenum(GLU_TESS_VERTEX_DATA), 460 (GLvoid (CGAL_GLU_TESS_CALLBACK *)(CGAL_GLU_TESS_DOTS)) &vertexCallback); 461 gluTessCallback(tess_, GLenum(GLU_TESS_COMBINE), 462 (GLvoid (CGAL_GLU_TESS_CALLBACK *)(CGAL_GLU_TESS_DOTS)) &combineCallback); 463 gluTessCallback(tess_, GLenum(GLU_TESS_BEGIN), 464 (GLvoid (CGAL_GLU_TESS_CALLBACK *)(CGAL_GLU_TESS_DOTS)) &beginCallback); 465 gluTessCallback(tess_, GLenum(GLU_TESS_END), 466 (GLvoid (CGAL_GLU_TESS_CALLBACK *)(CGAL_GLU_TESS_DOTS)) &endCallback); 467 gluTessCallback(tess_, GLenum(GLU_TESS_ERROR), 468 (GLvoid (CGAL_GLU_TESS_CALLBACK *)(CGAL_GLU_TESS_DOTS)) &errorCallback); 469 gluTessProperty(tess_, GLenum(GLU_TESS_WINDING_RULE), 470 GLU_TESS_WINDING_POSITIVE); 471 472 DFacet::Coord_const_iterator cit; 473 CGAL::Color c = getFacetColor(f,is_back_facing); 474 glColor3ub(c.red(),c.green(),c.blue()); 475 gluTessBeginPolygon(tess_,f->normal()); 476 // CGAL_NEF_TRACEN(" "); 477 // CGAL_NEF_TRACEN("Begin Polygon"); 478 gluTessNormal(tess_,f->dx(),f->dy(),f->dz()); 479 // forall facet cycles of f: 480 for(unsigned i = 0; i < f->number_of_facet_cycles(); ++i) { 481 gluTessBeginContour(tess_); 482 // CGAL_NEF_TRACEN(" Begin Contour"); 483 // put all vertices in facet cycle into contour: 484 for(cit = f->facet_cycle_begin(i); 485 cit != f->facet_cycle_end(i); ++cit) { 486 gluTessVertex(tess_, *cit, *cit); 487 // CGAL_NEF_TRACEN(" add Vertex"); 488 } 489 gluTessEndContour(tess_); 490 // CGAL_NEF_TRACEN(" End Contour"); 491 } 492 gluTessEndPolygon(tess_); 493 // CGAL_NEF_TRACEN("End Polygon"); 494 gluDeleteTess(tess_); 495 combineCallback(NULL, NULL, NULL, NULL); 496 } 497 construct_axes()498 void construct_axes() const 499 { 500 PRINTD("construct_axes"); 501 glLineWidth(2.0); 502 // red x-axis 503 glColor3f(1.0,0.0,0.0); 504 glBegin(GL_LINES); 505 glVertex3f(0.0,0.0,0.0); 506 glVertex3f(5000.0,0.0,0.0); 507 glEnd(); 508 // green y-axis 509 glColor3f(0.0,1.0,0.0); 510 glBegin(GL_LINES); 511 glVertex3f(0.0,0.0,0.0); 512 glVertex3f(0.0,5000.0,0.0); 513 glEnd(); 514 // blue z-axis and equator 515 glColor3f(0.0,0.0,1.0); 516 glBegin(GL_LINES); 517 glVertex3f(0.0,0.0,0.0); 518 glVertex3f(0.0,0.0,5000.0); 519 glEnd(); 520 // six coordinate points in pink: 521 glPointSize(10); 522 glBegin(GL_POINTS); 523 glColor3f(1.0,0.0,0.0); 524 glVertex3d(5,0,0); 525 glColor3f(0.0,1.0,0.0); 526 glVertex3d(0,5,0); 527 glColor3f(0.0,0.0,1.0); 528 glVertex3d(0,0,5); 529 glEnd(); 530 } 531 532 fill_display_lists()533 void fill_display_lists() { 534 PRINTD("fill_display_lists"); 535 glNewList(object_list_, GL_COMPILE); 536 Vertex_iterator v; 537 for(v=vertices_.begin();v!=vertices_.end();++v) 538 draw(v); 539 glEndList(); 540 541 glNewList(object_list_+1, GL_COMPILE); 542 Edge_iterator e; 543 for(e=edges_.begin();e!=edges_.end();++e) 544 draw(e); 545 glEndList(); 546 547 glNewList(object_list_+2, GL_COMPILE); 548 549 if (cull_backfaces || color_backfaces) { 550 glEnable(GL_CULL_FACE); 551 glCullFace(GL_BACK); 552 } 553 for (int i = 0; i < (color_backfaces ? 2 : 1); i++) { 554 Halffacet_iterator f; 555 for(f=halffacets_.begin();f!=halffacets_.end();++f) 556 draw(f, i); 557 if (color_backfaces) glCullFace(GL_FRONT); 558 } 559 if (cull_backfaces || color_backfaces) { 560 glCullFace(GL_BACK); 561 glDisable(GL_CULL_FACE); 562 } 563 glEndList(); 564 565 glNewList(object_list_+3, GL_COMPILE); // axes: 566 construct_axes(); 567 glEndList(); 568 569 } 570 init()571 void init() override { 572 PRINTD("init()"); 573 if (init_) return; 574 init_ = true; 575 switches[SNC_AXES] = false; 576 style = SNC_BOUNDARY; 577 object_list_ = glGenLists(4); 578 CGAL_assertion(object_list_); 579 fill_display_lists(); 580 PRINTD("init() end"); 581 } 582 583 draw()584 void draw() const override 585 { 586 PRINTD("draw()"); 587 if (!is_initialized()) const_cast<Polyhedron&>(*this).init(); 588 double l = (std::max)( (std::max)( bbox().xmax() - bbox().xmin(), 589 bbox().ymax() - bbox().ymin()), 590 bbox().zmax() - bbox().zmin()); 591 if ( l < 1) // make sure that a single point doesn't screw up here 592 l = 1; 593 glScaled( 4.0/l, 4.0/l, 4.0/l); 594 glTranslated( -(bbox().xmax() + bbox().xmin()) / 2.0, 595 -(bbox().ymax() + bbox().ymin()) / 2.0, 596 -(bbox().zmax() + bbox().zmin()) / 2.0); 597 if (style == SNC_BOUNDARY) { 598 //glEnable(GL_LIGHTING); 599 glCallList(object_list_+2); // facets 600 //glDisable(GL_LIGHTING); 601 } 602 // move edges and vertices a bit towards the view-point, 603 // i.e., 1/100th of the unit vector in camera space 604 // double f = l / 4.0 / 100.0; 605 // glTranslated( z_vec[0] * f, z_vec[1] * f, z_vec[2] * f); 606 glCallList(object_list_+1); // edges 607 glCallList(object_list_); // vertices 608 if (switches[SNC_AXES]) glCallList(object_list_+3); // axis 609 PRINTD("draw() end"); 610 } 611 612 void debug(std::ostream& os = std::cerr) const 613 { 614 os << "OGL::Polyhedron" << std::endl; 615 os << "Vertices:" << std::endl; 616 Vertex_iterator v; 617 for(v=vertices_.begin();v!=vertices_.end();++v) 618 os << " "<<*v<<", mark="<<v->mark()<<std::endl; 619 os << "Edges:" << std::endl; 620 Edge_iterator e; 621 for(e=edges_.begin();e!=edges_.end();++e) 622 os << " "<<*e<<", mark="<<e->mark()<<std::endl; 623 os << "Facets:" << std::endl; 624 Halffacet_iterator f; 625 for(f=halffacets_.begin();f!=halffacets_.end();++f) { 626 f->debug(); os << std::endl; 627 } 628 os << std::endl; 629 } 630 631 }; // Polyhedron 632 633 template<typename Nef_polyhedron> 634 class Nef3_Converter { 635 typedef typename Nef_polyhedron::SNC_structure SNC_structure; 636 typedef CGAL::SNC_decorator<SNC_structure> Base; 637 typedef CGAL::SNC_FM_decorator<SNC_structure> FM_decorator; 638 639 public: 640 typedef typename SNC_structure::Vertex_const_iterator Vertex_const_iterator; 641 typedef typename SNC_structure::Halfedge_const_iterator Halfedge_const_iterator; 642 typedef typename SNC_structure::Halffacet_const_iterator Halffacet_const_iterator; 643 typedef typename SNC_structure::Halffacet_cycle_const_iterator Halffacet_cycle_const_iterator; 644 645 typedef typename SNC_structure::Object_const_handle Object_const_handle; 646 typedef typename SNC_structure::SHalfedge_const_handle SHalfedge_const_handle; 647 typedef typename SNC_structure::SHalfloop_const_handle SHalfloop_const_handle; 648 649 typedef typename SNC_structure::Vertex_const_handle Vertex_const_handle; 650 typedef typename SNC_structure::Halfedge_const_handle Halfedge_const_handle; 651 typedef typename SNC_structure::Halffacet_const_handle Halffacet_const_handle; 652 653 typedef typename SNC_structure::Point_3 Point_3; 654 typedef typename SNC_structure::Vector_3 Vector_3; 655 typedef typename SNC_structure::Segment_3 Segment_3; 656 typedef typename SNC_structure::Plane_3 Plane_3; 657 typedef typename SNC_structure::Mark Mark; 658 typedef typename SNC_structure::SHalfedge_around_facet_const_circulator 659 SHalfedge_around_facet_const_circulator; 660 661 private: double_point(const Point_3 & p)662 static OGL::Double_point double_point(const Point_3& p) 663 { return OGL::Double_point(CGAL::to_double(p.x()), 664 CGAL::to_double(p.y()), 665 CGAL::to_double(p.z())); } 666 double_segment(const Segment_3 & s)667 static OGL::Double_segment double_segment(const Segment_3& s) 668 { return OGL::Double_segment(double_point(s.source()), 669 double_point(s.target())); } 670 draw(Vertex_const_handle v,const Nef_polyhedron &,CGAL::OGL::Polyhedron & P)671 static void draw(Vertex_const_handle v, const Nef_polyhedron& , 672 CGAL::OGL::Polyhedron& P) { 673 Point_3 bp = v->point(); 674 // CGAL_NEF_TRACEN("vertex " << bp); 675 P.push_back(double_point(bp), v->mark()); 676 } 677 draw(Halfedge_const_handle e,const Nef_polyhedron &,CGAL::OGL::Polyhedron & P)678 static void draw(Halfedge_const_handle e, const Nef_polyhedron& , 679 CGAL::OGL::Polyhedron& P) { 680 Vertex_const_handle s = e->source(); 681 Vertex_const_handle t = e->twin()->source(); 682 Segment_3 seg(s->point(),t->point()); 683 // CGAL_NEF_TRACEN("edge " << seg); 684 P.push_back(double_segment(seg), e->mark()); 685 } 686 same_orientation(Plane_3 p1,Plane_3 p2)687 static bool same_orientation(Plane_3 p1, Plane_3 p2) { 688 if(p1.a() != 0) 689 return CGAL::sign(p1.a()) == CGAL::sign(p2.a()); 690 if(p1.b() != 0) 691 return CGAL::sign(p1.b()) == CGAL::sign(p2.b()); 692 return CGAL::sign(p1.c()) == CGAL::sign(p2.c()); 693 } 694 draw(Halffacet_const_handle f,const Nef_polyhedron &,CGAL::OGL::Polyhedron & P)695 static void draw(Halffacet_const_handle f, const Nef_polyhedron& , 696 CGAL::OGL::Polyhedron& P) { 697 698 if (f->incident_volume()->mark()) return; // Skip halffaces facing solid volume 699 OGL::DFacet g; 700 Halffacet_cycle_const_iterator fc; // all facet cycles: 701 CGAL_forall_facet_cycles_of(fc,f) 702 if ( fc.is_shalfedge() ) { // non-trivial facet cycle 703 g.new_facet_cycle(); 704 SHalfedge_const_handle h = fc; 705 SHalfedge_around_facet_const_circulator hc(h), he(hc); 706 CGAL_For_all(hc,he){ // all vertex coordinates in facet cycle 707 Point_3 sp = hc->source()->source()->point(); 708 // CGAL_NEF_TRACEN(" ");CGAL_NEF_TRACEN("facet" << sp); 709 g.push_back_vertex(double_point(sp)); 710 } 711 } 712 Vector_3 v = f->plane().orthogonal_vector(); 713 g.set_normal(CGAL::to_double(v.x()), 714 CGAL::to_double(v.y()), 715 CGAL::to_double(v.z()), 716 f->mark()); 717 P.push_back(g); 718 } 719 720 // Returns the bounding box of the finite vertices of the polyhedron. 721 // Returns $[-1,+1]^3$ as bounding box if no finite vertex exists. 722 bounded_bbox(const Nef_polyhedron & N)723 static Bbox_3 bounded_bbox(const Nef_polyhedron& N) { 724 bool first_vertex = true; 725 Bbox_3 bbox( -1.0, -1.0, -1.0, 1.0, 1.0, 1.0); 726 Vertex_const_iterator vi; 727 CGAL_forall_vertices(vi, N) { 728 Point_3 p = vi->point(); 729 double x = CGAL::to_double(p.hx()); 730 double y = CGAL::to_double(p.hy()); 731 double z = CGAL::to_double(p.hz()); 732 double w = CGAL::to_double(p.hw()); 733 if (N.is_standard(vi)) { 734 if(first_vertex) { 735 bbox = Bbox_3(x/w, y/w, z/w, x/w, y/w, z/w); 736 first_vertex = false; 737 } else { 738 bbox = bbox + Bbox_3(x/w, y/w, z/w, x/w, y/w, z/w); 739 first_vertex = false; 740 } 741 } 742 } 743 return bbox; 744 } 745 set_R(Bbox_3 & bbox,const Nef_polyhedron & N)746 static void set_R(Bbox_3& bbox, const Nef_polyhedron& N) { 747 if(N.is_standard_kernel()) return; 748 double size = abs(bbox.xmin()); 749 if(size < bbox.xmax()) size = bbox.xmax(); 750 if(size < bbox.ymin()) size = bbox.ymin(); 751 if(size < bbox.ymax()) size = bbox.ymax(); 752 if(size < bbox.zmin()) size = bbox.zmin(); 753 if(size < bbox.zmax()) size = bbox.zmax(); 754 N.set_size_of_infimaximal_box(size*50); 755 // CGAL_NEF_TRACEN("set infi box size to " << size); 756 Vertex_const_iterator vi; 757 CGAL_forall_vertices(vi, N) 758 if(N.is_standard(vi)) 759 return; 760 bbox = Bbox_3(bbox.xmin()*10,bbox.ymin()*10,bbox.zmin()*10, 761 bbox.xmax()*10,bbox.ymax()*10,bbox.zmax()*10); 762 } 763 public: convert_to_OGLPolyhedron(const Nef_polyhedron & N,CGAL::OGL::Polyhedron * P)764 static void convert_to_OGLPolyhedron(const Nef_polyhedron& N, CGAL::OGL::Polyhedron* P) { 765 Bbox_3 bbox(bounded_bbox(N)); 766 set_R(bbox,N); 767 P->bbox() = bbox; 768 Vertex_const_iterator v; 769 CGAL_forall_vertices(v,*N.sncp()) draw(v,N,*P); 770 Halfedge_const_iterator e; 771 CGAL_forall_edges(e,*N.sncp()) draw(e,N,*P); 772 Halffacet_const_iterator f; 773 CGAL_forall_halffacets(f,*N.sncp()) draw(f,N,*P); 774 } 775 776 }; // Nef3_Converter 777 778 } // namespace OGL 779 780 } //namespace CGAL 781