OpenGL ES SDK for Android ARM Developer Center
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
vector_math.h
Go to the documentation of this file.
1 /* Copyright (c) 2015-2017, ARM Limited and Contributors
2  *
3  * SPDX-License-Identifier: MIT
4  *
5  * Permission is hereby granted, free of charge,
6  * to any person obtaining a copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation the rights to
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
14  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
16  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
17  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19  */
20 
21 #ifndef VECTOR_MATH_H__
22 #define VECTOR_MATH_H__
23 
24 #include <string.h>
25 #include <math.h>
26 #include <stdint.h>
27 
28 #ifndef PI
29 #define PI 3.141592653f
30 #endif
31 
32 // Basic vector math.
33 
34 template<typename T>
35 const typename T::data_type *value_ptr(const T& vec)
36 {
37  return vec.data;
38 }
39 
40 struct vec2
41 {
42  union
43  {
44  struct
45  {
46  float x, y;
47  };
48  // Allow us to use vec2, vec3 and vec4 directly in uniform buffers.
49  // GLSL using std140 packing demands that packing of vectors is four floats.
50  // The rules on packing with arrays can be slightly complicated howewer.
51  float data[2];
52  };
53  enum { vector_size = 2 };
54  typedef float data_type;
55  typedef vec2 vector_type;
56  vec2() {}
57  vec2(float s) { this->x = this->y = s; }
58  vec2(float x, float y) { this->x = x; this->y = y; }
59  vec2(const float *vec) { memcpy(data, vec, 2 * sizeof(float)); }
60 };
61 
62 namespace detail
63 {
64  template<typename T>
65  struct ivec2
66  {
67  union
68  {
69  struct
70  {
71  T x, y;
72  };
73  // Allow us to use vec2, vec3 and vec4 directly in uniform buffers.
74  // GLSL using std140 packing demands that packing of vectors is four floats.
75  // The rules on packing with arrays can be slightly complicated howewer.
76  T data[2];
77  };
78  enum { vector_size = 2 };
79  typedef T data_type;
81  ivec2() {}
82  ivec2(T s) { x = y = s; }
83  ivec2(T x, T y) { this->x = x; this->y = y; }
84  ivec2(const T *vec) { memcpy(data, vec, 2 * sizeof(T)); }
85  ivec2(vec2 s) { x = T(s.x); y = T(s.y); }
86  operator vec2() const { return vec2(x, y); }
87  };
88 }
89 
93 
94 struct vec3
95 {
96  union
97  {
98  struct
99  {
100  float x, y, z;
101  };
102  float data[4];
103  };
104  enum { vector_size = 3 };
105  typedef float data_type;
106  typedef vec3 vector_type;
107  vec3() {}
108  vec3(float s) { x = y = z = s; }
109  vec3(float x, float y, float z) { this->x = x; this->y = y; this->z = z; }
110  vec3(const float *vec) { memcpy(data, vec, 3 * sizeof(float)); }
111 };
112 
113 struct vec4
114 {
115  union
116  {
117  struct
118  {
119  float x, y, z, w;
120  };
121  float data[4];
122  };
123  enum { vector_size = 4 };
124  typedef float data_type;
125  typedef vec4 vector_type;
126  vec4() {}
127  vec4(float s) { x = y = z = w = s; }
128  vec4(float x, float y, float z, float w) { this->x = x; this->y = y; this->z = z; this->w = w; }
129  vec4(const float *vec) { memcpy(data, vec, 4 * sizeof(float)); }
130 
131  vec4(const vec3& vec, float v)
132  {
133  *this = vec4(vec.x, vec.y, vec.z, v);
134  }
135 
136  vec4(const vec2& a, const vec2& b)
137  {
138  *this = vec4(a.x, a.y, b.x, b.y);
139  }
140 
141  vec4(const vec2& a, float b, float c)
142  {
143  *this = vec4(a.x, a.y, b, c);
144  }
145 
146  operator vec3() const { return vec3(data); }
147 };
148 
149 struct mat4
150 {
151  float data[16];
152 
153  mat4() {}
154  mat4(float s) { for (unsigned int i = 0; i < 16; i++) data[i] = s; }
155  mat4(float c00, float c01, float c02, float c03,
156  float c10, float c11, float c12, float c13,
157  float c20, float c21, float c22, float c23,
158  float c30, float c31, float c32, float c33)
159  {
160  data[ 0] = c00; data[ 1] = c01; data[ 2] = c02; data[ 3] = c03;
161  data[ 4] = c10; data[ 5] = c11; data[ 6] = c12; data[ 7] = c13;
162  data[ 8] = c20; data[ 9] = c21; data[10] = c22; data[11] = c23;
163  data[12] = c30; data[13] = c31; data[14] = c32; data[15] = c33;
164  }
165  mat4(const float *mat) { memcpy(data, mat, 16 * sizeof(float)); }
166  typedef float data_type;
167 };
168 
169 // Use SFINAE to avoid dubious overloads.
170 
171 template<typename T>
172 inline typename T::vector_type operator-(const T& a)
173 {
174  T res;
175  for (unsigned int i = 0; i < T::vector_size; i++)
176  res.data[i] = -a.data[i];
177  return res;
178 }
179 
180 template<typename T>
181 inline typename T::vector_type operator*(const T& a, const T& b)
182 {
183  T res;
184  for (unsigned int i = 0; i < T::vector_size; i++)
185  res.data[i] = a.data[i] * b.data[i];
186  return res;
187 }
188 
189 template<typename T>
190 inline typename T::vector_type operator/(const T& a, const T& b)
191 {
192  T res;
193  for (unsigned int i = 0; i < T::vector_size; i++)
194  res.data[i] = a.data[i] / b.data[i];
195  return res;
196 }
197 
198 template<typename T>
199 inline typename T::vector_type operator+(const T& a, const T& b)
200 {
201  T res;
202  for (unsigned int i = 0; i < T::vector_size; i++)
203  res.data[i] = a.data[i] + b.data[i];
204  return res;
205 }
206 
207 template<typename T>
208 inline typename T::vector_type operator-(const T& a, const T& b)
209 {
210  T res;
211  for (unsigned int i = 0; i < T::vector_size; i++)
212  res.data[i] = a.data[i] - b.data[i];
213  return res;
214 }
215 
216 template<typename T>
217 inline typename T::vector_type& operator*=(T& a, const T& b)
218 {
219  for (unsigned int i = 0; i < T::vector_size; i++)
220  a.data[i] *= b.data[i];
221  return a;
222 }
223 
224 template<typename T>
225 inline typename T::vector_type& operator/=(T& a, const T& b)
226 {
227  for (unsigned int i = 0; i < T::vector_size; i++)
228  a.data[i] /= b.data[i];
229  return a;
230 }
231 
232 template<typename T>
233 inline typename T::vector_type& operator+=(T& a, const T& b)
234 {
235  for (unsigned int i = 0; i < T::vector_size; i++)
236  a.data[i] += b.data[i];
237  return a;
238 }
239 
240 template<typename T>
241 inline typename T::vector_type& operator-=(T& a, const T& b)
242 {
243  for (unsigned int i = 0; i < T::vector_size; i++)
244  a.data[i] -= b.data[i];
245  return a;
246 }
247 
248 inline mat4 operator*(const mat4& a, const mat4& b)
249 {
250  mat4 res;
251  for (unsigned int r = 0; r < 4; r++)
252  {
253  for (unsigned int c = 0; c < 4; c++)
254  {
255  float sum = 0.0f;
256  for (unsigned int k = 0; k < 4; k++)
257  sum += a.data[r + 4 * k] * b.data[4 * c + k];
258  res.data[r + 4 * c] = sum;
259  }
260  }
261 
262  return res;
263 }
264 
265 inline vec4 operator*(const mat4& mat, const vec4& vec)
266 {
267  vec4 res(0.0f);
268  for (unsigned int i = 0; i < 4; i++)
269  res += vec4(mat.data + 4 * i) * vec4(vec.data[i]);
270  return res;
271 }
272 
273 inline mat4& operator*=(mat4& mat, float v)
274 {
275  for (unsigned int i = 0; i < 16; i++)
276  mat.data[i] *= v;
277  return mat;
278 }
279 
280 inline vec3 vec_cross(const vec3& a, const vec3& b)
281 {
282  return vec3(
283  a.y * b.z - b.y * a.z,
284  a.z * b.x - b.z * a.x,
285  a.x * b.y - b.x * a.y);
286 }
287 
288 template<typename T>
289 inline float vec_dot(const T& a, const T& b)
290 {
291  float sum = 0.0f;
292  for (unsigned int i = 0; i < T::vector_size; i++)
293  sum += a.data[i] * b.data[i];
294  return sum;
295 }
296 
297 template<typename T>
298 inline float vec_length(const T& vec)
299 {
300  return sqrt(vec_dot(vec, vec));
301 }
302 
303 template<typename T>
304 inline T vec_normalize(const T& vec)
305 {
306  return vec / T(vec_length(vec));
307 }
308 
309 template<typename T>
310 inline T vec_floor(const T& vec)
311 {
312  T res;
313  for (unsigned int i = 0; i < T::vector_size; i++)
314  res.data[i] = floor(vec.data[i]);
315  return res;
316 }
317 
318 template<typename T>
319 inline T vec_round(const T& vec)
320 {
321  T res;
322  for (unsigned int i = 0; i < T::vector_size; i++)
323  res.data[i] = round(vec.data[i]);
324  return res;
325 }
326 
327 template<typename T>
328 inline T vec_fract(const T& vec)
329 {
330  return vec - vec_floor(vec);
331 }
332 
333 inline vec3 vec_project(const vec4& vec)
334 {
335  return vec3(vec.data) / vec3(vec.w);
336 }
337 
338 template<typename T>
339 inline T clamp(T value, T lo, T hi)
340 {
341  if (value < lo)
342  return lo;
343  else if (value > hi)
344  return hi;
345  else
346  return value;
347 }
348 
349 template<typename T>
350 inline T vec_clamp(const T& vec, const T& lo, const T& hi)
351 {
352  T res;
353  for (unsigned int i = 0; i < T::vector_size; i++)
354  res.data[i] = clamp(vec.data[i], lo.data[i], hi.data[i]);
355  return res;
356 }
357 
358 inline mat4 mat_look_at(const vec3& eye, const vec3& center,
359  const vec3& up)
360 {
361  vec3 zaxis = vec_normalize(center - eye);
362  vec3 xaxis = vec_normalize(vec_cross(zaxis, up));
363  vec3 yaxis = vec_cross(xaxis, zaxis);
364  return mat4(
365  xaxis.x, yaxis.x, -zaxis.x, 0.0f,
366  xaxis.y, yaxis.y, -zaxis.y, 0.0f,
367  xaxis.z, yaxis.z, -zaxis.z, 0.0f,
368  -vec_dot(xaxis, eye), -vec_dot(yaxis, eye), -vec_dot(-zaxis, eye), 1.0f);
369 }
370 
371 inline mat4 mat_rotate_x(float radians)
372 {
373  float cos_r = cos(radians);
374  float sin_r = sin(radians);
375 
376  return mat4(1.0f, 0.0f, 0.0f, 0.0f,
377  0.0f, cos_r, sin_r, 0.0f,
378  0.0f, -sin_r, cos_r, 0.0f,
379  0.0f, 0.0f, 0.0f, 1.0f);
380 }
381 
382 inline mat4 mat_rotate_y(float radians)
383 {
384  float cos_r = cos(radians);
385  float sin_r = sin(radians);
386 
387  return mat4(cos_r, 0.0f, sin_r, 0.0f,
388  0.0f, 1.0f, 0.0f, 0.0f,
389  -sin_r, 0.0f, cos_r, 0.0f,
390  0.0f, 0.0f, 0.0f, 1.0f);
391 }
392 
393 inline mat4 mat_rotate_z(float radians)
394 {
395  float cos_r = cos(radians);
396  float sin_r = sin(radians);
397 
398  return mat4(cos_r, sin_r, 0.0f, 0.0f,
399  -sin_r, cos_r, 0.0f, 0.0f,
400  0.0f, 0.0f, 1.0f, 0.0f,
401  0.0f, 0.0f, 0.0f, 1.0f);
402 }
403 
404 inline vec3 vec_rotateX(const vec3& v, float radians)
405 {
406  return vec3(mat_rotate_x(radians) * vec4(v, 1.0f));
407 }
408 
409 inline vec3 vec_rotateY(const vec3& v, float radians)
410 {
411  return vec3(mat_rotate_y(radians) * vec4(v, 1.0f));
412 }
413 
414 inline vec3 vec_rotateZ(const vec3& v, float radians)
415 {
416  return vec3(mat_rotate_z(radians) * vec4(v, 1.0f));
417 }
418 
419 inline mat4 mat_perspective_fov(float fovy, float aspect,
420  float zn, float zf)
421 {
422  float yFac = tanf(fovy * PI / 360.0f);
423  float xFac = yFac * aspect;
424  return mat4(1.0f / xFac, 0.0f, 0.0f, 0.0f,
425  0.0f, 1.0f / yFac, 0.0f, 0.0f,
426  0.0f, 0.0f, -(zf + zn) / (zf - zn), -1.0f,
427  0.0f, 0.0f, -(2.0f * zf * zn) / (zf - zn), 0.0f);
428 }
429 
430 inline mat4 mat_inverse(const mat4& a)
431 {
432  float a0 = a.data[ 0] * a.data[ 5] - a.data[ 4] * a.data[ 1];
433  float a1 = a.data[ 0] * a.data[ 9] - a.data[ 8] * a.data[ 1];
434  float a2 = a.data[ 0] * a.data[13] - a.data[12] * a.data[ 1];
435  float a3 = a.data[ 4] * a.data[ 9] - a.data[ 8] * a.data[ 5];
436  float a4 = a.data[ 4] * a.data[13] - a.data[12] * a.data[ 5];
437  float a5 = a.data[ 8] * a.data[13] - a.data[12] * a.data[ 9];
438  float b0 = a.data[ 2] * a.data[ 7] - a.data[ 6] * a.data[ 3];
439  float b1 = a.data[ 2] * a.data[11] - a.data[10] * a.data[ 3];
440  float b2 = a.data[ 2] * a.data[15] - a.data[14] * a.data[ 3];
441  float b3 = a.data[ 6] * a.data[11] - a.data[10] * a.data[ 7];
442  float b4 = a.data[ 6] * a.data[15] - a.data[14] * a.data[ 7];
443  float b5 = a.data[10] * a.data[15] - a.data[14] * a.data[11];
444 
445  float det = a0 * b5 - a1 * b4 + a2 * b3 + a3 * b2 - a4 * b1 + a5 * b0;
446  float inv_det = 1.0f / det;
447 
448  mat4 inv;
449  inv.data[ 0] = + a.data[5] * b5 - a.data[ 9] * b4 + a.data[13] * b3;
450  inv.data[ 1] = - a.data[1] * b5 + a.data[ 9] * b2 - a.data[13] * b1;
451  inv.data[ 2] = + a.data[1] * b4 - a.data[ 5] * b2 + a.data[13] * b0;
452  inv.data[ 3] = - a.data[1] * b3 + a.data[ 5] * b1 - a.data[ 9] * b0;
453  inv.data[ 4] = - a.data[4] * b5 + a.data[ 8] * b4 - a.data[12] * b3;
454  inv.data[ 5] = + a.data[0] * b5 - a.data[ 8] * b2 + a.data[12] * b1;
455  inv.data[ 6] = - a.data[0] * b4 + a.data[ 4] * b2 - a.data[12] * b0;
456  inv.data[ 7] = + a.data[0] * b3 - a.data[ 4] * b1 + a.data[ 8] * b0;
457  inv.data[ 8] = + a.data[7] * a5 - a.data[11] * a4 + a.data[15] * a3;
458  inv.data[ 9] = - a.data[3] * a5 + a.data[11] * a2 - a.data[15] * a1;
459  inv.data[10] = + a.data[3] * a4 - a.data[ 7] * a2 + a.data[15] * a0;
460  inv.data[11] = - a.data[3] * a3 + a.data[ 7] * a1 - a.data[11] * a0;
461  inv.data[12] = - a.data[6] * a5 + a.data[10] * a4 - a.data[14] * a3;
462  inv.data[13] = + a.data[2] * a5 - a.data[10] * a2 + a.data[14] * a1;
463  inv.data[14] = - a.data[2] * a4 + a.data[ 6] * a2 - a.data[14] * a0;
464  inv.data[15] = + a.data[2] * a3 - a.data[ 6] * a1 + a.data[10] * a0;
465 
466  inv *= inv_det;
467  return inv;
468 }
469 
470 #endif
T vec_fract(const T &vec)
Definition: vector_math.h:328
T vec_floor(const T &vec)
Definition: vector_math.h:310
vec2(const float *vec)
Definition: vector_math.h:59
ivec2(T x, T y)
Definition: vector_math.h:83
const GLfloat * v
Definition: gl2ext.h:2231
vec3 vec_rotateX(const vec3 &v, float radians)
Definition: vector_math.h:404
vec3()
Definition: vector_math.h:107
float data[4]
Definition: vector_math.h:121
float data_type
Definition: vector_math.h:166
vec2()
Definition: vector_math.h:56
float data_type
Definition: vector_math.h:54
T::vector_type & operator/=(T &a, const T &b)
Definition: vector_math.h:225
vec4(const vec2 &a, const vec2 &b)
Definition: vector_math.h:136
vec4(const vec2 &a, float b, float c)
Definition: vector_math.h:141
vec3(const float *vec)
Definition: vector_math.h:110
ivec2(const T *vec)
Definition: vector_math.h:84
GLboolean GLboolean GLboolean GLboolean a
Definition: gl2ext.h:306
Definition: matrix.h:51
float vec_dot(const T &a, const T &b)
Definition: vector_math.h:289
GLboolean r
Definition: gl2ext.h:306
mat4 mat_look_at(const vec3 &eye, const vec3 &center, const vec3 &up)
Definition: vector_math.h:358
vec2 vector_type
Definition: vector_math.h:55
Definition: matrix.h:28
vec3 vec_cross(const vec3 &a, const vec3 &b)
Definition: vector_math.h:280
T::vector_type operator/(const T &a, const T &b)
Definition: vector_math.h:190
vec2(float x, float y)
Definition: vector_math.h:58
T::vector_type operator*(const T &a, const T &b)
Definition: vector_math.h:181
T::vector_type operator+(const T &a, const T &b)
Definition: vector_math.h:199
const T::data_type * value_ptr(const T &vec)
Definition: vector_math.h:35
mat4 mat_rotate_y(float radians)
Definition: vector_math.h:382
GLint value
Definition: gl2ext.h:558
float z
Definition: matrix.h:55
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
Definition: gl2ext.h:179
mat4(const float *mat)
Definition: vector_math.h:165
Definition: matrix.h:75
mat4(float c00, float c01, float c02, float c03, float c10, float c11, float c12, float c13, float c20, float c21, float c22, float c23, float c30, float c31, float c32, float c33)
Definition: vector_math.h:155
float data_type
Definition: vector_math.h:105
vec4(float x, float y, float z, float w)
Definition: vector_math.h:128
float vec_length(const T &vec)
Definition: vector_math.h:298
float data_type
Definition: vector_math.h:124
vec4 vector_type
Definition: vector_math.h:125
vec2(float s)
Definition: vector_math.h:57
struct vec4::@39::@42 c
T::vector_type operator-(const T &a)
Definition: vector_math.h:172
GLfloat GLfloat GLfloat w
Definition: gl2ext.h:2701
vec3 vec_rotateZ(const vec3 &v, float radians)
Definition: vector_math.h:414
GLfloat GLfloat f
Definition: gl2ext.h:2707
T::vector_type & operator+=(T &a, const T &b)
Definition: vector_math.h:233
float y
Definition: matrix.h:31
vec3(float s)
Definition: vector_math.h:108
mat4 mat_rotate_z(float radians)
Definition: vector_math.h:393
float w
Definition: matrix.h:80
float x
Definition: matrix.h:53
float y
Definition: matrix.h:54
mat4 mat_rotate_x(float radians)
Definition: vector_math.h:371
mat4 mat_perspective_fov(float fovy, float aspect, float zn, float zf)
Definition: vector_math.h:419
mat4()
Definition: vector_math.h:153
float data[16]
Definition: vector_math.h:151
detail::ivec2< uint8_t > ubvec2
Definition: vector_math.h:92
vec4(const vec3 &vec, float v)
Definition: vector_math.h:131
vec3 vec_rotateY(const vec3 &v, float radians)
Definition: vector_math.h:409
GLint GLint GLint GLint GLint x
Definition: gl2ext.h:574
vec3 vector_type
Definition: vector_math.h:106
Definition: matrix.h:104
ivec2< T > vector_type
Definition: vector_math.h:80
T::vector_type & operator*=(T &a, const T &b)
Definition: vector_math.h:217
T vec_clamp(const T &vec, const T &lo, const T &hi)
Definition: vector_math.h:350
mat4 mat_inverse(const mat4 &a)
Definition: vector_math.h:430
vec4(float s)
Definition: vector_math.h:127
ivec2(vec2 s)
Definition: vector_math.h:85
float z
Definition: matrix.h:79
T::vector_type & operator-=(T &a, const T &b)
Definition: vector_math.h:241
T clamp(T value, T lo, T hi)
Definition: vector_math.h:339
T vec_normalize(const T &vec)
Definition: vector_math.h:304
GLboolean GLboolean GLboolean b
Definition: gl2ext.h:306
float x
Definition: matrix.h:30
#define PI
Definition: vector_math.h:29
vec4(const float *vec)
Definition: vector_math.h:129
detail::ivec2< uint32_t > uvec2
Definition: vector_math.h:90
T vec_round(const T &vec)
Definition: vector_math.h:319
float x
Definition: matrix.h:77
vec3 vec_project(const vec4 &vec)
Definition: vector_math.h:333
float y
Definition: matrix.h:78
detail::ivec2< int32_t > ivec2
Definition: vector_math.h:91
GLint y
Definition: gl2ext.h:179
vec3(float x, float y, float z)
Definition: vector_math.h:109
vec4()
Definition: vector_math.h:126
mat4(float s)
Definition: vector_math.h:154