[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [15365] branches/soc-2008-unclezeiv/source /blender/render/intern/source/lightcuts.c: - added correct computation of scene bounding box diagonal, needed to compute cluster similiarity metric during tree building; this completes support for oriented lights

Davide Vercelli davide.vercelli at gmail.com
Fri Jun 27 03:06:37 CEST 2008


Revision: 15365
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=15365
Author:   unclezeiv
Date:     2008-06-27 03:05:31 +0200 (Fri, 27 Jun 2008)

Log Message:
-----------
- added correct computation of scene bounding box diagonal, needed to compute cluster similiarity metric during tree building; this completes support for oriented lights
- simplified code a bit, as translations were often not needed in many calculations; this way I also found out that I was using transposed matrices w.r.t. blender convention (they were isolated though, no bugs because of this)

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-26 18:28:33 UTC (rev 15364)
+++ branches/soc-2008-unclezeiv/source/blender/render/intern/source/lightcuts.c	2008-06-27 01:05:31 UTC (rev 15365)
@@ -40,6 +40,7 @@
 #include "MEM_guardedalloc.h"
 #include "PIL_time.h"
 #include "RE_pipeline.h"
+#include "RE_raytrace.h"
 
 #include "blendef.h"
 #include "render_types.h"
@@ -115,7 +116,6 @@
 
 typedef struct LightcutsData {
 	/* NOTE: conservative space estimation */
-	/* TODO: equivalent data structures for sun and spot */
 	ListBase pointlights;
 
 	LightcutsTree trees[_TREES_SIZE];
@@ -145,10 +145,11 @@
 } LightcutsData;
 
 #define VEC_LEN_SQ(v) (v[0]*v[0] + v[1]*v[1] + v[2]*v[2])
+#define VECCOPYMUL(v1,v2,aS) {*(v1)= *(v2)*aS; *(v1+1)= *(v2+1)*aS; *(v1+2)= *(v2+2)*aS;}
+#define VECNEG(v) {*(v)=-*(v); *(v+1)=-*(v+1); *(v+2)=-*(v+2);}
 /* TODO: tentative calculation, will look better into it */
 #define LC_LUMINOSITY(c) (0.299*(c)[0] + 0.587*(c)[1] + 0.114*(c)[2])
 /* #define LC_LUMINOSITY(c) (0.316*c[0] + 0.460*c[1] + 0.224*c[2]) */
-#define VECCOPYMUL(v1,v2,aS) {*(v1)= *(v2)*aS; *(v1+1)= *(v2+1)*aS; *(v1+2)= *(v2+2)*aS;}
 #define IS_LEAF(node) (!(node)->child1 && !(node)->child2)
 
 /* XXX: this function looks really slow! */
@@ -464,7 +465,7 @@
 			lar->shadsamp= MEM_mallocN(re->r.threads*sizeof(LampShadowSample), "lamp shadow sample");
 			ls= lar->shadsamp;
 
-			/* shadfacs actually mean light, let's put them to 1 to prevent unitialized accidents */
+			/* shadfacs actually mean light, let's put them to 1 to prevent uninitialized accidents */
 			for(a=0; a<re->r.threads; a++, ls++) {
 				lss= ls->s;
 				for(b=0; b<re->r.osa; b++, lss++) {
@@ -520,7 +521,6 @@
 			lcd->trees[TREE_LOCAL].counter++;
 
 			/* TODO: handle other attenuation models */
-
 			if (lar->dist < lcd->max_local_dist)
 				lcd->max_local_dist = lar->dist;
 
@@ -530,6 +530,8 @@
 			break;
 		case LA_SPOT:
 			/* TODO: check if it's a valid spot */
+			
+			/* TODO: handle other attenuation models */
 			if (lar->dist < lcd->max_spot_dist)
 				lcd->max_spot_dist= lar->dist;
 			
@@ -560,7 +562,7 @@
 		gonew->recalc= go->recalc;
 		/*
 		 * XXX: probably wrong, more a test to see if it is used somewhere
-		 * or dealloacated
+		 * or deallocated
 		 * The point here is that we create new lights with no corresponding
 		 * objects... do we need objects there?
 		 */
@@ -599,9 +601,12 @@
 	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;
 	
+	/* we need the scene's diagonal squared */
+	lcd->bb_diag_sq= RE_ray_tree_max_size(re->raytree);
+	printf("Scene diagonal %f\n", lcd->bb_diag_sq);
+	lcd->bb_diag_sq*= lcd->bb_diag_sq;
+	
 	re->i.infostr= "Building light trees";
 	re->stats_draw(&re->i);
 
@@ -611,7 +616,6 @@
 			lightcuts_fill_array(pointlights, &lcd->trees[i], i);
 			printf("Lightcuts: building %s tree - ", tree_names[i]);
 			lightcuts_build_tree(&lcd->trees[i], lcd->bb_diag_sq);
-			/* TODO: put square of scene bounding box diagonale instead of 0.0f */
 		}
 	}
 	
@@ -627,18 +631,17 @@
 }
 
 /* Adapted from "Transforming Axis-Aligned Bounding Boxes" by Jim Arvo, "Graphics Gems", Academic Press, 1990 */
