diff --git a/src/main/java/com/syncleus/spangraph/spacetime/AbstractOctree.java b/src/main/java/com/syncleus/spangraph/spacetime/OctBox.java
similarity index 66%
rename from src/main/java/com/syncleus/spangraph/spacetime/AbstractOctree.java
rename to src/main/java/com/syncleus/spangraph/spacetime/OctBox.java
index b1f725a3a2eb8f2e01e23aa465d906ac7551a0bf..e5f5f0c6a10f2645f8ddfce9ab6e7c79dc29cc07 100644
--- a/src/main/java/com/syncleus/spangraph/spacetime/AbstractOctree.java
+++ b/src/main/java/com/syncleus/spangraph/spacetime/OctBox.java
@@ -4,36 +4,28 @@ import toxi.geom.*;
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
 import java.util.function.Consumer;
 
 
-public class AbstractOctree<L> extends AABB implements Shape3D {
+public class OctBox<V extends XYZ> extends AABB implements Shape3D {
 
     /**
      * alternative tree recursion limit, number of world units when cells are
      * not subdivided any further
      */
-    protected float minNodeSize = 0.1f;
+    protected Vec3D resolution;
 
     /**
      *
      */
-    public final AbstractOctree parent;
+    public final OctBox parent;
 
-    protected AbstractOctree[] children;
+    protected OctBox[] children;
 
-    protected byte numChildren;
+    protected Collection<V> points;
 
-    protected Collection<XYZ> points;
-
-    protected float size, halfSize;
-
-    protected Vec3D center;
-
-    private int depth = 0;
-
-    private boolean isAutoReducing = true;
 
     /**
      * Constructs a new AbstractOctree node within the AABB cube volume: {o.x, o.y,
@@ -46,18 +38,19 @@ public class AbstractOctree<L> extends AABB implements Shape3D {
      * @param halfSize
      *            half length of the tree volume along a single axis
      */
-    private AbstractOctree(AbstractOctree p, Vec3D o, float halfSize) {
-        super(o.add(halfSize, halfSize, halfSize), new Vec3D(halfSize,
-                halfSize, halfSize));
+    private OctBox(OctBox p, Vec3D o, Vec3D halfSize) {
+        super(o.add(halfSize), new Vec3D(halfSize));
         this.parent = p;
-        this.halfSize = halfSize;
-        this.size = halfSize * 2;
-        this.center = o;
-        this.numChildren = 0;
         if (parent != null) {
-            depth = parent.depth + 1;
-            minNodeSize = parent.minNodeSize;
+            resolution = parent.resolution;
         }
+
+
+    }
+
+    public int depth() {
+        if (parent == null) return 0;
+        return parent.depth() + 1;
     }
 
     /**
@@ -66,30 +59,34 @@ public class AbstractOctree<L> extends AABB implements Shape3D {
      *
      * @param o
      *            tree origin
-     * @param size
      *            size of the tree volume along a single axis
      */
-    public AbstractOctree(Vec3D o, float size, float minResolution) {
-        this(null, o, size / 2);
-        this.minNodeSize = minResolution;
+    public OctBox(Vec3D o, Vec3D extents, Vec3D resolution) {
+        this(null, o, extents);
+        this.resolution = resolution;
     }
 
+
     /**
-     * Adds all points of the collection to the octree. IMPORTANT: Points need
-     * be of type Vec3D or have subclassed it.
+     * Adds all points of the collection to the octree.
      *
      * @param points
      *            point collection
-     * @return true, if all points have been added successfully.
+     * @return how many points were added
      */
-    public boolean put(Collection<XYZ> points) {
-        boolean addedAll = true;
-        for (XYZ p : points) {
-            addedAll &= put(p);
+    public int put(final Collection<V> points) {
+        int count = 0;
+        for (final V p : points) {
+            if (put(p)) count++;
         }
-        return addedAll;
+        return count;
     }
 
+    public boolean belowResolution() {
+        return extent.x <= resolution.x ||
+                extent.y <= resolution.y ||
+                extent.z <= resolution.z;
+    }
     /**
      * Adds a new point/particle to the tree structure. All points are stored
      * within leaf nodes only. The tree implementation is using lazy
@@ -98,15 +95,13 @@ public class AbstractOctree<L> extends AABB implements Shape3D {
      * @param p
      * @return true, if point has been added successfully
      */
-    public boolean put(final XYZ p) {
-        final float halfSize = this.halfSize;
-
+    public boolean put(final V p) {
 
 
         // check if point is inside cube
         if (containsPoint(p)) {
             // only add points to leaves for now
-            if (halfSize <= minNodeSize) {
+            if (belowResolution()) {
                 if (points == null) {
                     points = newPointsCollection();
                 }
@@ -114,17 +109,16 @@ public class AbstractOctree<L> extends AABB implements Shape3D {
                 return true;
             } else {
                 if (children == null) {
-                    children = new AbstractOctree[8];
+                    children = new OctBox[8];
                 }
-                int octant = getOctantID(p, center);
+                int octant = getOctantID(p, min);
                 if (children[octant] == null) {
-                    Vec3D off = center.add(new Vec3D(
-                            (octant & 1) != 0 ? halfSize : 0,
-                            (octant & 2) != 0 ? halfSize : 0,
-                            (octant & 4) != 0 ? halfSize : 0));
-                    children[octant] = new AbstractOctree(this, off,
-                            halfSize * 0.5f);
-                    numChildren++;
+                    Vec3D off = min.add(new Vec3D(
+                            (octant & 1) != 0 ? extent.x : 0,
+                            (octant & 2) != 0 ? extent.y : 0,
+                            (octant & 4) != 0 ? extent.z : 0));
+                    children[octant] = new OctBox(this, off,
+                            extent.scale(0.5f));
                 }
                 return children[octant].put(p);
             }
@@ -132,7 +126,7 @@ public class AbstractOctree<L> extends AABB implements Shape3D {
         return false;
     }
 
-    protected Collection<XYZ> newPointsCollection() {
+    protected Collection<V> newPointsCollection() {
         return new ArrayList();
     }
 
@@ -141,10 +135,10 @@ public class AbstractOctree<L> extends AABB implements Shape3D {
      * Applies the given {@link OctreeVisitor} implementation to this node and
      * all of its children.
      */
-    public void forEachRecursive(Consumer<AbstractOctree> visitor) {
+    public void forEachRecursive(Consumer<OctBox> visitor) {
         visitor.accept(this);
-        if (numChildren > 0) {
-            for (AbstractOctree c : children) {
+        if (children!=null) {
+            for (OctBox c : children) {
                 if (c != null) {
                     c.forEachRecursive(visitor);
                 }
@@ -156,8 +150,7 @@ public class AbstractOctree<L> extends AABB implements Shape3D {
         return p.isInAABB(this);
     }
 
-    public AbstractOctree clear() {
-        numChildren = 0;
+    public OctBox clear() {
         children = null;
         points = null;
         return this;
@@ -166,32 +159,27 @@ public class AbstractOctree<L> extends AABB implements Shape3D {
     /**
      * @return a copy of the child nodes array
      */
-    public AbstractOctree[] getChildrenCopy() {
+    public OctBox[] getChildrenCopy() {
         if (children != null) {
-            AbstractOctree[] clones = new AbstractOctree[8];
+            OctBox[] clones = new OctBox[8];
             System.arraycopy(children, 0, clones, 0, 8);
             return clones;
         }
         return null;
     }
 
-    /**
-     * @return the depth
-     */
-    public int getDepth() {
-        return depth;
-    }
+
 
     /**
      * Finds the leaf node which spatially relates to the given point
      *
      * @return leaf node or null if point is outside the tree dimensions
      */
-    public AbstractOctree getLeafForPoint(XYZ p) {
+    public OctBox getLeafForPoint(XYZ p) {
         // if not a leaf node...
         if (p.isInAABB(this)) {
-            if (numChildren > 0) {
-                int octant = getOctantID(p, center);
+            if (children!=null) {
+                int octant = getOctantID(p, this);
                 if (children[octant] != null) {
                     return children[octant].getLeafForPoint(p);
                 }
@@ -211,20 +199,10 @@ public class AbstractOctree<L> extends AABB implements Shape3D {
      *
      * @return the minimum size of tree nodes
      */
-    public float getMinNodeSize() {
-        return minNodeSize;
+    public Vec3D getResolution() {
+        return resolution;
     }
 
-    public float getNodeSize() {
-        return size;
-    }
-
-    /**
-     * @return the number of child nodes (max. 8)
-     */
-    public int getNumChildren() {
-        return numChildren;
-    }
 
     /**
      * Computes the local child octant/cube index for the given point
@@ -234,10 +212,10 @@ public class AbstractOctree<L> extends AABB implements Shape3D {
      * @return octant index
      */
     protected final int getOctantID(final Vec3D plocal) {
-        float halfSize = this.halfSize;
+        final Vec3D h = this.extent;
 
-        return (plocal.x >= halfSize ? 1 : 0) + (plocal.y >= halfSize ? 2 : 0)
-                + (plocal.z >= halfSize ? 4 : 0);
+        return (plocal.x >= h.x ? 1 : 0) + (plocal.y >= h.y ? 2 : 0)
+                + (plocal.z >= h.z ? 4 : 0);
     }
 
     /** computes getOctantID for the point subtracted by another point,
@@ -245,25 +223,22 @@ public class AbstractOctree<L> extends AABB implements Shape3D {
 
      */
     private int getOctantID(final XYZ p, final Vec3D s) {
-        return ((p.x() - s.x) >= halfSize ? 1 : 0) + ((p.y() - s.y) >= halfSize ? 2 : 0)
-                + ((p.z() - s.z) >= halfSize ? 4 : 0);
+        final Vec3D h = this.extent;
+        return ((p.x() - s.x) >= h.x ? 1 : 0) + ((p.y() - s.y) >= h.y? 2 : 0)
+                + ((p.z() - s.z) >= h.z ? 4 : 0);
     }
 
-    /**
-     * @return the offset
-     */
-    public roVec3D getCenter() {
-        return center;
-    }
+
 
     /**
      * @return the parent
      */
-    public AbstractOctree getParent() {
+    public OctBox getParent() {
         return parent;
     }
 
-    public Collection<XYZ> getPoints() {
+    public Collection<V> getPoints() {
+        if (points == null) return Collections.EMPTY_LIST;
         return points;
     }
 
@@ -278,17 +253,17 @@ public class AbstractOctree<L> extends AABB implements Shape3D {
         return points.size();
     }
 
-    public List<XYZ> getPointsRecursively() {
+    public List<V> getPointsRecursively() {
         return getPointsRecursively(new ArrayList());
     }
 
     /**
      * @return the points
      */
-    public List<XYZ> getPointsRecursively(List<XYZ> results) {
+    public List<V> getPointsRecursively(List<V> results) {
         if (points != null) {
             results.addAll(points);
-        } else if (numChildren > 0) {
+        } else if (children!=null) {
             for (int i = 0; i < 8; i++) {
                 if (children[i] != null) {
                     children[i].getPointsRecursively(results);
@@ -305,7 +280,7 @@ public class AbstractOctree<L> extends AABB implements Shape3D {
      *            AABB
      * @return all points with the box volume
      */
-    @Deprecated public List<XYZ> getPointsWithinBox(AABB b) {
+    @Deprecated public List<XYZ> getPointsWithinBox(BB b) {
         ArrayList<XYZ> results = null;
         if (this.intersectsBox(b)) {
             if (points != null) {
@@ -317,7 +292,7 @@ public class AbstractOctree<L> extends AABB implements Shape3D {
                         results.add(q);
                     }
                 }
-            } else if (numChildren > 0) {
+            } else if (children!=null) {
                 for (int i = 0; i < 8; i++) {
                     if (children[i] != null) {
                         List<XYZ> points = children[i].getPointsWithinBox(b);
@@ -334,7 +309,7 @@ public class AbstractOctree<L> extends AABB implements Shape3D {
         return results;
     }
 
-    public void forEachInBox(AABB b, Consumer<XYZ> c) {
+    public void forEachInBox(BB b, Consumer<XYZ> c) {
         if (this.intersectsBox(b)) {
             if (points != null) {
                 for (XYZ q : points) {
@@ -342,7 +317,7 @@ public class AbstractOctree<L> extends AABB implements Shape3D {
                         c.accept(q);
                     }
                 }
-            } else if (numChildren > 0) {
+            } else if (children!=null) {
                 for (int i = 0; i < 8; i++) {
                     if (children[i] != null) {
                         children[i].forEachInBox(b, c);
@@ -360,9 +335,9 @@ public class AbstractOctree<L> extends AABB implements Shape3D {
                         c.accept(q);
                     }
                 }
-            } else if (numChildren > 0) {
+            } else if (children!=null) {
                 for (int i = 0; i < 8; i++) {
-                    AbstractOctree cc = children[i];
+                    OctBox cc = children[i];
                     if (cc != null) {
                         cc.forEachInSphere(s, c);
                     }
@@ -389,7 +364,7 @@ public class AbstractOctree<L> extends AABB implements Shape3D {
                         results.add(q);
                     }
                 }
-            } else if (numChildren > 0) {
+            } else if (children!=null) {
                 for (int i = 0; i < 8; i++) {
                     if (children[i] != null) {
                         List<XYZ> points = children[i].getPointsWithinSphere(s);
@@ -419,18 +394,13 @@ public class AbstractOctree<L> extends AABB implements Shape3D {
         forEachInSphere(new Sphere(sphereOrigin, clipRadius), c);
     }
 
-    /**
-     * @return the size
-     */
-    public float getScale() {
-        return size;
-    }
+
 
     private void reduceBranch() {
         if (points != null && points.size() == 0) {
             points = null;
         }
-        if (numChildren > 0) {
+        if (children!=null) {
             for (int i = 0; i < 8; i++) {
                 if (children[i] != null && children[i].points == null) {
                     children[i] = null;
@@ -450,13 +420,13 @@ public class AbstractOctree<L> extends AABB implements Shape3D {
      *            point to delete
      * @return true, if the point was found & removed
      */
-    public boolean remove(XYZ p) {
+    public boolean remove(V p) {
         boolean found = false;
-        AbstractOctree leaf = getLeafForPoint(p);
+        OctBox leaf = getLeafForPoint(p);
         if (leaf != null) {
             if (leaf.points.remove(p)) {
                 found = true;
-                if (isAutoReducing && leaf.points.size() == 0) {
+                if (leaf.points.size() == 0) {
                     leaf.reduceBranch();
                 }
             }
@@ -464,36 +434,18 @@ public class AbstractOctree<L> extends AABB implements Shape3D {
         return found;
     }
 
-    public void removeAll(Collection<XYZ> points) {
-        for (XYZ p : points) {
+    public void removeAll(Collection<V> points) {
+        for (V p : points) {
             remove(p);
         }
     }
 
-    /**
-     * @param minNodeSize
-     */
-    public void setMinNodeSize(float minNodeSize) {
-        this.minNodeSize = minNodeSize * 0.5f;
-    }
-
-    /**
-     * Enables/disables auto reduction of branches after points have been
-     * deleted from the tree. Turned off by default.
-     *
-     * @param state
-     *            true, to enable feature
-     */
-    public void setTreeAutoReduction(boolean state) {
-        isAutoReducing = state;
-    }
-
     /*
      * (non-Javadoc)
      *
      * @see toxi.geom.AABB#toString()
      */
     public String toString() {
-        return "<octree> offset: " + super.toString() + " size: " + size;
+        return "<OctBox @" + super.toString() + '>';
     }
 }
diff --git a/src/main/java/toxi/geom/AABB.java b/src/main/java/toxi/geom/AABB.java
index d8b33c30ffe37f880d12f3d140ab3d821bea13fa..a7468fe318b09cc333da0b06930e20c480223a31 100644
--- a/src/main/java/toxi/geom/AABB.java
+++ b/src/main/java/toxi/geom/AABB.java
@@ -31,61 +31,14 @@ import toxi.math.MathUtils;
 
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlTransient;
-import java.util.List;
 
 /**
  * Axis-aligned bounding box with basic intersection features for Ray, AABB and
  * Sphere classes.
  */
 @XmlAccessorType(XmlAccessType.FIELD)
-public class AABB extends Vec3D implements Shape3D {
-
-    /**
-     * Creates a new instance from two vectors specifying opposite corners of
-     * the box
-     * 
-     * @param min
-     *            first corner point
-     * @param max
-     *            second corner point
-     * @return new AABB with centre at the half point between the 2 input
-     *         vectors
-     */
-    public static final AABB fromMinMax(Vec3D min, Vec3D max) {
-        Vec3D a = Vec3D.min(min, max);
-        Vec3D b = Vec3D.max(min, max);
-        return new AABB(a.interpolateTo(b, 0.5f), b.sub(a).scaleSelf(0.5f));
-    }
-
-    /**
-     * Factory method, computes & returns the bounding box for the given list of
-     * points.
-     * 
-     * @param points
-     * @return bounding rect
-     */
-    public static final AABB getBoundingBox(List<? extends XYZ> points) {
-        if (points == null || points.size() == 0) {
-            return null;
-        }
-        XYZ first = points.get(0);
-        Vec3D min = new Vec3D(first);
-        Vec3D max = new Vec3D(first);
-        int n = points.size();
-        if (n > 1) {
-            for (int i = 1; i < n; i++) {
-                XYZ p = points.get(i);
-                min.minSelf(p);
-                max.maxSelf(p);
-            }
-        }
-        return fromMinMax(min, max);
-    }
-
-    @XmlElement(required = true)
-    protected Vec3D extent;
+public class AABB extends BB implements Shape3D {
 
     @XmlTransient
     protected Vec3D min, max;
@@ -100,7 +53,7 @@ public class AABB extends Vec3D implements Shape3D {
      * 
      * @param box
      */
-    public AABB(AABB box) {
+    public AABB(BB box) {
         this(box, box.getExtent());
     }
 
@@ -138,29 +91,10 @@ public class AABB extends Vec3D implements Shape3D {
         setExtent(extent);
     }
 
-    public boolean containsPoint(XYZ p) {
-        return p.isInAABB(this);
-    }
-
-    public AABB copy() {
+    public BB copy() {
         return new AABB(this);
     }
 
-    public Sphere getBoundingSphere() {
-        return new Sphere(this, extent.magnitude());
-    }
-
-    /**
-     * Returns the current box size as new Vec3D instance (updating this vector
-     * will NOT update the box size! Use {@link #setExtent(roVec3D)} for
-     * those purposes)
-     * 
-     * @return box size
-     */
-    public final Vec3D getExtent() {
-        return extent.copy();
-    }
-
     public final Vec3D getMax() {
         // return this.add(extent);
         return max.copy();
@@ -193,7 +127,7 @@ public class AABB extends Vec3D implements Shape3D {
      *            point to include
      * @return itself
      */
-    public AABB growToContainPoint(roVec3D p) {
+    public BB growToContainPoint(roVec3D p) {
         min.minSelf(p);
         max.maxSelf(p);
         set(min.interpolateTo(max, 0.5f));
@@ -201,30 +135,17 @@ public class AABB extends Vec3D implements Shape3D {
         return this;
     }
 
-    /**
-     * Checks if the box intersects the passed in one.
-     * 
-     * @param box
-     *            box to check
-     * @return true, if boxes overlap
-     */
-    public boolean intersectsBox(final AABB box) {
-        return MathUtils.abs(box.x - x) <= (extent.x + box.extent.x)
-                && MathUtils.abs(box.y - y) <= (extent.y + box.extent.y)
-                && MathUtils.abs(box.z - z) <= (extent.z + box.extent.z);
-    }
-
     /**
      * Calculates intersection with the given ray between a certain distance
      * interval.
-     * 
+     *
      * Ray-box intersection is using IEEE numerical properties to ensure the
      * test is both robust and efficient, as described in:
-     * 
+     *
      * Amy Williams, Steve Barrus, R. Keith Morley, and Peter Shirley: "An
      * Efficient and Robust Ray-Box Intersection Algorithm" Journal of graphics
      * tools, 10(1):49-54, 2005
-     * 
+     *
      * @param ray
      *            incident ray
      * @param minDist
@@ -273,48 +194,6 @@ public class AABB extends Vec3D implements Shape3D {
         return null;
     }
 
-    public boolean intersectsSphere(Sphere s) {
-        return intersectsSphere(s, s.radius);
-    }
-
-    /**
-     * @param c
-     *            sphere centre
-     * @param r
-     *            sphere radius
-     * @return true, if AABB intersects with sphere
-     */
-    public boolean intersectsSphere(Vec3D c, float r) {
-        float s, d = 0;
-        // find the square of the distance
-        // from the sphere to the box
-        if (c.x < min.x) {
-            s = c.x - min.x;
-            d = s * s;
-        } else if (c.x > max.x) {
-            s = c.x - max.x;
-            d += s * s;
-        }
-
-        if (c.y < min.y) {
-            s = c.y - min.y;
-            d += s * s;
-        } else if (c.y > max.y) {
-            s = c.y - max.y;
-            d += s * s;
-        }
-
-        if (c.z < min.z) {
-            s = c.z - min.z;
-            d += s * s;
-        } else if (c.z > max.z) {
-            s = c.z - max.z;
-            d += s * s;
-        }
-
-        return d <= r * r;
-    }
-
     public boolean intersectsTriangle(Triangle3D tri) {
         // use separating axis theorem to test overlap between triangle and box
         // need to test for overlap in these directions:
@@ -450,7 +329,7 @@ public class AABB extends Vec3D implements Shape3D {
         return false;
     }
 
-    public AABB set(AABB box) {
+    public BB set(BB box) {
         extent.set(box.extent);
         return set((XYZ) box);
     }
@@ -474,7 +353,7 @@ public class AABB extends Vec3D implements Shape3D {
      * {@link #updateBounds()} immediately
      * 
      */
-    public AABB set(XYZ v) {
+    public BB set(XYZ v) {
         x = v.x();
         y = v.y();
         z = v.z();
@@ -489,7 +368,7 @@ public class AABB extends Vec3D implements Shape3D {
      *            new box size
      * @return itself, for method chaining
      */
-    public AABB setExtent(roVec3D extent) {
+    public BB setExtent(roVec3D extent) {
         this.extent = extent.copy();
         return updateBounds();
     }
@@ -558,12 +437,12 @@ public class AABB extends Vec3D implements Shape3D {
      */
     public String toString() {
         StringBuffer sb = new StringBuffer();
-        sb.append("<aabb> pos: ").append(super.toString()).append(" ext: ")
+        sb.append("<aabb @").append(super.toString()).append("x")
                 .append(extent);
         return sb.toString();
     }
 
-    public AABB union(AABB box) {
+    public BB union(AABB box) {
         min.minSelf(box.getMin());
         max.maxSelf(box.getMax());
         set(min.interpolateTo(max, 0.5f));
@@ -577,7 +456,7 @@ public class AABB extends Vec3D implements Shape3D {
      * 
      * @return itself
      */
-    public final AABB updateBounds() {
+    public final BB updateBounds() {
         // this is check is necessary for the constructor
         if (extent != null) {
             this.min = this.sub(extent);
@@ -586,25 +465,4 @@ public class AABB extends Vec3D implements Shape3D {
         return this;
     }
 
-    public boolean contains(final XYZ v) {
-        final Vec3D min = this.min;
-        final Vec3D max = this.max;
-
-        final float x = v.x();
-        if (x < min.x || x > max.x) {
-            return false;
-        }
-
-        final float y = v.y();
-        if (y < min.y || y > max.y) {
-            return false;
-        }
-
-        final float z = v.z();
-        if (z < min.z || z > max.z) {
-            return false;
-        }
-
-        return true;
-    }
 }
\ No newline at end of file
diff --git a/src/main/java/toxi/geom/BB.java b/src/main/java/toxi/geom/BB.java
new file mode 100644
index 0000000000000000000000000000000000000000..231b467987ae33d3672d229078a298ca747093f4
--- /dev/null
+++ b/src/main/java/toxi/geom/BB.java
@@ -0,0 +1,169 @@
+package toxi.geom;
+
+import toxi.math.MathUtils;
+
+import javax.xml.bind.annotation.XmlElement;
+import java.util.List;
+
+/**
+ * Created by me on 6/14/15.
+ */
+public abstract class BB extends Vec3D {
+
+
+    protected Vec3D extent;
+
+    public BB() {
+        super();
+    }
+
+    public BB(XYZ v) {
+        super(v);
+    }
+
+    /**
+     * Creates a new instance from two vectors specifying opposite corners of
+     * the box
+     *
+     * @param min
+     *            first corner point
+     * @param max
+     *            second corner point
+     * @return new AABB with centre at the half point between the 2 input
+     *         vectors
+     */
+    public static final BB fromMinMax(Vec3D min, Vec3D max) {
+        Vec3D a = Vec3D.min(min, max);
+        Vec3D b = Vec3D.max(min, max);
+        return new AABB(a.interpolateTo(b, 0.5f), b.sub(a).scaleSelf(0.5f));
+    }
+
+    /**
+     * Factory method, computes & returns the bounding box for the given list of
+     * points.
+     *
+     * @param points
+     * @return bounding rect
+     */
+    public static final BB getBoundingBox(List<? extends XYZ> points) {
+        if (points == null || points.size() == 0) {
+            return null;
+        }
+        XYZ first = points.get(0);
+        Vec3D min = new Vec3D(first);
+        Vec3D max = new Vec3D(first);
+        int n = points.size();
+        if (n > 1) {
+            for (int i = 1; i < n; i++) {
+                XYZ p = points.get(i);
+                min.minSelf(p);
+                max.maxSelf(p);
+            }
+        }
+        return fromMinMax(min, max);
+    }
+
+    public boolean containsPoint(XYZ p) {
+        return p.isInAABB(this);
+    }
+
+    public Sphere getBoundingSphere() {
+        return new Sphere(this, extent.magnitude());
+    }
+
+    /**
+     * Returns the current box size as new Vec3D instance (updating this vector
+     * will NOT update the box size! Use {@link #setExtent(roVec3D)} for
+     * those purposes)
+     *
+     * @return box size
+     */
+    public final Vec3D getExtent() {
+        return extent.copy();
+    }
+
+    /**
+     * Checks if the box intersects the passed in one.
+     *
+     * @param box
+     *            box to check
+     * @return true, if boxes overlap
+     */
+    public boolean intersectsBox(final BB box) {
+        return MathUtils.abs(box.x - x) <= (extent.x + box.extent.x)
+                && MathUtils.abs(box.y - y) <= (extent.y + box.extent.y)
+                && MathUtils.abs(box.z - z) <= (extent.z + box.extent.z);
+    }
+
+
+
+    public boolean intersectsSphere(Sphere s) {
+        return intersectsSphere(s, s.radius);
+    }
+
+    /**
+     * @param c
+     *            sphere centre
+     * @param r
+     *            sphere radius
+     * @return true, if AABB intersects with sphere
+     */
+    public boolean intersectsSphere(Vec3D c, float r) {
+        float s, d = 0;
+        // find the square of the distance
+        // from the sphere to the box
+        if (c.x < minX()) {
+            s = c.x - minX();
+            d = s * s;
+        } else if (c.x > maxX()) {
+            s = c.x - maxX();
+            d += s * s;
+        }
+
+        if (c.y < minY()) {
+            s = c.y - minY();
+            d += s * s;
+        } else if (c.y > maxY()) {
+            s = c.y - maxY();
+            d += s * s;
+        }
+
+        if (c.z < minZ()) {
+            s = c.z - minZ();
+            d += s * s;
+        } else if (c.z > maxZ()) {
+            s = c.z - maxZ();
+            d += s * s;
+        }
+
+        return d <= r * r;
+    }
+
+    public boolean contains(final XYZ v) {
+        final float x = v.x();
+        if (x < minX() || x > maxX()) {
+            return false;
+        }
+
+        final float y = v.y();
+        if (y < minY() || y > maxY()) {
+            return false;
+        }
+
+        final float z = v.z();
+        if (z < minZ() || z > maxZ()) {
+            return false;
+        }
+
+        return true;
+    }
+
+
+    float minX() { return x - extent.x; }
+    float maxX() { return x + extent.x; }
+    float minY() { return y - extent.y; }
+    float maxY() { return y + extent.y; }
+    float minZ() { return z - extent.z; }
+    float maxZ() { return z + extent.z; }
+
+}
diff --git a/src/main/java/toxi/geom/BoxIntersector.java b/src/main/java/toxi/geom/BoxIntersector.java
index 3b02acd3fe074bea6a447eed771055f25334d2a1..6f481c5236c56323c5de8928deb0d29c36e2b6fd 100644
--- a/src/main/java/toxi/geom/BoxIntersector.java
+++ b/src/main/java/toxi/geom/BoxIntersector.java
@@ -13,7 +13,7 @@ public class BoxIntersector implements Intersector3D {
     /**
      * @return the box
      */
-    public AABB getBox() {
+    public BB getBox() {
         return box;
     }
 
diff --git a/src/main/java/toxi/geom/Line3D.java b/src/main/java/toxi/geom/Line3D.java
index 45af97ad73c1829bf9355f26fa607996d58429b0..49e37349e880b6f01fb90c3cc42cc1b97087d088 100644
--- a/src/main/java/toxi/geom/Line3D.java
+++ b/src/main/java/toxi/geom/Line3D.java
@@ -241,8 +241,8 @@ public class Line3D {
      * @return aabb
      * @see AABB
      */
-    public AABB getBounds() {
-        return AABB.fromMinMax(a, b);
+    public BB getBounds() {
+        return BB.fromMinMax(a, b);
     }
 
     public Vec3D getDirection() {
diff --git a/src/main/java/toxi/geom/PointCloud3D.java b/src/main/java/toxi/geom/PointCloud3D.java
index dbe8a46cf502ebd44a527319f7dc6dc942623bec..376a5c3303423479be650fe9ce45091ce2e1ca75 100644
--- a/src/main/java/toxi/geom/PointCloud3D.java
+++ b/src/main/java/toxi/geom/PointCloud3D.java
@@ -140,8 +140,8 @@ public class PointCloud3D implements Iterable<Vec3D> {
         return c;
     }
 
-    public AABB getBoundingBox() {
-        return AABB.fromMinMax(min, max);
+    public BB getBoundingBox() {
+        return BB.fromMinMax(min, max);
     }
 
     public Sphere getBoundingSphere() {
diff --git a/src/main/java/toxi/geom/PointOctree.java b/src/main/java/toxi/geom/PointOctree.java
index c5de07f5e8e46e846a0b7c8a8a32e3baa825a55f..675162a22b269e41707bdb63b162e09bab86c8c7 100644
--- a/src/main/java/toxi/geom/PointOctree.java
+++ b/src/main/java/toxi/geom/PointOctree.java
@@ -304,7 +304,7 @@ public class PointOctree extends AABB implements Shape3D {
      *            AABB
      * @return all points with the box volume
      */
-    public List<XYZ> getPointsWithinBox(AABB b) {
+    public List<XYZ> getPointsWithinBox(BB b) {
         ArrayList<XYZ> results = null;
         if (this.intersectsBox(b)) {
             if (points != null) {
diff --git a/src/main/java/toxi/geom/Triangle3D.java b/src/main/java/toxi/geom/Triangle3D.java
index 44c787bd10e4108892cd3f5056fee5bcce56929a..162d21c010d70be64214ecdde4a230a3b17106e8 100644
--- a/src/main/java/toxi/geom/Triangle3D.java
+++ b/src/main/java/toxi/geom/Triangle3D.java
@@ -217,10 +217,10 @@ public class Triangle3D implements Shape3D {
                 * p.z());
     }
 
-    public AABB getBoundingBox() {
+    public BB getBoundingBox() {
         Vec3D min = Vec3D.min(Vec3D.min(a, b), c);
         Vec3D max = Vec3D.max(Vec3D.max(a, b), c);
-        return AABB.fromMinMax(min, max);
+        return BB.fromMinMax(min, max);
     }
 
     /**
diff --git a/src/main/java/toxi/geom/XYZ.java b/src/main/java/toxi/geom/XYZ.java
index 91c52c8e878251798adbcf349544122ac964c75f..7e61b40b646b7bb3b2b8503a182facc8015d4d34 100644
--- a/src/main/java/toxi/geom/XYZ.java
+++ b/src/main/java/toxi/geom/XYZ.java
@@ -81,7 +81,7 @@ public interface XYZ {
      *
      * @see toxi.geom.ReadonlyVec3D#isInAABB(toxi.geom.AABB)
      */
-    default public boolean isInAABB(final AABB box) {
+    default public boolean isInAABB(final BB box) {
         return box.contains(this);
     }
 
diff --git a/src/test/java/com/syncleus/spangraph/geom/OctreeTest.java b/src/test/java/com/syncleus/spangraph/geom/OctreeTest.java
index 5c18d3caab84d86a1175e68f622acd97ba2ecb21..4b2aeedd0260fc984f07a7e7551d39eaec7d6418 100644
--- a/src/test/java/com/syncleus/spangraph/geom/OctreeTest.java
+++ b/src/test/java/com/syncleus/spangraph/geom/OctreeTest.java
@@ -1,13 +1,15 @@
 package com.syncleus.spangraph.geom;
 
-import com.syncleus.spangraph.spacetime.AbstractOctree;
+import com.syncleus.spangraph.spacetime.OctBox;
 import org.junit.Test;
 import toxi.geom.AABB;
+import toxi.geom.BB;
 import toxi.geom.Vec3D;
 
 import java.util.List;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
 /**
  * Created by me on 6/13/15.
@@ -15,10 +17,18 @@ import static org.junit.Assert.assertEquals;
 public class OctreeTest {
     @Test
     public void test1() {
-        AbstractOctree o = new AbstractOctree(
-                new Vec3D(-2f, -2f, -2f), 4f, 0.05f);
-        
-        o.put(new Vec3D(1, 1, 0));
+        OctBox o = new OctBox(
+                new Vec3D(-2f, -2f, -2f),
+                new Vec3D(4f, 4f, 4f),
+                new Vec3D(0.05f, 0.05f, 0.05f));
+
+        assertEquals(0, o.countPointsRecursively());
+
+        boolean b = o.put(new Vec3D(3,3,3));
+        assertTrue(b);
+        assertEquals(1, o.countPointsRecursively());
+
+        o.put(new Vec3D(0, 1, 0));
         o.put(new Vec3D(0, 1, 0));
         o.put(new Vec3D(0, 0, 1));
         o.put(new Vec3D(0, 0, 1.25f));
@@ -31,14 +41,14 @@ public class OctreeTest {
 
         o.forEachRecursive(x -> {
 
-            List p = (((AbstractOctree) x).getPointsRecursively());
+            List p = (((OctBox) x).getPointsRecursively());
             //if (!p.isEmpty())
             //System.out.println(x + " " + p);
         });
 
         //System.out.println("size: " + o.getNumChildren());
 
-        assertEquals(o.countPointsRecursively(), 10);
+        assertEquals(o.countPointsRecursively(), 11);
 
         int[] sphereCount = new int[1];
         o.forEachInSphere(new Vec3D(0, 0, -0.75f), 0.5f, x -> {
@@ -48,8 +58,8 @@ public class OctreeTest {
 
         int[] boxCount = new int[1];
 
-        AABB aabb = new AABB(new Vec3D(0f, -0.5f, -2.0f), new Vec3D(0.5f, 0.5f, 0.5f));
-        o.forEachInBox(aabb, x -> {
+        BB BB = new AABB(new Vec3D(0f, -0.5f, -2.0f), new Vec3D(0.5f, 0.5f, 0.5f));
+        o.forEachInBox(BB, x -> {
             boxCount[0]++;
         });
         assertEquals(3, boxCount[0]);