Merge remote branch 'upstream/master'

stl_dim
Don Bright 2011-08-03 16:37:51 -05:00
commit f78d4f74b2
25 changed files with 1455 additions and 1106 deletions

View File

@ -52,7 +52,6 @@ o non-convex minkowski example from chrysn fails with an exception
USER INTERFACE USER INTERFACE
-------------- --------------
o Preferences o Preferences
- Remember settings done in menus between sessions (automatic reload, perspective, show*, hide*)
- Beautify color schemes - Beautify color schemes
- Color schemes read from file - Color schemes read from file
- Color scheme editor - Color scheme editor
@ -60,7 +59,6 @@ o Preferences
- pointsize - pointsize
- OpenGL params - OpenGL params
- Default language feature settings - Default language feature settings
- Auto-view CSG/thrown together on load
- Make the library search path configurable? - Make the library search path configurable?
o Export etc.: automatically add missing extension as in SaveAs o Export etc.: automatically add missing extension as in SaveAs
o MDI o MDI
@ -166,7 +164,6 @@ o Mesh optimization on STL export
- Remove super small triangles (all sides are short) - Remove super small triangles (all sides are short)
- Replace super thin triangles (one h is short) - Replace super thin triangles (one h is short)
o Misc o Misc
- Add symbolic colors to the color() statement
- When specifying a transparency with the color() statement, - When specifying a transparency with the color() statement,
the object is not sorted and will be rendered wrongly 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) - Go through default values of parameters (e.g. cube() has x,y,z=1 while linear_extrude() has height=100)

View File

@ -3,8 +3,8 @@ opencsg {
CONFIG += glew CONFIG += glew
include(glew.pri) include(glew.pri)
HEADERS += src/render-opencsg.h HEADERS += src/opencsgrenderer.h
SOURCES += src/render-opencsg.cc SOURCES += src/opencsgrenderer.cc
isEmpty(DEPLOYDIR) { isEmpty(DEPLOYDIR) {
# Optionally specify location of OpenCSG using the # Optionally specify location of OpenCSG using the

View File

@ -118,7 +118,11 @@ include(boost.pri)
FORMS += src/MainWindow.ui \ FORMS += src/MainWindow.ui \
src/Preferences.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/GLView.h \
src/MainWindow.h \ src/MainWindow.h \
src/Preferences.h \ src/Preferences.h \
@ -146,6 +150,8 @@ HEADERS += src/CGAL_renderer.h \
SOURCES += src/openscad.cc \ SOURCES += src/openscad.cc \
src/mainwin.cc \ src/mainwin.cc \
src/cgalrenderer.cc \
src/throwntogetherrenderer.cc \
src/glview.cc \ src/glview.cc \
src/export.cc \ src/export.cc \
src/value.cc \ src/value.cc \

View File

@ -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;
};

View File

@ -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 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/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 +++ 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 /// Texture stuff
GLenum textureTarget; GLenum textureTarget;
@ -1112,7 +1112,9 @@ diff -ru OpenCSG-1.3.0/src/frameBufferObject.h OpenCSG-1.3.0-mac/src/frameBuffer
+ GLuint depthID; + GLuint depthID;
- unsigned int framebufferID; - unsigned int framebufferID;
- int oldFramebufferID;
+ GLuint framebufferID; + GLuint framebufferID;
+ GLint oldFramebufferID;
bool initialized; bool initialized;
}; };

View File

@ -119,7 +119,9 @@ build_cgal()
version=$1 version=$1
echo "Building CGAL" $version "..." echo "Building CGAL" $version "..."
cd $BASEDIR/src 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 tar xzf CGAL-$version.tar.gz
cd CGAL-$version cd CGAL-$version
# We build a static lib. Not really necessary, but it's well tested. # 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 mkdir -p $SRCDIR $DEPLOYDIR
build_gmp 5.0.1 build_gmp 5.0.1
build_mpfr 3.0.1 build_mpfr 3.0.1
build_boost 1.46.1 build_boost 1.47.0
build_cgal 3.7 # NB! For CGAL, also update the actual download URL in the function
build_glew 1.5.8 build_cgal 3.8
build_glew 1.6.0
build_opencsg 1.3.0 build_opencsg 1.3.0

