clray

diff src/scene.cc @ 27:8b2f2ad14ae7

semi-fixed the kdtree construction
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 17 Aug 2010 20:35:00 +0100
parents c740ae431d51
children 97cfd9675310
line diff
     1.1 --- a/src/scene.cc	Tue Aug 17 01:19:43 2010 +0100
     1.2 +++ b/src/scene.cc	Tue Aug 17 20:35:00 2010 +0100
     1.3 @@ -2,11 +2,15 @@
     1.4  #include <float.h>
     1.5  #include <assert.h>
     1.6  #include "scene.h"
     1.7 +#include "ogl.h"
     1.8  
     1.9  
    1.10 -static int build_kdtree(KDNode *kd);
    1.11 -static float eval_cost(const std::list<const Face*> &faces, const AABBox &aabb, int axis);
    1.12 +static void draw_kdtree(const KDNode *node, int level = 0);
    1.13 +static bool build_kdtree(KDNode *kd, int level = 0);
    1.14 +static float eval_cost(const std::list<const Face*> &faces, const AABBox &aabb, int axis, float par_sarea = 1.0);
    1.15  static void free_kdtree(KDNode *node);
    1.16 +static int kdtree_depth(const KDNode *node);
    1.17 +static void print_item_counts(const KDNode *node, int level);
    1.18  
    1.19  
    1.20  static int accel_param[NUM_ACCEL_PARAMS] = {
    1.21 @@ -155,13 +159,91 @@
    1.22  }
    1.23  
    1.24  
    1.25 -void Scene::build_kdtree()
    1.26 +void Scene::draw_kdtree() const
    1.27 +{
    1.28 +	glPushAttrib(GL_ENABLE_BIT);
    1.29 +	glDisable(GL_LIGHTING);
    1.30 +	glDepthMask(0);
    1.31 +
    1.32 +	glBegin(GL_LINES);
    1.33 +	::draw_kdtree(kdtree, 0);
    1.34 +	glEnd();
    1.35 +
    1.36 +	glDepthMask(1);
    1.37 +	glPopAttrib();
    1.38 +}
    1.39 +
    1.40 +static float palette[][3] = {
    1.41 +	{0, 1, 0},
    1.42 +	{0, 1, 0},
    1.43 +	{0, 1, 0},
    1.44 +	{1, 0, 0},
    1.45 +	{1, 0, 0},
    1.46 +	{1, 0, 0},
    1.47 +	{0, 0, 1},
    1.48 +	{0, 0, 1},
    1.49 +	{0, 0, 1},
    1.50 +	{1, 1, 0},
    1.51 +	{1, 1, 0},
    1.52 +	{1, 1, 0},
    1.53 +	{0, 0, 1},
    1.54 +	{0, 0, 1},
    1.55 +	{0, 0, 1},
    1.56 +	{1, 0, 1},
    1.57 +	{1, 0, 1},
    1.58 +	{1, 0, 1}
    1.59 +};
    1.60 +static int pal_size = sizeof palette / sizeof *palette;
    1.61 +
    1.62 +static void draw_kdtree(const KDNode *node, int level)
    1.63 +{
    1.64 +	if(!node) return;
    1.65 +
    1.66 +	draw_kdtree(node->left, level + 1);
    1.67 +	draw_kdtree(node->right, level + 1);
    1.68 +
    1.69 +	glColor3fv(palette[level % pal_size]);
    1.70 +
    1.71 +	glVertex3fv(node->aabb.min);
    1.72 +	glVertex3f(node->aabb.max[0], node->aabb.min[1], node->aabb.min[2]);
    1.73 +	glVertex3f(node->aabb.max[0], node->aabb.min[1], node->aabb.min[2]);
    1.74 +	glVertex3f(node->aabb.max[0], node->aabb.max[1], node->aabb.min[2]);
    1.75 +	glVertex3f(node->aabb.max[0], node->aabb.max[1], node->aabb.min[2]);
    1.76 +	glVertex3f(node->aabb.min[0], node->aabb.max[1], node->aabb.min[2]);
    1.77 +	glVertex3f(node->aabb.min[0], node->aabb.max[1], node->aabb.min[2]);
    1.78 +	glVertex3fv(node->aabb.min);
    1.79 +
    1.80 +	glVertex3f(node->aabb.min[0], node->aabb.min[1], node->aabb.max[2]);
    1.81 +	glVertex3f(node->aabb.max[0], node->aabb.min[1], node->aabb.max[2]);
    1.82 +	glVertex3f(node->aabb.max[0], node->aabb.min[1], node->aabb.max[2]);
    1.83 +	glVertex3fv(node->aabb.max);
    1.84 +	glVertex3fv(node->aabb.max);
    1.85 +	glVertex3f(node->aabb.min[0], node->aabb.max[1], node->aabb.max[2]);
    1.86 +	glVertex3f(node->aabb.min[0], node->aabb.max[1], node->aabb.max[2]);
    1.87 +	glVertex3f(node->aabb.min[0], node->aabb.min[1], node->aabb.max[2]);
    1.88 +
    1.89 +	glVertex3fv(node->aabb.min);
    1.90 +	glVertex3f(node->aabb.min[0], node->aabb.min[1], node->aabb.max[2]);
    1.91 +	glVertex3f(node->aabb.max[0], node->aabb.min[1], node->aabb.min[2]);
    1.92 +	glVertex3f(node->aabb.max[0], node->aabb.min[1], node->aabb.max[2]);
    1.93 +	glVertex3f(node->aabb.max[0], node->aabb.max[1], node->aabb.min[2]);
    1.94 +	glVertex3fv(node->aabb.max);
    1.95 +	glVertex3f(node->aabb.min[0], node->aabb.max[1], node->aabb.min[2]);
    1.96 +	glVertex3f(node->aabb.min[0], node->aabb.max[1], node->aabb.max[2]);
    1.97 +}
    1.98 +
    1.99 +bool Scene::build_kdtree()
   1.100  {
   1.101  	const Face *faces = get_face_buffer();
   1.102  	int num_faces = get_num_faces();
   1.103  
   1.104  	printf("Constructing kd-tree out of %d faces ...\n", num_faces);
   1.105  
   1.106 +	int icost = accel_param[ACCEL_PARAM_COST_INTERSECT];
   1.107 +	int tcost = accel_param[ACCEL_PARAM_COST_TRAVERSE];
   1.108 +	printf("  max items per leaf: %d\n", accel_param[ACCEL_PARAM_MAX_NODE_ITEMS]);
   1.109 +	printf("  SAH parameters - tcost: %d - icost: %d\n", tcost, icost);
   1.110 +
   1.111  	free_kdtree(kdtree);
   1.112  	kdtree = new KDNode;
   1.113  
   1.114 @@ -197,17 +279,27 @@
   1.115  	kdtree->cost = eval_cost(kdtree->faces, kdtree->aabb, kdtree->axis);
   1.116  
   1.117  	// now proceed splitting the root recursively
   1.118 -	::build_kdtree(kdtree);
   1.119 +	if(!::build_kdtree(kdtree)) {
   1.120 +		fprintf(stderr, "failed to build kdtree\n");
   1.121 +		return false;
   1.122 +	}
   1.123 +
   1.124 +	printf("  tree depth: %d\n", kdtree_depth(kdtree));
   1.125 +	print_item_counts(kdtree, 0);
   1.126 +	return true;
   1.127  }
   1.128  
   1.129 -static int build_kdtree(KDNode *kd)
   1.130 +static bool build_kdtree(KDNode *kd, int level)
   1.131  {
   1.132  	int opt_max_items = accel_param[ACCEL_PARAM_MAX_NODE_ITEMS];
   1.133 -	if(kd->num_faces == 0 || (opt_max_items > 1 && kd->num_faces < opt_max_items)) {
   1.134 -		return 0;
   1.135 +	int tcost = accel_param[ACCEL_PARAM_COST_TRAVERSE];
   1.136 +
   1.137 +	if(kd->num_faces == 0) {
   1.138 +		return true;
   1.139  	}
   1.140  
   1.141 -	int axis = (kd->axis + 1) % 3;
   1.142 +	int axis = level % 3;
   1.143 +	//float parent_sa = kd->aabb.calc_surface_area();
   1.144  
   1.145  	float best_cost[2], best_sum_cost = FLT_MAX;
   1.146  	float best_split;
   1.147 @@ -226,7 +318,7 @@
   1.148  
   1.149  			float left_cost = eval_cost(kd->faces, aabb_left, axis);
   1.150  			float right_cost = eval_cost(kd->faces, aabb_right, axis);
   1.151 -			float sum_cost = left_cost + right_cost;
   1.152 +			float sum_cost = left_cost + right_cost - tcost;	// tcost is added twice
   1.153  
   1.154  			if(sum_cost < best_sum_cost) {
   1.155  				best_cost[0] = left_cost;
   1.156 @@ -237,8 +329,9 @@
   1.157  		}
   1.158  	}
   1.159  
   1.160 -	if(best_sum_cost >= kd->cost) {
   1.161 -		return 0;	// stop splitting if it doesn't reduce the cost
   1.162 +	printf("current cost: %f,   best_cost: %f\n", kd->cost, best_sum_cost);
   1.163 +	if(best_sum_cost > kd->cost && (opt_max_items == 0 || kd->num_faces <= opt_max_items)) {
   1.164 +		return true;	// stop splitting if it doesn't reduce the cost
   1.165  	}
   1.166  	kd->pt = best_split;
   1.167  
   1.168 @@ -247,7 +340,6 @@
   1.169  	kdleft = new KDNode;
   1.170  	kdright = new KDNode;
   1.171  
   1.172 -	kdleft->axis = kdright->axis = axis;
   1.173  	kdleft->aabb = kdright->aabb = kd->aabb;
   1.174  
   1.175  	kdleft->aabb.max[axis] = best_split;
   1.176 @@ -256,6 +348,8 @@
   1.177  	kdleft->cost = best_cost[0];
   1.178  	kdright->cost = best_cost[1];
   1.179  
   1.180 +	//kdleft->axis = kdright->axis = (axis + 1) % 3;
   1.181 +
   1.182  	it = kd->faces.begin();
   1.183  	while(it != kd->faces.end()) {
   1.184  		const Face *face = *it++;
   1.185 @@ -273,13 +367,15 @@
   1.186  			kdright->num_faces++;
   1.187  		}
   1.188  	}
   1.189 +	kd->faces.clear();	// only leaves have faces
   1.190  
   1.191  	kd->left = kdleft;
   1.192  	kd->right = kdright;
   1.193 -	return 0;
   1.194 +
   1.195 +	return build_kdtree(kd->left, level + 1) && build_kdtree(kd->right, level + 1);
   1.196  }
   1.197  
   1.198 -static float eval_cost(const std::list<const Face*> &faces, const AABBox &aabb, int axis)
   1.199 +static float eval_cost(const std::list<const Face*> &faces, const AABBox &aabb, int axis, float par_sarea)
   1.200  {
   1.201  	int num_inside = 0;
   1.202  	int tcost = accel_param[ACCEL_PARAM_COST_TRAVERSE];
   1.203 @@ -297,7 +393,12 @@
   1.204  		}
   1.205  	}
   1.206  
   1.207 -	return tcost + aabb.calc_surface_area() * num_inside * icost;
   1.208 +	float sarea = aabb.calc_surface_area();
   1.209 +	if(sarea < 1e-8) {
   1.210 +		return FLT_MAX;	// heavily penalize 0-area voxels
   1.211 +	}
   1.212 +
   1.213 +	return tcost + (sarea / par_sarea) * num_inside * icost;
   1.214  }
   1.215  
   1.216  static void free_kdtree(KDNode *node)
   1.217 @@ -308,3 +409,25 @@
   1.218  		delete node;
   1.219  	}
   1.220  }
   1.221 +
   1.222 +static int kdtree_depth(const KDNode *node)
   1.223 +{
   1.224 +	if(!node) return 0;
   1.225 +
   1.226 +	int left = kdtree_depth(node->left);
   1.227 +	int right = kdtree_depth(node->right);
   1.228 +	return (left > right ? left : right) + 1;
   1.229 +}
   1.230 +
   1.231 +static void print_item_counts(const KDNode *node, int level)
   1.232 +{
   1.233 +	if(!node) return;
   1.234 +
   1.235 +	for(int i=0; i<level; i++) {
   1.236 +		fputs("   ", stdout);
   1.237 +	}
   1.238 +	printf("- %d (cost: %f)\n", node->num_faces, node->cost);
   1.239 +
   1.240 +	print_item_counts(node->left, level + 1);
   1.241 +	print_item_counts(node->right, level + 1);
   1.242 +}