Commits

Michael Ludwig committed 7e22eec

Add BoundedSpatialIndex interface to allow QuadTrees and Octrees to have their extents updated.

Comments (0)

Files changed (6)

ferox-math/src/main/java/com/ferox/math/Vector3.java

     }
 
     /**
+     * Floor each component of the vector <tt>v</tt> and store them in this
+     * vector.
+     * 
+     * @param v The vector to be floored
+     * @return This vector
+     * @throws NullPointerException if v is null
+     */
+    public Vector3 floor(Vector3 v) {
+        return set(Math.floor(v.x), Math.floor(v.y), Math.floor(v.z));
+    }
+
+    /**
+     * Floor this vector component-wise.
+     * 
+     * @return This vector
+     */
+    public Vector3 floor() {
+        return floor(this);
+    }
+
+    /**
+     * Compute the ceiling of each component of the vector <tt>v</tt> and store
+     * them in this vector.
+     * 
+     * @param v The vector to be ceil'ed
+     * @return This vector
+     * @throws NullPointerException if v is null
+     */
+    public Vector3 ceil(Vector3 v) {
+        return set(Math.ceil(v.x), Math.ceil(v.y), Math.ceil(v.z));
+    }
+
+    /**
+     * Compute the ceiling this vector component-wise.
+     * 
+     * @return This vector
+     */
+    public Vector3 ceil() {
+        return ceil(this);
+    }
+
+    /**
      * Compute the length of this vector.
      * 
      * @return Length of this vector

ferox-math/src/main/java/com/ferox/math/Vector4.java

     }
 
     /**
+     * Floor each component of the vector <tt>v</tt> and store them in this
+     * vector.
+     * 
+     * @param v The vector to be floored
+     * @return This vector
+     * @throws NullPointerException if v is null
+     */
+    public Vector4 floor(Vector4 v) {
+        return set(Math.floor(v.x), Math.floor(v.y), Math.floor(v.z), Math.floor(v.w));
+    }
+
+    /**
+     * Floor this vector component-wise.
+     * 
+     * @return This vector
+     */
+    public Vector4 floor() {
+        return floor(this);
+    }
+
+    /**
+     * Compute the ceiling of each component of the vector <tt>v</tt> and store
+     * them in this vector.
+     * 
+     * @param v The vector to be ceil'ed
+     * @return This vector
+     * @throws NullPointerException if v is null
+     */
+    public Vector4 ceil(Vector4 v) {
+        return set(Math.ceil(v.x), Math.ceil(v.y), Math.ceil(v.z), Math.ceil(v.w));
+    }
+
+    /**
+     * Compute the ceiling this vector component-wise.
+     * 
+     * @return This vector
+     */
+    public Vector4 ceil() {
+        return ceil(this);
+    }
+
+    /**
      * Solve the linear system of equations, <code>[m] x [this] = [a]</code> and
      * store the resultant values of (x, y, z, w) into this vector:
      * 

ferox-math/src/main/java/com/ferox/math/bounds/BoundedSpatialIndex.java

+package com.ferox.math.bounds;
+
+import com.ferox.math.AxisAlignedBox;
+import com.ferox.math.Const;
+
+/**
+ * BoundedSpatialIndex is a SpatialIndex that has a maximum extent that all
+ * added objects must fit within. It will ignore objects that extend past its
+ * extent. This interface provides mechanisms to query and set the size of the
+ * extent.
+ * 
+ * @author Michael Ludwig
+ * 
+ * @param <T>
+ */
+public interface BoundedSpatialIndex<T> extends SpatialIndex<T> {
+    /**
+     * @return The current extent of the index
+     */
+    @Const
+    public AxisAlignedBox getExtent();
+
+    /**
+     * Set the new extent of the spatial index. This can only be called when the
+     * index is empty.
+     * 
+     * @param bounds The new bounding box for the extent of this index
+     * @throws IllegalStateException if the index is not empty
+     * @throws NullPointerException if bounds is null
+     */
+    public void setExtent(@Const AxisAlignedBox bounds);
+}

ferox-math/src/main/java/com/ferox/math/bounds/Frustum.java

 
         return result;
     }
-
+    
     /*
      * Update the plane instances returned by getFrustumPlane() to reflect any
      * changes to the frustum's local parameters or orientation. Also update the

ferox-math/src/main/java/com/ferox/math/bounds/Octree.java

  * @author Michael Ludwig
  * @param <T> The data type stored in the octree
  */
