Revision: 15349
          
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=15349
Author:   unclezeiv
Date:     2008-06-25 03:04:21 +0200 (Wed, 25 Jun 2008)

Log Message:
-----------
added tree building and geometric error bound for oriented lights; the only 
thing missing now is the correct computation of the similarity metric 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-06-24 22:19:00 UTC (rev 15348)
+++ branches/soc-2008-unclezeiv/source/blender/render/intern/source/lightcuts.c 
2008-06-25 01:04:21 UTC (rev 15349)
@@ -121,6 +121,7 @@
        LightcutsTree trees[_TREES_SIZE];
 
        float max_local_dist; /* maximum distance for local lights */
+       float max_spot_dist; /* maximum distance for oriented lights */
 
        int light_counter;
 
@@ -174,7 +175,7 @@
        return angle_new;
 }
 
-static float lightcuts_compute_metric(float c, LightcutsCluster * one, 
LightcutsCluster * two)
+static float lightcuts_compute_metric(float csq, LightcutsCluster * one, 
LightcutsCluster * two)
 {
        float diff[3], min[3], max[3];
 
@@ -189,7 +190,7 @@
        if (one->type == CLUSTER_SPOT) {
                float cos_a= cosf(get_bounding_cone(one, two, NULL));
                float term = (1 - cos_a) * (1 - cos_a);
-               return (one->luminance + two->luminance) * (VEC_LEN_SQ(diff) + 
c * term);
+               return (one->luminance + two->luminance) * (VEC_LEN_SQ(diff) + 
csq * term);
        }
 
        return (one->luminance + two->luminance) * VEC_LEN_SQ(diff);
@@ -222,6 +223,10 @@
        VECCOPY(dest->max, one->max);
        DO_MINMAX(two->min, dest->min, dest->max);
        DO_MINMAX(two->max, dest->min, dest->max);
+       
+       /* if LA_SPOT, compute new bounding cone */
+       if (one->type == CLUSTER_SPOT)
+               dest->cone_angle= get_bounding_cone(one, two, dest->cone_dir);
 
        /* the representative light is chosen randomly among children */
        if (BLI_frand() * (one->luminance + two->luminance) < one->luminance) {
@@ -313,6 +318,12 @@
                        clus->min[2]= -lar->vec[2];
                        VECCOPY(clus->max, clus->min);
                        break;
+               case LA_SPOT:
+                       VECCOPY(clus->min, lar->co);
+                       VECCOPY(clus->max, lar->co);
+                       VECCOPY(clus->cone_dir, lar->vec);
+                       clus->cone_angle= 0.0f;
+                       break;
                }
                clus->lar = lar;
 
@@ -366,7 +377,7 @@
        LightcutsCluster *array= tree->array;
 
        Heap * heap = BLI_heap_new();
-       /* TODO: taylor size: done. current TODO is "check if it works" */
+       /* TODO: tailor size: done. current TODO is "check if it works" */
        LightcutsClusterPair *pair_array= 
MEM_callocN(sizeof(LightcutsClusterPair) * tree->counter * 2, "pair_array");
 
        for (i = 0; i < tree->counter; i++)
@@ -489,7 +500,8 @@
 
        re->lcdata = lcd = MEM_callocN(sizeof(LightcutsData), "LightcutsData");
        pointlights= &lcd->pointlights;
-       lcd->max_local_dist = MAXFLOAT;
+       lcd->max_local_dist= MAXFLOAT;
+       lcd->max_spot_dist= MAXFLOAT;
        lcd->light_counter= 0;
 
        for(go=lights->first; go; go= go->next) {
@@ -516,6 +528,13 @@
                case LA_SUN:
                        lcd->trees[TREE_SUN].counter++;
                        break;
+               case LA_SPOT:
+                       /* TODO: check if it's a valid spot */
+                       if (lar->dist < lcd->max_spot_dist)
+                               lcd->max_spot_dist= lar->dist;
+                       
+                       lcd->trees[TREE_SPOT].counter++;
+                       break;
                default:
                        continue;
                }
@@ -575,11 +594,13 @@
 #endif
        }
 
-       /* XXX: whis should be equal to re->r.lightcuts_max_lights when light 
generation is in place */
+       /* XXX: this should be equal to re->r.lightcuts_max_lights when light 
generation is in place */
        lcd->max_lights= lcd->light_counter;
        lcd->error_rate= re->r.lightcuts_max_error;
        lcd->max_cut= MIN2(re->r.lightcuts_max_cut, lcd->light_counter);
        lcd->start_time= PIL_check_seconds_timer();
+       /* XXX: TODO: get proper scene diagonal */
+       lcd->bb_diag_sq= 11.747*11.747;
        
        re->i.infostr= "Building light trees";
        re->stats_draw(&re->i);
@@ -589,7 +610,7 @@
                if (lcd->trees[i].counter > 0) {
                        lightcuts_fill_array(pointlights, &lcd->trees[i], i);
                        printf("Lightcuts: building %s tree - ", tree_names[i]);
-                       lightcuts_build_tree(&lcd->trees[i], 0.0f);
+                       lightcuts_build_tree(&lcd->trees[i], lcd->bb_diag_sq);
                        /* TODO: put square of scene bounding box diagonale 
instead of 0.0f */
                }
        }
