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