added main menu added debug display many debug widgets for plotting live data worked on android live sensors added offline-data sensor feeding some dummy data sensors worked on the map display added ui debug for grid-points, particles and weights added a cool dude to display the estimation added real filtering based on the Indoor components c++11 fixes for android compilation online and offline filtering support new resampling technique for testing map loading via dialog
267 lines
6.2 KiB
C++
267 lines
6.2 KiB
C++
#include "MapView.h"
|
|
|
|
#include <QMouseEvent>
|
|
#include <QGLShaderProgram>
|
|
|
|
#include "elements/Walls.h"
|
|
#include "elements/Ground.h"
|
|
#include "elements/Handrails.h"
|
|
#include "elements/Stairs.h"
|
|
#include "elements/Doors.h"
|
|
#include "elements/Path.h"
|
|
#include "elements/ColorPoints.h"
|
|
#include "elements/Object.h"
|
|
|
|
#include <Indoor/data/Timestamp.h>
|
|
#include <QDebug>
|
|
|
|
/**
|
|
* before adding elements to the MapView via setMap(),
|
|
* the MapViews openGL context must be initialized
|
|
* that means: the MapView must have been added to a window,
|
|
* which is already visible!
|
|
*/
|
|
|
|
MapView::MapView(QWidget* parent) : QOpenGLWidget(parent) {
|
|
|
|
|
|
|
|
};
|
|
|
|
void MapView::clear() {
|
|
|
|
for (Renderable* r : elements) {delete r;}
|
|
elements.clear();
|
|
|
|
}
|
|
|
|
void MapView::setMap(Floorplan::IndoorMap* map) {
|
|
|
|
clear();
|
|
|
|
if (!isGLInitialized) {throw Exception("openGL is not yet initialized. add mapView to a visible window!");}
|
|
|
|
// first to be rendered
|
|
this->colorPoints = new ColorPoints();
|
|
elements.push_back(this->colorPoints);
|
|
|
|
//leDude = new Object("/mnt/firma/tmp/3D/minion/minion.obj", "/mnt/firma/tmp/3D/minion/minion.png", "", 0.35);
|
|
leDude = new Object("/mnt/firma/tmp/3D/gnome/gnome.obj", "/mnt/firma/tmp/3D/gnome/gnome_diffuse.jpg", "/mnt/firma/tmp/3D/gnome/gnome_normal.jpg", 0.033);
|
|
//leDude = new Object("/mnt/firma/tmp/3D/squirrel/squirrel.obj", "/mnt/firma/tmp/3D/squirrel/squirrel.jpg", "/mnt/firma/tmp/3D/squirrel/squirrel_normal.jpg", 0.033);
|
|
elements.push_back(leDude);
|
|
|
|
for (Floorplan::Floor* floor : map->floors) {
|
|
elements.push_back(new Ground(floor));
|
|
elements.push_back(new Walls(floor));
|
|
elements.push_back(new Handrails(floor));
|
|
elements.push_back(new Stairs(floor));
|
|
elements.push_back(new Doors(floor));
|
|
}
|
|
|
|
this->path = new Path();
|
|
elements.push_back(this->path);
|
|
|
|
|
|
|
|
// initialize the OpenGL context of all contained elements
|
|
for (Renderable* r : elements) {
|
|
r->initGL();
|
|
}
|
|
|
|
// i want the focus! needed for key-events
|
|
setFocusPolicy(Qt::StrongFocus);
|
|
|
|
}
|
|
|
|
void MapView::setPath(const std::vector<Point3>& path) {
|
|
this->path->set(path);
|
|
}
|
|
|
|
|
|
void MapView::timerEvent(QTimerEvent *) {
|
|
update();
|
|
}
|
|
|
|
void MapView::initializeGL() {
|
|
|
|
initializeOpenGLFunctions();
|
|
|
|
// basic config
|
|
glEnable(GL_DEPTH_TEST);
|
|
glEnable(GL_CULL_FACE);
|
|
|
|
// start background update timer
|
|
const int fps = 25;
|
|
const int interval = 1000 / fps;
|
|
timer.start(interval, this);
|
|
|
|
// OpenGL is now initialized
|
|
isGLInitialized = true;
|
|
|
|
}
|
|
|
|
void MapView::paintGL() {
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
draw();
|
|
}
|
|
|
|
void MapView::resizeGL(int w, int h) {
|
|
|
|
// Calculate aspect ratio
|
|
qreal aspect = qreal(w) / qreal(h ? h : 1);
|
|
|
|
// viewing frustrum [0:50] meter
|
|
const qreal zNear = 0.02, zFar = 50, fov = 50.0;
|
|
|
|
// Reset projection
|
|
matProject.setToIdentity();
|
|
matProject.scale(-1, 1, 1);
|
|
glCullFace(GL_FRONT);
|
|
//matProject.scale(0.05, 0.05, 0.05);
|
|
matProject.perspective(fov, aspect, zNear, zFar);
|
|
//matProject.scale(-0.01, 0.01, 0.01);
|
|
|
|
}
|
|
|
|
void MapView::rebuildLookat() {
|
|
// QVector3D qDir(lookAt.dir.x, lookAt.dir.z, lookAt.dir.y);
|
|
// QVector3D at = QVector3D(lookAt.pos.x, lookAt.pos.z, lookAt.pos.y);
|
|
// QVector3D eye = at + qDir * 0.1;
|
|
// QVector3D up = QVector3D(0,1,0);
|
|
// matView.setToIdentity();
|
|
// //matView.scale(0.01, 0.01, 0.01);
|
|
// matView.lookAt(eye, at, up);
|
|
// //matView.scale(0.99, 1, 1);
|
|
// //matView.translate(0.7, 0, 0);
|
|
// lightPos = eye + QVector3D(0.0, 4.0, 0.0);
|
|
// eyePos = eye;
|
|
|
|
const Point3 dir = lookAt.getDir();
|
|
|
|
QVector3D qDir(dir.x, dir.z, dir.y);
|
|
QVector3D eye(lookAt.eye_m.x, lookAt.eye_m.z, lookAt.eye_m.y);
|
|
QVector3D at = eye + qDir * 0.5;
|
|
QVector3D up = QVector3D(0,1,0);
|
|
matView.setToIdentity();
|
|
matView.lookAt(eye, at, up);
|
|
lightPos = eye + QVector3D(0.0, 0.5, 0.0) + qDir * 1.2;
|
|
eyePos = eye;
|
|
|
|
|
|
|
|
}
|
|
|
|
void MapView::setCurrentEstimation(const Point3 pos, const Point3 dir) {
|
|
const float angle = std::atan2(dir.y, dir.x) * 180 / M_PI;
|
|
if (leDude) {
|
|
leDude->setPosition(pos.x, pos.y, pos.z);
|
|
leDude->setRotation(0, 0, -angle + 90);
|
|
}
|
|
}
|
|
|
|
void MapView::setLookAt(const Point3 pos_m, const Point3 dir) {
|
|
lookAt.eye_m = pos_m + dir * 0.1;
|
|
lookAt.dir = dir;
|
|
rebuildLookat();
|
|
}
|
|
|
|
void MapView::setLookDir(const Point3 dir) {
|
|
lookAt.dir = dir;
|
|
rebuildLookat();
|
|
}
|
|
|
|
void MapView::setLookEye(const Point3 eye_m) {
|
|
lookAt.eye_m = eye_m;
|
|
rebuildLookat();
|
|
}
|
|
|
|
|
|
|
|
void MapView::mousePressEvent(QMouseEvent* evt) {
|
|
mouseState.down = true;
|
|
mouseState.x = evt->x();
|
|
mouseState.y = evt->y();
|
|
}
|
|
|
|
void MapView::mouseMoveEvent(QMouseEvent* evt) {
|
|
|
|
const float dx = evt->x() - mouseState.x;
|
|
const float dy = evt->y() - mouseState.y;
|
|
|
|
// PI*0.3 head movement left/right and up/down
|
|
const float yFac = (this->height() / 2) / (M_PI * 0.3);
|
|
const float xFac = (this->width() / 2) / (M_PI * 0.3);
|
|
|
|
lookAt.dirOffset = Point3(0, std::sin(dx/xFac), std::sin(-dy/yFac));
|
|
rebuildLookat();
|
|
|
|
}
|
|
|
|
void MapView::mouseReleaseEvent(QMouseEvent* evt) {
|
|
mouseState.down = false;
|
|
}
|
|
|
|
|
|
void MapView::keyPressEvent(QKeyEvent* evt) {
|
|
|
|
if (evt->key() == Qt::Key_W) {lookAt.eye_m += lookAt.getDir(); rebuildLookat();}
|
|
if (evt->key() == Qt::Key_S) {lookAt.eye_m -= lookAt.getDir(); rebuildLookat();}
|
|
|
|
|
|
}
|
|
|
|
void MapView::toggleRenderMode() {
|
|
|
|
renderMode = (RenderMode) (((int)renderMode + 1) % 3);
|
|
|
|
for (Renderable* r : elements) {
|
|
if (renderMode == RenderMode::OUTLINE) {
|
|
r->setOutlineOnly(true);
|
|
} else {
|
|
r->setOutlineOnly(false);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void MapView::draw() {
|
|
|
|
//const Timestamp ts1 = Timestamp::fromUnixTime();
|
|
|
|
// clear everything
|
|
glClearColor(0,0,0,1);
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
if (renderMode == RenderMode::TRANSPARENT) {
|
|
glEnable(GL_BLEND);
|
|
} else {
|
|
glDisable(GL_BLEND);
|
|
}
|
|
|
|
glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
|
|
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
|
|
|
|
|
|
|
|
for (Renderable* r : elements) {
|
|
|
|
QOpenGLShaderProgram& program = r->getProgram();
|
|
program.bind();
|
|
|
|
// set the matrices
|
|
program.setUniformValue("m_matrix", r->modelMatrix.mat);
|
|
program.setUniformValue("mv_matrix", matView * r->modelMatrix.mat);
|
|
program.setUniformValue("mvp_matrix", matProject * matView * r->modelMatrix.mat);
|
|
program.setUniformValue("lightWorldPos", lightPos);
|
|
program.setUniformValue("eyeWorldPos", eyePos);
|
|
|
|
r->render();
|
|
|
|
}
|
|
|
|
//const Timestamp ts2 = Timestamp::fromUnixTime();
|
|
//qDebug("%d ms", (ts2-ts1).ms());
|
|
|
|
|
|
}
|