Commit a03dc25d authored by David Flynn's avatar David Flynn
Browse files

geom: refactor occupancy (de)coding

This commit replaces some repetitive code with a loop.
parent 2c6d7287
......@@ -121,6 +121,22 @@ struct CtxModelOctreeOccupancy {
o3dgc::Adaptive_Bit_Model b7[127];
CtxModelOctreeOccupancy();
o3dgc::Adaptive_Bit_Model* operator[](int bit_pos)
{
assert(unsigned(bit_pos) < 8);
switch (bit_pos) {
case 0: return b0;
case 1: return b1;
case 2: return b2;
case 3: return b3;
case 4: return b4;
case 5: return b5;
case 6: return b6;
case 7: return b7;
default: return nullptr;
}
}
};
//---------------------------------------------------------------------------
......
......@@ -106,46 +106,22 @@ GeometryOctreeDecoder::decodePositionLeafNumPoints()
int
GeometryOctreeDecoder::decodeOccupancyNeighZ()
{
static const int8_t occupancyCodingOrder[8]{1, 7, 5, 3, 2, 4, 6, 0};
int minOccupied = 2;
int numOccupiedAcc = 0;
int bit;
int occupancy = 0;
bit = _arithmeticDecoder->decode(_ctxOccupancy.b0[numOccupiedAcc]);
numOccupiedAcc += bit;
occupancy |= bit << 1;
bit = _arithmeticDecoder->decode(_ctxOccupancy.b1[numOccupiedAcc]);
numOccupiedAcc += bit;
occupancy |= bit << 7;
bit = _arithmeticDecoder->decode(_ctxOccupancy.b2[numOccupiedAcc]);
numOccupiedAcc += bit;
occupancy |= bit << 5;
bit = _arithmeticDecoder->decode(_ctxOccupancy.b3[numOccupiedAcc]);
numOccupiedAcc += bit;
occupancy |= bit << 3;
bit = _arithmeticDecoder->decode(_ctxOccupancy.b4[numOccupiedAcc]);
numOccupiedAcc += bit;
occupancy |= bit << 2;
bit = _arithmeticDecoder->decode(_ctxOccupancy.b5[numOccupiedAcc]);
numOccupiedAcc += bit;
occupancy |= bit << 4;
// NB: There must be at least two occupied child nodes
// -- avoid coding the occupancyB if it is implied.
bit = 1;
if (numOccupiedAcc >= 1)
bit = _arithmeticDecoder->decode(_ctxOccupancy.b6[numOccupiedAcc]);
numOccupiedAcc += bit;
occupancy |= bit << 6;
bit = 1;
if (numOccupiedAcc >= 2)
bit = _arithmeticDecoder->decode(_ctxOccupancy.b7[numOccupiedAcc]);
occupancy |= bit << 0;
for (int i = 0; i < 8; i++) {
int bit = 1;
// NB: There must be at least two occupied child nodes
// -- avoid coding the occupancy bit if it is implied.
if (numOccupiedAcc >= minOccupied + i - 7) {
int idx = numOccupiedAcc;
bit = _arithmeticDecoder->decode(_ctxOccupancy[i][idx]);
}
numOccupiedAcc += bit;
occupancy |= bit << occupancyCodingOrder[i];
}
return occupancy;
}
......@@ -156,59 +132,44 @@ GeometryOctreeDecoder::decodeOccupancyNeighZ()
int
GeometryOctreeDecoder::decodeOccupancyNeighNZ(int neighPattern10)
{
static const int8_t occupancyCodingOrder[8]{1, 7, 5, 3, 2, 4, 6, 0};
int neighPattern7 = kNeighPattern10to7[neighPattern10];
int neighPattern5 = kNeighPattern7to5[neighPattern7];
int occupancy = 0;
int partialOccupancy = 0;
int idx;
int bit;
idx = neighPattern10;
bit = _arithmeticDecoder->decode(_ctxOccupancy.b0[idx]);
partialOccupancy |= bit << 0;
occupancy |= bit << 1;
idx = (neighPattern10 << 1) + partialOccupancy;
bit = _arithmeticDecoder->decode(_ctxOccupancy.b1[idx]);
partialOccupancy |= bit << 1;
occupancy |= bit << 7;
idx = (neighPattern10 << 2) + partialOccupancy;
bit = _arithmeticDecoder->decode(_ctxOccupancy.b2[idx]);
partialOccupancy |= bit << 2;
occupancy |= bit << 5;
idx = (neighPattern10 << 3) + partialOccupancy;
bit = _arithmeticDecoder->decode(_ctxOccupancy.b3[idx]);
partialOccupancy |= bit << 3;
occupancy |= bit << 3;
// todo(df): merge constants into lut.
idx = ((neighPattern10 - 1) << 4) + partialOccupancy;
idx = kOccMapBit4CtxIdx[idx] - 1 + 5;
bit = _arithmeticDecoder->decode(_ctxOccupancy.b4[idx]);
partialOccupancy |= bit << 4;
occupancy |= bit << 2;
idx = ((neighPattern10 - 1) << 5) + partialOccupancy;
idx = kOccMapBit5CtxIdx[idx] - 1 + 6;
bit = _arithmeticDecoder->decode(_ctxOccupancy.b5[idx]);
partialOccupancy |= bit << 5;
occupancy |= bit << 4;
int neighPattern7 = kNeighPattern10to7[neighPattern10];
idx = ((neighPattern7 - 1) << 6) + partialOccupancy;
idx = kOccMapBit6CtxIdx[idx] - 1 + 7;
bit = _arithmeticDecoder->decode(_ctxOccupancy.b6[idx]);
partialOccupancy += bit << 6;
occupancy |= bit << 6;
// NB: it is impossible for pattern to be 0 (handled in Z case).
// NB: offsets are added since ctxIdxMap is shared between Z and NZ cases.
for (int i = 0; i < 8; i++) {
int idx, bit;
if (i < 4) {
idx = (neighPattern10 << i) + partialOccupancy;
} else if (i == 4) {
idx = ((neighPattern10 - 1) << i) + partialOccupancy;
idx = kOccMapBit4CtxIdx[idx] + i;
} else if (i == 5) {
idx = ((neighPattern10 - 1) << i) + partialOccupancy;
idx = kOccMapBit5CtxIdx[idx] + i;
} else if (i == 6) {
idx = ((neighPattern7 - 1) << i) + partialOccupancy;
idx = kOccMapBit6CtxIdx[idx] + i;
} else if (i == 7) {
idx = ((neighPattern5 - 1) << i) + partialOccupancy;
idx = kOccMapBit7CtxIdx[idx] + i;
bit = 1;
} else {
// work around clang -Wsometimes-uninitialized fault
break;
}
int neighPattern5 = kNeighPattern7to5[neighPattern7];
idx = ((neighPattern5 - 1) << 7) + partialOccupancy;
idx = kOccMapBit7CtxIdx[idx] - 1 + 8;
// NB: if firt 7 bits are 0, then the last is implicitly 1.
bit = 1;
if (partialOccupancy)
bit = _arithmeticDecoder->decode(_ctxOccupancy.b7[idx]);
occupancy |= bit << 0;
// NB: if firt 7 bits are 0, then the last is implicitly 1.
if (i < 7 || partialOccupancy)
bit = _arithmeticDecoder->decode(_ctxOccupancy[i][idx]);
partialOccupancy |= bit << i;
occupancy |= bit << occupancyCodingOrder[i];
}
return occupancy;
}
......
......@@ -106,43 +106,23 @@ GeometryOctreeEncoder::encodePositionLeafNumPoints(int count)
void
GeometryOctreeEncoder::encodeOccupancyNeighZ(int mappedOccupancy)
{
int occupancyB0 = !!(mappedOccupancy & 2);
int occupancyB1 = !!(mappedOccupancy & 128);
int occupancyB2 = !!(mappedOccupancy & 32);
int occupancyB3 = !!(mappedOccupancy & 8);
int occupancyB4 = !!(mappedOccupancy & 4);
int occupancyB5 = !!(mappedOccupancy & 16);
int occupancyB6 = !!(mappedOccupancy & 64);
int occupancyB7 = !!(mappedOccupancy & 1);
static const int8_t occupancyCodingOrder[8]{1, 7, 5, 3, 2, 4, 6, 0};
int minOccupied = 2;
int numOccupiedAcc = 0;
_arithmeticEncoder->encode(occupancyB0, _ctxOccupancy.b0[numOccupiedAcc]);
numOccupiedAcc += occupancyB0;
_arithmeticEncoder->encode(occupancyB1, _ctxOccupancy.b1[numOccupiedAcc]);
numOccupiedAcc += occupancyB1;
_arithmeticEncoder->encode(occupancyB2, _ctxOccupancy.b2[numOccupiedAcc]);
numOccupiedAcc += occupancyB2;
_arithmeticEncoder->encode(occupancyB3, _ctxOccupancy.b3[numOccupiedAcc]);
numOccupiedAcc += occupancyB3;
_arithmeticEncoder->encode(occupancyB4, _ctxOccupancy.b4[numOccupiedAcc]);
numOccupiedAcc += occupancyB4;
_arithmeticEncoder->encode(occupancyB5, _ctxOccupancy.b5[numOccupiedAcc]);
numOccupiedAcc += occupancyB5;
// NB: There must be at least two occupied child nodes
// -- avoid coding the occupancyB if it is implied.
if (numOccupiedAcc >= 1)
_arithmeticEncoder->encode(occupancyB6, _ctxOccupancy.b6[numOccupiedAcc]);
numOccupiedAcc += occupancyB6;
for (int i = 0; i < 8; i++) {
// NB: There must be at least minOccupied child nodes
// -- avoid coding the occupancyBit if it is implied.
if (numOccupiedAcc < minOccupied + i - 7) {
assert(i >= 6);
break;
}
if (numOccupiedAcc >= 2)
_arithmeticEncoder->encode(occupancyB7, _ctxOccupancy.b7[numOccupiedAcc]);
int occupancyBit = (mappedOccupancy >> occupancyCodingOrder[i]) & 1;
int idx = numOccupiedAcc;
_arithmeticEncoder->encode(occupancyBit, _ctxOccupancy[i][idx]);
numOccupiedAcc += occupancyBit;
}
}
//-------------------------------------------------------------------------
......@@ -152,57 +132,43 @@ void
GeometryOctreeEncoder::encodeOccupancyNeighNZ(
int mappedOccupancy, int neighPattern10)
{
int occupancyB0 = !!(mappedOccupancy & 2);
int occupancyB1 = !!(mappedOccupancy & 128);
int occupancyB2 = !!(mappedOccupancy & 32);
int occupancyB3 = !!(mappedOccupancy & 8);
int occupancyB4 = !!(mappedOccupancy & 4);
int occupancyB5 = !!(mappedOccupancy & 16);
int occupancyB6 = !!(mappedOccupancy & 64);
int occupancyB7 = !!(mappedOccupancy & 1);
uint32_t partialOccupancy = 0;
int idx;
idx = neighPattern10;
_arithmeticEncoder->encode(occupancyB0, _ctxOccupancy.b0[idx]);
partialOccupancy |= occupancyB0;
static const int8_t occupancyCodingOrder[8]{1, 7, 5, 3, 2, 4, 6, 0};
idx = (neighPattern10 << 1) + partialOccupancy;
_arithmeticEncoder->encode(occupancyB1, _ctxOccupancy.b1[idx]);
partialOccupancy |= occupancyB1 << 1;
idx = (neighPattern10 << 2) + partialOccupancy;
_arithmeticEncoder->encode(occupancyB2, _ctxOccupancy.b2[idx]);
partialOccupancy |= occupancyB2 << 2;
idx = (neighPattern10 << 3) + partialOccupancy;
_arithmeticEncoder->encode(occupancyB3, _ctxOccupancy.b3[idx]);
partialOccupancy |= occupancyB3 << 3;
// todo(df): merge constants into lut.
idx = ((neighPattern10 - 1) << 4) + partialOccupancy;
idx = kOccMapBit4CtxIdx[idx] - 1 + 5;
_arithmeticEncoder->encode(occupancyB4, _ctxOccupancy.b4[idx]);
partialOccupancy |= occupancyB4 << 4;
int neighPattern7 = kNeighPattern10to7[neighPattern10];
int neighPattern5 = kNeighPattern7to5[neighPattern7];
idx = ((neighPattern10 - 1) << 5) + partialOccupancy;
idx = kOccMapBit5CtxIdx[idx] - 1 + 6;
_arithmeticEncoder->encode(occupancyB5, _ctxOccupancy.b5[idx]);
partialOccupancy |= occupancyB5 << 5;
uint32_t partialOccupancy = 0;
int neighPattern7 = kNeighPattern10to7[neighPattern10];
idx = ((neighPattern7 - 1) << 6) + partialOccupancy;
idx = kOccMapBit6CtxIdx[idx] - 1 + 7;
_arithmeticEncoder->encode(occupancyB6, _ctxOccupancy.b6[idx]);
partialOccupancy |= occupancyB6 << 6;
// NB: it is impossible for pattern to be 0 (handled in Z case).
for (int i = 0; i < 8; i++) {
int occupancyBit = (mappedOccupancy >> occupancyCodingOrder[i]) & 1;
int idx;
if (i < 4)
idx = (neighPattern10 << i) + partialOccupancy;
else if (i == 4) {
idx = ((neighPattern10 - 1) << i) + partialOccupancy;
idx = kOccMapBit4CtxIdx[idx] + i;
} else if (i == 5) {
idx = ((neighPattern10 - 1) << i) + partialOccupancy;
idx = kOccMapBit5CtxIdx[idx] + i;
} else if (i == 6) {
idx = ((neighPattern7 - 1) << i) + partialOccupancy;
idx = kOccMapBit6CtxIdx[idx] + i;
} else if (i == 7) {
// NB: if firt 7 bits are 0, then the last is implicitly 1.
if (!partialOccupancy)
break;
idx = ((neighPattern5 - 1) << i) + partialOccupancy;
idx = kOccMapBit7CtxIdx[idx] + i;
} else {
// work around clang -Wsometimes-uninitialized fault
break;
}
int neighPattern5 = kNeighPattern7to5[neighPattern7];
idx = ((neighPattern5 - 1) << 7) + partialOccupancy;
idx = kOccMapBit7CtxIdx[idx] - 1 + 8;
// NB: if firt 7 bits are 0, then the last is implicitly 1.
if (partialOccupancy)
_arithmeticEncoder->encode(occupancyB7, _ctxOccupancy.b7[idx]);
_arithmeticEncoder->encode(occupancyBit, _ctxOccupancy[i][idx]);
partialOccupancy |= occupancyBit << i;
}
}
//-------------------------------------------------------------------------
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment