diff --git a/qglengine/globject.h b/qglengine/globject.h index a98d2b6..e49f127 100644 --- a/qglengine/globject.h +++ b/qglengine/globject.h @@ -307,6 +307,7 @@ inline T globject_cast(const ObjectBase * object) {return reinterpret_cast(ob QDataStream & operator <<(QDataStream & s, const ObjectBase * p); QDataStream & operator >>(QDataStream & s, ObjectBase *& p); -inline ObjectBaseList light2objectList(const QList & v) {ObjectBaseList ret; foreach (Light*i, v) ret << (ObjectBase*)i; return ret;} +inline ObjectBaseList lights2objectList(const QList & v) {ObjectBaseList ret; foreach (Light*i, v) ret << (ObjectBase*)i; return ret;} +inline ObjectBaseList cameras2objectList(const QList & v) {ObjectBaseList ret; foreach (Camera*i, v) ret << (ObjectBase*)i; return ret;} #endif // GLOBJECT_H diff --git a/qglengine/glscene.cpp b/qglengine/glscene.cpp index f8923c5..65a9c4d 100644 --- a/qglengine/glscene.cpp +++ b/qglengine/glscene.cpp @@ -35,7 +35,7 @@ Scene::Scene() { Scene::~Scene() { destroying = true; - destroy(); + clear(); delete root_; } @@ -74,7 +74,7 @@ void Scene::addScene(const Scene * s) { void Scene::assignFrom(const Scene * s) { - destroy(); + clear(); setName(s->name()); foreach (Material * m, s->materials) { Material * nm = new Material(); @@ -91,6 +91,19 @@ void Scene::assignFrom(const Scene * s) { } +void Scene::clear() { + selected_.clear(); + selected_top.clear(); + emitSelectionChanged(); + root_->clearChildren(true); + td_geometries << geometries; + qDeleteAll(materials); + geometries.clear(); + materials.clear(); + emit __destroyed(); + emit treeChanged();} + + void Scene::objectsCountInternal(int * cnt, ObjectBase * where) { ++(*cnt); foreach (ObjectBase * i, where->children_) @@ -422,6 +435,9 @@ void Scene::prepareTree(ObjectBase * o) { co->setObjectsChanged(); } break; + case ObjectBase::glCamera: + cameras_used << globject_cast(co); + break; default: break; } prepareTree(co); @@ -445,6 +461,7 @@ bool Scene::prepare() { geometries_used[rpSolid ].clear(); geometries_used[rpTransparent].clear(); lights_used.clear(); + cameras_used.clear(); prepareTree(root_); if (tree_struct_changed) { tree_struct_changed = false; @@ -459,17 +476,9 @@ bool Scene::prepare() { } -void Scene::destroy() { - selected_.clear(); - selected_top.clear(); - emitSelectionChanged(); - root_->clearChildren(true); - td_geometries << geometries; - qDeleteAll(materials); - geometries.clear(); - materials.clear(); - emit __destroyed(); - emit treeChanged(); +void Scene::destroy(QOpenGLExtraFunctions * f) { + foreach (Mesh * g, geometries) + g->destroy(f); } diff --git a/qglengine/glscene.h b/qglengine/glscene.h index c3677af..fac4336 100644 --- a/qglengine/glscene.h +++ b/qglengine/glscene.h @@ -60,6 +60,7 @@ public: void addScene(const Scene * s); void assignFrom(const Scene * s); + void clear(); int objectsCount(bool all = false); ObjectBaseList objects(bool all = false); @@ -89,7 +90,7 @@ public: void removeLight(Light * l); void dump(); - void destroy(); + void destroy(QOpenGLExtraFunctions * f); void destroyUnused(QOpenGLExtraFunctions * f); protected: @@ -120,6 +121,7 @@ protected: QMap> geometries_used; // [pass][mesh] = ObjectBaseList QMap> lights_used; // by Light::Type + QList cameras_used; QVector changed_materials; SelectionMode sel_mode_; diff --git a/qglengine/mouse_controller.cpp b/qglengine/mouse_controller.cpp index 71a0954..02fe546 100644 --- a/qglengine/mouse_controller.cpp +++ b/qglengine/mouse_controller.cpp @@ -208,8 +208,8 @@ void MouseController::mouseMoveEvent(QMouseEvent * e) { view->camera()->orbitZ (dx / 4.f); view->camera()->orbitXY(dy / 4.f); } else { - view->camera()->rotateZ(dx / 4.f); - view->camera()->rotateX(dy / 4.f); + view->camera()->rotateZ(-dx / 4.f); + view->camera()->rotateX(-dy / 4.f); } emit view->cameraPosChanged(view->camera()->pos()); } else if (e->buttons().testFlag(Qt::RightButton)) { diff --git a/qglengine/qglview.cpp b/qglengine/qglview.cpp index f4c05dc..7f31489 100644 --- a/qglengine/qglview.cpp +++ b/qglengine/qglview.cpp @@ -81,12 +81,14 @@ QGLView::QGLView(): OpenGLWindow(), renderer_(this), mouse(this) { scene_ = new Scene(); connect(scene_, SIGNAL(selectionChanged()), this, SIGNAL(selectionChanged())); connect(scene_, SIGNAL(__destroyed()), this, SLOT(__destroyed())); - camera_ = new Camera(); - camera_->setPos(QVector3D(2, 2, 2)); - camera_->setAim(QVector3D()); + connect(scene_, SIGNAL(__objectDeleted(ObjectBase*)), this, SLOT(__objectDeleted(ObjectBase*))); + default_camera = new Camera(); + default_camera->setPos(QVector3D(2, 2, 2)); + default_camera->setAim(QVector3D()); + camera_ = default_camera; // qDebug() << camera_->aim(); - camera_->setName("Camera"); - emit cameraPosChanged(camera_->pos()); + default_camera->setName("Camera"); + emit cameraPosChanged(default_camera->pos()); //camera().aim_ = camera().pos_; ktm_.restart(); @@ -109,8 +111,9 @@ QGLView::QGLView(): OpenGLWindow(), renderer_(this), mouse(this) { QGLView::~QGLView() { deleting_ = true; stop(); - scene_->destroy(); + scene_->clear(); delete scene_; + delete default_camera; } @@ -210,6 +213,12 @@ void QGLView::__destroyed() { } +void QGLView::__objectDeleted(ObjectBase * o) { + if (o == camera_) + setDefaultCamera(); +} + + void QGLView::resizeGL(int width, int height) { if (!is_init) return; if (width <= 0 || height <= 0) return; diff --git a/qglengine/qglview.h b/qglengine/qglview.h index d2d04af..7cd77f9 100644 --- a/qglengine/qglview.h +++ b/qglengine/qglview.h @@ -178,6 +178,7 @@ public: Camera * camera() {return camera_;} const Camera * camera() const {return camera_;} void setCamera(Camera * camera) {camera_ = camera;} + void setDefaultCamera() {camera_ = default_camera;} QByteArray saveCamera(); void restoreCamera(const QByteArray & ba); QByteArray saveFeatures(); @@ -215,7 +216,7 @@ private: bool setupViewport(); Scene * scene_; - Camera * camera_; + Camera * camera_, * default_camera; MouseController mouse; QMenu context_menu; // uint cid; @@ -237,6 +238,7 @@ private: private slots: void __destroyed(); + void __objectDeleted(ObjectBase * o); public slots: void setBackColor(const QColor & arg) {backColor_ = arg;} diff --git a/qglengine/qglview_test/qglview_window.cpp b/qglengine/qglview_test/qglview_window.cpp index 5d9d37e..c100356 100644 --- a/qglengine/qglview_test/qglview_window.cpp +++ b/qglengine/qglview_test/qglview_window.cpp @@ -145,7 +145,7 @@ void QGLViewWindow::loadFile(const QString & path, bool import) { void QGLViewWindow::on_actionReset_triggered() { ///view->view()->removeObject(axis, false); - view->view()->scene()->destroy(); + view->view()->scene()->clear(); ///view->view()->addObject(axis); } diff --git a/qglengine/renderer_selection.cpp b/qglengine/renderer_selection.cpp index 97c341d..c912d33 100644 --- a/qglengine/renderer_selection.cpp +++ b/qglengine/renderer_selection.cpp @@ -79,6 +79,12 @@ void RendererSelection::generateObjectsID(Scene & scene) { o->id_ = id; } } + foreach (Camera * o, scene.cameras_used) { + uint id = qHash(o); + ids[id] = o; + aim_ids[id + 1] = o; + o->id_ = id; + } } } @@ -130,6 +136,7 @@ void RendererSelection::renderSelection(Scene & scene) { RendererService & rs(r->rend_service); rs.drawLights(); + rs.drawCameras(); rs.drawCurrentHandleObjects(); //mouse_rect = fbo_selection.rect(); diff --git a/qglengine/renderer_service.cpp b/qglengine/renderer_service.cpp index 3011095..901b57c 100644 --- a/qglengine/renderer_service.cpp +++ b/qglengine/renderer_service.cpp @@ -54,6 +54,7 @@ RendererService::RendererService(Renderer * r_): r(r_) { axis_camera->setFOV(45.); axis_mesh = Primitive::arrow(12); size_vp_scale = size_full_scale = 1.; + box_mesh = Primitive::cube(0.8, 0.8, 0.8); box_mesh_f = Primitive::cubeFrame(0.8, 0.8, 0.8); omni_mesh = Primitive::ellipsoid(2, 1, 0.5); @@ -75,11 +76,23 @@ RendererService::RendererService(Renderer * r_): r(r_) { cone_mesh ->translatePoints(0,0,-0.5); cone_mesh ->scalePoints(1.5); + camera_mesh = Primitive::cube(1.2, 1.2, 1.2); + mat.translate(0,0,-0.5); + Mesh * m = Primitive::cone(6, 0.6, 1.); + m->scalePoints(1.4); + m->transformPoints(mat); + camera_mesh->append(m); + camera_mesh_f = Primitive::cubeFrame(1., 1., 1.); + camera_mesh_f->append(Primitive::cubeFrame(0.5, 0.5, 0.5)); + m = Primitive::coneFrame(6, 0.6, 1.); + m->transformPoints(mat); + camera_mesh_f->append(m); + line_mesh_f = Primitive::lineFrame(QVector3D(), QVector3D(0, 0, -1)); 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, 0.5, 90); + m = Primitive::disc(8, 0.5, 90); handle_ms_2_mesh->append(m); m->flipNormals(); handle_ms_2_mesh->append(m); @@ -113,6 +126,8 @@ RendererService::~RendererService() { delete omni_mesh_f; delete cone_mesh; delete cone_mesh_f; + delete camera_mesh; + delete camera_mesh_f; delete line_mesh_f; delete axis_camera; delete axis_mesh; @@ -187,8 +202,7 @@ void RendererService::fillOmniObjects() { } -void RendererService::fillSpotObjects() { - QList ll = r->view->scene()->lights_used.value(Light::Cone); +void RendererService::fillAimedObjects(const ObjectBaseList & objects) { Object o; cur_objects.clear(); cur_aims.clear(); @@ -197,18 +211,19 @@ void RendererService::fillSpotObjects() { QVector & lt (line_mesh_f->texcoords ()); QVector< Vector2i> & lind(line_mesh_f->indicesLines()); lv.clear(); - foreach (Light * l, ll) { + foreach (ObjectBase * go, objects) { + AimedObject * ao = (AimedObject *)go; QMatrix4x4 m; - m = invariantSizeMatrix(l->worldPos()) * parentRotationMatrix(l); + m = invariantSizeMatrix(ao->worldPos()) * parentRotationMatrix(ao); m.transposed().copyDataTo(o.modelmatrix); - o.object_id = l->id_; + o.object_id = ao->id_; cur_objects << o; - lv << l->worldPos() << l->worldAim(); + lv << ao->worldPos() << ao->worldAim(); - m = invariantSizeMatrix(l->worldAim()); + m = invariantSizeMatrix(ao->worldAim()); m.transposed().copyDataTo(o.modelmatrix); - o.object_id = l->id_ + 1; + o.object_id = ao->id_ + 1; cur_aims << o; } ln.resize(lv.size()); @@ -313,13 +328,14 @@ void RendererService::drawLights() { fillOmniObjects(); omni_mesh->loadObjects(v, cur_objects); - r->fillSelectionsBuffer(rs.cur_selections_, light2objectList(v->scene_->lights_used.value(Light::Omni))); + r->fillSelectionsBuffer(rs.cur_selections_, lights2objectList(v->scene_->lights_used.value(Light::Omni))); omni_mesh->loadSelections(v, rs.cur_selections_); omni_mesh->draw(v, cur_objects.size()); - fillSpotObjects(); + ObjectBaseList ll = lights2objectList(r->view->scene()->lights_used.value(Light::Cone)); + fillAimedObjects(ll); cone_mesh->loadObjects(v, cur_objects); - r->fillSelectionsBuffer(rs.cur_selections_, light2objectList(v->scene_->lights_used.value(Light::Cone))); + r->fillSelectionsBuffer(rs.cur_selections_, ll); cone_mesh->loadSelections(v, rs.cur_selections_); cone_mesh->draw(v, cur_objects.size()); box_mesh->loadObjects(v, cur_aims); @@ -336,14 +352,15 @@ void RendererService::drawLightsFrame(QColor color) { fillOmniObjects(); setObjectsColor(cur_objects, color); omni_mesh_f->loadObjects(v, cur_objects); - r->fillSelectionsBuffer(rs.cur_selections_, light2objectList(v->scene_->lights_used.value(Light::Omni))); + r->fillSelectionsBuffer(rs.cur_selections_, lights2objectList(v->scene_->lights_used.value(Light::Omni))); omni_mesh_f->loadSelections(v, rs.cur_selections_); omni_mesh_f->draw(v, cur_objects.size()); - fillSpotObjects(); + ObjectBaseList ll = lights2objectList(r->view->scene()->lights_used.value(Light::Cone)); + fillAimedObjects(ll); setObjectsColor(cur_objects, color); cone_mesh_f->loadObjects(v, cur_objects); - r->fillSelectionsBuffer(rs.cur_selections_, light2objectList(v->scene_->lights_used.value(Light::Cone))); + r->fillSelectionsBuffer(rs.cur_selections_, ll); cone_mesh_f->loadSelections(v, rs.cur_selections_); cone_mesh_f->draw(v, cur_objects.size()); @@ -355,6 +372,45 @@ void RendererService::drawLightsFrame(QColor color) { } +void RendererService::drawCameras() { + QGLView * v = r->view; + RendererSelection & rs(r->rend_selection); + + ObjectBaseList cl = cameras2objectList(r->view->scene()->cameras_used); + cl.removeOne(r->view->camera()); + fillAimedObjects(cl); + camera_mesh->loadObjects(v, cur_objects); + r->fillSelectionsBuffer(rs.cur_selections_, cl); + camera_mesh->loadSelections(v, rs.cur_selections_); + camera_mesh->draw(v, cur_objects.size()); + box_mesh->loadObjects(v, cur_aims); + box_mesh->loadSelections(v, rs.cur_selections_); + box_mesh->draw(v, cur_aims.size()); + +} + + +void RendererService::drawCamerasFrame(QColor color) { + QGLView * v = r->view; + RendererSelection & rs(r->rend_selection); + + ObjectBaseList cl = cameras2objectList(r->view->scene()->cameras_used); + cl.removeOne(r->view->camera()); + fillAimedObjects(cl); + setObjectsColor(cur_objects, color); + camera_mesh_f->loadObjects(v, cur_objects); + r->fillSelectionsBuffer(rs.cur_selections_, cl); + camera_mesh_f->loadSelections(v, rs.cur_selections_); + camera_mesh_f->draw(v, cur_objects.size()); + + setObjectsColor(cur_aims, color); + box_mesh_f->loadObjects(v, cur_aims); + box_mesh_f->loadSelections(v, rs.cur_selections_); + box_mesh_f->draw(v, cur_aims.size()); + +} + + void RendererService::setObjectsColor(QVector & ol, QColor col) { QVector4D cv = QColor2QVector(col); for (int i = 0; i < ol.size(); ++i) @@ -380,9 +436,11 @@ void RendererService::renderService() { prog->setUniformValue("line_width", 2.f); prog->setUniformValue("z_offset", 0.f); drawLightsFrame(Qt::white); + drawCamerasFrame(Qt::white); prog->setUniformValue("line_width", 1.f); prog->setUniformValue("z_offset", -1.E-2f); drawLightsFrame(Qt::black); + drawCamerasFrame(Qt::black); } if (r->bindShader(Renderer::srServiceLine, &prog)) { diff --git a/qglengine/renderer_service.h b/qglengine/renderer_service.h index 92c3644..1903e90 100644 --- a/qglengine/renderer_service.h +++ b/qglengine/renderer_service.h @@ -69,12 +69,14 @@ public: QMatrix4x4 parentRotationMatrix(ObjectBase * o, bool self_rotation = true); void fillXYZObjects(); void fillOmniObjects(); - void fillSpotObjects(); + void fillAimedObjects(const ObjectBaseList & objects); void fillHandleObjects(QVector3D center, HandleMesh ids[], const QVector & mats, const QVector & colors, QMatrix4x4 add_mat, int count = 3); bool calculateCenter(); void drawCurrentHandleObjects(); void drawLights(); void drawLightsFrame(QColor color); + void drawCameras(); + void drawCamerasFrame(QColor color); void setObjectsColor(QVector & ol, QColor col); void renderService(); void setCurrentAction(HandleAction ha) {current_action = ha;} @@ -85,7 +87,8 @@ private: 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, * cone_mesh_f, * box_mesh, * omni_mesh, * cone_mesh; + Mesh * box_mesh_f, * omni_mesh_f, * cone_mesh_f, * camera_mesh_f; + Mesh * box_mesh, * omni_mesh, * cone_mesh, * camera_mesh; Mesh * line_mesh_f; QMatrix4x4 v_mat, axis_mat; QVector3D selection_center; diff --git a/qglengine/widgets/scene_tree.cpp b/qglengine/widgets/scene_tree.cpp index 9fcbac2..e32307c 100644 --- a/qglengine/widgets/scene_tree.cpp +++ b/qglengine/widgets/scene_tree.cpp @@ -103,6 +103,7 @@ QList SceneTree::actionsSelection() { << ui->actionGroup << ui->actionClone << newSeparator() << ui->actionSelect_parent << ui->actionSelect_by_mesh << ui->actionSelect_by_material << newSeparator() << ui->actionTransfer_transform_to_children << newSeparator() + << ui->actionActive_camera << ui->actionDefault_camera << newSeparator() << ui->actionRemove; return ret; } @@ -165,6 +166,8 @@ void SceneTree::makeObjetTree(ObjectBase * o, QTreeWidgetItem * ti) { case ObjectBase::glCamera: t = otCamera; ci->setIcon(cName, icon_camera); + ci->setText(cVis, (co == view->camera()) ? "*" : ""); + cam_items << ci; break; default: break; } @@ -217,6 +220,16 @@ void SceneTree::materialsChanged() { } +void SceneTree::cameraChanged() { + if (!view) return; + foreach (QTreeWidgetItem * i, cam_items) { + ObjectBase * o = itemObject(i); + if (!o) continue; + i->setText(cVis, (o == view->camera()) ? "*" : ""); + } +} + + bool SceneTree::filterTree(QTreeWidgetItem * ti, const QString & filter, int types) { bool ret = false; for (int i = 0; i < ti->childCount(); ++i) { @@ -262,6 +275,7 @@ void SceneTree::checkActions() { ui->actionSelect_parent->setEnabled(has_1); ui->actionSelect_by_mesh->setEnabled(has_1); ui->actionSelect_by_material->setEnabled(has_1); + ui->actionActive_camera->setEnabled(has_1); } @@ -299,6 +313,11 @@ void SceneTree::__objectDeleted(ObjectBase * o) { geo_items.removeAt(i); --i; } + for (int i = 0; i < cam_items.size(); ++i) + if (itemObject(cam_items[i]) == o) { + cam_items.removeAt(i); + --i; + } } @@ -396,6 +415,23 @@ void SceneTree::on_actionTransfer_transform_to_children_triggered() { } +void SceneTree::on_actionActive_camera_triggered() { + if (!view) return; + ObjectBase * o = view->scene()->selectedObject(); + if (!o) return; + if (o->type() != ObjectBase::glCamera) return; + view->setCamera((Camera *)o); + cameraChanged(); +} + + +void SceneTree::on_actionDefault_camera_triggered() { + if (!view) return; + view->setDefaultCamera(); + cameraChanged(); +} + + void SceneTree::on_actionSelect_parent_triggered() { if (!view) return; ObjectBaseList sol = view->scene()->selectedObjects(true); @@ -448,6 +484,7 @@ void SceneTree::objectsTreeChanged() { int vpos = ui->treeObjects->verticalScrollBar()->value(); expanded_.clear(); geo_items.clear(); + cam_items.clear(); rememberExpanded(ui->treeObjects->invisibleRootItem()); block_tree = true; ui->treeObjects->clear(); diff --git a/qglengine/widgets/scene_tree.h b/qglengine/widgets/scene_tree.h index 7caade0..4dc732f 100644 --- a/qglengine/widgets/scene_tree.h +++ b/qglengine/widgets/scene_tree.h @@ -55,7 +55,7 @@ private: int hidden_by_filter, obj_count; QIcon icon_empty, icon_geo, icon_camera, icon_light, icon_vis[2]; QSet expanded_; - QList geo_items; + QList geo_items, cam_items; QGLView * view; private slots: @@ -73,6 +73,9 @@ private slots: void on_actionGroup_triggered(); void on_actionTransfer_transform_to_children_triggered(); + void on_actionActive_camera_triggered(); + void on_actionDefault_camera_triggered(); + void on_actionSelect_parent_triggered(); void on_actionSelect_by_mesh_triggered(); void on_actionSelect_by_material_triggered(); @@ -82,10 +85,10 @@ private slots: void objectsTreeChanged(); void selectionChanged(); void materialsChanged(); + void cameraChanged(); void filter(); void __objectDeleted(ObjectBase * o); - public slots: signals: diff --git a/qglengine/widgets/scene_tree.ui b/qglengine/widgets/scene_tree.ui index 7a98713..ec57188 100644 --- a/qglengine/widgets/scene_tree.ui +++ b/qglengine/widgets/scene_tree.ui @@ -265,6 +265,24 @@ Transfer transform to children + + + + :/icons/type-camera.png:/icons/type-camera.png + + + Active camera + + + + + + :/icons/type-camera.png:/icons/type-camera.png + + + Default camera + +