diff options
-rw-r--r-- | core/image.cpp | 151 | ||||
-rw-r--r-- | core/image.h | 1 | ||||
-rw-r--r-- | core/math/math_funcs.h | 6 | ||||
-rw-r--r-- | core/object.cpp | 12 | ||||
-rw-r--r-- | doc/classes/Image.xml | 2 | ||||
-rw-r--r-- | editor/editor_node.cpp | 3 | ||||
-rw-r--r-- | editor/editor_settings.cpp | 2 | ||||
-rw-r--r-- | editor/editor_themes.cpp | 2 | ||||
-rw-r--r-- | modules/bullet/rigid_body_bullet.cpp | 10 | ||||
-rw-r--r-- | scene/gui/text_edit.cpp | 5 |
10 files changed, 173 insertions, 21 deletions
diff --git a/core/image.cpp b/core/image.cpp index 99d5eab864..30af724de9 100644 --- a/core/image.cpp +++ b/core/image.cpp @@ -725,6 +725,131 @@ static void _scale_nearest(const uint8_t *__restrict p_src, uint8_t *__restrict } } +#define LANCZOS_TYPE 3 + +static float _lanczos(float p_x) { + return Math::abs(p_x) >= LANCZOS_TYPE ? 0 : Math::sincn(p_x) * Math::sincn(p_x / LANCZOS_TYPE); +} + +template <int CC, class T> +static void _scale_lanczos(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) { + + int32_t src_width = p_src_width; + int32_t src_height = p_src_height; + int32_t dst_height = p_dst_height; + int32_t dst_width = p_dst_width; + + uint32_t buffer_size = src_height * dst_width * CC; + float *buffer = memnew_arr(float, buffer_size); // Store the first pass in a buffer + + { // FIRST PASS (horizontal) + + float x_scale = float(src_width) / float(dst_width); + + float scale_factor = MAX(x_scale, 1); // A larger kernel is required only when downscaling + int32_t half_kernel = LANCZOS_TYPE * scale_factor; + + float *kernel = memnew_arr(float, half_kernel * 2 - 1); + + for (int32_t buffer_x = 0; buffer_x < dst_width; buffer_x++) { + + float src_real_x = buffer_x * x_scale; + int32_t src_x = src_real_x; + + int32_t start_x = MAX(0, src_x - half_kernel + 1); + int32_t end_x = MIN(src_width - 1, src_x + half_kernel); + + // Create the kernel used by all the pixels of the column + for (int32_t target_x = start_x; target_x <= end_x; target_x++) + kernel[target_x - start_x] = _lanczos((src_real_x - target_x) / scale_factor); + + for (int32_t buffer_y = 0; buffer_y < src_height; buffer_y++) { + + float pixel[CC] = { 0 }; + float weight = 0; + + for (int32_t target_x = start_x; target_x <= end_x; target_x++) { + + float lanczos_val = kernel[target_x - start_x]; + weight += lanczos_val; + + const T *__restrict src_data = ((const T *)p_src) + (buffer_y * src_width + target_x) * CC; + + for (uint32_t i = 0; i < CC; i++) { + if (sizeof(T) == 2) //half float + pixel[i] += Math::half_to_float(src_data[i]) * lanczos_val; + else + pixel[i] += src_data[i] * lanczos_val; + } + } + + float *dst_data = ((float *)buffer) + (buffer_y * dst_width + buffer_x) * CC; + + for (uint32_t i = 0; i < CC; i++) + dst_data[i] = pixel[i] / weight; // Normalize the sum of all the samples + } + } + + memdelete_arr(kernel); + } // End of first pass + + { // SECOND PASS (vertical + result) + + float y_scale = float(src_height) / float(dst_height); + + float scale_factor = MAX(y_scale, 1); + int32_t half_kernel = LANCZOS_TYPE * scale_factor; + + float *kernel = memnew_arr(float, half_kernel * 2 - 1); + + for (int32_t dst_y = 0; dst_y < dst_height; dst_y++) { + + float buffer_real_y = dst_y * y_scale; + int32_t buffer_y = buffer_real_y; + + int32_t start_y = MAX(0, buffer_y - half_kernel + 1); + int32_t end_y = MIN(src_height - 1, buffer_y + half_kernel); + + for (int32_t target_y = start_y; target_y <= end_y; target_y++) + kernel[target_y - start_y] = _lanczos((buffer_real_y - target_y) / scale_factor); + + for (int32_t dst_x = 0; dst_x < dst_width; dst_x++) { + + float pixel[CC] = { 0 }; + float weight = 0; + + for (int32_t target_y = start_y; target_y <= end_y; target_y++) { + + float lanczos_val = kernel[target_y - start_y]; + weight += lanczos_val; + + float *buffer_data = ((float *)buffer) + (target_y * dst_width + dst_x) * CC; + + for (uint32_t i = 0; i < CC; i++) + pixel[i] += buffer_data[i] * lanczos_val; + } + + T *dst_data = ((T *)p_dst) + (dst_y * dst_width + dst_x) * CC; + + for (uint32_t i = 0; i < CC; i++) { + pixel[i] /= weight; + + if (sizeof(T) == 1) //byte + dst_data[i] = CLAMP(Math::fast_ftoi(pixel[i]), 0, 255); + else if (sizeof(T) == 2) //half float + dst_data[i] = Math::make_half_float(pixel[i]); + else // float + dst_data[i] = pixel[i]; + } + } + } + + memdelete_arr(kernel); + } // End of second pass + + memdelete_arr(buffer); +} + static void _overlay(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, float p_alpha, uint32_t p_width, uint32_t p_height, uint32_t p_pixel_size) { uint16_t alpha = CLAMP((uint16_t)(p_alpha * 256.0f), 0, 256); @@ -939,6 +1064,31 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) { } } } break; + case INTERPOLATE_LANCZOS: { + + if (format >= FORMAT_L8 && format <= FORMAT_RGBA8) { + switch (get_format_pixel_size(format)) { + case 1: _scale_lanczos<1, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; + case 2: _scale_lanczos<2, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; + case 3: _scale_lanczos<3, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; + case 4: _scale_lanczos<4, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; + } + } else if (format >= FORMAT_RF && format <= FORMAT_RGBAF) { + switch (get_format_pixel_size(format)) { + case 4: _scale_lanczos<1, float>(r_ptr, w_ptr, width, height, p_width, p_height); break; + case 8: _scale_lanczos<2, float>(r_ptr, w_ptr, width, height, p_width, p_height); break; + case 12: _scale_lanczos<3, float>(r_ptr, w_ptr, width, height, p_width, p_height); break; + case 16: _scale_lanczos<4, float>(r_ptr, w_ptr, width, height, p_width, p_height); break; + } + } else if (format >= FORMAT_RH && format <= FORMAT_RGBAH) { + switch (get_format_pixel_size(format)) { + case 2: _scale_lanczos<1, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; + case 4: _scale_lanczos<2, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; + case 6: _scale_lanczos<3, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; + case 8: _scale_lanczos<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; + } + } + } break; } r = PoolVector<uint8_t>::Read(); @@ -2685,6 +2835,7 @@ void Image::_bind_methods() { BIND_ENUM_CONSTANT(INTERPOLATE_BILINEAR); BIND_ENUM_CONSTANT(INTERPOLATE_CUBIC); BIND_ENUM_CONSTANT(INTERPOLATE_TRILINEAR); + BIND_ENUM_CONSTANT(INTERPOLATE_LANCZOS); BIND_ENUM_CONSTANT(ALPHA_NONE); BIND_ENUM_CONSTANT(ALPHA_BIT); diff --git a/core/image.h b/core/image.h index 69a42f169a..752ef20208 100644 --- a/core/image.h +++ b/core/image.h @@ -109,6 +109,7 @@ public: INTERPOLATE_BILINEAR, INTERPOLATE_CUBIC, INTERPOLATE_TRILINEAR, + INTERPOLATE_LANCZOS, /* INTERPOLATE_TRICUBIC, */ /* INTERPOLATE GAUSS */ }; diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h index a75f2fb4ab..82b5b56c01 100644 --- a/core/math/math_funcs.h +++ b/core/math/math_funcs.h @@ -61,6 +61,12 @@ public: static _ALWAYS_INLINE_ double sinh(double p_x) { return ::sinh(p_x); } static _ALWAYS_INLINE_ float sinh(float p_x) { return ::sinhf(p_x); } + static _ALWAYS_INLINE_ float sinc(float p_x) { return p_x == 0 ? 1 : ::sin(p_x) / p_x; } + static _ALWAYS_INLINE_ double sinc(double p_x) { return p_x == 0 ? 1 : ::sin(p_x) / p_x; } + + static _ALWAYS_INLINE_ float sincn(float p_x) { return sinc(Math_PI * p_x); } + static _ALWAYS_INLINE_ double sincn(double p_x) { return sinc(Math_PI * p_x); } + static _ALWAYS_INLINE_ double cosh(double p_x) { return ::cosh(p_x); } static _ALWAYS_INLINE_ float cosh(float p_x) { return ::coshf(p_x); } diff --git a/core/object.cpp b/core/object.cpp index 937aa3c745..2a4ab93a6d 100644 --- a/core/object.cpp +++ b/core/object.cpp @@ -608,18 +608,16 @@ Variant Object::get_indexed(const Vector<StringName> &p_names, bool *r_valid) co } bool valid = false; - Variant current_value = get(p_names[0]); + Variant current_value = get(p_names[0], &valid); for (int i = 1; i < p_names.size(); i++) { current_value = current_value.get_named(p_names[i], &valid); - if (!valid) { - if (r_valid) - *r_valid = false; - return Variant(); - } + if (!valid) + break; } if (r_valid) - *r_valid = true; + *r_valid = valid; + return current_value; } diff --git a/doc/classes/Image.xml b/doc/classes/Image.xml index 641bd64599..8dfabdd884 100644 --- a/doc/classes/Image.xml +++ b/doc/classes/Image.xml @@ -603,6 +603,8 @@ If the image does not have mipmaps, they will be generated and used internally, but no mipmaps will be generated on the resulting image. (Note that if you intend to scale multiple copies of the original image, it's better to call [code]generate_mipmaps[/code] on it in advance, to avoid wasting processing power in generating them again and again.) On the other hand, if the image already has mipmaps, they will be used, and a new set will be generated for the resulting image. </constant> + <constant name="INTERPOLATE_LANCZOS" value="4" enum="Interpolation"> + </constant> <constant name="ALPHA_NONE" value="0" enum="AlphaMode"> </constant> <constant name="ALPHA_BIT" value="1" enum="AlphaMode"> diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 68ebaf1226..40e05940a7 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -1015,8 +1015,7 @@ void EditorNode::_save_scene_with_preview(String p_file, int p_idx) { y = (img->get_height() - size) / 2; img->crop_from_point(x, y, size, size); - // We could get better pictures with better filters - img->resize(preview_size, preview_size, Image::INTERPOLATE_CUBIC); + img->resize(preview_size, preview_size, Image::INTERPOLATE_LANCZOS); } img->convert(Image::FORMAT_RGB8); diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index c32dcb0ace..8f26663f81 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -651,7 +651,7 @@ void EditorSettings::_load_default_text_editor_theme() { _initial_set("text_editor/highlighting/executing_line_color", Color(0.2, 0.8, 0.2, 0.4)); _initial_set("text_editor/highlighting/code_folding_color", Color(0.8, 0.8, 0.8, 0.8)); _initial_set("text_editor/highlighting/search_result_color", Color(0.05, 0.25, 0.05, 1)); - _initial_set("text_editor/highlighting/search_result_border_color", Color(0.1, 0.45, 0.1, 1)); + _initial_set("text_editor/highlighting/search_result_border_color", Color(0.41, 0.61, 0.91, 0.38)); } bool EditorSettings::_save_text_editor_theme(String p_file) { diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index f74e913208..e1addaa532 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -1121,7 +1121,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { const Color executing_line_color = Color(0.2, 0.8, 0.2, 0.4); const Color code_folding_color = alpha3; const Color search_result_color = alpha1; - const Color search_result_border_color = alpha3; + const Color search_result_border_color = Color(0.41, 0.61, 0.91, 0.38); EditorSettings *setting = EditorSettings::get_singleton(); String text_editor_color_theme = setting->get("text_editor/theme/color_theme"); diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp index e5f70a0b34..733a900396 100644 --- a/modules/bullet/rigid_body_bullet.cpp +++ b/modules/bullet/rigid_body_bullet.cpp @@ -741,22 +741,20 @@ void RigidBodyBullet::set_continuous_collision_detection(bool p_enable) { if (p_enable) { // This threshold enable CCD if the object moves more than // 1 meter in one simulation frame - btBody->setCcdMotionThreshold(0.1); + btBody->setCcdMotionThreshold(1e-7); /// Calculate using the rule writte below the CCD swept sphere radius /// CCD works on an embedded sphere of radius, make sure this radius /// is embedded inside the convex objects, preferably smaller: /// for an object of dimensions 1 meter, try 0.2 - btScalar radius; + btScalar radius(1.0); if (btBody->getCollisionShape()) { btVector3 center; btBody->getCollisionShape()->getBoundingSphere(center, radius); - } else { - radius = 0; } btBody->setCcdSweptSphereRadius(radius * 0.2); } else { - btBody->setCcdMotionThreshold(0.); + btBody->setCcdMotionThreshold(10000.0); btBody->setCcdSweptSphereRadius(0.); } } @@ -834,7 +832,7 @@ void RigidBodyBullet::reload_shapes() { btBody->updateInertiaTensor(); reload_kinematic_shapes(); - + set_continuous_collision_detection(btBody->getCcdMotionThreshold() < 9998.0); reload_body(); } diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 10bd9e2a8b..86b99b3c6d 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -1072,10 +1072,7 @@ void TextEdit::_notification(int p_what) { } if ((char_ofs + char_margin + char_w) >= xmargin_end) { - if (syntax_coloring) - continue; - else - break; + break; } bool in_search_result = false; |