1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "animation/rs_render_particle_effector.h"
17
18 #include <cmath>
19 #include <iostream>
20 #include <random>
21 #ifdef ENABLE_RUST
22 #include "cxx.h"
23 #include "lib.rs.h"
24 #endif
25
26 #include "animation/rs_value_estimator.h"
27 namespace OHOS {
28 namespace Rosen {
29 constexpr float DEGREE_TO_RADIAN = M_PI / 180;
RSRenderParticleEffector(const std::vector<std::shared_ptr<RSRenderParticle>> activeParticles)30 RSRenderParticleEffector::RSRenderParticleEffector(const std::vector<std::shared_ptr<RSRenderParticle>> activeParticles)
31 {
32 activeParticles_ = activeParticles;
33 }
34
CalculateColorInt(const std::shared_ptr<RSRenderParticle> & particle,Vector4<int16_t> colorInt,Vector4<float> colorF,Vector4<float> colorSpeed,float deltaTime)35 Vector4<int16_t> RSRenderParticleEffector::CalculateColorInt(
36 const std::shared_ptr<RSRenderParticle>& particle, Vector4<int16_t> colorInt,
37 Vector4<float> colorF, Vector4<float> colorSpeed, float deltaTime)
38 {
39 for (int i = 0; i < 4; i ++) { // 4 is color tunnel count
40 if (!((colorInt.data_[i] <= 0 && colorSpeed.data_[i] <= 0.f)
41 || (colorInt.data_[i] >= UINT8_MAX && colorSpeed.data_[i] >= 0.f))) {
42 colorF.data_[i] += colorSpeed.data_[i] * deltaTime;
43 if (std::abs(colorF.data_[i]) >= 1.f) {
44 colorInt.data_[i] += static_cast<int16_t>(colorF.data_[i]);
45 colorF.data_[i] -= std::floor(colorF.data_[i]);
46 }
47 particle->SetRedF(colorF.data_[i]);
48 colorInt.data_[i] = std::clamp<int16_t>(colorInt.data_[i], 0, UINT8_MAX);
49 }
50 }
51 return colorInt;
52 }
53
UpdateCurveValue(const std::vector<std::shared_ptr<ChangeInOverLife<float>>> & valChangeOverLife,int64_t activeTime)54 float RSRenderParticleEffector::UpdateCurveValue(
55 const std::vector<std::shared_ptr<ChangeInOverLife<float>>>& valChangeOverLife, int64_t activeTime)
56 {
57 float value = 0.f;
58 for (size_t i = 0; i < valChangeOverLife.size(); i++) {
59 int startTime = valChangeOverLife[i]->startMillis_;
60 int endTime = valChangeOverLife[i]->endMillis_;
61 if (activeTime < startTime || activeTime > endTime) {
62 continue;
63 }
64 float startValue = valChangeOverLife[i]->fromValue_;
65 float endValue = valChangeOverLife[i]->toValue_;
66 #ifdef ENABLE_RUST
67 value = generate_value(startValue, endValue, startTime, endTime, activeTime);
68 #else
69 float t = 0.f;
70 if (endTime - startTime != 0) {
71 t = static_cast<float>(activeTime - startTime) / static_cast<float>(endTime - startTime);
72 auto interpolator = valChangeOverLife[i]->interpolator_;
73 t = (interpolator != nullptr) ? interpolator->Interpolate(t) : t;
74 value = startValue * (1.0f - t) + endValue * t;
75 } else {
76 value = startValue;
77 }
78 #endif
79 }
80 return value;
81 }
82
UpdateColorCurveValue(const std::vector<std::shared_ptr<ChangeInOverLife<Color>>> & valChangeOverLife,int64_t activeTime)83 Color RSRenderParticleEffector::UpdateColorCurveValue(
84 const std::vector<std::shared_ptr<ChangeInOverLife<Color>>>& valChangeOverLife, int64_t activeTime)
85 {
86 Color color;
87 for (size_t i = 0; i < valChangeOverLife.size(); i++) {
88 int startTime = valChangeOverLife[i]->startMillis_;
89 int endTime = valChangeOverLife[i]->endMillis_;
90 if (activeTime < startTime || activeTime > endTime) {
91 continue;
92 }
93 Color startValue = valChangeOverLife[i]->fromValue_;
94 Color endValue = valChangeOverLife[i]->toValue_;
95 float t = 0.f;
96 if (endTime - startTime != 0) {
97 t = static_cast<float>(activeTime - startTime) / static_cast<float>(endTime - startTime);
98 auto interpolator = valChangeOverLife[i]->interpolator_;
99 t = (interpolator != nullptr) ? interpolator->Interpolate(t) : t;
100 auto interpolationValue = startValue * (1.0f - t) + endValue * t;
101 color = interpolationValue;
102 } else {
103 color = startValue;
104 }
105 color = Color(color.AsArgbInt());
106 }
107 return color;
108 }
109
UpdateColor(float deltaTime)110 void RSRenderParticleEffector::UpdateColor(float deltaTime)
111 {
112 for (auto &particle : activeParticles_) {
113 if (particle == nullptr) {
114 return;
115 }
116 if (particle->GetParticleType() == ParticleType::IMAGES) {
117 return;
118 }
119 auto colorUpdator = particle->GetColorUpdator();
120 Color color = particle->GetColor();
121 if (colorUpdator == ParticleUpdator::RANDOM) {
122 auto colorInt = Vector4<int16_t>(color.GetRed(), color.GetGreen(), color.GetBlue(), color.GetAlpha());
123 auto colorSpeed = Vector4f(particle->GetRedSpeed(), particle->GetGreenSpeed(),
124 particle->GetBlueSpeed(), particle->GetAlphaSpeed());
125 auto colorF = Vector4f(particle->GetRedF(), particle->GetGreenF(),
126 particle->GetBlueF(), particle->GetAlphaF());
127 colorInt = CalculateColorInt(particle, colorInt, colorF, colorSpeed, deltaTime);
128 color.SetRed(colorInt.x_);
129 color.SetGreen(colorInt.y_);
130 color.SetBlue(colorInt.z_);
131 color.SetAlpha(colorInt.w_);
132 } else if (colorUpdator == ParticleUpdator::CURVE) {
133 int64_t activeTime = particle->GetActiveTime() / NS_PER_MS;
134 auto valChangeOverLife = particle->GetColorChangeOverLife();
135 color = UpdateColorCurveValue(valChangeOverLife, activeTime);
136 }
137 particle->SetColor(color);
138 }
139 }
140
UpdateOpacity(float deltaTime)141 void RSRenderParticleEffector::UpdateOpacity(float deltaTime)
142 {
143 for (auto &particle : activeParticles_) {
144 if (particle == nullptr) {
145 return;
146 }
147 auto opacityUpdator = particle->GetOpacityUpdator();
148 auto opacity = particle->GetOpacity();
149 if (opacityUpdator == ParticleUpdator::RANDOM) {
150 auto opacitySpeed = particle->GetOpacitySpeed();
151 if (opacity <= 0 && opacitySpeed <= 0) {
152 particle->SetIsDead();
153 return;
154 }
155 if (opacity >= 1.0 && opacitySpeed >= 0.f) {
156 return;
157 }
158 opacity += opacitySpeed * deltaTime;
159 opacity = std::clamp<float>(opacity, 0.f, 1.f);
160 } else if (opacityUpdator == ParticleUpdator::CURVE) {
161 int64_t activeTime = particle->GetActiveTime() / NS_PER_MS;
162 auto valChangeOverLife = particle->GetOpacityChangeOverLife();
163 opacity = UpdateCurveValue(valChangeOverLife, activeTime);
164 }
165 particle->SetOpacity(opacity);
166 }
167 }
168
UpdateScale(float deltaTime)169 void RSRenderParticleEffector::UpdateScale(float deltaTime)
170 {
171 for (auto &particle : activeParticles_) {
172 if (particle == nullptr) {
173 return;
174 }
175 auto scaleUpdator = particle->GetScaleUpdator();
176 auto scale = particle->GetScale();
177 if (scaleUpdator == ParticleUpdator::RANDOM) {
178 auto scaleSpeed = particle->GetScaleSpeed();
179 if (scale <= 0 && scaleSpeed <= 0) {
180 particle->SetIsDead();
181 return;
182 }
183 scale += scaleSpeed * deltaTime;
184 } else if (scaleUpdator == ParticleUpdator::CURVE) {
185 int64_t activeTime = particle->GetActiveTime() / NS_PER_MS;
186 auto valChangeOverLife = particle->GetScaleChangeOverLife();
187 scale = UpdateCurveValue(valChangeOverLife, activeTime);
188 }
189 particle->SetScale(scale);
190 }
191 }
192
UpdateSpin(float deltaTime)193 void RSRenderParticleEffector::UpdateSpin(float deltaTime)
194 {
195 for (auto &particle : activeParticles_) {
196 if (particle == nullptr) {
197 return;
198 }
199 auto spinUpdator = particle->GetSpinUpdator();
200 auto spin = particle->GetSpin();
201 if (spinUpdator == ParticleUpdator::RANDOM) {
202 auto spinSpeed = particle->GetSpinSpeed();
203 spin += spinSpeed * deltaTime;
204 } else if (spinUpdator == ParticleUpdator::CURVE) {
205 int64_t activeTime = particle->GetActiveTime() / NS_PER_MS;
206 auto valChangeOverLife = particle->GetSpinChangeOverLife();
207 spin = UpdateCurveValue(valChangeOverLife, activeTime);
208 }
209 particle->SetSpin(spin);
210 }
211 }
212
UpdateAccelerationAngle(float deltaTime)213 void RSRenderParticleEffector::UpdateAccelerationAngle(float deltaTime)
214 {
215 for (auto &particle : activeParticles_) {
216 if (particle == nullptr) {
217 return;
218 }
219 auto accelerationAngle = particle->GetAccelerationAngle();
220 auto acceAngleUpdator = particle->GetAccelerationAngleUpdator();
221 if (acceAngleUpdator == ParticleUpdator::RANDOM) {
222 float acceAngleSpeed = particle->GetAccelerationAngleSpeed();
223 accelerationAngle += acceAngleSpeed * deltaTime;
224 } else if (acceAngleUpdator == ParticleUpdator::CURVE) {
225 int64_t activeTime = particle->GetActiveTime() / NS_PER_MS;
226 auto valChangeOverLife = particle->GetAcceAngChangeOverLife();
227 accelerationAngle = UpdateCurveValue(valChangeOverLife, activeTime);
228 }
229 particle->SetAccelerationAngle(accelerationAngle);
230 }
231 }
232
UpdateAccelerationValue(float deltaTime)233 void RSRenderParticleEffector::UpdateAccelerationValue(float deltaTime)
234 {
235 for (auto &particle : activeParticles_) {
236 if (particle == nullptr) {
237 return;
238 }
239 auto accelerationValue = particle->GetAccelerationValue();
240 auto acceValueUpdator = particle->GetAccelerationValueUpdator();
241 if (acceValueUpdator == ParticleUpdator::RANDOM) {
242 float acceValueSpeed = particle->GetAccelerationValueSpeed();
243 accelerationValue += acceValueSpeed * deltaTime;
244 } else if (acceValueUpdator == ParticleUpdator::CURVE) {
245 int64_t activeTime = particle->GetActiveTime() / NS_PER_MS;
246 auto valChangeOverLife = particle->GetAcceValChangeOverLife();
247 accelerationValue = UpdateCurveValue(valChangeOverLife, activeTime);
248 }
249 particle->SetAccelerationValue(accelerationValue);
250 }
251 }
252
UpdatePosition(float deltaTime)253 void RSRenderParticleEffector::UpdatePosition(float deltaTime)
254 {
255 for (auto &particle : activeParticles_) {
256 if (particle == nullptr) {
257 return;
258 }
259 auto accelerationValue = particle->GetAccelerationValue();
260 auto accelerationAngle = particle->GetAccelerationAngle();
261 accelerationAngle *= DEGREE_TO_RADIAN;
262 auto acceleration = Vector2f { accelerationValue * std::cos(accelerationAngle),
263 accelerationValue * std::sin(accelerationAngle) };
264 particle->SetAcceleration(acceleration);
265
266 Vector2f velocity = particle->GetVelocity();
267 if (!(ROSEN_EQ(acceleration.x_, 0.f) && ROSEN_EQ(acceleration.y_, 0.f))) {
268 velocity.x_ += acceleration.x_ * deltaTime;
269 velocity.y_ += acceleration.y_ * deltaTime;
270 particle->SetVelocity(velocity);
271 }
272
273 Vector2f position = particle->GetPosition();
274 if (!(ROSEN_EQ(velocity.x_, 0.f) && ROSEN_EQ(velocity.y_, 0.f))) {
275 position.x_ += velocity.x_ * deltaTime;
276 position.y_ += velocity.y_ * deltaTime;
277 particle->SetPosition(position);
278 }
279 }
280 }
281
UpdateActiveTime(int64_t deltaTime)282 void RSRenderParticleEffector::UpdateActiveTime(int64_t deltaTime)
283 {
284 for (auto &particle : activeParticles_) {
285 if (particle != nullptr) {
286 int64_t activeTime = particle->GetActiveTime();
287 activeTime += deltaTime;
288 particle->SetActiveTime(activeTime);
289 }
290 }
291 }
292
293 // Apply effector to particle
ApplyEffectorToParticle(int64_t deltaTime)294 void RSRenderParticleEffector::ApplyEffectorToParticle(int64_t deltaTime)
295 {
296 float dt = static_cast<float>(deltaTime) / NS_TO_S;
297 UpdateAccelerationValue(dt);
298 UpdateAccelerationAngle(dt);
299 UpdateColor(dt);
300 UpdateOpacity(dt);
301 UpdateScale(dt);
302 UpdateSpin(dt);
303 UpdatePosition(dt);
304 UpdateActiveTime(deltaTime);
305 }
306
Update(const std::vector<std::shared_ptr<RSRenderParticle>> & activeParticles,int64_t deltaTime)307 void RSRenderParticleEffector::Update(
308 const std::vector<std::shared_ptr<RSRenderParticle>>& activeParticles, int64_t deltaTime)
309 {
310 activeParticles_ = activeParticles;
311 ApplyEffectorToParticle(deltaTime);
312 }
313
314 } // namespace Rosen
315 } // namespace OHOS
316