mirror of
https://github.com/overte-org/overte.git
synced 2025-08-04 23:29:39 +02:00
Merge pull request #15783 from hyperlogic/feature/anim-debug-draw-improvement
Improvement to Developer > Avatar > Draw Animation
This commit is contained in:
commit
10dae7e4d9
6 changed files with 72 additions and 10 deletions
|
@ -1416,6 +1416,10 @@ void MyAvatar::setEnableDebugDrawAnimPose(bool isEnabled) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MyAvatar::setDebugDrawAnimPoseName(QString poseName) {
|
||||||
|
_debugDrawAnimPoseName.set(poseName);
|
||||||
|
}
|
||||||
|
|
||||||
void MyAvatar::setEnableDebugDrawPosition(bool isEnabled) {
|
void MyAvatar::setEnableDebugDrawPosition(bool isEnabled) {
|
||||||
if (isEnabled) {
|
if (isEnabled) {
|
||||||
const glm::vec4 red(1.0f, 0.0f, 0.0f, 1.0f);
|
const glm::vec4 red(1.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
@ -3086,15 +3090,26 @@ void MyAvatar::postUpdate(float deltaTime, const render::ScenePointer& scene) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_enableDebugDrawAnimPose && animSkeleton) {
|
if (_enableDebugDrawAnimPose && animSkeleton) {
|
||||||
// build absolute AnimPoseVec from rig
|
|
||||||
AnimPoseVec absPoses;
|
AnimPoseVec absPoses;
|
||||||
const Rig& rig = _skeletonModel->getRig();
|
const Rig& rig = _skeletonModel->getRig();
|
||||||
absPoses.reserve(rig.getJointStateCount());
|
const glm::vec4 CYAN(0.1f, 0.6f, 0.6f, 1.0f);
|
||||||
for (int i = 0; i < rig.getJointStateCount(); i++) {
|
|
||||||
absPoses.push_back(AnimPose(rig.getJointTransform(i)));
|
QString name = _debugDrawAnimPoseName.get();
|
||||||
|
if (name.isEmpty()) {
|
||||||
|
// build absolute AnimPoseVec from rig transforms. i.e. the same that are used for rendering.
|
||||||
|
absPoses.reserve(rig.getJointStateCount());
|
||||||
|
for (int i = 0; i < rig.getJointStateCount(); i++) {
|
||||||
|
absPoses.push_back(AnimPose(rig.getJointTransform(i)));
|
||||||
|
}
|
||||||
|
AnimDebugDraw::getInstance().addAbsolutePoses("myAvatarAnimPoses", animSkeleton, absPoses, xform, CYAN);
|
||||||
|
} else {
|
||||||
|
AnimNode::ConstPointer node = rig.findAnimNodeByName(name);
|
||||||
|
if (node) {
|
||||||
|
rig.buildAbsoluteRigPoses(node->getPoses(), absPoses);
|
||||||
|
AnimDebugDraw::getInstance().addAbsolutePoses("myAvatarAnimPoses", animSkeleton, absPoses, xform, CYAN);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
glm::vec4 cyan(0.1f, 0.6f, 0.6f, 1.0f);
|
|
||||||
AnimDebugDraw::getInstance().addAbsolutePoses("myAvatarAnimPoses", animSkeleton, absPoses, xform, cyan);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2018,12 +2018,20 @@ public slots:
|
||||||
void setEnableDebugDrawDefaultPose(bool isEnabled);
|
void setEnableDebugDrawDefaultPose(bool isEnabled);
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Displays animation debug graphics.
|
* Displays animation debug graphics. By default it shows the animation poses used for rendering.
|
||||||
|
* However, the property MyAvatar.setDebugDrawAnimPoseName can be used to draw a specific animation node.
|
||||||
* @function MyAvatar.setEnableDebugDrawAnimPose
|
* @function MyAvatar.setEnableDebugDrawAnimPose
|
||||||
* @param {boolean} enabled - <code>true</code> to show the debug graphics, <code>false</code> to hide.
|
* @param {boolean} enabled - <code>true</code> to show the debug graphics, <code>false</code> to hide.
|
||||||
*/
|
*/
|
||||||
void setEnableDebugDrawAnimPose(bool isEnabled);
|
void setEnableDebugDrawAnimPose(bool isEnabled);
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* If set it determines which animation debug graphics to draw, when MyAvatar.setEnableDebugDrawAnimPose is set to true.
|
||||||
|
* @function MyAvatar.setDebugDrawAnimPoseName
|
||||||
|
* @param {boolean} enabled - <code>true</code> to show the debug graphics, <code>false</code> to hide.
|
||||||
|
*/
|
||||||
|
void setDebugDrawAnimPoseName(QString poseName);
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Displays position debug graphics.
|
* Displays position debug graphics.
|
||||||
* @function MyAvatar.setEnableDebugDrawPosition
|
* @function MyAvatar.setEnableDebugDrawPosition
|
||||||
|
@ -2666,6 +2674,8 @@ private:
|
||||||
bool _enableDebugDrawIKChains { false };
|
bool _enableDebugDrawIKChains { false };
|
||||||
bool _enableDebugDrawDetailedCollision { false };
|
bool _enableDebugDrawDetailedCollision { false };
|
||||||
|
|
||||||
|
ThreadSafeValueCache<QString> _debugDrawAnimPoseName;
|
||||||
|
|
||||||
mutable bool _cauterizationNeedsUpdate { false }; // do we need to scan children and update their "cauterized" state?
|
mutable bool _cauterizationNeedsUpdate { false }; // do we need to scan children and update their "cauterized" state?
|
||||||
|
|
||||||
AudioListenerMode _audioListenerMode;
|
AudioListenerMode _audioListenerMode;
|
||||||
|
|
|
@ -10,10 +10,13 @@
|
||||||
|
|
||||||
#include "AnimClip.h"
|
#include "AnimClip.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include "GLMHelpers.h"
|
#include "GLMHelpers.h"
|
||||||
#include "AnimationLogging.h"
|
#include "AnimationLogging.h"
|
||||||
#include "AnimUtil.h"
|
#include "AnimUtil.h"
|
||||||
|
|
||||||
|
|
||||||
AnimClip::AnimClip(const QString& id, const QString& url, float startFrame, float endFrame, float timeScale, bool loopFlag, bool mirrorFlag) :
|
AnimClip::AnimClip(const QString& id, const QString& url, float startFrame, float endFrame, float timeScale, bool loopFlag, bool mirrorFlag) :
|
||||||
AnimNode(AnimNode::Type::Clip, id),
|
AnimNode(AnimNode::Type::Clip, id),
|
||||||
_startFrame(startFrame),
|
_startFrame(startFrame),
|
||||||
|
@ -107,6 +110,19 @@ static std::vector<int> buildJointIndexMap(const AnimSkeleton& dstSkeleton, cons
|
||||||
return jointIndexMap;
|
return jointIndexMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_CUSTOM_ASSERT
|
||||||
|
#undef ASSERT
|
||||||
|
#define ASSERT(x) \
|
||||||
|
do { \
|
||||||
|
if (!(x)) { \
|
||||||
|
int* bad_ptr = 0; \
|
||||||
|
*bad_ptr = 0x0badf00d; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
#else
|
||||||
|
#define ASSERT assert
|
||||||
|
#endif
|
||||||
|
|
||||||
void AnimClip::copyFromNetworkAnim() {
|
void AnimClip::copyFromNetworkAnim() {
|
||||||
assert(_networkAnim && _networkAnim->isLoaded() && _skeleton);
|
assert(_networkAnim && _networkAnim->isLoaded() && _skeleton);
|
||||||
_anim.clear();
|
_anim.clear();
|
||||||
|
@ -165,11 +181,14 @@ void AnimClip::copyFromNetworkAnim() {
|
||||||
|
|
||||||
for (int frame = 0; frame < animFrameCount; frame++) {
|
for (int frame = 0; frame < animFrameCount; frame++) {
|
||||||
const HFMAnimationFrame& animFrame = animModel.animationFrames[frame];
|
const HFMAnimationFrame& animFrame = animModel.animationFrames[frame];
|
||||||
|
ASSERT(frame >= 0 && frame < (int)animModel.animationFrames.size());
|
||||||
|
|
||||||
// extract the full rotations from the animFrame (including pre and post rotations from the animModel).
|
// extract the full rotations from the animFrame (including pre and post rotations from the animModel).
|
||||||
std::vector<glm::quat> animRotations;
|
std::vector<glm::quat> animRotations;
|
||||||
animRotations.reserve(animJointCount);
|
animRotations.reserve(animJointCount);
|
||||||
for (int i = 0; i < animJointCount; i++) {
|
for (int i = 0; i < animJointCount; i++) {
|
||||||
|
ASSERT(i >= 0 && i < (int)animModel.joints.size());
|
||||||
|
ASSERT(i >= 0 && i < (int)animFrame.rotations.size());
|
||||||
animRotations.push_back(animModel.joints[i].preRotation * animFrame.rotations[i] * animModel.joints[i].postRotation);
|
animRotations.push_back(animModel.joints[i].preRotation * animFrame.rotations[i] * animModel.joints[i].postRotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,10 +199,12 @@ void AnimClip::copyFromNetworkAnim() {
|
||||||
std::vector<glm::quat> avatarRotations;
|
std::vector<glm::quat> avatarRotations;
|
||||||
avatarRotations.reserve(avatarJointCount);
|
avatarRotations.reserve(avatarJointCount);
|
||||||
for (int avatarJointIndex = 0; avatarJointIndex < avatarJointCount; avatarJointIndex++) {
|
for (int avatarJointIndex = 0; avatarJointIndex < avatarJointCount; avatarJointIndex++) {
|
||||||
|
ASSERT(avatarJointIndex >= 0 && avatarJointIndex < (int)avatarToAnimJointIndexMap.size());
|
||||||
int animJointIndex = avatarToAnimJointIndexMap[avatarJointIndex];
|
int animJointIndex = avatarToAnimJointIndexMap[avatarJointIndex];
|
||||||
if (animJointIndex >= 0) {
|
if (animJointIndex >= 0) {
|
||||||
// This joint is in both animation and avatar.
|
// This joint is in both animation and avatar.
|
||||||
// Set the absolute rotation directly
|
// Set the absolute rotation directly
|
||||||
|
ASSERT(animJointIndex >= 0 && animJointIndex < (int)animRotations.size());
|
||||||
avatarRotations.push_back(animRotations[animJointIndex]);
|
avatarRotations.push_back(animRotations[animJointIndex]);
|
||||||
} else {
|
} else {
|
||||||
// This joint is NOT in the animation at all.
|
// This joint is NOT in the animation at all.
|
||||||
|
@ -192,6 +213,7 @@ void AnimClip::copyFromNetworkAnim() {
|
||||||
glm::quat avatarParentAbsoluteRot;
|
glm::quat avatarParentAbsoluteRot;
|
||||||
int avatarParentJointIndex = avatarSkeleton->getParentIndex(avatarJointIndex);
|
int avatarParentJointIndex = avatarSkeleton->getParentIndex(avatarJointIndex);
|
||||||
if (avatarParentJointIndex >= 0) {
|
if (avatarParentJointIndex >= 0) {
|
||||||
|
ASSERT(avatarParentJointIndex >= 0 && avatarParentJointIndex < (int)avatarRotations.size());
|
||||||
avatarParentAbsoluteRot = avatarRotations[avatarParentJointIndex];
|
avatarParentAbsoluteRot = avatarRotations[avatarParentJointIndex];
|
||||||
}
|
}
|
||||||
avatarRotations.push_back(avatarParentAbsoluteRot * avatarRelativeDefaultRot);
|
avatarRotations.push_back(avatarParentAbsoluteRot * avatarRelativeDefaultRot);
|
||||||
|
@ -201,6 +223,7 @@ void AnimClip::copyFromNetworkAnim() {
|
||||||
// convert avatar rotations into relative frame
|
// convert avatar rotations into relative frame
|
||||||
avatarSkeleton->convertAbsoluteRotationsToRelative(avatarRotations);
|
avatarSkeleton->convertAbsoluteRotationsToRelative(avatarRotations);
|
||||||
|
|
||||||
|
ASSERT(frame >= 0 && frame < (int)_anim.size());
|
||||||
_anim[frame].reserve(avatarJointCount);
|
_anim[frame].reserve(avatarJointCount);
|
||||||
for (int avatarJointIndex = 0; avatarJointIndex < avatarJointCount; avatarJointIndex++) {
|
for (int avatarJointIndex = 0; avatarJointIndex < avatarJointCount; avatarJointIndex++) {
|
||||||
const AnimPose& avatarDefaultPose = avatarSkeleton->getRelativeDefaultPose(avatarJointIndex);
|
const AnimPose& avatarDefaultPose = avatarSkeleton->getRelativeDefaultPose(avatarJointIndex);
|
||||||
|
@ -209,12 +232,15 @@ void AnimClip::copyFromNetworkAnim() {
|
||||||
glm::vec3 relativeScale = avatarDefaultPose.scale();
|
glm::vec3 relativeScale = avatarDefaultPose.scale();
|
||||||
|
|
||||||
glm::vec3 relativeTranslation;
|
glm::vec3 relativeTranslation;
|
||||||
|
ASSERT(avatarJointIndex >= 0 && avatarJointIndex < (int)avatarToAnimJointIndexMap.size());
|
||||||
int animJointIndex = avatarToAnimJointIndexMap[avatarJointIndex];
|
int animJointIndex = avatarToAnimJointIndexMap[avatarJointIndex];
|
||||||
if (animJointIndex >= 0) {
|
if (animJointIndex >= 0) {
|
||||||
// This joint is in both animation and avatar.
|
// This joint is in both animation and avatar.
|
||||||
|
ASSERT(animJointIndex >= 0 && animJointIndex < (int)animFrame.translations.size());
|
||||||
const glm::vec3& animTrans = animFrame.translations[animJointIndex];
|
const glm::vec3& animTrans = animFrame.translations[animJointIndex];
|
||||||
|
|
||||||
// retarget translation from animation to avatar
|
// retarget translation from animation to avatar
|
||||||
|
ASSERT(animJointIndex >= 0 && animJointIndex < (int)animModel.animationFrames[0].translations.size());
|
||||||
const glm::vec3& animZeroTrans = animModel.animationFrames[0].translations[animJointIndex];
|
const glm::vec3& animZeroTrans = animModel.animationFrames[0].translations[animJointIndex];
|
||||||
relativeTranslation = avatarDefaultPose.trans() + boneLengthScale * (animTrans - animZeroTrans);
|
relativeTranslation = avatarDefaultPose.trans() + boneLengthScale * (animTrans - animZeroTrans);
|
||||||
} else {
|
} else {
|
||||||
|
@ -224,6 +250,7 @@ void AnimClip::copyFromNetworkAnim() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// build the final pose
|
// build the final pose
|
||||||
|
ASSERT(avatarJointIndex >= 0 && avatarJointIndex < (int)avatarRotations.size());
|
||||||
_anim[frame].push_back(AnimPose(relativeScale, avatarRotations[avatarJointIndex], relativeTranslation));
|
_anim[frame].push_back(AnimPose(relativeScale, avatarRotations[avatarJointIndex], relativeTranslation));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,6 +98,8 @@ public:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const AnimPoseVec& getPoses() const { return getPosesInternal(); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
virtual void setCurrentFrameInternal(float frame) {}
|
virtual void setCurrentFrameInternal(float frame) {}
|
||||||
|
|
|
@ -2232,6 +2232,14 @@ void Rig::initAnimGraph(const QUrl& url) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AnimNode::ConstPointer Rig::findAnimNodeByName(const QString& name) const {
|
||||||
|
if (_animNode) {
|
||||||
|
return _animNode->findByName(name);
|
||||||
|
} else {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool Rig::getModelRegistrationPoint(glm::vec3& modelRegistrationPointOut) const {
|
bool Rig::getModelRegistrationPoint(glm::vec3& modelRegistrationPointOut) const {
|
||||||
if (_animSkeleton && _rootJointIndex >= 0) {
|
if (_animSkeleton && _rootJointIndex >= 0) {
|
||||||
modelRegistrationPointOut = _geometryOffset * -_animSkeleton->getAbsoluteDefaultPose(_rootJointIndex).trans();
|
modelRegistrationPointOut = _geometryOffset * -_animSkeleton->getAbsoluteDefaultPose(_rootJointIndex).trans();
|
||||||
|
@ -2258,7 +2266,7 @@ void Rig::applyOverridePoses() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Rig::buildAbsoluteRigPoses(const AnimPoseVec& relativePoses, AnimPoseVec& absolutePosesOut) {
|
void Rig::buildAbsoluteRigPoses(const AnimPoseVec& relativePoses, AnimPoseVec& absolutePosesOut) const {
|
||||||
DETAILED_PERFORMANCE_TIMER("buildAbsolute");
|
DETAILED_PERFORMANCE_TIMER("buildAbsolute");
|
||||||
if (!_animSkeleton) {
|
if (!_animSkeleton) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -196,6 +196,7 @@ public:
|
||||||
void initAnimGraph(const QUrl& url);
|
void initAnimGraph(const QUrl& url);
|
||||||
|
|
||||||
AnimNode::ConstPointer getAnimNode() const { return _animNode; }
|
AnimNode::ConstPointer getAnimNode() const { return _animNode; }
|
||||||
|
AnimNode::ConstPointer findAnimNodeByName(const QString& name) const;
|
||||||
AnimSkeleton::ConstPointer getAnimSkeleton() const { return _animSkeleton; }
|
AnimSkeleton::ConstPointer getAnimSkeleton() const { return _animSkeleton; }
|
||||||
QScriptValue addAnimationStateHandler(QScriptValue handler, QScriptValue propertiesList);
|
QScriptValue addAnimationStateHandler(QScriptValue handler, QScriptValue propertiesList);
|
||||||
void removeAnimationStateHandler(QScriptValue handler);
|
void removeAnimationStateHandler(QScriptValue handler);
|
||||||
|
@ -243,7 +244,7 @@ public:
|
||||||
Flow& getFlow() { return _internalFlow; }
|
Flow& getFlow() { return _internalFlow; }
|
||||||
|
|
||||||
float getUnscaledEyeHeight() const;
|
float getUnscaledEyeHeight() const;
|
||||||
|
void buildAbsoluteRigPoses(const AnimPoseVec& relativePoses, AnimPoseVec& absolutePosesOut) const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void onLoadComplete();
|
void onLoadComplete();
|
||||||
|
@ -252,7 +253,6 @@ protected:
|
||||||
bool isIndexValid(int index) const { return _animSkeleton && index >= 0 && index < _animSkeleton->getNumJoints(); }
|
bool isIndexValid(int index) const { return _animSkeleton && index >= 0 && index < _animSkeleton->getNumJoints(); }
|
||||||
void updateAnimationStateHandlers();
|
void updateAnimationStateHandlers();
|
||||||
void applyOverridePoses();
|
void applyOverridePoses();
|
||||||
void buildAbsoluteRigPoses(const AnimPoseVec& relativePoses, AnimPoseVec& absolutePosesOut);
|
|
||||||
|
|
||||||
void updateHead(bool headEnabled, bool hipsEnabled, const AnimPose& headMatrix);
|
void updateHead(bool headEnabled, bool hipsEnabled, const AnimPose& headMatrix);
|
||||||
void updateHands(bool leftHandEnabled, bool rightHandEnabled, bool hipsEnabled, bool hipsEstimated,
|
void updateHands(bool leftHandEnabled, bool rightHandEnabled, bool hipsEnabled, bool hipsEstimated,
|
||||||
|
|
Loading…
Reference in a new issue