tbttfox / math3d

A numpy based vector/transform library with a focus on 3d graphics
20 stars 1 forks source link

Matrix3.asQuaternion() returns wrong result #4

Open jpasserin opened 2 years ago

jpasserin commented 2 years ago
from math3d.matrixN import Matrix3
m = Matrix3([1,0,0,0,-1,0,0,0,-1])
print(m.asQuaternion())
# [0.000000e+00  0.000000e+00  0.000000e+00  6.123234e-17]
# This is basically (0,0,0,0) which is not a valid quaternion

I found an alternate algorithm for Matrix3 to Quaternion which gave me the correct result

from math import sqrt

m = [[1,0,0],[0,-1,0],[0,0,-1]]

tr = m[0][0] + m[1][1] + m[2][2]

if tr > 0:
    S = sqrt(tr+1.0) * 2
    qw = 0.25 * S
    qx = (m[2][1] - m[1][2]) / S
    qy = (m[0][2] - m[2][0]) / S
    qz = (m[1][0] - m[0][1]) / S
elif (m[0][0] > m[1][1]) and (m[0][0] > m[2][2]):
    S = sqrt(1.0 + m[0][0] - m[1][1] - m[2][2]) * 2
    qw = (m[2][1] - m[1][2]) / S
    qx = 0.25 * S
    qy = (m[0][1] + m[1][0]) / S
    qz = (m[0][2] + m[2][0]) / S
elif m[1][1] > m[2][2]:
    S = sqrt(1.0 + m[1][1] - m[0][0] - m[2][2]) * 2
    qw = (m[0][2] - m[2][0]) / S
    qx = (m[0][1] + m[1][0]) / S
    qy = 0.25 * S
    qz = (m[1][2] + m[2][1]) / S
else: 
    S = sqrt(1.0 + m[2][2] - m[0][0] - m[1][1]) * 2
    qw = (m[1][0] - m[0][1]) / S
    qx = (m[0][2] + m[2][0]) / S
    qy = (m[1][2] + m[2][1]) / S
    qz = 0.25 * S

print (qx, qy, qz, qw)
# (1,0,0,0)
jpasserin commented 2 years ago

Looks like there is still an issue. it seems that when passing an Array of Matrix3 the output quaternion array is an array of the last item.

from math3d import Matrix3, Matrix3Array

m = Matrix3Array(
    [Matrix3([1,0,0,0,1,0,0,0,1])]
)

print(m)
# [[[1. 0. 0.]
#  [0. 1. 0.]
#  [0. 0. 1.]]]

print(m.asQuaternionArray())
# Correct Result, when passing only one matrix3
# [[0. 0. 0. 1.]]

But when passing two matrices

from math3d import Matrix3, Matrix3Array

m = Matrix3Array([
    Matrix3([1,0,0,0,1,0,0,0,1]),
    Matrix3([.707,0,.707,0,1,0,-.707,0,.707])]
)

print(m)
# [[[ 1.     0.     0.   ]
#  [ 0.     1.     0.   ]
#  [ 0.     0.     1.   ]]
# [[ 0.707  0.     0.707]
#  [ 0.     1.     0.   ]
#  [-0.707  0.     0.707]]]

print(m.asQuaternionArray())
# This is seems to be the second matrix twice
# [[0.         0.38263761 0.         0.92385064]
# [0.         0.38263761 0.         0.92385064]]

# Should be 
# [[0. 0. 0. 1.]
# [0.         0.38263761 0.         0.92385064]]
tbttfox commented 2 years ago

OK, should work now.