The provided replacement for CFrame.new(pos,lookat) is inadequate, as it results in invalid rotation matrices.
function lookAt(target, eye)
local forwardVector = (eye - target).Unit
local upVector = Vector3.new(0, 1, 0)
-- You have to remember the right hand rule or google search to get this right
local rightVector = forwardVector:Cross(upVector)
local upVector2 = rightVector:Cross(forwardVector)
return CFrame.fromMatrix(eye, rightVector, upVector2)
end
Because the rightVector and upVector2 aren’t normalized, they can have a magnitude different than 1.
print(lookAt(Vector3.new(1,1,1),Vector3.new()).RightVector.Magnitude)
--> 0.81649655103683
-- should be 1
print(lookAt(Vector3.new(0,1,0),Vector3.new()))
--> 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0
-- ???
The function should handle the case where the points are the same or when the target is directly above/below the eye.
Something like this would work better than the current replacement for CFrame.new(pos,lookat)
local vertical = Vector3.fromAxis(Enum.Axis.Y)
local function lookAt(eye,target)
local look = eye-target
if look.Magnitude <= 1e-5 then
return CFrame.new(eye)
else
look = look.Unit
end
local right = vertical:Cross(look)
if right.Magnitude <= 1e-5 then
return look:Dot(vertical) > 0 and CFrame.new(eye.X,eye.Y,eye.Z,0,1,0,0,0,1,1,0,0) or CFrame.new(eye.X,eye.Y,eye.Z,0,1,0,0,0,-1,-1,0,0)
else
right = right.Unit
end
return CFrame.fromMatrix(eye,right,look:Cross(right).Unit,look)
end