package sim.physics2D; import sim.engine.SimState; import sim.engine.Steppable; import sim.physics2D.forceGenerator.*; import sim.physics2D.integrator.*; import sim.physics2D.constraint.*; import sim.physics2D.collisionDetection.*; import sim.physics2D.physicalObject.*; import sim.util.Bag; /** PhysicsEngine2D coordinates all the activities of the physics engine. */ public class PhysicsEngine2D implements Steppable { private final static double ZERO_VELOCITY = 0.000001; private final static double STICKY_THRESHOLD = 0.02; private ODESolver objODE; private CollisionDetectionEngine objCDE; private PhysicsState physicsState; private ConstraintEngine objCE; private ForceEngine objFE; public PhysicsEngine2D() { physicsState = PhysicsState.reset(); objCE = ConstraintEngine.reset(); objFE = ForceEngine.reset(); objCDE = new CollisionDetectionEngine(); objODE = new ODERungeKuttaSolver(); } /** Replace the default runge-kutta ODE integrator with a new one. */ public void setODESolver(ODESolver solver) { this.objODE = solver; } public void step(SimState state) { physicsState.backupCurrentPosition(); // Handle collisions Bag contactList = objCDE.getCollisions(); Bag collidingList = new Bag(); // Notify each object involved in collisions of the collision for (int i = 0; i < contactList.size(); i++) { CollisionPair pair = (CollisionPair)contactList.objs[i]; int colType1 = pair.c1.handleCollision(pair.c2, pair.getColPoint1()); int colType2 = pair.c2.handleCollision(pair.c1, pair.getColPoint2()); if (colType1 != 0 && colType2 != 0) { if (colType1 == 2 || colType2 == 2) pair.setSticky(); collidingList.add(pair); } } objCE.addCollisionResponses(collidingList); // Handle resting contacts and other forces/constraints physicsState.saveLastState(); objODE.solve(1); } /** Registers a physical object, force generator, or constraint * with the physics engine. */ public void register(Object obj) { if (obj instanceof PhysicalObject2D) objCDE.register((PhysicalObject2D)obj); if (obj instanceof MobileObject2D) objFE.registerMobileObject((MobileObject2D)obj); if (obj instanceof ForceGenerator) objFE.registerForceGenerator((ForceGenerator)obj); if (obj instanceof ForceConstraint) objCE.registerForceConstraint((ForceConstraint)obj); if (obj instanceof ImpulseConstraint) objCE.registerImpulseConstraint((ImpulseConstraint)obj); } /** Turns off collision response for a pair of objects */ public void setNoCollisions(PhysicalObject2D c1, PhysicalObject2D c2) { objCE.setNoCollisions(c1, c2); } /** Removes a constraint */ public void unRegister(Object obj) { if (obj instanceof ForceConstraint) objCE.unRegisterForceConstraint((ForceConstraint)obj); if (obj instanceof ImpulseConstraint) objCE.unRegisterImpulseConstraint((ImpulseConstraint)obj); } }