(originally for M. Campanelli's undergrad intern, L. Moon.)

By default, VisIt does not explicitly expose a camera position in the way that OpenGL, VTK, Maya, Blender, etc., do. Instead VisIt infers the camera position from the view normal, the focus point, the view angle, and the (horribly named) parallel scale. The formula for finding the camera position in world space coordinates is here:

http://visitusers.org/index.php?title=CameraModel#Where_the_camera_is_located

parallelScale is essentially used so that no matter the dimensions of the data set, it always appears in front of the camera and entirely within the viewport upon first draw. A better name might be cameraOffset or viewVectorScale.

(There are other annoyances if you have OpenGL or D3D experience - no way to have back facing polygons rendered differently than front facing, near/far clip planes appear to be set in world space instead of camera space, etc.)

Interactors

VisIt has three interactor styles which determine how the GUI responds to the mouse and how the camera behaves in scripts.

Trackball

The default interactor style, in this mode, the camera never actually moves. The data is spun in front, like an old Centipede arcade game trackball. "zooming" in this mode is more or less an image-space zoom, meaning, effectively the same as if you took a screenshot, opened it in photoshop, and scaled the image up (it's not quite that underneath the hood, but close enough). If you want to move the camera closer in world space while in this mode, parallelScale is the variable that controls this, but it won't let you actually enter the data space.  

Dolly

The dolly interactor style is supposedly the same as trackball, except in this case, zooming does actually move the camera closer to the data (thought in my testing it depends exactly on how the zoom is performed (sigh).)

Flythrough

Flythrough interactor mode is what the HelixCode script is using. This does allow the camera to be directly positioned in world space and to enter the data's bounds; however, since there isn't a camera position variable in the API, the position is set with the 3D view's focus attribute. It also appears that the view normal needs to be negated. Yet, parallelScale and imageZoom are still active, so those will also affect the final image. (Also, viewAngle, which should not be touched, unless trying to do an optical zoom, but that's yet another completely different type of zoom).

Unfortunately, by my testing, VisIt will often still draw things even if the vectors and positions don't make logical or geometrical sense.

Animating the Camera

So, how to actually move the camera?

Keyframing - use the GUI to set view attributes at specific times and let VisIt do the rest.

Procedural trackball - program keyframes by hand. The fly() example at http://visitusers.org/index.php?title=Fly_through shows how to do this. Each c0, c1, … is a “keyframe” and the view attributes are as how they’d be set in the GUI.

Procedural trackball 2 - figure out where the camera should be in world space at which timeframes using a normative camera model (e.g., the OpenGL camera model). Then use the Camera position formula from the wiki to calculate what the trackball mode equivalents should be. (This is what Rob S. does.) Do not switch interactor styles in the script.

Procedural flythrough - use the example in the “Setting the camera position” section at http://visitusers.org/index.php?title=Fly_through keeping in mind the overloaded use of “focus” to mean camera position and that view_normal might need to be negated (depending upon what mental camera model you’re used to.)

I’ve uploaded two example scripts and video output showing what I consider a more usual approach to animating a camera based on an OpenGL camera model. I’ve removed the cubic spline interpolation to clarify things.

fly-down-Z.py - this alters the wiki example to have the camera start on the positive Z axis, looking towards the origin at globe.silo, then move towards and through it. There is some weirdness going on after entering the data bounds which I’m not entirely sure about.

orbit.py - this takes HelixCode and makes the same kinds of changes as are in fly-down-Z.py.


  • No labels