9 #ifndef opengl_COctreePointRenderer_H    10 #define opengl_COctreePointRenderer_H    21 namespace global_settings
    51 template <
class Derived>
    76         return *
static_cast<const Derived*
>(
this);
   136                   std::numeric_limits<float>::max(),
   137                   std::numeric_limits<float>::max(),
   138                   std::numeric_limits<float>::max()),
   140                   -
std::numeric_limits<float>::max(),
   141                   -
std::numeric_limits<float>::max(),
   142                   -
std::numeric_limits<float>::max())
   196             switch (my_child_index)
   255                     throw std::runtime_error(
"my_child_index!=[0,7]");
   290         bool corners_are_all_computed = 
true,
   291         bool trust_me_youre_visible = 
false,
   292         float approx_area_sqpixels = 0)
 const   296         if (!corners_are_all_computed)
   298             for (
int i = 0; i < 8; i++)
   302                     node.getCornerX(i), node.getCornerY(i), node.getCornerZ(i),
   303                     cr_px[i].
x, cr_px[i].
y, cr_z[i]);
   308             std::numeric_limits<float>::max(),
   309             std::numeric_limits<float>::max()),
   311                 -std::numeric_limits<float>::max(),
   312                 -std::numeric_limits<float>::max());
   313         if (!trust_me_youre_visible)
   316             for (
int i = 0; i < 8; i++)
   324             const bool any_cr_zs_neg =
   325                 (cr_z[0] < 0 || cr_z[1] < 0 || cr_z[2] < 0 || cr_z[3] < 0 ||
   326                  cr_z[4] < 0 || cr_z[5] < 0 || cr_z[6] < 0 || cr_z[7] < 0);
   327             const bool any_cr_zs_pos =
   328                 (cr_z[0] > 0 || cr_z[1] > 0 || cr_z[2] > 0 || cr_z[3] > 0 ||
   329                  cr_z[4] > 0 || cr_z[5] > 0 || cr_z[6] > 0 || cr_z[7] > 0);
   330             const bool box_crosses_image_plane = any_cr_zs_pos && any_cr_zs_neg;
   337                                              px_max.
x < 0 || px_max.
y < 0))
   344             if (node.all || !node.pts.empty())
   350                 float render_area_sqpixels =
   351                     trust_me_youre_visible ? approx_area_sqpixels
   352                                            : std::abs(px_min.x - px_max.
x) *
   353                                                  std::abs(px_min.y - px_max.
y);
   354                 render_area_sqpixels = std::max(1.0f, render_area_sqpixels);
   358                     TRenderQueueElement(node_idx, render_area_sqpixels));
   367             bool children_are_all_visible_for_sure = 
