# 68. `opengl.camera` — OpenGL camera handling

Python OpenGL framework for pyFormex

This OpenGL framework is intended to replace (in due time) the current OpenGL framework in pyFormex.

3. 2013 Benedict Verhegghe and the pyFormex project.

## 68.1. Classes defined in module opengl.camera

class `opengl.camera.``ViewAngles`(data={'back': (180.0, 0.0, 0.0), 'bottom': (0.0, -90.0, 0.0), 'front': (0.0, 0.0, 0.0), 'iso0': (45.0, 45.0, 0.0), 'iso1': (45.0, 135.0, 0.0), 'iso2': (45.0, 225.0, 0.0), 'iso3': (45.0, 315.0, 0.0), 'iso4': (-45.0, 45.0, 0.0), 'iso5': (-45.0, 135.0, 0.0), 'iso6': (-45.0, 225.0, 0.0), 'iso7': (-45.0, 315.0, 0.0), 'left': (270.0, 0.0, 0.0), 'right': (90.0, 0.0, 0.0), 'top': (0.0, 90.0, 0.0)})

  A dict to keep named camera angle settings.

  This class keeps a dictionary of named angle settings. Each value is a tuple of (longitude, latitude, twist) camera angles. This is a static class which should not need to be instantiated.

  There are seven predefined values: six for looking along global coordinate axes, one isometric view.

  `get`(name)

    Get the angles for a named view.

    Returns a tuple of angles (longitude, latitude, twist) if the named view was defined, or None otherwise

