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