Camera Motion Zoooooom.
There are a few ways to move the camera along simple tracks that are built into AstroBlend. These include zooming in and out along a line, rotating either with fixed radius or moving radius, or motion along a Bezier curve dictated by a collection of points. Below are simple examples of how to use each.
This tutorial assumes you've gone through the the first tutorial and know how to render some images from reading simple rendering tutorial. Here we also assume you're familiar with how to add simple 3D models to your space, and more info about this can be found in the simple 3D models tutorial.
Throughout this tutorial, I'm going to assume you are working by copying and pasting the example chunks of code directly into the python console. Therefore, make sure you paste in the following before you begin:
import science
cam = science.Camera()
Also, add some colored spheres to the situation by copying and pasting the following into the console:
sph1 = science.simpleobjects.Sphere('Sphere1', color = (1,0,0), shadeless=False)
sph1.location = (0, 3, 0)
sph2 = science.simpleobjects.Sphere('Sphere2', color = (1,1,0), shadeless=False)
sph2.location = (3, 0, 0)
sph3 = science.simpleobjects.Sphere('Sphere3', color = (0,0,1), shadeless=False)
sph3.location = (0, -3, 0)
This should leave you with the following setup:
Zoom
The first way we can move our camera is to zoom in and out of wherever the camera happens to be pointing. We'll do this by setting our camera somewhere far out, like at 10 Blender units on the x axis and zooming into 5 Blender units.
# first set Blender directory
render_directory = '/Users/jillnaiman/blenderRenders/'
render_name = 'testzoom_'
# move camera out
cam.location = (10, 0, 0)
Now, all that is left to do is figure out a factor we want to zoom by zoom_factor
,
which will will set to 0.5 to half the distance of where the camera is currently sitting,
and how many steps to take to get there render_steps
as shown with this line of code:
movie = science.Movies(cam, render_directory, render_name,
render_type = 'Zoom', render_steps = 60, zoom_factor = 0.5)
If you are following the code from this tutorial, this will put the camera's final location at (5,0,0), pointing at (0,0,0). If you want to zoom the camera out just choose a number for the zoom factor which is larger than 1.
For our example, the 60 frames generated, when combined with your favorite movie maker (FFmpeg, Quicktime 7 Pro, etc), produces the following video:
Rotations
Perhaps you want to rotate around an object. An excellent choice.
The way you do this is once again using the Movies
class,
but the Rotation
keyword instead of the Zoom
keyword. This allows you to rotate around the x/y plane or along
z-axis, and can accommodate a changing radial
distance from the object you're rotating around. For reference we will be
using "phi" and "theta" from your typical
spherical coordinates to parameterize our rotations:
For this example lets first start with the camera out along the x-axis, pointing at the yellow sphere:
science.set_camera((25,0,0),(3,0,0)) # set along x axis, point at yellow sphere
The following bit of code will setup the scene, assuming a blank blend file, add the spheres, and rotate around the yellow sphere:
import science
#set up the camera
cam = science.Camera()
# create and place spheres
sph1 = science.simpleobjects.Sphere('Sphere1', color = (1,0,0), shadeless=False)
sph1.location = (0, 3, 0)
sph2 = science.simpleobjects.Sphere('Sphere2', color = (1,1,0), shadeless=False)
sph2.location = (3, 0, 0)
sph3 = science.simpleobjects.Sphere('Sphere3', color = (0,0,1), shadeless=False)
sph3.location = (0, -3, 0)
# first set render directory and frame base names
render_directory = '/Users/jillnaiman/blenderRenders/'
render_name = 'testrot_'
# move camera out
cam.location = (10, 10, 10)
# point camera at the yellow sphere
cam.pointing = sph2.location
# create a 60 frame movie
movie = science.Movies(cam, render_directory, render_name,
render_type = 'Rotation', render_steps = 60,
radius_end = 2.0, theta_end = 0.1, phi_end = 90.,
use_current_start_angles=True, use_current_radius = True)
The above code uses the optional commands use_current_start_angles = True
to
start the rotation from the camera's current angle and use_current_radius
to
start the rotation from the camera's current radius. By the end of the movie, the
camera ends up at angles (θ = 0.1, φ = 90) while the radius has shrunk down to
2 Blender units. Note that the final θ is a little above zero - this is because
setting it to exactly zero will force the camera through the pole, which would mess
up its rotation.
Below is the movie made with these commands:
Bezier Curves
The final way to move the camera around is to specify a series of camera locations and pointings, and then have AstroBlend interpolate Bezier tracks for the camera.
Bezier curves are basically a way to specify a unique curve given a series of points and tangent vectors to these points. In this case, our tangent vectors will be lines from the camera pointing points to the camera location points. A possibly helpful diagram of this for a set of two location/pointing points is below:
Now, lets pick a few points for your location and pointing curves:
locs = [[10,10,10], [10, -10, 10], [10, -10, -10]] # camera goes through these points
pts = [[0,3,0], [0, -3, 0], [0, 3, 0]] # camera will point at these points along the way
Before we place our camera along these paths and render, we might want to see how these paths actually look, just in case we want to edit them. The Bezier camera function has an option to visualize the location and pointings of our camera with points. For example, lets say we wanted to use the above points and render 60 frames. Then our full script starting from scratch would look like:
import science
cam = science.Camera()
sph1 = science.simpleobjects.Sphere('Sphere1', color = (1,0,0), shadeless=False)
sph1.location = (0, 3, 0)
sph2 = science.simpleobjects.Sphere('Sphere2', color = (1,1,0), shadeless=False)
sph2.location = (3, 0, 0)
sph3 = science.simpleobjects.Sphere('Sphere3', color = (0,0,1), shadeless=False)
sph3.location = (0, -3, 0)
# first set Blender directory
render_directory = '/Users/jillnaiman/blenderRenders/'
render_name = 'testbez_'
locs = [[10,10,10], [10, -10, 10], [10, -10, -10]] # camera goes through these points
pts = [[0,3,0], [0, -3, 0], [0, 3, 0]] # camera will point at these points along the way
# create the visualization of our camera paths and pointings
movie = science.Movies(cam, render_directory, render_name,
render_type = 'Bezier', render_steps = 60,
bezier_locations=locs, bezier_pointings=pts,
bezier_visualize=True)
Once we copy and paste these things into the python console two sets of points will be put into your 3D viewer. They will be called "bezierCurveLoc####" and "bezierCurvePts####" where "####" is some number from '0000' to '9999'. The number will automatically update each time you add or delete and add a set of curves, in case you want to plot several curves at once. If you select in the Object Selector panel the "bezierCurveLoc" set of points in our example, you should see something like the following:
The curve goes straight from [10,10,10] to [10,-10,10] in 30 frames, and then from [10,-10,10] to [10,-10,-10] in the final 30 frames. At each of the three input points, the curve of the Bezier trajectory is determined by a line connecting the input pointing coordinates and these location coordinates.
If you select the "bezierCurvePts" set of points and rotate your 3D viewer a bit, you will see something like:
Again, the above is the path of pointings for the camera as it changes locations.
Assuming you are happy with these paths and pointings, all that is left to do is render out movie frames. When you do this, all the Bezier curves you made before will be deleted automatically. We can now render out our little movie with this tidbit of code:
movie = science.Movies(cam, render_directory, render_name,
render_type = 'Bezier', render_steps = 60,
bezier_locations=locs, bezier_pointings=pts,
bezier_visualize=False)
Which produces the following short movie:
In all these examples, we have moved the camera around fixed objects. In what follows we'll go through a quick example with a time evolving model.
Time Evolving Bezier Movie
In this example, we will be using the text-formatted SPH data used in
a previous
tutorial. We will also use scaled versions of the Bezier camera pointings and locations from the
previous example, but now we will do a time evolving movie. How does this change our
code? Turns out, not a lot! All we need to do is pass the list of SPH files to
the Load
command instead of a single file and AstroBlend can figure out
if you are loading a single file or multiple. If multiple files are assigned to
myobject
then AstroBlend will only import the first file when
Load
is called.
The following code shows how to load a series of files into myobject
and then render out a time evolving movie with camera motions. The major changes
to this code are that the halo sizes has been increased since the camera
spends much of its time further out, and the number of frames in our movie has
increased to the number of files. If we had not increased the number of frames
ourselves, AstroBlend would have chosen the larger of render_steps
or the number of files listed in myobject
.
import science
# make a list of data files
ddir = '/Users/jillnaiman/data/sphdec/' # where data is stored
df = 'outputs_dec_' # base name of data files
dfiles = []
nf = 200
ns = 1
# create list of files
for i in range(ns,nf):
num = "%03d" % (i) # create strings from numbers, with 3 digits
dfiles.append(ddir + df + num + '.txt')
halo_sizes = (0.008,0.008,0.008,0.008,0.008,0.008) # halos or particles
colors = [(1,1,0), (0,0,1), (1,0,0), (1,0,0), (1,1,1), (0,1,0)]
# how many particle types?
# 0 = Gas
# 1 = Halo
# 2 = Disk (disk and bulge = old stars?)
# 3 = Bulge
# 4 = Stars (New stars?)
# 5 = BHs
particle_types = 6
# load particle data
myobject = science.Load(dfiles, scale = (0.1, 0.1, 0.1),
halo_sizes = halo_sizes, particle_num=particle_types,
particle_colors=colors)
# hide the 1st particle
part_hide = (False, True, False, False, False, False)
myobject.particle_hide = part_hide
# init camera
cam = science.Camera()
# first set Blender directory & render name
render_directory = '/Users/jillnaiman/blenderRenders/'
render_name = 'testbezsph_'
locs = [[3,3,3], [3, -3, 3], [3, -3, -3]] # camera goes through these points
pts = [[0,3,0], [0, -3, 0], [0, 3, 0]] # camera will point at these points along the way
# render out the movie
movie = science.Movies(cam, render_directory, render_name, myobject,
render_type = 'Bezier', render_steps = nf-1,
bezier_locations=locs, bezier_pointings=pts,
bezier_visualize=False)
The above code produces the little movie below: