/* 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 . */ #include "qglview.h" #include "glmesh.h" #include "gltexture_manager.h" #include #include #include #include #include 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 QGLView::selectedLights() const { QList ret; ObjectBaseList sol = scene_->selectedObjects(); foreach(ObjectBase * o, sol) if (o->type() == ObjectBase::glLight) ret << (Light *)o; return ret; } QList QGLView::selectedCameras() const { QList 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; }