From a95b030ff1fcec1912482ad7a8e6d0331a68ef74 Mon Sep 17 00:00:00 2001 From: Marc Gilleron Date: Sun, 9 Jun 2024 20:14:35 +0100 Subject: [PATCH] Formatting --- edition/mesh_sdf.cpp | 204 ++++++++++++++++++++------ edition/mesh_sdf.h | 62 ++++++-- edition/voxel_tool.cpp | 96 ++++++++---- edition/voxel_tool.h | 34 +++-- edition/voxel_tool_buffer.cpp | 12 +- edition/voxel_tool_buffer.h | 9 +- meshers/cubes/voxel_color_palette.cpp | 16 +- meshers/voxel_mesher.cpp | 53 +++++-- 8 files changed, 363 insertions(+), 123 deletions(-) diff --git a/edition/mesh_sdf.cpp b/edition/mesh_sdf.cpp index 30f0b0deb..76fe4e6fe 100644 --- a/edition/mesh_sdf.cpp +++ b/edition/mesh_sdf.cpp @@ -8,12 +8,12 @@ #include "../util/voxel_raycast.h" // Debug -//#define ZN_MESH_SDF_DEBUG_SLICES +// #define ZN_MESH_SDF_DEBUG_SLICES #ifdef ZN_MESH_SDF_DEBUG_SLICES #include "../util/math/color.h" #include #endif -//#define ZN_MESH_SDF_DEBUG_BATCH +// #define ZN_MESH_SDF_DEBUG_BATCH #ifdef ZN_MESH_SDF_DEBUG_BATCH #include "../ddd.h" #endif @@ -31,12 +31,18 @@ namespace zylann::voxel::mesh_sdf { // First tries with floats, as it is the most common case when data is float. // In case of occasional parallel results, retry with doubles, as it often clears it up. -math::TriangleIntersectionResult ray_intersects_triangle2(const Vector3f &p_from, const Vector3f &p_dir, - const Vector3f &p_v0, const Vector3f &p_v1, const Vector3f &p_v2) { +math::TriangleIntersectionResult ray_intersects_triangle2( + const Vector3f &p_from, + const Vector3f &p_dir, + const Vector3f &p_v0, + const Vector3f &p_v1, + const Vector3f &p_v2 +) { math::TriangleIntersectionResult r = math::ray_intersects_triangle(p_from, p_dir, p_v0, p_v1, p_v2); if (r.case_id == math::TriangleIntersectionResult::PARALLEL) { r = math::ray_intersects_triangle( - to_vec3d(p_from), to_vec3d(p_dir), to_vec3d(p_v0), to_vec3d(p_v1), to_vec3d(p_v2)); + to_vec3d(p_from), to_vec3d(p_dir), to_vec3d(p_v0), to_vec3d(p_v1), to_vec3d(p_v2) + ); } return r; } @@ -110,7 +116,9 @@ const Triangle *raycast(const ChunkGrid &chunk_grid, Vector3f ray_position, Vect #ifdef ZN_MESH_SDF_DEBUG_BATCH DDD::draw_wirebox_min_max( // to_vec3f(cpos) * chunk_grid.chunk_size + chunk_grid.min_pos, - to_vec3f(cpos + Vector3i(1, 1, 1)) * chunk_grid.chunk_size + chunk_grid.min_pos, Color(0, 1, 1)); + to_vec3f(cpos + Vector3i(1, 1, 1)) * chunk_grid.chunk_size + chunk_grid.min_pos, + Color(0, 1, 1) + ); #endif const unsigned int loc = Vector3iUtil::get_zxy_index(rs.hit_prev_position, chunk_grid.size); ZN_ASSERT(loc < chunk_grid.chunks.size()); @@ -156,8 +164,16 @@ const Triangle *raycast(const ChunkGrid &chunk_grid, Vector3f ray_position, Vect Vector3i hit_prev_chunk_pos; float distance_along_ray; float distance_along_ray_prev; - if (!voxel_raycast(cposf, ray_dir, raycast_chunk, max_distance_chunks, hit_chunk_pos, hit_prev_chunk_pos, - distance_along_ray, distance_along_ray_prev)) { + if (!voxel_raycast( + cposf, + ray_dir, + raycast_chunk, + max_distance_chunks, + hit_chunk_pos, + hit_prev_chunk_pos, + distance_along_ray, + distance_along_ray_prev + )) { // In case the distance to travel is smaller than a chunk, the voxel_raycast won't "enter" any chunk and return // false. Note, `hit_position` isn't used. raycast_chunk({ math::floor_to_int(cposf), 0.f, Vector3i(), max_distance }); @@ -168,7 +184,11 @@ const Triangle *raycast(const ChunkGrid &chunk_grid, Vector3f ray_position, Vect } bool find_sdf_sign_with_raycast( - const ChunkGrid &chunk_grid, Vector3f ray_position, const Triangle &ref_triangle, int &out_sign) { + const ChunkGrid &chunk_grid, + Vector3f ray_position, + const Triangle &ref_triangle, + int &out_sign +) { // ZN_PROFILE_SCOPE(); const Vector3f ref_center = (ref_triangle.v1 + ref_triangle.v2 + ref_triangle.v3) / 3.f; @@ -191,7 +211,8 @@ bool find_sdf_sign_with_raycast( if (s_tri_not_found_error == false) { s_tri_not_found_error = true; ZN_PRINT_VERBOSE( - format("Could not find triangle by raycast, dp: {}", math::dot(get_normal(ref_triangle), ray_dir))); + format("Could not find triangle by raycast, dp: {}", math::dot(get_normal(ref_triangle), ray_dir)) + ); } #endif return false; @@ -243,8 +264,14 @@ enum Flag { // FLAG_FROZEN }; -void fix_sdf_sign_from_boundary(Span sdf_grid, Span flag_grid, Vector3i res, Vector3f min_pos, - Vector3f max_pos, StdVector &seeds) { +void fix_sdf_sign_from_boundary( + Span sdf_grid, + Span flag_grid, + Vector3i res, + Vector3f min_pos, + Vector3f max_pos, + StdVector &seeds +) { ZN_PROFILE_SCOPE(); ZN_ASSERT(sdf_grid.size() == flag_grid.size()); @@ -413,7 +440,12 @@ void compute_near_chunks(ChunkGrid &chunk_grid) { } void partition_triangles( - int subdiv, Span triangles, Vector3f min_pos, Vector3f max_pos, ChunkGrid &chunk_grid) { + int subdiv, + Span triangles, + Vector3f min_pos, + Vector3f max_pos, + ChunkGrid &chunk_grid +) { ZN_PROFILE_SCOPE(); // TODO This rarely causes SDF errors, but not sure yet what it is yet @@ -547,10 +579,13 @@ float get_distance_to_triangle_squared_precalc(const Triangle &t, const Vector3f if (det < 2.f) { // Outside of the prism: get distance to closest edge - return min(min( // - length_squared(t.v21 * clamp(dot(t.v21, p1) * t.inv_v21_length_squared, 0.f, 1.f) - p1), - length_squared(t.v32 * clamp(dot(t.v32, p2) * t.inv_v32_length_squared, 0.f, 1.f) - p2)), - length_squared(t.v13 * clamp(dot(t.v13, p3) * t.inv_v13_length_squared, 0.f, 1.f) - p3)); + return min( + min( // + length_squared(t.v21 * clamp(dot(t.v21, p1) * t.inv_v21_length_squared, 0.f, 1.f) - p1), + length_squared(t.v32 * clamp(dot(t.v32, p2) * t.inv_v32_length_squared, 0.f, 1.f) - p2) + ), + length_squared(t.v13 * clamp(dot(t.v13, p3) * t.inv_v13_length_squared, 0.f, 1.f) - p3) + ); } else { // Inside the prism: get distance to plane return squared(dot(t.nor, p1)) * t.inv_nor_length_squared; @@ -737,8 +772,13 @@ struct EvaluatorCG { } }; -void generate_mesh_sdf_approx_interp(Span sdf_grid, const Vector3i res, Span triangles, - const Vector3f min_pos, const Vector3f max_pos) { +void generate_mesh_sdf_approx_interp( + Span sdf_grid, + const Vector3i res, + Span triangles, + const Vector3f min_pos, + const Vector3f max_pos +) { ZN_PROFILE_SCOPE(); static const float FAR_SD = 9999999.f; @@ -848,7 +888,8 @@ void generate_mesh_sdf_approx_interp(Span sdf_grid, const Vector3i res, S } const Vector3f ipf = to_vec3f(grid_pos - cell_box.position) / float(node_size_cells); const float sd = math::interpolate_trilinear( - sd000, sd100, sd101, sd001, sd010, sd110, sd111, sd011, ipf); + sd000, sd100, sd101, sd001, sd010, sd110, sd111, sd011, ipf + ); ZN_ASSERT(i < sdf_grid.size()); sdf_grid[i] = sd; } @@ -860,8 +901,14 @@ void generate_mesh_sdf_approx_interp(Span sdf_grid, const Vector3i res, S } } -void generate_mesh_sdf_naive(Span sdf_grid, const Vector3i res, const Box3i sub_box, - Span triangles, const Vector3f min_pos, const Vector3f max_pos) { +void generate_mesh_sdf_naive( + Span sdf_grid, + const Vector3i res, + const Box3i sub_box, + Span triangles, + const Vector3f min_pos, + const Vector3f max_pos +) { ZN_PROFILE_SCOPE(); ZN_ASSERT(Box3i(Vector3i(), res).contains(sub_box)); ZN_ASSERT(int64_t(sdf_grid.size()) == Vector3iUtil::get_volume(res)); @@ -894,8 +941,14 @@ void generate_mesh_sdf_naive(Span sdf_grid, const Vector3i res, const Box // println(format("Spent {} usec", usec)); } -void generate_mesh_sdf_partitioned(Span sdf_grid, const Vector3i res, const Box3i sub_box, - const Vector3f min_pos, const Vector3f max_pos, const ChunkGrid &chunk_grid) { +void generate_mesh_sdf_partitioned( + Span sdf_grid, + const Vector3i res, + const Box3i sub_box, + const Vector3f min_pos, + const Vector3f max_pos, + const ChunkGrid &chunk_grid +) { ZN_PROFILE_SCOPE(); ZN_ASSERT(Box3i(Vector3i(), res).contains(sub_box)); ZN_ASSERT(int64_t(sdf_grid.size()) == Vector3iUtil::get_volume(res)); @@ -924,8 +977,14 @@ void generate_mesh_sdf_partitioned(Span sdf_grid, const Vector3i res, con } } -void generate_mesh_sdf_partitioned(Span sdf_grid, const Vector3i res, Span triangles, - const Vector3f min_pos, const Vector3f max_pos, int subdiv) { +void generate_mesh_sdf_partitioned( + Span sdf_grid, + const Vector3i res, + Span triangles, + const Vector3f min_pos, + const Vector3f max_pos, + int subdiv +) { // TODO Make this thread-local? ChunkGrid chunk_grid; partition_triangles(subdiv, triangles, min_pos, max_pos, chunk_grid); @@ -934,7 +993,12 @@ void generate_mesh_sdf_partitioned(Span sdf_grid, const Vector3i res, Spa } CheckResult check_sdf( - Span sdf_grid, Vector3i res, Span triangles, Vector3f min_pos, Vector3f max_pos) { + Span sdf_grid, + Vector3i res, + Span triangles, + Vector3f min_pos, + Vector3f max_pos +) { CheckResult result; result.ok = false; @@ -970,7 +1034,7 @@ CheckResult check_sdf( const Vector3i npos = pos + dirs[dir]; if (npos.x < 0 || npos.y < 0 || npos.z < 0 || npos.x >= res.x || npos.y >= res.y || - npos.z >= res.z) { + npos.z >= res.z) { continue; } @@ -983,8 +1047,15 @@ CheckResult check_sdf( const float variation = Math::abs(v - nv); if (variation > max_variation) { - ZN_PRINT_VERBOSE(format("Found variation of {} > {}, {} and {}, at cell {} and {}", variation, - max_variation, v, nv, pos, npos)); + ZN_PRINT_VERBOSE( + format("Found variation of {} > {}, {} and {}, at cell {} and {}", + variation, + max_variation, + v, + nv, + pos, + npos) + ); const Vector3f posf0 = eval.grid_to_space(pos); const Vector3f posf1 = eval.grid_to_space(npos); @@ -1010,13 +1081,23 @@ CheckResult check_sdf( return result; } -void generate_mesh_sdf_naive(Span sdf_grid, const Vector3i res, Span triangles, - const Vector3f min_pos, const Vector3f max_pos) { +void generate_mesh_sdf_naive( + Span sdf_grid, + const Vector3i res, + Span triangles, + const Vector3f min_pos, + const Vector3f max_pos +) { generate_mesh_sdf_naive(sdf_grid, res, Box3i(Vector3i(), res), triangles, min_pos, max_pos); } -bool prepare_triangles(Span vertices, Span indices, StdVector &triangles, - Vector3f &out_min_pos, Vector3f &out_max_pos) { +bool prepare_triangles( + Span vertices, + Span indices, + StdVector &triangles, + Vector3f &out_min_pos, + Vector3f &out_max_pos +) { ZN_PROFILE_SCOPE(); // The mesh can't be closed if it has less than 4 vertices @@ -1082,10 +1163,17 @@ void GenMeshSDFSubBoxTask::run(ThreadedTaskContext &ctx) { if (shared_data->use_chunk_grid) { generate_mesh_sdf_partitioned( - sdf_grid, buffer.get_size(), box, shared_data->min_pos, shared_data->max_pos, shared_data->chunk_grid); + sdf_grid, buffer.get_size(), box, shared_data->min_pos, shared_data->max_pos, shared_data->chunk_grid + ); } else { - generate_mesh_sdf_naive(sdf_grid, buffer.get_size(), box, to_span(shared_data->triangles), shared_data->min_pos, - shared_data->max_pos); + generate_mesh_sdf_naive( + sdf_grid, + buffer.get_size(), + box, + to_span(shared_data->triangles), + shared_data->min_pos, + shared_data->max_pos + ); } if (shared_data->pending_jobs.fetch_sub(1, std::memory_order_acq_rel) == 1) { @@ -1100,7 +1188,11 @@ void GenMeshSDFSubBoxTask::run(ThreadedTaskContext &ctx) { static const float FAR_SD = 9999999.f; int find_sdf_sign_with_raycast_multi_attempt( - const ChunkGrid &chunk_grid, Span triangles, Vector3f pos, unsigned int &ref_triangle_index) { + const ChunkGrid &chunk_grid, + Span triangles, + Vector3f pos, + unsigned int &ref_triangle_index +) { // TODO Optimization: It could be faster to target a triangle close to the cell? int sign_sum = 0; // Do multiple raycasts to reduce ambiguity. @@ -1125,9 +1217,16 @@ int find_sdf_sign_with_raycast_multi_attempt( return sign_sum; } -void generate_mesh_sdf_hull(Span sdf_grid, const Vector3i res, Span triangles, - const Vector3f min_pos, const Vector3f max_pos, const ChunkGrid &chunk_grid, Span flag_grid, - uint8_t near_surface_flag_value) { +void generate_mesh_sdf_hull( + Span sdf_grid, + const Vector3i res, + Span triangles, + const Vector3f min_pos, + const Vector3f max_pos, + const ChunkGrid &chunk_grid, + Span flag_grid, + uint8_t near_surface_flag_value +) { ZN_PROFILE_SCOPE(); ZN_ASSERT(sdf_grid.size() == flag_grid.size()); @@ -1212,7 +1311,8 @@ void generate_mesh_sdf_hull(Span sdf_grid, const Vector3i res, Span sdf_grid, Vector3i res, const int y, int iteration, StdVector *seeds) { + Span sdf_grid, + Vector3i res, + const int y, + int iteration, + StdVector *seeds +) { Ref im; im.instantiate(); im->create(res.x, res.z, false, Image::FORMAT_RGB8); @@ -1282,8 +1387,15 @@ void debug_print_sdf_image_slice( #endif -void generate_mesh_sdf_approx_floodfill(Span sdf_grid, const Vector3i res, Span triangles, - const ChunkGrid &chunk_grid, const Vector3f min_pos, const Vector3f max_pos, bool boundary_sign_fix) { +void generate_mesh_sdf_approx_floodfill( + Span sdf_grid, + const Vector3i res, + Span triangles, + const ChunkGrid &chunk_grid, + const Vector3f min_pos, + const Vector3f max_pos, + bool boundary_sign_fix +) { ZN_PROFILE_SCOPE(); StdVector flag_grid; @@ -1325,7 +1437,7 @@ void generate_mesh_sdf_approx_floodfill(Span sdf_grid, const Vector3i res for (unsigned int dir = 0; dir < dirs6.size(); ++dir) { const Vector3i npos = pos + dirs6[dir]; if (npos.x < 0 || npos.y < 0 || npos.z < 0 || npos.x >= res.x || npos.y >= res.y || - npos.z >= res.z) { + npos.z >= res.z) { continue; } diff --git a/edition/mesh_sdf.h b/edition/mesh_sdf.h index 7d953c5eb..8360fb1fc 100644 --- a/edition/mesh_sdf.h +++ b/edition/mesh_sdf.h @@ -77,13 +77,23 @@ class GenMeshSDFSubBoxTask : public IThreadedTask { }; // Computes a representation of the mesh that's more optimal to compute distance to triangles. -bool prepare_triangles(Span vertices, Span indices, StdVector &triangles, - Vector3f &out_min_pos, Vector3f &out_max_pos); +bool prepare_triangles( + Span vertices, + Span indices, + StdVector &triangles, + Vector3f &out_min_pos, + Vector3f &out_max_pos +); // Partitions triangles of the mesh such that we can reduce the number of triangles to check when evaluating the SDF. // Space is subdivided in a grid of chunks. Triangles overlapping chunks are listed. void partition_triangles( - int subdiv, Span triangles, Vector3f min_pos, Vector3f max_pos, ChunkGrid &chunk_grid); + int subdiv, + Span triangles, + Vector3f min_pos, + Vector3f max_pos, + ChunkGrid &chunk_grid +); // For each chunk, finds which other non-empty chunks are close to it. The amount of subvidisions should be carefully // chosen: too low will cause less triangles to be skipped, too high will make partitionning slower. @@ -93,22 +103,38 @@ void compute_near_chunks(ChunkGrid &chunk_grid); // A naive method to get a sampled SDF from a mesh, by checking every triangle at every cell. It's accurate, but much // slower than other techniques, but could be used as a CPU-based alternative, for less // realtime-intensive tasks. The mesh must be closed, otherwise the SDF will contain errors. -void generate_mesh_sdf_naive(Span sdf_grid, const Vector3i res, Span triangles, - const Vector3f min_pos, const Vector3f max_pos); +void generate_mesh_sdf_naive( + Span sdf_grid, + const Vector3i res, + Span triangles, + const Vector3f min_pos, + const Vector3f max_pos +); // Compute the SDF faster by partitionning triangles, while retaining the same accuracy as if all triangles // were checked. With Suzanne mesh subdivided once with 3900 triangles and `subdiv = 32`, it's about 8 times fasterthan // checking every triangle on every cell. -void generate_mesh_sdf_partitioned(Span sdf_grid, const Vector3i res, Span triangles, - const Vector3f min_pos, const Vector3f max_pos, int subdiv); +void generate_mesh_sdf_partitioned( + Span sdf_grid, + const Vector3i res, + Span triangles, + const Vector3f min_pos, + const Vector3f max_pos, + int subdiv +); // Generates an approximation. // Subdivides the grid into nodes spanning 4*4*4 cells each. // If a node's corner distances are close to the surface, the SDF is fully evaluated. Otherwise, it is interpolated. // Tests with Suzanne show it is 2 to 3 times faster than the basic naive method, with only minor quality decrease. // It's still quite slow though. -void generate_mesh_sdf_approx_interp(Span sdf_grid, const Vector3i res, Span triangles, - const Vector3f min_pos, const Vector3f max_pos); +void generate_mesh_sdf_approx_interp( + Span sdf_grid, + const Vector3i res, + Span triangles, + const Vector3f min_pos, + const Vector3f max_pos +); Vector3i auto_compute_grid_resolution(const Vector3f box_size, int cell_count); @@ -126,7 +152,12 @@ struct CheckResult { // Checks if SDF variations are legit. The difference between two neighboring cells cannot be higher than the distance // between those two cells. This is intended at proper SDF, not approximation or scaled ones. CheckResult check_sdf( - Span sdf_grid, Vector3i res, Span triangles, Vector3f min_pos, Vector3f max_pos); + Span sdf_grid, + Vector3i res, + Span triangles, + Vector3f min_pos, + Vector3f max_pos +); // The current method provides imperfect signs. Due to ambiguities, sometimes patches of cells get the wrong sign. // This function attempts to correct these. @@ -140,8 +171,15 @@ void fix_sdf_sign_from_boundary(Span sdf_grid, Vector3i res, Vector3f min // Generates an approximation. // Calculates a thin hull of accurate SDF values, then propagates it with a 26-way floodfill. -void generate_mesh_sdf_approx_floodfill(Span sdf_grid, const Vector3i res, Span triangles, - const ChunkGrid &chunk_grid, const Vector3f min_pos, const Vector3f max_pos, bool boundary_sign_fix); +void generate_mesh_sdf_approx_floodfill( + Span sdf_grid, + const Vector3i res, + Span triangles, + const ChunkGrid &chunk_grid, + const Vector3f min_pos, + const Vector3f max_pos, + bool boundary_sign_fix +); } // namespace zylann::voxel::mesh_sdf diff --git a/edition/voxel_tool.cpp b/edition/voxel_tool.cpp index d67438817..003da5648 100644 --- a/edition/voxel_tool.cpp +++ b/edition/voxel_tool.cpp @@ -159,8 +159,10 @@ void VoxelTool::do_sphere(Vector3 center, float radius) { ZN_PROFILE_SCOPE(); // Default, suboptimal implementation - const Box3i box(math::floor_to_int(center) - Vector3iUtil::create(Math::floor(radius)), - Vector3iUtil::create(Math::ceil(radius) * 2)); + const Box3i box( + math::floor_to_int(center) - Vector3iUtil::create(Math::floor(radius)), + Vector3iUtil::create(Math::ceil(radius) * 2) + ); if (_allow_out_of_bounds == false && !is_area_editable(box)) { ZN_PRINT_VERBOSE("Area not editable"); @@ -276,21 +278,26 @@ void VoxelTool::paste(Vector3i p_pos, Ref p_voxels, uint8_t paste(p_pos, p_voxels->get_buffer(), channels_mask); } -void VoxelTool::paste_masked(Vector3i p_pos, Ref p_voxels, uint8_t channels_mask, - uint8_t mask_channel, uint64_t mask_value) { +void VoxelTool::paste_masked( + Vector3i p_pos, + Ref p_voxels, + uint8_t channels_mask, + uint8_t mask_channel, + uint64_t mask_value +) { ERR_FAIL_COND(p_voxels.is_null()); ERR_PRINT("Not implemented"); // Implemented in derived classes } -void VoxelTool::paste_masked_writable_list( // - Vector3i pos, // - Ref p_voxels, // - uint8_t channels_mask, // - uint8_t src_mask_channel, // - uint64_t src_mask_value, // - uint8_t dst_mask_channel, // - PackedInt32Array dst_writable_list // +void VoxelTool::paste_masked_writable_list( + Vector3i pos, + Ref p_voxels, + uint8_t channels_mask, + uint8_t src_mask_channel, + uint64_t src_mask_value, + uint8_t dst_mask_channel, + PackedInt32Array dst_writable_list ) { ZN_PRINT_ERROR("Not implemented"); // Implemented in derived classes @@ -303,7 +310,8 @@ void VoxelTool::smooth_sphere(Vector3 sphere_center, float sphere_radius, int bl const Box3i voxel_box = Box3i::from_min_max( math::floor_to_int(sphere_center - Vector3(sphere_radius, sphere_radius, sphere_radius)), - math::ceil_to_int(sphere_center + Vector3(sphere_radius, sphere_radius, sphere_radius))); + math::ceil_to_int(sphere_center + Vector3(sphere_radius, sphere_radius, sphere_radius)) + ); const Box3i padded_voxel_box = voxel_box.padded(blur_radius); @@ -339,7 +347,8 @@ void VoxelTool::grow_sphere(Vector3 sphere_center, float sphere_radius, float st const Box3i voxel_box = Box3i::from_min_max( math::floor_to_int(sphere_center - Vector3(sphere_radius, sphere_radius, sphere_radius)), - math::ceil_to_int(sphere_center + Vector3(sphere_radius, sphere_radius, sphere_radius))); + math::ceil_to_int(sphere_center + Vector3(sphere_radius, sphere_radius, sphere_radius)) + ); if (_allow_out_of_bounds == false && !is_area_editable(voxel_box)) { ZN_PRINT_VERBOSE("Area not editable"); @@ -431,7 +440,12 @@ void VoxelTool::_b_paste(Vector3i pos, Ref voxels, int chann } void VoxelTool::_b_paste_masked( - Vector3i pos, Ref voxels, int channels_mask, int mask_channel, int64_t mask_value) { + Vector3i pos, + Ref voxels, + int channels_mask, + int mask_channel, + int64_t mask_value +) { paste_masked(pos, voxels, channels_mask, mask_channel, mask_value); } @@ -526,9 +540,11 @@ void VoxelTool::_bind_methods() { ClassDB::bind_method(D_METHOD("do_path", "points", "radii"), &VoxelTool::_b_do_path); ClassDB::bind_method( - D_METHOD("smooth_sphere", "sphere_center", "sphere_radius", "blur_radius"), &VoxelTool::smooth_sphere); + D_METHOD("smooth_sphere", "sphere_center", "sphere_radius", "blur_radius"), &VoxelTool::smooth_sphere + ); ClassDB::bind_method( - D_METHOD("grow_sphere", "sphere_center", "sphere_radius", "strength"), &VoxelTool::grow_sphere); + D_METHOD("grow_sphere", "sphere_center", "sphere_radius", "strength"), &VoxelTool::grow_sphere + ); ClassDB::bind_method(D_METHOD("set_voxel_metadata", "pos", "meta"), &VoxelTool::_b_set_voxel_metadata); ClassDB::bind_method(D_METHOD("get_voxel_metadata", "pos"), &VoxelTool::_b_get_voxel_metadata); @@ -537,31 +553,53 @@ void VoxelTool::_bind_methods() { ClassDB::bind_method(D_METHOD("paste", "dst_pos", "src_buffer", "channels_mask"), &VoxelTool::_b_paste); ClassDB::bind_method( D_METHOD("paste_masked", "dst_pos", "src_buffer", "channels_mask", "mask_channel", "mask_value"), - &VoxelTool::_b_paste_masked); - ClassDB::bind_method(D_METHOD("paste_masked_writable_list", "position", "voxels", "channels_mask", - "src_mask_channel", "src_mask_value", "dst_mask_channel", "dst_writable_list"), - &VoxelTool::paste_masked_writable_list); + &VoxelTool::_b_paste_masked + ); + ClassDB::bind_method( + D_METHOD( + "paste_masked_writable_list", + "position", + "voxels", + "channels_mask", + "src_mask_channel", + "src_mask_value", + "dst_mask_channel", + "dst_writable_list" + ), + &VoxelTool::paste_masked_writable_list + ); - ClassDB::bind_method(D_METHOD("raycast", "origin", "direction", "max_distance", "collision_mask"), - &VoxelTool::_b_raycast, DEFVAL(10.0), DEFVAL(0xffffffff)); + ClassDB::bind_method( + D_METHOD("raycast", "origin", "direction", "max_distance", "collision_mask"), + &VoxelTool::_b_raycast, + DEFVAL(10.0), + DEFVAL(0xffffffff) + ); ClassDB::bind_method(D_METHOD("is_area_editable", "box"), &VoxelTool::_b_is_area_editable); // Encoding helpers ClassDB::bind_static_method(VoxelTool::get_class_static(), D_METHOD("color_to_u16", "color"), &_b_color_to_u16); ClassDB::bind_static_method( - VoxelTool::get_class_static(), D_METHOD("vec4i_to_u16_indices"), &_b_vec4i_to_u16_indices); + VoxelTool::get_class_static(), D_METHOD("vec4i_to_u16_indices"), &_b_vec4i_to_u16_indices + ); ClassDB::bind_static_method( - VoxelTool::get_class_static(), D_METHOD("color_to_u16_weights"), &_b_color_to_u16_weights); + VoxelTool::get_class_static(), D_METHOD("color_to_u16_weights"), &_b_color_to_u16_weights + ); ClassDB::bind_static_method( - VoxelTool::get_class_static(), D_METHOD("u16_indices_to_vec4i"), &_b_u16_indices_to_vec4i); + VoxelTool::get_class_static(), D_METHOD("u16_indices_to_vec4i"), &_b_u16_indices_to_vec4i + ); ClassDB::bind_static_method( - VoxelTool::get_class_static(), D_METHOD("u16_weights_to_color"), &_b_u16_weights_to_color); + VoxelTool::get_class_static(), D_METHOD("u16_weights_to_color"), &_b_u16_weights_to_color + ); ClassDB::bind_static_method(VoxelTool::get_class_static(), D_METHOD("normalize_color"), &_b_normalize_color); ADD_PROPERTY(PropertyInfo(Variant::INT, "value"), "set_value", "get_value"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "channel", PROPERTY_HINT_ENUM, godot::VoxelBuffer::CHANNEL_ID_HINT_STRING), - "set_channel", "get_channel"); + ADD_PROPERTY( + PropertyInfo(Variant::INT, "channel", PROPERTY_HINT_ENUM, godot::VoxelBuffer::CHANNEL_ID_HINT_STRING), + "set_channel", + "get_channel" + ); ADD_PROPERTY(PropertyInfo(Variant::INT, "eraser_value"), "set_eraser_value", "get_eraser_value"); ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Add,Remove,Set"), "set_mode", "get_mode"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdf_scale"), "set_sdf_scale", "get_sdf_scale"); diff --git a/edition/voxel_tool.h b/edition/voxel_tool.h index 15fd317b3..607783a19 100644 --- a/edition/voxel_tool.h +++ b/edition/voxel_tool.h @@ -79,17 +79,22 @@ class VoxelTool : public RefCounted { virtual void paste(Vector3i pos, const VoxelBuffer &src, uint8_t channels_mask); void paste(Vector3i pos, Ref p_voxels, uint8_t channels_mask); - virtual void paste_masked(Vector3i pos, Ref p_voxels, uint8_t channels_mask, - uint8_t mask_channel, uint64_t mask_value); - - virtual void paste_masked_writable_list( // - Vector3i pos, // - Ref p_voxels, // - uint8_t channels_mask, // - uint8_t src_mask_channel, // - uint64_t src_mask_value, // - uint8_t dst_mask_channel, // - PackedInt32Array dst_writable_list // + virtual void paste_masked( + Vector3i pos, + Ref p_voxels, + uint8_t channels_mask, + uint8_t mask_channel, + uint64_t mask_value + ); + + virtual void paste_masked_writable_list( + Vector3i pos, + Ref p_voxels, + uint8_t channels_mask, + uint8_t src_mask_channel, + uint64_t src_mask_value, + uint8_t dst_mask_channel, + PackedInt32Array dst_writable_list ); void smooth_sphere(Vector3 sphere_center, float sphere_radius, int blur_radius); @@ -130,7 +135,12 @@ class VoxelTool : public RefCounted { void _b_copy(Vector3i pos, Ref voxels, int channel_mask); void _b_paste(Vector3i pos, Ref voxels, int channels_mask); void _b_paste_masked( - Vector3i pos, Ref voxels, int channels_mask, int mask_channel, int64_t mask_value); + Vector3i pos, + Ref voxels, + int channels_mask, + int mask_channel, + int64_t mask_value + ); Variant _b_get_voxel_metadata(Vector3i pos) const; void _b_set_voxel_metadata(Vector3i pos, Variant meta); bool _b_is_area_editable(AABB box) const; diff --git a/edition/voxel_tool_buffer.cpp b/edition/voxel_tool_buffer.cpp index 2535d05bd..da006f40b 100644 --- a/edition/voxel_tool_buffer.cpp +++ b/edition/voxel_tool_buffer.cpp @@ -162,8 +162,13 @@ void VoxelToolBuffer::paste(Vector3i p_pos, const VoxelBuffer &src, uint8_t chan dst.copy_voxel_metadata_in_area(src, Box3i(Vector3i(), src.get_size()), p_pos); } -void VoxelToolBuffer::paste_masked(Vector3i p_pos, Ref p_voxels, uint8_t channels_mask, - uint8_t mask_channel, uint64_t mask_value) { +void VoxelToolBuffer::paste_masked( + Vector3i p_pos, + Ref p_voxels, + uint8_t channels_mask, + uint8_t mask_channel, + uint64_t mask_value +) { ERR_FAIL_COND(_buffer.is_null()); ERR_FAIL_COND(p_voxels.is_null()); @@ -248,7 +253,8 @@ void VoxelToolBuffer::do_path(Span positions, Span r op.shape = shape; op.texture_params = _texture_params; dst.write_box_2_template, uint16_t, uint16_t>( - local_box, VoxelBuffer::CHANNEL_INDICES, VoxelBuffer::CHANNEL_WEIGHTS, op, Vector3i()); + local_box, VoxelBuffer::CHANNEL_INDICES, VoxelBuffer::CHANNEL_WEIGHTS, op, Vector3i() + ); } break; default: diff --git a/edition/voxel_tool_buffer.h b/edition/voxel_tool_buffer.h index 123b365bb..6393abe3f 100644 --- a/edition/voxel_tool_buffer.h +++ b/edition/voxel_tool_buffer.h @@ -13,8 +13,13 @@ class VoxelToolBuffer : public VoxelTool { bool is_area_editable(const Box3i &box) const override; void paste(Vector3i p_pos, const VoxelBuffer &src, uint8_t channels_mask) override; - void paste_masked(Vector3i p_pos, Ref p_voxels, uint8_t channels_mask, uint8_t mask_channel, - uint64_t mask_value) override; + void paste_masked( + Vector3i p_pos, + Ref p_voxels, + uint8_t channels_mask, + uint8_t mask_channel, + uint64_t mask_value + ) override; void set_voxel_metadata(Vector3i pos, Variant meta) override; Variant get_voxel_metadata(Vector3i pos) const override; diff --git a/meshers/cubes/voxel_color_palette.cpp b/meshers/cubes/voxel_color_palette.cpp index f7b8d20c1..12b2fdd7e 100644 --- a/meshers/cubes/voxel_color_palette.cpp +++ b/meshers/cubes/voxel_color_palette.cpp @@ -74,11 +74,17 @@ void VoxelColorPalette::_bind_methods() { ClassDB::bind_method(D_METHOD("get_data"), &VoxelColorPalette::_b_get_data); // This is just to allow editing colors in the editor - ADD_PROPERTY(PropertyInfo(Variant::PACKED_COLOR_ARRAY, "colors", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), - "set_colors", "get_colors"); - - ADD_PROPERTY(PropertyInfo(Variant::PACKED_INT32_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), - "set_data", "get_data"); + ADD_PROPERTY( + PropertyInfo(Variant::PACKED_COLOR_ARRAY, "colors", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), + "set_colors", + "get_colors" + ); + + ADD_PROPERTY( + PropertyInfo(Variant::PACKED_INT32_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), + "set_data", + "get_data" + ); BIND_CONSTANT(MAX_COLORS); } diff --git a/meshers/voxel_mesher.cpp b/meshers/voxel_mesher.cpp index 84867df25..3d8d154f0 100644 --- a/meshers/voxel_mesher.cpp +++ b/meshers/voxel_mesher.cpp @@ -15,7 +15,10 @@ using namespace zylann::godot; namespace zylann::voxel { Ref VoxelMesher::build_mesh( - const VoxelBuffer &voxels, TypedArray materials, Dictionary additional_data) { + const VoxelBuffer &voxels, + TypedArray materials, + Dictionary additional_data +) { ZN_PROFILE_SCOPE(); Output output; @@ -34,10 +37,11 @@ Ref VoxelMesher::build_mesh( additional_data.get("octahedral_normal_encoding_enabled", false); detail_texture_settings.tile_resolution_min = int(additional_data.get("normalmap_tile_resolution", 16)); detail_texture_settings.tile_resolution_max = detail_texture_settings.tile_resolution_min; - detail_texture_settings.max_deviation_degrees = - math::clamp(int(additional_data.get("normalmap_max_deviation_degrees", 0)), - int(DetailRenderingSettings::MIN_DEVIATION_DEGREES), - int(DetailRenderingSettings::MAX_DEVIATION_DEGREES)); + detail_texture_settings.max_deviation_degrees = math::clamp( + int(additional_data.get("normalmap_max_deviation_degrees", 0)), + int(DetailRenderingSettings::MIN_DEVIATION_DEGREES), + int(DetailRenderingSettings::MAX_DEVIATION_DEGREES) + ); input.detail_texture_hint = detail_texture_settings.enabled; } @@ -86,17 +90,32 @@ Ref VoxelMesher::build_mesh( TransvoxelCellIterator cell_iterator(cell_infos); DetailTextureData nm_data; - compute_detail_texture_data(cell_iterator, to_span(mesh_arrays.vertices), to_span(mesh_arrays.normals), - to_span(mesh_arrays.indices), nm_data, detail_texture_settings.tile_resolution_min, - *input.generator, nullptr, input.origin_in_voxels, input.voxels.get_size(), input.lod_index, + compute_detail_texture_data( + cell_iterator, + to_span(mesh_arrays.vertices), + to_span(mesh_arrays.normals), + to_span(mesh_arrays.indices), + nm_data, + detail_texture_settings.tile_resolution_min, + *input.generator, + nullptr, + input.origin_in_voxels, + input.voxels.get_size(), + input.lod_index, detail_texture_settings.octahedral_encoding_enabled, - math::deg_to_rad(float(detail_texture_settings.max_deviation_degrees)), false); + math::deg_to_rad(float(detail_texture_settings.max_deviation_degrees)), + false + ); const Vector3i block_size = input.voxels.get_size() - Vector3iUtil::create(get_minimum_padding() + get_maximum_padding()); - DetailImages images = store_normalmap_data_to_images(nm_data, detail_texture_settings.tile_resolution_min, - block_size, detail_texture_settings.octahedral_encoding_enabled); + DetailImages images = store_normalmap_data_to_images( + nm_data, + detail_texture_settings.tile_resolution_min, + block_size, + detail_texture_settings.octahedral_encoding_enabled + ); const DetailTextures textures = store_normalmap_data_to_textures(images); // That should be in return value, but for now I just want this for testing with GDScript, so it gotta go @@ -150,7 +169,10 @@ Ref VoxelMesher::get_default_lod_material() const { } Ref VoxelMesher::_b_build_mesh( - Ref voxels, TypedArray materials, Dictionary additional_data) { + Ref voxels, + TypedArray materials, + Dictionary additional_data +) { ERR_FAIL_COND_V(voxels.is_null(), Ref()); return build_mesh(voxels->get_buffer(), materials, additional_data); } @@ -159,8 +181,11 @@ void VoxelMesher::_bind_methods() { // Shortcut if you want to generate a mesh directly from a fixed grid of voxels. // Useful for testing the different meshers. // TODO Have an object type to specify input - ClassDB::bind_method(D_METHOD("build_mesh", "voxel_buffer", "materials", "additional_data"), - &VoxelMesher::_b_build_mesh, DEFVAL(Dictionary())); + ClassDB::bind_method( + D_METHOD("build_mesh", "voxel_buffer", "materials", "additional_data"), + &VoxelMesher::_b_build_mesh, + DEFVAL(Dictionary()) + ); ClassDB::bind_method(D_METHOD("get_minimum_padding"), &VoxelMesher::get_minimum_padding); ClassDB::bind_method(D_METHOD("get_maximum_padding"), &VoxelMesher::get_maximum_padding); }