Improve compress quaternion by only dropping the largest value out of 4
This commit is contained in:
parent
565dfcef96
commit
5330951842
@ -55,35 +55,35 @@ namespace MiniGLM
|
|||||||
Log::info("MiniGLM::unitTesting", "Quaternion compression");
|
Log::info("MiniGLM::unitTesting", "Quaternion compression");
|
||||||
core::quaternion quat(11.0f, 44.0f, 55.0f, 77.0f);
|
core::quaternion quat(11.0f, 44.0f, 55.0f, 77.0f);
|
||||||
quat.normalize();
|
quat.normalize();
|
||||||
packed = compressQuaternion(quat);
|
packed = compressIrrQuaternion(quat);
|
||||||
core::quaternion out_quat = decompressQuaternion(packed);
|
core::quaternion out_quat = decompressQuaternion(packed);
|
||||||
Log::info("MiniGLM::unitTesting", "Result before: x:%f y:%f z:%f w:%f,"
|
Log::info("MiniGLM::unitTesting", "Result before: x:%f y:%f z:%f w:%f,"
|
||||||
" after: x:%f y:%f z:%f w:%f", quat.X, quat.Y, quat.Z, quat.W,
|
" after: x:%f y:%f z:%f w:%f", quat.X, quat.Y, quat.Z, quat.W,
|
||||||
out_quat.X, out_quat.Y, out_quat.Z, out_quat.W);
|
out_quat.X, out_quat.Y, out_quat.Z, out_quat.W);
|
||||||
quat = core::quaternion(-23.0f, -44.0f, -7.0f, 0.0f);
|
quat = core::quaternion(-23.0f, -44.0f, -7.0f, 0.0f);
|
||||||
quat.normalize();
|
quat.normalize();
|
||||||
packed = compressQuaternion(quat);
|
packed = compressIrrQuaternion(quat);
|
||||||
out_quat = decompressQuaternion(packed);
|
out_quat = decompressQuaternion(packed);
|
||||||
Log::info("MiniGLM::unitTesting", "Result before: x:%f y:%f z:%f w:%f,"
|
Log::info("MiniGLM::unitTesting", "Result before: x:%f y:%f z:%f w:%f,"
|
||||||
" after: x:%f y:%f z:%f w:%f", quat.X, quat.Y, quat.Z, quat.W,
|
" after: x:%f y:%f z:%f w:%f", quat.X, quat.Y, quat.Z, quat.W,
|
||||||
out_quat.X, out_quat.Y, out_quat.Z, out_quat.W);
|
out_quat.X, out_quat.Y, out_quat.Z, out_quat.W);
|
||||||
quat = core::quaternion(0.0f, 0.0f, 0.0f, 1.0f);
|
quat = core::quaternion(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
quat.normalize();
|
quat.normalize();
|
||||||
packed = compressQuaternion(quat);
|
packed = compressIrrQuaternion(quat);
|
||||||
out_quat = decompressQuaternion(packed);
|
out_quat = decompressQuaternion(packed);
|
||||||
Log::info("MiniGLM::unitTesting", "Result before: x:%f y:%f z:%f w:%f,"
|
Log::info("MiniGLM::unitTesting", "Result before: x:%f y:%f z:%f w:%f,"
|
||||||
" after: x:%f y:%f z:%f w:%f", quat.X, quat.Y, quat.Z, quat.W,
|
" after: x:%f y:%f z:%f w:%f", quat.X, quat.Y, quat.Z, quat.W,
|
||||||
out_quat.X, out_quat.Y, out_quat.Z, out_quat.W);
|
out_quat.X, out_quat.Y, out_quat.Z, out_quat.W);
|
||||||
quat = core::quaternion(0.0f, 0.0f, 0.0f, -1.0f);
|
quat = core::quaternion(0.0f, 0.0f, 0.0f, -1.0f);
|
||||||
quat.normalize();
|
quat.normalize();
|
||||||
packed = compressQuaternion(quat);
|
packed = compressIrrQuaternion(quat);
|
||||||
out_quat = decompressQuaternion(packed);
|
out_quat = decompressQuaternion(packed);
|
||||||
Log::info("MiniGLM::unitTesting", "Result before: x:%f y:%f z:%f w:%f,"
|
Log::info("MiniGLM::unitTesting", "Result before: x:%f y:%f z:%f w:%f,"
|
||||||
" after: x:%f y:%f z:%f w:%f", quat.X, quat.Y, quat.Z, quat.W,
|
" after: x:%f y:%f z:%f w:%f", quat.X, quat.Y, quat.Z, quat.W,
|
||||||
out_quat.X, out_quat.Y, out_quat.Z, out_quat.W);
|
out_quat.X, out_quat.Y, out_quat.Z, out_quat.W);
|
||||||
quat = core::quaternion(-43.0f, 20.0f, 16.0f, -88.0f);
|
quat = core::quaternion(-43.0f, 20.0f, 16.0f, -88.0f);
|
||||||
quat.normalize();
|
quat.normalize();
|
||||||
packed = compressQuaternion(quat);
|
packed = compressIrrQuaternion(quat);
|
||||||
out_quat = decompressQuaternion(packed);
|
out_quat = decompressQuaternion(packed);
|
||||||
Log::info("MiniGLM::unitTesting", "Result before: x:%f y:%f z:%f w:%f,"
|
Log::info("MiniGLM::unitTesting", "Result before: x:%f y:%f z:%f w:%f,"
|
||||||
" after: x:%f y:%f z:%f w:%f", quat.X, quat.Y, quat.Z, quat.W,
|
" after: x:%f y:%f z:%f w:%f", quat.X, quat.Y, quat.Z, quat.W,
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "LinearMath/btQuaternion.h"
|
#include "LinearMath/btQuaternion.h"
|
||||||
#include "utils/vec3.hpp"
|
#include "utils/vec3.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
@ -231,7 +232,8 @@ namespace MiniGLM
|
|||||||
}
|
}
|
||||||
} // toFloat16
|
} // toFloat16
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
inline uint32_t normalizedSignedFloatsTo1010102(std::array<float, 4> src)
|
inline uint32_t normalizedSignedFloatsTo1010102
|
||||||
|
(const std::array<float, 3>& src, int extra_2_bit = -1)
|
||||||
{
|
{
|
||||||
int part = 0;
|
int part = 0;
|
||||||
uint32_t packed = 0;
|
uint32_t packed = 0;
|
||||||
@ -265,19 +267,17 @@ namespace MiniGLM
|
|||||||
part = (int)((v * 512.0f) - 0.5f);
|
part = (int)((v * 512.0f) - 0.5f);
|
||||||
}
|
}
|
||||||
packed |= ((uint32_t)part & 1023) << 20;
|
packed |= ((uint32_t)part & 1023) << 20;
|
||||||
v = fminf(1.0f, fmaxf(-1.0f, src[3]));
|
if (extra_2_bit >= 0)
|
||||||
if (v > 0.0f)
|
|
||||||
{
|
{
|
||||||
part = (int)((v * 1.0f) + 0.5f);
|
part = extra_2_bit;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
part = (int)((v * 2.0f) - 0.5f);
|
part = (int)(-0.5f);
|
||||||
}
|
}
|
||||||
part = (int)((v * 2.0f) - 0.5f);
|
|
||||||
packed |= ((uint32_t)part & 3) << 30;
|
packed |= ((uint32_t)part & 3) << 30;
|
||||||
return packed;
|
return packed;
|
||||||
} // fourFloatsTo1010102
|
} // normalizedSignedFloatsTo1010102
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
inline std::array<short, 4> vertexType2101010RevTo4HF(uint32_t packed)
|
inline std::array<short, 4> vertexType2101010RevTo4HF(uint32_t packed)
|
||||||
{
|
{
|
||||||
@ -329,7 +329,7 @@ namespace MiniGLM
|
|||||||
inline std::array<float, 4> extractNormalizedSignedFloats(uint32_t packed,
|
inline std::array<float, 4> extractNormalizedSignedFloats(uint32_t packed,
|
||||||
bool calculate_w = false)
|
bool calculate_w = false)
|
||||||
{
|
{
|
||||||
std::array<float, 4> ret;
|
std::array<float, 4> ret = {};
|
||||||
int part = packed & 1023;
|
int part = packed & 1023;
|
||||||
if (part & 512)
|
if (part & 512)
|
||||||
{
|
{
|
||||||
@ -357,29 +357,56 @@ namespace MiniGLM
|
|||||||
{
|
{
|
||||||
ret[2] = (float)part * (1.0f / 511.0f);
|
ret[2] = (float)part * (1.0f / 511.0f);
|
||||||
}
|
}
|
||||||
part = (packed >> 30) & 3;
|
|
||||||
if (part & 2)
|
|
||||||
{
|
|
||||||
ret[3] = (float)(4 - part) * (-1.0f / 2.0f);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ret[3] = (float)part;
|
|
||||||
}
|
|
||||||
if (calculate_w)
|
if (calculate_w)
|
||||||
{
|
{
|
||||||
float w = sqrtf(fmaxf(0.0f, 1.0f -
|
float largest_val = sqrtf(fmaxf(0.0f, 1.0f -
|
||||||
(ret[0] * ret[0]) - (ret[1] * ret[1]) - (ret[2] * ret[2])));
|
(ret[0] * ret[0]) - (ret[1] * ret[1]) - (ret[2] * ret[2])));
|
||||||
ret[3] = ret[3] > 0.0f ? w : -w;
|
part = (packed >> 30) & 3;
|
||||||
|
switch(part)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
auto tmp = ret;
|
||||||
|
ret[0] = largest_val;
|
||||||
|
ret[1] = tmp[0];
|
||||||
|
ret[2] = tmp[1];
|
||||||
|
ret[3] = tmp[2];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
auto tmp = ret;
|
||||||
|
ret[0] = tmp[0];
|
||||||
|
ret[1] = largest_val;
|
||||||
|
ret[2] = tmp[1];
|
||||||
|
ret[3] = tmp[2];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
auto tmp = ret;
|
||||||
|
ret[0] = tmp[0];
|
||||||
|
ret[1] = tmp[1];
|
||||||
|
ret[2] = largest_val;
|
||||||
|
ret[3] = tmp[2];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3:
|
||||||
|
ret[3] = largest_val;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
} // extractNormalizedSignedFloats
|
} // extractNormalizedSignedFloats
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// Please normalize vector and quaternion before compressing
|
// Please normalize vector before compressing
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
inline uint32_t compressVector3(const irr::core::vector3df& vec)
|
inline uint32_t compressVector3(const irr::core::vector3df& vec)
|
||||||
{
|
{
|
||||||
return normalizedSignedFloatsTo1010102({{vec.X, vec.Y, vec.Z, 0.0f}});
|
return normalizedSignedFloatsTo1010102({{vec.X, vec.Y, vec.Z}});
|
||||||
} // compressVector3
|
} // compressVector3
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
inline core::vector3df decompressVector3(uint32_t packed)
|
inline core::vector3df decompressVector3(uint32_t packed)
|
||||||
@ -389,12 +416,67 @@ namespace MiniGLM
|
|||||||
return ret.normalize();
|
return ret.normalize();
|
||||||
} // decompressVector3
|
} // decompressVector3
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
inline uint32_t compressQuaternion(const core::quaternion& q)
|
inline uint32_t compressQuaternion(const btQuaternion& q)
|
||||||
{
|
{
|
||||||
return normalizedSignedFloatsTo1010102({{q.X, q.Y, q.Z,
|
const float length = q.length();
|
||||||
q.W >= 0.0f ? 1.0f : -1.0f}});
|
assert(length != 0.0f);
|
||||||
|
std::array<float, 4> tmp_2 =
|
||||||
|
{{
|
||||||
|
q.x() / length,
|
||||||
|
q.y() / length,
|
||||||
|
q.z() / length,
|
||||||
|
q.w() / length
|
||||||
|
}};
|
||||||
|
std::array<float, 3> tmp_3;
|
||||||
|
auto ret = std::max_element(tmp_2.begin(), tmp_2.end(),
|
||||||
|
[](float a, float b) { return std::abs(a) < std::abs(b); });
|
||||||
|
int extra_2_bit = int(std::distance(tmp_2.begin(), ret));
|
||||||
|
switch (extra_2_bit)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
float neg = tmp_2[0] < 0.0f ? -1.0f : 1.0f;
|
||||||
|
tmp_3[0] = tmp_2[1] * neg;
|
||||||
|
tmp_3[1] = tmp_2[2] * neg;
|
||||||
|
tmp_3[2] = tmp_2[3] * neg;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
float neg = tmp_2[1] < 0.0f ? -1.0f : 1.0f;
|
||||||
|
tmp_3[0] = tmp_2[0] * neg;
|
||||||
|
tmp_3[1] = tmp_2[2] * neg;
|
||||||
|
tmp_3[2] = tmp_2[3] * neg;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
float neg = tmp_2[2] < 0.0f ? -1.0f : 1.0f;
|
||||||
|
tmp_3[0] = tmp_2[0] * neg;
|
||||||
|
tmp_3[1] = tmp_2[1] * neg;
|
||||||
|
tmp_3[2] = tmp_2[3] * neg;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3:
|
||||||
|
{
|
||||||
|
float neg = tmp_2[3] < 0.0f ? -1.0f : 1.0f;
|
||||||
|
tmp_3[0] = tmp_2[0] * neg;
|
||||||
|
tmp_3[1] = tmp_2[1] * neg;
|
||||||
|
tmp_3[2] = tmp_2[2] * neg;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return normalizedSignedFloatsTo1010102(tmp_3, extra_2_bit);
|
||||||
} // compressQuaternion
|
} // compressQuaternion
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
inline uint32_t compressIrrQuaternion(const core::quaternion& q)
|
||||||
|
{
|
||||||
|
return compressQuaternion(btQuaternion(q.X, q.Y, q.Z, q.W));
|
||||||
|
}
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
inline core::quaternion decompressQuaternion(uint32_t packed)
|
inline core::quaternion decompressQuaternion(uint32_t packed)
|
||||||
{
|
{
|
||||||
const std::array<float, 4> out = extractNormalizedSignedFloats(packed,
|
const std::array<float, 4> out = extractNormalizedSignedFloats(packed,
|
||||||
@ -403,12 +485,6 @@ namespace MiniGLM
|
|||||||
return ret.normalize();
|
return ret.normalize();
|
||||||
} // decompressQuaternion
|
} // decompressQuaternion
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
inline uint32_t compressbtQuaternion(const btQuaternion& q)
|
|
||||||
{
|
|
||||||
return normalizedSignedFloatsTo1010102({{q.x(), q.y(), q.z(),
|
|
||||||
q.w() >= 0.0f ? 1.0f : -1.0f}});
|
|
||||||
} // compressbtQuaternion
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
inline btQuaternion decompressbtQuaternion(uint32_t packed)
|
inline btQuaternion decompressbtQuaternion(uint32_t packed)
|
||||||
{
|
{
|
||||||
const std::array<float, 4> out = extractNormalizedSignedFloats(packed,
|
const std::array<float, 4> out = extractNormalizedSignedFloats(packed,
|
||||||
|
Loading…
Reference in New Issue
Block a user