9 #ifndef opengl_COctreePointRenderer_H    10 #define opengl_COctreePointRenderer_H    20         namespace global_settings
    44                 template <
class Derived>
    68                         inline const Derived & 
octree_derived()
 const { 
return *
static_cast<const Derived*
>(
this); }
   121                                         bb_min( 
std::numeric_limits<float>::max(), 
std::numeric_limits<float>::max(), 
std::numeric_limits<float>::max() ),
   122                                         bb_max(-
std::numeric_limits<float>::max(),-
std::numeric_limits<float>::max(),-
std::numeric_limits<float>::max() ),
   146                                 inline float getCornerX(
int i)
 const { 
return (i & 0x01)==0 ? bb_min.
x : bb_max.
x; }
   147                                 inline float getCornerY(
int i)
 const { 
return (i & 0x02)==0 ? bb_min.
y : bb_max.
y; }
   148                                 inline float getCornerZ(
int i)
 const { 
return (i & 0x04)==0 ? bb_min.
z : bb_max.
z; }
   153                                         switch (my_child_index)
   193                                         default: 
throw std::runtime_error(
"my_child_index!=[0,7]");
   223                                 bool         corners_are_all_computed = 
true,
   224                                 bool         trust_me_youre_visible   = 
false,
   225                                 float        approx_area_sqpixels     = 0
   230                                 if (!corners_are_all_computed)
   232                                         for (
int i=0;i<8;i++)
   236                                                         node.getCornerX(i),node.getCornerY(i),node.getCornerZ(i),
   237                                                         cr_px[i].
x,cr_px[i].
y,cr_z[i]);
   241                                 mrpt::utils::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());
   242                                 if (!trust_me_youre_visible)
   245                                         for (
int i=0;i<8;i++)
   251                                         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);
   252                                         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);
   253                                         const bool box_crosses_image_plane = any_cr_zs_pos && any_cr_zs_neg;
   257                                         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) )
   264                                         if (node.all || !node.pts.empty())
   269                                                 float render_area_sqpixels = trust_me_youre_visible ?
   272                                                         std::abs(px_min.x-px_max.
x) * std::abs(px_min.y-px_max.
y);
   273                                                 render_area_sqpixels = std::max(1.0f, render_area_sqpixels);
   275                                                 m_render_queue.push_back( TRenderQueueElement(node_idx,render_area_sqpixels) );
   282                                         bool children_are_all_visible_for_sure = 
true;
   284                                         if (!trust_me_youre_visible) 
   286                                                 for (
int i=0;i<8;i++)
   290                                                                 children_are_all_visible_for_sure = 
false;
   297                                         if (children_are_all_visible_for_sure)
   303                                                 const float approx_child_area = trust_me_youre_visible ?
   304                                                         approx_area_sqpixels/8.0f
   306                                                         std::abs(px_min.x-px_max.
x) * std::abs(px_min.y-px_max.
y) / 8.0f;
   308                                                 for (
int i=0;i<8;i++)
   314 #pragma clang diagnostic push  // clang complains about unused vars (becase it doesn't realize of the macros?)   315 #pragma clang diagnostic ignored "-Wunused-variable"   350 #define PROJ_SUB_NODE(POSTFIX) \   351                                                 mrpt::utils::TPixelCoordf px_##POSTFIX; \   352                                                 float        depth_##POSTFIX; \   353                                                 ri.projectPointPixels( p_##POSTFIX.x, p_##POSTFIX.y, p_##POSTFIX.z, px_##POSTFIX.x,px_##POSTFIX.y,depth_##POSTFIX);   355 #define PROJ_SUB_NODE_ALREADY_DONE(INDEX, POSTFIX) \   356                                                 const mrpt::utils::TPixelCoordf px_##POSTFIX = cr_px[INDEX]; \   357                                                 float        depth_##POSTFIX = cr_z[INDEX];   394 #define DO_RECURSE_CHILD(INDEX, SEQ0,SEQ1,SEQ2,SEQ3,SEQ4,SEQ5,SEQ6,SEQ7) \   396                                                         mrpt::utils::TPixelCoordf child_cr_px[8] = { px_##SEQ0,px_##SEQ1,px_##SEQ2,px_##SEQ3,px_##SEQ4,px_##SEQ5,px_##SEQ6,px_##SEQ7 }; \   397                                                         float        child_cr_z[8]  = { depth_##SEQ0,depth_##SEQ1,depth_##SEQ2,depth_##SEQ3,depth_##SEQ4,depth_##SEQ5,depth_##SEQ6,depth_##SEQ7 }; \   398                                                         this->octree_recursive_render(node.child_id[INDEX],ri,child_cr_px, child_cr_z); \   402                                                 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 )
   403                                                 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 )
   404                                                 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 )
   405                                                 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 )
   406                                                 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 )
   407                                                 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 )
   408                                                 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 )
   409                                                 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 )
   410 #undef DO_RECURSE_CHILD   412 #undef PROJ_SUB_NODE_ALREADY_DONE   415 #pragma clang diagnostic pop   440                                 const size_t N = all_pts ? 
