add basic collision detection
This commit is contained in:
parent
87f8c49cff
commit
861d505606
@ -12,9 +12,11 @@ SOURCES += src/opengl_mesh.cc
|
||||
SOURCES += src/opengl_widget.cc
|
||||
SOURCES += src/drone_controller.cc
|
||||
SOURCES += src/load_obj.cc
|
||||
SOURCES += src/settings_pane.cc
|
||||
|
||||
HEADERS += src/main_window.hh
|
||||
HEADERS += src/opengl_mesh.hh
|
||||
HEADERS += src/opengl_widget.hh
|
||||
HEADERS += src/drone_controller.hh
|
||||
HEADERS += src/load_obj.hh
|
||||
HEADERS += src/settings_pane.hh
|
||||
|
@ -22,7 +22,8 @@ Waypoint::Waypoint(const QJsonObject &json)
|
||||
bool Drone::mesh_initialized = false;
|
||||
OpenGLMesh *Drone::mesh = nullptr;
|
||||
|
||||
Drone::Drone() {
|
||||
Drone::Drone(int id)
|
||||
:id(id) {
|
||||
if (!mesh_initialized) {
|
||||
QVector<GLfloat> verts = load_obj(":/mdl/dji600.obj", LOAD_OBJ_NORMALS | LOAD_OBJ_UVS);
|
||||
QOpenGLTexture *texture = new QOpenGLTexture(QImage(":/img/dji600.jpg").mirrored());
|
||||
@ -35,7 +36,7 @@ Drone::Drone() {
|
||||
|
||||
|
||||
Drone::Drone(const QJsonObject &json)
|
||||
:Drone() {
|
||||
:Drone(json["id"].toInt()) {
|
||||
QJsonArray ja = json["waypoints"].toArray();
|
||||
waypoints.reserve(ja.size());
|
||||
for (const QJsonValue &o : ja) {
|
||||
@ -65,12 +66,23 @@ void Drone::setTo(int frame) {
|
||||
OpenGLMesh &mesh = OpenGLWidget::instance->meshes[mesh_id];
|
||||
mesh.mat = QMatrix4x4();
|
||||
if (next > -1 && prev == -1) {
|
||||
mesh.mat.translate(next_wp->pos);
|
||||
pos = next_wp->pos;
|
||||
} else if (prev > -1 && next == -1) {
|
||||
mesh.mat.translate(prev_wp->pos);
|
||||
pos = prev_wp->pos;
|
||||
} else {
|
||||
mesh.mat.translate(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 {
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
int Drone::getId() const {
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
@ -164,3 +176,23 @@ void DroneController::seek(int frame) {
|
||||
this->frame = frame;
|
||||
step();
|
||||
}
|
||||
|
||||
|
||||
void DroneController::computeCollisions(double sphere_radius) {
|
||||
double sqDist = sphere_radius * sphere_radius * 2;
|
||||
for (int i = 0; i < duration; i++) {
|
||||
for (const Drone &a : drones) {
|
||||
for (const Drone &b : drones) {
|
||||
if (&a == &b) continue;
|
||||
if (collides(a, b, sqDist)) {
|
||||
emit collision(a.getId(), b.getId(), frame);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool DroneController::collides(const Drone &a, const Drone &b, double sqDist) {
|
||||
return (b.getPos() - a.getPos()).lengthSquared() < sqDist;
|
||||
}
|
||||
|
@ -29,12 +29,16 @@ class Drone {
|
||||
|
||||
QVector<Waypoint> waypoints;
|
||||
int mesh_id;
|
||||
QVector3D pos;
|
||||
int id;
|
||||
|
||||
public:
|
||||
Drone();
|
||||
Drone(int id);
|
||||
Drone(const QJsonObject &json);
|
||||
const QVector<Waypoint> getWaypoints() const;
|
||||
void setTo(int frame);
|
||||
QVector3D getPos() const;
|
||||
int getId() const;
|
||||
};
|
||||
|
||||
|
||||
@ -48,6 +52,8 @@ class DroneController : public QObject {
|
||||
QTimer timer;
|
||||
bool paused = true;
|
||||
|
||||
static bool collides(const Drone &a, const Drone &b, double radius);
|
||||
|
||||
public:
|
||||
DroneController(const QJsonObject &json);
|
||||
int getDuration() const;
|
||||
@ -56,6 +62,7 @@ signals:
|
||||
void frameChanged(int frame);
|
||||
void playing();
|
||||
void pausing();
|
||||
void collision(int idA, int idB, int frame);
|
||||
|
||||
private slots:
|
||||
void step();
|
||||
@ -66,6 +73,7 @@ public slots:
|
||||
void suspend();
|
||||
void resume();
|
||||
void seek(int frame);
|
||||
void computeCollisions(double sphere_radius);
|
||||
};
|
||||
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <QFileDialog>
|
||||
#include <QJsonDocument>
|
||||
#include <QStyle>
|
||||
#include <QDockWidget>
|
||||
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent) {
|
||||
@ -25,6 +26,12 @@ MainWindow::MainWindow(QWidget *parent) {
|
||||
slider = new QSlider(Qt::Horizontal);
|
||||
bottom_tb.addWidget(slider);
|
||||
slider->setEnabled(false);
|
||||
|
||||
QDockWidget *dock = new QDockWidget("Outils", this);
|
||||
dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
|
||||
settings_pane = new SettingsPane();
|
||||
dock->setWidget(settings_pane);
|
||||
addDockWidget(Qt::RightDockWidgetArea, dock);
|
||||
}
|
||||
|
||||
|
||||
@ -65,6 +72,8 @@ void MainWindow::open(const QString &path) {
|
||||
connect(slider, &QSlider::sliderReleased, dc, &DroneController::resume);
|
||||
connect(slider, &QSlider::valueChanged, dc, &DroneController::seek);
|
||||
connect(dc, &DroneController::frameChanged, slider, &QSlider::setValue);
|
||||
connect(dc, &DroneController::collision, settings_pane, &SettingsPane::addCollision);
|
||||
dc->computeCollisions(10);
|
||||
pause();
|
||||
slider->setEnabled(true);
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include "opengl_widget.hh"
|
||||
#include "drone_controller.hh"
|
||||
#include "settings_pane.hh"
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QTimer>
|
||||
@ -20,6 +21,7 @@ class MainWindow : public QMainWindow {
|
||||
QAction *open_action;
|
||||
QAction *playpause_action;
|
||||
QSlider *slider;
|
||||
SettingsPane *settings_pane;
|
||||
DroneController *dc = nullptr;
|
||||
void play();
|
||||
void pause();
|
||||
|
44
src/settings_pane.cc
Normal file
44
src/settings_pane.cc
Normal file
@ -0,0 +1,44 @@
|
||||
#include "settings_pane.hh"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QDoubleSpinBox>
|
||||
#include <QFormLayout>
|
||||
|
||||
|
||||
SettingsPane::SettingsPane(QWidget *parent)
|
||||
:QWidget(parent) {
|
||||
QDoubleSpinBox *sphere_radius = new QDoubleSpinBox();
|
||||
QCheckBox *show_trajectories = new QCheckBox();
|
||||
QCheckBox *show_support_lines = new QCheckBox();
|
||||
collisions = new QListWidget();
|
||||
|
||||
connect(sphere_radius, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
|
||||
this, &SettingsPane::sphereRadiusChanged);
|
||||
connect(show_trajectories, &QCheckBox::stateChanged,
|
||||
this, &SettingsPane::toggledTrajectories);
|
||||
connect(show_support_lines, &QCheckBox::stateChanged,
|
||||
this, &SettingsPane::toggledSupportLines);
|
||||
|
||||
QFormLayout *layout = new QFormLayout;
|
||||
layout->addRow("Taille de la sphère de collision", sphere_radius);
|
||||
layout->addRow("Afficher les trajectoires", show_trajectories);
|
||||
layout->addRow("Afficher les lignes de support", show_support_lines);
|
||||
layout->addRow(collisions);
|
||||
setLayout(layout);
|
||||
}
|
||||
|
||||
|
||||
void SettingsPane::addCollision(int idA, int idB, int frame) {
|
||||
QListWidgetItem *item = new QListWidgetItem(QString::number(frame) + ": "
|
||||
+ QString::number(idA) + " / " + QString::number(idB));
|
||||
item->setFlags(Qt::ItemIsEnabled | Qt::ItemNeverHasChildren);
|
||||
collisions->addItem(item);
|
||||
}
|
||||
|
||||
|
||||
void SettingsPane::clearCollisions() {
|
||||
QListWidgetItem *item;
|
||||
while ((item = collisions->takeItem(0)) != nullptr) {
|
||||
delete item;
|
||||
}
|
||||
}
|
27
src/settings_pane.hh
Normal file
27
src/settings_pane.hh
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef SETTINGS_PANE_HH
|
||||
#define SETTINGS_PANE_HH
|
||||
|
||||
#include <QWidget>
|
||||
#include <QListWidget>
|
||||
|
||||
|
||||
class SettingsPane : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
QListWidget *collisions = nullptr;
|
||||
|
||||
public:
|
||||
SettingsPane(QWidget *parent=nullptr);
|
||||
|
||||
public slots:
|
||||
void addCollision(int idA, int idB, int frame);
|
||||
void clearCollisions();
|
||||
|
||||
signals:
|
||||
void sphereRadiusChanged(double sqRadius);
|
||||
void toggledTrajectories(int shown);
|
||||
void toggledSupportLines(int shown);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user