mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 11:45:36 +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 "AnimClip.h"
|
||||
|
||||
AnimBlendLinear::AnimBlendLinear(const QString& id, float alpha) :
|
||||
AnimBlendLinear::AnimBlendLinear(const QString& id, float alpha, AnimBlendType blendType) :
|
||||
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()) {
|
||||
_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:
|
||||
friend class AnimTests;
|
||||
|
||||
AnimBlendLinear(const QString& id, float alpha);
|
||||
AnimBlendLinear(const QString& id, float alpha, AnimBlendType blendType);
|
||||
virtual ~AnimBlendLinear() override;
|
||||
|
||||
virtual const AnimPoseVec& evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, AnimVariantMap& triggersOut) override;
|
||||
|
@ -43,6 +43,7 @@ protected:
|
|||
|
||||
AnimPoseVec _poses;
|
||||
|
||||
AnimBlendType _blendType;
|
||||
float _alpha;
|
||||
|
||||
QString _alphaVar;
|
||||
|
|
|
@ -34,6 +34,13 @@ enum class AnimNodeType {
|
|||
NumTypes
|
||||
};
|
||||
|
||||
enum AnimBlendType {
|
||||
AnimBlendType_Normal,
|
||||
AnimBlendType_AddRelative,
|
||||
AnimBlendType_AddAbsolute,
|
||||
AnimBlendType_NumTypes
|
||||
};
|
||||
|
||||
class AnimContext {
|
||||
public:
|
||||
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) {
|
||||
switch (type) {
|
||||
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) {
|
||||
|
||||
READ_FLOAT(alpha, jsonObj, id, jsonUrl, nullptr);
|
||||
|
||||
READ_OPTIONAL_STRING(blendType, 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()) {
|
||||
node->setAlphaVar(alphaVar);
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
|
||||
// TODO: use restrict keyword
|
||||
// TODO: excellent candidate for simd vectorization.
|
||||
|
||||
void blend(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];
|
||||
|
@ -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) {
|
||||
if (numQuats == 0) {
|
||||
return glm::quat();
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
// this is where the magic happens
|
||||
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);
|
||||
|
||||
float accumulateTime(float startFrame, float endFrame, float timeScale, float currentFrame, float dt, bool loopFlag,
|
||||
|
|
Loading…
Reference in a new issue