# Cool short quaternion vs Euler angles comparison

Quick demo I made to show the differences of using quaternions and the standard Euler angles. Here you could easily see why quaternions are much more stable and smoother for rotational interpolation.

Plus a ton of other benefits over using quaternions include preventing a gimbal lock, numerical efficiency, and stability in general. Pretty underrated and underused when it comes to cframing and animations on roblox.

1 Like

Awesome! Down with the ambiguity!

I know it is better but I can not find an explanation on how to create this. I even asked my math teacher - which he then asked other math teachers and they had no clue on how to calculate them. So I gave up

1 Like

When I said that I mean explanations I understood. Iâ€™ve read most of what you posted except the first.

1 Like

http://wiki.roblox.com/index.php?title=Quaternions_for_Rotation

What sort of explanations do you want in particular?
Iâ€™ve just started studying this topic for my math class research topic, and perhaps I could help myself better understand it by explaining some of it here maybe

1 Like

Only thing I do not get is for calculating w do you add together x, y and zed? Orâ€¦?

w is the component that determines the amount of rotation around the axis.
I havenâ€™t really studied exactly on what it exactly means, but it is supposedly in the definition of a quaternion you automatically set the value of w to be:

angle = 30 â€”in degrees
w = cos(angle/2)

Basically when constructing angles using quaternions, w is the cosine of half the rotation angle.

This is neat. Iâ€™ll have to play around with it when I get home.

What would I do if I wanted to change the axis of rotation while the part is rotated?

Really because, I did this and it seems to work fine with no gimbal.

``````function other(x, y, z, part, ticks)
while wait(ticks) do
cos_x = math.cos(.5 * x)
cos_y = math.cos(.5 * y)
cos_z = math.cos(.5 * z)
sinf_x = math.sin(.5 * x)
sinf_y = math.sin(.5 * y)
sinf_z = math.sin(.5 * z)
w = ((cos_x * cos_y * cos_x) + (sinf_x * sinf_y * sinf_z))
x2 = ((cos_z * cos_y * sinf_x) - (sinf_z * sinf_y * cos_x))
y2 = ((cos_z * sinf_y * cos_x) + (sinf_z * cos_y * sinf_z))
z2 = ((sinf_z * cos_y * cos_x) - (cos_z * sinf_y * sinf_x))
print(w, x)
part.CFrame = part.CFrame *CFrame.Angles(x2,y2,z2)
end
end
part=Workspace.Part

[quote] This is neat. Iâ€™ll have to play around with it when I get home.

What would I do if I wanted to change the axis of rotation while the part is rotated? [/quote]

You start off with a vector that represents the axis of rotation.
The vector must be a unit vector in order for a smooth rotation.

Given the definition of a quaternion in a complete set, you have this for an x rotation for example:

``````v = Vector3.new(1,0,0).unit
w=math.cos(a/2)
x=math.sin(a/2)*v.x
y=math.sin(a/2)*v.y
z=math.sin(a/2)*v.z

part.CFrame = CFrame.new(0,0,0,x,y,z,w)
``````
1 Like

[quote] This is neat. Iâ€™ll have to play around with it when I get home.

What would I do if I wanted to change the axis of rotation while the part is rotated? [/quote]

You start off with a vector that represents the axis of rotation.
The vector must be a unit vector in order for a smooth rotation.

Given the definition of a quaternion in a complete set, you have this for an x rotation for example:

[code]
v = Vector3.new(1,0,0).unit
w=math.cos(a/2)
x=math.sin(a/2)*v.x
y=math.sin(a/2)*v.y
z=math.sin(a/2)*v.z

part.CFrame = CFrame.new(0,0,0,x,y,z,w)

[/code][/quote]

Thanks!
Now, say I rotated the part 20â”¬â–‘ around the X axis, and now I wanted to continue from there and rotate it around the Z axis. Would I add Vector3.new(0,0,1) to v and keep normalizing, or is it more complicated than that?

