Worm Animation

Index


Creating A New Seamless File

First we need to create a new smls file.

Click on the new smls file button

and save the new smls file as wormAnimation.smls


Create the Part Structure

Open the scene tree window

Create a structure of 8 parts and name them as shown

Like this each Part except for seg0 will have a parent Part it belongs to. We will later see how each parent Part will have an affect on their descendants when they are animated.


Generating the Triangles

Drag a new GroupBuild to the Seamless node
Select the part named seg0 and click (so that a CylinderBuild referencing seg0 is added to the GroupBuild)

Select the CylinderBuild
set height to .4
set radius to .05
set staves to 8
set bands to 8
uncheck topCap
uncheck baseCap


In the 3d window:

we should now see the triangles generated for seg0 in the form of a cylinder. The cylinder should have a radius of .05 meters (baseRad = .05) and it should contain 8 staves (8 flat vertical faces), 8 bands with each band equaling .05 meters in height ( .05 * 8 = .4 )

Because we dont need to see the nodes contained in the GroupBuild for a while, collapse the GroupBuild node:




Transferring Ownership to the Rest of the Parts

At this stage Part seg0 contains all the vertices. To share the vertices out to the other 7 parts, we will use 7 TransferVertex nodes.

Drag a new GroupBuild as a sibling below the last GroupBuild



Drag 7 new TransferVertex nodes to the new GroupBuild and reference the source and destination parts as shown:


Note the source references are distinguished from the dest(ination) references by the blue dot in the scene tree window.
To drag a part as a source reference, drag to the upper half of the TransferVertex icon:



To drag a part as a dest(ination), drag to the lower half of the TransferVertex icon:


 

Node:
A blue arrow indicates the cursor is in the source region of the icon.
A red arrow indicates the cursor is in the dest(tination) region of the icon.

Set the first TransferVertex node's fromVertex to 16 so that we are left with 2 rings of vertices in Part seg0. Leave the numOf field to the default -1 value. -1 is interpreted as a very large number. This will cause the first TransferVertex node to transfer the ownership of all vertices after the first 16 vertices in seg0 to seg1, leaving seg0 to own the first 2 rings of vertices in the cylinder.

Set the rest of the TransferVertex node's fromVertex field to 8 so that we have one ring of vertices left for the remaining Parts

We can verify if we have the correct vertices owned by a part. If we click on a vertex in the 3d window the 3d window's title bar will display the part the vertex is owned by. (the part that has ownership over the vertex)


Collapse the GroupBuild node that contains the TransferVertex nodes.

Centering the Parts

At this stage we have all the part's owning a portion of the vertices in the cylinder but the parts are not yet ready to be animated because they are all centred at the base of the cylinder, that is if we select any part we will see the the yellow dot at the base of the cylinder. Because each part rotates around it's yellow dot when animated this will not do. To change the center of each part we will use the CenterJoint node. The CenterJoint node centers the part it USEes to a location calculated by averaging all the locations of the vertices specified.

Drag a new GroupBuild as a sibling of the last GroupBuild.
Drag 8 new CenterJoint nodes to the new GroupBuild and reference the parts as shown:

