Support modifiers in distance normalmaps

master
Marc Gilleron 2022-08-07 23:03:45 +01:00
parent 5bb0f4a508
commit b0cd02a2ef
5 changed files with 80 additions and 8 deletions

View File

@ -1,5 +1,6 @@
#include "distance_normalmaps.h"
#include "../../generators/voxel_generator.h"
#include "../../storage/voxel_data_map.h"
#include "../../util/math/conv.h"
#include "../../util/math/triangle.h"
#include "../../util/profiling.h"
@ -166,7 +167,8 @@ inline Vector3f encode_normal_xyz(const Vector3f n) {
// Sample voxels inside the cell to compute a tile of world space normals from the SDF.
void compute_normalmap(Span<const transvoxel::CellInfo> cell_infos, const transvoxel::MeshArrays &mesh,
NormalMapData &normal_map_data, unsigned int tile_resolution, VoxelGenerator &generator,
Vector3i origin_in_voxels, unsigned int lod_index, bool octahedral_encoding) {
const VoxelDataLodMap *voxel_data, Vector3i origin_in_voxels, unsigned int lod_index,
bool octahedral_encoding) {
ZN_PROFILE_SCOPE();
ZN_ASSERT_RETURN(generator.supports_series_generation());
@ -289,11 +291,34 @@ void compute_normalmap(Span<const transvoxel::CellInfo> cell_infos, const transv
tls_sdf_buffer.resize(tls_x_buffer.size());
// Query voxel data
// TODO Support edited voxels
// TODO Support modifiers
generator.generate_series(to_span(tls_x_buffer), to_span(tls_y_buffer), to_span(tls_z_buffer),
VoxelBufferInternal::CHANNEL_SDF, to_span(tls_sdf_buffer), cell_origin_world,
cell_origin_world + Vector3f(cell_size));
{
const Vector3f query_min_pos = cell_origin_world;
const Vector3f query_max_pos = cell_origin_world + Vector3f(cell_size);
generator.generate_series(to_span(tls_x_buffer), to_span(tls_y_buffer), to_span(tls_z_buffer),
VoxelBufferInternal::CHANNEL_SDF, to_span(tls_sdf_buffer), query_min_pos, query_max_pos);
if (voxel_data != nullptr) {
voxel_data->modifiers.apply(to_span(tls_x_buffer), to_span(tls_y_buffer), to_span(tls_z_buffer),
to_span(tls_sdf_buffer), query_min_pos, query_max_pos);
// TODO Support edited voxels
// Naive method:
// Do 4 single sample queries for every pixel. In each sample, check if there is edited data. If yes,
// interpolate linearly it with 8 neighbors. Neighbors are obtained through single queries too. If the
// sample is not edited, use the generator and modifiers.
// It seems extremely slow though...
// const Vector3i query_min_pos_i = math::floor_to_int(query_min_pos);
// const Vector3i query_max_pos_i = math::ceil_to_int(query_max_pos);
// VoxelDataGrid grid;
// {
// const VoxelDataLodMap::Lod &lod0 = voxel_data->lods[0];
// RWLockRead rlock(lod0.map_lock);
// grid.reference_area(lod0.map, Box3i::from_min_max(query_min_pos_i, query_max_pos_i));
// }
}
}
static thread_local std::vector<Vector3f> tls_tile_normals;
tls_tile_normals.clear();

View File

@ -14,6 +14,7 @@ class Image;
namespace zylann::voxel {
class VoxelGenerator;
struct VoxelDataLodMap;
// TODO This system could be extended to more than just normals (texturing)
@ -43,7 +44,7 @@ struct NormalMapData {
// Sample voxels inside the cell to compute a tile of world space normals from the SDF.
void compute_normalmap(Span<const transvoxel::CellInfo> cell_infos, const transvoxel::MeshArrays &mesh,
NormalMapData &normal_map_data, unsigned int tile_resolution, VoxelGenerator &generator,
Vector3i origin_in_voxels, unsigned int lod_index, bool octahedral_encoding);
const VoxelDataLodMap *voxel_data, Vector3i origin_in_voxels, unsigned int lod_index, bool octahedral_encoding);
struct NormalMapImages {
Vector<Ref<Image>> atlas_images;

View File

@ -281,7 +281,7 @@ void VoxelMesherTransvoxel::build(VoxelMesher::Output &output, const VoxelMesher
// - So the mesh can be obtained sooner
// - And we can prevent it from updating as frequently as the mesh if repeatedly modified
compute_normalmap(to_span(*cell_infos), tls_mesh_arrays, tls_normalmap_data, tile_resolution, *input.generator,
input.origin_in_voxels + offset, input.lod, settings.octahedral_encoding_enabled);
input.data, input.origin_in_voxels + offset, input.lod, settings.octahedral_encoding_enabled);
const Vector3i block_size =
input.voxels.get_size() - Vector3iUtil::create(get_minimum_padding() + get_maximum_padding());

View File

@ -31,6 +31,20 @@ Span<const Vector3> get_positions_temporary(Vector3i buffer_size, Vector3 origin
return positions;
}
Span<const Vector3> get_positions_temporary(
Span<const float> x_buffer, Span<const float> y_buffer, Span<const float> z_buffer) {
ZN_ASSERT(x_buffer.size() == z_buffer.size() && y_buffer.size() == z_buffer.size());
tls_positions.resize(x_buffer.size());
Span<Vector3> positions = to_span(tls_positions);
for (unsigned int i = 0; i < x_buffer.size(); ++i) {
positions[i] = Vector3(x_buffer[i], y_buffer[i], z_buffer[i]);
}
return positions;
}
Span<float> decompress_sdf_to_temporary(VoxelBufferInternal &voxels) {
ZN_DSTACK();
const Vector3i bs = voxels.get_size();
@ -246,6 +260,31 @@ void VoxelModifierStack::apply(float &sdf, Vector3 position) const {
}
}
void VoxelModifierStack::apply(Span<const float> x_buffer, Span<const float> y_buffer, Span<const float> z_buffer,
Span<float> sdf_buffer, Vector3f min_pos, Vector3f max_pos) const {
ZN_PROFILE_SCOPE();
RWLockRead lock(_stack_lock);
if (_stack.size() == 0) {
return;
}
VoxelModifierContext ctx;
ctx.positions = get_positions_temporary(x_buffer, y_buffer, z_buffer);
ctx.sdf = sdf_buffer;
const AABB aabb(to_vec3(min_pos), to_vec3(max_pos - min_pos));
for (unsigned int i = 0; i < _stack.size(); ++i) {
const VoxelModifier *modifier = _stack[i];
ZN_ASSERT(modifier != nullptr);
if (modifier->get_aabb().intersects(aabb)) {
modifier->apply(ctx);
}
}
}
void VoxelModifierStack::clear() {
RWLockWrite lock(_stack_lock);
_stack.clear();

View File

@ -140,6 +140,11 @@ private:
float _isolevel;
};
// TODO Capsule
// TODO Box
// TODO Heightmap
// TODO Graph (using generator graph as a brush?)
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class VoxelModifierStack {
@ -167,6 +172,8 @@ public:
VoxelModifier *get_modifier(uint32_t id) const;
void apply(VoxelBufferInternal &voxels, AABB aabb) const;
void apply(float &sdf, Vector3 position) const;
void apply(Span<const float> x_buffer, Span<const float> y_buffer, Span<const float> z_buffer,
Span<float> sdf_buffer, Vector3f min_pos, Vector3f max_pos) const;
void clear();
private: