Blender V2.61 - r43446

vbvh.h

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 <assert.h>
00034 #include <algorithm>
00035 
00036 #include "BLI_memarena.h"
00037 
00038 #include "rayobject_rtbuild.h"
00039 
00040 /*
00041  * VBVHNode represents a BVHNode with support for a variable number of childrens
00042  */
00043 struct VBVHNode
00044 {
00045     float   bb[6];
00046 
00047     VBVHNode *child;
00048     VBVHNode *sibling;
00049 };
00050 
00051 
00052 /*
00053  * Push nodes (used on dfs)
00054  */
00055 template<class Node>
00056 inline static void bvh_node_push_childs(Node *node, Isect *UNUSED(isec), Node **stack, int &stack_pos)
00057 {
00058     Node *child = node->child;
00059 
00060     if(is_leaf(child))
00061     {
00062         stack[stack_pos++] = child;
00063     }
00064     else
00065     {
00066         while(child)
00067         {
00068             //Skips BB tests on primitives
00069 /*
00070             if(is_leaf(child->child))
00071                 stack[stack_pos++] = child->child;
00072             else
00073 */
00074                 stack[stack_pos++] = child;
00075                 
00076             child = child->sibling;
00077         }
00078     }
00079 }
00080 
00081 
00082 template<class Node>
00083 int count_childs(Node *parent)
00084 {
00085     int n = 0;
00086     for(Node *i = parent->child; i; i = i->sibling)
00087     {
00088         n++;
00089         if(is_leaf(i))
00090             break;
00091     }
00092         
00093     return n;
00094 }
00095 
00096 
00097 template<class Node>
00098 void append_sibling(Node *node, Node *sibling)
00099 {
00100     while(node->sibling)
00101         node = node->sibling;
00102         
00103     node->sibling = sibling;
00104 }
00105 
00106 
00107 /*
00108  * Builds a binary VBVH from a rtbuild
00109  */
00110 template<class Node>
00111 struct BuildBinaryVBVH
00112 {
00113     MemArena *arena;
00114     RayObjectControl *control;
00115 
00116     void test_break()
00117     {
00118         if(RE_rayobjectcontrol_test_break(control))
00119             throw "Stop";
00120     }
00121 
00122     BuildBinaryVBVH(MemArena *a, RayObjectControl *c)
00123     {
00124         arena = a;
00125         control = c;
00126     }
00127 
00128     Node *create_node()
00129     {
00130         Node *node = (Node*)BLI_memarena_alloc( arena, sizeof(Node) );
00131         assert( RE_rayobject_isAligned(node) );
00132 
00133         node->sibling = NULL;
00134         node->child   = NULL;
00135 
00136         return node;
00137     }
00138     
00139     int rtbuild_split(RTBuilder *builder)
00140     {
00141         return ::rtbuild_heuristic_object_split(builder, 2);
00142     }
00143     
00144     Node *transform(RTBuilder *builder)
00145     {
00146         try
00147         {
00148             return _transform(builder);
00149             
00150         } catch(...)
00151         {
00152         }
00153         return NULL;
00154     }
00155     
00156     Node *_transform(RTBuilder *builder)
00157     {
00158         int size = rtbuild_size(builder);
00159 
00160         if(size == 0) {
00161             return NULL;
00162         }
00163         else if(size == 1)
00164         {
00165             Node *node = create_node();
00166             INIT_MINMAX(node->bb, node->bb+3);
00167             rtbuild_merge_bb(builder, node->bb, node->bb+3);        
00168             node->child = (Node*) rtbuild_get_primitive( builder, 0 );
00169             return node;
00170         }
00171         else
00172         {
00173             test_break();
00174             
00175             Node *node = create_node();
00176 
00177             Node **child = &node->child;
00178 
00179             int nc = rtbuild_split(builder);
00180             INIT_MINMAX(node->bb, node->bb+3);
00181 
00182             assert(nc == 2);
00183             for(int i=0; i<nc; i++)
00184             {
00185                 RTBuilder tmp;
00186                 rtbuild_get_child(builder, i, &tmp);
00187                 
00188                 *child = _transform(&tmp);
00189                 DO_MIN((*child)->bb, node->bb);
00190                 DO_MAX((*child)->bb+3, node->bb+3);
00191                 child = &((*child)->sibling);
00192             }
00193 
00194             *child = 0;
00195             return node;
00196         }
00197     }
00198 };
00199 
00200 /*
00201 template<class Tree,class OldNode>
00202 struct Reorganize_VBVH
00203 {
00204     Tree *tree;
00205     
00206     Reorganize_VBVH(Tree *t)
00207     {
00208         tree = t;
00209     }
00210     
00211     VBVHNode *create_node()
00212     {
00213         VBVHNode *node = (VBVHNode*)BLI_memarena_alloc(tree->node_arena, sizeof(VBVHNode));
00214         return node;
00215     }
00216     
00217     void copy_bb(VBVHNode *node, OldNode *old)
00218     {
00219         std::copy( old->bb, old->bb+6, node->bb );
00220     }
00221     
00222     VBVHNode *transform(OldNode *old)
00223     {
00224         if(is_leaf(old))
00225             return (VBVHNode*)old;
00226 
00227         VBVHNode *node = create_node();
00228         VBVHNode **child_ptr = &node->child;
00229         node->sibling = 0;
00230 
00231         copy_bb(node,old);
00232 
00233         for(OldNode *o_child = old->child; o_child; o_child = o_child->sibling)
00234         {
00235             VBVHNode *n_child = transform(o_child);
00236             *child_ptr = n_child;
00237             if(is_leaf(n_child)) return node;
00238             child_ptr = &n_child->sibling;
00239         }
00240         *child_ptr = 0;
00241         
00242         return node;
00243     }   
00244 };
00245 */