make some things compile after reorganization

This commit is contained in:
Andrew Meadows 2015-04-30 13:02:18 -07:00
parent 9c5f51917a
commit c3901939e6
14 changed files with 232 additions and 205 deletions

View file

@ -299,6 +299,7 @@ public:
void* getPhysicsInfo() const { return _physicsInfo; } void* getPhysicsInfo() const { return _physicsInfo; }
void setPhysicsInfo(void* data) { _physicsInfo = data; }
EntityTreeElement* getElement() const { return _element; } EntityTreeElement* getElement() const { return _element; }
EntitySimulation* getSimulation() const { return _simulation; } EntitySimulation* getSimulation() const { return _simulation; }
@ -311,7 +312,6 @@ public:
glm::vec3 entityToWorld(const glm::vec3& point) const; glm::vec3 entityToWorld(const glm::vec3& point) const;
protected: protected:
void setPhysicsInfo(void* data) { _physicsInfo = data; }
static bool _sendPhysicsUpdates; static bool _sendPhysicsUpdates;
EntityTypes::EntityType _type; EntityTypes::EntityType _type;

View file

@ -56,7 +56,7 @@ void EntitySimulation::getEntitiesToDelete(SetOfEntities& entitiesToDelete) {
} }
} }
// private // protected
void EntitySimulation::expireMortalEntities(const quint64& now) { void EntitySimulation::expireMortalEntities(const quint64& now) {
if (now > _nextExpiry) { if (now > _nextExpiry) {
// only search for expired entities if we expect to find one // only search for expired entities if we expect to find one
@ -82,7 +82,7 @@ void EntitySimulation::expireMortalEntities(const quint64& now) {
} }
} }
// private // protected
void EntitySimulation::callUpdateOnEntitiesThatNeedIt(const quint64& now) { void EntitySimulation::callUpdateOnEntitiesThatNeedIt(const quint64& now) {
PerformanceTimer perfTimer("updatingEntities"); PerformanceTimer perfTimer("updatingEntities");
SetOfEntities::iterator itemItr = _entitiesToUpdate.begin(); SetOfEntities::iterator itemItr = _entitiesToUpdate.begin();
@ -99,7 +99,7 @@ void EntitySimulation::callUpdateOnEntitiesThatNeedIt(const quint64& now) {
} }
} }
// private // protected
void EntitySimulation::sortEntitiesThatMoved() { void EntitySimulation::sortEntitiesThatMoved() {
// NOTE: this is only for entities that have been moved by THIS EntitySimulation. // NOTE: this is only for entities that have been moved by THIS EntitySimulation.
// External changes to entity position/shape are expected to be sorted outside of the EntitySimulation. // External changes to entity position/shape are expected to be sorted outside of the EntitySimulation.

View file

@ -77,6 +77,8 @@ signals:
protected: protected:
void clearEntitySimulation(EntityItem* entity) { entity->_simulation = nullptr; }
// These pure virtual methods are protected because they are not to be called will-nilly. The base class // These pure virtual methods are protected because they are not to be called will-nilly. The base class
// calls them in the right places. // calls them in the right places.

View file

@ -65,15 +65,15 @@ void SimpleEntitySimulation::removeEntityInternal(EntityItem* entity) {
_movingEntities.remove(entity); _movingEntities.remove(entity);
_movableButStoppedEntities.remove(entity); _movableButStoppedEntities.remove(entity);
_hasSimulationOwnerEntities.remove(entity); _hasSimulationOwnerEntities.remove(entity);
entity->_simulation = nullptr; clearEntitySimulation(entity);
} }
void SimpleEntitySimulation::deleteEntityInternal(EntityItem* entity) { void SimpleEntitySimulation::deleteEntityInternal(EntityItem* entity) {
_movingEntities.remove(entity); _movingEntities.remove(entity);
_movableButStoppedEntities.remove(entity); _movableButStoppedEntities.remove(entity);
_hasSimulationOwnerEntities.remove(entity); _hasSimulationOwnerEntities.remove(entity);
entity->_simulation = nullptr; clearEntitySimulation(entity);
if (!entity->_tree) { if (!entity->getElement()) {
// we held the last reference to this entity, so delete it // we held the last reference to this entity, so delete it
delete entity; delete entity;
} }

View file

@ -54,21 +54,6 @@ MotionType EntityMotionState::computeObjectMotionType() const {
return _entity->isMoving() ? MOTION_TYPE_KINEMATIC : MOTION_TYPE_STATIC; return _entity->isMoving() ? MOTION_TYPE_KINEMATIC : MOTION_TYPE_STATIC;
} }
void EntityMotionState::updateKinematicState(uint32_t substep) {
setKinematic(_entity->isMoving(), substep);
}
void EntityMotionState::stepKinematicSimulation(quint64 now) {
assert(_isKinematic);
// NOTE: this is non-physical kinematic motion which steps to real run-time (now)
// which is different from physical kinematic motion (inside getWorldTransform())
// which steps in physics simulation time.
_entity->simulate(now);
// TODO: we can't use measureBodyAcceleration() here because the entity
// has no RigidBody and the timestep is a little bit out of sync with the physics simulation anyway.
// Hence we must manually measure kinematic velocity and acceleration.
}
bool EntityMotionState::isMoving() const { bool EntityMotionState::isMoving() const {
return _entity->isMoving(); return _entity->isMoving();
} }
@ -79,18 +64,18 @@ bool EntityMotionState::isMoving() const {
// (2) at the beginning of each simulation step for KINEMATIC RigidBody's -- // (2) at the beginning of each simulation step for KINEMATIC RigidBody's --
// it is an opportunity for outside code to update the object's simulation position // it is an opportunity for outside code to update the object's simulation position
void EntityMotionState::getWorldTransform(btTransform& worldTrans) const { void EntityMotionState::getWorldTransform(btTransform& worldTrans) const {
if (_isKinematic) { if (_motionType == MOTION_TYPE_KINEMATIC) {
// This is physical kinematic motion which steps strictly by the subframe count // This is physical kinematic motion which steps strictly by the subframe count
// of the physics simulation. // of the physics simulation.
uint32_t substep = PhysicsEngine::getNumSubsteps(); uint32_t thisStep = ObjectMotionState::getWorldSimulationStep();
float dt = (substep - _lastKinematicSubstep) * PHYSICS_ENGINE_FIXED_SUBSTEP; float dt = (thisStep - _lastKinematicStep) * PHYSICS_ENGINE_FIXED_SUBSTEP;
_entity->simulateKinematicMotion(dt); _entity->simulateKinematicMotion(dt);
_entity->setLastSimulated(usecTimestampNow()); _entity->setLastSimulated(usecTimestampNow());
// bypass const-ness so we can remember the substep // bypass const-ness so we can remember the step
const_cast<EntityMotionState*>(this)->_lastKinematicSubstep = substep; const_cast<EntityMotionState*>(this)->_lastKinematicStep = thisStep;
} }
worldTrans.setOrigin(glmToBullet(_entity->getPosition() - ObjectMotionState::getWorldOffset())); worldTrans.setOrigin(glmToBullet(getObjectPosition()));
worldTrans.setRotation(glmToBullet(_entity->getRotation())); worldTrans.setRotation(glmToBullet(_entity->getRotation()));
} }
@ -101,13 +86,8 @@ void EntityMotionState::setWorldTransform(const btTransform& worldTrans) {
_entity->setPosition(bulletToGLM(worldTrans.getOrigin()) + ObjectMotionState::getWorldOffset()); _entity->setPosition(bulletToGLM(worldTrans.getOrigin()) + ObjectMotionState::getWorldOffset());
_entity->setRotation(bulletToGLM(worldTrans.getRotation())); _entity->setRotation(bulletToGLM(worldTrans.getRotation()));
glm::vec3 v; _entity->setVelocity(getBodyLinearVelocity());
getVelocity(v); _entity->setAngularVelocity(getBodyAngularVelocity());
_entity->setVelocity(v);
glm::vec3 av;
getAngularVelocity(av);
_entity->setAngularVelocity(av);
_entity->setLastSimulated(usecTimestampNow()); _entity->setLastSimulated(usecTimestampNow());
@ -405,3 +385,32 @@ uint32_t EntityMotionState::getIncomingDirtyFlags() const {
return dirtyFlags; return dirtyFlags;
*/ */
} }
void EntityMotionState::resetMeasuredBodyAcceleration() {
_lastMeasureStep = ObjectMotionState::getWorldSimulationStep();
_lastVelocity = bulletToGLM(_body->getLinearVelocity());
_measuredAcceleration = glm::vec3(0.0f);
}
void EntityMotionState::measureBodyAcceleration() {
// try to manually measure the true acceleration of the object
uint32_t thisStep = ObjectMotionState::getWorldSimulationStep();
uint32_t numSubsteps = thisStep - _lastMeasureStep;
if (numSubsteps > 0) {
float dt = ((float)numSubsteps * PHYSICS_ENGINE_FIXED_SUBSTEP);
float invDt = 1.0f / dt;
_lastMeasureStep = thisStep;
// Note: the integration equation for velocity uses damping: v1 = (v0 + a * dt) * (1 - D)^dt
// hence the equation for acceleration is: a = (v1 / (1 - D)^dt - v0) / dt
glm::vec3 velocity = bulletToGLM(_body->getLinearVelocity());
_measuredAcceleration = (velocity / powf(1.0f - _body->getLinearDamping(), dt) - _lastVelocity) * invDt;
_lastVelocity = velocity;
}
}
// virtual
void EntityMotionState::setMotionType(MotionType motionType) {
ObjectMotionState::setMotionType(motionType);
resetMeasuredBodyAcceleration();
}

View file

@ -31,9 +31,6 @@ public:
/// \return MOTION_TYPE_DYNAMIC or MOTION_TYPE_STATIC based on params set in EntityItem /// \return MOTION_TYPE_DYNAMIC or MOTION_TYPE_STATIC based on params set in EntityItem
virtual MotionType computeObjectMotionType() const; virtual MotionType computeObjectMotionType() const;
virtual void updateKinematicState(uint32_t substep);
virtual void stepKinematicSimulation(quint64 now);
virtual bool isMoving() const; virtual bool isMoving() const;
// this relays incoming position/rotation to the RigidBody // this relays incoming position/rotation to the RigidBody
@ -65,15 +62,20 @@ public:
virtual float getObjectLinearDamping() const { return _entity->getDamping(); } virtual float getObjectLinearDamping() const { return _entity->getDamping(); }
virtual float getObjectAngularDamping() const { return _entity->getAngularDamping(); } virtual float getObjectAngularDamping() const { return _entity->getAngularDamping(); }
virtual const glm::vec3& getObjectPosition() const { return _entity->getPosition(); } virtual glm::vec3 getObjectPosition() const { return _entity->getPosition() - ObjectMotionState::getWorldOffset(); }
virtual const glm::quat& getObjectRotation() const { return _entity->getRotation(); } virtual const glm::quat& getObjectRotation() const { return _entity->getRotation(); }
virtual const glm::vec3& getObjectLinearVelocity() const { return _entity->getVelocity(); } virtual const glm::vec3& getObjectLinearVelocity() const { return _entity->getVelocity(); }
virtual const glm::vec3& getObjectAngularVelocity() const { return _entity->getAngularVelocity(); } virtual const glm::vec3& getObjectAngularVelocity() const { return _entity->getAngularVelocity(); }
virtual const glm::vec3& getObjectGravity() const { return _entity->getGravity(); } virtual const glm::vec3& getObjectGravity() const { return _entity->getGravity(); }
EntityItem* getEntityItem() const { return _entityItem; } EntityItem* getEntity() const { return _entity; }
void resetMeasuredBodyAcceleration();
void measureBodyAcceleration();
protected: protected:
virtual void setMotionType(MotionType motionType);
EntityItem* _entity; EntityItem* _entity;
bool _sentMoving; // true if last update was moving bool _sentMoving; // true if last update was moving
@ -87,6 +89,10 @@ protected:
glm::vec3 _sentGravity; glm::vec3 _sentGravity;
glm::vec3 _sentAcceleration; glm::vec3 _sentAcceleration;
uint32_t _lastMeasureStep;
glm::vec3 _lastVelocity;
glm::vec3 _measuredAcceleration;
quint8 _accelerationNearlyGravityCount; quint8 _accelerationNearlyGravityCount;
bool _shouldClaimSimulationOwnership; bool _shouldClaimSimulationOwnership;
quint32 _movingStepsWithoutSimulationOwner; quint32 _movingStepsWithoutSimulationOwner;

View file

@ -36,22 +36,26 @@ const glm::vec3& ObjectMotionState::getWorldOffset() {
} }
// static // static
uint32_t _worldSimulationStep = 0; uint32_t worldSimulationStep = 0;
void ObjectMotionState::setWorldSimulationStep(uint32_t step) { void ObjectMotionState::setWorldSimulationStep(uint32_t step) {
assert(step > _worldSimulationStep); assert(step > worldSimulationStep);
_worldSimulationStep = step; worldSimulationStep = step;
}
uint32_t ObjectMotionState::getWorldSimulationStep() {
return worldSimulationStep;
} }
// static // static
ShapeManager* _shapeManager = nullptr; ShapeManager* shapeManager = nullptr;
void ObjectMotionState::setShapeManager(ShapeManager* shapeManager) { void ObjectMotionState::setShapeManager(ShapeManager* manager) {
assert(shapeManager); assert(manager);
_shapeManager = shapeManager; shapeManager = manager;
} }
ShapeManager* ObjectMotionState::getShapeManager() { ShapeManager* ObjectMotionState::getShapeManager() {
assert(_shapeManager); // you must properly set _shapeManager before calling getShapeManager() assert(shapeManager); // you must properly set shapeManager before calling getShapeManager()
return _shapeManager; return shapeManager;
} }
ObjectMotionState::ObjectMotionState(btCollisionShape* shape) : ObjectMotionState::ObjectMotionState(btCollisionShape* shape) :
@ -59,43 +63,8 @@ ObjectMotionState::ObjectMotionState(btCollisionShape* shape) :
_shape(shape), _shape(shape),
_body(nullptr), _body(nullptr),
_mass(0.0f), _mass(0.0f),
_lastSimulationStep(0), _lastKinematicStep(worldSimulationStep)
_lastVelocity(0.0f),
_measuredAcceleration(0.0f)
{ {
assert(_shape);
}
ObjectMotionState::~ObjectMotionState() {
// NOTE: you MUST remove this MotionState from the world before you call the dtor.
assert(_body == nullptr);
if (_shape) {
// the ObjectMotionState owns a reference to its shape in the ShapeManager
// se we must release it
getShapeManager()->releaseShape(_shape);
_shape = nullptr;
}
}
void ObjectMotionState::measureBodyAcceleration() {
// try to manually measure the true acceleration of the object
uint32_t numSubsteps = _worldSimulationStep - _lastSimulationStep;
if (numSubsteps > 0) {
float dt = ((float)numSubsteps * PHYSICS_ENGINE_FIXED_SUBSTEP);
float invDt = 1.0f / dt;
_lastSimulationStep = _worldSimulationStep;
// Note: the integration equation for velocity uses damping: v1 = (v0 + a * dt) * (1 - D)^dt
// hence the equation for acceleration is: a = (v1 / (1 - D)^dt - v0) / dt
glm::vec3 velocity = bulletToGLM(_body->getLinearVelocity());
_measuredAcceleration = (velocity / powf(1.0f - _body->getLinearDamping(), dt) - _lastVelocity) * invDt;
_lastVelocity = velocity;
}
}
void ObjectMotionState::resetMeasuredBodyAcceleration() {
_lastSimulationStep = _worldSimulationStep;
_lastVelocity = bulletToGLM(_body->getLinearVelocity());
} }
void ObjectMotionState::setBodyLinearVelocity(const glm::vec3& velocity) const { void ObjectMotionState::setBodyLinearVelocity(const glm::vec3& velocity) const {
@ -110,7 +79,7 @@ void ObjectMotionState::setBodyGravity(const glm::vec3& gravity) const {
_body->setGravity(glmToBullet(gravity)); _body->setGravity(glmToBullet(gravity));
} }
glm::vec3 ObjectMotionState::getBodyVelocity() const { glm::vec3 ObjectMotionState::getBodyLinearVelocity() const {
return bulletToGLM(_body->getLinearVelocity()); return bulletToGLM(_body->getLinearVelocity());
} }
@ -118,6 +87,17 @@ glm::vec3 ObjectMotionState::getBodyAngularVelocity() const {
return bulletToGLM(_body->getAngularVelocity()); return bulletToGLM(_body->getAngularVelocity());
} }
void ObjectMotionState::releaseShape() {
if (_shape) {
shapeManager->releaseShape(_shape);
_shape = nullptr;
}
}
void ObjectMotionState::setMotionType(MotionType motionType) {
_motionType = motionType;
}
void ObjectMotionState::setRigidBody(btRigidBody* body) { void ObjectMotionState::setRigidBody(btRigidBody* body) {
// give the body a (void*) back-pointer to this ObjectMotionState // give the body a (void*) back-pointer to this ObjectMotionState
if (_body != body) { if (_body != body) {

View file

@ -18,7 +18,7 @@
#include <EntityItem.h> #include <EntityItem.h>
#include "ContactInfo.h" #include "ContactInfo.h"
#include "ShapeInfo.h" #include "ShapeManager.h"
enum MotionType { enum MotionType {
MOTION_TYPE_STATIC, // no motion MOTION_TYPE_STATIC, // no motion
@ -46,6 +46,7 @@ const uint32_t OUTGOING_DIRTY_PHYSICS_FLAGS = EntityItem::DIRTY_POSITION | Entit
class OctreeEditPacketSender; class OctreeEditPacketSender;
class PhysicsEngine;
extern const int MAX_NUM_NON_MOVING_UPDATES; extern const int MAX_NUM_NON_MOVING_UPDATES;
@ -56,18 +57,18 @@ public:
// ObjectMotionState context. // ObjectMotionState context.
static void setWorldOffset(const glm::vec3& offset); static void setWorldOffset(const glm::vec3& offset);
static const glm::vec3& getWorldOffset(); static const glm::vec3& getWorldOffset();
static void setWorldSimulationStep(uint32_t step); static void setWorldSimulationStep(uint32_t step);
static void setShapeManager(ShapeManager* shapeManager); static uint32_t getWorldSimulationStep();
static void setShapeManager(ShapeManager* manager);
static ShapeManager* getShapeManager(); static ShapeManager* getShapeManager();
ObjectMotionState(btCollisionShape* shape); ObjectMotionState(btCollisionShape* shape);
~ObjectMotionState(); ~ObjectMotionState();
void measureBodyAcceleration(); void handleEasyChanges(uint32_t flags);
void resetMeasuredBodyAcceleration(); void handleHardAndEasyChanges(uint32_t flags, PhysicsEngine* engine);
void handleEasyChanges();
void handleHardAndEasyChanges();
virtual void updateBodyMaterialProperties(); virtual void updateBodyMaterialProperties();
virtual void updateBodyVelocities(); virtual void updateBodyVelocities();
@ -82,7 +83,7 @@ public:
void setBodyAngularVelocity(const glm::vec3& velocity) const; void setBodyAngularVelocity(const glm::vec3& velocity) const;
void setBodyGravity(const glm::vec3& gravity) const; void setBodyGravity(const glm::vec3& gravity) const;
glm::vec3 getBodyVelocity() const; glm::vec3 getBodyLinearVelocity() const;
glm::vec3 getBodyAngularVelocity() const; glm::vec3 getBodyAngularVelocity() const;
virtual uint32_t getIncomingDirtyFlags() const = 0; virtual uint32_t getIncomingDirtyFlags() const = 0;
@ -93,6 +94,8 @@ public:
btCollisionShape* getShape() const { return _shape; } btCollisionShape* getShape() const { return _shape; }
btRigidBody* getRigidBody() const { return _body; } btRigidBody* getRigidBody() const { return _body; }
void releaseShape();
virtual bool isMoving() const = 0; virtual bool isMoving() const = 0;
// These pure virtual methods must be implemented for each MotionState type // These pure virtual methods must be implemented for each MotionState type
@ -103,7 +106,7 @@ public:
virtual float getObjectLinearDamping() const = 0; virtual float getObjectLinearDamping() const = 0;
virtual float getObjectAngularDamping() const = 0; virtual float getObjectAngularDamping() const = 0;
virtual const glm::vec3& getObjectPosition() const = 0; virtual glm::vec3 getObjectPosition() const = 0;
virtual const glm::quat& getObjectRotation() const = 0; virtual const glm::quat& getObjectRotation() const = 0;
virtual const glm::vec3& getObjectLinearVelocity() const = 0; virtual const glm::vec3& getObjectLinearVelocity() const = 0;
virtual const glm::vec3& getObjectAngularVelocity() const = 0; virtual const glm::vec3& getObjectAngularVelocity() const = 0;
@ -112,6 +115,7 @@ public:
friend class PhysicsEngine; friend class PhysicsEngine;
protected: protected:
virtual void setMotionType(MotionType motionType);
void setRigidBody(btRigidBody* body); void setRigidBody(btRigidBody* body);
MotionStateType _type = MOTION_STATE_TYPE_UNKNOWN; // type of MotionState MotionStateType _type = MOTION_STATE_TYPE_UNKNOWN; // type of MotionState
@ -121,9 +125,7 @@ protected:
btRigidBody* _body; btRigidBody* _body;
float _mass; float _mass;
uint32_t _lastSimulationStep; uint32_t _lastKinematicStep;
glm::vec3 _lastVelocity;
glm::vec3 _measuredAcceleration;
}; };
#endif // hifi_ObjectMotionState_h #endif // hifi_ObjectMotionState_h

View file

@ -9,13 +9,15 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
#include "EntityMotionState.h"
#include "PhysicalEntitySimulation.h" #include "PhysicalEntitySimulation.h"
#include "PhysicsEngine.h" #include "PhysicsEngine.h"
#include "PhysicsHelpers.h" #include "PhysicsHelpers.h"
#include "PhysicsLogging.h" #include "PhysicsLogging.h"
#include "ShapeInfoUtil.h" #include "ShapeInfoUtil.h"
#include "ShapeManager.h"
PhysicalEntitySimulation::PhysicalEntitySimulation() : PhysicalEntitySimulation::PhysicalEntitySimulation() {
} }
PhysicalEntitySimulation::~PhysicalEntitySimulation() { PhysicalEntitySimulation::~PhysicalEntitySimulation() {
@ -29,10 +31,10 @@ void PhysicalEntitySimulation::init(
assert(tree); assert(tree);
setEntityTree(tree); setEntityTree(tree);
assert(*physicsEngine); assert(physicsEngine);
_physicsEngine = physicsEngine; _physicsEngine = physicsEngine;
assert(*shapeManager); assert(shapeManager);
_shapeManager = shapeManager; _shapeManager = shapeManager;
assert(packetSender); assert(packetSender);
@ -44,26 +46,6 @@ void PhysicalEntitySimulation::updateEntitiesInternal(const quint64& now) {
// TODO: add back non-physical kinematic objects and step them forward here // TODO: add back non-physical kinematic objects and step them forward here
} }
void PhysicalEntitySimulation::sendOutgoingPackets() {
uint32_t numSubsteps = _physicsEngine->getNumSubsteps();
if (_lastNumSubstepsAtUpdateInternal != numSubsteps) {
_lastNumSubstepsAtUpdateInternal = numSubsteps;
SetOfMotionStates::iterator stateItr = _outgoingChanges.begin();
while (stateItr != _outgoingChanges.end()) {
EntityMotionState* state = *stateItr;
if (state->doesNotNeedToSendUpdate()) {
stateItr = _outgoingChanges.erase(stateItr);
} else if (state->shouldSendUpdate(numSubsteps)) {
state->sendUpdate(_entityPacketSender, numSubsteps);
++stateItr;
} else {
++stateItr;
}
}
}
}
void PhysicalEntitySimulation::addEntityInternal(EntityItem* entity) { void PhysicalEntitySimulation::addEntityInternal(EntityItem* entity) {
assert(entity); assert(entity);
void* physicsInfo = entity->getPhysicsInfo(); void* physicsInfo = entity->getPhysicsInfo();
@ -76,10 +58,9 @@ void PhysicalEntitySimulation::removeEntityInternal(EntityItem* entity) {
assert(entity); assert(entity);
void* physicsInfo = entity->getPhysicsInfo(); void* physicsInfo = entity->getPhysicsInfo();
if (physicsInfo) { if (physicsInfo) {
ObjectMotionState* motionState = static_cast<ObjectMotionState*>(physicsInfo); _pendingRemoves.insert(entity);
_pendingRemoves.insert(motionState);
} else { } else {
entity->_simulation = nullptr; clearEntitySimulation(entity);
} }
} }
@ -87,10 +68,9 @@ void PhysicalEntitySimulation::deleteEntityInternal(EntityItem* entity) {
assert(entity); assert(entity);
void* physicsInfo = entity->getPhysicsInfo(); void* physicsInfo = entity->getPhysicsInfo();
if (physicsInfo) { if (physicsInfo) {
ObjectMotionState* motionState = static_cast<ObjectMotionState*>(physicsInfo); _pendingRemoves.insert(entity);
_pendingRemoves.insert(motionState);
} else { } else {
entity->_simulation = nullptr; clearEntitySimulation(entity);
delete entity; delete entity;
} }
} }
@ -100,10 +80,9 @@ void PhysicalEntitySimulation::entityChangedInternal(EntityItem* entity) {
assert(entity); assert(entity);
void* physicsInfo = entity->getPhysicsInfo(); void* physicsInfo = entity->getPhysicsInfo();
if (physicsInfo) { if (physicsInfo) {
ObjectMotionState* motionState = static_cast<ObjectMotionState*>(physicsInfo); _pendingChanges.insert(entity);
_pendingChanges.insert(motionState);
} else { } else {
if (!entity->ignoreForCollisions()) { if (!entity->getIgnoreForCollisions()) {
// The intent is for this object to be in the PhysicsEngine. // The intent is for this object to be in the PhysicsEngine.
// Perhaps it's shape has changed and it can now be added? // Perhaps it's shape has changed and it can now be added?
_pendingAdds.insert(entity); _pendingAdds.insert(entity);
@ -130,14 +109,16 @@ void PhysicalEntitySimulation::clearEntitiesInternal() {
// TODO: we should probably wait to lock the _physicsEngine so we don't mess up data structures // TODO: we should probably wait to lock the _physicsEngine so we don't mess up data structures
// while it is in the middle of a simulation step. As it is, we're probably in shutdown mode // while it is in the middle of a simulation step. As it is, we're probably in shutdown mode
// anyway, so maybe the simulation was already properly shutdown? Cross our fingers... // anyway, so maybe the simulation was already properly shutdown? Cross our fingers...
SetOfMotionStates::const_iterator stateItr = _physicalEntities.begin();
_physicsEngine->deleteObjects(_physicalEntities);
for (auto stateItr : _physicalEntities) { for (auto stateItr : _physicalEntities) {
EntityMotionState motionState = static_cast<EntityMotionState*>(*stateItr); EntityMotionState* motionState = static_cast<EntityMotionState*>(&(*stateItr));
_physicsEngine->removeObjectFromBullet(motionState); EntityItem* entity = motionState->getEntity();
EntityItem* entity = motionState->_entity; entity->setPhysicsInfo(nullptr);
_entity->setPhysicsInfo(nullptr);
delete motionState; delete motionState;
} }
_physicalEntities.clear(); _physicalEntities.clear();
_pendingRemoves.clear(); _pendingRemoves.clear();
_pendingAdds.clear(); _pendingAdds.clear();
@ -149,13 +130,13 @@ void PhysicalEntitySimulation::clearEntitiesInternal() {
VectorOfMotionStates& PhysicalEntitySimulation::getObjectsToRemove() { VectorOfMotionStates& PhysicalEntitySimulation::getObjectsToRemove() {
_tempVector.clear(); _tempVector.clear();
for (auto entityItr : _pendingRemoves) { for (auto entityItr : _pendingRemoves) {
EntityItem* entity = *entityItr; EntityItem* entity = &(*entityItr);
_physicalEntities.remove(entity);
_pendingAdds.remove(entity); _pendingAdds.remove(entity);
_pendingChanges.remove(entity); _pendingChanges.remove(entity);
ObjectMotionState* motionState = static_cast<ObjectMotionState*>(entity->getPhysicsInfo()); EntityMotionState* motionState = static_cast<EntityMotionState*>(entity->getPhysicsInfo());
if (motionState) { if (motionState) {
_tempVector.push_back(motionState); _tempVector.push_back(motionState);
_physicalEntities.remove(motionState);
} }
} }
_pendingRemoves.clear(); _pendingRemoves.clear();
@ -176,15 +157,14 @@ VectorOfMotionStates& PhysicalEntitySimulation::getObjectsToAdd() {
if (shape) { if (shape) {
EntityMotionState* motionState = new EntityMotionState(shape, entity); EntityMotionState* motionState = new EntityMotionState(shape, entity);
entity->setPhysicsInfo(static_cast<void*>(motionState)); entity->setPhysicsInfo(static_cast<void*>(motionState));
motionState->setMass(entity->computeMass());
_physicalEntities.insert(motionState); _physicalEntities.insert(motionState);
_tempVector.push_back(motionState);
entityItr = _pendingAdds.erase(entityItr); entityItr = _pendingAdds.erase(entityItr);
// TODO: figure out how to get shapeInfo (or relevant info) to PhysicsEngine during add
//_physicsEngine->addObject(shapeInfo, motionState);
} else { } else {
++entityItr; ++entityItr;
} }
} }
_tempVector.push_back(motionState);
} }
return _tempVector; return _tempVector;
} }
@ -192,7 +172,7 @@ VectorOfMotionStates& PhysicalEntitySimulation::getObjectsToAdd() {
VectorOfMotionStates& PhysicalEntitySimulation::getObjectsToChange() { VectorOfMotionStates& PhysicalEntitySimulation::getObjectsToChange() {
_tempVector.clear(); _tempVector.clear();
for (auto entityItr : _pendingChanges) { for (auto entityItr : _pendingChanges) {
EntityItem* entity = *entityItr; EntityItem* entity = &(*entityItr);
ObjectMotionState* motionState = static_cast<ObjectMotionState*>(entity->getPhysicsInfo()); ObjectMotionState* motionState = static_cast<ObjectMotionState*>(entity->getPhysicsInfo());
if (motionState) { if (motionState) {
_tempVector.push_back(motionState); _tempVector.push_back(motionState);
@ -205,14 +185,32 @@ VectorOfMotionStates& PhysicalEntitySimulation::getObjectsToChange() {
void PhysicalEntitySimulation::handleOutgoingChanges(VectorOfMotionStates& motionStates) { void PhysicalEntitySimulation::handleOutgoingChanges(VectorOfMotionStates& motionStates) {
// walk the motionStates looking for those that correspond to entities // walk the motionStates looking for those that correspond to entities
for (auto stateItr : motionStates) { for (auto stateItr : motionStates) {
ObjectMotionState* state = *stateItr; ObjectMotionState* state = &(*stateItr);
if (state->getType() == MOTION_STATE_TYPE_ENTITY) { if (state->getType() == MOTION_STATE_TYPE_ENTITY) {
EntityMotionState* entityState = static_cast<EntityMotionState*>(state); EntityMotionState* entityState = static_cast<EntityMotionState*>(state);
_outgoingChanges.insert(entityState); _outgoingChanges.insert(entityState);
_entitiesToSort.insert(entityState->getEntityItem()); _entitiesToSort.insert(entityState->getEntity());
}
}
// send outgoing packets
uint32_t numSubsteps = _physicsEngine->getNumSubsteps();
if (_lastStepSendPackets != numSubsteps) {
_lastStepSendPackets = numSubsteps;
QSet<EntityMotionState*>::iterator stateItr = _outgoingChanges.begin();
while (stateItr != _outgoingChanges.end()) {
EntityMotionState* state = *stateItr;
if (state->doesNotNeedToSendUpdate()) {
stateItr = _outgoingChanges.erase(stateItr);
} else if (state->shouldSendUpdate(numSubsteps)) {
state->sendUpdate(_entityPacketSender, numSubsteps);
++stateItr;
} else {
++stateItr;
}
} }
} }
sendOutgoingPackets();
} }
void PhysicalEntitySimulation::bump(EntityItem* bumpEntity) { void PhysicalEntitySimulation::bump(EntityItem* bumpEntity) {

View file

@ -22,14 +22,16 @@
#include "PhysicsTypedefs.h" #include "PhysicsTypedefs.h"
class EntityMotionState;
class PhysicsEngine; class PhysicsEngine;
class ShapeManager;
class PhysicalEntitySimulation :public EntitySimulation { class PhysicalEntitySimulation :public EntitySimulation {
public: public:
PhysicalEntitySimulation(); PhysicalEntitySimulation();
~PhysicalEntitySimulation(); ~PhysicalEntitySimulation();
void init(EntityTree* tree, PhysicsEngine* engine, EntityEditPacketSender* packetSender); void init(EntityTree* tree, PhysicsEngine* engine, ShapeManager* shapeManager, EntityEditPacketSender* packetSender);
// overrides for EntitySimulation // overrides for EntitySimulation
void updateEntitiesInternal(const quint64& now); void updateEntitiesInternal(const quint64& now);
@ -64,7 +66,7 @@ private:
PhysicsEngine* _physicsEngine = nullptr; PhysicsEngine* _physicsEngine = nullptr;
EntityEditPacketSender* _entityPacketSender = nullptr; EntityEditPacketSender* _entityPacketSender = nullptr;
uint32_t _lastNumSubstepsAtUpdateInternal = 0; uint32_t _lastStepSendPackets = 0;
}; };
#endif // hifi_PhysicalEntitySimulation_h #endif // hifi_PhysicalEntitySimulation_h

View file

@ -68,11 +68,26 @@ void PhysicsEngine::removeObjects(VectorOfMotionStates& objects) {
btRigidBody* body = object->getRigidBody(); btRigidBody* body = object->getRigidBody();
_dynamicsWorld->removeRigidBody(body); _dynamicsWorld->removeRigidBody(body);
removeContacts(object);
// NOTE: setRigidBody() modifies body->m_userPointer so we should clear the MotionState's body BEFORE deleting it. // NOTE: setRigidBody() modifies body->m_userPointer so we should clear the MotionState's body BEFORE deleting it.
object->setRigidBody(nullptr); object->setRigidBody(nullptr);
delete body; delete body;
object->releaseShape();
}
}
void PhysicsEngine::deleteObjects(SetOfMotionStates& objects) {
for (auto object : objects) {
assert(object);
btRigidBody* body = object->getRigidBody();
_dynamicsWorld->removeRigidBody(body);
removeContacts(object); removeContacts(object);
// NOTE: setRigidBody() modifies body->m_userPointer so we should clear the MotionState's body BEFORE deleting it.
object->setRigidBody(nullptr);
delete body;
object->releaseShape(); object->releaseShape();
} }
} }
@ -151,6 +166,7 @@ void PhysicsEngine::stepSimulation() {
} }
void PhysicsEngine::doOwnershipInfection(const btCollisionObject* objectA, const btCollisionObject* objectB) { void PhysicsEngine::doOwnershipInfection(const btCollisionObject* objectA, const btCollisionObject* objectB) {
/* TODO: Andrew to make this work for ObjectMotionState
BT_PROFILE("ownershipInfection"); BT_PROFILE("ownershipInfection");
assert(objectA); assert(objectA);
assert(objectB); assert(objectB);
@ -184,6 +200,7 @@ void PhysicsEngine::doOwnershipInfection(const btCollisionObject* objectA, const
a->setShouldClaimSimulationOwnership(true); a->setShouldClaimSimulationOwnership(true);
} }
} }
*/
} }
void PhysicsEngine::computeCollisionEvents() { void PhysicsEngine::computeCollisionEvents() {
@ -215,7 +232,13 @@ void PhysicsEngine::computeCollisionEvents() {
doOwnershipInfection(objectA, objectB); doOwnershipInfection(objectA, objectB);
} }
} }
fireCollisionEvents();
++_numContactFrames;
}
void PhysicsEngine::fireCollisionEvents() {
/* TODO: Andrew to make this work for ObjectMotionStates
const uint32_t CONTINUE_EVENT_FILTER_FREQUENCY = 10; const uint32_t CONTINUE_EVENT_FILTER_FREQUENCY = 10;
// scan known contacts and trigger events // scan known contacts and trigger events
@ -253,14 +276,14 @@ void PhysicsEngine::computeCollisionEvents() {
++contactItr; ++contactItr;
} }
} }
++_numContactFrames; */
} }
VectorOfMotionStates& PhysicsEngine::getOutgoingChanges() { VectorOfMotionStates& PhysicsEngine::getOutgoingChanges() {
BT_PROFILE("copyOutgoingChanges"); BT_PROFILE("copyOutgoingChanges");
_dynamicsWorld.synchronizeMotionStates(); _dynamicsWorld->synchronizeMotionStates();
_hasOutgoingChanges = false; _hasOutgoingChanges = false;
return _dynamicsWorld.getChangedMotionStates(); return _dynamicsWorld->getChangedMotionStates();
} }
void PhysicsEngine::dumpStatsIfNecessary() { void PhysicsEngine::dumpStatsIfNecessary() {
@ -287,7 +310,9 @@ void PhysicsEngine::addObject(ObjectMotionState* 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 = nullptr; btRigidBody* body = nullptr;
switch(motionState->computeObjectMotionType()) { MotionType motionType = motionState->computeObjectMotionType();
motionState->setMotionType(motionType);
switch(motionType) {
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);
@ -330,11 +355,50 @@ void PhysicsEngine::addObject(ObjectMotionState* motionState) {
motionState->updateBodyMaterialProperties(); motionState->updateBodyMaterialProperties();
_dynamicsWorld->addRigidBody(body); _dynamicsWorld->addRigidBody(body);
motionState->resetMeasuredBodyAcceleration();
} }
/* TODO: convert bump() to take an ObjectMotionState. void PhysicsEngine::bump(ObjectMotionState* object) {
* Expose SimulationID to ObjectMotionState*/ /* TODO: Andrew to implement this
// If this node is doing something like deleting an entity, scan for contacts involving the
// entity. For each found, flag the other entity involved as being simulated by this node.
int numManifolds = _collisionDispatcher->getNumManifolds();
for (int i = 0; i < numManifolds; ++i) {
btPersistentManifold* contactManifold = _collisionDispatcher->getManifoldByIndexInternal(i);
if (contactManifold->getNumContacts() > 0) {
const btCollisionObject* objectA = static_cast<const btCollisionObject*>(contactManifold->getBody0());
const btCollisionObject* objectB = static_cast<const btCollisionObject*>(contactManifold->getBody1());
if (objectA && objectB) {
void* a = objectA->getUserPointer();
void* b = objectB->getUserPointer();
if (a && b) {
EntityMotionState* entityMotionStateA = static_cast<EntityMotionState*>(a);
EntityMotionState* entityMotionStateB = static_cast<EntityMotionState*>(b);
EntityItem* entityA = entityMotionStateA ? entityMotionStateA->getEntity() : nullptr;
EntityItem* entityB = entityMotionStateB ? entityMotionStateB->getEntity() : nullptr;
if (entityA && entityB) {
if (entityA == bumpEntity) {
entityMotionStateB->setShouldClaimSimulationOwnership(true);
if (!objectB->isActive()) {
objectB->setActivationState(ACTIVE_TAG);
}
}
if (entityB == bumpEntity) {
entityMotionStateA->setShouldClaimSimulationOwnership(true);
if (!objectA->isActive()) {
objectA->setActivationState(ACTIVE_TAG);
}
}
}
}
}
}
}
*/
}
/*
// TODO: convert bump() to take an ObjectMotionState.
// Expose SimulationID to ObjectMotionState
void PhysicsEngine::bump(EntityItem* bumpEntity) { void PhysicsEngine::bump(EntityItem* bumpEntity) {
// If this node is doing something like deleting an entity, scan for contacts involving the // If this node is doing something like deleting an entity, scan for contacts involving the
// entity. For each found, flag the other entity involved as being simulated by this node. // entity. For each found, flag the other entity involved as being simulated by this node.
@ -371,58 +435,13 @@ void PhysicsEngine::bump(EntityItem* bumpEntity) {
} }
} }
} }
*/
void PhysicsEngine::removeRigidBody(btRigidBody* body) { void PhysicsEngine::removeRigidBody(btRigidBody* body) {
// pull body out of physics engine // pull body out of physics engine
_dynamicsWorld->removeRigidBody(body); _dynamicsWorld->removeRigidBody(body);
} }
void PhysicsEngine::addRigidBody(btRigidBody* body, MotionType motionType, float mass) {
switch (motionType) {
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 & EntityItem::DIRTY_MASS)) {
// always update mass properties when going dynamic (unless it's already been done above)
btVector3 inertia(0.0f, 0.0f, 0.0f);
body->getCollisionShape()->calculateLocalInertia(mass, inertia);
body->setMassProps(mass, inertia);
body->updateInertiaTensor();
}
body->forceActivationState(ACTIVE_TAG);
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);
body->setMassProps(0.0f, btVector3(0.0f, 0.0f, 0.0f));
body->updateInertiaTensor();
body->setLinearVelocity(btVector3(0.0f, 0.0f, 0.0f));
body->setAngularVelocity(btVector3(0.0f, 0.0f, 0.0f));
break;
}
}
_dynamicsWorld->addRigidBody(body);
body->activate();
}
void PhysicsEngine::setCharacterController(DynamicCharacterController* character) { void PhysicsEngine::setCharacterController(DynamicCharacterController* character) {
if (_characterController != character) { if (_characterController != character) {
if (_characterController) { if (_characterController) {

View file

@ -53,11 +53,13 @@ public:
/// process queue of changed from external sources /// process queue of changed from external sources
void removeObjects(VectorOfMotionStates& objects); void removeObjects(VectorOfMotionStates& objects);
void deleteObjects(SetOfMotionStates& objects);
void addObjects(VectorOfMotionStates& objects); void addObjects(VectorOfMotionStates& objects);
void changeObjects(VectorOfMotionStates& objects); void changeObjects(VectorOfMotionStates& objects);
void stepSimulation(); void stepSimulation();
void computeCollisionEvents(); void computeCollisionEvents();
void fireCollisionEvents();
bool hasOutgoingChanges() const { return _hasOutgoingChanges; } bool hasOutgoingChanges() const { return _hasOutgoingChanges; }
VectorOfMotionStates& getOutgoingChanges(); VectorOfMotionStates& getOutgoingChanges();
@ -71,7 +73,11 @@ public:
/// \param motionState pointer to Object's MotionState /// \param motionState pointer to Object's MotionState
/// \return true if Object added /// \return true if Object added
void addObject(const ShapeInfo& shapeInfo, btCollisionShape* shape, ObjectMotionState* motionState); void addObject(ObjectMotionState* motionState);
void bump(ObjectMotionState* motionState);
void removeRigidBody(btRigidBody* body);
void setCharacterController(DynamicCharacterController* character); void setCharacterController(DynamicCharacterController* character);

View file

@ -17,6 +17,7 @@
#include <LinearMath/btQuickprof.h> #include <LinearMath/btQuickprof.h>
#include "ObjectMotionState.h"
#include "ThreadSafeDynamicsWorld.h" #include "ThreadSafeDynamicsWorld.h"
ThreadSafeDynamicsWorld::ThreadSafeDynamicsWorld( ThreadSafeDynamicsWorld::ThreadSafeDynamicsWorld(
@ -95,7 +96,7 @@ void ThreadSafeDynamicsWorld::synchronizeMotionStates() {
btRigidBody* body = btRigidBody::upcast(colObj); btRigidBody* body = btRigidBody::upcast(colObj);
if (body) { if (body) {
synchronizeSingleMotionState(body); synchronizeSingleMotionState(body);
_changedMotionStates.push_back(body->getMotionState()); _changedMotionStates.push_back(static_cast<ObjectMotionState*>(body->getMotionState()));
} }
} }
} else { } else {
@ -104,7 +105,7 @@ void ThreadSafeDynamicsWorld::synchronizeMotionStates() {
btRigidBody* body = m_nonStaticRigidBodies[i]; btRigidBody* body = m_nonStaticRigidBodies[i];
if (body->isActive()) { if (body->isActive()) {
synchronizeSingleMotionState(body); synchronizeSingleMotionState(body);
_changedMotionStates.push_back(body->getMotionState()); _changedMotionStates.push_back(static_cast<ObjectMotionState*>(body->getMotionState()));
} }
} }
} }

View file

@ -18,6 +18,7 @@
#ifndef hifi_ThreadSafeDynamicsWorld_h #ifndef hifi_ThreadSafeDynamicsWorld_h
#define hifi_ThreadSafeDynamicsWorld_h #define hifi_ThreadSafeDynamicsWorld_h
#include <BulletDynamics/Dynamics/btRigidBody.h>
#include <BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h> #include <BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h>
#include "PhysicsTypedefs.h" #include "PhysicsTypedefs.h"
@ -34,13 +35,14 @@ public:
// virtual overrides from btDiscreteDynamicsWorld // virtual overrides from btDiscreteDynamicsWorld
int stepSimulation( btScalar timeStep, int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.)); int stepSimulation( btScalar timeStep, int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.));
void synchronizeMotionStates();
// btDiscreteDynamicsWorld::m_localTime is the portion of real-time that has not yet been simulated // btDiscreteDynamicsWorld::m_localTime is the portion of real-time that has not yet been simulated
// but is used for MotionState::setWorldTransform() extrapolation (a feature that Bullet uses to provide // but is used for MotionState::setWorldTransform() extrapolation (a feature that Bullet uses to provide
// smoother rendering of objects when the physics simulation loop is ansynchronous to the render loop). // smoother rendering of objects when the physics simulation loop is ansynchronous to the render loop).
float getLocalTimeAccumulation() const { return m_localTime; } float getLocalTimeAccumulation() const { return m_localTime; }
VectorOfMotionStates& getChangedMotionStates() const { return _changedMotionStates; } VectorOfMotionStates& getChangedMotionStates() { return _changedMotionStates; }
private: private:
VectorOfMotionStates _changedMotionStates; VectorOfMotionStates _changedMotionStates;