#include <iostream>
#include <iomanip>
#include <vector>
#include <cmath>
using namespace std;
typedef unsigned char uchar;
struct float3 {
float x, y, z;
};
ostream &operator<<(ostream &out, float3 v) {
return out << fixed << setprecision(2) << "float3( "
<< setw(5) << v.x << ","
<< setw(5) << v.y << ","
<< setw(5) << v.z << " )";
}
struct uchar4 {
uchar x, y, z, w;
};
ostream &operator<<(ostream &out, uchar4 v) {
return out << "uchar4( "
<< setw(3) << (int)v.x << ","
<< setw(3) << (int)v.y << ","
<< setw(3) << (int)v.z << ","
<< setw(3) << (int)v.w << " )";
}
float3 unpackCompactVector(uchar4 packed) {
float exp = (float)(packed.w & 0x1F) - 16.0;
float factor = exp2(exp) / 256.0;
float x = (float)(packed.x) * factor * (packed.w & 0x20 ? -1.0 : 1.0);
float y = (float)(packed.y) * factor * (packed.w & 0x40 ? -1.0 : 1.0);
float z = (float)(packed.z) * factor * (packed.w & 0x80 ? -1.0 : 1.0);
float3 result = { x, y, z };
return result;
}
uchar4 packCompactVector(float3 vec) {
float xAbs = abs(vec.x); uchar xSign = vec.x < 0.0 ? 0x20 : 0;
float yAbs = abs(vec.y); uchar ySign = vec.y < 0.0 ? 0x40 : 0;
float zAbs = abs(vec.z); uchar zSign = vec.z < 0.0 ? 0x80 : 0;
float maxAbs = max(max(xAbs, yAbs), zAbs);
int exp = floor(log2(maxAbs)) + 1;
float factor = exp2(exp);
uchar xMant = floor(xAbs / factor * 256);
uchar yMant = floor(yAbs / factor * 256);
uchar zMant = floor(zAbs / factor * 256);
uchar w = ((exp + 16) & 0x1F) + xSign + ySign + zSign;
uchar4 result = { xMant, yMant, zMant, w };
return result;
}
int main() {
vector<float3> testCases = {
{ 1.0, 3.0, 7.95 },
{ 1.0, 3.0, 7.98 },
{ 1.0,-3.0, 8.00 },
{-1.0, 3.0, 8.05 },
{-1.0,-3.0, 8.10 },
};
for (float3 v : testCases) {
uchar4 packed = packCompactVector(v);
float3 unpacked = unpackCompactVector(packed);
cout << v << " -> " << packed << " -> " << unpacked << endl;
}
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8aW9tYW5pcD4KI2luY2x1ZGUgPHZlY3Rvcj4KI2luY2x1ZGUgPGNtYXRoPgp1c2luZyBuYW1lc3BhY2Ugc3RkOwoKdHlwZWRlZiB1bnNpZ25lZCBjaGFyIHVjaGFyOwpzdHJ1Y3QgZmxvYXQzIHsKICAgIGZsb2F0IHgsIHksIHo7Cn07Cm9zdHJlYW0gJm9wZXJhdG9yPDwob3N0cmVhbSAmb3V0LCBmbG9hdDMgdikgewogICAgcmV0dXJuIG91dCA8PCBmaXhlZCA8PCBzZXRwcmVjaXNpb24oMikgPDwgImZsb2F0MyggIgogICAgICAgIDw8IHNldHcoNSkgPDwgdi54IDw8ICIsIgogICAgICAgIDw8IHNldHcoNSkgPDwgdi55IDw8ICIsIgogICAgICAgIDw8IHNldHcoNSkgPDwgdi56IDw8ICIgKSI7Cn0Kc3RydWN0IHVjaGFyNCB7CiAgICB1Y2hhciB4LCB5LCB6LCB3Owp9Owpvc3RyZWFtICZvcGVyYXRvcjw8KG9zdHJlYW0gJm91dCwgdWNoYXI0IHYpIHsKICAgIHJldHVybiBvdXQgPDwgInVjaGFyNCggIgogICAgICAgIDw8IHNldHcoMykgPDwgKGludCl2LnggPDwgIiwiCiAgICAgICAgPDwgc2V0dygzKSA8PCAoaW50KXYueSA8PCAiLCIKICAgICAgICA8PCBzZXR3KDMpIDw8IChpbnQpdi56IDw8ICIsIgogICAgICAgIDw8IHNldHcoMykgPDwgKGludCl2LncgPDwgIiApIjsKfQoKCmZsb2F0MyB1bnBhY2tDb21wYWN0VmVjdG9yKHVjaGFyNCBwYWNrZWQpIHsKICAgIGZsb2F0IGV4cCA9IChmbG9hdCkocGFja2VkLncgJiAweDFGKSAtIDE2LjA7CiAgICBmbG9hdCBmYWN0b3IgPSBleHAyKGV4cCkgLyAyNTYuMDsKICAgIGZsb2F0IHggPSAoZmxvYXQpKHBhY2tlZC54KSAqIGZhY3RvciAqIChwYWNrZWQudyAmIDB4MjAgPyAtMS4wIDogMS4wKTsKICAgIGZsb2F0IHkgPSAoZmxvYXQpKHBhY2tlZC55KSAqIGZhY3RvciAqIChwYWNrZWQudyAmIDB4NDAgPyAtMS4wIDogMS4wKTsKICAgIGZsb2F0IHogPSAoZmxvYXQpKHBhY2tlZC56KSAqIGZhY3RvciAqIChwYWNrZWQudyAmIDB4ODAgPyAtMS4wIDogMS4wKTsKICAgIGZsb2F0MyByZXN1bHQgPSB7IHgsIHksIHogfTsKICAgIHJldHVybiByZXN1bHQ7Cn0KCnVjaGFyNCBwYWNrQ29tcGFjdFZlY3RvcihmbG9hdDMgdmVjKSB7CiAgICBmbG9hdCB4QWJzID0gYWJzKHZlYy54KTsgICB1Y2hhciB4U2lnbiA9IHZlYy54IDwgMC4wID8gMHgyMCA6IDA7CiAgICBmbG9hdCB5QWJzID0gYWJzKHZlYy55KTsgICB1Y2hhciB5U2lnbiA9IHZlYy55IDwgMC4wID8gMHg0MCA6IDA7CiAgICBmbG9hdCB6QWJzID0gYWJzKHZlYy56KTsgICB1Y2hhciB6U2lnbiA9IHZlYy56IDwgMC4wID8gMHg4MCA6IDA7CiAgICBmbG9hdCBtYXhBYnMgPSBtYXgobWF4KHhBYnMsIHlBYnMpLCB6QWJzKTsKICAgIGludCBleHAgPSBmbG9vcihsb2cyKG1heEFicykpICsgMTsKICAgIGZsb2F0IGZhY3RvciA9IGV4cDIoZXhwKTsKICAgIHVjaGFyIHhNYW50ID0gZmxvb3IoeEFicyAvIGZhY3RvciAqIDI1Nik7CiAgICB1Y2hhciB5TWFudCA9IGZsb29yKHlBYnMgLyBmYWN0b3IgKiAyNTYpOwogICAgdWNoYXIgek1hbnQgPSBmbG9vcih6QWJzIC8gZmFjdG9yICogMjU2KTsKICAgIHVjaGFyIHcgPSAoKGV4cCArIDE2KSAmIDB4MUYpICsgeFNpZ24gKyB5U2lnbiArIHpTaWduOwogICAgdWNoYXI0IHJlc3VsdCA9IHsgeE1hbnQsIHlNYW50LCB6TWFudCwgdyB9OwogICAgcmV0dXJuIHJlc3VsdDsKfQoKCgppbnQgbWFpbigpIHsKICAgIHZlY3RvcjxmbG9hdDM+IHRlc3RDYXNlcyA9IHsKICAgICAgICB7IDEuMCwgMy4wLCA3Ljk1IH0sCiAgICAgICAgeyAxLjAsIDMuMCwgNy45OCB9LAogICAgICAgIHsgMS4wLC0zLjAsIDguMDAgfSwKICAgICAgICB7LTEuMCwgMy4wLCA4LjA1IH0sCiAgICAgICAgey0xLjAsLTMuMCwgOC4xMCB9LAogICAgfTsKICAgIGZvciAoZmxvYXQzIHYgOiB0ZXN0Q2FzZXMpIHsKICAgICAgICB1Y2hhcjQgcGFja2VkID0gcGFja0NvbXBhY3RWZWN0b3Iodik7CiAgICAgICAgZmxvYXQzIHVucGFja2VkID0gdW5wYWNrQ29tcGFjdFZlY3RvcihwYWNrZWQpOwogICAgICAgIGNvdXQgPDwgdiA8PCAiIC0+ICIgPDwgcGFja2VkIDw8ICIgLT4gIiA8PCB1bnBhY2tlZCA8PCBlbmRsOwogICAgfQp9
float3( 1.00, 3.00, 7.95 ) -> uchar4( 32, 96,254, 19 ) -> float3( 1.00, 3.00, 7.94 )
float3( 1.00, 3.00, 7.98 ) -> uchar4( 32, 96,255, 19 ) -> float3( 1.00, 3.00, 7.97 )
float3( 1.00,-3.00, 8.00 ) -> uchar4( 16, 48,128, 84 ) -> float3( 1.00,-3.00, 8.00 )
float3( -1.00, 3.00, 8.05 ) -> uchar4( 16, 48,128, 52 ) -> float3( -1.00, 3.00, 8.00 )
float3( -1.00,-3.00, 8.10 ) -> uchar4( 16, 48,129,116 ) -> float3( -1.00,-3.00, 8.06 )