285 lines
7.1 KiB
C++
285 lines
7.1 KiB
C++
/*
|
|
QGLView
|
|
Ivan Pelipenko peri4ko@yandex.ru
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU Lesser General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "qglview.h"
|
|
#include "glmesh.h"
|
|
#include "gltexture_manager.h"
|
|
#include <chunkstream.h>
|
|
#include <qad_types.h>
|
|
#include <QApplication>
|
|
#include <QOpenGLTexture>
|
|
#include <QKeyEvent>
|
|
|
|
using namespace QGLEngineShaders;
|
|
|
|
|
|
QGLView::QGLView(): OpenGLWindow(), renderer_(this), mouse(this) {
|
|
setIcon(QIcon(":/icons/qglview.png"));
|
|
is_init = false;
|
|
timer = 0;
|
|
hoverHaloColor_ = QColor(195, 140, 255);
|
|
selectionHaloColor_ = QColor(175, 255, 140);
|
|
lineWidth_ = 1.;
|
|
max_anisotropic = 1;
|
|
max_texture_chanels = 8;
|
|
lightEnabled_ = true;
|
|
shaders_supported = false;
|
|
fps_cnt = 0;
|
|
fps_tm = fps_ = 0.;
|
|
fogColor_ = Qt::darkGray;
|
|
fogDensity_ = 0.;
|
|
fogDecay_ = 10.;
|
|
hoverHaloFill_ = selectionHaloFill_ = 0.15f;
|
|
//lmode = Simple;
|
|
setFeature(qglFXAA, false);
|
|
setFeature(qglAnisotropicLevel, 8);
|
|
setFeature(qglEyeAccomodationEnabled, false);
|
|
setFeature(qglEyeAccomodationTime, 16.);
|
|
setFeature(qglEyeAccomodationMaxSpeed, 0.2);
|
|
setFeature(qglBloomEnabled, false);
|
|
setFeature(qglBloomThreshold, 0.9);
|
|
setFeature(qglBloomFactor, 1.);
|
|
setFeature(qglBloomRadius, 8);
|
|
setFeature(qglMotionBlurEnabled, false);
|
|
setFeature(qglMotionBlurFactor, 1.);
|
|
setFeature(qglMotionBlurSteps, 8);
|
|
setFeature(qglShadowsEnabled, false);
|
|
setFeature(qglShadowsMapSize, 512);
|
|
setFeature(qglShadowsSoftEnabled, true);
|
|
setFeature(qglReflectionsEnabled, false);
|
|
setFeature(qglReflectionsBlur, true);
|
|
setFeature(qglSSAOEnabled, false);
|
|
setFeature(qglSSAORadius, 5);
|
|
setFeature(qglDepthOfFieldEnabled, false);
|
|
setFeature(qglDepthOfFieldAutoFocusEnabled, true);
|
|
setFeature(qglDepthOfFieldAutoFocusSpeed, 0.1);
|
|
setFeature(qglDepthOfFieldFocus, 1.);
|
|
setFeature(qglDepthOfFieldDiaphragm, 8.);
|
|
hoverHalo_ = selectionHalo_ = true;
|
|
fogEnabled_ = shaders_bind = false;
|
|
rmode = ObjectBase::Fill;
|
|
scene_ = new Scene();
|
|
connect(scene_, SIGNAL(selectionChanged()), this, SIGNAL(selectionChanged()));
|
|
connect(scene_, SIGNAL(__destroyed()), this, SLOT(__destroyed()));
|
|
connect(scene_, SIGNAL(__objectDeleted(ObjectBase*)), this, SLOT(__objectDeleted(ObjectBase*)));
|
|
default_camera = new Camera();
|
|
default_camera->setPos(QVector3D(2, 2, 2));
|
|
default_camera->setAim(QVector3D());
|
|
camera_ = default_camera;
|
|
// qDebug() << camera_->aim();
|
|
default_camera->setName("Camera");
|
|
emit cameraPosChanged(default_camera->pos());
|
|
|
|
Mesh * m = Primitive::cube(10, 10, 10);
|
|
m->flipNormals();
|
|
ObjectBase * o = new ObjectBase(m);
|
|
o->setColor(Qt::cyan);
|
|
scene()->addObject(o);
|
|
delete m;
|
|
}
|
|
|
|
|
|
QGLView::~QGLView() {
|
|
stop();
|
|
scene_->clear();
|
|
delete scene_;
|
|
delete default_camera;
|
|
}
|
|
|
|
|
|
void QGLView::stop() {
|
|
if (timer) killTimer(timer);
|
|
}
|
|
|
|
|
|
void QGLView::start(float freq) {
|
|
timer = startTimer(freq <= 0.f ? 0 : int(1000.f / freq));
|
|
}
|
|
|
|
|
|
QList<Light * > QGLView::selectedLights() const {
|
|
QList<Light * > ret;
|
|
ObjectBaseList sol = scene_->selectedObjects();
|
|
foreach (ObjectBase * o, sol)
|
|
if (o->type() == ObjectBase::glLight)
|
|
ret << (Light*)o;
|
|
return ret;
|
|
}
|
|
|
|
|
|
QList<Camera * > QGLView::selectedCameras() const {
|
|
QList<Camera * > ret;
|
|
ObjectBaseList sol = scene_->selectedObjects();
|
|
for (ObjectBase * o : sol) {
|
|
if (o->type() == ObjectBase::glCamera) ret << (Camera*)o;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
|
|
void QGLView::resizeEvent(QResizeEvent * e) {
|
|
renderLater();
|
|
mouse.resize();
|
|
}
|
|
|
|
|
|
void QGLView::timerEvent(QTimerEvent *) {
|
|
renderNow();
|
|
Qt::KeyboardModifiers km = QApplication::keyboardModifiers();
|
|
foreach (int i, keys_)
|
|
emit keyEvent((Qt::Key)i, km);
|
|
}
|
|
|
|
|
|
void QGLView::render() {
|
|
resizeGL(width(), height());
|
|
emit glBeginPaint();
|
|
renderer_.mouse_pos = mapFromGlobal(QCursor::pos());
|
|
renderer_.renderScene();
|
|
emit glEndPaint();
|
|
fps_tm = time.elapsed();
|
|
fps_cnt++;
|
|
if (fps_tm < 1000.) return;
|
|
time.restart();
|
|
fps_ = fps_cnt / fps_tm * 1000.;
|
|
fps_tm = 0.;
|
|
fps_cnt = 0;
|
|
}
|
|
|
|
|
|
void QGLView::initialize() {
|
|
checkCaps();
|
|
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
glDisable(GL_MULTISAMPLE);
|
|
glDisable(GL_BLEND);
|
|
glEnable(GL_TEXTURE_2D);
|
|
glEnable(GL_TEXTURE_CUBE_MAP);
|
|
glEnable(GL_TEXTURE_MAX_ANISOTROPY_EXT);
|
|
glEnable(GL_CULL_FACE);
|
|
glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
|
|
glCullFace(GL_BACK);
|
|
renderer_.reloadShaders();
|
|
renderer_.init(width(), height());
|
|
scene_->reinitAll();
|
|
is_init = true;
|
|
prev_size = QSize();
|
|
emit glInitializeDone();
|
|
}
|
|
|
|
|
|
void QGLView::checkCaps() {
|
|
glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &max_anisotropic);
|
|
shaders_supported = QOpenGLShaderProgram::hasOpenGLShaderPrograms();
|
|
}
|
|
|
|
|
|
void QGLView::__destroyed() {
|
|
renderer_.rend_mat.mat_thumbnails.clear();
|
|
mouse.hov_objects.clear();
|
|
}
|
|
|
|
|
|
void QGLView::__objectDeleted(ObjectBase * o) {
|
|
if (o == camera_) setDefaultCamera();
|
|
}
|
|
|
|
|
|
void QGLView::resizeGL(int width, int height) {
|
|
if (!is_init) return;
|
|
if (width <= 0 || height <= 0) return;
|
|
if (prev_size == QSize(width, height)) return;
|
|
prev_size = QSize(width, height);
|
|
aspect = float(width) / float(height);
|
|
renderer_.resize(width, height);
|
|
//qDebug() << "resize" << width << height;
|
|
iaspect = (aspect == 0.f) ? 0. : 1 / aspect;
|
|
glViewport(0, 0, width, height);
|
|
emit glResize(width, height);
|
|
}
|
|
|
|
|
|
void QGLView::keyPressEvent(QKeyEvent * e) {
|
|
emit glKeyPressEvent(e);
|
|
if (e->key() > 0) keys_.insert(e->key());
|
|
if (e->key() == Qt::Key_F11) {
|
|
emit doubleClick();
|
|
}
|
|
}
|
|
|
|
|
|
void QGLView::keyReleaseEvent(QKeyEvent * e) {
|
|
emit glKeyReleaseEvent(e);
|
|
keys_.remove(e->key());
|
|
}
|
|
|
|
|
|
void QGLView::focusOutEvent(QFocusEvent *) {
|
|
keys_.clear();
|
|
}
|
|
|
|
|
|
void QGLView::focusOn(const Box3D & bb) {
|
|
if (bb.isEmpty() || !camera()) return;
|
|
double size = qMax(qMax(bb.width, bb.length), bb.height);
|
|
camera()->setAim(bb.center());
|
|
camera()->flyToDistance(size * 1.25);
|
|
}
|
|
|
|
|
|
QByteArray QGLView::saveCamera() {
|
|
ChunkStream cs;
|
|
const Camera * c = default_camera;
|
|
cs.add(1, c->pos()).add(2, c->aim()).add(3, c->rotation()).add(4, c->FOV());
|
|
return cs.data();
|
|
}
|
|
|
|
|
|
void QGLView::restoreCamera(const QByteArray & ba) {
|
|
if (ba.isEmpty()) return;
|
|
setDefaultCamera();
|
|
Camera * c = default_camera;
|
|
QVector3D pos(c->pos()), aim(c->aim()), ang(c->rotation());
|
|
float fov(c->FOV());
|
|
ChunkStream cs(ba);
|
|
cs.readAll();
|
|
cs.get(1, pos).get(2, aim).get(3, ang).get(4, fov);
|
|
camera()->setPos(pos);
|
|
camera()->setAim(aim);
|
|
camera()->setAngles(ang);
|
|
camera()->setFOV(fov);
|
|
}
|
|
|
|
|
|
QByteArray QGLView::saveFeatures() {
|
|
QByteArray ba;
|
|
QDataStream ds(&ba, QIODevice::WriteOnly);
|
|
ds << features_;
|
|
return ba;
|
|
}
|
|
|
|
|
|
void QGLView::restoreFeatures(const QByteArray & ba) {
|
|
QHash<int, QVariant> f;
|
|
QDataStream ds(ba);
|
|
ds >> f;
|
|
features_ = f;
|
|
}
|