/// <summary> /// Compresses <see cref="AnimTrackTransform"></see> track and writes to writer /// </summary> /// <param name="w"></param> /// <param name="values"></param> private void CompressTransformTracks(BinaryWriter w, IList <object> values) { Quantanizer sx = new Quantanizer(); Quantanizer sy = new Quantanizer(); Quantanizer sz = new Quantanizer(); Quantanizer rx = new Quantanizer(); Quantanizer ry = new Quantanizer(); Quantanizer rz = new Quantanizer(); Quantanizer x = new Quantanizer(); Quantanizer y = new Quantanizer(); Quantanizer z = new Quantanizer(); // pre-process foreach (AnimTrackTransform transform in values) { sx.Add(transform.Sx); sy.Add(transform.Sy); sz.Add(transform.Sz); rx.Add(transform.Rx); ry.Add(transform.Ry); rz.Add(transform.Rz); x.Add(transform.X); y.Add(transform.Y); z.Add(transform.Z); } short flags = 0; ushort bitsPerEntry = 0; bool hasScale = (!sx.Constant || !sy.Constant || !sz.Constant); bool hasRotation = (!rx.Constant || !ry.Constant || !rz.Constant); bool hasPosition = (!x.Constant || !y.Constant || !z.Constant); if (sx.GetBitCount(epsilon) == -1 || sy.GetBitCount(epsilon) == -1 || (sz.GetBitCount(epsilon) == -1 || rx.GetBitCount(epsilon) == -1) || (ry.GetBitCount(epsilon) == -1 || rz.GetBitCount(epsilon) == -1 || (x.GetBitCount(epsilon) == -1 || y.GetBitCount(epsilon) == -1)) || z.GetBitCount(epsilon) == -1) { throw new Exception("Compression Level is too small to compress!"); } if (!hasScale) { flags |= 0x02; } else { bitsPerEntry += (ushort)((sx.Constant ? 0 : sx.GetBitCount(epsilon)) + (sy.Constant ? 0 : sy.GetBitCount(epsilon)) + (sz.Constant ? 0 : sz.GetBitCount(epsilon))); flags |= 0x01; } if (hasRotation) { bitsPerEntry += (ushort)((rx.Constant ? 0 : rx.GetBitCount(epsilon)) + (ry.Constant ? 0 : ry.GetBitCount(epsilon)) + (rz.Constant ? 0 : rz.GetBitCount(epsilon)) + 1); // the 1 is for extra w rotation bit flags |= 0x04; } if (hasPosition) { bitsPerEntry += (ushort)((x.Constant ? 0 : x.GetBitCount(epsilon)) + (y.Constant ? 0 : y.GetBitCount(epsilon)) + (z.Constant ? 0 : z.GetBitCount(epsilon))); flags |= 0x08; } // Compressed Header w.Write((short)0x04); w.Write(flags); w.Write((short)160); w.Write(bitsPerEntry); w.Write(204); w.Write(values.Count); w.Write(sx.Min); w.Write(sx.Max); w.Write(hasScale ? sx.GetBitCount(epsilon) : 16L); w.Write(sy.Min); w.Write(sy.Max); w.Write(hasScale ? sy.GetBitCount(epsilon) : 16L); w.Write(sz.Min); w.Write(sz.Max); w.Write(hasScale ? sz.GetBitCount(epsilon) : 16L); w.Write(rx.Min); w.Write(rx.Max); w.Write(hasRotation ? rx.GetBitCount(epsilon) : 16L); w.Write(ry.Min); w.Write(ry.Max); w.Write(hasRotation ? ry.GetBitCount(epsilon) : 16L); w.Write(rz.Min); w.Write(rz.Max); w.Write(hasRotation ? rz.GetBitCount(epsilon) : 16L); w.Write(x.Min); w.Write(x.Max); w.Write(hasPosition ? x.GetBitCount(epsilon) : 16L); w.Write(y.Min); w.Write(y.Max); w.Write(hasPosition ? y.GetBitCount(epsilon) : 16L); w.Write(z.Min); w.Write(z.Max); w.Write(hasPosition ? z.GetBitCount(epsilon) : 16L); AnimTrackTransform defaultValue = (AnimTrackTransform)values[0]; w.Write(defaultValue.Sx); w.Write(defaultValue.Sy); w.Write(defaultValue.Sz); w.Write(defaultValue.Rx); w.Write(defaultValue.Ry); w.Write(defaultValue.Rz); w.Write(defaultValue.Rw); w.Write(defaultValue.X); w.Write(defaultValue.Y); w.Write(defaultValue.Z); w.Write(0); // write compressed values BitWriter writer = new BitWriter(); foreach (AnimTrackTransform transform in values) { if (hasScale) { writer.WriteBits(sx.GetQuantanizedValue(transform.Sx), sx.GetBitCount(epsilon)); writer.WriteBits(sy.GetQuantanizedValue(transform.Sy), sy.GetBitCount(epsilon)); writer.WriteBits(sz.GetQuantanizedValue(transform.Sz), sz.GetBitCount(epsilon)); } if (hasRotation) { writer.WriteBits(rx.GetQuantanizedValue(transform.Rx), rx.GetBitCount(epsilon)); writer.WriteBits(ry.GetQuantanizedValue(transform.Ry), ry.GetBitCount(epsilon)); writer.WriteBits(rz.GetQuantanizedValue(transform.Rz), rz.GetBitCount(epsilon)); } if (hasPosition) { writer.WriteBits(x.GetQuantanizedValue(transform.X), x.GetBitCount(epsilon)); writer.WriteBits(y.GetQuantanizedValue(transform.Y), y.GetBitCount(epsilon)); writer.WriteBits(z.GetQuantanizedValue(transform.Z), z.GetBitCount(epsilon)); } if (hasRotation) { // flip w bit float calculateW = (float)Math.Sqrt(Math.Abs(1 - ( rx.DecompressedValue(transform.Rx) * rx.DecompressedValue(transform.Rx) + ry.DecompressedValue(transform.Ry) * ry.DecompressedValue(transform.Ry) + rz.DecompressedValue(transform.Rz) * rz.DecompressedValue(transform.Rz)))); writer.WriteBits(Math.Sign(transform.Rw) != Math.Sign(calculateW) ? 1 : 0, 1); } } w.Write(writer.GetBytes()); }
/// <summary> /// Compresses <see cref="AnimTrackTransform" track and writes to writer/> /// </summary> /// <param name="w"></param> /// <param name="values"></param> private void CompressTransformTracks(BinaryWriter w, IList <object> values) { Quantanizer SX = new Quantanizer(); Quantanizer SY = new Quantanizer(); Quantanizer SZ = new Quantanizer(); Quantanizer RX = new Quantanizer(); Quantanizer RY = new Quantanizer(); Quantanizer RZ = new Quantanizer(); Quantanizer X = new Quantanizer(); Quantanizer Y = new Quantanizer(); Quantanizer Z = new Quantanizer(); // pre-process foreach (AnimTrackTransform transform in values) { SX.Add(transform.SX); SY.Add(transform.SY); SZ.Add(transform.SZ); RX.Add(transform.RX); RY.Add(transform.RY); RZ.Add(transform.RZ); X.Add(transform.X); Y.Add(transform.Y); Z.Add(transform.Z); } short Flags = 0; ushort BitsPerEntry = 0; bool hasScale = (!SX.Constant || !SY.Constant || !SZ.Constant); bool hasRotation = (!RX.Constant || !RY.Constant || !RZ.Constant); bool hasPosition = (!X.Constant || !Y.Constant || !Z.Constant); if (!hasScale) { Flags |= 0x02; } else { BitsPerEntry += (ushort)((SX.Constant ? 0 : SX.GetBitCount(Epsilon)) + (SY.Constant ? 0 : SY.GetBitCount(Epsilon)) + (SZ.Constant ? 0 : SZ.GetBitCount(Epsilon))); Flags |= 0x01; } if (hasRotation) { BitsPerEntry += (ushort)((RX.Constant ? 0 : RX.GetBitCount(Epsilon)) + (RY.Constant ? 0 : RY.GetBitCount(Epsilon)) + (RZ.Constant ? 0 : RZ.GetBitCount(Epsilon)) + 1); // the 1 is for extra w rotation bit Flags |= 0x04; } if (hasPosition) { BitsPerEntry += (ushort)((X.Constant ? 0 : X.GetBitCount(Epsilon)) + (Y.Constant ? 0 : Y.GetBitCount(Epsilon)) + (Z.Constant ? 0 : Z.GetBitCount(Epsilon))); Flags |= 0x08; } // Compressed Header w.Write((short)0x04); w.Write(Flags); w.Write((short)(0x10 + 0x10 * 9)); // default values offset w.Write(BitsPerEntry); w.Write(0x10 + 0x10 * 9 + sizeof(float) * 11); // compressed data start w.Write(values.Count); // frame count // write chunks w.Write(SX.Min); w.Write(SX.Max); w.Write((long)SX.GetBitCount(Epsilon)); w.Write(SY.Min); w.Write(SY.Max); w.Write((long)SY.GetBitCount(Epsilon)); w.Write(SZ.Min); w.Write(SZ.Max); w.Write((long)SZ.GetBitCount(Epsilon)); w.Write(RX.Min); w.Write(RX.Max); w.Write((long)RX.GetBitCount(Epsilon)); w.Write(RY.Min); w.Write(RY.Max); w.Write((long)RY.GetBitCount(Epsilon)); w.Write(RZ.Min); w.Write(RZ.Max); w.Write((long)RZ.GetBitCount(Epsilon)); w.Write(X.Min); w.Write(X.Max); w.Write((long)X.GetBitCount(Epsilon)); w.Write(Y.Min); w.Write(Y.Max); w.Write((long)Y.GetBitCount(Epsilon)); w.Write(Z.Min); w.Write(Z.Max); w.Write((long)Z.GetBitCount(Epsilon)); // write default values AnimTrackTransform defaultValue = (AnimTrackTransform)values[0]; w.Write(defaultValue.SX); w.Write(defaultValue.SY); w.Write(defaultValue.SZ); w.Write(defaultValue.RX); w.Write(defaultValue.RY); w.Write(defaultValue.RZ); w.Write(defaultValue.RW); w.Write(defaultValue.X); w.Write(defaultValue.Y); w.Write(defaultValue.Z); w.Write(0); // write compressed values BitWriter writer = new BitWriter(); foreach (AnimTrackTransform transform in values) { if (hasScale) { writer.WriteBits(SX.GetQuantanizedValue(transform.SX), SX.GetBitCount(Epsilon)); writer.WriteBits(SY.GetQuantanizedValue(transform.SY), SY.GetBitCount(Epsilon)); writer.WriteBits(SZ.GetQuantanizedValue(transform.SZ), SZ.GetBitCount(Epsilon)); } if (hasRotation) { writer.WriteBits(RX.GetQuantanizedValue(transform.RX), RX.GetBitCount(Epsilon)); writer.WriteBits(RY.GetQuantanizedValue(transform.RY), RY.GetBitCount(Epsilon)); writer.WriteBits(RZ.GetQuantanizedValue(transform.RZ), RZ.GetBitCount(Epsilon)); } if (hasPosition) { writer.WriteBits(X.GetQuantanizedValue(transform.X), X.GetBitCount(Epsilon)); writer.WriteBits(Y.GetQuantanizedValue(transform.Y), Y.GetBitCount(Epsilon)); writer.WriteBits(Z.GetQuantanizedValue(transform.Z), Z.GetBitCount(Epsilon)); } if (hasRotation) { // flip w bit float calculateW = (float)Math.Sqrt(Math.Abs(1 - ( RX.DecompressedValue(transform.RX) * RX.DecompressedValue(transform.RX) + RY.DecompressedValue(transform.RY) * RY.DecompressedValue(transform.RY) + RZ.DecompressedValue(transform.RZ) * RZ.DecompressedValue(transform.RZ)))); writer.WriteBits(Math.Sign((int)transform.RW) != Math.Sign((int)calculateW) ? 1 : 0, 1); } } w.Write(writer.GetBytes()); }
/// <summary> /// Compresses <see cref="AnimTrackTransform"></see> track and writes to writer /// </summary> /// <param name="w"></param> /// <param name="values"></param> private void CompressTransformTracks(BinaryWriter w, IList <object> values) { Quantanizer sx = new Quantanizer(); Quantanizer sy = new Quantanizer(); Quantanizer sz = new Quantanizer(); Quantanizer rx = new Quantanizer(); Quantanizer ry = new Quantanizer(); Quantanizer rz = new Quantanizer(); Quantanizer x = new Quantanizer(); Quantanizer y = new Quantanizer(); Quantanizer z = new Quantanizer(); // pre-process foreach (AnimTrackTransform transform in values) { sx.Add(transform.Sx); sy.Add(transform.Sy); sz.Add(transform.Sz); rx.Add(transform.Rx); ry.Add(transform.Ry); rz.Add(transform.Rz); x.Add(transform.X); y.Add(transform.Y); z.Add(transform.Z); } short flags = 0; ushort bitsPerEntry = 0; bool hasScale = (!sx.Constant || !sy.Constant || !sz.Constant); bool hasRotation = (!rx.Constant || !ry.Constant || !rz.Constant); bool hasPosition = (!x.Constant || !y.Constant || !z.Constant); if (!hasScale) { flags |= 0x02; } else { bitsPerEntry += (ushort)((sx.Constant ? 0 : sx.GetBitCount(epsilon)) + (sy.Constant ? 0 : sy.GetBitCount(epsilon)) + (sz.Constant ? 0 : sz.GetBitCount(epsilon))); flags |= 0x01; } if (hasRotation) { bitsPerEntry += (ushort)((rx.Constant ? 0 : rx.GetBitCount(epsilon)) + (ry.Constant ? 0 : ry.GetBitCount(epsilon)) + (rz.Constant ? 0 : rz.GetBitCount(epsilon)) + 1); // the 1 is for extra w rotation bit flags |= 0x04; } if (hasPosition) { bitsPerEntry += (ushort)((x.Constant ? 0 : x.GetBitCount(epsilon)) + (y.Constant ? 0 : y.GetBitCount(epsilon)) + (z.Constant ? 0 : z.GetBitCount(epsilon))); flags |= 0x08; } // Compressed Header w.Write((short)0x04); w.Write(flags); w.Write((short)(0x10 + 0x10 * 9)); // default values offset w.Write(bitsPerEntry); w.Write(0x10 + 0x10 * 9 + sizeof(float) * 11); // compressed data start w.Write(values.Count); // frame count // write chunks w.Write(sx.Min); w.Write(sx.Max); w.Write((long)sx.GetBitCount(epsilon)); w.Write(sy.Min); w.Write(sy.Max); w.Write((long)sy.GetBitCount(epsilon)); w.Write(sz.Min); w.Write(sz.Max); w.Write((long)sz.GetBitCount(epsilon)); w.Write(rx.Min); w.Write(rx.Max); w.Write((long)rx.GetBitCount(epsilon)); w.Write(ry.Min); w.Write(ry.Max); w.Write((long)ry.GetBitCount(epsilon)); w.Write(rz.Min); w.Write(rz.Max); w.Write((long)rz.GetBitCount(epsilon)); w.Write(x.Min); w.Write(x.Max); w.Write((long)x.GetBitCount(epsilon)); w.Write(y.Min); w.Write(y.Max); w.Write((long)y.GetBitCount(epsilon)); w.Write(z.Min); w.Write(z.Max); w.Write((long)z.GetBitCount(epsilon)); // write default values AnimTrackTransform defaultValue = (AnimTrackTransform)values[0]; w.Write(defaultValue.Sx); w.Write(defaultValue.Sy); w.Write(defaultValue.Sz); w.Write(defaultValue.Rx); w.Write(defaultValue.Ry); w.Write(defaultValue.Rz); w.Write(defaultValue.Rw); w.Write(defaultValue.X); w.Write(defaultValue.Y); w.Write(defaultValue.Z); w.Write(0); // write compressed values BitWriter writer = new BitWriter(); foreach (AnimTrackTransform transform in values) { if (hasScale) { writer.WriteBits(sx.GetQuantanizedValue(transform.Sx), sx.GetBitCount(epsilon)); writer.WriteBits(sy.GetQuantanizedValue(transform.Sy), sy.GetBitCount(epsilon)); writer.WriteBits(sz.GetQuantanizedValue(transform.Sz), sz.GetBitCount(epsilon)); } if (hasRotation) { writer.WriteBits(rx.GetQuantanizedValue(transform.Rx), rx.GetBitCount(epsilon)); writer.WriteBits(ry.GetQuantanizedValue(transform.Ry), ry.GetBitCount(epsilon)); writer.WriteBits(rz.GetQuantanizedValue(transform.Rz), rz.GetBitCount(epsilon)); } if (hasPosition) { writer.WriteBits(x.GetQuantanizedValue(transform.X), x.GetBitCount(epsilon)); writer.WriteBits(y.GetQuantanizedValue(transform.Y), y.GetBitCount(epsilon)); writer.WriteBits(z.GetQuantanizedValue(transform.Z), z.GetBitCount(epsilon)); } if (hasRotation) { // flip w bit float calculateW = (float)Math.Sqrt(Math.Abs(1 - ( rx.DecompressedValue(transform.Rx) * rx.DecompressedValue(transform.Rx) + ry.DecompressedValue(transform.Ry) * ry.DecompressedValue(transform.Ry) + rz.DecompressedValue(transform.Rz) * rz.DecompressedValue(transform.Rz)))); writer.WriteBits(Math.Sign((int)transform.Rw) != Math.Sign((int)calculateW) ? 1 : 0, 1); } } w.Write(writer.GetBytes()); }