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

View File

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

View File

@ -3,6 +3,7 @@
#include <QJsonArray>
#include <QDebug>
#include <QOpenGLShaderProgram>
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);
}
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 {
return duration;
}
void DroneController::step() {
for (Drone d : drones) {
for (Drone &d : drones) {
d.setTo(frame);
}
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 "opengl_widget.hh"
#include <QJsonObject>
#include <QTimer>
#include <QOpenGLExtraFunctions>
class DroneController : public QObject {
class DroneController : public QObject, public Painter {
Q_OBJECT
int framerate;
@ -22,6 +25,7 @@ class DroneController : public QObject {
public:
DroneController(const QJsonObject &json);
int getDuration() const;
void draw(QOpenGLExtraFunctions *f) const;
signals:
void frameChanged(int frame);

View File

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

View File

@ -4,8 +4,9 @@
#include <QOpenGLFunctions>
OpenGLMesh::OpenGLMesh(QVector<float> verts, QOpenGLTexture *tex)
:tex(tex) {
OpenGLMesh::OpenGLMesh(QVector<float> verts, QOpenGLTexture *tex, QOpenGLShaderProgram *program)
:tex(tex),
program(program) {
OpenGLWidget::instance->makeCurrent();
QOpenGLExtraFunctions *glf = OpenGLWidget::instance;
nverts = verts.size() / 8;
@ -24,3 +25,13 @@ OpenGLMesh::OpenGLMesh(QVector<float> verts, QOpenGLTexture *tex)
glf->glBindVertexArray(0);
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 <QVector>
#include <QOpenGLTexture>
#include <QOpenGLShaderProgram>
#include <QOpenGLExtraFunctions>
struct OpenGLMesh {
GLuint vao, vbo;
unsigned nverts;
QMatrix4x4 mat;
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() {
initializeOpenGLFunctions();
GLint major, minor;
@ -123,6 +139,7 @@ void OpenGLWidget::initializeGL() {
main_program.release();
loadSkybox();
loadGround();
glClearColor(1, 1, 1, 0);
glEnable(GL_DEPTH_TEST);
@ -163,13 +180,15 @@ void OpenGLWidget::paintGL() {
main_program.setUniformValue("view", view);
glActiveTexture(GL_TEXTURE0);
for (const OpenGLMesh &mesh : meshes) {
main_program.setUniformValue("model", mesh.mat);
glBindVertexArray(mesh.vao);
mesh.tex->bind();
glDrawArrays(GL_TRIANGLES, 0, mesh.nverts);
mesh.tex->release();
}
ground->draw(this, QMatrix4x4());
if (painter) painter->draw(this);
// for (const OpenGLMesh &mesh : meshes) {
// main_program.setUniformValue("model", mesh.mat);
// glBindVertexArray(mesh.vao);
// mesh.tex->bind();
// glDrawArrays(GL_TRIANGLES, 0, mesh.nverts);
// mesh.tex->release();
// }
main_program.release();
}
@ -203,3 +222,13 @@ void OpenGLWidget::wheelEvent(QWheelEvent *e) {
cam_dist -= e->angleDelta().y() / 1000. * cam_dist;
update();
}
void OpenGLWidget::setPainter(const Painter *p) {
painter = p;
}
QOpenGLShaderProgram *OpenGLWidget::getMainProgram() {
return &main_program;
}

View File

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