So thanks this post and some more research on the topic I can do pretty nice look-at stuff (like a surveillance camera orsmth.). Anyway all of solutions screw up one angle that should not rotate at all. Here is the code:
local UNIT_X = Vector3.new(1, 0, 0)
local UNIT_Z = Vector3.new(0, 0, 1)
local eyePart = workspace.Eye
local goalPart = workspace.Goal
-- Try 1
local function fromTo(v1, v2)
local a = Vector3.new()
local xAxis = Vector3.new(1,0,0)
local yAxis = Vector3.new(0,1,0)
local dot = v1:Dot(v2)
if (dot < -0.999999) then
a = xAxis:Cross(v1)
if (a.Magnitude < 0.000001) then
a = yAxis:Cross(v1)
end
a = a.Unit
return CFrame.fromAxisAngle(a, math.pi)
elseif (dot > 0.999999) then
return CFrame.new()
else
a = v1:Cross(v2)
return CFrame.new(0,0,0, a.X, a.Y, a.Z, 1 + dot)
end
end
-- Example 1
local function getRotationBetween(u, v, axis)
local dot = u:Dot(v)
if (dot > 0.99999) then
-- situation 1
return CFrame.new()
elseif (dot < -0.99999) then
-- situation 2
return CFrame.fromAxisAngle(axis, math.pi)
end
-- situation 3
return CFrame.fromAxisAngle(u:Cross(v), math.acos(dot))
end
game:GetService("RunService").Heartbeat:Connect(function(dt)
local eyeCF = eyePart.CFrame
--local delta = getRotationBetween(-UNIT_Z, eyeCF:PointToObjectSpace(goalPart.Position).Unit, UNIT_X)
--eyePart.CFrame = eyeCF * delta
eyePart.CFrame = eyeCF * fromTo(Vector3.new(1,0,0), eyeCF:PointToObjectSpace(goalPart.Position).Unit);
end)
You’ve made multiple posts about this but I’m still confused as to what you actually want. Can you show an image of what you want the final product to look like?
From your post it sounds like you want it to be a surveillance camera, if so, it should be rotating on a point towards the goal - that should stop it from rotating undesirably.
Will slow reply as I have work to do, but I’ll be back to help at some point. Please provide as much info as possible, incl. preferably an image of how it should work
Eye part should look at the Goal just like now (in provided code - mine or yours or whatever), but without doing rolling (just pitch and yaw) as: a) it makes no sense roll, b) roll just makes the Eye object look awkward (imagine a frog looking at a fly).
I don’t think this is about not understanding CFrame and matrix. But more lack on the correct technique to achieve what I want. So what you just suggested isn’t helpful and could come from anybody why want’s to play Smart. Sorry.
I’m kind of leaving this topic, as I realized that I do not really know what I want - how the look-at should behave in different scenarious. Will open new post when I have clear vision in my mind.
Im bumping this topic since it’s quite essential lost people know this, I’ve met loads with the issue and I’ve had it for years before I understood how CFrames worked, I also can’t find another post with the solution at all so I believe I’m justified?
Long waffle explanation
Sorry to bump, but this is in case anybody else was suffering from CFrame.lookAt’s tendency to smooth out rotation up to the TopVector (0,1,0), you can use either AxisAngles and ignoring theta (which are giving me some wild results and not even returning a value!??!) or EulerAngles by ignoring the Z axis.
To explain this:
EulerAngles can work in the order of Y, X, Z (they usually also X, Y, Z but that’s ew) (look this up for an image/explanation) where each axis is based off of the previous one so that rotating along Y (spinning around by Yaw) will mean that X will pull the eye up and down from that rotation (Pitch!), we ignore Z since that’s kind of something to do with your issue where the eye is rolling itself.
So we can convert the CFrame.lookAt() return value into angles with :ToEulerAngleYXZ (note YXZ not XYZ) and steal only the X and Y values, turning it back into a CFrame. There is a better way of doing this I’m sure but I forgot since that was about a year ago.
In conclusion the solution was actually really obvious, OP said: I don’t want roll… Solution: Don’t use roll with maths… Although OP was inexplicit in explaining this goal the video showed an unnatural result of CFrame.lookAt(arg1.Position,arg2.Position,arg1.UpVector)
Simple Solution:
local weirdLook = CFrame.lookAt(eyePart.Position,goalPart.Position,eyePart.UpVector)
local x,y,z = weirdLook:ToEulerAnglesYXZ()
local normalLook = CFrame.fromEulerAnglesYXZ(x,y,0)
eyePart.CFrame = normalLook + eyePart.CFrame.Position
I know you probably moved on now trshmanx but good luck with your endeavours