|
Blender
V2.59
|
00001 /* 00002 * $Id: rayobject_vbvh.cpp 35477 2011-03-11 22:27:06Z blendix $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 * 00020 * The Original Code is Copyright (C) 2009 Blender Foundation. 00021 * All rights reserved. 00022 * 00023 * The Original Code is: all of this file. 00024 * 00025 * Contributor(s): André Pinto. 00026 * 00027 * ***** END GPL LICENSE BLOCK ***** 00028 */ 00029 00035 int tot_pushup = 0; 00036 int tot_pushdown = 0; 00037 int tot_hints = 0; 00038 00039 #include <assert.h> 00040 00041 #include "MEM_guardedalloc.h" 00042 00043 #include "BKE_global.h" 00044 00045 #include "BLI_math.h" 00046 #include "BLI_memarena.h" 00047 #include "BLI_utildefines.h" 00048 00049 #include "rayintersection.h" 00050 #include "rayobject.h" 00051 #include "rayobject_rtbuild.h" 00052 00053 #include "reorganize.h" 00054 #include "bvh.h" 00055 #include "vbvh.h" 00056 00057 #include <queue> 00058 #include <algorithm> 00059 00060 #define DFS_STACK_SIZE 256 00061 00062 struct VBVHTree 00063 { 00064 RayObject rayobj; 00065 VBVHNode *root; 00066 MemArena *node_arena; 00067 float cost; 00068 RTBuilder *builder; 00069 }; 00070 00071 /* 00072 * Cost to test N childs 00073 */ 00074 struct PackCost 00075 { 00076 float operator()(int n) 00077 { 00078 return n; 00079 } 00080 }; 00081 00082 template<> 00083 void bvh_done<VBVHTree>(VBVHTree *obj) 00084 { 00085 rtbuild_done(obj->builder, &obj->rayobj.control); 00086 00087 //TODO find a away to exactly calculate the needed memory 00088 MemArena *arena1 = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "vbvh arena"); 00089 BLI_memarena_use_malloc(arena1); 00090 00091 //Build and optimize the tree 00092 if(1) 00093 { 00094 VBVHNode *root = BuildBinaryVBVH<VBVHNode>(arena1,&obj->rayobj.control).transform(obj->builder); 00095 if(RE_rayobjectcontrol_test_break(&obj->rayobj.control)) 00096 { 00097 BLI_memarena_free(arena1); 00098 return; 00099 } 00100 00101 if(root) { 00102 reorganize(root); 00103 remove_useless(root, &root); 00104 bvh_refit(root); 00105 00106 pushup(root); 00107 pushdown(root); 00108 obj->root = root; 00109 } 00110 else 00111 obj->root = NULL; 00112 } 00113 else 00114 { 00115 /* 00116 TODO 00117 MemArena *arena2 = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "vbvh arena2"); 00118 BLI_memarena_use_malloc(arena2); 00119 00120 //Finds the optimal packing of this tree using a given cost model 00121 //TODO this uses quite a lot of memory, find ways to reduce memory usage during building 00122 OVBVHNode *root = BuildBinaryVBVH<OVBVHNode>(arena2).transform(obj->builder); 00123 VBVH_optimalPackSIMD<OVBVHNode,PackCost>(PackCost()).transform(root); 00124 obj->root = Reorganize_VBVH<OVBVHNode>(arena1).transform(root); 00125 00126 BLI_memarena_free(arena2); 00127 */ 00128 } 00129 00130 //Cleanup 00131 rtbuild_free( obj->builder ); 00132 obj->builder = NULL; 00133 00134 obj->node_arena = arena1; 00135 obj->cost = 1.0; 00136 } 00137 00138 template<int StackSize> 00139 int intersect(VBVHTree *obj, Isect* isec) 00140 { 00141 //TODO renable hint support 00142 if(RE_rayobject_isAligned(obj->root)) { 00143 if(isec->mode == RE_RAY_SHADOW) 00144 return bvh_node_stack_raycast<VBVHNode,StackSize,false,true>( obj->root, isec); 00145 else 00146 return bvh_node_stack_raycast<VBVHNode,StackSize,false,false>( obj->root, isec); 00147 } 00148 else 00149 return RE_rayobject_intersect( (RayObject*) obj->root, isec ); 00150 } 00151 00152 template<class Tree> 00153 void bvh_hint_bb(Tree *tree, LCTSHint *hint, float *min, float *max) 00154 { 00155 //TODO renable hint support 00156 { 00157 hint->size = 0; 00158 hint->stack[hint->size++] = (RayObject*)tree->root; 00159 } 00160 } 00161 00162 void bfree(VBVHTree *tree) 00163 { 00164 if(tot_pushup + tot_pushdown + tot_hints + tot_moves) 00165 { 00166 if(G.f & G_DEBUG) { 00167 printf("tot pushups: %d\n", tot_pushup); 00168 printf("tot pushdowns: %d\n", tot_pushdown); 00169 printf("tot moves: %d\n", tot_moves); 00170 printf("tot hints created: %d\n", tot_hints); 00171 } 00172 00173 tot_pushup = 0; 00174 tot_pushdown = 0; 00175 tot_hints = 0; 00176 tot_moves = 0; 00177 } 00178 bvh_free(tree); 00179 } 00180 00181 /* the cast to pointer function is needed to workarround gcc bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11407 */ 00182 template<class Tree, int STACK_SIZE> 00183 RayObjectAPI make_api() 00184 { 00185 static RayObjectAPI api = 00186 { 00187 (RE_rayobject_raycast_callback) ((int(*)(Tree*,Isect*)) &intersect<STACK_SIZE>), 00188 (RE_rayobject_add_callback) ((void(*)(Tree*,RayObject*)) &bvh_add<Tree>), 00189 (RE_rayobject_done_callback) ((void(*)(Tree*)) &bvh_done<Tree>), 00190 (RE_rayobject_free_callback) ((void(*)(Tree*)) &bvh_free<Tree>), 00191 (RE_rayobject_merge_bb_callback)((void(*)(Tree*,float*,float*)) &bvh_bb<Tree>), 00192 (RE_rayobject_cost_callback) ((float(*)(Tree*)) &bvh_cost<Tree>), 00193 (RE_rayobject_hint_bb_callback) ((void(*)(Tree*,LCTSHint*,float*,float*)) &bvh_hint_bb<Tree>) 00194 }; 00195 00196 return api; 00197 } 00198 00199 template<class Tree> 00200 RayObjectAPI* bvh_get_api(int maxstacksize) 00201 { 00202 static RayObjectAPI bvh_api256 = make_api<Tree,1024>(); 00203 00204 if(maxstacksize <= 1024) return &bvh_api256; 00205 assert(maxstacksize <= 256); 00206 return 0; 00207 } 00208 00209 RayObject *RE_rayobject_vbvh_create(int size) 00210 { 00211 return bvh_create_tree<VBVHTree,DFS_STACK_SIZE>(size); 00212 }