25
$\begingroup$

I want to be able to have the camera rotate around an axis, while still remaining pointed at the center of said axis. The camera should pan around the model in a circular motion with the model always in the center of the view. How do I do this?

$\endgroup$

3 Answers 3

20
$\begingroup$

You can parent the camera to an Empty to do this. While in the 3D Viewport, press Shift + S and select Cursor to Selected or Cursor to Center. Add an empty (Shift + A > Empty > Plain Axes). Parent your camera to that empty by selecting the camera first then hold shift while selecting empty. Press Ctrl + P and select Object (Keep Transform), now you can rotate the empty 360 degrees based on Z axis so your camera will pan around in circular motion.

Camera parented to the empty

Hope you find this useful!

$\endgroup$
5
  • $\begingroup$ This is a lot more professional than the idea I had in mind, I was going to set the camera's center to origin and then rotate the camera, your way is a lot cleaner. Great answer. $\endgroup$
    – John
    Commented May 23, 2013 at 8:17
  • 7
    $\begingroup$ Instead of parenting, it would be much better to use the Track To constraint. That way you can animate the location of your camera, without having to worry about its rotation. $\endgroup$
    – jesterKing
    Commented May 23, 2013 at 11:03
  • $\begingroup$ @jesterKing feel free to add another answer if it sheds more light or an alternative approach to the question. $\endgroup$
    – iKlsR
    Commented May 23, 2013 at 13:12
  • $\begingroup$ @aditia With this method is there any way you have found to make the camera spiral in while focusing on the subject? $\endgroup$ Commented Jun 14, 2017 at 17:18
  • $\begingroup$ @JustWondering you can use constraint for that, like track-to constraint $\endgroup$
    – aditia
    Commented Jul 7, 2017 at 12:03
22
$\begingroup$

Another trick that might help is to track the camera to a target.

If you have a specific object you want to orbit around and the motion doesn't have to be absolutely circular then you can add a Track To constraint to the camera with the object in question as your target. If you keep Space as World Space <-> World Space, you'll want to switch the Up: to Y and the To: to -Z.

Instead of directly tracking to the object in question you could add an empty of course, and make sure the empty is where it should be. You then can move the camera freely around, it will keep tracking its target. Set your key frames for camera location where you need them, rotation is handled by the Track To constraint, keeping the camera trained on its target.

The quick way to do this is to first select your target, then Shift + select your camera. Shift + Ctrl + C will give you a constraint popup, select Track To. The first selected target will be automatically assigned the target for your constraint.

$\endgroup$
1
  • $\begingroup$ This is my default setup: a sun lamp and a camera tracking to an empty. (You can also select the camera, then select the target, then press Ctrl-T and select "Track To" for the same effect.) $\endgroup$ Commented Jun 28, 2013 at 0:50
1
$\begingroup$

Script versions

This is a reduced version of https://blender.stackexchange.com/a/176762/15543 The idea here is to pan around z axis at (0, 0, 0) but keep the focus of original camera. The default scene cube is at (0, 0, 0) the default camera focus does not pass through (0, 0, 0) The scripts make a duplicate camera with same transform as original scene camera such that they can scribe or follow an orbit, starting from original camera

Add empty parent

Quite simply, duplicate camera, add empty at desired location, parent camera to empty. Now rotating the empty on its local z axis makes the camera scribe a circular path.

The only property to set is the z https://blender.stackexchange.com/a/176762/15543rotation of the empty.

import bpy

context = bpy.context
scene = context.scene
cam = scene.camera

if cam:
    bpy.ops.object.empty_add(location=(0, 0, 0))
    mt = context.object
    mt.empty_display_type = 'SPHERE'
    mt.empty_display_size = 4
    cam2 = cam.copy()
    cam2.parent = mt
    context.collection.objects.link(cam2)

Note since am using the global origin as pivot point, adding a LOCAL to LOCAL copy transform constraint on copy to original, will adjust radius automatically based on originals location.

Move the camera by rotating the empty. Possibly worth noting that to see for example a turntable rotation, without reference points like grid and directional lighting could have stationary camera and spin the cube, or spin the whole scene (sans cam), spin the camera as shown, or orbit a circle path... result would appear same

Drivers

enter image description here

To animate with drivers. Add a driver to the z rotation euler property of the empty

driver = mt.driver_add("rotation_euler", 2).driver

Set the expression. For examples below No driver variables are needed as frame is "known" (a member of the driver namespace) to be current frame, as is the noise module

Spin 1 rev per 24 frames. Zero at frame 1.

driver.expression = "2 * pi * (frame - 1) / 24"

Random location on ring

driver.expression = "2 * pi * noise.random()"

IMO particularly handy for a "turntable" animation. The image above switches scene camera to active object. The first half is driver 1, the second driver 2.

Keyframes

Adds a random location at every 10th frame starting from 1, sorted by order of angle.

frames = range(1, 250, 10)
angles = sorted(random() for f in frames)
for f, a in zip(frames, angles):
    mt.keyframe_insert("rotation_euler", index=2, frame=f)

Make an orbit

Here we make a circular orbit. A camera with a follow path constraint with follow curve, tracking -X axis with Y up focuses camera with no transform on the path center.

Here is a script to add orbit, set up a new camera copy, put it on orbit.

enter image description here Once again notice that the camera is not focused on (0, 0, 0) and orbiting gives the impression of cube rotating on (0, 0, 0)

Now only the offset of the follow path constraint need be animated. 0 is same position as orginal. 1 is same position (one full orbit) At 0 and 1 the added camera match the orginal scene camera.

import bpy
from mathutils import Vector, Matrix
context = bpy.context
scene = context.scene

while scene.collection.objects:
    bpy.data.objects.remove(scene.collection.objects[0])

cam = scene.camera
mw = cam.matrix_world
r = mw.translation.xy
r3d = Vector((r.x, r.y, 0))

h = mw.translation.z
from math import degrees
R = Matrix.Rotation(
        r.angle_signed(Vector((0, -1))),
        4,
        'Z',
        )


T = Matrix.Translation((0, 0, h))

bpy.ops.curve.primitive_bezier_circle_add(
        location=(0, 0, 0),
        radius=r.length)
path = context.object 
cu = path.data
cu.transform(R @ T)

cam2 = cam.copy()
cam2.matrix_world = Matrix()
fp = cam2.constraints.new('FOLLOW_PATH')
fp.target = path
fp.use_curve_follow = True
fp.use_fixed_location = True
fp.forward_axis = 'TRACK_NEGATIVE_X'
fp.up_axis = 'UP_Y'

context.collection.objects.link(cam2)
context.view_layer.update()

cam2.matrix_basis = cam2.matrix_world.inverted() @ mw
scene.camera = cam2
context.view_layer.objects.active = cam2

Pros. Can see the orbit, can edit to be non circular.

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .