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

DOT_THRESHOLD seems to break things

mcclure opened this issue · comments

Short version: I am getting incorrect results when composing a quaternion with a pow()ed version of another quaternion. Looking at the code in quat.lua I find

	if dot > DOT_THRESHOLD then
		return a:scale(s)
	end

I don't understand what this means, but if I remove it, I get correct results again.

Long version:

I am generating a random quaternion with

	local RQ = quat.from_angle_axis( (math.random()-0.5)*maxAngle*2, 1,0,0 )
	        * quat.from_angle_axis( (math.random()-0.5)*maxAngle*2, 0,1,0 )
	        * quat.from_angle_axis( (math.random()-0.5)*maxAngle*2, 0,0,1 )

I'm not doing anything to set the seed so I get get consistent values every time I run. I have a quaternion EQ representing the rotation of an object. For each object I am animating RQ:pow(x)*EQ with x interpolating from 0 to 1.

For one of the objects (but not the others), RQ managed to find a "cursed" quaternion CQ; if I print out the xyzq values of CQ with string.format("%f") I get -0.014149,0.020479,-0.006684,0.999668. If I take CQ to a power, I get wacky results. If I take it to a power around 0.05, even though CQ is a very small rotation, this small power of a small rotation results in a huge rotation essentially equivalent to flipping 180 degrees on the X axis. pow() appears to work with quaternions other than CQ.

If I modify my transformation library to automatically normalize quaternions before applying them, the object just sort of jitters and freezes in place; it turns out if I take CQ and raise it to any power less than 1, then normalize, I get -0.019496,0.026780,-0.001824,0.999450 regardless of which power I took it to:

local quatTest = quat(-0.014149,0.020479,-0.006684,0.999668)
print("QUAT TEST", quatTest, quatTest:pow(1/36):normalize(), quatTest:pow(1/2):normalize())

If I remove the if dot > DOT_THRESHOLD block from the definition of pow(), all these problems go away.

I am totally lost. It seems there is a bug in pow(), but I feel afraid just taking the code out since I don't know why it's there?

reading the code, i'm pretty confident that the dot check is a copy paste error from slerp that wasn't tested well enough. maybe it's derived from something that made sense, but it doesn't now.

i would remove it.