mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 15:49:24 +02:00
AddRelative blending support (Absolute is still not working)
This commit is contained in:
parent
f1afc9e873
commit
ed3ba876a8
6 changed files with 76 additions and 7 deletions
|
@ -14,9 +14,10 @@
|
||||||
#include "AnimUtil.h"
|
#include "AnimUtil.h"
|
||||||
#include "AnimClip.h"
|
#include "AnimClip.h"
|
||||||
|
|
||||||
AnimBlendLinear::AnimBlendLinear(const QString& id, float alpha) :
|
AnimBlendLinear::AnimBlendLinear(const QString& id, float alpha, AnimBlendType blendType) :
|
||||||
AnimNode(AnimNode::Type::BlendLinear, id),
|
AnimNode(AnimNode::Type::BlendLinear, id),
|
||||||
_alpha(alpha) {
|
_alpha(alpha),
|
||||||
|
_blendType(blendType) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +80,23 @@ void AnimBlendLinear::evaluateAndBlendChildren(const AnimVariantMap& animVars, c
|
||||||
if (prevPoses.size() > 0 && prevPoses.size() == nextPoses.size()) {
|
if (prevPoses.size() > 0 && prevPoses.size() == nextPoses.size()) {
|
||||||
_poses.resize(prevPoses.size());
|
_poses.resize(prevPoses.size());
|
||||||
|
|
||||||
::blend(_poses.size(), &prevPoses[0], &nextPoses[0], alpha, &_poses[0]);
|
if (_blendType == AnimBlendType_Normal) {
|
||||||
|
::blend(_poses.size(), &prevPoses[0], &nextPoses[0], alpha, &_poses[0]);
|
||||||
|
} else if (_blendType == AnimBlendType_AddRelative) {
|
||||||
|
::blendAdd(_poses.size(), &prevPoses[0], &nextPoses[0], alpha, &_poses[0]);
|
||||||
|
} else if (_blendType == AnimBlendType_AddAbsolute) {
|
||||||
|
// onvert from relative to absolute
|
||||||
|
AnimPoseVec prev = prevPoses;
|
||||||
|
_skeleton->convertRelativePosesToAbsolute(prev);
|
||||||
|
AnimPoseVec next = nextPoses;
|
||||||
|
_skeleton->convertRelativePosesToAbsolute(next);
|
||||||
|
|
||||||
|
// then blend
|
||||||
|
::blendAdd(_poses.size(), &prevPoses[0], &nextPoses[0], alpha, &_poses[0]);
|
||||||
|
|
||||||
|
// convert result back into relative
|
||||||
|
_skeleton->convertAbsolutePosesToRelative(_poses);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ class AnimBlendLinear : public AnimNode {
|
||||||
public:
|
public:
|
||||||
friend class AnimTests;
|
friend class AnimTests;
|
||||||
|
|
||||||
AnimBlendLinear(const QString& id, float alpha);
|
AnimBlendLinear(const QString& id, float alpha, AnimBlendType blendType);
|
||||||
virtual ~AnimBlendLinear() override;
|
virtual ~AnimBlendLinear() override;
|
||||||
|
|
||||||
virtual const AnimPoseVec& evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, AnimVariantMap& triggersOut) override;
|
virtual const AnimPoseVec& evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, AnimVariantMap& triggersOut) override;
|
||||||
|
@ -43,6 +43,7 @@ protected:
|
||||||
|
|
||||||
AnimPoseVec _poses;
|
AnimPoseVec _poses;
|
||||||
|
|
||||||
|
AnimBlendType _blendType;
|
||||||
float _alpha;
|
float _alpha;
|
||||||
|
|
||||||
QString _alphaVar;
|
QString _alphaVar;
|
||||||
|
|
|
@ -34,6 +34,13 @@ enum class AnimNodeType {
|
||||||
NumTypes
|
NumTypes
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum AnimBlendType {
|
||||||
|
AnimBlendType_Normal,
|
||||||
|
AnimBlendType_AddRelative,
|
||||||
|
AnimBlendType_AddAbsolute,
|
||||||
|
AnimBlendType_NumTypes
|
||||||
|
};
|
||||||
|
|
||||||
class AnimContext {
|
class AnimContext {
|
||||||
public:
|
public:
|
||||||
AnimContext() {}
|
AnimContext() {}
|
||||||
|
|
|
@ -161,6 +161,19 @@ static EasingType stringToEasingType(const QString& str) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static AnimBlendType stringToAnimBlendType(const QString& str) {
|
||||||
|
if (str == "normal") {
|
||||||
|
return AnimBlendType_Normal;
|
||||||
|
} else if (str == "addRelative") {
|
||||||
|
return AnimBlendType_AddRelative;
|
||||||
|
} else if (str == "addAbsolute") {
|
||||||
|
return AnimBlendType_AddAbsolute;
|
||||||
|
} else {
|
||||||
|
return AnimBlendType_NumTypes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static const char* animManipulatorJointVarTypeToString(AnimManipulator::JointVar::Type type) {
|
static const char* animManipulatorJointVarTypeToString(AnimManipulator::JointVar::Type type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case AnimManipulator::JointVar::Type::Absolute: return "absolute";
|
case AnimManipulator::JointVar::Type::Absolute: return "absolute";
|
||||||
|
@ -413,10 +426,19 @@ static AnimNode::Pointer loadClipNode(const QJsonObject& jsonObj, const QString&
|
||||||
static AnimNode::Pointer loadBlendLinearNode(const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl) {
|
static AnimNode::Pointer loadBlendLinearNode(const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl) {
|
||||||
|
|
||||||
READ_FLOAT(alpha, jsonObj, id, jsonUrl, nullptr);
|
READ_FLOAT(alpha, jsonObj, id, jsonUrl, nullptr);
|
||||||
|
READ_OPTIONAL_STRING(blendType, jsonObj);
|
||||||
READ_OPTIONAL_STRING(alphaVar, jsonObj);
|
READ_OPTIONAL_STRING(alphaVar, jsonObj);
|
||||||
|
|
||||||
auto node = std::make_shared<AnimBlendLinear>(id, alpha);
|
AnimBlendType blendTypeEnum = AnimBlendType_Normal; // default value
|
||||||
|
if (!blendType.isEmpty()) {
|
||||||
|
blendTypeEnum = stringToAnimBlendType(blendType);
|
||||||
|
if (blendTypeEnum == AnimBlendType_NumTypes) {
|
||||||
|
qCCritical(animation) << "AnimNodeLoader, bad blendType on blendLinear, id = " << id;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto node = std::make_shared<AnimBlendLinear>(id, alpha, blendTypeEnum);
|
||||||
|
|
||||||
if (!alphaVar.isEmpty()) {
|
if (!alphaVar.isEmpty()) {
|
||||||
node->setAlphaVar(alphaVar);
|
node->setAlphaVar(alphaVar);
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
|
|
||||||
// TODO: use restrict keyword
|
// TODO: use restrict keyword
|
||||||
// TODO: excellent candidate for simd vectorization.
|
// TODO: excellent candidate for simd vectorization.
|
||||||
|
|
||||||
void blend(size_t numPoses, const AnimPose* a, const AnimPose* b, float alpha, AnimPose* result) {
|
void blend(size_t numPoses, const AnimPose* a, const AnimPose* b, float alpha, AnimPose* result) {
|
||||||
for (size_t i = 0; i < numPoses; i++) {
|
for (size_t i = 0; i < numPoses; i++) {
|
||||||
const AnimPose& aPose = a[i];
|
const AnimPose& aPose = a[i];
|
||||||
|
@ -27,6 +26,26 @@ void blend(size_t numPoses, const AnimPose* a, const AnimPose* b, float alpha, A
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// additive blend
|
||||||
|
void blendAdd(size_t numPoses, const AnimPose* a, const AnimPose* b, float alpha, AnimPose* result) {
|
||||||
|
for (size_t i = 0; i < numPoses; i++) {
|
||||||
|
const AnimPose& aPose = a[i];
|
||||||
|
const AnimPose& bPose = b[i];
|
||||||
|
|
||||||
|
result[i].scale() = lerp(aPose.scale(), bPose.scale(), alpha);
|
||||||
|
|
||||||
|
// adjust sign of bPose.rot() if necessary
|
||||||
|
glm::quat bTemp = bPose.rot();
|
||||||
|
float dot = glm::dot(aPose.rot(), bTemp);
|
||||||
|
if (dot < 0.0f) {
|
||||||
|
bTemp = -bTemp;
|
||||||
|
}
|
||||||
|
result[i].rot() = glm::normalize((alpha * bTemp) * aPose.rot());
|
||||||
|
|
||||||
|
result[i].trans() = aPose.trans() + (alpha * bPose.trans());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
glm::quat averageQuats(size_t numQuats, const glm::quat* quats) {
|
glm::quat averageQuats(size_t numQuats, const glm::quat* quats) {
|
||||||
if (numQuats == 0) {
|
if (numQuats == 0) {
|
||||||
return glm::quat();
|
return glm::quat();
|
||||||
|
|
|
@ -16,6 +16,9 @@
|
||||||
// this is where the magic happens
|
// this is where the magic happens
|
||||||
void blend(size_t numPoses, const AnimPose* a, const AnimPose* b, float alpha, AnimPose* result);
|
void blend(size_t numPoses, const AnimPose* a, const AnimPose* b, float alpha, AnimPose* result);
|
||||||
|
|
||||||
|
// additive blending
|
||||||
|
void blendAdd(size_t numPoses, const AnimPose* a, const AnimPose* b, float alpha, AnimPose* result);
|
||||||
|
|
||||||
glm::quat averageQuats(size_t numQuats, const glm::quat* quats);
|
glm::quat averageQuats(size_t numQuats, const glm::quat* quats);
|
||||||
|
|
||||||
float accumulateTime(float startFrame, float endFrame, float timeScale, float currentFrame, float dt, bool loopFlag,
|
float accumulateTime(float startFrame, float endFrame, float timeScale, float currentFrame, float dt, bool loopFlag,
|
||||||
|
|
Loading…
Reference in a new issue