View File

@ -1,660 +1,104 @@
// Copyright (c) 1997-2002 Max-Planck-Institute Saarbruecken (Germany). /*
// All rights reserved. * OpenSCAD (www.openscad.org)
// * Copyright (C) 2009-2011 Clifford Wolf <clifford@clifford.at> and
// This file is part of CGAL (www.cgal.org); you may redistribute it under * Marius Kintel <marius@kintel.net>
// the terms of the Q Public License version 1.0. *
// See the file LICENSE.QPL distributed with CGAL. * 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
// Licensees holding a valid commercial license may use this file in * the Free Software Foundation; either version 2 of the License, or
// accordance with the commercial license agreement provided with the software. * (at your option) any later version.
// *
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * As a special exception, you have permission to link this program
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * with the CGAL library and distribute executables, as long as you
// * follow the requirements of the GNU GPL in regard to all of the
// $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Nef_3/include/CGAL/Nef_3/OGL_helper.h $ * software in the executable aside from CGAL.
// $Id: OGL_helper.h 44713 2008-08-01 15:38:58Z hachenb $ *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// Author(s) : Peter Hachenberger <hachenberger@mpi-sb.mpg.de> * 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_NEF_OPENGL_HELPER_H #ifndef CGAL_RENDERER_H
#define CGAL_NEF_OPENGL_HELPER_H #define CGAL_RENDERER_H
#include <CGAL/Nef_S2/OGL_base_object.h> #include "OGL_helper.h"
#include <CGAL/Simple_cartesian.h> #undef CGAL_NEF3_MARKED_VERTEX_COLOR
#include <CGAL/Nef_3/SNC_decorator.h> #undef CGAL_NEF3_MARKED_EDGE_COLOR
#include <qgl.h> #undef CGAL_NEF3_MARKED_FACET_COLOR
#include <cstdlib>
#ifdef _WIN32 #undef CGAL_NEF3_UNMARKED_VERTEX_COLOR
#define CGAL_GLU_TESS_CALLBACK CALLBACK #undef CGAL_NEF3_UNMARKED_EDGE_COLOR
#else #undef CGAL_NEF3_UNMARKED_FACET_COLOR
#define CGAL_GLU_TESS_CALLBACK
#endif
#ifdef __APPLE__ using CGAL::OGL::SNC_BOUNDARY;
# include <AvailabilityMacros.h> using CGAL::OGL::SNC_SKELETON;
#endif
#if defined __APPLE__ && !defined MAC_OS_X_VERSION_10_5 class Polyhedron : public CGAL::OGL::Polyhedron
#define CGAL_GLU_TESS_DOTS ... {
#else public:
#define CGAL_GLU_TESS_DOTS
#endif
using namespace CGAL; enum RenderColor {
using namespace CGAL::OGL; 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
};
namespace OpenSCAD { 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);
}
namespace OGL { void draw(bool showedges) const {
if(this->style == SNC_BOUNDARY) {
// ---------------------------------------------------------------------------- glCallList(this->object_list_+2);
// Drawable double types: if(showedges) {
// ---------------------------------------------------------------------------- glDisable(GL_LIGHTING);
glCallList(this->object_list_+1);
typedef CGAL::Simple_cartesian<double> DKernel; glCallList(this->object_list_);
typedef DKernel::Point_3 Double_point; }
typedef DKernel::Vector_3 Double_vector; } else {
typedef DKernel::Segment_3 Double_segment; glDisable(GL_LIGHTING);
typedef DKernel::Aff_transformation_3 Affine_3; glCallList(this->object_list_+1);
glCallList(this->object_list_);
// 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);
} }
}
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;
}
inline void CGAL_GLU_TESS_CALLBACK vertexCallback(GLvoid* vertex, CGAL::Color getEdgeColor(Edge_iterator e) const {
GLvoid* user) CGAL::Color c = e->mark() ? colors[CGAL_NEF3_UNMARKED_EDGE_COLOR] : colors[CGAL_NEF3_MARKED_EDGE_COLOR];
{ GLdouble* pc(static_cast<GLdouble*>(vertex)); return c;
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) CGAL::Color getFacetColor(Halffacet_iterator f) const {
{ CGAL::Color c = f->mark() ? colors[CGAL_NEF3_UNMARKED_FACET_COLOR] : colors[CGAL_NEF3_MARKED_FACET_COLOR];
static std::list<GLdouble*> pcache; return c;
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();
}
}
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];
enum { SNC_AXES}; }; // Polyhedron
enum { SNC_BOUNDARY, SNC_SKELETON };
class Polyhedron : public CGAL::OGL::OGL_base_object { #endif // CGAL_RENDERER_H
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

View File

@ -12,24 +12,31 @@
class GLView : public QGLWidget class GLView : public QGLWidget
{ {
Q_OBJECT 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 showAxes READ showAxes WRITE setShowAxes);
Q_PROPERTY(bool showCrosshairs READ showCrosshairs WRITE setShowCrosshairs); Q_PROPERTY(bool showCrosshairs READ showCrosshairs WRITE setShowCrosshairs);
Q_PROPERTY(bool orthoMode READ orthoMode WRITE setOrthoMode); Q_PROPERTY(bool orthoMode READ orthoMode WRITE setOrthoMode);
public: public:
GLView(QWidget *parent = NULL); GLView(QWidget *parent = NULL);
void setRenderFunc(void (*func)(void*), void *userdata); void setRenderer(class Renderer* r);
#ifdef ENABLE_OPENCSG #ifdef ENABLE_OPENCSG
bool hasOpenCSGSupport() { return this->opencsg_support; } bool hasOpenCSGSupport() { return this->opencsg_support; }
#endif #endif
// Properties // 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; } bool showAxes() const { return this->showaxes; }
void setShowAxes(bool enabled) { this->showaxes = enabled; } void setShowAxes(bool enabled) { this->showaxes = enabled; }
bool showCrosshairs() const { return this->showcrosshairs; } bool showCrosshairs() const { return this->showcrosshairs; }
void setShowCrosshairs(bool enabled) { this->showcrosshairs = enabled; } void setShowCrosshairs(bool enabled) { this->showcrosshairs = enabled; }
bool orthoMode() const { return this->orthomode; } bool orthoMode() const { return this->orthomode; }
void setOrthoMode(bool enabled) { this->orthomode = enabled; } void setOrthoMode(bool enabled) { this->orthomode = enabled; }
public:
QLabel *statusLabel; QLabel *statusLabel;
double object_rot_x; double object_rot_x;
double object_rot_y; double object_rot_y;
@ -45,9 +52,10 @@ public:
#endif #endif
private: private:
void (*renderfunc)(void*); Renderer *renderer;
void *renderfunc_vp;
bool showfaces;
bool showedges;
bool showaxes; bool showaxes;
bool showcrosshairs; bool showcrosshairs;
bool orthomode; bool orthomode;
@ -57,8 +65,7 @@ private:
double w_h_ratio; double w_h_ratio;
bool mouse_drag_active; bool mouse_drag_active;
int last_mouse_x; QPoint last_mouse;
int last_mouse_y;
void keyPressEvent(QKeyEvent *event); void keyPressEvent(QKeyEvent *event);
void wheelEvent(QWheelEvent *event); void wheelEvent(QWheelEvent *event);
@ -68,7 +75,10 @@ private:
void initializeGL(); void initializeGL();
void resizeGL(int w, int h); void resizeGL(int w, int h);
void setupPerspective();
void setupOrtho(double distance,bool offset=false);
void paintGL(); void paintGL();
void normalizeAngle(GLdouble& angle);
#ifdef ENABLE_OPENCSG #ifdef ENABLE_OPENCSG
private slots: private slots:

View File

@ -38,17 +38,18 @@ public:
class CSGChain *root_chain; class CSGChain *root_chain;
#ifdef ENABLE_CGAL #ifdef ENABLE_CGAL
class CGAL_Nef_polyhedron *root_N; class CGAL_Nef_polyhedron *root_N;
bool recreate_cgal_ogl_p; class CGALRenderer *cgalRenderer;
void *cgal_ogl_p;
PolySet *cgal_ogl_ps;
#endif #endif
#ifdef ENABLE_OPENCSG
class OpenCSGRenderer *opencsgRenderer;
#endif
class ThrownTogetherRenderer *thrownTogetherRenderer;
QVector<CSGTerm*> highlight_terms; QVector<CSGTerm*> highlight_terms;
CSGChain *highlights_chain; CSGChain *highlights_chain;
QVector<CSGTerm*> background_terms; QVector<CSGTerm*> background_terms;
CSGChain *background_chain; CSGChain *background_chain;
QString last_compiled_doc; QString last_compiled_doc;
bool enableOpenCSG;
static const int maxRecentFiles = 10; static const int maxRecentFiles = 10;
QAction *actionRecentFile[maxRecentFiles]; QAction *actionRecentFile[maxRecentFiles];

704
src/OGL_helper.h Normal file
View File

@ -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

126
src/cgalrenderer.cc Normal file
View File

@ -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);
}
}

