Loading...
Searching...
No Matches
QuantizedUnitVec.h
Go to the documentation of this file.
// Copyright Contributors to the OpenVDB Project
// SPDX-License-Identifier: MPL-2.0
#ifndef OPENVDB_MATH_QUANTIZED_UNIT_VEC_HAS_BEEN_INCLUDED
#define OPENVDB_MATH_QUANTIZED_UNIT_VEC_HAS_BEEN_INCLUDED
#include <openvdb/Platform.h>
#include <openvdb/version.h>
#include "Vec3.h"
namespace openvdb {
OPENVDB_USE_VERSION_NAMESPACE
namespace OPENVDB_VERSION_NAME {
namespace math {
/// @brief Unit vector occupying only 16 bits
/// @details Stores two quantized components. Based on the
/// "Higher Accuracy Quantized Normals" article from GameDev.Net LLC, 2000
class OPENVDB_API QuantizedUnitVec
{
public:
template<typename T> static uint16_t pack(const Vec3<T>& vec);
static Vec3s unpack(const uint16_t data);
static void flipSignBits(uint16_t&);
private:
QuantizedUnitVec() {}
// bit masks
static const uint16_t MASK_SLOTS = 0x1FFF; // 0001111111111111
static const uint16_t MASK_XSLOT = 0x1F80; // 0001111110000000
static const uint16_t MASK_YSLOT = 0x007F; // 0000000001111111
static const uint16_t MASK_XSIGN = 0x8000; // 1000000000000000
static const uint16_t MASK_YSIGN = 0x4000; // 0100000000000000
static const uint16_t MASK_ZSIGN = 0x2000; // 0010000000000000
// normalization weights, 32 kilobytes.
static float sNormalizationWeights[MASK_SLOTS + 1];
}; // class QuantizedUnitVec
////////////////////////////////////////
template<typename T>
inline uint16_t
QuantizedUnitVec::pack(const Vec3<T>& vec)
{
if (math::isZero(vec)) return 0;
uint16_t data = 0;
T x(vec[0]), y(vec[1]), z(vec[2]);
// The sign of the three components are first stored using
// 3-bits and can then safely be discarded.
if (x < T(0.0)) { data |= MASK_XSIGN; x = -x; }
if (y < T(0.0)) { data |= MASK_YSIGN; y = -y; }
if (z < T(0.0)) { data |= MASK_ZSIGN; z = -z; }
// The z component is discarded and x & y are quantized in
// the 0 to 126 range.
T w = T(126.0) / (x + y + z);
uint16_t xbits = static_cast<uint16_t>((x * w));
uint16_t ybits = static_cast<uint16_t>((y * w));
// The remaining 13 bits in our 16 bit word are dividied into a
// 6-bit x-slot and a 7-bit y-slot. Both the xbits and the ybits
// can still be represented using (2^7 - 1) quantization levels.
// If the xbits requre more than 6-bits, store the complement.
// (xbits + ybits < 127, thus if xbits > 63 => ybits <= 63)
if (xbits > 63) {
xbits = static_cast<uint16_t>(127 - xbits);
ybits = static_cast<uint16_t>(127 - ybits);
}
// Pack components into their respective slots.
data = static_cast<uint16_t>(data | (xbits << 7));
data = static_cast<uint16_t>(data | ybits);
return data;
}
inline Vec3s
QuantizedUnitVec::unpack(const uint16_t data)
{
const float w = sNormalizationWeights[data & MASK_SLOTS];
uint16_t xbits = static_cast<uint16_t>((data & MASK_XSLOT) >> 7);
uint16_t ybits = static_cast<uint16_t>(data & MASK_YSLOT);
// Check if the complement components where stored and revert.
if ((xbits + ybits) > 126) {
xbits = static_cast<uint16_t>(127 - xbits);
ybits = static_cast<uint16_t>(127 - ybits);
}
Vec3s vec(float(xbits) * w, float(ybits) * w, float(126 - xbits - ybits) * w);
if (data & MASK_XSIGN) vec[0] = -vec[0];
if (data & MASK_YSIGN) vec[1] = -vec[1];
if (data & MASK_ZSIGN) vec[2] = -vec[2];
return vec;
}
////////////////////////////////////////
inline void
QuantizedUnitVec::flipSignBits(uint16_t& v)
{
v = static_cast<uint16_t>((v & MASK_SLOTS) | (~v & ~MASK_SLOTS));
}
} // namespace math
} // namespace OPENVDB_VERSION_NAME
} // namespace openvdb
#endif // OPENVDB_MATH_QUANTIZED_UNIT_VEC_HAS_BEEN_INCLUDED
Platform.h
OPENVDB_API
#define OPENVDB_API
Definition Platform.h:274
Vec3.h
openvdb::v11_0::math::QuantizedUnitVec::unpack
static Vec3s unpack(const uint16_t data)
Definition QuantizedUnitVec.h:86
openvdb::v11_0::math::QuantizedUnitVec::flipSignBits
static void flipSignBits(uint16_t &)
Definition QuantizedUnitVec.h:112
openvdb::v11_0::math::QuantizedUnitVec::pack
static uint16_t pack(const Vec3< T > &vec)
Definition QuantizedUnitVec.h:48
openvdb::v11_0::math::Vec3
Definition Vec3.h:24
openvdb::v11_0::math::isZero
bool isZero(const Type &x)
Return true if x is exactly equal to zero.
Definition Math.h:337
openvdb::v11_0::math::Vec3s
Vec3< float > Vec3s
Definition Vec3.h:663
openvdb
Definition Exceptions.h:13
OPENVDB_VERSION_NAME
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition version.h.in:121
OPENVDB_USE_VERSION_NAMESPACE
#define OPENVDB_USE_VERSION_NAMESPACE
Definition version.h.in:212