summaryrefslogtreecommitdiff
path: root/include/cglm/aabb2d.h
blob: 6369d08a34df5df6ddb4c4ed217d0f65ce59bd70 (plain) (blame)
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
/*
 * Copyright (c), Recep Aslantas.
 *
 * MIT License (MIT), http://opensource.org/licenses/MIT
 * Full license can be found in the LICENSE file
 */

#ifndef cglm_aabb2d_h
#define cglm_aabb2d_h

#include "common.h"
#include "vec2.h"
#include "util.h"

/* DEPRECATED! use _diag */
#define glm_aabb2d_size(aabb)         glm_aabb2d_diag(aabb)

/*!
 * @brief make [aabb] zero
 *
 * @param[in, out]  aabb aabb
 */
CGLM_INLINE
void
glm_aabb2d_zero(vec2 aabb[2]) {
  glm_vec2_zero(aabb[0]);
  glm_vec2_zero(aabb[1]);
}

/*!
 * @brief copy all members of [aabb] to [dest]
 *
 * @param[in]  aabb source
 * @param[out] dest destination
 */
CGLM_INLINE
void
glm_aabb2d_copy(vec2 aabb[2], vec2 dest[2]) {
  glm_vec2_copy(aabb[0], dest[0]);
  glm_vec2_copy(aabb[1], dest[1]);
}

/*!
 * @brief apply transform to Axis-Aligned Bounding aabb
 *
 * @param[in]  aabb  bounding aabb
 * @param[in]  m    transform matrix
 * @param[out] dest transformed bounding aabb
 */
CGLM_INLINE
void
glm_aabb2d_transform(vec2 aabb[2], mat3 m, vec2 dest[2]) {
  vec2 v[2], xa, xb, ya, yb;

  glm_vec2_scale(m[0], aabb[0][0], xa);
  glm_vec2_scale(m[0], aabb[1][0], xb);

  glm_vec2_scale(m[1], aabb[0][1], ya);
  glm_vec2_scale(m[1], aabb[1][1], yb);

  /* translation + min(xa, xb) + min(ya, yb) */
  glm_vec2(m[2], v[0]);
  glm_vec2_minadd(xa, xb, v[0]);
  glm_vec2_minadd(ya, yb, v[0]);

  /* translation + max(xa, xb) + max(ya, yb) */
  glm_vec2(m[2], v[1]);
  glm_vec2_maxadd(xa, xb, v[1]);
  glm_vec2_maxadd(ya, yb, v[1]);

  glm_vec2_copy(v[0], dest[0]);
  glm_vec2_copy(v[1], dest[1]);
}

/*!
 * @brief merges two AABB bounding aabb and creates new one
 *
 * two aabb must be in same space, if one of aabb is in different space then
 * you should consider to convert it's space by glm_aabb_space
 *
 * @param[in]  aabb1 bounding aabb 1
 * @param[in]  aabb2 bounding aabb 2
 * @param[out] dest merged bounding aabb
 */
CGLM_INLINE
void
glm_aabb2d_merge(vec2 aabb1[2], vec2 aabb2[2], vec2 dest[2]) {
  dest[0][0] = glm_min(aabb1[0][0], aabb2[0][0]);
  dest[0][1] = glm_min(aabb1[0][1], aabb2[0][1]);

  dest[1][0] = glm_max(aabb1[1][0], aabb2[1][0]);
  dest[1][1] = glm_max(aabb1[1][1], aabb2[1][1]);
}

/*!
 * @brief crops a bounding aabb with another one.
 *
 * this could be useful for getting a baabb which fits with view frustum and
 * object bounding aabbes. In this case you crop view frustum aabb with objects
 * aabb
 *
 * @param[in]  aabb     bounding aabb 1
 * @param[in]  cropAabb crop aabb
 * @param[out] dest     cropped bounding aabb
 */
CGLM_INLINE
void
glm_aabb2d_crop(vec2 aabb[2], vec2 cropAabb[2], vec2 dest[2]) {
  dest[0][0] = glm_max(aabb[0][0], cropAabb[0][0]);
  dest[0][1] = glm_max(aabb[0][1], cropAabb[0][1]);

  dest[1][0] = glm_min(aabb[1][0], cropAabb[1][0]);
  dest[1][1] = glm_min(aabb[1][1], cropAabb[1][1]);
}

/*!
 * @brief crops a bounding aabb with another one.
 *
 * this could be useful for getting a baabb which fits with view frustum and
 * object bounding aabbes. In this case you crop view frustum aabb with objects
 * aabb
 *
 * @param[in]  aabb      bounding aabb
 * @param[in]  cropAabb  crop aabb
 * @param[in]  clampAabb minimum aabb
 * @param[out] dest      cropped bounding aabb
 */
