RayObject *RE_rayobject_blibvh_create(int size) { BVHObject *obj= (BVHObject*)MEM_callocN(sizeof(BVHObject), "BVHObject"); assert(RE_rayobject_isAligned(obj)); /* RayObject API assumes real data to be 4-byte aligned */ obj->rayobj.api = &bvh_api; obj->bvh = BLI_bvhtree_new(size, 0.0, 4, 6); obj->next_leaf = obj->leafs = (RayObject**)MEM_callocN(size*sizeof(RayObject*), "BVHObject leafs"); INIT_MINMAX(obj->bb[0], obj->bb[1]); return RE_rayobject_unalignRayAPI((RayObject*) obj); }
RayObject *RE_rayobject_instance_create(RayObject *target, float transform[4][4], void *ob, void *target_ob) { InstanceRayObject *obj = (InstanceRayObject *)MEM_callocN(sizeof(InstanceRayObject), "InstanceRayObject"); assert(RE_rayobject_isAligned(obj) ); /* RayObject API assumes real data to be 4-byte aligned */ obj->rayobj.api = &instance_api; obj->target = target; obj->ob = ob; obj->target_ob = target_ob; copy_m4_m4(obj->target2global, transform); invert_m4_m4(obj->global2target, obj->target2global); return RE_rayobject_unalignRayAPI((RayObject *) obj); }
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; }
RayObject *RE_rayobject_empty_create() { return RE_rayobject_unalignRayAPI( &empty_raytree ); }