 # Vector3:Slerp(v2,t unclamped)

As a Roblox developer, it is currently annoying (and slow) to slerp vectors
Right now we have to write our own utility functions to do slerp and I think it discourages its use

So far I’ve only used slerp 3 times in my game, but I think I would have found a lot more use cases for it had I an open mind about slerp (2 of these 3 times have been today when I was working on my hover car)

I know we can implement it with axis angles/pythag(?) but I’ve had it implemented and haven’t used it much
Also I think if Roblox made Vector3:slerp() it would be a lot faster than these implementations:

``````local axisangle=CFrame.fromAxisAngle
local asin=math.asin
function md.slerp(v0,v1,t0)
local unit
if t0==0 then unit=v0.unit
elseif t0==1 then unit=v1.unit
elseif v0.unit==v1.unit then unit=v0.unit
else
local cross=v0.unit:Cross(v1.unit)
local t1=asin(cross.magnitude)*t0
unit=axisangle(cross.unit,t1)*v0.unit
end
assert(unit.X==unit.X,'vecs are opposite')
return unit--*(v0.magnitude*(1-t0)+v1.magnitude*t0)--uncomment to lerp magnitudes
end
``````
``````local new=Vector3.new
local acos=math.acos
local cos=math.cos
local sin=math.sin
local sqrt=math.sqrt

function md.slerp(q0,q1,t)--too lazy to rewrite so just took quaternion one; use slerp for directions and lerp for points
--unclamped
--http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/
--https://en.wikipedia.org/wiki/Slerp
q0=q0.unit q1=q1.unit--only unit quaternions are valid Rotations; normalize to avoid undefined behavior
local xx=q0.x
local xy=q0.y
local xz=q0.z
local px=q1.x
local py=q1.y
local pz=q1.z
local dot=xx*px+xy*py+xz*pz
if dot>1-1e-4 then
local t0=1-t
return new(xx*t0+px*t,xy*t0+py*t,xz*t0+pz*t)
end

local yx=px-dot*xx
local yy=py-dot*xy
local yz=pz-dot*xz
local a=acos(dot)*t
local c=cos(a)
local s=sin(a)/sqrt(yx*yx+yy*yy+yz*yz)
return new(xx*c+yx*s,xy*c+yy*s,xz*c+yz*s)
end
``````
1 Like

An slerp on a 3d value is just lerp unless you assume that it is a direction vector from the origin, which doesn’t make sense to have as assumption for most use cases where you’d want to smoothly interpolate between two 3d values.

You should use CFrame.Lerp, it actually does slerping despite the name implies. (Source: How would I slerp between 2 CFrames)

``````local cfr1 = CFrame.new(Vector3.new(), v1)
local cfr2 = CFrame.new(Vector3.new(), v2)

local result = cfr1:Lerp(cfr2, t).LookVector
``````

I don’t know where you use this code, but it might be convenient to entirely work with CFrame values and not touching loose direction vectors at all, then you don’t need to do the CFrame instancing. I’ve never personally had a situation where I didn’t already have CFrame values available when I wanted to slerp, at least.

7 Likes