This commit is contained in:
Yggdrasil75
2025-11-05 11:56:56 -05:00
commit 5a0d81134e
22 changed files with 5497 additions and 0 deletions

363
f.cpp Normal file
View File

@@ -0,0 +1,363 @@
#include <vector>
#include <cmath>
#include <limits>
#include <algorithm>
#include <unordered_map>
#include <cstdio>
#include <cstring>
#include <fstream>
#include <iostream>
#include <vector>
#include <random>
#include <functional>
#include <tuple>
#include "util/timing_decorator.hpp"
#include "util/vec3.hpp"
#include "util/vec4.hpp"
#include "util/bmpwriter.hpp"
#include "util/voxelgrid.hpp"
std::vector<Vec3> generateSphere(int numPoints, float radius = 1.0f, float wiggleAmount = 0.1f) {
printf("Generating sphere with %d points using grid method...\n", numPoints);
printf("Wiggle amount: %.3f\n", wiggleAmount);
std::vector<Vec3> points;
// Random number generator for wiggling
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<float> dist(-1.0f, 1.0f);
// Calculate grid resolution based on desired number of points
// For a sphere, we need to account that only about 52% of points in a cube will be inside the sphere
int gridRes = static_cast<int>(std::cbrt(numPoints / 0.52f)) + 1;
printf("Using grid resolution: %d x %d x %d\n", gridRes, gridRes, gridRes);
// Calculate voxel size for wiggling (based on average distance between points)
float voxelSize = 2.0f / gridRes;
float maxWiggle = wiggleAmount * voxelSize;
printf("Voxel size: %.4f, Max wiggle: %.4f\n", voxelSize, maxWiggle);
// Generate points in a cube from -1 to 1 in all dimensions
for (int x = 0; x < gridRes; ++x) {
for (int y = 0; y < gridRes; ++y) {
for (int z = 0; z < gridRes; ++z) {
// Convert grid coordinates to normalized cube coordinates [-1, 1]
Vec3 point(
(2.0f * x / (gridRes - 1)) - 1.0f,
(2.0f * y / (gridRes - 1)) - 1.0f,
(2.0f * z / (gridRes - 1)) - 1.0f
);
// Check if point is inside the unit sphere
if (point.lengthSquared() <= 1.0f) {
// Apply randomized wiggling
Vec3 wiggle(
dist(gen) * maxWiggle,
dist(gen) * maxWiggle,
dist(gen) * maxWiggle
);
Vec3 wiggledPoint = point + wiggle;
// Re-normalize to maintain spherical shape while preserving the wiggle
// This ensures the point stays within the sphere while having natural variation
float currentLength = wiggledPoint.length();
if (currentLength > 1.0f) {
// Scale back to unit sphere surface, but preserve the wiggle direction
wiggledPoint = wiggledPoint * (1.0f / currentLength);
}
points.push_back(wiggledPoint * radius); // Scale by radius
}
}
}
}
printf("Generated %zu points inside sphere\n", points.size());
// If we have too many points, randomly sample down to the desired number
if (points.size() > static_cast<size_t>(numPoints)) {
printf("Sampling down from %zu to %d points...\n", points.size(), numPoints);
// Shuffle and resize
std::shuffle(points.begin(), points.end(), gen);
points.resize(numPoints);
}
// If we have too few points, we'll use what we have
else if (points.size() < static_cast<size_t>(numPoints)) {
printf("Warning: Only generated %zu points (requested %d)\n", points.size(), numPoints);
}
return points;
}
// Alternative sphere generation with perlin-like noise for more natural wiggling
std::vector<Vec3> generateSphereWithNaturalWiggle(int numPoints, float radius = 1.0f, float noiseStrength = 0.15f) {
printf("Generating sphere with natural wiggling using %d points...\n", numPoints);
printf("Noise strength: %.3f\n", noiseStrength);
std::vector<Vec3> points;
// Random number generators
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<float> dist(-1.0f, 1.0f);
// Calculate grid resolution
int gridRes = static_cast<int>(std::cbrt(numPoints / 0.52f)) + 1;
printf("Using grid resolution: %d x %d x %d\n", gridRes, gridRes, gridRes);
float voxelSize = 2.0f / gridRes;
float maxDisplacement = noiseStrength * voxelSize;
// Pre-compute some random offsets for pseudo-perlin noise
std::vector<float> randomOffsets(gridRes * gridRes * gridRes);
for (size_t i = 0; i < randomOffsets.size(); ++i) {
randomOffsets[i] = dist(gen);
}
auto getNoise = [&](int x, int y, int z) -> float {
int idx = (x * gridRes * gridRes) + (y * gridRes) + z;
return randomOffsets[idx % randomOffsets.size()];
};
for (int x = 0; x < gridRes; ++x) {
for (int y = 0; y < gridRes; ++y) {
for (int z = 0; z < gridRes; ++z) {
Vec3 point(
(2.0f * x / (gridRes - 1)) - 1.0f,
(2.0f * y / (gridRes - 1)) - 1.0f,
(2.0f * z / (gridRes - 1)) - 1.0f
);
if (point.lengthSquared() <= 1.0f) {
// Use smoother noise for more natural displacement
float noiseX = getNoise(x, y, z);
float noiseY = getNoise(y, z, x);
float noiseZ = getNoise(z, x, y);
// Apply displacement that preserves the overall spherical structure
Vec3 displacement(
noiseX * maxDisplacement,
noiseY * maxDisplacement,
noiseZ * maxDisplacement
);
Vec3 displacedPoint = point + displacement;
// Ensure we don't push points too far from sphere surface
float currentLength = displacedPoint.length();
if (currentLength > 1.0f) {
displacedPoint = displacedPoint * (0.95f + 0.05f * dist(gen)); // Small random scaling
}
points.push_back(displacedPoint * radius);
}
}
}
}
printf("Generated %zu points with natural wiggling\n", points.size());
// Sample down if needed
if (points.size() > static_cast<size_t>(numPoints)) {
printf("Sampling down from %zu to %d points...\n", points.size(), numPoints);
std::shuffle(points.begin(), points.end(), gen);
points.resize(numPoints);
} else if (points.size() < static_cast<size_t>(numPoints)) {
printf("Warning: Only generated %zu points (requested %d)\n", points.size(), numPoints);
}
return points;
}
// Modified function to populate voxel grid with sphere points and assign layers
void populateVoxelGridWithLayeredSphere(VoxelGrid& grid, const std::vector<Vec3>& points) {
printf("Populating voxel grid with %zu sphere points...\n", points.size());
// First add all voxels with a default color
Vec4 defaultColor(1.0f, 1.0f, 1.0f, 1.0f); // Temporary color
for (const auto& point : points) {
grid.addVoxel(point, defaultColor);
}
printf("Voxel grid populated with %zu voxels\n", grid.getOccupiedPositions().size());
// Now assign the planetary layers
grid.assignPlanetaryLayers();
}
Vec3 rotateX(const Vec3& point, float angle) {
float cosA = std::cos(angle);
float sinA = std::sin(angle);
return Vec3(
point.x,
point.y * cosA - point.z * sinA,
point.y * sinA + point.z * cosA
);
}
Vec3 rotateY(const Vec3& point, float angle) {
float cosA = std::cos(angle);
float sinA = std::sin(angle);
return Vec3(
point.x * cosA + point.z * sinA,
point.y,
-point.x * sinA + point.z * cosA
);
}
Vec3 rotateZ(const Vec3& point, float angle) {
float cosA = std::cos(angle);
float sinA = std::sin(angle);
return Vec3(
point.x * cosA - point.y * sinA,
point.x * sinA + point.y * cosA,
point.z
);
}
void visualizePointCloud(const std::vector<Vec3>& points, const std::vector<Vec4>& colors,
const std::string& filename, int width = 1000, int height = 1000,
float angleX = 0.0f, float angleY = 0.0f, float angleZ = 0.0f) {
TIME_FUNCTION;
std::vector<uint8_t> pixels(width * height * 3, 0);
// Background color (dark blue)
for (int i = 0; i < width * height * 3; i += 3) {
pixels[i] = 30; // B
pixels[i + 1] = 30; // G
pixels[i + 2] = 50; // R
}
// Find bounds of point cloud
Vec3 minPoint( std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max());
Vec3 maxPoint(-std::numeric_limits<float>::max(), -std::numeric_limits<float>::max(), -std::numeric_limits<float>::max());
// Apply rotation to all points and find new bounds
std::vector<Vec3> rotatedPoints;
rotatedPoints.reserve(points.size());
for (const auto& point : points) {
Vec3 rotated = point;
rotated = rotateX(rotated, angleX);
rotated = rotateY(rotated, angleY);
rotated = rotateZ(rotated, angleZ);
rotatedPoints.push_back(rotated);
minPoint.x = std::min(minPoint.x, rotated.x);
minPoint.y = std::min(minPoint.y, rotated.y);
minPoint.z = std::min(minPoint.z, rotated.z);
maxPoint.x = std::max(maxPoint.x, rotated.x);
maxPoint.y = std::max(maxPoint.y, rotated.y);
maxPoint.z = std::max(maxPoint.z, rotated.z);
}
Vec3 cloudSize = maxPoint - minPoint;
float maxDim = std::max({cloudSize.x, cloudSize.y, cloudSize.z});
// Draw points
for (size_t i = 0; i < rotatedPoints.size(); i++) {
const auto& point = rotatedPoints[i];
const auto& color = colors[i];
// Map 3D point to 2D screen coordinates (orthographic projection)
int screenX = static_cast<int>(((point.x - minPoint.x) / maxDim) * (width - 20)) + 10;
int screenY = static_cast<int>(((point.y - minPoint.y) / maxDim) * (height - 20)) + 10;
if (screenX >= 0 && screenX < width && screenY >= 0 && screenY < height) {
uint8_t r, g, b;
color.toUint8(r, g, b);
// Draw a 2x2 pixel for each point
for (int dy = -1; dy <= 1; dy++) {
for (int dx = -1; dx <= 1; dx++) {
int px = screenX + dx;
int py = screenY + dy;
if (px >= 0 && px < width && py >= 0 && py < height) {
int index = (py * width + px) * 3;
pixels[index] = b;
pixels[index + 1] = g;
pixels[index + 2] = r;
}
}
}
}
}
BMPWriter::saveBMP(filename, pixels, width, height);
}
int main() {
printf("=== Layered Sphere Generation and Visualization ===\n\n");
const int numPoints = 100000000;
const float radius = 2.0f;
printf("Generating layered spheres with %d points each, radius %.1f\n\n", numPoints, radius);
// Create voxel grid
VoxelGrid grid(Vec3(10, 10, 10), Vec3(0.1f, 0.1f, 0.1f));
// Generate sphere with different wiggle options:
// Option 1: Simple random wiggling (small amount - 10% of voxel size)
printf("1. Generating sphere with simple wiggling...\n");
auto sphere1 = generateSphereWithNaturalWiggle(numPoints, radius, 0.1f);
populateVoxelGridWithLayeredSphere(grid, sphere1);
// Extract positions and colors for visualization
std::vector<Vec3> occupiedPositions = grid.getOccupiedPositions();
std::vector<Vec4> layerColors = grid.getColors();
// Convert to world coordinates for visualization
std::vector<Vec3> worldPositions;
for (const auto& gridPos : occupiedPositions) {
worldPositions.push_back(grid.gridToWorld(gridPos));
}
// Create multiple visualizations from different angles
printf("\nGenerating views from different angles...\n");
// Front view (0, 0, 0)
visualizePointCloud(worldPositions, layerColors, "output/sphere_front.bmp", 1000, 1000, 0.0f, 0.0f, 0.0f);
printf(" - sphere_front.bmp (front view)\n");
// 45 degree rotation around Y axis
visualizePointCloud(worldPositions, layerColors, "output/sphere_45y.bmp", 1000, 1000, 0.0f, M_PI/4, 0.0f);
printf(" - sphere_45y.bmp (45° Y rotation)\n");
// 90 degree rotation around Y axis (side view)
visualizePointCloud(worldPositions, layerColors, "output/sphere_side.bmp", 1000, 1000, 0.0f, M_PI/2, 0.0f);
printf(" - sphere_side.bmp (side view)\n");
// 45 degree rotation around X axis (top-down perspective)
visualizePointCloud(worldPositions, layerColors, "output/sphere_45x.bmp", 1000, 1000, M_PI/4, 0.0f, 0.0f);
printf(" - sphere_45x.bmp (45° X rotation)\n");
// Combined rotation (30° X, 30° Y)
visualizePointCloud(worldPositions, layerColors, "output/sphere_30x_30y.bmp", 1000, 1000, M_PI/6, M_PI/6, 0.0f);
printf(" - sphere_30x_30y.bmp (30° X, 30° Y rotation)\n");
// Top view (90° X rotation)
visualizePointCloud(worldPositions, layerColors, "output/sphere_top.bmp", 1000, 1000, M_PI/2, 0.0f, 0.0f);
printf(" - sphere_top.bmp (top view)\n");
printf("\n=== Sphere generated successfully ===\n");
printf("Files created in output/ directory:\n");
printf(" - sphere_front.bmp (Front view)\n");
printf(" - sphere_45y.bmp (45° Y rotation)\n");
printf(" - sphere_side.bmp (Side view)\n");
printf(" - sphere_45x.bmp (45° X rotation)\n");
printf(" - sphere_30x_30y.bmp (30° X, 30° Y rotation)\n");
printf(" - sphere_top.bmp (Top view)\n");
return 0;
}