四元数压缩
https://blog.codingnow.com/2017/11/quaternion_compress.html
https://bitbucket.org/Nabril/unitynetworking/commits/702a387656c6ee54311345a1c29f286767b59a22?at=5.4
public void Write(Quaternion value) { //nafio info index,用来标识绝对值最大的那个分量的index int largest = 0; float a, b, c; float abs_w = Mathf.Abs(value.w); float abs_x = Mathf.Abs(value.x); float abs_y = Mathf.Abs(value.y); float abs_z = Mathf.Abs(value.z); float largest_value = abs_x; if (abs_y > largest_value) { largest = 1; largest_value = abs_y; } if (abs_z > largest_value) { largest = 2; largest_value = abs_z; } if (abs_w > largest_value) { largest = 3; largest_value = abs_w; } //nafio info 最终要将4个分量存到uint中,这里应该决定了哪个分量存哪个位置 //假设largest=3 //a = value[4%4] = value[0] = x //b = value[5%4] = value[1] = y //c = value[6%4] = value[2] = z //假设largest=2 //a = value[3%4] = value[3] = w //b = value[4%4] = value[0] = x //c = value[5%4] = value[1] = y if (value[largest] >= 0f) { a = value[(largest + 1) % 4]; b = value[(largest + 2) % 4]; c = value[(largest + 3) % 4]; } else { a = -value[(largest + 1) % 4]; b = -value[(largest + 2) % 4]; c = -value[(largest + 3) % 4]; } //nafio 这里 1/根号2 有什么玄机还不清楚 //这里实际是个精度,但为什么精度是这个需要考虑 // serialize const float minimum = -1.0f / 1.414214f; // note: 1.0f / sqrt(2) const float maximum = +1.0f / 1.414214f; const float delta = maximum - minimum; const uint maxIntegerValue = (1 << 10) - 1; // 10 bits const float maxIntegerValueF = (float)maxIntegerValue; float normalizedValue; uint integerValue; uint sentData = ((uint)largest) << 30; // a normalizedValue = Mathf.Clamp01((a - minimum) / delta); integerValue = (uint)Mathf.Floor(normalizedValue * maxIntegerValueF + 0.5f); sentData = sentData | ((integerValue & maxIntegerValue) << 20); // b normalizedValue = Mathf.Clamp01((b - minimum) / delta); integerValue = (uint)Mathf.Floor(normalizedValue * maxIntegerValueF + 0.5f); sentData = sentData | ((integerValue & maxIntegerValue) << 10); // c normalizedValue = Mathf.Clamp01((c - minimum) / delta); integerValue = (uint)Mathf.Floor(normalizedValue * maxIntegerValueF + 0.5f); sentData = sentData | (integerValue & maxIntegerValue); Write(sentData); }