Open3D C++ 3D点云动画失效问题排查
Open3D C++点云动画窗口冻结问题解决
问题背景
在Open3D C环境中实现3D点云堆叠动画时,代码可编译运行且能显示初始点,但动画无法渲染,窗口出现冻结。参考Python方案未解决,且无相关C示例。
问题根源
代码存在三个核心错误:
sleep(2)阻塞主线程:sleep会直接卡住UI渲染线程,导致窗口失去响应。- 动画回调内嵌套
visualizer->Run():Run()是阻塞式主循环,在回调中调用会彻底打乱渲染流程。 - 动画回调逻辑错误:回调函数应负责单次帧更新,而非内部写循环执行所有动画步骤。Open3D的动画回调会被主渲染循环反复调用,需控制单次回调仅完成一步更新。
修正后的代码
#include <Eigen/Dense> #include <iostream> #include <memory> #include <chrono> #include "open3d/Open3D.h" using namespace open3d; void PrintPointCloud(const std::shared_ptr<geometry::PointCloud> &pointcloud) { 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); int animation_step = 0; std::chrono::steady_clock::time_point last_update_time; bool AnimatePointCloud(visualization::Visualizer *visualizer) { if (!visualizer) return false; auto now = std::chrono::steady_clock::now(); auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(now - last_update_time).count(); if (animation_step < 10 && elapsed >= 2) { pointcloud->points_.push_back(Eigen::Vector3d(0.0, 0.0, animation_step + 1.0)); pointcloud->points_.push_back(Eigen::Vector3d(1.0, 0.0, animation_step + 1.0)); pointcloud->points_.push_back(Eigen::Vector3d(0.0, 1.0, animation_step + 1.0)); PrintPointCloud(pointcloud); visualizer->UpdateGeometry(pointcloud); visualizer->UpdateRender(); animation_step++; last_update_time = now; } return animation_step < 10; } 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)); PrintPointCloud(pointcloud); visualization::Visualizer visualizer; visualizer.CreateVisualizerWindow("Open3D", 1600, 900); visualizer.AddGeometry(pointcloud); last_update_time = std::chrono::steady_clock::now(); visualizer.RegisterAnimationCallback(AnimatePointCloud); visualizer.Run(); visualizer.DestroyVisualizerWindow(); return 0; }
关键修改说明
- 替换
sleep为时间差判断:使用std::chrono记录上次更新时间,避免阻塞UI线程,保证窗口正常响应。 - 移除回调内的
Run()调用:主循环仅在main中调用一次,回调仅处理单次帧的更新逻辑。 - 全局变量控制动画进度:通过
animation_step跟踪当前动画阶段,确保每次回调仅执行一步更新,直到完成10次循环。 - 回调返回值控制动画启停:返回
true继续动画,返回false停止,符合Open3D回调的设计规范。
内容的提问来源于stack exchange,提问作者fghoussen
相关产品推荐
相关产品推荐

