From 888f970f44c3455b561d5f6f978ec8c1ece32314 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D0=B5=D0=BB=D0=B8=D0=BF=D0=B5=D0=BD=D0=BA=D0=BE=20?= =?UTF-8?q?=D0=98=D0=B2=D0=B0=D0=BD?= Date: Wed, 4 Dec 2019 17:04:06 +0000 Subject: [PATCH] git-svn-id: svn://db.shs.com.ru/libs@651 a8b55f48-bf90-11e4-a774-851b48703e85 --- qglengine/core/gltypes.cpp | 2 +- qglengine/core/gltypes.h | 2 +- qglengine/glcamera.cpp | 189 +------------------- qglengine/glcamera.h | 31 +--- qglengine/globject.cpp | 71 +++++--- qglengine/globject.h | 13 ++ qglengine/glrendererbase.cpp | 1 - qglengine/glwidget.cpp | 10 -- qglengine/glwidget.h | 3 - qglengine/icons/dialog-cancel.png | Bin 0 -> 45200 bytes qglengine/mouse_controller.cpp | 6 +- qglengine/qglview.h | 3 - qglengine/qglview_test/qglview_window.cpp | 1 - qglengine/qglview_test/qglview_window.h | 1 - qglengine/widgets/materials_editor.cpp | 9 + qglengine/widgets/materials_editor.h | 1 + qglengine/widgets/materials_editor.ui | 199 +++++++++++++++------- qglengine/widgets/object_editor.cpp | 8 + qglengine/widgets/object_editor.h | 2 +- qglengine/widgets/widgets.qrc | 1 + 20 files changed, 224 insertions(+), 329 deletions(-) create mode 100644 qglengine/icons/dialog-cancel.png diff --git a/qglengine/core/gltypes.cpp b/qglengine/core/gltypes.cpp index 2d03b41..bd588d7 100644 --- a/qglengine/core/gltypes.cpp +++ b/qglengine/core/gltypes.cpp @@ -187,7 +187,7 @@ void createGLTexture(QOpenGLExtraFunctions * f, GLuint & tex, const QImage & ima } -QMatrix4x4 glMatrixPerspective(float angle, float aspect, float near_, float far_) { +QMatrix4x4 glMatrixPerspective(float angle, float aspect, float near_) { QMatrix4x4 ret; float t = 1.f / (tanf(angle * deg2rad / 2.f)), e = 2.4e-7f; if (aspect >= 1.) { diff --git a/qglengine/core/gltypes.h b/qglengine/core/gltypes.h index 14c8f9a..2877e2d 100644 --- a/qglengine/core/gltypes.h +++ b/qglengine/core/gltypes.h @@ -157,7 +157,7 @@ void glClearFramebuffer(const QColor & color = Qt::black, bool depth = true); void glDrawQuad(QOpenGLShaderProgram * prog = nullptr, QVector4D * corner_dirs = nullptr, GLfloat x = -1.f, GLfloat y = -1.f, GLfloat w = 2.f, GLfloat h = 2.f); void createGLTexture(QOpenGLExtraFunctions * f, GLuint & tex, int width, int height, const GLenum & format = GL_RGBA, const GLenum & target = GL_TEXTURE_2D); void createGLTexture(QOpenGLExtraFunctions * f, GLuint & tex, const QImage & image, const GLenum & format = GL_RGBA, const GLenum & target = GL_TEXTURE_2D); -QMatrix4x4 glMatrixPerspective(float angle, float aspect, float near_, float far_); +QMatrix4x4 glMatrixPerspective(float angle, float aspect, float near_); QImage rotateQImageLeft(const QImage & im); QImage rotateQImageRight(const QImage & im); inline QImage rotateQImage180(const QImage & im) {return im.mirrored(true, true);} diff --git a/qglengine/glcamera.cpp b/qglengine/glcamera.cpp index 2112527..e316885 100644 --- a/qglengine/glcamera.cpp +++ b/qglengine/glcamera.cpp @@ -23,23 +23,12 @@ Camera::Camera() { type_ = glCamera; fov_ = 60.; - angle_limit_lower_xy = 0.f; - angle_limit_upper_xy = 360.f; //setRotationX(90.f); depth_start = 0.1f; - depth_end = 1000.f; mirror_x = mirror_y = false; } -void Camera::anglesFromPoints() { - //QVector3D dv = aim_ - pos_, tv; - //tv = QVector3D(dv.x(), dv.y(), 0.); - //angles_.setZ(atan2f(tv.x(), tv.y()) * rad2deg); - //angles_.setY(piClamp(atan2f(tv.length(), dv.z()) * rad2deg, angle_limit_lower_xy, angle_limit_upper_xy) + 180.f); -} - - QMatrix4x4 Camera::offsetMatrix() const { QMatrix4x4 ret; ret.translate(parent_ ? -offset_ : -aim()); @@ -65,12 +54,9 @@ void Camera::assign(const Camera & c) { trans = c.trans; aim_dist = c.aim_dist; fov_ = c.fov_; - angle_limit_lower_xy = c.angle_limit_lower_xy; - angle_limit_upper_xy = c.angle_limit_upper_xy; mirror_x = c.mirror_x; mirror_y = c.mirror_y; depth_start = c.depth_start; - depth_end = c.depth_end; buildTransform(); } @@ -89,12 +75,9 @@ ObjectBase * Camera::clone(bool withChildren) { o->trans = trans; o->aim_dist = aim_dist; o->fov_ = fov_; - o->angle_limit_lower_xy = angle_limit_lower_xy; - o->angle_limit_upper_xy = angle_limit_upper_xy; o->mirror_x = mirror_x; o->mirror_y = mirror_y; o->depth_start = depth_start; - o->depth_end = depth_end; o->meta = meta; return o; } @@ -121,175 +104,5 @@ QMatrix4x4 Camera::viewMatrix() const { QMatrix4x4 Camera::projectionMatrix(double aspect) const { - return glMatrixPerspective(fov_, aspect, depth_start, depth_end); + return glMatrixPerspective(fov_, aspect, depth_start); } - - -void Camera::panZ(const float & a) { - /*QVector3D dv = aim_ - pos_; - float tl = QVector2D(dv.x(), dv.y()).length(); - angles_.setZ(angles_.z() + a); - dv = QVector3D(sinf(angles_.z() * deg2rad) * tl, cosf(angles_.z() * deg2rad) * tl, dv.z()); - aim_ = pos_ + dv; - buildTransform();*/ -} - - -void Camera::panXY(const float & a) { - /*QVector3D dv = aim_ - pos_; - float tl = dv.length(), tc; - angles_.setY(angles_.y() + a); - angles_.setY(piClamp(angles_.y(), angle_limit_lower_xy, angle_limit_upper_xy)); - tc = -sinf(angles_.y() * deg2rad); - dv = QVector3D(sinf(angles_.z() * deg2rad) * tc, cosf(angles_.z() * deg2rad) * tc, -cosf(angles_.y() * deg2rad)); - aim_ = pos_ + dv * tl; - buildTransform();*/ -} - - -void Camera::rotateZ(const float & a) { - /*QVector3D dv = aim_ - pos_; - float tl = QVector2D(dv.x(), dv.y()).length(); - angles_.setZ(angles_.z() + a); - dv = QVector3D(sinf(angles_.z() * deg2rad) * tl, cosf(angles_.z() * deg2rad) * tl, dv.z()); - aim_ = pos_ + dv; - buildTransform();*/ -} - - -void Camera::rotateXY(const float & a) { - /*QVector3D dv = aim_ - pos_; - float tl = dv.length(), tc; - angles_.setY(angles_.y() + a); - angles_.setY(piClamp(angles_.y(), angle_limit_lower_xy, angle_limit_upper_xy)); - tc = -sinf(angles_.y() * deg2rad); - dv = QVector3D(sinf(angles_.z() * deg2rad) * tc, cosf(angles_.z() * deg2rad) * tc, -cosf(angles_.y() * deg2rad)); - aim_ = pos_ + dv * tl; - buildTransform();*/ -} - - -void Camera::orbitZ(const float & a) { - //qDebug() << rotation() << Transform::fromDirection(direction()); - QVector3D pa = aim(); - //trans.rotationRef() *= QQuaternion::fromEulerAngles(0, a, 0); - ObjectBase::rotateZ(-a); - move(pa - aim()); - /*QVector3D dv = aim_ - pos_; - float tl = QVector2D(dv.x(), dv.y()).length(); - angles_.setZ(angles_.z() + a); - dv = QVector3D(sinf(angles_.z() * deg2rad) * tl, cosf(angles_.z() * deg2rad) * tl, dv.z()); - pos_ = aim_ - dv; - buildTransform();*/ -} - - -void Camera::orbitXY(const float & a) { - QVector3D pa = aim(); - //trans.rotationRef() *= QQuaternion::fromEulerAngles(a, 0, 0); - ObjectBase::rotateX(-a); - move(pa - aim()); - - //qDebug() << pos() << aim(); - /*QVector3D dv = aim_ - pos_; - float tl = dv.length(), tc; - angles_.setY(angles_.y() + a); - angles_.setY(piClamp(angles_.y(), angle_limit_lower_xy, angle_limit_upper_xy)); - tc = -sinf(angles_.y() * deg2rad); - dv = QVector3D(sinf(angles_.z() * deg2rad) * tc, cosf(angles_.z() * deg2rad) * tc, -cosf(angles_.y() * deg2rad)); - pos_ = aim_ - dv * tl; - buildTransform();*/ -} - - -void Camera::setAngleZ(const float & a) { - /*QVector3D dv = aim_ - pos_; - float tl = QVector2D(dv.x(), dv.y()).length(); - angles_.setZ(a); - dv = QVector3D(sinf(angles_.z() * deg2rad) * tl, cosf(angles_.z() * deg2rad) * tl, dv.z()); - aim_ = pos_ + dv; - buildTransform();*/ -} - - -void Camera::setAngleXY(const float & a) { - /*QVector3D dv = aim_ - pos_; - float tl = dv.length(), tc; - angles_.setY(a); - tc = -sinf(angles_.y() * deg2rad); - dv = QVector3D(sinf(angles_.z() * deg2rad) * tc, cosf(angles_.z() * deg2rad) * tc, -cosf(angles_.y() * deg2rad)); - //pos_ = aim_ - dv; - aim_ = pos_ + dv * tl; - buildTransform();*/ - //anglesFromPoints(); -} - - -void Camera::moveForward(const float & x, bool withZ) { - /*Vector3D dv;// = aim_ - pos_; - float tc = -sinf(angles_.y() * deg2rad); - dv = QVector3D(sinf(angles_.z() * deg2rad) * tc, cosf(angles_.z() * deg2rad) * tc, 0.); - if (withZ) dv.setZ(-cosf(angles_.y() * deg2rad)); - dv.normalize(); - dv *= x; - pos_ += dv; - aim_ += dv; - buildTransform();*/ -} - - -void Camera::moveLeft(const float & x, bool withZ) { - /*QVector3D dv;// = aim_ - pos_; - float tc = -sinf(angles_.y() * deg2rad); - dv = QVector3D(sinf(angles_.z() * deg2rad - float(M_PI_2)) * tc, cosf(angles_.z() * deg2rad - float(M_PI_2)) * tc, 0.f); - if (withZ) dv.setZ(-sinf(angles_.x() * deg2rad)); - dv.normalize(); - dv *= x; - pos_ += dv; - aim_ += dv; - buildTransform();*/ -} - - -void Camera::moveUp(const float & x, bool onlyZ) { - /*QVector3D dv; - if (onlyZ) - dv = QVector3D(0., 0., x); - else { - float tc = cosf(angles_.y() * deg2rad); - dv = QVector3D(sinf(angles_.z() * deg2rad) * tc, cosf(angles_.z() * deg2rad) * tc, -sinf(angles_.y() * deg2rad)); - dv.normalize(); - dv *= x; - } - pos_ += dv; - aim_ += dv; - buildTransform();*/ -} - -/* -void Camera::flyCloser(const float & s) { - QVector3D dv = aim_ - pos_; - float tl = dv.length() / (1.f + s), tc = -sinf(angles_.y() * deg2rad); - dv = QVector3D(sinf(angles_.z() * deg2rad) * tc, cosf(angles_.z() * deg2rad) * tc, -cosf(angles_.y() * deg2rad)); - pos_ = aim_ - dv * tl; - buildTransform(); -} - - -void Camera::flyFarer(const float & s) { - QVector3D dv = aim_ - pos_; - float tl = dv.length() * (1.f + s), tc = -sinf(angles_.y() * deg2rad); - dv = QVector3D(sinf(angles_.z() * deg2rad) * tc, cosf(angles_.z() * deg2rad) * tc, -cosf(angles_.y() * deg2rad)); - pos_ = aim_ - dv * tl; - buildTransform(); -} - - -void Camera::flyToDistance(const float & d) { - QVector3D dv = aim_ - pos_; - float tc = -sinf(angles_.y() * deg2rad); - dv = QVector3D(sinf(angles_.z() * deg2rad) * tc, cosf(angles_.z() * deg2rad) * tc, -cosf(angles_.y() * deg2rad)); - pos_ = aim_ - dv * d; - buildTransform(); -} -*/ diff --git a/qglengine/glcamera.h b/qglengine/glcamera.h index a6e9d98..120515d 100644 --- a/qglengine/glcamera.h +++ b/qglengine/glcamera.h @@ -33,29 +33,12 @@ class Camera: public AimedObject public: Camera(); - void moveForward(const float & x, bool withZ = true); - void moveBackward(const float & x, bool withZ = true) {moveForward(-x, withZ);} - void moveLeft(const float & x, bool withZ = true); - void moveRight(const float & x, bool withZ = true) {moveLeft(-x, withZ);} - void moveUp(const float & x, bool onlyZ = false); - void moveDown(const float & x, bool onlyZ = false) {moveUp(-x, onlyZ);} - void rotateZ(const float & a); - void rotateXY(const float & a); - void rotateRoll(const float & a) {rotateX(a);} - void orbitZ(const float & a); - void orbitXY(const float & a); - void panZ(const float & a); - void panXY(const float & a); void setFOV(const float & f) {fov_ = f;} void setAngles(const QVector3D & a) {setRotation(a);} - void setAngleZ(const float & a); - void setAngleXY(const float & a); - void setAngleRoll(const float & a) {setRotationX(a);} - void setAngleLowerLimitXY(const float & a) {angle_limit_lower_xy = a; buildTransform();} - void setAngleUpperLimitXY(const float & a) {angle_limit_upper_xy = a; buildTransform();} - void setAngleLimitsXY(const float & lower, const float & upper) {angle_limit_lower_xy = lower; angle_limit_upper_xy = upper; buildTransform();} + void setAngleZ(const float & a) {setRotationZ(a);} + void setAngleXY(const float & a) {setRotationX(a);} + void setAngleRoll(const float & a) {setRotationY(a);} void setDepthStart(const float & d) {depth_start = d;} - void setDepthEnd(const float & d) {depth_end = d;} void setMirrorX(bool yes) {mirror_x = yes;} void setMirrorY(bool yes) {mirror_y = yes;} @@ -63,16 +46,11 @@ public: float angleZ() const {return rotationZ();} float angleXY() const {return rotationY();} float angleRoll() const {return rotationZ();} - float angleLowerLimitXY() const {return angle_limit_lower_xy;} - float angleUpperLimitXY() const {return angle_limit_upper_xy;} float depthStart() const {return depth_start;} - float depthEnd() const {return depth_end;} bool isMirrorX() const {return mirror_x;} bool isMirrorY() const {return mirror_y;} - void anglesFromPoints(); void assign(const Camera & c); - virtual ObjectBase * clone(bool withChildren = true); QMatrix4x4 viewMatrix() const; QMatrix4x4 projectionMatrix(double aspect) const; @@ -84,9 +62,6 @@ private: mutable QVector3D offset_; GLfloat fov_; GLfloat depth_start; - GLfloat depth_end; - GLfloat angle_limit_lower_xy; - GLfloat angle_limit_upper_xy; bool mirror_x; bool mirror_y; diff --git a/qglengine/globject.cpp b/qglengine/globject.cpp index 0593938..c833535 100644 --- a/qglengine/globject.cpp +++ b/qglengine/globject.cpp @@ -495,6 +495,41 @@ void AimedObject::flyToDistance(double d) { } +void AimedObject::moveForward(const float & x, bool withZ) { + QVector3D dv = itransform_.mapVector(QVector3D(0, 0, -x)); + if (!withZ) dv[2] = 0.; + move(dv); +} + + +void AimedObject::moveLeft(const float & x, bool withZ) { + QVector3D dv = itransform_.mapVector(QVector3D(-x, 0, 0)); + if (!withZ) dv[2] = 0.; + move(dv); +} + + +void AimedObject::moveUp(const float & x, bool onlyZ) { + QVector3D dv = itransform_.mapVector(QVector3D(0, x, 0)); + if (onlyZ) dv[0] = dv[1] = 0.; + move(dv); +} + + +void AimedObject::orbitZ(const float & a) { + QVector3D pa = aim(); + rotateZ(-a); + move(pa - aim()); +} + + +void AimedObject::orbitXY(const float & a) { + QVector3D pa = aim(); + rotateX(-a); + move(pa - aim()); +} + + void AimedObject::transformChanged() { } @@ -561,23 +596,23 @@ QDataStream & operator <<(QDataStream & s, const ObjectBase * p) { ChunkStream cs; //qDebug() << "place" << p->name() << "..."; cs.add(1, int(p->type_)).add(2, p->accept_light).add(3, p->accept_fog).add(4, p->visible_) - .add(5, p->cast_shadow).add(6, p->rec_shadow).add(7, p->raw_matrix).add(8, p->line_width) - .add(9, int(p->render_mode)).add(14, p->mat_).add(16, p->children_.size()) - .add(17, p->name_).add(18, p->meta).add(19, p->color_).add(20, p->trans); + .add(5, p->cast_shadow).add(6, p->rec_shadow).add(7, p->raw_matrix).add(8, p->line_width) + .add(9, int(p->render_mode)).add(14, p->mat_).add(16, p->children_.size()) + .add(17, p->name_).add(18, p->meta).add(19, p->color_).add(20, p->trans); //qDebug() << "place self done"; if (p->type_ == ObjectBase::glLight) { //qDebug() << "place light ..."; const Light * l = (const Light*)p; - cs.add(100, l->aim()).add(101, l->angle_start).add(102, l->angle_end).add(103, l->intensity) - .add(104, l->decay_const).add(105, l->decay_linear).add(106, l->decay_quadratic) - .add(107, l->decay_start).add(108, l->decay_end).add(109, int(l->light_type)); + cs.add(101, l->angle_start).add(102, l->angle_end).add(103, l->intensity) + .add(104, l->decay_const).add(105, l->decay_linear).add(106, l->decay_quadratic) + .add(107, l->decay_start).add(108, l->decay_end).add(109, int(l->light_type)) + .add(111, l->distance()); } if (p->type_ == ObjectBase::glCamera) { //qDebug() << "place camera ..."; const Camera * c = (const Camera*)p; - cs.add(200, c->aim()).add(201, c->fov_).add(202, c->depth_start).add(203, c->depth_end) - .add(204, c->angle_limit_lower_xy).add(205, c->angle_limit_upper_xy) - .add(206, c->mirror_x).add(207, c->mirror_y); + cs.add(200, c->aim()).add(201, c->fov_).add(202, c->depth_start) + .add(206, c->mirror_x).add(207, c->mirror_y).add(208, c->distance()); } //qDebug() << "place" << p->name() << cs.data().size() << s.device()->size(); s << cs.data(); @@ -591,7 +626,6 @@ QDataStream & operator >>(QDataStream & s, ObjectBase *& p) { int ccnt = 0; Light * l = nullptr; Camera * c = nullptr; - QVector3D cam_angles; //qDebug() << "read obj ..."; while (!cs.atEnd()) { switch (cs.read()) { @@ -613,18 +647,7 @@ QDataStream & operator >>(QDataStream & s, ObjectBase *& p) { case 7: if (p) p->raw_matrix = cs.getData(); break; case 8: if (p) p->line_width = cs.getData(); break; case 9: if (p) p->render_mode = (ObjectBase::RenderMode)cs.getData(); break; - //case 10: if (p) p->material_ = cs.getData(); break; - //case 11: if (p) p->pos_ = cs.getData(); break; - //case 12: - // if (p) p->angles_ = cs.getData(); - // if (c) { - // c->setAngles(cs.getData()); - // cam_angles = c->angles(); - // } - //break; - //case 13: if (p) p->scale_ = cs.getData(); break; case 14: if (p) p->mat_ = cs.getData(); break; - //case 15: if (p) p->vbo = cs.getData(); break; case 16: if (p) ccnt = cs.getData(); break; case 17: if (p) p->name_ = cs.getData(); break; case 18: if (p) p->meta = cs.getData(); break; @@ -640,17 +663,15 @@ QDataStream & operator >>(QDataStream & s, ObjectBase *& p) { case 107: if (l) l->decay_start = cs.getData(); break; case 108: if (l) l->decay_end = cs.getData(); break; case 109: if (l) l->light_type = (Light::Type)cs.getData(); break; + case 111: if (l) l->setDistance(cs.getData()); break; case 200: if (c) c->setAim(cs.getData()); break; case 201: if (c) c->setFOV(cs.getData()); break; case 202: if (c) c->setDepthStart(cs.getData()); break; - case 203: if (c) c->setDepthEnd(cs.getData()); break; - case 204: if (c) c->setAngleLowerLimitXY(cs.getData()); break; - case 205: if (c) c->setAngleUpperLimitXY(cs.getData()); break; case 206: if (c) c->mirror_x = cs.getData(); break; case 207: if (c) c->mirror_y = cs.getData(); break; + case 208: if (c) c->setDistance(cs.getData()); break; } } - //if (c) c->setAngles(cam_angles); //qDebug() << p->name() << ccnt; for (int i = 0; i < ccnt; ++i) { ObjectBase * c = nullptr; diff --git a/qglengine/globject.h b/qglengine/globject.h index cd5fce8..7ad84b8 100644 --- a/qglengine/globject.h +++ b/qglengine/globject.h @@ -247,11 +247,24 @@ public: QVector3D worldDirection() const {return (itransform_ * QVector4D(QVector3D(0,0,-1), 0.)).toVector3D().normalized();} void setDirection(const QVector3D & d); void setDirection(double x, double y, double z) {setDirection(QVector3D(x, y, z));} + double distance() const {return aim_dist;} void setDistance(double d) {aim_dist = d;} void flyCloser(double s); void flyFarer(double s); void flyToDistance(double d); + + void moveForward(const float & x, bool withZ = true); + void moveBackward(const float & x, bool withZ = true) {moveForward(-x, withZ);} + void moveLeft(const float & x, bool withZ = true); + void moveRight(const float & x, bool withZ = true) {moveLeft(-x, withZ);} + void moveUp(const float & x, bool onlyZ = false); + void moveDown(const float & x, bool onlyZ = false) {moveUp(-x, onlyZ);} + + void rotateRoll(const float & a) {rotateY(a);} + void orbitZ(const float & a); + void orbitXY(const float & a); + protected: void transformChanged() override; double aim_dist; diff --git a/qglengine/glrendererbase.cpp b/qglengine/glrendererbase.cpp index c7904ad..3c75192 100644 --- a/qglengine/glrendererbase.cpp +++ b/qglengine/glrendererbase.cpp @@ -211,7 +211,6 @@ void GLRendererBase::renderShadow(Light * l, QOpenGLShaderProgram * prog, QMatri cam.setPos(wp); cam.setAim(wp + (l->worldTransform() * QVector4D(l->direction())).toVector3D()); cam.setDepthStart(view->camera()->depthStart()); - cam.setDepthEnd(view->camera()->depthEnd()); cam.setFOV(l->angle_end); //cam.apply(1.); /*cam.rotateXY(l->angle_end); diff --git a/qglengine/glwidget.cpp b/qglengine/glwidget.cpp index 44f6f1a..c850db1 100644 --- a/qglengine/glwidget.cpp +++ b/qglengine/glwidget.cpp @@ -37,11 +37,6 @@ qreal GLWidget::depthStart() const { } -qreal GLWidget::depthEnd() const { - return view_->depthEnd(); -} - - QColor GLWidget::ambientColor() const { return view_->ambientColor(); } @@ -153,11 +148,6 @@ void GLWidget::setDepthStart(const qreal & arg) { } -void GLWidget::setDepthEnd(const qreal & arg) { - view_->setDepthEnd(arg); -} - - void GLWidget::setAmbientColor(const QColor & arg) { view_->setAmbientColor(arg); } diff --git a/qglengine/glwidget.h b/qglengine/glwidget.h index e88180a..b101fce 100644 --- a/qglengine/glwidget.h +++ b/qglengine/glwidget.h @@ -15,7 +15,6 @@ class GLWidget : public QWidget Q_PROPERTY (qreal lineWidth READ lineWidth WRITE setLineWidth) Q_PROPERTY (qreal FOV READ FOV WRITE setFOV) Q_PROPERTY (qreal depthStart READ depthStart WRITE setDepthStart) - Q_PROPERTY (qreal depthEnd READ depthEnd WRITE setDepthEnd) Q_PROPERTY (QColor ambientColor READ ambientColor WRITE setAmbientColor) Q_PROPERTY (bool grabMouse READ isGrabMouseEnabled WRITE setGrabMouseEnabled) Q_PROPERTY (bool mouseRotate READ isMouseRotateEnabled WRITE setMouseRotateEnabled) @@ -35,7 +34,6 @@ public: qreal lineWidth() const; qreal FOV() const; qreal depthStart() const; - qreal depthEnd() const; QColor ambientColor() const; bool isLightEnabled() const; bool isGrabMouseEnabled() const; @@ -61,7 +59,6 @@ public slots: void setLineWidth(const qreal & arg); void setFOV(const qreal & arg); void setDepthStart(const qreal & arg); - void setDepthEnd(const qreal & arg); void setAmbientColor(const QColor & arg); void setLightEnabled(const bool & arg); void setGrabMouseEnabled(const bool & arg); diff --git a/qglengine/icons/dialog-cancel.png b/qglengine/icons/dialog-cancel.png new file mode 100644 index 0000000000000000000000000000000000000000..ace88ab0b4ad7d743e0173d7638eae6b807afe7d GIT binary patch literal 45200 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 literal 0 HcmV?d00001 diff --git a/qglengine/mouse_controller.cpp b/qglengine/mouse_controller.cpp index 4303d96..406f66d 100644 --- a/qglengine/mouse_controller.cpp +++ b/qglengine/mouse_controller.cpp @@ -199,17 +199,17 @@ void MouseController::mouseMoveEvent(QMouseEvent * e) { float dy = e->y() - lastPos.y(); if (e->buttons().testFlag(Qt::MidButton)) { if (cameraOrbit_) { - view->camera()->orbitZ(dx / 4.f); + view->camera()->orbitZ (dx / 4.f); view->camera()->orbitXY(dy / 4.f); } else { view->camera()->rotateZ(dx / 4.f); - view->camera()->rotateXY(dy / 4.f); + view->camera()->rotateX(dy / 4.f); } emit view->cameraPosChanged(view->camera()->pos()); } else if (e->buttons().testFlag(Qt::RightButton)) { float ad = view->camera()->distance(); view->camera()->moveLeft(dx / 1000.f * ad); - view->camera()->moveUp(dy / 1000.f * ad); + view->camera()->moveUp (dy / 1000.f * ad); emit view->cameraPosChanged(view->camera()->pos()); } } diff --git a/qglengine/qglview.h b/qglengine/qglview.h index 1be8c78..e2604de 100644 --- a/qglengine/qglview.h +++ b/qglengine/qglview.h @@ -47,7 +47,6 @@ class QGLView: public OpenGLWindow Q_PROPERTY (float lineWidth READ lineWidth WRITE setLineWidth) Q_PROPERTY (float FOV READ FOV WRITE setFOV) Q_PROPERTY (float depthStart READ depthStart WRITE setDepthStart) - Q_PROPERTY (float depthEnd READ depthEnd WRITE setDepthEnd) Q_PROPERTY (QColor ambientColor READ ambientColor WRITE setAmbientColor) Q_PROPERTY (QColor fogColor READ fogColor WRITE setFogColor) Q_PROPERTY (bool fogEnabled READ isFogEnabled WRITE setFogEnabled) @@ -108,7 +107,6 @@ public: float lineWidth() const {return lineWidth_;} float FOV() const {return camera()->fov_;} float depthStart() const {return camera()->depth_start;} - float depthEnd() const {return camera()->depth_end;} float currentFPS() const {return fps_;} int maxAnisotropicLevel() const {return max_anisotropic;} @@ -228,7 +226,6 @@ public slots: void setLineWidth(const float & arg) {lineWidth_ = arg;} void setFOV(const float & arg) {camera()->fov_ = arg;} void setDepthStart(const float & arg) {camera()->depth_start = arg;} - void setDepthEnd(const float & arg) {camera()->depth_end = arg;} void setAmbientColor(const QColor & arg) {ambientColor_ = arg;} void setFogColor(const QColor & arg) {fogColor_ = arg;} void setFogDensity(const float & arg) {fogDensity_ = arg;} diff --git a/qglengine/qglview_test/qglview_window.cpp b/qglengine/qglview_test/qglview_window.cpp index a784b3e..fec35e1 100644 --- a/qglengine/qglview_test/qglview_window.cpp +++ b/qglengine/qglview_test/qglview_window.cpp @@ -45,7 +45,6 @@ QGLViewWindow::QGLViewWindow(QWidget * parent): QMainWindow(parent), Ui::QGLView spinFOV->setValue(view->view()->FOV()); spinDepthStart->setValue(view->view()->depthStart()); - spinDepthEnd->setValue(view->view()->depthEnd()); groupHoverHalo->setChecked(view->view()->isHoverHaloEnabled()); groupSelectionHalo->setChecked(view->view()->isSelectionHaloEnabled()); spinHoverHaloFill->setValue(view->view()->hoverHaloFillAlpha()); diff --git a/qglengine/qglview_test/qglview_window.h b/qglengine/qglview_test/qglview_window.h index 15ef1e8..d9b2737 100644 --- a/qglengine/qglview_test/qglview_window.h +++ b/qglengine/qglview_test/qglview_window.h @@ -63,7 +63,6 @@ private: private slots: void on_spinFOV_valueChanged(double val) {view->view()->setFOV(val);} void on_spinDepthStart_valueChanged(double val) {view->view()->setDepthStart(val);} - void on_spinDepthEnd_valueChanged(double val) {view->view()->setDepthEnd(val);} void on_comboViewRenderMode_currentIndexChanged(int val) {static int modes[] = {GL_POINT, GL_LINE, GL_FILL}; view->view()->setRenderMode((ObjectBase::RenderMode)modes[val]);} void on_groupHoverHalo_clicked(bool val) {view->view()->setHoverHaloEnabled(val);} void on_groupSelectionHalo_clicked(bool val) {view->view()->setSelectionHaloEnabled(val);} diff --git a/qglengine/widgets/materials_editor.cpp b/qglengine/widgets/materials_editor.cpp index 0b96b98..ae29604 100644 --- a/qglengine/widgets/materials_editor.cpp +++ b/qglengine/widgets/materials_editor.cpp @@ -51,6 +51,7 @@ bool MaterialsEditor::event(QEvent * e) { ui->buttonAdd ->setIconSize(sz); ui->buttonDelete->setIconSize(sz); ui->buttonAssign->setIconSize(sz); + ui->buttonUnset ->setIconSize(sz); } return QWidget::event(e); } @@ -175,3 +176,11 @@ void MaterialsEditor::on_buttonAssign_clicked() { foreach (ObjectBase * o, ol) o->setMaterial(m, true); } + + +void MaterialsEditor::on_buttonUnset_clicked() { + if (!view) return; + QList ol = view->selectedObjects(); + foreach (ObjectBase * o, ol) + o->setMaterial(0, true); +} diff --git a/qglengine/widgets/materials_editor.h b/qglengine/widgets/materials_editor.h index 60b9ad3..2bbc8be 100644 --- a/qglengine/widgets/materials_editor.h +++ b/qglengine/widgets/materials_editor.h @@ -55,6 +55,7 @@ private slots: void on_buttonAdd_clicked(); void on_buttonDelete_clicked(); void on_buttonAssign_clicked(); + void on_buttonUnset_clicked(); signals: void changed(); diff --git a/qglengine/widgets/materials_editor.ui b/qglengine/widgets/materials_editor.ui index 7e1dbc1..e81227f 100644 --- a/qglengine/widgets/materials_editor.ui +++ b/qglengine/widgets/materials_editor.ui @@ -6,11 +6,23 @@ 0 0 - 542 - 492 + 386 + 520 - + + + 0 + + + 0 + + + 0 + + + 0 + @@ -27,63 +39,122 @@ - - - Rename ... - - - - :/icons/edit-rename.png:/icons/edit-rename.png - - - - - - - Add - - - - :/icons/list-add.png:/icons/list-add.png - - - - - - - Delete - - - - :/icons/edit-delete.png:/icons/edit-delete.png - - - - - - - Qt::Horizontal - - - QSizePolicy::Preferred - - - - 20 - 20 - - - - - - - - Assign - - - - :/icons/go-jump.png:/icons/go-jump.png - + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Vertical + + + + 20 + 1 + + + + + + + + + + Rename ... + + + + :/icons/edit-rename.png:/icons/edit-rename.png + + + + + + + Qt::Horizontal + + + QSizePolicy::Preferred + + + + 40 + 10 + + + + + + + + Unset + + + + :/icons/dialog-cancel.png:/icons/dialog-cancel.png + + + + + + + Add + + + + :/icons/list-add.png:/icons/list-add.png + + + + + + + Delete + + + + :/icons/edit-delete.png:/icons/edit-delete.png + + + + + + + Assign + + + + :/icons/go-jump.png:/icons/go-jump.png + + + + + + + + + Qt::Vertical + + + + 20 + 1 + + + + + @@ -104,12 +175,12 @@ 0 0 - 522 - 440 + 386 + 434 - false + true @@ -160,6 +231,8 @@ + + diff --git a/qglengine/widgets/object_editor.cpp b/qglengine/widgets/object_editor.cpp index dd7a33f..c3a4a46 100644 --- a/qglengine/widgets/object_editor.cpp +++ b/qglengine/widgets/object_editor.cpp @@ -28,6 +28,7 @@ ObjectEditor::ObjectEditor(QWidget * parent): QWidget(parent) { ui->setupUi(this); view = 0; active = true; + ignore_next = false; on_comboLightType_currentIndexChanged(0); ui->widgetMain->setEnabled(false); ui->labelAimDist->hide(); @@ -84,6 +85,10 @@ void ObjectEditor::changeEvent(QEvent * e) { void ObjectEditor::selectionChanged() { + if (ignore_next) { + ignore_next = false; + return; + } ui->widgetMain->setEnabled(false); if (!view) return; QList sol = view->selectedObjects(true); @@ -207,6 +212,7 @@ void ObjectEditor::spinChanged(double v) { if (s == ui->spinScaleY ) o->setScaleY (v); if (s == ui->spinScaleZ ) o->setScaleZ (v); } + ignore_next = true; } @@ -224,6 +230,7 @@ void ObjectEditor::spinLightChanged(double v) { if (s == ui->spinAimDist ) o->setDistance(v); o->apply(); } + ignore_next = true; } @@ -236,6 +243,7 @@ void ObjectEditor::spinCameraChanged(double v) { if (s == ui->spinCameraDepthStart) o->setDepthStart(v); if (s == ui->spinAimDist ) o->setDistance(v); } + ignore_next = true; } diff --git a/qglengine/widgets/object_editor.h b/qglengine/widgets/object_editor.h index 2933152..da81394 100644 --- a/qglengine/widgets/object_editor.h +++ b/qglengine/widgets/object_editor.h @@ -40,7 +40,7 @@ protected: Ui::ObjectEditor * ui; QGLView * view; - bool active; + bool active, ignore_next; private slots: void selectionChanged(); diff --git a/qglengine/widgets/widgets.qrc b/qglengine/widgets/widgets.qrc index db6b102..c83819f 100644 --- a/qglengine/widgets/widgets.qrc +++ b/qglengine/widgets/widgets.qrc @@ -2,6 +2,7 @@ ../icons/go-jump.png ../icons/dialog-close.png + ../icons/dialog-cancel.png ../icons/edit-clear.png ../icons/configure.png ../icons/document-save.png