Set Camera?

A script I am working on cycles through all the pages (scenes) in the model. This changes the camera POV so I’d like to return the user to exactly the POV where they started when complete.

I thought this would be as simple as storing the original camera…

original_cam = Sketchup.active_model.active_view.camera

then restoring it at the end of the script…

Sketchup.active_model.camera.set(cam)

but that does not work. What am I missing?

image

I guess the restoring should be:

Sketchup.active_model.active_view.camera = original_cam
1 Like

The Sketchup::Camera#set method requires 3 arguments, none of them being a Sketchup::Camera object.

Try this …

cam = Sketchup.active_model.active_view.camera
@cam_props = [cam.eye, cam.target, cam.up]

… and then later on …

Sketchup.active_model.active_view.camera.set(*@cam_props)

The “splat” (*) operator expands the @cam_props array into a parameter list.


There is an issue with trying to save the original camera like …

original_cam = Sketchup.active_model.active_view.camera

… because the SketchUp active model’s view is a singleton object, each time you ask for a reference to it’s camera, you get the same C++ object, but Ruby reports a different object ID each time (which fools us to think that we get a new camera object.)

To force the saving of a new camera object that will not be affected by view changes …

cam = Sketchup.active_model.active_view.camera
@old_cam = Sketchup::Camera.new(cam.eye, cam.target, cam.up)

… and then later on …

Sketchup.active_model.active_view.camera= @old_cam
1 Like

Thanks @dezmo that’s what I meant! I think @DanRathbun addresses the nuances of this method which seems a little squirrely.

That did it @DanRathbun! Once again, I am so impressed with the depth of your knowledge about how SU really works under the hood! I’m not sure how, just based on the API documentation, a layperson could work that out but thank the universe for you.

In addition to what @DanRathbun showed, you should also capture camera.perspective? and if that is false you will need camera.height.

2 Likes

Steve, is correct. If any of your scene’s cameras switch to parallel projection you might need to restore the camera’s perspective. For simplicity, I only showed the main 3: eye, target and up vector.

But the Camera#set method only takes the 3 main arguments.

To set the 2 two that Steve mentions.

Example 1 saving properties in an array:

cam = Sketchup.active_model.active_view.camera
@cam_props = [cam.eye, cam.target, cam.up, cam.height, cam.perspective?]

… later …

cam = Sketchup.active_model.active_view.camera.set(*@cam_props[0..2])
cam.perspective= @cam_props[4]
cam.height= @cam_props[3] if !cam.perspective?

For example 2, where we save the whole camera object, …
the Camera class constructor takes additional optional arguments.

cam = Sketchup.active_model.active_view.camera
if cam.perspective?
  @old_cam = Sketchup::Camera.new(
    cam.eye, cam.target, cam.up, cam.perspective?, cam.fov
  )
else
  @old_cam = Sketchup::Camera.new(
    cam.eye, cam.target, cam.up, cam.perspective?
  )
end
@old_height = cam.perspective? ? nil : cam.height

… later …

cam = Sketchup.active_model.active_view.camera= @old_cam
cam.height= @old_height if !cam.perspective? && @old_height

Also, the reason I showed saving as instance vars is that I don’t know whether your iterate scenes and the camera restoration are done in the same method or separated into various methods.

If it is all in the same method, then you can omit the @s and just use local variables.

1 Like

True! @slbaumgartner and @DanRathbun we do have different perspective views so that is important to catch too. Thanks again.

BTW I could not use this with now having 5 members in the @cam_props array so instead did…

cam = Sketchup.active_model.active_view.camera.set(@cam_props[0],@cam_props[1],@cam_props[2])

Yea my bad. You can also do …

cam = Sketchup.active_model.active_view.camera.set(*@cam_props[0..2])

(Corrected the above exampe.)

1 Like