How to calculate rotation in degrees, between two CFrames, along a single axis?

Trying to find the rotation (in degrees) of a model relative to another part. So imagine a light is placed on a wall, and lets say the walls orientation is -90, -90, 0 (can be anything, just as long as the Top face is facing the inside of the house, and the front is facing the ground). And the light takes on the walls orientation when moved onto it when placed. But what if that light is then rotated on the wall. How would I find that x rotation change from where it started/the walls orientation, to where it is now?

I’ve come up with

local rotationChange = math.acos(cf1.LookVector:Dot(cf2.LookVector))
print(math.deg(rotationChange))

so far and it works really well, but only goes from [0 pi], meaning once it goes past 180 it goes back to postive numbers and counts back to 0, instead of being negative. I need it to go from [-pi/2 pi/2].

So are you looking for your angle to have directionality? I believe then you need to have a third vector in order to define when the angle becomes positive and when it becomes negative. For this, you can use this module from Sleitnick which is the function AngleBetweenSigned.

Vector Util Module
-- Vector Util
-- Stephen Leitnick
-- April 22, 2020

--[[

	VectorUtil.ClampMagnitude(vector, maxMagnitude)
	VectorUtil.AngleBetween(vector1, vector2)
	VectorUtil.AngleBetweenSigned(vector1, vector2, axisVector)


	EXAMPLES:

		ClampMagnitude:

			Clamps the magnitude of a vector so it is only a certain length.

			ClampMagnitude(Vector3.new(100, 0, 0), 15) == Vector3.new(15, 0, 0)
			ClampMagnitude(Vector3.new(10, 0, 0), 20)  == Vector3.new(10, 0, 0)

		
		AngleBetween:

			Finds the angle (in radians) between two vectors.

			v1 = Vector3.new(10, 0, 0)
			v2 = Vector3.new(0, 10, 0)
			AngleBetween(v1, v2) == math.rad(90)

		
		AngleBetweenSigned:

			Same as AngleBetween, but returns a signed value.

			v1 = Vector3.new(10, 0, 0)
			v2 = Vector3.new(0, 0, -10)
			axis = Vector3.new(0, 1, 0)
			AngleBetweenSigned(v1, v2, axis) == math.rad(90)

--]]


local VectorUtil = {}


function VectorUtil.ClampMagnitude(vector, maxMagnitude)
	return (vector.Magnitude > maxMagnitude and (vector.Unit * maxMagnitude) or vector)
end


function VectorUtil.AngleBetween(vector1, vector2)
	return math.acos(math.clamp(vector1.Unit:Dot(vector2.Unit), -1, 1))
end


function VectorUtil.AngleBetweenSigned(vector1, vector2, axisVector)
	local angle = VectorUtil.AngleBetween(vector1, vector2)
	return angle * math.sign(axisVector:Dot(vector1:Cross(vector2)))
end

function VectorUtil.SquaredMagnitude(vector)
	return vector.X^2+vector.Y^2+vector.Z^2
end


return VectorUtil
	local v1 = Vector3.new(10, 0, 0)
	local v2 = Vector3.new(0, 0, -10)
	local axis = Vector3.new(0, 1, 0)
	print(math.deg(VectorUtil.AngleBetweenSigned(v1, v2, axis)))
--Prints 90 degrees
	local v1 = Vector3.new(10, 0, 0)
	local v2 = Vector3.new(0, 0, 10)
	local axis = Vector3.new(0, 1, 0)
	print(math.deg(VectorUtil.AngleBetweenSigned(v1, v2, axis)))
--prints -90 Degrees
2 Likes

I believe you are looking for CFrame:ToObjectSpace.