fghoussen
fghoussen

Reputation: 565

Open3D - C++: how to animate 3D point cloud

In Open3D, with C++, how to animate 3D point cloud: same question that this one in python Open3d: How to update point cloud during window running? but can't get this to work.

The following code (inspired from github repo example examples/cpp/PointCloud.cpp) compile, run (the viewer and point appears), but animation is not rendered

>> cat ../examples/cpp/PtCloud.cpp 
#include <Eigen/Dense>
#include <iostream>
#include <memory>

#include "open3d/Open3D.h"

#include <unistd.h> // sleep

using namespace open3d;

void PrintPointCloud(const std::shared_ptr<geometry::PointCloud> &pointcloud) {
    using namespace open3d;

    bool pointcloud_has_normal = pointcloud->HasNormals();
    utility::LogInfo("Pointcloud has %d points.",
                     (int)pointcloud->points_.size());

    Eigen::Vector3d min_bound = pointcloud->GetMinBound();
    Eigen::Vector3d max_bound = pointcloud->GetMaxBound();
    utility::LogInfo(
            "Bounding box is: ({:.4f}, {:.4f}, {:.4f}) - ({:.4f}, {:.4f}, "
            "{:.4f})",
            min_bound(0), min_bound(1), min_bound(2), max_bound(0),
            max_bound(1), max_bound(2));

    for (size_t i = 0; i < pointcloud->points_.size(); i++) {
        if (pointcloud_has_normal) {
            const Eigen::Vector3d &point = pointcloud->points_[i];
            const Eigen::Vector3d &normal = pointcloud->normals_[i];
            utility::LogInfo("{:.6f} {:.6f} {:.6f} {:.6f} {:.6f} {:.6f}",
                             point(0), point(1), point(2), normal(0), normal(1),
                             normal(2));
        } else {
            const Eigen::Vector3d &point = pointcloud->points_[i];
            utility::LogInfo("{:.6f} {:.6f} {:.6f}", point(0), point(1),
                             point(2));
        }
    }
    utility::LogInfo("End of the list.");
}

std::shared_ptr<geometry::PointCloud> pointcloud(new geometry::PointCloud);

bool AnimatePointCloud(visualization::Visualizer * visualizer) {
    if (!visualizer) return false;

    for (int i = 0; i < 10; i++) {
         sleep(2);
         pointcloud->points_.push_back(Eigen::Vector3d(0.0, 0.0, i+1.0));
         pointcloud->points_.push_back(Eigen::Vector3d(1.0, 0.0, i+1.0));
         pointcloud->points_.push_back(Eigen::Vector3d(0.0, 1.0, i+1.0));
         PrintPointCloud(pointcloud);
         visualizer->UpdateGeometry(pointcloud);
         visualizer->PollEvents();
         visualizer->UpdateRender();
         visualizer->Run();
    }
    return true;
}

int main(int argc, char *argv[]) {
    // 1. test basic pointcloud functions.

    pointcloud->points_.push_back(Eigen::Vector3d(0.0, 0.0, 0.0));
    pointcloud->points_.push_back(Eigen::Vector3d(1.0, 0.0, 0.0));
    pointcloud->points_.push_back(Eigen::Vector3d(0.0, 1.0, 0.0));
    PrintPointCloud(pointcloud);

    // 2. test pointcloud visualization

    visualization::Visualizer visualizer;
    visualizer.CreateVisualizerWindow("Open3D", 1600, 900);
    visualizer.AddGeometry(pointcloud);
    visualizer.RegisterAnimationCallback(AnimatePointCloud);
    visualizer.Run();
    visualizer.DestroyVisualizerWindow();

    return 0;
}

The code is supposed to animate points that stack up in animated way: the viewer seems to freeze. Didn't find any C++ example. What's wrong?

Upvotes: 0

Views: 867

Answers (1)

saurabheights
saurabheights

Reputation: 4574

There are 3 issues in your code:-

  1. First of all, AFAIK the linked SO answer is incorrect. There is no need to update visualizer from callback functions, see official docs for this. This probably will fix your problem. Also, official docs and linked answer are for python. In C++, you have less things to worry about, for example, no need to re-add geometry.

  2. The new points generated are too far away to see and easily cross visualizer view port bounds. I have updated your code to only update once every second and new points are only one centimeter away.

  3. Do not add sleep in your code. You are basically making visualizer thread sleep, hence the window becomes unresponsive.

#include <Eigen/Dense>
#include <chrono>

#include "open3d/Open3D.h"

using namespace open3d;

std::shared_ptr<geometry::PointCloud> pointcloud(new geometry::PointCloud);

std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
int pointsShiftFactor = 1;

bool AnimatePointCloud(visualization::Visualizer * visualizer) {
    if (!visualizer) return false;

    std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
    if (std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count() > 1000000) {
        begin = std::chrono::steady_clock::now();
        pointsShiftFactor += 1;
        pointcloud->points_.push_back(Eigen::Vector3d(0.0, 0.0, 0.01 * pointsShiftFactor));
        pointcloud->points_.push_back(Eigen::Vector3d(1.0, 0.0, 0.01 * pointsShiftFactor));
        pointcloud->points_.push_back(Eigen::Vector3d(0.0, 1.0, 0.01 * pointsShiftFactor));
    }
    return true;
}

int main(int argc, char *argv[]) {
    pointcloud->points_.push_back(Eigen::Vector3d(0.0, 0.0, 0.0));
    pointcloud->points_.push_back(Eigen::Vector3d(1.0, 0.0, 0.0));
    pointcloud->points_.push_back(Eigen::Vector3d(0.0, 1.0, 0.0));

    visualization::Visualizer visualizer;
    visualizer.CreateVisualizerWindow("Open3D", 1600, 900);
    visualizer.AddGeometry(pointcloud);
    visualizer.RegisterAnimationCallback(AnimatePointCloud);
    visualizer.Run();
    visualizer.DestroyVisualizerWindow();

    return 0;
}

Result -

Open3d interactive visualization of animated pointcloud

Upvotes: 0

Related Questions