• 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::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