excessive / cpml

Cirno's Perfect Math Library: Just about everything you need for 2D/3D games. Hopefully.

Home Page:https://excessive.github.io/cpml/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

quat.to_angle_axis and default quaternion

Germanunkol opened this issue · comments

When I run to_angle_axis on the the identity quaternion (0,0,0,1), for example like this

print( cpml.quat.to_angle_axis( cpml.quat() ) )

then the result is

0 (+0.000,+0.000,+0.000)

I expected to get an angle of zero around an arbitray axis instead. The reason is that the identity quaternion is a valid rotation (0 around an axis), and running to_angle_axis on this valid rotation should give me a valid angle and axis, correct?

I had the to_angle_axis buried somewhere deep in my code. Now if I want to keep using it I would need to check for an axis of zero length every time...?

Is there a nice solution? Is this the expected behavior?

This does seem like a bug to me, I wanna talk to holo but I will look at this this weekend

this is somewhat expected, but definitely not good behavior. it should check the axis being returned to prevent this (default to +z axis or something)

Thanks for the replies. Yes, my current workaround does fall back to the X axis if the returned axis isn't valid:

function toAngleAxis( q )
	local ang, axis = cpml.quat.to_angle_axis( q )
	if cpml.vec3.len( axis ) < 0.9999 then
		axis = cpml.vec3(1,0,0)
		ang = 0
	end
	return ang, axis
end

Don't know if there's any "good" convention on which axis to choose, as the choice is arbitrary. Depending on what the user does with the rotation afterwards, this might be confusing as well. Another solution might be to let the user pass a fallback_axis to the function, which is chosen in this case? It could default to (0,0,1) if not supplied.

I'm happy to make a pull request if someone tells me which functionality to implement.

I tried looking at other implementations, here's Ogre's: https://github.com/OGRECave/ogre/blob/e1c3732c51f9099bed10d36805b738015adc8f47/OgreMain/src/OgreQuaternion.cpp#L126

It's a bit different from the one in cpml and seems to catch the error by falling back on the x-axis.

Is everyone in this thread okay with this solution? https://github.com/excessive/cpml/pull/56/files

  • Based on discussion with holo I do not compare to zero, I compare the length to DBL_EPSILON (I still wonder if this could ever do the wrong thing and left a comment to that effect but I don't understand quaternions so well)
  • Based on suggestion from Germanunkol you can include an identity default
  • Based on majority vote in this thread :P I default to Z-axis for identity.

I don't think it matters what axis we use as the fallback because the only situation where that could ever matter is if someone is composing angle-axis rotations (?) and if they're doing that they're already lost

I guess it would have made more sense to take the default axis instead of the default angle, huh…

Added tests and had it take the default axis instead of the default 4-value, which is less confusing anyway.

Addressed in #56 and it's in the "version 0.10.0" and "version 1.0.0" releases.