|
Blender
V2.59
|
00001 /* 00002 * $Id: rayobject_qbvh.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 QBVHTree 00048 { 00049 RayObject rayobj; 00050 00051 SVBVHNode *root; 00052 MemArena *node_arena; 00053 00054 float cost; 00055 RTBuilder *builder; 00056 }; 00057 00058 00059 template<> 00060 void bvh_done<QBVHTree>(QBVHTree *obj) 00061 { 00062 rtbuild_done(obj->builder, &obj->rayobj.control); 00063 00064 //TODO find a away to exactly calculate the needed memory 00065 MemArena *arena1 = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "qbvh arena"); 00066 BLI_memarena_use_malloc(arena1); 00067 00068 MemArena *arena2 = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "qbvh arena 2"); 00069 BLI_memarena_use_malloc(arena2); 00070 BLI_memarena_use_align(arena2, 16); 00071 00072 //Build and optimize the tree 00073 //TODO do this in 1 pass (half memory usage during building) 00074 VBVHNode *root = BuildBinaryVBVH<VBVHNode>(arena1, &obj->rayobj.control).transform(obj->builder); 00075 00076 if(RE_rayobjectcontrol_test_break(&obj->rayobj.control)) 00077 { 00078 BLI_memarena_free(arena1); 00079 BLI_memarena_free(arena2); 00080 return; 00081 } 00082 00083 if(root) { 00084 pushup_simd<VBVHNode,4>(root); 00085 obj->root = Reorganize_SVBVH<VBVHNode>(arena2).transform(root); 00086 } 00087 else 00088 obj->root = NULL; 00089 00090 //Free data 00091 BLI_memarena_free(arena1); 00092 00093 obj->node_arena = arena2; 00094 obj->cost = 1.0; 00095 00096 rtbuild_free(obj->builder); 00097 obj->builder = NULL; 00098 } 00099 00100 template<int StackSize> 00101 int intersect(QBVHTree *obj, Isect* isec) 00102 { 00103 //TODO renable hint support 00104 if(RE_rayobject_isAligned(obj->root)) { 00105 if(isec->mode == RE_RAY_SHADOW) 00106 return svbvh_node_stack_raycast<StackSize,true>(obj->root, isec); 00107 else 00108 return svbvh_node_stack_raycast<StackSize,false>(obj->root, isec); 00109 } 00110 else 00111 return RE_rayobject_intersect((RayObject*)obj->root, isec); 00112 } 00113 00114 template<class Tree> 00115 void bvh_hint_bb(Tree *tree, LCTSHint *hint, float *min, float *max) 00116 { 00117 //TODO renable hint support 00118 { 00119 hint->size = 0; 00120 hint->stack[hint->size++] = (RayObject*)tree->root; 00121 } 00122 } 00123 /* the cast to pointer function is needed to workarround gcc bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11407 */ 00124 template<class Tree, int STACK_SIZE> 00125 RayObjectAPI make_api() 00126 { 00127 static RayObjectAPI api = 00128 { 00129 (RE_rayobject_raycast_callback) ((int(*)(Tree*,Isect*)) &intersect<STACK_SIZE>), 00130 (RE_rayobject_add_callback) ((void(*)(Tree*,RayObject*)) &bvh_add<Tree>), 00131 (RE_rayobject_done_callback) ((void(*)(Tree*)) &bvh_done<Tree>), 00132 (RE_rayobject_free_callback) ((void(*)(Tree*)) &bvh_free<Tree>), 00133 (RE_rayobject_merge_bb_callback)((void(*)(Tree*,float*,float*)) &bvh_bb<Tree>), 00134 (RE_rayobject_cost_callback) ((float(*)(Tree*)) &bvh_cost<Tree>), 00135 (RE_rayobject_hint_bb_callback) ((void(*)(Tree*,LCTSHint*,float*,float*)) &bvh_hint_bb<Tree>) 00136 }; 00137 00138 return api; 00139 } 00140 00141 template<class Tree> 00142 RayObjectAPI* bvh_get_api(int maxstacksize) 00143 { 00144 static RayObjectAPI bvh_api256 = make_api<Tree,1024>(); 00145 00146 if(maxstacksize <= 1024) return &bvh_api256; 00147 assert(maxstacksize <= 256); 00148 return 0; 00149 } 00150 00151 RayObject *RE_rayobject_qbvh_create(int size) 00152 { 00153 return bvh_create_tree<QBVHTree,DFS_STACK_SIZE>(size); 00154 } 00155 00156 #else 00157 00158 RayObject *RE_rayobject_qbvh_create(int size) 00159 { 00160 puts("WARNING: SSE disabled at compile time\n"); 00161 return NULL; 00162 } 00163 00164 #endif