Files
qglengine/src/core/view/qglview.cpp
peri4 0151e34477 delete GLView crash fix
fixed fog/background color, now not x2 amplified
fixed bug when no shadows enabled on start (sum with fog on geometry)
2023-04-23 23:15:31 +03:00

301 lines
7.7 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 <QApplication>
#include <QKeyEvent>
#include <QOpenGLTexture>
#include <chunkstream.h>
#include <qad_types.h>
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;
FXAA_ = false;
fps_cnt = 0;
soft_shadows_quality = 1.;
soft_shadows_samples = 32;
soft_shadows = false;
shadows_ = false;
fps_tm = fps_ = 0.;
fogColor_ = Qt::darkGray;
fogDensity_ = 0.;
fogDecay_ = 10.;
hoverHaloFill_ = selectionHaloFill_ = 0.15f;
render_mode = rmFill;
shadow_map_size = QSize(512, 512);
// 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;
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::plane(10, 10, 10);
// m->flipNormals();
ObjectBase * o = new ObjectBase(m);
o->setColor(Qt::cyan);
scene()->addObject(o);
delete m;*/
}
QGLView::~QGLView() {
stop();
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::reloadTextures() {
renderer_.markReloadMaterials();
renderer_.recreateMaterialThumbnails(true);
scene_->setLightsChanged();
}
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(pixelWidth(), pixelHeight());
emit glBeginPaint();
renderer_.mouse_pos = mapFromGlobal(QCursor::pos()) * devicePixelRatio();
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(pixelWidth(), pixelHeight());
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);
}
void QGLView::setShadowMapSize(QSize sz) {
shadow_map_size = sz;
}
void QGLView::setTextureMapSize(QSize sz) {
renderer_.maps_size = sz;
renderer_.markReloadMaterials();
}
QSize QGLView::shadowMapSize() const {
return shadow_map_size;
}
QSize QGLView::textureMapSize() const {
return renderer_.maps_size;
}