[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [16912] branches/soc-2008-unclezeiv/source /blender/render/intern/source/lightcuts.c: Added a workaround to a bug that could cause unusually long tree building times and result in wrong renderings ; this was caused by nan values finding their way into the kdtree.

Davide Vercelli davide.vercelli at gmail.com
Sat Oct 4 11:03:46 CEST 2008


Revision: 16912
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=16912
Author:   unclezeiv
Date:     2008-10-04 11:03:45 +0200 (Sat, 04 Oct 2008)

Log Message:
-----------
Added a workaround to a bug that could cause unusually long tree building times and result in wrong renderings; this was caused by nan values finding their way into the kdtree.

To cope with similar situations should they occur in the future, I also added more test_break() checks, in order to be able to interrupt the rendering at will even during tree building.

Modified Paths:
--------------
    branches/soc-2008-unclezeiv/source/blender/render/intern/source/lightcuts.c

Modified: branches/soc-2008-unclezeiv/source/blender/render/intern/source/lightcuts.c
===================================================================
--- branches/soc-2008-unclezeiv/source/blender/render/intern/source/lightcuts.c	2008-10-04 01:18:05 UTC (rev 16911)
+++ branches/soc-2008-unclezeiv/source/blender/render/intern/source/lightcuts.c	2008-10-04 09:03:45 UTC (rev 16912)
@@ -230,6 +230,8 @@
 #endif
 	float *dbg_vis_vpl;
 	int *vpl_to_cap;
+	
+	int (*test_break)(void);
 } LightcutsData;
 
 typedef struct SampleCoordInfo {
@@ -457,7 +459,7 @@
 			}
 			
 			if (!found)
-				printf("TERRIBLE bug!\n");
+				printf("BUG: no representative selected for %d: tot_lum %f\n", one->id, tot_lum);
 		}
 		
 		/* sort list and allocate list */
@@ -534,6 +536,9 @@
 	else
 		data->mindir= 0.0f;
 	
+#ifdef LIGHTCUTS_DEBUG
+	printf("id %d, type %d, energy %10.7f, intensity %10.7f, luminance %10.7f ", one->id, one->type, one->lar->energy, one->intensity, one->luminance);
+#endif
 	other= BLI_kdtree_find_callback(tree, one->lar->co, NULL, one->id, cb_update_metric_max_dist, data, nearest);
 	
 	if (other != -1)
@@ -562,6 +567,11 @@
 		if (lar->type!=cur_type)
 			continue;
 
+#ifdef LIGHTCUTS_DEBUG
+		if (isnan(lar->energy))
+			printf("ISNAN %d\n", tree->free);
+#endif
+
 		clus->type = LA_TYPE_TO_CLUSTER_TYPE(cur_type);
 		clus->in_tree = 0;
 		clus->id = tree->free;
@@ -756,11 +766,11 @@
 #endif
 
 /* this one uses kdtree */
