CUGL 1.1
Cornell University Game Library
CUVec4.h
1 //
2 // CUVec4.h
3 // Cornell University Game Library (CUGL)
4 //
5 // This module provides support for a 4d vector. It has support for basic
6 // arithmetic, as well as conversions to color formats. It also has
7 // homogenous vector support for Vec3.
8 //
9 // Because math objects are intended to be on the stack, we do not provide
10 // any shared pointer support in this class.
11 //
12 // This module is based on an original file from GamePlay3D: http://gameplay3d.org.
13 // It has been modified to support the CUGL framework.
14 //
15 // CUGL zlib License:
16 // This software is provided 'as-is', without any express or implied
17 // warranty. In no event will the authors be held liable for any damages
18 // arising from the use of this software.
19 //
20 // Permission is granted to anyone to use this software for any purpose,
21 // including commercial applications, and to alter it and redistribute it
22 // freely, subject to the following restrictions:
23 //
24 // 1. The origin of this software must not be misrepresented; you must not
25 // claim that you wrote the original software. If you use this software
26 // in a product, an acknowledgment in the product documentation would be
27 // appreciated but is not required.
28 //
29 // 2. Altered source versions must be plainly marked as such, and must not
30 // be misrepresented as being the original software.
31 //
32 // 3. This notice may not be removed or altered from any source distribution.
33 //
34 // Author: Walker White
35 // Version: 5/30/16
36 
37 #ifndef __CU_VEC4_H__
38 #define __CU_VEC4_H__
39 
40 // Vectorizaton support
41 #ifdef CU_MATH_VECTOR_APPLE
42  // Need this hack, because Apple dumps Size/Rect into empty namespace
43  #define VIMAGE_H
44  #include <Accelerate/Accelerate.h>
45 #endif
46 #ifdef CU_MATH_VECTOR_SSE
47  #include <xmmintrin.h>
48 #endif
49 
50 #include <math.h>
51 #include <functional>
52 #include "CUMathBase.h"
53 #include "CURect.h"
54 
55 namespace cugl {
56 
57 // Forward reference for conversions
58 class Color4;
59 class Color4f;
60 class Vec2;
61 class Vec3;
62 
73 class Vec4 {
74 
75 #pragma mark Values
76 public:
77 #if defined CU_MATH_VECTOR_APPLE
78  union {
79  struct {
81  float x;
83  float y;
85  float z;
87  float w;
88  };
89  vFloat v;
90  };
91 #elif defined CU_MATH_VECTOR_SSE
92  __declspec(align(16)) union {
93  struct {
95  float x;
97  float y;
99  float z;
101  float w;
102  };
103  __m128 v;
104  };
105 #else
106 
107  float x;
109  float y;
111  float z;
113  float w;
114 #endif
115 
117  static const Vec4 ZERO;
119  static const Vec4 ONE;
121  static const Vec4 UNIT_X;
123  static const Vec4 UNIT_Y;
125  static const Vec4 UNIT_Z;
127  static const Vec4 UNIT_W;
128 
129  // Homogenous constants
131  static const Vec4 HOMOG_ORIGIN;
133  static const Vec4 HOMOG_X;
135  static const Vec4 HOMOG_Y;
137  static const Vec4 HOMOG_Z;
138 
139 #pragma mark -
140 #pragma mark Constructors
141 public:
145  Vec4() : x(0), y(0), z(0), w(0) {}
146 
155  Vec4(float x, float y, float z, float w) {
156  this->x = x; this->y = y; this->z = z; this->w = w;
157  }
158 
166  Vec4(const float* array) {
167 #if defined CU_MATH_VECTOR_APPLE
168  v = *((vFloat*)array);
169 #else
170  x = array[0]; y = array[1]; z = array[2]; w = array[3];
171 #endif
172  }
173 
180  Vec4(const Vec4& p1, const Vec4& p2) {
181 #if defined CU_MATH_VECTOR_APPLE
182  v = p2.v-p1.v;
183 #else
184  x = p2.x-p1.x; y = p2.y-p1.y; z = p2.z-p1.z; w = p2.w-p1.w;
185 #endif
186  }
187 
188 
189 #pragma mark -
190 #pragma mark Setters
191 
200  Vec4& operator=(const float* array) {
201  return set(array);
202  }
203 
214  Vec4& set(float x, float y, float z, float w) {
215  this->x = x; this->y = y; this->z = z; this->w = w;
216  return *this;
217  }
218 
228  Vec4& set(const float* array) {
229 #if defined CU_MATH_VECTOR_APPLE
230  v = *((vFloat*)array);
231 #else
232  x = array[0]; y = array[1]; z = array[2]; w = array[3];
233 #endif
234  return *this;
235  }
236 
244  Vec4& set(const Vec4& v) {
245 #if defined CU_MATH_VECTOR_APPLE
246  this->v = v.v;
247 #else
248  x = v.x; y = v.y; z = v.z; w = v.w;
249 #endif
250  return *this;
251  }
252 
261  Vec4& set(const Vec4& p1, const Vec4& p2) {
262 #if defined CU_MATH_VECTOR_APPLE
263  v = p2.v-p1.v;
264 #else
265  x = p2.x-p1.x; y = p2.y-p1.y; z = p2.z-p1.z; w = p2.w-p1.w;
266 #endif
267  return *this;
268  }
269 
276  x = y = z = w = 0;
277  return *this;
278  }
279 
280 
281 #pragma mark -
282 #pragma mark Static Arithmetic
283 
293  static Vec4* clamp(const Vec4& v, const Vec4& min, const Vec4& max, Vec4* dst);
294 
310  static float angle(const Vec4& v1, const Vec4& v2);
311 
321  static Vec4* add(const Vec4& v1, const Vec4& v2, Vec4* dst);
322 
334  static Vec4* subtract(const Vec4& v1, const Vec4& v2, Vec4* dst);
335 
347  static Vec4* scale(const Vec4& v, float s, Vec4* dst);
348 
360  static Vec4* scale(const Vec4& v1, const Vec4& v2, Vec4* dst);
361 
373  static Vec4* divide(const Vec4& v, float s, Vec4* dst);
374 
386  static Vec4* divide(const Vec4& v1, const Vec4& v2, Vec4* dst);
387 
400  static Vec4* reciprocate(const Vec4& v, Vec4* dst);
401 
410  static Vec4* negate(const Vec4& v, Vec4* dst);
411 
412 
413 #pragma mark -
414 #pragma mark Arithmetic
415 
423  Vec4& clamp(const Vec4& min, const Vec4& max);
424 
435  Vec4 getClamp(const Vec4& min, const Vec4& max) const {
436  return Vec4(clampf(x,min.x,max.x), clampf(y,min.y,max.y),
437  clampf(z,min.z,max.z), clampf(w,min.w,max.w));
438  }
439 
447  Vec4& add(const Vec4& v) {
448 #if defined CU_MATH_VECTOR_APPLE
449  this->v += v.v;
450 #else
451  x += v.x; y += v.y; z += v.z; w += v.w;
452 #endif
453  return *this;
454  }
455 
466  Vec4& add(float x, float y, float z, float w) {
467  this->x += x; this->y += y; this->z += z; this->w += w;
468  return *this;
469  }
470 
478  Vec4& subtract(const Vec4& v) {
479 #if defined CU_MATH_VECTOR_APPLE
480  this->v -= v.v;
481 #else
482  x -= v.x; y -= v.y; z -= v.z; w -= v.w;
483 #endif
484  return *this;
485  }
486 
497  Vec4& subtract(float x, float y, float z, float w) {
498  this->x -= x; this->y -= y; this->z -= z; this->w -= w;
499  return *this;
500  }
501 
509  Vec4& scale(float s) {
510 #if defined CU_MATH_VECTOR_APPLE
511  vSscal(4, s, &v);
512 #else
513  x *= s; y *= s; z *= s; w *= s;
514 #endif
515  return *this;
516  }
517 
528  Vec4& scale(float sx, float sy, float sz, float sw) {
529  x *= sx; y *= sy; z *= sz; w *= sw;
530  return *this;
531  }
532 
540  Vec4& scale(const Vec4& v) {
541 #if defined CU_MATH_VECTOR_APPLE
542  this->v *= v.v;
543 #else
544  x *= v.x; y *= v.y; z *= v.z; w *= v.w;
545 #endif
546  return *this;
547  }
548 
556  Vec4& divide(float s);
557 
568  Vec4& divide(float sx, float sy, float sz, float sw);
569 
579  Vec4& divide(const Vec4& v);
580 
587  x = -x; y = -y; z = -z; w = -w;
588  return *this;
589  }
590 
601  x = 1.0f/x; y = 1.0f/y; z = 1.0f/z; w = 1.0f/w;
602  return *this;
603  }
604 
612  Vec4 getNegation() const {
613  Vec4 result(*this);
614  return result.negate();
615  }
616 
628  Vec4 getReciprocal() const {
629  Vec4 result(*this);
630  return result.reciprocate();
631  }
632 
643  Vec4& map(std::function<float(float)> func) {
644  x = func(x); y = func(y); z = func(z); w = func(w);
645  return *this;
646  }
647 
658  Vec4 getMap(std::function<float(float)> func) const {
659  return Vec4(func(x), func(y), func(z), func(w));
660  }
661 
662 
663 #pragma mark -
664 #pragma mark Operators
665 
672  Vec4& operator+=(const Vec4& v) {
673  return add(v);
674  }
675 
683  Vec4& operator-=(const Vec4& v) {
684  return subtract(v);
685  }
686 
694  Vec4& operator*=(float s) {
695  return scale(s);
696  }
697 
705  Vec4& operator*=(const Vec4& v) {
706  return scale(v);
707  }
708 
716  Vec4& operator/=(float s) {
717  return divide(s);
718  }
719 
729  Vec4& operator/=(const Vec4& v) {
730  return divide(v);
731  }
732 
742  const Vec4 operator+(const Vec4& v) const {
743  Vec4 result(*this);
744  return result.add(v);
745  }
746 
756  const Vec4 operator-(const Vec4& v) const {
757  Vec4 result(*this);
758  return result.subtract(v);
759  }
760 
768  const Vec4 operator-() const {
769  Vec4 result(*this);
770  return result.negate();
771  }
772 
782  const Vec4 operator*(float s) const {
783  Vec4 result(*this);
784  return result.scale(s);
785  }
786 
797  const Vec4 operator*(const Vec4& v) const {
798  Vec4 result(*this);
799  return result.scale(v);
800  }
801 
811  const Vec4 operator/(float s) const {
812  Vec4 result(*this);
813  return result.divide(s);
814  }
815 
826  const Vec4 operator/(const Vec4& v) const {
827  Vec4 result(*this);
828  return result.divide(v);
829  }
830 
831 
832 #pragma mark -
833 #pragma mark Comparisons
834 
845  bool operator<(const Vec4& v) const {
846  return (x == v.x ? (y == v.y ? (z == v.z ? w < v.w : z < v.z) : y < v.y) : x < v.x);
847  }
848 
860  bool operator<=(const Vec4& v) const {
861  return (x == v.x ? (y == v.y ? (z == v.z ? w <= v.w : z <= v.z) : y <= v.y) : x <= v.x);
862  }
863 
875  bool operator>(const Vec4& v) const {
876  return (x == v.x ? (y == v.y ? (z == v.z ? w > v.w : z > v.z) : y > v.y) : x > v.x);
877  }
878 
890  bool operator>=(const Vec4& v) const {
891  return (x == v.x ? (y == v.y ? (z == v.z ? w >= v.w : z >= v.z) : y >= v.y) : x >= v.x);
892  }
893 
904  bool operator==(const Vec4& v) const {
905  return x == v.x && y == v.y && z == v.z && w == v.w;
906  }
907 
918  bool operator!=(const Vec4& v) const {
919  return x != v.x || y != v.y || z != v.z || w != v.w;
920  }
921 
932  bool under(const Vec4& v) const {
933  return x <= v.x && y <= v.y && z <= v.z && w <= v.w;
934  }
935 
946  bool over(const Vec4& v) const {
947  return x >= v.x && y >= v.y && z >= v.z && w >= v.w;
948  }
949 
961  bool equals(const Vec4& v, float variance=CU_MATH_EPSILON) const {
962  return distanceSquared(v) <= variance*variance;
963  }
964 
965 
966 #pragma mark -
967 #pragma mark Linear Attributes
968 
973  bool isZero() const {
974  return x == 0.0f && y == 0.0f && z == 0.0f && w == 0.0f;
975  }
976 
984  bool isNearZero(float variance=CU_MATH_EPSILON) const {
985  return lengthSquared() <= variance*variance;
986  }
987 
993  bool isOne() const {
994  return x == 1.0f && y == 1.0f && z == 1.0f && w == 1.0f;
995  }
996 
1002  bool isInvertible() const {
1003  return x != 0.0f && y != 0.0f && z != 0.0f && w != 0.0f;
1004  }
1005 
1013  bool isUnit(float variance=CU_MATH_EPSILON) const {
1014  float dot = length()-1.0f;
1015  return dot <= variance && dot >= -variance;
1016  }
1017 
1023  bool isHomogenous() const {
1024  return w == 1.0f;
1025  }
1026 
1037  float getAngle(const Vec4& other) const;
1038 
1048  float distance(const Vec4& v) const {
1049 #if defined CU_MATH_VECTOR_APPLE
1050  vFloat nv = this->v-v.v;
1051  return vSnorm2(4, &nv);
1052 #else
1053  return sqrt(distanceSquared(v));
1054 #endif
1055  }
1056 
1071  float distanceSquared(const Vec4& v) const {
1072 #if defined CU_MATH_VECTOR_APPLE
1073  vFloat nv = this->v-v.v;
1074  return vSdot(4, &nv, &nv);
1075 #else
1076  return (x-v.x)*(x-v.x)+(y-v.y)*(y-v.y)+(z-v.z)*(z-v.z)+(w-v.w)*(w-v.w);
1077 #endif
1078  }
1079 
1087  float length() const {
1088 #if defined CU_MATH_VECTOR_APPLE
1089  return vSnorm2(4, &v);
1090 #else
1091  return sqrt(lengthSquared());
1092 #endif
1093  }
1094 
1107  float lengthSquared() const {
1108 #if defined CU_MATH_VECTOR_APPLE
1109  return vSdot(4, &v, &v);
1110 #else
1111  return x*x+y*y+z*z+w*w;
1112 #endif
1113  }
1114 
1115 
1116 #pragma mark -
1117 #pragma mark Linear Algebra
1118 
1125  float dot(const Vec4& v) const {
1126 #if defined CU_MATH_VECTOR_APPLE
1127  return vSdot(4, &(this->v), &(v.v));
1128 #else
1129  return (x * v.x + y * v.y + z * v.z + w * v.w);
1130 #endif
1131  }
1132 
1143  Vec4& normalize();
1144 
1157  Vec4 result(*this);
1158  return result.normalize();
1159  }
1160 
1170  Vec4 getMidpoint(const Vec4& other) const {
1171  Vec4 result;
1172  midpoint(*this,other, &result);
1173  return result;
1174  }
1175 
1183  Vec4& project(const Vec4& other) {
1184  *this = getProjection(other);
1185  return *this;
1186  }
1187 
1197  Vec4 getProjection(const Vec4& other) const {
1198  return other * (dot(other)/other.dot(other));
1199  }
1200 
1210  float dw = (w == 0 ? 1 : 1/w);
1211  *this *= dw; w = 1;
1212  return *this;
1213  }
1214 
1226  Vec4 copy(*this);
1227  copy.homogenize();
1228  return copy;
1229  }
1230 
1243  Vec4& lerp(const Vec4& other, float alpha) {
1244  *this *= (1.f - alpha);
1245  return *this += other * alpha;
1246  }
1247 
1260  Vec4 getLerp(const Vec4& other, float alpha) {
1261  return *this * (1.f - alpha) + other * alpha;
1262  }
1263 
1276  void smooth(const Vec4& target, float elapsed, float response);
1277 
1278 
1279 #pragma mark -
1280 #pragma mark Static Linear Algebra
1281 
1289  static float dot(const Vec4& v1, const Vec4& v2);
1290 
1302  static Vec4* normalize(const Vec4& v, Vec4* dst);
1303 
1315  static Vec4* homogenize(const Vec4& v, Vec4* dst);
1316 
1326  static Vec4* midpoint(const Vec4& v1, const Vec4& v2, Vec4* dst);
1327 
1337  static Vec4* project(const Vec4& v1, const Vec4& v2, Vec4* dst);
1338 
1353  static Vec4* lerp(const Vec4& v1, const Vec4& v2, float alpha, Vec4* dst);
1354 
1355 #pragma mark -
1356 #pragma mark Conversion Methods
1357 public:
1368  std::string toString(bool verbose = false) const;
1369 
1371  operator std::string() const { return toString(); }
1372 
1374  operator Color4() const;
1375 
1384  explicit Vec4(Color4 color);
1385 
1396  Vec4& operator= (Color4 color);
1397 
1399  operator Color4f() const;
1400 
1408  explicit Vec4(const Color4f& color);
1409 
1419  Vec4& operator= (const Color4f& color);
1420 
1427  operator Vec2() const;
1428 
1437  explicit Vec4(const Vec2& v);
1438 
1449  Vec4& operator= (const Vec2& size);
1450 
1457  operator Vec3() const;
1458 
1467  explicit Vec4(const Vec3& v);
1468 
1477  Vec4(const Vec3& v, float w);
1478 
1489  Vec4& operator= (const Vec3& v);
1490 
1501  Vec4& set(const Vec3& v, float w);
1502 };
1503 
1504 
1505 #pragma mark -
1506 #pragma mark Friend Operations
1507 
1515  inline const Vec4 operator*(float x, const Vec4& v) {
1516  Vec4 result(v);
1517  return result.scale(x);
1518  }
1519 
1520 }
1521 
1522 #endif /* __CU_VEC4_H__ */
bool isZero() const
Definition: CUVec4.h:973
Vec4 & set(const Vec4 &v)
Definition: CUVec4.h:244
static const Vec4 ZERO
Definition: CUVec4.h:117
Vec4(const Vec4 &p1, const Vec4 &p2)
Definition: CUVec4.h:180
Vec4 & add(float x, float y, float z, float w)
Definition: CUVec4.h:466
bool isNearZero(float variance=CU_MATH_EPSILON) const
Definition: CUVec4.h:984
static Vec4 * negate(const Vec4 &v, Vec4 *dst)
static Vec4 * subtract(const Vec4 &v1, const Vec4 &v2, Vec4 *dst)
static const Vec4 ONE
Definition: CUVec4.h:119
static const Vec4 UNIT_W
Definition: CUVec4.h:127
Vec4(float x, float y, float z, float w)
Definition: CUVec4.h:155
Vec4 & add(const Vec4 &v)
Definition: CUVec4.h:447
Definition: CUVec2.h:61
const Vec4 operator-() const
Definition: CUVec4.h:768
float dot(const Vec4 &v) const
Definition: CUVec4.h:1125
bool isHomogenous() const
Definition: CUVec4.h:1023
Vec4 & subtract(const Vec4 &v)
Definition: CUVec4.h:478
Vec4 & operator*=(const Vec4 &v)
Definition: CUVec4.h:705
float z
Definition: CUVec4.h:111
static const Vec4 HOMOG_Y
Definition: CUVec4.h:135
Vec4 & operator*=(float s)
Definition: CUVec4.h:694
static Vec4 * scale(const Vec4 &v, float s, Vec4 *dst)
const Vec4 operator*(const Vec4 &v) const
Definition: CUVec4.h:797
static const Vec4 HOMOG_X
Definition: CUVec4.h:133
Vec4 & operator/=(float s)
Definition: CUVec4.h:716
Vec4 getHomogenized()
Definition: CUVec4.h:1225
Vec4 & setZero()
Definition: CUVec4.h:275
static const Vec4 HOMOG_ORIGIN
Definition: CUVec4.h:131
const Vec4 operator*(float s) const
Definition: CUVec4.h:782
bool operator<=(const Vec4 &v) const
Definition: CUVec4.h:860
Vec4 & scale(float s)
Definition: CUVec4.h:509
Vec4 & negate()
Definition: CUVec4.h:586
bool operator<(const Vec4 &v) const
Definition: CUVec4.h:845
Vec4(const float *array)
Definition: CUVec4.h:166
Vec4 getNegation() const
Definition: CUVec4.h:612
Definition: CUColor4.h:73
Vec4 getLerp(const Vec4 &other, float alpha)
Definition: CUVec4.h:1260
Vec4 & set(const Vec4 &p1, const Vec4 &p2)
Definition: CUVec4.h:261
static const Vec4 UNIT_X
Definition: CUVec4.h:121
const Vec4 operator/(float s) const
Definition: CUVec4.h:811
float lengthSquared() const
Definition: CUVec4.h:1107
static const Vec4 UNIT_Y
Definition: CUVec4.h:123
bool over(const Vec4 &v) const
Definition: CUVec4.h:946
void smooth(const Vec4 &target, float elapsed, float response)
float y
Definition: CUVec4.h:109
Vec4 getReciprocal() const
Definition: CUVec4.h:628
bool operator>(const Vec4 &v) const
Definition: CUVec4.h:875
static const Vec4 UNIT_Z
Definition: CUVec4.h:125
const Vec4 operator-(const Vec4 &v) const
Definition: CUVec4.h:756
static const Vec4 HOMOG_Z
Definition: CUVec4.h:137
Vec4 & map(std::function< float(float)> func)
Definition: CUVec4.h:643
Vec4 & operator/=(const Vec4 &v)
Definition: CUVec4.h:729
bool operator>=(const Vec4 &v) const
Definition: CUVec4.h:890
Vec4()
Definition: CUVec4.h:145
static Vec4 * midpoint(const Vec4 &v1, const Vec4 &v2, Vec4 *dst)
static float angle(const Vec4 &v1, const Vec4 &v2)
float distanceSquared(const Vec4 &v) const
Definition: CUVec4.h:1071
bool under(const Vec4 &v) const
Definition: CUVec4.h:932
float distance(const Vec4 &v) const
Definition: CUVec4.h:1048
Definition: CUVec4.h:73
Vec4 & reciprocate()
Definition: CUVec4.h:600
bool isInvertible() const
Definition: CUVec4.h:1002
Vec4 getMidpoint(const Vec4 &other) const
Definition: CUVec4.h:1170
Vec4 & normalize()
const Vec4 operator+(const Vec4 &v) const
Definition: CUVec4.h:742
Vec4 & lerp(const Vec4 &other, float alpha)
Definition: CUVec4.h:1243
std::string toString(bool verbose=false) const
static Vec4 * clamp(const Vec4 &v, const Vec4 &min, const Vec4 &max, Vec4 *dst)
static Vec4 * reciprocate(const Vec4 &v, Vec4 *dst)
float getAngle(const Vec4 &other) const
Vec4 & operator-=(const Vec4 &v)
Definition: CUVec4.h:683
Vec4 & set(const float *array)
Definition: CUVec4.h:228
bool equals(const Vec4 &v, float variance=CU_MATH_EPSILON) const
Definition: CUVec4.h:961
Vec4 getNormalization() const
Definition: CUVec4.h:1156
float length() const
Definition: CUVec4.h:1087
int operator*(Font::Style value)
Definition: CUFont.h:1503
bool operator==(const Vec4 &v) const
Definition: CUVec4.h:904
Vec4 & scale(const Vec4 &v)
Definition: CUVec4.h:540
Definition: CUVec3.h:61
Vec4 & set(float x, float y, float z, float w)
Definition: CUVec4.h:214
Vec4 getMap(std::function< float(float)> func) const
Definition: CUVec4.h:658
float x
Definition: CUVec4.h:107
Vec4 & operator+=(const Vec4 &v)
Definition: CUVec4.h:672
Vec4 & project(const Vec4 &other)
Definition: CUVec4.h:1183
bool operator!=(const Vec4 &v) const
Definition: CUVec4.h:918
Definition: CUColor4.h:1084
Vec4 getClamp(const Vec4 &min, const Vec4 &max) const
Definition: CUVec4.h:435
Vec4 & operator=(const float *array)
Definition: CUVec4.h:200
Definition: CUAction.h:51
Vec4 getProjection(const Vec4 &other) const
Definition: CUVec4.h:1197
const Vec4 operator/(const Vec4 &v) const
Definition: CUVec4.h:826
bool isOne() const
Definition: CUVec4.h:993
float w
Definition: CUVec4.h:113
Vec4 & homogenize()
Definition: CUVec4.h:1209
static Vec4 * divide(const Vec4 &v, float s, Vec4 *dst)
Vec4 & subtract(float x, float y, float z, float w)
Definition: CUVec4.h:497
Vec4 & scale(float sx, float sy, float sz, float sw)
Definition: CUVec4.h:528
bool isUnit(float variance=CU_MATH_EPSILON) const
Definition: CUVec4.h:1013
static Vec4 * add(const Vec4 &v1, const Vec4 &v2, Vec4 *dst)