11 #include <IJsonConvertibleIO.h>
18 #include "io/PointCloudIO.h"
23 #if defined(BUILD_GUI)
31 namespace visualization {
35 #if defined(BUILD_GUI)
46 glewExperimental =
true;
47 const GLenum init_ret = glewInit();
55 bool is_headless = (glfwGetPlatform() == GLFW_PLATFORM_NULL);
57 if (init_ret != GLEW_OK && init_ret != GLEW_ERROR_NO_GLX_DISPLAY) {
59 if (is_headless && init_ret == GLEW_ERROR_NO_GL_VERSION) {
61 "GLEW initialization returned GLEW_ERROR_NO_GL_VERSION in "
62 "headless mode, continuing anyway.");
64 const std::string err_msg{
reinterpret_cast<const char *
>(
65 glewGetErrorString(init_ret))};
78 glEnable(GL_DEPTH_TEST);
82 glPixelStorei(GL_PACK_ALIGNMENT, 1);
83 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
86 glEnable(GL_CULL_FACE);
89 glReadBuffer(GL_FRONT);
95 glfwMakeContextCurrent(
window_);
112 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex_w, tex_h, 0, GL_RGB,
114 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
115 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
116 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
121 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, tex_w,
123 glBindRenderbuffer(GL_RENDERBUFFER, 0);
124 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
128 glEnable(GL_MULTISAMPLE);
131 glClearColor((GLclampf)background_color(0), (GLclampf)background_color(1),
132 (GLclampf)background_color(2), 1.0f);
134 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
143 opt = &optIt->second;
152 if (reset_bounding_box) {
160 boundingbox.GetMaxExtent() * 0.2,
161 boundingbox.GetMinBound());
176 std::string clipboard_string;
181 glfwSetClipboardString(
window_, clipboard_string.c_str());
185 const char *clipboard_string_buffer = glfwGetClipboardString(
window_);
186 if (clipboard_string_buffer !=
NULL) {
187 std::string clipboard_string(clipboard_string_buffer);
190 trajectory) ==
false) {
210 glfwMakeContextCurrent(
window_);
215 screen_image.
data_.data());
219 auto image_ptr = std::make_shared<geometry::Image>();
223 for (
int i = 0; i < screen_image.
height_; i++) {
224 memcpy(image_ptr->data_.data() + bytes_per_line * i,
225 screen_image.
data_.data() +
226 bytes_per_line * (screen_image.
height_ - i - 1),
234 std::string png_filename =
filename;
235 std::string camera_filename;
236 if (png_filename.empty()) {
238 png_filename =
"ScreenCapture_" + timestamp +
".png";
239 camera_filename =
"ScreenCamera_" + timestamp +
".json";
251 screen_image.
data_.data());
259 for (
int i = 0; i < screen_image.
height_; i++) {
260 memcpy(png_image.
data_.data() + bytes_per_line * i,
261 screen_image.
data_.data() +
262 bytes_per_line * (screen_image.
height_ - i - 1),
267 png_filename.c_str());
269 if (!camera_filename.empty()) {
271 camera_filename.c_str());
299 std::vector<float> float_buffer(depth_image.
height_);
300 float *p = (
float *)depth_image.
data_.data();
301 for (
int j = 0; j < depth_image.
width_; j++) {
302 glReadPixels(j, 0, 1, depth_image.
height_, GL_DEPTH_COMPONENT, GL_FLOAT,
303 float_buffer.data());
304 for (
int i = 0; i < depth_image.
height_; i++) {
305 p[i * depth_image.
width_ + j] = float_buffer[i];
311 GL_DEPTH_COMPONENT, GL_FLOAT, depth_image.
data_.data());
316 auto image_ptr = std::make_shared<geometry::Image>();
322 for (
int i = 0; i < depth_image.
height_; i++) {
323 float *p_depth = (
float *)(depth_image.
data_.data() +
325 (depth_image.
height_ - i - 1));
326 float *p_image = (
float *)(image_ptr->data_.data() +
327 image_ptr->BytesPerLine() * i);
328 for (
int j = 0; j < depth_image.
width_; j++) {
329 if (p_depth[j] == 1.0) {
333 2.0 * z_near * z_far /
335 (2.0 * (double)p_depth[j] - 1.0) * (z_far - z_near));
336 p_image[j] = (float)z_depth;
344 double depth_scale ) {
345 std::string png_filename =
filename;
346 std::string camera_filename;
347 if (png_filename.empty()) {
349 png_filename =
"DepthCapture_" + timestamp +
".png";
350 camera_filename =
"DepthCamera_" + timestamp +
".json";
372 std::vector<float> float_buffer(depth_image.
height_);
373 float *p = (
float *)depth_image.
data_.data();
374 for (
int j = 0; j < depth_image.
width_; j++) {
375 glReadPixels(j, 0, 1, depth_image.
width_, GL_DEPTH_COMPONENT, GL_FLOAT,
376 float_buffer.data());
377 for (
int i = 0; i < depth_image.
height_; i++) {
378 p[i * depth_image.
width_ + j] = float_buffer[i];
384 GL_DEPTH_COMPONENT, GL_FLOAT, depth_image.
data_.data());
395 for (
int i = 0; i < depth_image.
height_; i++) {
396 float *p_depth = (
float *)(depth_image.
data_.data() +
398 (depth_image.
height_ - i - 1));
399 uint16_t *p_png = (uint16_t *)(png_image.
data_.data() +
401 for (
int j = 0; j < depth_image.
width_; j++) {
402 if (p_depth[j] == 1.0) {
406 2.0 * z_near * z_far /
408 (2.0 * (double)p_depth[j] - 1.0) * (z_far - z_near));
409 p_png[j] = (uint16_t)
std::min(std::round(depth_scale * z_depth),
416 if (!camera_filename.empty()) {
418 camera_filename.c_str());
428 bool convert_to_world_coordinate ) {
429 std::string ply_filename =
filename;
430 std::string camera_filename;
431 if (ply_filename.empty()) {
433 ply_filename =
"DepthCapture_" + timestamp +
".ply";
434 camera_filename =
"DepthCamera_" + timestamp +
".json";
456 std::vector<float> float_buffer(depth_image.
height_);
457 float *p = (
float *)depth_image.
data_.data();
458 for (
int j = 0; j < depth_image.
width_; j++) {
459 glReadPixels(j, 0, 1, depth_image.
width_, GL_DEPTH_COMPONENT, GL_FLOAT,
460 float_buffer.data());
461 for (
int i = 0; i < depth_image.
height_; i++) {
462 p[i * depth_image.
width_ + j] = float_buffer[i];
468 GL_DEPTH_COMPONENT, GL_FLOAT, depth_image.
data_.data());
472 if (convert_to_world_coordinate) {
481 for (
int i = 0; i < depth_image.
height_; i++) {
482 float *p_depth = (
float *)(depth_image.
data_.data() +
484 for (
int j = 0; j < depth_image.
width_; j++) {
485 if (p_depth[j] == 1.0) {
489 Eigen::Vector3d(j + 0.5, i + 0.5, p_depth[j]), mvp_matrix,
496 ply_filename.c_str());
498 if (!camera_filename.empty()) {
500 camera_filename.c_str());
508 std::string json_filename =
filename;
509 if (json_filename.empty()) {
511 json_filename =
"RenderOption_" + timestamp +
".json";
514 json_filename.c_str());
static std::shared_ptr< ccMesh > CreateCoordinateFrame(double size=1.0, const Eigen::Vector3d &origin=Eigen::Vector3d(0.0, 0.0, 0.0))
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
void addPoint(const CCVector3 &P)
Adds a 3D point to the database.
Contains both intrinsic and extrinsic pinhole camera parameters.
The Image class stores image with customizable width, height, num of channels and bytes per channel.
Image & Prepare(int width, int height, int num_of_channels, int bytes_per_channel)
Prepare Image properties and allocate Image buffer.
int height_
Height of the image.
int BytesPerLine() const
Returns data size per line (row, or the width) in bytes.
int width_
Width of the image.
std::vector< uint8_t > data_
Image storage buffer.
Defines rendering options for visualizer.
std::vector< ViewParameters > view_status_
std::vector< std::shared_ptr< glsl::GeometryRenderer > > utility_renderer_ptrs_
std::shared_ptr< geometry::Image > CaptureDepthFloatBuffer(bool do_render=true)
void CaptureDepthPointCloud(const std::string &filename="", bool do_render=true, bool convert_to_world_coordinate=false)
Function to capture and save local point cloud.
virtual bool InitOpenGL()
Function to initialize OpenGL.
std::shared_ptr< ccMesh > coordinate_frame_mesh_ptr_
void CaptureScreenImage(const std::string &filename="", bool do_render=true)
Function to capture and save a screen image.
std::unordered_set< std::shared_ptr< const ccHObject > > geometry_ptrs_
std::unordered_map< std::shared_ptr< glsl::GeometryRenderer >, RenderOption > utility_renderer_opts_
std::unique_ptr< RenderOption > render_option_ptr_
void ResetViewPoint(bool reset_bounding_box=false)
Function to reset view point.
GLuint render_depth_stencil_rbo_
std::unordered_set< std::shared_ptr< glsl::GeometryRenderer > > geometry_renderer_ptrs_
std::shared_ptr< geometry::Image > CaptureScreenFloatBuffer(bool do_render=true)
Function to capture screen and store RGB in a float buffer.
virtual void Render(bool render_screen=false)
std::unique_ptr< ViewControl > view_control_ptr_
void CaptureRenderOption(const std::string &filename="")
void CopyViewStatusFromClipboard()
void CopyViewStatusToClipboard()
void CaptureDepthImage(const std::string &filename="", bool do_render=true, double depth_scale=1000.0)
std::shared_ptr< glsl::CoordinateFrameRenderer > coordinate_frame_mesh_renderer_ptr_
bool ReadIJsonConvertibleFromJSONString(const std::string &json_string, cloudViewer::utility::IJsonConvertible &object)
bool WriteIJsonConvertible(const std::string &filename, const cloudViewer::utility::IJsonConvertible &object)
bool WriteIJsonConvertibleToJSONString(std::string &json_string, const cloudViewer::utility::IJsonConvertible &object)
bool WriteImage(const std::string &filename, const geometry::Image &image, int quality=kCloudViewerImageIODefaultQuality)
bool WritePointCloud(const std::string &filename, const ccPointCloud &pointcloud, const WritePointCloudOption ¶ms)
std::string GetCurrentTimeStamp()
Returns current time stamp.
Eigen::Matrix< float, 4, 4, Eigen::ColMajor > GLMatrix4f
Eigen::Vector3d Unproject(const Eigen::Vector3d &screen_point, const GLMatrix4f &mvp_matrix, const int width, const int height)
Generic file read and write utility for python interface.