1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-11-07 11:22:45 +01:00
openrw/rwviewer/ViewerWidget.cpp

232 lines
5.5 KiB
C++
Raw Normal View History

2014-02-10 13:41:05 +01:00
#include "ViewerWidget.hpp"
2014-02-11 14:40:56 +01:00
#include <render/Model.hpp>
#include <glm/gtc/type_ptr.hpp>
2014-02-11 16:45:45 +01:00
#include <QMouseEvent>
2014-03-01 12:19:33 +01:00
#include <engine/GameObject.hpp>
#include <engine/Animator.hpp>
2014-06-10 01:46:48 +02:00
#include <QFileDialog>
#include <algorithm>
2014-09-19 17:06:09 +02:00
2014-06-10 02:32:29 +02:00
#include <objects/InstanceObject.hpp>
2014-09-19 17:06:09 +02:00
#include <objects/CharacterObject.hpp>
#include <objects/VehicleObject.hpp>
2014-02-10 13:41:05 +01:00
2014-02-11 06:46:29 +01:00
ViewerWidget::ViewerWidget(QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f)
2014-06-10 01:46:48 +02:00
: QGLWidget(parent, shareWidget, f), gworld(nullptr), dummyObject(nullptr), currentObjectID(0),
2014-06-10 21:26:04 +02:00
_lastModel(nullptr), canimation(nullptr), viewDistance(1.f), dragging(false),
_frameWidgetDraw(nullptr), _frameWidgetGeom(nullptr)
2014-02-11 06:46:29 +01:00
{
}
2014-06-10 21:26:04 +02:00
struct WidgetVertex {
float x, y, z;
static const AttributeList vertex_attributes() {
return {
{ATRS_Position, 2, sizeof(WidgetVertex), 0ul}
};
}
};
std::vector<WidgetVertex> widgetVerts = {
{-1.f, 0.f, 0.f},
{ 1.f, 0.f, 0.f},
{ 0.f,-1.f, 0.f},
{ 0.f, 1.f, 0.f},
{ 0.f, 0.f,-1.f},
{ 0.f, 0.f, 1.f}
};
2014-02-10 13:41:05 +01:00
void ViewerWidget::initializeGL()
{
2014-02-10 18:22:07 +01:00
QGLWidget::initializeGL();
timer.setInterval(16);
connect(&timer, SIGNAL(timeout()), SLOT(updateGL()));
timer.start();
2014-06-10 21:26:04 +02:00
_frameWidgetDraw = new DrawBuffer;
_frameWidgetDraw->setFaceType(GL_LINES);
_frameWidgetGeom = new GeometryBuffer;
_frameWidgetGeom->uploadVertices(widgetVerts);
_frameWidgetDraw->addGeometry(_frameWidgetGeom);
2014-02-10 13:41:05 +01:00
}
void ViewerWidget::resizeGL(int w, int h)
{
2014-02-10 18:22:07 +01:00
QGLWidget::resizeGL(w, h);
2014-02-11 06:46:29 +01:00
glViewport(0, 0, w, h);
2014-02-10 13:41:05 +01:00
}
void ViewerWidget::paintGL()
{
glClearColor(0.3f, 0.3f, 0.3f, 1.f);
2014-02-11 14:40:56 +01:00
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, width(), height());
2014-06-08 02:58:49 +02:00
if( gworld == nullptr ) return;
2014-02-11 14:40:56 +01:00
auto& r = gworld->renderer;
2014-03-01 12:19:33 +01:00
if(dummyObject && dummyObject->animator) {
dummyObject->animator->tick(1.f/60.f);
}
2014-02-11 14:40:56 +01:00
2014-06-10 02:32:29 +02:00
if(dummyObject) {
2014-06-10 17:47:44 +02:00
gworld->_work->update();
r.getRenderer()->invalidate();
2014-06-10 17:47:44 +02:00
if( dummyObject->model->model != _lastModel ) {
_lastModel = dummyObject->model->model;
emit modelChanged(_lastModel);
}
2014-02-11 16:45:45 +01:00
glEnable(GL_DEPTH_TEST);
2014-02-11 14:40:56 +01:00
glm::mat4 m;
r.getRenderer()->useProgram(r.worldProg);
2014-02-10 18:22:07 +01:00
ViewCamera vc;
vc.frustum.far = 500.f;
vc.frustum.near = 0.1f;
vc.frustum.fov = 90.f;
vc.frustum.aspectRatio = width()/(height()*1.f);
glm::mat4 proj = vc.frustum.projection();
2014-02-11 16:45:45 +01:00
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));
2014-06-17 22:46:54 +02:00
2014-09-19 17:06:09 +02:00
r.getRenderer()->setSceneParameters({ proj, view, glm::vec4(1.f), glm::vec4(1.f), glm::vec4(1.f), glm::vec4(0.f), 90.f, vc.frustum.far });
2014-06-17 22:46:54 +02:00
r.getRenderer()->invalidate();
2014-06-10 02:32:29 +02:00
if( dummyObject->model->model ) {
gworld->renderer.renderModel(dummyObject->model->model, m, dummyObject);
2014-06-10 21:26:04 +02:00
drawFrameWidget(dummyObject->model->model->frames[dummyObject->model->model->rootFrameIdx]);
2014-06-10 02:32:29 +02:00
}
2014-02-10 18:22:07 +01:00
}
2014-02-10 13:41:05 +01:00
}
2014-02-10 18:22:07 +01:00
2014-06-10 21:26:04 +02:00
void ViewerWidget::drawFrameWidget(ModelFrame* f, const glm::mat4& m)
{
auto thisM = m * f->getTransform();
if(f->getGeometries().size() == 0) {
glBindTexture(GL_TEXTURE_2D, 0);
2014-06-17 22:46:54 +02:00
/*glUniform4f(gworld->renderer.uniCol, 1.f, 1.f, 1.f, 1.f);
glUniformMatrix4fv(gworld->renderer.uniModel, 1, GL_FALSE, glm::value_ptr(thisM));*/
2014-06-10 21:26:04 +02:00
glBindVertexArray(_frameWidgetDraw->getVAOName());
glDrawArrays(_frameWidgetDraw->getFaceType(), 0, 6);
}
for(auto c : f->getChildren()) {
drawFrameWidget(c, thisM);
}
}
2014-02-11 06:46:29 +01:00
GameWorld* ViewerWidget::world()
{
return gworld;
}
2014-06-08 02:58:49 +02:00
void ViewerWidget::showItem(qint16 item)
2014-02-11 06:46:29 +01:00
{
2014-06-10 01:46:48 +02:00
currentObjectID = item;
2014-06-10 02:32:29 +02:00
if( dummyObject ) gworld->destroyObject( dummyObject );
2014-09-19 17:06:09 +02:00
auto def = world()->objectTypes[item];
if( def )
{
if(def->class_type == ObjectData::class_id)
{
dummyObject = gworld->createInstance(item, {});
}
else if(def->class_type == CharacterData::class_id)
{
dummyObject = gworld->createPedestrian(item, {});
}
else if(def->class_type == VehicleData::class_id)
{
dummyObject = gworld->createVehicle(item, {});
}
}
2014-02-11 06:46:29 +01:00
}
2014-02-11 16:45:45 +01:00
2014-03-01 12:19:33 +01:00
void ViewerWidget::showAnimation(Animation *anim)
{
canimation = anim;
if(dummyObject) {
if(dummyObject->animator == nullptr) {
dummyObject->animator = new Animator;
2014-06-06 13:18:32 +02:00
dummyObject->animator->setModel(dummyObject->model->model);
2014-03-01 12:19:33 +01:00
}
dummyObject->animator->setAnimation(canimation);
}
}
2014-06-10 01:46:48 +02:00
void ViewerWidget::exportModel()
{
QString toSv = QFileDialog::getSaveFileName(this,
"Export Model",
QDir::homePath(),
"Model (*.DFF)");
if( toSv.size() == 0 ) return;
#if 0
2014-06-10 01:46:48 +02:00
auto it = world()->objectTypes.find(currentObjectID);
if( it != world()->objectTypes.end() ) {
for( auto& archive : world()->gameData.archives ) {
for(size_t i = 0; i < archive.second.getAssetCount(); ++i) {
auto& assetI = archive.second.getAssetInfoByIndex(i);
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());
}
}
}
}
#endif
2014-06-10 01:46:48 +02:00
}
void ViewerWidget::dataLoaded(GameWorld *world)
2014-02-12 07:42:07 +01:00
{
gworld = world;
2014-02-12 07:42:07 +01:00
}
Model* ViewerWidget::currentModel() const
2014-02-12 07:42:07 +01:00
{
return _lastModel;
2014-02-12 07:42:07 +01:00
}
2014-02-11 16:45:45 +01:00
void ViewerWidget::mousePressEvent(QMouseEvent* e)
{
dragging = true;
dstart = e->localPos();
dastart = viewAngles;
}
void ViewerWidget::mouseReleaseEvent(QMouseEvent*)
{
dragging = false;
}
void ViewerWidget::mouseMoveEvent(QMouseEvent* e)
{
if(dragging) {
auto d = e->localPos() - dstart;
viewAngles = dastart + glm::vec2(d.x(), d.y()) * 0.01f;
}
}
void ViewerWidget::wheelEvent(QWheelEvent* e)
{
2014-05-27 01:08:14 +02:00
viewDistance = qMax(viewDistance - e->angleDelta().y() / 240.f, 0.5f);
2014-02-11 16:45:45 +01:00
}