added sphere and noise documentation
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
#include <cmath>
|
||||
|
||||
#include "../util/grid/grid3.hpp"
|
||||
#include "../util/grid/g3_serialization.hpp"
|
||||
@@ -42,6 +43,23 @@ std::atomic<int> recordingFramesRemaining{0};
|
||||
std::vector<frame> recordedFrames;
|
||||
std::mutex recordingMutex;
|
||||
|
||||
// Sphere generation parameters
|
||||
struct SphereConfig {
|
||||
float centerX = 256.0f;
|
||||
float centerY = 256.0f;
|
||||
float centerZ = 32.0f;
|
||||
float radius = 30.0f;
|
||||
uint8_t r = 0;
|
||||
uint8_t g = 255;
|
||||
uint8_t b = 0;
|
||||
uint8_t a = 255;
|
||||
bool fillInside = true;
|
||||
bool outlineOnly = false;
|
||||
float outlineThickness = 1.0f;
|
||||
};
|
||||
|
||||
SphereConfig sphereConfig;
|
||||
|
||||
struct Shared {
|
||||
std::mutex mutex;
|
||||
VoxelGrid grid;
|
||||
@@ -74,9 +92,7 @@ void setup(defaults config, VoxelGrid& grid) {
|
||||
uint8_t g = config.noise.permute(Vec3f(static_cast<float>(x) * gValw, static_cast<float>(y) * gValh, static_cast<float>(z) * gVald)) * 255;
|
||||
uint8_t b = config.noise.permute(Vec3f(static_cast<float>(x) * bValw, static_cast<float>(y) * bValh, static_cast<float>(z) * bVald)) * 255;
|
||||
uint8_t a = config.noise.permute(Vec3f(static_cast<float>(x) * aValw, static_cast<float>(y) * aValh, static_cast<float>(z) * aVald)) * 255;
|
||||
//Vec4ui8 noisecolor = config.noise.permuteColor(Vec3f( static_cast<float>(x) / 64, static_cast<float>(y) / 64, static_cast<float>(z) / 64));
|
||||
if (a > threshold) {
|
||||
//std::cout << "setting a position" << std::endl;
|
||||
grid.set(Vec3i(x, y, z), true, Vec3ui8(r,g,b));
|
||||
}
|
||||
}
|
||||
@@ -87,6 +103,67 @@ void setup(defaults config, VoxelGrid& grid) {
|
||||
grid.printStats();
|
||||
}
|
||||
|
||||
void createGreenSphere(defaults config, VoxelGrid& grid) {
|
||||
grid.resize(config.gridWidth, config.gridHeight, config.gridDepth);
|
||||
std::cout << "Creating green sphere of size " << config.gridWidth << "x" << config.gridHeight << "x" << config.gridDepth << std::endl;
|
||||
|
||||
float radiusSq = sphereConfig.radius * sphereConfig.radius;
|
||||
float outlineInnerRadiusSq = (sphereConfig.radius - sphereConfig.outlineThickness) *
|
||||
(sphereConfig.radius - sphereConfig.outlineThickness);
|
||||
float outlineOuterRadiusSq = (sphereConfig.radius + sphereConfig.outlineThickness) *
|
||||
(sphereConfig.radius + sphereConfig.outlineThickness);
|
||||
|
||||
int progressStep = std::max(1, config.gridDepth / 10);
|
||||
|
||||
for (int z = 0; z < config.gridDepth; ++z) {
|
||||
if (z % progressStep == 0) {
|
||||
std::cout << "Processing layer " << z << " of " << config.gridDepth << std::endl;
|
||||
}
|
||||
|
||||
for (int y = 0; y < config.gridHeight; ++y) {
|
||||
for (int x = 0; x < config.gridWidth; ++x) {
|
||||
// Calculate distance from sphere center
|
||||
float dx = x - sphereConfig.centerX;
|
||||
float dy = y - sphereConfig.centerY;
|
||||
float dz = z - sphereConfig.centerZ;
|
||||
float distSq = dx*dx + dy*dy + dz*dz;
|
||||
|
||||
bool shouldSet = false;
|
||||
|
||||
if (sphereConfig.outlineOnly) {
|
||||
// Only create outline (shell)
|
||||
if (distSq >= outlineInnerRadiusSq && distSq <= outlineOuterRadiusSq) {
|
||||
shouldSet = true;
|
||||
}
|
||||
} else if (sphereConfig.fillInside) {
|
||||
// Fill entire sphere
|
||||
if (distSq <= radiusSq) {
|
||||
shouldSet = true;
|
||||
}
|
||||
} else {
|
||||
// Hollow sphere (just the surface)
|
||||
if (distSq <= radiusSq && distSq >= (radiusSq - sphereConfig.radius * 0.5f)) {
|
||||
shouldSet = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldSet) {
|
||||
grid.set(Vec3i(x, y, z), true,
|
||||
Vec3ui8(sphereConfig.r, sphereConfig.g, sphereConfig.b));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "Green sphere generation complete!" << std::endl;
|
||||
std::cout << "Sphere center: (" << sphereConfig.centerX << ", "
|
||||
<< sphereConfig.centerY << ", " << sphereConfig.centerZ << ")" << std::endl;
|
||||
std::cout << "Sphere radius: " << sphereConfig.radius << std::endl;
|
||||
|
||||
grid.serializeToFile("output/sphere_grid.ygg3");
|
||||
grid.printStats();
|
||||
}
|
||||
|
||||
void livePreview(VoxelGrid& grid, defaults& config, const Camera& cam) {
|
||||
std::lock_guard<std::mutex> lock(PreviewMutex);
|
||||
updatePreview = true;
|
||||
@@ -148,10 +225,7 @@ void stopAndSaveAVI(defaults& config, const std::string& filename) {
|
||||
now.time_since_epoch()).count();
|
||||
std::string finalFilename = "output/recording_" + std::to_string(timestamp) + ".avi";
|
||||
|
||||
|
||||
std::cout << "Saving AVI with " << recordedFrames.size() << " frames..." << std::endl;
|
||||
|
||||
// Save using the new streaming method
|
||||
bool success = AVIWriter::saveAVIFromCompressedFrames(finalFilename, recordedFrames, config.outWidth, config.outHeight, config.fps);
|
||||
|
||||
if (success) {
|
||||
@@ -167,7 +241,7 @@ void stopAndSaveAVI(defaults& config, const std::string& filename) {
|
||||
recordingFramesRemaining = 0;
|
||||
}
|
||||
|
||||
void saveSlices(defaults& config, VoxelGrid& grid) {
|
||||
void saveSlices(const defaults& config, VoxelGrid& grid) {
|
||||
std::vector<frame> frames = grid.genSlices(frame::colormap::RGB);
|
||||
for (int i = 0; i < frames.size(); i++) {
|
||||
std::string filename = "output/slices/" + std::to_string(i) + ".bmp";
|
||||
@@ -281,6 +355,13 @@ int main() {
|
||||
float autoRotationAngle = 0.0f; // Accumulated rotation angle
|
||||
Vec3f initialUpDir = Vec3f(0, 1, 0); // Initial up direction
|
||||
|
||||
|
||||
// After your existing initialization code, add sphere parameter initialization:
|
||||
sphereConfig.centerX = config.gridWidth / 2.0f;
|
||||
sphereConfig.centerY = config.gridHeight / 2.0f;
|
||||
sphereConfig.centerZ = config.gridDepth / 2.0f;
|
||||
sphereConfig.radius = std::min(config.gridWidth, std::min(config.gridHeight, config.gridDepth)) / 4.0f;
|
||||
|
||||
// Variables for framerate limiting
|
||||
const double targetFrameTime = 1.0 / config.fps; // 30 FPS
|
||||
double lastFrameTime = glfwGetTime();
|
||||
@@ -348,14 +429,28 @@ int main() {
|
||||
camX = config.gridWidth / 2.0f;
|
||||
camY = config.gridHeight / 2.0f;
|
||||
camZ = config.gridDepth / 2.0f;
|
||||
//camYaw = 0.0f;
|
||||
//camPitch = 0.0f;
|
||||
|
||||
// Update camera position
|
||||
cam.posfor.origin = Vec3f(camX, camY, camZ);
|
||||
cam.posfor.direction = Vec3f(camvX, camvY, camvZ);
|
||||
// cam.rotateYaw(camYaw);
|
||||
// cam.rotatePitch(camPitch);
|
||||
|
||||
savePreview(grid, config, cam);
|
||||
cameraMoved = true;
|
||||
}
|
||||
|
||||
// Add the new green sphere button
|
||||
if (ImGui::Button("Create Green Sphere")) {
|
||||
createGreenSphere(config, grid);
|
||||
gridInitialized = true;
|
||||
|
||||
// Reset camera to center of grid
|
||||
camX = config.gridWidth / 2.0f;
|
||||
camY = config.gridHeight / 2.0f;
|
||||
camZ = config.gridDepth / 2.0f;
|
||||
|
||||
// Update camera position
|
||||
cam.posfor.origin = Vec3f(camX, camY, camZ);
|
||||
cam.posfor.direction = Vec3f(camvX, camvY, camvZ);
|
||||
|
||||
savePreview(grid, config, cam);
|
||||
cameraMoved = true;
|
||||
@@ -371,7 +466,7 @@ int main() {
|
||||
|
||||
if (!isRecordingAVI) {
|
||||
ImGui::InputInt("Frames to Record", &recordingDurationFrames, 30, 300);
|
||||
recordingDurationFrames = std::max(30, recordingDurationFrames); // Minimum 1 second at 30fps
|
||||
recordingDurationFrames = std::max(30, recordingDurationFrames);
|
||||
|
||||
if (ImGui::Button("Start AVI Recording")) {
|
||||
startAVIRecording(recordingDurationFrames);
|
||||
@@ -388,6 +483,7 @@ int main() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Display camera controls
|
||||
if (gridInitialized) {
|
||||
ImGui::Separator();
|
||||
@@ -452,7 +548,7 @@ int main() {
|
||||
cam.posfor.origin.z);
|
||||
// ImGui::Text("Yaw: %.2f°, Pitch: %.2f°", camYaw, camPitch);
|
||||
}
|
||||
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
@@ -607,6 +703,74 @@ int main() {
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// Add a new window for sphere configuration
|
||||
{
|
||||
ImGui::Begin("Sphere Configuration");
|
||||
|
||||
if (ImGui::CollapsingHeader("Sphere Properties", ImGuiTreeNodeFlags_DefaultOpen)) {
|
||||
ImGui::Text("Sphere Center:");
|
||||
ImGui::SliderFloat("Center X", &sphereConfig.centerX, 0.0f, static_cast<float>(config.gridWidth));
|
||||
ImGui::SliderFloat("Center Y", &sphereConfig.centerY, 0.0f, static_cast<float>(config.gridHeight));
|
||||
ImGui::SliderFloat("Center Z", &sphereConfig.centerZ, 0.0f, static_cast<float>(config.gridDepth));
|
||||
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Sphere Size:");
|
||||
float maxRadius = std::min(std::min(config.gridWidth, config.gridHeight), config.gridDepth) / 2.0f;
|
||||
ImGui::SliderFloat("Radius", &sphereConfig.radius, 5.0f, maxRadius);
|
||||
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Sphere Style:");
|
||||
ImGui::Checkbox("Fill Inside", &sphereConfig.fillInside);
|
||||
if (!sphereConfig.fillInside) {
|
||||
ImGui::Checkbox("Outline Only", &sphereConfig.outlineOnly);
|
||||
if (sphereConfig.outlineOnly) {
|
||||
ImGui::SliderFloat("Outline Thickness", &sphereConfig.outlineThickness, 0.5f, 10.0f);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Sphere Color:");
|
||||
float color[3] = {sphereConfig.r, sphereConfig.g, sphereConfig.b};
|
||||
if (ImGui::ColorEdit3("Color", color)) {
|
||||
sphereConfig.r = static_cast<uint8_t>(color[0] * 255);
|
||||
sphereConfig.g = static_cast<uint8_t>(color[1] * 255);
|
||||
sphereConfig.b = static_cast<uint8_t>(color[2] * 255);
|
||||
}
|
||||
|
||||
// Preview color
|
||||
ImGui::SameLine();
|
||||
ImVec4 previewColor = ImVec4(sphereConfig.r/255.0f, sphereConfig.g/255.0f, sphereConfig.b/255.0f, 1.0f);
|
||||
ImGui::ColorButton("##preview", previewColor, ImGuiColorEditFlags_NoTooltip, ImVec2(20, 20));
|
||||
|
||||
// Quick color presets
|
||||
if (ImGui::Button("Green")) {
|
||||
sphereConfig.r = 0;
|
||||
sphereConfig.g = 255;
|
||||
sphereConfig.b = 0;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Blue")) {
|
||||
sphereConfig.r = 0;
|
||||
sphereConfig.g = 0;
|
||||
sphereConfig.b = 255;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Red")) {
|
||||
sphereConfig.r = 255;
|
||||
sphereConfig.g = 0;
|
||||
sphereConfig.b = 0;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Random")) {
|
||||
sphereConfig.r = rand() % 256;
|
||||
sphereConfig.g = rand() % 256;
|
||||
sphereConfig.b = rand() % 256;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// Handle AVI recording start request
|
||||
if (recordingRequested) {
|
||||
isRecordingAVI = true;
|
||||
|
||||
@@ -16,14 +16,28 @@ private:
|
||||
std::vector<int> permutation;
|
||||
std::default_random_engine rng;
|
||||
|
||||
/// @brief Linear interpolation between two values
|
||||
/// @param t Interpolation factor [0,1]
|
||||
/// @param a1 First value
|
||||
/// @param a2 Second value
|
||||
/// @return Interpolated value between a1 and a2
|
||||
/// @note Changing interpolation method affects noise smoothness
|
||||
float lerp(float t, float a1, float a2) {
|
||||
return a1 + t * (a2 - a1);
|
||||
}
|
||||
|
||||
/// @brief Fade function for smooth interpolation
|
||||
/// @param t Input parameter
|
||||
/// @return Smoothed t value using 6t^5 - 15t^4 + 10t^3
|
||||
/// @note Critical for gradient continuity; changes affect noise smoothness
|
||||
static double fade(double t) {
|
||||
return t * t * t * (t * (t * 6 - 15) + 10);
|
||||
}
|
||||
|
||||
/// @brief Get constant gradient vector for 2D Perlin noise
|
||||
/// @param v Hash value (0-3)
|
||||
/// @return One of four 2D gradient vectors
|
||||
/// @note Changing vectors affects noise pattern orientation
|
||||
Vec2f GetConstantVector(int v) {
|
||||
int h = v & 3;
|
||||
if (h == 0) return Vec2f(1,1);
|
||||
@@ -32,6 +46,10 @@ private:
|
||||
else return Vec2f(1,-1);
|
||||
}
|
||||
|
||||
/// @brief Get constant gradient vector for 3D Perlin noise
|
||||
/// @param v Hash value (0-7)
|
||||
/// @return One of eight 3D gradient vectors
|
||||
/// @note Vector selection affects 3D noise patterns
|
||||
Vec3ui8 GetConstantVector3(int v) {
|
||||
int h = v & 7;
|
||||
if (h == 0) return Vec3ui8(1,1,1);
|
||||
@@ -44,6 +62,13 @@ private:
|
||||
else return Vec3ui8(1,-1, -1);
|
||||
}
|
||||
|
||||
/// @brief Gradient function for 2D/3D Perlin noise
|
||||
/// @param hash Hash value for gradient selection
|
||||
/// @param x X coordinate
|
||||
/// @param y Y coordinate
|
||||
/// @param z Z coordinate (default 0 for 2D)
|
||||
/// @return Dot product of gradient vector and distance vector
|
||||
/// @note Core of Perlin noise; changes affect basic noise character
|
||||
static double grad(int hash, double x, double y, double z = 0.0) {
|
||||
int h = hash & 15;
|
||||
double u = h < 8 ? x : y;
|
||||
@@ -51,6 +76,8 @@ private:
|
||||
return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
|
||||
}
|
||||
|
||||
/// @brief Initialize permutation table with shuffled values
|
||||
/// @note Called on construction; changing seed or shuffle affects all noise patterns
|
||||
void initializePermutation() {
|
||||
permutation.clear();
|
||||
std::vector<int> permutationt;
|
||||
@@ -63,38 +90,82 @@ private:
|
||||
permutation.insert(permutation.end(), permutationt.begin(), permutationt.end());
|
||||
}
|
||||
|
||||
/// @brief Normalize noise value from [-1,1] to [0,1]
|
||||
/// @param point Input coordinate
|
||||
/// @return Normalized noise value in [0,1] range
|
||||
/// @note Useful for texture generation; changes affect output range
|
||||
float normalizedNoise(const Vec2<float>& point) {
|
||||
return (permute(point) + 1.0f) * 0.5f;
|
||||
}
|
||||
|
||||
/// @brief Map value from one range to another
|
||||
/// @param value Input value
|
||||
/// @param inMin Original range minimum
|
||||
/// @param inMax Original range maximum
|
||||
/// @param outMin Target range minimum
|
||||
/// @param outMax Target range maximum
|
||||
/// @return Value mapped to new range
|
||||
/// @note Useful for post-processing; changes affect output scaling
|
||||
float mapRange(float value, float inMin, float inMax, float outMin, float outMax) {
|
||||
return (value - inMin) * (outMax - outMin) / (inMax - inMin) + outMin;
|
||||
}
|
||||
|
||||
/// @brief Blend two noise values
|
||||
/// @param noise1 First noise value
|
||||
/// @param noise2 Second noise value
|
||||
/// @param blendFactor Blending factor [0,1]
|
||||
/// @return Blended noise value
|
||||
/// @note Changes affect multi-layer noise combinations
|
||||
float blendNoises(float noise1, float noise2, float blendFactor) {
|
||||
return lerp(noise1, noise2, blendFactor);
|
||||
}
|
||||
|
||||
/// @brief Add two noise values with clamping
|
||||
/// @param noise1 First noise value
|
||||
/// @param noise2 Second noise value
|
||||
/// @return Sum clamped to [-1,1]
|
||||
/// @note Clamping prevents overflow; changes affect combined noise magnitude
|
||||
float addNoises(float noise1, float noise2) {
|
||||
return std::clamp(noise1 + noise2, -1.0f, 1.0f);
|
||||
}
|
||||
|
||||
/// @brief Multiply two noise values
|
||||
/// @param noise1 First noise value
|
||||
/// @param noise2 Second noise value
|
||||
/// @return Product of noise values
|
||||
/// @note Creates modulation effects; changes affect combined noise character
|
||||
float multiplyNoises(float noise1, float noise2) {
|
||||
return noise1 * noise2;
|
||||
}
|
||||
|
||||
/// @brief Hash function for 2D coordinates
|
||||
/// @param x X coordinate integer
|
||||
/// @param y Y coordinate integer
|
||||
/// @return Hash value in [-1,1] range
|
||||
/// @note Core of value noise; changes affect random distribution
|
||||
float hash(int x, int y) {
|
||||
return (permutation[(x + permutation[y & 255]) & 255] / 255.0f) * 2.0f - 1.0f;
|
||||
}
|
||||
|
||||
public:
|
||||
/// @brief Default constructor with random seed
|
||||
/// @note Uses random_device for seed; different runs produce different noise
|
||||
PNoise2() : rng(std::random_device{}()) {
|
||||
initializePermutation();
|
||||
}
|
||||
|
||||
/// @brief Constructor with specified seed
|
||||
/// @param seed Random seed value
|
||||
/// @note Same seed produces identical noise patterns across runs
|
||||
PNoise2(unsigned int seed) : rng(seed) {
|
||||
initializePermutation();
|
||||
}
|
||||
|
||||
/// @brief Generate 2D Perlin noise at given point
|
||||
/// @tparam T Coordinate type (float, double, etc.)
|
||||
/// @param point 2D coordinate
|
||||
/// @return Noise value in [-1,1] range
|
||||
/// @note Core 2D noise function; changes affect all 2D noise outputs
|
||||
template<typename T>
|
||||
float permute(Vec2<T> point) {
|
||||
TIME_FUNCTION;
|
||||
@@ -132,6 +203,11 @@ public:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/// @brief Generate 3D Perlin noise at given point
|
||||
/// @tparam T Coordinate type (float, double, etc.)
|
||||
/// @param point 3D coordinate
|
||||
/// @return Noise value in [-1,1] range
|
||||
/// @note Core 3D noise function; changes affect all 3D noise outputs
|
||||
template<typename T>
|
||||
float permute(Vec3<T> point) {
|
||||
TIME_FUNCTION;
|
||||
@@ -190,6 +266,10 @@ public:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/// @brief Generate 2D value noise (simpler alternative to Perlin)
|
||||
/// @param point 2D coordinate
|
||||
/// @return Noise value in [-1,1] range
|
||||
/// @note Different character than Perlin; changes affect value-based textures
|
||||
float valueNoise(const Vec2<float>& point) {
|
||||
int xi = (int)std::floor(point.x);
|
||||
int yi = (int)std::floor(point.y);
|
||||
@@ -218,6 +298,10 @@ public:
|
||||
return lerp(nx0, nx1, sy);
|
||||
}
|
||||
|
||||
/// @brief Generate RGBA color from 3D noise with offset channels
|
||||
/// @param point 3D coordinate
|
||||
/// @return Vec4ui8 containing RGBA noise values
|
||||
/// @note Each channel uses different offset; changes affect color patterns
|
||||
Vec4ui8 permuteColor(const Vec3<float>& point) {
|
||||
TIME_FUNCTION;
|
||||
float noiseR = permute(point);
|
||||
@@ -240,6 +324,14 @@ public:
|
||||
return Vec4ui8(r, g, b, a);
|
||||
}
|
||||
|
||||
/// @brief Generate fractal (octave) noise for natural-looking patterns
|
||||
/// @tparam T Coordinate type
|
||||
/// @param point Input coordinate
|
||||
/// @param octaves Number of noise layers
|
||||
/// @param persistence Amplitude multiplier per octave
|
||||
/// @param lacunarity Frequency multiplier per octave
|
||||
/// @return Combined noise value
|
||||
/// @note Parameters control noise character: octaves=detail, persistence=roughness, lacunarity=frequency change
|
||||
template<typename T>
|
||||
float fractalNoise(const Vec2<T>& point, int octaves, float persistence, float lacunarity) {
|
||||
float total = 0.0f;
|
||||
@@ -256,6 +348,12 @@ public:
|
||||
return total / maxV;
|
||||
}
|
||||
|
||||
/// @brief Generate turbulence noise (absolute value of octaves)
|
||||
/// @tparam T Coordinate type
|
||||
/// @param point Input coordinate
|
||||
/// @param octaves Number of noise layers
|
||||
/// @return Turbulence noise value
|
||||
/// @note Creates swirling, turbulent patterns; changes affect visual complexity
|
||||
template<typename T>
|
||||
float turbulence(const Vec2<T>& point, int octaves) {
|
||||
float value = 0.0f;
|
||||
@@ -267,6 +365,12 @@ public:
|
||||
return value;
|
||||
}
|
||||
|
||||
/// @brief Generate ridged (ridged multifractal) noise
|
||||
/// @param point Input coordinate
|
||||
/// @param octaves Number of noise layers
|
||||
/// @param offset Weighting offset for ridge formation
|
||||
/// @return Ridged noise value
|
||||
/// @note Creates sharp ridge-like patterns; offset controls ridge prominence
|
||||
float ridgedNoise(const Vec2<float>& point, int octaves, float offset = 1.0f) {
|
||||
float result = 0.f;
|
||||
float weight = 1.f;
|
||||
@@ -284,6 +388,11 @@ public:
|
||||
return result;
|
||||
}
|
||||
|
||||
/// @brief Generate billow (cloud-like) noise
|
||||
/// @param point Input coordinate
|
||||
/// @param octaves Number of noise layers
|
||||
/// @return Billow noise value
|
||||
/// @note Creates soft, billowy patterns like clouds
|
||||
float billowNoise(const Vec2<float>& point, int octaves) {
|
||||
float value = 0.0f;
|
||||
float amplitude = 1.0f;
|
||||
@@ -297,8 +406,6 @@ public:
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user