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