octree_derived().size() : node.pts.size();
   451                                         if (has_to_compute_bb)
   454                                                          for (
size_t i=0;i<N;i++) node.update_bb( 
octree_derived().getPointf(i) );
   455                                                 else for (
size_t i=0;i<N;i++) node.update_bb( 
octree_derived().getPointf(node.pts[i]) );
   464                                                 for (
size_t i=0;i<N;i++)
   468                                                         if (has_to_compute_bb) node.update_bb( 
p );
   471                                                 for (
size_t i=0;i<N;i++)
   475                                                         if (has_to_compute_bb) node.update_bb( 
p );
   479                                         node.is_leaf = 
false;
   480                                         node.center  = 
mean * (1.0f/N);
   485                                         for (
int i=0;i<8;i++)
   486                                                 node.child_id[i] = children_idx_base + i;
   489                                         for (
int i=0;i<8;i++)
   490                                                 m_octree_nodes[children_idx_base + i].setBBFromOrderInParent(node,i);
   494                                         for (
size_t j=0;j<N;j++)
   496                                                 const size_t i = all_pts ? j : node.pts[j];
   532                                                 std::vector<size_t> emptyVec;
   533                                                 node.pts.swap(emptyVec);  
   537                                         for (
int i=0;i<8;i++)
   558                                 const double lines_width = 1,
   560                                 const bool draw_solid_boxes = 
false )
 const   567                                         if (!node.is_leaf) 
continue;
   570                                         gl_box->setColor(lines_color);
   571                                         gl_box->setLineWidth(lines_width);
   572                                         gl_box->setWireframe(!draw_solid_boxes);
   582                                 size_t total_elements = 0;
   587                                         o << 
"Node #" << i << 
": ";
   591                                                 if (node.all) { o << 
"(all)\n"; total_elements+=
octree_derived().size(); }
   592                                                 else { o << node.pts.size() << 
" elements; "; total_elements+=node.pts.size(); }
   597                                                 o << 
"parent, center=(" << node.center.x << 
"," << node.center.y<<
","<<node.center.z<<
"), children: "   598                                                   << node.child_id[0] << 
","<< node.child_id[1] << 
","<< node.child_id[2] << 
","<< node.child_id[3] << 
","   599                                                   << node.child_id[4] << 
","<< node.child_id[5] << 
","<< node.child_id[6] << 
","<< node.child_id[7] << 
"; ";
   601                                         o << 
" bb: (" << node.bb_min.x << 
","<< node.bb_min.y << 
","<< node.bb_min.z << 
")-("   602                                                       << node.bb_max.x << 
","<< node.bb_max.y << 
","<< node.bb_max.z << 
")\n";
   604                                 o << 
"Total elements in all nodes: " << total_elements << std::endl;
 void clear()
Clear the list of objects in the scene, deleting objects' memory. 
 
The structure for each octree spatial node. 
 
bool is_leaf
true: it's a leaf and pts has valid indices; false: children is valid. 
 
A pair (x,y) of pixel coordinates (subpixel resolution). 
 
void update_bb(const mrpt::math::TPoint3Df &p)
update bounding box with a new point: 
 
volatile size_t m_visible_octree_nodes_ongoing
 
bool all
true: All elements in the reference object; false: only those in pts 
 
A set of object, which are referenced to the coordinates framework established in this object...
 
size_t octree_get_visible_nodes() const
Return the number of visible octree nodes in the last render event. 
 
#define MRPT_MAKE_ALIGNED_OPERATOR_NEW
 
float getCornerZ(int i) const
 
