Example: opengl_octree_render_huge_pointcloud
C++ example source code:
/* +------------------------------------------------------------------------+ | Mobile Robot Programming Toolkit (MRPT) | | https://www.mrpt.org/ | | | | Copyright (c) 2005-2023, Individual contributors, see AUTHORS file | | See: https://www.mrpt.org/Authors - All rights reserved. | | Released under BSD License. See: https://www.mrpt.org/License | +------------------------------------------------------------------------+ */ #include <mrpt/gui/CDisplayWindow3D.h> #include <mrpt/img/TColor.h> #include <mrpt/math/geometry.h> #include <mrpt/opengl/CPointCloud.h> #include <mrpt/random.h> #include <chrono> #include <iostream> #include <thread> using namespace std; using namespace mrpt; using namespace mrpt::gui; using namespace mrpt::opengl; using namespace mrpt::math; using namespace mrpt::img; void insertRandomPoints_uniform( const size_t N, opengl::CPointCloud::Ptr& gl, const TPoint3D& p_min, const TPoint3D& p_max) { auto& rnd = random::getRandomGenerator(); for (size_t i = 0; i < N; i++) gl->insertPoint( rnd.drawUniform<float>(p_min.x, p_max.x), rnd.drawUniform<float>(p_min.y, p_max.y), rnd.drawUniform<float>(p_min.z, p_max.z)); } void insertRandomPoints_screw( const size_t N, opengl::CPointCloud::Ptr& gl, const TPoint3D& p_start, const TPoint3D& p_end) { TPoint3D d = p_end - p_start; d *= 1.0 / N; TPoint3D up(0, 0, 1); TPoint3D lat; mrpt::math::crossProduct3D(d, up, lat); lat *= 1.0 / lat.norm(); TPoint3D p = p_start; for (size_t i = 0; i < N; i++) { const double ang = i * 0.01; TPoint3D pp = p + up * 30 * cos(ang) + lat * 30 * sin(ang); const auto ppf = TPoint3Df(pp); gl->insertPoint(ppf.x, ppf.y, ppf.z); p += d; } } void insertRandomPoints_gauss( const size_t N, opengl::CPointCloud::Ptr& gl, const TPoint3D& p_mean, const TPoint3D& p_stddevs) { auto& rnd = random::getRandomGenerator(); for (size_t i = 0; i < N; i++) gl->insertPoint( rnd.drawGaussian1D<float>(p_mean.x, p_stddevs.x), rnd.drawGaussian1D<float>(p_mean.y, p_stddevs.y), rnd.drawGaussian1D<float>(p_mean.z, p_stddevs.z)); } // ------------------------------------------------------ // TestOctreeRenderHugePointCloud // ------------------------------------------------------ void TestOctreeRenderHugePointCloud() { // Change this in your program as needed: // mrpt::global_settings::OCTREE_RENDER_MAX_DENSITY_POINTS_PER_SQPIXEL(0.1f); CDisplayWindow3D win("Demo of MRPT's octree pointclouds", 640, 480); Scene::Ptr& theScene = win.get3DSceneAndLock(); // CPointCloud opengl::CPointCloud::Ptr gl_pointcloud = opengl::CPointCloud::Create(); theScene->insert(gl_pointcloud); gl_pointcloud->setPointSize(3.0); gl_pointcloud->enableColorFromZ(); // Set the list of all points: const double L = 1e3; cout << "Building point cloud..."; cout.flush(); for (int XX = -10; XX <= 10; XX++) { const double off_x = XX * 2 * L; for (int YY = -10; YY <= 10; YY++) { const double off_y = YY * 2 * L; insertRandomPoints_screw( 1e4, gl_pointcloud, TPoint3D(off_x + 0, off_y + 0, 0), TPoint3D(off_x + L, off_y + 0, 500)); insertRandomPoints_screw( 1e4, gl_pointcloud, TPoint3D(off_x + L, off_y + 0, 500), TPoint3D(off_x + L, off_y + L, -500)); insertRandomPoints_screw( 1e4, gl_pointcloud, TPoint3D(off_x + L, off_y + L, -500), TPoint3D(off_x + 0, off_y + L, 500)); insertRandomPoints_screw( 1e4, gl_pointcloud, TPoint3D(off_x + 0, off_y + L, 500), TPoint3D(off_x + 0, off_y + 0, 0)); } } cout << "Done.\n"; cout.flush(); printf("Point count: %e\n", (double)gl_pointcloud->size()); // Draw the octree bounding boxes: mrpt::opengl::CSetOfObjects::Ptr gl_bb = mrpt::opengl::CSetOfObjects::Create(); gl_pointcloud->octree_get_graphics_boundingboxes(*gl_bb); theScene->insert(gl_bb); // gl_pointcloud->octree_debug_dump_tree(std::cout); win.setCameraZoom(600); { mrpt::opengl::Viewport::Ptr view = theScene->getViewport("main"); view->setViewportClipDistances(0.1f, 1e6f); } // IMPORTANT!!! IF NOT UNLOCKED, THE WINDOW WILL NOT BE UPDATED! win.unlockAccess3DScene(); win.repaint(); cout << "Close the window or press any key to end.\n"; bool end = false; while (win.isOpen() && !end) { std::this_thread::sleep_for(5ms); if (win.keyHit()) { switch (win.getPushedKey()) { case 'q': end = true; break; case 'b': gl_bb->setVisibility(!gl_bb->isVisible()); break; }; } // Update the texts on the gl display: string s = mrpt::format( "FPS=%5.02f | Rendered points=%.02e/%.02e (%.02f%%) | " "Visib.oct.nodes: %u/%u", win.getRenderingFPS(), (double)gl_pointcloud->getActuallyRendered(), (double)gl_pointcloud->size(), 100 * double(gl_pointcloud->getActuallyRendered()) / double(gl_pointcloud->size()), (unsigned int)gl_pointcloud->octree_get_visible_nodes(), (unsigned int)gl_pointcloud->octree_get_node_count()); win.get3DSceneAndLock(); win.addTextMessage(5, 5, s, 0); win.addTextMessage( 5, 35, "'b': switch bounding-boxes visible, 'q': quit", 1); win.unlockAccess3DScene(); win.repaint(); } } // ------------------------------------------------------ // MAIN // ------------------------------------------------------ int main() { try { TestOctreeRenderHugePointCloud(); std::this_thread::sleep_for(500ms); return 0; } catch (const std::exception& e) { std::cerr << "MRPT error: " << mrpt::exception_to_str(e) << std::endl; return -1; } }