Skip to content

Instantly share code, notes, and snippets.

@Vincenz099
Last active January 1, 2021 15:40
Show Gist options
  • Select an option

  • Save Vincenz099/8a8c5d3a8ac0486da02c288abadb5238 to your computer and use it in GitHub Desktop.

Select an option

Save Vincenz099/8a8c5d3a8ac0486da02c288abadb5238 to your computer and use it in GitHub Desktop.
Smallest Three Bitlevel Addition
/*
* Copyright (c) 2019 Stanislav Denisov, Maxim Munnig Schmidt
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*
Delta Compression by Glenn Fiedler.
This source code is placed in the public domain.
http://gafferongames.com/2015/03/14/the-networked-physics-data-compression-challenge/
*/
//Generic:
private const float SmallestThreeUnpack = 0.70710678118654752440084436210485f + 0.0000001f; // addition to rounding to not overflow.
private const float SmallestThreePack = 1f / SmallestThreeUnpack; // sqrt(2)
//Compress + serialize:
public void CompressSerialQuad(Quaternion quaternion, int bitsPerValue, BitBuffer bitBuffer)
{
float halfrangeFloat = (1 << bitsPerValue - 1);
float packer = SmallestThreePack * halfrangeFloat;
uint m = 0;
float maxValue = float.MinValue;
bool signminus = false;
for (uint quadIndex = 0; quadIndex <= 3; quadIndex++)
{
float element = 0f;
float abs = 0f;
switch (quadIndex)
{
case 0:
element = quaternion.x;
break;
case 1:
element = quaternion.y;
break;
case 2:
element = quaternion.z;
break;
case 3:
element = quaternion.w;
break;
}
abs = Math.Abs(element);
if (abs > maxValue)
{
signminus = (element < 0f);
m = quadIndex;
maxValue = abs;
}
}
float aflt, bflt, cflt;
switch (m)
{
case 0: aflt = quaternion.y; bflt = quaternion.z; cflt = quaternion.w; break;
case 1: aflt = quaternion.x; bflt = quaternion.z; cflt = quaternion.w; break;
case 2: aflt = quaternion.x; bflt = quaternion.y; cflt = quaternion.w; break;
default: aflt = quaternion.x; bflt = quaternion.y; cflt = quaternion.z; break;
}
uint a, b, c;
if (signminus)
{
a = (uint)((-aflt * packer) + halfrangeFloat);
b = (uint)((-bflt * packer) + halfrangeFloat);
c = (uint)((-cflt * packer) + halfrangeFloat);
}
else
{
a = (uint)((aflt * packer) + halfrangeFloat);
b = (uint)((bflt * packer) + halfrangeFloat);
c = (uint)((cflt * packer) + halfrangeFloat);
}
bitBuffer.Add(2, m);
bitBuffer.Add(bitsPerValue, a);
bitBuffer.Add(bitsPerValue, b);
bitBuffer.Add(bitsPerValue, c);
}
//deserialize + Decompress:
public Quaternion DecompressUnserialQuad(int bitsPerValue, BitBuffer bitBuffer)
{
int halfrange = (1 << bitsPerValue -1 ); // - 1
float unpacker = SmallestThreeUnpack * (1f / halfrange);
uint m = bitBuffer.Read(2);
int aint = (int)bitBuffer.Read(bitsPerValue);
int bint = (int)bitBuffer.Read(bitsPerValue);
int cint = (int)bitBuffer.Read(bitsPerValue);
aint -= halfrange;
bint -= halfrange;
cint -= halfrange;
float a = aint * unpacker;
float b = bint * unpacker;
float c = cint * unpacker;
float d = (float)Math.Sqrt(1f - ((a * a) + (b * b) + (c * c)));
switch (m)
{
case 0:
return new Quaternion(d, a, b, c);
break;
case 1:
return new Quaternion(a, d, b, c);
break;
case 2:
return new Quaternion(a, b, d, c);
break;
case 3:
return new Quaternion(a, b, c, d);
break;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment