1 /** @file vector.h Vector templates.
2 *
3 * The Vector templates use the convention that in an expression, the type of
4 * the left-hand operand defines which type is used for the operation. For
5 * instance, when comparing a < b, where @a a is a 2D vector and @a b is a 3D
6 * vector, the comparison only involves the first two components of @a b
7 * (comparing as a 2D vector).
8 *
9 * @authors Copyright © 2009-2017 Jaakko Keränen <jaakko.keranen@iki.fi>
10 * @authors Copyright © 2013 Daniel Swanson <danij@dengine.net>
11 *
12 * @par License
13 * LGPL: http://www.gnu.org/licenses/lgpl.html
14 *
15 * <small>This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU Lesser General Public License as published by
17 * the Free Software Foundation; either version 3 of the License, or (at your
18 * option) any later version. This program is distributed in the hope that it
19 * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
20 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
21 * General Public License for more details. You should have received a copy of
22 * the GNU Lesser General Public License along with this program; if not, see:
23 * http://www.gnu.org/licenses</small>
24 */
25
26 #ifndef LIBDENG2_VECTOR_H
27 #define LIBDENG2_VECTOR_H
28
29 #include "../math.h"
30 #include "../Error"
31 #include "../ISerializable"
32 #include "../Writer"
33 #include "../ByteRefArray"
34 #include "../Reader"
35 #include "../String"
36 #include "../NumberValue"
37
38 #include <QTextStream>
39 #include <cmath>
40
41 #ifdef WIN32
42 # undef min
43 # undef max
44 #endif
45
46 namespace de {
47
48 // Function for comparing numbers for equality in the Vector templates.
49 template <typename T>
numberEqual(T const & a,T const & b)50 inline bool numberEqual(T const &a, T const &b) {
51 return a == b;
52 }
53 template <>
numberEqual(dfloat const & a,dfloat const & b)54 inline bool numberEqual(dfloat const &a, dfloat const &b) {
55 return fequal(a, b);
56 }
57 template <>
numberEqual(ddouble const & a,ddouble const & b)58 inline bool numberEqual(ddouble const &a, ddouble const &b) {
59 return fequal(a, b);
60 }
61
62 /**
63 * Utility for converting a value with multiple elements into a vector. This
64 * only works if the value contains a sufficient number of elements and they
65 * can be converted to numbers.
66 *
67 * @param value Value with multiple elements.
68 *
69 * @return Vector.
70 */
71 template <typename VecType>
vectorFromValue(Value const & value)72 VecType vectorFromValue(Value const &value) {
73 VecType converted;
74 for (int i = 0; i < converted.size(); ++i) {
75 converted[i] = typename VecType::ValueType(value.element(i).asNumber());
76 }
77 return converted;
78 }
79
80 enum SwizzleAxis
81 {
82 AxisX = 0,
83 AxisY = 1,
84 AxisZ = 2,
85 AxisW = 3,
86
87 AxisNegX = -1,
88 AxisNegY = -2,
89 AxisNegZ = -3,
90 AxisNegW = -4
91 };
92
93 /**
94 * Template class for 2D vectors (points). The members are public for
95 * convenient access. The used value type must be serializable.
96 *
97 * Does not directly implement ISerializable to keep the size of the class
98 * at sizeof(Type) * 2 for array usage.
99 *
100 * @ingroup math
101 */
102 template <typename Type>
103 class Vector2
104 {
105 public:
106 typedef Type ValueType;
107
108 public:
x(a)109 Vector2(Type a = Type(0), Type b = Type(0)) : x(a), y(b) {}
Vector2(Type const * ab)110 Vector2(Type const *ab) : x(ab[0]), y(ab[1]) {}
Vector2(Value const & value)111 Vector2(Value const &value) { *this = vectorFromValue< Vector2<Type> >(value); }
Vector2(Vector2 const & other)112 Vector2(Vector2 const &other) : x(other.x), y(other.y) {}
113
114 /// Implicit conversion operator to a float vector.
115 operator Vector2<dfloat> () const {
116 return Vector2<dfloat>(dfloat(x), dfloat(y));
117 }
118 /// Implicit conversion operator to a double vector.
119 operator Vector2<ddouble> () const {
120 return Vector2<ddouble>(ddouble(x), ddouble(y));
121 }
toVector2i()122 Vector2<dint> toVector2i() const {
123 return Vector2<dint>(dint(x), dint(y));
124 }
toVector2ui()125 Vector2<duint> toVector2ui() const {
126 return Vector2<duint>(duint(de::max(Type(0), x)), duint(de::max(Type(0), y)));
127 }
size()128 int size() const {
129 return 2;
130 }
data()131 ByteRefArray const data() const {
132 return ByteRefArray(&x, size() * sizeof(ValueType));
133 }
data()134 ByteRefArray data() {
135 return ByteRefArray(&x, size() * sizeof(ValueType));
136 }
constPtr()137 ValueType const *constPtr() const {
138 return &x;
139 }
140 Type &operator [] (int index) {
141 DENG2_ASSERT(index >= 0 && index <= 1);
142 if (index >= 0 && index < 2)
143 {
144 return (&x)[index];
145 }
146 throw Error("Vector2::operator []", QString("Illegal index %1").arg(index));
147 }
148 Type const &operator [] (int index) const {
149 return const_cast<Vector2<Type> &>(*this)[index];
150 }
151 Vector2 operator + (Vector2 const &other) const {
152 return Vector2(x + other.x, y + other.y);
153 }
154 Vector2 operator - (Vector2 const &other) const {
155 return Vector2(x - other.x, y - other.y);
156 }
157 Vector2 operator - () const {
158 return Vector2(-x, -y);
159 }
160 Vector2 operator * (int scalar) const {
161 return Vector2(Type(x * scalar), Type(y * scalar));
162 }
163 Vector2 operator * (float scalar) const {
164 return Vector2(Type(x * scalar), Type(y * scalar));
165 }
166 Vector2 operator * (double scalar) const {
167 return Vector2(Type(x * scalar), Type(y * scalar));
168 }
169 Vector2 operator * (Vector2 const &other) const {
170 return Vector2(x * other.x, y * other.y);
171 }
172 Vector2 operator / (ddouble scalar) const {
173 return *this * (1.0 / scalar);
174 }
175 Vector2 operator / (Vector2 const &other) const {
176 return Vector2(x / other.x, y / other.y);
177 }
178 Vector2 &operator += (Vector2 const &other) {
179 x += other.x;
180 y += other.y;
181 return *this;
182 }
183 Vector2 &operator -= (Vector2 const &other) {
184 x -= other.x;
185 y -= other.y;
186 return *this;
187 }
188 inline Vector2 &operator *= (ddouble scalar) {
189 x *= scalar;
190 y *= scalar;
191 return *this;
192 }
193 inline Vector2 &operator *= (Vector2 const &other) {
194 x *= other.x;
195 y *= other.y;
196 return *this;
197 }
198 inline Vector2 &operator /= (ddouble scalar) {
199 return (*this) *= 1.0 / scalar;
200 }
201 inline bool operator == (Vector2 const &other) const {
202 return numberEqual(x, other.x) && numberEqual(y, other.y);
203 }
204 inline bool operator != (Vector2 const &other) const {
205 return !(*this == other);
206 }
207 bool operator > (Vector2 const &other) const {
208 if (x == other.x) return y > other.y;
209 return x > other.x && y > other.y;
210 }
211 bool operator < (Vector2 const &other) const {
212 if (x == other.x) return y < other.y;
213 return x < other.x && y < other.y;
214 }
215 bool operator >= (Vector2 const &other) const {
216 return *this == other || *this > other;
217 }
218 bool operator <= (Vector2 const &other) const {
219 return *this == other || *this < other;
220 }
length()221 inline ddouble length() const {
222 return std::sqrt(lengthSquared());
223 }
lengthSquared()224 inline ddouble lengthSquared() const {
225 return ddouble(x*x + y*y);
226 }
setLength(ddouble len)227 void setLength(ddouble len) {
228 *this = *this / length() * len;
229 }
normalize()230 Vector2 normalize() const {
231 ddouble const len = length();
232 if (len != 0) {
233 return *this / len;
234 }
235 return Vector2();
236 }
asText()237 String asText() const {
238 String str;
239 QTextStream s(&str);
240 s << *this;
241 return str;
242 }
abs()243 Vector2 abs() const {
244 return Vector2(de::abs(x), de::abs(y));
245 }
dot(const Vector2 & other)246 double dot(const Vector2 &other) const {
247 return x * other.x + y * other.y;
248 }
cross(const Vector2 & other)249 double cross(const Vector2 &other) const {
250 return x * other.y - y * other.x;
251 }
min(Vector2 const & other)252 Vector2 min(Vector2 const &other) const {
253 return Vector2(de::min(x, other.x), de::min(y, other.y));
254 }
max(Vector2 const & other)255 Vector2 max(Vector2 const &other) const {
256 return Vector2(de::max(x, other.x), de::max(y, other.y));
257 }
min()258 Type min() const {
259 return de::min(x, y);
260 }
max()261 Type max() const {
262 return de::max(x, y);
263 }
minAxis()264 int minAxis() const {
265 Vector2 vecAbs = abs();
266 return vecAbs.x < vecAbs.y? 0 : 1;
267 }
maxAxis()268 int maxAxis() const {
269 Vector2 vecAbs = abs();
270 return vecAbs.x > vecAbs.y? 1 : 0;
271 }
decompose(Type * array)272 inline void decompose(Type *array) const {
273 for (int i = 0; i < 2; ++i) array[i] = (*this)[i];
274 }
yx()275 Vector2<Type> yx() const { return swizzle(*this, AxisY, AxisX); }
276
277 public:
278 Type x;
279 Type y;
280 };
281
282 // Serialization of Vector2.
283 template <typename Type>
284 inline Writer &operator << (Writer &to, Vector2<Type> const &vec2) {
285 to << vec2.x << vec2.y;
286 return to;
287 }
288
289 template <typename Type>
290 inline void operator << (Writer const &to, Vector2<Type> const &vec2) {
291 Writer w(to);
292 w << vec2.x << vec2.y;
293 }
294
295 template <typename Type>
296 inline Reader &operator >> (Reader &from, Vector2<Type> &vec2) {
297 from >> vec2.x >> vec2.y;
298 return from;
299 }
300
301 template <typename Type>
302 inline void operator >> (Reader const &from, Vector2<Type> &vec2) {
303 Reader r(from);
304 r >> vec2.x >> vec2.y;
305 }
306
307 template <typename Type>
308 inline QTextStream &operator << (QTextStream &os, Vector2<Type> const &vec2) {
309 os << "(" << vec2.x << ", " << vec2.y << ")";
310 return os;
311 }
312
313 /**
314 * Template class for 3D vectors (points).
315 * The members are public for convenient access.
316 *
317 * @ingroup math
318 */
319 template <typename Type>
320 class Vector3 : public Vector2<Type>
321 {
322 public:
323 Vector3(Type a = 0, Type b = 0, Type c = 0) : Vector2<Type>(a, b), z(c) {}
324 Vector3(Vector2<Type> const &v2, Type c = 0) : Vector2<Type>(v2), z(c) {}
Vector3(Type const * abc)325 Vector3(Type const *abc) : Vector2<Type>(abc), z(abc[2]) {}
Vector3(Value const & value)326 Vector3(Value const &value) { *this = vectorFromValue< Vector3<Type> >(value); }
327
328 /// Implicit conversion operator to a float vector.
329 operator Vector3<dfloat> () const {
330 return Vector3<dfloat>(Vector2<Type>::x, Vector2<Type>::y, z);
331 }
332 /// Implicit conversion operator to a double vector.
333 operator Vector3<ddouble> () const {
334 return Vector3<ddouble>(Vector2<Type>::x, Vector2<Type>::y, z);
335 }
toVector3ub()336 Vector3<dbyte> toVector3ub() const {
337 return Vector3<dbyte>(dbyte(Vector2<Type>::x), dbyte(Vector2<Type>::y), dbyte(z));
338 }
toVector3f()339 Vector3<dfloat> toVector3f() const {
340 return Vector3<dfloat>(dfloat(Vector2<Type>::x), dfloat(Vector2<Type>::y), dfloat(z));
341 }
toVector3i()342 Vector3<dint> toVector3i() const {
343 return Vector3<dint>(dint(Vector2<Type>::x), dint(Vector2<Type>::y), dint(z));
344 }
size()345 int size() const {
346 return 3;
347 }
data()348 ByteRefArray const data() const {
349 return ByteRefArray(&this->Vector2<Type>::x, size() * sizeof(Type));
350 }
data()351 ByteRefArray data() {
352 return ByteRefArray(&this->Vector2<Type>::x, size() * sizeof(Type));
353 }
354 Type &operator [] (int index) {
355 DENG2_ASSERT(index >= 0 && index <= 2);
356 if (index >= 0 && index < 3)
357 {
358 return (&(this->Vector2<Type>::x))[index];
359 }
360 throw Error("Vector3::operator []", QString("Illegal index %1").arg(index));
361 }
362 Type const &operator [] (int index) const {
363 return const_cast<Vector3<Type> &>(*this)[index];
364 }
365 Vector3 operator + (Vector3 const &other) const {
366 return Vector3(Vector2<Type>::x + other.x, Vector2<Type>::y + other.y, z + other.z);
367 }
368 Vector3 operator - (Vector3 const &other) const {
369 return Vector3(Vector2<Type>::x - other.x, Vector2<Type>::y - other.y, z - other.z);
370 }
371 Vector3 operator - () const {
372 return Vector3(-Vector2<Type>::x, -Vector2<Type>::y, -z);
373 }
374 Vector3 operator * (ddouble scalar) const {
375 return Vector3(Type(Vector2<Type>::x * scalar), Type(Vector2<Type>::y * scalar),
376 Type(z * scalar));
377 }
378 Vector3 operator / (ddouble scalar) const {
379 return *this * (1.0 / scalar);
380 }
381 Vector3 operator * (Vector3 const &other) const {
382 return Vector3(Vector2<Type>::x * other.x, Vector2<Type>::y * other.y, z * other.z);
383 }
384 Vector3 &operator += (Vector3 const &other) {
385 Vector2<Type>::x += other.x;
386 Vector2<Type>::y += other.y;
387 z += other.z;
388 return *this;
389 }
390 Vector3 &operator -= (Vector3 const &other) {
391 Vector2<Type>::x -= other.x;
392 Vector2<Type>::y -= other.y;
393 z -= other.z;
394 return *this;
395 }
396 inline Vector3 &operator *= (ddouble scalar) {
397 Vector2<Type>::operator *= (scalar);
398 z *= scalar;
399 return *this;
400 }
401 inline Vector3 &operator *= (Vector3 const &other) {
402 Vector2<Type>::operator *= (other);
403 z *= other.z;
404 return *this;
405 }
406 inline Vector3 &operator /= (ddouble scalar) {
407 return (*this) *= 1.0 / scalar;
408 }
409 inline bool operator == (Vector3 const &other) const {
410 return Vector2<Type>::operator == (other) && numberEqual(z, other.z);
411 }
412 inline bool operator != (Vector3 const &other) const {
413 return !(*this == other);
414 }
415 bool operator > (Vector3 const &other) const {
416 if (Vector2<Type>::operator == (other)) return z > other.z;
417 return Vector2<Type>::operator > (other) && z > other.z;
418 }
419 bool operator < (Vector3 const &other) const {
420 if (Vector2<Type>::operator == (other)) return z < other.z;
421 return Vector2<Type>::operator < (other) && z < other.z;
422 }
423 bool operator >= (Vector3 const &other) const {
424 return *this == other || *this > other;
425 }
426 bool operator <= (Vector3 const &other) const {
427 return *this == other || *this < other;
428 }
length()429 inline ddouble length() const {
430 return std::sqrt(lengthSquared());
431 }
setLength(ddouble len)432 void setLength(ddouble len) {
433 *this = *this / length() * len;
434 }
lengthSquared()435 ddouble lengthSquared() const {
436 return Vector2<Type>::x*Vector2<Type>::x + Vector2<Type>::y*Vector2<Type>::y + z*z;
437 }
normalize()438 Vector3 normalize() const {
439 ddouble const len = length();
440 if (len != 0) {
441 return *this / len;
442 }
443 return Vector3();
444 }
asText()445 String asText() const {
446 String str;
447 QTextStream os(&str);
448 os << *this;
449 return str;
450 }
abs()451 Vector3 abs() const {
452 return Vector3(de::abs(Vector2<Type>::x), de::abs(Vector2<Type>::y), de::abs(z));
453 }
dot(Vector3 const & other)454 ddouble dot(Vector3 const &other) const {
455 return Vector2<Type>::x * other.x + Vector2<Type>::y * other.y + z * other.z;
456 }
cross(Vector3 const & other)457 inline Vector3 cross(Vector3 const &other) const {
458 return Vector3(Vector2<Type>::y * other.z - z * other.y,
459 z * other.x - Vector2<Type>::x * other.z,
460 Vector2<Type>::x * other.y - Vector2<Type>::y * other.x);
461 }
min(Vector3 const & other)462 Vector3 min(Vector3 const &other) const {
463 return Vector3(de::min(Vector2<Type>::x, other.x), de::min(Vector2<Type>::y, other.y),
464 de::min(z, other.z));
465 }
max(Vector3 const & other)466 Vector3 max(Vector3 const &other) const {
467 return Vector3(de::max(Vector2<Type>::x, other.x), de::max(Vector2<Type>::y, other.y),
468 de::max(z, other.z));
469 }
min()470 Type min() const {
471 return de::min(z, Vector2<Type>::min());
472 }
max()473 Type max() const {
474 return de::max(z, Vector2<Type>::max());
475 }
minAxis()476 int minAxis() const {
477 Vector3 vecAbs = abs();
478 int axis = 2;
479 if (vecAbs.y < vecAbs[axis]) axis = 1;
480 if (vecAbs.x < vecAbs[axis]) axis = 0;
481 return axis;
482 }
maxAxis()483 int maxAxis() const {
484 Vector3 vecAbs = abs();
485 int axis = 0;
486 if (vecAbs.y > vecAbs[axis]) axis = 1;
487 if (vecAbs.z > vecAbs[axis]) axis = 2;
488 return axis;
489 }
decompose(Type * array)490 inline void decompose(Type *array) const {
491 for (int i = 0; i < 3; ++i) array[i] = (*this)[i];
492 }
xy()493 Vector2<Type> xy() const { return *this; }
xz()494 Vector2<Type> xz() const { return swizzle(*this, AxisX, AxisZ); }
xzy()495 Vector3<Type> xzy() const { return swizzle(*this, AxisX, AxisZ, AxisY); }
zyx()496 Vector3<Type> zyx() const { return swizzle(*this, AxisZ, AxisY, AxisX); }
497
498 public:
499 Type z;
500 };
501
502 // Serialization of Vector3.
503 template <typename Type>
504 inline Writer &operator << (Writer &to, Vector3<Type> const &vec3) {
505 to << vec3.x << vec3.y << vec3.z;
506 return to;
507 }
508
509 template <typename Type>
510 inline void operator << (Writer const &to, Vector3<Type> const &vec3) {
511 Writer w(to);
512 w << vec3.x << vec3.y << vec3.z;
513 }
514
515 template <typename Type>
516 inline Reader &operator >> (Reader &from, Vector3<Type> &vec3) {
517 from >> vec3.x >> vec3.y >> vec3.z;
518 return from;
519 }
520
521 template <typename Type>
522 inline void operator >> (Reader const &from, Vector3<Type> &vec3) {
523 Reader r(from);
524 r >> vec3.x >> vec3.y >> vec3.z;
525 }
526
527 template <typename Type>
528 QTextStream &operator << (QTextStream &os, Vector3<Type> const &vec3)
529 {
530 os << "(" << vec3.x << ", " << vec3.y << ", " << vec3.z << ")";
531 return os;
532 }
533
534 /**
535 * Template class for 4D vectors.
536 * The members are public for convenient access.
537 *
538 * Note that when mixing 3D and 4D vectors, by default the automatic conversion
539 * between these simply disregards the @em w component. If the intention is to
540 * treat 4D vectors as homogeneous, one must explicitly convert to/from 3D
541 * vectors using Vector4<Type>::fromEuclidean() and
542 * Vector4<Type>::toEuclidean().
543 *
544 * @ingroup math
545 */
546 template <typename Type>
547 class Vector4 : public Vector3<Type>
548 {
549 public:
550 Vector4(Type a = 0, Type b = 0, Type c = 0, Type d = 0) : Vector3<Type>(a, b, c), w(d) {}
551 Vector4(Vector3<Type> const &v3, Type d = 0) : Vector3<Type>(v3), w(d) {}
Vector4(Vector2<Type> const & a,Vector2<Type> const & b)552 Vector4(Vector2<Type> const &a, Vector2<Type> const &b) : Vector3<Type>(a, b.x), w(b.y) {}
Vector4(Type const * abcd)553 Vector4(Type const *abcd) : Vector3<Type>(abcd), w(abcd[3]) {}
Vector4(Value const & value)554 Vector4(Value const &value) { *this = vectorFromValue< Vector4<Type> >(value); }
555
556 /// Implicit conversion operator to a float vector.
557 operator Vector4<dfloat> () const {
558 return Vector4<dfloat>(Vector3<Type>::x, Vector3<Type>::y, Vector3<Type>::z, w);
559 }
560 /// Implicit conversion operator to a double vector.
561 operator Vector4<ddouble> () const {
562 return Vector4<ddouble>(Vector3<Type>::x, Vector3<Type>::y, Vector3<Type>::z, w);
563 }
toVector4i()564 Vector4<dint> toVector4i() const {
565 return Vector4<dint>(dint(Vector3<Type>::x), dint(Vector3<Type>::y), dint(Vector3<Type>::z), dint(w));
566 }
toVector4ub()567 Vector4<dbyte> toVector4ub() const {
568 return Vector4<dbyte>(dbyte(Vector3<Type>::x), dbyte(Vector3<Type>::y), dbyte(Vector3<Type>::z), dbyte(w));
569 }
toVector4f()570 Vector4<dfloat> toVector4f() const {
571 return Vector4<dfloat>(dfloat(Vector3<Type>::x), dfloat(Vector3<Type>::y), dfloat(Vector3<Type>::z), dfloat(w));
572 }
size()573 int size() const {
574 return 4;
575 }
data()576 ByteRefArray const data() const {
577 return ByteRefArray(&this->Vector2<Type>::x, size() * sizeof(Type));
578 }
data()579 ByteRefArray data() {
580 return ByteRefArray(&this->Vector2<Type>::x, size() * sizeof(Type));
581 }
582 Type &operator [] (int index) {
583 DENG2_ASSERT(index >= 0 && index <= 3);
584 if (index >= 0 && index < 4)
585 {
586 return (&(this->Vector2<Type>::x))[index];
587 }
588 throw Error("Vector4::operator []", QString("Illegal index %1").arg(index));
589 }
590 Type const &operator [] (int index) const {
591 return const_cast<Vector4<Type> &>(*this)[index];
592 }
593 Vector4 operator + (Vector4 const &other) const {
594 return Vector4(Vector3<Type>::x + other.x, Vector3<Type>::y + other.y,
595 Vector3<Type>::z + other.z, w + other.w);
596 }
597 Vector4 operator - (Vector4 const &other) const {
598 return Vector4(Vector3<Type>::x - other.x, Vector3<Type>::y - other.y,
599 Vector3<Type>::z - other.z, w - other.w);
600 }
601 Vector4 operator - () const {
602 return Vector4(-Vector3<Type>::x, -Vector3<Type>::y, -Vector3<Type>::z, -w);
603 }
604 Vector4 operator * (ddouble scalar) const {
605 return Vector4(Type(Vector3<Type>::x * scalar), Type(Vector3<Type>::y * scalar),
606 Type(Vector3<Type>::z * scalar), Type(w * scalar));
607 }
608 Vector4 operator * (Vector4 const &other) const {
609 return Vector4(Vector3<Type>::x * other.x, Vector3<Type>::y * other.y,
610 Vector3<Type>::z * other.z, w * other.w);
611 }
612 Vector4 &operator += (Vector4 const &other) {
613 Vector3<Type>::x += other.x;
614 Vector3<Type>::y += other.y;
615 Vector3<Type>::z += other.z;
616 w += other.w;
617 return *this;
618 }
619 Vector4 &operator -= (Vector4 const &other) {
620 Vector3<Type>::x -= other.x;
621 Vector3<Type>::y -= other.y;
622 Vector3<Type>::z -= other.z;
623 w -= other.w;
624 return *this;
625 }
626 inline Vector4 &operator *= (ddouble scalar) {
627 Vector3<Type>::operator *= (scalar);
628 w *= scalar;
629 return *this;
630 }
631 inline Vector4 &operator *= (Vector4 const &other) {
632 Vector3<Type>::operator *= (other);
633 w *= other.w;
634 return *this;
635 }
636 Vector4 operator / (ddouble scalar) const {
637 return *this * (1.0 / scalar);
638 }
639 inline Vector4 &operator /= (ddouble scalar) {
640 return (*this) *= 1.0 / scalar;
641 }
642 inline bool operator == (Vector4 const &other) const {
643 return Vector3<Type>::operator == (other) && numberEqual(w, other.w);
644 }
645 inline bool operator != (Vector4 const &other) const {
646 return !(*this == other);
647 }
648 bool operator > (Vector4 const &other) const {
649 if (Vector3<Type>::operator == (other)) return w > other.w;
650 return Vector3<Type>::operator > (other) && w > other.w;
651 }
652 bool operator < (Vector4 const &other) const {
653 if (Vector3<Type>::operator == (other)) return w < other.w;
654 return Vector3<Type>::operator < (other) && w < other.w;
655 }
656 bool operator >= (Vector4 const &other) const {
657 return *this == other || *this > other;
658 }
659 bool operator <= (Vector4 const &other) const {
660 return *this == other || *this < other;
661 }
asText()662 String asText() const {
663 String str;
664 QTextStream os(&str);
665 os << *this;
666 return str;
667 }
abs()668 Vector4 abs() const {
669 return Vector4(de::abs(Vector3<Type>::x), de::abs(Vector3<Type>::y), de::abs(Vector3<Type>::z), de::abs(w));
670 }
dot(Vector4 const & other)671 ddouble dot(Vector4 const &other) const {
672 return Vector3<Type>::x * other.x + Vector3<Type>::y * other.y
673 + Vector3<Type>::z * other.z + w * other.w;
674 }
min(Vector4 const & other)675 Vector4 min(Vector4 const &other) const {
676 return Vector4(de::min(Vector3<Type>::x, other.x), de::min(Vector3<Type>::y, other.y),
677 de::min(Vector3<Type>::z, other.z), de::min(w, other.w));
678 }
max(Vector4 const & other)679 Vector4 max(Vector4 const &other) const {
680 return Vector4(de::max(Vector3<Type>::x, other.x), de::max(Vector3<Type>::y, other.y),
681 de::max(Vector3<Type>::z, other.z), de::max(w, other.w));
682 }
min()683 Type min() const {
684 return de::min(w, Vector3<Type>::min());
685 }
max()686 Type max() const {
687 return de::max(w, Vector3<Type>::max());
688 }
minAxis()689 int minAxis() const {
690 Vector4 vecAbs = abs();
691 int axis = 3;
692 if (vecAbs.z < vecAbs[axis]) axis = 2;
693 if (vecAbs.y < vecAbs[axis]) axis = 1;
694 if (vecAbs.x < vecAbs[axis]) axis = 0;
695 return axis;
696 }
maxAxis()697 int maxAxis() const {
698 Vector4 vecAbs = abs();
699 int axis = 0;
700 if (vecAbs.y > vecAbs[axis]) axis = 1;
701 if (vecAbs.z > vecAbs[axis]) axis = 2;
702 if (vecAbs.w > vecAbs[axis]) axis = 3;
703 return axis;
704 }
decompose(Type * array)705 inline void decompose(Type *array) const {
706 for (int i = 0; i < 4; ++i) array[i] = (*this)[i];
707 }
708
709 // Implements ISerializable.
710 void operator >> (Writer &to) const {
711 Vector3<Type>::operator >> (to);
712 to << w;
713 }
714 void operator << (Reader &from) {
715 Vector3<Type>::operator << (from);
716 from >> w;
717 }
718
fromEuclidean(Vector3<Type> const & vec3)719 static Vector4 fromEuclidean(Vector3<Type> const &vec3) {
720 return Vector4(vec3, Type(1));
721 }
toEuclidean()722 Vector3<Type> toEuclidean() const {
723 if (w != 0)
724 {
725 return Vector3<Type>(Vector2<Type>::x/w, Vector2<Type>::y/w, Vector3<Type>::z/w);
726 }
727 return Vector3<Type>();
728 }
xy()729 Vector2<Type> xy() const { return *this; }
zw()730 Vector2<Type> zw() const { return swizzle(*this, AxisZ, AxisW); }
xyz()731 Vector3<Type> xyz() const { return *this; }
zyxw()732 Vector4<Type> zyxw() const { return swizzle(*this, AxisZ, AxisY, AxisX, AxisW); }
replaced(int index,Type const & value)733 Vector4<Type> replaced(int index, Type const &value) const {
734 Vector4 v = *this;
735 v[index] = value;
736 return v;
737 }
738
739 public:
740 Type w;
741 };
742
743 // Swizzling.
744 template <typename Type>
swizzledComponent(Type const & vec,SwizzleAxis axis)745 typename Type::ValueType swizzledComponent(Type const &vec, SwizzleAxis axis) {
746 if (axis >= 0) return vec[axis];
747 return -vec[-axis - 1];
748 }
749
750 template <typename Type>
swizzle(Type const & vec,SwizzleAxis a,SwizzleAxis b)751 Vector2<typename Type::ValueType> swizzle(Type const &vec, SwizzleAxis a, SwizzleAxis b) {
752 return Vector2<typename Type::ValueType>(swizzledComponent(vec, a),
753 swizzledComponent(vec, b));
754 }
755
756 template <typename Type>
swizzle(Type const & vec,SwizzleAxis a,SwizzleAxis b,SwizzleAxis c)757 Vector3<typename Type::ValueType> swizzle(Type const &vec, SwizzleAxis a, SwizzleAxis b, SwizzleAxis c) {
758 return Vector3<typename Type::ValueType>(swizzledComponent(vec, a),
759 swizzledComponent(vec, b),
760 swizzledComponent(vec, c));
761 }
762
763 template <typename Type>
swizzle(Type const & vec,SwizzleAxis a,SwizzleAxis b,SwizzleAxis c,SwizzleAxis d)764 Vector4<typename Type::ValueType> swizzle(Type const &vec, SwizzleAxis a, SwizzleAxis b, SwizzleAxis c, SwizzleAxis d) {
765 return Vector4<typename Type::ValueType>(swizzledComponent(vec, a),
766 swizzledComponent(vec, b),
767 swizzledComponent(vec, c),
768 swizzledComponent(vec, d));
769 }
770
771 // Serialization of Vector4.
772 template <typename Type>
773 inline Writer &operator << (Writer &to, Vector4<Type> const &vec4) {
774 to << vec4.x << vec4.y << vec4.z << vec4.w;
775 return to;
776 }
777
778 template <typename Type>
779 inline void operator << (Writer const &to, Vector4<Type> const &vec4) {
780 Writer w(to);
781 w << vec4.x << vec4.y << vec4.z << vec4.w;
782 }
783
784 template <typename Type>
785 inline Reader &operator >> (Reader &from, Vector4<Type> &vec4) {
786 from >> vec4.x >> vec4.y >> vec4.z >> vec4.w;
787 return from;
788 }
789
790 template <typename Type>
791 inline void operator >> (Reader const &from, Vector4<Type> &vec4) {
792 Reader r(from);
793 r >> vec4.x >> vec4.y >> vec4.z >> vec4.w;
794 }
795
796 template <typename Type>
797 QTextStream &operator << (QTextStream &os, Vector4<Type> const &vec4)
798 {
799 os << "(" << vec4.x << ", " << vec4.y << ", " << vec4.z << ", " << vec4.w << ")";
800 return os;
801 }
802
803 ///@{
804 /// @ingroup types
805 typedef Vector2<dint> Vector2i; ///< 2-component vector of integer values.
806 typedef Vector2<duint> Vector2ui; ///< 2-component vector of unsigned integer values.
807 typedef Vector2<dfloat> Vector2f; ///< 2-component vector of floating point values.
808 typedef Vector2<ddouble> Vector2d; ///< 2-component vector of high-precision floating point values.
809 typedef Vector3<dbyte> Vector3ub; ///< 3-component vector of unsigned byte values.
810 typedef Vector3<dint> Vector3i; ///< 3-component vector of integer values.
811 typedef Vector3<duint> Vector3ui; ///< 3-component vector of unsigned integer values.
812 typedef Vector3<dfloat> Vector3f; ///< 3-component vector of floating point values.
813 typedef Vector3<ddouble> Vector3d; ///< 3-component vector of high-precision floating point values.
814 typedef Vector4<dbyte> Vector4ub; ///< 4-component vector of unsigned byte values.
815 typedef Vector4<dint> Vector4i; ///< 4-component vector of integer values.
816 typedef Vector4<duint> Vector4ui; ///< 4-component vector of unsigned integer values.
817 typedef Vector4<dfloat> Vector4f; ///< 4-component vector of floating point values.
818 typedef Vector4<ddouble> Vector4d; ///< 4-component vector of high-precision floating point values.
819 ///@}
820
821 using Vec2i = Vector2i;
822 using Vec2ui = Vector2ui;
823 using Vec3i = Vector3i;
824 using Vec3ui = Vector3ui;
825 using Vec4i = Vector4i;
826 using Vec4ub = Vector4ub;
827 using Vec2f = Vector2f;
828 using Vec3f = Vector3f;
829 using Vec4f = Vector4f;
830 using Vec2d = Vector2d;
831 using Vec3d = Vector3d;
832 using Vec4d = Vector4d;
833
834 // Qt hash functions:
qHash(Vector2i const & vec)835 inline quint32 qHash(Vector2i const &vec) { return vec.x * vec.y + vec.x - vec.y; }
836
837 } // namespace de
838
839 #endif /* LIBDENG2_VECTOR_H */
840