mirror of
https://github.com/overte-org/overte.git
synced 2025-04-22 19:13:38 +02:00
Transit animations won't play, they just get sent over the network
This commit is contained in:
parent
ad09007bd8
commit
7da5fa9ea7
5 changed files with 146 additions and 9 deletions
|
@ -151,22 +151,22 @@ void AvatarManager::handleTransitAnimations(AvatarTransit::Status status) {
|
|||
switch (status) {
|
||||
case AvatarTransit::Status::STARTED:
|
||||
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);
|
||||
break;
|
||||
case AvatarTransit::Status::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);
|
||||
break;
|
||||
case AvatarTransit::Status::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);
|
||||
break;
|
||||
case AvatarTransit::Status::ENDED:
|
||||
qDebug() << "END_FRAME";
|
||||
_myAvatar->restoreAnimation();
|
||||
_myAvatar->restoreNetworkAnimation();
|
||||
break;
|
||||
case AvatarTransit::Status::PRE_TRANSIT:
|
||||
break;
|
||||
|
|
|
@ -1124,6 +1124,15 @@ void MyAvatar::overrideAnimation(const QString& url, float fps, bool loop, float
|
|||
_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() {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "restoreAnimation");
|
||||
|
@ -1132,6 +1141,14 @@ void MyAvatar::restoreAnimation() {
|
|||
_skeletonModel->getRig().restoreAnimation();
|
||||
}
|
||||
|
||||
void MyAvatar::restoreNetworkAnimation() {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "restoreNetworkAnimation");
|
||||
return;
|
||||
}
|
||||
_skeletonModel->getRig().restoreNetworkAnimation();
|
||||
}
|
||||
|
||||
QStringList MyAvatar::getAnimationRoles() {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QStringList result;
|
||||
|
|
|
@ -376,6 +376,7 @@ public:
|
|||
* }, 3000);
|
||||
*/
|
||||
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
|
||||
* 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);
|
||||
*/
|
||||
Q_INVOKABLE void restoreAnimation();
|
||||
Q_INVOKABLE void restoreNetworkAnimation();
|
||||
|
||||
/**jsdoc
|
||||
* Each avatar has an avatar-animation.json file that defines which animations are used and how they are blended together with procedural data
|
||||
|
|
|
@ -133,6 +133,43 @@ void Rig::overrideAnimation(const QString& url, float fps, bool loop, float firs
|
|||
_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() {
|
||||
if (_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 {
|
||||
if (_animNode) {
|
||||
QStringList list;
|
||||
|
@ -208,11 +256,17 @@ void Rig::restoreRoleAnimation(const QString& role) {
|
|||
void Rig::destroyAnimGraph() {
|
||||
_animSkeleton.reset();
|
||||
_animLoader.reset();
|
||||
_networkLoader.reset();
|
||||
_animNode.reset();
|
||||
_internalPoseSet._relativePoses.clear();
|
||||
_internalPoseSet._absolutePoses.clear();
|
||||
_internalPoseSet._overridePoses.clear();
|
||||
_internalPoseSet._overrideFlags.clear();
|
||||
_networkNode.reset();
|
||||
_networkPoseSet._relativePoses.clear();
|
||||
_networkPoseSet._absolutePoses.clear();
|
||||
_networkPoseSet._overridePoses.clear();
|
||||
_networkPoseSet._overrideFlags.clear();
|
||||
_numOverrides = 0;
|
||||
_leftEyeJointChildren.clear();
|
||||
_rightEyeJointChildren.clear();
|
||||
|
@ -229,14 +283,24 @@ void Rig::initJointStates(const FBXGeometry& geometry, const glm::mat4& modelOff
|
|||
|
||||
_internalPoseSet._relativePoses.clear();
|
||||
_internalPoseSet._relativePoses = _animSkeleton->getRelativeDefaultPoses();
|
||||
_networkPoseSet._relativePoses.clear();
|
||||
_networkPoseSet._relativePoses = _animSkeleton->getRelativeDefaultPoses();
|
||||
|
||||
buildAbsoluteRigPoses(_internalPoseSet._relativePoses, _internalPoseSet._absolutePoses);
|
||||
buildAbsoluteRigPoses(_networkPoseSet._relativePoses, _networkPoseSet._absolutePoses);
|
||||
|
||||
_internalPoseSet._overridePoses.clear();
|
||||
_internalPoseSet._overridePoses = _animSkeleton->getRelativeDefaultPoses();
|
||||
|
||||
_internalPoseSet._overrideFlags.clear();
|
||||
_internalPoseSet._overrideFlags.resize(_animSkeleton->getNumJoints(), false);
|
||||
|
||||
_networkPoseSet._overridePoses.clear();
|
||||
_networkPoseSet._overridePoses = _animSkeleton->getRelativeDefaultPoses();
|
||||
|
||||
_networkPoseSet._overrideFlags.clear();
|
||||
_networkPoseSet._overrideFlags.resize(_animSkeleton->getNumJoints(), false);
|
||||
|
||||
_numOverrides = 0;
|
||||
|
||||
buildAbsoluteRigPoses(_animSkeleton->getRelativeDefaultPoses(), _absoluteDefaultPoses);
|
||||
|
@ -270,6 +334,18 @@ void Rig::reset(const FBXGeometry& geometry) {
|
|||
|
||||
_internalPoseSet._overrideFlags.clear();
|
||||
_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;
|
||||
|
||||
buildAbsoluteRigPoses(_animSkeleton->getRelativeDefaultPoses(), _absoluteDefaultPoses);
|
||||
|
@ -1049,26 +1125,37 @@ void Rig::updateAnimations(float deltaTime, const glm::mat4& rootTransform, cons
|
|||
|
||||
updateAnimationStateHandlers();
|
||||
_animVars.setRigToGeometryTransform(_rigToGeometryTransform);
|
||||
|
||||
if (_networkNode) {
|
||||
_networkVars.setRigToGeometryTransform(_rigToGeometryTransform);
|
||||
}
|
||||
AnimContext context(_enableDebugDrawIKTargets, _enableDebugDrawIKConstraints, _enableDebugDrawIKChains,
|
||||
getGeometryToRigTransform(), rigToWorldTransform);
|
||||
|
||||
// evaluate the animation
|
||||
AnimVariantMap triggersOut;
|
||||
|
||||
AnimVariantMap networkTriggersOut;
|
||||
_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()) {
|
||||
// animations haven't fully loaded yet.
|
||||
_internalPoseSet._relativePoses = _animSkeleton->getRelativeDefaultPoses();
|
||||
}
|
||||
if ((int)_networkPoseSet._relativePoses.size() != _animSkeleton->getNumJoints()) {
|
||||
// animations haven't fully loaded yet.
|
||||
_networkPoseSet._relativePoses = _animSkeleton->getRelativeDefaultPoses();
|
||||
}
|
||||
_lastAnimVars = _animVars;
|
||||
_animVars.clearTriggers();
|
||||
_animVars = triggersOut;
|
||||
_networkVars.clearTriggers();
|
||||
_networkVars = networkTriggersOut;
|
||||
_lastContext = context;
|
||||
}
|
||||
applyOverridePoses();
|
||||
buildAbsoluteRigPoses(_internalPoseSet._relativePoses, _internalPoseSet._absolutePoses);
|
||||
|
||||
buildAbsoluteRigPoses(_networkPoseSet._relativePoses, _networkPoseSet._absolutePoses);
|
||||
// copy internal poses to external poses
|
||||
{
|
||||
QWriteLocker writeLock(&_externalPoseSetLock);
|
||||
|
@ -1707,9 +1794,12 @@ void Rig::initAnimGraph(const QUrl& url) {
|
|||
_animGraphURL = url;
|
||||
|
||||
_animNode.reset();
|
||||
_networkNode.reset();
|
||||
|
||||
// load the anim graph
|
||||
_animLoader.reset(new AnimNodeLoader(url));
|
||||
_networkLoader.reset(new AnimNodeLoader(url));
|
||||
|
||||
std::weak_ptr<AnimSkeleton> weakSkeletonPtr = _animSkeleton;
|
||||
connect(_animLoader.get(), &AnimNodeLoader::success, [this, weakSkeletonPtr](AnimNode::Pointer nodeIn) {
|
||||
_animNode = nodeIn;
|
||||
|
@ -1740,6 +1830,26 @@ void Rig::initAnimGraph(const QUrl& url) {
|
|||
connect(_animLoader.get(), &AnimNodeLoader::error, [url](int error, QString 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)) {
|
||||
// rotations are in absolute rig frame.
|
||||
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);
|
||||
|
||||
// translations are in relative frame but scaled so that they are in meters,
|
||||
// instead of geometry units.
|
||||
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);
|
||||
} else {
|
||||
data.translationIsDefaultPose = true;
|
||||
|
|
|
@ -113,7 +113,9 @@ public:
|
|||
void destroyAnimGraph();
|
||||
|
||||
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 restoreNetworkAnimation();
|
||||
QStringList getAnimationRoles() const;
|
||||
void overrideRoleAnimation(const QString& role, const QString& url, float fps, bool loop, float firstFrame, float lastFrame);
|
||||
void restoreRoleAnimation(const QString& role);
|
||||
|
@ -270,6 +272,7 @@ protected:
|
|||
|
||||
// Only accessed by the main thread
|
||||
PoseSet _internalPoseSet;
|
||||
PoseSet _networkPoseSet;
|
||||
|
||||
// Copy of the _poseSet for external threads.
|
||||
PoseSet _externalPoseSet;
|
||||
|
@ -301,9 +304,12 @@ protected:
|
|||
|
||||
QUrl _animGraphURL;
|
||||
std::shared_ptr<AnimNode> _animNode;
|
||||
std::shared_ptr<AnimNode> _networkNode;
|
||||
std::shared_ptr<AnimSkeleton> _animSkeleton;
|
||||
std::unique_ptr<AnimNodeLoader> _animLoader;
|
||||
std::unique_ptr<AnimNodeLoader> _networkLoader;
|
||||
AnimVariantMap _animVars;
|
||||
AnimVariantMap _networkVars;
|
||||
|
||||
enum class RigRole {
|
||||
Idle = 0,
|
||||
|
@ -350,6 +356,7 @@ protected:
|
|||
};
|
||||
|
||||
UserAnimState _userAnimState;
|
||||
UserAnimState _networkAnimState;
|
||||
std::map<QString, RoleAnimState> _roleAnimStates;
|
||||
|
||||
float _leftHandOverlayAlpha { 0.0f };
|
||||
|
@ -391,6 +398,7 @@ protected:
|
|||
|
||||
int _rigId;
|
||||
bool _headEnabled { false };
|
||||
bool _sendNetworkNode { false };
|
||||
|
||||
AnimContext _lastContext;
|
||||
AnimVariantMap _lastAnimVars;
|
||||
|
|
Loading…
Reference in a new issue