Blender  V2.59
rayobject_qbvh.cpp
Go to the documentation of this file.
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