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