From 887f7eb99ff7dfaa2f088d7e210b09b10892f19a Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Sat, 30 Jul 2011 21:29:40 +0200 Subject: Refactored GL rendering inspired by Giles' work on RapCad. The ultimate goal is to become independent of Qt diff --git a/opencsg.pri b/opencsg.pri index 8538f99..02be596 100644 --- a/opencsg.pri +++ b/opencsg.pri @@ -3,8 +3,8 @@ opencsg { CONFIG += glew include(glew.pri) - HEADERS += src/render-opencsg.h - SOURCES += src/render-opencsg.cc + HEADERS += src/opencsgrenderer.h + SOURCES += src/opencsgrenderer.cc isEmpty(DEPLOYDIR) { # Optionally specify location of OpenCSG using the diff --git a/openscad.pro b/openscad.pro index 6b85d59..61000f1 100644 --- a/openscad.pro +++ b/openscad.pro @@ -118,7 +118,10 @@ 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 \ @@ -147,6 +150,8 @@ HEADERS += src/CGAL_renderer.h \ SOURCES += src/openscad.cc \ src/mainwin.cc \ + src/cgalrenderer.cc \ + src/throwntogetherrenderer.cc \ src/glview.cc \ src/export.cc \ src/value.cc \ diff --git a/src/CGAL_renderer.h b/src/CGAL_renderer.h index a8bdc43..acc902f 100644 --- a/src/CGAL_renderer.h +++ b/src/CGAL_renderer.h @@ -39,13 +39,6 @@ using CGAL::OGL::SNC_BOUNDARY; using CGAL::OGL::SNC_SKELETON; -namespace OpenSCAD -{ - -namespace OGL -{ - - class Polyhedron : public CGAL::OGL::Polyhedron { public: @@ -108,8 +101,4 @@ private: }; // Polyhedron -} // namespace OGL - -} // namespace OpenSCAD - #endif // CGAL_RENDERER_H diff --git a/src/GLView.h b/src/GLView.h index be21578..764b23b 100644 --- a/src/GLView.h +++ b/src/GLView.h @@ -12,24 +12,31 @@ class GLView : public QGLWidget { Q_OBJECT + Q_PROPERTY(bool showFaces READ showFaces WRITE setShowFaces); + Q_PROPERTY(bool showEdges READ showEdges WRITE setShowEdges); Q_PROPERTY(bool showAxes READ showAxes WRITE setShowAxes); Q_PROPERTY(bool showCrosshairs READ showCrosshairs WRITE setShowCrosshairs); Q_PROPERTY(bool orthoMode READ orthoMode WRITE setOrthoMode); public: GLView(QWidget *parent = NULL); - void setRenderFunc(void (*func)(void*), void *userdata); + void setRenderer(class Renderer* r); #ifdef ENABLE_OPENCSG bool hasOpenCSGSupport() { return this->opencsg_support; } #endif // Properties + bool showFaces() const { return this->showfaces; } + void setShowFaces(bool enabled) { this->showfaces = enabled; } + bool showEdges() const { return this->showedges; } + void setShowEdges(bool enabled) { this->showedges = enabled; } bool showAxes() const { return this->showaxes; } void setShowAxes(bool enabled) { this->showaxes = enabled; } bool showCrosshairs() const { return this->showcrosshairs; } void setShowCrosshairs(bool enabled) { this->showcrosshairs = enabled; } bool orthoMode() const { return this->orthomode; } void setOrthoMode(bool enabled) { this->orthomode = enabled; } - + +public: QLabel *statusLabel; double object_rot_x; double object_rot_y; @@ -45,9 +52,10 @@ public: #endif private: - void (*renderfunc)(void*); - void *renderfunc_vp; + Renderer *renderer; + bool showfaces; + bool showedges; bool showaxes; bool showcrosshairs; bool orthomode; diff --git a/src/MainWindow.h b/src/MainWindow.h index 43ab273..adbf634 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -38,10 +38,12 @@ 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 highlight_terms; CSGChain *highlights_chain; diff --git a/src/cgalrenderer.cc b/src/cgalrenderer.cc new file mode 100644 index 0000000..551c061 --- /dev/null +++ b/src/cgalrenderer.cc @@ -0,0 +1,126 @@ +/* + * OpenSCAD (www.openscad.org) + * Copyright (C) 2009-2011 Clifford Wolf and + * Marius Kintel + * + * 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::convert_to_OGLPolyhedron(this->root.p3, this->polyhedron); + this->polyhedron->init(); + } +} + +CGALRenderer::~CGALRenderer() +{ + if (this->polyset) this->polyset->unlink(); +} + +void CGALRenderer::draw(bool showfaces, bool showedges) const +{ + if (this->root.dim == 2) { + // Draw 2D polygons + glDisable(GL_LIGHTING); + const QColor &col = Preferences::inst()->color(Preferences::CGAL_FACE_2D_COLOR); + glColor3f(col.redF(), col.greenF(), col.blueF()); + + for (int i=0; i < this->polyset->polygons.size(); i++) { + glBegin(GL_POLYGON); + for (int j=0; j < this->polyset->polygons[i].size(); j++) { + PolySet::Point p = this->polyset->polygons[i][j]; + glVertex3d(p.x, p.y, -0.1); + } + glEnd(); + } + + typedef CGAL_Nef_polyhedron2::Explorer Explorer; + typedef Explorer::Face_const_iterator fci_t; + typedef Explorer::Halfedge_around_face_const_circulator heafcc_t; + typedef Explorer::Point Point; + Explorer E = this->root.p2.explorer(); + + // Draw 2D edges + glDisable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + glLineWidth(2); + const QColor &col2 = Preferences::inst()->color(Preferences::CGAL_EDGE_2D_COLOR); + glColor3f(col2.redF(), col2.greenF(), col2.blueF()); + + // Extract the boundary, including inner boundaries of the polygons + for (fci_t fit = E.faces_begin(), facesend = E.faces_end(); fit != facesend; ++fit) { + bool fset = false; + double fx = 0.0, fy = 0.0; + heafcc_t fcirc(E.halfedge(fit)), fend(fcirc); + CGAL_For_all(fcirc, fend) { + if(E.is_standard(E.target(fcirc))) { + Point p = E.point(E.target(fcirc)); + double x = to_double(p.x()), y = to_double(p.y()); + if (!fset) { + glBegin(GL_LINE_STRIP); + fx = x, fy = y; + fset = true; + } + glVertex3d(x, y, -0.1); + } + } + if (fset) { + glVertex3d(fx, fy, -0.1); + glEnd(); + } + } + + glEnable(GL_DEPTH_TEST); + } + else if (this->root.dim == 3) { + if (showfaces) this->polyhedron->set_style(SNC_BOUNDARY); + else this->polyhedron->set_style(SNC_SKELETON); + + this->polyhedron->draw(showfaces && showedges); + } +} diff --git a/src/cgalrenderer.h b/src/cgalrenderer.h new file mode 100644 index 0000000..b3c1638 --- /dev/null +++ b/src/cgalrenderer.h @@ -0,0 +1,20 @@ +#ifndef CGALRENDERER_H_ +#define CGALRENDERER_H_ + +#include "renderer.h" +#include "cgal.h" + +class CGALRenderer : public Renderer +{ +public: + CGALRenderer(const CGAL_Nef_polyhedron &root); + ~CGALRenderer(); + void draw(bool showfaces, bool showedges) const; + +private: + const CGAL_Nef_polyhedron &root; + class Polyhedron *polyhedron; + class PolySet *polyset; +}; + +#endif diff --git a/src/glview.cc b/src/glview.cc index 31c9e58..9d82443 100644 --- a/src/glview.cc +++ b/src/glview.cc @@ -26,6 +26,7 @@ #include "GLView.h" #include "Preferences.h" +#include "renderer.h" #include #include @@ -41,9 +42,13 @@ #include "mathc99.h" #include +#ifdef ENABLE_OPENCSG +# include +#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; @@ -58,9 +63,8 @@ GLView::GLView(QWidget *parent) : QGLWidget(parent) 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; @@ -75,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() @@ -295,6 +299,8 @@ void GLView::setupOrtho(double distance, bool offset) void GLView::paintGL() { + glEnable(GL_LIGHTING); + if (orthomode) setupOrtho(viewer_distance); @@ -355,8 +361,13 @@ 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) diff --git a/src/mainwin.cc b/src/mainwin.cc index 2255ac3..609a5b8 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -40,11 +40,12 @@ #include "dxftess.h" #include "progress.h" #ifdef ENABLE_OPENCSG -#include "render-opencsg.h" +#include "opencsgRenderer.h" #endif #ifdef USE_PROGRESSWIDGET #include "ProgressWidget.h" #endif +#include "thrownTogetherRenderer.h" #include #include @@ -75,9 +76,7 @@ #ifdef ENABLE_CGAL -#include "CGAL_renderer.h" -using OpenSCAD::OGL::Polyhedron; -using CGAL::OGL::Nef3_Converter; +#include "cgalrenderer.h" #endif // ENABLE_CGAL @@ -153,10 +152,12 @@ 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; @@ -305,11 +306,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())); @@ -409,19 +405,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 } @@ -590,6 +581,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) { @@ -800,13 +801,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()); @@ -844,6 +838,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; @@ -1110,16 +1118,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(); @@ -1145,10 +1153,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..."); @@ -1232,10 +1242,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."); @@ -1439,37 +1452,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 @@ -1479,8 +1461,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(); } @@ -1490,113 +1471,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) { - m->cgal_ogl_p = p = new Polyhedron(); - p->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()); - p->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()); - - Nef3_Converter::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); - - p->draw(m->viewActionShowEdges->isChecked()); - - } -} - void MainWindow::viewModeCGALSurface() { viewModeActionsUncheck(); viewActionCGALSurfaces->setChecked(true); - screen->setRenderFunc(renderGLviaCGAL, this); + screen->setShowFaces(true); + screen->setRenderer(this->cgalRenderer); screen->updateGL(); } @@ -1604,104 +1484,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,int> polySetVisitMark; - bool showEdges = m->viewActionShowEdges->isChecked(); - for (int i = 0; i < chain->polysets.size(); i++) { - if (polySetVisitMark[QPair(chain->polysets[i], chain->matrices[i])]++ > 0) - continue; - double *m = chain->matrices[i]; - glPushMatrix(); - glMultMatrixd(m); - int csgmode = chain->types[i] == CSGTerm::TYPE_DIFFERENCE ? PolySet::CSGMODE_DIFFERENCE : PolySet::CSGMODE_NORMAL; - if (highlight) { - chain->polysets[i]->render_surface(PolySet::COLORMODE_HIGHLIGHT, PolySet::csgmode_e(csgmode + 20), m); - if (showEdges) { - glDisable(GL_LIGHTING); - chain->polysets[i]->render_edges(PolySet::COLORMODE_HIGHLIGHT, PolySet::csgmode_e(csgmode + 20)); - glEnable(GL_LIGHTING); - } - } else if (background) { - chain->polysets[i]->render_surface(PolySet::COLORMODE_BACKGROUND, PolySet::csgmode_e(csgmode + 10), m); - if (showEdges) { - glDisable(GL_LIGHTING); - chain->polysets[i]->render_edges(PolySet::COLORMODE_BACKGROUND, PolySet::csgmode_e(csgmode + 10)); - glEnable(GL_LIGHTING); - } - } else if (fberror) { - if (highlight) { - chain->polysets[i]->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode + 20), m); - } else if (background) { - chain->polysets[i]->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode + 10), m); - } else { - chain->polysets[i]->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode), m); - } - } else if (m[16] >= 0 || m[17] >= 0 || m[18] >= 0 || m[19] >= 0) { - glColor4d(m[16], m[17], m[18], m[19]); - chain->polysets[i]->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode), m); - if (showEdges) { - glDisable(GL_LIGHTING); - glColor4d((m[16]+1)/2, (m[17]+1)/2, (m[18]+1)/2, 1.0); - chain->polysets[i]->render_edges(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode)); - glEnable(GL_LIGHTING); - } - } else if (chain->types[i] == CSGTerm::TYPE_DIFFERENCE) { - chain->polysets[i]->render_surface(PolySet::COLORMODE_CUTOUT, PolySet::csgmode_e(csgmode), m); - if (showEdges) { - glDisable(GL_LIGHTING); - chain->polysets[i]->render_edges(PolySet::COLORMODE_CUTOUT, PolySet::csgmode_e(csgmode)); - glEnable(GL_LIGHTING); - } - } else { - chain->polysets[i]->render_surface(PolySet::COLORMODE_MATERIAL, PolySet::csgmode_e(csgmode), m); - if (showEdges) { - glDisable(GL_LIGHTING); - chain->polysets[i]->render_edges(PolySet::COLORMODE_MATERIAL, PolySet::csgmode_e(csgmode)); - glEnable(GL_LIGHTING); - } - } - glPopMatrix(); - } -} - -static void renderGLThrownTogether(void *vp) -{ - MainWindow *m = (MainWindow*)vp; - if (m->root_chain) { - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); - renderGLThrownTogetherChain(m, m->root_chain, false, false, false); - glCullFace(GL_FRONT); - glColor3ub(255, 0, 255); - renderGLThrownTogetherChain(m, m->root_chain, false, false, true); - glDisable(GL_CULL_FACE); - } - if (m->background_chain) - renderGLThrownTogetherChain(m, m->background_chain, false, true, false); - if (m->highlights_chain) - renderGLThrownTogetherChain(m, m->highlights_chain, true, false, false); -} - void MainWindow::viewModeThrownTogether() { viewModeActionsUncheck(); viewActionThrownTogether->setChecked(true); - screen->setRenderFunc(renderGLThrownTogether, this); - screen->updateGL(); + screen->setRenderer(this->thrownTogetherRenderer); } void MainWindow::viewModeShowEdges() { QSettings settings; settings.setValue("view/showEdges",viewActionShowEdges->isChecked()); + screen->setShowEdges(viewActionShowEdges->isChecked()); screen->updateGL(); } diff --git a/src/opencsgrenderer.cc b/src/opencsgrenderer.cc new file mode 100644 index 0000000..768176c --- /dev/null +++ b/src/opencsgrenderer.cc @@ -0,0 +1,138 @@ +/* + * OpenSCAD (www.openscad.org) + * Copyright (C) 2009-2011 Clifford Wolf and + * Marius Kintel + * + * 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" + +class OpenCSGPrim : public OpenCSG::Primitive +{ +public: + OpenCSGPrim(OpenCSG::Operation operation, unsigned int convexity) : + OpenCSG::Primitive(operation, convexity) { } + PolySet *p; + double *m; + int csgmode; + virtual void render() { + glPushMatrix(); + glMultMatrixd(m); + p->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode), m); + glPopMatrix(); + } +}; + +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 primitives; + int j = 0; + for (int i = 0;; i++) + { + bool last = i == chain->polysets.size(); + + if (last || chain->types[i] == CSGTerm::TYPE_UNION) + { + if (j+1 != i) { + OpenCSG::render(primitives); + glDepthFunc(GL_EQUAL); + } + if (shaderinfo) + glUseProgram(shaderinfo[0]); + for (; j < i; j++) { + double *m = chain->matrices[j]; + glPushMatrix(); + glMultMatrixd(m); + int csgmode = chain->types[j] == CSGTerm::TYPE_DIFFERENCE ? PolySet::CSGMODE_DIFFERENCE : PolySet::CSGMODE_NORMAL; + if (highlight) { + chain->polysets[j]->render_surface(PolySet::COLORMODE_HIGHLIGHT, PolySet::csgmode_e(csgmode + 20), m, shaderinfo); + } else if (background) { + chain->polysets[j]->render_surface(PolySet::COLORMODE_BACKGROUND, PolySet::csgmode_e(csgmode + 10), m, shaderinfo); + } else if (m[16] >= 0 || m[17] >= 0 || m[18] >= 0 || m[19] >= 0) { + // User-defined color from source + glColor4d(m[16], m[17], m[18], m[19]); + if (shaderinfo) { + glUniform4f(shaderinfo[1], m[16], m[17], m[18], m[19]); + glUniform4f(shaderinfo[2], (m[16]+1)/2, (m[17]+1)/2, (m[18]+1)/2, 1.0); + } + chain->polysets[j]->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode), m, shaderinfo); + } else if (chain->types[j] == CSGTerm::TYPE_DIFFERENCE) { + chain->polysets[j]->render_surface(PolySet::COLORMODE_CUTOUT, PolySet::csgmode_e(csgmode), m, shaderinfo); + } else { + chain->polysets[j]->render_surface(PolySet::COLORMODE_MATERIAL, PolySet::csgmode_e(csgmode), m, shaderinfo); + } + glPopMatrix(); + } + if (shaderinfo) + glUseProgram(0); + for (unsigned int k = 0; k < primitives.size(); k++) { + delete primitives[k]; + } + glDepthFunc(GL_LEQUAL); + primitives.clear(); + } + + if (last) + break; + + OpenCSGPrim *prim = new OpenCSGPrim(chain->types[i] == CSGTerm::TYPE_DIFFERENCE ? + OpenCSG::Subtraction : OpenCSG::Intersection, chain->polysets[i]->convexity); + prim->p = chain->polysets[i]; + prim->m = chain->matrices[i]; + prim->csgmode = chain->types[i] == CSGTerm::TYPE_DIFFERENCE ? PolySet::CSGMODE_DIFFERENCE : PolySet::CSGMODE_NORMAL; + if (highlight) + prim->csgmode += 20; + else if (background) + prim->csgmode += 10; + primitives.push_back(prim); + } +} diff --git a/src/opencsgrenderer.h b/src/opencsgrenderer.h new file mode 100644 index 0000000..95ffc8e --- /dev/null +++ b/src/opencsgrenderer.h @@ -0,0 +1,24 @@ +#ifndef OPENCSGRENDERER_H_ +#define OPENCSGRENDERER_H_ + +#include "renderer.h" +#include // this must be included before the GL headers +#include + +class OpenCSGRenderer : public Renderer +{ +public: + OpenCSGRenderer(class CSGChain *root_chain, CSGChain *highlights_chain, + CSGChain *background_chain, GLint *shaderinfo); + void draw(bool showfaces, bool showedges) const; +private: + void renderCSGChain(class CSGChain *chain, GLint *shaderinfo, + bool highlight, bool background) const; + + CSGChain *root_chain; + CSGChain *highlights_chain; + CSGChain *background_chain; + GLint *shaderinfo; +}; + +#endif diff --git a/src/polyset.h b/src/polyset.h index 0914e91..8712ff2 100644 --- a/src/polyset.h +++ b/src/polyset.h @@ -1,10 +1,7 @@ #ifndef POLYSET_H_ #define POLYSET_H_ -#ifdef ENABLE_OPENCSG -// this must be included before the GL headers -# include -#endif +#include // this must be included before the GL headers #include #include "grid.h" diff --git a/src/render-opencsg.cc b/src/render-opencsg.cc deleted file mode 100644 index f6d26ac..0000000 --- a/src/render-opencsg.cc +++ /dev/null @@ -1,84 +0,0 @@ -#include "render-opencsg.h" -#include "polyset.h" -#include "csgterm.h" - -class OpenCSGPrim : public OpenCSG::Primitive -{ -public: - OpenCSGPrim(OpenCSG::Operation operation, unsigned int convexity) : - OpenCSG::Primitive(operation, convexity) { } - PolySet *p; - double *m; - int csgmode; - virtual void render() { - glPushMatrix(); - glMultMatrixd(m); - p->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode), m); - glPopMatrix(); - } -}; - -void renderCSGChainviaOpenCSG(CSGChain *chain, GLint *shaderinfo, bool highlight, bool background) -{ - std::vector primitives; - int j = 0; - for (int i = 0;; i++) - { - bool last = i == chain->polysets.size(); - - if (last || chain->types[i] == CSGTerm::TYPE_UNION) - { - if (j+1 != i) { - OpenCSG::render(primitives); - glDepthFunc(GL_EQUAL); - } - if (shaderinfo) - glUseProgram(shaderinfo[0]); - for (; j < i; j++) { - double *m = chain->matrices[j]; - glPushMatrix(); - glMultMatrixd(m); - int csgmode = chain->types[j] == CSGTerm::TYPE_DIFFERENCE ? PolySet::CSGMODE_DIFFERENCE : PolySet::CSGMODE_NORMAL; - if (highlight) { - chain->polysets[j]->render_surface(PolySet::COLORMODE_HIGHLIGHT, PolySet::csgmode_e(csgmode + 20), m, shaderinfo); - } else if (background) { - chain->polysets[j]->render_surface(PolySet::COLORMODE_BACKGROUND, PolySet::csgmode_e(csgmode + 10), m, shaderinfo); - } else if (m[16] >= 0 || m[17] >= 0 || m[18] >= 0 || m[19] >= 0) { - // User-defined color from source - glColor4d(m[16], m[17], m[18], m[19]); - if (shaderinfo) { - glUniform4f(shaderinfo[1], m[16], m[17], m[18], m[19]); - glUniform4f(shaderinfo[2], (m[16]+1)/2, (m[17]+1)/2, (m[18]+1)/2, 1.0); - } - chain->polysets[j]->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode), m, shaderinfo); - } else if (chain->types[j] == CSGTerm::TYPE_DIFFERENCE) { - chain->polysets[j]->render_surface(PolySet::COLORMODE_CUTOUT, PolySet::csgmode_e(csgmode), m, shaderinfo); - } else { - chain->polysets[j]->render_surface(PolySet::COLORMODE_MATERIAL, PolySet::csgmode_e(csgmode), m, shaderinfo); - } - glPopMatrix(); - } - if (shaderinfo) - glUseProgram(0); - for (unsigned int k = 0; k < primitives.size(); k++) { - delete primitives[k]; - } - glDepthFunc(GL_LEQUAL); - primitives.clear(); - } - - if (last) - break; - - OpenCSGPrim *prim = new OpenCSGPrim(chain->types[i] == CSGTerm::TYPE_DIFFERENCE ? - OpenCSG::Subtraction : OpenCSG::Intersection, chain->polysets[i]->convexity); - prim->p = chain->polysets[i]; - prim->m = chain->matrices[i]; - prim->csgmode = chain->types[i] == CSGTerm::TYPE_DIFFERENCE ? PolySet::CSGMODE_DIFFERENCE : PolySet::CSGMODE_NORMAL; - if (highlight) - prim->csgmode += 20; - else if (background) - prim->csgmode += 10; - primitives.push_back(prim); - } -} diff --git a/src/render-opencsg.h b/src/render-opencsg.h deleted file mode 100644 index 9433cbe..0000000 --- a/src/render-opencsg.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef RENDER_OPENCSG_H_ -#define RENDER_OPENCSG_H_ - -#include - -void renderCSGChainviaOpenCSG(class CSGChain *chain, GLint *shaderinfo, bool highlight, bool background); - -#endif diff --git a/src/renderer.h b/src/renderer.h new file mode 100644 index 0000000..3c25e98 --- /dev/null +++ b/src/renderer.h @@ -0,0 +1,11 @@ +#ifndef RENDERER_H_ +#define RENDERER_H_ + +class Renderer +{ +public: + virtual ~Renderer() {} + virtual void draw(bool showfaces, bool showedges) const = 0; +}; + +#endif // RENDERER_H diff --git a/src/throwntogetherrenderer.cc b/src/throwntogetherrenderer.cc new file mode 100644 index 0000000..0a0c9c8 --- /dev/null +++ b/src/throwntogetherrenderer.cc @@ -0,0 +1,120 @@ +/* + * OpenSCAD (www.openscad.org) + * Copyright (C) 2009-2011 Clifford Wolf and + * Marius Kintel + * + * 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 // this must be included before the GL headers +#include + +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,int> polySetVisitMark; + for (int i = 0; i < chain->polysets.size(); i++) { + if (polySetVisitMark[QPair(chain->polysets[i], chain->matrices[i])]++ > 0) + continue; + double *m = chain->matrices[i]; + glPushMatrix(); + glMultMatrixd(m); + int csgmode = chain->types[i] == CSGTerm::TYPE_DIFFERENCE ? PolySet::CSGMODE_DIFFERENCE : PolySet::CSGMODE_NORMAL; + if (highlight) { + chain->polysets[i]->render_surface(PolySet::COLORMODE_HIGHLIGHT, PolySet::csgmode_e(csgmode + 20), m); + if (showedges) { + glDisable(GL_LIGHTING); + chain->polysets[i]->render_edges(PolySet::COLORMODE_HIGHLIGHT, PolySet::csgmode_e(csgmode + 20)); + glEnable(GL_LIGHTING); + } + } else if (background) { + chain->polysets[i]->render_surface(PolySet::COLORMODE_BACKGROUND, PolySet::csgmode_e(csgmode + 10), m); + if (showedges) { + glDisable(GL_LIGHTING); + chain->polysets[i]->render_edges(PolySet::COLORMODE_BACKGROUND, PolySet::csgmode_e(csgmode + 10)); + glEnable(GL_LIGHTING); + } + } else if (fberror) { + if (highlight) { + chain->polysets[i]->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode + 20), m); + } else if (background) { + chain->polysets[i]->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode + 10), m); + } else { + chain->polysets[i]->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode), m); + } + } else if (m[16] >= 0 || m[17] >= 0 || m[18] >= 0 || m[19] >= 0) { + glColor4d(m[16], m[17], m[18], m[19]); + chain->polysets[i]->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode), m); + if (showedges) { + glDisable(GL_LIGHTING); + glColor4d((m[16]+1)/2, (m[17]+1)/2, (m[18]+1)/2, 1.0); + chain->polysets[i]->render_edges(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode)); + glEnable(GL_LIGHTING); + } + } else if (chain->types[i] == CSGTerm::TYPE_DIFFERENCE) { + chain->polysets[i]->render_surface(PolySet::COLORMODE_CUTOUT, PolySet::csgmode_e(csgmode), m); + if (showedges) { + glDisable(GL_LIGHTING); + chain->polysets[i]->render_edges(PolySet::COLORMODE_CUTOUT, PolySet::csgmode_e(csgmode)); + glEnable(GL_LIGHTING); + } + } else { + chain->polysets[i]->render_surface(PolySet::COLORMODE_MATERIAL, PolySet::csgmode_e(csgmode), m); + if (showedges) { + glDisable(GL_LIGHTING); + chain->polysets[i]->render_edges(PolySet::COLORMODE_MATERIAL, PolySet::csgmode_e(csgmode)); + glEnable(GL_LIGHTING); + } + } + glPopMatrix(); + } +} diff --git a/src/throwntogetherrenderer.h b/src/throwntogetherrenderer.h new file mode 100644 index 0000000..09d13f3 --- /dev/null +++ b/src/throwntogetherrenderer.h @@ -0,0 +1,21 @@ +#ifndef THROWNTOGETHERRENDERER_H_ +#define THROWNTOGETHERRENDERER_H_ + +#include "renderer.h" + +class ThrownTogetherRenderer : public Renderer +{ +public: + ThrownTogetherRenderer(class CSGChain *root_chain, + CSGChain *highlights_chain, CSGChain *background_chain); + void draw(bool showfaces, bool showedges) const; +private: + void renderCSGChain(CSGChain *chain, bool highlight, bool background, bool showedges, + bool fberror) const; + + CSGChain *root_chain; + CSGChain *highlights_chain; + CSGChain *background_chain; +}; + +#endif -- cgit v0.10.1