#include "pcl-converter.hpp" // Get RGB values based on normals - texcoords, normals value [u v] std::tuple PCLConverter::get_texcolor(rs2::video_frame texture, rs2::texture_coordinate texcoords) { const int w = texture.get_width(), h = texture.get_height(); // convert normals [u v] to basic coords [x y] int x = std::min(std::max(int(texcoords.u * w + .5f), 0), w - 1); int y = std::min(std::max(int(texcoords.v * h + .5f), 0), h - 1); int idx = x * texture.get_bytes_per_pixel() + y * texture.get_stride_in_bytes(); const auto texture_data = reinterpret_cast(texture.get_data()); return std::tuple(texture_data[idx], texture_data[idx + 1], texture_data[idx + 2]); } PtrCloud PCLConverter::points_to_pcl(const rs2::points &points, const rs2::video_frame &color) { auto sp = points.get_profile().as(); PtrCloud cloud(new PointCloudRGB); // Config of PCL Cloud object cloud->width = static_cast(sp.width()); cloud->height = static_cast(sp.height()); cloud->is_dense = false; cloud->points.resize(points.size()); auto tex_coords = points.get_texture_coordinates(); auto vertices = points.get_vertices(); // Iterating through all points and setting XYZ coordinates // and RGB values for (int i = 0; i < points.size(); ++i) { cloud->points[i].x = vertices[i].x; cloud->points[i].y = vertices[i].y; cloud->points[i].z = vertices[i].z; std::tuple current_color; current_color = get_texcolor(color, tex_coords[i]); // Reversed order- 2-1-0 because of BGR (Blue, Green, Red) model used in camera cloud->points[i].r = std::get<2>(current_color); cloud->points[i].g = std::get<1>(current_color); cloud->points[i].b = std::get<0>(current_color); } return cloud; } void PCLConverter::convert_and_save_ply(const std::string &fileName, const rs2::points &points, const rs2::video_frame &color) { auto cloud = points_to_pcl(points, color); pcl::io::savePLYFile(fileName, *cloud); }