149 lines
3.0 KiB
C++
149 lines
3.0 KiB
C++
#include "drone_controller.hh"
|
|
#include "opengl_widget.hh"
|
|
#include "load_obj.hh"
|
|
|
|
#include <QJsonArray>
|
|
#include <QDebug>
|
|
#include <QOpenGLShaderProgram>
|
|
|
|
|
|
const unsigned char DroneController::sphere_neutral[] = {
|
|
166, 166, 166
|
|
};
|
|
|
|
OpenGLMesh *DroneController::sphere = nullptr;
|
|
|
|
|
|
DroneController::DroneController(const QJsonObject &json)
|
|
:framerate(json["framerate"].toInt()),
|
|
sphere_timer(this) {
|
|
sphere_timer.setSingleShot(true);
|
|
connect(&sphere_timer, &QTimer::timeout, [&]() {
|
|
draw_spheres = false;
|
|
OpenGLWidget::instance->update();
|
|
});
|
|
if (sphere == nullptr) {
|
|
OpenGLWidget::instance->makeCurrent();
|
|
sphere = new OpenGLMesh(load_obj(":/mdl/sphere.obj", LOAD_OBJ_NORMALS | LOAD_OBJ_UVS),
|
|
new QOpenGLTexture(QImage(sphere_neutral, 1, 1, QImage::Format_RGB888)),
|
|
OpenGLWidget::instance->getMainProgram());
|
|
OpenGLWidget::instance->makeCurrent();
|
|
}
|
|
QJsonArray ja = json["drones"].toArray();
|
|
drones.reserve(ja.size());
|
|
for (const QJsonValue &o : ja) {
|
|
drones.append(Drone(o.toObject()));
|
|
}
|
|
for (const Drone &d : drones) {
|
|
for (const Waypoint &wp : d.getWaypoints()) {
|
|
if (wp.frame > duration) duration = wp.frame;
|
|
}
|
|
}
|
|
|
|
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);
|
|
if (draw_spheres) {
|
|
mat.scale(sphere_radius);
|
|
sphere->draw(f, mat);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
int DroneController::getDuration() const {
|
|
return duration;
|
|
}
|
|
|
|
|
|
void DroneController::step() {
|
|
for (Drone &d : drones) {
|
|
d.setTo(frame);
|
|
}
|
|
OpenGLWidget::instance->update();
|
|
emit frameChanged(frame);
|
|
if (frame == duration) {
|
|
pause();
|
|
} else {
|
|
frame++;
|
|
}
|
|
}
|
|
|
|
|
|
void DroneController::play() {
|
|
if (!paused) return;
|
|
paused = false;
|
|
timer.start(1000. / framerate);
|
|
emit playing();
|
|
}
|
|
|
|
|
|
void DroneController::pause() {
|
|
if (paused) return;
|
|
paused = true;
|
|
timer.stop();
|
|
emit pausing();
|
|
}
|
|
|
|
|
|
void DroneController::suspend() {
|
|
if (!paused) {
|
|
pause();
|
|
paused = false;
|
|
}
|
|
}
|
|
|
|
|
|
void DroneController::resume() {
|
|
if (!paused) {
|
|
paused = true;
|
|
play();
|
|
}
|
|
}
|
|
|
|
|
|
void DroneController::seek(int frame) {
|
|
if (this->frame == frame) return;
|
|
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 (Drone &a : drones) {
|
|
a.setTo(i);
|
|
for (Drone &b : drones) {
|
|
b.setTo(i);
|
|
if (&a == &b) continue;
|
|
if (collides(a, b, sqDist)) {
|
|
emit collision(a.getId(), b.getId(), i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (Drone &d : drones) {
|
|
d.setTo(frame);
|
|
}
|
|
}
|
|
|
|
|
|
void DroneController::displaySpheres(double sphere_radius) {
|
|
draw_spheres = true;
|
|
this->sphere_radius = sphere_radius;
|
|
sphere_timer.start(1000);
|
|
OpenGLWidget::instance->update();
|
|
}
|
|
|
|
|
|
bool DroneController::collides(const Drone &a, const Drone &b, double sqDist) {
|
|
return (b.getPos() - a.getPos()).lengthSquared() < sqDist;
|
|
}
|