OctreeNeighMap.h 6.96 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/* The copyright in this software is being made available under the BSD
 * Licence, included below.  This software may be subject to other third
 * party and contributor rights, including patent rights, and no such
 * rights are granted under this licence.
 *
 * Copyright (c) 2017-2018, ISO/IEC
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of the ISO/IEC nor the names of its contributors
 *   may be used to endorse or promote products derived from this
 *   software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#pragma once

#include "PCCMath.h"
39
#include "geometry_octree.h"
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include "ringbuf.h"
#include "tables.h"

#include <cassert>
#include <memory>
#include <vector>

namespace pcc {

//============================================================================
// Provides a mapping of (x,y,z) co-ordinate to a bit flag.
//
// Internal representation uses a morton code to access an array of flags.
//
// Updates to the array are made byte-wise, allowing 8 flags (in morton order)
// to be stored in a single operation.

class MortonMap3D {
public:
  void resize(const uint32_t cubeSizeLog2)
  {
    assert(cubeSizeLog2 < 10);
    const uint32_t halfCubeSizeLog2 = cubeSizeLog2 ? cubeSizeLog2 - 1 : 0;
    _cubeSizeLog2 = cubeSizeLog2;
    _cubeSize = 1 << cubeSizeLog2;
65
    _bufferSizeInBytes = 1 << (3 * cubeSizeLog2);
66
    _buffer.reset(new uint8_t[_bufferSizeInBytes]);
67
    _childOccupancy.reset(new uint8_t[_bufferSizeInBytes << 3]);
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
    _updates.reserve(1 << 16);
  }

  int cubeSize() const { return _cubeSize; }
  int cubeSizeLog2() const { return _cubeSizeLog2; }

  void clear()
  {
    memset(_buffer.get(), 0, _bufferSizeInBytes);
    _updates.resize(0);
  }

  void clearUpdates()
  {
    for (const auto byteIndex : _updates) {
      _buffer[byteIndex] = uint8_t(0);
    }
    _updates.resize(0);
  }

  void setByte(
    const int32_t x, const int32_t y, const int32_t z, const uint8_t value)
  {
    assert(
      x >= 0 && y >= 0 && z >= 0 && x < _cubeSize && y < _cubeSize
      && z < _cubeSize);
    if (value) {
      const uint32_t byteIndex = getByteIndex(x, y, z);
      _buffer[byteIndex] = value;
      _updates.push_back(byteIndex);
    }
  }

101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
  uint32_t get(
    const int32_t x,
    const int32_t y,
    const int32_t z,
    const int shiftX,
    const int shiftY,
    const int shiftZ) const
  {
    assert(
      x >= 0 && y >= 0 && z >= 0 && x < _cubeSize && y < _cubeSize
      && z < _cubeSize);
    return (_buffer[getByteIndex(x >> shiftX, y >> shiftY, z >> shiftZ)]
            >> getBitIndex(shiftX ? x : 0, shiftY ? y : 0, shiftZ ? z : 0))
      & 1;
  }

  uint32_t getWithCheck(
    const int32_t x,
    const int32_t y,
    const int32_t z,
    const int shiftX,
    const int shiftY,
    const int shiftZ) const
  {
    if (
      x < 0 || x >= _cubeSize || y < 0 || y >= _cubeSize || z < 0
      || z >= _cubeSize) {
      return false;
    }
    return get(x, y, z, shiftX, shiftY, shiftZ);
  }

133
134
135
136
137
  uint32_t get(const int32_t x, const int32_t y, const int32_t z) const
  {
    assert(
      x >= 0 && y >= 0 && z >= 0 && x < _cubeSize && y < _cubeSize
      && z < _cubeSize);
138
    return _buffer[getByteIndex(x, y, z)] & 1;
139
140
141
142
143
144
145
146
147
148
149
150
151
  }

  uint32_t
  getWithCheck(const int32_t x, const int32_t y, const int32_t z) const
  {
    if (
      x < 0 || x >= _cubeSize || y < 0 || y >= _cubeSize || z < 0
      || z >= _cubeSize) {
      return false;
    }
    return get(x, y, z);
  }

152
153
  void setChildOcc(int32_t x, int32_t y, int32_t z, uint8_t childOccupancy)
  {
154
    _childOccupancy[getByteIndex(x, y, z)] = childOccupancy;
155
156
157
158
  }

  uint8_t getChildOcc(int32_t x, int32_t y, int32_t z) const
  {
159
    uint8_t childOccupancy = _childOccupancy[getByteIndex(x, y, z)];
160
161
162
    return childOccupancy;
  }

163
164
165
166
167
168
169
170
171
private:
  int32_t getBitIndex(const int32_t x, const int32_t y, const int32_t z) const
  {
    return (z & 1) + ((y & 1) << 1) + ((x & 1) << 2);
  }

  uint32_t
  getByteIndex(const int32_t x, const int32_t y, const int32_t z) const
  {
172
    return kMortonCode256X[x] | kMortonCode256Y[y] | kMortonCode256Z[z];
173
174
175
176
177
178
179
180
181
182
  }

  int _cubeSize = 0;
  int _cubeSizeLog2 = 0;

  uint32_t _bufferSizeInBytes = 0;
  std::unique_ptr<uint8_t[]> _buffer;

  // A list of indexes in _buffer that are dirty
  std::vector<uint32_t> _updates;
183
184
185

  // Child occupancy values
  std::unique_ptr<uint8_t[]> _childOccupancy;
186
187
188
189
};

//============================================================================

190
191
192
193
struct GeometryNeighPattern {
  // Mask indicating presence of neigbours of the corresponding tree node
  uint8_t neighPattern;

194
  // mask indicating the number of external child neighbours
195
196
  uint8_t adjacencyGt0;
  uint8_t adjacencyGt1;
197
198
199

  // mask indicating unoccupied external child neighbours
  uint8_t adjacencyUnocc;
200
201
202
};

//============================================================================
203
// determine the occupancy pattern of the six neighbours of the node at
204
205
206
// @position.  If @adjacent_child_contextualization_enabled_flag is true,
// the occupancy state of previously coded neighbours is used to refine
// the neighbour pattern and derive external adjacency counts for each child.
207
GeometryNeighPattern makeGeometryNeighPattern(
208
  bool adjacent_child_contextualization_enabled_flag,
209
  const Vec3<uint32_t>& currentPosition,
210
  const int atlasShift,
211
212
213
214
215
  const MortonMap3D& occupancyAtlas);

// populate (if necessary) the occupancy atlas with occupancy information
// from @fifo.
void updateGeometryOccupancyAtlas(
216
  const Vec3<uint32_t>& position,
217
  const int atlasShift,
218
219
220
  const ringbuf<PCCOctree3Node>& fifo,
  const ringbuf<PCCOctree3Node>::iterator& fifoCurrLvlEnd,
  MortonMap3D* occupancyAtlas,
221
  Vec3<uint32_t>* atlasOrigin);
222

223
void updateGeometryOccupancyAtlasOccChild(
224
  const Vec3<uint32_t>& pos,
225
226
227
  uint8_t childOccupancy,
  MortonMap3D* occupancyAtlas);

228
}  // namespace pcc