some attempts to resolve chunking issues
This commit is contained in:
@@ -23,9 +23,9 @@
|
|||||||
struct defaults {
|
struct defaults {
|
||||||
int outWidth = 512;
|
int outWidth = 512;
|
||||||
int outHeight = 512;
|
int outHeight = 512;
|
||||||
int gridWidth = 512;
|
int gridWidth = 256;
|
||||||
int gridHeight = 512;
|
int gridHeight = 256;
|
||||||
int gridDepth = 512;
|
int gridDepth = 256;
|
||||||
float fps = 30.0f;
|
float fps = 30.0f;
|
||||||
PNoise2 noise = PNoise2(42);
|
PNoise2 noise = PNoise2(42);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -53,10 +53,10 @@ Mat4f perspective(float fovy, float aspect, float zNear, float zfar) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct Voxel {
|
struct Voxel {
|
||||||
float weight;
|
float weight = 1.0;
|
||||||
bool active;
|
bool active = false;
|
||||||
float alpha;
|
float alpha = 0.0;
|
||||||
Vec3ui8 color;
|
Vec3ui8 color = Vec3ui8(0,0,0);
|
||||||
Voxel() = default;
|
Voxel() = default;
|
||||||
Voxel(float weight, bool active, float alpha, Vec3ui8 color) : weight(weight), active(active), alpha(alpha), color(color) {}
|
Voxel(float weight, bool active, float alpha, Vec3ui8 color) : weight(weight), active(active), alpha(alpha), color(color) {}
|
||||||
// TODO: add curving and similar for water and glass and so on.
|
// TODO: add curving and similar for water and glass and so on.
|
||||||
@@ -155,13 +155,12 @@ struct Chunk {
|
|||||||
|
|
||||||
if (children.empty()) {
|
if (children.empty()) {
|
||||||
int index = getVoxelIndex(pos);
|
int index = getVoxelIndex(pos);
|
||||||
if (index >= 0 && index < static_cast<int>(voxels.size())) {
|
//if (index >= 0 && index < static_cast<int>(voxels.size())) {
|
||||||
voxels[index] = newVox;
|
voxels[index] = newVox;
|
||||||
dirty = true;
|
dirty = true;
|
||||||
return true;
|
return true;
|
||||||
|
// }
|
||||||
}
|
// return false;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Chunk& child : children) {
|
for (Chunk& child : children) {
|
||||||
@@ -223,7 +222,7 @@ struct Chunk {
|
|||||||
return Voxel();
|
return Voxel();
|
||||||
}
|
}
|
||||||
|
|
||||||
const Voxel get(const Vec3i& pos, int maxDepth = 0) const {
|
const Voxel& get(const Vec3i& pos, int maxDepth = 0) const {
|
||||||
if (!inChunk(pos)) {
|
if (!inChunk(pos)) {
|
||||||
return Voxel();
|
return Voxel();
|
||||||
}
|
}
|
||||||
@@ -251,12 +250,11 @@ struct Chunk {
|
|||||||
|
|
||||||
int getVoxelIndex(Vec3i pos) const {
|
int getVoxelIndex(Vec3i pos) const {
|
||||||
Vec3i localPos = pos - minCorner;
|
Vec3i localPos = pos - minCorner;
|
||||||
return localPos.z * chunkSize.x * chunkSize.y +
|
return localPos.z * chunkSize.x * chunkSize.y + localPos.y * chunkSize.x + localPos.x;
|
||||||
localPos.y * chunkSize.x +
|
|
||||||
localPos.x;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateAverages() {
|
void updateAverages() {
|
||||||
|
TIME_FUNCTION;
|
||||||
if (voxels.empty()) {
|
if (voxels.empty()) {
|
||||||
weight = 0.0f;
|
weight = 0.0f;
|
||||||
alpha = 0.0f;
|
alpha = 0.0f;
|
||||||
@@ -303,6 +301,7 @@ struct Chunk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void updateAveragesRecursive() {
|
void updateAveragesRecursive() {
|
||||||
|
TIME_FUNCTION;
|
||||||
if (children.empty()) {
|
if (children.empty()) {
|
||||||
updateAverages();
|
updateAverages();
|
||||||
} else {
|
} else {
|
||||||
@@ -353,6 +352,7 @@ struct Chunk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void subdivide(int numChildrenPerAxis = 2) {
|
void subdivide(int numChildrenPerAxis = 2) {
|
||||||
|
TIME_FUNCTION;
|
||||||
if (!children.empty()) return; // Already subdivided
|
if (!children.empty()) return; // Already subdivided
|
||||||
|
|
||||||
Vec3i childSize = (maxCorner - minCorner) / numChildrenPerAxis;
|
Vec3i childSize = (maxCorner - minCorner) / numChildrenPerAxis;
|
||||||
@@ -387,13 +387,10 @@ struct Chunk {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear parent voxels after subdivision to save memory
|
|
||||||
voxels.clear();
|
|
||||||
voxels.shrink_to_fit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void merge() {
|
void merge() {
|
||||||
|
TIME_FUNCTION;
|
||||||
if (children.empty()) return;
|
if (children.empty()) return;
|
||||||
|
|
||||||
// Calculate total size from children
|
// Calculate total size from children
|
||||||
@@ -441,6 +438,55 @@ private:
|
|||||||
return rads * (M_PI / 180);
|
return rads * (M_PI / 180);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void createChunksFromVoxels() {
|
||||||
|
TIME_FUNCTION;
|
||||||
|
chunks.clear();
|
||||||
|
|
||||||
|
// Create chunks based on CHUNK_THRESHOLD
|
||||||
|
int chunksX = std::max(1, (gridSize.x + CHUNK_THRESHOLD - 1) / CHUNK_THRESHOLD);
|
||||||
|
int chunksY = std::max(1, (gridSize.y + CHUNK_THRESHOLD - 1) / CHUNK_THRESHOLD);
|
||||||
|
int chunksZ = std::max(1, (gridSize.z + CHUNK_THRESHOLD - 1) / CHUNK_THRESHOLD);
|
||||||
|
|
||||||
|
Vec3i chunkSize = Vec3i(
|
||||||
|
(gridSize.x + chunksX - 1) / chunksX,
|
||||||
|
(gridSize.y + chunksY - 1) / chunksY,
|
||||||
|
(gridSize.z + chunksZ - 1) / chunksZ
|
||||||
|
);
|
||||||
|
|
||||||
|
for (int z = 0; z < chunksZ; z++) {
|
||||||
|
for (int y = 0; y < chunksY; y++) {
|
||||||
|
for (int x = 0; x < chunksX; x++) {
|
||||||
|
Vec3i minCorner = Vec3i(x * chunkSize.x, y * chunkSize.y, z * chunkSize.z);
|
||||||
|
Vec3i maxCorner = Vec3i(
|
||||||
|
std::min(minCorner.x + chunkSize.x, gridSize.x),
|
||||||
|
std::min(minCorner.y + chunkSize.y, gridSize.y),
|
||||||
|
std::min(minCorner.z + chunkSize.z, gridSize.z)
|
||||||
|
);
|
||||||
|
|
||||||
|
Chunk chunk(minCorner, maxCorner);
|
||||||
|
|
||||||
|
// Copy voxel data to chunk
|
||||||
|
for (int cz = minCorner.z; cz < maxCorner.z; cz++) {
|
||||||
|
for (int cy = minCorner.y; cy < maxCorner.y; cy++) {
|
||||||
|
for (int cx = minCorner.x; cx < maxCorner.x; cx++) {
|
||||||
|
Vec3i pos(cx, cy, cz);
|
||||||
|
int voxelIndex = cz * gridSize.x * gridSize.y + cy * gridSize.x + cx;
|
||||||
|
int chunkIndex = chunk.getVoxelIndex(pos);
|
||||||
|
|
||||||
|
if (voxelIndex >= 0 && voxelIndex < static_cast<int>(voxels.size()) &&
|
||||||
|
chunkIndex >= 0 && chunkIndex < static_cast<int>(chunk.voxels.size())) {
|
||||||
|
chunk.voxels[chunkIndex] = voxels[voxelIndex];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
chunks.push_back(chunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
double binSize = 1;
|
double binSize = 1;
|
||||||
VoxelGrid() : gridSize(0,0,0) {
|
VoxelGrid() : gridSize(0,0,0) {
|
||||||
@@ -449,6 +495,12 @@ public:
|
|||||||
|
|
||||||
VoxelGrid(int w, int h, int d) : gridSize(w,h,d) {
|
VoxelGrid(int w, int h, int d) : gridSize(w,h,d) {
|
||||||
voxels.resize(w * h * d);
|
voxels.resize(w * h * d);
|
||||||
|
|
||||||
|
// // Enable chunks if any dimension exceeds CHUNK_THRESHOLD
|
||||||
|
// if (w > CHUNK_THRESHOLD || h > CHUNK_THRESHOLD || d > CHUNK_THRESHOLD) {
|
||||||
|
// useChunks = true;
|
||||||
|
// createChunksFromVoxels();
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
bool serializeToFile(const std::string& filename);
|
bool serializeToFile(const std::string& filename);
|
||||||
@@ -456,26 +508,46 @@ public:
|
|||||||
static std::unique_ptr<VoxelGrid> deserializeFromFile(const std::string& filename);
|
static std::unique_ptr<VoxelGrid> deserializeFromFile(const std::string& filename);
|
||||||
|
|
||||||
Voxel& get(int x, int y, int z) {
|
Voxel& get(int x, int y, int z) {
|
||||||
|
if (useChunks) {
|
||||||
|
for (Chunk& chunk : chunks) {
|
||||||
|
if (chunk.inChunk(Vec3i(x, y, z))) {
|
||||||
|
Voxel* voxelPtr = chunk.getPtr(Vec3i(x, y, z));
|
||||||
|
if (voxelPtr) {
|
||||||
|
return *voxelPtr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return voxels[z * gridSize.x * gridSize.y + y * gridSize.x + x];
|
return voxels[z * gridSize.x * gridSize.y + y * gridSize.x + x];
|
||||||
}
|
}
|
||||||
|
|
||||||
const Voxel& get(int x, int y, int z) const {
|
const Voxel& get(int x, int y, int z) const {
|
||||||
|
if (useChunks) {
|
||||||
|
for (const Chunk& chunk : chunks) {
|
||||||
|
if (chunk.inChunk(Vec3i(x, y, z))) {
|
||||||
|
Voxel voxel = chunk.get(Vec3i(x, y, z));
|
||||||
|
return voxel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return voxels[z * gridSize.x * gridSize.y + y * gridSize.x + x];
|
return voxels[z * gridSize.x * gridSize.y + y * gridSize.x + x];
|
||||||
}
|
}
|
||||||
|
|
||||||
Voxel& get(const Vec3i& xyz) {
|
Voxel& get(const Vec3i& xyz) {
|
||||||
return voxels[xyz.z * gridSize.x * gridSize.y + xyz.y * gridSize.x + xyz.x];
|
return get(xyz.x, xyz.y, xyz.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Voxel& get(const Vec3i& xyz) const {
|
const Voxel& get(const Vec3i& xyz) const {
|
||||||
return voxels[xyz.z * gridSize.x * gridSize.y + xyz.y * gridSize.x + xyz.x];
|
return get(xyz.x, xyz.y, xyz.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
void resize(int newW, int newH, int newD) {
|
void resize(int newW, int newH, int newD) {
|
||||||
|
TIME_FUNCTION;
|
||||||
std::vector<Voxel> newVoxels(newW * newH * newD);
|
std::vector<Voxel> newVoxels(newW * newH * newD);
|
||||||
int copyW = std::min(static_cast<int>(gridSize.x), newW);
|
int copyW = std::min(static_cast<int>(gridSize.x), newW);
|
||||||
int copyH = std::min(static_cast<int>(gridSize.y), newH);
|
int copyH = std::min(static_cast<int>(gridSize.y), newH);
|
||||||
int copyD = std::min(static_cast<int>(gridSize.z), newD);
|
int copyD = std::min(static_cast<int>(gridSize.z), newD);
|
||||||
|
|
||||||
for (int z = 0; z < copyD; ++z) {
|
for (int z = 0; z < copyD; ++z) {
|
||||||
for (int y = 0; y < copyH; ++y) {
|
for (int y = 0; y < copyH; ++y) {
|
||||||
int oldRowStart = z * gridSize.x * gridSize.y + y * gridSize.x;
|
int oldRowStart = z * gridSize.x * gridSize.y + y * gridSize.x;
|
||||||
@@ -487,8 +559,18 @@ public:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
voxels = std::move(newVoxels);
|
voxels = std::move(newVoxels);
|
||||||
gridSize = Vec3i(newW, newH, newD);
|
gridSize = Vec3i(newW, newH, newD);
|
||||||
|
|
||||||
|
// Check if we need to enable chunks
|
||||||
|
if (newW > CHUNK_THRESHOLD || newH > CHUNK_THRESHOLD || newD > CHUNK_THRESHOLD) {
|
||||||
|
useChunks = true;
|
||||||
|
createChunksFromVoxels();
|
||||||
|
} else {
|
||||||
|
useChunks = false;
|
||||||
|
chunks.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void resize(Vec3i newsize) {
|
void resize(Vec3i newsize) {
|
||||||
@@ -512,8 +594,21 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
Voxel& v = get(pos);
|
Voxel& v = get(pos);
|
||||||
v.active = active; // std::clamp(active, 0.0f, 1.0f);
|
v.active = active;
|
||||||
v.color = color;
|
v.color = color;
|
||||||
|
|
||||||
|
// // Also update in chunks if using chunks
|
||||||
|
// if (useChunks) {
|
||||||
|
// for (Chunk& chunk : chunks) {
|
||||||
|
// if (chunk.inChunk(pos)) {
|
||||||
|
// Voxel newVoxel;
|
||||||
|
// newVoxel.active = active;
|
||||||
|
// newVoxel.color = color;
|
||||||
|
// chunk.set(pos, newVoxel);
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -560,7 +655,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (lv != cv && inGrid(cv) && visitedVoxel.size() < 10) {
|
while (lv != cv && inGrid(cv) && visitedVoxel.size() < 10) {
|
||||||
if (get(cv).active) {
|
const Voxel& cvv = get(cv);
|
||||||
|
|
||||||
|
if (cvv.active) {
|
||||||
visitedVoxel.push_back(cv);
|
visitedVoxel.push_back(cv);
|
||||||
}
|
}
|
||||||
if (tMax.x < tMax.y) {
|
if (tMax.x < tMax.y) {
|
||||||
@@ -606,7 +703,7 @@ public:
|
|||||||
float maxDist = std::sqrt(gridSize.lengthSquared()) * binSize;
|
float maxDist = std::sqrt(gridSize.lengthSquared()) * binSize;
|
||||||
frame outFrame(resolution.x, resolution.y, frame::colormap::RGB);
|
frame outFrame(resolution.x, resolution.y, frame::colormap::RGB);
|
||||||
std::vector<uint8_t> colorBuffer(resolution.x * resolution.y * 3);
|
std::vector<uint8_t> colorBuffer(resolution.x * resolution.y * 3);
|
||||||
#pragma omp parallel for
|
//#pragma omp parallel for
|
||||||
for (int y = 0; y < resolution.x; y++) {
|
for (int y = 0; y < resolution.x; y++) {
|
||||||
float v = (static_cast<float>(y) / static_cast<float>(resolution.x - 1)) - 0.5f;
|
float v = (static_cast<float>(y) / static_cast<float>(resolution.x - 1)) - 0.5f;
|
||||||
for (int x = 0; x < resolution.y; x++) {
|
for (int x = 0; x < resolution.y; x++) {
|
||||||
@@ -616,7 +713,9 @@ public:
|
|||||||
Vec3f rayEnd = cam.posfor.origin + rayDirWorld * maxDist;
|
Vec3f rayEnd = cam.posfor.origin + rayDirWorld * maxDist;
|
||||||
Vec3d rayStartGrid = cam.posfor.origin.toDouble() / binSize;
|
Vec3d rayStartGrid = cam.posfor.origin.toDouble() / binSize;
|
||||||
Vec3d rayEndGrid = rayEnd.toDouble() / binSize;
|
Vec3d rayEndGrid = rayEnd.toDouble() / binSize;
|
||||||
|
std::cout << "traversing";
|
||||||
voxelTraverse(rayStartGrid, rayEndGrid, hitVoxels);
|
voxelTraverse(rayStartGrid, rayEndGrid, hitVoxels);
|
||||||
|
std::cout << "traversed";
|
||||||
Vec3ui8 hitColor(10, 10, 255);
|
Vec3ui8 hitColor(10, 10, 255);
|
||||||
for (const Vec3i& voxelPos : hitVoxels) {
|
for (const Vec3i& voxelPos : hitVoxels) {
|
||||||
if (inGrid(voxelPos)) {
|
if (inGrid(voxelPos)) {
|
||||||
@@ -628,6 +727,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
std::cout << "hit done" << std::endl;
|
||||||
hitVoxels.clear();
|
hitVoxels.clear();
|
||||||
hitVoxels.shrink_to_fit();
|
hitVoxels.shrink_to_fit();
|
||||||
// Set pixel color in buffer
|
// Set pixel color in buffer
|
||||||
@@ -808,7 +908,6 @@ public:
|
|||||||
return outframes;
|
return outframes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
//#include "g3_serialization.hpp" needed to be usable
|
//#include "g3_serialization.hpp" needed to be usable
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user