Set the first CenterJoint's baseVertex to 8 and it's numOf to 8 so that seg0 is centered to it's top ring of vertices. baseVertex specifies the vertex (by it's index) the averaging will begin from and numOf specifies how many vertices there after to average. (The coordIndex displayed in the top left of the 3d window shows the selected vertex's index)

Set the rest of the CenterJoints each with a numOf field set to 8 and each baseVertex left set to 0

Now if we select seg0 we will see the yellow dot in the center of it's top ring of vertices and all the rest of the parts when selected will show the yellow dot in the center of their ring of vertices. This means our cylinder is now ready to be animated like a worm.


Tip. To see the yellow dot exactly on the line of vertices for the selected part same as shown above go to settings and unchecked perspective.

Collapse the GroupBuild node that contains the CenterJoint nodes.


Coloring The Vertices

At this stage all the parts are ready for animation but I think it would be sad to write the rest of the tutorial before our worm is colored unless we want it white.
To color the vertices we will use a ColorSweep node.
We could add the ColorSweep node to the build field so that it is immediately after the CenterJoint node but if we put it here we would have to USE all 8 Parts for the ColorSweep's part field in order to color all the vertices in the cylinder.
Build nodes function sequentially during a build cycle. When we use build nodes we are writing a simple program ie. the build nodes are a sequence of instructions. So how an instruction functions may depend where it is put in the program.
Understanding this fact, instead of putting the ColorSwep node after the last CenterJoint node we will insert it immediately after the Stem node. Here it will only have to USE seg0 to color all of the vertices.

Expand The top GroupBuild node containing the CylinderBuild and drag a new ColorSweep as a sibling below the CylinderBuild.
Reference seg0 for the ColorSweep.


 

Select the ColorSweep.
Check the ColorSweep node's straight field.
Make count for the number of color elements = 9
Set the location field to 0 -.001 0
Set the color and distance fields to:
 

index distance color
0
1 1 0
1 .05 1 1 0
2 .05 1 0 0
3 .05 1 1 0
4 .05 1 0 0
5 .05 1 1 0
6 .05 1 0 0
7 .05 1 1 0
8 .052 1 0 0


Now our  worm has it's traditional red and yellow stripes :) 
but feel free to color it any way you like. How it is colored will have no affect on the the rest of the tutorial.

Note The reason for having location =0 -.001 0 and the last distance element = .052 instead of .05 is so that all the vertices are ensured of being overlapped slightly.


Animating The Parts

We can easily animate all the segments using a standard VRML OrientationInterpolator which is explained in my minimalist tutorial but here I will show how anyone can easily use a Seamless3d RotAccelerator node to create sophisticated looking movement.

Add a time sensor node to the scene node paste/children/new/TimeSensor
Add a RotAccelerator node as a sibling below the TimeSensor node paste/sibling below/new/RotAccelerator
Set the TimeSensor's cycleInterval to 4
Check the TimeSensor's loop
Add a ROUTE from the TimeSensor's fraction_changed  TO the RotAccelerator's set_fraction paste/fraction_changed/TO/set_fraction (copy the RotAccelerator first)

In the TimeSensor node we should now see the ROUTE we added:

For the RotAcclerator:
Set fracMult to 4 so that it matches the 4 seconds specified in the TimeSensor's cycleInterval
Set count to 1 so that we have only one envelope for the angle to begin with
Set axis to 0 0 1 so that the rotation will rotate on the z axis
Set accelerate to .4
Set attack to 1 second
Set decay to 1 second
Add 8 ROUTEs from value_changed to the 8 parts paste/value_changed/segx/rotation

We should now see the worm animate.

The following graph shows the envelope for our RotAccelerator's angle:


Returning the Rotations Back to Where They Start

We can add more envelopes by incrementing the count button.
Which envelope we are editing will depend on the index.
All of the envelopes are combined to produce a single rotation value. This is the value (value_changed) sent to the parts.
The envelopes smoothly change rotation values starting with the value specified by init.

We will now make the worm come back to where it starts smoothly:
Add another envelope by setting count to 2
For index 1:
Set delay to 2 seconds
Set attack to 1 second
Set decay to 1 second
Right click on the RotAccelerator node in the scene tree and select calculate acceleration for return

Now we see a worm bending back and forth smoothly but always to the left never the right. To make it so it bends equal amounts in both directions set init to 0 0 1 -.2

Notes:

The timing periods (delay, attack sustain and decay) must be specified  before commanding calculate acceleration for return

calculate acceleration for return calculates for the envelope whose index is specified (currently being edited)

The returning envelop should be timed (delay, attack, sustain and decay ) so that it is the last envelope to finish however the return envelope can start before the earlier envelopes finish.

If any of the earlier envelopes are changed we must re-calculate acceleration for return for the return envelope.

If 2 envelopes have exactly the same values but one runs on an opposite axis, the two envelopes will cancel each other out.

An envelope wont work properly if attack = 0 for the versions of Seamless3d so far


Inverting Rotations

If we make the last 4 parts in the worm rotate in an opposite direction we can make our animation more interestingly complex.

Delete the 4 ROUTEs TO seg4, seg5, seg6 and seg7 from the RotAccelerator. (right click on the ROUTEs in the control panel and select delete this ROUTE)

Add a RotFilter as a sibling below the RotAccelerator paste/sibling below/new/RotFilter


Add a ROUTE from the RotAccelerator's value_changed TO the RotFilfer's inRot paste/value_changed/TO inRot

Set the RotFilter's angle to -1
Add 4 ROUTEs from the RotFilter's outRot TO seg4, seg5, seg6 and seg7 paste/outRot/TO segx/rotation

Now we should see the last 4 parts rotate in the opposite direction to the first 4 :)
The Rot Filter simply multiplies the numbers in the axis and angle fields (as individual floats one at a time not as a rotation multiplication function like the RotMult does) with the incoming rotations and sends the modified values out to the parts.
By changing the angle field from 1 to -1 we invert the angle component in the rotations.
We can invert any of the axis components (x, y and z) the same way as well.  Nice and simple isn't it?


Cat Tail Like Effects

To create a cat tail like effect we wont need the RotFilter any more but we will add 1 more TimeSensors and 1 more RotAccelerator.
The 2 RotAccelerators will have identical values only the ROUTEs will be different to each other.
Like the last lesson we will have the last 4 parts rotate different to the first 4 but instead of simply inverting the rotations for the last 4 parts we will delay the time they bend to the first 4 parts.
This can be easily done by setting the first TimeSensor's startTime to a different time to the first. For example if the first TimeSensor's startTime is left at 0 but the second TimeSensor's startTime is set to 1 the second will delay the second RotAccelerator behind in time by 1 second. Simple enough?

First delete the RotFilter node from the last lesson

Right click on the TimeSensor and select copy
Right click on the TimeSensorr and select paste/sibling below/copy of
Repeat the same for the RotAccelerator (making copy ofs saves a lot of time compared to pasting in a new RotAccelerator because a copy of has all the values we want here)

DEFine the two TimeSensors and RotAccelerators

Add a ROUTE from timeSensor1's fraction_changed TO rotAccelerator1's set_fraction

Add 4 ROUTEs from rotAccelerator1's value_changed TO seg4's, seg5's, seg6's and seg7's rotation

Now we should see our worm animating the same as it did in lesson Animating The Parts
Set timeSensor1's startTime to 2 and we see exactly the same effect we got in the last lesson where we inverted the last 4 parts to get this effect.
Set timeSensor1's startTime to 3 and we should see our worm animating quite different to any lesson before.
Set timeSensor1's startTime to 1 and we see movement in our worm that reminds me much of how a cat's or tiger's tail moves .

We can see from this how powerful it is to simply delay parts different amounts of time.

Note. The two RotAccelerator nodes field values remain identical. We did not change any of the RotAccelerator's delay fields for this lesson.



To be continued, how to make ripple effects for things like fish tails and flags





Copyright © 2000-2006 Graham Perrett thyme@seamless3d.com