[quote] [quote=â€śVolcanoINCâ€ť post=53163]This is neat. Iâ€™ll have to play around with it when I get home.

What would I do if I wanted to change the axis of rotation while the part is rotated? [/quote]

You start off with a vector that represents the axis of rotation.
The vector must be a unit vector in order for a smooth rotation.

Given the definition of a quaternion in a complete set, you have this for an x rotation for example:

[code]
v = Vector3.new(1,0,0).unit
w=math.cos(a/2)
x=math.sin(a/2)*v.x
y=math.sin(a/2)*v.y
z=math.sin(a/2)*v.z

part.CFrame = CFrame.new(0,0,0,x,y,z,w)

[/code][/quote]

Thanks!
Now, say I rotated the part 20â”¬â–‘ around the X axis, and now I wanted to continue from there and rotate it around the Z axis. Would I add Vector3.new(0,0,1) to v and keep normalizing, or is it more complicated than that?[/quote]

From the sounds of it you would just subtract 1 from the X value of the vector and at 1 to the Z value of the vector.

[quote] [quote=â€ślitozinnamonâ€ť post=53171]

[/quote]

Thanks!
Now, say I rotated the part 20â”¬â–‘ around the X axis, and now I wanted to continue from there and rotate it around the Z axis. Would I add Vector3.new(0,0,1) to v and keep normalizing, or is it more complicated than that?[/quote]

From the sounds of it you would just subtract 1 from the X value of the vector and at 1 to the Z value of the vector.[/quote]

From the looks of it, that would reverse the rotation I have made along the X axis and rotate it only along the Z axis.

[quote] [quote=â€śVolcanoINCâ€ť post=53173][quote=â€ślitozinnamonâ€ť post=53171]

[/quote]

Thanks!
Now, say I rotated the part 20â”¬â–‘ around the X axis, and now I wanted to continue from there and rotate it around the Z axis. Would I add Vector3.new(0,0,1) to v and keep normalizing, or is it more complicated than that?[/quote]

From the sounds of it you would just subtract 1 from the X value of the vector and at 1 to the Z value of the vector.[/quote]

From the looks of it, that would reverse the rotation I have made along the X axis and rotate it only along the Z axis.[/quote]
Didnâ€™t you want it to rotate around the Z axis after 20 degrees anyways?

[quote] [quote=â€śflatline115â€ť post=53174][quote=â€śVolcanoINCâ€ť post=53173][quote=â€ślitozinnamonâ€ť post=53171]

[/quote]

Thanks!
Now, say I rotated the part 20â”¬â–‘ around the X axis, and now I wanted to continue from there and rotate it around the Z axis. Would I add Vector3.new(0,0,1) to v and keep normalizing, or is it more complicated than that?[/quote]

From the sounds of it you would just subtract 1 from the X value of the vector and at 1 to the Z value of the vector.[/quote]

From the looks of it, that would reverse the rotation I have made along the X axis and rotate it only along the Z axis.[/quote]
Didnâ€™t you want it to rotate around the Z axis after 20 degrees anyways?[/quote]

Yes, but I wanted to keep the rotation Iâ€™ve made around the X axis.

[quote] [quote=â€śVolcanoINCâ€ť post=53177][quote=â€śflatline115â€ť post=53174][quote=â€śVolcanoINCâ€ť post=53173][quote=â€ślitozinnamonâ€ť post=53171]

[/quote]

Thanks!
Now, say I rotated the part 20â”¬â–‘ around the X axis, and now I wanted to continue from there and rotate it around the Z axis. Would I add Vector3.new(0,0,1) to v and keep normalizing, or is it more complicated than that?[/quote]

From the sounds of it you would just subtract 1 from the X value of the vector and at 1 to the Z value of the vector.[/quote]

