mirror of
https://github.com/overte-org/overte.git
synced 2025-08-11 14:42:03 +02:00
Merge pull request #9255 from AndrewMeadows/benji-002
optimization of incoming avatar joint data in interface client
This commit is contained in:
commit
9128d4b140
5 changed files with 99 additions and 103 deletions
|
@ -4307,7 +4307,7 @@ void Application::update(float deltaTime) {
|
||||||
|
|
||||||
// AvatarManager update
|
// AvatarManager update
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("AvatarManger");
|
PerformanceTimer perfTimer("AvatarManager");
|
||||||
_avatarSimCounter.increment();
|
_avatarSimCounter.increment();
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
@ -275,13 +275,16 @@ void Avatar::updateAvatarEntities() {
|
||||||
}
|
}
|
||||||
|
|
||||||
AvatarEntityIDs recentlyDettachedAvatarEntities = getAndClearRecentlyDetachedIDs();
|
AvatarEntityIDs recentlyDettachedAvatarEntities = getAndClearRecentlyDetachedIDs();
|
||||||
_avatarEntitiesLock.withReadLock([&] {
|
if (!recentlyDettachedAvatarEntities.empty()) {
|
||||||
foreach (auto entityID, recentlyDettachedAvatarEntities) {
|
// only lock this thread when absolutely necessary
|
||||||
if (!_avatarEntityData.contains(entityID)) {
|
_avatarEntitiesLock.withReadLock([&] {
|
||||||
entityTree->deleteEntity(entityID, true, true);
|
foreach (auto entityID, recentlyDettachedAvatarEntities) {
|
||||||
|
if (!_avatarEntityData.contains(entityID)) {
|
||||||
|
entityTree->deleteEntity(entityID, true, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
|
@ -299,18 +302,25 @@ void Avatar::simulate(float deltaTime) {
|
||||||
}
|
}
|
||||||
animateScaleChanges(deltaTime);
|
animateScaleChanges(deltaTime);
|
||||||
|
|
||||||
bool avatarPositionInView = false;
|
bool avatarInView = false;
|
||||||
bool avatarMeshInView = false;
|
|
||||||
{ // update the shouldAnimate flag to match whether or not we will render the avatar.
|
{ // update the shouldAnimate flag to match whether or not we will render the avatar.
|
||||||
PerformanceTimer perfTimer("cull");
|
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 MINIMUM_VISIBILITY_FOR_ON = 0.4f;
|
||||||
const float MAXIMUM_VISIBILITY_FOR_OFF = 0.6f;
|
const float MAXIMUM_VISIBILITY_FOR_OFF = 0.6f;
|
||||||
|
ViewFrustum viewFrustum;
|
||||||
qApp->copyViewFrustum(viewFrustum);
|
qApp->copyViewFrustum(viewFrustum);
|
||||||
float visibility = calculateRenderAccuracy(viewFrustum.getPosition(),
|
float visibility = calculateRenderAccuracy(viewFrustum.getPosition(),
|
||||||
getBounds(), DependencyManager::get<LODManager>()->getOctreeSizeScale());
|
getBounds(), DependencyManager::get<LODManager>()->getOctreeSizeScale());
|
||||||
if (!_shouldAnimate) {
|
if (!_shouldAnimate) {
|
||||||
if (visibility > MINIMUM_VISIBILITY_FOR_ON) {
|
if (visibility > MINIMUM_VISIBILITY_FOR_ON) {
|
||||||
_shouldAnimate = true;
|
_shouldAnimate = true;
|
||||||
|
@ -321,19 +331,11 @@ void Avatar::simulate(float deltaTime) {
|
||||||
qCDebug(interfaceapp) << "Optimizing" << (isMyAvatar() ? "myself" : getSessionUUID()) << "for visibility" << visibility;
|
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();
|
uint64_t start = usecTimestampNow();
|
||||||
if (_shouldAnimate && !_shouldSkipRender && (avatarPositionInView || avatarMeshInView)) {
|
// CRUFT? _shouldSkipRender is never set 'true'
|
||||||
|
if (_shouldAnimate && avatarInView && !_shouldSkipRender) {
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("skeleton");
|
PerformanceTimer perfTimer("skeleton");
|
||||||
_skeletonModel->getRig()->copyJointsFromJointData(_jointData);
|
_skeletonModel->getRig()->copyJointsFromJointData(_jointData);
|
||||||
|
@ -725,7 +727,7 @@ glm::vec3 Avatar::getDisplayNamePosition() const {
|
||||||
glm::vec3 bodyUpDirection = getBodyUpDirection();
|
glm::vec3 bodyUpDirection = getBodyUpDirection();
|
||||||
DEBUG_VALUE("bodyUpDirection =", bodyUpDirection);
|
DEBUG_VALUE("bodyUpDirection =", bodyUpDirection);
|
||||||
|
|
||||||
if (getSkeletonModel()->getNeckPosition(namePosition)) {
|
if (_skeletonModel->getNeckPosition(namePosition)) {
|
||||||
float headHeight = getHeadHeight();
|
float headHeight = getHeadHeight();
|
||||||
DEBUG_VALUE("namePosition =", namePosition);
|
DEBUG_VALUE("namePosition =", namePosition);
|
||||||
DEBUG_VALUE("headHeight =", headHeight);
|
DEBUG_VALUE("headHeight =", headHeight);
|
||||||
|
@ -1244,8 +1246,8 @@ glm::vec3 Avatar::getUncachedLeftPalmPosition() const {
|
||||||
return leftPalmPosition;
|
return leftPalmPosition;
|
||||||
}
|
}
|
||||||
// avatar didn't have a LeftHandMiddle1 joint, fall back on this:
|
// avatar didn't have a LeftHandMiddle1 joint, fall back on this:
|
||||||
getSkeletonModel()->getJointRotationInWorldFrame(getSkeletonModel()->getLeftHandJointIndex(), leftPalmRotation);
|
_skeletonModel->getJointRotationInWorldFrame(_skeletonModel->getLeftHandJointIndex(), leftPalmRotation);
|
||||||
getSkeletonModel()->getLeftHandPosition(leftPalmPosition);
|
_skeletonModel->getLeftHandPosition(leftPalmPosition);
|
||||||
leftPalmPosition += HAND_TO_PALM_OFFSET * glm::inverse(leftPalmRotation);
|
leftPalmPosition += HAND_TO_PALM_OFFSET * glm::inverse(leftPalmRotation);
|
||||||
return leftPalmPosition;
|
return leftPalmPosition;
|
||||||
}
|
}
|
||||||
|
@ -1253,7 +1255,7 @@ glm::vec3 Avatar::getUncachedLeftPalmPosition() const {
|
||||||
glm::quat Avatar::getUncachedLeftPalmRotation() const {
|
glm::quat Avatar::getUncachedLeftPalmRotation() const {
|
||||||
assert(QThread::currentThread() == thread()); // main thread access only
|
assert(QThread::currentThread() == thread()); // main thread access only
|
||||||
glm::quat leftPalmRotation;
|
glm::quat leftPalmRotation;
|
||||||
getSkeletonModel()->getJointRotationInWorldFrame(getSkeletonModel()->getLeftHandJointIndex(), leftPalmRotation);
|
_skeletonModel->getJointRotationInWorldFrame(_skeletonModel->getLeftHandJointIndex(), leftPalmRotation);
|
||||||
return leftPalmRotation;
|
return leftPalmRotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1265,8 +1267,8 @@ glm::vec3 Avatar::getUncachedRightPalmPosition() const {
|
||||||
return rightPalmPosition;
|
return rightPalmPosition;
|
||||||
}
|
}
|
||||||
// avatar didn't have a RightHandMiddle1 joint, fall back on this:
|
// avatar didn't have a RightHandMiddle1 joint, fall back on this:
|
||||||
getSkeletonModel()->getJointRotationInWorldFrame(getSkeletonModel()->getRightHandJointIndex(), rightPalmRotation);
|
_skeletonModel->getJointRotationInWorldFrame(_skeletonModel->getRightHandJointIndex(), rightPalmRotation);
|
||||||
getSkeletonModel()->getRightHandPosition(rightPalmPosition);
|
_skeletonModel->getRightHandPosition(rightPalmPosition);
|
||||||
rightPalmPosition += HAND_TO_PALM_OFFSET * glm::inverse(rightPalmRotation);
|
rightPalmPosition += HAND_TO_PALM_OFFSET * glm::inverse(rightPalmRotation);
|
||||||
return rightPalmPosition;
|
return rightPalmPosition;
|
||||||
}
|
}
|
||||||
|
@ -1274,7 +1276,7 @@ glm::vec3 Avatar::getUncachedRightPalmPosition() const {
|
||||||
glm::quat Avatar::getUncachedRightPalmRotation() const {
|
glm::quat Avatar::getUncachedRightPalmRotation() const {
|
||||||
assert(QThread::currentThread() == thread()); // main thread access only
|
assert(QThread::currentThread() == thread()); // main thread access only
|
||||||
glm::quat rightPalmRotation;
|
glm::quat rightPalmRotation;
|
||||||
getSkeletonModel()->getJointRotationInWorldFrame(getSkeletonModel()->getRightHandJointIndex(), rightPalmRotation);
|
_skeletonModel->getJointRotationInWorldFrame(_skeletonModel->getRightHandJointIndex(), rightPalmRotation);
|
||||||
return rightPalmRotation;
|
return rightPalmRotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -161,6 +161,7 @@ void Rig::destroyAnimGraph() {
|
||||||
_internalPoseSet._absolutePoses.clear();
|
_internalPoseSet._absolutePoses.clear();
|
||||||
_internalPoseSet._overridePoses.clear();
|
_internalPoseSet._overridePoses.clear();
|
||||||
_internalPoseSet._overrideFlags.clear();
|
_internalPoseSet._overrideFlags.clear();
|
||||||
|
_numOverrides = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Rig::initJointStates(const FBXGeometry& geometry, const glm::mat4& modelOffset) {
|
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.clear();
|
||||||
_internalPoseSet._overrideFlags.resize(_animSkeleton->getNumJoints(), false);
|
_internalPoseSet._overrideFlags.resize(_animSkeleton->getNumJoints(), false);
|
||||||
|
_numOverrides = 0;
|
||||||
|
|
||||||
buildAbsoluteRigPoses(_animSkeleton->getRelativeDefaultPoses(), _absoluteDefaultPoses);
|
buildAbsoluteRigPoses(_animSkeleton->getRelativeDefaultPoses(), _absoluteDefaultPoses);
|
||||||
|
|
||||||
|
@ -207,6 +209,7 @@ void Rig::reset(const FBXGeometry& geometry) {
|
||||||
|
|
||||||
_internalPoseSet._overrideFlags.clear();
|
_internalPoseSet._overrideFlags.clear();
|
||||||
_internalPoseSet._overrideFlags.resize(_animSkeleton->getNumJoints(), false);
|
_internalPoseSet._overrideFlags.resize(_animSkeleton->getNumJoints(), false);
|
||||||
|
_numOverrides = 0;
|
||||||
|
|
||||||
buildAbsoluteRigPoses(_animSkeleton->getRelativeDefaultPoses(), _absoluteDefaultPoses);
|
buildAbsoluteRigPoses(_animSkeleton->getRelativeDefaultPoses(), _absoluteDefaultPoses);
|
||||||
|
|
||||||
|
@ -276,13 +279,17 @@ void Rig::setModelOffset(const glm::mat4& modelOffsetMat) {
|
||||||
|
|
||||||
void Rig::clearJointState(int index) {
|
void Rig::clearJointState(int index) {
|
||||||
if (isIndexValid(index)) {
|
if (isIndexValid(index)) {
|
||||||
_internalPoseSet._overrideFlags[index] = false;
|
if (_internalPoseSet._overrideFlags[index]) {
|
||||||
|
_internalPoseSet._overrideFlags[index] = false;
|
||||||
|
--_numOverrides;
|
||||||
|
}
|
||||||
_internalPoseSet._overridePoses[index] = _animSkeleton->getRelativeDefaultPose(index);
|
_internalPoseSet._overridePoses[index] = _animSkeleton->getRelativeDefaultPose(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Rig::clearJointStates() {
|
void Rig::clearJointStates() {
|
||||||
_internalPoseSet._overrideFlags.clear();
|
_internalPoseSet._overrideFlags.clear();
|
||||||
|
_numOverrides = 0;
|
||||||
if (_animSkeleton) {
|
if (_animSkeleton) {
|
||||||
_internalPoseSet._overrideFlags.resize(_animSkeleton->getNumJoints());
|
_internalPoseSet._overrideFlags.resize(_animSkeleton->getNumJoints());
|
||||||
_internalPoseSet._overridePoses = _animSkeleton->getRelativeDefaultPoses();
|
_internalPoseSet._overridePoses = _animSkeleton->getRelativeDefaultPoses();
|
||||||
|
@ -291,7 +298,10 @@ void Rig::clearJointStates() {
|
||||||
|
|
||||||
void Rig::clearJointAnimationPriority(int index) {
|
void Rig::clearJointAnimationPriority(int index) {
|
||||||
if (isIndexValid(index)) {
|
if (isIndexValid(index)) {
|
||||||
_internalPoseSet._overrideFlags[index] = false;
|
if (_internalPoseSet._overrideFlags[index]) {
|
||||||
|
_internalPoseSet._overrideFlags[index] = false;
|
||||||
|
--_numOverrides;
|
||||||
|
}
|
||||||
_internalPoseSet._overridePoses[index] = _animSkeleton->getRelativeDefaultPose(index);
|
_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 (isIndexValid(index)) {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
assert(_internalPoseSet._overrideFlags.size() == _internalPoseSet._overridePoses.size());
|
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;
|
_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) {
|
void Rig::setJointState(int index, bool valid, const glm::quat& rotation, const glm::vec3& translation, float priority) {
|
||||||
if (isIndexValid(index)) {
|
if (isIndexValid(index)) {
|
||||||
assert(_internalPoseSet._overrideFlags.size() == _internalPoseSet._overridePoses.size());
|
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].rot = rotation;
|
||||||
_internalPoseSet._overridePoses[index].trans = translation;
|
_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 (isIndexValid(index)) {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
ASSERT(_internalPoseSet._overrideFlags.size() == _internalPoseSet._overridePoses.size());
|
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].rot = rotation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -518,7 +537,7 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
|
||||||
|
|
||||||
// sine wave LFO var for testing.
|
// sine wave LFO var for testing.
|
||||||
static float t = 0.0f;
|
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 moveForwardAlpha = 0.0f;
|
||||||
float moveBackwardAlpha = 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) {
|
void Rig::updateAnimations(float deltaTime, glm::mat4 rootTransform) {
|
||||||
|
|
||||||
PROFILE_RANGE_EX(simulation_animation, __FUNCTION__, 0xffff00ff, 0);
|
PROFILE_RANGE_EX(simulation_animation, __FUNCTION__, 0xffff00ff, 0);
|
||||||
|
PerformanceTimer perfTimer("updateAnimations");
|
||||||
|
|
||||||
setModelOffset(rootTransform);
|
setModelOffset(rootTransform);
|
||||||
|
|
||||||
if (_animNode) {
|
if (_animNode) {
|
||||||
|
PerformanceTimer perfTimer("handleTriggers");
|
||||||
|
|
||||||
updateAnimationStateHandlers();
|
updateAnimationStateHandlers();
|
||||||
_animVars.setRigToGeometryTransform(_rigToGeometryTransform);
|
_animVars.setRigToGeometryTransform(_rigToGeometryTransform);
|
||||||
|
@ -903,9 +924,8 @@ void Rig::updateAnimations(float deltaTime, glm::mat4 rootTransform) {
|
||||||
for (auto& trigger : triggersOut) {
|
for (auto& trigger : triggersOut) {
|
||||||
_animVars.setTrigger(trigger);
|
_animVars.setTrigger(trigger);
|
||||||
}
|
}
|
||||||
|
applyOverridePoses();
|
||||||
}
|
}
|
||||||
|
|
||||||
applyOverridePoses();
|
|
||||||
buildAbsoluteRigPoses(_internalPoseSet._relativePoses, _internalPoseSet._absolutePoses);
|
buildAbsoluteRigPoses(_internalPoseSet._relativePoses, _internalPoseSet._absolutePoses);
|
||||||
|
|
||||||
// copy internal poses to external poses
|
// copy internal poses to external poses
|
||||||
|
@ -1176,7 +1196,8 @@ bool Rig::getModelRegistrationPoint(glm::vec3& modelRegistrationPointOut) const
|
||||||
}
|
}
|
||||||
|
|
||||||
void Rig::applyOverridePoses() {
|
void Rig::applyOverridePoses() {
|
||||||
if (!_animSkeleton) {
|
PerformanceTimer perfTimer("override");
|
||||||
|
if (_numOverrides == 0 || !_animSkeleton) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1192,28 +1213,24 @@ void Rig::applyOverridePoses() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Rig::buildAbsoluteRigPoses(const AnimPoseVec& relativePoses, AnimPoseVec& absolutePosesOut) {
|
void Rig::buildAbsoluteRigPoses(const AnimPoseVec& relativePoses, AnimPoseVec& absolutePosesOut) {
|
||||||
|
PerformanceTimer perfTimer("buildAbsolute");
|
||||||
if (!_animSkeleton) {
|
if (!_animSkeleton) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(_animSkeleton->getNumJoints() == (int)relativePoses.size());
|
ASSERT(_animSkeleton->getNumJoints() == (int)relativePoses.size());
|
||||||
|
|
||||||
// flatten all poses out so they are absolute not relative
|
|
||||||
absolutePosesOut.resize(relativePoses.size());
|
absolutePosesOut.resize(relativePoses.size());
|
||||||
|
AnimPose geometryToRigTransform(_geometryToRigTransform);
|
||||||
for (int i = 0; i < (int)relativePoses.size(); i++) {
|
for (int i = 0; i < (int)relativePoses.size(); i++) {
|
||||||
int parentIndex = _animSkeleton->getParentIndex(i);
|
int parentIndex = _animSkeleton->getParentIndex(i);
|
||||||
if (parentIndex == -1) {
|
if (parentIndex == -1) {
|
||||||
absolutePosesOut[i] = relativePoses[i];
|
// transform all root absolute poses into rig space
|
||||||
|
absolutePosesOut[i] = geometryToRigTransform * relativePoses[i];
|
||||||
} else {
|
} else {
|
||||||
absolutePosesOut[i] = absolutePosesOut[parentIndex] * relativePoses[i];
|
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 {
|
glm::mat4 Rig::getJointTransform(int jointIndex) const {
|
||||||
|
@ -1251,62 +1268,36 @@ void Rig::copyJointsIntoJointData(QVector<JointData>& jointDataVec) const {
|
||||||
|
|
||||||
void Rig::copyJointsFromJointData(const QVector<JointData>& jointDataVec) {
|
void Rig::copyJointsFromJointData(const QVector<JointData>& jointDataVec) {
|
||||||
PerformanceTimer perfTimer("copyJoints");
|
PerformanceTimer perfTimer("copyJoints");
|
||||||
if (_animSkeleton && jointDataVec.size() == (int)_internalPoseSet._overrideFlags.size()) {
|
if (_animSkeleton && jointDataVec.size() == (int)_internalPoseSet._relativePoses.size()) {
|
||||||
|
// make a vector of rotations in absolute-geometry-frame
|
||||||
// transform all the default poses into rig space.
|
const AnimPoseVec& absoluteDefaultPoses = _animSkeleton->getAbsoluteDefaultPoses();
|
||||||
const AnimPose geometryToRigPose(_geometryToRigTransform);
|
|
||||||
std::vector<bool> overrideFlags(_internalPoseSet._overridePoses.size(), false);
|
|
||||||
|
|
||||||
// start with the default rotations in absolute rig frame
|
|
||||||
std::vector<glm::quat> rotations;
|
std::vector<glm::quat> rotations;
|
||||||
rotations.reserve(_animSkeleton->getAbsoluteDefaultPoses().size());
|
rotations.reserve(_animSkeleton->getAbsoluteDefaultPoses().size());
|
||||||
for (auto& pose : _animSkeleton->getAbsoluteDefaultPoses()) {
|
const glm::quat rigToGeometryRot(glmExtractRotation(_rigToGeometryTransform));
|
||||||
rotations.push_back(geometryToRigPose.rot * pose.rot);
|
|
||||||
}
|
|
||||||
|
|
||||||
// start translations in relative frame but scaled to meters.
|
|
||||||
std::vector<glm::vec3> 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
|
|
||||||
for (int i = 0; i < jointDataVec.size(); i++) {
|
for (int i = 0; i < jointDataVec.size(); i++) {
|
||||||
if (isIndexValid(i)) {
|
const JointData& data = jointDataVec.at(i);
|
||||||
const JointData& data = jointDataVec.at(i);
|
if (data.rotationSet) {
|
||||||
if (data.rotationSet) {
|
// JointData rotations are in absolute rig-frame so we rotate them to absolute geometry-frame
|
||||||
overrideFlags[i] = true;
|
rotations.push_back(rigToGeometryRot * data.rotation);
|
||||||
rotations[i] = data.rotation;
|
} else {
|
||||||
}
|
rotations.push_back(absoluteDefaultPoses[i].rot);
|
||||||
if (data.translationSet) {
|
|
||||||
overrideFlags[i] = true;
|
|
||||||
translations[i] = data.translation;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(_internalPoseSet._overrideFlags.size() == _internalPoseSet._overridePoses.size());
|
// convert rotations from absolute to parent relative.
|
||||||
|
|
||||||
// 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);
|
_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++) {
|
for (int i = 0; i < jointDataVec.size(); i++) {
|
||||||
if (overrideFlags[i]) {
|
const JointData& data = jointDataVec.at(i);
|
||||||
_internalPoseSet._overrideFlags[i] = true;
|
_internalPoseSet._relativePoses[i].scale = Vectors::ONE;
|
||||||
_internalPoseSet._overridePoses[i].scale = Vectors::ONE;
|
_internalPoseSet._relativePoses[i].rot = rotations[i];
|
||||||
_internalPoseSet._overridePoses[i].rot = rotations[i];
|
if (data.translationSet) {
|
||||||
// scale translations from meters back into geometry units.
|
// JointData translations are in scaled relative-frame so we scale back to regular relative-frame
|
||||||
_internalPoseSet._overridePoses[i].trans = _invGeometryOffset.scale * translations[i];
|
_internalPoseSet._relativePoses[i].trans = _invGeometryOffset.scale * data.translation;
|
||||||
|
} else {
|
||||||
|
_internalPoseSet._relativePoses[i].trans = relativeDefaultPoses[i].trans;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -311,6 +311,7 @@ protected:
|
||||||
|
|
||||||
std::map<QString, AnimNode::Pointer> _origRoleAnimations;
|
std::map<QString, AnimNode::Pointer> _origRoleAnimations;
|
||||||
|
|
||||||
|
int32_t _numOverrides { 0 };
|
||||||
bool _lastEnableInverseKinematics { true };
|
bool _lastEnableInverseKinematics { true };
|
||||||
bool _enableInverseKinematics { true };
|
bool _enableInverseKinematics { true };
|
||||||
|
|
||||||
|
|
|
@ -234,17 +234,19 @@ void Model::updateRenderItems() {
|
||||||
render::PendingChanges pendingChanges;
|
render::PendingChanges pendingChanges;
|
||||||
foreach (auto itemID, self->_modelMeshRenderItems.keys()) {
|
foreach (auto itemID, self->_modelMeshRenderItems.keys()) {
|
||||||
pendingChanges.updateItem<ModelMeshPartPayload>(itemID, [modelTransform, modelMeshOffset, deleteGeometryCounter](ModelMeshPartPayload& data) {
|
pendingChanges.updateItem<ModelMeshPartPayload>(itemID, [modelTransform, modelMeshOffset, deleteGeometryCounter](ModelMeshPartPayload& data) {
|
||||||
if (!data.hasStartedFade() && data._model && data._model->isLoaded() && data._model->getGeometry()->areTexturesLoaded()) {
|
if (data._model && data._model->isLoaded()) {
|
||||||
data.startFade();
|
if (!data.hasStartedFade() && 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) {
|
// Ensure the model geometry was not reset between frames
|
||||||
// lazy update of cluster matrices used for rendering. We need to update them here, so we can correctly update the bounding box.
|
if (deleteGeometryCounter == data._model->_deleteGeometryCounter) {
|
||||||
data._model->updateClusterMatrices(modelTransform.getTranslation(), modelTransform.getRotation());
|
// 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.
|
// update the model transform and bounding box for this render item.
|
||||||
const Model::MeshState& state = data._model->_meshStates.at(data._meshIndex);
|
const Model::MeshState& state = data._model->_meshStates.at(data._meshIndex);
|
||||||
data.updateTransformForSkinnedMesh(modelTransform, modelMeshOffset, state.clusterMatrices);
|
data.updateTransformForSkinnedMesh(modelTransform, modelMeshOffset, state.clusterMatrices);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue