diff --git a/rwengine/include/render/GameRenderer.hpp b/rwengine/include/render/GameRenderer.hpp index 64c21422..05c41aef 100644 --- a/rwengine/include/render/GameRenderer.hpp +++ b/rwengine/include/render/GameRenderer.hpp @@ -183,6 +183,9 @@ public: /** Increases cinematic value */ void renderLetterbox(); + void setupRender(); + void renderPostProcess(); + Renderer* getRenderer() { return renderer; diff --git a/rwengine/src/render/GameRenderer.cpp b/rwengine/src/render/GameRenderer.cpp index 0cff80f9..7f8bf268 100644 --- a/rwengine/src/render/GameRenderer.cpp +++ b/rwengine/src/render/GameRenderer.cpp @@ -226,6 +226,15 @@ float mix(uint8_t a, uint8_t b, float num) return a+(b-a)*num; } +void GameRenderer::setupRender() +{ + // Set the viewport + const glm::ivec2& vp = getRenderer()->getViewport(); + glViewport(0, 0, vp.x, vp.y); + glBindFramebuffer(GL_FRAMEBUFFER, framebufferName); + glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT); +} + void GameRenderer::renderWorld(const ViewCamera &camera, float alpha) { _renderAlpha = alpha; @@ -233,11 +242,7 @@ void GameRenderer::renderWorld(const ViewCamera &camera, float alpha) // Store the input camera, _camera = camera; - // Set the viewport - const glm::ivec2& vp = getRenderer()->getViewport(); - glViewport(0, 0, vp.x, vp.y); - glBindFramebuffer(GL_FRAMEBUFFER, framebufferName); - glClear(GL_DEPTH_BUFFER_BIT); + setupRender(); glBindVertexArray( vao ); @@ -496,7 +501,17 @@ void GameRenderer::renderWorld(const ViewCamera &camera, float alpha) if( (engine->state.isCinematic || engine->state.currentCutscene ) && splashTexName == 0 ) { renderLetterbox(); } - + + renderPostProcess(); + + glUseProgram(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindVertexArray( 0 ); +} + +void GameRenderer::renderPostProcess() +{ glBindFramebuffer(GL_FRAMEBUFFER, 0); glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); @@ -508,11 +523,6 @@ void GameRenderer::renderWorld(const ViewCamera &camera, float alpha) wdp.textures = {fbTextures[0]}; renderer->drawArrays(glm::mat4(), &ssRectDraw, wdp); - - glUseProgram(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindVertexArray( 0 ); } void GameRenderer::renderPedestrian(CharacterObject *pedestrian) diff --git a/rwviewer/CMakeLists.txt b/rwviewer/CMakeLists.txt index 9c1edb76..d3f2c23a 100644 --- a/rwviewer/CMakeLists.txt +++ b/rwviewer/CMakeLists.txt @@ -6,16 +6,19 @@ find_package(Qt5Core REQUIRED) add_executable(rwviewer main.cpp ViewerWindow.cpp - ObjectViewer.cpp models/ObjectListModel.cpp + models/DFFFramesTreeModel.cpp + + + views/ObjectViewer.cpp + views/ModelViewer.cpp ViewerWidget.cpp ItemListModel.cpp ItemListWidget.cpp IMGArchiveModel.cpp - DFFFramesTreeModel.cpp - ModelFramesWidget.cpp + widgets/ModelFramesWidget.cpp AnimationListModel.cpp AnimationListWidget.cpp) diff --git a/rwviewer/ViewerWidget.cpp b/rwviewer/ViewerWidget.cpp index 99109a70..13a45429 100644 --- a/rwviewer/ViewerWidget.cpp +++ b/rwviewer/ViewerWidget.cpp @@ -1,5 +1,7 @@ #include "ViewerWidget.hpp" #include +#include +#include #include #include #include @@ -13,7 +15,7 @@ ViewerWidget::ViewerWidget(QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f) -: QGLWidget(parent, shareWidget, f), gworld(nullptr), dummyObject(nullptr), currentObjectID(0), +: QGLWidget(parent, shareWidget, f), gworld(nullptr), activeModel(nullptr), dummyObject(nullptr), currentObjectID(0), _lastModel(nullptr), canimation(nullptr), viewDistance(1.f), dragging(false), _frameWidgetDraw(nullptr), _frameWidgetGeom(nullptr) { @@ -66,25 +68,29 @@ void ViewerWidget::paintGL() if( gworld == nullptr ) return; - auto& r = gworld->renderer; + auto& r = *renderer; + + r.setViewport(width(), height()); if(dummyObject && dummyObject->animator) { dummyObject->animator->tick(1.f/60.f); } - if(dummyObject) { + if(activeModel) { gworld->_work->update(); r.getRenderer()->invalidate(); - if( dummyObject->model->model != _lastModel ) { - _lastModel = dummyObject->model->model; + Model* model = activeModel; + + if( model != _lastModel ) { + _lastModel = model; emit modelChanged(_lastModel); } glEnable(GL_DEPTH_TEST); - glm::mat4 m; + glm::mat4 m(1.f); r.getRenderer()->useProgram(r.worldProg); @@ -105,24 +111,31 @@ void ViewerWidget::paintGL() r.getRenderer()->invalidate(); - if( dummyObject->model->model ) { - gworld->renderer.renderModel(dummyObject->model->model, m, dummyObject); + r.setupRender(); + if( model ) { + r.renderModel(model, m, dummyObject); - drawFrameWidget(dummyObject->model->model->frames[dummyObject->model->model->rootFrameIdx]); + drawFrameWidget(model->frames[model->rootFrameIdx]); } + r.renderPostProcess(); } } void ViewerWidget::drawFrameWidget(ModelFrame* f, const glm::mat4& m) { auto thisM = m * f->getTransform(); - if(f->getGeometries().size() == 0) { - glBindTexture(GL_TEXTURE_2D, 0); - /*glUniform4f(gworld->renderer.uniCol, 1.f, 1.f, 1.f, 1.f); - glUniformMatrix4fv(gworld->renderer.uniModel, 1, GL_FALSE, glm::value_ptr(thisM));*/ - glBindVertexArray(_frameWidgetDraw->getVAOName()); - glDrawArrays(_frameWidgetDraw->getFaceType(), 0, 6); + if(f->getGeometries().size() == 0) + { + Renderer::DrawParameters dp; + dp.count = _frameWidgetGeom->getCount(); + dp.start = 0; + dp.ambient = 1.f; + dp.diffuse = 1.f; + dp.colour = {255, 255, 255, 255}; + dp.textures = { 0 }; + renderer->getRenderer()->drawArrays(thisM, _frameWidgetDraw, dp); } + for(auto c : f->getChildren()) { drawFrameWidget(c, thisM); } @@ -155,9 +168,18 @@ void ViewerWidget::showItem(qint16 item) { dummyObject = gworld->createVehicle(item, {}); } + activeModel = dummyObject->model->resource; } } +void ViewerWidget::showModel(Model* model) +{ + if( dummyObject ) gworld->destroyObject( dummyObject ); + dummyObject = nullptr; + activeModel = model; +} + + void ViewerWidget::exportModel() { QString toSv = QFileDialog::getSaveFileName(this, @@ -189,9 +211,14 @@ void ViewerWidget::dataLoaded(GameWorld *world) gworld = world; } +void ViewerWidget::setRenderer(GameRenderer *render) +{ + renderer = render; +} + Model* ViewerWidget::currentModel() const { - return _lastModel; + return activeModel; } void ViewerWidget::mousePressEvent(QMouseEvent* e) diff --git a/rwviewer/ViewerWidget.hpp b/rwviewer/ViewerWidget.hpp index 043c65d3..1841bbde 100644 --- a/rwviewer/ViewerWidget.hpp +++ b/rwviewer/ViewerWidget.hpp @@ -8,18 +8,23 @@ #include #include #include +#include #include +class GameRenderer; class Model; class ViewerWidget : public QGLWidget { Q_OBJECT + GameRenderer* renderer; + QString currentFile; QTimer timer; GameWorld* gworld; + Model* activeModel; GameObject* dummyObject; quint16 currentObjectID; @@ -35,7 +40,7 @@ class ViewerWidget : public QGLWidget DrawBuffer* _frameWidgetDraw; GeometryBuffer* _frameWidgetGeom; - void drawFrameWidget(ModelFrame* f, const glm::mat4& = {}); + void drawFrameWidget(ModelFrame* f, const glm::mat4& = glm::mat4(1.f)); public: ViewerWidget(QWidget* parent = 0, const QGLWidget* shareWidget = 0, Qt::WindowFlags f = 0); @@ -53,11 +58,14 @@ public: public slots: void showItem(qint16 item); + void showModel(Model* model); void exportModel(); void dataLoaded(GameWorld* world); + void setRenderer(GameRenderer* renderer); + signals: void fileOpened(const QString& file); diff --git a/rwviewer/ViewerWindow.cpp b/rwviewer/ViewerWindow.cpp index 8e87bbb5..ffc3b397 100644 --- a/rwviewer/ViewerWindow.cpp +++ b/rwviewer/ViewerWindow.cpp @@ -1,7 +1,9 @@ #include "ViewerWindow.hpp" -#include "ObjectViewer.hpp" +#include "views/ObjectViewer.hpp" +#include "views/ModelViewer.hpp" #include +#include #include #include #include @@ -14,7 +16,7 @@ static int MaxRecentGames = 5; ViewerWindow::ViewerWindow(QWidget* parent, Qt::WindowFlags flags) - : QMainWindow(parent, flags), gameWorld(nullptr) + : QMainWindow(parent, flags), gameWorld(nullptr), renderer(nullptr) { setMinimumSize(640, 480); @@ -47,8 +49,17 @@ ViewerWindow::ViewerWindow(QWidget* parent, Qt::WindowFlags flags) connect(this, SIGNAL(loadedData(GameWorld*)), objectViewer, SLOT(showData(GameWorld*))); connect(this, SIGNAL(loadedData(GameWorld*)), viewerWidget, SLOT(dataLoaded(GameWorld*))); + modelViewer = new ModelViewer(viewerWidget); + + connect(this, SIGNAL(loadedData(GameWorld*)), modelViewer, SLOT(showData(GameWorld*))); + viewSwitcher = new QStackedWidget; viewSwitcher->addWidget(objectViewer); + viewSwitcher->addWidget(modelViewer); + + connect(objectViewer, SIGNAL(modelChanged(Model*)), modelViewer, SLOT(showModel(Model*))); + + objectViewer->setViewerWidget( viewerWidget ); QMenu* view = mb->addMenu("&View"); QAction* objectAction = view->addAction("&Object"); @@ -66,13 +77,6 @@ ViewerWindow::ViewerWindow(QWidget* parent, Qt::WindowFlags flags) QMenu* anim = mb->addMenu("&Animation"); anim->addAction("Load &Animations", this, SLOT(openAnimations())); - modelLayout = new QVBoxLayout; - - QWidget* span = new QWidget; - span->setLayout(modelLayout); - - viewSwitcher->addWidget(span); - this->setCentralWidget(viewSwitcher); updateRecentGames(); @@ -144,8 +148,11 @@ void ViewerWindow::loadGame(const QString &path) QDir gameDir( path ); if( gameDir.exists() && path.size() > 0 ) { - gameWorld = new GameWorld( gameDir.absolutePath().toStdString() ); - gameWorld->load(); + gameWorld = new GameWorld( &engineLog, gameDir.absolutePath().toStdString() ); + renderer = new GameRenderer(&engineLog, gameWorld); + viewerWidget->setRenderer(renderer); + + gameWorld->gameData.load(); // Initalize all the archives. gameWorld->gameData.loadIMG("/models/gta3"); @@ -181,12 +188,11 @@ void ViewerWindow::switchWidget() if( index == 0 ) { - modelLayout->removeWidget( viewerWidget ); objectViewer->setViewerWidget( viewerWidget ); } else if( index == 1 ) { - modelLayout->addWidget( viewerWidget ); + modelViewer->setViewerWidget( viewerWidget ); } viewSwitcher->setCurrentIndex( index ); diff --git a/rwviewer/ViewerWindow.hpp b/rwviewer/ViewerWindow.hpp index 51429bfe..4f912a06 100644 --- a/rwviewer/ViewerWindow.hpp +++ b/rwviewer/ViewerWindow.hpp @@ -3,25 +3,30 @@ #define _VIEWERWINDOW_HPP_ #include #include +#include #include #include #include class ObjectViewer; +class ModelViewer; class ViewerWidget; +class GameRenderer; class ViewerWindow : public QMainWindow { Q_OBJECT - + + Logger engineLog; + GameWorld* gameWorld; + GameRenderer* renderer; /** Contains the OGL context */ ViewerWidget* viewerWidget; ObjectViewer* objectViewer; - - QVBoxLayout* modelLayout; + ModelViewer* modelViewer; QStackedWidget* viewSwitcher; diff --git a/rwviewer/DFFFramesTreeModel.cpp b/rwviewer/models/DFFFramesTreeModel.cpp similarity index 100% rename from rwviewer/DFFFramesTreeModel.cpp rename to rwviewer/models/DFFFramesTreeModel.cpp diff --git a/rwviewer/DFFFramesTreeModel.hpp b/rwviewer/models/DFFFramesTreeModel.hpp similarity index 98% rename from rwviewer/DFFFramesTreeModel.hpp rename to rwviewer/models/DFFFramesTreeModel.hpp index 3edfca5a..a0b6b66b 100644 --- a/rwviewer/DFFFramesTreeModel.hpp +++ b/rwviewer/models/DFFFramesTreeModel.hpp @@ -4,6 +4,8 @@ #include #include +class Model; + class DFFFramesTreeModel : public QAbstractItemModel { Model* model; diff --git a/rwviewer/views/ModelViewer.cpp b/rwviewer/views/ModelViewer.cpp new file mode 100644 index 00000000..762a17df --- /dev/null +++ b/rwviewer/views/ModelViewer.cpp @@ -0,0 +1,43 @@ +#include "ModelViewer.hpp" +#include +#include "ViewerWidget.hpp" +#include + +ModelViewer::ModelViewer(ViewerWidget* viewer, QWidget* parent, Qt::WindowFlags f) +: QWidget(parent, f), _world(nullptr), viewing(nullptr) +{ + mainSplit = new QSplitter; + mainLayout = new QVBoxLayout; + + viewerWidget = viewer; + viewerWidget->setMinimumSize(250,250); + + frames = new ModelFramesWidget; + frames->setMaximumWidth(300); + + mainSplit->addWidget(frames); + mainLayout->addWidget(mainSplit); + + this->setLayout(mainLayout); + + setViewerWidget(viewerWidget); +} + +void ModelViewer::setViewerWidget(ViewerWidget* widget) +{ + viewerWidget = widget; + mainSplit->addWidget(viewerWidget); + showModel(viewing); +} + +void ModelViewer::showData(GameWorld* world) +{ + _world = world; +} + +void ModelViewer::showModel(Model* model) +{ + viewing = model; + viewerWidget->showModel(model); + frames->setModel(model); +} diff --git a/rwviewer/views/ModelViewer.hpp b/rwviewer/views/ModelViewer.hpp new file mode 100644 index 00000000..df887c62 --- /dev/null +++ b/rwviewer/views/ModelViewer.hpp @@ -0,0 +1,47 @@ +#pragma once +#ifndef _MODELVIEWER_HPP_ +#define _MODELVIEWER_HPP_ +#include +#include +#include +#include +#include +#include +#include +#include + +class ViewerWidget; +class Model; +class ModelFramesWidget; + +class ModelViewer : public QWidget +{ + Q_OBJECT + + GameWorld* _world; + Model* viewing; + + QSplitter* mainSplit; + QVBoxLayout* mainLayout; + ViewerWidget* viewerWidget; + + ModelFramesWidget* frames; +public: + + ModelViewer(ViewerWidget *viewer = 0, QWidget* parent = 0, Qt::WindowFlags f = 0); + + GameWorld* world() + { + return _world; + } + + void setViewerWidget( ViewerWidget* widget ); + +public slots: + + void showModel(Model* model); + + void showData(GameWorld* world); +}; + +#endif diff --git a/rwviewer/ObjectViewer.cpp b/rwviewer/views/ObjectViewer.cpp similarity index 98% rename from rwviewer/ObjectViewer.cpp rename to rwviewer/views/ObjectViewer.cpp index 4b258615..eebc591a 100644 --- a/rwviewer/ObjectViewer.cpp +++ b/rwviewer/views/ObjectViewer.cpp @@ -78,6 +78,7 @@ void ObjectViewer::showItem(qint16 item) } previewWidget->showItem(item); + modelChanged( previewWidget->currentModel() ); } } diff --git a/rwviewer/ObjectViewer.hpp b/rwviewer/views/ObjectViewer.hpp similarity index 93% rename from rwviewer/ObjectViewer.hpp rename to rwviewer/views/ObjectViewer.hpp index daf0888e..b94ba46d 100644 --- a/rwviewer/ObjectViewer.hpp +++ b/rwviewer/views/ObjectViewer.hpp @@ -10,6 +10,7 @@ #include class ViewerWidget; +class Model; class ObjectViewer : public QWidget { @@ -35,6 +36,10 @@ public: void setViewerWidget( ViewerWidget* widget ); +signals: + + void modelChanged(Model* model); + public slots: void showItem(qint16 item); diff --git a/rwviewer/ModelFramesWidget.cpp b/rwviewer/widgets/ModelFramesWidget.cpp similarity index 92% rename from rwviewer/ModelFramesWidget.cpp rename to rwviewer/widgets/ModelFramesWidget.cpp index 61e8bd72..edeb20bc 100644 --- a/rwviewer/ModelFramesWidget.cpp +++ b/rwviewer/widgets/ModelFramesWidget.cpp @@ -34,19 +34,17 @@ void ModelFramesWidget::selectedModelChanged(const QModelIndex & n, const QModel } ModelFramesWidget::ModelFramesWidget(QWidget* parent, Qt::WindowFlags flags) -: QDockWidget(parent, flags), gmodel(nullptr), framemodel(nullptr) +: QWidget(parent, flags), gmodel(nullptr), framemodel(nullptr) { setWindowTitle("Frames"); - QWidget* w = new QWidget(this); - - _layout = new QVBoxLayout(w); + _layout = new QVBoxLayout; tree = new QTreeView(this); _layout->addWidget(tree); _frameLabel = new QLabel(this); _layout->addWidget(_frameLabel); - setWidget(w); + setLayout(_layout); } void ModelFramesWidget::setModel(Model *model) diff --git a/rwviewer/ModelFramesWidget.hpp b/rwviewer/widgets/ModelFramesWidget.hpp similarity index 88% rename from rwviewer/ModelFramesWidget.hpp rename to rwviewer/widgets/ModelFramesWidget.hpp index 211eefff..f84484d4 100644 --- a/rwviewer/ModelFramesWidget.hpp +++ b/rwviewer/widgets/ModelFramesWidget.hpp @@ -3,14 +3,14 @@ #define _MODELFRAMESWIDGET_HPP_ #include #include -#include "DFFFramesTreeModel.hpp" +#include "models/DFFFramesTreeModel.hpp" #include #include #include class ModelFrame; -class ModelFramesWidget : public QDockWidget +class ModelFramesWidget : public QWidget { Q_OBJECT