TUTORIAL 8 – DNA - Molecular Movies

TUTORIAL 8 – DNA: variations on a theme
In this tutorial, we’ll explore different methods for modeling,
rigging, and animating DNA. There are many ways to
approach this macromolecule in Maya and each has its
merits depending on what the model will be used for in your
scene. We’ll start with a simple ‘plank’ DNA model that is
roughly based on what is known about the molecule’s
proportions, and then look at different ways to deform it.
Next we’ll import a PDB coordinate set for B-DNA and
experiment with different representations using particles.
These first two methods assume that the helix does not need
to unwind and melt. Finally, we’ll go over a programmatic
approach to building DNA using PDB data for a single base
pair – this method will allow us to twist and unzip the double
Before we jump in, let’s briefly review the structural features
of B-DNA that are important for our modeling efforts:
19 Å in diameter
10.5 base pairs per helical turn (~34 per base pair)
34 Å high per helical turn (~3.3 Å per base pair)
For the purposes of our initial modeling efforts (i.e. ‘plank
DNA’), we will round out these numbers to assume ~10 base
pairs per helical turn and ~20 Å in diameter.
One helical turn of ‘reference’ B-DNA created
using the cartoon representation in PyMOL
Part 1 – Plank DNA
Modeling plank DNA
In this first exercise, we’ll create a stand-in model for B-DNA
that could be useful in schematic animations where atomic
resolution is not required and melting of the double helix is
not necessary. Here’s a quick overview of the process: 1)
model a base pair with polygons, 2) animate its rotation and
elevation to use the ‘animated snapshot’ tool, 3) create 2
NURBS curves slightly offset from the base pair, 4) use the
‘animated sweep’ tool to extrude those circles and create the
backbone and finally 5) ‘duplicate special’ to create
The first base pair consists of 4 polygon cubes
additional helical turns to the model prior to rigging.
Although we’ve reviewed B-DNA’s characteristics above,
let’s also have a PDB-derived cartoon model in our scene to
make sure we have the right proportions as we go through
the modeling process. Go to the Learning section of
www.molecularmovies.org and download supporting files.
Open the ref_1helicalTurn.ma file – it’s a simple model of a
single helical turn of DNA. This was generated in PyMOL
(with the ‘cartoon’ representation), exported as a vrml2 file,
converted to an obj, and then imported into Maya. Observe
the model in various orthographic views and notice that it is
4 grid units wide and ~7 grid units high (from bottom baseTutorial 8 – DNA: variations on a theme
Fall ’08
Gaël McGill & Janet Iwasa
pair to top base-pair). As expected, this is the correct ratio
for B-DNA (i.e. 7units/4units = 34Å/20Å = ~1.7). Extend
your timeline to 800 frames and save the file as
Let’s begin by creating a single base-pair with simple
geometry. Using the polygon primitive cube tool, create a
plank that is roughly 2 units long along the x axis, ~ 0.5 units
wide along the z with just a little thickness along the y axis.
Duplicated base pairs after the animated snapshot
Duplicate the plank, scale it down slightly along the x axis,
and move it on the other side of the origin along the x axis.
Add a small plank angled at 45 degrees along the y to each
larger plank (refer to the pictures on the right for placement).
Select the 4 planks, group and name ‘bp.’
This base pair would need to rotate 360 degrees and travel
~7 grid units along the y axis to find itself one helical turn
away from where it is now. Let’s animate that displacement:
making sure you are on frame 1 of the timeline, select the
bp group and key its Translate y and Rotate y attributes in
the Channel Box (they should both be 0 by default). Now go
to frame 100, change Translate y to 7 and Rotate y to 360
– key those values and play the animation. The base pair
rises along the y axis while rotating, as if were traveling
through all of the intermediate positions where the
Placement of NURBS circles relative to the base pair
intervening 8 base pairs would be. We will use this
animation to ‘sprinkle’ a copy of the base pair at each
appropriate location along the y – to do this well use Maya’s
Animation Snapshot tool. With the bp group selected, go to
the Animation menu set and go to Animate -> Create
Animation Snapshot | Options – reset. With the Start
time set to 1, the End time set to 100 (i.e. the range of
your base pair animation), and the ‘Increment’ set to 10,
click ‘Snapshot.’ Maya plays through the specific range of
frames and takes a snapshot of the geometry every 10
frames (that’s the increment setting). Notice that it actually
left out the last base pair – this is fine in that we will be
Animation sweep settings for the backbone
duplicating the entire helical turn later and therefore would
not want this overlap. If you did want to get all 10 base pairs
in the animated snapshot, you would need to set the End
time to 101 (instead of 100) with the same increment of 10.
Although we’ve applied it in a very basic way here (we could
have used the ‘Duplicate Special’ tool here), the ‘Animated
Snapshot’ technique is a powerful method of using any kind
of animation to create duplicated geometry.
Now we’ll use a similar to tool to create the backbone.
Maya’s ‘Animated sweep’ tool, like the animated snapshot,
places new copies of geometry based on an animation – but
with 2 important differences: 1) it only works with curves and
2) it creates a lofted NURBS surface from all of these
duplicated curves. Let’s see how this works.
Create a NURBS circle and scale/position it on the grid such
that it overlaps one of the outer corners of your plank.
Duplicate Special settings to extend the DNA strand
Tutorial 8 – DNA: variations on a theme
Fall ’08
Gaël McGill & Janet Iwasa
Duplicate the circle and move/position it on the other side of
the plank (see image on the right). Make sure they are both
offset on the same side of the plank - this offset is what will
create the major and minor grooving of your DNA model (i.e.
the base pairs are centered on the helical axis, but the
backbone strands are not). Select both circles, group and
name ‘backbone circles.’ Similar to the process we used to
set up the Animated Snapshot, we’ll need to animate the
circles group – on frame 1, key the Translate y and Rotate
y values and the on frame 100, key Translate y to 7 and
Rotate y to 360. Back on frame 1 with the ‘backbone
circles’ group selected in the Outliner, go to Animate ->
Create Animated Sweep | Options (reset). Set the Start
time to 1, the End time to 101 (we’ll want the geometry to
The completed ‘plank DNA’ model
extend all the way up to 7 grid units this time) and By Time
to 10 – leave all the rest to defaults and press “Anim
Notice the snapshot5 & snapshot6 groups in the Outliner, as
well as 2 ‘loftedSurfaces.’ This shows you how the
Animated Sweep works – it first does an Animated Snapshot
operation and then lofts between the curves in the snapshot
groups. Compare your modeled DNA to the reference model
– they should be pretty much identical in terms of
proportions (except for the intentionally missing last base
pair at the top of your model). You can now hide ‘bp’
‘backbone circles’ ‘snapshot5Group’ and
Lattice settings
‘snapshot6Group’ before we proceed to growing the DNA
Select ‘snapshotGroups’ 1, 2, 3 and 4 (i.e. the base pairs)
and the 2 lofted surfaces (i.e the backbone strands) and
group them – rename the group ‘DNA.’ With this group
selected in the Outliner, go to Edit -> Duplicate Special |
Options (Reset). Use the following settings: Group under World, Translate y to 7, Number of copies to 4. You
should now have a DNA model that is 5 helical turns – the
Outliner shows every turn of the helix as a separate group.
Save you file, and then Save Scene As:
Rigging your model
There are many ways to deform this DNA model depending
on the animation goals – in this tutorial, we’ll explore a
technique where instead of creating a skeleton and skinning
it to the geometry (which is typical), we first apply a lattice to
the model and then skin the lattice to a skeleton. This can
yield faster and smoother deformations – the skeleton
controls the lattice, which in turn controls the model it is
wrapped around.
Select all the DNA groups in the Outliner and group them –
rename it ‘DNA_strand.’ With this new group selected, go
to Create Defomers -> Lattice | Options (Reset). We’ll use Adding a skeleton to your DNA model
Tutorial 8 – DNA: variations on a theme
Fall ’08
Gaël McGill & Janet Iwasa
settings that give us plenty of ‘deforming resolution’ along
the y axis: Divisions 2 10 2 (keep the rest as defaults).
You can test to see if your lattice works by RMB-clicking
over the lattice and selecting ‘Lattice Point’ from the popup. Now drag-select some points and rotate or move them
to deform the model.
Switch to the ‘front’ orthographic camera and, with your
model maximized/scaled in the viewport, go to Skeleton ->
Joint Tool and create joints from bottom to top clicking at
each ‘rung’ or division in the lattice. Press enter when you
finished creating your skeleton – you should have 10 joints
Settings for binding the lattice to the skeleton
total and your joint chain should be centered inside the
lattice by default. Return to the ‘perspective’ viewport. With
the root joint selected (i.e. joint 1 in the Outliner), shift-select
the lattice in the viewport and go Skin -> Bind Skin ->
Smooth Bind | Options (Reset). Use the following settings:
Bind Method: Closest distance, Max influences: 3 (rest at
defaults) – click on ‘Bind Skin.’ Now select a joint at the
center of the chain and rotate it – you should now see your
DNA model bending around as you control the rotation of the
joints! Save your scene.
Controlling your rig
A common way to control a skeleton is through the use of IK
(Inverse Kinematics): instead of rotating and keying the
position of every joint in a chain, IK allows you to key the
position of a single IK handle. We already explored this
when we rigged the sigma ‘tentacle’ in the Animation tutorial Rotating individuals joints deforms the lattice
along with the underlying DNA model
– for our model DNA, however, we’ll look at another type of
IK called spline IK. The main difference is that in spline IK a
curve is used to control the joint chain instead of an IK
Save your scene as plankDNA_03_rigControl.ma. To
make things easier to select and see as we add layers of
control to this rig, hide the lattice and switch your viewport to
X-Ray mode (shading -> X-Ray). To add a spline Ik
controller to your skeleton, go to Skeleton -> IK Spline
Handle Tool | Options (Reset). As per the instructions that
show up in the lower left-hand corner of your scnreen, first
click on the root joint of the skeleton (joint 1 at the bottom)
and then on the top joint of the chain. You’ll notice two new
nodes in the Outliner: an IK handle (which, unlike ‘regular
IK’, you will not be able to move) and a curve. In the ‘Show’
drop-down menu of your perspective viewport, toggle off the
visibility of ‘Joints’ and ‘IK Handles.’ What should be left at
the center of your DNA model is a blue curve. Select it and,
in the Surfaces menu set, go to Edit Curves -> Rebuild
Curves | Options (Reset) – set the Number of spans to
10, make sure it is cubic/degree 3 curve, and the ‘Keep
original’ option is off – click Rebuild. With the curve
selected, switch to component mode (F8), select one or
several CVs and move them – the DNA model is now being
Rebuilding the spline IK curve
Tutorial 8 – DNA: variations on a theme
Fall ’08
Gaël McGill & Janet Iwasa
deformed in response to the shape of the curve! Typically, if
you want start keying the shape of the curve, you would
select the CVs and create clusters for each one and key the
position of the clusters. You could also apply any deformer
to the curve – anything that influences the shape of your
curve over time will animate the DNA.
To add some organic motion to the DNA, we’re going to
convert the spline IK curve into a softbody with goals and
then apply fields. Select the curve and, in the Dynamics
menu set, go to Soft/Rigid Bodies -> Create Softbody |
Options (Reset) – use the following settings:
Creation Options: Duplicate, make original soft
(this is key since it is only the original curve that is the spline
IK and controls your skeleton).
Hide non-soft object is on
Make non-soft a goal is on
Weight: 0.3
Click ‘Create.’
Moving the CVs on the spline IK deforms the DNA
As with any particles, we’ll need to add a field to see any
effect – expand the ‘curve1’ node in the Outliner and select
the particle object under it. Go to Fields -> Turbulence |
Options (Reset) – set the magnitude to 10 and the
attenuation to 0, click Create. Select the field in the
Outliner and, in the Channel Box, add an expression to the
Phase X channel (select the channel, RMB-click over it and
select ‘Editors -> Expressions’):
Adding a Turbulence field to affect the softbody curve
If you now play the animation you should see a wiggling
DNA strand! You now have all the control that dynamics
affords you in terms of how the DNA follows the goal curve
(fields, springs, goalPP, etc…). Instead of a softbody we
could also have turned the spline IK curve into Maya hair –
this option gives you even more attributes and control over a
goal weight value for the softbody. If you want to add more
‘directed’ animation and motion to your DNA on top of the
dynamic/organic wiggling, you still have the goal curve
(hidden and called ‘copyOfcurve1) to animate. You could
add clusters to each of the CVs and then key their positions
and/or add non-linear deformers to the curve. For an
example of both of these deformations, view the
plankDNA.mov example movie associated with this tutorial
on molecularmovies.org (and see the picture to the right).
Fully rigged DNA model (includes clusters & sine
deformer on spline IK goal curve)
Tutorial 8 – DNA: variations on a theme
Fall ’08
Gaël McGill & Janet Iwasa
Part 2 - Imported PDB DNA
pdbReader & ballAndStick MEL scripts
In this section of the tutorial we’ll import a PDB file for an
entire strand of B-DNA using Tom Doeden’s pdbReader
script that creates NURBS spheres at every PDB coordinate
point. The original script has been around for while and can
be downloaded form www.highend3d.com. We will actually
be using a version of the script that was slightly modified by Sourcing a MEL script from the script editor
Geordie Martinez (www.negative13.com) so that it works
with his ballAndStick MEL script. The latter script will allow
us to add bonds (NURBS cylinders) between atoms
generated by the pdbReader script. Another approach will
also be to take the spheres generated by the pdbReader
script and, instead of adding bonds, we’ll use a MEL script to
create a particle at every sphere (jPivToParticle created by
Julian Mann) and then use the blobby sphere render type to
render the DNA.
An important note before we jump into this section – this part
of the tutorial is heavily influenced by THE original tutorial on
the use of these scripts: Eric Keller’s now famous “Working
with Macromolecular Data in Maya: DNA” which can be
found on www.highend3d.com. Kudos to Eric
(www.bloopatone.com) for initially putting this material
together into a tutorial – it has been widely used since it’s
initial print publication in Highend3D magazine. The
following is just my ‘reimplementation’ of the steps as they
relate to an audience of scientists.
Start with a new Maya scene and go to the script editor –
under File -> Source Script… find the pdbReader.mel
script. Nothing will happen when you click ‘Open.’ To run
The pdbReader.mel script window
the script, type ‘pdbReader’ in the MEL command line at
the bottom left of the Maya interface – hit enter, and a small
pop-up window should appear. At the top click on “Get PDB
File” and search for the DNA.pdb file that you downloaded
along with the other materials for this tutorial. Once loaded
into the window, you will notice that the “Sample line of data Imported sphere model in the perspective viewport
from the file” is now populated with typical PDB data – this
takes a little experimenting as the columns may be slightly
different for different PDBs… but the goal is to find the right x
y z coordinate columns and specify them in the X Field, Y
Field, Z Field in the script window. In the case of this PDB,
enter 3 for the Atom Field, and 7, 8, 9, for the X, Y, Z
Field values respectively. Now click on ‘PRESS ME –
Create Molecule Structure.’
This may take a few moments – you will know Maya is done
when you see four new nodes in the Outliner called
‘PhosphorusGrp’, ‘OxygenGrp’ etc… If you click in the
perspective viewport to unselect any geometry and then
press F, your camera should now zoom out to encompass
The ballAndStick.mel script window
Tutorial 8 – DNA: variations on a theme
Fall ’08
Gaël McGill & Janet Iwasa
the imported model. As is typical with imported PDB data,
the model is large and far away from the grid. Press 5 to
view the shaded model. You’ll notice that the pdbReader
script has assigned a different shader to each atom – very
convenient. Let’s resist the urge to scale and center the
model until we have played with the ballAndStick script a bit.
In the MEL command line, type ‘ballAndStick’ and press
Enter – a pop-up window appears. Read Geordie’s
comments – he goes over the basics of how the script works
and provides default values that work well to create bonds.
As suggested, let’s begin by resizing all of the spheres in our
DNA model – open each of the 4 atom groups in the Outliner
and select the long list of spheres within each group,
scale each down to 0.5 in the Channel Box. Now let’s test Sticks added to part of the DNA model
the script – marquee-select a few spheres (~1 base pair
equivalent) in the perspective viewport and run the script by
pressing ‘Generate Sticks.’ You should see light grey
cylinders appear between atoms in your selection. Repeat
the operation a few times by selecting different sets of
atoms. To view the fully-shaded bonds, go to Renderer ->
High Quality Rendering in your perspective viewport dropdown menu.
Creating particles with jPivToParticle
In the Outliner, delete the ‘StickGroup’ that was generated
as a result of running the ballAndStick script. Select the
remaining 4 main groups (PhosphorusGrp, OxygenGrp
etc…) and group them – name the group ‘DNA.’ Now with
this new group selected, scale it down to 0.2 and center
pivot. Move the model to the center of the grid and switch
between orthographic views to straighten the model. Freeze
transformations on the master group ‘DNA’ and the four
If you inspect the model and expand the groups in the
Outliner you’ll notice that the spheres are all very low
tessellation NURBS which is what makes this script so great.
Indeed, a sphere model imported from any molecular
graphics program would yield polygonal spheres with high
tessellation (with the exception of Jmol which now has an
export to the .ma file type and yields NURBS spheres –
thanks to Bob Hanson for that Jmol feature!). In any case,
despite this lighter geometry, it is still almost unworkable
when dealing with medium to large models of proteins for
example. Converting the spheres to particles increases
performance and, for some like Drew Berry, is also a
preferred means of rendering molecules (using Hardware
rendering as opposed to Software rendering).
To run the jPivToParticle script, begin by ungrouping all
spheres in the Outliner: select the 4 main groups and go
to Edit -> Ungroup. You should now have a long list of
NURBS objects with various atom names listed directly
The model scaled down and centered at the origin
Tutorial 8 – DNA: variations on a theme
Fall ’08
Gaël McGill & Janet Iwasa
under the DNA group. Select all the spheres in the
Outliner and, in the MEL command line, type jPivToParticle
“DNA_” and press Enter. A new particle object should
appear in the Outliner, all the names of the spheres now
start with DNA_ and have a number. You can now select
the DNA master group and hide it – what should remain in
the viewport is a mist of grey particle points. Each sphere
has been replaced with a single particle and all the particles
belong to the same particle object. This last point is critical it‘s what will allow us to get a blobby look between the DNA
atoms (this would not happen if each atom type was in its
own particle object – i.e. blobbies don’t form blobbies
between particle objects).
Select the particle object and, in the Attribute Editor, switch
the render attributes to ‘Blobby Surface [s/w]’ – click on
Current Render Type and reduce the radius to 0.3. Take
a render and click the “Keep Image” button (little open grey
box with a black arrow pointing down into it). Now increase
the Threshold value to 0.45 and take another render –
compare the two images.
After running the jPivToParticle script, particles are
positioned at each sphere location in the model.
Points are switched to ‘blobby surfaces’ for rendering.
Now that your model is made of particles, there are a
number of ways to control it. Since Maya version 6, you can
also add non-linear deformers to particles. For an example
of a bend-deformer applied to this model, view the
blobbyDNA.mov example movie associated with this
tutorial on molecularmovies.org
DNA rendered with blobby surfaces: Threshold=0
DNA rendered with blobby surfaces: Threshold=0.45
Tutorial 8 – DNA: variations on a theme
Fall ’08
Gaël McGill & Janet Iwasa
Part 3 - Creating a DNA rig by Janet
In this section of the tutorial, you will use PDB reader and
some rigging tricks to create a segment of DNA that can
undergo strand twisting and untwisting as well as strand
Importing nucleotides using PDB reader
The primary building block that we're going to use to create
our rig is two nucleotides base paired to one another. I
created a PDB for you to use by taking a PDB of doublestranded DNA, and rather laboriously deleting everything but
two paired bases (plus some extra atoms for alignment).
Scaling the atoms of the base pair to have a more
conventional spacefilling look.
If you haven't already sourced the PDB reader script, go to
the script editor, select File > Source Script and select the
PDBreader plugin. In the MEL command line, type
"pdbReader" and press Enter. Run pdbReader as you've
done in the previous example, using "oneBP.pdb" as the
input pdb file.
After you import the basepair, if you take a look at it (frame
using the 'f' key in the perspective view), you'll see that the
atoms are sort of small. Draw a selection box around all of
the atoms of the basepair and scale them up so that they
have a more conventional space-filling look.
In the perspective window, select the atoms of one of the
nucleotides, press ctrl+g to create a new group, and name it
"baseL" in the outliner (by double clicking on the name).
Select the atoms of the other nucleotide, create a new
group, and name it "baseR."
Create groups for the left and right nucleotides.
Note that the atom type groups that were created by
PDBreader ("NitrogenGrp," "CarbonGrp," etc) are now empty
and can be deleted.
Select baseL and baseR in the outliner and group them
together, naming the new group "pair0."
Center the pivot of pair0 (Modify > Center Pivot) and move
pair0 to the center of the grid using grid snapping (by
keeping x depressed while moving). Rotate pair0 so that the
bases are approximately flat along the x-z plane, and scale
to 0.5. Freeze the transformations of pair0 (Modify > Freeze
Creating a double stranded helix
Top orthogonal and side orthogonal views of the
pair0 after adjusting rotation and scale.
Tutorial 8 – DNA: variations on a theme
Fall ’08
Gaël McGill & Janet Iwasa
Select pair0 in the outliner and duplicate it (ctrl+d). This
duplicate should be named "pair1" by default. In the channel
box, change the rotation Y value to 36. Move pair1 around
in X, Y and Z to align it so that pair 1 has overlapping
oxygens with pair0 (refer to image on right). Do this without
changing any of the rotation values; only change the
translate values! This might be tough depending on how you
set up pair0, and don't worry if it isn't perfect. If the oxygens
are impossibly far apart, delete pair1 and go back and adjust
the rotation of pair0, making sure to freeze transformations
after you make your adjustments.
Delete one of each of the overlapping oxygens (doesn't
matter which one). Now select pair1 in the outliner and take
a look at its translate coordinates in the channel box
(remember, the rotations should all be 0 except rotate Y,
which should be 36). With pair1 still selected, go to Edit >
Duplicate Special and open the options box.
In the Duplicate Special Options window, input the translate
values for X, Y and Z of pair1 into the translate boxes.
Change the rotate Y value to 36, and change number of
copies to 19. Press 'Duplicate Special.'
Top orthogonal and side orthogonal views of the pair1
and pair0, with overlapping oxygens shown in green for
You should now have a nice helical model of DNA.
Building a DNA untwister
In order to unwind our DNA, we need to change the Y
rotation coordinates for each of our pairs to 0. We could do
this manually, or better, brainstorming a bit and coming up
with some clever MEL tricks.
One way that we can imagine how to rig the DNA twist is by
imagining that the bottommost pair (pair0) is fixed, and that
the topmost pair (pair20) is free to rotate in Y, and that its
rotation will determine the rotation of all the other basepairs.
Imagine, for example, holding a rope ladder from the top
rung and rotating that rung around, with the bottommost rung
being tied down to the ground, and thus unable to rotate.
Duplicate Special Options box for creating 19 duplicates
of pair1 with the correct translation and rotation values.
To get started, we need to figure out what the rotation is for
the topmost pair. If you click on pair20 and check out its Y
rotation, you'll see that it's 0. Each 10th base should return
to 0 since each base's Y rotation is offset by 36 degrees.
This means that you can think of the Y rotation value of
pair10 as 360 and pair20 as 720. Change the Y rotation
value of pair20 to 720.
Since base0 will always be 0, all the basepairs in between
(base2 through base19) will be a fraction of the Y rotation of
base20, such that base20 would be the master rotation
controller of all of the basepairs underneath it. For this, we
would want the Y rotation of base19 to be 19/20th the Y
rotation of base20, base18 should be 18/20th, and so on.
The DNA after duplicating pair1. You should have 21
basepairs in all.
Tutorial 8 – DNA: variations on a theme
Fall ’08
Gaël McGill & Janet Iwasa
We could do this using expressions that control the Y
rotation of each pair. To see how expressions are handled
in MEL, let's go through one example.
Select pair19, select "RotateY" in the channel box and right click. Select "expressions" from the drop down menu.
Type in the following expression:
rotateY = pair20.rotateY * 0.95;
and press 'Create.' (note that 0.95 is 19/20). You shouldn't notice any difference since the rotation value should
be the same as it was before, but now if you rotate pair20, you should see that pair19 rotates with it (but always
slightly less). Take a look at the MEL that was used to create the expression by opening the script editor
(Window > General Editors > Script Editor). You should see a line that looks something like this:
expression -s "rotateY = pair20.rotateY * .95;" -o pair5 -ae 1 -uc all;
We want to use MEL to create this expression for pairs2 through pair19. First, make sure that the expression is
no longer controlling pair19's rotation by selecting 'RotateY' in the channel editor and selecting 'Break
Connections' from the drop-down menu.
Now to implement the plan, type in the following in the script editor:
for ($i=1; $i<=19; $i++) {
float $rotY = $i * 0.05;
expression -s ("rotateY = pair20.rotateY * " + $rotY + ";") -o ("pair" + $i) -ae 1 -uc all;
Select the text and press control+Enter to run it without clearing the text (which makes things easier to edit in
case you made a mistake).
Let's go through what the script is doing.
for ($i=1; $i<=19; $i++) {}
This is a for loop, similar to ones we've done before, where
anything in the curly brackets will be done 19 times (starting
with 1 and ending with 19).
float $rotY = $i * 0.05;
Here we're creating a variable, $rotY, which will determine
what fraction of pair20's Y rotation will be given to the
basepairs below it. In this case, we want pair1 to have a Y
rotation that is 0.05 (or 1/20th), pair2 to have 0.1 (or 2/20th),
and so on.
expression -s ("rotateY = pair20.rotateY * " + $rotY + ";")
-o ("pair" + $i) -ae 1 -uc all;
For this line we simply copied and pasted from the line we
saw earlier when we created a new expression, but edited it
so that the pair name ("pair" + $i) changes dynamically while
working through the for loop. Within the expression, we're
combining a string ("rotateY = pair20.rotateY * ") with a float
value ($rotY, which we defined in the previous line).
Pair20 is now controlling the Y rotation of all the
bases underneath it.
Tutorial 8 – DNA: variations on a theme
Fall ’08
Gaël McGill & Janet Iwasa
Take a look at the Y rotation in the channel box for each of
the pairs betwen 1 and 19. You should see that the box is
purple, and when you right click and select 'Expressions...,'
you can view and edit the expression you made with the
Now if you change the value of pair20's Y rotation, you
should see that all of the pairs below follow.
Creating a DNA Master Controller
Next, we're going to build a master controller that's going to
let us control our DNA's movements a little more intuitively.
Creating a new attribute called 'twist' for the
Create a new null group by selecting Create > Empty Group. masterController. Note the channel box on right is blank.
In your outliner, you should notice that you now have
something called "null1." Rename the empty group
We're going to be creating our own attributes for our
masterController, and won't be needing any of the default
ones. In the channel box, click-drag over everything (from
TranslateX to Visibility), and with them selected, right click
and select "Hide Selected" from the drop down menu.
Now we'll create a new attribute. Right click in the empty
channel box and select "Attributes -> Add Attribute" from the
dropdown menu. In the window that appears, name the
attribute "twist," make sure that's it's data type is "float" and
set the minimum to 0, the maximum to 1, and the default to
1. Select "Add." Create another new attribute called
"separate" with the same settings, except have the default
value be 0.
The channel box of the masterController now has two
new attributes.
So what are we going to have this master controller do? We
want the twist value of the master controller to control the
rotateY value of pair20, which will in turn control the rotation
of the pairs below it. When twist is at 0, we want the rotateY
of pair20 to also be at 0, but when twist is set to 1, we want
pair20 to be 720.
To set up this relationship, we'll use the "setDriven"
technique. Select pair20 in the outliner, then, in the
Animation menu, go to Animate > Set Driven Key > Set... A
new window should appear, with pair20 appearing in the
lower, "Driven" area. Now select the masterController in the
outliner, and in the Set Driven Key window, click on "Load
Driver." In the right section, next to "masterController," click
on "twist." In the bottom right, next to "pair20," click on
What this sets up is a relationship where we can have the
masterController's twist attribute controlling the rotateY of
Setting up the driver and driven objects.
Tutorial 8 – DNA: variations on a theme
Fall ’08
Gaël McGill & Janet Iwasa
pair20. Now we need to set keys to determine the range of
Make sure that the twist attribute of the masterController is set to 1, and the rotateY attribute of pair20 is set to
720 in the channel box. Then click on "Key" in the Set Driven Key window.
Now set the twist attribute of the masterController to 0, and set the rotateY of pair20 to 0 as well, and click on
"Key" in the Set Driven Key window again.
Now change the Twist value of the masterController. It
should be controlling the twist of the DNA. A nice way to do
this is to click on "Twist" in the channel box (the text should
highlighted in black on a PC - as shown in the image on the
right – and blue on a Mac), and middle mouse drag in the
perspective window. This should allow you to dynamically
change the attribute.
Set the Twist value to 0. You probably already noticed that
when all of the pairs Y rotation is set to 0, the DNA looks
quite wavy. How can we fix this?
The problem is due to the fact that when we originally
created the helix, we moved the pairs in X and Z, and these
movements were repeated along the length of the helix.
Ideally, we'd like to keep the current values of translateX and
translateZ when the helix is completely twisted, but have
them set to 0 for when twist is set to 0.
When twist is set to 0, the DNA looks wavy.
Let's set up some more set driven keys to do this, but using MEL. If you take a look at your script editor, you
should notice that the command to create a set driven key is pretty simple:
setDrivenKeyframe -currentDriver masterController.twist pair20.rotateY;
The -currentDriver flag indicates the driver (the twist attribute of the masterController) and the last argument
(pair20.rotateY) determines what's being driven.
Type in the following into the script editor:
for ($i=1; $i<=19; $i++) {
setAttr "masterController.twist" 1;
setDrivenKeyframe -currentDriver masterController.twist ("pair" + $i + ".translateX");
setAttr "masterController.twist" 0;
setAttr ("pair" + $i + ".translateX") 0;
setDrivenKeyframe -currentDriver masterController.twist ("pair" + $i + ".translateX");
Run the script (highlight it and hit Ctrl-Enter) and try changing the twist value of the masterController to check if
it's working. You should see that now the translateX is moving to 0 when twist is 0, but translate Z hasn't been
fixed yet. Run the previous expression again (you can cut and paste it from the upper part of the script editor)
and replace all three instances of "translateX" with "translateZ."
Breaking down the script:
setAttr "masterController.twist" 1;
Tutorial 8 – DNA: variations on a theme
Fall ’08
Gaël McGill & Janet Iwasa
"setAttr" is short for "set Attribute" and sets, in this case, the twist attribute of the masterController to 1. The
translateX (or Z) value should already be set to whatever we want it to be when twist is 1, so we can go ahead
and set the driven key:
setDrivenKeyframe -currentDriver masterController.twist ("pair" + $i + ".translateX");
In the 2nd half of the script, we're repeating the same thing
after setting twist to 0 and translateX of the pair to 0.
The last thing that we want the masterController to do is to
separate the two strands of DNA.
In the outliner, take a look at the hierarchy of your DNA.
Each pair is made up of a "baseL" and a "baseR." For our
strand separation, we'd like baseL and baseR to move in
opposite directions from the origin. Depending on how you
arranged your DNA, baseL may need to go in the +X, -X, +Z
or -Z direction, and baseR in the opposite direction along the
same axis. Figure this out before the next step!
Now we'll just write a little more MEL to have the
masterController's 'separate' attribute control strand
separation. We will be using the exact same setDriven
technique as we have before.
Type in the following script into the Script Editor (keeping in
mind that you’ll need to replace “translateX” and “5” with
whatever axis and +/- value for 5 works in your case)
Very straight DNA when twist is set to 0
for ($i=0; $i<=20; $i++) {
setAttr "masterController.separate" 1;
setAttr ("pair" + $i + "|baseL.translateX") 5;
setDrivenKeyframe -currentDriver masterController.separate ("pair" + $i + "|baseL.translateX");
setAttr "masterController.separate" 0;
setAttr ("pair" + $i + "|baseL.translateX") 0;
setDrivenKeyframe -currentDriver masterController.separate ("pair" + $i + "|baseL.translateX");
Now test out the script by changing the masterController
separate attribute. You should see that the left bases move
away as the separate value gets larger. For the right bases,
repeat the script above, but replace the "baseL" with "baseR"
(four instances) and the 5 with -5 (or vice versa).
After extending your timeline to ~200 frames, you can now
key the twist channel from 0 (on frame 1) to 1 (on frame
~100). Now key the separate channel to 0 on frame 1, set
another key of 0 at frame ~ 80, and then a value of 1 on
frame 150. You can see that having a masterController like
this could make your life much easier as you're trying to
animate. Rather than needing to set keyframes on a large
number of objects (42 bases, or 21 pairs of bases, in this
case), we only need to set a single keyframe of a
masterController attribute.
A bit of Twist & Separation.
Tutorial 8 – DNA: variations on a theme
Fall ’08
Gaël McGill & Janet Iwasa