Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
96c65af91c | ||
|
|
498c66e145 |
10
.vscode/settings.json
vendored
10
.vscode/settings.json
vendored
@@ -1,6 +1,8 @@
|
||||
{
|
||||
"workbench.editor.enablePreview": false,
|
||||
"files.associations": {
|
||||
"*.cs": "cpp",
|
||||
"*.wgsl": "cpp",
|
||||
"*.vs": "cpp",
|
||||
"*.fs": "cpp",
|
||||
"filesystem": "cpp",
|
||||
@@ -79,7 +81,13 @@
|
||||
"condition_variable": "cpp",
|
||||
"regex": "cpp",
|
||||
"stack": "cpp",
|
||||
"variant": "cpp"
|
||||
"variant": "cpp",
|
||||
"bit": "cpp",
|
||||
"charconv": "cpp",
|
||||
"compare": "cpp",
|
||||
"format": "cpp",
|
||||
"optional": "cpp",
|
||||
"stop_token": "cpp"
|
||||
},
|
||||
"files.trimTrailingWhitespace": false,
|
||||
"editor.fontSize": 28,
|
||||
|
||||
@@ -16,527 +16,31 @@ namespace dbgwriter{
|
||||
};
|
||||
|
||||
|
||||
vector<Point> getPoints(Node* node, Attributes attributes) {
|
||||
vector<Point> getPoints(Node* node, Attributes attributes);
|
||||
|
||||
vector<Point> points;
|
||||
std::pair<Point, Point> computeBox(vector<Point> points);
|
||||
|
||||
for (int64_t i = 0; i < node->numPoints; i++) {
|
||||
int64_t offset = i * attributes.bytes;
|
||||
void writePosition2(string dir, Node* node, Attributes attributes);
|
||||
|
||||
int32_t sX, sY, sZ;
|
||||
memcpy(&sX, node->points->data_u8 + offset + 0, 4);
|
||||
memcpy(&sY, node->points->data_u8 + offset + 4, 4);
|
||||
memcpy(&sZ, node->points->data_u8 + offset + 8, 4);
|
||||
|
||||
Point p;
|
||||
p.x = sX;
|
||||
p.y = sY;
|
||||
p.z = sZ;
|
||||
|
||||
points.push_back(p);
|
||||
|
||||
}
|
||||
|
||||
return points;
|
||||
}
|
||||
|
||||
std::pair<Point, Point> computeBox(vector<Point> points) {
|
||||
|
||||
Point min, max;
|
||||
|
||||
min.x = std::numeric_limits<int64_t>::max();
|
||||
min.y = std::numeric_limits<int64_t>::max();
|
||||
min.z = std::numeric_limits<int64_t>::max();
|
||||
max.x = std::numeric_limits<int64_t>::min();
|
||||
max.y = std::numeric_limits<int64_t>::min();
|
||||
max.z = std::numeric_limits<int64_t>::min();
|
||||
|
||||
for (Point& point : points) {
|
||||
min.x = std::min(min.x, point.x);
|
||||
min.y = std::min(min.y, point.y);
|
||||
min.z = std::min(min.z, point.z);
|
||||
|
||||
max.x = std::max(max.x, point.x);
|
||||
max.y = std::max(max.y, point.y);
|
||||
max.z = std::max(max.z, point.z);
|
||||
}
|
||||
|
||||
return { min, max };
|
||||
}
|
||||
|
||||
//struct PNode {
|
||||
|
||||
// vector<PNode*> children;
|
||||
// Point min;
|
||||
// Point max;
|
||||
|
||||
// bool isLeaf = true;
|
||||
// vector<Point> points;
|
||||
// int maxPoints = 20;
|
||||
|
||||
// PNode() {
|
||||
// children.resize(8, nullptr);
|
||||
// }
|
||||
|
||||
// void add(Point point) {
|
||||
|
||||
// if (isLeaf) {
|
||||
// points.push_back(point);
|
||||
|
||||
// if (points.size() > maxPoints) {
|
||||
// split();
|
||||
// }
|
||||
// } else {
|
||||
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
// void split() {
|
||||
|
||||
// }
|
||||
|
||||
//};
|
||||
|
||||
//void writePositionTree(string dir, Node* node, Attributes attributes) {
|
||||
|
||||
// auto points = getPoints(node, attributes);
|
||||
// auto [min, max] = computeBox(points);
|
||||
|
||||
// Point range;
|
||||
// range.x = max.x - min.x;
|
||||
// range.y = max.y - min.y;
|
||||
// range.z = max.z - min.z;
|
||||
|
||||
// for (Point& point : points) {
|
||||
// point.x = point.x - min.x;
|
||||
// point.y = point.y - min.y;
|
||||
// point.z = point.z - min.z;
|
||||
// }
|
||||
|
||||
// // round to nearest power of two
|
||||
// range.x = std::pow(2, std::ceil(std::log2(range.x)));
|
||||
// range.y = std::pow(2, std::ceil(std::log2(range.y)));
|
||||
// range.y = std::pow(2, std::ceil(std::log2(range.z)));
|
||||
|
||||
// int64_t cubeSize = std::max(range.x, std::max(range.y, range.z));
|
||||
|
||||
// PNode* root = new PNode();
|
||||
// root->min = min;
|
||||
// root->max = min;
|
||||
// root->max.x += cubeSize - 1;
|
||||
// root->max.y += cubeSize - 1;
|
||||
// root->max.z += cubeSize - 1;
|
||||
|
||||
// for (Point& point : points) {
|
||||
// root->add(point);
|
||||
// }
|
||||
|
||||
|
||||
//}
|
||||
|
||||
void writePosition2(string dir, Node* node, Attributes attributes) {
|
||||
|
||||
int64_t numPoints = node->numPoints;
|
||||
|
||||
int64_t minX = std::numeric_limits<int64_t>::max();
|
||||
int64_t minY = std::numeric_limits<int64_t>::max();
|
||||
int64_t minZ = std::numeric_limits<int64_t>::max();
|
||||
int64_t maxX = std::numeric_limits<int64_t>::min();
|
||||
int64_t maxY = std::numeric_limits<int64_t>::min();
|
||||
int64_t maxZ = std::numeric_limits<int64_t>::min();
|
||||
|
||||
for (int64_t i = 1; i < numPoints; i++) {
|
||||
int64_t offset = i * attributes.bytes;
|
||||
|
||||
int32_t sX, sY, sZ;
|
||||
memcpy(&sX, node->points->data_u8 + offset + 0, 4);
|
||||
memcpy(&sY, node->points->data_u8 + offset + 4, 4);
|
||||
memcpy(&sZ, node->points->data_u8 + offset + 8, 4);
|
||||
|
||||
minX = std::min(minX, int64_t(sX));
|
||||
minY = std::min(minY, int64_t(sY));
|
||||
minZ = std::min(minZ, int64_t(sZ));
|
||||
|
||||
maxX = std::max(maxX, int64_t(sX));
|
||||
maxY = std::max(maxY, int64_t(sY));
|
||||
maxZ = std::max(maxZ, int64_t(sZ));
|
||||
|
||||
}
|
||||
|
||||
int64_t rangeX = maxX - minX;
|
||||
int64_t rangeY = maxY - minY;
|
||||
int64_t rangeZ = maxZ - minZ;
|
||||
|
||||
int bitsX = std::log2(rangeX);
|
||||
int bitsY = std::log2(rangeY);
|
||||
int bitsZ = std::log2(rangeZ);
|
||||
|
||||
auto computeBytes = [](int bits) {
|
||||
if (bits <= 8) {
|
||||
return 1;
|
||||
} else if (bits <= 16) {
|
||||
return 2;
|
||||
} else if (bits <= 32) {
|
||||
return 4;
|
||||
}
|
||||
};
|
||||
|
||||
int bytesX = computeBytes(bitsX);
|
||||
int bytesY = computeBytes(bitsY);
|
||||
int bytesZ = computeBytes(bitsZ);
|
||||
|
||||
Buffer X(numPoints * bytesX);
|
||||
Buffer Y(numPoints * bytesY);
|
||||
Buffer Z(numPoints * bytesZ);
|
||||
|
||||
for (int64_t i = 1; i < numPoints; i++) {
|
||||
int64_t offset = i * attributes.bytes;
|
||||
|
||||
int32_t sX, sY, sZ;
|
||||
memcpy(&sX, node->points->data_u8 + offset + 0, 4);
|
||||
memcpy(&sY, node->points->data_u8 + offset + 4, 4);
|
||||
memcpy(&sZ, node->points->data_u8 + offset + 8, 4);
|
||||
|
||||
int32_t oX = sX - minX;
|
||||
int32_t oY = sY - minY;
|
||||
int32_t oZ = sZ - minZ;
|
||||
|
||||
if (bytesX == 1) {
|
||||
X.data_u8[i] = oX;
|
||||
} else if (bytesX == 2) {
|
||||
X.data_u16[i] = oX;
|
||||
} else if (bytesX == 4) {
|
||||
X.data_u32[i] = oX;
|
||||
}
|
||||
|
||||
if (bytesY == 1) {
|
||||
Y.data_u8[i] = oY;
|
||||
} else if (bytesY == 2) {
|
||||
Y.data_u16[i] = oY;
|
||||
} else if (bytesY == 4) {
|
||||
Y.data_u32[i] = oY;
|
||||
}
|
||||
|
||||
if (bytesZ == 1) {
|
||||
Z.data_u8[i] = oZ;
|
||||
} else if (bytesZ == 2) {
|
||||
Z.data_u16[i] = oZ;
|
||||
} else if (bytesZ == 4) {
|
||||
Z.data_u32[i] = oZ;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
writeBinaryFile(dir + "/quantized_X.bin", X);
|
||||
writeBinaryFile(dir + "/quantized_Y.bin", Y);
|
||||
writeBinaryFile(dir + "/quantized_Z.bin", Z);
|
||||
|
||||
int a = 10;
|
||||
|
||||
}
|
||||
|
||||
void writePosition(string dir, Node* node, Attributes attributes) {
|
||||
|
||||
int64_t numPoints = node->numPoints;
|
||||
vector<Point> points = getPoints(node, attributes);
|
||||
|
||||
Buffer X(numPoints * 4);
|
||||
Buffer Y(numPoints * 4);
|
||||
Buffer Z(numPoints * 4);
|
||||
Buffer diffX(numPoints * 4);
|
||||
Buffer diffY(numPoints * 4);
|
||||
Buffer diffZ(numPoints * 4);
|
||||
|
||||
stringstream ssDiffX;
|
||||
stringstream ssDiffY;
|
||||
stringstream ssDiffZ;
|
||||
|
||||
stringstream ssPoints;
|
||||
|
||||
for (int64_t i = 0; i < numPoints; i++) {
|
||||
int64_t offset = i * attributes.bytes;
|
||||
|
||||
Point point = points[i];
|
||||
|
||||
X.data_i32[i] = point.x;
|
||||
Y.data_i32[i] = point.y;
|
||||
Z.data_i32[i] = point.z;
|
||||
|
||||
int64_t idiffX, idiffY, idiffZ;
|
||||
|
||||
if (i == 0) {
|
||||
idiffX = point.x;
|
||||
idiffY = point.y;
|
||||
idiffZ = point.z;
|
||||
} else {
|
||||
idiffX = points[i].x - points[i - 1].x;
|
||||
idiffZ = points[i].y - points[i - 1].y;
|
||||
idiffY = points[i].z - points[i - 1].z;
|
||||
}
|
||||
|
||||
diffX.data_i32[i] = idiffX;
|
||||
diffY.data_i32[i] = idiffY;
|
||||
diffZ.data_i32[i] = idiffZ;
|
||||
|
||||
ssDiffX << idiffX << ", ";
|
||||
ssDiffY << idiffY << ", ";
|
||||
ssDiffZ << idiffZ << ", ";
|
||||
|
||||
ssPoints << "[" << point.x << ", " << point.y << ", " << point.z << "], ";
|
||||
|
||||
}
|
||||
|
||||
writeBinaryFile(dir + "/X.bin", X);
|
||||
writeBinaryFile(dir + "/Y.bin", Y);
|
||||
writeBinaryFile(dir + "/Z.bin", Z);
|
||||
|
||||
writeBinaryFile(dir + "/diff_X.bin", diffX);
|
||||
writeBinaryFile(dir + "/diff_Y.bin", diffY);
|
||||
writeBinaryFile(dir + "/diff_Z.bin", diffZ);
|
||||
|
||||
writeFile(dir + "/diffX.txt", ssDiffX.str());
|
||||
writeFile(dir + "/diffY.txt", ssDiffY.str());
|
||||
writeFile(dir + "/diffZ.txt", ssDiffZ.str());
|
||||
|
||||
writeFile(dir + "/points.txt", ssPoints.str());
|
||||
}
|
||||
void writePosition(string dir, Node* node, Attributes attributes);
|
||||
|
||||
// method to seperate bits from a given integer 3 positions apart
|
||||
inline uint64_t splitBy3(unsigned int a) {
|
||||
inline uint64_t splitBy3(unsigned int a);
|
||||
|
||||
uint64_t x = a & 0x1fffff; // we only look at the first 21 bits
|
||||
x = (x | x << 32) & 0x1f00000000ffff; // shift left 32 bits, OR with self, and 00011111000000000000000000000000000000001111111111111111
|
||||
x = (x | x << 16) & 0x1f0000ff0000ff; // shift left 32 bits, OR with self, and 00011111000000000000000011111111000000000000000011111111
|
||||
x = (x | x << 8) & 0x100f00f00f00f00f; // shift left 32 bits, OR with self, and 0001000000001111000000001111000000001111000000001111000000000000
|
||||
x = (x | x << 4) & 0x10c30c30c30c30c3; // shift left 32 bits, OR with self, and 0001000011000011000011000011000011000011000011000011000100000000
|
||||
x = (x | x << 2) & 0x1249249249249249;
|
||||
inline uint64_t mortonEncode_magicbits(unsigned int x, unsigned int y, unsigned int z);
|
||||
|
||||
return x;
|
||||
}
|
||||
void writePositionMortonCode(string dir, Node* node, Attributes attributes);
|
||||
|
||||
inline uint64_t mortonEncode_magicbits(unsigned int x, unsigned int y, unsigned int z) {
|
||||
void writeIntensity(string dir, Node* node, Attributes attributes);
|
||||
|
||||
uint64_t answer = 0;
|
||||
answer |= splitBy3(x) | splitBy3(y) << 1 | splitBy3(z) << 2;
|
||||
|
||||
return answer;
|
||||
}
|
||||
void writeNormal(string dir, Node* node, Attributes attributes, Attribute attribute);
|
||||
|
||||
void writePositionMortonCode(string dir, Node* node, Attributes attributes) {
|
||||
void writeRGB(string dir, Node* node, Attributes attributes, Attribute attribute);
|
||||
|
||||
int64_t numPoints = node->numPoints;
|
||||
void writeDifference(string dir, Node* node, Attributes attributes, Attribute attribute);
|
||||
|
||||
vector<Point> points = getPoints(node, attributes);
|
||||
|
||||
auto [min, max] = computeBox(points);
|
||||
|
||||
int64_t rangeX = max.x - min.x;
|
||||
int64_t rangeY = max.z - min.z;
|
||||
int64_t rangeZ = max.y - min.y;
|
||||
|
||||
|
||||
vector<uint64_t> mortonCodes;
|
||||
|
||||
for (int64_t i = 0; i < numPoints; i++) {
|
||||
int64_t offset = i * attributes.bytes;
|
||||
|
||||
Point point = points[i];
|
||||
|
||||
uint32_t oX = point.x - min.x;
|
||||
uint32_t oY = point.z - min.z;
|
||||
uint32_t oZ = point.y - min.y;
|
||||
|
||||
uint64_t mortonCode = mortonEncode_magicbits(oX, oY, oZ);
|
||||
|
||||
mortonCodes.push_back(mortonCode);
|
||||
|
||||
}
|
||||
|
||||
sort(mortonCodes.begin(), mortonCodes.end(), [](uint64_t& a, uint64_t& b) {
|
||||
return a < b;
|
||||
});
|
||||
|
||||
Buffer data(8 * numPoints);
|
||||
Buffer dataDiff(8 * numPoints);
|
||||
|
||||
stringstream ss;
|
||||
stringstream ssDiff;
|
||||
ss << "[";
|
||||
ssDiff << "[";
|
||||
|
||||
for (int64_t i = 0; i < numPoints; i++) {
|
||||
uint64_t mortonCode = mortonCodes[i];
|
||||
data.data_u64[i] = mortonCode;
|
||||
|
||||
uint64_t diff;
|
||||
|
||||
if (i == 0) {
|
||||
diff = mortonCode;
|
||||
} else {
|
||||
diff = mortonCodes[i] - mortonCodes[i - 1];
|
||||
}
|
||||
dataDiff.data_u64[i] = diff;
|
||||
|
||||
ss << mortonCode << ", ";
|
||||
ssDiff << diff << ", ";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
ss << "]";
|
||||
ssDiff << "]";
|
||||
|
||||
writeFile(dir + "/mortoncode.txt", ss.str());
|
||||
writeFile(dir + "/mortoncode_diff.txt", ssDiff.str());
|
||||
|
||||
|
||||
writeBinaryFile(dir + "/mortoncode.bin", data);
|
||||
writeBinaryFile(dir + "/mortoncode_diff.bin", dataDiff);
|
||||
|
||||
|
||||
int a = 10;
|
||||
}
|
||||
|
||||
void writeIntensity(string dir, Node* node, Attributes attributes) {
|
||||
|
||||
int64_t numPoints = node->numPoints;
|
||||
int64_t attributeOffset = attributes.getOffset("intensity");
|
||||
|
||||
//int16_t intensity_origin_u16;
|
||||
//memcpy(&intensity_origin_u16, node->points->data_u8 + attributeOffset, 2);
|
||||
//int64_t intensity_origin = intensity_origin_u16;
|
||||
|
||||
Buffer I(numPoints * 2);
|
||||
|
||||
memcpy(I.data, node->points->data_u8 + attributeOffset, 2);
|
||||
|
||||
int64_t intensity_previous = I.data_u16[0];
|
||||
int64_t intensity_current;
|
||||
|
||||
for (int64_t i = 1; i < numPoints; i++) {
|
||||
int64_t offset = i * attributes.bytes;
|
||||
|
||||
int16_t intensity_1_u16;
|
||||
memcpy(&intensity_1_u16, node->points->data_u8 + offset + attributeOffset, 2);
|
||||
|
||||
intensity_current = intensity_1_u16;
|
||||
|
||||
int64_t diff = (intensity_current - intensity_previous);
|
||||
int64_t sign = diff < 0 ? 0b1000'0000'0000'0000 : 0b0;
|
||||
|
||||
uint16_t diff16 = sign | std::abs(diff);
|
||||
//uint16_t diff16 = ((std::abs(diff) << 1) | sign);
|
||||
|
||||
I.data_u16[i] = diff16;
|
||||
|
||||
intensity_previous = intensity_current;
|
||||
}
|
||||
|
||||
writeBinaryFile(dir + "/diff_intensity.bin", I);
|
||||
}
|
||||
|
||||
|
||||
void writeNormal(string dir, Node* node, Attributes attributes, Attribute attribute) {
|
||||
int attributeOffset = attributes.getOffset(attribute.name);
|
||||
int64_t numBytes = attribute.size * node->numPoints;
|
||||
Buffer buffer(numBytes);
|
||||
|
||||
uint8_t* source = node->points->data_u8;
|
||||
uint8_t* target = buffer.data_u8;
|
||||
|
||||
for (int64_t i = 0; i < node->numPoints; i++) {
|
||||
|
||||
int64_t sourceOffset = i * attributes.bytes + attributeOffset;
|
||||
int64_t targetOffset = i * attribute.size;
|
||||
|
||||
memcpy(target + targetOffset, source + sourceOffset, attribute.size);
|
||||
}
|
||||
|
||||
string filepath = dir + "/" + attribute.name + ".bin";
|
||||
vector<uint8_t> data(target, target + numBytes);
|
||||
writeBinaryFile(filepath, data);
|
||||
}
|
||||
|
||||
void writeRGB(string dir, Node* node, Attributes attributes, Attribute attribute) {
|
||||
int attributeOffset = attributes.getOffset(attribute.name);
|
||||
int64_t numPoints = node->numPoints;
|
||||
//int64_t numBytes = 4 * numPoints;
|
||||
//Buffer buffer(numBytes);
|
||||
|
||||
uint8_t* source = node->points->data_u8;
|
||||
//uint8_t* target = buffer.data_u8;
|
||||
|
||||
int64_t dimx = ceil(sqrt(numPoints));
|
||||
int64_t dimy = dimx;
|
||||
|
||||
string filepath = dir + "/" + attribute.name + ".ppm";
|
||||
ofstream ofs(filepath, ios::out | ios::binary);
|
||||
ofs << "P6" << endl << dimx << ' ' << dimy << endl << "255" << endl;
|
||||
|
||||
|
||||
for (int64_t i = 0; i < numPoints; i++) {
|
||||
|
||||
int64_t sourceOffset = i * attributes.bytes + attributeOffset;
|
||||
|
||||
uint16_t rgb[3];
|
||||
memcpy(rgb, source + sourceOffset, 6);
|
||||
|
||||
uint8_t r = rgb[0] > 255 ? rgb[0] / 256 : rgb[0];
|
||||
uint8_t g = rgb[1] > 255 ? rgb[1] / 256 : rgb[1];
|
||||
uint8_t b = rgb[2] > 255 ? rgb[2] / 256 : rgb[2];
|
||||
|
||||
ofs << r << g << b;
|
||||
|
||||
//ofs << (char)(i % 256) << (char)(j % 256) << (char)((i * j) % 256);
|
||||
|
||||
//memcpy(target + targetOffset, source + sourceOffset, attribute.size);
|
||||
}
|
||||
ofs.close();
|
||||
|
||||
}
|
||||
|
||||
void writeDifference(string dir, Node* node, Attributes attributes, Attribute attribute) {
|
||||
|
||||
if (attribute.type == AttributeType::UINT16) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void writeNode(Node* node, Attributes attributes){
|
||||
|
||||
string dir = "D:/temp/compression/" + node->name;
|
||||
|
||||
fs::create_directories(dir);
|
||||
|
||||
int64_t attributeOffset = 0;
|
||||
for (Attribute& attribute : attributes.list) {
|
||||
|
||||
if (attribute.name == "position") {
|
||||
//writeNormal(dir, node, attributes, attribute);
|
||||
writePosition(dir, node, attributes);
|
||||
writePosition2(dir, node, attributes);
|
||||
writePositionMortonCode(dir, node, attributes);
|
||||
} else if(attribute.name == "intensity"){
|
||||
writeIntensity(dir, node, attributes);
|
||||
} else if (attribute.name == "rgb") {
|
||||
writeRGB(dir, node, attributes, attribute);
|
||||
}
|
||||
|
||||
writeNormal(dir, node, attributes, attribute);
|
||||
//writeDifference(dir, node, attributes, attribute);
|
||||
|
||||
attributeOffset += attribute.size;
|
||||
}
|
||||
|
||||
|
||||
writeBinaryFile(dir + "/all.bin", *node->points);
|
||||
|
||||
|
||||
}
|
||||
void writeNode(Node* node, Attributes attributes);
|
||||
|
||||
|
||||
}
|
||||
|
||||
20
Converter/include/chunker_sparse.h
Normal file
20
Converter/include/chunker_sparse.h
Normal file
@@ -0,0 +1,20 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Vector3.h"
|
||||
#include "Attributes.h"
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
class Source;
|
||||
class State;
|
||||
|
||||
namespace chunker_sparse {
|
||||
|
||||
void run(vector<Source> sources, string targetDir, Vector3 min, Vector3 max, State& state, Attributes outputAttributes);
|
||||
|
||||
}
|
||||
@@ -83,23 +83,67 @@ struct BoundingBox {
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: LICENSE
|
||||
inline uint64_t everyThirdBit(uint64_t mask){
|
||||
// see https://stackoverflow.com/questions/45694690/how-i-can-remove-all-odds-bits-in-c
|
||||
|
||||
// input alignment of desired bits:
|
||||
// a..b..c..d..e..f..g..h..i..j..k..l..m..n..o..p..q..r..s..t..u..v
|
||||
|
||||
uint64_t bits = mask;
|
||||
|
||||
// a..b..c..d..e..f..g..h..i..j..k..l..m..n..o..p..q..r..s..t..u..v a..b..c..d..e..f..g..h..i..j..k..l..m..n..o..p..q..r..s..t..u..v
|
||||
// a.....c.....e.....g.....i.....k.....m.....o.....q.....s.....u... ...b.....d.....f.....h.....j.....l.....n.....p.....r.....t.....v
|
||||
// ..a.....c.....e.....g.....i.....k.....m.....o.....q.....s.....u. ...b.....d.....f.....h.....j.....l.....n.....p.....r.....t.....v
|
||||
bits = ((bits & 0b1000001000001000001000001000001000001000001000001000001000001000) >> 2) | ((bits & 0b0001000001000001000001000001000001000001000001000001000001000001) >> 0);
|
||||
// ..ab....cd....ef....gh....ij....kl....mn....op....qr....st....uv ..ab....cd....ef....gh....ij....kl....mn....op....qr....st....uv
|
||||
// ........cd..........gh..........kl..........op..........st...... ..ab..........ef..........ij..........mn..........qr..........uv
|
||||
// ............cd..........gh..........kl..........op..........st.. ..ab..........ef..........ij..........mn..........qr..........uv
|
||||
bits = ((bits & 0b0000000011000000000011000000000011000000000011000000000011000000) >> 4) | ((bits & 0b0011000000000011000000000011000000000011000000000011000000000011) >> 0);
|
||||
|
||||
// ..ab........cdef........ghij........klmn........opqr........stuv ..ab........cdef........ghij........klmn........opqr........stuv
|
||||
// ..ab....................ghij....................opqr............ ............cdef....................klmn....................stuv
|
||||
// ..........ab....................ghij....................opqr.... ............cdef....................klmn....................stuv
|
||||
bits = ((bits & 0b1111000000000000000000001111000000000000000000001111000000000000) >> 8) | ((bits & 0b0000000000001111000000000000000000001111000000000000000000001111) >> 0);
|
||||
|
||||
// ..........abcdef................ghijklmn................opqrstuv ..........abcdef................ghijklmn................opqrstuv
|
||||
// ................................ghijklmn........................ ..........abcdef........................................opqrstuv
|
||||
// ................................................ghijklmn........ ..........abcdef........................................opqrstuv
|
||||
bits = ((bits & 0b0000000000000000000000000000000011111111000000000000000000000000) >> 16) | ((bits & 0b0000000011111111000000000000000000000000000000000000000011111111) >> 0);
|
||||
|
||||
// ..........abcdef................................ghijklmnopqrstuv ..........abcdef................................ghijklmnopqrstuv
|
||||
// ..........abcdef................................................ ................................................ghijklmnopqrstuv
|
||||
// ..........................................abcdef................ ................................................ghijklmnopqrstuv
|
||||
bits = ((bits & 0b1111111111111111000000000000000000000000000000000000000000000000) >> 32) | ((bits & 0b0000000000000000000000000000000000000000000000001111111111111111) >> 0);
|
||||
|
||||
// sucessfully realigned!
|
||||
// bits = ..........................................abcdefghijklmnopqrstuv
|
||||
|
||||
return bits;
|
||||
}
|
||||
|
||||
// see https://www.forceflow.be/2013/10/07/morton-encodingdecoding-through-bit-interleaving-implementations/
|
||||
// method to seperate bits from a given integer 3 positions apart
|
||||
// TODO: LICENSE
|
||||
inline uint64_t splitBy3(unsigned int a) {
|
||||
|
||||
uint64_t x = a & 0x1fffff; // we only look at the first 21 bits
|
||||
x = (x | x << 32) & 0x1f00000000ffff; // shift left 32 bits, OR with self, and 00011111000000000000000000000000000000001111111111111111
|
||||
x = (x | x << 16) & 0x1f0000ff0000ff; // shift left 32 bits, OR with self, and 00011111000000000000000011111111000000000000000011111111
|
||||
x = (x | x << 8) & 0x100f00f00f00f00f; // shift left 32 bits, OR with self, and 0001000000001111000000001111000000001111000000001111000000000000
|
||||
x = (x | x << 4) & 0x10c30c30c30c30c3; // shift left 32 bits, OR with self, and 0001000011000011000011000011000011000011000011000011000100000000
|
||||
x = (x | x << 2) & 0x1249249249249249;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
// see https://www.forceflow.be/2013/10/07/morton-encodingdecoding-through-bit-interleaving-implementations/
|
||||
// TODO: LICENSE
|
||||
inline uint64_t mortonEncode_magicbits(unsigned int x, unsigned int y, unsigned int z) {
|
||||
|
||||
uint64_t answer = 0;
|
||||
answer |= splitBy3(x) | splitBy3(y) << 1 | splitBy3(z) << 2;
|
||||
|
||||
return answer;
|
||||
}
|
||||
|
||||
|
||||
208
Converter/include/indexer_voxels.h
Normal file
208
Converter/include/indexer_voxels.h
Normal file
@@ -0,0 +1,208 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
#include <algorithm>
|
||||
#include <deque>
|
||||
#include <unordered_map>
|
||||
#include <atomic>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <fstream>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
|
||||
#include "json/json.hpp"
|
||||
|
||||
#include "Attributes.h"
|
||||
#include "converter_utils.h"
|
||||
#include "Vector3.h"
|
||||
#include "unsuck/unsuck.hpp"
|
||||
#include "unsuck/TaskPool.hpp"
|
||||
#include "structures.h"
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
using std::atomic_int64_t;
|
||||
using std::atomic_int64_t;
|
||||
using std::deque;
|
||||
using std::string;
|
||||
using std::unordered_map;
|
||||
using std::function;
|
||||
using std::shared_ptr;
|
||||
using std::make_shared;
|
||||
using std::fstream;
|
||||
using std::mutex;
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace indexer_voxels{
|
||||
|
||||
//constexpr int numSampleThreads = 10;
|
||||
//constexpr int numFlushThreads = 36;
|
||||
constexpr int maxPointsPerChunk = 50'000;
|
||||
|
||||
inline int numSampleThreads() {
|
||||
return getCpuData().numProcessors;
|
||||
// return 1;
|
||||
}
|
||||
|
||||
struct Hierarchy {
|
||||
int64_t stepSize = 0;
|
||||
vector<uint8_t> buffer;
|
||||
int64_t firstChunkSize = 0;
|
||||
};
|
||||
|
||||
struct Chunk {
|
||||
Vector3 min;
|
||||
Vector3 max;
|
||||
|
||||
string file;
|
||||
string id;
|
||||
};
|
||||
|
||||
struct Chunks {
|
||||
vector<shared_ptr<Chunk>> list;
|
||||
Vector3 min;
|
||||
Vector3 max;
|
||||
Attributes attributes;
|
||||
|
||||
Chunks(vector<shared_ptr<Chunk>> list, Vector3 min, Vector3 max) {
|
||||
this->list = list;
|
||||
this->min = min;
|
||||
this->max = max;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
shared_ptr<Chunks> getChunks(string pathIn);
|
||||
|
||||
|
||||
|
||||
struct Indexer;
|
||||
|
||||
struct Writer {
|
||||
|
||||
Indexer* indexer = nullptr;
|
||||
int64_t capacity = 16 * 1024 * 1024;
|
||||
|
||||
// copy node data here first
|
||||
shared_ptr<Buffer> activeBuffer = nullptr;
|
||||
|
||||
// backlog of buffers that reached capacity and are ready to be written to disk
|
||||
deque<shared_ptr<Buffer>> backlog;
|
||||
|
||||
bool closeRequested = false;
|
||||
bool closed = false;
|
||||
std::condition_variable cvClose;
|
||||
|
||||
fstream fsOctree;
|
||||
|
||||
//thread tWrite;
|
||||
|
||||
mutex mtx;
|
||||
|
||||
Writer(Indexer* indexer);
|
||||
|
||||
void writeAndUnload(Node* node, Attributes attributes);
|
||||
|
||||
void launchWriterThread();
|
||||
|
||||
void closeAndWait();
|
||||
|
||||
int64_t backlogSizeMB();
|
||||
|
||||
};
|
||||
|
||||
struct HierarchyChunk {
|
||||
string name = "";
|
||||
vector<Node*> nodes;
|
||||
};
|
||||
|
||||
struct FlushedChunkRoot {
|
||||
shared_ptr<Node> node;
|
||||
int64_t offset = 0;
|
||||
int64_t sizePoints = 0;
|
||||
int64_t sizeVoxels = 0;
|
||||
};
|
||||
|
||||
struct Indexer{
|
||||
|
||||
string targetDir = "";
|
||||
|
||||
Options options;
|
||||
|
||||
Attributes attributes;
|
||||
shared_ptr<Node> root;
|
||||
|
||||
shared_ptr<Writer> writer;
|
||||
|
||||
vector<shared_ptr<Node>> detachedParts;
|
||||
|
||||
atomic_int64_t byteOffset = 0;
|
||||
|
||||
double scale = 0.001;
|
||||
double spacing = 1.0;
|
||||
|
||||
atomic_int64_t dbg = 0;
|
||||
|
||||
mutex mtx_depth;
|
||||
int64_t octreeDepth = 0;
|
||||
|
||||
//shared_ptr<TaskPool<FlushTask>> flushPool;
|
||||
atomic_int64_t bytesInMemory = 0;
|
||||
atomic_int64_t bytesToWrite = 0;
|
||||
atomic_int64_t bytesWritten = 0;
|
||||
|
||||
mutex mtx_chunkRoot;
|
||||
fstream fChunkRoots;
|
||||
vector<FlushedChunkRoot> flushedChunkRoots;
|
||||
|
||||
Indexer(string targetDir) {
|
||||
|
||||
this->targetDir = targetDir;
|
||||
|
||||
writer = make_shared<Writer>(this);
|
||||
|
||||
string chunkRootFile = targetDir + "/tmpChunkRoots.bin";
|
||||
fChunkRoots.open(chunkRootFile, ios::out | ios::binary);
|
||||
}
|
||||
|
||||
~Indexer() {
|
||||
fChunkRoots.close();
|
||||
}
|
||||
|
||||
void waitUntilWriterBacklogBelow(int maxMegabytes);
|
||||
|
||||
void waitUntilMemoryBelow(int maxMegabytes);
|
||||
|
||||
string createMetadata(Options options, State& state, Hierarchy hierarchy);
|
||||
|
||||
string createDebugHierarchy();
|
||||
|
||||
HierarchyChunk gatherChunk(Node* start, int levels);
|
||||
|
||||
vector<HierarchyChunk> createHierarchyChunks(Node* root, int hierarchyStepSize);
|
||||
|
||||
Hierarchy createHierarchy(string path);
|
||||
|
||||
void flushChunkRoot(shared_ptr<Node> chunkRoot);
|
||||
|
||||
void reloadChunkRoots();
|
||||
};
|
||||
|
||||
class punct_facet : public std::numpunct<char> {
|
||||
protected:
|
||||
char do_decimal_point() const { return '.'; };
|
||||
char do_thousands_sep() const { return '\''; };
|
||||
string do_grouping() const { return "\3"; }
|
||||
};
|
||||
|
||||
void doIndexing(string targetDir, State& state, Options& options, Sampler& sampler);
|
||||
|
||||
|
||||
}
|
||||
321
Converter/include/sampler_voxels.h
Normal file
321
Converter/include/sampler_voxels.h
Normal file
@@ -0,0 +1,321 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <execution>
|
||||
|
||||
#include "structures.h"
|
||||
#include "Attributes.h"
|
||||
#include "PotreeConverter.h"
|
||||
|
||||
|
||||
struct SamplerVoxels : public Sampler {
|
||||
|
||||
static constexpr int gridSize = 256;
|
||||
static constexpr float fGridSize = 256;
|
||||
|
||||
// subsample a local octree from bottom up
|
||||
void sample(shared_ptr<Node> node, Attributes attributes, double baseSpacing, function<void(Node*)> onNodeCompleted) {
|
||||
|
||||
struct Point {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
int r = 0;
|
||||
int g = 0;
|
||||
int b = 0;
|
||||
int32_t pointIndex;
|
||||
int32_t childIndex;
|
||||
};
|
||||
|
||||
function<void(Node*, function<void(Node*)>)> traversePost = [&traversePost](Node* node, function<void(Node*)> callback) {
|
||||
for (auto child : node->children) {
|
||||
|
||||
if (child != nullptr && !child->sampled) {
|
||||
traversePost(child.get(), callback);
|
||||
}
|
||||
}
|
||||
|
||||
callback(node);
|
||||
};
|
||||
|
||||
int64_t bytesPerPoint = attributes.bytes;
|
||||
Vector3 scale = attributes.posScale;
|
||||
Vector3 offset = attributes.posOffset;
|
||||
|
||||
traversePost(node.get(), [bytesPerPoint, baseSpacing, scale, offset, &onNodeCompleted, &attributes](Node* node) {
|
||||
node->sampled = true;
|
||||
|
||||
int64_t numPoints = node->numPoints;
|
||||
|
||||
auto max = node->max;
|
||||
auto min = node->min;
|
||||
auto size = max - min;
|
||||
auto scale = attributes.posScale;
|
||||
auto offset = attributes.posOffset;
|
||||
|
||||
bool isLeaf = node->isLeaf();
|
||||
|
||||
if (isLeaf) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Attribute* aRGB = attributes.get("rgb");
|
||||
int rgbOffset = 0;
|
||||
if(aRGB == nullptr){
|
||||
aRGB = attributes.get("rgba");
|
||||
}else if(aRGB == nullptr){
|
||||
aRGB = attributes.get("RGB");
|
||||
}else if(aRGB == nullptr){
|
||||
aRGB = attributes.get("RGBA");
|
||||
}
|
||||
if(aRGB){
|
||||
rgbOffset = attributes.getOffset(aRGB->name);
|
||||
}
|
||||
|
||||
auto getColor = [aRGB, &attributes, rgbOffset](Node* node, int pointIndex, int& r, int& g, int&b){
|
||||
|
||||
int64_t pointOffset = pointIndex * attributes.bytes;
|
||||
|
||||
if(aRGB){
|
||||
// int32_t* rgb = reinterpret_cast<int32_t*>(node->points->data_u8 + pointOffset + aRGB->offset);
|
||||
if(aRGB->elementSize == 1){
|
||||
r = node->points->get<uint8_t>(pointOffset + rgbOffset + 0);
|
||||
g = node->points->get<uint8_t>(pointOffset + rgbOffset + 1);
|
||||
b = node->points->get<uint8_t>(pointOffset + rgbOffset + 2);
|
||||
}else if(aRGB->elementSize == 2){
|
||||
r = node->points->get<uint16_t>(pointOffset + rgbOffset + 0);
|
||||
g = node->points->get<uint16_t>(pointOffset + rgbOffset + 2);
|
||||
b = node->points->get<uint16_t>(pointOffset + rgbOffset + 4);
|
||||
|
||||
r = r > 255 ? r / 256 : r;
|
||||
g = g > 255 ? g / 256 : g;
|
||||
b = b > 255 ? b / 256 : b;
|
||||
}
|
||||
|
||||
}else{
|
||||
r = 0;
|
||||
g = 0;
|
||||
b = 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
{
|
||||
// merge groups of 2x2x2 voxels of children into a new voxel for current node
|
||||
// note: morton code is zyxzyx, but for some reason we've made child index in order xyz
|
||||
// we node to evaluate children in zyx order (from right to left, first x, then y, then z)
|
||||
|
||||
// vector<Voxel>& voxels = node->voxels;
|
||||
|
||||
int numEstimatedVoxels = 0;
|
||||
for(auto child : node->children){
|
||||
|
||||
if(child == nullptr) continue;
|
||||
|
||||
numEstimatedVoxels += child->numPoints;
|
||||
numEstimatedVoxels += child->voxels.size() / 4;
|
||||
}
|
||||
node->voxels.reserve(numEstimatedVoxels);
|
||||
|
||||
for(int childIndex : {0b000, 0b100, 0b010, 0b110, 0b001, 0b101, 0b011, 0b111}){
|
||||
// now we iterate through voxels of a child
|
||||
// voxels are already sorted in morton order (first x, then y, then z)
|
||||
|
||||
auto child = node->children[childIndex];
|
||||
|
||||
if(child == nullptr) continue;
|
||||
|
||||
if(child->numPoints > 0){
|
||||
// voxelize child
|
||||
|
||||
Vector3 childSize = child->max - child->min;
|
||||
int childGridSize = gridSize;
|
||||
float fChildGridSize = float(childGridSize);
|
||||
static thread_local vector<double> childGrid(childGridSize * childGridSize * childGridSize * 4, 0.0);
|
||||
static thread_local vector<double> childGrid_weight(childGridSize * childGridSize * childGridSize, 0.0);
|
||||
// std::fill(childGrid.begin(), childGrid.end(), 0.0);
|
||||
|
||||
for(int i = 0; i < child->numPoints; i++){
|
||||
int64_t pointOffset = i * attributes.bytes;
|
||||
int32_t* xyz = reinterpret_cast<int32_t*>(child->points->data_u8 + pointOffset);
|
||||
|
||||
double x = (xyz[0] * scale.x) + offset.x;
|
||||
double y = (xyz[1] * scale.y) + offset.y;
|
||||
double z = (xyz[2] * scale.z) + offset.z;
|
||||
|
||||
int r, g, b;
|
||||
getColor(child.get(), i, r, g, b);
|
||||
|
||||
Point point = { x, y, z, r, g, b, i, childIndex };
|
||||
|
||||
float fvx = fChildGridSize * (point.x - child->min.x) / childSize.x;
|
||||
float fvy = fChildGridSize * (point.y - child->min.y) / childSize.y;
|
||||
float fvz = fChildGridSize * (point.z - child->min.z) / childSize.z;
|
||||
|
||||
int ivx = int(std::clamp(fvx, 0.0f, fChildGridSize - 1.0f));
|
||||
int ivy = int(std::clamp(fvy, 0.0f, fChildGridSize - 1.0f));
|
||||
int ivz = int(std::clamp(fvz, 0.0f, fChildGridSize - 1.0f));
|
||||
|
||||
for(int ox = ivx; ox <= ivx + 1; ox++)
|
||||
for(int oy = ivy; oy <= ivy + 1; oy++)
|
||||
for(int oz = ivz; oz <= ivz + 1; oz++)
|
||||
{
|
||||
if(ox < 0 || ox >= childGridSize) continue;
|
||||
if(oy < 0 || oy >= childGridSize) continue;
|
||||
if(oz < 0 || oz >= childGridSize) continue;
|
||||
|
||||
float center_vx = float(ox) + 0.5;
|
||||
float center_vy = float(oy) + 0.5;
|
||||
float center_vz = float(oz) + 0.5;
|
||||
|
||||
float dx = fvx - center_vx;
|
||||
float dy = fvy - center_vy;
|
||||
float dz = fvz - center_vz;
|
||||
|
||||
float distance = sqrt(dx * dx + dy * dy + dz *dz);
|
||||
|
||||
float weight = std::clamp(1.0 - distance, 0.0, 1.0);
|
||||
|
||||
int voxelIndex = mortonEncode_magicbits(ox, oy, oz);
|
||||
|
||||
childGrid[voxelIndex * 4 + 0] += weight * point.r;
|
||||
childGrid[voxelIndex * 4 + 1] += weight * point.g;
|
||||
childGrid[voxelIndex * 4 + 2] += weight * point.b;
|
||||
// childGrid[voxelIndex * 4 + 3] += weight;
|
||||
childGrid_weight[voxelIndex] += weight;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// exctract voxels from grid, store in a list
|
||||
// vector<Voxel> childVoxels;
|
||||
// for(int x = 0; x < gridSize; x++)
|
||||
// for(int y = 0; y < gridSize; y++)
|
||||
// for(int z = 0; z < gridSize; z++)
|
||||
// {
|
||||
// int voxelIndex = x + y * gridSize + z * gridSize * gridSize;
|
||||
int numVoxels = childGridSize * childGridSize * childGridSize;
|
||||
for(int i = 0; i < numVoxels; i++){
|
||||
|
||||
int voxelIndex = i;
|
||||
|
||||
double w = childGrid_weight[voxelIndex];
|
||||
|
||||
if(w > 0.0){
|
||||
|
||||
double r = childGrid[voxelIndex * 4 + 0];
|
||||
double g = childGrid[voxelIndex * 4 + 1];
|
||||
double b = childGrid[voxelIndex * 4 + 2];
|
||||
// double w = childGrid[voxelIndex * 4 + 3];
|
||||
|
||||
int x = everyThirdBit(voxelIndex >> 0);
|
||||
int y = everyThirdBit(voxelIndex >> 1);
|
||||
int z = everyThirdBit(voxelIndex >> 2);
|
||||
|
||||
Voxel voxel = {r, g, b, w, x, y, z};
|
||||
|
||||
child->voxels.push_back(voxel);
|
||||
|
||||
childGrid[voxelIndex * 4 + 0] = 0.0;
|
||||
childGrid[voxelIndex * 4 + 1] = 0.0;
|
||||
childGrid[voxelIndex * 4 + 2] = 0.0;
|
||||
childGrid_weight[voxelIndex] = 0.0;
|
||||
}
|
||||
}
|
||||
// child->voxels = childVoxels;
|
||||
}
|
||||
|
||||
|
||||
Voxel current;
|
||||
for(Voxel childVoxel : child->voxels){
|
||||
|
||||
int childX = (childIndex >> 2) & 1;
|
||||
int childY = (childIndex >> 1) & 1;
|
||||
int childZ = (childIndex >> 0) & 1;
|
||||
|
||||
int currentVoxelX = (childVoxel.x + gridSize * childX) / 2;
|
||||
int currentVoxelY = (childVoxel.y + gridSize * childY) / 2;
|
||||
int currentVoxelZ = (childVoxel.z + gridSize * childZ) / 2;
|
||||
|
||||
int isSameVoxel = currentVoxelX == current.x && currentVoxelY == current.y && currentVoxelZ == current.z;
|
||||
|
||||
if(isSameVoxel){
|
||||
current.r += childVoxel.r;
|
||||
current.g += childVoxel.g;
|
||||
current.b += childVoxel.b;
|
||||
current.w += childVoxel.w;
|
||||
}else{
|
||||
if(current.w > 0.0){
|
||||
node->voxels.push_back(current);
|
||||
}
|
||||
|
||||
current = Voxel();
|
||||
current.x = currentVoxelX;
|
||||
current.y = currentVoxelY;
|
||||
current.z = currentVoxelZ;
|
||||
current.r = childVoxel.r;
|
||||
current.g = childVoxel.g;
|
||||
current.b = childVoxel.b;
|
||||
current.w = childVoxel.w;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(current.w > 0.0){
|
||||
node->voxels.push_back(current);
|
||||
}
|
||||
|
||||
// node->voxels = voxels;
|
||||
}
|
||||
|
||||
|
||||
// for(Voxel voxel : childVoxels){
|
||||
// int voxelIndex = voxel.x + voxel.y * gridSize + voxel.z * gridSize * gridSize;
|
||||
// grid[voxelIndex * 4 + 0] += voxel.r;
|
||||
// grid[voxelIndex * 4 + 1] += voxel.g;
|
||||
// grid[voxelIndex * 4 + 2] += voxel.b;
|
||||
// grid[voxelIndex * 4 + 3] += voxel.w;
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
// vector<Voxel> voxels;
|
||||
// for(int x = 0; x < gridSize; x++)
|
||||
// for(int y = 0; y < gridSize; y++)
|
||||
// for(int z = 0; z < gridSize; z++)
|
||||
// {
|
||||
// int voxelIndex = x + y * gridSize + z * gridSize * gridSize;
|
||||
|
||||
// double r = grid[voxelIndex * 4 + 0];
|
||||
// double g = grid[voxelIndex * 4 + 1];
|
||||
// double b = grid[voxelIndex * 4 + 2];
|
||||
// double w = grid[voxelIndex * 4 + 3];
|
||||
|
||||
// if(w > 0.0){
|
||||
// Voxel voxel = {r, g, b, w, x, y, z};
|
||||
|
||||
// voxels.push_back(voxel);
|
||||
// }
|
||||
// }
|
||||
// node->voxels = voxels;
|
||||
|
||||
// write child nodes to disk
|
||||
for (int64_t childIndex = 0; childIndex < 8; childIndex++) {
|
||||
auto child = node->children[childIndex];
|
||||
|
||||
if (child == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
onNodeCompleted(child.get());
|
||||
}
|
||||
|
||||
// node->points = accepted;
|
||||
// node->numPoints = numAccepted;
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "Vector3.h"
|
||||
#include "unsuck/unsuck.hpp"
|
||||
#include "Attributes.h"
|
||||
#include "converter_utils.h"
|
||||
|
||||
using std::vector;
|
||||
using std::shared_ptr;
|
||||
@@ -24,12 +25,23 @@ struct CumulativeColor {
|
||||
int64_t w = 0;
|
||||
};
|
||||
|
||||
struct Voxel{
|
||||
double r = 0.0;
|
||||
double g = 0.0;
|
||||
double b = 0.0;
|
||||
double w = 0.0;
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int z = 0;
|
||||
};
|
||||
|
||||
struct Node {
|
||||
|
||||
vector<shared_ptr<Node>> children;
|
||||
|
||||
string name;
|
||||
shared_ptr<Buffer> points;
|
||||
vector<Voxel> voxels;
|
||||
vector<CumulativeColor> colors;
|
||||
Vector3 min;
|
||||
Vector3 max;
|
||||
|
||||
2544
Converter/libs/robinhood_map/robin_hood.h
Normal file
2544
Converter/libs/robinhood_map/robin_hood.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -159,6 +159,16 @@ struct Buffer {
|
||||
free(data);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T get(int64_t position) {
|
||||
|
||||
T value;
|
||||
|
||||
memcpy(&value, data_u8 + position, sizeof(T));
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void set(T value, int64_t position) {
|
||||
memcpy(data_u8 + position, &value, sizeof(T));
|
||||
|
||||
469
Converter/src/DbgWriter.cpp
Normal file
469
Converter/src/DbgWriter.cpp
Normal file
@@ -0,0 +1,469 @@
|
||||
|
||||
#include "DbgWriter.h"
|
||||
|
||||
namespace dbgwriter{
|
||||
|
||||
// struct Point {
|
||||
// int64_t x;
|
||||
// int64_t y;
|
||||
// int64_t z;
|
||||
// };
|
||||
|
||||
|
||||
vector<Point> getPoints(Node* node, Attributes attributes) {
|
||||
|
||||
vector<Point> points;
|
||||
|
||||
for (int64_t i = 0; i < node->numPoints; i++) {
|
||||
int64_t offset = i * attributes.bytes;
|
||||
|
||||
int32_t sX, sY, sZ;
|
||||
memcpy(&sX, node->points->data_u8 + offset + 0, 4);
|
||||
memcpy(&sY, node->points->data_u8 + offset + 4, 4);
|
||||
memcpy(&sZ, node->points->data_u8 + offset + 8, 4);
|
||||
|
||||
Point p;
|
||||
p.x = sX;
|
||||
p.y = sY;
|
||||
p.z = sZ;
|
||||
|
||||
points.push_back(p);
|
||||
|
||||
}
|
||||
|
||||
return points;
|
||||
}
|
||||
|
||||
std::pair<Point, Point> computeBox(vector<Point> points) {
|
||||
|
||||
Point min, max;
|
||||
|
||||
min.x = std::numeric_limits<int64_t>::max();
|
||||
min.y = std::numeric_limits<int64_t>::max();
|
||||
min.z = std::numeric_limits<int64_t>::max();
|
||||
max.x = std::numeric_limits<int64_t>::min();
|
||||
max.y = std::numeric_limits<int64_t>::min();
|
||||
max.z = std::numeric_limits<int64_t>::min();
|
||||
|
||||
for (Point& point : points) {
|
||||
min.x = std::min(min.x, point.x);
|
||||
min.y = std::min(min.y, point.y);
|
||||
min.z = std::min(min.z, point.z);
|
||||
|
||||
max.x = std::max(max.x, point.x);
|
||||
max.y = std::max(max.y, point.y);
|
||||
max.z = std::max(max.z, point.z);
|
||||
}
|
||||
|
||||
return { min, max };
|
||||
}
|
||||
|
||||
void writePosition2(string dir, Node* node, Attributes attributes) {
|
||||
|
||||
int64_t numPoints = node->numPoints;
|
||||
|
||||
int64_t minX = std::numeric_limits<int64_t>::max();
|
||||
int64_t minY = std::numeric_limits<int64_t>::max();
|
||||
int64_t minZ = std::numeric_limits<int64_t>::max();
|
||||
int64_t maxX = std::numeric_limits<int64_t>::min();
|
||||
int64_t maxY = std::numeric_limits<int64_t>::min();
|
||||
int64_t maxZ = std::numeric_limits<int64_t>::min();
|
||||
|
||||
for (int64_t i = 1; i < numPoints; i++) {
|
||||
int64_t offset = i * attributes.bytes;
|
||||
|
||||
int32_t sX, sY, sZ;
|
||||
memcpy(&sX, node->points->data_u8 + offset + 0, 4);
|
||||
memcpy(&sY, node->points->data_u8 + offset + 4, 4);
|
||||
memcpy(&sZ, node->points->data_u8 + offset + 8, 4);
|
||||
|
||||
minX = std::min(minX, int64_t(sX));
|
||||
minY = std::min(minY, int64_t(sY));
|
||||
minZ = std::min(minZ, int64_t(sZ));
|
||||
|
||||
maxX = std::max(maxX, int64_t(sX));
|
||||
maxY = std::max(maxY, int64_t(sY));
|
||||
maxZ = std::max(maxZ, int64_t(sZ));
|
||||
|
||||
}
|
||||
|
||||
int64_t rangeX = maxX - minX;
|
||||
int64_t rangeY = maxY - minY;
|
||||
int64_t rangeZ = maxZ - minZ;
|
||||
|
||||
int bitsX = std::log2(rangeX);
|
||||
int bitsY = std::log2(rangeY);
|
||||
int bitsZ = std::log2(rangeZ);
|
||||
|
||||
auto computeBytes = [](int bits) {
|
||||
if (bits <= 8) {
|
||||
return 1;
|
||||
} else if (bits <= 16) {
|
||||
return 2;
|
||||
} else if (bits <= 32) {
|
||||
return 4;
|
||||
}
|
||||
};
|
||||
|
||||
int bytesX = computeBytes(bitsX);
|
||||
int bytesY = computeBytes(bitsY);
|
||||
int bytesZ = computeBytes(bitsZ);
|
||||
|
||||
Buffer X(numPoints * bytesX);
|
||||
Buffer Y(numPoints * bytesY);
|
||||
Buffer Z(numPoints * bytesZ);
|
||||
|
||||
for (int64_t i = 1; i < numPoints; i++) {
|
||||
int64_t offset = i * attributes.bytes;
|
||||
|
||||
int32_t sX, sY, sZ;
|
||||
memcpy(&sX, node->points->data_u8 + offset + 0, 4);
|
||||
memcpy(&sY, node->points->data_u8 + offset + 4, 4);
|
||||
memcpy(&sZ, node->points->data_u8 + offset + 8, 4);
|
||||
|
||||
int32_t oX = sX - minX;
|
||||
int32_t oY = sY - minY;
|
||||
int32_t oZ = sZ - minZ;
|
||||
|
||||
if (bytesX == 1) {
|
||||
X.data_u8[i] = oX;
|
||||
} else if (bytesX == 2) {
|
||||
X.data_u16[i] = oX;
|
||||
} else if (bytesX == 4) {
|
||||
X.data_u32[i] = oX;
|
||||
}
|
||||
|
||||
if (bytesY == 1) {
|
||||
Y.data_u8[i] = oY;
|
||||
} else if (bytesY == 2) {
|
||||
Y.data_u16[i] = oY;
|
||||
} else if (bytesY == 4) {
|
||||
Y.data_u32[i] = oY;
|
||||
}
|
||||
|
||||
if (bytesZ == 1) {
|
||||
Z.data_u8[i] = oZ;
|
||||
} else if (bytesZ == 2) {
|
||||
Z.data_u16[i] = oZ;
|
||||
} else if (bytesZ == 4) {
|
||||
Z.data_u32[i] = oZ;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
writeBinaryFile(dir + "/quantized_X.bin", X);
|
||||
writeBinaryFile(dir + "/quantized_Y.bin", Y);
|
||||
writeBinaryFile(dir + "/quantized_Z.bin", Z);
|
||||
|
||||
int a = 10;
|
||||
|
||||
}
|
||||
|
||||
void writePosition(string dir, Node* node, Attributes attributes) {
|
||||
|
||||
int64_t numPoints = node->numPoints;
|
||||
vector<Point> points = getPoints(node, attributes);
|
||||
|
||||
Buffer X(numPoints * 4);
|
||||
Buffer Y(numPoints * 4);
|
||||
Buffer Z(numPoints * 4);
|
||||
Buffer diffX(numPoints * 4);
|
||||
Buffer diffY(numPoints * 4);
|
||||
Buffer diffZ(numPoints * 4);
|
||||
|
||||
stringstream ssDiffX;
|
||||
stringstream ssDiffY;
|
||||
stringstream ssDiffZ;
|
||||
|
||||
stringstream ssPoints;
|
||||
|
||||
for (int64_t i = 0; i < numPoints; i++) {
|
||||
int64_t offset = i * attributes.bytes;
|
||||
|
||||
Point point = points[i];
|
||||
|
||||
X.data_i32[i] = point.x;
|
||||
Y.data_i32[i] = point.y;
|
||||
Z.data_i32[i] = point.z;
|
||||
|
||||
int64_t idiffX, idiffY, idiffZ;
|
||||
|
||||
if (i == 0) {
|
||||
idiffX = point.x;
|
||||
idiffY = point.y;
|
||||
idiffZ = point.z;
|
||||
} else {
|
||||
idiffX = points[i].x - points[i - 1].x;
|
||||
idiffZ = points[i].y - points[i - 1].y;
|
||||
idiffY = points[i].z - points[i - 1].z;
|
||||
}
|
||||
|
||||
diffX.data_i32[i] = idiffX;
|
||||
diffY.data_i32[i] = idiffY;
|
||||
diffZ.data_i32[i] = idiffZ;
|
||||
|
||||
ssDiffX << idiffX << ", ";
|
||||
ssDiffY << idiffY << ", ";
|
||||
ssDiffZ << idiffZ << ", ";
|
||||
|
||||
ssPoints << "[" << point.x << ", " << point.y << ", " << point.z << "], ";
|
||||
|
||||
}
|
||||
|
||||
writeBinaryFile(dir + "/X.bin", X);
|
||||
writeBinaryFile(dir + "/Y.bin", Y);
|
||||
writeBinaryFile(dir + "/Z.bin", Z);
|
||||
|
||||
writeBinaryFile(dir + "/diff_X.bin", diffX);
|
||||
writeBinaryFile(dir + "/diff_Y.bin", diffY);
|
||||
writeBinaryFile(dir + "/diff_Z.bin", diffZ);
|
||||
|
||||
writeFile(dir + "/diffX.txt", ssDiffX.str());
|
||||
writeFile(dir + "/diffY.txt", ssDiffY.str());
|
||||
writeFile(dir + "/diffZ.txt", ssDiffZ.str());
|
||||
|
||||
writeFile(dir + "/points.txt", ssPoints.str());
|
||||
}
|
||||
|
||||
// method to seperate bits from a given integer 3 positions apart
|
||||
inline uint64_t splitBy3(unsigned int a) {
|
||||
|
||||
uint64_t x = a & 0x1fffff; // we only look at the first 21 bits
|
||||
x = (x | x << 32) & 0x1f00000000ffff; // shift left 32 bits, OR with self, and 00011111000000000000000000000000000000001111111111111111
|
||||
x = (x | x << 16) & 0x1f0000ff0000ff; // shift left 32 bits, OR with self, and 00011111000000000000000011111111000000000000000011111111
|
||||
x = (x | x << 8) & 0x100f00f00f00f00f; // shift left 32 bits, OR with self, and 0001000000001111000000001111000000001111000000001111000000000000
|
||||
x = (x | x << 4) & 0x10c30c30c30c30c3; // shift left 32 bits, OR with self, and 0001000011000011000011000011000011000011000011000011000100000000
|
||||
x = (x | x << 2) & 0x1249249249249249;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
inline uint64_t mortonEncode_magicbits(unsigned int x, unsigned int y, unsigned int z) {
|
||||
|
||||
uint64_t answer = 0;
|
||||
answer |= splitBy3(x) | splitBy3(y) << 1 | splitBy3(z) << 2;
|
||||
|
||||
return answer;
|
||||
}
|
||||
|
||||
void writePositionMortonCode(string dir, Node* node, Attributes attributes) {
|
||||
|
||||
int64_t numPoints = node->numPoints;
|
||||
|
||||
vector<Point> points = getPoints(node, attributes);
|
||||
|
||||
auto [min, max] = computeBox(points);
|
||||
|
||||
int64_t rangeX = max.x - min.x;
|
||||
int64_t rangeY = max.z - min.z;
|
||||
int64_t rangeZ = max.y - min.y;
|
||||
|
||||
|
||||
vector<uint64_t> mortonCodes;
|
||||
|
||||
for (int64_t i = 0; i < numPoints; i++) {
|
||||
int64_t offset = i * attributes.bytes;
|
||||
|
||||
Point point = points[i];
|
||||
|
||||
uint32_t oX = point.x - min.x;
|
||||
uint32_t oY = point.z - min.z;
|
||||
uint32_t oZ = point.y - min.y;
|
||||
|
||||
uint64_t mortonCode = mortonEncode_magicbits(oX, oY, oZ);
|
||||
|
||||
mortonCodes.push_back(mortonCode);
|
||||
|
||||
}
|
||||
|
||||
sort(mortonCodes.begin(), mortonCodes.end(), [](uint64_t& a, uint64_t& b) {
|
||||
return a < b;
|
||||
});
|
||||
|
||||
Buffer data(8 * numPoints);
|
||||
Buffer dataDiff(8 * numPoints);
|
||||
|
||||
stringstream ss;
|
||||
stringstream ssDiff;
|
||||
ss << "[";
|
||||
ssDiff << "[";
|
||||
|
||||
for (int64_t i = 0; i < numPoints; i++) {
|
||||
uint64_t mortonCode = mortonCodes[i];
|
||||
data.data_u64[i] = mortonCode;
|
||||
|
||||
uint64_t diff;
|
||||
|
||||
if (i == 0) {
|
||||
diff = mortonCode;
|
||||
} else {
|
||||
diff = mortonCodes[i] - mortonCodes[i - 1];
|
||||
}
|
||||
dataDiff.data_u64[i] = diff;
|
||||
|
||||
ss << mortonCode << ", ";
|
||||
ssDiff << diff << ", ";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
ss << "]";
|
||||
ssDiff << "]";
|
||||
|
||||
writeFile(dir + "/mortoncode.txt", ss.str());
|
||||
writeFile(dir + "/mortoncode_diff.txt", ssDiff.str());
|
||||
|
||||
|
||||
writeBinaryFile(dir + "/mortoncode.bin", data);
|
||||
writeBinaryFile(dir + "/mortoncode_diff.bin", dataDiff);
|
||||
|
||||
|
||||
int a = 10;
|
||||
}
|
||||
|
||||
void writeIntensity(string dir, Node* node, Attributes attributes) {
|
||||
|
||||
int64_t numPoints = node->numPoints;
|
||||
int64_t attributeOffset = attributes.getOffset("intensity");
|
||||
|
||||
//int16_t intensity_origin_u16;
|
||||
//memcpy(&intensity_origin_u16, node->points->data_u8 + attributeOffset, 2);
|
||||
//int64_t intensity_origin = intensity_origin_u16;
|
||||
|
||||
Buffer I(numPoints * 2);
|
||||
|
||||
memcpy(I.data, node->points->data_u8 + attributeOffset, 2);
|
||||
|
||||
int64_t intensity_previous = I.data_u16[0];
|
||||
int64_t intensity_current;
|
||||
|
||||
for (int64_t i = 1; i < numPoints; i++) {
|
||||
int64_t offset = i * attributes.bytes;
|
||||
|
||||
int16_t intensity_1_u16;
|
||||
memcpy(&intensity_1_u16, node->points->data_u8 + offset + attributeOffset, 2);
|
||||
|
||||
intensity_current = intensity_1_u16;
|
||||
|
||||
int64_t diff = (intensity_current - intensity_previous);
|
||||
int64_t sign = diff < 0 ? 0b1000'0000'0000'0000 : 0b0;
|
||||
|
||||
uint16_t diff16 = sign | std::abs(diff);
|
||||
//uint16_t diff16 = ((std::abs(diff) << 1) | sign);
|
||||
|
||||
I.data_u16[i] = diff16;
|
||||
|
||||
intensity_previous = intensity_current;
|
||||
}
|
||||
|
||||
writeBinaryFile(dir + "/diff_intensity.bin", I);
|
||||
}
|
||||
|
||||
|
||||
void writeNormal(string dir, Node* node, Attributes attributes, Attribute attribute) {
|
||||
int attributeOffset = attributes.getOffset(attribute.name);
|
||||
int64_t numBytes = attribute.size * node->numPoints;
|
||||
Buffer buffer(numBytes);
|
||||
|
||||
uint8_t* source = node->points->data_u8;
|
||||
uint8_t* target = buffer.data_u8;
|
||||
|
||||
for (int64_t i = 0; i < node->numPoints; i++) {
|
||||
|
||||
int64_t sourceOffset = i * attributes.bytes + attributeOffset;
|
||||
int64_t targetOffset = i * attribute.size;
|
||||
|
||||
memcpy(target + targetOffset, source + sourceOffset, attribute.size);
|
||||
}
|
||||
|
||||
string filepath = dir + "/" + attribute.name + ".bin";
|
||||
vector<uint8_t> data(target, target + numBytes);
|
||||
writeBinaryFile(filepath, data);
|
||||
}
|
||||
|
||||
void writeRGB(string dir, Node* node, Attributes attributes, Attribute attribute) {
|
||||
int attributeOffset = attributes.getOffset(attribute.name);
|
||||
int64_t numPoints = node->numPoints;
|
||||
//int64_t numBytes = 4 * numPoints;
|
||||
//Buffer buffer(numBytes);
|
||||
|
||||
uint8_t* source = node->points->data_u8;
|
||||
//uint8_t* target = buffer.data_u8;
|
||||
|
||||
int64_t dimx = ceil(sqrt(numPoints));
|
||||
int64_t dimy = dimx;
|
||||
|
||||
string filepath = dir + "/" + attribute.name + ".ppm";
|
||||
ofstream ofs(filepath, ios::out | ios::binary);
|
||||
ofs << "P6" << endl << dimx << ' ' << dimy << endl << "255" << endl;
|
||||
|
||||
|
||||
for (int64_t i = 0; i < numPoints; i++) {
|
||||
|
||||
int64_t sourceOffset = i * attributes.bytes + attributeOffset;
|
||||
|
||||
uint16_t rgb[3];
|
||||
memcpy(rgb, source + sourceOffset, 6);
|
||||
|
||||
uint8_t r = rgb[0] > 255 ? rgb[0] / 256 : rgb[0];
|
||||
uint8_t g = rgb[1] > 255 ? rgb[1] / 256 : rgb[1];
|
||||
uint8_t b = rgb[2] > 255 ? rgb[2] / 256 : rgb[2];
|
||||
|
||||
ofs << r << g << b;
|
||||
|
||||
//ofs << (char)(i % 256) << (char)(j % 256) << (char)((i * j) % 256);
|
||||
|
||||
//memcpy(target + targetOffset, source + sourceOffset, attribute.size);
|
||||
}
|
||||
ofs.close();
|
||||
|
||||
}
|
||||
|
||||
void writeDifference(string dir, Node* node, Attributes attributes, Attribute attribute) {
|
||||
|
||||
if (attribute.type == AttributeType::UINT16) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void writeNode(Node* node, Attributes attributes){
|
||||
|
||||
string dir = "D:/temp/compression/" + node->name;
|
||||
|
||||
fs::create_directories(dir);
|
||||
|
||||
int64_t attributeOffset = 0;
|
||||
for (Attribute& attribute : attributes.list) {
|
||||
|
||||
if (attribute.name == "position") {
|
||||
//writeNormal(dir, node, attributes, attribute);
|
||||
writePosition(dir, node, attributes);
|
||||
writePosition2(dir, node, attributes);
|
||||
writePositionMortonCode(dir, node, attributes);
|
||||
} else if(attribute.name == "intensity"){
|
||||
writeIntensity(dir, node, attributes);
|
||||
} else if (attribute.name == "rgb") {
|
||||
writeRGB(dir, node, attributes, attribute);
|
||||
}
|
||||
|
||||
writeNormal(dir, node, attributes, attribute);
|
||||
//writeDifference(dir, node, attributes, attribute);
|
||||
|
||||
attributeOffset += attribute.size;
|
||||
}
|
||||
|
||||
|
||||
writeBinaryFile(dir + "/all.bin", *node->points);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
133
Converter/src/chunker_sparse.cpp
Normal file
133
Converter/src/chunker_sparse.cpp
Normal file
@@ -0,0 +1,133 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <filesystem>
|
||||
#include <unordered_map>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <memory>
|
||||
#include <atomic>
|
||||
|
||||
#include "chunker_countsort_laszip.h"
|
||||
|
||||
#include "Attributes.h"
|
||||
#include "converter_utils.h"
|
||||
#include "unsuck/unsuck.hpp"
|
||||
#include "unsuck/TaskPool.hpp"
|
||||
#include "Vector3.h"
|
||||
#include "ConcurrentWriter.h"
|
||||
|
||||
#include "json/json.hpp"
|
||||
#include "laszip/laszip_api.h"
|
||||
#include "LasLoader/LasLoader.h"
|
||||
#include "PotreeConverter.h"
|
||||
#include "logger.h"
|
||||
|
||||
#include "robinhood_map/robin_hood.h"
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
using std::unordered_map;
|
||||
using std::thread;
|
||||
using std::mutex;
|
||||
using std::lock_guard;
|
||||
using std::make_shared;
|
||||
using std::shared_ptr;
|
||||
using std::unique_ptr;
|
||||
using std::atomic_int32_t;
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
|
||||
|
||||
namespace chunker_sparse {
|
||||
|
||||
void run(vector<Source> sources, string targetDir, Vector3 min, Vector3 max, State& state, Attributes outputAttributes) {
|
||||
|
||||
auto tStart = now();
|
||||
|
||||
for (auto source : sources) {
|
||||
|
||||
string path = source.path;
|
||||
|
||||
laszip_POINTER laszip_reader;
|
||||
laszip_header* header;
|
||||
laszip_point* point;
|
||||
|
||||
{
|
||||
laszip_BOOL is_compressed;
|
||||
laszip_BOOL request_reader = 1;
|
||||
|
||||
laszip_create(&laszip_reader);
|
||||
laszip_request_compatibility_mode(laszip_reader, request_reader);
|
||||
laszip_open_reader(laszip_reader, path.c_str(), &is_compressed);
|
||||
laszip_get_header_pointer(laszip_reader, &header);
|
||||
laszip_get_point_pointer(laszip_reader, &point);
|
||||
// laszip_seek_point(laszip_reader, task->firstPoint);
|
||||
}
|
||||
|
||||
int64_t numPoints = std::max(uint64_t(header->number_of_point_records), header->extended_number_of_point_records);
|
||||
double xyz[3];
|
||||
|
||||
int gridSize = 1024;
|
||||
float fGridSize = float(gridSize);
|
||||
robin_hood::unordered_map<int32_t, int32_t> grid;
|
||||
grid.reserve(10'000'000);
|
||||
|
||||
//int gridSize = 512;
|
||||
//float fGridSize = float(gridSize);
|
||||
//unordered_map<int32_t, int32_t> grid;
|
||||
//grid.reserve(10'000'000);
|
||||
|
||||
//int gridSize = 512;
|
||||
//float fGridSize = float(gridSize);
|
||||
// vector<int64_t> grid(gridSize * gridSize * gridSize, 0);
|
||||
//vector<std::atomic_int32_t> grid(gridSize * gridSize * gridSize);
|
||||
|
||||
double size[3] = {
|
||||
header->max_x - header->min_x,
|
||||
header->max_y - header->min_y,
|
||||
header->max_z - header->min_z
|
||||
};
|
||||
|
||||
int64_t prevKey = 0;
|
||||
int64_t prevCount = 0;
|
||||
|
||||
for (int64_t i = 0; i < numPoints; i++) {
|
||||
laszip_read_point(laszip_reader);
|
||||
laszip_get_coordinates(laszip_reader, xyz);
|
||||
|
||||
int64_t gx = std::min(int(fGridSize * (xyz[0] - header->min_x) / size[0]), gridSize - 1);
|
||||
int64_t gy = std::min(int(fGridSize * (xyz[1] - header->min_y) / size[1]), gridSize - 1);
|
||||
int64_t gz = std::min(int(fGridSize * (xyz[2] - header->min_z) / size[2]), gridSize - 1);
|
||||
// int64_t key = (gx << 40) | (gy << 20) | (gz << 0);
|
||||
int32_t key = gx + gy * gridSize + gz * gridSize * gridSize;
|
||||
|
||||
if(key == prevKey){
|
||||
prevCount++;
|
||||
}else{
|
||||
grid[prevKey] += prevCount;
|
||||
|
||||
prevKey = key;
|
||||
prevCount = 1;
|
||||
}
|
||||
|
||||
|
||||
//grid[key]++;
|
||||
}
|
||||
|
||||
grid[prevKey] += prevCount;
|
||||
|
||||
cout << "grid size: " << grid.size() << endl;
|
||||
|
||||
}
|
||||
|
||||
double duration = now() - tStart;
|
||||
cout << "duration: " << formatNumber(duration, 1) << "s" << endl;
|
||||
state.values["duration(chunking-total)"] = formatNumber(duration, 3);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
1743
Converter/src/indexer_voxels.cpp
Normal file
1743
Converter/src/indexer_voxels.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -5,16 +5,20 @@
|
||||
|
||||
#include "unsuck/unsuck.hpp"
|
||||
#include "chunker_countsort_laszip.h"
|
||||
#include "chunker_sparse.h"
|
||||
#include "indexer.h"
|
||||
#include "indexer_voxels.h"
|
||||
#include "sampler_poisson.h"
|
||||
#include "sampler_poisson_average.h"
|
||||
#include "sampler_random.h"
|
||||
#include "sampler_voxels.h"
|
||||
#include "Attributes.h"
|
||||
#include "PotreeConverter.h"
|
||||
#include "logger.h"
|
||||
|
||||
#include "arguments/Arguments.hpp"
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
Options parseArguments(int argc, char** argv) {
|
||||
@@ -343,6 +347,8 @@ shared_ptr<Monitor> startMonitoring(State& state) {
|
||||
|
||||
void chunking(Options& options, vector<Source>& sources, string targetDir, Stats& stats, State& state, Attributes outputAttributes) {
|
||||
|
||||
// chunker_sparse::run(sources, targetDir, stats.min, stats.max, state, outputAttributes);
|
||||
|
||||
if (options.noChunking) {
|
||||
return;
|
||||
}
|
||||
@@ -365,30 +371,36 @@ void chunking(Options& options, vector<Source>& sources, string targetDir, Stats
|
||||
exit(123);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void indexing(Options& options, string targetDir, State& state) {
|
||||
|
||||
if (options.noIndexing) {
|
||||
return;
|
||||
{
|
||||
SamplerVoxels sampler;
|
||||
indexer_voxels::doIndexing(targetDir, state, options, sampler);
|
||||
}
|
||||
|
||||
if (options.method == "random") {
|
||||
// if (options.noIndexing) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
SamplerRandom sampler;
|
||||
indexer::doIndexing(targetDir, state, options, sampler);
|
||||
// if (options.method == "random") {
|
||||
|
||||
} else if (options.method == "poisson") {
|
||||
// SamplerRandom sampler;
|
||||
// indexer::doIndexing(targetDir, state, options, sampler);
|
||||
|
||||
SamplerPoisson sampler;
|
||||
indexer::doIndexing(targetDir, state, options, sampler);
|
||||
// } else if (options.method == "poisson") {
|
||||
|
||||
} else if (options.method == "poisson_average") {
|
||||
// SamplerPoisson sampler;
|
||||
// indexer::doIndexing(targetDir, state, options, sampler);
|
||||
|
||||
SamplerPoissonAverage sampler;
|
||||
indexer::doIndexing(targetDir, state, options, sampler);
|
||||
// } else if (options.method == "poisson_average") {
|
||||
|
||||
}
|
||||
// SamplerPoissonAverage sampler;
|
||||
// indexer::doIndexing(targetDir, state, options, sampler);
|
||||
|
||||
// }
|
||||
}
|
||||
|
||||
void createReport(Options& options, vector<Source> sources, string targetDir, Stats& stats, State& state, double tStart) {
|
||||
|
||||
Reference in New Issue
Block a user