Beispiel #1
0
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++;
}
Beispiel #2
0
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);
	}
}
Beispiel #3
0
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);
    }
}
Beispiel #5
0
/* 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);
	}
}