aboutsummaryrefslogtreecommitdiff
path: root/include/math/vec4.h
blob: 60da464e5f3b44bc7b80d84250e0d8cba0c6506a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#pragma once

#include "defs.h"

#include <assert.h>
#include <stdbool.h>

/// A 4D vector.
typedef struct vec4 {
  R x, y, z, w;
} vec4;

/// Construct a vector from 4 coordinates.
static inline vec4 vec4_make(R x, R y, R z, R w) { return (vec4){x, y, z, w}; }

/// Construct a vector from an array.
static inline vec4 vec4_from_array(const R xyzw[4]) {
  return (vec4){xyzw[0], xyzw[1], xyzw[2], xyzw[3]};
}

/// Construct a vector from a single scalar value.
/// x = y = z = val.
static inline vec4 vec4_from_scalar(R val) {
  return (vec4){val, val, val, val};
}

/// Return the vector's ith coordinate.
static inline R vec4_ith(vec4 v, int i) {
  assert(i >= 0 && i < 4);
  return ((const R*)&v)[i];
}

/// Negate the given vector.
static inline vec4 vec4_neg(vec4 v) { return (vec4){-v.x, -v.y, -v.z, -v.w}; }

/// Add two vectors.
static inline vec4 vec4_add(vec4 a, vec4 b) {
  return (vec4){a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w};
}

/// Subtract two vectors.
static inline vec4 vec4_sub(vec4 a, vec4 b) {
  return (vec4){a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w};
}

/// Modulate two vectors (component-wise multiplication).
static inline vec4 vec4_mul(vec4 a, vec4 b) {
  return (vec4){a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w};
}

/// Divide two vectors component-wise.
static inline vec4 vec4_div(vec4 a, vec4 b) {
  return (vec4){a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w};
}

/// Scale a vector by a scalar value.
static inline vec4 vec4_scale(vec4 v, R s) {
  return (vec4){v.x * s, v.y * s, v.z * s, v.w * s};
}

/// Compare two vectors for equality.
static inline bool vec4_eq(vec4 a, vec4 b) {
  return a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w;
}

/// Return the absolute value of the vector.
static inline vec4 vec4_abs(vec4 v) {
  return (vec4){rabs(v.x), rabs(v.y), rabs(v.z), rabs(v.w)};
}

/// Compare two vectors for inequality.
static inline bool vec4_ne(vec4 a, vec4 b) { return !(vec4_eq(a, b)); }

/// Return the vector's squared magnitude.
static inline R vec4_norm2(vec4 v) {
  return v.x * v.x + v.y * v.y + v.z * v.z + v.w * v.w;
}

/// Return the vector's magnitude.
static inline R vec4_norm(vec4 v) { return sqrt(vec4_norm2(v)); }

/// Return the squared distance between two points.
static inline R vec4_dist2(vec4 a, vec4 b) {
  const vec4 v = vec4_sub(b, a);
  return vec4_norm2(v);
}

/// Return the distance between two points.
static inline R vec4_dist(vec4 a, vec4 b) { return sqrt(vec4_dist2(a, b)); }

/// Return the given vector divided by its magnitude.
static inline vec4 vec4_normalize(vec4 v) {
  const R n = vec4_norm(v);
  assert(n > 0);
  return (vec4){v.x / n, v.y / n, v.z / n, v.w / n};
}

/// Return the dot product of two vectors.
static inline R vec4_dot(vec4 a, vec4 b) {
  return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
}

/// Reflect the vector about the normal.
static inline vec4 vec4_reflect(vec4 v, vec4 n) {
  // r = v - 2 * dot(v, n) * n
  return vec4_sub(v, vec4_scale(n, 2 * vec4_dot(v, n)));
}

/// Refract the vector about the normal.
static inline vec4 vec4_refract(vec4 v, vec4 n, R e) {
  // k = 1 - e^2(1 - dot(n,v) * dot(n,v))
  const R k = 1.0 - e * e * (1.0 - vec4_dot(n, v) * vec4_dot(n, v));
  assert(k >= 0);
  // r = e*v - (e * dot(n,v) + sqrt(k)) * n
  return vec4_sub(vec4_scale(v, e),
                  vec4_scale(n, e * vec4_dot(n, v) * sqrt(k)));
}

/// Elevate the vector to a power.
static inline vec4 vec4_pow(vec4 v, R p) {
  return (vec4){pow(v.x, p), pow(v.y, p), pow(v.z, p), pow(v.w, p)};
}

/// The (1, 0, 0, 0) vector.
static inline vec4 right4() { return (vec4){1.0, 0.0, 0.0, 0.0}; }

/// The (0, 1, 0, 0) vector.
static inline vec4 up4() { return (const vec4){0.0, 1.0, 0.0, 0.0}; }

/// The (0, 0, -1, 0) vector.
static inline vec4 forward4() { return (const vec4){0.0, 0.0, -1.0, 0.0}; }

/// The (0, 0, 0, 0) vector.
static inline vec4 zero4() { return (const vec4){0.0, 0.0, 0.0, 0.0}; }