3
0
Fork 0
mirror of https://github.com/JulianGro/overte.git synced 2025-05-06 00:07:58 +02:00

optimizations for processing avatar joint data

This commit is contained in:
Andrew Meadows 2016-12-15 14:32:55 -08:00
parent 08cfd8a40e
commit 8ab6974233
4 changed files with 106 additions and 61 deletions
interface/src
libraries/animation/src

View file

@ -2572,6 +2572,7 @@ bool Application::eventFilter(QObject* object, QEvent* event) {
}
static bool _altPressed{ false };
static bool dumpAllTimerRecords { false }; // adebug hack
void Application::keyPressEvent(QKeyEvent* event) {
_altPressed = event->key() == Qt::Key_Alt;
@ -2662,7 +2663,8 @@ void Application::keyPressEvent(QKeyEvent* event) {
break;
case Qt::Key_F: {
_physicsEngine->dumpNextStats();
//_physicsEngine->dumpNextStats();
dumpAllTimerRecords = true; // adebug hack
break;
}
@ -3408,6 +3410,11 @@ void Application::idle(float nsecsElapsed) {
}
_overlayConductor.update(secondsSinceLastUpdate);
// adebug hack
if (dumpAllTimerRecords) {
PerformanceTimer::dumpAllTimerRecords();
dumpAllTimerRecords = false;
}
}
void Application::setLowVelocityFilter(bool lowVelocityFilter) {
@ -4307,7 +4314,7 @@ void Application::update(float deltaTime) {
// AvatarManager update
{
PerformanceTimer perfTimer("AvatarManger");
PerformanceTimer perfTimer("AvatarManager");
_avatarSimCounter.increment();
{

View file

@ -275,13 +275,16 @@ void Avatar::updateAvatarEntities() {
}
AvatarEntityIDs recentlyDettachedAvatarEntities = getAndClearRecentlyDetachedIDs();
_avatarEntitiesLock.withReadLock([&] {
foreach (auto entityID, recentlyDettachedAvatarEntities) {
if (!_avatarEntityData.contains(entityID)) {
entityTree->deleteEntity(entityID, true, true);
if (!recentlyDettachedAvatarEntities.empty()) {
// only lock this thread when absolutely necessary
_avatarEntitiesLock.withReadLock([&] {
foreach (auto entityID, recentlyDettachedAvatarEntities) {
if (!_avatarEntityData.contains(entityID)) {
entityTree->deleteEntity(entityID, true, true);
}
}
}
});
});
}
});
if (success) {
@ -299,18 +302,25 @@ void Avatar::simulate(float deltaTime) {
}
animateScaleChanges(deltaTime);
bool avatarPositionInView = false;
bool avatarMeshInView = false;
bool avatarInView = false;
{ // update the shouldAnimate flag to match whether or not we will render the avatar.
PerformanceTimer perfTimer("cull");
ViewFrustum viewFrustum;
{
PerformanceTimer perfTimer("LOD");
// simple frustum check
PerformanceTimer perfTimer("inView");
ViewFrustum viewFrustum;
qApp->copyDisplayViewFrustum(viewFrustum);
avatarInView = viewFrustum.sphereIntersectsFrustum(getPosition(), getBoundingRadius())
|| viewFrustum.boxIntersectsFrustum(_skeletonModel->getRenderableMeshBound());
}
PerformanceTimer lodPerfTimer("LOD");
if (avatarInView) {
const float MINIMUM_VISIBILITY_FOR_ON = 0.4f;
const float MAXIMUM_VISIBILITY_FOR_OFF = 0.6f;
ViewFrustum viewFrustum;
qApp->copyViewFrustum(viewFrustum);
float visibility = calculateRenderAccuracy(viewFrustum.getPosition(),
getBounds(), DependencyManager::get<LODManager>()->getOctreeSizeScale());
getBounds(), DependencyManager::get<LODManager>()->getOctreeSizeScale());
if (!_shouldAnimate) {
if (visibility > MINIMUM_VISIBILITY_FOR_ON) {
_shouldAnimate = true;
@ -321,19 +331,11 @@ void Avatar::simulate(float deltaTime) {
qCDebug(interfaceapp) << "Optimizing" << (isMyAvatar() ? "myself" : getSessionUUID()) << "for visibility" << visibility;
}
}
{
PerformanceTimer perfTimer("inView");
// simple frustum check
float boundingRadius = getBoundingRadius();
qApp->copyDisplayViewFrustum(viewFrustum);
avatarPositionInView = viewFrustum.sphereIntersectsFrustum(getPosition(), boundingRadius);
avatarMeshInView = viewFrustum.boxIntersectsFrustum(_skeletonModel->getRenderableMeshBound());
}
}
uint64_t start = usecTimestampNow();
if (_shouldAnimate && !_shouldSkipRender && (avatarPositionInView || avatarMeshInView)) {
// CRUFT? _shouldSkipRender is never set 'true'
if (_shouldAnimate && avatarInView && !_shouldSkipRender) {
{
PerformanceTimer perfTimer("skeleton");
_skeletonModel->getRig()->copyJointsFromJointData(_jointData);
@ -643,6 +645,8 @@ glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const {
}
void Avatar::fixupModelsInScene() {
#define ADEBUG
#ifdef ADEBUG
_attachmentsToDelete.clear();
// check to see if when we added our models to the scene they were ready, if they were not ready, then
@ -666,6 +670,7 @@ void Avatar::fixupModelsInScene() {
_attachmentsToDelete.insert(_attachmentsToDelete.end(), _attachmentsToRemove.begin(), _attachmentsToRemove.end());
_attachmentsToRemove.clear();
scene->enqueuePendingChanges(pendingChanges);
#endif // ADEBUG
}
bool Avatar::shouldRenderHead(const RenderArgs* renderArgs) const {
@ -725,7 +730,7 @@ glm::vec3 Avatar::getDisplayNamePosition() const {
glm::vec3 bodyUpDirection = getBodyUpDirection();
DEBUG_VALUE("bodyUpDirection =", bodyUpDirection);
if (getSkeletonModel()->getNeckPosition(namePosition)) {
if (_skeletonModel->getNeckPosition(namePosition)) {
float headHeight = getHeadHeight();
DEBUG_VALUE("namePosition =", namePosition);
DEBUG_VALUE("headHeight =", headHeight);
@ -1244,8 +1249,8 @@ glm::vec3 Avatar::getUncachedLeftPalmPosition() const {
return leftPalmPosition;
}
// avatar didn't have a LeftHandMiddle1 joint, fall back on this:
getSkeletonModel()->getJointRotationInWorldFrame(getSkeletonModel()->getLeftHandJointIndex(), leftPalmRotation);
getSkeletonModel()->getLeftHandPosition(leftPalmPosition);
_skeletonModel->getJointRotationInWorldFrame(_skeletonModel->getLeftHandJointIndex(), leftPalmRotation);
_skeletonModel->getLeftHandPosition(leftPalmPosition);
leftPalmPosition += HAND_TO_PALM_OFFSET * glm::inverse(leftPalmRotation);
return leftPalmPosition;
}
@ -1253,7 +1258,7 @@ glm::vec3 Avatar::getUncachedLeftPalmPosition() const {
glm::quat Avatar::getUncachedLeftPalmRotation() const {
assert(QThread::currentThread() == thread()); // main thread access only
glm::quat leftPalmRotation;
getSkeletonModel()->getJointRotationInWorldFrame(getSkeletonModel()->getLeftHandJointIndex(), leftPalmRotation);
_skeletonModel->getJointRotationInWorldFrame(_skeletonModel->getLeftHandJointIndex(), leftPalmRotation);
return leftPalmRotation;
}
@ -1265,8 +1270,8 @@ glm::vec3 Avatar::getUncachedRightPalmPosition() const {
return rightPalmPosition;
}
// avatar didn't have a RightHandMiddle1 joint, fall back on this:
getSkeletonModel()->getJointRotationInWorldFrame(getSkeletonModel()->getRightHandJointIndex(), rightPalmRotation);
getSkeletonModel()->getRightHandPosition(rightPalmPosition);
_skeletonModel->getJointRotationInWorldFrame(_skeletonModel->getRightHandJointIndex(), rightPalmRotation);
_skeletonModel->getRightHandPosition(rightPalmPosition);
rightPalmPosition += HAND_TO_PALM_OFFSET * glm::inverse(rightPalmRotation);
return rightPalmPosition;
}
@ -1274,7 +1279,7 @@ glm::vec3 Avatar::getUncachedRightPalmPosition() const {
glm::quat Avatar::getUncachedRightPalmRotation() const {
assert(QThread::currentThread() == thread()); // main thread access only
glm::quat rightPalmRotation;
getSkeletonModel()->getJointRotationInWorldFrame(getSkeletonModel()->getRightHandJointIndex(), rightPalmRotation);
_skeletonModel->getJointRotationInWorldFrame(_skeletonModel->getRightHandJointIndex(), rightPalmRotation);
return rightPalmRotation;
}
@ -1291,10 +1296,23 @@ void Avatar::setOrientation(const glm::quat& orientation) {
void Avatar::updatePalms() {
PerformanceTimer perfTimer("palms");
// update thread-safe caches
_leftPalmRotationCache.set(getUncachedLeftPalmRotation());
_rightPalmRotationCache.set(getUncachedRightPalmRotation());
_leftPalmPositionCache.set(getUncachedLeftPalmPosition());
_rightPalmPositionCache.set(getUncachedRightPalmPosition());
glm::quat rotation;
int i = _skeletonModel->getLeftHandJointIndex();
if (_skeletonModel->getJointRotationInWorldFrame(i, rotation)) {
_leftPalmRotationCache.set(rotation);
}
glm::vec3 position;
if (_skeletonModel->getJointPositionInWorldFrame(i, position)) {
_leftPalmPositionCache.set(position);
}
i = _skeletonModel->getRightHandJointIndex();
if (_skeletonModel->getJointRotationInWorldFrame(i, rotation)) {
_rightPalmRotationCache.set(rotation);
}
if (_skeletonModel->getJointPositionInWorldFrame(i, position)) {
_rightPalmPositionCache.set(position);
}
}
void Avatar::setParentID(const QUuid& parentID) {

View file

@ -161,6 +161,7 @@ void Rig::destroyAnimGraph() {
_internalPoseSet._absolutePoses.clear();
_internalPoseSet._overridePoses.clear();
_internalPoseSet._overrideFlags.clear();
_numOverrides = 0;
}
void Rig::initJointStates(const FBXGeometry& geometry, const glm::mat4& modelOffset) {
@ -180,6 +181,7 @@ void Rig::initJointStates(const FBXGeometry& geometry, const glm::mat4& modelOff
_internalPoseSet._overrideFlags.clear();
_internalPoseSet._overrideFlags.resize(_animSkeleton->getNumJoints(), false);
_numOverrides = 0;
buildAbsoluteRigPoses(_animSkeleton->getRelativeDefaultPoses(), _absoluteDefaultPoses);
@ -207,6 +209,7 @@ void Rig::reset(const FBXGeometry& geometry) {
_internalPoseSet._overrideFlags.clear();
_internalPoseSet._overrideFlags.resize(_animSkeleton->getNumJoints(), false);
_numOverrides = 0;
buildAbsoluteRigPoses(_animSkeleton->getRelativeDefaultPoses(), _absoluteDefaultPoses);
@ -276,13 +279,17 @@ void Rig::setModelOffset(const glm::mat4& modelOffsetMat) {
void Rig::clearJointState(int index) {
if (isIndexValid(index)) {
_internalPoseSet._overrideFlags[index] = false;
if (_internalPoseSet._overrideFlags[index]) {
_internalPoseSet._overrideFlags[index] = false;
--_numOverrides;
}
_internalPoseSet._overridePoses[index] = _animSkeleton->getRelativeDefaultPose(index);
}
}
void Rig::clearJointStates() {
_internalPoseSet._overrideFlags.clear();
_numOverrides = 0;
if (_animSkeleton) {
_internalPoseSet._overrideFlags.resize(_animSkeleton->getNumJoints());
_internalPoseSet._overridePoses = _animSkeleton->getRelativeDefaultPoses();
@ -291,7 +298,10 @@ void Rig::clearJointStates() {
void Rig::clearJointAnimationPriority(int index) {
if (isIndexValid(index)) {
_internalPoseSet._overrideFlags[index] = false;
if (_internalPoseSet._overrideFlags[index]) {
_internalPoseSet._overrideFlags[index] = false;
--_numOverrides;
}
_internalPoseSet._overridePoses[index] = _animSkeleton->getRelativeDefaultPose(index);
}
}
@ -320,7 +330,10 @@ void Rig::setJointTranslation(int index, bool valid, const glm::vec3& translatio
if (isIndexValid(index)) {
if (valid) {
assert(_internalPoseSet._overrideFlags.size() == _internalPoseSet._overridePoses.size());
_internalPoseSet._overrideFlags[index] = true;
if (!_internalPoseSet._overrideFlags[index]) {
_internalPoseSet._overrideFlags[index] = true;
++_numOverrides;
}
_internalPoseSet._overridePoses[index].trans = translation;
}
}
@ -329,7 +342,10 @@ void Rig::setJointTranslation(int index, bool valid, const glm::vec3& translatio
void Rig::setJointState(int index, bool valid, const glm::quat& rotation, const glm::vec3& translation, float priority) {
if (isIndexValid(index)) {
assert(_internalPoseSet._overrideFlags.size() == _internalPoseSet._overridePoses.size());
_internalPoseSet._overrideFlags[index] = true;
if (!_internalPoseSet._overrideFlags[index]) {
_internalPoseSet._overrideFlags[index] = true;
++_numOverrides;
}
_internalPoseSet._overridePoses[index].rot = rotation;
_internalPoseSet._overridePoses[index].trans = translation;
}
@ -339,7 +355,10 @@ void Rig::setJointRotation(int index, bool valid, const glm::quat& rotation, flo
if (isIndexValid(index)) {
if (valid) {
ASSERT(_internalPoseSet._overrideFlags.size() == _internalPoseSet._overridePoses.size());
_internalPoseSet._overrideFlags[index] = true;
if (!_internalPoseSet._overrideFlags[index]) {
_internalPoseSet._overrideFlags[index] = true;
++_numOverrides;
}
_internalPoseSet._overridePoses[index].rot = rotation;
}
}
@ -518,7 +537,7 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
// sine wave LFO var for testing.
static float t = 0.0f;
_animVars.set("sine", 2.0f * static_cast<float>(0.5 * sin(t) + 0.5));
_animVars.set("sine", 2.0f * 0.5f * sinf(t) + 0.5f);
float moveForwardAlpha = 0.0f;
float moveBackwardAlpha = 0.0f;
@ -884,10 +903,12 @@ void Rig::updateAnimationStateHandlers() { // called on avatar update thread (wh
void Rig::updateAnimations(float deltaTime, glm::mat4 rootTransform) {
PROFILE_RANGE_EX(simulation_animation, __FUNCTION__, 0xffff00ff, 0);
PerformanceTimer perfTimer("updateAnimations");
setModelOffset(rootTransform);
if (_animNode) {
PerformanceTimer perfTimer("handleTriggers");
updateAnimationStateHandlers();
_animVars.setRigToGeometryTransform(_rigToGeometryTransform);
@ -903,13 +924,13 @@ void Rig::updateAnimations(float deltaTime, glm::mat4 rootTransform) {
for (auto& trigger : triggersOut) {
_animVars.setTrigger(trigger);
}
applyOverridePoses();
}
applyOverridePoses();
buildAbsoluteRigPoses(_internalPoseSet._relativePoses, _internalPoseSet._absolutePoses);
// copy internal poses to external poses
{
PerformanceTimer perfTimer("copy");
QWriteLocker writeLock(&_externalPoseSetLock);
_externalPoseSet = _internalPoseSet;
}
@ -1176,7 +1197,8 @@ bool Rig::getModelRegistrationPoint(glm::vec3& modelRegistrationPointOut) const
}
void Rig::applyOverridePoses() {
if (!_animSkeleton) {
PerformanceTimer perfTimer("override");
if (!_animSkeleton || _numOverrides == 0) {
return;
}
@ -1192,28 +1214,26 @@ void Rig::applyOverridePoses() {
}
void Rig::buildAbsoluteRigPoses(const AnimPoseVec& relativePoses, AnimPoseVec& absolutePosesOut) {
PerformanceTimer perfTimer("buildAbsolute");
if (!_animSkeleton) {
return;
}
ASSERT(_animSkeleton->getNumJoints() == (int)relativePoses.size());
// flatten all poses out so they are absolute not relative
absolutePosesOut.resize(relativePoses.size());
for (int i = 0; i < (int)relativePoses.size(); i++) {
int parentIndex = _animSkeleton->getParentIndex(i);
if (parentIndex == -1) {
absolutePosesOut[i] = relativePoses[i];
} else {
absolutePosesOut[i] = absolutePosesOut[parentIndex] * relativePoses[i];
{
absolutePosesOut.resize(relativePoses.size());
AnimPose geometryToRigTransform(_geometryToRigTransform);
for (int i = 0; i < (int)relativePoses.size(); i++) {
int parentIndex = _animSkeleton->getParentIndex(i);
if (parentIndex == -1) {
// transform all root absolute poses into rig space
absolutePosesOut[i] = geometryToRigTransform * relativePoses[i];
} else {
absolutePosesOut[i] = absolutePosesOut[parentIndex] * relativePoses[i];
}
}
}
// transform all absolute poses into rig space.
AnimPose geometryToRigTransform(_geometryToRigTransform);
for (int i = 0; i < (int)absolutePosesOut.size(); i++) {
absolutePosesOut[i] = geometryToRigTransform * absolutePosesOut[i];
}
}
glm::mat4 Rig::getJointTransform(int jointIndex) const {
@ -1302,11 +1322,10 @@ void Rig::copyJointsFromJointData(const QVector<JointData>& jointDataVec) {
// copy the geometry space parent relative poses into _overridePoses
for (int i = 0; i < jointDataVec.size(); i++) {
if (overrideFlags[i]) {
_internalPoseSet._overrideFlags[i] = true;
_internalPoseSet._overridePoses[i].scale = Vectors::ONE;
_internalPoseSet._overridePoses[i].rot = rotations[i];
_internalPoseSet._relativePoses[i].scale = Vectors::ONE;
_internalPoseSet._relativePoses[i].rot = rotations[i];
// scale translations from meters back into geometry units.
_internalPoseSet._overridePoses[i].trans = _invGeometryOffset.scale * translations[i];
_internalPoseSet._relativePoses[i].trans = _invGeometryOffset.scale * translations[i];
}
}
}

View file

@ -311,6 +311,7 @@ protected:
std::map<QString, AnimNode::Pointer> _origRoleAnimations;
int32_t _numOverrides { 0 };
bool _lastEnableInverseKinematics { true };
bool _enableInverseKinematics { true };