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)


_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to