pushing some more features to chunks before implementing.

This commit is contained in:
Yggdrasil75
2026-01-19 09:09:05 -05:00
parent a914e7a1f7
commit 835ac45c9a

View File

@@ -4,6 +4,8 @@
#include <unordered_map> #include <unordered_map>
#include <fstream> #include <fstream>
#include <cstring> #include <cstring>
#include <memory>
#include <array>
#include "../vectorlogic/vec2.hpp" #include "../vectorlogic/vec2.hpp"
#include "../vectorlogic/vec3.hpp" #include "../vectorlogic/vec3.hpp"
#include "../vectorlogic/vec4.hpp" #include "../vectorlogic/vec4.hpp"
@@ -16,6 +18,7 @@
#include "../basicdefines.hpp" #include "../basicdefines.hpp"
//constexpr char magic[4] = {'Y', 'G', 'G', '3'}; //constexpr char magic[4] = {'Y', 'G', 'G', '3'};
static constexpr int CHUNK_THRESHOLD = 16; //at this size, subdivide.
Mat4f lookAt(const Vec3f& eye, const Vec3f& center, const Vec3f& up) { Mat4f lookAt(const Vec3f& eye, const Vec3f& center, const Vec3f& up) {
Vec3f const f = (center - eye).normalized(); Vec3f const f = (center - eye).normalized();
@@ -126,12 +129,20 @@ struct Chunk {
Vec3i minCorner; Vec3i minCorner;
Vec3i maxCorner; Vec3i maxCorner;
int depth; int depth;
bool dirty = false;
Chunk() : depth(0) {} Chunk(Vec3i minCorner, Vec3i maxCorner, int depth = 0)
: minCorner(minCorner), maxCorner(maxCorner), depth(depth) {
Chunk(Vec3i minCorner, Vec3i maxCorner, int depth = 0) : minCorner(minCorner), maxCorner(maxCorner), depth(depth) {
chunkSize = maxCorner - minCorner; chunkSize = maxCorner - minCorner;
voxels.resize(chunkSize.x * chunkSize.y * chunkSize.z);
// Check if we need to subdivide based on CHUNK_THRESHOLD
if (chunkSize.x > CHUNK_THRESHOLD || chunkSize.y > CHUNK_THRESHOLD || chunkSize.z > CHUNK_THRESHOLD) {
// This chunk is too large, need to subdivide
subdivide();
} else {
// This chunk is small enough, create voxels
voxels.resize(chunkSize.x * chunkSize.y * chunkSize.z);
}
} }
bool inChunk(Vec3i pos) const { bool inChunk(Vec3i pos) const {
@@ -139,28 +150,51 @@ struct Chunk {
return false; return false;
} }
bool setRecurse(Vec3i pos, Voxel newVox) { bool set(Vec3i pos, Voxel newVox) {
if (!inChunk(pos)) return false; if (!inChunk(pos)) return false;
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;
return true; return true;
updateAverages();
} }
return false; return false;
} }
for (Chunk& child : children) { for (Chunk& child : children) {
if (child.set(pos, newVox)) { if (child.set(pos, newVox)) {
dirty = true;
return true; return true;
} }
} }
return false; return false;
} }
Voxel get(Vec3i pos, int maxDepth = 0) const { Voxel* getPtr(Vec3i pos, int maxDepth = 0) {
if (!inChunk(pos)) {
return nullptr;
}
if (children.empty() || (maxDepth > 0 && depth >= maxDepth)) {
int index = getVoxelIndex(pos);
if (index >= 0 && index < static_cast<int>(voxels.size())) {
return &voxels[index];
}
return nullptr;
}
for (Chunk& child : children) {
if (child.inChunk(pos)) {
return child.getPtr(pos, maxDepth);
}
}
return nullptr;
}
Voxel get(Vec3i pos, int maxDepth = 0) {
if (!inChunk(pos)) { if (!inChunk(pos)) {
return Voxel(); return Voxel();
} }
@@ -168,6 +202,38 @@ struct Chunk {
if (children.empty() || (maxDepth > 0 && depth >= maxDepth)) { if (children.empty() || (maxDepth > 0 && depth >= maxDepth)) {
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())) {
if (dirty) {
updateAveragesRecursive();
}
return voxels[index];
}
return Voxel();
} else if (maxDepth > 0 && depth >= maxDepth) {
return Voxel(weight, active, alpha, color);
}
for (Chunk& child : children) {
if (child.inChunk(pos)) {
if (dirty) {
updateAveragesRecursive();
}
return child.get(pos, maxDepth);
}
}
return Voxel();
}
const Voxel get(const Vec3i& pos, int maxDepth = 0) const {
if (!inChunk(pos)) {
return Voxel();
}
if (children.empty() || (maxDepth > 0 && depth >= maxDepth)) {
int index = getVoxelIndex(pos);
if (index >= 0 && index < static_cast<int>(voxels.size())) {
if (dirty) {
std::cout << "need to clean chunk" << std::endl;
}
return voxels[index]; return voxels[index];
} }
return Voxel(); return Voxel();
@@ -183,18 +249,6 @@ struct Chunk {
return Voxel(); return Voxel();
} }
bool set(Vec3i pos, Voxel newVox) {
if (inChunk(pos)) {
int index = getVoxelIndex(pos);
voxels[index] = newVox;
if (newVox.active) {
updateAveragesRecursive();
return true;
}
}
return false;
}
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 +
@@ -245,6 +299,7 @@ struct Chunk {
color = Vec3ui8(0, 0, 0); color = Vec3ui8(0, 0, 0);
active = false; active = false;
} }
dirty = false;
} }
void updateAveragesRecursive() { void updateAveragesRecursive() {
@@ -294,6 +349,7 @@ struct Chunk {
active = false; active = false;
} }
} }
dirty = false;
} }
void subdivide(int numChildrenPerAxis = 2) { void subdivide(int numChildrenPerAxis = 2) {
@@ -376,7 +432,9 @@ struct Chunk {
class VoxelGrid { class VoxelGrid {
private: private:
Vec3i gridSize; Vec3i gridSize;
std::vector<Chunk> chunks;
std::vector<Voxel> voxels; std::vector<Voxel> voxels;
bool useChunks = false;
bool meshDirty = true; bool meshDirty = true;
float radians(float rads) { float radians(float rads) {
@@ -618,7 +676,11 @@ public:
std::cout << "Active voxels: " << activeVoxels << std::endl; std::cout << "Active voxels: " << activeVoxels << std::endl;
std::cout << "Inactive voxels: " << (totalVoxels - activeVoxels) << std::endl; std::cout << "Inactive voxels: " << (totalVoxels - activeVoxels) << std::endl;
std::cout << "Active percentage: " << activePercentage << "%" << std::endl; std::cout << "Active percentage: " << activePercentage << "%" << std::endl;
std::cout << "Memory usage (approx): " << (voxels.size() * sizeof(Voxel)) / 1024 << " KB" << std::endl; std::cout << "Memory usage (approx): " << (voxels.size() * sizeof(Voxel)) / 1024 << " KB" << std::endl; //needs to be updated to include chunks
std::cout << "Using chunks: " << (useChunks ? "Yes" : "No") << std::endl;
if (useChunks) {
std::cout << "Number of chunks: " << chunks.size() << std::endl;
}
std::cout << "============================" << std::endl; std::cout << "============================" << std::endl;
} }
@@ -662,53 +724,6 @@ private:
} }
return Vec3f(0, 1, 0); // Default up normal return Vec3f(0, 1, 0); // Default up normal
} }
Vertex getEdgeVertex(int edge, int x, int y, int z, float isoLevel = 0.5f) const {
// Edge vertices based on Marching Cubes algorithm
static const std::array<std::array<int, 2>, 12> edgeVertices = {{
{0, 1}, {1, 2}, {2, 3}, {3, 0}, // Bottom edges
{4, 5}, {5, 6}, {6, 7}, {7, 4}, // Top edges
{0, 4}, {1, 5}, {2, 6}, {3, 7} // Vertical edges
}};
static const std::array<Vec3f, 8> cubeVertices = {{
Vec3f(0, 0, 0), Vec3f(1, 0, 0), Vec3f(1, 1, 0), Vec3f(0, 1, 0),
Vec3f(0, 0, 1), Vec3f(1, 0, 1), Vec3f(1, 1, 1), Vec3f(0, 1, 1)
}};
const auto& [v1, v2] = edgeVertices[edge];
const Vec3f& p1 = cubeVertices[v1];
const Vec3f& p2 = cubeVertices[v2];
// For binary voxels, we can just use midpoint
Vec3f position = (p1 + p2) * 0.5f;
// Convert to world coordinates
position = position + Vec3f(x, y, z);
position = position * binSize;
// Get colors from neighboring voxels
Vec3ui8 color1 = get(x, y, z).color;
Vec3ui8 color2 = color1;
// Determine which neighboring voxel to use for the second color
// This is simplified - in a full implementation, you'd interpolate based on values
if (v2 == 1) color2 = get(x+1, y, z).color;
else if (v2 == 3) color2 = get(x, y+1, z).color;
else if (v2 == 4) color2 = get(x, y, z+1).color;
// Interpolate color
Vec3ui8 color(
static_cast<uint8_t>((color1.x + color2.x) / 2),
static_cast<uint8_t>((color1.y + color2.y) / 2),
static_cast<uint8_t>((color1.z + color2.z) / 2)
);
// Calculate normal (simplified)
Vec3f normal = calculateVoxelNormal(x, y, z);
return Vertex(position, normal, color);
}
public: public:
std::vector<frame> genSlices(frame::colormap colorFormat = frame::colormap::RGB) const { std::vector<frame> genSlices(frame::colormap colorFormat = frame::colormap::RGB) const {
@@ -740,7 +755,7 @@ public:
for (int y = 0; y < gridSize.y; y++) { for (int y = 0; y < gridSize.y; y++) {
int yMult = layerMult + (y * gridSize.x); int yMult = layerMult + (y * gridSize.x);
for (int x = 0; x < gridSize.x; x++) { for (int x = 0; x < gridSize.x; x++) {
int vidx = yMult+x; int vidx = yMult + x;
int pidx = (y * gridSize.x + x) * colors; int pidx = (y * gridSize.x + x) * colors;
Voxel cv = voxels[vidx]; Voxel cv = voxels[vidx];
Vec3ui8 cvColor; Vec3ui8 cvColor;