From 8ab6974233572515f588a4ab148f6287ac60366d Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 15 Dec 2016 14:32:55 -0800 Subject: [PATCH 01/10] optimizations for processing avatar joint data --- interface/src/Application.cpp | 11 ++++- interface/src/avatar/Avatar.cpp | 82 ++++++++++++++++++++------------- libraries/animation/src/Rig.cpp | 73 ++++++++++++++++++----------- libraries/animation/src/Rig.h | 1 + 4 files changed, 106 insertions(+), 61 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b4b0ad10bb..e32e9e90b1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -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(); { diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 2f99ccfdc8..908b3def8d 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -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()->getOctreeSizeScale()); + getBounds(), DependencyManager::get()->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) { diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 886eafffcf..85e2fceb9b 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -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(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& 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]; } } } diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index 151a7ae8e9..aa091fe10c 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -311,6 +311,7 @@ protected: std::map _origRoleAnimations; + int32_t _numOverrides { 0 }; bool _lastEnableInverseKinematics { true }; bool _enableInverseKinematics { true }; From 3f687887b9d1cd2ddb69b8fb5b701bf4def07ddd Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 15 Dec 2016 15:03:20 -0800 Subject: [PATCH 02/10] faster math when unpacking JointData rotations --- libraries/animation/src/Rig.cpp | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 85e2fceb9b..dfcace1d77 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -1274,14 +1274,13 @@ void Rig::copyJointsFromJointData(const QVector& jointDataVec) { if (_animSkeleton && jointDataVec.size() == (int)_internalPoseSet._overrideFlags.size()) { // transform all the default poses into rig space. - const AnimPose geometryToRigPose(_geometryToRigTransform); std::vector overrideFlags(_internalPoseSet._overridePoses.size(), false); // start with the default rotations in absolute rig frame std::vector rotations; rotations.reserve(_animSkeleton->getAbsoluteDefaultPoses().size()); for (auto& pose : _animSkeleton->getAbsoluteDefaultPoses()) { - rotations.push_back(geometryToRigPose.rot * pose.rot); + rotations.push_back(pose.rot); } // start translations in relative frame but scaled to meters. @@ -1294,12 +1293,14 @@ void Rig::copyJointsFromJointData(const QVector& jointDataVec) { ASSERT(overrideFlags.size() == rotations.size()); // copy over rotations from the jointDataVec, which is also in absolute rig frame + const glm::quat rigToGeometryRot(glmExtractRotation(_rigToGeometryTransform)); for (int i = 0; i < jointDataVec.size(); i++) { if (isIndexValid(i)) { const JointData& data = jointDataVec.at(i); if (data.rotationSet) { overrideFlags[i] = true; - rotations[i] = data.rotation; + // JointData rotations are in rig frame + rotations[i] = rigToGeometryRot * data.rotation; } if (data.translationSet) { overrideFlags[i] = true; @@ -1310,12 +1311,6 @@ void Rig::copyJointsFromJointData(const QVector& jointDataVec) { ASSERT(_internalPoseSet._overrideFlags.size() == _internalPoseSet._overridePoses.size()); - // convert resulting rotations into geometry space. - const glm::quat rigToGeometryRot(glmExtractRotation(_rigToGeometryTransform)); - for (auto& rot : rotations) { - rot = rigToGeometryRot * rot; - } - // convert all rotations from absolute to parent relative. _animSkeleton->convertAbsoluteRotationsToRelative(rotations); From b937eff582eeca1372b17f43e3d746dcc6cd002f Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 15 Dec 2016 16:03:44 -0800 Subject: [PATCH 03/10] more faster math copying JointData --- libraries/animation/src/Rig.cpp | 60 +++++++++++---------------------- 1 file changed, 20 insertions(+), 40 deletions(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index dfcace1d77..c6aae824e4 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -1271,56 +1271,36 @@ void Rig::copyJointsIntoJointData(QVector& jointDataVec) const { void Rig::copyJointsFromJointData(const QVector& jointDataVec) { PerformanceTimer perfTimer("copyJoints"); - if (_animSkeleton && jointDataVec.size() == (int)_internalPoseSet._overrideFlags.size()) { - - // transform all the default poses into rig space. - std::vector overrideFlags(_internalPoseSet._overridePoses.size(), false); - - // start with the default rotations in absolute rig frame + if (_animSkeleton && jointDataVec.size() == (int)_internalPoseSet._relativePoses.size()) { + // make a vector of rotations in absolute-geometry-frame + const AnimPoseVec& absoluteDefaultPoses = _animSkeleton->getAbsoluteDefaultPoses(); std::vector rotations; rotations.reserve(_animSkeleton->getAbsoluteDefaultPoses().size()); - for (auto& pose : _animSkeleton->getAbsoluteDefaultPoses()) { - rotations.push_back(pose.rot); - } - - // start translations in relative frame but scaled to meters. - std::vector translations; - translations.reserve(_animSkeleton->getRelativeDefaultPoses().size()); - for (auto& pose : _animSkeleton->getRelativeDefaultPoses()) { - translations.push_back(_geometryOffset.scale * pose.trans); - } - - ASSERT(overrideFlags.size() == rotations.size()); - - // copy over rotations from the jointDataVec, which is also in absolute rig frame const glm::quat rigToGeometryRot(glmExtractRotation(_rigToGeometryTransform)); for (int i = 0; i < jointDataVec.size(); i++) { - if (isIndexValid(i)) { - const JointData& data = jointDataVec.at(i); - if (data.rotationSet) { - overrideFlags[i] = true; - // JointData rotations are in rig frame - rotations[i] = rigToGeometryRot * data.rotation; - } - if (data.translationSet) { - overrideFlags[i] = true; - translations[i] = data.translation; - } + const JointData& data = jointDataVec.at(i); + if (data.rotationSet) { + // JointData rotations are in absolute rig-frame so we rotate them to absolute geometry-frame + rotations.push_back(rigToGeometryRot * data.rotation); + } else { + rotations.push_back(absoluteDefaultPoses[i].rot); } } - ASSERT(_internalPoseSet._overrideFlags.size() == _internalPoseSet._overridePoses.size()); - - // convert all rotations from absolute to parent relative. + // convert rotations from absolute to parent relative. _animSkeleton->convertAbsoluteRotationsToRelative(rotations); - // copy the geometry space parent relative poses into _overridePoses + // store new relative poses + const AnimPoseVec& relativeDefaultPoses = _animSkeleton->getRelativeDefaultPoses(); for (int i = 0; i < jointDataVec.size(); i++) { - if (overrideFlags[i]) { - _internalPoseSet._relativePoses[i].scale = Vectors::ONE; - _internalPoseSet._relativePoses[i].rot = rotations[i]; - // scale translations from meters back into geometry units. - _internalPoseSet._relativePoses[i].trans = _invGeometryOffset.scale * translations[i]; + const JointData& data = jointDataVec.at(i); + _internalPoseSet._relativePoses[i].scale = Vectors::ONE; + _internalPoseSet._relativePoses[i].rot = rotations[i]; + if (data.translationSet) { + // JointData translations are in scaled relative-frame so we scale back to regular relative-frame + _internalPoseSet._relativePoses[i].trans = _invGeometryOffset.scale * data.translation; + } else { + _internalPoseSet._relativePoses[i].trans = relativeDefaultPoses[i].trans; } } } From 383064999051202ff6e61258278bc08ec7e8bfd8 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 16 Dec 2016 08:46:11 -0800 Subject: [PATCH 04/10] remove debugging and profiling --- interface/src/avatar/Avatar.cpp | 3 --- libraries/animation/src/Rig.cpp | 7 ++----- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 908b3def8d..a79d2372c5 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -645,8 +645,6 @@ 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 @@ -670,7 +668,6 @@ 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 { diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index c6aae824e4..b6bb8ccc8f 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -929,11 +929,8 @@ void Rig::updateAnimations(float deltaTime, glm::mat4 rootTransform) { buildAbsoluteRigPoses(_internalPoseSet._relativePoses, _internalPoseSet._absolutePoses); // copy internal poses to external poses - { - PerformanceTimer perfTimer("copy"); - QWriteLocker writeLock(&_externalPoseSetLock); - _externalPoseSet = _internalPoseSet; - } + QWriteLocker writeLock(&_externalPoseSetLock); + _externalPoseSet = _internalPoseSet; } void Rig::inverseKinematics(int endIndex, glm::vec3 targetPosition, const glm::quat& targetRotation, float priority, From 2209c0ebbac75a665350ce67eb2f63dd260535a9 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 16 Dec 2016 13:10:30 -0800 Subject: [PATCH 05/10] remove debug hook for dumping stats to logs --- interface/src/Application.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e32e9e90b1..d92ba53f6e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2572,7 +2572,6 @@ 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; @@ -2663,8 +2662,7 @@ void Application::keyPressEvent(QKeyEvent* event) { break; case Qt::Key_F: { - //_physicsEngine->dumpNextStats(); - dumpAllTimerRecords = true; // adebug hack + _physicsEngine->dumpNextStats(); break; } @@ -3410,11 +3408,6 @@ void Application::idle(float nsecsElapsed) { } _overlayConductor.update(secondsSinceLastUpdate); - // adebug hack - if (dumpAllTimerRecords) { - PerformanceTimer::dumpAllTimerRecords(); - dumpAllTimerRecords = false; - } } void Application::setLowVelocityFilter(bool lowVelocityFilter) { From 0b0c3f0be4cee9aeea4a78f2239bd247082903fb Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 20 Dec 2016 16:43:50 -0800 Subject: [PATCH 06/10] cleanup some if-logic --- libraries/render-utils/src/Model.cpp | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 14c80faa96..436574a1ff 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -234,17 +234,19 @@ void Model::updateRenderItems() { render::PendingChanges pendingChanges; foreach (auto itemID, self->_modelMeshRenderItems.keys()) { pendingChanges.updateItem(itemID, [modelTransform, modelMeshOffset, deleteGeometryCounter](ModelMeshPartPayload& data) { - if (!data.hasStartedFade() && data._model && data._model->isLoaded() && data._model->getGeometry()->areTexturesLoaded()) { - data.startFade(); - } - // Ensure the model geometry was not reset between frames - if (data._model && data._model->isLoaded() && deleteGeometryCounter == data._model->_deleteGeometryCounter) { - // lazy update of cluster matrices used for rendering. We need to update them here, so we can correctly update the bounding box. - data._model->updateClusterMatrices(modelTransform.getTranslation(), modelTransform.getRotation()); + if (data._model && data._model->isLoaded()) { + if (!data.hasStartedFade() && data._model->getGeometry()->areTexturesLoaded()) { + data.startFade(); + } + // Ensure the model geometry was not reset between frames + if (deleteGeometryCounter == data._model->_deleteGeometryCounter) { + // lazy update of cluster matrices used for rendering. We need to update them here, so we can correctly update the bounding box. + data._model->updateClusterMatrices(modelTransform.getTranslation(), modelTransform.getRotation()); - // update the model transform and bounding box for this render item. - const Model::MeshState& state = data._model->_meshStates.at(data._meshIndex); - data.updateTransformForSkinnedMesh(modelTransform, modelMeshOffset, state.clusterMatrices); + // update the model transform and bounding box for this render item. + const Model::MeshState& state = data._model->_meshStates.at(data._meshIndex); + data.updateTransformForSkinnedMesh(modelTransform, modelMeshOffset, state.clusterMatrices); + } } }); } From 890e35e96ec38e1aa24c892ac4b6a9efdf2bc064 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 21 Dec 2016 15:37:23 -0800 Subject: [PATCH 07/10] cleanup unnecessary scope and swap if-check order --- libraries/animation/src/Rig.cpp | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index b6bb8ccc8f..eec8035957 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -1195,7 +1195,7 @@ bool Rig::getModelRegistrationPoint(glm::vec3& modelRegistrationPointOut) const void Rig::applyOverridePoses() { PerformanceTimer perfTimer("override"); - if (!_animSkeleton || _numOverrides == 0) { + if (_numOverrides == 0 || !_animSkeleton) { return; } @@ -1218,17 +1218,15 @@ void Rig::buildAbsoluteRigPoses(const AnimPoseVec& relativePoses, AnimPoseVec& a ASSERT(_animSkeleton->getNumJoints() == (int)relativePoses.size()); - { - 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]; - } + 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]; } } } From b3be7f0f3eedea240de5fd05401ce0dcc2c62977 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 22 Dec 2016 10:42:05 -0800 Subject: [PATCH 08/10] restore expensive version of Avatar::updatePalms() --- interface/src/avatar/Avatar.cpp | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index a79d2372c5..dc5b6233aa 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -1293,23 +1293,10 @@ void Avatar::setOrientation(const glm::quat& orientation) { void Avatar::updatePalms() { PerformanceTimer perfTimer("palms"); // update thread-safe caches - 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); - } + _leftPalmRotationCache.set(getUncachedLeftPalmRotation()); + _rightPalmRotationCache.set(getUncachedRightPalmRotation()); + _leftPalmPositionCache.set(getUncachedLeftPalmPosition()); + _rightPalmPositionCache.set(getUncachedRightPalmPosition()); } void Avatar::setParentID(const QUuid& parentID) { From 4161775673c5709cbd76d7ee133d284b9f2c60e8 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 22 Dec 2016 10:54:58 -0800 Subject: [PATCH 09/10] restore context around lock --- libraries/animation/src/Rig.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index eec8035957..6066905943 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -929,8 +929,10 @@ void Rig::updateAnimations(float deltaTime, glm::mat4 rootTransform) { buildAbsoluteRigPoses(_internalPoseSet._relativePoses, _internalPoseSet._absolutePoses); // copy internal poses to external poses - QWriteLocker writeLock(&_externalPoseSetLock); - _externalPoseSet = _internalPoseSet; + { + QWriteLocker writeLock(&_externalPoseSetLock); + _externalPoseSet = _internalPoseSet; + } } void Rig::inverseKinematics(int endIndex, glm::vec3 targetPosition, const glm::quat& targetRotation, float priority, From a5efc08473ed05209a89a782617e3dde77c4eaf1 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 22 Dec 2016 15:32:30 -0800 Subject: [PATCH 10/10] use PROFILE_COUNTER not SAMPLE_PROFILE_COUNTER --- interface/src/avatar/AvatarManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 53f17e9635..c5222641ff 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -170,9 +170,9 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { // simulate avatar fades simulateAvatarFades(deltaTime); - SAMPLE_PROFILE_COUNTER(0.1f, simulation_avatar, "NumAvatarsPerSec", + PROFILE_COUNTER(simulation_avatar, "NumAvatarsPerSec", { { "NumAvatarsPerSec", (float)(size() * USECS_PER_SECOND) / (float)(usecTimestampNow() - start) } }); - SAMPLE_PROFILE_COUNTER(0.1f, simulation_avatar, "NumJointsPerSec", { { "NumJointsPerSec", Avatar::getNumJointsProcessedPerSecond() } }); + PROFILE_COUNTER(simulation_avatar, "NumJointsPerSec", { { "NumJointsPerSec", Avatar::getNumJointsProcessedPerSecond() } }); } void AvatarManager::postUpdate(float deltaTime) {