Blender V2.61 - r43446

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