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