diff --git a/qglengine/glmesh.cpp b/qglengine/glmesh.cpp index 6c832d8..c5c97cc 100644 --- a/qglengine/glmesh.cpp +++ b/qglengine/glmesh.cpp @@ -310,20 +310,33 @@ uint Mesh::hash() const { void Mesh::translatePoints(const QVector3D & dp) { - if (vertices_.isEmpty()) return; - int vcnt = vertices_.size(); - for (int i = 0; i < vcnt; ++i) { - vertices_[i] += dp; - } - changed = hash_changed = true; + QMatrix4x4 m; + m.translate(dp); + transformPoints(m); } void Mesh::scalePoints(const QVector3D & dp) { + QMatrix4x4 m; + m.scale(dp); + transformPoints(m); +} + + +void Mesh::rotatePoints(const double & angle, const QVector3D & a) { + QMatrix4x4 m; + m.rotate(angle, a); + transformPoints(m); +} + + +void Mesh::transformPoints(const QMatrix4x4 & mat) { if (vertices_.isEmpty()) return; - int vcnt = vertices_.size(); + int vcnt = vertices_.size(), ncnt = normals_.size(); for (int i = 0; i < vcnt; ++i) { - vertices_[i] *= dp; + vertices_[i] = (mat * QVector4D(vertices_[i], 1)).toVector3D(); + if (i < ncnt) + normals_[i] = (mat * QVector4D(normals_[i], 0)).toVector3D(); } changed = hash_changed = true; } diff --git a/qglengine/glmesh.h b/qglengine/glmesh.h index c1b98eb..1244f2c 100644 --- a/qglengine/glmesh.h +++ b/qglengine/glmesh.h @@ -62,8 +62,12 @@ public: QVector< Vector2i> & indicesLines () {changed = hash_changed = true; return lines_;} void translatePoints(const QVector3D & dp); + void translatePoints(const double & x, const double & y, const double & z) {translatePoints(QVector3D(x, y, z));} void scalePoints (const QVector3D & dp); void scalePoints (const double & s) {scalePoints(QVector3D(s, s, s));} + void rotatePoints (const double & angle, const QVector3D & a); + void rotatePoints (const double & angle, const double & x, const double & y, const double & z) {rotatePoints(angle, QVector3D(x, y, z));} + void transformPoints(const QMatrix4x4 & mat); void append(const Mesh * m); bool saveToFile(const QString & filename); diff --git a/qglengine/glprimitives.cpp b/qglengine/glprimitives.cpp index 55d3fd7..7b1caf1 100644 --- a/qglengine/glprimitives.cpp +++ b/qglengine/glprimitives.cpp @@ -126,7 +126,7 @@ Mesh * Primitive::ellipsoid(int segments_wl, int segments_h, float width, float } -Mesh * Primitive::disc(int segments, float width, float length, bool up) { +Mesh * Primitive::disc(int segments, float width, float length, bool up, float end_angle) { Mesh * ret = new Mesh(); QVector & v(ret->vertices ()); QVector & n(ret->normals ()); @@ -137,8 +137,9 @@ Mesh * Primitive::disc(int segments, float width, float length, bool up) { QVector3D cp; v << QVector3D(); t << QVector2D(0.5f, 0.5f); + end_angle *= deg2rad; for (int i = 0; i < segments; i++) { - double a = (double)i / (segments - 1) * M_2PI; + double a = (double)i / (segments - 1) * end_angle; cp.setX(length / 2. * cos(a)); cp.setY(width / 2. * sin(a)); v << cp; @@ -263,7 +264,7 @@ Mesh * Primitive::arrow(int segments, float thick, float angle) { } -Mesh * Primitive::torus(int segments_main, int segments_second, float radius_main, float radius_second) { +Mesh * Primitive::torus(int segments_main, int segments_second, float radius_main, float radius_second, float end_angle) { Mesh * ret = new Mesh(); QVector & v(ret->vertices ()); QVector & n(ret->normals ()); @@ -287,7 +288,7 @@ Mesh * Primitive::torus(int segments_main, int segments_second, float radius_mai for (int i = 0; i < segments_main; i++) { double x = (double)i / (segments_main - 1); QMatrix4x4 rm; - rm.rotate(x * 360., 0., 0., 1.); + rm.rotate(x * end_angle, 0., 0., 1.); for (int j = 0; j < ccnt; j++) { ct[j].setX(x); v << rm.map(cv[j]); diff --git a/qglengine/glprimitives.h b/qglengine/glprimitives.h index 2007b7a..934a615 100644 --- a/qglengine/glprimitives.h +++ b/qglengine/glprimitives.h @@ -31,7 +31,7 @@ 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 * disc(int segments, float width = 1., float length = 1., bool up = true); +Mesh * disc(int segments, float width = 1., float length = 1., bool up = true, float end_angle = 360.); Mesh * cone(int segments, float width = 1., float length = 1., float height = 1.); @@ -39,7 +39,7 @@ Mesh * cylinder(int segments, float width = 1., float length = 1., float height Mesh * arrow(int segments = 16, float thick = 0.04, float angle = 30.); // length = 1 -Mesh * torus(int segments_main = 30, int segments_second = 16, float radius_main = 2.5, float radius_second = 0.5); +Mesh * torus(int segments_main = 30, int segments_second = 16, float radius_main = 2.5, float radius_second = 0.5, float end_angle = 360.); Mesh * cubeFrame(float width = 1., float length = 1., float height = 1.); diff --git a/qglengine/glscene.cpp b/qglengine/glscene.cpp index c4b70f0..0c8425a 100644 --- a/qglengine/glscene.cpp +++ b/qglengine/glscene.cpp @@ -205,6 +205,7 @@ void Scene::selectObjects(QList ol, bool add_to_selection) { void Scene::clearSelection() { selected_.clear(); + selected_top.clear(); QList ol = root_->children(true); foreach (ObjectBase * o, ol) { o->selected_ = false; @@ -412,13 +413,14 @@ bool Scene::prepare() { void Scene::destroy() { + selected_.clear(); + selected_top.clear(); + emitSelectionChanged(); root_->clearChildren(true); qDeleteAll(geometries); qDeleteAll(materials); geometries.clear(); materials.clear(); - selected_.clear(); - selected_top.clear(); emit __destroyed(); emit treeChanged(); } diff --git a/qglengine/gltypes.h b/qglengine/gltypes.h index cc55be2..f79de41 100644 --- a/qglengine/gltypes.h +++ b/qglengine/gltypes.h @@ -163,6 +163,7 @@ QImage rotateQImageRight(const QImage & im); inline QImage rotateQImage180(const QImage & im) {return im.mirrored(true, true);} class QGLView; +class MouseController; class ObjectBase; class Light; class Camera; diff --git a/qglengine/mouse_controller.cpp b/qglengine/mouse_controller.cpp new file mode 100644 index 0000000..f258d3d --- /dev/null +++ b/qglengine/mouse_controller.cpp @@ -0,0 +1,271 @@ +/* + MouseController + Copyright (C) 2019 Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "mouse_controller.h" +#include "glmesh.h" +#include "qglview.h" +#include +#include +#include + +using namespace QGLEngineShaders; + + +MouseController::MouseController(QGLView * view_): view(view_) { + app_scale = 1; + lastPos = QPoint(-1, -1); + cur_action = RendererService::haNoAction; + sel_button = Qt::LeftButton; + sel_mod = Qt::ControlModifier; + mouse_first = mouseSelect_ = mouseRotate_ = cameraOrbit_ = canSelect_ = true; + grabMouse_ = mouse_sec = selecting_ = customMouseMove_ = false; +} + + +MouseController::~MouseController() { +} + + +void MouseController::resize() { + mouse_first = true; + app_scale = appScale(); +} + + +void MouseController::mouseReleaseEvent(QMouseEvent * e) { + if (cur_action != RendererService::haNoAction) { + mouseMoveEvent(e); + return; + } + bool add_ts = e->modifiers().testFlag(sel_mod); + if (selecting_) { + selecting_ = false; + canSelect_ = true; + view->renderer_.mouse_rect = QRect(); + view->scene_->selectObjects(hov_objects.toList(), add_ts); + return; + } + if (canSelect_ && mouseSelect_ && e->button() == Qt::LeftButton) { + if ((lastPos - downPos).manhattanLength() < QApplication::startDragDistance() && !hov_objects.isEmpty()) { + view->scene_->selectObject(hov_objects[0], add_ts); + } + } + canSelect_ = e->buttons() == 0; + emit view->glMouseReleaseEvent(e); +} + + +void MouseController::mousePressEvent(QMouseEvent * e) { + downPos = e->pos(); + if (cur_action != RendererService::haNoAction && e->buttons() == Qt::LeftButton) { + return; + } + if (selecting_) { + selecting_ = false; + view->renderer_.mouse_rect = QRect(); + return; + } + if (!QRect(QPoint(), view->size()).contains(e->pos())) return; + lastPos = e->pos(); + downPos = lastPos; + emit view->glMousePressEvent(e); +} + + +void MouseController::mouseMoveEvent(QMouseEvent * e) { + QPoint cpos = e->pos(); + if (cur_action != RendererService::haNoAction && (e->buttons() == Qt::LeftButton)) { + RendererService & rs(view->renderer_.rend_service); + QList objects = view->scene_->selectedObjects(true); + QVector axis; + switch (cur_action) { + case RendererService::haMove: + if (cur_handle.testFlag(RendererService::hmMoveX)) axis << 0; + if (cur_handle.testFlag(RendererService::hmMoveY)) axis << 1; + if (cur_handle.testFlag(RendererService::hmMoveZ)) axis << 2; + break; + case RendererService::haRotate: + if (cur_handle.testFlag(RendererService::hmRotateX)) axis << 0; + if (cur_handle.testFlag(RendererService::hmRotateY)) axis << 1; + if (cur_handle.testFlag(RendererService::hmRotateZ)) axis << 2; + break; + case RendererService::haScale: + if (cur_handle.testFlag(RendererService::hmScaleX)) axis << 0; + if (cur_handle.testFlag(RendererService::hmScaleY)) axis << 1; + if (cur_handle.testFlag(RendererService::hmScaleZ)) axis << 2; + break; + default: break; + } + QVector scales; + foreach (int a, axis) { + QVector3D axe_vector; axe_vector[a] = 1.; + QMatrix4x4 axis_mat = view->camera()->fullViewMatrix() * rs.axis_mat; + QVector3D center_screen = axis_mat * rs.selection_center; + QVector3D axe_screen = ((axis_mat * (rs.selection_center + axe_vector)) - center_screen).normalized(); + QVector3D mouse_vector(cpos - lastPos); + mouse_vector[1] *= -1.; + if (cur_action == RendererService::haMove) { + double len_scl = 1. / QVector3D(axe_screen.x(), axe_screen.y(), 1.E-6).length(); + mouse_vector /= QVector3D(view->width(), view->height(), 1); + mouse_vector *= -center_screen.z() * len_scl; + axe_vector *= QVector3D::dotProduct(axe_screen, mouse_vector); + QMatrix4x4 pmat; + foreach (ObjectBase * o, objects) { + pmat.setToIdentity(); + if (o->parent()) { + pmat = o->parent()->worldTransform(); + pmat.setColumn(3, QVector4D(0,0,0,1)); + double det = pmat.determinant(); + if (det > 0.) pmat /= sqrt(det); + } + o->move((QVector4D(axe_vector, 0) * pmat).toVector3D()); + } + } + if (cur_action == RendererService::haRotate) { + axe_screen.setZ(0.); + axe_screen.normalize(); + QVector3D norm = QVector3D(axe_screen.y(), -axe_screen.x(), 0.); + axe_vector *= QVector3D::dotProduct(mouse_vector, norm) / 2. / app_scale; + foreach (ObjectBase * o, objects) + o->setRotation(o->rotation() + axe_vector); + } + if (cur_action == RendererService::haScale) { + mouse_vector /= QVector3D(view->width(), view->height(), 1); + mouse_vector *= 3. / app_scale; + axe_vector *= QVector3D::dotProduct(axe_screen, mouse_vector); + scales << axe_vector; + } + } + //if (cur_handle >= RendererService::htScaleX && cur_handle <= RendererService::htScaleZ ) cs = Qt::SplitHCursor; + if (cur_action == RendererService::haScale) { + double sc = 0., max = 0.; + foreach (const QVector3D & s, scales) { + double v = QVector3D::dotProduct(s, QVector3D(1,1,1)); + sc += v; + max = qMax(max, qAbs(v)); + } + sc = max * (sc > 0. ? 1. : -1); + QVector3D axe_vector; + foreach (int a, axis) + axe_vector[a] = 1.; + foreach (ObjectBase * o, objects) + o->scale(QVector3D(1,1,1) + (axe_vector * sc)); + QCursor::setPos(view->mapToGlobal(downPos)); + } else + lastPos = e->pos(); + return; + } + if (selecting_) { + view->renderer_.mouse_rect = QRect(downPos, cpos).normalized(); + return; + } + if (e->buttons().testFlag(Qt::LeftButton)) { + if ((cpos - downPos).manhattanLength() >= QApplication::startDragDistance()) { + selecting_ = true; + canSelect_ = false; + } + return; + } + QRect g_rect(QPoint(), view->size()); + if (mouseRotate_) { + float dx = e->x() - lastPos.x(); + float dy = e->y() - lastPos.y(); + if (e->buttons().testFlag(Qt::MidButton)) { + if (cameraOrbit_) { + 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); + } + 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); + emit view->cameraPosChanged(view->camera()->pos()); + } + } + lastPos = e->pos(); + if (customMouseMove_) emit view->customMouseMoveEvent(e->pos(), lastPos, e->buttons()); + if (e->buttons() == 0) { + cur_handle = 0; + cur_action = RendererService::haNoAction; + Qt::CursorShape cs = Qt::CrossCursor; + if (view->renderer_.edit_mode) { + uint hid = view->renderer_.rend_selection.id_hover; + cur_handle = (RendererService::HandleMesh)hid; + if (hid >= RendererService::hmMoveX && hid <= RendererService::hmMaxMove ) { + cur_action = RendererService::haMove; + cs = Qt::SizeAllCursor; + } + if (hid >= RendererService::hmRotateX && hid <= RendererService::hmMaxRotate) { + cur_action = RendererService::haRotate; + cs = Qt::PointingHandCursor; + } + if (hid >= RendererService::hmScaleX && hid <= RendererService::hmMaxScale ) { + cur_action = RendererService::haScale; + cs = Qt::SplitHCursor; + } + } + if (cur_action == RendererService::haNoAction) + cur_handle = 0; + view->setCursor(cs); + view->renderer_.rend_service.current_handle = cur_handle; + } + if (grabMouse_) { + QCursor::setPos(view->mapToGlobal(QRect(QPoint(), view->size()).center())); + if (mouse_sec) { + mouse_sec = false; + return; + } + if (mouse_first) { + mouse_first = false; + mouse_sec = true; + return; + } + lastPos = g_rect.center(); + int dx = e->x() - lastPos.x(); + int dy = e->y() - lastPos.y(); + emit view->glMouseMoveEvent(new QMouseEvent(QEvent::MouseMove, QPoint(dx, dy), e->button(), e->buttons(), e->modifiers())); + return; + } + emit view->glMouseMoveEvent(e); +} + + +void MouseController::wheelEvent(QWheelEvent * e) { + if (mouseRotate_) { + if (e->delta() > 0) view->camera()->flyCloser(0.1f); + if (e->delta() < 0) view->camera()->flyFarer(0.1f); + emit view->cameraPosChanged(view->camera()->pos()); + } + emit view->glWheelEvent(e); +} + + +void MouseController::leaveEvent(QEvent * ) { + lastPos = QPoint(-1, -1); + //qDebug() << lastPos; +} + + +void MouseController::mouseDoubleClickEvent(QMouseEvent * e) { + if (e->buttons().testFlag(Qt::MidButton)) + emit view->doubleClick(); +} diff --git a/qglengine/mouse_controller.h b/qglengine/mouse_controller.h new file mode 100644 index 0000000..564f34c --- /dev/null +++ b/qglengine/mouse_controller.h @@ -0,0 +1,84 @@ +/* + QGLView + Copyright (C) 2019 Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef MOUSE_CONTROLLER_H +#define MOUSE_CONTROLLER_H + +#include "glprimitives.h" +#include "glcamera.h" +#include "renderer_service.h" +#include +#include + + +class MouseController: public QObject +{ + friend class QGLView; + friend class RendererSelection; + Q_OBJECT +public: + MouseController(QGLView * view_); + virtual ~MouseController(); + + bool isGrabMouseEnabled() const {return grabMouse_;} + bool isMouseRotateEnabled() const {return mouseRotate_;} + bool isMouseSelectionEnabled() const {return mouseSelect_;} + bool isCameraOrbit() const {return cameraOrbit_;} + + Qt::MouseButton selectionButton() const {return sel_button;} + Qt::KeyboardModifier selectionModifier() const {return sel_mod;} + + void setSelectionButton(Qt::MouseButton v) {sel_button = v;} + void setSelectionModifier(Qt::KeyboardModifier v) {sel_mod = v;} + +protected: + void resize(); + void mousePressEvent(QMouseEvent * e); + void mouseMoveEvent(QMouseEvent * e); + void mouseReleaseEvent(QMouseEvent * e); + void wheelEvent(QWheelEvent * e); + void leaveEvent(QEvent * ); + void mouseDoubleClickEvent(QMouseEvent * e); + +private: + QGLView * view; + QPoint lastPos, downPos; + QSet keys_; + QVector hov_objects; + Qt::MouseButton sel_button; + Qt::KeyboardModifier sel_mod; + RendererService::HandleAction cur_action; + QFlags cur_handle; + float app_scale; + bool grabMouse_, mouse_first, mouseRotate_, mouseSelect_, customMouseMove_, canSelect_; + bool cameraOrbit_, selecting_, mouse_sec; + +private slots: + +public slots: + void setGrabMouseEnabled(const bool & arg) {grabMouse_ = arg; mouse_first = true;} + void setMouseRotateEnabled(const bool & arg) {mouseRotate_ = arg;} + void setMouseSelectionEnabled(const bool & arg) {mouseSelect_ = arg;} + void setCustomMouseMove(const bool & arg) {customMouseMove_ = arg;} + void setCameraOrbit(const bool & arg) {cameraOrbit_ = arg;} + +signals: + +}; + +#endif // QGLVIEW_H diff --git a/qglengine/qglview.cpp b/qglengine/qglview.cpp index 2534ebd..6476526 100644 --- a/qglengine/qglview.cpp +++ b/qglengine/qglview.cpp @@ -28,25 +28,20 @@ using namespace QGLEngineShaders; -QGLView::QGLView(): OpenGLWindow(), renderer_(this) { +QGLView::QGLView(): OpenGLWindow(), renderer_(this), mouse(this) { setIcon(QIcon(":/icons/qglview.png")); deleting_ = false; timer = 0; - app_scale = 1; - cur_handle = RendererService::htNoHandle; need_init_ = is_first_draw = true; backColor_ = Qt::darkGray; hoverHaloColor_ = QColor(195, 140, 255); selectionHaloColor_ = QColor(175, 255, 140); ambientColor_ = QColor(10, 10, 10); - lastPos = QPoint(-1, -1); lineWidth_ = 1.; max_anisotropic = 1; max_texture_chanels = 8; - cameraOrbit_ = lightEnabled_ = canSelect_ = true; - shaders_supported = selecting_ = customMouseMove_ = false; - sel_button = Qt::LeftButton; - sel_mod = Qt::ControlModifier; + lightEnabled_ = true; + shaders_supported = false; fps_cnt = 0; fps_tm = fps_ = 0.; fogDensity_ = fogEnd_ = 1.; @@ -77,9 +72,8 @@ QGLView::QGLView(): OpenGLWindow(), renderer_(this) { setFeature(qglDepthOfFieldAutoFocusSpeed, 0.1); setFeature(qglDepthOfFieldFocus, 1.); setFeature(qglDepthOfFieldDiaphragm, 8.); - mouse_first = mouseSelect_ = hoverHalo_ = selectionHalo_ = true; - mouseRotate_ = true; - fogEnabled_ = is_init = grabMouse_ = shaders_bind = changed_ = false; + hoverHalo_ = selectionHalo_ = true; + fogEnabled_ = is_init = shaders_bind = changed_ = false; rmode = ObjectBase::Fill; // sel_pen = QPen(Qt::black, 1, Qt::DashLine); // sel_brush = QBrush(QColor(170, 100, 255, 120)); @@ -94,7 +88,10 @@ QGLView::QGLView(): OpenGLWindow(), renderer_(this) { //camera().aim_ = camera().pos_; ktm_.restart(); - Mesh * m = Primitive::torus(30, 12, 1., 0.1); + //Mesh * m = Primitive::torus(30, 12, 1., 0.1, 90); + Mesh * m = Primitive::disc(10, 1, 1., true, 90); + QMatrix4x4 mat; mat.rotate(90, 1,0,0); + //m->transformPoints(mat); ObjectBase * o = new ObjectBase(m); o->setColor(Qt::cyan); scene()->addObject(o); @@ -121,40 +118,10 @@ void QGLView::start(float freq) { } -Scene::SelectionMode QGLView::selectionMode() const { - return scene_->selectionMode(); -} - - -void QGLView::setSelectionMode(Scene::SelectionMode m) { - scene_->setSelectionMode(m); -} - - -void QGLView::selectObject(ObjectBase * o, bool add_to_selection) { - scene_->selectObject(o, add_to_selection); -} - - -void QGLView::clearSelection() { - scene_->clearSelection(); -} - - -QList QGLView::selectedObjects() const { - return scene_->selectedObjects(); -} - - -ObjectBase * QGLView::selectedObject() const { - return scene_->selectedObject(); -} - - void QGLView::resizeEvent(QResizeEvent * e) { renderLater(); - app_scale = appScale(); + mouse.resize(); } @@ -211,7 +178,7 @@ void QGLView::checkCaps() { void QGLView::__destroyed() { renderer_.rend_mat.mat_thumbnails.clear(); - hov_objects.clear(); + mouse.hov_objects.clear(); } @@ -222,7 +189,6 @@ void QGLView::resizeGL(int width, int height) { prev_size = QSize(width, height); aspect = float(width) / float(height); renderer_.resize(width, height); - mouse_first = true; //qDebug() << "resize" << width << height; iaspect = (aspect == 0.f) ? 0. : 1 / aspect; glViewport(0, 0, width, height); @@ -230,173 +196,6 @@ void QGLView::resizeGL(int width, int height) { } -void QGLView::mouseReleaseEvent(QMouseEvent * e) { - if (cur_handle != RendererService::htNoHandle) { - mouseMoveEvent(e); - return; - } - bool add_ts = e->modifiers().testFlag(sel_mod); - if (selecting_) { - selecting_ = false; - canSelect_ = true; - renderer_.mouse_rect = QRect(); - scene_->selectObjects(hov_objects.toList(), add_ts); - return; - } - if (canSelect_ && mouseSelect_ && e->button() == Qt::LeftButton) { - if ((lastPos - downPos).manhattanLength() < QApplication::startDragDistance() && !hov_objects.isEmpty()) { - scene_->selectObject(hov_objects[0], add_ts); - } - } - canSelect_ = e->buttons() == 0; - emit glMouseReleaseEvent(e); -} - - -void QGLView::mousePressEvent(QMouseEvent * e) { - if (cur_handle != RendererService::htNoHandle && e->buttons() == Qt::LeftButton) { - return; - } - if (selecting_) { - downPos = e->pos(); - selecting_ = false; - renderer_.mouse_rect = QRect(); - return; - } - if (!QRect(QPoint(), size()).contains(e->pos())) return; - lastPos = e->pos(); - downPos = lastPos; - emit glMousePressEvent(e); -} - - -void QGLView::mouseMoveEvent(QMouseEvent * e) { - QPoint cpos = e->pos(); - if (cur_handle != RendererService::htNoHandle && (e->buttons() == Qt::LeftButton)) { - RendererService & rs(renderer_.rend_service); - QList objects = scene()->selectedObjects(true); - int axis = cur_handle; - if (cur_handle >= RendererService::htMoveX && cur_handle <= RendererService::htMoveZ ) axis -= RendererService::htMoveX; - if (cur_handle >= RendererService::htRotateX && cur_handle <= RendererService::htRotateZ) axis -= RendererService::htRotateX; - if (cur_handle >= RendererService::htScaleX && cur_handle <= RendererService::htScaleZ ) axis -= RendererService::htScaleX; - QVector3D axe_vector; axe_vector[axis] = 1.; - QMatrix4x4 axis_mat = camera()->fullViewMatrix() * rs.axis_mat; - QVector3D center_screen = axis_mat * rs.selection_center; - QVector3D axe_screen = ((axis_mat * (rs.selection_center + axe_vector)) - center_screen).normalized(); - QVector3D mouse_vector(cpos - lastPos); - mouse_vector[1] *= -1.; - if (cur_handle >= RendererService::htMoveX && cur_handle <= RendererService::htMoveZ) { - double len_scl = 1. / QVector3D(axe_screen.x(), axe_screen.y(), 1.E-6).length(); - mouse_vector /= QVector3D(width(), height(), 1); - mouse_vector *= -center_screen.z() * len_scl; - axe_vector *= QVector3D::dotProduct(axe_screen, mouse_vector); - foreach (ObjectBase * o, objects) - o->move(axe_vector); - } - if (cur_handle >= RendererService::htRotateX && cur_handle <= RendererService::htRotateZ) { - axe_screen.setZ(0.); - axe_screen.normalize(); - QVector3D norm = QVector3D(axe_screen.y(), -axe_screen.x(), 0.); - axe_vector *= QVector3D::dotProduct(mouse_vector, norm) / 2. / app_scale; - foreach (ObjectBase * o, objects) - o->setRotation(o->rotation() + axe_vector); - } - if (cur_handle >= RendererService::htScaleX && cur_handle <= RendererService::htScaleZ) { - mouse_vector /= QVector3D(width(), height(), 1); - mouse_vector *= 3. / app_scale; - axe_vector *= QVector3D::dotProduct(axe_screen, mouse_vector); - foreach (ObjectBase * o, objects) - o->scale(QVector3D(1,1,1) + axe_vector); - } - //if (cur_handle >= RendererService::htScaleX && cur_handle <= RendererService::htScaleZ ) cs = Qt::SplitHCursor; - lastPos = e->pos(); - return; - } - if (selecting_) { - renderer_.mouse_rect = QRect(downPos, cpos).normalized(); - return; - } - if (e->buttons().testFlag(Qt::LeftButton)) { - if ((cpos - downPos).manhattanLength() >= QApplication::startDragDistance()) { - selecting_ = true; - canSelect_ = false; - } - return; - } - QRect g_rect(QPoint(), size()); - if (mouseRotate_) { - float dx = e->x() - lastPos.x(); - float dy = e->y() - lastPos.y(); - if (e->buttons().testFlag(Qt::MidButton)) { - if (cameraOrbit_) { - camera()->orbitZ(dx / 4.f); - camera()->orbitXY(dy / 4.f); - } else { - camera()->rotateZ(dx / 4.f); - camera()->rotateXY(dy / 4.f); - } - emit cameraPosChanged(camera()->pos()); - } else if (e->buttons().testFlag(Qt::RightButton)) { - float ad = camera()->distance(); - camera()->moveLeft(dx / 1000.f * ad); - camera()->moveUp(dy / 1000.f * ad); - emit cameraPosChanged(camera()->pos()); - } - } - lastPos = e->pos(); - if (customMouseMove_) emit customMouseMoveEvent(e->pos(), lastPos, e->buttons()); - if (e->buttons() == 0) { - cur_handle = RendererService::htNoHandle; - Qt::CursorShape cs = Qt::CrossCursor; - if (renderer_.edit_mode) { - uint hid = renderer_.rend_selection.id_hover; - if (hid >= RendererService::htMoveX && hid <= RendererService::htScaleZ) { - cur_handle = (RendererService::HandleType)hid; - if (hid >= RendererService::htMoveX && hid <= RendererService::htMoveZ ) cs = Qt::SizeAllCursor; - if (hid >= RendererService::htRotateX && hid <= RendererService::htRotateZ) cs = Qt::PointingHandCursor; - if (hid >= RendererService::htScaleX && hid <= RendererService::htScaleZ ) cs = Qt::SplitHCursor; - } - } - setCursor(cs); - } - if (grabMouse_) { - QCursor::setPos(mapToGlobal(QRect(QPoint(), size()).center())); - static bool mouse_sec = false; - if (mouse_sec) { - mouse_sec = false; - return; - } - if (mouse_first) { - mouse_first = false; - mouse_sec = true; - return; - } - lastPos = g_rect.center(); - int dx = e->x() - lastPos.x(); - int dy = e->y() - lastPos.y(); - emit glMouseMoveEvent(new QMouseEvent(QEvent::MouseMove, QPoint(dx, dy), e->button(), e->buttons(), e->modifiers())); - return; - } - emit glMouseMoveEvent(e); -} - - -void QGLView::wheelEvent(QWheelEvent * e) { - if (mouseRotate_) { - if (e->delta() > 0) camera()->flyCloser(0.1f); - if (e->delta() < 0) camera()->flyFarer(0.1f); - emit cameraPosChanged(camera()->pos()); - } - emit glWheelEvent(e); -} - - -void QGLView::leaveEvent(QEvent * ) { - lastPos = QPoint(-1, -1); - //qDebug() << lastPos; -} - - void QGLView::keyPressEvent(QKeyEvent * e) { emit glKeyPressEvent(e); if (e->key() > 0) keys_.insert(e->key()); @@ -417,37 +216,6 @@ void QGLView::focusOutEvent(QFocusEvent *) { } -void QGLView::mouseDoubleClickEvent(QMouseEvent * e) { - if (e->buttons().testFlag(Qt::MidButton)) - emit doubleClick(); -} - - -Camera * QGLView::camera() { - return camera_; -} - - -const Camera * QGLView::camera() const { - return camera_; -} - - -void QGLView::setCamera(Camera * camera) { - camera_ = camera; -} - - -TextureManager * QGLView::textureManager() { - return renderer_.textures_manager; -} - - -void QGLView::reloadTextures() { - renderer_.markReloadTextures(); -} - - void QGLView::focusOn(const Box3D & bb) { if (bb.isEmpty() || !camera()) return; double size = qMax(qMax(bb.width, bb.length), bb.height); @@ -456,16 +224,6 @@ void QGLView::focusOn(const Box3D & bb) { } -void QGLView::setCameraLightOn(bool on) { - renderer_.setCameraLightOn(on); -} - - -bool QGLView::isCameraLightOn() const { - return renderer_.isCameraLightOn(); -} - - QByteArray QGLView::saveCamera() { ChunkStream cs; const Camera * c = camera(); @@ -503,14 +261,3 @@ void QGLView::restoreFeatures(const QByteArray & ba) { ds >> f; features_ = f; } - - -QImage QGLView::materialThumbnail(Material * m) { - return renderer_.materialThumbnail(m); -} - - -void QGLView::setCurrentHadle(RendererService::HandleType ht) { - renderer_.rend_service.setCurrentHadle(ht); -} - diff --git a/qglengine/qglview.h b/qglengine/qglview.h index 4f662ba..514a914 100644 --- a/qglengine/qglview.h +++ b/qglengine/qglview.h @@ -26,11 +26,13 @@ #include "glscene.h" #include "glrendererbase.h" #include "renderer.h" +#include "mouse_controller.h" #include class QGLView: public OpenGLWindow { + friend class MouseController; friend class GLRendererBase; friend class TextureManager; friend class ObjectBase; @@ -117,10 +119,10 @@ public: float fogEnd() const {return fogEnd_;} bool isFogEnabled() const {return fogEnabled_;} bool isLightEnabled() const {return lightEnabled_;} - bool isGrabMouseEnabled() const {return grabMouse_;} - bool isMouseRotateEnabled() const {return mouseRotate_;} - bool isMouseSelectionEnabled() const {return mouseSelect_;} - bool isCameraOrbit() const {return cameraOrbit_;} + bool isGrabMouseEnabled() const {return mouse.isGrabMouseEnabled();} + bool isMouseRotateEnabled() const {return mouse.isMouseRotateEnabled();} + bool isMouseSelectionEnabled() const {return mouse.isMouseSelectionEnabled();} + bool isCameraOrbit() const {return mouse.isCameraOrbit();} bool isHoverHaloEnabled() const {return hoverHalo_;} QColor hoverHaloColor() const {return hoverHaloColor_;} float hoverHaloFillAlpha() const {return hoverHaloFill_;} @@ -137,37 +139,37 @@ public: // void addObject(GLObjectBase & o) {addObject(&o);} - Scene::SelectionMode selectionMode() const; - Qt::MouseButton selectionButton() const {return sel_button;} - Qt::KeyboardModifier selectionModifier() const {return sel_mod;} + Scene::SelectionMode selectionMode() const {return scene_->selectionMode();} + Qt::MouseButton selectionButton() const {return mouse.selectionButton();} + Qt::KeyboardModifier selectionModifier() const {return mouse.selectionModifier();} - void setSelectionMode(Scene::SelectionMode m); - void setSelectionButton(Qt::MouseButton v) {sel_button = v;} - void setSelectionModifier(Qt::KeyboardModifier v) {sel_mod = v;} + void setSelectionMode(Scene::SelectionMode m) {scene_->setSelectionMode(m);} + void setSelectionButton(Qt::MouseButton v) {mouse.setSelectionButton(v);} + void setSelectionModifier(Qt::KeyboardModifier v) {mouse.setSelectionModifier(v);} - void selectObject(ObjectBase * o, bool add_to_selection = false); - void clearSelection(); - QList selectedObjects() const; - ObjectBase * selectedObject() const; + void selectObject(ObjectBase * o, bool add_to_selection = false) {scene_->selectObject(o, add_to_selection);} + void clearSelection() {scene_->clearSelection();} + QList selectedObjects() const {return scene_->selectedObjects();} + ObjectBase * selectedObject() const {return scene_->selectedObject();} - TextureManager * textureManager(); - void reloadTextures(); + TextureManager * textureManager() {return renderer_.textures_manager;} + void reloadTextures() {renderer_.markReloadTextures();} Scene * scene() {return scene_;} void focusOn(const Box3D & bb); - void setCameraLightOn(bool on); - bool isCameraLightOn() const; + void setCameraLightOn(bool on) {renderer_.setCameraLightOn(on);} + bool isCameraLightOn() const {return renderer_.isCameraLightOn();} - Camera * camera(); - const Camera * camera() const; - void setCamera(Camera * camera); + Camera * camera() {return camera_;} + const Camera * camera() const {return camera_;} + void setCamera(Camera * camera) {camera_ = camera;} QByteArray saveCamera(); void restoreCamera(const QByteArray & ba); QByteArray saveFeatures(); void restoreFeatures(const QByteArray & ba); - QImage materialThumbnail(Material * m); - void setCurrentHadle(RendererService::HandleType ht); + QImage materialThumbnail(Material * m) {return renderer_.materialThumbnail(m);} + void setCurrentAction(RendererService::HandleAction ha) {renderer_.rend_service.setCurrentAction(ha);} GLfloat aspect, iaspect; @@ -180,12 +182,12 @@ protected: void timerEvent(QTimerEvent * ); void initialize(); void resizeGL(int width, int height); - void mousePressEvent(QMouseEvent * e); - void mouseMoveEvent(QMouseEvent * e); - void mouseReleaseEvent(QMouseEvent * e); - void wheelEvent(QWheelEvent * e); + void mousePressEvent(QMouseEvent * e) {mouse.mousePressEvent(e);} + void mouseMoveEvent(QMouseEvent * e) {mouse.mouseMoveEvent(e);} + void mouseReleaseEvent(QMouseEvent * e) {mouse.mouseReleaseEvent(e);} + void wheelEvent(QWheelEvent * e) {mouse.wheelEvent(e);} + void mouseDoubleClickEvent(QMouseEvent * e) {mouse.mouseDoubleClickEvent(e);} void leaveEvent(QEvent * ); - void mouseDoubleClickEvent(QMouseEvent * e); void keyPressEvent(QKeyEvent * e); void keyReleaseEvent(QKeyEvent * e); @@ -199,28 +201,24 @@ private: void processKeys(); bool setupViewport(); - QPoint lastPos, downPos; Scene * scene_; Camera * camera_; + MouseController mouse; // uint cid; QSet keys_; QColor backColor_, fogColor_, ambientColor_, hoverHaloColor_, selectionHaloColor_; QTime time, ktm_; GLint max_anisotropic, max_texture_chanels; ObjectBase::RenderMode rmode; - QVector hov_objects; - Qt::MouseButton sel_button; - Qt::KeyboardModifier sel_mod; GLRendererBase::RenderingParameters start_rp; - RendererService::HandleType cur_handle; QHash features_; QSize prev_size; - float lineWidth_, app_scale; + float lineWidth_; float fogDensity_, fogStart_, fogEnd_, fps_, fps_tm, hoverHaloFill_, selectionHaloFill_, m_motionBlurFactor; int timer, fps_cnt, sh_id_loc, deleting_; - bool is_first_draw, is_init, fogEnabled_, lightEnabled_, grabMouse_, mouse_first, mouseRotate_, mouseSelect_, customMouseMove_, canSelect_; - bool shaders_supported, changed_, cameraOrbit_, need_init_; - bool hoverHalo_, selectionHalo_, shaders_bind, selecting_; + bool is_first_draw, is_init, fogEnabled_, lightEnabled_; + bool shaders_supported, changed_, need_init_; + bool hoverHalo_, selectionHalo_, shaders_bind; private slots: void __destroyed(); @@ -238,11 +236,11 @@ public slots: void setFogEnd(const float & arg) {fogEnd_ = arg;} void setFogEnabled(const bool & arg) {fogEnabled_ = arg;} void setLightEnabled(const bool & arg) {lightEnabled_ = arg;} - void setGrabMouseEnabled(const bool & arg) {grabMouse_ = arg; mouse_first = true;} - void setMouseRotateEnabled(const bool & arg) {mouseRotate_ = arg;} - void setMouseSelectionEnabled(const bool & arg) {mouseSelect_ = arg;} - void setCustomMouseMove(const bool & arg) {customMouseMove_ = arg;} - void setCameraOrbit(const bool & arg) {cameraOrbit_ = arg;} + void setGrabMouseEnabled(const bool & arg) {mouse.setGrabMouseEnabled(arg);} + void setMouseRotateEnabled(const bool & arg) {mouse.setMouseRotateEnabled(arg);} + void setMouseSelectionEnabled(const bool & arg) {mouse.setMouseSelectionEnabled(arg);} + void setCustomMouseMove(const bool & arg) {mouse.setCustomMouseMove(arg);} + void setCameraOrbit(const bool & arg) {mouse.setCameraOrbit(arg);} void setHoverHaloEnabled(const bool & arg) {hoverHalo_ = arg;} void setHoverHaloColor(const QColor & arg) {hoverHaloColor_ = arg;} void setHoverHaloFillAlpha(const float & arg) {hoverHaloFill_ = arg;} diff --git a/qglengine/qglview_test/qglview_window.cpp b/qglengine/qglview_test/qglview_window.cpp index 5ad5aae..98c44e6 100644 --- a/qglengine/qglview_test/qglview_window.cpp +++ b/qglengine/qglview_test/qglview_window.cpp @@ -291,7 +291,7 @@ void QGLViewWindow::on_actionArrow_triggered(bool on) { actionMove ->setChecked(false); actionRotate->setChecked(false); actionScale ->setChecked(false); - view->view()->setCurrentHadle(RendererService::htNoHandle); + view->view()->setCurrentAction(RendererService::haNoAction); } @@ -300,7 +300,7 @@ void QGLViewWindow::on_actionMove_triggered(bool on) { actionMove ->setChecked(true); actionRotate->setChecked(false); actionScale ->setChecked(false); - view->view()->setCurrentHadle(RendererService::htMoveX); + view->view()->setCurrentAction(RendererService::haMove); } @@ -309,7 +309,7 @@ void QGLViewWindow::on_actionRotate_triggered(bool on) { actionMove ->setChecked(false); actionRotate->setChecked(true); actionScale ->setChecked(false); - view->view()->setCurrentHadle(RendererService::htRotateX); + view->view()->setCurrentAction(RendererService::haRotate); } @@ -318,5 +318,5 @@ void QGLViewWindow::on_actionScale_triggered(bool on) { actionMove ->setChecked(false); actionRotate->setChecked(false); actionScale ->setChecked(true); - view->view()->setCurrentHadle(RendererService::htScaleX); + view->view()->setCurrentAction(RendererService::haScale); } diff --git a/qglengine/renderer.h b/qglengine/renderer.h index 1e7e6d9..d4a4b6d 100644 --- a/qglengine/renderer.h +++ b/qglengine/renderer.h @@ -28,6 +28,7 @@ class Renderer: public RendererBase { friend class QGLView; + friend class MouseController; friend class RendererMaterial; friend class RendererService; friend class RendererSelection; diff --git a/qglengine/renderer_selection.cpp b/qglengine/renderer_selection.cpp index 48e5855..e445e2b 100644 --- a/qglengine/renderer_selection.cpp +++ b/qglengine/renderer_selection.cpp @@ -88,23 +88,24 @@ void RendererSelection::fillSelectionsBuffer(bool yes, int size) { void RendererSelection::renderSelection(Scene & scene) { QOpenGLShaderProgram * prog = 0; QGLView * view = r->view; + MouseController & mc(view->mouse); if (r->bindShader(Renderer::srSelectionFill, &prog)) { - view->hov_objects.clear(); + mc.hov_objects.clear(); id_hover = 0; if (fbo_selection.queriedPoints() > 0) { if (fbo_selection.queriedPoints() == 1) { id_hover = fbo_selection.getPoint(); - view->hov_objects.resize(1); - view->hov_objects[0] = ids.value(id_hover); + mc.hov_objects.resize(1); + mc.hov_objects[0] = ids.value(id_hover); //qDebug() << id_hover; } else { QVector points = fbo_selection.getPoints(); QSet ids_hover; foreach (uint i, points) ids_hover << i; - view->hov_objects.clear(); + mc.hov_objects.clear(); foreach (uint i, ids_hover) - view->hov_objects << ids.value(i); + mc.hov_objects << ids.value(i); //qDebug() << ids_hover; } } @@ -125,15 +126,7 @@ void RendererSelection::renderSelection(Scene & scene) { rs.omni_mesh->loadSelections(view, cur_selections_); rs.omni_mesh->draw(view, rs.cur_objects.size()); - if (rs.fillCurrentHandleObjects()) { - Mesh * hm = rs.currentHandleMesh(); - if (hm) { - hm->loadObjects(view, rs.cur_objects); - fillSelectionsBuffer(false, 3); - hm->loadSelections(view, cur_selections_); - hm->draw(view, 3); - } - } + rs.drawCurrentHandleObjects(); //mouse_rect = fbo_selection.rect(); if (r->mouse_rect.isNull()) diff --git a/qglengine/renderer_selection.h b/qglengine/renderer_selection.h index 7c656bf..7e5097a 100644 --- a/qglengine/renderer_selection.h +++ b/qglengine/renderer_selection.h @@ -25,6 +25,7 @@ class RendererSelection { friend class QGLView; + friend class MouseController; friend class Renderer; public: diff --git a/qglengine/renderer_service.cpp b/qglengine/renderer_service.cpp index f45f54d..62e10bb 100644 --- a/qglengine/renderer_service.cpp +++ b/qglengine/renderer_service.cpp @@ -29,17 +29,26 @@ using namespace QGLEngineShaders; RendererService::RendererService(Renderer * r_): r(r_) { line_width = 1; - current_handle = htNoHandle; - mat_xyz.resize(3); - color_xyz.resize(3); - const QVector3D _rot[3] = {QVector3D(0,1,0), QVector3D(-1,0,0), QVector3D(0,0,1)}; + current_action = haNoAction; + current_handle = 0; + mat_xyz.resize(3); mat_ms2.resize(3); + color_xyz.resize(3); color_ms2.resize(3); + const QVector3D _rot [3] = {QVector3D(0,1,0), QVector3D(-1,0,0), QVector3D(0, 0,1)}; + const QVector3D _rot2[3] = {QVector3D(0,0,0), QVector3D( 1,0,0), QVector3D(0,-1,0)}; for (int i = 0; i < 3; ++i) { QMatrix4x4 m; m.rotate(90., _rot[i]); mat_xyz[i] = m; - color_xyz[i] = QVector4D(0,0,0,0.667); + m.setToIdentity(); + if (!_rot2[i].isNull()) + m.rotate(90., _rot2[i]); + mat_ms2[i] = m; + color_xyz[i] = color_ms2[i] = QVector4D(0,0,0,0.8); color_xyz[i][i] = 1.; } + color_ms2[0] = (color_xyz[0] + color_xyz[1]) / 2.; + color_ms2[1] = (color_xyz[0] + color_xyz[2]) / 2.; + color_ms2[2] = (color_xyz[1] + color_xyz[2]) / 2.; axis_camera = new Camera(); axis_camera->setAim(QVector3D()); axis_camera->setFOV(45.); @@ -53,20 +62,34 @@ RendererService::RendererService(Renderer * r_): r(r_) { omni_mesh_f->scalePoints(1.5); box_mesh ->scalePoints(1.3); omni_mesh ->scalePoints(1.3); - handle_move_mesh = Primitive::arrow(12, 0.06); + + handle_move_mesh = Primitive::arrow(12, 0.06); + handle_ms_2_mesh = Primitive::torus(8, 12, 0.5, 0.025, 90); + Mesh * m = Primitive::disc(8, 1., 1., true, 90); + handle_ms_2_mesh->append(m); + delete m; + m = Primitive::disc(8, 1., 1., false, 90); + handle_ms_2_mesh->append(m); + delete m; + handle_rotate_mesh = Primitive::arrow(12, 0.03); - Mesh * m = Primitive::torus(30, 12, 0.5, 0.06); + m = Primitive::torus(30, 12, 0.5, 0.06); m->translatePoints(QVector3D(0., 0., 0.75)); handle_rotate_mesh->append(m); delete m; - handle_scale_mesh = Primitive::cylinder(12, 0.06, 0.06, 0.85); + + handle_scale_mesh = Primitive::cylinder(12, 0.06, 0.06, 0.85); m = Primitive::ellipsoid(12, 12, 0.3, 0.3, 0.3); m->translatePoints(QVector3D(0., 0., 0.85)); handle_scale_mesh->append(m); delete m; - handle_move_mesh ->scalePoints(7.5); - handle_rotate_mesh->scalePoints(7.5); - handle_scale_mesh ->scalePoints(7.5); + handle_scale_3_mesh = Primitive::ellipsoid(12, 12, 0.4, 0.4, 0.4); + + handle_move_mesh ->scalePoints(7.5); + handle_ms_2_mesh ->scalePoints(7.5); + handle_rotate_mesh ->scalePoints(7.5); + handle_scale_mesh ->scalePoints(7.5); + handle_scale_3_mesh ->scalePoints(7.5); } @@ -78,8 +101,10 @@ RendererService::~RendererService() { delete axis_camera; delete axis_mesh; delete handle_move_mesh; + delete handle_ms_2_mesh; delete handle_rotate_mesh; delete handle_scale_mesh; + delete handle_scale_3_mesh; } @@ -130,42 +155,98 @@ void RendererService::fillOmniObjects() { } -void RendererService::fillHandleObjects(QVector3D center, HandleType first, QMatrix4x4 add_mat) { - cur_objects.resize(3); - for (int i = 0; i < 3; ++i) { - cur_objects[i].color = color_xyz[i]; - QMatrix4x4 m = invariantSizeMatrix(center); - m = m * add_mat * mat_xyz[i]; - cur_objects[i].object_id = first + i; - m.transposed().copyDataTo(cur_objects[i].modelmatrix); +void RendererService::fillHandleObjects(QVector3D center, HandleMesh ids[], const QVector & mats, const QVector & colors, QMatrix4x4 add_mat, int count) { + QMatrix4x4 m = invariantSizeMatrix(center) * add_mat; + cur_objects.resize(count); + for (int i = 0; i < count; ++i) { + cur_objects[i].color = colors[i]; + QMatrix4x4 omat = m * mats[i]; + cur_objects[i].object_id = ids[i]; + if (current_handle.testFlag(ids[i])) { + cur_objects[i].color = QVector4D(0,1,1,1); + } + omat.transposed().copyDataTo(cur_objects[i].modelmatrix); } } -bool RendererService::fillCurrentHandleObjects() { +bool RendererService::calculateCenter() { QList sol = r->view->scene()->selectedObjects(true); if (sol.isEmpty()) return false; - selection_center = QVector3D(); - Box3D bb; - foreach (ObjectBase * o, sol) { - o->calculateBoundingBox(); - bb |= o->boundingBox(); + selection_center = sol[0]->worldPos(); + if (sol.size() > 1) { + Box3D bb; + foreach (ObjectBase * o, sol) { + o->calculateBoundingBox(); + bb |= o->boundingBox(); + } + if (!bb.isEmpty()) + selection_center = bb.center(); } - if (bb.isEmpty()) - selection_center = sol[0]->worldPos(); - else - selection_center = bb.center(); axis_mat = QMatrix4x4(); - if ((sol.size() == 1) && (current_handle >= htRotateX)) { - axis_mat.rotate(sol[0]->angles_.z(), 0., 0., 1.); - axis_mat.rotate(sol[0]->angles_.y(), 0., 1., 0.); - axis_mat.rotate(sol[0]->angles_.x(), 1., 0., 0.); + if ((sol.size() == 1) && (current_action != haMove)) { + ObjectBase * o = sol[0]; + QMatrix4x4 pmat; + if (o->parent()) { + pmat = o->parent()->worldTransform(); + pmat.setColumn(3, QVector4D(0,0,0,1)); + double det = pmat.determinant(); + if (det > 0.) pmat /= sqrt(det); + } + axis_mat.rotate(o->angles_.z(), 0., 0., 1.); + axis_mat.rotate(o->angles_.y(), 0., 1., 0.); + axis_mat.rotate(o->angles_.x(), 1., 0., 0.); + axis_mat = pmat * axis_mat; } - fillHandleObjects(selection_center, current_handle, axis_mat); return true; } +void RendererService::drawCurrentHandleObjects() { + if (current_action == haNoAction) return; + if (calculateCenter()) { + HandleMesh ids[3]; + switch (current_action) { + case haMove : ids[0] = hmMoveX ; ids[1] = hmMoveY ; ids[2] = hmMoveZ ; break; + case haRotate: ids[0] = hmRotateX; ids[1] = hmRotateY; ids[2] = hmRotateZ; break; + case haScale : ids[0] = hmScaleX ; ids[1] = hmScaleY ; ids[2] = hmScaleZ ; break; + default: break; + } + fillHandleObjects(selection_center, ids, mat_xyz, color_xyz, axis_mat); + Mesh * hm = currentHandleMesh(); + QVector sel; + sel.fill(0, 3); + if (hm) { + hm->loadObjects(r->view, cur_objects); + hm->loadSelections(r->view, sel); + hm->draw(r->view, 3); + } + if (current_action == haMove || current_action == haScale) { + switch (current_action) { + case haMove : ids[0] = hmMoveXY ; ids[1] = hmMoveXZ ; ids[2] = hmMoveYZ ; break; + case haScale : ids[0] = hmScaleXY ; ids[1] = hmScaleXZ ; ids[2] = hmScaleYZ ; break; + default: break; + } + hm = handle_ms_2_mesh; + fillHandleObjects(selection_center, ids, mat_ms2, color_ms2, axis_mat); + hm->loadObjects(r->view, cur_objects); + hm->loadSelections(r->view, sel); + hm->draw(r->view, 3); + if (current_action == haScale) { + hm = handle_scale_3_mesh; + QVector mv; mv.resize(1); + QVector cv; cv.fill(QVector4D(0.9, 0.9, 0.7, 1), 1); + ids[0] = hmMaxScale; + fillHandleObjects(selection_center, ids, mv, cv, axis_mat, 1); + hm->loadObjects(r->view, cur_objects); + hm->loadSelections(r->view, sel); + hm->draw(r->view, 1); + } + } + } +} + + void RendererService::setObjectsColor(QVector & ol, QColor col) { QVector4D cv = QColor2QVector(col); for (int i = 0; i < ol.size(); ++i) @@ -210,16 +291,10 @@ void RendererService::renderService() { r->setUniformCamera(prog, r->view->camera()); /// handles - if (fillCurrentHandleObjects()) { - f->glEnable(GL_BLEND); - f->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - Mesh * hm = currentHandleMesh(); - if (hm) { - hm->loadObjects(r->view, cur_objects); - hm->draw(f, 3); - } - f->glDisable(GL_BLEND); - } + f->glEnable(GL_BLEND); + f->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + drawCurrentHandleObjects(); + f->glDisable(GL_BLEND); /// axis f->glViewport(0, 0, axis_viewport.width(), axis_viewport.height()); @@ -234,16 +309,10 @@ void RendererService::renderService() { Mesh * RendererService::currentHandleMesh() { - switch (current_handle) { - case htMoveX : - case htMoveY : - case htMoveZ : return handle_move_mesh; - case htRotateX: - case htRotateY: - case htRotateZ: return handle_rotate_mesh; - case htScaleX : - case htScaleY : - case htScaleZ : return handle_scale_mesh; + switch (current_action) { + case haMove : return handle_move_mesh; + case haRotate: return handle_rotate_mesh; + case haScale : return handle_scale_mesh; default: break; } return 0; diff --git a/qglengine/renderer_service.h b/qglengine/renderer_service.h index 08561d4..746598f 100644 --- a/qglengine/renderer_service.h +++ b/qglengine/renderer_service.h @@ -26,6 +26,7 @@ class RendererService { friend class QGLView; + friend class MouseController; friend class Renderer; friend class RendererSelection; @@ -33,17 +34,32 @@ public: RendererService(Renderer * r_); virtual ~RendererService(); - enum HandleType { - htNoHandle, - htMoveX, - htMoveY, - htMoveZ, - htRotateX, - htRotateY, - htRotateZ, - htScaleX, - htScaleY, - htScaleZ, + enum HandleAction { + haNoAction, + haMove, + haRotate, + haScale, + }; + + enum HandleMesh { + hmMoveX = 0x01, + hmMoveY = 0x02, + hmMoveZ = 0x04, + hmMoveXY = hmMoveX | hmMoveY, + hmMoveXZ = hmMoveX | hmMoveZ, + hmMoveYZ = hmMoveY | hmMoveZ, + hmMaxMove = hmMoveX | hmMoveY | hmMoveZ, + hmRotateX = 0x08, + hmRotateY = 0x10, + hmRotateZ = 0x20, + hmMaxRotate = hmRotateX | hmRotateY | hmRotateZ, + hmScaleX = 0x40, + hmScaleY = 0x80, + hmScaleZ = 0x100, + hmScaleXY = hmScaleX | hmScaleY, + hmScaleXZ = hmScaleX | hmScaleZ, + hmScaleYZ = hmScaleY | hmScaleZ, + hmMaxScale = hmScaleX | hmScaleY | hmScaleZ, }; void init(int width, int height); @@ -52,26 +68,29 @@ public: QMatrix4x4 invariantSizeMatrix(QVector3D p); void fillXYZObjects(); void fillOmniObjects(); - void fillHandleObjects(QVector3D center, HandleType first, QMatrix4x4 add_mat); - bool fillCurrentHandleObjects(); + void fillHandleObjects(QVector3D center, HandleMesh ids[], const QVector & mats, const QVector & colors, QMatrix4x4 add_mat, int count = 3); + bool calculateCenter(); + void drawCurrentHandleObjects(); void setObjectsColor(QVector & ol, QColor col); void renderService(); - void setCurrentHadle(HandleType ht) {current_handle = ht;} + void setCurrentAction(HandleAction ha) {current_action = ha;} Mesh * currentHandleMesh(); private: Renderer * r; Mesh * axis_mesh, * handle_move_mesh, * handle_rotate_mesh, * handle_scale_mesh; + Mesh * handle_ms_2_mesh, * handle_scale_3_mesh; Mesh * box_mesh_f, * omni_mesh_f, * box_mesh, * omni_mesh; QMatrix4x4 v_mat, axis_mat; QVector3D selection_center; - QVector mat_xyz; - QVector color_xyz; + QVector mat_xyz, mat_ms2; + QVector color_xyz, color_ms2; QVector cur_objects; Camera * axis_camera; QSize axis_viewport; - HandleType current_handle; + HandleAction current_action; + QFlags current_handle; int line_width; double size_vp_scale, size_full_scale;