00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00037 #ifndef FCL_BV_SPLITTER_H
00038 #define FCL_BV_SPLITTER_H
00039
00040 #include "fcl/BVH/BVH_internal.h"
00041 #include "fcl/BV/kIOS.h"
00042 #include "fcl/BV/OBBRSS.h"
00043 #include <vector>
00044 #include <iostream>
00045
00046 namespace fcl
00047 {
00048
00050 template<typename BV>
00051 class BVSplitterBase
00052 {
00053 public:
00055 virtual void set(Vec3f* vertices_, Triangle* tri_indices_, BVHModelType type_) = 0;
00056
00058 virtual void computeRule(const BV& bv, unsigned int* primitive_indices, int num_primitives) = 0;
00059
00061 virtual bool apply(const Vec3f& q) const = 0;
00062
00064 virtual void clear() = 0;
00065 };
00066
00067
00069 enum SplitMethodType {SPLIT_METHOD_MEAN, SPLIT_METHOD_MEDIAN, SPLIT_METHOD_BV_CENTER};
00070
00071
00073 template<typename BV>
00074 class BVSplitter : public BVSplitterBase<BV>
00075 {
00076 public:
00077
00078 BVSplitter(SplitMethodType method) : split_method(method)
00079 {
00080 }
00081
00083 virtual ~BVSplitter() {}
00084
00086 void set(Vec3f* vertices_, Triangle* tri_indices_, BVHModelType type_)
00087 {
00088 vertices = vertices_;
00089 tri_indices = tri_indices_;
00090 type = type_;
00091 }
00092
00094 void computeRule(const BV& bv, unsigned int* primitive_indices, int num_primitives)
00095 {
00096 switch(split_method)
00097 {
00098 case SPLIT_METHOD_MEAN:
00099 computeRule_mean(bv, primitive_indices, num_primitives);
00100 break;
00101 case SPLIT_METHOD_MEDIAN:
00102 computeRule_median(bv, primitive_indices, num_primitives);
00103 break;
00104 case SPLIT_METHOD_BV_CENTER:
00105 computeRule_bvcenter(bv, primitive_indices, num_primitives);
00106 break;
00107 default:
00108 std::cerr << "Split method not supported" << std::endl;
00109 }
00110 }
00111
00113 bool apply(const Vec3f& q) const
00114 {
00115 return q[split_axis] > split_value;
00116 }
00117
00119 void clear()
00120 {
00121 vertices = NULL;
00122 tri_indices = NULL;
00123 type = BVH_MODEL_UNKNOWN;
00124 }
00125
00126 private:
00127
00130 int split_axis;
00131 Vec3f split_vector;
00132
00134 FCL_REAL split_value;
00135
00137 Vec3f* vertices;
00138
00140 Triangle* tri_indices;
00141
00143 BVHModelType type;
00144
00146 SplitMethodType split_method;
00147
00149 void computeRule_bvcenter(const BV& bv, unsigned int* primitive_indices, int num_primitives)
00150 {
00151 Vec3f center = bv.center();
00152 int axis = 2;
00153
00154 if(bv.width() >= bv.height() && bv.width() >= bv.depth())
00155 axis = 0;
00156 else if(bv.height() >= bv.width() && bv.height() >= bv.depth())
00157 axis = 1;
00158
00159 split_axis = axis;
00160 split_value = center[axis];
00161 }
00162
00164 void computeRule_mean(const BV& bv, unsigned int* primitive_indices, int num_primitives)
00165 {
00166 int axis = 2;
00167
00168 if(bv.width() >= bv.height() && bv.width() >= bv.depth())
00169 axis = 0;
00170 else if(bv.height() >= bv.width() && bv.height() >= bv.depth())
00171 axis = 1;
00172
00173 split_axis = axis;
00174 FCL_REAL sum = 0;
00175
00176 if(type == BVH_MODEL_TRIANGLES)
00177 {
00178 for(int i = 0; i < num_primitives; ++i)
00179 {
00180 const Triangle& t = tri_indices[primitive_indices[i]];
00181 sum += (vertices[t[0]][split_axis] + vertices[t[1]][split_axis] + vertices[t[2]][split_axis]);
00182 }
00183
00184 sum /= 3;
00185 }
00186 else if(type == BVH_MODEL_POINTCLOUD)
00187 {
00188 for(int i = 0; i < num_primitives; ++i)
00189 {
00190 sum += vertices[primitive_indices[i]][split_axis];
00191 }
00192 }
00193
00194 split_value = sum / num_primitives;
00195 }
00196
00198 void computeRule_median(const BV& bv, unsigned int* primitive_indices, int num_primitives)
00199 {
00200 int axis = 2;
00201
00202 if(bv.width() >= bv.height() && bv.width() >= bv.depth())
00203 axis = 0;
00204 else if(bv.height() >= bv.width() && bv.height() >= bv.depth())
00205 axis = 1;
00206
00207 split_axis = axis;
00208 std::vector<FCL_REAL> proj(num_primitives);
00209
00210 if(type == BVH_MODEL_TRIANGLES)
00211 {
00212 for(int i = 0; i < num_primitives; ++i)
00213 {
00214 const Triangle& t = tri_indices[primitive_indices[i]];
00215 proj[i] = (vertices[t[0]][split_axis] + vertices[t[1]][split_axis] + vertices[t[2]][split_axis]) / 3;
00216 }
00217 }
00218 else if(type == BVH_MODEL_POINTCLOUD)
00219 {
00220 for(int i = 0; i < num_primitives; ++i)
00221 proj[i] = vertices[primitive_indices[i]][split_axis];
00222 }
00223
00224 std::sort(proj.begin(), proj.end());
00225
00226 if(num_primitives % 2 == 1)
00227 {
00228 split_value = proj[(num_primitives - 1) / 2];
00229 }
00230 else
00231 {
00232 split_value = (proj[num_primitives / 2] + proj[num_primitives / 2 - 1]) / 2;
00233 }
00234 }
00235 };
00236
00237
00238 template<>
00239 bool BVSplitter<OBB>::apply(const Vec3f& q) const;
00240
00241 template<>
00242 bool BVSplitter<RSS>::apply(const Vec3f& q) const;
00243
00244 template<>
00245 bool BVSplitter<kIOS>::apply(const Vec3f& q) const;
00246
00247 template<>
00248 bool BVSplitter<OBBRSS>::apply(const Vec3f& q) const;
00249
00250 template<>
00251 void BVSplitter<OBB>::computeRule_bvcenter(const OBB& bv, unsigned int* primitive_indices, int num_primitives);
00252
00253 template<>
00254 void BVSplitter<OBB>::computeRule_mean(const OBB& bv, unsigned int* primitive_indices, int num_primitives);
00255
00256 template<>
00257 void BVSplitter<OBB>::computeRule_median(const OBB& bv, unsigned int* primitive_indices, int num_primitives);
00258
00259 template<>
00260 void BVSplitter<RSS>::computeRule_bvcenter(const RSS& bv, unsigned int* primitive_indices, int num_primitives);
00261
00262 template<>
00263 void BVSplitter<RSS>::computeRule_mean(const RSS& bv, unsigned int* primitive_indices, int num_primitives);
00264
00265 template<>
00266 void BVSplitter<RSS>::computeRule_median(const RSS& bv, unsigned int* primitive_indices, int num_primitives);
00267
00268 template<>
00269 void BVSplitter<kIOS>::computeRule_bvcenter(const kIOS& bv, unsigned int* primitive_indices, int num_primitives);
00270
00271 template<>
00272 void BVSplitter<kIOS>::computeRule_mean(const kIOS& bv, unsigned int* primitive_indices, int num_primitives);
00273
00274 template<>
00275 void BVSplitter<kIOS>::computeRule_median(const kIOS& bv, unsigned int* primitive_indices, int num_primitives);
00276
00277 template<>
00278 void BVSplitter<OBBRSS>::computeRule_bvcenter(const OBBRSS& bv, unsigned int* primitive_indices, int num_primitives);
00279
00280 template<>
00281 void BVSplitter<OBBRSS>::computeRule_mean(const OBBRSS& bv, unsigned int* primitive_indices, int num_primitives);
00282
00283 template<>
00284 void BVSplitter<OBBRSS>::computeRule_median(const OBBRSS& bv, unsigned int* primitive_indices, int num_primitives);
00285
00286 }
00287
00288 #endif