Open3D icon indicating copy to clipboard operation
Open3D copied to clipboard

Changing view point in C++

Open Constantin771 opened this issue 4 years ago • 11 comments
trafficstars

Hi everybody, I want to change the view point of the visualizer in C++, but it does not work and I am running out of ideas why that is. No matter what I set front_, lookat_ or up_ to, it doesn’t change the view in the visualizer window. Here is a minimal toy example:

	// Create Visualizer and point cloud
    open3d::visualization::Visualizer vis;
    vis.CreateVisualizerWindow("Open3D");
    std::vector<Eigen::Vector3d> points = std::vector<Eigen::Vector3d>();
    for (int i = 0; i < 1000; i++)
    {
        auto tmp = Eigen::Vector3d(rand() % 100, rand() % 100, rand() % 100);
        points.push_back(tmp);
    }
    open3d::geometry::PointCloud point_cloud = open3d::geometry::PointCloud(points);
    std::shared_ptr<open3d::geometry::PointCloud> cloud_ptr = std::make_shared<open3d::geometry::PointCloud>(point_cloud);
    vis.AddGeometry(cloud_ptr);

	// Change view
    open3d::visualization::ViewControl view_control = vis.GetViewControl();
    auto view_params = open3d::visualization::ViewParameters();
    view_control.ConvertToViewParameters(view_params);
    view_params.front_ = Eigen::Vector3d(15, 30, 0);
    view_params.lookat_ = Eigen::Vector3d(2, 5, -0.3);
    view_params.up_ = Eigen::Vector3d(4, -1, 0);
    view_control.ConvertFromViewParameters(view_params);

    while (true)
    {
        vis.UpdateGeometry();
        vis.UpdateRender();
        vis.PollEvents();
    }

I can not find any examples of this, so any advice would be greatly appreciated.

best regards!

Constantin771 avatar Jan 03 '21 21:01 Constantin771

With the old viewer, use the allow_arbitrary argument. Related PR: https://github.com/intel-isl/Open3D/pull/2564

Here there is an example but in python: https://github.com/pablospe/open3D_depthmap_example

I think for the new viewer, you can take a look to this example: https://github.com/intel-isl/Open3D/blob/master/examples/python/gui/render-to-image.py

Also check the comments about the new version 0.12.0:

  • Support for arbitrary camera intrinsic matrices: A small step for the Camera class; a very anticipated step by the Open3D community
Camera::SetProjection(const Eigen::Matrix3d& intrinsics,
                               double near,
                               double far,
                               double width,
                               double height)

pablospe avatar Jan 04 '21 09:01 pablospe

Thanks for your answer, the python example works but it doesn't work in C++.

Here is my adapted code:

    open3d::visualization::Visualizer vis;
    vis.CreateVisualizerWindow("Open3D");
    vis.PollEvents();
    vis.UpdateRender();

    auto point_cloud = open3d::geometry::PointCloud();
    open3d::io::ReadPointCloud("fragment.ply", point_cloud);
    auto cloud_ptr = std::make_shared<open3d::geometry::PointCloud>(point_cloud);
    vis.AddGeometry(cloud_ptr);

    auto param = open3d::camera::PinholeCameraParameters();
    open3d::io::ReadIJsonConvertible("view_point.json", param);
    auto intrinsic = param.intrinsic_.intrinsic_matrix_;
    auto extrinsic = param.extrinsic_;
    auto view_control = vis.GetViewControl();

    param = open3d::camera::PinholeCameraParameters();
    param.intrinsic_ = open3d::camera::PinholeCameraIntrinsic();
    param.intrinsic_.intrinsic_matrix_ = intrinsic;
    param.extrinsic_ = extrinsic;
    view_control.ConvertFromPinholeCameraParameters(param, true);
    vis.UpdateRender();
    vis.Run();

This looks like a bug that is related to #2874

Constantin771 avatar Jan 10 '21 18:01 Constantin771

