[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