00001 #ifndef OPENTISSUE_COLLISION_OBB_TREE_OBB_TREE_TOP_DOWN_POLICY_H
00002 #define OPENTISSUE_COLLISION_OBB_TREE_OBB_TREE_TOP_DOWN_POLICY_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/core/geometry/geometry_obb_fit.h>
00013
00014 #include <cassert>
00015
00016 namespace OpenTissue
00017 {
00018
00019 namespace obb_tree
00020 {
00021
00022 template<
00023 typename bvh_type
00024 , typename obb_tree_types_
00025 >
00026 class TopDownPolicy
00027 {
00028 public:
00029
00030 typedef obb_tree_types_ obb_tree_types;
00031 typedef typename obb_tree_types::obb_type obb_type;
00032 typedef typename obb_tree_types::plane_type plane_type;
00033
00034
00035 typedef typename obb_tree_types::math_types math_types;
00036 typedef typename math_types::vector3_type vector3_type;
00037 typedef typename math_types::real_type real_type;
00038 typedef typename math_types::value_traits value_traits;
00039
00040
00041 typedef TopDownPolicy<bvh_type,obb_tree_types> top_down_type;
00042
00043 typedef typename bvh_type::bv_ptr bv_ptr;
00044 typedef typename bvh_type::annotated_bv_type annotated_bv_type;
00045 typedef typename bvh_type::annotated_bv_ptr annotated_bv_ptr;
00046 typedef typename bvh_type::volume_type volume_type;
00047 typedef typename bvh_type::geometry_type geometry_type;
00048 typedef typename std::vector<geometry_type> geometry_container;
00049
00050 typedef typename obb_tree_types::face_ptr_type face_ptr_type;
00051
00052
00053 protected:
00054
00055 geometry_container m_geometry;
00056
00057 size_t m_degree;
00058
00059 public:
00060
00061 class partition_type
00062 {
00063 public:
00064
00065 friend class TopDownPolicy<bvh_type,obb_tree_types>;
00066
00067 public:
00068
00069 typedef std::vector<partition_type> partition_container;
00070 typedef typename partition_container::iterator partition_iterator;
00071
00072 protected:
00073
00074 partition_container m_sub_partitions;
00075 size_t m_left;
00076 size_t m_right;
00077 top_down_type * m_owner;
00078 bv_ptr m_bv;
00079
00080 public:
00081
00082 partition_type()
00083 : m_left(0)
00084 , m_right(0)
00085 , m_owner(0)
00086 , m_bv()
00087 {}
00088
00089 partition_type(top_down_type * owner,unsigned int left,unsigned int right)
00090 : m_left(left)
00091 , m_right(right)
00092 , m_owner(owner)
00093 , m_bv()
00094 {}
00095
00096 bool annotated() const { return size()==1; }
00097 unsigned int size() const { return (m_right-m_left+1); }
00098 bool empty() { return (size()==0); }
00099 void split() { m_owner->split((*this)); }
00100 partition_iterator sub_partition_begin() { return m_sub_partitions.begin(); }
00101 partition_iterator sub_partition_end() { return m_sub_partitions.end(); }
00102
00103 void fit(bv_ptr bv)
00104 {
00105 m_bv = bv;
00106 m_owner->fit(bv,(*this));
00107 }
00108
00109 };
00110
00111 public:
00112
00113 typedef typename partition_type::partition_container partition_container;
00114 typedef typename partition_type::partition_iterator partition_iterator;
00115
00116 protected:
00117
00118 class vector3_iterator
00119 : public std::iterator<std::forward_iterator_tag, vector3_type>
00120 {
00121 protected:
00122
00123 top_down_type * m_owner;
00124 unsigned int m_idx;
00125 unsigned int m_sub_idx;
00126
00127 public:
00128
00129 vector3_iterator(top_down_type * owner,unsigned int idx)
00130 : m_owner(owner)
00131 , m_idx(idx)
00132 , m_sub_idx()
00133 {}
00134
00135 public:
00136
00137 bool operator==(vector3_iterator const& other) const { return (m_idx==other.m_idx && m_sub_idx==other.m_sub_idx); }
00138 bool operator!=(vector3_iterator const& other) const { return !(m_idx==other.m_idx && m_sub_idx==other.m_sub_idx); }
00139
00140 vector3_iterator & operator++()
00141 {
00142 if(m_sub_idx==3)
00143 {
00144 ++m_idx;
00145 m_sub_idx = 0;
00146 }
00147 else
00148 {
00149 ++m_sub_idx;
00150 }
00151 return *this;
00152 }
00153
00154 vector3_type & operator*() const
00155 {
00156 face_ptr_type f = m_owner->m_geometry[m_idx];
00157 if(m_sub_idx==0)
00158 return *(f->m_v0);
00159 else if (m_sub_idx==1)
00160 return *(f->m_v1);
00161 return *(f->m_v2);
00162 }
00163
00164 };
00165
00166 public:
00167
00168 TopDownPolicy()
00169 : m_degree(2)
00170 {}
00171
00172
00173 partition_type all() { return partition_type(this,0,static_cast<unsigned int>(m_geometry.size()-1)); }
00174
00175 template<typename iterator>
00176 void init(iterator begin,iterator end)
00177 {
00178 m_geometry.clear();
00179 std::copy( begin, end, std::back_inserter( m_geometry ) );
00180 }
00181
00187 void set_degree(size_t const & new_degree)
00188 {
00189 assert( new_degree == 2u || new_degree == 4u || new_degree == 8u || !"TopDownPolicy::set_degree(): invalid degree value!");
00190 m_degree = new_degree;
00191 }
00192
00193 protected:
00194
00198 size_t const & degree() const {return m_degree;}
00199
00209 void make_plane_split(plane_type const & plane, partition_type const & set, partition_type & left_subset, partition_type & right_subset )
00210 {
00211 assert( set.size() > 1u || !"make_plane_split(): Impossible to split a set of one element into two subsets");
00212
00213 using std::min;
00214
00215 vector3_type center;
00216
00217 size_t current = set.m_left;
00218 size_t last = set.m_right;
00219
00220 for(;current<last;)
00221 {
00222 OpenTissue::mesh::compute_face_center( (*m_geometry[current]), center);
00223 if( plane.signed_distance(center) > value_traits::zero() )
00224 {
00225 std::swap(m_geometry[current],m_geometry[last]);
00226 --last;
00227 }
00228 else
00229 {
00230 ++current;
00231 }
00232 }
00233
00234 size_t first_right = min(last+1, set.m_right);
00235 size_t last_left = first_right - 1;
00236 size_t first_left = set.m_left;
00237 size_t last_right = set.m_right;
00238
00239 left_subset = partition_type( this, first_left, last_left );
00240 right_subset = partition_type( this, first_right, last_right );
00241 }
00242
00243 void split(partition_type & partition)
00244 {
00245 using std::min;
00246
00247 assert(partition.m_bv || !"TopDownPolicy::split(...): bounding volume was null?");
00248
00249
00250 obb_type & obb = partition.m_bv->volume();
00251 vector3_type center = obb.center();
00252
00253 size_t order[3];
00254 OpenTissue::math::get_increasing_order( obb.ext(), order );
00255
00256 vector3_type axis1 = obb.orientation().column( order[2] );
00257 vector3_type axis2 = obb.orientation().column( order[1] );
00258 vector3_type axis3 = obb.orientation().column( order[0] );
00259
00260 plane_type split_plane1(axis1,center);
00261 plane_type split_plane2(axis2,center);
00262 plane_type split_plane3(axis3,center);
00263
00264
00265 partition.m_sub_partitions.resize( this->degree() );
00266
00267
00268 if(this->degree()==2)
00269 {
00270 make_plane_split( split_plane1, partition, partition.m_sub_partitions[0], partition.m_sub_partitions[1] );
00271 }
00272 else if(this->degree()==4)
00273 {
00274 partition_type tmp_left;
00275 partition_type tmp_right;
00276 make_plane_split( split_plane1, partition, tmp_left, tmp_right );
00277
00278 make_plane_split( split_plane2, tmp_left, partition.m_sub_partitions[0], partition.m_sub_partitions[1] );
00279 make_plane_split( split_plane2, tmp_right, partition.m_sub_partitions[2], partition.m_sub_partitions[3] );
00280 }
00281 else if(this->degree()==8)
00282 {
00283 partition_type tmp_left;
00284 partition_type tmp_right;
00285 make_plane_split( split_plane1, partition, tmp_left, tmp_right );
00286
00287 partition_type tmp_left_left;
00288 partition_type tmp_left_right;
00289 partition_type tmp_right_left;
00290 partition_type tmp_right_right;
00291 make_plane_split( split_plane2, tmp_left, tmp_left_left, tmp_left_right );
00292 make_plane_split( split_plane2, tmp_right, tmp_right_left, tmp_right_right );
00293
00294 make_plane_split( split_plane3, tmp_left_left, partition.m_sub_partitions[0], partition.m_sub_partitions[1] );
00295 make_plane_split( split_plane3, tmp_left_right, partition.m_sub_partitions[2], partition.m_sub_partitions[3] );
00296 make_plane_split( split_plane3, tmp_right_left, partition.m_sub_partitions[4], partition.m_sub_partitions[5] );
00297 make_plane_split( split_plane3, tmp_right_right, partition.m_sub_partitions[6], partition.m_sub_partitions[7] );
00298 }
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337 }
00338
00339 void fit(bv_ptr bv,partition_type & partition)
00340 {
00341 partition.m_bv = bv;
00342
00343 if(partition.annotated())
00344 {
00345 annotated_bv_ptr A = boost::static_pointer_cast<annotated_bv_type>(bv);
00346 A->insert( m_geometry[partition.m_left] );
00347 }
00348 vector3_iterator begin( this, partition.m_left );
00349 vector3_iterator end( this, partition.m_right+1 );
00350 OpenTissue::geometry::obb_fit(begin,end,bv->volume());
00351 }
00352
00353 };
00354
00355 }
00356
00357 }
00358
00359
00360 #endif