1//: Cell Utility functions.
2#define X_MIN (short4)(1,0,0,0);
3#define X_MAX (short4)(1,0,0,1);
4#define Y_MIN (short4)(0,1,0,0);
5#define Y_MAX (short4)(0,1,0,1);
6#define Z_MIN (short4)(0,0,1,0);
7#define Z_MAX (short4)(0,0,1,1);
8
9/*
10uint rgbaFloatToInt(float4 rgba)
11{
12    rgba.x = clamp(rgba.x,0.0f,1.0f);
13    rgba.y = clamp(rgba.y,0.0f,1.0f);
14    rgba.z = clamp(rgba.z,0.0f,1.0f);
15    rgba.w = clamp(rgba.w,0.0f,1.0f);
16    return ((uint)(rgba.w*255.0f)<<24) | ((uint)(rgba.z*255.0f)<<16) | ((uint)(rgba.y*255.0f)<<8) | (uint)(rgba.x*255.0f);
17}
18
19uint intensityFloatToInt(float intensity)
20{
21    intensity = clamp(intensity, 0.0f, 1.0f);
22    return ((uint)(intensity*255.0f)<<24) | ((uint)(intensity*255.0f)<<16) | ((uint)(intensity*255.0f)<<8) | (uint)(intensity*255.0f);
23}
24*/
25
26//---------------------------------------------------------------------
27// The vector result for the exit face as a short vector in X, Y, Z
28// The element corresponding to the exit coordinate has the value 1
29// The other coordinate elements are 0. The return has the 'w' element
30// set to 1 if the result is a max face otherwise if a min face it is 0.
31// cell_min is the minimum point in the cell and cell_max is the
32// maximum point in the cell.
33//---------------------------------------------------------------------
34short4 cell_exit_face(float4 exit_point, float4 cell_min, float4 cell_max)
35{
36  float4 min_diff =   fabs(exit_point-cell_min);
37  float4 max_diff =   fabs(exit_point-cell_max);
38
39  float min=1e5f;
40  short4 faceid=(short4)(-1,-1,-1,-1);
41  if (min_diff.x<min)
42  {
43    min=min_diff.x;
44    faceid=X_MIN;
45  }
46  if (min_diff.y<min)
47  {
48    min=min_diff.y;
49    faceid=Y_MIN;
50  }
51  if (min_diff.z<min)
52  {
53    min=min_diff.z;
54    faceid=Z_MIN;
55  }
56  if (max_diff.x<min)
57  {
58    min=max_diff.x;
59    faceid=X_MAX;
60  }
61  if (max_diff.y<min)
62  {
63    min=max_diff.y;
64    faceid=Y_MAX;
65  }
66  if (max_diff.z<min)
67  {
68    min=max_diff.z;
69    faceid=Z_MAX;
70  }
71
72  return faceid;
73}
74
75short4 cell_exit_face_safe(float4 exit_point,float4 ray_d, float4 cell_min, float4 cell_max)
76{
77  float4 min_diff =   fabs(exit_point-cell_min);
78  float4 max_diff =   fabs(exit_point-cell_max);
79
80  float min=1e5f;
81  short4 faceid=(short4)(-1,-1,-1,-1);
82  if (min_diff.x<min && ray_d.x<0)
83  {
84    min=min_diff.x;
85    faceid=X_MIN;
86  }
87  if (min_diff.y<min && ray_d.y<0)
88  {
89    min=min_diff.y;
90    faceid=Y_MIN;
91  }
92  if (min_diff.z<min && ray_d.z<0)
93  {
94    min=min_diff.z;
95    faceid=Z_MIN;
96  }
97  if (max_diff.x<min && ray_d.x>0)
98  {
99    min=max_diff.x;
100    faceid=X_MAX;
101  }
102  if (max_diff.y<min&& ray_d.y>0)
103  {
104    min=max_diff.y;
105    faceid=Y_MAX;
106  }
107  if (max_diff.z<min&& ray_d.z>0)
108  {
109    min=max_diff.z;
110    faceid=Z_MAX;
111  }
112
113  return faceid;
114}
115
116short4 cell_exit_face_but_not_entry_face(float4 exit_point, float4 cell_min, float4 cell_max,short4 entry_face)
117{
118  float4 min_diff =  fabs(exit_point-cell_min);
119  float4 max_diff =  fabs(exit_point-cell_max);
120
121  short4 faceid=(short4) -1;
122
123  float min=1.0f;
124
125  // short4 temp; not used at the moment
126  if (min_diff.x<min)
127  {
128    if (!(entry_face.x==1 && entry_face.w==0 ))
129    {
130      min=min_diff.x;
131      faceid=X_MIN;
132    }
133  }
134  if (min_diff.y<min )
135  {
136    if (!(entry_face.y==1 && entry_face.w==0 ))
137    {
138      min=min_diff.y;
139      faceid=Y_MIN;
140    }
141  }
142  if (min_diff.z<min)
143  {
144    if (!(entry_face.z==1 && entry_face.w==0 ))
145    {
146      min=min_diff.z;
147      faceid=Z_MIN;
148    }
149  }
150  if (max_diff.x<min )
151  {
152    if (!(entry_face.x==1 && entry_face.w==1 ))
153    {
154      min=max_diff.x;
155      faceid=X_MAX;
156    }
157  }
158  if (max_diff.y<min )
159  {
160    if (!(entry_face.y==1 && entry_face.w==1 ))
161    {
162      min=max_diff.y;
163      faceid=Y_MAX;
164    }
165  }
166  if (max_diff.z<min )
167  {
168    if (!(entry_face.z==1 && entry_face.w==1 ))
169    {
170      min=max_diff.z;
171      faceid=Z_MAX;
172    }
173  }
174
175  return faceid;
176}
177
178//-------------------------------------------------------------------
179// Given the location code determine the bounding box for the
180// cell in local tree coordinates, i.e. the max bounds of the
181// tree are (0,0,0)->(1,1,1)
182//-------------------------------------------------------------------
183void cell_bounding_box(short4 loc_code, int n_levels,
184                       float4* cell_min, float4* cell_max)
185{
186  float tree_size = (float)(1<<(n_levels-1));
187  float cell_size = ((float)(1<<loc_code.w))/tree_size;
188  float4 rtsize = (float4)(1.0f/tree_size);
189  (*cell_min) = convert_float4(loc_code);
190  (*cell_min) *= rtsize;
191  float4 csize = (float4)cell_size;
192  (*cell_max) = (*cell_min) + csize;
193  (*cell_min).w = 0.0f;   (*cell_max).w = 0.0f;
194}
195
196
197#if 1
198//--------------------------------------------------------------------------
199// Given the ray origin, ray_o and its direction, ray_d and the cell min
200// and max points, find the ray parameters, tnear and tfar that correspond
201// to the entry and exit points of the cell-ray intersection. If the ray
202// does not intersect the cell, 0 is returned.
203//-------------------------------------------------------------------------
204int intersect_cell(float4 ray_o, float4 ray_d, float4 cell_min, float4 cell_max, float *tnear, float *tfar)
205{
206  // compute intersection of ray with all six cell planes
207  float4 invR = (float4)(1.0f,1.0f,1.0f,1.0f) / ray_d;
208
209  float4 tmin = invR * (cell_min - ray_o);
210  float4 tmax = invR * (cell_max - ray_o);
211
212  // re-order intersections to find smallest and largest on each axis
213  // minimum t values for either bounding plane
214  float4 tmin_s =   min(tmax, tmin);
215  // maximum t values for either bounding plane
216  float4 tmax_s =   max(tmax, tmin);
217
218  if (ray_d.x ==0.0f) {
219    tmin_s.x = -3.4e38f;
220    tmax_s.x = 3.4e38f;
221  }
222  if (ray_d.y ==0.0f) {
223    tmin_s.y = -3.4e38f;
224    tmax_s.y = 3.4e38f;
225  }
226  if (ray_d.z ==0.0f) {
227    tmin_s.z = -3.4e38f;
228    tmax_s.z = 3.4e38f;
229  }
230
231  // find the largest tmin and the smallest tmax
232  float largest_tmin =   max(  max(tmin_s.x, tmin_s.y),   max(tmin_s.x, tmin_s.z));
233  float smallest_tmax =   min(  min(tmax_s.x, tmax_s.y),   min(tmax_s.x, tmax_s.z));
234  *tnear = largest_tmin;
235  *tfar = smallest_tmax;
236  return smallest_tmax > largest_tmin;
237}
238#endif
239
240#if 0
241//------------------------------------------------------------------------------
242// New Intersect Cell takes in ray origin, ray direction, cell min and cell
243// dimension (doesn't not assume cubic volume).  Doesn't use cell_max
244// Lots of redundant code - everything here depends on RAY_D
245//------------------------------------------------------------------------------
246#if 0
247int intersect_cell(float4 ray_o, float4 ray_d, float4 cell_min, float4 cell_dims, float *tnear, float *tfar)
248{
249  // compute intersection of ray with all six cell planes
250  float4 tmin = (1.0/ray_d) * (cell_min - ray_o);
251  float4 tmax = (1.0/ray_d) * (cell_min + cell_dims - ray_o);
252
253  // re-order intersections to find smallest and largest on each axis
254  // minimum t values for either bounding plane
255  float4 tmin_s =   min(tmax, tmin);
256  // maximum t values for either bounding plane
257  float4 tmax_s =   max(tmax, tmin);
258
259  if (ray_d.x == 0.0f) {
260    tmin_s.x = -3.4e38f;
261    tmax_s.x = 3.4e38f;
262  }
263  if (ray_d.y == 0.0f) {
264    tmin_s.y = -3.4e38f;
265    tmax_s.y = 3.4e38f;
266  }
267  if (ray_d.z == 0.0f) {
268    tmin_s.z = -3.4e38f;
269    tmax_s.z = 3.4e38f;
270  }
271
272  // find the largest tmin and the smallest tmax
273  float largest_tmin  =   max(  max(tmin_s.x, tmin_s.y),   max(tmin_s.x, tmin_s.z));
274  float smallest_tmax =   min(  min(tmax_s.x, tmax_s.y),   min(tmax_s.x, tmax_s.z));
275  *tnear = largest_tmin;
276  *tfar = smallest_tmax;
277  return smallest_tmax > largest_tmin;
278}
279#endif
280//------------------------------------------------------------------------------
281// Optimized intersect cell takes in ray origin, ray direction, cell min and cell
282// dimension (doesn't not assume cubic volume).  Doesn't use cell_max
283// Lots of redundant code - everything here depends on RAY_D
284//------------------------------------------------------------------------------
285int intersect_cell_opt(float4 ray_o, float4 ray_d, float4 ray_d_inv, float4 cell_min, float4 cell_dims, float *tnear, float *tfar)
286{
287
288  // compute intersection of ray with all six cell planes
289  float4 tmin = ray_d_inv * (cell_min - ray_o);
290  float4 tmax = tmin + ray_d_inv*cell_dims;
291  //float4 tmax = ray_d_inv * (cell_min + cell_dims - ray_o);
292
293  // re-order intersections to find smallest and largest on each axis
294  // minimum t values for either bounding plane
295  float4 tmin_s =   min(tmax, tmin);
296  // maximum t values for either bounding plane
297  float4 tmax_s =   max(tmax, tmin);
298
299  // find the largest tmin and the smallest tmax
300  float largest_tmin  =   max(  max(tmin_s.x, tmin_s.y),   max(tmin_s.x, tmin_s.z));
301  float smallest_tmax =   min(  min(tmax_s.x, tmax_s.y),   min(tmax_s.x, tmax_s.z));
302  *tnear = largest_tmin;
303  *tfar = smallest_tmax;
304  return smallest_tmax > largest_tmin;
305}
306#endif
307
308
309/*
310//------------------------------------------------------------------------------
311// Intersect scene takes in 3 floats for ray o, ray d, ray d inv
312//------------------------------------------------------------------------------
313void intersect_scene(float ray_ox, float ray_oy, float ray_oz,
314                     float ray_dx, float ray_dy, float ray_dz,
315                     //float min_fx, float min_fy, float min_fz,
316                     //float max_fx, float max_fy, float max_fz,
317                     float4 min_face, float4 max_face,
318                     float *tnear, float *tfar)
319{
320
321  // compute intersection of ray with all six cell planes
322  float4 tmin = ray_d_inv * (cell_min - ray_o);
323  float4 tmax = tmin + ray_d_inv*cell_dims;
324  //float4 tmax = ray_d_inv * (cell_min + cell_dims - ray_o);
325
326  // re-order intersections to find smallest and largest on each axis
327  // minimum t values for either bounding plane
328  float4 tmin_s =   min(tmax, tmin);
329  // maximum t values for either bounding plane
330  float4 tmax_s =   max(tmax, tmin);
331
332  // find the largest tmin and the smallest tmax
333  float largest_tmin  =   max(  max(tmin_s.x, tmin_s.y),   max(tmin_s.x, tmin_s.z));
334  float smallest_tmax =   min(  min(tmax_s.x, tmax_s.y),   min(tmax_s.x, tmax_s.z));
335  *tnear = largest_tmin;
336  *tfar = smallest_tmax;
337  return smallest_tmax > largest_tmin;
338}
339*/
340
341
342//-----------------------------------------------------------------------------
343// find exit tvalue given an array of exit faces
344//-----------------------------------------------------------------------------
345float calc_t_exit(float4 ray_o, float4 ray_d_inv, float4 exit_planes)
346{
347  float4 tvec = (exit_planes - ray_o) * ray_d_inv;
348  return min(min(tvec.x, tvec.y), tvec.z);
349}
350
351//--------------------------------------------------------------------------
352// Find the ray entry point to a box that encloses the entire octree
353// Returns 0 if there is no intersection.
354//-------------------------------------------------------------------------
355int cell_entry_point(float4 ray_org, float4 ray_dir,
356                     float4 cell_min, float4 cell_max, float4* entry_pt)
357{
358  float tnear = 0, tfar =0;
359  int hit = intersect_cell(ray_org, ray_dir, cell_min, cell_max,
360                           &tnear, &tfar);
361  if (!hit) {
362    (*entry_pt)=(float4)(-1.0f, -1.0f, -1.0f, -1.0f);
363    return 0;
364  }
365  else {
366    (*entry_pt) = ray_org + tnear*ray_dir;
367    return 1;
368  }
369}
370
371//--------------------------------------------------------------------------
372// Find the ray exit point from a cell that is specified by its loc_code
373// Returns 0 if there is no intersection with the cell
374//-------------------------------------------------------------------------
375
376int cell_exit_point(float4 ray_org, float4 ray_dir,
377                    float4 cell_min, float4 cell_max, float4* exit_pt)
378{
379  float tnear = 0, tfar =0;
380  int hit = intersect_cell(ray_org, ray_dir, cell_min, cell_max,
381                           &tnear, &tfar);
382  if (!hit) {
383    (*exit_pt)=(float4)(tnear, tfar, -1.0f, -1.0f);
384    return 0;
385  }
386  else {
387    (*exit_pt) = ray_org + tfar*ray_dir;
388    return 1;
389  }
390}
391
392int cell_contains_exit_pt(int n_levels, short4 loc_code, float4 exit_pt)
393{
394  exit_pt.w = 0.0f; ///should be no side effects since arg is copied
395  float4 cell_min, cell_max;
396  cell_bounding_box(loc_code, n_levels, &cell_min, &cell_max);
397  int4 test =isless(exit_pt , cell_min);
398  if (any(test)) return 0;
399  test =isgreater(exit_pt , cell_max);
400  if (any(test)) return 0;
401  return 1;
402}
403
404