use of org.terasology.physics.components.RigidBodyComponent in project Terasology by MovingBlocks.
the class BulletPhysics method newRigidBody.
private RigidBody newRigidBody(EntityRef entity) {
LocationComponent location = entity.getComponent(LocationComponent.class);
RigidBodyComponent rigidBody = entity.getComponent(RigidBodyComponent.class);
ConvexShape shape = getShapeFor(entity);
if (location != null && rigidBody != null && shape != null) {
float scale = location.getWorldScale();
shape.setLocalScaling(new Vector3f(scale, scale, scale));
if (rigidBody.mass < 1) {
logger.warn("RigidBodyComponent.mass is set to less than 1.0, this can lead to strange behaviour, such as the objects moving through walls. " + "Entity: {}", entity);
}
Vector3f fallInertia = new Vector3f();
shape.calculateLocalInertia(rigidBody.mass, fallInertia);
RigidBodyConstructionInfo info = new RigidBodyConstructionInfo(rigidBody.mass, new EntityMotionState(entity), shape, fallInertia);
BulletRigidBody collider = new BulletRigidBody(info);
collider.rb.setUserPointer(entity);
collider.rb.setAngularFactor(VecMath.to(rigidBody.angularFactor));
collider.rb.setLinearFactor(VecMath.to(rigidBody.linearFactor));
collider.rb.setFriction(rigidBody.friction);
collider.rb.setRestitution(rigidBody.restitution);
collider.collidesWith = combineGroups(rigidBody.collidesWith);
updateKinematicSettings(rigidBody, collider);
BulletRigidBody oldBody = entityRigidBodies.put(entity, collider);
addRigidBody(collider, Lists.<CollisionGroup>newArrayList(rigidBody.collisionGroup), rigidBody.collidesWith);
if (oldBody != null) {
removeRigidBody(oldBody);
}
collider.setVelocity(rigidBody.velocity, rigidBody.angularVelocity);
collider.setTransform(location.getWorldPosition(), location.getWorldRotation());
return collider;
} else {
throw new IllegalArgumentException("Can only create a new rigid body for entities with a LocationComponent," + " RigidBodyComponent and ShapeComponent, this entity misses at least one: " + entity);
}
}
use of org.terasology.physics.components.RigidBodyComponent in project Terasology by MovingBlocks.
the class BulletPhysics method updateRigidBody.
@Override
public boolean updateRigidBody(EntityRef entity) {
LocationComponent location = entity.getComponent(LocationComponent.class);
RigidBodyComponent rb = entity.getComponent(RigidBodyComponent.class);
BulletRigidBody rigidBody = entityRigidBodies.get(entity);
if (location == null) {
logger.warn("Updating rigid body of entity that has no " + "LocationComponent?! Nothing is done, except log this" + " warning instead. Entity: {}", entity);
return false;
} else if (rigidBody != null) {
float scale = location.getWorldScale();
if (Math.abs(rigidBody.rb.getCollisionShape().getLocalScaling(new Vector3f()).x - scale) > BulletGlobals.SIMD_EPSILON || rigidBody.collidesWith != combineGroups(rb.collidesWith)) {
removeRigidBody(rigidBody);
newRigidBody(entity);
} else {
rigidBody.rb.setAngularFactor(VecMath.to(rb.angularFactor));
rigidBody.rb.setLinearFactor(VecMath.to(rb.linearFactor));
rigidBody.rb.setFriction(rb.friction);
}
return true;
} else {
/*
* During the destruction of the entity it can happen that the rigged body is already destroyed while
* the location component changes.
* e.g. because another component that was attached via the LocationComponent gets removed.
*
* In such a situation it would be wrong to recreate the rigid body as it can't be updated properly after
* the destruction of the entity.
*
*/
return false;
}
// TODO: update if mass or collision groups change
}
use of org.terasology.physics.components.RigidBodyComponent in project Terasology by MovingBlocks.
the class PhysicsSystem method update.
@Override
public void update(float delta) {
PerformanceMonitor.startActivity("Physics Renderer");
physics.update(time.getGameDelta());
PerformanceMonitor.endActivity();
// Update the velocity from physics engine bodies to Components:
Iterator<EntityRef> iter = physics.physicsEntitiesIterator();
while (iter.hasNext()) {
EntityRef entity = iter.next();
RigidBodyComponent comp = entity.getComponent(RigidBodyComponent.class);
RigidBody body = physics.getRigidBody(entity);
if (body.isActive()) {
body.getLinearVelocity(comp.velocity);
body.getAngularVelocity(comp.angularVelocity);
Vector3f vLocation = Vector3f.zero();
body.getLocation(vLocation);
Vector3f vDirection = new Vector3f(comp.velocity);
float fDistanceThisFrame = vDirection.length();
vDirection.normalize();
fDistanceThisFrame = fDistanceThisFrame * delta;
while (true) {
HitResult hitInfo = physics.rayTrace(vLocation, vDirection, fDistanceThisFrame + 0.5f, DEFAULT_COLLISION_GROUP);
if (hitInfo.isHit()) {
Block hitBlock = worldProvider.getBlock(hitInfo.getBlockPosition());
if (hitBlock != null) {
Vector3f vTravelledDistance = vLocation.sub(hitInfo.getHitPoint());
float fTravelledDistance = vTravelledDistance.length();
if (fTravelledDistance > fDistanceThisFrame) {
break;
}
if (hitBlock.isPenetrable()) {
if (!hitInfo.getEntity().hasComponent(BlockComponent.class)) {
entity.send(new EntityImpactEvent(hitInfo.getHitPoint(), hitInfo.getHitNormal(), comp.velocity, fDistanceThisFrame, hitInfo.getEntity()));
break;
}
// decrease the remaining distance to check if we hit a block
fDistanceThisFrame = fDistanceThisFrame - fTravelledDistance;
vLocation = hitInfo.getHitPoint();
} else {
entity.send(new BlockImpactEvent(hitInfo.getHitPoint(), hitInfo.getHitNormal(), comp.velocity, fDistanceThisFrame, hitInfo.getEntity()));
break;
}
} else {
break;
}
} else {
break;
}
}
}
}
if (networkSystem.getMode().isServer() && time.getGameTimeInMs() - TIME_BETWEEN_NETSYNCS > lastNetsync) {
sendSyncMessages();
lastNetsync = time.getGameTimeInMs();
}
List<CollisionPair> collisionPairs = physics.getCollisionPairs();
for (CollisionPair pair : collisionPairs) {
if (pair.b.exists()) {
short bCollisionGroup = getCollisionGroupFlag(pair.b);
short aCollidesWith = getCollidesWithGroupFlag(pair.a);
if ((bCollisionGroup & aCollidesWith) != 0 || (pair.b.hasComponent(BlockComponent.class) && !pair.a.hasComponent(BlockComponent.class))) {
pair.a.send(new CollideEvent(pair.b, pair.pointA, pair.pointB, pair.distance, pair.normal));
}
}
if (pair.a.exists()) {
short aCollisionGroup = getCollisionGroupFlag(pair.a);
short bCollidesWith = getCollidesWithGroupFlag(pair.b);
if ((aCollisionGroup & bCollidesWith) != 0 || (pair.a.hasComponent(BlockComponent.class) && !pair.b.hasComponent(BlockComponent.class))) {
pair.b.send(new CollideEvent(pair.a, pair.pointB, pair.pointA, pair.distance, new Vector3f(pair.normal).invert()));
}
}
}
}
use of org.terasology.physics.components.RigidBodyComponent in project Terasology by MovingBlocks.
the class PhysicsSystem method getCollidesWithGroupFlag.
private short getCollidesWithGroupFlag(EntityRef entity) {
List<CollisionGroup> collidesWithGroup = Lists.<CollisionGroup>newArrayList(StandardCollisionGroup.NONE);
if (entity.hasComponent(TriggerComponent.class)) {
TriggerComponent entityTrigger = entity.getComponent(TriggerComponent.class);
collidesWithGroup = entityTrigger.detectGroups;
} else if (entity.hasComponent(RigidBodyComponent.class)) {
RigidBodyComponent entityRigidBody = entity.getComponent(RigidBodyComponent.class);
collidesWithGroup = entityRigidBody.collidesWith;
}
short flag = 0;
Iterator<CollisionGroup> iter = collidesWithGroup.iterator();
while (iter.hasNext()) {
CollisionGroup group = iter.next();
flag |= group.getFlag();
}
return flag;
}
use of org.terasology.physics.components.RigidBodyComponent in project Terasology by MovingBlocks.
the class PhysicsSystem method getCollisionGroupFlag.
private short getCollisionGroupFlag(EntityRef entity) {
CollisionGroup collisionGroup = StandardCollisionGroup.NONE;
if (entity.hasComponent(TriggerComponent.class)) {
TriggerComponent entityTrigger = entity.getComponent(TriggerComponent.class);
collisionGroup = entityTrigger.collisionGroup;
} else if (entity.hasComponent(RigidBodyComponent.class)) {
RigidBodyComponent entityRigidBody = entity.getComponent(RigidBodyComponent.class);
collisionGroup = entityRigidBody.collisionGroup;
}
return collisionGroup.getFlag();
}
Aggregations