• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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