-public class Octree<T> implements SpatialIndex<T> {
+public class Octree<T> implements BoundedSpatialIndex<T> {
     private static final int POS_X = 0x1;
     private static final int POS_Y = 0x2;
     private static final int POS_Z = 0x4;
     private final Cell[] spatialHash;
     private final int maxCellDimension;
 
-    private final double widthScaleFactor;
-    private final double heightScaleFactor;
-    private final double depthScaleFactor;
+    private double widthScaleFactor;
+    private double heightScaleFactor;
+    private double depthScaleFactor;
 
-    private final double widthOffset;
-    private final double heightOffset;
-    private final double depthOffset;
+    private double widthOffset;
+    private double heightOffset;
+    private double depthOffset;
 
     private final AxisAlignedBox rootBounds;
 
      */
     public Octree(@Const AxisAlignedBox aabb, int depth) {
         this.depth = depth;
-        rootBounds = aabb.clone();
+        rootBounds = new AxisAlignedBox();
 
         maxCellDimension = 1 << (depth - 1);
         spatialHash = new Cell[maxCellDimension * maxCellDimension * maxCellDimension];
         size = 0;
         queryIdCounter = 0;
 
-        widthScaleFactor = maxCellDimension / (aabb.max.x - aabb.min.x);
-        heightScaleFactor = maxCellDimension / (aabb.max.y - aabb.min.y);
-        depthScaleFactor = maxCellDimension / (aabb.max.z - aabb.min.z);
-
-        widthOffset = -aabb.min.x;
-        heightOffset = -aabb.min.y;
-        depthOffset = -aabb.min.z;
+        setExtent(aabb);
 
         int numNodes = getLevelOffset(depth);
         octree = new int[numNodes];
     }
 
     @Override
+    @Const
+    public AxisAlignedBox getExtent() {
+        return rootBounds;
+    }
+
+    @Override
+    public void setExtent(AxisAlignedBox bounds) {
+        if (size > 0) {
+            throw new IllegalStateException("Index is not empty");
+        }
+
+        rootBounds.set(bounds);
+
+        widthScaleFactor = maxCellDimension / (rootBounds.max.x - rootBounds.min.x);
+        heightScaleFactor = maxCellDimension / (rootBounds.max.y - rootBounds.min.y);
+        depthScaleFactor = maxCellDimension / (rootBounds.max.z - rootBounds.min.z);
+
+        widthOffset = -rootBounds.min.x;
+        heightOffset = -rootBounds.min.y;
+        depthOffset = -rootBounds.min.z;
+    }
+
+    @Override
     public boolean remove(T element) {
         if (element == null) {
             throw new NullPointerException("Item cannot be null");

ferox-math/src/main/java/com/ferox/math/bounds/QuadTree.java

  * @author Michael Ludwig
  * @param <T> The data type stored in the quadtree
  */
-public class QuadTree<T> implements SpatialIndex<T> {
+public class QuadTree<T> implements BoundedSpatialIndex<T> {
     private static final int POS_X = 0x1;
     private static final int POS_Y = 0x2;
 
     private final Cell[] spatialHash;
     private final int maxCellDimension;
 
-    private final double widthScaleFactor;
-    private final double heightScaleFactor;
+    private double widthScaleFactor;
+    private double heightScaleFactor;
 
-    private final double widthOffset;
-    private final double heightOffset;
+    private double widthOffset;
+    private double heightOffset;
 
     private final AxisAlignedBox rootBounds;
 
         }
 
         this.depth = depth;
-        rootBounds = aabb.clone();
+        rootBounds = new AxisAlignedBox();
 
         maxCellDimension = 1 << (depth - 1);
         spatialHash = new Cell[maxCellDimension * maxCellDimension];
         size = 0;
         queryIdCounter = 0;
 
-        widthScaleFactor = maxCellDimension / (getFirstDimension(aabb.max) - getFirstDimension(aabb.min));
-        heightScaleFactor = maxCellDimension / (getSecondDimension(aabb.max) - getSecondDimension(aabb.min));
-
-        widthOffset = -getFirstDimension(aabb.min);
-        heightOffset = -getSecondDimension(aabb.min);
+        setExtent(aabb);
 
         int numNodes = getLevelOffset(depth);
         quadtree = new int[numNodes];
     }
 
     @Override
+    @Const
+    public AxisAlignedBox getExtent() {
+        return rootBounds;
+    }
+
+    @Override
+    public void setExtent(AxisAlignedBox bounds) {
+        if (size > 0) {
+            throw new IllegalStateException("Index is not empty");
+        }
+
+        rootBounds.set(bounds);
+
+        widthScaleFactor = maxCellDimension / (getFirstDimension(rootBounds.max) - getFirstDimension(rootBounds.min));
+        heightScaleFactor = maxCellDimension / (getSecondDimension(rootBounds.max) - getSecondDimension(rootBounds.min));
+
+        widthOffset = -getFirstDimension(rootBounds.min);
+        heightOffset = -getSecondDimension(rootBounds.min);
+    }
+
+    @Override
     public boolean remove(T element) {
         if (element == null) {
             throw new NullPointerException("Item cannot be null");
         int minX = hashCellX(bounds.min);
         int minY = hashCellY(bounds.min);
         int maxX = hashCellX(bounds.max);
-        int maxY = hashCellY(bounds.max); // FIXME if exactly on far edge of max, we get out of bounds
+        int maxY = hashCellY(bounds.max);
 
         int hash;
         Cell cell;