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 #ifndef opengl_COctreePointRenderer_H
00029 #define opengl_COctreePointRenderer_H
00030
00031 #include <mrpt/opengl/CRenderizable.h>
00032 #include <mrpt/opengl/CSetOfObjects.h>
00033 #include <mrpt/opengl/CBox.h>
00034
00035
00036 namespace mrpt
00037 {
00038 namespace global_settings
00039 {
00040
00041
00042
00043
00044
00045 extern OPENGL_IMPEXP float OCTREE_RENDER_MAX_DENSITY_POINTS_PER_SQPIXEL;
00046
00047
00048
00049
00050
00051
00052 extern OPENGL_IMPEXP size_t OCTREE_RENDER_MAX_POINTS_PER_NODE;
00053 }
00054
00055
00056 namespace opengl
00057 {
00058 using namespace mrpt::utils;
00059
00060
00061
00062
00063
00064 template <class Derived>
00065 class COctreePointRenderer
00066 {
00067 public:
00068
00069 COctreePointRenderer() :
00070 m_octree_has_to_rebuild_all(true),
00071 m_visible_octree_nodes(0),
00072 m_visible_octree_nodes_ongoing(0)
00073 { }
00074
00075
00076 COctreePointRenderer(const COctreePointRenderer &) :
00077 m_octree_has_to_rebuild_all(true)
00078 { }
00079
00080
00081 enum { OCTREE_ROOT_NODE = 0 };
00082
00083 protected:
00084
00085 inline Derived & octree_derived() { return *static_cast<Derived*>(this); }
00086 inline const Derived & octree_derived() const { return *static_cast<const Derived*>(this); }
00087
00088
00089 inline void octree_assure_uptodate() const
00090 {
00091 const_cast<COctreePointRenderer<Derived>*>(this)->internal_octree_assure_uptodate();
00092 }
00093
00094
00095
00096
00097 void octree_render(const mrpt::opengl::gl_utils::TRenderInfo &ri ) const
00098 {
00099 m_visible_octree_nodes_ongoing = 0;
00100
00101
00102 m_render_queue.clear();
00103 m_render_queue.reserve(m_octree_nodes.size());
00104
00105 TPixelCoordf cr_px[8];
00106 float cr_z[8];
00107 octree_recursive_render(OCTREE_ROOT_NODE,ri, cr_px, cr_z, false );
00108
00109 m_visible_octree_nodes = m_visible_octree_nodes_ongoing;
00110
00111
00112 for (size_t i=0;i<m_render_queue.size();i++)
00113 {
00114 const TNode & node = m_octree_nodes[ m_render_queue[i].node_id ];
00115 octree_derived().render_subset( node.all,node.pts,m_render_queue[i].render_area_sqpixels);
00116 }
00117 }
00118
00119
00120 private:
00121
00122
00123
00124 struct OPENGL_IMPEXP TNode
00125 {
00126 TNode() :
00127 bb_min( std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max() ),
00128 bb_max(-std::numeric_limits<float>::max(),-std::numeric_limits<float>::max(),-std::numeric_limits<float>::max() )
00129 { }
00130
00131 bool is_leaf;
00132
00133
00134 mrpt::math::TPoint3Df bb_min, bb_max;
00135
00136
00137 std::vector<size_t> pts;
00138 bool all;
00139
00140
00141 mrpt::math::TPoint3Df center;
00142 size_t child_id[8];
00143
00144
00145 inline void update_bb(const mrpt::math::TPoint3Df &p)
00146 {
00147 keep_min(bb_min.x, p.x); keep_min(bb_min.y, p.y); keep_min(bb_min.z, p.z);
00148 keep_max(bb_max.x, p.x); keep_max(bb_max.y, p.y); keep_max(bb_max.z, p.z);
00149 }
00150
00151 inline float getCornerX(int i) const { return (i & 0x01)==0 ? bb_min.x : bb_max.x; }
00152 inline float getCornerY(int i) const { return (i & 0x02)==0 ? bb_min.y : bb_max.y; }
00153 inline float getCornerZ(int i) const { return (i & 0x04)==0 ? bb_min.z : bb_max.z; }
00154
00155 void setBBFromOrderInParent(const TNode &parent, int my_child_index)
00156 {
00157
00158 switch (my_child_index)
00159 {
00160 case 0:
00161 bb_min = parent.bb_min;
00162 bb_max = parent.center;
00163 break;
00164 case 1:
00165 bb_min.x = parent.center.x; bb_max.x = parent.bb_max.x;
00166 bb_min.y = parent.bb_min.y; bb_max.y = parent.center.y;
00167 bb_min.z = parent.bb_min.z; bb_max.z = parent.center.z;
00168 break;
00169 case 2:
00170 bb_min.x = parent.bb_min.x; bb_max.x = parent.center.x;
00171 bb_min.y = parent.center.y; bb_max.y = parent.bb_max.y;
00172 bb_min.z = parent.bb_min.z; bb_max.z = parent.center.z;
00173 break;
00174 case 3:
00175 bb_min.x = parent.center.x; bb_max.x = parent.bb_max.x;
00176 bb_min.y = parent.center.y; bb_max.y = parent.bb_max.y;
00177 bb_min.z = parent.bb_min.z; bb_max.z = parent.center.z;
00178 break;
00179 case 4:
00180 bb_min.x = parent.bb_min.x; bb_max.x = parent.center.x;
00181 bb_min.y = parent.bb_min.y; bb_max.y = parent.center.y;
00182 bb_min.z = parent.center.z; bb_max.z = parent.bb_max.z;
00183 break;
00184 case 5:
00185 bb_min.x = parent.center.x; bb_max.x = parent.bb_max.x;
00186 bb_min.y = parent.bb_min.y; bb_max.y = parent.center.y;
00187 bb_min.z = parent.center.z; bb_max.z = parent.bb_max.z;
00188 break;
00189 case 6:
00190 bb_min.x = parent.bb_min.x; bb_max.x = parent.center.x;
00191 bb_min.y = parent.center.y; bb_max.y = parent.bb_max.y;
00192 bb_min.z = parent.center.z; bb_max.z = parent.bb_max.z;
00193 break;
00194 case 7:
00195 bb_min = parent.center;
00196 bb_max = parent.bb_max;
00197 break;
00198 default: throw std::runtime_error("my_child_index!=[0,7]");
00199 }
00200 }
00201 };
00202
00203 struct OPENGL_IMPEXP TRenderQueueElement
00204 {
00205 inline TRenderQueueElement(const size_t id, float area_sq) : node_id(id), render_area_sqpixels(area_sq) { }
00206
00207 size_t node_id;
00208 float render_area_sqpixels;
00209 };
00210 mutable std::vector<TRenderQueueElement> m_render_queue;
00211
00212
00213 bool m_octree_has_to_rebuild_all;
00214 std::deque<TNode> m_octree_nodes;
00215
00216
00217 volatile mutable size_t m_visible_octree_nodes, m_visible_octree_nodes_ongoing;
00218
00219
00220 void octree_recursive_render(
00221 size_t node_idx,
00222 const mrpt::opengl::gl_utils::TRenderInfo &ri,
00223 TPixelCoordf cr_px[8],
00224 float cr_z[8],
00225 bool corners_are_all_computed = true,
00226 bool trust_me_youre_visible = false,
00227 float approx_area_sqpixels = 0
00228 ) const
00229 {
00230 const TNode &node = m_octree_nodes[node_idx];
00231
00232 if (!corners_are_all_computed)
00233 {
00234 for (int i=0;i<8;i++)
00235 {
00236
00237 ri.projectPointPixels(
00238 node.getCornerX(i),node.getCornerY(i),node.getCornerZ(i),
00239 cr_px[i].x,cr_px[i].y,cr_z[i]);
00240 }
00241 }
00242
00243 TPixelCoordf px_min( std::numeric_limits<float>::max(),std::numeric_limits<float>::max()), px_max(-std::numeric_limits<float>::max(),-std::numeric_limits<float>::max());
00244 if (!trust_me_youre_visible)
00245 {
00246
00247 for (int i=0;i<8;i++)
00248 {
00249 keep_min(px_min.x,cr_px[i].x); keep_min(px_min.y,cr_px[i].y);
00250 keep_max(px_max.x,cr_px[i].x); keep_max(px_max.y,cr_px[i].y);
00251 }
00252
00253 const bool any_cr_zs_neg = (cr_z[0]<0 ||cr_z[1]<0 ||cr_z[2]<0 ||cr_z[3]<0 ||cr_z[4]<0 ||cr_z[5]<0 ||cr_z[6]<0 ||cr_z[7]<0);
00254 const bool any_cr_zs_pos = (cr_z[0]>0 ||cr_z[1]>0 ||cr_z[2]>0 ||cr_z[3]>0 ||cr_z[4]>0 ||cr_z[5]>0 ||cr_z[6]>0 ||cr_z[7]>0);
00255 const bool box_crosses_image_plane = any_cr_zs_pos && any_cr_zs_neg;
00256
00257
00258
00259 if (!box_crosses_image_plane && ( px_min.x>=ri.vp_width || px_min.y>=ri.vp_height || px_max.x<0 || px_max.y<0) )
00260 return;
00261 }
00262
00263
00264 if (node.is_leaf)
00265 {
00266 if (node.all || !node.pts.empty())
00267 {
00268
00269 m_visible_octree_nodes_ongoing++;
00270
00271 const float render_area_sqpixels = trust_me_youre_visible ?
00272 approx_area_sqpixels
00273 :
00274 std::abs(px_min.x-px_max.x) * std::abs(px_min.y-px_max.y);
00275
00276
00277 m_render_queue.push_back( TRenderQueueElement(node_idx,render_area_sqpixels) );
00278 }
00279 }
00280 else
00281 {
00282
00283
00284 bool children_are_all_visible_for_sure = true;
00285
00286 if (!trust_me_youre_visible)
00287 {
00288 for (int i=0;i<8;i++)
00289 {
00290 if (!( cr_px[i].x>=0 && cr_px[i].y>=0 && cr_px[i].x<ri.vp_width && cr_px[i].y<ri.vp_height ))
00291 {
00292 children_are_all_visible_for_sure = false;
00293 break;
00294 }
00295 }
00296 }
00297
00298
00299 if (children_are_all_visible_for_sure)
00300 {
00301 TPixelCoordf child_cr_px[8];
00302 float child_cr_z[8];
00303
00304
00305 const float approx_child_area = trust_me_youre_visible ?
00306 approx_area_sqpixels/8.0f
00307 :
00308 std::abs(px_min.x-px_max.x) * std::abs(px_min.y-px_max.y) / 8.0f;
00309
00310 for (int i=0;i<8;i++)
00311 this->octree_recursive_render(node.child_id[i],ri,child_cr_px, child_cr_z, true, true, approx_child_area); \
00312 }
00313 else
00314 {
00315
00316 const TPoint3Df p_Xm_Ym_Zm ( node.bb_min.x, node.bb_min.y, node.bb_min.z );
00317 const TPoint3Df p_X0_Ym_Zm ( node.center.x, node.bb_min.y, node.bb_min.z );
00318 const TPoint3Df p_Xp_Ym_Zm ( node.bb_max.x, node.bb_min.y, node.bb_min.z );
00319 const TPoint3Df p_Xm_Y0_Zm ( node.bb_min.x, node.center.y, node.bb_min.z );
00320 const TPoint3Df p_X0_Y0_Zm ( node.center.x, node.center.y, node.bb_min.z );
00321 const TPoint3Df p_Xp_Y0_Zm ( node.bb_max.x, node.center.y, node.bb_min.z );
00322 const TPoint3Df p_Xm_Yp_Zm ( node.bb_min.x, node.bb_max.y, node.bb_min.z );
00323 const TPoint3Df p_X0_Yp_Zm ( node.center.x, node.bb_max.y, node.bb_min.z );
00324 const TPoint3Df p_Xp_Yp_Zm ( node.bb_max.x, node.bb_max.y, node.bb_min.z );
00325
00326 const TPoint3Df p_Xm_Ym_Z0 ( node.bb_min.x, node.bb_min.y, node.center.z );
00327 const TPoint3Df p_X0_Ym_Z0 ( node.center.x, node.bb_min.y, node.center.z );
00328 const TPoint3Df p_Xp_Ym_Z0 ( node.bb_max.x, node.bb_min.y, node.center.z );
00329 const TPoint3Df p_Xm_Y0_Z0 ( node.bb_min.x, node.center.y, node.center.z );
00330 const TPoint3Df p_X0_Y0_Z0 ( node.center.x, node.center.y, node.center.z );
00331 const TPoint3Df p_Xp_Y0_Z0 ( node.bb_max.x, node.center.y, node.center.z );
00332 const TPoint3Df p_Xm_Yp_Z0 ( node.bb_min.x, node.bb_max.y, node.center.z );
00333 const TPoint3Df p_X0_Yp_Z0 ( node.center.x, node.bb_max.y, node.center.z );
00334 const TPoint3Df p_Xp_Yp_Z0 ( node.bb_max.x, node.bb_max.y, node.center.z );
00335
00336 const TPoint3Df p_Xm_Ym_Zp ( node.bb_min.x, node.bb_min.y, node.bb_max.z );
00337 const TPoint3Df p_X0_Ym_Zp ( node.center.x, node.bb_min.y, node.bb_max.z );
00338 const TPoint3Df p_Xp_Ym_Zp ( node.bb_min.x, node.bb_min.y, node.bb_max.z );
00339 const TPoint3Df p_Xm_Y0_Zp ( node.bb_min.x, node.center.y, node.bb_max.z );
00340 const TPoint3Df p_X0_Y0_Zp ( node.center.x, node.center.y, node.bb_max.z );
00341 const TPoint3Df p_Xp_Y0_Zp ( node.bb_max.x, node.center.y, node.bb_max.z );
00342 const TPoint3Df p_Xm_Yp_Zp ( node.bb_min.x, node.bb_max.y, node.bb_max.z );
00343 const TPoint3Df p_X0_Yp_Zp ( node.center.x, node.bb_max.y, node.bb_max.z );
00344 const TPoint3Df p_Xp_Yp_Zp ( node.bb_max.x, node.bb_max.y, node.bb_max.z );
00345
00346
00347 #define PROJ_SUB_NODE(POSTFIX) \
00348 TPixelCoordf px_##POSTFIX; \
00349 float depth_##POSTFIX; \
00350 ri.projectPointPixels( p_##POSTFIX.x, p_##POSTFIX.y, p_##POSTFIX.z, px_##POSTFIX.x,px_##POSTFIX.y,depth_##POSTFIX);
00351
00352 #define PROJ_SUB_NODE_ALREADY_DONE(INDEX, POSTFIX) \
00353 const TPixelCoordf px_##POSTFIX = cr_px[INDEX]; \
00354 float depth_##POSTFIX = cr_z[INDEX];
00355
00356 PROJ_SUB_NODE_ALREADY_DONE(0,Xm_Ym_Zm)
00357 PROJ_SUB_NODE(X0_Ym_Zm)
00358 PROJ_SUB_NODE_ALREADY_DONE(1, Xp_Ym_Zm)
00359
00360 PROJ_SUB_NODE(Xm_Y0_Zm)
00361 PROJ_SUB_NODE(X0_Y0_Zm)
00362 PROJ_SUB_NODE(Xp_Y0_Zm)
00363
00364 PROJ_SUB_NODE_ALREADY_DONE(2, Xm_Yp_Zm)
00365 PROJ_SUB_NODE(X0_Yp_Zm)
00366 PROJ_SUB_NODE_ALREADY_DONE(3, Xp_Yp_Zm)
00367
00368 PROJ_SUB_NODE(Xm_Ym_Z0)
00369 PROJ_SUB_NODE(X0_Ym_Z0)
00370 PROJ_SUB_NODE(Xp_Ym_Z0)
00371 PROJ_SUB_NODE(Xm_Y0_Z0)
00372 PROJ_SUB_NODE(X0_Y0_Z0)
00373 PROJ_SUB_NODE(Xp_Y0_Z0)
00374 PROJ_SUB_NODE(Xm_Yp_Z0)
00375 PROJ_SUB_NODE(X0_Yp_Z0)
00376 PROJ_SUB_NODE(Xp_Yp_Z0)
00377
00378 PROJ_SUB_NODE_ALREADY_DONE(4, Xm_Ym_Zp)
00379 PROJ_SUB_NODE(X0_Ym_Zp)
00380 PROJ_SUB_NODE_ALREADY_DONE(5, Xp_Ym_Zp)
00381
00382 PROJ_SUB_NODE(Xm_Y0_Zp)
00383 PROJ_SUB_NODE(X0_Y0_Zp)
00384 PROJ_SUB_NODE(Xp_Y0_Zp)
00385
00386 PROJ_SUB_NODE_ALREADY_DONE(6, Xm_Yp_Zp)
00387 PROJ_SUB_NODE(X0_Yp_Zp)
00388 PROJ_SUB_NODE_ALREADY_DONE(7, Xp_Yp_Zp)
00389
00390
00391 #define DO_RECURSE_CHILD(INDEX, SEQ0,SEQ1,SEQ2,SEQ3,SEQ4,SEQ5,SEQ6,SEQ7) \
00392 { \
00393 TPixelCoordf child_cr_px[8] = { px_##SEQ0,px_##SEQ1,px_##SEQ2,px_##SEQ3,px_##SEQ4,px_##SEQ5,px_##SEQ6,px_##SEQ7 }; \
00394 float child_cr_z[8] = { depth_##SEQ0,depth_##SEQ1,depth_##SEQ2,depth_##SEQ3,depth_##SEQ4,depth_##SEQ5,depth_##SEQ6,depth_##SEQ7 }; \
00395 this->octree_recursive_render(node.child_id[INDEX],ri,child_cr_px, child_cr_z); \
00396 }
00397
00398
00399 DO_RECURSE_CHILD(0, Xm_Ym_Zm, X0_Ym_Zm, Xm_Y0_Zm, X0_Y0_Zm, Xm_Ym_Z0, X0_Ym_Z0, Xm_Y0_Z0, X0_Y0_Z0 )
00400 DO_RECURSE_CHILD(1, X0_Ym_Zm, Xp_Ym_Zm, X0_Y0_Zm, Xp_Y0_Zm, X0_Ym_Z0, Xp_Ym_Z0, X0_Y0_Z0, Xp_Y0_Z0 )
00401 DO_RECURSE_CHILD(2, Xm_Y0_Zm, X0_Y0_Zm, Xm_Yp_Zm, X0_Yp_Zm, Xm_Y0_Z0, X0_Y0_Z0, Xm_Yp_Z0, X0_Yp_Z0 )
00402 DO_RECURSE_CHILD(3, X0_Y0_Zm, Xp_Y0_Zm, X0_Yp_Zm, Xp_Yp_Zm, X0_Y0_Z0, Xp_Y0_Z0, X0_Yp_Z0, Xp_Yp_Z0 )
00403 DO_RECURSE_CHILD(4, Xm_Ym_Z0, X0_Ym_Z0, Xm_Y0_Z0, X0_Y0_Z0, Xm_Ym_Zp, X0_Ym_Zp, Xm_Y0_Zp, X0_Y0_Zp )
00404 DO_RECURSE_CHILD(5, X0_Ym_Z0, Xp_Ym_Z0, X0_Y0_Z0, Xp_Y0_Z0, X0_Ym_Zp, Xp_Ym_Zp, X0_Y0_Zp, Xp_Y0_Zp )
00405 DO_RECURSE_CHILD(6, Xm_Y0_Z0, X0_Y0_Z0, Xm_Yp_Z0, X0_Yp_Z0, Xm_Y0_Zp, X0_Y0_Zp, Xm_Yp_Zp, X0_Yp_Zp )
00406 DO_RECURSE_CHILD(7, X0_Y0_Z0, Xp_Y0_Z0, X0_Yp_Z0, Xp_Yp_Z0, X0_Y0_Zp, Xp_Y0_Zp, X0_Yp_Zp, Xp_Yp_Zp )
00407 #undef DO_RECURSE_CHILD
00408 #undef PROJ_SUB_NODE
00409 #undef PROJ_SUB_NODE_ALREADY_DONE
00410 }
00411 }
00412 }
00413
00414
00415 void internal_octree_assure_uptodate()
00416 {
00417 if (!m_octree_has_to_rebuild_all) return;
00418 m_octree_has_to_rebuild_all = false;
00419
00420
00421 m_octree_nodes.assign(1, TNode() );
00422
00423
00424 internal_recursive_split( OCTREE_ROOT_NODE, true );
00425 }
00426
00427
00428
00429
00430 void internal_recursive_split(const size_t node_id, const bool all_pts = false)
00431 {
00432 TNode &node = m_octree_nodes[node_id];
00433 const size_t N = all_pts ? octree_derived().size() : node.pts.size();
00434
00435 const bool has_to_compute_bb = (node_id ==OCTREE_ROOT_NODE);
00436
00437 if (N<=mrpt::global_settings::OCTREE_RENDER_MAX_POINTS_PER_NODE)
00438 {
00439
00440 node.is_leaf = true;
00441 node.all = all_pts;
00442
00443
00444 if (has_to_compute_bb)
00445 {
00446 if (all_pts)
00447 for (size_t i=0;i<N;i++) node.update_bb( octree_derived().getPointf(i) );
00448 else for (size_t i=0;i<N;i++) node.update_bb( octree_derived().getPointf(node.pts[i]) );
00449 }
00450 }
00451 else
00452 {
00453
00454
00455 mrpt::math::TPoint3Df mean(0,0,0);
00456 if (all_pts)
00457 for (size_t i=0;i<N;i++)
00458 {
00459 mrpt::math::TPoint3Df p = octree_derived().getPointf(i);
00460 mean+= p;
00461 if (has_to_compute_bb) node.update_bb( p );
00462 }
00463 else
00464 for (size_t i=0;i<N;i++)
00465 {
00466 mrpt::math::TPoint3Df p = octree_derived().getPointf(node.pts[i]);
00467 mean+= p;
00468 if (has_to_compute_bb) node.update_bb( p );
00469 }
00470
00471
00472 node.is_leaf = false;
00473 node.center = mean * (1.0f/N);
00474
00475
00476 const size_t children_idx_base = m_octree_nodes.size();
00477 m_octree_nodes.resize(children_idx_base + 8 );
00478 for (int i=0;i<8;i++)
00479 node.child_id[i] = children_idx_base + i;
00480
00481
00482 for (int i=0;i<8;i++)
00483 m_octree_nodes[children_idx_base + i].setBBFromOrderInParent(node,i);
00484
00485
00486 const mrpt::math::TPoint3Df &c = node.center;
00487 for (size_t j=0;j<N;j++)
00488 {
00489 const size_t i = all_pts ? j : node.pts[j];
00490 const TPoint3Df p = octree_derived().getPointf(i);
00491 if (p.z<c.z)
00492 {
00493 if (p.y<c.y)
00494 {
00495 if (p.x<c.x)
00496 m_octree_nodes[children_idx_base+ 0 ].pts.push_back(i);
00497 else m_octree_nodes[children_idx_base+ 1 ].pts.push_back(i);
00498 }
00499 else
00500 {
00501 if (p.x<c.x)
00502 m_octree_nodes[children_idx_base+ 2 ].pts.push_back(i);
00503 else m_octree_nodes[children_idx_base+ 3 ].pts.push_back(i);
00504 }
00505 }
00506 else
00507 {
00508 if (p.y<c.y)
00509 {
00510 if (p.x<c.x)
00511 m_octree_nodes[children_idx_base+ 4 ].pts.push_back(i);
00512 else m_octree_nodes[children_idx_base+ 5 ].pts.push_back(i);
00513 }
00514 else
00515 {
00516 if (p.x<c.x)
00517 m_octree_nodes[children_idx_base+ 6 ].pts.push_back(i);
00518 else m_octree_nodes[children_idx_base+ 7 ].pts.push_back(i);
00519 }
00520 }
00521 }
00522
00523
00524 {
00525 std::vector<size_t> emptyVec;
00526 node.pts.swap(emptyVec);
00527 }
00528
00529
00530 for (int i=0;i<8;i++)
00531 internal_recursive_split( node.child_id[i] );
00532 }
00533 }
00534
00535 public:
00536
00537
00538 size_t octree_get_node_count() const { return m_octree_nodes.size(); }
00539
00540
00541 size_t octree_get_visible_nodes() const { return m_visible_octree_nodes; }
00542
00543
00544 inline void octree_mark_as_outdated() { m_octree_has_to_rebuild_all=true; }
00545
00546
00547
00548 void octree_get_graphics_boundingboxes(
00549 mrpt::opengl::CSetOfObjects &gl_bb,
00550 const double lines_width = 1,
00551 const TColorf lines_color = TColorf(1,1,1) ) const
00552 {
00553 octree_assure_uptodate();
00554 gl_bb.clear();
00555 for (size_t i=0;i<m_octree_nodes.size();i++)
00556 {
00557 const TNode & node = m_octree_nodes[i];
00558 if (!node.is_leaf) continue;
00559 mrpt::opengl::CBoxPtr gl_box = mrpt::opengl::CBox::Create();
00560 gl_box->setBoxCorners( mrpt::math::TPoint3D(node.bb_min), mrpt::math::TPoint3D(node.bb_max) );
00561 gl_box->setColor(lines_color);
00562 gl_box->setLineWidth(lines_width);
00563 gl_box->setWireframe(true);
00564 gl_bb.insert(gl_box);
00565 }
00566 }
00567
00568
00569
00570 void octree_debug_dump_tree(std::ostream &o) const
00571 {
00572 o << "Octree nodes: " << m_octree_nodes.size() << std::endl;
00573 size_t total_elements = 0;
00574 for (size_t i=0;i<m_octree_nodes.size();i++)
00575 {
00576 const TNode & node = m_octree_nodes[i];
00577
00578 o << "Node #" << i << ": ";
00579 if (node.is_leaf)
00580 {
00581 o << "leaf, ";
00582 if (node.all) { o << "(all)\n"; total_elements+=octree_derived().size(); }
00583 else { o << node.pts.size() << " elements; "; total_elements+=node.pts.size(); }
00584
00585 }
00586 else
00587 {
00588 o << "parent, center=(" << node.center.x << "," << node.center.y<<","<<node.center.z<<"), children: "
00589 << node.child_id[0] << ","<< node.child_id[1] << ","<< node.child_id[2] << ","<< node.child_id[3] << ","
00590 << node.child_id[4] << ","<< node.child_id[5] << ","<< node.child_id[6] << ","<< node.child_id[7] << "; ";
00591 }
00592 o << " bb: (" << node.bb_min.x << ","<< node.bb_min.y << ","<< node.bb_min.z << ")-("
00593 << node.bb_max.x << ","<< node.bb_max.y << ","<< node.bb_max.z << ")\n";
00594 }
00595 o << "Total elements in all nodes: " << total_elements << std::endl;
00596 }
00597
00598 };
00599
00600 }
00601 }
00602 #endif