vector_math.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647
  1. // Licensed under GPLv2 or any later version
  2. // Refer to the license.txt file included.
  3. // Copyright 2014 Tony Wasserka
  4. // All rights reserved.
  5. //
  6. // Redistribution and use in source and binary forms, with or without
  7. // modification, are permitted provided that the following conditions are met:
  8. //
  9. // * Redistributions of source code must retain the above copyright
  10. // notice, this list of conditions and the following disclaimer.
  11. // * Redistributions in binary form must reproduce the above copyright
  12. // notice, this list of conditions and the following disclaimer in the
  13. // documentation and/or other materials provided with the distribution.
  14. // * Neither the name of the owner nor the names of its contributors may
  15. // be used to endorse or promote products derived from this software
  16. // without specific prior written permission.
  17. //
  18. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  21. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  22. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  23. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  24. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  28. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. #pragma once
  30. #include <cmath>
  31. #include <type_traits>
  32. namespace Math {
  33. template<typename T> class Vec2;
  34. template<typename T> class Vec3;
  35. template<typename T> class Vec4;
  36. template<typename T>
  37. static inline Vec2<T> MakeVec(const T& x, const T& y);
  38. template<typename T>
  39. static inline Vec3<T> MakeVec(const T& x, const T& y, const T& z);
  40. template<typename T>
  41. static inline Vec4<T> MakeVec(const T& x, const T& y, const T& z, const T& w);
  42. template<typename T>
  43. class Vec2 {
  44. public:
  45. T x;
  46. T y;
  47. T* AsArray() { return &x; }
  48. Vec2() = default;
  49. Vec2(const T a[2]) : x(a[0]), y(a[1]) {}
  50. Vec2(const T& _x, const T& _y) : x(_x), y(_y) {}
  51. template<typename T2>
  52. Vec2<T2> Cast() const {
  53. return Vec2<T2>((T2)x, (T2)y);
  54. }
  55. static Vec2 AssignToAll(const T& f)
  56. {
  57. return Vec2<T>(f, f);
  58. }
  59. void Write(T a[2])
  60. {
  61. a[0] = x; a[1] = y;
  62. }
  63. Vec2<decltype(T{}+T{})> operator +(const Vec2& other) const
  64. {
  65. return MakeVec(x+other.x, y+other.y);
  66. }
  67. void operator += (const Vec2 &other)
  68. {
  69. x+=other.x; y+=other.y;
  70. }
  71. Vec2<decltype(T{}-T{})> operator -(const Vec2& other) const
  72. {
  73. return MakeVec(x-other.x, y-other.y);
  74. }
  75. void operator -= (const Vec2& other)
  76. {
  77. x-=other.x; y-=other.y;
  78. }
  79. template<typename Q = T,class = typename std::enable_if<std::is_signed<Q>::value>::type>
  80. Vec2<decltype(-T{})> operator -() const
  81. {
  82. return MakeVec(-x,-y);
  83. }
  84. Vec2<decltype(T{}*T{})> operator * (const Vec2& other) const
  85. {
  86. return MakeVec(x*other.x, y*other.y);
  87. }
  88. template<typename V>
  89. Vec2<decltype(T{}*V{})> operator * (const V& f) const
  90. {
  91. return MakeVec(x*f,y*f);
  92. }
  93. template<typename V>
  94. void operator *= (const V& f)
  95. {
  96. x*=f; y*=f;
  97. }
  98. template<typename V>
  99. Vec2<decltype(T{}/V{})> operator / (const V& f) const
  100. {
  101. return MakeVec(x/f,y/f);
  102. }
  103. template<typename V>
  104. void operator /= (const V& f)
  105. {
  106. *this = *this / f;
  107. }
  108. T Length2() const
  109. {
  110. return x*x + y*y;
  111. }
  112. // Only implemented for T=float
  113. float Length() const;
  114. void SetLength(const float l);
  115. Vec2 WithLength(const float l) const;
  116. float Distance2To(Vec2 &other);
  117. Vec2 Normalized() const;
  118. float Normalize(); // returns the previous length, which is often useful
  119. T& operator [] (int i) //allow vector[1] = 3 (vector.y=3)
  120. {
  121. return *((&x) + i);
  122. }
  123. T operator [] (const int i) const
  124. {
  125. return *((&x) + i);
  126. }
  127. void SetZero()
  128. {
  129. x=0; y=0;
  130. }
  131. // Common aliases: UV (texel coordinates), ST (texture coordinates)
  132. T& u() { return x; }
  133. T& v() { return y; }
  134. T& s() { return x; }
  135. T& t() { return y; }
  136. const T& u() const { return x; }
  137. const T& v() const { return y; }
  138. const T& s() const { return x; }
  139. const T& t() const { return y; }
  140. // swizzlers - create a subvector of specific components
  141. const Vec2 yx() const { return Vec2(y, x); }
  142. const Vec2 vu() const { return Vec2(y, x); }
  143. const Vec2 ts() const { return Vec2(y, x); }
  144. };
  145. template<typename T, typename V>
  146. Vec2<T> operator * (const V& f, const Vec2<T>& vec)
  147. {
  148. return Vec2<T>(f*vec.x,f*vec.y);
  149. }
  150. typedef Vec2<float> Vec2f;
  151. template<typename T>
  152. class Vec3
  153. {
  154. public:
  155. T x;
  156. T y;
  157. T z;
  158. T* AsArray() { return &x; }
  159. Vec3() = default;
  160. Vec3(const T a[3]) : x(a[0]), y(a[1]), z(a[2]) {}
  161. Vec3(const T& _x, const T& _y, const T& _z) : x(_x), y(_y), z(_z) {}
  162. template<typename T2>
  163. Vec3<T2> Cast() const {
  164. return MakeVec<T2>((T2)x, (T2)y, (T2)z);
  165. }
  166. // Only implemented for T=int and T=float
  167. static Vec3 FromRGB(unsigned int rgb);
  168. unsigned int ToRGB() const; // alpha bits set to zero
  169. static Vec3 AssignToAll(const T& f)
  170. {
  171. return MakeVec(f, f, f);
  172. }
  173. void Write(T a[3])
  174. {
  175. a[0] = x; a[1] = y; a[2] = z;
  176. }
  177. Vec3<decltype(T{}+T{})> operator +(const Vec3 &other) const
  178. {
  179. return MakeVec(x+other.x, y+other.y, z+other.z);
  180. }
  181. void operator += (const Vec3 &other)
  182. {
  183. x+=other.x; y+=other.y; z+=other.z;
  184. }
  185. Vec3<decltype(T{}-T{})> operator -(const Vec3 &other) const
  186. {
  187. return MakeVec(x-other.x, y-other.y, z-other.z);
  188. }
  189. void operator -= (const Vec3 &other)
  190. {
  191. x-=other.x; y-=other.y; z-=other.z;
  192. }
  193. template<typename Q = T,class = typename std::enable_if<std::is_signed<Q>::value>::type>
  194. Vec3<decltype(-T{})> operator -() const
  195. {
  196. return MakeVec(-x,-y,-z);
  197. }
  198. Vec3<decltype(T{}*T{})> operator * (const Vec3 &other) const
  199. {
  200. return MakeVec(x*other.x, y*other.y, z*other.z);
  201. }
  202. template<typename V>
  203. Vec3<decltype(T{}*V{})> operator * (const V& f) const
  204. {
  205. return MakeVec(x*f,y*f,z*f);
  206. }
  207. template<typename V>
  208. void operator *= (const V& f)
  209. {
  210. x*=f; y*=f; z*=f;
  211. }
  212. template<typename V>
  213. Vec3<decltype(T{}/V{})> operator / (const V& f) const
  214. {
  215. return MakeVec(x/f,y/f,z/f);
  216. }
  217. template<typename V>
  218. void operator /= (const V& f)
  219. {
  220. *this = *this / f;
  221. }
  222. T Length2() const
  223. {
  224. return x*x + y*y + z*z;
  225. }
  226. // Only implemented for T=float
  227. float Length() const;
  228. void SetLength(const float l);
  229. Vec3 WithLength(const float l) const;
  230. float Distance2To(Vec3 &other);
  231. Vec3 Normalized() const;
  232. float Normalize(); // returns the previous length, which is often useful
  233. T& operator [] (int i) //allow vector[2] = 3 (vector.z=3)
  234. {
  235. return *((&x) + i);
  236. }
  237. T operator [] (const int i) const
  238. {
  239. return *((&x) + i);
  240. }
  241. void SetZero()
  242. {
  243. x=0; y=0; z=0;
  244. }
  245. // Common aliases: UVW (texel coordinates), RGB (colors), STQ (texture coordinates)
  246. T& u() { return x; }
  247. T& v() { return y; }
  248. T& w() { return z; }
  249. T& r() { return x; }
  250. T& g() { return y; }
  251. T& b() { return z; }
  252. T& s() { return x; }
  253. T& t() { return y; }
  254. T& q() { return z; }
  255. const T& u() const { return x; }
  256. const T& v() const { return y; }
  257. const T& w() const { return z; }
  258. const T& r() const { return x; }
  259. const T& g() const { return y; }
  260. const T& b() const { return z; }
  261. const T& s() const { return x; }
  262. const T& t() const { return y; }
  263. const T& q() const { return z; }
  264. // swizzlers - create a subvector of specific components
  265. // e.g. Vec2 uv() { return Vec2(x,y); }
  266. // _DEFINE_SWIZZLER2 defines a single such function, DEFINE_SWIZZLER2 defines all of them for all component names (x<->r) and permutations (xy<->yx)
  267. #define _DEFINE_SWIZZLER2(a, b, name) const Vec2<T> name() const { return Vec2<T>(a, b); }
  268. #define DEFINE_SWIZZLER2(a, b, a2, b2, a3, b3, a4, b4) \
  269. _DEFINE_SWIZZLER2(a, b, a##b); \
  270. _DEFINE_SWIZZLER2(a, b, a2##b2); \
  271. _DEFINE_SWIZZLER2(a, b, a3##b3); \
  272. _DEFINE_SWIZZLER2(a, b, a4##b4); \
  273. _DEFINE_SWIZZLER2(b, a, b##a); \
  274. _DEFINE_SWIZZLER2(b, a, b2##a2); \
  275. _DEFINE_SWIZZLER2(b, a, b3##a3); \
  276. _DEFINE_SWIZZLER2(b, a, b4##a4)
  277. DEFINE_SWIZZLER2(x, y, r, g, u, v, s, t);
  278. DEFINE_SWIZZLER2(x, z, r, b, u, w, s, q);
  279. DEFINE_SWIZZLER2(y, z, g, b, v, w, t, q);
  280. #undef DEFINE_SWIZZLER2
  281. #undef _DEFINE_SWIZZLER2
  282. };
  283. template<typename T, typename V>
  284. Vec3<T> operator * (const V& f, const Vec3<T>& vec)
  285. {
  286. return Vec3<T>(f*vec.x,f*vec.y,f*vec.z);
  287. }
  288. template<>
  289. inline float Vec3<float>::Length() const {
  290. return std::sqrt(x * x + y * y + z * z);
  291. }
  292. template<>
  293. inline Vec3<float> Vec3<float>::Normalized() const {
  294. return *this / Length();
  295. }
  296. typedef Vec3<float> Vec3f;
  297. template<typename T>
  298. class Vec4
  299. {
  300. public:
  301. T x;
  302. T y;
  303. T z;
  304. T w;
  305. T* AsArray() { return &x; }
  306. Vec4() = default;
  307. Vec4(const T a[4]) : x(a[0]), y(a[1]), z(a[2]), w(a[3]) {}
  308. Vec4(const T& _x, const T& _y, const T& _z, const T& _w) : x(_x), y(_y), z(_z), w(_w) {}
  309. template<typename T2>
  310. Vec4<T2> Cast() const {
  311. return Vec4<T2>((T2)x, (T2)y, (T2)z, (T2)w);
  312. }
  313. // Only implemented for T=int and T=float
  314. static Vec4 FromRGBA(unsigned int rgba);
  315. unsigned int ToRGBA() const;
  316. static Vec4 AssignToAll(const T& f) {
  317. return Vec4<T>(f, f, f, f);
  318. }
  319. void Write(T a[4])
  320. {
  321. a[0] = x; a[1] = y; a[2] = z; a[3] = w;
  322. }
  323. Vec4<decltype(T{}+T{})> operator +(const Vec4& other) const
  324. {
  325. return MakeVec(x+other.x, y+other.y, z+other.z, w+other.w);
  326. }
  327. void operator += (const Vec4& other)
  328. {
  329. x+=other.x; y+=other.y; z+=other.z; w+=other.w;
  330. }
  331. Vec4<decltype(T{}-T{})> operator -(const Vec4 &other) const
  332. {
  333. return MakeVec(x-other.x, y-other.y, z-other.z, w-other.w);
  334. }
  335. void operator -= (const Vec4 &other)
  336. {
  337. x-=other.x; y-=other.y; z-=other.z; w-=other.w;
  338. }
  339. template<typename Q = T,class = typename std::enable_if<std::is_signed<Q>::value>::type>
  340. Vec4<decltype(-T{})> operator -() const
  341. {
  342. return MakeVec(-x,-y,-z,-w);
  343. }
  344. Vec4<decltype(T{}*T{})> operator * (const Vec4 &other) const
  345. {
  346. return MakeVec(x*other.x, y*other.y, z*other.z, w*other.w);
  347. }
  348. template<typename V>
  349. Vec4<decltype(T{}*V{})> operator * (const V& f) const
  350. {
  351. return MakeVec(x*f,y*f,z*f,w*f);
  352. }
  353. template<typename V>
  354. void operator *= (const V& f)
  355. {
  356. x*=f; y*=f; z*=f; w*=f;
  357. }
  358. template<typename V>
  359. Vec4<decltype(T{}/V{})> operator / (const V& f) const
  360. {
  361. return MakeVec(x/f,y/f,z/f,w/f);
  362. }
  363. template<typename V>
  364. void operator /= (const V& f)
  365. {
  366. *this = *this / f;
  367. }
  368. T Length2() const
  369. {
  370. return x*x + y*y + z*z + w*w;
  371. }
  372. // Only implemented for T=float
  373. float Length() const;
  374. void SetLength(const float l);
  375. Vec4 WithLength(const float l) const;
  376. float Distance2To(Vec4 &other);
  377. Vec4 Normalized() const;
  378. float Normalize(); // returns the previous length, which is often useful
  379. T& operator [] (int i) //allow vector[2] = 3 (vector.z=3)
  380. {
  381. return *((&x) + i);
  382. }
  383. T operator [] (const int i) const
  384. {
  385. return *((&x) + i);
  386. }
  387. void SetZero()
  388. {
  389. x = 0;
  390. y = 0;
  391. z = 0;
  392. w = 0;
  393. }
  394. // Common alias: RGBA (colors)
  395. T& r() { return x; }
  396. T& g() { return y; }
  397. T& b() { return z; }
  398. T& a() { return w; }
  399. const T& r() const { return x; }
  400. const T& g() const { return y; }
  401. const T& b() const { return z; }
  402. const T& a() const { return w; }
  403. // Swizzlers - Create a subvector of specific components
  404. // e.g. Vec2 uv() { return Vec2(x,y); }
  405. // _DEFINE_SWIZZLER2 defines a single such function
  406. // DEFINE_SWIZZLER2_COMP1 defines one-component functions for all component names (x<->r)
  407. // DEFINE_SWIZZLER2_COMP2 defines two component functions for all component names (x<->r) and permutations (xy<->yx)
  408. #define _DEFINE_SWIZZLER2(a, b, name) const Vec2<T> name() const { return Vec2<T>(a, b); }
  409. #define DEFINE_SWIZZLER2_COMP1(a, a2) \
  410. _DEFINE_SWIZZLER2(a, a, a##a); \
  411. _DEFINE_SWIZZLER2(a, a, a2##a2)
  412. #define DEFINE_SWIZZLER2_COMP2(a, b, a2, b2) \
  413. _DEFINE_SWIZZLER2(a, b, a##b); \
  414. _DEFINE_SWIZZLER2(a, b, a2##b2); \
  415. _DEFINE_SWIZZLER2(b, a, b##a); \
  416. _DEFINE_SWIZZLER2(b, a, b2##a2)
  417. DEFINE_SWIZZLER2_COMP2(x, y, r, g);
  418. DEFINE_SWIZZLER2_COMP2(x, z, r, b);
  419. DEFINE_SWIZZLER2_COMP2(x, w, r, a);
  420. DEFINE_SWIZZLER2_COMP2(y, z, g, b);
  421. DEFINE_SWIZZLER2_COMP2(y, w, g, a);
  422. DEFINE_SWIZZLER2_COMP2(z, w, b, a);
  423. DEFINE_SWIZZLER2_COMP1(x, r);
  424. DEFINE_SWIZZLER2_COMP1(y, g);
  425. DEFINE_SWIZZLER2_COMP1(z, b);
  426. DEFINE_SWIZZLER2_COMP1(w, a);
  427. #undef DEFINE_SWIZZLER2_COMP1
  428. #undef DEFINE_SWIZZLER2_COMP2
  429. #undef _DEFINE_SWIZZLER2
  430. #define _DEFINE_SWIZZLER3(a, b, c, name) const Vec3<T> name() const { return Vec3<T>(a, b, c); }
  431. #define DEFINE_SWIZZLER3_COMP1(a, a2) \
  432. _DEFINE_SWIZZLER3(a, a, a, a##a##a); \
  433. _DEFINE_SWIZZLER3(a, a, a, a2##a2##a2)
  434. #define DEFINE_SWIZZLER3_COMP3(a, b, c, a2, b2, c2) \
  435. _DEFINE_SWIZZLER3(a, b, c, a##b##c); \
  436. _DEFINE_SWIZZLER3(a, c, b, a##c##b); \
  437. _DEFINE_SWIZZLER3(b, a, c, b##a##c); \
  438. _DEFINE_SWIZZLER3(b, c, a, b##c##a); \
  439. _DEFINE_SWIZZLER3(c, a, b, c##a##b); \
  440. _DEFINE_SWIZZLER3(c, b, a, c##b##a); \
  441. _DEFINE_SWIZZLER3(a, b, c, a2##b2##c2); \
  442. _DEFINE_SWIZZLER3(a, c, b, a2##c2##b2); \
  443. _DEFINE_SWIZZLER3(b, a, c, b2##a2##c2); \
  444. _DEFINE_SWIZZLER3(b, c, a, b2##c2##a2); \
  445. _DEFINE_SWIZZLER3(c, a, b, c2##a2##b2); \
  446. _DEFINE_SWIZZLER3(c, b, a, c2##b2##a2)
  447. DEFINE_SWIZZLER3_COMP3(x, y, z, r, g, b);
  448. DEFINE_SWIZZLER3_COMP3(x, y, w, r, g, a);
  449. DEFINE_SWIZZLER3_COMP3(x, z, w, r, b, a);
  450. DEFINE_SWIZZLER3_COMP3(y, z, w, g, b, a);
  451. DEFINE_SWIZZLER3_COMP1(x, r);
  452. DEFINE_SWIZZLER3_COMP1(y, g);
  453. DEFINE_SWIZZLER3_COMP1(z, b);
  454. DEFINE_SWIZZLER3_COMP1(w, a);
  455. #undef DEFINE_SWIZZLER3_COMP1
  456. #undef DEFINE_SWIZZLER3_COMP3
  457. #undef _DEFINE_SWIZZLER3
  458. };
  459. template<typename T, typename V>
  460. Vec4<decltype(V{}*T{})> operator * (const V& f, const Vec4<T>& vec)
  461. {
  462. return MakeVec(f*vec.x,f*vec.y,f*vec.z,f*vec.w);
  463. }
  464. typedef Vec4<float> Vec4f;
  465. template<typename T>
  466. static inline decltype(T{}*T{}+T{}*T{}) Dot(const Vec2<T>& a, const Vec2<T>& b)
  467. {
  468. return a.x*b.x + a.y*b.y;
  469. }
  470. template<typename T>
  471. static inline decltype(T{}*T{}+T{}*T{}) Dot(const Vec3<T>& a, const Vec3<T>& b)
  472. {
  473. return a.x*b.x + a.y*b.y + a.z*b.z;
  474. }
  475. template<typename T>
  476. static inline decltype(T{}*T{}+T{}*T{}) Dot(const Vec4<T>& a, const Vec4<T>& b)
  477. {
  478. return a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w;
  479. }
  480. template<typename T>
  481. static inline Vec3<decltype(T{}*T{}-T{}*T{})> Cross(const Vec3<T>& a, const Vec3<T>& b)
  482. {
  483. return MakeVec(a.y*b.z-a.z*b.y, a.z*b.x-a.x*b.z, a.x*b.y-a.y*b.x);
  484. }
  485. // linear interpolation via float: 0.0=begin, 1.0=end
  486. template<typename X>
  487. static inline decltype(X{}*float{}+X{}*float{}) Lerp(const X& begin, const X& end, const float t)
  488. {
  489. return begin*(1.f-t) + end*t;
  490. }
  491. // linear interpolation via int: 0=begin, base=end
  492. template<typename X, int base>
  493. static inline decltype((X{}*int{}+X{}*int{}) / base) LerpInt(const X& begin, const X& end, const int t)
  494. {
  495. return (begin*(base-t) + end*t) / base;
  496. }
  497. // Utility vector factories
  498. template<typename T>
  499. static inline Vec2<T> MakeVec(const T& x, const T& y)
  500. {
  501. return Vec2<T>{x, y};
  502. }
  503. template<typename T>
  504. static inline Vec3<T> MakeVec(const T& x, const T& y, const T& z)
  505. {
  506. return Vec3<T>{x, y, z};
  507. }
  508. template<typename T>
  509. static inline Vec4<T> MakeVec(const T& x, const T& y, const Vec2<T>& zw)
  510. {
  511. return MakeVec(x, y, zw[0], zw[1]);
  512. }
  513. template<typename T>
  514. static inline Vec3<T> MakeVec(const Vec2<T>& xy, const T& z)
  515. {
  516. return MakeVec(xy[0], xy[1], z);
  517. }
  518. template<typename T>
  519. static inline Vec3<T> MakeVec(const T& x, const Vec2<T>& yz)
  520. {
  521. return MakeVec(x, yz[0], yz[1]);
  522. }
  523. template<typename T>
  524. static inline Vec4<T> MakeVec(const T& x, const T& y, const T& z, const T& w)
  525. {
  526. return Vec4<T>{x, y, z, w};
  527. }
  528. template<typename T>
  529. static inline Vec4<T> MakeVec(const Vec2<T>& xy, const T& z, const T& w)
  530. {
  531. return MakeVec(xy[0], xy[1], z, w);
  532. }
  533. template<typename T>
  534. static inline Vec4<T> MakeVec(const T& x, const Vec2<T>& yz, const T& w)
  535. {
  536. return MakeVec(x, yz[0], yz[1], w);
  537. }
  538. // NOTE: This has priority over "Vec2<Vec2<T>> MakeVec(const Vec2<T>& x, const Vec2<T>& y)".
  539. // Even if someone wanted to use an odd object like Vec2<Vec2<T>>, the compiler would error
  540. // out soon enough due to misuse of the returned structure.
  541. template<typename T>
  542. static inline Vec4<T> MakeVec(const Vec2<T>& xy, const Vec2<T>& zw)
  543. {
  544. return MakeVec(xy[0], xy[1], zw[0], zw[1]);
  545. }
  546. template<typename T>
  547. static inline Vec4<T> MakeVec(const Vec3<T>& xyz, const T& w)
  548. {
  549. return MakeVec(xyz[0], xyz[1], xyz[2], w);
  550. }
  551. template<typename T>
  552. static inline Vec4<T> MakeVec(const T& x, const Vec3<T>& yzw)
  553. {
  554. return MakeVec(x, yzw[0], yzw[1], yzw[2]);
  555. }
  556. } // namespace