diff options
-rw-r--r-- | csg.cc | 6 | ||||
-rw-r--r-- | glview.cc | 5 | ||||
-rw-r--r-- | module.cc | 4 | ||||
-rw-r--r-- | openscad.h | 1 | ||||
-rw-r--r-- | polyset.cc | 4 | ||||
-rw-r--r-- | primitive.cc | 73 |
6 files changed, 75 insertions, 18 deletions
@@ -44,9 +44,7 @@ public: #ifdef ENABLE_CGAL virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const; #endif -#ifdef ENABLE_OPENCSG CSGTerm *render_csg_term(double m[16]) const; -#endif virtual QString dump(QString indent) const; }; @@ -85,8 +83,6 @@ CGAL_Nef_polyhedron CsgNode::render_cgal_nef_polyhedron() const #endif /* ENABLE_CGAL */ -#ifdef ENABLE_OPENCSG - CSGTerm *CsgNode::render_csg_term(double m[16]) const { CSGTerm *t1 = NULL; @@ -107,8 +103,6 @@ CSGTerm *CsgNode::render_csg_term(double m[16]) const return t1; } -#endif /* ENABLE_OPENCSG */ - QString CsgNode::dump(QString indent) const { QString text = indent + QString("n%1: ").arg(idx); @@ -51,7 +51,8 @@ void GLView::initializeGL() void GLView::resizeGL(int w, int h) { - glViewport(0, 0, (GLint)w, (GLint)h); + glViewport(0, 0, w, h); + w_h_ratio = sqrt((double)w / (double)h); } void GLView::paintGL() @@ -60,7 +61,7 @@ void GLView::paintGL() glMatrixMode(GL_PROJECTION); glLoadIdentity(); - glFrustum(-1.0, +1.0, -1.0, +1.0, +10.0, +FAR_FAR_AWAY); + glFrustum(-w_h_ratio, +w_h_ratio, -(1/w_h_ratio), +(1/w_h_ratio), +10.0, +FAR_FAR_AWAY); gluLookAt(0.0, -viewer_distance, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0); glMatrixMode(GL_MODELVIEW); @@ -218,8 +218,6 @@ CGAL_Nef_polyhedron AbstractNode::render_cgal_nef_polyhedron() const #endif /* ENABLE_CGAL */ -#ifdef ENABLE_OPENCSG - CSGTerm *AbstractNode::render_csg_term(double m[16]) const { CSGTerm *t1 = NULL; @@ -234,8 +232,6 @@ CSGTerm *AbstractNode::render_csg_term(double m[16]) const return t1; } -#endif /* ENABLE_OPENCSG */ - QString AbstractNode::dump(QString indent) const { QString text = indent + QString("n%1: group() {\n").arg(idx); @@ -419,6 +419,7 @@ public: double viewer_distance; double object_rot_y; double object_rot_z; + double w_h_ratio; GLView(QWidget *parent = NULL); @@ -178,13 +178,9 @@ CGAL_Nef_polyhedron AbstractPolyNode::render_cgal_nef_polyhedron() const #endif /* ENABLE_CGAL */ -#ifdef ENABLE_OPENCSG - CSGTerm *AbstractPolyNode::render_csg_term(double m[16]) const { PolySet *ps = render_polyset(RENDER_OPENCSG); return new CSGTerm(ps, QString("n%1").arg(idx), m); } -#endif /* ENABLE_OPENCSG */ - diff --git a/primitive.cc b/primitive.cc index 2c1093e..beb73ba 100644 --- a/primitive.cc +++ b/primitive.cc @@ -132,6 +132,11 @@ void register_builtin_primitive() builtin_modules["cylinder"] = new PrimitiveModule(CYLINDER); } +int get_fragments_from_r(double r) +{ + double fa = 72, fs = 0.5; + return ceil(fmax(360.0 / fa, fmax(r*M_PI / fs, 5))); +} PolySet *PrimitiveNode::render_polyset(render_mode_e mode) const { @@ -193,12 +198,76 @@ PolySet *PrimitiveNode::render_polyset(render_mode_e mode) const if (type == SPHERE && r1 > 0) { - /* FIXME */ + struct point2d { + double x, y; + }; + + struct ring_s { + int fragments; + point2d *points; + double r, z; + }; + + int rings = get_fragments_from_r(r1); + ring_s ring[rings]; + + for (int i = 0; i < rings; i++) { + double phi = (M_PI * (i + 0.5)) / rings; + ring[i].r = r1 * sin(phi); + ring[i].z = r1 * cos(phi); + ring[i].fragments = get_fragments_from_r(ring[i].r); + ring[i].points = new point2d[ring[i].fragments]; + for (int j = 0; j < ring[i].fragments; j++) { + phi = (M_PI*2*j) / ring[i].fragments; + ring[i].points[j].x = ring[i].r * cos(phi); + ring[i].points[j].y = ring[i].r * sin(phi); + } + } + + p->append_poly(); + for (int i = 0; i < ring[0].fragments; i++) + p->insert_vertex(ring[0].points[i].x, ring[0].points[i].y, ring[0].z); + + for (int i = 0; i < rings-1; i++) { + ring_s *r1 = &ring[i]; + ring_s *r2 = &ring[i+1]; + int r1i = 0, r2i = 0; + while (r1i < r1->fragments || r2i < r2->fragments) + { + if (r1i >= r1->fragments) + goto sphere_next_r2; + if (r2i >= r2->fragments) + goto sphere_next_r1; + if ((double)r1i / r1->fragments < + (double)r2i / r2->fragments) + { +sphere_next_r1: + p->append_poly(); + int r1j = (r1i+1) % r1->fragments; + p->append_vertex(r1->points[r1i].x, r1->points[r1i].y, r1->z); + p->append_vertex(r1->points[r1j].x, r1->points[r1j].y, r1->z); + p->append_vertex(r2->points[r2i % r2->fragments].x, r2->points[r2i % r2->fragments].y, r2->z); + r1i++; + } else { +sphere_next_r2: + p->append_poly(); + int r2j = (r2i+1) % r2->fragments; + p->append_vertex(r2->points[r2i].x, r2->points[r2i].y, r2->z); + p->append_vertex(r2->points[r2j].x, r2->points[r2j].y, r2->z); + p->append_vertex(r1->points[r1i % r1->fragments].x, r1->points[r1i % r1->fragments].y, r1->z); + r2i++; + } + } + } + + p->append_poly(); + for (int i = 0; i < ring[rings-1].fragments; i++) + p->append_vertex(ring[rings-1].points[i].x, ring[rings-1].points[i].y, ring[rings-1].z); } if (type == CYLINDER && h > 0 && r1 >=0 && r2 >= 0 && (r1 > 0 || r2 > 0)) { - int fragments = 10; + int fragments = get_fragments_from_r(fmax(r1, r2)); double z1, z2; if (center) { |