[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [15349] branches/soc-2008-unclezeiv/source /blender/render/intern/source/lightcuts.c: 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

Davide Vercelli davide.vercelli at gmail.com
Wed Jun 25 03:05:00 CEST 2008


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));





More information about the Bf-blender-cvs mailing list