public void stepPhysics(double timeStep) {
		// Collision
		for (int i = 0; i < COLLISION_ITERATIONS; i++) {
			collisionBroadphase.updateCollisionPairs(timeStep);
			processCollisions(timeStep);
		}

		// Velocity update
		for (int i = 0; i < rigidBodies.size(); i++) {
			RigidBody rigidBody = rigidBodies.get(i);
			if (rigidBody.dynamicsType == RigidBody.DYNAMIC) {
				rigidBody.clearForces();

				// Effects
				for (int j = i + 1; j < rigidBodies.size(); j++) {
					RigidBody rigidBody2 = rigidBodies.get(j);
					if (rigidBody2.getEffect() != null) {
						Matrix3d rotation = new Matrix3d();
						rotation.set(rigidBody2.getRotation());
						Vector3d force = rigidBody2.getEffect().getForceAt(
								rigidBody2.getPosition(), rotation,
								rigidBody.getPosition());
						rigidBody.addForce(force);
					}
				}

				// Gravity
				Vector3d force = new Vector3d(gravity);
				force.scale(rigidBody.getMass());
				rigidBody.addForce(force);

				// Step
				rigidBody.stepVelocity(timeStep);
			}
		}

		// Contact
		for (int i = 0; i < CONTACT_ITERATIONS; i++) {
			collisionBroadphase.updateCollisionPairs(timeStep);
			processContacts(timeStep);
		}
		// Position update
		for (Iterator<RigidBody> it = rigidBodies.iterator(); it.hasNext();) {
			RigidBody rigidBody = (RigidBody) it.next();
			if (rigidBody.dynamicsType == RigidBody.DYNAMIC) {
				rigidBody.stepPosition(timeStep);
			}
		}

		// Cleanup
		collisionBroadphase.clearCollisionPairs();
	}