my grid should work. just need minor tests
This commit is contained in:
2
makefile
2
makefile
@@ -16,7 +16,7 @@ PKG_FLAGS := $(LINUX_GL_LIBS) `pkg-config --static --cflags --libs glfw3`
|
|||||||
CXXFLAGS += $(PKG_FLAGS)
|
CXXFLAGS += $(PKG_FLAGS)
|
||||||
|
|
||||||
# Source files
|
# Source files
|
||||||
SRC := $(SRC_DIR)/g3chromatic.cpp
|
SRC := $(SRC_DIR)/g3test2.cpp
|
||||||
#SRC := $(SRC_DIR)/g2chromatic2.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)/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
|
SRC += $(IMGUI_DIR)/backends/imgui_impl_glfw.cpp $(IMGUI_DIR)/backends/imgui_impl_opengl3.cpp
|
||||||
|
|||||||
154
tests/g3test2.cpp
Normal file
154
tests/g3test2.cpp
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
// main.cpp - Noise Grid Generator and Renderer
|
||||||
|
#include <iostream>
|
||||||
|
#include <memory>
|
||||||
|
#include <cmath>
|
||||||
|
#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<uint8_t>(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<uint8_t> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,10 +18,49 @@ struct Voxel {
|
|||||||
Vec3ui8 color;
|
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 {
|
class VoxelGrid {
|
||||||
private:
|
private:
|
||||||
size_t width, height, depth;
|
size_t width, height, depth;
|
||||||
std::vector<Voxel> voxels;
|
std::vector<Voxel> 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:
|
public:
|
||||||
VoxelGrid(size_t w, size_t h, size_t d) : width(w), height(h), depth(d) {
|
VoxelGrid(size_t w, size_t h, size_t d) : width(w), height(h), depth(d) {
|
||||||
voxels.resize(w * h * d);
|
voxels.resize(w * h * d);
|
||||||
@@ -76,6 +115,22 @@ public:
|
|||||||
return (voxl >= 0 && voxl.x < width && voxl.y < height && voxl.z < depth);
|
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) {
|
bool rayCast(const Ray3f& ray, float maxDistance, Vec3f hitPos, Vec3f hitNormal, Vec3f& hitColor) {
|
||||||
hitColor = Vec3f(0,0,0);
|
hitColor = Vec3f(0,0,0);
|
||||||
Vec3f rayDir = ray.direction;
|
Vec3f rayDir = ray.direction;
|
||||||
@@ -107,7 +162,6 @@ public:
|
|||||||
current voxel.
|
current voxel.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
float tEntry = 0.0;
|
|
||||||
Vec3f tBMin;
|
Vec3f tBMin;
|
||||||
Vec3f tBMax;
|
Vec3f tBMax;
|
||||||
tBMin.x = (0.0 - rayOrigin.x) / rayDir.x;
|
tBMin.x = (0.0 - rayOrigin.x) / rayDir.x;
|
||||||
@@ -186,6 +240,46 @@ public:
|
|||||||
}
|
}
|
||||||
return hit;
|
return hit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t getWidth() const {
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
size_t getHeight() const {
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
size_t getDepth() const {
|
||||||
|
return depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
void renderOut(std::vector<uint8_t>& 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<uint8_t>(finalColor.x * 255);
|
||||||
|
output[pixelIndex + 1] = static_cast<uint8_t>(finalColor.y * 255);
|
||||||
|
output[pixelIndex + 2] = static_cast<uint8_t>(finalColor.z * 255);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -320,36 +320,5 @@ inline Mat4<T> operator*(T scalar, const Mat4<T>& mat) {
|
|||||||
using Mat4f = Mat4<float>;
|
using Mat4f = Mat4<float>;
|
||||||
using Mat4d = Mat4<double>;
|
using Mat4d = Mat4<double>;
|
||||||
|
|
||||||
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
|
#endif
|
||||||
@@ -471,22 +471,7 @@ Vec3<T> mix(const Vec3<T>& a, const Vec3<T>& b, const Vec3<bool>& mask) {
|
|||||||
mask.x ? b.x : a.x,
|
mask.x ? b.x : a.x,
|
||||||
mask.y ? b.y : a.y,
|
mask.y ? b.y : a.y,
|
||||||
mask.z ? b.z : a.z
|
mask.z ? b.z : a.z
|
||||||
)
|
);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
std::pair<Vec3<T>, Vec3<T>> multiMix(const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c, const Vec3<T>& d, const Vec3<bool>& mask) {
|
|
||||||
outa = Vec3<T>(
|
|
||||||
mask.x ? b.x : a.x,
|
|
||||||
mask.y ? b.y : a.y,
|
|
||||||
mask.z ? b.z : a.z
|
|
||||||
)
|
|
||||||
outb = Vec3<T>(
|
|
||||||
mask.x ? d.x : c.x,
|
|
||||||
mask.y ? d.y : c.y,
|
|
||||||
mask.z ? d.z : c.z
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
Reference in New Issue
Block a user