I tried making it work with quaternions. It should give the desired effect, like the video you sent in. You might need to put the quaternion class in a module script.
local Quaternion = {}
Quaternion.__index = Quaternion
function Quaternion.new(w, x, y, z)
local invLength = 1 / math.sqrt(w * w + x * x + y * y + z * z)
local self = setmetatable({
W = w * invLength,
X = x * invLength,
Y = y * invLength,
Z = z * invLength,
}, Quaternion)
return self
end
function Quaternion.fromAxisAngle(axis, angle)
local sin = math.sin(angle / 2)
return Quaternion.new(math.cos(angle / 2), sin * axis.X, sin * axis.Y, sin * axis.Z)
end
function Quaternion:Conjugate()
return Quaternion.new(self.W, -self.X, -self.Y, -self.Z)
end
function Quaternion.__mul(self, other)
local w = self.W * other.W - self.X * other.X - self.Y * other.Y - self.Z * other.Z
local x = self.X * other.W + self.W * other.X - self.Z * other.Y + self.Y * other.Z
local y = self.Y * other.W + self.Z * other.X + self.W * other.Y - self.X * other.Z
local z = self.Z * other.W - self.Y * other.X + self.X * other.Y + self.W * other.Z
return Quaternion.new(w, x, y, z)
end
function Quaternion:ToAxisAngle()
local angle = math.acos(self.W) * 2
local sin = math.sin(angle / 2)
local axis = Vector3.new(self.X, self.Y, self.Z) / sin
return axis, angle
end
function Quaternion:ToCFrame()
local nx = self * Quaternion.new(0, 1, 0, 0) * self:Conjugate()
local ny = self * Quaternion.new(0, 0, 1, 0) * self:Conjugate()
local nz = self * Quaternion.new(0, 0, 0, 1) * self:Conjugate()
nx = Vector3.new(nx.X, nx.Y, nx.Z)
ny = Vector3.new(ny.X, ny.Y, ny.Z)
nz = Vector3.new(nz.X, nz.Y, nz.Z)
return CFrame.fromMatrix(Vector3.zero, nx, ny, nz)
end
function Quaternion:Slerp(other, t)
local rel = other * self:Conjugate()
local axis, angle = rel:ToAxisAngle()
angle *= t
return Quaternion.fromAxisAngle(axis, angle)
end
local p = workspace.Part
local s, positive = 0, true
local origin = p.CFrame
local speedMultiplier = 100
game:GetService("RunService").PostSimulation:Connect(function(DeltaTime)
local rot = math.pi / 8
local identity = Quaternion.new(1, 0, 0, 0)
local up = Quaternion.new(math.cos(rot / 2), 0, 0, math.sin(rot / 2))
local right = Quaternion.new(math.cos(rot / 2), math.sin(rot / 2), 0, 0)
local final = up:Slerp(identity, math.sin(math.rad(s))) * right:Slerp(identity, math.cos(math.rad(s)))
p.CFrame = origin * final:ToCFrame()
s += DeltaTime * speedMultiplier
end)