Rotation
A 3-D rotation, stored as a unit quaternion. See Position for the rationale behind the distinct type — the same one applies doubly here, since filament-utils' Quaternion has mutable components and so is an unstable Compose input.
Build one with axisAngle or euler rather than the raw component constructor, and combine with * (right operand applied first):
Cube(rotation = Rotation.axisAngle(Direction.Up, degrees = spin))
Cube(rotation = Rotation.euler(yaw = 45f) * Rotation.euler(pitch = 30f))
// Aim an entity at a target, and blend towards a new pose over time
Cube(rotation = Rotation.lookTowards(target - turret))
Cube(rotation = Rotation.slerp(from, to, t))fromTo, lookTowards, slerp, nlerp, toEuler, angleTo and normalized cover the usual scene work. For anything beyond them — matrix interop, swizzles, custom interpolation — hop to filament-utils' Quaternion and back; the two are the same four floats and the conversion is lossless:
val blended = Rotation(myOwnInterpolation(a.toQuaternion(), b.toQuaternion()))
val asRotation = someQuaternion.toRotation() // or Rotation(someQuaternion)Equality is component-wise, as for any data class — which is not the same as "same orientation": r and its all-components-negated twin turn an entity to the identical pose but compare unequal, and accumulated products drift. That is what you want for Compose (equal values let a composable skip), but to ask whether two orientations agree use angleTo against a tolerance rather than ==.
Constructors
From a filament-utils Quaternion.