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