Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * The Original Code is Copyright (C) 2009 Blender Foundation. 00019 * All rights reserved. 00020 * 00021 * The Original Code is: all of this file. 00022 * 00023 * Contributor(s): André Pinto. 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 */ 00027 00033 #include <assert.h> 00034 #include <math.h> 00035 #include <stdlib.h> 00036 #include <algorithm> 00037 00038 #include "rayobject_rtbuild.h" 00039 00040 #include "MEM_guardedalloc.h" 00041 00042 #include "BLI_math.h" 00043 #include "BLI_utildefines.h" 00044 00045 static bool selected_node(RTBuilder::Object *node) 00046 { 00047 return node->selected; 00048 } 00049 00050 static void rtbuild_init(RTBuilder *b) 00051 { 00052 b->split_axis = -1; 00053 b->primitives.begin = 0; 00054 b->primitives.end = 0; 00055 b->primitives.maxsize = 0; 00056 00057 for(int i=0; i<RTBUILD_MAX_CHILDS; i++) 00058 b->child_offset[i] = 0; 00059 00060 for(int i=0; i<3; i++) 00061 b->sorted_begin[i] = b->sorted_end[i] = 0; 00062 00063 INIT_MINMAX(b->bb, b->bb+3); 00064 } 00065 00066 RTBuilder* rtbuild_create(int size) 00067 { 00068 RTBuilder *builder = (RTBuilder*) MEM_mallocN( sizeof(RTBuilder), "RTBuilder" ); 00069 RTBuilder::Object *memblock= (RTBuilder::Object*)MEM_mallocN( sizeof(RTBuilder::Object)*size,"RTBuilder.objects"); 00070 00071 00072 rtbuild_init(builder); 00073 00074 builder->primitives.begin = builder->primitives.end = memblock; 00075 builder->primitives.maxsize = size; 00076 00077 for(int i=0; i<3; i++) 00078 { 00079 builder->sorted_begin[i] = (RTBuilder::Object**)MEM_mallocN( sizeof(RTBuilder::Object*)*size,"RTBuilder.sorted_objects"); 00080 builder->sorted_end[i] = builder->sorted_begin[i]; 00081 } 00082 00083 00084 return builder; 00085 } 00086 00087 void rtbuild_free(RTBuilder *b) 00088 { 00089 if(b->primitives.begin) MEM_freeN(b->primitives.begin); 00090 00091 for(int i=0; i<3; i++) 00092 if(b->sorted_begin[i]) 00093 MEM_freeN(b->sorted_begin[i]); 00094 00095 MEM_freeN(b); 00096 } 00097 00098 void rtbuild_add(RTBuilder *b, RayObject *o) 00099 { 00100 float bb[6]; 00101 00102 assert( b->primitives.begin + b->primitives.maxsize != b->primitives.end ); 00103 00104 INIT_MINMAX(bb, bb+3); 00105 RE_rayobject_merge_bb(o, bb, bb+3); 00106 00107 /* skip objects with invalid bounding boxes, nan causes DO_MINMAX 00108 to do nothing, so we get these invalid values. this shouldn't 00109 happen usually, but bugs earlier in the pipeline can cause it. */ 00110 if(bb[0] > bb[3] || bb[1] > bb[4] || bb[2] > bb[5]) 00111 return; 00112 /* skip objects with inf bounding boxes */ 00113 if(!finite(bb[0]) || !finite(bb[1]) || !finite(bb[2])) 00114 return; 00115 if(!finite(bb[3]) || !finite(bb[4]) || !finite(bb[5])) 00116 return; 00117 /* skip objects with zero bounding box, they are of no use, and 00118 will give problems in rtbuild_heuristic_object_split later */ 00119 if(bb[0] == bb[3] && bb[1] == bb[4] && bb[2] == bb[5]) 00120 return; 00121 00122 copy_v3_v3(b->primitives.end->bb, bb); 00123 copy_v3_v3(b->primitives.end->bb+3, bb+3); 00124 b->primitives.end->obj = o; 00125 b->primitives.end->cost = RE_rayobject_cost(o); 00126 00127 for(int i=0; i<3; i++) 00128 { 00129 *(b->sorted_end[i]) = b->primitives.end; 00130 b->sorted_end[i]++; 00131 } 00132 b->primitives.end++; 00133 } 00134 00135 int rtbuild_size(RTBuilder *b) 00136 { 00137 return b->sorted_end[0] - b->sorted_begin[0]; 00138 } 00139 00140 00141 template<class Obj,int Axis> 00142 static bool obj_bb_compare(const Obj &a, const Obj &b) 00143 { 00144 if(a->bb[Axis] != b->bb[Axis]) 00145 return a->bb[Axis] < b->bb[Axis]; 00146 return a->obj < b->obj; 00147 } 00148 00149 template<class Item> 00150 static void object_sort(Item *begin, Item *end, int axis) 00151 { 00152 if(axis == 0) return std::sort(begin, end, obj_bb_compare<Item,0> ); 00153 if(axis == 1) return std::sort(begin, end, obj_bb_compare<Item,1> ); 00154 if(axis == 2) return std::sort(begin, end, obj_bb_compare<Item,2> ); 00155 assert(false); 00156 } 00157 00158 void rtbuild_done(RTBuilder *b, RayObjectControl* ctrl) 00159 { 00160 for(int i=0; i<3; i++) 00161 if(b->sorted_begin[i]) 00162 { 00163 if(RE_rayobjectcontrol_test_break(ctrl)) break; 00164 object_sort( b->sorted_begin[i], b->sorted_end[i], i ); 00165 } 00166 } 00167 00168 RayObject* rtbuild_get_primitive(RTBuilder *b, int index) 00169 { 00170 return b->sorted_begin[0][index]->obj; 00171 } 00172 00173 RTBuilder* rtbuild_get_child(RTBuilder *b, int child, RTBuilder *tmp) 00174 { 00175 rtbuild_init( tmp ); 00176 00177 for(int i=0; i<3; i++) 00178 if(b->sorted_begin[i]) 00179 { 00180 tmp->sorted_begin[i] = b->sorted_begin[i] + b->child_offset[child ]; 00181 tmp->sorted_end [i] = b->sorted_begin[i] + b->child_offset[child+1]; 00182 } 00183 else 00184 { 00185 tmp->sorted_begin[i] = 0; 00186 tmp->sorted_end [i] = 0; 00187 } 00188 00189 return tmp; 00190 } 00191 00192 void rtbuild_calc_bb(RTBuilder *b) 00193 { 00194 if(b->bb[0] == 1.0e30f) 00195 { 00196 for(RTBuilder::Object **index = b->sorted_begin[0]; index != b->sorted_end[0]; index++) 00197 RE_rayobject_merge_bb( (*index)->obj , b->bb, b->bb+3); 00198 } 00199 } 00200 00201 void rtbuild_merge_bb(RTBuilder *b, float *min, float *max) 00202 { 00203 rtbuild_calc_bb(b); 00204 DO_MIN(b->bb, min); 00205 DO_MAX(b->bb+3, max); 00206 } 00207 00208 /* 00209 int rtbuild_get_largest_axis(RTBuilder *b) 00210 { 00211 rtbuild_calc_bb(b); 00212 return bb_largest_axis(b->bb, b->bb+3); 00213 } 00214 00215 //Left balanced tree 00216 int rtbuild_mean_split(RTBuilder *b, int nchilds, int axis) 00217 { 00218 int i; 00219 int mleafs_per_child, Mleafs_per_child; 00220 int tot_leafs = rtbuild_size(b); 00221 int missing_leafs; 00222 00223 long long s; 00224 00225 assert(nchilds <= RTBUILD_MAX_CHILDS); 00226 00227 //TODO optimize calc of leafs_per_child 00228 for(s=nchilds; s<tot_leafs; s*=nchilds); 00229 Mleafs_per_child = s/nchilds; 00230 mleafs_per_child = Mleafs_per_child/nchilds; 00231 00232 //split min leafs per child 00233 b->child_offset[0] = 0; 00234 for(i=1; i<=nchilds; i++) 00235 b->child_offset[i] = mleafs_per_child; 00236 00237 //split remaining leafs 00238 missing_leafs = tot_leafs - mleafs_per_child*nchilds; 00239 for(i=1; i<=nchilds; i++) 00240 { 00241 if(missing_leafs > Mleafs_per_child - mleafs_per_child) 00242 { 00243 b->child_offset[i] += Mleafs_per_child - mleafs_per_child; 00244 missing_leafs -= Mleafs_per_child - mleafs_per_child; 00245 } 00246 else 00247 { 00248 b->child_offset[i] += missing_leafs; 00249 missing_leafs = 0; 00250 break; 00251 } 00252 } 00253 00254 //adjust for accumulative offsets 00255 for(i=1; i<=nchilds; i++) 00256 b->child_offset[i] += b->child_offset[i-1]; 00257 00258 //Count created childs 00259 for(i=nchilds; b->child_offset[i] == b->child_offset[i-1]; i--); 00260 split_leafs(b, b->child_offset, i, axis); 00261 00262 assert( b->child_offset[0] == 0 && b->child_offset[i] == tot_leafs ); 00263 return i; 00264 } 00265 00266 00267 int rtbuild_mean_split_largest_axis(RTBuilder *b, int nchilds) 00268 { 00269 int axis = rtbuild_get_largest_axis(b); 00270 return rtbuild_mean_split(b, nchilds, axis); 00271 } 00272 */ 00273 00274 /* 00275 * "separators" is an array of dim NCHILDS-1 00276 * and indicates where to cut the childs 00277 */ 00278 /* 00279 int rtbuild_median_split(RTBuilder *b, float *separators, int nchilds, int axis) 00280 { 00281 int size = rtbuild_size(b); 00282 00283 assert(nchilds <= RTBUILD_MAX_CHILDS); 00284 if(size <= nchilds) 00285 { 00286 return rtbuild_mean_split(b, nchilds, axis); 00287 } 00288 else 00289 { 00290 int i; 00291 00292 b->split_axis = axis; 00293 00294 //Calculate child offsets 00295 b->child_offset[0] = 0; 00296 for(i=0; i<nchilds-1; i++) 00297 b->child_offset[i+1] = split_leafs_by_plane(b, b->child_offset[i], size, separators[i]); 00298 b->child_offset[nchilds] = size; 00299 00300 for(i=0; i<nchilds; i++) 00301 if(b->child_offset[i+1] - b->child_offset[i] == size) 00302 return rtbuild_mean_split(b, nchilds, axis); 00303 00304 return nchilds; 00305 } 00306 } 00307 00308 int rtbuild_median_split_largest_axis(RTBuilder *b, int nchilds) 00309 { 00310 int la, i; 00311 float separators[RTBUILD_MAX_CHILDS]; 00312 00313 rtbuild_calc_bb(b); 00314 00315 la = bb_largest_axis(b->bb,b->bb+3); 00316 for(i=1; i<nchilds; i++) 00317 separators[i-1] = (b->bb[la+3]-b->bb[la])*i / nchilds; 00318 00319 return rtbuild_median_split(b, separators, nchilds, la); 00320 } 00321 */ 00322 00323 //Heuristics Object Splitter 00324 00325 00326 struct SweepCost 00327 { 00328 float bb[6]; 00329 float cost; 00330 }; 00331 00332 /* Object Surface Area Heuristic splitter */ 00333 int rtbuild_heuristic_object_split(RTBuilder *b, int nchilds) 00334 { 00335 int size = rtbuild_size(b); 00336 assert(nchilds == 2); 00337 assert(size > 1); 00338 int baxis = -1, boffset = 0; 00339 00340 if(size > nchilds) 00341 { 00342 float bcost = FLT_MAX; 00343 baxis = -1, boffset = size/2; 00344 00345 SweepCost *sweep = (SweepCost*)MEM_mallocN( sizeof(SweepCost)*size, "RTBuilder.HeuristicSweep" ); 00346 00347 for(int axis=0; axis<3; axis++) 00348 { 00349 SweepCost sweep_left; 00350 00351 RTBuilder::Object **obj = b->sorted_begin[axis]; 00352 00353 // float right_cost = 0; 00354 for(int i=size-1; i>=0; i--) 00355 { 00356 if(i == size-1) 00357 { 00358 copy_v3_v3(sweep[i].bb, obj[i]->bb); 00359 copy_v3_v3(sweep[i].bb+3, obj[i]->bb+3); 00360 sweep[i].cost = obj[i]->cost; 00361 } 00362 else 00363 { 00364 sweep[i].bb[0] = MIN2(obj[i]->bb[0], sweep[i+1].bb[0]); 00365 sweep[i].bb[1] = MIN2(obj[i]->bb[1], sweep[i+1].bb[1]); 00366 sweep[i].bb[2] = MIN2(obj[i]->bb[2], sweep[i+1].bb[2]); 00367 sweep[i].bb[3] = MAX2(obj[i]->bb[3], sweep[i+1].bb[3]); 00368 sweep[i].bb[4] = MAX2(obj[i]->bb[4], sweep[i+1].bb[4]); 00369 sweep[i].bb[5] = MAX2(obj[i]->bb[5], sweep[i+1].bb[5]); 00370 sweep[i].cost = obj[i]->cost + sweep[i+1].cost; 00371 } 00372 // right_cost += obj[i]->cost; 00373 } 00374 00375 sweep_left.bb[0] = obj[0]->bb[0]; 00376 sweep_left.bb[1] = obj[0]->bb[1]; 00377 sweep_left.bb[2] = obj[0]->bb[2]; 00378 sweep_left.bb[3] = obj[0]->bb[3]; 00379 sweep_left.bb[4] = obj[0]->bb[4]; 00380 sweep_left.bb[5] = obj[0]->bb[5]; 00381 sweep_left.cost = obj[0]->cost; 00382 00383 // right_cost -= obj[0]->cost; if(right_cost < 0) right_cost = 0; 00384 00385 for(int i=1; i<size; i++) 00386 { 00387 //Worst case heuristic (cost of each child is linear) 00388 float hcost, left_side, right_side; 00389 00390 // not using log seems to have no impact on raytracing perf, but 00391 // makes tree construction quicker, left out for now to test (brecht) 00392 // left_side = bb_area(sweep_left.bb, sweep_left.bb+3)*(sweep_left.cost+logf((float)i)); 00393 // right_side= bb_area(sweep[i].bb, sweep[i].bb+3)*(sweep[i].cost+logf((float)size-i)); 00394 left_side = bb_area(sweep_left.bb, sweep_left.bb+3)*(sweep_left.cost); 00395 right_side= bb_area(sweep[i].bb, sweep[i].bb+3)*(sweep[i].cost); 00396 hcost = left_side+right_side; 00397 00398 assert(left_side >= 0); 00399 assert(right_side >= 0); 00400 00401 if(left_side > bcost) break; //No way we can find a better heuristic in this axis 00402 00403 assert(hcost >= 0); 00404 if( hcost < bcost 00405 || (hcost == bcost && axis < baxis)) //this makes sure the tree built is the same whatever is the order of the sorting axis 00406 { 00407 bcost = hcost; 00408 baxis = axis; 00409 boffset = i; 00410 } 00411 DO_MIN( obj[i]->bb, sweep_left.bb ); 00412 DO_MAX( obj[i]->bb+3, sweep_left.bb+3 ); 00413 00414 sweep_left.cost += obj[i]->cost; 00415 // right_cost -= obj[i]->cost; if(right_cost < 0) right_cost = 0; 00416 } 00417 00418 //assert(baxis >= 0 && baxis < 3); 00419 if (!(baxis >= 0 && baxis < 3)) 00420 baxis = 0; 00421 } 00422 00423 00424 MEM_freeN(sweep); 00425 } 00426 else if(size == 2) 00427 { 00428 baxis = 0; 00429 boffset = 1; 00430 } 00431 else if(size == 1) 00432 { 00433 b->child_offset[0] = 0; 00434 b->child_offset[1] = 1; 00435 return 1; 00436 } 00437 00438 b->child_offset[0] = 0; 00439 b->child_offset[1] = boffset; 00440 b->child_offset[2] = size; 00441 00442 00443 /* Adjust sorted arrays for childs */ 00444 for(int i=0; i<boffset; i++) b->sorted_begin[baxis][i]->selected = true; 00445 for(int i=boffset; i<size; i++) b->sorted_begin[baxis][i]->selected = false; 00446 for(int i=0; i<3; i++) 00447 std::stable_partition( b->sorted_begin[i], b->sorted_end[i], selected_node ); 00448 00449 return nchilds; 00450 } 00451 00452 /* 00453 * Helper code 00454 * PARTITION code / used on mean-split 00455 * basicly this a std::nth_element (like on C++ STL algorithm) 00456 */ 00457 /* 00458 static void split_leafs(RTBuilder *b, int *nth, int partitions, int split_axis) 00459 { 00460 int i; 00461 b->split_axis = split_axis; 00462 00463 for(i=0; i < partitions-1; i++) 00464 { 00465 assert(nth[i] < nth[i+1] && nth[i+1] < nth[partitions]); 00466 00467 if(split_axis == 0) std::nth_element(b, nth[i], nth[i+1], nth[partitions], obj_bb_compare<RTBuilder::Object,0>); 00468 if(split_axis == 1) std::nth_element(b, nth[i], nth[i+1], nth[partitions], obj_bb_compare<RTBuilder::Object,1>); 00469 if(split_axis == 2) std::nth_element(b, nth[i], nth[i+1], nth[partitions], obj_bb_compare<RTBuilder::Object,2>); 00470 } 00471 } 00472 */ 00473 00474 /* 00475 * Bounding Box utils 00476 */ 00477 float bb_volume(float *min, float *max) 00478 { 00479 return (max[0]-min[0])*(max[1]-min[1])*(max[2]-min[2]); 00480 } 00481 00482 float bb_area(float *min, float *max) 00483 { 00484 float sub[3], a; 00485 sub[0] = max[0]-min[0]; 00486 sub[1] = max[1]-min[1]; 00487 sub[2] = max[2]-min[2]; 00488 00489 a = (sub[0]*sub[1] + sub[0]*sub[2] + sub[1]*sub[2])*2; 00490 /* used to have an assert() here on negative results 00491 * however, in this case its likely some overflow or ffast math error. 00492 * so just return 0.0f instead. */ 00493 return a < 0.0f ? 0.0f : a; 00494 } 00495 00496 int bb_largest_axis(float *min, float *max) 00497 { 00498 float sub[3]; 00499 00500 sub[0] = max[0]-min[0]; 00501 sub[1] = max[1]-min[1]; 00502 sub[2] = max[2]-min[2]; 00503 if(sub[0] > sub[1]) 00504 { 00505 if(sub[0] > sub[2]) 00506 return 0; 00507 else 00508 return 2; 00509 } 00510 else 00511 { 00512 if(sub[1] > sub[2]) 00513 return 1; 00514 else 00515 return 2; 00516 } 00517 } 00518 00519 int bb_fits_inside(float *outer_min, float *outer_max, float *inner_min, float *inner_max) 00520 { 00521 int i; 00522 for(i=0; i<3; i++) 00523 if(outer_min[i] > inner_min[i]) return 0; 00524 00525 for(i=0; i<3; i++) 00526 if(outer_max[i] < inner_max[i]) return 0; 00527 00528 return 1; 00529 }