Skip to content
Snippets Groups Projects
CgSceneControl.cpp 13.1 KiB
Newer Older
  • Learn to ignore specific revisions
  • ganthern's avatar
    ganthern committed
    #define GLM_ENABLE_EXPERIMENTAL
    
    #include "CgSceneControl.h"
    #include "CgBase/CgEnums.h"
    #include "CgEvents/CgMouseEvent.h"
    
    ganthern's avatar
    ganthern committed
    #include "CgEvents/CgWheelEvent.h"
    
    ganthern's avatar
    ganthern committed
    #include "CgEvents/CgKeyEvent.h"
    #include "CgEvents/CgWindowResizeEvent.h"
    #include "CgEvents/CgLoadMeshEvent.h"
    #include "CgEvents/CgLoadPointCloudEvent.h"
    #include "CgEvents/CgTrackballEvent.h"
    #include "CgEvents/CgSplatEvent.h"
    #include "CgEvents/CgPickRayEvent.h"
    #include "CgBase/CgBaseRenderer.h"
    #include "CgPointCloud.h"
    #include "CgPolyLine.h"
    #include "CgTriangleMesh.h"
    #include <iostream>
    #include <glm/gtc/matrix_transform.hpp>
    #include <glm/ext.hpp>
    #include "CgUtils/ObjLoader.h"
    #include "CgMath/CgEigenDecomposition3x3.h"
    #include <string>
    #include <CgMath/Eigen/SVD>
    #include <CgMath/Eigen/Core>
    using namespace Eigen;
    
    CgSceneControl::CgSceneControl()
    {
        m_pointcloud=nullptr;
        m_current_transformation=glm::mat4(1.);
        m_lookAt_matrix= glm::lookAt(glm::vec3(0.0,0.0,1.0),glm::vec3(0.0,0.0,0.0),glm::vec3(0.0,1.0,0.0));
        m_proj_matrix= glm::mat4x4(glm::vec4(1.792591, 0.0, 0.0, 0.0), glm::vec4(0.0, 1.792591, 0.0, 0.0), glm::vec4(0.0, 0.0, -1.0002, -1.0), glm::vec4(0.0, 0.0, -0.020002, 0.0));
    
        m_trackball_rotation=glm::mat4(1.);
    
        m_select_ray=NULL;
        m_disc = new CgTriangleMesh(78);
        m_pointcloud = NULL;
        m_center=glm::vec3(0.);
        m_triangle_mesh= NULL;
        m_show_splats=false;
        m_show_pickray=false;
    }
    
    
    CgSceneControl::~CgSceneControl()
    {
        if(m_pointcloud!=NULL)
            delete m_pointcloud;
        if(m_triangle_mesh!=NULL)
            delete m_triangle_mesh;
        if(m_disc!=NULL)
            delete m_disc;
        if(m_select_ray!=NULL)
            delete m_select_ray;
    }
    
    
    
    void CgSceneControl::calculatePickRay(double x, double y)
    {
      double w = (double) m_renderer->getViewportWidth();
      double h = (double) m_renderer->getViewportHeight();
    
      // normalize into [-1;1]
      x=2.0*x / w -1.0;
      if (x<-1.0) x=-1.0;
      if (x>1.0) x=1.0;
    
      y=2.0*y / h -1.0;
      if (y<-1.0) y=-1.0;
      if (y>1.0) y=1.0;
    
      // change to right handed coordinate system
      y=-y;
    
      glm::mat4 inverse_proj=glm::inverse(m_proj_matrix);
    
      //unproject point on front clipping plane
      glm::vec4 p(x,y,-0.01,1);
      glm::vec4 q= inverse_proj*p;
      q/= q.w;
    
      //unproject point on back clipping plane
      glm::vec4 r(x,y,1.0,1);
      glm::vec4 s= inverse_proj*r;
      s/= s.w;
    
      //construct current modelview matrix by hand, since there is no scenegraph
      m_current_transformation = glm::translate(m_current_transformation,-m_center);
      glm::mat4 mv_matrix = m_lookAt_matrix * m_trackball_rotation* m_current_transformation ;
      m_current_transformation = glm::translate(m_current_transformation,m_center);
    
    
      // convert pick ray into local "bunny coordinates"
      glm::mat4 mv_matrix_inv = glm::inverse(mv_matrix);
      glm::vec4 raystart=mv_matrix_inv*q;
      glm::vec4 rayend=mv_matrix_inv*s;
    
      // init new CgPolyline to draw the pick ray
      if(m_select_ray!=NULL)
        delete m_select_ray;
      std::vector<glm::vec3> pointlist;
      pointlist.push_back(raystart);
      pointlist.push_back(rayend);
      m_select_ray = new CgPolyLine(33,pointlist);
      m_renderer->init(m_select_ray);
    
    
      m_renderer->redraw();
    }
    
    
    void CgSceneControl::calculateEigenDecomposition3x3()
    {
        glm::mat3 testmat = glm::mat3(3.,2.,4.,2.,0.,2.,4.,2.,3.);
        std::cout << glm::to_string(testmat) << std::endl;
    
        CgEigenDecomposition3x3 eigen(testmat);
        glm::mat3 eigenvectors= eigen.getEigenvectors();
        glm::vec3 eigenvalues = eigen.getEigenvalues();
    
        std::cout << glm::to_string(eigenvalues) << std::endl;
        std::cout << glm::to_string(eigenvectors) << std::endl;
    }
    
    void CgSceneControl::calculateSingularValueDecomposition()
    {
          //init some arbitrary test matrix
          MatrixXd C(2,3);
          C(0,0)=3.0;C(0,1)=2.0;C(0,2)=2.0;
          C(1,0)=2.0;C(1,1)=3.0;C(1,2)=-2.0;
    
          std::cout << C << std::endl;
    
          //compute decomposition
          JacobiSVD<Eigen::MatrixXd> svd(C,ComputeThinU|ComputeThinV);
          Eigen::MatrixXd U=svd.matrixU();
          Eigen::MatrixXd V=svd.matrixV();
          Eigen::VectorXd SV=svd.singularValues();
    
          //build a diagonal matrix out of the singular values
          Eigen::MatrixXd S(2,2);
          S.setZero();
          S(0,0)=SV(0);S(1,1)=SV(1);
    
          std::cout << U << std::endl;
          std::cout << S << std::endl;
          std::cout << V.transpose() << std::endl;
    
    
        // compute Moore-Penrose inverse now
    
         S(0,0)=1.0/S(0,0);S(1,1)=1.0/S(1,1);
         Eigen::MatrixXd C_plus = V*S*U.transpose();
    
         std::cout << std::endl;
         std::cout << C_plus << std::endl;
    }
    
    void CgSceneControl::handleEvent(CgBaseEvent* e)
    {
        // any kind of MouseEvents can be checked via CgEvent::CgMouseEvent a
        // see CgEvent enums in CgEnums.h
    
        if(e->getType() & Cg::CgMouseEvent)
        {
            CgMouseEvent* ev = (CgMouseEvent*)e;
            if(ev->button()==Cg::RightButton)
                calculatePickRay((double)ev->x(),(double)ev->y());
    
    ganthern's avatar
    ganthern committed
        } 
    
        if(e->getType() & Cg::CgMouseWheel) 
        {
          CgWheelEvent* ev = (CgWheelEvent*)e;
          //scaling of scene, i.e. of the one single object
          float scaleFactor = 1.0f + 0.01f * ev->numDegrees();
          glm::mat4 scalemat = glm::mat4(1.);
          scalemat = glm::scale(scalemat, glm::vec3(scaleFactor,scaleFactor,scaleFactor));
          m_current_transformation = m_current_transformation * scalemat;
          m_renderer->redraw();
    
    ganthern's avatar
    ganthern committed
        }
    
        if(e->getType() & Cg::CgTrackballEvent)
        {
            CgTrackballEvent* ev = (CgTrackballEvent*)e;
    
            m_trackball_rotation=ev->getRotationMatrix();
            m_renderer->redraw();
        }
    
        // any kind of KeyEvents can be checked via CgEvent::CgKeyEvent
        // see CgEvent enums in CgEnums.h
    
        if(e->getType() & Cg::CgKeyEvent)
        {
            CgKeyEvent* ev = (CgKeyEvent*)e;
    
            if(ev->text()=="e")
            {
                // example usage of eigen library to compute the eigen-decomposition of a matrix
                calculateEigenDecomposition3x3();
            }
    
            if(ev->text()=="s")
            {
              // example usage of eigen library to compute the eigen-decomposition of a matrix
              calculateSingularValueDecomposition();
            }
    
            if(ev->text()=="+")
            {
                //scaling of scene, i.e. of the one single object
                glm::mat4 scalemat = glm::mat4(1.);
                scalemat = glm::scale(scalemat,glm::vec3(1.1,1.1,1.1));
                m_current_transformation=m_current_transformation*scalemat;
                m_renderer->redraw();
            }
            if(ev->text()=="-")
            {
                //scaling of scene, i.e. of the one single object
                glm::mat4 scalemat = glm::mat4(1.);
                scalemat = glm::scale(scalemat,glm::vec3(0.9,0.9,0.9));
                m_current_transformation=m_current_transformation*scalemat;
                m_renderer->redraw();
            }
        }
    
    
        if(e->getType() & Cg::CgSplatEvent)
        {
            // checkbox in GUI changed for showing/hiding splats
            CgSplatEvent* ev = (CgSplatEvent*)e;
            m_show_splats=ev->useSplatting();
            m_renderer->redraw();
        }
    
        if(e->getType() & Cg::CgPickRayEvent)
        {
            // checkbox in GUI changed for showing/hiding pick ray
            CgPickRayEvent* ev = (CgPickRayEvent*)e;
            m_show_pickray=ev->showPickRay();
            renderObjects();
            m_renderer->redraw();
        }
    
    
        if(e->getType() & Cg::WindowResizeEvent)
        {
             CgWindowResizeEvent* ev = (CgWindowResizeEvent*)e;
             std::cout << *ev <<std::endl;
             m_proj_matrix=glm::perspective(45.0f, (float)(ev->w()) / ev->h(), 0.01f, 100.0f);
        }
    
        if(e->getType() & Cg::CgLoadPointCloudEvent)
        {
    
            CgLoadPointCloudEvent* ev = (CgLoadPointCloudEvent*)e;
            ObjLoader* loader= new ObjLoader();
    
            std::string filename =ev->FileName();
            if(filename !="")
              {
                loader->load(filename);
    
                if(m_triangle_mesh!=NULL)
                  {
                    delete m_triangle_mesh;
                    m_triangle_mesh=NULL;
                  }
                if(m_pointcloud!=NULL)
                  {
                    delete m_pointcloud;
                    m_pointcloud=NULL;
                  }
    
                m_pointcloud= new CgPointCloud();
                m_pointcloud->init(ev->FileName(),true);
    
                m_center=m_pointcloud->getCenter();
                m_renderer->init(m_pointcloud);
                m_renderer->redraw();
              }
        }
    
    
        if(e->getType() & Cg::CgLoadMeshEvent)
        {
    
            CgLoadMeshEvent* ev = (CgLoadMeshEvent*)e;
            ObjLoader* loader= new ObjLoader();
            std::string filename =ev->FileName();
    
            if(filename !="")
              {
                loader->load(filename);
    
                if(m_triangle_mesh!=NULL)
                  {
                    delete m_triangle_mesh;
                    m_triangle_mesh=NULL;
                  }
                if(m_pointcloud!=NULL)
                  {
                    delete m_pointcloud;
                    m_pointcloud=NULL;
                  }
    
                m_triangle_mesh= new CgTriangleMesh();
                m_triangle_mesh->init(ev->FileName());
    
                m_center=m_triangle_mesh->getCenter();
                m_renderer->init(m_triangle_mesh);
                m_renderer->redraw();
              }
        }
    
    
        // delete event
        delete e;
    }
    
    
    
    
    
    // rendering stuff
    /*******************************************************************************************************/
    
    void CgSceneControl::setRenderer(CgBaseRenderer* r)
    {
        m_renderer=r;
        m_renderer->setSceneControl(this);
    
        if(m_pointcloud!=NULL)
        m_renderer->init(m_pointcloud);
    
        if(m_disc!=NULL)
        m_renderer->init(m_disc);
    
        if(m_select_ray!=NULL)
        m_renderer->init(m_select_ray);
    
        if(m_triangle_mesh!=NULL)
        m_renderer->init(m_triangle_mesh);
    }
    
    
    void CgSceneControl::renderObjects()
    {
    
        // Materialeigenschaften setzen
    
    
        m_renderer->setUniformValue("mycolor",glm::vec4(0.0,1.0,0.0,1.0));
    
        m_renderer->setUniformValue("matDiffuseColor",glm::vec4(0.780392f, 0.568627f, 0.113725f, 1.0f ));
        m_renderer->setUniformValue("lightDiffuseColor",glm::vec4(1.0,1.0,1.0,1.0));
    
        m_renderer->setUniformValue("matAmbientColor",glm::vec4(0.329412f, 0.223529f, 0.027451f,1.0f ));
        m_renderer->setUniformValue("lightAmbientColor",glm::vec4(1.0,1.0,1.0,1.0));
    
        m_renderer->setUniformValue("matSpecularColor",glm::vec4(0.992157f, 0.941176f, 0.807843f, 1.0f));
        m_renderer->setUniformValue("lightSpecularColor",glm::vec4(1.0,1.0,1.0,1.0));
    
        m_renderer->setUniformValue("shininess",27.8974f);
    
    
    
    
    
    
        if(m_triangle_mesh!=NULL)
          {
            m_current_transformation = glm::translate(m_current_transformation,-m_center);
            glm::mat4 mv_matrix = m_lookAt_matrix * m_trackball_rotation* m_current_transformation ;
            m_renderer->render(m_triangle_mesh,mv_matrix,m_proj_matrix);
            m_current_transformation = glm::translate(m_current_transformation,m_center);
          }
    
        if((m_pointcloud!=NULL)&&(!m_show_splats))
          {
            m_current_transformation = glm::translate(m_current_transformation,-m_center);
            glm::mat4 mv_matrix = m_lookAt_matrix * m_trackball_rotation* m_current_transformation ;
            m_renderer->render(m_pointcloud,mv_matrix,m_proj_matrix);
            m_current_transformation = glm::translate(m_current_transformation,m_center);
          }
    
    
    
    
        if((m_select_ray!=NULL)&&(m_show_pickray))
          {
            m_current_transformation = glm::translate(m_current_transformation,-m_center);
            glm::mat4 mv_matrix = m_lookAt_matrix * m_trackball_rotation* m_current_transformation ;
            m_renderer->render(m_select_ray,mv_matrix,m_proj_matrix);
            m_current_transformation = glm::translate(m_current_transformation,m_center);
          }
    
    
        // you would never ever render splats like this, a splat is never a scenegraph object
        // just to have not much effort to show the shape, inefficient rendering!
        if((m_pointcloud!=NULL)&&(m_show_splats))
          {
    
            m_renderer->setUniformValue("rendersplats",1);
    
        const std::vector<glm::vec3>& vertex_colors = m_pointcloud->getVertexColors();
        const std::vector<glm::vec3>& vertices = m_pointcloud->getVertices();
        const std::vector<unsigned int>& splat_indices= m_pointcloud->getSplatIndices();
        const std::vector<glm::mat4>& orientations = m_pointcloud->getSplatOrientations();
        const std::vector<glm::vec2>& scalings = m_pointcloud->getSplatScalings();
    
        glm::mat4 mv_matrix;
    
          for(unsigned int i=0;i<splat_indices.size();i++)
          {
            //m_renderer->setUniformValue("mycolor",glm::vec4(vertex_colors[splat_indices[i]],1.0));
    
            m_current_transformation = glm::translate(m_current_transformation,-m_center);
            m_current_transformation = m_current_transformation * glm::inverse(orientations[splat_indices[i]]);
    
            m_current_transformation=glm::scale(m_current_transformation,glm::vec3(scalings[splat_indices[i]][0],scalings[splat_indices[i]][1],1.0));
    
            mv_matrix = m_lookAt_matrix * m_trackball_rotation* m_current_transformation ;
    
            if(m_disc!=NULL)
                 m_renderer->render(m_disc,mv_matrix,m_proj_matrix);
    
            m_current_transformation=glm::scale(m_current_transformation,glm::vec3(1.0/scalings[splat_indices[i]][0],1.0/scalings[splat_indices[i]][1],1.0));
    
            m_current_transformation = m_current_transformation * orientations[splat_indices[i]];
            m_current_transformation = glm::translate(m_current_transformation,m_center);
    
            }
        }
    
    }