# 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, ys, zs, math.sqrt(xs + ys + zs))
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, ys, zs, math.sqrt(xs + ys + zs))``

To

``part.CFrame = part.CFrame * CFrame.new(0, 0, 0, xs, ys, zs, xs)``

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, ys, zs, math.sqrt(xs + ys + zs))