[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [21666] branches/soc-2009-jaguarandi/ source/blender/render/intern/raytrace: Another try with building better trees (this should never make worst trees )
André Pinto
andresusanopinto at gmail.com
Fri Jul 17 21:09:44 CEST 2009
Revision: 21666
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=21666
Author: jaguarandi
Date: 2009-07-17 21:09:42 +0200 (Fri, 17 Jul 2009)
Log Message:
-----------
Another try with building better trees (this should never make worst trees)
Expected number of BB tests should reduce a bit (depending on the scene)
Modified Paths:
--------------
branches/soc-2009-jaguarandi/source/blender/render/intern/raytrace/rayobject_vbvh.cpp
Added Paths:
-----------
branches/soc-2009-jaguarandi/source/blender/render/intern/raytrace/reorganize.h
Modified: branches/soc-2009-jaguarandi/source/blender/render/intern/raytrace/rayobject_vbvh.cpp
===================================================================
--- branches/soc-2009-jaguarandi/source/blender/render/intern/raytrace/rayobject_vbvh.cpp 2009-07-17 18:35:49 UTC (rev 21665)
+++ branches/soc-2009-jaguarandi/source/blender/render/intern/raytrace/rayobject_vbvh.cpp 2009-07-17 19:09:42 UTC (rev 21666)
@@ -38,6 +38,7 @@
#include "rayobject.h"
};
+#include "reorganize.h"
#include "bvh.h"
#include <queue>
@@ -146,9 +147,9 @@
//assert(bb_fits_inside(parent->bb, parent->bb+3, child->bb, child->bb+3));
for(Node *i = parent->child; RayObject_isAligned(i) && i; i = i->sibling)
- if(child != i && bb_fits_inside(i->bb, i->bb+3, child->bb, child->bb+3))
+ if(child != i && bb_fits_inside(i->bb, i->bb+3, child->bb, child->bb+3) && RayObject_isAligned(i->child))
{
-// todo optimize (hsould the one with the smallest area
+// todo optimize (should the one with the smallest area?)
// float ia = bb_area(i->bb, i->bb+3)
// if(child->i)
*s_child = child->sibling;
@@ -167,8 +168,65 @@
pushdown( i );
}
+template<class Node>
+int count_childs(Node *parent)
+{
+ int n = 0;
+ for(Node *i = parent->child; i; i = i->sibling)
+ {
+ n++;
+ if(!RayObject_isAligned(i))
+ break;
+ }
+
+ return n;
+}
+
+template<class Node>
+void append_sibling(Node *node, Node *sibling)
+{
+ while(node->sibling)
+ node = node->sibling;
+
+ node->sibling = sibling;
+}
+
+template<class Node>
+void pushup(Node *parent)
+{
+ float p_area = bb_area(parent->bb, parent->bb+3);
+ Node **prev = &parent->child;
+ for(Node *child = parent->child; RayObject_isAligned(child) && child; )
+ {
+ float c_area = bb_area(child->bb, child->bb+3) ;
+ int nchilds = count_childs(child);
+ float original_cost = (c_area / p_area)*nchilds + 1;
+ float flatten_cost = nchilds;
+ if(flatten_cost < original_cost && nchilds >= 2)
+ {
+ append_sibling(child, child->child);
+ child = child->sibling;
+ *prev = child;
+
+// *prev = child->child;
+// append_sibling( *prev, child->sibling );
+// child = *prev;
+ tot_pushup++;
+ }
+ else
+ {
+ *prev = child;
+ prev = &(*prev)->sibling;
+ child = *prev;
+ }
+ }
+
+ for(Node *child = parent->child; RayObject_isAligned(child) && child; child = child->sibling)
+ pushup(child);
+}
+
template<class Tree, class Node, class Builder>
-Node *bvh_rearrange(Tree *tree, Builder *builder, float *cost)
+Node *bvh_rearrange(Tree *tree, Builder *builder)
{
int size = rtbuild_size(builder);
@@ -176,61 +234,31 @@
{
Node *node = bvh_new_node(tree);
INIT_MINMAX(node->bb, node->bb+3);
- rtbuild_merge_bb(builder, node->bb, node->bb+3);
-
+ rtbuild_merge_bb(builder, node->bb, node->bb+3);
node->child = (BVHNode*)builder->begin[0];
-
- *cost = RE_rayobject_cost((RayObject*)node->child)+RAY_BB_TEST_COST;
return node;
}
else
{
Node *node = bvh_new_node(tree);
- float parent_area;
-
+
INIT_MINMAX(node->bb, node->bb+3);
rtbuild_merge_bb(builder, node->bb, node->bb+3);
- parent_area = bb_area( node->bb, node->bb+3 );
Node **child = &node->child;
-
- std::queue<Builder> childs;
- childs.push(*builder);
-
- *cost = 0;
-
- while(!childs.empty())
+
+ int nc = rtbuild_split(builder, 2);
+ assert(nc == 2);
+ for(int i=0; i<nc; i++)
{
- Builder b = childs.front();
- childs.pop();
+ Builder tmp;
+ rtbuild_get_child(builder, i, &tmp);
- float hit_prob = rtbuild_area(&b) / parent_area;
- if(hit_prob > 1.0f / 2.0f && rtbuild_size(&b) > 1)
- {
- //The expected number of BB test is smaller if we directly add the 2 childs of this node
- int nc = rtbuild_split(&b, 2);
- assert(nc == 2);
- for(int i=0; i<nc; i++)
- {
- Builder tmp;
- rtbuild_get_child(&b, i, &tmp);
- childs.push(tmp);
- }
- tot_pushup++;
-
- }
- else
- {
- float tcost;
- *child = bvh_rearrange<Tree,Node,Builder>(tree, &b, &tcost);
- child = &((*child)->sibling);
-
- *cost += tcost*hit_prob + RAY_BB_TEST_COST;
- }
+ *child = bvh_rearrange<Tree,Node,Builder>(tree, &tmp);
+ child = &((*child)->sibling);
}
- assert(child != &node->child);
+
*child = 0;
-
return node;
}
}
@@ -246,9 +274,13 @@
BLI_memarena_use_malloc(obj->node_arena);
- obj->root = bvh_rearrange<BVHTree,BVHNode,RTBuilder>( obj, obj->builder, &obj->cost );
+ obj->root = bvh_rearrange<BVHTree,BVHNode,RTBuilder>( obj, obj->builder );
+ reorganize(obj->root);
+ remove_useless(obj->root, &obj->root);
+ pushup(obj->root);
pushdown(obj->root);
-// obj->cost = 1.0;
+// obj->root = memory_rearrange(obj->root);
+ obj->cost = 1.0;
rtbuild_free( obj->builder );
obj->builder = NULL;
@@ -336,14 +368,16 @@
void bfree(BVHTree *tree)
{
- if(tot_pushup + tot_pushdown + tot_hints)
+ if(tot_pushup + tot_pushdown + tot_hints + tot_moves)
{
printf("tot pushups: %d\n", tot_pushup);
printf("tot pushdowns: %d\n", tot_pushdown);
+ printf("tot moves: %d\n", tot_moves);
printf("tot hints created: %d\n", tot_hints);
tot_pushup = 0;
tot_pushdown = 0;
tot_hints = 0;
+ tot_moves = 0;
}
bvh_free(tree);
}
Added: branches/soc-2009-jaguarandi/source/blender/render/intern/raytrace/reorganize.h
===================================================================
--- branches/soc-2009-jaguarandi/source/blender/render/intern/raytrace/reorganize.h (rev 0)
+++ branches/soc-2009-jaguarandi/source/blender/render/intern/raytrace/reorganize.h 2009-07-17 19:09:42 UTC (rev 21666)
@@ -0,0 +1,138 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2009 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): André Pinto.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#include <algorithm>
+#include <queue>
+
+template<class Node>
+bool node_fits_inside(Node *a, Node *b)
+{
+ return bb_fits_inside(b->bb, b->bb+3, a->bb, a->bb+3);
+}
+
+template<class Node>
+void reorganize_find_fittest_parent(Node *tree, Node *node, std::pair<float,Node*> &cost)
+{
+ std::queue<Node*> q;
+ q.push(tree);
+
+ while(!q.empty())
+ {
+ Node *parent = q.front();
+ q.pop();
+
+ if(parent == node) continue;
+ if(node_fits_inside(node, parent) && RayObject_isAligned(parent->child) )
+ {
+ float pcost = bb_area(parent->bb, parent->bb+3);
+ cost = std::min( cost, std::make_pair(pcost,parent) );
+ for(Node *child = parent->child; child; child = child->sibling)
+ q.push(child);
+ }
+ }
+}
+
+static int tot_moves = 0;
+template<class Node>
+void reorganize(Node *root)
+{
+ std::queue<Node*> q;
+
+ q.push(root);
+ while(!q.empty())
+ {
+ Node * node = q.front();
+ q.pop();
+
+ if( RayObject_isAligned(node->child) )
+ {
+ for(Node **prev = &node->child; *prev; )
+ {
+ assert( RayObject_isAligned(*prev) );
+ q.push(*prev);
+
+ std::pair<float,Node*> best(FLT_MAX, root);
+ reorganize_find_fittest_parent( root, *prev, best );
+
+ if(best.second == node)
+ {
+ //Already inside the fitnest BB
+ prev = &(*prev)->sibling;
+ }
+ else
+ {
+ Node *tmp = *prev;
+ *prev = (*prev)->sibling;
+
+ tmp->sibling = best.second->child;
+ best.second->child = tmp;
+
+ tot_moves++;
+ }
+
+
+ }
+ }
+ if(node != root)
+ {
+ }
+ }
+}
+
+/*
+ * Prunes useless nodes from trees:
+ * erases nodes with total ammount of primitives = 0
+ * prunes nodes with only one child (except if that child is a primitive)
+ */
+template<class Node>
+void remove_useless(Node *node, Node **new_node)
+{
+ if( RayObject_isAligned(node->child) )
+ {
+
+ for(Node **prev = &node->child; *prev; )
+ {
+ Node *next = (*prev)->sibling;
+ remove_useless(*prev, prev);
+ if(*prev == 0)
+ *prev = next;
+ else
+ {
+ (*prev)->sibling = next;
+ prev = &((*prev)->sibling);
+ }
+ }
+ }
+ if(node->child)
+ {
+ if(RayObject_isAligned(node->child) && node->child->child == 0)
+ *new_node = node->child;
+ }
+ else if(node->child == 0)
+ *new_node = 0;
+}
Property changes on: branches/soc-2009-jaguarandi/source/blender/render/intern/raytrace/reorganize.h
___________________________________________________________________
Name: svn:keywords
+ Author Date Id Revision
Name: svn:eol-style
+ native
More information about the Bf-blender-cvs
mailing list