Initial implementation of improved operator handling. Provides the bulk of work for #304

felipesanches-svg
Marius Kintel 2013-05-24 18:40:09 -04:00
parent ef9d8a853b
commit e1766faeed
9 changed files with 157 additions and 138 deletions

View File

@ -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<CSGTerm> evaluate_csg_term_from_ps(const State &state,
stream << node.name() << node.index();
shared_ptr<CSGTerm> 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()) {

View File

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

View File

@ -77,35 +77,45 @@ void OpenCSGRenderer::renderCSGChain(CSGChain *chain, GLint *shaderinfo,
std::vector<OpenCSG::Primitive*> 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);

View File

@ -31,6 +31,7 @@
#include "system-gl.h"
#include <boost/unordered_map.hpp>
#include <boost/foreach.hpp>
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<std::pair<PolySet*,Transform3d*>,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<std::pair<PolySet*,const Transform3d*>,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();

View File

@ -28,6 +28,7 @@
#include "polyset.h"
#include "linalg.h"
#include <sstream>
#include <boost/foreach.hpp>
/*!
\class CSGTerm
@ -103,19 +104,19 @@ shared_ptr<CSGTerm> CSGTerm::createCSGTerm(type_e type, CSGTerm *left, CSGTerm *
}
CSGTerm::CSGTerm(const shared_ptr<PolySet> &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<CSGTerm> left, shared_ptr<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();
}
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> &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<CSGTerm> term, CSGTerm::type_e type)
void CSGChain::import(shared_ptr<CSGTerm> 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;i<polysets.size();i++) {
if (types[i] != CSGTerm::TYPE_DIFFERENCE) {
BoundingBox psbox = polysets[i]->getBoundingBox();
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);
}
}
}

View File

@ -18,6 +18,12 @@ public:
TYPE_DIFFERENCE
};
enum Flag {
FLAG_NONE = 0x00,
FLAG_BACKGROUND = 0x01,
FLAG_HIGHLIGHT = 0x03
};
static shared_ptr<CSGTerm> createCSGTerm(type_e type, shared_ptr<CSGTerm> left, shared_ptr<CSGTerm> right);
static shared_ptr<CSGTerm> createCSGTerm(type_e type, CSGTerm *left, CSGTerm *right);
@ -27,6 +33,7 @@ public:
shared_ptr<CSGTerm> left;
shared_ptr<CSGTerm> right;
BoundingBox bbox;
Flag flag;
CSGTerm(const shared_ptr<PolySet> &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> 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> polyset;
Transform3d matrix;
Color4f color;
CSGTerm::type_e type;
std::string label;
CSGTerm::Flag flag;
};
class CSGChain
{
public:
std::vector<shared_ptr<PolySet> > polysets;
std::vector<Transform3d> matrices;
std::vector<Color4f> colors;
std::vector<CSGTerm::type_e> types;
std::vector<std::string> labels;
std::vector<CSGChainObject> objects;
CSGChain();
CSGChain() {};
void add(const shared_ptr<PolySet> &polyset, const Transform3d &m, const Color4f &color, CSGTerm::type_e type, std::string label);
void import(shared_ptr<CSGTerm> term, CSGTerm::type_e type = CSGTerm::TYPE_UNION);
void import(shared_ptr<CSGTerm> term, CSGTerm::type_e type = CSGTerm::TYPE_UNION,
CSGTerm::Flag flag = CSGTerm::FLAG_NONE);
std::string dump(bool full = false);
BoundingBox getBoundingBox() const;

View File

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

View File

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

View File

@ -2,6 +2,7 @@
#define RENDERER_H_
#include "system-gl.h"
#include "linalg.h"
#ifdef _MSC_VER // NULL
#include <cstdlib>
@ -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;