This commit is contained in:
Yggdrasil75
2026-01-07 14:06:25 -05:00
parent 65f2464c70
commit 1aa81ce65f
2 changed files with 165 additions and 203 deletions

View File

@@ -1,228 +1,176 @@
// main.cpp - Noise Grid Generator and Renderer
#include <iostream> #include <iostream>
#include <memory>
#include <cmath>
#include <vector> #include <vector>
#include "../util/grid/grid3.hpp" #include "../util/grid/grid3.hpp"
#include "../util/output/bmpwriter.hpp" #include "../util/output/bmpwriter.hpp"
#include "../util/noise/pnoise2.hpp" #include "../util/output/frame.hpp"
#include "../util/timing_decorator.cpp" #include "../util/timing_decorator.cpp"
// Constants #include "../imgui/imgui.h"
const size_t GRID_SIZE = 128; #include "../imgui/backends/imgui_impl_glfw.h"
const size_t RENDER_WIDTH = 512; #include "../imgui/backends/imgui_impl_opengl3.h"
const size_t RENDER_HEIGHT = 512; #include <GLFW/glfw3.h>
#include "../stb/stb_image.h"
// Function to generate grayscale noise grid struct defaults {
void generateNoiseGrid(VoxelGrid& grid, PNoise2& noise) { int outWidth = 1024;
TIME_FUNCTION; int outHeight = 1024;
std::cout << "Generating 1024x1024x1024 noise grid..." << std::endl; size_t gridWidth = 1024;
size_t gridHeight = 1024;
// Generate Perlin noise in the grid size_t gridDepth = 1024;
#pragma omp parallel for float fps = 30.0f;
for (size_t z = 0; z < GRID_SIZE; ++z) { PNoise2 noise = PNoise2(42);
};
std::mutex PreviewMutex;
frame currentPreviewFrame;
GLuint textu = 0;
bool updatePreview;
VoxelGrid setup(defaults config) {
float threshold = 0.3 * 255;
VoxelGrid grid(config.gridWidth, config.gridHeight, config.gridDepth);
std::cout << "Generating grid of size " << config.gridWidth << "x" << config.gridHeight << "x" << config.gridDepth << std::endl;
for (size_t z = 0; z < config.gridDepth; ++z) {
if (z % 64 == 0) { if (z % 64 == 0) {
std::cout << "Processing layer " << z << " of " << GRID_SIZE << std::endl; std::cout << "Processing layer " << z << " of " << config.gridDepth << std::endl;
} }
//#pragma omp parallel for for (size_t y = 0; y < config.gridWidth; ++y) {
for (size_t y = 0; y < GRID_SIZE; ++y) { for (size_t x = 0; x < config.gridHeight; ++x) {
//#pragma omp parallel for Vec4ui8 noisecolor = config.noise.permuteColor(Vec3f( x / 64, y / 64, z / 64));
for (size_t x = 0; x < GRID_SIZE; ++x) { if (noisecolor.a > threshold) {
// Create 3D noise coordinates (scaled for better frequency) grid.set(Vec3T(x,y,z), true, Vec3ui8(noisecolor.xyz()));
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.3;
float active = (noiseVal > threshold) ? noiseVal : 0.0f;
// Create grayscale color based on noise value
uint8_t grayValue = static_cast<uint8_t>(noiseVal * 255);
Vec3ui8 color(grayValue, grayValue, 0);
#pragma omp critical
if (active > threshold) {
grid.set(x, y, z, true, color);
} }
} }
} }
} }
std::cout << "Noise grid generation complete!" << std::endl; std::cout << "Noise grid generation complete!" << std::endl;
} }
// Function to render grid from a specific viewpoint void livePreview(VoxelGrid& grid, defaults config, Camera cam) {
bool renderView(const std::string& filename, VoxelGrid& grid, const Vec3f& position, std::lock_guard<std::mutex> lock(PreviewMutex);
const Vec3f& direction, const Vec3f& up = Vec3f(0, 1, 0)) {
TIME_FUNCTION;
Camera cam(position, direction, up, 40);
std::vector<uint8_t> renderBuffer; currentPreviewFrame = grid.renderFrame(cam.posfor.origin, cam.posfor.direction, cam.up, cam.fov, config.outWidth, config.outHeight, frame::colormap::BGRA);
size_t width = RENDER_WIDTH;
size_t height = RENDER_HEIGHT; glGenTextures(1, &textu);
glBindTexture(GL_TEXTURE_2D, textu);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
// Render the view glBindTexture(GL_TEXTURE_2D, textu);
frame output = grid.renderFrame(position, direction, up, 40, RENDER_WIDTH, RENDER_HEIGHT); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, currentPreviewFrame.getWidth(), currentPreviewFrame.getHeight(),
//grid.renderOut(renderBuffer, width, height, cam); 0, GL_RGBA, GL_UNSIGNED_BYTE, currentPreviewFrame.getData().data());
// Save to BMP updatePreview = true;
bool success = BMPWriter::saveBMP(filename, output);
//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;
} }
Vec3f rotateX(const Vec3f& vec, float angle) { static void glfw_error_callback(int error, const char* description)
TIME_FUNCTION; {
float cosA = cos(angle); fprintf(stderr, "GLFW Error %d: %s\n", error, description);
float sinA = sin(angle);
return Vec3f(
vec.x,
vec.y * cosA - vec.z * sinA,
vec.y * sinA + vec.z * cosA
);
} }
Vec3f rotateY(const Vec3f& vec, float angle) {
TIME_FUNCTION;
float cosA = cos(angle);
float sinA = sin(angle);
return Vec3f(
vec.x * cosA + vec.z * sinA,
vec.y,
-vec.x * sinA + vec.z * cosA
);
}
Vec3f rotateZ(const Vec3f& vec, float angle) {
TIME_FUNCTION;
float cosA = cos(angle);
float sinA = sin(angle);
return Vec3f(
vec.x * cosA - vec.y * sinA,
vec.x * sinA + vec.y * cosA,
vec.z
);
}
int main() { int main() {
TIME_FUNCTION; glfwSetErrorCallback(glfw_error_callback);
std::cout << "=== Noise Grid Generator and Renderer ===" << std::endl; if (!glfwInit()) {
std::cout << "Grid Size: 1024x1024x1024 voxels" << std::endl; std::cerr << "gui stuff is dumb in c++." << std::endl;
std::cout << "Render Size: 512x512 pixels" << std::endl; glfwTerminate();
return 1;
// 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;
int numFrames = 360;
// Base camera position (looking from front)
Vec3f basePosition(0, 0, cameraDistance);
Vec3f baseDirection(0, 0, -1); // Looking towards negative Z (towards center)
Vec3f up(0, 1, 0);
// // Render frames around 180 degrees
// for (int i = 0; i <= numFrames; i++) {
// float angle = (float)i / numFrames * M_PI; // 0 to π (180 degrees)
// // Rotate camera position around Y axis
// Vec3f rotatedPos = rotateY(basePosition, angle);
// Vec3f finalPos = gridCenter + rotatedPos;
// //Vec3f rotatedDir = rotateY(baseDirection, angle);
// Vec3f rotatedDir = (gridCenter - finalPos).normalized();
// // Create filename with frame number
// char filename[256];
// snprintf(filename, sizeof(filename), "output/framey_%03d.bmp", i);
// // std::cout << "Rendering frame " << i << "/" << numFrames
// // << " (angle: " << (angle * 360.0f / M_PI) << " degrees)" << std::endl;
// renderView(filename, grid, finalPos, rotatedDir, up);
// }
// basePosition = Vec3f(0, 0, cameraDistance);
// baseDirection = Vec3f(0, 0, -1);
// up = Vec3f(0, 1, 0);
// for (int i = 0; i <= numFrames; i++) {
// float angle = (float)i / numFrames * M_PI; // 0 to π (180 degrees)
// // Rotate camera position around Y axis
// Vec3f rotatedPos = rotateZ(basePosition, angle);
// Vec3f finalPos = gridCenter + rotatedPos;
// //Vec3f rotatedDir = rotateY(baseDirection, angle);
// Vec3f rotatedDir = (gridCenter - finalPos).normalized();
// // Create filename with frame number
// char filename[256];
// snprintf(filename, sizeof(filename), "output/framez_%03d.bmp", i);
// // std::cout << "Rendering frame " << i << "/" << numFrames
// // << " (angle: " << (angle * 360.0f / M_PI) << " degrees)" << std::endl;
// renderView(filename, grid, finalPos, rotatedDir, up);
// }
// basePosition = Vec3f(0, 0, cameraDistance);
// baseDirection = Vec3f(0, 0, -1);
// up = Vec3f(0, 1, 0);
for (int i = 0; i <= numFrames; i++) {
float angle = (float)i / numFrames * M_PI; // 0 to π (180 degrees)
// Rotate camera position around Y axis
Vec3f rotatedPos = rotateX(basePosition, angle);
Vec3f finalPos = gridCenter + rotatedPos;
//Vec3f rotatedDir = rotateY(baseDirection, angle);
Vec3f rotatedDir = (gridCenter - finalPos).normalized();
// Create filename with frame number
char filename[256];
snprintf(filename, sizeof(filename), "output/framex_%03d.bmp", i);
std::cout << "Rendering frame " << i << "/" << numFrames
<< " (angle: " << (angle * 360.0f / M_PI) << " degrees)" << std::endl;
renderView(filename, grid, finalPos, rotatedDir, up);
} }
// COPIED VERBATIM FROM IMGUI.
#if defined(IMGUI_IMPL_OPENGL_ES2)
// GL ES 2.0 + GLSL 100 (WebGL 1.0)
const char* glsl_version = "#version 100";
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
#elif defined(IMGUI_IMPL_OPENGL_ES3)
// GL ES 3.0 + GLSL 300 es (WebGL 2.0)
const char* glsl_version = "#version 300 es";
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
#elif defined(__APPLE__)
// GL 3.2 + GLSL 150
const char* glsl_version = "#version 150";
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 3.2+ only
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Required on Mac
#else
// GL 3.0 + GLSL 130
const char* glsl_version = "#version 130";
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
//glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 3.2+ only
//glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // 3.0+ only
#endif
bool application_not_closed = true;
GLFWwindow* window = glfwCreateWindow((int)(1280), (int)(800), "voxelgrid live renderer", nullptr, nullptr);
if (window == nullptr)
return 1;
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
ImGui::StyleColorsDark();
ImGuiStyle& style = ImGui::GetStyle();
ImGui_ImplGlfw_InitForOpenGL(window, true);
#ifdef __EMSCRIPTEN__
ImGui_ImplGlfw_InstallEmscriptenCallbacks(window, "#canvas");
#endif
ImGui_ImplOpenGL3_Init(glsl_version);
bool show_demo_window = true;
bool show_another_window = false;
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
while (!glfwWindowShouldClose(window)) {
glfwPollEvents();
// Start the Dear ImGui frame
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
{
ImGui::Begin("settings");
}
// std::cout << "ending frame" << std::endl;
ImGui::Render();
int display_w, display_h;
glfwGetFramebufferSize(window, &display_w, &display_h);
glViewport(0, 0, display_w, display_h);
glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
glClear(GL_COLOR_BUFFER_BIT);
// std::cout << "rendering" << std::endl;
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
glfwSwapBuffers(window);
//mainlogicthread.join();
// std::cout << "swapping buffers" << std::endl;
}
std::cout << "\nRendering zenith and nadir views..." << std::endl; // std::cout << "shutting down" << std::endl;
renderView("output/zenith_view.bmp", grid, ImGui_ImplOpenGL3_Shutdown();
gridCenter + Vec3f(0, cameraDistance, 0), ImGui_ImplGlfw_Shutdown();
Vec3f(0, -1, 0), // Look down ImGui::DestroyContext();
Vec3f(0, 0, -1)); // Adjust up vector for proper orientation
// std::cout << "destroying" << std::endl;
// Nadir view (looking from below) glfwDestroyWindow(window);
renderView("output/nadir_view.bmp", grid, if (textu != 0) {
gridCenter + Vec3f(0, -cameraDistance, 0), glDeleteTextures(1, &textu);
Vec3f(0, 1, 0), // Look up textu = 0;
Vec3f(0, 0, 1)); // Adjust up vector }
glfwTerminate();
std::cout << "\n=== All renders complete! ===" << std::endl;
FunctionTimer::printStats(FunctionTimer::Mode::ENHANCED); FunctionTimer::printStats(FunctionTimer::Mode::ENHANCED);
// std::cout << "printing" << std::endl;
return 0; return 0;
} }

View File

@@ -197,7 +197,7 @@ public:
return gridSize.z; return gridSize.z;
} }
frame renderFrame(const Vec3f& CamPos, const Vec3f& dir, const Vec3f& up, float fov, size_t outW, size_t outH) { frame renderFrame(const Vec3f& CamPos, const Vec3f& dir, const Vec3f& up, float fov, size_t outW, size_t outH, frame::colormap colorformat = frame::colormap::RGB) {
TIME_FUNCTION; TIME_FUNCTION;
Vec3f forward = (dir - CamPos).normalized(); Vec3f forward = (dir - CamPos).normalized();
Vec3f right = forward.cross(up).normalized(); Vec3f right = forward.cross(up).normalized();
@@ -234,10 +234,24 @@ public:
hitVoxels.clear(); hitVoxels.clear();
hitVoxels.shrink_to_fit(); hitVoxels.shrink_to_fit();
// Set pixel color in buffer // Set pixel color in buffer
size_t idx = (y * outW + x) * 3; switch (colorformat) {
colorBuffer[idx + 0] = hitColor.x; case frame::colormap::RGB: {
colorBuffer[idx + 1] = hitColor.y; size_t idx = (y * outW + x) * 3;
colorBuffer[idx + 2] = hitColor.z; colorBuffer[idx + 0] = hitColor.x;
colorBuffer[idx + 1] = hitColor.y;
colorBuffer[idx + 2] = hitColor.z;
break;
}
case frame::colormap::BGRA: {
size_t idx = (y * outW + x) * 4;
colorBuffer[idx + 3] = hitColor.x;
colorBuffer[idx + 2] = hitColor.y;
colorBuffer[idx + 1] = hitColor.z;
colorBuffer[idx + 0] = 1;
break;
}
}
} }
} }