I am reviewing @EmilyBendsSpace’s code here.
It does seem to do the exact thing that I am trying to achieve, I might mark it as the solution if it ends up working.
(Some comments added by me to express thought.)
local part = game.Workspace:WaitForChild("Block")
local dummy = game.Workspace:WaitForChild("Dummy")
local oldUp = part.CFrame.UpVector
local EPSILON = 1e-6 -- Tolerance value?
function GetAxisAngleToRotateVectorAtoB( a, b )
if a.Magnitude < EPSILON or b.Magnitude < EPSILON then
return Vector3.yAxis, 0
end
local ua = a.Unit
local ub = b.Unit
local dp = ua:Dot(ub.Unit) -- I wonder what we're using Dot product for.
local cp = ua:Cross(ub) -- Cross between Unit A and B, likely the axis we want to rotate on?
if math.abs(dp) > (1.0-EPSILON) or cp.Magnitude < EPSILON then -- Dot product used as some tolerance value?
if dp < 0 then
return Vector3.yAxis, math.pi -- Pi is used here?
end
return Vector3.yAxis, 0
end
local axis = cp.Unit
local angle = math.atan2( cp.Magnitude, dp ) -- What does arc tangent do with cross and dot?
return axis, angle
end
part:GetPropertyChangedSignal("CFrame"):Connect(function()
local newUp = part.CFrame.UpVector
local axis, angle = GetAxisAngleToRotateVectorAtoB(oldUp, newUp)
local rotCF = CFrame.fromAxisAngle(axis,angle)
local dummyCF = dummy:GetPrimaryPartCFrame()
-- Why subtract position if we add position back after??
dummyCF = rotCF * (dummyCF - dummyCF.Position) + dummyCF.Position
dummy:SetPrimaryPartCFrame(dummyCF)
oldUp = newUp
end)
I understand most of this code, the one part that kiiiinda confuses me a bit are these?
if a.Magnitude < EPSILON or b.Magnitude < EPSILON then
return Vector3.yAxis, 0
end
My guess is that this is some sort of check to basically prevent “division by 0” sorta scenarios but for rotation?
Or it’s to rotate a character 180 degrees onto a ceiling?
I just see Magnitude < Epsilon
and the first thing coming to mind is that if a value is super tiny or super large we might want to do something different with it.
if math.abs(dp) > (1.0-EPSILON) or cp.Magnitude < EPSILON then
if dp < 0 then
return Vector3.yAxis, math.pi
end
return Vector3.yAxis, 0
end
Here I see Pi
being returned as the angle of the function.
Why Pi
specifically?
local angle = math.atan2( cp.Magnitude, dp )
Arc tangent! I honestly forgot what it exactly does, I’ve only used a tangent function before when writing a neural network activation function to remap a input value (that was hyperbolic tangent).
I haven’t touched trigonometry in ages, haven’t fully learned it.
If the point of Devforum is learning then I am very curious about these specific choices made in code.