mirror of
https://github.com/Relintai/godot_voxel.git
synced 2025-01-23 17:27:20 +01:00
Optimized VoxelProviderNoise with a noise buffer so it does less OpenSimplex calculations
This commit is contained in:
parent
a521501add
commit
017f64ddb9
@ -42,7 +42,32 @@ void VoxelProviderNoise::emerge_block(Ref<VoxelBuffer> out_buffer, Vector3i orig
|
||||
|
||||
} else {
|
||||
|
||||
FloatBuffer3D &noise_buffer = _noise_buffer;
|
||||
const int noise_buffer_step = 2;
|
||||
|
||||
Vector3i noise_buffer_size = buffer.get_size() / noise_buffer_step + Vector3i(1);
|
||||
if (noise_buffer.get_size() != noise_buffer_size) {
|
||||
noise_buffer.create(noise_buffer_size);
|
||||
}
|
||||
|
||||
// Cache noise at lower grid resolution and interpolate after, much cheaper
|
||||
for (int z = 0; z < noise_buffer.get_size().z; ++z) {
|
||||
for (int x = 0; x < noise_buffer.get_size().x; ++x) {
|
||||
for (int y = 0; y < noise_buffer.get_size().y; ++y) {
|
||||
|
||||
float lx = origin_in_voxels.x + (x << lod) * noise_buffer_step;
|
||||
float ly = origin_in_voxels.y + (y << lod) * noise_buffer_step;
|
||||
float lz = origin_in_voxels.z + (z << lod) * noise_buffer_step;
|
||||
|
||||
float n = noise.get_noise_3d(lx, ly, lz);
|
||||
|
||||
noise_buffer.set(x, y, z, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float iso_scale = noise.get_period() * 0.1;
|
||||
float noise_buffer_scale = 1.f / static_cast<float>(noise_buffer_step);
|
||||
|
||||
for (int z = 0; z < buffer.get_size().z; ++z) {
|
||||
for (int x = 0; x < buffer.get_size().x; ++x) {
|
||||
@ -50,13 +75,8 @@ void VoxelProviderNoise::emerge_block(Ref<VoxelBuffer> out_buffer, Vector3i orig
|
||||
|
||||
float ly = origin_in_voxels.y + (y << lod);
|
||||
|
||||
float n = noise.get_noise_3d(
|
||||
origin_in_voxels.x + (x << lod),
|
||||
ly,
|
||||
origin_in_voxels.z + (z << lod));
|
||||
|
||||
float n = noise_buffer.get_trilinear(x * noise_buffer_scale, y * noise_buffer_scale, z * noise_buffer_scale);
|
||||
float t = (ly - _height_start) / _height_range;
|
||||
|
||||
float d = (n + 2.0 * t - 1.0) * iso_scale;
|
||||
|
||||
buffer.set_voxel_f(d, x, y, z, VoxelBuffer::CHANNEL_ISOLEVEL);
|
||||
|
@ -1,6 +1,7 @@
|
||||
#ifndef VOXEL_PROVIDER_NOISE_H
|
||||
#define VOXEL_PROVIDER_NOISE_H
|
||||
|
||||
#include "../util/float_buffer_3d.h"
|
||||
#include "voxel_provider.h"
|
||||
#include <modules/opensimplex/open_simplex_noise.h>
|
||||
|
||||
@ -23,6 +24,7 @@ protected:
|
||||
|
||||
private:
|
||||
Ref<OpenSimplexNoise> _noise;
|
||||
FloatBuffer3D _noise_buffer;
|
||||
float _height_start = 0;
|
||||
float _height_range = 300;
|
||||
};
|
||||
|
80
util/float_buffer_3d.cpp
Normal file
80
util/float_buffer_3d.cpp
Normal file
@ -0,0 +1,80 @@
|
||||
#include "float_buffer_3d.h"
|
||||
#include "utility.h"
|
||||
|
||||
FloatBuffer3D::~FloatBuffer3D() {
|
||||
clear();
|
||||
}
|
||||
|
||||
void FloatBuffer3D::clear() {
|
||||
if (_data) {
|
||||
memfree(_data);
|
||||
_data = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void FloatBuffer3D::create(Vector3i size) {
|
||||
ERR_FAIL_COND(size.x <= 0);
|
||||
ERR_FAIL_COND(size.y <= 0);
|
||||
ERR_FAIL_COND(size.z <= 0);
|
||||
clear();
|
||||
_data = (float *)memalloc(size.x * size.y * size.z * sizeof(float));
|
||||
_size = size;
|
||||
}
|
||||
|
||||
void FloatBuffer3D::fill(float v) {
|
||||
ERR_FAIL_COND(_data == nullptr);
|
||||
int count = _size.x * _size.y * _size.z;
|
||||
for (int i = 0; i < count; ++i) {
|
||||
_data[i] = v;
|
||||
}
|
||||
}
|
||||
|
||||
float FloatBuffer3D::get(int x, int y, int z) const {
|
||||
ERR_FAIL_COND_V(_data == nullptr, 0);
|
||||
ERR_FAIL_COND_V(x < 0 || x >= _size.x, 0);
|
||||
ERR_FAIL_COND_V(y < 0 || y >= _size.y, 0);
|
||||
ERR_FAIL_COND_V(z < 0 || z >= _size.z, 0);
|
||||
return _data[get_index(x, y, z)];
|
||||
}
|
||||
|
||||
void FloatBuffer3D::set(int x, int y, int z, float v) {
|
||||
ERR_FAIL_COND(_data == nullptr);
|
||||
ERR_FAIL_COND(x < 0 || x >= _size.x);
|
||||
ERR_FAIL_COND(y < 0 || y >= _size.y);
|
||||
ERR_FAIL_COND(z < 0 || z >= _size.z);
|
||||
_data[get_index(x, y, z)] = v;
|
||||
}
|
||||
|
||||
float FloatBuffer3D::get_clamped(int x, int y, int z) const {
|
||||
ERR_FAIL_COND_V(_data == nullptr, 0);
|
||||
x = x >= _size.x ? _size.x - 1 : x;
|
||||
y = y >= _size.y ? _size.y - 1 : y;
|
||||
z = z >= _size.z ? _size.z - 1 : z;
|
||||
return _data[get_index(x, y, z)];
|
||||
}
|
||||
|
||||
float FloatBuffer3D::get_trilinear(float x, float y, float z) const {
|
||||
ERR_FAIL_COND_V(_data == nullptr, 0);
|
||||
|
||||
int x0 = static_cast<int>(x);
|
||||
int y0 = static_cast<int>(y);
|
||||
int z0 = static_cast<int>(z);
|
||||
|
||||
int x1 = static_cast<int>(Math::ceil(x));
|
||||
int y1 = static_cast<int>(Math::ceil(y));
|
||||
int z1 = static_cast<int>(Math::ceil(z));
|
||||
|
||||
float v0 = get_clamped(x0, y0, z0);
|
||||
float v1 = get_clamped(x1, y0, z0);
|
||||
float v2 = get_clamped(x1, y0, z1);
|
||||
float v3 = get_clamped(x0, y0, z1);
|
||||
|
||||
float v4 = get_clamped(x0, y1, z0);
|
||||
float v5 = get_clamped(x1, y1, z0);
|
||||
float v6 = get_clamped(x1, y1, z1);
|
||||
float v7 = get_clamped(x0, y1, z1);
|
||||
|
||||
Vector3 rpos(x - x0, y - y0, z - z0);
|
||||
|
||||
return interpolate(v0, v1, v2, v3, v4, v5, v6, v7, rpos);
|
||||
}
|
32
util/float_buffer_3d.h
Normal file
32
util/float_buffer_3d.h
Normal file
@ -0,0 +1,32 @@
|
||||
#ifndef FLOAT_BUFFER_3D_H
|
||||
#define FLOAT_BUFFER_3D_H
|
||||
|
||||
#include "../math/vector3i.h"
|
||||
|
||||
// Simple 3D array of floats, until VoxelBuffer supports higher-precision
|
||||
class FloatBuffer3D {
|
||||
public:
|
||||
~FloatBuffer3D();
|
||||
|
||||
void clear();
|
||||
void create(Vector3i size);
|
||||
void fill(float v);
|
||||
|
||||
inline const Vector3i &get_size() const { return _size; }
|
||||
|
||||
float get(int x, int y, int z) const;
|
||||
float get_clamped(int x, int y, int z) const;
|
||||
float get_trilinear(float x, float y, float z) const;
|
||||
|
||||
void set(int x, int y, int z, float v);
|
||||
|
||||
private:
|
||||
inline int get_index(int x, int y, int z) const {
|
||||
return y + _size.y * (x + _size.x * z);
|
||||
}
|
||||
|
||||
float *_data = nullptr;
|
||||
Vector3i _size;
|
||||
};
|
||||
|
||||
#endif // FLOAT_BUFFER_3D_H
|
Loading…
Reference in New Issue
Block a user