-static void transform_aabb(float tsm[4][4], float min[3], float max[3], float rmin[3], float rmax[3], int do_transl)
+static void transform_aabb(float tsm[3][3], float min[3], float max[3], float rmin[3], float rmax[3])
 {
 	int i, j;
 	float a, b;
 
 	for (i = 0; i < 3; i++) {
-		/* translation */
-		rmin[i]= rmax[i]= (do_transl ? tsm[i][3] : 0.0f);
+		rmin[i]= rmax[i]= 0.0f;
 
 		for (j = 0; j < 3; j++) {
-			a= tsm[i][j] * min[j];
-			b= tsm[i][j] * max[j];
+			a= tsm[j][i] * min[j];
+			b= tsm[j][i] * max[j];
 			if (a < b) {
 				rmin[i]+= a;
 				rmax[i]+= b;
@@ -667,45 +670,32 @@
 	return max[2] / sqrt(xsq + ysq + max[2]*max[2]);
 }
 
-/* fill in tangent space matrix tsm given normal and position; please note, it's also a translation matrix */
-/* 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)
+/* fill in tangent space matrix tsm given normal */
+static void get_tangent_space_matrix(float tsm[3][3], float *nor)
 {
-	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 */
-	if (negate) {
-		normat[2][0] = -nor[0];
-		normat[2][1] = -nor[1];
-		normat[2][2] = -nor[2];
-	}
-	else
-		VECCOPY(normat[2], nor);
-
+	float normat[3][3];
+	
+	VECCOPY(normat[2], nor);
 	VecOrthoBasisf(normat[2], normat[0], normat[1]);
 
-	VECCOPY(normat[3], pos);
-
-	normat[0][3]= normat[1][3]= normat[2][3]= 0.0f;
-	normat[3][3]= 1.0f;
-
-	Mat4Transp(normat);
 	/* now we have a proper tangent-to-world matrix: let's invert it */
-	Mat4Invert(tsm, normat);
+	Mat3Inv(tsm, normat);
 }
 
 /* error bound: material term */
 /* TODO: currently supporting only diffuse */
-static float calc_material_eb(float tsm[4][4], LightcutsCluster *clus)
+static float calc_material_eb(float tsm[3][3], LightcutsCluster *clus, float *pos)
 {
 	float tmin[3], tmax[3];
-	transform_aabb(tsm, clus->min, clus->max, tmin, tmax, (clus->type!=CLUSTER_SUN));
+	transform_aabb(tsm, clus->min, clus->max, tmin, tmax);
+	if (clus->type != CLUSTER_SUN) {
+		VECADD(tmin, pos, tmin);
+		VECADD(tmax, pos, tmax);
+	}
 	return MAX2(compute_cosine_bound(tmin, tmax), 0.0);
 }
 
 /* error bound: geometric term */
-/* TODO: missing LA_SPOT eb */
 static float calc_geometric_eb(LightcutsData *lcd, LightcutsCluster *clus, float *pos)
 {
 	/* find the nearest point in the bounding box */
@@ -734,14 +724,14 @@
 		float newmin[3], transmin[3];
 		float newmax[3], transmax[3];
 		float cos_t, angle;
-		float tsm[4][4];
+		float tsm[3][3];
 		
-		get_tangent_space_matrix(tsm, clus->cone_dir, pos, 0);
+		get_tangent_space_matrix(tsm, clus->cone_dir);
 		
 		VECSUB(newmax, pos, clus->min);
 		VECSUB(newmin, pos, clus->max);
 		
-		transform_aabb(tsm, newmin, newmax, transmin, transmax, 0);
+		transform_aabb(tsm, newmin, newmax, transmin, transmax);
 		
 		cos_t= compute_cosine_bound(transmin, transmax);
 		angle= acosf(cos_t);
@@ -773,11 +763,13 @@
 	int it= 0;
 	int used= 0;
 	float i, i_noshad;
-	float tsm[4][4]; /* tangent space matrix */
+	float tsm[3][3]; /* tangent space matrix */
+	float tspos[3];
 	LightcutsCluster *array;
 
-	/* this heap maintaines the current cut */
-	/* TODO: its maximum size is known in advance, this allows to
+	/* 
+	 * this heap maintains the current cut
+	 * TODO: its maximum size is known in advance, this allows to
 	 * preallocate it and share it between subsequent executions
 	 */
 	Heap *cut= BLI_heap_new();
@@ -791,9 +783,17 @@
 
 	float dbg_totlum = 0.0f;
 #endif
+	
+	/* XXX: shi->vn seems to point inside the mesh, investigate; works inverted like this */
+	VECCOPY(tspos, shi->vn);
+	VECNEG(tspos);
+	get_tangent_space_matrix(tsm, tspos);
+	
+	/* get sample coordinates in tangent space */
+	VECCOPY(tspos, shi->co);
+	Mat3MulVecfl(tsm, tspos);
+	VECNEG(tspos);
 
-	get_tangent_space_matrix(tsm, shi->vn, shi->co, 1);
-
 	cut_nodes= lcd->cut_nodes + shi->thread * lcd->cut_nodes_size;
 
 	/* initial nodes in the queue */
@@ -810,7 +810,7 @@
 
 				root->id= tree->root;
 				root->type= clus->type;
-				root->error_bound= calc_geometric_eb(lcd, clus, shi->co) * calc_material_eb(tsm, clus) * shi->refl;
+				root->error_bound= calc_geometric_eb(lcd, clus, shi->co) * calc_material_eb(tsm, clus, tspos) * shi->refl;
 #ifdef LIGHTCUTS_DEBUG
 				dbg_convert[tree->root]= 0;
 #endif
@@ -903,15 +903,11 @@
 #ifdef LIGHTCUTS_DEBUG
 			dbg_totlum-= cn_hinode->contr_factor * hinode->luminance;
 #endif
-
-			/* this is a strong assumption on linearity of intensity contribution... is it strong indeed?
-			 * and numerically questionable again */
-			/* TODO: there is room to reuse the same block here */
-
-			/* for the reprsented light we can reuse most calculations */
+			
+			/* for the represented light we can reuse most calculations */
 			cn_rep->id= rep->id;
 			cn_rep->type= rep->type;
-			cn_rep->error_bound= calc_geometric_eb(lcd, rep, shi->co) * calc_material_eb(tsm, rep) * shi->refl;
+			cn_rep->error_bound= calc_geometric_eb(lcd, rep, shi->co) * calc_material_eb(tsm, rep, tspos) * shi->refl;
 
 			if (cn_rep->error_bound > FLT_EPSILON) {
 				cn_rep->contr_factor= cn_hinode->contr_factor;
@@ -932,7 +928,7 @@
 			/* for the "unrepresented" light we have to compute stuff from scratch */
 			cn_unrep->id= unrep->id;
 			cn_unrep->type= unrep->type;
-			cn_unrep->error_bound= calc_geometric_eb(lcd, unrep, shi->co) * calc_material_eb(tsm, unrep) * shi->refl;
+			cn_unrep->error_bound= calc_geometric_eb(lcd, unrep, shi->co) * calc_material_eb(tsm, unrep, tspos) * shi->refl;
 
 			if (cn_unrep->error_bound > FLT_EPSILON) {
 				get_contrib(unrep->lar, shi, &i, &i_noshad);





More information about the Bf-blender-cvs mailing list