/* QGLView Copyright (C) 2019 Ivan Pelipenko peri4ko@yandex.ru This program is free software: you can redistribute it and/or modify it under the terms of the GNU 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 General Public License for more details. You should have received a copy of the GNU 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")); deleting_ = false; timer = 0; need_init_ = is_first_draw = true; backColor_ = Qt::darkGray; hoverHaloColor_ = QColor(195, 140, 255); selectionHaloColor_ = QColor(175, 255, 140); ambientColor_ = QColor(10, 10, 10); 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_ = is_init = shaders_bind = changed_ = false; rmode = ObjectBase::Fill; // sel_pen = QPen(Qt::black, 1, Qt::DashLine); // sel_brush = QBrush(QColor(170, 100, 255, 120)); scene_ = new Scene(); connect(scene_, SIGNAL(selectionChanged()), this, SIGNAL(selectionChanged())); connect(scene_, SIGNAL(__destroyed()), this, SLOT(__destroyed())); camera_ = new Camera(); camera_->setPos(QVector3D(2, 2, 2)); camera_->setAim(QVector3D()); // qDebug() << camera_->aim(); camera_->setName("Camera"); emit cameraPosChanged(camera_->pos()); //camera().aim_ = camera().pos_; ktm_.restart(); //Mesh * m = Primitive::torus(100, 40, 1., 0.4, 360); Mesh * m = Primitive::cube(10, 10, 10); m->flipNormals(); //QMatrix4x4 mat; //mat.rotate(90, 0,1,0); //mat.translate(0, 0, 2); //mat.rotate(180, 1,0,0); //m->transformPoints(mat); ObjectBase * o = new ObjectBase(m); o->setColor(Qt::cyan); scene()->addObject(o); delete m; } QGLView::~QGLView() { deleting_ = true; stop(); scene_->destroy(); delete scene_; } 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(); foreach (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(); //if (ktm_.elapsed() < QApplication::keyboardInputInterval()) return; 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 glPainting(); emit glEndPaint(); fps_tm += time.elapsed(); time.restart(); fps_cnt++; if (fps_tm < 1000.) return; 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()); is_init = true; need_init_ = false; 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::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 = 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; Camera * c = 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 f; QDataStream ds(ba); ds >> f; features_ = f; }