class `opengl.camera.``Camera`(focus=[0.0, 0.0, 0.0], angles=[0.0, 0.0, 0.0], dist=1.0)

  A camera for 3D model rendering.

  The Camera class holds all the camera parameters related to the rendering of a 3D scene onto a 2D canvas. These includes parameters related to camera position and orientation, as well as lens related parameters (opening angle, front and back clipping planes). The class provides the required matrices to transform the 3D world coordinates to 2D canvas coordinates, as well as a wealth of methods to change the camera settings in a convenient way so as to simulate smooth camera manipulation.

  The basic theory of camera handling and 3D rendering can be found in a lot of places on the internet, especially in OpenGL related places. However, while the pyFormex rendering engine is based on OpenGL, the way it stores and handles the camera parameters is more sophisticated than what is usually found in popular tutorials on OpenGL rendering. Therefore we give here a extensive description of how the pyFormex camera handling and 3D to 2D coordinate transformation works.

  Camera position and orientation:

  > The camera viewing line is defined by two points: the position of the camera and the center of the scene the camera is looking at. We use the center of the scene as the origin of a local coordinate system to define the camera position. For convenience, this could be stored in spherical coordinates, as a distance value and two angles: longitude and latitude. Furthermore, the camera can also rotate around its viewing line. We can define this by a third angle, the twist. From these four values, the needed translation vector and rotation matrix for the scene rendering may be calculated.

  > Inversely however, we can not compute a unique set of angles from a given rotation matrix (this is known as ‘gimball lock’). As a result, continuous (smooth) camera rotation by e.g. mouse control requires that the camera orientation be stored as the full rotation matrix, rather than as three angles. Therefore we store the camera position and orientation as follows:

  > - ctr: [ x,y,z ] : the reference point of the camera: this is always a point on the viewing axis. Usually, it is set to the center of the scene you are looking at.
  > - dist: distance of the camera to the reference point.
  > - rot: a 3x3 rotation matrix, rotating the global coordinate system thus that the z-direction is oriented from center to camera.

  > These values have influence on the Modelview matrix.

  Camera lens settings:

  > The lens parameters define the volume that is seen by the camera. It is described by the following parameters:

  > - fovy: the vertical lens opening angle (Field Of View Y),
  > - aspect: the aspect ratio (width/height) of the lens. The product fovy * aspect is the horizontal field of view.
  > - near, far: the position of the front and back clipping planes. They are given as distances from the camera and should both be strictly positive. Anything that is closer to the camera than the near plane or further away than the far plane, will not be shown on the canvas.

  > Camera methods that change these values will not directly change the Modelview matrix. The `loadModelview()` method has to be called explicitely to make the settings active.

  > These values have influence on the Projection matrix.

  Methods that change the camera position, orientation or lens parameters will not directly change the related Modelview or Projection matrix. They will just flag a change in the camera settings. The changes are only activated by a call to the `loadModelview()` or `loadProjection()` method, which will test the flags to see whether the corresponding matrix needs a rebuild.

  The default camera is at distance 1.0 of the center point [0.,0.,0.] and looking in the -z direction. Near and far clipping planes are by default set to 0.1, resp 10 times the camera distance.

  Properties:

  - modelview: Matrix4: the OpenGL Modelview transformation matrix
  - projection: Matrix4: the OpenGL Projection transformation matrix
  `modelview`

    Return the current modelview matrix.

    This will recompute the modelview matrix if any camera position parameters have changed.

  `projection`

    Return the current projection matrix.

    This will recompute the projection matrix if any camera lens parameters have changed.

  `viewport`

    Return the camera viewport.

    This property can not be changed directly. It should be changed by resizing the parent canvas.

  `focus`

    Return the camera reference point (the focus point).

  `dist`

    Return the camera distance.

    The camera distance is the distance between the camera eye and the camera focus point.

  `perspective`

    Return the perspecive flag.

    If the perspective flag is True, the camera uses a perspective projection. If it is False, the camera uses orthogonal projection.

  `rot`

    Return the camera rotation matrix.

  `upvector`

    Return the camera up vector

  `axis`

    Return a unit vector along the camera axis.

    The camera axis points from the focus towards the camera.

  `setAngles`(angles)

    Set the rotation angles.

    angles is either:

    - a tuple of angles (long,lat,twist)
    - a named view corresponding to angles in view_angles
    - None
  `eye`

    Return the position of the camera.

  `lock`(onoff=True)

    Lock/unlock a camera.

    When a camera is locked, its position and lens parameters can not be changed. This can e.g. be used in multiple viewports layouts to create fixed views from different angles.

  `report`()

    Return a report of the current camera settings.

  `dolly`(val)

    Move the camera eye towards/away from the scene center.

    This has the effect of zooming. A value > 1 zooms out, a value < 1 zooms in. The resulting enlargement of the view will approximately be 1/val. A zero value will move the camera to the center of the scene. The front and back clipping planes may need adjustment after a dolly operation.

  `pan`(val, axis=0)

    Rotate the camera around axis through its eye.

    The camera is rotated around an axis through the eye point. For axes 0 and 1, this will move the focus, creating a panning effect. The default axis is parallel to the y-axis, resulting in horizontal panning. For vertical panning (axis=1) a convenience alias tilt is created. For axis = 2 the operation is equivalent to the rotate operation.

  `tilt`(val)

    Rotate the camera up/down around its own horizontal axis.

    The camera is rotated around and perpendicular to the plane of the y-axis and the viewing axis. This has the effect of a vertical pan. A positive value tilts the camera up, shifting the scene down. The value is specified in degrees.

  `move`(dx, dy, dz)

    Move the camera over translation (dx,dy,dz) in global coordinates.

    The focus of the camera is moved over the specified translation vector. This has the effect of moving the scene in opposite direction.

  `setLens`(fovy=None, aspect=None)

    Set the field of view of the camera.

    We set the field of view by the vertical opening angle fovy and the aspect ratio (width/height) of the viewing volume. A parameter that is not specified is left unchanged.

  `resetArea`()

    Set maximal camera area.

    Resets the camera window area to its maximum values corresponding to the fovy setting, symmetrical about the camera axes.

  `setArea`(hmin, vmin, hmax, vmax, relative=True, focus=False, center=False, clip=True)

    Set the viewable area of the camera.

    Note: Use relative=False and clip=False if you want to set the zoom exactly as in previously recorded values.

  `zoomArea`(val=0.5, area=None)

    Zoom in/out by shrinking/enlarging the camera view area.

    The zoom factor is relative to the current setting. Values smaller than 1.0 zoom in, larger values zoom out.

  `transArea`(dx, dy)

    Pan by moving the vamera area.

    dx and dy are relative movements in fractions of the current area size.

  `setClip`(near, far)

    Set the near and far clipping planes

  `setTracking`(onoff=True)

    Enable/disable coordinate tracking using the camera

  `setProjection`()

    Set the projection matrix.

    This computes and sets the camera’s projection matrix, depending on the current camera settings. The projection can either be an orthogonal or a perspective one.

    The computed matrix is saved as the camera’s projection matrix, and the lensChanged attribute is set to False.

    The matrix can be retrieved from the projection attribute, and can be loaded in the GL context with loadProjection().

    This function does nothing if the camera is locked.

  `loadProjection`()

    Load the Projection matrix.

    If lens parameters of the camera have been changed, the current Projection matrix is rebuild. Then, the current Projection matrix of the camera is loaded into the OpenGL engine.

  `pickMatrix`(rect, viewport=None)

    Return a picking matrix.

    The picking matrix confines the scope of the normalized device coordinates to a rectangular subregion of the camera viewport. This means that values in the range -1 to +1 are inside the rectangle.

    Parameters:

    - rect: a tuple of 4 floats (x,y,w,h) defining the picking region center (x,y) and size (w,h)
    - viewport: a tuple of 4 int values (xmin,ymin,xmax,ymax) defining the size of the viewport. This is normally left unspecified and set to the camera viewport.
  `eyeToClip`(x)

    Transform a vertex from eye to clip coordinates.

    This transforms the vertex using the current Projection matrix.

    It is equivalent with multiplying the homogeneous coordinates with the Projection matrix, but is done here in an optimized way.

  `clipToEye`(x)

    Transform a vertex from clip to eye coordinates.

    This transforms the vertex using the inverse of the current Projection matrix.

    It is equivalent with multiplying the homogeneous coordinates with the inverse Projection matrix, but is done here in an optimized way.

  `lookAt`(focus=None, eye=None, up=None)

    Set the Modelview matrix to look at the specified focus point.

    The Modelview matrix is set with the camera positioned at eye and looking at the focus points, while the camera up vector is in the plane of the camera axis (focus-eye) and the specified up vector.

    If any of the arguments is left unspecified, the current value will be used.

  `rotate`(val, vx, vy, vz)

    Rotate the camera around current camera axes.

  `setModelview`(m=None, angles=None)

    Set the Modelview matrix.

    The Modelview matrix can be set from one of the following sources:

    - if mat is specified, it is a 4x4 matrix with a valuable Modelview transformation. It will be set as the current camera Modelview matrix.
    - else, if angles is specified, it is a sequence of the three camera angles (latitude, longitude and twist). The camera Modelview matrix is set from the current camera focus, the current camera distance, and the specified angles. This option is typically used to change the viewing direction of the camera, while keeping the focus point and camera distance.
    - else, if the viewChanged flags is set, the camera Modelview matrix is set from the current camera focus, the current camera distance, and the current camera rotation matrix. This option is typically used after changing the camera focus point and/or distance, while keeping the current viewing angles.
    - else, the current Modelview matrix remains unchanged.

    In all cases, if a modelview callback was set, it is called, and the viewChanged flag is cleared.

  `loadModelview`()

    Load the Modelview matrix.

    If camera positioning parameters have been changed, the current Modelview matrix is rebuild. Then, the current Modelview matrix of the camera is loaded into the OpenGL engine.

  `toEye`(x)

    Transform a vertex from world to eye coordinates.

    This transforms the vertex using the current Modelview matrix.

    It is equivalent with multiplying the homogeneous coordinates with the Modelview matrix, but is done here in an optimized way.

  `toWorld`(x)

    Transform a vertex from eye to world coordinates.

    This transforms the vertex using the inverse of the current Modelview matrix.

    It is equivalent with multiplying the homogeneous coordinates with the inverse Modelview matrix, but is done here in an optimized way.

  `toWindow`(x)

    Convert normalized device coordinates to window coordinates

  `fromWindow`(x)

    Convert window coordinates to normalized device coordinates

  `toNDC`(x, rect=None)

    Convert world coordinates to normalized device coordinates.

    The normalized device coordinates (NDC) have x and y values in the range -1 to +1 for points that are falling within the visible region of the camera.

    Parameters:

    - x: Coords with the world coordinates to be converted
    - rect: optional, a tuple of 4 values (x,y,w,h) specifying a rectangular subregion of the camera’s viewport. The default is the full camera viewport.

    The return value is a Coords. The z-coordinate provides depth information.

  `toNDC1`(x, rect=None)

    This is like toNDC without the perspective divide

    This function is useful to compute the vertex position of a 3D point as computed by the vertex shader.

  `project`(x)

    Map the world coordinates (x,y,z) to window coordinates.

  `unproject`(x)

    Map the window coordinates x to object coordinates.

  `inside`(x, rect=None, return_depth=False)

    Test if points are visible inside camera.

    Parameters:

    - rect: optional, a tuple of 4 values (x,y,w,h) specifying a rectangular subregion of the camera’s viewport. The default is the full camera viewport.
    - return_depth: if True, also returns the the z-depth of the points.

    Returns a boolean array with value 1 (True) for the points that are projected inside the rectangular are of the camera. If return_depth is True, a second array with the z-depth value of all the points is returned.

  `loadModelView`()

    Load the Modelview matrix.

    If camera positioning parameters have been changed, the current Modelview matrix is rebuild. Then, the current Modelview matrix of the camera is loaded into the OpenGL engine.