CGLM_INLINE
void
glm_aabb2d_crop_until(vec2 aabb[2],
                      vec2 cropAabb[2],
                      vec2 clampAabb[2],
                      vec2 dest[2]) {
  glm_aabb2d_crop(aabb, cropAabb, dest);
  glm_aabb2d_merge(clampAabb, dest, dest);
}

/*!
 * @brief invalidate AABB min and max values
 *
 * @param[in, out]  aabb bounding aabb
 */
CGLM_INLINE
void
glm_aabb2d_invalidate(vec2 aabb[2]) {
  glm_vec2_fill(aabb[0], FLT_MAX);
  glm_vec2_fill(aabb[1], -FLT_MAX);
}

/*!
 * @brief check if AABB is valid or not
 *
 * @param[in]  aabb bounding aabb
 */
CGLM_INLINE
bool
glm_aabb2d_isvalid(vec2 aabb[2]) {
  return glm_vec2_max(aabb[0]) != FLT_MAX
         && glm_vec2_min(aabb[1]) != -FLT_MAX;
}

/*!
 * @brief distance between of min and max
 *
 * @param[in]  aabb bounding aabb
 */
CGLM_INLINE
float
glm_aabb2d_diag(vec2 aabb[2]) {
  return glm_vec2_distance(aabb[0], aabb[1]);
}

/*!
 * @brief size of aabb
 *
 * @param[in]  aabb bounding aabb
 * @param[out]  dest size
 */
CGLM_INLINE
void
glm_aabb2d_sizev(vec2 aabb[2], vec2 dest) {
  glm_vec2_sub(aabb[1], aabb[0], dest); 
}

/*!
 * @brief radius of sphere which surrounds AABB
 *
 * @param[in]  aabb bounding aabb
 */
CGLM_INLINE
float
glm_aabb2d_radius(vec2 aabb[2]) {
  return glm_aabb2d_diag(aabb) * 0.5f;
}

/*!
 * @brief computes center point of AABB
 *
 * @param[in]   aabb  bounding aabb
 * @param[out]  dest center of bounding aabb
 */
CGLM_INLINE
void
glm_aabb2d_center(vec2 aabb[2], vec2 dest) {
  glm_vec2_center(aabb[0], aabb[1], dest);
}

/*!
 * @brief check if two AABB intersects
 *
 * @param[in]   aabb    bounding aabb
 * @param[in]   other  other bounding aabb
 */
CGLM_INLINE
bool
glm_aabb2d_aabb(vec2 aabb[2], vec2 other[2]) {
  return (aabb[0][0] <= other[1][0] && aabb[1][0] >= other[0][0])
      && (aabb[0][1] <= other[1][1] && aabb[1][1] >= other[0][1]);
}

/*!
 * @brief check if AABB intersects with a circle
 *
 * Circle Representation in cglm: [center.x, center.y, radii]
 *
 * @param[in]   aabb   solid bounding aabb
 * @param[in]   c      solid circle
 */
CGLM_INLINE
bool
glm_aabb2d_circle(vec2 aabb[2], vec3 c) {
  float dmin;
  int   a, b;

  a = (c[0] < aabb[0][0]) + (c[0] > aabb[1][0]);
  b = (c[1] < aabb[0][1]) + (c[1] > aabb[1][1]);

  dmin  = glm_pow2((c[0] - aabb[!(a - 1)][0]) * (a != 0))
        + glm_pow2((c[1] - aabb[!(b - 1)][1]) * (b != 0));

  return dmin <= glm_pow2(c[2]);
}

/*!
 * @brief check if point is inside of AABB
 *
 * @param[in]   aabb    bounding aabb
 * @param[in]   point  point
 */
CGLM_INLINE
bool
glm_aabb2d_point(vec2 aabb[2], vec2 point) {
  return (point[0] >= aabb[0][0] && point[0] <= aabb[1][0])
      && (point[1] >= aabb[0][1] && point[1] <= aabb[1][1]);
}

/*!
 * @brief check if AABB contains other AABB
 *
 * @param[in]   aabb    bounding aabb
 * @param[in]   other  other bounding aabb
 */
CGLM_INLINE
bool
glm_aabb2d_contains(vec2 aabb[2], vec2 other[2]) {
  return (aabb[0][0] <= other[0][0] && aabb[1][0] >= other[1][0])
      && (aabb[0][1] <= other[0][1] && aabb[1][1] >= other[1][1]);
}

#endif /* cglm_aabb2d_h */