mirror of
https://github.com/lubosz/overte.git
synced 2025-08-07 17:41:12 +02:00
Support for EvaluteBoth interpType and easing
This commit is contained in:
parent
ee4bb233b9
commit
ec08139a46
7 changed files with 230 additions and 11 deletions
|
@ -29,6 +29,7 @@
|
||||||
#include "AnimTwoBoneIK.h"
|
#include "AnimTwoBoneIK.h"
|
||||||
#include "AnimSplineIK.h"
|
#include "AnimSplineIK.h"
|
||||||
#include "AnimPoleVectorConstraint.h"
|
#include "AnimPoleVectorConstraint.h"
|
||||||
|
#include "AnimUtil.h"
|
||||||
|
|
||||||
using NodeLoaderFunc = AnimNode::Pointer (*)(const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl);
|
using NodeLoaderFunc = AnimNode::Pointer (*)(const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl);
|
||||||
using NodeProcessFunc = bool (*)(AnimNode::Pointer node, const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl);
|
using NodeProcessFunc = bool (*)(AnimNode::Pointer node, const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl);
|
||||||
|
@ -91,6 +92,8 @@ static AnimStateMachine::InterpType stringToInterpType(const QString& str) {
|
||||||
return AnimStateMachine::InterpType::SnapshotBoth;
|
return AnimStateMachine::InterpType::SnapshotBoth;
|
||||||
} else if (str == "snapshotPrev") {
|
} else if (str == "snapshotPrev") {
|
||||||
return AnimStateMachine::InterpType::SnapshotPrev;
|
return AnimStateMachine::InterpType::SnapshotPrev;
|
||||||
|
} else if (str == "evaluateBoth") {
|
||||||
|
return AnimStateMachine::InterpType::EvaluateBoth;
|
||||||
} else {
|
} else {
|
||||||
return AnimStateMachine::InterpType::NumTypes;
|
return AnimStateMachine::InterpType::NumTypes;
|
||||||
}
|
}
|
||||||
|
@ -101,11 +104,61 @@ static AnimRandomSwitch::InterpType stringToRandomInterpType(const QString& str)
|
||||||
return AnimRandomSwitch::InterpType::SnapshotBoth;
|
return AnimRandomSwitch::InterpType::SnapshotBoth;
|
||||||
} else if (str == "snapshotPrev") {
|
} else if (str == "snapshotPrev") {
|
||||||
return AnimRandomSwitch::InterpType::SnapshotPrev;
|
return AnimRandomSwitch::InterpType::SnapshotPrev;
|
||||||
|
} else if (str == "evaluateBoth") {
|
||||||
|
return AnimRandomSwitch::InterpType::EvaluateBoth;
|
||||||
} else {
|
} else {
|
||||||
return AnimRandomSwitch::InterpType::NumTypes;
|
return AnimRandomSwitch::InterpType::NumTypes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static EasingType stringToEasingType(const QString& str) {
|
||||||
|
if (str == "easeInSine") {
|
||||||
|
return EasingType_EaseInSine;
|
||||||
|
} else if (str == "easeOutSine") {
|
||||||
|
return EasingType_EaseOutSine;
|
||||||
|
} else if (str == "easeInOutSine") {
|
||||||
|
return EasingType_EaseInOutSine;
|
||||||
|
} else if (str == "easeInQuad") {
|
||||||
|
return EasingType_EaseInQuad;
|
||||||
|
} else if (str == "easeOutQuad") {
|
||||||
|
return EasingType_EaseOutQuad;
|
||||||
|
} else if (str == "easeInOutQuad") {
|
||||||
|
return EasingType_EaseInOutQuad;
|
||||||
|
} else if (str == "easeInCubic") {
|
||||||
|
return EasingType_EaseInCubic;
|
||||||
|
} else if (str == "easeOutCubic") {
|
||||||
|
return EasingType_EaseOutCubic;
|
||||||
|
} else if (str == "easeInOutCubic") {
|
||||||
|
return EasingType_EaseInOutCubic;
|
||||||
|
} else if (str == "easeInQuart") {
|
||||||
|
return EasingType_EaseInQuart;
|
||||||
|
} else if (str == "easeOutQuart") {
|
||||||
|
return EasingType_EaseOutQuart;
|
||||||
|
} else if (str == "easeInOutQuart") {
|
||||||
|
return EasingType_EaseInOutQuart;
|
||||||
|
} else if (str == "easeInQuint") {
|
||||||
|
return EasingType_EaseInQuint;
|
||||||
|
} else if (str == "easeOutQuint") {
|
||||||
|
return EasingType_EaseOutQuint;
|
||||||
|
} else if (str == "easeInOutQuint") {
|
||||||
|
return EasingType_EaseInOutQuint;
|
||||||
|
} else if (str == "easeInExpo") {
|
||||||
|
return EasingType_EaseInExpo;
|
||||||
|
} else if (str == "easeOutExpo") {
|
||||||
|
return EasingType_EaseOutExpo;
|
||||||
|
} else if (str == "easeInOutExpo") {
|
||||||
|
return EasingType_EaseInOutExpo;
|
||||||
|
} else if (str == "easeInCirc") {
|
||||||
|
return EasingType_EaseInCirc;
|
||||||
|
} else if (str == "easeOutCirc") {
|
||||||
|
return EasingType_EaseOutCirc;
|
||||||
|
} else if (str == "easeInOutCirc") {
|
||||||
|
return EasingType_EaseInOutCirc;
|
||||||
|
} else {
|
||||||
|
return EasingType_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";
|
||||||
|
@ -723,6 +776,7 @@ bool processStateMachineNode(AnimNode::Pointer node, const QJsonObject& jsonObj,
|
||||||
READ_FLOAT(interpTarget, stateObj, nodeId, jsonUrl, false);
|
READ_FLOAT(interpTarget, stateObj, nodeId, jsonUrl, false);
|
||||||
READ_FLOAT(interpDuration, stateObj, nodeId, jsonUrl, false);
|
READ_FLOAT(interpDuration, stateObj, nodeId, jsonUrl, false);
|
||||||
READ_OPTIONAL_STRING(interpType, stateObj);
|
READ_OPTIONAL_STRING(interpType, stateObj);
|
||||||
|
READ_OPTIONAL_STRING(easingType, stateObj);
|
||||||
|
|
||||||
READ_OPTIONAL_STRING(interpTargetVar, stateObj);
|
READ_OPTIONAL_STRING(interpTargetVar, stateObj);
|
||||||
READ_OPTIONAL_STRING(interpDurationVar, stateObj);
|
READ_OPTIONAL_STRING(interpDurationVar, stateObj);
|
||||||
|
@ -743,7 +797,16 @@ bool processStateMachineNode(AnimNode::Pointer node, const QJsonObject& jsonObj,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto statePtr = std::make_shared<AnimStateMachine::State>(id, iter->second, interpTarget, interpDuration, interpTypeEnum);
|
EasingType easingTypeEnum = EasingType_Linear; // default value
|
||||||
|
if (!easingType.isEmpty()) {
|
||||||
|
easingTypeEnum = stringToEasingType(easingType);
|
||||||
|
if (easingTypeEnum == EasingType_NumTypes) {
|
||||||
|
qCCritical(animation) << "AnimNodeLoader, bad easingType on stateMachine state, nodeId = " << nodeId << "stateId =" << id;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto statePtr = std::make_shared<AnimStateMachine::State>(id, iter->second, interpTarget, interpDuration, interpTypeEnum, easingTypeEnum);
|
||||||
assert(statePtr);
|
assert(statePtr);
|
||||||
|
|
||||||
if (!interpTargetVar.isEmpty()) {
|
if (!interpTargetVar.isEmpty()) {
|
||||||
|
@ -845,6 +908,7 @@ bool processRandomSwitchStateMachineNode(AnimNode::Pointer node, const QJsonObje
|
||||||
READ_FLOAT(interpTarget, stateObj, nodeId, jsonUrl, false);
|
READ_FLOAT(interpTarget, stateObj, nodeId, jsonUrl, false);
|
||||||
READ_FLOAT(interpDuration, stateObj, nodeId, jsonUrl, false);
|
READ_FLOAT(interpDuration, stateObj, nodeId, jsonUrl, false);
|
||||||
READ_OPTIONAL_STRING(interpType, stateObj);
|
READ_OPTIONAL_STRING(interpType, stateObj);
|
||||||
|
READ_OPTIONAL_STRING(easingType, stateObj);
|
||||||
READ_FLOAT(priority, stateObj, nodeId, jsonUrl, false);
|
READ_FLOAT(priority, stateObj, nodeId, jsonUrl, false);
|
||||||
READ_BOOL(resume, stateObj, nodeId, jsonUrl, false);
|
READ_BOOL(resume, stateObj, nodeId, jsonUrl, false);
|
||||||
|
|
||||||
|
@ -867,7 +931,16 @@ bool processRandomSwitchStateMachineNode(AnimNode::Pointer node, const QJsonObje
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto randomStatePtr = std::make_shared<AnimRandomSwitch::RandomSwitchState>(id, iter->second, interpTarget, interpDuration, interpTypeEnum, priority, resume);
|
EasingType easingTypeEnum = EasingType_Linear; // default value
|
||||||
|
if (!easingType.isEmpty()) {
|
||||||
|
easingTypeEnum = stringToEasingType(easingType);
|
||||||
|
if (easingTypeEnum == EasingType_NumTypes) {
|
||||||
|
qCCritical(animation) << "AnimNodeLoader, bad easingType on randomSwitch state, nodeId = " << nodeId << "stateId =" << id;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto randomStatePtr = std::make_shared<AnimRandomSwitch::RandomSwitchState>(id, iter->second, interpTarget, interpDuration, interpTypeEnum, easingTypeEnum, priority, resume);
|
||||||
if (priority > 0.0f) {
|
if (priority > 0.0f) {
|
||||||
smNode->addToPrioritySum(priority);
|
smNode->addToPrioritySum(priority);
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,6 +89,7 @@ const AnimPoseVec& AnimRandomSwitch::evaluate(const AnimVariantMap& animVars, co
|
||||||
|
|
||||||
assert(_currentState);
|
assert(_currentState);
|
||||||
auto currentStateNode = _children[_currentState->getChildIndex()];
|
auto currentStateNode = _children[_currentState->getChildIndex()];
|
||||||
|
auto previousStateNode = _children[_previousState->getChildIndex()];
|
||||||
assert(currentStateNode);
|
assert(currentStateNode);
|
||||||
|
|
||||||
if (_duringInterp) {
|
if (_duringInterp) {
|
||||||
|
@ -97,6 +98,7 @@ const AnimPoseVec& AnimRandomSwitch::evaluate(const AnimVariantMap& animVars, co
|
||||||
AnimPoseVec* nextPoses = nullptr;
|
AnimPoseVec* nextPoses = nullptr;
|
||||||
AnimPoseVec* prevPoses = nullptr;
|
AnimPoseVec* prevPoses = nullptr;
|
||||||
AnimPoseVec localNextPoses;
|
AnimPoseVec localNextPoses;
|
||||||
|
AnimPoseVec localPrevPoses;
|
||||||
if (_interpType == InterpType::SnapshotBoth) {
|
if (_interpType == InterpType::SnapshotBoth) {
|
||||||
// interp between both snapshots
|
// interp between both snapshots
|
||||||
prevPoses = &_prevPoses;
|
prevPoses = &_prevPoses;
|
||||||
|
@ -107,13 +109,18 @@ const AnimPoseVec& AnimRandomSwitch::evaluate(const AnimVariantMap& animVars, co
|
||||||
localNextPoses = currentStateNode->evaluate(animVars, context, dt, triggersOut);
|
localNextPoses = currentStateNode->evaluate(animVars, context, dt, triggersOut);
|
||||||
prevPoses = &_prevPoses;
|
prevPoses = &_prevPoses;
|
||||||
nextPoses = &localNextPoses;
|
nextPoses = &localNextPoses;
|
||||||
|
} else if (_interpType == InterpType::EvaluateBoth) {
|
||||||
|
localPrevPoses = previousStateNode->evaluate(animVars, context, dt, triggersOut);
|
||||||
|
localNextPoses = currentStateNode->evaluate(animVars, context, dt, triggersOut);
|
||||||
|
prevPoses = &localPrevPoses;
|
||||||
|
nextPoses = &localNextPoses;
|
||||||
} else {
|
} else {
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
if (_poses.size() > 0 && nextPoses && prevPoses && nextPoses->size() > 0 && prevPoses->size() > 0) {
|
if (_poses.size() > 0 && nextPoses && prevPoses && nextPoses->size() > 0 && prevPoses->size() > 0) {
|
||||||
::blend(_poses.size(), &(prevPoses->at(0)), &(nextPoses->at(0)), _alpha, &_poses[0]);
|
::blend(_poses.size(), &(prevPoses->at(0)), &(nextPoses->at(0)), easingFunc(_alpha, _easingType), &_poses[0]);
|
||||||
}
|
}
|
||||||
context.setDebugAlpha(_currentState->getID(), _alpha * parentDebugAlpha, _children[_currentState->getChildIndex()]->getType());
|
context.setDebugAlpha(_currentState->getID(), easingFunc(_alpha, _easingType) * parentDebugAlpha, _children[_currentState->getChildIndex()]->getType());
|
||||||
} else {
|
} else {
|
||||||
_duringInterp = false;
|
_duringInterp = false;
|
||||||
_prevPoses.clear();
|
_prevPoses.clear();
|
||||||
|
@ -160,6 +167,7 @@ void AnimRandomSwitch::switchRandomState(const AnimVariantMap& animVars, const A
|
||||||
float duration = std::max(0.001f, animVars.lookup(desiredState->_interpDurationVar, desiredState->_interpDuration));
|
float duration = std::max(0.001f, animVars.lookup(desiredState->_interpDurationVar, desiredState->_interpDuration));
|
||||||
_alphaVel = FRAMES_PER_SECOND / duration;
|
_alphaVel = FRAMES_PER_SECOND / duration;
|
||||||
_interpType = (InterpType)animVars.lookup(desiredState->_interpTypeVar, (int)desiredState->_interpType);
|
_interpType = (InterpType)animVars.lookup(desiredState->_interpTypeVar, (int)desiredState->_interpType);
|
||||||
|
_easingType = desiredState->_easingType;
|
||||||
|
|
||||||
// because dt is 0, we should not encounter any triggers
|
// because dt is 0, we should not encounter any triggers
|
||||||
const float dt = 0.0f;
|
const float dt = 0.0f;
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "AnimNode.h"
|
#include "AnimNode.h"
|
||||||
|
#include "AnimUtil.h"
|
||||||
|
|
||||||
// Random Switch State Machine for random transitioning between children AnimNodes
|
// Random Switch State Machine for random transitioning between children AnimNodes
|
||||||
//
|
//
|
||||||
|
@ -51,6 +52,7 @@ public:
|
||||||
enum class InterpType {
|
enum class InterpType {
|
||||||
SnapshotBoth = 0,
|
SnapshotBoth = 0,
|
||||||
SnapshotPrev,
|
SnapshotPrev,
|
||||||
|
EvaluateBoth,
|
||||||
NumTypes
|
NumTypes
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -73,12 +75,13 @@ protected:
|
||||||
RandomSwitchState::Pointer _randomSwitchState;
|
RandomSwitchState::Pointer _randomSwitchState;
|
||||||
};
|
};
|
||||||
|
|
||||||
RandomSwitchState(const QString& id, int childIndex, float interpTarget, float interpDuration, InterpType interpType, float priority, bool resume) :
|
RandomSwitchState(const QString& id, int childIndex, float interpTarget, float interpDuration, InterpType interpType, EasingType easingType, float priority, bool resume) :
|
||||||
_id(id),
|
_id(id),
|
||||||
_childIndex(childIndex),
|
_childIndex(childIndex),
|
||||||
_interpTarget(interpTarget),
|
_interpTarget(interpTarget),
|
||||||
_interpDuration(interpDuration),
|
_interpDuration(interpDuration),
|
||||||
_interpType(interpType),
|
_interpType(interpType),
|
||||||
|
_easingType(easingType),
|
||||||
_priority(priority),
|
_priority(priority),
|
||||||
_resume(resume){
|
_resume(resume){
|
||||||
}
|
}
|
||||||
|
@ -106,6 +109,7 @@ protected:
|
||||||
float _interpTarget; // frames
|
float _interpTarget; // frames
|
||||||
float _interpDuration; // frames
|
float _interpDuration; // frames
|
||||||
InterpType _interpType;
|
InterpType _interpType;
|
||||||
|
EasingType _easingType;
|
||||||
float _priority {0.0f};
|
float _priority {0.0f};
|
||||||
bool _resume {false};
|
bool _resume {false};
|
||||||
|
|
||||||
|
@ -154,7 +158,8 @@ protected:
|
||||||
int _randomSwitchEvaluationCount { 0 };
|
int _randomSwitchEvaluationCount { 0 };
|
||||||
// interpolation state
|
// interpolation state
|
||||||
bool _duringInterp = false;
|
bool _duringInterp = false;
|
||||||
InterpType _interpType{ InterpType::SnapshotPrev };
|
InterpType _interpType { InterpType::SnapshotPrev };
|
||||||
|
EasingType _easingType { EasingType_Linear };
|
||||||
float _alphaVel = 0.0f;
|
float _alphaVel = 0.0f;
|
||||||
float _alpha = 0.0f;
|
float _alpha = 0.0f;
|
||||||
AnimPoseVec _prevPoses;
|
AnimPoseVec _prevPoses;
|
||||||
|
|
|
@ -48,6 +48,7 @@ const AnimPoseVec& AnimStateMachine::evaluate(const AnimVariantMap& animVars, co
|
||||||
|
|
||||||
assert(_currentState);
|
assert(_currentState);
|
||||||
auto currentStateNode = _children[_currentState->getChildIndex()];
|
auto currentStateNode = _children[_currentState->getChildIndex()];
|
||||||
|
auto previousStateNode = _children[_previousState->getChildIndex()];
|
||||||
assert(currentStateNode);
|
assert(currentStateNode);
|
||||||
|
|
||||||
if (_duringInterp) {
|
if (_duringInterp) {
|
||||||
|
@ -56,6 +57,8 @@ const AnimPoseVec& AnimStateMachine::evaluate(const AnimVariantMap& animVars, co
|
||||||
AnimPoseVec* nextPoses = nullptr;
|
AnimPoseVec* nextPoses = nullptr;
|
||||||
AnimPoseVec* prevPoses = nullptr;
|
AnimPoseVec* prevPoses = nullptr;
|
||||||
AnimPoseVec localNextPoses;
|
AnimPoseVec localNextPoses;
|
||||||
|
AnimPoseVec localPrevPoses;
|
||||||
|
|
||||||
if (_interpType == InterpType::SnapshotBoth) {
|
if (_interpType == InterpType::SnapshotBoth) {
|
||||||
// interp between both snapshots
|
// interp between both snapshots
|
||||||
prevPoses = &_prevPoses;
|
prevPoses = &_prevPoses;
|
||||||
|
@ -66,13 +69,18 @@ const AnimPoseVec& AnimStateMachine::evaluate(const AnimVariantMap& animVars, co
|
||||||
localNextPoses = currentStateNode->evaluate(animVars, context, dt, triggersOut);
|
localNextPoses = currentStateNode->evaluate(animVars, context, dt, triggersOut);
|
||||||
prevPoses = &_prevPoses;
|
prevPoses = &_prevPoses;
|
||||||
nextPoses = &localNextPoses;
|
nextPoses = &localNextPoses;
|
||||||
|
} else if (_interpType == InterpType::EvaluateBoth) {
|
||||||
|
localPrevPoses = previousStateNode->evaluate(animVars, context, dt, triggersOut);
|
||||||
|
localNextPoses = currentStateNode->evaluate(animVars, context, dt, triggersOut);
|
||||||
|
prevPoses = &localPrevPoses;
|
||||||
|
nextPoses = &localNextPoses;
|
||||||
} else {
|
} else {
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
if (_poses.size() > 0 && nextPoses && prevPoses && nextPoses->size() > 0 && prevPoses->size() > 0) {
|
if (_poses.size() > 0 && nextPoses && prevPoses && nextPoses->size() > 0 && prevPoses->size() > 0) {
|
||||||
::blend(_poses.size(), &(prevPoses->at(0)), &(nextPoses->at(0)), _alpha, &_poses[0]);
|
::blend(_poses.size(), &(prevPoses->at(0)), &(nextPoses->at(0)), easingFunc(_alpha, _easingType), &_poses[0]);
|
||||||
}
|
}
|
||||||
context.setDebugAlpha(_currentState->getID(), _alpha * parentDebugAlpha, _children[_currentState->getChildIndex()]->getType());
|
context.setDebugAlpha(_currentState->getID(), easingFunc(_alpha, _easingType) * parentDebugAlpha, _children[_currentState->getChildIndex()]->getType());
|
||||||
} else {
|
} else {
|
||||||
_duringInterp = false;
|
_duringInterp = false;
|
||||||
_prevPoses.clear();
|
_prevPoses.clear();
|
||||||
|
@ -125,6 +133,7 @@ void AnimStateMachine::switchState(const AnimVariantMap& animVars, const AnimCon
|
||||||
float duration = std::max(0.001f, animVars.lookup(desiredState->_interpDurationVar, desiredState->_interpDuration));
|
float duration = std::max(0.001f, animVars.lookup(desiredState->_interpDurationVar, desiredState->_interpDuration));
|
||||||
_alphaVel = FRAMES_PER_SECOND / duration;
|
_alphaVel = FRAMES_PER_SECOND / duration;
|
||||||
_interpType = (InterpType)animVars.lookup(desiredState->_interpTypeVar, (int)desiredState->_interpType);
|
_interpType = (InterpType)animVars.lookup(desiredState->_interpTypeVar, (int)desiredState->_interpType);
|
||||||
|
_easingType = desiredState->_easingType;
|
||||||
|
|
||||||
// because dt is 0, we should not encounter any triggers
|
// because dt is 0, we should not encounter any triggers
|
||||||
const float dt = 0.0f;
|
const float dt = 0.0f;
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "AnimNode.h"
|
#include "AnimNode.h"
|
||||||
|
#include "AnimUtil.h"
|
||||||
|
|
||||||
// State Machine for transitioning between children AnimNodes
|
// State Machine for transitioning between children AnimNodes
|
||||||
//
|
//
|
||||||
|
@ -47,6 +48,7 @@ public:
|
||||||
enum class InterpType {
|
enum class InterpType {
|
||||||
SnapshotBoth = 0,
|
SnapshotBoth = 0,
|
||||||
SnapshotPrev,
|
SnapshotPrev,
|
||||||
|
EvaluateBoth,
|
||||||
NumTypes
|
NumTypes
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -69,12 +71,13 @@ protected:
|
||||||
State::Pointer _state;
|
State::Pointer _state;
|
||||||
};
|
};
|
||||||
|
|
||||||
State(const QString& id, int childIndex, float interpTarget, float interpDuration, InterpType interpType) :
|
State(const QString& id, int childIndex, float interpTarget, float interpDuration, InterpType interpType, EasingType easingType) :
|
||||||
_id(id),
|
_id(id),
|
||||||
_childIndex(childIndex),
|
_childIndex(childIndex),
|
||||||
_interpTarget(interpTarget),
|
_interpTarget(interpTarget),
|
||||||
_interpDuration(interpDuration),
|
_interpDuration(interpDuration),
|
||||||
_interpType(interpType) {}
|
_interpType(interpType),
|
||||||
|
_easingType(easingType) {}
|
||||||
|
|
||||||
void setInterpTargetVar(const QString& interpTargetVar) { _interpTargetVar = interpTargetVar; }
|
void setInterpTargetVar(const QString& interpTargetVar) { _interpTargetVar = interpTargetVar; }
|
||||||
void setInterpDurationVar(const QString& interpDurationVar) { _interpDurationVar = interpDurationVar; }
|
void setInterpDurationVar(const QString& interpDurationVar) { _interpDurationVar = interpDurationVar; }
|
||||||
|
@ -95,6 +98,7 @@ protected:
|
||||||
float _interpTarget; // frames
|
float _interpTarget; // frames
|
||||||
float _interpDuration; // frames
|
float _interpDuration; // frames
|
||||||
InterpType _interpType;
|
InterpType _interpType;
|
||||||
|
EasingType _easingType;
|
||||||
|
|
||||||
QString _interpTargetVar;
|
QString _interpTargetVar;
|
||||||
QString _interpDurationVar;
|
QString _interpDurationVar;
|
||||||
|
@ -135,6 +139,7 @@ protected:
|
||||||
// interpolation state
|
// interpolation state
|
||||||
bool _duringInterp = false;
|
bool _duringInterp = false;
|
||||||
InterpType _interpType { InterpType::SnapshotPrev };
|
InterpType _interpType { InterpType::SnapshotPrev };
|
||||||
|
EasingType _easingType { EasingType_Linear };
|
||||||
float _alphaVel = 0.0f;
|
float _alphaVel = 0.0f;
|
||||||
float _alpha = 0.0f;
|
float _alpha = 0.0f;
|
||||||
AnimPoseVec _prevPoses;
|
AnimPoseVec _prevPoses;
|
||||||
|
|
|
@ -211,3 +211,95 @@ bool findPointKDopDisplacement(const glm::vec3& point, const AnimPose& shapePose
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// See https://easings.net/en# for a graphical visualiztion of easing types.
|
||||||
|
float easingFunc(float alpha, EasingType type) {
|
||||||
|
switch (type) {
|
||||||
|
case EasingType_Linear:
|
||||||
|
return alpha;
|
||||||
|
case EasingType_EaseInSine:
|
||||||
|
return sinf((alpha - 1.0f) * PI_OVER_TWO) + 1.0f;
|
||||||
|
case EasingType_EaseOutSine:
|
||||||
|
return sinf(alpha * PI_OVER_TWO);
|
||||||
|
case EasingType_EaseInOutSine:
|
||||||
|
return 0.5f * (1.0f - cos(alpha * PI));
|
||||||
|
case EasingType_EaseInQuad:
|
||||||
|
return alpha * alpha;
|
||||||
|
case EasingType_EaseOutQuad:
|
||||||
|
return -(alpha * (alpha - 2.0f));
|
||||||
|
case EasingType_EaseInOutQuad:
|
||||||
|
return (alpha < 0.5f) ? (2.0f * alpha * alpha) : ((-2.0f * alpha * alpha) + (4.0f * alpha) - 1.0f);
|
||||||
|
case EasingType_EaseInCubic:
|
||||||
|
return alpha * alpha * alpha;
|
||||||
|
case EasingType_EaseOutCubic:
|
||||||
|
{
|
||||||
|
float temp = alpha - 1.0f;
|
||||||
|
return temp * temp * temp + 1.0f;
|
||||||
|
}
|
||||||
|
case EasingType_EaseInOutCubic:
|
||||||
|
if (alpha < 0.5f) {
|
||||||
|
return 4.0f * alpha * alpha * alpha;
|
||||||
|
} else {
|
||||||
|
float temp = ((2.0f * alpha) - 2.0f);
|
||||||
|
return 0.5f * temp * temp * temp + 1.0f;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EasingType_EaseInQuart:
|
||||||
|
return alpha * alpha * alpha * alpha;
|
||||||
|
case EasingType_EaseOutQuart:
|
||||||
|
{
|
||||||
|
float temp = alpha - 1.0f;
|
||||||
|
return temp * temp * temp * (1.0f - alpha) + 1.0f;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EasingType_EaseInOutQuart:
|
||||||
|
if (alpha < 0.5f) {
|
||||||
|
return 8.0f * alpha * alpha * alpha * alpha;
|
||||||
|
} else {
|
||||||
|
float temp = alpha - 1.0f;
|
||||||
|
return -8.0f * temp * temp * temp * temp + 1.0f;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EasingType_EaseInQuint:
|
||||||
|
return alpha * alpha * alpha * alpha * alpha;
|
||||||
|
case EasingType_EaseOutQuint:
|
||||||
|
{
|
||||||
|
float temp = (alpha - 1.0f);
|
||||||
|
return temp * temp * temp * temp * temp + 1.0f;
|
||||||
|
}
|
||||||
|
case EasingType_EaseInOutQuint:
|
||||||
|
if (alpha < 0.5f) {
|
||||||
|
return 16.0f * alpha * alpha * alpha * alpha * alpha;
|
||||||
|
} else {
|
||||||
|
float temp = ((2.0f * alpha) - 2.0f);
|
||||||
|
return 0.5f * temp * temp * temp * temp * temp + 1.0f;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EasingType_EaseInExpo:
|
||||||
|
return (alpha == 0.0f) ? alpha : powf(2.0f, 10.0f * (alpha - 1.0f));
|
||||||
|
case EasingType_EaseOutExpo:
|
||||||
|
return (alpha == 1.0f) ? alpha : 1.0f - powf(2.0f, -10.0f * alpha);
|
||||||
|
case EasingType_EaseInOutExpo:
|
||||||
|
if (alpha == 0.0f || alpha == 1.0f)
|
||||||
|
return alpha;
|
||||||
|
else if (alpha < 0.5) {
|
||||||
|
return 0.5f * powf(2.0f, (20.0f * alpha) - 10.0f);
|
||||||
|
} else {
|
||||||
|
return -0.5f * powf(2.0f, (-20.0f * alpha) + 10.0f) + 1.0f;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EasingType_EaseInCirc:
|
||||||
|
return 1.0f - sqrtf(1.0f - (alpha * alpha));
|
||||||
|
case EasingType_EaseOutCirc:
|
||||||
|
return sqrtf((2.0f - alpha) * alpha);
|
||||||
|
case EasingType_EaseInOutCirc:
|
||||||
|
if (alpha < 0.5f) {
|
||||||
|
return 0.5f * (1.0f - sqrtf(1.0f - 4.0f * (alpha * alpha)));
|
||||||
|
} else {
|
||||||
|
return 0.5f * (sqrtf(-((2.0f * alpha) - 3.0f) * ((2.0f * alpha) - 1.0f)) + 1.0f);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return alpha;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -128,10 +128,37 @@ protected:
|
||||||
bool _snapshotValid { false };
|
bool _snapshotValid { false };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// returns true if the given point lies inside of the k-dop, specified by shapeInfo & shapePose.
|
// returns true if the given point lies inside of the k-dop, specified by shapeInfo & shapePose.
|
||||||
// if the given point does lie within the k-dop, it also returns the amount of displacement necessary to push that point outward
|
// if the given point does lie within the k-dop, it also returns the amount of displacement necessary to push that point outward
|
||||||
// such that it lies on the surface of the kdop.
|
// such that it lies on the surface of the kdop.
|
||||||
bool findPointKDopDisplacement(const glm::vec3& point, const AnimPose& shapePose, const HFMJointShapeInfo& shapeInfo, glm::vec3& displacementOut);
|
bool findPointKDopDisplacement(const glm::vec3& point, const AnimPose& shapePose, const HFMJointShapeInfo& shapeInfo, glm::vec3& displacementOut);
|
||||||
|
|
||||||
|
enum EasingType {
|
||||||
|
EasingType_Linear,
|
||||||
|
EasingType_EaseInSine,
|
||||||
|
EasingType_EaseOutSine,
|
||||||
|
EasingType_EaseInOutSine,
|
||||||
|
EasingType_EaseInQuad,
|
||||||
|
EasingType_EaseOutQuad,
|
||||||
|
EasingType_EaseInOutQuad,
|
||||||
|
EasingType_EaseInCubic,
|
||||||
|
EasingType_EaseOutCubic,
|
||||||
|
EasingType_EaseInOutCubic,
|
||||||
|
EasingType_EaseInQuart,
|
||||||
|
EasingType_EaseOutQuart,
|
||||||
|
EasingType_EaseInOutQuart,
|
||||||
|
EasingType_EaseInQuint,
|
||||||
|
EasingType_EaseOutQuint,
|
||||||
|
EasingType_EaseInOutQuint,
|
||||||
|
EasingType_EaseInExpo,
|
||||||
|
EasingType_EaseOutExpo,
|
||||||
|
EasingType_EaseInOutExpo,
|
||||||
|
EasingType_EaseInCirc,
|
||||||
|
EasingType_EaseOutCirc,
|
||||||
|
EasingType_EaseInOutCirc,
|
||||||
|
EasingType_NumTypes
|
||||||
|
};
|
||||||
|
|
||||||
|
float easingFunc(float alpha, EasingType type);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue