Example: opengl_objects_demo
C++ example source code:
/* +------------------------------------------------------------------------+ | Mobile Robot Programming Toolkit (MRPT) | | https://www.mrpt.org/ | | | | Copyright (c) 2005-2024, 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/maps/COctoMap.h> #include <mrpt/obs/stock_observations.h> #include <mrpt/opengl.h> #include <mrpt/opengl/CPlanarLaserScan.h> #include <mrpt/random.h> #include <mrpt/system/filesystem.h> #include <Eigen/Dense> // transpose() #include <chrono> #include <iostream> #include <thread> using namespace std; using namespace mrpt::literals; // _deg using namespace mrpt; // opengl:: using namespace mrpt::gui; using namespace mrpt::opengl; using namespace mrpt::math; using namespace std::string_literals; // ------------------------------------------------------ // TestOpenGLObjects // ------------------------------------------------------ void TestOpenGLObjects() { mrpt::global_settings::OCTREE_RENDER_MAX_POINTS_PER_NODE(10000); CDisplayWindow3D win("Demo of MRPT's OpenGL objects", 640, 480); Scene::Ptr& theScene = win.get3DSceneAndLock(); auto& rng = mrpt::random::getRandomGenerator(); // Objects: double off_x = 0; const double off_y_label = 20; const double STEP_X = 25; // XY Grid { // using mrpt smart pointers so that obj survives outside this scope. auto obj = opengl::CGridPlaneXY::Create(-7, 7, -7, 7, 0, 1); obj->setColor(0.7f, 0.7f, 0.7f); obj->setLocation(off_x, 0, 0); theScene->insert(obj); auto obj2 = opengl::CGridPlaneXY::Create(-9, 9, -9, 9, 0, 2); obj2->setColor(0.3f, 0.3f, 0.3f, 0.99f); obj2->setLocation(off_x, 20, 0); obj2->enableAntiAliasing(); theScene->insert(obj2); auto gl_txt = opengl::CText::Create("CGridPlaneXY"); gl_txt->setLocation(off_x, off_y_label, 0); theScene->insert(gl_txt); } off_x += STEP_X; // XZ Grid { auto obj = opengl::CGridPlaneXZ::Create(-7, 7, -7, 7, 0, 1); obj->setColor(0.7f, 0.7f, 0.7f); obj->setLocation(off_x, 0, 0); theScene->insert(obj); auto gl_txt = opengl::CText::Create("CGridPlaneXZ"); gl_txt->setLocation(off_x, off_y_label, 0); theScene->insert(gl_txt); } off_x += STEP_X; // Arrow { auto obj = opengl::CArrow::Create(0, 0, 0, 3, 0, 0, 0.2f, 0.1f, 0.2f); obj->setLocation(off_x, 0, 0); obj->setColor(1, 0, 0); obj->setName("arrow #1"); obj->enableShowName(); theScene->insert(obj); auto obj2 = opengl::CArrow::Create(1, 2, 3, 6, -3, 0, 0.1f, 0.1f, 0.3f); obj2->setLocation(off_x, 0, 0); obj2->setColor(0, 0, 1); theScene->insert(obj2); auto gl_txt = opengl::CText::Create("CArrow"); gl_txt->setLocation(off_x, off_y_label, 0); theScene->insert(gl_txt); } off_x += STEP_X; // Axis { auto obj = opengl::CAxis::Create(-6, -6, -6, 6, 6, 6, 2, 2, true); obj->setLocation(off_x, 0, 0); theScene->insert(obj); auto gl_txt = opengl::CText::Create("CAxis"); gl_txt->setLocation(off_x, off_y_label, 0); theScene->insert(gl_txt); } off_x += STEP_X; // Box { auto obj = opengl::CBox::Create( TPoint3D(0, 0, 0), TPoint3D(1, 1, 1), true, 3.0); obj->setLocation(off_x, 0, 0); theScene->insert(obj); auto obj2 = opengl::CBox::Create(TPoint3D(0, 0, 0), TPoint3D(1, 1, 1), false); obj2->setLocation(off_x, 4, 0); theScene->insert(obj2); auto obj3 = opengl::CBox::Create(TPoint3D(0, 0, 0), TPoint3D(1, 1, 1), false); obj3->enableBoxBorder(true); obj3->setLineWidth(3); obj3->setColor_u8(0xff, 0x00, 0x00, 0xa0); obj3->setLocation(off_x, 8, 0); theScene->insert(obj3); auto gl_txt = opengl::CText::Create("CBox"); gl_txt->setLocation(off_x, off_y_label, 0); theScene->insert(gl_txt); } off_x += STEP_X; // Frustum { auto obj = opengl::CFrustum::Create(1, 5, 60, 45, 1.5f, true, false); obj->setLocation(off_x, 0, 0); theScene->insert(obj); auto obj2 = opengl::CFrustum::Create(1, 5, 60, 45, 2.5f, true, true); obj2->setLocation(off_x, 6, 0); obj2->setColor_u8(0xff, 0x00, 0x00, 0x80); theScene->insert(obj2); // Default camera params: mrpt::img::TCamera c; c.nrows = 800; c.ncols = 600; c.setIntrinsicParamsFromValues(700, 700, 400, 300); auto obj3 = opengl::CFrustum::Create(c); obj3->setLocation(off_x, 12, 0); obj3->setColor_u8(0xff, 0x00, 0x00, 0x80); theScene->insert(obj3); auto gl_txt = opengl::CText::Create("CFrustum"); gl_txt->setLocation(off_x, off_y_label, 0); theScene->insert(gl_txt); } off_x += STEP_X; // Cylinder { auto obj = opengl::CCylinder::Create(2, 2, 4, 20); obj->setLocation(off_x, 0, 0); obj->setColor(0, 0, 0.8f); theScene->insert(obj); auto obj2 = opengl::CCylinder::Create(2, 1, 4, 20); obj2->setLocation(off_x, 6, 0); obj2->setColor(0, 0, 0.8f); theScene->insert(obj2); auto obj3 = opengl::CCylinder::Create(2, 0, 4, 20); obj3->setLocation(off_x, -6, 0); obj3->setColor(0, 0, 0.8f); theScene->insert(obj3); auto gl_txt = opengl::CText::Create("CCylinder"); gl_txt->setLocation(off_x, off_y_label, 0); theScene->insert(gl_txt); } off_x += STEP_X; // CDisk { { auto obj = opengl::CDisk::Create(2.0f, 1.8f, 50); obj->setLocation(off_x, 0, 0); obj->setColor(0.8f, 0, 0); theScene->insert(obj); } { auto obj = opengl::CDisk::Create(2.0f, 0, 50); obj->setLocation(off_x, 5, 0); obj->setColor(0.8f, 0, 0); theScene->insert(obj); } auto gl_txt = opengl::CText::Create("CDisk"); gl_txt->setLocation(off_x, off_y_label, 0); theScene->insert(gl_txt); } off_x += STEP_X; // CEllipsoid3D { const double cov3d_dat[] = {0.9, 0.7, -0.4, 0.7, 1.6, -0.6, -0.4, -0.6, 1.5}; const double cov2d_dat[] = {0.9, 0.7, 0.7, 1.6}; mrpt::math::CMatrixDouble22 cov2d(cov2d_dat); mrpt::math::CMatrixDouble33 cov3d(cov3d_dat); { auto obj = opengl::CEllipsoid2D::Create(); obj->setCovMatrix(cov2d); obj->setLocation(off_x, 6, 0); obj->setQuantiles(2.0); theScene->insert(obj); } { auto obj = opengl::CEllipsoid2D::Create(); obj->setCovMatrix(cov2d); obj->setLocation(off_x, 12, 0); obj->enableDrawSolid3D(true); obj->setQuantiles(2.0); theScene->insert(obj); } { auto obj = opengl::CEllipsoid3D::Create(); obj->setCovMatrix(cov3d); obj->setQuantiles(2.0); obj->enableDrawSolid3D(false); obj->setLocation(off_x, 0, 0); theScene->insert(obj); } { auto obj = opengl::CEllipsoid3D::Create(); obj->setCovMatrix(cov3d); obj->setQuantiles(2.0); obj->materialShininess(0.99f); obj->setName("Ellipsoid shininess=0.99"); obj->enableShowName(); obj->enableDrawSolid3D(true); obj->setLocation(off_x, -6, 0); theScene->insert(obj); } { auto obj = opengl::CEllipsoid3D::Create(); obj->setCovMatrix(cov3d); obj->setQuantiles(2.0); obj->materialShininess(0.01f); obj->setName("Ellipsoid shininess=0.01"); obj->enableShowName(); obj->enableDrawSolid3D(true); obj->setLocation(off_x, -12, 0); theScene->insert(obj); } auto gl_txt = opengl::CText::Create("CEllipsoid3D"); gl_txt->setLocation(off_x, off_y_label, 0); theScene->insert(gl_txt); } off_x += STEP_X; // CEllipsoidRangeBearing2D { // (range,bearing) -> (x,y) const double cov_params_dat[] = {0.2, 0, 0, 0.1}; const double mean_params_dat[] = {3.0, 0.5}; mrpt::math::CMatrixFixed<double, 2, 2> cov_params(cov_params_dat); mrpt::math::CMatrixFixed<double, 2, 1> mean_params(mean_params_dat); { auto obj = opengl::CEllipsoidRangeBearing2D::Create(); obj->setCovMatrixAndMean(cov_params, mean_params); obj->setLocation(off_x, 6, 0); obj->setQuantiles(2.0f); // obj->setNumberOfSegments(50); theScene->insert(obj); auto obj_corner = opengl::stock_objects::CornerXYSimple(1, 3); obj_corner->setLocation(off_x, 6, 0); theScene->insert(obj_corner); } } { // (range,bearing) -> (x,y) const double cov_params_dat[] = {0.2, 0.09, 0.09, 0.1}; const double mean_params_dat[] = {5.0, -0.5}; mrpt::math::CMatrixFixed<double, 2, 2> cov_params(cov_params_dat); mrpt::math::CMatrixFixed<double, 2, 1> mean_params(mean_params_dat); { auto obj = opengl::CEllipsoidRangeBearing2D::Create(); obj->setCovMatrixAndMean(cov_params, mean_params); obj->setLocation(off_x, 0, 0); obj->setQuantiles(2.0f); // obj->setNumberOfSegments(50); theScene->insert(obj); auto obj_corner = opengl::stock_objects::CornerXYSimple(1, 3); obj_corner->setLocation(off_x, 0, 0); theScene->insert(obj_corner); } auto gl_txt = opengl::CText::Create("CEllipsoidRangeBearing2D"); gl_txt->setLocation(off_x, off_y_label, 0); theScene->insert(gl_txt); } off_x += STEP_X; // CEllipsoidInverseDepth2D { // (inv_range,yaw) -> (x,y) // Formula from our book (ch8) for confidence intervals of 3sigmas: const double max_dist = 1e4; const double min_dist = 1; const double rho_mean = 0.5 * (1. / min_dist + 1. / max_dist); const double rho_std = (1. / 6.) * (1. / min_dist - 1. / max_dist); const double cov_params_dat[] = { square(rho_std), 0, 0, square(2.0_deg)}; const double mean_params_dat[] = {rho_mean, 70.0_deg}; mrpt::math::CMatrixFixed<double, 2, 2> cov_params(cov_params_dat); mrpt::math::CMatrixFixed<double, 2, 1> mean_params(mean_params_dat); { auto obj = opengl::CEllipsoidInverseDepth2D::Create(); obj->setCovMatrixAndMean(cov_params, mean_params); obj->setLocation(off_x, 6, 0); obj->setQuantiles(3.f); obj->setNumberOfSegments(100); theScene->insert(obj); auto obj_corner = opengl::stock_objects::CornerXYSimple(1, 3); obj_corner->setLocation(off_x, 6, 0); theScene->insert(obj_corner); } auto gl_txt = opengl::CText::Create("CEllipsoidInverseDepth2D"); gl_txt->setLocation(off_x, off_y_label, 0); theScene->insert(gl_txt); } off_x += STEP_X; // CEllipsoidInverseDepth3D { // (inv_range,yaw,pitch) -> (x,y,z) // Formula from our book (ch8) for confidence intervals of 3sigmas: const double max_dist = 1e2; const double min_dist = 1; const double rho_mean = 0.5 * (1. / min_dist + 1. / max_dist); const double rho_std = (1. / 6.) * (1. / min_dist - 1. / max_dist); const double cov_params_dat[] = {square(rho_std), 0, 0, 0, square(2.0_deg), 0, 0, 0, square(2.0_deg)}; const double mean_params_dat[] = {rho_mean, 30.0_deg, -45.0_deg}; mrpt::math::CMatrixFixed<double, 3, 3> cov_params(cov_params_dat); mrpt::math::CMatrixFixed<double, 3, 1> mean_params(mean_params_dat); { auto obj = opengl::CEllipsoidInverseDepth3D::Create(); obj->setCovMatrixAndMean(cov_params, mean_params); obj->setLocation(off_x, 0, 0); obj->setQuantiles(3.f); // obj->setNumberOfSegments(50); theScene->insert(obj); auto obj_corner = opengl::stock_objects::CornerXYZSimple(1, 3); obj_corner->setLocation(off_x, 0, 0); theScene->insert(obj_corner); } auto gl_txt = opengl::CText::Create("CEllipsoidInverseDepth3D"); gl_txt->setLocation(off_x, off_y_label, 0); theScene->insert(gl_txt); } off_x += STEP_X; // CMesh3D { auto obj = opengl::CMesh3D::Create(); obj->enableShowEdges(false); obj->enableShowFaces(true); obj->enableShowVertices(false); obj->setLocation(off_x, 0, 0); const unsigned int rows = 200, cols = 200; const unsigned int num_verts = (rows + 1) * (cols + 1); const unsigned int num_faces = rows * cols; int* vert_per_face = new int[num_faces]; int* face_verts = new int[4 * num_faces]; float* vert_coords = new float[3 * num_verts]; // Assign vertices to faces and set them to be Quads unsigned int first_ind = 0; for (unsigned int u = 0; u < cols; u++) { for (unsigned int v = 0; v < rows; v++) { const unsigned int face_ind = v + u * rows; vert_per_face[face_ind] = 4; face_verts[4 * face_ind] = first_ind; face_verts[4 * face_ind + 1] = first_ind + 1; face_verts[4 * face_ind + 2] = first_ind + rows + 2; face_verts[4 * face_ind + 3] = first_ind + rows + 1; first_ind++; } first_ind++; } // Create vert coords for (unsigned int u = 0; u <= cols; u++) for (unsigned int v = 0; v <= rows; v++) { const unsigned int vert_ind = v + u * (rows + 1); vert_coords[3 * vert_ind] = (2.f - 0.01f * u) * (2.f + cos(0.01f * M_PI * v)) * cos(0.01f * M_PI * u); vert_coords[3 * vert_ind + 1] = (2.f - 0.01f * u) * (2.f + cos(0.01f * M_PI * v)) * sin(0.01f * M_PI * u); vert_coords[3 * vert_ind + 2] = 3.f * 0.01f * u + (2.f - 0.01f * u) * sin(0.01f * M_PI * v); } obj->loadMesh( num_verts, num_faces, vert_per_face, face_verts, vert_coords); theScene->insert(obj); auto gl_txt = opengl::CText::Create("CMesh3D"); gl_txt->setLocation(off_x, off_y_label, 0); theScene->insert(gl_txt); } off_x += STEP_X; // CMeshFast, CMesh: { opengl::CMeshFast::Ptr obj1 = opengl::CMeshFast::Create(); opengl::CMeshFast::Ptr obj2 = opengl::CMeshFast::Create(); opengl::CMesh::Ptr obj3 = opengl::CMesh::Create(); opengl::CMesh::Ptr obj4 = opengl::CMesh::Create(); opengl::CMesh::Ptr obj5 = opengl::CMesh::Create(); obj1->setXBounds(-1, 1); obj1->setYBounds(-1, 1); const int W = 128, H = 128; mrpt::math::CMatrixDynamic<float> Z(H, W); for (int r = 0; r < H; r++) for (int c = 0; c < W; c++) Z(r, c) = sin(0.05 * (c + r) - 0.5) * cos(0.9 - 0.03 * r); const std::string texture_file = mrpt::system::getShareMRPTDir() + "datasets/sample-texture-terrain.jpg"s; const std::string texture_file2 = mrpt::system::getShareMRPTDir() + "datasets/sample-texture-corners.jpg"s; mrpt::img::CImage im, im2; // obj1: obj1->setZ(Z); obj1->enableColorFromZ(true); obj1->setPointSize(2.0); obj1->setLocation(off_x, 0, 0); theScene->insert(obj1); // obj 2: if (im.loadFromFile(texture_file)) { obj2->assignImageAndZ(im, Z); obj2->setPointSize(2.0); obj2->setLocation(off_x, 3, 0); theScene->insert(obj2); } { auto gl_txt = opengl::CText::Create("CMeshFast"); gl_txt->setLocation(off_x, off_y_label, 0); theScene->insert(gl_txt); } off_x += STEP_X; // obj 3: obj3->setZ(Z); obj3->enableColorFromZ(true, mrpt::img::cmJET); obj3->enableWireFrame(true); obj3->setLocation(off_x, 0, 0); obj3->cullFaces(mrpt::opengl::TCullFace::BACK); // obj3->enableTextureMipMap(false); theScene->insert(obj3); // obj 4: if (im.getWidth() > 1) { obj4->assignImageAndZ(im, Z); obj4->setLocation(off_x, 3, 0); obj4->cullFaces(mrpt::opengl::TCullFace::BACK); // obj4->enableTextureMipMap(false); theScene->insert(obj4); } // obj 5: if (im.getWidth() > 1) { obj5->assignImageAndZ(im, Z); obj5->setMeshTextureExtension(0.25, 0.5); obj5->setLocation(off_x + 3, 3, 0); // obj5->enableTextureMipMap(false); theScene->insert(obj5); } mrpt::math::CMatrixDynamic<float> Z2(H, W); if (im2.loadFromFile(texture_file2)) { im2.getAsMatrix(Z2); opengl::CMesh::Ptr obj = opengl::CMesh::Create( false /*transparency*/, // -1, 1, // x: Min Max 1, -1 // y: Min Max ); obj->assignImageAndZ(im2, Z2); obj->setLocation(off_x, 6, 0); theScene->insert(obj); } if (im2.loadFromFile(texture_file2)) { opengl::CMesh::Ptr obj = opengl::CMesh::Create( false /*transparency*/, // 1, -1, // x: Min Max -1, 1 // y: Min Max ); obj->assignImageAndZ(im2, Z2); obj->setLocation(off_x, 9, 0); theScene->insert(obj); } { auto gl_txt = opengl::CText::Create("CMesh"); gl_txt->setLocation(off_x, off_y_label, 0); theScene->insert(gl_txt); } } off_x += STEP_X; // CPointCloud { auto obj = opengl::CPointCloud::Create(); obj->setLocation(off_x, 0, 0); theScene->insert(obj); obj->setPointSize(1.0); obj->enableColorFromY(); for (int i = 0; i < 100000; i++) obj->insertPoint( rng.drawUniform<float>(-5, 5), rng.drawUniform<float>(-5, 5), rng.drawUniform<float>(-5, 5)); auto gl_txt = opengl::CText::Create("CPointCloud"); gl_txt->setLocation(off_x, off_y_label, 0); theScene->insert(gl_txt); } off_x += STEP_X; // CPointCloudColoured { auto obj = opengl::CPointCloudColoured::Create(); obj->setLocation(off_x, 0, 0); theScene->insert(obj); obj->setPointSize(1.0); for (int i = 0; i < 200; i++) obj->push_back( rng.drawUniform<float>(-5, 5), rng.drawUniform<float>(-5, 5), rng.drawUniform<float>(-5, 5), rng.drawUniform<float>(0, 1), rng.drawUniform<float>(0, 1), rng.drawUniform<float>(0, 1)); auto gl_txt = opengl::CText::Create("CPointCloudColoured"); gl_txt->setLocation(off_x, off_y_label, 0); theScene->insert(gl_txt); } off_x += STEP_X; // CPolyhedron { { auto obj = opengl::CPolyhedron::CreateCuboctahedron(1.0); obj->setLocation(off_x, 0, 0); obj->setWireframe(true); theScene->insert(obj); } { auto obj = opengl::CPolyhedron::CreateDodecahedron(1.0); obj->setLocation(off_x, -5, 0); theScene->insert(obj); } { auto obj = opengl::CPolyhedron::CreateIcosahedron(1.0); obj->setLocation(off_x, 5, 0); theScene->insert(obj); } auto gl_txt = opengl::CText::Create("CPolyhedron"); gl_txt->setLocation(off_x, off_y_label, 0); theScene->insert(gl_txt); } off_x += STEP_X; // CSphere { { auto obj = opengl::CSphere::Create(3.0); obj->setLocation(off_x, 0, 0); theScene->insert(obj); } auto gl_txt = opengl::CText::Create("CSphere"); gl_txt->setLocation(off_x, off_y_label, 0); theScene->insert(gl_txt); } off_x += STEP_X; // CText { { auto obj = opengl::CText::Create( "This is a CText example! My size is invariant to " "eye-distance"); obj->setLocation(off_x, 0, 0); theScene->insert(obj); } auto gl_txt = opengl::CText::Create("CText"); gl_txt->setLocation(off_x, off_y_label, 0); theScene->insert(gl_txt); } off_x += STEP_X; // CText3D { { auto obj = opengl::CText3D::Create("I'm a cool CText3D!"); obj->setLocation(off_x, 0, 0); theScene->insert(obj); } { auto obj = opengl::CText3D::Create("A rotated CText3D"); obj->setPose( mrpt::poses::CPose3D(off_x, 0, 0, 0, 0, 0) + mrpt::poses::CPose3D::FromString("[0 5 0 180 0 90]")); theScene->insert(obj); } auto gl_txt = opengl::CText::Create("CText3D"); gl_txt->setLocation(off_x, off_y_label, 0); theScene->insert(gl_txt); } off_x += STEP_X; // CColorMap { { auto obj = opengl::CColorBar::Create( mrpt::img::cmHOT, 0.2, 1.0, 0.0, 1.0, -50.0, 100.0, "%7.02f m/s"); obj->setLocation(off_x, 0, 0); theScene->insert(obj); } auto gl_txt = opengl::CText::Create("CColorBar"); gl_txt->setLocation(off_x, off_y_label, 0); theScene->insert(gl_txt); } off_x += STEP_X; // CSetOfLines { for (int rep = 0; rep < 2; rep++) { auto obj = opengl::CSetOfLines::Create(); obj->setLocation(off_x, rep * 20, 0); for (int i = 0; i < 15; i++) obj->appendLine( rng.drawUniform(-5, 5), rng.drawUniform(-5, 5), rng.drawUniform(-5, 5), rng.drawUniform(-5, 5), rng.drawUniform(-5, 5), rng.drawUniform(-5, 5)); if (rep == 1) obj->setVerticesPointSize(5.0f); theScene->insert(obj); } auto gl_txt = opengl::CText::Create("CSetOfLines"); gl_txt->setLocation(off_x, off_y_label, 0); theScene->insert(gl_txt); } off_x += STEP_X; // CSimpleLine { { auto obj = opengl::CSimpleLine::Create(); obj->setLocation(off_x, 0, 0); obj->setLineCoords( rng.drawUniform<float>(-5, 5), rng.drawUniform<float>(-5, 5), rng.drawUniform<float>(-5, 5), rng.drawUniform<float>(-5, 5), rng.drawUniform<float>(-5, 5), rng.drawUniform<float>(-5, 5)); theScene->insert(obj); } auto gl_txt = opengl::CText::Create("CSimpleLine"); gl_txt->setLocation(off_x, off_y_label, 0); theScene->insert(gl_txt); } off_x += STEP_X; // CVectorField2D { { auto obj = opengl::CVectorField2D::Create(); obj->setLocation(off_x, 0, 0); CMatrixFloat x(16, 16), y(16, 16); for (int i = 0; i < x.rows(); i++) for (int j = 0; j < x.cols(); j++) { x(i, j) = sin(0.3 * i); y(i, j) = cos(0.3 * i); } obj->setVectorField(x, y); obj->setPointColor(1, 0.3f, 0); obj->setVectorFieldColor(0, 0, 1); obj->setPointSize(3.0); obj->setLineWidth(2.0); obj->setGridCenterAndCellSize(0, 0, 1.2f, 1.2f); obj->adjustVectorFieldToGrid(); theScene->insert(obj); } auto gl_txt = opengl::CText::Create("CVectorField2D"); gl_txt->setLocation(off_x, off_y_label, 0); theScene->insert(gl_txt); } off_x += STEP_X; // CVectorField3D { { const unsigned int num = 20; const float scale = 0.8 * STEP_X / num; auto obj = opengl::CVectorField3D::Create(); obj->setLocation(off_x, -0.5 * scale * num, 0); // CMatrixFloat x(num, num), y(num, num), z(num, num); CMatrixFloat vx(num, num), vy(num, num), vz(num, num); for (int i = 0; i < x.rows(); i++) for (int j = 0; j < x.cols(); j++) { x(i, j) = (i - 0.5 * num) * scale; y(i, j) = j * scale; z(i, j) = 3 * sin(0.3 * i) * cos(0.3 * j); vx(i, j) = 0.4 * sin(0.3 * i); vy(i, j) = 0.8 * cos(0.3 * i); vz(i, j) = 0.01 * i * j; } obj->setPointCoordinates(x, y, z); obj->setVectorField(vx, vy, vz); obj->setPointColor(1, 0.3f, 0); obj->setVectorFieldColor(0, 0, 1); obj->setPointSize(3.0); obj->setLineWidth(2.0); obj->enableColorFromModule(); obj->setMaxSpeedForColor(3.0); obj->setMotionFieldColormap(0, 0, 1, 1, 0, 0); theScene->insert(obj); } auto gl_txt = opengl::CText::Create("CVectorField3D"); gl_txt->setLocation(off_x, off_y_label, 0); theScene->insert(gl_txt); } off_x += STEP_X; // stock_objects::BumblebeeCamera { { auto obj = opengl::stock_objects::BumblebeeCamera(); obj->setLocation(off_x, 0, 0); theScene->insert(obj); } auto gl_txt = opengl::CText::Create("stock_objects::BumblebeeCamera()"); gl_txt->setLocation(off_x, off_y_label, 0); theScene->insert(gl_txt); } off_x += STEP_X; // stock_objects::CornerXYSimple { { auto obj = opengl::stock_objects::CornerXYSimple(1, 3); obj->setLocation(off_x, 0, 0); theScene->insert(obj); } auto gl_txt = opengl::CText::Create("stock_objects::CornerXYSimple()"); gl_txt->setLocation(off_x, off_y_label, 0); theScene->insert(gl_txt); } off_x += STEP_X; // stock_objects::CornerXYZSimple { { auto obj = opengl::stock_objects::CornerXYZSimple(1, 3); obj->setLocation(off_x, 0, 0); theScene->insert(obj); } auto gl_txt = opengl::CText::Create("stock_objects::CornerXYZSimple()"); gl_txt->setLocation(off_x, off_y_label, 0); theScene->insert(gl_txt); } off_x += STEP_X; // stock_objects::CornerXYZ { { auto obj = opengl::stock_objects::CornerXYZ(); obj->setLocation(off_x, 0, 0); theScene->insert(obj); } auto gl_txt = opengl::CText::Create("stock_objects::CornerXYZ()"); gl_txt->setLocation(off_x, off_y_label, 0); theScene->insert(gl_txt); } off_x += STEP_X; // CSetOfTriangles: tested via stock_objects: // stock_objects::RobotPioneer { { auto obj = opengl::stock_objects::RobotPioneer(); obj->setLocation(off_x, 0, 0); theScene->insert(obj); } auto gl_txt = opengl::CText::Create("stock_objects::RobotPioneer()"); gl_txt->setLocation(off_x, off_y_label, 0); theScene->insert(gl_txt); } off_x += STEP_X; // stock_objects::Hokuyo_URG { { auto obj = opengl::stock_objects::Hokuyo_URG(); obj->setLocation(off_x, 0, 0); theScene->insert(obj); } auto gl_txt = opengl::CText::Create("stock_objects::Hokuyo_URG()"); gl_txt->setLocation(off_x, off_y_label, 0); theScene->insert(gl_txt); } off_x += STEP_X; // stock_objects::Hokuyo_UTM { { auto obj = opengl::stock_objects::Hokuyo_UTM(); obj->setLocation(off_x, 0, 0); theScene->insert(obj); } auto gl_txt = opengl::CText::Create("stock_objects::Hokuyo_UTM()"); gl_txt->setLocation(off_x, off_y_label, 0); theScene->insert(gl_txt); } off_x += STEP_X; // stock_objects::Househam_Sprayer { { auto obj = opengl::stock_objects::Househam_Sprayer(); obj->setLocation(off_x, 0, 0); theScene->insert(obj); } auto gl_txt = opengl::CText::Create("stock_objects::Househam_Sprayer()"); gl_txt->setLocation(off_x, off_y_label, 0); theScene->insert(gl_txt); } off_x += STEP_X; // stock_objects::RobotRhodon { { auto obj = opengl::stock_objects::RobotRhodon(); obj->setLocation(off_x, 0, 0); theScene->insert(obj); } auto gl_txt = opengl::CText::Create("stock_objects::RobotRhodon()"); gl_txt->setLocation(off_x, off_y_label, 0); theScene->insert(gl_txt); } off_x += STEP_X; // CPlanarLaserScan { auto obj = mrpt::opengl::CPlanarLaserScan::Create(); obj->setPose(mrpt::poses::CPose3D(off_x, 0, 0, 90.0_deg, 0, 0)); mrpt::obs::CObservation2DRangeScan scan; mrpt::obs::stock_observations::example2DRangeScan(scan); obj->setScan(scan); theScene->insert(obj); auto gl_txt = opengl::CText::Create("CPlanarLaserScan"); gl_txt->setLocation(off_x, off_y_label, 0); theScene->insert(gl_txt); } off_x += STEP_X; // CTexturedPlane { mrpt::img::CImage pic, picAlpha; const size_t W = 256, H = 256; pic.resize(W, H, mrpt::img::CH_RGB); picAlpha.resize(W, H, mrpt::img::CH_GRAY); pic.filledRectangle(0, 0, W - 1, H - 1, mrpt::img::TColor::black()); pic.filledRectangle(0, 0, W / 4, H / 2, mrpt::img::TColor::white()); picAlpha.filledRectangle( 0, 0, W - 1, H - 1, mrpt::img::TColor(0x55, 0x55, 0x55)); picAlpha.filledRectangle( 0, 0, W / 4, H / 2, mrpt::img::TColor(0xa0, 0xa0, 0xa0)); { opengl::CTexturedPlane::Ptr obj = opengl::CTexturedPlane::Create(); obj->setPose(mrpt::poses::CPose3D(off_x, 0, 0, 0, 90.0_deg, 0)); obj->assignImage(pic); theScene->insert(obj); } { opengl::CTexturedPlane::Ptr obj = opengl::CTexturedPlane::Create(); obj->setPose(mrpt::poses::CPose3D(off_x, 4.0, 0, 0, 90.0_deg, 0)); obj->assignImage(pic, picAlpha); theScene->insert(obj); } // a plane w/o a texture is a plain color plane: { opengl::CTexturedPlane::Ptr obj = opengl::CTexturedPlane::Create(); obj->setPose(mrpt::poses::CPose3D(off_x, 8.0, 0, 0, 90.0_deg, 0)); obj->setColor_u8(0xff, 0x00, 0x00, 0xff); theScene->insert(obj); } { opengl::CTexturedPlane::Ptr obj = opengl::CTexturedPlane::Create(); obj->setPose(mrpt::poses::CPose3D(off_x, 12.0, 0, 0, 90.0_deg, 0)); obj->setColor_u8(0xff, 0x00, 0x00, 0x40); theScene->insert(obj); } { opengl::CTexturedPlane::Ptr obj = opengl::CTexturedPlane::Create(); obj->setPose(mrpt::poses::CPose3D(off_x, 6.0, -3.0, 0, 0.0_deg, 0)); obj->assignImage(pic); obj->enableLighting(true); theScene->insert(obj); } { opengl::CTexturedPlane::Ptr obj = opengl::CTexturedPlane::Create(); obj->setPose(mrpt::poses::CPose3D(off_x, 3.9, -3.0, 0, 0.0_deg, 0)); obj->setColor_u8(0xff, 0x00, 0x00, 0xff); obj->enableLighting(true); theScene->insert(obj); } auto gl_txt = opengl::CText::Create("CTexturedPlane"); gl_txt->setLocation(off_x, off_y_label, 0); theScene->insert(gl_txt); } off_x += STEP_X; // COctoMapVoxels { mrpt::maps::COctoMap map(0.2); // Insert 2D scan: mrpt::obs::CObservation2DRangeScan scan1; mrpt::obs::stock_observations::example2DRangeScan(scan1); map.insertObservation(scan1); auto gl_map1 = mrpt::opengl::COctoMapVoxels::Create(); auto gl_map2 = mrpt::opengl::COctoMapVoxels::Create(); auto gl_map3 = mrpt::opengl::COctoMapVoxels::Create(); map.getAsOctoMapVoxels(*gl_map1); map.getAsOctoMapVoxels(*gl_map2); // map.renderingOptions.generateGridLines = true; map.getAsOctoMapVoxels(*gl_map3); gl_map1->showGridLines(false); gl_map1->showVoxelsAsPoints(true); gl_map1->setPointSize(3.0); gl_map1->setLocation(off_x, 0, 0); theScene->insert(gl_map1); gl_map2->showVoxelsAsPoints(false); gl_map2->showVoxels(VOXEL_SET_OCCUPIED, true); gl_map2->showVoxels(VOXEL_SET_FREESPACE, true); gl_map2->setLocation(off_x, 4, 0); theScene->insert(gl_map2); gl_map3->showVoxelsAsPoints(true); gl_map3->showGridLines(true); gl_map3->setLocation(off_x, 8, 0); theScene->insert(gl_map3); auto gl_txt = opengl::CText::Create("COctoMapVoxels"); gl_txt->setLocation(off_x, off_y_label, 0); theScene->insert(gl_txt); } off_x += STEP_X; // ground plane (to test shadows): // A plane w/o a texture is a plain color plane: { auto obj = mrpt::opengl::CBox::Create(); obj->setColor_u8(0xa0, 0xa0, 0xa0, 0xff); obj->setLocation(0, 0, -5.0f); obj->setBoxCorners({-20.0f, -20.0f, .0f}, {off_x + 20.f, 40.0f, -0.1f}); obj->cullFaces(TCullFace::BACK); // avoid z-fighting theScene->insert(obj); } // Arrow to show the light direction: auto glLightArrow = opengl::CArrow::Create( mrpt::math::TPoint3Df(0, 0, 0), mrpt::math::TPoint3Df(1, 0, 0)); glLightArrow->setLocation(off_x / 5, -4.0, 5.0); glLightArrow->setColor(0, 1, 0); glLightArrow->setName("Light dir."); glLightArrow->enableShowName(); theScene->insert(glLightArrow); // Add image-mode viewport: { const std::string img_file = mrpt::system::getShareMRPTDir() + "datasets/stereo-calib/0_left.jpg"s; mrpt::img::CImage im; if (im.loadFromFile(img_file)) { auto glView = theScene->createViewport("image1"); glView->setViewportPosition(0.7, 0, 0.3, 0.3); glView->setImageView(im); glView->setBorderSize(1); } } // Zoom out: win.setCameraZoom(250); // IMPORTANT!!! IF NOT UNLOCKED, THE WINDOW WILL NOT BE UPDATED! win.unlockAccess3DScene(); win.repaint(); cout << "Close the window to end.\n"; mrpt::opengl::TFontParams fp; fp.vfont_scale = 14; // pixels fp.draw_shadow = true; win.addTextMessage(5, 5, "", 0 /*id*/, fp); auto viewport = theScene->getViewport(); mrpt::opengl::TLightParameters& lights = viewport->lightParameters(); lights.ambient = 0.2; while (win.isOpen()) { // Lights: const double t = mrpt::Clock::nowDouble(); const auto p = glLightArrow->getPose(); const auto lightDir = mrpt::poses::CPose3D::FromXYZYawPitchRoll( p.x, p.y, p.z, t * 10.0_deg, 45.0_deg, 0.0_deg); glLightArrow->setPose(lightDir); lights.direction = lightDir.getRotationMatrix().extractColumn<mrpt::math::TVector3Df>( 0); if (win.keyHit()) { switch (win.getPushedKey()) { case 'S': case 's': // toggle shadows: viewport->enableShadowCasting( !viewport->isShadowCastingEnabled()); break; }; } win.updateTextMessage( 0 /*id*/, format( "Render time=%.03fms | Shadows: %s", 1e3 / win.getRenderingFPS(), viewport->isShadowCastingEnabled() ? "On" : "Off")); std::this_thread::sleep_for(2ms); win.repaint(); } } // ------------------------------------------------------ // MAIN // ------------------------------------------------------ int main() { try { TestOpenGLObjects(); return 0; } catch (const std::exception& e) { std::cerr << "MRPT error: " << mrpt::exception_to_str(e) << std::endl; return -1; } }