载入中...
搜索中...
未找到
AnimTrail.cpp
浏览该文件的文档.
2
5
6#include "common/Exception.h"
7#include "graphics/Graphics.h"
8
9#include <algorithm>
10#include <cmath>
11
12namespace eve::animation {
13
14// Color lives in eve::graphics (see graphics/Canvas.h); keep the unqualified form.
16
20
22 if (capacity < 2) throw Exception("AnimTrail.setCapacity: capacity must be >= 2");
23 capacity_ = capacity;
24 while (static_cast<int>(points_.size()) > capacity_) {
25 points_.erase(points_.begin());
26 }
27}
28
29void AnimTrail::setDuration(float seconds) {
30 duration_ = seconds;
31}
32
34 if (distance < 0.f) throw Exception("AnimTrail.setMinDistance: must be >= 0");
35 minDistance_ = distance;
36}
37
39 if (pixels <= 0.f) throw Exception("AnimTrail.setWidth: must be > 0");
40 width_ = pixels;
41}
42
43void AnimTrail::setColor(float r, float g, float b, float a) {
44 colorR_ = r;
45 colorG_ = g;
46 colorB_ = b;
47 colorA_ = a;
48}
49
50void AnimTrail::setFade(bool enable) { fade_ = enable; }
51
52void AnimTrail::setStyle(const std::string &style) {
53 if (style == "line") {
54 style_ = Style::Line;
55 return;
56 }
57 if (style == "points") {
58 style_ = Style::Points;
59 return;
60 }
61 throw Exception("AnimTrail.setStyle: unknown style '%s' (use line|points)", style.c_str());
62}
63
64std::string AnimTrail::getStyle() const {
65 return style_ == Style::Line ? "line" : "points";
66}
67
68void AnimTrail::setDrawScale(float sx, float sy) {
69 drawScaleX_ = sx;
70 drawScaleY_ = sy;
71}
72
73void AnimTrail::setDrawOffset(float ox, float oy) {
74 drawOffsetX_ = ox;
75 drawOffsetY_ = oy;
76}
77
78void AnimTrail::addPoint(float x, float y) { pushPoint(x, y, 0.f); }
79
80void AnimTrail::addPoint3(float x, float y, float z) { pushPoint(x, y, z); }
81
82void AnimTrail::projectPlane(float x, float y, float z, const std::string &plane, float *outX,
83 float *outY) const {
84 if (!outX || !outY) return;
85 if (plane == "xy" || plane.empty()) {
86 *outX = x;
87 *outY = y;
88 return;
89 }
90 if (plane == "xz") {
91 *outX = x;
92 *outY = z;
93 return;
94 }
95 if (plane == "yz") {
96 *outX = y;
97 *outY = z;
98 return;
99 }
100 throw Exception("AnimTrail: unknown plane '%s' (use xy|xz|yz)", plane.c_str());
101}
102
103void AnimTrail::sampleBone(const AnimPose *pose, int boneIndex, const std::string &plane) {
104 sampleBoneOffset(pose, boneIndex, 0.f, 0.f, 0.f, plane);
105}
106
107void AnimTrail::sampleBoneOffset(const AnimPose *pose, int boneIndex, float ox, float oy, float oz,
108 const std::string &plane) {
109 if (!pose) throw Exception("AnimTrail.sampleBone: pose is null");
110 if (boneIndex < 0 || boneIndex >= pose->getBoneCount()) {
111 throw Exception("AnimTrail.sampleBone: boneIndex %d out of range (count=%d)", boneIndex,
112 pose->getBoneCount());
113 }
114 const float wx = pose->getWorldPositionX(boneIndex) + ox;
115 const float wy = pose->getWorldPositionY(boneIndex) + oy;
116 const float wz = pose->getWorldPositionZ(boneIndex) + oz;
117 float px = 0.f, py = 0.f;
118 projectPlane(wx, wy, wz, plane, &px, &py);
119 pushPoint(px, py, plane == "xy" || plane.empty() ? wz : (plane == "xz" ? wy : wx));
120}
121
122void AnimTrail::pushPoint(float x, float y, float z) {
123 if (!points_.empty() && minDistance_ > 0.f) {
124 const Point &last = points_.back();
125 const float dx = x - last.x;
126 const float dy = y - last.y;
127 const float dz = z - last.z;
128 if (dx * dx + dy * dy + dz * dz < minDistance_ * minDistance_) return;
129 }
130 Point p;
131 p.x = x;
132 p.y = y;
133 p.z = z;
134 p.age = 0.f;
135 points_.push_back(p);
136 while (static_cast<int>(points_.size()) > capacity_) {
137 points_.erase(points_.begin());
138 }
139}
140
141void AnimTrail::clear() { points_.clear(); }
142
143void AnimTrail::updateUnchecked(float dt) {
144 if (dt < 0.f) dt = 0.f;
145 for (Point &p : points_) p.age += dt;
146 if (duration_ > 0.f) {
147 auto it = points_.begin();
148 while (it != points_.end()) {
149 if (it->age > duration_) {
150 it = points_.erase(it);
151 } else {
152 ++it;
153 }
154 }
155 }
156}
157
159 auto seconds = detail::secondsForStep(step, hasLastTick_, lastTick_, "AnimTrail");
160 if (!seconds) return eve::Result<void>::failure(seconds.status());
161 updateUnchecked(std::move(seconds).takeValue());
162 lastTick_ = step.tick;
163 hasLastTick_ = true;
165}
166
167void AnimTrail::update(float dt) {
168 auto step = detail::legacyStep(dt, hasLastTick_, lastTick_, "AnimTrail");
169 if (!step) {
170 step.ignore("legacy AnimTrail update");
171 return;
172 }
173 advance(std::move(step).takeValue()).ignore("legacy AnimTrail update");
174}
175
176void AnimTrail::requireIndex(int index) const {
177 if (index < 0 || index >= getPointCount()) {
178 throw Exception("AnimTrail: point index %d out of range (count=%d)", index, getPointCount());
179 }
180}
181
182float AnimTrail::getPointX(int index) const {
183 requireIndex(index);
184 return points_[static_cast<size_t>(index)].x;
185}
186
187float AnimTrail::getPointY(int index) const {
188 requireIndex(index);
189 return points_[static_cast<size_t>(index)].y;
190}
191
192float AnimTrail::getPointZ(int index) const {
193 requireIndex(index);
194 return points_[static_cast<size_t>(index)].z;
195}
196
198 requireIndex(index);
199 return points_[static_cast<size_t>(index)].age;
200}
201
202float AnimTrail::alphaFor(const Point &p) const {
203 if (!fade_ || duration_ <= 0.f) return colorA_;
204 const float t = 1.f - std::min(1.f, p.age / duration_);
205 return colorA_ * t;
206}
207
209 requireIndex(index);
210 return alphaFor(points_[static_cast<size_t>(index)]);
211}
212
213void AnimTrail::toScreen(float x, float y, float *sx, float *sy) const {
214 if (!sx || !sy) return;
215 *sx = x * drawScaleX_ + drawOffsetX_;
216 *sy = y * drawScaleY_ + drawOffsetY_;
217}
218
219void AnimTrail::drawDot(graphics::Graphics *gfx, float x, float y, float alpha) const {
220 if (!gfx || alpha <= 0.f) return;
221 float sx = 0.f, sy = 0.f;
222 toScreen(x, y, &sx, &sy);
223 const float half = width_ * 0.5f;
224 gfx->drawSolidRect(sx - half, sy - half, width_, width_,
225 Color(colorR_, colorG_, colorB_, alpha));
226}
227
228void AnimTrail::drawSegment(graphics::Graphics *gfx, float x0, float y0, float x1, float y1,
229 float a0, float a1) const {
230 if (!gfx) return;
231 float sx0 = 0.f, sy0 = 0.f, sx1 = 0.f, sy1 = 0.f;
232 toScreen(x0, y0, &sx0, &sy0);
233 toScreen(x1, y1, &sx1, &sy1);
234 const float dx = sx1 - sx0;
235 const float dy = sy1 - sy0;
236 const float len = std::sqrt(dx * dx + dy * dy);
237 if (len < 1e-4f) {
238 drawDot(gfx, x1, y1, a1);
239 return;
240 }
241 const float step = std::max(1.f, width_ * 0.75f);
242 const int steps = std::max(1, int(len / step));
243 const float half = width_ * 0.5f;
244 for (int i = 0; i <= steps; ++i) {
245 const float t = float(i) / float(steps);
246 const float a = a0 + (a1 - a0) * t;
247 if (a <= 0.f) continue;
248 const float px = sx0 + dx * t;
249 const float py = sy0 + dy * t;
250 gfx->drawSolidRect(px - half, py - half, width_, width_,
251 Color(colorR_, colorG_, colorB_, a));
252 }
253}
254
256 if (!gfx || points_.empty()) return;
257
258 if (style_ == Style::Points) {
259 for (const Point &p : points_) {
260 drawDot(gfx, p.x, p.y, alphaFor(p));
261 }
262 return;
263 }
264
265 // Line: connect oldest → newest with per-vertex fade.
266 for (size_t i = 1; i < points_.size(); ++i) {
267 const Point &a = points_[i - 1];
268 const Point &b = points_[i];
269 drawSegment(gfx, a.x, a.y, b.x, b.y, alphaFor(a), alphaFor(b));
270 }
271 // Emphasize the head.
272 if (!points_.empty()) {
273 const Point &head = points_.back();
274 drawDot(gfx, head.x, head.y, alphaFor(head));
275 }
276}
277
278} // namespace eve::animation
float y
Definition AnimClip.cpp:738
float x
Definition AnimClip.cpp:738
float z
Definition AnimClip.cpp:738
eve::EntitySpatialPose pose
float py
glm::vec4 p[6]
tensor::Graph g
Definition GpuGraph.cpp:7
std::uint32_t capacity
double r
std::vector< Colorf > px
MeleePoint3 b
Definition MeleeHit.cpp:41
MeleePoint3 a
Definition MeleeHit.cpp:40
float distance
int steps
float t
uint8_t * pixels
float dz
float dy
float dx
float step
Definition TreeMesh.cpp:314
uint32_t index
double oy
double ox
float wz
float wx
float wy
EVENGINE_API_FOUNDATION public API.
Definition Exception.h:13
void ignore(std::string_view reason={}) const noexcept
Explicitly discard this result after documenting the reason.
Definition Result.h:537
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
std::string getStyle() const
Returns the style.
Definition AnimTrail.cpp:64
void setDuration(float seconds)
How long each sample lives (seconds). <= 0 keeps until capacity eviction.
Definition AnimTrail.cpp:29
void setCapacity(int capacity)
Max retained samples (ring). Clamped to >= 2.
Definition AnimTrail.cpp:21
void setWidth(float pixels)
Sets the width.
Definition AnimTrail.cpp:38
void update(float dt)
Legacy seconds facade; explicitly forwards to advance().
void addPoint3(float x, float y, float z)
Append a 3D sample (draw uses set plane / first two mapped axes via sampleBone).
Definition AnimTrail.cpp:80
void setDrawOffset(float ox, float oy)
Sets the draw offset.
Definition AnimTrail.cpp:73
int getPointCount() const
Returns the point count.
Definition AnimTrail.h:125
void setMinDistance(float distance)
Skip new samples closer than this distance to the newest point (0 = always add).
Definition AnimTrail.cpp:33
void draw(graphics::Graphics *gfx)
Draw trajectory in 2D pixel/world space via Graphics.
void setColor(float r, float g, float b, float a=1.f)
Head (newest) color; alpha fades toward 0 along the trail when fade is on.
Definition AnimTrail.cpp:43
float getPointZ(int index) const
Returns the point z.
void sampleBone(const AnimPose *pose, int boneIndex, const std::string &plane="xy")
Sample bone world position after pose->computeWorld. plane maps axes to draw (x,y): "xy" | "xz" | "yz...
eve::Result< void > advance(const eve::SimulationStep &step)
Age samples by one scheduler-owned deterministic step.
void setStyle(const std::string &style)
"line" | "points". Invalid → exception.
Definition AnimTrail.cpp:52
void setFade(bool enable)
Sets the fade.
Definition AnimTrail.cpp:50
float getPointAlpha(int index) const
Effective draw alpha in [0, colorA] after fade.
float getPointX(int index) const
Index 0 = oldest retained sample; count-1 = newest.
void setDrawScale(float sx, float sy)
Applied at draw time: screen = (x,y) * scale + offset. Useful when sampling bone world units into pix...
Definition AnimTrail.cpp:68
float getPointY(int index) const
Returns the point y.
float getPointAge(int index) const
Returns the point age.
void sampleBoneOffset(const AnimPose *pose, int boneIndex, float ox, float oy, float oz, const std::string &plane="xy")
Sample bone offset.
void addPoint(float x, float y)
Append a 2D sample (z stored as 0).
Definition AnimTrail.cpp:78
AnimTrail(int capacity=64)
Anim trail.
Definition AnimTrail.cpp:17
virtual void drawSolidRect(float x, float y, float w, float h, float r, float g, float b, float a=1.f)
RGBA-float overload matching the script-facing drawSolidRect name.
eve::Result< eve::SimulationStep > legacyStep(float seconds, bool hasLastTick, eve::SimulationTick lastTick, const char *owner)
Convert a legacy seconds call to the next local scheduler step.
eve::Result< float > secondsForStep(const eve::SimulationStep &step, bool hasLastTick, eve::SimulationTick lastTick, const char *owner)
Validate a scheduler step before an animation object mutates state.
eve::Color Color
RGBA color used by every graphics draw call. Lives inside eve::graphics so including a graphics heade...
Definition Color.h:13
glm::vec4 Color
Render-neutral RGBA color shared by graphics-facing modules.
Definition RenderTypes.h:8
One deterministic fixed-step emitted by SimulationClock.
Definition Time.h:158