diff options
-rw-r--r-- | mainwin.cc | 28 | ||||
-rw-r--r-- | openscad.h | 2 | ||||
-rw-r--r-- | polyset.cc | 61 | ||||
-rw-r--r-- | transform.cc | 59 |
4 files changed, 100 insertions, 50 deletions
@@ -1160,7 +1160,7 @@ public: virtual void render() { glPushMatrix(); glMultMatrixd(m); - p->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode)); + p->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode), m); glPopMatrix(); } }; @@ -1187,20 +1187,20 @@ static void renderCSGChainviaOpenCSG(CSGChain *chain, GLint *shaderinfo, bool hi glMultMatrixd(m); int csgmode = chain->types[j] == CSGTerm::TYPE_DIFFERENCE ? PolySet::CSGMODE_DIFFERENCE : PolySet::CSGMODE_NORMAL; if (highlight) { - chain->polysets[j]->render_surface(PolySet::COLORMODE_HIGHLIGHT, PolySet::csgmode_e(csgmode + 20), shaderinfo); + chain->polysets[j]->render_surface(PolySet::COLORMODE_HIGHLIGHT, PolySet::csgmode_e(csgmode + 20), m, shaderinfo); } else if (background) { - chain->polysets[j]->render_surface(PolySet::COLORMODE_BACKGROUND, PolySet::csgmode_e(csgmode + 10), shaderinfo); + chain->polysets[j]->render_surface(PolySet::COLORMODE_BACKGROUND, PolySet::csgmode_e(csgmode + 10), m, shaderinfo); } else if (m[16] >= 0 || m[17] >= 0 || m[18] >= 0 || m[19] >= 0) { glColor4d(m[16], m[17], m[18], m[19]); if (shaderinfo) { glUniform4f(shaderinfo[1], m[16], m[17], m[18], m[19]); glUniform4f(shaderinfo[2], (m[16]+1)/2, (m[17]+1)/2, (m[18]+1)/2, 1.0); } - chain->polysets[j]->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode), shaderinfo); + chain->polysets[j]->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode), m, shaderinfo); } else if (chain->types[j] == CSGTerm::TYPE_DIFFERENCE) { - chain->polysets[j]->render_surface(PolySet::COLORMODE_CUTOUT, PolySet::csgmode_e(csgmode), shaderinfo); + chain->polysets[j]->render_surface(PolySet::COLORMODE_CUTOUT, PolySet::csgmode_e(csgmode), m, shaderinfo); } else { - chain->polysets[j]->render_surface(PolySet::COLORMODE_MATERIAL, PolySet::csgmode_e(csgmode), shaderinfo); + chain->polysets[j]->render_surface(PolySet::COLORMODE_MATERIAL, PolySet::csgmode_e(csgmode), m, shaderinfo); } glPopMatrix(); } @@ -1414,14 +1414,14 @@ static void renderGLThrownTogetherChain(MainWindow *m, CSGChain *chain, bool hig glMultMatrixd(m); int csgmode = chain->types[i] == CSGTerm::TYPE_DIFFERENCE ? PolySet::CSGMODE_DIFFERENCE : PolySet::CSGMODE_NORMAL; if (highlight) { - chain->polysets[i]->render_surface(PolySet::COLORMODE_HIGHLIGHT, PolySet::csgmode_e(csgmode + 20)); + chain->polysets[i]->render_surface(PolySet::COLORMODE_HIGHLIGHT, PolySet::csgmode_e(csgmode + 20), m); if (showEdges) { glDisable(GL_LIGHTING); chain->polysets[i]->render_edges(PolySet::COLORMODE_HIGHLIGHT, PolySet::csgmode_e(csgmode + 20)); glEnable(GL_LIGHTING); } } else if (background) { - chain->polysets[i]->render_surface(PolySet::COLORMODE_BACKGROUND, PolySet::csgmode_e(csgmode + 10)); + chain->polysets[i]->render_surface(PolySet::COLORMODE_BACKGROUND, PolySet::csgmode_e(csgmode + 10), m); if (showEdges) { glDisable(GL_LIGHTING); chain->polysets[i]->render_edges(PolySet::COLORMODE_BACKGROUND, PolySet::csgmode_e(csgmode + 10)); @@ -1429,15 +1429,15 @@ static void renderGLThrownTogetherChain(MainWindow *m, CSGChain *chain, bool hig } } else if (fberror) { if (highlight) { - chain->polysets[i]->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode + 20)); + chain->polysets[i]->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode + 20), m); } else if (background) { - chain->polysets[i]->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode + 10)); + chain->polysets[i]->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode + 10), m); } else { - chain->polysets[i]->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode)); + chain->polysets[i]->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode), m); } } else if (m[16] >= 0 || m[17] >= 0 || m[18] >= 0 || m[19] >= 0) { glColor4d(m[16], m[17], m[18], m[19]); - chain->polysets[i]->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode)); + chain->polysets[i]->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode), m); if (showEdges) { glDisable(GL_LIGHTING); glColor4d((m[16]+1)/2, (m[17]+1)/2, (m[18]+1)/2, 1.0); @@ -1445,14 +1445,14 @@ static void renderGLThrownTogetherChain(MainWindow *m, CSGChain *chain, bool hig glEnable(GL_LIGHTING); } } else if (chain->types[i] == CSGTerm::TYPE_DIFFERENCE) { - chain->polysets[i]->render_surface(PolySet::COLORMODE_CUTOUT, PolySet::csgmode_e(csgmode)); + chain->polysets[i]->render_surface(PolySet::COLORMODE_CUTOUT, PolySet::csgmode_e(csgmode), m); if (showEdges) { glDisable(GL_LIGHTING); chain->polysets[i]->render_edges(PolySet::COLORMODE_CUTOUT, PolySet::csgmode_e(csgmode)); glEnable(GL_LIGHTING); } } else { - chain->polysets[i]->render_surface(PolySet::COLORMODE_MATERIAL, PolySet::csgmode_e(csgmode)); + chain->polysets[i]->render_surface(PolySet::COLORMODE_MATERIAL, PolySet::csgmode_e(csgmode), m); if (showEdges) { glDisable(GL_LIGHTING); chain->polysets[i]->render_edges(PolySet::COLORMODE_MATERIAL, PolySet::csgmode_e(csgmode)); @@ -571,7 +571,7 @@ public: static QCache<QString,ps_cache_entry> ps_cache; - void render_surface(colormode_e colormode, csgmode_e csgmode, GLint *shaderinfo = NULL) const; + void render_surface(colormode_e colormode, csgmode_e csgmode, double *m, GLint *shaderinfo = NULL) const; void render_edges(colormode_e colormode, csgmode_e csgmode) const; #ifdef ENABLE_CGAL @@ -73,7 +73,7 @@ void PolySet::insert_vertex(double x, double y, double z) polygons.last().insert(0, Point(x, y, z)); } -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 z) +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 z, bool mirrored) { double ax = p1->x - p0->x, bx = p1->x - p2->x; double ay = p1->y - p0->y, by = p1->y - p2->y; @@ -93,28 +93,45 @@ static void gl_draw_triangle(GLint *shaderinfo, const PolySet::Point *p0, const glVertexAttrib3d(shaderinfo[5], p2->x, p2->y, p2->z + z); glVertexAttrib3d(shaderinfo[6], 0.0, 1.0, 0.0); glVertex3d(p0->x, p0->y, p0->z + z); - glVertexAttrib3d(shaderinfo[3], e0f, e1f, e2f); - glVertexAttrib3d(shaderinfo[4], p0->x, p0->y, p0->z + z); - glVertexAttrib3d(shaderinfo[5], p2->x, p2->y, p2->z + z); - glVertexAttrib3d(shaderinfo[6], 0.0, 0.0, 1.0); - glVertex3d(p1->x, p1->y, p1->z + z); + if (!mirrored) { + glVertexAttrib3d(shaderinfo[3], e0f, e1f, e2f); + glVertexAttrib3d(shaderinfo[4], p0->x, p0->y, p0->z + z); + glVertexAttrib3d(shaderinfo[5], p2->x, p2->y, p2->z + z); + glVertexAttrib3d(shaderinfo[6], 0.0, 0.0, 1.0); + glVertex3d(p1->x, p1->y, p1->z + z); + } glVertexAttrib3d(shaderinfo[3], e0f, e1f, e2f); glVertexAttrib3d(shaderinfo[4], p0->x, p0->y, p0->z + z); glVertexAttrib3d(shaderinfo[5], p1->x, p1->y, p1->z + z); glVertexAttrib3d(shaderinfo[6], 1.0, 0.0, 0.0); glVertex3d(p2->x, p2->y, p2->z + z); + if (mirrored) { + glVertexAttrib3d(shaderinfo[3], e0f, e1f, e2f); + glVertexAttrib3d(shaderinfo[4], p0->x, p0->y, p0->z + z); + glVertexAttrib3d(shaderinfo[5], p2->x, p2->y, p2->z + z); + glVertexAttrib3d(shaderinfo[6], 0.0, 0.0, 1.0); + glVertex3d(p1->x, p1->y, p1->z + z); + } } else #endif { glVertex3d(p0->x, p0->y, p0->z + z); - glVertex3d(p1->x, p1->y, p1->z + z); + if (!mirrored) + glVertex3d(p1->x, p1->y, p1->z + z); glVertex3d(p2->x, p2->y, p2->z + z); + if (mirrored) + glVertex3d(p1->x, p1->y, p1->z + z); } } -void PolySet::render_surface(colormode_e colormode, csgmode_e csgmode, GLint *shaderinfo) const +void PolySet::render_surface(colormode_e colormode, csgmode_e csgmode, double *m, GLint *shaderinfo) const { + double m_scale_rotate_det = + m[0]*m[5]*m[10] + m[4]*m[9]*m[2] + m[8]*m[1]*m[6] - + (m[8]*m[5]*m[2] + m[4]*m[1]*m[10] + m[0]*m[9]*m[6]); + bool mirrored = m_scale_rotate_det < 0; + if (colormode == COLORMODE_MATERIAL) { glColor3ub(249, 215, 44); #ifdef ENABLE_OPENCSG @@ -166,18 +183,18 @@ void PolySet::render_surface(colormode_e colormode, csgmode_e csgmode, GLint *sh const Polygon *poly = &polygons[i]; if (poly->size() == 3) { if (z < 0) { - gl_draw_triangle(shaderinfo, &poly->at(0), &poly->at(2), &poly->at(1), true, true, true, z); + gl_draw_triangle(shaderinfo, &poly->at(0), &poly->at(2), &poly->at(1), true, true, true, z, mirrored); } else { - gl_draw_triangle(shaderinfo, &poly->at(0), &poly->at(1), &poly->at(2), true, true, true, z); + gl_draw_triangle(shaderinfo, &poly->at(0), &poly->at(1), &poly->at(2), true, true, true, z, mirrored); } } else if (poly->size() == 4) { if (z < 0) { - gl_draw_triangle(shaderinfo, &poly->at(0), &poly->at(3), &poly->at(1), true, false, true, z); - gl_draw_triangle(shaderinfo, &poly->at(2), &poly->at(1), &poly->at(3), true, false, true, z); + gl_draw_triangle(shaderinfo, &poly->at(0), &poly->at(3), &poly->at(1), true, false, true, z, mirrored); + gl_draw_triangle(shaderinfo, &poly->at(2), &poly->at(1), &poly->at(3), true, false, true, z, mirrored); } else { - gl_draw_triangle(shaderinfo, &poly->at(0), &poly->at(1), &poly->at(3), true, false, true, z); - gl_draw_triangle(shaderinfo, &poly->at(2), &poly->at(3), &poly->at(1), true, false, true, z); + gl_draw_triangle(shaderinfo, &poly->at(0), &poly->at(1), &poly->at(3), true, false, true, z, mirrored); + gl_draw_triangle(shaderinfo, &poly->at(2), &poly->at(3), &poly->at(1), true, false, true, z, mirrored); } } else { @@ -191,10 +208,10 @@ void PolySet::render_surface(colormode_e colormode, csgmode_e csgmode, GLint *sh for (int j = 1; j <= poly->size(); j++) { if (z < 0) { gl_draw_triangle(shaderinfo, ¢er, &poly->at(j % poly->size()), &poly->at(j - 1), - false, true, false, z); + false, true, false, z, mirrored); } else { gl_draw_triangle(shaderinfo, ¢er, &poly->at(j - 1), &poly->at(j % poly->size()), - false, true, false, z); + false, true, false, z, mirrored); } } } @@ -210,8 +227,8 @@ void PolySet::render_surface(colormode_e colormode, csgmode_e csgmode, GLint *sh Point p3 = poly->at(j % poly->size()), p4 = poly->at(j % poly->size()); p1.z -= zbase/2, p2.z += zbase/2; p3.z -= zbase/2, p4.z += zbase/2; - gl_draw_triangle(shaderinfo, &p2, &p1, &p3, true, true, false, 0); - gl_draw_triangle(shaderinfo, &p2, &p3, &p4, false, true, true, 0); + gl_draw_triangle(shaderinfo, &p2, &p1, &p3, true, true, false, 0, mirrored); + gl_draw_triangle(shaderinfo, &p2, &p3, &p4, false, true, true, 0, mirrored); } } glEnd(); @@ -220,11 +237,11 @@ void PolySet::render_surface(colormode_e colormode, csgmode_e csgmode, GLint *sh const Polygon *poly = &polygons[i]; glBegin(GL_TRIANGLES); if (poly->size() == 3) { - gl_draw_triangle(shaderinfo, &poly->at(0), &poly->at(1), &poly->at(2), true, true, true, 0); + gl_draw_triangle(shaderinfo, &poly->at(0), &poly->at(1), &poly->at(2), true, true, true, 0, mirrored); } else if (poly->size() == 4) { - gl_draw_triangle(shaderinfo, &poly->at(0), &poly->at(1), &poly->at(3), true, false, true, 0); - gl_draw_triangle(shaderinfo, &poly->at(2), &poly->at(3), &poly->at(1), true, false, true, 0); + gl_draw_triangle(shaderinfo, &poly->at(0), &poly->at(1), &poly->at(3), true, false, true, 0, mirrored); + gl_draw_triangle(shaderinfo, &poly->at(2), &poly->at(3), &poly->at(1), true, false, true, 0, mirrored); } else { Point center; @@ -237,7 +254,7 @@ void PolySet::render_surface(colormode_e colormode, csgmode_e csgmode, GLint *sh center.y /= poly->size(); center.z /= poly->size(); for (int j = 1; j <= poly->size(); j++) { - gl_draw_triangle(shaderinfo, ¢er, &poly->at(j - 1), &poly->at(j % poly->size()), false, true, false, 0); + gl_draw_triangle(shaderinfo, ¢er, &poly->at(j - 1), &poly->at(j % poly->size()), false, true, false, 0, mirrored); } } glEnd(); diff --git a/transform.cc b/transform.cc index a920dd5..3c09c14 100644 --- a/transform.cc +++ b/transform.cc @@ -26,6 +26,7 @@ enum transform_type_e { SCALE, ROTATE, + MIRROR, TRANSLATE, MULTMATRIX, COLOR @@ -69,6 +70,9 @@ AbstractNode *TransformModule::evaluate(const Context *ctx, const ModuleInstanti if (type == ROTATE) { argnames = QVector<QString>() << "a" << "v"; } + if (type == MIRROR) { + argnames = QVector<QString>() << "v"; + } if (type == TRANSLATE) { argnames = QVector<QString>() << "v"; } @@ -141,25 +145,53 @@ AbstractNode *TransformModule::evaluate(const Context *ctx, const ModuleInstanti if (x != 0.0 || y != 0.0 || z != 0.0) { double sn = 1.0 / sqrt(x*x + y*y + z*z); x *= sn, y *= sn, z *= sn; - } else { - x = 0, y = 0, z = 1; } } - double c = cos(a*M_PI/180.0); - double s = sin(a*M_PI/180.0); + if (x != 0.0 || y != 0.0 || z != 0.0) + { + 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 == MIRROR) + { + Value val_v = c.lookup_variable("v"); + double x = 1, y = 0, z = 0; + + if (val_v.getv3(x, y, z)) { + if (x != 0.0 || y != 0.0 || z != 0.0) { + double sn = 1.0 / sqrt(x*x + y*y + z*z); + x *= sn, y *= sn, z *= sn; + } + } - 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; + if (x != 0.0 || y != 0.0 || z != 0.0) + { + node->m[ 0] = 1-2*x*x; + node->m[ 1] = -2*y*x; + node->m[ 2] = -2*z*x; - 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[ 4] = -2*x*y; + node->m[ 5] = 1-2*y*y; + node->m[ 6] = -2*z*y; - 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; + node->m[ 8] = -2*x*z; + node->m[ 9] = -2*y*z; + node->m[10] = 1-2*z*z; } } if (type == TRANSLATE) @@ -329,6 +361,7 @@ void register_builtin_transform() { builtin_modules["scale"] = new TransformModule(SCALE); builtin_modules["rotate"] = new TransformModule(ROTATE); + builtin_modules["mirror"] = new TransformModule(MIRROR); builtin_modules["translate"] = new TransformModule(TRANSLATE); builtin_modules["multmatrix"] = new TransformModule(MULTMATRIX); builtin_modules["color"] = new TransformModule(COLOR); |