BitStream
Loading...
Searching...
No Matches
smallest_three.h
Go to the documentation of this file.
1#pragma once
2
3/*
4 * Copyright (c) 2020 Stanislav Denisov, Maxim Munning, Davin Carten
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25#include <cstdint>
26#include <cmath>
27
28namespace bitstream
29{
34 {
35 uint32_t m;
36 uint32_t a;
37 uint32_t b;
38 uint32_t c;
39
40 constexpr quantized_quaternion() noexcept :
41 m(0),
42 a(0),
43 b(0),
44 c(0) {}
45
46 constexpr quantized_quaternion(uint32_t w, uint32_t x, uint32_t y, uint32_t z) noexcept :
47 m(w), a(x), b(y), c(z) {}
48 };
49
54 template<typename T, size_t BitsPerElement = 12>
56 {
57 private:
58 static constexpr float SMALLEST_THREE_UNPACK = 0.70710678118654752440084436210485f + 0.0000001f;
59 static constexpr float SMALLEST_THREE_PACK = 1.0f / SMALLEST_THREE_UNPACK;
60
61 public:
62 inline static quantized_quaternion quantize(const T& quaternion) noexcept
63 {
64 constexpr float half_range = static_cast<float>(1 << (BitsPerElement - 1));
65 constexpr float packer = SMALLEST_THREE_PACK * half_range;
66
67 float max_value = -1.0f;
68 bool sign_minus = false;
69 uint32_t m = 0;
70 uint32_t a = 0;
71 uint32_t b = 0;
72 uint32_t c = 0;
73
74 for (uint32_t i = 0; i < 4; i++)
75 {
76 float element = quaternion[i];
77
78 float abs = element > 0.0f ? element : -element;
79
80 if (abs > max_value)
81 {
82 sign_minus = element < 0.0f;
83 m = i;
84 max_value = abs;
85 }
86 }
87
88 float af = 0.0f;
89 float bf = 0.0f;
90 float cf = 0.0f;
91
92 switch (m)
93 {
94 case 0:
95 af = quaternion[1];
96 bf = quaternion[2];
97 cf = quaternion[3];
98 break;
99 case 1:
100 af = quaternion[0];
101 bf = quaternion[2];
102 cf = quaternion[3];
103 break;
104 case 2:
105 af = quaternion[0];
106 bf = quaternion[1];
107 cf = quaternion[3];
108 break;
109 default: // case 3
110 af = quaternion[0];
111 bf = quaternion[1];
112 cf = quaternion[2];
113 break;
114 }
115
116 if (sign_minus)
117 {
118 a = static_cast<uint32_t>((-af * packer) + half_range);
119 b = static_cast<uint32_t>((-bf * packer) + half_range);
120 c = static_cast<uint32_t>((-cf * packer) + half_range);
121 }
122 else
123 {
124 a = static_cast<uint32_t>((af * packer) + half_range);
125 b = static_cast<uint32_t>((bf * packer) + half_range);
126 c = static_cast<uint32_t>((cf * packer) + half_range);
127 }
128
129 return { m, a, b, c };
130 }
131
132 inline static T dequantize(const quantized_quaternion& data) noexcept
133 {
134 constexpr uint32_t half_range = (1 << (BitsPerElement - 1));
135 constexpr float unpacker = SMALLEST_THREE_UNPACK * (1.0f / half_range);
136
137 float a = static_cast<float>(data.a * unpacker - half_range * unpacker);
138 float b = static_cast<float>(data.b * unpacker - half_range * unpacker);
139 float c = static_cast<float>(data.c * unpacker - half_range * unpacker);
140
141 float d = std::sqrt(1.0f - ((a * a) + (b * b) + (c * c)));
142
143 switch (data.m)
144 {
145 case 0:
146 return T{ d, a, b, c };
147 case 1:
148 return T{ a, d, b, c };
149 case 2:
150 return T{ a, b, d, c };
151 default: // case 3
152 return T{ a, b, c, d };
153 }
154 }
155 };
156}
Class for quantizing a user-specified quaternion into fewer bits using the smallest-three algorithm.
Definition smallest_three.h:56
static T dequantize(const quantized_quaternion &data) noexcept
Definition smallest_three.h:132
static quantized_quaternion quantize(const T &quaternion) noexcept
Definition smallest_three.h:62
Definition bounded_range.h:28
A quantized representation of a quaternion.
Definition smallest_three.h:34
uint32_t c
Definition smallest_three.h:38
constexpr quantized_quaternion(uint32_t w, uint32_t x, uint32_t y, uint32_t z) noexcept
Definition smallest_three.h:46
uint32_t m
Definition smallest_three.h:35
constexpr quantized_quaternion() noexcept
Definition smallest_three.h:40
uint32_t b
Definition smallest_three.h:37
uint32_t a
Definition smallest_three.h:36