1.3.64
 
Loading...
Searching...
No Matches
primitiveIntersection.cu
Go to the documentation of this file.
1
16#include <optix.h>
17#include <optixu/optixu_aabb_namespace.h>
18#include <optixu/optixu_math_namespace.h>
19#include <optixu/optixu_matrix_namespace.h>
20
21using namespace optix;
22
23#include "RayTracing.cuh"
24
25rtDeclareVariable(Ray, ray, rtCurrentRay, );
26rtDeclareVariable(PerRayData, prd, rtPayload, );
27
28rtDeclareVariable(unsigned int, UUID, attribute UUID, );
29// Note: Nprimitives is declared in RayTracing.cuh (for bbox position calculation)
30
31//----------------- Rectangle Primitive ----------------------//
32
35RT_PROGRAM void rectangle_intersect(int objID ) {
36
37 if (prd.origin_UUID == patch_UUID[objID]) { // the ray should not intersect the primitive from which it was launched
38 return;
39 }
40 // FIX: Convert UUID to position for twosided_flag access
41 uint position = primitive_positions[patch_UUID[objID]];
42 if (twosided_flag[position] >= 2) { // if twosided_flag=2, ignore intersection (transparent)
43 return;
44 }
45
46 float3 v0 = patch_vertices[make_uint2(0, objID)];
47 float3 v1 = patch_vertices[make_uint2(1, objID)];
48 float3 v2 = patch_vertices[make_uint2(2, objID)];
49 float3 v3 = patch_vertices[make_uint2(3, objID)];
50
51 float3 anchor = v0;
52 float3 normal = normalize(cross(v1 - v0, v2 - v0));
53
54 float3 a = v1 - v0;
55 float3 b = v3 - v0;
56
57 float t = dot(anchor - ray.origin, normal) / dot(ray.direction, normal);
58
59 if (t == t && t > 1e-8 && t < 1e8) {
60
61 float3 p = ray.origin + ray.direction * t;
62 float3 d = p - anchor;
63
64 float ddota = dot(d, a);
65
66 if (ddota > 0.0 && ddota < dot(a, a)) {
67
68 float ddotb = dot(d, b);
69
70 if (ddotb > 0.0 && ddotb < dot(b, b)) {
71
72 uint U = patch_UUID[objID];
73
74 // FIX: Convert UUID to position using primitive_positions lookup
75 // objectID is position-indexed, not UUID-indexed
76 uint ID = primitive_positions[U];
77
78 // Skip if UUID maps to invalid position (e.g., deleted UUID)
79 if (ID == UINT_MAX) {
80 return;
81 }
82
83 if (maskID[ID] == -1) { // no texture transparency
84 if (rtPotentialIntersection(t)) {
85 UUID = patch_UUID[objID];
86 rtReportIntersection(0);
87 }
88 } else { // use transparency mask
89
90 float amag = d_magnitude(a);
91 float bmag = d_magnitude(b);
92 float2 uv = make_float2(ddota / amag / amag, ddotb / bmag / bmag);
93 int2 sz = masksize[maskID[ID]];
94 uint3 ind;
95 if (uvID[ID] == -1) { // does not have custom (u,v) coordinates
96 ind = make_uint3(floorf(float(sz.x - 1) * uv.x), floorf(float(sz.y - 1) * (1.f - uv.y)), maskID[ID]);
97 } else {
98
99 float2 uvmin = uvdata[make_uint2(0, uvID[ID])];
100 float2 duv;
101 duv.x = uvdata[make_uint2(1, uvID[ID])].x - uvdata[make_uint2(0, uvID[ID])].x;
102 duv.y = uvdata[make_uint2(2, uvID[ID])].y - uvdata[make_uint2(1, uvID[ID])].y;
103
104 ind = make_uint3(floorf(float(sz.x - 1) * (uvmin.x + uv.x * duv.x)), floorf(float(sz.y - 1) * (1.f - uvmin.y - uv.y * duv.y)), maskID[ID]);
105 if (ind.x >= sz.x || ind.y >= sz.y) {
106 // Texture coord out of bounds - skip
107 }
108 }
109 if (maskdata[ind]) {
110 if (rtPotentialIntersection(t)) {
111 UUID = patch_UUID[objID];
112 rtReportIntersection(0);
113 }
114 }
115 }
116 }
117 }
118 }
119}
120
123RT_PROGRAM void rectangle_bounds(int objID, float result[6]) {
124 optix::Aabb *aabb = (optix::Aabb *) result;
125 float3 v0 = patch_vertices[make_uint2(0, objID)];
126 float3 v1 = patch_vertices[make_uint2(1, objID)];
127 float3 v2 = patch_vertices[make_uint2(2, objID)];
128 float3 v3 = patch_vertices[make_uint2(3, objID)];
129 float3 min = make_float3(fmin(fmin(v0.x, v1.x), fmin(v2.x, v3.x)), fmin(fmin(v0.y, v1.y), fmin(v2.y, v3.y)), fmin(fmin(v0.z, v1.z), fmin(v2.z, v3.z)));
130 float3 max = make_float3(fmax(fmax(v0.x, v1.x), fmax(v2.x, v3.x)), fmax(fmax(v0.y, v1.y), fmax(v2.y, v3.y)), fmax(fmax(v0.z, v1.z), fmax(v2.z, v3.z)));
131 aabb->set(min, max);
132}
133
134//----------------- Triangle Primitive ----------------------//
135
138RT_PROGRAM void triangle_intersect(int objID ) {
139
140 if (prd.origin_UUID == triangle_UUID[objID]) { // the ray should not intersect the primitive from which it was launched
141 return;
142 }
143 // FIX: Convert UUID to position for twosided_flag access
144 uint position = primitive_positions[triangle_UUID[objID]];
145 if (twosided_flag[position] >= 2) { // if twosided_flag=2, ignore intersection (transparent)
146 return;
147 }
148
149 float3 v0 = triangle_vertices[make_uint2(0, objID)];
150 float3 v1 = triangle_vertices[make_uint2(1, objID)];
151 float3 v2 = triangle_vertices[make_uint2(2, objID)];
152
153 float a = v0.x - v1.x, b = v0.x - v2.x, c = ray.direction.x, d = v0.x - ray.origin.x;
154 float e = v0.y - v1.y, f = v0.y - v2.y, g = ray.direction.y, h = v0.y - ray.origin.y;
155 float i = v0.z - v1.z, j = v0.z - v2.z, k = ray.direction.z, l = v0.z - ray.origin.z;
156
157 float m = f * k - g * j, n = h * k - g * l, p = f * l - h * j;
158 float q = g * i - e * k, s = e * j - f * i;
159
160 float inv_denom = 1.f / (a * m + b * q + c * s);
161
162 float e1 = d * m - b * n - c * p;
163 float beta = e1 * inv_denom;
164
165 if (beta > 0.0) {
166
167 float r = r = e * l - h * i;
168 float e2 = a * n + d * q + c * r;
169 float gamma = e2 * inv_denom;
170
171 if (gamma > 0.0 && beta + gamma < 1.0) {
172
173 float e3 = a * p - b * r + d * s;
174 float t = e3 * inv_denom;
175
176 if (t > 1e-8) {
177
178 uint U = triangle_UUID[objID];
179
180 // FIX: Convert UUID to position using primitive_positions lookup
181 uint ID = primitive_positions[U];
182
183 // Skip if UUID maps to invalid position (e.g., deleted UUID)
184 if (ID == UINT_MAX) {
185 return;
186 }
187
188 if (maskID[ID] == -1) { // no texture transparency
189 if (rtPotentialIntersection(t)) {
190 UUID = triangle_UUID[objID];
191 rtReportIntersection(0);
192 }
193 } else { // has texture transparency
194
195 int2 sz = masksize[maskID[ID]];
196
197 float2 uv0 = uvdata[make_uint2(0, uvID[ID])];
198 float2 uv1 = uvdata[make_uint2(1, uvID[ID])];
199 float2 uv2 = uvdata[make_uint2(2, uvID[ID])];
200
201 float2 uv = uv0 + beta * (uv1 - uv0) + gamma * (uv2 - uv0);
202 uv.y = 1.f - uv.y;
203
204 uint3 ind = make_uint3(roundf(float(sz.x - 1) * fabs(uv.x)), roundf(float(sz.y - 1) * fabs(uv.y)), maskID[ID]);
205 if (ind.x >= sz.x || ind.y >= sz.y) {
206 // Texture coord out of bounds - skip
207 }
208 if (maskdata[ind]) {
209 if (rtPotentialIntersection(t)) {
210 UUID = triangle_UUID[objID];
211 rtReportIntersection(0);
212 }
213 }
214 }
215 }
216 }
217 }
218}
219
220
222RT_PROGRAM void triangle_bounds(int objID, float result[6]) {
223 optix::Aabb *aabb = (optix::Aabb *) result;
224 float3 v0 = triangle_vertices[make_uint2(0, objID)];
225 float3 v1 = triangle_vertices[make_uint2(1, objID)];
226 float3 v2 = triangle_vertices[make_uint2(2, objID)];
227 float3 mn = make_float3(fmin(fmin(v0.x, v1.x), v2.x), fmin(fmin(v0.y, v1.y), v2.y), fmin(fmin(v0.z, v1.z), v2.z));
228 float3 mx = make_float3(fmax(fmax(v0.x, v1.x), v2.x), fmax(fmax(v0.y, v1.y), v2.y), fmax(fmax(v0.z, v1.z), v2.z));
229 aabb->set(mn, mx);
230}
231
232//----------------- Disk Primitive ----------------------//
233
236RT_PROGRAM void disk_intersect(int objID ) {
237
238 if (prd.origin_UUID == disk_UUID[objID]) { // the ray should not intersect the primitive from which it was launched
239 return;
240 }
241 // FIX: Convert UUID to position for twosided_flag access
242 uint position = primitive_positions[disk_UUID[objID]];
243 if (twosided_flag[position] >= 2) { // if twosided_flag=2, ignore intersection (transparent)
244 return;
245 }
246
247 float3 center = make_float3(0, 0, 0);
248 float3 normal = make_float3(0, 0, 1);
249
250 float t = dot(center - ray.origin, normal) / dot(ray.direction, normal);
251
252 if (t > 1e-6) {
253
254 float3 p = ray.origin + t * ray.direction;
255
256 float3 r = p - center;
257
258 if (r.x * r.x + r.y * r.y + r.z * r.z < 1.f) {
259
260 if (rtPotentialIntersection(t)) {
261 UUID = disk_UUID[objID];
262 rtReportIntersection(0);
263 }
264 }
265 }
266}
267
268
270RT_PROGRAM void disk_bounds(int objID, float result[6]) {
271 optix::Aabb *aabb = (optix::Aabb *) result;
272 float3 mn = make_float3(-1, -1, -0.001f);
273 float3 mx = make_float3(1, 1, 0.001f);
274 aabb->set(mn, mx);
275}
276
277//----------------- Voxel Primitive ----------------------//
278
281RT_PROGRAM void voxel_intersect(int objID ) {
282
283 if (prd.origin_UUID == voxel_UUID[objID]) { // the ray should not intersect the primitive from which it was launched
284 return;
285 }
286 // FIX: Convert UUID to position for twosided_flag access
287 uint position = primitive_positions[voxel_UUID[objID]];
288 if (twosided_flag[position] >= 2) { // if twosided_flag=2, ignore intersection (transparent)
289 return;
290 }
291
292 float x0 = voxel_vertices[make_uint2(0, objID)].x;
293 float y0 = voxel_vertices[make_uint2(0, objID)].y;
294 float z0 = voxel_vertices[make_uint2(0, objID)].z;
295
296 float x1 = voxel_vertices[make_uint2(1, objID)].x;
297 float y1 = voxel_vertices[make_uint2(1, objID)].y;
298 float z1 = voxel_vertices[make_uint2(1, objID)].z;
299
300 float ox = ray.origin.x;
301 float oy = ray.origin.y;
302 float oz = ray.origin.z;
303 float dx = ray.direction.x;
304 float dy = ray.direction.y;
305 float dz = ray.direction.z;
306
307 float tx_min, ty_min, tz_min;
308 float tx_max, ty_max, tz_max;
309
310 float a = 1.0 / dx;
311 if (a >= 0) {
312 tx_min = (x0 - ox) * a;
313 tx_max = (x1 - ox) * a;
314 } else {
315 tx_min = (x1 - ox) * a;
316 tx_max = (x0 - ox) * a;
317 }
318
319 float b = 1.0 / dy;
320 if (b >= 0) {
321 ty_min = (y0 - oy) * b;
322 ty_max = (y1 - oy) * b;
323 } else {
324 ty_min = (y1 - oy) * b;
325 ty_max = (y0 - oy) * b;
326 }
327
328 float c = 1.0 / dz;
329 if (c >= 0) {
330 tz_min = (z0 - oz) * c;
331 tz_max = (z1 - oz) * c;
332 } else {
333 tz_min = (z1 - oz) * c;
334 tz_max = (z0 - oz) * c;
335 }
336
337 float t0, t1;
338
339 // find largest entering t value
340
341 if (tx_min > ty_min)
342 t0 = tx_min;
343 else
344 t0 = ty_min;
345
346 if (tz_min > t0)
347 t0 = tz_min;
348
349 // find smallest exiting t value
350
351 if (tx_max < ty_max)
352 t1 = tx_max;
353 else
354 t1 = ty_max;
355
356 if (tz_max < t1)
357 t1 = tz_max;
358
359 if (t0 < t1 && t0 > 1e-5) { // note: if ray originated inside voxel, no intersection occurs.
360 if (rtPotentialIntersection(t0)) {
361 UUID = voxel_UUID[objID];
362 rtReportIntersection(0);
363 }
364 }
365}
366
369RT_PROGRAM void voxel_bounds(int objID, float result[6]) {
370 optix::Aabb *aabb = (optix::Aabb *) result;
371 float3 min = voxel_vertices[make_uint2(0, objID)];
372 float3 max = voxel_vertices[make_uint2(1, objID)];
373 aabb->set(min, max);
374}
375
376//----------------- Bounding Box Primitive ----------------------//
377
380RT_PROGRAM void bbox_intersect(int objID ) {
381
382 if (prd.origin_UUID == bbox_UUID[objID]) { // the ray should not intersect the primitive from which it was launched
383 return;
384 }
385 // Bbox position is deterministic: Nprimitives + objID
386 // (bboxes are synthetic geometry, not in primitive_positions lookup table)
387 uint position = Nprimitives + objID;
388 if (twosided_flag[position] >= 2) { // if twosided_flag=2, ignore intersection (transparent)
389 return;
390 }
391
392 float3 v0 = bbox_vertices[make_uint2(0, objID)];
393 float3 v1 = bbox_vertices[make_uint2(1, objID)];
394 float3 v2 = bbox_vertices[make_uint2(2, objID)];
395 float3 v3 = bbox_vertices[make_uint2(3, objID)];
396
397 float3 anchor = v0;
398 float3 normal = normalize(cross(v1 - v0, v2 - v0));
399
400 float3 a = v1 - v0;
401 float3 b = v3 - v0;
402
403 float t = dot(anchor - ray.origin, normal) / dot(ray.direction, normal);
404
405 if (t == t && t > 1e-8 && t < 1e8) {
406
407 float3 p = ray.origin + ray.direction * t;
408 float3 d = p - anchor;
409
410 float ddota = dot(d, a);
411
412 if (ddota > 0.0 && ddota < dot(a, a)) {
413
414 float ddotb = dot(d, b);
415
416 if (ddotb > 0.0 && ddotb < dot(b, b)) {
417
418 if (rtPotentialIntersection(t)) {
419 UUID = bbox_UUID[objID];
420 rtReportIntersection(0);
421 }
422 }
423 }
424 }
425}
426
429RT_PROGRAM void bbox_bounds(int objID, float result[6]) {
430 optix::Aabb *aabb = (optix::Aabb *) result;
431 float3 v0 = bbox_vertices[make_uint2(0, objID)];
432 float3 v1 = bbox_vertices[make_uint2(1, objID)];
433 float3 v2 = bbox_vertices[make_uint2(2, objID)];
434 float3 v3 = bbox_vertices[make_uint2(3, objID)];
435 float3 min = make_float3(fmin(fmin(v0.x, v1.x), fmin(v2.x, v3.x)), fmin(fmin(v0.y, v1.y), fmin(v2.y, v3.y)), fmin(fmin(v0.z, v1.z), fmin(v2.z, v3.z)));
436 float3 max = make_float3(fmax(fmax(v0.x, v1.x), fmax(v2.x, v3.x)), fmax(fmax(v0.y, v1.y), fmax(v2.y, v3.y)), fmax(fmax(v0.z, v1.z), fmax(v2.z, v3.z)));
437 aabb->set(min, max);
438}
439
440//----------------- Tile Object ----------------------//
441
444RT_PROGRAM void tile_intersect(int objID ) {
445
446 if (prd.origin_UUID == tile_UUID[objID]) { // the ray should not intersect the primitive from which it was launched
447 return;
448 }
449 // FIX: Convert UUID to position for twosided_flag access
450 uint position = primitive_positions[tile_UUID[objID]];
451 if (twosided_flag[position] >= 2) { // if twosided_flag=2, ignore intersection (transparent)
452 return;
453 }
454
455 float3 v0 = tile_vertices[make_uint2(0, objID)];
456 float3 v1 = tile_vertices[make_uint2(1, objID)];
457 float3 v2 = tile_vertices[make_uint2(2, objID)];
458 float3 v3 = tile_vertices[make_uint2(3, objID)];
459
460 float3 anchor = v0;
461 float3 normal = normalize(cross(v1 - v0, v2 - v0));
462
463 float3 a = v1 - v0;
464 float3 b = v3 - v0;
465
466 float t = dot(anchor - ray.origin, normal) / dot(ray.direction, normal);
467
468 if (t == t && t > 1e-8 && t < 1e8) {
469
470 float3 p = ray.origin + ray.direction * t;
471 float3 d = p - anchor;
472
473 float ddota = dot(d, a);
474
475 if (ddota > 0.0 && ddota < dot(a, a)) {
476
477 float ddotb = dot(d, b);
478
479 if (ddotb > 0.0 && ddotb < dot(b, b)) {
480
481 float amag = d_magnitude(a);
482 float bmag = d_magnitude(b);
483 float2 uv = make_float2(ddota / amag / amag, ddotb / bmag / bmag);
484
485 // Get tile base UUID - objID should always be 0 since each tile has one geometry entry
486 uint U = tile_UUID[objID];
487
488 // FIX: Convert UUID to position using primitive_positions lookup
489 uint ID = primitive_positions[U];
490
491 // Skip if UUID maps to invalid position (e.g., deleted UUID)
492 if (ID == UINT_MAX) {
493 return;
494 }
495
496 if (maskID[ID] == -1) { // no texture transparency
497 if (rtPotentialIntersection(t)) {
498 // Calculate subpatch indices and clamp to valid range [0, subdivisions-1]
499 int subpatch_x = min((int) floorf(uv.x * object_subdivisions[ID].x), object_subdivisions[ID].x - 1);
500 int subpatch_y = min((int) floorf(uv.y * object_subdivisions[ID].y), object_subdivisions[ID].y - 1);
501 UUID = U + subpatch_y * object_subdivisions[ID].x + subpatch_x;
502 rtReportIntersection(0);
503 }
504 } else { // use transparency mask
505
506
507 int2 sz = masksize[maskID[ID]];
508 uint3 ind = make_uint3(floorf(float(sz.x - 1) * uv.x), floorf(float(sz.y - 1) * (1.f - uv.y)), maskID[ID]);
509
510 if (maskdata[ind]) {
511 if (rtPotentialIntersection(t)) {
512 // Calculate subpatch indices and clamp to valid range [0, subdivisions-1]
513 int subpatch_x = min((int) floorf(uv.x * object_subdivisions[ID].x), object_subdivisions[ID].x - 1);
514 int subpatch_y = min((int) floorf(uv.y * object_subdivisions[ID].y), object_subdivisions[ID].y - 1);
515 UUID = U + subpatch_y * object_subdivisions[ID].x + subpatch_x;
516 rtReportIntersection(0);
517 }
518 }
519 }
520 }
521 }
522 }
523}
524
527RT_PROGRAM void tile_bounds(int objID, float result[6]) {
528 optix::Aabb *aabb = (optix::Aabb *) result;
529 float3 v0 = tile_vertices[make_uint2(0, objID)];
530 float3 v1 = tile_vertices[make_uint2(1, objID)];
531 float3 v2 = tile_vertices[make_uint2(2, objID)];
532 float3 v3 = tile_vertices[make_uint2(3, objID)];
533 float3 min = make_float3(fmin(fmin(v0.x, v1.x), fmin(v2.x, v3.x)), fmin(fmin(v0.y, v1.y), fmin(v2.y, v3.y)), fmin(fmin(v0.z, v1.z), fmin(v2.z, v3.z)));
534 float3 max = make_float3(fmax(fmax(v0.x, v1.x), fmax(v2.x, v3.x)), fmax(fmax(v0.y, v1.y), fmax(v2.y, v3.y)), fmax(fmax(v0.z, v1.z), fmax(v2.z, v3.z)));
535 aabb->set(min, max);
536}