From c92b5dc2031fa8a7720076e151f1e5a58bb0bc6d Mon Sep 17 00:00:00 2001 From: Yggdrasil75 Date: Wed, 31 Dec 2025 10:49:52 -0500 Subject: [PATCH] my grid should work. just need minor tests --- makefile | 2 +- tests/g3test2.cpp | 154 ++++++++++++++++++++++++++++++++++++++ util/grid/grid3.hpp | 96 +++++++++++++++++++++++- util/vecmat/mat4.hpp | 31 -------- util/vectorlogic/vec3.hpp | 17 +---- 5 files changed, 251 insertions(+), 49 deletions(-) create mode 100644 tests/g3test2.cpp diff --git a/makefile b/makefile index 99a8037..a426c7d 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)/g3chromatic.cpp +SRC := $(SRC_DIR)/g3test2.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/tests/g3test2.cpp b/tests/g3test2.cpp new file mode 100644 index 0000000..fe3c27b --- /dev/null +++ b/tests/g3test2.cpp @@ -0,0 +1,154 @@ +// main.cpp - Noise Grid Generator and Renderer +#include +#include +#include +#include "../util/grid/grid3.hpp" +#include "../util/output/bmpwriter.hpp" +#include "../util/noise/pnoise2.hpp" + +// Constants +const size_t GRID_SIZE = 1024; +const size_t RENDER_WIDTH = 512; +const size_t RENDER_HEIGHT = 512; + +// Function to generate grayscale noise grid +void generateNoiseGrid(VoxelGrid& grid, PNoise2& noise) { + std::cout << "Generating 1024x1024x1024 noise grid..." << std::endl; + + // Generate Perlin noise in the grid + for (size_t z = 0; z < GRID_SIZE; ++z) { + if (z % 64 == 0) { + std::cout << "Processing layer " << z << " of " << GRID_SIZE << std::endl; + } + + for (size_t y = 0; y < GRID_SIZE; ++y) { + for (size_t x = 0; x < GRID_SIZE; ++x) { + // Create 3D noise coordinates (scaled for better frequency) + float scale = 0.05f; // Controls noise frequency + float noiseVal = noise.permute(Vec3f(x * scale, y * scale, z * scale)); + + // Convert from [-1, 1] to [0, 1] range + float normalizedNoise = (noiseVal + 1.0f) * 0.5f; + + // Apply threshold to make some voxels "active" + // Higher threshold = sparser voxels + float threshold = 0.3f; + float active = (normalizedNoise > threshold) ? normalizedNoise : 0.0f; + + // Create grayscale color based on noise value + uint8_t grayValue = static_cast(normalizedNoise * 255); + Vec3ui8 color(grayValue, grayValue, grayValue); + + grid.set(x, y, z, active, color); + } + } + } + + std::cout << "Noise grid generation complete!" << std::endl; +} + +// Function to render grid from a specific viewpoint +bool renderView(const std::string& filename, VoxelGrid& grid, const Vec3f& position, + const Vec3f& direction, const Vec3f& up = Vec3f(0, 1, 0)) { + + Camera cam(position, direction, up); + + std::vector renderBuffer; + size_t width = RENDER_WIDTH; + size_t height = RENDER_HEIGHT; + + // Render the view + grid.renderOut(renderBuffer, width, height, cam); + + // Save to BMP + bool success = BMPWriter::saveBMP(filename, renderBuffer, width, height); + + if (success) { + std::cout << "Saved: " << filename << std::endl; + } else { + std::cout << "Failed to save: " << filename << std::endl; + } + + return success; +} + +int main() { + try { + std::cout << "=== Noise Grid Generator and Renderer ===" << std::endl; + std::cout << "Grid Size: 1024x1024x1024 voxels" << std::endl; + std::cout << "Render Size: 512x512 pixels" << std::endl; + + // Initialize Perlin noise generator + PNoise2 noise; + + // Create voxel grid + VoxelGrid grid(GRID_SIZE, GRID_SIZE, GRID_SIZE); + + // Generate noise grid + generateNoiseGrid(grid, noise); + + // Define center of the grid for camera positioning + Vec3f gridCenter(GRID_SIZE / 2.0f, GRID_SIZE / 2.0f, GRID_SIZE / 2.0f); + + // Camera distance from center (outside the grid) + float cameraDistance = GRID_SIZE * 2.0f; + + // Render from 4 cardinal directions (looking at center) + std::cout << "\nRendering cardinal views..." << std::endl; + + // North view (looking from positive Z towards center) + renderView("north_view.bmp", grid, + gridCenter + Vec3f(0, 0, cameraDistance), + Vec3f(0, 0, -1)); // Look towards negative Z + + // South view (looking from negative Z towards center) + renderView("south_view.bmp", grid, + gridCenter + Vec3f(0, 0, -cameraDistance), + Vec3f(0, 0, 1)); // Look towards positive Z + + // East view (looking from positive X towards center) + renderView("east_view.bmp", grid, + gridCenter + Vec3f(cameraDistance, 0, 0), + Vec3f(-1, 0, 0)); // Look towards negative X + + // West view (looking from negative X towards center) + renderView("west_view.bmp", grid, + gridCenter + Vec3f(-cameraDistance, 0, 0), + Vec3f(1, 0, 0)); // Look towards positive X + + // Zenith view (looking from above) + std::cout << "\nRendering zenith and nadir views..." << std::endl; + renderView("zenith_view.bmp", grid, + gridCenter + Vec3f(0, cameraDistance, 0), + Vec3f(0, -1, 0), // Look down + Vec3f(0, 0, -1)); // Adjust up vector for proper orientation + + // Nadir view (looking from below) + renderView("nadir_view.bmp", grid, + gridCenter + Vec3f(0, -cameraDistance, 0), + Vec3f(0, 1, 0), // Look up + Vec3f(0, 0, 1)); // Adjust up vector + + // Optional: Create a front view (alternative to north) + renderView("front_view.bmp", grid, + gridCenter + Vec3f(0, 0, cameraDistance), + Vec3f(0, 0, -1), + Vec3f(0, 1, 0)); + + std::cout << "\n=== All renders complete! ===" << std::endl; + std::cout << "Generated BMP files:" << std::endl; + std::cout << "1. north_view.bmp - Looking from positive Z" << std::endl; + std::cout << "2. south_view.bmp - Looking from negative Z" << std::endl; + std::cout << "3. east_view.bmp - Looking from positive X" << std::endl; + std::cout << "4. west_view.bmp - Looking from negative X" << std::endl; + std::cout << "5. zenith_view.bmp - Looking from above" << std::endl; + std::cout << "6. nadir_view.bmp - Looking from below" << std::endl; + std::cout << "7. front_view.bmp - Alternative front view" << std::endl; + + return 0; + + } catch (const std::exception& e) { + std::cerr << "Error: " << e.what() << std::endl; + return 1; + } +} \ No newline at end of file diff --git a/util/grid/grid3.hpp b/util/grid/grid3.hpp index b374a23..7997456 100644 --- a/util/grid/grid3.hpp +++ b/util/grid/grid3.hpp @@ -18,10 +18,49 @@ struct Voxel { Vec3ui8 color; }; +struct Camera { + Ray3f posfor; + Vec3f up; + float fov; + Camera(Vec3f pos, Vec3f viewdir, Vec3f up, float fov = 80) : posfor(Ray3f(pos, viewdir)), up(up), fov(fov) {} +}; + class VoxelGrid { private: size_t width, height, depth; std::vector voxels; + + static Mat4f lookAt(Vec3f const& eye, Vec3f const& center, Vec3f const& up) { + Vec3f const f = (center - eye).normalized(); + Vec3f const s = f.cross(up).normalized(); + Vec3f const u = s.cross(f); + + Mat4f Result = Mat4f::identity(); + Result(0, 0) = s.x; + Result(1, 0) = s.y; + Result(2, 0) = s.z; + Result(3, 0) = -s.dot(eye); + Result(0, 1) = u.x; + Result(1, 1) = u.y; + Result(2, 1) = u.z; + Result(3, 1) = -u.dot(eye); + Result(0, 2) = -f.x; + Result(1, 2) = -f.y; + Result(2, 2) = -f.z; + Result(3, 2) = f.dot(eye); + return Result; + } + + static Mat4f perspective(float fovy, float aspect, float zNear, float zfar) { + float const tanhalfF = tan(fovy / 2); + Mat4f Result = 0; + Result(0,0) = 1 / (aspect * tanhalfF); + Result(1,1) = 1 / tanhalfF; + Result(2,2) = zfar / (zNear - zfar); + Result(2,3) = -1; + Result(3,2) = -(zfar * zNear) / (zfar - zNear); + return Result; + } public: VoxelGrid(size_t w, size_t h, size_t d) : width(w), height(h), depth(d) { voxels.resize(w * h * d); @@ -76,6 +115,22 @@ public: return (voxl >= 0 && voxl.x < width && voxl.y < height && voxl.z < depth); } + Vec3f perPixelRayDir(size_t x, size_t y, size_t imgWidth, size_t imgHeight, const Camera& cam) const { + float normedX = (x + 0.5) / imgWidth * 2 - 1; + float normedY = 1 - (y+0.5) / imgHeight * 2; + float aspect = imgWidth / imgHeight; + + float fovRad = cam.fov * M_PI / 180; + float scale = tan(fovRad * 0.5); + Vec3f rayDirCam = Vec3f(normedX * aspect * scale, normedY * scale, -1).normalized(); + Vec3f eye = cam.posfor.origin; + Vec3f center = eye + cam.posfor.direction; + Mat4f viewMat = lookAt(eye, center, cam.up); + Mat4f invViewMat = viewMat.inverse(); + Vec3f rayDirWorld = invViewMat.transformDirection(rayDirCam); + return rayDirWorld.normalized(); + } + bool rayCast(const Ray3f& ray, float maxDistance, Vec3f hitPos, Vec3f hitNormal, Vec3f& hitColor) { hitColor = Vec3f(0,0,0); Vec3f rayDir = ray.direction; @@ -107,7 +162,6 @@ public: current voxel. */ - float tEntry = 0.0; Vec3f tBMin; Vec3f tBMax; tBMin.x = (0.0 - rayOrigin.x) / rayDir.x; @@ -186,6 +240,46 @@ public: } return hit; } + + size_t getWidth() const { + return width; + } + size_t getHeight() const { + return height; + } + size_t getDepth() const { + return depth; + } + + void renderOut(std::vector& output, size_t& outwidth, size_t& outheight, const Camera& cam) { + output.resize(outwidth * outheight * 3); + Vec3f backgroundColor(0.1f, 0.1f, 0.1f); + float maxDistance = std::sqrt(width*width + height*height + depth*depth) * 2.0f; + + for (size_t y = 0; y < outheight; y++) { + for (size_t x = 0; x < outwidth; x++) { + Vec3f rayDir = perPixelRayDir(x, y, outwidth, outheight, cam); + Ray3f ray(cam.posfor.origin, rayDir); + Vec3f hitPos; + Vec3f hitNorm; + Vec3f hitColor; + bool hit = rayCast(ray, maxDistance, hitPos, hitNorm, hitColor); + + Vec3f finalColor; + if (!hit) { + finalColor = backgroundColor; + } else { + finalColor = hitColor; + } + + finalColor = finalColor.clamp(0, 1); + size_t pixelIndex = (y * outwidth + x) * 3; + output[pixelIndex + 0] = static_cast(finalColor.x * 255); + output[pixelIndex + 1] = static_cast(finalColor.y * 255); + output[pixelIndex + 2] = static_cast(finalColor.z * 255); + } + } + } }; #endif diff --git a/util/vecmat/mat4.hpp b/util/vecmat/mat4.hpp index c69475c..d232019 100644 --- a/util/vecmat/mat4.hpp +++ b/util/vecmat/mat4.hpp @@ -320,36 +320,5 @@ inline Mat4 operator*(T scalar, const Mat4& mat) { using Mat4f = Mat4; using Mat4d = Mat4; -Mat4f lookAt(Vec3f const& eye, Vec3f const& center, Vec3f const& up) { - Vec3f const f = (center - eye).normalized(); - Vec3f const s = f.cross(up).normalized(); - Vec3f const u = s.cross(f); - - Mat4f Result = Mat4f::identity(); - Result(0, 0) = s.x; - Result(1, 0) = s.y; - Result(2, 0) = s.z; - Result(3, 0) = -s.dot(eye); - Result(0, 1) = u.x; - Result(1, 1) = u.y; - Result(2, 1) = u.z; - Result(3, 1) = -u.dot(eye); - Result(0, 2) = -f.x; - Result(1, 2) = -f.y; - Result(2, 2) = -f.z; - Result(3, 2) = f.dot(eye); - return Result; -} - -Mat4f perspective(float fovy, float aspect, float zNear, float zfar) { - float const tanhalfF = tan(fovy / 2); - Mat4f Result = 0; - Result(0,0) = 1 / (aspect * tanhalfF); - Result(1,1) = 1 / tanhalfF; - Result(2,2) = zfar / (zNear - zfar); - Result(2,3) = -1; - Result(3,2) = -(zfar * zNear) / (zfar - zNear); - return Result; -} #endif \ No newline at end of file diff --git a/util/vectorlogic/vec3.hpp b/util/vectorlogic/vec3.hpp index f6e819e..f3de94d 100644 --- a/util/vectorlogic/vec3.hpp +++ b/util/vectorlogic/vec3.hpp @@ -471,22 +471,7 @@ Vec3 mix(const Vec3& a, const Vec3& b, const Vec3& mask) { mask.x ? b.x : a.x, mask.y ? b.y : a.y, mask.z ? b.z : a.z - ) -} - - -template -std::pair, Vec3> multiMix(const Vec3& a, const Vec3& b, const Vec3& c, const Vec3& d, const Vec3& mask) { - outa = Vec3( - mask.x ? b.x : a.x, - mask.y ? b.y : a.y, - mask.z ? b.z : a.z - ) - outb = Vec3( - mask.x ? d.x : c.x, - mask.y ? d.y : c.y, - mask.z ? d.z : c.z - ) + ); } #endif \ No newline at end of file