diff --git a/src/CSGTermEvaluator.cc b/src/CSGTermEvaluator.cc index 4624d4c6..9fc31474 100644 --- a/src/CSGTermEvaluator.cc +++ b/src/CSGTermEvaluator.cc @@ -57,6 +57,7 @@ void CSGTermEvaluator::applyToChildren(const AbstractNode &node, CSGTermEvaluato } } if (t1 && node.modinst->isHighlight()) { + t1->flag = CSGTerm::FLAG_HIGHLIGHT; this->highlights.push_back(t1); } if (t1 && node.modinst->isBackground()) { @@ -95,6 +96,7 @@ static shared_ptr evaluate_csg_term_from_ps(const State &state, stream << node.name() << node.index(); shared_ptr t(new CSGTerm(ps, state.matrix(), state.color(), stream.str())); if (modinst->isHighlight()) { + t->flag = CSGTerm::FLAG_HIGHLIGHT; highlights.push_back(t); } if (modinst->isBackground()) { diff --git a/src/CsgInfo.h b/src/CsgInfo.h index fe953b5a..774325bf 100644 --- a/src/CsgInfo.h +++ b/src/CsgInfo.h @@ -57,7 +57,7 @@ public: if (this->root_norm_term) { this->root_chain = new CSGChain(); this->root_chain->import(this->root_norm_term); - PRINTB("Normalized CSG tree has %d elements", int(this->root_chain->polysets.size())); + PRINTB("Normalized CSG tree has %d elements", int(this->root_chain->objects.size())); } else { this->root_chain = NULL; diff --git a/src/OpenCSGRenderer.cc b/src/OpenCSGRenderer.cc index add90d31..31f27db7 100644 --- a/src/OpenCSGRenderer.cc +++ b/src/OpenCSGRenderer.cc @@ -77,35 +77,45 @@ void OpenCSGRenderer::renderCSGChain(CSGChain *chain, GLint *shaderinfo, std::vector primitives; size_t j = 0; for (size_t i = 0;; i++) { - bool last = i == chain->polysets.size(); - if (last || chain->types[i] == CSGTerm::TYPE_UNION) { + const CSGChainObject &i_obj = chain->objects[i]; + bool last = i == chain->objects.size(); + if (last || i_obj.type == CSGTerm::TYPE_UNION) { if (j+1 != i) { OpenCSG::render(primitives); glDepthFunc(GL_EQUAL); } if (shaderinfo) glUseProgram(shaderinfo[0]); for (; j < i; j++) { - const Transform3d &m = chain->matrices[j]; - const Color4f &c = chain->colors[j]; + const CSGChainObject &j_obj = chain->objects[j]; + const Color4f &c = j_obj.color; glPushMatrix(); - glMultMatrixd(m.data()); - PolySet::csgmode_e csgmode = chain->types[j] == CSGTerm::TYPE_DIFFERENCE ? PolySet::CSGMODE_DIFFERENCE : PolySet::CSGMODE_NORMAL; - if (highlight) { - setColor(COLORMODE_HIGHLIGHT, shaderinfo); - csgmode = PolySet::csgmode_e(csgmode + 20); - } - else if (background) { - setColor(COLORMODE_BACKGROUND, c.data(), shaderinfo); + glMultMatrixd(j_obj.matrix.data()); + PolySet::csgmode_e csgmode = j_obj.type == CSGTerm::TYPE_DIFFERENCE ? PolySet::CSGMODE_DIFFERENCE : PolySet::CSGMODE_NORMAL; + ColorMode colormode = COLORMODE_NONE; + if (background) { + colormode = COLORMODE_BACKGROUND; csgmode = PolySet::csgmode_e(csgmode + 10); - } else if (c[0] >= 0 || c[1] >= 0 || c[2] >= 0 || c[3] >= 0) { - // User-defined color or alpha from source - setColor(c.data(), shaderinfo); - } else if (chain->types[j] == CSGTerm::TYPE_DIFFERENCE) { - setColor(COLORMODE_CUTOUT, shaderinfo); + } else if (j_obj.type == CSGTerm::TYPE_DIFFERENCE) { + if (j_obj.flag & CSGTerm::FLAG_HIGHLIGHT) { + colormode = COLORMODE_HIGHLIGHT; + csgmode = PolySet::csgmode_e(csgmode + 20); + } + else { + colormode = COLORMODE_CUTOUT; + } } else { - setColor(COLORMODE_MATERIAL, shaderinfo); + if (j_obj.flag & CSGTerm::FLAG_HIGHLIGHT) { + colormode = COLORMODE_HIGHLIGHT; + csgmode = PolySet::csgmode_e(csgmode + 20); + } + else { + colormode = COLORMODE_MATERIAL; + } } - chain->polysets[j]->render_surface(csgmode, m, shaderinfo); + + setColor(colormode, c.data(), shaderinfo); + + j_obj.polyset->render_surface(csgmode, j_obj.matrix, shaderinfo); glPopMatrix(); } if (shaderinfo) glUseProgram(0); @@ -118,11 +128,11 @@ void OpenCSGRenderer::renderCSGChain(CSGChain *chain, GLint *shaderinfo, if (last) break; - OpenCSGPrim *prim = new OpenCSGPrim(chain->types[i] == CSGTerm::TYPE_DIFFERENCE ? - OpenCSG::Subtraction : OpenCSG::Intersection, chain->polysets[i]->convexity); - prim->ps = chain->polysets[i]; - prim->m = chain->matrices[i]; - prim->csgmode = chain->types[i] == CSGTerm::TYPE_DIFFERENCE ? PolySet::CSGMODE_DIFFERENCE : PolySet::CSGMODE_NORMAL; + OpenCSGPrim *prim = new OpenCSGPrim(i_obj.type == CSGTerm::TYPE_DIFFERENCE ? + OpenCSG::Subtraction : OpenCSG::Intersection, i_obj.polyset->convexity); + prim->ps = i_obj.polyset; + prim->m = i_obj.matrix; + prim->csgmode = i_obj.type == CSGTerm::TYPE_DIFFERENCE ? PolySet::CSGMODE_DIFFERENCE : PolySet::CSGMODE_NORMAL; if (highlight) prim->csgmode = PolySet::csgmode_e(prim->csgmode + 20); else if (background) prim->csgmode = PolySet::csgmode_e(prim->csgmode + 10); primitives.push_back(prim); diff --git a/src/ThrownTogetherRenderer.cc b/src/ThrownTogetherRenderer.cc index 146d2e12..61511454 100644 --- a/src/ThrownTogetherRenderer.cc +++ b/src/ThrownTogetherRenderer.cc @@ -31,6 +31,7 @@ #include "system-gl.h" #include +#include ThrownTogetherRenderer::ThrownTogetherRenderer(CSGChain *root_chain, CSGChain *highlights_chain, @@ -62,56 +63,56 @@ void ThrownTogetherRenderer::renderCSGChain(CSGChain *chain, bool highlight, bool fberror) const { glDepthFunc(GL_LEQUAL); - boost::unordered_map,int> polySetVisitMark; - for (size_t i = 0; i < chain->polysets.size(); i++) { - if (polySetVisitMark[std::make_pair(chain->polysets[i].get(), &chain->matrices[i])]++ > 0) + boost::unordered_map,int> polySetVisitMark; + BOOST_FOREACH(const CSGChainObject &obj, chain->objects) { + if (polySetVisitMark[std::make_pair(obj.polyset.get(), &obj.matrix)]++ > 0) continue; - const Transform3d &m = chain->matrices[i]; - const Color4f &c = chain->colors[i]; + const Transform3d &m = obj.matrix; + const Color4f &c = obj.color; glPushMatrix(); glMultMatrixd(m.data()); - PolySet::csgmode_e csgmode = chain->types[i] == CSGTerm::TYPE_DIFFERENCE ? PolySet::CSGMODE_DIFFERENCE : PolySet::CSGMODE_NORMAL; + PolySet::csgmode_e csgmode = obj.type == CSGTerm::TYPE_DIFFERENCE ? PolySet::CSGMODE_DIFFERENCE : PolySet::CSGMODE_NORMAL; if (highlight) { csgmode = PolySet::csgmode_e(csgmode + 20); setColor(COLORMODE_HIGHLIGHT); - chain->polysets[i]->render_surface(csgmode, m); + obj.polyset->render_surface(csgmode, m); if (showedges) { setColor(COLORMODE_HIGHLIGHT_EDGES); - chain->polysets[i]->render_edges(csgmode); + obj.polyset->render_edges(csgmode); } } else if (background) { csgmode = PolySet::csgmode_e(csgmode + 10); setColor(COLORMODE_BACKGROUND); - chain->polysets[i]->render_surface(csgmode, m); + obj.polyset->render_surface(csgmode, m); if (showedges) { setColor(COLORMODE_BACKGROUND_EDGES); - chain->polysets[i]->render_edges(csgmode); + obj.polyset->render_edges(csgmode); } } else if (fberror) { if (highlight) csgmode = PolySet::csgmode_e(csgmode + 20); else if (background) csgmode = PolySet::csgmode_e(csgmode + 10); else csgmode = PolySet::csgmode_e(csgmode); - chain->polysets[i]->render_surface(csgmode, m); + obj.polyset->render_surface(csgmode, m); } else if (c[0] >= 0 || c[1] >= 0 || c[2] >= 0 || c[3] >= 0) { setColor(c.data()); - chain->polysets[i]->render_surface(csgmode, m); + obj.polyset->render_surface(csgmode, m); if (showedges) { glColor4f((c[0]+1)/2, (c[1]+1)/2, (c[2]+1)/2, 1.0); - chain->polysets[i]->render_edges(csgmode); + obj.polyset->render_edges(csgmode); } - } else if (chain->types[i] == CSGTerm::TYPE_DIFFERENCE) { + } else if (obj.type == CSGTerm::TYPE_DIFFERENCE) { setColor(COLORMODE_CUTOUT); - chain->polysets[i]->render_surface(csgmode, m); + obj.polyset->render_surface(csgmode, m); if (showedges) { setColor(COLORMODE_CUTOUT_EDGES); - chain->polysets[i]->render_edges(csgmode); + obj.polyset->render_edges(csgmode); } } else { setColor(COLORMODE_MATERIAL); - chain->polysets[i]->render_surface(csgmode, m); + obj.polyset->render_surface(csgmode, m); if (showedges) { setColor(COLORMODE_MATERIAL_EDGES); - chain->polysets[i]->render_edges(csgmode); + obj.polyset->render_edges(csgmode); } } glPopMatrix(); diff --git a/src/csgterm.cc b/src/csgterm.cc index aed97b24..7852715f 100644 --- a/src/csgterm.cc +++ b/src/csgterm.cc @@ -28,6 +28,7 @@ #include "polyset.h" #include "linalg.h" #include +#include /*! \class CSGTerm @@ -103,19 +104,19 @@ shared_ptr CSGTerm::createCSGTerm(type_e type, CSGTerm *left, CSGTerm * } CSGTerm::CSGTerm(const shared_ptr &polyset, const Transform3d &matrix, const Color4f &color, const std::string &label) - : type(TYPE_PRIMITIVE), polyset(polyset), label(label), m(matrix), color(color) + : type(TYPE_PRIMITIVE), polyset(polyset), label(label), flag(CSGTerm::FLAG_NONE), m(matrix), color(color) { initBoundingBox(); } CSGTerm::CSGTerm(type_e type, shared_ptr left, shared_ptr right) - : type(type), left(left), right(right), m(Transform3d::Identity()) + : type(type), left(left), right(right), flag(CSGTerm::FLAG_NONE), m(Transform3d::Identity()) { initBoundingBox(); } CSGTerm::CSGTerm(type_e type, CSGTerm *left, CSGTerm *right) - : type(type), left(left), right(right), m(Transform3d::Identity()) + : type(type), left(left), right(right), flag(CSGTerm::FLAG_NONE), m(Transform3d::Identity()) { initBoundingBox(); } @@ -181,26 +182,14 @@ std::string CSGTerm::dump() return dump.str(); } -CSGChain::CSGChain() -{ -} - -void CSGChain::add(const shared_ptr &polyset, const Transform3d &m, const Color4f &color, CSGTerm::type_e type, std::string label) -{ - polysets.push_back(polyset); - matrices.push_back(m); - colors.push_back(color); - types.push_back(type); - labels.push_back(label); -} - -void CSGChain::import(shared_ptr term, CSGTerm::type_e type) +void CSGChain::import(shared_ptr term, CSGTerm::type_e type, CSGTerm::Flag flag) { + CSGTerm::Flag newflag = (CSGTerm::Flag)(term->flag | flag); if (term->type == CSGTerm::TYPE_PRIMITIVE) { - add(term->polyset, term->m, term->color, type, term->label); + this->objects.push_back(CSGChainObject(term->polyset, term->m, term->color, type, term->label, newflag)); } else { - import(term->left, type); - import(term->right, term->type); + import(term->left, type, newflag); + import(term->right, term->type, newflag); } } @@ -208,21 +197,20 @@ std::string CSGChain::dump(bool full) { std::stringstream dump; - for (size_t i = 0; i < types.size(); i++) - { - if (types[i] == CSGTerm::TYPE_UNION) { - if (i != 0) dump << "\n"; + BOOST_FOREACH(const CSGChainObject &obj, this->objects) { + if (obj.type == CSGTerm::TYPE_UNION) { + if (&obj != &this->objects.front()) dump << "\n"; dump << "+"; } - else if (types[i] == CSGTerm::TYPE_DIFFERENCE) + else if (obj.type == CSGTerm::TYPE_DIFFERENCE) dump << " -"; - else if (types[i] == CSGTerm::TYPE_INTERSECTION) + else if (obj.type == CSGTerm::TYPE_INTERSECTION) dump << " *"; - dump << labels[i]; + dump << obj.label; if (full) { - dump << " polyset: \n" << polysets[i]->dump() << "\n"; - dump << " matrix: \n" << matrices[i].matrix() << "\n"; - dump << " color: \n" << colors[i] << "\n"; + dump << " polyset: \n" << obj.polyset->dump() << "\n"; + dump << " matrix: \n" << obj.matrix.matrix() << "\n"; + dump << " color: \n" << obj.color << "\n"; } } dump << "\n"; @@ -232,11 +220,11 @@ std::string CSGChain::dump(bool full) BoundingBox CSGChain::getBoundingBox() const { BoundingBox bbox; - for (size_t i=0;igetBoundingBox(); + BOOST_FOREACH(const CSGChainObject &obj, this->objects) { + if (obj.type != CSGTerm::TYPE_DIFFERENCE) { + BoundingBox psbox = obj.polyset->getBoundingBox(); if (!psbox.isNull()) { - bbox.extend(matrices[i] * psbox); + bbox.extend(obj.matrix * psbox); } } } diff --git a/src/csgterm.h b/src/csgterm.h index 566ebc35..94878e5f 100644 --- a/src/csgterm.h +++ b/src/csgterm.h @@ -18,6 +18,12 @@ public: TYPE_DIFFERENCE }; + enum Flag { + FLAG_NONE = 0x00, + FLAG_BACKGROUND = 0x01, + FLAG_HIGHLIGHT = 0x03 + }; + static shared_ptr createCSGTerm(type_e type, shared_ptr left, shared_ptr right); static shared_ptr createCSGTerm(type_e type, CSGTerm *left, CSGTerm *right); @@ -27,6 +33,7 @@ public: shared_ptr left; shared_ptr right; BoundingBox bbox; + Flag flag; CSGTerm(const shared_ptr &polyset, const Transform3d &matrix, const Color4f &color, const std::string &label); ~CSGTerm(); @@ -46,19 +53,34 @@ private: friend class CSGChain; }; +class CSGChainObject +{ +public: + CSGChainObject(shared_ptr polyset, + const Transform3d &matrix, + const Color4f &color, + CSGTerm::type_e type, + const std::string &label, + CSGTerm::Flag flag = CSGTerm::FLAG_NONE) + : polyset(polyset), matrix(matrix), color(color), type(type), label(label), flag(flag) {} + + shared_ptr polyset; + Transform3d matrix; + Color4f color; + CSGTerm::type_e type; + std::string label; + CSGTerm::Flag flag; +}; + class CSGChain { public: - std::vector > polysets; - std::vector matrices; - std::vector colors; - std::vector types; - std::vector labels; + std::vector objects; - CSGChain(); + CSGChain() {}; - void add(const shared_ptr &polyset, const Transform3d &m, const Color4f &color, CSGTerm::type_e type, std::string label); - void import(shared_ptr term, CSGTerm::type_e type = CSGTerm::TYPE_UNION); + void import(shared_ptr term, CSGTerm::type_e type = CSGTerm::TYPE_UNION, + CSGTerm::Flag flag = CSGTerm::FLAG_NONE); std::string dump(bool full = false); BoundingBox getBoundingBox() const; diff --git a/src/mainwin.cc b/src/mainwin.cc index da3501d9..1ac96fa1 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -771,14 +771,14 @@ void MainWindow::compileCSG(bool procevents) } if (this->root_chain && - (this->root_chain->polysets.size() > + (this->root_chain->objects.size() > Preferences::inst()->getValue("advanced/openCSGLimit").toUInt())) { - PRINTB("WARNING: Normalized tree has %d elements!", this->root_chain->polysets.size()); + PRINTB("WARNING: Normalized tree has %d elements!", this->root_chain->objects.size()); PRINT("WARNING: OpenCSG rendering has been disabled."); } else { PRINTB("Normalized CSG tree has %d elements", - (this->root_chain ? this->root_chain->polysets.size() : 0)); + (this->root_chain ? this->root_chain->objects.size() : 0)); this->opencsgRenderer = new OpenCSGRenderer(this->root_chain, this->highlights_chain, this->background_chain, diff --git a/src/renderer.cc b/src/renderer.cc index 77dcde98..7c4f8d79 100644 --- a/src/renderer.cc +++ b/src/renderer.cc @@ -1,49 +1,11 @@ #include "renderer.h" #include "rendersettings.h" -#include "linalg.h" -void Renderer::setColor(const float color[4], GLint *shaderinfo) const +bool Renderer::getColor(Renderer::ColorMode colormode, Color4f &col) const { - Color4f col = RenderSettings::inst()->color(RenderSettings::OPENCSG_FACE_FRONT_COLOR); - float c[4] = {color[0], color[1], color[2], color[3]}; - if (c[0] < 0) c[0] = col[0]; - if (c[1] < 0) c[1] = col[1]; - if (c[2] < 0) c[2] = col[2]; - if (c[3] < 0) c[3] = col[3]; - glColor4fv(c); - if (shaderinfo) { - glUniform4f(shaderinfo[1], c[0], c[1], c[2], c[3]); - glUniform4f(shaderinfo[2], (c[0]+1)/2, (c[1]+1)/2, (c[2]+1)/2, 1.0); - } -} - -void Renderer::setColor(ColorMode colormode, const float color[4], GLint *shaderinfo) const -{ - if (colormode == COLORMODE_BACKGROUND && - color[0] >= 0 || color[1] >= 0 || color[2] >= 0 || color[3] >= 0) { - - Color4f col; - col.setRgb(180, 180, 180, 255); - float c[4] = {color[0], color[1], color[2], color[3]}; - if (c[0] < 0) c[0] = col[0]; - if (c[1] < 0) c[1] = col[1]; - if (c[2] < 0) c[2] = col[2]; - if (c[3] < 0) c[3] = col[3]; - - c[3] /= 2; // Background objects are half-transparent - setColor(c, shaderinfo); - } - else { - setColor(colormode, shaderinfo); - } -} - -void Renderer::setColor(ColorMode colormode, GLint *shaderinfo) const -{ - Color4f col; switch (colormode) { case COLORMODE_NONE: - return; + return false; break; case COLORMODE_MATERIAL: col = RenderSettings::inst()->color(RenderSettings::OPENCSG_FACE_FRONT_COLOR); @@ -52,7 +14,7 @@ void Renderer::setColor(ColorMode colormode, GLint *shaderinfo) const col = RenderSettings::inst()->color(RenderSettings::OPENCSG_FACE_BACK_COLOR); break; case COLORMODE_HIGHLIGHT: - col.setRgb(255, 157, 81, 128); + col.setRgb(255, 81, 81, 128); break; case COLORMODE_BACKGROUND: col.setRgb(180, 180, 180, 128); @@ -70,19 +32,51 @@ void Renderer::setColor(ColorMode colormode, GLint *shaderinfo) const col.setRgb(150, 150, 150, 128); break; default: - return; + return false; break; } - float rgba[4]; - rgba[0] = col[0]; - rgba[1] = col[1]; - rgba[2] = col[2]; - rgba[3] = col[3]; - glColor4fv(rgba); + return true; +} + +void Renderer::setColor(const float color[4], GLint *shaderinfo) const +{ + Color4f col = RenderSettings::inst()->color(RenderSettings::OPENCSG_FACE_FRONT_COLOR); + float c[4] = {color[0], color[1], color[2], color[3]}; + if (c[0] < 0) c[0] = col[0]; + if (c[1] < 0) c[1] = col[1]; + if (c[2] < 0) c[2] = col[2]; + if (c[3] < 0) c[3] = col[3]; + glColor4fv(c); #ifdef ENABLE_OPENCSG if (shaderinfo) { - glUniform4f(shaderinfo[1], col[0], col[1], col[2], 1.0f); - glUniform4f(shaderinfo[2], (col[0]+1)/2, (col[1]+1)/2, (col[2]+1)/2, 1.0f); + glUniform4f(shaderinfo[1], c[0], c[1], c[2], c[3]); + glUniform4f(shaderinfo[2], (c[0]+1)/2, (c[1]+1)/2, (c[2]+1)/2, 1.0); } #endif } + +void Renderer::setColor(ColorMode colormode, const float color[4], GLint *shaderinfo) const +{ + Color4f basecol; + if (getColor(colormode, basecol)) { + if (colormode == COLORMODE_BACKGROUND) { + basecol = Color4f(color[0] >= 0 ? color[0] : basecol[0], + color[1] >= 0 ? color[1] : basecol[1], + color[2] >= 0 ? color[2] : basecol[2], + color[3] >= 0 ? color[3] : basecol[3]); + } + else if (colormode != COLORMODE_HIGHLIGHT) { + basecol = Color4f(color[0] >= 0 ? color[0] : basecol[0], + color[1] >= 0 ? color[1] : basecol[1], + color[2] >= 0 ? color[2] : basecol[2], + color[3] >= 0 ? color[3] : basecol[3]); + } + setColor(basecol.data(), shaderinfo); + } +} + +void Renderer::setColor(ColorMode colormode, GLint *shaderinfo) const +{ + float c[4] = {-1,-1,-1,-1}; + setColor(colormode, c, shaderinfo); +} diff --git a/src/renderer.h b/src/renderer.h index 24c1d94a..f70b4e1e 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -2,6 +2,7 @@ #define RENDERER_H_ #include "system-gl.h" +#include "linalg.h" #ifdef _MSC_VER // NULL #include @@ -25,6 +26,7 @@ public: COLORMODE_BACKGROUND_EDGES }; + virtual bool getColor(ColorMode colormode, Color4f &col) const; virtual void setColor(const float color[4], GLint *shaderinfo = NULL) const; virtual void setColor(ColorMode colormode, GLint *shaderinfo = NULL) const; virtual void setColor(ColorMode colormode, const float color[4], GLint *shaderinfo = NULL) const;