Blender V2.61 - r43446

rayobject_qbvh.cpp

Go to the documentation of this file.
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