-static void lightcuts_build_tree2(LightcutsData *lcd, int tree_index)
+static int lightcuts_build_tree2(LightcutsData *lcd, int tree_index)
 {
 	LightcutsTree *tree= &lcd->trees[tree_index];
 	float c= lcd->scene_diag * lcd->scene_diag;
-	int i, rep, cluster_id= 0;
+	int i, rep, cluster_id= 0, stop=0;
 	LightcutsCluster *array= tree->array;
 #ifdef LIGHTCUTS_DEBUG
 	double p1, p2;
@@ -817,17 +827,28 @@
 #endif
 		
 	for (i = 0; i < tree->counter; i++)
-		if (array[i].type != CLUSTER_EMPTY)
+		if (array[i].type != CLUSTER_EMPTY) {
+			if (lcd->test_break()) {
+				stop= 1;
+				break;
+			}
+			
 			find_and_insert_new_min2(heap, kdtree, nearest, &data, &pair_array[i], i);
+		}
 
 	/* now we have a nice heap with shortest metric for each element */
 	/* heap size = N (number of lights) - 1, and it doesn't grow */
 
 	/* go through heap building the tree */
-	while (!BLI_heap_empty(heap)) {
+	while (!stop && !BLI_heap_empty(heap)) {
 		LightcutsClusterPair * minpair = (LightcutsClusterPair *)BLI_heap_popmin(heap);
 		short in_tree1 = array[minpair->first].in_tree;
 		short in_tree2 = array[minpair->second].in_tree;
+		
+		if (lcd->test_break()) {
+			stop= 1;
+			break;
+		}
 
 		if (in_tree1)
 			continue;
@@ -876,10 +897,15 @@
 		dbg_print_tree(array, tree->root, 0);
 	}
 #endif
-	printf(" %d nodes used.\n", tree->root + 1);
+	if (stop)
+		printf(" aborted.\n");
+	else
+		printf(" %d nodes used.\n", tree->root + 1);
 
 	MEM_freeN(pair_array);
 	MEM_freeN(nearest);
+	
+	return -stop;
 }
 
 static void lamp_init(Render * re, LampRen * lar)
@@ -1341,6 +1367,7 @@
 	int old_vlr_flag;
 	
 	/* hack: increase current color/energy in order to avoid too dark results */
+	/* XXX: how does this interact with color ramps? */
 	energy= lar->energy;
 	savecol[0]= lar->r;
 	savecol[1]= lar->g;
@@ -1350,7 +1377,7 @@
 	lar->b /= lar->energy;
 	lar->energy= 1.0f;
 	
-	/* don't do normal flipping in this phase */
+	/* don't do normal flipping in this phase, as the query is not camera aligned */
 	old_vlr_flag= vla->flag;
 	vla->flag |= R_NOPUNOFLIP;
 	
@@ -1360,7 +1387,7 @@
 	light_override.gobject.first= &go;
 	light_override.gobject.last= &go;
 	
-	/* long and complex shade input initialization */
+	/* start long and complex shade input initialization */
 	memset(shi, 0, sizeof(ShadeInput));
 	
 	/* from shade_input_initialize, but without a RenderLayer */
@@ -1425,6 +1452,16 @@
 #endif
 	
 	shade_input_set_uv(shi);
+	
+	/*
+	 * XXX: workaround, actually the problem is about using camera space
+	 * instead of our own sampling space
+	 */
+	if (isnan(shi->u)) {
+		lcd->stat_discard_nan++;
+		return -1.0f;
+	}
+	
 	shade_input_set_normals(shi);
 	shade_input_set_shade_texco(shi);
 	
@@ -1519,6 +1556,9 @@
 	VECADDFAC(co, isec.start, isec.vec, isec.labda - 0.01);
 	
 	fac= get_bounce_color(lcd, isec.ob, vla, co, orig, scol, isec.isect);
+	
+	if (fac == -1.0f)
+		return;
 
 	if (fac <= 0.0f) {
 		lcd->stat_discard_black++;
@@ -1555,6 +1595,11 @@
 	
 	/* note that lamp_get_visibility is called in get_bounce_color */
 	lar->energy= fac * orig->energy * lcd->indir_fac * weight;
+
+#ifdef LIGHTCUTS_DEBUG
+	if (isnan(lar->energy))
+		printf("addVPL ISNAN %d\n", lcd->vpl_counter + 1);
+#endif
 	
 	/* TODO: without proper spectrum handling, this could be too darkening */
 	scol[0]*= col[0];
@@ -1693,7 +1738,7 @@
 	ListBase *lights = &re->lights;
 	LampRen *lar, *own;
 	char tree_time_str[12]; /* length 12 required by BLI_timestr */
-	int i;
+	int i, stop=0;
 	
 	re->i.infostr= "Initializing Lightcuts";
 	re->stats_draw(&re->i);
@@ -1707,6 +1752,7 @@
 	lcd->options= re->r.lightcuts_options;
 	lcd->error_rate= re->r.lightcuts_max_error;
 	lcd->scene_diag= RE_ray_tree_max_size(re->raytree);
+	lcd->test_break= re->test_break;
 #ifdef LIGHTCUTS_DEBUG
 	lcd->dbg_options= re->r.lightcuts_debug_options;
 #endif
@@ -1857,7 +1903,10 @@
 		if (lcd->trees[i].counter > 0) {
 			lightcuts_fill_array(lcd, i);
 			printf("Lightcuts: building %s tree - ", tree_names[i]);
-			lightcuts_build_tree2(lcd, i);
+			if (lightcuts_build_tree2(lcd, i) == -1) {
+				stop= 1;
+				break;
+			}
 		}
 	}
 	
@@ -1874,7 +1923,7 @@
 	/* XXX: restore mode (terrible hack needed by get_bounce_color) */
 	R.r.mode|= R_LIGHTCUTS;
 	
-	if (lcd->vpl_counter) {
+	if (!stop && lcd->vpl_counter) {
 		lcd->vpl_to_cap= MEM_callocN(sizeof(int) * lcd->max_cut * re->r.threads, "vpl_to_cap");
 		
 		if (lcd->options & LC_OPT_INDIR_MESH && lcd->vpl_counter > 0)





More information about the Bf-blender-cvs mailing list