mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-07-23 12:24:29 +02:00
route more entity updates into physics engine
This commit is contained in:
parent
eda779b434
commit
ec1f11c1a8
13 changed files with 290 additions and 147 deletions
|
@ -50,7 +50,9 @@ void EntityCollisionSystem::update() {
|
||||||
if (_entities->tryLockForRead()) {
|
if (_entities->tryLockForRead()) {
|
||||||
QList<EntityItem*>& movingEntities = _entities->getMovingEntities();
|
QList<EntityItem*>& movingEntities = _entities->getMovingEntities();
|
||||||
foreach (EntityItem* entity, movingEntities) {
|
foreach (EntityItem* entity, movingEntities) {
|
||||||
checkEntity(entity);
|
if (!entity->getMotionState()) {
|
||||||
|
checkEntity(entity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_entities->unlock();
|
_entities->unlock();
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,9 +91,7 @@ EntityItem::EntityItem(const EntityItemID& entityItemID) {
|
||||||
_lastEditedFromRemoteInRemoteTime = 0;
|
_lastEditedFromRemoteInRemoteTime = 0;
|
||||||
_lastUpdated = 0;
|
_lastUpdated = 0;
|
||||||
_created = 0;
|
_created = 0;
|
||||||
#ifdef USE_BULLET_PHYSICS
|
|
||||||
_motionState = NULL;
|
_motionState = NULL;
|
||||||
#endif // USE_BULLET_PHYSICS
|
|
||||||
_updateFlags = 0;
|
_updateFlags = 0;
|
||||||
_changedOnServer = 0;
|
_changedOnServer = 0;
|
||||||
initFromEntityItemID(entityItemID);
|
initFromEntityItemID(entityItemID);
|
||||||
|
@ -107,9 +105,7 @@ EntityItem::EntityItem(const EntityItemID& entityItemID, const EntityItemPropert
|
||||||
_lastEditedFromRemoteInRemoteTime = 0;
|
_lastEditedFromRemoteInRemoteTime = 0;
|
||||||
_lastUpdated = 0;
|
_lastUpdated = 0;
|
||||||
_created = properties.getCreated();
|
_created = properties.getCreated();
|
||||||
#ifdef USE_BULLET_PHYSICS
|
|
||||||
_motionState = NULL;
|
_motionState = NULL;
|
||||||
#endif // USE_BULLET_PHYSICS
|
|
||||||
_updateFlags = 0;
|
_updateFlags = 0;
|
||||||
_changedOnServer = 0;
|
_changedOnServer = 0;
|
||||||
initFromEntityItemID(entityItemID);
|
initFromEntityItemID(entityItemID);
|
||||||
|
@ -118,11 +114,9 @@ EntityItem::EntityItem(const EntityItemID& entityItemID, const EntityItemPropert
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityItem::~EntityItem() {
|
EntityItem::~EntityItem() {
|
||||||
#ifdef USE_BULLET_PHYSICS
|
|
||||||
// Make sure the EntityItem has been removed from the physics engine AND
|
// Make sure the EntityItem has been removed from the physics engine AND
|
||||||
// that its _motionState has been destroyed BEFORE you get here.
|
// that its _motionState has been destroyed BEFORE you get here.
|
||||||
assert(_motionState == NULL);
|
assert(_motionState == NULL);
|
||||||
#endif // USE_BULLET_PHYSICS
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
|
EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
|
||||||
|
@ -519,7 +513,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
||||||
READ_ENTITY_PROPERTY_SETTER(PROP_GRAVITY, glm::vec3, updateGravity);
|
READ_ENTITY_PROPERTY_SETTER(PROP_GRAVITY, glm::vec3, updateGravity);
|
||||||
READ_ENTITY_PROPERTY(PROP_DAMPING, float, _damping);
|
READ_ENTITY_PROPERTY(PROP_DAMPING, float, _damping);
|
||||||
READ_ENTITY_PROPERTY_SETTER(PROP_LIFETIME, float, updateLifetime);
|
READ_ENTITY_PROPERTY_SETTER(PROP_LIFETIME, float, updateLifetime);
|
||||||
READ_ENTITY_PROPERTY_STRING(PROP_SCRIPT,setScript);
|
READ_ENTITY_PROPERTY_STRING(PROP_SCRIPT, updateScript);
|
||||||
READ_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, glm::vec3, _registrationPoint);
|
READ_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, glm::vec3, _registrationPoint);
|
||||||
READ_ENTITY_PROPERTY_SETTER(PROP_ANGULAR_VELOCITY, glm::vec3, updateAngularVelocity);
|
READ_ENTITY_PROPERTY_SETTER(PROP_ANGULAR_VELOCITY, glm::vec3, updateAngularVelocity);
|
||||||
READ_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, float, _angularDamping);
|
READ_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, float, _angularDamping);
|
||||||
|
@ -797,23 +791,23 @@ bool EntityItem::setProperties(const EntityItemProperties& properties, bool forc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(position, setPositionInMeters); // this will call recalculate collision shape if needed
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(position, updatePositionInMeters); // this will call recalculate collision shape if needed
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(dimensions, setDimensionsInMeters); // NOTE: radius is obsolete
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(dimensions, updateDimensionsInMeters); // NOTE: radius is obsolete
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(rotation, setRotation);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(rotation, updateRotation);
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(mass, setMass);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(mass, updateMass);
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(velocity, setVelocityInMeters);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(velocity, updateVelocityInMeters);
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(gravity, setGravityInMeters);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(gravity, updateGravityInMeters);
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(damping, setDamping);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(damping, setDamping);
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(lifetime, setLifetime);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(lifetime, updateLifetime);
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(script, setScript);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(script, updateScript);
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(registrationPoint, setRegistrationPoint);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(registrationPoint, setRegistrationPoint);
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(angularVelocity, setAngularVelocity);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(angularVelocity, updateAngularVelocity);
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(angularDamping, setAngularDamping);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(angularDamping, setAngularDamping);
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(glowLevel, setGlowLevel);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(glowLevel, setGlowLevel);
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(localRenderAlpha, setLocalRenderAlpha);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(localRenderAlpha, setLocalRenderAlpha);
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(visible, setVisible);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(visible, setVisible);
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(ignoreForCollisions, setIgnoreForCollisions);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(ignoreForCollisions, updateIgnoreForCollisions);
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(collisionsWillMove, setCollisionsWillMove);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(collisionsWillMove, updateCollisionsWillMove);
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(locked, setLocked);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(locked, setLocked);
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(userData, setUserData);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(userData, setUserData);
|
||||||
|
|
||||||
|
@ -985,7 +979,7 @@ void EntityItem::updateDimensions(const glm::vec3& value) {
|
||||||
if (_dimensions != value) {
|
if (_dimensions != value) {
|
||||||
_dimensions = value;
|
_dimensions = value;
|
||||||
recalculateCollisionShape();
|
recalculateCollisionShape();
|
||||||
_updateFlags |= EntityItem::UPDATE_SHAPE;
|
_updateFlags |= (EntityItem::UPDATE_SHAPE | EntityItem::UPDATE_MASS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -994,7 +988,7 @@ void EntityItem::updateDimensionsInMeters(const glm::vec3& value) {
|
||||||
if (_dimensions != dimensions) {
|
if (_dimensions != dimensions) {
|
||||||
_dimensions = dimensions;
|
_dimensions = dimensions;
|
||||||
recalculateCollisionShape();
|
recalculateCollisionShape();
|
||||||
_updateFlags |= EntityItem::UPDATE_SHAPE;
|
_updateFlags |= (EntityItem::UPDATE_SHAPE | EntityItem::UPDATE_MASS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1031,7 +1025,7 @@ void EntityItem::updateVelocityInMeters(const glm::vec3& value) {
|
||||||
void EntityItem::updateGravity(const glm::vec3& value) {
|
void EntityItem::updateGravity(const glm::vec3& value) {
|
||||||
if (_gravity != value) {
|
if (_gravity != value) {
|
||||||
_gravity = value;
|
_gravity = value;
|
||||||
_updateFlags |= EntityItem::UPDATE_VELOCITY;
|
_updateFlags |= EntityItem::UPDATE_GRAVITY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1039,7 +1033,7 @@ void EntityItem::updateGravityInMeters(const glm::vec3& value) {
|
||||||
glm::vec3 gravity = value / (float) TREE_SCALE;
|
glm::vec3 gravity = value / (float) TREE_SCALE;
|
||||||
if (_gravity != gravity) {
|
if (_gravity != gravity) {
|
||||||
_gravity = gravity;
|
_gravity = gravity;
|
||||||
_updateFlags |= EntityItem::UPDATE_VELOCITY;
|
_updateFlags |= EntityItem::UPDATE_GRAVITY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1071,12 +1065,17 @@ void EntityItem::updateLifetime(float value) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_BULLET_PHYSICS
|
void EntityItem::updateScript(const QString& value) {
|
||||||
|
if (_script != value) {
|
||||||
|
_script = value;
|
||||||
|
_updateFlags |= EntityItem::UPDATE_SCRIPT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void EntityItem::destroyMotionState() {
|
void EntityItem::destroyMotionState() {
|
||||||
if (_motionState) {
|
if (_motionState) {
|
||||||
delete _motionState;
|
delete _motionState;
|
||||||
_motionState = NULL;
|
_motionState = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // USE_BULLET_PHYSICS
|
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include <Octree.h> // for EncodeBitstreamParams class
|
#include <Octree.h> // for EncodeBitstreamParams class
|
||||||
#include <OctreeElement.h> // for OctreeElement::AppendState
|
#include <OctreeElement.h> // for OctreeElement::AppendState
|
||||||
#include <OctreePacketData.h>
|
#include <OctreePacketData.h>
|
||||||
|
#include <PhysicsEngine.h>
|
||||||
#include <VoxelDetail.h>
|
#include <VoxelDetail.h>
|
||||||
|
|
||||||
#include "EntityItemID.h"
|
#include "EntityItemID.h"
|
||||||
|
@ -35,9 +36,7 @@ class EntityTreeElementExtraEncodeData;
|
||||||
#define DONT_ALLOW_INSTANTIATION virtual void pureVirtualFunctionPlaceHolder() = 0;
|
#define DONT_ALLOW_INSTANTIATION virtual void pureVirtualFunctionPlaceHolder() = 0;
|
||||||
#define ALLOW_INSTANTIATION virtual void pureVirtualFunctionPlaceHolder() { };
|
#define ALLOW_INSTANTIATION virtual void pureVirtualFunctionPlaceHolder() { };
|
||||||
|
|
||||||
#ifdef USE_BULLET_PHYSICS
|
|
||||||
class EntityMotionState;
|
class EntityMotionState;
|
||||||
#endif // USE_BULLET_PHYSICS
|
|
||||||
|
|
||||||
/// EntityItem class this is the base class for all entity types. It handles the basic properties and functionality available
|
/// EntityItem class this is the base class for all entity types. It handles the basic properties and functionality available
|
||||||
/// to all other entity types. In particular: postion, size, rotation, age, lifetime, velocity, gravity. You can not instantiate
|
/// to all other entity types. In particular: postion, size, rotation, age, lifetime, velocity, gravity. You can not instantiate
|
||||||
|
@ -46,14 +45,21 @@ class EntityItem {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum EntityUpdateFlags {
|
enum EntityUpdateFlags {
|
||||||
UPDATE_POSITION = 0x0001,
|
// flags for things that need to be relayed to physics engine
|
||||||
UPDATE_VELOCITY = 0x0002,
|
UPDATE_POSITION = PHYSICS_UPDATE_POSITION, //0x0001,
|
||||||
UPDATE_MASS = 0x0004,
|
UPDATE_VELOCITY = PHYSICS_UPDATE_VELOCITY, //0x0002,
|
||||||
UPDATE_COLLISION_GROUP = 0x0008,
|
UPDATE_GRAVITY = PHYSICS_UPDATE_GRAVITY, //0x0004,
|
||||||
UPDATE_MOTION_TYPE = 0x0010,
|
UPDATE_MASS = PHYSICS_UPDATE_MASS, //0x0008,
|
||||||
UPDATE_SHAPE = 0x0020,
|
UPDATE_COLLISION_GROUP = PHYSICS_UPDATE_COLLISION_GROUP, //0x0010,
|
||||||
UPDATE_LIFETIME = 0x0040
|
UPDATE_MOTION_TYPE = PHYSICS_UPDATE_MOTION_TYPE, //0x0020,
|
||||||
//UPDATE_APPEARANCE = 0x8000,
|
UPDATE_SHAPE = PHYSICS_UPDATE_SHAPE, //0x0040,
|
||||||
|
//...
|
||||||
|
// add new flags here in the middle
|
||||||
|
//...
|
||||||
|
// non-physics stuff
|
||||||
|
UPDATE_SCRIPT = 0x2000,
|
||||||
|
UPDATE_LIFETIME = 0x4000,
|
||||||
|
UPDATE_APPEARANCE = 0x8000
|
||||||
};
|
};
|
||||||
|
|
||||||
DONT_ALLOW_INSTANTIATION // This class can not be instantiated directly
|
DONT_ALLOW_INSTANTIATION // This class can not be instantiated directly
|
||||||
|
@ -292,19 +298,18 @@ public:
|
||||||
void updateIgnoreForCollisions(bool value);
|
void updateIgnoreForCollisions(bool value);
|
||||||
void updateCollisionsWillMove(bool value);
|
void updateCollisionsWillMove(bool value);
|
||||||
void updateLifetime(float value);
|
void updateLifetime(float value);
|
||||||
|
void updateScript(const QString& value);
|
||||||
|
|
||||||
uint32_t getUpdateFlags() const { return _updateFlags; }
|
uint32_t getUpdateFlags() const { return _updateFlags; }
|
||||||
void clearUpdateFlags() { _updateFlags = 0; }
|
|
||||||
|
|
||||||
#ifdef USE_BULLET_PHYSICS
|
|
||||||
EntityMotionState* getMotionState() const { return _motionState; }
|
EntityMotionState* getMotionState() const { return _motionState; }
|
||||||
virtual EntityMotionState* createMotionState() { return NULL; }
|
virtual EntityMotionState* createMotionState() { return NULL; }
|
||||||
void destroyMotionState();
|
void destroyMotionState();
|
||||||
#endif // USE_BULLET_PHYSICS
|
|
||||||
SimulationState getSimulationState() const { return _simulationState; }
|
SimulationState getSimulationState() const { return _simulationState; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class EntityTree;
|
friend class EntityTree;
|
||||||
|
void clearUpdateFlags() { _updateFlags = 0; }
|
||||||
void setSimulationState(SimulationState state) { _simulationState = state; }
|
void setSimulationState(SimulationState state) { _simulationState = state; }
|
||||||
|
|
||||||
virtual void initFromEntityItemID(const EntityItemID& entityItemID); // maybe useful to allow subclasses to init
|
virtual void initFromEntityItemID(const EntityItemID& entityItemID); // maybe useful to allow subclasses to init
|
||||||
|
@ -348,9 +353,7 @@ protected:
|
||||||
void setRadius(float value);
|
void setRadius(float value);
|
||||||
|
|
||||||
AACubeShape _collisionShape;
|
AACubeShape _collisionShape;
|
||||||
#ifdef USE_BULLET_PHYSICS
|
|
||||||
EntityMotionState* _motionState;
|
EntityMotionState* _motionState;
|
||||||
#endif // USE_BULLET_PHYSICS
|
|
||||||
SimulationState _simulationState; // only set by EntityTree
|
SimulationState _simulationState; // only set by EntityTree
|
||||||
|
|
||||||
// UpdateFlags are set whenever a property changes that requires the change to be communicated to other
|
// UpdateFlags are set whenever a property changes that requires the change to be communicated to other
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
#ifdef USE_BULLET_PHYSICS
|
#ifdef USE_BULLET_PHYSICS
|
||||||
#include <BulletUtil.h>
|
#include <BulletUtil.h>
|
||||||
|
#endif // USE_BULLET_PHYSICS
|
||||||
|
|
||||||
#include "EntityItem.h"
|
#include "EntityItem.h"
|
||||||
#include "EntityMotionState.h"
|
#include "EntityMotionState.h"
|
||||||
|
@ -41,9 +42,10 @@ MotionType EntityMotionState::getMotionType() const {
|
||||||
// HACK: According to EntityTree the meaning of "static" is "not moving" whereas
|
// 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
|
// to Bullet it means "can't move". For demo purposes we temporarily interpret
|
||||||
// Entity::weightless to mean Bullet::static.
|
// Entity::weightless to mean Bullet::static.
|
||||||
return _entity->hasGravity() ? MOTION_TYPE_DYNAMIC : MOTION_TYPE_STATIC;
|
return _entity->getCollisionsWillMove() ? MOTION_TYPE_DYNAMIC : MOTION_TYPE_STATIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_BULLET_PHYSICS
|
||||||
// This callback is invoked by the physics simulation in two cases:
|
// This callback is invoked by the physics simulation in two cases:
|
||||||
// (1) when the RigidBody is first added to the world
|
// (1) when the RigidBody is first added to the world
|
||||||
// (irregardless of MotionType: STATIC, DYNAMIC, or KINEMATIC)
|
// (irregardless of MotionType: STATIC, DYNAMIC, or KINEMATIC)
|
||||||
|
@ -64,34 +66,54 @@ void EntityMotionState::getWorldTransform (btTransform &worldTrans) const {
|
||||||
// This callback is invoked by the physics simulation at the end of each simulation frame...
|
// This callback is invoked by the physics simulation at the end of each simulation frame...
|
||||||
// iff the corresponding RigidBody is DYNAMIC and has moved.
|
// iff the corresponding RigidBody is DYNAMIC and has moved.
|
||||||
void EntityMotionState::setWorldTransform (const btTransform &worldTrans) {
|
void EntityMotionState::setWorldTransform (const btTransform &worldTrans) {
|
||||||
glm::vec3 pos;
|
uint32_t updateFlags = _entity->getUpdateFlags();
|
||||||
bulletToGLM(worldTrans.getOrigin(), pos);
|
if (! (updateFlags & PHYSICS_UPDATE_POSITION)) {
|
||||||
_entity->setPositionInMeters(pos + _cachedWorldOffset);
|
glm::vec3 pos;
|
||||||
|
bulletToGLM(worldTrans.getOrigin(), pos);
|
||||||
|
_entity->setPositionInMeters(pos + _cachedWorldOffset);
|
||||||
|
|
||||||
glm::quat rot;
|
glm::quat rot;
|
||||||
bulletToGLM(worldTrans.getRotation(), rot);
|
bulletToGLM(worldTrans.getRotation(), rot);
|
||||||
_entity->setRotation(rot);
|
_entity->setRotation(rot);
|
||||||
|
}
|
||||||
|
|
||||||
glm::vec3 v;
|
if (! (updateFlags & PHYSICS_UPDATE_VELOCITY)) {
|
||||||
getVelocity(v);
|
glm::vec3 v;
|
||||||
_entity->setVelocityInMeters(v);
|
getVelocity(v);
|
||||||
getAngularVelocity(v);
|
_entity->setVelocityInMeters(v);
|
||||||
_entity->setAngularVelocity(v);
|
getAngularVelocity(v);
|
||||||
|
_entity->setAngularVelocity(v);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#endif // USE_BULLET_PHYSICS
|
||||||
|
|
||||||
void EntityMotionState::applyVelocities() const {
|
void EntityMotionState::applyVelocities() const {
|
||||||
|
#ifdef USE_BULLET_PHYSICS
|
||||||
if (_body) {
|
if (_body) {
|
||||||
setVelocity(_entity->getVelocityInMeters());
|
setVelocity(_entity->getVelocityInMeters());
|
||||||
setAngularVelocity(_entity->getAngularVelocity());
|
setAngularVelocity(_entity->getAngularVelocity());
|
||||||
|
_body->setActivationState(ACTIVE_TAG);
|
||||||
}
|
}
|
||||||
|
#endif // USE_BULLET_PHYSICS
|
||||||
|
}
|
||||||
|
|
||||||
|
void EntityMotionState::applyGravity() const {
|
||||||
|
#ifdef USE_BULLET_PHYSICS
|
||||||
|
if (_body) {
|
||||||
|
setGravity(_entity->getGravityInMeters());
|
||||||
|
_body->setActivationState(ACTIVE_TAG);
|
||||||
|
}
|
||||||
|
#endif // USE_BULLET_PHYSICS
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityMotionState::computeShapeInfo(ShapeInfo& info) {
|
void EntityMotionState::computeShapeInfo(ShapeInfo& info) {
|
||||||
|
#ifdef USE_BULLET_PHYSICS
|
||||||
// HACK: for now we make everything a box.
|
// HACK: for now we make everything a box.
|
||||||
glm::vec3 halfExtents = _entity->getDimensionsInMeters();
|
glm::vec3 halfExtents = 0.5f * _entity->getDimensionsInMeters();
|
||||||
btVector3 bulletHalfExtents;
|
btVector3 bulletHalfExtents;
|
||||||
glmToBullet(halfExtents, bulletHalfExtents);
|
glmToBullet(halfExtents, bulletHalfExtents);
|
||||||
info.setBox(bulletHalfExtents);
|
info.setBox(bulletHalfExtents);
|
||||||
|
#endif // USE_BULLET_PHYSICS
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityMotionState::getBoundingCubes(AACube& oldCube, AACube& newCube) {
|
void EntityMotionState::getBoundingCubes(AACube& oldCube, AACube& newCube) {
|
||||||
|
@ -100,4 +122,3 @@ void EntityMotionState::getBoundingCubes(AACube& oldCube, AACube& newCube) {
|
||||||
_oldBoundingCube = newCube;
|
_oldBoundingCube = newCube;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // USE_BULLET_PHYSICS
|
|
||||||
|
|
|
@ -12,10 +12,16 @@
|
||||||
#ifndef hifi_EntityMotionState_h
|
#ifndef hifi_EntityMotionState_h
|
||||||
#define hifi_EntityMotionState_h
|
#define hifi_EntityMotionState_h
|
||||||
|
|
||||||
#ifdef USE_BULLET_PHYSICS
|
|
||||||
|
|
||||||
#include <AACube.h>
|
#include <AACube.h>
|
||||||
|
#ifdef USE_BULLET_PHYSICS
|
||||||
#include <CustomMotionState.h>
|
#include <CustomMotionState.h>
|
||||||
|
#else // USE_BULLET_PHYSICS
|
||||||
|
// CustomMotionState stubbery
|
||||||
|
class CustomMotionState {
|
||||||
|
public:
|
||||||
|
bool _foo;
|
||||||
|
};
|
||||||
|
#endif // USE_BULLET_PHYSICS
|
||||||
|
|
||||||
class EntityItem;
|
class EntityItem;
|
||||||
|
|
||||||
|
@ -29,9 +35,12 @@ public:
|
||||||
|
|
||||||
MotionType getMotionType() const;
|
MotionType getMotionType() const;
|
||||||
|
|
||||||
|
#ifdef USE_BULLET_PHYSICS
|
||||||
void getWorldTransform (btTransform &worldTrans) const;
|
void getWorldTransform (btTransform &worldTrans) const;
|
||||||
void setWorldTransform (const btTransform &worldTrans);
|
void setWorldTransform (const btTransform &worldTrans);
|
||||||
|
#endif // USE_BULLET_PHYSICS
|
||||||
void applyVelocities() const;
|
void applyVelocities() const;
|
||||||
|
void applyGravity() const;
|
||||||
|
|
||||||
void computeShapeInfo(ShapeInfo& info);
|
void computeShapeInfo(ShapeInfo& info);
|
||||||
|
|
||||||
|
@ -42,5 +51,4 @@ protected:
|
||||||
AACube _oldBoundingCube;
|
AACube _oldBoundingCube;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // USE_BULLET_PHYSICS
|
|
||||||
#endif // hifi_EntityMotionState_h
|
#endif // hifi_EntityMotionState_h
|
||||||
|
|
|
@ -77,12 +77,13 @@ EntityItem* EntityTree::getOrCreateEntityItem(const EntityItemID& entityID, cons
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a new entity item to the tree
|
/// Adds a new entity item to the tree
|
||||||
void EntityTree::addEntityItem(EntityItem* entity) {
|
void EntityTree::addEntityInternal(EntityItem* entity) {
|
||||||
// You should not call this on existing entities that are already part of the tree! Call updateEntity()
|
// You should not call this on existing entities that are already part of the tree! Call updateEntity()
|
||||||
EntityItemID entityID = entity->getEntityItemID();
|
EntityItemID entityID = entity->getEntityItemID();
|
||||||
EntityTreeElement* containingElement = getContainingElement(entityID);
|
EntityTreeElement* containingElement = getContainingElement(entityID);
|
||||||
if (containingElement) {
|
if (containingElement) {
|
||||||
qDebug() << "UNEXPECTED!!!! don't call addEntityItem() on existing EntityItems. entityID=" << entityID;
|
// should probably assert here
|
||||||
|
qDebug() << "UNEXPECTED!!!! don't call addEntityInternal() on existing EntityItems. entityID=" << entityID;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,17 +91,39 @@ void EntityTree::addEntityItem(EntityItem* entity) {
|
||||||
AddEntityOperator theOperator(this, entity);
|
AddEntityOperator theOperator(this, entity);
|
||||||
recurseTreeWithOperator(&theOperator);
|
recurseTreeWithOperator(&theOperator);
|
||||||
|
|
||||||
updateEntityState(entity);
|
emitAddingEntity(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EntityTree::emitAddingEntity(EntityItem* entity) {
|
||||||
|
// add entity to proper internal lists
|
||||||
|
EntityItem::SimulationState newState = entity->computeSimulationState();
|
||||||
|
switch (newState) {
|
||||||
|
case EntityItem::Moving:
|
||||||
|
_movingEntities.push_back(entity);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EntityItem::Mortal:
|
||||||
|
_mortalEntities.push_back(entity);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
entity->setSimulationState(newState);
|
||||||
|
entity->clearUpdateFlags();
|
||||||
|
|
||||||
|
// add entity to physics engine
|
||||||
if (_physicsEngine && !entity->getMotionState()) {
|
if (_physicsEngine && !entity->getMotionState()) {
|
||||||
addEntityToPhysicsEngine(entity);
|
addEntityToPhysicsEngine(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
_isDirty = true;
|
_isDirty = true;
|
||||||
|
|
||||||
|
// finally emit the signal
|
||||||
|
emit addingEntity(entity->getEntityItemID());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EntityTree::updateEntity(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
bool EntityTree::updateEntity(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||||
// You should not call this on existing entities that are already part of the tree! Call updateEntity()
|
|
||||||
EntityTreeElement* containingElement = getContainingElement(entityID);
|
EntityTreeElement* containingElement = getContainingElement(entityID);
|
||||||
if (!containingElement) {
|
if (!containingElement) {
|
||||||
qDebug() << "UNEXPECTED!!!! EntityTree::updateEntity() entityID doesn't exist!!! entityID=" << entityID;
|
qDebug() << "UNEXPECTED!!!! EntityTree::updateEntity() entityID doesn't exist!!! entityID=" << entityID;
|
||||||
|
@ -127,20 +150,9 @@ bool EntityTree::updateEntity(const EntityItemID& entityID, const EntityItemProp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// check to see if we need to simulate this entity...
|
|
||||||
QString entityScriptBefore = existingEntity->getScript();
|
|
||||||
|
|
||||||
UpdateEntityOperator theOperator(this, containingElement, existingEntity, properties);
|
UpdateEntityOperator theOperator(this, containingElement, existingEntity, properties);
|
||||||
recurseTreeWithOperator(&theOperator);
|
recurseTreeWithOperator(&theOperator);
|
||||||
_isDirty = true;
|
_isDirty = true;
|
||||||
|
|
||||||
updateEntityState(existingEntity);
|
|
||||||
|
|
||||||
QString entityScriptAfter = existingEntity->getScript();
|
|
||||||
if (entityScriptBefore != entityScriptAfter) {
|
|
||||||
emitEntityScriptChanging(entityID); // the entity script has changed
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
containingElement = getContainingElement(entityID);
|
containingElement = getContainingElement(entityID);
|
||||||
|
@ -177,8 +189,7 @@ EntityItem* EntityTree::addEntity(const EntityItemID& entityID, const EntityItem
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
// this does the actual adding of the entity
|
// this does the actual adding of the entity
|
||||||
addEntityItem(result);
|
addEntityInternal(result);
|
||||||
emitAddingEntity(entityID);
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -204,14 +215,6 @@ void EntityTree::setPhysicsEngine(PhysicsEngine* engine) {
|
||||||
_physicsEngine = engine;
|
_physicsEngine = engine;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityTree::emitAddingEntity(const EntityItemID& entityItemID) {
|
|
||||||
emit addingEntity(entityItemID);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EntityTree::emitEntityScriptChanging(const EntityItemID& entityItemID) {
|
|
||||||
emit entityScriptChanging(entityItemID);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EntityTree::deleteEntity(const EntityItemID& entityID) {
|
void EntityTree::deleteEntity(const EntityItemID& entityID) {
|
||||||
emit deletingEntity(entityID);
|
emit deletingEntity(entityID);
|
||||||
|
|
||||||
|
@ -619,13 +622,6 @@ void EntityTree::updateEntityState(EntityItem* entity) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
entity->setSimulationState(newState);
|
entity->setSimulationState(newState);
|
||||||
|
|
||||||
if (_physicsEngine) {
|
|
||||||
EntityMotionState* motionState = entity->getMotionState();
|
|
||||||
if (motionState) {
|
|
||||||
_physicsEngine->updateEntityMotionType(motionState);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -701,8 +697,15 @@ void EntityTree::updateChangedEntities(quint64 now, QSet<EntityItemID>& entities
|
||||||
entitiesToDelete << thisEntity->getEntityItemID();
|
entitiesToDelete << thisEntity->getEntityItemID();
|
||||||
clearEntityState(thisEntity);
|
clearEntityState(thisEntity);
|
||||||
} else {
|
} else {
|
||||||
// TODO: Andrew to push changes to physics engine (when we know how to sort the changes)
|
uint32_t flags = thisEntity->getUpdateFlags();
|
||||||
|
if (flags & EntityItem::UPDATE_SCRIPT) {
|
||||||
|
emit entityScriptChanging(thisEntity->getEntityItemID());
|
||||||
|
}
|
||||||
|
|
||||||
updateEntityState(thisEntity);
|
updateEntityState(thisEntity);
|
||||||
|
if (_physicsEngine && thisEntity->getMotionState()) {
|
||||||
|
_physicsEngine->updateEntity(thisEntity->getMotionState(), flags);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
thisEntity->clearUpdateFlags();
|
thisEntity->clearUpdateFlags();
|
||||||
}
|
}
|
||||||
|
@ -742,7 +745,7 @@ void EntityTree::updateMovingEntities(quint64 now, QSet<EntityItemID>& entitiesT
|
||||||
qDebug() << "Entity " << thisEntity->getEntityItemID() << " moved out of domain bounds.";
|
qDebug() << "Entity " << thisEntity->getEntityItemID() << " moved out of domain bounds.";
|
||||||
entitiesToDelete << thisEntity->getEntityItemID();
|
entitiesToDelete << thisEntity->getEntityItemID();
|
||||||
clearEntityState(thisEntity);
|
clearEntityState(thisEntity);
|
||||||
} else {
|
} else if (newCube != oldCube) {
|
||||||
moveOperator.addEntityToMoveList(thisEntity, oldCube, newCube);
|
moveOperator.addEntityToMoveList(thisEntity, oldCube, newCube);
|
||||||
updateEntityState(thisEntity);
|
updateEntityState(thisEntity);
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,7 +79,8 @@ public:
|
||||||
|
|
||||||
// The newer API...
|
// The newer API...
|
||||||
EntityItem* getOrCreateEntityItem(const EntityItemID& entityID, const EntityItemProperties& properties);
|
EntityItem* getOrCreateEntityItem(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||||
void addEntityItem(EntityItem* entityItem);
|
void addEntityInternal(EntityItem* entityItem);
|
||||||
|
void emitAddingEntity(EntityItem* entityItem);
|
||||||
|
|
||||||
EntityItem* addEntity(const EntityItemID& entityID, const EntityItemProperties& properties);
|
EntityItem* addEntity(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||||
bool updateEntity(const EntityItemID& entityID, const EntityItemProperties& properties);
|
bool updateEntity(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||||
|
@ -147,9 +148,6 @@ public:
|
||||||
|
|
||||||
void trackDeletedEntity(const EntityItemID& entityID);
|
void trackDeletedEntity(const EntityItemID& entityID);
|
||||||
|
|
||||||
void emitAddingEntity(const EntityItemID& entityItemID);
|
|
||||||
void emitEntityScriptChanging(const EntityItemID& entityItemID);
|
|
||||||
|
|
||||||
QList<EntityItem*>& getMovingEntities() { return _movingEntities; }
|
QList<EntityItem*>& getMovingEntities() { return _movingEntities; }
|
||||||
|
|
||||||
void setPhysicsEngine(PhysicsEngine* engine);
|
void setPhysicsEngine(PhysicsEngine* engine);
|
||||||
|
|
|
@ -742,12 +742,13 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int
|
||||||
// TODO: Do we need to also do this?
|
// TODO: Do we need to also do this?
|
||||||
// 3) remember the old cube for the entity so we can mark it as dirty
|
// 3) remember the old cube for the entity so we can mark it as dirty
|
||||||
if (entityItem) {
|
if (entityItem) {
|
||||||
QString entityScriptBefore = entityItem->getScript();
|
uint32_t oldFlags = entityItem->getUpdateFlags();
|
||||||
bool bestFitBefore = bestFitEntityBounds(entityItem);
|
bool bestFitBefore = bestFitEntityBounds(entityItem);
|
||||||
EntityTreeElement* currentContainingElement = _myTree->getContainingElement(entityItemID);
|
EntityTreeElement* currentContainingElement = _myTree->getContainingElement(entityItemID);
|
||||||
|
|
||||||
bytesForThisEntity = entityItem->readEntityDataFromBuffer(dataAt, bytesLeftToRead, args);
|
bytesForThisEntity = entityItem->readEntityDataFromBuffer(dataAt, bytesLeftToRead, args);
|
||||||
if (entityItem->getUpdateFlags()) {
|
if (!oldFlags && entityItem->getUpdateFlags()) {
|
||||||
|
// this entity is not yet on the changed list and needs to be added
|
||||||
_myTree->entityChanged(entityItem);
|
_myTree->entityChanged(entityItem);
|
||||||
}
|
}
|
||||||
bool bestFitAfter = bestFitEntityBounds(entityItem);
|
bool bestFitAfter = bestFitEntityBounds(entityItem);
|
||||||
|
@ -763,21 +764,14 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString entityScriptAfter = entityItem->getScript();
|
|
||||||
if (entityScriptBefore != entityScriptAfter) {
|
|
||||||
_myTree->emitEntityScriptChanging(entityItemID); // the entity script has changed
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
entityItem = EntityTypes::constructEntityItem(dataAt, bytesLeftToRead, args);
|
entityItem = EntityTypes::constructEntityItem(dataAt, bytesLeftToRead, args);
|
||||||
if (entityItem) {
|
if (entityItem) {
|
||||||
bytesForThisEntity = entityItem->readEntityDataFromBuffer(dataAt, bytesLeftToRead, args);
|
bytesForThisEntity = entityItem->readEntityDataFromBuffer(dataAt, bytesLeftToRead, args);
|
||||||
addEntityItem(entityItem); // add this new entity to this elements entities
|
addEntityItem(entityItem); // add this new entity to this elements entities
|
||||||
|
_myTree->emitAddingEntity(entityItem);
|
||||||
entityItemID = entityItem->getEntityItemID();
|
entityItemID = entityItem->getEntityItemID();
|
||||||
_myTree->setContainingElement(entityItemID, this);
|
_myTree->setContainingElement(entityItemID, this);
|
||||||
_myTree->updateEntityState(entityItem);
|
|
||||||
_myTree->emitAddingEntity(entityItemID); // we just added an entity
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Move the buffer forward to read more entities
|
// Move the buffer forward to read more entities
|
||||||
|
|
|
@ -299,14 +299,25 @@ bool UpdateEntityOperator::preRecursion(OctreeElement* element) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the entity properties and mark our element as changed.
|
// set the entity properties and mark our element as changed.
|
||||||
_existingEntity->setProperties(_properties);
|
uint32_t oldUpdateFlags = _existingEntity->getUpdateFlags();
|
||||||
|
bool somethingChanged = _existingEntity->setProperties(_properties);
|
||||||
|
uint32_t newUpdateFlags = _existingEntity->getUpdateFlags();
|
||||||
|
if (somethingChanged && !oldUpdateFlags && _existingEntity->getUpdateFlags()) {
|
||||||
|
// this entity hasn't yet been added to changed list
|
||||||
|
_tree->entityChanged(_existingEntity);
|
||||||
|
}
|
||||||
if (_wantDebug) {
|
if (_wantDebug) {
|
||||||
qDebug() << " *** set properties ***";
|
qDebug() << " *** set properties ***";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// otherwise, this is an add case.
|
// otherwise, this is an add case.
|
||||||
entityTreeElement->addEntityItem(_existingEntity);
|
entityTreeElement->addEntityItem(_existingEntity);
|
||||||
_existingEntity->setProperties(_properties); // still need to update the properties!
|
uint32_t oldUpdateFlags = _existingEntity->getUpdateFlags();
|
||||||
|
bool somethingChanged = _existingEntity->setProperties(_properties); // still need to update the properties!
|
||||||
|
if (somethingChanged && !oldUpdateFlags && _existingEntity->getUpdateFlags()) {
|
||||||
|
// this entity hasn't yet been added to changed list
|
||||||
|
_tree->entityChanged(_existingEntity);
|
||||||
|
}
|
||||||
_tree->setContainingElement(_entityItemID, entityTreeElement);
|
_tree->setContainingElement(_entityItemID, entityTreeElement);
|
||||||
if (_wantDebug) {
|
if (_wantDebug) {
|
||||||
qDebug() << " *** ADDING ENTITY to ELEMENT and MAP and SETTING PROPERTIES ***";
|
qDebug() << " *** ADDING ENTITY to ELEMENT and MAP and SETTING PROPERTIES ***";
|
||||||
|
|
|
@ -72,6 +72,12 @@ void CustomMotionState::setAngularVelocity(const glm::vec3& velocity) const {
|
||||||
_body->setAngularVelocity(v);
|
_body->setAngularVelocity(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CustomMotionState::setGravity(const glm::vec3& gravity) const {
|
||||||
|
btVector3 g;
|
||||||
|
glmToBullet(gravity, g);
|
||||||
|
_body->setGravity(g);
|
||||||
|
}
|
||||||
|
|
||||||
void CustomMotionState::getVelocity(glm::vec3& velocityOut) const {
|
void CustomMotionState::getVelocity(glm::vec3& velocityOut) const {
|
||||||
bulletToGLM(_body->getLinearVelocity(), velocityOut);
|
bulletToGLM(_body->getLinearVelocity(), velocityOut);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ public:
|
||||||
//virtual void setWorldTransform (const btTransform &worldTrans);
|
//virtual void setWorldTransform (const btTransform &worldTrans);
|
||||||
|
|
||||||
virtual void applyVelocities() const = 0;
|
virtual void applyVelocities() const = 0;
|
||||||
|
virtual void applyGravity() const = 0;
|
||||||
|
|
||||||
virtual void computeShapeInfo(ShapeInfo& info) = 0;
|
virtual void computeShapeInfo(ShapeInfo& info) = 0;
|
||||||
|
|
||||||
|
@ -49,6 +50,7 @@ public:
|
||||||
|
|
||||||
void setVelocity(const glm::vec3& velocity) const;
|
void setVelocity(const glm::vec3& velocity) const;
|
||||||
void setAngularVelocity(const glm::vec3& velocity) const;
|
void setAngularVelocity(const glm::vec3& velocity) const;
|
||||||
|
void setGravity(const glm::vec3& gravity) const;
|
||||||
|
|
||||||
void getVelocity(glm::vec3& velocityOut) const;
|
void getVelocity(glm::vec3& velocityOut) const;
|
||||||
void getAngularVelocity(glm::vec3& angularVelocityOut) const;
|
void getAngularVelocity(glm::vec3& angularVelocityOut) const;
|
||||||
|
|
|
@ -32,7 +32,7 @@ void PhysicsEngine::init() {
|
||||||
// NOTE: we don't care about memory leaking groundShape and groundObject -->
|
// NOTE: we don't care about memory leaking groundShape and groundObject -->
|
||||||
// they'll exist until the executable exits.
|
// they'll exist until the executable exits.
|
||||||
const float halfSide = 200.0f;
|
const float halfSide = 200.0f;
|
||||||
const float halfHeight = 10.0f;
|
const float halfHeight = 1.0f;
|
||||||
|
|
||||||
btCollisionShape* groundShape = new btBoxShape(btVector3(halfSide, halfHeight, halfSide));
|
btCollisionShape* groundShape = new btBoxShape(btVector3(halfSide, halfHeight, halfSide));
|
||||||
btTransform groundTransform;
|
btTransform groundTransform;
|
||||||
|
@ -40,6 +40,7 @@ void PhysicsEngine::init() {
|
||||||
groundTransform.setOrigin(btVector3(halfSide, -halfHeight, halfSide));
|
groundTransform.setOrigin(btVector3(halfSide, -halfHeight, halfSide));
|
||||||
|
|
||||||
btCollisionObject* groundObject = new btCollisionObject();
|
btCollisionObject* groundObject = new btCollisionObject();
|
||||||
|
groundObject->setCollisionFlags(btCollisionObject::CF_STATIC_OBJECT);
|
||||||
groundObject->setCollisionShape(groundShape);
|
groundObject->setCollisionShape(groundShape);
|
||||||
groundObject->setWorldTransform(groundTransform);
|
groundObject->setWorldTransform(groundTransform);
|
||||||
_dynamicsWorld->addCollisionObject(groundObject);
|
_dynamicsWorld->addCollisionObject(groundObject);
|
||||||
|
@ -131,7 +132,7 @@ bool PhysicsEngine::addEntity(CustomMotionState* motionState) {
|
||||||
btVector3 inertia(0.0f, 0.0f, 0.0f);
|
btVector3 inertia(0.0f, 0.0f, 0.0f);
|
||||||
float mass = 0.0f;
|
float mass = 0.0f;
|
||||||
btRigidBody* body = NULL;
|
btRigidBody* body = NULL;
|
||||||
switch(motionState->_motionType) {
|
switch(motionState->getMotionType()) {
|
||||||
case MOTION_TYPE_KINEMATIC: {
|
case MOTION_TYPE_KINEMATIC: {
|
||||||
body = new btRigidBody(mass, motionState, shape, inertia);
|
body = new btRigidBody(mass, motionState, shape, inertia);
|
||||||
body->setCollisionFlags(btCollisionObject::CF_KINEMATIC_OBJECT);
|
body->setCollisionFlags(btCollisionObject::CF_KINEMATIC_OBJECT);
|
||||||
|
@ -147,6 +148,7 @@ bool PhysicsEngine::addEntity(CustomMotionState* motionState) {
|
||||||
body->updateInertiaTensor();
|
body->updateInertiaTensor();
|
||||||
motionState->_body = body;
|
motionState->_body = body;
|
||||||
motionState->applyVelocities();
|
motionState->applyVelocities();
|
||||||
|
motionState->applyGravity();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MOTION_TYPE_STATIC:
|
case MOTION_TYPE_STATIC:
|
||||||
|
@ -158,6 +160,8 @@ bool PhysicsEngine::addEntity(CustomMotionState* motionState) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// wtf?
|
||||||
|
body->setFlags(BT_DISABLE_WORLD_GRAVITY);
|
||||||
body->setRestitution(motionState->_restitution);
|
body->setRestitution(motionState->_restitution);
|
||||||
body->setFriction(motionState->_friction);
|
body->setFriction(motionState->_friction);
|
||||||
_dynamicsWorld->addRigidBody(body);
|
_dynamicsWorld->addRigidBody(body);
|
||||||
|
@ -182,60 +186,132 @@ bool PhysicsEngine::removeEntity(CustomMotionState* motionState) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PhysicsEngine::updateEntityMotionType(CustomMotionState* motionState) {
|
bool PhysicsEngine::updateEntity(CustomMotionState* motionState, uint32_t flags) {
|
||||||
btRigidBody* body = motionState->_body;
|
btRigidBody* body = motionState->_body;
|
||||||
if (!body) {
|
if (!body) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flags & PHYSICS_UPDATE_HARD) {
|
||||||
|
// a hard update requires the body be pulled out of physics engine, changed, then reinserted
|
||||||
|
updateEntityHard(body, motionState, flags);
|
||||||
|
} else if (flags & PHYSICS_UPDATE_EASY) {
|
||||||
|
// an easy update does not require that the body be pulled out of physics engine
|
||||||
|
updateEntityEasy(body, motionState, flags);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// private
|
||||||
|
void PhysicsEngine::updateEntityHard(btRigidBody* body, CustomMotionState* motionState, uint32_t flags) {
|
||||||
|
MotionType newType = motionState->getMotionType();
|
||||||
MotionType oldType = MOTION_TYPE_DYNAMIC;
|
MotionType oldType = MOTION_TYPE_DYNAMIC;
|
||||||
if (body->isStaticObject()) {
|
if (body->isStaticObject()) {
|
||||||
oldType = MOTION_TYPE_STATIC;
|
oldType = MOTION_TYPE_STATIC;
|
||||||
} else if (body->isKinematicObject()) {
|
} else if (body->isKinematicObject()) {
|
||||||
oldType = MOTION_TYPE_KINEMATIC;
|
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
|
// pull body out of physics engine
|
||||||
switch (newType) {
|
_dynamicsWorld->removeRigidBody(body);
|
||||||
case MOTION_TYPE_KINEMATIC: {
|
|
||||||
body->setCollisionFlags(btCollisionObject::CF_KINEMATIC_OBJECT);
|
if (flags & PHYSICS_UPDATE_SHAPE) {
|
||||||
body->setActivationState(DISABLE_DEACTIVATION);
|
btCollisionShape* oldShape = body->getCollisionShape();
|
||||||
body->updateInertiaTensor();
|
ShapeInfo info;
|
||||||
break;
|
motionState->computeShapeInfo(info);
|
||||||
}
|
btCollisionShape* newShape = _shapeManager.getShape(info);
|
||||||
case MOTION_TYPE_DYNAMIC: {
|
if (newShape != oldShape) {
|
||||||
|
body->setCollisionShape(newShape);
|
||||||
|
_shapeManager.releaseShape(oldShape);
|
||||||
|
} else {
|
||||||
|
// whoops, shape hasn't changed after all so we must release the reference
|
||||||
|
// that was created when looking it up
|
||||||
|
_shapeManager.releaseShape(newShape);
|
||||||
|
}
|
||||||
|
// MASS bit should be set whenever SHAPE is set
|
||||||
|
assert(flags & PHYSICS_UPDATE_MASS);
|
||||||
|
}
|
||||||
|
bool easyUpdate = flags & PHYSICS_UPDATE_EASY;
|
||||||
|
if (easyUpdate) {
|
||||||
|
updateEntityEasy(body, motionState, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
// update the motion parameters
|
||||||
|
switch (newType) {
|
||||||
|
case MOTION_TYPE_KINEMATIC: {
|
||||||
|
int collisionFlags = body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT;
|
||||||
|
collisionFlags &= ~(btCollisionObject::CF_STATIC_OBJECT);
|
||||||
|
body->setCollisionFlags(collisionFlags);
|
||||||
|
body->forceActivationState(DISABLE_DEACTIVATION);
|
||||||
|
|
||||||
|
body->setMassProps(0.0f, btVector3(0.0f, 0.0f, 0.0f));
|
||||||
|
body->updateInertiaTensor();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MOTION_TYPE_DYNAMIC: {
|
||||||
|
int collisionFlags = body->getCollisionFlags() & ~(btCollisionObject::CF_KINEMATIC_OBJECT | btCollisionObject::CF_STATIC_OBJECT);
|
||||||
|
body->setCollisionFlags(collisionFlags);
|
||||||
|
if (! (flags & PHYSICS_UPDATE_MASS)) {
|
||||||
|
// always update mass properties when going dynamic (unless it's already been done)
|
||||||
btVector3 inertia(0.0f, 0.0f, 0.0f);
|
btVector3 inertia(0.0f, 0.0f, 0.0f);
|
||||||
float mass = motionState->getMass();
|
float mass = motionState->getMass();
|
||||||
body->getCollisionShape()->calculateLocalInertia(mass, inertia);
|
body->getCollisionShape()->calculateLocalInertia(mass, inertia);
|
||||||
|
body->setMassProps(mass, inertia);
|
||||||
body->updateInertiaTensor();
|
body->updateInertiaTensor();
|
||||||
motionState->applyVelocities();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
// MOTION_TYPE_STATIC
|
|
||||||
body->setCollisionFlags(btCollisionObject::CF_STATIC_OBJECT);
|
|
||||||
body->updateInertiaTensor();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
bool forceActivation = true;
|
||||||
|
body->activate(forceActivation);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
default: {
|
||||||
|
// MOTION_TYPE_STATIC
|
||||||
|
int collisionFlags = body->getCollisionFlags() | btCollisionObject::CF_STATIC_OBJECT;
|
||||||
|
collisionFlags &= ~(btCollisionObject::CF_KINEMATIC_OBJECT);
|
||||||
|
body->setCollisionFlags(collisionFlags);
|
||||||
|
body->forceActivationState(DISABLE_SIMULATION);
|
||||||
|
|
||||||
// reinsert body into physics engine
|
body->setMassProps(0.0f, btVector3(0.0f, 0.0f, 0.0f));
|
||||||
body->setRestitution(motionState->_restitution);
|
body->updateInertiaTensor();
|
||||||
body->setFriction(motionState->_friction);
|
|
||||||
_dynamicsWorld->addRigidBody(body);
|
body->setLinearVelocity(btVector3(0.0f, 0.0f, 0.0f));
|
||||||
return true;
|
body->setAngularVelocity(btVector3(0.0f, 0.0f, 0.0f));
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
|
// reinsert body into physics engine
|
||||||
|
_dynamicsWorld->addRigidBody(body);
|
||||||
|
|
||||||
|
body->activate();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PhysicsEngine::updateEntityMassProperties(CustomMotionState* motionState, float mass, const glm::vec3& inertiaEigenValues) {
|
// private
|
||||||
// TODO: implement this
|
void PhysicsEngine::updateEntityEasy(btRigidBody* body, CustomMotionState* motionState, uint32_t flags) {
|
||||||
assert(motionState);
|
if (flags & PHYSICS_UPDATE_POSITION) {
|
||||||
return false;
|
btTransform transform;
|
||||||
}
|
motionState->getWorldTransform(transform);
|
||||||
|
body->setWorldTransform(transform);
|
||||||
|
}
|
||||||
|
if (flags & PHYSICS_UPDATE_VELOCITY) {
|
||||||
|
motionState->applyVelocities();
|
||||||
|
motionState->applyGravity();
|
||||||
|
}
|
||||||
|
body->setRestitution(motionState->_restitution);
|
||||||
|
body->setFriction(motionState->_friction);
|
||||||
|
|
||||||
|
if (flags & PHYSICS_UPDATE_MASS) {
|
||||||
|
float mass = motionState->getMass();
|
||||||
|
btVector3 inertia(0.0f, 0.0f, 0.0f);
|
||||||
|
body->getCollisionShape()->calculateLocalInertia(mass, inertia);
|
||||||
|
body->setMassProps(mass, inertia);
|
||||||
|
body->updateInertiaTensor();
|
||||||
|
}
|
||||||
|
body->activate();
|
||||||
|
|
||||||
|
btVector3 v = body->getLinearVelocity();
|
||||||
|
btVector3 g = body->getGravity();
|
||||||
|
|
||||||
|
// TODO: support collision groups
|
||||||
|
};
|
||||||
|
|
||||||
#endif // USE_BULLET_PHYSICS
|
#endif // USE_BULLET_PHYSICS
|
||||||
|
|
|
@ -12,6 +12,24 @@
|
||||||
#ifndef hifi_PhysicsEngine_h
|
#ifndef hifi_PhysicsEngine_h
|
||||||
#define hifi_PhysicsEngine_h
|
#define hifi_PhysicsEngine_h
|
||||||
|
|
||||||
|
enum PhysicsUpdateFlag {
|
||||||
|
PHYSICS_UPDATE_POSITION = 0x0001,
|
||||||
|
PHYSICS_UPDATE_VELOCITY = 0x0002,
|
||||||
|
PHYSICS_UPDATE_GRAVITY = 0x0004,
|
||||||
|
PHYSICS_UPDATE_MASS = 0x0008,
|
||||||
|
PHYSICS_UPDATE_COLLISION_GROUP = 0x0010,
|
||||||
|
PHYSICS_UPDATE_MOTION_TYPE = 0x0020,
|
||||||
|
PHYSICS_UPDATE_SHAPE = 0x0040
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef unsigned int uint32_t;
|
||||||
|
|
||||||
|
// The update flags trigger two varieties of updates: "hard" which require the body to be pulled
|
||||||
|
// and re-added to the physics engine and "easy" which just updates the body properties.
|
||||||
|
const uint32_t PHYSICS_UPDATE_HARD = PHYSICS_UPDATE_MOTION_TYPE | PHYSICS_UPDATE_SHAPE;
|
||||||
|
const uint32_t PHYSICS_UPDATE_EASY = PHYSICS_UPDATE_POSITION | PHYSICS_UPDATE_VELOCITY |
|
||||||
|
PHYSICS_UPDATE_GRAVITY PHYSICS_UPDATE_MASS | PHYSICS_UPDATE_COLLISION_GROUP;
|
||||||
|
|
||||||
#ifdef USE_BULLET_PHYSICS
|
#ifdef USE_BULLET_PHYSICS
|
||||||
|
|
||||||
#include <btBulletDynamicsCommon.h>
|
#include <btBulletDynamicsCommon.h>
|
||||||
|
@ -68,12 +86,14 @@ public:
|
||||||
bool removeEntity(CustomMotionState* motionState);
|
bool removeEntity(CustomMotionState* motionState);
|
||||||
|
|
||||||
/// \param motionState pointer to Entity's MotionState
|
/// \param motionState pointer to Entity's MotionState
|
||||||
|
/// \param flags set of bits indicating what categories of properties need to be updated
|
||||||
/// \return true if entity updated
|
/// \return true if entity updated
|
||||||
bool updateEntityMotionType(CustomMotionState* motionState);
|
bool updateEntity(CustomMotionState* motionState, uint32_t flags);
|
||||||
|
|
||||||
bool updateEntityMassProperties(CustomMotionState* motionState, float mass, const glm::vec3& inertiaEigenValues);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
void updateEntityHard(btRigidBody* body, CustomMotionState* motionState, uint32_t flags);
|
||||||
|
void updateEntityEasy(btRigidBody* body, CustomMotionState* motionState, uint32_t flags);
|
||||||
|
|
||||||
btClock _clock;
|
btClock _clock;
|
||||||
btDefaultCollisionConfiguration* _collisionConfig;
|
btDefaultCollisionConfiguration* _collisionConfig;
|
||||||
btCollisionDispatcher* _collisionDispatcher;
|
btCollisionDispatcher* _collisionDispatcher;
|
||||||
|
|
Loading…
Reference in a new issue