20
src/cgalrenderer.h Normal file
View File

@ -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

View File

@ -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()); cgal_nef_cache.insert(cache_id, new cgal_nef_cache_entry(N), N.weight());
} }
catch (CGAL::Assertion_exception e) { 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); CGAL::set_error_behaviour(old_behaviour);

View File

@ -158,7 +158,7 @@ void dxf_tesselate(PolySet *ps, DxfData *dxf, double rot, bool up, bool /* do_tr
} }
catch (CGAL::Assertion_exception e) { 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); CGAL::set_error_behaviour(old_behaviour);
return; return;
} }

View File

@ -26,6 +26,7 @@
#include "GLView.h" #include "GLView.h"
#include "Preferences.h" #include "Preferences.h"
#include "renderer.h"
#include <QApplication> #include <QApplication>
#include <QWheelEvent> #include <QWheelEvent>
@ -41,9 +42,13 @@
#include "mathc99.h" #include "mathc99.h"
#include <stdio.h> #include <stdio.h>
#ifdef ENABLE_OPENCSG
# include <opencsg.h>
#endif
#define FAR_FAR_AWAY 100000.0 #define FAR_FAR_AWAY 100000.0
GLView::GLView(QWidget *parent) : QGLWidget(parent) GLView::GLView(QWidget *parent) : QGLWidget(parent), renderer(NULL)
{ {
viewer_distance = 500; viewer_distance = 500;
object_rot_x = 35; object_rot_x = 35;
@ -54,15 +59,12 @@ GLView::GLView(QWidget *parent) : QGLWidget(parent)
object_trans_z = 0; object_trans_z = 0;
mouse_drag_active = false; mouse_drag_active = false;
last_mouse_x = 0;
last_mouse_y = 0;
orthomode = false; orthomode = false;
showaxes = false; showaxes = false;
showcrosshairs = false; showcrosshairs = false;
showedges = false;
renderfunc = NULL; showfaces = true;
renderfunc_vp = NULL;
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
shaderinfo[i] = 0; shaderinfo[i] = 0;
@ -77,10 +79,10 @@ GLView::GLView(QWidget *parent) : QGLWidget(parent)
#endif #endif
} }
void GLView::setRenderFunc(void (*func)(void*), void *userdata) void GLView::setRenderer(Renderer *r)
{ {
this->renderfunc = func; this->renderer = r;
this->renderfunc_vp = userdata; updateGL();
} }
void GLView::initializeGL() void GLView::initializeGL()
@ -91,6 +93,22 @@ void GLView::initializeGL()
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 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 #ifdef ENABLE_OPENCSG
GLenum err = glewInit(); GLenum err = glewInit();
if (GLEW_OK != err) { if (GLEW_OK != err) {
@ -256,43 +274,47 @@ void GLView::resizeGL(int w, int h)
#endif #endif
glViewport(0, 0, w, h); glViewport(0, 0, w, h);
w_h_ratio = sqrt((double)w / (double)h); w_h_ratio = sqrt((double)w / (double)h);
setupPerspective();
}
void GLView::setupPerspective()
{
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() void GLView::paintGL()
{ {
glEnable(GL_LIGHTING);
if (orthomode)
setupOrtho(viewer_distance);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
const QColor &bgcol = Preferences::inst()->color(Preferences::BACKGROUND_COLOR); const QColor &bgcol = Preferences::inst()->color(Preferences::BACKGROUND_COLOR);
glClearColor(bgcol.redF(), bgcol.greenF(), bgcol.blueF(), 0.0); glClearColor(bgcol.redF(), bgcol.greenF(), bgcol.blueF(), 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
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); gluLookAt(0.0, -viewer_distance, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0);
glMatrixMode(GL_MODELVIEW); glTranslated(object_trans_x, object_trans_y, object_trans_z);
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};
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);
glRotated(object_rot_x, 1.0, 0.0, 0.0); glRotated(object_rot_x, 1.0, 0.0, 0.0);
glRotated(object_rot_y, 0.0, 1.0, 0.0); glRotated(object_rot_y, 0.0, 1.0, 0.0);
@ -315,8 +337,6 @@ void GLView::paintGL()
glEnd(); glEnd();
} }
glTranslated(object_trans_x, object_trans_y, object_trans_z);
// Large gray axis cross inline with the model // Large gray axis cross inline with the model
// FIXME: This is always gray - adjust color to keep contrast with background // FIXME: This is always gray - adjust color to keep contrast with background
if (showaxes) if (showaxes)
@ -324,12 +344,13 @@ void GLView::paintGL()
glLineWidth(1); glLineWidth(1);
glColor3d(0.5, 0.5, 0.5); glColor3d(0.5, 0.5, 0.5);
glBegin(GL_LINES); glBegin(GL_LINES);
glVertex3d(-viewer_distance/10, 0, 0); double l = viewer_distance/10;
glVertex3d(+viewer_distance/10, 0, 0); glVertex3d(-l, 0, 0);
glVertex3d(0, -viewer_distance/10, 0); glVertex3d(+l, 0, 0);
glVertex3d(0, +viewer_distance/10, 0); glVertex3d(0, -l, 0);
glVertex3d(0, 0, -viewer_distance/10); glVertex3d(0, +l, 0);
glVertex3d(0, 0, +viewer_distance/10); glVertex3d(0, 0, -l);
glVertex3d(0, 0, +l);
glEnd(); glEnd();
} }
@ -340,20 +361,21 @@ void GLView::paintGL()
glLineWidth(2); glLineWidth(2);
glColor3d(1.0, 0.0, 0.0); glColor3d(1.0, 0.0, 0.0);
if (renderfunc) if (this->renderer) {
renderfunc(renderfunc_vp); #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 // Small axis cross in the lower left corner
if (showaxes) if (showaxes)
{ {
glDepthFunc(GL_ALWAYS); glDepthFunc(GL_ALWAYS);
glMatrixMode(GL_PROJECTION); setupOrtho(1000,true);
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);
gluLookAt(0.0, -1000, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0); gluLookAt(0.0, -1000, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0);
glMatrixMode(GL_MODELVIEW); 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);
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(); glEnd();
//Restore perspective for next paint
if(!orthomode)
setupPerspective();
} }
if (statusLabel) { if (statusLabel) {
@ -452,101 +478,48 @@ void GLView::wheelEvent(QWheelEvent *event)
void GLView::mousePressEvent(QMouseEvent *event) void GLView::mousePressEvent(QMouseEvent *event)
{ {
mouse_drag_active = true; mouse_drag_active = true;
last_mouse_x = event->globalX(); last_mouse = event->globalPos();
last_mouse_y = event->globalY();
grabMouse(); grabMouse();
setFocus(); 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]; while(angle < 0)
for (int x = 0; x < 4; x++) angle += 360;
for (int y = 0; y < 4; y++) while(angle > 360)
{ angle -= 360;
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];
} }
void GLView::mouseMoveEvent(QMouseEvent *event) void GLView::mouseMoveEvent(QMouseEvent *event)
{ {
int this_mouse_x = event->globalX(); QPoint this_mouse = event->globalPos();
int this_mouse_y = event->globalY(); 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 (mouse_drag_active) {
if ((event->buttons() & Qt::LeftButton) != 0) { 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) if ((QApplication::keyboardModifiers() & Qt::ShiftModifier) != 0)
object_rot_y += (this_mouse_x-last_mouse_x) * 0.7; object_rot_y += dx;
else else
object_rot_z += (this_mouse_x-last_mouse_x) * 0.7; object_rot_z += dx;
while (object_rot_x < 0)
object_rot_x += 360; normalizeAngle(object_rot_x);
while (object_rot_x >= 360) normalizeAngle(object_rot_y);
object_rot_x -= 360; normalizeAngle(object_rot_z);
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;
} else { } 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) { if ((QApplication::keyboardModifiers() & Qt::ShiftModifier) != 0) {
vec[3] = 0; viewer_distance += (GLdouble)dy;
vec[7] = my; } else {
vec[11] = 0; 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(); updateGL();
emit doAnimateUpdate(); emit doAnimateUpdate();
} }
last_mouse_x = this_mouse_x; last_mouse = this_mouse;
last_mouse_y = this_mouse_y;
} }
void GLView::mouseReleaseEvent(QMouseEvent*) void GLView::mouseReleaseEvent(QMouseEvent*)

View File

@ -40,11 +40,12 @@
#include "dxftess.h" #include "dxftess.h"
#include "progress.h" #include "progress.h"
#ifdef ENABLE_OPENCSG #ifdef ENABLE_OPENCSG
#include "render-opencsg.h" #include "opencsgRenderer.h"
#endif #endif
#ifdef USE_PROGRESSWIDGET #ifdef USE_PROGRESSWIDGET
#include "ProgressWidget.h" #include "ProgressWidget.h"
#endif #endif
#include "thrownTogetherRenderer.h"
#include <QMenu> #include <QMenu>
#include <QTime> #include <QTime>
@ -75,32 +76,8 @@
#ifdef ENABLE_CGAL #ifdef ENABLE_CGAL
#if 1 #include "cgalrenderer.h"
#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
#endif // ENABLE_CGAL #endif // ENABLE_CGAL
#define QUOTE(x__) # x__ #define QUOTE(x__) # x__
@ -175,15 +152,16 @@ MainWindow::MainWindow(const QString &filename)
root_chain = NULL; root_chain = NULL;
#ifdef ENABLE_CGAL #ifdef ENABLE_CGAL
this->root_N = NULL; this->root_N = NULL;
this->recreate_cgal_ogl_p = false; this->cgalRenderer = NULL;
cgal_ogl_p = NULL;
cgal_ogl_ps = NULL;
#endif #endif
#ifdef ENABLE_OPENCSG
this->opencsgRenderer = NULL;
#endif
this->thrownTogetherRenderer = NULL;
highlights_chain = NULL; highlights_chain = NULL;
background_chain = NULL; background_chain = NULL;
root_node = NULL; root_node = NULL;
enableOpenCSG = false;
tval = 0; tval = 0;
fps = 0; fps = 0;
@ -327,11 +305,6 @@ MainWindow::MainWindow(const QString &filename)
connect(this->viewActionOrthogonal, SIGNAL(triggered()), this, SLOT(viewOrthogonal())); connect(this->viewActionOrthogonal, SIGNAL(triggered()), this, SLOT(viewOrthogonal()));
connect(this->viewActionHide, SIGNAL(triggered()), this, SLOT(hideConsole())); 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 // Help menu
connect(this->helpActionAbout, SIGNAL(triggered()), this, SLOT(helpAbout())); connect(this->helpActionAbout, SIGNAL(triggered()), this, SLOT(helpAbout()));
connect(this->helpActionHomepage, SIGNAL(triggered()), this, SLOT(helpHomepage())); connect(this->helpActionHomepage, SIGNAL(triggered()), this, SLOT(helpHomepage()));
@ -431,19 +404,14 @@ MainWindow::loadDesignSettings()
MainWindow::~MainWindow() MainWindow::~MainWindow()
{ {
if (root_module) if (root_module) delete root_module;
delete root_module; if (root_node) delete root_node;
if (root_node)
delete root_node;
#ifdef ENABLE_CGAL #ifdef ENABLE_CGAL
if (this->root_N) if (this->root_N) delete this->root_N;
delete this->root_N; delete this->cgalRenderer;
if (cgal_ogl_p) { #endif
Polyhedron *p = (Polyhedron*)cgal_ogl_p; #ifdef ENABLE_OPENCSG
delete p; delete this->opencsgRenderer;
}
if (cgal_ogl_ps)
cgal_ogl_ps->unlink();
#endif #endif
} }
@ -612,6 +580,16 @@ void MainWindow::compile(bool procevents)
if (procevents) if (procevents)
QApplication::processEvents(); 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 // Remove previous CSG tree
if (root_module) { if (root_module) {
@ -656,7 +634,6 @@ void MainWindow::compile(bool procevents)
background_chain = NULL; background_chain = NULL;
} }
root_node = NULL; root_node = NULL;
enableOpenCSG = false;
// Initialize special variables // Initialize special variables
root_ctx.set_variable("$t", Value(e_tval->text().toDouble())); 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 = new CSGChain();
root_chain->import(root_norm_term); 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) if (highlight_terms.size() > 0)
{ {
PRINTF("Compiling highlights (%d CSG Trees)...", highlight_terms.size()); PRINTF("Compiling highlights (%d CSG Trees)...", highlight_terms.size());
@ -866,6 +836,20 @@ void MainWindow::compileCSG(bool procevents)
background_chain->import(background_terms[i]); 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."); PRINT("CSG generation finished.");
int s = t.elapsed() / 1000; int s = t.elapsed() / 1000;
@ -1132,16 +1116,16 @@ void MainWindow::actionCompile()
if (this->root_node) compileCSG(!viewActionAnimate->isChecked()); if (this->root_node) compileCSG(!viewActionAnimate->isChecked());
// Go to non-CGAL view mode // Go to non-CGAL view mode
if (!viewActionOpenCSG->isChecked() && !viewActionThrownTogether->isChecked()) { if (viewActionThrownTogether->isChecked()) {
viewModeThrownTogether();
}
else {
#ifdef ENABLE_OPENCSG #ifdef ENABLE_OPENCSG
viewModeOpenCSG(); viewModeOpenCSG();
#else #else
viewModeThrownTogether(); viewModeThrownTogether();
#endif #endif
} }
else {
screen->updateGL();
}
if (viewActionAnimate->isChecked() && e_dump->isChecked()) { if (viewActionAnimate->isChecked() && e_dump->isChecked()) {
QImage img = screen->grabFrameBuffer(); QImage img = screen->grabFrameBuffer();
@ -1167,10 +1151,12 @@ void MainWindow::actionRenderCGAL()
if (!root_module || !root_node) if (!root_module || !root_node)
return; return;
this->screen->setRenderer(NULL);
delete this->cgalRenderer;
this->cgalRenderer = NULL;
if (this->root_N) { if (this->root_N) {
delete this->root_N; delete this->root_N;
this->root_N = NULL; this->root_N = NULL;
this->recreate_cgal_ogl_p = true;
} }
PRINT("Rendering Polygon Mesh using CGAL..."); PRINT("Rendering Polygon Mesh using CGAL...");
@ -1254,10 +1240,13 @@ void MainWindow::actionRenderCGAL()
int s = t.elapsed() / 1000; int s = t.elapsed() / 1000;
PRINTF("Total rendering time: %d hours, %d minutes, %d seconds", s / (60*60), (s / 60) % 60, s % 60); 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(); viewModeCGALSurface();
} else {
screen->updateGL();
} }
PRINT("Rendering finished."); PRINT("Rendering finished.");
@ -1461,37 +1450,6 @@ void MainWindow::viewModeActionsUncheck()
#ifdef ENABLE_OPENCSG #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. Go to the OpenCSG view mode.
Falls back to thrown together mode if OpenCSG is not available Falls back to thrown together mode if OpenCSG is not available
@ -1501,8 +1459,7 @@ void MainWindow::viewModeOpenCSG()
if (screen->hasOpenCSGSupport()) { if (screen->hasOpenCSGSupport()) {
viewModeActionsUncheck(); viewModeActionsUncheck();
viewActionOpenCSG->setChecked(true); viewActionOpenCSG->setChecked(true);
screen->setRenderFunc(renderGLviaOpenCSG, this); screen->setRenderer(this->opencsgRenderer ? (Renderer *)this->opencsgRenderer : (Renderer *)this->thrownTogetherRenderer);
screen->updateGL();
} else { } else {
viewModeThrownTogether(); viewModeThrownTogether();
} }
@ -1512,125 +1469,12 @@ void MainWindow::viewModeOpenCSG()
#ifdef ENABLE_CGAL #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() void MainWindow::viewModeCGALSurface()
{ {
viewModeActionsUncheck(); viewModeActionsUncheck();
viewActionCGALSurfaces->setChecked(true); viewActionCGALSurfaces->setChecked(true);
screen->setRenderFunc(renderGLviaCGAL, this); screen->setShowFaces(true);
screen->setRenderer(this->cgalRenderer);
screen->updateGL(); screen->updateGL();
} }
@ -1638,104 +1482,24 @@ void MainWindow::viewModeCGALGrid()
{ {
viewModeActionsUncheck(); viewModeActionsUncheck();
viewActionCGALGrid->setChecked(true); viewActionCGALGrid->setChecked(true);
screen->setRenderFunc(renderGLviaCGAL, this); screen->setShowFaces(false);
screen->updateGL(); screen->setRenderer(this->cgalRenderer);
} }
#endif /* ENABLE_CGAL */ #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() void MainWindow::viewModeThrownTogether()
{ {
viewModeActionsUncheck(); viewModeActionsUncheck();
viewActionThrownTogether->setChecked(true); viewActionThrownTogether->setChecked(true);
screen->setRenderFunc(renderGLThrownTogether, this); screen->setRenderer(this->thrownTogetherRenderer);
screen->updateGL();
} }
void MainWindow::viewModeShowEdges() void MainWindow::viewModeShowEdges()
{ {
QSettings settings; QSettings settings;
settings.setValue("view/showEdges",viewActionShowEdges->isChecked()); settings.setValue("view/showEdges",viewActionShowEdges->isChecked());
screen->setShowEdges(viewActionShowEdges->isChecked());
screen->updateGL(); screen->updateGL();
} }

View File

@ -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 "polyset.h"
#include "csgterm.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; std::vector<OpenCSG::Primitive*> primitives;
int j = 0; int j = 0;

24
src/opencsgrenderer.h Normal file
View File

@ -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

View File

@ -665,7 +665,7 @@ CGAL_Nef_polyhedron PolySet::render_cgal_nef_polyhedron() const
return CGAL_Nef_polyhedron(N); return CGAL_Nef_polyhedron(N);
} }
catch (CGAL::Assertion_exception e) { 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); CGAL::set_error_behaviour(old_behaviour);
return CGAL_Nef_polyhedron(); return CGAL_Nef_polyhedron();
} }

View File

@ -1,10 +1,7 @@
#ifndef POLYSET_H_ #ifndef POLYSET_H_
#define POLYSET_H_ #define POLYSET_H_
#ifdef ENABLE_OPENCSG #include <GL/glew.h> // this must be included before the GL headers
// this must be included before the GL headers
# include <GL/glew.h>
#endif
#include <qgl.h> #include <qgl.h>
#include "grid.h" #include "grid.h"

View File

@ -124,7 +124,7 @@ PolySet *ProjectionNode::render_polyset(render_mode_e) const
} }
} }
catch (CGAL::Assertion_exception e) { 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); CGAL::set_error_behaviour(old_behaviour);
return ps; return ps;
} }

View File

@ -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

11
src/renderer.h Normal file
View File

@ -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

View File

@ -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();
}
}

View File

@ -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