diff --git a/CgQtViewer/CgQtGui.cpp b/CgQtViewer/CgQtGui.cpp
index 30dd7d2c3dccf582c27222d98dc440062024f73f..4cc60893dceeedaf96fe967cebf681f0c5bc9ba9 100644
--- a/CgQtViewer/CgQtGui.cpp
+++ b/CgQtViewer/CgQtGui.cpp
@@ -156,7 +156,7 @@ void CgQtGui::createKdTreeOptionPanel(QWidget* parent)
 
     /* label */
 
-    QLabel *max_depth_label = new QLabel("depth limit (0 for none):");
+    QLabel *max_depth_label = new QLabel("depth limit:");
     tab1_control->addWidget(max_depth_label);
     max_depth_label->setAlignment(Qt::AlignTop);
     max_depth_label->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
@@ -165,9 +165,9 @@ void CgQtGui::createKdTreeOptionPanel(QWidget* parent)
 
     max_kd_depth_spinbox = new QSpinBox();
     tab1_control->addWidget(max_kd_depth_spinbox);
-    max_kd_depth_spinbox->setMinimum(0);
+    max_kd_depth_spinbox->setMinimum(1);
     max_kd_depth_spinbox->setMaximum(50);
-    max_kd_depth_spinbox->setValue(0);
+    max_kd_depth_spinbox->setValue(7);
     connect(max_kd_depth_spinbox, SIGNAL(valueChanged(int) ), this, SLOT(slotKdDepthSpinboxChanged()) );
     tab1_control->addWidget(max_kd_depth_spinbox);
     max_kd_depth_spinbox->setAlignment(Qt::AlignTop);
diff --git a/CgSceneGraph/CgKdTree.cpp b/CgSceneGraph/CgKdTree.cpp
index 1725edb87229e99cd30e1dc51c7708eb458d590b..77e9fb6af797f49902297db666de20c1929d1ce1 100644
--- a/CgSceneGraph/CgKdTree.cpp
+++ b/CgSceneGraph/CgKdTree.cpp
@@ -1,58 +1,39 @@
 #include "CgKdTree.h"
 
-// nodes
-CgKdTree::TreeNode::TreeNode(glm::vec3 point) {
-    m_point = point;
-    m_lower = nullptr;
-    m_higher = nullptr;
-}
-
-CgKdTree::TreeNode::~TreeNode() {
-    if(m_lower) delete m_lower;
-    if(m_higher) delete m_higher;
-}
-
-// kdtree API
 CgKdTree::CgKdTree() {
 
 }
 
 CgKdTree::~CgKdTree() {
     m_points.clear();
-    if(m_root) delete m_root;
 }
 
-// builds a kd-tree out of the glm::vec3 between 
-// begin (inclusive) and end (exklusive)
-CgKdTree::TreeNode* CgKdTree::buildTree(glm::vec3* begin, glm::vec3* end, int depth) {
+void CgKdTree::buildTree(glm::vec3* begin, glm::vec3* end, int depth) {
     auto half_size = (end - begin) / 2;
 
-    if(begin == end) { // array is empty
-        return nullptr;
-    } else if(half_size == 0) { // there is one element
-        return new CgKdTree::TreeNode(*begin);
-    } else { // more than one element!
+    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))
+        // 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];
         });
 
-        // create node with median point
-        auto node = new CgKdTree::TreeNode(begin[half_size]);
         // split array in two (excluding median) and recurse
-        node->m_lower = buildTree(begin, begin + half_size, depth + 1);
-        node->m_higher = buildTree(begin + half_size + 1, end, depth + 1);
-
-        return node;
+        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;
-    m_root = buildTree(&points.front(), &(*(points.end() - 1)), 0);
+    buildTree(&m_points.front(), &(*(m_points.end() - 1)), 0);
 }
 
 std::vector<int> CgKdTree::getNearestNeighbors(int current_point, unsigned int k) {
@@ -61,23 +42,31 @@ std::vector<int> CgKdTree::getNearestNeighbors(int current_point, unsigned int k
     return erg;
 }
 
-// return the locations of the split planes in a breadth-first manner
-std::vector<double> CgKdTree::getSplits() {
-    std::vector<double> erg;
-    std::queue<CgKdTree::TreeNode*> q;
-    if(m_root == nullptr) return erg;
-    int depth = 0;
-    q.push(m_root);
+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++) {
-            CgKdTree:TreeNode* curr = q.front();
-            erg.push_back(curr->m_point[depth % 3]);
-            if(curr->m_lower != nullptr) q.push(curr->m_lower);
-            if(curr->m_higher != nullptr) q.push(curr->m_higher);
+            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;
     }
-    return erg;
+}
+
+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
index 3077dee555212a7d5da46bdb4c4f9b18d782f063..228c39ddcae161e51c65316cb43034e5a2ec86a9 100644
--- a/CgSceneGraph/CgKdTree.h
+++ b/CgSceneGraph/CgKdTree.h
@@ -8,6 +8,8 @@
 #include <iostream>
 #include <algorithm>
 #include <numeric>
