载入中...
搜索中...
未找到
AnimPlayer.cpp
浏览该文件的文档.
4
5#include "common/Exception.h"
6
7namespace eve::animation {
8
9AnimPlayer::AnimPlayer(AnimSkeleton *skeleton) : skeleton_(skeleton) {
10 if (!skeleton_) throw Exception("AnimPlayer: skeleton is null");
11 pose_.resize(skeleton_->getBoneCount());
12 prevPose_.resize(skeleton_->getBoneCount());
13 skeleton_->applyBindPose(&pose_);
14}
15
16bool AnimPlayer::effectiveLoop() const {
17 if (hasLoopOverride_) return loopOverride_;
18 return clip_ ? clip_->getLoop() : true;
19}
20
21bool AnimPlayer::getLoop() const { return effectiveLoop(); }
22
23void AnimPlayer::setSpeed(float speed) {
24 if (speed < 0.f) throw Exception("AnimPlayer.setSpeed: speed must be >= 0");
25 speed_ = speed;
26}
27
28void AnimPlayer::setTime(float seconds) {
29 if (seconds < 0.f) throw Exception("AnimPlayer.setTime: time must be >= 0");
30 time_ = seconds;
31 if (clip_) {
32 clip_->sample(time_, &pose_, skeleton_);
33 }
34}
35
37 if (!clip) throw Exception("AnimPlayer.play: clip is null");
38 clip_ = clip;
39 prevClip_ = nullptr;
40 blending_ = false;
41 time_ = 0.f;
42 playing_ = true;
43 paused_ = false;
44 clip_->sample(0.f, &pose_, skeleton_);
45}
46
47void AnimPlayer::crossFade(AnimClip *clip, float blendSeconds) {
48 if (!clip) throw Exception("AnimPlayer.crossFade: clip is null");
49 if (blendSeconds < 0.f) throw Exception("AnimPlayer.crossFade: blendSeconds must be >= 0");
50 if (!clip_ || blendSeconds <= 1e-6f) {
51 play(clip);
52 return;
53 }
54 prevClip_ = clip_;
55 prevTime_ = time_;
56 prevPose_.copyFrom(&pose_);
57 clip_ = clip;
58 time_ = 0.f;
59 blendDuration_ = blendSeconds;
60 blendElapsed_ = 0.f;
61 blending_ = true;
62 playing_ = true;
63 paused_ = false;
64}
65
67 playing_ = false;
68 paused_ = false;
69 blending_ = false;
70 clip_ = nullptr;
71 prevClip_ = nullptr;
72 time_ = 0.f;
73 if (skeleton_) skeleton_->applyBindPose(&pose_);
74}
75
77 if (playing_) paused_ = true;
78}
79
81 if (playing_) paused_ = false;
82}
83
84AnimPose *AnimPlayer::getPose() { return &pose_; }
85
86void AnimPlayer::update(float dt) {
87 if (dt < 0.f) throw Exception("AnimPlayer.update: dt must be >= 0");
88 if (!playing_ || paused_ || !clip_) return;
89
90 time_ += dt * speed_;
91 if (!effectiveLoop() && clip_->getDuration() > 0.f && time_ >= clip_->getDuration()) {
92 time_ = clip_->getDuration();
93 playing_ = false;
94 }
95
96 AnimPose sampled;
97 clip_->sample(time_, &sampled, skeleton_);
98
99 if (blending_ && prevClip_) {
100 blendElapsed_ += dt;
101 float t = blendDuration_ > 1e-8f ? blendElapsed_ / blendDuration_ : 1.f;
102 if (t >= 1.f) {
103 blending_ = false;
104 prevClip_ = nullptr;
105 pose_.copyFrom(&sampled);
106 } else {
107 // Advance previous clip time during fade for continuity.
108 prevTime_ += dt * speed_;
109 prevClip_->sample(prevTime_, &prevPose_, skeleton_);
110 pose_.blendFrom(&prevPose_, &sampled, t);
111 }
112 } else {
113 pose_.copyFrom(&sampled);
114 }
115}
116
117} // namespace eve::animation
Keyframed skeletal animation clip (local TRS tracks per bone). Script type: AnimClip.
Definition AnimClip.h:17
float getDuration() const
Definition AnimClip.h:29
bool getLoop() const
Definition AnimClip.h:32
void sample(float time, AnimPose *out, const AnimSkeleton *skeleton=nullptr) const
Sample local pose at time (seconds). If skeleton non-null, missing tracks fall back to bind pose; oth...
Definition AnimClip.cpp:276
void setSpeed(float speed)
void setTime(float seconds)
AnimPlayer(AnimSkeleton *skeleton)
Definition AnimPlayer.cpp:9
void update(float dt)
Advance playback and sample into internal pose.
void crossFade(AnimClip *clip, float blendSeconds)
Cross-fade to clip over blendSeconds (keeps sampling previous until done).
void play(AnimClip *clip)
Evaluated local (and optional world) pose for an AnimSkeleton. Script type: AnimPose.
Definition AnimPose.h:15
void blendFrom(const AnimPose *a, const AnimPose *b, float t)
Definition AnimPose.cpp:62
void copyFrom(const AnimPose *other)
Definition AnimPose.cpp:56
void resize(int boneCount)
Definition AnimPose.cpp:44
3D bone hierarchy + bind-pose local TRS for skeletal animation. Independent of ik::Skeleton3D (FABRIK...
void applyBindPose(class AnimPose *pose) const
Fill pose locals with bind pose.