mirror of
https://github.com/overte-org/overte.git
synced 2025-04-19 13:43:49 +02:00
initial support for STATIC and KINEMATIC motion
This commit is contained in:
parent
bd34ac4357
commit
2f9a35412f
7 changed files with 147 additions and 24 deletions
|
@ -37,6 +37,13 @@ EntityMotionState::EntityMotionState(EntityItem* entity) : _entity(entity) {
|
|||
EntityMotionState::~EntityMotionState() {
|
||||
}
|
||||
|
||||
MotionType EntityMotionState::getMotionType() const {
|
||||
// HACK: According to EntityTree the meaning of "static" is "not moving" whereas
|
||||
// to Bullet it means "can't move". For demo purposes we temporarily interpret
|
||||
// Entity::weightless to mean Bullet::static.
|
||||
return _entity->hasGravity() ? MOTION_TYPE_DYNAMIC : MOTION_TYPE_STATIC;
|
||||
}
|
||||
|
||||
// This callback is invoked by the physics simulation in two cases:
|
||||
// (1) when the RigidBody is first added to the world
|
||||
// (irregardless of MotionType: STATIC, DYNAMIC, or KINEMATIC)
|
||||
|
|
|
@ -27,6 +27,8 @@ public:
|
|||
EntityMotionState(EntityItem* item);
|
||||
virtual ~EntityMotionState();
|
||||
|
||||
MotionType getMotionType() const;
|
||||
|
||||
void getWorldTransform (btTransform &worldTrans) const;
|
||||
void setWorldTransform (const btTransform &worldTrans);
|
||||
void applyVelocities() const;
|
||||
|
|
|
@ -77,9 +77,9 @@ EntityItem* EntityTree::getOrCreateEntityItem(const EntityItemID& entityID, cons
|
|||
}
|
||||
|
||||
/// Adds a new entity item to the tree
|
||||
void EntityTree::addEntityItem(EntityItem* entityItem) {
|
||||
void EntityTree::addEntityItem(EntityItem* entity) {
|
||||
// You should not call this on existing entities that are already part of the tree! Call updateEntity()
|
||||
EntityItemID entityID = entityItem->getEntityItemID();
|
||||
EntityItemID entityID = entity->getEntityItemID();
|
||||
EntityTreeElement* containingElement = getContainingElement(entityID);
|
||||
if (containingElement) {
|
||||
qDebug() << "UNEXPECTED!!!! don't call addEntityItem() on existing entity items. entityID=" << entityID;
|
||||
|
@ -87,12 +87,15 @@ void EntityTree::addEntityItem(EntityItem* entityItem) {
|
|||
}
|
||||
|
||||
// Recurse the tree and store the entity in the correct tree element
|
||||
AddEntityOperator theOperator(this, entityItem);
|
||||
AddEntityOperator theOperator(this, entity);
|
||||
recurseTreeWithOperator(&theOperator);
|
||||
|
||||
// check to see if we need to simulate this entity..
|
||||
// BOOKMARK -- add entity to physics engine here
|
||||
changeEntityState(entityItem, EntityItem::Static, entityItem->getSimulationState());
|
||||
changeEntityState(entity, EntityItem::Static, entity->getSimulationState());
|
||||
|
||||
if (_physicsWorld && !entity->getMotionState()) {
|
||||
addEntityToPhysicsWorld(entity);
|
||||
}
|
||||
|
||||
_isDirty = true;
|
||||
}
|
||||
|
@ -530,7 +533,7 @@ int EntityTree::processEditPacketData(PacketType packetType, const unsigned char
|
|||
// search for the entity by EntityItemID
|
||||
EntityItem* existingEntity = findEntityByEntityItemID(entityItemID);
|
||||
|
||||
// if the entityItem exists, then update it
|
||||
// if the EntityItem exists, then update it
|
||||
if (existingEntity) {
|
||||
updateEntity(entityItemID, properties);
|
||||
existingEntity->markAsChangedOnServer();
|
||||
|
@ -621,9 +624,6 @@ void EntityTree::changeEntityState(EntityItem* const entity,
|
|||
|
||||
case EntityItem::Moving:
|
||||
_movingEntities.push_back(entity);
|
||||
if (_physicsWorld && !entity->getMotionState()) {
|
||||
addEntityToPhysicsWorld(entity);
|
||||
}
|
||||
break;
|
||||
|
||||
case EntityItem::Mortal:
|
||||
|
@ -683,7 +683,11 @@ void EntityTree::updateChangingEntities(quint64 now, QSet<EntityItemID>& entitie
|
|||
// TODO: switch these to iterators so we can remove items that get deleted
|
||||
for (int i = 0; i < _changingEntities.size(); i++) {
|
||||
EntityItem* thisEntity = _changingEntities[i];
|
||||
thisEntity->update(now);
|
||||
EntityMotionState* motionState = thisEntity->getMotionState();
|
||||
if (!motionState) {
|
||||
thisEntity->update(now);
|
||||
}
|
||||
|
||||
// always check to see if the lifetime has expired, for immortal entities this is always false
|
||||
if (thisEntity->lifetimeHasExpired()) {
|
||||
qDebug() << "Lifetime has expired for entity:" << thisEntity->getEntityItemID();
|
||||
|
|
|
@ -34,7 +34,8 @@ CustomMotionState::CustomMotionState() :
|
|||
_volume(DEFAULT_VOLUME),
|
||||
_friction(DEFAULT_FRICTION),
|
||||
_restitution(DEFAULT_RESTITUTION),
|
||||
_motionType(MOTION_TYPE_STATIC),
|
||||
_wasInWorld(false),
|
||||
_motionType(MOTION_TYPE_STATIC),
|
||||
_body(NULL) {
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ public:
|
|||
|
||||
virtual void computeShapeInfo(ShapeInfo& info) = 0;
|
||||
|
||||
MotionType getMotionType() const { return _motionType; }
|
||||
virtual MotionType getMotionType() const { return _motionType; }
|
||||
|
||||
void setDensity(float density);
|
||||
void setFriction(float friction);
|
||||
|
@ -54,15 +54,16 @@ public:
|
|||
void getAngularVelocity(glm::vec3& angularVelocityOut) const;
|
||||
|
||||
friend class PhysicsWorld;
|
||||
protected:
|
||||
|
||||
protected:
|
||||
float _density;
|
||||
float _volume;
|
||||
float _friction;
|
||||
float _restitution;
|
||||
|
||||
// The data members below have NO setters. They are only changed by a PhysicsWorld instance.
|
||||
bool _wasInWorld;
|
||||
MotionType _motionType;
|
||||
|
||||
// _body has NO setters -- it is only changed by PhysicsWorld
|
||||
btRigidBody* _body;
|
||||
};
|
||||
|
||||
|
|
|
@ -23,6 +23,26 @@ void PhysicsWorld::init() {
|
|||
_broadphaseFilter = new btDbvtBroadphase();
|
||||
_constraintSolver = new btSequentialImpulseConstraintSolver;
|
||||
_dynamicsWorld = new btDiscreteDynamicsWorld(_collisionDispatcher, _broadphaseFilter, _constraintSolver, _collisionConfig);
|
||||
|
||||
// TODO: once the initial physics system is working we will set gravity of the world to be zero
|
||||
// and each object will have to specify its own local gravity, or we'll set up gravity zones.
|
||||
//_dynamicsWorld->setGravity(btVector3(0.0f, 0.0f, 0.0f));
|
||||
//
|
||||
// GROUND HACK: In the meantime we add a big planar floor to catch falling objects
|
||||
// NOTE: we don't care about memory leaking groundShape and groundObject -->
|
||||
// they'll exist until the executable exits.
|
||||
const float halfSide = 200.0f;
|
||||
const float halfHeight = 10.0f;
|
||||
|
||||
btCollisionShape* groundShape = new btBoxShape(btVector3(halfSide, halfHeight, halfSide));
|
||||
btTransform groundTransform;
|
||||
groundTransform.setIdentity();
|
||||
groundTransform.setOrigin(btVector3(halfSide, -halfHeight, halfSide));
|
||||
|
||||
btCollisionObject* groundObject = new btCollisionObject();
|
||||
groundObject->setCollisionShape(groundShape);
|
||||
groundObject->setWorldTransform(groundTransform);
|
||||
_dynamicsWorld->addCollisionObject(groundObject);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,19 +113,103 @@ bool PhysicsWorld::removeVoxel(const glm::vec3& position, float scale) {
|
|||
return false;
|
||||
}
|
||||
|
||||
// Bullet collision flags are as follows:
|
||||
// CF_STATIC_OBJECT= 1,
|
||||
// CF_KINEMATIC_OBJECT= 2,
|
||||
// CF_NO_CONTACT_RESPONSE = 4,
|
||||
// CF_CUSTOM_MATERIAL_CALLBACK = 8,//this allows per-triangle material (friction/restitution)
|
||||
// CF_CHARACTER_OBJECT = 16,
|
||||
// CF_DISABLE_VISUALIZE_OBJECT = 32, //disable debug drawing
|
||||
// CF_DISABLE_SPU_COLLISION_PROCESSING = 64//disable parallel/SPU processing
|
||||
|
||||
bool PhysicsWorld::addEntity(CustomMotionState* motionState) {
|
||||
assert(motionState);
|
||||
ShapeInfo info;
|
||||
motionState->computeShapeInfo(info);
|
||||
btCollisionShape* shape = _shapeManager.getShape(info);
|
||||
if (shape) {
|
||||
btVector3 inertia;
|
||||
float mass = motionState->getMass();
|
||||
shape->calculateLocalInertia(mass, inertia);
|
||||
btRigidBody* body = new btRigidBody(mass, motionState, shape, inertia);
|
||||
motionState->_body = body;
|
||||
motionState->applyVelocities();
|
||||
// TODO: set dynamic/kinematic/static property from data stored in motionState
|
||||
btVector3 inertia(0.0f, 0.0f, 0.0f);
|
||||
float mass = 0.0f;
|
||||
btRigidBody* body = NULL;
|
||||
switch(motionState->_motionType) {
|
||||
case MOTION_TYPE_KINEMATIC: {
|
||||
body = new btRigidBody(mass, motionState, shape, inertia);
|
||||
body->setCollisionFlags(btCollisionObject::CF_KINEMATIC_OBJECT);
|
||||
body->setActivationState(DISABLE_DEACTIVATION);
|
||||
body->updateInertiaTensor();
|
||||
motionState->_body = body;
|
||||
break;
|
||||
}
|
||||
case MOTION_TYPE_DYNAMIC: {
|
||||
mass = motionState->getMass();
|
||||
shape->calculateLocalInertia(mass, inertia);
|
||||
body = new btRigidBody(mass, motionState, shape, inertia);
|
||||
body->updateInertiaTensor();
|
||||
motionState->_body = body;
|
||||
motionState->applyVelocities();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// MOTION_TYPE_STATIC
|
||||
body = new btRigidBody(mass, motionState, shape, inertia);
|
||||
body->setCollisionFlags(btCollisionObject::CF_STATIC_OBJECT);
|
||||
body->updateInertiaTensor();
|
||||
motionState->_body = body;
|
||||
break;
|
||||
}
|
||||
}
|
||||
body->setRestitution(motionState->_restitution);
|
||||
body->setFriction(motionState->_friction);
|
||||
_dynamicsWorld->addRigidBody(body);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PhysicsWorld::updateEntityMotionType(CustomMotionState* motionState) {
|
||||
btRigidBody* body = motionState->_body;
|
||||
if (!body) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MotionType oldType = MOTION_TYPE_DYNAMIC;
|
||||
if (body->isStaticObject()) {
|
||||
oldType = MOTION_TYPE_STATIC;
|
||||
} else if (body->isKinematicObject()) {
|
||||
oldType = MOTION_TYPE_KINEMATIC;
|
||||
}
|
||||
MotionType newType = motionState->getMotionType();
|
||||
if (oldType != newType) {
|
||||
// pull body out of physics engine
|
||||
_dynamicsWorld->removeRigidBody(body);
|
||||
|
||||
// update various properties and flags
|
||||
switch (newType) {
|
||||
case MOTION_TYPE_KINEMATIC: {
|
||||
body->setCollisionFlags(btCollisionObject::CF_KINEMATIC_OBJECT);
|
||||
body->setActivationState(DISABLE_DEACTIVATION);
|
||||
body->updateInertiaTensor();
|
||||
break;
|
||||
}
|
||||
case MOTION_TYPE_DYNAMIC: {
|
||||
btVector3 inertia(0.0f, 0.0f, 0.0f);
|
||||
float mass = motionState->getMass();
|
||||
body->getCollisionShape()->calculateLocalInertia(mass, inertia);
|
||||
body->updateInertiaTensor();
|
||||
motionState->applyVelocities();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// MOTION_TYPE_STATIC
|
||||
body->setCollisionFlags(btCollisionObject::CF_STATIC_OBJECT);
|
||||
body->updateInertiaTensor();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// reinsert body into physics engine
|
||||
body->setRestitution(motionState->_restitution);
|
||||
body->setFriction(motionState->_friction);
|
||||
_dynamicsWorld->addRigidBody(body);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -59,11 +59,15 @@ public:
|
|||
/// \return true if Voxel removed
|
||||
bool removeVoxel(const glm::vec3& position, float scale);
|
||||
|
||||
/// \param info information about collision shapes to create
|
||||
/// \param motionState pointer to Entity's MotionState
|
||||
/// \return true if Entity added
|
||||
bool addEntity(CustomMotionState* motionState);
|
||||
|
||||
/// \param id UUID of the entity
|
||||
/// \param motionState pointer to Entity's MotionState
|
||||
/// \return true if entity updated
|
||||
bool updateEntityMotionType(CustomMotionState* motionState);
|
||||
|
||||
/// \param motionState pointer to Entity's MotionState
|
||||
/// \return true if Entity removed
|
||||
bool removeEntity(CustomMotionState* motionState);
|
||||
|
||||
|
|
Loading…
Reference in a new issue