diff --git a/CgSceneGraph/CgKdTree.cpp b/CgSceneGraph/CgKdTree.cpp
deleted file mode 100644
index 77e9fb6af797f49902297db666de20c1929d1ce1..0000000000000000000000000000000000000000
--- a/CgSceneGraph/CgKdTree.cpp
+++ /dev/null
@@ -1,72 +0,0 @@
-#include "CgKdTree.h"
-
-CgKdTree::CgKdTree() {
-
-}
-
-CgKdTree::~CgKdTree() {
-    m_points.clear();
-}
-
-void CgKdTree::buildTree(glm::vec3* begin, glm::vec3* end, int depth) {
-    auto half_size = (end - begin) / 2;
-
-    if(begin == end || half_size == 0) {
-        // zero or one element, nothing to do 
-        return;
-    } else { 
-        // more than one element!
-
-        // partially sort and ensure median element 
-        // is in the middle (runs in O(n))
-        // about 4x faster on tyra.obj than std::sort
-        std::nth_element(begin, begin + half_size, end, [=](glm::vec3 a, glm::vec3 b) {
-            return a[depth % 3] < b[depth % 3];
-        });
-
-        // split array in two (excluding median) and recurse
-        buildTree(begin, begin + half_size, depth + 1);
-        buildTree(begin + half_size + 1, end, depth + 1);
-    }
-}
-
-void CgKdTree::init(std::vector<glm::vec3>& points) {
-    // copy points for now.
-    m_points = points;
-    buildTree(&m_points.front(), &(*(m_points.end() - 1)), 0);
-}
-
-std::vector<int> CgKdTree::getNearestNeighbors(int current_point, unsigned int k) {
-    std::vector<int> erg(k);
-    std::iota(erg.begin(), erg.end(), 0);
-    return erg;
-}
-
-void CgKdTree::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)
-    std::queue<std::pair<glm::vec3*, glm::vec3*>> q;
-    if(m_points.empty()) return;
-    unsigned int depth = 0;
-    q.push({&m_points.front(), &(*(m_points.end() - 1))});
-    while(!q.empty()) {
-        int level_count = q.size();
-        for(int i = 0; i < level_count; i++) {
-            auto curr = q.front();
-            glm::vec3* begin = curr.first;
-            glm::vec3* end = curr.second;
-            unsigned int half_size = (end - begin) / 2;
-            glm::vec3* curr_pointer = begin + half_size;
-            fn(curr_pointer, depth);
-            // push left & right half of array to reconstruct splits
-            if(half_size != 0) q.push({begin, begin + half_size});
-            if(begin + half_size != end) q.push({begin + half_size + 1, end});
-            q.pop();
-        }
-        depth += 1;
-    }
-}
-
-const std::vector<glm::vec3>& CgKdTree::getVertices() const {
-    return m_points;
-}
\ No newline at end of file
diff --git a/CgSceneGraph/CgKdTree.h b/CgSceneGraph/CgKdTree.h
deleted file mode 100644
index 228c39ddcae161e51c65316cb43034e5a2ec86a9..0000000000000000000000000000000000000000
--- a/CgSceneGraph/CgKdTree.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#ifndef CGKDTREE_H
-#define CGKDTREE_H
-
-#include <vector>
-#include <queue>
-#include <glm/glm.hpp>
-#include <string>
-#include <iostream>
-#include <algorithm>
-#include <numeric>
-#include <utility>
-#include <functional>
-
-class CgKdTree
-{
-public:
-  CgKdTree();
-  ~CgKdTree();
-  void init(std::vector<glm::vec3>& points);
-  std::vector<int> getNearestNeighbors(int current_point,unsigned int k);
-  std::vector<double> getSplits();
-  const std::vector<glm::vec3>& getVertices() const;
-  // traverse the tree in BFO and call a function on each node
-  void traverseBFO(std::function<void(glm::vec3*, const unsigned int)> fn);
-
-private:
-    // builds a kd-tree between the pointers begin and end
-    void buildTree(glm::vec3* begin, glm::vec3* end, int depth);
-    std::vector<glm::vec3> m_points;
-};
-
-#endif // CGKDTREE_H
\ No newline at end of file
diff --git a/CgSceneGraph/CgPointCloud.cpp b/CgSceneGraph/CgPointCloud.cpp
index b79cba5c43af9af8a7c6a729b01cf5df77293162..c419e3f0b6816e4bcf0071d5ab44518e914c319b 100644
--- a/CgSceneGraph/CgPointCloud.cpp
+++ b/CgSceneGraph/CgPointCloud.cpp
@@ -9,20 +9,15 @@ CgPointCloud::CgPointCloud(51)
 
 CgPointCloud::CgPointCloud(int id):
 m_type(Cg::PointCloud),
