Merge pull request #6673 from hyperlogic/tony/get-palm-thread-safe

Make Avatar palm position/rotation accessors thread safe
This commit is contained in:
Brad Hefta-Gaub 2016-01-05 13:07:47 -08:00
commit c2f2f950fb
5 changed files with 98 additions and 20 deletions

View file

@ -237,6 +237,7 @@ void Avatar::simulate(float deltaTime) {
measureMotionDerivatives(deltaTime);
simulateAttachments(deltaTime);
updatePalms();
}
bool Avatar::isLookingAtMe(AvatarSharedPointer avatar) const {
@ -1155,34 +1156,24 @@ void Avatar::rebuildCollisionShape() {
}
}
// thread-safe
glm::vec3 Avatar::getLeftPalmPosition() {
glm::vec3 leftHandPosition;
getSkeletonModel().getLeftHandPosition(leftHandPosition);
glm::quat leftRotation;
getSkeletonModel().getJointRotationInWorldFrame(getSkeletonModel().getLeftHandJointIndex(), leftRotation);
leftHandPosition += HAND_TO_PALM_OFFSET * glm::inverse(leftRotation);
return leftHandPosition;
return _leftPalmPositionCache.get();
}
// thread-safe
glm::quat Avatar::getLeftPalmRotation() {
glm::quat leftRotation;
getSkeletonModel().getJointRotationInWorldFrame(getSkeletonModel().getLeftHandJointIndex(), leftRotation);
return leftRotation;
return _leftPalmRotationCache.get();
}
// thread-safe
glm::vec3 Avatar::getRightPalmPosition() {
glm::vec3 rightHandPosition;
getSkeletonModel().getRightHandPosition(rightHandPosition);
glm::quat rightRotation;
getSkeletonModel().getJointRotationInWorldFrame(getSkeletonModel().getRightHandJointIndex(), rightRotation);
rightHandPosition += HAND_TO_PALM_OFFSET * glm::inverse(rightRotation);
return rightHandPosition;
return _rightPalmPositionCache.get();
}
// thread-safe
glm::quat Avatar::getRightPalmRotation() {
glm::quat rightRotation;
getSkeletonModel().getJointRotationInWorldFrame(getSkeletonModel().getRightHandJointIndex(), rightRotation);
return rightRotation;
return _rightPalmRotationCache.get();
}
void Avatar::setPosition(const glm::vec3& position) {
@ -1194,3 +1185,24 @@ void Avatar::setOrientation(const glm::quat& orientation) {
AvatarData::setOrientation(orientation);
updateAttitude();
}
void Avatar::updatePalms() {
// get palm rotations
glm::quat leftPalmRotation, rightPalmRotation;
getSkeletonModel().getJointRotationInWorldFrame(getSkeletonModel().getLeftHandJointIndex(), leftPalmRotation);
getSkeletonModel().getJointRotationInWorldFrame(getSkeletonModel().getRightHandJointIndex(), rightPalmRotation);
// get palm positions
glm::vec3 leftPalmPosition, rightPalmPosition;
getSkeletonModel().getLeftHandPosition(leftPalmPosition);
getSkeletonModel().getRightHandPosition(rightPalmPosition);
leftPalmPosition += HAND_TO_PALM_OFFSET * glm::inverse(leftPalmRotation);
rightPalmPosition += HAND_TO_PALM_OFFSET * glm::inverse(rightPalmRotation);
// update thread-safe caches
_leftPalmRotationCache.set(leftPalmRotation);
_rightPalmRotationCache.set(rightPalmRotation);
_leftPalmPositionCache.set(leftPalmPosition);
_rightPalmPositionCache.set(rightPalmPosition);
}

View file

@ -27,6 +27,7 @@
#include "SkeletonModel.h"
#include "world.h"
#include "Rig.h"
#include <ThreadSafeValueCache.h>
namespace render {
template <> const ItemKey payloadGetKey(const AvatarSharedPointer& avatar);
@ -227,8 +228,15 @@ protected:
virtual void updateJointMappings() override;
virtual void updatePalms();
render::ItemID _renderItemID;
ThreadSafeValueCache<glm::vec3> _leftPalmPositionCache { glm::vec3() };
ThreadSafeValueCache<glm::quat> _leftPalmRotationCache { glm::quat() };
ThreadSafeValueCache<glm::vec3> _rightPalmPositionCache { glm::vec3() };
ThreadSafeValueCache<glm::quat> _rightPalmRotationCache { glm::quat() };
private:
bool _initialized;
NetworkTexturePointer _billboardTexture;

View file

@ -417,6 +417,8 @@ void MyAvatar::updateSensorToWorldMatrix() {
// position when driven from the head.
glm::mat4 desiredMat = createMatFromQuatAndPos(getOrientation(), getPosition());
_sensorToWorldMatrix = desiredMat * glm::inverse(_bodySensorMatrix);
lateUpdatePalms();
}
// Update avatar head rotation with sensor data
@ -1839,3 +1841,8 @@ QScriptValue audioListenModeToScriptValue(QScriptEngine* engine, const AudioList
void audioListenModeFromScriptValue(const QScriptValue& object, AudioListenerMode& audioListenerMode) {
audioListenerMode = (AudioListenerMode)object.toUInt16();
}
void MyAvatar::lateUpdatePalms() {
Avatar::updatePalms();
}

View file

@ -311,12 +311,14 @@ private:
void setVisibleInSceneIfReady(Model* model, render::ScenePointer scene, bool visiblity);
PalmData getActivePalmData(int palmIndex) const;
// derive avatar body position and orientation from the current HMD Sensor location.
// results are in HMD frame
glm::mat4 deriveBodyFromHMDSensor() const;
virtual void updatePalms() override {}
void lateUpdatePalms();
float _driveKeys[MAX_DRIVE_KEYS];
bool _wasPushing;
bool _isPushing;

View file

@ -0,0 +1,49 @@
//
// ThreadSafeValueCache.h
// interface/src/avatar
//
// Copyright 2012 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_ThreadSafeValueCache_h
#define hifi_ThreadSafeValueCache_h
#include <mutex>
// Helper class for for sharing a value type between threads.
// It allows many threads to get or set a value atomically.
// This provides cache semantics, any get will return the last set value.
//
// For example: This can be used to copy values between C++ code running on the application thread
// and JavaScript which is running on a different thread.
template <typename T>
class ThreadSafeValueCache {
public:
ThreadSafeValueCache(const T& v) : _value { v } {}
// returns atomic copy of the cached value.
T get() const {
std::lock_guard<std::mutex> guard(_mutex);
return _value;
}
// will reflect copy of value into the cache.
void set(const T& v) {
std::lock_guard<std::mutex> guard(_mutex);
_value = v;
}
private:
mutable std::mutex _mutex;
T _value;
// no copies
ThreadSafeValueCache(const ThreadSafeValueCache&) = delete;
ThreadSafeValueCache& operator=(const ThreadSafeValueCache&) = delete;
};
#endif // #define hifi_ThreadSafeValueCache_h