volatile size_t m_visible_octree_nodes
 
std::deque< TYPE1, Eigen::aligned_allocator< TYPE1 > > deque_t
 
const Derived & octree_derived() const
 
void keep_min(T &var, const K test_val)
If the second argument is below the first one, set the first argument to this lower value...
 
void internal_recursive_split(const size_t node_id, const bool all_pts=false)
 
Template class that implements the data structure and algorithms for Octree-based efficient rendering...
 
int vp_height
Rendering viewport geometry (in pixels) 
 
COctreePointRenderer()
Default ctor. 
 
TRenderQueueElement(const size_t id, float area_sq)
 
Lightweight 3D point (float version). 
 
size_t octree_get_node_count() const
Return the number of octree nodes (all of them, including the empty ones) 
 
OPENGL_IMPEXP float OCTREE_RENDER_MAX_DENSITY_POINTS_PER_SQPIXEL
Default value = 0.01 points/px^2. 
 
mrpt::math::TPoint3Df center
[is_leaf=false] The center of the node, whose coordinates are used to decide between the 8 children n...
 
Information about the rendering process being issued. 
 
Derived & octree_derived()
 
void octree_render(const mrpt::opengl::gl_utils::TRenderInfo &ri) const
Render the entire octree recursively. 
 
mrpt::math::TPoint3Df bb_max
 
void insert(const CRenderizablePtr &newObject)
Insert a new object to the list. 
 
std::vector< TRenderQueueElement > m_render_queue
The list of elements that really are visible and will be rendered. 
 
COctreePointRenderer(const COctreePointRenderer &)
Copy ctor. 
 
bool m_octree_has_to_rebuild_all
 
#define PROJ_SUB_NODE(POSTFIX)
 
void octree_mark_as_outdated()
Called from the derived class (or the user) to indicate we have/want to rebuild the entire node tree ...
 
void octree_debug_dump_tree(std::ostream &o) const
Used for debug only. 
 
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries. 
 
std::vector< size_t > pts
Point indices in the derived class that fall into this node. 
 
OPENGL_IMPEXP size_t OCTREE_RENDER_MAX_POINTS_PER_NODE
Default value = 1e5. 
 
mrpt::aligned_containers< TNode >::deque_t m_octree_nodes
First one [0] is always the root node. 
 
void internal_octree_assure_uptodate()
 
void octree_get_graphics_boundingboxes(mrpt::opengl::CSetOfObjects &gl_bb, const double lines_width=1, const mrpt::utils::TColorf &lines_color=mrpt::utils::TColorf(1, 1, 1), const bool draw_solid_boxes=false) const
Returns a graphical representation of all the bounding boxes of the octree (leaf) nodes...
 
void octree_getBoundingBox(mrpt::math::TPoint3D &bb_min, mrpt::math::TPoint3D &bb_max) const
 
float getCornerY(int i) const
 
A RGB color - floats in the range [0,1]. 
 
#define DO_RECURSE_CHILD(INDEX, SEQ0, SEQ1, SEQ2, SEQ3, SEQ4, SEQ5, SEQ6, SEQ7)
 
float render_area_sqpixels
The approximate size of the octree on the screen (squared pixels). 
 
void octree_recursive_render(size_t node_idx, const mrpt::opengl::gl_utils::TRenderInfo &ri, mrpt::utils::TPixelCoordf cr_px[8], float cr_z[8], bool corners_are_all_computed=true, bool trust_me_youre_visible=false, float approx_area_sqpixels=0) const
Render a given node. 
 
void projectPointPixels(float x, float y, float z, float &proj_x_px, float &proj_y_px, float &proj_z_depth) const
Exactly like projectPoint but the (x,y) projected coordinates are given in pixels instead of normaliz...
 
void setBBFromOrderInParent(const TNode &parent, int my_child_index)
 
size_t node_id
The node ID to render. 
 
void octree_assure_uptodate() const
Must be called at children class' render() previously to octree_render() 
 
void keep_max(T &var, const K test_val)
If the second argument is above the first one, set the first argument to this higher value...
 
EIGEN_STRONG_INLINE double mean() const
Computes the mean of the entire matrix. 
 
#define PROJ_SUB_NODE_ALREADY_DONE(INDEX, POSTFIX)
 
float getCornerX(int i) const
 
mrpt::math::TPoint3Df bb_min