Changeset View
Changeset View
Standalone View
Standalone View
intern/cycles/kernel/geom/geom_bvh_volume.h
| Context not available. | |||||
| * | * | ||||
| */ | */ | ||||
| ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, | ccl_device uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, | ||||
| const Ray *ray, | const Ray *ray, | ||||
| Intersection *isect) | Intersection *isect_array, | ||||
| const uint max_hits) | |||||
| { | { | ||||
| /* todo: | /* todo: | ||||
| * - test if pushing distance on the stack helps (for non shadow rays) | * - test if pushing distance on the stack helps (for non shadow rays) | ||||
| Context not available. | |||||
| int nodeAddr = kernel_data.bvh.root; | int nodeAddr = kernel_data.bvh.root; | ||||
| /* ray parameters in registers */ | /* ray parameters in registers */ | ||||
| const float tmax = ray->t; | |||||
| float3 P = ray->P; | float3 P = ray->P; | ||||
| float3 dir = bvh_clamp_direction(ray->D); | float3 dir = bvh_clamp_direction(ray->D); | ||||
| float3 idir = bvh_inverse_direction(dir); | float3 idir = bvh_inverse_direction(dir); | ||||
| int object = OBJECT_NONE; | int object = OBJECT_NONE; | ||||
| float isect_t = tmax; | |||||
| const uint visibility = PATH_RAY_ALL_VISIBILITY; | const uint visibility = PATH_RAY_ALL_VISIBILITY; | ||||
| Context not available. | |||||
| Transform ob_tfm; | Transform ob_tfm; | ||||
| #endif | #endif | ||||
| isect->t = ray->t; | #if BVH_FEATURE(BVH_INSTANCING) | ||||
| isect->u = 0.0f; | int num_hits_in_instance = 0; | ||||
| isect->v = 0.0f; | #endif | ||||
| isect->prim = PRIM_NONE; | |||||
| isect->object = OBJECT_NONE; | uint num_hits = 0; | ||||
| isect_array->t = tmax; | |||||
| #if defined(__KERNEL_SSE2__) | #if defined(__KERNEL_SSE2__) | ||||
| const shuffle_swap_t shuf_identity = shuffle_swap_identity(); | const shuffle_swap_t shuf_identity = shuffle_swap_identity(); | ||||
| Context not available. | |||||
| Psplat[1] = ssef(P.y); | Psplat[1] = ssef(P.y); | ||||
| Psplat[2] = ssef(P.z); | Psplat[2] = ssef(P.z); | ||||
| ssef tsplat(0.0f, 0.0f, -isect->t, -isect->t); | ssef tsplat(0.0f, 0.0f, -isect_t, -isect_t); | ||||
| gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz); | gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz); | ||||
| #endif | #endif | ||||
| Context not available. | |||||
| #if !defined(__KERNEL_SSE2__) | #if !defined(__KERNEL_SSE2__) | ||||
| /* Intersect two child bounding boxes, non-SSE version */ | /* Intersect two child bounding boxes, non-SSE version */ | ||||
| float t = isect->t; | float t = isect_array->t; | ||||
| /* fetch node data */ | /* fetch node data */ | ||||
| float4 node0 = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+0); | float4 node0 = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+0); | ||||
| Context not available. | |||||
| #endif | #endif | ||||
| const int primAddr2 = __float_as_int(leaf.y); | const int primAddr2 = __float_as_int(leaf.y); | ||||
| const uint type = __float_as_int(leaf.w); | const uint type = __float_as_int(leaf.w); | ||||
| bool hit; | |||||
| /* pop */ | /* pop */ | ||||
| nodeAddr = traversalStack[stackPtr]; | nodeAddr = traversalStack[stackPtr]; | ||||
| Context not available. | |||||
| if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) { | if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| triangle_intersect(kg, &isect_precalc, isect, P, visibility, object, primAddr); | hit = triangle_intersect(kg, &isect_precalc, isect_array, P, visibility, object, primAddr); | ||||
| if(hit) { | |||||
| /* Move on to next entry in intersections array. */ | |||||
| isect_array++; | |||||
| num_hits++; | |||||
| #if BVH_FEATURE(BVH_INSTANCING) | |||||
| num_hits_in_instance++; | |||||
| #endif | |||||
| isect_array->t = isect_t; | |||||
| if(num_hits == max_hits) { | |||||
| #if BVH_FEATURE(BVH_INSTANCING) | |||||
| #if BVH_FEATURE(BVH_MOTION) | |||||
| float t_fac = len(transform_direction(&ob_tfm, 1.0f/idir)); | |||||
| #else | |||||
| Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM); | |||||
| float t_fac = len(transform_direction(&tfm, 1.0f/idir)); | |||||
| #endif | |||||
| for(int i = 0; i < num_hits_in_instance; i++) { | |||||
| (isect_array-i-1)->t *= t_fac; | |||||
| } | |||||
| #endif /* BVH_FEATURE(BVH_INSTANCING) */ | |||||
| return num_hits; | |||||
| } | |||||
| } | |||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| Context not available. | |||||
| if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) { | if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr); | hit = motion_triangle_intersect(kg, isect_array, P, dir, ray->time, visibility, object, primAddr); | ||||
| if(hit) { | |||||
| /* Move on to next entry in intersections array. */ | |||||
| isect_array++; | |||||
| num_hits++; | |||||
| #if BVH_FEATURE(BVH_INSTANCING) | |||||
| num_hits_in_instance++; | |||||
| #endif | |||||
| isect_array->t = isect_t; | |||||
| if(num_hits == max_hits) { | |||||
| #if BVH_FEATURE(BVH_INSTANCING) | |||||
| # if BVH_FEATURE(BVH_MOTION) | |||||
| float t_fac = len(transform_direction(&ob_tfm, 1.0f/idir)); | |||||
| # else | |||||
| Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM); | |||||
| float t_fac = len(transform_direction(&tfm, 1.0f/idir)); | |||||
| #endif | |||||
| for(int i = 0; i < num_hits_in_instance; i++) { | |||||
| (isect_array-i-1)->t *= t_fac; | |||||
| } | |||||
| #endif /* BVH_FEATURE(BVH_INSTANCING) */ | |||||
| return num_hits; | |||||
| } | |||||
| } | |||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| Context not available. | |||||
| continue; | continue; | ||||
| } | } | ||||
| if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) | if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) | ||||
| bvh_cardinal_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0); | hit = bvh_cardinal_curve_intersect(kg, isect_array, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0); | ||||
| else | else | ||||
| bvh_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0); | hit = bvh_curve_intersect(kg, isect_array, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0); | ||||
| if(hit) { | |||||
| /* Move on to next entry in intersections array. */ | |||||
| isect_array++; | |||||
| num_hits++; | |||||
| #if BVH_FEATURE(BVH_INSTANCING) | |||||
| num_hits_in_instance++; | |||||
| #endif | |||||
| isect_array->t = isect_t; | |||||
| if(num_hits == max_hits) { | |||||
| #if BVH_FEATURE(BVH_INSTANCING) | |||||
| # if BVH_FEATURE(BVH_MOTION) | |||||
| float t_fac = len(transform_direction(&ob_tfm, 1.0f/idir)); | |||||
| # else | |||||
| Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM); | |||||
| float t_fac = len(transform_direction(&tfm, 1.0f/idir)); | |||||
| #endif | |||||
| for(int i = 0; i < num_hits_in_instance; i++) { | |||||
| (isect_array-i-1)->t *= t_fac; | |||||
| } | |||||
| #endif /* BVH_FEATURE(BVH_INSTANCING) */ | |||||
| return num_hits; | |||||
| } | |||||
| } | |||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| Context not available. | |||||
| if(object_flag & SD_OBJECT_HAS_VOLUME) { | if(object_flag & SD_OBJECT_HAS_VOLUME) { | ||||
| #if BVH_FEATURE(BVH_MOTION) | #if BVH_FEATURE(BVH_MOTION) | ||||
| bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect->t, &ob_tfm); | bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect_t, &ob_tfm); | ||||
| #else | #else | ||||
| bvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect->t); | bvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect_t); | ||||
| #endif | #endif | ||||
| triangle_intersect_precalc(dir, &isect_precalc); | triangle_intersect_precalc(dir, &isect_precalc); | ||||
| num_hits_in_instance = 0; | |||||
| isect_array->t = isect_t; | |||||
| #if defined(__KERNEL_SSE2__) | #if defined(__KERNEL_SSE2__) | ||||
| Psplat[0] = ssef(P.x); | Psplat[0] = ssef(P.x); | ||||
| Psplat[1] = ssef(P.y); | Psplat[1] = ssef(P.y); | ||||
| Psplat[2] = ssef(P.z); | Psplat[2] = ssef(P.z); | ||||
| tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t); | tsplat = ssef(0.0f, 0.0f, -isect_t, -isect_t); | ||||
| gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz); | gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz); | ||||
| #endif | #endif | ||||
| Context not available. | |||||
| if(stackPtr >= 0) { | if(stackPtr >= 0) { | ||||
| kernel_assert(object != OBJECT_NONE); | kernel_assert(object != OBJECT_NONE); | ||||
| /* instance pop */ | if(num_hits_in_instance) { | ||||
| float t_fac; | |||||
| #if BVH_FEATURE(BVH_MOTION) | #if BVH_FEATURE(BVH_MOTION) | ||||
| bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, &isect->t, &ob_tfm); | bvh_instance_motion_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac, &ob_tfm); | ||||
| #else | #else | ||||
| bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &isect->t); | bvh_instance_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac); | ||||
| #endif | #endif | ||||
| triangle_intersect_precalc(dir, &isect_precalc); | |||||
| /* Scale isect->t to adjust for instancing. */ | |||||
| for(int i = 0; i < num_hits_in_instance; i++) { | |||||
| (isect_array-i-1)->t *= t_fac; | |||||
| } | |||||
| } | |||||
| else { | |||||
| float ignore_t = FLT_MAX; | |||||
| #if BVH_FEATURE(BVH_MOTION) | |||||
| bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, &ignore_t, &ob_tfm); | |||||
| #else | |||||
| bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &ignore_t); | |||||
| #endif | |||||
| triangle_intersect_precalc(dir, &isect_precalc); | |||||
| } | |||||
| triangle_intersect_precalc(dir, &isect_precalc); | isect_t = tmax; | ||||
| isect_array->t = isect_t; | |||||
| #if defined(__KERNEL_SSE2__) | #if defined(__KERNEL_SSE2__) | ||||
| Psplat[0] = ssef(P.x); | Psplat[0] = ssef(P.x); | ||||
| Psplat[1] = ssef(P.y); | Psplat[1] = ssef(P.y); | ||||
| Psplat[2] = ssef(P.z); | Psplat[2] = ssef(P.z); | ||||
| tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t); | tsplat = ssef(0.0f, 0.0f, -isect_t, -isect_t); | ||||
| gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz); | gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz); | ||||
| #endif | #endif | ||||
| Context not available. | |||||
| #endif /* FEATURE(BVH_MOTION) */ | #endif /* FEATURE(BVH_MOTION) */ | ||||
| } while(nodeAddr != ENTRYPOINT_SENTINEL); | } while(nodeAddr != ENTRYPOINT_SENTINEL); | ||||
| return (isect->prim != PRIM_NONE); | return num_hits; | ||||
| } | } | ||||
| ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg, | ccl_device_inline uint BVH_FUNCTION_NAME(KernelGlobals *kg, | ||||
| const Ray *ray, | const Ray *ray, | ||||
| Intersection *isect) | Intersection *isect_array, | ||||
| const uint max_hits) | |||||
| { | { | ||||
| #ifdef __QBVH__ | #ifdef __QBVH__ | ||||
| if(kernel_data.bvh.use_qbvh) { | if(kernel_data.bvh.use_qbvh) { | ||||
| return BVH_FUNCTION_FULL_NAME(QBVH)(kg, | return BVH_FUNCTION_FULL_NAME(QBVH)(kg, | ||||
| ray, | ray, | ||||
| isect); | isect_array, | ||||
| max_hits); | |||||
| } | } | ||||
| else | else | ||||
| #endif | #endif | ||||
| Context not available. | |||||
| kernel_assert(kernel_data.bvh.use_qbvh == false); | kernel_assert(kernel_data.bvh.use_qbvh == false); | ||||
| return BVH_FUNCTION_FULL_NAME(BVH)(kg, | return BVH_FUNCTION_FULL_NAME(BVH)(kg, | ||||
| ray, | ray, | ||||
| isect); | isect_array, | ||||
| max_hits); | |||||
| } | } | ||||
| } | } | ||||
| Context not available. | |||||