1 /**************************************************************************
3 * Copyright 2013-2014 RAD Game Tools and Valve Software
4 * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 **************************************************************************/
30 #include "vogl_core.h"
31 #include "vogl_rand.h"
35 template <uint N, typename T>
36 class vec : public helpers::rel_ops<vec<N, T> >
39 typedef T scalar_type;
54 inline vec(const vec &other)
56 for (uint i = 0; i < N; i++)
57 m_s[i] = other.m_s[i];
60 template <uint O, typename U>
61 inline vec(const vec<O, U> &other)
66 template <uint O, typename U>
67 inline vec(const vec<O, U> &other, T w)
73 explicit inline vec(T val)
78 inline vec(T val0, T val1)
83 inline vec(T val0, T val1, T val2)
85 set(val0, val1, val2);
88 inline vec(T val0, T val1, T val2, T val3)
90 set(val0, val1, val2, val3);
94 T val0, T val1, T val2, T val3,
95 T val4, T val5, T val6, T val7,
96 T val8, T val9, T val10, T val11,
97 T val12, T val13, T val14, T val15)
99 set(val0, val1, val2, val3,
100 val4, val5, val6, val7,
101 val8, val9, val10, val11,
102 val12, val13, val14, val15);
106 T val0, T val1, T val2, T val3,
107 T val4, T val5, T val6, T val7,
108 T val8, T val9, T val10, T val11,
109 T val12, T val13, T val14, T val15,
110 T val16, T val17, T val18, T val19)
112 set(val0, val1, val2, val3,
113 val4, val5, val6, val7,
114 val8, val9, val10, val11,
115 val12, val13, val14, val15,
116 val16, val17, val18, val19);
120 T val0, T val1, T val2, T val3,
121 T val4, T val5, T val6, T val7,
122 T val8, T val9, T val10, T val11,
123 T val12, T val13, T val14, T val15,
124 T val16, T val17, T val18, T val19,
125 T val20, T val21, T val22, T val23,
128 set(val0, val1, val2, val3,
129 val4, val5, val6, val7,
130 val8, val9, val10, val11,
131 val12, val13, val14, val15,
132 val16, val17, val18, val19,
133 val20, val21, val22, val23,
140 memset(m_s, 0, sizeof(m_s));
143 for (uint i = 0; i < N; i++)
148 template <uint ON, typename OT>
149 inline vec &set(const vec<ON, OT> &other)
151 if ((void *)this == (void *)&other)
153 const uint m = math::minimum(N, ON);
155 for (i = 0; i < m; i++)
156 m_s[i] = static_cast<T>(other[i]);
162 inline vec &set_component(uint index, T val)
164 VOGL_ASSERT(index < N);
169 inline vec &set(T val)
171 for (uint i = 0; i < N; i++)
176 inline vec &set(T val0, T val1)
183 for (uint i = 2; i < N; i++)
189 inline vec &set(T val0, T val1, T val2)
200 for (uint i = 3; i < N; i++)
207 inline vec &set(T val0, T val1, T val2, T val3)
222 for (uint i = 4; i < N; i++)
231 T val0, T val1, T val2, T val3,
232 T val4, T val5, T val6, T val7,
233 T val8, T val9, T val10, T val11,
234 T val12, T val13, T val14, T val15)
271 for (uint i = 16; i < N; i++)
278 T val0, T val1, T val2, T val3,
279 T val4, T val5, T val6, T val7,
280 T val8, T val9, T val10, T val11,
281 T val12, T val13, T val14, T val15,
282 T val16, T val17, T val18, T val19)
328 for (uint i = 20; i < N; i++)
335 T val0, T val1, T val2, T val3,
336 T val4, T val5, T val6, T val7,
337 T val8, T val9, T val10, T val11,
338 T val12, T val13, T val14, T val15,
339 T val16, T val17, T val18, T val19,
340 T val20, T val21, T val22, T val23,
399 for (uint i = 25; i < N; i++)
405 inline vec &set(const T *pValues)
407 for (uint i = 0; i < N; i++)
412 template <uint ON, typename OT>
413 inline vec &swizzle_set(const vec<ON, OT> &other, uint i)
415 return set(static_cast<T>(other[i]));
418 template <uint ON, typename OT>
419 inline vec &swizzle_set(const vec<ON, OT> &other, uint i, uint j)
421 return set(static_cast<T>(other[i]), static_cast<T>(other[j]));
424 template <uint ON, typename OT>
425 inline vec &swizzle_set(const vec<ON, OT> &other, uint i, uint j, uint k)
427 return set(static_cast<T>(other[i]), static_cast<T>(other[j]), static_cast<T>(other[k]));
430 template <uint ON, typename OT>
431 inline vec &swizzle_set(const vec<ON, OT> &other, uint i, uint j, uint k, uint l)
433 return set(static_cast<T>(other[i]), static_cast<T>(other[j]), static_cast<T>(other[k]), static_cast<T>(other[l]));
436 inline vec &operator=(const vec &rhs)
440 for (uint i = 0; i < N; i++)
446 template <uint O, typename U>
447 inline vec &operator=(const vec<O, U> &other)
449 if ((void *)this == (void *)&other)
452 uint s = math::minimum(N, O);
455 for (i = 0; i < s; i++)
456 m_s[i] = static_cast<T>(other[i]);
464 inline bool operator==(const vec &rhs) const
466 for (uint i = 0; i < N; i++)
467 if (!(m_s[i] == rhs.m_s[i]))
472 inline bool operator<(const vec &rhs) const
474 for (uint i = 0; i < N; i++)
476 if (m_s[i] < rhs.m_s[i])
478 else if (!(m_s[i] == rhs.m_s[i]))
485 inline T operator[](uint i) const
491 inline T &operator[](uint i)
497 template <uint index>
498 inline uint64_t get_component_as_uint() const
500 VOGL_ASSUME(index < N);
501 if (sizeof(T) == sizeof(float))
502 return *reinterpret_cast<const uint32 *>(&m_s[index]);
504 return *reinterpret_cast<const uint64_t *>(&m_s[index]);
507 inline T get_x(void) const
511 inline T get_y(void) const
516 inline T get_z(void) const
521 inline T get_w(void) const
527 inline vec get_x_vector() const
529 return broadcast<0>();
531 inline vec get_y_vector() const
533 return broadcast<1>();
535 inline vec get_z_vector() const
537 return broadcast<2>();
539 inline vec get_w_vector() const
541 return broadcast<3>();
544 inline T get_component(uint i) const
549 inline vec &set_x(T v)
554 inline vec &set_y(T v)
560 inline vec &set_z(T v)
566 inline vec &set_w(T v)
573 inline const T *get_ptr() const
575 return reinterpret_cast<const T *>(&m_s[0]);
579 return reinterpret_cast<T *>(&m_s[0]);
582 inline vec as_point() const
589 inline vec as_dir() const
596 inline vec<2, T> select2(uint i, uint j) const
598 VOGL_ASSERT((i < N) && (j < N));
599 return vec<2, T>(m_s[i], m_s[j]);
602 inline vec<3, T> select3(uint i, uint j, uint k) const
604 VOGL_ASSERT((i < N) && (j < N) && (k < N));
605 return vec<3, T>(m_s[i], m_s[j], m_s[k]);
608 inline vec<4, T> select4(uint i, uint j, uint k, uint l) const
610 VOGL_ASSERT((i < N) && (j < N) && (k < N) && (l < N));
611 return vec<4, T>(m_s[i], m_s[j], m_s[k], m_s[l]);
614 inline bool is_dir() const
616 return m_s[N - 1] == 0;
618 inline bool is_vector() const
622 inline bool is_point() const
624 return m_s[N - 1] == 1;
627 inline vec project() const
631 result /= result[N - 1];
635 inline vec broadcast(unsigned i) const
637 return vec((*this)[i]);
641 inline vec broadcast() const
643 return vec((*this)[i]);
646 inline vec swizzle(uint i, uint j) const
648 return vec((*this)[i], (*this)[j]);
651 inline vec swizzle(uint i, uint j, uint k) const
653 return vec((*this)[i], (*this)[j], (*this)[k]);
656 inline vec swizzle(uint i, uint j, uint k, uint l) const
658 return vec((*this)[i], (*this)[j], (*this)[k], (*this)[l]);
661 inline vec operator-() const
664 for (uint i = 0; i < N; i++)
665 result.m_s[i] = -m_s[i];
669 inline vec operator+() const
674 inline vec &operator+=(const vec &other)
676 for (uint i = 0; i < N; i++)
677 m_s[i] += other.m_s[i];
681 inline vec &operator-=(const vec &other)
683 for (uint i = 0; i < N; i++)
684 m_s[i] -= other.m_s[i];
688 inline vec &operator*=(const vec &other)
690 for (uint i = 0; i < N; i++)
691 m_s[i] *= other.m_s[i];
695 inline vec &operator/=(const vec &other)
697 for (uint i = 0; i < N; i++)
698 m_s[i] /= other.m_s[i];
702 inline vec &operator*=(T s)
704 for (uint i = 0; i < N; i++)
709 inline vec &operator/=(T s)
711 for (uint i = 0; i < N; i++)
716 // component-wise multiply (not a dot product like in previous versions)
717 friend inline vec operator*(const vec &lhs, const vec &rhs)
719 return vec::mul_components(lhs, rhs);
722 friend inline vec operator*(const vec &lhs, T val)
725 for (uint i = 0; i < N; i++)
726 result.m_s[i] = lhs.m_s[i] * val;
730 friend inline vec operator*(T val, const vec &rhs)
733 for (uint i = 0; i < N; i++)
734 result.m_s[i] = val * rhs.m_s[i];
738 friend inline vec operator/(const vec &lhs, const vec &rhs)
741 for (uint i = 0; i < N; i++)
742 result.m_s[i] = lhs.m_s[i] / rhs.m_s[i];
746 friend inline vec operator/(const vec &lhs, T val)
749 for (uint i = 0; i < N; i++)
750 result.m_s[i] = lhs.m_s[i] / val;
754 friend inline vec operator+(const vec &lhs, const vec &rhs)
757 for (uint i = 0; i < N; i++)
758 result.m_s[i] = lhs.m_s[i] + rhs.m_s[i];
762 friend inline vec operator-(const vec &lhs, const vec &rhs)
765 for (uint i = 0; i < N; i++)
766 result.m_s[i] = lhs.m_s[i] - rhs.m_s[i];
770 static inline vec<3, T> cross2(const vec &a, const vec &b)
773 return vec<3, T>(0, 0, a[0] * b[1] - a[1] * b[0]);
776 inline vec<3, T> cross2(const vec &b) const
778 return cross2(*this, b);
781 static inline vec<3, T> cross3(const vec &a, const vec &b)
784 return vec<3, T>(a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]);
787 inline vec<3, T> cross3(const vec &b) const
789 return cross3(*this, b);
792 static inline vec<3, T> cross(const vec &a, const vec &b)
802 inline vec<3, T> cross(const vec &b) const
805 return cross(*this, b);
808 inline T dot(const vec &rhs) const
810 return dot(*this, rhs);
813 inline vec dot_vector(const vec &rhs) const
815 return vec(dot(*this, rhs));
818 static inline T dot(const vec &lhs, const vec &rhs)
820 T result = lhs.m_s[0] * rhs.m_s[0];
821 for (uint i = 1; i < N; i++)
822 result += lhs.m_s[i] * rhs.m_s[i];
826 inline T dot2(const vec &rhs) const
829 return m_s[0] * rhs.m_s[0] + m_s[1] * rhs.m_s[1];
832 inline T dot3(const vec &rhs) const
835 return m_s[0] * rhs.m_s[0] + m_s[1] * rhs.m_s[1] + m_s[2] * rhs.m_s[2];
838 inline T dot4(const vec &rhs) const
841 return m_s[0] * rhs.m_s[0] + m_s[1] * rhs.m_s[1] + m_s[2] * rhs.m_s[2] + m_s[3] * rhs.m_s[3];
844 inline T norm(void) const
846 T sum = m_s[0] * m_s[0];
847 for (uint i = 1; i < N; i++)
848 sum += m_s[i] * m_s[i];
852 inline T length(void) const
857 inline T squared_distance(const vec &rhs) const
860 for (uint i = 0; i < N; i++)
862 T d = m_s[i] - rhs.m_s[i];
868 inline T squared_distance(const vec &rhs, T early_out) const
871 for (uint i = 0; i < N; i++)
873 T d = m_s[i] - rhs.m_s[i];
875 if (dist2 > early_out)
881 inline T distance(const vec &rhs) const
884 for (uint i = 0; i < N; i++)
886 T d = m_s[i] - rhs.m_s[i];
892 inline vec inverse() const
895 for (uint i = 0; i < N; i++)
896 result[i] = m_s[i] ? (1.0f / m_s[i]) : 0;
900 // returns squared length (norm)
901 inline double normalize(const vec *pDefaultVec = NULL)
903 double n = m_s[0] * m_s[0];
904 for (uint i = 1; i < N; i++)
905 n += m_s[i] * m_s[i];
908 *this *= static_cast<T>(1.0f / sqrt(n));
909 else if (pDefaultVec)
910 *this = *pDefaultVec;
914 inline double normalize3(const vec *pDefaultVec = NULL)
918 double n = m_s[0] * m_s[0] + m_s[1] * m_s[1] + m_s[2] * m_s[2];
921 *this *= static_cast<T>((1.0f / sqrt(n)));
922 else if (pDefaultVec)
923 *this = *pDefaultVec;
927 inline vec &normalize_in_place(const vec *pDefaultVec = NULL)
929 normalize(pDefaultVec);
933 inline vec &normalize3_in_place(const vec *pDefaultVec = NULL)
935 normalize3(pDefaultVec);
939 inline vec get_normalized(const vec *pDefaultVec = NULL) const
942 result.normalize(pDefaultVec);
946 inline vec get_normalized3(const vec *pDefaultVec = NULL) const
949 result.normalize3(pDefaultVec);
953 inline vec &clamp(T l, T h)
955 for (uint i = 0; i < N; i++)
956 m_s[i] = static_cast<T>(math::clamp(m_s[i], l, h));
960 inline vec &clamp(const vec &l, const vec &h)
962 for (uint i = 0; i < N; i++)
963 m_s[i] = static_cast<T>(math::clamp(m_s[i], l[i], h[i]));
967 inline bool is_within_bounds(const vec &l, const vec &h) const
969 for (uint i = 0; i < N; i++)
970 if ((m_s[i] < l[i]) || (m_s[i] > h[i]))
976 inline bool is_within_bounds(T l, T h) const
978 for (uint i = 0; i < N; i++)
979 if ((m_s[i] < l) || (m_s[i] > h))
985 inline uint get_major_axis(void) const
989 for (uint i = 1; i < N; i++)
991 const T c = fabs(m_s[i]);
1001 inline uint get_minor_axis(void) const
1005 for (uint i = 1; i < N; i++)
1007 const T c = fabs(m_s[i]);
1017 inline void get_projection_axes(uint &u, uint &v) const
1019 const int axis = get_major_axis();
1020 if (m_s[axis] < 0.0f)
1022 v = math::next_wrap<uint>(axis, N);
1023 u = math::next_wrap<uint>(v, N);
1027 u = math::next_wrap<uint>(axis, N);
1028 v = math::next_wrap<uint>(u, N);
1032 inline T get_absolute_minimum(void) const
1034 T result = fabs(m_s[0]);
1035 for (uint i = 1; i < N; i++)
1036 result = math::minimum(result, fabs(m_s[i]));
1040 inline T get_absolute_maximum(void) const
1042 T result = fabs(m_s[0]);
1043 for (uint i = 1; i < N; i++)
1044 result = math::maximum(result, fabs(m_s[i]));
1048 inline T get_minimum(void) const
1051 for (uint i = 1; i < N; i++)
1052 result = math::minimum(result, m_s[i]);
1056 inline T get_maximum(void) const
1059 for (uint i = 1; i < N; i++)
1060 result = math::maximum(result, m_s[i]);
1064 inline vec &remove_unit_direction(const vec &dir)
1066 *this -= (dot(dir) * dir);
1070 inline vec get_remove_unit_direction(const vec &dir) const
1072 return *this - (dot(dir) * dir);
1075 inline bool all_less(const vec &b) const
1077 for (uint i = 0; i < N; i++)
1078 if (m_s[i] >= b.m_s[i])
1083 inline bool all_less_equal(const vec &b) const
1085 for (uint i = 0; i < N; i++)
1086 if (m_s[i] > b.m_s[i])
1091 inline bool all_greater(const vec &b) const
1093 for (uint i = 0; i < N; i++)
1094 if (m_s[i] <= b.m_s[i])
1099 inline bool all_greater_equal(const vec &b) const
1101 for (uint i = 0; i < N; i++)
1102 if (m_s[i] < b.m_s[i])
1107 inline vec negate_xyz() const
1117 for (uint i = 3; i < N; i++)
1123 inline vec &invert()
1125 for (uint i = 0; i < N; i++)
1127 m_s[i] = 1.0f / m_s[i];
1131 inline scalar_type perp_dot(const vec &b) const
1133 VOGL_ASSUME(N == 2);
1134 return m_s[0] * b.m_s[1] - m_s[1] * b.m_s[0];
1137 inline vec perp() const
1139 VOGL_ASSUME(N == 2);
1140 return vec(-m_s[1], m_s[0]);
1143 inline vec get_floor() const
1146 for (uint i = 0; i < N; i++)
1147 result[i] = floor(m_s[i]);
1151 inline vec get_ceil() const
1154 for (uint i = 0; i < N; i++)
1155 result[i] = ceil(m_s[i]);
1159 // static helper methods
1161 static inline vec mul_components(const vec &lhs, const vec &rhs)
1164 for (uint i = 0; i < N; i++)
1165 result[i] = lhs.m_s[i] * rhs.m_s[i];
1169 static inline vec mul_add_components(const vec &a, const vec &b, const vec &c)
1172 for (uint i = 0; i < N; i++)
1173 result[i] = a.m_s[i] * b.m_s[i] + c.m_s[i];
1177 static inline vec make_axis(uint i)
1185 static inline vec component_max(const vec &a, const vec &b)
1188 for (uint i = 0; i < N; i++)
1189 ret.m_s[i] = math::maximum(a.m_s[i], b.m_s[i]);
1193 static inline vec component_min(const vec &a, const vec &b)
1196 for (uint i = 0; i < N; i++)
1197 ret.m_s[i] = math::minimum(a.m_s[i], b.m_s[i]);
1201 static inline vec lerp(const vec &a, const vec &b, float t)
1204 for (uint i = 0; i < N; i++)
1205 ret.m_s[i] = a.m_s[i] + (b.m_s[i] - a.m_s[i]) * t;
1209 static inline bool equal_tol(const vec &a, const vec &b, float t)
1211 for (uint i = 0; i < N; i++)
1212 if (!math::equal_tol(a.m_s[i], b.m_s[i], t))
1217 inline bool equal_tol(const vec &b, float t) const
1219 return equal_tol(*this, b, t);
1222 static inline vec make_random(random &r, float l, float h)
1225 for (uint i = 0; i < N; i++)
1226 result[i] = r.frand(l, h);
1230 static inline vec make_random(fast_random &r, float l, float h)
1233 for (uint i = 0; i < N; i++)
1234 result[i] = r.frand(l, h);
1238 static inline vec make_random(random &r, const vec &l, const vec &h)
1241 for (uint i = 0; i < N; i++)
1242 result[i] = r.frand(l[i], h[i]);
1246 static inline vec make_random(fast_random &r, const vec &l, const vec &h)
1249 for (uint i = 0; i < N; i++)
1250 result[i] = r.frand(l[i], h[i]);
1258 typedef vec<1, double> vec1D;
1259 typedef vec<2, double> vec2D;
1260 typedef vec<3, double> vec3D;
1261 typedef vec<4, double> vec4D;
1263 typedef vec<1, float> vec1F;
1265 typedef vec<2, float> vec2F;
1266 typedef vogl::vector<vec2F> vec2F_array;
1268 typedef vec<3, float> vec3F;
1269 typedef vogl::vector<vec3F> vec3F_array;
1271 typedef vec<4, float> vec4F;
1272 typedef vogl::vector<vec4F> vec4F_array;
1274 typedef vec<2, uint> vec2U;
1275 typedef vec<2, int> vec2I;
1276 typedef vec<3, int> vec3I;
1277 typedef vec<4, int> vec4I;
1279 typedef vec<2, int16> vec2I16;
1280 typedef vec<3, int16> vec3I16;
1282 template <uint N, typename T>
1283 struct scalar_type<vec<N, T> >
1289 static inline void construct(vec<N, T> *p)
1291 VOGL_NOTE_UNUSED(p);
1293 static inline void construct(vec<N, T> *p, const vec<N, T> &init)
1295 memcpy(p, &init, sizeof(vec<N, T>));
1297 static inline void construct_array(vec<N, T> *p, uint n)
1299 VOGL_NOTE_UNUSED(p), VOGL_NOTE_UNUSED(n);
1301 static inline void destruct(vec<N, T> *p)
1303 VOGL_NOTE_UNUSED(p);
1305 static inline void destruct_array(vec<N, T> *p, uint n)
1307 VOGL_NOTE_UNUSED(p), VOGL_NOTE_UNUSED(n);