2014-02-10 13:41:05 +01:00
|
|
|
#include "ViewerWidget.hpp"
|
2018-08-10 02:40:23 +02:00
|
|
|
|
|
|
|
#include "QOpenGLContextWrapper.hpp"
|
|
|
|
|
2016-09-09 22:13:21 +02:00
|
|
|
#include <engine/Animator.hpp>
|
2017-09-07 19:03:18 +02:00
|
|
|
#include <engine/GameData.hpp>
|
|
|
|
#include <engine/GameWorld.hpp>
|
2014-02-11 14:40:56 +01:00
|
|
|
#include <glm/gtc/type_ptr.hpp>
|
2014-09-19 17:06:09 +02:00
|
|
|
#include <objects/CharacterObject.hpp>
|
2016-09-09 22:13:21 +02:00
|
|
|
#include <objects/InstanceObject.hpp>
|
2014-09-19 17:06:09 +02:00
|
|
|
#include <objects/VehicleObject.hpp>
|
2017-01-08 21:43:18 +01:00
|
|
|
#include <render/GameRenderer.hpp>
|
|
|
|
#include <render/ObjectRenderer.hpp>
|
2017-09-07 19:03:18 +02:00
|
|
|
#include <render/TextRenderer.hpp>
|
2018-01-16 02:05:23 +01:00
|
|
|
|
2018-08-10 02:40:23 +02:00
|
|
|
#include <QFileDialog>
|
|
|
|
#include <QMouseEvent>
|
|
|
|
|
2018-01-16 02:05:23 +01:00
|
|
|
constexpr float kViewFov = glm::radians(90.0f);
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
ViewCamera OrbitCamera (const glm::vec2& viewPort, const glm::vec2& viewAngles,
|
|
|
|
float viewDistance, glm::mat4& view, glm::mat4& proj)
|
|
|
|
{
|
|
|
|
ViewCamera vc;
|
|
|
|
glm::vec3 eye(sin(viewAngles.x) * cos(viewAngles.y),
|
|
|
|
cos(viewAngles.x) * cos(viewAngles.y), sin(viewAngles.y));
|
|
|
|
|
|
|
|
vc.position = eye * viewDistance;
|
|
|
|
vc.frustum.aspectRatio = viewPort.x / viewPort.y;
|
|
|
|
proj = vc.frustum.projection();
|
|
|
|
view = glm::lookAt(vc.position, {0.f, 0.f, 0.f}, {0.f, 0.f, 1.f});
|
|
|
|
vc.rotation = -glm::quat_cast(view);
|
|
|
|
vc.frustum.update(proj * view);
|
|
|
|
return vc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-10 02:40:23 +02:00
|
|
|
ViewerWidget::ViewerWidget(QOpenGLContextWrapper* context, QWindow* parent)
|
2018-01-16 02:05:23 +01:00
|
|
|
: QWindow(parent)
|
2018-08-10 02:40:23 +02:00
|
|
|
, m_context(context) {
|
2018-01-16 02:05:23 +01:00
|
|
|
setSurfaceType(OpenGLSurface);
|
2014-02-11 06:46:29 +01:00
|
|
|
}
|
|
|
|
|
2014-06-10 21:26:04 +02:00
|
|
|
struct WidgetVertex {
|
2016-09-09 22:13:21 +02:00
|
|
|
float x, y, z;
|
|
|
|
static const AttributeList vertex_attributes() {
|
|
|
|
return {{ATRS_Position, 3, sizeof(WidgetVertex), 0ul}};
|
|
|
|
}
|
2014-06-10 21:26:04 +02:00
|
|
|
};
|
|
|
|
|
2016-09-09 22:13:21 +02:00
|
|
|
std::vector<WidgetVertex> widgetVerts = {{-.5f, 0.f, 0.f}, {.5f, 0.f, 0.f},
|
|
|
|
{0.f, -.5f, 0.f}, {0.f, .5f, 0.f},
|
|
|
|
{0.f, 0.f, -.5f}, {0.f, 0.f, .5f}};
|
|
|
|
|
2018-01-16 02:05:23 +01:00
|
|
|
void ViewerWidget::initGL() {
|
2016-09-09 22:13:21 +02:00
|
|
|
_frameWidgetDraw = new DrawBuffer;
|
|
|
|
_frameWidgetDraw->setFaceType(GL_LINES);
|
|
|
|
_frameWidgetGeom = new GeometryBuffer;
|
|
|
|
_frameWidgetGeom->uploadVertices(widgetVerts);
|
|
|
|
_frameWidgetDraw->addGeometry(_frameWidgetGeom);
|
|
|
|
|
|
|
|
glGenTextures(1, &whiteTex);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, whiteTex);
|
|
|
|
GLuint tex = 0xFFFFFFFF;
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE,
|
|
|
|
&tex);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
2014-02-10 13:41:05 +01:00
|
|
|
}
|
|
|
|
|
2018-01-16 02:05:23 +01:00
|
|
|
void ViewerWidget::drawModel(GameRenderer& r, ClumpPtr& model) {
|
2018-02-06 20:47:31 +01:00
|
|
|
glm::mat4 view{1.0f}, proj{1.0f};
|
2018-01-16 02:05:23 +01:00
|
|
|
const auto& vc = OrbitCamera({width(), height()},
|
|
|
|
viewAngles,
|
|
|
|
viewDistance,
|
|
|
|
view, proj);
|
2014-06-10 17:47:44 +02:00
|
|
|
|
2018-01-16 02:05:23 +01:00
|
|
|
r.getRenderer()->useProgram(r.worldProg.get());
|
|
|
|
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});
|
|
|
|
model->getFrame()->updateHierarchyTransform();
|
2015-04-13 02:48:29 +02:00
|
|
|
|
2018-01-16 02:05:23 +01:00
|
|
|
ObjectRenderer _renderer(world(), vc, 1.f, 0);
|
|
|
|
RenderList renders;
|
2018-02-06 20:47:31 +01:00
|
|
|
_renderer.renderClump(model.get(), glm::mat4(1.0f), nullptr, renders);
|
2018-01-16 02:05:23 +01:00
|
|
|
r.getRenderer()->drawBatched(renders);
|
2014-09-19 01:10:05 +02:00
|
|
|
|
2018-01-16 02:05:23 +01:00
|
|
|
drawFrameWidget(model->getFrame().get());
|
|
|
|
r.renderPostProcess();
|
|
|
|
}
|
2014-02-10 18:22:07 +01:00
|
|
|
|
2018-01-16 02:05:23 +01:00
|
|
|
void ViewerWidget::drawObject(GameRenderer &r, GameObject *object) {
|
2018-02-06 20:47:31 +01:00
|
|
|
glm::mat4 view{1.0f}, proj{1.0f};
|
2018-01-16 02:05:23 +01:00
|
|
|
const auto& vc = OrbitCamera({width(), height()},
|
|
|
|
viewAngles,
|
|
|
|
viewDistance,
|
|
|
|
view, proj);
|
2014-08-12 22:15:26 +02:00
|
|
|
|
2017-10-29 19:47:52 +01:00
|
|
|
r.getRenderer()->useProgram(r.worldProg.get());
|
2018-01-16 02:05:23 +01:00
|
|
|
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});
|
2014-09-21 17:20:30 +02:00
|
|
|
|
2018-01-16 02:05:23 +01:00
|
|
|
ObjectRenderer objectRenderer(world(), vc, 1.f, 0);
|
|
|
|
RenderList renders;
|
|
|
|
objectRenderer.buildRenderList(object, renders);
|
|
|
|
std::sort(renders.begin(), renders.end(),
|
|
|
|
[](const Renderer::RenderInstruction& a,
|
|
|
|
const Renderer::RenderInstruction& b) {
|
|
|
|
return a.sortKey < b.sortKey;
|
|
|
|
});
|
|
|
|
r.getRenderer()->drawBatched(renders);
|
|
|
|
r.renderPostProcess();
|
|
|
|
}
|
2016-05-16 01:06:51 +02:00
|
|
|
|
2018-01-16 02:05:23 +01:00
|
|
|
void ViewerWidget::drawWorld(GameRenderer& r) {
|
|
|
|
ViewCamera vc;
|
|
|
|
vc.frustum.fov = kViewFov;
|
|
|
|
vc.frustum.far = 1000.f;
|
2016-09-09 22:13:21 +02:00
|
|
|
vc.frustum.near = 0.1f;
|
2018-01-16 02:05:23 +01:00
|
|
|
vc.position = viewPosition;
|
|
|
|
vc.rotation = glm::angleAxis(glm::half_pi<float>() + viewAngles.x,
|
|
|
|
glm::vec3(0.f, 0.f, 1.f)) *
|
|
|
|
glm::angleAxis(viewAngles.y, glm::vec3(0.f, 1.f, 0.f));
|
2016-09-09 22:13:21 +02:00
|
|
|
vc.frustum.aspectRatio = width() / (height() * 1.f);
|
2018-01-16 02:05:23 +01:00
|
|
|
r.renderWorld(world(), vc, 0.f);
|
|
|
|
}
|
2014-06-17 22:46:54 +02:00
|
|
|
|
2017-09-07 19:03:18 +02:00
|
|
|
void ViewerWidget::drawText(GameRenderer& r) {
|
|
|
|
for(auto &textInfo : textInfos) {
|
|
|
|
_renderer->text.renderText(textInfo, false);
|
|
|
|
}
|
|
|
|
r.renderPostProcess();
|
|
|
|
}
|
|
|
|
|
2018-01-16 02:05:23 +01:00
|
|
|
void ViewerWidget::paintGL() {
|
2018-02-01 16:16:04 +01:00
|
|
|
glViewport(0, 0, width() * devicePixelRatio(), height() * devicePixelRatio());
|
2018-01-16 02:05:23 +01:00
|
|
|
glClearColor(0.3f, 0.3f, 0.3f, 1.f);
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
2014-06-17 22:46:54 +02:00
|
|
|
|
2018-01-16 02:05:23 +01:00
|
|
|
if (world() == nullptr) return;
|
2014-09-19 01:10:05 +02:00
|
|
|
|
2018-01-16 02:05:23 +01:00
|
|
|
RW_CHECK(_renderer != nullptr, "GameRenderer is null");
|
|
|
|
auto& r = *_renderer;
|
|
|
|
r.getRenderer()->invalidate();
|
2018-02-01 16:16:04 +01:00
|
|
|
r.setViewport(width() * devicePixelRatio(), height() * devicePixelRatio());
|
2017-01-08 21:43:18 +01:00
|
|
|
|
2018-01-16 02:05:23 +01:00
|
|
|
glEnable(GL_DEPTH_TEST);
|
2014-06-10 21:26:04 +02:00
|
|
|
|
2018-01-16 02:05:23 +01:00
|
|
|
r.getRenderer()->invalidate();
|
|
|
|
r.setupRender();
|
|
|
|
|
|
|
|
switch (_viewMode) {
|
|
|
|
case Mode::Model:
|
|
|
|
if (_model) drawModel(r, _model);
|
|
|
|
break;
|
|
|
|
case Mode::Object:
|
|
|
|
if (_object) drawObject(r, _object);
|
|
|
|
break;
|
|
|
|
case Mode::World:
|
|
|
|
drawWorld(r);
|
|
|
|
break;
|
2017-09-07 19:03:18 +02:00
|
|
|
case Mode::Text:
|
|
|
|
drawText(r);
|
|
|
|
break;
|
2016-09-09 22:13:21 +02:00
|
|
|
}
|
|
|
|
}
|
2014-06-10 02:32:29 +02:00
|
|
|
|
2016-09-09 22:13:21 +02:00
|
|
|
void ViewerWidget::drawFrameWidget(ModelFrame* f, const glm::mat4& m) {
|
|
|
|
auto thisM = m * f->getTransform();
|
2017-01-08 21:43:18 +01:00
|
|
|
Renderer::DrawParameters dp;
|
|
|
|
dp.count = _frameWidgetGeom->getCount();
|
|
|
|
dp.start = 0;
|
|
|
|
dp.ambient = 1.f;
|
|
|
|
dp.diffuse = 1.f;
|
|
|
|
if (f == selectedFrame) {
|
|
|
|
dp.colour = {255, 255, 0, 255};
|
|
|
|
// Sorry!
|
|
|
|
glLineWidth(10.f);
|
|
|
|
} else {
|
|
|
|
dp.colour = {255, 255, 255, 255};
|
|
|
|
glLineWidth(1.f);
|
2016-09-09 22:13:21 +02:00
|
|
|
}
|
2017-01-08 21:43:18 +01:00
|
|
|
dp.textures = {whiteTex};
|
rwlib: Use ClumpPtr instead of Clump*
Should fix these memory leaks:
==22737== 14,598,040 (131,472 direct, 14,466,568 indirect) bytes in 2,739 blocks are definitely lost in loss record 3,124 of 3,126
==22737== at 0x4C2F1CA: operator new(unsigned long) (vg_replace_malloc.c:334)
==22737== by 0x90FE4B: LoaderDFF::loadFromMemory(std::shared_ptr<FileContentsInfo>) (LoaderDFF.cpp:443)
==22737== by 0x7BCC86: GameData::loadModel(unsigned short) (GameData.cpp:474)
==22737== by 0x7DF7BC: GameWorld::createInstance(unsigned short, glm::tvec3<float, (glm::precision)0> const&, glm::tquat<float, (glm::precision)0> const&) (GameWorld.cpp:144)
==22737== by 0x7DF44C: GameWorld::placeItems(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (GameWorld.cpp:120)
==22737== by 0x758D38: RWGame::newGame() (RWGame.cpp:116)
==22737== by 0x786389: LoadingState::enter() (LoadingState.cpp:9)
==22737== by 0x75DC59: void StateManager::enter<LoadingState, RWGame*, RWGame::RWGame(Logger&, int, char**)::{lambda()#1}>(RWGame*&&, RWGame::RWGame(Logger&, int, char**)::{lambda()#1}&&) (StateManager.hpp:40)
==22737== by 0x758484: RWGame::RWGame(Logger&, int, char**) (RWGame.cpp:81)
==22737== by 0x747815: main (main.cpp:13)
2017-09-13 00:47:22 +02:00
|
|
|
|
2018-01-16 02:05:23 +01:00
|
|
|
RW_CHECK(_renderer != nullptr, "GameRenderer is null");
|
|
|
|
if(_renderer != nullptr) {
|
|
|
|
_renderer->getRenderer()->drawArrays(thisM, _frameWidgetDraw, dp);
|
2017-04-16 07:57:08 +02:00
|
|
|
}
|
2016-09-09 22:13:21 +02:00
|
|
|
|
|
|
|
for (auto c : f->getChildren()) {
|
2017-01-08 21:43:18 +01:00
|
|
|
drawFrameWidget(c.get(), thisM);
|
2016-09-09 22:13:21 +02:00
|
|
|
}
|
|
|
|
}
|
2014-06-10 02:32:29 +02:00
|
|
|
|
2016-09-09 22:13:21 +02:00
|
|
|
GameWorld* ViewerWidget::world() {
|
2018-01-16 02:05:23 +01:00
|
|
|
return _world;
|
2016-09-09 22:13:21 +02:00
|
|
|
}
|
2014-09-19 17:06:09 +02:00
|
|
|
|
2018-01-16 02:05:23 +01:00
|
|
|
void ViewerWidget::showObject(quint16 item) {
|
|
|
|
RW_ASSERT(world());
|
|
|
|
_viewMode = Mode::Object;
|
|
|
|
_objectID = item;
|
2016-09-09 22:13:21 +02:00
|
|
|
|
2018-01-16 02:05:23 +01:00
|
|
|
if (_object) _world->destroyObject(_object);
|
|
|
|
_object = nullptr;
|
2016-09-09 22:13:21 +02:00
|
|
|
|
2016-09-11 03:58:00 +02:00
|
|
|
auto def = world()->data->modelinfo[item].get();
|
2018-01-16 02:05:23 +01:00
|
|
|
if (!def) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!world()->data->loadModel(item)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (def->type()) {
|
|
|
|
default:
|
|
|
|
_object = _world->createInstance(item, {});
|
|
|
|
break;
|
|
|
|
case ModelDataType::PedInfo:
|
|
|
|
_object = _world->createPedestrian(item, {});
|
|
|
|
break;
|
|
|
|
case ModelDataType::VehicleInfo:
|
|
|
|
_object = _world->createVehicle(item, {});
|
|
|
|
break;
|
|
|
|
}
|
2016-09-09 22:13:21 +02:00
|
|
|
|
2018-01-16 02:05:23 +01:00
|
|
|
RW_CHECK(_object != nullptr, "Dummy Object is null");
|
|
|
|
|
|
|
|
if (_object->getModel()) {
|
|
|
|
auto objectRadius = _object->getModel()->getBoundingRadius();
|
|
|
|
viewDistance = objectRadius * 2;
|
|
|
|
viewAngles.x = glm::radians(-45.f);
|
|
|
|
viewAngles.y = glm::radians(22.5f);
|
2016-09-09 22:13:21 +02:00
|
|
|
}
|
2014-02-11 06:46:29 +01:00
|
|
|
}
|
2014-02-11 16:45:45 +01:00
|
|
|
|
2017-09-07 19:03:18 +02:00
|
|
|
void ViewerWidget::clearText() {
|
|
|
|
textInfos.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ViewerWidget::showText(const TextRenderer::TextInfo &ti) {
|
|
|
|
textInfos.push_back(ti);
|
|
|
|
}
|
|
|
|
|
rwlib: Use ClumpPtr instead of Clump*
Should fix these memory leaks:
==22737== 14,598,040 (131,472 direct, 14,466,568 indirect) bytes in 2,739 blocks are definitely lost in loss record 3,124 of 3,126
==22737== at 0x4C2F1CA: operator new(unsigned long) (vg_replace_malloc.c:334)
==22737== by 0x90FE4B: LoaderDFF::loadFromMemory(std::shared_ptr<FileContentsInfo>) (LoaderDFF.cpp:443)
==22737== by 0x7BCC86: GameData::loadModel(unsigned short) (GameData.cpp:474)
==22737== by 0x7DF7BC: GameWorld::createInstance(unsigned short, glm::tvec3<float, (glm::precision)0> const&, glm::tquat<float, (glm::precision)0> const&) (GameWorld.cpp:144)
==22737== by 0x7DF44C: GameWorld::placeItems(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (GameWorld.cpp:120)
==22737== by 0x758D38: RWGame::newGame() (RWGame.cpp:116)
==22737== by 0x786389: LoadingState::enter() (LoadingState.cpp:9)
==22737== by 0x75DC59: void StateManager::enter<LoadingState, RWGame*, RWGame::RWGame(Logger&, int, char**)::{lambda()#1}>(RWGame*&&, RWGame::RWGame(Logger&, int, char**)::{lambda()#1}&&) (StateManager.hpp:40)
==22737== by 0x758484: RWGame::RWGame(Logger&, int, char**) (RWGame.cpp:81)
==22737== by 0x747815: main (main.cpp:13)
2017-09-13 00:47:22 +02:00
|
|
|
void ViewerWidget::showModel(ClumpPtr model) {
|
2018-01-16 02:05:23 +01:00
|
|
|
_viewMode = Mode::Model;
|
|
|
|
_model = model;
|
2017-09-07 19:03:18 +02:00
|
|
|
textInfos.clear();
|
2015-04-13 02:48:29 +02:00
|
|
|
}
|
|
|
|
|
2016-09-09 22:13:21 +02:00
|
|
|
void ViewerWidget::selectFrame(ModelFrame* frame) {
|
|
|
|
selectedFrame = frame;
|
2015-04-13 03:09:14 +02:00
|
|
|
}
|
2015-04-13 02:48:29 +02:00
|
|
|
|
2016-09-09 22:13:21 +02:00
|
|
|
void ViewerWidget::exportModel() {
|
2018-01-16 02:05:23 +01:00
|
|
|
#if 0
|
2016-09-09 22:13:21 +02:00
|
|
|
QString toSv = QFileDialog::getSaveFileName(
|
|
|
|
this, "Export Model", QDir::homePath(), "Model (*.DFF)");
|
2014-06-10 01:46:48 +02:00
|
|
|
|
2016-09-09 22:13:21 +02:00
|
|
|
if (toSv.size() == 0) return;
|
2014-06-10 01:46:48 +02:00
|
|
|
|
|
|
|
auto it = world()->objectTypes.find(currentObjectID);
|
|
|
|
if( it != world()->objectTypes.end() ) {
|
2015-04-18 02:11:17 +02:00
|
|
|
for( auto& archive : world()->data.archives ) {
|
2014-06-10 01:46:48 +02:00
|
|
|
for(size_t i = 0; i < archive.second.getAssetCount(); ++i) {
|
2017-09-07 19:03:18 +02:00
|
|
|
auto& assetI = archive.second.getAssetInfoByIndex(i);;
|
2014-06-10 01:46:48 +02:00
|
|
|
std::string q(assetI.name);
|
|
|
|
std::transform(q.begin(), q.end(), q.begin(), ::tolower);
|
|
|
|
if( q.find(it->second->modelName) != q.npos ) {
|
|
|
|
archive.second.saveAsset(q, toSv.toStdString());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-09-17 04:13:02 +02:00
|
|
|
#endif
|
2014-06-10 01:46:48 +02:00
|
|
|
}
|
|
|
|
|
2016-09-09 22:13:21 +02:00
|
|
|
void ViewerWidget::keyPressEvent(QKeyEvent* e) {
|
|
|
|
if (e->key() == Qt::Key_Shift) moveFast = true;
|
|
|
|
|
2018-02-06 20:47:31 +01:00
|
|
|
glm::vec3 movement{};
|
2016-09-09 22:13:21 +02:00
|
|
|
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;
|
|
|
|
}
|
2016-05-16 01:06:51 +02:00
|
|
|
}
|
|
|
|
|
2016-09-09 22:13:21 +02:00
|
|
|
void ViewerWidget::keyReleaseEvent(QKeyEvent* e) {
|
|
|
|
if (e->key() == Qt::Key_Shift) moveFast = false;
|
2016-05-16 01:06:51 +02:00
|
|
|
}
|
|
|
|
|
rwlib: Use ClumpPtr instead of Clump*
Should fix these memory leaks:
==22737== 14,598,040 (131,472 direct, 14,466,568 indirect) bytes in 2,739 blocks are definitely lost in loss record 3,124 of 3,126
==22737== at 0x4C2F1CA: operator new(unsigned long) (vg_replace_malloc.c:334)
==22737== by 0x90FE4B: LoaderDFF::loadFromMemory(std::shared_ptr<FileContentsInfo>) (LoaderDFF.cpp:443)
==22737== by 0x7BCC86: GameData::loadModel(unsigned short) (GameData.cpp:474)
==22737== by 0x7DF7BC: GameWorld::createInstance(unsigned short, glm::tvec3<float, (glm::precision)0> const&, glm::tquat<float, (glm::precision)0> const&) (GameWorld.cpp:144)
==22737== by 0x7DF44C: GameWorld::placeItems(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (GameWorld.cpp:120)
==22737== by 0x758D38: RWGame::newGame() (RWGame.cpp:116)
==22737== by 0x786389: LoadingState::enter() (LoadingState.cpp:9)
==22737== by 0x75DC59: void StateManager::enter<LoadingState, RWGame*, RWGame::RWGame(Logger&, int, char**)::{lambda()#1}>(RWGame*&&, RWGame::RWGame(Logger&, int, char**)::{lambda()#1}&&) (StateManager.hpp:40)
==22737== by 0x758484: RWGame::RWGame(Logger&, int, char**) (RWGame.cpp:81)
==22737== by 0x747815: main (main.cpp:13)
2017-09-13 00:47:22 +02:00
|
|
|
ClumpPtr ViewerWidget::currentModel() const {
|
2018-01-16 02:05:23 +01:00
|
|
|
return _model;
|
2014-02-12 07:42:07 +01:00
|
|
|
}
|
|
|
|
|
2016-09-09 22:13:21 +02:00
|
|
|
GameObject* ViewerWidget::currentObject() const {
|
2018-01-16 02:05:23 +01:00
|
|
|
return _object;
|
2015-04-14 02:06:50 +02:00
|
|
|
}
|
|
|
|
|
2016-09-09 22:13:21 +02:00
|
|
|
void ViewerWidget::mousePressEvent(QMouseEvent* e) {
|
|
|
|
dragging = true;
|
|
|
|
dstart = e->localPos();
|
|
|
|
dastart = viewAngles;
|
2014-02-11 16:45:45 +01:00
|
|
|
}
|
|
|
|
|
2016-09-09 22:13:21 +02:00
|
|
|
void ViewerWidget::mouseReleaseEvent(QMouseEvent*) {
|
|
|
|
dragging = false;
|
2014-02-11 16:45:45 +01:00
|
|
|
}
|
|
|
|
|
2016-09-09 22:13:21 +02:00
|
|
|
void ViewerWidget::mouseMoveEvent(QMouseEvent* e) {
|
|
|
|
if (dragging) {
|
|
|
|
auto d = e->localPos() - dstart;
|
|
|
|
viewAngles = dastart + glm::vec2(d.x(), d.y()) * 0.01f;
|
|
|
|
}
|
2014-02-11 16:45:45 +01:00
|
|
|
}
|
|
|
|
|
2016-09-09 22:13:21 +02:00
|
|
|
void ViewerWidget::wheelEvent(QWheelEvent* e) {
|
|
|
|
viewDistance = qMax(viewDistance - e->angleDelta().y() / 240.f, 0.5f);
|
2014-02-11 16:45:45 +01:00
|
|
|
}
|
2018-01-16 02:05:23 +01:00
|
|
|
|
|
|
|
void ViewerWidget::gameLoaded(GameWorld *world, GameRenderer *renderer) {
|
|
|
|
_world = world;
|
|
|
|
_renderer = renderer;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ViewerWidget::renderNow() {
|
|
|
|
if (!isExposed()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-08-10 02:40:23 +02:00
|
|
|
m_context->makeCurrent(this);
|
2018-01-16 02:05:23 +01:00
|
|
|
|
|
|
|
if (!initialised) {
|
|
|
|
initGL();
|
|
|
|
initialised = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
paintGL();
|
2018-08-10 02:40:23 +02:00
|
|
|
m_context->swapBuffers(this);
|
2018-01-16 02:05:23 +01:00
|
|
|
|
|
|
|
requestUpdate();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ViewerWidget::event(QEvent *e) {
|
|
|
|
switch(e->type()) {
|
|
|
|
case QEvent::UpdateRequest:
|
|
|
|
renderNow();
|
|
|
|
return true;
|
|
|
|
default: return QWindow::event(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ViewerWidget::exposeEvent(QExposeEvent *) {
|
|
|
|
if (isExposed()) {
|
|
|
|
requestUpdate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|