Blender V2.61 - r43446
|
00001 00002 /* 00003 ----------------------------------------------------------------------------- 00004 This source file is part of GIMPACT Library. 00005 00006 For the latest info, see http://gimpact.sourceforge.net/ 00007 00008 Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. 00009 email: projectileman@yahoo.com 00010 00011 This library is free software; you can redistribute it and/or 00012 modify it under the terms of EITHER: 00013 (1) The GNU Lesser General Public License as published by the Free 00014 Software Foundation; either version 2.1 of the License, or (at 00015 your option) any later version. The text of the GNU Lesser 00016 General Public License is included with this library in the 00017 file GIMPACT-LICENSE-LGPL.TXT. 00018 (2) The BSD-style license that is included with this library in 00019 the file GIMPACT-LICENSE-BSD.TXT. 00020 (3) The zlib/libpng license that is included with this library in 00021 the file GIMPACT-LICENSE-ZLIB.TXT. 00022 00023 This library is distributed in the hope that it will be useful, 00024 but WITHOUT ANY WARRANTY; without even the implied warranty of 00025 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files 00026 GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. 00027 00028 ----------------------------------------------------------------------------- 00029 */ 00030 00031 00032 #include "gim_box_set.h" 00033 00034 00035 GUINT GIM_BOX_TREE::_calc_splitting_axis( 00036 gim_array<GIM_AABB_DATA> & primitive_boxes, GUINT startIndex, GUINT endIndex) 00037 { 00038 GUINT i; 00039 00040 btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.)); 00041 btVector3 variance(btScalar(0.),btScalar(0.),btScalar(0.)); 00042 GUINT numIndices = endIndex-startIndex; 00043 00044 for (i=startIndex;i<endIndex;i++) 00045 { 00046 btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max + 00047 primitive_boxes[i].m_bound.m_min); 00048 means+=center; 00049 } 00050 means *= (btScalar(1.)/(btScalar)numIndices); 00051 00052 for (i=startIndex;i<endIndex;i++) 00053 { 00054 btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max + 00055 primitive_boxes[i].m_bound.m_min); 00056 btVector3 diff2 = center-means; 00057 diff2 = diff2 * diff2; 00058 variance += diff2; 00059 } 00060 variance *= (btScalar(1.)/ ((btScalar)numIndices-1) ); 00061 00062 return variance.maxAxis(); 00063 } 00064 00065 00066 GUINT GIM_BOX_TREE::_sort_and_calc_splitting_index( 00067 gim_array<GIM_AABB_DATA> & primitive_boxes, GUINT startIndex, 00068 GUINT endIndex, GUINT splitAxis) 00069 { 00070 GUINT i; 00071 GUINT splitIndex =startIndex; 00072 GUINT numIndices = endIndex - startIndex; 00073 00074 // average of centers 00075 btScalar splitValue = 0.0f; 00076 for (i=startIndex;i<endIndex;i++) 00077 { 00078 splitValue+= 0.5f*(primitive_boxes[i].m_bound.m_max[splitAxis] + 00079 primitive_boxes[i].m_bound.m_min[splitAxis]); 00080 } 00081 splitValue /= (btScalar)numIndices; 00082 00083 //sort leafNodes so all values larger then splitValue comes first, and smaller values start from 'splitIndex'. 00084 for (i=startIndex;i<endIndex;i++) 00085 { 00086 btScalar center = 0.5f*(primitive_boxes[i].m_bound.m_max[splitAxis] + 00087 primitive_boxes[i].m_bound.m_min[splitAxis]); 00088 if (center > splitValue) 00089 { 00090 //swap 00091 primitive_boxes.swap(i,splitIndex); 00092 splitIndex++; 00093 } 00094 } 00095 00096 //if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex 00097 //otherwise the tree-building might fail due to stack-overflows in certain cases. 00098 //unbalanced1 is unsafe: it can cause stack overflows 00099 //bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1))); 00100 00101 //unbalanced2 should work too: always use center (perfect balanced trees) 00102 //bool unbalanced2 = true; 00103 00104 //this should be safe too: 00105 GUINT rangeBalancedIndices = numIndices/3; 00106 bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices))); 00107 00108 if (unbalanced) 00109 { 00110 splitIndex = startIndex+ (numIndices>>1); 00111 } 00112 00113 btAssert(!((splitIndex==startIndex) || (splitIndex == (endIndex)))); 00114 00115 return splitIndex; 00116 } 00117 00118 00119 void GIM_BOX_TREE::_build_sub_tree(gim_array<GIM_AABB_DATA> & primitive_boxes, GUINT startIndex, GUINT endIndex) 00120 { 00121 GUINT current_index = m_num_nodes++; 00122 00123 btAssert((endIndex-startIndex)>0); 00124 00125 if((endIndex-startIndex) == 1) //we got a leaf 00126 { 00127 m_node_array[current_index].m_left = 0; 00128 m_node_array[current_index].m_right = 0; 00129 m_node_array[current_index].m_escapeIndex = 0; 00130 00131 m_node_array[current_index].m_bound = primitive_boxes[startIndex].m_bound; 00132 m_node_array[current_index].m_data = primitive_boxes[startIndex].m_data; 00133 return; 00134 } 00135 00136 //configure inner node 00137 00138 GUINT splitIndex; 00139 00140 //calc this node bounding box 00141 m_node_array[current_index].m_bound.invalidate(); 00142 for (splitIndex=startIndex;splitIndex<endIndex;splitIndex++) 00143 { 00144 m_node_array[current_index].m_bound.merge(primitive_boxes[splitIndex].m_bound); 00145 } 00146 00147 //calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'. 00148 00149 //split axis 00150 splitIndex = _calc_splitting_axis(primitive_boxes,startIndex,endIndex); 00151 00152 splitIndex = _sort_and_calc_splitting_index( 00153 primitive_boxes,startIndex,endIndex,splitIndex); 00154 00155 //configure this inner node : the left node index 00156 m_node_array[current_index].m_left = m_num_nodes; 00157 //build left child tree 00158 _build_sub_tree(primitive_boxes, startIndex, splitIndex ); 00159 00160 //configure this inner node : the right node index 00161 m_node_array[current_index].m_right = m_num_nodes; 00162 00163 //build right child tree 00164 _build_sub_tree(primitive_boxes, splitIndex ,endIndex); 00165 00166 //configure this inner node : the escape index 00167 m_node_array[current_index].m_escapeIndex = m_num_nodes - current_index; 00168 } 00169 00171 void GIM_BOX_TREE::build_tree( 00172 gim_array<GIM_AABB_DATA> & primitive_boxes) 00173 { 00174 // initialize node count to 0 00175 m_num_nodes = 0; 00176 // allocate nodes 00177 m_node_array.resize(primitive_boxes.size()*2); 00178 00179 _build_sub_tree(primitive_boxes, 0, primitive_boxes.size()); 00180 } 00181 00182