mirror of
https://github.com/lubosz/overte.git
synced 2025-04-24 09:23:17 +02:00
Merge pull request #7643 from AndrewMeadows/faster-bullet
faster Bullet kinematics
This commit is contained in:
commit
ea4da05cba
16 changed files with 80 additions and 88 deletions
|
@ -3444,7 +3444,7 @@ void Application::update(float deltaTime) {
|
|||
getEntities()->getTree()->withWriteLock([&] {
|
||||
PerformanceTimer perfTimer("handleOutgoingChanges");
|
||||
const VectorOfMotionStates& outgoingChanges = _physicsEngine->getOutgoingChanges();
|
||||
_entitySimulation.handleOutgoingChanges(outgoingChanges, Physics::getSessionUUID());
|
||||
_entitySimulation.handleOutgoingChanges(outgoingChanges);
|
||||
avatarManager->handleOutgoingChanges(outgoingChanges);
|
||||
});
|
||||
|
||||
|
@ -4540,10 +4540,7 @@ bool Application::acceptURL(const QString& urlString, bool defaultUpload) {
|
|||
}
|
||||
|
||||
void Application::setSessionUUID(const QUuid& sessionUUID) const {
|
||||
// HACK: until we swap the library dependency order between physics and entities
|
||||
// we cache the sessionID in two distinct places for physics.
|
||||
Physics::setSessionUUID(sessionUUID); // TODO: remove this one
|
||||
_physicsEngine->setSessionUUID(sessionUUID);
|
||||
Physics::setSessionUUID(sessionUUID);
|
||||
}
|
||||
|
||||
bool Application::askToSetAvatarUrl(const QString& url) {
|
||||
|
|
|
@ -94,7 +94,7 @@ void EntityMotionState::updateServerPhysicsVariables() {
|
|||
}
|
||||
|
||||
// virtual
|
||||
bool EntityMotionState::handleEasyChanges(uint32_t& flags) {
|
||||
void EntityMotionState::handleEasyChanges(uint32_t& flags) {
|
||||
assert(entityTreeIsLocked());
|
||||
updateServerPhysicsVariables();
|
||||
ObjectMotionState::handleEasyChanges(flags);
|
||||
|
@ -137,8 +137,6 @@ bool EntityMotionState::handleEasyChanges(uint32_t& flags) {
|
|||
if ((flags & Simulation::DIRTY_PHYSICS_ACTIVATION) && !_body->isActive()) {
|
||||
_body->activate();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -223,7 +221,6 @@ void EntityMotionState::setWorldTransform(const btTransform& worldTrans) {
|
|||
|
||||
if (_entity->getSimulatorID().isNull()) {
|
||||
_loopsWithoutOwner++;
|
||||
|
||||
if (_loopsWithoutOwner > LOOPS_FOR_SIMULATION_ORPHAN && usecTimestampNow() > _nextOwnershipBid) {
|
||||
upgradeOutgoingPriority(VOLUNTEER_SIMULATION_PRIORITY);
|
||||
}
|
||||
|
@ -255,11 +252,13 @@ btCollisionShape* EntityMotionState::computeNewShape() {
|
|||
return getShapeManager()->getShape(shapeInfo);
|
||||
}
|
||||
|
||||
bool EntityMotionState::isCandidateForOwnership(const QUuid& sessionID) const {
|
||||
bool EntityMotionState::isCandidateForOwnership() const {
|
||||
assert(_body);
|
||||
assert(_entity);
|
||||
assert(entityTreeIsLocked());
|
||||
return _outgoingPriority != 0 || sessionID == _entity->getSimulatorID() || _entity->actionDataNeedsTransmit();
|
||||
return _outgoingPriority != 0
|
||||
|| Physics::getSessionUUID() == _entity->getSimulatorID()
|
||||
|| _entity->actionDataNeedsTransmit();
|
||||
}
|
||||
|
||||
bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) {
|
||||
|
@ -384,7 +383,7 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) {
|
|||
return (fabsf(glm::dot(actualRotation, _serverRotation)) < MIN_ROTATION_DOT);
|
||||
}
|
||||
|
||||
bool EntityMotionState::shouldSendUpdate(uint32_t simulationStep, const QUuid& sessionID) {
|
||||
bool EntityMotionState::shouldSendUpdate(uint32_t simulationStep) {
|
||||
// NOTE: we expect _entity and _body to be valid in this context, since shouldSendUpdate() is only called
|
||||
// after doesNotNeedToSendUpdate() returns false and that call should return 'true' if _entity or _body are NULL.
|
||||
assert(_entity);
|
||||
|
@ -399,7 +398,7 @@ bool EntityMotionState::shouldSendUpdate(uint32_t simulationStep, const QUuid& s
|
|||
return true;
|
||||
}
|
||||
|
||||
if (_entity->getSimulatorID() != sessionID) {
|
||||
if (_entity->getSimulatorID() != Physics::getSessionUUID()) {
|
||||
// we don't own the simulation
|
||||
bool shouldBid = _outgoingPriority > 0 && // but we would like to own it and
|
||||
usecTimestampNow() > _nextOwnershipBid; // it is time to bid again
|
||||
|
@ -415,7 +414,7 @@ bool EntityMotionState::shouldSendUpdate(uint32_t simulationStep, const QUuid& s
|
|||
return remoteSimulationOutOfSync(simulationStep);
|
||||
}
|
||||
|
||||
void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, const QUuid& sessionID, uint32_t step) {
|
||||
void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_t step) {
|
||||
assert(_entity);
|
||||
assert(entityTreeIsLocked());
|
||||
|
||||
|
@ -514,9 +513,10 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, const Q
|
|||
// but we remember we do still own it... and rely on the server to tell us we don't
|
||||
properties.clearSimulationOwner();
|
||||
_outgoingPriority = 0;
|
||||
} else if (sessionID != _entity->getSimulatorID()) {
|
||||
} else if (Physics::getSessionUUID() != _entity->getSimulatorID()) {
|
||||
// we don't own the simulation for this entity yet, but we're sending a bid for it
|
||||
properties.setSimulationOwner(sessionID, glm::max<uint8_t>(_outgoingPriority, VOLUNTEER_SIMULATION_PRIORITY));
|
||||
properties.setSimulationOwner(Physics::getSessionUUID(),
|
||||
glm::max<uint8_t>(_outgoingPriority, VOLUNTEER_SIMULATION_PRIORITY));
|
||||
_nextOwnershipBid = now + USECS_BETWEEN_OWNERSHIP_BIDS;
|
||||
_outgoingPriority = 0; // reset outgoing priority whenever we bid
|
||||
} else if (_outgoingPriority != _entity->getSimulationPriority()) {
|
||||
|
@ -526,7 +526,7 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, const Q
|
|||
properties.clearSimulationOwner();
|
||||
} else {
|
||||
// we just need to change the priority
|
||||
properties.setSimulationOwner(sessionID, _outgoingPriority);
|
||||
properties.setSimulationOwner(Physics::getSessionUUID(), _outgoingPriority);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ public:
|
|||
virtual ~EntityMotionState();
|
||||
|
||||
void updateServerPhysicsVariables();
|
||||
virtual bool handleEasyChanges(uint32_t& flags) override;
|
||||
virtual void handleEasyChanges(uint32_t& flags) override;
|
||||
virtual bool handleHardAndEasyChanges(uint32_t& flags, PhysicsEngine* engine) override;
|
||||
|
||||
/// \return PhysicsMotionType based on params set in EntityItem
|
||||
|
@ -43,10 +43,10 @@ public:
|
|||
// this relays outgoing position/rotation to the EntityItem
|
||||
virtual void setWorldTransform(const btTransform& worldTrans) override;
|
||||
|
||||
bool isCandidateForOwnership(const QUuid& sessionID) const;
|
||||
bool isCandidateForOwnership() const;
|
||||
bool remoteSimulationOutOfSync(uint32_t simulationStep);
|
||||
bool shouldSendUpdate(uint32_t simulationStep, const QUuid& sessionID);
|
||||
void sendUpdate(OctreeEditPacketSender* packetSender, const QUuid& sessionID, uint32_t step);
|
||||
bool shouldSendUpdate(uint32_t simulationStep);
|
||||
void sendUpdate(OctreeEditPacketSender* packetSender, uint32_t step);
|
||||
|
||||
virtual uint32_t getIncomingDirtyFlags() override;
|
||||
virtual void clearIncomingDirtyFlags() override;
|
||||
|
|
|
@ -164,7 +164,7 @@ void ObjectMotionState::setRigidBody(btRigidBody* body) {
|
|||
}
|
||||
}
|
||||
|
||||
bool ObjectMotionState::handleEasyChanges(uint32_t& flags) {
|
||||
void ObjectMotionState::handleEasyChanges(uint32_t& flags) {
|
||||
if (flags & Simulation::DIRTY_POSITION) {
|
||||
btTransform worldTrans = _body->getWorldTransform();
|
||||
btVector3 newPosition = glmToBullet(getObjectPosition());
|
||||
|
@ -183,6 +183,10 @@ bool ObjectMotionState::handleEasyChanges(uint32_t& flags) {
|
|||
worldTrans.setRotation(newRotation);
|
||||
}
|
||||
_body->setWorldTransform(worldTrans);
|
||||
if (!(flags & HARD_DIRTY_PHYSICS_FLAGS) && _body->isStaticObject()) {
|
||||
// force activate static body so its Aabb is updated later
|
||||
_body->activate(true);
|
||||
}
|
||||
} else if (flags & Simulation::DIRTY_ROTATION) {
|
||||
btTransform worldTrans = _body->getWorldTransform();
|
||||
btQuaternion newRotation = glmToBullet(getObjectRotation());
|
||||
|
@ -192,6 +196,10 @@ bool ObjectMotionState::handleEasyChanges(uint32_t& flags) {
|
|||
}
|
||||
worldTrans.setRotation(newRotation);
|
||||
_body->setWorldTransform(worldTrans);
|
||||
if (!(flags & HARD_DIRTY_PHYSICS_FLAGS) && _body->isStaticObject()) {
|
||||
// force activate static body so its Aabb is updated later
|
||||
_body->activate(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & Simulation::DIRTY_LINEAR_VELOCITY) {
|
||||
|
@ -232,8 +240,6 @@ bool ObjectMotionState::handleEasyChanges(uint32_t& flags) {
|
|||
if (flags & Simulation::DIRTY_MASS) {
|
||||
updateBodyMassProperties();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ObjectMotionState::handleHardAndEasyChanges(uint32_t& flags, PhysicsEngine* engine) {
|
||||
|
|
|
@ -50,11 +50,12 @@ const uint32_t HARD_DIRTY_PHYSICS_FLAGS = (uint32_t)(Simulation::DIRTY_MOTION_TY
|
|||
Simulation::DIRTY_COLLISION_GROUP);
|
||||
const uint32_t EASY_DIRTY_PHYSICS_FLAGS = (uint32_t)(Simulation::DIRTY_TRANSFORM | Simulation::DIRTY_VELOCITIES |
|
||||
Simulation::DIRTY_MASS | Simulation::DIRTY_MATERIAL |
|
||||
Simulation::DIRTY_SIMULATOR_ID | Simulation::DIRTY_SIMULATION_OWNERSHIP_PRIORITY);
|
||||
Simulation::DIRTY_SIMULATOR_ID | Simulation::DIRTY_SIMULATION_OWNERSHIP_PRIORITY |
|
||||
Simulation::DIRTY_PHYSICS_ACTIVATION);
|
||||
|
||||
|
||||
// These are the set of incoming flags that the PhysicsEngine needs to hear about:
|
||||
const uint32_t DIRTY_PHYSICS_FLAGS = (uint32_t)(HARD_DIRTY_PHYSICS_FLAGS | EASY_DIRTY_PHYSICS_FLAGS |
|
||||
Simulation::DIRTY_PHYSICS_ACTIVATION);
|
||||
const uint32_t DIRTY_PHYSICS_FLAGS = (uint32_t)(HARD_DIRTY_PHYSICS_FLAGS | EASY_DIRTY_PHYSICS_FLAGS);
|
||||
|
||||
// These are the outgoing flags that the PhysicsEngine can affect:
|
||||
const uint32_t OUTGOING_DIRTY_PHYSICS_FLAGS = Simulation::DIRTY_TRANSFORM | Simulation::DIRTY_VELOCITIES;
|
||||
|
@ -80,7 +81,7 @@ public:
|
|||
ObjectMotionState(btCollisionShape* shape);
|
||||
~ObjectMotionState();
|
||||
|
||||
virtual bool handleEasyChanges(uint32_t& flags);
|
||||
virtual void handleEasyChanges(uint32_t& flags);
|
||||
virtual bool handleHardAndEasyChanges(uint32_t& flags, PhysicsEngine* engine);
|
||||
|
||||
void updateBodyMaterialProperties();
|
||||
|
|
|
@ -251,7 +251,7 @@ void PhysicalEntitySimulation::getObjectsToChange(VectorOfMotionStates& result)
|
|||
_pendingChanges.clear();
|
||||
}
|
||||
|
||||
void PhysicalEntitySimulation::handleOutgoingChanges(const VectorOfMotionStates& motionStates, const QUuid& sessionID) {
|
||||
void PhysicalEntitySimulation::handleOutgoingChanges(const VectorOfMotionStates& motionStates) {
|
||||
QMutexLocker lock(&_mutex);
|
||||
|
||||
// walk the motionStates looking for those that correspond to entities
|
||||
|
@ -261,7 +261,7 @@ void PhysicalEntitySimulation::handleOutgoingChanges(const VectorOfMotionStates&
|
|||
EntityMotionState* entityState = static_cast<EntityMotionState*>(state);
|
||||
EntityItemPointer entity = entityState->getEntity();
|
||||
assert(entity.get());
|
||||
if (entityState->isCandidateForOwnership(sessionID)) {
|
||||
if (entityState->isCandidateForOwnership()) {
|
||||
_outgoingChanges.insert(entityState);
|
||||
}
|
||||
_entitiesToSort.insert(entity);
|
||||
|
@ -272,7 +272,7 @@ void PhysicalEntitySimulation::handleOutgoingChanges(const VectorOfMotionStates&
|
|||
if (_lastStepSendPackets != numSubsteps) {
|
||||
_lastStepSendPackets = numSubsteps;
|
||||
|
||||
if (sessionID.isNull()) {
|
||||
if (Physics::getSessionUUID().isNull()) {
|
||||
// usually don't get here, but if so --> nothing to do
|
||||
_outgoingChanges.clear();
|
||||
return;
|
||||
|
@ -282,12 +282,12 @@ void PhysicalEntitySimulation::handleOutgoingChanges(const VectorOfMotionStates&
|
|||
QSet<EntityMotionState*>::iterator stateItr = _outgoingChanges.begin();
|
||||
while (stateItr != _outgoingChanges.end()) {
|
||||
EntityMotionState* state = *stateItr;
|
||||
if (!state->isCandidateForOwnership(sessionID)) {
|
||||
if (!state->isCandidateForOwnership()) {
|
||||
// prune
|
||||
stateItr = _outgoingChanges.erase(stateItr);
|
||||
} else if (state->shouldSendUpdate(numSubsteps, sessionID)) {
|
||||
} else if (state->shouldSendUpdate(numSubsteps)) {
|
||||
// update
|
||||
state->sendUpdate(_entityPacketSender, sessionID, numSubsteps);
|
||||
state->sendUpdate(_entityPacketSender, numSubsteps);
|
||||
++stateItr;
|
||||
} else {
|
||||
++stateItr;
|
||||
|
|
|
@ -54,7 +54,7 @@ public:
|
|||
void setObjectsToChange(const VectorOfMotionStates& objectsToChange);
|
||||
void getObjectsToChange(VectorOfMotionStates& result);
|
||||
|
||||
void handleOutgoingChanges(const VectorOfMotionStates& motionStates, const QUuid& sessionID);
|
||||
void handleOutgoingChanges(const VectorOfMotionStates& motionStates);
|
||||
void handleCollisionEvents(const CollisionEvents& collisionEvents);
|
||||
|
||||
EntityEditPacketSender* getPacketSender() { return _entityPacketSender; }
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
|
||||
PhysicsEngine::PhysicsEngine(const glm::vec3& offset) :
|
||||
_originOffset(offset),
|
||||
_sessionID(),
|
||||
_myAvatarController(nullptr) {
|
||||
}
|
||||
|
||||
|
@ -50,6 +49,13 @@ void PhysicsEngine::init() {
|
|||
// default gravity of the world is zero, so each object must specify its own gravity
|
||||
// TODO: set up gravity zones
|
||||
_dynamicsWorld->setGravity(btVector3(0.0f, 0.0f, 0.0f));
|
||||
|
||||
// By default Bullet will update the Aabb's of all objects every frame, even statics.
|
||||
// This can waste CPU cycles so we configure Bullet to only update ACTIVE objects here.
|
||||
// However, this means when a static object is moved we must manually update its Aabb
|
||||
// in order for its broadphase collision queries to work correctly. Look at how we use
|
||||
// _activeStaticBodies to track and update the Aabb's of moved static objects.
|
||||
_dynamicsWorld->setForceUpdateAllAabbs(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -189,12 +195,18 @@ VectorOfMotionStates PhysicsEngine::changeObjects(const VectorOfMotionStates& ob
|
|||
stillNeedChange.push_back(object);
|
||||
}
|
||||
} else if (flags & EASY_DIRTY_PHYSICS_FLAGS) {
|
||||
if (object->handleEasyChanges(flags)) {
|
||||
object->clearIncomingDirtyFlags();
|
||||
} else {
|
||||
stillNeedChange.push_back(object);
|
||||
}
|
||||
object->handleEasyChanges(flags);
|
||||
object->clearIncomingDirtyFlags();
|
||||
}
|
||||
if (object->getMotionType() == MOTION_TYPE_STATIC && object->isActive()) {
|
||||
_activeStaticBodies.push_back(object->getRigidBody());
|
||||
}
|
||||
}
|
||||
// active static bodies have changed (in an Easy way) and need their Aabbs updated
|
||||
// but we've configured Bullet to NOT update them automatically (for improved performance)
|
||||
// so we must do it ourselves
|
||||
for (size_t i = 0; i < _activeStaticBodies.size(); ++i) {
|
||||
_dynamicsWorld->updateSingleAabb(_activeStaticBodies[i]);
|
||||
}
|
||||
return stillNeedChange;
|
||||
}
|
||||
|
@ -286,20 +298,20 @@ void PhysicsEngine::doOwnershipInfection(const btCollisionObject* objectA, const
|
|||
ObjectMotionState* motionStateB = static_cast<ObjectMotionState*>(objectB->getUserPointer());
|
||||
|
||||
if (motionStateB &&
|
||||
((motionStateA && motionStateA->getSimulatorID() == _sessionID && !objectA->isStaticObject()) ||
|
||||
((motionStateA && motionStateA->getSimulatorID() == Physics::getSessionUUID() && !objectA->isStaticObject()) ||
|
||||
(objectA == characterObject))) {
|
||||
// NOTE: we might own the simulation of a kinematic object (A)
|
||||
// but we don't claim ownership of kinematic objects (B) based on collisions here.
|
||||
if (!objectB->isStaticOrKinematicObject() && motionStateB->getSimulatorID() != _sessionID) {
|
||||
if (!objectB->isStaticOrKinematicObject() && motionStateB->getSimulatorID() != Physics::getSessionUUID()) {
|
||||
quint8 priorityA = motionStateA ? motionStateA->getSimulationPriority() : PERSONAL_SIMULATION_PRIORITY;
|
||||
motionStateB->bump(priorityA);
|
||||
}
|
||||
} else if (motionStateA &&
|
||||
((motionStateB && motionStateB->getSimulatorID() == _sessionID && !objectB->isStaticObject()) ||
|
||||
((motionStateB && motionStateB->getSimulatorID() == Physics::getSessionUUID() && !objectB->isStaticObject()) ||
|
||||
(objectB == characterObject))) {
|
||||
// SIMILARLY: we might own the simulation of a kinematic object (B)
|
||||
// but we don't claim ownership of kinematic objects (A) based on collisions here.
|
||||
if (!objectA->isStaticOrKinematicObject() && motionStateA->getSimulatorID() != _sessionID) {
|
||||
if (!objectA->isStaticOrKinematicObject() && motionStateA->getSimulatorID() != Physics::getSessionUUID()) {
|
||||
quint8 priorityB = motionStateB ? motionStateB->getSimulationPriority() : PERSONAL_SIMULATION_PRIORITY;
|
||||
motionStateA->bump(priorityB);
|
||||
}
|
||||
|
@ -333,7 +345,7 @@ void PhysicsEngine::updateContactMap() {
|
|||
_contactMap[ContactKey(a, b)].update(_numContactFrames, contactManifold->getContactPoint(0));
|
||||
}
|
||||
|
||||
if (!_sessionID.isNull()) {
|
||||
if (!Physics::getSessionUUID().isNull()) {
|
||||
doOwnershipInfection(objectA, objectB);
|
||||
}
|
||||
}
|
||||
|
@ -388,6 +400,12 @@ const CollisionEvents& PhysicsEngine::getCollisionEvents() {
|
|||
|
||||
const VectorOfMotionStates& PhysicsEngine::getOutgoingChanges() {
|
||||
BT_PROFILE("copyOutgoingChanges");
|
||||
// Bullet will not deactivate static objects (it doesn't expect them to be active)
|
||||
// so we must deactivate them ourselves
|
||||
for (size_t i = 0; i < _activeStaticBodies.size(); ++i) {
|
||||
_activeStaticBodies[i]->forceActivationState(ISLAND_SLEEPING);
|
||||
}
|
||||
_activeStaticBodies.clear();
|
||||
_dynamicsWorld->synchronizeMotionStates();
|
||||
_hasOutgoingChanges = false;
|
||||
return _dynamicsWorld->getChangedMotionStates();
|
||||
|
|
|
@ -13,9 +13,9 @@
|
|||
#define hifi_PhysicsEngine_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
#include <QUuid>
|
||||
#include <QVector>
|
||||
#include <btBulletDynamicsCommon.h>
|
||||
#include <BulletCollision/CollisionDispatch/btGhostObject.h>
|
||||
|
||||
|
@ -41,7 +41,7 @@ public:
|
|||
};
|
||||
|
||||
typedef std::map<ContactKey, ContactInfo> ContactMap;
|
||||
typedef QVector<Collision> CollisionEvents;
|
||||
typedef std::vector<Collision> CollisionEvents;
|
||||
|
||||
class PhysicsEngine {
|
||||
public:
|
||||
|
@ -87,8 +87,6 @@ public:
|
|||
void removeAction(const QUuid actionID);
|
||||
void forEachAction(std::function<void(EntityActionPointer)> actor);
|
||||
|
||||
void setSessionUUID(const QUuid& sessionID) { _sessionID = sessionID; }
|
||||
|
||||
private:
|
||||
void addObjectToDynamicsWorld(ObjectMotionState* motionState);
|
||||
|
||||
|
@ -110,9 +108,9 @@ private:
|
|||
ContactMap _contactMap;
|
||||
CollisionEvents _collisionEvents;
|
||||
QHash<QUuid, EntityActionPointer> _objectActions;
|
||||
std::vector<btRigidBody*> _activeStaticBodies;
|
||||
|
||||
glm::vec3 _originOffset;
|
||||
QUuid _sessionID;
|
||||
|
||||
CharacterController* _myAvatarController;
|
||||
|
||||
|
@ -121,7 +119,6 @@ private:
|
|||
|
||||
bool _dumpNextStats = false;
|
||||
bool _hasOutgoingChanges = false;
|
||||
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<PhysicsEngine> PhysicsEnginePointer;
|
||||
|
|
|
@ -463,14 +463,6 @@ glm::vec2 getFacingDir2D(const glm::mat4& m) {
|
|||
}
|
||||
}
|
||||
|
||||
bool isNaN(glm::vec3 value) {
|
||||
return isNaN(value.x) || isNaN(value.y) || isNaN(value.z);
|
||||
}
|
||||
|
||||
bool isNaN(glm::quat value) {
|
||||
return isNaN(value.w) || isNaN(value.x) || isNaN(value.y) || isNaN(value.z);
|
||||
}
|
||||
|
||||
glm::mat4 orthoInverse(const glm::mat4& m) {
|
||||
glm::mat4 r = m;
|
||||
r[3] = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
|
|
|
@ -229,8 +229,8 @@ void generateBasisVectors(const glm::vec3& primaryAxis, const glm::vec3& seconda
|
|||
glm::vec2 getFacingDir2D(const glm::quat& rot);
|
||||
glm::vec2 getFacingDir2D(const glm::mat4& m);
|
||||
|
||||
bool isNaN(glm::vec3 value);
|
||||
bool isNaN(glm::quat value);
|
||||
inline bool isNaN(const glm::vec3& value) { return isNaN(value.x) || isNaN(value.y) || isNaN(value.z); }
|
||||
inline bool isNaN(const glm::quat& value) { return isNaN(value.w) || isNaN(value.x) || isNaN(value.y) || isNaN(value.z); }
|
||||
|
||||
glm::mat4 orthoInverse(const glm::mat4& m);
|
||||
|
||||
|
|
|
@ -51,10 +51,10 @@ const int16_t BULLET_COLLISION_GROUP_COLLISIONLESS = 1 << 14;
|
|||
const int16_t BULLET_COLLISION_MASK_DEFAULT = ~ BULLET_COLLISION_GROUP_COLLISIONLESS;
|
||||
|
||||
// STATIC does not collide with itself (as optimization of physics simulation)
|
||||
const int16_t BULLET_COLLISION_MASK_STATIC = ~ (BULLET_COLLISION_GROUP_COLLISIONLESS | BULLET_COLLISION_GROUP_STATIC);
|
||||
const int16_t BULLET_COLLISION_MASK_STATIC = ~ (BULLET_COLLISION_GROUP_COLLISIONLESS | BULLET_COLLISION_GROUP_KINEMATIC | BULLET_COLLISION_GROUP_STATIC);
|
||||
|
||||
const int16_t BULLET_COLLISION_MASK_DYNAMIC = BULLET_COLLISION_MASK_DEFAULT;
|
||||
const int16_t BULLET_COLLISION_MASK_KINEMATIC = BULLET_COLLISION_MASK_DEFAULT;
|
||||
const int16_t BULLET_COLLISION_MASK_KINEMATIC = BULLET_COLLISION_MASK_STATIC;
|
||||
|
||||
// MY_AVATAR does not collide with itself
|
||||
const int16_t BULLET_COLLISION_MASK_MY_AVATAR = ~(BULLET_COLLISION_GROUP_COLLISIONLESS | BULLET_COLLISION_GROUP_MY_AVATAR);
|
||||
|
|
|
@ -247,12 +247,6 @@ int getNthBit(unsigned char byte, int ordinal) {
|
|||
return ERROR_RESULT;
|
||||
}
|
||||
|
||||
bool isBetween(int64_t value, int64_t max, int64_t min) {
|
||||
return ((value <= max) && (value >= min));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void setSemiNibbleAt(unsigned char& byte, int bitIndex, int value) {
|
||||
//assert(value <= 3 && value >= 0);
|
||||
byte |= ((value & 3) << (6 - bitIndex)); // semi-nibbles store 00, 01, 10, or 11
|
||||
|
@ -260,12 +254,7 @@ void setSemiNibbleAt(unsigned char& byte, int bitIndex, int value) {
|
|||
|
||||
bool isInEnvironment(const char* environment) {
|
||||
char* environmentString = getenv("HIFI_ENVIRONMENT");
|
||||
|
||||
if (environmentString && strcmp(environmentString, environment) == 0) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return (environmentString && strcmp(environmentString, environment) == 0);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -632,10 +621,6 @@ void debug::checkDeadBeef(void* memoryVoid, int size) {
|
|||
assert(memcmp((unsigned char*)memoryVoid, DEADBEEF, std::min(size, DEADBEEF_SIZE)) != 0);
|
||||
}
|
||||
|
||||
bool isNaN(float value) {
|
||||
return value != value;
|
||||
}
|
||||
|
||||
QString formatUsecTime(float usecs, int prec) {
|
||||
static const quint64 SECONDS_PER_MINUTE = 60;
|
||||
static const quint64 USECS_PER_MINUTE = USECS_PER_SECOND * SECONDS_PER_MINUTE;
|
||||
|
|
|
@ -180,11 +180,11 @@ private:
|
|||
static int DEADBEEF_SIZE;
|
||||
};
|
||||
|
||||
bool isBetween(int64_t value, int64_t max, int64_t min);
|
||||
|
||||
/// \return true when value is between max and min
|
||||
inline bool isBetween(int64_t value, int64_t max, int64_t min) { return ((value <= max) && (value >= min)); }
|
||||
|
||||
/// \return bool is the float NaN
|
||||
bool isNaN(float value);
|
||||
inline bool isNaN(float value) { return value != value; }
|
||||
|
||||
QString formatUsecTime(float usecs, int prec = 3);
|
||||
QString formatSecondsElapsed(float seconds);
|
||||
|
|
|
@ -150,7 +150,3 @@ QJsonObject Transform::toJson(const Transform& transform) {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Transform::containsNaN() const {
|
||||
return isNaN(_rotation) || isNaN(_scale) || isNaN(_translation);
|
||||
}
|
||||
|
|
|
@ -145,7 +145,7 @@ public:
|
|||
Vec4 transform(const Vec4& pos) const;
|
||||
Vec3 transform(const Vec3& pos) const;
|
||||
|
||||
bool containsNaN() const;
|
||||
bool containsNaN() const { return isNaN(_rotation) || isNaN(glm::dot(_scale, _translation)); }
|
||||
|
||||
protected:
|
||||
|
||||
|
|
Loading…
Reference in a new issue