Jump to content

[FUNC] Euler angles into quaternions


Essle

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
Link to comment

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
Link to comment
  • Scripting Moderators
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
  • Thanks 1
Link to comment

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.
×
×
  • Create New...