236 lines
4.9 KiB
C++
236 lines
4.9 KiB
C++
#include "MapView3D.h"
|
|
|
|
|
|
#include "../model/MapModelElement.h"
|
|
#include "../model/MapModel.h"
|
|
|
|
#include "../3DGrid/GridModel.h"
|
|
#include "../3DGrid/GridRenderer.h"
|
|
|
|
MapView3D::MapView3D(QWidget *parent) : QGLWidget(parent) {
|
|
|
|
rot.x = 45;
|
|
rot.y = 0;
|
|
rot.z = 45;
|
|
|
|
center.x = 0;
|
|
center.y = 0;
|
|
center.z = 0;
|
|
|
|
scale.x = 0.05f;
|
|
scale.y = 0.05f;
|
|
scale.z = 0.05f;
|
|
|
|
gridRenderer = new GridRenderer();
|
|
|
|
}
|
|
|
|
|
|
void MapView3D::initializeGL() {
|
|
|
|
//setFormat(QGLFormat(QGL::SampleBuffers));
|
|
|
|
QGLWidget::initializeGL();
|
|
|
|
glCullFace(GL_FRONT);
|
|
//glDisable(GL_CULL_FACE);
|
|
glEnable(GL_CULL_FACE);
|
|
|
|
// culling, lighting, depth-test, ...
|
|
glEnable(GL_DEPTH_TEST);
|
|
//glShadeModel(GL_SMOOTH);
|
|
|
|
// glEnable(GL_MULTISAMPLE);
|
|
// glEnable(GL_LINE_SMOOTH);
|
|
|
|
glEnable(GL_LIGHTING);
|
|
glEnable(GL_LIGHT0);
|
|
glEnable(GL_LIGHT1);
|
|
|
|
|
|
// GLfloat light0_position [] = {+50, 50, +50, 1};
|
|
// GLfloat light1_position [] = {-50, 50, -50, 1};
|
|
|
|
// glLightfv ( GL_LIGHT0, GL_POSITION, light0_position );
|
|
// glLightfv ( GL_LIGHT1, GL_POSITION, light1_position );
|
|
|
|
GLfloat light_diffuse []={ 0.7, 0.7, 0.7, 1.0 };
|
|
glLightfv ( GL_LIGHT0, GL_DIFFUSE, light_diffuse );
|
|
glLightfv ( GL_LIGHT1, GL_DIFFUSE, light_diffuse );
|
|
|
|
|
|
// otherwise scaling the scene kills lighting normals!
|
|
glEnable(GL_NORMALIZE);
|
|
|
|
// allow using glColor3(r,g,b)
|
|
glEnable(GL_COLOR_MATERIAL);
|
|
|
|
// GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
|
|
// GLfloat mat_shininess[] = { 50.0 };
|
|
// glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
|
|
// glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
|
|
|
|
// background color
|
|
qglClearColor(Qt::white);
|
|
|
|
}
|
|
|
|
void MapView3D::paintGL() {
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
glLoadIdentity();
|
|
|
|
|
|
|
|
|
|
glScalef(+1, -1, +1);
|
|
|
|
|
|
// 3) scale
|
|
glScalef(scale.x, scale.y, scale.z);
|
|
|
|
// 2) rotate around center
|
|
glRotatef(rot.x, 1.0, 0.0, 0.0);
|
|
glRotatef(rot.z, 0.0, 1.0, 0.0);
|
|
glRotatef(rot.y, 0.0, 0.0, 1.0);
|
|
|
|
// 1) post translate (mouse moving)
|
|
glTranslatef(center.x, center.z, center.y);
|
|
|
|
// 0) swap the y axis
|
|
//glScalef(+1, -1, +1);
|
|
|
|
GLfloat light0_position [] = {100, 50, 100, 1};
|
|
glLightfv ( GL_LIGHT0, GL_POSITION, light0_position );
|
|
GLfloat light1_position [] = {0, 50, 0, 1};
|
|
glLightfv ( GL_LIGHT1, GL_POSITION, light1_position );
|
|
|
|
|
|
// // 1) translate into center
|
|
// glTranslatef(tra.x, tra.y, tra.z);
|
|
|
|
draw();
|
|
|
|
|
|
}
|
|
|
|
void MapView3D::resizeGL(int width, int height) {
|
|
|
|
//int side = qMin(width, height);
|
|
//glViewport((width - side) / 2, (height - side) / 2, side, side);
|
|
|
|
glViewport(0, 0, width, height);
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
glLoadIdentity();
|
|
//glOrtho(-2, +2, -2, +2, 1.0, 25.0);
|
|
//glFrustum(-1,1, -1,1, 0.1,20);
|
|
viewport.size.x = 2.0f;
|
|
viewport.size.y = 2.0f * height / width;
|
|
const float w = viewport.size.x;
|
|
const float h = viewport.size.y;
|
|
glOrtho(-w, +w, -h, +h, -20, +20);
|
|
//glScalef(1,-1,1);
|
|
|
|
//glFrustum(+w, -w, -h, +h, -20, +20);
|
|
|
|
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
}
|
|
|
|
|
|
void MapView3D::mousePressEvent(QMouseEvent* e) {
|
|
mouse.btn = e->button();
|
|
mouse.x = e->x();
|
|
mouse.y = e->y();
|
|
update();
|
|
}
|
|
|
|
void MapView3D::mouseMoveEvent(QMouseEvent* e) {
|
|
float dx = mouse.x - e->x();
|
|
float dy = mouse.y - e->y();
|
|
if (mouse.btn == 1) {
|
|
//rot.z += dx/2.0f; // upward
|
|
//rot.x -= dy/2.0f;
|
|
rot.z += dx/2.0f; // upward
|
|
rot.x += dy/2.0f;
|
|
} else if (mouse.btn == 4) {
|
|
//Point3 vec(-dx / width() * 2 * viewport.size.x, 0, +dy / height() * 2 * viewport.size.y);
|
|
Point3 vec(-dx / width() * 2 * viewport.size.x, 0, -dy / height() * 2 * viewport.size.y);
|
|
vec = vec.rot(rot.x/180*M_PI, rot.y/180*M_PI, rot.z/180*M_PI);
|
|
vec /= scale;
|
|
center += vec;
|
|
}
|
|
mouse.x = e->x();
|
|
mouse.y = e->y();
|
|
update();
|
|
}
|
|
|
|
void MapView3D::mouseReleaseEvent(QMouseEvent* e) {
|
|
(void) e;
|
|
update();
|
|
}
|
|
|
|
void MapView3D::wheelEvent(QWheelEvent* e) {
|
|
float f = e->delta() / 120.0f;
|
|
scale *= (f > 0) ? (2) : (0.5);
|
|
update();
|
|
}
|
|
|
|
|
|
void MapView3D::showFloorplan() {
|
|
if (gridModel) {delete gridModel; gridModel = nullptr;}
|
|
update();
|
|
}
|
|
|
|
void MapView3D::showGrid() {
|
|
|
|
// delete the previous grid (if any)
|
|
if (gridModel) {delete gridModel; gridModel = nullptr;}
|
|
|
|
// build a new model
|
|
GridModel* gm = new GridModel();
|
|
Floorplan::IndoorMap* im = getModel()->getMap();
|
|
gm->rebuild(im);
|
|
|
|
// remember
|
|
this->gridModel = gm;
|
|
|
|
// update UI
|
|
update();
|
|
|
|
}
|
|
|
|
void MapView3D::draw() {
|
|
|
|
if (gridModel) {
|
|
|
|
// show grid
|
|
gridRenderer->paintGL(gridModel->getGrid());
|
|
|
|
} else {
|
|
|
|
std::vector<MapModelElement*> elements = getModel()->getVisibleElements();
|
|
|
|
// order: transparent last
|
|
auto func = [] (const MapModelElement* e1, const MapModelElement* e2) {
|
|
if (e1->getMV3D() == nullptr) {return false;}
|
|
if (e2->getMV3D() == nullptr) {return true;}
|
|
const bool e1t = e1->getMV3D()->isTransparent();
|
|
const bool e2t = e2->getMV3D()->isTransparent();
|
|
return e1t < e2t;
|
|
};
|
|
|
|
std::sort(elements.begin(), elements.end(), func);
|
|
|
|
// show floorplan
|
|
for (MapModelElement* el : elements) {
|
|
if (el->getMV3D()) {el->getMV3D()->paintGL();}
|
|
}
|
|
|
|
}
|
|
|
|
}
|