I am attempting to write a spherical interpolation algorithm for for the application of smooth 3D animation in a game. The scripting language that the game engine uses is Lua. It is often easier for me to write an algorithm for 2D first and then 3D second, so I came up with the following (untested) algorithm for 2D spherical interpolation:
function slerp( x, y, x1, y1, t )
local rad = t * math.acos( x*x1 + y*y1 )
local newX = x * math.cos( rad ) - y * math.sin( rad )
local newY = x * math.sin( rad ) + y * math.cos( rad )
return newX, newY
end
From what I understand, the above formula should calculate a fraction of the radian angle between two 2D unit vectors and then rotate counterclockwise x and y by that fractional angle. For the 3D algorithm, I thought about changing the above code to the following:
function slerp( x, y, z, x1, y1, z1, t )
local rad = t * math.acos( x*x1 + y*y1 + z * z1 )
local newX = x * math.cos( rad ) - y * math.sin( rad )
local newY = x * math.sin( rad ) + y * math.cos( rad )
local newZ = z * math.cos( rad ) - x * math.sin( rad )
return newX, newY, newZ
end
My question is the following 2 points:
- Is my algorithm a correct implementation of spherical interpolation?
- Is there a less expensive way of calculating spherical interpolation in 3D (preferably with a thorough explanation )?
Best Answer
No, your algorithm is not a correct implementation (if by "spherical interpolation" you mean this).
In the two-dimensional case, you were able to calculate the new point using only the point $(x,y)$ (using $(x_1,y_1)$ only to calculate the angle, but not as a component of a linear combination) because in two dimensions there is only one direction to rotate $(x,y)$ into, namely $(-y,x)$, so you don't need to use $(x_1,y_1)$ to rotate in its direction.
In three dimensions, this is different. Given a vector $(x,y,z)$, there are two linearly independent directions that are perpendicular to it, and you don't know which direction to rotate into without using the point $(x_1,y_1,z_1)$ that tells you. (In fact you're not even multiplying the sine by a vector that's perpendicular to $(x,y,z)$, so the result doesn't even lie on the sphere, let alone on the great circle through $(x_1,y_1,z_1)$.)
As regards your question about a more efficient way to do this, as far as I'm aware the Wikipedia article (linked to above) describes correctly how it's usually done, both using vectors and using quaternions.