28 #ifndef opengl_COctreePointRenderer_H
29 #define opengl_COctreePointRenderer_H
38 namespace global_settings
58 using namespace mrpt::utils;
64 template <
class Derived>
70 m_octree_has_to_rebuild_all(true),
71 m_visible_octree_nodes(0),
72 m_visible_octree_nodes_ongoing(0)
77 m_octree_has_to_rebuild_all(true)
81 enum { OCTREE_ROOT_NODE = 0 };
86 inline const Derived &
octree_derived()
const {
return *
static_cast<const Derived*
>(
this); }
89 inline void octree_assure_uptodate()
const
99 m_visible_octree_nodes_ongoing = 0;
102 m_render_queue.clear();
103 m_render_queue.reserve(m_octree_nodes.size());
107 octree_recursive_render(OCTREE_ROOT_NODE,ri, cr_px, cr_z,
false );
109 m_visible_octree_nodes = m_visible_octree_nodes_ongoing;
112 for (
size_t i=0;i<m_render_queue.size();i++)
114 const TNode & node = m_octree_nodes[ m_render_queue[i].node_id ];
115 octree_derived().render_subset( node.all,node.pts,m_render_queue[i].render_area_sqpixels);
127 bb_min( std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max() ),
128 bb_max(-std::numeric_limits<float>::max(),-std::numeric_limits<float>::max(),-std::numeric_limits<float>::max() )
151 inline float getCornerX(
int i)
const {
return (i & 0x01)==0 ? bb_min.x : bb_max.x; }
152 inline float getCornerY(
int i)
const {
return (i & 0x02)==0 ? bb_min.y : bb_max.y; }
153 inline float getCornerZ(
int i)
const {
return (i & 0x04)==0 ? bb_min.z : bb_max.z; }
155 void setBBFromOrderInParent(
const TNode &parent,
int my_child_index)
158 switch (my_child_index)
198 default:
throw std::runtime_error(
"my_child_index!=[0,7]");
205 inline TRenderQueueElement(
const size_t id,
float area_sq) : node_id(id), render_area_sqpixels(area_sq) { }
220 void octree_recursive_render(
225 bool corners_are_all_computed =
true,
226 bool trust_me_youre_visible =
false,
227 float approx_area_sqpixels = 0
230 const TNode &node = m_octree_nodes[node_idx];
232 if (!corners_are_all_computed)
234 for (
int i=0;i<8;i++)
238 node.getCornerX(i),node.getCornerY(i),node.getCornerZ(i),
239 cr_px[i].
x,cr_px[i].
y,cr_z[i]);
243 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());
244 if (!trust_me_youre_visible)
247 for (
int i=0;i<8;i++)
253 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);
254 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);
255 const bool box_crosses_image_plane = any_cr_zs_pos && any_cr_zs_neg;
259 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) )
266 if (node.all || !node.pts.empty())
269 m_visible_octree_nodes_ongoing++;
271 const float render_area_sqpixels = trust_me_youre_visible ?
277 m_render_queue.push_back( TRenderQueueElement(node_idx,render_area_sqpixels) );
284 bool children_are_all_visible_for_sure =
true;
286 if (!trust_me_youre_visible)
288 for (
int i=0;i<8;i++)
290 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 ))
292 children_are_all_visible_for_sure =
false;
299 if (children_are_all_visible_for_sure)
305 const float approx_child_area = trust_me_youre_visible ?
306 approx_area_sqpixels/8.0f
310 for (
int i=0;i<8;i++)
311 this->octree_recursive_render(node.child_id[i],ri,child_cr_px, child_cr_z,
true,
true, approx_child_area); \
316 const TPoint3Df p_Xm_Ym_Zm ( node.bb_min.x, node.bb_min.y, node.bb_min.z );
317 const TPoint3Df p_X0_Ym_Zm ( node.center.x, node.bb_min.y, node.bb_min.z );
318 const TPoint3Df p_Xp_Ym_Zm ( node.bb_max.x, node.bb_min.y, node.bb_min.z );
319 const TPoint3Df p_Xm_Y0_Zm ( node.bb_min.x, node.center.y, node.bb_min.z );
320 const TPoint3Df p_X0_Y0_Zm ( node.center.x, node.center.y, node.bb_min.z );
321 const TPoint3Df p_Xp_Y0_Zm ( node.bb_max.x, node.center.y, node.bb_min.z );
322 const TPoint3Df p_Xm_Yp_Zm ( node.bb_min.x, node.bb_max.y, node.bb_min.z );
323 const TPoint3Df p_X0_Yp_Zm ( node.center.x, node.bb_max.y, node.bb_min.z );
324 const TPoint3Df p_Xp_Yp_Zm ( node.bb_max.x, node.bb_max.y, node.bb_min.z );
326 const TPoint3Df p_Xm_Ym_Z0 ( node.bb_min.x, node.bb_min.y, node.center.z );
327 const TPoint3Df p_X0_Ym_Z0 ( node.center.x, node.bb_min.y, node.center.z );
328 const TPoint3Df p_Xp_Ym_Z0 ( node.bb_max.x, node.bb_min.y, node.center.z );
329 const TPoint3Df p_Xm_Y0_Z0 ( node.bb_min.x, node.center.y, node.center.z );
330 const TPoint3Df p_X0_Y0_Z0 ( node.center.x, node.center.y, node.center.z );
331 const TPoint3Df p_Xp_Y0_Z0 ( node.bb_max.x, node.center.y, node.center.z );
332 const TPoint3Df p_Xm_Yp_Z0 ( node.bb_min.x, node.bb_max.y, node.center.z );
333 const TPoint3Df p_X0_Yp_Z0 ( node.center.x, node.bb_max.y, node.center.z );
334 const TPoint3Df p_Xp_Yp_Z0 ( node.bb_max.x, node.bb_max.y, node.center.z );
336 const TPoint3Df p_Xm_Ym_Zp ( node.bb_min.x, node.bb_min.y, node.bb_max.z );
337 const TPoint3Df p_X0_Ym_Zp ( node.center.x, node.bb_min.y, node.bb_max.z );
338 const TPoint3Df p_Xp_Ym_Zp ( node.bb_min.x, node.bb_min.y, node.bb_max.z );
339 const TPoint3Df p_Xm_Y0_Zp ( node.bb_min.x, node.center.y, node.bb_max.z );
340 const TPoint3Df p_X0_Y0_Zp ( node.center.x, node.center.y, node.bb_max.z );
341 const TPoint3Df p_Xp_Y0_Zp ( node.bb_max.x, node.center.y, node.bb_max.z );
342 const TPoint3Df p_Xm_Yp_Zp ( node.bb_min.x, node.bb_max.y, node.bb_max.z );
343 const TPoint3Df p_X0_Yp_Zp ( node.center.x, node.bb_max.y, node.bb_max.z );
344 const TPoint3Df p_Xp_Yp_Zp ( node.bb_max.x, node.bb_max.y, node.bb_max.z );
347 #define PROJ_SUB_NODE(POSTFIX) \
348 TPixelCoordf px_##POSTFIX; \
349 float depth_##POSTFIX; \
350 ri.projectPointPixels( p_##POSTFIX.x, p_##POSTFIX.y, p_##POSTFIX.z, px_##POSTFIX.x,px_##POSTFIX.y,depth_##POSTFIX);
352 #define PROJ_SUB_NODE_ALREADY_DONE(INDEX, POSTFIX) \
353 const TPixelCoordf px_##POSTFIX = cr_px[INDEX]; \
354 float depth_##POSTFIX = cr_z[INDEX];
391 #define DO_RECURSE_CHILD(INDEX, SEQ0,SEQ1,SEQ2,SEQ3,SEQ4,SEQ5,SEQ6,SEQ7) \
393 TPixelCoordf child_cr_px[8] = { px_##SEQ0,px_##SEQ1,px_##SEQ2,px_##SEQ3,px_##SEQ4,px_##SEQ5,px_##SEQ6,px_##SEQ7 }; \
394 float child_cr_z[8] = { depth_##SEQ0,depth_##SEQ1,depth_##SEQ2,depth_##SEQ3,depth_##SEQ4,depth_##SEQ5,depth_##SEQ6,depth_##SEQ7 }; \
395 this->octree_recursive_render(node.child_id[INDEX],ri,child_cr_px, child_cr_z); \
399 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 )
400 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 )
401 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 )
402 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 )
403 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 )
404 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 )
405 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 )
406 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 )
407 #undef DO_RECURSE_CHILD
409 #undef PROJ_SUB_NODE_ALREADY_DONE
415 void internal_octree_assure_uptodate()
417 if (!m_octree_has_to_rebuild_all)
return;
418 m_octree_has_to_rebuild_all =
false;
421 m_octree_nodes.assign(1, TNode() );
424 internal_recursive_split( OCTREE_ROOT_NODE,
true );
430 void internal_recursive_split(
const size_t node_id,
const bool all_pts =
false)
432 TNode &node = m_octree_nodes[node_id];
433 const size_t N = all_pts ? octree_derived().size() : node.pts.size();
435 const bool has_to_compute_bb = (node_id ==OCTREE_ROOT_NODE);
444 if (has_to_compute_bb)
447 for (
size_t i=0;i<N;i++) node.update_bb( octree_derived().getPointf(i) );
448 else for (
size_t i=0;i<N;i++) node.update_bb( octree_derived().getPointf(node.pts[i]) );
457 for (
size_t i=0;i<N;i++)
461 if (has_to_compute_bb) node.update_bb( p );
464 for (
size_t i=0;i<N;i++)
468 if (has_to_compute_bb) node.update_bb( p );
472 node.is_leaf =
false;
473 node.center = mean * (1.0f/N);
476 const size_t children_idx_base = m_octree_nodes.size();
477 m_octree_nodes.resize(children_idx_base + 8 );
478 for (
int i=0;i<8;i++)
479 node.child_id[i] = children_idx_base + i;
482 for (
int i=0;i<8;i++)
483 m_octree_nodes[children_idx_base + i].setBBFromOrderInParent(node,i);
487 for (
size_t j=0;j<N;j++)
489 const size_t i = all_pts ? j : node.pts[j];
490 const TPoint3Df p = octree_derived().getPointf(i);
496 m_octree_nodes[children_idx_base+ 0 ].pts.push_back(i);
497 else m_octree_nodes[children_idx_base+ 1 ].pts.push_back(i);
502 m_octree_nodes[children_idx_base+ 2 ].pts.push_back(i);
503 else m_octree_nodes[children_idx_base+ 3 ].pts.push_back(i);
511 m_octree_nodes[children_idx_base+ 4 ].pts.push_back(i);
512 else m_octree_nodes[children_idx_base+ 5 ].pts.push_back(i);
517 m_octree_nodes[children_idx_base+ 6 ].pts.push_back(i);
518 else m_octree_nodes[children_idx_base+ 7 ].pts.push_back(i);
525 std::vector<size_t> emptyVec;
526 node.pts.swap(emptyVec);
530 for (
int i=0;i<8;i++)
531 internal_recursive_split( node.child_id[i] );
548 void octree_get_graphics_boundingboxes(
550 const double lines_width = 1,
553 octree_assure_uptodate();
555 for (
size_t i=0;i<m_octree_nodes.size();i++)
557 const TNode & node = m_octree_nodes[i];
558 if (!node.is_leaf)
continue;
570 void octree_debug_dump_tree(std::ostream &o)
const
572 o <<
"Octree nodes: " << m_octree_nodes.size() << std::endl;
573 size_t total_elements = 0;
574 for (
size_t i=0;i<m_octree_nodes.size();i++)
576 const TNode & node = m_octree_nodes[i];
578 o <<
"Node #" << i <<
": ";
582 if (node.all) { o <<
"(all)\n"; total_elements+=octree_derived().size(); }
583 else { o << node.pts.size() <<
" elements; "; total_elements+=node.pts.size(); }
588 o <<
"parent, center=(" << node.center.x <<
"," << node.center.y<<
","<<node.center.z<<
"), children: "
589 << node.child_id[0] <<
","<< node.child_id[1] <<
","<< node.child_id[2] <<
","<< node.child_id[3] <<
","
590 << node.child_id[4] <<
","<< node.child_id[5] <<
","<< node.child_id[6] <<
","<< node.child_id[7] <<
"; ";
592 o <<
" bb: (" << node.bb_min.x <<
","<< node.bb_min.y <<
","<< node.bb_min.z <<
")-("
593 << node.bb_max.x <<
","<< node.bb_max.y <<
","<< node.bb_max.z <<
")\n";
595 o <<
"Total elements in all nodes: " << total_elements << std::endl;