“Average” of multiple quaternions?

前端 未结 13 1617
执念已碎
执念已碎 2020-12-12 17:31

I\'m trying to make the switch from matrices to quaternions for skeletal animation in my OpenGL program, but I\'ve encountered a problem:

Given a number of unit quat

13条回答
  •  醉梦人生
    2020-12-12 17:44

    Quaternions are not an ideal set of DOF to use for rotations when computing an unconstrained average.

    Here is what I use most of the time (

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
        internal static Vector3 ToAngularVelocity( this Quaternion q )
        {
            if ( abs(q.w) > 1023.5f / 1024.0f)
                return new Vector3();
                var angle = acos( abs(q.w) );
                var gain = Sign(q.w)*2.0f * angle / Sin(angle);
    
            return new Vector3(q.x * gain, q.y * gain, q.z * gain);
        }
    
    
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        internal static Quaternion FromAngularVelocity( this Vector3 w )
        {
            var mag = w.magnitude;
            if (mag <= 0)
                return Quaternion.identity;
            var cs = cos(mag * 0.5f);
            var siGain = sin(mag * 0.5f) / mag;
            return new Quaternion(w.x * siGain, w.y * siGain, w.z * siGain, cs);
    
        }
    
        internal static Quaternion Average(this Quaternion refence, Quaternion[] source)
        {
    
            var refernceInverse = refence.Inverse();
            Assert.IsFalse(source.IsNullOrEmpty());
            Vector3 result = new Vector3();
            foreach (var q in source)
            {
                result += (refernceInverse*q).ToAngularVelocity();
            }
    
            return reference*((result / source.Length).FromAngularVelocity());
        }
         internal static Quaternion Average(Quaternion[] source)
        {
            Assert.IsFalse(source.IsNullOrEmpty());
            Vector3 result = new Vector3();
            foreach (var q in source)
            {
                result += q.ToAngularVelocity();
            }
    
            return (result / source.Length).FromAngularVelocity();
        }
         internal static Quaternion Average(Quaternion[] source, int iterations)
        {
            Assert.IsFalse(source.IsNullOrEmpty());
            var reference = Quaternion.identity;
            for(int i = 0;i < iterations;i++)
            {
                reference = Average(reference,source);
    
            }
            return reference;
    
        }`
    

提交回复
热议问题