|
7 | 7 | #include "../util/string/format.h"
|
8 | 8 | #include "metadata/voxel_metadata_variant.h"
|
9 | 9 |
|
| 10 | +namespace zylann::voxel { |
| 11 | + |
| 12 | +template <typename F> |
| 13 | +void op_buffer_value_f( |
| 14 | + VoxelBuffer &dst, |
| 15 | + const float b, |
| 16 | + VoxelBuffer::ChannelId channel, |
| 17 | + F f // (float a, float b) -> float |
| 18 | +) { |
| 19 | + if (dst.get_channel_compression(channel) == VoxelBuffer::COMPRESSION_UNIFORM) { |
| 20 | + const float a = dst.get_voxel_f(0, 0, 0, channel); |
| 21 | + dst.fill_f(f(a, b), channel); |
| 22 | + return; |
| 23 | + } |
| 24 | + |
| 25 | + switch (dst.get_channel_depth(channel)) { |
| 26 | + case VoxelBuffer::DEPTH_8_BIT: { |
| 27 | + Span<int8_t> dst_data; |
| 28 | + ZN_ASSERT(dst.get_channel_data(channel, dst_data)); |
| 29 | + for (int8_t &d : dst_data) { |
| 30 | + const float a = s8_to_snorm(d) * constants::QUANTIZED_SDF_8_BITS_SCALE_INV; |
| 31 | + d = snorm_to_s8(f(a, b) * constants::QUANTIZED_SDF_8_BITS_SCALE); |
| 32 | + } |
| 33 | + } break; |
| 34 | + |
| 35 | + case VoxelBuffer::DEPTH_16_BIT: { |
| 36 | + Span<int16_t> dst_data; |
| 37 | + ZN_ASSERT(dst.get_channel_data(channel, dst_data)); |
| 38 | + for (int16_t &d : dst_data) { |
| 39 | + const float a = s16_to_snorm(d) * constants::QUANTIZED_SDF_16_BITS_SCALE_INV; |
| 40 | + d = snorm_to_s16(f(a, b) * constants::QUANTIZED_SDF_16_BITS_SCALE); |
| 41 | + } |
| 42 | + } break; |
| 43 | + |
| 44 | + case VoxelBuffer::DEPTH_32_BIT: { |
| 45 | + Span<float> dst_data; |
| 46 | + ZN_ASSERT(dst.get_channel_data(channel, dst_data)); |
| 47 | + for (float &d : dst_data) { |
| 48 | + d = f(d, b); |
| 49 | + } |
| 50 | + } break; |
| 51 | + |
| 52 | + case VoxelBuffer::DEPTH_64_BIT: |
| 53 | + ZN_PRINT_ERROR("Unsupported depth for operation"); |
| 54 | + break; |
| 55 | + |
| 56 | + default: |
| 57 | + ZN_CRASH(); |
| 58 | + break; |
| 59 | + } |
| 60 | +} |
| 61 | + |
| 62 | +template <typename F> |
| 63 | +void op_buffer_buffer_f( |
| 64 | + VoxelBuffer &dst, |
| 65 | + const VoxelBuffer &src, |
| 66 | + VoxelBuffer::ChannelId channel, |
| 67 | + F f // (float a, float b) -> float |
| 68 | +) { |
| 69 | + if (src.get_channel_compression(channel) == zylann::voxel::VoxelBuffer::COMPRESSION_UNIFORM) { |
| 70 | + const float value = src.get_voxel_f(0, 0, 0, channel); |
| 71 | + op_buffer_value_f(dst, value, channel, f); |
| 72 | + return; |
| 73 | + } |
| 74 | + |
| 75 | + if (dst.get_channel_compression(channel) == zylann::voxel::VoxelBuffer::COMPRESSION_UNIFORM) { |
| 76 | + dst.decompress_channel(channel); |
| 77 | + } |
| 78 | + |
| 79 | + switch (src.get_channel_depth(channel)) { |
| 80 | + case VoxelBuffer::DEPTH_8_BIT: { |
| 81 | + Span<const int8_t> src_data; |
| 82 | + Span<int8_t> dst_data; |
| 83 | + ZN_ASSERT(src.get_channel_data_read_only(channel, src_data)); |
| 84 | + ZN_ASSERT(dst.get_channel_data(channel, dst_data)); |
| 85 | + for (unsigned int i = 0; i < src_data.size(); ++i) { |
| 86 | + const float a = s8_to_snorm(dst_data[i]) * constants::QUANTIZED_SDF_8_BITS_SCALE_INV; |
| 87 | + const float b = s8_to_snorm(src_data[i]) * constants::QUANTIZED_SDF_8_BITS_SCALE_INV; |
| 88 | + dst_data[i] = snorm_to_s8(f(a, b) * constants::QUANTIZED_SDF_8_BITS_SCALE); |
| 89 | + } |
| 90 | + } break; |
| 91 | + |
| 92 | + case VoxelBuffer::DEPTH_16_BIT: { |
| 93 | + Span<const int16_t> src_data; |
| 94 | + Span<int16_t> dst_data; |
| 95 | + ZN_ASSERT(src.get_channel_data_read_only(channel, src_data)); |
| 96 | + ZN_ASSERT(dst.get_channel_data(channel, dst_data)); |
| 97 | + for (unsigned int i = 0; i < src_data.size(); ++i) { |
| 98 | + const float a = s16_to_snorm(dst_data[i]) * constants::QUANTIZED_SDF_16_BITS_SCALE_INV; |
| 99 | + const float b = s16_to_snorm(src_data[i]) * constants::QUANTIZED_SDF_16_BITS_SCALE_INV; |
| 100 | + dst_data[i] = snorm_to_s16(f(a, b) * constants::QUANTIZED_SDF_16_BITS_SCALE); |
| 101 | + } |
| 102 | + } break; |
| 103 | + |
| 104 | + case VoxelBuffer::DEPTH_32_BIT: { |
| 105 | + Span<const float> src_data; |
| 106 | + Span<float> dst_data; |
| 107 | + ZN_ASSERT(src.get_channel_data_read_only(channel, src_data)); |
| 108 | + ZN_ASSERT(dst.get_channel_data(channel, dst_data)); |
| 109 | + for (unsigned int i = 0; i < src_data.size(); ++i) { |
| 110 | + dst_data[i] = f(dst_data[i], src_data[i]); |
| 111 | + } |
| 112 | + } break; |
| 113 | + |
| 114 | + case VoxelBuffer::DEPTH_64_BIT: |
| 115 | + ZN_PRINT_ERROR("Non-implemented depth for operation"); |
| 116 | + break; |
| 117 | + |
| 118 | + default: |
| 119 | + ZN_CRASH(); |
| 120 | + break; |
| 121 | + } |
| 122 | +} |
| 123 | + |
| 124 | +} // namespace zylann::voxel |
| 125 | + |
10 | 126 | namespace zylann::voxel::godot {
|
11 | 127 |
|
12 | 128 | const char *VoxelBuffer::CHANNEL_ID_HINT_STRING = "Type,Sdf,Color,Indices,Weights,Data5,Data6,Data7";
|
@@ -191,175 +307,93 @@ VoxelBuffer::Allocator VoxelBuffer::get_allocator() const {
|
191 | 307 | return static_cast<VoxelBuffer::Allocator>(_buffer->get_allocator());
|
192 | 308 | }
|
193 | 309 |
|
194 |
| -template <typename F> |
195 |
| -void op_buffer_value_f( // |
196 |
| - zylann::voxel::VoxelBuffer &dst, // |
197 |
| - const float b, // |
198 |
| - VoxelBuffer::ChannelId channel, // |
199 |
| - F f // (float a, float b) -> float |
200 |
| -) { |
201 |
| - if (dst.get_channel_compression(channel) == zylann::voxel::VoxelBuffer::COMPRESSION_UNIFORM) { |
202 |
| - const float a = dst.get_voxel_f(0, 0, 0, channel); |
203 |
| - dst.fill_f(f(a, b), channel); |
204 |
| - return; |
205 |
| - } |
206 |
| - |
207 |
| - switch (dst.get_channel_depth(channel)) { |
208 |
| - case VoxelBuffer::DEPTH_8_BIT: { |
209 |
| - Span<int8_t> dst_data; |
210 |
| - ZN_ASSERT(dst.get_channel_data(channel, dst_data)); |
211 |
| - for (int8_t &d : dst_data) { |
212 |
| - const float a = s8_to_snorm(d) * constants::QUANTIZED_SDF_8_BITS_SCALE_INV; |
213 |
| - d = snorm_to_s8(f(a, b) * constants::QUANTIZED_SDF_8_BITS_SCALE); |
214 |
| - } |
215 |
| - } break; |
216 |
| - |
217 |
| - case VoxelBuffer::DEPTH_16_BIT: { |
218 |
| - Span<int16_t> dst_data; |
219 |
| - ZN_ASSERT(dst.get_channel_data(channel, dst_data)); |
220 |
| - for (int16_t &d : dst_data) { |
221 |
| - const float a = s16_to_snorm(d) * constants::QUANTIZED_SDF_16_BITS_SCALE_INV; |
222 |
| - d = snorm_to_s16(f(a, b) * constants::QUANTIZED_SDF_16_BITS_SCALE); |
223 |
| - } |
224 |
| - } break; |
225 |
| - |
226 |
| - case VoxelBuffer::DEPTH_32_BIT: { |
227 |
| - Span<float> dst_data; |
228 |
| - ZN_ASSERT(dst.get_channel_data(channel, dst_data)); |
229 |
| - for (float &d : dst_data) { |
230 |
| - d = f(d, b); |
231 |
| - } |
232 |
| - } break; |
233 |
| - |
234 |
| - case VoxelBuffer::DEPTH_64_BIT: |
235 |
| - ZN_PRINT_ERROR("Unsupported depth for operation"); |
236 |
| - break; |
237 |
| - |
238 |
| - default: |
239 |
| - ZN_CRASH(); |
240 |
| - break; |
241 |
| - } |
242 |
| -} |
243 |
| - |
244 |
| -template <typename F> |
245 |
| -void op_buffer_buffer_f( // |
246 |
| - zylann::voxel::VoxelBuffer &dst, // |
247 |
| - const zylann::voxel::VoxelBuffer &src, // |
248 |
| - VoxelBuffer::ChannelId channel, // |
249 |
| - F f // (float a, float b) -> float |
250 |
| -) { |
251 |
| - if (src.get_channel_compression(channel) == zylann::voxel::VoxelBuffer::COMPRESSION_UNIFORM) { |
252 |
| - const float value = src.get_voxel_f(0, 0, 0, channel); |
253 |
| - op_buffer_value_f(dst, value, channel, f); |
254 |
| - return; |
255 |
| - } |
256 |
| - |
257 |
| - if (dst.get_channel_compression(channel) == zylann::voxel::VoxelBuffer::COMPRESSION_UNIFORM) { |
258 |
| - dst.decompress_channel(channel); |
259 |
| - } |
260 |
| - |
261 |
| - switch (src.get_channel_depth(channel)) { |
262 |
| - case VoxelBuffer::DEPTH_8_BIT: { |
263 |
| - Span<const int8_t> src_data; |
264 |
| - Span<int8_t> dst_data; |
265 |
| - ZN_ASSERT(src.get_channel_data_read_only(channel, src_data)); |
266 |
| - ZN_ASSERT(dst.get_channel_data(channel, dst_data)); |
267 |
| - for (unsigned int i = 0; i < src_data.size(); ++i) { |
268 |
| - const float a = s8_to_snorm(dst_data[i]) * constants::QUANTIZED_SDF_8_BITS_SCALE_INV; |
269 |
| - const float b = s8_to_snorm(src_data[i]) * constants::QUANTIZED_SDF_8_BITS_SCALE_INV; |
270 |
| - dst_data[i] = snorm_to_s8(f(a, b) * constants::QUANTIZED_SDF_8_BITS_SCALE); |
271 |
| - } |
272 |
| - } break; |
273 |
| - |
274 |
| - case VoxelBuffer::DEPTH_16_BIT: { |
275 |
| - Span<const int16_t> src_data; |
276 |
| - Span<int16_t> dst_data; |
277 |
| - ZN_ASSERT(src.get_channel_data_read_only(channel, src_data)); |
278 |
| - ZN_ASSERT(dst.get_channel_data(channel, dst_data)); |
279 |
| - for (unsigned int i = 0; i < src_data.size(); ++i) { |
280 |
| - const float a = s16_to_snorm(dst_data[i]) * constants::QUANTIZED_SDF_16_BITS_SCALE_INV; |
281 |
| - const float b = s16_to_snorm(src_data[i]) * constants::QUANTIZED_SDF_16_BITS_SCALE_INV; |
282 |
| - dst_data[i] = snorm_to_s16(f(a, b) * constants::QUANTIZED_SDF_16_BITS_SCALE); |
283 |
| - } |
284 |
| - } break; |
285 |
| - |
286 |
| - case VoxelBuffer::DEPTH_32_BIT: { |
287 |
| - Span<const float> src_data; |
288 |
| - Span<float> dst_data; |
289 |
| - ZN_ASSERT(src.get_channel_data_read_only(channel, src_data)); |
290 |
| - ZN_ASSERT(dst.get_channel_data(channel, dst_data)); |
291 |
| - for (unsigned int i = 0; i < src_data.size(); ++i) { |
292 |
| - dst_data[i] = f(dst_data[i], src_data[i]); |
293 |
| - } |
294 |
| - } break; |
295 |
| - |
296 |
| - case VoxelBuffer::DEPTH_64_BIT: |
297 |
| - ZN_PRINT_ERROR("Non-implemented depth for operation"); |
298 |
| - break; |
299 |
| - |
300 |
| - default: |
301 |
| - ZN_CRASH(); |
302 |
| - break; |
303 |
| - } |
304 |
| -} |
305 |
| - |
306 | 310 | void VoxelBuffer::op_add_buffer_f(Ref<VoxelBuffer> other, VoxelBuffer::ChannelId channel) {
|
307 | 311 | ZN_ASSERT_RETURN(other.is_valid());
|
308 | 312 | ZN_ASSERT_RETURN(channel >= 0 && channel < VoxelBuffer::MAX_CHANNELS);
|
309 | 313 | ZN_ASSERT_RETURN(get_channel_depth(channel) == other->get_channel_depth(channel));
|
310 | 314 | ZN_ASSERT_RETURN(get_size() == other->get_size());
|
311 |
| - op_buffer_buffer_f(*_buffer, other->get_buffer(), channel, [](float a, float b) { return a + b; }); |
| 315 | + op_buffer_buffer_f( |
| 316 | + *_buffer, |
| 317 | + other->get_buffer(), |
| 318 | + static_cast<zylann::voxel::VoxelBuffer::ChannelId>(channel), |
| 319 | + [](float a, float b) { return a + b; } |
| 320 | + ); |
312 | 321 | }
|
313 | 322 |
|
314 | 323 | void VoxelBuffer::op_sub_buffer_f(Ref<VoxelBuffer> other, VoxelBuffer::ChannelId channel) {
|
315 | 324 | ZN_ASSERT_RETURN(other.is_valid());
|
316 | 325 | ZN_ASSERT_RETURN(channel >= 0 && channel < VoxelBuffer::MAX_CHANNELS);
|
317 | 326 | ZN_ASSERT_RETURN(get_channel_depth(channel) == other->get_channel_depth(channel));
|
318 | 327 | ZN_ASSERT_RETURN(get_size() == other->get_size());
|
319 |
| - op_buffer_buffer_f(*_buffer, other->get_buffer(), channel, [](float a, float b) { return a - b; }); |
| 328 | + op_buffer_buffer_f( |
| 329 | + *_buffer, |
| 330 | + other->get_buffer(), |
| 331 | + static_cast<zylann::voxel::VoxelBuffer::ChannelId>(channel), |
| 332 | + [](float a, float b) { return a - b; } |
| 333 | + ); |
320 | 334 | }
|
321 | 335 |
|
322 | 336 | void VoxelBuffer::op_mul_buffer_f(Ref<VoxelBuffer> other, VoxelBuffer::ChannelId channel) {
|
323 | 337 | ZN_ASSERT_RETURN(other.is_valid());
|
324 | 338 | ZN_ASSERT_RETURN(channel >= 0 && channel < VoxelBuffer::MAX_CHANNELS);
|
325 | 339 | ZN_ASSERT_RETURN(get_channel_depth(channel) == other->get_channel_depth(channel));
|
326 | 340 | ZN_ASSERT_RETURN(get_size() == other->get_size());
|
327 |
| - op_buffer_buffer_f(*_buffer, other->get_buffer(), channel, [](float a, float b) { return a * b; }); |
| 341 | + op_buffer_buffer_f( |
| 342 | + *_buffer, |
| 343 | + other->get_buffer(), |
| 344 | + static_cast<zylann::voxel::VoxelBuffer::ChannelId>(channel), |
| 345 | + [](float a, float b) { return a * b; } |
| 346 | + ); |
328 | 347 | }
|
329 | 348 |
|
330 | 349 | void VoxelBuffer::op_mul_value_f(float scale, VoxelBuffer::ChannelId channel) {
|
331 | 350 | ZN_ASSERT_RETURN(channel >= 0 && channel < VoxelBuffer::MAX_CHANNELS);
|
332 |
| - op_buffer_value_f(*_buffer, scale, channel, [](float a, float b) { return a * b; }); |
| 351 | + op_buffer_value_f( |
| 352 | + *_buffer, |
| 353 | + scale, |
| 354 | + static_cast<zylann::voxel::VoxelBuffer::ChannelId>(channel), |
| 355 | + [](float a, float b) { return a * b; } |
| 356 | + ); |
333 | 357 | }
|
334 | 358 |
|
335 | 359 | void VoxelBuffer::op_min_buffer_f(Ref<VoxelBuffer> other, VoxelBuffer::ChannelId channel) {
|
336 | 360 | ZN_ASSERT_RETURN(other.is_valid());
|
337 | 361 | ZN_ASSERT_RETURN(channel >= 0 && channel < VoxelBuffer::MAX_CHANNELS);
|
338 | 362 | ZN_ASSERT_RETURN(get_channel_depth(channel) == other->get_channel_depth(channel));
|
339 | 363 | ZN_ASSERT_RETURN(get_size() == other->get_size());
|
340 |
| - op_buffer_buffer_f(*_buffer, other->get_buffer(), channel, [](float a, float b) { return math::min(a, b); }); |
| 364 | + op_buffer_buffer_f( |
| 365 | + *_buffer, |
| 366 | + other->get_buffer(), |
| 367 | + static_cast<zylann::voxel::VoxelBuffer::ChannelId>(channel), |
| 368 | + [](float a, float b) { return math::min(a, b); } |
| 369 | + ); |
341 | 370 | }
|
342 | 371 |
|
343 | 372 | void VoxelBuffer::op_max_buffer_f(Ref<VoxelBuffer> other, VoxelBuffer::ChannelId channel) {
|
344 | 373 | ZN_ASSERT_RETURN(other.is_valid());
|
345 | 374 | ZN_ASSERT_RETURN(channel >= 0 && channel < VoxelBuffer::MAX_CHANNELS);
|
346 | 375 | ZN_ASSERT_RETURN(get_channel_depth(channel) == other->get_channel_depth(channel));
|
347 | 376 | ZN_ASSERT_RETURN(get_size() == other->get_size());
|
348 |
| - op_buffer_buffer_f(*_buffer, other->get_buffer(), channel, [](float a, float b) { return math::max(a, b); }); |
| 377 | + op_buffer_buffer_f( |
| 378 | + *_buffer, |
| 379 | + other->get_buffer(), |
| 380 | + static_cast<zylann::voxel::VoxelBuffer::ChannelId>(channel), |
| 381 | + [](float a, float b) { return math::max(a, b); } |
| 382 | + ); |
349 | 383 | }
|
350 | 384 |
|
351 | 385 | template <typename TIn, typename TOut>
|
352 | 386 | inline TOut select_less(TIn src, TIn threshold, TOut value_if_less, TOut value_if_more) {
|
353 | 387 | return src < threshold ? value_if_less : value_if_more;
|
354 | 388 | }
|
355 | 389 |
|
356 |
| -void VoxelBuffer::op_select_less_src_f_dst_i_values( // |
357 |
| - Ref<VoxelBuffer> src_ref, // |
358 |
| - VoxelBuffer::ChannelId src_channel, // |
359 |
| - float threshold, // |
360 |
| - int value_if_less, // |
361 |
| - int value_if_more, // |
362 |
| - VoxelBuffer::ChannelId dst_channel // |
| 390 | +void VoxelBuffer::op_select_less_src_f_dst_i_values( |
| 391 | + Ref<VoxelBuffer> src_ref, |
| 392 | + const VoxelBuffer::ChannelId src_channel, |
| 393 | + const float threshold, |
| 394 | + const int value_if_less, |
| 395 | + const int value_if_more, |
| 396 | + const VoxelBuffer::ChannelId dst_channel |
363 | 397 | ) {
|
364 | 398 | ZN_ASSERT_RETURN(src_ref.is_valid());
|
365 | 399 | ZN_ASSERT_RETURN(src_channel >= 0 && src_channel < VoxelBuffer::MAX_CHANNELS);
|
|
0 commit comments