protected void updateActivationState(float timeStep) { Vector3f tmp = Stack.alloc(Vector3f.class); for (int i = 0; i < collisionObjects.size(); i++) { CollisionObject colObj = collisionObjects.getQuick(i); RigidBody body = RigidBody.upcast(colObj); if (body != null) { body.updateDeactivation(timeStep); if (body.wantsSleeping()) { if (body.isStaticOrKinematicObject()) { body.setActivationState(CollisionObject.ISLAND_SLEEPING); } else { if (body.getActivationState() == CollisionObject.ACTIVE_TAG) { body.setActivationState(CollisionObject.WANTS_DEACTIVATION); } if (body.getActivationState() == CollisionObject.ISLAND_SLEEPING) { tmp.set(0f, 0f, 0f); body.setAngularVelocity(tmp); body.setLinearVelocity(tmp); } } } else { if (body.getActivationState() != CollisionObject.DISABLE_DEACTIVATION) { body.setActivationState(CollisionObject.ACTIVE_TAG); } } } } }
protected void integrateTransforms(float timeStep) { Vector3f tmp = Stack.alloc(Vector3f.class); Transform tmpTrans = Stack.alloc(Transform.class); Transform predictedTrans = Stack.alloc(Transform.class); for (int i = 0; i < collisionObjects.size(); i++) { CollisionObject colObj = collisionObjects.getQuick(i); RigidBody body = RigidBody.upcast(colObj); if (body != null) { body.setHitFraction(1f); if (body.isActive() && (!body.isStaticOrKinematicObject())) { body.predictIntegratedTransform(timeStep, predictedTrans); tmp.sub(predictedTrans.origin, body.getWorldTransform(tmpTrans).origin); float squareMotion = tmp.lengthSquared(); if (body.getCcdSquareMotionThreshold() != 0f && body.getCcdSquareMotionThreshold() < squareMotion) { if (body.getCollisionShape().isConvex()) { ClosestNotMeConvexResultCallback sweepResults = new ClosestNotMeConvexResultCallback( body, body.getWorldTransform(tmpTrans).origin, predictedTrans.origin, getBroadphase().getOverlappingPairCache(), getDispatcher()); // ConvexShape convexShape = (ConvexShape)body.getCollisionShape(); SphereShape tmpSphere = new SphereShape( body .getCcdSweptSphereRadius()); // btConvexShape* convexShape = // static_cast<btConvexShape*>(body->getCollisionShape()); sweepResults.collisionFilterGroup = body.getBroadphaseProxy().collisionFilterGroup; sweepResults.collisionFilterMask = body.getBroadphaseProxy().collisionFilterMask; convexSweepTest( tmpSphere, body.getWorldTransform(tmpTrans), predictedTrans, sweepResults); // JAVA NOTE: added closestHitFraction test to prevent objects being stuck if (sweepResults.hasHit() && (sweepResults.closestHitFraction > 0.0001f)) { body.setHitFraction(sweepResults.closestHitFraction); body.predictIntegratedTransform(timeStep * body.getHitFraction(), predictedTrans); body.setHitFraction(0f); // System.out.printf("clamped integration to hit fraction = %f\n", // sweepResults.closestHitFraction); } } } body.proceedToTransform(predictedTrans); } } } }
@Override public void setGravity(Vector3f gravity) { this.gravity.set(gravity); for (int i = 0; i < collisionObjects.size(); i++) { CollisionObject colObj = collisionObjects.getQuick(i); RigidBody body = RigidBody.upcast(colObj); if (body != null) { body.setGravity(gravity); } } }
/** Apply gravity, call this once per timestep. */ public void applyGravity() { // todo: iterate over awake simulation islands! for (int i = 0; i < collisionObjects.size(); i++) { CollisionObject colObj = collisionObjects.getQuick(i); RigidBody body = RigidBody.upcast(colObj); if (body != null && body.isActive()) { body.applyGravity(); } } }
@Override public void clearForces() { // todo: iterate over awake simulation islands! for (int i = 0; i < collisionObjects.size(); i++) { CollisionObject colObj = collisionObjects.getQuick(i); RigidBody body = RigidBody.upcast(colObj); if (body != null) { body.clearForces(); } } }
protected void saveKinematicState(float timeStep) { for (int i = 0; i < collisionObjects.size(); i++) { CollisionObject colObj = collisionObjects.getQuick(i); RigidBody body = RigidBody.upcast(colObj); if (body != null) { // Transform predictedTrans = new Transform(); if (body.getActivationState() != CollisionObject.ISLAND_SLEEPING) { if (body.isKinematicObject()) { // to calculate velocities next frame body.saveKinematicState(timeStep); } } } } }
protected void predictUnconstraintMotion(float timeStep) { Transform tmpTrans = Stack.alloc(Transform.class); for (int i = 0; i < collisionObjects.size(); i++) { CollisionObject colObj = collisionObjects.getQuick(i); RigidBody body = RigidBody.upcast(colObj); if (body != null) { if (!body.isStaticOrKinematicObject()) { if (body.isActive()) { body.integrateVelocities(timeStep); // damping body.applyDamping(timeStep); body.predictIntegratedTransform( timeStep, body.getInterpolationWorldTransform(tmpTrans)); } } } } }
protected void synchronizeMotionStates() { Transform interpolatedTransform = Stack.alloc(Transform.class); Transform tmpTrans = Stack.alloc(Transform.class); Vector3f tmpLinVel = Stack.alloc(Vector3f.class); Vector3f tmpAngVel = Stack.alloc(Vector3f.class); // todo: iterate over awake simulation islands! for (int i = 0; i < collisionObjects.size(); i++) { CollisionObject colObj = collisionObjects.getQuick(i); RigidBody body = RigidBody.upcast(colObj); if (body != null && body.getMotionState() != null && !body.isStaticOrKinematicObject()) { // we need to call the update at least once, even for sleeping objects // otherwise the 'graphics' transform never updates properly // so todo: add 'dirty' flag // if (body->getActivationState() != ISLAND_SLEEPING) { TransformUtil.integrateTransform( body.getInterpolationWorldTransform(tmpTrans), body.getInterpolationLinearVelocity(tmpLinVel), body.getInterpolationAngularVelocity(tmpAngVel), localTime * body.getHitFraction(), interpolatedTransform); body.getMotionState().setWorldTransform(interpolatedTransform); } } } if (getDebugDrawer() != null && (getDebugDrawer().getDebugMode() & DebugDrawModes.DRAW_WIREFRAME) != 0) { for (int i = 0; i < vehicles.size(); i++) { for (int v = 0; v < vehicles.getQuick(i).getNumWheels(); v++) { // synchronize the wheels with the (interpolated) chassis worldtransform vehicles.getQuick(i).updateWheelTransform(v, true); } } } }