mirror of
https://github.com/overte-org/overte.git
synced 2025-07-10 14:18:46 +02:00
PhysicsEngine is now an EntitySimulation
This commit is contained in:
parent
919214b7cb
commit
c9ea6885c1
11 changed files with 163 additions and 90 deletions
|
@ -2021,8 +2021,10 @@ void Application::init() {
|
||||||
connect(_myAvatar, &MyAvatar::transformChanged, this, &Application::updateMyAvatarTransform);
|
connect(_myAvatar, &MyAvatar::transformChanged, this, &Application::updateMyAvatarTransform);
|
||||||
|
|
||||||
#ifdef USE_BULLET_PHYSICS
|
#ifdef USE_BULLET_PHYSICS
|
||||||
// _physicsEngine.initSafe(_entities.getTree());
|
EntityTree* tree = _entities.getTree();
|
||||||
// _entities.getTree()->setSimulation(&_physicsEngine);
|
_physicsEngine.setEntityTree(tree);
|
||||||
|
tree->setSimulation(&_physicsEngine);
|
||||||
|
_physicsEngine.init();
|
||||||
#endif // USE_BULLET_PHYSICS
|
#endif // USE_BULLET_PHYSICS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -504,7 +504,7 @@ private:
|
||||||
ViewFrustum _sharedVoxelSystemViewFrustum;
|
ViewFrustum _sharedVoxelSystemViewFrustum;
|
||||||
|
|
||||||
#ifdef USE_BULLET_PHYSICS
|
#ifdef USE_BULLET_PHYSICS
|
||||||
ThreadSafePhysicsEngine _physicsEngine;
|
PhysicsEngine _physicsEngine;
|
||||||
#endif // USE_BULLET_PHYSICS
|
#endif // USE_BULLET_PHYSICS
|
||||||
|
|
||||||
EntityTreeRenderer _entities;
|
EntityTreeRenderer _entities;
|
||||||
|
|
|
@ -9,55 +9,12 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
#include <EntityTree.h>
|
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
#include <ThreadSafeDynamicsWorld.h>
|
|
||||||
|
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
#include "world.h"
|
#include "world.h"
|
||||||
#include "Physics.h"
|
#include "Physics.h"
|
||||||
|
|
||||||
// DynamicsImpl is an implementation of ThreadSafeDynamicsWorld that knows how to lock an EntityTree
|
|
||||||
class DynamicsImpl : public ThreadSafeDynamicsWorld {
|
|
||||||
public:
|
|
||||||
DynamicsImpl(
|
|
||||||
btDispatcher* dispatcher,
|
|
||||||
btBroadphaseInterface* pairCache,
|
|
||||||
btConstraintSolver* constraintSolver,
|
|
||||||
btCollisionConfiguration* collisionConfiguration,
|
|
||||||
EntityTree* entities)
|
|
||||||
: ThreadSafeDynamicsWorld(dispatcher, pairCache, constraintSolver, collisionConfiguration), _entities(entities) {
|
|
||||||
assert(entities);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool tryLock() {
|
|
||||||
// wait for lock
|
|
||||||
_entities->lockForRead();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void unlock() {
|
|
||||||
_entities->unlock();
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
EntityTree* _entities;
|
|
||||||
};
|
|
||||||
|
|
||||||
ThreadSafePhysicsEngine::ThreadSafePhysicsEngine(const glm::vec3& offset) : PhysicsEngine(offset) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void ThreadSafePhysicsEngine::initSafe(EntityTree* entities) {
|
|
||||||
assert(!_dynamicsWorld); // only call this once
|
|
||||||
assert(entities);
|
|
||||||
_collisionConfig = new btDefaultCollisionConfiguration();
|
|
||||||
_collisionDispatcher = new btCollisionDispatcher(_collisionConfig);
|
|
||||||
_broadphaseFilter = new btDbvtBroadphase();
|
|
||||||
_constraintSolver = new btSequentialImpulseConstraintSolver;
|
|
||||||
// ThreadSafePhysicsEngine gets a DynamicsImpl, which derives from ThreadSafeDynamicsWorld
|
|
||||||
_dynamicsWorld = new DynamicsImpl(_collisionDispatcher, _broadphaseFilter, _constraintSolver, _collisionConfig, entities);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Applies static friction: maxVelocity is the largest velocity for which there
|
// Applies static friction: maxVelocity is the largest velocity for which there
|
||||||
// there is friction, and strength is the amount of friction force applied to reduce
|
// there is friction, and strength is the amount of friction force applied to reduce
|
||||||
|
|
|
@ -12,20 +12,6 @@
|
||||||
#ifndef hifi_Physics_h
|
#ifndef hifi_Physics_h
|
||||||
#define hifi_Physics_h
|
#define hifi_Physics_h
|
||||||
|
|
||||||
#include <PhysicsEngine.h>
|
|
||||||
|
|
||||||
class EntityTree;
|
|
||||||
|
|
||||||
class ThreadSafePhysicsEngine : public PhysicsEngine {
|
|
||||||
public:
|
|
||||||
ThreadSafePhysicsEngine(const glm::vec3& offset);
|
|
||||||
|
|
||||||
// virtual override from PhysicsEngine
|
|
||||||
void init() { assert(false); } // call initSafe() instead
|
|
||||||
|
|
||||||
void initSafe(EntityTree* entities);
|
|
||||||
};
|
|
||||||
|
|
||||||
void applyStaticFriction(float deltaTime, glm::vec3& velocity, float maxVelocity, float strength);
|
void applyStaticFriction(float deltaTime, glm::vec3& velocity, float maxVelocity, float strength);
|
||||||
void applyDamping(float deltaTime, glm::vec3& velocity, float linearStrength, float squaredStrength);
|
void applyDamping(float deltaTime, glm::vec3& velocity, float linearStrength, float squaredStrength);
|
||||||
|
|
||||||
|
|
|
@ -35,8 +35,6 @@ 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() { };
|
||||||
|
|
||||||
class EntityMotionState;
|
|
||||||
|
|
||||||
/// 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
|
||||||
/// one directly, instead you must only construct one of it's derived classes with additional features.
|
/// one directly, instead you must only construct one of it's derived classes with additional features.
|
||||||
|
@ -303,9 +301,10 @@ public:
|
||||||
void clearUpdateFlags() { _updateFlags = 0; }
|
void clearUpdateFlags() { _updateFlags = 0; }
|
||||||
|
|
||||||
void* getPhysicsInfo() const { return _physicsInfo; }
|
void* getPhysicsInfo() const { return _physicsInfo; }
|
||||||
|
void setPhysicsInfo(void* data) { _physicsInfo = data; }
|
||||||
SimulationState getSimulationState() const { return _simulationState; }
|
SimulationState getSimulationState() const { return _simulationState; }
|
||||||
|
|
||||||
void setSimulationState(SimulationState state) { _simulationState = state; }
|
void setSimulationState(SimulationState state) { _simulationState = state; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
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
|
||||||
|
@ -349,8 +348,8 @@ protected:
|
||||||
void setRadius(float value);
|
void setRadius(float value);
|
||||||
|
|
||||||
AACubeShape _collisionShape;
|
AACubeShape _collisionShape;
|
||||||
void* _physicsInfo;
|
void* _physicsInfo; // only set by EntitySimulation
|
||||||
SimulationState _simulationState; // only set by EntityTree
|
SimulationState _simulationState; // only set by EntitySimulation
|
||||||
|
|
||||||
// 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
|
||||||
// data structures. It is the responsibility of the EntityTree to relay changes entity and clear flags.
|
// data structures. It is the responsibility of the EntityTree to relay changes entity and clear flags.
|
||||||
|
|
|
@ -154,9 +154,9 @@ void SimpleEntitySimulation::updateMortalEntities(quint64 now, QSet<EntityItem*>
|
||||||
item_itr = _mortalEntities.erase(item_itr);
|
item_itr = _mortalEntities.erase(item_itr);
|
||||||
entity->setSimulationState(EntityItem::Static);
|
entity->setSimulationState(EntityItem::Static);
|
||||||
} else {
|
} else {
|
||||||
// check to see if this entity is no longer moving
|
|
||||||
EntityItem::SimulationState newState = entity->computeSimulationState();
|
EntityItem::SimulationState newState = entity->computeSimulationState();
|
||||||
if (newState != EntityItem::Mortal) {
|
if (newState != EntityItem::Mortal) {
|
||||||
|
// check to see if this entity is moving
|
||||||
if (newState == EntityItem::Moving) {
|
if (newState == EntityItem::Moving) {
|
||||||
entity->update(now);
|
entity->update(now);
|
||||||
_movingEntities.push_back(entity);
|
_movingEntities.push_back(entity);
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
#ifdef USE_BULLET_PHYSICS
|
#ifdef USE_BULLET_PHYSICS
|
||||||
#include "CustomMotionState.h"
|
#include "CustomMotionState.h"
|
||||||
#else // USE_BULLET_PHYSICS
|
#else // USE_BULLET_PHYSICS
|
||||||
|
|
||||||
// CustomMotionState stubbery
|
// CustomMotionState stubbery
|
||||||
class CustomMotionState {
|
class CustomMotionState {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -12,19 +12,116 @@
|
||||||
#include "PhysicsEngine.h"
|
#include "PhysicsEngine.h"
|
||||||
#ifdef USE_BULLET_PHYSICS
|
#ifdef USE_BULLET_PHYSICS
|
||||||
|
|
||||||
|
#include "EntityMotionState.h"
|
||||||
#include "ShapeInfoUtil.h"
|
#include "ShapeInfoUtil.h"
|
||||||
|
#include "ThreadSafeDynamicsWorld.h"
|
||||||
|
|
||||||
|
class EntityTree;
|
||||||
|
|
||||||
|
PhysicsEngine::PhysicsEngine(const glm::vec3& offset)
|
||||||
|
: _collisionConfig(NULL),
|
||||||
|
_collisionDispatcher(NULL),
|
||||||
|
_broadphaseFilter(NULL),
|
||||||
|
_constraintSolver(NULL),
|
||||||
|
_dynamicsWorld(NULL),
|
||||||
|
_originOffset(offset),
|
||||||
|
_voxels() {
|
||||||
|
}
|
||||||
|
|
||||||
PhysicsEngine::~PhysicsEngine() {
|
PhysicsEngine::~PhysicsEngine() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \param tree pointer to EntityTree which is stored internally
|
||||||
|
void PhysicsEngine::setEntityTree(EntityTree* tree) {
|
||||||
|
assert(_entityTree == NULL);
|
||||||
|
assert(tree);
|
||||||
|
_entityTree = tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \param[out] entitiesToDelete list of entities removed from simulation and should be deleted.
|
||||||
|
void PhysicsEngine::updateEntities(QSet<EntityItem*>& entitiesToDelete) {
|
||||||
|
// relay changes
|
||||||
|
QSet<EntityItem*>::iterator item_itr = _changedEntities.begin();
|
||||||
|
while (item_itr != _changedEntities.end()) {
|
||||||
|
EntityItem* entity = *item_itr;
|
||||||
|
void* physicsInfo = entity->getPhysicsInfo();
|
||||||
|
if (physicsInfo) {
|
||||||
|
CustomMotionState* motionState = static_cast<CustomMotionState*>(physicsInfo);
|
||||||
|
updateObject(motionState, entity->getUpdateFlags());
|
||||||
|
}
|
||||||
|
entity->clearUpdateFlags();
|
||||||
|
// TODO: implement this
|
||||||
|
++item_itr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// hunt for entities who have expired
|
||||||
|
// TODO: make EntityItems use an expiry to make this work faster.
|
||||||
|
item_itr = _mortalEntities.begin();
|
||||||
|
while (item_itr != _mortalEntities.end()) {
|
||||||
|
EntityItem* entity = *item_itr;
|
||||||
|
// always check to see if the lifetime has expired, for immortal entities this is always false
|
||||||
|
if (entity->lifetimeHasExpired()) {
|
||||||
|
qDebug() << "Lifetime has expired for entity:" << entity->getEntityItemID();
|
||||||
|
entitiesToDelete.insert(entity);
|
||||||
|
// remove entity from the list
|
||||||
|
item_itr = _mortalEntities.erase(item_itr);
|
||||||
|
} else if (entity->isImmortal()) {
|
||||||
|
// remove entity from the list
|
||||||
|
item_itr = _mortalEntities.erase(item_itr);
|
||||||
|
} else {
|
||||||
|
++item_itr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: check for entities that have exited the world boundaries
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \param entity pointer to EntityItem to add to the simulation
|
||||||
|
/// \sideeffect the EntityItem::_simulationState member may be updated to indicate membership to internal list
|
||||||
|
void PhysicsEngine::addEntity(EntityItem* entity) {
|
||||||
|
assert(entity);
|
||||||
|
void* physicsInfo = entity->getPhysicsInfo();
|
||||||
|
if (!physicsInfo) {
|
||||||
|
EntityMotionState* motionState = new EntityMotionState(entity);
|
||||||
|
entity->setPhysicsInfo(static_cast<void*>(motionState));
|
||||||
|
if (entity->isMortal()) {
|
||||||
|
_mortalEntities.insert(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \param entity pointer to EntityItem to removed from the simulation
|
||||||
|
/// \sideeffect the EntityItem::_simulationState member may be updated to indicate non-membership to internal list
|
||||||
|
void PhysicsEngine::removeEntity(EntityItem* entity) {
|
||||||
|
assert(entity);
|
||||||
|
void* physicsInfo = entity->getPhysicsInfo();
|
||||||
|
if (physicsInfo) {
|
||||||
|
CustomMotionState* motionState = static_cast<CustomMotionState*>(physicsInfo);
|
||||||
|
removeObject(motionState);
|
||||||
|
entity->setPhysicsInfo(NULL);
|
||||||
|
}
|
||||||
|
_mortalEntities.remove(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \param entity pointer to EntityItem to that may have changed in a way that would affect its simulation
|
||||||
|
void PhysicsEngine::entityChanged(EntityItem* entity) {
|
||||||
|
_changedEntities.insert(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PhysicsEngine::clearEntities() {
|
||||||
|
// For now we assume this would only be called on shutdown in which case we can just let the memory get lost.
|
||||||
|
}
|
||||||
|
|
||||||
// virtual
|
// virtual
|
||||||
void PhysicsEngine::init() {
|
void PhysicsEngine::init() {
|
||||||
|
// _entityTree should be set prior to the init() call
|
||||||
|
assert(_entityTree);
|
||||||
|
|
||||||
if (!_dynamicsWorld) {
|
if (!_dynamicsWorld) {
|
||||||
_collisionConfig = new btDefaultCollisionConfiguration();
|
_collisionConfig = new btDefaultCollisionConfiguration();
|
||||||
_collisionDispatcher = new btCollisionDispatcher(_collisionConfig);
|
_collisionDispatcher = new btCollisionDispatcher(_collisionConfig);
|
||||||
_broadphaseFilter = new btDbvtBroadphase();
|
_broadphaseFilter = new btDbvtBroadphase();
|
||||||
_constraintSolver = new btSequentialImpulseConstraintSolver;
|
_constraintSolver = new btSequentialImpulseConstraintSolver;
|
||||||
_dynamicsWorld = new btDiscreteDynamicsWorld(_collisionDispatcher, _broadphaseFilter, _constraintSolver, _collisionConfig);
|
_dynamicsWorld = new ThreadSafeDynamicsWorld(_collisionDispatcher, _broadphaseFilter, _constraintSolver, _collisionConfig, _entityTree);
|
||||||
|
|
||||||
// default gravity of the world is zero, so each object must specify its own gravity
|
// default gravity of the world is zero, so each object must specify its own gravity
|
||||||
// TODO: set up gravity zones
|
// TODO: set up gravity zones
|
||||||
|
|
|
@ -32,31 +32,53 @@ const uint32_t PHYSICS_UPDATE_EASY = PHYSICS_UPDATE_POSITION | PHYSICS_UPDATE_VE
|
||||||
|
|
||||||
#ifdef USE_BULLET_PHYSICS
|
#ifdef USE_BULLET_PHYSICS
|
||||||
|
|
||||||
|
#include <QSet>
|
||||||
#include <btBulletDynamicsCommon.h>
|
#include <btBulletDynamicsCommon.h>
|
||||||
|
|
||||||
|
#include <EntityItem.h>
|
||||||
|
#include <EntitySimulation.h>
|
||||||
|
|
||||||
#include "BulletUtil.h"
|
#include "BulletUtil.h"
|
||||||
#include "CustomMotionState.h"
|
#include "CustomMotionState.h"
|
||||||
#include "PositionHashKey.h"
|
#include "PositionHashKey.h"
|
||||||
#include "ShapeManager.h"
|
#include "ShapeManager.h"
|
||||||
|
#include "ThreadSafeDynamicsWorld.h"
|
||||||
#include "VoxelObject.h"
|
#include "VoxelObject.h"
|
||||||
|
|
||||||
const float HALF_SIMULATION_EXTENT = 512.0f; // meters
|
const float HALF_SIMULATION_EXTENT = 512.0f; // meters
|
||||||
|
|
||||||
class PhysicsEngine {
|
class PhysicsEngine : public EntitySimulation {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
PhysicsEngine(const glm::vec3& offset)
|
PhysicsEngine(const glm::vec3& offset);
|
||||||
: _collisionConfig(NULL),
|
|
||||||
_collisionDispatcher(NULL),
|
|
||||||
_broadphaseFilter(NULL),
|
|
||||||
_constraintSolver(NULL),
|
|
||||||
_dynamicsWorld(NULL),
|
|
||||||
_originOffset(offset),
|
|
||||||
_voxels() {
|
|
||||||
}
|
|
||||||
|
|
||||||
~PhysicsEngine();
|
~PhysicsEngine();
|
||||||
|
|
||||||
|
// override from EntitySimulation
|
||||||
|
/// \param tree pointer to EntityTree which is stored internally
|
||||||
|
void setEntityTree(EntityTree* tree);
|
||||||
|
|
||||||
|
// override from EntitySimulation
|
||||||
|
/// \param[out] entitiesToDelete list of entities removed from simulation and should be deleted.
|
||||||
|
void updateEntities(QSet<EntityItem*>& entitiesToDelete);
|
||||||
|
|
||||||
|
// override from EntitySimulation
|
||||||
|
/// \param entity pointer to EntityItem to add to the simulation
|
||||||
|
/// \sideeffect the EntityItem::_simulationState member may be updated to indicate membership to internal list
|
||||||
|
void addEntity(EntityItem* entity);
|
||||||
|
|
||||||
|
// override from EntitySimulation
|
||||||
|
/// \param entity pointer to EntityItem to removed from the simulation
|
||||||
|
/// \sideeffect the EntityItem::_simulationState member may be updated to indicate non-membership to internal list
|
||||||
|
void removeEntity(EntityItem* entity);
|
||||||
|
|
||||||
|
// override from EntitySimulation
|
||||||
|
/// \param entity pointer to EntityItem to that may have changed in a way that would affect its simulation
|
||||||
|
void entityChanged(EntityItem* entity);
|
||||||
|
|
||||||
|
// override from EntitySimulation
|
||||||
|
void clearEntities();
|
||||||
|
|
||||||
virtual void init();
|
virtual void init();
|
||||||
|
|
||||||
void stepSimulation();
|
void stepSimulation();
|
||||||
|
@ -99,12 +121,16 @@ protected:
|
||||||
btCollisionDispatcher* _collisionDispatcher;
|
btCollisionDispatcher* _collisionDispatcher;
|
||||||
btBroadphaseInterface* _broadphaseFilter;
|
btBroadphaseInterface* _broadphaseFilter;
|
||||||
btSequentialImpulseConstraintSolver* _constraintSolver;
|
btSequentialImpulseConstraintSolver* _constraintSolver;
|
||||||
btDiscreteDynamicsWorld* _dynamicsWorld;
|
ThreadSafeDynamicsWorld* _dynamicsWorld;
|
||||||
ShapeManager _shapeManager;
|
ShapeManager _shapeManager;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
glm::vec3 _originOffset;
|
glm::vec3 _originOffset;
|
||||||
btHashMap<PositionHashKey, VoxelObject> _voxels;
|
btHashMap<PositionHashKey, VoxelObject> _voxels;
|
||||||
|
|
||||||
|
// EntitySimulation stuff
|
||||||
|
QSet<EntityItem*> _changedEntities;
|
||||||
|
QSet<EntityItem*> _mortalEntities;
|
||||||
};
|
};
|
||||||
|
|
||||||
#else // USE_BULLET_PHYSICS
|
#else // USE_BULLET_PHYSICS
|
||||||
|
|
|
@ -15,21 +15,25 @@
|
||||||
* Copied and modified from btDiscreteDynamicsWorld.cpp by AndrewMeadows on 2014.11.12.
|
* Copied and modified from btDiscreteDynamicsWorld.cpp by AndrewMeadows on 2014.11.12.
|
||||||
* */
|
* */
|
||||||
|
|
||||||
|
#include <EntityTree.h>
|
||||||
|
|
||||||
#include "ThreadSafeDynamicsWorld.h"
|
#include "ThreadSafeDynamicsWorld.h"
|
||||||
|
|
||||||
ThreadSafeDynamicsWorld::ThreadSafeDynamicsWorld(
|
ThreadSafeDynamicsWorld::ThreadSafeDynamicsWorld(
|
||||||
btDispatcher* dispatcher,
|
btDispatcher* dispatcher,
|
||||||
btBroadphaseInterface* pairCache,
|
btBroadphaseInterface* pairCache,
|
||||||
btConstraintSolver* constraintSolver,
|
btConstraintSolver* constraintSolver,
|
||||||
btCollisionConfiguration* collisionConfiguration)
|
btCollisionConfiguration* collisionConfiguration,
|
||||||
|
EntityTree* entities)
|
||||||
: btDiscreteDynamicsWorld(dispatcher, pairCache, constraintSolver, collisionConfiguration) {
|
: btDiscreteDynamicsWorld(dispatcher, pairCache, constraintSolver, collisionConfiguration) {
|
||||||
|
assert(entities);
|
||||||
|
_entities = entities;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThreadSafeDynamicsWorld::synchronizeMotionStates() {
|
void ThreadSafeDynamicsWorld::synchronizeMotionStates() {
|
||||||
if (tryLock()) {
|
_entities->lockForWrite();
|
||||||
btDiscreteDynamicsWorld::synchronizeMotionStates();
|
btDiscreteDynamicsWorld::synchronizeMotionStates();
|
||||||
unlock();
|
_entities->unlock();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ThreadSafeDynamicsWorld::stepSimulation( btScalar timeStep, int maxSubSteps, btScalar fixedTimeStep) {
|
int ThreadSafeDynamicsWorld::stepSimulation( btScalar timeStep, int maxSubSteps, btScalar fixedTimeStep) {
|
||||||
|
@ -77,6 +81,8 @@ int ThreadSafeDynamicsWorld::stepSimulation( btScalar timeStep, int maxSubSteps,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We only sync motion states once at the end of all substeps.
|
||||||
|
// This is to avoid placing multiple, repeated thread locks on _entities.
|
||||||
synchronizeMotionStates();
|
synchronizeMotionStates();
|
||||||
clearForces();
|
clearForces();
|
||||||
return subSteps;
|
return subSteps;
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
|
|
||||||
#include <BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h>
|
#include <BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h>
|
||||||
|
|
||||||
|
class EntityTree;
|
||||||
|
|
||||||
ATTRIBUTE_ALIGNED16(class) ThreadSafeDynamicsWorld : public btDiscreteDynamicsWorld
|
ATTRIBUTE_ALIGNED16(class) ThreadSafeDynamicsWorld : public btDiscreteDynamicsWorld
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -29,16 +31,15 @@ public:
|
||||||
btDispatcher* dispatcher,
|
btDispatcher* dispatcher,
|
||||||
btBroadphaseInterface* pairCache,
|
btBroadphaseInterface* pairCache,
|
||||||
btConstraintSolver* constraintSolver,
|
btConstraintSolver* constraintSolver,
|
||||||
btCollisionConfiguration* collisionConfiguration);
|
btCollisionConfiguration* collisionConfiguration,
|
||||||
|
EntityTree* entities);
|
||||||
|
|
||||||
// virtual overrides of 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();
|
void synchronizeMotionStates();
|
||||||
|
|
||||||
/// \return true if lock succeeds
|
private:
|
||||||
virtual bool tryLock() = 0;
|
EntityTree* _entities;
|
||||||
|
|
||||||
virtual void unlock() = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_ThreadSafeDynamicsWorld_h
|
#endif // hifi_ThreadSafeDynamicsWorld_h
|
||||||
|
|
Loading…
Reference in a new issue