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