Added some test_break during the build process.
[blender-staging.git] / source / blender / render / intern / raytrace / rayobject_qbvh.cpp
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2009 Blender Foundation.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): AndrĂ© Pinto.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29 #include "vbvh.h"
30 #include "svbvh.h"
31 #include "reorganize.h"
32
33 #define DFS_STACK_SIZE  256
34
35 struct QBVHTree
36 {
37         RayObject rayobj;
38
39         SVBVHNode *root;
40         MemArena *node_arena;
41
42         float cost;
43         RTBuilder *builder;
44 };
45
46
47 template<>
48 void bvh_done<QBVHTree>(QBVHTree *obj)
49 {
50         rtbuild_done(obj->builder, &obj->rayobj.control);
51         
52         //TODO find a away to exactly calculate the needed memory
53         MemArena *arena1 = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
54                                            BLI_memarena_use_malloc(arena1);
55
56         MemArena *arena2 = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
57                                            BLI_memarena_use_malloc(arena2);
58                                            BLI_memarena_use_align(arena2, 16);
59
60         //Build and optimize the tree   
61         //TODO do this in 1 pass (half memory usage during building)    
62         VBVHNode *root = BuildBinaryVBVH<VBVHNode>(arena1, &obj->rayobj.control).transform(obj->builder);       
63         
64         if(RE_rayobjectcontrol_test_break(&obj->rayobj.control))
65         {
66                 BLI_memarena_free(arena1);
67                 BLI_memarena_free(arena2);
68                 return;
69         }
70         
71         pushup_simd<VBVHNode,4>(root);                                     
72         obj->root = Reorganize_SVBVH<VBVHNode>(arena2).transform(root);
73         
74         //Cleanup
75         BLI_memarena_free(arena1);      
76         
77         rtbuild_free( obj->builder );
78         obj->builder = NULL;
79
80         obj->node_arena = arena2;
81         obj->cost = 1.0;        
82 }
83
84
85 template<int StackSize>
86 int intersect(QBVHTree *obj, Isect* isec)
87 {
88         //TODO renable hint support
89         if(RE_rayobject_isAligned(obj->root))
90                 return bvh_node_stack_raycast<SVBVHNode,StackSize,false>( obj->root, isec);
91         else
92                 return RE_rayobject_intersect( (RayObject*) obj->root, isec );
93 }
94
95 template<class Tree>
96 void bvh_hint_bb(Tree *tree, LCTSHint *hint, float *min, float *max)
97 {
98         //TODO renable hint support
99         {
100                 hint->size = 0;
101                 hint->stack[hint->size++] = (RayObject*)tree->root;
102         }
103 }
104 /* the cast to pointer function is needed to workarround gcc bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11407 */
105 template<class Tree, int STACK_SIZE>
106 RayObjectAPI make_api()
107 {
108         static RayObjectAPI api = 
109         {
110                 (RE_rayobject_raycast_callback) ((int(*)(Tree*,Isect*)) &intersect<STACK_SIZE>),
111                 (RE_rayobject_add_callback)     ((void(*)(Tree*,RayObject*)) &bvh_add<Tree>),
112                 (RE_rayobject_done_callback)    ((void(*)(Tree*))       &bvh_done<Tree>),
113                 (RE_rayobject_free_callback)    ((void(*)(Tree*))       &bvh_free<Tree>),
114                 (RE_rayobject_merge_bb_callback)((void(*)(Tree*,float*,float*)) &bvh_bb<Tree>),
115                 (RE_rayobject_cost_callback)    ((float(*)(Tree*))      &bvh_cost<Tree>),
116                 (RE_rayobject_hint_bb_callback) ((void(*)(Tree*,LCTSHint*,float*,float*)) &bvh_hint_bb<Tree>)
117         };
118         
119         return api;
120 }
121
122 template<class Tree>
123 RayObjectAPI* bvh_get_api(int maxstacksize)
124 {
125         static RayObjectAPI bvh_api256 = make_api<Tree,1024>();
126         
127         if(maxstacksize <= 1024) return &bvh_api256;
128         assert(maxstacksize <= 256);
129         return 0;
130 }
131
132
133 RayObject *RE_rayobject_qbvh_create(int size)
134 {
135         return bvh_create_tree<QBVHTree,DFS_STACK_SIZE>(size);
136 }