diff --git a/CgQtViewer/CGQtGLRenderWidget.cpp b/CgQtViewer/CGQtGLRenderWidget.cpp index e2e53001af2fc28e99122a9aaef2ecc11bd70cde..7cb8ebf1fb84f51a686582561a6816ccdf44152b 100644 --- a/CgQtViewer/CGQtGLRenderWidget.cpp +++ b/CgQtViewer/CGQtGLRenderWidget.cpp @@ -32,8 +32,7 @@ CgQtGLRenderWidget::CgQtGLRenderWidget(QWidget *parent) m_lighting(false), m_use_splats(false), m_scene_control(NULL), - m_polygonmode(1) -{ + m_polygonmode(1) { m_core = QSurfaceFormat::defaultFormat().profile() == QSurfaceFormat::CoreProfile; // --transparent causes the clear color to be transparent. Therefore, on systems that // support it, the widget will become transparent apart from the logo. @@ -42,24 +41,17 @@ CgQtGLRenderWidget::CgQtGLRenderWidget(QWidget *parent) fmt.setAlphaBufferSize(8); setFormat(fmt); } - - - } -CgQtGLRenderWidget::~CgQtGLRenderWidget() -{ +CgQtGLRenderWidget::~CgQtGLRenderWidget() { cleanup(); } -void CgQtGLRenderWidget::redraw() -{ +void CgQtGLRenderWidget::redraw() { update(); } - -void CgQtGLRenderWidget::writeImageToFile(CgBaseImage* image,std::string filename) -{ +void CgQtGLRenderWidget::writeImageToFile(CgBaseImage* image,std::string filename) { QImage qimage(image->getSizeX(),image->getSizeY(),QImage::Format_RGB32); QRgb qvalue; glm::vec3 value; @@ -79,39 +71,31 @@ void CgQtGLRenderWidget::writeImageToFile(CgBaseImage* image,std::string filenam } -glm::mat4 CgQtGLRenderWidget::getTrackballRotation() -{ +glm::mat4 CgQtGLRenderWidget::getTrackballRotation() { return m_trackball->getRotationMatrix(); } +void CgQtGLRenderWidget::resetTrackballRotation() { + m_trackball->init(); +} -QSize CgQtGLRenderWidget::minimumSizeHint() const -{ +QSize CgQtGLRenderWidget::minimumSizeHint() const { return QSize(50, 50); } -QSize CgQtGLRenderWidget::sizeHint() const -{ +QSize CgQtGLRenderWidget::sizeHint() const { return QSize(400, 400); } - - -void CgQtGLRenderWidget::cleanup() -{ - if (m_program == NULL) - return; +void CgQtGLRenderWidget::cleanup() { + if (m_program == NULL) return; makeCurrent(); delete m_program; m_program = 0; doneCurrent(); } - - - -void CgQtGLRenderWidget::render(CgBaseRenderableObject* obj,glm::mat4 mv_matrix,glm::mat4 proj_matrix) -{ +void CgQtGLRenderWidget::render(CgBaseRenderableObject* obj, glm::mat4 mv_matrix, glm::mat4 proj_matrix) { glm::mat3 normal_matrix = glm::transpose(glm::inverse(glm::mat3(mv_matrix))); @@ -130,61 +114,49 @@ void CgQtGLRenderWidget::render(CgBaseRenderableObject* obj,glm::mat4 mv_matrix, } - -void CgQtGLRenderWidget::setUniformValue(std::string name,glm::mat3 val) -{ +void CgQtGLRenderWidget::setUniformValue(std::string name, glm::mat3 val) { if(m_attribute_locations.find(name)==m_attribute_locations.end()) m_attribute_locations.insert(std::make_pair(name, m_program->uniformLocation(name.c_str()))); m_program->bind(); m_program->setUniformValue(m_attribute_locations[name], QMatrix3x3(glm::value_ptr(val)).transposed()); } -void CgQtGLRenderWidget::setUniformValue(std::string name,glm::mat4 val) -{ +void CgQtGLRenderWidget::setUniformValue(std::string name, glm::mat4 val) { if(m_attribute_locations.find(name)==m_attribute_locations.end()) m_attribute_locations.insert(std::make_pair(name, m_program->uniformLocation(name.c_str()))); m_program->bind(); m_program->setUniformValue(m_attribute_locations[name], QMatrix4x4(glm::value_ptr(val)).transposed()); } - -void CgQtGLRenderWidget::setUniformValue(std::string name,glm::vec4 val) -{ +void CgQtGLRenderWidget::setUniformValue(std::string name, glm::vec4 val) { if(m_attribute_locations.find(name)==m_attribute_locations.end()) m_attribute_locations.insert(std::make_pair(name, m_program->uniformLocation(name.c_str()))); m_program->bind(); m_program->setUniformValue(m_attribute_locations[name],QVector4D(val.x,val.y,val.z,val.w)); } - -void CgQtGLRenderWidget::setUniformValue(std::string name,glm::vec3 val) -{ +void CgQtGLRenderWidget::setUniformValue(std::string name, glm::vec3 val) { if(m_attribute_locations.find(name)==m_attribute_locations.end()) m_attribute_locations.insert(std::make_pair(name, m_program->uniformLocation(name.c_str()))); m_program->bind(); m_program->setUniformValue(m_attribute_locations[name],QVector3D(val.x,val.y,val.z)); } -void CgQtGLRenderWidget::setUniformValue(std::string name,double val) -{ +void CgQtGLRenderWidget::setUniformValue(std::string name, double val) { if(m_attribute_locations.find(name)==m_attribute_locations.end()) m_attribute_locations.insert(std::make_pair(name, m_program->uniformLocation(name.c_str()))); m_program->bind(); m_program->setUniformValue(m_attribute_locations[name],(float)val); } -void CgQtGLRenderWidget::setUniformValue(std::string name,int val) -{ +void CgQtGLRenderWidget::setUniformValue(std::string name, int val) { if(m_attribute_locations.find(name)==m_attribute_locations.end()) m_attribute_locations.insert(std::make_pair(name, m_program->uniformLocation(name.c_str()))); m_program->bind(); m_program->setUniformValue(m_attribute_locations[name],(GLint)val); } - - -void CgQtGLRenderWidget::init(CgBaseRenderableObject* obj) -{ +void CgQtGLRenderWidget::init(CgBaseRenderableObject* obj) { CgQtGlBufferObject* bobj; if(m_gl_buffer_objects.find(obj->getID())!=m_gl_buffer_objects.end()) @@ -214,14 +186,9 @@ void CgQtGLRenderWidget::init(CgBaseRenderableObject* obj) bobj->initPointCloud((CgBasePointCloud*)obj); } - } - - - - -void CgQtGLRenderWidget::initializeGL() -{ +} +void CgQtGLRenderWidget::initializeGL() { m_trackball = new CgTrackball(); m_trackball->init(); @@ -250,32 +217,23 @@ void CgQtGLRenderWidget::initializeGL() m_program->bind(); - - - - // Light position is fixed. m_light_pos=glm::vec3(0.0,0.0,70.0); setUniformValue("mylightpos",m_light_pos); } -void CgQtGLRenderWidget::setShaderSourceFiles(std::string filename_vert,std::string filename_fragment) -{ - if(m_program->isLinked()) - m_program->release(); +void CgQtGLRenderWidget::setShaderSourceFiles(std::string filename_vert,std::string filename_fragment) { + if(m_program->isLinked()) + m_program->release(); - m_program->removeAllShaders(); - m_program->addShaderFromSourceFile(QOpenGLShader::Vertex,filename_vert.c_str()); - m_program->addShaderFromSourceFile(QOpenGLShader::Fragment,filename_fragment.c_str()); - m_program->link(); - m_program->bind(); + m_program->removeAllShaders(); + m_program->addShaderFromSourceFile(QOpenGLShader::Vertex,filename_vert.c_str()); + m_program->addShaderFromSourceFile(QOpenGLShader::Fragment,filename_fragment.c_str()); + m_program->link(); + m_program->bind(); } - - -void CgQtGLRenderWidget::paintGL() -{ - +void CgQtGLRenderWidget::paintGL() { switch(m_polygonmode) { @@ -288,7 +246,6 @@ void CgQtGLRenderWidget::paintGL() default: break; } - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_PROGRAM_POINT_SIZE); glEnable(GL_DEPTH_TEST); @@ -303,22 +260,17 @@ void CgQtGLRenderWidget::paintGL() if(m_scene_control!=NULL) m_scene_control->renderObjects(); - - m_program->release(); - } -void CgQtGLRenderWidget::resizeGL(int w, int h) -{ +void CgQtGLRenderWidget::resizeGL(int w, int h) { m_viewport_width=w; m_viewport_height=h; emit viewportChanged(w,h); } -void CgQtGLRenderWidget::mousePressEvent(QMouseEvent *event) -{ +void CgQtGLRenderWidget::mousePressEvent(QMouseEvent *event) { GLfloat w=(GLfloat)m_viewport_width; GLfloat h=(GLfloat)m_viewport_height; @@ -346,55 +298,39 @@ void CgQtGLRenderWidget::mousePressEvent(QMouseEvent *event) update(); } -void CgQtGLRenderWidget::mouseMoveEvent(QMouseEvent *event) -{ - - /* GLint viewport[4]; - glGetIntegerv(GL_VIEWPORT,viewport); - GLfloat w=(GLfloat)viewport[2]; - GLfloat h=(GLfloat)viewport[3]; -*/ +void CgQtGLRenderWidget::mouseMoveEvent(QMouseEvent *event) { GLfloat w=(GLfloat)m_viewport_width; GLfloat h=(GLfloat)m_viewport_height; - float x= (float)event->x(); - float y= (float)event->y(); - - + float x = (float)event->x(); + float y = (float)event->y(); // 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; + 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; + y = 2.0 * y / h - 1.0; + if (y < -1.0) y = -1.0; + if (y > 1.0) y = 1.0; - m_trackball->Ball_Mouse(glm::vec3(x,-y,0.0)); + m_trackball->Ball_Mouse(glm::vec3(x, -y, 0.0)); m_trackball->Ball_Update(); emit trackballChanged(); - emit mouseEvent(event); - - update(); + update(); } - -int CgQtGLRenderWidget::getViewportWidth() -{ +int CgQtGLRenderWidget::getViewportWidth() { return m_viewport_width; } -int CgQtGLRenderWidget::getViewportHeight() -{ +int CgQtGLRenderWidget::getViewportHeight() { return m_viewport_height; } - -void CgQtGLRenderWidget::mouseReleaseEvent(QMouseEvent *event) -{ +void CgQtGLRenderWidget::mouseReleaseEvent(QMouseEvent *event) { if(event->button()&Qt::LeftButton) { m_trackball->endDrag(); @@ -404,44 +340,34 @@ void CgQtGLRenderWidget::mouseReleaseEvent(QMouseEvent *event) update(); } - - -void CgQtGLRenderWidget::slotBackfaceCulling() -{ +void CgQtGLRenderWidget::slotBackfaceCulling() { m_backface_culling=!m_backface_culling; update(); } -void CgQtGLRenderWidget::slotLighting() -{ +void CgQtGLRenderWidget::slotLighting() { m_lighting=!m_lighting; update(); } -void CgQtGLRenderWidget::slotUseSplats() -{ +void CgQtGLRenderWidget::slotUseSplats() { m_use_splats=!m_use_splats; update(); } - - -void CgQtGLRenderWidget::slotRenderPoints() -{ +void CgQtGLRenderWidget::slotRenderPoints() { m_polygonmode=0; update(); } -void CgQtGLRenderWidget::slotRenderLines() -{ +void CgQtGLRenderWidget::slotRenderLines() { m_polygonmode=1; update(); } -void CgQtGLRenderWidget::slotRenderFilled() -{ +void CgQtGLRenderWidget::slotRenderFilled() { m_polygonmode=2; update(); } diff --git a/CgQtViewer/CgQtGLRenderWidget.h b/CgQtViewer/CgQtGLRenderWidget.h index 1969afc692e70748433e6dcbdd5dab0870f0c0ed..f066d48a2eb3827541a05e557aaf00fbc0c01183 100644 --- a/CgQtViewer/CgQtGLRenderWidget.h +++ b/CgQtViewer/CgQtGLRenderWidget.h @@ -42,6 +42,7 @@ public: void init(CgBaseRenderableObject*); glm::mat4 getTrackballRotation(); + void resetTrackballRotation(); void setSceneControl(CgBaseSceneControl* scene_control) {m_scene_control=scene_control;} diff --git a/CgQtViewer/CgQtGui.cpp b/CgQtViewer/CgQtGui.cpp index 5ea395670ca9d7e389aa40c14ab84f1bcd75a45e..7bff5da1a8be48570ea9509f00cf81b09778fbd0 100644 --- a/CgQtViewer/CgQtGui.cpp +++ b/CgQtViewer/CgQtGui.cpp @@ -37,21 +37,16 @@ -CgQtGui::CgQtGui(CgQtMainApplication *mw) - : m_mainWindow(mw) -{ +CgQtGui::CgQtGui(CgQtMainApplication *mw) : m_mainWindow(mw) { m_glRenderWidget = new CgQtGLRenderWidget; - connect(m_glRenderWidget, SIGNAL(mouseEvent(QMouseEvent*)), this, SLOT(mouseEvent(QMouseEvent*))); connect(m_glRenderWidget, SIGNAL(viewportChanged(int,int)), this, SLOT(viewportChanged(int,int))); connect(m_glRenderWidget, SIGNAL(trackballChanged()), this, SLOT(slotTrackballChanged())); - QVBoxLayout *mainLayout = new QVBoxLayout; QHBoxLayout *container = new QHBoxLayout; - QWidget *kdTreeOptionsWidget = new QWidget; createKdTreeOptionPanel(kdTreeOptionsWidget); @@ -74,14 +69,12 @@ CgQtGui::CgQtGui(CgQtMainApplication *mw) setLayout(mainLayout); setWindowTitle(tr("Exercise Visual Computing - Summer 2021")); - /* create Menu Bar */ m_menuBar = new QMenuBar; QMenu *file_menu = new QMenu("&File" ); file_menu->addAction("&Open Mesh Model", this, SLOT(slotLoadMeshFile())); file_menu->addAction("&Open Point Cloud", this, SLOT(slotLoadPointCloudFile())); - // todo: Add Quit-Action m_menuBar->addMenu( file_menu ); QMenu *settings_menu = new QMenu("&Setting" ); @@ -130,8 +123,7 @@ CgQtGui::CgQtGui(CgQtMainApplication *mw) m_mainWindow->setMenuBar(m_menuBar); } -QSlider *CgQtGui::createSlider() -{ +QSlider *CgQtGui::createSlider() { QSlider *slider = new QSlider(Qt::Vertical); slider->setRange(0, 360 * 16); slider->setSingleStep(16); @@ -141,8 +133,7 @@ QSlider *CgQtGui::createSlider() return slider; } -void CgQtGui::createKdTreeOptionPanel(QWidget* parent) -{ +void CgQtGui::createKdTreeOptionPanel(QWidget* parent) { QVBoxLayout *tab1_control = new QVBoxLayout(); /* checkbox for toggling the plane display*/ @@ -181,8 +172,7 @@ void CgQtGui::createKdTreeOptionPanel(QWidget* parent) parent->setLayout(tab1_control); } -void CgQtGui::createOptionPanelExample2(QWidget* parent) -{ +void CgQtGui::createOptionPanelExample2(QWidget* parent) { QVBoxLayout *tab2_control = new QVBoxLayout(); QHBoxLayout *subBox = new QHBoxLayout(); @@ -224,8 +214,7 @@ void CgQtGui::createOptionPanelExample2(QWidget* parent) } -void CgQtGui::slotButtonGroupSelectionChanged() -{ +void CgQtGui::slotButtonGroupSelectionChanged() { } @@ -239,45 +228,39 @@ void CgQtGui::slotKdDepthSpinboxChanged() { m_glRenderWidget->redraw(); } -void CgQtGui::slotLoadPointCloudFile() -{ +void CgQtGui::slotLoadPointCloudFile() { QString file= QFileDialog::getOpenFileName(this, tr("Open Obj-File"),"",tr("Model Files (*.obj)")); CgBaseEvent* e = new CgLoadPointCloudEvent(Cg::CgLoadPointCloudEvent, file.toStdString()); notifyObserver(e); } -void CgQtGui::slotSplatting() -{ +void CgQtGui::slotSplatting() { m_use_spats=!m_use_spats; CgBaseEvent* e = new CgSplatEvent(Cg::CgSplatEvent, m_use_spats); notifyObserver(e); } -void CgQtGui::slotPickRay() -{ +void CgQtGui::slotPickRay() { m_show_pickray=!m_show_pickray; CgBaseEvent* e = new CgPickRayEvent(Cg::CgPickRayEvent, m_show_pickray); notifyObserver(e); } -void CgQtGui::slotLoadMeshFile() -{ +void CgQtGui::slotLoadMeshFile() { QString file= QFileDialog::getOpenFileName(this, tr("Open Obj-File"),"",tr("Model Files (*.obj)")); CgBaseEvent* e = new CgLoadMeshEvent(Cg::CgLoadMeshEvent, file.toStdString()); notifyObserver(e); } -void CgQtGui::slotTrackballChanged() -{ +void CgQtGui::slotTrackballChanged() { CgBaseEvent* e = new CgTrackballEvent(Cg::CgTrackballEvent, m_glRenderWidget->getTrackballRotation()); notifyObserver(e); } -void CgQtGui::mouseEvent(QMouseEvent* event) -{ +void CgQtGui::mouseEvent(QMouseEvent* event) { if(event->type()==QEvent::MouseButtonPress) { @@ -314,7 +297,14 @@ void CgQtGui::wheelEvent(QWheelEvent* event) { } void CgQtGui::keyPressEvent(QKeyEvent *event) { - CgBaseEvent* e= new CgKeyEvent(Cg::CgKeyPressEvent,(Cg::Key)event->key(),(Cg::KeyboardModifiers)event->nativeModifiers(),event->text().toStdString()); + auto text = event->text().toStdString(); + if(text == "c") m_glRenderWidget->resetTrackballRotation(); + CgBaseEvent* e = new CgKeyEvent( + Cg::CgKeyPressEvent, + (Cg::Key)event->key(), + (Cg::KeyboardModifiers) event->nativeModifiers(), + text + ); notifyObserver(e); } @@ -324,9 +314,6 @@ void CgQtGui::viewportChanged(int w, int h) { notifyObserver(e); } - - - CgBaseRenderer* CgQtGui::getRenderer() { return m_glRenderWidget; diff --git a/CgQtViewer/CgTrackball.cpp b/CgQtViewer/CgTrackball.cpp index 62871aeb92d8bb849a9f4ef60ef513d38053abcb..ca816ae62cf68b04e695254d0e92e6695fb6a8ce 100644 --- a/CgQtViewer/CgTrackball.cpp +++ b/CgQtViewer/CgTrackball.cpp @@ -1,49 +1,40 @@ #include "CgTrackball.h" - - CgTrackball::CgTrackball() :center(0.0), vNow(0.0,0.0,0.0), vDown(0.0,0.0,0.0), qNow(1.0,0.0,0.0,0.0), -qDown(1.0,0.0,0.0,0.0) -{ +qDown(1.0,0.0,0.0,0.0) { init(); } - /* Establish reasonable initial values for controller. */ -void CgTrackball::init(const glm::mat4& m) -{ - mNow= mDown=m; - qDown=glm::quat_cast(mNow); +void CgTrackball::init(const glm::mat4& m) { + mNow = mDown = m; + qDown = glm::quat_cast(mNow); radius = 1.0; - dragging = false; + dragging = false; } /* Set the center and size of the controller. */ -void CgTrackball::place(const glm::vec3& ncenter, float nradius) -{ +void CgTrackball::place(const glm::vec3& ncenter, float nradius) { center = ncenter; radius = nradius; } /* Incorporate new mouse position. */ -void CgTrackball::Ball_Mouse(glm::vec3 nvNow) -{ +void CgTrackball::Ball_Mouse(glm::vec3 nvNow) { vNow = nvNow; } /* Using vDown, vNow, dragging, compute rotation etc. */ -void CgTrackball::Ball_Update() -{ +void CgTrackball::Ball_Update() { vFrom = MouseOnSphere(vDown, center, radius); vTo = MouseOnSphere(vNow, center, radius); - if (dragging) - { + if (dragging) { // construct unit quaternion from two points on sphere glm::vec3 perp = glm::cross(vFrom,vTo); float angle = glm::dot(vFrom,vTo); @@ -51,38 +42,30 @@ void CgTrackball::Ball_Update() qNow = qDrag * qDown; } Qt_ToBallPoints(qDown, &vrFrom, &vrTo); - mNow = glm::mat4_cast(qNow); - } /* Return rotation matrix defined by controller use. */ -const glm::mat4& CgTrackball::getRotationMatrix() -{ +const glm::mat4& CgTrackball::getRotationMatrix() { return mNow; } - /* Begin drag sequence. */ -void CgTrackball::beginDrag() -{ +void CgTrackball::beginDrag() { dragging = true; vDown = vNow; - vTo = vFrom; + vTo = vFrom; } /* Stop drag sequence. */ -void CgTrackball::endDrag() -{ - +void CgTrackball::endDrag() { dragging = false; qDown = qNow; mDown = mNow; } /* Convert window coordinates to sphere coordinates. */ -glm::vec3 CgTrackball::MouseOnSphere(glm::vec3 mouse, glm::vec3 ballCenter, float ballRadius) -{ +glm::vec3 CgTrackball::MouseOnSphere(glm::vec3 mouse, glm::vec3 ballCenter, float ballRadius) { glm::vec3 ballMouse; float mag; @@ -90,7 +73,7 @@ glm::vec3 CgTrackball::MouseOnSphere(glm::vec3 mouse, glm::vec3 ballCenter, floa ballMouse.y = (mouse.y - ballCenter.y) / ballRadius; mag = ballMouse.x*ballMouse.x + ballMouse.y*ballMouse.y; if (mag > 1.0) { - float scale = 1.0f/sqrt(mag); + float scale = 1.0f / sqrt(mag); ballMouse.x *= scale; ballMouse.y *= scale; ballMouse.z = 0.0; } else { @@ -99,10 +82,8 @@ glm::vec3 CgTrackball::MouseOnSphere(glm::vec3 mouse, glm::vec3 ballCenter, floa return (ballMouse); } - /* Convert a unit quaternion to two points on unit sphere */ -void CgTrackball::Qt_ToBallPoints(glm::quat q, glm::vec3 *arcFrom, glm::vec3 *arcTo) -{ +void CgTrackball::Qt_ToBallPoints(glm::quat q, glm::vec3 *arcFrom, glm::vec3 *arcTo) { double s; s = sqrt(q.x*q.x + q.y*q.y); if (s == 0.0) { @@ -119,12 +100,8 @@ void CgTrackball::Qt_ToBallPoints(glm::quat q, glm::vec3 *arcFrom, glm::vec3 *ar if (q.w < 0.0) *arcFrom = glm::vec3(-arcFrom->x, -arcFrom->y, 0.0); } - - - /* Force sphere point to be perpendicular to axis. */ -glm::vec3 CgTrackball::ConstrainToAxis(glm::vec3 loose, glm::vec3 axis) -{ +glm::vec3 CgTrackball::ConstrainToAxis(glm::vec3 loose, glm::vec3 axis) { glm::vec3 onPlane = loose - axis * glm::dot(axis, loose); @@ -141,8 +118,7 @@ glm::vec3 CgTrackball::ConstrainToAxis(glm::vec3 loose, glm::vec3 axis) } /* Find the index of nearest arc of axis set. */ -unsigned int CgTrackball::NearestConstraintAxis(glm::vec3 loose, std::vector<glm::vec3> axes) -{ +unsigned int CgTrackball::NearestConstraintAxis(glm::vec3 loose, std::vector<glm::vec3> axes) { glm::vec3 onPlane; float max, dot; unsigned int i, nearest; diff --git a/CgQtViewer/CgTrackball.h b/CgQtViewer/CgTrackball.h index 57163117e15a6c87544ca7f1166b00ff5e33cf01..00d18a683ac81b44ab4381be74b93be4a31af452 100644 --- a/CgQtViewer/CgTrackball.h +++ b/CgQtViewer/CgTrackball.h @@ -4,7 +4,6 @@ #define GLM_ENABLE_EXPERIMENTAL #include <vector> - #include <glm/glm.hpp> #include <glm/gtx/quaternion.hpp> @@ -26,16 +25,12 @@ class CgTrackball { void Ball_Update(); private: - - glm::vec3 MouseOnSphere(glm::vec3 mouse, glm::vec3 ballCenter, float ballRadius); void Qt_ToBallPoints(glm::quat q, glm::vec3 *arcFrom, glm::vec3 *arcTo); glm::vec3 ConstrainToAxis(glm::vec3 loose, glm::vec3 axis); unsigned int NearestConstraintAxis(glm::vec3 loose, std::vector<glm::vec3> axes); - - glm::vec3 center; float radius; @@ -43,7 +38,7 @@ private: glm::vec3 vNow, vDown, vFrom, vTo, vrFrom, vrTo; bool showResult, dragging; - glm::mat4 mNow,mDown; + glm::mat4 mNow, mDown; glm::quat qNow, qDown, qDrag; diff --git a/CgSceneGraph/CgPointCloud.cpp b/CgSceneGraph/CgPointCloud.cpp index d640829cd253d0230e461ffe8d4f0be23450c857..52ce4f143e92ebf55975596da8d00d090c7153bd 100644 --- a/CgSceneGraph/CgPointCloud.cpp +++ b/CgSceneGraph/CgPointCloud.cpp @@ -61,20 +61,22 @@ void CgPointCloud::init( std::string filename, bool cheat_normals) { ObjLoader loader; loader.load(filename); loader.getPositionData(m_vertices); + std::cout << "got " << m_vertices.size() << " points" << std::endl; + + buildKdTree(&m_vertices.front(), &(*(m_vertices.end() - 1)), 0); + calculateAABB(); + estimateNormals(); // do this for cheating with the normals // you need to replace this by a normal estimation algorithm if(cheat_normals) loader.getNormalData(m_vertex_normals); - buildKdTree(&m_vertices.front(), &(*(m_vertices.end() - 1)), 0); - // calculate local coordinate system for splats // (arbitrary orientation of ellipse in plane) // replace this if you have the real coordinate // system, use up vector = y-Axis of your local // coordinate system instead of getPerpendicularVector(...) calculateSplatOrientations(); - calculateAABB(); //add a standard color for each point if lighting turned off for(unsigned int i = 0;i < m_vertices.size(); i++) { @@ -110,6 +112,30 @@ void CgPointCloud::buildKdTree(glm::vec3* begin, glm::vec3* end, int depth) { } } +void CgPointCloud::estimateNormals() { + // find point with highest y-value + std::vector<unsigned int> spanning_tree(m_vertices.size()); + float max_y =-std::numeric_limits<float>::infinity(); + unsigned int max_y_index = 0; + for(int i = 0; i < m_vertices.size(); i++) { + float curr = m_vertices[i].y; + if(max_y < curr) { + max_y = curr; + max_y_index = i; + } + } + // the extremal point is selected as root (has no parent) + spanning_tree[max_y_index] = max_y_index; + + // build minimal spanning tree (for each index, record the index we came from) + // traverse the tree, search neighborhoods + // estimate normal: + // calc centroid + // create covariance matrix + // select shortest eigenvector + // select normal pointing roughly in the same direction as parent's normal +} + void CgPointCloud::traverseBFO(std::function<void(glm::vec3*, const unsigned int)> fn) { // queue of pairs of vec3 pointers // (range of points in the current node and its children) @@ -304,14 +330,11 @@ void CgPointCloud::resetColors(glm::vec3 color) { // calculates an arbitrary verctor perpendicular to the given one glm::vec3 CgPointCloud::getPerpendicularVector(glm::vec3 arg) { - if((arg[0]==0.0)&&(arg[1]==0.0)) - { - if(arg[2]==0.0) - return glm::vec3(0.); - - return glm::vec3(0.0,1.0,0.0); - } - return glm::normalize(glm::vec3(-arg[1],arg[0],0.0)); + if((arg.x == 0.0) && (arg.y == 0.0)) { + if(arg.z == 0.0) return glm::vec3(0.); + return glm::vec3(0.0, 1.0, 0.0); + } + return glm::normalize(glm::vec3(-arg.y, arg.x, 0.0)); } const glm::vec3 CgPointCloud::getCenter() const { @@ -341,7 +364,7 @@ void CgPointCloud::calculateAABB() { min_z = min_z > curr[2] ? curr[2] : min_z; } - m_aabb.position = glm::vec3((max_x + min_x) * 0.5, (max_y + min_y) * 0.5, (max_z + min_z) * 0.5); + m_aabb.position = glm::vec3((max_x + min_x) * 0.5, (max_y + min_y) * 0.5, (max_z + min_z) * 0.5); m_aabb.extent = glm::vec3((max_x - min_x) * 0.5, (max_y - min_y) * 0.5, (max_z - min_z) * 0.5); } diff --git a/CgSceneGraph/CgPointCloud.h b/CgSceneGraph/CgPointCloud.h index 80938b8870c8f7bd29cda8320adf4a90ea3fc38c..8dc2d091258aa0ecccdc79ff9ff9a3f2a3179eab 100644 --- a/CgSceneGraph/CgPointCloud.h +++ b/CgSceneGraph/CgPointCloud.h @@ -87,6 +87,7 @@ private: // rearrange the vec3 between begin and end so they form a kd-tree void buildKdTree(glm::vec3* begin, glm::vec3* end, int depth); + void estimateNormals(); std::vector<glm::vec3> m_vertices; std::vector<glm::vec3> m_vertex_normals; diff --git a/CgSceneGraph/CgPolyLine.cpp b/CgSceneGraph/CgPolyLine.cpp index 884a0e2b4c9a7dcbffffc5b5cff3dcf7eea4bcf6..36a20e8ebbb773f40b45232516e7b01aee6ce319 100644 --- a/CgSceneGraph/CgPolyLine.cpp +++ b/CgSceneGraph/CgPolyLine.cpp @@ -17,19 +17,16 @@ m_linewidth(1.0) CgPolyLine::CgPolyLine(int id,std::vector<glm::vec3> points): m_type(Cg::Polyline), m_id(id), -m_linewidth(1.0) -{ +m_linewidth(1.0) { m_vertices.clear(); m_vertices=points; - for(unsigned int i=0;i<m_vertices.size();i++) - { + for(unsigned int i=0;i<m_vertices.size();i++) { m_vertex_colors.push_back(glm::vec3(0.0,0.0,1.0)); - } + } } -CgPolyLine::~CgPolyLine() -{ +CgPolyLine::~CgPolyLine() { m_vertices.clear(); m_vertex_colors.clear(); } diff --git a/CgSceneGraph/CgSceneControl.cpp b/CgSceneGraph/CgSceneControl.cpp index e4ae4fb44a625005ab3db028e1c5d86b3714d23b..47d30c11c824db72868c7774e9f0017c38b2453d 100644 --- a/CgSceneGraph/CgSceneControl.cpp +++ b/CgSceneGraph/CgSceneControl.cpp @@ -57,8 +57,7 @@ CgSceneControl::CgSceneControl() } void CgSceneControl::resetTransform() { - m_current_translation = glm::mat4(1.0); - m_current_translation = glm::translate(m_current_translation, glm::vec3(0.0, 0.0, -2.0)); + m_current_translation = glm::translate(glm::mat4(1.0), glm::vec3(0.0, 0.0, -2.0)); m_current_scale = glm::mat4(1.0); m_current_rotation = glm::mat4(1.0); m_current_transformation = glm::mat4(1.0); @@ -75,6 +74,7 @@ CgSceneControl::~CgSceneControl() delete m_disc; if(m_select_ray!=NULL) delete m_select_ray; + for(int i = 0; i < m_kd_tree_mesh.size(); i++) delete m_kd_tree_mesh[i]; m_kd_tree_mesh.clear(); } @@ -120,8 +120,7 @@ void CgSceneControl::calculatePickRay(float x, float y) { } -void CgSceneControl::calculateEigenDecomposition3x3() -{ +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; @@ -133,8 +132,7 @@ void CgSceneControl::calculateEigenDecomposition3x3() std::cout << glm::to_string(eigenvectors) << std::endl; } -void CgSceneControl::calculateSingularValueDecomposition() -{ +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; @@ -214,48 +212,46 @@ void CgSceneControl::createKdTreeViz(int max_depth) { } } -void CgSceneControl::handleEvent(CgBaseEvent* e) -{ +void CgSceneControl::handlePickEvent(float x, float y) { + calculatePickRay(x, y); + if(m_pointcloud != nullptr) { + std::vector<glm::vec3> points = m_select_ray->getVertices(); + glm::vec3 start = points[0]; + glm::vec3 direction = points[1] - start; + int picked_index = m_pointcloud->getClosestPointToRay(start, direction); + if(picked_index != -1) { // -1 => point found + std::vector<unsigned int> neighbors = m_pointcloud->getNearestNeighborsFast(picked_index, 50); + m_pointcloud->resetColors(glm::vec3(0.0, 0.75, 0.0)); + m_pointcloud->setColors(neighbors, glm::vec3(0.75, 0.0, 0.0)); + m_pointcloud->setColors({picked_index}, glm::vec3(1.0, 1.0, 0.0)); + m_renderer->init(m_pointcloud); + m_renderer->redraw(); + } + } +} + +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::CgMouseButtonPress) - { + if(e->getType() & Cg::CgMouseButtonPress) { CgMouseEvent* ev = (CgMouseEvent*)e; if(ev->button()== Cg::RightButton) { - calculatePickRay((double)ev->x(),(double)ev->y()); - if(m_pointcloud != nullptr) { - std::vector<glm::vec3> points = m_select_ray->getVertices(); - glm::vec3 start = points[0]; - glm::vec3 direction = points[1] - start; - int picked_index = m_pointcloud->getClosestPointToRay(start, direction); - if(picked_index != -1) { // -1 => point found - std::vector<unsigned int> neighbors = m_pointcloud->getNearestNeighborsFast(picked_index, 50); - m_pointcloud->resetColors(glm::vec3(0.0, 0.75, 0.0)); - m_pointcloud->setColors(neighbors, glm::vec3(0.75, 0.0, 0.0)); - m_pointcloud->setColors({picked_index}, glm::vec3(1.0, 1.0, 0.0)); - m_renderer->init(m_pointcloud); - m_renderer->redraw(); - } - } + handlePickEvent(ev->x(), ev->y()); } else if(ev->button() == Cg::MiddleButton) { m_drag_center = glm::vec2((double)ev->x(), (double)ev->y()); m_is_dragging = true; } } - if(e->getType() & Cg::CgMouseButtonRelease) - { + if(e->getType() & Cg::CgMouseButtonRelease) { CgMouseEvent* ev = (CgMouseEvent*) e; - if(ev->button() == Cg::MiddleButton) - { + if(ev->button() == Cg::MiddleButton) { m_is_dragging = false; } } - if(e->getType() & Cg::CgMouseMove) - { - if(!m_is_dragging) return; + if(e->getType() & Cg::CgMouseMove && m_is_dragging) { CgMouseEvent* ev = (CgMouseEvent*) e; glm::vec2 new_center = glm::vec2(ev->x(), ev->y()); glm::vec3 delta = glm::vec3( @@ -270,8 +266,7 @@ void CgSceneControl::handleEvent(CgBaseEvent* e) m_renderer->redraw(); } - if(e->getType() & Cg::CgMouseWheel) - { + 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(); @@ -279,10 +274,8 @@ void CgSceneControl::handleEvent(CgBaseEvent* e) m_renderer->redraw(); } - if(e->getType() & Cg::CgTrackballEvent) - { - CgTrackballEvent* ev = (CgTrackballEvent*)e; - + if(e->getType() & Cg::CgTrackballEvent) { + CgTrackballEvent* ev = (CgTrackballEvent*) e; m_current_rotation = ev->getRotationMatrix(); m_renderer->redraw(); } @@ -290,16 +283,15 @@ void CgSceneControl::handleEvent(CgBaseEvent* e) // any kind of KeyEvents can be checked via CgEvent::CgKeyEvent // see CgEvent enums in CgEnums.h - if(e->getType() & Cg::CgKeyEvent) - { + if(e->getType() & Cg::CgKeyEvent) { CgKeyEvent* ev = (CgKeyEvent*)e; - if(ev->text()=="e") { + if(ev->text() == "e") { // example usage of eigen library to compute the eigen-decomposition of a matrix calculateEigenDecomposition3x3(); } - if(ev->text()=="s") { + if(ev->text() == "s") { // example usage of eigen library to compute the eigen-decomposition of a matrix calculateSingularValueDecomposition(); } @@ -309,35 +301,30 @@ void CgSceneControl::handleEvent(CgBaseEvent* e) m_renderer->redraw(); } - if(ev->text()=="+") - { + 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; + 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()=="-") - { + 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; + 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) - { + 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) - { + if(e->getType() & Cg::CgPickRayEvent) { // checkbox in GUI changed for showing/hiding pick ray CgPickRayEvent* ev = (CgPickRayEvent*)e; m_show_pickray=ev->showPickRay(); @@ -352,15 +339,13 @@ void CgSceneControl::handleEvent(CgBaseEvent* e) m_renderer->redraw(); } - if(e->getType() & Cg::WindowResizeEvent) - { + 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) - { + if(e->getType() & Cg::CgLoadPointCloudEvent) { CgLoadPointCloudEvent* ev = (CgLoadPointCloudEvent*)e; ObjLoader* loader= new ObjLoader(); @@ -391,8 +376,7 @@ void CgSceneControl::handleEvent(CgBaseEvent* e) } - if(e->getType() & Cg::CgLoadMeshEvent) - { + if(e->getType() & Cg::CgLoadMeshEvent) { CgLoadMeshEvent* ev = (CgLoadMeshEvent*)e; ObjLoader* loader= new ObjLoader(); @@ -426,10 +410,6 @@ void CgSceneControl::handleEvent(CgBaseEvent* e) delete e; } - - - - // rendering stuff /*******************************************************************************************************/ @@ -460,7 +440,7 @@ void CgSceneControl::renderObjects() { if(m_triangle_mesh != nullptr) { m_current_transformation = glm::translate(m_current_transformation, -m_center); - glm::mat4 mv_matrix = m_lookAt_matrix * m_current_transformation ; + glm::mat4 mv_matrix = m_lookAt_matrix * m_current_transformation; m_renderer->render(m_triangle_mesh, mv_matrix, m_proj_matrix); m_current_transformation = glm::translate(m_current_transformation, m_center); } diff --git a/CgSceneGraph/CgSceneControl.h b/CgSceneGraph/CgSceneControl.h index d919d4ba0106985c461bfcfd9c272ed190dacaee..741aefb55b858e3db902c78fa0f0d2bc64ad7c1a 100644 --- a/CgSceneGraph/CgSceneControl.h +++ b/CgSceneGraph/CgSceneControl.h @@ -42,6 +42,7 @@ private: void calculateEigenDecomposition3x3(); void calculateSingularValueDecomposition(); void createKdTreeViz(int max_depth); + void handlePickEvent(float x, float y); // one single Disc used as Object to render the spats (in own local coordinates) CgTriangleMesh* m_disc;