1 /*
2  * Copyright (c) 2024 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 #ifndef ROSEN_ENGINE_CORE_ANIMATION_RS_NOISE_FIELD_H
17 #define ROSEN_ENGINE_CORE_ANIMATION_RS_NOISE_FIELD_H
18 #include <algorithm>
19 #include <cmath>
20 #include <random>
21 
22 #include "rs_render_particle.h"
23 
24 namespace OHOS {
25 namespace Rosen {
26 class RSB_EXPORT ParticleNoiseField {
27 public:
28     int fieldStrength_ { 0 };
29     ShapeType fieldShape_;
30     Vector2f fieldSize_;
31     Vector2f fieldCenter_;
32     uint16_t fieldFeather_ { 0 };
33     float noiseScale_ { 0.0 };
34     float noiseFrequency_ { 0.0 };
35     float noiseAmplitude_ { 0.0 };
36 
ParticleNoiseField(const int fieldStrength,const ShapeType & fieldShape,const Vector2f & fieldSize,const Vector2f & fieldCenter,uint16_t fieldFeather,float noiseScale,float noiseFrequency,float noiseAmplitude)37     explicit ParticleNoiseField(const int fieldStrength, const ShapeType& fieldShape, const Vector2f& fieldSize,
38         const Vector2f& fieldCenter, uint16_t fieldFeather, float noiseScale, float noiseFrequency,
39         float noiseAmplitude)
40         : fieldStrength_(fieldStrength), fieldShape_(fieldShape), fieldSize_(fieldSize), fieldCenter_(fieldCenter),
41           fieldFeather_(fieldFeather), noiseScale_(noiseScale), noiseFrequency_(noiseFrequency),
42           noiseAmplitude_(noiseAmplitude)
43     {}
44     ParticleNoiseField(const ParticleNoiseField& config) = default;
45     ParticleNoiseField& operator=(const ParticleNoiseField& config) = default;
46     ~ParticleNoiseField() = default;
47     float CalculateFeatherEffect(float distanceToEdge, float featherWidth);
48     Vector2f ApplyField(const Vector2f& position, float deltaTime);
49     Vector2f ApplyCurlNoise(const Vector2f& position);
50 
51     bool operator==(const ParticleNoiseField& rhs) const
52     {
53         bool equal = (this->fieldStrength_ == rhs.fieldStrength_) && (this->fieldShape_ == rhs.fieldShape_) &&
54                      (this->fieldSize_ == rhs.fieldSize_) && (this->fieldCenter_ == rhs.fieldCenter_) &&
55                      (this->fieldFeather_ == rhs.fieldFeather_) && (this->noiseScale_ == rhs.noiseScale_) &&
56                      (this->noiseFrequency_ == rhs.noiseFrequency_) && (this->noiseAmplitude_ == rhs.noiseAmplitude_);
57         return equal;
58     }
59 
60 private:
61     bool IsPointInField(
62         const Vector2f& point, const ShapeType& fieldShape, const Vector2f& fieldCenter, float width, float height);
63     float CalculateDistanceToRectangleEdge(
64         const Vector2f& position, const Vector2f& direction, const Vector2f& center, const Vector2f& size);
65 };
66 
67 class RSB_EXPORT PerlinNoise2D {
68 private:
69     std::vector<int> p; // Permutation vector
70     float Fade(float t);
71     float Lerp(float t, float a, float b);
72     float Grad(int hash, float x, float y);
73     float noiseScale_ { 0.0 };
74     float noiseFrequency_ { 0.0 };
75     float noiseAmplitude_ { 0.0 };
76 
77 public:
78     PerlinNoise2D(float noiseScale, float noiseFrequency, float noiseAmplitude);
79     float Noise(float x, float y);
80     Vector2f Curl(float x, float y);
81 };
82 
83 class ParticleNoiseFields {
84 public:
85     std::vector<std::shared_ptr<ParticleNoiseField>> fields_;
86 
87     ParticleNoiseFields() = default;
88 
AddField(const std::shared_ptr<ParticleNoiseField> & field)89     void AddField(const std::shared_ptr<ParticleNoiseField>& field)
90     {
91         fields_.push_back(field);
92     }
93 
RemoveField(size_t index)94     void RemoveField(size_t index)
95     {
96         if (index < fields_.size()) {
97             fields_.erase(fields_.begin() + index);
98         }
99     }
100 
GetField(size_t index)101     std::shared_ptr<ParticleNoiseField> GetField(size_t index)
102     {
103         if (index < fields_.size()) {
104             return fields_[index];
105         }
106         return nullptr;
107     }
108 
GetFieldCount()109     size_t GetFieldCount() const
110     {
111         return fields_.size();
112     }
113 
ApplyAllFields(const Vector2f & position,float deltaTime)114     Vector2f ApplyAllFields(const Vector2f& position, float deltaTime)
115     {
116         Vector2f totalEffect = {0.0f, 0.0f};
117         for (auto& field : fields_) {
118             totalEffect += (field->ApplyField(position, deltaTime) + field->ApplyCurlNoise(position));
119         }
120         return totalEffect;
121     }
122 
ClearFields()123     void ClearFields()
124     {
125         fields_.clear();
126     }
127 
128     bool operator==(const ParticleNoiseFields& rhs) const
129     {
130         return fields_ == rhs.fields_;
131     }
132 
133     void Dump(std::string& out) const;
134 };
135 
136 } // namespace Rosen
137 } // namespace OHOS
138 
139 #endif // ROSEN_ENGINE_CORE_ANIMATION_RS_NOISE_FIELD_H
140