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::shared_ptr<ParticleRenderParams> particleParams)30 RSRenderParticleEffector::RSRenderParticleEffector(const std::shared_ptr<ParticleRenderParams> particleParams)
31 {
32 particleParams_ = particleParams;
33 }
34
CalculateRedInt(const std::shared_ptr<RSRenderParticle> & particle,int16_t redInt,float redF,float redSpeed,float deltaTime)35 int16_t RSRenderParticleEffector::CalculateRedInt(
36 const std::shared_ptr<RSRenderParticle>& particle, int16_t redInt, float redF, float redSpeed, float deltaTime)
37 {
38 if (!((redInt <= 0 && redSpeed <= 0.f) || (redInt >= UINT8_MAX && redSpeed >= 0.f))) {
39 redF += redSpeed * deltaTime;
40 if (std::abs(redF) >= 1.f) {
41 redInt += static_cast<int16_t>(redF);
42 redF -= std::floor(redF);
43 }
44 particle->SetRedF(redF);
45 redInt = std::clamp<int16_t>(redInt, 0, UINT8_MAX);
46 }
47 return redInt;
48 }
49
CalculateGreenInt(const std::shared_ptr<RSRenderParticle> & particle,int16_t greenInt,float greenF,float greenSpeed,float deltaTime)50 int16_t RSRenderParticleEffector::CalculateGreenInt(const std::shared_ptr<RSRenderParticle>& particle, int16_t greenInt,
51 float greenF, float greenSpeed, float deltaTime)
52 {
53 if (!((greenInt <= 0 && greenSpeed <= 0.f) || (greenInt >= UINT8_MAX && greenSpeed >= 0.f))) {
54 greenF += greenSpeed * deltaTime;
55 if (std::abs(greenF) >= 1.f) {
56 greenInt += static_cast<int16_t>(greenF);
57 greenF -= std::floor(greenF);
58 }
59 particle->SetGreenF(greenF);
60 greenInt = std::clamp<int16_t>(greenInt, 0, UINT8_MAX);
61 }
62 return greenInt;
63 }
64
CalculateBlueInt(const std::shared_ptr<RSRenderParticle> & particle,int16_t blueInt,float blueF,float blueSpeed,float deltaTime)65 int16_t RSRenderParticleEffector::CalculateBlueInt(
66 const std::shared_ptr<RSRenderParticle>& particle, int16_t blueInt, float blueF, float blueSpeed, float deltaTime)
67 {
68 if (!((blueInt <= 0 && blueSpeed <= 0.f) || (blueInt >= UINT8_MAX && blueSpeed >= 0.f))) {
69 blueF += blueSpeed * deltaTime;
70 if (std::abs(blueF) >= 1.f) {
71 blueInt += static_cast<int16_t>(blueF);
72 blueF -= std::floor(blueF);
73 }
74 particle->SetBlueF(blueF);
75 blueInt = std::clamp<int16_t>(blueInt, 0, UINT8_MAX);
76 }
77 return blueInt;
78 }
79
CalculateAlphaInt(const std::shared_ptr<RSRenderParticle> & particle,int16_t alphaInt,float alphaF,float alphaSpeed,float deltaTime)80 int16_t RSRenderParticleEffector::CalculateAlphaInt(const std::shared_ptr<RSRenderParticle>& particle, int16_t alphaInt,
81 float alphaF, float alphaSpeed, float deltaTime)
82 {
83 if (!((alphaInt <= 0 && alphaSpeed <= 0.f) || (alphaInt >= UINT8_MAX && alphaSpeed >= 0.f))) {
84 alphaF += alphaSpeed * deltaTime;
85 if (std::abs(alphaF) >= 1.f) {
86 alphaInt += static_cast<int16_t>(alphaF);
87 alphaF -= std::floor(alphaF);
88 }
89 particle->SetAlphaF(alphaF);
90 alphaInt = std::clamp<int16_t>(alphaInt, 0, UINT8_MAX);
91 }
92 return alphaInt;
93 }
94
UpdateColorRandom(const std::shared_ptr<RSRenderParticle> & particle,float deltaTime,Color color)95 Color RSRenderParticleEffector::UpdateColorRandom(
96 const std::shared_ptr<RSRenderParticle>& particle, float deltaTime, Color color)
97 {
98 int16_t redInt = color.GetRed();
99 int16_t greenInt = color.GetGreen();
100 int16_t blueInt = color.GetBlue();
101 int16_t alphaInt = color.GetAlpha();
102 float redSpeed = particle->GetRedSpeed();
103 float greenSpeed = particle->GetGreenSpeed();
104 float blueSpeed = particle->GetBlueSpeed();
105 float alphaSpeed = particle->GetAlphaSpeed();
106 float redF = particle->GetRedF();
107 float greenF = particle->GetGreenF();
108 float blueF = particle->GetBlueF();
109 float alphaF = particle->GetAlphaF();
110
111 redInt = CalculateRedInt(particle, redInt, redF, redSpeed, deltaTime);
112 greenInt = CalculateGreenInt(particle, greenInt, greenF, greenSpeed, deltaTime);
113 blueInt = CalculateBlueInt(particle, blueInt, blueF, blueSpeed, deltaTime);
114 alphaInt = CalculateAlphaInt(particle, alphaInt, alphaF, alphaSpeed, deltaTime);
115 color.SetRed(redInt);
116 color.SetGreen(greenInt);
117 color.SetBlue(blueInt);
118 color.SetAlpha(alphaInt);
119 return color;
120 }
121
UpdateColorCurve(int64_t activeTime,Color color)122 Color RSRenderParticleEffector::UpdateColorCurve(int64_t activeTime, Color color)
123 {
124 auto valChangeOverLife = particleParams_->color_.valChangeOverLife_;
125 for (size_t i = 0; i < valChangeOverLife.size(); i++) {
126 Color startValue = valChangeOverLife[i]->fromValue_;
127 Color endValue = valChangeOverLife[i]->toValue_;
128 int startTime = valChangeOverLife[i]->startMillis_;
129 int endTime = valChangeOverLife[i]->endMillis_;
130 auto interpolator = valChangeOverLife[i]->interpolator_;
131
132 if (activeTime >= startTime && activeTime < endTime) {
133 color = GenerateValue(startValue, endValue, startTime, endTime, activeTime, interpolator);
134 int16_t red = std::clamp<int16_t>(color.GetRed(), 0, UINT8_MAX);
135 int16_t green = std::clamp<int16_t>(color.GetGreen(), 0, UINT8_MAX);
136 int16_t blue = std::clamp<int16_t>(color.GetBlue(), 0, UINT8_MAX);
137 int16_t alpha = std::clamp<int16_t>(color.GetAlpha(), 0, UINT8_MAX);
138 color.SetRed(red);
139 color.SetGreen(green);
140 color.SetBlue(blue);
141 color.SetAlpha(alpha);
142 }
143 }
144 return color;
145 }
146
UpdateColor(const std::shared_ptr<RSRenderParticle> & particle,float deltaTime,int64_t activeTime)147 void RSRenderParticleEffector::UpdateColor(
148 const std::shared_ptr<RSRenderParticle>& particle, float deltaTime, int64_t activeTime)
149 {
150 auto colorUpdator = particleParams_->GetColorUpdator();
151 activeTime /= NS_PER_MS;
152 Color color = particle->GetColor();
153 if (colorUpdator == ParticleUpdator::RANDOM) {
154 color = UpdateColorRandom(particle, deltaTime, color);
155 } else if (colorUpdator == ParticleUpdator::CURVE) {
156 color = UpdateColorCurve(activeTime, color);
157 }
158 particle->SetColor(color);
159 }
160
UpdateOpacity(const std::shared_ptr<RSRenderParticle> & particle,float deltaTime,int64_t activeTime)161 void RSRenderParticleEffector::UpdateOpacity(
162 const std::shared_ptr<RSRenderParticle>& particle, float deltaTime, int64_t activeTime)
163 {
164 auto opacityUpdator = particleParams_->GetOpacityUpdator();
165 activeTime /= NS_PER_MS;
166 if (opacityUpdator == ParticleUpdator::RANDOM) {
167 auto opacity = particle->GetOpacity();
168 auto opacitySpeed = particle->GetOpacitySpeed();
169 if (opacity <= 0 && opacitySpeed <= 0) {
170 particle->SetIsDead();
171 return;
172 }
173 if (opacity >= 1.0 && opacitySpeed >= 0.f) {
174 return;
175 }
176 opacity += opacitySpeed * deltaTime;
177 opacity = std::clamp<float>(opacity, 0.f, 1.f);
178 particle->SetOpacity(opacity);
179 } else if (opacityUpdator == ParticleUpdator::CURVE) {
180 auto valChangeOverLife = particleParams_->opacity_.valChangeOverLife_;
181 for (size_t i = 0; i < valChangeOverLife.size(); i++) {
182 float startValue = valChangeOverLife[i]->fromValue_;
183 float endValue = valChangeOverLife[i]->toValue_;
184 int startTime = valChangeOverLife[i]->startMillis_;
185 int endTime = valChangeOverLife[i]->endMillis_;
186 auto interpolator = valChangeOverLife[i]->interpolator_;
187 if (activeTime >= startTime && activeTime < endTime) {
188 float value = 0.f;
189 if (!interpolator) {
190 value = GenerateValue(startValue, endValue, startTime, endTime, activeTime);
191 } else {
192 value = GenerateValue(startValue, endValue, startTime, endTime, activeTime, interpolator);
193 }
194 value = std::clamp<float>(value, 0.f, 1.f);
195 particle->SetOpacity(value);
196 }
197 }
198 }
199 }
200
UpdateScale(const std::shared_ptr<RSRenderParticle> & particle,float deltaTime,int64_t activeTime)201 void RSRenderParticleEffector::UpdateScale(
202 const std::shared_ptr<RSRenderParticle>& particle, float deltaTime, int64_t activeTime)
203 {
204 auto scaleUpdator = particleParams_->GetScaleUpdator();
205 activeTime /= NS_PER_MS;
206 if (scaleUpdator == ParticleUpdator::RANDOM) {
207 auto scale = particle->GetScale();
208 auto scaleSpeed = particle->GetScaleSpeed();
209 if (scale <= 0 && scaleSpeed <= 0) {
210 particle->SetIsDead();
211 return;
212 }
213 scale += scaleSpeed * deltaTime;
214 particle->SetScale(scale);
215 } else if (scaleUpdator == ParticleUpdator::CURVE) {
216 auto valChangeOverLife = particleParams_->scale_.valChangeOverLife_;
217 for (size_t i = 0; i < valChangeOverLife.size(); i++) {
218 float startValue = valChangeOverLife[i]->fromValue_;
219 float endValue = valChangeOverLife[i]->toValue_;
220 int startTime = valChangeOverLife[i]->startMillis_;
221 int endTime = valChangeOverLife[i]->endMillis_;
222 auto interpolator = valChangeOverLife[i]->interpolator_;
223 if (activeTime >= startTime && activeTime < endTime) {
224 float value = 0.f;
225 if (!interpolator) {
226 value = GenerateValue(startValue, endValue, startTime, endTime, activeTime);
227 } else {
228 value = GenerateValue(startValue, endValue, startTime, endTime, activeTime, interpolator);
229 }
230 particle->SetScale(value);
231 }
232 }
233 }
234 }
235
UpdateSpin(const std::shared_ptr<RSRenderParticle> & particle,float deltaTime,int64_t activeTime)236 void RSRenderParticleEffector::UpdateSpin(
237 const std::shared_ptr<RSRenderParticle>& particle, float deltaTime, int64_t activeTime)
238 {
239 auto spinUpdator = particleParams_->GetSpinUpdator();
240 activeTime /= NS_PER_MS;
241 if (spinUpdator == ParticleUpdator::RANDOM) {
242 auto spin = particle->GetSpin();
243 auto spinSpeed = particle->GetSpinSpeed();
244 spin += spinSpeed * deltaTime;
245 particle->SetSpin(spin);
246 } else if (spinUpdator == ParticleUpdator::CURVE) {
247 auto valChangeOverLife = particleParams_->spin_.valChangeOverLife_;
248 for (size_t i = 0; i < valChangeOverLife.size(); i++) {
249 float startValue = valChangeOverLife[i]->fromValue_;
250 float endValue = valChangeOverLife[i]->toValue_;
251 int startTime = valChangeOverLife[i]->startMillis_;
252 int endTime = valChangeOverLife[i]->endMillis_;
253 auto interpolator = valChangeOverLife[i]->interpolator_;
254 if (activeTime >= startTime && activeTime < endTime) {
255 float value = 0.f;
256 if (!interpolator) {
257 value = GenerateValue(startValue, endValue, startTime, endTime, activeTime);
258 } else {
259 value = GenerateValue(startValue, endValue, startTime, endTime, activeTime, interpolator);
260 }
261 particle->SetSpin(value);
262 }
263 }
264 }
265 }
266
UpdateAccelerationAngle(const std::shared_ptr<RSRenderParticle> & particle,float deltaTime,int64_t activeTime)267 void RSRenderParticleEffector::UpdateAccelerationAngle(
268 const std::shared_ptr<RSRenderParticle>& particle, float deltaTime, int64_t activeTime)
269 {
270 auto accelerationAngle = particle->GetAccelerationAngle();
271 auto acceAngleUpdator = particleParams_->GetAccelerationAngleUpdator();
272 float acceAngleChange = 0.f;
273 if (acceAngleUpdator == ParticleUpdator::RANDOM) {
274 float acceAngleSpeed = particle->GetAccelerationAngleSpeed();
275 acceAngleChange = acceAngleSpeed * deltaTime;
276 accelerationAngle += acceAngleChange;
277 } else if (acceAngleUpdator == ParticleUpdator::CURVE) {
278 auto valChangeOverLife = particleParams_->acceleration_.accelerationAngle_.valChangeOverLife_;
279 for (size_t i = 0; i < valChangeOverLife.size(); i++) {
280 float startValue = valChangeOverLife[i]->fromValue_;
281 float endValue = valChangeOverLife[i]->toValue_;
282 int startTime = valChangeOverLife[i]->startMillis_;
283 int endTime = valChangeOverLife[i]->endMillis_;
284 auto interpolator = valChangeOverLife[i]->interpolator_;
285 if (activeTime >= startTime && activeTime < endTime) {
286 accelerationAngle = (interpolator != nullptr)
287 ? GenerateValue(startValue, endValue, startTime, endTime, activeTime, interpolator)
288 : GenerateValue(startValue, endValue, startTime, endTime, activeTime);
289 }
290 }
291 }
292 particle->SetAccelerationAngle(accelerationAngle);
293 }
294
UpdateAccelerationValue(const std::shared_ptr<RSRenderParticle> & particle,float deltaTime,int64_t activeTime)295 void RSRenderParticleEffector::UpdateAccelerationValue(
296 const std::shared_ptr<RSRenderParticle>& particle, float deltaTime, int64_t activeTime)
297 {
298 auto accelerationValue = particle->GetAccelerationValue();
299 auto acceValueUpdator = particleParams_->GetAccelerationValueUpdator();
300 float acceValueChange = 0.f;
301 if (acceValueUpdator == ParticleUpdator::RANDOM) {
302 float acceValueSpeed = particle->GetAccelerationValueSpeed();
303 acceValueChange = acceValueSpeed * deltaTime;
304 accelerationValue += acceValueChange;
305 } else if (acceValueUpdator == ParticleUpdator::CURVE) {
306 auto valChangeOverLife = particleParams_->acceleration_.accelerationValue_.valChangeOverLife_;
307 for (size_t i = 0; i < valChangeOverLife.size(); i++) {
308 float startValue = valChangeOverLife[i]->fromValue_;
309 float endValue = valChangeOverLife[i]->toValue_;
310 int startTime = valChangeOverLife[i]->startMillis_;
311 int endTime = valChangeOverLife[i]->endMillis_;
312 auto interpolator = valChangeOverLife[i]->interpolator_;
313 if (activeTime >= startTime && activeTime < endTime) {
314 accelerationValue = (interpolator != nullptr)
315 ? GenerateValue(startValue, endValue, startTime, endTime, activeTime, interpolator)
316 : GenerateValue(startValue, endValue, startTime, endTime, activeTime);
317 }
318 }
319 }
320 particle->SetAccelerationValue(accelerationValue);
321 }
322
UpdateAccelerate(const std::shared_ptr<RSRenderParticle> & particle,float deltaTime,int64_t activeTime)323 void RSRenderParticleEffector::UpdateAccelerate(
324 const std::shared_ptr<RSRenderParticle>& particle, float deltaTime, int64_t activeTime)
325 {
326 activeTime /= NS_PER_MS;
327 auto acceValueUpdator = particleParams_->GetAccelerationValueUpdator();
328 auto acceAngleUpdator = particleParams_->GetAccelerationAngleUpdator();
329 UpdateAccelerationValue(particle, deltaTime, activeTime);
330 UpdateAccelerationAngle(particle, deltaTime, activeTime);
331 auto accelerationValue = particle->GetAccelerationValue();
332 auto accelerationAngle = particle->GetAccelerationAngle();
333 accelerationAngle *= DEGREE_TO_RADIAN;
334 if (acceValueUpdator == ParticleUpdator::RANDOM && acceAngleUpdator == ParticleUpdator::RANDOM) {
335 auto acceleration = particle->GetAcceleration();
336 acceleration = Vector2f { accelerationValue * std::cos(accelerationAngle),
337 accelerationValue * std::sin(accelerationAngle) };
338 particle->SetAcceleration(acceleration);
339 } else if (acceValueUpdator == ParticleUpdator::CURVE && acceAngleUpdator == ParticleUpdator::CURVE) {
340 particle->SetAcceleration(
341 { accelerationValue * std::cos(accelerationAngle), accelerationValue * std::sin(accelerationAngle) });
342 }
343 }
344
345 // Apply effector to particle
ApplyEffectorToParticle(const std::shared_ptr<RSRenderParticle> & particle,int64_t deltaTime)346 void RSRenderParticleEffector::ApplyEffectorToParticle(
347 const std::shared_ptr<RSRenderParticle>& particle, int64_t deltaTime)
348 {
349 int64_t activeTime = particle->GetActiveTime();
350 float dt = static_cast<float>(deltaTime) / NS_TO_S;
351 UpdateAccelerate(particle, dt, activeTime);
352 UpdateColor(particle, dt, activeTime);
353 UpdateOpacity(particle, dt, activeTime);
354 UpdateScale(particle, dt, activeTime);
355 UpdateSpin(particle, dt, activeTime);
356
357 auto acceleration = particle->GetAcceleration();
358 Vector2f velocity = particle->GetVelocity();
359 if (!(ROSEN_EQ(acceleration.x_, 0.f) && ROSEN_EQ(acceleration.y_, 0.f))) {
360 velocity.x_ += acceleration.x_ * dt;
361 velocity.y_ += acceleration.y_ * dt;
362 particle->SetVelocity(velocity);
363 }
364 Vector2f position = particle->GetPosition();
365 if (!(ROSEN_EQ(velocity.x_, 0.f) && ROSEN_EQ(velocity.y_, 0.f))) {
366 position.x_ += velocity.x_ * dt;
367 position.y_ += velocity.y_ * dt;
368 particle->SetPosition(position);
369 }
370 activeTime += deltaTime;
371 particle->SetActiveTime(activeTime);
372 }
373
374 template<typename T>
GenerateValue(T startValue,T endValue,int startTime,int endTime,int currentTime,std::shared_ptr<RSInterpolator> interpolator)375 T RSRenderParticleEffector::GenerateValue(
376 T startValue, T endValue, int startTime, int endTime, int currentTime, std::shared_ptr<RSInterpolator> interpolator)
377 {
378 float t = 0.f;
379 if (endTime - startTime != 0) {
380 t = static_cast<float>(currentTime - startTime) / static_cast<float>(endTime - startTime);
381 }
382 float fraction = interpolator->Interpolate(t);
383 auto interpolationValue = startValue * (1.0f - fraction) + endValue * fraction;
384 return interpolationValue;
385 }
386
GenerateValue(float startValue,float endValue,int startTime,int endTime,int currentTime)387 float RSRenderParticleEffector::GenerateValue(
388 float startValue, float endValue, int startTime, int endTime, int currentTime)
389 {
390 #ifdef ENABLE_RUST
391 return generate_value(startValue, endValue, startTime, endTime, currentTime);
392 #else
393 float t = 0.f;
394 if (endTime - startTime != 0) {
395 t = static_cast<float>(currentTime - startTime) / static_cast<float>(endTime - startTime);
396 }
397 auto interpolationValue = startValue * (1.0f - t) + endValue * t;
398 return interpolationValue;
399 #endif
400 }
401
402 } // namespace Rosen
403 } // namespace OHOS
404