Transit animations won't play, they just get sent over the network

This commit is contained in:
luiscuenca 2018-10-16 11:33:58 -07:00
parent ad09007bd8
commit 7da5fa9ea7
5 changed files with 146 additions and 9 deletions

View file

@ -151,22 +151,22 @@ void AvatarManager::handleTransitAnimations(AvatarTransit::Status status) {
switch (status) { switch (status) {
case AvatarTransit::Status::STARTED: case AvatarTransit::Status::STARTED:
qDebug() << "START_FRAME"; qDebug() << "START_FRAME";
_myAvatar->overrideAnimation(startAnimation._animationUrl, REFERENCE_FPS, false, startAnimation._firstFrame, _myAvatar->overrideNetworkAnimation(startAnimation._animationUrl, REFERENCE_FPS, false, startAnimation._firstFrame,
startAnimation._firstFrame + startAnimation._frameCount); startAnimation._firstFrame + startAnimation._frameCount);
break; break;
case AvatarTransit::Status::START_TRANSIT: case AvatarTransit::Status::START_TRANSIT:
qDebug() << "START_TRANSIT"; qDebug() << "START_TRANSIT";
_myAvatar->overrideAnimation(middleAnimation._animationUrl, REFERENCE_FPS, false, middleAnimation._firstFrame, _myAvatar->overrideNetworkAnimation(middleAnimation._animationUrl, REFERENCE_FPS, false, middleAnimation._firstFrame,
middleAnimation._firstFrame + middleAnimation._frameCount); middleAnimation._firstFrame + middleAnimation._frameCount);
break; break;
case AvatarTransit::Status::END_TRANSIT: case AvatarTransit::Status::END_TRANSIT:
qDebug() << "END_TRANSIT"; qDebug() << "END_TRANSIT";
_myAvatar->overrideAnimation(endAnimation._animationUrl, REFERENCE_FPS, false, endAnimation._firstFrame, _myAvatar->overrideNetworkAnimation(endAnimation._animationUrl, REFERENCE_FPS, false, endAnimation._firstFrame,
endAnimation._firstFrame + endAnimation._frameCount); endAnimation._firstFrame + endAnimation._frameCount);
break; break;
case AvatarTransit::Status::ENDED: case AvatarTransit::Status::ENDED:
qDebug() << "END_FRAME"; qDebug() << "END_FRAME";
_myAvatar->restoreAnimation(); _myAvatar->restoreNetworkAnimation();
break; break;
case AvatarTransit::Status::PRE_TRANSIT: case AvatarTransit::Status::PRE_TRANSIT:
break; break;

View file

@ -1124,6 +1124,15 @@ void MyAvatar::overrideAnimation(const QString& url, float fps, bool loop, float
_skeletonModel->getRig().overrideAnimation(url, fps, loop, firstFrame, lastFrame); _skeletonModel->getRig().overrideAnimation(url, fps, loop, firstFrame, lastFrame);
} }
void MyAvatar::overrideNetworkAnimation(const QString& url, float fps, bool loop, float firstFrame, float lastFrame) {
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "overrideNetworkAnimation", Q_ARG(const QString&, url), Q_ARG(float, fps),
Q_ARG(bool, loop), Q_ARG(float, firstFrame), Q_ARG(float, lastFrame));
return;
}
_skeletonModel->getRig().overrideNetworkAnimation(url, fps, loop, firstFrame, lastFrame);
}
void MyAvatar::restoreAnimation() { void MyAvatar::restoreAnimation() {
if (QThread::currentThread() != thread()) { if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "restoreAnimation"); QMetaObject::invokeMethod(this, "restoreAnimation");
@ -1132,6 +1141,14 @@ void MyAvatar::restoreAnimation() {
_skeletonModel->getRig().restoreAnimation(); _skeletonModel->getRig().restoreAnimation();
} }
void MyAvatar::restoreNetworkAnimation() {
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "restoreNetworkAnimation");
return;
}
_skeletonModel->getRig().restoreNetworkAnimation();
}
QStringList MyAvatar::getAnimationRoles() { QStringList MyAvatar::getAnimationRoles() {
if (QThread::currentThread() != thread()) { if (QThread::currentThread() != thread()) {
QStringList result; QStringList result;

View file

@ -376,6 +376,7 @@ public:
* }, 3000); * }, 3000);
*/ */
Q_INVOKABLE void overrideAnimation(const QString& url, float fps, bool loop, float firstFrame, float lastFrame); Q_INVOKABLE void overrideAnimation(const QString& url, float fps, bool loop, float firstFrame, float lastFrame);
Q_INVOKABLE void overrideNetworkAnimation(const QString& url, float fps, bool loop, float firstFrame, float lastFrame);
/**jsdoc /**jsdoc
* The avatar animation system includes a set of default animations along with rules for how those animations are blended together with * The avatar animation system includes a set of default animations along with rules for how those animations are blended together with
@ -392,6 +393,7 @@ public:
* }, 3000); * }, 3000);
*/ */
Q_INVOKABLE void restoreAnimation(); Q_INVOKABLE void restoreAnimation();
Q_INVOKABLE void restoreNetworkAnimation();
/**jsdoc /**jsdoc
* Each avatar has an avatar-animation.json file that defines which animations are used and how they are blended together with procedural data * Each avatar has an avatar-animation.json file that defines which animations are used and how they are blended together with procedural data

View file

@ -133,6 +133,43 @@ void Rig::overrideAnimation(const QString& url, float fps, bool loop, float firs
_animVars.set("userAnimB", clipNodeEnum == UserAnimState::B); _animVars.set("userAnimB", clipNodeEnum == UserAnimState::B);
} }
void Rig::overrideNetworkAnimation(const QString& url, float fps, bool loop, float firstFrame, float lastFrame) {
UserAnimState::ClipNodeEnum clipNodeEnum;
if (_networkAnimState.clipNodeEnum == UserAnimState::None || _networkAnimState.clipNodeEnum == UserAnimState::B) {
clipNodeEnum = UserAnimState::A;
}
else {
clipNodeEnum = UserAnimState::B;
}
if (_networkNode) {
// find an unused AnimClip clipNode
_sendNetworkNode = true;
std::shared_ptr<AnimClip> clip;
if (clipNodeEnum == UserAnimState::A) {
clip = std::dynamic_pointer_cast<AnimClip>(_networkNode->findByName("userAnimA"));
}
else {
clip = std::dynamic_pointer_cast<AnimClip>(_networkNode->findByName("userAnimB"));
}
if (clip) {
// set parameters
clip->setLoopFlag(loop);
clip->setStartFrame(firstFrame);
clip->setEndFrame(lastFrame);
const float REFERENCE_FRAMES_PER_SECOND = 30.0f;
float timeScale = fps / REFERENCE_FRAMES_PER_SECOND;
clip->setTimeScale(timeScale);
clip->loadURL(url);
}
}
// store current user anim state.
_networkAnimState = { clipNodeEnum, url, fps, loop, firstFrame, lastFrame };
// notify the userAnimStateMachine the desired state.
_networkVars.set("userAnimNone", false);
_networkVars.set("userAnimA", clipNodeEnum == UserAnimState::A);
_networkVars.set("userAnimB", clipNodeEnum == UserAnimState::B);
}
void Rig::restoreAnimation() { void Rig::restoreAnimation() {
if (_userAnimState.clipNodeEnum != UserAnimState::None) { if (_userAnimState.clipNodeEnum != UserAnimState::None) {
_userAnimState.clipNodeEnum = UserAnimState::None; _userAnimState.clipNodeEnum = UserAnimState::None;
@ -144,6 +181,17 @@ void Rig::restoreAnimation() {
} }
} }
void Rig::restoreNetworkAnimation() {
_sendNetworkNode = false;
if (_networkAnimState.clipNodeEnum != UserAnimState::None) {
_networkAnimState.clipNodeEnum = UserAnimState::None;
// notify the userAnimStateMachine the desired state.
_networkVars.set("userAnimNone", true);
_networkVars.set("userAnimA", false);
_networkVars.set("userAnimB", false);
}
}
QStringList Rig::getAnimationRoles() const { QStringList Rig::getAnimationRoles() const {
if (_animNode) { if (_animNode) {
QStringList list; QStringList list;
@ -208,11 +256,17 @@ void Rig::restoreRoleAnimation(const QString& role) {
void Rig::destroyAnimGraph() { void Rig::destroyAnimGraph() {
_animSkeleton.reset(); _animSkeleton.reset();
_animLoader.reset(); _animLoader.reset();
_networkLoader.reset();
_animNode.reset(); _animNode.reset();
_internalPoseSet._relativePoses.clear(); _internalPoseSet._relativePoses.clear();
_internalPoseSet._absolutePoses.clear(); _internalPoseSet._absolutePoses.clear();
_internalPoseSet._overridePoses.clear(); _internalPoseSet._overridePoses.clear();
_internalPoseSet._overrideFlags.clear(); _internalPoseSet._overrideFlags.clear();
_networkNode.reset();
_networkPoseSet._relativePoses.clear();
_networkPoseSet._absolutePoses.clear();
_networkPoseSet._overridePoses.clear();
_networkPoseSet._overrideFlags.clear();
_numOverrides = 0; _numOverrides = 0;
_leftEyeJointChildren.clear(); _leftEyeJointChildren.clear();
_rightEyeJointChildren.clear(); _rightEyeJointChildren.clear();
@ -229,14 +283,24 @@ void Rig::initJointStates(const FBXGeometry& geometry, const glm::mat4& modelOff
_internalPoseSet._relativePoses.clear(); _internalPoseSet._relativePoses.clear();
_internalPoseSet._relativePoses = _animSkeleton->getRelativeDefaultPoses(); _internalPoseSet._relativePoses = _animSkeleton->getRelativeDefaultPoses();
_networkPoseSet._relativePoses.clear();
_networkPoseSet._relativePoses = _animSkeleton->getRelativeDefaultPoses();
buildAbsoluteRigPoses(_internalPoseSet._relativePoses, _internalPoseSet._absolutePoses); buildAbsoluteRigPoses(_internalPoseSet._relativePoses, _internalPoseSet._absolutePoses);
buildAbsoluteRigPoses(_networkPoseSet._relativePoses, _networkPoseSet._absolutePoses);
_internalPoseSet._overridePoses.clear(); _internalPoseSet._overridePoses.clear();
_internalPoseSet._overridePoses = _animSkeleton->getRelativeDefaultPoses(); _internalPoseSet._overridePoses = _animSkeleton->getRelativeDefaultPoses();
_internalPoseSet._overrideFlags.clear(); _internalPoseSet._overrideFlags.clear();
_internalPoseSet._overrideFlags.resize(_animSkeleton->getNumJoints(), false); _internalPoseSet._overrideFlags.resize(_animSkeleton->getNumJoints(), false);
_networkPoseSet._overridePoses.clear();
_networkPoseSet._overridePoses = _animSkeleton->getRelativeDefaultPoses();
_networkPoseSet._overrideFlags.clear();
_networkPoseSet._overrideFlags.resize(_animSkeleton->getNumJoints(), false);
_numOverrides = 0; _numOverrides = 0;
buildAbsoluteRigPoses(_animSkeleton->getRelativeDefaultPoses(), _absoluteDefaultPoses); buildAbsoluteRigPoses(_animSkeleton->getRelativeDefaultPoses(), _absoluteDefaultPoses);
@ -270,6 +334,18 @@ void Rig::reset(const FBXGeometry& geometry) {
_internalPoseSet._overrideFlags.clear(); _internalPoseSet._overrideFlags.clear();
_internalPoseSet._overrideFlags.resize(_animSkeleton->getNumJoints(), false); _internalPoseSet._overrideFlags.resize(_animSkeleton->getNumJoints(), false);
_networkPoseSet._relativePoses.clear();
_networkPoseSet._relativePoses = _animSkeleton->getRelativeDefaultPoses();
buildAbsoluteRigPoses(_networkPoseSet._relativePoses, _networkPoseSet._absolutePoses);
_networkPoseSet._overridePoses.clear();
_networkPoseSet._overridePoses = _animSkeleton->getRelativeDefaultPoses();
_networkPoseSet._overrideFlags.clear();
_networkPoseSet._overrideFlags.resize(_animSkeleton->getNumJoints(), false);
_numOverrides = 0; _numOverrides = 0;
buildAbsoluteRigPoses(_animSkeleton->getRelativeDefaultPoses(), _absoluteDefaultPoses); buildAbsoluteRigPoses(_animSkeleton->getRelativeDefaultPoses(), _absoluteDefaultPoses);
@ -1049,26 +1125,37 @@ void Rig::updateAnimations(float deltaTime, const glm::mat4& rootTransform, cons
updateAnimationStateHandlers(); updateAnimationStateHandlers();
_animVars.setRigToGeometryTransform(_rigToGeometryTransform); _animVars.setRigToGeometryTransform(_rigToGeometryTransform);
if (_networkNode) {
_networkVars.setRigToGeometryTransform(_rigToGeometryTransform);
}
AnimContext context(_enableDebugDrawIKTargets, _enableDebugDrawIKConstraints, _enableDebugDrawIKChains, AnimContext context(_enableDebugDrawIKTargets, _enableDebugDrawIKConstraints, _enableDebugDrawIKChains,
getGeometryToRigTransform(), rigToWorldTransform); getGeometryToRigTransform(), rigToWorldTransform);
// evaluate the animation // evaluate the animation
AnimVariantMap triggersOut; AnimVariantMap triggersOut;
AnimVariantMap networkTriggersOut;
_internalPoseSet._relativePoses = _animNode->evaluate(_animVars, context, deltaTime, triggersOut); _internalPoseSet._relativePoses = _animNode->evaluate(_animVars, context, deltaTime, triggersOut);
if (_networkNode) {
_networkPoseSet._relativePoses = _networkNode->evaluate(_networkVars, context, deltaTime, networkTriggersOut);
}
if ((int)_internalPoseSet._relativePoses.size() != _animSkeleton->getNumJoints()) { if ((int)_internalPoseSet._relativePoses.size() != _animSkeleton->getNumJoints()) {
// animations haven't fully loaded yet. // animations haven't fully loaded yet.
_internalPoseSet._relativePoses = _animSkeleton->getRelativeDefaultPoses(); _internalPoseSet._relativePoses = _animSkeleton->getRelativeDefaultPoses();
} }
if ((int)_networkPoseSet._relativePoses.size() != _animSkeleton->getNumJoints()) {
// animations haven't fully loaded yet.
_networkPoseSet._relativePoses = _animSkeleton->getRelativeDefaultPoses();
}
_lastAnimVars = _animVars; _lastAnimVars = _animVars;
_animVars.clearTriggers(); _animVars.clearTriggers();
_animVars = triggersOut; _animVars = triggersOut;
_networkVars.clearTriggers();
_networkVars = networkTriggersOut;
_lastContext = context; _lastContext = context;
} }
applyOverridePoses(); applyOverridePoses();
buildAbsoluteRigPoses(_internalPoseSet._relativePoses, _internalPoseSet._absolutePoses); buildAbsoluteRigPoses(_internalPoseSet._relativePoses, _internalPoseSet._absolutePoses);
buildAbsoluteRigPoses(_networkPoseSet._relativePoses, _networkPoseSet._absolutePoses);
// copy internal poses to external poses // copy internal poses to external poses
{ {
QWriteLocker writeLock(&_externalPoseSetLock); QWriteLocker writeLock(&_externalPoseSetLock);
@ -1707,9 +1794,12 @@ void Rig::initAnimGraph(const QUrl& url) {
_animGraphURL = url; _animGraphURL = url;
_animNode.reset(); _animNode.reset();
_networkNode.reset();
// load the anim graph // load the anim graph
_animLoader.reset(new AnimNodeLoader(url)); _animLoader.reset(new AnimNodeLoader(url));
_networkLoader.reset(new AnimNodeLoader(url));
std::weak_ptr<AnimSkeleton> weakSkeletonPtr = _animSkeleton; std::weak_ptr<AnimSkeleton> weakSkeletonPtr = _animSkeleton;
connect(_animLoader.get(), &AnimNodeLoader::success, [this, weakSkeletonPtr](AnimNode::Pointer nodeIn) { connect(_animLoader.get(), &AnimNodeLoader::success, [this, weakSkeletonPtr](AnimNode::Pointer nodeIn) {
_animNode = nodeIn; _animNode = nodeIn;
@ -1740,6 +1830,26 @@ void Rig::initAnimGraph(const QUrl& url) {
connect(_animLoader.get(), &AnimNodeLoader::error, [url](int error, QString str) { connect(_animLoader.get(), &AnimNodeLoader::error, [url](int error, QString str) {
qCCritical(animation) << "Error loading" << url.toDisplayString() << "code = " << error << "str =" << str; qCCritical(animation) << "Error loading" << url.toDisplayString() << "code = " << error << "str =" << str;
}); });
connect(_networkLoader.get(), &AnimNodeLoader::success, [this, weakSkeletonPtr](AnimNode::Pointer nodeIn) {
_networkNode = nodeIn;
// abort load if the previous skeleton was deleted.
auto sharedSkeletonPtr = weakSkeletonPtr.lock();
if (!sharedSkeletonPtr) {
return;
}
_networkNode->setSkeleton(sharedSkeletonPtr);
if (_networkAnimState.clipNodeEnum != UserAnimState::None) {
// restore the user animation we had before reset.
UserAnimState origState = _networkAnimState;
_networkAnimState = { UserAnimState::None, "", 30.0f, false, 0.0f, 0.0f };
overrideNetworkAnimation(origState.url, origState.fps, origState.loop, origState.firstFrame, origState.lastFrame);
}
// emit onLoadComplete();
});
connect(_networkLoader.get(), &AnimNodeLoader::error, [url](int error, QString str) {
qCCritical(animation) << "Error loading" << url.toDisplayString() << "code = " << error << "str =" << str;
});
} }
} }
@ -1817,13 +1927,13 @@ void Rig::copyJointsIntoJointData(QVector<JointData>& jointDataVec) const {
if (isIndexValid(i)) { if (isIndexValid(i)) {
// rotations are in absolute rig frame. // rotations are in absolute rig frame.
glm::quat defaultAbsRot = geometryToRigPose.rot() * _animSkeleton->getAbsoluteDefaultPose(i).rot(); glm::quat defaultAbsRot = geometryToRigPose.rot() * _animSkeleton->getAbsoluteDefaultPose(i).rot();
data.rotation = _internalPoseSet._absolutePoses[i].rot(); data.rotation = !_sendNetworkNode ? _internalPoseSet._absolutePoses[i].rot() : _networkPoseSet._absolutePoses[i].rot();
data.rotationIsDefaultPose = isEqual(data.rotation, defaultAbsRot); data.rotationIsDefaultPose = isEqual(data.rotation, defaultAbsRot);
// translations are in relative frame but scaled so that they are in meters, // translations are in relative frame but scaled so that they are in meters,
// instead of geometry units. // instead of geometry units.
glm::vec3 defaultRelTrans = _geometryOffset.scale() * _animSkeleton->getRelativeDefaultPose(i).trans(); glm::vec3 defaultRelTrans = _geometryOffset.scale() * _animSkeleton->getRelativeDefaultPose(i).trans();
data.translation = _geometryOffset.scale() * _internalPoseSet._relativePoses[i].trans(); data.translation = _geometryOffset.scale() * (!_sendNetworkNode ? _internalPoseSet._relativePoses[i].trans() : _networkPoseSet._relativePoses[i].trans());
data.translationIsDefaultPose = isEqual(data.translation, defaultRelTrans); data.translationIsDefaultPose = isEqual(data.translation, defaultRelTrans);
} else { } else {
data.translationIsDefaultPose = true; data.translationIsDefaultPose = true;

View file

@ -113,7 +113,9 @@ public:
void destroyAnimGraph(); void destroyAnimGraph();
void overrideAnimation(const QString& url, float fps, bool loop, float firstFrame, float lastFrame); void overrideAnimation(const QString& url, float fps, bool loop, float firstFrame, float lastFrame);
void overrideNetworkAnimation(const QString& url, float fps, bool loop, float firstFrame, float lastFrame);
void restoreAnimation(); void restoreAnimation();
void restoreNetworkAnimation();
QStringList getAnimationRoles() const; QStringList getAnimationRoles() const;
void overrideRoleAnimation(const QString& role, const QString& url, float fps, bool loop, float firstFrame, float lastFrame); void overrideRoleAnimation(const QString& role, const QString& url, float fps, bool loop, float firstFrame, float lastFrame);
void restoreRoleAnimation(const QString& role); void restoreRoleAnimation(const QString& role);
@ -270,6 +272,7 @@ protected:
// Only accessed by the main thread // Only accessed by the main thread
PoseSet _internalPoseSet; PoseSet _internalPoseSet;
PoseSet _networkPoseSet;
// Copy of the _poseSet for external threads. // Copy of the _poseSet for external threads.
PoseSet _externalPoseSet; PoseSet _externalPoseSet;
@ -301,9 +304,12 @@ protected:
QUrl _animGraphURL; QUrl _animGraphURL;
std::shared_ptr<AnimNode> _animNode; std::shared_ptr<AnimNode> _animNode;
std::shared_ptr<AnimNode> _networkNode;
std::shared_ptr<AnimSkeleton> _animSkeleton; std::shared_ptr<AnimSkeleton> _animSkeleton;
std::unique_ptr<AnimNodeLoader> _animLoader; std::unique_ptr<AnimNodeLoader> _animLoader;
std::unique_ptr<AnimNodeLoader> _networkLoader;
AnimVariantMap _animVars; AnimVariantMap _animVars;
AnimVariantMap _networkVars;
enum class RigRole { enum class RigRole {
Idle = 0, Idle = 0,
@ -350,6 +356,7 @@ protected:
}; };
UserAnimState _userAnimState; UserAnimState _userAnimState;
UserAnimState _networkAnimState;
std::map<QString, RoleAnimState> _roleAnimStates; std::map<QString, RoleAnimState> _roleAnimStates;
float _leftHandOverlayAlpha { 0.0f }; float _leftHandOverlayAlpha { 0.0f };
@ -391,6 +398,7 @@ protected:
int _rigId; int _rigId;
bool _headEnabled { false }; bool _headEnabled { false };
bool _sendNetworkNode { false };
AnimContext _lastContext; AnimContext _lastContext;
AnimVariantMap _lastAnimVars; AnimVariantMap _lastAnimVars;