Post

Animating Transforms

Motivation

An animation changes something over time:

  • position - a car driving
  • orientation - an airplane banking
  • color - seasons changing

Animation requires control over time:

  • When to start and stop
  • How fast to go

Controlling time

  • A TimeSensor node is similar to a stop watch
    • You control the start and stop time
  • The sensor generates time events while it is running
  • To animate, route time events into other nodes

Using absolute time

  • A TimeSensor node generates absolute and fractional time events
  • Absolute time events give the wall-clock time
    • Absolute time is measured in seconds since 12:00am January 1, 1970!
    • Useful for triggering events at specific dates and times

Using fractional time

  • Fractional time events give a number from 0.0 to 1.0
    • When the sensor starts, it outputs a 0.0
    • At the end of a cycle, it outputs a 1.0
    • The number of seconds between 0.0 and 1.0 is controlled by the cycle interval
  • The sensor can loop forever, or run through only one cycle and stop

Syntax: TimeSensor

  • A TimeSensor node generates events based upon time
    • startTime and stopTime - when to run
    • cycleInterval - how long a cycle is
    • loop - whether or not to repeat cycles

XML Encoding

1
2
3
4
5
<TimeSensor
    cycleInterval='1.0'
    loop='false'
    startTime='0.0'
    stopTime='0.0'/>

Classic Encoding

1
2
3
4
5
6
TimeSensor {
  cycleInterval 1.0
  loop FALSE
  startTime 0.0
  stopTime 0.0
}

Using timers

To create a continuously running timer:

  • loop TRUE
  • stopTime <= startTime

When stop time <= start time, stop time is ignored

To run until the stop time:

  • loop TRUE
  • stopTime > startTime

To run one cycle then stop:

  • loop FALSE
  • stopTime <= startTime

The set_startTime input event:

  • Sets when the timer should start

The set_stopTime input event:

  • Sets when the timer should stop

Using timer outputs

The isActive output event:

  • Outputs TRUE at timer start
  • Outputs FALSE at timer stop

The time output event:

  • Outputs the absolute time

The fraction_changed output event:

  • Outputs values from 0.0 to 1.0 during a cycle
  • Resets to 0.0 at the start of each cycle

A sample time sensor

XML Encoding

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<Shape>
  <Appearance>
    <Material DEF='Monolith1Facade'
        diffuseColor='0.2 0.2 0.2'/>
  </Appearance>
  <Box size='2.0 4.0 0.3'/>
</Shape>
<TimeSensor DEF='Monolith1Timer'
    cycleInterval='4.0'
    loop='false'
    startTime='0.0'
    stopTime='0.1'/>

<ROUTE fromNode='Monolith1Touch' fromField='touchTime' toNode='Monolith1Timer' toField='set_startTime'/>
<ROUTE fromNode='Monolith1Timer' fromField='fraction_changed' toNode='Monolith1Facade' toField='set_transparency'/>

Classic Encoding

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Shape {
  appearance Appearance {
    material DEF Monolith1Facade Material {
      diffuseColor 0.2 0.2 0.2
    }
  }
  geometry Box { size 2.0 4.0 0.3 }
}
DEF Monolith1Timer TimeSensor {
  cycleInterval 4.0
  loop FALSE
  startTime 0.0
  stopTime  0.1
}

ROUTE Monolith1Touch.touchTime TO Monolith1Timer.set_startTime
ROUTE Monolith1Timer.fraction_changed TO Monolith1Facade.set_transparency

Converting time to position

To animate the position of a shape you provide:

  • A list of key positions for a movement path
  • A time at which to be at each position

An interpolatorsolator node converts an input time to an output position

  • When a time is in between two key positions, the interpolatorsolator computes an intermediate position

Interpolating positions

Each key position along a path has:

  • A key value (such as a position)
  • A key fractional time

Interpolation fills in values between your key values:

Fractional TimePosition
0.00.0 0.0 0.0
0.10.4 0.1 0.0
0.20.8 0.2 0.0
0.54.0 1.0 0.0

Syntax: PositionInterpolator