From the looks of it, that would reverse the rotation I have made along the X axis and rotate it only along the Z axis.[/quote]
Didnâ€™t you want it to rotate around the Z axis after 20 degrees anyways?[/quote]

Yes, but I wanted to keep the rotation Iâ€™ve made around the X axis.[/quote]

Then just multiply the CFrame instead of setting it to that directly ex:

[code]function changes(dir, val)
if dir == â€śxâ€ť then
v = Vector3.new(1,0, 0)
w = math.cos(val/2)
x2 = math.sin(val/2)*v.x
y2 = math.sin(val/2)*v.y
z2 = math.sin(val/2)*v.z
return w, x2
elseif dir == â€śyâ€ť then
v = Vector3.new(0,1, 0)
w = math.cos(val/2)
x2 = math.sin(val/2)*v.x
y2 = math.sin(val/2)*v.y
z2 = math.sin(val/2)*v.z
return w, y2
elseif dir == â€śzâ€ť then
v = Vector3.new(0,0, 1)
w = math.cos(val/2)
x2 = math.sin(val/2)*v.x
y2 = math.sin(val/2)*v.y
z2 = math.sin(val/2)*v.z
return w, z2
end
end

function calc(x, y, z, part)
for i = 1, 100 do
xs = {changes(â€śxâ€ť, x)}
ys = {changes(â€śyâ€ť, y)}
zs = {changes(â€śzâ€ť, z)}
part.CFrame = part.CFrame * CFrame.new(0, 0, 0, xs[2], ys[2], zs[2], math.sqrt(xs[1] + ys[1] + zs[2]))
wait()
end
end
[/code]

[quote]
Yes, but I wanted to keep the rotation Iâ€™ve made around the X axis. [/quote]

Hold onâ€¦ youâ€™re right, I havenâ€™t figured out how that would work =O

In Euler angles, you could easily interpolate from the current cframe angle, and just rotate on only one axis

For example:

``````--- this orientation
--- interpolate to

--- would rotate around the same axis even if it was :
part.CFrame = CFrame.Angles(0,0,0)
--- interpolating to
``````

I canâ€™t figure out how to get the same movement effect while using quaternions yet, since the â€śwâ€ť would get you from a zero rotation directly to the rotational orientation equivalent to CFrame.Angles(math.rad(90),0,math.rad(20).

Anyone know how to solve this problem?

[quote]
Yes, but I wanted to keep the rotation Iâ€™ve made around the X axis. [/quote]

Hold onâ€¦ youâ€™re right, I havenâ€™t figured out how that would work =O

In Euler angles, you could easily interpolate from the current cframe angle, and just rotate on only one axis

For example:

``````--- this orientation
--- interpolate to

--- would rotate around the same axis even if it was :
part.CFrame = CFrame.Angles(0,0,0)
--- interpolating to
``````

I canâ€™t figure out how to get the same movement effect while using quaternions yet, since the â€śwâ€ť would get you from a zero rotation directly to the rotational orientation equivalent to CFrame.Angles(math.rad(90),0,math.rad(20).

Anyone know how to solve this problem?[/quote]

With the code I presented you could just choose one of the axisâ€™s w val. As each table â€śxs, ys and zsâ€ť is calculated so youâ€™d change;

``part.CFrame = part.CFrame * CFrame.new(0, 0, 0, xs[2], ys[2], zs[2], math.sqrt(xs[1] + ys[1] + zs[2]))``

To

``part.CFrame = part.CFrame * CFrame.new(0, 0, 0, xs[2], ys[2], zs[2], xs[1])``

Therefore you get the same rotation, orientation.

But here you are rotating using the partâ€™s current cframe angles.
My goal was to have it where the partâ€™s existing cframe angle orientation would have no effect on the rotation it will undergo.

``````--- this orientation
``````part.CFrame = part.CFrame * CFrame.new(0, 0, 0, xs[2], ys[2], zs[2], math.sqrt(xs[1] + ys[1] + zs[2]))