refactor drawing code

This commit is contained in:
ccolin 2021-01-03 12:30:16 +01:00
parent 8ad1cf1b89
commit 928d45c3fb
9 changed files with 101 additions and 39 deletions

View File

@ -4,6 +4,7 @@
#include "opengl_widget.hh" #include "opengl_widget.hh"
#include <QJsonArray> #include <QJsonArray>
#include <QDebug>
bool Drone::mesh_initialized = false; bool Drone::mesh_initialized = false;
@ -11,14 +12,15 @@ OpenGLMesh *Drone::mesh = nullptr;
Drone::Drone(int id) Drone::Drone(int id)
:id(id) { :id(id) {
OpenGLWidget *glw = OpenGLWidget::instance;
if (!mesh_initialized) { if (!mesh_initialized) {
glw->makeCurrent();
QVector<GLfloat> verts = load_obj(":/mdl/dji600.obj", LOAD_OBJ_NORMALS | LOAD_OBJ_UVS); QVector<GLfloat> verts = load_obj(":/mdl/dji600.obj", LOAD_OBJ_NORMALS | LOAD_OBJ_UVS);
QOpenGLTexture *texture = new QOpenGLTexture(QImage(":/img/dji600.jpg").mirrored()); QOpenGLTexture *texture = new QOpenGLTexture(QImage(":/img/dji600.jpg").mirrored());
mesh = new OpenGLMesh(verts, texture); mesh = new OpenGLMesh(verts, texture, glw->getMainProgram());
mesh_initialized = true; mesh_initialized = true;
glw->doneCurrent();
} }
OpenGLWidget::instance->meshes.append(*mesh);
mesh_id = OpenGLWidget::instance->meshes.size() - 1;
} }
@ -51,8 +53,6 @@ void Drone::setTo(int frame) {
break; break;
} }
} }
OpenGLMesh &mesh = OpenGLWidget::instance->meshes[mesh_id];
mesh.mat = QMatrix4x4();
if (next > -1 && prev == -1) { if (next > -1 && prev == -1) {
pos = next_wp->pos; pos = next_wp->pos;
} else if (prev > -1 && next == -1) { } else if (prev > -1 && next == -1) {
@ -60,11 +60,10 @@ void Drone::setTo(int frame) {
} else { } else {
pos = lerp(prev_wp->pos, next_wp->pos, (double) (frame-prev) / (next-prev)); pos = lerp(prev_wp->pos, next_wp->pos, (double) (frame-prev) / (next-prev));
} }
mesh.mat.translate(pos);
} }
QVector3D Drone::getPos() const { const QVector3D Drone::getPos() const {
return pos; return pos;
} }
@ -72,3 +71,8 @@ QVector3D Drone::getPos() const {
int Drone::getId() const { int Drone::getId() const {
return id; return id;
} }
const OpenGLMesh *Drone::getMesh() const {
return mesh;
}

View File

@ -20,7 +20,6 @@ class Drone {
static bool mesh_initialized; static bool mesh_initialized;
QVector<Waypoint> waypoints; QVector<Waypoint> waypoints;
int mesh_id;
QVector3D pos; QVector3D pos;
int id; int id;
@ -29,8 +28,9 @@ public:
Drone(const QJsonObject &json); Drone(const QJsonObject &json);
const QVector<Waypoint> getWaypoints() const; const QVector<Waypoint> getWaypoints() const;
void setTo(int frame); void setTo(int frame);
QVector3D getPos() const; const QVector3D getPos() const;
int getId() const; int getId() const;
const OpenGLMesh *getMesh() const;
}; };

View File

