void rtbuild_add(RTBuilder *b, RayObject *o) { float bb[6]; assert(b->primitives.begin + b->primitives.maxsize != b->primitives.end); INIT_MINMAX(bb, bb + 3); RE_rayobject_merge_bb(o, bb, bb + 3); /* skip objects with invalid bounding boxes, nan causes DO_MINMAX * to do nothing, so we get these invalid values. this shouldn't * happen usually, but bugs earlier in the pipeline can cause it. */ if (bb[0] > bb[3] || bb[1] > bb[4] || bb[2] > bb[5]) return; /* skip objects with inf bounding boxes */ if (!finite(bb[0]) || !finite(bb[1]) || !finite(bb[2])) return; if (!finite(bb[3]) || !finite(bb[4]) || !finite(bb[5])) return; /* skip objects with zero bounding box, they are of no use, and * will give problems in rtbuild_heuristic_object_split later */ if (bb[0] == bb[3] && bb[1] == bb[4] && bb[2] == bb[5]) return; copy_v3_v3(b->primitives.end->bb, bb); copy_v3_v3(b->primitives.end->bb + 3, bb + 3); b->primitives.end->obj = o; b->primitives.end->cost = RE_rayobject_cost(o); for (int i = 0; i < 3; i++) { *(b->sorted_end[i]) = b->primitives.end; b->sorted_end[i]++; } b->primitives.end++; }
static void rtbuild_calc_bb(RTBuilder *b) { if (b->bb[0] == 1.0e30f) { for (RTBuilder::Object **index = b->sorted_begin[0]; index != b->sorted_end[0]; index++) RE_rayobject_merge_bb( (*index)->obj, b->bb, b->bb + 3); } }
static void RE_rayobject_blibvh_add(RayObject *o, RayObject *ob) { BVHObject *obj = (BVHObject*)o; float min_max[6]; INIT_MINMAX(min_max, min_max+3); RE_rayobject_merge_bb(ob, min_max, min_max+3); DO_MIN(min_max, obj->bb[0]); DO_MAX(min_max + 3, obj->bb[1]); BLI_bvhtree_insert(obj->bvh, obj->next_leaf - obj->leafs, min_max, 2); *(obj->next_leaf++) = ob; }
static void RE_rayobject_instance_bb(RayObject *o, float *min, float *max) { //TODO: // *better bb.. calculated without rotations of bb // *maybe cache that better-fitted-BB at the InstanceRayObject InstanceRayObject *obj = (InstanceRayObject *)o; float m[3], M[3], t[3]; int i, j; INIT_MINMAX(m, M); RE_rayobject_merge_bb(obj->target, m, M); //There must be a faster way than rotating all the 8 vertexs of the BB for (i = 0; i < 8; i++) { for (j = 0; j < 3; j++) t[j] = (i & (1 << j)) ? M[j] : m[j]; mul_m4_v3(obj->target2global, t); DO_MINMAX(t, min, max); } }
/* Precache a volume into a 3D voxel grid. * The voxel grid is stored in the ObjectInstanceRen, * in camera space, aligned with the ObjectRen's bounding box. * Resolution is defined by the user. */ void vol_precache_objectinstance_threads(Render *re, ObjectInstanceRen *obi, Material *ma) { VolumePrecache *vp; VolPrecachePart *nextpa, *pa; RayObject *tree; ShadeInput shi; ListBase threads; float *bbmin=obi->obr->boundbox[0], *bbmax=obi->obr->boundbox[1]; int parts[3] = {1, 1, 1}, totparts; int caching=1, counter=0; int totthread = re->r.threads; double time, lasttime= PIL_check_seconds_timer(); R = *re; /* create a raytree with just the faces of the instanced ObjectRen, * used for checking if the cached point is inside or outside. */ //tree = create_raytree_obi(obi, bbmin, bbmax); tree = makeraytree_object(&R, obi); if (!tree) return; INIT_MINMAX(bbmin, bbmax); RE_rayobject_merge_bb( tree, bbmin, bbmax); vp = MEM_callocN(sizeof(VolumePrecache), "volume light cache"); if (!precache_resolution(vp, bbmin, bbmax, ma->vol.precache_resolution)) { MEM_freeN(vp); vp = NULL; return; } vp->data_r = MEM_callocN(sizeof(float)*vp->res[0]*vp->res[1]*vp->res[2], "volume light cache data red channel"); vp->data_g = MEM_callocN(sizeof(float)*vp->res[0]*vp->res[1]*vp->res[2], "volume light cache data green channel"); vp->data_b = MEM_callocN(sizeof(float)*vp->res[0]*vp->res[1]*vp->res[2], "volume light cache data blue channel"); obi->volume_precache = vp; /* Need a shadeinput to calculate scattering */ precache_setup_shadeinput(re, obi, ma, &shi); precache_init_parts(re, tree, &shi, obi, totthread, parts); totparts = parts[0] * parts[1] * parts[2]; BLI_init_threads(&threads, vol_precache_part, totthread); while(caching) { if(BLI_available_threads(&threads) && !(re->test_break(re->tbh))) { nextpa = precache_get_new_part(re); if (nextpa) { nextpa->working = 1; BLI_insert_thread(&threads, nextpa); } } else PIL_sleep_ms(50); caching=0; counter=0; for(pa= re->volume_precache_parts.first; pa; pa= pa->next) { if(pa->done) { counter++; BLI_remove_thread(&threads, pa); } else caching = 1; } if (re->test_break(re->tbh) && BLI_available_threads(&threads)==totthread) caching=0; time= PIL_check_seconds_timer(); if(time-lasttime>1.0f) { char str[64]; sprintf(str, "Precaching volume: %d%%", (int)(100.0f * ((float)counter / (float)totparts))); re->i.infostr= str; re->stats_draw(re->sdh, &re->i); re->i.infostr= NULL; lasttime= time; } } BLI_end_threads(&threads); BLI_freelistN(&re->volume_precache_parts); if(tree) { //TODO: makeraytree_object creates a tree and saves it on OBI, if we free this tree we should also clear other pointers to it //RE_rayobject_free(tree); //tree= NULL; } lightcache_filter(obi->volume_precache); if (ELEM(ma->vol.shade_type, MA_VOL_SHADE_MULTIPLE, MA_VOL_SHADE_SHADEDPLUSMULTIPLE)) { multiple_scattering_diffusion(re, vp, ma); } }