fork download
  1. #include <iostream>
  2. #include <iomanip>
  3. #include <vector>
  4. #include <cmath>
  5. using namespace std;
  6.  
  7. typedef unsigned char uchar;
  8. struct float3 {
  9. float x, y, z;
  10. };
  11. ostream &operator<<(ostream &out, float3 v) {
  12. return out << fixed << setprecision(2) << "float3( "
  13. << setw(5) << v.x << ","
  14. << setw(5) << v.y << ","
  15. << setw(5) << v.z << " )";
  16. }
  17. struct uchar4 {
  18. uchar x, y, z, w;
  19. };
  20. ostream &operator<<(ostream &out, uchar4 v) {
  21. return out << "uchar4( "
  22. << setw(3) << (int)v.x << ","
  23. << setw(3) << (int)v.y << ","
  24. << setw(3) << (int)v.z << ","
  25. << setw(3) << (int)v.w << " )";
  26. }
  27.  
  28.  
  29. float3 unpackCompactVector(uchar4 packed) {
  30. float exp = (float)(packed.w & 0x1F) - 16.0;
  31. float factor = exp2(exp) / 256.0;
  32. float x = (float)(packed.x) * factor * (packed.w & 0x20 ? -1.0 : 1.0);
  33. float y = (float)(packed.y) * factor * (packed.w & 0x40 ? -1.0 : 1.0);
  34. float z = (float)(packed.z) * factor * (packed.w & 0x80 ? -1.0 : 1.0);
  35. float3 result = { x, y, z };
  36. return result;
  37. }
  38.  
  39. uchar4 packCompactVector(float3 vec) {
  40. float xAbs = abs(vec.x); uchar xSign = vec.x < 0.0 ? 0x20 : 0;
  41. float yAbs = abs(vec.y); uchar ySign = vec.y < 0.0 ? 0x40 : 0;
  42. float zAbs = abs(vec.z); uchar zSign = vec.z < 0.0 ? 0x80 : 0;
  43. float maxAbs = max(max(xAbs, yAbs), zAbs);
  44. int exp = floor(log2(maxAbs)) + 1;
  45. float factor = exp2(exp);
  46. uchar xMant = floor(xAbs / factor * 256);
  47. uchar yMant = floor(yAbs / factor * 256);
  48. uchar zMant = floor(zAbs / factor * 256);
  49. uchar w = ((exp + 16) & 0x1F) + xSign + ySign + zSign;
  50. uchar4 result = { xMant, yMant, zMant, w };
  51. return result;
  52. }
  53.  
  54.  
  55.  
  56. int main() {
  57. vector<float3> testCases = {
  58. { 1.0, 3.0, 7.95 },
  59. { 1.0, 3.0, 7.98 },
  60. { 1.0,-3.0, 8.00 },
  61. {-1.0, 3.0, 8.05 },
  62. {-1.0,-3.0, 8.10 },
  63. };
  64. for (float3 v : testCases) {
  65. uchar4 packed = packCompactVector(v);
  66. float3 unpacked = unpackCompactVector(packed);
  67. cout << v << " -> " << packed << " -> " << unpacked << endl;
  68. }
  69. }
Success #stdin #stdout 0s 3032KB
stdin
Standard input is empty
stdout
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 )