Commits

Michael Ludwig committed 7b3dc5c

Update physics module to use entreri-1.6.0-SNAPSHOT

Comments (0)

Files changed (16)

ferox-physics/src/main/java/com/ferox/physics/collision/CollisionBody.java

 import com.ferox.math.entreri.Matrix4Property;
 import com.ferox.math.entreri.Matrix4Property.DefaultMatrix4;
 import com.lhkbob.entreri.ComponentData;
-import com.lhkbob.entreri.TypeId;
 import com.lhkbob.entreri.Unmanaged;
 import com.lhkbob.entreri.property.DoubleProperty;
 import com.lhkbob.entreri.property.DoubleProperty.DefaultDouble;
      */
     public static final int MAX_GROUPS = 64;
 
-    /**
-     * TypeId for CollisionBody's.
-     */
-    public static final TypeId<CollisionBody> ID = TypeId.get(CollisionBody.class);
-
     @DefaultMatrix4(m00 = 1.0, m01 = 0.0, m02 = 0.0, m03 = 0.0, m10 = 0.0, m11 = 1.0,
                     m12 = 0.0, m13 = 0.0, m20 = 0.0, m21 = 0.0, m22 = 1.0, m23 = 0.0,
                     m30 = 0.0, m31 = 0.0, m32 = 0.0, m33 = 1.0)
      * 
      * @return The world transform of the Collidable
      */
