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