载入中...
搜索中...
未找到
RootMotionPolicy.cpp
浏览该文件的文档.
2
4
5#include <cmath>
6#include <cstdint>
7#include <string>
8
9namespace eve::animation {
10namespace {
11
12bool isKnownApplySpace(RootMotionApplySpace space) noexcept {
14}
15
16bool isKnownLockMask(RootMotionLockAxes mask) noexcept {
17 constexpr std::uint8_t kAll = static_cast<std::uint8_t>(RootMotionLockAxes::All);
18 return (static_cast<std::uint8_t>(mask) & static_cast<std::uint8_t>(~kAll)) == 0;
19}
20
21TransformTRS sanitize(TransformTRS delta) {
22 if (!std::isfinite(delta.px)) delta.px = 0.f;
23 if (!std::isfinite(delta.py)) delta.py = 0.f;
24 if (!std::isfinite(delta.pz)) delta.pz = 0.f;
25 if (!std::isfinite(delta.qx) || !std::isfinite(delta.qy) || !std::isfinite(delta.qz) ||
26 !std::isfinite(delta.qw)) {
27 delta.qx = delta.qy = delta.qz = 0.f;
28 delta.qw = 1.f;
29 } else {
30 delta.normalizeRotation();
31 }
32 return delta;
33}
34
35TransformTRS rotatePlanarByYaw(TransformTRS delta, float yaw) {
36 const float c = std::cos(yaw);
37 const float s = std::sin(yaw);
38 const float x = delta.px;
39 const float z = delta.pz;
40 // Ry(yaw) * (x,0,z) with forward (sin(yaw), 0, cos(yaw)) for +Z local.
41 delta.px = x * c + z * s;
42 delta.pz = -x * s + z * c;
43 return delta;
44}
45
46} // namespace
47
49 if (!std::isfinite(policy.characterYaw))
51 "root motion policy characterYaw must be finite"));
52 if (!isKnownApplySpace(policy.applySpace))
54 "root motion policy applySpace is unknown"));
55 if (!isKnownLockMask(policy.lockAxes))
57 "root motion policy lockAxes has unknown bits"));
59}
60
62 TransformTRS delta = sanitize(rawDelta);
63 if (policy.lockRotation) {
64 delta.qx = delta.qy = delta.qz = 0.f;
65 delta.qw = 1.f;
66 }
67 if (policy.applySpace == RootMotionApplySpace::CharacterFacing && std::isfinite(policy.characterYaw))
68 delta = rotatePlanarByYaw(delta, policy.characterYaw);
69 if (hasLock(policy.lockAxes, RootMotionLockAxes::X)) delta.px = 0.f;
70 if (hasLock(policy.lockAxes, RootMotionLockAxes::Y)) delta.py = 0.f;
71 if (hasLock(policy.lockAxes, RootMotionLockAxes::Z)) delta.pz = 0.f;
72 return delta;
73}
74
76 const RootMotionPolicy& policy) {
77 if (boneIndex < 0 || boneIndex >= pose.getBoneCount())
79 "bake root motion bone index out of range"));
80 if (!policy.bakeTranslationIntoPose && !policy.bakeRotationIntoPose)
82
83 TransformTRS& root = pose.local(boneIndex);
84 bool changed = false;
85 if (policy.bakeTranslationIntoPose) {
86 // Locked pose-local axes stay animated (e.g. vertical bob); unlocked axes
87 // plant on the stable reference so the capsule owns locomotion.
88 if (!hasLock(policy.lockAxes, RootMotionLockAxes::X) && root.px != referenceRoot.px) {
89 root.px = referenceRoot.px;
90 changed = true;
91 }
92 if (!hasLock(policy.lockAxes, RootMotionLockAxes::Y) && root.py != referenceRoot.py) {
93 root.py = referenceRoot.py;
94 changed = true;
95 }
96 if (!hasLock(policy.lockAxes, RootMotionLockAxes::Z) && root.pz != referenceRoot.pz) {
97 root.pz = referenceRoot.pz;
98 changed = true;
99 }
100 }
101 if (policy.bakeRotationIntoPose && !policy.lockRotation) {
102 root.qx = referenceRoot.qx;
103 root.qy = referenceRoot.qy;
104 root.qz = referenceRoot.qz;
105 root.qw = referenceRoot.qw;
106 root.normalizeRotation();
107 changed = true;
108 }
111}
112
132
142
143} // namespace eve::animation
float x
Definition AnimClip.cpp:738
float z
Definition AnimClip.cpp:738
int root
Definition AnimSmr.cpp:119
eve::EntitySpatialPose pose
const std::string & s
int mask
std::int32_t c
std::string name
static Diagnostic error(DiagnosticCode code, std::string message, std::string path={}, DiagnosticDetails details={}, std::string source={})
Construct an error diagnostic with the standard error severity.
Definition Diagnostic.h:125
Move-only operation result carrying either a value or Status.
Definition Result.h:155
static Result success(T value)
Construct a successful result owning value.
Definition Result.h:164
static Result failure(Status status)
Construct a failed result from a structured status.
Definition Result.h:175
static Status success(StatusCode code=StatusCode::Ok)
Construct a successful status with an explicit non-error outcome.
Definition Status.h:81
Evaluated local (and optional world) pose for an AnimSkeleton. Script type: AnimPose.
Definition AnimPose.h:17
RootMotionLockAxes
Per-axis translation locks for extracted root-motion deltas.
eve::Result< void > bakeRootMotionIntoPose(AnimPose &pose, int boneIndex, const TransformTRS &referenceRoot, const RootMotionPolicy &policy)
Remove extracted root motion from a pose when bake flags are set.
eve::Result< void > validateRootMotionPolicy(const RootMotionPolicy &policy)
Validate policy fields.
TransformTRS applyRootMotionPolicy(const TransformTRS &rawDelta, const RootMotionPolicy &policy)
Filter a raw root-bone delta into a controller-facing delta.
RootMotionApplySpace
Coordinate space used when publishing root-motion translation.
eve::Result< RootMotionLockAxes > parseRootMotionLockAxes(std::string_view name)
Parse a script/C++ lock-axis name.
constexpr bool hasLock(RootMotionLockAxes mask, RootMotionLockAxes axis) noexcept
True when mask contains the given axis bit.
eve::Result< RootMotionApplySpace > parseRootMotionApplySpace(std::string_view name)
Parse a script/C++ apply-space name.
Policy applied after raw root-bone delta extraction. @ownership Value type; owned by AnimPlayer or th...
float characterYaw
Yaw in radians for CharacterFacing; ignored for BoneLocal.
Local TRS used by skeletal animation (quaternion xyzw).
Definition AnimMath.h:9