Blender V2.61 - r43446

rayobject_vbvh.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 int tot_pushup   = 0;
00034 int tot_pushdown = 0;
00035 int tot_hints    = 0;
00036 
00037 #include <assert.h>
00038 
00039 #include "MEM_guardedalloc.h"
00040 
00041 #include "BKE_global.h"
00042 
00043 #include "BLI_math.h"
00044 #include "BLI_memarena.h"
00045 #include "BLI_utildefines.h"
00046 
00047 #include "rayintersection.h"
00048 #include "rayobject.h"
00049 #include "rayobject_rtbuild.h"
00050 
00051 #include "reorganize.h"
00052 #include "bvh.h"
00053 #include "vbvh.h"
00054 
00055 #include <queue>
00056 #include <algorithm>
00057 
00058 #define DFS_STACK_SIZE  256
00059 
00060 struct VBVHTree
00061 {
00062     RayObject rayobj;
00063     VBVHNode *root;
00064     MemArena *node_arena;
00065     float cost;
00066     RTBuilder *builder;
00067 };
00068 
00069 /*
00070  * Cost to test N childs
00071  */
00072 struct PackCost
00073 {
00074     float operator()(int n)
00075     {
00076         return n;
00077     }
00078 };
00079 
00080 template<>
00081 void bvh_done<VBVHTree>(VBVHTree *obj)
00082 {
00083     rtbuild_done(obj->builder, &obj->rayobj.control);
00084     
00085     //TODO find a away to exactly calculate the needed memory
00086     MemArena *arena1 = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "vbvh arena");
00087                        BLI_memarena_use_malloc(arena1);
00088     
00089     //Build and optimize the tree
00090     if(1)
00091     {
00092         VBVHNode *root = BuildBinaryVBVH<VBVHNode>(arena1,&obj->rayobj.control).transform(obj->builder);
00093         if(RE_rayobjectcontrol_test_break(&obj->rayobj.control))
00094         {
00095             BLI_memarena_free(arena1);
00096             return;
00097         }
00098 
00099         if(root) {
00100             reorganize(root);
00101             remove_useless(root, &root);
00102             bvh_refit(root);
00103         
00104             pushup(root);
00105             pushdown(root);
00106             obj->root = root;
00107         }
00108         else
00109             obj->root = NULL;
00110     }
00111     else
00112     {
00113 /*
00114     TODO
00115         MemArena *arena2 = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "vbvh arena2");
00116                            BLI_memarena_use_malloc(arena2);
00117                            
00118         //Finds the optimal packing of this tree using a given cost model
00119         //TODO this uses quite a lot of memory, find ways to reduce memory usage during building
00120         OVBVHNode *root = BuildBinaryVBVH<OVBVHNode>(arena2).transform(obj->builder);           
00121         VBVH_optimalPackSIMD<OVBVHNode,PackCost>(PackCost()).transform(root);
00122         obj->root = Reorganize_VBVH<OVBVHNode>(arena1).transform(root);
00123         
00124         BLI_memarena_free(arena2);
00125  */
00126     }
00127 
00128     //Cleanup
00129     rtbuild_free( obj->builder );
00130     obj->builder = NULL;
00131 
00132     obj->node_arena = arena1;
00133     obj->cost = 1.0;    
00134 }
00135 
00136 template<int StackSize>
00137 int intersect(VBVHTree *obj, Isect* isec)
00138 {
00139     //TODO renable hint support
00140     if(RE_rayobject_isAligned(obj->root)) {
00141         if(isec->mode == RE_RAY_SHADOW)
00142             return bvh_node_stack_raycast<VBVHNode,StackSize,false,true>( obj->root, isec);
00143         else
00144             return bvh_node_stack_raycast<VBVHNode,StackSize,false,false>( obj->root, isec);
00145     }
00146     else
00147         return RE_rayobject_intersect( (RayObject*) obj->root, isec );
00148 }
00149 
00150 template<class Tree>
00151 void bvh_hint_bb(Tree *tree, LCTSHint *hint, float *UNUSED(min), float *UNUSED(max))
00152 {
00153     //TODO renable hint support
00154     {
00155         hint->size = 0;
00156         hint->stack[hint->size++] = (RayObject*)tree->root;
00157     }
00158 }
00159 
00160 void bfree(VBVHTree *tree)
00161 {
00162     if(tot_pushup + tot_pushdown + tot_hints + tot_moves)
00163     {
00164         if(G.f & G_DEBUG) {
00165             printf("tot pushups: %d\n", tot_pushup);
00166             printf("tot pushdowns: %d\n", tot_pushdown);
00167             printf("tot moves: %d\n", tot_moves);
00168             printf("tot hints created: %d\n", tot_hints);
00169         }
00170 
00171         tot_pushup = 0;
00172         tot_pushdown = 0;
00173         tot_hints = 0;
00174         tot_moves = 0;
00175     }
00176     bvh_free(tree);
00177 }
00178 
00179 /* the cast to pointer function is needed to workarround gcc bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11407 */
00180 template<class Tree, int STACK_SIZE>
00181 RayObjectAPI make_api()
00182 {
00183     static RayObjectAPI api = 
00184     {
00185         (RE_rayobject_raycast_callback) ((int(*)(Tree*,Isect*)) &intersect<STACK_SIZE>),
00186         (RE_rayobject_add_callback)     ((void(*)(Tree*,RayObject*)) &bvh_add<Tree>),
00187         (RE_rayobject_done_callback)    ((void(*)(Tree*))       &bvh_done<Tree>),
00188         (RE_rayobject_free_callback)    ((void(*)(Tree*))       &bvh_free<Tree>),
00189         (RE_rayobject_merge_bb_callback)((void(*)(Tree*,float*,float*)) &bvh_bb<Tree>),
00190         (RE_rayobject_cost_callback)    ((float(*)(Tree*))      &bvh_cost<Tree>),
00191         (RE_rayobject_hint_bb_callback) ((void(*)(Tree*,LCTSHint*,float*,float*)) &bvh_hint_bb<Tree>)
00192     };
00193     
00194     return api;
00195 }
00196 
00197 template<class Tree>
00198 RayObjectAPI* bvh_get_api(int maxstacksize)
00199 {
00200     static RayObjectAPI bvh_api256 = make_api<Tree,1024>();
00201     
00202     if(maxstacksize <= 1024) return &bvh_api256;
00203     assert(maxstacksize <= 256);
00204     return 0;
00205 }
00206 
00207 RayObject *RE_rayobject_vbvh_create(int size)
00208 {
00209     return bvh_create_tree<VBVHTree,DFS_STACK_SIZE>(size);
00210 }