mirror of
https://github.com/lubosz/overte.git
synced 2025-04-23 13:33:38 +02:00
some list management of AvatarMotionStates
This commit is contained in:
parent
2f4162f447
commit
67f5d0773d
16 changed files with 216 additions and 115 deletions
|
@ -2156,7 +2156,7 @@ void Application::init() {
|
|||
_physicsEngine.init();
|
||||
|
||||
EntityTree* tree = _entities.getTree();
|
||||
_entitySimulation.init(tree, &_physicsEngine, &_shapeManager, &_entityEditSender);
|
||||
_entitySimulation.init(tree, &_physicsEngine, &_entityEditSender);
|
||||
tree->setSimulation(&_entitySimulation);
|
||||
|
||||
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "Application.h"
|
||||
#include "Avatar.h"
|
||||
#include "AvatarManager.h"
|
||||
#include "AvatarMotionState.h"
|
||||
#include "Hand.h"
|
||||
#include "Head.h"
|
||||
#include "Menu.h"
|
||||
|
@ -972,6 +973,9 @@ int Avatar::parseDataAtOffset(const QByteArray& packet, int offset) {
|
|||
|
||||
const float MOVE_DISTANCE_THRESHOLD = 0.001f;
|
||||
_moving = glm::distance(oldPosition, _position) > MOVE_DISTANCE_THRESHOLD;
|
||||
if (_moving && _motionState) {
|
||||
_motionState->addDirtyFlags(EntityItem::DIRTY_POSITION);
|
||||
}
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
@ -1087,20 +1091,15 @@ void Avatar::setShowDisplayName(bool showDisplayName) {
|
|||
|
||||
}
|
||||
|
||||
// virtual
|
||||
void Avatar::rebuildSkeletonBody() {
|
||||
/* TODO: implement this and remove override from MyAvatar (when we have AvatarMotionStates working)
|
||||
if (_motionState) {
|
||||
// compute localAABox
|
||||
const CapsuleShape& capsule = _skeletonModel.getBoundingShape();
|
||||
float radius = capsule.getRadius();
|
||||
float height = 2.0f * (capsule.getHalfHeight() + radius);
|
||||
glm::vec3 corner(-radius, -0.5f * height, -radius);
|
||||
corner += _skeletonModel.getBoundingShapeOffset();
|
||||
glm::vec3 scale(2.0f * radius, height, 2.0f * radius);
|
||||
//_characterController.setLocalBoundingBox(corner, scale);
|
||||
_motionState->setBoundingBox(corner, scale);
|
||||
}
|
||||
*/
|
||||
// virtual
|
||||
void Avatar::computeShapeInfo(ShapeInfo& shapeInfo) {
|
||||
const CapsuleShape& capsule = _skeletonModel.getBoundingShape();
|
||||
shapeInfo.setCapsuleY(capsule.getRadius(), capsule.getHalfHeight());
|
||||
shapeInfo.setOffset(_skeletonModel.getBoundingShapeOffset());
|
||||
}
|
||||
|
||||
// virtual
|
||||
void Avatar::rebuildSkeletonBody() {
|
||||
DependencyManager::get<AvatarManager>()->updateAvatarPhysicsShape(getSessionUUID());
|
||||
}
|
||||
|
||||
|
|
|
@ -18,11 +18,11 @@
|
|||
#include <QtCore/QUuid>
|
||||
|
||||
#include <AvatarData.h>
|
||||
#include <ShapeInfo.h>
|
||||
|
||||
#include "Hand.h"
|
||||
#include "Head.h"
|
||||
#include "InterfaceConfig.h"
|
||||
#include "Recorder.h"
|
||||
#include "SkeletonModel.h"
|
||||
#include "world.h"
|
||||
|
||||
|
@ -55,6 +55,7 @@ enum ScreenTintLayer {
|
|||
NUM_SCREEN_TINT_LAYERS
|
||||
};
|
||||
|
||||
class AvatarMotionState;
|
||||
class Texture;
|
||||
|
||||
class Avatar : public AvatarData {
|
||||
|
@ -164,6 +165,10 @@ public:
|
|||
|
||||
virtual void rebuildSkeletonBody();
|
||||
|
||||
virtual void computeShapeInfo(ShapeInfo& shapeInfo);
|
||||
|
||||
friend class AvatarManager;
|
||||
|
||||
signals:
|
||||
void collisionWithAvatar(const QUuid& myUUID, const QUuid& theirUUID, const CollisionInfo& collision);
|
||||
|
||||
|
@ -231,7 +236,7 @@ private:
|
|||
|
||||
int _voiceSphereID;
|
||||
|
||||
//AvatarMotionState* _motionState = nullptr;
|
||||
AvatarMotionState* _motionState = nullptr;
|
||||
};
|
||||
|
||||
#endif // hifi_Avatar_h
|
||||
|
|
|
@ -174,7 +174,6 @@ AvatarSharedPointer AvatarManager::newSharedAvatar() {
|
|||
// virtual
|
||||
AvatarSharedPointer AvatarManager::addAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer) {
|
||||
AvatarSharedPointer avatar = AvatarHashMap::addAvatar(sessionUUID, mixerWeakPointer);
|
||||
// TODO: create MotionState for avatar and add to internal lists
|
||||
return avatar;
|
||||
}
|
||||
|
||||
|
@ -184,6 +183,16 @@ void AvatarManager::removeAvatar(const QUuid& sessionUUID) {
|
|||
if (avatarIterator != _avatarHash.end()) {
|
||||
Avatar* avatar = reinterpret_cast<Avatar*>(avatarIterator.value().data());
|
||||
if (avatar != _myAvatar && avatar->isInitialized()) {
|
||||
AvatarMotionState* motionState= avatar->_motionState;
|
||||
if (motionState) {
|
||||
// clean up physics stuff
|
||||
motionState->clearObjectBackPointer();
|
||||
avatar->_motionState = nullptr;
|
||||
_avatarMotionStates.remove(motionState);
|
||||
_motionStatesToAdd.remove(motionState);
|
||||
_motionStatesToDelete.push_back(motionState);
|
||||
}
|
||||
|
||||
_avatarFades.push_back(avatarIterator.value());
|
||||
_avatarHash.erase(avatarIterator);
|
||||
}
|
||||
|
@ -225,14 +234,28 @@ QVector<AvatarManager::LocalLight> AvatarManager::getLocalLights() const {
|
|||
}
|
||||
|
||||
VectorOfMotionStates& AvatarManager::getObjectsToDelete() {
|
||||
_tempMotionStates.clear();
|
||||
_tempMotionStates.swap(_motionStatesToDelete);
|
||||
return _tempMotionStates;
|
||||
}
|
||||
|
||||
VectorOfMotionStates& AvatarManager::getObjectsToAdd() {
|
||||
_tempMotionStates.clear();
|
||||
|
||||
for (auto motionState : _motionStatesToAdd) {
|
||||
_tempMotionStates.push_back(motionState);
|
||||
}
|
||||
_motionStatesToAdd.clear();
|
||||
return _tempMotionStates;
|
||||
}
|
||||
|
||||
VectorOfMotionStates& AvatarManager::getObjectsToChange() {
|
||||
_tempMotionStates.clear();
|
||||
for (auto state : _avatarMotionStates) {
|
||||
if (state->_dirtyFlags > 0) {
|
||||
_tempMotionStates.push_back(state);
|
||||
}
|
||||
}
|
||||
return _tempMotionStates;
|
||||
}
|
||||
|
||||
|
@ -242,3 +265,23 @@ void AvatarManager::handleOutgoingChanges(VectorOfMotionStates& motionStates) {
|
|||
void AvatarManager::handleCollisionEvents(CollisionEvents& collisionEvents) {
|
||||
}
|
||||
|
||||
void AvatarManager::updateAvatarPhysicsShape(const QUuid& id) {
|
||||
AvatarHash::iterator avatarItr = _avatarHash.find(id);
|
||||
if (avatarItr != _avatarHash.end()) {
|
||||
Avatar* avatar = static_cast<Avatar*>(avatarItr.value().data());
|
||||
AvatarMotionState* motionState = avatar->_motionState;
|
||||
if (motionState) {
|
||||
motionState->addDirtyFlags(EntityItem::DIRTY_SHAPE);
|
||||
} else {
|
||||
ShapeInfo shapeInfo;
|
||||
avatar->computeShapeInfo(shapeInfo);
|
||||
btCollisionShape* shape = ObjectMotionState::getShapeManager()->getShape(shapeInfo);
|
||||
if (shape) {
|
||||
AvatarMotionState* motionState = new AvatarMotionState(avatar, shape);
|
||||
avatar->_motionState = motionState;
|
||||
_motionStatesToAdd.insert(motionState);
|
||||
_avatarMotionStates.insert(motionState);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,6 +59,8 @@ public:
|
|||
VectorOfMotionStates& getObjectsToChange();
|
||||
void handleOutgoingChanges(VectorOfMotionStates& motionStates);
|
||||
void handleCollisionEvents(CollisionEvents& collisionEvents);
|
||||
|
||||
void updateAvatarPhysicsShape(const QUuid& id);
|
||||
|
||||
public slots:
|
||||
void setShouldShowReceiveStats(bool shouldShowReceiveStats) { _shouldShowReceiveStats = shouldShowReceiveStats; }
|
||||
|
@ -83,7 +85,9 @@ private:
|
|||
|
||||
bool _shouldShowReceiveStats = false;
|
||||
|
||||
VectorOfAvatarMotionStates _avatarMotionStates;
|
||||
SetOfAvatarMotionStates _avatarMotionStates;
|
||||
SetOfMotionStates _motionStatesToAdd;
|
||||
VectorOfMotionStates _motionStatesToDelete;
|
||||
VectorOfMotionStates _tempMotionStates;
|
||||
};
|
||||
|
||||
|
|
|
@ -28,25 +28,27 @@ void AvatarMotionState::handleHardAndEasyChanges(uint32_t flags, PhysicsEngine*
|
|||
}
|
||||
|
||||
// virtual
|
||||
void AvatarMotionState::updateBodyMaterialProperties() {
|
||||
uint32_t AvatarMotionState::getAndClearIncomingDirtyFlags() {
|
||||
uint32_t dirtyFlags = 0;
|
||||
if (_body && _avatar) {
|
||||
dirtyFlags = _dirtyFlags;
|
||||
_dirtyFlags = 0;
|
||||
}
|
||||
return dirtyFlags;
|
||||
}
|
||||
|
||||
// virtual
|
||||
void AvatarMotionState::updateBodyVelocities() {
|
||||
}
|
||||
|
||||
// virtual
|
||||
uint32_t AvatarMotionState::getAndClearIncomingDirtyFlags() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// virtual
|
||||
MotionType AvatarMotionState::computeObjectMotionType() const {
|
||||
return _motionType;
|
||||
}
|
||||
|
||||
// virtual
|
||||
void AvatarMotionState::computeObjectShapeInfo(ShapeInfo& shapeInfo) {
|
||||
btCollisionShape* AvatarMotionState::computeNewShape() {
|
||||
if (_avatar) {
|
||||
ShapeInfo shapeInfo;
|
||||
_avatar->computeShapeInfo(shapeInfo);
|
||||
return getShapeManager()->getShape(shapeInfo);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// virtual
|
||||
|
@ -54,6 +56,16 @@ bool AvatarMotionState::isMoving() const {
|
|||
return false;
|
||||
}
|
||||
|
||||
// virtual
|
||||
void AvatarMotionState::getWorldTransform(btTransform& worldTrans) const {
|
||||
// TODO: implement this
|
||||
}
|
||||
|
||||
// virtual
|
||||
void AvatarMotionState::setWorldTransform(const btTransform& worldTrans) {
|
||||
// TODO: implement this
|
||||
}
|
||||
|
||||
// These pure virtual methods must be implemented for each MotionState type
|
||||
// and make it possible to implement more complicated methods in this base class.
|
||||
|
||||
|
@ -61,14 +73,17 @@ bool AvatarMotionState::isMoving() const {
|
|||
float AvatarMotionState::getObjectRestitution() const {
|
||||
return 0.5f;
|
||||
}
|
||||
|
||||
// virtual
|
||||
float AvatarMotionState::getObjectFriction() const {
|
||||
return 0.5f;
|
||||
}
|
||||
|
||||
// virtual
|
||||
float AvatarMotionState::getObjectLinearDamping() const {
|
||||
return 0.5f;
|
||||
}
|
||||
|
||||
// virtual
|
||||
float AvatarMotionState::getObjectAngularDamping() const {
|
||||
return 0.5f;
|
||||
|
@ -78,10 +93,12 @@ float AvatarMotionState::getObjectAngularDamping() const {
|
|||
glm::vec3 AvatarMotionState::getObjectPosition() const {
|
||||
return glm::vec3(0.0f);
|
||||
}
|
||||
|
||||
// virtual
|
||||
glm::quat AvatarMotionState::getObjectRotation() const {
|
||||
return _avatar->getOrientation();
|
||||
}
|
||||
|
||||
// virtual
|
||||
const glm::vec3& AvatarMotionState::getObjectLinearVelocity() const {
|
||||
return _avatar->getVelocity();
|
||||
|
@ -111,6 +128,10 @@ QUuid AvatarMotionState::getSimulatorID() const {
|
|||
void AvatarMotionState::bump() {
|
||||
}
|
||||
|
||||
// protected, virtual
|
||||
void AvatarMotionState::setMotionType(MotionType motionType) {
|
||||
// virtual
|
||||
void AvatarMotionState::clearObjectBackPointer() {
|
||||
ObjectMotionState::clearObjectBackPointer();
|
||||
_avatar = nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#ifndef hifi_AvatarMotionState_h
|
||||
#define hifi_AvatarMotionState_h
|
||||
|
||||
#include <QVector>
|
||||
#include <QSet>
|
||||
|
||||
#include <ObjectMotionState.h>
|
||||
|
||||
|
@ -26,42 +26,53 @@ public:
|
|||
virtual void handleEasyChanges(uint32_t flags);
|
||||
virtual void handleHardAndEasyChanges(uint32_t flags, PhysicsEngine* engine);
|
||||
|
||||
virtual void updateBodyMaterialProperties();
|
||||
virtual void updateBodyVelocities();
|
||||
|
||||
virtual MotionType getMotionType() const { return _motionType; }
|
||||
|
||||
virtual uint32_t getAndClearIncomingDirtyFlags() const = 0;
|
||||
virtual uint32_t getAndClearIncomingDirtyFlags();
|
||||
|
||||
virtual MotionType computeObjectMotionType() const = 0;
|
||||
virtual void computeObjectShapeInfo(ShapeInfo& shapeInfo) = 0;
|
||||
virtual MotionType computeObjectMotionType() const;
|
||||
virtual btCollisionShape* computeNewShape();
|
||||
|
||||
virtual bool isMoving() const;
|
||||
|
||||
// this relays incoming position/rotation to the RigidBody
|
||||
virtual void getWorldTransform(btTransform& worldTrans) const;
|
||||
|
||||
// this relays outgoing position/rotation to the EntityItem
|
||||
virtual void setWorldTransform(const btTransform& worldTrans);
|
||||
|
||||
virtual bool isMoving() const = 0;
|
||||
|
||||
// These pure virtual methods must be implemented for each MotionState type
|
||||
// and make it possible to implement more complicated methods in this base class.
|
||||
|
||||
virtual float getObjectRestitution() const = 0;
|
||||
virtual float getObjectFriction() const = 0;
|
||||
virtual float getObjectLinearDamping() const = 0;
|
||||
virtual float getObjectAngularDamping() const = 0;
|
||||
virtual float getObjectRestitution() const;
|
||||
virtual float getObjectFriction() const;
|
||||
virtual float getObjectLinearDamping() const;
|
||||
virtual float getObjectAngularDamping() const;
|
||||
|
||||
virtual glm::vec3 getObjectPosition() const = 0;
|
||||
virtual glm::quat getObjectRotation() const = 0;
|
||||
virtual const glm::vec3& getObjectLinearVelocity() const = 0;
|
||||
virtual const glm::vec3& getObjectAngularVelocity() const = 0;
|
||||
virtual const glm::vec3& getObjectGravity() const = 0;
|
||||
virtual glm::vec3 getObjectPosition() const;
|
||||
virtual glm::quat getObjectRotation() const;
|
||||
virtual const glm::vec3& getObjectLinearVelocity() const;
|
||||
virtual const glm::vec3& getObjectAngularVelocity() const;
|
||||
virtual const glm::vec3& getObjectGravity() const;
|
||||
|
||||
virtual const QUuid& getObjectID() const = 0;
|
||||
virtual const QUuid& getObjectID() const;
|
||||
|
||||
virtual QUuid getSimulatorID() const = 0;
|
||||
virtual void bump() = 0;
|
||||
virtual QUuid getSimulatorID() const;
|
||||
virtual void bump();
|
||||
|
||||
void setBoundingBox(const glm::vec3& corner, const glm::vec3& diagonal);
|
||||
|
||||
void addDirtyFlags(uint32_t flags) { _dirtyFlags |= flags; }
|
||||
|
||||
friend class AvatarManager;
|
||||
|
||||
protected:
|
||||
virtual void setMotionType(MotionType motionType);
|
||||
virtual void clearObjectBackPointer();
|
||||
Avatar* _avatar;
|
||||
uint32_t _dirtyFlags;
|
||||
};
|
||||
|
||||
typedef QVector<AvatarMotionState*> VectorOfAvatarMotionStates;
|
||||
typedef QSet<AvatarMotionState*> SetOfAvatarMotionStates;
|
||||
|
||||
#endif // hifi_AvatarMotionState_h
|
||||
|
|
|
@ -39,7 +39,7 @@ EntityMotionState::EntityMotionState(btCollisionShape* shape, EntityItem* entity
|
|||
_loopsSinceOwnershipBid(0),
|
||||
_loopsWithoutOwner(0)
|
||||
{
|
||||
_type = MOTION_STATE_TYPE_ENTITY;
|
||||
_type = MOTIONSTATE_TYPE_ENTITY;
|
||||
assert(entity != nullptr);
|
||||
}
|
||||
|
||||
|
@ -98,10 +98,9 @@ void EntityMotionState::handleHardAndEasyChanges(uint32_t flags, PhysicsEngine*
|
|||
ObjectMotionState::handleHardAndEasyChanges(flags, engine);
|
||||
}
|
||||
|
||||
void EntityMotionState::clearEntity() {
|
||||
void EntityMotionState::clearObjectBackPointer() {
|
||||
ObjectMotionState::clearObjectBackPointer();
|
||||
_entity = nullptr;
|
||||
// set the type to INVALID so that external logic that pivots on the type won't try to access _entity
|
||||
_type = MOTION_STATE_TYPE_INVALID;
|
||||
}
|
||||
|
||||
MotionType EntityMotionState::computeObjectMotionType() const {
|
||||
|
@ -178,10 +177,13 @@ void EntityMotionState::setWorldTransform(const btTransform& worldTrans) {
|
|||
#endif
|
||||
}
|
||||
|
||||
void EntityMotionState::computeObjectShapeInfo(ShapeInfo& shapeInfo) {
|
||||
btCollisionShape* EntityMotionState::computeNewShape() {
|
||||
if (_entity) {
|
||||
ShapeInfo shapeInfo;
|
||||
_entity->computeShapeInfo(shapeInfo);
|
||||
return getShapeManager()->getShape(shapeInfo);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// RELIABLE_SEND_HACK: until we have truly reliable resends of non-moving updates
|
||||
|
@ -445,7 +447,7 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, const Q
|
|||
_lastStep = step;
|
||||
}
|
||||
|
||||
uint32_t EntityMotionState::getAndClearIncomingDirtyFlags() const {
|
||||
uint32_t EntityMotionState::getAndClearIncomingDirtyFlags() {
|
||||
uint32_t dirtyFlags = 0;
|
||||
if (_body && _entity) {
|
||||
dirtyFlags = _entity->getDirtyFlags();
|
||||
|
|
|
@ -43,14 +43,14 @@ public:
|
|||
// this relays outgoing position/rotation to the EntityItem
|
||||
virtual void setWorldTransform(const btTransform& worldTrans);
|
||||
|
||||
virtual void computeObjectShapeInfo(ShapeInfo& shapeInfo);
|
||||
virtual btCollisionShape* computeNewShape();
|
||||
|
||||
bool isCandidateForOwnership(const QUuid& sessionID) const;
|
||||
bool remoteSimulationOutOfSync(uint32_t simulationStep);
|
||||
bool shouldSendUpdate(uint32_t simulationStep, const QUuid& sessionID);
|
||||
void sendUpdate(OctreeEditPacketSender* packetSender, const QUuid& sessionID, uint32_t step);
|
||||
|
||||
virtual uint32_t getAndClearIncomingDirtyFlags() const;
|
||||
virtual uint32_t getAndClearIncomingDirtyFlags();
|
||||
|
||||
void incrementAccelerationNearlyGravityCount() { _accelerationNearlyGravityCount++; }
|
||||
void resetAccelerationNearlyGravityCount() { _accelerationNearlyGravityCount = 0; }
|
||||
|
@ -82,8 +82,7 @@ public:
|
|||
friend class PhysicalEntitySimulation;
|
||||
|
||||
protected:
|
||||
void clearEntity();
|
||||
|
||||
virtual void clearObjectBackPointer();
|
||||
virtual void setMotionType(MotionType motionType);
|
||||
|
||||
EntityItem* _entity;
|
||||
|
|
|
@ -140,20 +140,14 @@ void ObjectMotionState::handleEasyChanges(uint32_t flags) {
|
|||
}
|
||||
|
||||
if (flags & EntityItem::DIRTY_MASS) {
|
||||
float mass = getMass();
|
||||
btVector3 inertia(0.0f, 0.0f, 0.0f);
|
||||
_body->getCollisionShape()->calculateLocalInertia(mass, inertia);
|
||||
_body->setMassProps(mass, inertia);
|
||||
_body->updateInertiaTensor();
|
||||
updateBodyMassProperties();
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectMotionState::handleHardAndEasyChanges(uint32_t flags, PhysicsEngine* engine) {
|
||||
if (flags & EntityItem::DIRTY_SHAPE) {
|
||||
// make sure the new shape is valid
|
||||
ShapeInfo shapeInfo;
|
||||
computeObjectShapeInfo(shapeInfo);
|
||||
btCollisionShape* newShape = getShapeManager()->getShape(shapeInfo);
|
||||
btCollisionShape* newShape = computeNewShape();
|
||||
if (!newShape) {
|
||||
qCDebug(physics) << "Warning: failed to generate new shape!";
|
||||
// failed to generate new shape! --> keep old shape and remove shape-change flag
|
||||
|
@ -168,17 +162,21 @@ void ObjectMotionState::handleHardAndEasyChanges(uint32_t flags, PhysicsEngine*
|
|||
}
|
||||
}
|
||||
getShapeManager()->releaseShape(_shape);
|
||||
_shape = newShape;
|
||||
_body->setCollisionShape(_shape);
|
||||
if (flags & EASY_DIRTY_PHYSICS_FLAGS) {
|
||||
handleEasyChanges(flags);
|
||||
}
|
||||
} else {
|
||||
if (flags & EASY_DIRTY_PHYSICS_FLAGS) {
|
||||
handleEasyChanges(flags);
|
||||
if (_shape != newShape) {
|
||||
// huh... the shape didn't actually change, so we remove the DIRTY_SHAPE flag
|
||||
_shape = newShape;
|
||||
_body->setCollisionShape(_shape);
|
||||
flags &= ~EntityItem::DIRTY_SHAPE;
|
||||
}
|
||||
}
|
||||
engine->reinsertObject(this);
|
||||
if (flags & EASY_DIRTY_PHYSICS_FLAGS) {
|
||||
handleEasyChanges(flags);
|
||||
}
|
||||
// it is possible that there are no HARD flags at this point (if DIRTY_SHAPE was removed)
|
||||
// so we check again befoe we reinsert:
|
||||
if (flags & HARD_DIRTY_PHYSICS_FLAGS) {
|
||||
engine->reinsertObject(this);
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectMotionState::updateBodyMaterialProperties() {
|
||||
|
@ -193,3 +191,11 @@ void ObjectMotionState::updateBodyVelocities() {
|
|||
setBodyGravity(getObjectGravity());
|
||||
_body->setActivationState(ACTIVE_TAG);
|
||||
}
|
||||
|
||||
void ObjectMotionState::updateBodyMassProperties() {
|
||||
float mass = getMass();
|
||||
btVector3 inertia(0.0f, 0.0f, 0.0f);
|
||||
_body->getCollisionShape()->calculateLocalInertia(mass, inertia);
|
||||
_body->setMassProps(mass, inertia);
|
||||
_body->updateInertiaTensor();
|
||||
}
|
||||
|
|
|
@ -30,9 +30,9 @@ enum MotionType {
|
|||
};
|
||||
|
||||
enum MotionStateType {
|
||||
MOTION_STATE_TYPE_INVALID,
|
||||
MOTION_STATE_TYPE_ENTITY,
|
||||
MOTION_STATE_TYPE_AVATAR
|
||||
MOTIONSTATE_TYPE_INVALID,
|
||||
MOTIONSTATE_TYPE_ENTITY,
|
||||
MOTIONSTATE_TYPE_AVATAR
|
||||
};
|
||||
|
||||
// The update flags trigger two varieties of updates: "hard" which require the body to be pulled
|
||||
|
@ -74,8 +74,9 @@ public:
|
|||
virtual void handleEasyChanges(uint32_t flags);
|
||||
virtual void handleHardAndEasyChanges(uint32_t flags, PhysicsEngine* engine);
|
||||
|
||||
virtual void updateBodyMaterialProperties();
|
||||
virtual void updateBodyVelocities();
|
||||
void updateBodyMaterialProperties();
|
||||
void updateBodyVelocities();
|
||||
virtual void updateBodyMassProperties();
|
||||
|
||||
MotionStateType getType() const { return _type; }
|
||||
virtual MotionType getMotionType() const { return _motionType; }
|
||||
|
@ -90,11 +91,10 @@ public:
|
|||
glm::vec3 getBodyLinearVelocity() const;
|
||||
glm::vec3 getBodyAngularVelocity() const;
|
||||
|
||||
virtual uint32_t getAndClearIncomingDirtyFlags() const = 0;
|
||||
virtual uint32_t getAndClearIncomingDirtyFlags() = 0;
|
||||
|
||||
virtual MotionType computeObjectMotionType() const = 0;
|
||||
virtual void computeObjectShapeInfo(ShapeInfo& shapeInfo) = 0;
|
||||
|
||||
virtual btCollisionShape* computeNewShape() = 0;
|
||||
|
||||
btCollisionShape* getShape() const { return _shape; }
|
||||
btRigidBody* getRigidBody() const { return _body; }
|
||||
|
@ -127,10 +127,14 @@ public:
|
|||
friend class PhysicsEngine;
|
||||
|
||||
protected:
|
||||
virtual void setMotionType(MotionType motionType);
|
||||
void setMotionType(MotionType motionType);
|
||||
|
||||
// clearObjectBackPointer() overrrides should call the base method, then actually clear the object back pointer.
|
||||
virtual void clearObjectBackPointer() { _type = MOTIONSTATE_TYPE_INVALID; }
|
||||
|
||||
void setRigidBody(btRigidBody* body);
|
||||
|
||||
MotionStateType _type = MOTION_STATE_TYPE_INVALID; // type of MotionState
|
||||
MotionStateType _type = MOTIONSTATE_TYPE_INVALID; // type of MotionState
|
||||
MotionType _motionType; // type of motion: KINEMATIC, DYNAMIC, or STATIC
|
||||
|
||||
btCollisionShape* _shape;
|
||||
|
|
|
@ -24,7 +24,6 @@ PhysicalEntitySimulation::~PhysicalEntitySimulation() {
|
|||
void PhysicalEntitySimulation::init(
|
||||
EntityTree* tree,
|
||||
PhysicsEngine* physicsEngine,
|
||||
ShapeManager* shapeManager,
|
||||
EntityEditPacketSender* packetSender) {
|
||||
assert(tree);
|
||||
setEntityTree(tree);
|
||||
|
@ -32,9 +31,6 @@ void PhysicalEntitySimulation::init(
|
|||
assert(physicsEngine);
|
||||
_physicsEngine = physicsEngine;
|
||||
|
||||
assert(shapeManager);
|
||||
_shapeManager = shapeManager;
|
||||
|
||||
assert(packetSender);
|
||||
_entityPacketSender = packetSender;
|
||||
}
|
||||
|
@ -59,7 +55,7 @@ void PhysicalEntitySimulation::addEntityInternal(EntityItem* entity) {
|
|||
void PhysicalEntitySimulation::removeEntityInternal(EntityItem* entity) {
|
||||
EntityMotionState* motionState = static_cast<EntityMotionState*>(entity->getPhysicsInfo());
|
||||
if (motionState) {
|
||||
motionState->clearEntity();
|
||||
motionState->clearObjectBackPointer();
|
||||
entity->setPhysicsInfo(nullptr);
|
||||
_pendingRemoves.insert(motionState);
|
||||
_outgoingChanges.remove(motionState);
|
||||
|
@ -108,7 +104,7 @@ void PhysicalEntitySimulation::clearEntitiesInternal() {
|
|||
if (entity) {
|
||||
entity->setPhysicsInfo(nullptr);
|
||||
}
|
||||
motionState->clearEntity();
|
||||
motionState->clearObjectBackPointer();
|
||||
}
|
||||
|
||||
// then delete the objects (aka MotionStates)
|
||||
|
@ -134,7 +130,7 @@ VectorOfMotionStates& PhysicalEntitySimulation::getObjectsToDelete() {
|
|||
if (entity) {
|
||||
_pendingAdds.remove(entity);
|
||||
entity->setPhysicsInfo(nullptr);
|
||||
motionState->clearEntity();
|
||||
motionState->clearObjectBackPointer();
|
||||
}
|
||||
_tempVector.push_back(motionState);
|
||||
}
|
||||
|
@ -157,7 +153,7 @@ VectorOfMotionStates& PhysicalEntitySimulation::getObjectsToAdd() {
|
|||
} else if (entity->isReadyToComputeShape()) {
|
||||
ShapeInfo shapeInfo;
|
||||
entity->computeShapeInfo(shapeInfo);
|
||||
btCollisionShape* shape = _shapeManager->getShape(shapeInfo);
|
||||
btCollisionShape* shape = ObjectMotionState::getShapeManager()->getShape(shapeInfo);
|
||||
if (shape) {
|
||||
EntityMotionState* motionState = new EntityMotionState(shape, entity);
|
||||
entity->setPhysicsInfo(static_cast<void*>(motionState));
|
||||
|
@ -191,7 +187,7 @@ void PhysicalEntitySimulation::handleOutgoingChanges(VectorOfMotionStates& motio
|
|||
// walk the motionStates looking for those that correspond to entities
|
||||
for (auto stateItr : motionStates) {
|
||||
ObjectMotionState* state = &(*stateItr);
|
||||
if (state && state->getType() == MOTION_STATE_TYPE_ENTITY) {
|
||||
if (state && state->getType() == MOTIONSTATE_TYPE_ENTITY) {
|
||||
EntityMotionState* entityState = static_cast<EntityMotionState*>(state);
|
||||
EntityItem* entity = entityState->getEntity();
|
||||
if (entity) {
|
||||
|
|
|
@ -23,8 +23,6 @@
|
|||
#include "PhysicsEngine.h"
|
||||
#include "EntityMotionState.h"
|
||||
|
||||
class ShapeManager;
|
||||
|
||||
typedef QSet<EntityMotionState*> SetOfEntityMotionStates;
|
||||
|
||||
class PhysicalEntitySimulation :public EntitySimulation {
|
||||
|
@ -32,7 +30,7 @@ public:
|
|||
PhysicalEntitySimulation();
|
||||
~PhysicalEntitySimulation();
|
||||
|
||||
void init(EntityTree* tree, PhysicsEngine* engine, ShapeManager* shapeManager, EntityEditPacketSender* packetSender);
|
||||
void init(EntityTree* tree, PhysicsEngine* engine, EntityEditPacketSender* packetSender);
|
||||
|
||||
protected: // only called by EntitySimulation
|
||||
// overrides for EntitySimulation
|
||||
|
@ -62,7 +60,6 @@ private:
|
|||
SetOfMotionStates _physicalObjects; // MotionStates of entities in PhysicsEngine
|
||||
VectorOfMotionStates _tempVector; // temporary array reference, valid immediately after getObjectsToRemove() (and friends)
|
||||
|
||||
ShapeManager* _shapeManager = nullptr;
|
||||
PhysicsEngine* _physicsEngine = nullptr;
|
||||
EntityEditPacketSender* _entityPacketSender = nullptr;
|
||||
|
||||
|
|
|
@ -318,16 +318,16 @@ CollisionEvents& PhysicsEngine::getCollisionEvents() {
|
|||
ObjectMotionState* A = static_cast<ObjectMotionState*>(contactItr->first._a);
|
||||
ObjectMotionState* B = static_cast<ObjectMotionState*>(contactItr->first._b);
|
||||
|
||||
if (A && A->getType() == MOTION_STATE_TYPE_ENTITY) {
|
||||
if (A && A->getType() == MOTIONSTATE_TYPE_ENTITY) {
|
||||
QUuid idA = A->getObjectID();
|
||||
QUuid idB;
|
||||
if (B && B->getType() == MOTION_STATE_TYPE_ENTITY) {
|
||||
if (B && B->getType() == MOTIONSTATE_TYPE_ENTITY) {
|
||||
idB = B->getObjectID();
|
||||
}
|
||||
glm::vec3 position = bulletToGLM(contact.getPositionWorldOnB()) + _originOffset;
|
||||
glm::vec3 penetration = bulletToGLM(contact.distance * contact.normalWorldOnB);
|
||||
_collisionEvents.push_back(Collision(type, idA, idB, position, penetration));
|
||||
} else if (B && B->getType() == MOTION_STATE_TYPE_ENTITY) {
|
||||
} else if (B && B->getType() == MOTIONSTATE_TYPE_ENTITY) {
|
||||
QUuid idB = B->getObjectID();
|
||||
glm::vec3 position = bulletToGLM(contact.getPositionWorldOnA()) + _originOffset;
|
||||
// NOTE: we're flipping the order of A and B (so that the first objectID is never NULL)
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
void ShapeInfo::clear() {
|
||||
_type = SHAPE_TYPE_NONE;
|
||||
_halfExtents = glm::vec3(0.0f);
|
||||
_halfExtents = _offset = glm::vec3(0.0f);
|
||||
_doubleHashKey.clear();
|
||||
}
|
||||
|
||||
|
@ -45,6 +45,7 @@ void ShapeInfo::setParams(ShapeType type, const glm::vec3& halfExtents, QString
|
|||
_halfExtents = halfExtents;
|
||||
break;
|
||||
}
|
||||
_doubleHashKey.clear();
|
||||
}
|
||||
|
||||
void ShapeInfo::setBox(const glm::vec3& halfExtents) {
|
||||
|
@ -85,6 +86,11 @@ void ShapeInfo::setCapsuleY(float radius, float halfHeight) {
|
|||
_doubleHashKey.clear();
|
||||
}
|
||||
|
||||
void ShapeInfo::setOffset(const glm::vec3& offset) {
|
||||
_offset = offset;
|
||||
_doubleHashKey.clear();
|
||||
}
|
||||
|
||||
uint32_t ShapeInfo::getNumSubShapes() const {
|
||||
if (_type == SHAPE_TYPE_NONE) {
|
||||
return 0;
|
||||
|
@ -190,9 +196,12 @@ const DoubleHashKey& ShapeInfo::getHash() const {
|
|||
for (int j = 0; j < 3; ++j) {
|
||||
// NOTE: 0.49f is used to bump the float up almost half a millimeter
|
||||
// so the cast to int produces a round() effect rather than a floor()
|
||||
uint32_t floatHash =
|
||||
DoubleHashKey::hashFunction((uint32_t)(_halfExtents[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _halfExtents[j]) * 0.49f), primeIndex++);
|
||||
hash ^= floatHash;
|
||||
hash ^= DoubleHashKey::hashFunction(
|
||||
(uint32_t)(_halfExtents[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _halfExtents[j]) * 0.49f),
|
||||
primeIndex++);
|
||||
hash ^= DoubleHashKey::hashFunction(
|
||||
(uint32_t)(_offset[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _offset[j]) * 0.49f),
|
||||
primeIndex++);
|
||||
}
|
||||
key.setHash(hash);
|
||||
|
||||
|
@ -201,8 +210,10 @@ const DoubleHashKey& ShapeInfo::getHash() const {
|
|||
for (int j = 0; j < 3; ++j) {
|
||||
// NOTE: 0.49f is used to bump the float up almost half a millimeter
|
||||
// so the cast to int produces a round() effect rather than a floor()
|
||||
uint32_t floatHash =
|
||||
DoubleHashKey::hashFunction2((uint32_t)(_halfExtents[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _halfExtents[j]) * 0.49f));
|
||||
uint32_t floatHash = DoubleHashKey::hashFunction2(
|
||||
(uint32_t)(_halfExtents[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _halfExtents[j]) * 0.49f));
|
||||
floatHash ^= DoubleHashKey::hashFunction2(
|
||||
(uint32_t)(_offset[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _offset[j]) * 0.49f));
|
||||
hash += ~(floatHash << 17);
|
||||
hash ^= (floatHash >> 11);
|
||||
hash += (floatHash << 4);
|
||||
|
|
|
@ -46,10 +46,12 @@ public:
|
|||
void setEllipsoid(const glm::vec3& halfExtents);
|
||||
void setConvexHulls(const QVector<QVector<glm::vec3>>& points);
|
||||
void setCapsuleY(float radius, float halfHeight);
|
||||
void setOffset(const glm::vec3& offset);
|
||||
|
||||
int getType() const { return _type; }
|
||||
|
||||
const glm::vec3& getHalfExtents() const { return _halfExtents; }
|
||||
const glm::vec3& getOffset() const { return _offset; }
|
||||
|
||||
const QVector<QVector<glm::vec3>>& getPoints() const { return _points; }
|
||||
uint32_t getNumSubShapes() const;
|
||||
|
@ -68,6 +70,7 @@ public:
|
|||
protected:
|
||||
ShapeType _type = SHAPE_TYPE_NONE;
|
||||
glm::vec3 _halfExtents = glm::vec3(0.0f);
|
||||
glm::vec3 _offset = glm::vec3(0.0f);
|
||||
DoubleHashKey _doubleHashKey;
|
||||
QVector<QVector<glm::vec3>> _points; // points for convex collision hulls
|
||||
QUrl _url; // url for model of convex collision hulls
|
||||
|
|
Loading…
Reference in a new issue