diff --git a/GraphicsView/include/CGAL/Qt/qglviewer.h b/GraphicsView/include/CGAL/Qt/qglviewer.h index 17b91c38b45..ccf4e26e378 100644 --- a/GraphicsView/include/CGAL/Qt/qglviewer.h +++ b/GraphicsView/include/CGAL/Qt/qglviewer.h @@ -1205,6 +1205,7 @@ protected: qglviewer::Vec _offset; //C o n t e x t bool is_ogl_4_3; + bool is_sharing; public: //! Is used to know if the openGL context is 4.3 or ES 2.0. //! @returns `true` if the context is 4.3. diff --git a/Polyhedron/demo/Polyhedron/CMakeLists.txt b/Polyhedron/demo/Polyhedron/CMakeLists.txt index 4e949955731..52067f57ef0 100644 --- a/Polyhedron/demo/Polyhedron/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/CMakeLists.txt @@ -129,6 +129,7 @@ if(CGAL_Qt5_FOUND AND Qt5_FOUND AND OPENGL_FOUND ) find_package(Boost COMPONENTS thread system filesystem) qt5_wrap_ui( MainWindowUI_files MainWindow.ui) + qt5_wrap_ui( SubViewerUI_files SubViewer.ui) qt5_wrap_ui( statisticsUI_FILES Statistics_on_item_dialog.ui) qt5_wrap_ui( FileLoaderDialogUI_files FileLoaderDialog.ui ) qt5_wrap_ui( Show_point_dialogUI_FILES Show_point_dialog.ui ) @@ -309,7 +310,8 @@ if(CGAL_Qt5_FOUND AND Qt5_FOUND AND OPENGL_FOUND ) Polyhedron_demo.cpp File_loader_dialog_moc.cpp ${CGAL_Qt5_RESOURCE_FILES} ${CGAL_Qt5_MOC_FILES} - ${FileLoaderDialogUI_files} ${MainWindowUI_files} ${PreferencesUI_FILES} ${statisticsUI_FILES}) + ${FileLoaderDialogUI_files} ${MainWindowUI_files} ${PreferencesUI_FILES} + ${statisticsUI_FILES} ${SubViewerUI_files}) target_link_libraries(polyhedron_demo PUBLIC demo_framework point_dialog Qt5::Gui Qt5::OpenGL Qt5::Widgets Qt5::Script) add_executable ( Polyhedron_3 Polyhedron_3.cpp ) diff --git a/Polyhedron/demo/Polyhedron/MainWindow.cpp b/Polyhedron/demo/Polyhedron/MainWindow.cpp index c80a8690b1e..af57cde27d0 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.cpp +++ b/Polyhedron/demo/Polyhedron/MainWindow.cpp @@ -51,6 +51,7 @@ #include #include #include +#include "ui_SubViewer.h" #include "ui_MainWindow.h" #include "ui_Preferences.h" #include "ui_Statistics_on_item_dialog.h" @@ -147,6 +148,7 @@ MainWindow::MainWindow(bool verbose, QWidget* parent) // Save some pointers from ui, for latter use. sceneView = ui->sceneView; viewer = ui->viewer; + viewer->setObjectName("viewer"); // do not save the state of the viewer (anoying) viewer->setStateFileName(QString::null); @@ -167,6 +169,12 @@ MainWindow::MainWindow(bool verbose, QWidget* parent) connect(shortcut, SIGNAL(activated()), this, SLOT(toggleFullScreen())); } + setupViewer(viewer, 0); + + viewer->setKeyDescription(Qt::Key_R + Qt::CTRL, + tr("Recenters the viewer under the cursor. " + "If the cursor is not over any viewer, " + "then all viewers are recentered.")); proxyModel = new QSortFilterProxyModel(this); proxyModel->setSourceModel(scene); @@ -206,7 +214,7 @@ MainWindow::MainWindow(bool verbose, QWidget* parent) this, SLOT(removeManipulatedFrame(CGAL::Three::Scene_item*))); connect(scene, SIGNAL(updated_bbox(bool)), - this, SLOT(updateViewerBBox(bool))); + this, SLOT(updateViewersBboxes(bool))); connect(scene, SIGNAL(selectionChanged(int)), this, SLOT(selectSceneItem(int))); @@ -806,7 +814,7 @@ void MainWindow::viewerShow(float xmin, min_(xmin, ymin, zmin), max_(xmax, ymax, zmax); - if(min_ == max_) return viewerShow(xmin, ymin, zmin); + if(min_ == max_) return viewerShow(viewer, xmin, ymin, zmin); viewer->camera()->setPivotPoint((min_+max_)*0.5); @@ -818,18 +826,17 @@ void MainWindow::viewerShow(float xmin, viewer->setVisualHintsMask(1); } -void MainWindow::viewerShow(float x, float y, float z) { - // viewer->camera()->lookAt(CGAL::qglviewer::Vec(x, y, z)); +void MainWindow::viewerShow(Viewer_interface* vi, float x, float y, float z) { + + CGAL::qglviewer::ManipulatedCameraFrame backup_frame(*vi->camera()->frame()); + vi->camera()->fitSphere(CGAL::qglviewer::Vec(x, y, z), + vi->camera()->sceneRadius()/100); + CGAL::qglviewer::ManipulatedCameraFrame new_frame(*vi->camera()->frame()); + *vi->camera()->frame() = backup_frame; + vi->camera()->interpolateTo(new_frame, 1.f); + vi->setVisualHintsMask(1); - CGAL::qglviewer::ManipulatedCameraFrame backup_frame(*viewer->camera()->frame()); - viewer->camera()->fitSphere(CGAL::qglviewer::Vec(x, y, z), - viewer->camera()->sceneRadius()/100); - CGAL::qglviewer::ManipulatedCameraFrame new_frame(*viewer->camera()->frame()); - *viewer->camera()->frame() = backup_frame; - viewer->camera()->interpolateTo(new_frame, 1.f); - viewer->setVisualHintsMask(1); - - viewer->camera()->setPivotPoint(CGAL::qglviewer::Vec(x, y, z)); + vi->camera()->setPivotPoint(CGAL::qglviewer::Vec(x, y, z)); } void MainWindow::message(QString message, QString colorName, QString font) { @@ -860,10 +867,24 @@ void MainWindow::error(QString text) { this->message("ERROR: " + text, "red"); } -void MainWindow::updateViewerBBox(bool recenter = true) +void MainWindow::updateViewersBboxes(bool recenter) { - const Scene::Bbox bbox = scene->bbox(); - CGAL::qglviewer::Vec center = viewer->camera()->pivotPoint(); + CGAL::qglviewer::Vec min, max; + computeViewerBBox(min, max); + Q_FOREACH(CGAL::QGLViewer* v, CGAL::QGLViewer::QGLViewerPool()) + { + if(v == NULL) + continue; + Viewer* vi = static_cast(v); + updateViewerBbox(vi, recenter, min, max); + } + +} + +void MainWindow::computeViewerBBox(CGAL::qglviewer::Vec& min, CGAL::qglviewer::Vec& max) +{ + const Scene::Bbox bbox = scene->visibleBbox(); + const Scene::Bbox all_bbox = scene->bbox(); const double xmin = bbox.xmin(); const double ymin = bbox.ymin(); const double zmin = bbox.zmin(); @@ -871,15 +892,26 @@ void MainWindow::updateViewerBBox(bool recenter = true) const double ymax = bbox.ymax(); const double zmax = bbox.zmax(); + const double axmin = all_bbox.xmin(); + const double aymin = all_bbox.ymin(); + const double azmin = all_bbox.zmin(); + const double axmax = all_bbox.xmax(); + const double aymax = all_bbox.ymax(); + const double azmax = all_bbox.zmax(); + + + + min = CGAL::qglviewer::Vec(xmin, ymin, zmin); + max= CGAL::qglviewer::Vec(xmax, ymax, zmax); + + CGAL::qglviewer::Vec abbox_center((axmin+axmax)/2, (aymin+aymax)/2, (azmin+azmax)/2), + bbox_center((xmin+xmax)/2, (ymin+ymax)/2, (zmin+zmax)/2); - CGAL::qglviewer::Vec - vec_min(xmin, ymin, zmin), - vec_max(xmax, ymax, zmax), - bbox_center((xmin+xmax)/2, (ymin+ymax)/2, (zmin+zmax)/2); CGAL::qglviewer::Vec offset(0,0,0); + double l_dist = (std::max)((std::abs)(bbox_center.x - viewer->offset().x), - (std::max)((std::abs)(bbox_center.y - viewer->offset().y), - (std::abs)(bbox_center.z - viewer->offset().z))); + (std::max)((std::abs)(bbox_center.y - viewer->offset().y), + (std::abs)(bbox_center.z - viewer->offset().z))); if((std::log2)(l_dist) > 13.0 ) for(int i=0; i<3; ++i) { @@ -888,25 +920,20 @@ void MainWindow::updateViewerBBox(bool recenter = true) } if(offset != viewer->offset()) { - viewer->setOffset(offset); + Q_FOREACH(CGAL::QGLViewer* v, CGAL::QGLViewer::QGLViewerPool()) + { + if(v == NULL) + continue; + Viewer* vi = qobject_cast(v); + vi->setOffset(offset); + } for(int i=0; inumberOfEntries(); ++i) { +// scene->item(i)->invalidate(Scene_item::GEOMETRY); scene->item(i)->invalidateOpenGLBuffers(); scene->item(i)->itemChanged(); } } - - - viewer->setSceneBoundingBox(vec_min, - vec_max); - if(recenter) - { - viewer->camera()->showEntireScene(); - } - else - { - viewer->camera()->setPivotPoint(center); - } } void MainWindow::reloadItem() { @@ -1238,31 +1265,36 @@ void MainWindow::selectionChanged() scene->setSelectedItemIndex(getSelectedSceneItemIndex()); scene->setSelectedItemsList(getSelectedSceneItemIndices()); CGAL::Three::Scene_item* item = scene->item(getSelectedSceneItemIndex()); - if(item != NULL && item->manipulatable()) { - viewer->setManipulatedFrame(item->manipulatedFrame()); - } else { - viewer->setManipulatedFrame(0); - } - if(viewer->manipulatedFrame() == 0) { - Q_FOREACH(CGAL::Three::Scene_item* item, scene->entries()) { - if(item->manipulatable() && item->manipulatedFrame() != 0) { - if(viewer->manipulatedFrame() != 0) { - // there are at least two possible frames - viewer->setManipulatedFrame(0); - break; - } else { - viewer->setManipulatedFrame(item->manipulatedFrame()); + Q_FOREACH(CGAL::QGLViewer* vi, CGAL::QGLViewer::QGLViewerPool()) + { + if(vi == NULL) + continue; + + if(item != NULL && item->manipulatable()) { + vi->setManipulatedFrame(item->manipulatedFrame()); + } else { + vi->setManipulatedFrame(0); + } + if(vi->manipulatedFrame() == 0) { + Q_FOREACH(CGAL::Three::Scene_item* item, scene->entries()) { + if(item->manipulatable() && item->manipulatedFrame() != 0) { + if(vi->manipulatedFrame() != 0) { + // there are at least two possible frames + vi->setManipulatedFrame(0); + break; + } else { + vi->setManipulatedFrame(item->manipulatedFrame()); + } } } } + if(vi->manipulatedFrame() != 0) { + connect(vi->manipulatedFrame(), SIGNAL(modified()), + this, SLOT(updateInfo())); + } + vi->update(); } - if(viewer->manipulatedFrame() != 0) { - connect(viewer->manipulatedFrame(), SIGNAL(modified()), - this, SLOT(updateInfo())); - } - viewer->update(); } - void MainWindow::contextMenuRequested(const QPoint& global_pos) { int index = scene->mainSelectionIndex(); showSceneContextMenu(index, global_pos); @@ -1958,10 +1990,16 @@ void MainWindow::on_actionPreferences_triggered() void MainWindow::setBackgroundColor() { QColor c = QColorDialog::getColor(); - if(c.isValid()) { - viewer->setBackgroundColor(c); - viewer->update(); - } + if(c.isValid()) { + Q_FOREACH(CGAL::QGLViewer* v, CGAL::QGLViewer::QGLViewerPool()) + { + if(v == NULL) + continue; + v->setBackgroundColor(c); + v->update(); + } + } + } void MainWindow::setLighting_triggered() @@ -1977,7 +2015,8 @@ void MainWindow::on_actionLookAt_triggered() if( i == QDialog::Accepted && dialog.has_correct_coordinates() ) { - viewerShow((float)dialog.get_x()+viewer->offset().x, + viewerShow(viewer, + (float)dialog.get_x()+viewer->offset().x, (float)dialog.get_y()+viewer->offset().y, (float)dialog.get_z()+viewer->offset().z); } @@ -1999,7 +2038,7 @@ void MainWindow::viewerShowObject() max.x, max.y, max.z); } } - +/* to check QString MainWindow::cameraString() const { const CGAL::qglviewer::Vec pos = viewer->camera()->position() - viewer->offset(); @@ -2013,21 +2052,26 @@ QString MainWindow::cameraString() const .arg(q[1]) .arg(q[2]) .arg(q[3]); +}*/ +QString MainWindow::cameraString(CGAL::Three::Viewer_interface* v) const +{ + return v->dumpCameraCoordinates(); } void MainWindow::on_actionDumpCamera_triggered() { //remove offset information(QString("Camera: %1") - .arg(cameraString())); + .arg(cameraString(viewer))); } void MainWindow::on_actionCopyCamera_triggered() { //remove offset - qApp->clipboard()->setText(this->cameraString()); + qApp->clipboard()->setText(this->cameraString(viewer)); } +/* to check void MainWindow::on_actionPasteCamera_triggered() { //add offset @@ -2044,6 +2088,11 @@ void MainWindow::on_actionPasteCamera_triggered() for(int i=0; i<7; ++i) s.append(new_s[i]).append(" "); viewer->moveCameraToCoordinates(s, 0.5f); +}*/ +void MainWindow::on_actionPasteCamera_triggered() +{ + QString s = qApp->clipboard()->text(); + viewer->moveCameraToCoordinates(s, 0.5f); } void MainWindow::setAddKeyFrameKeyboardModifiers(::Qt::KeyboardModifiers m) @@ -2053,8 +2102,17 @@ void MainWindow::setAddKeyFrameKeyboardModifiers(::Qt::KeyboardModifiers m) void MainWindow::on_actionRecenterScene_triggered() { - updateViewerBBox(); - viewer->camera()->interpolateToFitScene(); + scene->computeBbox(); + scene->computeVisibleBbox(); + CGAL::qglviewer::Vec min, max; + computeViewerBBox(min, max); + Q_FOREACH(CGAL::QGLViewer* v, CGAL::QGLViewer::QGLViewerPool()) + { + if(v == NULL) + continue; + updateViewerBbox(static_cast(v), true, min, max); + v->camera()->interpolateToFitScene(); + } } void MainWindow::on_actionLoadPlugin_triggered() @@ -2368,6 +2426,7 @@ void MainWindow::propagate_action() } } } + void MainWindow::setTransparencyPasses(int val) { viewer->setTotalPass(val); @@ -2406,3 +2465,271 @@ void MainWindow::setDefaultSaveDir() QSettings settings; settings.setValue("default_saveas_dir", def_save_dir); } +void MainWindow::setupViewer(Viewer* viewer, SubViewer* subviewer=NULL) +{ + // do not save the state of the viewer (anoying) + viewer->setStateFileName(QString::null); + viewer->textRenderer()->setScene(scene); + viewer->setScene(scene); + connect(scene, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex & )), + viewer, SLOT(update())); + connect(scene, SIGNAL(updated()), + viewer, SLOT(update())); + + if(subviewer == NULL) + { + connect(ui->actionRecenterScene, SIGNAL(triggered()), + viewer, SLOT(update())); + + connect(ui->actionRecenterScene, SIGNAL(triggered()), + this, SLOT(on_actionRecenterScene_triggered())); + connect(ui->actionLookAt, SIGNAL(triggered()), + this, SLOT(on_actionLookAt_triggered())); + connect(ui->actionSetBackgroundColor, SIGNAL(triggered()), + this, SLOT(on_actionSetBackgroundColor_triggered())); + connect(ui->actionDumpCamera, SIGNAL(triggered()), + this, SLOT(on_actionDumpCamera_triggered())); + connect(ui->actionCopyCamera, SIGNAL(triggered()), + this, SLOT(on_actionCopyCamera_triggered())); + connect(ui->actionPasteCamera, SIGNAL(triggered()), + this, SLOT(on_actionPasteCamera_triggered())); + connect(ui->actionAntiAliasing, SIGNAL(toggled(bool)), + viewer, SLOT(setAntiAliasing(bool))); + connect(ui->actionDrawTwoSides, SIGNAL(toggled(bool)), + viewer, SLOT(setTwoSides(bool))); + connect(ui->actionQuickCameraMode, SIGNAL(toggled(bool)), + viewer, SLOT(setFastDrawing(bool))); + connect(ui->actionSwitchProjection, SIGNAL(toggled(bool)), + viewer, SLOT(SetOrthoProjection(bool))); + connect(ui->actionSet_Transparency_Pass_Number, SIGNAL(triggered()), + viewer, SLOT(setTotalPass_clicked())); + } + else + { + QAction* action = subviewer->findChild("actionRecenter"); + connect(action, SIGNAL(triggered()), + viewer, SLOT(update())); + connect(action, &QAction::triggered, + subviewer, &SubViewer::recenter); + action= subviewer->findChild("actionLookat"); + connect(action, SIGNAL(triggered()), + subviewer, SLOT(lookat())); + action= subviewer->findChild("actionColor"); + connect(action, &QAction::triggered, + subviewer, &SubViewer::color); + action= subviewer->findChild("actionDumpCamera"); + connect(action, &QAction::triggered, + [this, viewer](){ + information(QString("Camera: %1") + .arg(cameraString(viewer))); + }); + action= subviewer->findChild("actionCopyCamera"); + connect(action, &QAction::triggered, + [this, viewer](){ + qApp->clipboard()->setText(cameraString(viewer)); + }); + action= subviewer->findChild("actionPasteCamera"); + connect(action, &QAction::triggered, + this, [viewer](){ + QString s = qApp->clipboard()->text(); + viewer->moveCameraToCoordinates(s, 0.5f); + }); + action= subviewer->findChild("actionAntiAliasing"); + connect(action, SIGNAL(toggled(bool)), + viewer, SLOT(setAntiAliasing(bool))); + action= subviewer->findChild("actionDrawTwoSide"); + connect(action, SIGNAL(toggled(bool)), + viewer, SLOT(setTwoSides(bool))); + action= subviewer->findChild("actionQuick"); + connect(action, SIGNAL(toggled(bool)), + viewer, SLOT(setFastDrawing(bool))); + action= subviewer->findChild("actionOrtho"); + connect(action, SIGNAL(toggled(bool)), + viewer, SLOT(SetOrthoProjection(bool))); + action= subviewer->findChild("actionTotalPass"); + connect(action, &QAction::triggered, + viewer, &Viewer::setTotalPass_clicked); + + } + + + connect(viewer, SIGNAL(requestContextMenu(QPoint)), + this, SLOT(contextMenuRequested(QPoint))); + connect(viewer, SIGNAL(selected(int)), + this, SLOT(selectSceneItem(int))); + connect(viewer, SIGNAL(selectedPoint(double, double, double)), + this, SLOT(showSelectedPoint(double, double, double))); + + connect(viewer, SIGNAL(selectionRay(double, double, double, + double, double, double)), + scene, SIGNAL(selectionRay(double, double, double, + double, double, double))); + + connect(viewer, SIGNAL(sendMessage(QString)), + this, SLOT(information(QString))); + +} + +void MainWindow::on_actionAdd_Viewer_triggered() +{ + Viewer *viewer2 = new Viewer(ui->centralwidget, viewer); + viewer2->setManipulatedFrame(viewer->manipulatedFrame()); + CGAL::qglviewer::Vec min, max; + computeViewerBBox(min, max); + updateViewerBbox(viewer2, true, min, max); + viewer2->camera()->interpolateToFitScene(); + viewer2->setObjectName("viewer2"); + connect(viewer2, SIGNAL(doneInitGL(CGAL::Three::Viewer_interface*)), + scene, SLOT(newViewer(CGAL::Three::Viewer_interface*))); + SubViewer* sub_viewer = new SubViewer(this, viewer2); + ui->viewerLayout->addWidget(sub_viewer); + setupViewer(viewer2, sub_viewer); + connect(sub_viewer->ui->exitButton, &QPushButton::clicked, + [this, sub_viewer](){ + scene->removeViewer(sub_viewer->viewer); + sub_viewer->deleteLater();}); + +} + +void MainWindow::recenterViewer() +{ + scene->computeBbox(); + scene->computeVisibleBbox(); + CGAL::qglviewer::Vec min, max; + computeViewerBBox(min, max); + Viewer* target = qobject_cast(childAt(cursor().pos())); + if(target) + { + scene->computeBbox(); + updateViewerBbox(target, true, min, max); + target->camera()->interpolateToFitScene(); + } +} + +void MainWindow::updateViewerBbox(Viewer *vi, bool recenter, + CGAL::qglviewer::Vec min, + CGAL::qglviewer::Vec max){ + + CGAL::qglviewer::Vec center = viewer->camera()->pivotPoint(); + vi->setSceneBoundingBox(min, + max); + if(recenter) + { + vi->resetFov(); + vi->camera()->showEntireScene(); + } + else + { + vi->camera()->setPivotPoint(center); + } +} + +QObject* MainWindow::getDirectChild(QObject* widget) +{ + + if(!widget->property("helpText").toString().isEmpty()) + return widget; + return getDirectChild(widget->parent()); +} + +SubViewer::SubViewer(MainWindow* mw, Viewer* viewer) + :QWidget(mw), + mw(mw), + viewer(viewer), + viewMenu(new QMenu(this)) +{ + ui = new Ui::SubViewer; + ui->setupUi(this); + ui->mainLayout->addWidget(viewer, 1); + ui->menuButton->setMenu(viewMenu); + ui->menuButton->setProperty("helpText", QString("This is the view menu for this Viewer. \n" + "It holds independant display options.")); + ui->exitButton->setProperty("helpText", QString("Click here to close this Viewer.")); + + + QAction* actionRecenter = new QAction("Re¢er Scene",this); + actionRecenter->setObjectName("actionRecenter"); + viewMenu->addAction(actionRecenter); + QAction* actionLookat = new QAction("&Look at...",this); + actionLookat->setObjectName("actionLookat"); + viewMenu->addAction(actionLookat); + QAction* actionColor = new QAction("Change &Background Color...",this); + actionColor->setObjectName("actionColor"); + viewMenu->addAction(actionColor); + QAction* actionDumpCamera = new QAction("&Dump Camera Coordinates",this); + actionDumpCamera->setObjectName("actionDumpCamera"); + QAction* actionCopyCamera = new QAction("&Copy Camera",this); + actionCopyCamera->setObjectName("actionCopyCamera"); + QAction* actionPasteCamera = new QAction("&Paste Camera",this); + actionPasteCamera->setObjectName("actionPasteCamera"); + QMenu* cameraMenu = new QMenu("Camera", mw); + cameraMenu->addAction(actionDumpCamera); + cameraMenu->addAction(actionCopyCamera); + cameraMenu->addAction(actionPasteCamera); + viewMenu->addMenu(cameraMenu); + + QAction* actionAntiAliasing = new QAction("&Antialiasing",this); + actionAntiAliasing->setObjectName("actionAntiAliasing"); + actionAntiAliasing->setCheckable(true); + actionAntiAliasing->setChecked(false); + viewMenu->addAction(actionAntiAliasing); + QAction* actionDrawTwoSide = new QAction("Draw &Two Sides",this); + actionDrawTwoSide->setObjectName("actionDrawTwoSide"); + actionDrawTwoSide->setCheckable(true); + actionDrawTwoSide->setChecked(false); + viewMenu->addAction(actionDrawTwoSide); + QAction* actionQuick = new QAction("Quick Camera Mode",this); + actionQuick->setObjectName("actionQuick"); + actionQuick->setCheckable(true); + actionQuick->setChecked(true); + viewMenu->addAction(actionQuick); + QAction* actionOrtho = new QAction("Orthographic Projection",this); + actionOrtho->setObjectName("actionOrtho"); + actionOrtho->setCheckable(true); + actionOrtho->setChecked(false); + viewMenu->addAction(actionOrtho); + QAction* actionLight = new QAction("L&ighting...",this); + actionLight->setObjectName("actionLight"); + viewMenu->addAction(actionLight); + QAction* actionTotalPass = new QAction("Set Transparency Pass &Number...",this); + actionTotalPass->setObjectName("actionTotalPass"); + viewMenu->addAction(actionTotalPass); +} + +SubViewer::~SubViewer() +{ + delete ui; + viewer->deleteLater(); +} + +void SubViewer::recenter() +{ + CGAL::qglviewer::Vec min, max; + mw->computeViewerBBox(min, max); + mw->updateViewerBbox(viewer, true, min, max); + viewer->camera()->interpolateToFitScene(); +} + +void SubViewer::lookat() +{ + Show_point_dialog dialog(mw); + dialog.setWindowTitle(tr("Look at...")); + int i = dialog.exec(); + if( i == QDialog::Accepted && + dialog.has_correct_coordinates() ) + { + mw->viewerShow(viewer, + (float)dialog.get_x(), + (float)dialog.get_y(), + (float)dialog.get_z()); + } +} + +void SubViewer::color() +{ + QColor c = QColorDialog::getColor(); + if(c.isValid()) { + viewer->setBackgroundColor(c); + viewer->update(); + } +} diff --git a/Polyhedron/demo/Polyhedron/MainWindow.h b/Polyhedron/demo/Polyhedron/MainWindow.h index a3be3f9ab87..cb3245f87c5 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.h +++ b/Polyhedron/demo/Polyhedron/MainWindow.h @@ -19,6 +19,7 @@ #include class Scene; class Viewer; +struct SubViewer; class QTreeView; class QMenu; namespace CGAL { @@ -26,6 +27,10 @@ namespace Three{ class Polyhedron_demo_io_plugin_interface; class Polyhedron_demo_plugin_interface; class Scene_item; +class Viewer_interface; +} +namespace qglviewer{ +class Vec; } } @@ -33,6 +38,7 @@ class QSortFilterProxyModel; namespace Ui { class MainWindow; + class SubViewer; class Statistics_on_item_dialog; } @@ -81,7 +87,7 @@ public: * throws `std::logic_error` if loading does not succeed or * `std::invalid_argument` if `fileinfo` specifies an invalid file*/ CGAL::Three::Scene_item* loadItem(QFileInfo fileinfo, CGAL::Three::Polyhedron_demo_io_plugin_interface*); - + Q_SIGNALS: //! Is emitted when the Application is closed. void on_closure(); @@ -96,7 +102,7 @@ public Q_SLOTS: void makeNewGroup(); //! Re-computes the viewer's Bbox //! If `b` is true, recenters the scene. - void updateViewerBBox(bool b); + void updateViewersBboxes(bool recenter); //! Opens a script or a file with the default loader if there is. void open(QString); //! Is called when the up button is pressed. @@ -193,21 +199,21 @@ public Q_SLOTS: void addAction(QString actionName, QString actionText, QString menuName); - /*! - * Sets the scene center to the target position and makes the - * scene slide to this new center. Also sets the pivotPoint of - * the camera to this position. - */ - void viewerShow(float, float, float); - /*! - * Sets the scene center to be the center of the target BBox. - * Also sets the pivotPoint of the camera to this position. - */ - void viewerShow(float, float, float, float, float, float); - /*! - * Centers the scene on the target object. - */ - void viewerShowObject(); + + /*! Sets the scene center to the target position and makes the + * scene slide to this new center. Also sets the pivotPoint of + * the camera to this position. + */ + void viewerShow(CGAL::Three::Viewer_interface *viewer, float, float, float); + /*! + * Sets the scene center to be the center of the target BBox. + * Also sets the pivotPoint of the camera to this position. + */ + void viewerShow(float, float, float, float, float, float); + /*! + * Centers the scene on the target object. + */ + void viewerShowObject(); /*! * Displays a text preceded by the mention "INFO :". */ @@ -335,7 +341,7 @@ protected Q_SLOTS: */ void on_actionLookAt_triggered(); //!Returns the position and orientation of the current camera frame. - QString cameraString() const; + QString cameraString(CGAL::Three::Viewer_interface *v) const; /*! Prints the position and orientation of the current camera frame. * @see cameraString() */ @@ -383,7 +389,9 @@ protected: //! Returns a list of the selected items in the Geometric Objects view. QList getSelectedSceneItemIndices() const; private: + QObject* getDirectChild(QObject* widget); void updateMenus(); + void setupViewer(Viewer* viewer, SubViewer *subviewer); bool load_plugin(QString names, bool blacklisted); void recurseExpand(QModelIndex index); QMap menu_map; @@ -438,6 +446,29 @@ private: QLineEdit operationSearchBar; QWidgetAction* searchAction; QString def_save_dir; + void computeViewerBBox(CGAL::qglviewer::Vec &min, CGAL::qglviewer::Vec &max); + void updateViewerBbox(Viewer* vi, bool recenter, CGAL::qglviewer::Vec min, + CGAL::qglviewer::Vec max); + +private Q_SLOTS: + void on_actionAdd_Viewer_triggered(); + void recenterViewer(); }; + +struct SubViewer : public QWidget +{ + Q_OBJECT +public: + MainWindow* mw; + Viewer* viewer; + Ui::SubViewer* ui; + QMenu* viewMenu; + SubViewer(MainWindow* mw, Viewer* viewer); + ~SubViewer(); +public Q_SLOTS: + void recenter(); + void lookat(); + void color(); +}; #endif // ifndef MAINWINDOW_H diff --git a/Polyhedron/demo/Polyhedron/MainWindow.ui b/Polyhedron/demo/Polyhedron/MainWindow.ui index 5065f1d63cc..c7d3c056f3b 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.ui +++ b/Polyhedron/demo/Polyhedron/MainWindow.ui @@ -20,14 +20,18 @@ - - - - 0 - 1 - - - + + + + + + 0 + 1 + + + + + @@ -95,6 +99,7 @@ + @@ -492,12 +497,18 @@ Set Different Colors for Selected Items + + + Add &Viewer + + Viewer QWidget
Viewer.h
+ 1
diff --git a/Polyhedron/demo/Polyhedron/Scene.cpp b/Polyhedron/demo/Polyhedron/Scene.cpp index 7e4e0fcf240..a1bdef72667 100644 --- a/Polyhedron/demo/Polyhedron/Scene.cpp +++ b/Polyhedron/demo/Polyhedron/Scene.cpp @@ -435,10 +435,10 @@ void Scene::initializeGL(CGAL::Three::Viewer_interface* viewer) vbo[1].create(); viewer->makeCurrent(); - vao = new QOpenGLVertexArrayObject(); - vao->create(); + vaos[viewer] = new QOpenGLVertexArrayObject(); + vaos[viewer]->create(); program.bind(); - vao->bind(); + vaos[viewer]->bind(); vbo[0].bind(); vbo[0].allocate(points, 18 * sizeof(float)); program.enableAttributeArray("vertex"); @@ -450,7 +450,7 @@ void Scene::initializeGL(CGAL::Three::Viewer_interface* viewer) program.enableAttributeArray("v_texCoord"); program.setAttributeArray("v_texCoord", GL_FLOAT, 0, 2); vbo[1].release(); - vao->release(); + vaos[viewer]->release(); program.release(); gl_init = true; } @@ -778,7 +778,7 @@ Scene::draw_aux(bool with_names, CGAL::Three::Viewer_interface* viewer) //blending program.bind(); - vao->bind(); + vaos[viewer]->bind(); viewer->glClearColor(background.redF(), background.greenF(), background.blueF(), @@ -802,7 +802,7 @@ Scene::draw_aux(bool with_names, CGAL::Three::Viewer_interface* viewer) } viewer->glDisable(GL_BLEND); viewer->glEnable(GL_DEPTH_TEST); - vao->release(); + vaos[viewer]->release(); program.release(); } @@ -1201,6 +1201,7 @@ void Scene::itemVisibilityChanged(CGAL::Three::Scene_item* item) && !item->isEmpty()) { //does not recenter + computeVisibleBbox(); Q_EMIT updated_bbox(false); } } @@ -1662,3 +1663,75 @@ void Scene::adjustIds(Item_id removed_id) m_entries[i]->setId(i-1);//the signal is emitted before m_entries is amputed from the item, so new id is current id -1. } } + +void Scene::computeVisibleBbox() +{ + if(m_entries.empty()) + { + last_visible_bbox = Bbox(0,0,0,0,0,0); + return; + } + + bool bbox_initialized = false; + Bbox bbox = Bbox(0,0,0,0,0,0); + Q_FOREACH(CGAL::Three::Scene_item* item, m_entries) + { + if(item->isFinite() && !item->isEmpty() && item->visible()) { + if(bbox_initialized) { + + bbox = bbox + item->bbox(); + } + else { + bbox = item->bbox(); + bbox_initialized = true; + + } + } + + } + last_visible_bbox = bbox; +} + +void Scene::computeBbox() +{ + if(m_entries.empty()) + { + last_bbox = Bbox(0,0,0,0,0,0); + return; + } + + bool bbox_initialized = false; + Bbox bbox = Bbox(0,0,0,0,0,0); + Q_FOREACH(CGAL::Three::Scene_item* item, m_entries) + { + if(item->isFinite() && !item->isEmpty() ) { + if(bbox_initialized) { + + bbox = bbox + item->bbox(); + } + else { + bbox = item->bbox(); + bbox_initialized = true; + + } + } + + } + last_bbox = bbox; +} + +void Scene::removeViewer(Viewer_interface *viewer) +{ + vaos[viewer]->destroy(); + vaos[viewer]->deleteLater(); + vaos.remove(viewer); + Q_FOREACH(Scene_item* item, m_entries) + { + item->removeViewer(viewer); + } +} + +Scene::Bbox Scene::visibleBbox() const +{ + return last_visible_bbox; +} diff --git a/Polyhedron/demo/Polyhedron/Scene.h b/Polyhedron/demo/Polyhedron/Scene.h index aa778970fb7..ca862d87539 100644 --- a/Polyhedron/demo/Polyhedron/Scene.h +++ b/Polyhedron/demo/Polyhedron/Scene.h @@ -93,6 +93,9 @@ public: void updatePrimitiveIds(Viewer_interface *, Scene_item *item) Q_DECL_OVERRIDE; bool testDisplayId(double x, double y, double z, CGAL::Three::Viewer_interface* viewer) Q_DECL_OVERRIDE; Bbox bbox() const Q_DECL_OVERRIDE; + Bbox visibleBbox() const ; + void computeBbox(); + void computeVisibleBbox(); double len_diagonal() const Q_DECL_OVERRIDE { Bbox box = bbox(); @@ -278,9 +281,12 @@ private: float points[18]; float uvs[12]; QOpenGLShaderProgram program; - QOpenGLVertexArrayObject* vao; + QMap vaos; mutable QOpenGLBuffer vbo[2]; - + Bbox last_bbox; + Bbox last_visible_bbox; +public: + void removeViewer(CGAL::Three::Viewer_interface*); }; // end class Scene class QAbstractProxyModel; @@ -316,6 +322,7 @@ private: QAbstractProxyModel *proxy; Scene *scene; mutable int size; + }; // end class SceneDelegate #endif // SCENE_H diff --git a/Polyhedron/demo/Polyhedron/Scene_group_item.cpp b/Polyhedron/demo/Polyhedron/Scene_group_item.cpp index 0a3c31f6653..34be29ac0fc 100644 --- a/Polyhedron/demo/Polyhedron/Scene_group_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_group_item.cpp @@ -15,8 +15,7 @@ Scene_group_item::Scene_group_item(QString name, int nb_vbos, int nb_vaos ) bool Scene_group_item::isFinite() const { Q_FOREACH(Scene_interface::Item_id id, children) - if(!getChild(id)->isFinite()){ - return false; + if(!getChild(id)->isFinite()){ return false; } return true; } @@ -246,3 +245,5 @@ void Scene_group_item::setAlpha(int ) } } +void Scene_group_item::removeViewer(CGAL::Three::Viewer_interface*) +{} diff --git a/Polyhedron/demo/Polyhedron/Scene_item_rendering_helper.cpp b/Polyhedron/demo/Polyhedron/Scene_item_rendering_helper.cpp index c4b6e12b0e3..05101473627 100644 --- a/Polyhedron/demo/Polyhedron/Scene_item_rendering_helper.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_item_rendering_helper.cpp @@ -242,3 +242,19 @@ void Scene_item_rendering_helper::setBuffersInit(Viewer_interface* viewer, bool { priv->buffers_init[viewer] = val; } + +void Scene_item_rendering_helper::removeViewer(Viewer_interface *viewer) +{ + Q_FOREACH(Triangle_container* tc, priv->triangle_containers) + { + tc->removeViewer(viewer); + } + Q_FOREACH(Edge_container* ec, priv->edge_containers) + { + ec->removeViewer(viewer); + } + Q_FOREACH(Point_container* pc, priv->point_containers) + { + pc->removeViewer(viewer); + } +} diff --git a/Polyhedron/demo/Polyhedron/Scene_polygon_soup_item.h b/Polyhedron/demo/Polyhedron/Scene_polygon_soup_item.h index f2deb9fadf7..e422b126c6d 100644 --- a/Polyhedron/demo/Polyhedron/Scene_polygon_soup_item.h +++ b/Polyhedron/demo/Polyhedron/Scene_polygon_soup_item.h @@ -152,6 +152,7 @@ public: const Polygons& polygons() const; const Edges& non_manifold_edges() const; + void removeViewer(CGAL::Three::Viewer_interface*)Q_DECL_OVERRIDE{} public Q_SLOTS: void shuffle_orientations(); bool orient(); diff --git a/Polyhedron/demo/Polyhedron/SubViewer.ui b/Polyhedron/demo/Polyhedron/SubViewer.ui new file mode 100644 index 00000000000..9a7104eef15 --- /dev/null +++ b/Polyhedron/demo/Polyhedron/SubViewer.ui @@ -0,0 +1,88 @@ + + + SubViewer + + + + 0 + 0 + 400 + 240 + + + + Form + + + + + + + + + + Qt::Horizontal + + + + 40 + 10 + + + + + + + + + + + + :/cgal/icons/menu:/cgal/icons/menu + + + + 10 + 10 + + + + false + + + true + + + + + + + + + + + :/cgal/icons/exit:/cgal/icons/exit + + + + 10 + 10 + + + + true + + + + + + + + + + + + + + + diff --git a/Polyhedron/demo/Polyhedron/Viewer.cpp b/Polyhedron/demo/Polyhedron/Viewer.cpp index cd27d55bda8..ca4d15b60b7 100644 --- a/Polyhedron/demo/Polyhedron/Viewer.cpp +++ b/Polyhedron/demo/Polyhedron/Viewer.cpp @@ -23,12 +23,13 @@ #include #include #endif - +#define ORIGINAL_FOV 0.94853805396568136 class Viewer_impl { public: CGAL::Three::Scene_draw_interface* scene; Viewer *viewer; + Viewer *shareViewer; bool antialiasing; bool twosides; bool macro_mode; @@ -97,9 +98,13 @@ public: void clearDistancedisplay(); void draw_aux(bool with_names, Viewer*); //! Contains all the programs for the item rendering. - mutable std::vector shader_programs; + static std::vector shader_programs; QMatrix4x4 projectionMatrix; void sendSnapshotToClipboard(Viewer*); + std::vector& shaderPrograms() + { + return shader_programs; + } }; class LightingDialog : @@ -211,10 +216,10 @@ private: QColorDialog spec_dial; }; -Viewer::Viewer(QWidget* parent, bool antialiasing) - : CGAL::Three::Viewer_interface(parent) +std::vector Viewer_impl::shader_programs = + std::vector(Viewer::NB_OF_PROGRAMS); +void Viewer::doBindings() { - d = new Viewer_impl; QSettings viewer_settings; // enable anti-aliasing QString cam_pos = viewer_settings.value("cam_pos", QString("0.0,0.0,1.0")).toString(); @@ -245,7 +250,6 @@ Viewer::Viewer(QWidget* parent, bool antialiasing) d->scene = 0; d->projection_is_ortho = false; d->initialized = false; - d->antialiasing = antialiasing; d->twosides = false; this->setProperty("draw_two_sides", false); d->macro_mode = false; @@ -306,6 +310,32 @@ Viewer::Viewer(QWidget* parent, bool antialiasing) setTextIsEnabled(true); } +Viewer::Viewer(QWidget* parent, bool antialiasing) + : CGAL::Three::Viewer_interface(parent) +{ + d = new Viewer_impl; + d->antialiasing = antialiasing; + doBindings(); +} + +Viewer::Viewer(QWidget* parent, + Viewer* sharedWidget, + bool antialiasing) + : CGAL::Three::Viewer_interface(parent, sharedWidget) +{ + d = new Viewer_impl; + d->viewer = this; + d->shareViewer = sharedWidget; + is_sharing = true; + d->antialiasing = antialiasing; + this->setProperty("draw_two_sides", false); + this->setProperty("helpText", QString("This is a sub-viewer. It displays the scene " + "from another point of view. \n ")); + is_ogl_4_3 = sharedWidget->is_ogl_4_3; + d->_recentFunctions = sharedWidget->d->_recentFunctions; + doBindings(); +} + Viewer::~Viewer() { QSettings viewer_settings; @@ -1639,5 +1669,10 @@ void Viewer::setGlPointSize(const GLfloat &p) { d->gl_point_size = p; } const GLfloat& Viewer::getGlPointSize() const { return d->gl_point_size; } +void Viewer::resetFov() +{ + camera()->setHorizontalFieldOfView(ORIGINAL_FOV); +} + #include "Viewer.moc" diff --git a/Polyhedron/demo/Polyhedron/Viewer.h b/Polyhedron/demo/Polyhedron/Viewer.h index 19895e80ded..888b170dc2f 100644 --- a/Polyhedron/demo/Polyhedron/Viewer.h +++ b/Polyhedron/demo/Polyhedron/Viewer.h @@ -16,6 +16,10 @@ #include // forward declarations class QWidget; +class QMouseEvent; +class QKeyEvent; +class QContextMenuEvent; +class Viewer_impl; namespace CGAL{ namespace Three{ class Scene_draw_interface; @@ -34,6 +38,7 @@ class VIEWER_EXPORT Viewer : public CGAL::Three::Viewer_interface { public: Viewer(QWidget * parent, bool antialiasing = false); + Viewer(QWidget * parent, Viewer *sharedWidget, bool antialiasing = false); ~Viewer(); bool testDisplayId(double, double, double)Q_DECL_OVERRIDE; void updateIds(CGAL::Three::Scene_item *)Q_DECL_OVERRIDE; @@ -85,9 +90,10 @@ public: const QImage& staticImage() const Q_DECL_OVERRIDE; //!Set total number of depth peeling passes. void setTotalPass(int); - + void resetFov(); Q_SIGNALS: void sendMessage(QString); + void doneInitGL(CGAL::Three::Viewer_interface*); public Q_SLOTS: //! Sets the antialiasing to true or false. void setAntiAliasing(bool b) Q_DECL_OVERRIDE; @@ -122,6 +128,7 @@ public Q_SLOTS: void setLighting(); void messageLogged(QOpenGLDebugMessage); + void initializeGL()Q_DECL_OVERRIDE; protected: void paintEvent(QPaintEvent *)Q_DECL_OVERRIDE; @@ -142,6 +149,7 @@ protected: friend class Viewer_impl; Viewer_impl* d; double prev_radius; + void doBindings(); public: QOpenGLFunctions_4_3_Core* openGL_4_3_functions() Q_DECL_OVERRIDE; diff --git a/Three/include/CGAL/Three/Scene_group_item.h b/Three/include/CGAL/Three/Scene_group_item.h index c962d0642f7..7af8890d425 100644 --- a/Three/include/CGAL/Three/Scene_group_item.h +++ b/Three/include/CGAL/Three/Scene_group_item.h @@ -237,7 +237,7 @@ public : void moveUp(int); //!Moves a child down in the list. void moveDown(int); - + void removeViewer(CGAL::Three::Viewer_interface* )Q_DECL_OVERRIDE; public Q_SLOTS: //!\brief Redraws children. //! diff --git a/Three/include/CGAL/Three/Scene_item.h b/Three/include/CGAL/Three/Scene_item.h index 02e154cc92a..2ca17fd7898 100644 --- a/Three/include/CGAL/Three/Scene_item.h +++ b/Three/include/CGAL/Three/Scene_item.h @@ -301,6 +301,12 @@ public: //!Contains the number of group and subgroups containing this item. int has_group; + //! + //! \brief removeViewer removes the Vaos fo `viewer`. + //! + //! Must be overriden; + //! + virtual void removeViewer(CGAL::Three::Viewer_interface* viewer) = 0; public Q_SLOTS: diff --git a/Three/include/CGAL/Three/Scene_item_rendering_helper.h b/Three/include/CGAL/Three/Scene_item_rendering_helper.h index e8e729810ed..186cd10e63f 100644 --- a/Three/include/CGAL/Three/Scene_item_rendering_helper.h +++ b/Three/include/CGAL/Three/Scene_item_rendering_helper.h @@ -190,6 +190,9 @@ public: //! @returns the item's bounding box's diagonal length. //! @todo must replace the one from Scene_item eventually virtual double diagonalBbox() const Q_DECL_OVERRIDE; + //! \brief removeViewer removes the Vaos for `viewer`. + //! \param viewer the viewer to be removed. + void removeViewer(Viewer_interface *viewer) Q_DECL_OVERRIDE; protected: diff --git a/Three/include/CGAL/Three/Viewer_interface.h b/Three/include/CGAL/Three/Viewer_interface.h index 0c78e97c68b..0ae1ec09a92 100644 --- a/Three/include/CGAL/Three/Viewer_interface.h +++ b/Three/include/CGAL/Three/Viewer_interface.h @@ -107,6 +107,14 @@ public: //! Creates a valid context for OpenGL ES 2.0. //! \param parent the parent widget. It usually is the MainWindow. Viewer_interface(QWidget* parent) : CGAL::QGLViewer(parent) {} + //! + //! \brief Constructor for the secondary viewers. + //! + //! \param parent the parent widget. It usually is the MainWindow. + //! \param sharedWidget the main viewer of the Application. This will share the + //! context and allow synchronized rendering of multiple views. + //! + Viewer_interface(QWidget* parent, QWidget*) : QGLViewer(parent){} virtual ~Viewer_interface() {} //! \brief Sets the scene for the viewer.