Commit 0d8f1119 authored by David Flynn's avatar David Flynn
Browse files

trisoup/m46530: replace trisoup hls with trisoup_node_size_log2

This commit provides trisoup_node_size_log2 as a replacement for
the following HLS syntax variables:
 - geom_codec_type (redundant wrt. triangle node size derivation)
 - trisoup_depth (redundant wrt. bounding box)
 - trisoup_triangle_level (semantics simplified)

The following config options have been removed:
 - geometryCodec (redundant wrt. trisoup_node_size_log2)
 - triSoupLevel  (replaced by trisoup_node_size_log2)
 - triSoupDepth  (unnecessary)
 - triSoupIntToOrigScale (redundant wrt. positionQuantizationScale)
parent 9f4349a9
......@@ -9,7 +9,7 @@ categories:
##
# geometry parameters (octree)
# - preserve lossless geometry property
- geometryCodec: 1
- trisoup_node_size_log2: 0
- mergeDuplicatedPoints: 0
- ctxOccupancyReductionFactor: 3
- neighbourAvailBoundaryLog2: 8
......
......@@ -8,7 +8,7 @@ categories:
##
# geometry parameters (octree)
- geometryCodec: 1
- trisoup_node_size_log2: 0
- mergeDuplicatedPoints: 1
- ctxOccupancyReductionFactor: 3
- neighbourAvailBoundaryLog2: 8
......
......@@ -12,7 +12,7 @@ categories:
##
# geometry parameters (octree)
- geometryCodec: 1
- trisoup_node_size_log2: 0
- ctxOccupancyReductionFactor: 3
- neighbourAvailBoundaryLog2: 8
- intra_pred_max_node_size_log2: 6
......
......@@ -12,7 +12,7 @@ categories:
##
# geometry parameters (octree)
- geometryCodec: 1
- trisoup_node_size_log2: 0
- ctxOccupancyReductionFactor: 3
- neighbourAvailBoundaryLog2: 8
- intra_pred_max_node_size_log2: 6
......
......@@ -9,7 +9,7 @@ categories:
##
# geometry parameters (octree)
# - preserve lossless geometry property
- geometryCodec: 1
- trisoup_node_size_log2: 0
- mergeDuplicatedPoints: 0
- ctxOccupancyReductionFactor: 3
- neighbourAvailBoundaryLog2: 8
......
......@@ -8,7 +8,7 @@ categories:
##
# geometry parameters (octree)
- geometryCodec: 1
- trisoup_node_size_log2: 0
- mergeDuplicatedPoints: 1
- ctxOccupancyReductionFactor: 3
- neighbourAvailBoundaryLog2: 8
......
......@@ -9,20 +9,18 @@ categories:
##
# geometry parameters (trisoup)
- geometryCodec: 2
- ctxOccupancyReductionFactor: 3
- neighbourAvailBoundaryLog2: 8
- intra_pred_max_node_size_log2: 6
- inferredDirectCodingMode: 0
- triSoupDepth: ${test-depth}
- triSoupIntToOrigScale: '$eval{ 1 << ( ${src-geometry-precision} - ${test-depth} ) }'
- triSoupLevel:
r01: '$eval{ ${test-depth} - 4 }'
r02: '$eval{ ${test-depth} - 3 }'
r03: '$eval{ ${test-depth} - 3 }'
r04: '$eval{ ${test-depth} - 3 }'
r05: '$eval{ ${test-depth} - 2 }'
r06: ${test-depth}
- positionQuantizationScale: '$eval{ 1 / (1 << ( ${src-geometry-precision} - ${test-depth} )) }'
- trisoup_node_size_log2:
r01: 4
r02: 3
r03: 3
r04: 3
r05: 2
r06: 0
####
# attribute coding (common options -- relies on option ordering)
......
......@@ -9,20 +9,18 @@ categories:
##
# geometry parameters (trisoup)
- geometryCodec: 2
- ctxOccupancyReductionFactor: 3
- neighbourAvailBoundaryLog2: 8
- intra_pred_max_node_size_log2: 6
- inferredDirectCodingMode: 0
- triSoupDepth: ${test-depth}
- triSoupIntToOrigScale: '$eval{ 1 << ( ${src-geometry-precision} - ${test-depth} ) }'
- triSoupLevel:
r01: '$eval{ ${test-depth} - 4 }'
r02: '$eval{ ${test-depth} - 3 }'
r03: '$eval{ ${test-depth} - 3 }'
r04: '$eval{ ${test-depth} - 3 }'
r05: '$eval{ ${test-depth} - 2 }'
r06: ${test-depth}
- positionQuantizationScale: '$eval{ 1 / (1 << ( ${src-geometry-precision} - ${test-depth} )) }'
- trisoup_node_size_log2:
r01: 4
r02: 3
r03: 3
r04: 3
r05: 2
r06: 0
####
# attribute coding (common options -- relies on option ordering)
......
......@@ -111,19 +111,6 @@ attribute coding, as if they had never been configured.
Geometry coding
---------------
### `--geometryCodec=1|2`
Selects the geometry coding method. Both available methods use octree
coding as a base, where points are represented by the occupancy of an
octree. The trisoup method terminates the octree coding early and
continues by encoding triangles which are subsequently voxelised to
produce points.
| Value | Description |
|:-----:| ---------------- |
| 0 | invalid |
| 1 | octree only |
| 2 | octree + trisoup |
### `--bitwiseOccupancyCoding=0|1`
In octree geometry coding, there are both byte-wise and bit-wise tools to
encode the occupancy data. This option selects between the two methods.
......@@ -163,19 +150,13 @@ The total number of contexts used is 256 >> *VALUE*.
NB: the final standard is expected to define this factor as a constant.
### `--triSoupDepth=INT-VALUE`
Configures the maximum log2 node size of the geometry octree used by
trisoup geometry coding.
### `--triSoupLevel=INT-VALUE`
Configures the log2 octree node size used for triangulation (the
reconstructed surface) in trisoup geometry coding.
### `--triSoupIntToOrigScale=REAL-VALUE`
This option is the inverse of `positionQuantizationScale`, and is used to
configure input scaling when trisoup geometry coding is enabled.
### `--trisoup_node_size_log2=INT-VALUE`
Controls the use of trisoup by setting the node size for triangle
based surface reconstruction. The trisoup method terminates the
octree coding at the given node size and continues by encoding
triangles which are subsequently voxelised to produce points.
NB: this option will be removed in a future software version.
A value of 0 disables the use of trisoup.
Attribute coding
......
......@@ -141,14 +141,6 @@ operator>>(std::istream& in, AttributeEncoding& val)
}
} // namespace pcc
namespace pcc {
static std::istream&
operator>>(std::istream& in, GeometryCodecType& val)
{
return readUInt(in, val);
}
} // namespace pcc
namespace pcc {
static std::ostream&
operator<<(std::ostream& out, const AttributeEncoding& val)
......@@ -162,18 +154,6 @@ operator<<(std::ostream& out, const AttributeEncoding& val)
}
} // namespace pcc
namespace pcc {
static std::ostream&
operator<<(std::ostream& out, const GeometryCodecType& val)
{
switch (val) {
case GeometryCodecType::kOctree: out << "1 (Octree)"; break;
case GeometryCodecType::kTriSoup: out << "2 (TriSoup)"; break;
}
return out;
}
} // namespace pcc
//---------------------------------------------------------------------------
// :: Command line / config parsing
......@@ -298,12 +278,6 @@ ParseParameters(int argc, char* argv[], Parameters& params)
(po::Section("Geometry"))
// tools
("geometryCodec",
params.encoder.gps.geom_codec_type, GeometryCodecType::kOctree,
"Controls the method used to encode geometry:\n"
" 1: octree (TMC3)\n"
" 2: trisoup (TMC1)")
("bitwiseOccupancyCoding",
params.encoder.gps.bitwise_occupancy_coding_flag, true,
"Selects between bitwise and bytewise occupancy coding:\n"
......@@ -331,18 +305,10 @@ ParseParameters(int argc, char* argv[], Parameters& params)
params.encoder.gps.geom_occupancy_ctx_reduction_factor, 3,
"Adjusts the number of contexts used in occupancy coding")
// (trisoup) geometry parameters
("triSoupDepth", // log2(maxBB+1), where maxBB+1 is analogous to image width
params.encoder.gps.trisoup_depth, 10,
"Depth of voxels (reconstructed points) in trisoup geometry")
("triSoupLevel",
params.encoder.gps.trisoup_triangle_level, 7,
"Level of triangles (reconstructed surface) in trisoup geometry")
("triSoupIntToOrigScale", // reciprocal of positionQuantizationScale
params.encoder.sps.donotuse_trisoup_int_to_orig_scale, 1.f,
"orig_coords = integer_coords * intToOrigScale")
("trisoup_node_size_log2",
params.encoder.gps.trisoup_node_size_log2, 0,
"Size of nodes for surface triangulation.\n"
" 0: disabled\n")
(po::Section("Attributes"))
......@@ -430,31 +396,9 @@ ParseParameters(int argc, char* argv[], Parameters& params)
return false;
}
if (int(params.encoder.gps.geom_codec_type) == 0) {
err.error() << "Bypassed geometry coding is no longer supported\n";
}
// For trisoup, ensure that positionQuantizationScale is the exact inverse of intToOrigScale.
if (params.encoder.gps.geom_codec_type == GeometryCodecType::kTriSoup) {
params.encoder.sps.seq_source_geom_scale_factor =
1.0f / params.encoder.sps.donotuse_trisoup_int_to_orig_scale;
}
// TriSoup geometry is only enabled when trisoup depth > triangle_level.
// NB: this happens after the scale factor fudge above, since the user
// believes they are configuring trisoup
if (params.encoder.gps.geom_codec_type == GeometryCodecType::kTriSoup) {
const auto& gps = params.encoder.gps;
int trisoupNodeSizeLog2 = gps.trisoup_depth - gps.trisoup_triangle_level;
if (trisoupNodeSizeLog2 <= 0) {
err.warn() << "TriSoup disabled when depth <= triangle level\n";
params.encoder.gps.geom_codec_type = GeometryCodecType::kOctree;
}
}
// Certain coding modes are not available when trisoup is enabled.
// Disable them, and warn if set (they may be set as defaults).
if (params.encoder.gps.geom_codec_type == GeometryCodecType::kTriSoup) {
if (params.encoder.gps.trisoup_node_size_log2 > 0) {
if (!params.encoder.gps.geom_unique_points_flag)
err.warn() << "TriSoup geometry does not preserve duplicated points\n";
......
......@@ -170,11 +170,10 @@ PCCTMC3Decoder3::decodeGeometryBrick(const PayloadBuffer& buf)
arithmeticDecoder.setBuffer(int(buf.size()) - gbhSize, buf.data() + gbhSize);
arithmeticDecoder.start();
if (_gps->geom_codec_type == GeometryCodecType::kOctree) {
if (_gps->trisoup_node_size_log2 == 0) {
_currentPointCloud.resize(gbh.geom_num_points);
decodeGeometryOctree(*_gps, gbh, _currentPointCloud, &arithmeticDecoder);
}
if (_gps->geom_codec_type == GeometryCodecType::kTriSoup) {
} else {
decodeGeometryTrisoup(*_gps, gbh, _currentPointCloud, &arithmeticDecoder);
}
......
......@@ -155,8 +155,8 @@ PCCTMC3Encoder3::compress(
// recolouring
// NB: recolouring is required if points are added / removed
bool recolourNeeded = _gps->geom_unique_points_flag
|| _gps->geom_codec_type == GeometryCodecType::kTriSoup;
bool recolourNeeded =
_gps->geom_unique_points_flag || _gps->trisoup_node_size_log2 > 0;
if (recolourNeeded) {
recolour(
......@@ -227,10 +227,6 @@ PCCTMC3Encoder3::encodeGeometryBrick(PayloadBuffer* buf)
// the current node dimension (log2) encompasing maxBB
int nodeSizeLog2 = ceillog2(maxBB + 1);
// todo(df): consider removal of trisoup_depth
if (_gps->geom_codec_type == GeometryCodecType::kTriSoup)
nodeSizeLog2 = _gps->trisoup_depth;
GeometryBrickHeader gbh;
gbh.geom_geom_parameter_set_id = _gps->gps_geom_parameter_set_id;
gbh.geomBoxOrigin.x() = int(minPositions.x());
......@@ -246,10 +242,9 @@ PCCTMC3Encoder3::encodeGeometryBrick(PayloadBuffer* buf)
EntropyEncoder arithmeticEncoder(maxAcBufLen, nullptr);
arithmeticEncoder.start();
if (_gps->geom_codec_type == GeometryCodecType::kOctree) {
if (_gps->trisoup_node_size_log2 == 0) {
encodeGeometryOctree(*_gps, gbh, pointCloud, &arithmeticEncoder);
}
if (_gps->geom_codec_type == GeometryCodecType::kTriSoup) {
} else {
encodeGeometryTrisoup(*_gps, gbh, pointCloud, &arithmeticEncoder);
}
......@@ -316,20 +311,10 @@ PCCTMC3Encoder3::quantization(const PCCPointSet3& inputPointCloud)
// todo(df): allow overriding of minposition from CLI
// todo(df): remove trisoup hack
minPositions = PCCVector3D{0.0};
if (_gps->geom_codec_type == GeometryCodecType::kOctree)
if (_gps->trisoup_node_size_log2 == 0)
computeMinPositions(inputPointCloud);
PCCBox3<int32_t> clampBox{{0, 0, 0}, {INT32_MAX, INT32_MAX, INT32_MAX}};
if (_gps->geom_codec_type == GeometryCodecType::kTriSoup) {
// NB: Since trisoup forces the octree root node size, and the
// quantiser above rounds half away from zero it is possible that
// an input ranged [0,2**n) becomes [0,2**m], requiring an octree
// root node size of 2**(m+1).
// todo(??): consider truncation towards zero in quantisation.
int32_t maxval = (1 << _gps->trisoup_depth) - 1;
clampBox = PCCBox3<int32_t>{{0, 0, 0}, {maxval, maxval, maxval}};
}
if (_gps->geom_unique_points_flag) {
quantizePositionsUniq(
_sps->seq_source_geom_scale_factor, -minPositions, clampBox,
......
......@@ -354,11 +354,6 @@ decodeGeometryOctree(
// the current node dimension (log2)
int nodeSizeLog2 = gbh.geom_max_node_size_log2;
// termination for trisoup
int terminalNodeSizeLog2 = 0;
if (gps.geom_codec_type == GeometryCodecType::kTriSoup)
terminalNodeSizeLog2 = gps.trisoup_depth - gps.trisoup_triangle_level;
// push the first node
fifo.emplace_back();
PCCOctree3Node& node00 = fifo.back();
......@@ -396,7 +391,7 @@ decodeGeometryOctree(
decoder.beginOctreeLevel();
// allow partial tree encoding using trisoup
if (nodeSizeLog2 == terminalNodeSizeLog2)
if (nodeSizeLog2 == gps.trisoup_node_size_log2)
break;
}
......
......@@ -381,11 +381,6 @@ encodeGeometryOctree(
// the initial node size is the root node's
int nodeSizeLog2 = gbh.geom_max_node_size_log2;
// termination for trisoup
int terminalNodeSizeLog2 = 0;
if (gps.geom_codec_type == GeometryCodecType::kTriSoup)
terminalNodeSizeLog2 = gps.trisoup_depth - gps.trisoup_triangle_level;
// this counter represents fifo.end() - fifoCurrLvlEnd().
// ie, the number of nodes added to the next level of the tree
int numNodesNextLvl = 0;
......@@ -408,7 +403,7 @@ encodeGeometryOctree(
encoder.beginOctreeLevel();
// allow partial tree encoding using trisoup
if (nodeSizeLog2 == terminalNodeSizeLog2)
if (nodeSizeLog2 == gps.trisoup_node_size_log2)
break;
}
......
......@@ -90,7 +90,7 @@ decodeGeometryTrisoup(
pcc::ringbuf<PCCOctree3Node> nodes;
decodeGeometryOctree(gps, gbh, pointCloud, arithmeticDecoder, &nodes);
int blockWidth = 1 << (gps.trisoup_depth - gps.trisoup_triangle_level);
int blockWidth = 1 << gps.trisoup_node_size_log2;
uint32_t symbolCount;
AdaptiveBitModel ctxTemp;
......@@ -118,7 +118,7 @@ decodeGeometryTrisoup(
}
// Compute refinedVertices.
int32_t maxval = (1 << gps.trisoup_depth) - 1;
int32_t maxval = (1 << gbh.geom_max_node_size_log2) - 1;
decodeTrisoupCommon(nodes, segind, vertices, pointCloud, blockWidth, maxval);
}
......
......@@ -54,7 +54,7 @@ encodeGeometryTrisoup(
pcc::ringbuf<PCCOctree3Node> nodes;
encodeGeometryOctree(gps, gbh, pointCloud, arithmeticEncoder, &nodes);
int blockWidth = 1 << (gps.trisoup_depth - gps.trisoup_triangle_level);
int blockWidth = 1 << gps.trisoup_node_size_log2;
uint32_t symbolCount;
......@@ -96,7 +96,7 @@ encodeGeometryTrisoup(
}
// Decode refinedVertices from segind and vertices.
int32_t maxval = (1 << gps.trisoup_depth) - 1;
int32_t maxval = (1 << gbh.geom_max_node_size_log2) - 1;
decodeTrisoupCommon(nodes, segind, vertices, pointCloud, blockWidth, maxval);
}
......
......@@ -56,17 +56,6 @@ enum class PayloadType
//============================================================================
// Describes the geometry coding method.
enum class GeometryCodecType
{
// TMC3 lossless geometry codec using ocrees
kOctree = 1,
// TMC1 octree + triangulation
kTriSoup = 2,
};
//============================================================================
enum class KnownAttributeLabel : uint32_t
{
kColour = 0,
......@@ -165,10 +154,6 @@ struct SequenceParameterSet {
// A value describing the scaling of the source positions prior to encoding.
float seq_source_geom_scale_factor;
// orig_coords = integer_coords * intToOrigScale + intToOrigTranslation
// NB: this parameter has been replaced by seq_source_geom_scale_factor
float donotuse_trisoup_int_to_orig_scale;
// NB: attributeSets.size() = num_attribute_sets
std::vector<AttributeDescription> attributeSets;
};
......@@ -179,9 +164,6 @@ struct GeometryParameterSet {
int gps_geom_parameter_set_id;
int gps_seq_parameter_set_id;
// The geometry coding method
GeometryCodecType geom_codec_type;
// Indicates that the GeometryBrickHeader contains a valid
// geom_box_origin_xyz.
int geom_box_present_flag;
......@@ -214,11 +196,9 @@ struct GeometryParameterSet {
// Maximum node size where intra prediction is enabled
int intra_pred_max_node_size_log2;
// depth of voxels (reconstructed points) in trisoup geometry
int trisoup_depth;
// level of triangles (reconstructed surface) in trisoup geometry
int trisoup_triangle_level;
// size of triangle nodes (reconstructed surface) in trisoup geometry.
// a value of zero disables the feature
int trisoup_node_size_log2;
};
//============================================================================
......
......@@ -187,7 +187,6 @@ write(const GeometryParameterSet& gps)
bs.writeUe(gps.gps_geom_parameter_set_id);
bs.writeUe(gps.gps_seq_parameter_set_id);
bs.writeUe(gps.geom_codec_type);
bs.write(gps.geom_box_present_flag);
bs.write(gps.geom_unique_points_flag);
bs.write(gps.neighbour_context_restriction_flag);
......@@ -196,11 +195,7 @@ write(const GeometryParameterSet& gps)
bs.writeUe(gps.geom_occupancy_ctx_reduction_factor);
bs.writeUe(gps.neighbour_avail_boundary_log2);
bs.writeUe(gps.intra_pred_max_node_size_log2);
if (gps.geom_codec_type == GeometryCodecType::kTriSoup) {
bs.writeUe(gps.trisoup_depth);
bs.writeUe(gps.trisoup_triangle_level);
}
bs.writeUe(gps.trisoup_node_size_log2);
bool gps_extension_flag = false;
bs.write(gps_extension_flag);
......@@ -220,7 +215,6 @@ parseGps(const PayloadBuffer& buf)
bs.readUe(&gps.gps_geom_parameter_set_id);
bs.readUe(&gps.gps_seq_parameter_set_id);
bs.readUe(&gps.geom_codec_type);
bs.read(&gps.geom_box_present_flag);
bs.read(&gps.geom_unique_points_flag);
bs.read(&gps.neighbour_context_restriction_flag);
......@@ -229,11 +223,7 @@ parseGps(const PayloadBuffer& buf)
bs.readUe(&gps.geom_occupancy_ctx_reduction_factor);
bs.readUe(&gps.neighbour_avail_boundary_log2);
bs.readUe(&gps.intra_pred_max_node_size_log2);
if (gps.geom_codec_type == GeometryCodecType::kTriSoup) {
bs.readUe(&gps.trisoup_depth);
bs.readUe(&gps.trisoup_triangle_level);
}
bs.readUe(&gps.trisoup_node_size_log2);
bool gps_extension_flag = bs.read();
if (gps_extension_flag) {
......
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