diff options
author | clifford <clifford@b57f626f-c46c-0410-a088-ec61d464b74c> | 2009-07-14 05:25:55 (GMT) |
---|---|---|
committer | clifford <clifford@b57f626f-c46c-0410-a088-ec61d464b74c> | 2009-07-14 05:25:55 (GMT) |
commit | f950feace3beaeec9bd5a6d6e65f7790bd80a9d8 (patch) | |
tree | c03b995d7f2589612f0cb284c59e473289313791 | |
parent | 2bea6501b7d7be3e10dc6dae1609f80c5e542199 (diff) |
Clifford Wolf:
Fixed cylinders, added "render" statement
git-svn-id: http://svn.clifford.at/openscad/trunk@55 b57f626f-c46c-0410-a088-ec61d464b74c
-rw-r--r-- | example.scad | 32 | ||||
-rw-r--r-- | module.cc | 10 | ||||
-rw-r--r-- | openscad.h | 1 | ||||
-rw-r--r-- | openscad.pro | 2 | ||||
-rw-r--r-- | primitives.cc | 18 | ||||
-rw-r--r-- | render.cc | 200 |
6 files changed, 240 insertions, 23 deletions
diff --git a/example.scad b/example.scad index f91d22f..8c991cb 100644 --- a/example.scad +++ b/example.scad @@ -86,21 +86,26 @@ module test005() module test006() { - $fa = 30; + module edgeprofile() + { + render() difference() { + cube([20 20 150], center = true); + translate([-10 -10 0]) + cylinder(h = 150, r = 10, center = true); + } + } + difference() { cube(100, center = true); -// for (rot = [ [0 0 0], [1 0 0], [0 1 0] ]) { -// rotate(90, rot) -// for (x = [-1, +1], y = [-1, +1]) { -// difference() { -// translate([ x*50, y*50, 0 ]) -// cube([20 20 150], center = true); -// translate([ x*40, y*40, 0 ]) -// cylinder(h = 150, r = 10, center = true); -// } -// } -// } + for (rot = [ [0 0 0], [1 0 0], [0 1 0] ]) { + rotate(90, rot) + for (p = [[+1 +1 0], [-1 +1 90], [-1 -1 180], [+1 -1 270]]) { + translate([ p[0]*50, p[1]*50, 0 ]) + rotate(p[2], [0 0 1]) + edgeprofile(); + } + } for (i = [ [ 0, 0, [ [0 0] ] ], [ 90, 0, [ [-20 -20], [+20 +20] ] ], @@ -116,5 +121,4 @@ module test006() } } -test001(); - +test006(); @@ -190,6 +190,7 @@ void initialize_builtin_modules() register_builtin_transform(); register_builtin_primitives(); register_builtin_control(); + register_builtin_render(); } void destroy_builtin_modules() @@ -219,10 +220,11 @@ QCache<QString, CGAL_Nef_polyhedron> AbstractNode::cgal_nef_cache; QString AbstractNode::cgal_nef_cache_id() const { - QString cache_id = dump(""); - cache_id.remove(' '); - cache_id.remove('\t'); - cache_id.remove('\n'); + QString cache_id = dump(""); + cache_id.remove(QRegExp("[a-zA-Z_][a-zA-Z_0-9]*:")); + cache_id.remove(' '); + cache_id.remove('\t'); + cache_id.remove('\n'); return cache_id; } @@ -263,6 +263,7 @@ extern void register_builtin_csgops(); extern void register_builtin_transform(); extern void register_builtin_primitives(); extern void register_builtin_control(); +extern void register_builtin_render(); class Context { diff --git a/openscad.pro b/openscad.pro index 2446082..cd990e1 100644 --- a/openscad.pro +++ b/openscad.pro @@ -15,7 +15,7 @@ HEADERS += openscad.h SOURCES += openscad.cc mainwin.cc glview.cc SOURCES += value.cc expr.cc func.cc module.cc context.cc SOURCES += csgterm.cc polyset.cc csgops.cc transform.cc -SOURCES += primitives.cc control.cc +SOURCES += primitives.cc control.cc render.cc QMAKE_CXXFLAGS += -O3 -march=pentium // QMAKE_CXXFLAGS += -O3 -march=athlon64 diff --git a/primitives.cc b/primitives.cc index a2ca971..c08e0a1 100644 --- a/primitives.cc +++ b/primitives.cc @@ -286,10 +286,20 @@ sphere_next_r2: for (int i=0; i<fragments; i++) { double phi = (M_PI*2*i) / fragments; - circle1[i].x = r1*cos(phi); - circle1[i].y = r1*sin(phi); - circle2[i].x = r2*cos(phi); - circle2[i].y = r2*sin(phi); + if (r1 > 0) { + circle1[i].x = r1*cos(phi); + circle1[i].y = r1*sin(phi); + } else { + circle1[i].x = 0; + circle1[i].y = 0; + } + if (r2 > 0) { + circle2[i].x = r2*cos(phi); + circle2[i].y = r2*sin(phi); + } else { + circle2[i].x = 0; + circle2[i].y = 0; + } } for (int i=0; i<fragments; i++) { diff --git a/render.cc b/render.cc new file mode 100644 index 0000000..1d73f1e --- /dev/null +++ b/render.cc @@ -0,0 +1,200 @@ +/* + * OpenSCAD (www.openscad.at) + * Copyright (C) 2009 Clifford Wolf <clifford@clifford.at> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#define INCLUDE_ABSTRACT_NODE_DETAILS + +#include "openscad.h" +#include <QProgressDialog> +#include <QApplication> +#include <QTime> + +class RenderModule : public AbstractModule +{ +public: + RenderModule() { } + virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstanciation *inst) const; +}; + +class RenderNode : public AbstractNode +{ +public: + RenderNode(const ModuleInstanciation *mi) : AbstractNode(mi) { } +#ifdef ENABLE_CGAL + virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const; +#endif + CSGTerm *render_csg_term(double m[16], QVector<CSGTerm*> *highlights) const; + virtual QString dump(QString indent) const; +}; + +AbstractNode *RenderModule::evaluate(const Context*, const ModuleInstanciation *inst) const +{ + RenderNode *node = new RenderNode(inst); + foreach (ModuleInstanciation *v, inst->children) { + AbstractNode *n = v->evaluate(inst->ctx); + if (n != NULL) + node->children.append(n); + } + return node; +} + +void register_builtin_render() +{ + builtin_modules["render"] = new RenderModule(); +} + +#ifdef ENABLE_CGAL + +CGAL_Nef_polyhedron RenderNode::render_cgal_nef_polyhedron() const +{ + QString cache_id = cgal_nef_cache_id(); + if (cgal_nef_cache.contains(cache_id)) { + progress_report(); + return *cgal_nef_cache[cache_id]; + } + + bool first = true; + CGAL_Nef_polyhedron N; + foreach(AbstractNode * v, children) + { + if (first) { + N = v->render_cgal_nef_polyhedron(); + first = false; + } else { + N += v->render_cgal_nef_polyhedron(); + } + } + + cgal_nef_cache.insert(cache_id, new CGAL_Nef_polyhedron(N), N.number_of_vertices()); + progress_report(); + return N; +} + +static void report_func(const class AbstractNode*, void *vp, int mark) +{ + QProgressDialog *pd = (QProgressDialog*)vp; + int v = (int)((mark*100.0) / progress_report_count); + pd->setValue(v < 100 ? v : 99); + QString label; + label.sprintf("Rendering Polygon Mesh using CGAL (%d/%d)", mark, progress_report_count); + pd->setLabelText(label); + QApplication::processEvents(); +} + +CSGTerm *RenderNode::render_csg_term(double m[16], QVector<CSGTerm*> *highlights) const +{ + CGAL_Nef_polyhedron N; + + QString cache_id = cgal_nef_cache_id(); + if (cgal_nef_cache.contains(cache_id)) + { + N = *cgal_nef_cache[cache_id]; + } + else + { + PRINT("Processing uncached render statement..."); + // PRINTA("Cache ID: %1", cache_id); + QApplication::processEvents(); + + QTime t; + t.start(); + + QProgressDialog *pd = new QProgressDialog("Rendering Polygon Mesh using CGAL...", QString(), 0, 100); + pd->setValue(0); + pd->setAutoClose(false); + pd->show(); + QApplication::processEvents(); + + progress_report_prep((AbstractNode*)this, report_func, pd); + N = this->render_cgal_nef_polyhedron(); + progress_report_fin(); + + int s = t.elapsed() / 1000; + PRINTF("..rendering time: %d hours, %d minutes, %d seconds", s / (60*60), (s / 60) % 60, s % 60); + + delete pd; + } + + if (!N.is_simple()) { + PRINTF("WARNING: Result of render() isn't a single polyeder or otherwise invalid! Modify your design.."); + return NULL; + } + + PolySet *ps = new PolySet(); + ps->setmatrix(m); + + CGAL_Polyhedron P; + N.convert_to_Polyhedron(P); + + typedef CGAL_Polyhedron::Vertex Vertex; + typedef CGAL_Polyhedron::Vertex_const_iterator VCI; + typedef CGAL_Polyhedron::Facet_const_iterator FCI; + typedef CGAL_Polyhedron::Halfedge_around_facet_const_circulator HFCC; + + for (FCI fi = P.facets_begin(); fi != P.facets_end(); ++fi) { + HFCC hc = fi->facet_begin(); + HFCC hc_end = hc; + ps->append_poly(); + do { + Vertex v = *VCI((hc++)->vertex()); + double x = CGAL::to_double(v.point().x()); + double y = CGAL::to_double(v.point().y()); + double z = CGAL::to_double(v.point().z()); + ps->append_vertex(x, y, z); + } while (hc != hc_end); + } + + CSGTerm *term = new CSGTerm(ps, QString("n%1").arg(idx)); + if (modinst->tag_highlight && highlights) + highlights->append(term->link()); + return term; +} + +#else + +CSGTerm *RenderNode::render_csg_term(double m[16], QVector<CSGTerm*> *highlights) const +{ + CSGTerm *t1 = NULL; + PRINT("WARNING: Found render() statement but compiled without CGAL support!"); + foreach(AbstractNode * v, children) { + CSGTerm *t2 = v->render_csg_term(m, highlights); + if (t2 && !t1) { + t1 = t2; + } else if (t2 && t1) { + t1 = new CSGTerm(CSGTerm::UNION, t1, t2); + } + } + if (modinst->tag_highlight && highlights) + highlights->append(t1->link()); + return t1; +} + +#endif + +QString RenderNode::dump(QString indent) const +{ + if (dump_cache.isEmpty()) { + QString text = indent + QString("n%1: ").arg(idx) + QString("render() {\n"); + foreach (AbstractNode *v, children) + text += v->dump(indent + QString("\t")); + ((AbstractNode*)this)->dump_cache = text + indent + "}\n"; + } + return dump_cache; +} + |