diff --git a/src/main/java/electrosphere/entity/state/GravityTree.java b/src/main/java/electrosphere/entity/state/GravityTree.java index 49c93261..0a619ade 100644 --- a/src/main/java/electrosphere/entity/state/GravityTree.java +++ b/src/main/java/electrosphere/entity/state/GravityTree.java @@ -7,6 +7,7 @@ import electrosphere.entity.state.movement.Impulse; import electrosphere.entity.types.creature.CreatureUtils; import electrosphere.game.collision.PhysicsUtils; import electrosphere.game.collision.collidable.Collidable; +import electrosphere.main.Globals; import electrosphere.net.parser.net.message.EntityMessage; import electrosphere.renderer.Actor; import java.util.concurrent.CopyOnWriteArrayList; @@ -65,7 +66,10 @@ public class GravityTree { state = GravityTreeState.NOT_ACTIVE; } - public void simulate(){ + static final float gravityConstant = 0.3f; + static final float linearDamping = 0.002f; + + public void simulate(float deltaTime){ float velocity = CreatureUtils.getVelocity(parent); float acceleration = CreatureUtils.getAcceleration(parent); float maxNaturalVelocity = CreatureUtils.getMaxNaturalVelocity(parent); @@ -104,7 +108,15 @@ public class GravityTree { if(hadGroundCollision()){ state = GravityTreeState.NOT_ACTIVE; } else { - position.set(new Vector3f(position.x,position.y - 0.08f,position.z)); + float gravityDif = gravityConstant * (float)Math.pow(1.0f - linearDamping,deltaTime); + Vector3f newGravityPos = new Vector3f(position.x,position.y - gravityDif,position.z); + float hitFraction = Globals.collisionEngine.sweepTest(body, position, newGravityPos); + if(hitFraction >= 0){ + position.set(new Vector3f(position.x,position.y - gravityDif * hitFraction,position.z)); + } else { + position.set(new Vector3f(position.x,position.y - gravityDif,position.z)); + } +// System.out.println(hitFraction); bodyTransformMatrix = new javax.vecmath.Matrix4f(PhysicsUtils.jomlToVecmathQuaternionf(rotation),PhysicsUtils.jomlToVecmathVector3f(position),1.0f); body.setWorldTransform(new com.bulletphysics.linearmath.Transform(bodyTransformMatrix)); } diff --git a/src/main/java/electrosphere/game/collision/CollisionEngine.java b/src/main/java/electrosphere/game/collision/CollisionEngine.java index 456a7a68..48b82f99 100644 --- a/src/main/java/electrosphere/game/collision/CollisionEngine.java +++ b/src/main/java/electrosphere/game/collision/CollisionEngine.java @@ -1,15 +1,22 @@ package electrosphere.game.collision; import com.bulletphysics.collision.broadphase.BroadphaseInterface; +import com.bulletphysics.collision.broadphase.BroadphasePair; +import com.bulletphysics.collision.broadphase.BroadphaseProxy; import com.bulletphysics.collision.broadphase.DbvtBroadphase; import com.bulletphysics.collision.broadphase.Dispatcher; +import com.bulletphysics.collision.broadphase.OverlappingPairCache; import com.bulletphysics.collision.dispatch.CollisionDispatcher; import com.bulletphysics.collision.dispatch.CollisionObject; +import com.bulletphysics.collision.dispatch.CollisionWorld.ClosestConvexResultCallback; +import com.bulletphysics.collision.dispatch.CollisionWorld.ConvexResultCallback; +import com.bulletphysics.collision.dispatch.CollisionWorld.LocalConvexResult; import com.bulletphysics.collision.dispatch.DefaultCollisionConfiguration; import com.bulletphysics.collision.narrowphase.ManifoldPoint; import com.bulletphysics.collision.narrowphase.PersistentManifold; import com.bulletphysics.collision.shapes.BoxShape; import com.bulletphysics.collision.shapes.CollisionShape; +import com.bulletphysics.collision.shapes.SphereShape; import com.bulletphysics.dynamics.DiscreteDynamicsWorld; import com.bulletphysics.dynamics.DynamicsWorld; import com.bulletphysics.dynamics.InternalTickCallback; @@ -18,6 +25,7 @@ import com.bulletphysics.dynamics.RigidBodyConstructionInfo; import com.bulletphysics.dynamics.constraintsolver.SequentialImpulseConstraintSolver; import com.bulletphysics.linearmath.DefaultMotionState; import com.bulletphysics.linearmath.Transform; +import com.bulletphysics.util.ObjectArrayList; import electrosphere.entity.Entity; import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityUtils; @@ -25,6 +33,7 @@ import electrosphere.entity.state.movement.Impulse; import electrosphere.entity.types.hitbox.HitboxData; import electrosphere.game.collision.collidable.Collidable; import electrosphere.game.server.world.ServerWorldData; +import static electrosphere.main.Main.deltaTime; import java.util.ArrayList; import java.util.List; import org.joml.Vector3f; @@ -40,6 +49,7 @@ public class CollisionEngine { BroadphaseInterface broadphase; DefaultCollisionConfiguration collisionConfiguration; CollisionDispatcher dispatcher; + InternalTickCallback callback; List collisionEntities = new ArrayList(); List physicsEntities = new ArrayList(); @@ -48,6 +58,8 @@ public class CollisionEngine { List collisionObject = new ArrayList(); List collidableList = new ArrayList(); + static final float linearDamping = 0.2f; + public CollisionEngine(){ broadphase = new DbvtBroadphase(); collisionConfiguration = new DefaultCollisionConfiguration(); @@ -63,7 +75,7 @@ public class CollisionEngine { // // world.addRigidBody(boxRigidBody); - world.setInternalTickCallback(new InternalTickCallback(){ + callback = new InternalTickCallback(){ @Override public void internalTick(DynamicsWorld dw, float f) { Dispatcher dispatcher = dw.getDispatcher(); @@ -82,6 +94,8 @@ public class CollisionEngine { ManifoldPoint contactPoint = manifold.getContactPoint(j); if (contactPoint.getDistance() < 0.0f) { magnitude = contactPoint.getDistance(); + //linear dampen + magnitude = magnitude * (float)Math.pow(1.0f - linearDamping,deltaTime) * deltaTime * 8; hit = true; normal = new Vector3f(contactPoint.normalWorldOnB.x,contactPoint.normalWorldOnB.y,contactPoint.normalWorldOnB.z); break; @@ -95,7 +109,8 @@ public class CollisionEngine { } } } - }, world); + }; + world.setInternalTickCallback(callback, world); //https://pybullet.org/Bullet/phpBB3/viewtopic.php?t=11507 //https://www.google.com/search?client=firefox-b-1-d&q=bullet+set+position+and+check+if+collision @@ -159,7 +174,9 @@ public class CollisionEngine { } public void simulatePhysics(float time){ - world.stepSimulation(time); + world.performDiscreteCollisionDetection(); + callback.internalTick(world, time); +// world.stepSimulation(time); } /** @@ -278,4 +295,103 @@ public class CollisionEngine { return entityHeight > worldHeight + 0.1f; } + public float sweepTest(CollisionObject object, Vector3f startPos, Vector3f endPos){ + SphereShape sphere = new SphereShape(0.1f); +// CollisionObject collider = new CollisionObject(); +// collider.setCollisionShape(sphere); + ClosestConvexResultCallbackImpl callback = new ClosestConvexResultCallbackImpl(startPos,endPos,object,dispatcher,world.getPairCache()); + callback.collisionFilterGroup = 1; + callback.collisionFilterMask = 1; + world.convexSweepTest(sphere, PhysicsUtils.jomlVecToTransform(startPos), PhysicsUtils.jomlVecToTransform(endPos), callback); +// callback.hasHit() + if(callback.hasHit()){ + return callback.closestHitFraction; + } else { + return -1.0f; + } + } + + + + + + +// private static class SpecificConvexResultCallback extends ConvexResultCallback { +// +// @Override +// public float addSingleResult(LocalConvexResult convexResult, boolean bln) { +// } +// +// } + + + private static class ClosestConvexResultCallbackImpl extends ClosestConvexResultCallback { + + CollisionObject me; + private OverlappingPairCache pairCache; + private Dispatcher dispatcher; + + public ClosestConvexResultCallbackImpl(Vector3f startPos, Vector3f endPos, CollisionObject me, Dispatcher dispatcher, OverlappingPairCache pairCache){ + super(PhysicsUtils.jomlToVecmathVector3f(startPos),PhysicsUtils.jomlToVecmathVector3f(endPos)); + this.me = me; + this.pairCache = pairCache; + this.dispatcher = dispatcher; + } + + @Override + public float addSingleResult(LocalConvexResult convexResult, boolean normalInWorldSpace) { + if (convexResult.hitCollisionObject == me) { + return 1f; + } + + Vector3f linVelA = new Vector3f(), linVelB = new Vector3f(); + linVelA.sub(PhysicsUtils.vecmathToJomlVector3f(convexToWorld), PhysicsUtils.vecmathToJomlVector3f(convexFromWorld)); + linVelB.set(0f, 0f, 0f);//toB.getOrigin()-fromB.getOrigin(); + + Vector3f relativeVelocity = new Vector3f(); + relativeVelocity.sub(linVelA, linVelB); + // don't report time of impact for motion away from the contact normal (or causes minor penetration) + if (convexResult.hitNormalLocal.dot(PhysicsUtils.jomlToVecmathVector3f(relativeVelocity)) >= -0f) { + return 1f; + } + + return super.addSingleResult(convexResult, normalInWorldSpace); + } + + @Override + public boolean needsCollision(BroadphaseProxy proxy0) { + // don't collide with itself + if (proxy0.clientObject == me) { + return false; + } + + // don't do CCD when the collision filters are not matching + if (!super.needsCollision(proxy0)) { + return false; + } + + CollisionObject otherObj = (CollisionObject)proxy0.clientObject; + + // call needsResponse, see http://code.google.com/p/bullet/issues/detail?id=179 + if (dispatcher.needsResponse(me, otherObj)) { + // don't do CCD when there are already contact points (touching contact/penetration) + ObjectArrayList manifoldArray = new ObjectArrayList(); + BroadphasePair collisionPair = pairCache.findPair(me.getBroadphaseHandle(), proxy0); + if (collisionPair != null) { + if (collisionPair.algorithm != null) { + //manifoldArray.resize(0); + collisionPair.algorithm.getAllContactManifolds(manifoldArray); + for (int j=0; j 0) { + return false; + } + } + } + } + } + return true; + } + } + } diff --git a/src/main/java/electrosphere/game/collision/PhysicsUtils.java b/src/main/java/electrosphere/game/collision/PhysicsUtils.java index ab3a45d1..2b4460ab 100644 --- a/src/main/java/electrosphere/game/collision/PhysicsUtils.java +++ b/src/main/java/electrosphere/game/collision/PhysicsUtils.java @@ -266,6 +266,18 @@ public class PhysicsUtils { return new javax.vecmath.Quat4f(quaternion.x, quaternion.y, quaternion.z, quaternion.w); } + public static com.bulletphysics.linearmath.Transform jomlVecToTransform(Vector3f vector){ + com.bulletphysics.linearmath.Transform transform = new com.bulletphysics.linearmath.Transform(); + + javax.vecmath.Matrix4f transformMatrix = new javax.vecmath.Matrix4f(); + transformMatrix.setIdentity(); + + transformMatrix.setTranslation(new javax.vecmath.Vector3f(vector.x, vector.y, vector.z)); + transform.set(transformMatrix); + + return transform; + } + public static void setRigidBodyTransform(Vector3f position, Quaternionf rotation, CollisionObject body){ com.bulletphysics.linearmath.Transform transform = new com.bulletphysics.linearmath.Transform(); diff --git a/src/main/java/electrosphere/game/state/MicroSimulation.java b/src/main/java/electrosphere/game/state/MicroSimulation.java index ba95bfd1..f6709a36 100644 --- a/src/main/java/electrosphere/game/state/MicroSimulation.java +++ b/src/main/java/electrosphere/game/state/MicroSimulation.java @@ -61,7 +61,7 @@ public class MicroSimulation { //simulate creature gravity trees for(Entity currentGravity : Globals.entityManager.getGravityEntities()){ GravityTree gravityTree = (GravityTree)currentGravity.getData(EntityDataStrings.GRAVITY_TREE); - gravityTree.simulate(); + gravityTree.simulate(deltaTime); } //attacker behavior tree for(Entity currentAttacker : Globals.entityManager.getAttackerEntities()){