From 3a183e0f92b2e22c348fdfb75cb056a7cbc6afbc Mon Sep 17 00:00:00 2001 From: Yggdrasil75 Date: Tue, 13 Jan 2026 07:51:03 -0500 Subject: [PATCH] bunch of fixes to the grid33 version --- makefile | 2 +- readme.md | 1 + tests/g3test3.cpp | 137 ++++++++++++++++++++++++++++++++++++++ util/grid/grid33.hpp | 81 +++++++++++++++++----- util/vectorlogic/vec3.hpp | 1 + 5 files changed, 206 insertions(+), 16 deletions(-) create mode 100644 readme.md create mode 100644 tests/g3test3.cpp diff --git a/makefile b/makefile index a426c7d..2a00990 100644 --- a/makefile +++ b/makefile @@ -16,7 +16,7 @@ PKG_FLAGS := $(LINUX_GL_LIBS) `pkg-config --static --cflags --libs glfw3` CXXFLAGS += $(PKG_FLAGS) # Source files -SRC := $(SRC_DIR)/g3test2.cpp +SRC := $(SRC_DIR)/g3test3.cpp #SRC := $(SRC_DIR)/g2chromatic2.cpp SRC += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp SRC += $(IMGUI_DIR)/backends/imgui_impl_glfw.cpp $(IMGUI_DIR)/backends/imgui_impl_opengl3.cpp diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..30d63aa --- /dev/null +++ b/readme.md @@ -0,0 +1 @@ +Thanks to Treexy, Amanatides, Woo, Occam, Incf, and so on. \ No newline at end of file diff --git a/tests/g3test3.cpp b/tests/g3test3.cpp new file mode 100644 index 0000000..2e93ca0 --- /dev/null +++ b/tests/g3test3.cpp @@ -0,0 +1,137 @@ +// test_voxel_render.cpp +#include "../util/grid/grid33.hpp" +#include "../util/output/bmpwriter.hpp" +#include +#include + +int main() { + // Initialize random number generator + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution<> pos_dist(-1.0, 1.0); + std::uniform_int_distribution<> color_dist(0, 255); + + // Create a voxel grid with 0.1 unit resolution + VoxelGrid voxelGrid(0.1); + + std::cout << "Placing 10 random colored voxels..." << std::endl; + + // Place 10 random colored voxels + for (int i = 0; i < 10; ++i) { + // Generate random position + double x = pos_dist(gen); + double y = pos_dist(gen); + double z = pos_dist(gen); + + // Generate random color + uint8_t r = static_cast(color_dist(gen)); + uint8_t g = static_cast(color_dist(gen)); + uint8_t b = static_cast(color_dist(gen)); + + Vec3d worldPos(x, y, z); + Vec3ui8 color(r, g, b); + + // Set voxel color + bool wasOn = voxelGrid.setVoxelColor(worldPos, color); + + std::cout << "Voxel " << i + 1 << ": " + << "Pos(" << x << ", " << y << ", " << z << ") " + << "Color(RGB:" << static_cast(r) << "," + << static_cast(g) << "," << static_cast(b) << ") " + << (wasOn ? "(overwritten)" : "(new)") << std::endl; + } + + std::cout << "\nMemory usage: " << voxelGrid.getMemoryUsage() << " bytes" << std::endl; + + // Render to BMP + std::cout << "\nRendering orthographic projection to BMP..." << std::endl; + + int width = 512; + int height = 512; + + // Create a buffer for the rendered image + std::vector imageBuffer; + + // Render with orthographic projection (view along Z axis) + voxelGrid.renderProjectedToRGBBuffer(imageBuffer, width, height, + Vec3d(0, 0, 1), // View direction (looking along Z) + Vec3d(0, 1, 0)); // Up direction + + std::cout << "Image buffer size: " << imageBuffer.size() << " bytes" << std::endl; + std::cout << "Expected size: " << (width * height * 3) << " bytes" << std::endl; + + // Save to BMP using BMPWriter + std::string filename = "voxel_render.bmp"; + + // Create a frame object from the buffer + frame renderFrame(width, height, frame::colormap::RGB); + renderFrame.setData(imageBuffer); + + // Save as BMP + if (BMPWriter::saveBMP(filename, renderFrame)) { + std::cout << "Successfully saved to: " << filename << std::endl; + + // Also save using the direct vector interface as backup + if (BMPWriter::saveBMP("voxel_render_direct.bmp", imageBuffer, width, height)) { + std::cout << "Also saved direct version: voxel_render_direct.bmp" << std::endl; + } + } else { + std::cout << "Failed to save BMP!" << std::endl; + + // Try alternative save method + std::cout << "Trying alternative save method..." << std::endl; + + // Convert to Vec3ui8 format + std::vector pixelsVec3; + pixelsVec3.reserve(width * height); + + for (size_t i = 0; i < imageBuffer.size(); i += 3) { + pixelsVec3.push_back(Vec3ui8( + imageBuffer[i], + imageBuffer[i + 1], + imageBuffer[i + 2] + )); + } + + if (BMPWriter::saveBMP("voxel_render_vec3.bmp", pixelsVec3, width, height)) { + std::cout << "Saved Vec3ui8 version: voxel_render_vec3.bmp" << std::endl; + } else { + std::cout << "All save methods failed!" << std::endl; + } + } + + // Test accessor functionality + std::cout << "\nTesting accessor functionality..." << std::endl; + auto accessor = voxelGrid.createAccessor(); + + // Try to retrieve one of the voxels + Vec3d testPos(0.0, 0.0, 0.0); // Center point + Vec3i testCoord = voxelGrid.posToCoord(testPos); + + Vec3ui8* retrievedColor = voxelGrid.getVoxelColor(testPos); + if (retrievedColor) { + std::cout << "Found voxel at center: Color(RGB:" + << static_cast(retrievedColor->x) << "," + << static_cast(retrievedColor->y) << "," + << static_cast(retrievedColor->z) << ")" << std::endl; + } else { + std::cout << "No voxel found at center position" << std::endl; + } + + // Iterate through all voxels using forEachCell + std::cout << "\nIterating through all voxels:" << std::endl; + int voxelCount = 0; + voxelGrid.forEachCell([&](const Vec3ui8& color, const Vec3i& coord) { + Vec3d pos = voxelGrid.Vec3iToPos(coord); + std::cout << "Voxel " << ++voxelCount << ": " + << "Coord(" << coord.x << ", " << coord.y << ", " << coord.z << ") " + << "WorldPos(" << pos.x << ", " << pos.y << ", " << pos.z << ") " + << "Color(RGB:" << static_cast(color.x) << "," + << static_cast(color.y) << "," << static_cast(color.z) << ")" + << std::endl; + }); + + std::cout << "\nTotal voxels in grid: " << voxelCount << std::endl; + + return 0; +} \ No newline at end of file diff --git a/util/grid/grid33.hpp b/util/grid/grid33.hpp index 5608bf6..680c621 100644 --- a/util/grid/grid33.hpp +++ b/util/grid/grid33.hpp @@ -45,9 +45,7 @@ inline uint32_t CountOn(uint64_t v) // Software Implementation v = v - ((v >> 1) & uint64_t(0x5555555555555555)); v = (v & uint64_t(0x3333333333333333)) + ((v >> 2) & uint64_t(0x3333333333333333)); - v = (((v + (v >> 4)) & uint64_t(0xF0F0F0F0F0F0F0F)) * - uint64_t(0x101010101010101)) >> - 56; + v = (((v + (v >> 4)) & uint64_t(0xF0F0F0F0F0F0F0F)) * uint64_t(0x101010101010101)) >> 56; #endif return static_cast(v); } @@ -70,7 +68,7 @@ private: } uint32_t findNextOn(uint32_t start) const { - uint32_t n start >> 6; + uint32_t n = start >> 6; if (n >= WORD_COUNT) { return SIZE; } @@ -126,7 +124,7 @@ public: Iterator& operator=(const Iterator&) = default; - uint32_t opeator*() const { + uint32_t operator*() const { return mPos; } @@ -138,7 +136,7 @@ public: mPos = mParent -> findNextOn(mPos + 1); return *this; } - } + }; Mask() { for (uint32_t i = 0; i < WORD_COUNT; ++i) { @@ -269,6 +267,7 @@ public: template class Grid { +public: constexpr static int DIM = 1 << Log2DIM; constexpr static int SIZE = DIM * DIM * DIM; std::array data; @@ -277,8 +276,6 @@ class Grid { template class VoxelGrid { -private: - public: constexpr static int32_t Log2N = INNER_BITS + LEAF_BITS; using LeafGrid = Grid; @@ -310,7 +307,7 @@ public: return total_size; } - static inline Veci PosToCoord(float x, float y, float z) { + static inline Vec3i PosToCoord(float x, float y, float z) { // union VI { // __m128i m; // int32_t i[4]; @@ -333,7 +330,7 @@ public: return pos.floorToI(); } - Vec3d Vec3ioPos(const Vec3i &coord) { + Vec3d Vec3iToPos(const Vec3i& coord) const { return (coord.toDouble() * resolution) + half_resolution; } @@ -342,7 +339,10 @@ public: constexpr static int32_t MASK_LEAF = ((1 << LEAF_BITS) - 1); constexpr static int32_t MASK_INNER = ((1 << INNER_BITS) - 1); for (auto& map_it : root_map) { - const auto& [xA, yA, zA] = (map_it.first); + const Vec3i& root_coord = map_it.first; + int32_t xA = root_coord.x; + int32_t yA = root_coord.y; + int32_t zA = root_coord.z; InnerGrid& inner_grid = map_it.second; auto& mask2 = inner_grid.mask; for (auto inner_it = mask2.beginOn(); inner_it; ++inner_it) { @@ -364,7 +364,6 @@ public: } } - class Accessor { private: RootMap &root_; @@ -383,7 +382,7 @@ public: if (root_key != prev_root_coord_ || !prev_inner_ptr_) { auto root_it = root_.find(root_key); if (root_it == root_.end()) { - root_it = root_insert({root_key, InnerGrid()}).first; + root_it = root_.insert({root_key, InnerGrid()}).first; } inner_ptr = &(root_it->second); @@ -426,7 +425,7 @@ public: } const uint32_t inner_index = getInnerIndex(coord); - auto& inner_data - inner_ptr->data[inner_index]; + auto& inner_data = inner_ptr->data[inner_index]; if (!inner_ptr->mask.isOn(inner_index)) { return nullptr; @@ -452,7 +451,7 @@ public: const LeafGrid* lastLeafGrid() const { return prev_leaf_ptr_; } - } + }; Accessor createAccessor() { return Accessor(root_map); @@ -488,4 +487,56 @@ public: ((coord.z & MASK) << (LEAF_BITS * 2)); // clang-format on } + + bool setVoxelColor(const Vec3d& worldPos, const Vec3ui8& color) { + Vec3i coord = posToCoord(worldPos); + Accessor accessor = createAccessor(); + return accessor.setValue(coord, color); + } + + Vec3ui8* getVoxelColor(const Vec3d& worldPos) { + Vec3i coord = posToCoord(worldPos); + Accessor accessor = createAccessor(); + return accessor.value(coord); + } + + // Render with projection (simple orthographic projection) + void renderProjectedToRGBBuffer(std::vector& buffer, int width, int height, const Vec3d& viewDir = Vec3d(0, 0, 1), + const Vec3d& upDir = Vec3d(0, 1, 0)) { + // Clear buffer + buffer.clear(); + buffer.resize(width * height * 3, 0); + + // Create view matrix (simplified orthographic projection) + Vec3d view = viewDir.normalized(); + Vec3d up = upDir.normalized(); + Vec3d right = view.cross(up).normalized(); + up = right.cross(view).normalized(); // Re-orthogonalize + + // For each voxel, project to screen + forEachCell([&](const Vec3ui8& color, const Vec3i& coord) { + // Convert voxel coordinate to world position + Vec3d worldPos = Vec3iToPos(coord); + + // Simple orthographic projection: drop view direction component + double xProj = worldPos.dot(right); + double yProj = worldPos.dot(up); + + // Normalize to pixel coordinates (assuming unit size) + int px = static_cast((xProj + 0.5) * width); + int py = static_cast((yProj + 0.5) * height); + + // Clamp to image bounds + if (px >= 0 && px < width && py >= 0 && py < height) { + int index = (py * width + px) * 3; + + Vec3ui8 finalColor = color; + + // Write RGB + buffer[index] = finalColor.x; // R + buffer[index + 1] = finalColor.y; // G + buffer[index + 2] = finalColor.z; // B + } + }); + } }; \ No newline at end of file diff --git a/util/vectorlogic/vec3.hpp b/util/vectorlogic/vec3.hpp index 6c7a9fe..02bfcd3 100644 --- a/util/vectorlogic/vec3.hpp +++ b/util/vectorlogic/vec3.hpp @@ -6,6 +6,7 @@ #include #include #include +#include "vec2.hpp" template class Vec3 {