Quaternion can describe not only rotation, but also an orientation, i.e. rotation from initial (zero) position.
I was wishing to model smooth rotation from one orientation to another. I calculated start orientation startOrientation
and end orientation endOrientation
and was wishing to describe intermediate orientations as startOrientation*(1-argument) + endOrientation*argument
while argument
changes from 0
to 1
.
The code for monkey engine update function is follows:
@Override
public void simpleUpdate(float tpf) {
if( endOrientation != null ) {
if( !started ) {
started = true;
}
else {
fraction += tpf * speed;
argument = (float) ((1 - Math.cos(fraction * Math.PI)) / 2);
orientation = startOrientation.mult(1-argument).add(endOrientation.mult(argument));
//orientation = startOrientation.mult(1-fraction).add(endOrientation.mult(fraction));
log.debug("tpf = {}, fraction = {}, argument = {}", tpf, fraction, argument);
//log.debug("orientation = {}", orientation);
rootNode.setLocalRotation(orientation);
if( fraction >= 1 ) {
rootNode.setLocalRotation(endOrientation);
log.debug("Stopped rotating");
startOrientation = endOrientation = null;
fraction = 0;
started = false;
}
}
}
}
The cosine formula was expected to model smooth accelerating at the beginning and decelerating at the end.
The code works but not as expected: the smooth rotation starts and finishes long before fraction
and argument
values reach 1
and I don't understand, why.
Why the orientation
value reaches endOrientation
so fast?
You have stated that in your case
startOrientation
was being modified. However; the following remains trueInterpolating between quaternions
The method
slerp
is included within the Quaternion class for this purpose: interpolating between two rotations.Assuming we have two quaternions
startOrientation
andendOrientation
and we want the pointinterpolation
between them then we interpolate between then using the following code:Why your approach may be dangerous
Quaternions are somewhat complex internally and follow somewhat different mathematical rules to say vectors. You have called the
multiply(float scalar)
method on the quaternion. Internally this looks like thisSo it just does a simple multiplication of all the elements. This explicitly does not return a rotation that is
scalar
times the size. In fact such a quaternion no longer represents a valid rotation at all since its no longer a unit quaternion. If you callednormalise
on this quaterion it would immediately undo the scaling. I'm sureQuaternion#multiply(float scalar)
has some use but I am yet to find them.It is also the case that "adding" quaternions does not combine them. In fact you multiply them. So combining q1 then q2 then q3 would be achieved as follows:
The cheat sheet is incredibly useful for this
Formula vs slerp comparison
In your case your formula for interpolation is nearly but not quite correct. This shows a graph of yaw for interpolation between 2 quaternions using both methods