Jump to content

[FUNC] Euler angles into quaternions


Essle

Recommended Posts

Posted (edited)

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
Posted

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()

 

  • Moderators
Posted (edited)
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

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...