@ -3,6 +3,7 @@
#include <QJsonArray> #include <QJsonArray>
#include <QDebug> #include <QDebug>
#include <QOpenGLShaderProgram>
DroneController::DroneController(const QJsonObject &json) DroneController::DroneController(const QJsonObject &json)
@ -19,33 +20,26 @@ DroneController::DroneController(const QJsonObject &json)
} }
} }
OpenGLWidget::instance->makeCurrent();
QOpenGLTexture *ground_tex = new QOpenGLTexture(QImage(":/img/ground.jpg").mirrored());
ground_tex->setMagnificationFilter(QOpenGLTexture::LinearMipMapLinear);
ground_tex->setMinificationFilter(QOpenGLTexture::LinearMipMapLinear);
ground_tex->setWrapMode(QOpenGLTexture::MirroredRepeat);
OpenGLMesh *ground = new OpenGLMesh({
-1000, 0, -1000, 0, 1000, 0, 0, 0,
1000, 0, -1000, 0, 1000, 0, 1000, 0,
-1000, 0, 1000, 0, 1000, 0, 0, 1000,
1000, 0, -1000, 0, 1000, 0, 1000, 0,
-1000, 0, 1000, 0, 1000, 0, 0, 1000,
1000, 0, 1000, 0, 1000, 0, 1000, 1000,
}, ground_tex);
OpenGLWidget::instance->meshes.append(*ground);
OpenGLWidget::instance->doneCurrent();
connect(&timer, &QTimer::timeout, this, &DroneController::step); connect(&timer, &QTimer::timeout, this, &DroneController::step);
} }
void DroneController::draw(QOpenGLExtraFunctions *f) const {
for (const Drone &d : drones) {
QMatrix4x4 mat;
mat.translate(d.getPos());
d.getMesh()->draw(f, mat);
}
}
int DroneController::getDuration() const { int DroneController::getDuration() const {
return duration; return duration;
} }
void DroneController::step() { void DroneController::step() {
for (Drone d : drones) { for (Drone &d : drones) {
d.setTo(frame); d.setTo(frame);
} }
OpenGLWidget::instance->update(); OpenGLWidget::instance->update();
@ -111,7 +105,9 @@ void DroneController::computeCollisions(double sphere_radius) {
} }
} }
} }
seek(frame); for (Drone &d : drones) {
d.setTo(frame);
}
} }

View File

@ -3,11 +3,14 @@
#include "drone.hh" #include "drone.hh"
#include "opengl_widget.hh"
#include <QJsonObject> #include <QJsonObject>
#include <QTimer> #include <QTimer>
#include <QOpenGLExtraFunctions>
class DroneController : public QObject { class DroneController : public QObject, public Painter {
Q_OBJECT Q_OBJECT
int framerate; int framerate;
@ -22,6 +25,7 @@ class DroneController : public QObject {
public: public:
DroneController(const QJsonObject &json); DroneController(const QJsonObject &json);
int getDuration() const; int getDuration() const;
void draw(QOpenGLExtraFunctions *f) const;
signals: signals:
void frameChanged(int frame); void frameChanged(int frame);

View File

@ -81,6 +81,7 @@ void MainWindow::open(const QString &path) {
slider, &QSlider::setValue); slider, &QSlider::setValue);
slider->setEnabled(true); slider->setEnabled(true);
// Settings pane
connect(dc, &DroneController::collision, settings_pane, &SettingsPane::addCollision); connect(dc, &DroneController::collision, settings_pane, &SettingsPane::addCollision);
connect(settings_pane, &SettingsPane::sphereRadiusChanged, connect(settings_pane, &SettingsPane::sphereRadiusChanged,
[&](double _) { settings_pane->clearCollisions(); }); [&](double _) { settings_pane->clearCollisions(); });
@ -88,6 +89,8 @@ void MainWindow::open(const QString &path) {
dc, &DroneController::computeCollisions); dc, &DroneController::computeCollisions);
settings_pane->setEnabled(true); settings_pane->setEnabled(true);
glw.setPainter(dc);
dc->computeCollisions(.1); dc->computeCollisions(.1);
pause(); pause();
} }

View File

@ -4,8 +4,9 @@
#include <QOpenGLFunctions> #include <QOpenGLFunctions>
OpenGLMesh::OpenGLMesh(QVector<float> verts, QOpenGLTexture *tex) OpenGLMesh::OpenGLMesh(QVector<float> verts, QOpenGLTexture *tex, QOpenGLShaderProgram *program)
:tex(tex) { :tex(tex),
program(program) {
OpenGLWidget::instance->makeCurrent(); OpenGLWidget::instance->makeCurrent();
QOpenGLExtraFunctions *glf = OpenGLWidget::instance; QOpenGLExtraFunctions *glf = OpenGLWidget::instance;
nverts = verts.size() / 8; nverts = verts.size() / 8;
@ -24,3 +25,13 @@ OpenGLMesh::OpenGLMesh(QVector<float> verts, QOpenGLTexture *tex)
glf->glBindVertexArray(0); glf->glBindVertexArray(0);
OpenGLWidget::instance->doneCurrent(); OpenGLWidget::instance->doneCurrent();
} }
void OpenGLMesh::draw(QOpenGLExtraFunctions *f, const QMatrix4x4 &mat) const {
program->bind();
program->setUniformValue("model", mat);
f->glBindVertexArray(vao);
tex->bind();
f->glDrawArrays(GL_TRIANGLES, 0, nverts);
tex->release();
}

View File

