From 789934ce32709bb77c692eaed7e11d9d800edb59 Mon Sep 17 00:00:00 2001 From: "Andrii Doroshenko (Xrayez)" Date: Sat, 17 Nov 2018 10:32:10 +0200 Subject: [PATCH] Add methods to map noise to 3D image, including seamless 3.1.alpha.Xrayez.0afdc5c --- noise.cpp | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- noise.h | 6 ++++ 2 files changed, 93 insertions(+), 4 deletions(-) diff --git a/noise.cpp b/noise.cpp index 666042a..242b890 100644 --- a/noise.cpp +++ b/noise.cpp @@ -769,6 +769,17 @@ Ref AccidentalNoise::get_texture(int p_width, int p_height) { return texture; } +Vector> AccidentalNoise::get_image_3d(int p_width, int p_height, int p_depth) { + + return _map_to_image_3d(p_width, p_height, p_depth, function, mode, format, ranges); +} + +Vector> AccidentalNoise::get_seamless_image_3d(int p_width, int p_height, int p_depth) { + + // Returns seamless 3D image regardless of mapping mode + return _map_to_image_3d(p_width, p_height, p_depth, function, anl::SEAMLESS_XY, format, ranges); +} + Ref AccidentalNoise::_map_to_image(int p_width, int p_height, Index p_index, anl::EMappingModes p_mode, Format p_format, const AABB& p_ranges) { anl::SMappingRanges ranges( @@ -780,11 +791,12 @@ Ref AccidentalNoise::_map_to_image(int p_width, int p_height, Index p_ind PoolVector dest_data; const int SIZE = p_width * p_height; - Ref noise = memnew(Image); + Image::Format image_format = Image::Format::FORMAT_L8; switch(p_format) { case FORMAT_NOISE: { // scalar, grayscale image + image_format = Image::Format::FORMAT_L8; anl::CArray2Dd img(p_width, p_height); anl::map2DNoZ(p_mode, img, kernel, ranges, p_index); @@ -796,11 +808,10 @@ Ref AccidentalNoise::_map_to_image(int p_width, int p_height, Index p_ind for(int i = 0; i < SIZE; ++i) { w[i] = (uint8_t)(src_data[i] * 255); } - noise->create(p_width, p_height, 0, Image::FORMAT_L8, dest_data); - } break; case FORMAT_COLOR: { // suitable for textures + image_format = Image::Format::FORMAT_RGBA8; anl::CArray2Drgba img(p_width, p_height); anl::mapRGBA2DNoZ(p_mode, img, kernel, ranges, p_index); @@ -815,11 +826,83 @@ Ref AccidentalNoise::_map_to_image(int p_width, int p_height, Index p_ind w[i * 4 + 2] = (uint8_t)(src_data[i].b * 255); w[i * 4 + 3] = (uint8_t)(src_data[i].a * 255); } - noise->create(p_width, p_height, 0, Image::FORMAT_RGBA8, dest_data); + } break; + } + + Ref noise = memnew(Image); + noise->create(p_width, p_height, 0, image_format, dest_data); + + return noise; +} + +Vector> AccidentalNoise::_map_to_image_3d(int p_width, int p_height, int p_depth, Index p_index, anl::EMappingModes p_mode, Format p_format, const AABB& p_ranges) { + + anl::SMappingRanges ranges( + p_ranges.position.x, p_ranges.position.x + p_ranges.size.x, + p_ranges.position.y, p_ranges.position.y + p_ranges.size.y, + p_ranges.position.z, p_ranges.position.z + p_ranges.size.z + ); + Vector> dest_data; + const int SIZE = p_width * p_height; + + Image::Format image_format = Image::Format::FORMAT_L8; + + switch(p_format) { + + case FORMAT_NOISE: { // scalar, grayscale image + image_format = Image::Format::FORMAT_L8; + + anl::CArray3Dd img(p_width, p_height, p_depth); + anl::map3D(p_mode, img, kernel, ranges, p_index); + + for (int k = 0; k < p_depth; k++) { + + PoolVector dest_data_image; + dest_data_image.resize(SIZE); + PoolVector::Write w = dest_data_image.write(); + + auto src_data = img.getData(); + + for (int i = SIZE * k; i < SIZE * (k + 1); i++) { + w[i] = (uint8_t)(src_data[i] * 255); + } + dest_data.push_back(dest_data_image); + } + } break; + + case FORMAT_COLOR: { // suitable for textures + image_format = Image::Format::FORMAT_RGBA8; + + anl::CArray3Drgba img(p_width, p_height, p_depth); + anl::mapRGBA3D(p_mode, img, kernel, ranges, p_index); + + for(int k = 0; k < p_depth; ++k) { + + PoolVector dest_data_image; + dest_data_image.resize(SIZE * 4); + PoolVector::Write w = dest_data_image.write(); + + auto src_data = img.getData(); + + for(int dest = 0, src = SIZE * k; src < SIZE * (k + 1); dest += 4, ++src) { // TODO: optimize (like 2D)? + w[dest + 0] = (uint8_t)(src_data[src].r * 255); + w[dest + 1] = (uint8_t)(src_data[src].g * 255); + w[dest + 2] = (uint8_t)(src_data[src].b * 255); + w[dest + 3] = (uint8_t)(src_data[src].a * 255); + } + dest_data.push_back(dest_data_image); + } } break; } + Vector> noise; + for (int i = 0; i < dest_data.size(); i++) { + Ref noise_image = memnew(Image); + noise_image->create(p_width, p_height, 0, image_format, dest_data[i]); + noise.push_back(noise_image); + } + return noise; } diff --git a/noise.h b/noise.h index b6aa05d..53955b2 100644 --- a/noise.h +++ b/noise.h @@ -237,11 +237,16 @@ class AccidentalNoise : public Resource { //------------------------------------------------------------------------------ // Image/texture methods //------------------------------------------------------------------------------ + // 2D Ref get_image(int p_width, int p_height); Ref get_seamless_image(int p_width, int p_height); Ref get_texture(int p_width, int p_height); + // 3D + Vector> get_image_3d(int p_width, int p_height, int p_depth); + Vector> get_seamless_image_3d(int p_width, int p_height, int p_depth); + private: anl::CKernel kernel; anl::CNoiseExecutor vm; @@ -256,6 +261,7 @@ class AccidentalNoise : public Resource { String expression; Ref _map_to_image(int p_width, int p_height, Index p_index, anl::EMappingModes p_mode, Format p_format, const AABB &p_ranges); + Vector> _map_to_image_3d(int p_width, int p_height, int p_depth, Index p_index, anl::EMappingModes p_mode, Format p_format, const AABB& p_ranges); }; VARIANT_ENUM_CAST(anl::InterpolationTypes);