static int vol_get_bounds(ShadeInput *shi, const float co[3], const float vec[3], float hitco[3], Isect *isect, int intersect_type) { copy_v3_v3(isect->start, co); copy_v3_v3(isect->dir, vec); isect->dist = FLT_MAX; isect->mode = RE_RAY_MIRROR; isect->last_hit = NULL; isect->lay = -1; isect->check = RE_CHECK_VLR_NONE; if (intersect_type == VOL_BOUNDS_DEPTH) { isect->skip = RE_SKIP_VLR_NEIGHBOUR; isect->orig.face = (void *)shi->vlr; isect->orig.ob = (void *)shi->obi; } else { // if (intersect_type == VOL_BOUNDS_SS) { isect->skip = 0; isect->orig.face = NULL; isect->orig.ob = NULL; } if (RE_rayobject_raycast(R.raytree, isect)) { hitco[0] = isect->start[0] + isect->dist * isect->dir[0]; hitco[1] = isect->start[1] + isect->dist * isect->dir[1]; hitco[2] = isect->start[2] + isect->dist * isect->dir[2]; return 1; } else { return 0; } }
static void vol_trace_behind(ShadeInput *shi, VlakRen *vlr, const float co[3], float col_r[4]) { Isect isect; copy_v3_v3(isect.start, co); copy_v3_v3(isect.dir, shi->view); isect.dist = FLT_MAX; isect.mode = RE_RAY_MIRROR; isect.check = RE_CHECK_VLR_NONE; isect.skip = RE_SKIP_VLR_NEIGHBOUR; isect.orig.ob = (void *) shi->obi; isect.orig.face = (void *)vlr; isect.last_hit = NULL; isect.lay = -1; /* check to see if there's anything behind the volume, otherwise shade the sky */ if (RE_rayobject_raycast(R.raytree, &isect)) { shade_intersection(shi, col_r, &isect); } else { shadeSkyView(col_r, co, shi->view, NULL, shi->thread); shadeSunView(col_r, shi->view); } }
static int bake_intersect_tree(RayObject *raytree, Isect *isect, float *start, float *dir, float sign, float *hitco, float *dist) { float maxdist; int hit; /* might be useful to make a user setting for maxsize*/ if (R.r.bake_maxdist > 0.0f) maxdist = R.r.bake_maxdist; else maxdist = RE_RAYTRACE_MAXDIST + R.r.bake_biasdist; /* 'dir' is always normalized */ madd_v3_v3v3fl(isect->start, start, dir, -R.r.bake_biasdist); mul_v3_v3fl(isect->dir, dir, sign); isect->dist = maxdist; hit = RE_rayobject_raycast(raytree, isect); if (hit) { madd_v3_v3v3fl(hitco, isect->start, isect->dir, isect->dist); *dist = isect->dist; } return hit; }
/* return FALSE if nothing was hit and TRUE otherwise */ static int trace_ao_ray(MAOBakeData *ao_data, float ray_start[3], float ray_direction[3]) { Isect isect = {{0}}; isect.dist = RE_RAYTRACE_MAXDIST; copy_v3_v3(isect.start, ray_start); copy_v3_v3(isect.dir, ray_direction); isect.lay = -1; normalize_v3(isect.dir); return RE_rayobject_raycast(ao_data->raytree, &isect); }
/* tracing */ static float vol_get_shadow(ShadeInput *shi, LampRen *lar, const float co[3]) { float visibility = 1.f; if (lar->shb) { float dxco[3] = {0.f, 0.f, 0.f}, dyco[3] = {0.f, 0.f, 0.f}; visibility = testshadowbuf(&R, lar->shb, co, dxco, dyco, 1.0, 0.0); } else if (lar->mode & LA_SHAD_RAY) { /* trace shadow manually, no good lamp api atm */ Isect is; copy_v3_v3(is.start, co); if (lar->type == LA_SUN || lar->type == LA_HEMI) { is.dir[0] = -lar->vec[0]; is.dir[1] = -lar->vec[1]; is.dir[2] = -lar->vec[2]; is.dist = R.maxdist; } else { sub_v3_v3v3(is.dir, lar->co, is.start); is.dist = normalize_v3(is.dir); } is.mode = RE_RAY_MIRROR; is.check = RE_CHECK_VLR_NON_SOLID_MATERIAL; is.skip = 0; if (lar->mode & (LA_LAYER | LA_LAYER_SHADOW)) is.lay = lar->lay; else is.lay = -1; is.orig.ob = NULL; is.orig.face = NULL; is.last_hit = lar->last_hit[shi->thread]; RE_instance_rotate_ray(shi->obi, &is); if (RE_rayobject_raycast(R.raytree, &is)) { RE_instance_rotate_ray_restore(shi->obi, &is); visibility = 0.f; } lar->last_hit[shi->thread] = is.last_hit; } return visibility; }
/* tracing */ static float vol_get_shadow(ShadeInput *shi, LampRen *lar, float *co) { float visibility = 1.f; if(lar->shb) { float dxco[3]={0.f, 0.f, 0.f}, dyco[3]={0.f, 0.f, 0.f}; visibility = testshadowbuf(&R, lar->shb, co, dxco, dyco, 1.0, 0.0); } else if (lar->mode & LA_SHAD_RAY) { /* trace shadow manually, no good lamp api atm */ Isect is; VecCopyf(is.start, co); if(lar->type==LA_SUN || lar->type==LA_HEMI) { is.vec[0] = -lar->vec[0]; is.vec[1] = -lar->vec[1]; is.vec[2] = -lar->vec[2]; is.labda = R.maxdist; } else { VECSUB( is.vec, lar->co, is.start ); is.labda = VecLength( is.vec ); } is.mode = RE_RAY_MIRROR; is.skip = RE_SKIP_VLR_RENDER_CHECK | RE_SKIP_VLR_NON_SOLID_MATERIAL; if(lar->mode & (LA_LAYER|LA_LAYER_SHADOW)) is.lay= lar->lay; else is.lay= -1; is.orig.ob = NULL; is.orig.face = NULL; is.last_hit = lar->last_hit[shi->thread]; if(RE_rayobject_raycast(R.raytree,&is)) { visibility = 0.f; } lar->last_hit[shi->thread]= is.last_hit; } return visibility; }
/* Recursive test for intersections, from a point inside the mesh, to outside * Number of intersections (depth) determine if a point is inside or outside the mesh */ int intersect_outside_volume(RayObject *tree, Isect *isect, float *offset, int limit, int depth) { if (limit == 0) return depth; if (RE_rayobject_raycast(tree, isect)) { isect->start[0] = isect->start[0] + isect->labda*isect->vec[0]; isect->start[1] = isect->start[1] + isect->labda*isect->vec[1]; isect->start[2] = isect->start[2] + isect->labda*isect->vec[2]; isect->labda = FLT_MAX; isect->skip = RE_SKIP_VLR_NEIGHBOUR; isect->orig.face= isect->hit.face; isect->orig.ob= isect->hit.ob; return intersect_outside_volume(tree, isect, offset, limit-1, depth+1); } else { return depth; } }
static void vol_trace_behind(ShadeInput *shi, VlakRen *vlr, float *co, float *col) { Isect isect; VECCOPY(isect.start, co); VECCOPY(isect.vec, shi->view); isect.labda = FLT_MAX; isect.mode= RE_RAY_MIRROR; isect.skip = RE_SKIP_VLR_NEIGHBOUR | RE_SKIP_VLR_RENDER_CHECK; isect.orig.ob = (void*) shi->obi; isect.orig.face = (void*)vlr; isect.last_hit = NULL; isect.lay= -1; /* check to see if there's anything behind the volume, otherwise shade the sky */ if(RE_rayobject_raycast(R.raytree, &isect)) { shade_intersection(shi, col, &isect); } else { shadeSkyView(col, co, shi->view, NULL, shi->thread); shadeSunView(col, shi->view); } }
static int vol_get_bounds(ShadeInput *shi, float *co, float *vec, float *hitco, Isect *isect, int intersect_type) { /* XXX TODO - get raytrace max distance from object instance's bounding box */ /* need to account for scaling only, but keep coords in camera space... * below code is WIP and doesn't work! VecSubf(bb_dim, shi->obi->obr->boundbox[1], shi->obi->obr->boundbox[2]); Mat3MulVecfl(shi->obi->nmat, bb_dim); maxsize = VecLength(bb_dim); */ VECCOPY(isect->start, co); VECCOPY(isect->vec, vec ); isect->labda = FLT_MAX; isect->mode= RE_RAY_MIRROR; isect->last_hit = NULL; isect->lay= -1; if (intersect_type == VOL_BOUNDS_DEPTH) { isect->skip = RE_SKIP_VLR_NEIGHBOUR; isect->orig.face = (void*)shi->vlr; isect->orig.ob = (void*)shi->obi; } else { // if (intersect_type == VOL_BOUNDS_SS) { isect->skip= 0; isect->orig.face= NULL; isect->orig.ob = NULL; } if(RE_rayobject_raycast(R.raytree, isect)) { hitco[0] = isect->start[0] + isect->labda*isect->vec[0]; hitco[1] = isect->start[1] + isect->labda*isect->vec[1]; hitco[2] = isect->start[2] + isect->labda*isect->vec[2]; return 1; } else { return 0; } }