3
-----------------------------------------------------------------------------
4
This source file is part of GIMPACT Library.
6
For the latest info, see http://gimpact.sourceforge.net/
8
Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
9
email: projectileman@yahoo.com
11
This library is free software; you can redistribute it and/or
12
modify it under the terms of EITHER:
13
(1) The GNU Lesser General Public License as published by the Free
14
Software Foundation; either version 2.1 of the License, or (at
15
your option) any later version. The text of the GNU Lesser
16
General Public License is included with this library in the
17
file GIMPACT-LICENSE-LGPL.TXT.
18
(2) The BSD-style license that is included with this library in
19
the file GIMPACT-LICENSE-BSD.TXT.
20
(3) The zlib/libpng license that is included with this library in
21
the file GIMPACT-LICENSE-ZLIB.TXT.
23
This library is distributed in the hope that it will be useful,
24
but WITHOUT ANY WARRANTY; without even the implied warranty of
25
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
26
GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
28
-----------------------------------------------------------------------------
32
#include "gim_box_set.h"
35
GUINT GIM_BOX_TREE::_calc_splitting_axis(
36
gim_array<GIM_AABB_DATA> & primitive_boxes, GUINT startIndex, GUINT endIndex)
40
btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.));
41
btVector3 variance(btScalar(0.),btScalar(0.),btScalar(0.));
42
GUINT numIndices = endIndex-startIndex;
44
for (i=startIndex;i<endIndex;i++)
46
btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
47
primitive_boxes[i].m_bound.m_min);
50
means *= (btScalar(1.)/(btScalar)numIndices);
52
for (i=startIndex;i<endIndex;i++)
54
btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
55
primitive_boxes[i].m_bound.m_min);
56
btVector3 diff2 = center-means;
57
diff2 = diff2 * diff2;
60
variance *= (btScalar(1.)/ ((btScalar)numIndices-1) );
62
return variance.maxAxis();
66
GUINT GIM_BOX_TREE::_sort_and_calc_splitting_index(
67
gim_array<GIM_AABB_DATA> & primitive_boxes, GUINT startIndex,
68
GUINT endIndex, GUINT splitAxis)
71
GUINT splitIndex =startIndex;
72
GUINT numIndices = endIndex - startIndex;
75
btScalar splitValue = 0.0f;
76
for (i=startIndex;i<endIndex;i++)
78
splitValue+= 0.5f*(primitive_boxes[i].m_bound.m_max[splitAxis] +
79
primitive_boxes[i].m_bound.m_min[splitAxis]);
81
splitValue /= (btScalar)numIndices;
83
//sort leafNodes so all values larger then splitValue comes first, and smaller values start from 'splitIndex'.
84
for (i=startIndex;i<endIndex;i++)
86
btScalar center = 0.5f*(primitive_boxes[i].m_bound.m_max[splitAxis] +
87
primitive_boxes[i].m_bound.m_min[splitAxis]);
88
if (center > splitValue)
91
primitive_boxes.swap(i,splitIndex);
96
//if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex
97
//otherwise the tree-building might fail due to stack-overflows in certain cases.
98
//unbalanced1 is unsafe: it can cause stack overflows
99
//bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1)));
101
//unbalanced2 should work too: always use center (perfect balanced trees)
102
//bool unbalanced2 = true;
104
//this should be safe too:
105
GUINT rangeBalancedIndices = numIndices/3;
106
bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices)));
110
splitIndex = startIndex+ (numIndices>>1);
113
btAssert(!((splitIndex==startIndex) || (splitIndex == (endIndex))));
119
void GIM_BOX_TREE::_build_sub_tree(gim_array<GIM_AABB_DATA> & primitive_boxes, GUINT startIndex, GUINT endIndex)
121
GUINT current_index = m_num_nodes++;
123
btAssert((endIndex-startIndex)>0);
125
if((endIndex-startIndex) == 1) //we got a leaf
127
m_node_array[current_index].m_left = 0;
128
m_node_array[current_index].m_right = 0;
129
m_node_array[current_index].m_escapeIndex = 0;
131
m_node_array[current_index].m_bound = primitive_boxes[startIndex].m_bound;
132
m_node_array[current_index].m_data = primitive_boxes[startIndex].m_data;
136
//configure inner node
140
//calc this node bounding box
141
m_node_array[current_index].m_bound.invalidate();
142
for (splitIndex=startIndex;splitIndex<endIndex;splitIndex++)
144
m_node_array[current_index].m_bound.merge(primitive_boxes[splitIndex].m_bound);
147
//calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'.
150
splitIndex = _calc_splitting_axis(primitive_boxes,startIndex,endIndex);
152
splitIndex = _sort_and_calc_splitting_index(
153
primitive_boxes,startIndex,endIndex,splitIndex);
155
//configure this inner node : the left node index
156
m_node_array[current_index].m_left = m_num_nodes;
157
//build left child tree
158
_build_sub_tree(primitive_boxes, startIndex, splitIndex );
160
//configure this inner node : the right node index
161
m_node_array[current_index].m_right = m_num_nodes;
163
//build right child tree
164
_build_sub_tree(primitive_boxes, splitIndex ,endIndex);
166
//configure this inner node : the escape index
167
m_node_array[current_index].m_escapeIndex = m_num_nodes - current_index;
170
//! stackless build tree
171
void GIM_BOX_TREE::build_tree(
172
gim_array<GIM_AABB_DATA> & primitive_boxes)
174
// initialize node count to 0
177
m_node_array.resize(primitive_boxes.size()*2);
179
_build_sub_tree(primitive_boxes, 0, primitive_boxes.size());