From bc33d997038d02792c3a3d92220e04d50e0c2d27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D1=8B=D1=87=D0=BA=D0=BE=D0=B2=20=D0=90=D0=BD=D0=B4?= =?UTF-8?q?=D1=80=D0=B5=D0=B9?= Date: Thu, 12 Dec 2019 16:13:16 +0000 Subject: [PATCH] qglengine: direct primitive editor git-svn-id: svn://db.shs.com.ru/libs@687 a8b55f48-bf90-11e4-a774-851b48703e85 --- qglengine/core/glprimitives.cpp | 81 +++++++++++------- qglengine/core/glprimitives.h | 6 +- qglengine/renderer_service.cpp | 5 +- qglengine/widgets/primitiveeditor.cpp | 116 +++++++++++++++++++++++--- qglengine/widgets/primitiveeditor.h | 3 +- qglengine/widgets/primitiveeditor.ui | 44 +++------- 6 files changed, 174 insertions(+), 81 deletions(-) diff --git a/qglengine/core/glprimitives.cpp b/qglengine/core/glprimitives.cpp index d0652cd..d05eb5f 100644 --- a/qglengine/core/glprimitives.cpp +++ b/qglengine/core/glprimitives.cpp @@ -87,7 +87,7 @@ Mesh * Primitive::cube(float width, float length, float height) { } -Mesh * Primitive::ellipsoid(int segments_wl, int segments_h, float width, float length, float height) { +Mesh * Primitive::ellipsoid(int segments_wl, int segments_h, float width, float length, float height, float end_angle) { Mesh * ret = new Mesh(); QVector & v(ret->vertices ()); QVector & n(ret->normals ()); @@ -96,6 +96,7 @@ Mesh * Primitive::ellipsoid(int segments_wl, int segments_h, float width, float double hh = height / 2.f; int hseg = segments_h + 1, wlseg = segments_wl + 1; double crw, crl, a, ch, twl; + double eang = deg2rad * end_angle; QVector3D cp; for (int i = 0; i <= hseg; i++) { @@ -106,10 +107,12 @@ Mesh * Primitive::ellipsoid(int segments_wl, int segments_h, float width, float crl = twl * length; int cvcnt = wlseg * 2; for (int j = 0; j < cvcnt; j++) { - a = (double)j / (cvcnt - 1) * M_2PI; + a = (double)j / (cvcnt - 1) * eang; cp.setX(crl * cos(a)); cp.setY(crw * sin(a)); - v << cp; t << QVector2D((double)j / (cvcnt - 1), ch/2.f + 0.5f); + v << cp; + t << QVector2D((double)j / (cvcnt - 1), ch/2.f + 0.5f); + n << (cp / QVector3D(length * length, width * width, height * height)).normalized(); int si = v.size() - 1; if (j > 0 && i > 0) { ind << Vector3i(si - cvcnt - 1, si, si - 1); @@ -117,16 +120,22 @@ Mesh * Primitive::ellipsoid(int segments_wl, int segments_h, float width, float } } } - - n.resize(v.size()); - for (int i = 0; i < v.size(); i++) - n[i] = v[i].normalized(); - + if (end_angle < 360.) { + Mesh * cap = Primitive::disc(segments_h+1, length, height, 180); + cap->rotatePoints(90, 0, 1, 0); + cap->rotatePoints(-90, 0, 0, 1); + ret->append(cap); + cap->flipNormals(); + cap->rotatePoints(end_angle, 0, 0, 1); + cap->scalePoints(QVector3D((cos(eang)*cos(eang)*width+sin(eang)*sin(eang)*length)/width, (cos(eang)*cos(eang)*length+sin(eang)*sin(eang)*width)/length, 1)); + ret->append(cap); + delete cap; + } return ret; } -Mesh * Primitive::disc(int segments, float width, float length, bool up, float end_angle) { +Mesh * Primitive::disc(int segments, float width, float length, float end_angle) { Mesh * ret = new Mesh(); QVector & v(ret->vertices ()); QVector & n(ret->normals ()); @@ -136,6 +145,7 @@ Mesh * Primitive::disc(int segments, float width, float length, bool up, float e segments = qMax(segments + 1, 4); QVector3D cp; v << QVector3D(); + n << QVector3D(0, 0, 1); t << QVector2D(0.5f, 0.5f); end_angle *= deg2rad; for (int i = 0; i < segments; i++) { @@ -143,20 +153,11 @@ Mesh * Primitive::disc(int segments, float width, float length, bool up, float e cp.setX(length / 2. * cos(a)); cp.setY(width / 2. * sin(a)); v << cp; + n << QVector3D(0, 0, 1); t << QVector2D(cp.x() / width + 0.5f, cp.y() / length + 0.5f); int si = v.size() - 1; - if (i > 0) { - if (up) - ind << Vector3i(si - 1, si, 0); - else - ind << Vector3i(si, si - 1, 0); - } + if (i > 0) ind << Vector3i(si - 1, si, 0); } - - n.resize(v.size()); - for (int i = 0; i < v.size(); i++) - n[i] = QVector3D(0, 0, up ? 1 : -1); - return ret; } @@ -172,6 +173,8 @@ QVector3D coneNormal(double rx, double ry, double height, double ang) { norm.setZ(norm.length() * tan(ca)); return norm.normalized(); } + + Mesh * Primitive::cone(int segments, float width, float length, float height) { Mesh * ret = new Mesh(); QVector & v(ret->vertices ()); @@ -200,7 +203,8 @@ Mesh * Primitive::cone(int segments, float width, float length, float height) { ind << Vector3i(si - 1, si - 2, si); } - Mesh * cap = Primitive::disc(segments, width, length, false); + Mesh * cap = Primitive::disc(segments, width, length); + cap->flipNormals(); ret->append(cap); delete cap; @@ -208,7 +212,7 @@ Mesh * Primitive::cone(int segments, float width, float length, float height) { } -Mesh * Primitive::cylinder(int segments, float width, float length, float height) { +Mesh * Primitive::cylinder(int segments, float width, float length, float height, float end_angle) { Mesh * ret = new Mesh(); QVector & v(ret->vertices ()); QVector & n(ret->normals ()); @@ -218,12 +222,14 @@ Mesh * Primitive::cylinder(int segments, float width, float length, float height int seg = qMax(segments + 1, 4); double rx = width / 2., ry = length / 2.; QVector3D cp, norm; + double eang = deg2rad * end_angle; + for (int i = 0; i < seg; i++) { - double a = (double)i / (seg - 1) * M_2PI; + double a = (double)i / (seg - 1) * eang; cp.setX(ry * cos(a)); cp.setY(rx * sin(a)); cp.setZ(0.); - norm = cp.normalized(); + norm = (cp / QVector3D(length * length, width * width, 1)).normalized(); v << cp; cp.setZ(height); v << cp; @@ -237,14 +243,27 @@ Mesh * Primitive::cylinder(int segments, float width, float length, float height } } - Mesh * cap = Primitive::disc(segments, width, length, false); + Mesh * cap = Primitive::disc(segments, width, length, end_angle); + cap->flipNormals(); ret->append(cap); - delete cap; - cap = Primitive::disc(segments, width, length, true); cap->translatePoints(QVector3D(0., 0., height)); + cap->flipNormals(); ret->append(cap); delete cap; + if (end_angle < 360.) { + Mesh * cap = Primitive::plane(length/2, height); + cap->rotatePoints(90, 1, 0, 0); + //cap->rotatePoints(-90, 0, 0, 1); + cap->translatePoints(length/4, 0, height/2); + ret->append(cap); + cap->flipNormals(); + cap->rotatePoints(end_angle, 0, 0, 1); + cap->scalePoints(QVector3D((cos(eang)*cos(eang)*width+sin(eang)*sin(eang)*length)/width, (cos(eang)*cos(eang)*length+sin(eang)*sin(eang)*width)/length, 1)); + ret->append(cap); + delete cap; + } + return ret; } @@ -304,16 +323,14 @@ Mesh * Primitive::torus(int segments_main, int segments_second, float radius_mai pcnt = v.size(); } if (end_angle < 360.) { - Mesh * cap = Primitive::disc(segments_second-1, radius_second * 2, radius_second * 2, true); + Mesh * cap = Primitive::disc(segments_second-1, radius_second * 2, radius_second * 2); cap->rotatePoints(90, 1, 0, 0); cap->translatePoints(radius_main, 0, 0); ret->append(cap); - delete cap; - cap = Primitive::disc(segments_second-1, radius_second * 2, radius_second * 2, false); - cap->rotatePoints(90, 1, 0, 0); - cap->translatePoints(radius_main, 0, 0); + cap->flipNormals(); cap->rotatePoints(end_angle, 0, 0, 1); ret->append(cap); + delete cap; } return ret; } diff --git a/qglengine/core/glprimitives.h b/qglengine/core/glprimitives.h index 11e1297..fb6597b 100644 --- a/qglengine/core/glprimitives.h +++ b/qglengine/core/glprimitives.h @@ -29,13 +29,13 @@ Mesh * plane(float width = 1., float length = 1.); Mesh * cube(float width = 1., float length = 1., float height = 1.); -Mesh * ellipsoid(int segments_wl, int segments_h, float width = 1., float length = 1., float height = 1.); +Mesh * ellipsoid(int segments_wl, int segments_h, float width = 1., float length = 1., float height = 1., float end_angle = 360.); -Mesh * disc(int segments, float width = 1., float length = 1., bool up = true, float end_angle = 360.); +Mesh * disc(int segments, float width = 1., float length = 1., float end_angle = 360.); Mesh * cone(int segments, float width = 1., float length = 1., float height = 1.); -Mesh * cylinder(int segments, float width = 1., float length = 1., float height = 1.); +Mesh * cylinder(int segments, float width = 1., float length = 1., float height = 1., float end_angle = 360.); Mesh * arrow(int segments = 16, float thick = 0.04, float angle = 30.); // length = 1 diff --git a/qglengine/renderer_service.cpp b/qglengine/renderer_service.cpp index 792aecf..f6756ab 100644 --- a/qglengine/renderer_service.cpp +++ b/qglengine/renderer_service.cpp @@ -79,10 +79,11 @@ RendererService::RendererService(Renderer * r_): r(r_) { handle_move_mesh = Primitive::arrow(12, 0.06); handle_ms_2_mesh = Primitive::torus(8, 12, 0.5, 0.02, 90); - Mesh * m = Primitive::disc(8, 1., 1., true, 90); + Mesh * m = Primitive::disc(8, 1., 1., 90); handle_ms_2_mesh->append(m); delete m; - m = Primitive::disc(8, 1., 1., false, 90); + m = Primitive::disc(8, 1., 1., 90); + m->flipNormals(); handle_ms_2_mesh->append(m); delete m; diff --git a/qglengine/widgets/primitiveeditor.cpp b/qglengine/widgets/primitiveeditor.cpp index 708627b..2cbc629 100644 --- a/qglengine/widgets/primitiveeditor.cpp +++ b/qglengine/widgets/primitiveeditor.cpp @@ -7,6 +7,7 @@ PrimitiveEditor::PrimitiveEditor(QWidget *parent) : QWidget(parent), ui(new Ui::PrimitiveEditor) { view = 0; + can_replace = false; ui->setupUi(this); editors[Plane] << ui->widgetWidth; editors[Plane] << ui->widgetLength; @@ -18,6 +19,7 @@ PrimitiveEditor::PrimitiveEditor(QWidget *parent) : QWidget(parent), ui(new Ui:: editors[Ellipsoid] << ui->widgetHeight; editors[Ellipsoid] << ui->widgetSegments; editors[Ellipsoid] << ui->widgetSegments2; + editors[Ellipsoid] << ui->widgetAngle; editors[Disc] << ui->widgetWidth; editors[Disc] << ui->widgetLength; editors[Disc] << ui->widgetSegments; @@ -30,6 +32,7 @@ PrimitiveEditor::PrimitiveEditor(QWidget *parent) : QWidget(parent), ui(new Ui:: editors[Cylinder] << ui->widgetLength; editors[Cylinder] << ui->widgetHeight; editors[Cylinder] << ui->widgetSegments; + editors[Cylinder] << ui->widgetAngle; editors[Torus] << ui->widgetRadius1; editors[Torus] << ui->widgetRadius2; editors[Torus] << ui->widgetSegments; @@ -63,44 +66,70 @@ void PrimitiveEditor::assignQGLView(QGLView * v) { } -Mesh * PrimitiveEditor::createMesh() { +Mesh * PrimitiveEditor::createMesh(QVariantList & params) { Mesh * m = 0; PrimitiveType pt = (PrimitiveType)ui->comboPrimitives->currentIndex(); + params << pt; switch (pt) { case Plane: m = Primitive::plane(ui->spinWidth->value(), ui->spinLength->value()); + params << ui->spinWidth->value() + << ui->spinLength->value(); break; case Cube: m = Primitive::cube(ui->spinWidth->value(), ui->spinLength->value(), ui->spinHeight->value()); + params << ui->spinWidth->value() + << ui->spinLength->value() + << ui->spinHeight->value(); break; case Ellipsoid: m = Primitive::ellipsoid(ui->spinSegments->value(), ui->spinSegments2->value(), ui->spinWidth->value(), ui->spinLength->value(), - ui->spinHeight->value()); + ui->spinHeight->value(), + ui->spinAngle->value()); + params << ui->spinSegments->value() + << ui->spinSegments2->value() + << ui->spinWidth->value() + << ui->spinLength->value() + << ui->spinHeight->value() + << ui->spinAngle->value(); break; case Disc: m = Primitive::disc(ui->spinSegments->value(), ui->spinWidth->value(), ui->spinLength->value(), - true, ui->spinAngle->value()); + params << ui->spinSegments->value() + << ui->spinWidth->value() + << ui->spinLength->value() + << ui->spinAngle->value(); break; case Cone: m = Primitive::cone(ui->spinSegments->value(), ui->spinWidth->value(), ui->spinLength->value(), ui->spinHeight->value()); + params << ui->spinSegments->value() + << ui->spinWidth->value() + << ui->spinLength->value() + << ui->spinHeight->value(); break; case Cylinder: m = Primitive::cylinder(ui->spinSegments->value(), ui->spinWidth->value(), ui->spinLength->value(), - ui->spinHeight->value()); + ui->spinHeight->value(), + ui->spinAngle->value()); + params << ui->spinSegments->value() + << ui->spinWidth->value() + << ui->spinLength->value() + << ui->spinHeight->value() + << ui->spinAngle->value(); break; case Torus: m = Primitive::torus(ui->spinSegments->value(), @@ -108,9 +137,16 @@ Mesh * PrimitiveEditor::createMesh() { ui->spinRadius->value(), ui->spinRadius2->value(), ui->spinAngle->value()); + params << ui->spinSegments->value() + << ui->spinSegments2->value() + << ui->spinRadius->value() + << ui->spinRadius2->value() + << ui->spinAngle->value(); break; default: return 0; } + params << ui->flipNormals->isChecked(); + params << ui->colorButton->color(); if (ui->flipNormals->isChecked()) m->flipNormals(); return m; @@ -126,32 +162,90 @@ void PrimitiveEditor::showEditors() { void PrimitiveEditor::selectionChanged() { - ObjectBase * so = view->selectedObject(); - bool has_1 = so; - ui->buttonReplace->setEnabled(has_1); + ObjectBase * so = view->selectedObject();\ + can_replace = false; + if (so) { + QVariantList vl = so->property("primitive", &can_replace).toList(); + if (can_replace && !vl.isEmpty()) { + PrimitiveType pt = (PrimitiveType)vl.takeFirst().toInt(); + ui->comboPrimitives->setCurrentIndex(pt); + switch (pt) { + case Plane: + ui->spinWidth->setValue(vl.takeFirst().toDouble()); + ui->spinLength->setValue(vl.takeFirst().toDouble()); + break; + case Cube: + ui->spinWidth->setValue(vl.takeFirst().toDouble()); + ui->spinLength->setValue(vl.takeFirst().toDouble()); + ui->spinHeight->setValue(vl.takeFirst().toDouble()); + break; + case Ellipsoid: + ui->spinSegments->setValue(vl.takeFirst().toDouble()); + ui->spinSegments2->setValue(vl.takeFirst().toDouble()); + ui->spinWidth->setValue(vl.takeFirst().toDouble()); + ui->spinLength->setValue(vl.takeFirst().toDouble()); + ui->spinHeight->setValue(vl.takeFirst().toDouble()); + ui->spinAngle->setValue(vl.takeFirst().toDouble()); + break; + case Disc: + ui->spinSegments->setValue(vl.takeFirst().toDouble()); + ui->spinWidth->setValue(vl.takeFirst().toDouble()); + ui->spinLength->setValue(vl.takeFirst().toDouble()); + ui->spinAngle->setValue(vl.takeFirst().toDouble()); + break; + case Cone: + ui->spinSegments->setValue(vl.takeFirst().toDouble()); + ui->spinWidth->setValue(vl.takeFirst().toDouble()); + ui->spinLength->setValue(vl.takeFirst().toDouble()); + ui->spinHeight->setValue(vl.takeFirst().toDouble()); + break; + case Cylinder: + ui->spinSegments->setValue(vl.takeFirst().toDouble()); + ui->spinWidth->setValue(vl.takeFirst().toDouble()); + ui->spinLength->setValue(vl.takeFirst().toDouble()); + ui->spinHeight->setValue(vl.takeFirst().toDouble()); + ui->spinAngle->setValue(vl.takeFirst().toDouble()); + break; + case Torus: + ui->spinSegments->setValue(vl.takeFirst().toDouble()); + ui->spinSegments2->setValue(vl.takeFirst().toDouble()); + ui->spinRadius->setValue(vl.takeFirst().toDouble()); + ui->spinRadius2->setValue(vl.takeFirst().toDouble()); + ui->spinAngle->setValue(vl.takeFirst().toDouble()); + break; + } + ui->flipNormals->setChecked(vl.takeFirst().toBool()); + ui->colorButton->setColor(vl.takeFirst().value()); + } + } } void PrimitiveEditor::replaceMesh() { if (!view) return; - if (!ui->buttonReplace->isEnabled() || !ui->buttonReplace->isChecked()) return; + if (!can_replace) return; ObjectBase * so = view->selectedObject(); if (!so) return; - Mesh * m = createMesh(); + QVariantList params; + Mesh * m = createMesh(params); if (!m) return; so->setMesh(m); + so->setColor(ui->colorButton->color()); + so->setName(ui->comboPrimitives->currentText()); + so->setProperty("primitive", params); delete m; - } void PrimitiveEditor::on_buttonAdd_clicked() { if (!view) return; - Mesh * m = createMesh(); + QVariantList params; + Mesh * m = createMesh(params); if (!m) return; ObjectBase * o = new ObjectBase(m); o->setColor(ui->colorButton->color()); o->setName(ui->comboPrimitives->currentText()); + o->setProperty("primitive", params); view->scene()->addObject(o); view->scene()->selectObject(o); delete m; diff --git a/qglengine/widgets/primitiveeditor.h b/qglengine/widgets/primitiveeditor.h index ef34b7c..d0e71cb 100644 --- a/qglengine/widgets/primitiveeditor.h +++ b/qglengine/widgets/primitiveeditor.h @@ -30,13 +30,14 @@ public: void assignQGLView(QGLView * v); protected: - Mesh * createMesh(); + Mesh * createMesh(QVariantList & params); void showEditors(); Ui::PrimitiveEditor *ui; QGLView * view; QMap > editors; QList all_editors; + bool can_replace; private slots: void selectionChanged(); diff --git a/qglengine/widgets/primitiveeditor.ui b/qglengine/widgets/primitiveeditor.ui index 5501ffa..7add853 100644 --- a/qglengine/widgets/primitiveeditor.ui +++ b/qglengine/widgets/primitiveeditor.ui @@ -384,31 +384,9 @@ Add - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - false - - - Replace - - - true + + + :/icons/list-add.png:/icons/list-add.png @@ -438,7 +416,9 @@
scroll_spin_box.h
- + + + spinWidth @@ -601,18 +581,18 @@ - buttonReplace - clicked() + colorButton + colorChanged(QColor) PrimitiveEditor replaceMesh() - 340 - 529 + 271 + 285 - 367 - 524 + 179 + 267