ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
ecvNormalCompressor.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
8 #include "ecvNormalCompressor.h"
9 
10 // cloudViewer
11 #include <CVConst.h>
12 
13 // System
14 #include <assert.h>
15 
17  if (code != NULL_NORM_CODE) {
18  // see 'Decompress' for a better understanding
19  code ^= (static_cast<CompressedNormType>(7) << 2 * QUANTIZE_LEVEL);
20  }
21 }
22 
24  assert(QUANTIZE_LEVEL != 0);
25 
27  unsigned res = 0;
29  if (n[0] >= 0) {
30  x = n[0];
31  } else {
32  res |= 4;
33  x = -n[0];
34  }
35  if (n[1] >= 0) {
36  y = n[1];
37  } else {
38  res |= 2;
39  y = -n[1];
40  }
41  if (n[2] >= 0) {
42  z = n[2];
43  } else {
44  res |= 1;
45  z = -n[2];
46  }
47 
49  PointCoordinateType psnorm = x + y + z;
50  if (psnorm == 0) {
51  return NULL_NORM_CODE;
52  }
53  x /= psnorm;
54  y /= psnorm;
55  z /= psnorm;
56 
58  PointCoordinateType box[6] = {0, 0, 0, 1, 1, 1};
60  bool flip = false;
61  for (unsigned char level = QUANTIZE_LEVEL; level != 0;) {
62  // next level
63  res <<= 2;
64  --level;
65 
66  PointCoordinateType halfBox[3] = {(box[0] + box[3]) / 2,
67  (box[1] + box[4]) / 2,
68  (box[2] + box[5]) / 2};
69 
70  unsigned sector = 3;
71  if (flip) {
72  if (z < halfBox[2])
73  sector = 2;
74  else if (y < halfBox[1])
75  sector = 1;
76  else if (x < halfBox[0])
77  sector = 0;
78  } else {
79  if (z > halfBox[2])
80  sector = 2;
81  else if (y > halfBox[1])
82  sector = 1;
83  else if (x > halfBox[0])
84  sector = 0;
85  }
86  res |= sector;
87 
88  if (level != 0) // skip this at the last level
89  {
90  if (flip) {
91  if (sector != 3) psnorm = box[sector];
92  box[0] = halfBox[0];
93  box[1] = halfBox[1];
94  box[2] = halfBox[2];
95  if (sector != 3) {
96  box[3 + sector] = box[sector];
97  box[sector] = psnorm;
98  } else {
99  flip = false;
100  }
101  } else {
102  if (sector != 3) psnorm = box[3 + sector];
103  box[3] = halfBox[0];
104  box[4] = halfBox[1];
105  box[5] = halfBox[2];
106  if (sector != 3) {
107  box[sector] = box[3 + sector];
108  box[3 + sector] = psnorm;
109  } else {
110  flip = true;
111  }
112  }
113  }
114  }
115 
116  return res;
117 }
118 
119 void ccNormalCompressor::Decompress(unsigned index,
120  PointCoordinateType n[3],
121  unsigned char level /*=QUANTIZE_LEVEL*/) {
122  assert(level != 0);
123 
125  if (index == NULL_NORM_CODE) {
126  n[0] = n[1] = n[2] = 0;
127  return;
128  }
129 
131  PointCoordinateType box[6] = {0, 0, 0, 1, 1, 1};
132  bool flip = false;
133 
134  unsigned char l_shift = level * 2;
135  for (unsigned char k = 0; k < level; ++k) {
136  l_shift -= 2;
137  const unsigned sector = ((index >> l_shift) & 3);
138  if (flip) {
139  const PointCoordinateType tmp = box[sector];
140  box[0] = (box[0] + box[3]) / 2;
141  box[1] = (box[1] + box[4]) / 2;
142  box[2] = (box[2] + box[5]) / 2;
143  if (sector != 3) {
144  box[3 + sector] = box[sector];
145  box[sector] = tmp;
146  } else {
147  flip = false;
148  }
149  } else {
150  const PointCoordinateType tmp = (sector != 3 ? box[3 + sector] : 0);
151 
152  box[3] = (box[0] + box[3]) / 2;
153  box[4] = (box[1] + box[4]) / 2;
154  box[5] = (box[2] + box[5]) / 2;
155 
156  if (sector != 3) {
157  box[sector] = box[3 + sector];
158  box[3 + sector] = tmp;
159  } else {
160  flip = true;
161  }
162  }
163  }
164 
165  // get the sector
166  const unsigned sector = index >> (level + level);
167 
168  n[0] = ((sector & 4) != 0 ? -(box[3] + box[0]) : box[3] + box[0]);
169  n[1] = ((sector & 2) != 0 ? -(box[4] + box[1]) : box[4] + box[1]);
170  n[2] = ((sector & 1) != 0 ? -(box[5] + box[2]) : box[5] + box[2]);
171 }
float PointCoordinateType
Type of the coordinates of a (N-D) point.
Definition: CVTypes.h:16
static const unsigned char QUANTIZE_LEVEL
Compressed normals quantization level (number of directions: 2^(2*N+3))
static const unsigned NULL_NORM_CODE
Null normal code.
static unsigned Compress(const PointCoordinateType N[3])
Compression algorithm.
static void Decompress(unsigned index, PointCoordinateType N[3], unsigned char level=QUANTIZE_LEVEL)
Decompression algorithm.
static void InvertNormal(CompressedNormType &code)
Inverts a (compressed) normal.
unsigned int CompressedNormType
Compressed normals type.
Definition: ecvBasicTypes.h:16
normal_z y
normal_z x
normal_z z