Try this and tell me where our negatives and positives are. I changed 3 things.
local A = Baseplate.CFrame.RightVector * -1
A = Vector2.new(A.X, A.Z)
local B = ( Vector3.new(Hit.X, BluePart.CFrame.Y, Hit.Z) - BluePart.CFrame.p ).Unit
B = Vector2.new(B.X, B.Z)
local Cost = ( A:Dot(B) ) / (A.Magnitude * B.Magnitude)
local T = math.acos(Cost)
local B = Hit.p
local X = BluePart.CFrame:PointToObjectSpace(B)
print(X.Z)
Note: You will need to change the name of BluePart.
Great! That’s what I was looking for. Now we can change our code to this:
local A = Baseplate.CFrame.RightVector * -1
A = Vector2.new(A.X, A.Z)
local B = ( Vector3.new(Hit.X, BluePart.CFrame.Y, Hit.Z) - BluePart.CFrame.p ).Unit
B = Vector2.new(B.X, B.Z)
local Cost = ( A:Dot(B) ) / (A.Magnitude * B.Magnitude)
local T = math.acos(Cost)
local B = Hit.p
local X = (BluePart.CFrame*CFrame.Angles(0,math.rad(90),0).):PointToObjectSpace(B)
if X.Z<0 then --This is the only thing that was added since last change.
T=-T
end
print(X.Z)
un-comment that line of code that rotated the mortar and tell me how that does.
is how you make a code block think you could edit your last post to reflect this? Make it easier on people who might find this post and read through the MANY MANY MANY replies haha.
Computing angle from cross product, dot product and arc tangent is numerically stable for small angles, whereas taking the arc cosine of the dot product is not.
local function GetAngle(v1,v2)
return math.atan2((v1:Cross(v2)).Magnitude,v1:Dot(v2))
end
It’s in response to no one giving you the standard arc tangent based solution, which is the one you should use. The solution you accepted isn’t normally used for this, because math.acos of the dot product loses precision as the angle gets near zero, and it requires you to do a conditional check to make sure you’re not dividing by zero.
Not so, it can return any value between 0 and pi, which is the angle in Radians. You can use math.deg() on if you want to print it out in degrees (0 to 180). Results will generally agree between the two methods for all but tiny angles. You can see for yourself by running the snippet below. Notice how the results for random vectors generally agree, but if you try to measure small angles, the arc cosine method gives inaccurate results and often NANs.
local function GetAngleAtan(v1,v2)
return math.atan2((v1:Cross(v2)).Magnitude,v1:Dot(v2))
end
local function GetAngleAcos(v1,v2)
return math.acos( (v1:Dot(v2) ) / (v1.Magnitude * v2.Magnitude))
end
-- Random vectors
print("With two random vectors:")
for i=1,30 do
local v1 = 100 * Vector3.new( 2*math.random()-1, 2*math.random()-1, 2*math.random()-1)
local v2 = 100 * Vector3.new( 2*math.random()-1, 2*math.random()-1, 2*math.random()-1)
print("Arctan method:",math.deg(GetAngleAtan(v1,v2))," Arccos method:",math.deg(GetAngleAcos(v1,v2)))
end
print("\n")
-- Random vector and same vector rotated a *tiny* amount
print("With very small angles:")
for i=1,30 do
local v1 = Vector3.new( 2*math.random()-1, 2*math.random()-1, 2*math.random()-1)
local v2 = CFrame.fromOrientation(0, math.random()*0.001, 0) * v1
print("Arctan method:",math.deg(GetAngleAtan(v1,v2))," Arccos method:",math.deg(GetAngleAcos(v1,v2)))
end
That’s very interesting! I recommend swapping out our equation for the one EmilyBendsSpace suggested. For your specific problem, we still need the code that gets our two vectors and the code that checks whether our angle should be positive or negative. But we should change how we calculate T (theta). Now we would have this:
local A = Baseplate.CFrame.RightVector * -1
A = Vector2.new(A.X, A.Z)
local B = ( Vector3.new(Hit.X, BluePart.CFrame.Y, Hit.Z) - BluePart.CFrame.p ).Unit
B = Vector2.new(B.X, B.Z)
local T = math.atan2((A:Cross(B)).magnitude,A:Dot(B)) -- swapped over to the equation suggested by EmilyBendsSpace.
local B = Hit.p
local X = (BluePart.CFrame*CFrame.Angles(0,math.rad(90),0).):PointToObjectSpace(B)
if X.Z<0 then
T=-T
end
--make sure we turn our radians into degrees
local angle=math.deg(T)
print(X.Z)
print("radians: " ..tostring(T))
print("degrees: " ..tostring(angle))
Had to remove the Vector2.new stuff. I appreciate you putting it in code form. Seems to be the only way I actually understand the math. Also thanks @EmilyBendsSpace for providing the awesome formula. Barely understood it, and was being too self conscious to ask you to dumbify it for me.
You guys are amazing, wish I could do this complicated math it would definitely help me with programming.