Line data Source code
1 : /**
2 : Copyright 2013 BlackBerry Inc.
3 : Copyright (c) 2014-2015 Chukong Technologies
4 : Copyright (c) 2017-2022 Roman Katuntsev <sbkarr@stappler.org>
5 : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
6 :
7 : Licensed under the Apache License, Version 2.0 (the "License");
8 : you may not use this file except in compliance with the License.
9 : You may obtain a copy of the License at
10 :
11 : http://www.apache.org/licenses/LICENSE-2.0
12 :
13 : Unless required by applicable law or agreed to in writing, software
14 : distributed under the License is distributed on an "AS IS" BASIS,
15 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 : See the License for the specific language governing permissions and
17 : limitations under the License.
18 :
19 : Original file from GamePlay3D: http://gameplay3d.org
20 :
21 : This file was modified to fit the cocos2d-x project
22 : This file was modified for stappler project
23 : */
24 :
25 : #ifndef STAPPLER_GEOM_SPVEC4_H
26 : #define STAPPLER_GEOM_SPVEC4_H
27 :
28 : #include "SPSIMD.h"
29 : #include "SPVec2.h"
30 : #include "SPVec3.h"
31 :
32 : namespace STAPPLER_VERSIONIZED stappler::geom {
33 :
34 : class Mat4;
35 :
36 : class alignas(16) Vec4 {
37 : public:
38 : static constexpr size_t Dimansions = 2;
39 :
40 : static const Vec4 ZERO;
41 : static const Vec4 ONE;
42 : static const Vec4 UNIT_X;
43 : static const Vec4 UNIT_Y;
44 : static const Vec4 UNIT_Z;
45 : static const Vec4 UNIT_W;
46 :
47 : static void add(const Vec4& v1, const Vec4& v2, Vec4* dst) {
48 : simd::add(&v1.x, &v2.x, &dst->x);
49 : }
50 :
51 : static void subtract(const Vec4& v1, const Vec4& v2, Vec4* dst) {
52 : simd::sub(&v1.x, &v2.x, &dst->x);
53 : }
54 :
55 30692772 : static void scale(const Vec4& v1, const Vec4& v2, Vec4* dst) {
56 30692772 : simd::multiply(&v1.x, &v2.x, &dst->x);
57 30692772 : }
58 :
59 : static void unscale(const Vec4& v1, const Vec4& v2, Vec4* dst) {
60 : simd::divide(&v1.x, &v2.x, &dst->x);
61 : }
62 :
63 50 : static float dot(const Vec4& v1, const Vec4& v2) {
64 50 : return (v1.x * v2.x + v1.y * v2.y + v1.z * v2.z + v1.w * v2.w);
65 : }
66 :
67 : static float angle(const Vec4& v1, const Vec4& v2);
68 :
69 : static void clamp(const Vec4& v, const Vec4& min, const Vec4& max, Vec4* dst);
70 :
71 : template <typename Functor>
72 : static constexpr std::bitset<4> bitop(const Vec4& v, const Functor &f) {
73 : std::bitset<4> ret;
74 : ret.set(0, f(v.x));
75 : ret.set(1, f(v.y));
76 : ret.set(2, f(v.z));
77 : ret.set(3, f(v.w));
78 : return ret;
79 : }
80 :
81 : template <typename Functor>
82 : static constexpr std::bitset<4> bitop(const Vec4& v1, const Vec4& v2, const Functor &f) {
83 : std::bitset<4> ret;
84 : ret.set(0, f(v1.x, v2.x));
85 : ret.set(1, f(v1.y, v2.y));
86 : ret.set(2, f(v1.z, v2.z));
87 : ret.set(3, f(v1.w, v2.w));
88 : return ret;
89 : }
90 :
91 : static constexpr Vec4 fill(float v) {
92 : return Vec4(v, v, v, v);
93 : }
94 :
95 : float x;
96 : float y;
97 : float z;
98 : float w;
99 :
100 42001193 : constexpr Vec4() : x(0.0f), y(0.0f), z(0.0f), w(0.0f) { }
101 70121005 : constexpr Vec4(float xx, float yy, float zz, float ww) : x(xx), y(yy), z(zz), w(ww) { }
102 736692 : constexpr Vec4(const Vec2 &origin, float zz, float ww) : x(origin.x), y(origin.y), z(zz), w(ww) { }
103 20 : constexpr Vec4(const Vec3 &origin, float ww) : x(origin.x), y(origin.y), z(origin.z), w(ww) { }
104 2419 : constexpr Vec4(const Vec2 &origin, const Vec2 &extra) : x(origin.x), y(origin.y), z(extra.x), w(extra.y) { }
105 :
106 : constexpr Vec4(const Vec4 &p1, const Vec4 &p2) : x(p2.x - p1.x), y(p2.y - p1.y), z(p2.z - p1.z), w(p2.w - p1.w) { }
107 : constexpr Vec4(const Vec4 ©) = default;
108 :
109 : template <typename Functor>
110 50 : constexpr Vec4(const Vec4 &v, const Functor &f) : x(f(v.x)), y(f(v.y)), z(f(v.z)), w(f(v.w)) { }
111 :
112 : template <typename Functor>
113 : constexpr Vec4(const Vec4 &v1, const Vec4 &v2, const Functor &f) : x(f(v1.x, v2.x)), y(f(v1.y, v2.y)), z(f(v1.z, v2.z)), w(f(v1.w, v2.w)) { }
114 :
115 : constexpr bool isValid() const { return !std::isnan(x) && !std::isnan(y) && !std::isnan(z) && !std::isnan(w); }
116 :
117 : constexpr Vec2 xy() const {
118 : return Vec2(x, y);
119 : }
120 :
121 : constexpr Vec3 xyz() const {
122 : return Vec3(x, y, z);
123 : }
124 :
125 : void add(const float &v) {
126 : simd::add(&this->x, v, &this->x);
127 : }
128 :
129 50 : void add(const Vec4 &v) {
130 50 : simd::add(&this->x, &v.x, &this->x);
131 50 : }
132 :
133 : void subtract(const float &v) {
134 : simd::sub(&this->x, v, &this->x);
135 : }
136 :
137 : void subtract(const Vec4 &v) {
138 : simd::sub(&this->x, &v.x, &this->x);
139 : }
140 :
141 : void scale(const float &v) {
142 : simd::multiply(&this->x, v, &this->x);
143 : }
144 :
145 : void scale(const Vec4 &v) {
146 : simd::multiply(&this->x, &v.x, &this->x);
147 : }
148 :
149 : void unscale(const float &v) {
150 : simd::divide(&this->x, v, &this->x);
151 : }
152 :
153 : void unscale(const Vec4 &v) {
154 : simd::divide(&this->x, &v.x, &this->x);
155 : }
156 :
157 : void clamp(const Vec4& min, const Vec4& max);
158 :
159 : constexpr float distanceSquared(const Vec4& v) const {
160 : const float dx = v.x - x;
161 : const float dy = v.y - y;
162 : const float dz = v.z - z;
163 : const float dw = v.w - w;
164 :
165 : return (dx * dx + dy * dy + dz * dz + dw * dw);
166 : }
167 :
168 : constexpr float lengthSquared() const {
169 : return (x * x + y * y + z * z + w * w);
170 : }
171 :
172 : constexpr float distance(const Vec4& v) const { return std::sqrt(distanceSquared(v)); }
173 :
174 : constexpr float length() const { return std::sqrt(lengthSquared()); }
175 :
176 : constexpr bool isWithinDistance(const Vec4& v, float val) const {
177 : return distanceSquared(v) < val * val;
178 : }
179 :
180 : constexpr float dot(const Vec4& v) const { return (x * v.x + y * v.y + z * v.z + w * v.w); }
181 :
182 : constexpr void negate() { x = -x; y = -y; z = -z; w = -w; }
183 :
184 : constexpr Vec4 & normalize();
185 :
186 : Vec4 getNormalized() const;
187 :
188 : constexpr bool fuzzyEquals(const Vec4& b, float var = NumericLimits<float>::epsilon()) const {
189 : return (x - var <= b.x && b.x <= x + var) && (y - var <= b.y && b.y <= y + var)
190 : && (z - var <= b.z && b.z <= z + var) && (w - var <= b.w && b.w <= w + var);
191 : }
192 :
193 : Vec4& operator+=(const float &v) {
194 : add(v);
195 : return *this;
196 : }
197 :
198 25 : Vec4& operator+=(const Vec4& v) {
199 25 : add(v);
200 25 : return *this;
201 : }
202 :
203 : Vec4& operator-=(const float &v) {
204 : subtract(v);
205 : return *this;
206 : }
207 :
208 : Vec4& operator-=(const Vec4& v) {
209 : subtract(v);
210 : return *this;
211 : }
212 :
213 : Vec4& operator*=(const float &v) {
214 : scale(v);
215 : return *this;
216 : }
217 :
218 : Vec4& operator*=(const Vec4 &s) {
219 : scale(s);
220 : return *this;
221 : }
222 :
223 : Vec4& operator/=(const float &v) {
224 : unscale(v);
225 : return *this;
226 : }
227 :
228 : Vec4& operator/=(const Vec4 &s) {
229 : unscale(s);
230 : return *this;
231 : }
232 :
233 : SP_THREE_WAY_COMPARISON_FRIEND_CONSTEXPR(Vec4)
234 : };
235 :
236 25 : constexpr inline Vec4 &Vec4::normalize() {
237 25 : float n = x * x + y * y + z * z + w * w;
238 : // Already normalized.
239 25 : if (n == 1.0f) {
240 0 : return *this;
241 : }
242 :
243 25 : n = sqrt(n);
244 : // Too close to zero.
245 25 : if (n < math::MATH_TOLERANCE) {
246 0 : return *this;
247 : }
248 :
249 25 : n = 1.0f / n;
250 25 : x *= n;
251 25 : y *= n;
252 25 : z *= n;
253 25 : w *= n;
254 :
255 25 : return *this;
256 : }
257 :
258 : #ifndef __LCC__
259 :
260 : constexpr const Vec4 Vec4::ZERO = Vec4(0.0f, 0.0f, 0.0f, 0.0f);
261 : constexpr const Vec4 Vec4::ONE = Vec4(1.0f, 1.0f, 1.0f, 1.0f);
262 : constexpr const Vec4 Vec4::UNIT_X = Vec4(1.0f, 0.0f, 0.0f, 0.0f);
263 : constexpr const Vec4 Vec4::UNIT_Y = Vec4(0.0f, 1.0f, 0.0f, 0.0f);
264 : constexpr const Vec4 Vec4::UNIT_Z = Vec4(0.0f, 0.0f, 1.0f, 0.0f);
265 : constexpr const Vec4 Vec4::UNIT_W = Vec4(0.0f, 0.0f, 0.0f, 1.0f);
266 :
267 : #endif
268 :
269 : inline const Vec4 operator+(const Vec4 &l, const Vec4 &r) {
270 : Vec4 result;
271 : Vec4::add(l, r, &result);
272 : return result;
273 : }
274 :
275 : inline const Vec4 operator+(const Vec4 &l, const float &r) {
276 : Vec4 result(l);
277 : result.add(r);
278 : return result;
279 : }
280 :
281 : inline const Vec4 operator+(const float &l, const Vec4 &r) {
282 : Vec4 result(r);
283 : result.add(l);
284 : return result;
285 : }
286 :
287 : inline const Vec4 operator-(const Vec4 &l, const Vec4 &r) {
288 : Vec4 result;
289 : Vec4::subtract(l, r, &result);
290 : return result;
291 : }
292 :
293 : inline const Vec4 operator-(const Vec4 &l, const float &r) {
294 : Vec4 result(l);
295 : result.subtract(r);
296 : return result;
297 : }
298 :
299 30693134 : inline const Vec4 operator*(const Vec4 &l, const Vec4 &r) {
300 30693134 : Vec4 result;
301 30693134 : Vec4::scale(l, r, &result);
302 30693278 : return result;
303 : }
304 :
305 : inline const Vec4 operator*(const Vec4 &l, const float &r) {
306 : Vec4 result(l);
307 : result.scale(r);
308 : return result;
309 : }
310 :
311 : inline const Vec4 operator*(const float &l, const Vec4 &r) {
312 : Vec4 result(r);
313 : result.scale(l);
314 : return result;
315 : }
316 :
317 : inline const Vec4 operator/(const Vec4 &l, const Vec4 &r) {
318 : Vec4 result;
319 : Vec4::unscale(l, r, &result);
320 : return result;
321 : }
322 :
323 : inline const Vec4 operator/(const Vec4 &l, const float &r) {
324 : Vec4 result(l);
325 : result.unscale(r);
326 : return result;
327 : }
328 :
329 : constexpr Vec4 operator-(const Vec4& v) {
330 : Vec4 result(v);
331 : result.negate();
332 : return result;
333 : }
334 :
335 : inline std::basic_ostream<char> &
336 : operator << (std::basic_ostream<char> & os, const Vec4 & vec) {
337 : os << "(x: " << vec.x << "; y: " << vec.y << "; z: " << vec.z << "; w: " << vec.w << ")";
338 : return os;
339 : }
340 :
341 : }
342 :
343 : #endif /* STAPPLER_GEOM_SPVEC4_H */
|