From acba629774bc23a4474eb1bd88a41bfd0b862687 Mon Sep 17 00:00:00 2001 From: Yggdrasil75 Date: Fri, 16 Jan 2026 13:37:13 -0500 Subject: [PATCH] noise features, fixed some grid stuff. --- tests/g3test2.cpp | 36 ++++++++++--- util/grid/grid3.hpp | 83 +++++++++++++++++++++++++++++ util/noise/pnoise2.hpp | 115 ++++++++++++++++++++++++++++++++++++++++- voxel_render.png | Bin 842 -> 0 bytes 4 files changed, 226 insertions(+), 8 deletions(-) delete mode 100644 voxel_render.png diff --git a/tests/g3test2.cpp b/tests/g3test2.cpp index d349544..4519047 100644 --- a/tests/g3test2.cpp +++ b/tests/g3test2.cpp @@ -22,8 +22,8 @@ struct defaults { int outWidth = 512; int outHeight = 512; - int gridWidth = 64; - int gridHeight = 64; + int gridWidth = 512; + int gridHeight = 512; int gridDepth = 64; float fps = 30.0f; PNoise2 noise = PNoise2(42); @@ -51,6 +51,18 @@ void setup(defaults config, VoxelGrid& grid) { uint8_t threshold = 0.1 * 255; grid.resize(config.gridWidth, config.gridHeight, config.gridDepth); std::cout << "Generating grid of size " << config.gridWidth << "x" << config.gridHeight << "x" << config.gridDepth << std::endl; + size_t rValw = config.gridWidth / 64; + size_t rValh = config.gridHeight / 64; + size_t rVald = config.gridDepth / 64; + size_t gValw = config.gridWidth / 32; + size_t gValh = config.gridHeight / 32; + size_t gVald = config.gridDepth / 32; + size_t bValw = config.gridWidth / 16; + size_t bValh = config.gridHeight / 16; + size_t bVald = config.gridDepth / 16; + size_t aValw = config.gridWidth / 8; + size_t aValh = config.gridHeight / 8; + size_t aVald = config.gridDepth / 8; for (int z = 0; z < config.gridDepth; ++z) { if (z % 64 == 0) { std::cout << "Processing layer " << z << " of " << config.gridDepth << std::endl; @@ -58,10 +70,10 @@ void setup(defaults config, VoxelGrid& grid) { for (int y = 0; y < config.gridHeight; ++y) { for (int x = 0; x < config.gridWidth; ++x) { - uint8_t r = config.noise.permute(Vec3f(static_cast(x) / config.gridWidth / 64, static_cast(y) / config.gridHeight / 64, static_cast(z) / config.gridDepth / 64)) * 255; - uint8_t g = config.noise.permute(Vec3f(static_cast(x) / config.gridWidth / 32, static_cast(y) / config.gridHeight / 32, static_cast(z) / config.gridDepth / 32)) * 255; - uint8_t b = config.noise.permute(Vec3f(static_cast(x) / config.gridWidth / 16, static_cast(y) / config.gridHeight / 16, static_cast(z) / config.gridDepth / 16)) * 255; - uint8_t a = config.noise.permute(Vec3f(static_cast(x) / config.gridWidth / 8 , static_cast(y) / config.gridHeight / 8 , static_cast(z) / config.gridDepth / 8)) * 255; + uint8_t r = config.noise.permute(Vec3f(static_cast(x) * rValw, static_cast(y) * rValh, static_cast(z) * rVald)) * 255; + uint8_t g = config.noise.permute(Vec3f(static_cast(x) * gValw, static_cast(y) * gValh, static_cast(z) * gVald)) * 255; + uint8_t b = config.noise.permute(Vec3f(static_cast(x) * bValw, static_cast(y) * bValh, static_cast(z) * bVald)) * 255; + uint8_t a = config.noise.permute(Vec3f(static_cast(x) * aValw, static_cast(y) * aValh, static_cast(z) * aVald)) * 255; //Vec4ui8 noisecolor = config.noise.permuteColor(Vec3f( static_cast(x) / 64, static_cast(y) / 64, static_cast(z) / 64)); if (a > threshold) { //std::cout << "setting a position" << std::endl; @@ -155,6 +167,14 @@ void stopAndSaveAVI(defaults& config, const std::string& filename) { recordingFramesRemaining = 0; } +void saveSlices(defaults& config, VoxelGrid& grid) { + std::vector frames = grid.genSlices(frame::colormap::RGB); + for (int i = 0; i < frames.size(); i++) { + std::string filename = "output/slices/" + std::to_string(i) + ".bmp"; + BMPWriter::saveBMP(filename, frames[i]); + } +} + static void glfw_error_callback(int error, const char* description) { fprintf(stderr, "GLFW Error %d: %s\n", error, description); @@ -341,6 +361,10 @@ int main() { cameraMoved = true; } + if (ImGui::Button("Save Slices")) { + saveSlices(config, grid); + } + // AVI Recording Controls ImGui::Separator(); ImGui::Text("AVI Recording:"); diff --git a/util/grid/grid3.hpp b/util/grid/grid3.hpp index db7861b..a2be471 100644 --- a/util/grid/grid3.hpp +++ b/util/grid/grid3.hpp @@ -659,6 +659,89 @@ public: bool isMeshDirty() const { return meshDirty; } + + std::vector genSlices(frame::colormap colorFormat = frame::colormap::RGB) const { + TIME_FUNCTION; + int colors; + std::vector outframes; + switch (colorFormat) { + case frame::colormap::RGBA: + case frame::colormap::BGRA: { + colors = 4; + break; + } + case frame::colormap::B: { + colors = 1; + break; + } + case frame::colormap::RGB: + case frame::colormap::BGR: + default: { + colors = 3; + break; + } + } + size_t cbsize = gridSize.x * gridSize.y * colors; + for (int layer = 0; layer < getDepth(); layer++) { + int layerMult = layer * gridSize.x * gridSize.y; + frame layerFrame(gridSize.x, gridSize.y, colorFormat); + std::vector colorBuffer(cbsize); + for (int y = 0; y < gridSize.y; y++) { + int yMult = layerMult + (y * gridSize.x); + for (int x = 0; x < gridSize.x; x++) { + int vidx = yMult+x; + int pidx = (y * gridSize.x + x) * colors; + Voxel cv = voxels[vidx]; + Vec3ui8 cvColor; + float cvAlpha; + if (cv.active) { + cvColor = cv.color; + cvAlpha = cv.alpha; + } else { + cvColor = Vec3ui8(255,255,255); + cvAlpha = 255; + } + switch (colorFormat) { + case frame::colormap::RGBA: { + colorBuffer[pidx + 1] = cvColor.x; + colorBuffer[pidx + 2] = cvColor.y; + colorBuffer[pidx + 3] = cvColor.z; + colorBuffer[pidx + 0] = cvAlpha; + break; + } + case frame::colormap::BGRA: { + colorBuffer[pidx + 3] = cvColor.x; + colorBuffer[pidx + 2] = cvColor.y; + colorBuffer[pidx + 1] = cvColor.z; + colorBuffer[pidx + 0] = cvAlpha; + break; + } + case frame::colormap::RGB: { + colorBuffer[pidx + 1] = cvColor.x; + colorBuffer[pidx + 2] = cvColor.y; + colorBuffer[pidx + 3] = cvColor.z; + break; + } + case frame::colormap::BGR: { + colorBuffer[pidx + 3] = cvColor.x; + colorBuffer[pidx + 2] = cvColor.y; + colorBuffer[pidx + 1] = cvColor.z; + break; + } + case frame::colormap::B: { + colorBuffer[pidx] = (cvColor.x * 0.299) + (cvColor.y * 0.587) + (cvColor.z * 0.114); + break; + } + } + } + } + layerFrame.setData(colorBuffer); + //layerFrame.compressFrameLZ78(); + outframes.emplace_back(layerFrame); + } + return outframes; + } + }; //#include "g3_serialization.hpp" needed to be usable diff --git a/util/noise/pnoise2.hpp b/util/noise/pnoise2.hpp index 3e3bf4a..c12c6e2 100644 --- a/util/noise/pnoise2.hpp +++ b/util/noise/pnoise2.hpp @@ -62,6 +62,30 @@ private: permutation.insert(permutation.end(), permutationt.begin(), permutationt.end()); permutation.insert(permutation.end(), permutationt.begin(), permutationt.end()); } + + float normalizedNoise(const Vec2& point) { + return (permute(point) + 1.0f) * 0.5f; + } + + float mapRange(float value, float inMin, float inMax, float outMin, float outMax) { + return (value - inMin) * (outMax - outMin) / (inMax - inMin) + outMin; + } + + float blendNoises(float noise1, float noise2, float blendFactor) { + return lerp(noise1, noise2, blendFactor); + } + + float addNoises(float noise1, float noise2) { + return std::clamp(noise1 + noise2, -1.0f, 1.0f); + } + + float multiplyNoises(float noise1, float noise2) { + return noise1 * noise2; + } + + float hash(int x, int y) { + return (permutation[(x + permutation[y & 255]) & 255] / 255.0f) * 2.0f - 1.0f; + } public: PNoise2() : rng(std::random_device{}()) { initializePermutation(); @@ -74,8 +98,8 @@ public: template float permute(Vec2 point) { TIME_FUNCTION; - float x = point.x; - float y = point.y; + float x = static_cast(point.x); + float y = static_cast(point.y); int X = (int)floor(x); int xmod = X & 255; int Y = (int)floor(point.y); @@ -166,6 +190,34 @@ public: return retval; } + float valueNoise(const Vec2& point) { + int xi = (int)std::floor(point.x); + int yi = (int)std::floor(point.y); + + float tx = point.x - xi; + float ty = point.y - yi; + + int rx0 = xi & 255; + int rx1 = (xi + 1) & 255; + int ry0 = yi & 255; + int ry1 = (yi + 1) & 255; + + // Random values at corners + float c00 = hash(rx0, ry0); + float c10 = hash(rx1, ry0); + float c01 = hash(rx0, ry1); + float c11 = hash(rx1, ry1); + + // Interpolation + float sx = fade(tx); + float sy = fade(ty); + + float nx0 = lerp(c00, c10, sx); + float nx1 = lerp(c01, c11, sx); + + return lerp(nx0, nx1, sy); + } + Vec4ui8 permuteColor(const Vec3& point) { TIME_FUNCTION; float noiseR = permute(point); @@ -188,6 +240,65 @@ public: return Vec4ui8(r, g, b, a); } + template + float fractalNoise(const Vec2& point, int octaves, float persistence, float lacunarity) { + float total = 0.0f; + float frequency = 1.f; + float amplitude = 1.f; + float maxV = 0.f; + for (int i = 0; i < octaves; i++) { + total += permute(point*frequency) * amplitude; + maxV += amplitude; + amplitude *= persistence; + frequency *= lacunarity; + } + + return total / maxV; + } + + template + float turbulence(const Vec2& point, int octaves) { + float value = 0.0f; + Vec2 tempPoint = point; + for (int i = 0; i < octaves; i++) { + value += std::abs(permute(tempPoint)); + tempPoint *= 2.f; + } + return value; + } + + float ridgedNoise(const Vec2& point, int octaves, float offset = 1.0f) { + float result = 0.f; + float weight = 1.f; + Vec2 p = point; + + for (int i = 0; i < octaves; i++) { + float signal = 1.f - std::abs(permute(p)); + signal *= signal; + signal *= weight; + weight = signal * offset; + result += signal; + p *= 2.f; + } + + return result; + } + + float billowNoise(const Vec2& point, int octaves) { + float value = 0.0f; + float amplitude = 1.0f; + float frequency = 1.0f; + + for (int i = 0; i < octaves; i++) { + value += std::abs(permute(point * frequency)) * amplitude; + amplitude *= 0.5f; + frequency *= 2.0f; + } + + return value; + } + + }; #endif \ No newline at end of file diff --git a/voxel_render.png b/voxel_render.png deleted file mode 100644 index 5220d0f9dbfa747cdb356761a73beb1b1f1c96bb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 842 zcmeAS@N?(olHy`uVBq!ia0y~yU;;9k7&t&wwUqN(1_ow9PZ!6KiaBo&HUh;M4lno_ o9RH9Zlo7-k1*0J_;zHm+KGPNk#z+z0_aLu(y85}Sb4q9e0Lk|gumAu6