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

pointcloud/m42611: change geometry representation from double to int32_t

Since the codec can only code integer positions, using Vec3<double> for
position data requires repeated inefficient format conversions.  This
commit changes the internal representation to Vec3<int32_t>.
parent cc9fc8e4
......@@ -56,11 +56,14 @@ namespace pcc {
// The type used for internally representing attribute data
typedef uint16_t attr_t;
// The type used for internally representing positions
typedef Vec3<int32_t> point_t;
//============================================================================
class PCCPointSet3 {
public:
typedef Vec3<double> PointType;
typedef point_t PointType;
//=========================================================================
// proxy object for use with iterator, allowing handling of PCCPointSet3's
......@@ -256,12 +259,12 @@ public:
swap(withFrameIndex, other.withFrameIndex);
}
Vec3<double> operator[](const size_t index) const
PointType operator[](const size_t index) const
{
assert(index < positions.size());
return positions[index];
}
Vec3<double>& operator[](const size_t index)
PointType& operator[](const size_t index)
{
assert(index < positions.size());
return positions[index];
......@@ -403,7 +406,7 @@ public:
size_t removeDuplicatePointInQuantizedPoint(int minGeomNodeSizeLog2)
{
for (int i = 0; i < positions.size(); i++) {
Vec3<double> newPoint = positions[i];
PointType newPoint = positions[i];
if (minGeomNodeSizeLog2 > 0) {
uint32_t mask = ((uint32_t)-1) << minGeomNodeSizeLog2;
positions[i].x() = ((int32_t)(positions[i].x()) & mask);
......@@ -454,13 +457,13 @@ public:
}
}
Box3<double> computeBoundingBox() const
Box3<int32_t> computeBoundingBox() const
{
Box3<double> bbox = {std::numeric_limits<double>::max(),
std::numeric_limits<double>::lowest()};
Box3<int32_t> bbox = {std::numeric_limits<int32_t>::max(),
std::numeric_limits<int32_t>::lowest()};
const size_t pointCount = getPointCount();
for (size_t i = 0; i < pointCount; ++i) {
const Vec3<double>& pt = (*this)[i];
const auto& pt = (*this)[i];
for (int k = 0; k < 3; ++k) {
if (pt[k] > bbox.max[k]) {
bbox.max[k] = pt[k];
......@@ -478,14 +481,14 @@ public:
// given by iterating over [begin, end)
template<typename ForwardIt>
Box3<double> computeBoundingBox(ForwardIt begin, ForwardIt end) const
Box3<int32_t> computeBoundingBox(ForwardIt begin, ForwardIt end) const
{
Box3<double> bbox = {std::numeric_limits<double>::max(),
std::numeric_limits<double>::lowest()};
Box3<int32_t> bbox = {std::numeric_limits<int32_t>::max(),
std::numeric_limits<int32_t>::lowest()};
for (auto it = begin; it != end; ++it) {
int i = *it;
const Vec3<double>& pt = (*this)[i];
const auto& pt = (*this)[i];
for (int k = 0; k < 3; ++k) {
if (pt[k] > bbox.max[k]) {
bbox.max[k] = pt[k];
......@@ -501,7 +504,7 @@ public:
//--------------------------------------------------------------------------
private:
std::vector<Vec3<double>> positions;
std::vector<PointType> positions;
std::vector<Vec3<attr_t>> colors;
std::vector<attr_t> reflectances;
std::vector<uint8_t> frameidx;
......
......@@ -503,23 +503,21 @@ FindNeighborWithinDistance(
inline bool
checkDistance(
const Vec3<double>& point,
const Vec3<double>& refpoint,
int32_t nodeSizeLog2)
const point_t& point, const point_t& refpoint, int32_t nodeSizeLog2)
{
uint32_t mask = uint32_t(-1) << nodeSizeLog2;
int32_t minX = (int32_t(refpoint.x()) & mask) * 2 - 1;
int32_t minY = (int32_t(refpoint.y()) & mask) * 2 - 1;
int32_t minZ = (int32_t(refpoint.z()) & mask) * 2 - 1;
int32_t minX = (refpoint.x() & mask) * 2 - 1;
int32_t minY = (refpoint.y() & mask) * 2 - 1;
int32_t minZ = (refpoint.z() & mask) * 2 - 1;
int32_t maxX = minX + (2 << nodeSizeLog2);
int32_t maxY = minY + (2 << nodeSizeLog2);
int32_t maxZ = minZ + (2 << nodeSizeLog2);
int32_t x = int32_t(point.x()) * 2;
int32_t y = int32_t(point.y()) * 2;
int32_t z = int32_t(point.z()) * 2;
int32_t x = point.x() * 2;
int32_t y = point.y() * 2;
int32_t z = point.z() * 2;
return minX < x && maxX > x && minY < y && maxY > y && minZ < z && maxZ > z;
}
......@@ -553,22 +551,19 @@ findNeighborWithinVoxel(
//---------------------------------------------------------------------------
inline Vec3<double>
inline point_t
clacIntermediatePosition(
bool enabled, int32_t nodeSizeLog2, const Vec3<double>& point)
bool enabled, int32_t nodeSizeLog2, const point_t& point)
{
if (!enabled || !nodeSizeLog2)
return point;
uint32_t mask = (uint32_t(-1)) << nodeSizeLog2;
int32_t centerX = (int32_t(point.x()) & mask) + (1 << (nodeSizeLog2 - 1));
int32_t centerY = (int32_t(point.y()) & mask) + (1 << (nodeSizeLog2 - 1));
int32_t centerZ = (int32_t(point.z()) & mask) + (1 << (nodeSizeLog2 - 1));
int32_t centerX = (point.x() & mask) + (1 << (nodeSizeLog2 - 1));
int32_t centerY = (point.y() & mask) + (1 << (nodeSizeLog2 - 1));
int32_t centerZ = (point.z() & mask) + (1 << (nodeSizeLog2 - 1));
Vec3<double> newPoint = point;
newPoint.x() = centerX;
newPoint.y() = centerY;
newPoint.z() = centerZ;
point_t newPoint{centerX, centerY, centerZ};
return newPoint;
}
......@@ -596,7 +591,7 @@ computeNearestNeighbors(
std::vector<PCCPredictor>& predictors,
std::vector<uint32_t>& pointIndexToPredictorIndex,
int32_t& predIndex,
std::vector<Box3<double>>& bBoxes)
std::vector<Box3<int32_t>>& bBoxes)
{
const int32_t retainedSize = retained.size();
const int32_t bucketSize = 8;
......@@ -618,7 +613,7 @@ computeNearestNeighbors(
}
}
std::vector<Box3<double>> bBoxesI;
std::vector<Box3<int32_t>> bBoxesI;
const int32_t indexesSize = endIndex - startIndex;
if (aps.intra_lod_prediction_enabled_flag) {
bBoxesI.resize((indexesSize + bucketSize - 1) / bucketSize);
......@@ -954,7 +949,7 @@ buildPredictorsFast(
numberOfPointsPerLevelOfDetail.push_back(pointCount);
// NB: when partial decoding is enabled, LoDs correspond to octree levels
std::vector<Box3<double>> bBoxes;
std::vector<Box3<int32_t>> bBoxes;
int32_t predIndex = int32_t(pointCount);
for (auto lodIndex = minGeomNodeSizeLog2;
!input.empty() && lodIndex <= aps.num_detail_levels; ++lodIndex) {
......
......@@ -145,7 +145,7 @@ private:
int _frameCounter;
// Map quantized points to the original input points
std::multimap<Vec3<double>, int32_t> quantizedToOrigin;
std::multimap<point_t, int32_t> quantizedToOrigin;
};
//----------------------------------------------------------------------------
......
......@@ -130,7 +130,7 @@ PCCTMC3Encoder3::compress(
// Get the bounding box of current tile and write it into tileInventory
partitions.tileInventory.tiles.resize(tileMaps.size());
for (int t = 0; t < tileMaps.size(); t++) {
Box3<double> bbox = inverseQuantizedCloud.computeBoundingBox(
Box3<int32_t> bbox = inverseQuantizedCloud.computeBoundingBox(
tileMaps[t].begin(), tileMaps[t].end());
auto& tileIvt = partitions.tileInventory.tiles[t];
......@@ -173,7 +173,7 @@ PCCTMC3Encoder3::compress(
// Get the point cloud of current tile and compute their bounding boxes
PCCPointSet3 tileCloud;
getSrcPartition(quantizedInputCloud, tileCloud, tile);
Box3<double> bbox = tileCloud.computeBoundingBox();
Box3<int32_t> bbox = tileCloud.computeBoundingBox();
Vec3<int> tile_quantized_box_xyz0;
for (int k = 0; k < 3; k++) {
tile_quantized_box_xyz0[k] = int(bbox.min[k]);
......@@ -234,7 +234,7 @@ PCCTMC3Encoder3::compress(
std::vector<int32_t> partitionOriginIdxes;
for (int i = 0; i < partition.pointIndexes.size(); i++) {
const auto& point = srcPartition[i];
std::multimap<Vec3<double>, int32_t>::iterator pos;
std::multimap<point_t, int32_t>::iterator pos;
for (pos = quantizedToOrigin.lower_bound(point);
pos != quantizedToOrigin.upper_bound(point); ++pos) {
partitionOriginIdxes.push_back(pos->second);
......@@ -329,15 +329,12 @@ PCCTMC3Encoder3::compressPartition(
pointCloud = inputPointCloud;
// Offset the point cloud to account for (preset) _sliceOrigin.
Vec3<double> sliceOriginD{double(_sliceOrigin[0]), double(_sliceOrigin[1]),
double(_sliceOrigin[2])};
// The new maximum bounds of the offset cloud
Vec3<int> maxBound{0};
const size_t pointCount = pointCloud.getPointCount();
for (size_t i = 0; i < pointCount; ++i) {
const Vec3<double> point = (pointCloud[i] -= sliceOriginD);
const point_t point = (pointCloud[i] -= _sliceOrigin);
for (int k = 0; k < 3; ++k) {
const int k_coord = int(point[k]);
assert(k_coord >= 0);
......@@ -563,15 +560,12 @@ PCCTMC3Encoder3::quantization(const PCCPointSet3& inputPointCloud)
}
// Offset the point cloud to account for (preset) _sliceOrigin.
Vec3<double> sliceOriginD{double(_sliceOrigin[0]), double(_sliceOrigin[1]),
double(_sliceOrigin[2])};
// The new maximum bounds of the offset cloud
Vec3<int> maxBound{0};
const size_t pointCount = pointCloud0.getPointCount();
for (size_t i = 0; i < pointCount; ++i) {
const Vec3<double> point = (pointCloud0[i] -= sliceOriginD);
const point_t point = (pointCloud0[i] -= _sliceOrigin);
for (int k = 0; k < 3; ++k) {
const int k_coord = int(point[k]);
assert(k_coord >= 0);
......
......@@ -883,8 +883,7 @@ GeometryOctreeDecoder::decodeDirectPosition(
*(outputPoints++) = pos =
decodePointPosition(nodeSizeLog2, node.planarMode, node.planePosBits);
// todo(df): currently the output buffer holds two points ...
for (int i = 0; i < std::min(1, numDuplicatePoints); i++)
for (int i = 0; i < numDuplicatePoints; i++)
*(outputPoints++) = pos;
return numPoints + numDuplicatePoints;
......@@ -1207,12 +1206,11 @@ decodeGeometryOctree(
}
// the final bits from the leaf:
Vec3<int32_t> pos{(node0.pos[0] << !(occupancySkip & 4)) + x,
(node0.pos[1] << !(occupancySkip & 2)) + y,
(node0.pos[2] << !(occupancySkip & 1)) + z};
Vec3<int32_t> point{(node0.pos[0] << !(occupancySkip & 4)) + x,
(node0.pos[1] << !(occupancySkip & 2)) + y,
(node0.pos[2] << !(occupancySkip & 1)) + z};
pos = invQuantPosition(node0.qp, posQuantBitMasks, pos);
const Vec3<double> point(pos[0], pos[1], pos[2]);
point = invQuantPosition(node0.qp, posQuantBitMasks, point);
for (int i = 0; i < numPoints; ++i)
pointCloud[processedPointCount++] = point;
......@@ -1246,28 +1244,20 @@ decodeGeometryOctree(
&& planarProb[0] * planarProb[1] * planarProb[2] <= th_idcm;
if (isDirectModeEligible(
idcmEnabled, effectiveNodeMaxDimLog2, node0, child)) {
// todo(df): this should go away when output is integer
Vec3<int32_t> points[2]{};
int numPoints = decoder.decodeDirectPosition(
gps.geom_unique_points_flag, effectiveChildSizeLog2, child, points);
gps.geom_unique_points_flag, effectiveChildSizeLog2, child,
&pointCloud[processedPointCount]);
for (int j = 0; j < std::min(2, numPoints); j++) {
auto& point = points[j];
for (int j = 0; j < numPoints; j++) {
auto& point = pointCloud[processedPointCount++];
for (int k = 0; k < 3; k++) {
int shift = std::max(0, effectiveChildSizeLog2[k]);
point[k] += child.pos[k] << shift;
}
point = invQuantPosition(node0.qp, posQuantBitMasks, point);
pointCloud[processedPointCount++] =
Vec3<double>(point[0], point[1], point[2]);
}
// todo(df): remove this when removing points array
for (int j = 2; j < numPoints; j++)
pointCloud[processedPointCount++] =
Vec3<double>(points[1][0], points[1][1], points[1][2]);
if (numPoints > 0) {
// node fully decoded, do not split: discard child
fifo.pop_back();
......@@ -1340,10 +1330,8 @@ decodeGeometryOctreeScalable(
pointCloud.resize(size + nodes.size());
size_t processedPointCount = size;
for (auto node0 : nodes) {
const Vec3<double> point(node0.pos[0], node0.pos[1], node0.pos[2]);
pointCloud[processedPointCount++] = point;
}
for (auto node0 : nodes)
pointCloud[processedPointCount++] = node0.pos;
}
}
......
......@@ -924,7 +924,7 @@ checkDuplicatePoints(
auto first = PCCPointSet3::iterator(&pointCloud, node.start);
auto last = PCCPointSet3::iterator(&pointCloud, node.end);
std::set<Vec3<double>> uniquePointsSet;
std::set<Vec3<int32_t>> uniquePointsSet;
for (auto i = first; i != last;) {
if (uniquePointsSet.find(**i) == uniquePointsSet.end()) {
uniquePointsSet.insert(**i);
......@@ -982,13 +982,10 @@ GeometryOctreeEncoder::encodeDirectPosition(
numPoints = 1;
}
for (auto idx = node.start; idx < node.start + numPoints; idx++)
for (auto idx = node.start; idx < node.start + numPoints; idx++) {
encodePointPosition(
nodeSizeLog2,
Vec3<int32_t>{int32_t(pointCloud[idx][0]), int32_t(pointCloud[idx][1]),
int32_t(pointCloud[idx][2])}
>> shiftBits,
node.planarMode);
nodeSizeLog2, pointCloud[idx] >> shiftBits, node.planarMode);
}
return true;
}
......
......@@ -589,9 +589,7 @@ decodeTrisoupCommon(
// Move list of points to pointCloud.
pointCloud.resize(refinedVertices.size());
for (int i = 0; i < refinedVertices.size(); i++) {
pointCloud[i] = Vec3<double>{(double)refinedVertices[i][0],
(double)refinedVertices[i][1],
(double)refinedVertices[i][2]};
pointCloud[i] = refinedVertices[i];
}
}
......
......@@ -356,7 +356,7 @@ struct AttributeParameterSet {
int max_num_direct_predictors;
int adaptive_prediction_threshold;
int search_range;
Vec3<double> lod_neigh_bias;
Vec3<int32_t> lod_neigh_bias;
bool intra_lod_prediction_enabled_flag;
bool inter_component_prediction_enabled_flag;
......
......@@ -108,7 +108,7 @@ partitionByUniformGeom(
{
std::vector<Partition> slices;
Box3<double> bbox = cloud.computeBoundingBox();
Box3<int32_t> bbox = cloud.computeBoundingBox();
int maxEdgeAxis = longestAxis(bbox);
int maxEdge = bbox.max[maxEdgeAxis] - bbox.min[maxEdgeAxis];
......@@ -183,7 +183,7 @@ partitionByOctreeDepth(
// noting that there is a correspondence between point position
// and octree node, calculate the position mask and shift required
// to determine the node address for a point.
Box3<double> bbox = cloud.computeBoundingBox();
Box3<int32_t> bbox = cloud.computeBoundingBox();
int maxBb = (int)std::max({bbox.max[0], bbox.max[1], bbox.max[2]});
int cloudSizeLog2 = ceillog2(maxBb + 1);
......@@ -260,7 +260,7 @@ tilePartition(const PartitionParams& params, const PCCPointSet3& cloud)
// for each point determine the tile to which it belongs
// let tile_origin = floor(pos / tile_size)
// append pointIdx to tileMap[tile_origin]
Box3<double> bbox = cloud.computeBoundingBox();
Box3<int32_t> bbox = cloud.computeBoundingBox();
int maxtileNum =
std::ceil(std::max({bbox.max[0], bbox.max[1], bbox.max[2]}) / tileSize);
int tileNumlog2 = ceillog2(maxtileNum);
......
......@@ -63,15 +63,14 @@ quantizePositionsUniq(
const Box3<int> clamp,
const PCCPointSet3& src,
PCCPointSet3* dst,
std::multimap<Vec3<double>, int32_t>& doubleQuantizedToOrigin)
std::multimap<Vec3<int32_t>, int32_t>& mapQuantisedPosToIndexes)
{
// Determine the set of unique quantised points
std::multimap<Vec3<int32_t>, int32_t> intQuantizedToOrigin;
std::set<Vec3<int32_t>> uniquePoints;
int numSrcPoints = src.getPointCount();
for (int i = 0; i < numSrcPoints; ++i) {
const Vec3<double>& point = src[i];
const auto& point = src[i];
Vec3<int32_t> quantizedPoint;
for (int k = 0; k < 3; k++) {
......@@ -90,19 +89,11 @@ quantizePositionsUniq(
dst->addRemoveAttributes(src.hasColors(), src.hasReflectances());
}
dst->resize(uniquePoints.size());
doubleQuantizedToOrigin.clear();
std::swap(intQuantizedToOrigin, mapQuantisedPosToIndexes);
int idx = 0;
for (const auto& point : uniquePoints) {
auto& dstPoint = (*dst)[idx++];
for (int k = 0; k < 3; ++k)
dstPoint[k] = double(point[k]);
std::multimap<Vec3<int32_t>, int32_t>::iterator pos;
for (pos = intQuantizedToOrigin.lower_bound(point);
pos != intQuantizedToOrigin.upper_bound(point); ++pos) {
doubleQuantizedToOrigin.insert(std::make_pair(dstPoint, pos->second));
}
}
for (const auto& point : uniquePoints)
(*dst)[idx++] = point;
}
//============================================================================
......@@ -131,17 +122,12 @@ quantizePositions(
dst->resize(numSrcPoints);
}
Box3<double> clampD{
{double(clamp.min[0]), double(clamp.min[1]), double(clamp.min[2])},
{double(clamp.max[0]), double(clamp.max[1]), double(clamp.max[2])},
};
for (int i = 0; i < numSrcPoints; ++i) {
const Vec3<double> point = src[i];
const auto point = src[i];
auto& dstPoint = (*dst)[i];
for (int k = 0; k < 3; ++k) {
double k_pos = std::round((point[k] - offset[k]) * scaleFactor);
dstPoint[k] = PCCClip(k_pos, clampD.min[k], clampD.max[k]);
dstPoint[k] = PCCClip(int32_t(k_pos), clamp.min[k], clamp.max[k]);
}
}
......
......@@ -77,7 +77,7 @@ void quantizePositionsUniq(
const Box3<int> clamp,
const PCCPointSet3& src,
PCCPointSet3* dst,
std::multimap<Vec3<double>, int32_t>& doubleQuantizedToOrigin);
std::multimap<point_t, int32_t>& doubleQuantizedToOrigin);
//============================================================================
// Quantise the geometry of a point cloud, retaining duplicate points.
......@@ -98,7 +98,7 @@ void quantizePositions(
//============================================================================
// Clamp point co-ordinates in @cloud to @bbox, preserving attributes.
void clampVolume(Box3<double> bbox, PCCPointSet3* cloud);
void clampVolume(Box3<int32_t> bbox, PCCPointSet3* cloud);
//============================================================================
// Determine colour attribute values from a reference/source point cloud.
......@@ -126,7 +126,7 @@ bool recolourColour(
const RecolourParams& params,
const PCCPointSet3& source,
double sourceToTargetScaleFactor,
Vec3<double> targetToSourceOffset,
point_t targetToSourceOffset,
PCCPointSet3& target);
//============================================================================
......@@ -155,7 +155,7 @@ bool recolourReflectance(
const RecolourParams& cfg,
const PCCPointSet3& source,
double sourceToTargetScaleFactor,
Vec3<double> targetToSourceOffset,
point_t targetToSourceOffset,
PCCPointSet3& target);
//============================================================================
......
......@@ -136,7 +136,7 @@ deriveQpSet(
//============================================================================
//for PredLift
Quantizers
QpSet::quantizers(const Vec3<double>& point, int qpLayer) const
QpSet::quantizers(const Vec3<int32_t>& point, int qpLayer) const
{
int qpRegionOffset = 0;
if (regionOffset.valid && regionOffset.region.contains(point)) {
......
......@@ -112,7 +112,7 @@ typedef std::vector<Qps> QpLayers;
struct QpRegionOffset {
bool valid;
int qpOffset;
Box3<double> region;
Box3<int32_t> region;
};
//============================================================================
......@@ -122,7 +122,7 @@ struct QpSet {
QpRegionOffset regionOffset;
// Lookup the quantizer for a point at a particular layer
Quantizers quantizers(const Vec3<double>& point, int qpLayer) const;
Quantizers quantizers(const Vec3<int32_t>& point, int qpLayer) const;
// Return the list of quantisers for all layers
std::vector<Quantizers> quantizerLayers() const;
......
Markdown is supported
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