Quaternion is a class with three values: X, Y, Z and W.
It is a class to describe rotation. However, we do not specify Quaternion directly to change the values directly.
In most cases, we use methods listed below to change the values.
For the latest list of the methods, refer to “types.lua” file in “EmbeddedScriptWorkspace” folder.
To shorten the description, Vector3 type
is abbreviated as Vec
and number type
is abbreviated as num
.
Arguments are shown in ()
and return values are shown after semicolons :
.
Method name | Description |
_new fun(x: num, y: num, z: num, w: num): Quaternion | Initialization |
FromToRotation fun(fromDirection: Vec3, toDirection: Vec3): Quaternion | Rotate from the fromDirection to the toDirection . |
Inverse fun(rotation: Quaternion): Quaternion | Create a Quaternion that is the opposite of the rotation. |
Slerp fun(a: Quaternion, b: Quaternion, t: num): Quaternion | Spherically interpolates between a and b by the coefficient t. The range of t is [0, 1]. |
SlerpUnclamped fun(a: Quaternion, b: Quaternion, t: num): Quaternion | Same as Slerp, but doesn't restrict the t range to [0, 1]. Used for things like springs. |
Lerp fun(a: Quaternion, b: Quaternion, t: num): Quaternion | Linearly interpolates between a and b by the coefficient t. The range of t is [0, 1]. |
LerpUnclamped fun(a: Quaternion, b: Quaternion, t: num): Quaternion | Same as Lerp, but doesn't restrict the t range to [0, 1]. Used for things like springs. |
AngleAxis fun(angle: num, axis: Vec3): Quaternion | Create a rotation of angle degrees, using vector of the axis as the center |
LookRotation fun(forward: Vec3, upwards: Vec3): Quaternion | Turn towards forward direction and upwards direction. |
Dot fun(a: Quaternion, b: Quaternion): num | Returns the inner product of two rotations: a and b. |
Angle fun(a: Quaternion, b: Quaternion): num | Returns the angle of two rotations: a and b. |
Euler fun(x: num, y: num, z: num): Quaternion | Create a Quaternion by specifying Euler angle |
ToAngleAxis fun(angle: usertype, axis: usertype) | Convert the rotation to a value of angle against the axis (AngleAxis). |
RotateTowards fun(from: Quaternion, to: Quaternion, maxDegreesDelta: num): Quaternion | Interpolate the largest rotation between the two Quaternions. |
Normalize fun(q: Quaternion): Quaternion | |
GetHashCode fun(): num | Not to be used. |
ToString fun(): string | |
ToEuler fun(): Vec3 | |
ToEulerAngles fun(): Vec3 | |
identity Quaternion | Create a basic Quaternion of (0.0, 0.0, 0.0, 1.0). |
eulerAngles Vec3 | Return rotation in value of Euler angle. |
normalized Quaternion | |
x num | In most cases, do not change Quaternion directly. |
y num | In most cases, do not change Quaternion directly. |
z num | In most cases, do not change Quaternion directly. |
w num | In most cases, do not change Quaternion directly. |
kEpsilon num |
Example
rotate = Quaternion.identity print(rotate)
The result
(0.0, 0.0, 0.0, 1.0)
Basically, use Quaternion.identity
to initialize a Quaternion.
You can also use __new()
to declare, but it is very rare to handle a Quaternion directly.
Also, in the example above, you can access each element directly like rotate.x = 1
, but it is recommended to use methods provided to manipulate a quaternion.
Example
-- The name of the SubItem game object and the argument string in GetTransform("") must match. Subitem = vci.assets.GetTransform("Subitem") function onUngrab() local rotate = Quaternion.identity local velocity = Vector3.zero Subitem.SetLocalRotation(rotate) Subitem.SetVelocity(velocity) end
The result
(When you release the VCI from the grabbed state, its rotation will be set to the initial state (x = 0, y = 0, z = 0).)
By using SetLocalRotation()
, you can set the attitude to the Quaternion created.
When doing so, after setting the attitude, SetVelocity()
to 0 to avoid the attitude from being updated by Rigidbody.
Euler fun(x: number, y: number, z: number): Quaternion
Example
--- The name of the SubItem game object and the argument string in GetTransform("") must match. Subitem = vci.assets.GetTransform("Subitem") function onUngrab() local rotate = Quaternion.Euler(30, 45, 60) local velocity = Vector3.zero Subitem.SetLocalRotation(rotate) Subitem.SetVelocity(velocity) end
The result
(When you release the VCI from grabbed state, its rotation will be set to (x = 30, y = 45, z = 60).)
Specify the rotation with Euler angle value (0 ~ 360 degrees) to create Quaternion.
Specification of elements shall be done in order of X, Y and Z.
eulerAngles Vector3
Example
euler = Quaternion.Euler(30, 45, 60) print(euler) print(euler.eulerAngles) print(euler.eulerAngles.x) print(euler.eulerAngles.y) print(euler.eulerAngles.z)
The result
(0.4, 0.2, 0.4, 0.8) (30.0, 45.0, 60.0) 30.0000019073486 45 60.0000038146973
Return a Quaternion value in form of Euler angle value.
By specifying individual element after eulerAngles.
, you can access each element of the angles.
AngleAxis fun(angle: number, axis: Vector3): Quaternion
Example
-- The name of the SubItem game object and the argument string in GetTransform("") must match. Subitem = vci.assets.GetTransform("Subitem") angle = 0 function onUngrab() angle = angle + math.pi / 180 if angle > (2 * math.pi) then angle = 0 end print(angle) local axis = Vector3.up local rotate = Quaternion.AxisAngle(axis, angle) Subitem.SetLocalRotation(rotate) local velocity = Vector3.zero Subitem.SetVelocity(velocity) end
The result
(When you release the VCI from grabbed state, the y-axis rotation (Rotation.y) is incremented by 1 degree.)
Specify a direction with Vector3 to use as an axis of rotation and rotate by the value of “angle”.
In the example, axis = Vector3.up
creates an axis that goes from down to up, which then is used as the axis of rotation.
The “angle” specifying the degrees of rotation, shall be specified with a value between 0~6.28318530718(2π)
.
2π divided by 360 is 0.01745329251
. So by adding this value to the “angle,” the object will rotate by 1 degree.
To express π in Lua, use math.pi
.
LookRotation fun(forward: Vector3, upwards: Vector3): Quaternion
Example
function onUngrab(target) local forward = vci.assets.GetTransform(target).GetForward() local up = vci.assets.GetTransform(target).GetUp() local rotate = Quaternion.LookRotation(forward, up) print(rotate) print(vci.assets.GetTransform(target).GetRotation()) end
The result
(0.0, -0.3, -0.1, 1.0) (0.0, -0.3, -0.1, 1.0) (0.0, 0.9, 0.0, 0.4) (0.0, 0.9, 0.0, 0.4)
Create a Quaternion using an up vector and a forward vector.
In the example,rotate
and vci.assets.GetTransform(target).GetRotation()
take the same value.
Lerp fun(a: Quaternion, b: Quaternion, t: number): Quaternion
Example
-- The name of the SubItem game object and the argument string in GetTransform("") must match. Subitem = vci.assets.GetTransform("Subitem") base = Quaternion.identity target = Quaternion.Euler(0, 90, 0) function update() local time = math.abs(math.sin((vci.me.FrameCount / 60))) local lerp = Quaternion.Lerp(base, target, time) Subitem.SetRotation(lerp) end
The result
(The SubItem slowly oscillates by 90 degrees.)
Creates a Quaternion that interpolates between the base Quaternion and the target Quaternion.
By specifying a value in the range of 0-1, you get a Quaternion that corresponds to the quotient.
By changing it gradually, its attitude slowly changes from one attitude to the another.
Dot fun(a: Quaternion, b: Quaternion): number
Example
function onUngrab(target) local rotate = vci.assets.GetTransform(target).GetRotation() local base = Quaternion.identity print(Quaternion.Dot(rotate, base)) end
The result
0.886427819728851 -0.289039075374603 (When you release your hand from VCI, it acquires the inner product of the grabbed item and the base)
Compare two Quaternions and acquires the inner product.
The return value is in the range of -1~1
.