diff options
| -rw-r--r-- | doc/TODO.txt | 3 | ||||
| -rw-r--r-- | opencsg.pri | 4 | ||||
| -rw-r--r-- | openscad.pro | 8 | ||||
| -rw-r--r-- | patches/OpenCSG-1.3.0-FBO.patch | 80 | ||||
| -rw-r--r-- | patches/OpenCSG-1.3.0-MacOSX-port.patch | 4 | ||||
| -rwxr-xr-x | scripts/macosx-build-dependencies.sh | 11 | ||||
| -rw-r--r-- | src/CGAL_renderer.h | 762 | ||||
| -rw-r--r-- | src/GLView.h | 22 | ||||
| -rw-r--r-- | src/MainWindow.h | 9 | ||||
| -rw-r--r-- | src/OGL_helper.h | 704 | ||||
| -rw-r--r-- | src/cgalrenderer.cc | 126 | ||||
| -rw-r--r-- | src/cgalrenderer.h | 20 | ||||
| -rw-r--r-- | src/csgops.cc | 2 | ||||
| -rw-r--r-- | src/dxftess-cgal.cc | 2 | ||||
| -rw-r--r-- | src/glview.cc | 219 | ||||
| -rw-r--r-- | src/mainwin.cc | 356 | ||||
| -rw-r--r-- | src/opencsgrenderer.cc (renamed from src/render-opencsg.cc) | 58 | ||||
| -rw-r--r-- | src/opencsgrenderer.h | 24 | ||||
| -rw-r--r-- | src/polyset.cc | 2 | ||||
| -rw-r--r-- | src/polyset.h | 5 | ||||
| -rw-r--r-- | src/projection.cc | 2 | ||||
| -rw-r--r-- | src/render-opencsg.h | 8 | ||||
| -rw-r--r-- | src/renderer.h | 11 | ||||
| -rw-r--r-- | src/throwntogetherrenderer.cc | 120 | ||||
| -rw-r--r-- | src/throwntogetherrenderer.h | 21 | 
25 files changed, 1466 insertions, 1117 deletions
diff --git a/doc/TODO.txt b/doc/TODO.txt index b9440c6..49cacd7 100644 --- a/doc/TODO.txt +++ b/doc/TODO.txt @@ -52,7 +52,6 @@ o non-convex minkowski example from chrysn fails with an exception  USER INTERFACE  --------------  o Preferences -  - Remember settings done in menus between sessions (automatic reload, perspective, show*, hide*)    - Beautify color schemes    - Color schemes read from file    - Color scheme editor @@ -60,7 +59,6 @@ o Preferences    - pointsize    - OpenGL params    - Default language feature settings -  - Auto-view CSG/thrown together on load    - Make the library search path configurable?  o Export etc.: automatically add missing extension as in SaveAs  o MDI @@ -166,7 +164,6 @@ o Mesh optimization on STL export    - Remove super small triangles (all sides are short)    - Replace super thin triangles (one h is short)  o Misc -  - Add symbolic colors to the color() statement    - When specifying a transparency with the color() statement,      the object is not sorted and will be rendered wrongly    - Go through default values of parameters (e.g. cube() has x,y,z=1 while linear_extrude() has height=100) diff --git a/opencsg.pri b/opencsg.pri index 8538f99..02be596 100644 --- a/opencsg.pri +++ b/opencsg.pri @@ -3,8 +3,8 @@ opencsg {    CONFIG += glew    include(glew.pri) -  HEADERS += src/render-opencsg.h -  SOURCES += src/render-opencsg.cc +  HEADERS += src/opencsgrenderer.h +  SOURCES += src/opencsgrenderer.cc    isEmpty(DEPLOYDIR) {      # Optionally specify location of OpenCSG using the  diff --git a/openscad.pro b/openscad.pro index eecae9a..61000f1 100644 --- a/openscad.pro +++ b/openscad.pro @@ -118,7 +118,11 @@ include(boost.pri)  FORMS   += src/MainWindow.ui \             src/Preferences.ui -HEADERS += src/CGAL_renderer.h \ +HEADERS += src/renderer.h \ +           src/cgalrenderer.h \ +           src/throwntogetherrenderer.h \ +           src/CGAL_renderer.h \ +           src/OGL_helper.h \             src/GLView.h \             src/MainWindow.h \             src/Preferences.h \ @@ -146,6 +150,8 @@ HEADERS += src/CGAL_renderer.h \  SOURCES += src/openscad.cc \             src/mainwin.cc \ +           src/cgalrenderer.cc \ +           src/throwntogetherrenderer.cc \             src/glview.cc \             src/export.cc \             src/value.cc \ diff --git a/patches/OpenCSG-1.3.0-FBO.patch b/patches/OpenCSG-1.3.0-FBO.patch new file mode 100644 index 0000000..150a12e --- /dev/null +++ b/patches/OpenCSG-1.3.0-FBO.patch @@ -0,0 +1,80 @@ +diff -ru OpenCSG-1.3.0/src/frameBufferObject.cpp OpenCSG-1.3.0-fbofix/src/frameBufferObject.cpp +--- OpenCSG-1.3.0/src/frameBufferObject.cpp	2010-02-06 21:35:10.000000000 +0100 ++++ OpenCSG-1.3.0-fbofix/src/frameBufferObject.cpp	2011-08-02 01:33:31.000000000 +0200 +@@ -57,6 +57,7 @@ +             glGenRenderbuffers(1, &depthID);  +             glGenTextures(1, &textureID); +  ++            glGetIntegerv(GL_FRAMEBUFFER_BINDING, &oldFramebufferID); +             glBindFramebuffer(GL_FRAMEBUFFER, framebufferID); +             glBindTexture(GL_TEXTURE_2D, textureID); +             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_INT, 0); +@@ -76,7 +77,7 @@ +                 return false; +             } +  +-            glBindFramebuffer(GL_FRAMEBUFFER, 0); ++            glBindFramebuffer(GL_FRAMEBUFFER, oldFramebufferID); +             glBindTexture(GL_TEXTURE_2D, 0); +  +             textureTarget = GL_TEXTURE_2D; +@@ -133,7 +134,7 @@ +         // Unbinds frame buffer texture. +         bool FrameBufferObject::EndCapture() +         { +-            glBindFramebuffer(GL_FRAMEBUFFER, 0); ++            glBindFramebuffer(GL_FRAMEBUFFER, oldFramebufferID); +             return true; +         } +  +diff -ru OpenCSG-1.3.0/src/frameBufferObject.h OpenCSG-1.3.0-fbofix/src/frameBufferObject.h +--- OpenCSG-1.3.0/src/frameBufferObject.h	2011-08-02 17:30:01.000000000 +0200 ++++ OpenCSG-1.3.0-fbofix/src/frameBufferObject.h	2011-08-02 01:32:58.000000000 +0200 +@@ -83,6 +83,7 @@ +             unsigned int depthID; +  +             unsigned int framebufferID; ++            int oldFramebufferID; +  +             bool         initialized; +         }; +diff -ru OpenCSG-1.3.0/src/frameBufferObjectExt.cpp OpenCSG-1.3.0-fbofix/src/frameBufferObjectExt.cpp +--- OpenCSG-1.3.0/src/frameBufferObjectExt.cpp	2010-02-06 21:35:10.000000000 +0100 ++++ OpenCSG-1.3.0-fbofix/src/frameBufferObjectExt.cpp	2011-08-02 01:33:46.000000000 +0200 +@@ -58,6 +58,7 @@ +             glGenRenderbuffersEXT(1, &depthID);  +             glGenTextures(1, &textureID); +  ++            glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &oldFramebufferID); +             glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebufferID);	 +             glBindTexture(GL_TEXTURE_2D, textureID); +             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_INT, 0); +@@ -77,7 +78,7 @@ +                 return false; +             } +  +-            glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); ++            glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, oldFramebufferID); +             glBindTexture(GL_TEXTURE_2D, 0); +  +             textureTarget = GL_TEXTURE_2D; +@@ -134,7 +135,7 @@ +         // Unbinds frame buffer texture. +         bool FrameBufferObjectExt::EndCapture() +         { +-            glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); ++            glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, oldFramebufferID); +             return true; +         } +  +diff -ru OpenCSG-1.3.0/src/frameBufferObjectExt.h OpenCSG-1.3.0-fbofix/src/frameBufferObjectExt.h +--- OpenCSG-1.3.0/src/frameBufferObjectExt.h	2010-02-06 21:35:10.000000000 +0100 ++++ OpenCSG-1.3.0-fbofix/src/frameBufferObjectExt.h	2011-08-02 01:33:08.000000000 +0200 +@@ -83,6 +83,7 @@ +             unsigned int depthID; +  +             unsigned int framebufferID; ++            int oldFramebufferID; +  +             bool         initialized; +         }; diff --git a/patches/OpenCSG-1.3.0-MacOSX-port.patch b/patches/OpenCSG-1.3.0-MacOSX-port.patch index bb55165..e8eaa92 100644 --- a/patches/OpenCSG-1.3.0-MacOSX-port.patch +++ b/patches/OpenCSG-1.3.0-MacOSX-port.patch @@ -1102,7 +1102,7 @@ diff -ru OpenCSG-1.3.0/src/channelManager.cpp OpenCSG-1.3.0-mac/src/channelManag  diff -ru OpenCSG-1.3.0/src/frameBufferObject.h OpenCSG-1.3.0-mac/src/frameBufferObject.h  --- OpenCSG-1.3.0/src/frameBufferObject.h	2010-02-06 21:35:10.000000000 +0100  +++ OpenCSG-1.3.0-mac/src/frameBufferObject.h	2010-05-09 02:51:36.000000000 +0200 -@@ -79,10 +79,10 @@ +@@ -79,11 +79,11 @@               /// Texture stuff               GLenum       textureTarget; @@ -1112,7 +1112,9 @@ diff -ru OpenCSG-1.3.0/src/frameBufferObject.h OpenCSG-1.3.0-mac/src/frameBuffer  +            GLuint depthID;  -            unsigned int framebufferID; +-            int oldFramebufferID;  +            GLuint framebufferID; ++            GLint oldFramebufferID;               bool         initialized;           }; diff --git a/scripts/macosx-build-dependencies.sh b/scripts/macosx-build-dependencies.sh index e011582..6de5331 100755 --- a/scripts/macosx-build-dependencies.sh +++ b/scripts/macosx-build-dependencies.sh @@ -119,7 +119,9 @@ build_cgal()    version=$1    echo "Building CGAL" $version "..."    cd $BASEDIR/src -  curl -O https://gforge.inria.fr/frs/download.php/27641/CGAL-$version.tar.gz +  rm -rf CGAL* +  curl -O https://gforge.inria.fr/frs/download.php/28500/CGAL-$version.tar.gz +#  curl -O https://gforge.inria.fr/frs/download.php/27641/CGAL-$version.tar.gz    tar xzf CGAL-$version.tar.gz    cd CGAL-$version    # We build a static lib. Not really necessary, but it's well tested. @@ -159,7 +161,8 @@ echo "Using basedir:" $BASEDIR  mkdir -p $SRCDIR $DEPLOYDIR  build_gmp 5.0.1  build_mpfr 3.0.1 -build_boost 1.46.1 -build_cgal 3.7 -build_glew 1.5.8 +build_boost 1.47.0 +# NB! For CGAL, also update the actual download URL in the function +build_cgal 3.8 +build_glew 1.6.0  build_opencsg 1.3.0 diff --git a/src/CGAL_renderer.h b/src/CGAL_renderer.h index 0758339..acc902f 100644 --- a/src/CGAL_renderer.h +++ b/src/CGAL_renderer.h @@ -1,660 +1,104 @@ -// Copyright (c) 1997-2002  Max-Planck-Institute Saarbruecken (Germany). -// All rights reserved. -// -// This file is part of CGAL (www.cgal.org); you may redistribute it under -// the terms of the Q Public License version 1.0. -// See the file LICENSE.QPL distributed with CGAL. -// -// Licensees holding a valid commercial license may use this file in -// accordance with the commercial license agreement provided with the software. -// -// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -// -// $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Nef_3/include/CGAL/Nef_3/OGL_helper.h $ -// $Id: OGL_helper.h 44713 2008-08-01 15:38:58Z hachenb $ -//  -// -// Author(s)     : Peter Hachenberger <hachenberger@mpi-sb.mpg.de> - -#ifndef CGAL_NEF_OPENGL_HELPER_H -#define CGAL_NEF_OPENGL_HELPER_H - -#include <CGAL/Nef_S2/OGL_base_object.h> -#include <CGAL/Simple_cartesian.h> -#include <CGAL/Nef_3/SNC_decorator.h> -#include <qgl.h> -#include <cstdlib> - -#ifdef _WIN32 -#define CGAL_GLU_TESS_CALLBACK CALLBACK -#else -#define CGAL_GLU_TESS_CALLBACK  -#endif - -#ifdef __APPLE__ -#  include <AvailabilityMacros.h> -#endif - -#if defined __APPLE__ && !defined MAC_OS_X_VERSION_10_5 -#define CGAL_GLU_TESS_DOTS ... -#else -#define CGAL_GLU_TESS_DOTS -#endif - -using namespace CGAL; -using namespace CGAL::OGL; - -namespace OpenSCAD { - -	namespace OGL { - -// ---------------------------------------------------------------------------- -// Drawable double types: -// ---------------------------------------------------------------------------- - -		typedef CGAL::Simple_cartesian<double> DKernel;   -		typedef DKernel::Point_3               Double_point; -		typedef DKernel::Vector_3              Double_vector; -		typedef DKernel::Segment_3             Double_segment; -		typedef DKernel::Aff_transformation_3  Affine_3; - -		// DPoint = a double point including a mark -		class DPoint : public Double_point { -			bool m_; -		public: -			DPoint() {} -			DPoint(const Double_point& p, bool m) : Double_point(p) { m_ = m; } -			DPoint(const DPoint& p) : Double_point(p) { m_ = p.m_; } -			DPoint& operator=(const DPoint& p) -				{ Double_point::operator=(p); m_ = p.m_; return *this; } -			bool mark() const { return m_; } -		}; - -		// DSegment = a double segment including a mark -		class DSegment : public Double_segment { -			bool m_; -		public: -			DSegment() {} -			DSegment(const Double_segment& s, bool m) : Double_segment(s) { m_ = m; } -			DSegment(const DSegment& s) : Double_segment(s) { m_ = s.m_; } -			DSegment& operator=(const DSegment& s) -				{ Double_segment::operator=(s); m_ = s.m_; return *this; } -			bool mark() const { return m_; } -		}; - -		// Double_triple = a class that stores a triple of double -		// coordinates; we need a pointer to the coordinates in a C array -		// for OpenGL -		class Double_triple { -			typedef double*       double_ptr; -			typedef const double* const_double_ptr; -			double coords_[3]; -		public: -			Double_triple()  -				{ coords_[0]=coords_[1]=coords_[2]=0.0; } -			Double_triple(double x, double y, double z) -				{ coords_[0]=x; coords_[1]=y; coords_[2]=z; } -			Double_triple(const Double_triple& t) -				{ coords_[0]=t.coords_[0]; -					coords_[1]=t.coords_[1]; -					coords_[2]=t.coords_[2]; -				} -			Double_triple& operator=(const Double_triple& t) -				{ coords_[0]=t.coords_[0]; -					coords_[1]=t.coords_[1]; -					coords_[2]=t.coords_[2]; -					return *this; } -			operator double_ptr() const  -				{ return const_cast<Double_triple&>(*this).coords_; } -			double operator[](unsigned i)  -				{ CGAL_assertion(i<3); return coords_[i]; } -		}; // Double_triple - -		static std::ostream& operator << (std::ostream& os, -																			const Double_triple& t) -		{ os << "(" << t[0] << "," << t[1] << "," << t[2] << ")"; -			return os; } - - -		// DFacet stores the facet cycle vertices in a continuus C array -		// of three double components, this is necessary due to the OpenGL -		// tesselator input format ! -		class DFacet { -			typedef std::vector<Double_triple>   Coord_vector; -			typedef std::vector<unsigned>        Cycle_vector; -			Coord_vector    coords_;  // stores all vertex coordinates -			Cycle_vector    fc_ends_; // stores entry points of facet cycles -			Double_triple   normal_; // stores normal and mark of facet -			bool            mark_; - -		public: -			typedef Coord_vector::iterator Coord_iterator; -			typedef Coord_vector::const_iterator Coord_const_iterator; - -			DFacet() {} - -			void push_back_vertex(double x, double y, double z) -				{ coords_.push_back(Double_triple(x,y,z)); } - -			DFacet(const DFacet& f)  -				{ coords_  = f.coords_; -					fc_ends_ = f.fc_ends_; -					normal_  = f.normal_; -					mark_    = f.mark_; -				} - -			DFacet& operator=(const DFacet& f)  -				{ coords_ =  f.coords_; -					fc_ends_ = f.fc_ends_; -					normal_ =  f.normal_; -					mark_    = f.mark_; -					return *this;  -				} - -			~DFacet() -				{ coords_.clear(); fc_ends_.clear(); } - -			void push_back_vertex(const Double_point& p) -				{ push_back_vertex(p.x(),p.y(),p.z()); } -    -			void set_normal(double x, double y, double z, bool m) -				{ double l = sqrt(x*x + y*y + z*z); -					normal_ = Double_triple(x/l,y/l,z/l); mark_ = m; } - -			double dx() const { return normal_[0]; } -			double dy() const { return normal_[1]; } -			double dz() const { return normal_[2]; } -			bool mark() const { return mark_; } -			double* normal() const  -				{ return static_cast<double*>(normal_); } - -			void new_facet_cycle() -				{ fc_ends_.push_back(coords_.size()); } -     -			unsigned number_of_facet_cycles() const -				{ return fc_ends_.size(); } - -			Coord_iterator facet_cycle_begin(unsigned i)  -				{ CGAL_assertion(i<number_of_facet_cycles()); -					if (i==0) return coords_.begin(); -					else return coords_.begin()+fc_ends_[i]; } - -			Coord_iterator facet_cycle_end(unsigned i)  -				{ CGAL_assertion(i<number_of_facet_cycles()); -					if (i<fc_ends_.size()-1) return coords_.begin()+fc_ends_[i+1]; -					else return coords_.end(); } - -			Coord_const_iterator facet_cycle_begin(unsigned i) const -				{ CGAL_assertion(i<number_of_facet_cycles()); -					if (i==0) return coords_.begin(); -					else return coords_.begin()+fc_ends_[i]; } - -			Coord_const_iterator facet_cycle_end(unsigned i) const -				{ CGAL_assertion(i<number_of_facet_cycles()); -					if (i<fc_ends_.size()-1) return coords_.begin()+fc_ends_[i+1]; -					else return coords_.end(); } - -			void debug(std::ostream& os = std::cerr) const -				{ os << "DFacet, normal=" << normal_ << ", mark=" << mark() << std::endl; -					for(unsigned i=0; i<number_of_facet_cycles(); ++i) { -						os << "  facet cycle "; -						// put all vertices in facet cycle into contour: -						Coord_const_iterator cit; -						for(cit = facet_cycle_begin(i); cit != facet_cycle_end(i); ++cit) -							os << *cit; -						os << std::endl; -					} -				} -     -		}; // DFacet - - -// ---------------------------------------------------------------------------- -// OGL Drawable Polyhedron: -// ---------------------------------------------------------------------------- - -		inline void CGAL_GLU_TESS_CALLBACK beginCallback(GLenum which) -		{ glBegin(which); } - -		inline void CGAL_GLU_TESS_CALLBACK endCallback(void) -		{ glEnd(); } - -		inline void CGAL_GLU_TESS_CALLBACK errorCallback(GLenum errorCode) -		{ const GLubyte *estring; -			estring = gluErrorString(errorCode); -			fprintf(stderr, "Tessellation Error: %s\n", estring); -			std::exit (0); -		} - -		inline void CGAL_GLU_TESS_CALLBACK vertexCallback(GLvoid* vertex, -																											GLvoid* user) -		{ GLdouble* pc(static_cast<GLdouble*>(vertex)); -			GLdouble* pu(static_cast<GLdouble*>(user)); -			//    CGAL_NEF_TRACEN("vertexCallback coord  "<<pc[0]<<","<<pc[1]<<","<<pc[2]); -			//    CGAL_NEF_TRACEN("vertexCallback normal "<<pu[0]<<","<<pu[1]<<","<<pu[2]); -			glNormal3dv(pu); -			glVertex3dv(pc);  +/* + *  OpenSCAD (www.openscad.org) + *  Copyright (C) 2009-2011 Clifford Wolf <clifford@clifford.at> and + *                          Marius Kintel <marius@kintel.net> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 2 of the License, or + *  (at your option) any later version. + * + *  As a special exception, you have permission to link this program + *  with the CGAL library and distribute executables, as long as you + *  follow the requirements of the GNU GPL in regard to all of the + *  software in the executable aside from CGAL. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + * + */ + +#ifndef CGAL_RENDERER_H +#define CGAL_RENDERER_H + +#include "OGL_helper.h" +#undef CGAL_NEF3_MARKED_VERTEX_COLOR +#undef CGAL_NEF3_MARKED_EDGE_COLOR +#undef CGAL_NEF3_MARKED_FACET_COLOR + +#undef CGAL_NEF3_UNMARKED_VERTEX_COLOR +#undef CGAL_NEF3_UNMARKED_EDGE_COLOR +#undef CGAL_NEF3_UNMARKED_FACET_COLOR + +using CGAL::OGL::SNC_BOUNDARY; +using CGAL::OGL::SNC_SKELETON; + +class Polyhedron : public CGAL::OGL::Polyhedron +{ +public: + +	enum RenderColor { +		CGAL_NEF3_MARKED_VERTEX_COLOR, +		CGAL_NEF3_MARKED_EDGE_COLOR, +		CGAL_NEF3_MARKED_FACET_COLOR, +		CGAL_NEF3_UNMARKED_VERTEX_COLOR, +		CGAL_NEF3_UNMARKED_EDGE_COLOR, +		CGAL_NEF3_UNMARKED_FACET_COLOR, +		NUM_COLORS +	}; + +	Polyhedron() { +		setColor(CGAL_NEF3_MARKED_VERTEX_COLOR,0xb7,0xe8,0x5c); +		setColor(CGAL_NEF3_MARKED_EDGE_COLOR,0xab,0xd8,0x56); +		setColor(CGAL_NEF3_MARKED_FACET_COLOR,0x9d,0xcb,0x51); +		setColor(CGAL_NEF3_UNMARKED_VERTEX_COLOR,0xff,0xf6,0x7c); +		setColor(CGAL_NEF3_UNMARKED_EDGE_COLOR,0xff,0xec,0x5e); +		setColor(CGAL_NEF3_UNMARKED_FACET_COLOR,0xf9,0xd7,0x2c); +	} + +	void draw(bool showedges) const { +		if(this->style == SNC_BOUNDARY) { +			glCallList(this->object_list_+2); +			if(showedges) { +				glDisable(GL_LIGHTING); +				glCallList(this->object_list_+1); +				glCallList(this->object_list_); +			} +		} else { +			glDisable(GL_LIGHTING); +			glCallList(this->object_list_+1); +			glCallList(this->object_list_);  		} - -		inline void CGAL_GLU_TESS_CALLBACK combineCallback(GLdouble coords[3], GLvoid *[4], GLfloat [4], GLvoid **dataOut) -		{ -			static std::list<GLdouble*> pcache; -			if (dataOut) { -				GLdouble *n = new GLdouble[3]; -				n[0] = coords[0]; -				n[1] = coords[1]; -				n[2] = coords[2]; -				pcache.push_back(n); -				*dataOut = n; -			} else { -				for (std::list<GLdouble*>::const_iterator i = pcache.begin(); i != pcache.end(); i++) -					delete[] *i; -				pcache.clear(); -			} -		} - - -		enum { SNC_AXES}; -		enum { SNC_BOUNDARY, SNC_SKELETON }; - -		class Polyhedron : public CGAL::OGL::OGL_base_object { -		public: -			std::list<DPoint>    vertices_; -			std::list<DSegment>  edges_; -			std::list<DFacet>    halffacets_; - -			GLuint         object_list_; -			bool init_; - -			Bbox_3  bbox_; - -			int style; -			std::vector<bool> switches; - -			typedef std::list<DPoint>::const_iterator   Vertex_iterator; -			typedef std::list<DSegment>::const_iterator Edge_iterator; -			typedef std::list<DFacet>::const_iterator   Halffacet_iterator; - -			enum RenderColor { -				CGAL_NEF3_MARKED_VERTEX_COLOR, -				CGAL_NEF3_MARKED_EDGE_COLOR, -				CGAL_NEF3_MARKED_FACET_COLOR, -				CGAL_NEF3_UNMARKED_VERTEX_COLOR, -				CGAL_NEF3_UNMARKED_EDGE_COLOR, -				CGAL_NEF3_UNMARKED_FACET_COLOR, -				NUM_COLORS -			}; -			static unsigned char colors[NUM_COLORS][3]; -		public: -			Polyhedron() : bbox_(-1,-1,-1,1,1,1), switches(1) {  -				object_list_ = 0; -				init_ = false; -				style = SNC_BOUNDARY; -				switches[SNC_AXES] = false;  -			} - -			~Polyhedron()  -				{ if (object_list_) glDeleteLists(object_list_, 4); } - -			void push_back(const Double_point& p, bool m) { -        vertices_.push_back(DPoint(p,m)); -			} -			void push_back(const Double_segment& s, bool m)  -				{ edges_.push_back(DSegment(s,m)); } -			void push_back(const DFacet& f)  -				{ halffacets_.push_back(f); } -  -			void toggle(int index) {  -				switches[index] = !switches[index];  -			} -     -			void set_style(int index) { -				style = index; -			} - -			bool is_initialized() const { return init_; } - -			Bbox_3  bbox() const { return bbox_; } -			Bbox_3& bbox()       { return bbox_; } - -			void draw(Vertex_iterator v) const {  -				//      CGAL_NEF_TRACEN("drawing vertex "<<*v); -				unsigned char *c = v->mark() ? colors[CGAL_NEF3_UNMARKED_VERTEX_COLOR] : colors[CGAL_NEF3_MARKED_VERTEX_COLOR]; -				glPointSize(10); -				glColor3ubv(c); -				glBegin(GL_POINTS); -				glVertex3d(v->x(),v->y(),v->z()); -#ifdef CGAL_NEF_EMPHASIZE_VERTEX -				glColor3ub(255,0,0); -				glVertex3d(CGAL_NEF_EMPHASIZE_VERTEX); -#endif -				glEnd(); -			} - -			void draw(Edge_iterator e) const {  -				//      CGAL_NEF_TRACEN("drawing edge "<<*e); -				Double_point p = e->source(), q = e->target(); -				unsigned char *c = e->mark() ? colors[CGAL_NEF3_UNMARKED_EDGE_COLOR] : colors[CGAL_NEF3_MARKED_EDGE_COLOR]; -				glLineWidth(5); -				glColor3ubv(c); -				glBegin(GL_LINE_STRIP); -				glVertex3d(p.x(), p.y(), p.z()); -				glVertex3d(q.x(), q.y(), q.z()); -				glEnd(); -			} - -			void draw(Halffacet_iterator f) const {  -				//      CGAL_NEF_TRACEN("drawing facet "<<(f->debug(),"")); -				GLUtesselator* tess_ = gluNewTess(); -				gluTessCallback(tess_, GLenum(GLU_TESS_VERTEX_DATA), -												(GLvoid (CGAL_GLU_TESS_CALLBACK *)(CGAL_GLU_TESS_DOTS)) &vertexCallback); -				gluTessCallback(tess_, GLenum(GLU_TESS_COMBINE), -												(GLvoid (CGAL_GLU_TESS_CALLBACK *)(CGAL_GLU_TESS_DOTS)) &combineCallback); -				gluTessCallback(tess_, GLenum(GLU_TESS_BEGIN), -												(GLvoid (CGAL_GLU_TESS_CALLBACK *)(CGAL_GLU_TESS_DOTS)) &beginCallback); -				gluTessCallback(tess_, GLenum(GLU_TESS_END), -												(GLvoid (CGAL_GLU_TESS_CALLBACK *)(CGAL_GLU_TESS_DOTS)) &endCallback); -				gluTessCallback(tess_, GLenum(GLU_TESS_ERROR), -												(GLvoid (CGAL_GLU_TESS_CALLBACK *)(CGAL_GLU_TESS_DOTS)) &errorCallback); -				gluTessProperty(tess_, GLenum(GLU_TESS_WINDING_RULE), -												GLU_TESS_WINDING_POSITIVE); - -				DFacet::Coord_const_iterator cit; -				unsigned char *c = f->mark() ? colors[CGAL_NEF3_UNMARKED_FACET_COLOR] : colors[CGAL_NEF3_MARKED_FACET_COLOR]; -				glColor3ubv(c); -				gluTessBeginPolygon(tess_,f->normal()); -				//      CGAL_NEF_TRACEN(" "); -				//      CGAL_NEF_TRACEN("Begin Polygon"); -				gluTessNormal(tess_,f->dx(),f->dy(),f->dz()); -				// forall facet cycles of f: -				for(unsigned i = 0; i < f->number_of_facet_cycles(); ++i) { -					gluTessBeginContour(tess_); -					//	CGAL_NEF_TRACEN("  Begin Contour"); -					// put all vertices in facet cycle into contour: -					for(cit = f->facet_cycle_begin(i);  -							cit != f->facet_cycle_end(i); ++cit) { -						gluTessVertex(tess_, *cit, *cit); -						//	  CGAL_NEF_TRACEN("    add Vertex"); -					} -					gluTessEndContour(tess_); -					//	CGAL_NEF_TRACEN("  End Contour"); -				} -				gluTessEndPolygon(tess_); -				//      CGAL_NEF_TRACEN("End Polygon"); -				gluDeleteTess(tess_); -				combineCallback(NULL, NULL, NULL, NULL); -			} - -			void construct_axes() const -				{  -					glLineWidth(2.0); -					// red x-axis -					glColor3f(1.0,0.0,0.0); -					glBegin(GL_LINES); -					glVertex3f(0.0,0.0,0.0); -					glVertex3f(5000.0,0.0,0.0); -					glEnd(); -					// green y-axis  -					glColor3f(0.0,1.0,0.0); -					glBegin(GL_LINES); -					glVertex3f(0.0,0.0,0.0); -					glVertex3f(0.0,5000.0,0.0); -					glEnd(); -					// blue z-axis and equator -					glColor3f(0.0,0.0,1.0); -					glBegin(GL_LINES); -					glVertex3f(0.0,0.0,0.0); -					glVertex3f(0.0,0.0,5000.0); -					glEnd(); -					// six coordinate points in pink: -					glPointSize(10); -					glBegin(GL_POINTS); -					glColor3f(1.0,0.0,0.0); -					glVertex3d(5,0,0); -					glColor3f(0.0,1.0,0.0); -					glVertex3d(0,5,0); -					glColor3f(0.0,0.0,1.0); -					glVertex3d(0,0,5); -					glEnd(); -				} - - -			void fill_display_lists() { -				glNewList(object_list_, GL_COMPILE); -				Vertex_iterator v; -				for(v=vertices_.begin();v!=vertices_.end();++v)  -					draw(v); -				glEndList();      - -				glNewList(object_list_+1, GL_COMPILE); -				Edge_iterator e; -				for(e=edges_.begin();e!=edges_.end();++e) -					draw(e); -				glEndList();      - -				glNewList(object_list_+2, GL_COMPILE); -				Halffacet_iterator f; -				for(f=halffacets_.begin();f!=halffacets_.end();++f) -					draw(f); -				glEndList(); - -				glNewList(object_list_+3, GL_COMPILE); // axes: -				construct_axes(); -				glEndList(); - -			} - -			void init() {  -				if (init_) return; -				init_ = true; -				switches[SNC_AXES] = false; -				style = SNC_BOUNDARY; -				object_list_ = glGenLists(4);  -				CGAL_assertion(object_list_);  -				fill_display_lists(); -			} - - -			void draw() const -				{  -					if (!is_initialized()) const_cast<Polyhedron&>(*this).init(); -					double l = (std::max)( (std::max)( bbox().xmax() - bbox().xmin(), -																						 bbox().ymax() - bbox().ymin()), -																 bbox().zmax() - bbox().zmin()); -					if ( l < 1) // make sure that a single point doesn't screw up here -						l = 1; -					glScaled( 4.0/l, 4.0/l, 4.0/l); -					glTranslated( -(bbox().xmax() + bbox().xmin()) / 2.0, -												-(bbox().ymax() + bbox().ymin()) / 2.0, -												-(bbox().zmax() + bbox().zmin()) / 2.0); -					if (style == SNC_BOUNDARY) { -						//glEnable(GL_LIGHTING);  -						glCallList(object_list_+2); // facets -						//glDisable(GL_LIGHTING); -					} -					// move edges and vertices a bit towards the view-point,  -					// i.e., 1/100th of the unit vector in camera space -					//      double f = l / 4.0 / 100.0; -					//      glTranslated( z_vec[0] * f, z_vec[1] * f, z_vec[2] * f); -					glCallList(object_list_+1); // edges -					glCallList(object_list_);   // vertices -					if (switches[SNC_AXES]) glCallList(object_list_+3); // axis -				} - -			void debug(std::ostream& os = std::cerr) const -				{ -					os << "OGL::Polyhedron" << std::endl; -					os << "Vertices:" << std::endl; -					Vertex_iterator v; -					for(v=vertices_.begin();v!=vertices_.end();++v)  -						os << "  "<<*v<<", mark="<<v->mark()<<std::endl; -					os << "Edges:" << std::endl; -					Edge_iterator e; -					for(e=edges_.begin();e!=edges_.end();++e) -						os << "  "<<*e<<", mark="<<e->mark()<<std::endl; -					os << "Facets:" << std::endl; -					Halffacet_iterator f; -					for(f=halffacets_.begin();f!=halffacets_.end();++f) -						f->debug(); os << std::endl; -					os << std::endl; -				} - -		}; // Polyhedron -		unsigned char Polyhedron::colors[][3] = { -			{0xb7, 0xe8, 0x5c}, -			{0xab, 0xd8, 0x56}, -			{0x9d, 0xcb, 0x51}, -			{0xff, 0xf6, 0x7c}, -			{0xff, 0xec, 0x5e}, -			{0xf9, 0xd7, 0x2c} -		}; - -		template<typename Nef_polyhedron> -		class Nef3_Converter {  -			typedef typename Nef_polyhedron::SNC_structure           SNC_structure; -			typedef CGAL::SNC_decorator<SNC_structure>               Base; -			typedef CGAL::SNC_FM_decorator<SNC_structure>            FM_decorator; -     -    public: -			typedef typename SNC_structure::Vertex_const_iterator Vertex_const_iterator;  -			typedef typename SNC_structure::Halfedge_const_iterator Halfedge_const_iterator;  -			typedef typename SNC_structure::Halffacet_const_iterator Halffacet_const_iterator;  -			typedef typename SNC_structure::Halffacet_cycle_const_iterator Halffacet_cycle_const_iterator; -     -			typedef typename SNC_structure::Object_const_handle Object_const_handle; -			typedef typename SNC_structure::SHalfedge_const_handle SHalfedge_const_handle;  -			typedef typename SNC_structure::SHalfloop_const_handle SHalfloop_const_handle;  -     -			typedef typename SNC_structure::Vertex_const_handle Vertex_const_handle;  -			typedef typename SNC_structure::Halfedge_const_handle Halfedge_const_handle;  -			typedef typename SNC_structure::Halffacet_const_handle Halffacet_const_handle; -     -			typedef typename SNC_structure::Point_3 Point_3; -			typedef typename SNC_structure::Vector_3 Vector_3; -			typedef typename SNC_structure::Segment_3 Segment_3; -			typedef typename SNC_structure::Plane_3 Plane_3; -			typedef typename SNC_structure::Mark Mark; -			typedef typename SNC_structure::SHalfedge_around_facet_const_circulator  -      SHalfedge_around_facet_const_circulator; -     -		private: -			static OGL::Double_point double_point(const Point_3& p) -				{ return OGL::Double_point(CGAL::to_double(p.x()), -																	 CGAL::to_double(p.y()), -																	 CGAL::to_double(p.z())); } -     -			static OGL::Double_segment double_segment(const Segment_3& s) -				{ return OGL::Double_segment(double_point(s.source()), -																		 double_point(s.target())); } -     -			static void draw(Vertex_const_handle v, const Nef_polyhedron& ,  -											 Polyhedron& P) {  -				Point_3 bp = v->point(); -				//    CGAL_NEF_TRACEN("vertex " << bp); -				P.push_back(double_point(bp), v->mark());  -			} -     -			static void draw(Halfedge_const_handle e, const Nef_polyhedron& , -											 Polyhedron& P) {  -				Vertex_const_handle s = e->source(); -				Vertex_const_handle t = e->twin()->source(); -				Segment_3 seg(s->point(),t->point()); -				//    CGAL_NEF_TRACEN("edge " << seg); -				P.push_back(double_segment(seg), e->mark());  -			} -     -			static void draw(Halffacet_const_handle f, const Nef_polyhedron& , -											 Polyhedron& P) {  -				OGL::DFacet g; -				Halffacet_cycle_const_iterator fc; // all facet cycles: -				CGAL_forall_facet_cycles_of(fc,f) -					if ( fc.is_shalfedge() ) { // non-trivial facet cycle -						g.new_facet_cycle(); -						SHalfedge_const_handle h = fc; -						SHalfedge_around_facet_const_circulator hc(h), he(hc); -						CGAL_For_all(hc,he){ // all vertex coordinates in facet cycle -							Point_3 sp = hc->source()->source()->point(); -							//	      CGAL_NEF_TRACEN(" ");CGAL_NEF_TRACEN("facet" << sp); -							g.push_back_vertex(double_point(sp)); -						} -					} -				Vector_3 v = f->plane().orthogonal_vector(); -				g.set_normal(CGAL::to_double(v.x()),  -										 CGAL::to_double(v.y()),  -										 CGAL::to_double(v.z()),  -										 f->mark()); -				P.push_back(g); -			} -     -			// Returns the bounding box of the finite vertices of the polyhedron. -			// Returns $[-1,+1]^3$ as bounding box if no finite vertex exists. -     -			static Bbox_3  bounded_bbox(const Nef_polyhedron& N) { -				bool first_vertex = true; -				Bbox_3 bbox( -1.0, -1.0, -1.0, 1.0, 1.0, 1.0); -				Vertex_const_iterator vi; -				CGAL_forall_vertices(vi, N) { -					Point_3 p = vi->point(); -					double x = CGAL::to_double(p.hx()); -					double y = CGAL::to_double(p.hy()); -					double z = CGAL::to_double(p.hz()); -					double w = CGAL::to_double(p.hw()); -					if (N.is_standard(vi)) { -						if(first_vertex) { -							bbox = Bbox_3(x/w, y/w, z/w, x/w, y/w, z/w); -							first_vertex = false; -						} else { -							bbox = bbox + Bbox_3(x/w, y/w, z/w, x/w, y/w, z/w); -							first_vertex = false; -						} -					} -				} -				return bbox; -			}   -     -			static void set_R(Bbox_3& bbox, const Nef_polyhedron& N) { -				if(N.is_standard_kernel()) return; -				double size = abs(bbox.xmin()); -				if(size < bbox.xmax()) size = bbox.xmax(); -				if(size < bbox.ymin()) size = bbox.ymin(); -				if(size < bbox.ymax()) size = bbox.ymax(); -				if(size < bbox.zmin()) size = bbox.zmin(); -				if(size < bbox.zmax()) size = bbox.zmax(); -				N.set_size_of_infimaximal_box(size*50); -				//    CGAL_NEF_TRACEN("set infi box size to " << size); -				Vertex_const_iterator vi; -				CGAL_forall_vertices(vi, N) -					if(N.is_standard(vi)) -						return; -				bbox = Bbox_3(bbox.xmin()*10,bbox.ymin()*10,bbox.zmin()*10, -											bbox.xmax()*10,bbox.ymax()*10,bbox.zmax()*10); -			} -		public: -			static void setColor(Polyhedron::RenderColor color_index,  -													 unsigned char r, unsigned char g, unsigned char b) { -				assert(color_index < Polyhedron::NUM_COLORS); -				Polyhedron::colors[color_index][0] = r; -				Polyhedron::colors[color_index][1] = g; -				Polyhedron::colors[color_index][2] = b; -			} - -			static void convert_to_OGLPolyhedron(const Nef_polyhedron& N, Polyhedron* P) {  -				Bbox_3 bbox(bounded_bbox(N)); -				set_R(bbox,N); -				P->bbox() = bbox;     -				Vertex_const_iterator v; -				CGAL_forall_vertices(v,*N.sncp()) draw(v,N,*P); -				Halfedge_const_iterator e; -				CGAL_forall_edges(e,*N.sncp()) draw(e,N,*P); -				Halffacet_const_iterator f; -				CGAL_forall_facets(f,*N.sncp()) draw(f,N,*P); -			} -     -		}; // Nef3_Converter - -	} // namespace OGL - -} // namespace OpenSCAD - -#endif // CGAL_NEF_OPENGL_HELPER_H +	} +	CGAL::Color getVertexColor(Vertex_iterator v) const { +		CGAL::Color c = v->mark() ? colors[CGAL_NEF3_UNMARKED_VERTEX_COLOR] : colors[CGAL_NEF3_MARKED_VERTEX_COLOR]; +		return c; +	} + +	CGAL::Color getEdgeColor(Edge_iterator e) const { +		CGAL::Color c = e->mark() ? colors[CGAL_NEF3_UNMARKED_EDGE_COLOR] : colors[CGAL_NEF3_MARKED_EDGE_COLOR]; +		return c; +	} + +	CGAL::Color getFacetColor(Halffacet_iterator f) const { +		CGAL::Color c = f->mark() ? colors[CGAL_NEF3_UNMARKED_FACET_COLOR] : colors[CGAL_NEF3_MARKED_FACET_COLOR]; +		return c; +	} + +	void setColor(Polyhedron::RenderColor color_index, +				  unsigned char r, unsigned char g, unsigned char b) { +		assert(color_index < Polyhedron::NUM_COLORS); +		this->colors[color_index] = CGAL::Color(r,g,b); +	} +private: +	CGAL::Color colors[NUM_COLORS]; + +}; // Polyhedron + +#endif // CGAL_RENDERER_H diff --git a/src/GLView.h b/src/GLView.h index 7516894..764b23b 100644 --- a/src/GLView.h +++ b/src/GLView.h @@ -12,24 +12,31 @@  class GLView : public QGLWidget  {  	Q_OBJECT +	Q_PROPERTY(bool showFaces READ showFaces WRITE setShowFaces); +	Q_PROPERTY(bool showEdges READ showEdges WRITE setShowEdges);  	Q_PROPERTY(bool showAxes READ showAxes WRITE setShowAxes);  	Q_PROPERTY(bool showCrosshairs READ showCrosshairs WRITE setShowCrosshairs);  	Q_PROPERTY(bool orthoMode READ orthoMode WRITE setOrthoMode);  public:  	GLView(QWidget *parent = NULL); -	void setRenderFunc(void (*func)(void*), void *userdata); +	void setRenderer(class Renderer* r);  #ifdef ENABLE_OPENCSG  	bool hasOpenCSGSupport() { return this->opencsg_support; }  #endif  	// Properties +	bool showFaces() const { return this->showfaces; } +	void setShowFaces(bool enabled) { this->showfaces = enabled; } +	bool showEdges() const { return this->showedges; } +	void setShowEdges(bool enabled) { this->showedges = enabled; }  	bool showAxes() const { return this->showaxes; }  	void setShowAxes(bool enabled) { this->showaxes = enabled; }  	bool showCrosshairs() const { return this->showcrosshairs; }  	void setShowCrosshairs(bool enabled) { this->showcrosshairs = enabled; }  	bool orthoMode() const { return this->orthomode; }  	void setOrthoMode(bool enabled) { this->orthomode = enabled; } - +	 +public:  	QLabel *statusLabel;  	double object_rot_x;  	double object_rot_y; @@ -45,9 +52,10 @@ public:  #endif  private: -	void (*renderfunc)(void*); -	void *renderfunc_vp; +	Renderer *renderer; +	bool showfaces; +	bool showedges;  	bool showaxes;  	bool showcrosshairs;  	bool orthomode; @@ -57,8 +65,7 @@ private:  	double w_h_ratio;  	bool mouse_drag_active; -	int last_mouse_x; -	int last_mouse_y; +	QPoint last_mouse;  	void keyPressEvent(QKeyEvent *event);  	void wheelEvent(QWheelEvent *event); @@ -68,7 +75,10 @@ private:  	void initializeGL();  	void resizeGL(int w, int h); +	void setupPerspective(); +	void setupOrtho(double distance,bool offset=false);  	void paintGL(); +	void normalizeAngle(GLdouble& angle);  #ifdef ENABLE_OPENCSG  private slots: diff --git a/src/MainWindow.h b/src/MainWindow.h index 43ab273..243a5ad 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -38,17 +38,18 @@ public:  	class CSGChain *root_chain;  #ifdef ENABLE_CGAL  	class CGAL_Nef_polyhedron *root_N; -	bool recreate_cgal_ogl_p; -	void *cgal_ogl_p; -	PolySet *cgal_ogl_ps; +	class CGALRenderer *cgalRenderer;  #endif +#ifdef ENABLE_OPENCSG +	class OpenCSGRenderer *opencsgRenderer; +#endif +	class ThrownTogetherRenderer *thrownTogetherRenderer;  	QVector<CSGTerm*> highlight_terms;  	CSGChain *highlights_chain;  	QVector<CSGTerm*> background_terms;  	CSGChain *background_chain;  	QString last_compiled_doc; -	bool enableOpenCSG;  	static const int maxRecentFiles = 10;  	QAction *actionRecentFile[maxRecentFiles]; diff --git a/src/OGL_helper.h b/src/OGL_helper.h new file mode 100644 index 0000000..2764561 --- /dev/null +++ b/src/OGL_helper.h @@ -0,0 +1,704 @@ +// Copyright (c) 1997-2002  Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you may redistribute it under +// the terms of the Q Public License version 1.0. +// See the file LICENSE.QPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.7-branch/Nef_3/include/CGAL/Nef_3/OGL_helper.h $ +// $Id: OGL_helper.h 56667 2010-06-09 07:37:13Z sloriot $ +//  +// +// Author(s)     : Peter Hachenberger <hachenberger@mpi-sb.mpg.de> + +#ifndef CGAL_NEF_OPENGL_HELPER_H +#define CGAL_NEF_OPENGL_HELPER_H + +#include <CGAL/Nef_S2/OGL_base_object.h> +#include <CGAL/Simple_cartesian.h> +#include <CGAL/Nef_3/SNC_decorator.h> +#include <qgl.h> +#include <cstdlib> + +#define CGAL_NEF3_MARKED_VERTEX_COLOR 183,232,92 +#define CGAL_NEF3_MARKED_EDGE_COLOR 171,216,86 +#define CGAL_NEF3_MARKED_FACET_COLOR  157,203,81 + +#define CGAL_NEF3_UNMARKED_VERTEX_COLOR 255,246,124 +#define CGAL_NEF3_UNMARKED_EDGE_COLOR 255,236,94 +#define CGAL_NEF3_UNMARKED_FACET_COLOR 249,215,44 + +#ifdef _WIN32 +#define CGAL_GLU_TESS_CALLBACK CALLBACK +#else +#define CGAL_GLU_TESS_CALLBACK  +#endif + +#ifdef __APPLE__ +#  include <AvailabilityMacros.h> +#endif + +#if defined __APPLE__ && !defined MAC_OS_X_VERSION_10_5 +    #define CGAL_GLU_TESS_DOTS ... +#else +    #define CGAL_GLU_TESS_DOTS +#endif + + +namespace CGAL { + +namespace OGL { + +// ---------------------------------------------------------------------------- +// Drawable double types: +// ---------------------------------------------------------------------------- + +  typedef CGAL::Simple_cartesian<double> DKernel;   +  typedef DKernel::Point_3               Double_point; +  typedef DKernel::Vector_3              Double_vector; +  typedef DKernel::Segment_3             Double_segment; +  typedef DKernel::Aff_transformation_3  Affine_3; + +  // DPoint = a double point including a mark +  class DPoint : public Double_point { +    bool m_; +  public: +    DPoint() {} +    DPoint(const Double_point& p, bool m) : Double_point(p) { m_ = m; } +    DPoint(const DPoint& p) : Double_point(p) { m_ = p.m_; } +    DPoint& operator=(const DPoint& p) +    { Double_point::operator=(p); m_ = p.m_; return *this; } +    bool mark() const { return m_; } +  }; + +  // DSegment = a double segment including a mark +  class DSegment : public Double_segment { +    bool m_; +  public: +    DSegment() {} +    DSegment(const Double_segment& s, bool m) : Double_segment(s) { m_ = m; } +    DSegment(const DSegment& s) : Double_segment(s) { m_ = s.m_; } +    DSegment& operator=(const DSegment& s) +    { Double_segment::operator=(s); m_ = s.m_; return *this; } +    bool mark() const { return m_; } +  }; + +  // Double_triple = a class that stores a triple of double +  // coordinates; we need a pointer to the coordinates in a C array +  // for OpenGL +  class Double_triple { +    typedef double*       double_ptr; +    typedef const double* const_double_ptr; +    double coords_[3]; +  public: +    Double_triple()  +    { coords_[0]=coords_[1]=coords_[2]=0.0; } +    Double_triple(double x, double y, double z) +    { coords_[0]=x; coords_[1]=y; coords_[2]=z; } +    Double_triple(const Double_triple& t) +    { coords_[0]=t.coords_[0]; +      coords_[1]=t.coords_[1]; +      coords_[2]=t.coords_[2]; +    } +    Double_triple& operator=(const Double_triple& t) +    { coords_[0]=t.coords_[0]; +      coords_[1]=t.coords_[1]; +      coords_[2]=t.coords_[2]; +      return *this; } +    operator double_ptr() const  +    { return const_cast<Double_triple&>(*this).coords_; } +    double operator[](unsigned i)  +    { CGAL_assertion(i<3); return coords_[i]; } +  }; // Double_triple + +  static std::ostream& operator << (std::ostream& os, +				    const Double_triple& t) +  { os << "(" << t[0] << "," << t[1] << "," << t[2] << ")"; +    return os; } + + +  // DFacet stores the facet cycle vertices in a continuus C array +  // of three double components, this is necessary due to the OpenGL +  // tesselator input format ! +  class DFacet { +    typedef std::vector<Double_triple>   Coord_vector; +    typedef std::vector<unsigned>        Cycle_vector; +    Coord_vector    coords_;  // stores all vertex coordinates +    Cycle_vector    fc_ends_; // stores entry points of facet cycles +    Double_triple   normal_; // stores normal and mark of facet +    bool            mark_; + +  public: +    typedef Coord_vector::iterator Coord_iterator; +    typedef Coord_vector::const_iterator Coord_const_iterator; + +    DFacet() {} + +    void push_back_vertex(double x, double y, double z) +    { coords_.push_back(Double_triple(x,y,z)); } + +    DFacet(const DFacet& f)  +    { coords_  = f.coords_; +      fc_ends_ = f.fc_ends_; +      normal_  = f.normal_; +      mark_    = f.mark_; +    } + +    DFacet& operator=(const DFacet& f)  +    { coords_ =  f.coords_; +      fc_ends_ = f.fc_ends_; +      normal_ =  f.normal_; +      mark_    = f.mark_; +      return *this;  +    } + +    ~DFacet() +    { coords_.clear(); fc_ends_.clear(); } + +    void push_back_vertex(const Double_point& p) +    { push_back_vertex(p.x(),p.y(),p.z()); } +    +    void set_normal(double x, double y, double z, bool m) +    { double l = sqrt(x*x + y*y + z*z); +      normal_ = Double_triple(x/l,y/l,z/l); mark_ = m; } + +    double dx() const { return normal_[0]; } +    double dy() const { return normal_[1]; } +    double dz() const { return normal_[2]; } +    bool mark() const { return mark_; } +    double* normal() const  +    { return static_cast<double*>(normal_); } + +    void new_facet_cycle() +    { fc_ends_.push_back(coords_.size()); } +     +    unsigned number_of_facet_cycles() const +    { return fc_ends_.size(); } + +    Coord_iterator facet_cycle_begin(unsigned i)  +    { CGAL_assertion(i<number_of_facet_cycles()); +      if (i==0) return coords_.begin(); +      else return coords_.begin()+fc_ends_[i]; } + +    Coord_iterator facet_cycle_end(unsigned i)  +    { CGAL_assertion(i<number_of_facet_cycles()); +      if (i<fc_ends_.size()-1) return coords_.begin()+fc_ends_[i+1]; +      else return coords_.end(); } + +    Coord_const_iterator facet_cycle_begin(unsigned i) const +    { CGAL_assertion(i<number_of_facet_cycles()); +      if (i==0) return coords_.begin(); +      else return coords_.begin()+fc_ends_[i]; } + +    Coord_const_iterator facet_cycle_end(unsigned i) const +    { CGAL_assertion(i<number_of_facet_cycles()); +      if (i<fc_ends_.size()-1) return coords_.begin()+fc_ends_[i+1]; +      else return coords_.end(); } + +    void debug(std::ostream& os = std::cerr) const +    { os << "DFacet, normal=" << normal_ << ", mark=" << mark() << std::endl; +      for(unsigned i=0; i<number_of_facet_cycles(); ++i) { +	os << "  facet cycle "; +	// put all vertices in facet cycle into contour: +	Coord_const_iterator cit; +	for(cit = facet_cycle_begin(i); cit != facet_cycle_end(i); ++cit) +	  os << *cit; +	os << std::endl; +      } +    } +     +  }; // DFacet + + +// ---------------------------------------------------------------------------- +// OGL Drawable Polyhedron: +// ---------------------------------------------------------------------------- + +  inline void CGAL_GLU_TESS_CALLBACK beginCallback(GLenum which) +  { glBegin(which); } + +  inline void CGAL_GLU_TESS_CALLBACK endCallback(void) +  { glEnd(); } + +  inline void CGAL_GLU_TESS_CALLBACK errorCallback(GLenum errorCode) +  { const GLubyte *estring; +    estring = gluErrorString(errorCode); +    fprintf(stderr, "Tessellation Error: %s\n", estring); +    std::exit (0); +  } + +  inline void CGAL_GLU_TESS_CALLBACK vertexCallback(GLvoid* vertex, +			                            GLvoid* user) +  { GLdouble* pc(static_cast<GLdouble*>(vertex)); +    GLdouble* pu(static_cast<GLdouble*>(user)); +    //    CGAL_NEF_TRACEN("vertexCallback coord  "<<pc[0]<<","<<pc[1]<<","<<pc[2]); +    //    CGAL_NEF_TRACEN("vertexCallback normal "<<pu[0]<<","<<pu[1]<<","<<pu[2]); +    glNormal3dv(pu); +    glVertex3dv(pc);  +  } + +  inline void CGAL_GLU_TESS_CALLBACK combineCallback(GLdouble coords[3], GLvoid *[4], GLfloat [4], GLvoid **dataOut) +  { static std::list<GLdouble*> pcache; +    if (dataOut) { +        GLdouble *n = new GLdouble[3]; +        n[0] = coords[0]; +        n[1] = coords[1]; +        n[2] = coords[2]; +        pcache.push_back(n); +        *dataOut = n; +    } else { +        for (std::list<GLdouble*>::const_iterator i = pcache.begin(); i != pcache.end(); i++) +            delete[] *i; +        pcache.clear(); +    } +  } + + enum { SNC_AXES}; + enum { SNC_BOUNDARY, SNC_SKELETON }; + + class Polyhedron : public OGL_base_object { + protected: +    std::list<DPoint>    vertices_; +    std::list<DSegment>  edges_; +    std::list<DFacet>    halffacets_; + +    GLuint         object_list_; +    bool init_; + +    Bbox_3  bbox_; + +    int style; +    std::vector<bool> switches; + +    typedef std::list<DPoint>::const_iterator   Vertex_iterator; +    typedef std::list<DSegment>::const_iterator Edge_iterator; +    typedef std::list<DFacet>::const_iterator   Halffacet_iterator; + +  public: +    Polyhedron() : bbox_(-1,-1,-1,1,1,1), switches(1) {  +      object_list_ = 0; +      init_ = false; +      style = SNC_BOUNDARY; +      switches[SNC_AXES] = false;  +    } + +    /* +    Polyhedron(const Polyhedron& P) : +      object_list_(0), +      init_(false), +      bbox_(P.bbox_), +      style(P.style), +      switches(2) { +       +      switches[SNC_AXES] = P.switches[SNC_AXES];  + +      Vertex_iterator v; +      for(v=P.vertices_.begin();v!=P.vertices_.end();++v) +	vertices_.push_back(*v); +      Edge_iterator e; +      for(e=P.edges_.begin();e!=P.edges_.end();++e) +	edges_.push_back(*e); +      Halffacet_iterator f; +      for(f=P.halffacets_.begin();f!=P.halffacets_.end();++f) +	halffacets_.push_back(*f); +    } + +    Polyhedron& operator=(const Polyhedron& P) {  +      if (object_list_) glDeleteLists(object_list_, 4); +      object_list_ = 0; +      init_ = false; +      style = P.style; +      switches[SNC_AXES] = P.switches[SNC_AXES];  + +      Vertex_iterator v; +      vertices_.clear(); +      for(v=P.vertices_.begin();v!=P.vertices_.end();++v) +	vertices_.push_back(*v); +      Edge_iterator e; +      edges_.clear(); +      for(e=P.edges_.begin();e!=P.edges_.end();++e) +	edges_.push_back(*e); +      Halffacet_iterator f; +      halffacets_.clear(); +      for(f=P.halffacets_.begin();f!=P.halffacets_.end();++f) +	halffacets_.push_back(*f); +      init();       +      return *this; +    } +    */ +    ~Polyhedron()  +    { if (object_list_) glDeleteLists(object_list_, 4); } + +    void push_back(const Double_point& p, bool m) { +        vertices_.push_back(DPoint(p,m)); +    } +    void push_back(const Double_segment& s, bool m)  +    { edges_.push_back(DSegment(s,m)); } +    void push_back(const DFacet& f)  +    { halffacets_.push_back(f); } +  +    void toggle(int index) {  +      switches[index] = !switches[index];  +    } +     +    void set_style(int index) { +      style = index; +    } + +    bool is_initialized() const { return init_; } + +    Bbox_3  bbox() const { return bbox_; } +    Bbox_3& bbox()       { return bbox_; } + +    virtual CGAL::Color getVertexColor(Vertex_iterator v) const +    { +	CGAL::Color cf(CGAL_NEF3_MARKED_VERTEX_COLOR), +	  ct(CGAL_NEF3_UNMARKED_VERTEX_COLOR); // more blue-ish +	CGAL::Color c = v->mark() ? ct : cf; +	return c; +    } + +    void draw(Vertex_iterator v) const {  +      //      CGAL_NEF_TRACEN("drawing vertex "<<*v); +      CGAL::Color c = getVertexColor(v); +      glPointSize(10); +      glColor3ub(c.red(), c.green(), c.blue()); +      glBegin(GL_POINTS); +      glVertex3d(v->x(),v->y(),v->z()); +#ifdef CGAL_NEF_EMPHASIZE_VERTEX +      glColor3ub(255,0,0); +      glVertex3d(CGAL_NEF_EMPHASIZE_VERTEX); +#endif +      glEnd(); +    } + +    virtual CGAL::Color getEdgeColor(Edge_iterator e) const +    { +	CGAL::Color cf(CGAL_NEF3_MARKED_EDGE_COLOR), +	  ct(CGAL_NEF3_UNMARKED_EDGE_COLOR); // more blue-ish +	CGAL::Color c = e->mark() ? ct : cf; +	return c; +    } + +    void draw(Edge_iterator e) const {  +      //      CGAL_NEF_TRACEN("drawing edge "<<*e); +      Double_point p = e->source(), q = e->target(); +      CGAL::Color c = getEdgeColor(e); +      glLineWidth(5); +      glColor3ub(c.red(),c.green(),c.blue()); +      glBegin(GL_LINE_STRIP); +      glVertex3d(p.x(), p.y(), p.z()); +      glVertex3d(q.x(), q.y(), q.z()); +      glEnd(); +    } + +    virtual CGAL::Color getFacetColor(Halffacet_iterator f) const +    { +	CGAL::Color cf(CGAL_NEF3_MARKED_FACET_COLOR), +	  ct(CGAL_NEF3_UNMARKED_FACET_COLOR); // more blue-ish +	CGAL::Color c = (f->mark() ? ct : cf); +	return c; +    } + +    void draw(Halffacet_iterator f) const {  +      //      CGAL_NEF_TRACEN("drawing facet "<<(f->debug(),"")); +      GLUtesselator* tess_ = gluNewTess(); +      gluTessCallback(tess_, GLenum(GLU_TESS_VERTEX_DATA), +		      (GLvoid (CGAL_GLU_TESS_CALLBACK *)(CGAL_GLU_TESS_DOTS)) &vertexCallback); +      gluTessCallback(tess_, GLenum(GLU_TESS_COMBINE), +		      (GLvoid (CGAL_GLU_TESS_CALLBACK *)(CGAL_GLU_TESS_DOTS)) &combineCallback); +      gluTessCallback(tess_, GLenum(GLU_TESS_BEGIN), +		      (GLvoid (CGAL_GLU_TESS_CALLBACK *)(CGAL_GLU_TESS_DOTS)) &beginCallback); +      gluTessCallback(tess_, GLenum(GLU_TESS_END), +		      (GLvoid (CGAL_GLU_TESS_CALLBACK *)(CGAL_GLU_TESS_DOTS)) &endCallback); +      gluTessCallback(tess_, GLenum(GLU_TESS_ERROR), +		      (GLvoid (CGAL_GLU_TESS_CALLBACK *)(CGAL_GLU_TESS_DOTS)) &errorCallback); +      gluTessProperty(tess_, GLenum(GLU_TESS_WINDING_RULE), +		      GLU_TESS_WINDING_POSITIVE); + +      DFacet::Coord_const_iterator cit; +      CGAL::Color c = getFacetColor(f); +      glColor3ub(c.red(),c.green(),c.blue()); +      gluTessBeginPolygon(tess_,f->normal()); +      //      CGAL_NEF_TRACEN(" "); +      //      CGAL_NEF_TRACEN("Begin Polygon"); +      gluTessNormal(tess_,f->dx(),f->dy(),f->dz()); +      // forall facet cycles of f: +      for(unsigned i = 0; i < f->number_of_facet_cycles(); ++i) { +        gluTessBeginContour(tess_); +	//	CGAL_NEF_TRACEN("  Begin Contour"); +	// put all vertices in facet cycle into contour: +	for(cit = f->facet_cycle_begin(i);  +	    cit != f->facet_cycle_end(i); ++cit) { +	  gluTessVertex(tess_, *cit, *cit); +	  //	  CGAL_NEF_TRACEN("    add Vertex"); +	} +        gluTessEndContour(tess_); +	//	CGAL_NEF_TRACEN("  End Contour"); +      } +      gluTessEndPolygon(tess_); +      //      CGAL_NEF_TRACEN("End Polygon"); +      gluDeleteTess(tess_); +    } + +    void construct_axes() const +    {  +      glLineWidth(2.0); +      // red x-axis +      glColor3f(1.0,0.0,0.0); +      glBegin(GL_LINES); +      glVertex3f(0.0,0.0,0.0); +      glVertex3f(5000.0,0.0,0.0); +      glEnd(); +       // green y-axis  +      glColor3f(0.0,1.0,0.0); +      glBegin(GL_LINES); +      glVertex3f(0.0,0.0,0.0); +      glVertex3f(0.0,5000.0,0.0); +      glEnd(); +      // blue z-axis and equator +      glColor3f(0.0,0.0,1.0); +      glBegin(GL_LINES); +      glVertex3f(0.0,0.0,0.0); +      glVertex3f(0.0,0.0,5000.0); +      glEnd(); +      // six coordinate points in pink: +      glPointSize(10); +      glBegin(GL_POINTS); +      glColor3f(1.0,0.0,0.0); +      glVertex3d(5,0,0); +      glColor3f(0.0,1.0,0.0); +      glVertex3d(0,5,0); +      glColor3f(0.0,0.0,1.0); +      glVertex3d(0,0,5); +      glEnd(); +    } + + +    void fill_display_lists() { +      glNewList(object_list_, GL_COMPILE); +      Vertex_iterator v; +      for(v=vertices_.begin();v!=vertices_.end();++v)  +	draw(v); +      glEndList();      + +      glNewList(object_list_+1, GL_COMPILE); +      Edge_iterator e; +      for(e=edges_.begin();e!=edges_.end();++e) +	draw(e); +      glEndList();      + +      glNewList(object_list_+2, GL_COMPILE); +      Halffacet_iterator f; +      for(f=halffacets_.begin();f!=halffacets_.end();++f) +	draw(f); +      glEndList(); + +      glNewList(object_list_+3, GL_COMPILE); // axes: +      construct_axes(); +      glEndList(); + +    } + +    void init() {  +      if (init_) return; +      init_ = true; +      switches[SNC_AXES] = false; +      style = SNC_BOUNDARY; +      object_list_ = glGenLists(4);  +      CGAL_assertion(object_list_);  +      fill_display_lists(); +    } + + +    void draw() const +    {  +      if (!is_initialized()) const_cast<Polyhedron&>(*this).init(); +      double l = (std::max)( (std::max)( bbox().xmax() - bbox().xmin(), +					 bbox().ymax() - bbox().ymin()), +			     bbox().zmax() - bbox().zmin()); +      if ( l < 1) // make sure that a single point doesn't screw up here +          l = 1; +      glScaled( 4.0/l, 4.0/l, 4.0/l); +      glTranslated( -(bbox().xmax() + bbox().xmin()) / 2.0, +                    -(bbox().ymax() + bbox().ymin()) / 2.0, +                    -(bbox().zmax() + bbox().zmin()) / 2.0); +      if (style == SNC_BOUNDARY) { +	//glEnable(GL_LIGHTING);  +	glCallList(object_list_+2); // facets +	//glDisable(GL_LIGHTING); +      } +      // move edges and vertices a bit towards the view-point,  +      // i.e., 1/100th of the unit vector in camera space +      //      double f = l / 4.0 / 100.0; +      //      glTranslated( z_vec[0] * f, z_vec[1] * f, z_vec[2] * f); +      glCallList(object_list_+1); // edges +      glCallList(object_list_);   // vertices +      if (switches[SNC_AXES]) glCallList(object_list_+3); // axis +   } + +    void debug(std::ostream& os = std::cerr) const +    { +      os << "OGL::Polyhedron" << std::endl; +      os << "Vertices:" << std::endl; +      Vertex_iterator v; +      for(v=vertices_.begin();v!=vertices_.end();++v)  +	os << "  "<<*v<<", mark="<<v->mark()<<std::endl; +      os << "Edges:" << std::endl; +      Edge_iterator e; +      for(e=edges_.begin();e!=edges_.end();++e) +	os << "  "<<*e<<", mark="<<e->mark()<<std::endl; +      os << "Facets:" << std::endl; +      Halffacet_iterator f; +      for(f=halffacets_.begin();f!=halffacets_.end();++f) +	f->debug(); os << std::endl; +      os << std::endl; +    } + +  }; // Polyhedron + +  template<typename Nef_polyhedron> +  class Nef3_Converter {  +    typedef typename Nef_polyhedron::SNC_structure           SNC_structure; +    typedef CGAL::SNC_decorator<SNC_structure>               Base; +    typedef CGAL::SNC_FM_decorator<SNC_structure>            FM_decorator; +     +    public: +    typedef typename SNC_structure::Vertex_const_iterator Vertex_const_iterator;  +    typedef typename SNC_structure::Halfedge_const_iterator Halfedge_const_iterator;  +    typedef typename SNC_structure::Halffacet_const_iterator Halffacet_const_iterator;  +    typedef typename SNC_structure::Halffacet_cycle_const_iterator Halffacet_cycle_const_iterator; +     +    typedef typename SNC_structure::Object_const_handle Object_const_handle; +    typedef typename SNC_structure::SHalfedge_const_handle SHalfedge_const_handle;  +    typedef typename SNC_structure::SHalfloop_const_handle SHalfloop_const_handle;  +     +    typedef typename SNC_structure::Vertex_const_handle Vertex_const_handle;  +    typedef typename SNC_structure::Halfedge_const_handle Halfedge_const_handle;  +    typedef typename SNC_structure::Halffacet_const_handle Halffacet_const_handle; +     +    typedef typename SNC_structure::Point_3 Point_3; +    typedef typename SNC_structure::Vector_3 Vector_3; +    typedef typename SNC_structure::Segment_3 Segment_3; +    typedef typename SNC_structure::Plane_3 Plane_3; +    typedef typename SNC_structure::Mark Mark; +    typedef typename SNC_structure::SHalfedge_around_facet_const_circulator  +      SHalfedge_around_facet_const_circulator; +     +  private: +    static OGL::Double_point double_point(const Point_3& p) +      { return OGL::Double_point(CGAL::to_double(p.x()), +				 CGAL::to_double(p.y()), +				 CGAL::to_double(p.z())); } +     +    static OGL::Double_segment double_segment(const Segment_3& s) +      { return OGL::Double_segment(double_point(s.source()), +				   double_point(s.target())); } +     +    static void draw(Vertex_const_handle v, const Nef_polyhedron& ,  +		     CGAL::OGL::Polyhedron& P) {  +      Point_3 bp = v->point(); +      //    CGAL_NEF_TRACEN("vertex " << bp); +      P.push_back(double_point(bp), v->mark());  +    } +     +    static void draw(Halfedge_const_handle e, const Nef_polyhedron& , +		     CGAL::OGL::Polyhedron& P) {  +      Vertex_const_handle s = e->source(); +      Vertex_const_handle t = e->twin()->source(); +      Segment_3 seg(s->point(),t->point()); +      //    CGAL_NEF_TRACEN("edge " << seg); +      P.push_back(double_segment(seg), e->mark());  +    } +     +    static void draw(Halffacet_const_handle f, const Nef_polyhedron& , +		     CGAL::OGL::Polyhedron& P) {  +      OGL::DFacet g; +      Halffacet_cycle_const_iterator fc; // all facet cycles: +      CGAL_forall_facet_cycles_of(fc,f) +	if ( fc.is_shalfedge() ) { // non-trivial facet cycle +	  g.new_facet_cycle(); +	  SHalfedge_const_handle h = fc; +	  SHalfedge_around_facet_const_circulator hc(h), he(hc); +	  CGAL_For_all(hc,he){ // all vertex coordinates in facet cycle +	    Point_3 sp = hc->source()->source()->point(); +	    //	      CGAL_NEF_TRACEN(" ");CGAL_NEF_TRACEN("facet" << sp); +	    g.push_back_vertex(double_point(sp)); +	  } +	} +      Vector_3 v = f->plane().orthogonal_vector(); +      g.set_normal(CGAL::to_double(v.x()),  +		   CGAL::to_double(v.y()),  +		   CGAL::to_double(v.z()),  +		   f->mark()); +      P.push_back(g); +    } +     +    // Returns the bounding box of the finite vertices of the polyhedron. +    // Returns $[-1,+1]^3$ as bounding box if no finite vertex exists. +     +    static Bbox_3  bounded_bbox(const Nef_polyhedron& N) { +      bool first_vertex = true; +      Bbox_3 bbox( -1.0, -1.0, -1.0, 1.0, 1.0, 1.0); +      Vertex_const_iterator vi; +      CGAL_forall_vertices(vi, N) { +	Point_3 p = vi->point(); +	double x = CGAL::to_double(p.hx()); +	double y = CGAL::to_double(p.hy()); +	double z = CGAL::to_double(p.hz()); +	double w = CGAL::to_double(p.hw()); +	if (N.is_standard(vi)) { +	  if(first_vertex) { +	    bbox = Bbox_3(x/w, y/w, z/w, x/w, y/w, z/w); +	    first_vertex = false; +	  } else { +	    bbox = bbox + Bbox_3(x/w, y/w, z/w, x/w, y/w, z/w); +	    first_vertex = false; +	  } +	} +      } +      return bbox; +    }   +     +    static void set_R(Bbox_3& bbox, const Nef_polyhedron& N) { +      if(N.is_standard_kernel()) return; +      double size = abs(bbox.xmin()); +      if(size < bbox.xmax()) size = bbox.xmax(); +      if(size < bbox.ymin()) size = bbox.ymin(); +      if(size < bbox.ymax()) size = bbox.ymax(); +      if(size < bbox.zmin()) size = bbox.zmin(); +      if(size < bbox.zmax()) size = bbox.zmax(); +      N.set_size_of_infimaximal_box(size*50); +      //    CGAL_NEF_TRACEN("set infi box size to " << size); +      Vertex_const_iterator vi; +      CGAL_forall_vertices(vi, N) +	if(N.is_standard(vi)) +	  return; +      bbox = Bbox_3(bbox.xmin()*10,bbox.ymin()*10,bbox.zmin()*10, +		    bbox.xmax()*10,bbox.ymax()*10,bbox.zmax()*10); +    } +  public: +    static void convert_to_OGLPolyhedron(const Nef_polyhedron& N, CGAL::OGL::Polyhedron* P) {  +      Bbox_3 bbox(bounded_bbox(N)); +      set_R(bbox,N); +      P->bbox() = bbox;     +      Vertex_const_iterator v; +      CGAL_forall_vertices(v,*N.sncp()) draw(v,N,*P); +      Halfedge_const_iterator e; +      CGAL_forall_edges(e,*N.sncp()) draw(e,N,*P); +      Halffacet_const_iterator f; +      CGAL_forall_facets(f,*N.sncp()) draw(f,N,*P); +    } +     +  }; // Nef3_Converter + +} // namespace OGL + +} //namespace CGAL +#endif // CGAL_NEF_OPENGL_HELPER_H diff --git a/src/cgalrenderer.cc b/src/cgalrenderer.cc new file mode 100644 index 0000000..551c061 --- /dev/null +++ b/src/cgalrenderer.cc @@ -0,0 +1,126 @@ +/* + *  OpenSCAD (www.openscad.org) + *  Copyright (C) 2009-2011 Clifford Wolf <clifford@clifford.at> and + *                          Marius Kintel <marius@kintel.net> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 2 of the License, or + *  (at your option) any later version. + * + *  As a special exception, you have permission to link this program + *  with the CGAL library and distribute executables, as long as you + *  follow the requirements of the GNU GPL in regard to all of the + *  software in the executable aside from CGAL. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + * + */ + +#include "cgalrenderer.h" +#include "polyset.h" +#include "CGAL_renderer.h" +#include "dxfdata.h" +#include "dxftess.h" + +#include "Preferences.h" + +CGALRenderer::CGALRenderer(const CGAL_Nef_polyhedron &root) : root(root) +{ +	if (root.dim == 2) { +		DxfData dd(root); +		this->polyset = new PolySet(); +		this->polyset->is2d = true; +		dxf_tesselate(this->polyset, &dd, 0, true, false, 0); +	} +	else if (root.dim == 3) { +		this->polyhedron = new Polyhedron(); +    // FIXME: Make independent of Preferences +		this->polyhedron->setColor(Polyhedron::CGAL_NEF3_MARKED_FACET_COLOR, +															 Preferences::inst()->color(Preferences::CGAL_FACE_BACK_COLOR).red(), +															 Preferences::inst()->color(Preferences::CGAL_FACE_BACK_COLOR).green(), +															 Preferences::inst()->color(Preferences::CGAL_FACE_BACK_COLOR).blue()); +		this->polyhedron->setColor(Polyhedron::CGAL_NEF3_UNMARKED_FACET_COLOR, +															 Preferences::inst()->color(Preferences::CGAL_FACE_FRONT_COLOR).red(), +															 Preferences::inst()->color(Preferences::CGAL_FACE_FRONT_COLOR).green(), +															 Preferences::inst()->color(Preferences::CGAL_FACE_FRONT_COLOR).blue()); +		 +		CGAL::OGL::Nef3_Converter<CGAL_Nef_polyhedron3>::convert_to_OGLPolyhedron(this->root.p3, this->polyhedron); +		this->polyhedron->init(); +	} +} + +CGALRenderer::~CGALRenderer() +{ +	if (this->polyset) this->polyset->unlink(); +} + +void CGALRenderer::draw(bool showfaces, bool showedges) const +{ +	if (this->root.dim == 2) { +		// Draw 2D polygons +		glDisable(GL_LIGHTING); +		const QColor &col = Preferences::inst()->color(Preferences::CGAL_FACE_2D_COLOR); +		glColor3f(col.redF(), col.greenF(), col.blueF()); +		 +		for (int i=0; i < this->polyset->polygons.size(); i++) { +			glBegin(GL_POLYGON); +			for (int j=0; j < this->polyset->polygons[i].size(); j++) { +				PolySet::Point p = this->polyset->polygons[i][j]; +				glVertex3d(p.x, p.y, -0.1); +			} +			glEnd(); +		} +		 +		typedef CGAL_Nef_polyhedron2::Explorer Explorer; +		typedef Explorer::Face_const_iterator fci_t; +		typedef Explorer::Halfedge_around_face_const_circulator heafcc_t; +		typedef Explorer::Point Point; +		Explorer E = this->root.p2.explorer(); +		 +		// Draw 2D edges +		glDisable(GL_DEPTH_TEST); +		glDisable(GL_LIGHTING); +		glLineWidth(2); +		const QColor &col2 = Preferences::inst()->color(Preferences::CGAL_EDGE_2D_COLOR); +		glColor3f(col2.redF(), col2.greenF(), col2.blueF()); +		 +		// Extract the boundary, including inner boundaries of the polygons +		for (fci_t fit = E.faces_begin(), facesend = E.faces_end(); fit != facesend; ++fit) { +			bool fset = false; +			double fx = 0.0, fy = 0.0; +			heafcc_t fcirc(E.halfedge(fit)), fend(fcirc); +			CGAL_For_all(fcirc, fend) { +				if(E.is_standard(E.target(fcirc))) { +					Point p = E.point(E.target(fcirc)); +					double x = to_double(p.x()), y = to_double(p.y()); +					if (!fset) { +						glBegin(GL_LINE_STRIP); +						fx = x, fy = y; +						fset = true; +					} +					glVertex3d(x, y, -0.1); +				} +			} +			if (fset) { +				glVertex3d(fx, fy, -0.1); +				glEnd(); +			} +		} +		 +		glEnable(GL_DEPTH_TEST); +	} +	else if (this->root.dim == 3) { +		if (showfaces) this->polyhedron->set_style(SNC_BOUNDARY); +		else this->polyhedron->set_style(SNC_SKELETON); +		 +		this->polyhedron->draw(showfaces && showedges); +  } +} diff --git a/src/cgalrenderer.h b/src/cgalrenderer.h new file mode 100644 index 0000000..b3c1638 --- /dev/null +++ b/src/cgalrenderer.h @@ -0,0 +1,20 @@ +#ifndef CGALRENDERER_H_ +#define CGALRENDERER_H_ + +#include "renderer.h" +#include "cgal.h" + +class CGALRenderer : public Renderer +{ +public: +	CGALRenderer(const CGAL_Nef_polyhedron &root); +	~CGALRenderer(); +	void draw(bool showfaces, bool showedges) const; + +private: +	const CGAL_Nef_polyhedron &root; +	class Polyhedron *polyhedron; +	class PolySet *polyset; +}; + +#endif diff --git a/src/csgops.cc b/src/csgops.cc index 55d91d2..8c295f9 100644 --- a/src/csgops.cc +++ b/src/csgops.cc @@ -118,7 +118,7 @@ CGAL_Nef_polyhedron CsgNode::render_cgal_nef_polyhedron() const  	cgal_nef_cache.insert(cache_id, new cgal_nef_cache_entry(N), N.weight());  	}  	catch (CGAL::Assertion_exception e) { -		PRINTF("ERROR: Illegal polygonal object - make sure all polygons are defined with the same winding order. Skipping affected object."); +		PRINTF("CGAL error: %s", e.what());  	}  	CGAL::set_error_behaviour(old_behaviour); diff --git a/src/dxftess-cgal.cc b/src/dxftess-cgal.cc index 2e80fea..adb7e9a 100644 --- a/src/dxftess-cgal.cc +++ b/src/dxftess-cgal.cc @@ -158,7 +158,7 @@ void dxf_tesselate(PolySet *ps, DxfData *dxf, double rot, bool up, bool /* do_tr  	}  	catch (CGAL::Assertion_exception e) { -		PRINTF("ERROR: Polygon intersection detected. Skipping affected polygons."); +		PRINTF("CGAL error: %s", e.what());  		CGAL::set_error_behaviour(old_behaviour);  		return;  	} diff --git a/src/glview.cc b/src/glview.cc index ef023f2..9d82443 100644 --- a/src/glview.cc +++ b/src/glview.cc @@ -26,6 +26,7 @@  #include "GLView.h"  #include "Preferences.h" +#include "renderer.h"  #include <QApplication>  #include <QWheelEvent> @@ -41,9 +42,13 @@  #include "mathc99.h"  #include <stdio.h> +#ifdef ENABLE_OPENCSG +#  include <opencsg.h> +#endif +  #define FAR_FAR_AWAY 100000.0 -GLView::GLView(QWidget *parent) : QGLWidget(parent) +GLView::GLView(QWidget *parent) : QGLWidget(parent), renderer(NULL)  {  	viewer_distance = 500;  	object_rot_x = 35; @@ -54,15 +59,12 @@ GLView::GLView(QWidget *parent) : QGLWidget(parent)  	object_trans_z = 0;  	mouse_drag_active = false; -	last_mouse_x = 0; -	last_mouse_y = 0;  	orthomode = false;  	showaxes = false;  	showcrosshairs = false; - -	renderfunc = NULL; -	renderfunc_vp = NULL; +	showedges = false; +	showfaces = true;  	for (int i = 0; i < 10; i++)  		shaderinfo[i] = 0; @@ -77,10 +79,10 @@ GLView::GLView(QWidget *parent) : QGLWidget(parent)  #endif  } -void GLView::setRenderFunc(void (*func)(void*), void *userdata) +void GLView::setRenderer(Renderer *r)  { -	this->renderfunc = func; -	this->renderfunc_vp = userdata; +	this->renderer = r; +	updateGL();  }  void GLView::initializeGL() @@ -91,6 +93,22 @@ void GLView::initializeGL()  	glEnable(GL_BLEND);  	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +	GLfloat light_diffuse[] = {1.0, 1.0, 1.0, 1.0}; +	GLfloat light_position0[] = {-1.0, -1.0, +1.0, 0.0}; +	GLfloat light_position1[] = {+1.0, +1.0, -1.0, 0.0}; + +	glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); +	glLightfv(GL_LIGHT0, GL_POSITION, light_position0); +	glEnable(GL_LIGHT0); +	glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse); +	glLightfv(GL_LIGHT1, GL_POSITION, light_position1); +	glEnable(GL_LIGHT1); +	glEnable(GL_LIGHTING); +	glEnable(GL_NORMALIZE); + +	glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); +	glEnable(GL_COLOR_MATERIAL); +  #ifdef ENABLE_OPENCSG  	GLenum err = glewInit();  	if (GLEW_OK != err) { @@ -256,43 +274,47 @@ void GLView::resizeGL(int w, int h)  #endif  	glViewport(0, 0, w, h);  	w_h_ratio = sqrt((double)w / (double)h); + +	setupPerspective();  } -void GLView::paintGL() +void GLView::setupPerspective()  { -	const QColor &bgcol = Preferences::inst()->color(Preferences::BACKGROUND_COLOR); -	glClearColor(bgcol.redF(), bgcol.greenF(), bgcol.blueF(), 0.0); - -	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); +	glMatrixMode(GL_PROJECTION); +	glLoadIdentity(); +	glFrustum(-w_h_ratio, +w_h_ratio, -(1/w_h_ratio), +(1/w_h_ratio), +10.0, +FAR_FAR_AWAY); +} +void GLView::setupOrtho(double distance, bool offset) +{  	glMatrixMode(GL_PROJECTION);  	glLoadIdentity(); +	if(offset) +		glTranslated(-0.8, -0.8, 0); +	double l = distance/10; +	glOrtho(-w_h_ratio*l, +w_h_ratio*l, +			-(1/w_h_ratio)*l, +(1/w_h_ratio)*l, +			-FAR_FAR_AWAY, +FAR_FAR_AWAY); +} + +void GLView::paintGL() +{ +	glEnable(GL_LIGHTING); +  	if (orthomode) -		glOrtho(-w_h_ratio*viewer_distance/10, +w_h_ratio*viewer_distance/10, -				-(1/w_h_ratio)*viewer_distance/10, +(1/w_h_ratio)*viewer_distance/10, -				-FAR_FAR_AWAY, +FAR_FAR_AWAY); -	else -		glFrustum(-w_h_ratio, +w_h_ratio, -(1/w_h_ratio), +(1/w_h_ratio), +10.0, +FAR_FAR_AWAY); -	gluLookAt(0.0, -viewer_distance, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0); +		setupOrtho(viewer_distance);  	glMatrixMode(GL_MODELVIEW);  	glLoadIdentity(); -	GLfloat light_diffuse[] = {1.0, 1.0, 1.0, 1.0}; -	GLfloat light_position0[] = {-1.0, -1.0, +1.0, 0.0}; -	GLfloat light_position1[] = {+1.0, +1.0, -1.0, 0.0}; +	const QColor &bgcol = Preferences::inst()->color(Preferences::BACKGROUND_COLOR); +	glClearColor(bgcol.redF(), bgcol.greenF(), bgcol.blueF(), 0.0); -	glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); -	glLightfv(GL_LIGHT0, GL_POSITION, light_position0); -	glEnable(GL_LIGHT0); -	glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse); -	glLightfv(GL_LIGHT1, GL_POSITION, light_position1); -	glEnable(GL_LIGHT1); -	glEnable(GL_LIGHTING); -	glEnable(GL_NORMALIZE); +	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); -	glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); -	glEnable(GL_COLOR_MATERIAL); +	gluLookAt(0.0, -viewer_distance, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0); + +	glTranslated(object_trans_x, object_trans_y, object_trans_z);  	glRotated(object_rot_x, 1.0, 0.0, 0.0);  	glRotated(object_rot_y, 0.0, 1.0, 0.0); @@ -315,8 +337,6 @@ void GLView::paintGL()  		glEnd();  	} -	glTranslated(object_trans_x, object_trans_y, object_trans_z); -  	// Large gray axis cross inline with the model    // FIXME: This is always gray - adjust color to keep contrast with background  	if (showaxes) @@ -324,12 +344,13 @@ void GLView::paintGL()  		glLineWidth(1);  		glColor3d(0.5, 0.5, 0.5);  		glBegin(GL_LINES); -		glVertex3d(-viewer_distance/10, 0, 0); -		glVertex3d(+viewer_distance/10, 0, 0); -		glVertex3d(0, -viewer_distance/10, 0); -		glVertex3d(0, +viewer_distance/10, 0); -		glVertex3d(0, 0, -viewer_distance/10); -		glVertex3d(0, 0, +viewer_distance/10); +		double l = viewer_distance/10; +		glVertex3d(-l, 0, 0); +		glVertex3d(+l, 0, 0); +		glVertex3d(0, -l, 0); +		glVertex3d(0, +l, 0); +		glVertex3d(0, 0, -l); +		glVertex3d(0, 0, +l);  		glEnd();  	} @@ -340,20 +361,21 @@ void GLView::paintGL()  	glLineWidth(2);  	glColor3d(1.0, 0.0, 0.0); -	if (renderfunc) -		renderfunc(renderfunc_vp); +	if (this->renderer) { +#if defined(ENABLE_MDI) && defined(ENABLE_OPENCSG) +		// FIXME: This belongs in the OpenCSG renderer, but it doesn't know about this ID yet +		OpenCSG::setContext(this->opencsg_id); +#endif +		this->renderer->draw(showfaces, showedges); +	}  	// Small axis cross in the lower left corner  	if (showaxes)  	{  		glDepthFunc(GL_ALWAYS); -		glMatrixMode(GL_PROJECTION); -		glLoadIdentity(); -		glTranslated(-0.8, -0.8, 0); -		glOrtho(-w_h_ratio*1000/10, +w_h_ratio*1000/10, -				-(1/w_h_ratio)*1000/10, +(1/w_h_ratio)*1000/10, -				-FAR_FAR_AWAY, +FAR_FAR_AWAY); +		setupOrtho(1000,true); +  		gluLookAt(0.0, -1000, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0);  		glMatrixMode(GL_MODELVIEW); @@ -418,6 +440,10 @@ void GLView::paintGL()  		glVertex3d(zlabel_x-3, zlabel_y+3, 0); glVertex3d(zlabel_x+3, zlabel_y+3, 0);  		glVertex3d(zlabel_x-3, zlabel_y-3, 0); glVertex3d(zlabel_x+3, zlabel_y+3, 0);  		glEnd(); + +		//Restore perspective for next paint +		if(!orthomode) +			setupPerspective();  	}  	if (statusLabel) { @@ -452,101 +478,48 @@ void GLView::wheelEvent(QWheelEvent *event)  void GLView::mousePressEvent(QMouseEvent *event)  {  	mouse_drag_active = true; -	last_mouse_x = event->globalX(); -	last_mouse_y = event->globalY(); +	last_mouse = event->globalPos();  	grabMouse();  	setFocus();  } -static void mat_id(double *trg) -{ -	for (int i = 0; i < 16; i++) -		trg[i] = i%5 == 0; -} -static void mat_mul(double *trg, const double *m1, const double *m2) +void GLView::normalizeAngle(GLdouble& angle)  { -	double m[16]; -	for (int x = 0; x < 4; x++) -	for (int y = 0; y < 4; y++) -	{ -		m[x+y*4] = 0; -		for (int i = 0; i < 4; i++) -			m[x+y*4] += m1[i+y*4] * m2[x+i*4]; -	} -	for (int i = 0; i < 16; i++) -		trg[i] = m[i]; -} - -static void mat_rot(double *trg, double angle, double x, double y, double z) -{ -	double s = sin(M_PI*angle/180), c = cos(M_PI*angle/180); -	double cc = 1 - c; -	double m[16] = { -		x*x*cc+c,	x*y*cc-z*s,	x*z*cc+y*s,	0, -		y*x*cc+z*s,	y*y*cc+c,	y*z*cc-x*s,	0, -		x*z*cc-y*s,	y*z*cc+x*s,	z*z*cc+c,	0, -		0,		0,		0,		1 -	}; -	for (int i = 0; i < 16; i++) -		trg[i] = m[i]; +	while(angle < 0) +		angle += 360; +	while(angle > 360) +		angle -= 360;  }  void GLView::mouseMoveEvent(QMouseEvent *event)  { -	int this_mouse_x = event->globalX(); -	int this_mouse_y = event->globalY(); +	QPoint this_mouse = event->globalPos(); +	double dx = (this_mouse.x()-last_mouse.x()) * 0.7; +	double dy = (this_mouse.y()-last_mouse.y()) * 0.7;  	if (mouse_drag_active) {  		if ((event->buttons() & Qt::LeftButton) != 0) { -			object_rot_x += (this_mouse_y-last_mouse_y) * 0.7; +			object_rot_x += dy;  			if ((QApplication::keyboardModifiers() & Qt::ShiftModifier) != 0) -				object_rot_y += (this_mouse_x-last_mouse_x) * 0.7; +				object_rot_y += dx;  			else -				object_rot_z += (this_mouse_x-last_mouse_x) * 0.7; -			while (object_rot_x < 0) -				object_rot_x += 360; -			while (object_rot_x >= 360) -				object_rot_x -= 360; -			while (object_rot_y < 0) -				object_rot_y += 360; -			while (object_rot_y >= 360) -				object_rot_y -= 360; -			while (object_rot_z < 0) -				object_rot_z += 360; -			while (object_rot_z >= 360) -				object_rot_z -= 360; +				object_rot_z += dx; + +			normalizeAngle(object_rot_x); +			normalizeAngle(object_rot_y); +			normalizeAngle(object_rot_z);  		} else { -			double mx = +(this_mouse_x-last_mouse_x) * viewer_distance/1000; -			double my = -(this_mouse_y-last_mouse_y) * viewer_distance/1000; -			double rx[16], ry[16], rz[16], tm[16]; -			mat_rot(rx, -object_rot_x, 1.0, 0.0, 0.0); -			mat_rot(ry, -object_rot_y, 0.0, 1.0, 0.0); -			mat_rot(rz, -object_rot_z, 0.0, 0.0, 1.0); -			mat_id(tm); -			mat_mul(tm, rx, tm); -			mat_mul(tm, ry, tm); -			mat_mul(tm, rz, tm); -			double vec[16] = { -				0,	0,	0,	mx, -				0,	0,	0,	0, -				0,	0,	0,	my, -				0,	0,	0,	1 -			};  			if ((QApplication::keyboardModifiers() & Qt::ShiftModifier) != 0) { -				vec[3] = 0; -				vec[7] = my; -				vec[11] = 0; +				viewer_distance += (GLdouble)dy; +			} else { +				object_trans_x += dx; +				object_trans_z -= dy;  			} -			mat_mul(tm, tm, vec); -			object_trans_x += tm[3]; -			object_trans_y += tm[7]; -			object_trans_z += tm[11];  		}  		updateGL();  		emit doAnimateUpdate();  	} -	last_mouse_x = this_mouse_x; -	last_mouse_y = this_mouse_y; +	last_mouse = this_mouse;  }  void GLView::mouseReleaseEvent(QMouseEvent*) diff --git a/src/mainwin.cc b/src/mainwin.cc index 0492dac..3453b1c 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -40,11 +40,12 @@  #include "dxftess.h"  #include "progress.h"  #ifdef ENABLE_OPENCSG -#include "render-opencsg.h" +#include "opencsgRenderer.h"  #endif  #ifdef USE_PROGRESSWIDGET  #include "ProgressWidget.h"  #endif +#include "thrownTogetherRenderer.h"  #include <QMenu>  #include <QTime> @@ -75,32 +76,8 @@  #ifdef ENABLE_CGAL -#if 1 -#include "CGAL_renderer.h" -using OpenSCAD::OGL::Polyhedron; -using OpenSCAD::OGL::SNC_BOUNDARY; -using OpenSCAD::OGL::SNC_SKELETON; -using OpenSCAD::OGL::Nef3_Converter; -#else -// a little hackish: we need access to default-private members of -// CGAL::OGL::Nef3_Converter so we can implement our own draw function -// that does not scale the model. so we define 'class' to 'struct' -// for this header.. -// -// theoretically there could be two problems: -// 1.) defining language keyword with the pre processor is illegal afair -// 2.) the compiler could use a different memory layout or name mangling for structs -// -// both does not seam to be the case with todays compilers... -// -#define class struct -#include <CGAL/Nef_3/OGL_helper.h> -#undef class -using CGAL::OGL::Polyhedron; -using CGAL::OGL::SNC_BOUNDARY; -using CGAL::OGL::SNC_SKELETON; -using CGAL::OGL::Nef3_Converter; -#endif +#include "cgalrenderer.h" +  #endif // ENABLE_CGAL  #define QUOTE(x__) # x__ @@ -175,15 +152,16 @@ MainWindow::MainWindow(const QString &filename)  	root_chain = NULL;  #ifdef ENABLE_CGAL  	this->root_N = NULL; -	this->recreate_cgal_ogl_p = false; -	cgal_ogl_p = NULL; -	cgal_ogl_ps = NULL; +	this->cgalRenderer = NULL;  #endif +#ifdef ENABLE_OPENCSG +	this->opencsgRenderer = NULL; +#endif +	this->thrownTogetherRenderer = NULL;  	highlights_chain = NULL;  	background_chain = NULL;  	root_node = NULL; -	enableOpenCSG = false;  	tval = 0;  	fps = 0; @@ -327,11 +305,6 @@ MainWindow::MainWindow(const QString &filename)  	connect(this->viewActionOrthogonal, SIGNAL(triggered()), this, SLOT(viewOrthogonal()));  	connect(this->viewActionHide, SIGNAL(triggered()), this, SLOT(hideConsole())); -// #ifdef ENABLE_CGAL -// 	viewActionCGALSurface = menu->addAction("CGAL Surfaces", this, SLOT(viewModeCGALSurface()), QKeySequence(Qt::Key_F10)); -// 	viewActionCGALGrid = menu->addAction("CGAL Grid Only", this, SLOT(viewModeCGALGrid()), QKeySequence(Qt::Key_F11)); -// #endif -  	// Help menu  	connect(this->helpActionAbout, SIGNAL(triggered()), this, SLOT(helpAbout()));  	connect(this->helpActionHomepage, SIGNAL(triggered()), this, SLOT(helpHomepage())); @@ -431,19 +404,14 @@ MainWindow::loadDesignSettings()  MainWindow::~MainWindow()  { -	if (root_module) -		delete root_module; -	if (root_node) -		delete root_node; +	if (root_module) delete root_module; +	if (root_node) delete root_node;  #ifdef ENABLE_CGAL -	if (this->root_N) -		delete this->root_N; -	if (cgal_ogl_p) { -		Polyhedron *p = (Polyhedron*)cgal_ogl_p; -		delete p; -	} -	if (cgal_ogl_ps) -		cgal_ogl_ps->unlink(); +	if (this->root_N) delete this->root_N; +	delete this->cgalRenderer; +#endif +#ifdef ENABLE_OPENCSG +	delete this->opencsgRenderer;  #endif  } @@ -612,6 +580,16 @@ void MainWindow::compile(bool procevents)  	if (procevents)  		QApplication::processEvents(); +  // Invalidate renderers before we kill the CSG tree +	screen->setRenderer(NULL); +	if (this->opencsgRenderer) { +		delete this->opencsgRenderer; +		this->opencsgRenderer = NULL; +	} +	if (this->thrownTogetherRenderer) { +		delete this->thrownTogetherRenderer; +		this->thrownTogetherRenderer = NULL; +	}  	// Remove previous CSG tree  	if (root_module) { @@ -656,7 +634,6 @@ void MainWindow::compile(bool procevents)  		background_chain = NULL;  	}  	root_node = NULL; -	enableOpenCSG = false;  	// Initialize special variables  	root_ctx.set_variable("$t", Value(e_tval->text().toDouble())); @@ -822,13 +799,6 @@ void MainWindow::compileCSG(bool procevents)  		root_chain = new CSGChain();  		root_chain->import(root_norm_term); -		if (root_chain->polysets.size() > 1000) { -			PRINTF("WARNING: Normalized tree has %d elements!", root_chain->polysets.size()); -			PRINTF("WARNING: OpenCSG rendering has been disabled."); -		} else { -			enableOpenCSG = true; -		} -		  		if (highlight_terms.size() > 0)  		{  			PRINTF("Compiling highlights (%d CSG Trees)...", highlight_terms.size()); @@ -866,6 +836,20 @@ void MainWindow::compileCSG(bool procevents)  				background_chain->import(background_terms[i]);  			}  		} + +		if (root_chain->polysets.size() > 1000) { +			PRINTF("WARNING: Normalized tree has %d elements!", root_chain->polysets.size()); +			PRINTF("WARNING: OpenCSG rendering has been disabled."); +		} +		else { +			this->opencsgRenderer = new OpenCSGRenderer(this->root_chain,  +																									this->highlights_chain,  +																									this->background_chain,  +																									this->screen->shaderinfo); +		} +		this->thrownTogetherRenderer = new ThrownTogetherRenderer(this->root_chain,  +																															this->highlights_chain,  +																															this->background_chain);  		PRINT("CSG generation finished.");  		int s = t.elapsed() / 1000; @@ -1132,16 +1116,16 @@ void MainWindow::actionCompile()  	if (this->root_node) compileCSG(!viewActionAnimate->isChecked());  	// Go to non-CGAL view mode -	if (!viewActionOpenCSG->isChecked() && !viewActionThrownTogether->isChecked()) { +	if (viewActionThrownTogether->isChecked()) { +		viewModeThrownTogether(); +	} +	else {  #ifdef ENABLE_OPENCSG  		viewModeOpenCSG();  #else  		viewModeThrownTogether();  #endif  	} -	else { -		screen->updateGL(); -	}  	if (viewActionAnimate->isChecked() && e_dump->isChecked()) {  		QImage img = screen->grabFrameBuffer(); @@ -1167,10 +1151,12 @@ void MainWindow::actionRenderCGAL()  	if (!root_module || !root_node)  		return; +	this->screen->setRenderer(NULL); +	delete this->cgalRenderer; +	this->cgalRenderer = NULL;  	if (this->root_N) {  		delete this->root_N;  		this->root_N = NULL; -		this->recreate_cgal_ogl_p = true;  	}  	PRINT("Rendering Polygon Mesh using CGAL..."); @@ -1254,10 +1240,13 @@ void MainWindow::actionRenderCGAL()  		int s = t.elapsed() / 1000;  		PRINTF("Total rendering time: %d hours, %d minutes, %d seconds", s / (60*60), (s / 60) % 60, s % 60); -		if (!viewActionCGALSurfaces->isChecked() && !viewActionCGALGrid->isChecked()) { +		this->cgalRenderer = new CGALRenderer(*this->root_N); +		// Go to CGAL view mode +		if (viewActionCGALGrid->isChecked()) { +			viewModeCGALGrid(); +		} +		else {  			viewModeCGALSurface(); -		} else { -			screen->updateGL();  		}  		PRINT("Rendering finished."); @@ -1461,37 +1450,6 @@ void MainWindow::viewModeActionsUncheck()  #ifdef ENABLE_OPENCSG -static void renderGLThrownTogether(void *vp); - -static void renderGLviaOpenCSG(void *vp) -{ -	MainWindow *m = (MainWindow*)vp; -	if (!m->enableOpenCSG) { -		renderGLThrownTogether(vp); -		return; -	} -	static int glew_initialized = 0; -	if (!glew_initialized) { -		glew_initialized = 1; -		glewInit(); -	} -#ifdef ENABLE_MDI -	OpenCSG::setContext(m->screen->opencsg_id); -#endif -	if (m->root_chain) { -		GLint *shaderinfo = m->screen->shaderinfo; -		if (!shaderinfo[0]) -			shaderinfo = NULL; -		renderCSGChainviaOpenCSG(m->root_chain, m->viewActionShowEdges->isChecked() ? shaderinfo : NULL, false, false); -		if (m->background_chain) { -			renderCSGChainviaOpenCSG(m->background_chain, m->viewActionShowEdges->isChecked() ? shaderinfo : NULL, false, true); -		} -		if (m->highlights_chain) { -			renderCSGChainviaOpenCSG(m->highlights_chain, m->viewActionShowEdges->isChecked() ? shaderinfo : NULL, true, false); -		} -	} -} -  /*!  	Go to the OpenCSG view mode.  	Falls back to thrown together mode if OpenCSG is not available @@ -1501,8 +1459,7 @@ void MainWindow::viewModeOpenCSG()  	if (screen->hasOpenCSGSupport()) {  		viewModeActionsUncheck();  		viewActionOpenCSG->setChecked(true); -		screen->setRenderFunc(renderGLviaOpenCSG, this); -		screen->updateGL(); +		screen->setRenderer(this->opencsgRenderer ? (Renderer *)this->opencsgRenderer : (Renderer *)this->thrownTogetherRenderer);  	} else {  		viewModeThrownTogether();  	} @@ -1512,125 +1469,12 @@ void MainWindow::viewModeOpenCSG()  #ifdef ENABLE_CGAL -static void renderGLviaCGAL(void *vp) -{ -	MainWindow *m = (MainWindow*)vp; -	if (m->recreate_cgal_ogl_p) { -		m->recreate_cgal_ogl_p = false; -		Polyhedron *p = (Polyhedron*)m->cgal_ogl_p; -		delete p; -		m->cgal_ogl_p = NULL; -		if (m->cgal_ogl_ps) -			m->cgal_ogl_ps->unlink(); -		m->cgal_ogl_ps = NULL; -	} -	if (!m->root_N) return; -	if (m->root_N->dim == 2) -	{ -		if (m->cgal_ogl_ps == NULL) { -			DxfData dd(*m->root_N); -			m->cgal_ogl_ps = new PolySet(); -			m->cgal_ogl_ps->is2d = true; -			dxf_tesselate(m->cgal_ogl_ps, &dd, 0, true, false, 0); -		} - -		// Draw 2D polygons -		glDisable(GL_LIGHTING); -		const QColor &col = Preferences::inst()->color(Preferences::CGAL_FACE_2D_COLOR); -		glColor3f(col.redF(), col.greenF(), col.blueF()); - -		for (int i=0; i < m->cgal_ogl_ps->polygons.size(); i++) { -			glBegin(GL_POLYGON); -			for (int j=0; j < m->cgal_ogl_ps->polygons[i].size(); j++) { -				PolySet::Point p = m->cgal_ogl_ps->polygons[i][j]; -				glVertex3d(p.x, p.y, -0.1); -			} -			glEnd(); -		} - -		typedef CGAL_Nef_polyhedron2::Explorer Explorer; -		typedef Explorer::Face_const_iterator fci_t; -		typedef Explorer::Halfedge_around_face_const_circulator heafcc_t; -		typedef Explorer::Point Point; -		Explorer E = m->root_N->p2.explorer(); -		 -		// Draw 2D edges -		glDisable(GL_DEPTH_TEST); -		glDisable(GL_LIGHTING); -		glLineWidth(2); -		const QColor &col2 = Preferences::inst()->color(Preferences::CGAL_EDGE_2D_COLOR); -		glColor3f(col2.redF(), col2.greenF(), col2.blueF()); - -		// Extract the boundary, including inner boundaries of the polygons -		for (fci_t fit = E.faces_begin(), facesend = E.faces_end(); fit != facesend; ++fit) -		{ -			bool fset = false; -			double fx = 0.0, fy = 0.0; -			heafcc_t fcirc(E.halfedge(fit)), fend(fcirc); -			CGAL_For_all(fcirc, fend) { -				if(E.is_standard(E.target(fcirc))) { -					Point p = E.point(E.target(fcirc)); -					double x = to_double(p.x()), y = to_double(p.y()); -					if (!fset) { -						glBegin(GL_LINE_STRIP); -						fx = x, fy = y; -						fset = true; -					} -					glVertex3d(x, y, -0.1); -				} -			} -			if (fset) { -				glVertex3d(fx, fy, -0.1); -				glEnd(); -			} -		} - -		glEnable(GL_DEPTH_TEST); -	} -	else if (m->root_N->dim == 3) -	{ -		Polyhedron *p = (Polyhedron*)m->cgal_ogl_p; -		if (!p) { -			Nef3_Converter<CGAL_Nef_polyhedron3>::setColor(Polyhedron::CGAL_NEF3_MARKED_FACET_COLOR, -																										 Preferences::inst()->color(Preferences::CGAL_FACE_BACK_COLOR).red(), -																										 Preferences::inst()->color(Preferences::CGAL_FACE_BACK_COLOR).green(), -																										 Preferences::inst()->color(Preferences::CGAL_FACE_BACK_COLOR).blue()); -			Nef3_Converter<CGAL_Nef_polyhedron3>::setColor(Polyhedron::CGAL_NEF3_UNMARKED_FACET_COLOR, -																										 Preferences::inst()->color(Preferences::CGAL_FACE_FRONT_COLOR).red(), -																										 Preferences::inst()->color(Preferences::CGAL_FACE_FRONT_COLOR).green(), -																										 Preferences::inst()->color(Preferences::CGAL_FACE_FRONT_COLOR).blue()); -			m->cgal_ogl_p = p = new Polyhedron(); -			Nef3_Converter<CGAL_Nef_polyhedron3>::convert_to_OGLPolyhedron(m->root_N->p3, p); -			p->init(); -		} -		if (m->viewActionCGALSurfaces->isChecked()) -			p->set_style(SNC_BOUNDARY); -		if (m->viewActionCGALGrid->isChecked()) -			p->set_style(SNC_SKELETON); -#if 0 -		p->draw(); -#else -		if (p->style == SNC_BOUNDARY) { -			glCallList(p->object_list_+2); -			if (m->viewActionShowEdges->isChecked()) { -				glDisable(GL_LIGHTING); -				glCallList(p->object_list_+1); -				glCallList(p->object_list_); -			} -		} else { -			glDisable(GL_LIGHTING); -			glCallList(p->object_list_+1); -			glCallList(p->object_list_); -		} -#endif -	} -} -  void MainWindow::viewModeCGALSurface()  {  	viewModeActionsUncheck();  	viewActionCGALSurfaces->setChecked(true); -	screen->setRenderFunc(renderGLviaCGAL, this); +	screen->setShowFaces(true); +	screen->setRenderer(this->cgalRenderer);  	screen->updateGL();  } @@ -1638,104 +1482,24 @@ void MainWindow::viewModeCGALGrid()  {  	viewModeActionsUncheck();  	viewActionCGALGrid->setChecked(true); -	screen->setRenderFunc(renderGLviaCGAL, this); -	screen->updateGL(); +	screen->setShowFaces(false); +	screen->setRenderer(this->cgalRenderer);  }  #endif /* ENABLE_CGAL */ -static void renderGLThrownTogetherChain(MainWindow *m, CSGChain *chain, bool highlight, bool background, bool fberror) -{ -	glDepthFunc(GL_LEQUAL); -	QHash<QPair<PolySet*,double*>,int> polySetVisitMark; -	bool showEdges = m->viewActionShowEdges->isChecked(); -	for (int i = 0; i < chain->polysets.size(); i++) { -		if (polySetVisitMark[QPair<PolySet*,double*>(chain->polysets[i], chain->matrices[i])]++ > 0) -			continue; -		double *m = chain->matrices[i]; -		glPushMatrix(); -		glMultMatrixd(m); -		int csgmode = chain->types[i] == CSGTerm::TYPE_DIFFERENCE ? PolySet::CSGMODE_DIFFERENCE : PolySet::CSGMODE_NORMAL; -		if (highlight) { -			chain->polysets[i]->render_surface(PolySet::COLORMODE_HIGHLIGHT, PolySet::csgmode_e(csgmode + 20), m); -			if (showEdges) { -				glDisable(GL_LIGHTING); -				chain->polysets[i]->render_edges(PolySet::COLORMODE_HIGHLIGHT, PolySet::csgmode_e(csgmode + 20)); -				glEnable(GL_LIGHTING); -			} -		} else if (background) { -			chain->polysets[i]->render_surface(PolySet::COLORMODE_BACKGROUND, PolySet::csgmode_e(csgmode + 10), m); -			if (showEdges) { -				glDisable(GL_LIGHTING); -				chain->polysets[i]->render_edges(PolySet::COLORMODE_BACKGROUND, PolySet::csgmode_e(csgmode + 10)); -				glEnable(GL_LIGHTING); -			} -		} else if (fberror) { -			if (highlight) { -				chain->polysets[i]->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode + 20), m); -			} else if (background) { -				chain->polysets[i]->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode + 10), m); -			} else { -				chain->polysets[i]->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode), m); -			} -		} else if (m[16] >= 0 || m[17] >= 0 || m[18] >= 0 || m[19] >= 0) { -			glColor4d(m[16], m[17], m[18], m[19]); -			chain->polysets[i]->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode), m); -			if (showEdges) { -				glDisable(GL_LIGHTING); -				glColor4d((m[16]+1)/2, (m[17]+1)/2, (m[18]+1)/2, 1.0); -				chain->polysets[i]->render_edges(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode)); -				glEnable(GL_LIGHTING); -			} -		} else if (chain->types[i] == CSGTerm::TYPE_DIFFERENCE) { -			chain->polysets[i]->render_surface(PolySet::COLORMODE_CUTOUT, PolySet::csgmode_e(csgmode), m); -			if (showEdges) { -				glDisable(GL_LIGHTING); -				chain->polysets[i]->render_edges(PolySet::COLORMODE_CUTOUT, PolySet::csgmode_e(csgmode)); -				glEnable(GL_LIGHTING); -			} -		} else { -			chain->polysets[i]->render_surface(PolySet::COLORMODE_MATERIAL, PolySet::csgmode_e(csgmode), m); -			if (showEdges) { -				glDisable(GL_LIGHTING); -				chain->polysets[i]->render_edges(PolySet::COLORMODE_MATERIAL, PolySet::csgmode_e(csgmode)); -				glEnable(GL_LIGHTING); -			} -		} -		glPopMatrix(); -	} -} - -static void renderGLThrownTogether(void *vp) -{ -	MainWindow *m = (MainWindow*)vp; -	if (m->root_chain) { -		glEnable(GL_CULL_FACE); -		glCullFace(GL_BACK); -		renderGLThrownTogetherChain(m, m->root_chain, false, false, false); -		glCullFace(GL_FRONT); -		glColor3ub(255, 0, 255); -		renderGLThrownTogetherChain(m, m->root_chain, false, false, true); -		glDisable(GL_CULL_FACE); -	} -	if (m->background_chain) -		renderGLThrownTogetherChain(m, m->background_chain, false, true, false); -	if (m->highlights_chain) -		renderGLThrownTogetherChain(m, m->highlights_chain, true, false, false); -} -  void MainWindow::viewModeThrownTogether()  {  	viewModeActionsUncheck();  	viewActionThrownTogether->setChecked(true); -	screen->setRenderFunc(renderGLThrownTogether, this); -	screen->updateGL(); +	screen->setRenderer(this->thrownTogetherRenderer);  }  void MainWindow::viewModeShowEdges()  {  	QSettings settings;  	settings.setValue("view/showEdges",viewActionShowEdges->isChecked()); +	screen->setShowEdges(viewActionShowEdges->isChecked());  	screen->updateGL();  } diff --git a/src/render-opencsg.cc b/src/opencsgrenderer.cc index f6d26ac..768176c 100644 --- a/src/render-opencsg.cc +++ b/src/opencsgrenderer.cc @@ -1,4 +1,30 @@ -#include "render-opencsg.h" +/* + *  OpenSCAD (www.openscad.org) + *  Copyright (C) 2009-2011 Clifford Wolf <clifford@clifford.at> and + *                          Marius Kintel <marius@kintel.net> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 2 of the License, or + *  (at your option) any later version. + * + *  As a special exception, you have permission to link this program + *  with the CGAL library and distribute executables, as long as you + *  follow the requirements of the GNU GPL in regard to all of the + *  software in the executable aside from CGAL. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + * + */ + +#include "opencsgrenderer.h"  #include "polyset.h"  #include "csgterm.h" @@ -18,7 +44,35 @@ public:  	}  }; -void renderCSGChainviaOpenCSG(CSGChain *chain, GLint *shaderinfo, bool highlight, bool background) +OpenCSGRenderer::OpenCSGRenderer(CSGChain *root_chain, CSGChain *highlights_chain, +																 CSGChain *background_chain, GLint *shaderinfo) +	: root_chain(root_chain), highlights_chain(highlights_chain),  +		background_chain(background_chain), shaderinfo(shaderinfo) +{ +} + +void OpenCSGRenderer::draw(bool showfaces, bool showedges) const +{ +	static int glew_initialized = 0; +	if (!glew_initialized) { +		glew_initialized = 1; +		glewInit(); +	} +	if (this->root_chain) { +		GLint *shaderinfo = this->shaderinfo; +		if (!shaderinfo[0]) shaderinfo = NULL; +		renderCSGChain(this->root_chain, showedges ? shaderinfo : NULL, false, false); +		if (this->background_chain) { +			renderCSGChain(this->background_chain, showedges ? shaderinfo : NULL, false, true); +		} +		if (this->highlights_chain) { +			renderCSGChain(this->highlights_chain, showedges ? shaderinfo : NULL, true, false); +		} +	} +} + +void OpenCSGRenderer::renderCSGChain(CSGChain *chain, GLint *shaderinfo,  +																		 bool highlight, bool background) const  {  	std::vector<OpenCSG::Primitive*> primitives;  	int j = 0; diff --git a/src/opencsgrenderer.h b/src/opencsgrenderer.h new file mode 100644 index 0000000..95ffc8e --- /dev/null +++ b/src/opencsgrenderer.h @@ -0,0 +1,24 @@ +#ifndef OPENCSGRENDERER_H_ +#define OPENCSGRENDERER_H_ + +#include "renderer.h" +#include <GL/glew.h> // this must be included before the GL headers +#include <qgl.h> + +class OpenCSGRenderer : public Renderer +{ +public: +	OpenCSGRenderer(class CSGChain *root_chain, CSGChain *highlights_chain,  +									CSGChain *background_chain, GLint *shaderinfo); +	void draw(bool showfaces, bool showedges) const; +private: +	void renderCSGChain(class CSGChain *chain, GLint *shaderinfo,  +											bool highlight, bool background) const; + +	CSGChain *root_chain; +	CSGChain *highlights_chain; +	CSGChain *background_chain; +	GLint *shaderinfo; +}; + +#endif diff --git a/src/polyset.cc b/src/polyset.cc index cccdaad..e34aeb3 100644 --- a/src/polyset.cc +++ b/src/polyset.cc @@ -665,7 +665,7 @@ CGAL_Nef_polyhedron PolySet::render_cgal_nef_polyhedron() const  		return CGAL_Nef_polyhedron(N);  		}  		catch (CGAL::Assertion_exception e) { -			PRINTF("ERROR: Illegal polygonal object - make sure all polygons are defined with the same winding order. Skipping affected object."); +			PRINTF("CGAL error: %s", e.what());  			CGAL::set_error_behaviour(old_behaviour);  			return CGAL_Nef_polyhedron();  		} diff --git a/src/polyset.h b/src/polyset.h index 0914e91..8712ff2 100644 --- a/src/polyset.h +++ b/src/polyset.h @@ -1,10 +1,7 @@  #ifndef POLYSET_H_  #define POLYSET_H_ -#ifdef ENABLE_OPENCSG -// this must be included before the GL headers -#  include <GL/glew.h> -#endif +#include <GL/glew.h> // this must be included before the GL headers  #include <qgl.h>  #include "grid.h" diff --git a/src/projection.cc b/src/projection.cc index f41ba56..d87b366 100644 --- a/src/projection.cc +++ b/src/projection.cc @@ -124,7 +124,7 @@ PolySet *ProjectionNode::render_polyset(render_mode_e) const  	}    }    catch (CGAL::Assertion_exception e) { -		PRINTF("ERROR: Illegal polygonal object - make sure all polygons are defined with the same winding order. Skipping affected object."); +		PRINTF("CGAL error: %s", e.what());  		CGAL::set_error_behaviour(old_behaviour);  		return ps;  	} diff --git a/src/render-opencsg.h b/src/render-opencsg.h deleted file mode 100644 index 9433cbe..0000000 --- a/src/render-opencsg.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef RENDER_OPENCSG_H_ -#define RENDER_OPENCSG_H_ - -#include <GL/glew.h> - -void renderCSGChainviaOpenCSG(class CSGChain *chain, GLint *shaderinfo, bool highlight, bool background); - -#endif diff --git a/src/renderer.h b/src/renderer.h new file mode 100644 index 0000000..3c25e98 --- /dev/null +++ b/src/renderer.h @@ -0,0 +1,11 @@ +#ifndef RENDERER_H_ +#define RENDERER_H_ + +class Renderer +{ +public: +	virtual ~Renderer() {} +	virtual void draw(bool showfaces, bool showedges) const = 0; +}; + +#endif // RENDERER_H diff --git a/src/throwntogetherrenderer.cc b/src/throwntogetherrenderer.cc new file mode 100644 index 0000000..0a0c9c8 --- /dev/null +++ b/src/throwntogetherrenderer.cc @@ -0,0 +1,120 @@ +/* + *  OpenSCAD (www.openscad.org) + *  Copyright (C) 2009-2011 Clifford Wolf <clifford@clifford.at> and + *                          Marius Kintel <marius@kintel.net> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 2 of the License, or + *  (at your option) any later version. + * + *  As a special exception, you have permission to link this program + *  with the CGAL library and distribute executables, as long as you + *  follow the requirements of the GNU GPL in regard to all of the + *  software in the executable aside from CGAL. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + * + */ + +#include "ThrownTogetherRenderer.h" +#include "polyset.h" +#include "csgterm.h" + +#include <GL/glew.h> // this must be included before the GL headers +#include <qgl.h> + +ThrownTogetherRenderer::ThrownTogetherRenderer(CSGChain *root_chain,  +																							 CSGChain *highlights_chain, +																							 CSGChain *background_chain) +	: root_chain(root_chain), highlights_chain(highlights_chain),  +		background_chain(background_chain) +{ +} + +void ThrownTogetherRenderer::draw(bool showfaces, bool showedges) const +{ +	if (this->root_chain) { +		glEnable(GL_CULL_FACE); +		glCullFace(GL_BACK); +		renderCSGChain(this->root_chain, false, false, showedges, false); +		glCullFace(GL_FRONT); +		glColor3ub(255, 0, 255); +		renderCSGChain(this->root_chain, false, false, showedges, true); +		glDisable(GL_CULL_FACE); +	} +	if (this->background_chain) +		renderCSGChain(this->background_chain, false, true, showedges, false); +	if (this->highlights_chain) +		renderCSGChain(this->highlights_chain, true, false, showedges, false); +} + +void ThrownTogetherRenderer::renderCSGChain(CSGChain *chain, bool highlight, +																						bool background, bool showedges,  +																						bool fberror) const +{ +	glDepthFunc(GL_LEQUAL); +	QHash<QPair<PolySet*,double*>,int> polySetVisitMark; +	for (int i = 0; i < chain->polysets.size(); i++) { +		if (polySetVisitMark[QPair<PolySet*,double*>(chain->polysets[i], chain->matrices[i])]++ > 0) +			continue; +		double *m = chain->matrices[i]; +		glPushMatrix(); +		glMultMatrixd(m); +		int csgmode = chain->types[i] == CSGTerm::TYPE_DIFFERENCE ? PolySet::CSGMODE_DIFFERENCE : PolySet::CSGMODE_NORMAL; +		if (highlight) { +			chain->polysets[i]->render_surface(PolySet::COLORMODE_HIGHLIGHT, PolySet::csgmode_e(csgmode + 20), m); +			if (showedges) { +				glDisable(GL_LIGHTING); +				chain->polysets[i]->render_edges(PolySet::COLORMODE_HIGHLIGHT, PolySet::csgmode_e(csgmode + 20)); +				glEnable(GL_LIGHTING); +			} +		} else if (background) { +			chain->polysets[i]->render_surface(PolySet::COLORMODE_BACKGROUND, PolySet::csgmode_e(csgmode + 10), m); +			if (showedges) { +				glDisable(GL_LIGHTING); +				chain->polysets[i]->render_edges(PolySet::COLORMODE_BACKGROUND, PolySet::csgmode_e(csgmode + 10)); +				glEnable(GL_LIGHTING); +			} +		} else if (fberror) { +			if (highlight) { +				chain->polysets[i]->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode + 20), m); +			} else if (background) { +				chain->polysets[i]->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode + 10), m); +			} else { +				chain->polysets[i]->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode), m); +			} +		} else if (m[16] >= 0 || m[17] >= 0 || m[18] >= 0 || m[19] >= 0) { +			glColor4d(m[16], m[17], m[18], m[19]); +			chain->polysets[i]->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode), m); +			if (showedges) { +				glDisable(GL_LIGHTING); +				glColor4d((m[16]+1)/2, (m[17]+1)/2, (m[18]+1)/2, 1.0); +				chain->polysets[i]->render_edges(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode)); +				glEnable(GL_LIGHTING); +			} +		} else if (chain->types[i] == CSGTerm::TYPE_DIFFERENCE) { +			chain->polysets[i]->render_surface(PolySet::COLORMODE_CUTOUT, PolySet::csgmode_e(csgmode), m); +			if (showedges) { +				glDisable(GL_LIGHTING); +				chain->polysets[i]->render_edges(PolySet::COLORMODE_CUTOUT, PolySet::csgmode_e(csgmode)); +				glEnable(GL_LIGHTING); +			} +		} else { +			chain->polysets[i]->render_surface(PolySet::COLORMODE_MATERIAL, PolySet::csgmode_e(csgmode), m); +			if (showedges) { +				glDisable(GL_LIGHTING); +				chain->polysets[i]->render_edges(PolySet::COLORMODE_MATERIAL, PolySet::csgmode_e(csgmode)); +				glEnable(GL_LIGHTING); +			} +		} +		glPopMatrix(); +	} +} diff --git a/src/throwntogetherrenderer.h b/src/throwntogetherrenderer.h new file mode 100644 index 0000000..09d13f3 --- /dev/null +++ b/src/throwntogetherrenderer.h @@ -0,0 +1,21 @@ +#ifndef THROWNTOGETHERRENDERER_H_ +#define THROWNTOGETHERRENDERER_H_ + +#include "renderer.h" + +class ThrownTogetherRenderer : public Renderer +{ +public: +	ThrownTogetherRenderer(class CSGChain *root_chain, +												 CSGChain *highlights_chain, CSGChain *background_chain); +	void draw(bool showfaces, bool showedges) const; +private: +	void renderCSGChain(CSGChain *chain, bool highlight, bool background, bool showedges,  +											bool fberror) const; + +	CSGChain *root_chain; +	CSGChain *highlights_chain; +	CSGChain *background_chain; +}; + +#endif  | 
