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();