Search in sources :

Example 1 with RigidBodyComponent

use of org.terasology.engine.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);
    btCollisionShape 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 inertia = new Vector3f();
        shape.calculateLocalInertia(rigidBody.mass, inertia);
        btRigidBody.btRigidBodyConstructionInfo info = new btRigidBody.btRigidBodyConstructionInfo(rigidBody.mass, new EntityMotionState(entity), shape, inertia);
        BulletRigidBody collider = new BulletRigidBody(info);
        collider.rb.userData = entity;
        collider.rb.setAngularFactor(rigidBody.angularFactor);
        collider.rb.setLinearFactor(rigidBody.linearFactor);
        collider.rb.setFriction(rigidBody.friction);
        collider.collidesWith = combineGroups(rigidBody.collidesWith);
        collider.setVelocity(rigidBody.velocity, rigidBody.angularVelocity);
        collider.setTransform(location.getWorldPosition(new Vector3f()), location.getWorldRotation(new Quaternionf()));
        updateKinematicSettings(rigidBody, collider);
        BulletRigidBody oldBody = entityRigidBodies.put(entity, collider);
        addRigidBody(collider, Lists.newArrayList(rigidBody.collisionGroup), rigidBody.collidesWith);
        if (oldBody != null) {
            removeRigidBody(oldBody);
        }
        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);
    }
}
Also used : com.badlogic.gdx.physics.bullet.dynamics.btRigidBody(com.badlogic.gdx.physics.bullet.dynamics.btRigidBody) RigidBodyComponent(org.terasology.engine.physics.components.RigidBodyComponent) Vector3f(org.joml.Vector3f) Quaternionf(org.joml.Quaternionf) LocationComponent(org.terasology.engine.logic.location.LocationComponent) com.badlogic.gdx.physics.bullet.collision.btCollisionShape(com.badlogic.gdx.physics.bullet.collision.btCollisionShape)

Example 2 with RigidBodyComponent

use of org.terasology.engine.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().x - scale) > this.getEpsilon() || rigidBody.collidesWith != combineGroups(rb.collidesWith)) {
            removeRigidBody(rigidBody);
            newRigidBody(entity);
        } else {
            rigidBody.rb.setAngularFactor(rb.angularFactor);
            rigidBody.rb.setLinearFactor(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
}
Also used : RigidBodyComponent(org.terasology.engine.physics.components.RigidBodyComponent) LocationComponent(org.terasology.engine.logic.location.LocationComponent)

Example 3 with RigidBodyComponent

use of org.terasology.engine.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);
        // force location component to update and sync trigger state
        if (entity.hasComponent(TriggerComponent.class)) {
            physics.updateTrigger(entity);
        }
        if (body.isActive()) {
            body.getLinearVelocity(comp.velocity);
            body.getAngularVelocity(comp.angularVelocity);
            Vector3f vLocation = body.getLocation(new Vector3f());
            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).mul(-1.0f)));
            }
        }
    }
}
Also used : RigidBodyComponent(org.terasology.engine.physics.components.RigidBodyComponent) HitResult(org.terasology.engine.physics.HitResult) BlockComponent(org.terasology.engine.world.block.BlockComponent) CollideEvent(org.terasology.engine.physics.events.CollideEvent) Vector3f(org.joml.Vector3f) BlockImpactEvent(org.terasology.engine.physics.events.BlockImpactEvent) OnChangedBlock(org.terasology.engine.world.OnChangedBlock) Block(org.terasology.engine.world.block.Block) EntityImpactEvent(org.terasology.engine.physics.events.EntityImpactEvent) EntityRef(org.terasology.engine.entitySystem.entity.EntityRef)

Example 4 with RigidBodyComponent

use of org.terasology.engine.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();
}
Also used : RigidBodyComponent(org.terasology.engine.physics.components.RigidBodyComponent) StandardCollisionGroup(org.terasology.engine.physics.StandardCollisionGroup) CollisionGroup(org.terasology.engine.physics.CollisionGroup) TriggerComponent(org.terasology.engine.physics.components.TriggerComponent)

Example 5 with RigidBodyComponent

use of org.terasology.engine.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;
}
Also used : RigidBodyComponent(org.terasology.engine.physics.components.RigidBodyComponent) StandardCollisionGroup(org.terasology.engine.physics.StandardCollisionGroup) CollisionGroup(org.terasology.engine.physics.CollisionGroup) TriggerComponent(org.terasology.engine.physics.components.TriggerComponent)

Aggregations

RigidBodyComponent (org.terasology.engine.physics.components.RigidBodyComponent)5 Vector3f (org.joml.Vector3f)2 LocationComponent (org.terasology.engine.logic.location.LocationComponent)2 CollisionGroup (org.terasology.engine.physics.CollisionGroup)2 StandardCollisionGroup (org.terasology.engine.physics.StandardCollisionGroup)2 TriggerComponent (org.terasology.engine.physics.components.TriggerComponent)2 com.badlogic.gdx.physics.bullet.collision.btCollisionShape (com.badlogic.gdx.physics.bullet.collision.btCollisionShape)1 com.badlogic.gdx.physics.bullet.dynamics.btRigidBody (com.badlogic.gdx.physics.bullet.dynamics.btRigidBody)1 Quaternionf (org.joml.Quaternionf)1 EntityRef (org.terasology.engine.entitySystem.entity.EntityRef)1 HitResult (org.terasology.engine.physics.HitResult)1 BlockImpactEvent (org.terasology.engine.physics.events.BlockImpactEvent)1 CollideEvent (org.terasology.engine.physics.events.CollideEvent)1 EntityImpactEvent (org.terasology.engine.physics.events.EntityImpactEvent)1 OnChangedBlock (org.terasology.engine.world.OnChangedBlock)1 Block (org.terasology.engine.world.block.Block)1 BlockComponent (org.terasology.engine.world.block.BlockComponent)1