@ -4,15 +4,18 @@
#include <QMatrix4x4> #include <QMatrix4x4>
#include <QVector> #include <QVector>
#include <QOpenGLTexture> #include <QOpenGLTexture>
#include <QOpenGLShaderProgram>
#include <QOpenGLExtraFunctions>
struct OpenGLMesh { struct OpenGLMesh {
GLuint vao, vbo; GLuint vao, vbo;
unsigned nverts; unsigned nverts;
QMatrix4x4 mat;
QOpenGLTexture *tex; QOpenGLTexture *tex;
QOpenGLShaderProgram *program;
OpenGLMesh(QVector<float> verts, QOpenGLTexture *tex); OpenGLMesh(QVector<float> verts, QOpenGLTexture *tex, QOpenGLShaderProgram *program);
void draw(QOpenGLExtraFunctions *f, const QMatrix4x4 &mat) const;
}; };

View File

@ -96,6 +96,22 @@ void OpenGLWidget::loadSkybox() {
} }
void OpenGLWidget::loadGround() {
QOpenGLTexture *ground_tex = new QOpenGLTexture(QImage(":/img/ground.jpg").mirrored());
ground_tex->setMagnificationFilter(QOpenGLTexture::LinearMipMapLinear);
ground_tex->setMinificationFilter(QOpenGLTexture::LinearMipMapLinear);
ground_tex->setWrapMode(QOpenGLTexture::MirroredRepeat);
ground = new OpenGLMesh({
-1000, 0, -1000, 0, 1000, 0, 0, 0,
1000, 0, -1000, 0, 1000, 0, 1000, 0,
-1000, 0, 1000, 0, 1000, 0, 0, 1000,
1000, 0, -1000, 0, 1000, 0, 1000, 0,
-1000, 0, 1000, 0, 1000, 0, 0, 1000,
1000, 0, 1000, 0, 1000, 0, 1000, 1000,
}, ground_tex, &main_program);
}
void OpenGLWidget::initializeGL() { void OpenGLWidget::initializeGL() {
initializeOpenGLFunctions(); initializeOpenGLFunctions();
GLint major, minor; GLint major, minor;
@ -123,6 +139,7 @@ void OpenGLWidget::initializeGL() {
main_program.release(); main_program.release();
loadSkybox(); loadSkybox();
loadGround();
glClearColor(1, 1, 1, 0); glClearColor(1, 1, 1, 0);
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
@ -163,13 +180,15 @@ void OpenGLWidget::paintGL() {
main_program.setUniformValue("view", view); main_program.setUniformValue("view", view);
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
for (const OpenGLMesh &mesh : meshes) { ground->draw(this, QMatrix4x4());
main_program.setUniformValue("model", mesh.mat); if (painter) painter->draw(this);
glBindVertexArray(mesh.vao); // for (const OpenGLMesh &mesh : meshes) {
mesh.tex->bind(); // main_program.setUniformValue("model", mesh.mat);
glDrawArrays(GL_TRIANGLES, 0, mesh.nverts); // glBindVertexArray(mesh.vao);
mesh.tex->release(); // mesh.tex->bind();
} // glDrawArrays(GL_TRIANGLES, 0, mesh.nverts);
// mesh.tex->release();
// }
main_program.release(); main_program.release();
} }
@ -203,3 +222,13 @@ void OpenGLWidget::wheelEvent(QWheelEvent *e) {
cam_dist -= e->angleDelta().y() / 1000. * cam_dist; cam_dist -= e->angleDelta().y() / 1000. * cam_dist;
update(); update();
} }
void OpenGLWidget::setPainter(const Painter *p) {
painter = p;
}
QOpenGLShaderProgram *OpenGLWidget::getMainProgram() {
return &main_program;
}

View File

@ -13,6 +13,12 @@
#define FOV 70 #define FOV 70
class Painter {
public:
virtual void draw(QOpenGLExtraFunctions *f) const = 0;
};
class OpenGLWidget : public QOpenGLWidget, public QOpenGLExtraFunctions { class OpenGLWidget : public QOpenGLWidget, public QOpenGLExtraFunctions {
Q_OBJECT Q_OBJECT
@ -25,8 +31,12 @@ class OpenGLWidget : public QOpenGLWidget, public QOpenGLExtraFunctions {
GLuint skybox_tex; GLuint skybox_tex;
GLuint skybox_vao; GLuint skybox_vao;
GLuint skybox_vbo; GLuint skybox_vbo;
OpenGLMesh *ground;
void loadSkybox(); void loadSkybox();
void loadGround();
const Painter *painter = nullptr;
protected: protected:
virtual void mousePressEvent(QMouseEvent *e); virtual void mousePressEvent(QMouseEvent *e);
@ -44,6 +54,8 @@ public:
void initializeGL() override; void initializeGL() override;
void resizeGL(int w, int h) override; void resizeGL(int w, int h) override;
void paintGL() override; void paintGL() override;
void setPainter(const Painter *p);
QOpenGLShaderProgram *getMainProgram();
signals: signals:
void initialized(); void initialized();