matrix - Understanding Dual Quaternion skinning -
i trying switch animation code matrices dual quaternions. i've read ladislav kavan's paper, , understand offers technique, transform animation matrix 2 special quaternions. reconstruct original matrix on gpu. however, failing work. when inserted code in app, animations got twisted, meaning reconstructed matrices incorrect.
i've written c# console app check , indeed case: matrices different before , after transformation. did normalize matrix before decomposition, not matter, reconstructed matrix never same. missing something? maybe input matrix should of specific type?
here console app code:
using system; using system.collections.generic; using system.linq; using system.text; using system.threading.tasks; using microsoft.xna.framework; namespace dualquaterniontest { class dualquaternion { public quaternion ordinary; public quaternion dual; public static matrix normalize(matrix m) { vector3 v = new vector3(m.m11, m.m21, m.m31); v.normalize(); m.m11 = v.x; m.m21 = v.y; m.m31 = v.z; v = new vector3(m.m12, m.m22, m.m32); v.normalize(); m.m12 = v.x; m.m22 = v.y; m.m32 = v.z; v = new vector3(m.m13, m.m23, m.m33); v.normalize(); m.m13 = v.x; m.m23 = v.y; m.m33 = v.z; return m; } public static dualquaternion quattrans2udq(quaternion q0, vector3 t) { dualquaternion dq = new dualquaternion(); dq.ordinary = q0; dq.dual.w = -0.5f * (t.x * q0.x + t.y * q0.y + t.z * q0.z); dq.dual.x = 0.5f * (t.x * q0.w + t.y * q0.z - t.z * q0.y); dq.dual.y = 0.5f * (-t.x * q0.z + t.y * q0.w + t.z * q0.x); dq.dual.z = 0.5f * (t.x * q0.y - t.y * q0.x + t.z * q0.w); return dq; } public static matrix udqtomatrix(dualquaternion dq) { matrix m; float len2 = quaternion.dot(dq.ordinary, dq.ordinary); float w = dq.ordinary.w, x = dq.ordinary.x, y = dq.ordinary.y, z = dq.ordinary.z; float t0 = dq.dual.w, t1 = dq.dual.x, t2 = dq.dual.y, t3 = dq.dual.z; m.m11 = w * w + x * x - y * y - z * z; m.m21 = 2 * x * y - 2 * w * z; m.m31 = 2 * x * z + 2 * w * y; m.m12 = 2 * x * y + 2 * w * z; m.m22 = w * w + y * y - x * x - z * z; m.m32 = 2 * y * z - 2 * w * x; m.m13 = 2 * x * z - 2 * w * y; m.m23 = 2 * y * z + 2 * w * x; m.m33 = w * w + z * z - x * x - y * y; m.m41 = -2 * t0 * x + 2 * w * t1 - 2 * t2 * z + 2 * y * t3; m.m42 = -2 * t0 * y + 2 * t1 * z - 2 * x * t3 + 2 * w * t2; m.m43 = -2 * t0 * z + 2 * x * t2 + 2 * w * t3 - 2 * t1 * y; m.m14 = 0; m.m24 = 0; m.m34 = 0; m.m44 = len2; m /= len2; return m; } } class program { static void main(string[] args) { matrix basematrix = matrix.identity; random random = new random(); basematrix.m11 = random.next(-1000000, 1000000) * 0.001f; basematrix.m12 = random.next(-1000000, 1000000) * 0.001f; basematrix.m13 = random.next(-1000000, 1000000) * 0.001f; basematrix.m14 = random.next(-1000000, 1000000) * 0.001f; basematrix.m21 = random.next(-1000000, 1000000) * 0.001f; basematrix.m22 = random.next(-1000000, 1000000) * 0.001f; basematrix.m23 = random.next(-1000000, 1000000) * 0.001f; basematrix.m24 = random.next(-1000000, 1000000) * 0.001f; basematrix.m31 = random.next(-1000000, 1000000) * 0.001f; basematrix.m32 = random.next(-1000000, 1000000) * 0.001f; basematrix.m33 = random.next(-1000000, 1000000) * 0.001f; basematrix.m34 = random.next(-1000000, 1000000) * 0.001f; basematrix.m41 = random.next(-1000000, 1000000) * 0.001f; basematrix.m42 = random.next(-1000000, 1000000) * 0.001f; basematrix.m43 = random.next(-1000000, 1000000) * 0.001f; basematrix.m44 = random.next(-1000000, 1000000) * 0.001f; matrix normalizedbasematrix = dualquaternion.normalize(basematrix); quaternion[] qq = new quaternion[2]; dualquaternion dualquaternion = null; dualquaternion = dualquaternion.quattrans2udq( quaternion.createfromrotationmatrix(normalizedbasematrix), normalizedbasematrix.translation); reconstructedmatrix = dualquaternion.udqtomatrix(dualquaternion); console.writeline(basematrix.tostring()); console.writeline(); console.writeline(normalizedbasematrix.tostring()); console.writeline(); console.writeline(reconstructedmatrix.tostring()); console.readkey(); } } }
when have matrix filled 16 random values (or 12 if considering 4x3 portion, since rightmost column going 0,0,0,1 in udqtomatrix
function), creating transforms cannot represented dual quaternions.
quaternions (and dual quaternions) cannot represent arbitrary non-orthogonal axes.
instead of generating random values, generate matrices randomizing operations of translation , rotation. should able convert reliably between matrix , dual quaternion
Comments
Post a Comment