As a Roblox developer, it is currently hard to interpolate between directional vectors. Adding in spherical interpolation would solve this. Sure, we can write our own Lua implementation, but having a built-in function to do this would be great.
Other game engines (e.g. Unity, Unreal, Godot) include this function as part of their Vector3 implementations.
local dir0 = Vector3.xAxis
local dir1 = Vector3.zAxis
local dir2 = dir0:Slerp(dir1, 0.5)
I think Roblox not only needs Slerp, but it needs to be brought up to parity with the math functions that every other engine is provided.
For every project I make these days, I need to pull in modules to do basic vector and cframe operations that other engines provide with the types themselves.
Things like Vector plane projection and calculating angles, slerp, cframe from to rotation… all that really should be in the engine as is.
Yeah, not having added this one yet is definitely a miss, thanks for pointing it out.
We’ve been filling out some more math methods recently, FuzzyEq for CFrames was enabled just today which was another annoying thing to implement yourself.
I’d like to just pitch that I like many of the vector methods that Unity has and would be cool to have them here, similar to what @ckdevver was saying!
How about an optional disambigution direction? A direction the slerp will pass through if the directions are opposite and collinear?
local dir0 = -Vector3.zAxis
local dir1 = Vector3.zAxis
local disambiguationDir = Vector3.xAxis
local dir2 = dir0:Slerp(dir1, 0.5, disambiguationDir)
print(dir2)
--> 1, 0, 0
Otherwise if no disambiguation vector is given or if the disambiguation vector is colinear with the inputs, should probably return dir0 when t < 1/2 and dir1 otherwise.
I understand what you’re asking for, and internally a Slerp could be used to get the result, but it should definitely not be in the API as Vector3.Slerp() for a number of reasons, which include Slerp not being defined for two arbitrary position vectors, and unit direction vectors not fully defining 3D orientations. There are proper formalisms for 3D rotations that are 3-value vectors for which Slerp makes much more sense, like Euler/Rodrigues rotation vectors / exponential map, where a Vector3 encodes a rotation axis scaled by angle. Roblox also uses Vector3 in some places to store triples of Euler angles, like for Part.Orientation. Developers might try to do PartA.Orientation:Slerp(PartB.Orientation, t) and would not get a sensible result because these Orientations are neither directional vectors nor rotation vectors.
It’s probably best to have a helper function for your case, with a name that clearly indicates what’s going on, like Vector3:InterpolateDirectionAndLength(), or some clever shortening of this name (Dlerp? Derp? ). Just not Slerp.
What is your opinion on other engines implementing Vector3.Slerp? It seems like Unity has it, but I couldn’t find UE or Godot references so they might agree with you. Does unity have a better use case?
Unity and Godot both have it, and it both cases it works on any arbitrary vectors, interpolating both direction (angle) and length. If both vectors are the same length, it is a geometric slerp. But when they are different length, the resulting path is an ellipse, so not spherical interpolation any more. I don’t object to the function existing, I just wish they had come up with a new name for it.
What if slerp just implements it the usual way with geometric algebra. (This ends up homomorphic to the quaterions)
dir1 * (dir1^-1 * dir2)^t
And you can implement it like so, though this would need a bit of work. (tested and appears to work)
local function slerp(a, b, t)
local magA = a.magnitude
local magB = b.magnitude
-- first interpolate the magnitude
-- these are the degenerate cases
if magA == 0 and magB == 0 then
return Vector3.zero
elseif magA == 0 then
if t < 1 then
return Vector3.zero
elseif t == 1 then
return b
else
return math.huge*b
end
elseif magB == 0 then
if t < 0 then
return math.huge*a
elseif t == 0 then
return a
else
return Vector3.zero
end
end
-- the typical path:
local magC = magA^(1 - t)*magB^t -- final magnitude
-- now interpolate direction:
-- get k*cosine and k*sine components of the angle between a and b
local co = a:Dot(b)
local si = a:Cross(b).magnitude
local unitA = a.unit
local unitB = b.unit
-- more degenerate cases
if co < 0 and si < -1e-16*co then -- this test sees, in a stable way, if they are opposite and abs(tan(angle)) < 1e-16
-- opposite and colinear
if t%2 < 1/2 or t%2 >= 3/2 then
return magC*unitA
else
return magC*unitB
end
elseif co > 0 and si < 1e-16*co then -- this test sees, in a stable way, if they are in the same direction and abs(tan(angle)) < 1e-16
-- colinear
-- so we approximate using a unitized lerp
return magC*((1 - t)*unitA + t*unitB).unit
end
-- the typical path:
-- compute the angle in a numerically stable way
local ang = math.atan2(si, co)
-- don't divide by sine(ang), instead just unitize the result for greater accuracy
local unitC = (math.sin((1 - t)*ang)*unitA + math.sin(t*ang)*unitB).unit
return magC*unitC
end
I don’t think this is a good response, given that it’s incorrect.
It can be agreed upon that the math library is built upon the initial implementation from Lua, but what currently exists in Luau includes several additions which aren’t even present up to Lua 5.4, for example; math.clamp, math.round, math.noise (which can be considered very game development centric), any hyperbolic trigonometric function, and etc.
Interpolation is also not a “game development” centric function either, I’m not sure why this was even said?
Either way - Roblox recently has been more attentive to what could be added to its existing libraries to make development quicker/easier - which is how we’ve gotten all these math library additions in the first place.
A built-in interpolation function (that operates on numbers) I believe is essential and I feel the same about a Slerp method for Vector3 as well: these two together would absolutely fill a gap that developers themselves have had to fill in the past with their own implementations.
You’re correct that this is changing. There have been some targeted additions, and you might see stuff like lerp added. You could even be the one to make an RFC proposing adding it! We are responsive to Luau RFCs from outside the company.
But that doesn’t change it being the explanation for why there is no lerp function (the legacy of the math library being a minimal general library for Lua), vs if we were designing a math library from scratch for Roblox specifically there probably would be.
Ah, my apologies then, it came off to me as if you were answering the original question (posed at the end) and then also asserting it as to why it wouldn’t be considered.
I’ve been watching the Luau RFC repository (and prior to that being made, just the Luau repository) intensively for new features to be aware of and pitch support for, there are several things I could make RFCs for that don’t already exist (and haven’t already been denied) but I’ve been waiting until the new type system is finished and stably released to do so. Will do some research on the guidelines for PRing a RFC and what is expected of you once one has been made (or prior to one being made).