Support modifiers in distance normalmaps
parent
5bb0f4a508
commit
b0cd02a2ef
|
@ -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
|
||||
{
|
||||
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), cell_origin_world,
|
||||
cell_origin_world + Vector3f(cell_size));
|
||||
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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue