aboutsummaryrefslogtreecommitdiff
path: root/include/math/vec2.h
blob: dc51c17594c2b9e1c4e3ac8a00785f859e46c15a (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
#pragma once

#include "defs.h"

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

/// A 2D vector.
typedef struct vec2 {
  R x, y;
} vec2;

/// Construct a vector from 2 coordinates.
static inline vec2 vec2_make(R x, R y) { return (vec2){x, y}; }

/// Construct a vector from an array.
static inline vec2 vec2_from_array(const R xy[2]) {
  return (vec2){xy[0], xy[1]};
}

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

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

/// Negate the given vector.
static inline vec2 vec2_neg(vec2 v) { return (vec2){-v.x, -v.y}; }

/// Add two vectors.
static inline vec2 vec2_add(vec2 a, vec2 b) {
  return (vec2){a.x + b.x, a.y + b.y};
}

/// Subtract two vectors.
static inline vec2 vec2_sub(vec2 a, vec2 b) {
  return (vec2){a.x - b.x, a.y - b.y};
}

/// Modulate two vectors (component-wise multiplication).
static inline vec2 vec2_mul(vec2 a, vec2 b) {
  return (vec2){a.x * b.x, a.y * b.y};
}

/// Divide two vectors component-wise.
static inline vec2 vec2_div(vec2 a, vec2 b) {
  return (vec2){a.x / b.x, a.y / b.y};
}

/// Scale a vector by a scalar value.
static inline vec2 vec2_scale(vec2 v, R s) {
  return (vec2){v.x * s, v.y * s};
}

/// Compare two vectors for equality.
static inline bool vec2_eq(vec2 a, vec2 b) {
  return a.x == b.x && a.y == b.y;
}

/// Return the absolute value of the vector.
static inline vec2 vec2_abs(vec2 v) {
  return (vec2){rabs(v.x), rabs(v.y)};
}

/// Compare two vectors for inequality.
static inline bool vec2_ne(vec2 a, vec2 b) { return !(vec2_eq(a, b)); }

/// Return the vector's squared magnitude.
static inline R vec2_norm2(vec2 v) { return v.x * v.x + v.y * v.y; }

/// Return the vector's magnitude.
static inline R vec2_norm(vec2 v) { return sqrt(vec2_norm2(v)); }

/// Return the squared distance between two points.
static inline R vec2_dist2(vec2 a, vec2 b) {
  const vec2 v = vec2_sub(b, a);
  return vec2_norm2(v);
}

/// Return the distance between two points.
static inline R vec2_dist(vec2 a, vec2 b) { return sqrt(vec2_dist2(a, b)); }

/// Return the given vector divided by its magnitude.
static inline vec2 vec2_normalize(vec2 v) {
  const R n = vec2_norm(v);
  assert(n > 0);
  return (vec2){v.x / n, v.y / n};
}

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

/// Reflect the vector about the normal.
static inline vec2 vec2_reflect(vec2 v, vec2 n) {
  // r = v - 2 * dot(v, n) * n
  return vec2_sub(v, vec2_scale(n, 2 * vec2_dot(v, n)));
}

/// Refract the vector about the normal.
static inline vec2 vec2_refract(vec2 v, vec2 n, R e) {
  // k = 1 - e^2(1 - dot(n,v) * dot(n,v))
  const R k = 1.0 - e * e * (1.0 - vec2_dot(n, v) * vec2_dot(n, v));
  assert(k >= 0);
  // r = e*v - (e * dot(n,v) + sqrt(k)) * n
  return vec2_sub(vec2_scale(v, e),
                  vec2_scale(n, e * vec2_dot(n, v) * sqrt(k)));
}

/// Elevate the vector to a power.
static inline vec2 vec2_pow(vec2 v, R p) {
  return (vec2){pow(v.x, p), pow(v.y, p)};
}

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

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

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