diff options
Diffstat (limited to 'include/math/vec3.h')
-rw-r--r-- | include/math/vec3.h | 44 |
1 files changed, 40 insertions, 4 deletions
diff --git a/include/math/vec3.h b/include/math/vec3.h index 641c02f..d8e1248 100644 --- a/include/math/vec3.h +++ b/include/math/vec3.h | |||
@@ -51,14 +51,14 @@ static inline vec3 vec3_div(vec3 a, vec3 b) { | |||
51 | return (vec3){a.x / b.x, a.y / b.y, a.z / b.z}; | 51 | return (vec3){a.x / b.x, a.y / b.y, a.z / b.z}; |
52 | } | 52 | } |
53 | 53 | ||
54 | /// Scale a vector by a scalar value. | 54 | /// Scale the vector. |
55 | static inline vec3 vec3_scale(vec3 v, R s) { | 55 | static inline vec3 vec3_scale(vec3 v, R s) { |
56 | return (vec3){v.x * s, v.y * s, v.z * s}; | 56 | return (vec3){v.x * s, v.y * s, v.z * s}; |
57 | } | 57 | } |
58 | 58 | ||
59 | /// Compare two vectors for equality. | 59 | /// Compare two vectors for equality. |
60 | static inline bool vec3_eq(vec3 a, vec3 b) { | 60 | static inline bool vec3_eq(vec3 a, vec3 b, R eps) { |
61 | return a.x == b.x && a.y == b.y && a.z == b.z; | 61 | return R_eq(a.x, b.x, eps) && R_eq(a.y, b.y, eps) && R_eq(a.z, b.z, eps); |
62 | } | 62 | } |
63 | 63 | ||
64 | /// Return the absolute value of the vector. | 64 | /// Return the absolute value of the vector. |
@@ -67,7 +67,9 @@ static inline vec3 vec3_abs(vec3 v) { | |||
67 | } | 67 | } |
68 | 68 | ||
69 | /// Compare two vectors for inequality. | 69 | /// Compare two vectors for inequality. |
70 | static inline bool vec3_ne(vec3 a, vec3 b) { return !(vec3_eq(a, b)); } | 70 | static inline bool vec3_ne(vec3 a, vec3 b, R eps) { |
71 | return !(vec3_eq(a, b, eps)); | ||
72 | } | ||
71 | 73 | ||
72 | /// Return the vector's squared magnitude. | 74 | /// Return the vector's squared magnitude. |
73 | static inline R vec3_norm2(vec3 v) { return v.x * v.x + v.y * v.y + v.z * v.z; } | 75 | static inline R vec3_norm2(vec3 v) { return v.x * v.x + v.y * v.y + v.z * v.z; } |
@@ -123,6 +125,40 @@ static inline vec3 vec3_pow(vec3 v, R p) { | |||
123 | return (vec3){pow(v.x, p), pow(v.y, p), pow(v.z, p)}; | 125 | return (vec3){pow(v.x, p), pow(v.y, p), pow(v.z, p)}; |
124 | } | 126 | } |
125 | 127 | ||
128 | /// Linearly interpolate two vectors. | ||
129 | static inline vec3 vec3_lerp(vec3 a, vec3 b, R t) { | ||
130 | return (vec3){ | ||
131 | .x = a.x + t * (b.x - a.x), | ||
132 | .y = a.y + t * (b.y - a.y), | ||
133 | .z = a.z + t * (b.z - a.z)}; | ||
134 | } | ||
135 | |||
136 | /// Interpolate two unit vectors using spherical linear interpolation. | ||
137 | /// | ||
138 | /// Note: You might want to normalize the result. | ||
139 | static inline vec3 vec3_slerp(vec3 a, vec3 b, R t) { | ||
140 | assert(0.0 <= t); | ||
141 | assert(t <= 1.0); | ||
142 | const R eps = 1e-5; | ||
143 | (void)eps; | ||
144 | assert(R_eq(vec3_norm2(a), 1.0, eps)); | ||
145 | assert(R_eq(vec3_norm2(b), 1.0, eps)); | ||
146 | R dot = vec3_dot(a, b); | ||
147 | // For numerical stability, perform linear interpolation when the two vectors | ||
148 | // are close to each other. | ||
149 | R ta, tb; | ||
150 | if (1.0 - dot > 1e-6) { | ||
151 | const R theta = acos(dot); | ||
152 | const R sin_theta = sqrt(1.0 - dot * dot); | ||
153 | ta = sin((1.0 - t) * theta) / sin_theta; | ||
154 | tb = sin(t * theta) / sin_theta; | ||
155 | } else { // Linear interpolation. | ||
156 | ta = 1.0 - t; | ||
157 | tb = t; | ||
158 | } | ||
159 | return vec3_add(vec3_scale(a, ta), vec3_scale(b, tb)); | ||
160 | } | ||
161 | |||
126 | /// The (1, 0, 0) vector. | 162 | /// The (1, 0, 0) vector. |
127 | static inline vec3 right3() { return (vec3){1.0, 0.0, 0.0}; } | 163 | static inline vec3 right3() { return (vec3){1.0, 0.0, 0.0}; } |
128 | 164 | ||