## Prerequisites

How to combine rotations and translations is scenegraph shown here:

## Order of transforms

In addition to the translation and rotation, described
here, the Transform group also allows a (possibly) non-uniform scale about
an arbitrary point.

To do these 3 things we have the following parameter:

- The T (translation) field specifies a translation to the coordinate system.
- The R (rotation) field specifies a rotation of the coordinate system.
- The C (centre) field specifies a translation offset from the origin of the
local coordinate system (0,0,0).
- The S (scale) field specifies a non-uniform scale of the coordinate system.
Scale values shall be greater than zero.
- The SR (scaleOrientation) specifies a rotation of the coordinate system
before the scale (to specify scales in arbitrary orientations). The scaleOrientation
applies only to the scale operation.

Given a 3-dimensional point P and Transform node, P is transformed into point
P' in its parent's coordinate system by a series of intermediate transformations.
In matrix transformation notation.

P' = T × C × R × SR × S × -SR × -C ×
P

The following Transform node:

Transform {

centre C

rotation R

scale S

scaleOrientation SR

translation T

children [...]

}

is equivalent to the nested sequence of:

Transform {
translation T
children Transform {
translation C
children Transform {
rotation R
children Transform {
rotation SR
children Transform {
scale S
children Transform {
rotation -SR
children Transform {
translation -C
children [...]
}
}
}
}
}
}
}

## Code

Java code see sftransform class in source
code.

public void calcTransform(sfvec3f translation, sfrotation rotation, sfvec3f center, sfvec3f sc, sfrotation scaleOrientation){
setIdentity();
if (translation != null) translate(translation);
if (rotation != null) rotate(rotation,center);
if (scaleOrientation != null) rotate(scaleOrientation,center);
if (sc != null) { // if scale is (0,0,0), such as when scale first
// enabled this will generate a non-afine error
// so do following check
if ((sc.x != 0) & (sc.y != 0) & (sc.z != 0)) scale(sc);
if (scaleOrientation != null) rotate(scaleOrientation.minus(),center);
}

## Example: To implement a trackball control

Assume we have a shape in a scenegraph under one or more Transform Groups,
we want a trackball control to apply rotation to the Transform adjacent to the
Shape3D node. The problem is that the cumulative rotations above it will modify
it, so when we move the mouse right we want the object to rotate about the y-axis
but the cumulative rotation will effect this and cause it to rotate about some
other axis.

What we want is the equivalent of the following where a transform is added
at the root of the tree, this will ensure that moving the mouse right will make
the object to rotate about the y-axis.

The problem with this solution is that any other shapes in the scenegraph will
also be transformed. What we want to work out is an equivalent rotation in the
local Transform which will have the same effect as this.

So in the required rotation is:

[Rcumulative] * [Rlocal]

where:

- [Rlocal] = the new local rotation after the tracker ball is applied.
- [Rcumulative] = the total effect of all the rotations in the tree excluding
the local transform.
- in other words Rcumulative is applied first, then multiplied by Rlocal

We want this to be equivalent to:

[trackball] * [Rcumulative] * [Rlocalb]

where:

- [Rlocalb] = the local rotation before the tracker ball is applied
- [Rcumulative] = the total effect of all the rotations in the tree excluding
the local transform.
- [trackball] = the rotation applied by the trackerball.
- In other words apply trackball then multiply by Rcumulative then multiply
by Rlocalb

Since we want these to be equivalent then:

[Rcumulative] * [Rlocal] = [trackball] * [Rcumulative] * [Rlocalb]

so if we pre-multiply both sides by the conjugate of Rcumulative we get:

[Rcumulative]' * [Rcumulative] * [Rlocal] = [Rcumulative]' * [trackball] *
[Rcumulative] * [Rlocalb]

cancelling out [Rcumulative]' * [Rcumulative] gives

[Rlocal] = [Rcumulative]' * [trackball] * [Rcumulative] * [Rlocalb]

## Further Reading

Or you may be interested in how these quantities are used to simulate physical
objects:

This site may have errors. Don't use for critical systems.