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?
3 Answers
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.
Hope you find this useful!
-
$\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$– JohnCommented 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$ 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$– iKlsRCommented 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$– aditiaCommented Jul 7, 2017 at 12:03
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.
-
$\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
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
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.
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.