@@ -647,15 +668,20 @@
 }
 
 /* fill in tangent space matrix tsm given normal and position; please note, 
it's also a translation matrix */
-static void get_tangent_space_matrix(float tsm[4][4], float *nor, float *pos)
+/* TODO: scrap the translation part, use a 3x3 and transform the vector when 
needed */
+static void get_tangent_space_matrix(float tsm[4][4], float *nor, float *pos, 
int negate)
 {
        float normat[4][4];
 
        /* warning: we fill it transposed as it's easier */
        /* XXX: shi->vn seems to point inside the mesh, investigate; works 
inverted like this */
-       normat[2][0] = -nor[0];
-       normat[2][1] = -nor[1];
-       normat[2][2] = -nor[2];
+       if (negate) {
+               normat[2][0] = -nor[0];
+               normat[2][1] = -nor[1];
+               normat[2][2] = -nor[2];
+       }
+       else
+               VECCOPY(normat[2], nor);
 
        VecOrthoBasisf(normat[2], normat[0], normat[1]);
 
@@ -682,26 +708,56 @@
 /* TODO: missing LA_SPOT eb */
 static float calc_geometric_eb(LightcutsData *lcd, LightcutsCluster *clus, 
float *pos)
 {
-       if (clus->type==CLUSTER_LOCAL) {
-               /* find the nearest point in the bounding box */
-               float *min= clus->min;
-               float *max= clus->max;
-               float nearest[3];
-               float len_sq;
-               nearest[0]= pos[0] < min[0] ? min[0] : (pos[0] > max[0] ? 
max[0] : pos[0]);
-               nearest[1]= pos[1] < min[1] ? min[1] : (pos[1] > max[1] ? 
max[1] : pos[1]);
-               nearest[2]= pos[2] < min[2] ? min[2] : (pos[2] > max[2] ? 
max[2] : pos[2]);
+       /* find the nearest point in the bounding box */
+       float *min= clus->min;
+       float *max= clus->max;
+       float nearest[3];
+       float len_sq;
+       
+       if (clus->type == CLUSTER_SUN)
+               return 1.0f;
+       
+       nearest[0]= pos[0] < min[0] ? min[0] : (pos[0] > max[0] ? max[0] : 
pos[0]);
+       nearest[1]= pos[1] < min[1] ? min[1] : (pos[1] > max[1] ? max[1] : 
pos[1]);
+       nearest[2]= pos[2] < min[2] ? min[2] : (pos[2] > max[2] ? max[2] : 
pos[2]);
 
-               VECSUB(nearest, nearest, pos);
-               len_sq= VEC_LEN_SQ(nearest);
+       VECSUB(nearest, nearest, pos);
+       len_sq= VEC_LEN_SQ(nearest);
 
+       /*
+        * TODO: could take the various supported attenuation functions into 
account,
+        * using the worst case among the one found while creating the tree
+        */
+       if (clus->type == CLUSTER_LOCAL)
+               return lcd->max_local_dist / (lcd->max_local_dist + len_sq);
+       else {
+               float newmin[3], transmin[3];
+               float newmax[3], transmax[3];
+               float cos_t, angle;
+               float tsm[4][4];
+               
+               get_tangent_space_matrix(tsm, clus->cone_dir, pos, 0);
+               
+               VECSUB(newmax, pos, clus->min);
+               VECSUB(newmin, pos, clus->max);
+               
+               transform_aabb(tsm, newmin, newmax, transmin, transmax, 0);
+               
+               cos_t= compute_cosine_bound(transmin, transmax);
+               angle= acosf(cos_t);
+               
+               if (angle < clus->cone_angle)
+                       return 1.0;
+               return lcd->max_spot_dist / (lcd->max_spot_dist + len_sq) * 
MAX2(0.0f, cosf(angle - clus->cone_angle));
+               
                /*
-                * TODO: could take the various supported attenuation functions 
into account,
-                * using the worst case among the one found while creating the 
tree
+                * cos(a+b) = cos_a*cos_b - sin_a*sin_b
+                * cos(angle-ca) = cos_t * cos_ca - sin_T * sin_ca
+                * - cos_ca and sin_ca precomputable in initial step
+                * - cos_t we have it already
+                * - sin_t it's sqrt(1 - cos_t * cos_t)... is it faster?
                 */
-               return lcd->max_local_dist / (lcd->max_local_dist + len_sq);
        }
-       return 1.0f;
 }
 
 /*
@@ -736,7 +792,7 @@
        float dbg_totlum = 0.0f;
 #endif
 
-       get_tangent_space_matrix(tsm, shi->vn, shi->co);
+       get_tangent_space_matrix(tsm, shi->vn, shi->co, 1);
 
        cut_nodes= lcd->cut_nodes + shi->thread * lcd->cut_nodes_size;
 
@@ -951,7 +1007,9 @@
               "Average cut size: %.2f\n"
               "Shadow rays: %.2f (%.2f%%)\n"
               "---------------\n",
-               lcd->stat_samples, lcd->light_counter, 
lcd->trees[TREE_LOCAL].counter, lcd->trees[TREE_SUN].counter, 0, lcd->max_cut,
+               lcd->stat_samples, lcd->light_counter,
+               lcd->trees[TREE_LOCAL].counter, lcd->trees[TREE_SUN].counter, 
lcd->trees[TREE_SPOT].counter,
+               lcd->max_cut,
                (float)lcd->stat_cut_size / (float)lcd->stat_samples,
                (float)lcd->stat_rays_shot / (float)lcd->stat_samples,
                100.0f * lcd->stat_rays_shot / (float)(lcd->stat_samples * 
lcd->light_counter));


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

Reply via email to