+#include <utility>
+#include <functional>
 
 class CgKdTree
 {
@@ -17,23 +19,14 @@ public:
   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:
-    class TreeNode
-    {
-      private:
-        TreeNode(glm::vec3 point);
-        ~TreeNode();
-        glm::vec3 m_point;
-        TreeNode* m_lower;
-        TreeNode* m_higher;
-        friend class CgKdTree;
-    };
-private:
-    CgKdTree::TreeNode* m_root;
-    CgKdTree::TreeNode* buildTree(glm::vec3* begin, glm::vec3* end, int depth);
+    // 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 14ada35a6356ef90c3a66e10594623677e4d0a92..b79cba5c43af9af8a7c6a729b01cf5df77293162 100644
--- a/CgSceneGraph/CgPointCloud.cpp
+++ b/CgSceneGraph/CgPointCloud.cpp
@@ -1,8 +1,4 @@
 #include "CgPointCloud.h"
-#include "CgBase/CgEnums.h"
-#include "CgUtils/ObjLoader.h"
-#include <glm/gtc/matrix_transform.hpp>
-#include <algorithm>
 
 
 CgPointCloud::CgPointCloud():
@@ -60,6 +56,10 @@ 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)
 {
diff --git a/CgSceneGraph/CgPointCloud.h b/CgSceneGraph/CgPointCloud.h
index dc32281f35931fc25b437d3d6f4e475d4eb4a698..83ddbbcb97246db2f6e246ef1456b2a28c950884 100644
--- a/CgSceneGraph/CgPointCloud.h
+++ b/CgSceneGraph/CgPointCloud.h
@@ -8,6 +8,10 @@
 #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
 {
@@ -25,7 +29,7 @@ public:
   //inherited from CgBasePointCloud
 
   // vertex positions in local coordinates
-  const std::vector<glm::vec3>& getVertices()     const;
+  const std::vector<glm::vec3>& getVertices() const;
 
   // normal directions in local coordinates (normalized)
   const std::vector<glm::vec3>& getVertexNormals() const;
@@ -87,7 +91,6 @@ private:
 
 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 fba8257a8c696309086e8c1437ba0b589abe560e..a40c1dd16cfbc9740f55db704971797295b35424 100644
--- a/CgSceneGraph/CgSceneControl.cpp
+++ b/CgSceneGraph/CgSceneControl.cpp
@@ -175,9 +175,11 @@ void CgSceneControl::createKdTreeViz(int max_depth) {
   m_kd_tree_mesh.clear();
 
   // recalculate mesh
-  max_depth = max_depth == 0 ? 7 : max_depth; 
   if(m_pointcloud != nullptr && max_depth != -1) {
-    std::vector<double> splits = m_pointcloud->getKdTree()->getSplits();
+    std::vector<double> splits;
+    m_pointcloud->getKdTree()->traverseBFO([&](glm::vec3* point, unsigned int depth) {
+        splits.push_back((*point)[depth % 3]);
+    });
     std::queue<CgAABB> aabb_queue;
     aabb_queue.push(m_pointcloud->getAABB());
     unsigned int index = 0;
@@ -197,7 +199,7 @@ void CgSceneControl::createKdTreeViz(int max_depth) {
       span1[current_axis] = 0.0;
       span2[current_axis] = 0.0;
       span2[next_axis] = -span2[next_axis];
-      CgQuad* new_quad = new CgQuad(34 + index, quad_position, span1, span2);
+      CgQuad* new_quad = new CgQuad(1000 + index, quad_position, span1, span2);
       m_renderer->init(new_quad);
       m_kd_tree_mesh.push_back(new_quad);
 
@@ -533,7 +535,6 @@ void CgSceneControl::renderObjects()
 
         m_current_transformation = m_current_transformation * orientations[splat_indices[i]];
         m_current_transformation = glm::translate(m_current_transformation,m_center);
-
       }
     }
 }