call a method on actions before each physics simulation step. use this to attempt to dejitter held objects

This commit is contained in:
Seth Alves 2015-12-16 14:00:04 -08:00
parent a422103e89
commit d3c57821c0
11 changed files with 134 additions and 33 deletions

View file

@ -2989,6 +2989,9 @@ void Application::update(float deltaTime) {
_physicsEngine->changeObjects(motionStates); _physicsEngine->changeObjects(motionStates);
myAvatar->prepareForPhysicsSimulation(); myAvatar->prepareForPhysicsSimulation();
_physicsEngine->forEachAction([&](EntityActionPointer action) {
action->prepareForPhysicsSimulation();
});
getEntities()->getTree()->withWriteLock([&] { getEntities()->getTree()->withWriteLock([&] {
_physicsEngine->stepSimulation(); _physicsEngine->stepSimulation();

View file

@ -14,6 +14,7 @@
#include <QVariantGLM.h> #include <QVariantGLM.h>
#include "avatar/AvatarManager.h" #include "avatar/AvatarManager.h"
#include "CharacterController.h"
const uint16_t AvatarActionHold::holdVersion = 1; const uint16_t AvatarActionHold::holdVersion = 1;
@ -32,6 +33,57 @@ AvatarActionHold::~AvatarActionHold() {
#endif #endif
} }
void AvatarActionHold::prepareForPhysicsSimulation() {
auto avatarManager = DependencyManager::get<AvatarManager>();
auto holdingAvatar = std::static_pointer_cast<Avatar>(avatarManager->getAvatarBySessionID(_holderID));
if (!holdingAvatar) {
return;
}
withTryReadLock([&]{
bool isRightHand = (_hand == "right");
if (_ignoreIK && holdingAvatar->isMyAvatar()) {
return;
}
if (holdingAvatar->isMyAvatar()) {
glm::vec3 palmPosition { Vectors::ZERO };
glm::quat palmRotation { Quaternions::IDENTITY };
if (isRightHand) {
palmPosition = holdingAvatar->getHand()->getCopyOfPalmData(HandData::RightHand).getPosition();
palmRotation = holdingAvatar->getHand()->getCopyOfPalmData(HandData::RightHand).getRotation();
} else {
palmPosition = holdingAvatar->getHand()->getCopyOfPalmData(HandData::LeftHand).getPosition();
palmRotation = holdingAvatar->getHand()->getCopyOfPalmData(HandData::LeftHand).getRotation();
}
// XXX dup code
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
MyCharacterController* controller = myAvatar ? myAvatar->getCharacterController() : nullptr;
if (!controller) {
qDebug() << "AvatarActionHold::prepareForPhysicsSimulation failed to get character controller";
return;
}
glm::vec3 avatarRigidBodyPosition;
glm::quat avatarRigidBodyRotation;
controller->getRigidBodyLocation(avatarRigidBodyPosition, avatarRigidBodyRotation);
if (isRightHand) {
palmPosition = holdingAvatar->getRightPalmPosition();
palmRotation = holdingAvatar->getRightPalmRotation();
} else {
palmPosition = holdingAvatar->getLeftPalmPosition();
palmRotation = holdingAvatar->getLeftPalmRotation();
}
_palmOffsetFromRigidBody = palmPosition - avatarRigidBodyPosition;
}
});
}
std::shared_ptr<Avatar> AvatarActionHold::getTarget(glm::quat& rotation, glm::vec3& position) { std::shared_ptr<Avatar> AvatarActionHold::getTarget(glm::quat& rotation, glm::vec3& position) {
auto avatarManager = DependencyManager::get<AvatarManager>(); auto avatarManager = DependencyManager::get<AvatarManager>();
auto holdingAvatar = std::static_pointer_cast<Avatar>(avatarManager->getAvatarBySessionID(_holderID)); auto holdingAvatar = std::static_pointer_cast<Avatar>(avatarManager->getAvatarBySessionID(_holderID));
@ -44,7 +96,7 @@ std::shared_ptr<Avatar> AvatarActionHold::getTarget(glm::quat& rotation, glm::ve
bool isRightHand = (_hand == "right"); bool isRightHand = (_hand == "right");
glm::vec3 palmPosition { Vectors::ZERO }; glm::vec3 palmPosition { Vectors::ZERO };
glm::quat palmRotation { Quaternions::IDENTITY }; glm::quat palmRotation { Quaternions::IDENTITY };
if (_ignoreIK && holdingAvatar->isMyAvatar()) { if (_ignoreIK && holdingAvatar->isMyAvatar()) {
// We cannot ignore other avatars IK and this is not the point of this option // We cannot ignore other avatars IK and this is not the point of this option
// This is meant to make the grabbing behavior more reactive. // This is meant to make the grabbing behavior more reactive.
@ -55,6 +107,22 @@ std::shared_ptr<Avatar> AvatarActionHold::getTarget(glm::quat& rotation, glm::ve
palmPosition = holdingAvatar->getHand()->getCopyOfPalmData(HandData::LeftHand).getPosition(); palmPosition = holdingAvatar->getHand()->getCopyOfPalmData(HandData::LeftHand).getPosition();
palmRotation = holdingAvatar->getHand()->getCopyOfPalmData(HandData::LeftHand).getRotation(); palmRotation = holdingAvatar->getHand()->getCopyOfPalmData(HandData::LeftHand).getRotation();
} }
} else if (holdingAvatar->isMyAvatar()) {
// XXX dup code
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
MyCharacterController* controller = myAvatar ? myAvatar->getCharacterController() : nullptr;
if (!controller) {
qDebug() << "AvatarActionHold::prepareForPhysicsSimulation failed to get character controller";
return;
}
glm::vec3 avatarRigidBodyPosition;
glm::quat avatarRigidBodyRotation;
controller->getRigidBodyLocation(avatarRigidBodyPosition, avatarRigidBodyRotation);
palmPosition = avatarRigidBodyPosition + _palmOffsetFromRigidBody;
palmRotation = holdingAvatar->getRightPalmRotation(); // XXX
} else { } else {
if (isRightHand) { if (isRightHand) {
palmPosition = holdingAvatar->getRightPalmPosition(); palmPosition = holdingAvatar->getRightPalmPosition();

View file

@ -25,18 +25,20 @@ public:
AvatarActionHold(const QUuid& id, EntityItemPointer ownerEntity); AvatarActionHold(const QUuid& id, EntityItemPointer ownerEntity);
virtual ~AvatarActionHold(); virtual ~AvatarActionHold();
virtual bool updateArguments(QVariantMap arguments); virtual bool updateArguments(QVariantMap arguments) override;
virtual QVariantMap getArguments(); virtual QVariantMap getArguments() override;
virtual void updateActionWorker(float deltaTimeStep); virtual void updateActionWorker(float deltaTimeStep) override;
QByteArray serialize() const; QByteArray serialize() const;
virtual void deserialize(QByteArray serializedArguments); virtual void deserialize(QByteArray serializedArguments) override;
virtual bool shouldSuppressLocationEdits() { return _active && !_ownerEntity.expired(); } virtual bool shouldSuppressLocationEdits() override { return _active && !_ownerEntity.expired(); }
std::shared_ptr<Avatar> getTarget(glm::quat& rotation, glm::vec3& position); std::shared_ptr<Avatar> getTarget(glm::quat& rotation, glm::vec3& position);
virtual void prepareForPhysicsSimulation() override;
private: private:
void doKinematicUpdate(float deltaTimeStep); void doKinematicUpdate(float deltaTimeStep);
@ -56,6 +58,8 @@ private:
float _previousDeltaTimeStep = 0.0f; float _previousDeltaTimeStep = 0.0f;
glm::vec3 _previousPositionalDelta; glm::vec3 _previousPositionalDelta;
glm::vec3 _palmOffsetFromRigidBody;
}; };
#endif // hifi_AvatarActionHold_h #endif // hifi_AvatarActionHold_h

View file

@ -58,6 +58,8 @@ public:
virtual bool shouldSuppressLocationEdits() { return false; } virtual bool shouldSuppressLocationEdits() { return false; }
virtual void prepareForPhysicsSimulation() { }
// these look in the arguments map for a named argument. if it's not found or isn't well formed, // these look in the arguments map for a named argument. if it's not found or isn't well formed,
// ok will be set to false (note that it's never set to true -- set it to true before calling these). // ok will be set to false (note that it's never set to true -- set it to true before calling these).
// if required is true, failure to extract an argument will cause a warning to be printed. // if required is true, failure to extract an argument will cause a warning to be printed.

View file

@ -15,6 +15,7 @@
#include "BulletUtil.h" #include "BulletUtil.h"
#include "PhysicsCollisionGroups.h" #include "PhysicsCollisionGroups.h"
#include "ObjectMotionState.h"
const btVector3 LOCAL_UP_AXIS(0.0f, 1.0f, 0.0f); const btVector3 LOCAL_UP_AXIS(0.0f, 1.0f, 0.0f);
const float JUMP_SPEED = 3.5f; const float JUMP_SPEED = 3.5f;
@ -379,3 +380,15 @@ void CharacterController::preSimulation() {
void CharacterController::postSimulation() { void CharacterController::postSimulation() {
// postSimulation() exists for symmetry and just in case we need to do something here later // postSimulation() exists for symmetry and just in case we need to do something here later
} }
bool CharacterController::getRigidBodyLocation(glm::vec3& avatarRigidBodyPosition, glm::quat& avatarRigidBodyRotation) {
if (!_rigidBody) {
return false;
}
const btTransform& worldTrans = _rigidBody->getCenterOfMassTransform();
avatarRigidBodyPosition = bulletToGLM(worldTrans.getOrigin()) + ObjectMotionState::getWorldOffset();
avatarRigidBodyRotation = bulletToGLM(worldTrans.getRotation());
return true;
}

View file

@ -79,6 +79,8 @@ public:
void setEnabled(bool enabled); void setEnabled(bool enabled);
bool isEnabled() const { return _enabled && _dynamicsWorld; } bool isEnabled() const { return _enabled && _dynamicsWorld; }
bool getRigidBodyLocation(glm::vec3& avatarRigidBodyPosition, glm::quat& avatarRigidBodyRotation);
protected: protected:
void updateUpAxis(const glm::quat& rotation); void updateUpAxis(const glm::quat& rotation);

View file

@ -29,12 +29,12 @@ public:
ObjectAction(EntityActionType type, const QUuid& id, EntityItemPointer ownerEntity); ObjectAction(EntityActionType type, const QUuid& id, EntityItemPointer ownerEntity);
virtual ~ObjectAction(); virtual ~ObjectAction();
virtual void removeFromSimulation(EntitySimulation* simulation) const; virtual void removeFromSimulation(EntitySimulation* simulation) const override;
virtual EntityItemWeakPointer getOwnerEntity() const { return _ownerEntity; } virtual EntityItemWeakPointer getOwnerEntity() const override { return _ownerEntity; }
virtual void setOwnerEntity(const EntityItemPointer ownerEntity) { _ownerEntity = ownerEntity; } virtual void setOwnerEntity(const EntityItemPointer ownerEntity) override { _ownerEntity = ownerEntity; }
virtual bool updateArguments(QVariantMap arguments); virtual bool updateArguments(QVariantMap arguments) override;
virtual QVariantMap getArguments(); virtual QVariantMap getArguments() override;
// this is called from updateAction and should be overridden by subclasses // this is called from updateAction and should be overridden by subclasses
virtual void updateActionWorker(float deltaTimeStep) = 0; virtual void updateActionWorker(float deltaTimeStep) = 0;
@ -43,25 +43,25 @@ public:
virtual void updateAction(btCollisionWorld* collisionWorld, btScalar deltaTimeStep); virtual void updateAction(btCollisionWorld* collisionWorld, btScalar deltaTimeStep);
virtual void debugDraw(btIDebugDraw* debugDrawer); virtual void debugDraw(btIDebugDraw* debugDrawer);
virtual QByteArray serialize() const = 0; virtual QByteArray serialize() const override = 0;
virtual void deserialize(QByteArray serializedArguments) = 0; virtual void deserialize(QByteArray serializedArguments) override = 0;
virtual bool lifetimeIsOver(); virtual bool lifetimeIsOver() override;
virtual quint64 getExpires() { return _expires; } virtual quint64 getExpires() override { return _expires; }
protected: protected:
quint64 localTimeToServerTime(quint64 timeValue) const; quint64 localTimeToServerTime(quint64 timeValue) const;
quint64 serverTimeToLocalTime(quint64 timeValue) const; quint64 serverTimeToLocalTime(quint64 timeValue) const;
virtual btRigidBody* getRigidBody(); virtual btRigidBody* getRigidBody();
virtual glm::vec3 getPosition(); virtual glm::vec3 getPosition() override;
virtual void setPosition(glm::vec3 position); virtual void setPosition(glm::vec3 position) override;
virtual glm::quat getRotation(); virtual glm::quat getRotation() override;
virtual void setRotation(glm::quat rotation); virtual void setRotation(glm::quat rotation) override;
virtual glm::vec3 getLinearVelocity(); virtual glm::vec3 getLinearVelocity() override;
virtual void setLinearVelocity(glm::vec3 linearVelocity); virtual void setLinearVelocity(glm::vec3 linearVelocity) override;
virtual glm::vec3 getAngularVelocity(); virtual glm::vec3 getAngularVelocity() override;
virtual void setAngularVelocity(glm::vec3 angularVelocity); virtual void setAngularVelocity(glm::vec3 angularVelocity) override;
virtual void activateBody(); virtual void activateBody();
virtual void forceBodyNonStatic(); virtual void forceBodyNonStatic();

View file

@ -22,13 +22,13 @@ public:
ObjectActionOffset(const QUuid& id, EntityItemPointer ownerEntity); ObjectActionOffset(const QUuid& id, EntityItemPointer ownerEntity);
virtual ~ObjectActionOffset(); virtual ~ObjectActionOffset();
virtual bool updateArguments(QVariantMap arguments); virtual bool updateArguments(QVariantMap arguments) override;
virtual QVariantMap getArguments(); virtual QVariantMap getArguments() override;
virtual void updateActionWorker(float deltaTimeStep); virtual void updateActionWorker(float deltaTimeStep) override;
virtual QByteArray serialize() const; virtual QByteArray serialize() const override;
virtual void deserialize(QByteArray serializedArguments); virtual void deserialize(QByteArray serializedArguments) override;
private: private:
static const uint16_t offsetVersion; static const uint16_t offsetVersion;

View file

@ -19,13 +19,13 @@ public:
ObjectActionSpring(const QUuid& id, EntityItemPointer ownerEntity); ObjectActionSpring(const QUuid& id, EntityItemPointer ownerEntity);
virtual ~ObjectActionSpring(); virtual ~ObjectActionSpring();
virtual bool updateArguments(QVariantMap arguments); virtual bool updateArguments(QVariantMap arguments) override;
virtual QVariantMap getArguments(); virtual QVariantMap getArguments() override;
virtual void updateActionWorker(float deltaTimeStep); virtual void updateActionWorker(float deltaTimeStep) override;
virtual QByteArray serialize() const; virtual QByteArray serialize() const override;
virtual void deserialize(QByteArray serializedArguments); virtual void deserialize(QByteArray serializedArguments) override;
protected: protected:
static const uint16_t springVersion; static const uint16_t springVersion;

View file

@ -497,3 +497,11 @@ void PhysicsEngine::removeAction(const QUuid actionID) {
_objectActions.remove(actionID); _objectActions.remove(actionID);
} }
} }
void PhysicsEngine::forEachAction(std::function<void(EntityActionPointer)> actor) {
QHashIterator<QUuid, EntityActionPointer> iter(_objectActions);
while (iter.hasNext()) {
iter.next();
actor(iter.value());
}
}

View file

@ -97,6 +97,7 @@ public:
EntityActionPointer getActionByID(const QUuid& actionID) const; EntityActionPointer getActionByID(const QUuid& actionID) const;
void addAction(EntityActionPointer action); void addAction(EntityActionPointer action);
void removeAction(const QUuid actionID); void removeAction(const QUuid actionID);
void forEachAction(std::function<void(EntityActionPointer)> actor);
private: private:
void removeContacts(ObjectMotionState* motionState); void removeContacts(ObjectMotionState* motionState);