diff options
author | clifford <clifford@b57f626f-c46c-0410-a088-ec61d464b74c> | 2009-06-26 23:36:23 (GMT) |
---|---|---|
committer | clifford <clifford@b57f626f-c46c-0410-a088-ec61d464b74c> | 2009-06-26 23:36:23 (GMT) |
commit | 9479f8e77ba5af4778b1efe417f6c4452811d459 (patch) | |
tree | dfbc63a91e60f3e597cfb78f76865b05855da23c | |
parent | 221ae1832702367047232bd0f12970f0422a0478 (diff) |
Clifford Wolf:
Transforms (scale, rotate, translate, multmatrix)
Various matrix related fixes
git-svn-id: http://svn.clifford.at/openscad/trunk@29 b57f626f-c46c-0410-a088-ec61d464b74c
-rw-r--r-- | csgterm.cc | 6 | ||||
-rw-r--r-- | expr.cc | 2 | ||||
-rw-r--r-- | mainwin.cc | 4 | ||||
-rw-r--r-- | openscad.h | 6 | ||||
-rw-r--r-- | polyset.cc | 17 | ||||
-rw-r--r-- | transform.cc | 161 | ||||
-rw-r--r-- | value.cc | 2 |
7 files changed, 170 insertions, 28 deletions
@@ -22,15 +22,13 @@ #include "openscad.h" -CSGTerm::CSGTerm(PolySet *polyset, QString label, double m[16]) +CSGTerm::CSGTerm(PolySet *polyset, 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; } @@ -40,8 +38,6 @@ CSGTerm::CSGTerm(type_e type, CSGTerm *left, CSGTerm *right) this->polyset = NULL; this->left = left; this->right = right; - for (int i=0; i<16; i++) - this->m[i] = 0; refcounter = 1; } @@ -87,7 +87,7 @@ Value Expression::evaluate(const Context *context) const Value v = children[i]->evaluate(context); if (v.type != Value::NUMBER) return Value(); - m[i] = v.num; + m[i == 15 ? 15 : (i*4) % 15] = v.num; } return Value(m); } @@ -255,6 +255,10 @@ void MainWindow::actionCompile() } double m[16]; + + for (int i = 0; i < 16; i++) + m[i] = i % 5 == 0 ? 1.0 : 0.0; + root_raw_term = root_node->render_csg_term(m); if (!root_raw_term) { @@ -301,6 +301,7 @@ public: }; typedef QList<Point> Polygon; QVector<Polygon> polygons; + double m[16]; PolySet(); @@ -308,6 +309,8 @@ public: 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, @@ -338,9 +341,8 @@ public: CSGTerm *left; CSGTerm *right; int refcounter; - double m[16]; - CSGTerm(PolySet *polyset, QString label, double m[16]); + CSGTerm(PolySet *polyset, QString label); CSGTerm(type_e type, CSGTerm *left, CSGTerm *right); CSGTerm *normalize(); @@ -24,6 +24,8 @@ PolySet::PolySet() { + for (int i = 0; i < 16; i++) + m[i] = i % 5 == 0 ? 1.0 : 0.0; } void PolySet::append_poly() @@ -41,6 +43,12 @@ 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) { #ifdef ENABLE_OPENCSG @@ -75,6 +83,8 @@ 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 @@ -125,10 +135,13 @@ 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) @@ -142,6 +155,7 @@ void PolySet::render_edges(colormode_e colormode) const } glEnd(); } + glPopMatrix(); } #ifdef ENABLE_CGAL @@ -235,6 +249,7 @@ CGAL_Nef_polyhedron AbstractPolyNode::render_cgal_nef_polyhedron() const 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); + ps->setmatrix(m); + return new CSGTerm(ps, QString("n%1").arg(idx)); } diff --git a/transform.cc b/transform.cc index 978de53..7ebce98 100644 --- a/transform.cc +++ b/transform.cc @@ -22,47 +22,139 @@ #include "openscad.h" -class TransModule : public AbstractModule +enum transform_type_e { + SCALE, + ROTATE, + TRANSLATE, + MULTMATRIX +}; + +class TransformModule : public AbstractModule { public: + transform_type_e type; + TransformModule(transform_type_e type) : type(type) { } virtual AbstractNode *evaluate(const Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues, const QVector<AbstractNode*> child_nodes) const; }; -class TransNode : public AbstractNode +class TransformNode : public AbstractNode { public: - double x, y, z; + double m[16]; #ifdef ENABLE_CGAL virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const; #endif + virtual CSGTerm *render_csg_term(double m[16]) const; virtual QString dump(QString indent) const; }; -AbstractNode *TransModule::evaluate(const Context*, const QVector<QString>&, const QVector<Value> &call_argvalues, const QVector<AbstractNode*> child_nodes) const +AbstractNode *TransformModule::evaluate(const Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues, const QVector<AbstractNode*> child_nodes) const { - TransNode *node = new TransNode(); - if (call_argvalues.size() == 1 && call_argvalues[0].type == Value::VECTOR) { - node->x = call_argvalues[0].x; - node->y = call_argvalues[0].y; - node->z = call_argvalues[0].z; - } else { - node->x = 0; - node->y = 0; - node->z = 0; + TransformNode *node = new TransformNode(); + + for (int i = 0; i < 16; i++) { + node->m[i] = i % 5 == 0 ? 1.0 : 0.0; + } + + QVector<QString> argnames; + QVector<Expression*> argexpr; + + if (type == SCALE) { + argnames = QVector<QString>() << "v"; + } + if (type == ROTATE) { + argnames = QVector<QString>() << "a" << "v"; + } + if (type == TRANSLATE) { + argnames = QVector<QString>() << "v"; + } + if (type == MULTMATRIX) { + argnames = QVector<QString>() << "m"; + } + + Context c(ctx); + c.args(argnames, argexpr, call_argnames, call_argvalues); + + if (type == SCALE) + { + Value v = c.lookup_variable("v"); + if (v.type == Value::NUMBER) { + node->m[0] = v.num; + node->m[5] = v.num; + node->m[10] = v.num; + } + if (v.type == Value::VECTOR) { + node->m[0] = v.x; + node->m[5] = v.y; + node->m[10] = v.z; + } + } + if (type == ROTATE) + { + Value val_a = c.lookup_variable("a"); + Value val_v = c.lookup_variable("v"); + double a = 0, x = 0, y = 0, z = 1; + + if (val_a.type == Value::NUMBER) { + a = val_a.num; + } + + if (val_v.type == Value::VECTOR) { + x = val_v.x; y = val_v.y; z = val_v.z; + double sn = 1.0 / sqrt(x*x + y*y + z*z); + x *= sn; y *= sn; z *= sn; + } + + double c = cos(a*M_PI/180.0); + double s = sin(a*M_PI/180.0); + + node->m[ 0] = x*x*(1-c)+c; + node->m[ 1] = y*x*(1-c)+z*s; + node->m[ 2] = z*x*(1-c)-y*s; + + node->m[ 4] = x*y*(1-c)-z*s; + node->m[ 5] = y*y*(1-c)+c; + node->m[ 6] = z*y*(1-c)+x*s; + + node->m[ 8] = x*z*(1-c)+y*s; + node->m[ 9] = y*z*(1-c)-x*s; + node->m[10] = z*z*(1-c)+c; } + if (type == TRANSLATE) + { + Value v = c.lookup_variable("v"); + if (v.type == Value::VECTOR) { + node->m[12] = v.x; + node->m[13] = v.y; + node->m[14] = v.z; + } + } + if (type == MULTMATRIX) + { + Value v = c.lookup_variable("m"); + if (v.type == Value::MATRIX) { + for (int i = 0; i < 16; i++) + node->m[i] = v.m[i]; + } + } + foreach (AbstractNode *v, child_nodes) node->children.append(v); + return node; } #ifdef ENABLE_CGAL -CGAL_Nef_polyhedron TransNode::render_cgal_nef_polyhedron() const +CGAL_Nef_polyhedron TransformNode::render_cgal_nef_polyhedron() const { CGAL_Nef_polyhedron N; foreach (AbstractNode *v, children) N += v->render_cgal_nef_polyhedron(); - CGAL_Aff_transformation t(CGAL::TRANSLATION, CGAL_Vector(x, y, z)); + CGAL_Aff_transformation t( + m[0], m[4], m[ 8], m[12], + m[1], m[5], m[ 9], m[13], + m[2], m[6], m[10], m[14], m[15]); N.transform(t); progress_report(); return N; @@ -70,10 +162,40 @@ CGAL_Nef_polyhedron TransNode::render_cgal_nef_polyhedron() const #endif /* ENABLE_CGAL */ -QString TransNode::dump(QString indent) const +CSGTerm *TransformNode::render_csg_term(double c[16]) const +{ + double x[16]; + + for (int i = 0; i < 16; i++) + { + int c_row = i%4; + int m_col = i/4; + x[i] = 0; + for (int j = 0; j < 4; j++) + x[i] += c[c_row + j*4] * m[m_col*4 + j]; + } + + CSGTerm *t1 = NULL; + foreach(AbstractNode *v, children) + { + CSGTerm *t2 = v->render_csg_term(x); + if (t2 && !t1) { + t1 = t2; + } else if (t2 && t1) { + t1 = new CSGTerm(CSGTerm::UNION, t1, t2); + } + } + return t1; +} + +QString TransformNode::dump(QString indent) const { QString text; - text.sprintf("n%d: trans([%f %f %f])", idx, x, y, z); + text.sprintf("n%d: multmatrix([%f %f %f %f; %f %f %f %f; %f %f %f %f; %f %f %f %f])", idx, + m[0], m[4], m[ 8], m[12], + m[1], m[5], m[ 9], m[13], + m[2], m[6], m[10], m[14], + m[3], m[7], m[11], m[15]); text = indent + text + " {\n"; foreach (AbstractNode *v, children) text += v->dump(indent + QString("\t")); @@ -82,6 +204,9 @@ QString TransNode::dump(QString indent) const void register_builtin_trans() { - builtin_modules["trans"] = new TransModule(); + builtin_modules["scale"] = new TransformModule(SCALE); + builtin_modules["rotate"] = new TransformModule(ROTATE); + builtin_modules["translate"] = new TransformModule(TRANSLATE); + builtin_modules["multmatrix"] = new TransformModule(MULTMATRIX); } @@ -186,7 +186,7 @@ QString Value::dump() const QString text = "["; for (int i=0; i<16; i++) { QString t; - t.sprintf("%f", m[i]); + t.sprintf("%f", m[i == 15 ? 15 : (i*4) % 15]); if (i % 4 == 0 && i > 0) text += ";"; if (i > 0) |