true;
   369             if (!trust_me_youre_visible)  
   371                 for (
int i = 0; i < 8; i++)
   373                     if (!(cr_px[i].x >= 0 && cr_px[i].y >= 0 &&
   377                         children_are_all_visible_for_sure = 
false;
   384             if (children_are_all_visible_for_sure)
   391                 const float approx_child_area =
   392                     trust_me_youre_visible
   393                         ? approx_area_sqpixels / 8.0f
   394                         : std::abs(px_min.x - px_max.
x) *
   395                               std::abs(px_min.y - px_max.
y) / 8.0f;
   397                 for (
int i = 0; i < 8; i++)
   399                         node.child_id[i], ri, child_cr_px, child_cr_z, 
true,
   400                         true, approx_child_area);
   405 #pragma clang diagnostic push  // clang complains about unused vars (becase it   407 #pragma clang diagnostic ignored "-Wunused-variable"   413                     node.bb_min.x, node.bb_min.y, node.bb_min.z);  
   415                     node.center.x, node.bb_min.y, node.bb_min.z);
   417                     node.bb_max.x, node.bb_min.y, node.bb_min.z);  
   419                     node.bb_min.x, node.center.y, node.bb_min.z);
   421                     node.center.x, node.center.y, node.bb_min.z);
   423                     node.bb_max.x, node.center.y, node.bb_min.z);
   425                     node.bb_min.x, node.bb_max.y, node.bb_min.z);  
   427                     node.center.x, node.bb_max.y, node.bb_min.z);
   429                     node.bb_max.x, node.bb_max.y, node.bb_min.z);  
   432                     node.bb_min.x, node.bb_min.y, node.center.z);
   434                     node.center.x, node.bb_min.y, node.center.z);
   436                     node.bb_max.x, node.bb_min.y, node.center.z);
   438                     node.bb_min.x, node.center.y, node.center.z);
   440                     node.center.x, node.center.y, node.center.z);
   442                     node.bb_max.x, node.center.y, node.center.z);
   444                     node.bb_min.x, node.bb_max.y, node.center.z);
   446                     node.center.x, node.bb_max.y, node.center.z);
   448                     node.bb_max.x, node.bb_max.y, node.center.z);
   451                     node.bb_min.x, node.bb_min.y, node.bb_max.z);  
   453                     node.center.x, node.bb_min.y, node.bb_max.z);
   455                     node.bb_min.x, node.bb_min.y, node.bb_max.z);  
   457                     node.bb_min.x, node.center.y, node.bb_max.z);
   459                     node.center.x, node.center.y, node.bb_max.z);
   461                     node.bb_max.x, node.center.y, node.bb_max.z);
   463                     node.bb_min.x, node.bb_max.y, node.bb_max.z);  
   465                     node.center.x, node.bb_max.y, node.bb_max.z);
   467                     node.bb_max.x, node.bb_max.y, node.bb_max.z);  
   470 #define PROJ_SUB_NODE(POSTFIX)                                       \   471     mrpt::img::TPixelCoordf px_##POSTFIX;                            \   472     float depth_##POSTFIX;                                           \   473     ri.projectPointPixels(                                           \   474         p_##POSTFIX.x, p_##POSTFIX.y, p_##POSTFIX.z, px_##POSTFIX.x, \   475         px_##POSTFIX.y, depth_##POSTFIX);   477 #define PROJ_SUB_NODE_ALREADY_DONE(INDEX, POSTFIX)             \   478     const mrpt::img::TPixelCoordf px_##POSTFIX = cr_px[INDEX]; \   479     float depth_##POSTFIX = cr_z[INDEX];   516 #define DO_RECURSE_CHILD(                                                \   517     INDEX, SEQ0, SEQ1, SEQ2, SEQ3, SEQ4, SEQ5, SEQ6, SEQ7)               \   519         mrpt::img::TPixelCoordf child_cr_px[8] = {                       \   520             px_##SEQ0, px_##SEQ1, px_##SEQ2, px_##SEQ3,                  \   521             px_##SEQ4, px_##SEQ5, px_##SEQ6, px_##SEQ7};                 \   522         float child_cr_z[8] = {depth_##SEQ0, depth_##SEQ1, depth_##SEQ2, \   523                                depth_##SEQ3, depth_##SEQ4, depth_##SEQ5, \   524                                depth_##SEQ6, depth_##SEQ7};              \   525         this->octree_recursive_render(                                   \   526             node.child_id[INDEX], ri, child_cr_px, child_cr_z);          \   532                     0, Xm_Ym_Zm, X0_Ym_Zm, Xm_Y0_Zm, X0_Y0_Zm, Xm_Ym_Z0,
   533                     X0_Ym_Z0, Xm_Y0_Z0, X0_Y0_Z0)
   535                     1, X0_Ym_Zm, Xp_Ym_Zm, X0_Y0_Zm, Xp_Y0_Zm, X0_Ym_Z0,
   536                     Xp_Ym_Z0, X0_Y0_Z0, Xp_Y0_Z0)
   538                     2, Xm_Y0_Zm, X0_Y0_Zm, Xm_Yp_Zm, X0_Yp_Zm, Xm_Y0_Z0,
   539                     X0_Y0_Z0, Xm_Yp_Z0, X0_Yp_Z0)
   541                     3, X0_Y0_Zm, Xp_Y0_Zm, X0_Yp_Zm, Xp_Yp_Zm, X0_Y0_Z0,
   542                     Xp_Y0_Z0, X0_Yp_Z0, Xp_Yp_Z0)
   544                     4, Xm_Ym_Z0, X0_Ym_Z0, Xm_Y0_Z0, X0_Y0_Z0, Xm_Ym_Zp,
   545                     X0_Ym_Zp, Xm_Y0_Zp, X0_Y0_Zp)
   547                     5, X0_Ym_Z0, Xp_Ym_Z0, X0_Y0_Z0, Xp_Y0_Z0, X0_Ym_Zp,
   548                     Xp_Ym_Zp, X0_Y0_Zp, Xp_Y0_Zp)
   550                     6, Xm_Y0_Z0, X0_Y0_Z0, Xm_Yp_Z0, X0_Yp_Z0, Xm_Y0_Zp,
   551                     X0_Y0_Zp, Xm_Yp_Zp, X0_Yp_Zp)
   553                     7, X0_Y0_Z0, Xp_Y0_Z0, X0_Yp_Z0, Xp_Yp_Z0, X0_Y0_Zp,
   554                     Xp_Y0_Zp, X0_Yp_Zp, Xp_Yp_Zp)
   555 #undef DO_RECURSE_CHILD   557 #undef PROJ_SUB_NODE_ALREADY_DONE   560 #pragma clang diagnostic pop   586         const size_t node_id, 
const bool all_pts = 
false)
   589         const size_t N = all_pts ? 
octree_derived().size() : node.pts.size();
   600             if (has_to_compute_bb)
   603                     for (
size_t i = 0; i < N; i++)
   606                     for (
size_t i = 0; i < N; i++)
   617                 for (
size_t i = 0; i < N; i++)
   621                     if (has_to_compute_bb) node.update_bb(p);
   624                 for (
size_t i = 0; i < N; i++)
   628                     if (has_to_compute_bb) node.update_bb(p);
   632             node.is_leaf = 
