1 //
2 // Copyright (C) 2009-2021 Intel Corporation
3 //
4 // SPDX-License-Identifier: MIT
5 //
6 //
7
8 #pragma once
9
10 #include "GRLRTASCommon.h"
11
12 #include "affinespace.h"
13
14 #ifndef __OPENCL_VERSION__
15 # include "stdio.h" //for printf
16 #endif
17
18 GRL_NAMESPACE_BEGIN(GRL)
GRL_NAMESPACE_BEGIN(RTAS)19 GRL_NAMESPACE_BEGIN(RTAS)
20
21 GRL_INLINE void AABB3f_init(struct AABB3f *aabb)
22 {
23 aabb->lower[0] = (float)(INFINITY);
24 aabb->lower[1] = (float)(INFINITY);
25 aabb->lower[2] = (float)(INFINITY);
26
27 aabb->upper[0] = -(float)(INFINITY);
28 aabb->upper[1] = -(float)(INFINITY);
29 aabb->upper[2] = -(float)(INFINITY);
30 }
31
AABB3f_load_lower(const struct AABB3f * aabb)32 GRL_INLINE float3 AABB3f_load_lower( const struct AABB3f* aabb )
33 {
34 float3 v = { aabb->lower[0], aabb->lower[1], aabb->lower[2] };
35 return v;
36 }
AABB3f_load_upper(const struct AABB3f * aabb)37 GRL_INLINE float3 AABB3f_load_upper( const struct AABB3f* aabb )
38 {
39 float3 v = { aabb->upper[0], aabb->upper[1], aabb->upper[2] };
40 return v;
41 }
42
AABB3f_extend(struct AABB3f * aabb,const struct AABB3f * v)43 GRL_INLINE void AABB3f_extend(struct AABB3f *aabb, const struct AABB3f *v)
44 {
45 aabb->lower[0] = fmin(aabb->lower[0], v->lower[0]);
46 aabb->lower[1] = fmin(aabb->lower[1], v->lower[1]);
47 aabb->lower[2] = fmin(aabb->lower[2], v->lower[2]);
48 aabb->upper[0] = fmax(aabb->upper[0], v->upper[0]);
49 aabb->upper[1] = fmax(aabb->upper[1], v->upper[1]);
50 aabb->upper[2] = fmax(aabb->upper[2], v->upper[2]);
51 }
52
AABB3f_intersect(struct AABB3f * aabb,struct AABB3f inters)53 GRL_INLINE void AABB3f_intersect(struct AABB3f* aabb, struct AABB3f inters)
54 {
55 aabb->upper[0] = fmin(inters.upper[0],aabb->upper[0]);
56 aabb->upper[1] = fmin(inters.upper[1],aabb->upper[1]);
57 aabb->upper[2] = fmin(inters.upper[2],aabb->upper[2]);
58 aabb->lower[0] = fmax(inters.lower[0],aabb->lower[0]);
59 aabb->lower[1] = fmax(inters.lower[1],aabb->lower[1]);
60 aabb->lower[2] = fmax(inters.lower[2],aabb->lower[2]);
61 }
62
AABB3f_trim_upper(struct AABB3f * aabb,const float * upper)63 GRL_INLINE void AABB3f_trim_upper(struct AABB3f* aabb, const float* upper)
64 {
65 aabb->upper[0] = fmin(upper[0], aabb->upper[0]);
66 aabb->upper[1] = fmin(upper[1], aabb->upper[1]);
67 aabb->upper[2] = fmin(upper[2], aabb->upper[2]);
68 }
69
AABB3f_set(struct AABB3f * aabb,float3 lower,float3 upper)70 GRL_INLINE void AABB3f_set( struct AABB3f* aabb, float3 lower, float3 upper )
71 {
72 aabb->lower[0] = lower.x ;
73 aabb->lower[1] = lower.y ;
74 aabb->lower[2] = lower.z ;
75 aabb->upper[0] = upper.x ;
76 aabb->upper[1] = upper.y ;
77 aabb->upper[2] = upper.z ;
78 }
79
AABB3f_extend_point(struct AABB3f * aabb,const float3 p)80 inline void AABB3f_extend_point(struct AABB3f *aabb, const float3 p)
81 {
82 aabb->lower[0] = fmin(aabb->lower[0], p.x);
83 aabb->lower[1] = fmin(aabb->lower[1], p.y);
84 aabb->lower[2] = fmin(aabb->lower[2], p.z);
85 aabb->upper[0] = fmax(aabb->upper[0], p.x);
86 aabb->upper[1] = fmax(aabb->upper[1], p.y);
87 aabb->upper[2] = fmax(aabb->upper[2], p.z);
88 }
89
AABB3f_extendlu(struct AABB3f * aabb,const float3 lower,const float3 upper)90 GRL_INLINE void AABB3f_extendlu(struct AABB3f *aabb, const float3 lower, const float3 upper)
91 {
92 aabb->lower[0] = fmin(aabb->lower[0], lower.x);
93 aabb->lower[1] = fmin(aabb->lower[1], lower.y);
94 aabb->lower[2] = fmin(aabb->lower[2], lower.z);
95 aabb->upper[0] = fmax(aabb->upper[0], upper.x);
96 aabb->upper[1] = fmax(aabb->upper[1], upper.y);
97 aabb->upper[2] = fmax(aabb->upper[2], upper.z);
98 }
99
AABB3f_size(struct AABB3f * aabb)100 GRL_INLINE float3 AABB3f_size(struct AABB3f* aabb)
101 {
102 return AABB3f_load_upper(aabb) - AABB3f_load_lower(aabb);
103 }
104
AABB3f_halfArea(struct AABB3f * aabb)105 GRL_INLINE float AABB3f_halfArea(struct AABB3f *aabb)
106 {
107 const float3 d = AABB3f_load_upper( aabb ) - AABB3f_load_lower( aabb );
108 return d.x* (d.y + d.z) + (d.y * d.z);
109 }
110
halfArea_AABB3f(struct AABB3f * aabb)111 GRL_INLINE float halfArea_AABB3f(struct AABB3f *aabb) // TODO: Remove me
112 {
113 const float3 d = { aabb->upper[0] - aabb->lower[0], aabb->upper[1] - aabb->lower[1], aabb->upper[2] - aabb->lower[2] };
114 return fma(d.x, (d.y + d.z), d.y * d.z);
115 }
116
AABB3f_set_lower(struct AABB3f * aabb,float3 lower)117 GRL_INLINE void AABB3f_set_lower(struct AABB3f* aabb, float3 lower)
118 {
119 aabb->lower[0] = lower.x;
120 aabb->lower[1] = lower.y;
121 aabb->lower[2] = lower.z;
122 }
123
AABB3f_set_upper(struct AABB3f * aabb,float3 upper)124 GRL_INLINE void AABB3f_set_upper(struct AABB3f* aabb, float3 upper)
125 {
126 aabb->upper[0] = upper.x;
127 aabb->upper[1] = upper.y;
128 aabb->upper[2] = upper.z;
129 }
130
conservativeExtent(float3 extent)131 GRL_INLINE float3 conservativeExtent(float3 extent)
132 {
133 const float v = FLT_EPSILON * fmax(extent.x, fmax(extent.y, extent.z));
134 float3 v3 = { v,v,v };
135 extent = extent + v3;
136 return extent;
137 }
138
transform_aabb(float3 lower,float3 upper,const float * Transform)139 inline struct AABB3f GRL_OVERLOADABLE transform_aabb(float3 lower, float3 upper, const float* Transform)
140 {
141 #if 1
142 // We use an abs-matrix to transform the AABB extent vector, which is enough to compute the area
143 // New AABB is center +- Extent.
144 //
145 // For derivation see:
146 // https://zeux.io/2010/10/17/aabb-from-obb-with-component-wise-abs/
147 //
148
149 float3 Center = (upper + lower) * 0.5f;
150 float3 Extent = (conservativeExtent(upper) - lower) * 0.5f;
151
152 float cx = Center.x * Transform[0] + Center.y * Transform[1] + Center.z * Transform[2] + Transform[3];
153 float cy = Center.x * Transform[4] + Center.y * Transform[5] + Center.z * Transform[6] + Transform[7];
154 float cz = Center.x * Transform[8] + Center.y * Transform[9] + Center.z * Transform[10] + Transform[11];
155 float ex = Extent.x * fabs(Transform[0]) + Extent.y * fabs(Transform[1]) + Extent.z * fabs(Transform[2]);
156 float ey = Extent.x * fabs(Transform[4]) + Extent.y * fabs(Transform[5]) + Extent.z * fabs(Transform[6]);
157 float ez = Extent.x * fabs(Transform[8]) + Extent.y * fabs(Transform[9]) + Extent.z * fabs(Transform[10]);
158
159 Center.x = cx; Center.y = cy; Center.z = cz;
160 Extent.x = ex; Extent.y = ey; Extent.z = ez;
161
162 struct AABB3f box;
163 AABB3f_set_lower(&box, Center - Extent);
164 AABB3f_set_upper(&box, Center + Extent);
165 return box;
166 #else
167 struct AffineSpace3f xfm = AffineSpace3f_load_row_major(Transform);
168
169 float3 plll = { lower.x, lower.y, lower.z };
170 float3 pllu = { lower.x, lower.y, upper.z };
171 float3 plul = { lower.x, upper.y, lower.z };
172 float3 pluu = { lower.x, upper.y, upper.z };
173 float3 pull = { upper.x, lower.y, lower.z };
174 float3 pulu = { upper.x, lower.y, upper.z };
175 float3 puul = { upper.x, upper.y, lower.z };
176 float3 puuu = { upper.x, upper.y, upper.z };
177 plll = xfmPoint(xfm, plll) ;
178 pllu = xfmPoint(xfm, pllu) ;
179 plul = xfmPoint(xfm, plul) ;
180 pluu = xfmPoint(xfm, pluu) ;
181 pull = xfmPoint(xfm, pull) ;
182 pulu = xfmPoint(xfm, pulu) ;
183 puul = xfmPoint(xfm, puul) ;
184 puuu = xfmPoint(xfm, puuu) ;
185
186 float3 p1_min = fmin(plll, pull);
187 float3 p2_min = fmin(pllu, pulu);
188 float3 p3_min = fmin(plul, puul);
189 float3 p4_min = fmin(pluu, puuu);
190 float3 p1_max = fmax(plll, pull);
191 float3 p2_max = fmax(pllu, pulu);
192 float3 p3_max = fmax(plul, puul);
193 float3 p4_max = fmax(pluu, puuu);
194 p1_min = fmin(p1_min, p3_min);
195 p2_min = fmin(p2_min, p4_min);
196 p1_max = fmax(p1_max, p3_max);
197 p2_max = fmax(p2_max, p4_max);
198 p1_min = fmin(p1_min, p2_min);
199 p1_max = fmax(p1_max, p2_max);
200
201 AABB3f out = {
202 {p1_min.x,p1_min.y,p1_min.z},
203 {p1_max.x,p1_max.y,p1_max.z}
204 };
205 return out;
206 #endif
207 }
208
transform_aabb(struct AABB3f box,const float * Transform)209 GRL_INLINE struct AABB3f GRL_OVERLOADABLE transform_aabb(struct AABB3f box, const float* Transform)
210 {
211 float3 lower = { box.lower[0], box.lower[1], box.lower[2] };
212 float3 upper = { box.upper[0], box.upper[1], box.upper[2] };
213 return transform_aabb(lower, upper, Transform);
214 }
215
AABB3f_transform(struct AffineSpace3f xfm,struct AABB3f in)216 GRL_INLINE struct AABB3f AABB3f_transform(struct AffineSpace3f xfm, struct AABB3f in)
217 {
218 struct AABB3f out;
219 float rmTransform[12];
220 load_row_major_from_AffineSpace3f(xfm, rmTransform);
221 out = transform_aabb(in, rmTransform);
222
223 return out;
224 }
225
AABB3f_isIn(struct AABB3f bigger,float3 contained)226 GRL_INLINE bool AABB3f_isIn(struct AABB3f bigger, float3 contained)
227 {
228 bool iscontained =
229 contained.x >= bigger.lower[0] &&
230 contained.y >= bigger.lower[1] &&
231 contained.z >= bigger.lower[2] &&
232 contained.x <= bigger.upper[0] &&
233 contained.y <= bigger.upper[1] &&
234 contained.z <= bigger.upper[2];
235
236 return iscontained;
237 }
238
AABB3f_isSubset(struct AABB3f bigger,struct AABB3f contained)239 GRL_INLINE bool AABB3f_isSubset(struct AABB3f bigger, struct AABB3f contained)
240 {
241 bool iscontained =
242 contained.lower[0] >= bigger.lower[0] &&
243 contained.lower[1] >= bigger.lower[1] &&
244 contained.lower[2] >= bigger.lower[2] &&
245 contained.upper[0] <= bigger.upper[0] &&
246 contained.upper[1] <= bigger.upper[1] &&
247 contained.upper[2] <= bigger.upper[2];
248
249 return iscontained;
250 }
251
AABB3f_is_degenerate(struct AABB3f * box)252 GRL_INLINE bool AABB3f_is_degenerate(struct AABB3f* box )
253 {
254 return box->lower[0] > box->upper[0] ||
255 box->lower[1] > box->upper[1] ||
256 box->lower[2] > box->upper[2];
257 }
258
AABB3f_print(struct AABB3f * aabb)259 GRL_INLINE void AABB3f_print(struct AABB3f *aabb)
260 {
261 printf("AABB {\n");
262 printf(" lower = %f, %f, %f\n", aabb->lower[0], aabb->lower[1], aabb->lower[2]);
263 printf(" upper = %f, %f, %f\n", aabb->upper[0], aabb->upper[1], aabb->upper[2]);
264 printf("}\n");
265 }
266
267
268
269 #ifdef __OPENCL_VERSION__
AABB3f_sub_group_shuffle(struct AABB3f * aabb,const uint slotID)270 GRL_INLINE struct AABB3f AABB3f_sub_group_shuffle(struct AABB3f *aabb, const uint slotID)
271 {
272 struct AABB3f bounds;
273 bounds.lower[0] = intel_sub_group_shuffle(aabb->lower[0], slotID);
274 bounds.lower[1] = intel_sub_group_shuffle(aabb->lower[1], slotID);
275 bounds.lower[2] = intel_sub_group_shuffle(aabb->lower[2], slotID);
276 bounds.upper[0] = intel_sub_group_shuffle(aabb->upper[0], slotID);
277 bounds.upper[1] = intel_sub_group_shuffle(aabb->upper[1], slotID);
278 bounds.upper[2] = intel_sub_group_shuffle(aabb->upper[2], slotID);
279 return bounds;
280 }
281
AABB3f_sub_group_reduce(struct AABB3f * aabb)282 GRL_INLINE struct AABB3f AABB3f_sub_group_reduce(struct AABB3f *aabb)
283 {
284 struct AABB3f bounds;
285 bounds.lower[0] = sub_group_reduce_min(aabb->lower[0]);
286 bounds.lower[1] = sub_group_reduce_min(aabb->lower[1]);
287 bounds.lower[2] = sub_group_reduce_min(aabb->lower[2]);
288 bounds.upper[0] = sub_group_reduce_max(aabb->upper[0]);
289 bounds.upper[1] = sub_group_reduce_max(aabb->upper[1]);
290 bounds.upper[2] = sub_group_reduce_max(aabb->upper[2]);
291 return bounds;
292 }
293
AABB3f_sub_group_scan_exclusive_min_max(struct AABB3f * aabb)294 GRL_INLINE struct AABB3f AABB3f_sub_group_scan_exclusive_min_max(struct AABB3f *aabb)
295 {
296 struct AABB3f bounds;
297 bounds.lower[0] = sub_group_scan_exclusive_min(aabb->lower[0]);
298 bounds.lower[1] = sub_group_scan_exclusive_min(aabb->lower[1]);
299 bounds.lower[2] = sub_group_scan_exclusive_min(aabb->lower[2]);
300 bounds.upper[0] = sub_group_scan_exclusive_max(aabb->upper[0]);
301 bounds.upper[1] = sub_group_scan_exclusive_max(aabb->upper[1]);
302 bounds.upper[2] = sub_group_scan_exclusive_max(aabb->upper[2]);
303 return bounds;
304 }
305
AABB3f_sub_group_scan_inclusive_min_max(struct AABB3f * aabb)306 GRL_INLINE struct AABB3f AABB3f_sub_group_scan_inclusive_min_max(struct AABB3f *aabb)
307 {
308 struct AABB3f bounds;
309 bounds.lower[0] = sub_group_scan_inclusive_min(aabb->lower[0]);
310 bounds.lower[1] = sub_group_scan_inclusive_min(aabb->lower[1]);
311 bounds.lower[2] = sub_group_scan_inclusive_min(aabb->lower[2]);
312 bounds.upper[0] = sub_group_scan_inclusive_max(aabb->upper[0]);
313 bounds.upper[1] = sub_group_scan_inclusive_max(aabb->upper[1]);
314 bounds.upper[2] = sub_group_scan_inclusive_max(aabb->upper[2]);
315 return bounds;
316 }
317
AABB3f_atomic_merge_local_nocheck(local struct AABB3f * aabb,const float4 lower,const float4 upper)318 GRL_INLINE void AABB3f_atomic_merge_local_nocheck(local struct AABB3f *aabb, const float4 lower, const float4 upper)
319 {
320 atomic_min((local float *)&aabb->lower + 0, lower.x);
321 atomic_min((local float *)&aabb->lower + 1, lower.y);
322 atomic_min((local float *)&aabb->lower + 2, lower.z);
323 atomic_max((local float *)&aabb->upper + 0, upper.x);
324 atomic_max((local float *)&aabb->upper + 1, upper.y);
325 atomic_max((local float *)&aabb->upper + 2, upper.z);
326 }
327
328
AABB3f_atomic_merge_global_lu(global struct AABB3f * aabb,const float3 lower,const float3 upper)329 GRL_INLINE void AABB3f_atomic_merge_global_lu( global struct AABB3f* aabb, const float3 lower, const float3 upper )
330 {
331 atomic_min( (global float*) & aabb->lower + 0, lower.x );
332 atomic_min( (global float*) & aabb->lower + 1, lower.y );
333 atomic_min( (global float*) & aabb->lower + 2, lower.z );
334 atomic_max( (global float*) & aabb->upper + 0, upper.x );
335 atomic_max( (global float*) & aabb->upper + 1, upper.y );
336 atomic_max( (global float*) & aabb->upper + 2, upper.z );
337 }
338
AABB3f_atomic_merge_local_lu(local struct AABB3f * aabb,const float3 lower,const float3 upper)339 GRL_INLINE void AABB3f_atomic_merge_local_lu( local struct AABB3f* aabb, const float3 lower, const float3 upper )
340 {
341 atomic_min( (local float*) & aabb->lower + 0, lower.x );
342 atomic_min( (local float*) & aabb->lower + 1, lower.y );
343 atomic_min( (local float*) & aabb->lower + 2, lower.z );
344 atomic_max( (local float*) & aabb->upper + 0, upper.x );
345 atomic_max( (local float*) & aabb->upper + 1, upper.y );
346 atomic_max( (local float*) & aabb->upper + 2, upper.z );
347 }
348
Uniform_AABB3f_atomic_merge_local_sub_group_lu(uniform local struct AABB3f * aabb,const float3 lower,const float3 upper)349 GRL_INLINE void Uniform_AABB3f_atomic_merge_local_sub_group_lu(uniform local struct AABB3f* aabb, const float3 lower, const float3 upper)
350 {
351 float lx = sub_group_reduce_min(lower.x);
352 float ly = sub_group_reduce_min(lower.y);
353 float lz = sub_group_reduce_min(lower.z);
354
355 float ux = sub_group_reduce_max(upper.x);
356 float uy = sub_group_reduce_max(upper.y);
357 float uz = sub_group_reduce_max(upper.z);
358
359 if (get_sub_group_local_id() == 0)
360 {
361 atomic_min((local float*) & aabb->lower + 0, lx);
362 atomic_min((local float*) & aabb->lower + 1, ly);
363 atomic_min((local float*) & aabb->lower + 2, lz);
364 atomic_max((local float*) & aabb->upper + 0, ux);
365 atomic_max((local float*) & aabb->upper + 1, uy);
366 atomic_max((local float*) & aabb->upper + 2, uz);
367 }
368 }
369
AABB3f_atomic_merge_global_sub_group_lu(uniform global struct AABB3f * aabb,const float3 lower,const float3 upper)370 GRL_INLINE void AABB3f_atomic_merge_global_sub_group_lu(uniform global struct AABB3f* aabb, const float3 lower, const float3 upper)
371 {
372 uint lane = get_sub_group_local_id();
373 float l[3];
374 l[0] = sub_group_reduce_min(lower.x);
375 l[1] = sub_group_reduce_min(lower.y);
376 l[2] = sub_group_reduce_min(lower.z);
377 float u[3];
378 u[0] = sub_group_reduce_max(upper.x);
379 u[1] = sub_group_reduce_max(upper.y);
380 u[2] = sub_group_reduce_max(upper.z);
381
382 if (lane < 3)
383 {
384 atomic_min((global float*)&aabb->lower + lane, l[lane]);
385 atomic_max((global float*)&aabb->upper + lane, u[lane]);
386 }
387 }
388
AABB3f_atomic_merge_global(global struct AABB3f * aabb,struct AABB3f * other)389 GRL_INLINE void AABB3f_atomic_merge_global( global struct AABB3f* aabb, struct AABB3f* other )
390 {
391 float3 lower = AABB3f_load_lower( other );
392 float3 upper = AABB3f_load_upper( other );
393 atomic_min( (global float*) & aabb->lower + 0, lower.x );
394 atomic_min( (global float*) & aabb->lower + 1, lower.y );
395 atomic_min( (global float*) & aabb->lower + 2, lower.z );
396 atomic_max( (global float*) & aabb->upper + 0, upper.x );
397 atomic_max( (global float*) & aabb->upper + 1, upper.y );
398 atomic_max( (global float*) & aabb->upper + 2, upper.z );
399 }
400
AABB3f_atomic_merge_localBB_nocheck(local struct AABB3f * aabb,struct AABB3f * bb)401 GRL_INLINE void AABB3f_atomic_merge_localBB_nocheck( local struct AABB3f* aabb, struct AABB3f* bb )
402 {
403 atomic_min( (local float*) & aabb->lower + 0, bb->lower[0] );
404 atomic_min( (local float*) & aabb->lower + 1, bb->lower[1] );
405 atomic_min( (local float*) & aabb->lower + 2, bb->lower[2] );
406 atomic_max( (local float*) & aabb->upper + 0, bb->upper[0] );
407 atomic_max( (local float*) & aabb->upper + 1, bb->upper[1] );
408 atomic_max( (local float*) & aabb->upper + 2, bb->upper[2] );
409 }
410
AABB3f_atomic_merge_local(local struct AABB3f * aabb,const float4 lower,const float4 upper)411 GRL_INLINE void AABB3f_atomic_merge_local(local struct AABB3f *aabb, const float4 lower, const float4 upper)
412 {
413 if (lower.x < aabb->lower[0])
414 atomic_min((local float *)&aabb->lower + 0, lower.x);
415 if (lower.y < aabb->lower[1])
416 atomic_min((local float *)&aabb->lower + 1, lower.y);
417 if (lower.z < aabb->lower[2])
418 atomic_min((local float *)&aabb->lower + 2, lower.z);
419 if (upper.x > aabb->upper[0])
420 atomic_max((local float *)&aabb->upper + 0, upper.x);
421 if (upper.y > aabb->upper[1])
422 atomic_max((local float *)&aabb->upper + 1, upper.y);
423 if (upper.z > aabb->upper[2])
424 atomic_max((local float *)&aabb->upper + 2, upper.z);
425 }
426
AABB3f_atomic_merge_global_local(global struct AABB3f * dest,local struct AABB3f * source)427 GRL_INLINE void AABB3f_atomic_merge_global_local(global struct AABB3f *dest, local struct AABB3f *source)
428 {
429 float3 l = AABB3f_load_lower(source);
430 float3 u = AABB3f_load_upper(source);
431 atomic_min((global float *)&dest->lower + 0, l.x );
432 atomic_min((global float *)&dest->lower + 1, l.y );
433 atomic_min((global float *)&dest->lower + 2, l.z );
434 atomic_max((global float *)&dest->upper + 0, u.x );
435 atomic_max((global float *)&dest->upper + 1, u.y );
436 atomic_max((global float *)&dest->upper + 2, u.z );
437 }
438
439
AABB3f_construct(float3 min,float3 max)440 struct AABB3f AABB3f_construct( float3 min, float3 max )
441 {
442 struct AABB3f bb;
443 bb.lower[0] = min.x; bb.lower[1] = min.y; bb.lower[2] = min.z;
444 bb.upper[0] = max.x; bb.upper[1] = max.y; bb.upper[2] = max.z;
445 return bb;
446 }
447
AABB3f_select(struct AABB3f left,struct AABB3f right,int3 cond)448 struct AABB3f AABB3f_select( struct AABB3f left, struct AABB3f right, int3 cond )
449 {
450 float3 l = select( AABB3f_load_lower(&left), AABB3f_load_lower(&right), cond );
451 float3 u = select( AABB3f_load_upper(&left), AABB3f_load_upper(&right), cond );
452 return AABB3f_construct( l, u );
453 }
454
455 #endif
456
457 GRL_NAMESPACE_END(RTAS)
458 GRL_NAMESPACE_END(GRL)
459
460