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

View File

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

View File

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

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
--- OpenCSG-1.3.0/src/frameBufferObject.h 2010-02-06 21:35:10.000000000 +0100
+++ OpenCSG-1.3.0-mac/src/frameBufferObject.h 2010-05-09 02:51:36.000000000 +0200
@@ -79,10 +79,10 @@
@@ -79,11 +79,11 @@
/// Texture stuff
GLenum textureTarget;
@ -1112,7 +1112,9 @@ diff -ru OpenCSG-1.3.0/src/frameBufferObject.h OpenCSG-1.3.0-mac/src/frameBuffer
+ GLuint depthID;
- unsigned int framebufferID;
- int oldFramebufferID;
+ GLuint framebufferID;
+ GLint oldFramebufferID;
bool initialized;
};

View File

@ -119,7 +119,9 @@ build_cgal()
version=$1
echo "Building CGAL" $version "..."
cd $BASEDIR/src
curl -O https://gforge.inria.fr/frs/download.php/27641/CGAL-$version.tar.gz
rm -rf CGAL*
curl -O https://gforge.inria.fr/frs/download.php/28500/CGAL-$version.tar.gz
# curl -O https://gforge.inria.fr/frs/download.php/27641/CGAL-$version.tar.gz
tar xzf CGAL-$version.tar.gz
cd CGAL-$version
# We build a static lib. Not really necessary, but it's well tested.
@ -159,7 +161,8 @@ echo "Using basedir:" $BASEDIR
mkdir -p $SRCDIR $DEPLOYDIR
build_gmp 5.0.1
build_mpfr 3.0.1
build_boost 1.46.1
build_cgal 3.7
build_glew 1.5.8
build_boost 1.47.0
# NB! For CGAL, also update the actual download URL in the function
build_cgal 3.8
build_glew 1.6.0
build_opencsg 1.3.0

View File

