diff options
author | Marius Kintel <marius@kintel.net> | 2010-11-03 18:26:06 (GMT) |
---|---|---|
committer | Marius Kintel <marius@kintel.net> | 2010-11-03 18:26:06 (GMT) |
commit | 264608981cfcd65de8e64af8d97648a315d52bc1 (patch) | |
tree | 486fed9c5c750d0e0b8c75290d315632db22c578 | |
parent | 4423c010301b8a94addee0ab0b3561023bba7290 (diff) |
Fixed some issues with PolySetRenderer, causing e.g. extrusions to fail in OpenCSG mode
-rw-r--r-- | src/CGALRenderer.cc | 2 | ||||
-rw-r--r-- | src/CGALRenderer.h | 6 | ||||
-rw-r--r-- | src/CSGTermRenderer.cc | 7 | ||||
-rw-r--r-- | src/CSGTermRenderer.h | 6 | ||||
-rw-r--r-- | src/PolySetCGALRenderer.cc | 29 | ||||
-rw-r--r-- | src/PolySetCGALRenderer.h | 3 | ||||
-rw-r--r-- | src/PolySetRenderer.h | 5 | ||||
-rw-r--r-- | src/csgterm.cc | 23 | ||||
-rw-r--r-- | src/dxflinextrude.cc | 6 | ||||
-rw-r--r-- | src/dxflinextrudenode.h | 2 | ||||
-rw-r--r-- | src/dxfrotextrude.cc | 6 | ||||
-rw-r--r-- | src/dxfrotextrudenode.h | 2 | ||||
-rw-r--r-- | src/import.cc | 2 | ||||
-rw-r--r-- | src/importnode.h | 2 | ||||
-rw-r--r-- | src/mainwin.cc | 20 | ||||
-rw-r--r-- | src/nef2dxf.cc | 1 | ||||
-rw-r--r-- | src/node.h | 2 | ||||
-rw-r--r-- | src/openscad.cc | 7 | ||||
-rw-r--r-- | src/primitives.cc | 4 | ||||
-rw-r--r-- | src/projection.cc | 5 | ||||
-rw-r--r-- | src/projectionnode.h | 2 | ||||
-rw-r--r-- | src/surface.cc | 4 |
22 files changed, 92 insertions, 54 deletions
diff --git a/src/CGALRenderer.cc b/src/CGALRenderer.cc index 9bdcfe1..9e98b61 100644 --- a/src/CGALRenderer.cc +++ b/src/CGALRenderer.cc @@ -230,7 +230,7 @@ Response CGALRenderer::visit(State &state, const AbstractPolyNode &node) applyToChildren(node, UNION); // Then apply polyset operation - PolySet *ps = node.render_polyset(AbstractPolyNode::RENDER_CGAL); + PolySet *ps = node.render_polyset(AbstractPolyNode::RENDER_CGAL, &this->psrenderer); try { CGAL_Nef_polyhedron N = renderCGALMesh(*ps); // print_messages_pop(); diff --git a/src/CGALRenderer.h b/src/CGALRenderer.h index 9a36522..def07a6 100644 --- a/src/CGALRenderer.h +++ b/src/CGALRenderer.h @@ -5,6 +5,7 @@ #include "visitor.h" #include "Tree.h" #include "cgal.h" +#include "PolySetCGALRenderer.h" #include <string> #include <map> @@ -23,7 +24,7 @@ class CGALRenderer : public Visitor public: enum CsgOp {UNION, INTERSECTION, DIFFERENCE, MINKOWSKI}; // FIXME: If a cache is not given, we need to fix this ourselves - CGALRenderer(QHash<string, CGAL_Nef_polyhedron> &cache, const Tree &tree) : cache(cache), tree(tree) {} + CGALRenderer(QHash<string, CGAL_Nef_polyhedron> &cache, const Tree &tree) : cache(cache), tree(tree), psrenderer(*this) {} virtual ~CGALRenderer() {} virtual Response visit(State &state, const AbstractNode &node); @@ -35,6 +36,8 @@ public: CGAL_Nef_polyhedron renderCGALMesh(const AbstractNode &node); CGAL_Nef_polyhedron renderCGALMesh(const PolySet &polyset); + const Tree &getTree() const { return this->tree; } + private: void addToParent(const State &state, const AbstractNode &node); bool isCached(const AbstractNode &node) const; @@ -47,6 +50,7 @@ private: QHash<string, CGAL_Nef_polyhedron> &cache; const Tree &tree; + PolySetCGALRenderer psrenderer; }; #endif diff --git a/src/CSGTermRenderer.cc b/src/CSGTermRenderer.cc index e59df1c..6f1f90c 100644 --- a/src/CSGTermRenderer.cc +++ b/src/CSGTermRenderer.cc @@ -26,10 +26,9 @@ CSGTerm *CSGTermRenderer::renderCSGTerm(const AbstractNode &node, vector<CSGTerm*> *highlights, vector<CSGTerm*> *background) { - CSGTermRenderer renderer; - Traverser render(renderer, node, Traverser::PRE_AND_POSTFIX); + Traverser render(*this, node, Traverser::PRE_AND_POSTFIX); render.execute(); - return renderer.stored_term[node.index()]; + return this->stored_term[node.index()]; } void CSGTermRenderer::applyToChildren(const AbstractNode &node, CSGTermRenderer::CsgOp op) @@ -101,7 +100,7 @@ static CSGTerm *render_csg_term_from_ps(const double m[20], Response CSGTermRenderer::visit(State &state, const AbstractPolyNode &node) { if (state.isPostfix()) { - PolySet *ps = node.render_polyset(AbstractPolyNode::RENDER_OPENCSG); + PolySet *ps = node.render_polyset(AbstractPolyNode::RENDER_OPENCSG, this->psrenderer); CSGTerm *t1 = render_csg_term_from_ps(state.matrix(), this->highlights, this->background, ps, node.modinst, node); this->stored_term[node.index()] = t1; addToParent(state, node); diff --git a/src/CSGTermRenderer.h b/src/CSGTermRenderer.h index fc3235e..ec3ee9c 100644 --- a/src/CSGTermRenderer.h +++ b/src/CSGTermRenderer.h @@ -5,6 +5,7 @@ #include <map> #include <list> #include <vector> +#include "Tree.h" #include "visitor.h" #include "node.h" @@ -16,7 +17,8 @@ using std::vector; class CSGTermRenderer : public Visitor { public: - CSGTermRenderer() : highlights(NULL), background(NULL) { + CSGTermRenderer(const Tree &tree, class PolySetRenderer *psrenderer = NULL) + : highlights(NULL), background(NULL), tree(tree), psrenderer(psrenderer) { } virtual ~CSGTermRenderer() {} @@ -44,6 +46,8 @@ public: vector<CSGTerm*> *highlights; vector<CSGTerm*> *background; + const Tree &tree; + class PolySetRenderer *psrenderer; }; #endif diff --git a/src/PolySetCGALRenderer.cc b/src/PolySetCGALRenderer.cc index 38cc1cc..b91098d 100644 --- a/src/PolySetCGALRenderer.cc +++ b/src/PolySetCGALRenderer.cc @@ -14,8 +14,7 @@ PolySet *PolySetCGALRenderer::renderPolySet(const ProjectionNode &node, AbstractPolyNode::render_mode_e) { - // FIXME: create cacheid from node - QString cacheid; + const string &cacheid = this->cgalrenderer.getTree().getString(node); if (this->cache.contains(cacheid)) return this->cache[cacheid]->ps->link(); CGAL_Nef_polyhedron N = this->cgalrenderer.renderCGALMesh(node); @@ -237,15 +236,22 @@ static void add_slice(PolySet *ps, DxfData::Path *pt, double rot1, double rot2, PolySet *PolySetCGALRenderer::renderPolySet(const DxfLinearExtrudeNode &node, AbstractPolyNode::render_mode_e) { - // FIXME: create cacheid from node - QString cacheid; + const string &cacheid = this->cgalrenderer.getTree().getString(node); if (this->cache.contains(cacheid)) return this->cache[cacheid]->ps->link(); DxfData *dxf; if (node.filename.isEmpty()) { - CGAL_Nef_polyhedron N = this->cgalrenderer.renderCGALMesh(node); + // Before extruding, union all (2D) children nodes + // to a single DxfData, then tesselate this into a PolySet + CGAL_Nef_polyhedron N; + N.dim = 2; + foreach (AbstractNode * v, node.getChildren()) { + if (v->modinst->tag_background) continue; + N.p2 += this->cgalrenderer.renderCGALMesh(*v).p2; + } + dxf = new DxfData(N); } else { dxf = new DxfData(node.fn, node.fs, node.fa, node.filename, node.layername, node.origin_x, node.origin_y, node.scale); @@ -320,15 +326,22 @@ PolySet *PolySetCGALRenderer::renderPolySet(const DxfLinearExtrudeNode &node, Ab PolySet *PolySetCGALRenderer::renderPolySet(const DxfRotateExtrudeNode &node, AbstractPolyNode::render_mode_e) { - // FIXME: create cacheid from node - QString cacheid; + const string &cacheid = this->cgalrenderer.getTree().getString(node); if (this->cache.contains(cacheid)) return this->cache[cacheid]->ps->link(); DxfData *dxf; if (node.filename.isEmpty()) { - CGAL_Nef_polyhedron N = this->cgalrenderer.renderCGALMesh(node); + // Before extruding, union all (2D) children nodes + // to a single DxfData, then tesselate this into a PolySet + CGAL_Nef_polyhedron N; + N.dim = 2; + foreach (AbstractNode * v, node.getChildren()) { + if (v->modinst->tag_background) continue; + N.p2 += this->cgalrenderer.renderCGALMesh(*v).p2; + } + dxf = new DxfData(N); } else { dxf = new DxfData(node.fn, node.fs, node.fa, node.filename, node.layername, node.origin_x, node.origin_y, node.scale); diff --git a/src/PolySetCGALRenderer.h b/src/PolySetCGALRenderer.h index ef71a57..d6ef63c 100644 --- a/src/PolySetCGALRenderer.h +++ b/src/PolySetCGALRenderer.h @@ -2,7 +2,6 @@ #define POLYSETCGALRENDERER_H_ #include "PolySetRenderer.h" -#include "CGALRenderer.h" /*! This is a PolySet renderer which uses the CGALRenderer to support building @@ -11,7 +10,7 @@ class PolySetCGALRenderer : public PolySetRenderer { public: - PolySetCGALRenderer(CGALRenderer &cgalrenderer) : + PolySetCGALRenderer(class CGALRenderer &cgalrenderer) : PolySetRenderer(), cgalrenderer(cgalrenderer) { } virtual ~PolySetCGALRenderer() { } virtual PolySet *renderPolySet(const ProjectionNode &node, AbstractPolyNode::render_mode_e); diff --git a/src/PolySetRenderer.h b/src/PolySetRenderer.h index ddd692f..c175825 100644 --- a/src/PolySetRenderer.h +++ b/src/PolySetRenderer.h @@ -1,6 +1,7 @@ #ifndef POLYSETRENDERER_H_ #define POLYSETRENDERER_H_ +#include "myqhash.h" #include "node.h" #include <QCache> @@ -20,8 +21,6 @@ public: this->cache.clear(); } - static PolySetRenderer *renderer() { return global_renderer; } - static void setRenderer(PolySetRenderer *r) { global_renderer = r; } protected: struct cache_entry { @@ -31,7 +30,7 @@ protected: ~cache_entry(); }; - QCache<QString, cache_entry> cache; + QCache<std::string, cache_entry> cache; private: static PolySetRenderer *global_renderer; diff --git a/src/csgterm.cc b/src/csgterm.cc index d0ab5df..0fd4196 100644 --- a/src/csgterm.cc +++ b/src/csgterm.cc @@ -26,6 +26,25 @@ #include "csgterm.h" #include "polyset.h" +/*! + \class CSGTerm + + A CSGTerm is either a "primitive" or a CSG operation with two + children terms. A primitive in this context is any PolySet, which + may or may not have a subtree which is already evaluated (e.g. using + the render() module). + + */ + +/*! + \class CSGChain + + A CSGChain is just a vector of primitives, each having a CSG type associated with it. + It's created by importing a CSGTerm tree. + + */ + + CSGTerm::CSGTerm(PolySet *polyset, const double m[20], QString label) { this->type = TYPE_PRIMITIVE; @@ -199,9 +218,9 @@ QString CSGChain::dump() text += "\n"; text += "+"; } - if (types[i] == CSGTerm::TYPE_DIFFERENCE) + else if (types[i] == CSGTerm::TYPE_DIFFERENCE) text += " -"; - if (types[i] == CSGTerm::TYPE_INTERSECTION) + else if (types[i] == CSGTerm::TYPE_INTERSECTION) text += " *"; text += labels[i]; } diff --git a/src/dxflinextrude.cc b/src/dxflinextrude.cc index d11a875..eb47b93 100644 --- a/src/dxflinextrude.cc +++ b/src/dxflinextrude.cc @@ -126,11 +126,11 @@ void register_builtin_dxf_linear_extrude() builtin_modules["linear_extrude"] = new DxfLinearExtrudeModule(); } -PolySet *DxfLinearExtrudeNode::render_polyset(render_mode_e mode) const +PolySet *DxfLinearExtrudeNode::render_polyset(render_mode_e mode, + PolySetRenderer *renderer) const { - PolySetRenderer *renderer = PolySetRenderer::renderer(); if (!renderer) { - PRINT("WARNING: No suitable PolySetRenderer found for linear_extrude() module!"); + PRINTF("WARNING: No suitable PolySetRenderer found for %s module!", this->name().c_str()); PolySet *ps = new PolySet(); ps->is2d = true; return ps; diff --git a/src/dxflinextrudenode.h b/src/dxflinextrudenode.h index 564ee55..8f829ea 100644 --- a/src/dxflinextrudenode.h +++ b/src/dxflinextrudenode.h @@ -24,7 +24,7 @@ public: double origin_x, origin_y, scale; bool center, has_twist; QString filename, layername; - virtual PolySet *render_polyset(render_mode_e mode) const; + virtual PolySet *render_polyset(render_mode_e mode, class PolySetRenderer *) const; }; #endif diff --git a/src/dxfrotextrude.cc b/src/dxfrotextrude.cc index 67a1c8c..7903579 100644 --- a/src/dxfrotextrude.cc +++ b/src/dxfrotextrude.cc @@ -102,11 +102,11 @@ void register_builtin_dxf_rotate_extrude() builtin_modules["rotate_extrude"] = new DxfRotateExtrudeModule(); } -PolySet *DxfRotateExtrudeNode::render_polyset(render_mode_e mode) const +PolySet *DxfRotateExtrudeNode::render_polyset(render_mode_e mode, + PolySetRenderer *renderer) const { - PolySetRenderer *renderer = PolySetRenderer::renderer(); if (!renderer) { - PRINT("WARNING: No suitable PolySetRenderer found for rotate_extrude() module!"); + PRINTF("WARNING: No suitable PolySetRenderer found for %s module!", this->name().c_str()); PolySet *ps = new PolySet(); ps->is2d = true; return ps; diff --git a/src/dxfrotextrudenode.h b/src/dxfrotextrudenode.h index dbf33a6..0372cb3 100644 --- a/src/dxfrotextrudenode.h +++ b/src/dxfrotextrudenode.h @@ -22,7 +22,7 @@ public: double fn, fs, fa; double origin_x, origin_y, scale; QString filename, layername; - virtual PolySet *render_polyset(render_mode_e mode) const; + virtual PolySet *render_polyset(render_mode_e mode, class PolySetRenderer *) const; }; #endif diff --git a/src/import.cc b/src/import.cc index f70930e..aeeeb71 100644 --- a/src/import.cc +++ b/src/import.cc @@ -102,7 +102,7 @@ void register_builtin_import() builtin_modules["import_dxf"] = new ImportModule(TYPE_DXF); } -PolySet *ImportNode::render_polyset(render_mode_e) const +PolySet *ImportNode::render_polyset(render_mode_e, class PolySetRenderer *) const { PolySet *p = new PolySet(); p->convexity = this->convexity; diff --git a/src/importnode.h b/src/importnode.h index b45ce22..a010d4c 100644 --- a/src/importnode.h +++ b/src/importnode.h @@ -26,7 +26,7 @@ public: int convexity; double fn, fs, fa; double origin_x, origin_y, scale; - virtual PolySet *render_polyset(render_mode_e mode) const; + virtual PolySet *render_polyset(render_mode_e mode, class PolySetRenderer *) const; }; #endif diff --git a/src/mainwin.cc b/src/mainwin.cc index be1a8ed..16ad59d 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -723,8 +723,12 @@ void MainWindow::compileCSG(bool procevents) progress_report_prep(root_node, report_func, pd); try { - CSGTermRenderer renderer; - root_raw_term = renderer.renderCSGTerm(*root_node, &highlight_terms, &background_terms); + // FIXME: put cache somewhere else as it's pretty useless now + QHash<std::string, CGAL_Nef_polyhedron> cache; + CGALRenderer cgalrenderer(cache, this->tree); + PolySetCGALRenderer psrenderer(cgalrenderer); + CSGTermRenderer csgrenderer(this->tree, &psrenderer); + root_raw_term = csgrenderer.renderCSGTerm(*root_node, &highlight_terms, &background_terms); if (!root_raw_term) { PRINT("ERROR: CSG generation failed! (no top level object found)"); if (procevents) @@ -770,12 +774,12 @@ void MainWindow::compileCSG(bool procevents) if (highlight_terms.size() > 0) { - PRINTF("Compiling highlights (%u CSG Trees)...", highlight_terms.size()); + PRINTF("Compiling highlights (%zu CSG Trees)...", highlight_terms.size()); if (procevents) QApplication::processEvents(); highlights_chain = new CSGChain(); - for (int i = 0; i < highlight_terms.size(); i++) { + for (unsigned int i = 0; i < highlight_terms.size(); i++) { while (1) { CSGTerm *n = highlight_terms[i]->normalize(); highlight_terms[i]->unlink(); @@ -789,12 +793,12 @@ void MainWindow::compileCSG(bool procevents) if (background_terms.size() > 0) { - PRINTF("Compiling background (%u CSG Trees)...", background_terms.size()); + PRINTF("Compiling background (%zu CSG Trees)...", background_terms.size()); if (procevents) QApplication::processEvents(); background_chain = new CSGChain(); - for (int i = 0; i < background_terms.size(); i++) { + for (unsigned int i = 0; i < background_terms.size(); i++) { while (1) { CSGTerm *n = background_terms[i]->normalize(); background_terms[i]->unlink(); @@ -1134,7 +1138,7 @@ void MainWindow::actionRenderCGAL() progress_report_prep(this->root_node, report_func, pd); try { - // FIXME: put cache somewhere else + // FIXME: put cache somewhere else as it's pretty useless now QHash<std::string, CGAL_Nef_polyhedron> cache; CGALRenderer renderer(cache, this->tree); this->root_N = new CGAL_Nef_polyhedron(renderer.renderCGALMesh(*this->root_node)); @@ -1378,7 +1382,7 @@ void MainWindow::actionExportDXF() void MainWindow::actionFlushCaches() { // FIXME: Polycache -> PolySetRenderer - PolySetRenderer::renderer()->clearCache(); +// FIXME: PolySetRenderer->clearCache(); #ifdef ENABLE_CGAL // FIXME: Flush caches through whatever channels we have // CGALRenderer::renderer()->getCache().clear(); diff --git a/src/nef2dxf.cc b/src/nef2dxf.cc index 44d7561..4c57e39 100644 --- a/src/nef2dxf.cc +++ b/src/nef2dxf.cc @@ -31,6 +31,7 @@ DxfData::DxfData(const struct CGAL_Nef_polyhedron &N) { + assert(N.dim == 2); Grid2d<int> grid(GRID_COARSE); typedef CGAL_Nef_polyhedron2::Explorer Explorer; @@ -80,7 +80,7 @@ public: /*! Should return a PolySet of the given geometry. It's normal to return an empty PolySet if smth. is wrong, but don't return NULL unless we change the calling strategy for this method. */ - virtual class PolySet *render_polyset(render_mode_e mode) const = 0; + virtual class PolySet *render_polyset(render_mode_e mode, class PolySetRenderer *renderer) const = 0; }; std::ostream &operator<<(std::ostream &stream, const AbstractNode &node); diff --git a/src/openscad.cc b/src/openscad.cc index ba4d574..4f63bb4 100644 --- a/src/openscad.cc +++ b/src/openscad.cc @@ -248,7 +248,6 @@ int main(int argc, char **argv) QHash<std::string, CGAL_Nef_polyhedron> cache; CGALRenderer cgalrenderer(cache, tree); PolySetCGALRenderer psrenderer(cgalrenderer); - PolySetRenderer::setRenderer(&psrenderer); if (stl_output_file || off_output_file || dxf_output_file) { @@ -300,10 +299,8 @@ int main(int argc, char **argv) AbstractNode::resetIndexCounter(); root_node = root_module->evaluate(&root_ctx, &root_inst); - Tree tree(root_node); - QHash<std::string, CGAL_Nef_polyhedron> cache; - CGALRenderer renderer(cache, tree); - CGAL_Nef_polyhedron root_N = renderer.renderCGALMesh(*tree.root()); + tree.setRoot(root_node); + CGAL_Nef_polyhedron root_N = cgalrenderer.renderCGALMesh(*tree.root()); QDir::setCurrent(original_path.absolutePath()); diff --git a/src/primitives.cc b/src/primitives.cc index 301df24..dd284fa 100644 --- a/src/primitives.cc +++ b/src/primitives.cc @@ -97,7 +97,7 @@ public: primitive_type_e type; int convexity; Value points, paths, triangles; - virtual PolySet *render_polyset(render_mode_e mode) const; + virtual PolySet *render_polyset(render_mode_e mode, class PolySetRenderer *) const; }; AbstractNode *PrimitiveModule::evaluate(const Context *ctx, const ModuleInstantiation *inst) const @@ -246,7 +246,7 @@ int get_fragments_from_r(double r, double fn, double fs, double fa) return (int)ceil(fmax(fmin(360.0 / fa, r*M_PI / fs), 5)); } -PolySet *PrimitiveNode::render_polyset(render_mode_e) const +PolySet *PrimitiveNode::render_polyset(render_mode_e, class PolySetRenderer *) const { PolySet *p = new PolySet(); diff --git a/src/projection.cc b/src/projection.cc index 073a5b1..b999d9b 100644 --- a/src/projection.cc +++ b/src/projection.cc @@ -85,11 +85,10 @@ AbstractNode *ProjectionModule::evaluate(const Context *ctx, const ModuleInstant return node; } -PolySet *ProjectionNode::render_polyset(render_mode_e mode) const +PolySet *ProjectionNode::render_polyset(render_mode_e mode, PolySetRenderer *renderer) const { - PolySetRenderer *renderer = PolySetRenderer::renderer(); if (!renderer) { - PRINT("WARNING: No suitable PolySetRenderer found for projection() module!"); + PRINTF("WARNING: No suitable PolySetRenderer found for %s module!", this->name().c_str()); PolySet *ps = new PolySet(); ps->is2d = true; return ps; diff --git a/src/projectionnode.h b/src/projectionnode.h index 9cc7918..295e48c 100644 --- a/src/projectionnode.h +++ b/src/projectionnode.h @@ -18,7 +18,7 @@ public: int convexity; bool cut_mode; - virtual PolySet *render_polyset(render_mode_e mode) const; + virtual PolySet *render_polyset(render_mode_e mode, class PolySetRenderer *renderer) const; }; #endif diff --git a/src/surface.cc b/src/surface.cc index b5f631e..725c1b1 100644 --- a/src/surface.cc +++ b/src/surface.cc @@ -56,7 +56,7 @@ public: QString filename; bool center; int convexity; - virtual PolySet *render_polyset(render_mode_e mode) const; + virtual PolySet *render_polyset(render_mode_e mode, class PolySetRenderer *) const; }; AbstractNode *SurfaceModule::evaluate(const Context *ctx, const ModuleInstantiation *inst) const @@ -91,7 +91,7 @@ void register_builtin_surface() builtin_modules["surface"] = new SurfaceModule(); } -PolySet *SurfaceNode::render_polyset(render_mode_e) const +PolySet *SurfaceNode::render_polyset(render_mode_e, class PolySetRenderer *) const { PolySet *p = new PolySet(); handle_dep(filename); |