user764323
user764323

Reputation: 309

Change viewport angle in blender using Python

I'm trying to find out if there is a way to change the viewport angle in blender using Python. I would like a result like you would get from pressing 1, 3, or 7 on the num. pad.

Thank you for any help

Upvotes: 8

Views: 7945

Answers (2)

Lawrence D'Oliveiro
Lawrence D'Oliveiro

Reputation: 2794

First of all, note that you can have multiple 3D views open at once, and each can have its own viewport angle, perspective/ortho settings etc. So your script will have to look for all the 3D views that might be present (which might be none) and decide which one(s) it’s going to affect.

Start with the bpy.data object, which has a window_managers attribute. This collection always seems to have just one element. However, there might be one or more open windows. Each window has a screen, which is divided into one or more areas. So you need to search through all the areas for one with a space type of "VIEW_3D". And then hunt through the spaces of this area for the one(s) with type "VIEW_3D". Such a space will be of subclass SpaceView3D. This will have a region_3d attribute of type RegionView3D. And finally, this object in turn has an attribute called view_matrix, which takes a value of type Matrix that you can get or set.

Got all that? :)

Upvotes: 9

Doug
Doug

Reputation: 35186

Once you've located the right 'view', you can modify:

view.spaces[0].region_3d.view_matrix
view.spaces[0].region_3d.view_rotation

Note that the region_3d.view_location is the 'look_at' target, not the location of the camera; you have to modify the view_matrix directly if you want to move the position of the camera (as far as I know), but you can subtly adjust the rotation using view_rotation quite easily. You'll probably need to read this to generate a valid quaternion though: http://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation

Perhaps something like this may be useful:

class Utils(object):

  def __init__(self, context):
    self.context = context

  @property
  def views(self):
    """ Returns the set of 3D views.
    """
    rtn = []
    for a in self.context.window.screen.areas:
      if a.type == 'VIEW_3D':
        rtn.append(a)
    return rtn

  def camera(self, view):
    """ Return position, rotation data about a given view for the first space attached to it """
    look_at = view.spaces[0].region_3d.view_location
    matrix = view.spaces[0].region_3d.view_matrix
    camera_pos = self.camera_position(matrix)
    rotation = view.spaces[0].region_3d.view_rotation
    return look_at, camera_pos, rotation

  def camera_position(self, matrix):
    """ From 4x4 matrix, calculate camera location """
    t = (matrix[0][3], matrix[1][3], matrix[2][3])
    r = (
      (matrix[0][0], matrix[0][1], matrix[0][2]),
      (matrix[1][0], matrix[1][1], matrix[1][2]),
      (matrix[2][0], matrix[2][1], matrix[2][2])
    )
    rp = (
      (-r[0][0], -r[1][0], -r[2][0]),
      (-r[0][1], -r[1][1], -r[2][1]),
      (-r[0][2], -r[1][2], -r[2][2])
    )
    output = (
      rp[0][0] * t[0] + rp[0][1] * t[1] + rp[0][2] * t[2],
      rp[1][0] * t[0] + rp[1][1] * t[1] + rp[1][2] * t[2],
      rp[2][0] * t[0] + rp[2][1] * t[1] + rp[2][2] * t[2],
    )
    return output

Upvotes: 8

Related Questions