-m_id(id)
-{
-
+m_id(id) {
     m_vertices.push_back(glm::vec3(0.0,0.0,0.0));
     m_vertex_normals.push_back(glm::vec3(0.0,0.0,1.0));
     m_vertex_colors.push_back(glm::vec3(0.0,0.0,1.0));
-
     calculateSplatOrientations();
-
 }
 
 
-CgPointCloud::~CgPointCloud()
-{
+CgPointCloud::~CgPointCloud() {
     m_vertices.clear();
     m_vertex_normals.clear();
     m_vertex_colors.clear();
@@ -30,8 +25,7 @@ CgPointCloud::~CgPointCloud()
 }
 
 
-void CgPointCloud::calculateSplatOrientations()
-{
+void CgPointCloud::calculateSplatOrientations() {
   // 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(...)
 
@@ -52,15 +46,6 @@ void CgPointCloud::calculateSplatOrientations()
 
 }
 
-CgKdTree* CgPointCloud::getKdTree() {
-  return &m_kd_tree;
-}
-
-const std::vector<glm::vec3>& CgPointCloud::getVertices() const {
-  return m_kd_tree.getVertices();
-}
-
-
 void CgPointCloud::init( std::string filename, bool cheat_normals)
 {
     m_vertices.clear();
@@ -74,44 +59,83 @@ void CgPointCloud::init( std::string filename, bool cheat_normals)
     ObjLoader loader;
     loader.load(filename);
     loader.getPositionData(m_vertices);
-    m_kd_tree.init(m_vertices);
-    //run_timed(10, [=]{m_kd_tree.init(m_vertices);});
 
     // 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);
+    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(...)
-
+    // 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();
 
     //add a standard color for each point if lighting turned off
-    for(unsigned int i=0;i<m_vertices.size();i++)
-      {
-          m_vertex_colors.push_back(glm::vec3(0.0,1.0,0.0));
-      }
-
-
-    //test of getNeartestNeighbors(..) method
-    // generates blue dots on the tail of the bunny
+    for(unsigned int i=0;i<m_vertices.size();i++) {
+      m_vertex_colors.push_back(glm::vec3(0.0,1.0,0.0));
+    }
 
     unsigned int k=50;
-    std::vector<int> neighbors = m_kd_tree.getNearestNeighbors(0,k);
+    std::vector<int> neighbors = getNearestNeighbors(0,k);
 
-    for(unsigned int i=0;i<k;i++)
-      {
-        m_vertex_colors[neighbors[i]]=glm::vec3(0.0,0.0,1.0);
-      }
+    for(unsigned int i = 0;i < k; i++) {
+      m_vertex_colors[neighbors[i]] = glm::vec3(0.0,0.0,1.0);
+    }
 }
 
+void CgPointCloud::buildKdTree(glm::vec3* begin, glm::vec3* end, int depth) {
+    auto half_size = (end - begin) / 2;
+
+    if(begin == end || half_size == 0) {
+        // zero or one element, nothing to do 
+        return;
+    } else { 
+        // more than one element!
+
+        // partially sort and ensure median element 
+        // is in the middle (runs in O(n))
+        // about 4x faster on tyra.obj than std::sort
+        std::nth_element(begin, begin + half_size, end, [=](glm::vec3 a, glm::vec3 b) {
+            return a[depth % 3] < b[depth % 3];
+        });
+
+        // split array in two (excluding median) and recurse
+        buildKdTree(begin, begin + half_size, depth + 1);
+        buildKdTree(begin + half_size + 1, end, depth + 1);
+    }
+}
 
-std::vector<int> CgPointCloud::getNearestNeighbors(int current_point,unsigned int k)
-{
+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)
+    std::queue<std::pair<glm::vec3*, glm::vec3*>> q;
+    if(m_vertices.empty()) return;
+    unsigned int depth = 0;
+    q.push({&m_vertices.front(), &(*(m_vertices.end() - 1))});
+    while(!q.empty()) {
+        int level_count = q.size();
+        for(int i = 0; i < level_count; i++) {
+            auto curr = q.front();
+            glm::vec3* begin = curr.first;
+            glm::vec3* end = curr.second;
+            unsigned int half_size = (end - begin) / 2;
+            glm::vec3* curr_pointer = begin + half_size;
+            fn(curr_pointer, depth);
+            // push left & right half of array to reconstruct splits
+            if(half_size != 0) q.push({begin, begin + half_size});
+            if(begin + half_size != end) q.push({begin + half_size + 1, end});
+            q.pop();
+        }
+        depth += 1;
+    }
+}
+
+std::vector<int> CgPointCloud::getNearestNeighbors(int current_point,unsigned int k) {
 
-  glm::vec3 q= m_vertices[current_point];
+  glm::vec3 q = m_vertices[current_point];
 
   std::vector<std::pair<double,int>> distances;
 
diff --git a/CgSceneGraph/CgPointCloud.h b/CgSceneGraph/CgPointCloud.h
index 83ddbbcb97246db2f6e246ef1456b2a28c950884..ddbfba204b3082b2074a2fcbfeff26287e7730f5 100644
--- a/CgSceneGraph/CgPointCloud.h
+++ b/CgSceneGraph/CgPointCloud.h
@@ -2,16 +2,20 @@
 #define CGPOINTCLOUD_H
 
 #include <vector>
+#include <queue>
 #include <limits>
 #include <glm/glm.hpp>
 #include <string>
+#include <algorithm>
+#include <iostream>
+#include <numeric>
+#include <utility>
+#include <functional>
 #include "CgBase/CgBasePointCloud.h"
-#include "CgSceneGraph/CgKdTree.h"
 #include "CgSceneGraph/CgAABB.h"
 #include "CgBase/CgEnums.h"
 #include "CgUtils/ObjLoader.h"
 #include <glm/gtc/matrix_transform.hpp>
-#include <algorithm>
 
 class CgPointCloud : public CgBasePointCloud
 {
@@ -49,14 +53,15 @@ public:
   // read a dataset from file, can cheat the normals, i.e read the mormals from file
   void init( std::string filename, bool cheat_normals=false);
 
-  CgKdTree* getKdTree();
-
   // the center of gravity of the object, for rendering
   const glm::vec3 getCenter() const;
 
   // returns the point clouds AABB
   const CgAABB getAABB() const;
 
+  // traverse the kd-tree in BFO and call a function on each node
+  void traverseBFO(std::function<void(glm::vec3*, const unsigned int)> fn);
+
 private:
 
     // the following demonstration methods have to be replaced by your own calculations
@@ -68,13 +73,14 @@ private:
     glm::vec3 getPerpendicularVector(glm::vec3 arg);
 
     // for demonstration purposes, very inefficient
-    std::vector<int> getNearestNeighbors(int current_point,unsigned int k);
+    std::vector<int> getNearestNeighbors(int current_point, unsigned int k);
 
+    // rearrange the vec3 between begin and end so they form a kd-tree
+    void buildKdTree(glm::vec3* begin, glm::vec3* end, int depth);
 
     std::vector<glm::vec3> m_vertices;
     std::vector<glm::vec3> m_vertex_normals;
     std::vector<glm::vec3> m_vertex_colors;
-    CgKdTree m_kd_tree;
 
     // indices of vertices for which a splat will be rendered
     std::vector<unsigned int> m_splat_indices;
@@ -85,12 +91,11 @@ private:
 
     const Cg::ObjectType m_type;
     const unsigned int m_id;
-
-
 };
 
 inline Cg::ObjectType  CgPointCloud::getType() const {return m_type;}
 inline unsigned int CgPointCloud::getID() const {return m_id;}
+inline const std::vector<glm::vec3>& CgPointCloud::getVertices() const{return m_vertices;}
 inline const std::vector<glm::vec3>& CgPointCloud::getVertexNormals() const{return m_vertex_normals;}
 inline const std::vector<glm::vec3>& CgPointCloud::getVertexColors() const{return m_vertex_colors;}
 inline const std::vector<glm::mat4>& CgPointCloud::getSplatOrientations() const{return m_splat_orientations;}
diff --git a/CgSceneGraph/CgSceneControl.cpp b/CgSceneGraph/CgSceneControl.cpp
index a40c1dd16cfbc9740f55db704971797295b35424..997e33991b5d00b64a0864a2ea22003203400c0d 100644
--- a/CgSceneGraph/CgSceneControl.cpp
+++ b/CgSceneGraph/CgSceneControl.cpp
@@ -177,7 +177,7 @@ void CgSceneControl::createKdTreeViz(int max_depth) {
   // recalculate mesh
   if(m_pointcloud != nullptr && max_depth != -1) {
     std::vector<double> splits;
-    m_pointcloud->getKdTree()->traverseBFO([&](glm::vec3* point, unsigned int depth) {
+    m_pointcloud->traverseBFO([&](glm::vec3* point, unsigned int depth) {
         splits.push_back((*point)[depth % 3]);
     });
     std::queue<CgAABB> aabb_queue;
diff --git a/ExerciseVC.pro b/ExerciseVC.pro
index aabdf813e2bb4f62fff05a902764c57e4e50546d..f7cb3432e8ffd2006512908262d5de3db9ae01dd 100644
--- a/ExerciseVC.pro
+++ b/ExerciseVC.pro
@@ -26,7 +26,6 @@ SOURCES += main.cpp \
     CgQtViewer/CgTrackball.cpp \
     CgEvents/CgWindowResizeEvent.cpp \
     CgSceneGraph/CgTriangleMesh.cpp \
-    CgSceneGraph/CgKdTree.cpp \
     CgUtils/ObjLoader.cpp \
     CgEvents/CgTrackballEvent.cpp
 
@@ -65,7 +64,6 @@ HEADERS += \
     CgQtViewer/CgTrackball.h \
     CgEvents/CgWindowResizeEvent.h \
     CgSceneGraph/CgTriangleMesh.h \
-    CgSceneGraph/CgKdTree.h \
     CgSceneGraph/CgAABB.h \
     CgUtils/ObjLoader.h \
     CgUtils/Timer.h \