载入中...
搜索中...
未找到
MeshEffect.cpp
浏览该文件的文档.
2
3#include "common/Exception.h"
5
6#include <algorithm>
7#include <cmath>
8#include <utility>
9
10namespace eve::stylize {
11
12MeshEffectInstance::MeshEffectInstance(std::string style, std::map<std::string, float> defaults)
13 : style_(std::move(style), std::move(defaults)) {}
14
15MeshEffectInstance::MeshEffectInstance(std::string style) : style_(std::move(style)) {
16 const StyleDefinition* definition = findStyleDefinition(style_.getStyle());
17 if (!definition || !definition->mesh)
18 throw eve::Exception("MeshEffectInstance: style '%s' has no mesh technique", style_.getStyle().c_str());
19}
20
22 if (target.isInvalid()) throw eve::Exception("MeshEffectInstance.bindTarget: invalid target handle");
23 target_ = target;
24}
25
27
28void MeshEffectInstance::validateDuration(float value, const char* name) {
29 if (!std::isfinite(value) || value < 0.f)
30 throw eve::Exception("MeshEffectInstance: %s must be finite and non-negative", name);
31}
32
34 validateDuration(playback.fadeIn, "fadeIn");
35 validateDuration(playback.duration, "duration");
36 validateDuration(playback.fadeOut, "fadeOut");
38 throw eve::Exception("MeshEffectInstance: a looping playback needs a positive cycle duration");
39 playback_ = playback;
40 if (state_ != MeshEffectState::Stopped && state_ != MeshEffectState::Finished) play();
41}
42
43void MeshEffectInstance::play() noexcept {
44 elapsed_ = 0.f;
45 stopElapsed_ = 0.f;
46 stopDuration_ = 0.f;
47 stopStartIntensity_ = 0.f;
48 updateTimelineState();
49}
50
51void MeshEffectInstance::stop(float fadeOutSeconds) {
52 validateDuration(fadeOutSeconds, "stop fadeOut");
53 if (state_ == MeshEffectState::Stopped || state_ == MeshEffectState::Finished) return;
54 if (fadeOutSeconds == 0.f) {
56 return;
57 }
58 stopStartIntensity_ = intensity();
59 stopElapsed_ = 0.f;
60 stopDuration_ = fadeOutSeconds;
62}
63
64void MeshEffectInstance::update(float dtSeconds) {
65 validateDuration(dtSeconds, "dt");
66 if (state_ == MeshEffectState::Stopped || state_ == MeshEffectState::Finished) return;
67 if (stopDuration_ > 0.f) {
68 stopElapsed_ += dtSeconds;
69 elapsed_ += dtSeconds;
70 if (stopElapsed_ >= stopDuration_) state_ = MeshEffectState::Finished;
71 } else {
72 elapsed_ += dtSeconds;
73 const float cycle = playback_.fadeIn + playback_.duration + playback_.fadeOut;
74 if (playback_.loop && cycle > 0.f)
75 elapsed_ = std::fmod(elapsed_, cycle);
76 else if (elapsed_ >= cycle) {
77 elapsed_ = cycle;
79 }
80 if (state_ != MeshEffectState::Finished) updateTimelineState();
81 }
82 if (style_.hasParam("time")) style_.setFloat("time", elapsed_);
83}
84
85void MeshEffectInstance::updateTimelineState() noexcept {
86 if (playback_.fadeIn > 0.f && elapsed_ < playback_.fadeIn) {
88 } else if (elapsed_ < playback_.fadeIn + playback_.duration) {
90 } else if (playback_.fadeOut > 0.f) {
92 } else {
94 }
95}
96
97float MeshEffectInstance::intensity() const noexcept {
98 if (state_ == MeshEffectState::Stopped || state_ == MeshEffectState::Finished) return 0.f;
99 if (stopDuration_ > 0.f)
100 return stopStartIntensity_ * std::clamp(1.f - stopElapsed_ / stopDuration_, 0.f, 1.f);
101 if (playback_.fadeIn > 0.f && elapsed_ < playback_.fadeIn)
102 return std::clamp(elapsed_ / playback_.fadeIn, 0.f, 1.f);
103 const float fadeOutStart = playback_.fadeIn + playback_.duration;
104 if (playback_.fadeOut > 0.f && elapsed_ >= fadeOutStart)
105 return std::clamp(1.f - (elapsed_ - fadeOutStart) / playback_.fadeOut, 0.f, 1.f);
106 return 1.f;
107}
108
110 if (style_.hasParam("time")) style_.setFloat("time", elapsed_);
111 return style_.newMeshShader(gfx);
112}
113
114} // namespace eve::stylize
LogicalId target
double value
std::string name
EVENGINE_API_FOUNDATION public API.
Definition Exception.h:13
constexpr bool isInvalid() const noexcept
Returns whether this value is the invalid sentinel.
static constexpr RuntimeHandle invalid() noexcept
Returns the canonical invalid handle.
Custom GPU program.
Definition Shader.h:39
void play() noexcept
Restart playback from time zero.
void unbindTarget() noexcept
Remove the observed target identity.
graphics::Shader * newMeshShader(graphics::Graphics *gfx)
Create a shader owned by gfx with current overrides and time.
void update(float dtSeconds)
Advance playback using caller-provided simulation time.
MeshEffectTargetHandle target() const noexcept
Return the observed target identity, possibly invalid.
Definition MeshEffect.h:55
void bindTarget(MeshEffectTargetHandle target)
Bind a process-local target identity without taking ownership.
void setPlayback(MeshEffectPlayback playback)
Replace timing after validating finite non-negative durations.
float intensity() const noexcept
Return the normalized lifecycle envelope in [0, 1].
void stop(float fadeOutSeconds=0.f)
Stop immediately or fade from the current envelope intensity.
MeshEffectPlayback playback() const noexcept
Return a value snapshot of the timing configuration.
Definition MeshEffect.h:62
MeshEffectInstance(std::string style)
Construct an unbound effect from a registered mesh style.
std::string getStyle() const
Returns the style.
graphics::Shader * newMeshShader(graphics::Graphics *gfx) const
Create a mesh technique shader and apply compatible overrides.
bool hasParam(const std::string &name) const
True when param.
void setFloat(const std::string &name, float value)
Sets the float.
const StyleDefinition * findStyleDefinition(const std::string &style)
Return a built-in definition, or nullptr when the id is unknown.
Deterministic timing configuration for one mesh effect playback.
Definition MeshEffect.h:24
Immutable capability metadata for one built-in stylization recipe.