## 68.2. Functions defined in module opengl.camera

`opengl.camera.``gl_projection`()

  Get the OpenGL projection matrix

`opengl.camera.``gl_modelview`()

  Get the OpenGL modelview matrix

`opengl.camera.``gl_viewport`()

  Get the OpenGL viewport

`opengl.camera.``gl_loadmodelview`(m)

  Load the OpenGL modelview matrix

`opengl.camera.``gl_loadprojection`(m)

  Load the OpenGL projection matrix

`opengl.camera.``gl_depth`(x, y)

  Read the depth value of the pixel at (x,y)

`opengl.camera.``normalize`(x, w)

  Normalized coordinates inside a window.

  Parameters:

  - x: an (np,nc) array with coordinates.
  - w: a (2,nc) array with minimal and width of the window that will be mapped to the range -1..1.

  Returns an array with the x values linearly remapped thus that values w[0] become -1 and values w[0]+w[1] become +1.

`opengl.camera.``denormalize`(x, w)

  Map normalized coordinates to fit a window

  Parameters:

  - x: an (np,nc) array with normalized coordinates.
  - w: a (2,nc) array with minimal and width values of the window.

  Returns an array with the x values linearly remapped thus that values -1 coincide with the minimum window values and +1 with the minimum+width values.

`opengl.camera.``perspective_matrix`(left, right, bottom, top, near, far)

  Create a perspective Projection matrix.

`opengl.camera.``orthogonal_matrix`(left, right, bottom, top, near, far)

  Create an orthogonal Projection matrix.

`opengl.camera.``pick_matrix`(x, y, w, h, viewport)

  Create a pick Projection matrix