From 7b4cc84cdab040d92b4b98a2ce1fcfaea829bb5a Mon Sep 17 00:00:00 2001 From: clifford Date: Tue, 28 Jul 2009 12:53:52 +0000 Subject: [PATCH] Clifford Wolf: Added dxf polyset caching git-svn-id: http://svn.clifford.at/openscad/trunk@83 b57f626f-c46c-0410-a088-ec61d464b74c --- csgops.cc | 2 +- csgterm.cc | 11 +++++++---- dxflinextrude.cc | 24 ++++++++++++++++++++---- dxfrotextrude.cc | 14 ++++++++++++-- mainwin.cc | 16 ++++++++++++++-- module.cc | 12 ++++++------ openscad.cc | 49 ------------------------------------------------ openscad.h | 28 +++++++++++++++++++++------ polyset.cc | 39 ++++++++++++++++++++------------------ render.cc | 7 +++---- transform.cc | 2 +- 11 files changed, 107 insertions(+), 97 deletions(-) diff --git a/csgops.cc b/csgops.cc index 451c4c4f..2e7cf0a0 100644 --- a/csgops.cc +++ b/csgops.cc @@ -63,7 +63,7 @@ AbstractNode *CsgModule::evaluate(const Context*, const ModuleInstanciation *ins CGAL_Nef_polyhedron CsgNode::render_cgal_nef_polyhedron() const { - QString cache_id = cgal_nef_cache_id(); + QString cache_id = mk_cache_id(); if (cgal_nef_cache.contains(cache_id)) { progress_report(); return *cgal_nef_cache[cache_id]; diff --git a/csgterm.cc b/csgterm.cc index 6835f407..ae8dfb0d 100644 --- a/csgterm.cc +++ b/csgterm.cc @@ -22,13 +22,15 @@ #include "openscad.h" -CSGTerm::CSGTerm(PolySet *polyset, QString label) +CSGTerm::CSGTerm(PolySet *polyset, double m[16], QString label) { this->type = PRIMITIVE; this->polyset = polyset; this->label = label; this->left = NULL; this->right = NULL; + for (int i = 0; i < 16; i++) + this->m[i] = m[i]; refcounter = 1; } @@ -141,7 +143,7 @@ void CSGTerm::unlink() { if (--refcounter <= 0) { if (polyset) - delete polyset; + polyset->unlink(); if (left) left->unlink(); if (right) @@ -165,9 +167,10 @@ CSGChain::CSGChain() { } -void CSGChain::add(PolySet *polyset, CSGTerm::type_e type, QString label) +void CSGChain::add(PolySet *polyset, double *m, CSGTerm::type_e type, QString label) { polysets.append(polyset); + matrices.append(m); types.append(type); labels.append(label); } @@ -175,7 +178,7 @@ void CSGChain::add(PolySet *polyset, CSGTerm::type_e type, QString label) void CSGChain::import(CSGTerm *term, CSGTerm::type_e type) { if (term->type == CSGTerm::PRIMITIVE) { - add(term->polyset, type, term->label); + add(term->polyset, term->m, type, term->label); } else { import(term->left, type); import(term->right, term->type); diff --git a/dxflinextrude.cc b/dxflinextrude.cc index 0bb771ff..01c0319d 100644 --- a/dxflinextrude.cc +++ b/dxflinextrude.cc @@ -55,7 +55,7 @@ AbstractNode *DxfLinearExtrudeModule::evaluate(const Context *ctx, const ModuleI { DxfLinearExtrudeNode *node = new DxfLinearExtrudeNode(inst); - QVector argnames = QVector() << "file" << "layer" << "height" << "origin" << "scale" << "center"; + QVector argnames = QVector() << "file" << "layer" << "height" << "origin" << "scale" << "center" << "twist" << "slices"; QVector argexpr; Context c(ctx); @@ -155,8 +155,14 @@ static void add_slice(PolySet *ps, DxfData::Path *pt, double rot1, double rot2, } } +static QCache ps_cache(100); + PolySet *DxfLinearExtrudeNode::render_polyset(render_mode_e) const { + QString key = mk_cache_id(); + if (ps_cache.contains(key)) + return ps_cache[key]->ps->link(); + DxfData dxf(fn, fs, fa, filename, layername, origin_x, origin_y, scale); PolySet *ps = new PolySet(); @@ -220,6 +226,7 @@ PolySet *DxfLinearExtrudeNode::render_polyset(render_mode_e) const } } + ps_cache.insert(key, new PolySetPtr(ps->link())); return ps; } @@ -230,10 +237,19 @@ QString DxfLinearExtrudeNode::dump(QString indent) const struct stat st; memset(&st, 0, sizeof(struct stat)); stat(filename.toAscii().data(), &st); - text.sprintf("dxf_linear_extrude(file = \"%s\", cache = \"%x.%x\", layer = \"%s\", height = %f, " - "origin = [ %f %f ], scale = %f, $fn = %f, $fa = %f, $fs = %f);\n", + text.sprintf("dxf_linear_extrude(file = \"%s\", cache = \"%x.%x\", layer = \"%s\", " + "height = %f, origin = [ %f %f ], scale = %f, center = %s", filename.toAscii().data(), (int)st.st_mtime, (int)st.st_size, - layername.toAscii().data(), height, origin_x, origin_y, scale, fn, fs, fa); + layername.toAscii().data(), height, origin_x, origin_y, scale, + center ? "true" : "false"); + if (has_twist) { + QString t2; + t2.sprintf(", twist = %f, slices = %d", twist, slices); + text += t2; + } + QString t3; + t3.sprintf(", $fn = %f, $fa = %f, $fs = %f);\n", fn, fs, fa); + text += t3; ((AbstractNode*)this)->dump_cache = indent + QString("n%1: ").arg(idx) + text; } return dump_cache; diff --git a/dxfrotextrude.cc b/dxfrotextrude.cc index a622b911..955dbc88 100644 --- a/dxfrotextrude.cc +++ b/dxfrotextrude.cc @@ -89,8 +89,15 @@ void register_builtin_dxf_rotate_extrude() builtin_modules["dxf_rotate_extrude"] = new DxfRotateExtrudeModule(); } +static QCache ps_cache(100); + PolySet *DxfRotateExtrudeNode::render_polyset(render_mode_e) const { + QString key = mk_cache_id(); + + if (ps_cache.contains(key)) + return ps_cache[key]->ps->link(); + DxfData dxf(fn, fs, fa, filename, layername, origin_x, origin_y, scale); PolySet *ps = new PolySet(); @@ -151,6 +158,7 @@ PolySet *DxfRotateExtrudeNode::render_polyset(render_mode_e) const } } + ps_cache.insert(key, new PolySetPtr(ps->link())); return ps; } @@ -162,9 +170,11 @@ QString DxfRotateExtrudeNode::dump(QString indent) const memset(&st, 0, sizeof(struct stat)); stat(filename.toAscii().data(), &st); text.sprintf("dxf_rotate_extrude(file = \"%s\", cache = \"%x.%x\", layer = \"%s\", " - "origin = [ %f %f ], scale = %f, $fn = %f, $fa = %f, $fs = %f);\n", + "origin = [ %f %f ], scale = %f, convexity = %d, " + "$fn = %f, $fa = %f, $fs = %f);\n", filename.toAscii().data(), (int)st.st_mtime, (int)st.st_size, - layername.toAscii().data(), origin_x, origin_y, scale, fn, fs, fa); + layername.toAscii().data(), origin_x, origin_y, scale, convexity, + fn, fs, fa); ((AbstractNode*)this)->dump_cache = indent + QString("n%1: ").arg(idx) + text; } return dump_cache; diff --git a/mainwin.cc b/mainwin.cc index 144959e0..378491aa 100644 --- a/mainwin.cc +++ b/mainwin.cc @@ -297,6 +297,7 @@ void MainWindow::compile() find_root_tag(absolute_root_node); if (!root_node) root_node = absolute_root_node; + root_node->dump(""); PRINT("Compiling design (CSG Products generation)..."); QApplication::processEvents(); @@ -814,8 +815,12 @@ public: OpenCSGPrim(OpenCSG::Operation operation, unsigned int convexity) : OpenCSG::Primitive(operation, convexity) { } PolySet *p; + double *m; virtual void render() { + glPushMatrix(); + glMultMatrixd(m); p->render_surface(PolySet::COLOR_NONE); + glPopMatrix(); } }; @@ -834,6 +839,8 @@ static void renderCSGChainviaOpenCSG(CSGChain *chain, GLint *shaderinfo, bool hi if (shaderinfo) glUseProgram(shaderinfo[0]); for (; j < i; j++) { + glPushMatrix(); + glMultMatrixd(chain->matrices[j]); if (highlight) { chain->polysets[j]->render_surface(PolySet::COLOR_HIGHLIGHT, shaderinfo); } else if (background) { @@ -843,6 +850,7 @@ static void renderCSGChainviaOpenCSG(CSGChain *chain, GLint *shaderinfo, bool hi } else { chain->polysets[j]->render_surface(PolySet::COLOR_MATERIAL, shaderinfo); } + glPopMatrix(); } if (shaderinfo) glUseProgram(0); @@ -859,6 +867,7 @@ static void renderCSGChainviaOpenCSG(CSGChain *chain, GLint *shaderinfo, bool hi OpenCSGPrim *prim = new OpenCSGPrim(chain->types[i] == CSGTerm::DIFFERENCE ? OpenCSG::Subtraction : OpenCSG::Intersection, chain->polysets[i]->convexity); prim->p = chain->polysets[i]; + prim->m = chain->matrices[i]; primitives.push_back(prim); } } @@ -972,11 +981,13 @@ void MainWindow::viewModeCGALGrid() static void renderGLThrownTogetherChain(MainWindow *m, CSGChain *chain, bool highlight, bool background) { glDepthFunc(GL_LEQUAL); - QHash polySetVisitMark; + QHash,int> polySetVisitMark; bool showEdges = m->actViewModeShowEdges->isChecked(); for (int i = 0; i < chain->polysets.size(); i++) { - if (polySetVisitMark[chain->polysets[i]]++ > 0) + if (polySetVisitMark[QPair(chain->polysets[i], chain->matrices[i])]++ > 0) continue; + glPushMatrix(); + glMultMatrixd(chain->matrices[i]); if (highlight) { chain->polysets[i]->render_surface(PolySet::COLOR_HIGHLIGHT); if (showEdges) { @@ -1006,6 +1017,7 @@ static void renderGLThrownTogetherChain(MainWindow *m, CSGChain *chain, bool hig glEnable(GL_LIGHTING); } } + glPopMatrix(); } } diff --git a/module.cc b/module.cc index 66e7c73d..98c1eb98 100644 --- a/module.cc +++ b/module.cc @@ -217,11 +217,7 @@ AbstractNode::~AbstractNode() delete v; } -#ifdef ENABLE_CGAL - -QCache AbstractNode::cgal_nef_cache; - -QString AbstractNode::cgal_nef_cache_id() const +QString AbstractNode::mk_cache_id() const { QString cache_id = dump(""); cache_id.remove(QRegExp("[a-zA-Z_][a-zA-Z_0-9]*:")); @@ -231,9 +227,13 @@ QString AbstractNode::cgal_nef_cache_id() const return cache_id; } +#ifdef ENABLE_CGAL + +QCache AbstractNode::cgal_nef_cache(100000); + CGAL_Nef_polyhedron AbstractNode::render_cgal_nef_polyhedron() const { - QString cache_id = cgal_nef_cache_id(); + QString cache_id = mk_cache_id(); if (cgal_nef_cache.contains(cache_id)) { progress_report(); return *cgal_nef_cache[cache_id]; diff --git a/openscad.cc b/openscad.cc index fe5fadf5..31e5e6f3 100644 --- a/openscad.cc +++ b/openscad.cc @@ -24,21 +24,10 @@ #include -#if 0 -void report_func(const class AbstractNode*, void*, int mark) -{ - printf("CSG rendering progress: %.2f%%\n", (mark*100.0) / progress_report_count); -} -#endif - int main(int argc, char **argv) { int rc; -#ifdef ENABLE_CGAL - AbstractNode::cgal_nef_cache.setMaxCost(100000); -#endif - initialize_builtin_functions(); initialize_builtin_modules(); @@ -58,44 +47,6 @@ int main(int argc, char **argv) a.connect(m, SIGNAL(destroyed()), &a, SLOT(quit())); rc = a.exec(); -#if 0 - Context root_ctx(NULL); - root_ctx.functions_p = &builtin_functions; - root_ctx.modules_p = &builtin_modules; - - AbstractModule *root_module = parse(stdin, 0); - - printf("--- Abstract Syntax Tree ---\n"); - QString ast_text = root_module->dump("", "**root**"); - printf("%s", ast_text.toAscii().data()); - - AbstractNode *root_node = root_module->evaluate(&root_ctx, QVector(), QVector(), QVector()); - - printf("--- Compiled CSG Tree ---\n"); - QString csg_text = root_node->dump(""); - printf("%s", csg_text.toAscii().data()); - - CGAL_Nef_polyhedron N; - CGAL_Polyhedron P; - - progress_report_prep(root_node, report_func, NULL); - N = root_node->render_cgal_nef_polyhedron(); - progress_report_fin(); - printf("CSG rendering finished.\n"); - - N.convert_to_Polyhedron(P); - - std::ofstream outFile("output.off"); - if (outFile.fail()) { - std::cerr << "unable to open output file merged.off for writing!" << std::endl; - exit(1); - } - outFile << P; - - delete root_node; - delete root_module; -#endif - destroy_builtin_functions(); destroy_builtin_modules(); diff --git a/openscad.h b/openscad.h index 36931010..14eb80e4 100644 --- a/openscad.h +++ b/openscad.h @@ -487,17 +487,15 @@ public: typedef QList Polygon; QVector polygons; Grid3d grid; - double m[16]; int convexity; PolySet(); + ~PolySet(); void append_poly(); void append_vertex(double x, double y, double z); void insert_vertex(double x, double y, double z); - void setmatrix(double m[16]); - enum colormode_e { COLOR_NONE, COLOR_MATERIAL, @@ -512,6 +510,22 @@ public: #ifdef ENABLE_CGAL CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const; #endif + + int refcount; + PolySet *link(); + void unlink(); +}; + +class PolySetPtr +{ +public: + PolySet *ps; + PolySetPtr(PolySet *ps) { + this->ps = ps; + } + ~PolySetPtr() { + ps->unlink(); + } }; class CSGTerm @@ -529,9 +543,10 @@ public: QString label; CSGTerm *left; CSGTerm *right; + double m[16]; int refcounter; - CSGTerm(PolySet *polyset, QString label); + CSGTerm(PolySet *polyset, double m[16], QString label); CSGTerm(type_e type, CSGTerm *left, CSGTerm *right); CSGTerm *normalize(); @@ -546,12 +561,13 @@ class CSGChain { public: QVector polysets; + QVector matrices; QVector types; QVector labels; CSGChain(); - void add(PolySet *polyset, CSGTerm::type_e type, QString label); + void add(PolySet *polyset, double *m, CSGTerm::type_e type, QString label); void import(CSGTerm *term, CSGTerm::type_e type = CSGTerm::UNION); QString dump(); }; @@ -572,9 +588,9 @@ public: AbstractNode(const ModuleInstanciation *mi); virtual ~AbstractNode(); + virtual QString mk_cache_id() const; #ifdef ENABLE_CGAL static QCache cgal_nef_cache; - virtual QString cgal_nef_cache_id() const; virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const; #endif virtual CSGTerm *render_csg_term(double m[16], QVector *highlights, QVector *background) const; diff --git a/polyset.cc b/polyset.cc index b6509e35..1bc015b9 100644 --- a/polyset.cc +++ b/polyset.cc @@ -24,9 +24,25 @@ PolySet::PolySet() { - for (int i = 0; i < 16; i++) - m[i] = i % 5 == 0 ? 1.0 : 0.0; convexity = 1; + refcount = 1; +} + +PolySet::~PolySet() +{ + assert(refcount == 0); +} + +PolySet* PolySet::link() +{ + refcount++; + return this; +} + +void PolySet::unlink() +{ + if (--refcount == 0) + delete this; } void PolySet::append_poly() @@ -46,12 +62,6 @@ void PolySet::insert_vertex(double x, double y, double z) polygons.last().insert(0, Point(x, y, z)); } -void PolySet::setmatrix(double m[16]) -{ - for (int i = 0; i < 16; i++) - this->m[i] = m[i]; -} - static void gl_draw_triangle(GLint *shaderinfo, const PolySet::Point *p0, const PolySet::Point *p1, const PolySet::Point *p2, bool e0, bool e1, bool e2) { double ax = p1->x - p0->x, bx = p1->x - p2->x; @@ -94,8 +104,6 @@ static void gl_draw_triangle(GLint *shaderinfo, const PolySet::Point *p0, const void PolySet::render_surface(colormode_e colormode, GLint *shaderinfo) const { - glPushMatrix(); - glMultMatrixd(m); if (colormode == COLOR_MATERIAL) { glColor3ub(249, 215, 44); #ifdef ENABLE_OPENCSG @@ -164,13 +172,10 @@ void PolySet::render_surface(colormode_e colormode, GLint *shaderinfo) const } glEnd(); } - glPopMatrix(); } void PolySet::render_edges(colormode_e colormode) const { - glPushMatrix(); - glMultMatrixd(m); if (colormode == COLOR_MATERIAL) glColor3ub(255, 236, 94); if (colormode == COLOR_CUTOUT) @@ -188,7 +193,6 @@ void PolySet::render_edges(colormode_e colormode) const } glEnd(); } - glPopMatrix(); } #ifdef ENABLE_CGAL @@ -299,7 +303,7 @@ PolySet *AbstractPolyNode::render_polyset(render_mode_e) const CGAL_Nef_polyhedron AbstractPolyNode::render_cgal_nef_polyhedron() const { - QString cache_id = cgal_nef_cache_id(); + QString cache_id = mk_cache_id(); if (cgal_nef_cache.contains(cache_id)) { progress_report(); return *cgal_nef_cache[cache_id]; @@ -310,7 +314,7 @@ CGAL_Nef_polyhedron AbstractPolyNode::render_cgal_nef_polyhedron() const cgal_nef_cache.insert(cache_id, new CGAL_Nef_polyhedron(N), N.number_of_vertices()); progress_report(); - delete ps; + ps->unlink(); return N; } @@ -319,8 +323,7 @@ CGAL_Nef_polyhedron AbstractPolyNode::render_cgal_nef_polyhedron() const CSGTerm *AbstractPolyNode::render_csg_term(double m[16], QVector *highlights, QVector *background) const { PolySet *ps = render_polyset(RENDER_OPENCSG); - ps->setmatrix(m); - CSGTerm *t = new CSGTerm(ps, QString("n%1").arg(idx)); + CSGTerm *t = new CSGTerm(ps, m, QString("n%1").arg(idx)); if (modinst->tag_highlight && highlights) highlights->append(t->link()); if (modinst->tag_background && background) { diff --git a/render.cc b/render.cc index 8463172c..ee03e8c4 100644 --- a/render.cc +++ b/render.cc @@ -76,7 +76,7 @@ void register_builtin_render() CGAL_Nef_polyhedron RenderNode::render_cgal_nef_polyhedron() const { - QString cache_id = cgal_nef_cache_id(); + QString cache_id = mk_cache_id(); if (cgal_nef_cache.contains(cache_id)) { progress_report(); return *cgal_nef_cache[cache_id]; @@ -116,7 +116,7 @@ CSGTerm *RenderNode::render_csg_term(double m[16], QVector *highlights { CGAL_Nef_polyhedron N; - QString cache_id = cgal_nef_cache_id(); + QString cache_id = mk_cache_id(); if (cgal_nef_cache.contains(cache_id)) { N = *cgal_nef_cache[cache_id]; @@ -152,7 +152,6 @@ CSGTerm *RenderNode::render_csg_term(double m[16], QVector *highlights } PolySet *ps = new PolySet(); - ps->setmatrix(m); ps->convexity = convexity; CGAL_Polyhedron P; @@ -176,7 +175,7 @@ CSGTerm *RenderNode::render_csg_term(double m[16], QVector *highlights } while (hc != hc_end); } - CSGTerm *term = new CSGTerm(ps, QString("n%1").arg(idx)); + CSGTerm *term = new CSGTerm(ps, m, QString("n%1").arg(idx)); if (modinst->tag_highlight && highlights) highlights->append(term->link()); if (modinst->tag_background && background) { diff --git a/transform.cc b/transform.cc index bb25d41d..6e65c3a6 100644 --- a/transform.cc +++ b/transform.cc @@ -146,7 +146,7 @@ AbstractNode *TransformModule::evaluate(const Context *ctx, const ModuleInstanci CGAL_Nef_polyhedron TransformNode::render_cgal_nef_polyhedron() const { - QString cache_id = cgal_nef_cache_id(); + QString cache_id = mk_cache_id(); if (cgal_nef_cache.contains(cache_id)) { progress_report(); return *cgal_nef_cache[cache_id];