1 /*
2  * Copyright (c) 2021-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 #ifndef RENDER_SERVICE_CLIENT_CORE_COMMON_RS_VECTOR4_H
17 #define RENDER_SERVICE_CLIENT_CORE_COMMON_RS_VECTOR4_H
18 
19 #include <algorithm>
20 #include <cmath>
21 
22 #include "common/rs_common_def.h"
23 
24 namespace OHOS {
25 namespace Rosen {
26 template<typename T>
27 class Vector4 {
28 public:
29     static constexpr uint32_t V4SIZE = 4;
30     union {
31         struct {
32             T x_;
33             T y_;
34             T z_;
35             T w_;
36         };
37         T data_[4];
38     };
39 
40     Vector4();
41     Vector4(T value);
42     Vector4(const Vector4<T>& value);
43     Vector4(T x, T y, T z, T w);
44     explicit Vector4(const T* array);
45     ~Vector4();
46 
47     Vector4 Normalized() const;
48     T Dot(const Vector4<T>& other) const;
49     T GetSqrLength() const;
50     T GetLength() const;
51     T Normalize();
52     void Identity();
53     bool IsInfinite() const;
54     bool IsIdentity() const;
55     bool IsZero() const;
56     void SetValues(T x, T y, T z, T w);
57     void SetZero();
58     uint32_t Size();
59     Vector4 operator-() const;
60     Vector4 operator-(const Vector4<T>& other) const;
61     Vector4 operator+(const Vector4<T>& other) const;
62     Vector4 operator/(float scale) const;
63     Vector4 operator*(float scale) const;
64     Vector4 operator*(const Vector4<T>& other) const;
65     Vector4& operator*=(const Vector4<T>& other);
66     Vector4& operator=(const Vector4<T>& other);
67     bool operator==(const Vector4& other) const;
68     bool operator!=(const Vector4& other) const;
69     bool IsNearEqual(const Vector4& other, T threshold = std::numeric_limits<T>::epsilon()) const;
70 
71     T operator[](int index) const;
72     T& operator[](int index);
73     T* GetData();
74 
75     void Scale(float arg);
76     void Sub(const Vector4<T>& arg);
77     void Add(const Vector4<T>& arg);
78     void Multiply(const Vector4<T>& arg);
79     void Div(const Vector4<T>& arg);
80     void Negate();
81     void Absolute();
82     static void Min(const Vector4<T>& a, const Vector4<T>& b, Vector4<T>& result);
83     static void Max(const Vector4<T>& a, const Vector4<T>& b, Vector4<T>& result);
84     static void Mix(const Vector4<T>& min, const Vector4<T>& max, T a, Vector4<T>& result);
85 };
86 
87 typedef Vector4<float> Vector4f;
88 typedef Vector4<double> Vector4d;
89 
90 class Quaternion : public Vector4f {
91 public:
Quaternion()92     Quaternion()
93     {
94         Identity();
95     }
Quaternion(float x,float y,float z,float w)96     Quaternion(float x, float y, float z, float w) : Vector4f(x, y, z, w) {}
Quaternion(const Vector4f & other)97     Quaternion(const Vector4f& other) : Vector4f(other) {}
Quaternion(const Vector4f && other)98     Quaternion(const Vector4f&& other) : Vector4f(other) {}
99     Quaternion Slerp(const Quaternion& to, float t);
100     Quaternion Flip() const;
101 };
102 
103 template<typename T>
Vector4()104 Vector4<T>::Vector4()
105 {
106     SetZero();
107 }
108 
109 template<typename T>
Vector4(T value)110 Vector4<T>::Vector4(T value)
111 {
112     data_[0] = value;
113     data_[1] = value;
114     data_[2] = value;
115     data_[3] = value;
116 }
117 
118 template<typename T>
Vector4(const Vector4<T> & value)119 Vector4<T>::Vector4(const Vector4<T>& value)
120 {
121     for (uint32_t i = 0; i < Size(); i++) {
122         data_[i] = value[i];
123     }
124 }
125 
126 template<typename T>
Vector4(T x,T y,T z,T w)127 Vector4<T>::Vector4(T x, T y, T z, T w)
128 {
129     data_[0] = x;
130     data_[1] = y;
131     data_[2] = z;
132     data_[3] = w;
133 }
134 
135 template<typename T>
Vector4(const T * array)136 Vector4<T>::Vector4(const T* array)
137 {
138     std::copy_n(array, std::size(data_), data_);
139 }
140 
141 template<typename T>
~Vector4()142 Vector4<T>::~Vector4()
143 {}
144 
Flip()145 inline Quaternion Quaternion::Flip() const
146 {
147     return { -data_[0], -data_[1], -data_[2], -data_[3] };
148 }
149 
Slerp(const Quaternion & to,float t)150 inline Quaternion Quaternion::Slerp(const Quaternion& to, float t)
151 {
152     constexpr double SLERP_EPSILON = 1e-5;
153     if (t < 0.0 || t > 1.0) {
154         return *this;
155     }
156 
157     auto from = *this;
158 
159     double cosHalfAngle = from.x_ * to.x_ + from.y_ * to.y_ + from.z_ * to.z_ + from.w_ * to.w_;
160     if (cosHalfAngle < 0.0) {
161         // Since the half angle is > 90 degrees, the full rotation angle would
162         // exceed 180 degrees. The quaternions (x, y, z, w) and (-x, -y, -z, -w)
163         // represent the same rotation. Flipping the orientation of either
164         // quaternion ensures that the half angle is less than 90 and that we are
165         // taking the shortest path.
166         from = from.Flip();
167         cosHalfAngle = -cosHalfAngle;
168     }
169 
170     // Ensure that acos is well behaved at the boundary.
171     if (cosHalfAngle > 1.0) {
172         cosHalfAngle = 1.0;
173     }
174 
175     double sinHalfAngle = std::sqrt(1.0 - cosHalfAngle * cosHalfAngle);
176     if (sinHalfAngle < SLERP_EPSILON) {
177         // Quaternions share common axis and angle.
178         return *this;
179     }
180 
181     double half_angle = std::acos(cosHalfAngle);
182 
183     float scaleA = std::sin((1.0 - t) * half_angle) / sinHalfAngle;
184     float scaleB = std::sin(t * half_angle) / sinHalfAngle;
185 
186     return (from * scaleA) + (to * scaleB);
187 }
188 
189 template<typename T>
Normalized()190 Vector4<T> Vector4<T>::Normalized() const
191 {
192     Vector4<T> rNormalize(*this);
193     rNormalize.Normalize();
194     return rNormalize;
195 }
196 
197 template<typename T>
Dot(const Vector4<T> & other)198 T Vector4<T>::Dot(const Vector4<T>& other) const
199 {
200     const T* oData = other.data_;
201     T sum = data_[0] * oData[0];
202     sum += data_[1] * oData[1];
203     sum += data_[2] * oData[2];
204     sum += data_[3] * oData[3];
205     return sum;
206 }
207 
208 template<typename T>
GetSqrLength()209 T Vector4<T>::GetSqrLength() const
210 {
211     T sum = data_[0] * data_[0];
212     sum += data_[1] * data_[1];
213     sum += data_[2] * data_[2];
214     sum += data_[3] * data_[3];
215     return sum;
216 }
217 
218 template<typename T>
GetLength()219 T Vector4<T>::GetLength() const
220 {
221     return sqrt(GetSqrLength());
222 }
223 
224 template<typename T>
Normalize()225 T Vector4<T>::Normalize()
226 {
227     T l = GetLength();
228     if (ROSEN_EQ<T>(l, 0.0)) {
229         return (T)0.0;
230     }
231 
232     const T d = 1.0f / l;
233     data_[0] *= d;
234     data_[1] *= d;
235     data_[2] *= d;
236     data_[3] *= d;
237     return l;
238 }
239 
240 template<typename T>
Min(const Vector4<T> & a,const Vector4<T> & b,Vector4<T> & result)241 void Vector4<T>::Min(const Vector4<T>& a, const Vector4<T>& b, Vector4<T>& result)
242 {
243     T* resultData = result.data_;
244     const T* aData = a.data_;
245     const T* bData = b.data_;
246     resultData[3] = std::min(aData[3], bData[3]);
247     resultData[2] = std::min(aData[2], bData[2]);
248     resultData[1] = std::min(aData[1], bData[1]);
249     resultData[0] = std::min(aData[0], bData[0]);
250 }
251 
252 template<typename T>
Max(const Vector4<T> & a,const Vector4<T> & b,Vector4<T> & result)253 void Vector4<T>::Max(const Vector4<T>& a, const Vector4<T>& b, Vector4<T>& result)
254 {
255     T* resultData = result.data_;
256     const T* aData = a.data_;
257     const T* bData = b.data_;
258     resultData[3] = std::max(aData[3], bData[3]);
259     resultData[2] = std::max(aData[2], bData[2]);
260     resultData[1] = std::max(aData[1], bData[1]);
261     resultData[0] = std::max(aData[0], bData[0]);
262 }
263 
264 template<typename T>
Mix(const Vector4<T> & min,const Vector4<T> & max,T a,Vector4<T> & result)265 void Vector4<T>::Mix(const Vector4<T>& min, const Vector4<T>& max, T a, Vector4<T>& result)
266 {
267     T* resultData = result.data_;
268     const T* minData = min.data_;
269     const T* maxData = max.data_;
270     resultData[3] = minData[3] + a * (maxData[3] - minData[3]);
271     resultData[2] = minData[2] + a * (maxData[2] - minData[2]);
272     resultData[1] = minData[1] + a * (maxData[1] - minData[1]);
273     resultData[0] = minData[0] + a * (maxData[0] - minData[0]);
274 }
275 
276 template<typename T>
GetData()277 inline T* Vector4<T>::GetData()
278 {
279     return data_;
280 }
281 
282 template<typename T>
Identity()283 void Vector4<T>::Identity()
284 {
285     SetValues(0.f, 0.f, 0.f, 1.f);
286 }
287 
288 template<typename T>
IsIdentity()289 bool Vector4<T>::IsIdentity() const
290 {
291     return operator==(Vector4<T>(0.f, 0.f, 0.f, 1.f));
292 }
293 
294 template<typename T>
IsZero()295 bool Vector4<T>::IsZero() const
296 {
297     return ROSEN_EQ<T>(data_[0], 0.f) && ROSEN_EQ<T>(data_[1], 0.f) &&
298            ROSEN_EQ<T>(data_[2], 0.f) && ROSEN_EQ<T>(data_[3], 0.f);
299 }
300 
301 template<typename T>
SetValues(T x,T y,T z,T w)302 void Vector4<T>::SetValues(T x, T y, T z, T w)
303 {
304     data_[0] = x;
305     data_[1] = y;
306     data_[2] = z;
307     data_[3] = w;
308 }
309 
310 template<typename T>
SetZero()311 void Vector4<T>::SetZero()
312 {
313     SetValues(T(0.f), T(0.f), T(0.f), T(0.f));
314 }
315 
316 template<typename T>
Size()317 uint32_t Vector4<T>::Size()
318 {
319     return V4SIZE;
320 }
321 
322 template<typename T>
323 Vector4<T> Vector4<T>::operator-(const Vector4<T>& other) const
324 {
325     const T* otherData = other.data_;
326 
327     return Vector4<T>(
328         data_[0] - otherData[0], data_[1] - otherData[1], data_[2] - otherData[2], data_[3] - otherData[3]);
329 }
330 
331 template<typename T>
332 Vector4<T> Vector4<T>::operator+(const Vector4<T>& other) const
333 {
334     const T* thisData = data_;
335     const T* otherData = other.data_;
336 
337     return Vector4<T>(
338         thisData[0] + otherData[0], thisData[1] + otherData[1], thisData[2] + otherData[2], thisData[3] + otherData[3]);
339 }
340 
341 template<typename T>
342 Vector4<T> Vector4<T>::operator/(float scale) const
343 {
344     if (ROSEN_EQ<float>(scale, 0)) {
345         return *this;
346     }
347     Vector4<T> clone(data_);
348     clone.Scale(1.0f / scale);
349     return clone;
350 }
351 
352 template<typename T>
353 Vector4<T> Vector4<T>::operator*(float scale) const
354 {
355     Vector4<T> clone(data_);
356     clone.Scale(scale);
357     return clone;
358 }
359 
360 template<typename T>
361 Vector4<T> Vector4<T>::operator*(const Vector4<T>& other) const
362 {
363     Vector4<T> rMult(data_);
364     return rMult *= other;
365 }
366 
367 template<typename T>
368 Vector4<T>& Vector4<T>::operator*=(const Vector4<T>& other)
369 {
370     const T* oData = other.data_;
371     data_[0] *= oData[0];
372     data_[1] *= oData[1];
373     data_[2] *= oData[2];
374     data_[3] *= oData[3];
375     return *this;
376 }
377 
378 template<typename T>
379 Vector4<T>& Vector4<T>::operator=(const Vector4<T>& other)
380 {
381     const T* oData = other.data_;
382     data_[0] = oData[0];
383     data_[1] = oData[1];
384     data_[2] = oData[2];
385     data_[3] = oData[3];
386     return *this;
387 }
388 
389 template<typename T>
390 inline bool Vector4<T>::operator==(const Vector4& other) const
391 {
392     const T* oData = other.data_;
393 
394     return (ROSEN_EQ<T>(data_[0], oData[0])) && (ROSEN_EQ<T>(data_[1], oData[1])) &&
395            (ROSEN_EQ<T>(data_[2], oData[2])) && (ROSEN_EQ<T>(data_[3], oData[3]));
396 }
397 
398 template<typename T>
399 inline bool Vector4<T>::operator!=(const Vector4& other) const
400 {
401     return !operator==(other);
402 }
403 
404 template<typename T>
IsNearEqual(const Vector4 & other,T threshold)405 bool Vector4<T>::IsNearEqual(const Vector4& other, T threshold) const
406 {
407     const T* value = other.data_;
408 
409     return (ROSEN_EQ<T>(data_[0], value[0], threshold)) && (ROSEN_EQ<T>(data_[1], value[1], threshold)) &&
410            (ROSEN_EQ<T>(data_[2], value[2], threshold)) && (ROSEN_EQ<T>(data_[3], value[3], threshold));
411 }
412 
413 template<typename T>
414 Vector4<T> Vector4<T>::operator-() const
415 {
416     return Vector4<T>(-data_[0], -data_[1], -data_[2], -data_[3]);
417 }
418 
419 template<typename T>
420 T Vector4<T>::operator[](int index) const
421 {
422     return data_[index];
423 }
424 
425 template<typename T>
426 T& Vector4<T>::operator[](int index)
427 {
428     return data_[index];
429 }
430 
431 template<typename T>
Scale(float arg)432 void Vector4<T>::Scale(float arg)
433 {
434     data_[3] *= arg;
435     data_[2] *= arg;
436     data_[1] *= arg;
437     data_[0] *= arg;
438 }
439 
440 template<typename T>
Sub(const Vector4<T> & arg)441 void Vector4<T>::Sub(const Vector4<T>& arg)
442 {
443     const T* argData = arg.data_;
444     data_[3] -= argData[3];
445     data_[2] -= argData[2];
446     data_[1] -= argData[1];
447     data_[0] -= argData[0];
448 }
449 
450 template<typename T>
Add(const Vector4<T> & arg)451 void Vector4<T>::Add(const Vector4<T>& arg)
452 {
453     const T* argData = arg.data_;
454     data_[3] += argData[3];
455     data_[2] += argData[2];
456     data_[1] += argData[1];
457     data_[0] += argData[0];
458 }
459 
460 template<typename T>
Multiply(const Vector4<T> & arg)461 void Vector4<T>::Multiply(const Vector4<T>& arg)
462 {
463     const T* argData = arg.data_;
464     data_[3] *= argData[3];
465     data_[2] *= argData[2];
466     data_[1] *= argData[1];
467     data_[0] *= argData[0];
468 }
469 
470 template<typename T>
Div(const Vector4<T> & arg)471 void Vector4<T>::Div(const Vector4<T>& arg)
472 {
473     const T* argData = arg.data_;
474     data_[3] /= argData[3];
475     data_[2] /= argData[2];
476     data_[1] /= argData[1];
477     data_[0] /= argData[0];
478 }
479 
480 template<typename T>
Negate()481 void Vector4<T>::Negate()
482 {
483     data_[3] = -data_[3];
484     data_[2] = -data_[2];
485     data_[1] = -data_[1];
486     data_[0] = -data_[0];
487 }
488 
489 template<typename T>
Absolute()490 void Vector4<T>::Absolute()
491 {
492     data_[3] = abs(data_[3]);
493     data_[2] = abs(data_[2]);
494     data_[1] = abs(data_[1]);
495     data_[0] = abs(data_[0]);
496 }
497 
498 template<typename T>
IsInfinite()499 bool Vector4<T>::IsInfinite() const
500 {
501     return std::isinf(data_[0]) || std::isinf(data_[1]) ||
502         std::isinf(data_[2]) || std::isinf(data_[3]);
503 }
504 } // namespace Rosen
505 } // namespace OHOS
506 #endif // RENDER_SERVICE_CLIENT_CORE_COMMON_RS_VECTOR4_H
507