false;
   633             node.center = 
mean * (1.0f / N);
   638             for (
int i = 0; i < 8; i++)
   639                 node.child_id[i] = children_idx_base + i;
   642             for (
int i = 0; i < 8; i++)
   649             for (
size_t j = 0; j < N; j++)
   651                 const size_t i = all_pts ? j : node.pts[j];
   699                 std::vector<size_t> emptyVec;
   700                 node.pts.swap(emptyVec);  
   705             for (
int i = 0; i < 8; i++)
   732         const bool draw_solid_boxes = 
false)
 const   739             if (!node.is_leaf) 
continue;
   741             gl_box->setBoxCorners(
   744             gl_box->setColor(lines_color);
   745             gl_box->setLineWidth(lines_width);
   746             gl_box->setWireframe(!draw_solid_boxes);
   755         size_t total_elements = 0;
   760             o << 
"Node #" << i << 
": ";
   771                     o << node.pts.size() << 
" elements; ";
   772                     total_elements += node.pts.size();
   777                 o << 
"parent, center=(" << node.center.x << 
"," << node.center.y
   778                   << 
"," << node.center.z << 
"), children: " << node.child_id[0]
   779                   << 
"," << node.child_id[1] << 
"," << node.child_id[2] << 
","   780                   << node.child_id[3] << 
"," << node.child_id[4] << 
","   781                   << node.child_id[5] << 
"," << node.child_id[6] << 
","   782                   << node.child_id[7] << 
"; ";
   784             o << 
" bb: (" << node.bb_min.x << 
"," << node.bb_min.y << 
","   785               << node.bb_min.z << 
")-(" << node.bb_max.x << 
"," << node.bb_max.y
   786               << 
"," << node.bb_max.z << 
")\n";
   788         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. 
 
void update_bb(const mrpt::math::TPoint3Df &p)
update bounding box with a new point: 
 
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...
 
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. 
 
void octree_get_graphics_boundingboxes(mrpt::opengl::CSetOfObjects &gl_bb, const float lines_width=1, const mrpt::img::TColorf &lines_color=mrpt::img::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...
 
float getCornerZ(int i) const
 
std::atomic< size_t > m_visible_octree_nodes
 
size_t OCTREE_RENDER_MAX_POINTS_PER_NODE()
Default value = 1e5. 
 
void octree_render(const mrpt::opengl::TRenderMatrices &ri) const
Render the entire octree recursively. 
 
COctreePointRenderer()=default
Default ctor. 
 
A pair (x,y) of pixel coordinates (subpixel resolution). 
 
const Derived & octree_derived() const
 
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...
 
void projectPointPixels(float x, float y, float z, float &proj_u_px, float &proj_v_px, float &proj_depth) const
Projects a point from global world coordinates into (u,v) pixel coordinates. 
 
TRenderQueueElement(const size_t id, float area_sq)
 
void octree_recursive_render(size_t node_idx, const mrpt::opengl::TRenderMatrices &ri, mrpt::img::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. 
 
size_t octree_get_node_count() const
Return the number of octree nodes (all of them, including the empty ones) 
 
size_t child_id[8]
[is_leaf=false] The indices in m_octree_nodes of the 8 children. 
 
void OCTREE_RENDER_MAX_DENSITY_POINTS_PER_SQPIXEL(float value)
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...
 
Derived & octree_derived()
 
mrpt::math::TPoint3Df bb_max
 
TPoint3D_< double > TPoint3D
Lightweight 3D point. 
 
size_t m_visible_octree_nodes_ongoing
 
Rendering state related to the projection and model-view matrices. 
 
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
 
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...
 
#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. 
 
std::deque< TNode > m_octree_nodes
First one [0] is always the root node. 
 
size_t viewport_width
In pixels. 
 
void internal_octree_assure_uptodate()
 
An RGBA color - floats in the range [0,1]. 
 
void octree_getBoundingBox(mrpt::math::TPoint3D &bb_min, mrpt::math::TPoint3D &bb_max) const
 
double mean(const CONTAINER &v)
Computes the mean value of a vector. 
 
#define DO_RECURSE_CHILD( INDEX, SEQ0, SEQ1, SEQ2, SEQ3, SEQ4, SEQ5, SEQ6, SEQ7)
 
float getCornerY(int i) const
 
float render_area_sqpixels
The approximate size of the octree on the screen (squared pixels). 
 
void setBBFromOrderInParent(const TNode &parent, int my_child_index)
 
size_t node_id
The node ID to render. 
 
void insert(const CRenderizable::Ptr &newObject)
Insert a new object to the list. 
 
void octree_assure_uptodate() const
Must be called at children class' render() previously to octree_render() 
 
#define PROJ_SUB_NODE_ALREADY_DONE(INDEX, POSTFIX)
 
float getCornerX(int i) const
 
static Ptr Create(Args &&... args)
 
mrpt::math::TPoint3Df bb_min
 
for(unsigned int i=0;i< NUM_IMGS;i++)