From 8ede36c59d0c6abadd9eb90707046e8dcaed7dc4 Mon Sep 17 00:00:00 2001 From: Daniel Evans Date: Mon, 16 May 2016 00:06:51 +0100 Subject: [PATCH] Implement semi-functional world viewer widget --- rwviewer/ViewerWidget.cpp | 105 +++++++++++++++++++++-------- rwviewer/ViewerWidget.hpp | 12 ++-- rwviewer/ViewerWindow.cpp | 13 +++- rwviewer/ViewerWindow.hpp | 3 +- rwviewer/views/ViewerInterface.hpp | 38 +++++++++++ rwviewer/views/WorldViewer.cpp | 38 +++++++++++ rwviewer/views/WorldViewer.hpp | 33 +++++++++ 7 files changed, 204 insertions(+), 38 deletions(-) create mode 100644 rwviewer/views/ViewerInterface.hpp create mode 100644 rwviewer/views/WorldViewer.cpp create mode 100644 rwviewer/views/WorldViewer.hpp diff --git a/rwviewer/ViewerWidget.cpp b/rwviewer/ViewerWidget.cpp index 1a418b04..ee96988d 100644 --- a/rwviewer/ViewerWidget.cpp +++ b/rwviewer/ViewerWidget.cpp @@ -16,11 +16,21 @@ ViewerWidget::ViewerWidget(QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f) -: QGLWidget(parent, shareWidget, f), gworld(nullptr), activeModel(nullptr), - selectedFrame(nullptr), dummyObject(nullptr), currentObjectID(0), - _lastModel(nullptr), canimation(nullptr), viewDistance(1.f), dragging(false), - _frameWidgetDraw(nullptr), _frameWidgetGeom(nullptr) + : QGLWidget(parent, shareWidget, f) + , gworld(nullptr) + , activeModel(nullptr) + , selectedFrame(nullptr) + , dummyObject(nullptr) + , currentObjectID(0) + , _lastModel(nullptr) + , canimation(nullptr) + , viewDistance(1.f) + , dragging(false) + , moveFast(false) + , _frameWidgetDraw(nullptr) + , _frameWidgetGeom(nullptr) { + setFocusPolicy(Qt::StrongFocus); } struct WidgetVertex { @@ -75,7 +85,7 @@ void ViewerWidget::paintGL() glViewport(0, 0, width(), height()); - if( gworld == nullptr ) return; + if( world() == nullptr ) return; auto& r = *renderer; @@ -86,35 +96,36 @@ void ViewerWidget::paintGL() dummyObject->skeleton->interpolate(1.f); } - if(activeModel) { - gworld->_work->update(); + gworld->_work->update(); - r.getRenderer()->invalidate(); + r.getRenderer()->invalidate(); - Model* model = activeModel; + glEnable(GL_DEPTH_TEST); - if( model != _lastModel ) { - _lastModel = model; - emit modelChanged(_lastModel); - } + glm::mat4 m(1.f); - glEnable(GL_DEPTH_TEST); - - glm::mat4 m(1.f); + r.getRenderer()->useProgram(r.worldProg); - r.getRenderer()->useProgram(r.worldProg); + ViewCamera vc; - ViewCamera vc; + float viewFov = glm::radians(45.f); - float viewFov = glm::radians(45.f); + vc.frustum.far = 500.f; + vc.frustum.near = 0.1f; + vc.frustum.fov = viewFov; + vc.frustum.aspectRatio = width()/(height()*1.f); - vc.frustum.far = 500.f; - vc.frustum.near = 0.1f; - vc.frustum.fov = viewFov; - vc.frustum.aspectRatio = width()/(height()*1.f); + Model* model = activeModel; + if( model != _lastModel ) { + _lastModel = model; + emit modelChanged(_lastModel); + } + glm::vec3 eye(sin(viewAngles.x) * cos(viewAngles.y), cos(viewAngles.x) * cos(viewAngles.y), sin(viewAngles.y)); + + if( model ) + { glm::mat4 proj = vc.frustum.projection(); - glm::vec3 eye(sin(viewAngles.x) * cos(viewAngles.y), cos(viewAngles.x) * cos(viewAngles.y), sin(viewAngles.y)); glm::mat4 view = glm::lookAt(eye * viewDistance, glm::vec3(0.f, 0.f, 0.f), glm::vec3(0.f, 0.f, 1.f)); r.getRenderer()->setSceneParameters({ proj, view, glm::vec4(0.15f), glm::vec4(0.7f), glm::vec4(1.f), glm::vec4(0.f), 90.f, vc.frustum.far }); @@ -122,14 +133,21 @@ void ViewerWidget::paintGL() r.getRenderer()->invalidate(); r.setupRender(); - if( model ) - { - r.renderModel(model, m, dummyObject); - drawFrameWidget(model->frames[model->rootFrameIdx]); - } + r.renderModel(model, m, dummyObject); + + drawFrameWidget(model->frames[model->rootFrameIdx]); r.renderPostProcess(); } + else if (world()->allObjects.size() > 0) + { + vc.frustum.fov = glm::radians(90.f); + vc.frustum.far = 1000.f; + vc.position = viewPosition; + vc.rotation = glm::angleAxis(glm::half_pi() + viewAngles.x, glm::vec3(0.f, 0.f, 1.f)) + * glm::angleAxis(viewAngles.y, glm::vec3(0.f, 1.f, 0.f)); + r.renderWorld(world(), vc, 0.f); + } } void ViewerWidget::drawFrameWidget(ModelFrame* f, const glm::mat4& m) @@ -244,6 +262,35 @@ void ViewerWidget::setRenderer(GameRenderer *render) renderer = render; } +void ViewerWidget::keyPressEvent(QKeyEvent* e) +{ + if (e->key() == Qt::Key_Shift) + moveFast = true; + + glm::vec3 movement; + if (e->key() == Qt::Key_W) + movement.y += moveFast ? 10.f : 1.f; + if (e->key() == Qt::Key_S) + movement.y -= moveFast ? 10.f : 1.f; + if (e->key() == Qt::Key_A) + movement.x -= moveFast ? 10.f : 1.f; + if (e->key() == Qt::Key_D) + movement.x += moveFast? 10.f : 1.f; + + if (movement.length() > 0.f) + { + movement = (glm::angleAxis(viewAngles.x, glm::vec3(0.f, 0.f, 1.f)) + * glm::angleAxis(viewAngles.y, glm::vec3(-1.f, 0.f, 0.f))) * movement; + viewPosition += movement; + } +} + +void ViewerWidget::keyReleaseEvent(QKeyEvent* e) +{ + if (e->key() == Qt::Key_Shift) + moveFast = false; +} + Model* ViewerWidget::currentModel() const { return activeModel; diff --git a/rwviewer/ViewerWidget.hpp b/rwviewer/ViewerWidget.hpp index 46089470..9a423080 100644 --- a/rwviewer/ViewerWidget.hpp +++ b/rwviewer/ViewerWidget.hpp @@ -38,10 +38,12 @@ class ViewerWidget : public QGLWidget float viewDistance; glm::vec2 viewAngles; + glm::vec3 viewPosition; bool dragging; QPointF dstart; glm::vec2 dastart; + bool moveFast; DrawBuffer* _frameWidgetDraw; GeometryBuffer* _frameWidgetGeom; @@ -83,10 +85,12 @@ signals: protected: - virtual void mousePressEvent(QMouseEvent*); - virtual void mouseReleaseEvent(QMouseEvent*); - virtual void mouseMoveEvent(QMouseEvent*); - virtual void wheelEvent(QWheelEvent*); + void keyPressEvent(QKeyEvent*) override; + void keyReleaseEvent(QKeyEvent*) override; + void mousePressEvent(QMouseEvent*) override; + void mouseReleaseEvent(QMouseEvent*) override; + void mouseMoveEvent(QMouseEvent*) override; + void wheelEvent(QWheelEvent*) override; }; #endif diff --git a/rwviewer/ViewerWindow.cpp b/rwviewer/ViewerWindow.cpp index 2c1553cc..54a081c2 100644 --- a/rwviewer/ViewerWindow.cpp +++ b/rwviewer/ViewerWindow.cpp @@ -4,6 +4,7 @@ #include "views/WorldViewer.hpp" #include +#include #include #include @@ -57,11 +58,9 @@ ViewerWindow::ViewerWindow(QWidget* parent, Qt::WindowFlags flags) m_views[ViewMode::Model] = new ModelViewer(viewerWidget); m_viewNames[ViewMode::Model] = "Model"; -#if 0 //------------- World Viewer m_views[ViewMode::World] = new WorldViewer(viewerWidget); m_viewNames[ViewMode::World] = "World"; -#endif //------------- display mode switching viewSwitcher = new QStackedWidget; @@ -73,10 +72,14 @@ ViewerWindow::ViewerWindow(QWidget* parent, Qt::WindowFlags flags) connect(this, SIGNAL(loadedData(GameWorld*)), viewer, SLOT(showData(GameWorld*))); auto viewerButton = new QPushButton(m_viewNames[i].c_str()); - signalMapper->setMapping(viewerButton, i++); + signalMapper->setMapping(m_views[i], i); + signalMapper->setMapping(viewerButton, i); connect(viewerButton, SIGNAL(clicked()), signalMapper, SLOT(map())); switchPanel->addWidget(viewerButton); + i++; } + // Map world viewer loading placements to switch to the world viewer + connect(m_views[ViewMode::World], SIGNAL(placementsLoaded(QString)), signalMapper, SLOT(map())); switchView(ViewMode::Object); @@ -100,6 +103,9 @@ ViewerWindow::ViewerWindow(QWidget* parent, Qt::WindowFlags flags) QMenu* anim = mb->addMenu("&Animation"); anim->addAction("Load &Animations", this, SLOT(openAnimations())); + QMenu* map = mb->addMenu("&Map"); + map->addAction("Load IPL", m_views[ViewMode::World], SLOT(loadPlacements())); + this->setCentralWidget(mainwidget); updateRecentGames(); @@ -151,6 +157,7 @@ void ViewerWindow::loadGame(const QString &path) gameData = new GameData( &engineLog, &work, gameDir.absolutePath().toStdString() ); gameWorld = new GameWorld( &engineLog, &work, gameData ); renderer = new GameRenderer(&engineLog, gameData ); + gameWorld->state = new GameState; viewerWidget->setRenderer(renderer); gameWorld->data->load(); diff --git a/rwviewer/ViewerWindow.hpp b/rwviewer/ViewerWindow.hpp index 4ec7cef9..4c425678 100644 --- a/rwviewer/ViewerWindow.hpp +++ b/rwviewer/ViewerWindow.hpp @@ -23,9 +23,7 @@ class ViewerWindow : public QMainWindow enum ViewMode { Object = 0, Model = 1, -#if 0 World = 2, -#endif _Count }; @@ -35,6 +33,7 @@ class ViewerWindow : public QMainWindow GameData* gameData; GameWorld* gameWorld; GameRenderer* renderer; + GameState* state; /** Contains the OGL context */ ViewerWidget* viewerWidget; diff --git a/rwviewer/views/ViewerInterface.hpp b/rwviewer/views/ViewerInterface.hpp new file mode 100644 index 00000000..7e176b57 --- /dev/null +++ b/rwviewer/views/ViewerInterface.hpp @@ -0,0 +1,38 @@ +#ifndef _RWVIEWER_VIEWERINTERFACE_HPP_ +#define _RWVIEWER_VIEWERINTERFACE_HPP_ +#include + +#include + +#include + +class ViewerInterface : public QWidget +{ + Q_OBJECT +public: + ViewerInterface(QWidget* parent = 0, Qt::WindowFlags f = 0) + : QWidget(parent, f) + , m_world(nullptr) + { + + } + + virtual void setViewerWidget( ViewerWidget* widget ) = 0; + + GameWorld* world() { return m_world; } + +protected: + virtual void worldChanged() { } + +public slots: + void showData(GameWorld* world) + { + m_world = world; + worldChanged(); + } + +private: + GameWorld* m_world; +}; + +#endif diff --git a/rwviewer/views/WorldViewer.cpp b/rwviewer/views/WorldViewer.cpp new file mode 100644 index 00000000..8131647d --- /dev/null +++ b/rwviewer/views/WorldViewer.cpp @@ -0,0 +1,38 @@ +#include "WorldViewer.hpp" +#include "ViewerWidget.hpp" + +#include + +WorldViewer::WorldViewer(ViewerWidget* viewer, QWidget* parent, Qt::WindowFlags f) +: ViewerInterface(parent, f) +{ + mainLayout = new QVBoxLayout; + + viewerWidget = viewer; + viewerWidget->setMinimumSize(250,250); + + this->setLayout(mainLayout); +} + +void WorldViewer::setViewerWidget(ViewerWidget* widget) +{ + viewerWidget = widget; + // Clear the active model + widget->showModel(nullptr); + mainLayout->addWidget(viewerWidget); +} + +void WorldViewer::loadPlacements(const QString& file) +{ + world()->placeItems(file.toStdString()); + placementsLoaded(file); +} + +void WorldViewer::loadPlacements() +{ + QFileDialog dialog(this, "Open Placements", "", "Placement (*.ipl)"); + if(dialog.exec()) { + loadPlacements(dialog.selectedFiles()[0]); + } +} + diff --git a/rwviewer/views/WorldViewer.hpp b/rwviewer/views/WorldViewer.hpp new file mode 100644 index 00000000..918d6a40 --- /dev/null +++ b/rwviewer/views/WorldViewer.hpp @@ -0,0 +1,33 @@ +#ifndef _RWVIEWER_WORLDVIEWER_HPP_ +#define _RWVIEWER_WORLDVIEWER_HPP_ +#include +#include + +#include "ViewerInterface.hpp" + +#include +#include +#include +#include +#include + +class WorldViewer : public ViewerInterface +{ + Q_OBJECT + + QVBoxLayout* mainLayout; + ViewerWidget* viewerWidget; +public: + WorldViewer(ViewerWidget *viewer = 0, QWidget* parent = 0, Qt::WindowFlags f = 0); + + void setViewerWidget( ViewerWidget* widget ) override; + +signals: + void placementsLoaded(const QString& file); + +public slots: + void loadPlacements(const QString& file); + void loadPlacements(); +}; + +#endif