Essle

[FUNC] Euler angles into quaternions

Recommended Posts

Function to translate angles of Euler into quaternions.

  • Arguments: RotX, RotY, RotZ
  • Return: RotX, RotY, RotZ, RotW
function math.quaternion(x, y, z)
	local c = { math.cos(math.rad(-x)), math.cos(math.rad(-y)), math.cos(math.rad(z)) }
	local s = { math.sin(math.rad(-x)), math.sin(math.rad(-y)), math.sin(math.rad(z)) }
	local t = { c[2] * c[3], s[1] * s[2] * s[3] + c[1] * c[3], c[1] * c[2] }
	return 
	math.drt(1.0 + t[1] - t[2] - t[3], (c[3] * s[1] - c[1] * s[2] * s[3]) - (-s[1] * c[2])),
	math.drt(1.0 - t[1] + t[2] - t[3], s[2] + (c[1] * s[2] * c[3] + s[1] * s[3])),
	math.drt(1.0 - t[1] - t[2] + t[3], (s[1] * s[2] * c[3] - c[1] * s[3]) - (c[2] * s[3])),
	math.drt(1.0 + t[1] + t[2] + t[3])
end

function math.drt(a, b)
	a = math.sqrt(math.max(0.0, a)) * 0.5
	return (b and ((b < 0) and -math.abs(a) or math.abs(a)) or a)
end

 

Edited by Essle
Updated function syntax
  • Like 1
  • Thanks 1

Share this post


Link to post

where to use it in a real situation? to calculate what? give a layman example... what did you used it for? thanks

Share this post


Link to post

This function is needed to convert .map to .ipl
In all converters rotation is not calculated correctly. But this function works perfectly.

Example

local file = File.new("map-test.ipl")
file:write("inst\n")

for _, theSubject in ipairs(Element.getAllByType("object")) do

	local rX, rY, rZ = getElementRotation(theSubject, "ZXY") 
	local rW = 0
	rX, rY, rZ, rW = math.quaternion(rX, rY, rZ)

	file:write(
		theSubject.model..", "..engineGetModelNameFromID(theSubject.model)..", 0, "..
		theSubject.position.x..", "..theSubject.position.y..", "..theSubject.position.z..", "..
		rX..", "..rY..", "..rZ..", "..rW..", -1\n"
	)

end

file:write("end")
file:flush()
file:close()

 

  • Thanks 1

Share this post


Link to post
function math.quaternion(x, y, z)
	local rx = math.rad( -x )
	local ry = math.rad( -y )
	local rz = math.rad( z )
	local fCosX = math.cos(rx)
	local fCosY = math.cos(ry)
	local fCosZ = math.cos(rz)
	local fSinX = math.sin(rx)
	local fSinY = math.sin(ry)
	local fSinZ = math.sin(rz)
	local temp1 = fCosY * fCosZ
	local temp2 = fSinX * fSinY * fSinZ + fCosX * fCosZ
	local temp3 = fCosX * fCosY
	local w = math.sqrt(math.max(0.0, 1.0 + temp1 + temp2 + temp3)) * 0.5
	local x = math.sqrt(math.max(0.0, 1.0 + temp1 - temp2 - temp3)) * 0.5
	local y = math.sqrt(math.max(0.0, 1.0 - temp1 + temp2 - temp3)) * 0.5
	local z = math.sqrt(math.max(0.0, 1.0 - temp1 - temp2 + temp3)) * 0.5
	x = math.sign(x, (fCosZ * fSinX - fCosX * fSinY * fSinZ) - (-fSinX * fCosY))
	y = math.sign(y, fSinY + (fCosX * fSinY * fCosZ + fSinX * fSinZ))
	z = math.sign(z, (fSinX * fSinY * fCosZ - fCosX * fSinZ) - (fCosY * fSinZ))
	return x, y, z, w
end

function math.sign(x, a)
	return (a < 0) and -math.abs(x) or math.abs(x)
end

This will get a better performance, won't it?

Edited by thisdp

Share this post


Link to post
36 minutes ago, thisdp said:

This will get a better performance, won't it?

On tests you will not even notice difference.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.