|
Blender
V2.59
|
00001 /* 00002 * $Id: rayobject_svbvh.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 #include "MEM_guardedalloc.h" 00036 00037 #include "BLI_utildefines.h" 00038 00039 #include "vbvh.h" 00040 #include "svbvh.h" 00041 #include "reorganize.h" 00042 00043 #ifdef __SSE__ 00044 00045 #define DFS_STACK_SIZE 256 00046 00047 struct SVBVHTree 00048 { 00049 RayObject rayobj; 00050 00051 SVBVHNode *root; 00052 MemArena *node_arena; 00053 00054 float cost; 00055 RTBuilder *builder; 00056 }; 00057 00058 /* 00059 * Cost to test N childs 00060 */ 00061 struct PackCost 00062 { 00063 float operator()(int n) 00064 { 00065 return (n / 4) + ((n % 4) > 2 ? 1 : n%4); 00066 } 00067 }; 00068 00069 00070 template<> 00071 void bvh_done<SVBVHTree>(SVBVHTree *obj) 00072 { 00073 rtbuild_done(obj->builder, &obj->rayobj.control); 00074 00075 //TODO find a away to exactly calculate the needed memory 00076 MemArena *arena1 = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "svbvh arena"); 00077 BLI_memarena_use_malloc(arena1); 00078 00079 MemArena *arena2 = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "svbvh arena2"); 00080 BLI_memarena_use_malloc(arena2); 00081 BLI_memarena_use_align(arena2, 16); 00082 00083 //Build and optimize the tree 00084 if(0) 00085 { 00086 VBVHNode *root = BuildBinaryVBVH<VBVHNode>(arena1, &obj->rayobj.control).transform(obj->builder); 00087 00088 if(RE_rayobjectcontrol_test_break(&obj->rayobj.control)) 00089 { 00090 BLI_memarena_free(arena1); 00091 BLI_memarena_free(arena2); 00092 return; 00093 } 00094 00095 reorganize(root); 00096 remove_useless(root, &root); 00097 bvh_refit(root); 00098 00099 pushup(root); 00100 pushdown(root); 00101 pushup_simd<VBVHNode,4>(root); 00102 00103 obj->root = Reorganize_SVBVH<VBVHNode>(arena2).transform(root); 00104 } 00105 else 00106 { 00107 //Finds the optimal packing of this tree using a given cost model 00108 //TODO this uses quite a lot of memory, find ways to reduce memory usage during building 00109 OVBVHNode *root = BuildBinaryVBVH<OVBVHNode>(arena1,&obj->rayobj.control).transform(obj->builder); 00110 00111 if(RE_rayobjectcontrol_test_break(&obj->rayobj.control)) 00112 { 00113 BLI_memarena_free(arena1); 00114 BLI_memarena_free(arena2); 00115 return; 00116 } 00117 00118 if(root) { 00119 VBVH_optimalPackSIMD<OVBVHNode,PackCost>(PackCost()).transform(root); 00120 obj->root = Reorganize_SVBVH<OVBVHNode>(arena2).transform(root); 00121 } 00122 else 00123 obj->root = NULL; 00124 } 00125 00126 //Free data 00127 BLI_memarena_free(arena1); 00128 00129 obj->node_arena = arena2; 00130 obj->cost = 1.0; 00131 00132 rtbuild_free( obj->builder ); 00133 obj->builder = NULL; 00134 } 00135 00136 template<int StackSize> 00137 int intersect(SVBVHTree *obj, Isect* isec) 00138 { 00139 //TODO renable hint support 00140 if(RE_rayobject_isAligned(obj->root)) { 00141 if(isec->mode == RE_RAY_SHADOW) 00142 return svbvh_node_stack_raycast<StackSize,true>(obj->root, isec); 00143 else 00144 return svbvh_node_stack_raycast<StackSize,false>(obj->root, isec); 00145 } 00146 else 00147 return RE_rayobject_intersect( (RayObject*) obj->root, isec ); 00148 } 00149 00150 template<class Tree> 00151 void bvh_hint_bb(Tree *tree, LCTSHint *hint, float *min, float *max) 00152 { 00153 //TODO renable hint support 00154 { 00155 hint->size = 0; 00156 hint->stack[hint->size++] = (RayObject*)tree->root; 00157 } 00158 } 00159 /* the cast to pointer function is needed to workarround gcc bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11407 */ 00160 template<class Tree, int STACK_SIZE> 00161 RayObjectAPI make_api() 00162 { 00163 static RayObjectAPI api = 00164 { 00165 (RE_rayobject_raycast_callback) ((int(*)(Tree*,Isect*)) &intersect<STACK_SIZE>), 00166 (RE_rayobject_add_callback) ((void(*)(Tree*,RayObject*)) &bvh_add<Tree>), 00167 (RE_rayobject_done_callback) ((void(*)(Tree*)) &bvh_done<Tree>), 00168 (RE_rayobject_free_callback) ((void(*)(Tree*)) &bvh_free<Tree>), 00169 (RE_rayobject_merge_bb_callback)((void(*)(Tree*,float*,float*)) &bvh_bb<Tree>), 00170 (RE_rayobject_cost_callback) ((float(*)(Tree*)) &bvh_cost<Tree>), 00171 (RE_rayobject_hint_bb_callback) ((void(*)(Tree*,LCTSHint*,float*,float*)) &bvh_hint_bb<Tree>) 00172 }; 00173 00174 return api; 00175 } 00176 00177 template<class Tree> 00178 RayObjectAPI* bvh_get_api(int maxstacksize) 00179 { 00180 static RayObjectAPI bvh_api256 = make_api<Tree,1024>(); 00181 00182 if(maxstacksize <= 1024) return &bvh_api256; 00183 assert(maxstacksize <= 256); 00184 return 0; 00185 } 00186 00187 RayObject *RE_rayobject_svbvh_create(int size) 00188 { 00189 return bvh_create_tree<SVBVHTree,DFS_STACK_SIZE>(size); 00190 } 00191 00192 #else 00193 00194 RayObject *RE_rayobject_svbvh_create(int size) 00195 { 00196 puts("WARNING: SSE disabled at compile time\n"); 00197 return NULL; 00198 } 00199 00200 #endif