| 22 | }; |
| 23 | |
| 24 | FORCE_INLINE static void Read(NetworkStream* stream, Quaternion& data) |
| 25 | { |
| 26 | uint8 flags; |
| 27 | stream->Read(flags); |
| 28 | if (flags == None) |
| 29 | { |
| 30 | // Early out on default value |
| 31 | data = Quaternion::Identity; |
| 32 | return; |
| 33 | } |
| 34 | |
| 35 | Quaternion raw = Quaternion::Identity; |
| 36 | #define READ_COMPONENT(comp, hasFlag, negativeFlag) \ |
| 37 | if (flags & hasFlag) \ |
| 38 | { \ |
| 39 | uint16 packed; \ |
| 40 | stream->Read(packed); \ |
| 41 | const float norm = (float)packed / (float)MAX_uint16; \ |
| 42 | raw.comp = norm; \ |
| 43 | if (flags & negativeFlag) \ |
| 44 | raw.comp = -raw.comp; \ |
| 45 | } |
| 46 | READ_COMPONENT(X, HasX, NegativeX); |
| 47 | READ_COMPONENT(Y, HasY, NegativeY); |
| 48 | READ_COMPONENT(Z, HasZ, NegativeZ); |
| 49 | #define READ_COMPONENT |
| 50 | |
| 51 | // Calculate W |
| 52 | raw.W = Math::Sqrt(Math::Max(1.0f - raw.X * raw.X - raw.Y * raw.Y - raw.Z * raw.Z, 0.0f)); |
| 53 | if (flags & NegativeW) |
| 54 | raw.W = -raw.W; |
| 55 | |
| 56 | raw.Normalize(); |
| 57 | data = raw; |
| 58 | } |
| 59 | |
| 60 | FORCE_INLINE static void Write(NetworkStream* stream, const Quaternion& data) |
| 61 | { |