rev |
line source |
nuclear@35
|
1 #include <stdlib.h>
|
nuclear@59
|
2 #include <string.h>
|
John@15
|
3 #include <math.h>
|
nuclear@25
|
4 #include <float.h>
|
nuclear@26
|
5 #include <assert.h>
|
nuclear@35
|
6 #include <map>
|
nuclear@22
|
7 #include "scene.h"
|
nuclear@27
|
8 #include "ogl.h"
|
nuclear@59
|
9 #include "vector.h"
|
nuclear@6
|
10
|
nuclear@38
|
11 #define CHECK_AABB(aabb) \
|
nuclear@38
|
12 assert(aabb.max[0] >= aabb.min[0] && aabb.max[1] >= aabb.min[1] && aabb.max[2] >= aabb.min[2])
|
nuclear@38
|
13
|
nuclear@26
|
14
|
nuclear@37
|
15 #define MIN(a, b) ((a) < (b) ? (a) : (b))
|
nuclear@37
|
16 #define MAX(a, b) ((a) > (b) ? (a) : (b))
|
nuclear@37
|
17
|
nuclear@37
|
18
|
nuclear@53
|
19 static int flatten_kdtree(const KDNode *node, KDNodeGPU *kdbuf, int *count);
|
nuclear@27
|
20 static void draw_kdtree(const KDNode *node, int level = 0);
|
nuclear@32
|
21 static bool build_kdtree(KDNode *kd, const Face *faces, int level = 0);
|
nuclear@32
|
22 static float eval_cost(const Face *faces, const int *face_idx, int num_faces, const AABBox &aabb, int axis);
|
nuclear@26
|
23 static void free_kdtree(KDNode *node);
|
nuclear@27
|
24 static void print_item_counts(const KDNode *node, int level);
|
nuclear@59
|
25 static int clip_face(const Face &inface, float splitpos, int axis, int sign, Face *faces);
|
nuclear@59
|
26 static float calc_sq_area(const Vector3 &a, const Vector3 &b, const Vector3 &c);
|
nuclear@26
|
27
|
nuclear@26
|
28
|
nuclear@26
|
29 static int accel_param[NUM_ACCEL_PARAMS] = {
|
nuclear@44
|
30 64, // max tree depth
|
nuclear@44
|
31 MAX_NODE_FACES, // max items per node (0 means ignore limit)
|
nuclear@26
|
32 5, // estimated traversal cost
|
nuclear@26
|
33 15 // estimated interseciton cost
|
nuclear@26
|
34 };
|
nuclear@26
|
35
|
nuclear@26
|
36
|
nuclear@26
|
37 void set_accel_param(int p, int v)
|
nuclear@26
|
38 {
|
nuclear@26
|
39 assert(p >= 0 && p < NUM_ACCEL_PARAMS);
|
nuclear@26
|
40 accel_param[p] = v;
|
nuclear@26
|
41 }
|
nuclear@26
|
42
|
nuclear@26
|
43
|
nuclear@25
|
44 float AABBox::calc_surface_area() const
|
nuclear@25
|
45 {
|
nuclear@25
|
46 float area1 = (max[0] - min[0]) * (max[1] - min[1]);
|
nuclear@25
|
47 float area2 = (max[3] - min[3]) * (max[1] - min[1]);
|
nuclear@25
|
48 float area3 = (max[0] - min[0]) * (max[3] - min[3]);
|
nuclear@25
|
49
|
nuclear@25
|
50 return 2.0f * (area1 + area2 + area3);
|
nuclear@25
|
51 }
|
nuclear@25
|
52
|
nuclear@26
|
53 KDNode::KDNode()
|
nuclear@26
|
54 {
|
nuclear@26
|
55 left = right = 0;
|
nuclear@32
|
56 cost = 0.0;
|
nuclear@26
|
57 }
|
nuclear@26
|
58
|
nuclear@25
|
59
|
nuclear@24
|
60 Scene::Scene()
|
nuclear@24
|
61 {
|
nuclear@24
|
62 facebuf = 0;
|
nuclear@24
|
63 num_faces = -1;
|
nuclear@24
|
64 kdtree = 0;
|
nuclear@28
|
65 kdbuf = 0;
|
nuclear@24
|
66 }
|
nuclear@24
|
67
|
nuclear@24
|
68 Scene::~Scene()
|
nuclear@24
|
69 {
|
nuclear@24
|
70 delete [] facebuf;
|
nuclear@28
|
71 delete [] kdbuf;
|
nuclear@28
|
72 free_kdtree(kdtree);
|
nuclear@24
|
73 }
|
nuclear@24
|
74
|
nuclear@13
|
75 bool Scene::add_mesh(Mesh *m)
|
nuclear@13
|
76 {
|
nuclear@13
|
77 // make sure triangles have material ids
|
nuclear@13
|
78 for(size_t i=0; i<m->faces.size(); i++) {
|
nuclear@13
|
79 m->faces[i].matid = m->matid;
|
nuclear@13
|
80 }
|
nuclear@24
|
81
|
nuclear@24
|
82 try {
|
nuclear@24
|
83 meshes.push_back(m);
|
nuclear@24
|
84 }
|
nuclear@24
|
85 catch(...) {
|
nuclear@24
|
86 return false;
|
nuclear@24
|
87 }
|
nuclear@24
|
88
|
nuclear@24
|
89 // invalidate facebuffer and count
|
nuclear@24
|
90 delete [] facebuf;
|
nuclear@24
|
91 facebuf = 0;
|
nuclear@24
|
92 num_faces = -1;
|
nuclear@24
|
93
|
nuclear@13
|
94 return true;
|
nuclear@13
|
95 }
|
nuclear@13
|
96
|
nuclear@54
|
97 bool Scene::add_light(const Light <)
|
nuclear@54
|
98 {
|
nuclear@54
|
99 try {
|
nuclear@54
|
100 lights.push_back(lt);
|
nuclear@54
|
101 }
|
nuclear@54
|
102 catch(...) {
|
nuclear@54
|
103 return false;
|
nuclear@54
|
104 }
|
nuclear@54
|
105 return true;
|
nuclear@54
|
106 }
|
nuclear@54
|
107
|
John@14
|
108 int Scene::get_num_meshes() const
|
John@14
|
109 {
|
John@14
|
110 return (int)meshes.size();
|
John@14
|
111 }
|
John@14
|
112
|
nuclear@54
|
113 int Scene::get_num_lights() const
|
nuclear@54
|
114 {
|
nuclear@54
|
115 return (int)lights.size();
|
nuclear@54
|
116 }
|
nuclear@54
|
117
|
nuclear@13
|
118 int Scene::get_num_faces() const
|
nuclear@13
|
119 {
|
nuclear@24
|
120 if(num_faces >= 0) {
|
nuclear@24
|
121 return num_faces;
|
nuclear@24
|
122 }
|
nuclear@24
|
123
|
nuclear@24
|
124 num_faces = 0;
|
nuclear@13
|
125 for(size_t i=0; i<meshes.size(); i++) {
|
nuclear@13
|
126 num_faces += meshes[i]->faces.size();
|
nuclear@13
|
127 }
|
nuclear@13
|
128 return num_faces;
|
nuclear@13
|
129 }
|
nuclear@13
|
130
|
John@14
|
131 int Scene::get_num_materials() const
|
John@14
|
132 {
|
John@14
|
133 return (int)matlib.size();
|
John@14
|
134 }
|
John@14
|
135
|
nuclear@35
|
136 int Scene::get_num_kdnodes() const
|
nuclear@35
|
137 {
|
nuclear@35
|
138 return kdtree_nodes(kdtree);
|
nuclear@35
|
139 }
|
nuclear@35
|
140
|
nuclear@54
|
141 Mesh **Scene::get_meshes()
|
nuclear@54
|
142 {
|
nuclear@54
|
143 if(meshes.empty()) {
|
nuclear@54
|
144 return 0;
|
nuclear@54
|
145 }
|
nuclear@54
|
146 return &meshes[0];
|
nuclear@54
|
147 }
|
nuclear@54
|
148
|
nuclear@54
|
149 const Mesh * const *Scene::get_meshes() const
|
nuclear@54
|
150 {
|
nuclear@54
|
151 if(meshes.empty()) {
|
nuclear@54
|
152 return 0;
|
nuclear@54
|
153 }
|
nuclear@54
|
154 return &meshes[0];
|
nuclear@54
|
155 }
|
nuclear@54
|
156
|
nuclear@54
|
157 Light *Scene::get_lights()
|
nuclear@54
|
158 {
|
nuclear@54
|
159 if(lights.empty()) {
|
nuclear@54
|
160 return 0;
|
nuclear@54
|
161 }
|
nuclear@54
|
162 return &lights[0];
|
nuclear@54
|
163 }
|
nuclear@54
|
164
|
nuclear@54
|
165 const Light *Scene::get_lights() const
|
nuclear@54
|
166 {
|
nuclear@54
|
167 if(lights.empty()) {
|
nuclear@54
|
168 return 0;
|
nuclear@54
|
169 }
|
nuclear@54
|
170 return &lights[0];
|
nuclear@54
|
171 }
|
nuclear@54
|
172
|
John@14
|
173 Material *Scene::get_materials()
|
John@14
|
174 {
|
John@14
|
175 if(matlib.empty()) {
|
John@14
|
176 return 0;
|
John@14
|
177 }
|
John@14
|
178 return &matlib[0];
|
John@14
|
179 }
|
John@14
|
180
|
John@14
|
181 const Material *Scene::get_materials() const
|
John@14
|
182 {
|
John@14
|
183 if(matlib.empty()) {
|
John@14
|
184 return 0;
|
John@14
|
185 }
|
John@14
|
186 return &matlib[0];
|
John@14
|
187 }
|
nuclear@24
|
188
|
nuclear@24
|
189 const Face *Scene::get_face_buffer() const
|
nuclear@24
|
190 {
|
nuclear@24
|
191 if(facebuf) {
|
nuclear@24
|
192 return facebuf;
|
nuclear@24
|
193 }
|
nuclear@24
|
194
|
nuclear@24
|
195 int num_meshes = get_num_meshes();
|
nuclear@24
|
196
|
nuclear@24
|
197 printf("constructing face buffer with %d faces (out of %d meshes)\n", get_num_faces(), num_meshes);
|
nuclear@24
|
198 facebuf = new Face[num_faces];
|
nuclear@24
|
199 Face *fptr = facebuf;
|
nuclear@24
|
200
|
nuclear@24
|
201 for(int i=0; i<num_meshes; i++) {
|
nuclear@24
|
202 for(size_t j=0; j<meshes[i]->faces.size(); j++) {
|
nuclear@24
|
203 *fptr++ = meshes[i]->faces[j];
|
nuclear@24
|
204 }
|
nuclear@24
|
205 }
|
nuclear@24
|
206 return facebuf;
|
nuclear@24
|
207 }
|
nuclear@24
|
208
|
nuclear@28
|
209 const KDNodeGPU *Scene::get_kdtree_buffer() const
|
nuclear@28
|
210 {
|
nuclear@28
|
211 if(kdbuf) {
|
nuclear@28
|
212 return kdbuf;
|
nuclear@28
|
213 }
|
nuclear@28
|
214
|
nuclear@28
|
215 if(!kdtree) {
|
nuclear@28
|
216 ((Scene*)this)->build_kdtree();
|
nuclear@28
|
217 }
|
nuclear@28
|
218
|
nuclear@35
|
219 int num_nodes = get_num_kdnodes();
|
nuclear@35
|
220 kdbuf = new KDNodeGPU[num_nodes];
|
nuclear@35
|
221
|
nuclear@35
|
222 int count = 0;
|
nuclear@35
|
223
|
nuclear@35
|
224 // first arrange the kdnodes into an array (flatten)
|
nuclear@53
|
225 flatten_kdtree(kdtree, kdbuf, &count);
|
nuclear@35
|
226
|
nuclear@28
|
227 return kdbuf;
|
nuclear@28
|
228 }
|
nuclear@28
|
229
|
nuclear@53
|
230 static int flatten_kdtree(const KDNode *node, KDNodeGPU *kdbuf, int *count)
|
nuclear@28
|
231 {
|
nuclear@38
|
232 const size_t max_node_items = sizeof kdbuf[0].face_idx / sizeof kdbuf[0].face_idx[0];
|
nuclear@35
|
233 int idx = (*count)++;
|
nuclear@29
|
234
|
nuclear@35
|
235 // copy the node
|
nuclear@35
|
236 kdbuf[idx].aabb = node->aabb;
|
nuclear@38
|
237 kdbuf[idx].num_faces = 0;
|
nuclear@38
|
238
|
nuclear@35
|
239 for(size_t i=0; i<node->face_idx.size(); i++) {
|
nuclear@38
|
240 if(i >= max_node_items) {
|
nuclear@38
|
241 fprintf(stderr, "WARNING too many faces per leaf node!\n");
|
nuclear@38
|
242 break;
|
nuclear@38
|
243 }
|
nuclear@35
|
244 kdbuf[idx].face_idx[i] = node->face_idx[i];
|
nuclear@38
|
245 kdbuf[idx].num_faces++;
|
nuclear@28
|
246 }
|
nuclear@35
|
247
|
nuclear@35
|
248 // recurse to the left/right (if we're not in a leaf node)
|
nuclear@35
|
249 if(node->left) {
|
nuclear@35
|
250 assert(node->right);
|
nuclear@35
|
251
|
nuclear@53
|
252 kdbuf[idx].left = flatten_kdtree(node->left, kdbuf, count);
|
nuclear@53
|
253 kdbuf[idx].right = flatten_kdtree(node->right, kdbuf, count);
|
nuclear@53
|
254 } else {
|
nuclear@53
|
255 kdbuf[idx].left = kdbuf[idx].right = -1;
|
nuclear@35
|
256 }
|
nuclear@28
|
257
|
nuclear@53
|
258 return idx;
|
nuclear@29
|
259 }
|
nuclear@24
|
260
|
nuclear@27
|
261 void Scene::draw_kdtree() const
|
nuclear@27
|
262 {
|
nuclear@27
|
263 glPushAttrib(GL_ENABLE_BIT);
|
nuclear@27
|
264 glDisable(GL_LIGHTING);
|
nuclear@27
|
265 glDepthMask(0);
|
nuclear@27
|
266
|
nuclear@27
|
267 glBegin(GL_LINES);
|
nuclear@27
|
268 ::draw_kdtree(kdtree, 0);
|
nuclear@27
|
269 glEnd();
|
nuclear@27
|
270
|
nuclear@27
|
271 glDepthMask(1);
|
nuclear@27
|
272 glPopAttrib();
|
nuclear@27
|
273 }
|
nuclear@27
|
274
|
nuclear@27
|
275 static float palette[][3] = {
|
nuclear@27
|
276 {0, 1, 0},
|
nuclear@27
|
277 {1, 0, 0},
|
nuclear@27
|
278 {0, 0, 1},
|
nuclear@27
|
279 {1, 1, 0},
|
nuclear@27
|
280 {0, 0, 1},
|
nuclear@27
|
281 {1, 0, 1}
|
nuclear@27
|
282 };
|
nuclear@27
|
283 static int pal_size = sizeof palette / sizeof *palette;
|
nuclear@27
|
284
|
nuclear@27
|
285 static void draw_kdtree(const KDNode *node, int level)
|
nuclear@27
|
286 {
|
nuclear@27
|
287 if(!node) return;
|
nuclear@27
|
288
|
nuclear@27
|
289 draw_kdtree(node->left, level + 1);
|
nuclear@27
|
290 draw_kdtree(node->right, level + 1);
|
nuclear@27
|
291
|
nuclear@27
|
292 glColor3fv(palette[level % pal_size]);
|
nuclear@27
|
293
|
nuclear@27
|
294 glVertex3fv(node->aabb.min);
|
nuclear@27
|
295 glVertex3f(node->aabb.max[0], node->aabb.min[1], node->aabb.min[2]);
|
nuclear@27
|
296 glVertex3f(node->aabb.max[0], node->aabb.min[1], node->aabb.min[2]);
|
nuclear@27
|
297 glVertex3f(node->aabb.max[0], node->aabb.max[1], node->aabb.min[2]);
|
nuclear@27
|
298 glVertex3f(node->aabb.max[0], node->aabb.max[1], node->aabb.min[2]);
|
nuclear@27
|
299 glVertex3f(node->aabb.min[0], node->aabb.max[1], node->aabb.min[2]);
|
nuclear@27
|
300 glVertex3f(node->aabb.min[0], node->aabb.max[1], node->aabb.min[2]);
|
nuclear@27
|
301 glVertex3fv(node->aabb.min);
|
nuclear@27
|
302
|
nuclear@27
|
303 glVertex3f(node->aabb.min[0], node->aabb.min[1], node->aabb.max[2]);
|
nuclear@27
|
304 glVertex3f(node->aabb.max[0], node->aabb.min[1], node->aabb.max[2]);
|
nuclear@27
|
305 glVertex3f(node->aabb.max[0], node->aabb.min[1], node->aabb.max[2]);
|
nuclear@27
|
306 glVertex3fv(node->aabb.max);
|
nuclear@27
|
307 glVertex3fv(node->aabb.max);
|
nuclear@27
|
308 glVertex3f(node->aabb.min[0], node->aabb.max[1], node->aabb.max[2]);
|
nuclear@27
|
309 glVertex3f(node->aabb.min[0], node->aabb.max[1], node->aabb.max[2]);
|
nuclear@27
|
310 glVertex3f(node->aabb.min[0], node->aabb.min[1], node->aabb.max[2]);
|
nuclear@27
|
311
|
nuclear@27
|
312 glVertex3fv(node->aabb.min);
|
nuclear@27
|
313 glVertex3f(node->aabb.min[0], node->aabb.min[1], node->aabb.max[2]);
|
nuclear@27
|
314 glVertex3f(node->aabb.max[0], node->aabb.min[1], node->aabb.min[2]);
|
nuclear@27
|
315 glVertex3f(node->aabb.max[0], node->aabb.min[1], node->aabb.max[2]);
|
nuclear@27
|
316 glVertex3f(node->aabb.max[0], node->aabb.max[1], node->aabb.min[2]);
|
nuclear@27
|
317 glVertex3fv(node->aabb.max);
|
nuclear@27
|
318 glVertex3f(node->aabb.min[0], node->aabb.max[1], node->aabb.min[2]);
|
nuclear@27
|
319 glVertex3f(node->aabb.min[0], node->aabb.max[1], node->aabb.max[2]);
|
nuclear@27
|
320 }
|
nuclear@27
|
321
|
nuclear@27
|
322 bool Scene::build_kdtree()
|
nuclear@24
|
323 {
|
nuclear@29
|
324 assert(kdtree == 0);
|
nuclear@29
|
325
|
nuclear@24
|
326 const Face *faces = get_face_buffer();
|
nuclear@24
|
327 int num_faces = get_num_faces();
|
nuclear@24
|
328
|
nuclear@25
|
329 printf("Constructing kd-tree out of %d faces ...\n", num_faces);
|
nuclear@25
|
330
|
nuclear@27
|
331 int icost = accel_param[ACCEL_PARAM_COST_INTERSECT];
|
nuclear@27
|
332 int tcost = accel_param[ACCEL_PARAM_COST_TRAVERSE];
|
nuclear@27
|
333 printf(" max items per leaf: %d\n", accel_param[ACCEL_PARAM_MAX_NODE_ITEMS]);
|
nuclear@27
|
334 printf(" SAH parameters - tcost: %d - icost: %d\n", tcost, icost);
|
nuclear@27
|
335
|
nuclear@25
|
336 free_kdtree(kdtree);
|
nuclear@25
|
337 kdtree = new KDNode;
|
nuclear@25
|
338
|
nuclear@25
|
339 /* Start the construction of the kdtree by adding all faces of the scene
|
nuclear@25
|
340 * to the new root node. At the same time calculate the root's AABB.
|
nuclear@25
|
341 */
|
nuclear@25
|
342 kdtree->aabb.min[0] = kdtree->aabb.min[1] = kdtree->aabb.min[2] = FLT_MAX;
|
nuclear@25
|
343 kdtree->aabb.max[0] = kdtree->aabb.max[1] = kdtree->aabb.max[2] = -FLT_MAX;
|
nuclear@25
|
344
|
nuclear@24
|
345 for(int i=0; i<num_faces; i++) {
|
nuclear@25
|
346 const Face *face = faces + i;
|
nuclear@25
|
347
|
nuclear@25
|
348 // for each vertex of the face ...
|
nuclear@25
|
349 for(int j=0; j<3; j++) {
|
nuclear@25
|
350 const float *pos = face->v[j].pos;
|
nuclear@25
|
351
|
nuclear@25
|
352 // for each element (xyz) of the position vector ...
|
nuclear@25
|
353 for(int k=0; k<3; k++) {
|
nuclear@25
|
354 if(pos[k] < kdtree->aabb.min[k]) {
|
nuclear@25
|
355 kdtree->aabb.min[k] = pos[k];
|
nuclear@25
|
356 }
|
nuclear@25
|
357 if(pos[k] > kdtree->aabb.max[k]) {
|
nuclear@25
|
358 kdtree->aabb.max[k] = pos[k];
|
nuclear@25
|
359 }
|
nuclear@25
|
360 }
|
nuclear@25
|
361 }
|
nuclear@25
|
362
|
nuclear@32
|
363 kdtree->face_idx.push_back(i); // add the face
|
nuclear@24
|
364 }
|
nuclear@24
|
365
|
nuclear@38
|
366 CHECK_AABB(kdtree->aabb);
|
nuclear@38
|
367
|
nuclear@26
|
368 // calculate the heuristic for the root
|
nuclear@32
|
369 kdtree->cost = eval_cost(faces, &kdtree->face_idx[0], kdtree->face_idx.size(), kdtree->aabb, 0);
|
nuclear@26
|
370
|
nuclear@25
|
371 // now proceed splitting the root recursively
|
nuclear@32
|
372 if(!::build_kdtree(kdtree, faces)) {
|
nuclear@27
|
373 fprintf(stderr, "failed to build kdtree\n");
|
nuclear@27
|
374 return false;
|
nuclear@27
|
375 }
|
nuclear@27
|
376
|
nuclear@27
|
377 printf(" tree depth: %d\n", kdtree_depth(kdtree));
|
nuclear@27
|
378 print_item_counts(kdtree, 0);
|
nuclear@27
|
379 return true;
|
nuclear@24
|
380 }
|
nuclear@24
|
381
|
nuclear@37
|
382 struct Split {
|
nuclear@37
|
383 int axis;
|
nuclear@37
|
384 float pos;
|
nuclear@37
|
385 float sum_cost;
|
nuclear@37
|
386 float cost_left, cost_right;
|
nuclear@37
|
387 };
|
nuclear@37
|
388
|
nuclear@37
|
389 static void find_best_split(const KDNode *node, int axis, const Face *faces, Split *split)
|
nuclear@37
|
390 {
|
nuclear@37
|
391 Split best_split;
|
nuclear@37
|
392 best_split.sum_cost = FLT_MAX;
|
nuclear@37
|
393
|
nuclear@37
|
394 for(size_t i=0; i<node->face_idx.size(); i++) {
|
nuclear@37
|
395 const Face *face = faces + node->face_idx[i];
|
nuclear@37
|
396
|
nuclear@37
|
397 float splitpt[2];
|
nuclear@37
|
398 splitpt[0] = MIN(face->v[0].pos[axis], MIN(face->v[1].pos[axis], face->v[2].pos[axis]));
|
nuclear@37
|
399 splitpt[1] = MAX(face->v[0].pos[axis], MAX(face->v[1].pos[axis], face->v[2].pos[axis]));
|
nuclear@37
|
400
|
nuclear@37
|
401 for(int j=0; j<2; j++) {
|
nuclear@38
|
402 if(splitpt[j] <= node->aabb.min[axis] || splitpt[j] >= node->aabb.max[axis]) {
|
nuclear@38
|
403 continue;
|
nuclear@38
|
404 }
|
nuclear@38
|
405
|
nuclear@37
|
406 AABBox aabb_left, aabb_right;
|
nuclear@37
|
407 aabb_left = aabb_right = node->aabb;
|
nuclear@37
|
408 aabb_left.max[axis] = splitpt[j];
|
nuclear@37
|
409 aabb_right.min[axis] = splitpt[j];
|
nuclear@37
|
410
|
nuclear@37
|
411 float left_cost = eval_cost(faces, &node->face_idx[0], node->face_idx.size(), aabb_left, axis);
|
nuclear@37
|
412 float right_cost = eval_cost(faces, &node->face_idx[0], node->face_idx.size(), aabb_right, axis);
|
nuclear@37
|
413 float sum_cost = left_cost + right_cost - accel_param[ACCEL_PARAM_COST_TRAVERSE]; // tcost is added twice
|
nuclear@37
|
414
|
nuclear@37
|
415 if(sum_cost < best_split.sum_cost) {
|
nuclear@37
|
416 best_split.cost_left = left_cost;
|
nuclear@37
|
417 best_split.cost_right = right_cost;
|
nuclear@37
|
418 best_split.sum_cost = sum_cost;
|
nuclear@37
|
419 best_split.pos = splitpt[j];
|
nuclear@37
|
420 }
|
nuclear@37
|
421 }
|
nuclear@37
|
422 }
|
nuclear@37
|
423
|
nuclear@37
|
424 assert(split);
|
nuclear@37
|
425 *split = best_split;
|
nuclear@37
|
426 split->axis = axis;
|
nuclear@37
|
427 }
|
nuclear@37
|
428
|
nuclear@32
|
429 static bool build_kdtree(KDNode *kd, const Face *faces, int level)
|
nuclear@24
|
430 {
|
nuclear@28
|
431 int opt_max_depth = accel_param[ACCEL_PARAM_MAX_TREE_DEPTH];
|
nuclear@26
|
432 int opt_max_items = accel_param[ACCEL_PARAM_MAX_NODE_ITEMS];
|
nuclear@27
|
433
|
nuclear@32
|
434 if(kd->face_idx.empty() || level >= opt_max_depth) {
|
nuclear@27
|
435 return true;
|
nuclear@25
|
436 }
|
nuclear@25
|
437
|
nuclear@37
|
438 Split best_split;
|
nuclear@38
|
439 best_split.axis = -1;
|
nuclear@37
|
440 best_split.sum_cost = FLT_MAX;
|
nuclear@26
|
441
|
nuclear@38
|
442 for(int i=0; i<3; i++) {
|
nuclear@37
|
443 Split split;
|
nuclear@37
|
444 find_best_split(kd, i, faces, &split);
|
nuclear@26
|
445
|
nuclear@37
|
446 if(split.sum_cost < best_split.sum_cost) {
|
nuclear@37
|
447 best_split = split;
|
nuclear@26
|
448 }
|
nuclear@26
|
449 }
|
nuclear@26
|
450
|
nuclear@38
|
451 if(best_split.axis == -1) {
|
nuclear@38
|
452 return true; // can't split any more, only 0-area splits available
|
nuclear@38
|
453 }
|
nuclear@37
|
454
|
nuclear@29
|
455 //printf("current cost: %f, best_cost: %f\n", kd->cost, best_sum_cost);
|
nuclear@37
|
456 if(best_split.sum_cost > kd->cost && (opt_max_items == 0 || (int)kd->face_idx.size() <= opt_max_items)) {
|
nuclear@27
|
457 return true; // stop splitting if it doesn't reduce the cost
|
nuclear@26
|
458 }
|
nuclear@26
|
459
|
nuclear@38
|
460 kd->axis = best_split.axis;
|
nuclear@38
|
461
|
nuclear@26
|
462 // create the two children
|
nuclear@26
|
463 KDNode *kdleft, *kdright;
|
nuclear@26
|
464 kdleft = new KDNode;
|
nuclear@26
|
465 kdright = new KDNode;
|
nuclear@26
|
466
|
nuclear@26
|
467 kdleft->aabb = kdright->aabb = kd->aabb;
|
nuclear@26
|
468
|
nuclear@37
|
469 kdleft->aabb.max[kd->axis] = best_split.pos;
|
nuclear@37
|
470 kdright->aabb.min[kd->axis] = best_split.pos;
|
nuclear@26
|
471
|
nuclear@37
|
472 kdleft->cost = best_split.cost_left;
|
nuclear@37
|
473 kdright->cost = best_split.cost_right;
|
nuclear@26
|
474
|
nuclear@34
|
475 // TODO would it be much better if we actually split faces that straddle the splitting plane?
|
nuclear@32
|
476 for(size_t i=0; i<kd->face_idx.size(); i++) {
|
nuclear@32
|
477 int fidx = kd->face_idx[i];
|
nuclear@32
|
478 const Face *face = faces + fidx;
|
nuclear@26
|
479
|
nuclear@37
|
480 if(face->v[0].pos[kd->axis] < best_split.pos ||
|
nuclear@37
|
481 face->v[1].pos[kd->axis] < best_split.pos ||
|
nuclear@37
|
482 face->v[2].pos[kd->axis] < best_split.pos) {
|
nuclear@32
|
483 kdleft->face_idx.push_back(fidx);
|
nuclear@26
|
484 }
|
nuclear@37
|
485 if(face->v[0].pos[kd->axis] >= best_split.pos ||
|
nuclear@37
|
486 face->v[1].pos[kd->axis] >= best_split.pos ||
|
nuclear@37
|
487 face->v[2].pos[kd->axis] >= best_split.pos) {
|
nuclear@32
|
488 kdright->face_idx.push_back(fidx);
|
nuclear@26
|
489 }
|
nuclear@26
|
490 }
|
nuclear@32
|
491 kd->face_idx.clear(); // only leaves have faces
|
nuclear@26
|
492
|
nuclear@26
|
493 kd->left = kdleft;
|
nuclear@26
|
494 kd->right = kdright;
|
nuclear@27
|
495
|
nuclear@32
|
496 return build_kdtree(kd->left, faces, level + 1) && build_kdtree(kd->right, faces, level + 1);
|
nuclear@26
|
497 }
|
nuclear@26
|
498
|
nuclear@32
|
499 static float eval_cost(const Face *faces, const int *face_idx, int num_faces, const AABBox &aabb, int axis)
|
nuclear@26
|
500 {
|
nuclear@26
|
501 int num_inside = 0;
|
nuclear@26
|
502 int tcost = accel_param[ACCEL_PARAM_COST_TRAVERSE];
|
nuclear@26
|
503 int icost = accel_param[ACCEL_PARAM_COST_INTERSECT];
|
nuclear@26
|
504
|
nuclear@32
|
505 for(int i=0; i<num_faces; i++) {
|
nuclear@32
|
506 const Face *face = faces + face_idx[i];
|
nuclear@26
|
507
|
nuclear@32
|
508 for(int j=0; j<3; j++) {
|
nuclear@32
|
509 if(face->v[j].pos[axis] >= aabb.min[axis] && face->v[j].pos[axis] < aabb.max[axis]) {
|
nuclear@26
|
510 num_inside++;
|
nuclear@26
|
511 break;
|
nuclear@26
|
512 }
|
nuclear@26
|
513 }
|
nuclear@26
|
514 }
|
nuclear@26
|
515
|
nuclear@38
|
516 float dx = aabb.max[0] - aabb.min[0];
|
nuclear@38
|
517 float dy = aabb.max[1] - aabb.min[1];
|
nuclear@38
|
518 float dz = aabb.max[2] - aabb.min[2];
|
nuclear@38
|
519
|
nuclear@38
|
520 if(dx < 0.0) {
|
nuclear@38
|
521 fprintf(stderr, "FOO DX = %f\n", dx);
|
nuclear@38
|
522 abort();
|
nuclear@38
|
523 }
|
nuclear@38
|
524 if(dy < 0.0) {
|
nuclear@38
|
525 fprintf(stderr, "FOO DX = %f\n", dy);
|
nuclear@38
|
526 abort();
|
nuclear@38
|
527 }
|
nuclear@38
|
528 if(dz < 0.0) {
|
nuclear@38
|
529 fprintf(stderr, "FOO DX = %f\n", dz);
|
nuclear@38
|
530 abort();
|
nuclear@38
|
531 }
|
nuclear@38
|
532
|
nuclear@38
|
533 if(dx < 1e-6 || dy < 1e-6 || dz < 1e-6) {
|
nuclear@27
|
534 return FLT_MAX; // heavily penalize 0-area voxels
|
nuclear@27
|
535 }
|
nuclear@27
|
536
|
nuclear@38
|
537 float sarea = 2.0 * (dx + dy + dz);//aabb.calc_surface_area();
|
nuclear@32
|
538 return tcost + sarea * num_inside * icost;
|
nuclear@24
|
539 }
|
nuclear@25
|
540
|
nuclear@25
|
541 static void free_kdtree(KDNode *node)
|
nuclear@25
|
542 {
|
nuclear@25
|
543 if(node) {
|
nuclear@25
|
544 free_kdtree(node->left);
|
nuclear@25
|
545 free_kdtree(node->right);
|
nuclear@25
|
546 delete node;
|
nuclear@25
|
547 }
|
nuclear@25
|
548 }
|
nuclear@27
|
549
|
nuclear@28
|
550 int kdtree_depth(const KDNode *node)
|
nuclear@27
|
551 {
|
nuclear@27
|
552 if(!node) return 0;
|
nuclear@27
|
553
|
nuclear@27
|
554 int left = kdtree_depth(node->left);
|
nuclear@27
|
555 int right = kdtree_depth(node->right);
|
nuclear@27
|
556 return (left > right ? left : right) + 1;
|
nuclear@27
|
557 }
|
nuclear@27
|
558
|
nuclear@28
|
559 int kdtree_nodes(const KDNode *node)
|
nuclear@28
|
560 {
|
nuclear@28
|
561 if(!node) return 0;
|
nuclear@28
|
562 return kdtree_nodes(node->left) + kdtree_nodes(node->right) + 1;
|
nuclear@28
|
563 }
|
nuclear@28
|
564
|
nuclear@27
|
565 static void print_item_counts(const KDNode *node, int level)
|
nuclear@27
|
566 {
|
nuclear@27
|
567 if(!node) return;
|
nuclear@27
|
568
|
nuclear@30
|
569 for(int i=0; i<level; i++) {
|
nuclear@27
|
570 fputs(" ", stdout);
|
nuclear@27
|
571 }
|
nuclear@32
|
572 printf("- %d (cost: %f)\n", (int)node->face_idx.size(), node->cost);
|
nuclear@27
|
573
|
nuclear@27
|
574 print_item_counts(node->left, level + 1);
|
nuclear@27
|
575 print_item_counts(node->right, level + 1);
|
nuclear@27
|
576 }
|
nuclear@59
|
577
|
nuclear@59
|
578 #define SGN(x) ((x) >= 0 ? 1 : -1)
|
nuclear@59
|
579 #define INSIDE(x) (SGN((x) - (splitpos)) == sign)
|
nuclear@59
|
580 #define OUTSIDE(x) (!INSIDE(x))
|
nuclear@59
|
581
|
nuclear@59
|
582 #define LERPV3(res, a, b, t) \
|
nuclear@58
|
583 do { \
|
nuclear@59
|
584 (res)[0] = (a)[0] + ((b)[0] - (a)[0]) * (t); \
|
nuclear@59
|
585 (res)[1] = (a)[1] + ((b)[1] - (a)[1]) * (t); \
|
nuclear@59
|
586 (res)[2] = (a)[2] + ((b)[2] - (a)[2]) * (t); \
|
nuclear@58
|
587 } while(0)
|
nuclear@58
|
588
|
nuclear@59
|
589 #define NORMALIZE(v) \
|
nuclear@59
|
590 do { \
|
nuclear@59
|
591 float mag = (float)sqrt((v)[0] * (v)[0] + (v)[1] * (v)[1] + (v)[2] * (v)[2]); \
|
nuclear@59
|
592 (v)[0] /= mag; \
|
nuclear@59
|
593 (v)[1] /= mag; \
|
nuclear@59
|
594 (v)[2] /= mag; \
|
nuclear@59
|
595 } while(0)
|
nuclear@59
|
596
|
nuclear@59
|
597 static int clip_face(const Face &inface, float splitpos, int axis, int sign, Face *faces)
|
nuclear@58
|
598 {
|
nuclear@58
|
599 assert(axis >= 0 && axis < 3);
|
nuclear@58
|
600
|
nuclear@58
|
601 std::vector<Vertex> verts;
|
nuclear@59
|
602 bool clipped = false;
|
nuclear@58
|
603
|
nuclear@58
|
604 for(int i=0; i<3; i++) {
|
nuclear@59
|
605 const Vertex *vstart = inface.v + i;
|
nuclear@59
|
606 const Vertex *vend = inface.v + ((i + 1) % 3);
|
nuclear@58
|
607
|
nuclear@59
|
608 float start = vstart->pos[axis];
|
nuclear@59
|
609 float end = vend->pos[axis];
|
nuclear@58
|
610
|
nuclear@59
|
611 if(OUTSIDE(start) && INSIDE(end)) {
|
nuclear@59
|
612 float t = (splitpos - start) / (end - start);
|
nuclear@58
|
613
|
nuclear@59
|
614 Vertex newv;
|
nuclear@59
|
615 memset(&newv, 0, sizeof newv);
|
nuclear@59
|
616 LERPV3(newv.pos, vstart->pos, vend->pos, t);
|
nuclear@59
|
617 LERPV3(newv.normal, vstart->normal, vend->normal, t);
|
nuclear@59
|
618 LERPV3(newv.tex, vstart->tex, vend->tex, t);
|
nuclear@59
|
619 NORMALIZE(newv.normal);
|
nuclear@59
|
620
|
nuclear@59
|
621 verts.push_back(newv);
|
nuclear@59
|
622 clipped = true;
|
nuclear@59
|
623
|
nuclear@59
|
624 } else if(INSIDE(start) && INSIDE(end)) {
|
nuclear@59
|
625 verts.push_back(inface.v[i]);
|
nuclear@59
|
626 } else if(INSIDE(start) && OUTSIDE(end)) {
|
nuclear@59
|
627 verts.push_back(inface.v[i]);
|
nuclear@59
|
628
|
nuclear@59
|
629 float t = (splitpos - start) / (end - start);
|
nuclear@59
|
630
|
nuclear@59
|
631 Vertex newv;
|
nuclear@59
|
632 memset(&newv, 0, sizeof newv);
|
nuclear@59
|
633 LERPV3(newv.pos, vstart->pos, vend->pos, t);
|
nuclear@59
|
634 LERPV3(newv.normal, vstart->normal, vend->normal, t);
|
nuclear@59
|
635 LERPV3(newv.tex, vstart->tex, vend->tex, t);
|
nuclear@59
|
636 NORMALIZE(newv.normal);
|
nuclear@59
|
637
|
nuclear@59
|
638 verts.push_back(newv);
|
nuclear@59
|
639 clipped = true;
|
nuclear@58
|
640 }
|
nuclear@58
|
641 }
|
nuclear@59
|
642
|
nuclear@59
|
643 if(!clipped) {
|
nuclear@59
|
644 return 0;
|
nuclear@59
|
645 }
|
nuclear@59
|
646
|
nuclear@59
|
647 assert(verts.size() < 5);
|
nuclear@59
|
648 bool quad = verts.size() > 3;
|
nuclear@59
|
649
|
nuclear@59
|
650 if(!quad) {
|
nuclear@59
|
651 faces[0] = inface;
|
nuclear@59
|
652 faces[0].v[0] = verts[0];
|
nuclear@59
|
653 faces[0].v[1] = verts[1];
|
nuclear@59
|
654 faces[0].v[2] = verts[2];
|
nuclear@59
|
655 return 1;
|
nuclear@59
|
656 }
|
nuclear@59
|
657
|
nuclear@59
|
658 /* calculate triangle areas for both possible splits and pick the one
|
nuclear@59
|
659 * with the smallest absolute difference to avoid slivers.
|
nuclear@59
|
660 */
|
nuclear@59
|
661 float area1, area2;
|
nuclear@59
|
662
|
nuclear@59
|
663 area1 = calc_sq_area(verts[0].pos, verts[1].pos, verts[2].pos);
|
nuclear@59
|
664 area2 = calc_sq_area(verts[0].pos, verts[2].pos, verts[3].pos);
|
nuclear@59
|
665 float s1diff = fabs(area1 - area2);
|
nuclear@59
|
666
|
nuclear@59
|
667 area1 = calc_sq_area(verts[0].pos, verts[1].pos, verts[3].pos);
|
nuclear@59
|
668 area2 = calc_sq_area(verts[1].pos, verts[2].pos, verts[3].pos);
|
nuclear@59
|
669 float s2diff = fabs(area1 - area2);
|
nuclear@59
|
670
|
nuclear@59
|
671 faces[0] = faces[1] = inface;
|
nuclear@59
|
672 if(s1diff < s2diff) {
|
nuclear@59
|
673 faces[0].v[0] = verts[0];
|
nuclear@59
|
674 faces[0].v[1] = verts[1];
|
nuclear@59
|
675 faces[0].v[2] = verts[2];
|
nuclear@59
|
676 faces[1].v[0] = verts[0];
|
nuclear@59
|
677 faces[1].v[1] = verts[2];
|
nuclear@59
|
678 faces[1].v[2] = verts[3];
|
nuclear@59
|
679 } else {
|
nuclear@59
|
680 faces[0].v[0] = verts[0];
|
nuclear@59
|
681 faces[0].v[1] = verts[1];
|
nuclear@59
|
682 faces[0].v[2] = verts[3];
|
nuclear@59
|
683 faces[1].v[0] = verts[1];
|
nuclear@59
|
684 faces[1].v[1] = verts[2];
|
nuclear@59
|
685 faces[1].v[2] = verts[3];
|
nuclear@59
|
686 }
|
nuclear@59
|
687 return 2;
|
nuclear@59
|
688 }
|
nuclear@59
|
689
|
nuclear@59
|
690 static float calc_sq_area(const Vector3 &a, const Vector3 &b, const Vector3 &c)
|
nuclear@59
|
691 {
|
nuclear@59
|
692 Vector3 v1 = b - a;
|
nuclear@59
|
693 Vector3 v2 = c - a;
|
nuclear@59
|
694 return cross(v1, v2).lengthsq();
|
nuclear@59
|
695 }
|