-    public @Const
-    Matrix4 getTransform() {
+    @Const
+    public Matrix4 getTransform() {
         return transformCache;
     }
 
      * 
      * @return The world bounds of this CollisionBody
      */
-    public @Const
-    AxisAlignedBox getWorldBounds() {
+    @Const
+    public AxisAlignedBox getWorldBounds() {
         return boundsCache;
     }
 

ferox-physics/src/main/java/com/ferox/physics/controller/CollisionController.java

-/*
- * Ferox, a graphics and game library in Java
- *
- * Copyright (c) 2012, Michael Ludwig
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- *     Redistributions of source code must retain the above copyright notice,
- *         this list of conditions and the following disclaimer.
- *     Redistributions in binary form must reproduce the above copyright notice,
- *         this list of conditions and the following disclaimer in the
- *         documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package com.ferox.physics.controller;
-
-import com.ferox.physics.collision.ClosestPair;
-import com.ferox.physics.collision.CollisionBody;
-import com.ferox.physics.dynamics.ContactManifoldPool;
-import com.ferox.physics.dynamics.LinearConstraintPool;
-import com.lhkbob.entreri.Component;
-import com.lhkbob.entreri.EntitySystem;
-import com.lhkbob.entreri.SimpleController;
-
-public abstract class CollisionController extends SimpleController {
-    private final ContactManifoldPool manifolds;
-
-    private final LinearConstraintPool contactGroup;
-    private final LinearConstraintPool frictionGroup;
-
-    public CollisionController() {
-        manifolds = new ContactManifoldPool();
-        contactGroup = new LinearConstraintPool(null);
-        frictionGroup = new LinearConstraintPool(contactGroup);
-    }
-
-    public ContactManifoldPool getContactManifoldPool() {
-        return manifolds;
-    }
-
-    public LinearConstraintPool getContactGroup() {
-        return contactGroup;
-    }
-
-    public LinearConstraintPool getFrictionGroup() {
-        return frictionGroup;
-    }
-
-    @Override
-    @SuppressWarnings("unchecked")
-    public void onComponentRemove(Component<?> c) {
-        if (c.getTypeId() == CollisionBody.ID) {
-            // must remove all contacts connected to this entity from the cache
-            manifolds.removeAllContacts((Component<CollisionBody>) c);
-        }
-    }
-
-    @Override
-    public void init(EntitySystem system) {
-        super.init(system);
-        manifolds.setEntitySystem(system);
-    }
-
-    @Override
-    public void preProcess(double dt) {
-        // reset constraint pools
-        contactGroup.clear();
-        frictionGroup.clear();
-    }
-
-    @Override
-    public void postProcess(double dt) {
-        // read back computed impulses from constraint solving controller
-        manifolds.computeWarmstartImpulses(contactGroup, frictionGroup);
-    }
-
-    protected void reportConstraints(double dt) {
-        manifolds.generateConstraints(dt, contactGroup, frictionGroup);
-        getEntitySystem().getControllerManager()
-                         .report(new ConstraintResult(contactGroup));
-        getEntitySystem().getControllerManager()
-                         .report(new ConstraintResult(frictionGroup));
-    }
-
-    protected void notifyContact(CollisionBody bodyA, CollisionBody bodyB,
-                                 ClosestPair contact) {
-        manifolds.addContact(bodyA, bodyB, contact);
-    }
-}

ferox-physics/src/main/java/com/ferox/physics/controller/CollisionTask.java

+/*
+ * Ferox, a graphics and game library in Java
+ *
+ * Copyright (c) 2012, Michael Ludwig
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ *     Redistributions of source code must retain the above copyright notice,
+ *         this list of conditions and the following disclaimer.
+ *     Redistributions in binary form must reproduce the above copyright notice,
+ *         this list of conditions and the following disclaimer in the
+ *         documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.ferox.physics.controller;
+
+import java.util.Collections;
+import java.util.Set;
+
+import com.ferox.physics.collision.ClosestPair;
+import com.ferox.physics.collision.CollisionBody;
+import com.ferox.physics.dynamics.ContactManifoldPool;
+import com.ferox.physics.dynamics.LinearConstraintPool;
+import com.lhkbob.entreri.ComponentData;
+import com.lhkbob.entreri.EntitySystem;
+import com.lhkbob.entreri.task.ElapsedTimeResult;
+import com.lhkbob.entreri.task.Job;
+import com.lhkbob.entreri.task.ParallelAware;
+import com.lhkbob.entreri.task.Task;
+
+public abstract class CollisionTask implements Task {
+    private final ContactManifoldPool manifolds;
+
+    private final LinearConstraintPool contactGroup;
+    private final LinearConstraintPool frictionGroup;
+
+    protected double dt;
+
+    public CollisionTask() {
+        manifolds = new ContactManifoldPool();
+        contactGroup = new LinearConstraintPool(null);
+        frictionGroup = new LinearConstraintPool(contactGroup);
+    }
+
+    public void report(ElapsedTimeResult dt) {
+        this.dt = dt.getTimeDelta();
+    }
+
+    @Override
+    public Task process(EntitySystem system, Job job) {
+        return new WarmstartTask();
+    }
+
+    @Override
+    public void reset(EntitySystem system) {
+        if (manifolds.getEntitySystem() != system) {
+            manifolds.setEntitySystem(system);
+        }
+
+        // reset constraint pools
+        contactGroup.clear();
+        frictionGroup.clear();
+    }
+
+    protected void reportConstraints(Job job) {
+        manifolds.generateConstraints(dt, contactGroup, frictionGroup);
+        job.report(new ConstraintResult(contactGroup));
+        job.report(new ConstraintResult(frictionGroup));
+    }
+
+    protected void notifyContact(CollisionBody bodyA, CollisionBody bodyB,
+                                 ClosestPair contact) {
+        manifolds.addContact(bodyA, bodyB, contact);
+    }
+
+    private class WarmstartTask implements Task, ParallelAware {
+        @Override
+        public Set<Class<? extends ComponentData<?>>> getAccessedComponents() {
+            return Collections.emptySet();
+        }
+
+        @Override
+        public boolean isEntitySetModified() {
+            return false;
+        }
+
+        @Override
+        public Task process(EntitySystem system, Job job) {
+            // read back computed impulses from constraint solving controller
+            manifolds.computeWarmstartImpulses(contactGroup, frictionGroup);
+            return null;
+        }
+
+        @Override
+        public void reset(EntitySystem system) {
+
+        }
+    }
+}

ferox-physics/src/main/java/com/ferox/physics/controller/ConstraintResult.java

 package com.ferox.physics.controller;
 
 import com.ferox.physics.dynamics.LinearConstraintPool;
-import com.lhkbob.entreri.Result;
+import com.lhkbob.entreri.task.Result;
 
-public class ConstraintResult implements Result {
+public class ConstraintResult extends Result {
     private final LinearConstraintPool group;
 
     public ConstraintResult(LinearConstraintPool group) {

ferox-physics/src/main/java/com/ferox/physics/controller/ConstraintSolvingController.java

-/*
- * Ferox, a graphics and game library in Java
- *
- * Copyright (c) 2012, Michael Ludwig
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- *     Redistributions of source code must retain the above copyright notice,
- *         this list of conditions and the following disclaimer.
- *     Redistributions in binary form must reproduce the above copyright notice,
- *         this list of conditions and the following disclaimer in the
- *         documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package com.ferox.physics.controller;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import com.ferox.math.Vector3;
-import com.ferox.math.entreri.Vector3Property;
-import com.ferox.physics.dynamics.LinearConstraintPool;
-import com.ferox.physics.dynamics.LinearConstraintSolver;
-import com.ferox.physics.dynamics.RigidBody;
-import com.lhkbob.entreri.EntitySystem;
-import com.lhkbob.entreri.Result;
-import com.lhkbob.entreri.SimpleController;
-
-public class ConstraintSolvingController extends SimpleController {
-    private final LinearConstraintSolver solver;
-
-    private List<LinearConstraintPool> groups;
-
-    private Vector3Property deltaLinearImpulse;
-    private Vector3Property deltaAngularImpulse;
-
-    public ConstraintSolvingController() {
-        solver = new LinearConstraintSolver();
-    }
-
-    public LinearConstraintSolver getSolver() {
-        return solver;
-    }
-
-    @Override
-    public void preProcess(double dt) {
-        groups = new ArrayList<LinearConstraintPool>();
-    }
-
-    @Override
-    public void process(double dt) {
-        Vector3 d = new Vector3();
-
-        LinearConstraintPool[] asArray = groups.toArray(new LinearConstraintPool[groups.size()]);
-        solver.solve(asArray);
-
-        // now apply all of the delta impulses back to the rigid bodies
-        Iterator<RigidBody> it = getEntitySystem().iterator(RigidBody.ID);
-        while (it.hasNext()) {
-            RigidBody b = it.next();
-
-            // linear velocity
-            deltaLinearImpulse.get(b.getIndex(), d);
-            b.setVelocity(d.add(b.getVelocity()));
-
-            // angular velocity
-            deltaAngularImpulse.get(b.getIndex(), d);
-            b.setAngularVelocity(d.add(b.getAngularVelocity()));
-
-            // 0 out delta impulse for next frame
-            d.set(0, 0, 0);
-            deltaLinearImpulse.set(d, b.getIndex());
-            deltaAngularImpulse.set(d, b.getIndex());
-        }
-    }
-
-    @Override
-    public void report(Result r) {
-        if (r instanceof ConstraintResult) {
-            groups.add(((ConstraintResult) r).getConstraints());
-        }
-    }
-
-    @Override
-    public void init(EntitySystem system) {
-        super.init(system);
-        deltaLinearImpulse = system.decorate(RigidBody.ID,
-                                             new Vector3Property.Factory(new Vector3()));
-        deltaAngularImpulse = system.decorate(RigidBody.ID,
-                                              new Vector3Property.Factory(new Vector3()));
-
-        solver.setDeltaLinearImpulseProperty(deltaLinearImpulse);
-        solver.setDeltaAngularImpulseProperty(deltaAngularImpulse);
-    }
-
-    @Override
-    public void destroy() {
-        getEntitySystem().undecorate(RigidBody.ID, deltaLinearImpulse);
-        getEntitySystem().undecorate(RigidBody.ID, deltaAngularImpulse);
-        super.destroy();
-    }
-}

ferox-physics/src/main/java/com/ferox/physics/controller/ConstraintSolvingTask.java

+/*
+ * Ferox, a graphics and game library in Java
+ *
+ * Copyright (c) 2012, Michael Ludwig
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ *     Redistributions of source code must retain the above copyright notice,
+ *         this list of conditions and the following disclaimer.
+ *     Redistributions in binary form must reproduce the above copyright notice,
+ *         this list of conditions and the following disclaimer in the
+ *         documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.ferox.physics.controller;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+import com.ferox.math.Vector3;
+import com.ferox.math.entreri.Vector3Property;
+import com.ferox.physics.dynamics.LinearConstraintPool;
+import com.ferox.physics.dynamics.LinearConstraintSolver;
+import com.ferox.physics.dynamics.RigidBody;
+import com.lhkbob.entreri.ComponentData;
+import com.lhkbob.entreri.ComponentIterator;
+import com.lhkbob.entreri.EntitySystem;
+import com.lhkbob.entreri.task.Job;
+import com.lhkbob.entreri.task.ParallelAware;
+import com.lhkbob.entreri.task.Task;
+
+public class ConstraintSolvingTask implements Task, ParallelAware {
+    private final LinearConstraintSolver solver;
+
+    private List<LinearConstraintPool> groups;
+
+    private Vector3Property deltaLinearImpulse;
+    private Vector3Property deltaAngularImpulse;
+
+    // instances used locally but instantiated once to save performance
+    private RigidBody rigidBody;
+    private ComponentIterator iterator;
+    private final Vector3 delta = new Vector3();
+
+    public ConstraintSolvingTask() {
+        solver = new LinearConstraintSolver();
+    }
+
+    @Override
+    public void reset(EntitySystem system) {
+        if (rigidBody == null) {
+            rigidBody = system.createDataInstance(RigidBody.class);
+            iterator = new ComponentIterator(system);
+            iterator.addRequired(rigidBody);
+
+            deltaLinearImpulse = system.decorate(RigidBody.class,
+                                                 new Vector3Property.Factory(new Vector3()));
+            deltaAngularImpulse = system.decorate(RigidBody.class,
+                                                  new Vector3Property.Factory(new Vector3()));
+
+            solver.setDeltaLinearImpulseProperty(deltaLinearImpulse);
+            solver.setDeltaAngularImpulseProperty(deltaAngularImpulse);
+        }
+
+        groups = new ArrayList<LinearConstraintPool>();
+        iterator.reset();
+    }
+
+    @Override
+    public Task process(EntitySystem system, Job job) {
+        LinearConstraintPool[] asArray = groups.toArray(new LinearConstraintPool[groups.size()]);
+        solver.solve(asArray);
+
+        // now apply all of the delta impulses back to the rigid bodies
+        while (iterator.next()) {
+            // linear velocity
+            deltaLinearImpulse.get(rigidBody.getIndex(), delta);
+            rigidBody.setVelocity(delta.add(rigidBody.getVelocity()));
+
+            // angular velocity
+            deltaAngularImpulse.get(rigidBody.getIndex(), delta);
+            rigidBody.setAngularVelocity(delta.add(rigidBody.getAngularVelocity()));
+
+            // 0 out delta impulse for next frame
+            delta.set(0, 0, 0);
+            deltaLinearImpulse.set(delta, rigidBody.getIndex());
+            deltaAngularImpulse.set(delta, rigidBody.getIndex());
+        }
+
+        return null;
+    }
+
+    public void report(ConstraintResult r) {
+        groups.add(r.getConstraints());
+    }
+
+    @Override
+    public Set<Class<? extends ComponentData<?>>> getAccessedComponents() {
+        return Collections.<Class<? extends ComponentData<?>>> singleton(RigidBody.class);
+    }
+
+    @Override
+    public boolean isEntitySetModified() {
+        return false;
+    }
+}

ferox-physics/src/main/java/com/ferox/physics/controller/ForcesController.java

-/*
- * Ferox, a graphics and game library in Java
- *
- * Copyright (c) 2012, Michael Ludwig
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- *     Redistributions of source code must retain the above copyright notice,
- *         this list of conditions and the following disclaimer.
- *     Redistributions in binary form must reproduce the above copyright notice,
- *         this list of conditions and the following disclaimer in the
- *         documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package com.ferox.physics.controller;
-
-import com.ferox.math.Const;
-import com.ferox.math.Matrix3;
-import com.ferox.math.Matrix4;
-import com.ferox.math.Vector3;
-import com.ferox.physics.collision.CollisionBody;
-import com.ferox.physics.dynamics.ExplicitEulerIntegrator;
-import com.ferox.physics.dynamics.Gravity;
-import com.ferox.physics.dynamics.Integrator;
-import com.ferox.physics.dynamics.RigidBody;
-import com.lhkbob.entreri.ComponentIterator;
-import com.lhkbob.entreri.SimpleController;
-
-public class ForcesController extends SimpleController {
-    private Integrator integrator;
-    private final Vector3 defaultGravity;
-
-    public ForcesController() {
-        defaultGravity = new Vector3(0, -10, 0);
-        setIntegrator(new ExplicitEulerIntegrator());
-    }
-
-    public void setGravity(@Const Vector3 gravity) {
-        defaultGravity.set(gravity);
-    }
-
-    public void setIntegrator(Integrator integrator) {
-        if (integrator == null) {
-            throw new NullPointerException("Integrator can't be null");
-        }
-        this.integrator = integrator;
-    }
-
-    public Integrator getIntegrator() {
-        return integrator;
-    }
-
-    @Override
-    public void process(double dt) {
-        Vector3 inertia = new Vector3();
-        Vector3 force = new Vector3();
-        Matrix3 rotation = new Matrix3();
-
-        RigidBody rb = getEntitySystem().createDataInstance(RigidBody.ID);
-        CollisionBody cb = getEntitySystem().createDataInstance(CollisionBody.ID);
-        Gravity g = getEntitySystem().createDataInstance(Gravity.ID);
-
-        ComponentIterator it = new ComponentIterator(getEntitySystem());
-        it.addRequired(rb);
-        it.addRequired(cb);
-        it.addOptional(g);
-
-        while (it.next()) {
-            Matrix4 transform = cb.getTransform();
-
-            // compute the body's new inertia tensor
-            // FIXME this might not be the best place to do this computation
-            Matrix3 tensor = rb.getInertiaTensorInverse();
-
-            cb.getShape().getInertiaTensor(rb.getMass(), inertia);
-            inertia.set(1.0 / inertia.x, 1.0 / inertia.y, 1.0 / inertia.z);
-
-            rotation.setUpper(transform);
-            tensor.mulDiagonal(rotation, inertia).mulTransposeRight(rotation);
-            rb.setInertiaTensorInverse(tensor);
-
-            // add gravity force
-            if (g.isEnabled()) {
-                force.scale(g.getGravity(), rb.getMass());
-            } else {
-                force.scale(defaultGravity, rb.getMass());
-            }
-
-            rb.addForce(force, null);
-
-            // integrate and apply forces to the body's velocity
-            Vector3 lv = rb.getVelocity();
-            integrator.integrateLinearAcceleration(force.scale(rb.getTotalForce(),
-                                                               rb.getInverseMass()), dt,
-                                                   lv);
-            rb.setVelocity(lv);
-
-            Vector3 la = rb.getAngularVelocity();
-            integrator.integrateAngularAcceleration(force.mul(tensor, rb.getTotalTorque()),
-                                                    dt, la);
-            rb.setAngularVelocity(la);
-
-            rb.clearForces();
-        }
-    }
-}

ferox-physics/src/main/java/com/ferox/physics/controller/ForcesTask.java

+/*
+ * Ferox, a graphics and game library in Java
+ *
+ * Copyright (c) 2012, Michael Ludwig
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ *     Redistributions of source code must retain the above copyright notice,
+ *         this list of conditions and the following disclaimer.
+ *     Redistributions in binary form must reproduce the above copyright notice,
+ *         this list of conditions and the following disclaimer in the
+ *         documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.ferox.physics.controller;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import com.ferox.math.Const;
+import com.ferox.math.Matrix3;
+import com.ferox.math.Matrix4;
+import com.ferox.math.Vector3;
+import com.ferox.physics.collision.CollisionBody;
+import com.ferox.physics.dynamics.ExplicitEulerIntegrator;
+import com.ferox.physics.dynamics.Gravity;
+import com.ferox.physics.dynamics.Integrator;
+import com.ferox.physics.dynamics.RigidBody;
+import com.lhkbob.entreri.ComponentData;
+import com.lhkbob.entreri.ComponentIterator;
+import com.lhkbob.entreri.EntitySystem;
+import com.lhkbob.entreri.task.ElapsedTimeResult;
+import com.lhkbob.entreri.task.Job;
+import com.lhkbob.entreri.task.ParallelAware;
+import com.lhkbob.entreri.task.Task;
+
+// FIXME this task should be split into 3 pieces:
+// 1. inertia tensor computer (which must be done before any force can be added to a body)
+// 2. gravity force applier
+// 3. force integrator
+public class ForcesTask implements Task, ParallelAware {
+    private static final Set<Class<? extends ComponentData<?>>> COMPONENTS;
+    static {
+        Set<Class<? extends ComponentData<?>>> types = new HashSet<Class<? extends ComponentData<?>>>();
+        types.add(CollisionBody.class);
+        types.add(RigidBody.class);
+        types.add(Gravity.class);
+        COMPONENTS = Collections.unmodifiableSet(types);
+    }
+
+    private final Integrator integrator;
+    private final Vector3 defaultGravity;
+
+    private double dt;
+
+    // cached instances that could be local to process()
+    private RigidBody rigidBody;
+    private CollisionBody colBody;
+    private Gravity gravity;
+    private ComponentIterator iterator;
+
+    private final Vector3 inertia = new Vector3();
+    private final Vector3 force = new Vector3();
+    private final Matrix3 rotation = new Matrix3();
+
+    public ForcesTask() {
+        this(new Vector3(0, -9.8, 0));
+    }
+
+    public ForcesTask(@Const Vector3 gravity) {
+        this(gravity, new ExplicitEulerIntegrator());
+    }
+
+    public ForcesTask(@Const Vector3 gravity, Integrator integrator) {
+        if (integrator == null) {
+            throw new NullPointerException("Integrator cannot be null");
+        }
+        defaultGravity = gravity.clone();
+        this.integrator = integrator;
+    }
+
+    public void report(ElapsedTimeResult dt) {
+        this.dt = dt.getTimeDelta();
+    }
+
+    @Override
+    public void reset(EntitySystem system) {
+        if (rigidBody == null) {
+            rigidBody = system.createDataInstance(RigidBody.class);
+            colBody = system.createDataInstance(CollisionBody.class);
+            gravity = system.createDataInstance(Gravity.class);
+
+            iterator = new ComponentIterator(system).addRequired(rigidBody)
+                                                    .addRequired(colBody)
+                                                    .addOptional(gravity);
+        }
+
+        iterator.reset();
+    }
+
+    @Override
+    public Task process(EntitySystem system, Job job) {
+        while (iterator.next()) {
+            Matrix4 transform = colBody.getTransform();
+
+            // compute the body's new inertia tensor
+            Matrix3 tensor = rigidBody.getInertiaTensorInverse();
+
+            colBody.getShape().getInertiaTensor(rigidBody.getMass(), inertia);
+            inertia.set(1.0 / inertia.x, 1.0 / inertia.y, 1.0 / inertia.z);
+
+            rotation.setUpper(transform);
+            tensor.mulDiagonal(rotation, inertia).mulTransposeRight(rotation);
+            rigidBody.setInertiaTensorInverse(tensor);
+
+            // add gravity force
+            if (gravity.isEnabled()) {
+                force.scale(gravity.getGravity(), rigidBody.getMass());
+            } else {
+                force.scale(defaultGravity, rigidBody.getMass());
+            }
+
+            rigidBody.addForce(force, null);
+
+            // integrate and apply forces to the body's velocity
+            Vector3 lv = rigidBody.getVelocity();
+            integrator.integrateLinearAcceleration(force.scale(rigidBody.getTotalForce(),
+                                                               rigidBody.getInverseMass()),
+                                                   dt, lv);
+            rigidBody.setVelocity(lv);
+
+            Vector3 la = rigidBody.getAngularVelocity();
+            integrator.integrateAngularAcceleration(force.mul(tensor,
+                                                              rigidBody.getTotalTorque()),
+                                                    dt, la);
+            rigidBody.setAngularVelocity(la);
+
+            // reset forces
+            rigidBody.clearForces();
+        }
+
+        return null;
+    }
+
+    @Override
+    public Set<Class<? extends ComponentData<?>>> getAccessedComponents() {
+        return COMPONENTS;
+    }
+
+    @Override
+    public boolean isEntitySetModified() {
+        return false;
+    }
+}

ferox-physics/src/main/java/com/ferox/physics/controller/MotionController.java

-/*
- * Ferox, a graphics and game library in Java
- *
- * Copyright (c) 2012, Michael Ludwig
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- *     Redistributions of source code must retain the above copyright notice,
- *         this list of conditions and the following disclaimer.
- *     Redistributions in binary form must reproduce the above copyright notice,
- *         this list of conditions and the following disclaimer in the
- *         documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package com.ferox.physics.controller;
-
-import com.ferox.math.Const;
-import com.ferox.math.Matrix3;
-import com.ferox.math.Matrix4;
-import com.ferox.math.Vector3;
-import com.ferox.physics.collision.CollisionBody;
-import com.ferox.physics.dynamics.ExplicitEulerIntegrator;
-import com.ferox.physics.dynamics.Integrator;
-import com.ferox.physics.dynamics.RigidBody;
-import com.lhkbob.entreri.ComponentIterator;
-import com.lhkbob.entreri.SimpleController;
-
-public class MotionController extends SimpleController {
-    private Integrator integrator;
-
-    public MotionController() {
-        setIntegrator(new ExplicitEulerIntegrator());
-    }
-
-    public void setIntegrator(Integrator integrator) {
-        if (integrator == null) {
-            throw new NullPointerException("Integrator can't be null");
-        }
-        this.integrator = integrator;
-    }
-
-    public Integrator getIntegrator() {
-        return integrator;
-    }
-
-    @Override
-    public void process(double dt) {
-        Vector3 predictedPosition = new Vector3();
-        Matrix3 predictedRotation = new Matrix3();
-
-        RigidBody rb = getEntitySystem().createDataInstance(RigidBody.ID);
-        CollisionBody cb = getEntitySystem().createDataInstance(CollisionBody.ID);
-
-        ComponentIterator it = new ComponentIterator(getEntitySystem());
-        it.addRequired(rb);
-        it.addRequired(cb);
-
-        while (it.next()) {
-            Matrix4 transform = cb.getTransform();
-
-            predictedRotation.setUpper(transform);
-            predictedPosition.set(transform.m03, transform.m13, transform.m23);
-
-            integrator.integrateLinearVelocity(rb.getVelocity(), dt, predictedPosition);
-            integrator.integrateAngularVelocity(rb.getAngularVelocity(), dt,
-                                                predictedRotation);
-
-            // push values back into transform
-            setTransform(predictedRotation, predictedPosition, transform);
-
-            cb.setTransform(transform);
-        }
-    }
-
-    private void setTransform(@Const Matrix3 r, @Const Vector3 p, Matrix4 t) {
-        t.setUpper(r);
-
-        t.m03 = p.x;
-        t.m13 = p.y;
-        t.m23 = p.z;
-
-        // ensure this is still an affine transform
-        t.m30 = 0.0;
-        t.m31 = 0.0;
-        t.m32 = 0.0;
-        t.m33 = 1.0;
-    }
-}

ferox-physics/src/main/java/com/ferox/physics/controller/MotionTask.java

+/*
+ * Ferox, a graphics and game library in Java
+ *
+ * Copyright (c) 2012, Michael Ludwig
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ *     Redistributions of source code must retain the above copyright notice,
+ *         this list of conditions and the following disclaimer.
+ *     Redistributions in binary form must reproduce the above copyright notice,
+ *         this list of conditions and the following disclaimer in the
+ *         documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.ferox.physics.controller;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import com.ferox.math.Const;
+import com.ferox.math.Matrix3;
+import com.ferox.math.Matrix4;
+import com.ferox.math.Vector3;
+import com.ferox.physics.collision.CollisionBody;
+import com.ferox.physics.dynamics.ExplicitEulerIntegrator;
+import com.ferox.physics.dynamics.Integrator;
+import com.ferox.physics.dynamics.RigidBody;
+import com.lhkbob.entreri.ComponentData;
+import com.lhkbob.entreri.ComponentIterator;
+import com.lhkbob.entreri.EntitySystem;
+import com.lhkbob.entreri.task.ElapsedTimeResult;
+import com.lhkbob.entreri.task.Job;
+import com.lhkbob.entreri.task.ParallelAware;
+import com.lhkbob.entreri.task.Task;
+
+public class MotionTask implements Task, ParallelAware {
+    private static final Set<Class<? extends ComponentData<?>>> COMPONENTS;
+    static {
+        Set<Class<? extends ComponentData<?>>> types = new HashSet<Class<? extends ComponentData<?>>>();
+        types.add(CollisionBody.class);
+        types.add(RigidBody.class);
+        COMPONENTS = Collections.unmodifiableSet(types);
+    }
+
+    private final Integrator integrator;
+
+    private double dt;
+
+    // values that could be local to process(), but don't need to be allocated
+    // every frame
+    private final Vector3 predictedPosition = new Vector3();
+    private final Matrix3 predictedRotation = new Matrix3();
+
+    private RigidBody rigidBody;
+    private CollisionBody collisionBody;
+    private ComponentIterator iterator;
+
+    public MotionTask() {
+        this(new ExplicitEulerIntegrator());
+    }
+
+    public MotionTask(Integrator integrator) {
+        if (integrator == null) {
+            throw new NullPointerException("Integrator can't be null");
+        }
+        this.integrator = integrator;
+    }
+
+    public void report(ElapsedTimeResult dt) {
+        this.dt = dt.getTimeDelta();
+    }
+
+    @Override
+    public void reset(EntitySystem system) {
+        if (iterator == null) {
+            rigidBody = system.createDataInstance(RigidBody.class);
+            collisionBody = system.createDataInstance(CollisionBody.class);
+            iterator = new ComponentIterator(system);
+        } else {
+            iterator.reset();
+        }
+    }
+
+    @Override
+    public Task process(EntitySystem system, Job job) {
+        while (iterator.next()) {
+            Matrix4 transform = collisionBody.getTransform();
+
+            predictedRotation.setUpper(transform);
+            predictedPosition.set(transform.m03, transform.m13, transform.m23);
+
+            integrator.integrateLinearVelocity(rigidBody.getVelocity(), dt,
+                                               predictedPosition);
+            integrator.integrateAngularVelocity(rigidBody.getAngularVelocity(), dt,
+                                                predictedRotation);
+
+            // push values back into transform
+            setTransform(predictedRotation, predictedPosition, transform);
+
+            collisionBody.setTransform(transform);
+        }
+
+        return null;
+    }
+
+    private void setTransform(@Const Matrix3 r, @Const Vector3 p, Matrix4 t) {
+        t.setUpper(r);
+
+        t.m03 = p.x;
+        t.m13 = p.y;
+        t.m23 = p.z;
+
+        // ensure this is still an affine transform
+        t.m30 = 0.0;
+        t.m31 = 0.0;
+        t.m32 = 0.0;
+        t.m33 = 1.0;
+    }
+
+    @Override
+    public Set<Class<? extends ComponentData<?>>> getAccessedComponents() {
+        return COMPONENTS;
+    }
+
+    @Override
+    public boolean isEntitySetModified() {
+        return false;
+    }
+}

ferox-physics/src/main/java/com/ferox/physics/controller/SingleAxisSAPCollisionController.java

  */
 package com.ferox.physics.controller;
 
-public class SingleAxisSAPCollisionController extends CollisionController {
+public class SingleAxisSAPCollisionController extends CollisionTask {
 
 }

ferox-physics/src/main/java/com/ferox/physics/controller/SpatialIndexCollisionController.java

  */
 package com.ferox.physics.controller;
 
+import java.util.Collections;
+import java.util.Set;
+
 import com.ferox.math.AxisAlignedBox;
+import com.ferox.math.bounds.BoundedSpatialIndex;
 import com.ferox.math.bounds.IntersectionCallback;
 import com.ferox.math.bounds.SpatialIndex;
 import com.ferox.physics.collision.ClosestPair;
 import com.ferox.physics.collision.CollisionAlgorithm;
 import com.ferox.physics.collision.CollisionAlgorithmProvider;
 import com.ferox.physics.collision.CollisionBody;
+import com.lhkbob.entreri.ComponentData;
 import com.lhkbob.entreri.ComponentIterator;
 import com.lhkbob.entreri.Entity;
+import com.lhkbob.entreri.EntitySystem;
+import com.lhkbob.entreri.task.Job;
+import com.lhkbob.entreri.task.ParallelAware;
+import com.lhkbob.entreri.task.Task;
 
-public class SpatialIndexCollisionController extends CollisionController {
-    private SpatialIndex<Entity> index;
-    private CollisionAlgorithmProvider algorithms;
+public class SpatialIndexCollisionController extends CollisionTask implements ParallelAware {
+    private final SpatialIndex<Entity> index;
+    private final CollisionAlgorithmProvider algorithms;
 
-    // FIXME: add a setter, too
+    // cached instances that are normally local to process()
+    private CollisionBody bodyA;
+    private CollisionBody bodyB;
+
+    private ComponentIterator iterator;
+
     public SpatialIndexCollisionController(SpatialIndex<Entity> index,
                                            CollisionAlgorithmProvider algorithms) {
+        if (index == null || algorithms == null) {
+            throw new NullPointerException("Arguments cannot be null");
+        }
         this.index = index;
         this.algorithms = algorithms;
     }
 
     @Override
-    public void preProcess(double dt) {
-        super.preProcess(dt);
+    public void reset(EntitySystem system) {
+        super.reset(system);
+
+        if (bodyA == null) {
+            bodyA = system.createDataInstance(CollisionBody.class);
+            bodyB = system.createDataInstance(CollisionBody.class);
+
+            iterator = new ComponentIterator(system).addRequired(bodyA);
+        }
+
         index.clear(true);
+        iterator.reset();
     }
 
     @Override
-    public void process(double dt) {
-        CollisionBody body1 = getEntitySystem().createDataInstance(CollisionBody.ID);
-        CollisionBody body2 = getEntitySystem().createDataInstance(CollisionBody.ID);
+    public Task process(EntitySystem system, Job job) {
+        // if the index is bounded, update its size so everything is processed
+        if (index instanceof BoundedSpatialIndex) {
+            // FIXME how much does computing the union hurt our performance?
+            // FIXME do we want to shrink the extent even when the original extent
+            // is large enough? How does that affect query performance?
+            AxisAlignedBox extent = new AxisAlignedBox();
+            boolean first = true;
+            while (iterator.next()) {
+                if (first) {
+                    extent.set(bodyA.getWorldBounds());
+                    first = false;
+                } else {
+                    extent.union(bodyA.getWorldBounds());
+                }
+            }
+
+            // make the extents slightly larger so floating point errors don't
+            // cause shapes on the edge to get discarded
+            extent.min.scale(1.1);
+            extent.max.scale(1.1);
+            ((BoundedSpatialIndex<Entity>) index).setExtent(extent);
+            iterator.reset();
+        }
 
         // fill the index with all collision bodies
-        ComponentIterator it = new ComponentIterator(getEntitySystem());
-        it.addRequired(body1);
-
-        while (it.next()) {
-            index.add(body1.getEntity(), body1.getWorldBounds());
+        while (iterator.next()) {
+            index.add(bodyA.getEntity(), bodyA.getWorldBounds());
         }
 
         // query for all intersections
-        index.query(new CollisionCallback(body1, body2));
+        index.query(new CollisionCallback(bodyA, bodyB));
 
-        reportConstraints(dt);
-    }
+        reportConstraints(job);
 
-    @Override
-    public void destroy() {
-        index.clear();
-        super.destroy();
+        return super.process(system, job);
     }
 
     private class CollisionCallback implements IntersectionCallback<Entity> {
             }
         }
     }
+
+    @Override
+    public Set<Class<? extends ComponentData<?>>> getAccessedComponents() {
+        return Collections.<Class<? extends ComponentData<?>>> singleton(CollisionBody.class);
+    }
+
+    @Override
+    public boolean isEntitySetModified() {
+        return false;
+    }
 }

ferox-physics/src/main/java/com/ferox/physics/controller/TemporalSAPCollisionController.java

  */
 package com.ferox.physics.controller;
 
-public class TemporalSAPCollisionController extends CollisionController {
+public class TemporalSAPCollisionController extends CollisionTask {
 
 }

ferox-physics/src/main/java/com/ferox/physics/dynamics/ContactManifoldPool.java

 
     public void generateConstraints(double dt, LinearConstraintPool contactPool,
                                     LinearConstraintPool frictionPool) {
-        CollisionBody bodyA = entitySystem.createDataInstance(CollisionBody.ID);
-        CollisionBody bodyB = entitySystem.createDataInstance(CollisionBody.ID);
-        RigidBody rbA = entitySystem.createDataInstance(RigidBody.ID);
-        RigidBody rbB = entitySystem.createDataInstance(RigidBody.ID);
+        CollisionBody bodyA = entitySystem.createDataInstance(CollisionBody.class);
+        CollisionBody bodyB = entitySystem.createDataInstance(CollisionBody.class);
+        RigidBody rbA = entitySystem.createDataInstance(RigidBody.class);
+        RigidBody rbB = entitySystem.createDataInstance(RigidBody.class);
 
         // we need 4 temporary vectors to compute constraint info
         Vector3 relPosA = new Vector3();
         for (int manifold = 0; manifold < maxAliveContact; manifold++) {
             if (alive[manifold]) {
                 // load in component data
-                objAs[manifold].get(bodyA);
-                objAs[manifold].get(rbA);
-                objBs[manifold].get(bodyB);
-                objBs[manifold].get(rbB);
+                boolean valid = objAs[manifold].get(bodyA);
+                valid &= objAs[manifold].get(rbA);
+                valid &= objBs[manifold].get(bodyB);
+                valid &= objBs[manifold].get(rbB);
+
+                if (!valid) {
+                    // component was removed and entity should no longer be in the manifold pool
+                    removeManifold(manifold);
+                    continue;
+                }
 
                 Matrix4 ta = bodyA.getTransform();
                 Matrix4 tb = bodyB.getTransform();
 
     private void removeManifold(int manifold) {
         // remove map entry
-        query.set(objAs[manifold].get(CollisionBody.ID),
-                  objBs[manifold].get(CollisionBody.ID));
+        query.set(objAs[manifold].get(CollisionBody.class),
+                  objBs[manifold].get(CollisionBody.class));
         manifolds.remove(query);
 
         // clear packed data

ferox-physics/src/main/java/com/ferox/physics/dynamics/Gravity.java

 import com.ferox.math.Vector3;
 import com.ferox.math.entreri.Vector3Property;
 import com.lhkbob.entreri.ComponentData;
-import com.lhkbob.entreri.TypeId;
 import com.lhkbob.entreri.Unmanaged;
 
 public class Gravity extends ComponentData<Gravity> {
-    public static final TypeId<Gravity> ID = TypeId.get(Gravity.class);
-
     private Vector3Property gravity;
 
     @Unmanaged

ferox-physics/src/main/java/com/ferox/physics/dynamics/RigidBody.java

 import com.ferox.math.Vector3;
 import com.ferox.math.entreri.Matrix3Property;
 import com.ferox.math.entreri.Vector3Property;
+import com.ferox.physics.collision.CollisionBody;
 import com.lhkbob.entreri.ComponentData;
-import com.lhkbob.entreri.TypeId;
+import com.lhkbob.entreri.Requires;
 import com.lhkbob.entreri.Unmanaged;
 import com.lhkbob.entreri.property.DoubleProperty;
 
+@Requires(CollisionBody.class)
 public class RigidBody extends ComponentData<RigidBody> {
-    public static final TypeId<RigidBody> ID = TypeId.get(RigidBody.class);
-
     private DoubleProperty inverseMass;
 
     private Matrix3Property inertiaTensorWorldInverse;
 
     private RigidBody() {}
 
-    public @Const
-    Matrix3 getInertiaTensorInverse() {
+    @Const
+    public Matrix3 getInertiaTensorInverse() {
         return tensorCache;
     }
 
         return inverseMass.get(getIndex());
     }
 
-    public @Const
-    Vector3 getVelocity() {
+    @Const
+    public Vector3 getVelocity() {
         return velocityCache;
     }
 
-    public @Const
-    Vector3 getAngularVelocity() {
+    @Const
+    public Vector3 getAngularVelocity() {
         return angularVelocityCache;
     }
 
-    public @Const
-    Vector3 getTotalForce() {
+    @Const
+    public Vector3 getTotalForce() {
         return forceCache;
     }
 
-    public @Const
-    Vector3 getTotalTorque() {
+    @Const
+    public Vector3 getTotalTorque() {
         return torqueCache;
     }