@ -1,660 +1,104 @@
// Copyright (c) 1997-2002 Max-Planck-Institute Saarbruecken (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org); you may redistribute it under
// the terms of the Q Public License version 1.0.
// See the file LICENSE.QPL distributed with CGAL.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Nef_3/include/CGAL/Nef_3/OGL_helper.h $
// $Id: OGL_helper.h 44713 2008-08-01 15:38:58Z hachenb $
//
//
// Author(s) : Peter Hachenberger <hachenberger@mpi-sb.mpg.de>
/*
* OpenSCAD (www.openscad.org)
* Copyright (C) 2009-2011 Clifford Wolf <clifford@clifford.at> and
* Marius Kintel <marius@kintel.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* As a special exception, you have permission to link this program
* with the CGAL library and distribute executables, as long as you
* follow the requirements of the GNU GPL in regard to all of the
* software in the executable aside from CGAL.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef CGAL_NEF_OPENGL_HELPER_H
#define CGAL_NEF_OPENGL_HELPER_H
#ifndef CGAL_RENDERER_H
#define CGAL_RENDERER_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>
#include "OGL_helper.h"
#undef CGAL_NEF3_MARKED_VERTEX_COLOR
#undef CGAL_NEF3_MARKED_EDGE_COLOR
#undef CGAL_NEF3_MARKED_FACET_COLOR
#ifdef _WIN32
#define CGAL_GLU_TESS_CALLBACK CALLBACK
#else
#define CGAL_GLU_TESS_CALLBACK
#endif
#undef CGAL_NEF3_UNMARKED_VERTEX_COLOR
#undef CGAL_NEF3_UNMARKED_EDGE_COLOR
#undef CGAL_NEF3_UNMARKED_FACET_COLOR
#ifdef __APPLE__
# include <AvailabilityMacros.h>
#endif
using CGAL::OGL::SNC_BOUNDARY;
using CGAL::OGL::SNC_SKELETON;
#if defined __APPLE__ && !defined MAC_OS_X_VERSION_10_5
#define CGAL_GLU_TESS_DOTS ...
#else
#define CGAL_GLU_TESS_DOTS
#endif
class Polyhedron : public CGAL::OGL::Polyhedron
{
public:
using namespace CGAL;
using namespace CGAL::OGL;
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
};
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 {
// ----------------------------------------------------------------------------
// 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);
void draw(bool showedges) const {
if(this->style == SNC_BOUNDARY) {
glCallList(this->object_list_+2);
if(showedges) {
glDisable(GL_LIGHTING);
glCallList(this->object_list_+1);
glCallList(this->object_list_);
}
} else {
glDisable(GL_LIGHTING);
glCallList(this->object_list_+1);
glCallList(this->object_list_);
}
}
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,
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);
}
CGAL::Color getEdgeColor(Edge_iterator e) const {
CGAL::Color c = e->mark() ? colors[CGAL_NEF3_UNMARKED_EDGE_COLOR] : colors[CGAL_NEF3_MARKED_EDGE_COLOR];
return c;
}
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();
}
}
CGAL::Color getFacetColor(Halffacet_iterator f) const {
CGAL::Color c = f->mark() ? colors[CGAL_NEF3_UNMARKED_FACET_COLOR] : colors[CGAL_NEF3_MARKED_FACET_COLOR];
return c;
}
void setColor(Polyhedron::RenderColor color_index,
unsigned char r, unsigned char g, unsigned char b) {
assert(color_index < Polyhedron::NUM_COLORS);
this->colors[color_index] = CGAL::Color(r,g,b);
}
private:
CGAL::Color colors[NUM_COLORS];
enum { SNC_AXES};
enum { SNC_BOUNDARY, SNC_SKELETON };
}; // Polyhedron
class Polyhedron : public CGAL::OGL::OGL_base_object {
public:
std::list<DPoint> vertices_;
std::list<DSegment> edges_;
std::list<DFacet> halffacets_;
GLuint object_list_;
bool init_;
Bbox_3 bbox_;
int style;
std::vector<bool> switches;
typedef std::list<DPoint>::const_iterator Vertex_iterator;
typedef std::list<DSegment>::const_iterator Edge_iterator;
typedef std::list<DFacet>::const_iterator Halffacet_iterator;
enum RenderColor {
CGAL_NEF3_MARKED_VERTEX_COLOR,
CGAL_NEF3_MARKED_EDGE_COLOR,
CGAL_NEF3_MARKED_FACET_COLOR,
CGAL_NEF3_UNMARKED_VERTEX_COLOR,
CGAL_NEF3_UNMARKED_EDGE_COLOR,
CGAL_NEF3_UNMARKED_FACET_COLOR,
NUM_COLORS
};
static unsigned char colors[NUM_COLORS][3];
public:
Polyhedron() : bbox_(-1,-1,-1,1,1,1), switches(1) {
object_list_ = 0;
init_ = false;
style = SNC_BOUNDARY;
switches[SNC_AXES] = false;
}
~Polyhedron()
{ if (object_list_) glDeleteLists(object_list_, 4); }
void push_back(const Double_point& p, bool m) {
vertices_.push_back(DPoint(p,m));
}
void push_back(const Double_segment& s, bool m)
{ edges_.push_back(DSegment(s,m)); }
void push_back(const DFacet& f)
{ halffacets_.push_back(f); }
void toggle(int index) {
switches[index] = !switches[index];
}
void set_style(int index) {
style = index;
}
bool is_initialized() const { return init_; }
Bbox_3 bbox() const { return bbox_; }
Bbox_3& bbox() { return bbox_; }
void draw(Vertex_iterator v) const {
// CGAL_NEF_TRACEN("drawing vertex "<<*v);
unsigned char *c = v->mark() ? colors[CGAL_NEF3_UNMARKED_VERTEX_COLOR] : colors[CGAL_NEF3_MARKED_VERTEX_COLOR];
glPointSize(10);
glColor3ubv(c);
glBegin(GL_POINTS);
glVertex3d(v->x(),v->y(),v->z());
#ifdef CGAL_NEF_EMPHASIZE_VERTEX
glColor3ub(255,0,0);
glVertex3d(CGAL_NEF_EMPHASIZE_VERTEX);
#endif
glEnd();
}
void draw(Edge_iterator e) const {
// CGAL_NEF_TRACEN("drawing edge "<<*e);
Double_point p = e->source(), q = e->target();
unsigned char *c = e->mark() ? colors[CGAL_NEF3_UNMARKED_EDGE_COLOR] : colors[CGAL_NEF3_MARKED_EDGE_COLOR];
glLineWidth(5);
glColor3ubv(c);
glBegin(GL_LINE_STRIP);
glVertex3d(p.x(), p.y(), p.z());
glVertex3d(q.x(), q.y(), q.z());
glEnd();
}
void draw(Halffacet_iterator f) const {
// CGAL_NEF_TRACEN("drawing facet "<<(f->debug(),""));
GLUtesselator* tess_ = gluNewTess();
gluTessCallback(tess_, GLenum(GLU_TESS_VERTEX_DATA),
(GLvoid (CGAL_GLU_TESS_CALLBACK *)(CGAL_GLU_TESS_DOTS)) &vertexCallback);
gluTessCallback(tess_, GLenum(GLU_TESS_COMBINE),
(GLvoid (CGAL_GLU_TESS_CALLBACK *)(CGAL_GLU_TESS_DOTS)) &combineCallback);
gluTessCallback(tess_, GLenum(GLU_TESS_BEGIN),
(GLvoid (CGAL_GLU_TESS_CALLBACK *)(CGAL_GLU_TESS_DOTS)) &beginCallback);
gluTessCallback(tess_, GLenum(GLU_TESS_END),
(GLvoid (CGAL_GLU_TESS_CALLBACK *)(CGAL_GLU_TESS_DOTS)) &endCallback);
gluTessCallback(tess_, GLenum(GLU_TESS_ERROR),
(GLvoid (CGAL_GLU_TESS_CALLBACK *)(CGAL_GLU_TESS_DOTS)) &errorCallback);
gluTessProperty(tess_, GLenum(GLU_TESS_WINDING_RULE),
GLU_TESS_WINDING_POSITIVE);
DFacet::Coord_const_iterator cit;
unsigned char *c = f->mark() ? colors[CGAL_NEF3_UNMARKED_FACET_COLOR] : colors[CGAL_NEF3_MARKED_FACET_COLOR];
glColor3ubv(c);
gluTessBeginPolygon(tess_,f->normal());
// CGAL_NEF_TRACEN(" ");
// CGAL_NEF_TRACEN("Begin Polygon");
gluTessNormal(tess_,f->dx(),f->dy(),f->dz());
// forall facet cycles of f:
for(unsigned i = 0; i < f->number_of_facet_cycles(); ++i) {
gluTessBeginContour(tess_);
// CGAL_NEF_TRACEN(" Begin Contour");
// put all vertices in facet cycle into contour:
for(cit = f->facet_cycle_begin(i);
cit != f->facet_cycle_end(i); ++cit) {
gluTessVertex(tess_, *cit, *cit);
// CGAL_NEF_TRACEN(" add Vertex");
}
gluTessEndContour(tess_);
// CGAL_NEF_TRACEN(" End Contour");
}
gluTessEndPolygon(tess_);
// CGAL_NEF_TRACEN("End Polygon");
gluDeleteTess(tess_);
combineCallback(NULL, NULL, NULL, NULL);
}
void construct_axes() const
{
glLineWidth(2.0);
// red x-axis
glColor3f(1.0,0.0,0.0);
glBegin(GL_LINES);
glVertex3f(0.0,0.0,0.0);
glVertex3f(5000.0,0.0,0.0);
glEnd();
// green y-axis
glColor3f(0.0,1.0,0.0);
glBegin(GL_LINES);
glVertex3f(0.0,0.0,0.0);
glVertex3f(0.0,5000.0,0.0);
glEnd();
// blue z-axis and equator
glColor3f(0.0,0.0,1.0);
glBegin(GL_LINES);
glVertex3f(0.0,0.0,0.0);
glVertex3f(0.0,0.0,5000.0);
glEnd();
// six coordinate points in pink:
glPointSize(10);
glBegin(GL_POINTS);
glColor3f(1.0,0.0,0.0);
glVertex3d(5,0,0);
glColor3f(0.0,1.0,0.0);
glVertex3d(0,5,0);
glColor3f(0.0,0.0,1.0);
glVertex3d(0,0,5);
glEnd();
}
void fill_display_lists() {
glNewList(object_list_, GL_COMPILE);
Vertex_iterator v;
for(v=vertices_.begin();v!=vertices_.end();++v)
draw(v);
glEndList();
glNewList(object_list_+1, GL_COMPILE);
Edge_iterator e;
for(e=edges_.begin();e!=edges_.end();++e)
draw(e);
glEndList();
glNewList(object_list_+2, GL_COMPILE);
Halffacet_iterator f;
for(f=halffacets_.begin();f!=halffacets_.end();++f)
draw(f);
glEndList();
glNewList(object_list_+3, GL_COMPILE); // axes:
construct_axes();
glEndList();
}
void init() {
if (init_) return;
init_ = true;
switches[SNC_AXES] = false;
style = SNC_BOUNDARY;
object_list_ = glGenLists(4);
CGAL_assertion(object_list_);
fill_display_lists();
}
void draw() const
{
if (!is_initialized()) const_cast<Polyhedron&>(*this).init();
double l = (std::max)( (std::max)( bbox().xmax() - bbox().xmin(),
bbox().ymax() - bbox().ymin()),
bbox().zmax() - bbox().zmin());
if ( l < 1) // make sure that a single point doesn't screw up here
l = 1;
glScaled( 4.0/l, 4.0/l, 4.0/l);
glTranslated( -(bbox().xmax() + bbox().xmin()) / 2.0,
-(bbox().ymax() + bbox().ymin()) / 2.0,
-(bbox().zmax() + bbox().zmin()) / 2.0);
if (style == SNC_BOUNDARY) {
//glEnable(GL_LIGHTING);
glCallList(object_list_+2); // facets
//glDisable(GL_LIGHTING);
}
// move edges and vertices a bit towards the view-point,
// i.e., 1/100th of the unit vector in camera space
// double f = l / 4.0 / 100.0;
// glTranslated( z_vec[0] * f, z_vec[1] * f, z_vec[2] * f);
glCallList(object_list_+1); // edges
glCallList(object_list_); // vertices
if (switches[SNC_AXES]) glCallList(object_list_+3); // axis
}
void debug(std::ostream& os = std::cerr) const
{
os << "OGL::Polyhedron" << std::endl;
os << "Vertices:" << std::endl;
Vertex_iterator v;
for(v=vertices_.begin();v!=vertices_.end();++v)
os << " "<<*v<<", mark="<<v->mark()<<std::endl;
os << "Edges:" << std::endl;
Edge_iterator e;
for(e=edges_.begin();e!=edges_.end();++e)
os << " "<<*e<<", mark="<<e->mark()<<std::endl;
os << "Facets:" << std::endl;
Halffacet_iterator f;
for(f=halffacets_.begin();f!=halffacets_.end();++f)
f->debug(); os << std::endl;
os << std::endl;
}
}; // Polyhedron
unsigned char Polyhedron::colors[][3] = {
{0xb7, 0xe8, 0x5c},
{0xab, 0xd8, 0x56},
{0x9d, 0xcb, 0x51},
{0xff, 0xf6, 0x7c},
{0xff, 0xec, 0x5e},
{0xf9, 0xd7, 0x2c}
};
template<typename Nef_polyhedron>
class Nef3_Converter {
typedef typename Nef_polyhedron::SNC_structure SNC_structure;
typedef CGAL::SNC_decorator<SNC_structure> Base;
typedef CGAL::SNC_FM_decorator<SNC_structure> FM_decorator;
public:
typedef typename SNC_structure::Vertex_const_iterator Vertex_const_iterator;
typedef typename SNC_structure::Halfedge_const_iterator Halfedge_const_iterator;
typedef typename SNC_structure::Halffacet_const_iterator Halffacet_const_iterator;
typedef typename SNC_structure::Halffacet_cycle_const_iterator Halffacet_cycle_const_iterator;
typedef typename SNC_structure::Object_const_handle Object_const_handle;
typedef typename SNC_structure::SHalfedge_const_handle SHalfedge_const_handle;
typedef typename SNC_structure::SHalfloop_const_handle SHalfloop_const_handle;
typedef typename SNC_structure::Vertex_const_handle Vertex_const_handle;
typedef typename SNC_structure::Halfedge_const_handle Halfedge_const_handle;
typedef typename SNC_structure::Halffacet_const_handle Halffacet_const_handle;
typedef typename SNC_structure::Point_3 Point_3;
typedef typename SNC_structure::Vector_3 Vector_3;
typedef typename SNC_structure::Segment_3 Segment_3;
typedef typename SNC_structure::Plane_3 Plane_3;
typedef typename SNC_structure::Mark Mark;
typedef typename SNC_structure::SHalfedge_around_facet_const_circulator
SHalfedge_around_facet_const_circulator;
private:
static OGL::Double_point double_point(const Point_3& p)
{ return OGL::Double_point(CGAL::to_double(p.x()),
CGAL::to_double(p.y()),
CGAL::to_double(p.z())); }
static OGL::Double_segment double_segment(const Segment_3& s)
{ return OGL::Double_segment(double_point(s.source()),
double_point(s.target())); }
static void draw(Vertex_const_handle v, const Nef_polyhedron& ,
Polyhedron& P) {
Point_3 bp = v->point();
// CGAL_NEF_TRACEN("vertex " << bp);
P.push_back(double_point(bp), v->mark());
}
static void draw(Halfedge_const_handle e, const Nef_polyhedron& ,
Polyhedron& P) {
Vertex_const_handle s = e->source();
Vertex_const_handle t = e->twin()->source();
Segment_3 seg(s->point(),t->point());
// CGAL_NEF_TRACEN("edge " << seg);
P.push_back(double_segment(seg), e->mark());
}
static void draw(Halffacet_const_handle f, const Nef_polyhedron& ,
Polyhedron& P) {
OGL::DFacet g;
Halffacet_cycle_const_iterator fc; // all facet cycles:
CGAL_forall_facet_cycles_of(fc,f)
if ( fc.is_shalfedge() ) { // non-trivial facet cycle
g.new_facet_cycle();
SHalfedge_const_handle h = fc;
SHalfedge_around_facet_const_circulator hc(h), he(hc);
CGAL_For_all(hc,he){ // all vertex coordinates in facet cycle
Point_3 sp = hc->source()->source()->point();
// CGAL_NEF_TRACEN(" ");CGAL_NEF_TRACEN("facet" << sp);
g.push_back_vertex(double_point(sp));
}
}
Vector_3 v = f->plane().orthogonal_vector();
g.set_normal(CGAL::to_double(v.x()),
CGAL::to_double(v.y()),
CGAL::to_double(v.z()),
f->mark());
P.push_back(g);
}
// Returns the bounding box of the finite vertices of the polyhedron.
// Returns $[-1,+1]^3$ as bounding box if no finite vertex exists.
static Bbox_3 bounded_bbox(const Nef_polyhedron& N) {
bool first_vertex = true;
Bbox_3 bbox( -1.0, -1.0, -1.0, 1.0, 1.0, 1.0);
Vertex_const_iterator vi;
CGAL_forall_vertices(vi, N) {
Point_3 p = vi->point();
double x = CGAL::to_double(p.hx());
double y = CGAL::to_double(p.hy());
double z = CGAL::to_double(p.hz());
double w = CGAL::to_double(p.hw());
if (N.is_standard(vi)) {
if(first_vertex) {
bbox = Bbox_3(x/w, y/w, z/w, x/w, y/w, z/w);
first_vertex = false;
} else {
bbox = bbox + Bbox_3(x/w, y/w, z/w, x/w, y/w, z/w);
first_vertex = false;
}
}
}
return bbox;
}
static void set_R(Bbox_3& bbox, const Nef_polyhedron& N) {
if(N.is_standard_kernel()) return;
double size = abs(bbox.xmin());
if(size < bbox.xmax()) size = bbox.xmax();
if(size < bbox.ymin()) size = bbox.ymin();
if(size < bbox.ymax()) size = bbox.ymax();
if(size < bbox.zmin()) size = bbox.zmin();
if(size < bbox.zmax()) size = bbox.zmax();
N.set_size_of_infimaximal_box(size*50);
// CGAL_NEF_TRACEN("set infi box size to " << size);
Vertex_const_iterator vi;
CGAL_forall_vertices(vi, N)
if(N.is_standard(vi))
return;
bbox = Bbox_3(bbox.xmin()*10,bbox.ymin()*10,bbox.zmin()*10,
bbox.xmax()*10,bbox.ymax()*10,bbox.zmax()*10);
}
public:
static void setColor(Polyhedron::RenderColor color_index,
unsigned char r, unsigned char g, unsigned char b) {
assert(color_index < Polyhedron::NUM_COLORS);
Polyhedron::colors[color_index][0] = r;
Polyhedron::colors[color_index][1] = g;
Polyhedron::colors[color_index][2] = b;
}
static void convert_to_OGLPolyhedron(const Nef_polyhedron& N, Polyhedron* P) {
Bbox_3 bbox(bounded_bbox(N));
set_R(bbox,N);
P->bbox() = bbox;
Vertex_const_iterator v;
CGAL_forall_vertices(v,*N.sncp()) draw(v,N,*P);
Halfedge_const_iterator e;
CGAL_forall_edges(e,*N.sncp()) draw(e,N,*P);
Halffacet_const_iterator f;
CGAL_forall_facets(f,*N.sncp()) draw(f,N,*P);
}
}; // Nef3_Converter
} // namespace OGL
} // namespace OpenSCAD
#endif // CGAL_NEF_OPENGL_HELPER_H
#endif // CGAL_RENDERER_H

View File

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

View File

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

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

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) {
PRINTF("ERROR: Polygon intersection detected. Skipping affected polygons.");
PRINTF("CGAL error: %s", e.what());
CGAL::set_error_behaviour(old_behaviour);
return;
}

View File

@ -26,6 +26,7 @@
#include "GLView.h"
#include "Preferences.h"
#include "renderer.h"
#include <QApplication>
#include <QWheelEvent>
@ -41,9 +42,13 @@
#include "mathc99.h"
#include <stdio.h>
#ifdef ENABLE_OPENCSG
# include <opencsg.h>
#endif
#define FAR_FAR_AWAY 100000.0
GLView::GLView(QWidget *parent) : QGLWidget(parent)
GLView::GLView(QWidget *parent) : QGLWidget(parent), renderer(NULL)
{
viewer_distance = 500;
object_rot_x = 35;
@ -54,15 +59,12 @@ GLView::GLView(QWidget *parent) : QGLWidget(parent)
object_trans_z = 0;
mouse_drag_active = false;
last_mouse_x = 0;
last_mouse_y = 0;
orthomode = false;
showaxes = false;
showcrosshairs = false;
renderfunc = NULL;
renderfunc_vp = NULL;
showedges = false;
showfaces = true;
for (int i = 0; i < 10; i++)
shaderinfo[i] = 0;
@ -77,10 +79,10 @@ GLView::GLView(QWidget *parent) : QGLWidget(parent)
#endif
}
void GLView::setRenderFunc(void (*func)(void*), void *userdata)
void GLView::setRenderer(Renderer *r)
{
this->renderfunc = func;
this->renderfunc_vp = userdata;
this->renderer = r;
updateGL();
}
void GLView::initializeGL()
@ -91,6 +93,22 @@ void GLView::initializeGL()
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
GLfloat light_diffuse[] = {1.0, 1.0, 1.0, 1.0};
GLfloat light_position0[] = {-1.0, -1.0, +1.0, 0.0};
GLfloat light_position1[] = {+1.0, +1.0, -1.0, 0.0};
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_POSITION, light_position0);
glEnable(GL_LIGHT0);
glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT1, GL_POSITION, light_position1);
glEnable(GL_LIGHT1);
glEnable(GL_LIGHTING);
glEnable(GL_NORMALIZE);
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);
#ifdef ENABLE_OPENCSG
GLenum err = glewInit();
if (GLEW_OK != err) {
@ -256,43 +274,47 @@ void GLView::resizeGL(int w, int h)
#endif
glViewport(0, 0, w, h);
w_h_ratio = sqrt((double)w / (double)h);
setupPerspective();
}
void GLView::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()
{
glEnable(GL_LIGHTING);
if (orthomode)
setupOrtho(viewer_distance);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
const QColor &bgcol = Preferences::inst()->color(Preferences::BACKGROUND_COLOR);
glClearColor(bgcol.redF(), bgcol.greenF(), bgcol.blueF(), 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
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);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
GLfloat light_diffuse[] = {1.0, 1.0, 1.0, 1.0};
GLfloat light_position0[] = {-1.0, -1.0, +1.0, 0.0};
GLfloat light_position1[] = {+1.0, +1.0, -1.0, 0.0};
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);
glTranslated(object_trans_x, object_trans_y, object_trans_z);
glRotated(object_rot_x, 1.0, 0.0, 0.0);
glRotated(object_rot_y, 0.0, 1.0, 0.0);
@ -315,8 +337,6 @@ void GLView::paintGL()
glEnd();
}
glTranslated(object_trans_x, object_trans_y, object_trans_z);
// Large gray axis cross inline with the model
// FIXME: This is always gray - adjust color to keep contrast with background
if (showaxes)
@ -324,12 +344,13 @@ void GLView::paintGL()
glLineWidth(1);
glColor3d(0.5, 0.5, 0.5);
glBegin(GL_LINES);
glVertex3d(-viewer_distance/10, 0, 0);
glVertex3d(+viewer_distance/10, 0, 0);
glVertex3d(0, -viewer_distance/10, 0);
glVertex3d(0, +viewer_distance/10, 0);
glVertex3d(0, 0, -viewer_distance/10);
glVertex3d(0, 0, +viewer_distance/10);
double l = viewer_distance/10;
glVertex3d(-l, 0, 0);
glVertex3d(+l, 0, 0);
glVertex3d(0, -l, 0);
glVertex3d(0, +l, 0);
glVertex3d(0, 0, -l);
glVertex3d(0, 0, +l);
glEnd();
}
@ -340,20 +361,21 @@ void GLView::paintGL()
glLineWidth(2);
glColor3d(1.0, 0.0, 0.0);
if (renderfunc)
renderfunc(renderfunc_vp);
if (this->renderer) {
#if defined(ENABLE_MDI) && defined(ENABLE_OPENCSG)
// FIXME: This belongs in the OpenCSG renderer, but it doesn't know about this ID yet
OpenCSG::setContext(this->opencsg_id);
#endif
this->renderer->draw(showfaces, showedges);
}
// Small axis cross in the lower left corner
if (showaxes)
{
glDepthFunc(GL_ALWAYS);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glTranslated(-0.8, -0.8, 0);
glOrtho(-w_h_ratio*1000/10, +w_h_ratio*1000/10,
-(1/w_h_ratio)*1000/10, +(1/w_h_ratio)*1000/10,
-FAR_FAR_AWAY, +FAR_FAR_AWAY);
setupOrtho(1000,true);
gluLookAt(0.0, -1000, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0);
glMatrixMode(GL_MODELVIEW);
@ -418,6 +440,10 @@ void GLView::paintGL()
glVertex3d(zlabel_x-3, zlabel_y+3, 0); glVertex3d(zlabel_x+3, zlabel_y+3, 0);
glVertex3d(zlabel_x-3, zlabel_y-3, 0); glVertex3d(zlabel_x+3, zlabel_y+3, 0);
glEnd();
//Restore perspective for next paint
if(!orthomode)
setupPerspective();
}
if (statusLabel) {
@ -452,101 +478,48 @@ void GLView::wheelEvent(QWheelEvent *event)
void GLView::mousePressEvent(QMouseEvent *event)
{
mouse_drag_active = true;
last_mouse_x = event->globalX();
last_mouse_y = event->globalY();
last_mouse = event->globalPos();
grabMouse();
setFocus();
}
static void mat_id(double *trg)
{
for (int i = 0; i < 16; i++)
trg[i] = i%5 == 0;
}
static void mat_mul(double *trg, const double *m1, const double *m2)
void GLView::normalizeAngle(GLdouble& angle)
{
double m[16];
for (int x = 0; x < 4; x++)
for (int y = 0; y < 4; y++)
{
m[x+y*4] = 0;
for (int i = 0; i < 4; i++)
m[x+y*4] += m1[i+y*4] * m2[x+i*4];
}
for (int i = 0; i < 16; i++)
trg[i] = m[i];
}
static void mat_rot(double *trg, double angle, double x, double y, double z)
{
double s = sin(M_PI*angle/180), c = cos(M_PI*angle/180);
double cc = 1 - c;
double m[16] = {
x*x*cc+c, x*y*cc-z*s, x*z*cc+y*s, 0,
y*x*cc+z*s, y*y*cc+c, y*z*cc-x*s, 0,
x*z*cc-y*s, y*z*cc+x*s, z*z*cc+c, 0,
0, 0, 0, 1
};
for (int i = 0; i < 16; i++)
trg[i] = m[i];
while(angle < 0)
angle += 360;
while(angle > 360)
angle -= 360;
}
void GLView::mouseMoveEvent(QMouseEvent *event)
{
int this_mouse_x = event->globalX();
int this_mouse_y = event->globalY();
QPoint this_mouse = event->globalPos();
double dx = (this_mouse.x()-last_mouse.x()) * 0.7;
double dy = (this_mouse.y()-last_mouse.y()) * 0.7;
if (mouse_drag_active) {
if ((event->buttons() & Qt::LeftButton) != 0) {
object_rot_x += (this_mouse_y-last_mouse_y) * 0.7;
object_rot_x += dy;
if ((QApplication::keyboardModifiers() & Qt::ShiftModifier) != 0)
object_rot_y += (this_mouse_x-last_mouse_x) * 0.7;
object_rot_y += dx;
else
object_rot_z += (this_mouse_x-last_mouse_x) * 0.7;
while (object_rot_x < 0)
object_rot_x += 360;
while (object_rot_x >= 360)
object_rot_x -= 360;
while (object_rot_y < 0)
object_rot_y += 360;
while (object_rot_y >= 360)
object_rot_y -= 360;
while (object_rot_z < 0)
object_rot_z += 360;
while (object_rot_z >= 360)
object_rot_z -= 360;
object_rot_z += dx;
normalizeAngle(object_rot_x);
normalizeAngle(object_rot_y);
normalizeAngle(object_rot_z);
} else {
double mx = +(this_mouse_x-last_mouse_x) * viewer_distance/1000;
double my = -(this_mouse_y-last_mouse_y) * viewer_distance/1000;
double rx[16], ry[16], rz[16], tm[16];
mat_rot(rx, -object_rot_x, 1.0, 0.0, 0.0);
mat_rot(ry, -object_rot_y, 0.0, 1.0, 0.0);
mat_rot(rz, -object_rot_z, 0.0, 0.0, 1.0);
mat_id(tm);
mat_mul(tm, rx, tm);
mat_mul(tm, ry, tm);
mat_mul(tm, rz, tm);
double vec[16] = {
0, 0, 0, mx,
0, 0, 0, 0,
0, 0, 0, my,
0, 0, 0, 1
};
if ((QApplication::keyboardModifiers() & Qt::ShiftModifier) != 0) {
vec[3] = 0;
vec[7] = my;
vec[11] = 0;
viewer_distance += (GLdouble)dy;
} else {
object_trans_x += dx;
object_trans_z -= dy;
}
mat_mul(tm, tm, vec);
object_trans_x += tm[3];
object_trans_y += tm[7];
object_trans_z += tm[11];
}
updateGL();
emit doAnimateUpdate();
}
last_mouse_x = this_mouse_x;
last_mouse_y = this_mouse_y;
last_mouse = this_mouse;
}
void GLView::mouseReleaseEvent(QMouseEvent*)

View File

@ -40,11 +40,12 @@
#include "dxftess.h"
#include "progress.h"
#ifdef ENABLE_OPENCSG
#include "render-opencsg.h"
#include "opencsgRenderer.h"
#endif
#ifdef USE_PROGRESSWIDGET
#include "ProgressWidget.h"
#endif
#include "thrownTogetherRenderer.h"
#include <QMenu>
#include <QTime>
@ -75,32 +76,8 @@
#ifdef ENABLE_CGAL
#if 1
#include "CGAL_renderer.h"
using OpenSCAD::OGL::Polyhedron;
using OpenSCAD::OGL::SNC_BOUNDARY;
using OpenSCAD::OGL::SNC_SKELETON;
using OpenSCAD::OGL::Nef3_Converter;
#else
// a little hackish: we need access to default-private members of
// CGAL::OGL::Nef3_Converter so we can implement our own draw function
// that does not scale the model. so we define 'class' to 'struct'
// for this header..
//
// theoretically there could be two problems:
// 1.) defining language keyword with the pre processor is illegal afair
// 2.) the compiler could use a different memory layout or name mangling for structs
//
// both does not seam to be the case with todays compilers...
//
#define class struct
#include <CGAL/Nef_3/OGL_helper.h>
#undef class
using CGAL::OGL::Polyhedron;
using CGAL::OGL::SNC_BOUNDARY;
using CGAL::OGL::SNC_SKELETON;
using CGAL::OGL::Nef3_Converter;
#endif
#include "cgalrenderer.h"
#endif // ENABLE_CGAL
#define QUOTE(x__) # x__
@ -175,15 +152,16 @@ MainWindow::MainWindow(const QString &filename)
root_chain = NULL;
#ifdef ENABLE_CGAL
this->root_N = NULL;
this->recreate_cgal_ogl_p = false;
cgal_ogl_p = NULL;
cgal_ogl_ps = NULL;
this->cgalRenderer = NULL;
#endif
#ifdef ENABLE_OPENCSG
this->opencsgRenderer = NULL;
#endif
this->thrownTogetherRenderer = NULL;
highlights_chain = NULL;
background_chain = NULL;
root_node = NULL;
enableOpenCSG = false;
tval = 0;
fps = 0;
@ -327,11 +305,6 @@ MainWindow::MainWindow(const QString &filename)
connect(this->viewActionOrthogonal, SIGNAL(triggered()), this, SLOT(viewOrthogonal()));
connect(this->viewActionHide, SIGNAL(triggered()), this, SLOT(hideConsole()));
// #ifdef ENABLE_CGAL
// viewActionCGALSurface = menu->addAction("CGAL Surfaces", this, SLOT(viewModeCGALSurface()), QKeySequence(Qt::Key_F10));
// viewActionCGALGrid = menu->addAction("CGAL Grid Only", this, SLOT(viewModeCGALGrid()), QKeySequence(Qt::Key_F11));
// #endif
// Help menu
connect(this->helpActionAbout, SIGNAL(triggered()), this, SLOT(helpAbout()));
connect(this->helpActionHomepage, SIGNAL(triggered()), this, SLOT(helpHomepage()));
@ -431,19 +404,14 @@ MainWindow::loadDesignSettings()
MainWindow::~MainWindow()
{
if (root_module)
delete root_module;
if (root_node)
delete root_node;
if (root_module) delete root_module;
if (root_node) delete root_node;
#ifdef ENABLE_CGAL
if (this->root_N)
delete this->root_N;
if (cgal_ogl_p) {
Polyhedron *p = (Polyhedron*)cgal_ogl_p;
delete p;
}
if (cgal_ogl_ps)
cgal_ogl_ps->unlink();
if (this->root_N) delete this->root_N;
delete this->cgalRenderer;
#endif
#ifdef ENABLE_OPENCSG
delete this->opencsgRenderer;
#endif
}
@ -612,6 +580,16 @@ void MainWindow::compile(bool procevents)
if (procevents)
QApplication::processEvents();
// Invalidate renderers before we kill the CSG tree
screen->setRenderer(NULL);
if (this->opencsgRenderer) {
delete this->opencsgRenderer;
this->opencsgRenderer = NULL;
}
if (this->thrownTogetherRenderer) {
delete this->thrownTogetherRenderer;
this->thrownTogetherRenderer = NULL;
}
// Remove previous CSG tree
if (root_module) {
@ -656,7 +634,6 @@ void MainWindow::compile(bool procevents)
background_chain = NULL;
}
root_node = NULL;
enableOpenCSG = false;
// Initialize special variables
root_ctx.set_variable("$t", Value(e_tval->text().toDouble()));
@ -822,13 +799,6 @@ void MainWindow::compileCSG(bool procevents)
root_chain = new CSGChain();
root_chain->import(root_norm_term);
if (root_chain->polysets.size() > 1000) {
PRINTF("WARNING: Normalized tree has %d elements!", root_chain->polysets.size());
PRINTF("WARNING: OpenCSG rendering has been disabled.");
} else {
enableOpenCSG = true;
}
if (highlight_terms.size() > 0)
{
PRINTF("Compiling highlights (%d CSG Trees)...", highlight_terms.size());
@ -866,6 +836,20 @@ void MainWindow::compileCSG(bool procevents)
background_chain->import(background_terms[i]);
}
}
if (root_chain->polysets.size() > 1000) {
PRINTF("WARNING: Normalized tree has %d elements!", root_chain->polysets.size());
PRINTF("WARNING: OpenCSG rendering has been disabled.");
}
else {
this->opencsgRenderer = new OpenCSGRenderer(this->root_chain,
this->highlights_chain,
this->background_chain,
this->screen->shaderinfo);
}
this->thrownTogetherRenderer = new ThrownTogetherRenderer(this->root_chain,
this->highlights_chain,
this->background_chain);
PRINT("CSG generation finished.");
int s = t.elapsed() / 1000;
@ -1132,16 +1116,16 @@ void MainWindow::actionCompile()
if (this->root_node) compileCSG(!viewActionAnimate->isChecked());
// Go to non-CGAL view mode
if (!viewActionOpenCSG->isChecked() && !viewActionThrownTogether->isChecked()) {
if (viewActionThrownTogether->isChecked()) {
viewModeThrownTogether();
}
else {
#ifdef ENABLE_OPENCSG
viewModeOpenCSG();
#else
viewModeThrownTogether();
#endif
}
else {
screen->updateGL();
}
if (viewActionAnimate->isChecked() && e_dump->isChecked()) {
QImage img = screen->grabFrameBuffer();
@ -1167,10 +1151,12 @@ void MainWindow::actionRenderCGAL()
if (!root_module || !root_node)
return;
this->screen->setRenderer(NULL);
delete this->cgalRenderer;
this->cgalRenderer = NULL;
if (this->root_N) {
delete this->root_N;
this->root_N = NULL;
this->recreate_cgal_ogl_p = true;
}
PRINT("Rendering Polygon Mesh using CGAL...");
@ -1254,10 +1240,13 @@ void MainWindow::actionRenderCGAL()
int s = t.elapsed() / 1000;
PRINTF("Total rendering time: %d hours, %d minutes, %d seconds", s / (60*60), (s / 60) % 60, s % 60);
if (!viewActionCGALSurfaces->isChecked() && !viewActionCGALGrid->isChecked()) {
this->cgalRenderer = new CGALRenderer(*this->root_N);
// Go to CGAL view mode
if (viewActionCGALGrid->isChecked()) {
viewModeCGALGrid();
}
else {
viewModeCGALSurface();
} else {
screen->updateGL();
}
PRINT("Rendering finished.");
@ -1461,37 +1450,6 @@ void MainWindow::viewModeActionsUncheck()
#ifdef ENABLE_OPENCSG
static void renderGLThrownTogether(void *vp);
static void renderGLviaOpenCSG(void *vp)
{
MainWindow *m = (MainWindow*)vp;
if (!m->enableOpenCSG) {
renderGLThrownTogether(vp);
return;
}
static int glew_initialized = 0;
if (!glew_initialized) {
glew_initialized = 1;
glewInit();
}
#ifdef ENABLE_MDI
OpenCSG::setContext(m->screen->opencsg_id);
#endif
if (m->root_chain) {
GLint *shaderinfo = m->screen->shaderinfo;
if (!shaderinfo[0])
shaderinfo = NULL;
renderCSGChainviaOpenCSG(m->root_chain, m->viewActionShowEdges->isChecked() ? shaderinfo : NULL, false, false);
if (m->background_chain) {
renderCSGChainviaOpenCSG(m->background_chain, m->viewActionShowEdges->isChecked() ? shaderinfo : NULL, false, true);
}
if (m->highlights_chain) {
renderCSGChainviaOpenCSG(m->highlights_chain, m->viewActionShowEdges->isChecked() ? shaderinfo : NULL, true, false);
}
}
}
/*!
Go to the OpenCSG view mode.
Falls back to thrown together mode if OpenCSG is not available
@ -1501,8 +1459,7 @@ void MainWindow::viewModeOpenCSG()
if (screen->hasOpenCSGSupport()) {
viewModeActionsUncheck();
viewActionOpenCSG->setChecked(true);
screen->setRenderFunc(renderGLviaOpenCSG, this);
screen->updateGL();
screen->setRenderer(this->opencsgRenderer ? (Renderer *)this->opencsgRenderer : (Renderer *)this->thrownTogetherRenderer);
} else {
viewModeThrownTogether();
}
@ -1512,125 +1469,12 @@ void MainWindow::viewModeOpenCSG()
#ifdef ENABLE_CGAL
static void renderGLviaCGAL(void *vp)
{
MainWindow *m = (MainWindow*)vp;
if (m->recreate_cgal_ogl_p) {
m->recreate_cgal_ogl_p = false;
Polyhedron *p = (Polyhedron*)m->cgal_ogl_p;
delete p;
m->cgal_ogl_p = NULL;
if (m->cgal_ogl_ps)
m->cgal_ogl_ps->unlink();
m->cgal_ogl_ps = NULL;
}
if (!m->root_N) return;
if (m->root_N->dim == 2)
{
if (m->cgal_ogl_ps == NULL) {
DxfData dd(*m->root_N);
m->cgal_ogl_ps = new PolySet();
m->cgal_ogl_ps->is2d = true;
dxf_tesselate(m->cgal_ogl_ps, &dd, 0, true, false, 0);
}
// Draw 2D polygons
glDisable(GL_LIGHTING);
const QColor &col = Preferences::inst()->color(Preferences::CGAL_FACE_2D_COLOR);
glColor3f(col.redF(), col.greenF(), col.blueF());
for (int i=0; i < m->cgal_ogl_ps->polygons.size(); i++) {
glBegin(GL_POLYGON);
for (int j=0; j < m->cgal_ogl_ps->polygons[i].size(); j++) {
PolySet::Point p = m->cgal_ogl_ps->polygons[i][j];
glVertex3d(p.x, p.y, -0.1);
}
glEnd();
}
typedef CGAL_Nef_polyhedron2::Explorer Explorer;
typedef Explorer::Face_const_iterator fci_t;
typedef Explorer::Halfedge_around_face_const_circulator heafcc_t;
typedef Explorer::Point Point;
Explorer E = m->root_N->p2.explorer();
// Draw 2D edges
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glLineWidth(2);
const QColor &col2 = Preferences::inst()->color(Preferences::CGAL_EDGE_2D_COLOR);
glColor3f(col2.redF(), col2.greenF(), col2.blueF());
// Extract the boundary, including inner boundaries of the polygons
for (fci_t fit = E.faces_begin(), facesend = E.faces_end(); fit != facesend; ++fit)
{
bool fset = false;
double fx = 0.0, fy = 0.0;
heafcc_t fcirc(E.halfedge(fit)), fend(fcirc);
CGAL_For_all(fcirc, fend) {
if(E.is_standard(E.target(fcirc))) {
Point p = E.point(E.target(fcirc));
double x = to_double(p.x()), y = to_double(p.y());
if (!fset) {
glBegin(GL_LINE_STRIP);
fx = x, fy = y;
fset = true;
}
glVertex3d(x, y, -0.1);
}
}
if (fset) {
glVertex3d(fx, fy, -0.1);
glEnd();
}
}
glEnable(GL_DEPTH_TEST);
}
else if (m->root_N->dim == 3)
{
Polyhedron *p = (Polyhedron*)m->cgal_ogl_p;
if (!p) {
Nef3_Converter<CGAL_Nef_polyhedron3>::setColor(Polyhedron::CGAL_NEF3_MARKED_FACET_COLOR,
Preferences::inst()->color(Preferences::CGAL_FACE_BACK_COLOR).red(),
Preferences::inst()->color(Preferences::CGAL_FACE_BACK_COLOR).green(),
Preferences::inst()->color(Preferences::CGAL_FACE_BACK_COLOR).blue());
Nef3_Converter<CGAL_Nef_polyhedron3>::setColor(Polyhedron::CGAL_NEF3_UNMARKED_FACET_COLOR,
Preferences::inst()->color(Preferences::CGAL_FACE_FRONT_COLOR).red(),
Preferences::inst()->color(Preferences::CGAL_FACE_FRONT_COLOR).green(),
Preferences::inst()->color(Preferences::CGAL_FACE_FRONT_COLOR).blue());
m->cgal_ogl_p = p = new Polyhedron();
Nef3_Converter<CGAL_Nef_polyhedron3>::convert_to_OGLPolyhedron(m->root_N->p3, p);
p->init();
}
if (m->viewActionCGALSurfaces->isChecked())
p->set_style(SNC_BOUNDARY);
if (m->viewActionCGALGrid->isChecked())
p->set_style(SNC_SKELETON);
#if 0
p->draw();
#else
if (p->style == SNC_BOUNDARY) {
glCallList(p->object_list_+2);
if (m->viewActionShowEdges->isChecked()) {
glDisable(GL_LIGHTING);
glCallList(p->object_list_+1);
glCallList(p->object_list_);
}
} else {
glDisable(GL_LIGHTING);
glCallList(p->object_list_+1);
glCallList(p->object_list_);
}
#endif
}
}
void MainWindow::viewModeCGALSurface()
{
viewModeActionsUncheck();
viewActionCGALSurfaces->setChecked(true);
screen->setRenderFunc(renderGLviaCGAL, this);
screen->setShowFaces(true);
screen->setRenderer(this->cgalRenderer);
screen->updateGL();
}
@ -1638,104 +1482,24 @@ void MainWindow::viewModeCGALGrid()
{
viewModeActionsUncheck();
viewActionCGALGrid->setChecked(true);
screen->setRenderFunc(renderGLviaCGAL, this);
screen->updateGL();
screen->setShowFaces(false);
screen->setRenderer(this->cgalRenderer);
}
#endif /* ENABLE_CGAL */
static void renderGLThrownTogetherChain(MainWindow *m, CSGChain *chain, bool highlight, bool background, bool fberror)
{
glDepthFunc(GL_LEQUAL);
QHash<QPair<PolySet*,double*>,int> polySetVisitMark;
bool showEdges = m->viewActionShowEdges->isChecked();
for (int i = 0; i < chain->polysets.size(); i++) {
if (polySetVisitMark[QPair<PolySet*,double*>(chain->polysets[i], chain->matrices[i])]++ > 0)
continue;
double *m = chain->matrices[i];
glPushMatrix();
glMultMatrixd(m);
int csgmode = chain->types[i] == CSGTerm::TYPE_DIFFERENCE ? PolySet::CSGMODE_DIFFERENCE : PolySet::CSGMODE_NORMAL;
if (highlight) {
chain->polysets[i]->render_surface(PolySet::COLORMODE_HIGHLIGHT, PolySet::csgmode_e(csgmode + 20), m);
if (showEdges) {
glDisable(GL_LIGHTING);
chain->polysets[i]->render_edges(PolySet::COLORMODE_HIGHLIGHT, PolySet::csgmode_e(csgmode + 20));
glEnable(GL_LIGHTING);
}
} else if (background) {
chain->polysets[i]->render_surface(PolySet::COLORMODE_BACKGROUND, PolySet::csgmode_e(csgmode + 10), m);
if (showEdges) {
glDisable(GL_LIGHTING);
chain->polysets[i]->render_edges(PolySet::COLORMODE_BACKGROUND, PolySet::csgmode_e(csgmode + 10));
glEnable(GL_LIGHTING);
}
} else if (fberror) {
if (highlight) {
chain->polysets[i]->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode + 20), m);
} else if (background) {
chain->polysets[i]->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode + 10), m);
} else {
chain->polysets[i]->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode), m);
}
} else if (m[16] >= 0 || m[17] >= 0 || m[18] >= 0 || m[19] >= 0) {
glColor4d(m[16], m[17], m[18], m[19]);
chain->polysets[i]->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode), m);
if (showEdges) {
glDisable(GL_LIGHTING);
glColor4d((m[16]+1)/2, (m[17]+1)/2, (m[18]+1)/2, 1.0);
chain->polysets[i]->render_edges(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode));
glEnable(GL_LIGHTING);
}
} else if (chain->types[i] == CSGTerm::TYPE_DIFFERENCE) {
chain->polysets[i]->render_surface(PolySet::COLORMODE_CUTOUT, PolySet::csgmode_e(csgmode), m);
if (showEdges) {
glDisable(GL_LIGHTING);
chain->polysets[i]->render_edges(PolySet::COLORMODE_CUTOUT, PolySet::csgmode_e(csgmode));
glEnable(GL_LIGHTING);
}
} else {
chain->polysets[i]->render_surface(PolySet::COLORMODE_MATERIAL, PolySet::csgmode_e(csgmode), m);
if (showEdges) {
glDisable(GL_LIGHTING);
chain->polysets[i]->render_edges(PolySet::COLORMODE_MATERIAL, PolySet::csgmode_e(csgmode));
glEnable(GL_LIGHTING);
}
}
glPopMatrix();
}
}
static void renderGLThrownTogether(void *vp)
{
MainWindow *m = (MainWindow*)vp;
if (m->root_chain) {
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
renderGLThrownTogetherChain(m, m->root_chain, false, false, false);
glCullFace(GL_FRONT);
glColor3ub(255, 0, 255);
renderGLThrownTogetherChain(m, m->root_chain, false, false, true);
glDisable(GL_CULL_FACE);
}
if (m->background_chain)
renderGLThrownTogetherChain(m, m->background_chain, false, true, false);
if (m->highlights_chain)
renderGLThrownTogetherChain(m, m->highlights_chain, true, false, false);
}
void MainWindow::viewModeThrownTogether()
{
viewModeActionsUncheck();
viewActionThrownTogether->setChecked(true);
screen->setRenderFunc(renderGLThrownTogether, this);
screen->updateGL();
screen->setRenderer(this->thrownTogetherRenderer);
}
void MainWindow::viewModeShowEdges()
{
QSettings settings;
settings.setValue("view/showEdges",viewActionShowEdges->isChecked());
screen->setShowEdges(viewActionShowEdges->isChecked());
screen->updateGL();
}

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 "csgterm.h"
@ -18,7 +44,35 @@ public:
}
};
void renderCSGChainviaOpenCSG(CSGChain *chain, GLint *shaderinfo, bool highlight, bool background)
OpenCSGRenderer::OpenCSGRenderer(CSGChain *root_chain, CSGChain *highlights_chain,
CSGChain *background_chain, GLint *shaderinfo)
: root_chain(root_chain), highlights_chain(highlights_chain),
background_chain(background_chain), shaderinfo(shaderinfo)
{
}
void OpenCSGRenderer::draw(bool showfaces, bool showedges) const
{
static int glew_initialized = 0;
if (!glew_initialized) {
glew_initialized = 1;
glewInit();
}
if (this->root_chain) {
GLint *shaderinfo = this->shaderinfo;
if (!shaderinfo[0]) shaderinfo = NULL;
renderCSGChain(this->root_chain, showedges ? shaderinfo : NULL, false, false);
if (this->background_chain) {
renderCSGChain(this->background_chain, showedges ? shaderinfo : NULL, false, true);
}
if (this->highlights_chain) {
renderCSGChain(this->highlights_chain, showedges ? shaderinfo : NULL, true, false);
}
}
}
void OpenCSGRenderer::renderCSGChain(CSGChain *chain, GLint *shaderinfo,
bool highlight, bool background) const
{
std::vector<OpenCSG::Primitive*> primitives;
int j = 0;

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);
}
catch (CGAL::Assertion_exception e) {
PRINTF("ERROR: Illegal polygonal object - make sure all polygons are defined with the same winding order. Skipping affected object.");
PRINTF("CGAL error: %s", e.what());
CGAL::set_error_behaviour(old_behaviour);
return CGAL_Nef_polyhedron();
}

View File

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

View File

@ -124,7 +124,7 @@ PolySet *ProjectionNode::render_polyset(render_mode_e) const
}
}
catch (CGAL::Assertion_exception e) {
PRINTF("ERROR: Illegal polygonal object - make sure all polygons are defined with the same winding order. Skipping affected object.");
PRINTF("CGAL error: %s", e.what());
CGAL::set_error_behaviour(old_behaviour);
return ps;
}

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