载入中...
搜索中...
未找到
ClimbingAnimation.cpp
浏览该文件的文档.
2
8#include "common/Exception.h"
9
10#include <cmath>
11#include <optional>
12#include <utility>
13
14namespace eve::climbing {
15namespace {
16
17std::optional<ClimbingNotifyKind> parseNotify(std::string_view name) {
18 if (name == "contact.left_hand") return ClimbingNotifyKind::ContactLeftHand;
19 if (name == "contact.right_hand") return ClimbingNotifyKind::ContactRightHand;
20 if (name == "collision.compact") return ClimbingNotifyKind::CollisionCompact;
21 if (name == "branch.open") return ClimbingNotifyKind::BranchOpen;
22 if (name == "branch.close") return ClimbingNotifyKind::BranchClose;
23 if (name == "land") return ClimbingNotifyKind::Land;
24 return std::nullopt;
25}
26
27bool finite(Vec3 value) { return std::isfinite(value.x) && std::isfinite(value.y) && std::isfinite(value.z); }
28
29} // namespace
30
32 int rootMotionBone) {
33 animation::AnimSkeleton* skeleton = player.getSkeleton();
34 if (!skeleton || rootMotionBone < 0 || rootMotionBone >= skeleton->getBoneCount())
36 "root-motion bone is invalid", "rootMotionBone", {},
37 "climbing.animation"));
38 if (!std::isfinite(clip.getDuration()) || clip.getDuration() <= 0.f)
40 eve::DiagnosticCode::PreconditionViolation, "climbing animation clip must have a positive finite duration",
41 "clip.duration", {}, "climbing.animation"));
42 player.setRootMotionBone(rootMotionBone);
43 player.setLoop(false);
44 player.play(&clip);
46}
47
50 if (!binding.clipId.empty() && clip.getName() != binding.clipId)
52 "animation clip does not match the climbing binding",
53 "binding.clipId", {}, "climbing.animation"));
54 animation::AnimSkeleton* skeleton = player.getSkeleton();
55 if (!skeleton)
57 "animation player has no skeleton", "player.skeleton",
58 {}, "climbing.animation"));
59 const int rootMotionBone = skeleton->findBone(binding.rootBone);
60 if (rootMotionBone < 0)
62 "climbing root-motion bone does not exist",
63 "binding.rootBone", {}, "climbing.animation"));
64 return beginClimbingAnimation(player, clip, rootMotionBone);
65}
66
69 Vec3 pelvisOffset) {
70 if (!finite(facing) || !finite(pelvisOffset))
72 eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument, "facing and pelvis offset must be finite",
73 "animationInput", {}, "climbing.animation"));
74 auto advanced = player.advance(step);
75 if (!advanced) return eve::Result<ClimbingAnimationFrame>::failure(advanced.status());
76
78 frame.motion.rootTranslation = {player.getRootMotionX(), player.getRootMotionY(), player.getRootMotionZ()};
79 frame.motion.facing = facing;
80 frame.motion.pelvisOffset = pelvisOffset;
81 const float qx = player.getRootMotionRotationX();
82 const float qy = player.getRootMotionRotationY();
83 const float qz = player.getRootMotionRotationZ();
84 const float qw = player.getRootMotionRotationW();
85 frame.motion.rootYawRadians = std::atan2(2.f * (qw * qy + qx * qz), 1.f - 2.f * (qy * qy + qz * qz));
86 frame.motion.hasRootMotion = player.isPlaying();
87 if (!finite(frame.motion.rootTranslation) || !std::isfinite(frame.motion.rootYawRadians))
89 eve::DiagnosticCode::InvariantViolation, "animation player produced non-finite root motion", "rootMotion",
90 {}, "climbing.animation"));
91
92 for (int index = 0; index < player.getEventCount(); ++index) {
93 const auto parsed = parseNotify(player.getEventName(index));
94 if (parsed) {
95 frame.motion.notifies.push_back(*parsed);
97 } else {
98 ++frame.ignoredNotifyCount;
99 }
100 }
101 return eve::Result<ClimbingAnimationFrame>::success(std::move(frame),
103}
104
107 if (executionId.isZero())
109 eve::DiagnosticCode::InvalidArgument, "graph projection requires a committed execution id", "executionId",
110 {}, "climbing.animation"));
111 if (oneShotNode < 0 || oneShotNode >= graph.getNodeCount())
113 eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument, "climbing graph one-shot node is invalid",
114 "oneShotNode", {}, "climbing.animation"));
115 if (state.activeExecutionId == executionId && state.provider == ClimbingGraphProvider::AnimGraph)
118 try {
119 graph.trigger(oneShotNode);
120 } catch (const eve::Exception& exception) {
122 eve::DiagnosticCode::PreconditionViolation, exception.what(), "oneShotNode", {}, "climbing.animation"));
123 }
124 state.activeExecutionId = executionId;
128}
129
131 animation::MotionMatcher& matcher, const eve::SimulationStep& step, Vec3 desiredVelocity,
132 float desiredYaw, ClimbingGraphState& state) {
133 if (!finite(desiredVelocity) || !std::isfinite(desiredYaw))
135 eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument, "motion-matching intent must be finite",
136 "motionMatching.intent", {}, "climbing.animation"));
137 matcher.setDesiredVelocity(desiredVelocity.x, desiredVelocity.z);
138 matcher.setDesiredYaw(desiredYaw);
139 auto advanced = matcher.advance(step);
140 if (!advanced) return eve::Result<ClimbingGraphProvider>::failure(advanced.status());
141 state.activeExecutionId = ClimbingExecutionId::zero();
145}
146
152
153} // namespace eve::climbing
double value
eve::action::ActionExecutionId executionId
Borrowed Animation player/graph adapters for climbing root motion and semantic notifies.
glm::vec4 clip
std::string name
ModuleFacing facing
bool finite
std::map< std::string, std::vector< std::string > > graph
Definition Package.cpp:59
eve::action::ActionVfxBinding binding
float step
Definition TreeMesh.cpp:314
uint32_t index
float qy
float qx
float qw
float qz
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
EVENGINE_API_FOUNDATION public API.
Definition Exception.h:13
virtual const char * what() const
Returns a string containing reason for the exception.
Definition Exception.h:24
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
Keyframed skeletal animation clip (local TRS tracks per bone). Script type: AnimClip.
Definition AnimClip.h:145
Composable runtime pose graph supporting clips, blends, additive layers, per-bone masks,...
Definition AnimGraph.h:26
Single-clip (or cross-fading) 3D animation player. Script type: AnimPlayer.
Definition AnimPlayer.h:30
AnimSkeleton * getSkeleton() const override
Borrowed pointer accessor. @ownership Borrowed @lifetime Valid while the owning animation object rema...
Definition AnimPlayer.h:44
float getRootMotionRotationW() const
Returns the root motion rotation w.
Definition AnimPlayer.h:124
std::string getEventName(int index) const override
Name of a dispatched event, or empty for invalid index.
eve::Result< void > advance(const eve::SimulationStep &step) override
Advance playback and sample into internal pose.
float getRootMotionRotationY() const
Returns the root motion rotation y.
Definition AnimPlayer.h:120
void setRootMotionBone(int boneIndex)
Select the bone whose per-frame motion is extracted (default 0).
float getRootMotionY() const
Returns the root motion y.
Definition AnimPlayer.h:114
void setLoop(bool loop)
Sets the loop.
Definition AnimPlayer.h:69
int getEventCount() const override
Number of events crossed by the most recent play/update call.
Definition AnimPlayer.h:133
float getRootMotionX() const
Controller-facing translation X after policy filtering (BoneLocal or CharacterFacing).
Definition AnimPlayer.h:112
float getRootMotionRotationX() const
Returns the root motion rotation x.
Definition AnimPlayer.h:118
float getRootMotionRotationZ() const
Returns the root motion rotation z.
Definition AnimPlayer.h:122
bool isPlaying() const
True when playing.
Definition AnimPlayer.h:77
float getRootMotionZ() const
Returns the root motion z.
Definition AnimPlayer.h:116
void play(AnimClip *clip)
Play.
3D bone hierarchy + bind-pose local TRS for skeletal animation. Independent of ik::Skeleton3D (FABRIK...
int getBoneCount() const
Returns the bone count.
int findBone(const std::string &name) const
Finds bone.
Runtime motion matching player: builds a query feature from current pose + desired trajectory,...
void setDesiredYaw(float yaw)
Desired facing yaw (radians, Y-up).
void setDesiredVelocity(float x, float z)
Desired planar velocity in character/world XZ (units/sec).
eve::Result< void > advance(const eve::SimulationStep &step)
Advance matching and pose blending by one scheduler step.
static constexpr StrongUint64 zero() noexcept
Returns the zero value for this strong type.
constexpr bool isZero() const noexcept
Returns whether this value is zero.
eve::Result< ClimbingAnimationFrame > advanceClimbingAnimation(animation::AnimPlayer &player, const eve::SimulationStep &step, Vec3 facing, Vec3 pelvisOffset)
Advances a borrowed player once and extracts root motion plus known semantic notifies.
eve::Result< ClimbingGraphProvider > driveClimbingGraph(animation::AnimGraph &graph, int oneShotNode, ClimbingExecutionId executionId, ClimbingGraphState &state)
Triggers a graph one-shot exactly once for a new climbing execution.
eve::Result< void > beginClimbingAnimation(animation::AnimPlayer &player, animation::AnimClip &clip, int rootMotionBone)
Starts a borrowed clip in a borrowed player and selects its root-motion bone.
eve::Result< ClimbingGraphProvider > driveClimbingMotionMatching(animation::MotionMatcher &matcher, const eve::SimulationStep &step, Vec3 desiredVelocity, float desiredYaw, ClimbingGraphState &state)
Advances ordinary locomotion Motion Matching and marks it as the current presentation provider.
ClimbingGraphProvider useDirectClimbingPose(ClimbingExecutionId executionId, ClimbingGraphState &state) noexcept
Selects the explicit no-graph degradation path without mutating gameplay authority.
ClimbingGraphProvider
Presentation provider selected for the climbing action pose.
One deterministic fixed-step emitted by SimulationClock.
Definition Time.h:158
Stable animation asset and graph binding metadata.
Definition Climbing.h:100
Owning result of extracting one animation frame for authoritative climbing motion.
Non-authoritative graph projection state; contains no borrowed pointers.
std::vector< ClimbingNotifyKind > notifies
Owning semantic notifies crossed by the animation player during this exact simulation step.
Definition Climbing.h:547
Small owning world-space vector used at climbing module boundaries.