summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorclifford <clifford@b57f626f-c46c-0410-a088-ec61d464b74c>2009-07-14 05:25:55 (GMT)
committerclifford <clifford@b57f626f-c46c-0410-a088-ec61d464b74c>2009-07-14 05:25:55 (GMT)
commitf950feace3beaeec9bd5a6d6e65f7790bd80a9d8 (patch)
treec03b995d7f2589612f0cb284c59e473289313791
parent2bea6501b7d7be3e10dc6dae1609f80c5e542199 (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.scad32
-rw-r--r--module.cc10
-rw-r--r--openscad.h1
-rw-r--r--openscad.pro2
-rw-r--r--primitives.cc18
-rw-r--r--render.cc200
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();
diff --git a/module.cc b/module.cc
index a0c8423..18eaa43 100644
--- a/module.cc
+++ b/module.cc
@@ -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;
}
diff --git a/openscad.h b/openscad.h
index d793784..0ee83eb 100644
--- a/openscad.h
+++ b/openscad.h
@@ -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;
+}
+
contact: Jan Huwald // Impressum