Open3d's easy draw_geometries
utility makes it possible to copy & paste camera parameters to restore a certain view point after it has been changed. It seems like this functionality would also be available when using the SceneWidget
and its Open3DScene
high level scene. However I have not figured out a way to mimic this behavior.
Copying and pasting a viewpoint from draw_geometries
onto notepad reveals this information:
boundingbox_max
, boundingbox_min
, field_of_view
, front
, lookat
, up
, zoom
In order for it to have the same effect using the SceneWidget
I would have to somehow obtain this information from the scene's camera, create a copy, and then load it later when it is needed. Nevertheless, I cannot access the above properties explicitly through the camera object, nor have I found a way to set them (assuming I already have them).
The next "obvious" solution would be the camera class's copy_from method, which sounds great, except I am unable to instantiate the Camera
class in order to use it.
How can I achieve this save & restore viewpoint effect?
Thanks in advance
In the end I was able to figure out two solutions. I could not figure out a way to instantiate the Camera
class in order to use the copy_from
method. A neat way around this problem is to create a second SceneWidget
that will not be shown and simply act as a buffer. Using the SceneWidget.Open3DScene
's camera property it is possible to copy to and from the main scene's camera. In summation, bind a key that saves the main camera to the buffer scene's camera, and another key to restore it.
This solution however only allows copying and pasting viewpoints for a single runtime of the application, so we need to save the camera parameters to a file. Using the default camera movement pattern, it appears that only the camera itself moves and rotates around the object. Through the camera's get_model_matrix()
method, we get a 4x4
matrix. The last column corresponds to the camera position and the first 3x3
matrix represents a composite rotation. We extract and save the following information
m = camera.get_model_matrix()
rot = model[:3, :3]
pos = model[:3, 3]
An then, in order to restore the viewpoint we use the SceneWidget
's look_at(point, camera_position, camera_up)
, as follows:
camera_dir = np.dot(rot, np.array([[0],[0],[-1]])).squeeze()
scene.look_at(pos + camera_dir, pos, np.array([0,1,0]))
Since by default the camera looks towards the screen (-z) we multiply the direction vector by the rotation matrix we save earlier, and obtain a point on the direction vector as pos + camera_dir
.
Warning! This does not account for the direction of the up vector. If the viewpoint you want to save is upside down, the up vector should be (0,-1,0)
.