[SOLVED][SCRIPTING] Math help please!

I created this function by copying a script from here:

function MatrixToEuler(in_matrix)
	-- Adapted from https://www.geometrictools.com/Documentation/EulerAngles.pdf, section 2.1
	local r00 = in_matrix[1]
	local r01 = in_matrix[2]
	local r02 = in_matrix[3]
	local r10 = in_matrix[4]
	local r11 = in_matrix[5]
	local r12 = in_matrix[6]
	local r20 = in_matrix[7]
	local r21 = in_matrix[8]
	local r22 = in_matrix[9]
	local thetaX = 0
	local thetaY = 0
	local thetaZ = 0
	if (r02 < 1) then
		if (r02 > -1) then
			thetaX = atan2(-r12, r22)
			thetaY = asin(r02)
			thetaZ = atan2(-r01, r00)
		else -- r02 = -1
			-- Not a unique solution: thetaZ − thetaX = atan2(r10, r11)
			thetaX = -atan2(r10, r11)
			thetaY = -90
			thetaZ = 0
		end
	else -- r02 = 1
		-- Not a unique solution: thetaZ + thetaX = atan2(r10, r11)
		thetaX = atan2(r10, r11)
		thetaY = 90
		thetaZ = 0
	end
	return {thetaX, thetaY, thetaZ}
end

I use it to convert the output of the SobGroup_GetCoordSys from a matrix to Euler rotation angles.

However, the PDF file doesn’t show how to do the inverse. E.g. convert Euler angles to a matrix.

I suck at math unfortunately. Could someone figure out how to do this? Thanks!

[edit]

The above function is not working consistently either. Maybe I copied it wrong.

Solved, thanks to Stack Exchange.

-- Adapted from https://www.geometrictools.com/Documentation/EulerAngles.pdf, section 2.6
function MatrixToEuler(in_matrix)
	local r00 = in_matrix[9]
	local r01 = in_matrix[8]
	local r02 = in_matrix[7]
	local r10 = in_matrix[6]
	local r11 = in_matrix[5]
	local r12 = in_matrix[4]
	local r20 = in_matrix[3]
	local r21 = in_matrix[2]
	local r22 = in_matrix[1]
	local angleX = 0
	local angleY = 0
	local angleZ = 0
	if (r20 < 1) then
		if (r20 > -1) then
			angleX = atan2(r10, r00)
			angleY = asin(-r20)
			angleZ = atan2(r21, r22)
		else
			angleX = -atan2(-r12, r11)
			angleY = 90
			angleZ = 0
		end
	else
		angleX = atan2(-r12, r11)
		angleY = -90
		angleZ = 0
	end
	if (angleX < 0) then
		angleX = angleX + 360
	end
	if (angleY < 0) then
		angleY = angleY + 360
	end
	if (angleZ < 0) then
		angleZ = angleZ + 360
	end
	return {angleX, angleY, angleZ}
end


-- Adapted from https://www.geometrictools.com/Documentation/EulerAngles.pdf, section 2.6
function EulerToMatrix(in_euler)
	local angleX = in_euler[1]
	local angleY = in_euler[2]
	local angleZ = in_euler[3]
	local c1 = cos(angleX)
	local c2 = cos(angleY)
	local c3 = cos(angleZ)
	local s1 = sin(angleX)
	local s2 = sin(angleY)
	local s3 = sin(angleZ)
	local r00 =  c1 * c2
	local r01 =  c1 * s2 * s3 - c3 * s1
	local r02 =  s1 * s3 + c1 * c3 * s2
	local r10 =  c2 * s1
	local r11 =  c1 * c3 + s1 * s2 * s3
	local r12 =  c3 * s1 * s2 - c1 * s3
	local r20 = -s2
	local r21 =  c2 * s3
	local r22 =  c2 * c3
	return {r22,r21,r20,r12,r11,r10,r02,r01,r00}
end
1 Like

You need to use the deg function on the results from the inverse trig functions:

theta = deg(atan2(y, x))

That, or change the 90 to pi/4 and 360 to 2*pi

No, it works. Lua 4 uses degrees for everything.

Sigh… the differences between Lua 4 and 5… :man_facepalming:

1 Like