A PositionInterpolator node describes a position path

  • key - key fractional times
  • keyValue - key positions

XML Encoding

1
2
3
<PositionInterpolator
    key='0.0, ...'
    keyValue='0.0 0.0 0.0, ...'/>

Classic Encoding

1
2
3
4
PositionInterpolator {
  key [ 0.0, ... ]
  keyValue [ 0.0 0.0 0.0, ... ]
}

Typically route into a Transform node’s set_translation input

Using position interpolatorsolator inputs and outputs

The set_fraction input:

  • Sets the current fractional time along the key path

The value_changed output:

  • Outputs the position along the path each time the fraction is set

A sample using position interpolatorsolators

XML Encoding

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<Transform DEF='Particle1'
  <Shape><!-- ... --></Shape>
</Transform>

<TimeSensor DEF='Timer1'
    cycleInterval='12.0'
    loop='true'
    startTime='0.0'
    stopTime='-1.0'/>

<PositionInterpolator DEF='Position1'
    key='0.0, ...'
    keyValue='0.0 0.0 0.0, ...'/>

<ROUTE fromNode='Timer1' fromField='fraction_changed' toNode='Position1' toField='set_fraction'/>
<ROUTE fromNode='Position1' fromField='value_changed' toNode='Particle1' toField='set_translation'/>

Classic Encoding

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
DEF Particle1 Transform {
  children [
    Shape { ... }
  ]
}

DEF Timer1 TimeSensor {
  cycleInterval 12.0
  loop TRUE
  startTime 0.0
  stopTime -1.0
}

DEF Position1 PositionInterpolator {
  key  [ 0.0, ... ]
  keyValue [ 0.0 0.0 0.0, ... ]
}

ROUTE Timer1.fraction_changed TO Position1.set_fraction
ROUTE Position1.value_changed TO Particle1.set_translation

Using other types of interpolatorsolators

  
Animate positionPositionInterpolator
Animate rotationOrientationInterpolator
Animate scalePositionInterpolator
Animate colorColorInterpolator
Animate transparencyScalarInterpolator

Syntax: OrientationInterpolator

A OrientationInterpolator node describes an orientation path

  • key - key fractional times
  • keyValue - key rotations (axis and angle)

XML Encoding

1
2
3
<OrientationInterpolator
    key='0.0, ...'
    keyValue='0.0 1.0 0.0 0.0, ...'/>

Classic Encoding

1
2
3
4
OrientationInterpolator {
  key [ 0.0, ... ]
  keyValue [ 0.0 1.0 0.0 0.0, ... ]
}

Typically route into a Transform node’s set_rotation input

Syntax: ColorInterpolator

ColorInterpolator node describes a color path

  • key - key fractional times
  • keyValue - key colors (red, green, blue)

XML Encoding

1
2
3
<ColorInterpolator
    key='0.0, ...'
    keyValue='1.0 1.0 0.0, ...'/>

Classic Encoding

1
2
3
4
ColorInterpolator {
  key [ 0.0, ... ]
  keyValue [ 1.0 1.0 0.0, ... ]
}

Typically route into a Material node’s set_diffuseColor or set_emissiveColor inputs

Syntax: ScalarInterpolator

ScalarInterpolator node describes a scalar path

  • key - key fractional times
  • keyValue - key scalars (used for anything)

XML Encoding

1
2
3
<ScalarInterpolator
    key='0.0, ...'
    keyValue='4.5, ...'/>

Classic Encoding

1
2
3
4
ScalarInterpolator {
  key [ 0.0, ... ]
  keyValue [ 4.5, ... ]
}

Often route into a Material node’s set_transparency input

Summary

The TimeSensor node’s fields control:

  • Timer start and stop times
  • The cycle interval
  • Whether the timer loops or not

The sensor outputs:

  • true/false on isActive at start and stop
  • absolute time on time while running
  • fractional time on fraction_changed while running

Interpolators use key times and values and compute intermediate values

All interpolatorsolators have:

  • a set_fraction input to set the fractional time
  • a value_changed output to send new values

Some interpolatorsolators are:

This post is licensed under CC BY 4.0 by the author.