1// Copyright 2009-2020 Intel Corporation
2// SPDX-License-Identifier: Apache-2.0
3
4#pragma once
5
6#include "vec.ih"
7
8//! a 1-d float bounding box (ie, a range<float>
9struct box1f
10{
11  float lower;
12  float upper;
13};
14
15//! a 2-d float bounding box
16struct box2f
17{
18  vec2f lower;
19  vec2f upper;
20};
21
22//! a 2-d integer bounding box
23struct box2i
24{
25  vec2i lower;
26  vec2i upper;
27};
28
29//! a 3-d float bounding box
30struct box3f
31{
32  vec3f lower;
33  vec3f upper;
34};
35
36//! a 3-d int bounding box
37struct box3i
38{
39  vec3i lower;
40  vec3i upper;
41};
42
43//! a 3-d float bounding box with aligned vec3f coordinates
44struct box3fa
45{
46  vec3f lower;
47  int32 align0;
48  vec3f upper;
49  int32 align1;
50};
51
52//! a 4-d float bounding box
53struct box4f
54{
55  vec4f lower;
56  vec4f upper;
57};
58
59// -------------------------------------------------------
60// all box1f operations
61// -------------------------------------------------------
62
63#define MAKE_BOX1F_uv(univary)                                       \
64  inline univary box1f make_box1f(const univary float f)             \
65  {                                                                  \
66    univary box1f bb;                                                \
67    bb.lower = bb.upper = f;                                         \
68    return bb;                                                       \
69  }                                                                  \
70                                                                     \
71  inline univary box1f make_box1f(const univary float lo,            \
72                                  const univary float hi)            \
73  {                                                                  \
74    univary box1f bb;                                                \
75    bb.lower = lo;                                                   \
76    bb.upper = hi;                                                   \
77    return bb;                                                       \
78  }                                                                  \
79                                                                     \
80  inline univary float box_size(const univary box1f &bb)             \
81  {                                                                  \
82    return bb.upper - bb.lower;                                      \
83  }                                                                  \
84                                                                     \
85  inline univary box1f box_extend(const univary box1f &a,            \
86                                  const univary box1f &b)            \
87  {                                                                  \
88    return make_box1f(min(a.lower, b.lower), max(a.upper, b.upper)); \
89  }                                                                  \
90                                                                     \
91  inline univary bool isEmpty(const univary box1f &bb)               \
92  {                                                                  \
93    return bb.upper < bb.lower;                                      \
94  }
95
96MAKE_BOX1F_uv(uniform) MAKE_BOX1F_uv(varying)
97#undef MAKE_BOX1F_uv
98
99// -------------------------------------------------------
100// box2 'constructors'
101// -------------------------------------------------------
102
103#define MAKE_BOX_CONSTRUCTORS_uv_2T_fromVec2(univary, Tabb, otherT)           \
104  inline univary box2##Tabb make_box2##Tabb(const univary vec2##otherT lower, \
105                                            const univary vec2##otherT upper) \
106  {                                                                           \
107    univary box2##Tabb bb;                                                    \
108    bb.lower.x = lower.x;                                                     \
109    bb.lower.y = lower.y;                                                     \
110    bb.upper.x = upper.x;                                                     \
111    bb.upper.y = upper.y;                                                     \
112    return bb;                                                                \
113  }
114
115#define MAKE_BOX_CONSTRUCTORS_uv_2T_fromBox2(univary, Tabb, otherT)           \
116  inline univary box2##Tabb make_box2##Tabb(const univary box2##otherT other) \
117  {                                                                           \
118    univary box2##Tabb bb;                                                    \
119    bb.lower.x = other.lower.x;                                               \
120    bb.lower.y = other.lower.y;                                               \
121    bb.upper.x = other.upper.x;                                               \
122    bb.upper.y = other.upper.y;                                               \
123    return bb;                                                                \
124  }
125
126#define MAKE_BOX_CONSTRUCTORS_uv_2T_empty(Tabb)                             \
127  inline uniform box2##Tabb make_box2##Tabb##_empty()                       \
128  {                                                                         \
129    return make_box2##Tabb(make_vec2##Tabb(inf), make_vec2##Tabb(neg_inf)); \
130  }
131
132#define MAKE_BOX_CONSTRUCTORS_uv_2T(univary, Tabb)               \
133  MAKE_BOX_CONSTRUCTORS_uv_2T_fromVec2(univary, Tabb, f)         \
134      MAKE_BOX_CONSTRUCTORS_uv_2T_fromVec2(univary, Tabb, i)     \
135                                                                 \
136          MAKE_BOX_CONSTRUCTORS_uv_2T_fromBox2(univary, Tabb, f) \
137              MAKE_BOX_CONSTRUCTORS_uv_2T_fromBox2(univary, Tabb, i)
138
139#define MAKE_BOX_CONSTRUCTORS_uv_2(univary) \
140  MAKE_BOX_CONSTRUCTORS_uv_2T(univary, i)   \
141      MAKE_BOX_CONSTRUCTORS_uv_2T(univary, f)
142
143#define MAKE_BOX_CONSTRUCTORS_uv(univary) MAKE_BOX_CONSTRUCTORS_uv_2(univary)
144
145    MAKE_BOX_CONSTRUCTORS_uv(uniform) MAKE_BOX_CONSTRUCTORS_uv(varying)
146        MAKE_BOX_CONSTRUCTORS_uv_2T_empty(f)
147
148#undef MAKE_BOX_CONSTRUCTORS_uv_2T_fromVec2
149#undef MAKE_BOX_CONSTRUCTORS_uv_2T_fromBox2
150#undef MAKE_BOX_CONSTRUCTORS_uv_2T_empty
151#undef MAKE_BOX_CONSTRUCTORS_uv_2T
152#undef MAKE_BOX_CONSTRUCTORS_uv_2
153#undef MAKE_BOX_CONSTRUCTORS_uv
154
155// -------------------------------------------------------
156// box3 'constructors'
157// -------------------------------------------------------
158
159#define MAKE_BOX_CONSTRUCTORS_uv_3T_fromVec3(univary, Tabb, otherT)           \
160  inline univary box3##Tabb make_box3##Tabb(const univary vec3##otherT lower, \
161                                            const univary vec3##otherT upper) \
162  {                                                                           \
163    univary box3##Tabb bb;                                                    \
164    bb.lower.x = lower.x;                                                     \
165    bb.lower.y = lower.y;                                                     \
166    bb.lower.z = lower.z;                                                     \
167    bb.upper.x = upper.x;                                                     \
168    bb.upper.y = upper.y;                                                     \
169    bb.upper.z = upper.z;                                                     \
170    return bb;                                                                \
171  }
172
173#define MAKE_BOX_CONSTRUCTORS_uv_3T_fromBox3(univary, Tabb, otherT)           \
174  inline univary box3##Tabb make_box3##Tabb(const univary box3##otherT other) \
175  {                                                                           \
176    univary box3##Tabb bb;                                                    \
177    bb.lower.x = other.lower.x;                                               \
178    bb.lower.y = other.lower.y;                                               \
179    bb.lower.z = other.lower.z;                                               \
180    bb.upper.x = other.upper.x;                                               \
181    bb.upper.y = other.upper.y;                                               \
182    bb.upper.z = other.upper.z;                                               \
183    return bb;                                                                \
184  }
185
186#define MAKE_BOX_CONSTRUCTORS_uv_3T_empty(Tabb)                   \
187  inline uniform box3##Tabb make_box3##Tabb##_empty()             \
188  {                                                               \
189    return make_box3##Tabb(make_vec3f(inf), make_vec3f(neg_inf)); \
190  }
191
192#define MAKE_BOX_CONSTRUCTORS_uv_3T(univary, Tabb)                    \
193  MAKE_BOX_CONSTRUCTORS_uv_3T_fromVec3(univary, Tabb, f)              \
194      MAKE_BOX_CONSTRUCTORS_uv_3T_fromVec3(univary, Tabb, i)          \
195                                                                      \
196          MAKE_BOX_CONSTRUCTORS_uv_3T_fromBox3(univary, Tabb, f)      \
197              MAKE_BOX_CONSTRUCTORS_uv_3T_fromBox3(univary, Tabb, fa) \
198                  MAKE_BOX_CONSTRUCTORS_uv_3T_fromBox3(univary, Tabb, i)
199
200#define MAKE_BOX_CONSTRUCTORS_uv_3(univary)                            \
201  MAKE_BOX_CONSTRUCTORS_uv_3T(univary, i) MAKE_BOX_CONSTRUCTORS_uv_3T( \
202      univary, f) MAKE_BOX_CONSTRUCTORS_uv_3T(univary, fa)
203
204#define MAKE_BOX_CONSTRUCTORS_uv(univary) MAKE_BOX_CONSTRUCTORS_uv_3(univary)
205
206            MAKE_BOX_CONSTRUCTORS_uv(uniform) MAKE_BOX_CONSTRUCTORS_uv(varying)
207                MAKE_BOX_CONSTRUCTORS_uv_3T_empty(f)
208                    MAKE_BOX_CONSTRUCTORS_uv_3T_empty(fa)
209
210#undef MAKE_BOX_CONSTRUCTORS_uv_3T_fromVec3
211#undef MAKE_BOX_CONSTRUCTORS_uv_3T_fromBox3
212#undef MAKE_BOX_CONSTRUCTORS_uv_3T_empty
213#undef MAKE_BOX_CONSTRUCTORS_uv_3T
214#undef MAKE_BOX_CONSTRUCTORS_uv_3
215#undef MAKE_BOX_CONSTRUCTORS_uv
216
217// -------------------------------------------------------
218// box 'operations'
219// -------------------------------------------------------
220
221#define BOX_OPERATIONS_uv_N_T(univary, N, T)                         \
222  inline univary vec##N##T box_size(const univary box##N##T &bb)     \
223  {                                                                  \
224    return bb.upper - bb.lower;                                      \
225  }                                                                  \
226                                                                     \
227  inline univary bool isEmpty(const univary box##N##T &bb)           \
228  {                                                                  \
229    return anyLessThan(bb.upper, bb.lower);                          \
230  }                                                                  \
231                                                                     \
232  inline univary box##N##T box_extend(const univary box##N##T bb,    \
233                                      const univary vec##N##T v)     \
234  {                                                                  \
235    return make_box##N##T(min(bb.lower, v), max(bb.upper, v));       \
236  }                                                                  \
237                                                                     \
238  inline univary box##N##T box_extend(const univary box##N##T bb,    \
239                                      const univary box##N##T other) \
240  {                                                                  \
241    return make_box##N##T(min(bb.lower, other.lower),                \
242                          max(bb.upper, other.upper));               \
243  }
244
245#define BOX_OPERATIONS_uv_3fa(univary)                         \
246  inline univary box3fa box_extend(const univary box3fa bb,    \
247                                   const univary vec3f v)      \
248  {                                                            \
249    return make_box3fa(min(bb.lower, v), max(bb.upper, v));    \
250  }                                                            \
251                                                               \
252  inline univary box3fa box_extend(const univary box3fa bb,    \
253                                   const univary box3fa other) \
254  {                                                            \
255    return make_box3fa(min(bb.lower, other.lower),             \
256                       max(bb.upper, other.upper));            \
257  }
258
259#define BOX_OPERATIONS_uv_N(univary, N) \
260  BOX_OPERATIONS_uv_N_T(univary, N, i) BOX_OPERATIONS_uv_N_T(univary, N, f)
261
262#define BOX_OPERATIONS_uv(univary)                                \
263  BOX_OPERATIONS_uv_N(univary, 2) BOX_OPERATIONS_uv_N(univary, 3) \
264      BOX_OPERATIONS_uv_3fa(univary)
265
266                        BOX_OPERATIONS_uv(uniform) BOX_OPERATIONS_uv(varying)
267
268#undef BOX_OPERATIONS_uv_N_T
269#undef BOX_OPERATIONS_uv_N
270#undef BOX_OPERATIONS_uv
271
272                            inline bool box_contains(const uniform box3f &bbox,
273                                                     const varying vec3f &p)
274{
275  return p.x >= bbox.lower.x && p.y >= bbox.lower.y && p.z >= bbox.lower.z &&
276         p.x <= bbox.upper.x && p.y <= bbox.upper.y && p.z <= bbox.upper.z;
277}
278
279
280// this is just a renaming - in some cases the code reads cleaner if we're
281// talking about 'regions' than about boxes
282typedef box1f range1f;
283typedef box2i range2i;
284
285inline void extend(uniform range1f &r, uniform float v)
286{
287  r.lower = min(r.lower, v);
288  r.upper = max(r.upper, v);
289}
290
291inline void extend(uniform range1f &r, varying float v)
292{
293  r.lower = min(r.lower, reduce_min(v));
294  r.upper = max(r.upper, reduce_max(v));
295}
296
297inline void extend(range1f &r, float v)
298{
299  r.lower = min(r.lower, v);
300  r.upper = max(r.upper, v);
301}
302