initial commit
This commit is contained in:
commit
7fbe0814d5
16
projet.pro
Normal file
16
projet.pro
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
QT += core gui widgets
|
||||||
|
TARGET = projet
|
||||||
|
TEMPLATE = app
|
||||||
|
DEFINES += QT_DEPRECATED_WARNINGS
|
||||||
|
CONFIG += qt debug
|
||||||
|
|
||||||
|
SOURCES += src/main.cc
|
||||||
|
SOURCES += src/main_window.cc
|
||||||
|
SOURCES += src/opengl_mesh.cc
|
||||||
|
SOURCES += src/opengl_widget.cc
|
||||||
|
SOURCES += src/drone_controller.cc
|
||||||
|
|
||||||
|
HEADERS += src/main_window.hh
|
||||||
|
HEADERS += src/opengl_mesh.hh
|
||||||
|
HEADERS += src/opengl_widget.hh
|
||||||
|
HEADERS += src/drone_controller.hh
|
108
src/boid.cc
Normal file
108
src/boid.cc
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
#include "main_window.hh"
|
||||||
|
|
||||||
|
#include <QVector3D>
|
||||||
|
#include <QRandomGenerator>
|
||||||
|
|
||||||
|
|
||||||
|
struct Fish {
|
||||||
|
QVector3D pos;
|
||||||
|
QVector3D vel;
|
||||||
|
float size;
|
||||||
|
float dist = 10;
|
||||||
|
float sqdist;
|
||||||
|
|
||||||
|
OpenGLMesh mesh;
|
||||||
|
|
||||||
|
Fish(QVector3D pos, OpenGLMesh mesh)
|
||||||
|
:pos(pos),
|
||||||
|
sqdist(dist * dist),
|
||||||
|
mesh(mesh) {}
|
||||||
|
|
||||||
|
void step() {
|
||||||
|
pos += vel;
|
||||||
|
mesh.mat.setToIdentity();
|
||||||
|
QMatrix4x4 rot;
|
||||||
|
rot.lookAt(pos, vel, {0, 1, 0});
|
||||||
|
mesh.mat.translate(pos);
|
||||||
|
// mesh.mat = rot * mesh.mat;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool in_neighborhood(const QVector3D &p) const {
|
||||||
|
return (p - pos).lengthSquared() < sqdist;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct Banc {
|
||||||
|
QVector<Fish> fishes;
|
||||||
|
|
||||||
|
Banc() {}
|
||||||
|
|
||||||
|
Banc(size_t nfishes) {
|
||||||
|
OpenGLMesh fish_mesh = OpenGLMesh({
|
||||||
|
0, .1, 0,
|
||||||
|
-.0866, -.05, 0,
|
||||||
|
.0866, -.05, 0,
|
||||||
|
});
|
||||||
|
QRandomGenerator *rng = QRandomGenerator::global();
|
||||||
|
for (size_t i = 0; i < nfishes; i++) {
|
||||||
|
Fish fish({
|
||||||
|
(float) (rng->generateDouble() * 3 - 1.5),
|
||||||
|
(float) (rng->generateDouble() * 3 - 1.5),
|
||||||
|
(float) (rng->generateDouble() * 3 - 1.5)
|
||||||
|
}, fish_mesh);
|
||||||
|
fishes.append(fish);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void step() {
|
||||||
|
QVector<Fish> neighbors;
|
||||||
|
for (Fish &fish : fishes) {
|
||||||
|
QVector3D neighbors_cog;
|
||||||
|
QVector3D neighbors_vel;
|
||||||
|
size_t nneighbors = 0;
|
||||||
|
for (Fish &fish_b : fishes) {
|
||||||
|
if (fish_b.in_neighborhood(fish.pos)) {
|
||||||
|
nneighbors++;
|
||||||
|
neighbors_cog += fish_b.pos;
|
||||||
|
neighbors_vel += fish_b.vel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
neighbors_cog /= nneighbors;
|
||||||
|
neighbors_vel /= nneighbors;
|
||||||
|
QVector3D v1 = -(fish.pos - neighbors_cog);
|
||||||
|
QVector3D v2 = fish.vel - neighbors_vel;
|
||||||
|
QVector3D v3 = neighbors_cog - fish.pos;
|
||||||
|
QVector3D v = 1.5 * v1 + v2 + v3;
|
||||||
|
float L = .001;
|
||||||
|
fish.vel = (1-L) * fish.vel + L * v;
|
||||||
|
fish.step();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Banc banc;
|
||||||
|
|
||||||
|
void MainWindow::init() {
|
||||||
|
banc = Banc(10);
|
||||||
|
for (Fish &fish : banc.fishes) {
|
||||||
|
glw.meshes.append(&fish.mesh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MainWindow::step() {
|
||||||
|
banc.step();
|
||||||
|
OpenGLWidget::instance->update();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OpenGLWidget::paintGL() {
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
for (const Fish &fish : banc.fishes) {
|
||||||
|
glUniformMatrix4fv(model_attr, 1, GL_FALSE, fish.mesh.mat.data());
|
||||||
|
glBindVertexArray(fish.mesh.vao);
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, fish.mesh.nverts);
|
||||||
|
}
|
||||||
|
}
|
102
src/drone_controller.cc
Normal file
102
src/drone_controller.cc
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
#include "drone_controller.hh"
|
||||||
|
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
|
||||||
|
Waypoint::Waypoint(unsigned frame, QVector3D pos)
|
||||||
|
:frame(frame),
|
||||||
|
pos(pos) {}
|
||||||
|
|
||||||
|
|
||||||
|
Waypoint::Waypoint(const QJsonObject &json)
|
||||||
|
:Waypoint(json["frame"].toInt(),
|
||||||
|
QVector3D(json["position"]["lng_X"].toInt(),
|
||||||
|
json["position"]["alt_Y"].toInt(),
|
||||||
|
json["position"]["lat_Z"].toInt())) {}
|
||||||
|
|
||||||
|
|
||||||
|
Drone::Drone(const QJsonObject &json) {
|
||||||
|
QJsonArray ja = json["waypoints"].toArray();
|
||||||
|
waypoints.reserve(ja.size());
|
||||||
|
for (const QJsonValue &o : ja) {
|
||||||
|
waypoints.append(Waypoint(o.toObject()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const QVector<Waypoint> Drone::getWaypoints() const {
|
||||||
|
return waypoints;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DroneController::DroneController(const QJsonObject &json)
|
||||||
|
:framerate(json["framerate"].toInt()) {
|
||||||
|
|
||||||
|
// TODO: REMOVE!!
|
||||||
|
framerate = 1;
|
||||||
|
|
||||||
|
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);
|
||||||
|
pause();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DroneController::~DroneController() {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int DroneController::getDuration() const {
|
||||||
|
return duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DroneController::step() {
|
||||||
|
qDebug() << "frame " << frame << "/" << duration
|
||||||
|
<< " (" << (double) frame / duration * 100 << "%)";
|
||||||
|
emit frameChanged(frame);
|
||||||
|
frame++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DroneController::play() {
|
||||||
|
paused = false;
|
||||||
|
timer.start(1000. / framerate);
|
||||||
|
qDebug() << "playing";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DroneController::pause() {
|
||||||
|
paused = true;
|
||||||
|
timer.stop();
|
||||||
|
qDebug() << "pausing";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DroneController::suspend() {
|
||||||
|
bool old_paused = paused;
|
||||||
|
pause();
|
||||||
|
paused = old_paused;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DroneController::resume() {
|
||||||
|
if (!paused) play();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DroneController::seek(int frame) {
|
||||||
|
if (this->frame == frame) return;
|
||||||
|
this->frame = frame;
|
||||||
|
step();
|
||||||
|
}
|
57
src/drone_controller.hh
Normal file
57
src/drone_controller.hh
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#ifndef DRONE_CONTROLLER_HH
|
||||||
|
#define DRONE_CONTROLLER_HH
|
||||||
|
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QVector3D>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
|
||||||
|
struct Waypoint {
|
||||||
|
int frame;
|
||||||
|
QVector3D pos;
|
||||||
|
|
||||||
|
Waypoint(unsigned frame, QVector3D pos);
|
||||||
|
Waypoint(const QJsonObject &json);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Drone {
|
||||||
|
QVector<Waypoint> waypoints;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Drone(const QJsonObject &json);
|
||||||
|
const QVector<Waypoint> getWaypoints() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class DroneController : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
int framerate;
|
||||||
|
int frame = 0;
|
||||||
|
int duration = 0;
|
||||||
|
QVector<Drone> drones;
|
||||||
|
QTimer timer;
|
||||||
|
bool paused = true;
|
||||||
|
|
||||||
|
public:
|
||||||
|
DroneController(const QJsonObject &json);
|
||||||
|
~DroneController();
|
||||||
|
int getDuration() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void frameChanged(int frame);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void step();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void play();
|
||||||
|
void pause();
|
||||||
|
void suspend();
|
||||||
|
void resume();
|
||||||
|
void seek(int frame);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
11
src/main.cc
Normal file
11
src/main.cc
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#include "main_window.hh"
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
QApplication app(argc, argv);
|
||||||
|
MainWindow mw;
|
||||||
|
mw.show();
|
||||||
|
return app.exec();
|
||||||
|
}
|
73
src/main_window.cc
Normal file
73
src/main_window.cc
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
#include "main_window.hh"
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QStyle>
|
||||||
|
|
||||||
|
|
||||||
|
MainWindow::MainWindow(QWidget *parent) {
|
||||||
|
(void) parent;
|
||||||
|
connect(&glw, &OpenGLWidget::initialized,
|
||||||
|
this, &MainWindow::onOpenGLWidgetInitialized);
|
||||||
|
// connect(&timer, &QTimer::timeout, this, &MainWindow::step);
|
||||||
|
setCentralWidget(&glw);
|
||||||
|
addToolBar(Qt::TopToolBarArea, &top_tb);
|
||||||
|
open_action = top_tb.addAction("Ouvrir…", [&]() {
|
||||||
|
open(QFileDialog::getOpenFileName(this, "Ouvrir un fichier JSON"));
|
||||||
|
});
|
||||||
|
open_action->setEnabled(false);
|
||||||
|
addToolBar(Qt::BottomToolBarArea, &bottom_tb);
|
||||||
|
playpause_action = bottom_tb.addAction(style()->standardIcon(QStyle::SP_MediaPlay), "",
|
||||||
|
this, &MainWindow::play);
|
||||||
|
playpause_action->setEnabled(false);
|
||||||
|
slider = new QSlider(Qt::Horizontal);
|
||||||
|
bottom_tb.addWidget(slider);
|
||||||
|
slider->setEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MainWindow::play() {
|
||||||
|
dc->play();
|
||||||
|
playpause_action->setIcon(style()->standardIcon(QStyle::SP_MediaPause));
|
||||||
|
disconnect(playpause_action, &QAction::triggered, nullptr, nullptr);
|
||||||
|
connect(playpause_action, &QAction::triggered, this, &MainWindow::pause);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MainWindow::pause() {
|
||||||
|
dc->pause();
|
||||||
|
playpause_action->setIcon(style()->standardIcon(QStyle::SP_MediaPlay));
|
||||||
|
disconnect(playpause_action, &QAction::triggered, nullptr, nullptr);
|
||||||
|
connect(playpause_action, &QAction::triggered, this, &MainWindow::play);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MainWindow::open(const QString &path) {
|
||||||
|
QFile file(path);
|
||||||
|
if (!file.open(QIODevice::ReadOnly)) {
|
||||||
|
qWarning("Impossible d’ouvrir le fichier.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QByteArray data = file.readAll();
|
||||||
|
QJsonDocument json_doc = QJsonDocument::fromJson(data);
|
||||||
|
if (dc) delete dc;
|
||||||
|
dc = new DroneController(json_doc.object());
|
||||||
|
playpause_action->setEnabled(true);
|
||||||
|
slider->setMinimum(0);
|
||||||
|
slider->setMaximum(dc->getDuration());
|
||||||
|
connect(slider, &QSlider::sliderPressed, dc, &DroneController::suspend);
|
||||||
|
connect(slider, &QSlider::sliderReleased, dc, &DroneController::resume);
|
||||||
|
connect(slider, &QSlider::valueChanged, dc, &DroneController::seek);
|
||||||
|
connect(dc, &DroneController::frameChanged, slider, &QSlider::setValue);
|
||||||
|
slider->setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MainWindow::onOpenGLWidgetInitialized() {
|
||||||
|
if (qApp->arguments().size() == 2) {
|
||||||
|
open(qApp->arguments().at(1));
|
||||||
|
}
|
||||||
|
open_action->setEnabled(true);
|
||||||
|
}
|
36
src/main_window.hh
Normal file
36
src/main_window.hh
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#ifndef MAIN_WINDOW_HH
|
||||||
|
#define MAIN_WINDOW_HH
|
||||||
|
|
||||||
|
#include "opengl_widget.hh"
|
||||||
|
#include "drone_controller.hh"
|
||||||
|
|
||||||
|
#include <QMainWindow>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QToolBar>
|
||||||
|
#include <QSlider>
|
||||||
|
|
||||||
|
|
||||||
|
class MainWindow : public QMainWindow {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
OpenGLWidget glw;
|
||||||
|
QTimer timer;
|
||||||
|
QToolBar top_tb;
|
||||||
|
QToolBar bottom_tb;
|
||||||
|
QAction *open_action;
|
||||||
|
QAction *playpause_action;
|
||||||
|
QSlider *slider;
|
||||||
|
DroneController *dc = nullptr;
|
||||||
|
void play();
|
||||||
|
void pause();
|
||||||
|
|
||||||
|
public:
|
||||||
|
MainWindow(QWidget *parent=nullptr);
|
||||||
|
void open(const QString &path);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onOpenGLWidgetInitialized();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
19
src/opengl_mesh.cc
Normal file
19
src/opengl_mesh.cc
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#include "opengl_mesh.hh"
|
||||||
|
|
||||||
|
#include "opengl_widget.hh"
|
||||||
|
|
||||||
|
|
||||||
|
OpenGLMesh::OpenGLMesh(QVector<float> verts) {
|
||||||
|
OpenGLWidget::instance->makeCurrent();
|
||||||
|
QOpenGLFunctions_4_4_Core *glf = OpenGLWidget::instance;
|
||||||
|
nverts = verts.size() / 3;
|
||||||
|
glf->glGenVertexArrays(1, &vao);
|
||||||
|
glf->glGenBuffers(1, &vbo);
|
||||||
|
glf->glBindVertexArray(vao);
|
||||||
|
glf->glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||||
|
glf->glBufferData(GL_ARRAY_BUFFER, nverts * 3 * sizeof (GLfloat), verts.data(), GL_STATIC_DRAW);
|
||||||
|
glf->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
|
||||||
|
glf->glEnableVertexAttribArray(0);
|
||||||
|
glf->glBindVertexArray(0);
|
||||||
|
OpenGLWidget::instance->doneCurrent();
|
||||||
|
}
|
18
src/opengl_mesh.hh
Normal file
18
src/opengl_mesh.hh
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#ifndef MESH_HH
|
||||||
|
#define MESH_HH
|
||||||
|
|
||||||
|
#include <QMatrix4x4>
|
||||||
|
#include <QVector>
|
||||||
|
#include <QOpenGLFunctions>
|
||||||
|
|
||||||
|
|
||||||
|
struct OpenGLMesh {
|
||||||
|
GLuint vao, vbo;
|
||||||
|
unsigned nverts;
|
||||||
|
QMatrix4x4 mat;
|
||||||
|
|
||||||
|
OpenGLMesh(QVector<float> verts);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
143
src/opengl_widget.cc
Normal file
143
src/opengl_widget.cc
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
#include "opengl_widget.hh"
|
||||||
|
|
||||||
|
|
||||||
|
static const GLchar *vertex_shader_source = R"glsl(
|
||||||
|
#version 330 core
|
||||||
|
|
||||||
|
layout(location = 0) in vec3 pos;
|
||||||
|
|
||||||
|
uniform mat4 proj;
|
||||||
|
uniform mat4 view;
|
||||||
|
uniform mat4 model;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
gl_Position = proj * view * model * vec4(pos, 1.0);
|
||||||
|
}
|
||||||
|
)glsl";
|
||||||
|
|
||||||
|
static const GLchar *fragment_shader_source = R"glsl(
|
||||||
|
#version 330 core
|
||||||
|
|
||||||
|
out vec4 final_col;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
final_col = vec4(0, 0, 0, 1);
|
||||||
|
}
|
||||||
|
)glsl";
|
||||||
|
|
||||||
|
|
||||||
|
static void GLAPIENTRY opengl_debug_cb(GLenum source, GLenum type, GLuint id,
|
||||||
|
GLenum severity, GLsizei length,
|
||||||
|
const GLchar* message,
|
||||||
|
const void* userParam) {
|
||||||
|
(void) source; (void) type; (void) id; (void) severity; (void) length;
|
||||||
|
(void) userParam;
|
||||||
|
qDebug() << "OpenGL debug output:" << message;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
OpenGLWidget *OpenGLWidget::instance = nullptr;
|
||||||
|
|
||||||
|
|
||||||
|
OpenGLWidget::OpenGLWidget(QWidget *parent)
|
||||||
|
:QOpenGLWidget(parent) {
|
||||||
|
OpenGLWidget::instance = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
OpenGLWidget::~OpenGLWidget() {
|
||||||
|
OpenGLWidget::instance = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OpenGLWidget::initializeGL() {
|
||||||
|
initializeOpenGLFunctions();
|
||||||
|
GLint major, minor;
|
||||||
|
glGetIntegerv(GL_MAJOR_VERSION, &major);
|
||||||
|
glGetIntegerv(GL_MINOR_VERSION, &minor);
|
||||||
|
qDebug("OpenGL version %d.%d", major, minor);
|
||||||
|
|
||||||
|
glEnable(GL_DEBUG_OUTPUT);
|
||||||
|
glDebugMessageCallback(opengl_debug_cb, 0);
|
||||||
|
|
||||||
|
/* Compile the vertex shader. */
|
||||||
|
GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
|
||||||
|
glShaderSource(vertex_shader, 1, &vertex_shader_source, NULL);
|
||||||
|
glCompileShader(vertex_shader);
|
||||||
|
GLint status;
|
||||||
|
glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &status);
|
||||||
|
if (status != GL_TRUE) {
|
||||||
|
char log[1024];
|
||||||
|
glGetShaderInfoLog(vertex_shader, sizeof log, NULL, log);
|
||||||
|
fprintf(stderr, "Failed to compile the vertex shader: %s\n", log);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compile the fragment shader. */
|
||||||
|
GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||||
|
glShaderSource(fragment_shader, 1, &fragment_shader_source, NULL);
|
||||||
|
glCompileShader(fragment_shader);
|
||||||
|
glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &status);
|
||||||
|
if (status != GL_TRUE) {
|
||||||
|
char log[1024];
|
||||||
|
glGetShaderInfoLog(fragment_shader, sizeof log, NULL, log);
|
||||||
|
fprintf(stderr, "Failed to compile the fragment shader: %s\n", log);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Link the shader program. */
|
||||||
|
GLuint shader_program = glCreateProgram();
|
||||||
|
glAttachShader(shader_program, vertex_shader);
|
||||||
|
glAttachShader(shader_program, fragment_shader);
|
||||||
|
glBindFragDataLocation(shader_program, 0, "out_color");
|
||||||
|
glLinkProgram(shader_program);
|
||||||
|
glGetProgramiv(shader_program, GL_LINK_STATUS, &status);
|
||||||
|
if (status != GL_TRUE) {
|
||||||
|
char log[1024];
|
||||||
|
glGetProgramInfoLog(shader_program, sizeof log, NULL, log);
|
||||||
|
fprintf(stderr, "Failed to link the shader program: %s\n", log);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Use it. */
|
||||||
|
glUseProgram(shader_program);
|
||||||
|
|
||||||
|
/* Get the position attribute. */
|
||||||
|
pos_attr = glGetAttribLocation(shader_program, "pos");
|
||||||
|
|
||||||
|
proj_attr = glGetUniformLocation(shader_program, "proj");
|
||||||
|
view_attr = glGetUniformLocation(shader_program, "view");
|
||||||
|
model_attr = glGetUniformLocation(shader_program, "model");
|
||||||
|
|
||||||
|
QMatrix4x4 view;
|
||||||
|
view.translate(0, 0, 5);
|
||||||
|
glUniformMatrix4fv(view_attr, 1, GL_FALSE, view.data());
|
||||||
|
|
||||||
|
QMatrix4x4 trans;
|
||||||
|
trans.translate(0, 0, -5);
|
||||||
|
glUniformMatrix4fv(view_attr, 1, GL_FALSE, trans.data());
|
||||||
|
|
||||||
|
glClearColor(1, 1, 1, 0);
|
||||||
|
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glEnable(GL_MULTISAMPLE);
|
||||||
|
|
||||||
|
emit initialized();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OpenGLWidget::resizeGL(int w, int h) {
|
||||||
|
QMatrix4x4 projection;
|
||||||
|
projection.perspective(FOV, (float) w/h, .1, 100);
|
||||||
|
glUniformMatrix4fv(proj_attr, 1, GL_FALSE, projection.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OpenGLWidget::paintGL() {
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
for (const OpenGLMesh &mesh : meshes) {
|
||||||
|
glUniformMatrix4fv(model_attr, 1, GL_FALSE, mesh.mat.data());
|
||||||
|
glBindVertexArray(mesh.vao);
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, mesh.nverts);
|
||||||
|
}
|
||||||
|
}
|
35
src/opengl_widget.hh
Normal file
35
src/opengl_widget.hh
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#ifndef OPENGL_WIDGET_HH
|
||||||
|
#define OPENGL_WIDGET_HH
|
||||||
|
|
||||||
|
#include "opengl_mesh.hh"
|
||||||
|
|
||||||
|
#include <QOpenGLWidget>
|
||||||
|
#include <QMatrix4x4>
|
||||||
|
#include <QOpenGLFunctions_4_4_Core>
|
||||||
|
#include <QOpenGLShaderProgram>
|
||||||
|
|
||||||
|
#define FOV 70
|
||||||
|
|
||||||
|
|
||||||
|
class OpenGLWidget : public QOpenGLWidget, public QOpenGLFunctions_4_4_Core {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
GLuint pos_attr, proj_attr, view_attr, model_attr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static OpenGLWidget *instance;
|
||||||
|
|
||||||
|
QVector<OpenGLMesh> meshes;
|
||||||
|
|
||||||
|
OpenGLWidget(QWidget *parent=nullptr);
|
||||||
|
~OpenGLWidget();
|
||||||
|
void initializeGL() override;
|
||||||
|
void resizeGL(int w, int h) override;
|
||||||
|
void paintGL() override;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void initialized();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
1
waypoints.json
Normal file
1
waypoints.json
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user