From 5326f294ceb95f1b535d145b5fdbdc221f560d53 Mon Sep 17 00:00:00 2001 From: ccolin Date: Sun, 3 Jan 2021 19:55:04 +0100 Subject: [PATCH] add option to draw trajectories --- shaders/line.frag | 5 +++++ shaders/line.vert | 8 +++++++ shaders/shaders_resources.qrc | 2 ++ src/drone_controller.cc | 41 +++++++++++++++++++++++++++++++++++ src/drone_controller.hh | 4 ++++ src/main_window.cc | 2 ++ src/opengl_mesh.cc | 1 + src/opengl_widget.cc | 23 ++++++++++++++++++++ src/opengl_widget.hh | 2 ++ 9 files changed, 88 insertions(+) create mode 100644 shaders/line.frag create mode 100644 shaders/line.vert diff --git a/shaders/line.frag b/shaders/line.frag new file mode 100644 index 0000000..ba83ada --- /dev/null +++ b/shaders/line.frag @@ -0,0 +1,5 @@ +uniform vec3 color; + +void main() { + gl_FragColor = vec4(color, 1); +} diff --git a/shaders/line.vert b/shaders/line.vert new file mode 100644 index 0000000..b41673c --- /dev/null +++ b/shaders/line.vert @@ -0,0 +1,8 @@ +attribute vec3 in_pos; + +uniform mat4 proj; +uniform mat4 view; + +void main() { + gl_Position = proj * view * vec4(in_pos, 1.0); +} diff --git a/shaders/shaders_resources.qrc b/shaders/shaders_resources.qrc index 1dc5251..ea905c1 100644 --- a/shaders/shaders_resources.qrc +++ b/shaders/shaders_resources.qrc @@ -5,5 +5,7 @@ main.frag skybox.vert skybox.frag + line.vert + line.frag diff --git a/src/drone_controller.cc b/src/drone_controller.cc index 512ad23..dbe9a00 100644 --- a/src/drone_controller.cc +++ b/src/drone_controller.cc @@ -44,6 +44,38 @@ DroneController::DroneController(const QJsonObject &json) } +void DroneController::drawTrajectory(QOpenGLExtraFunctions *f, const Drone &d) const { + OpenGLWidget::instance->getLineProgram()->bind(); + OpenGLWidget::instance->getLineProgram()->setUniformValue("color", 1, 0, .532); + size_t trajectory_len = 1; + for (const Waypoint &wp : d.getWaypoints()) { + if (wp.frame > frame) break; + trajectory_len++; + } + GLfloat trajectory[trajectory_len * 3] = {0}; + size_t i = 0; + for (const Waypoint &wp : d.getWaypoints()) { + if (wp.frame > frame) break; + trajectory[i] = wp.pos.x(); + trajectory[i + 1] = wp.pos.y(); + trajectory[i + 2] = wp.pos.z(); + i += 3; + } + trajectory[i] = d.getPos().x(); + trajectory[i + 1] = d.getPos().y(); + trajectory[i + 2] = d.getPos().z(); + f->glEnableVertexAttribArray(0); + f->glBindBuffer(GL_ARRAY_BUFFER, 0); + f->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, trajectory); + glLineWidth(2); + f->glDisable(GL_CULL_FACE); + f->glDrawArrays(GL_LINE_STRIP, 0, trajectory_len); + f->glEnable(GL_CULL_FACE); + OpenGLWidget::instance->getLineProgram()->release(); + OpenGLWidget::instance->getMainProgram()->bind(); +} + + void DroneController::draw(QOpenGLExtraFunctions *f) const { const QVector> &col = collisions[frame]; for (const Drone &d : drones) { @@ -60,6 +92,9 @@ void DroneController::draw(QOpenGLExtraFunctions *f) const { sphere->draw(f, mat); } OpenGLWidget::instance->getMainProgram()->setUniformValue("highlight", false); + if (draw_trajectories) { + drawTrajectory(f, d); + } } } @@ -155,3 +190,9 @@ void DroneController::displaySpheres(double sphere_radius) { bool DroneController::collides(const Drone &a, const Drone &b, double sqDist) { return (b.getPos() - a.getPos()).lengthSquared() < sqDist; } + + +void DroneController::setDrawTrajectories(bool enable) { + draw_trajectories = enable; + OpenGLWidget::instance->update(); +} diff --git a/src/drone_controller.hh b/src/drone_controller.hh index 11d7395..7ff087a 100644 --- a/src/drone_controller.hh +++ b/src/drone_controller.hh @@ -23,12 +23,15 @@ class DroneController : public QObject, public Painter { double sphere_radius = 0; QTimer sphere_timer; QMap>> collisions; + bool draw_trajectories = false; static OpenGLMesh *sphere; static const unsigned char sphere_neutral[]; static bool collides(const Drone &a, const Drone &b, double radius); + void drawTrajectory(QOpenGLExtraFunctions *f, const Drone &d) const; + public: DroneController(const QJsonObject &json); int getDuration() const; @@ -51,6 +54,7 @@ public slots: void seek(int frame); void computeCollisions(double sphere_radius); void displaySpheres(double sphere_radius); + void setDrawTrajectories(bool enable); }; diff --git a/src/main_window.cc b/src/main_window.cc index 9b4dff0..0471641 100644 --- a/src/main_window.cc +++ b/src/main_window.cc @@ -89,6 +89,8 @@ void MainWindow::open(const QString &path) { dc, &DroneController::computeCollisions); connect(settings_pane, &SettingsPane::sphereRadiusChanged, dc, &DroneController::displaySpheres); + connect(settings_pane, &SettingsPane::toggledTrajectories, + dc, &DroneController::setDrawTrajectories); settings_pane->setEnabled(true); glw.setPainter(dc); diff --git a/src/opengl_mesh.cc b/src/opengl_mesh.cc index f77a70a..8ad3336 100644 --- a/src/opengl_mesh.cc +++ b/src/opengl_mesh.cc @@ -32,4 +32,5 @@ void OpenGLMesh::draw(QOpenGLExtraFunctions *f, const QMatrix4x4 &mat) const { if (tex) tex->bind(); f->glDrawArrays(GL_TRIANGLES, 0, nverts); if (tex) tex->release(); + f->glBindVertexArray(0); } diff --git a/src/opengl_widget.cc b/src/opengl_widget.cc index 29361c5..fb318ab 100644 --- a/src/opengl_widget.cc +++ b/src/opengl_widget.cc @@ -144,6 +144,20 @@ void OpenGLWidget::initializeGL() { main_program.setUniformValue("tex", 0); main_program.release(); + if (!line_program.addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/line.vert")) { + qFatal("Error compiling line.vert: %s", line_program.log().toLocal8Bit().constData()); + } + if (!line_program.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/line.frag")) { + qFatal("Error compiling line.frag: %s", line_program.log().toLocal8Bit().constData()); + } + line_program.bindAttributeLocation("in_pos", 0); + if (!line_program.link()) { + qFatal("Error linking the line shader program: %s", line_program.log().toLocal8Bit().constData()); + } + line_program.bind(); + line_program.setUniformValue("color", 0, 0, 0); + line_program.release(); + loadSkybox(); loadGround(); @@ -183,6 +197,11 @@ void OpenGLWidget::paintGL() { glDepthMask(GL_TRUE); glDepthFunc(GL_LESS); + line_program.bind(); + line_program.setUniformValue("proj", proj); + line_program.setUniformValue("view", view); + line_program.release(); + main_program.bind(); main_program.setUniformValue("proj", proj); main_program.setUniformValue("view", view); @@ -232,3 +251,7 @@ void OpenGLWidget::setPainter(const Painter *p) { QOpenGLShaderProgram *OpenGLWidget::getMainProgram() { return &main_program; } + +QOpenGLShaderProgram *OpenGLWidget::getLineProgram() { + return &line_program; +} diff --git a/src/opengl_widget.hh b/src/opengl_widget.hh index 1bc2bbc..04e2ffc 100644 --- a/src/opengl_widget.hh +++ b/src/opengl_widget.hh @@ -28,6 +28,7 @@ class OpenGLWidget : public QOpenGLWidget, public QOpenGLExtraFunctions { QOpenGLShaderProgram main_program; QOpenGLShaderProgram skybox_program; + QOpenGLShaderProgram line_program; GLuint skybox_tex; GLuint skybox_vao; GLuint skybox_vbo; @@ -56,6 +57,7 @@ public: void paintGL() override; void setPainter(const Painter *p); QOpenGLShaderProgram *getMainProgram(); + QOpenGLShaderProgram *getLineProgram(); signals: void initialized();