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;