int RE_rayobject_raycast(RayObject *r, Isect *isec) { int i; RE_RC_COUNT(isec->raycounter->raycast.test); /* setup vars used on raycast */ for(i=0; i<3; i++) { isec->idot_axis[i] = 1.0f / isec->dir[i]; isec->bv_index[2*i] = isec->idot_axis[i] < 0.0 ? 1 : 0; isec->bv_index[2*i+1] = 1 - isec->bv_index[2*i]; isec->bv_index[2*i] = i+3*isec->bv_index[2*i]; isec->bv_index[2*i+1] = i+3*isec->bv_index[2*i+1]; } #ifdef RT_USE_LAST_HIT /* last hit heuristic */ if(isec->mode==RE_RAY_SHADOW && isec->last_hit) { RE_RC_COUNT(isec->raycounter->rayshadow_last_hit.test); if(RE_rayobject_intersect(isec->last_hit, isec)) { RE_RC_COUNT(isec->raycounter->raycast.hit); RE_RC_COUNT(isec->raycounter->rayshadow_last_hit.hit); return 1; } } #endif #ifdef RT_USE_HINT isec->hit_hint = 0; #endif if(RE_rayobject_intersect(r, isec)) { RE_RC_COUNT(isec->raycounter->raycast.hit); #ifdef RT_USE_HINT isec->hint = isec->hit_hint; #endif return 1; } return 0; }
int intersect(SVBVHTree *obj, Isect* isec) { //TODO renable hint support if(RE_rayobject_isAligned(obj->root)) return bvh_node_stack_raycast<SVBVHNode,StackSize,false>( obj->root, isec); else return RE_rayobject_intersect( (RayObject*) obj->root, isec ); }
static int intersect(QBVHTree *obj, Isect *isec) { //TODO renable hint support if (RE_rayobject_isAligned(obj->root)) { if (isec->mode == RE_RAY_SHADOW) return svbvh_node_stack_raycast<StackSize, true>(obj->root, isec); else return svbvh_node_stack_raycast<StackSize, false>(obj->root, isec); } else return RE_rayobject_intersect((RayObject *)obj->root, isec); }
static void bvh_callback(void *userdata, int index, const BVHTreeRay *UNUSED(ray), BVHTreeRayHit *hit) { struct BVHCallbackUserData *data = (struct BVHCallbackUserData*)userdata; Isect *isec = data->isec; RayObject *face = data->leafs[index]; if (RE_rayobject_intersect(face, isec)) { hit->index = index; if (isec->mode == RE_RAY_SHADOW) hit->dist = 0; else hit->dist = isec->dist; } }
static int RE_rayobject_instance_intersect(RayObject *o, Isect *isec) { InstanceRayObject *obj = (InstanceRayObject *)o; float start[3], dir[3], idot_axis[3], dist; int changed = 0, i, res; // TODO - this is disabling self intersection on instances if (isec->orig.ob == obj->ob && obj->ob) { changed = 1; isec->orig.ob = obj->target_ob; } // backup old values copy_v3_v3(start, isec->start); copy_v3_v3(dir, isec->dir); copy_v3_v3(idot_axis, isec->idot_axis); dist = isec->dist; // transform to target coordinates system mul_m4_v3(obj->global2target, isec->start); mul_mat3_m4_v3(obj->global2target, isec->dir); isec->dist *= normalize_v3(isec->dir); // update idot_axis and bv_index for (i = 0; i < 3; i++) { isec->idot_axis[i] = 1.0f / isec->dir[i]; isec->bv_index[2 * i] = isec->idot_axis[i] < 0.0f ? 1 : 0; isec->bv_index[2 * i + 1] = 1 - isec->bv_index[2 * i]; isec->bv_index[2 * i] = i + 3 * isec->bv_index[2 * i]; isec->bv_index[2 * i + 1] = i + 3 * isec->bv_index[2 * i + 1]; } // raycast res = RE_rayobject_intersect(obj->target, isec); // map dist into original coordinate space if (res == 0) { isec->dist = dist; } else { // note we don't just multiply dist, because of possible // non-uniform scaling in the transform matrix float vec[3]; mul_v3_v3fl(vec, isec->dir, isec->dist); mul_mat3_m4_v3(obj->target2global, vec); isec->dist = len_v3(vec); isec->hit.ob = obj->ob; #ifdef RT_USE_LAST_HIT // TODO support for last hit optimization in instances that can jump // directly to the last hit face. // For now it jumps directly to the last-hit instance root node. isec->last_hit = RE_rayobject_unalignRayAPI((RayObject *) obj); #endif } // restore values copy_v3_v3(isec->start, start); copy_v3_v3(isec->dir, dir); copy_v3_v3(isec->idot_axis, idot_axis); if (changed) isec->orig.ob = obj->ob; // restore bv_index for (i = 0; i < 3; i++) { isec->bv_index[2 * i] = isec->idot_axis[i] < 0.0f ? 1 : 0; isec->bv_index[2 * i + 1] = 1 - isec->bv_index[2 * i]; isec->bv_index[2 * i] = i + 3 * isec->bv_index[2 * i]; isec->bv_index[2 * i + 1] = i + 3 * isec->bv_index[2 * i + 1]; } return res; }