BitStream
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 
28 namespace 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