diff --git a/csgterm.cc b/csgterm.cc index 826ec440..c1c6e14a 100644 --- a/csgterm.cc +++ b/csgterm.cc @@ -164,3 +164,45 @@ QString CSGTerm::dump() return QString("(%1 - %2)").arg(left->dump(), right->dump()); return label; } + +CSGChain::CSGChain() +{ +} + +void CSGChain::add(PolySet *polyset, CSGTerm::type_e type, QString label) +{ + polysets.append(polyset); + types.append(type); + labels.append(label); +} + +void CSGChain::import(CSGTerm *term, CSGTerm::type_e type) +{ + if (term->type == CSGTerm::PRIMITIVE) { + add(term->polyset, type, term->label); + } else { + import(term->left, type); + import(term->right, term->type); + } +} + +QString CSGChain::dump() +{ + QString text; + for (int i = 0; i < types.size(); i++) + { + if (types[i] == CSGTerm::UNION) { + if (i != 0) + text += "\n"; + text += "+"; + } + if (types[i] == CSGTerm::DIFFERENCE) + text += " -"; + if (types[i] == CSGTerm::INTERSECTION) + text += " *"; + text += labels[i]; + } + text += "\n"; + return text; +} + diff --git a/glview.cc b/glview.cc index 3260645f..b6132536 100644 --- a/glview.cc +++ b/glview.cc @@ -47,6 +47,19 @@ void GLView::initializeGL() glDepthRange(-FAR_FAR_AWAY, +FAR_FAR_AWAY); glClearColor(1.0, 1.0, 0.9, 0.0); + +#if 0 + GLfloat light_diffuse[] = {1.0, 1.0, 1.0, 1.0}; + GLfloat light_position[] = {1.0, 1.0, -1.0, 0.0}; + + glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); + glLightfv(GL_LIGHT0, GL_POSITION, light_position); + glEnable(GL_LIGHT0); + + glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); + glEnable(GL_COLOR_MATERIAL); + glEnable(GL_LIGHTING); +#endif } void GLView::resizeGL(int w, int h) @@ -56,7 +69,7 @@ void GLView::resizeGL(int w, int h) void GLView::paintGL() { - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); @@ -68,7 +81,10 @@ void GLView::paintGL() glRotated(object_rot_y, 1.0, 0.0, 0.0); glRotated(object_rot_z, 0.0, 0.0, 1.0); + glDepthFunc(GL_LESS); + #if 0 + glLineWidth(1); glColor3d(0.0, 0.0, 1.0); glBegin(GL_LINES); glVertex3d(0, 0, 0); glVertex3d(10, 0, 0); @@ -77,6 +93,7 @@ void GLView::paintGL() glEnd(); #endif + glLineWidth(5); glColor3d(1.0, 0.0, 0.0); if (renderfunc) diff --git a/mainwin.cc b/mainwin.cc index 67a757fa..55e29142 100644 --- a/mainwin.cc +++ b/mainwin.cc @@ -37,6 +37,7 @@ MainWindow::MainWindow(const char *filename) root_node = NULL; root_raw_term = NULL; root_norm_term = NULL; + root_chain = NULL; #ifdef ENABLE_CGAL root_N = NULL; #endif @@ -82,8 +83,8 @@ MainWindow::MainWindow(const char *filename) actViewModeCGALSurface->setCheckable(true); actViewModeCGALGrid->setCheckable(true); #endif - actViewModeTrownTogether = menu->addAction("Thrown Together", this, SLOT(viewModeTrownTogether())); - actViewModeTrownTogether->setCheckable(true); + actViewModeThrownTogether = menu->addAction("Thrown Together", this, SLOT(viewModeThrownTogether())); + actViewModeThrownTogether->setCheckable(true); menu->addSeparator(); menu->addAction("Top"); @@ -137,7 +138,7 @@ MainWindow::MainWindow(const char *filename) #ifdef ENABLE_OPENCSG viewModeOpenCSG(); #else - viewModeTrownTogether(); + viewModeThrownTogether(); #endif setCentralWidget(s1); @@ -267,6 +268,11 @@ void MainWindow::actionCompile() root_norm_term = NULL; } + if (root_chain) { + delete root_chain; + root_chain = NULL; + } + root_norm_term = root_raw_term->link(); while (1) { @@ -282,6 +288,9 @@ void MainWindow::actionCompile() return; } + root_chain = new CSGChain(); + root_chain->import(root_norm_term); + console->append("Compilation finished."); } @@ -296,23 +305,6 @@ static void report_func(const class AbstractNode*, void *vp, int mark) m->console->append(msg); } -#include - -static void renderGLviaCGAL(void *vp) -{ - MainWindow *m = (MainWindow*)vp; - if (m->root_N) { - CGAL::OGL::Polyhedron P; - CGAL::OGL::Nef3_Converter::convert_to_OGLPolyhedron(*m->root_N, &P); - P.init(); - if (m->actViewModeCGALSurface->isChecked()) - P.set_style(CGAL::OGL::SNC_BOUNDARY); - if (m->actViewModeCGALGrid->isChecked()) - P.set_style(CGAL::OGL::SNC_SKELETON); - P.draw(); - } -} - void MainWindow::actionRenderCGAL() { actionCompile(); @@ -356,7 +348,7 @@ void MainWindow::actionDisplayCSGTree() { QTextEdit *e = new QTextEdit(NULL); e->setTabStopWidth(30); - e->setWindowTitle("CSG Dump"); + e->setWindowTitle("CSG Tree Dump"); if (root_node) { e->setPlainText(root_node->dump("")); } else { @@ -370,8 +362,8 @@ void MainWindow::actionDisplayCSGProducts() { QTextEdit *e = new QTextEdit(NULL); e->setTabStopWidth(30); - e->setWindowTitle("CSG Dump"); - e->setPlainText(QString("\nCSG before normalization:\n%1\n\n\nCSG after normalization:\n%2\n").arg(root_raw_term ? root_raw_term->dump() : "N/A", root_norm_term ? root_norm_term->dump() : "N/A")); + e->setWindowTitle("CSG Products Dump"); + e->setPlainText(QString("\nCSG before normalization:\n%1\n\n\nCSG after normalization:\n%2\n\n\nCSG rendering chain:\n%3\n").arg(root_raw_term ? root_raw_term->dump() : "N/A", root_norm_term ? root_norm_term->dump() : "N/A", root_chain ? root_chain->dump() : "N/A")); e->show(); e->resize(600, 400); } @@ -395,17 +387,79 @@ void MainWindow::viewModeActionsUncheck() actViewModeCGALSurface->setChecked(false); actViewModeCGALGrid->setChecked(false); #endif - actViewModeTrownTogether->setChecked(false); + actViewModeThrownTogether->setChecked(false); } #ifdef ENABLE_OPENCSG +#include + +class DLPrim : public OpenCSG::Primitive +{ +public: + DLPrim(unsigned int displayListId, OpenCSG::Operation operation, unsigned int convexity) : + OpenCSG::Primitive(operation, convexity), id(displayListId) { } + virtual void render() { glCallList(id); } + unsigned int id; +}; + +static void renderGLviaOpenCSG(void *vp) +{ + MainWindow *m = (MainWindow*)vp; + static int glew_initialized = 0; + if (!glew_initialized) { + glew_initialized = 1; + glewInit(); + } + if (m->root_chain) { + glDepthFunc(GL_LEQUAL); + /* FIXME */ + for (int i = 0; i < m->root_chain->polysets.size(); i++) { + if (m->root_chain->types[i] == CSGTerm::DIFFERENCE) { + m->root_chain->polysets[i]->render_surface(PolySet::COLOR_CUTOUT); + m->root_chain->polysets[i]->render_edges(PolySet::COLOR_CUTOUT); + } else { + m->root_chain->polysets[i]->render_surface(PolySet::COLOR_MATERIAL); + m->root_chain->polysets[i]->render_edges(PolySet::COLOR_MATERIAL); + } + } + } else { + GLuint id1 = glGenLists(1); + glNewList(id1, GL_COMPILE); + glutSolidCube(1.8); + glEndList(); + + GLuint id2 = glGenLists(1); + glNewList(id2, GL_COMPILE); + glutSolidSphere(1.2, 20, 20); + glEndList(); + + DLPrim* box = new DLPrim(id1, OpenCSG::Intersection, 1); + DLPrim* sphere = new DLPrim(id2, OpenCSG::Subtraction, 1); + std::vector primitives; + + primitives.push_back(box); + primitives.push_back(sphere); + + OpenCSG::render(primitives, OpenCSG::Goldfeather, OpenCSG::NoDepthComplexitySampling); + + glDepthFunc(GL_EQUAL); + glColor3f(1.0, 0, 0); + for (unsigned int i = 0; i < primitives.size(); i++) { + primitives[i]->render(); + glDeleteLists(((DLPrim*)primitives[i])->id, 1); + delete primitives[i]; + } + glDepthFunc(GL_LESS); + } +} + void MainWindow::viewModeOpenCSG() { - /* FIXME */ viewModeActionsUncheck(); actViewModeOpenCSG->setChecked(true); - screen->renderfunc = NULL; + screen->renderfunc = renderGLviaOpenCSG; + screen->renderfunc_vp = this; screen->updateGL(); } @@ -413,6 +467,23 @@ void MainWindow::viewModeOpenCSG() #ifdef ENABLE_CGAL +#include + +static void renderGLviaCGAL(void *vp) +{ + MainWindow *m = (MainWindow*)vp; + if (m->root_N) { + CGAL::OGL::Polyhedron P; + CGAL::OGL::Nef3_Converter::convert_to_OGLPolyhedron(*m->root_N, &P); + P.init(); + if (m->actViewModeCGALSurface->isChecked()) + P.set_style(CGAL::OGL::SNC_BOUNDARY); + if (m->actViewModeCGALGrid->isChecked()) + P.set_style(CGAL::OGL::SNC_SKELETON); + P.draw(); + } +} + void MainWindow::viewModeCGALSurface() { viewModeActionsUncheck(); @@ -433,28 +504,28 @@ void MainWindow::viewModeCGALGrid() #endif /* ENABLE_CGAL */ -static void renderGLTrownTogether_worker(CSGTerm *t) -{ - if (t->left) - renderGLTrownTogether_worker(t->left); - if (t->right) - renderGLTrownTogether_worker(t->right); - if (t->polyset) - t->polyset->render_opengl(); -} - -static void renderGLTrownTogether(void *vp) +static void renderGLThrownTogether(void *vp) { MainWindow *m = (MainWindow*)vp; - if (m->root_raw_term) - renderGLTrownTogether_worker(m->root_raw_term); + if (m->root_chain) { + glDepthFunc(GL_LEQUAL); + for (int i = 0; i < m->root_chain->polysets.size(); i++) { + if (m->root_chain->types[i] == CSGTerm::DIFFERENCE) { + m->root_chain->polysets[i]->render_surface(PolySet::COLOR_CUTOUT); + m->root_chain->polysets[i]->render_edges(PolySet::COLOR_CUTOUT); + } else { + m->root_chain->polysets[i]->render_surface(PolySet::COLOR_MATERIAL); + m->root_chain->polysets[i]->render_edges(PolySet::COLOR_MATERIAL); + } + } + } } -void MainWindow::viewModeTrownTogether() +void MainWindow::viewModeThrownTogether() { viewModeActionsUncheck(); - actViewModeTrownTogether->setChecked(true); - screen->renderfunc = renderGLTrownTogether; + actViewModeThrownTogether->setChecked(true); + screen->renderfunc = renderGLThrownTogether; screen->renderfunc_vp = this; screen->updateGL(); } diff --git a/openscad.h b/openscad.h index e9a7455c..e62e79c9 100644 --- a/openscad.h +++ b/openscad.h @@ -31,6 +31,11 @@ static inline uint qHash(double v) { return x.u[0] ^ x.u[1]; } +#ifdef ENABLE_OPENCSG +// this must be included before the GL headers +# include +#endif + #include #include #include @@ -59,8 +64,9 @@ class ModuleInstanciation; class Module; class Context; -class CSGTerm; class PolySet; +class CSGTerm; +class CSGChain; class AbstractNode; class AbstractPolyNode; @@ -274,6 +280,10 @@ typedef CGAL_Nef_polyhedron::Point_3 CGAL_Point; #endif /* ENABLE_CGAL */ +#ifdef ENABLE_OPENCSG +# include +#endif + class PolySet { public: @@ -291,14 +301,20 @@ public: void append_vertex(double x, double y, double z); void insert_vertex(double x, double y, double z); - void render_opengl() const; + enum colormode_e { + COLOR_NONE, + COLOR_MATERIAL, + COLOR_CUTOUT + }; + + void render_surface(colormode_e colormode) const; + void render_edges(colormode_e colormode) const; #ifdef ENABLE_CGAL CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const; #endif }; -#ifdef ENABLE_OPENCSG class CSGTerm { public: @@ -327,7 +343,20 @@ public: void unlink(); QString dump(); }; -#endif + +class CSGChain +{ +public: + QVector polysets; + QVector types; + QVector labels; + + CSGChain(); + + void add(PolySet *polyset, CSGTerm::type_e type, QString label); + void import(CSGTerm *term, CSGTerm::type_e type = CSGTerm::UNION); + QString dump(); +}; class AbstractNode { @@ -346,9 +375,7 @@ public: #ifdef ENABLE_CGAL virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const; #endif -#ifdef ENABLE_OPENCSG virtual CSGTerm *render_csg_term(double m[16]) const; -#endif virtual QString dump(QString indent) const; }; @@ -363,9 +390,7 @@ public: #ifdef ENABLE_CGAL virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const; #endif -#ifdef ENABLE_OPENCSG virtual CSGTerm *render_csg_term(double m[16]) const; -#endif }; extern int progress_report_count; @@ -428,6 +453,7 @@ public: AbstractNode *root_node; CSGTerm *root_raw_term; CSGTerm *root_norm_term; + CSGChain *root_chain; #ifdef ENABLE_CGAL CGAL_Nef_polyhedron *root_N; #endif @@ -460,7 +486,7 @@ public: QAction *actViewModeCGALSurface; QAction *actViewModeCGALGrid; #endif - QAction *actViewModeTrownTogether; + QAction *actViewModeThrownTogether; void viewModeActionsUncheck(); private slots: @@ -471,7 +497,7 @@ private slots: void viewModeCGALSurface(); void viewModeCGALGrid(); #endif - void viewModeTrownTogether(); + void viewModeThrownTogether(); }; extern AbstractModule *parse(const char *text, int debug); diff --git a/openscad.pro b/openscad.pro index 30caf29e..ed4618e5 100644 --- a/openscad.pro +++ b/openscad.pro @@ -6,7 +6,7 @@ DEFINES += "ENABLE_CGAL=1" LIBS += -lCGAL -lmpfr DEFINES += "ENABLE_OPENCSG=1" -LIBS += -lopencsg -lGLEW +LIBS += -lopencsg -lGLEW -lglut LEXSOURCES += lexer.l YACCSOURCES += parser.y diff --git a/polyset.cc b/polyset.cc index a60828b5..63d8514e 100644 --- a/polyset.cc +++ b/polyset.cc @@ -41,8 +41,12 @@ void PolySet::insert_vertex(double x, double y, double z) polygons.last().insert(0, Point(x, y, z)); } -void PolySet::render_opengl() const +void PolySet::render_surface(colormode_e colormode) const { + if (colormode == COLOR_MATERIAL) + glColor3ub(249, 215, 44); + if (colormode == COLOR_CUTOUT) + glColor3ub(157, 203, 81); for (int i = 0; i < polygons.size(); i++) { const Polygon *poly = &polygons[i]; glBegin(GL_POLYGON); @@ -54,6 +58,23 @@ void PolySet::render_opengl() const } } +void PolySet::render_edges(colormode_e colormode) const +{ + if (colormode == COLOR_MATERIAL) + glColor3ub(255, 236, 94); + if (colormode == COLOR_CUTOUT) + glColor3ub(171, 216, 86); + for (int i = 0; i < polygons.size(); i++) { + const Polygon *poly = &polygons[i]; + glBegin(GL_LINE_STRIP); + for (int j = 0; j < poly->size(); j++) { + const Point *p = &poly->at(j); + glVertex3d(p->x, p->y, p->z); + } + glEnd(); + } +} + #ifdef ENABLE_CGAL class CGAL_Build_PolySet : public CGAL::Modifier_base