Getting at advanced camera "image_width" field, or focal length, or camera type via SDK

In the Sketchup exporter plugin I’m writing, I want to be able to write out the camera lens that’s being used.
Ideally, I’d be able to query that in the API, but even without it, I can almost get it… The other piece of information I need is the “image_width” of the particular advanced camera that the user is using. If I reach into the cameras.csv file I can read it, but that assumes I know which camera they’ve chosen.

Given the horizontal field of view and the image_width in mm, I can calculate the focal length of the lens with a little trig:

focalLength = (width/2) / tan(hFOV/2)

so… Does anyone know how to read and of the following:

  • the particular “advanced camera” that is being used for a given scene
  • the “image_width” field of that camera
  • the focal length of the camera

SketchUp knows all three of these, but as far as I can tell, there’s no API for me to get that info.

The properties that the Advanced Camera Tools store is added to the group containing the camera/page it represent:

Looking at the code I see that ACT matches the page name to the name attribute in the camera dictionary and that it looks for that in Groups and ComponentInstances in the model root - it does not traverse into the depths of the model hierarchy. It appear that the extension assumes that the camera objects are at all times in the root of the model.

As for these other properties you want to read, I think we might be missing some in the C API - it doesn’t have full parity with the Ruby API yet. @Paul, @bugra - are any of the properties that Michael available?

I see in our code that SketchUp defaults to 36mm width - but I’m not sure when and if this is changed.

Interesting. I did notice that the ruby API for the Camera object has all the info I need:

http://www.sketchup.com/intl/en/developer/docs/ourdoc/camera

I will look at my code and try and see if I can introspect via the API on the group that the camera is and report back.

In the meantime, can I call out to the Ruby API from within my C++ plug-in? That would be an easy workaround for now…

The Ruby API is only available from within SketchUp. I assume you are creating your exporter using out C API? It’s rather an either or situation at this moment.

I can dig into the code further tomorrow and see if the default width is in practise always used or not. I’m not sure what the `iw¬ attribute is - it might be “image_width” but I need to look into the ACT’s code.

Are you only interested in the properties of the ACT camera - not actually the current view’s camera or the scene cameras?

I’m interested in any of the cameras - the act ones seemed to be the only ones that let me have a very specific filmic aspect ratio in the viewer, though. My clients model in SketchUp, but then use the “scenes” to place cameras in specific locations, and I want to make sure I export those out correctly to our application.

And yes, I’m writing my exporter with the C API.

There are other extensions that might set the aspect ratio. My V-Ray Tools does this. It doesn’t create geometric representation of the cameras, but the model’s camera’s aspect ratio gets set and get the safe frames bar.

Looking at the ACT code these are what the attributes it set represent:

# Set the attributes on the representation
  #
  # Args:
  # - camera: a Sketchup::Camera whose properties will be stored as attributes
  #   in the camera rep
  # - name: an optional name that will be stored in the name attribute
  #
  def set_attributes(camera, name = nil)
    return nil if not @rep

    # Make this look like a single operation
    model = @rep.model

    # First get the camera attributes on the entity.
    attributes = @rep.attribute_dictionary('camera', true)

    # Now assign the values
    attributes['name'] = name if name

    perspective = camera.perspective?
    attributes['p'] = perspective
    if perspective
      attributes['fov'] = camera.fov
    else
      attributes['h'] = camera.height
    end
    attributes['ar'] = camera.aspect_ratio
    attributes['iw'] = camera.image_width
    attributes['description'] = camera.description
  end

So for ACT cameras, even if the C API might not expose all the properties you can extract them from the attributes stored in the camera groups.

So I finally got around to looking at this, and even in scenes that are using the ACT cameras, none of my scene entities have any dictionaries. Here’s the code, in case I’m doing something silly:

std::vector scenes(num_scenes);
SU_CALL(SUModelGetScenes(model_, num_scenes, &scenes[0], &num_scenes));
for (size_t def = 0; def < num_scenes; ++def) {
SUSceneRef scene = scenes[def];

SUEntityRef entity = SUSceneToEntity(scene);
size_t dictionaryCount = 0, actualDictionaryCount = 0;
SU_CALL(SUEntityGetNumAttributeDictionaries(entity, &dictionaryCount));
std::vector<SUAttributeDictionaryRef> dictionaries(dictionaryCount);
SUEntityGetAttributeDictionaries(entity, dictionaryCount, &dictionaries[0], &actualDictionaryCount);
std::cerr << "there are " << actualDictionaryCount << " dictionaries\n";

And this always returns 0 dictionaries.

Sorry for being unclear. The attributes are not on the scenes - they are on the groups containing the camera representation. The groups should only be located in the root of the model so you want to scan instance found there for the camera dictionary then match that up with the scene name.