The python code is calling the C++ code in the end, so it should be a way to call C++ to do the same as python. What is the actual problem?

pablospe avatar Jan 10 '21 22:01 pablospe

I thought so too and I also confirmed in PyBind that I use the correct C++ functions as in your example, but it doesn't work. I have no clue why, can you perhaps check my example?

Constantin771 avatar Jan 11 '21 01:01 Constantin771

Not sure if I will be able have time to test this soon, but I will definitely give a try at some point.

Some questions. Why do you do twice param = open3d::camera::PinholeCameraParameters()? Shouldn't the following code be equivalent?

    open3d::visualization::Visualizer vis;
    vis.CreateVisualizerWindow("Open3D");

    auto point_cloud = open3d::geometry::PointCloud();
    open3d::io::ReadPointCloud("fragment.ply", point_cloud);
    auto cloud_ptr = std::make_shared<open3d::geometry::PointCloud>(point_cloud);
    vis.AddGeometry(cloud_ptr);

    auto param = open3d::camera::PinholeCameraParameters();
    open3d::io::ReadIJsonConvertible("view_point.json", param);

    auto view_control = vis.GetViewControl();
    view_control.ConvertFromPinholeCameraParameters(param, true);

    vis.PollEvents();
    vis.UpdateRender();
    vis.Run();
    vis.Destroy();

Maybe, instead of displaying it (with Run()) you could save the image with, using capture_screen_image or capture_depth_float_buffer for depth. Like in this example (python again, sorry): http://www.open3d.org/docs/release/tutorial/visualization/non_blocking_visualization.html?highlight=capture_screen_image

CaptureScreenImage (C++)

pablospe avatar Jan 11 '21 13:01 pablospe

Yes, your code is equivalent, but doesn't make a difference. Same with CaptureScreenImage.

Thanks for looking into it!

Constantin771 avatar Jan 13 '21 15:01 Constantin771

@Constantin771 So how did you run open3d on visual studio?

oguzmustafa avatar Feb 07 '21 19:02 oguzmustafa

@Constantin771 So how did you run open3d on visual studio?

I could not solve the issue sadly.

Constantin771 avatar Feb 21 '21 02:02 Constantin771

Not sure if I will be able have time to test this soon, but I will definitely give a try at some point.

Some questions. Why do you do twice param = open3d::camera::PinholeCameraParameters()? Shouldn't the following code be equivalent?

    open3d::visualization::Visualizer vis;
    vis.CreateVisualizerWindow("Open3D");

    auto point_cloud = open3d::geometry::PointCloud();
    open3d::io::ReadPointCloud("fragment.ply", point_cloud);
    auto cloud_ptr = std::make_shared<open3d::geometry::PointCloud>(point_cloud);
    vis.AddGeometry(cloud_ptr);

    auto param = open3d::camera::PinholeCameraParameters();
    open3d::io::ReadIJsonConvertible("view_point.json", param);

    auto view_control = vis.GetViewControl();
    view_control.ConvertFromPinholeCameraParameters(param, true);

    vis.PollEvents();
    vis.UpdateRender();
    vis.Run();
    vis.Destroy();

Maybe, instead of displaying it (with Run()) you could save the image with, using capture_screen_image or capture_depth_float_buffer for depth. Like in this example (python again, sorry): http://www.open3d.org/docs/release/tutorial/visualization/non_blocking_visualization.html?highlight=capture_screen_image

CaptureScreenImage (C++)

This still does not work for me. I would really appreciate it if someone could try this example too and confirm that it does not work.

Thanks :)

Constantin771 avatar May 03 '21 17:05 Constantin771

I just came across the same problem, you need to do auto &view_control = vis.GetViewControl(); meaning you must have & to do a proper reference

cbenitez81 avatar Jun 30 '21 15:06 cbenitez81

I just came across the same problem, you need to do auto &view_control = vis.GetViewControl(); meaning you must have & to do a proper reference

Yes, this fixed it for me.

cmosig avatar Sep 16 '22 09:09 cmosig