Advertisement
Guest User

scene.cpp

a guest
May 19th, 2019
91
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 15.62 KB | None | 0 0
  1. #include <cmath>
  2.  
  3. #include <QMessageBox>
  4. #include <fstream>
  5.  
  6. #include "CGFunctions.h"
  7. #include "EditWidgets.h"
  8. #include "Light.h"
  9. #include "Model.h"
  10. #include "Scene.h"
  11. #include "Skybox.h"
  12.  
  13. #include <QDebug>
  14.  
  15. inline void OpenGLError() {
  16.     GLenum errCode;
  17.     if ((errCode = glGetError()) != GL_NO_ERROR) {
  18.         qDebug() << "OpenGL Error: \n" << errCode << endl;
  19.     }
  20. }
  21.  
  22. Scene::Scene(QWidget *parent) : QGLWidget(parent) {
  23.     m_program = nullptr;
  24.  
  25.     mousepressed = false;
  26.     isDragging = false;
  27.  
  28.     frame = 0;
  29.  
  30.     Model::nameCount = 10;
  31.     m_selectedModel = -1;
  32.  
  33.     showFloor = true;
  34.  
  35.     // start the update Timer (30fps)
  36.     connect(&updateTimer, SIGNAL(timeout()), this, SLOT(updateGL()));
  37.     updateTimer.start(33);
  38.  
  39.     OpenGLError();
  40. }
  41.  
  42. void Scene::resetScene() {
  43.     // delete lights and models
  44.     m_models.clear();
  45.     m_lights.clear();
  46.     m_selectedModel = -1;
  47.     // reset camera
  48.     xRot = 0;
  49.     yRot = 0;
  50.     zRot = 0;
  51.     zoom = -10.0f;
  52.     transx = 0;
  53.     transy = -2.0;
  54.     // load plane
  55.     loadModelFromOBJFile(QString("plane/plane.obj"));
  56.     m_models.back()->rotate(QVector3D(1.0, 0.0, 0.0), -90);
  57.     m_models.back()->scale(10, 0, 10);
  58. }
  59.  
  60. Scene::~Scene() {
  61.     if (m_program) {
  62.         m_program = 0;
  63.     }
  64. }
  65.  
  66. void Scene::saveScene(QString filepath) {
  67.     // create File
  68.     std::ofstream file(filepath.toStdString().c_str());
  69.  
  70.     // 1. write header
  71.     file << m_models.size() - 1 - m_lights.size() << " " << m_lights.size()
  72.         << "\n";
  73.     file << xRot << " " << yRot << " " << zRot << " "
  74.         << " " << zoom << " " << transx << " " << transy;
  75.     file << "\n";
  76.  
  77.     // 2. save Models
  78.     for (size_t m = 1; m < m_models.size(); ++m) {
  79.         std::shared_ptr<Light> l = std::dynamic_pointer_cast<Light>(m_models[m]);
  80.         if (l)
  81.             continue;
  82.         file << m_models[m]->getPath().toStdString() << "\n";
  83.         QMatrix4x4 trafo = m_models[m]->getTransformations();
  84.         for (size_t i = 0; i < 4; ++i)
  85.             for (size_t j = 0; j < 4; ++j)
  86.                 file << trafo(i, j) << " ";
  87.         file << "\n";
  88.     }
  89.     file << "\n";
  90.  
  91.     // 3. save lights
  92.     for (size_t l = 0; l < m_lights.size(); ++l) {
  93.         Light *light = m_lights[l].get();
  94.         QVector3D a = light->getAmbient();
  95.         QVector3D d = light->getDiffuse();
  96.         QVector3D s = light->getSpecular();
  97.         file << a.x() << " " << a.y() << " " << a.z() << "\n";
  98.         file << d.x() << " " << d.y() << " " << d.z() << "\n";
  99.         file << s.x() << " " << s.y() << " " << s.z() << "\n";
  100.         QMatrix4x4 trafo = m_lights[l]->getTransformations();
  101.         for (size_t i = 0; i < 4; ++i)
  102.             for (size_t j = 0; j < 4; ++j)
  103.                 file << trafo(i, j) << " ";
  104.         file << "\n";
  105.     }
  106. }
  107.  
  108. void Scene::loadScene(QString filepath) {
  109.     std::ifstream file(filepath.toStdString().c_str());
  110.     size_t nModels, nLights;
  111.     file >> nModels >> nLights;
  112.     file >> xRot >> yRot >> zRot >> zoom >> transx >> transy;
  113.     float m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42,
  114.         m43, m44;
  115.     // read models
  116.     for (size_t m = 0; m < nModels; ++m) {
  117.         std::string path;
  118.         file >> path;
  119.         file >> m11 >> m12 >> m13 >> m14 >> m21 >> m22 >> m23 >> m24 >> m31 >>
  120.             m32 >> m33 >> m34 >> m41 >> m42 >> m43 >> m44;
  121.         loadModelFromOBJFile(QString(path.c_str()));
  122.         QMatrix4x4 trafo = QMatrix4x4(m11, m12, m13, m14, m21, m22, m23, m24, m31,
  123.             m32, m33, m34, m41, m42, m43, m44);
  124.         m_models.back()->setTransformations(trafo);
  125.     }
  126.     // read lights
  127.     for (size_t l = 0; l < nLights; ++l) {
  128.         double ar, ag, ab, dr, dg, db, sr, sg, sb;
  129.         file >> ar >> ag >> ab >> dr >> dg >> db >> sr >> sg >> sb;
  130.         file >> m11 >> m12 >> m13 >> m14 >> m21 >> m22 >> m23 >> m24 >> m31 >>
  131.             m32 >> m33 >> m34 >> m41 >> m42 >> m43 >> m44;
  132.         QMatrix4x4 trafo = QMatrix4x4(m11, m12, m13, m14, m21, m22, m23, m24, m31,
  133.             m32, m33, m34, m41, m42, m43, m44);
  134.         auto light = std::shared_ptr<Light>(new Light(Model::nameCount++));
  135.         light->setAmbient(ar, ag, ab);
  136.         ;
  137.         light->setDiffuse(dr, dg, db);
  138.         light->setSpecular(sr, sg, sb);
  139.         light->setTransformations(trafo);
  140.         m_lights.push_back(light);
  141.         m_models.push_back(m_lights.back());
  142.     }
  143. }
  144.  
  145. void Scene::deleteModel() {
  146.     if (m_selectedModel == -1)
  147.         return;
  148.  
  149.     updateTimer.stop();
  150.  
  151.     // check, if model is also a light
  152.     std::shared_ptr<Light> l =
  153.         std::dynamic_pointer_cast<Light>(m_models[m_selectedModel]);
  154.     if (l) {
  155.         // delete the corresponding Light
  156.         int name = m_models[m_selectedModel]->getName();
  157.         int lightIndex = -1;
  158.         for (size_t i = 0; i < m_lights.size(); ++i) {
  159.             if (m_lights[i]->getName() == name)
  160.                 lightIndex = i;
  161.         }
  162.         if (lightIndex >= 0) {
  163.             std::vector<std::shared_ptr<Light>>::iterator it = m_lights.begin();
  164.             m_lights.erase(it + lightIndex);
  165.         }
  166.         else
  167.             qDebug() << "Strange error: Did not find light to erase.\n";
  168.     }
  169.  
  170.     // delete the model
  171.     std::vector<std::shared_ptr<Model>>::iterator it = m_models.begin();
  172.     m_models.erase(it + m_selectedModel);
  173.  
  174.     // unselect Model
  175.     m_selectedModel = -1;
  176.  
  177.     updateTimer.start(33);
  178. }
  179.  
  180. bool Scene::loadModelFromOBJFile(QString path) {
  181.     m_models.push_back(std::shared_ptr<Model>(Model::importOBJFile(path)));
  182.     if (m_models.back()->getNpositions() == 0) {
  183.         QMessageBox::warning(this, QString("Error"),
  184.             QString("The file could not be opened."));
  185.         return false;
  186.     }
  187.     m_models.back()->rotate(QVector3D(1.0, 0.0, 0.0), -90);
  188.     return true;
  189. }
  190.  
  191. void Scene::scaleModel(double sx, double sy, double sz) {
  192.     if (m_selectedModel == -1)
  193.         return;
  194.     m_models[m_selectedModel]->scale(sx, sy, sz);
  195. }
  196.  
  197. void Scene::translateModel(double dx, double dy, double dz) {
  198.     if (m_selectedModel == -1)
  199.         return;
  200.     m_models[m_selectedModel]->translate(dx, dy, dz);
  201. }
  202.  
  203. void Scene::rotateModel(double ax, double ay, double az, double angle) {
  204.     if (m_selectedModel == -1)
  205.         return;
  206.     m_models[m_selectedModel]->rotate(QVector3D(ax, ay, az), angle);
  207. }
  208.  
  209. void Scene::addLight() {
  210.     auto l = std::shared_ptr<Light>(new Light(Model::nameCount++));
  211.     LightDialog ld(l.get());
  212.     if (ld.exec()) {
  213.         m_lights.push_back(l);
  214.         m_models.push_back(m_lights.back());
  215.     }
  216. }
  217.  
  218. std::shared_ptr<QOpenGLShaderProgram>
  219. Scene::loadShaders(QString vertexShaderSource, QString fragmentShaderSource) {
  220.     auto pr = std::make_shared<QOpenGLShaderProgram>();
  221.     pr->addShaderFromSourceFile(QOpenGLShader::Vertex, vertexShaderSource);
  222.     qDebug() << "Compile VertexShader: ";
  223.     qDebug() << pr->log();
  224.  
  225.     pr->addShaderFromSourceFile(QOpenGLShader::Fragment, fragmentShaderSource);
  226.     qDebug() << "Compile FragmentShader: ";
  227.     qDebug() << pr->log();
  228.  
  229.     pr->link();
  230.     qDebug() << "Linking Shader Program: ";
  231.     qDebug() << pr->log();
  232.  
  233.     return pr;
  234. }
  235.  
  236. void Scene::reloadShader() {
  237.     m_program = loadShaders(QString("shader/vertex.glsl"),
  238.         QString("shader/fragment.glsl"));
  239.     m_programSelect = loadShaders(QString("shader/vertex.glsl"),
  240.         QString("shader/fragmentSelected.glsl"));
  241.     m_programSkybox = loadShaders(QString("shader/vertexSkybox.glsl"),
  242.         QString("shader/fragmentSkybox.glsl"));
  243. }
  244.  
  245. void Scene::setFloor() { showFloor = !showFloor; }
  246.  
  247. void Scene::initializeGL() {
  248.  
  249.     qInfo() << "C++ Style Info Message";
  250.     vao.create();
  251.     vao.bind();
  252.  
  253.     glClearColor(1.0, 1.0, 1.0, 0.0);
  254.     glDepthFunc(GL_LEQUAL);
  255.     glEnable(GL_BLEND);
  256.     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  257.     glEnable(GL_DEPTH_TEST);
  258.     glDisable(GL_CULL_FACE);
  259.     glEnable(GL_TEXTURE_2D);
  260.     glEnable(GL_LIGHTING);
  261.     reloadShader();
  262.  
  263.     resetScene();
  264.  
  265.     OpenGLError();
  266.     m_skybox = std::shared_ptr<Skybox>(new Skybox());
  267.     //m_skybox = std::make_shared<Skybox>(new Skybox());
  268.     //m_skybox = std::make_shared<Skybox>();
  269.     //triangleInit();
  270. }
  271.  
  272. void Scene::triangleInit() {
  273.  
  274.     // AUFGABE 1: erzeugen Sie hier die Buffer und initialisieren sie alles
  275.     // notwendige
  276.  
  277.     positionBuffer = QOpenGLBuffer(QOpenGLBuffer::VertexBuffer);
  278.     positionBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw);
  279.     positionBuffer.create();
  280.     positionBuffer.bind();
  281.     positionBuffer.allocate(positions.data(), positions.size() * sizeof(QVector3D));
  282.  
  283.     colorBuffer = QOpenGLBuffer(QOpenGLBuffer::VertexBuffer);
  284.     colorBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw);
  285.     colorBuffer.create();
  286.     colorBuffer.bind();
  287.     colorBuffer.allocate(colors.data(), colors.size() * sizeof(QVector3D));
  288. }
  289.  
  290. void Scene::resizeGL(int width, int height) {
  291.     glViewport(0, 0, width, height);
  292.     qreal aspect = qreal(width) / qreal(height ? height : 1);
  293.     const qreal zNear = 0.1f, zFar = 400.0f, fov = 60.0f;
  294.     m_projection.setToIdentity();
  295.     m_projection.perspective(fov, aspect, zNear, zFar);
  296. }
  297.  
  298. void Scene::mouseMoveEvent(QMouseEvent *event) {
  299.     if (lastPos.x() == -1 || lastPos.y() == -1)
  300.         return;
  301.  
  302.     int dx = event->x() - lastPos.x();
  303.     int dy = event->y() - lastPos.y();
  304.  
  305.     if (event->buttons() & Qt::LeftButton && m_selectedModel == -1) {
  306.         setXRotation(xRot + 4 * dy);
  307.         setYRotation(yRot + 4 * dx);
  308.     }
  309.     else if (event->buttons() & Qt::RightButton) {
  310.         setXRotation(xRot + 4 * dy);
  311.         setZRotation(zRot - 4 * dx);
  312.     }
  313.     else if (event->buttons() & Qt::MidButton) {
  314.         transx += (double)dx * 0.01;
  315.         transy -= (double)dy * 0.01;
  316.     }
  317.     else if (event->buttons() & Qt::LeftButton &&
  318.         m_selectedModel != -1) // move the selected model
  319.     {
  320.         QMatrix4x4 imvpMatrix = (m_projection * m_view).inverted();
  321.         QVector4D center = m_models[m_selectedModel]->getBoundingBox().center;
  322.         // determine the last dragging position
  323.         if (!isDragging) // init with bounding box
  324.         {
  325.             // project the center to view (so that we look in z direction -> z
  326.             // is now the depth)
  327.             QVector4D centerView = m_view * center;
  328.             double z = centerView.z();
  329.             // calculate the depth buffer value of z
  330.             draggingDepth = 2.0 * (z - 0.1) / (1000.0 - 0.1) - 1.0;
  331.             lastDraggingPos = unprojectScreenCoordinates(
  332.                 event->x(), event->y(), draggingDepth, width(), height(), imvpMatrix);
  333.             isDragging = true;
  334.         }
  335.         QVector4D draggingPos = unprojectScreenCoordinates(
  336.             event->x(), event->y(), draggingDepth, width(), height(), imvpMatrix);
  337.         QVector4D translation = draggingPos - lastDraggingPos;
  338.         float factor = fabs(zoom * 10);
  339.         m_models[m_selectedModel]->translate(translation.x() * factor,
  340.             translation.y() * factor,
  341.             translation.z() * factor);
  342.         lastDraggingPos = draggingPos;
  343.     }
  344.  
  345.     lastPos = event->pos();
  346. }
  347.  
  348. void Scene::wheelEvent(QWheelEvent *event) { zoom -= event->delta() * 0.0025; }
  349.  
  350. void Scene::mousePressEvent(QMouseEvent *event) {
  351.     mousepressed = true;
  352.     lastPos = event->pos();
  353. }
  354.  
  355. void Scene::mouseDoubleClickEvent(QMouseEvent *event) {
  356.     // intersect ray with the bounding boxes of all models
  357.     // the functions for this technique are defined in CGFunctions.h
  358.  
  359.     // calculate intersections of ray in world space
  360.     QMatrix4x4 imvpMatrix = (m_projection * m_view).inverted();
  361.     QVector4D eyeRay_n = unprojectScreenCoordinates(
  362.         event->x(), event->y(), -1.0, width(), height(), imvpMatrix);
  363.     QVector4D eyeRay_z = unprojectScreenCoordinates(
  364.         event->x(), event->y(), 1.0, width(), height(), imvpMatrix);
  365.     float tnear, tfar;
  366.     float smallest_t = 1e33;
  367.     int nearestModel = -1;
  368.     for (size_t i = 0; i < m_models.size(); ++i) {
  369.         BoundingBox bb = m_models[i]->getBoundingBox();
  370.         if (intersectBox(eyeRay_n, eyeRay_z - eyeRay_n, bb.bbmin, bb.bbmax, &tnear,
  371.             &tfar)) {
  372.             if (tnear < smallest_t) {
  373.                 smallest_t = fabs(tnear);
  374.                 nearestModel = i;
  375.             }
  376.         }
  377.     }
  378.     if (nearestModel >= 0 && (nearestModel != m_selectedModel)) {
  379.         m_selectedModel = nearestModel;
  380.         std::cout << "Model: " << m_models[m_selectedModel]->getName()
  381.             << " was selected\n";
  382.     }
  383.     else
  384.         m_selectedModel = -1;
  385. }
  386.  
  387. void Scene::mouseReleaseEvent(QMouseEvent *event) {
  388.     mousepressed = false;
  389.     isDragging = false;
  390. }
  391.  
  392. void Scene::setXRotation(int angle) {
  393.     normalizeAngle(&angle);
  394.     if (angle != xRot) {
  395.         xRot = angle;
  396.     }
  397. }
  398.  
  399. void Scene::setYRotation(int angle) {
  400.     normalizeAngle(&angle);
  401.     if (angle != yRot) {
  402.         yRot = angle;
  403.     }
  404. }
  405.  
  406. void Scene::setZRotation(int angle) {
  407.     normalizeAngle(&angle);
  408.     if (angle != zRot) {
  409.         zRot = angle;
  410.     }
  411. }
  412.  
  413. void Scene::normalizeAngle(int *angle) {
  414.     while (*angle < 0)
  415.         *angle += 360 * 16;
  416.     while (*angle > 360 * 16)
  417.         *angle -= 360 * 16;
  418. }
  419.  
  420. void Scene::setTransformations() {
  421.     m_view = QMatrix4x4(); // init with idendity matrix
  422.     // do the translation
  423.     m_view.translate(transx, transy, zoom);
  424.     // do the rotation
  425.     m_view.rotate((xRot / 16.0f), 1.0f, 0.0f, 0.0f);
  426.     m_view.rotate((yRot / 16.0f), 0.0f, 1.0f, 0.0f);
  427.     m_view.rotate((zRot / 16.0f), 0.0f, 0.0f, 1.0f);
  428. }
  429.  
  430. void Scene::paintGL() {
  431.     ++frame;
  432.     if (frame < 0)
  433.         frame = 0;
  434.  
  435.     // clear the screen
  436.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
  437.  
  438.     // set the view matrix
  439.     setTransformations();
  440.  
  441.     // AUFGABE 1: der rendersbschnitt sollte hier her
  442.     //m_program->bind();
  443.     //m_program->enableAttributeArray(m_program->attributeLocation("position"));
  444.     //m_program->enableAttributeArray(m_program->attributeLocation("color"));
  445.     //positionBuffer.bind();
  446.     //m_program->setAttributeBuffer(m_program->attributeLocation("position"), GL_FLOAT, 0, 3);
  447.     //colorBuffer.bind();
  448.     //m_program->setAttributeBuffer(m_program->attributeLocation("color"), GL_FLOAT, 0, 3);
  449.     //glDrawArrays(GL_TRIANGLES, 0, 3);
  450.     //m_program->release();
  451.  
  452.     // AUFGABE 1: ENDE
  453.  
  454.     // AUFGABE 2 - fuer die zweite übungsserie sollte der folgende code wieder
  455.     //  aktiv gesetzt werden
  456.     // render all models
  457.     // the floor is always the first model, so if (showFloor == false), we
  458.     // simply start the rendering
  459.     // with the second model
  460.  
  461.     //auto stdLight = std::shared_ptr<Light>(new Light(Model::nameCount++));
  462.     //stdLight->setAmbient(1.0, 1.0, 1.0);
  463.     //stdLight->setDiffuse(1.0, 1.0, 1.0);
  464.     //stdLight->setSpecular(1.0, 1.0, 1.0);
  465.     m_programSkybox->bind();
  466.     m_programSkybox->setUniformValue(m_programSkybox->uniformLocation("view"), m_view);
  467.     m_programSkybox->setUniformValue(m_programSkybox->uniformLocation("projection"), m_projection);
  468.  
  469.     QVector3D camera;
  470.     m_skybox->render(m_programSkybox, camera);
  471.  
  472.     glDrawArrays(GL_TRIANGLES, 0, 3);
  473.     m_programSkybox->release();
  474.    
  475.  
  476.     auto l = std::shared_ptr<Light>(new Light(Model::nameCount++));
  477.     l->setAmbient(1.0f, 1.0f, 1.0f);
  478.     l->setDiffuse(1.0f, 1.0f, 1.0f);
  479.     l->setSpecular(1.0f, 1.0f, 1.0f);
  480.     if (m_lights.size() < 1) {
  481.         m_lights.push_back(l);
  482.     }
  483.    
  484.     int lightCount = m_lights.size();
  485.  
  486.     for (int j = 0; j < lightCount; j++) {
  487.         ambients[j] = m_lights[j]->getAmbient();
  488.         diffuses[j] = m_lights[j]->getDiffuse();
  489.         speculars[j] = m_lights[j]->getSpecular();
  490.         if (j == 0) {
  491.             lightPositions[j] = -m_view.row(1).toVector3D() * 100;
  492.         }
  493.         else {
  494.             lightPositions[j] = m_lights[j]->getBoundingBox().center;
  495.         }  
  496.     }
  497.  
  498.     size_t i;
  499.     for (showFloor ? i = 0 : i = 1; i < m_models.size(); ++i) {
  500.     //  m_program->bind();
  501.    
  502.         // render the model
  503.         std::shared_ptr<QOpenGLShaderProgram> new_program;
  504.         if (i == m_selectedModel) {
  505.             new_program = m_programSelect;
  506.         }
  507.         else {
  508.             new_program = m_program;
  509.         }
  510.         new_program->bind();
  511.  
  512.         //set uniform values
  513.         QMatrix4x4 matrix = m_models[i]->getTransformations();
  514.         new_program->setUniformValue(new_program->uniformLocation("modelMatrix"), matrix);
  515.         new_program->setUniformValue(new_program->uniformLocation("viewMatrix"), m_view);
  516.         new_program->setUniformValue(new_program->uniformLocation("projectionMatrix"), m_projection);
  517.  
  518.         new_program->setUniformValue(new_program->uniformLocation("lightCount"), lightCount);
  519.         new_program->setUniformValueArray(new_program->uniformLocation("ambients"), &ambients[0], lightCount);
  520.         new_program->setUniformValueArray(new_program->uniformLocation("diffuses"), &diffuses[0], lightCount);
  521.         new_program->setUniformValueArray(new_program->uniformLocation("speculars"), &speculars[0], lightCount);
  522.         new_program->setUniformValueArray(new_program->uniformLocation("lightPositions"), &lightPositions[0], lightCount);
  523.        
  524.         m_models[i]->render(new_program);
  525.  
  526.         // release shader the program
  527.         new_program->release();
  528.     }
  529.     // Aufgabe 2 - bis hier hin sollte eine Ebene der Kommentare entfernt
  530.     // werden
  531. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement