diff --git a/src/drone.cc b/src/drone.cc index 0be11a6..2c0fad8 100644 --- a/src/drone.cc +++ b/src/drone.cc @@ -4,6 +4,7 @@ #include "opengl_widget.hh" #include +#include 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 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; +} diff --git a/src/drone.hh b/src/drone.hh index 6c43cc1..873bb27 100644 --- a/src/drone.hh +++ b/src/drone.hh @@ -20,7 +20,6 @@ class Drone { static bool mesh_initialized; QVector waypoints; - int mesh_id; QVector3D pos; int id; @@ -29,8 +28,9 @@ public: Drone(const QJsonObject &json); const QVector getWaypoints() const; void setTo(int frame); - QVector3D getPos() const; + const QVector3D getPos() const; int getId() const; + const OpenGLMesh *getMesh() const; }; diff --git a/src/drone_controller.cc b/src/drone_controller.cc index f6edfb6..0be9844 100644 --- a/src/drone_controller.cc +++ b/src/drone_controller.cc @@ -3,6 +3,7 @@ #include #include +#include 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); + } } diff --git a/src/drone_controller.hh b/src/drone_controller.hh index 08dac42..bcf1a1a 100644 --- a/src/drone_controller.hh +++ b/src/drone_controller.hh @@ -3,11 +3,14 @@ #include "drone.hh" +#include "opengl_widget.hh" + #include #include +#include -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); diff --git a/src/main_window.cc b/src/main_window.cc index 26d9601..cd85ae7 100644 --- a/src/main_window.cc +++ b/src/main_window.cc @@ -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(); } diff --git a/src/opengl_mesh.cc b/src/opengl_mesh.cc index 01a73ff..a1f5a23 100644 --- a/src/opengl_mesh.cc +++ b/src/opengl_mesh.cc @@ -4,8 +4,9 @@ #include -OpenGLMesh::OpenGLMesh(QVector verts, QOpenGLTexture *tex) - :tex(tex) { +OpenGLMesh::OpenGLMesh(QVector 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 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(); +} diff --git a/src/opengl_mesh.hh b/src/opengl_mesh.hh index 5038816..7cffece 100644 --- a/src/opengl_mesh.hh +++ b/src/opengl_mesh.hh @@ -4,15 +4,18 @@ #include #include #include +#include +#include struct OpenGLMesh { GLuint vao, vbo; unsigned nverts; - QMatrix4x4 mat; QOpenGLTexture *tex; + QOpenGLShaderProgram *program; - OpenGLMesh(QVector verts, QOpenGLTexture *tex); + OpenGLMesh(QVector verts, QOpenGLTexture *tex, QOpenGLShaderProgram *program); + void draw(QOpenGLExtraFunctions *f, const QMatrix4x4 &mat) const; }; diff --git a/src/opengl_widget.cc b/src/opengl_widget.cc index adc851e..d69af61 100644 --- a/src/opengl_widget.cc +++ b/src/opengl_widget.cc @@ -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; +} diff --git a/src/opengl_widget.hh b/src/opengl_widget.hh index 785a17f..1bc2bbc 100644 --- a/src/opengl_widget.hh +++ b/src/opengl_widget.hh @@ -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();