====== Quaternion ====== 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. ===== List of methods ===== **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 | | ===== About initialization ===== 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() ===== **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 ===== **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. ===== AxisAngle() ===== **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() ===== **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() ===== **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.\\ ===== Angle() ===== **Angle fun(a: Quaternion, b: Quaternion): number** Example\\ The result\\ Description ===== Dot ===== **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''. ===== Method name ===== **** Example\\ The result\\ Description