• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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_spring_interpolator.h"
17 
18 #include <algorithm>
19 #include <cmath>
20 
21 #include "platform/common/rs_log.h"
22 
23 namespace OHOS {
24 namespace Rosen {
25 constexpr float MIN_DAMPING_RATIO = 0.0f;
26 constexpr float MAX_DAMPING_RATIO = 2.0f;
27 constexpr float MIN_DURATION = 0.02f;
28 constexpr float MAX_DURATION = 300.0f;
29 constexpr float SECONDS_TO_MICROSECONDS = 1e6f;
30 constexpr float MIN_RESPONSE = 1e-8;
31 constexpr float MIN_AMPLITUDE = 0.001f;
32 
RSSpringInterpolator(float response,float dampingRatio,float initialOffset,float minimumAmplitude,float initialVelocity,float duration)33 RSSpringInterpolator::RSSpringInterpolator(float response, float dampingRatio, float initialOffset,
34     float minimumAmplitude, float initialVelocity, float duration)
35     : response_(response), dampingRatio_(dampingRatio), initialVelocity_(initialVelocity),
36       initialOffset_(initialOffset), minimumAmplitude_(minimumAmplitude), duration_(duration)
37 {
38     CalculateSpringParameters();
39     ROSEN_LOGD("SAG, %s response = %.2f, dampingRatio = %.2f, initialVelocity "
40                "= %.2f, initialOffset = %.2f minimumAmplitude = %.5f, duration = %.2f",
41         __func__, response_, dampingRatio_, initialVelocity_, initialOffset_, minimumAmplitude_, duration_);
42 }
43 
Marshalling(Parcel & parcel) const44 bool RSSpringInterpolator::Marshalling(Parcel& parcel) const
45 {
46     if (!parcel.WriteUint16(InterpolatorType::SPRING)) {
47         ROSEN_LOGE("RSSpringInterpolator::Marshalling, Write type failed");
48         return false;
49     }
50     if (!(parcel.WriteFloat(response_) && parcel.WriteFloat(dampingRatio_) && parcel.WriteFloat(initialVelocity_) &&
51             parcel.WriteFloat(initialOffset_) && parcel.WriteFloat(minimumAmplitude_) &&
52             parcel.WriteFloat(duration_))) {
53         ROSEN_LOGE("RSSpringInterpolator::Marshalling, Write value failed");
54         return false;
55     }
56     return true;
57 }
58 
Unmarshalling(Parcel & parcel)59 RSSpringInterpolator* RSSpringInterpolator::Unmarshalling(Parcel& parcel)
60 {
61     float response, dampingRatio, initialVelocity, initialOffset, minimumAmplitude, duration;
62     if (!(parcel.ReadFloat(response) && parcel.ReadFloat(dampingRatio) && parcel.ReadFloat(initialVelocity) &&
63             parcel.ReadFloat(initialOffset) && parcel.ReadFloat(minimumAmplitude) && parcel.ReadFloat(duration))) {
64         ROSEN_LOGE("RSSpringInterpolator::Unmarshalling, SpringInterpolator failed");
65         return nullptr;
66     }
67     auto ret =
68         new RSSpringInterpolator(response, dampingRatio, initialOffset, minimumAmplitude, initialVelocity, duration);
69     return ret;
70 }
71 
InterpolateImpl(double seconds) const72 float RSSpringInterpolator::InterpolateImpl(double seconds) const
73 {
74     if (seconds <= 0) {
75         return 0;
76     } else if (seconds >= duration_) {
77         return initialOffset_;
78     }
79 
80     double displacement = CalculateDisplacement(seconds);
81     return initialOffset_ - displacement;
82 }
83 
CalculateDisplacement(double mappedTime) const84 double RSSpringInterpolator::CalculateDisplacement(double mappedTime) const
85 {
86     double coeffDecay = exp(coeffDecay_ * mappedTime);
87     if (dampingRatio_ < 1) {
88         // under-damped
89         double rad = dampedAngularVelocity_ * mappedTime;
90         double coeffPeriod = initialOffset_ * cos(rad) + coeffScale_ * sin(rad);
91         return coeffDecay * coeffPeriod;
92     } else if (dampingRatio_ == 1) {
93         // critical-damped
94         return coeffDecay * (initialOffset_ + coeffScale_ * mappedTime);
95     } else {
96         // over-damped
97         double coeffDecayMinus = exp(coeffDecayMinus_ * mappedTime);
98         return coeffDecay * coeffScale_ + coeffDecayMinus * coeffScaleMinus_;
99     }
100 }
101 
CalculateSpringParameters()102 void RSSpringInterpolator::CalculateSpringParameters()
103 {
104     // handle wrong parameters:
105     // 1. dampingRatio which not in [0, 2]
106     // 2. response/minimumAmplitude which <= 0
107     dampingRatio_ = std::clamp(dampingRatio_, MIN_DAMPING_RATIO, MAX_DAMPING_RATIO);
108     if (response_ <= 0) {
109         response_ = MIN_RESPONSE;
110     }
111 
112     float naturalAngularVelocity = 2 * M_PI / response_;
113     float initialVelocity = -initialVelocity_;
114     if (dampingRatio_ < 1) {
115         // Underdamped Systems
116         dampedAngularVelocity_ = naturalAngularVelocity * sqrt(1.0f - dampingRatio_ * dampingRatio_);
117         coeffDecay_ = -dampingRatio_ * naturalAngularVelocity;
118         coeffScale_ =
119             (initialVelocity + dampingRatio_ * naturalAngularVelocity * initialOffset_) / dampedAngularVelocity_;
120     } else if (dampingRatio_ == 1) {
121         // Critically-Damped Systems
122         coeffDecay_ = -naturalAngularVelocity;
123         coeffScale_ = initialVelocity + naturalAngularVelocity * initialOffset_;
124     } else {
125         // Overdamped Systems
126         float coeffTmp = sqrt(dampingRatio_ * dampingRatio_ - 1);
127         coeffDecay_ = (-dampingRatio_ + coeffTmp) * naturalAngularVelocity;
128         coeffScale_ = ((dampingRatio_ + coeffTmp) * naturalAngularVelocity * initialOffset_ + initialVelocity) /
129                       (2 * naturalAngularVelocity * coeffTmp);
130         coeffScaleMinus_ = (-(dampingRatio_ - coeffTmp) * naturalAngularVelocity * initialOffset_ - initialVelocity) /
131                            (2 * naturalAngularVelocity * coeffTmp);
132         coeffDecayMinus_ = (-dampingRatio_ - coeffTmp) * naturalAngularVelocity;
133     }
134 
135     if (duration_ <= 0) {
136         EstimateDuration();
137     }
138 }
139 
EstimateDuration()140 void RSSpringInterpolator::EstimateDuration()
141 {
142     if (minimumAmplitude_ <= 0) {
143         minimumAmplitude_ = MIN_AMPLITUDE;
144     }
145     if (dampingRatio_ < 1) {
146         // Underdamped Systems
147         if (coeffScale_ != 0) {
148             duration_ = log(abs(coeffScale_) / minimumAmplitude_) / -coeffDecay_;
149         }
150     } else if (dampingRatio_ == 1) {
151         // Critically-Damped Systems
152         if ((coeffScale_ + initialOffset_) != 0) {
153             duration_ = log(abs(coeffScale_ + initialOffset_) / minimumAmplitude_) / -coeffDecay_;
154         }
155     } else {
156         // Overdamped Systems
157         if (coeffScale_ != 0 && coeffScaleMinus_ != 0) {
158             duration_ = fmax(log(abs(coeffScale_) / minimumAmplitude_ * 2) / -coeffDecay_,
159                 log(abs(coeffScaleMinus_) / minimumAmplitude_ * 2) / -coeffDecayMinus_);
160         }
161     }
162     ROSEN_LOGD("SAG, %s estimated duration = %.5f, actual duration = %.5f", __func__, duration_,
163         std::clamp(duration_, MIN_DURATION, MAX_DURATION));
164     duration_ = std::clamp(duration_, MIN_DURATION, MAX_DURATION);
165 }
166 
UpdateParameters(float response,float dampingRatio,float initialVelocity,float initialOffset,float minimumAmplitude)167 void RSValueSpringInterpolator::UpdateParameters(
168     float response, float dampingRatio, float initialVelocity, float initialOffset, float minimumAmplitude)
169 {
170     if (response == response_ && dampingRatio == dampingRatio_ && initialVelocity == initialVelocity_ &&
171         initialOffset == initialOffset_ && isReversed_ == false) {
172         return;
173     }
174 
175     isReversed_ = false;
176     response_ = response;
177     dampingRatio_ = dampingRatio;
178     initialVelocity_ = initialVelocity;
179     initialOffset_ = initialOffset;
180     minimumAmplitude_ = minimumAmplitude;
181     duration_ = -1; // recalculate spring duration
182 
183     CalculateSpringParameters();
184 
185     ROSEN_LOGD("SAG, %s response = %.2f, dampingRatio = %.2f, initialOffset = %.2f, initialVelocity "
186                "= %.2f, minimumAmplitude = %.2f, duration = %.2f",
187         __func__, response_, dampingRatio_, initialOffset_, initialVelocity_, minimumAmplitude_, duration_);
188 }
189 
GetInstantaneousVelocity(int64_t microseconds) const190 float RSValueSpringInterpolator::GetInstantaneousVelocity(int64_t microseconds) const
191 {
192     if (microseconds <= 0) {
193         return initialVelocity_;
194     } else {
195         return (InterpolateValue(microseconds + 1) - InterpolateValue(microseconds)) * SECONDS_TO_MICROSECONDS;
196     }
197 }
198 
InterpolateValue(int64_t microseconds) const199 float RSValueSpringInterpolator::InterpolateValue(int64_t microseconds) const
200 {
201     if (isReversed_) {
202         return initialOffset_ - InterpolateImpl(duration_ - microseconds / SECONDS_TO_MICROSECONDS);
203     } else {
204         return InterpolateImpl(microseconds / SECONDS_TO_MICROSECONDS);
205     }
206 }
207 
GetEstimatedDuration() const208 int64_t RSValueSpringInterpolator::GetEstimatedDuration() const
209 {
210     return static_cast<int64_t>(duration_ * SECONDS_TO_MICROSECONDS);
211 }
212 
213 } // namespace Rosen
214 } // namespace OHOS
215