summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/ISSUE_TEMPLATE/bug_report.md11
-rw-r--r--.github/config.yml14
-rw-r--r--.gitignore3
-rw-r--r--COPYRIGHT.txt10
-rw-r--r--SConstruct81
-rw-r--r--core/SCsub1
-rw-r--r--core/bind/core_bind.cpp62
-rw-r--r--core/bind/core_bind.h5
-rw-r--r--core/callable_method_pointer.h36
-rw-r--r--core/color.cpp2
-rw-r--r--core/cowdata.h6
-rw-r--r--core/debugger/remote_debugger_peer.cpp6
-rw-r--r--core/engine.cpp4
-rw-r--r--core/error_macros.h37
-rw-r--r--core/image.cpp55
-rw-r--r--core/image.h1
-rw-r--r--core/input/input.cpp26
-rw-r--r--core/io/file_access_buffered_fa.h20
-rw-r--r--core/io/file_access_memory.cpp2
-rw-r--r--core/io/file_access_pack.cpp14
-rw-r--r--core/io/file_access_pack.h2
-rw-r--r--core/io/ip.cpp2
-rw-r--r--core/io/ip_address.cpp40
-rw-r--r--core/io/json.cpp18
-rw-r--r--core/io/marshalls.h2
-rw-r--r--core/io/packet_peer.cpp4
-rw-r--r--core/io/pck_packer.cpp32
-rw-r--r--core/io/xml_parser.cpp6
-rw-r--r--core/io/zip_io.cpp2
-rw-r--r--core/list.h60
-rw-r--r--core/local_vector.h4
-rw-r--r--core/make_binders.py6
-rw-r--r--core/map.h10
-rw-r--r--core/math/aabb.h2
-rw-r--r--core/math/camera_matrix.cpp18
-rw-r--r--core/math/expression.cpp48
-rw-r--r--core/math/geometry.cpp5
-rw-r--r--core/math/rect2.h4
-rw-r--r--core/math/triangulate.cpp2
-rw-r--r--core/math/vector2.cpp13
-rw-r--r--core/math/vector2.h13
-rw-r--r--core/message_queue.cpp15
-rw-r--r--core/message_queue.h1
-rw-r--r--core/oa_hash_map.h89
-rw-r--r--core/object.cpp2
-rw-r--r--core/ordered_hash_map.h16
-rw-r--r--core/os/dir_access.cpp8
-rw-r--r--core/os/file_access.cpp22
-rw-r--r--core/os/os.cpp22
-rw-r--r--core/os/os.h7
-rw-r--r--core/os/thread.cpp2
-rw-r--r--core/os/thread_dummy.cpp8
-rw-r--r--core/packed_data_container.cpp12
-rw-r--r--core/pool_allocator.cpp8
-rw-r--r--core/project_settings.cpp16
-rw-r--r--core/ring_buffer.h48
-rw-r--r--core/safe_refcount.cpp32
-rw-r--r--core/translation.cpp4
-rw-r--r--core/ustring.cpp44
-rw-r--r--core/variant.cpp52
-rw-r--r--core/variant.h4
-rw-r--r--core/variant_call.cpp11
-rw-r--r--core/variant_op.cpp30
-rw-r--r--core/variant_parser.cpp26
-rw-r--r--core/vector.h4
-rw-r--r--doc/classes/@GlobalScope.xml4
-rw-r--r--doc/classes/Array.xml2
-rw-r--r--doc/classes/Camera3D.xml1
-rw-r--r--doc/classes/CanvasItem.xml8
-rw-r--r--doc/classes/Dictionary.xml1
-rw-r--r--doc/classes/DisplayServer.xml4
-rw-r--r--doc/classes/Image.xml7
-rw-r--r--doc/classes/ImageTextureLayered.xml31
-rw-r--r--doc/classes/KinematicBody3D.xml16
-rw-r--r--doc/classes/Lightmapper.xml13
-rw-r--r--doc/classes/Node.xml12
-rw-r--r--doc/classes/OS.xml21
-rw-r--r--doc/classes/Object.xml2
-rw-r--r--doc/classes/PhysicalSkyMaterial.xml3
-rw-r--r--doc/classes/PopupMenu.xml2
-rw-r--r--doc/classes/ProjectSettings.xml30
-rw-r--r--doc/classes/TabContainer.xml4
-rw-r--r--doc/classes/TextEdit.xml16
-rw-r--r--drivers/alsa/audio_driver_alsa.cpp4
-rw-r--r--drivers/coreaudio/audio_driver_coreaudio.cpp6
-rw-r--r--drivers/dummy/rasterizer_dummy.h7
-rw-r--r--drivers/pulseaudio/audio_driver_pulseaudio.cpp4
-rw-r--r--drivers/vulkan/rendering_device_vulkan.cpp6
-rw-r--r--drivers/wasapi/audio_driver_wasapi.cpp2
-rw-r--r--drivers/xaudio2/audio_driver_xaudio2.cpp4
-rw-r--r--editor/SCsub26
-rw-r--r--editor/animation_track_editor.cpp4
-rw-r--r--editor/doc_data.h18
-rw-r--r--editor/editor_export.cpp56
-rw-r--r--editor/editor_export.h5
-rw-r--r--editor/editor_feature_profile.cpp36
-rw-r--r--editor/editor_feature_profile.h3
-rw-r--r--editor/editor_node.cpp5
-rw-r--r--editor/editor_spin_slider.cpp1
-rw-r--r--editor/icons/CameraEffects.svg1
-rw-r--r--editor/icons/Cubemap.svg (renamed from editor/icons/CubeMap.svg)0
-rw-r--r--editor/icons/CubemapArray.svg1
-rw-r--r--editor/icons/LightmapProbe.svg1
-rw-r--r--editor/icons/PanoramaSky.svg1
-rw-r--r--editor/icons/PanoramaSkyMaterial.svg1
-rw-r--r--editor/icons/PhysicalSkyMaterial.svg1
-rw-r--r--editor/icons/ProceduralSky.svg1
-rw-r--r--editor/icons/ProceduralSkyMaterial.svg1
-rw-r--r--editor/icons/RootMotionView.svg1
-rw-r--r--editor/icons/SCsub9
-rw-r--r--editor/icons/ShaderGlobalsOverride.svg1
-rw-r--r--editor/import_dock.cpp4
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp2
-rw-r--r--editor/project_export.cpp7
-rw-r--r--editor/project_export.h1
-rw-r--r--editor/scene_tree_dock.cpp15
-rw-r--r--gles_builders.py10
-rw-r--r--main/main.cpp77
-rw-r--r--main/tests/test_class_db.cpp882
-rw-r--r--main/tests/test_class_db.h42
-rw-r--r--main/tests/test_main.cpp6
-rw-r--r--main/tests/test_oa_hash_map.cpp141
-rw-r--r--methods.py69
-rw-r--r--misc/scons/compilation_db.py (renamed from misc/scons/site_tools/compilation_db.py)0
-rw-r--r--modules/SCsub13
-rw-r--r--modules/bullet/rigid_body_bullet.cpp5
-rw-r--r--modules/camera/camera_win.cpp16
-rw-r--r--modules/camera/camera_win.h2
-rw-r--r--modules/gdnative/gdnative/aabb.cpp2
-rw-r--r--modules/gdnative/gdnative/array.cpp34
-rw-r--r--modules/gdnative/gdnative/basis.cpp2
-rw-r--r--modules/gdnative/gdnative/callable.cpp252
-rw-r--r--modules/gdnative/gdnative/color.cpp2
-rw-r--r--modules/gdnative/gdnative/dictionary.cpp2
-rw-r--r--modules/gdnative/gdnative/gdnative.cpp7
-rw-r--r--modules/gdnative/gdnative/node_path.cpp2
-rw-r--r--modules/gdnative/gdnative/packed_arrays.cpp (renamed from modules/gdnative/gdnative/pool_arrays.cpp)326
-rw-r--r--modules/gdnative/gdnative/plane.cpp2
-rw-r--r--modules/gdnative/gdnative/quat.cpp2
-rw-r--r--modules/gdnative/gdnative/rect2.cpp155
-rw-r--r--modules/gdnative/gdnative/rid.cpp2
-rw-r--r--modules/gdnative/gdnative/string.cpp4
-rw-r--r--modules/gdnative/gdnative/string_name.cpp2
-rw-r--r--modules/gdnative/gdnative/transform.cpp2
-rw-r--r--modules/gdnative/gdnative/transform2d.cpp2
-rw-r--r--modules/gdnative/gdnative/variant.cpp133
-rw-r--r--modules/gdnative/gdnative/vector2.cpp151
-rw-r--r--modules/gdnative/gdnative/vector3.cpp146
-rw-r--r--modules/gdnative/gdnative_api.json1296
-rw-r--r--modules/gdnative/include/gdnative/array.h8
-rw-r--r--modules/gdnative/include/gdnative/callable.h126
-rw-r--r--modules/gdnative/include/gdnative/gdnative.h18
-rw-r--r--modules/gdnative/include/gdnative/packed_arrays.h (renamed from modules/gdnative/include/gdnative/pool_arrays.h)180
-rw-r--r--modules/gdnative/include/gdnative/rect2.h54
-rw-r--r--modules/gdnative/include/gdnative/rid.h2
-rw-r--r--modules/gdnative/include/gdnative/variant.h40
-rw-r--r--modules/gdnative/include/gdnative/vector2.h55
-rw-r--r--modules/gdnative/include/gdnative/vector3.h53
-rw-r--r--modules/gdnative/include/nativescript/godot_nativescript.h8
-rw-r--r--modules/gdnative/nativescript/godot_nativescript.cpp6
-rw-r--r--modules/gdnavigation/nav_map.cpp1
-rw-r--r--modules/gdscript/gdscript_function.cpp2
-rw-r--r--modules/gdscript/gdscript_parser.cpp86
-rw-r--r--modules/gdscript/gdscript_parser.h2
-rw-r--r--modules/gdscript/language_server/lsp.hpp6
-rw-r--r--modules/jsonrpc/jsonrpc.cpp2
-rw-r--r--modules/lightmapper_rd/lm_blendseams.glsl53
-rw-r--r--modules/lightmapper_rd/lm_common_inc.glsl7
-rw-r--r--modules/lightmapper_rd/lm_compute.glsl22
-rw-r--r--modules/lightmapper_rd/lm_raster.glsl22
-rw-r--r--modules/mobile_vr/mobile_vr_interface.cpp6
-rw-r--r--modules/mobile_vr/mobile_vr_interface.h2
-rw-r--r--modules/mono/SCsub2
-rw-r--r--modules/mono/config.py1
-rw-r--r--modules/mono/csharp_script.cpp60
-rw-r--r--modules/mono/csharp_script.h6
-rw-r--r--modules/mono/editor/bindings_generator.cpp492
-rw-r--r--modules/mono/editor/bindings_generator.h140
-rw-r--r--modules/mono/mono_gd/gd_mono.cpp3
-rw-r--r--modules/theora/video_stream_theora.cpp11
-rw-r--r--modules/websocket/register_types.cpp9
-rw-r--r--modules/xatlas_unwrap/register_types.cpp2
-rw-r--r--platform/android/audio_driver_jandroid.cpp4
-rw-r--r--platform/android/display_server_android.cpp23
-rw-r--r--platform/android/display_server_android.h4
-rw-r--r--platform/android/export/export.cpp148
-rw-r--r--platform/android/java/app/AndroidManifest.xml4
-rw-r--r--platform/android/java/app/build.gradle29
-rw-r--r--platform/android/java/app/config.gradle81
-rw-r--r--platform/android/java/build.gradle3
-rw-r--r--platform/android/java/gradle.properties3
-rw-r--r--platform/android/java/lib/src/com/google/android/vending/expansion/downloader/impl/DownloadNotification.java4
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/Godot.java9
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotIO.java4
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotLib.java11
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotRenderer.java2
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java39
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java10
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java6
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginRegistry.java15
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/plugin/SignalInfo.java3
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java3
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/vulkan/VkRenderer.kt11
-rw-r--r--platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/GodotPayment.java9
-rw-r--r--platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/PurchaseTask.java2
-rw-r--r--platform/android/java_godot_io_wrapper.cpp6
-rw-r--r--platform/android/java_godot_io_wrapper.h2
-rw-r--r--platform/android/java_godot_lib_jni.cpp25
-rw-r--r--platform/android/java_godot_lib_jni.h6
-rw-r--r--platform/android/plugin/godot_plugin_config.h251
-rw-r--r--platform/haiku/audio_driver_media_kit.cpp4
-rw-r--r--platform/iphone/os_iphone.cpp2
-rw-r--r--platform/iphone/os_iphone.h2
-rw-r--r--platform/javascript/audio_driver_javascript.cpp51
-rw-r--r--platform/javascript/audio_driver_javascript.h1
-rw-r--r--platform/osx/display_server_osx.mm49
-rw-r--r--platform/osx/export/export.cpp329
-rw-r--r--platform/uwp/os_uwp.cpp2
-rw-r--r--platform/uwp/os_uwp.h2
-rw-r--r--platform/uwp/thread_uwp.cpp8
-rw-r--r--platform/uwp/thread_uwp.h8
-rw-r--r--platform/windows/display_server_windows.cpp143
-rw-r--r--platform/windows/display_server_windows.h15
-rw-r--r--platform/windows/key_mapping_windows.cpp13
-rw-r--r--platform/windows/key_mapping_windows.h1
-rw-r--r--platform/windows/os_windows.cpp106
-rw-r--r--platform/windows/os_windows.h10
-rw-r--r--scene/3d/physics_body_3d.cpp12
-rw-r--r--scene/3d/proximity_group_3d.cpp9
-rw-r--r--scene/3d/proximity_group_3d.h10
-rw-r--r--scene/3d/xr_nodes.cpp36
-rw-r--r--scene/3d/xr_nodes.h28
-rw-r--r--scene/debugger/scene_debugger.cpp9
-rw-r--r--scene/gui/container.cpp4
-rw-r--r--scene/gui/graph_edit.cpp13
-rw-r--r--scene/gui/graph_edit.h1
-rw-r--r--scene/gui/line_edit.cpp12
-rw-r--r--scene/gui/option_button.cpp3
-rw-r--r--scene/gui/popup_menu.cpp2
-rw-r--r--scene/gui/tab_container.cpp4
-rw-r--r--scene/gui/text_edit.cpp18
-rw-r--r--scene/gui/text_edit.h8
-rw-r--r--scene/main/node.cpp18
-rw-r--r--scene/main/node.h2
-rw-r--r--scene/main/window.cpp11
-rw-r--r--scene/resources/default_theme/default_theme.cpp35
-rw-r--r--scene/resources/sky_material.cpp17
-rw-r--r--scene/resources/sky_material.h4
-rw-r--r--servers/audio/audio_driver_dummy.cpp12
-rw-r--r--servers/audio/audio_driver_dummy.h6
-rw-r--r--servers/audio_server.cpp3
-rw-r--r--servers/audio_server.h6
-rw-r--r--servers/display_server.cpp4
-rw-r--r--servers/display_server.h2
-rw-r--r--servers/physics_2d/physics_server_2d_sw.cpp4
-rw-r--r--servers/physics_2d/physics_server_2d_sw.h2
-rw-r--r--servers/physics_3d/physics_server_3d_sw.cpp8
-rw-r--r--servers/physics_3d/physics_server_3d_sw.h4
-rw-r--r--servers/rendering/rasterizer_rd/shaders/bokeh_dof.glsl5
-rw-r--r--servers/rendering/rasterizer_rd/shaders/canvas.glsl11
-rw-r--r--servers/rendering/rasterizer_rd/shaders/canvas_occlusion.glsl9
-rw-r--r--servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl5
-rw-r--r--servers/rendering/rasterizer_rd/shaders/copy.glsl5
-rw-r--r--servers/rendering/rasterizer_rd/shaders/copy_to_fb.glsl16
-rw-r--r--servers/rendering/rasterizer_rd/shaders/cube_to_dp.glsl5
-rw-r--r--servers/rendering/rasterizer_rd/shaders/cubemap_downsampler.glsl5
-rw-r--r--servers/rendering/rasterizer_rd/shaders/cubemap_filter.glsl6
-rw-r--r--servers/rendering/rasterizer_rd/shaders/cubemap_roughness.glsl5
-rw-r--r--servers/rendering/rasterizer_rd/shaders/giprobe.glsl10
-rw-r--r--servers/rendering/rasterizer_rd/shaders/giprobe_debug.glsl10
-rw-r--r--servers/rendering/rasterizer_rd/shaders/giprobe_sdf.glsl15
-rw-r--r--servers/rendering/rasterizer_rd/shaders/giprobe_write.glsl14
-rw-r--r--servers/rendering/rasterizer_rd/shaders/luminance_reduce.glsl6
-rw-r--r--servers/rendering/rasterizer_rd/shaders/roughness_limiter.glsl9
-rw-r--r--servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl10
-rw-r--r--servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl12
-rw-r--r--servers/rendering/rasterizer_rd/shaders/screen_space_reflection.glsl8
-rw-r--r--servers/rendering/rasterizer_rd/shaders/screen_space_reflection_filter.glsl8
-rw-r--r--servers/rendering/rasterizer_rd/shaders/screen_space_reflection_scale.glsl8
-rw-r--r--servers/rendering/rasterizer_rd/shaders/sky.glsl11
-rw-r--r--servers/rendering/rasterizer_rd/shaders/specular_merge.glsl8
-rw-r--r--servers/rendering/rasterizer_rd/shaders/ssao.glsl6
-rw-r--r--servers/rendering/rasterizer_rd/shaders/ssao_blur.glsl5
-rw-r--r--servers/rendering/rasterizer_rd/shaders/ssao_minify.glsl5
-rw-r--r--servers/rendering/rasterizer_rd/shaders/subsurface_scattering.glsl8
-rw-r--r--servers/rendering/rasterizer_rd/shaders/tonemap.glsl14
-rw-r--r--servers/rendering/rendering_device_binds.cpp28
-rw-r--r--servers/xr/xr_interface.cpp4
-rw-r--r--servers/xr/xr_positional_tracker.cpp4
-rw-r--r--servers/xr/xr_positional_tracker.h2
-rw-r--r--thirdparty/README.md8
-rw-r--r--thirdparty/jpeg-compressor/patches/fix-msvc-sse2-detection.patch44
-rw-r--r--thirdparty/jpeg-compressor/patches/fix-msvc2017-build.patch31
-rw-r--r--thirdparty/misc/cubemap_coeffs.h4
-rw-r--r--thirdparty/misc/hq2x.cpp2636
-rw-r--r--thirdparty/misc/hq2x.h19
-rw-r--r--thirdparty/misc/r128.h14
-rw-r--r--thirdparty/oidn/0001-window.h-case-sensitive.patch13
-rw-r--r--thirdparty/oidn/common/platform.h2
-rw-r--r--thirdparty/xatlas/LICENSE2
-rw-r--r--thirdparty/xatlas/xatlas.cpp6479
-rw-r--r--thirdparty/xatlas/xatlas.h63
302 files changed, 10613 insertions, 7609 deletions
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index 91528465c0..7e8c5fd740 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -6,13 +6,24 @@ labels: ''
assignees: ''
---
+<!-- Please search existing issues for potential duplicates before filing yours:
+https://github.com/godotengine/godot/issues?q=is%3Aissue
+-->
**Godot version:**
+<!-- Specify commit hash if using non-official build. -->
+
**OS/device including version:**
+<!-- Specify GPU model, drivers, and the backend (GLES2, GLES3, Vulkan) if graphics-related. -->
+
**Issue description:**
+<!-- What happened, and what was expected. -->
+
**Steps to reproduce:**
+
**Minimal reproduction project:**
+<!-- A small Godot project which reproduces the issue. Drag and drop a zip archive to upload it. -->
diff --git a/.github/config.yml b/.github/config.yml
new file mode 100644
index 0000000000..f787bec00e
--- /dev/null
+++ b/.github/config.yml
@@ -0,0 +1,14 @@
+blank_issues_enabled: false
+
+contact_links:
+ - name: Godot proposals
+ url: https://github.com/godotengine/godot-proposals
+ about: Please submit feature proposals on the Godot proposals repository, not here.
+
+ - name: Godot documentation repository
+ url: https://github.com/godotengine/godot-docs
+ about: Please report issues with documentation on the Godot documentation repository, not here.
+
+ - name: Godot community channels
+ url: https://godotengine.org/community
+ about: Please ask for technical support on one of the other community channels, not here.
diff --git a/.gitignore b/.gitignore
index 19490b9878..dfb1490aa9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -89,6 +89,9 @@ logs/
*.sln
*.vcxproj*
+# Custom SCons configuration override
+/custom.py
+
# Build results
[Dd]ebug/
[Dd]ebugPublic/
diff --git a/COPYRIGHT.txt b/COPYRIGHT.txt
index 443e6fee97..2d32bf1fd9 100644
--- a/COPYRIGHT.txt
+++ b/COPYRIGHT.txt
@@ -257,12 +257,6 @@ Comment: FastLZ
Copyright: 2005-2020, Ariya Hidayat
License: Expat
-Files: ./thirdparty/misc/hq2x.cpp
- ./thirdparty/misc/hq2x.h
-Comment: hq2x implementation
-Copyright: 2016, Bruno Ribeiro
-License: Apache-2.0
-
Files: ./thirdparty/misc/ifaddrs-android.cc
./thirdparty/misc/ifaddrs-android.h
Comment: libjingle
@@ -334,7 +328,7 @@ License: Zlib
Files: ./thirdparty/rvo2/
Comment: RVO2
-Copyright: 2016, University of North Carolina at Chapel Hill
+Copyright: 2016, University of North Carolina at Chapel Hill
License: Apache 2.0
Files: ./thirdparty/squish/
@@ -374,7 +368,7 @@ License: Expat
Files: ./thirdparty/xatlas/
Comment: xatlas
-Copyright: 2018, Jonathan Young
+Copyright: 2018-2020, Jonathan Young
2013, Thekla, Inc
2006, NVIDIA Corporation, Ignacio Castano
License: Expat
diff --git a/SConstruct b/SConstruct
index 86014b8160..515cad57d0 100644
--- a/SConstruct
+++ b/SConstruct
@@ -50,8 +50,6 @@ for x in sorted(glob.glob("platform/*")):
sys.path.remove(tmppath)
sys.modules.pop("detect")
-module_list = methods.detect_modules()
-
methods.save_active_platforms(active_platforms, active_platform_ids)
custom_tools = ["default"]
@@ -123,6 +121,7 @@ opts.Add(BoolVariable("use_precise_math_checks", "Math checks use very precise e
opts.Add(BoolVariable("deprecated", "Enable deprecated features", True))
opts.Add(BoolVariable("minizip", "Enable ZIP archive support using minizip", True))
opts.Add(BoolVariable("xaudio2", "Enable the XAudio2 audio driver", False))
+opts.Add("custom_modules", "A list of comma-separated directory paths containing custom modules to build.", "")
# Advanced options
opts.Add(BoolVariable("verbose", "Enable verbose output for the compilation", False))
@@ -181,18 +180,41 @@ for k in platform_opts.keys():
for o in opt_list:
opts.Add(o)
-for x in module_list:
- module_enabled = True
- tmppath = "./modules/" + x
- sys.path.insert(0, tmppath)
+# Detect modules.
+modules_detected = {}
+module_search_paths = ["modules"] # Built-in path.
+
+if ARGUMENTS.get("custom_modules"):
+ paths = ARGUMENTS.get("custom_modules").split(",")
+ for p in paths:
+ try:
+ module_search_paths.append(methods.convert_custom_modules_path(p))
+ except ValueError as e:
+ print(e)
+ sys.exit(255)
+
+for path in module_search_paths:
+ # Note: custom modules can override built-in ones.
+ modules_detected.update(methods.detect_modules(path))
+ include_path = os.path.dirname(path)
+ if include_path:
+ env_base.Prepend(CPPPATH=[include_path])
+
+# Add module options.
+for name, path in modules_detected.items():
+ enabled = True
+ sys.path.insert(0, path)
import config
- enabled_attr = getattr(config, "is_enabled", None)
- if callable(enabled_attr) and not config.is_enabled():
- module_enabled = False
- sys.path.remove(tmppath)
+ try:
+ enabled = config.is_enabled()
+ except AttributeError:
+ pass
+ sys.path.remove(path)
sys.modules.pop("config")
- opts.Add(BoolVariable("module_" + x + "_enabled", "Enable module '%s'" % (x,), module_enabled))
+ opts.Add(BoolVariable("module_" + name + "_enabled", "Enable module '%s'" % (name,), enabled))
+
+methods.write_modules(modules_detected)
opts.Update(env_base) # update environment
Help(opts.GenerateHelpText(env_base)) # generate help
@@ -272,14 +294,13 @@ if selected_platform in platform_list:
else:
env = env_base.Clone()
- # Custom tools are loaded automatically by SCons from site_scons/site_tools,
- # but we want to use a different folder, so we register it manually.
- from SCons.Script.Main import _load_site_scons_dir
-
- _load_site_scons_dir(".", "misc/scons")
+ # Compilation DB requires SCons 3.1.1+.
+ from SCons import __version__ as scons_raw_version
- env.Tool("compilation_db")
- env.Alias("compiledb", env.CompilationDatabase("compile_commands.json"))
+ scons_ver = env._get_major_minor_revision(scons_raw_version)
+ if scons_ver >= (3, 1, 1):
+ env.Tool("compilation_db", toolpath=["misc/scons"])
+ env.Alias("compiledb", env.CompilationDatabase("compile_commands.json"))
if env["dev"]:
env["verbose"] = True
@@ -502,41 +523,41 @@ if selected_platform in platform_list:
sys.path.remove(tmppath)
sys.modules.pop("detect")
- env.module_list = []
+ modules_enabled = {}
env.module_icons_paths = []
env.doc_class_path = {}
- for x in sorted(module_list):
- if not env["module_" + x + "_enabled"]:
+ for name, path in sorted(modules_detected.items()):
+ if not env["module_" + name + "_enabled"]:
continue
- tmppath = "./modules/" + x
- sys.path.insert(0, tmppath)
- env.current_module = x
+ sys.path.insert(0, path)
+ env.current_module = name
import config
if config.can_build(env, selected_platform):
config.configure(env)
- env.module_list.append(x)
-
# Get doc classes paths (if present)
try:
doc_classes = config.get_doc_classes()
doc_path = config.get_doc_path()
for c in doc_classes:
- env.doc_class_path[c] = "modules/" + x + "/" + doc_path
+ env.doc_class_path[c] = path + "/" + doc_path
except:
pass
# Get icon paths (if present)
try:
icons_path = config.get_icons_path()
- env.module_icons_paths.append("modules/" + x + "/" + icons_path)
+ env.module_icons_paths.append(path + "/" + icons_path)
except:
# Default path for module icons
- env.module_icons_paths.append("modules/" + x + "/" + "icons")
+ env.module_icons_paths.append(path + "/" + "icons")
+ modules_enabled[name] = path
- sys.path.remove(tmppath)
+ sys.path.remove(path)
sys.modules.pop("config")
+ env.module_list = modules_enabled
+
methods.update_version(env.module_version_string)
env["PROGSUFFIX"] = suffix + env.module_version_string + env["PROGSUFFIX"]
diff --git a/core/SCsub b/core/SCsub
index d53988fae7..80a5f6b623 100644
--- a/core/SCsub
+++ b/core/SCsub
@@ -52,7 +52,6 @@ thirdparty_misc_sources = [
"r128.c",
"smaz.c",
# C++ sources
- "hq2x.cpp",
"pcg.cpp",
"triangulator.cpp",
"clipper.cpp",
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp
index 607e17eae4..10f44d357b 100644
--- a/core/bind/core_bind.cpp
+++ b/core/bind/core_bind.cpp
@@ -117,7 +117,7 @@ PackedStringArray _ResourceLoader::get_dependencies(const String &p_path) {
}
return ret;
-};
+}
bool _ResourceLoader::has_cached(const String &p_path) {
String local_path = ProjectSettings::get_singleton()->localize_path(p_path);
@@ -224,7 +224,7 @@ Error _OS::shell_open(String p_uri) {
WARN_PRINT("Attempting to open an URL with the \"user://\" protocol. Use `ProjectSettings.globalize_path()` to convert a Godot-specific path to a system path before opening it with `OS.shell_open()`.");
}
return OS::get_singleton()->shell_open(p_uri);
-};
+}
int _OS::execute(const String &p_path, const Vector<String> &p_arguments, bool p_blocking, Array p_output, bool p_read_stderr) {
OS::ProcessID pid = -2;
@@ -252,7 +252,7 @@ Error _OS::kill(int p_pid) {
int _OS::get_process_id() const {
return OS::get_singleton()->get_process_id();
-};
+}
bool _OS::has_environment(const String &p_var) const {
return OS::get_singleton()->has_environment(p_var);
@@ -286,7 +286,7 @@ String _OS::get_model_name() const {
Error _OS::set_thread_name(const String &p_name) {
return Thread::set_name(p_name);
-};
+}
bool _OS::has_feature(const String &p_feature) const {
return OS::get_singleton()->has_feature(p_feature);
@@ -620,7 +620,7 @@ void _OS::print_resources_by_type(const Vector<String> &p_types) {
type_count[r->get_class()]++;
}
-};
+}
void _OS::print_all_resources(const String &p_to_file) {
OS::get_singleton()->print_all_resources(p_to_file);
@@ -636,7 +636,7 @@ void _OS::dump_resources_to_file(const String &p_file) {
String _OS::get_user_data_dir() const {
return OS::get_singleton()->get_user_data_dir();
-};
+}
bool _OS::is_debug_build() const {
#ifdef DEBUG_ENABLED
@@ -678,6 +678,22 @@ String _OS::get_unique_id() const {
return OS::get_singleton()->get_unique_id();
}
+int _OS::get_tablet_driver_count() const {
+ return OS::get_singleton()->get_tablet_driver_count();
+}
+
+String _OS::get_tablet_driver_name(int p_driver) const {
+ return OS::get_singleton()->get_tablet_driver_name(p_driver);
+}
+
+String _OS::get_current_tablet_driver() const {
+ return OS::get_singleton()->get_current_tablet_driver();
+}
+
+void _OS::set_current_tablet_driver(const String &p_driver) {
+ OS::get_singleton()->set_current_tablet_driver(p_driver);
+}
+
_OS *_OS::singleton = nullptr;
void _OS::_bind_methods() {
@@ -762,9 +778,15 @@ void _OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("request_permissions"), &_OS::request_permissions);
ClassDB::bind_method(D_METHOD("get_granted_permissions"), &_OS::get_granted_permissions);
+ ClassDB::bind_method(D_METHOD("get_tablet_driver_count"), &_OS::get_tablet_driver_count);
+ ClassDB::bind_method(D_METHOD("get_tablet_driver_name", "idx"), &_OS::get_tablet_driver_name);
+ ClassDB::bind_method(D_METHOD("get_current_tablet_driver"), &_OS::get_current_tablet_driver);
+ ClassDB::bind_method(D_METHOD("set_current_tablet_driver", "name"), &_OS::set_current_tablet_driver);
+
ADD_PROPERTY(PropertyInfo(Variant::INT, "exit_code"), "set_exit_code", "get_exit_code");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "low_processor_usage_mode"), "set_low_processor_usage_mode", "is_in_low_processor_usage_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "low_processor_usage_mode_sleep_usec"), "set_low_processor_usage_mode_sleep_usec", "get_low_processor_usage_mode_sleep_usec");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "tablet_driver"), "set_current_tablet_driver", "get_current_tablet_driver");
// Those default values need to be specified for the docs generator,
// to avoid using values from the documentation writer's own OS instance.
@@ -840,8 +862,8 @@ Variant _Geometry::segment_intersects_segment_2d(const Vector2 &p_from_a, const
return result;
} else {
return Variant();
- };
-};
+ }
+}
Variant _Geometry::line_intersects_line_2d(const Vector2 &p_from_a, const Vector2 &p_dir_a, const Vector2 &p_from_b, const Vector2 &p_dir_b) {
Vector2 result;
@@ -1071,7 +1093,7 @@ Dictionary _Geometry::make_atlas(const Vector<Size2> &p_rects) {
Vector<Size2i> rects;
for (int i = 0; i < p_rects.size(); i++) {
rects.push_back(p_rects[i]);
- };
+ }
Vector<Point2i> result;
Size2i size;
@@ -1082,13 +1104,13 @@ Dictionary _Geometry::make_atlas(const Vector<Size2> &p_rects) {
Vector<Point2> r_result;
for (int i = 0; i < result.size(); i++) {
r_result.push_back(result[i]);
- };
+ }
ret["points"] = r_result;
ret["size"] = r_size;
return ret;
-};
+}
int _Geometry::get_uv84_normal_bit(const Vector3 &p_vector) {
return Geometry::get_uv84_normal_bit(p_vector);
@@ -1436,13 +1458,13 @@ void _File::store_pascal_string(const String &p_string) {
ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
f->store_pascal_string(p_string);
-};
+}
String _File::get_pascal_string() {
ERR_FAIL_COND_V_MSG(!f, "", "File must be opened before use.");
return f->get_pascal_string();
-};
+}
void _File::store_line(const String &p_string) {
ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
@@ -1784,7 +1806,7 @@ String _Marshalls::variant_to_base64(const Variant &p_var, bool p_full_objects)
ERR_FAIL_COND_V(ret == "", ret);
return ret;
-};
+}
Variant _Marshalls::base64_to_variant(const String &p_str, bool p_allow_objects) {
int strlen = p_str.length();
@@ -1802,13 +1824,13 @@ Variant _Marshalls::base64_to_variant(const String &p_str, bool p_allow_objects)
ERR_FAIL_COND_V_MSG(err != OK, Variant(), "Error when trying to decode Variant.");
return v;
-};
+}
String _Marshalls::raw_to_base64(const Vector<uint8_t> &p_arr) {
String ret = CryptoCore::b64_encode_str(p_arr.ptr(), p_arr.size());
ERR_FAIL_COND_V(ret == "", ret);
return ret;
-};
+}
Vector<uint8_t> _Marshalls::base64_to_raw(const String &p_str) {
int strlen = p_str.length();
@@ -1825,14 +1847,14 @@ Vector<uint8_t> _Marshalls::base64_to_raw(const String &p_str) {
buf.resize(arr_len);
return buf;
-};
+}
String _Marshalls::utf8_to_base64(const String &p_str) {
CharString cstr = p_str.utf8();
String ret = CryptoCore::b64_encode_str((unsigned char *)cstr.get_data(), cstr.length());
ERR_FAIL_COND_V(ret == "", ret);
return ret;
-};
+}
String _Marshalls::base64_to_utf8(const String &p_str) {
int strlen = p_str.length();
@@ -1849,7 +1871,7 @@ String _Marshalls::base64_to_utf8(const String &p_str) {
String ret = String::utf8((char *)&w[0]);
return ret;
-};
+}
void _Marshalls::_bind_methods() {
ClassDB::bind_method(D_METHOD("variant_to_base64", "variant", "full_objects"), &_Marshalls::variant_to_base64, DEFVAL(false));
@@ -1860,7 +1882,7 @@ void _Marshalls::_bind_methods() {
ClassDB::bind_method(D_METHOD("utf8_to_base64", "utf8_str"), &_Marshalls::utf8_to_base64);
ClassDB::bind_method(D_METHOD("base64_to_utf8", "base64_str"), &_Marshalls::base64_to_utf8);
-};
+}
////// _Semaphore //////
diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h
index 32ddcf2c74..e5bd70262d 100644
--- a/core/bind/core_bind.h
+++ b/core/bind/core_bind.h
@@ -243,6 +243,11 @@ public:
bool request_permissions();
Vector<String> get_granted_permissions() const;
+ int get_tablet_driver_count() const;
+ String get_tablet_driver_name(int p_driver) const;
+ String get_current_tablet_driver() const;
+ void set_current_tablet_driver(const String &p_driver);
+
static _OS *get_singleton() { return singleton; }
_OS() { singleton = this; }
diff --git a/core/callable_method_pointer.h b/core/callable_method_pointer.h
index 3b0503e259..22db7d1c82 100644
--- a/core/callable_method_pointer.h
+++ b/core/callable_method_pointer.h
@@ -161,19 +161,35 @@ template <class T, class... P>
class CallableCustomMethodPointer : public CallableCustomMethodPointerBase {
struct Data {
T *instance;
+#ifdef DEBUG_ENABLED
+ uint64_t object_id;
+#endif
void (T::*method)(P...);
} data;
public:
- virtual ObjectID get_object() const { return data.instance->get_instance_id(); }
+ virtual ObjectID get_object() const {
+#ifdef DEBUG_ENABLED
+ if (ObjectDB::get_instance(ObjectID(data.object_id)) == nullptr) {
+ return ObjectID();
+ }
+#endif
+ return data.instance->get_instance_id();
+ }
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
+#ifdef DEBUG_ENABLED
+ ERR_FAIL_COND_MSG(ObjectDB::get_instance(ObjectID(data.object_id)) == nullptr, "Invalid Object id '" + uitos(data.object_id) + "', can't call method.");
+#endif
call_with_variant_args(data.instance, data.method, p_arguments, p_argcount, r_call_error);
}
CallableCustomMethodPointer(T *p_instance, void (T::*p_method)(P...)) {
zeromem(&data, sizeof(Data)); // Clear beforehand, may have padding bytes.
data.instance = p_instance;
+#ifdef DEBUG_ENABLED
+ data.object_id = p_instance->get_instance_id();
+#endif
data.method = p_method;
_setup((uint32_t *)&data, sizeof(Data));
}
@@ -242,20 +258,36 @@ template <class T, class R, class... P>
class CallableCustomMethodPointerRet : public CallableCustomMethodPointerBase {
struct Data {
T *instance;
+#ifdef DEBUG_ENABLED
+ uint64_t object_id;
+#endif
R(T::*method)
(P...);
} data;
public:
- virtual ObjectID get_object() const { return data.instance->get_instance_id(); }
+ virtual ObjectID get_object() const {
+#ifdef DEBUG_ENABLED
+ if (ObjectDB::get_instance(ObjectID(data.object_id)) == nullptr) {
+ return ObjectID();
+ }
+#endif
+ return data.instance->get_instance_id();
+ }
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
+#ifdef DEBUG_ENABLED
+ ERR_FAIL_COND_MSG(ObjectDB::get_instance(ObjectID(data.object_id)) == nullptr, "Invalid Object id '" + uitos(data.object_id) + "', can't call method.");
+#endif
call_with_variant_args_ret(data.instance, data.method, p_arguments, p_argcount, r_return_value, r_call_error);
}
CallableCustomMethodPointerRet(T *p_instance, R (T::*p_method)(P...)) {
zeromem(&data, sizeof(Data)); // Clear beforehand, may have padding bytes.
data.instance = p_instance;
+#ifdef DEBUG_ENABLED
+ data.object_id = p_instance->get_instance_id();
+#endif
data.method = p_method;
_setup((uint32_t *)&data, sizeof(Data));
}
diff --git a/core/color.cpp b/core/color.cpp
index fa3f6475d4..27a2d0af5c 100644
--- a/core/color.cpp
+++ b/core/color.cpp
@@ -588,7 +588,7 @@ void Color::operator/=(const real_t &rvalue) {
b = b / rvalue;
a = a / rvalue;
}
-};
+}
Color Color::operator-() const {
return Color(
diff --git a/core/cowdata.h b/core/cowdata.h
index 3f72362e29..82daefb5bd 100644
--- a/core/cowdata.h
+++ b/core/cowdata.h
@@ -161,10 +161,10 @@ public:
int len = size();
for (int i = p_index; i < len - 1; i++) {
p[i] = p[i + 1];
- };
+ }
resize(len - 1);
- };
+ }
Error insert(int p_pos, const T &p_val) {
ERR_FAIL_INDEX_V(p_pos, size() + 1, ERR_INVALID_PARAMETER);
@@ -175,7 +175,7 @@ public:
set(p_pos, p_val);
return OK;
- };
+ }
int find(const T &p_val, int p_from = 0) const;
diff --git a/core/debugger/remote_debugger_peer.cpp b/core/debugger/remote_debugger_peer.cpp
index fd1eee0654..faa3a75fda 100644
--- a/core/debugger/remote_debugger_peer.cpp
+++ b/core/debugger/remote_debugger_peer.cpp
@@ -178,13 +178,13 @@ Error RemoteDebuggerPeerTCP::connect_to_host(const String &p_host, uint16_t p_po
const int ms = waits[i];
OS::get_singleton()->delay_usec(ms * 1000);
print_verbose("Remote Debugger: Connection failed with status: '" + String::num(tcp_client->get_status()) + "', retrying in " + String::num(ms) + " msec.");
- };
- };
+ }
+ }
if (tcp_client->get_status() != StreamPeerTCP::STATUS_CONNECTED) {
ERR_PRINT("Remote Debugger: Unable to connect. Status: " + String::num(tcp_client->get_status()) + ".");
return FAILED;
- };
+ }
connected = true;
#ifndef NO_THREADS
running = true;
diff --git a/core/engine.cpp b/core/engine.cpp
index 43c5766431..c8bfffd020 100644
--- a/core/engine.cpp
+++ b/core/engine.cpp
@@ -188,11 +188,11 @@ Object *Engine::get_singleton_object(const String &p_name) const {
const Map<StringName, Object *>::Element *E = singleton_ptrs.find(p_name);
ERR_FAIL_COND_V_MSG(!E, nullptr, "Failed to retrieve non-existent singleton '" + p_name + "'.");
return E->get();
-};
+}
bool Engine::has_singleton(const String &p_name) const {
return singleton_ptrs.has(p_name);
-};
+}
void Engine::get_singletons(List<Singleton> *p_singletons) {
for (List<Singleton>::Element *E = singletons.front(); E; E = E->next()) {
diff --git a/core/error_macros.h b/core/error_macros.h
index a592f752d5..46a1623115 100644
--- a/core/error_macros.h
+++ b/core/error_macros.h
@@ -103,6 +103,11 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
* running application to fail or crash.
* Always try to return processable data, so the engine can keep running well.
* Use the _MSG versions to print a meaningful message to help with debugging.
+ *
+ * The `((void)0)` no-op statement is used as a trick to force us to put a semicolon after
+ * those macros, making them look like proper statements.
+ * The if wrappers are used to ensure that the macro replacement does not trigger unexpected
+ * issues when expanded e.g. after an `if (cond) ERR_FAIL();` without braces.
*/
// Index out of bounds error macros.
@@ -361,11 +366,11 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
* Ensures `m_cond` is false.
* If `m_cond` is true, the current function returns `m_retval`.
*/
-#define ERR_FAIL_COND_V(m_cond, m_retval) \
- if (unlikely(m_cond)) { \
- _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. returned: " _STR(m_retval)); \
- return m_retval; \
- } else \
+#define ERR_FAIL_COND_V(m_cond, m_retval) \
+ if (unlikely(m_cond)) { \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Returning: " _STR(m_retval)); \
+ return m_retval; \
+ } else \
((void)0)
/**
@@ -375,11 +380,11 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
* If checking for null use ERR_FAIL_NULL_V_MSG instead.
* If checking index bounds use ERR_FAIL_INDEX_V_MSG instead.
*/
-#define ERR_FAIL_COND_V_MSG(m_cond, m_retval, m_msg) \
- if (unlikely(m_cond)) { \
- _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. returned: " _STR(m_retval), DEBUG_STR(m_msg)); \
- return m_retval; \
- } else \
+#define ERR_FAIL_COND_V_MSG(m_cond, m_retval, m_msg) \
+ if (unlikely(m_cond)) { \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Returning: " _STR(m_retval), DEBUG_STR(m_msg)); \
+ return m_retval; \
+ } else \
((void)0)
/**
@@ -472,7 +477,7 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
*/
#define ERR_FAIL() \
if (1) { \
- _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/Function Failed."); \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed."); \
return; \
} else \
((void)0)
@@ -485,7 +490,7 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
*/
#define ERR_FAIL_MSG(m_msg) \
if (1) { \
- _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/Function Failed.", DEBUG_STR(m_msg)); \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed.", DEBUG_STR(m_msg)); \
return; \
} else \
((void)0)
@@ -499,7 +504,7 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
*/
#define ERR_FAIL_V(m_retval) \
if (1) { \
- _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/Function Failed, returning: " _STR(m_retval)); \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed. Returning: " _STR(m_retval)); \
return m_retval; \
} else \
((void)0)
@@ -512,7 +517,7 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
*/
#define ERR_FAIL_V_MSG(m_retval, m_msg) \
if (1) { \
- _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/Function Failed, returning: " _STR(m_retval), DEBUG_STR(m_msg)); \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed. Returning: " _STR(m_retval), DEBUG_STR(m_msg)); \
return m_retval; \
} else \
((void)0)
@@ -601,7 +606,7 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
*/
#define CRASH_NOW() \
if (1) { \
- _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Method/Function Failed."); \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Method/function failed."); \
GENERATE_TRAP(); \
} else \
((void)0)
@@ -613,7 +618,7 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
*/
#define CRASH_NOW_MSG(m_msg) \
if (1) { \
- _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Method/Function Failed.", DEBUG_STR(m_msg)); \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Method/function failed.", DEBUG_STR(m_msg)); \
GENERATE_TRAP(); \
} else \
((void)0)
diff --git a/core/image.cpp b/core/image.cpp
index 29be2ff5eb..4ab71128cd 100644
--- a/core/image.cpp
+++ b/core/image.cpp
@@ -37,8 +37,6 @@
#include "core/os/copymem.h"
#include "core/print_string.h"
-#include "thirdparty/misc/hq2x.h"
-
#include <stdio.h>
const char *Image::format_names[Image::FORMAT_MAX] = {
@@ -1401,7 +1399,7 @@ int Image::_get_dst_image_size(int p_width, int p_height, Format p_format, int &
h = MAX(minh, h >> 1);
}
mm++;
- };
+ }
r_mipmaps = mm;
return size;
@@ -1445,47 +1443,6 @@ static void _generate_po2_mipmap(const Component *p_src, Component *p_dst, uint3
}
}
-void Image::expand_x2_hq2x() {
- ERR_FAIL_COND(!_can_modify(format));
-
- bool used_mipmaps = has_mipmaps();
- if (used_mipmaps) {
- clear_mipmaps();
- }
-
- Format current = format;
-
- if (current != FORMAT_RGBA8) {
- convert(FORMAT_RGBA8);
- }
-
- Vector<uint8_t> dest;
- dest.resize(width * 2 * height * 2 * 4);
-
- {
- const uint8_t *r = data.ptr();
- uint8_t *w = dest.ptrw();
-
- ERR_FAIL_COND(!r);
-
- hq2x_resize((const uint32_t *)r, width, height, (uint32_t *)w);
- }
-
- width *= 2;
- height *= 2;
- data = dest;
-
- if (current != FORMAT_RGBA8) {
- convert(current);
- }
-
- // FIXME: This is likely meant to use "used_mipmaps" as defined above, but if we do,
- // we end up with a regression: GH-22747
- if (mipmaps) {
- generate_mipmaps();
- }
-}
-
void Image::shrink_x2() {
ERR_FAIL_COND(data.size() == 0);
@@ -1993,7 +1950,7 @@ void Image::create(const char **p_xpm) {
HashMap<String, Color> colormap;
int colormap_size = 0;
uint32_t pixel_size = 0;
- uint8_t *w;
+ uint8_t *data_write = nullptr;
while (status != DONE) {
const char *line_ptr = p_xpm[line];
@@ -2074,7 +2031,7 @@ void Image::create(const char **p_xpm) {
case 5:
col_b |= v;
break;
- };
+ }
}
// magenta mask
@@ -2089,7 +2046,7 @@ void Image::create(const char **p_xpm) {
if (line == colormap_size) {
status = READING_PIXELS;
create(size_width, size_height, false, has_alpha ? FORMAT_RGBA8 : FORMAT_RGB8);
- w = data.ptrw();
+ data_write = data.ptrw();
pixel_size = has_alpha ? 4 : 3;
}
} break;
@@ -2107,7 +2064,7 @@ void Image::create(const char **p_xpm) {
for (uint32_t i = 0; i < pixel_size; i++) {
pixel[i] = CLAMP((*colorptr)[i] * 255, 0, 255);
}
- _put_pixelb(x, y, pixel_size, w, pixel);
+ _put_pixelb(x, y, pixel_size, data_write, pixel);
}
if (y == (size_height - 1)) {
@@ -3047,7 +3004,6 @@ void Image::_bind_methods() {
ClassDB::bind_method(D_METHOD("resize_to_po2", "square"), &Image::resize_to_po2, DEFVAL(false));
ClassDB::bind_method(D_METHOD("resize", "width", "height", "interpolation"), &Image::resize, DEFVAL(INTERPOLATE_BILINEAR));
ClassDB::bind_method(D_METHOD("shrink_x2"), &Image::shrink_x2);
- ClassDB::bind_method(D_METHOD("expand_x2_hq2x"), &Image::expand_x2_hq2x);
ClassDB::bind_method(D_METHOD("crop", "width", "height"), &Image::crop);
ClassDB::bind_method(D_METHOD("flip_x"), &Image::flip_x);
@@ -3062,6 +3018,7 @@ void Image::_bind_methods() {
ClassDB::bind_method(D_METHOD("load", "path"), &Image::load);
ClassDB::bind_method(D_METHOD("save_png", "path"), &Image::save_png);
+ ClassDB::bind_method(D_METHOD("save_png_to_buffer"), &Image::save_png_to_buffer);
ClassDB::bind_method(D_METHOD("save_exr", "path", "grayscale"), &Image::save_exr, DEFVAL(false));
ClassDB::bind_method(D_METHOD("detect_alpha"), &Image::detect_alpha);
diff --git a/core/image.h b/core/image.h
index dbdfaa917b..53c203998e 100644
--- a/core/image.h
+++ b/core/image.h
@@ -235,7 +235,6 @@ public:
void resize_to_po2(bool p_square = false);
void resize(int p_width, int p_height, Interpolation p_interpolation = INTERPOLATE_BILINEAR);
void shrink_x2();
- void expand_x2_hq2x();
bool is_size_po2() const;
/**
* Crop the image to a specific size, if larger, then the image is filled by black
diff --git a/core/input/input.cpp b/core/input/input.cpp
index dc1c207524..4d152c1ac4 100644
--- a/core/input/input.cpp
+++ b/core/input/input.cpp
@@ -339,7 +339,7 @@ float Input::get_joy_axis(int p_device, int p_axis) const {
String Input::get_joy_name(int p_idx) {
_THREAD_SAFE_METHOD_
return joy_names[p_idx].name;
-};
+}
Vector2 Input::get_joy_vibration_strength(int p_device) {
if (joy_vibration.has(p_device)) {
@@ -374,7 +374,7 @@ static String _hex_str(uint8_t p_byte) {
ret[1] = dict[p_byte & 0xf];
return ret;
-};
+}
void Input::joy_connection_changed(int p_idx, bool p_connected, String p_name, String p_guid) {
_THREAD_SAFE_METHOD_
@@ -388,8 +388,8 @@ void Input::joy_connection_changed(int p_idx, bool p_connected, String p_name, S
int uidlen = MIN(p_name.length(), 16);
for (int i = 0; i < uidlen; i++) {
uidname = uidname + _hex_str(p_name[i]);
- };
- };
+ }
+ }
js.uid = uidname;
js.connected = true;
int mapping = fallback_mapping;
@@ -397,8 +397,8 @@ void Input::joy_connection_changed(int p_idx, bool p_connected, String p_name, S
if (js.uid == map_db[i].uid) {
mapping = i;
js.name = map_db[i].name;
- };
- };
+ }
+ }
js.mapping = mapping;
} else {
js.connected = false;
@@ -409,11 +409,11 @@ void Input::joy_connection_changed(int p_idx, bool p_connected, String p_name, S
for (int i = 0; i < JOY_AXIS_MAX; i++) {
set_joy_axis(p_idx, i, 0.0f);
}
- };
+ }
joy_names[p_idx] = js;
emit_signal("joy_connection_changed", p_idx, p_connected);
-};
+}
Vector3 Input::get_gravity() const {
_THREAD_SAFE_METHOD_
@@ -918,7 +918,7 @@ void Input::joy_axis(int p_device, int p_axis, const JoyAxis &p_value) {
if (joy.mapping == -1) {
_axis_event(p_device, p_axis, val);
return;
- };
+ }
JoyEvent map = _get_mapped_axis_event(map_db[joy.mapping], p_axis, p_value);
@@ -1003,7 +1003,7 @@ void Input::joy_hat(int p_device, int p_val) {
if (joy.mapping != -1) {
_get_mapped_hat_events(map_db[joy.mapping], 0, map);
- };
+ }
int cur_val = joy_names[p_device].hat_current;
@@ -1042,7 +1042,7 @@ void Input::_axis_event(int p_device, int p_axis, float p_value) {
ievent->set_axis_value(p_value);
parse_input_event(ievent);
-};
+}
Input::JoyEvent Input::_get_mapped_button_event(const JoyDeviceMapping &mapping, int p_button) {
JoyEvent event;
@@ -1274,10 +1274,10 @@ void Input::parse_mapping(String p_mapping) {
}
mapping.bindings.push_back(binding);
- };
+ }
map_db.push_back(mapping);
-};
+}
void Input::add_joy_mapping(String p_mapping, bool p_update_existing) {
parse_mapping(p_mapping);
diff --git a/core/io/file_access_buffered_fa.h b/core/io/file_access_buffered_fa.h
index 3ea98584a4..f22e54e154 100644
--- a/core/io/file_access_buffered_fa.h
+++ b/core/io/file_access_buffered_fa.h
@@ -58,35 +58,35 @@ class FileAccessBufferedFA : public FileAccessBuffered {
f.get_buffer(cache.buffer.ptrw(), p_size);
return p_size;
- };
- };
+ }
+ }
static FileAccess *create() {
return memnew(FileAccessBufferedFA<T>());
- };
+ }
protected:
virtual void _set_access_type(AccessType p_access) {
f._set_access_type(p_access);
FileAccessBuffered::_set_access_type(p_access);
- };
+ }
public:
void flush() {
f.flush();
- };
+ }
void store_8(uint8_t p_dest) {
f.store_8(p_dest);
- };
+ }
void store_buffer(const uint8_t *p_src, int p_length) {
f.store_buffer(p_src, p_length);
- };
+ }
bool file_exists(const String &p_name) {
return f.file_exists(p_name);
- };
+ }
Error _open(const String &p_path, int p_mode_flags) {
close();
@@ -106,7 +106,7 @@ public:
cache.offset = 0;
return set_error(OK);
- };
+ }
void close() {
f.close();
@@ -119,7 +119,7 @@ public:
cache.buffer.resize(0);
cache.offset = 0;
set_error(OK);
- };
+ }
virtual uint64_t _get_modified_time(const String &p_file) {
return f._get_modified_time(p_file);
diff --git a/core/io/file_access_memory.cpp b/core/io/file_access_memory.cpp
index 3c5f846941..a65ff92a89 100644
--- a/core/io/file_access_memory.cpp
+++ b/core/io/file_access_memory.cpp
@@ -145,7 +145,7 @@ int FileAccessMemory::get_buffer(uint8_t *p_dst, int p_length) const {
if (read < p_length) {
WARN_PRINT("Reading less data than requested");
- };
+ }
copymem(p_dst, &data[pos], read);
pos += p_length;
diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp
index 00c4e76efe..37240f234a 100644
--- a/core/io/file_access_pack.cpp
+++ b/core/io/file_access_pack.cpp
@@ -38,11 +38,11 @@ Error PackedData::add_pack(const String &p_path, bool p_replace_files) {
for (int i = 0; i < sources.size(); i++) {
if (sources[i]->try_open_pack(p_path, p_replace_files)) {
return OK;
- };
- };
+ }
+ }
return ERR_FILE_UNRECOGNIZED;
-};
+}
void PackedData::add_path(const String &pkg_path, const String &path, uint64_t ofs, uint64_t size, const uint8_t *p_md5, PackSource *p_src, bool p_replace_files) {
PathMD5 pmd5(path.md5_buffer());
@@ -96,7 +96,7 @@ void PackedData::add_pack_source(PackSource *p_source) {
if (p_source != nullptr) {
sources.push_back(p_source);
}
-};
+}
PackedData *PackedData::singleton = nullptr;
@@ -192,16 +192,16 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files)
uint8_t md5[16];
f->get_buffer(md5, 16);
PackedData::get_singleton()->add_path(p_path, path, ofs, size, md5, this, p_replace_files);
- };
+ }
f->close();
memdelete(f);
return true;
-};
+}
FileAccess *PackedSourcePCK::get_file(const String &p_path, PackedData::PackedFile *p_file) {
return memnew(FileAccessPack(p_path, *p_file));
-};
+}
//////////////////////////////////////////////////////////////////
diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h
index 320a6cb216..348bc0c450 100644
--- a/core/io/file_access_pack.h
+++ b/core/io/file_access_pack.h
@@ -79,7 +79,7 @@ private:
bool operator==(const PathMD5 &p_md5) const {
return a == p_md5.a && b == p_md5.b;
- };
+ }
PathMD5() {}
diff --git a/core/io/ip.cpp b/core/io/ip.cpp
index 653959b393..24b8ec7cc1 100644
--- a/core/io/ip.cpp
+++ b/core/io/ip.cpp
@@ -54,7 +54,7 @@ struct _IP_ResolverPrivate {
QueueItem() {
clear();
- };
+ }
};
QueueItem queue[IP::RESOLVER_MAX_QUERIES];
diff --git a/core/io/ip_address.cpp b/core/io/ip_address.cpp
index 89b317bf93..c7a0ae5605 100644
--- a/core/io/ip_address.cpp
+++ b/core/io/ip_address.cpp
@@ -58,7 +58,7 @@ IP_Address::operator String() const {
}
uint16_t num = (field8[i * 2] << 8) + field8[i * 2 + 1];
ret = ret + String::num_int64(num, 16);
- };
+ }
return ret;
}
@@ -68,7 +68,7 @@ static void _parse_hex(const String &p_string, int p_start, uint8_t *p_dst) {
for (int i = p_start; i < p_start + 4; i++) {
if (i >= p_string.length()) {
break;
- };
+ }
int n = 0;
CharType c = p_string[i];
@@ -82,14 +82,14 @@ static void _parse_hex(const String &p_string, int p_start, uint8_t *p_dst) {
break;
} else {
ERR_FAIL_MSG("Invalid character in IPv6 address: " + p_string + ".");
- };
+ }
ret = ret << 4;
ret += n;
- };
+ }
p_dst[0] = ret >> 8;
p_dst[1] = ret & 0xff;
-};
+}
void IP_Address::_parse_ipv6(const String &p_string) {
static const int parts_total = 8;
@@ -105,11 +105,11 @@ void IP_Address::_parse_ipv6(const String &p_string) {
if (c == ':') {
if (i == 0) {
continue; // next must be a ":"
- };
+ }
if (!part_found) {
part_skip = true;
parts[parts_idx++] = -1;
- };
+ }
part_found = false;
} else if (c == '.') {
part_ipv4 = true;
@@ -119,33 +119,33 @@ void IP_Address::_parse_ipv6(const String &p_string) {
parts[parts_idx++] = i;
part_found = true;
++parts_count;
- };
+ }
} else {
ERR_FAIL_MSG("Invalid character in IPv6 address: " + p_string + ".");
- };
- };
+ }
+ }
int parts_extra = 0;
if (part_skip) {
parts_extra = parts_total - parts_count;
- };
+ }
int idx = 0;
for (int i = 0; i < parts_idx; i++) {
if (parts[i] == -1) {
for (int j = 0; j < parts_extra; j++) {
field16[idx++] = 0;
- };
+ }
continue;
- };
+ }
if (part_ipv4 && i == parts_idx - 1) {
_parse_ipv4(p_string, parts[i], (uint8_t *)&field16[idx]); // should be the last one
} else {
_parse_hex(p_string, parts[i], (uint8_t *)&(field16[idx++]));
- };
- };
-};
+ }
+ }
+}
void IP_Address::_parse_ipv4(const String &p_string, int p_start, uint8_t *p_ret) {
String ip;
@@ -153,20 +153,20 @@ void IP_Address::_parse_ipv4(const String &p_string, int p_start, uint8_t *p_ret
ip = p_string.substr(p_start, p_string.length() - p_start);
} else {
ip = p_string;
- };
+ }
int slices = ip.get_slice_count(".");
ERR_FAIL_COND_MSG(slices != 4, "Invalid IP address string: " + ip + ".");
for (int i = 0; i < 4; i++) {
p_ret[i] = ip.get_slicec('.', i).to_int();
}
-};
+}
void IP_Address::clear() {
memset(&field8[0], 0, sizeof(field8));
valid = false;
wildcard = false;
-};
+}
bool IP_Address::is_ipv4() const {
return (field32[0] == 0 && field32[1] == 0 && field16[4] == 0 && field16[5] == 0xffff);
@@ -224,7 +224,7 @@ _FORCE_INLINE_ static void _32_to_buf(uint8_t *p_dst, uint32_t p_n) {
p_dst[1] = (p_n >> 16) & 0xff;
p_dst[2] = (p_n >> 8) & 0xff;
p_dst[3] = (p_n >> 0) & 0xff;
-};
+}
IP_Address::IP_Address(uint32_t p_a, uint32_t p_b, uint32_t p_c, uint32_t p_d, bool is_v6) {
clear();
diff --git a/core/io/json.cpp b/core/io/json.cpp
index 03f4e65220..1c603865ad 100644
--- a/core/io/json.cpp
+++ b/core/io/json.cpp
@@ -91,7 +91,7 @@ String JSON::_print_var(const Variant &p_var, const String &p_indent, int p_cur_
}
s += end_statement + _make_indent(p_indent, p_cur_indent) + "]";
return s;
- };
+ }
case Variant::DICTIONARY: {
String s = "{";
s += end_statement;
@@ -115,7 +115,7 @@ String JSON::_print_var(const Variant &p_var, const String &p_indent, int p_cur_
s += end_statement + _make_indent(p_indent, p_cur_indent) + "}";
return s;
- };
+ }
default:
return "\"" + String(p_var).json_escape() + "\"";
}
@@ -132,7 +132,7 @@ Error JSON::_get_token(const CharType *p_str, int &index, int p_len, Token &r_to
line++;
index++;
break;
- };
+ }
case 0: {
r_token.type = TK_EOF;
return OK;
@@ -141,32 +141,32 @@ Error JSON::_get_token(const CharType *p_str, int &index, int p_len, Token &r_to
r_token.type = TK_CURLY_BRACKET_OPEN;
index++;
return OK;
- };
+ }
case '}': {
r_token.type = TK_CURLY_BRACKET_CLOSE;
index++;
return OK;
- };
+ }
case '[': {
r_token.type = TK_BRACKET_OPEN;
index++;
return OK;
- };
+ }
case ']': {
r_token.type = TK_BRACKET_CLOSE;
index++;
return OK;
- };
+ }
case ':': {
r_token.type = TK_COLON;
index++;
return OK;
- };
+ }
case ',': {
r_token.type = TK_COMMA;
index++;
return OK;
- };
+ }
case '"': {
index++;
String str;
diff --git a/core/io/marshalls.h b/core/io/marshalls.h
index c21a97ac8a..c8ed497528 100644
--- a/core/io/marshalls.h
+++ b/core/io/marshalls.h
@@ -106,7 +106,7 @@ static inline int encode_cstring(const char *p_string, uint8_t *p_data) {
}
p_string++;
len++;
- };
+ }
if (p_data) {
*p_data = 0;
diff --git a/core/io/packet_peer.cpp b/core/io/packet_peer.cpp
index 6d37d95994..dacd548a3e 100644
--- a/core/io/packet_peer.cpp
+++ b/core/io/packet_peer.cpp
@@ -147,7 +147,7 @@ void PacketPeer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_encode_buffer_max_size", "max_size"), &PacketPeer::set_encode_buffer_max_size);
ADD_PROPERTY(PropertyInfo(Variant::INT, "encode_buffer_max_size"), "set_encode_buffer_max_size", "get_encode_buffer_max_size");
-};
+}
/***************/
@@ -267,7 +267,7 @@ void PacketPeerStream::set_stream_peer(const Ref<StreamPeer> &p_peer) {
if (p_peer.ptr() != peer.ptr()) {
ring_buffer.advance_read(ring_buffer.data_left()); // reset the ring buffer
- };
+ }
peer = p_peer;
}
diff --git a/core/io/pck_packer.cpp b/core/io/pck_packer.cpp
index 06d22ce897..374b2a5e07 100644
--- a/core/io/pck_packer.cpp
+++ b/core/io/pck_packer.cpp
@@ -45,19 +45,19 @@ static uint64_t _align(uint64_t p_n, int p_alignment) {
} else {
return p_n + (p_alignment - rest);
}
-};
+}
static void _pad(FileAccess *p_file, int p_bytes) {
for (int i = 0; i < p_bytes; i++) {
p_file->store_8(0);
- };
-};
+ }
+}
void PCKPacker::_bind_methods() {
ClassDB::bind_method(D_METHOD("pck_start", "pck_name", "alignment"), &PCKPacker::pck_start, DEFVAL(0));
ClassDB::bind_method(D_METHOD("add_file", "pck_path", "source_path"), &PCKPacker::add_file);
ClassDB::bind_method(D_METHOD("flush", "verbose"), &PCKPacker::flush, DEFVAL(false));
-};
+}
Error PCKPacker::pck_start(const String &p_file, int p_alignment) {
if (file != nullptr) {
@@ -78,18 +78,18 @@ Error PCKPacker::pck_start(const String &p_file, int p_alignment) {
for (int i = 0; i < 16; i++) {
file->store_32(0); // reserved
- };
+ }
files.clear();
return OK;
-};
+}
Error PCKPacker::add_file(const String &p_file, const String &p_src) {
FileAccess *f = FileAccess::open(p_src, FileAccess::READ);
if (!f) {
return ERR_FILE_CANT_OPEN;
- };
+ }
File pf;
pf.path = p_file;
@@ -103,7 +103,7 @@ Error PCKPacker::add_file(const String &p_file, const String &p_src) {
memdelete(f);
return OK;
-};
+}
Error PCKPacker::flush(bool p_verbose) {
ERR_FAIL_COND_V_MSG(!file, ERR_INVALID_PARAMETER, "File must be opened before use.");
@@ -123,7 +123,7 @@ Error PCKPacker::flush(bool p_verbose) {
file->store_32(0);
file->store_32(0);
file->store_32(0);
- };
+ }
uint64_t ofs = file->get_position();
ofs = _align(ofs, alignment);
@@ -141,7 +141,7 @@ Error PCKPacker::flush(bool p_verbose) {
int read = src->get_buffer(buf, MIN(to_write, buf_max));
file->store_buffer(buf, read);
to_write -= read;
- };
+ }
uint64_t pos = file->get_position();
file->seek(files[i].offset_offset); // go back to store the file's offset
@@ -158,9 +158,9 @@ Error PCKPacker::flush(bool p_verbose) {
if (count % 100 == 0) {
printf("%i/%i (%.2f)\r", count, files.size(), float(count) / files.size() * 100);
fflush(stdout);
- };
- };
- };
+ }
+ }
+ }
if (p_verbose) {
printf("\n");
@@ -170,11 +170,11 @@ Error PCKPacker::flush(bool p_verbose) {
memdelete_arr(buf);
return OK;
-};
+}
PCKPacker::~PCKPacker() {
if (file != nullptr) {
memdelete(file);
- };
+ }
file = nullptr;
-};
+}
diff --git a/core/io/xml_parser.cpp b/core/io/xml_parser.cpp
index 11f82fef9d..b11267b60f 100644
--- a/core/io/xml_parser.cpp
+++ b/core/io/xml_parser.cpp
@@ -361,7 +361,7 @@ void XMLParser::_parse_current_node() {
uint64_t XMLParser::get_node_offset() const {
return node_offset;
-};
+}
Error XMLParser::seek(uint64_t p_pos) {
ERR_FAIL_COND_V(!data, ERR_FILE_EOF);
@@ -370,7 +370,7 @@ Error XMLParser::seek(uint64_t p_pos) {
P = data + p_pos;
return read();
-};
+}
void XMLParser::_bind_methods() {
ClassDB::bind_method(D_METHOD("read"), &XMLParser::read);
@@ -398,7 +398,7 @@ void XMLParser::_bind_methods() {
BIND_ENUM_CONSTANT(NODE_COMMENT);
BIND_ENUM_CONSTANT(NODE_CDATA);
BIND_ENUM_CONSTANT(NODE_UNKNOWN);
-};
+}
Error XMLParser::read() {
// if not end reached, parse the node
diff --git a/core/io/zip_io.cpp b/core/io/zip_io.cpp
index 1979e91b8c..b8e7fd34d0 100644
--- a/core/io/zip_io.cpp
+++ b/core/io/zip_io.cpp
@@ -80,7 +80,7 @@ long zipio_seek(voidpf opaque, voidpf stream, uLong offset, int origin) {
break;
default:
break;
- };
+ }
f->seek(pos);
return 0;
diff --git a/core/list.h b/core/list.h
index 86e4a45036..6052a619fb 100644
--- a/core/list.h
+++ b/core/list.h
@@ -63,70 +63,70 @@ public:
*/
_FORCE_INLINE_ const Element *next() const {
return next_ptr;
- };
+ }
/**
* Get NEXT Element iterator,
*/
_FORCE_INLINE_ Element *next() {
return next_ptr;
- };
+ }
/**
* Get PREV Element iterator, for constant lists.
*/
_FORCE_INLINE_ const Element *prev() const {
return prev_ptr;
- };
+ }
/**
* Get PREV Element iterator,
*/
_FORCE_INLINE_ Element *prev() {
return prev_ptr;
- };
+ }
/**
* * operator, for using as *iterator, when iterators are defined on stack.
*/
_FORCE_INLINE_ const T &operator*() const {
return value;
- };
+ }
/**
* operator->, for using as iterator->, when iterators are defined on stack, for constant lists.
*/
_FORCE_INLINE_ const T *operator->() const {
return &value;
- };
+ }
/**
* * operator, for using as *iterator, when iterators are defined on stack,
*/
_FORCE_INLINE_ T &operator*() {
return value;
- };
+ }
/**
* operator->, for using as iterator->, when iterators are defined on stack, for constant lists.
*/
_FORCE_INLINE_ T *operator->() {
return &value;
- };
+ }
/**
* get the value stored in this element.
*/
_FORCE_INLINE_ T &get() {
return value;
- };
+ }
/**
* get the value stored in this element, for constant lists
*/
_FORCE_INLINE_ const T &get() const {
return value;
- };
+ }
/**
* set the value stored in this element.
*/
_FORCE_INLINE_ void set(const T &p_value) {
value = (T &)p_value;
- };
+ }
void erase() {
data->erase(this);
@@ -147,7 +147,7 @@ private:
if (first == p_I) {
first = p_I->next_ptr;
- };
+ }
if (last == p_I) {
last = p_I->prev_ptr;
@@ -176,28 +176,28 @@ public:
*/
_FORCE_INLINE_ const Element *front() const {
return _data ? _data->first : nullptr;
- };
+ }
/**
* return an iterator to the beginning of the list.
*/
_FORCE_INLINE_ Element *front() {
return _data ? _data->first : nullptr;
- };
+ }
/**
* return a const iterator to the last member of the list.
*/
_FORCE_INLINE_ const Element *back() const {
return _data ? _data->last : nullptr;
- };
+ }
/**
* return an iterator to the last member of the list.
*/
_FORCE_INLINE_ Element *back() {
return _data ? _data->last : nullptr;
- };
+ }
/**
* store a new element at the end of the list
@@ -230,7 +230,7 @@ public:
_data->size_cache++;
return n;
- };
+ }
void pop_back() {
if (_data && _data->last) {
@@ -268,7 +268,7 @@ public:
_data->size_cache++;
return n;
- };
+ }
void pop_front() {
if (_data && _data->first) {
@@ -339,10 +339,10 @@ public:
return it;
}
it = it->next();
- };
+ }
return nullptr;
- };
+ }
/**
* erase an element in the list, by iterator pointing to it. Return true if it was found/erased.
@@ -360,7 +360,7 @@ public:
}
return false;
- };
+ }
/**
* erase the first element in the list, that contains value
@@ -368,7 +368,7 @@ public:
bool erase(const T &value) {
Element *I = find(value);
return erase(I);
- };
+ }
/**
* return whether the list is empty
@@ -383,8 +383,8 @@ public:
void clear() {
while (front()) {
erase(front());
- };
- };
+ }
+ }
_FORCE_INLINE_ int size() const {
return _data ? _data->size_cache : 0;
@@ -464,7 +464,7 @@ public:
if (_data->first == p_I) {
_data->first = p_I->next_ptr;
- };
+ }
if (_data->last == p_I) {
_data->last = p_I->prev_ptr;
@@ -501,7 +501,7 @@ public:
if (_data->first == p_I) {
_data->first = p_I->next_ptr;
- };
+ }
if (_data->last == p_I) {
_data->last = p_I->prev_ptr;
@@ -536,7 +536,7 @@ public:
value->prev_ptr = _data->last;
_data->last = value;
return;
- };
+ }
value->prev_ptr = where->prev_ptr;
@@ -544,10 +544,10 @@ public:
where->prev_ptr->next_ptr = value;
} else {
_data->first = value;
- };
+ }
where->prev_ptr = value;
- };
+ }
/**
* simple insertion sort
@@ -672,7 +672,7 @@ public:
ERR_FAIL_COND(_data->size_cache);
memdelete_allocator<_Data, A>(_data);
}
- };
+ }
};
#endif // LIST_H
diff --git a/core/local_vector.h b/core/local_vector.h
index c8abb32bf5..b09a28b25a 100644
--- a/core/local_vector.h
+++ b/core/local_vector.h
@@ -185,8 +185,8 @@ public:
for (i = 0; i < count; i++) {
if (p_val < data[i]) {
break;
- };
- };
+ }
+ }
insert(i, p_val);
}
diff --git a/core/make_binders.py b/core/make_binders.py
index 94bee95bfb..7d0d08cde6 100644
--- a/core/make_binders.py
+++ b/core/make_binders.py
@@ -75,7 +75,7 @@ public:
#endif
$ifret _set_returns(true); $
- };
+ }
};
template<class T $ifret ,class R$ $ifargs ,$ $arg, class P@$>
@@ -170,7 +170,7 @@ public:
$ifret _set_returns(true); $
- };
+ }
};
template<class T $ifret ,class R$ $ifargs ,$ $arg, class P@$>
@@ -266,7 +266,7 @@ public:
#endif
$ifret _set_returns(true); $
- };
+ }
};
template<class T $ifret ,class R$ $ifargs ,$ $arg, class P@$>
diff --git a/core/map.h b/core/map.h
index 4861d6a026..fd4f500556 100644
--- a/core/map.h
+++ b/core/map.h
@@ -74,19 +74,19 @@ public:
}
const K &key() const {
return _key;
- };
+ }
V &value() {
return _value;
- };
+ }
const V &value() const {
return _value;
- };
+ }
V &get() {
return _value;
- };
+ }
const V &get() const {
return _value;
- };
+ }
Element() {}
};
diff --git a/core/math/aabb.h b/core/math/aabb.h
index 9bbedfe59c..4106fbb93c 100644
--- a/core/math/aabb.h
+++ b/core/math/aabb.h
@@ -198,7 +198,7 @@ Vector3 AABB::get_endpoint(int p_point) const {
return Vector3(position.x + size.x, position.y + size.y, position.z);
case 7:
return Vector3(position.x + size.x, position.y + size.y, position.z + size.z);
- };
+ }
ERR_FAIL_V(Vector3());
}
diff --git a/core/math/camera_matrix.cpp b/core/math/camera_matrix.cpp
index 81c602d8fe..22ab83f358 100644
--- a/core/math/camera_matrix.cpp
+++ b/core/math/camera_matrix.cpp
@@ -116,18 +116,18 @@ void CameraMatrix::set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_
left = -xmax + frustumshift;
right = xmax + frustumshift;
modeltranslation = p_intraocular_dist / 2.0;
- }; break;
+ } break;
case 2: { // right eye
left = -xmax - frustumshift;
right = xmax - frustumshift;
modeltranslation = -p_intraocular_dist / 2.0;
- }; break;
+ } break;
default: { // mono, should give the same result as set_perspective(p_fovy_degrees,p_aspect,p_z_near,p_z_far,p_flip_fov)
left = -xmax;
right = xmax;
modeltranslation = 0.0;
- }; break;
- };
+ } break;
+ }
set_frustum(left, right, -ymax, ymax, p_z_near, p_z_far);
@@ -157,14 +157,14 @@ void CameraMatrix::set_for_hmd(int p_eye, real_t p_aspect, real_t p_intraocular_
switch (p_eye) {
case 1: { // left eye
set_frustum(-f2 * p_z_near, f1 * p_z_near, -f3 * p_z_near, f3 * p_z_near, p_z_near, p_z_far);
- }; break;
+ } break;
case 2: { // right eye
set_frustum(-f1 * p_z_near, f2 * p_z_near, -f3 * p_z_near, f3 * p_z_near, p_z_near, p_z_far);
- }; break;
+ } break;
default: { // mono, does not apply here!
- }; break;
- };
-};
+ } break;
+ }
+}
void CameraMatrix::set_orthogonal(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_znear, real_t p_zfar) {
set_identity();
diff --git a/core/math/expression.cpp b/core/math/expression.cpp
index 81c1e7f564..db3bf2f830 100644
--- a/core/math/expression.cpp
+++ b/core/math/expression.cpp
@@ -753,39 +753,39 @@ Error Expression::_get_token(Token &r_token) {
case 0: {
r_token.type = TK_EOF;
return OK;
- };
+ }
case '{': {
r_token.type = TK_CURLY_BRACKET_OPEN;
return OK;
- };
+ }
case '}': {
r_token.type = TK_CURLY_BRACKET_CLOSE;
return OK;
- };
+ }
case '[': {
r_token.type = TK_BRACKET_OPEN;
return OK;
- };
+ }
case ']': {
r_token.type = TK_BRACKET_CLOSE;
return OK;
- };
+ }
case '(': {
r_token.type = TK_PARENTHESIS_OPEN;
return OK;
- };
+ }
case ')': {
r_token.type = TK_PARENTHESIS_CLOSE;
return OK;
- };
+ }
case ',': {
r_token.type = TK_COMMA;
return OK;
- };
+ }
case ':': {
r_token.type = TK_COLON;
return OK;
- };
+ }
case '$': {
r_token.type = TK_INPUT;
int index = 0;
@@ -803,7 +803,7 @@ Error Expression::_get_token(Token &r_token) {
r_token.value = index;
return OK;
- };
+ }
case '=': {
cchar = GET_CHAR();
if (cchar == '=') {
@@ -814,7 +814,7 @@ Error Expression::_get_token(Token &r_token) {
return ERR_PARSE_ERROR;
}
return OK;
- };
+ }
case '!': {
if (expression[str_ofs] == '=') {
r_token.type = TK_OP_NOT_EQUAL;
@@ -823,7 +823,7 @@ Error Expression::_get_token(Token &r_token) {
r_token.type = TK_OP_NOT;
}
return OK;
- };
+ }
case '>': {
if (expression[str_ofs] == '=') {
r_token.type = TK_OP_GREATER_EQUAL;
@@ -835,7 +835,7 @@ Error Expression::_get_token(Token &r_token) {
r_token.type = TK_OP_GREATER;
}
return OK;
- };
+ }
case '<': {
if (expression[str_ofs] == '=') {
r_token.type = TK_OP_LESS_EQUAL;
@@ -847,27 +847,27 @@ Error Expression::_get_token(Token &r_token) {
r_token.type = TK_OP_LESS;
}
return OK;
- };
+ }
case '+': {
r_token.type = TK_OP_ADD;
return OK;
- };
+ }
case '-': {
r_token.type = TK_OP_SUB;
return OK;
- };
+ }
case '/': {
r_token.type = TK_OP_DIV;
return OK;
- };
+ }
case '*': {
r_token.type = TK_OP_MUL;
return OK;
- };
+ }
case '%': {
r_token.type = TK_OP_MOD;
return OK;
- };
+ }
case '&': {
if (expression[str_ofs] == '&') {
r_token.type = TK_OP_AND;
@@ -876,7 +876,7 @@ Error Expression::_get_token(Token &r_token) {
r_token.type = TK_OP_BIT_AND;
}
return OK;
- };
+ }
case '|': {
if (expression[str_ofs] == '|') {
r_token.type = TK_OP_OR;
@@ -885,17 +885,17 @@ Error Expression::_get_token(Token &r_token) {
r_token.type = TK_OP_BIT_OR;
}
return OK;
- };
+ }
case '^': {
r_token.type = TK_OP_BIT_XOR;
return OK;
- };
+ }
case '~': {
r_token.type = TK_OP_BIT_INVERT;
return OK;
- };
+ }
case '"': {
String str;
while (true) {
@@ -1666,7 +1666,7 @@ Expression::ENode *Expression::_parse_expression() {
op = Variant::OP_BIT_NEGATE;
break;
default: {
- };
+ }
}
if (op == Variant::OP_MAX) { //stop appending stuff
diff --git a/core/math/geometry.cpp b/core/math/geometry.cpp
index f6f22e1db2..a4e9169a6f 100644
--- a/core/math/geometry.cpp
+++ b/core/math/geometry.cpp
@@ -42,16 +42,15 @@
// This implementation is very inefficient, commenting unless bugs happen. See the other one.
/*
bool Geometry::is_point_in_polygon(const Vector2 &p_point, const Vector<Vector2> &p_polygon) {
-
Vector<int> indices = Geometry::triangulate_polygon(p_polygon);
for (int j = 0; j + 3 <= indices.size(); j += 3) {
int i1 = indices[j], i2 = indices[j + 1], i3 = indices[j + 2];
- if (Geometry::is_point_in_triangle(p_point, p_polygon[i1], p_polygon[i2], p_polygon[i3]))
+ if (Geometry::is_point_in_triangle(p_point, p_polygon[i1], p_polygon[i2], p_polygon[i3])) {
return true;
+ }
}
return false;
}
-
*/
void Geometry::MeshData::optimize_vertices() {
diff --git a/core/math/rect2.h b/core/math/rect2.h
index 1b86dbd49a..14393325ec 100644
--- a/core/math/rect2.h
+++ b/core/math/rect2.h
@@ -156,7 +156,7 @@ struct Rect2 {
new_rect.size = new_rect.size - new_rect.position; //make relative again
return new_rect;
- };
+ }
inline bool has_point(const Point2 &p_point) const {
if (p_point.x < position.x) {
return false;
@@ -323,7 +323,7 @@ struct Rect2i {
new_rect.size = new_rect.size - new_rect.position; //make relative again
return new_rect;
- };
+ }
bool has_point(const Point2 &p_point) const {
if (p_point.x < position.x) {
return false;
diff --git a/core/math/triangulate.cpp b/core/math/triangulate.cpp
index 7fab36ff50..12bd384c6a 100644
--- a/core/math/triangulate.cpp
+++ b/core/math/triangulate.cpp
@@ -79,7 +79,7 @@ bool Triangulate::is_inside_triangle(real_t Ax, real_t Ay,
} else {
return ((aCROSSbp >= 0.0) && (bCROSScp >= 0.0) && (cCROSSap >= 0.0));
}
-};
+}
bool Triangulate::snip(const Vector<Vector2> &p_contour, int u, int v, int w, int n, const Vector<int> &V, bool relaxed) {
int p;
diff --git a/core/math/vector2.cpp b/core/math/vector2.cpp
index 7f264ce119..233421e070 100644
--- a/core/math/vector2.cpp
+++ b/core/math/vector2.cpp
@@ -209,28 +209,29 @@ void Vector2i::operator-=(const Vector2i &p_v) {
Vector2i Vector2i::operator*(const Vector2i &p_v1) const {
return Vector2i(x * p_v1.x, y * p_v1.y);
-};
+}
Vector2i Vector2i::operator*(const int &rvalue) const {
return Vector2i(x * rvalue, y * rvalue);
-};
+}
+
void Vector2i::operator*=(const int &rvalue) {
x *= rvalue;
y *= rvalue;
-};
+}
Vector2i Vector2i::operator/(const Vector2i &p_v1) const {
return Vector2i(x / p_v1.x, y / p_v1.y);
-};
+}
Vector2i Vector2i::operator/(const int &rvalue) const {
return Vector2i(x / rvalue, y / rvalue);
-};
+}
void Vector2i::operator/=(const int &rvalue) {
x /= rvalue;
y /= rvalue;
-};
+}
Vector2i Vector2i::operator-() const {
return Vector2i(-x, -y);
diff --git a/core/math/vector2.h b/core/math/vector2.h
index e5774f1d55..8a08d3bf64 100644
--- a/core/math/vector2.h
+++ b/core/math/vector2.h
@@ -174,28 +174,29 @@ _FORCE_INLINE_ void Vector2::operator-=(const Vector2 &p_v) {
_FORCE_INLINE_ Vector2 Vector2::operator*(const Vector2 &p_v1) const {
return Vector2(x * p_v1.x, y * p_v1.y);
-};
+}
_FORCE_INLINE_ Vector2 Vector2::operator*(const real_t &rvalue) const {
return Vector2(x * rvalue, y * rvalue);
-};
+}
+
_FORCE_INLINE_ void Vector2::operator*=(const real_t &rvalue) {
x *= rvalue;
y *= rvalue;
-};
+}
_FORCE_INLINE_ Vector2 Vector2::operator/(const Vector2 &p_v1) const {
return Vector2(x / p_v1.x, y / p_v1.y);
-};
+}
_FORCE_INLINE_ Vector2 Vector2::operator/(const real_t &rvalue) const {
return Vector2(x / rvalue, y / rvalue);
-};
+}
_FORCE_INLINE_ void Vector2::operator/=(const real_t &rvalue) {
x /= rvalue;
y /= rvalue;
-};
+}
_FORCE_INLINE_ Vector2 Vector2::operator-() const {
return Vector2(-x, -y);
diff --git a/core/message_queue.cpp b/core/message_queue.cpp
index 8c71f760b2..6dcf24e7ed 100644
--- a/core/message_queue.cpp
+++ b/core/message_queue.cpp
@@ -155,6 +155,21 @@ Error MessageQueue::push_callable(const Callable &p_callable, const Variant **p_
return OK;
}
+Error MessageQueue::push_callable(const Callable &p_callable, VARIANT_ARG_DECLARE) {
+ VARIANT_ARGPTRS;
+
+ int argc = 0;
+
+ for (int i = 0; i < VARIANT_ARG_MAX; i++) {
+ if (argptr[i]->get_type() == Variant::NIL) {
+ break;
+ }
+ argc++;
+ }
+
+ return push_callable(p_callable, argptr, argc);
+}
+
void MessageQueue::statistics() {
Map<StringName, int> set_count;
Map<int, int> notify_count;
diff --git a/core/message_queue.h b/core/message_queue.h
index 8e50f1b2b7..7d13e26208 100644
--- a/core/message_queue.h
+++ b/core/message_queue.h
@@ -79,6 +79,7 @@ public:
Error push_notification(ObjectID p_id, int p_notification);
Error push_set(ObjectID p_id, const StringName &p_prop, const Variant &p_value);
Error push_callable(const Callable &p_callable, const Variant **p_args, int p_argcount, bool p_show_error = false);
+ Error push_callable(const Callable &p_callable, VARIANT_ARG_LIST);
Error push_call(Object *p_object, const StringName &p_method, VARIANT_ARG_LIST);
Error push_notification(Object *p_object, int p_notification);
diff --git a/core/oa_hash_map.h b/core/oa_hash_map.h
index e411ced044..775e17fdb5 100644
--- a/core/oa_hash_map.h
+++ b/core/oa_hash_map.h
@@ -45,17 +45,22 @@
*
* The entries are stored inplace, so huge keys or values might fill cache lines
* a lot faster.
+ *
+ * Only used keys and values are constructed. For free positions there's space
+ * in the arrays for each, but that memory is kept uninitialized.
+ *
+ * The assignment operator copy the pairs from one map to the other.
*/
template <class TKey, class TValue,
class Hasher = HashMapHasherDefault,
class Comparator = HashMapComparatorDefault<TKey>>
class OAHashMap {
private:
- TValue *values;
- TKey *keys;
- uint32_t *hashes;
+ TValue *values = nullptr;
+ TKey *keys = nullptr;
+ uint32_t *hashes = nullptr;
- uint32_t capacity;
+ uint32_t capacity = 0;
uint32_t num_elements = 0;
@@ -139,32 +144,42 @@ private:
void _resize_and_rehash(uint32_t p_new_capacity) {
uint32_t old_capacity = capacity;
- capacity = p_new_capacity;
+
+ // Capacity can't be 0.
+ capacity = MAX(1, p_new_capacity);
TKey *old_keys = keys;
TValue *old_values = values;
uint32_t *old_hashes = hashes;
num_elements = 0;
- keys = memnew_arr(TKey, capacity);
- values = memnew_arr(TValue, capacity);
- hashes = memnew_arr(uint32_t, capacity);
+ keys = static_cast<TKey *>(Memory::alloc_static(sizeof(TKey) * capacity));
+ values = static_cast<TValue *>(Memory::alloc_static(sizeof(TValue) * capacity));
+ hashes = static_cast<uint32_t *>(Memory::alloc_static(sizeof(uint32_t) * capacity));
for (uint32_t i = 0; i < capacity; i++) {
hashes[i] = 0;
}
+ if (old_capacity == 0) {
+ // Nothing to do.
+ return;
+ }
+
for (uint32_t i = 0; i < old_capacity; i++) {
if (old_hashes[i] == EMPTY_HASH) {
continue;
}
_insert_with_hash(old_hashes[i], old_keys[i], old_values[i]);
+
+ old_keys[i].~TKey();
+ old_values[i].~TValue();
}
- memdelete_arr(old_keys);
- memdelete_arr(old_values);
- memdelete_arr(old_hashes);
+ Memory::free_static(old_keys);
+ Memory::free_static(old_values);
+ Memory::free_static(old_hashes);
}
void _resize_and_rehash() {
@@ -208,8 +223,7 @@ public:
bool exists = _lookup_pos(p_key, pos);
if (exists) {
- values[pos].~TValue();
- memnew_placement(&values[pos], TValue(p_data));
+ values[pos] = p_data;
} else {
insert(p_key, p_data);
}
@@ -226,8 +240,7 @@ public:
bool exists = _lookup_pos(p_key, pos);
if (exists) {
- r_data.~TValue();
- memnew_placement(&r_data, TValue(values[pos]));
+ r_data = values[pos];
return true;
}
@@ -294,7 +307,7 @@ public:
bool valid;
const TKey *key;
- const TValue *value;
+ TValue *value;
private:
uint32_t pos;
@@ -337,25 +350,49 @@ public:
return it;
}
- OAHashMap(const OAHashMap &) = delete; // Delete the copy constructor so we don't get unexpected copies and dangling pointers.
- OAHashMap &operator=(const OAHashMap &) = delete; // Same for assignment operator.
+ OAHashMap(const OAHashMap &p_other) {
+ (*this) = p_other;
+ }
+
+ OAHashMap &operator=(const OAHashMap &p_other) {
+ if (capacity != 0) {
+ clear();
+ }
+
+ _resize_and_rehash(p_other.capacity);
+
+ for (Iterator it = p_other.iter(); it.valid; it = p_other.next_iter(it)) {
+ set(*it.key, *it.value);
+ }
+ return *this;
+ }
OAHashMap(uint32_t p_initial_capacity = 64) {
- capacity = p_initial_capacity;
+ // Capacity can't be 0.
+ capacity = MAX(1, p_initial_capacity);
- keys = memnew_arr(TKey, p_initial_capacity);
- values = memnew_arr(TValue, p_initial_capacity);
- hashes = memnew_arr(uint32_t, p_initial_capacity);
+ keys = static_cast<TKey *>(Memory::alloc_static(sizeof(TKey) * capacity));
+ values = static_cast<TValue *>(Memory::alloc_static(sizeof(TValue) * capacity));
+ hashes = static_cast<uint32_t *>(Memory::alloc_static(sizeof(uint32_t) * capacity));
- for (uint32_t i = 0; i < p_initial_capacity; i++) {
+ for (uint32_t i = 0; i < capacity; i++) {
hashes[i] = EMPTY_HASH;
}
}
~OAHashMap() {
- memdelete_arr(keys);
- memdelete_arr(values);
- memdelete_arr(hashes);
+ for (uint32_t i = 0; i < capacity; i++) {
+ if (hashes[i] == EMPTY_HASH) {
+ continue;
+ }
+
+ values[i].~TValue();
+ keys[i].~TKey();
+ }
+
+ Memory::free_static(keys);
+ Memory::free_static(values);
+ Memory::free_static(hashes);
}
};
diff --git a/core/object.cpp b/core/object.cpp
index 0a4e8a5890..f3c5a13809 100644
--- a/core/object.cpp
+++ b/core/object.cpp
@@ -1000,7 +1000,7 @@ void Object::set_meta(const String &p_name, const Variant &p_value) {
if (p_value.get_type() == Variant::NIL) {
metadata.erase(p_name);
return;
- };
+ }
metadata[p_name] = p_value;
}
diff --git a/core/ordered_hash_map.h b/core/ordered_hash_map.h
index 1f1be71741..e6a6340a2f 100644
--- a/core/ordered_hash_map.h
+++ b/core/ordered_hash_map.h
@@ -106,27 +106,27 @@ public:
const K &key() const {
CRASH_COND(!list_element);
return *(list_element->get().first);
- };
+ }
V &value() {
CRASH_COND(!list_element);
return list_element->get().second;
- };
+ }
const V &value() const {
CRASH_COND(!list_element);
return list_element->get().second;
- };
+ }
V &get() {
CRASH_COND(!list_element);
return list_element->get().second;
- };
+ }
const V &get() const {
CRASH_COND(!list_element);
return list_element->get().second;
- };
+ }
};
class ConstElement {
@@ -172,17 +172,17 @@ public:
const K &key() const {
CRASH_COND(!list_element);
return *(list_element->get().first);
- };
+ }
const V &value() const {
CRASH_COND(!list_element);
return list_element->get().second;
- };
+ }
const V &get() const {
CRASH_COND(!list_element);
return list_element->get().second;
- };
+ }
};
ConstElement find(const K &p_key) const {
diff --git a/core/os/dir_access.cpp b/core/os/dir_access.cpp
index 9f2672e038..5e1cb8ea29 100644
--- a/core/os/dir_access.cpp
+++ b/core/os/dir_access.cpp
@@ -131,7 +131,7 @@ Error DirAccess::erase_contents_recursive() {
Error DirAccess::make_dir_recursive(String p_dir) {
if (p_dir.length() < 1) {
return OK;
- };
+ }
String full_dir;
@@ -185,7 +185,7 @@ String DirAccess::fix_path(String p_path) const {
String resource_path = ProjectSettings::get_singleton()->get_resource_path();
if (resource_path != "") {
return p_path.replace_first("res:/", resource_path);
- };
+ }
return p_path.replace_first("res://", "");
}
}
@@ -196,7 +196,7 @@ String DirAccess::fix_path(String p_path) const {
String data_dir = OS::get_singleton()->get_user_data_dir();
if (data_dir != "") {
return p_path.replace_first("user:/", data_dir);
- };
+ }
return p_path.replace_first("user://", "");
}
@@ -249,7 +249,7 @@ DirAccess *DirAccess::create(AccessType p_access) {
}
return da;
-};
+}
String DirAccess::get_full_path(const String &p_path, AccessType p_access) {
DirAccess *d = DirAccess::create(p_access);
diff --git a/core/os/file_access.cpp b/core/os/file_access.cpp
index f9ba8ff2d2..20b3435911 100644
--- a/core/os/file_access.cpp
+++ b/core/os/file_access.cpp
@@ -65,7 +65,7 @@ bool FileAccess::exists(const String &p_name) {
void FileAccess::_set_access_type(AccessType p_access) {
_access_type = p_access;
-};
+}
FileAccess *FileAccess::create_for_path(const String &p_path) {
FileAccess *ret = nullptr;
@@ -83,7 +83,7 @@ FileAccess *FileAccess::create_for_path(const String &p_path) {
Error FileAccess::reopen(const String &p_path, int p_mode_flags) {
return _open(p_path, p_mode_flags);
-};
+}
FileAccess *FileAccess::open(const String &p_path, int p_mode_flags, Error *r_error) {
//try packed data first
@@ -115,7 +115,7 @@ FileAccess *FileAccess::open(const String &p_path, int p_mode_flags, Error *r_er
FileAccess::CreateFunc FileAccess::get_create_func(AccessType p_access) {
return create_func[p_access];
-};
+}
String FileAccess::fix_path(const String &p_path) const {
//helper used by file accesses that use a single filesystem
@@ -129,7 +129,7 @@ String FileAccess::fix_path(const String &p_path) const {
String resource_path = ProjectSettings::get_singleton()->get_resource_path();
if (resource_path != "") {
return r_path.replace("res:/", resource_path);
- };
+ }
return r_path.replace("res://", "");
}
}
@@ -140,7 +140,7 @@ String FileAccess::fix_path(const String &p_path) const {
String data_dir = OS::get_singleton()->get_user_data_dir();
if (data_dir != "") {
return r_path.replace("user:/", data_dir);
- };
+ }
return r_path.replace("user://", "");
}
@@ -215,7 +215,7 @@ float FileAccess::get_float() const {
MarshallFloat m;
m.i = get_32();
return m.f;
-};
+}
real_t FileAccess::get_real() const {
if (real_is_double) {
@@ -229,7 +229,7 @@ double FileAccess::get_double() const {
MarshallDouble m;
m.l = get_64();
return m.d;
-};
+}
String FileAccess::get_token() const {
CharString token;
@@ -447,13 +447,13 @@ void FileAccess::store_float(float p_dest) {
MarshallFloat m;
m.f = p_dest;
store_32(m.i);
-};
+}
void FileAccess::store_double(double p_dest) {
MarshallDouble m;
m.d = p_dest;
store_64(m.l);
-};
+}
uint64_t FileAccess::get_modified_time(const String &p_file) {
if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && PackedData::get_singleton()->has_path(p_file)) {
@@ -503,7 +503,7 @@ void FileAccess::store_pascal_string(const String &p_string) {
CharString cs = p_string.utf8();
store_32(cs.length());
store_buffer((uint8_t *)&cs[0], cs.length());
-};
+}
String FileAccess::get_pascal_string() {
uint32_t sl = get_32();
@@ -516,7 +516,7 @@ String FileAccess::get_pascal_string() {
ret.parse_utf8(cs.ptr());
return ret;
-};
+}
void FileAccess::store_line(const String &p_line) {
store_string(p_line);
diff --git a/core/os/os.cpp b/core/os/os.cpp
index da9dabd401..c29930e485 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -85,7 +85,8 @@ uint64_t OS::get_splash_tick_msec() const {
uint64_t OS::get_unix_time() const {
return 0;
-};
+}
+
uint64_t OS::get_system_time_secs() const {
return 0;
}
@@ -94,10 +95,9 @@ uint64_t OS::get_system_time_msecs() const {
return 0;
}
-void OS::debug_break(){
-
+void OS::debug_break() {
// something
-};
+}
void OS::_set_logger(CompositeLogger *p_logger) {
if (_logger) {
@@ -127,7 +127,7 @@ void OS::print(const char *p_format, ...) {
_logger->logv(p_format, argp, false);
va_end(argp);
-};
+}
void OS::printerr(const char *p_format, ...) {
va_list argp;
@@ -136,7 +136,7 @@ void OS::printerr(const char *p_format, ...) {
_logger->logv(p_format, argp, true);
va_end(argp);
-};
+}
void OS::set_low_processor_usage_mode(bool p_enabled) {
low_processor_usage_mode = p_enabled;
@@ -160,7 +160,7 @@ String OS::get_executable_path() const {
int OS::get_process_id() const {
return -1;
-};
+}
void OS::vibrate_handheld(int p_duration_ms) {
WARN_PRINT("vibrate_handheld() only works with Android and iOS");
@@ -282,12 +282,12 @@ String OS::get_cache_path() const {
// Path to macOS .app bundle resources
String OS::get_bundle_resource_dir() const {
return ".";
-};
+}
// OS specific path for user://
String OS::get_user_data_dir() const {
return ".";
-};
+}
// Absolute path to res://
String OS::get_resource_dir() const {
@@ -301,7 +301,7 @@ String OS::get_system_dir(SystemDir p_dir) const {
Error OS::shell_open(String p_uri) {
return ERR_UNAVAILABLE;
-};
+}
// implement these with the canvas?
@@ -346,7 +346,7 @@ String OS::get_model_name() const {
void OS::set_cmdline(const char *p_execpath, const List<String> &p_args) {
_execpath = p_execpath;
_cmdline = p_args;
-};
+}
String OS::get_unique_id() const {
ERR_FAIL_V("");
diff --git a/core/os/os.h b/core/os/os.h
index 9296e17bb2..9ca034a01c 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -58,7 +58,6 @@ class OS {
bool _allow_layered = false;
bool _use_vsync;
bool _vsync_via_compositor;
- bool _disable_wintab;
char *last_error;
@@ -148,7 +147,11 @@ public:
bool is_layered_allowed() const { return _allow_layered; }
bool is_hidpi_allowed() const { return _allow_hidpi; }
- bool is_wintab_disabled() const { return _disable_wintab; }
+
+ virtual int get_tablet_driver_count() const { return 0; };
+ virtual String get_tablet_driver_name(int p_driver) const { return ""; };
+ virtual String get_current_tablet_driver() const { return ""; };
+ virtual void set_current_tablet_driver(const String &p_driver){};
void ensure_user_data_dir();
diff --git a/core/os/thread.cpp b/core/os/thread.cpp
index 70f960ed2a..fc0ce3c9b4 100644
--- a/core/os/thread.cpp
+++ b/core/os/thread.cpp
@@ -63,4 +63,4 @@ Error Thread::set_name(const String &p_name) {
}
return ERR_UNAVAILABLE;
-};
+}
diff --git a/core/os/thread_dummy.cpp b/core/os/thread_dummy.cpp
index 9dcddcae11..2672cd7ad9 100644
--- a/core/os/thread_dummy.cpp
+++ b/core/os/thread_dummy.cpp
@@ -34,16 +34,16 @@
Thread *ThreadDummy::create(ThreadCreateCallback p_callback, void *p_user, const Thread::Settings &p_settings) {
return memnew(ThreadDummy);
-};
+}
void ThreadDummy::make_default() {
Thread::create_func = &ThreadDummy::create;
-};
+}
RWLock *RWLockDummy::create() {
return memnew(RWLockDummy);
-};
+}
void RWLockDummy::make_default() {
RWLock::create_func = &RWLockDummy::create;
-};
+}
diff --git a/core/packed_data_container.cpp b/core/packed_data_container.cpp
index b5aefd6f2c..e335ec0daa 100644
--- a/core/packed_data_container.cpp
+++ b/core/packed_data_container.cpp
@@ -44,7 +44,7 @@ Variant PackedDataContainer::getvar(const Variant &p_key, bool *r_valid) const {
int PackedDataContainer::size() const {
return _size(0);
-};
+}
Variant PackedDataContainer::_iter_init_ofs(const Array &p_iter, uint32_t p_offset) {
Array ref = p_iter;
@@ -124,7 +124,7 @@ uint32_t PackedDataContainer::_type_at_ofs(uint32_t p_ofs) const {
uint32_t type = decode_uint32(r);
return type;
-};
+}
int PackedDataContainer::_size(uint32_t p_ofs) const {
const uint8_t *rd = data.ptr();
@@ -139,10 +139,10 @@ int PackedDataContainer::_size(uint32_t p_ofs) const {
} else if (type == TYPE_DICT) {
uint32_t len = decode_uint32(r + 4);
return len;
- };
+ }
return -1;
-};
+}
Variant PackedDataContainer::_key_at_ofs(uint32_t p_ofs, const Variant &p_key, bool &err) const {
const uint8_t *rd = data.ptr();
@@ -368,7 +368,7 @@ Variant PackedDataContainerRef::_iter_get(const Variant &p_iter) {
bool PackedDataContainerRef::_is_dictionary() const {
return from->_type_at_ofs(offset) == PackedDataContainer::TYPE_DICT;
-};
+}
void PackedDataContainerRef::_bind_methods() {
ClassDB::bind_method(D_METHOD("size"), &PackedDataContainerRef::size);
@@ -389,4 +389,4 @@ Variant PackedDataContainerRef::getvar(const Variant &p_key, bool *r_valid) cons
int PackedDataContainerRef::size() const {
return from->_size(offset);
-};
+}
diff --git a/core/pool_allocator.cpp b/core/pool_allocator.cpp
index 1dd215a787..b222c20a00 100644
--- a/core/pool_allocator.cpp
+++ b/core/pool_allocator.cpp
@@ -341,7 +341,7 @@ Error PoolAllocator::resize(ID p_mem, int p_new_size) {
if (uint32_t(_free + aligned(e->len)) < alloc_size) {
mt_unlock();
ERR_FAIL_V(ERR_OUT_OF_MEMORY);
- };
+ }
EntryIndicesPos entry_indices_pos;
@@ -358,7 +358,7 @@ Error PoolAllocator::resize(ID p_mem, int p_new_size) {
next_pos = pool_size; // - static_area_size;
} else {
next_pos = entry_array[entry_indices[entry_indices_pos + 1]].pos;
- };
+ }
if ((next_pos - e->pos) > alloc_size) {
free_mem += aligned(e->len);
@@ -564,8 +564,8 @@ PoolAllocator::PoolAllocator(void *p_mem, int p_size, int p_align, bool p_needs_
mem8 += p_align - (ofs % p_align);
p_size -= dif;
p_mem = (void *)mem8;
- };
- };
+ }
+ }
create_pool(p_mem, p_size, p_max_entries);
needs_locking = p_needs_locking;
diff --git a/core/project_settings.cpp b/core/project_settings.cpp
index cedc7f731f..83d94ad607 100644
--- a/core/project_settings.cpp
+++ b/core/project_settings.cpp
@@ -51,7 +51,7 @@ ProjectSettings *ProjectSettings::get_singleton() {
String ProjectSettings::get_resource_path() const {
return resource_path;
-};
+}
String ProjectSettings::localize_path(const String &p_path) const {
if (resource_path == "") {
@@ -87,7 +87,7 @@ String ProjectSettings::localize_path(const String &p_path) const {
if (!cwd.begins_with(res_path)) {
return p_path;
- };
+ }
return cwd.replace_first(res_path, "res://");
} else {
@@ -96,20 +96,20 @@ String ProjectSettings::localize_path(const String &p_path) const {
int sep = path.find_last("/");
if (sep == -1) {
return "res://" + path;
- };
+ }
String parent = path.substr(0, sep);
String plocal = localize_path(parent);
if (plocal == "") {
return "";
- };
+ }
// Only strip the starting '/' from 'path' if its parent ('plocal') ends with '/'
if (plocal[plocal.length() - 1] == '/') {
sep += 1;
}
return plocal + path.substr(sep, path.size() - sep);
- };
+ }
}
void ProjectSettings::set_initial_value(const String &p_name, const Variant &p_value) {
@@ -126,13 +126,13 @@ String ProjectSettings::globalize_path(const String &p_path) const {
if (p_path.begins_with("res://")) {
if (resource_path != "") {
return p_path.replace("res:/", resource_path);
- };
+ }
return p_path.replace("res://", "");
} else if (p_path.begins_with("user://")) {
String data_dir = OS::get_singleton()->get_user_data_dir();
if (data_dir != "") {
return p_path.replace("user:/", data_dir);
- };
+ }
return p_path.replace("user://", "");
}
@@ -759,7 +759,7 @@ Error ProjectSettings::_save_settings_text(const String &p_file, const Map<Strin
Error ProjectSettings::_save_custom_bnd(const String &p_file) { // add other params as dictionary and array?
return save_custom(p_file);
-};
+}
Error ProjectSettings::save_custom(const String &p_path, const CustomMap &p_custom, const Vector<String> &p_custom_features, bool p_merge_with_current) {
ERR_FAIL_COND_V_MSG(p_path == "", ERR_INVALID_PARAMETER, "Project settings save path cannot be empty.");
diff --git a/core/ring_buffer.h b/core/ring_buffer.h
index 2fd622b86f..6b71d12cf3 100644
--- a/core/ring_buffer.h
+++ b/core/ring_buffer.h
@@ -45,13 +45,13 @@ class RingBuffer {
p_var += p_size;
p_var = p_var & size_mask;
return ret;
- };
+ }
public:
T read() {
ERR_FAIL_COND_V(space_left() < 1, T());
return data.ptr()[inc(read_pos, 1)];
- };
+ }
int read(T *p_buf, int p_size, bool p_advance = true) {
int left = data_left();
@@ -66,15 +66,15 @@ public:
const T *read = data.ptr();
for (int i = 0; i < total; i++) {
p_buf[dst++] = read[pos + i];
- };
+ }
to_read -= total;
pos = 0;
- };
+ }
if (p_advance) {
inc(read_pos, p_size);
- };
+ }
return p_size;
- };
+ }
int copy(T *p_buf, int p_offset, int p_size) const {
int left = data_left();
@@ -95,12 +95,12 @@ public:
int total = end - pos;
for (int i = 0; i < total; i++) {
p_buf[dst++] = data[pos + i];
- };
+ }
to_read -= total;
pos = 0;
- };
+ }
return p_size;
- };
+ }
int find(const T &t, int p_offset, int p_max_size) const {
int left = data_left();
@@ -122,7 +122,7 @@ public:
if (data[pos + i] == t) {
return i + (p_max_size - to_read);
}
- };
+ }
to_read -= total;
pos = 0;
}
@@ -133,7 +133,7 @@ public:
p_n = MIN(p_n, data_left());
inc(read_pos, p_n);
return p_n;
- };
+ }
inline int decrease_write(int p_n) {
p_n = MIN(p_n, data_left());
@@ -145,7 +145,7 @@ public:
ERR_FAIL_COND_V(space_left() < 1, FAILED);
data.write[inc(write_pos, 1)] = p_v;
return OK;
- };
+ }
int write(const T *p_buf, int p_size) {
int left = space_left();
@@ -161,32 +161,32 @@ public:
for (int i = 0; i < total; i++) {
data.write[pos + i] = p_buf[src++];
- };
+ }
to_write -= total;
pos = 0;
- };
+ }
inc(write_pos, p_size);
return p_size;
- };
+ }
inline int space_left() const {
int left = read_pos - write_pos;
if (left < 0) {
return size() + left - 1;
- };
+ }
if (left == 0) {
return size() - 1;
- };
+ }
return left - 1;
- };
+ }
inline int data_left() const {
return size() - space_left() - 1;
- };
+ }
inline int size() const {
return data.size();
- };
+ }
inline void clear() {
read_pos = 0;
@@ -201,19 +201,19 @@ public:
if (old_size < new_size && read_pos > write_pos) {
for (int i = 0; i < write_pos; i++) {
data.write[(old_size + i) & mask] = data[i];
- };
+ }
write_pos = (old_size + write_pos) & mask;
} else {
read_pos = read_pos & mask;
write_pos = write_pos & mask;
- };
+ }
size_mask = mask;
- };
+ }
RingBuffer<T>(int p_power = 0) {
resize(p_power);
- };
+ }
~RingBuffer<T>() {}
};
diff --git a/core/safe_refcount.cpp b/core/safe_refcount.cpp
index 22b9ff9741..d5ee778ef7 100644
--- a/core/safe_refcount.cpp
+++ b/core/safe_refcount.cpp
@@ -42,24 +42,27 @@
/* taken from boost */ \
while (true) { \
m_cpp_type tmp = static_cast<m_cpp_type const volatile &>(*(m_pw)); \
- if (tmp == 0) \
+ if (tmp == 0) { \
return 0; /* if zero, can't add to it anymore */ \
- if (m_win_cmpxchg((m_win_type volatile *)(m_pw), tmp + 1, tmp) == tmp) \
+ } \
+ if (m_win_cmpxchg((m_win_type volatile *)(m_pw), tmp + 1, tmp) == tmp) { \
return tmp + 1; \
+ } \
}
#define ATOMIC_EXCHANGE_IF_GREATER_BODY(m_pw, m_val, m_win_type, m_win_cmpxchg, m_cpp_type) \
while (true) { \
m_cpp_type tmp = static_cast<m_cpp_type const volatile &>(*(m_pw)); \
- if (tmp >= m_val) \
+ if (tmp >= m_val) { \
return tmp; /* already greater, or equal */ \
- if (m_win_cmpxchg((m_win_type volatile *)(m_pw), m_val, tmp) == tmp) \
+ } \
+ if (m_win_cmpxchg((m_win_type volatile *)(m_pw), m_val, tmp) == tmp) { \
return m_val; \
+ } \
}
-_ALWAYS_INLINE_ uint32_t _atomic_conditional_increment_impl(volatile uint32_t *pw){
-
- ATOMIC_CONDITIONAL_INCREMENT_BODY(pw, LONG, InterlockedCompareExchange, uint32_t)
+_ALWAYS_INLINE_ uint32_t _atomic_conditional_increment_impl(volatile uint32_t *pw) {
+ ATOMIC_CONDITIONAL_INCREMENT_BODY(pw, LONG, InterlockedCompareExchange, uint32_t);
}
_ALWAYS_INLINE_ uint32_t _atomic_decrement_impl(volatile uint32_t *pw) {
@@ -78,14 +81,12 @@ _ALWAYS_INLINE_ uint32_t _atomic_add_impl(volatile uint32_t *pw, volatile uint32
return InterlockedAdd((LONG volatile *)pw, val);
}
-_ALWAYS_INLINE_ uint32_t _atomic_exchange_if_greater_impl(volatile uint32_t *pw, volatile uint32_t val){
-
- ATOMIC_EXCHANGE_IF_GREATER_BODY(pw, val, LONG, InterlockedCompareExchange, uint32_t)
+_ALWAYS_INLINE_ uint32_t _atomic_exchange_if_greater_impl(volatile uint32_t *pw, volatile uint32_t val) {
+ ATOMIC_EXCHANGE_IF_GREATER_BODY(pw, val, LONG, InterlockedCompareExchange, uint32_t);
}
-_ALWAYS_INLINE_ uint64_t _atomic_conditional_increment_impl(volatile uint64_t *pw){
-
- ATOMIC_CONDITIONAL_INCREMENT_BODY(pw, LONGLONG, InterlockedCompareExchange64, uint64_t)
+_ALWAYS_INLINE_ uint64_t _atomic_conditional_increment_impl(volatile uint64_t *pw) {
+ ATOMIC_CONDITIONAL_INCREMENT_BODY(pw, LONGLONG, InterlockedCompareExchange64, uint64_t);
}
_ALWAYS_INLINE_ uint64_t _atomic_decrement_impl(volatile uint64_t *pw) {
@@ -104,9 +105,8 @@ _ALWAYS_INLINE_ uint64_t _atomic_add_impl(volatile uint64_t *pw, volatile uint64
return InterlockedAdd64((LONGLONG volatile *)pw, val);
}
-_ALWAYS_INLINE_ uint64_t _atomic_exchange_if_greater_impl(volatile uint64_t *pw, volatile uint64_t val){
-
- ATOMIC_EXCHANGE_IF_GREATER_BODY(pw, val, LONGLONG, InterlockedCompareExchange64, uint64_t)
+_ALWAYS_INLINE_ uint64_t _atomic_exchange_if_greater_impl(volatile uint64_t *pw, volatile uint64_t val) {
+ ATOMIC_EXCHANGE_IF_GREATER_BODY(pw, val, LONGLONG, InterlockedCompareExchange64, uint64_t);
}
// The actual advertised functions; they'll call the right implementation
diff --git a/core/translation.cpp b/core/translation.cpp
index f3c1489ce4..4f835bd7b4 100644
--- a/core/translation.cpp
+++ b/core/translation.cpp
@@ -873,7 +873,7 @@ void Translation::get_message_list(List<StringName> *r_messages) const {
int Translation::get_message_count() const {
return translation_map.size();
-};
+}
void Translation::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_locale", "locale"), &Translation::set_locale);
@@ -1022,7 +1022,7 @@ void TranslationServer::remove_translation(const Ref<Translation> &p_translation
void TranslationServer::clear() {
translations.clear();
-};
+}
StringName TranslationServer::translate(const StringName &p_message) const {
// Match given message against the translation catalog for the project locale.
diff --git a/core/ustring.cpp b/core/ustring.cpp
index ed096bd475..7dbaed9fbe 100644
--- a/core/ustring.cpp
+++ b/core/ustring.cpp
@@ -247,15 +247,6 @@ String String::operator+(const String &p_str) const {
return res;
}
-/*
-String String::operator+(CharType p_chr) const {
-
- String res=*this;
- res+=p_chr;
- return res;
-}
-
-*/
String &String::operator+=(const String &p_str) {
if (empty()) {
*this = p_str;
@@ -1371,7 +1362,7 @@ String String::utf8(const char *p_utf8, int p_len) {
ret.parse_utf8(p_utf8, p_len);
return ret;
-};
+}
bool String::parse_utf8(const char *p_utf8, int p_len) {
#define _UNICERROR(m_err) print_line("Unicode parsing error: " + String(m_err) + ". Is the string valid UTF-8?");
@@ -1608,6 +1599,7 @@ String::String(CharType p_char) {
copy_from(p_char);
}
+
*/
String::String(const char *p_str) {
@@ -1833,7 +1825,7 @@ int String::to_int(const char *p_str, int p_len) {
bool String::is_numeric() const {
if (length() == 0) {
return false;
- };
+ }
int s = 0;
if (operator[](0) == '-') {
@@ -1845,16 +1837,16 @@ bool String::is_numeric() const {
if (c == '.') {
if (dot) {
return false;
- };
+ }
dot = true;
}
if (c < '0' || c > '9') {
return false;
- };
- };
+ }
+ }
return true; // TODO: Use the parser below for this instead
-};
+}
template <class C>
static double built_in_strtod(const C *string, /* A decimal ASCII floating-point number,
@@ -2278,7 +2270,7 @@ Vector<uint8_t> String::md5_buffer() const {
ret.write[i] = hash[i];
}
return ret;
-};
+}
Vector<uint8_t> String::sha1_buffer() const {
CharString cs = utf8();
@@ -2387,7 +2379,7 @@ int String::find(const String &p_str, int p_from) const {
if (read_pos >= len) {
ERR_PRINT("read_pos>=len");
return -1;
- };
+ }
if (src[read_pos] != str[j]) {
found = false;
@@ -2439,7 +2431,7 @@ int String::find(const char *p_str, int p_from) const {
if (read_pos >= len) {
ERR_PRINT("read_pos>=len");
return -1;
- };
+ }
if (src[read_pos] != p_str[j]) {
found = false;
@@ -2495,7 +2487,7 @@ int String::findmk(const Vector<String> &p_keys, int p_from, int *r_key) const {
if (read_pos >= len) {
found = false;
break;
- };
+ }
if (src[read_pos] != cmp[j]) {
found = false;
@@ -2536,7 +2528,7 @@ int String::findn(const String &p_str, int p_from) const {
if (read_pos >= length()) {
ERR_PRINT("read_pos>=length()");
return -1;
- };
+ }
CharType src = _find_lower(srcd[read_pos]);
CharType dst = _find_lower(p_str[j]);
@@ -2586,7 +2578,7 @@ int String::rfind(const String &p_str, int p_from) const {
if (read_pos >= len) {
ERR_PRINT("read_pos>=len");
return -1;
- };
+ }
if (src[read_pos] != p_str[j]) {
found = false;
@@ -2633,7 +2625,7 @@ int String::rfindn(const String &p_str, int p_from) const {
if (read_pos >= len) {
ERR_PRINT("read_pos>=len");
return -1;
- };
+ }
CharType srcc = _find_lower(src[read_pos]);
CharType dstc = _find_lower(p_str[j]);
@@ -3691,7 +3683,7 @@ bool String::is_valid_hex_number(bool p_with_prefix) const {
}
return true;
-};
+}
bool String::is_valid_float() const {
int len = length();
@@ -3851,11 +3843,11 @@ bool String::is_valid_ip_address() const {
return false;
}
continue;
- };
+ }
if (!n.is_valid_ip_address()) {
return false;
}
- };
+ }
} else {
Vector<String> ip = split(".");
@@ -3872,7 +3864,7 @@ bool String::is_valid_ip_address() const {
return false;
}
}
- };
+ }
return true;
}
diff --git a/core/variant.cpp b/core/variant.cpp
index 62d710e493..21aaa0fe9e 100644
--- a/core/variant.cpp
+++ b/core/variant.cpp
@@ -191,7 +191,7 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) {
if (p_type_from == NIL) {
return (p_type_to == OBJECT);
- };
+ }
const Type *valid_types = nullptr;
const Type *invalid_types = nullptr;
@@ -498,7 +498,7 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type
if (p_type_from == NIL) {
return (p_type_to == OBJECT);
- };
+ }
const Type *valid_types = nullptr;
@@ -870,11 +870,6 @@ bool Variant::is_zero() const {
return *reinterpret_cast<const Plane *>(_data._mem) == Plane();
} break;
- /*
- case QUAT: {
-
-
- } break;*/
case AABB: {
return *_data._aabb == ::AABB();
} break;
@@ -1284,7 +1279,7 @@ void Variant::clear() {
COLOR,
VECTOR2,
RECT2
- */
+ */
case TRANSFORM2D: {
memdelete(_data._transform2d);
} break;
@@ -1421,26 +1416,6 @@ Variant::operator int64_t() const {
}
}
-/*
-Variant::operator long unsigned int() const {
-
- switch( type ) {
-
- case NIL: return 0;
- case BOOL: return _data._bool ? 1 : 0;
- case INT: return _data._int;
- case FLOAT: return _data._real;
- case STRING: return operator String().to_int();
- default: {
-
- return 0;
- }
- }
-
- return 0;
-};
-*/
-
Variant::operator uint64_t() const {
switch (type) {
case NIL:
@@ -1488,7 +1463,7 @@ Variant::operator signed long() const {
}
return 0;
-};
+}
Variant::operator unsigned long() const {
switch (type) {
@@ -1508,7 +1483,7 @@ Variant::operator unsigned long() const {
}
return 0;
-};
+}
#endif
Variant::operator signed short() const {
@@ -1858,7 +1833,7 @@ String Variant::stringify(List<const void *> &stack) const {
if (_get_obj().obj) {
if (!_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) {
return "[Freed Object]";
- };
+ }
return _get_obj().obj->to_string();
} else {
@@ -2075,7 +2050,7 @@ Variant::operator RID() const {
#ifdef DEBUG_ENABLED
if (EngineDebugger::is_active()) {
ERR_FAIL_COND_V_MSG(ObjectDB::get_instance(_get_obj().id) == nullptr, RID(), "Invalid pointer (object was freed).");
- };
+ }
#endif
Callable::CallError ce;
Variant ret = _get_obj().obj->call(CoreStringNames::get_singleton()->get_rid, nullptr, 0, ce);
@@ -2387,14 +2362,6 @@ Variant::Variant(bool p_bool) {
_data._bool = p_bool;
}
-/*
-Variant::Variant(long unsigned int p_long) {
-
- type=INT;
- _data._int=p_long;
-};
-*/
-
Variant::Variant(signed int p_int) {
type = INT;
_data._int = p_int;
@@ -2939,11 +2906,6 @@ uint32_t Variant::hash() const {
return hash_djb2_one_float(reinterpret_cast<const Plane *>(_data._mem)->d, hash);
} break;
- /*
- case QUAT: {
-
-
- } break;*/
case AABB: {
uint32_t hash = 5831;
for (int i = 0; i < 3; i++) {
diff --git a/core/variant.h b/core/variant.h
index b24cf968de..50b7a21eda 100644
--- a/core/variant.h
+++ b/core/variant.h
@@ -219,10 +219,10 @@ public:
bool is_ref() const;
_FORCE_INLINE_ bool is_num() const {
return type == INT || type == FLOAT;
- };
+ }
_FORCE_INLINE_ bool is_array() const {
return type >= ARRAY;
- };
+ }
bool is_shared() const;
bool is_zero() const;
bool is_one() const;
diff --git a/core/variant_call.cpp b/core/variant_call.cpp
index 82b1f29805..404468a7b4 100644
--- a/core/variant_call.cpp
+++ b/core/variant_call.cpp
@@ -1174,6 +1174,9 @@ struct _VariantCall {
List<StringName> value_ordered;
#endif
Map<StringName, Variant> variant_value;
+#ifdef DEBUG_ENABLED
+ List<StringName> variant_value_ordered;
+#endif
};
static ConstantData *constant_data;
@@ -1187,6 +1190,9 @@ struct _VariantCall {
static void add_variant_constant(int p_type, StringName p_constant_name, const Variant &p_constant_value) {
constant_data[p_type].variant_value[p_constant_name] = p_constant_value;
+#ifdef DEBUG_ENABLED
+ constant_data[p_type].variant_value_ordered.push_back(p_constant_name);
+#endif
}
};
@@ -1652,8 +1658,13 @@ void Variant::get_constants_for_type(Variant::Type p_type, List<StringName> *p_c
#endif
}
+#ifdef DEBUG_ENABLED
+ for (List<StringName>::Element *E = cd.variant_value_ordered.front(); E; E = E->next()) {
+ p_constants->push_back(E->get());
+#else
for (Map<StringName, Variant>::Element *E = cd.variant_value.front(); E; E = E->next()) {
p_constants->push_back(E->key());
+#endif
}
}
diff --git a/core/variant_op.cpp b/core/variant_op.cpp
index 8641187f97..2c79e2029e 100644
--- a/core/variant_op.cpp
+++ b/core/variant_op.cpp
@@ -189,7 +189,7 @@ bool Variant::booleanize() const {
_RETURN(p_a._data.m_type m_op p_b._data._float); \
\
_RETURN_FAIL \
- };
+ }
#define DEFAULT_OP_NUM_NULL(m_prefix, m_op_name, m_name, m_op, m_type) \
CASE_TYPE(m_prefix, m_op_name, m_name) { \
@@ -201,7 +201,7 @@ bool Variant::booleanize() const {
_RETURN(!(p_b.type m_op NIL)); \
\
_RETURN_FAIL \
- };
+ }
#ifdef DEBUG_ENABLED
#define DEFAULT_OP_NUM_DIV(m_prefix, m_op_name, m_name, m_type) \
@@ -222,7 +222,7 @@ bool Variant::booleanize() const {
} \
\
_RETURN_FAIL \
- };
+ }
#else
#define DEFAULT_OP_NUM_DIV(m_prefix, m_op_name, m_name, m_type) \
CASE_TYPE(m_prefix, m_op_name, m_name) { \
@@ -232,18 +232,18 @@ bool Variant::booleanize() const {
_RETURN(p_a._data.m_type / p_b._data._float); \
\
_RETURN_FAIL \
- };
+ }
#endif
#define DEFAULT_OP_NUM_NEG(m_prefix, m_op_name, m_name, m_type) \
CASE_TYPE(m_prefix, m_op_name, m_name) { \
_RETURN(-p_a._data.m_type); \
- };
+ }
#define DEFAULT_OP_NUM_POS(m_prefix, m_op_name, m_name, m_type) \
CASE_TYPE(m_prefix, m_op_name, m_name) { \
_RETURN(p_a._data.m_type); \
- };
+ }
#define DEFAULT_OP_NUM_VEC(m_prefix, m_op_name, m_name, m_op, m_type) \
CASE_TYPE(m_prefix, m_op_name, m_name) { \
@@ -261,7 +261,7 @@ bool Variant::booleanize() const {
_RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector3 *>(p_b._data._mem)); \
\
_RETURN_FAIL \
- };
+ }
#define DEFAULT_OP_STR_REV(m_prefix, m_op_name, m_name, m_op, m_type) \
CASE_TYPE(m_prefix, m_op_name, m_name) { \
@@ -273,7 +273,7 @@ bool Variant::booleanize() const {
_RETURN(*reinterpret_cast<const m_type *>(p_b._data._mem) m_op *reinterpret_cast<const NodePath *>(p_a._data._mem)); \
\
_RETURN_FAIL \
- };
+ }
#define DEFAULT_OP_STR(m_prefix, m_op_name, m_name, m_op, m_type) \
CASE_TYPE(m_prefix, m_op_name, m_name) { \
@@ -285,7 +285,7 @@ bool Variant::booleanize() const {
_RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const NodePath *>(p_b._data._mem)); \
\
_RETURN_FAIL \
- };
+ }
#define DEFAULT_OP_STR_NULL(m_prefix, m_op_name, m_name, m_op, m_type) \
CASE_TYPE(m_prefix, m_op_name, m_name) { \
@@ -299,7 +299,7 @@ bool Variant::booleanize() const {
_RETURN(!(p_b.type m_op NIL)); \
\
_RETURN_FAIL \
- };
+ }
#define DEFAULT_OP_STR_NULL_NP(m_prefix, m_op_name, m_name, m_op, m_type) \
CASE_TYPE(m_prefix, m_op_name, m_name) { \
@@ -311,7 +311,7 @@ bool Variant::booleanize() const {
_RETURN(!(p_b.type m_op NIL)); \
\
_RETURN_FAIL \
- };
+ }
#define DEFAULT_OP_STR_NULL_SN(m_prefix, m_op_name, m_name, m_op, m_type) \
CASE_TYPE(m_prefix, m_op_name, m_name) { \
@@ -323,7 +323,7 @@ bool Variant::booleanize() const {
_RETURN(!(p_b.type m_op NIL)); \
\
_RETURN_FAIL \
- };
+ }
#define DEFAULT_OP_LOCALMEM_REV(m_prefix, m_op_name, m_name, m_op, m_type) \
CASE_TYPE(m_prefix, m_op_name, m_name) { \
@@ -331,7 +331,7 @@ bool Variant::booleanize() const {
_RETURN(*reinterpret_cast<const m_type *>(p_b._data._mem) m_op *reinterpret_cast<const m_type *>(p_a._data._mem)); \
\
_RETURN_FAIL \
- };
+ }
#define DEFAULT_OP_LOCALMEM(m_prefix, m_op_name, m_name, m_op, m_type) \
CASE_TYPE(m_prefix, m_op_name, m_name) { \
@@ -339,7 +339,7 @@ bool Variant::booleanize() const {
_RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const m_type *>(p_b._data._mem)); \
\
_RETURN_FAIL \
- };
+ }
#define DEFAULT_OP_LOCALMEM_NULL(m_prefix, m_op_name, m_name, m_op, m_type) \
CASE_TYPE(m_prefix, m_op_name, m_name) { \
@@ -349,7 +349,7 @@ bool Variant::booleanize() const {
_RETURN(!(p_b.type m_op NIL)); \
\
_RETURN_FAIL \
- };
+ }
#define DEFAULT_OP_LOCALMEM_NEG(m_prefix, m_op_name, m_name, m_type) \
CASE_TYPE(m_prefix, m_op_name, m_name) { \
diff --git a/core/variant_parser.cpp b/core/variant_parser.cpp
index 9fe98265dd..bdcad03353 100644
--- a/core/variant_parser.cpp
+++ b/core/variant_parser.cpp
@@ -110,7 +110,7 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri
case '\n': {
line++;
break;
- };
+ }
case 0: {
r_token.type = TK_EOF;
return OK;
@@ -118,31 +118,31 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri
case '{': {
r_token.type = TK_CURLY_BRACKET_OPEN;
return OK;
- };
+ }
case '}': {
r_token.type = TK_CURLY_BRACKET_CLOSE;
return OK;
- };
+ }
case '[': {
r_token.type = TK_BRACKET_OPEN;
return OK;
- };
+ }
case ']': {
r_token.type = TK_BRACKET_CLOSE;
return OK;
- };
+ }
case '(': {
r_token.type = TK_PARENTHESIS_OPEN;
return OK;
- };
+ }
case ')': {
r_token.type = TK_PARENTHESIS_CLOSE;
return OK;
- };
+ }
case ':': {
r_token.type = TK_COLON;
return OK;
- };
+ }
case ';': {
while (true) {
CharType ch = p_stream->get_char();
@@ -156,19 +156,19 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri
}
break;
- };
+ }
case ',': {
r_token.type = TK_COMMA;
return OK;
- };
+ }
case '.': {
r_token.type = TK_PERIOD;
return OK;
- };
+ }
case '=': {
r_token.type = TK_EQUAL;
return OK;
- };
+ }
case '#': {
StringBuffer<> color_str;
color_str += '#';
@@ -189,7 +189,7 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri
r_token.value = Color::html(color_str.as_string());
r_token.type = TK_COLOR;
return OK;
- };
+ }
case '@': {
cchar = p_stream->get_char();
if (cchar != '"') {
diff --git a/core/vector.h b/core/vector.h
index 696984ac28..4c152fb084 100644
--- a/core/vector.h
+++ b/core/vector.h
@@ -113,8 +113,8 @@ public:
for (i = 0; i < _cowdata.size(); i++) {
if (p_val < operator[](i)) {
break;
- };
- };
+ }
+ }
insert(i, p_val);
}
diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml
index bf2ce321ac..03eb733e54 100644
--- a/doc/classes/@GlobalScope.xml
+++ b/doc/classes/@GlobalScope.xml
@@ -1063,10 +1063,10 @@
<constant name="JOY_XBOX_RB" value="10" enum="JoyButtonList">
Xbox game controller right bumper button maps to SDL right shoulder button.
</constant>
- <constant name="JOY_BUTTON_MAX" value="36" enum="JoyAxisList">
+ <constant name="JOY_BUTTON_MAX" value="36" enum="JoyButtonList">
The maximum number of game controller buttons.
</constant>
- <constant name="JOY_INVALID_BUTTON" value="-1" enum="JoyButtonList">
+ <constant name="JOY_INVALID_AXIS" value="-1" enum="JoyAxisList">
An invalid game controller axis.
</constant>
<constant name="JOY_AXIS_LEFT_X" value="0" enum="JoyAxisList">
diff --git a/doc/classes/Array.xml b/doc/classes/Array.xml
index 20296bbf45..7593f7dff4 100644
--- a/doc/classes/Array.xml
+++ b/doc/classes/Array.xml
@@ -20,7 +20,7 @@
var array2 = [3, "Four"]
print(array1 + array2) # ["One", 2, 3, "Four"]
[/codeblock]
- Arrays are always passed by reference.
+ [b]Note:[/b] Arrays are always passed by reference. To get a copy of an array which can be modified independently of the original array, use [method duplicate].
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/Camera3D.xml b/doc/classes/Camera3D.xml
index 6ff4875364..598b4bd685 100644
--- a/doc/classes/Camera3D.xml
+++ b/doc/classes/Camera3D.xml
@@ -176,6 +176,7 @@
If not [constant DOPPLER_TRACKING_DISABLED], this camera will simulate the [url=https://en.wikipedia.org/wiki/Doppler_effect]Doppler effect[/url] for objects changed in particular [code]_process[/code] methods. See [enum DopplerTracking] for possible values.
</member>
<member name="effects" type="CameraEffects" setter="set_effects" getter="get_effects">
+ The [CameraEffects] to use for this camera.
</member>
<member name="environment" type="Environment" setter="set_environment" getter="get_environment">
The [Environment] to use for this camera.
diff --git a/doc/classes/CanvasItem.xml b/doc/classes/CanvasItem.xml
index 38e4453cf2..b3a3722836 100644
--- a/doc/classes/CanvasItem.xml
+++ b/doc/classes/CanvasItem.xml
@@ -608,8 +608,10 @@
If [code]true[/code], the object draws on top of its parent.
</member>
<member name="texture_filter" type="int" setter="set_texture_filter" getter="get_texture_filter" enum="CanvasItem.TextureFilter" default="0">
+ The texture filtering mode to use on this [CanvasItem].
</member>
<member name="texture_repeat" type="int" setter="set_texture_repeat" getter="get_texture_repeat" enum="CanvasItem.TextureRepeat" default="0">
+ The texture repeating mode to use on this [CanvasItem].
</member>
<member name="use_parent_material" type="bool" setter="set_use_parent_material" getter="get_use_parent_material" default="false">
If [code]true[/code], the parent [CanvasItem]'s [member material] property is used as this one's material.
@@ -666,12 +668,18 @@
The texture filter blends between the nearest four pixels. Use this for most cases where you want to avoid a pixelated style.
</constant>
<constant name="TEXTURE_FILTER_NEAREST_WITH_MIPMAPS" value="3" enum="TextureFilter">
+ The texture filter reads from the nearest pixel in the nearest mipmap. This is the fastest way to read from textures with mipmaps.
</constant>
<constant name="TEXTURE_FILTER_LINEAR_WITH_MIPMAPS" value="4" enum="TextureFilter">
+ The texture filter blends between the nearest 4 pixels and between the nearest 2 mipmaps. Use this for non-pixel art textures that may be viewed at a low scale (e.g. due to [Camera2D] zoom), as mipmaps are important to smooth out pixels that are smaller than on-screen pixels.
</constant>
<constant name="TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC" value="5" enum="TextureFilter">
+ The texture filter reads from the nearest pixel, but selects a mipmap based on the angle between the surface and the camera view. This reduces artifacts on surfaces that are almost in line with the camera.
+ [b]Note:[/b] This texture filter is rarely useful in 2D projects. [constant TEXTURE_FILTER_NEAREST_WITH_MIPMAPS] is usually more appropriate.
</constant>
<constant name="TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC" value="6" enum="TextureFilter">
+ The texture filter blends between the nearest 4 pixels and selects a mipmap based on the angle between the surface and the camera view. This reduces artifacts on surfaces that are almost in line with the camera. This is the slowest of the filtering options, but results in the highest quality texturing.
+ [b]Note:[/b] This texture filter is rarely useful in 2D projects. [constant TEXTURE_FILTER_LINEAR_WITH_MIPMAPS] is usually more appropriate.
</constant>
<constant name="TEXTURE_FILTER_MAX" value="7" enum="TextureFilter">
Represents the size of the [enum TextureFilter] enum.
diff --git a/doc/classes/Dictionary.xml b/doc/classes/Dictionary.xml
index e982e00d6d..385f4b7e59 100644
--- a/doc/classes/Dictionary.xml
+++ b/doc/classes/Dictionary.xml
@@ -7,6 +7,7 @@
Dictionary type. Associative container which contains values referenced by unique keys. Dictionaries are composed of pairs of keys (which must be unique) and values. Dictionaries will preserve the insertion order when adding elements, even though this may not be reflected when printing the dictionary. In other programming languages, this data structure is sometimes referred to as an hash map or associative array.
You can define a dictionary by placing a comma-separated list of [code]key: value[/code] pairs in curly braces [code]{}[/code].
Erasing elements while iterating over them [b]is not supported[/b] and will result in undefined behavior.
+ [b]Note:[/b] Dictionaries are always passed by reference. To get a copy of a dictionary which can be modified independently of the original dictionary, use [method duplicate].
Creating a dictionary:
[codeblock]
var my_dir = {} # Creates an empty dictionary.
diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml
index 90828089f9..7fe712753c 100644
--- a/doc/classes/DisplayServer.xml
+++ b/doc/classes/DisplayServer.xml
@@ -592,6 +592,10 @@
</argument>
<argument index="2" name="max_length" type="int" default="-1">
</argument>
+ <argument index="3" name="cursor_start" type="int" default="-1">
+ </argument>
+ <argument index="4" name="cursor_end" type="int" default="-1">
+ </argument>
<description>
</description>
</method>
diff --git a/doc/classes/Image.xml b/doc/classes/Image.xml
index 99253e8840..55d2275194 100644
--- a/doc/classes/Image.xml
+++ b/doc/classes/Image.xml
@@ -190,13 +190,6 @@
<description>
</description>
</method>
- <method name="expand_x2_hq2x">
- <return type="void">
- </return>
- <description>
- Stretches the image and enlarges it by a factor of 2. No interpolation is done.
- </description>
- </method>
<method name="fill">
<return type="void">
</return>
diff --git a/doc/classes/ImageTextureLayered.xml b/doc/classes/ImageTextureLayered.xml
new file mode 100644
index 0000000000..d06b44afa9
--- /dev/null
+++ b/doc/classes/ImageTextureLayered.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="ImageTextureLayered" inherits="TextureLayered" version="4.0">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="create_from_images">
+ <return type="int" enum="Error">
+ </return>
+ <argument index="0" name="images" type="Array">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="update_layer">
+ <return type="void">
+ </return>
+ <argument index="0" name="image" type="Image">
+ </argument>
+ <argument index="1" name="layer" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ </methods>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/KinematicBody3D.xml b/doc/classes/KinematicBody3D.xml
index 830d63ed11..5477c6bab6 100644
--- a/doc/classes/KinematicBody3D.xml
+++ b/doc/classes/KinematicBody3D.xml
@@ -18,7 +18,7 @@
<argument index="0" name="axis" type="int" enum="PhysicsServer3D.BodyAxis">
</argument>
<description>
- Returns [code]true[/code] if the specified [code]axis[/code] is locked. See also [member move_lock_x], [member move_lock_y] and [member move_lock_z].
+ Returns [code]true[/code] if the specified [code]axis[/code] is locked. See also [member axis_lock_motion_x], [member axis_lock_motion_y] and [member axis_lock_motion_z].
</description>
</method>
<method name="get_floor_normal" qualifiers="const">
@@ -145,7 +145,7 @@
<argument index="1" name="lock" type="bool">
</argument>
<description>
- Locks or unlocks the specified [code]axis[/code] depending on the value of [code]lock[/code]. See also [member move_lock_x], [member move_lock_y] and [member move_lock_z].
+ Locks or unlocks the specified [code]axis[/code] depending on the value of [code]lock[/code]. See also [member axis_lock_motion_x], [member axis_lock_motion_y] and [member axis_lock_motion_z].
</description>
</method>
<method name="test_move">
@@ -163,18 +163,18 @@
</method>
</methods>
<members>
- <member name="collision/safe_margin" type="float" setter="set_safe_margin" getter="get_safe_margin" default="0.001">
- If the body is at least this close to another body, this body will consider them to be colliding.
- </member>
- <member name="move_lock_x" type="bool" setter="set_axis_lock" getter="get_axis_lock" default="false">
+ <member name="axis_lock_motion_x" type="bool" setter="set_axis_lock" getter="get_axis_lock" default="false">
Lock the body's X axis movement.
</member>
- <member name="move_lock_y" type="bool" setter="set_axis_lock" getter="get_axis_lock" default="false">
+ <member name="axis_lock_motion_y" type="bool" setter="set_axis_lock" getter="get_axis_lock" default="false">
Lock the body's Y axis movement.
</member>
- <member name="move_lock_z" type="bool" setter="set_axis_lock" getter="get_axis_lock" default="false">
+ <member name="axis_lock_motion_z" type="bool" setter="set_axis_lock" getter="get_axis_lock" default="false">
Lock the body's Z axis movement.
</member>
+ <member name="collision/safe_margin" type="float" setter="set_safe_margin" getter="get_safe_margin" default="0.001">
+ If the body is at least this close to another body, this body will consider them to be colliding.
+ </member>
</members>
<constants>
</constants>
diff --git a/doc/classes/Lightmapper.xml b/doc/classes/Lightmapper.xml
new file mode 100644
index 0000000000..e80194858a
--- /dev/null
+++ b/doc/classes/Lightmapper.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="Lightmapper" inherits="Reference" version="4.0">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ </methods>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml
index 0c0d16753a..04c8d2bf57 100644
--- a/doc/classes/Node.xml
+++ b/doc/classes/Node.xml
@@ -129,21 +129,19 @@
child_node.get_parent().remove_child(child_node)
add_child(child_node)
[/codeblock]
- If you need the child node to be added below a specific node in the list of children, use [method add_child_below_node] instead of this method.
+ If you need the child node to be added below a specific node in the list of children, use [method add_sibling] instead of this method.
[b]Note:[/b] If you want a child to be persisted to a [PackedScene], you must set [member owner] in addition to calling [method add_child]. This is typically relevant for [url=https://godot.readthedocs.io/en/latest/tutorials/misc/running_code_in_the_editor.html]tool scripts[/url] and [url=https://godot.readthedocs.io/en/latest/tutorials/plugins/editor/index.html]editor plugins[/url]. If [method add_child] is called without setting [member owner], the newly added [Node] will not be visible in the scene tree, though it will be visible in the 2D/3D view.
</description>
</method>
- <method name="add_child_below_node">
+ <method name="add_sibling">
<return type="void">
</return>
- <argument index="0" name="preceding_node" type="Node">
+ <argument index="0" name="sibling" type="Node">
</argument>
- <argument index="1" name="node" type="Node">
- </argument>
- <argument index="2" name="legible_unique_name" type="bool" default="false">
+ <argument index="1" name="legible_unique_name" type="bool" default="false">
</argument>
<description>
- Adds a child node below the [code]preceding_node[/code].
+ Adds a [code]sibling[/code] node to current's node parent, at the the same level as that node, right below it.
If [code]legible_unique_name[/code] is [code]true[/code], the child node will have an human-readable name based on the name of the node being instanced instead of its type.
Use [method add_child] instead of this method if you don't need the child node to be added below a specific node in the list of children.
</description>
diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml
index 6a70297f40..03203e2ebb 100644
--- a/doc/classes/OS.xml
+++ b/doc/classes/OS.xml
@@ -268,6 +268,24 @@
Returns the epoch time of the operating system in seconds.
</description>
</method>
+ <method name="get_tablet_driver_count" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ Returns the total number of available tablet drivers.
+ [b]Note:[/b] This method is implemented on Windows.
+ </description>
+ </method>
+ <method name="get_tablet_driver_name" qualifiers="const">
+ <return type="String">
+ </return>
+ <argument index="0" name="idx" type="int">
+ </argument>
+ <description>
+ Returns the tablet driver name for the given index.
+ [b]Note:[/b] This method is implemented on Windows.
+ </description>
+ </method>
<method name="get_ticks_msec" qualifiers="const">
<return type="int">
</return>
@@ -500,6 +518,9 @@
<member name="low_processor_usage_mode_sleep_usec" type="int" setter="set_low_processor_usage_mode_sleep_usec" getter="get_low_processor_usage_mode_sleep_usec" default="6900">
The amount of sleeping between frames when the low-processor usage mode is enabled (in microseconds). Higher values will result in lower CPU usage.
</member>
+ <member name="tablet_driver" type="String" setter="set_current_tablet_driver" getter="get_current_tablet_driver" default="&quot;&quot;">
+ The current tablet drvier in use.
+ </member>
</members>
<constants>
<constant name="VIDEO_DRIVER_GLES2" value="0" enum="VideoDriver">
diff --git a/doc/classes/Object.xml b/doc/classes/Object.xml
index 35e87d1a2a..87bcab25db 100644
--- a/doc/classes/Object.xml
+++ b/doc/classes/Object.xml
@@ -192,7 +192,7 @@
<return type="void">
</return>
<description>
- Deletes the object from memory. Any pre-existing reference to the freed object will now return [code]null[/code].
+ Deletes the object from memory. Any pre-existing reference to the freed object will become invalid, e.g. [code]is_instance_valid(object)[/code] will return [code]false[/code].
</description>
</method>
<method name="get" qualifiers="const">
diff --git a/doc/classes/PhysicalSkyMaterial.xml b/doc/classes/PhysicalSkyMaterial.xml
index 89b43158dc..2e0f9c52f2 100644
--- a/doc/classes/PhysicalSkyMaterial.xml
+++ b/doc/classes/PhysicalSkyMaterial.xml
@@ -31,6 +31,9 @@
<member name="mie_eccentricity" type="float" setter="set_mie_eccentricity" getter="get_mie_eccentricity" default="0.8">
Controls the direction of the mie scattering. A value of [code]1[/code] means that when light hits a particle it passing through straight forward. A value of [code]-1[/code] means that all light is scatter backwards.
</member>
+ <member name="night_sky" type="Texture2D" setter="set_night_sky" getter="get_night_sky">
+ [Texture2D] for the night sky. This is added to the sky, so if it is bright enough, it may be visible during the day.
+ </member>
<member name="rayleigh_coefficient" type="float" setter="set_rayleigh_coefficient" getter="get_rayleigh_coefficient" default="2.0">
Controls the strength of the rayleigh scattering. Rayleigh scattering results from light colliding with small particles. It is responsible for the blue color of the sky.
</member>
diff --git a/doc/classes/PopupMenu.xml b/doc/classes/PopupMenu.xml
index 59450b7ea2..ce55c90c68 100644
--- a/doc/classes/PopupMenu.xml
+++ b/doc/classes/PopupMenu.xml
@@ -591,7 +591,7 @@
</method>
</methods>
<members>
- <member name="allow_search" type="bool" setter="set_allow_search" getter="get_allow_search" default="false">
+ <member name="allow_search" type="bool" setter="set_allow_search" getter="get_allow_search" default="true">
If [code]true[/code], allows to navigate [PopupMenu] with letter keys.
</member>
<member name="hide_on_checkable_item_selection" type="bool" setter="set_hide_on_checkable_item_selection" getter="is_hide_on_checkable_item_selection" default="true">
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index 92f116c7ec..daf8cb1d2f 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -414,9 +414,6 @@
<member name="display/mouse_cursor/tooltip_position_offset" type="Vector2" setter="" getter="" default="Vector2( 10, 10 )">
Position offset for tooltips, relative to the mouse cursor's hotspot.
</member>
- <member name="display/window/disable_wintab_api" type="bool" setter="" getter="" default="false">
- Disables WinTab API and always use Windows Ink API for the pen input (Windows only).
- </member>
<member name="display/window/dpi/allow_hidpi" type="bool" setter="" getter="" default="false">
If [code]true[/code], allows HiDPI display on Windows and macOS. This setting has no effect on desktop Linux, as DPI-awareness fallbacks are not supported there.
</member>
@@ -453,6 +450,9 @@
<member name="display/window/size/width" type="int" setter="" getter="" default="1024">
Sets the game's main viewport width. On desktop platforms, this is the default window size. Stretch mode settings also use this as a reference when enabled.
</member>
+ <member name="display/window/tablet_driver" type="String" setter="" getter="" default="&quot;&quot;">
+ Specifies the tablet driver to use. If left empty, the default driver will be used.
+ </member>
<member name="display/window/vsync/use_vsync" type="bool" setter="" getter="" default="true">
If [code]true[/code], enables vertical synchronization. This eliminates tearing that may appear in moving scenes, at the cost of higher input latency and stuttering at lower framerates. If [code]false[/code], vertical synchronization will be disabled, however, many platforms will enforce it regardless (such as mobile platforms and HTML5).
</member>
@@ -844,30 +844,6 @@
<member name="network/limits/webrtc/max_channel_in_buffer_kb" type="int" setter="" getter="" default="64">
Maximum size (in kiB) for the [WebRTCDataChannel] input buffer.
</member>
- <member name="network/limits/websocket_client/max_in_buffer_kb" type="int" setter="" getter="" default="64">
- Maximum size (in kiB) for the [WebSocketClient] input buffer.
- </member>
- <member name="network/limits/websocket_client/max_in_packets" type="int" setter="" getter="" default="1024">
- Maximum number of concurrent input packets for [WebSocketClient].
- </member>
- <member name="network/limits/websocket_client/max_out_buffer_kb" type="int" setter="" getter="" default="64">
- Maximum size (in kiB) for the [WebSocketClient] output buffer.
- </member>
- <member name="network/limits/websocket_client/max_out_packets" type="int" setter="" getter="" default="1024">
- Maximum number of concurrent output packets for [WebSocketClient].
- </member>
- <member name="network/limits/websocket_server/max_in_buffer_kb" type="int" setter="" getter="" default="64">
- Maximum size (in kiB) for the [WebSocketServer] input buffer.
- </member>
- <member name="network/limits/websocket_server/max_in_packets" type="int" setter="" getter="" default="1024">
- Maximum number of concurrent input packets for [WebSocketServer].
- </member>
- <member name="network/limits/websocket_server/max_out_buffer_kb" type="int" setter="" getter="" default="64">
- Maximum size (in kiB) for the [WebSocketServer] output buffer.
- </member>
- <member name="network/limits/websocket_server/max_out_packets" type="int" setter="" getter="" default="1024">
- Maximum number of concurrent output packets for [WebSocketServer].
- </member>
<member name="network/remote_fs/page_read_ahead" type="int" setter="" getter="" default="4">
Amount of read ahead used by remote filesystem. Higher values decrease the effects of latency at the cost of higher bandwidth usage.
</member>
diff --git a/doc/classes/TabContainer.xml b/doc/classes/TabContainer.xml
index 22e92ae5d9..d56781105b 100644
--- a/doc/classes/TabContainer.xml
+++ b/doc/classes/TabContainer.xml
@@ -204,8 +204,8 @@
<theme_item name="font_color_fg" type="Color" default="Color( 0.94, 0.94, 0.94, 1 )">
Font color of the currently selected tab.
</theme_item>
- <theme_item name="hseparation" type="int" default="4">
- Horizontal separation between tabs.
+ <theme_item name="icon_separation" type="int" default="4">
+ Space between tab's name and its icon.
</theme_item>
<theme_item name="increment" type="Texture2D">
Icon for the right arrow button that appears when there are too many tabs to fit in the container width. When the button is disabled (i.e. the last tab is visible) it appears semi-transparent.
diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml
index e553518b39..0c6615c53b 100644
--- a/doc/classes/TextEdit.xml
+++ b/doc/classes/TextEdit.xml
@@ -299,7 +299,7 @@
</description>
</method>
<method name="search" qualifiers="const">
- <return type="PackedInt32Array">
+ <return type="Dictionary">
</return>
<argument index="0" name="key" type="String">
</argument>
@@ -311,13 +311,13 @@
</argument>
<description>
Perform a search inside the text. Search flags can be specified in the [enum SearchFlags] enum.
- Returns an empty [code]PackedInt32Array[/code] if no result was found. Otherwise, the result line and column can be accessed at indices specified in the [enum SearchResult] enum, e.g:
+ Returns an empty [code]Dictionary[/code] if no result was found. Otherwise, returns a [code]Dictionary[/code] containing [code]line[/code] and [code]column[/code] entries, e.g:
[codeblock]
var result = search(key, flags, line, column)
- if result.size() &gt; 0:
+ if !result.empty():
# Result found.
- var res_line = result[TextEdit.SEARCH_RESULT_LINE]
- var res_column = result[TextEdit.SEARCH_RESULT_COLUMN]
+ var line_number = result.line
+ var column_number = result.column
[/codeblock]
</description>
</method>
@@ -536,12 +536,6 @@
<constant name="SEARCH_BACKWARDS" value="4" enum="SearchFlags">
Search from end to beginning.
</constant>
- <constant name="SEARCH_RESULT_COLUMN" value="0" enum="SearchResult">
- Used to access the result column from [method search].
- </constant>
- <constant name="SEARCH_RESULT_LINE" value="1" enum="SearchResult">
- Used to access the result line from [method search].
- </constant>
<constant name="MENU_CUT" value="0" enum="MenuItems">
Cuts (copies and clears) the selected text.
</constant>
diff --git a/drivers/alsa/audio_driver_alsa.cpp b/drivers/alsa/audio_driver_alsa.cpp
index 414b0c28e0..90c3d3af83 100644
--- a/drivers/alsa/audio_driver_alsa.cpp
+++ b/drivers/alsa/audio_driver_alsa.cpp
@@ -38,7 +38,7 @@
#include <errno.h>
Error AudioDriverALSA::init_device() {
- mix_rate = GLOBAL_DEF("audio/mix_rate", DEFAULT_MIX_RATE);
+ mix_rate = GLOBAL_GET("audio/mix_rate");
speaker_mode = SPEAKER_MODE_STEREO;
channels = 2;
@@ -104,7 +104,7 @@ Error AudioDriverALSA::init_device() {
// In ALSA the period size seems to be the one that will determine the actual latency
// Ref: https://www.alsa-project.org/main/index.php/FramesPeriods
unsigned int periods = 2;
- int latency = GLOBAL_DEF("audio/output_latency", DEFAULT_OUTPUT_LATENCY);
+ int latency = GLOBAL_GET("audio/output_latency");
buffer_frames = closest_power_of_2(latency * mix_rate / 1000);
buffer_size = buffer_frames * periods;
period_size = buffer_frames;
diff --git a/drivers/coreaudio/audio_driver_coreaudio.cpp b/drivers/coreaudio/audio_driver_coreaudio.cpp
index d71d8cdaba..48d0a29516 100644
--- a/drivers/coreaudio/audio_driver_coreaudio.cpp
+++ b/drivers/coreaudio/audio_driver_coreaudio.cpp
@@ -116,7 +116,7 @@ Error AudioDriverCoreAudio::init() {
break;
}
- mix_rate = GLOBAL_DEF_RST("audio/mix_rate", DEFAULT_MIX_RATE);
+ mix_rate = GLOBAL_GET("audio/mix_rate");
zeromem(&strdesc, sizeof(strdesc));
strdesc.mFormatID = kAudioFormatLinearPCM;
@@ -131,7 +131,7 @@ Error AudioDriverCoreAudio::init() {
result = AudioUnitSetProperty(audio_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, kOutputBus, &strdesc, sizeof(strdesc));
ERR_FAIL_COND_V(result != noErr, FAILED);
- int latency = GLOBAL_DEF_RST("audio/output_latency", DEFAULT_OUTPUT_LATENCY);
+ int latency = GLOBAL_GET("audio/output_latency");
// Sample rate is independent of channels (ref: https://stackoverflow.com/questions/11048825/audio-sample-frequency-rely-on-channels)
buffer_frames = closest_power_of_2(latency * mix_rate / 1000);
@@ -403,7 +403,7 @@ Error AudioDriverCoreAudio::capture_init() {
break;
}
- mix_rate = GLOBAL_DEF_RST("audio/mix_rate", DEFAULT_MIX_RATE);
+ mix_rate = GLOBAL_GET("audio/mix_rate");
zeromem(&strdesc, sizeof(strdesc));
strdesc.mFormatID = kAudioFormatLinearPCM;
diff --git a/drivers/dummy/rasterizer_dummy.h b/drivers/dummy/rasterizer_dummy.h
index d619a20745..7af7678f63 100644
--- a/drivers/dummy/rasterizer_dummy.h
+++ b/drivers/dummy/rasterizer_dummy.h
@@ -861,6 +861,13 @@ public:
texture_owner.free(p_rid);
memdelete(texture);
}
+
+ if (mesh_owner.owns(p_rid)) {
+ // delete the mesh
+ DummyMesh *mesh = mesh_owner.getornull(p_rid);
+ mesh_owner.free(p_rid);
+ memdelete(mesh);
+ }
return true;
}
diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.cpp b/drivers/pulseaudio/audio_driver_pulseaudio.cpp
index ce0b8ade95..a6bc4f3b2c 100644
--- a/drivers/pulseaudio/audio_driver_pulseaudio.cpp
+++ b/drivers/pulseaudio/audio_driver_pulseaudio.cpp
@@ -179,7 +179,7 @@ Error AudioDriverPulseAudio::init_device() {
break;
}
- int latency = GLOBAL_DEF_RST("audio/output_latency", DEFAULT_OUTPUT_LATENCY);
+ int latency = GLOBAL_GET("audio/output_latency");
buffer_frames = closest_power_of_2(latency * mix_rate / 1000);
pa_buffer_size = buffer_frames * pa_map.channels;
@@ -237,7 +237,7 @@ Error AudioDriverPulseAudio::init() {
thread_exited = false;
exit_thread = false;
- mix_rate = GLOBAL_DEF_RST("audio/mix_rate", DEFAULT_MIX_RATE);
+ mix_rate = GLOBAL_GET("audio/mix_rate");
pa_ml = pa_mainloop_new();
ERR_FAIL_COND_V(pa_ml == nullptr, ERR_CANT_OPEN);
diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp
index ea99594810..efd4f057fd 100644
--- a/drivers/vulkan/rendering_device_vulkan.cpp
+++ b/drivers/vulkan/rendering_device_vulkan.cpp
@@ -4431,6 +4431,12 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
write.pNext = nullptr;
write.dstSet = VK_NULL_HANDLE; //will assign afterwards when everything is valid
write.dstBinding = set_uniform.binding;
+ write.dstArrayElement = 0;
+ write.descriptorCount = 0;
+ write.descriptorType = VK_DESCRIPTOR_TYPE_MAX_ENUM; //Invalid value.
+ write.pImageInfo = nullptr;
+ write.pBufferInfo = nullptr;
+ write.pTexelBufferView = nullptr;
uint32_t type_size = 1;
switch (uniform.type) {
diff --git a/drivers/wasapi/audio_driver_wasapi.cpp b/drivers/wasapi/audio_driver_wasapi.cpp
index 707e55cfcb..cd1c08b717 100644
--- a/drivers/wasapi/audio_driver_wasapi.cpp
+++ b/drivers/wasapi/audio_driver_wasapi.cpp
@@ -387,7 +387,7 @@ Error AudioDriverWASAPI::finish_capture_device() {
}
Error AudioDriverWASAPI::init() {
- mix_rate = GLOBAL_DEF_RST("audio/mix_rate", DEFAULT_MIX_RATE);
+ mix_rate = GLOBAL_GET("audio/mix_rate");
Error err = init_render_device();
if (err != OK) {
diff --git a/drivers/xaudio2/audio_driver_xaudio2.cpp b/drivers/xaudio2/audio_driver_xaudio2.cpp
index df7d2488fd..421cf6a8cf 100644
--- a/drivers/xaudio2/audio_driver_xaudio2.cpp
+++ b/drivers/xaudio2/audio_driver_xaudio2.cpp
@@ -44,12 +44,12 @@ Error AudioDriverXAudio2::init() {
pcm_open = false;
samples_in = nullptr;
- mix_rate = GLOBAL_DEF_RST("audio/mix_rate", DEFAULT_MIX_RATE);
+ mix_rate = GLOBAL_GET("audio/mix_rate");
// FIXME: speaker_mode seems unused in the Xaudio2 driver so far
speaker_mode = SPEAKER_MODE_STEREO;
channels = 2;
- int latency = GLOBAL_DEF_RST("audio/output_latency", DEFAULT_OUTPUT_LATENCY);
+ int latency = GLOBAL_GET("audio/output_latency");
buffer_size = closest_power_of_2(latency * mix_rate / 1000);
samples_in = memnew_arr(int32_t, buffer_size * channels);
diff --git a/editor/SCsub b/editor/SCsub
index 13ae85bbf0..651dd5fffd 100644
--- a/editor/SCsub
+++ b/editor/SCsub
@@ -6,6 +6,7 @@ env.editor_sources = []
import os
import os.path
+import glob
from platform_methods import run_in_subprocess
import editor_builders
@@ -40,20 +41,21 @@ if env["tools"]:
f.write(reg_exporters_inc)
f.write(reg_exporters)
- # API documentation
+ # Core API documentation.
docs = []
- doc_dirs = ["doc/classes"]
+ docs += Glob("#doc/classes/*.xml")
- for p in env.doc_class_path.values():
- if p not in doc_dirs:
- doc_dirs.append(p)
+ # Module API documentation.
+ module_dirs = []
+ for d in env.doc_class_path.values():
+ if d not in module_dirs:
+ module_dirs.append(d)
- for d in doc_dirs:
- try:
- for f in os.listdir(os.path.join(env.Dir("#").abspath, d)):
- docs.append("#" + os.path.join(d, f))
- except OSError:
- pass
+ for d in module_dirs:
+ if not os.path.isabs(d):
+ docs += Glob("#" + d + "/*.xml") # Built-in.
+ else:
+ docs += Glob(d + "/*.xml") # Custom.
_make_doc_data_class_path(os.path.join(env.Dir("#").abspath, "editor"))
@@ -61,8 +63,6 @@ if env["tools"]:
env.Depends("#editor/doc_data_compressed.gen.h", docs)
env.CommandNoCache("#editor/doc_data_compressed.gen.h", docs, run_in_subprocess(editor_builders.make_doc_header))
- import glob
-
path = env.Dir(".").abspath
# Editor translations
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp
index 2a8e0d856e..75e7542abb 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -4882,12 +4882,12 @@ void AnimationTrackEditor::_box_selection_draw() {
void AnimationTrackEditor::_scroll_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event;
- if (mb.is_valid() && mb->is_pressed() && mb->get_command() && mb->get_button_index() == BUTTON_WHEEL_DOWN) {
+ if (mb.is_valid() && mb->is_pressed() && mb->get_command() && mb->get_button_index() == BUTTON_WHEEL_UP) {
timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() * 1.05);
scroll->accept_event();
}
- if (mb.is_valid() && mb->is_pressed() && mb->get_command() && mb->get_button_index() == BUTTON_WHEEL_UP) {
+ if (mb.is_valid() && mb->is_pressed() && mb->get_command() && mb->get_button_index() == BUTTON_WHEEL_DOWN) {
timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() / 1.05);
scroll->accept_event();
}
diff --git a/editor/doc_data.h b/editor/doc_data.h
index 06d0889af6..8c93bfa597 100644
--- a/editor/doc_data.h
+++ b/editor/doc_data.h
@@ -42,6 +42,9 @@ public:
String type;
String enumeration;
String default_value;
+ bool operator<(const ArgumentDoc &p_arg) const {
+ return name < p_arg.name;
+ }
};
struct MethodDoc {
@@ -51,8 +54,8 @@ public:
String qualifiers;
String description;
Vector<ArgumentDoc> arguments;
- bool operator<(const MethodDoc &p_md) const {
- return name < p_md.name;
+ bool operator<(const MethodDoc &p_method) const {
+ return name < p_method.name;
}
};
@@ -61,6 +64,9 @@ public:
String value;
String enumeration;
String description;
+ bool operator<(const ConstantDoc &p_const) const {
+ return name < p_const.name;
+ }
};
struct PropertyDoc {
@@ -70,13 +76,10 @@ public:
String description;
String setter, getter;
String default_value;
- bool overridden;
+ bool overridden = false;
bool operator<(const PropertyDoc &p_prop) const {
return name < p_prop.name;
}
- PropertyDoc() {
- overridden = false;
- }
};
struct ClassDoc {
@@ -91,6 +94,9 @@ public:
Vector<ConstantDoc> constants;
Vector<PropertyDoc> properties;
Vector<PropertyDoc> theme_properties;
+ bool operator<(const ClassDoc &p_class) const {
+ return name < p_class.name;
+ }
};
String version;
diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp
index 87ca499413..716ead9afc 100644
--- a/editor/editor_export.cpp
+++ b/editor/editor_export.cpp
@@ -1162,6 +1162,7 @@ void EditorExport::save_presets() {
}
void EditorExport::_bind_methods() {
+ ADD_SIGNAL(MethodInfo("export_presets_updated"));
}
void EditorExport::add_export_platform(const Ref<EditorExportPlatform> &p_platform) {
@@ -1229,8 +1230,13 @@ Vector<Ref<EditorExportPlugin>> EditorExport::get_export_plugins() {
}
void EditorExport::_notification(int p_what) {
- if (p_what == NOTIFICATION_ENTER_TREE) {
- load_config();
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ load_config();
+ } break;
+ case NOTIFICATION_PROCESS: {
+ update_export_presets();
+ } break;
}
}
@@ -1332,6 +1338,49 @@ void EditorExport::load_config() {
block_save = false;
}
+void EditorExport::update_export_presets() {
+ Map<StringName, List<EditorExportPlatform::ExportOption>> platform_options;
+
+ for (int i = 0; i < export_platforms.size(); i++) {
+ Ref<EditorExportPlatform> platform = export_platforms[i];
+
+ if (platform->should_update_export_options()) {
+ List<EditorExportPlatform::ExportOption> options;
+ platform->get_export_options(&options);
+
+ platform_options[platform->get_name()] = options;
+ }
+ }
+
+ bool export_presets_updated = false;
+ for (int i = 0; i < export_presets.size(); i++) {
+ Ref<EditorExportPreset> preset = export_presets[i];
+ if (platform_options.has(preset->get_platform()->get_name())) {
+ export_presets_updated = true;
+
+ List<EditorExportPlatform::ExportOption> options = platform_options[preset->get_platform()->get_name()];
+
+ // Copy the previous preset values
+ Map<StringName, Variant> previous_values = preset->values;
+
+ // Clear the preset properties and values prior to reloading
+ preset->properties.clear();
+ preset->values.clear();
+
+ for (List<EditorExportPlatform::ExportOption>::Element *E = options.front(); E; E = E->next()) {
+ preset->properties.push_back(E->get().option);
+
+ StringName option_name = E->get().option.name;
+ preset->values[option_name] = previous_values.has(option_name) ? previous_values[option_name] : E->get().default_value;
+ }
+ }
+ }
+
+ if (export_presets_updated) {
+ emit_signal(_export_presets_updated);
+ }
+}
+
bool EditorExport::poll_export_platforms() {
bool changed = false;
for (int i = 0; i < export_platforms.size(); i++) {
@@ -1351,7 +1400,10 @@ EditorExport::EditorExport() {
save_timer->connect("timeout", callable_mp(this, &EditorExport::_save));
block_save = false;
+ _export_presets_updated = "export_presets_updated";
+
singleton = this;
+ set_process(true);
}
EditorExport::~EditorExport() {
diff --git a/editor/editor_export.h b/editor/editor_export.h
index 797649855f..4978b39248 100644
--- a/editor/editor_export.h
+++ b/editor/editor_export.h
@@ -227,6 +227,7 @@ public:
virtual Ref<EditorExportPreset> create_preset();
virtual void get_export_options(List<ExportOption> *r_options) = 0;
+ virtual bool should_update_export_options() { return false; }
virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { return true; }
virtual String get_os_name() const = 0;
@@ -350,6 +351,8 @@ class EditorExport : public Node {
Vector<Ref<EditorExportPreset>> export_presets;
Vector<Ref<EditorExportPlugin>> export_plugins;
+ StringName _export_presets_updated;
+
Timer *save_timer;
bool block_save;
@@ -381,7 +384,7 @@ public:
Vector<Ref<EditorExportPlugin>> get_export_plugins();
void load_config();
-
+ void update_export_presets();
bool poll_export_platforms();
EditorExport();
diff --git a/editor/editor_feature_profile.cpp b/editor/editor_feature_profile.cpp
index d3749477cc..2a410c03e7 100644
--- a/editor/editor_feature_profile.cpp
+++ b/editor/editor_feature_profile.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "editor_feature_profile.h"
+
#include "core/io/json.h"
#include "core/os/dir_access.h"
#include "editor/editor_settings.h"
@@ -353,7 +354,7 @@ void EditorFeatureProfileManager::_update_profile_list(const String &p_select_pr
}
if (name == current_profile) {
- name += " (current)";
+ name += " " + TTR("(current)");
}
profile_list->add_item(name);
int index = profile_list->get_item_count() - 1;
@@ -363,12 +364,15 @@ void EditorFeatureProfileManager::_update_profile_list(const String &p_select_pr
}
}
+ class_list_vbc->set_visible(selected_profile != String());
+ property_list_vbc->set_visible(selected_profile != String());
+ no_profile_selected_help->set_visible(selected_profile == String());
profile_actions[PROFILE_CLEAR]->set_disabled(current_profile == String());
profile_actions[PROFILE_ERASE]->set_disabled(selected_profile == String());
profile_actions[PROFILE_EXPORT]->set_disabled(selected_profile == String());
profile_actions[PROFILE_SET]->set_disabled(selected_profile == String());
- current_profile_name->set_text(current_profile);
+ current_profile_name->set_text(current_profile != String() ? current_profile : TTR("(none)"));
_update_selected_profile();
}
@@ -451,6 +455,10 @@ void EditorFeatureProfileManager::_create_new_profile() {
new_profile->save_to_file(file);
_update_profile_list(name);
+ // The newly created profile is the first one, make it the current profile automatically.
+ if (profile_list->get_item_count() == 1) {
+ _profile_action(PROFILE_SET);
+ }
}
void EditorFeatureProfileManager::_profile_selected(int p_what) {
@@ -730,6 +738,10 @@ void EditorFeatureProfileManager::_import_profiles(const Vector<String> &p_paths
}
_update_profile_list();
+ // The newly imported profile is the first one, make it the current profile automatically.
+ if (profile_list->get_item_count() == 1) {
+ _profile_action(PROFILE_SET);
+ }
}
void EditorFeatureProfileManager::_export_profile(const String &p_path) {
@@ -779,6 +791,7 @@ EditorFeatureProfileManager::EditorFeatureProfileManager() {
HBoxContainer *name_hbc = memnew(HBoxContainer);
current_profile_name = memnew(LineEdit);
name_hbc->add_child(current_profile_name);
+ current_profile_name->set_text(TTR("(none)"));
current_profile_name->set_editable(false);
current_profile_name->set_h_size_flags(Control::SIZE_EXPAND_FILL);
profile_actions[PROFILE_CLEAR] = memnew(Button(TTR("Unset")));
@@ -827,7 +840,7 @@ EditorFeatureProfileManager::EditorFeatureProfileManager() {
h_split->set_v_size_flags(Control::SIZE_EXPAND_FILL);
main_vbc->add_child(h_split);
- VBoxContainer *class_list_vbc = memnew(VBoxContainer);
+ class_list_vbc = memnew(VBoxContainer);
h_split->add_child(class_list_vbc);
class_list_vbc->set_h_size_flags(Control::SIZE_EXPAND_FILL);
@@ -837,17 +850,30 @@ EditorFeatureProfileManager::EditorFeatureProfileManager() {
class_list->set_edit_checkbox_cell_only_when_checkbox_is_pressed(true);
class_list->connect("cell_selected", callable_mp(this, &EditorFeatureProfileManager::_class_list_item_selected));
class_list->connect("item_edited", callable_mp(this, &EditorFeatureProfileManager::_class_list_item_edited), varray(), CONNECT_DEFERRED);
+ // It will be displayed once the user creates or chooses a profile.
+ class_list_vbc->hide();
- VBoxContainer *property_list_vbc = memnew(VBoxContainer);
+ property_list_vbc = memnew(VBoxContainer);
h_split->add_child(property_list_vbc);
property_list_vbc->set_h_size_flags(Control::SIZE_EXPAND_FILL);
property_list = memnew(Tree);
- property_list_vbc->add_margin_child(TTR("Class Options"), property_list, true);
+ property_list_vbc->add_margin_child(TTR("Class Options:"), property_list, true);
property_list->set_hide_root(true);
property_list->set_hide_folding(true);
property_list->set_edit_checkbox_cell_only_when_checkbox_is_pressed(true);
property_list->connect("item_edited", callable_mp(this, &EditorFeatureProfileManager::_property_item_edited), varray(), CONNECT_DEFERRED);
+ // It will be displayed once the user creates or chooses a profile.
+ property_list_vbc->hide();
+
+ no_profile_selected_help = memnew(Label(TTR("Create or import a profile to edit available classes and properties.")));
+ // Add some spacing above the help label.
+ Ref<StyleBoxEmpty> sb = memnew(StyleBoxEmpty);
+ sb->set_default_margin(MARGIN_TOP, 20 * EDSCALE);
+ no_profile_selected_help->add_theme_style_override("normal", sb);
+ no_profile_selected_help->set_align(Label::ALIGN_CENTER);
+ no_profile_selected_help->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ h_split->add_child(no_profile_selected_help);
new_profile_dialog = memnew(ConfirmationDialog);
new_profile_dialog->set_title(TTR("New profile name:"));
diff --git a/editor/editor_feature_profile.h b/editor/editor_feature_profile.h
index 4036ec7ec6..38413e35a2 100644
--- a/editor/editor_feature_profile.h
+++ b/editor/editor_feature_profile.h
@@ -120,8 +120,11 @@ class EditorFeatureProfileManager : public AcceptDialog {
HSplitContainer *h_split;
+ VBoxContainer *class_list_vbc;
Tree *class_list;
+ VBoxContainer *property_list_vbc;
Tree *property_list;
+ Label *no_profile_selected_help;
EditorFileDialog *import_profiles;
EditorFileDialog *export_profile;
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index ca0e486259..8b7014fabe 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -6014,8 +6014,11 @@ EditorNode::EditorNode() {
left_menu_hb->add_child(settings_menu);
p = settings_menu->get_popup();
-
+#ifdef OSX_ENABLED
+ p->add_shortcut(ED_SHORTCUT("editor/editor_settings", TTR("Editor Settings..."), KEY_MASK_CMD + KEY_COMMA), SETTINGS_PREFERENCES);
+#else
p->add_shortcut(ED_SHORTCUT("editor/editor_settings", TTR("Editor Settings...")), SETTINGS_PREFERENCES);
+#endif
p->add_separator();
editor_layouts = memnew(PopupMenu);
diff --git a/editor/editor_spin_slider.cpp b/editor/editor_spin_slider.cpp
index 39e6746797..67d92c4839 100644
--- a/editor/editor_spin_slider.cpp
+++ b/editor/editor_spin_slider.cpp
@@ -186,6 +186,7 @@ void EditorSpinSlider::_notification(int p_what) {
p_what == NOTIFICATION_WM_FOCUS_IN ||
p_what == NOTIFICATION_EXIT_TREE) {
if (grabbing_spinner) {
+ grabber->hide();
Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
grabbing_spinner = false;
grabbing_spinner_attempt = false;
diff --git a/editor/icons/CameraEffects.svg b/editor/icons/CameraEffects.svg
new file mode 100644
index 0000000000..2f6dad5fd8
--- /dev/null
+++ b/editor/icons/CameraEffects.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m5.9492188 2a3 3 0 0 0 -2.9492188 3 3 3 0 0 0 1 2.2304688v1.7695312l-3-2v6l3-2v1c0 .554.44599 1 1 1h3c.0076117-.045309.0115938-.096059.0214844-.134766.0773621-.302758.1860981-.478282.2832031-.625.1397097-.211089.2814954-.338835.4257813-.480468-.1445165-.141692-.2879205-.269839-.4277344-.480469-.0971224-.146315-.2052562-.321748-.2832032-.623047-.0777157-.300405-.1044198-.8152648.1640626-1.2910156.2700589-.4775976.7340166-.7239536 1.0371093-.8105469.3037241-.0867737.5108695-.0808838.6875-.0703125.2608449.0156115.4500479.0763383.6503909.1328125.049596-.1859081.086921-.3641449.195312-.5800781.078477-.1563394.174637-.3364783.396485-.5527344.221847-.2162561.652628-.4930277 1.195312-.4980469a1.6124973 1.6124973 0 0 1 .033203 0c.542861.0056205.97185.2837448 1.19336.5.146452.1429781.230167.265896.298828.3808594a3 3 0 0 0 .128906-.8671875 3 3 0 0 0 -3-3 3 3 0 0 0 -2.0117188.7773438 3 3 0 0 0 -2.9882812-2.7773438 3 3 0 0 0 -.0507812 0z" fill="#e0e0e0"/><path d="m12.36062 8.59795a.53334 3.2001 0 0 0 -.50976 2.2754 3.2001.53334 30 0 0 -2.2656-.71484 3.2001.53334 30 0 0 1.75 1.6016.53334 3.2001 60 0 0 -1.7461 1.5996.53334 3.2001 60 0 0 2.2578-.71094.53334 3.2001 0 0 0 .51367 2.3496.53334 3.2001 0 0 0 .51367-2.3516 3.2001.53334 30 0 0 2.2539.71094 3.2001.53334 30 0 0 -1.7441-1.5977.53334 3.2001 60 0 0 1.748-1.5996.53334 3.2001 60 0 0 -2.2617.71484.53334 3.2001 0 0 0 -.50977-2.2773z" fill="#cea4f1" stroke-width="1.0667"/></svg> \ No newline at end of file
diff --git a/editor/icons/CubeMap.svg b/editor/icons/Cubemap.svg
index c9e6f1fa7d..c9e6f1fa7d 100644
--- a/editor/icons/CubeMap.svg
+++ b/editor/icons/Cubemap.svg
diff --git a/editor/icons/CubemapArray.svg b/editor/icons/CubemapArray.svg
new file mode 100644
index 0000000000..350a64f9c2
--- /dev/null
+++ b/editor/icons/CubemapArray.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 6v4h2v-4zm6 0v4h4v-4z" fill="#84ffb1"/><path d="m4 6v4h4v-4zm8 0v4h2v-4z" fill="#ff8484"/><path d="m4 2v4h4v-4zm0 8v4h4v-4z" fill="#84c2ff"/><path d="m-.00000002 2v12h4.00000002v-2h-2v-8h2v-2h-2zm12.00000002 0v2h2.000001v8h-2.000001v2h4.000001v-12h-2z" fill="#e0e0e0"/></svg> \ No newline at end of file
diff --git a/editor/icons/LightmapProbe.svg b/editor/icons/LightmapProbe.svg
new file mode 100644
index 0000000000..0972220fda
--- /dev/null
+++ b/editor/icons/LightmapProbe.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 9h3v-2h-3zm2.050781 2.535156 1.414063 1.414063 1.414062-1.414063-1.414062-1.414062zm0-7.070312 1.414063 1.414062 1.414062-1.414062-1.414062-1.414063zm1.949219 3.535156c0 1.6569 1.3432 3 3 3s3-1.3431 3-3-1.3432-3-3-3-3 1.3431-3 3zm3 7c3.865993 0 7-3.134007 7-7s-3.134007-7-7-7v2.333984c2.577329 0 4.666016 2.088687 4.666016 4.666016s-2.088687 4.666016-4.666016 4.666016z" fill="#fc9c9c" fill-opacity=".996078" stroke-width="1.16667"/></svg> \ No newline at end of file
diff --git a/editor/icons/PanoramaSky.svg b/editor/icons/PanoramaSky.svg
deleted file mode 100644
index bfff6840bd..0000000000
--- a/editor/icons/PanoramaSky.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientTransform="matrix(1.0096 0 0 1.0227 -.009615 -22.593)" gradientUnits="userSpaceOnUse" x1="8" x2="8" y1="1038.4" y2="1050.4"><stop offset="0" stop-color="#1ec3ff"/><stop offset="1" stop-color="#b2e1ff"/></linearGradient><g transform="translate(0 -1037.4)"><path d="m1 1039.4c4.2749 2.6091 10.765 2.7449 14 0v12c-3.5849-2.6849-9.7929-2.6544-14 0z" fill="url(#a)" stroke-width="15.242"/><path d="m11 6c-.554 0-1 .446-1 1h-1c-.554 0-1 .446-1 1s.446 1 1 1h2c.554 0 1-.446 1-1h1c.554 0 1-.446 1-1s-.446-1-1-1zm-8 3c-.554 0-1 .446-1 1s.446 1 1 1h1c.554 0 1-.446 1-1s-.446-1-1-1z" fill="#fff" transform="translate(0 1037.4)"/></g></svg> \ No newline at end of file
diff --git a/editor/icons/PanoramaSkyMaterial.svg b/editor/icons/PanoramaSkyMaterial.svg
new file mode 100644
index 0000000000..9f40ffb63c
--- /dev/null
+++ b/editor/icons/PanoramaSkyMaterial.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 5v2h8 1c0-.554.446-1 1-1h2c.554 0 1 .446 1 1h1v-2z" fill="#9dff70"/><path d="m1 3v2h14v-2h-1.589844c-2.86436 1.357608-6.9481434 1.30996-10.347656 0z" fill="#ffeb70"/><path d="m1 2v1h2.0625c-.7241713-.2790504-1.419865-.6077805-2.0625-1zm14 0c-.465784.3952185-1.005424.7230054-1.589844 1h1.589844z" fill="#ff7070"/><path d="m1 7v2h2 1 5c-.554 0-1-.446-1-1s.446-1 1-1zm13 0c0 .554-.446 1-1 1h-1c0 .554-.446 1-1 1h4v-2z" fill="#70ffb9"/><path d="m1 9v2h2c-.554 0-1-.446-1-1s.446-1 1-1zm3 0c.554 0 1 .446 1 1s-.446 1-1 1h11v-2h-4-2z" fill="#70deff"/><path d="m1 13v-2h14v2h-1.589844c-2.86436-1.357608-6.9481434-1.30996-10.347656 0z" fill="#9f70ff"/><path d="m1 14v-1h2.0625c-.7241713.27905-1.419865.60778-2.0625 1zm14 0c-.465784-.395219-1.005424-.723005-1.589844-1h1.589844z" fill="#ff70ac"/></svg> \ No newline at end of file
diff --git a/editor/icons/PhysicalSkyMaterial.svg b/editor/icons/PhysicalSkyMaterial.svg
new file mode 100644
index 0000000000..5831cb2c63
--- /dev/null
+++ b/editor/icons/PhysicalSkyMaterial.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 5v2h8 1c0-.554.446-1 1-1h2c.554 0 1 .446 1 1h1v-2z" fill="#9dff70"/><path d="m1 7v2h2 1 5c-.554 0-1-.446-1-1s.446-1 1-1zm13 0c0 .554-.446 1-1 1h-1c0 .554-.446 1-1 1h4v-2z" fill="#70ffb9"/><path d="m1 9v2h2c-.554 0-1-.446-1-1s.446-1 1-1zm3 0c.554 0 1 .446 1 1s-.446 1-1 1h11v-2h-4-2z" fill="#70deff"/><path d="m1 3v2h14v-2z" fill="#ffeb70"/><path d="m1 11v2h14v-2z" fill="#9f70ff"/></svg> \ No newline at end of file
diff --git a/editor/icons/ProceduralSky.svg b/editor/icons/ProceduralSky.svg
deleted file mode 100644
index 356a966fe9..0000000000
--- a/editor/icons/ProceduralSky.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="8" x2="8" y1="1040.4" y2="1050.4"><stop offset="0" stop-color="#1ec3ff"/><stop offset="1" stop-color="#b2e1ff"/></linearGradient><g transform="translate(0 -1037.4)"><path d="m8 1040.4a7 7 0 0 0 -7 7 7 7 0 0 0 .68555 3h12.631a7 7 0 0 0 .68359-3 7 7 0 0 0 -7-7z" fill="url(#a)"/><path d="m10 7c-.554 0-1 .446-1 1h-1c-.554 0-1 .446-1 1s.446 1 1 1h2c.554 0 1-.446 1-1h1c.554 0 1-.446 1-1s-.446-1-1-1zm-7 3c-.554 0-1 .446-1 1s.446 1 1 1h1c.554 0 1-.446 1-1s-.446-1-1-1z" fill="#fff" transform="translate(0 1037.4)"/></g></svg> \ No newline at end of file
diff --git a/editor/icons/ProceduralSkyMaterial.svg b/editor/icons/ProceduralSkyMaterial.svg
new file mode 100644
index 0000000000..f7a3944671
--- /dev/null
+++ b/editor/icons/ProceduralSkyMaterial.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1.0761719 11a7 7 0 0 0 .609375 2h12.6308591a7 7 0 0 0 .609375-2h-9.925781c0 .554-.446 1-1 1h-1c-.554 0-1-.446-1-1z" fill="#9f70ff"/><path d="m1.0722656 9a7 7 0 0 0 -.0722656 1 7 7 0 0 0 .0761719 1h.9238281c0-.554.446-1 1-1h1c.554 0 1 .446 1 1h9.925781a7 7 0 0 0 .074219-1 7 7 0 0 0 -.072266-1h-2.927734-1c0 .554-.446 1-1 1h-2c-.554 0-1-.446-1-1z" fill="#70deff"/><path d="m1.6757812 7a7 7 0 0 0 -.6035156 2h5.9277344c0-.554.446-1 1-1h1c0-.554.446-1 1-1zm10.3242188 0c.554 0 1 .446 1 1s-.446 1-1 1h2.927734a7 7 0 0 0 -.603515-2z" fill="#70ffb9"/><path d="m3.1035156 5a7 7 0 0 0 -1.4277344 2h12.6484378a7 7 0 0 0 -1.425781-2z" fill="#9dff70"/><path d="m8 3a7 7 0 0 0 -4.8964844 2h9.7949224a7 7 0 0 0 -4.898438-2z" fill="#ffeb70"/></svg> \ No newline at end of file
diff --git a/editor/icons/RootMotionView.svg b/editor/icons/RootMotionView.svg
new file mode 100644
index 0000000000..4d33420383
--- /dev/null
+++ b/editor/icons/RootMotionView.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><radialGradient id="a" cx="8" cy="8" gradientTransform="matrix(.85714281 -.00000007 .00000004 .85714284 1.142858 1.142858)" gradientUnits="userSpaceOnUse" r="7"><stop offset="0" stop-color="#fc9c9c"/><stop offset=".83333331" stop-color="#fc9c9c" stop-opacity=".701961"/><stop offset="1" stop-color="#fc9c9c" stop-opacity="0"/></radialGradient><path d="m5 2v3h-3v2h3v2h-3v2h3v3h2v-3h2v3h2v-3h3v-2h-3v-2h3v-2h-3v-3h-2v3h-2v-3zm2 5h2v2h-2z" fill="url(#a)"/></svg> \ No newline at end of file
diff --git a/editor/icons/SCsub b/editor/icons/SCsub
index f0d51999f0..e143276259 100644
--- a/editor/icons/SCsub
+++ b/editor/icons/SCsub
@@ -2,6 +2,8 @@
Import("env")
+import os
+
from platform_methods import run_in_subprocess
import editor_icons_builders
@@ -15,7 +17,10 @@ env["BUILDERS"]["MakeEditorIconsBuilder"] = make_editor_icons_builder
icon_sources = Glob("*.svg")
# Module icons
-for module_icons in env.module_icons_paths:
- icon_sources += Glob("#" + module_icons + "/*.svg")
+for path in env.module_icons_paths:
+ if not os.path.isabs(path):
+ icon_sources += Glob("#" + path + "/*.svg") # Built-in.
+ else:
+ icon_sources += Glob(path + "/*.svg") # Custom.
env.Alias("editor_icons", [env.MakeEditorIconsBuilder("#editor/editor_icons.gen.h", icon_sources)])
diff --git a/editor/icons/ShaderGlobalsOverride.svg b/editor/icons/ShaderGlobalsOverride.svg
new file mode 100644
index 0000000000..2fe76ed777
--- /dev/null
+++ b/editor/icons/ShaderGlobalsOverride.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1c-.55226.0001-.99994.4477-1 1v12c.0000552.5523.44774.9999 1 1h12c.55226-.0001.99994-.4477 1-1v-8l-5-5zm1 2h6v3c0 .554.44599 1 1 1h3v6h-10zm1 1v1h3v-1zm0 2v1h2v-1zm3 0v1h1v-1zm-2 3 3 3 3-3z" fill="#e0e0e0"/></svg> \ No newline at end of file
diff --git a/editor/import_dock.cpp b/editor/import_dock.cpp
index 1128b72c5a..8ab2e0aef1 100644
--- a/editor/import_dock.cpp
+++ b/editor/import_dock.cpp
@@ -441,7 +441,9 @@ void ImportDock::_reimport() {
} else {
//override entirely
config->set_value("remap", "importer", importer_name);
- config->erase_section("params");
+ if (config->has_section("params")) {
+ config->erase_section("params");
+ }
for (List<PropertyInfo>::Element *E = params->properties.front(); E; E = E->next()) {
config->set_value("params", E->get().name, params->values[E->get().name]);
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index 744c7907af..8f88612ffa 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -2240,7 +2240,7 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) {
return true;
}
- if (k.is_valid() && !k->is_pressed() && drag_type == DRAG_KEY_MOVE && tool == TOOL_SELECT &&
+ if (k.is_valid() && !k->is_pressed() && drag_type == DRAG_KEY_MOVE && (tool == TOOL_SELECT || tool == TOOL_MOVE) &&
(k->get_keycode() == KEY_UP || k->get_keycode() == KEY_DOWN || k->get_keycode() == KEY_LEFT || k->get_keycode() == KEY_RIGHT)) {
// Confirm canvas items move by arrow keys
if ((!Input::get_singleton()->is_key_pressed(KEY_UP)) &&
diff --git a/editor/project_export.cpp b/editor/project_export.cpp
index 32a1cf2fa1..e5372a5d47 100644
--- a/editor/project_export.cpp
+++ b/editor/project_export.cpp
@@ -133,6 +133,12 @@ void ProjectExportDialog::_add_preset(int p_platform) {
_edit_preset(EditorExport::get_singleton()->get_export_preset_count() - 1);
}
+void ProjectExportDialog::_force_update_current_preset_parameters() {
+ // Force the parameters section to refresh its UI.
+ parameters->edit(nullptr);
+ _update_current_preset();
+}
+
void ProjectExportDialog::_update_current_preset() {
_edit_preset(presets->get_current());
}
@@ -1101,6 +1107,7 @@ ProjectExportDialog::ProjectExportDialog() {
parameters->set_name(TTR("Options"));
parameters->set_v_size_flags(Control::SIZE_EXPAND_FILL);
parameters->connect("property_edited", callable_mp(this, &ProjectExportDialog::_update_parameters));
+ EditorExport::get_singleton()->connect("export_presets_updated", callable_mp(this, &ProjectExportDialog::_force_update_current_preset_parameters));
// Resources export parameters.
diff --git a/editor/project_export.h b/editor/project_export.h
index 2e311eb3b3..cfa00773d8 100644
--- a/editor/project_export.h
+++ b/editor/project_export.h
@@ -123,6 +123,7 @@ private:
void _delete_preset_confirm();
void _update_export_all();
+ void _force_update_current_preset_parameters();
void _update_current_preset();
void _update_presets();
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index e73c52047b..a81a2ff4e9 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -579,7 +579,8 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
dup->set_name(parent->validate_child_name(dup));
- editor_data->get_undo_redo().add_do_method(parent, "add_child_below_node", add_below_node, dup);
+ editor_data->get_undo_redo().add_do_method(add_below_node, "add_sibling", dup);
+
for (List<Node *>::Element *F = owned.front(); F; F = F->next()) {
if (!duplimap.has(F->get())) {
continue;
@@ -2063,9 +2064,21 @@ void SceneTreeDock::replace_node(Node *p_node, Node *p_by_node, bool p_keep_prop
if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) {
continue;
}
+
if (E->get().name == "__meta__") {
+ if (Object::cast_to<CanvasItem>(newnode)) {
+ Dictionary metadata = n->get(E->get().name);
+ if (metadata.has("_edit_group_") && metadata["_edit_group_"]) {
+ newnode->set_meta("_edit_group_", true);
+ }
+ if (metadata.has("_edit_lock_") && metadata["_edit_lock_"]) {
+ newnode->set_meta("_edit_lock_", true);
+ }
+ }
+
continue;
}
+
if (default_oldnode->get(E->get().name) != n->get(E->get().name)) {
newnode->set(E->get().name, n->get(E->get().name));
}
diff --git a/gles_builders.py b/gles_builders.py
index 85a8d7aa15..85d0112c9a 100644
--- a/gles_builders.py
+++ b/gles_builders.py
@@ -36,14 +36,14 @@ def include_file_in_legacygl_header(filename, header_data, depth):
while line:
- if line.find("[vertex]") != -1:
+ if line.find("#[vertex]") != -1:
header_data.reading = "vertex"
line = fs.readline()
header_data.line_offset += 1
header_data.vertex_offset = header_data.line_offset
continue
- if line.find("[fragment]") != -1:
+ if line.find("#[fragment]") != -1:
header_data.reading = "fragment"
line = fs.readline()
header_data.line_offset += 1
@@ -612,21 +612,21 @@ def include_file_in_rd_header(filename, header_data, depth):
while line:
- if line.find("[vertex]") != -1:
+ if line.find("#[vertex]") != -1:
header_data.reading = "vertex"
line = fs.readline()
header_data.line_offset += 1
header_data.vertex_offset = header_data.line_offset
continue
- if line.find("[fragment]") != -1:
+ if line.find("#[fragment]") != -1:
header_data.reading = "fragment"
line = fs.readline()
header_data.line_offset += 1
header_data.fragment_offset = header_data.line_offset
continue
- if line.find("[compute]") != -1:
+ if line.find("#[compute]") != -1:
header_data.reading = "compute"
line = fs.readline()
header_data.line_offset += 1
diff --git a/main/main.cpp b/main/main.cpp
index f35e73cdc2..94dd895a26 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -139,7 +139,6 @@ static DisplayServer::ScreenOrientation window_orientation = DisplayServer::SCRE
static uint32_t window_flags = 0;
static Size2i window_size = Size2i(1024, 600);
static bool window_vsync_via_compositor = false;
-static bool disable_wintab = false;
static int init_screen = -1;
static bool init_fullscreen = false;
@@ -313,7 +312,13 @@ void Main::print_help(const char *p_binary) {
OS::get_singleton()->print(" --enable-vsync-via-compositor When vsync is enabled, vsync via the OS' window compositor (Windows only).\n");
OS::get_singleton()->print(" --disable-vsync-via-compositor Disable vsync via the OS' window compositor (Windows only).\n");
OS::get_singleton()->print(" --single-window Use a single window (no separate subwindows).\n");
- OS::get_singleton()->print(" --disable-wintab Disable WinTab API and always use Windows Ink API for the pen input (Windows only).\n");
+ OS::get_singleton()->print(" --tablet-driver Tablet input driver (");
+ for (int i = 0; i < OS::get_singleton()->get_tablet_driver_count(); i++) {
+ if (i != 0)
+ OS::get_singleton()->print(", ");
+ OS::get_singleton()->print("'%s'", OS::get_singleton()->get_tablet_driver_name(i).utf8().get_data());
+ }
+ OS::get_singleton()->print(") (Windows only).\n");
OS::get_singleton()->print("\n");
#endif
@@ -438,6 +443,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
String display_driver = "";
String audio_driver = "";
+ String tablet_driver = "";
String project_path = ".";
bool upwards = false;
String debug_uri = "";
@@ -590,8 +596,26 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
} else if (I->get() == "--gpu-abort") { // force windowed window
Engine::singleton->abort_on_gpu_errors = true;
- } else if (I->get() == "--disable-wintab") {
- disable_wintab = true;
+ } else if (I->get() == "--tablet-driver") {
+ if (I->next()) {
+ tablet_driver = I->next()->get();
+ bool found = false;
+ for (int i = 0; i < OS::get_singleton()->get_tablet_driver_count(); i++) {
+ if (tablet_driver == OS::get_singleton()->get_tablet_driver_name(i)) {
+ found = true;
+ }
+ }
+
+ if (!found) {
+ OS::get_singleton()->print("Unknown tablet driver '%s', aborting.\n", tablet_driver.utf8().get_data());
+ goto error;
+ }
+
+ N = I->next()->next();
+ } else {
+ OS::get_singleton()->print("Missing tablet driver argument, aborting.\n");
+ goto error;
+ }
} else if (I->get() == "--single-window") { // force single window
single_window = true;
@@ -1056,12 +1080,20 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
OS::get_singleton()->_vsync_via_compositor = window_vsync_via_compositor;
- if (!disable_wintab) {
- // No "--disable_wintab" option
- disable_wintab = GLOBAL_DEF("display/window/disable_wintab_api", false);
+ if (tablet_driver == "") { // specified in project.godot
+ tablet_driver = GLOBAL_DEF_RST("display/window/tablet_driver", OS::get_singleton()->get_tablet_driver_name(0));
}
- OS::get_singleton()->_disable_wintab = disable_wintab;
+ for (int i = 0; i < OS::get_singleton()->get_tablet_driver_count(); i++) {
+ if (tablet_driver == OS::get_singleton()->get_tablet_driver_name(i)) {
+ OS::get_singleton()->set_current_tablet_driver(OS::get_singleton()->get_tablet_driver_name(i));
+ break;
+ }
+ }
+
+ if (tablet_driver == "") {
+ OS::get_singleton()->set_current_tablet_driver(OS::get_singleton()->get_tablet_driver_name(0));
+ }
/* todo restore
OS::get_singleton()->_allow_layered = GLOBAL_DEF("display/window/per_pixel_transparency/allowed", false);
@@ -1175,6 +1207,7 @@ error:
display_driver = "";
audio_driver = "";
+ tablet_driver = "";
project_path = "";
args.clear();
@@ -1532,7 +1565,11 @@ bool Main::start() {
} else if (args[i].length() && args[i][0] != '-' && positional_arg == "") {
positional_arg = args[i];
- if (args[i].ends_with(".scn") || args[i].ends_with(".tscn") || args[i].ends_with(".escn")) {
+ if (args[i].ends_with(".scn") ||
+ args[i].ends_with(".tscn") ||
+ args[i].ends_with(".escn") ||
+ args[i].ends_with(".res") ||
+ args[i].ends_with(".tres")) {
// Only consider the positional argument to be a scene path if it ends with
// a file extension associated with Godot scenes. This makes it possible
// for projects to parse command-line arguments for custom CLI arguments
@@ -1608,7 +1645,11 @@ bool Main::start() {
print_line("Loading docs...");
for (int i = 0; i < _doc_data_class_path_count; i++) {
- String path = doc_tool.plus_file(_doc_data_class_paths[i].path);
+ // Custom modules are always located by absolute path.
+ String path = _doc_data_class_paths[i].path;
+ if (path.is_rel_path()) {
+ path = doc_tool.plus_file(path);
+ }
String name = _doc_data_class_paths[i].name;
doc_data_classes[name] = path;
if (!checked_paths.has(path)) {
@@ -1921,6 +1962,16 @@ bool Main::start() {
ProjectSettings::get_singleton()->set_custom_property_info("rendering/canvas_textures/default_texture_repeat", PropertyInfo(Variant::INT, "rendering/canvas_textures/default_texture_repeat", PROPERTY_HINT_ENUM, "Disable,Enable,Mirror"));
}
+#ifdef TOOLS_ENABLED
+ if (editor) {
+ bool editor_embed_subwindows = EditorSettings::get_singleton()->get_setting("interface/editor/single_window_mode");
+
+ if (editor_embed_subwindows) {
+ sml->get_root()->set_embed_subwindows_hint(true);
+ }
+ }
+#endif
+
String local_game_path;
if (game_path != "" && !project_manager) {
local_game_path = game_path.replace("\\", "/");
@@ -1954,12 +2005,6 @@ bool Main::start() {
#ifdef TOOLS_ENABLED
if (editor) {
- bool editor_embed_subwindows = EditorSettings::get_singleton()->get_setting("interface/editor/single_window_mode");
-
- if (editor_embed_subwindows) {
- sml->get_root()->set_embed_subwindows_hint(true);
- }
-
if (game_path != GLOBAL_GET("application/run/main_scene") || !editor_node->has_scenes_in_session()) {
Error serr = editor_node->load_scene(local_game_path);
if (serr != OK) {
diff --git a/main/tests/test_class_db.cpp b/main/tests/test_class_db.cpp
new file mode 100644
index 0000000000..3171091402
--- /dev/null
+++ b/main/tests/test_class_db.cpp
@@ -0,0 +1,882 @@
+/*************************************************************************/
+/* test_class_db.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "test_class_db.h"
+
+#include "core/global_constants.h"
+#include "core/ordered_hash_map.h"
+#include "core/os/os.h"
+#include "core/string_name.h"
+#include "core/ustring.h"
+#include "core/variant.h"
+
+namespace TestClassDB {
+
+enum class [[nodiscard]] TestResult{
+ FAILED,
+ PASS
+};
+
+#define TEST_FAIL_COND(m_cond, m_msg) \
+ if (unlikely(m_cond)) { \
+ ERR_PRINT(m_msg); \
+ return TestResult::FAILED; \
+ } else \
+ ((void)0)
+
+#define TEST_COND(m_cond, m_msg) \
+ if (unlikely(m_cond)) { \
+ ERR_PRINT(m_msg); \
+ __test_result__ = TestResult::FAILED; \
+ } else \
+ ((void)0)
+
+#define TEST_FAIL_CHECK(m_test_expr) \
+ if (unlikely((m_test_expr) == TestResult::FAILED)) { \
+ return TestResult::FAILED; \
+ } else \
+ ((void)0)
+
+#define TEST_CHECK(m_test_expr) \
+ if (unlikely((m_test_expr) == TestResult::FAILED)) { \
+ __test_result__ = TestResult::FAILED; \
+ } else \
+ ((void)0)
+
+#define TEST_START() \
+ TestResult __test_result__ = TestResult::PASS; \
+ ((void)0)
+
+#define TEST_END() return __test_result__;
+
+struct TypeReference {
+ StringName name;
+ bool is_enum = false;
+};
+
+struct ConstantData {
+ String name;
+ int value = 0;
+};
+
+struct EnumData {
+ StringName name;
+ List<ConstantData> constants;
+
+ _FORCE_INLINE_ bool operator==(const EnumData &p_enum) const {
+ return p_enum.name == name;
+ }
+};
+
+struct PropertyData {
+ StringName name;
+ int index = 0;
+
+ StringName getter;
+ StringName setter;
+};
+
+struct ArgumentData {
+ TypeReference type;
+ String name;
+ bool has_defval = false;
+ Variant defval;
+};
+
+struct MethodData {
+ StringName name;
+ TypeReference return_type;
+ List<ArgumentData> arguments;
+ bool is_virtual = false;
+ bool is_vararg = false;
+};
+
+struct SignalData {
+ StringName name;
+ List<ArgumentData> arguments;
+};
+
+struct ExposedClass {
+ StringName name;
+ StringName base;
+
+ bool is_singleton = false;
+ bool is_instantiable = false;
+ bool is_reference = false;
+
+ ClassDB::APIType api_type;
+
+ List<ConstantData> constants;
+ List<EnumData> enums;
+ List<PropertyData> properties;
+ List<MethodData> methods;
+ List<SignalData> signals_;
+
+ const PropertyData *find_property_by_name(const StringName &p_name) const {
+ for (const List<PropertyData>::Element *E = properties.front(); E; E = E->next()) {
+ if (E->get().name == p_name) {
+ return &E->get();
+ }
+ }
+
+ return nullptr;
+ }
+
+ const MethodData *find_method_by_name(const StringName &p_name) const {
+ for (const List<MethodData>::Element *E = methods.front(); E; E = E->next()) {
+ if (E->get().name == p_name) {
+ return &E->get();
+ }
+ }
+
+ return nullptr;
+ }
+};
+
+struct NamesCache {
+ StringName variant_type = StaticCString::create("Variant");
+ StringName object_class = StaticCString::create("Object");
+ StringName reference_class = StaticCString::create("Reference");
+ StringName string_type = StaticCString::create("String");
+ StringName string_name_type = StaticCString::create("StringName");
+ StringName node_path_type = StaticCString::create("NodePath");
+ StringName bool_type = StaticCString::create("bool");
+ StringName int_type = StaticCString::create("int");
+ StringName float_type = StaticCString::create("float");
+ StringName void_type = StaticCString::create("void");
+ StringName vararg_stub_type = StaticCString::create("@VarArg@");
+ StringName vector2_type = StaticCString::create("Vector2");
+ StringName rect2_type = StaticCString::create("Rect2");
+ StringName vector3_type = StaticCString::create("Vector3");
+
+ // Object not included as it must be checked for all derived classes
+ static constexpr int nullable_types_count = 17;
+ StringName nullable_types[nullable_types_count] = {
+ string_type,
+ string_name_type,
+ node_path_type,
+
+ StaticCString::create(_STR(Array)),
+ StaticCString::create(_STR(Dictionary)),
+ StaticCString::create(_STR(Callable)),
+ StaticCString::create(_STR(Signal)),
+
+ StaticCString::create(_STR(PackedByteArray)),
+ StaticCString::create(_STR(PackedInt32Array)),
+ StaticCString::create(_STR(PackedInt64rray)),
+ StaticCString::create(_STR(PackedFloat32Array)),
+ StaticCString::create(_STR(PackedFloat64Array)),
+ StaticCString::create(_STR(PackedStringArray)),
+ StaticCString::create(_STR(PackedVector2Array)),
+ StaticCString::create(_STR(PackedVector3Array)),
+ StaticCString::create(_STR(PackedColorArray)),
+ };
+
+ bool is_nullable_type(const StringName &p_type) const {
+ for (int i = 0; i < nullable_types_count; i++) {
+ if (p_type == nullable_types[i]) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+};
+
+typedef OrderedHashMap<StringName, ExposedClass> ExposedClasses;
+
+struct Context {
+ Vector<StringName> enum_types;
+ Vector<StringName> builtin_types;
+ ExposedClasses exposed_classes;
+ List<EnumData> global_enums;
+ NamesCache names_cache;
+
+ const ExposedClass *find_exposed_class(const StringName &p_name) const {
+ ExposedClasses::ConstElement elem = exposed_classes.find(p_name);
+ return elem ? &elem.value() : nullptr;
+ }
+
+ const ExposedClass *find_exposed_class(const TypeReference &p_type_ref) const {
+ ExposedClasses::ConstElement elem = exposed_classes.find(p_type_ref.name);
+ return elem ? &elem.value() : nullptr;
+ }
+
+ bool has_type(const TypeReference &p_type_ref) const {
+ if (builtin_types.find(p_type_ref.name) >= 0) {
+ return true;
+ }
+
+ if (p_type_ref.is_enum) {
+ if (enum_types.find(p_type_ref.name) >= 0) {
+ return true;
+ }
+
+ // Enum not found. Most likely because none of its constants were bound, so it's empty. That's fine. Use int instead.
+ return builtin_types.find(names_cache.int_type);
+ }
+
+ return false;
+ }
+};
+
+bool arg_default_value_is_assignable_to_type(const Context &p_context, const Variant &p_val, const TypeReference &p_arg_type) {
+ if (p_arg_type.name == p_context.names_cache.variant_type) {
+ // Variant can take anything
+ return true;
+ }
+
+ switch (p_val.get_type()) {
+ case Variant::NIL:
+ return p_context.find_exposed_class(p_arg_type) ||
+ p_context.names_cache.is_nullable_type(p_arg_type.name);
+ case Variant::BOOL:
+ return p_arg_type.name == p_context.names_cache.bool_type;
+ case Variant::INT:
+ return p_arg_type.name == p_context.names_cache.int_type ||
+ p_arg_type.name == p_context.names_cache.float_type ||
+ p_arg_type.is_enum;
+ case Variant::FLOAT:
+ return p_arg_type.name == p_context.names_cache.float_type;
+ case Variant::STRING:
+ case Variant::STRING_NAME:
+ return p_arg_type.name == p_context.names_cache.string_type ||
+ p_arg_type.name == p_context.names_cache.string_name_type ||
+ p_arg_type.name == p_context.names_cache.node_path_type;
+ case Variant::NODE_PATH:
+ return p_arg_type.name == p_context.names_cache.node_path_type;
+ case Variant::TRANSFORM:
+ case Variant::TRANSFORM2D:
+ case Variant::BASIS:
+ case Variant::QUAT:
+ case Variant::PLANE:
+ case Variant::AABB:
+ case Variant::COLOR:
+ case Variant::VECTOR2:
+ case Variant::RECT2:
+ case Variant::VECTOR3:
+ case Variant::_RID:
+ case Variant::ARRAY:
+ case Variant::DICTIONARY:
+ case Variant::PACKED_BYTE_ARRAY:
+ case Variant::PACKED_INT32_ARRAY:
+ case Variant::PACKED_INT64_ARRAY:
+ case Variant::PACKED_FLOAT32_ARRAY:
+ case Variant::PACKED_FLOAT64_ARRAY:
+ case Variant::PACKED_STRING_ARRAY:
+ case Variant::PACKED_VECTOR2_ARRAY:
+ case Variant::PACKED_VECTOR3_ARRAY:
+ case Variant::PACKED_COLOR_ARRAY:
+ case Variant::CALLABLE:
+ case Variant::SIGNAL:
+ return p_arg_type.name == Variant::get_type_name(p_val.get_type());
+ case Variant::OBJECT:
+ return p_context.find_exposed_class(p_arg_type);
+ case Variant::VECTOR2I:
+ return p_arg_type.name == p_context.names_cache.vector2_type ||
+ p_arg_type.name == Variant::get_type_name(p_val.get_type());
+ case Variant::RECT2I:
+ return p_arg_type.name == p_context.names_cache.rect2_type ||
+ p_arg_type.name == Variant::get_type_name(p_val.get_type());
+ case Variant::VECTOR3I:
+ return p_arg_type.name == p_context.names_cache.vector3_type ||
+ p_arg_type.name == Variant::get_type_name(p_val.get_type());
+ default:
+ ERR_PRINT("Unexpected Variant type: " + itos(p_val.get_type()));
+ break;
+ }
+
+ return false;
+}
+
+TestResult validate_property(const Context &p_context, const ExposedClass &p_class, const PropertyData &p_prop) {
+ TEST_START();
+
+ const MethodData *setter = p_class.find_method_by_name(p_prop.setter);
+
+ // Search it in base classes too
+ const ExposedClass *top = &p_class;
+ while (!setter && top->base != StringName()) {
+ top = p_context.find_exposed_class(top->base);
+ TEST_FAIL_COND(!top, "Class not found '" + top->base + "'. Inherited by '" + top->name + "'.");
+ setter = top->find_method_by_name(p_prop.setter);
+ }
+
+ const MethodData *getter = p_class.find_method_by_name(p_prop.getter);
+
+ // Search it in base classes too
+ top = &p_class;
+ while (!getter && top->base != StringName()) {
+ top = p_context.find_exposed_class(top->base);
+ TEST_FAIL_COND(!top, "Class not found '" + top->base + "'. Inherited by '" + top->name + "'.");
+ getter = top->find_method_by_name(p_prop.getter);
+ }
+
+ TEST_FAIL_COND(!setter && !getter,
+ "Couldn't find neither the setter nor the getter for property: '" + p_class.name + "." + String(p_prop.name) + "'.");
+
+ if (setter) {
+ int setter_argc = p_prop.index != -1 ? 2 : 1;
+ TEST_FAIL_COND(setter->arguments.size() != setter_argc,
+ "Invalid property setter argument count: '" + p_class.name + "." + String(p_prop.name) + "'.");
+ }
+
+ if (getter) {
+ int getter_argc = p_prop.index != -1 ? 1 : 0;
+ TEST_FAIL_COND(getter->arguments.size() != getter_argc,
+ "Invalid property setter argument count: '" + p_class.name + "." + String(p_prop.name) + "'.");
+ }
+
+ if (getter && setter) {
+ const ArgumentData &setter_first_arg = setter->arguments.back()->get();
+ if (getter->return_type.name != setter_first_arg.type.name) {
+ // Special case for Node::set_name
+ bool whitelisted = getter->return_type.name == p_context.names_cache.string_name_type &&
+ setter_first_arg.type.name == p_context.names_cache.string_type;
+
+ TEST_FAIL_COND(!whitelisted,
+ "Return type from getter doesn't match first argument of setter, for property: '" + p_class.name + "." + String(p_prop.name) + "'.");
+ }
+ }
+
+ const TypeReference &prop_type_ref = getter ? getter->return_type : setter->arguments.back()->get().type;
+
+ const ExposedClass *prop_class = p_context.find_exposed_class(prop_type_ref);
+ if (prop_class) {
+ TEST_COND(prop_class->is_singleton,
+ "Property type is a singleton: '" + p_class.name + "." + String(p_prop.name) + "'.");
+ } else {
+ TEST_FAIL_COND(!p_context.has_type(prop_type_ref),
+ "Property type '" + prop_type_ref.name + "' not found: '" + p_class.name + "." + String(p_prop.name) + "'.");
+ }
+
+ if (getter) {
+ if (p_prop.index != -1) {
+ const ArgumentData &idx_arg = getter->arguments.front()->get();
+ if (idx_arg.type.name != p_context.names_cache.int_type) {
+ // If not an int, it can be an enum
+ TEST_COND(p_context.enum_types.find(idx_arg.type.name) < 0,
+ "Invalid type '" + idx_arg.type.name + "' for index argument of property getter: '" + p_class.name + "." + String(p_prop.name) + "'.");
+ }
+ }
+ }
+
+ if (setter) {
+ if (p_prop.index != -1) {
+ const ArgumentData &idx_arg = setter->arguments.front()->get();
+ if (idx_arg.type.name != p_context.names_cache.int_type) {
+ // Assume the index parameter is an enum
+ // If not an int, it can be an enum
+ TEST_COND(p_context.enum_types.find(idx_arg.type.name) < 0,
+ "Invalid type '" + idx_arg.type.name + "' for index argument of property setter: '" + p_class.name + "." + String(p_prop.name) + "'.");
+ }
+ }
+ }
+
+ TEST_END();
+}
+
+TestResult validate_method(const Context &p_context, const ExposedClass &p_class, const MethodData &p_method) {
+ TEST_START();
+
+ const ExposedClass *return_class = p_context.find_exposed_class(p_method.return_type);
+ if (return_class) {
+ TEST_COND(return_class->is_singleton,
+ "Method return type is a singleton: '" + p_class.name + "." + p_method.name + "'.");
+ }
+
+ for (const List<ArgumentData>::Element *F = p_method.arguments.front(); F; F = F->next()) {
+ const ArgumentData &arg = F->get();
+
+ const ExposedClass *arg_class = p_context.find_exposed_class(arg.type);
+ if (arg_class) {
+ TEST_COND(arg_class->is_singleton,
+ "Argument type is a singleton: '" + arg.name + "' of method '" + p_class.name + "." + p_method.name + "'.");
+ } else {
+ TEST_FAIL_COND(!p_context.has_type(arg.type),
+ "Argument type '" + arg.type.name + "' not found: '" + arg.name + "' of method" + p_class.name + "." + p_method.name + "'.");
+ }
+
+ if (arg.has_defval) {
+ TEST_COND(!arg_default_value_is_assignable_to_type(p_context, arg.defval, arg.type),
+ "Invalid default value for parameter '" + arg.name + "' of method '" + p_class.name + "." + p_method.name + "'.");
+ }
+ }
+
+ TEST_END();
+}
+
+TestResult validate_signal(const Context &p_context, const ExposedClass &p_class, const SignalData &p_signal) {
+ TEST_START();
+
+ for (const List<ArgumentData>::Element *F = p_signal.arguments.front(); F; F = F->next()) {
+ const ArgumentData &arg = F->get();
+
+ const ExposedClass *arg_class = p_context.find_exposed_class(arg.type);
+ if (arg_class) {
+ TEST_COND(arg_class->is_singleton,
+ "Argument class is a singleton: '" + arg.name + "' of signal" + p_class.name + "." + p_signal.name + "'.");
+ } else {
+ TEST_FAIL_COND(!p_context.has_type(arg.type),
+ "Argument type '" + arg.type.name + "' not found: '" + arg.name + "' of signal" + p_class.name + "." + p_signal.name + "'.");
+ }
+ }
+
+ TEST_END();
+}
+
+TestResult validate_class(const Context &p_context, const ExposedClass &p_exposed_class) {
+ TEST_START();
+
+ bool is_derived_type = p_exposed_class.base != StringName();
+
+ if (!is_derived_type) {
+ // Asserts about the base Object class
+ TEST_FAIL_COND(p_exposed_class.name != p_context.names_cache.object_class,
+ "Class '" + p_exposed_class.name + "' has no base class.");
+ TEST_FAIL_COND(!p_exposed_class.is_instantiable,
+ "Object class is not instantiable.");
+ TEST_FAIL_COND(p_exposed_class.api_type != ClassDB::API_CORE,
+ "Object class is API is not API_CORE.");
+ TEST_FAIL_COND(p_exposed_class.is_singleton,
+ "Object class is registered as a singleton.");
+ }
+
+ TEST_FAIL_COND(p_exposed_class.is_singleton && p_exposed_class.base != p_context.names_cache.object_class,
+ "Singleton base class '" + String(p_exposed_class.base) + "' is not Object, for class '" + p_exposed_class.name + "'.");
+
+ TEST_FAIL_COND(is_derived_type && !p_context.exposed_classes.has(p_exposed_class.base),
+ "Base type '" + p_exposed_class.base.operator String() + "' does not exist, for class '" + p_exposed_class.name + "'.");
+
+ for (const List<PropertyData>::Element *F = p_exposed_class.properties.front(); F; F = F->next()) {
+ TEST_CHECK(validate_property(p_context, p_exposed_class, F->get()));
+ }
+
+ for (const List<MethodData>::Element *F = p_exposed_class.methods.front(); F; F = F->next()) {
+ TEST_CHECK(validate_method(p_context, p_exposed_class, F->get()));
+ }
+
+ for (const List<SignalData>::Element *F = p_exposed_class.signals_.front(); F; F = F->next()) {
+ TEST_CHECK(validate_signal(p_context, p_exposed_class, F->get()));
+ }
+
+ TEST_END();
+}
+
+TestResult add_exposed_classes(Context &r_context) {
+ TEST_START();
+
+ List<StringName> class_list;
+ ClassDB::get_class_list(&class_list);
+ class_list.sort_custom<StringName::AlphCompare>();
+
+ while (class_list.size()) {
+ StringName class_name = class_list.front()->get();
+
+ ClassDB::APIType api_type = ClassDB::get_api_type(class_name);
+
+ if (api_type == ClassDB::API_NONE) {
+ class_list.pop_front();
+ continue;
+ }
+
+ if (!ClassDB::is_class_exposed(class_name)) {
+ OS::get_singleton()->print("Ignoring class '%s' because it's not exposed\n", String(class_name).utf8().get_data());
+ class_list.pop_front();
+ continue;
+ }
+
+ if (!ClassDB::is_class_enabled(class_name)) {
+ OS::get_singleton()->print("Ignoring class '%s' because it's not enabled\n", String(class_name).utf8().get_data());
+ class_list.pop_front();
+ continue;
+ }
+
+ ClassDB::ClassInfo *class_info = ClassDB::classes.getptr(class_name);
+
+ ExposedClass exposed_class;
+ exposed_class.name = class_name;
+ exposed_class.api_type = api_type;
+ exposed_class.is_singleton = Engine::get_singleton()->has_singleton(class_name);
+ exposed_class.is_instantiable = class_info->creation_func && !exposed_class.is_singleton;
+ exposed_class.is_reference = ClassDB::is_parent_class(class_name, "Reference");
+ exposed_class.base = ClassDB::get_parent_class(class_name);
+
+ // Add properties
+
+ List<PropertyInfo> property_list;
+ ClassDB::get_property_list(class_name, &property_list, true);
+
+ Map<StringName, StringName> accessor_methods;
+
+ for (const List<PropertyInfo>::Element *E = property_list.front(); E; E = E->next()) {
+ const PropertyInfo &property = E->get();
+
+ if (property.usage & PROPERTY_USAGE_GROUP || property.usage & PROPERTY_USAGE_SUBGROUP || property.usage & PROPERTY_USAGE_CATEGORY) {
+ continue;
+ }
+
+ PropertyData prop;
+ prop.name = property.name;
+ prop.setter = ClassDB::get_property_setter(class_name, prop.name);
+ prop.getter = ClassDB::get_property_getter(class_name, prop.name);
+
+ if (prop.setter != StringName()) {
+ accessor_methods[prop.setter] = prop.name;
+ }
+ if (prop.getter != StringName()) {
+ accessor_methods[prop.getter] = prop.name;
+ }
+
+ bool valid = false;
+ prop.index = ClassDB::get_property_index(class_name, prop.name, &valid);
+ TEST_FAIL_COND(!valid, "Invalid property: '" + exposed_class.name + "." + String(prop.name) + "'.");
+
+ exposed_class.properties.push_back(prop);
+ }
+
+ // Add methods
+
+ List<MethodInfo> virtual_method_list;
+ ClassDB::get_virtual_methods(class_name, &virtual_method_list, true);
+
+ List<MethodInfo> method_list;
+ ClassDB::get_method_list(class_name, &method_list, true);
+ method_list.sort();
+
+ for (List<MethodInfo>::Element *E = method_list.front(); E; E = E->next()) {
+ const MethodInfo &method_info = E->get();
+
+ int argc = method_info.arguments.size();
+
+ if (method_info.name.empty()) {
+ continue;
+ }
+
+ MethodData method;
+ method.name = method_info.name;
+
+ if (method_info.flags & METHOD_FLAG_VIRTUAL) {
+ method.is_virtual = true;
+ }
+
+ PropertyInfo return_info = method_info.return_val;
+
+ MethodBind *m = method.is_virtual ? nullptr : ClassDB::get_method(class_name, method_info.name);
+
+ method.is_vararg = m && m->is_vararg();
+
+ if (!m && !method.is_virtual) {
+ TEST_FAIL_COND(!virtual_method_list.find(method_info),
+ "Missing MethodBind for non-virtual method: '" + exposed_class.name + "." + method.name + "'.");
+
+ // A virtual method without the virtual flag. This is a special case.
+
+ // The method Object.free is registered as a virtual method, but without the virtual flag.
+ // This is because this method is not supposed to be overridden, but called.
+ // We assume the return type is void.
+ method.return_type.name = r_context.names_cache.void_type;
+
+ // Actually, more methods like this may be added in the future, which could return
+ // something different. Let's put this check to notify us if that ever happens.
+ if (exposed_class.name != r_context.names_cache.object_class || String(method.name) != "free") {
+ WARN_PRINT("Notification: New unexpected virtual non-overridable method found."
+ " We only expected Object.free, but found '" +
+ exposed_class.name + "." + method.name + "'.");
+ }
+ } else if (return_info.type == Variant::INT && return_info.usage & PROPERTY_USAGE_CLASS_IS_ENUM) {
+ method.return_type.name = return_info.class_name;
+ method.return_type.is_enum = true;
+ } else if (return_info.class_name != StringName()) {
+ method.return_type.name = return_info.class_name;
+
+ bool bad_reference_hint = !method.is_virtual && return_info.hint != PROPERTY_HINT_RESOURCE_TYPE &&
+ ClassDB::is_parent_class(return_info.class_name, r_context.names_cache.reference_class);
+ TEST_COND(bad_reference_hint, String() + "Return type is reference but hint is not '" _STR(PROPERTY_HINT_RESOURCE_TYPE) "'." +
+ " Are you returning a reference type by pointer? Method: '" +
+ exposed_class.name + "." + method.name + "'.");
+ } else if (return_info.hint == PROPERTY_HINT_RESOURCE_TYPE) {
+ method.return_type.name = return_info.hint_string;
+ } else if (return_info.type == Variant::NIL && return_info.usage & PROPERTY_USAGE_NIL_IS_VARIANT) {
+ method.return_type.name = r_context.names_cache.variant_type;
+ } else if (return_info.type == Variant::NIL) {
+ method.return_type.name = r_context.names_cache.void_type;
+ } else {
+ // NOTE: We don't care about the size and sign of int and float in these tests
+ method.return_type.name = Variant::get_type_name(return_info.type);
+ }
+
+ for (int i = 0; i < argc; i++) {
+ PropertyInfo arg_info = method_info.arguments[i];
+
+ String orig_arg_name = arg_info.name;
+
+ ArgumentData arg;
+ arg.name = orig_arg_name;
+
+ if (arg_info.type == Variant::INT && arg_info.usage & PROPERTY_USAGE_CLASS_IS_ENUM) {
+ arg.type.name = arg_info.class_name;
+ arg.type.is_enum = true;
+ } else if (arg_info.class_name != StringName()) {
+ arg.type.name = arg_info.class_name;
+ } else if (arg_info.hint == PROPERTY_HINT_RESOURCE_TYPE) {
+ arg.type.name = arg_info.hint_string;
+ } else if (arg_info.type == Variant::NIL) {
+ arg.type.name = r_context.names_cache.variant_type;
+ } else {
+ // NOTE: We don't care about the size and sign of int and float in these tests
+ arg.type.name = Variant::get_type_name(arg_info.type);
+ }
+
+ if (m && m->has_default_argument(i)) {
+ arg.has_defval = true;
+ arg.defval = m->get_default_argument(i);
+ }
+
+ method.arguments.push_back(arg);
+ }
+
+ if (method.is_vararg) {
+ ArgumentData vararg;
+ vararg.type.name = r_context.names_cache.vararg_stub_type;
+ vararg.name = "@varargs@";
+ method.arguments.push_back(vararg);
+ }
+
+ TEST_COND(exposed_class.find_property_by_name(method.name),
+ "Method name conflicts with property: '" + String(class_name) + "." + String(method.name) + "'.");
+
+ // Classes starting with an underscore are ignored unless they're used as a property setter or getter
+ if (!method.is_virtual && String(method.name)[0] == '_') {
+ for (const List<PropertyData>::Element *F = exposed_class.properties.front(); F; F = F->next()) {
+ const PropertyData &prop = F->get();
+
+ if (prop.setter == method.name || prop.getter == method.name) {
+ exposed_class.methods.push_back(method);
+ break;
+ }
+ }
+ } else {
+ exposed_class.methods.push_back(method);
+ }
+ }
+
+ // Add signals
+
+ const HashMap<StringName, MethodInfo> &signal_map = class_info->signal_map;
+ const StringName *k = nullptr;
+
+ while ((k = signal_map.next(k))) {
+ SignalData signal;
+
+ const MethodInfo &method_info = signal_map.get(*k);
+
+ signal.name = method_info.name;
+
+ int argc = method_info.arguments.size();
+
+ for (int i = 0; i < argc; i++) {
+ PropertyInfo arg_info = method_info.arguments[i];
+
+ String orig_arg_name = arg_info.name;
+
+ ArgumentData arg;
+ arg.name = orig_arg_name;
+
+ if (arg_info.type == Variant::INT && arg_info.usage & PROPERTY_USAGE_CLASS_IS_ENUM) {
+ arg.type.name = arg_info.class_name;
+ arg.type.is_enum = true;
+ } else if (arg_info.class_name != StringName()) {
+ arg.type.name = arg_info.class_name;
+ } else if (arg_info.hint == PROPERTY_HINT_RESOURCE_TYPE) {
+ arg.type.name = arg_info.hint_string;
+ } else if (arg_info.type == Variant::NIL) {
+ arg.type.name = r_context.names_cache.variant_type;
+ } else {
+ // NOTE: We don't care about the size and sign of int and float in these tests
+ arg.type.name = Variant::get_type_name(arg_info.type);
+ }
+
+ signal.arguments.push_back(arg);
+ }
+
+ bool method_conflict = exposed_class.find_property_by_name(signal.name);
+
+ if (method_conflict || exposed_class.find_method_by_name(signal.name)) {
+ // TODO:
+ // ClassDB allows signal names that conflict with method or property names.
+ // However registering a signal with a conflicting name is still considered wrong.
+ // Unfortunately there are some existing cases that are yet to be fixed.
+ // Until those are fixed we will print a warning instead of failing the test.
+ WARN_PRINT("Signal name conflicts with " + String(method_conflict ? "method" : "property") +
+ ": '" + String(class_name) + "." + String(signal.name) + "'.");
+ }
+
+ exposed_class.signals_.push_back(signal);
+ }
+
+ // Add enums and constants
+
+ List<String> constants;
+ ClassDB::get_integer_constant_list(class_name, &constants, true);
+
+ const HashMap<StringName, List<StringName>> &enum_map = class_info->enum_map;
+ k = nullptr;
+
+ while ((k = enum_map.next(k))) {
+ EnumData enum_;
+ enum_.name = *k;
+
+ const List<StringName> &enum_constants = enum_map.get(*k);
+ for (const List<StringName>::Element *E = enum_constants.front(); E; E = E->next()) {
+ const StringName &constant_name = E->get();
+ int *value = class_info->constant_map.getptr(constant_name);
+ TEST_FAIL_COND(!value, "Missing enum constant value: '" +
+ String(class_name) + "." + String(enum_.name) + "." + String(constant_name) + "'.");
+ constants.erase(constant_name);
+
+ ConstantData constant;
+ constant.name = constant_name;
+ constant.value = *value;
+
+ enum_.constants.push_back(constant);
+ }
+
+ exposed_class.enums.push_back(enum_);
+
+ r_context.enum_types.push_back(String(class_name) + "." + String(*k));
+ }
+
+ for (const List<String>::Element *E = constants.front(); E; E = E->next()) {
+ const String &constant_name = E->get();
+ int *value = class_info->constant_map.getptr(StringName(E->get()));
+ TEST_FAIL_COND(!value, "Missing enum constant value: '" + String(class_name) + "." + String(constant_name) + "'.");
+
+ ConstantData constant;
+ constant.name = constant_name;
+ constant.value = *value;
+
+ exposed_class.constants.push_back(constant);
+ }
+
+ r_context.exposed_classes.insert(class_name, exposed_class);
+ class_list.pop_front();
+ }
+
+ TEST_END();
+}
+
+void add_builtin_types(Context &r_context) {
+ // NOTE: We don't care about the size and sign of int and float in these tests
+ for (int i = 0; i < Variant::VARIANT_MAX; i++) {
+ r_context.builtin_types.push_back(Variant::get_type_name(Variant::Type(i)));
+ }
+
+ r_context.builtin_types.push_back(_STR(Variant));
+ r_context.builtin_types.push_back(r_context.names_cache.vararg_stub_type);
+ r_context.builtin_types.push_back("void");
+}
+
+void add_global_enums(Context &r_context) {
+ int global_constants_count = GlobalConstants::get_global_constant_count();
+
+ if (global_constants_count > 0) {
+ for (int i = 0; i < global_constants_count; i++) {
+ StringName enum_name = GlobalConstants::get_global_constant_enum(i);
+
+ if (enum_name != StringName()) {
+ ConstantData constant;
+ constant.name = GlobalConstants::get_global_constant_name(i);
+ constant.value = GlobalConstants::get_global_constant_value(i);
+
+ EnumData enum_;
+ enum_.name = enum_name;
+ List<EnumData>::Element *enum_match = r_context.global_enums.find(enum_);
+ if (enum_match) {
+ enum_match->get().constants.push_back(constant);
+ } else {
+ enum_.constants.push_back(constant);
+ r_context.global_enums.push_back(enum_);
+ }
+ }
+ }
+
+ for (List<EnumData>::Element *E = r_context.global_enums.front(); E; E = E->next()) {
+ r_context.enum_types.push_back(E->get().name);
+ }
+ }
+
+ // HARDCODED
+ List<StringName> hardcoded_enums;
+ hardcoded_enums.push_back("Vector2.Axis");
+ hardcoded_enums.push_back("Vector2i.Axis");
+ hardcoded_enums.push_back("Vector3.Axis");
+ hardcoded_enums.push_back("Vector3i.Axis");
+ for (List<StringName>::Element *E = hardcoded_enums.front(); E; E = E->next()) {
+ // These enums are not generated and must be written manually (e.g.: Vector3.Axis)
+ // Here, we assume core types do not begin with underscore
+ r_context.enum_types.push_back(E->get());
+ }
+}
+
+TestResult run_class_db_tests() {
+ TEST_START();
+
+ Context context;
+
+ TEST_FAIL_CHECK(add_exposed_classes(context));
+ add_builtin_types(context);
+ add_global_enums(context);
+
+ const ExposedClass *object_class = context.find_exposed_class(context.names_cache.object_class);
+ TEST_FAIL_COND(!object_class, "Object class not found.");
+ TEST_FAIL_COND(object_class->base != StringName(),
+ "Object class derives from another class: '" + object_class->base + "'.");
+
+ for (ExposedClasses::Element E = context.exposed_classes.front(); E; E = E.next()) {
+ TEST_CHECK(validate_class(context, E.value()));
+ }
+
+ TEST_END();
+}
+
+MainLoop *test() {
+ TestResult pass = run_class_db_tests();
+
+ OS::get_singleton()->print("ClassDB tests: %s\n", pass == TestResult::PASS ? "PASS" : "FAILED");
+
+ if (pass == TestResult::FAILED) {
+ OS::get_singleton()->set_exit_code(pass == TestResult::PASS ? 0 : 1);
+ }
+
+ return nullptr;
+}
+
+} // namespace TestClassDB
diff --git a/main/tests/test_class_db.h b/main/tests/test_class_db.h
new file mode 100644
index 0000000000..1a31cfb01b
--- /dev/null
+++ b/main/tests/test_class_db.h
@@ -0,0 +1,42 @@
+/*************************************************************************/
+/* test_class_db.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef GODOT_TEST_CLASS_DB_H
+#define GODOT_TEST_CLASS_DB_H
+
+#include "core/os/main_loop.h"
+
+namespace TestClassDB {
+
+MainLoop *test();
+
+}
+
+#endif //GODOT_TEST_CLASS_DB_H
diff --git a/main/tests/test_main.cpp b/main/tests/test_main.cpp
index eb60372e6c..0bb8367240 100644
--- a/main/tests/test_main.cpp
+++ b/main/tests/test_main.cpp
@@ -35,6 +35,7 @@
#ifdef DEBUG_ENABLED
#include "test_astar.h"
+#include "test_class_db.h"
#include "test_gdscript.h"
#include "test_gui.h"
#include "test_math.h"
@@ -54,6 +55,7 @@ const char **tests_get_names() {
"physics_3d",
"render",
"oa_hash_map",
+ "class_db",
"gui",
"shaderlang",
"gd_tokenizer",
@@ -93,6 +95,10 @@ MainLoop *test_main(String p_test, const List<String> &p_args) {
return TestOAHashMap::test();
}
+ if (p_test == "class_db") {
+ return TestClassDB::test();
+ }
+
#ifndef _3D_DISABLED
if (p_test == "gui") {
return TestGUI::test();
diff --git a/main/tests/test_oa_hash_map.cpp b/main/tests/test_oa_hash_map.cpp
index cae143bb5d..9182f66b61 100644
--- a/main/tests/test_oa_hash_map.cpp
+++ b/main/tests/test_oa_hash_map.cpp
@@ -35,6 +35,37 @@
namespace TestOAHashMap {
+struct CountedItem {
+ static int count;
+
+ int id = -1;
+ bool destroyed = false;
+
+ CountedItem() {
+ count++;
+ }
+
+ CountedItem(int p_id) :
+ id(p_id) {
+ count++;
+ }
+
+ CountedItem(const CountedItem &p_other) :
+ id(p_other.id) {
+ count++;
+ }
+
+ CountedItem &operator=(const CountedItem &p_other) = default;
+
+ ~CountedItem() {
+ CRASH_COND(destroyed);
+ count--;
+ destroyed = true;
+ }
+};
+
+int CountedItem::count;
+
MainLoop *test() {
OS::get_singleton()->print("\n\n\nHello from test\n");
@@ -152,6 +183,116 @@ MainLoop *test() {
map.set(5, 1);
}
+ // test memory management of items, should not crash or leak items
+ {
+ // Exercise different patterns of removal
+ for (int i = 0; i < 4; ++i) {
+ {
+ OAHashMap<String, CountedItem> map;
+ int id = 0;
+ for (int j = 0; j < 100; ++j) {
+ map.insert(itos(j), CountedItem(id));
+ }
+ if (i <= 1) {
+ for (int j = 0; j < 100; ++j) {
+ map.remove(itos(j));
+ }
+ }
+ if (i % 2 == 0) {
+ map.clear();
+ }
+ }
+
+ if (CountedItem::count != 0) {
+ OS::get_singleton()->print("%d != 0 (not performing the other test sub-cases, breaking...)\n", CountedItem::count);
+ break;
+ }
+ }
+ }
+
+ // Test map with 0 capacity.
+ {
+ OAHashMap<int, String> original_map(0);
+ original_map.set(1, "1");
+ OS::get_singleton()->print("OAHashMap 0 capacity initialization passed.\n");
+ }
+
+ // Test copy constructor.
+ {
+ OAHashMap<int, String> original_map;
+ original_map.set(1, "1");
+ original_map.set(2, "2");
+ original_map.set(3, "3");
+ original_map.set(4, "4");
+ original_map.set(5, "5");
+
+ OAHashMap<int, String> map_copy(original_map);
+
+ bool pass = true;
+ for (
+ OAHashMap<int, String>::Iterator it = original_map.iter();
+ it.valid;
+ it = original_map.next_iter(it)) {
+ if (map_copy.lookup_ptr(*it.key) == nullptr) {
+ pass = false;
+ }
+ if (*it.value != *map_copy.lookup_ptr(*it.key)) {
+ pass = false;
+ }
+ }
+ if (pass) {
+ OS::get_singleton()->print("OAHashMap copy constructor test passed.\n");
+ } else {
+ OS::get_singleton()->print("OAHashMap copy constructor test FAILED.\n");
+ }
+
+ map_copy.set(1, "Random String");
+ if (*map_copy.lookup_ptr(1) == *original_map.lookup_ptr(1)) {
+ OS::get_singleton()->print("OAHashMap copy constructor, atomic copy test FAILED.\n");
+ } else {
+ OS::get_singleton()->print("OAHashMap copy constructor, atomic copy test passed.\n");
+ }
+ }
+
+ // Test assign operator.
+ {
+ OAHashMap<int, String> original_map;
+ original_map.set(1, "1");
+ original_map.set(2, "2");
+ original_map.set(3, "3");
+ original_map.set(4, "4");
+ original_map.set(5, "5");
+
+ OAHashMap<int, String> map_copy(100000);
+ map_copy.set(1, "Just a string.");
+ map_copy = original_map;
+
+ bool pass = true;
+ for (
+ OAHashMap<int, String>::Iterator it = map_copy.iter();
+ it.valid;
+ it = map_copy.next_iter(it)) {
+ if (original_map.lookup_ptr(*it.key) == nullptr) {
+ pass = false;
+ }
+ if (*it.value != *original_map.lookup_ptr(*it.key)) {
+ pass = false;
+ }
+ }
+ if (pass) {
+ OS::get_singleton()->print("OAHashMap assign operation test passed.\n");
+ } else {
+ OS::get_singleton()->print("OAHashMap assign operation test FAILED.\n");
+ }
+
+ map_copy.set(1, "Random String");
+ if (*map_copy.lookup_ptr(1) == *original_map.lookup_ptr(1)) {
+ OS::get_singleton()->print("OAHashMap assign operation atomic copy test FAILED.\n");
+ } else {
+ OS::get_singleton()->print("OAHashMap assign operation atomic copy test passed.\n");
+ }
+ }
+
return nullptr;
}
diff --git a/methods.py b/methods.py
index 805ae256c3..46b58a13cd 100644
--- a/methods.py
+++ b/methods.py
@@ -137,37 +137,47 @@ def parse_cg_file(fname, uniforms, sizes, conditionals):
fs.close()
-def detect_modules():
+def detect_modules(at_path):
+ module_list = {} # name : path
- module_list = []
+ modules_glob = os.path.join(at_path, "*")
+ files = glob.glob(modules_glob)
+ files.sort() # so register_module_types does not change that often, and also plugins are registered in alphabetic order
+
+ for x in files:
+ if not is_module(x):
+ continue
+ name = os.path.basename(x)
+ path = x.replace("\\", "/") # win32
+ module_list[name] = path
+
+ return module_list
+
+
+def is_module(path):
+ return os.path.isdir(path) and os.path.exists(path + "/config.py")
+
+
+def write_modules(module_list):
includes_cpp = ""
+ preregister_cpp = ""
register_cpp = ""
unregister_cpp = ""
- preregister_cpp = ""
- files = glob.glob("modules/*")
- files.sort() # so register_module_types does not change that often, and also plugins are registered in alphabetic order
- for x in files:
- if not os.path.isdir(x):
- continue
- if not os.path.exists(x + "/config.py"):
- continue
- x = x.replace("modules/", "") # rest of world
- x = x.replace("modules\\", "") # win32
- module_list.append(x)
+ for name, path in module_list.items():
try:
- with open("modules/" + x + "/register_types.h"):
- includes_cpp += '#include "modules/' + x + '/register_types.h"\n'
- register_cpp += "#ifdef MODULE_" + x.upper() + "_ENABLED\n"
- register_cpp += "\tregister_" + x + "_types();\n"
- register_cpp += "#endif\n"
- preregister_cpp += "#ifdef MODULE_" + x.upper() + "_ENABLED\n"
- preregister_cpp += "#ifdef MODULE_" + x.upper() + "_HAS_PREREGISTER\n"
- preregister_cpp += "\tpreregister_" + x + "_types();\n"
+ with open(os.path.join(path, "register_types.h")):
+ includes_cpp += '#include "' + path + '/register_types.h"\n'
+ preregister_cpp += "#ifdef MODULE_" + name.upper() + "_ENABLED\n"
+ preregister_cpp += "#ifdef MODULE_" + name.upper() + "_HAS_PREREGISTER\n"
+ preregister_cpp += "\tpreregister_" + name + "_types();\n"
preregister_cpp += "#endif\n"
preregister_cpp += "#endif\n"
- unregister_cpp += "#ifdef MODULE_" + x.upper() + "_ENABLED\n"
- unregister_cpp += "\tunregister_" + x + "_types();\n"
+ register_cpp += "#ifdef MODULE_" + name.upper() + "_ENABLED\n"
+ register_cpp += "\tregister_" + name + "_types();\n"
+ register_cpp += "#endif\n"
+ unregister_cpp += "#ifdef MODULE_" + name.upper() + "_ENABLED\n"
+ unregister_cpp += "\tunregister_" + name + "_types();\n"
unregister_cpp += "#endif\n"
except IOError:
pass
@@ -202,7 +212,18 @@ void unregister_module_types() {
with open("modules/register_module_types.gen.cpp", "w") as f:
f.write(modules_cpp)
- return module_list
+
+def convert_custom_modules_path(path):
+ if not path:
+ return path
+ err_msg = "Build option 'custom_modules' must %s"
+ if not os.path.isdir(path):
+ raise ValueError(err_msg % "point to an existing directory.")
+ if os.path.realpath(path) == os.path.realpath("modules"):
+ raise ValueError(err_msg % "be a directory other than built-in `modules` directory.")
+ if is_module(path):
+ raise ValueError(err_msg % "point to a directory with modules, not a single module.")
+ return os.path.realpath(os.path.expanduser(path))
def disable_module(self):
diff --git a/misc/scons/site_tools/compilation_db.py b/misc/scons/compilation_db.py
index 87db32adc9..87db32adc9 100644
--- a/misc/scons/site_tools/compilation_db.py
+++ b/misc/scons/compilation_db.py
diff --git a/modules/SCsub b/modules/SCsub
index fb46c5f877..9155a53eaf 100644
--- a/modules/SCsub
+++ b/modules/SCsub
@@ -3,6 +3,7 @@
Import("env")
import modules_builders
+import os
env_modules = env.Clone()
@@ -13,16 +14,20 @@ env.CommandNoCache("modules_enabled.gen.h", Value(env.module_list), modules_buil
vs_sources = []
# libmodule_<name>.a for each active module.
-for module in env.module_list:
+for name, path in env.module_list.items():
env.modules_sources = []
- SConscript(module + "/SCsub")
+
+ if not os.path.isabs(path):
+ SConscript(name + "/SCsub") # Built-in.
+ else:
+ SConscript(path + "/SCsub") # Custom.
# Some modules are not linked automatically but can be enabled optionally
# on iOS, so we handle those specially.
- if env["platform"] == "iphone" and module in ["arkit", "camera"]:
+ if env["platform"] == "iphone" and name in ["arkit", "camera"]:
continue
- lib = env_modules.add_library("module_%s" % module, env.modules_sources)
+ lib = env_modules.add_library("module_%s" % name, env.modules_sources)
env.Prepend(LIBS=[lib])
if env["vsproj"]:
vs_sources += env.modules_sources
diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp
index 2fca7fe633..9aac7ba9e4 100644
--- a/modules/bullet/rigid_body_bullet.cpp
+++ b/modules/bullet/rigid_body_bullet.cpp
@@ -445,11 +445,6 @@ void RigidBodyBullet::assert_no_constraints() {
if (btBody->getNumConstraintRefs()) {
WARN_PRINT("A body with a joints is destroyed. Please check the implementation in order to destroy the joint before the body.");
}
- /*for(int i = btBody->getNumConstraintRefs()-1; 0<=i; --i){
- btTypedConstraint* btConst = btBody->getConstraintRef(i);
- JointBullet* joint = static_cast<JointBullet*>( btConst->getUserConstraintPtr() );
- space->removeConstraint(joint);
- }*/
}
void RigidBodyBullet::set_activation_state(bool p_active) {
diff --git a/modules/camera/camera_win.cpp b/modules/camera/camera_win.cpp
index 875f0b26bc..1646644be3 100644
--- a/modules/camera/camera_win.cpp
+++ b/modules/camera/camera_win.cpp
@@ -53,9 +53,9 @@ public:
void deactivate_feed();
};
-CameraFeedWindows::CameraFeedWindows(){
+CameraFeedWindows::CameraFeedWindows() {
///@TODO implement this, should store information about our available camera
-};
+}
CameraFeedWindows::~CameraFeedWindows() {
// make sure we stop recording if we are!
@@ -75,16 +75,16 @@ bool CameraFeedWindows::activate_feed() {
///@TODO we should probably have a callback method here that is being called by the
// camera API which provides frames and call back into the CameraServer to update our texture
-void CameraFeedWindows::deactivate_feed(){
+void CameraFeedWindows::deactivate_feed() {
///@TODO this should deactivate our camera and stop the process of capturing frames
-};
+}
//////////////////////////////////////////////////////////////////////////
// CameraWindows - Subclass for our camera server on windows
-void CameraWindows::add_active_cameras(){
+void CameraWindows::add_active_cameras() {
///@TODO scan through any active cameras and create CameraFeedWindows objects for them
-};
+}
CameraWindows::CameraWindows() {
// Find cameras active right now
@@ -92,7 +92,3 @@ CameraWindows::CameraWindows() {
// need to add something that will react to devices being connected/removed...
};
-
-CameraWindows::~CameraWindows(){
-
-};
diff --git a/modules/camera/camera_win.h b/modules/camera/camera_win.h
index 39a1b0b86f..bbc8880c12 100644
--- a/modules/camera/camera_win.h
+++ b/modules/camera/camera_win.h
@@ -40,7 +40,7 @@ private:
public:
CameraWindows();
- ~CameraWindows();
+ ~CameraWindows() {}
};
#endif /* CAMERAWIN_H */
diff --git a/modules/gdnative/gdnative/aabb.cpp b/modules/gdnative/gdnative/aabb.cpp
index 246e5d4e8d..7f22c7dfe3 100644
--- a/modules/gdnative/gdnative/aabb.cpp
+++ b/modules/gdnative/gdnative/aabb.cpp
@@ -37,6 +37,8 @@
extern "C" {
#endif
+static_assert(sizeof(godot_aabb) == sizeof(AABB), "AABB size mismatch");
+
void GDAPI godot_aabb_new(godot_aabb *r_dest, const godot_vector3 *p_pos, const godot_vector3 *p_size) {
const Vector3 *pos = (const Vector3 *)p_pos;
const Vector3 *size = (const Vector3 *)p_size;
diff --git a/modules/gdnative/gdnative/array.cpp b/modules/gdnative/gdnative/array.cpp
index 0c764ab8fd..59953f5182 100644
--- a/modules/gdnative/gdnative/array.cpp
+++ b/modules/gdnative/gdnative/array.cpp
@@ -41,6 +41,8 @@
extern "C" {
#endif
+static_assert(sizeof(godot_array) == sizeof(Array), "Array size mismatch");
+
void GDAPI godot_array_new(godot_array *r_dest) {
Array *dest = (Array *)r_dest;
memnew_placement(dest, Array);
@@ -100,9 +102,33 @@ void GDAPI godot_array_new_packed_string_array(godot_array *r_dest, const godot_
}
}
-void GDAPI godot_array_new_packed_real_array(godot_array *r_dest, const godot_packed_real_array *p_pra) {
+void GDAPI godot_array_new_packed_float32_array(godot_array *r_dest, const godot_packed_float32_array *p_pra) {
+ Array *dest = (Array *)r_dest;
+ Vector<float> *pca = (Vector<float> *)p_pra;
+ memnew_placement(dest, Array);
+ dest->resize(pca->size());
+
+ for (int i = 0; i < dest->size(); i++) {
+ Variant v = pca->operator[](i);
+ dest->operator[](i) = v;
+ }
+}
+
+void GDAPI godot_array_new_packed_float64_array(godot_array *r_dest, const godot_packed_float64_array *p_pra) {
+ Array *dest = (Array *)r_dest;
+ Vector<double> *pca = (Vector<double> *)p_pra;
+ memnew_placement(dest, Array);
+ dest->resize(pca->size());
+
+ for (int i = 0; i < dest->size(); i++) {
+ Variant v = pca->operator[](i);
+ dest->operator[](i) = v;
+ }
+}
+
+void GDAPI godot_array_new_packed_int32_array(godot_array *r_dest, const godot_packed_int32_array *p_pia) {
Array *dest = (Array *)r_dest;
- Vector<godot_real> *pca = (Vector<godot_real> *)p_pra;
+ Vector<int32_t> *pca = (Vector<int32_t> *)p_pia;
memnew_placement(dest, Array);
dest->resize(pca->size());
@@ -112,9 +138,9 @@ void GDAPI godot_array_new_packed_real_array(godot_array *r_dest, const godot_pa
}
}
-void GDAPI godot_array_new_packed_int_array(godot_array *r_dest, const godot_packed_int_array *p_pia) {
+void GDAPI godot_array_new_packed_int64_array(godot_array *r_dest, const godot_packed_int64_array *p_pia) {
Array *dest = (Array *)r_dest;
- Vector<godot_int> *pca = (Vector<godot_int> *)p_pia;
+ Vector<int64_t> *pca = (Vector<int64_t> *)p_pia;
memnew_placement(dest, Array);
dest->resize(pca->size());
diff --git a/modules/gdnative/gdnative/basis.cpp b/modules/gdnative/gdnative/basis.cpp
index 4f489287b9..990fd3795d 100644
--- a/modules/gdnative/gdnative/basis.cpp
+++ b/modules/gdnative/gdnative/basis.cpp
@@ -37,6 +37,8 @@
extern "C" {
#endif
+static_assert(sizeof(godot_basis) == sizeof(Basis), "Basis size mismatch");
+
void GDAPI godot_basis_new_with_rows(godot_basis *r_dest, const godot_vector3 *p_x_axis, const godot_vector3 *p_y_axis, const godot_vector3 *p_z_axis) {
const Vector3 *x_axis = (const Vector3 *)p_x_axis;
const Vector3 *y_axis = (const Vector3 *)p_y_axis;
diff --git a/modules/gdnative/gdnative/callable.cpp b/modules/gdnative/gdnative/callable.cpp
new file mode 100644
index 0000000000..868b324227
--- /dev/null
+++ b/modules/gdnative/gdnative/callable.cpp
@@ -0,0 +1,252 @@
+/*************************************************************************/
+/* callable.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "gdnative/callable.h"
+
+#include "core/callable.h"
+#include "core/resource.h"
+#include "core/variant.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static_assert(sizeof(godot_callable) == sizeof(Callable), "Callable size mismatch");
+static_assert(sizeof(godot_signal) == sizeof(Signal), "Signal size mismatch");
+
+// Callable
+
+void GDAPI godot_callable_new_with_object(godot_callable *r_dest, const godot_object *p_object, const godot_string_name *p_method) {
+ Callable *dest = (Callable *)r_dest;
+ const Object *object = (const Object *)p_object;
+ const StringName *method = (const StringName *)p_method;
+ memnew_placement(dest, Callable(object, *method));
+}
+
+void GDAPI godot_callable_new_with_object_id(godot_callable *r_dest, uint64_t p_objectid, const godot_string_name *p_method) {
+ Callable *dest = (Callable *)r_dest;
+ const StringName *method = (const StringName *)p_method;
+ memnew_placement(dest, Callable(ObjectID(p_objectid), *method));
+}
+
+void GDAPI godot_callable_new_copy(godot_callable *r_dest, const godot_callable *p_src) {
+ Callable *dest = (Callable *)r_dest;
+ const Callable *src = (const Callable *)p_src;
+ memnew_placement(dest, Callable(*src));
+}
+
+void GDAPI godot_callable_destroy(godot_callable *p_self) {
+ Callable *self = (Callable *)p_self;
+ self->~Callable();
+}
+
+godot_int GDAPI godot_callable_call(const godot_callable *p_self, const godot_variant **p_arguments, godot_int p_argcount, godot_variant *r_return_value) {
+ const Callable *self = (const Callable *)p_self;
+ const Variant **arguments = (const Variant **)p_arguments;
+ Variant *return_value = (Variant *)r_return_value;
+ Variant ret;
+ Callable::CallError err;
+ self->call(arguments, p_argcount, ret, err);
+ if (return_value)
+ (*return_value) = ret;
+ return (godot_int)err.error;
+}
+
+void GDAPI godot_callable_call_deferred(const godot_callable *p_self, const godot_variant **p_arguments, godot_int p_argcount) {
+ const Callable *self = (const Callable *)p_self;
+ const Variant **arguments = (const Variant **)p_arguments;
+ self->call_deferred(arguments, p_argcount);
+}
+
+godot_bool GDAPI godot_callable_is_null(const godot_callable *p_self) {
+ const Callable *self = (const Callable *)p_self;
+ return self->is_null();
+}
+
+godot_bool GDAPI godot_callable_is_custom(const godot_callable *p_self) {
+ const Callable *self = (const Callable *)p_self;
+ return self->is_custom();
+}
+
+godot_bool GDAPI godot_callable_is_standard(const godot_callable *p_self) {
+ const Callable *self = (const Callable *)p_self;
+ return self->is_standard();
+}
+
+godot_object GDAPI *godot_callable_get_object(const godot_callable *p_self) {
+ const Callable *self = (const Callable *)p_self;
+ return (godot_object *)self->get_object();
+}
+
+uint64_t GDAPI godot_callable_get_object_id(const godot_callable *p_self) {
+ const Callable *self = (const Callable *)p_self;
+ return (uint64_t)self->get_object_id();
+}
+
+godot_string_name GDAPI godot_callable_get_method(const godot_callable *p_self) {
+ godot_string_name raw_dest;
+ const Callable *self = (const Callable *)p_self;
+ StringName *dest = (StringName *)&raw_dest;
+ memnew_placement(dest, StringName(self->get_method()));
+ return raw_dest;
+}
+
+uint32_t GDAPI godot_callable_hash(const godot_callable *p_self) {
+ const Callable *self = (const Callable *)p_self;
+ return self->hash();
+}
+
+godot_string GDAPI godot_callable_as_string(const godot_callable *p_self) {
+ godot_string ret;
+ const Callable *self = (const Callable *)p_self;
+ memnew_placement(&ret, String(*self));
+ return ret;
+}
+
+godot_bool GDAPI godot_callable_operator_equal(const godot_callable *p_self, const godot_callable *p_other) {
+ const Callable *self = (const Callable *)p_self;
+ const Callable *other = (const Callable *)p_other;
+ return *self == *other;
+}
+
+godot_bool GDAPI godot_callable_operator_less(const godot_callable *p_self, const godot_callable *p_other) {
+ const Callable *self = (const Callable *)p_self;
+ const Callable *other = (const Callable *)p_other;
+ return *self < *other;
+}
+
+// Signal
+
+void GDAPI godot_signal_new_with_object(godot_signal *r_dest, const godot_object *p_object, const godot_string_name *p_name) {
+ Signal *dest = (Signal *)r_dest;
+ const Object *object = (const Object *)p_object;
+ const StringName *name = (const StringName *)p_name;
+ memnew_placement(dest, Signal(object, *name));
+}
+
+void GDAPI godot_signal_new_with_object_id(godot_signal *r_dest, uint64_t p_objectid, const godot_string_name *p_name) {
+ Signal *dest = (Signal *)r_dest;
+ const StringName *name = (const StringName *)p_name;
+ memnew_placement(dest, Signal(ObjectID(p_objectid), *name));
+}
+
+void GDAPI godot_signal_new_copy(godot_signal *r_dest, const godot_signal *p_src) {
+ Signal *dest = (Signal *)r_dest;
+ const Signal *src = (const Signal *)p_src;
+ memnew_placement(dest, Signal(*src));
+}
+
+void GDAPI godot_signal_destroy(godot_signal *p_self) {
+ Signal *self = (Signal *)p_self;
+ self->~Signal();
+}
+
+godot_int GDAPI godot_signal_emit(const godot_signal *p_self, const godot_variant **p_arguments, godot_int p_argcount) {
+ const Signal *self = (const Signal *)p_self;
+ const Variant **arguments = (const Variant **)p_arguments;
+ return (godot_int)self->emit(arguments, p_argcount);
+}
+
+godot_int GDAPI godot_signal_connect(godot_signal *p_self, const godot_callable *p_callable, const godot_array *p_binds, uint32_t p_flags) {
+ Signal *self = (Signal *)p_self;
+ const Callable *callable = (const Callable *)p_callable;
+ const Array *binds_ar = (const Array *)p_binds;
+ Vector<Variant> binds;
+ for (int i = 0; i < binds_ar->size(); i++) {
+ binds.push_back(binds_ar->get(i));
+ }
+ return (godot_int)self->connect(*callable, binds, p_flags);
+}
+
+void GDAPI godot_signal_disconnect(godot_signal *p_self, const godot_callable *p_callable) {
+ Signal *self = (Signal *)p_self;
+ const Callable *callable = (const Callable *)p_callable;
+ self->disconnect(*callable);
+}
+
+godot_bool GDAPI godot_signal_is_null(const godot_signal *p_self) {
+ const Signal *self = (const Signal *)p_self;
+ return self->is_null();
+}
+
+godot_bool GDAPI godot_signal_is_connected(const godot_signal *p_self, const godot_callable *p_callable) {
+ const Signal *self = (const Signal *)p_self;
+ const Callable *callable = (const Callable *)p_callable;
+ return self->is_connected(*callable);
+}
+
+godot_array GDAPI godot_signal_get_connections(const godot_signal *p_self) {
+ godot_array raw_dest;
+ const Signal *self = (const Signal *)p_self;
+ Array *dest = (Array *)&raw_dest;
+ memnew_placement(dest, Array(self->get_connections()));
+ return raw_dest;
+}
+
+godot_object GDAPI *godot_signal_get_object(const godot_signal *p_self) {
+ const Signal *self = (const Signal *)p_self;
+ return (godot_object *)self->get_object();
+}
+
+uint64_t GDAPI godot_signal_get_object_id(const godot_signal *p_self) {
+ const Signal *self = (const Signal *)p_self;
+ return (uint64_t)self->get_object_id();
+}
+
+godot_string_name GDAPI godot_signal_get_name(const godot_signal *p_self) {
+ godot_string_name raw_dest;
+ const Signal *self = (const Signal *)p_self;
+ StringName *dest = (StringName *)&raw_dest;
+ memnew_placement(dest, StringName(self->get_name()));
+ return raw_dest;
+}
+
+godot_string GDAPI godot_signal_as_string(const godot_signal *p_self) {
+ godot_string ret;
+ const Signal *self = (const Signal *)p_self;
+ memnew_placement(&ret, String(*self));
+ return ret;
+}
+
+godot_bool GDAPI godot_signal_operator_equal(const godot_signal *p_self, const godot_signal *p_other) {
+ const Signal *self = (const Signal *)p_self;
+ const Signal *other = (const Signal *)p_other;
+ return *self == *other;
+}
+
+godot_bool GDAPI godot_signal_operator_less(const godot_signal *p_self, const godot_signal *p_other) {
+ const Signal *self = (const Signal *)p_self;
+ const Signal *other = (const Signal *)p_other;
+ return *self < *other;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/modules/gdnative/gdnative/color.cpp b/modules/gdnative/gdnative/color.cpp
index d79170771a..c75e74daba 100644
--- a/modules/gdnative/gdnative/color.cpp
+++ b/modules/gdnative/gdnative/color.cpp
@@ -37,6 +37,8 @@
extern "C" {
#endif
+static_assert(sizeof(godot_color) == sizeof(Color), "Color size mismatch");
+
void GDAPI godot_color_new_rgba(godot_color *r_dest, const godot_real p_r, const godot_real p_g, const godot_real p_b, const godot_real p_a) {
Color *dest = (Color *)r_dest;
*dest = Color(p_r, p_g, p_b, p_a);
diff --git a/modules/gdnative/gdnative/dictionary.cpp b/modules/gdnative/gdnative/dictionary.cpp
index b145b88934..a126974815 100644
--- a/modules/gdnative/gdnative/dictionary.cpp
+++ b/modules/gdnative/gdnative/dictionary.cpp
@@ -39,6 +39,8 @@
extern "C" {
#endif
+static_assert(sizeof(godot_dictionary) == sizeof(Dictionary), "Dictionary size mismatch");
+
void GDAPI godot_dictionary_new(godot_dictionary *r_dest) {
Dictionary *dest = (Dictionary *)r_dest;
memnew_placement(dest, Dictionary);
diff --git a/modules/gdnative/gdnative/gdnative.cpp b/modules/gdnative/gdnative/gdnative.cpp
index 6b2b5b80a4..e94190b07b 100644
--- a/modules/gdnative/gdnative/gdnative.cpp
+++ b/modules/gdnative/gdnative/gdnative.cpp
@@ -165,7 +165,7 @@ void _gdnative_report_loading_error(const godot_object *p_library, const char *p
_err_print_error("gdnative_init", library->get_current_library_path().utf8().ptr(), 0, message.utf8().ptr());
}
-godot_object GDAPI *godot_instance_from_id(godot_int p_instance_id) {
+godot_object GDAPI *godot_instance_from_id(uint64_t p_instance_id) {
return (godot_object *)ObjectDB::get_instance(ObjectID(p_instance_id));
}
@@ -184,6 +184,11 @@ godot_object *godot_object_cast_to(const godot_object *p_object, void *p_class_t
return o->is_class_ptr(p_class_tag) ? (godot_object *)o : nullptr;
}
+uint64_t GDAPI godot_object_get_instance_id(const godot_object *p_object) {
+ const Object *o = (const Object *)p_object;
+ return (uint64_t)o->get_instance_id();
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/modules/gdnative/gdnative/node_path.cpp b/modules/gdnative/gdnative/node_path.cpp
index 93f43835c8..88ed650ebe 100644
--- a/modules/gdnative/gdnative/node_path.cpp
+++ b/modules/gdnative/gdnative/node_path.cpp
@@ -37,6 +37,8 @@
extern "C" {
#endif
+static_assert(sizeof(godot_node_path) == sizeof(NodePath), "NodePath size mismatch");
+
void GDAPI godot_node_path_new(godot_node_path *r_dest, const godot_string *p_from) {
NodePath *dest = (NodePath *)r_dest;
const String *from = (const String *)p_from;
diff --git a/modules/gdnative/gdnative/pool_arrays.cpp b/modules/gdnative/gdnative/packed_arrays.cpp
index 589b4d4dfe..675d66056a 100644
--- a/modules/gdnative/gdnative/pool_arrays.cpp
+++ b/modules/gdnative/gdnative/packed_arrays.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* pool_arrays.cpp */
+/* packed_arrays.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "gdnative/pool_arrays.h"
+#include "gdnative/packed_arrays.h"
#include "core/array.h"
@@ -42,6 +42,16 @@
extern "C" {
#endif
+static_assert(sizeof(godot_packed_byte_array) == sizeof(Vector<uint8_t>), "Vector<uint8_t> size mismatch");
+static_assert(sizeof(godot_packed_int32_array) == sizeof(Vector<int32_t>), "Vector<int32_t> size mismatch");
+static_assert(sizeof(godot_packed_int64_array) == sizeof(Vector<int64_t>), "Vector<int64_t> size mismatch");
+static_assert(sizeof(godot_packed_float32_array) == sizeof(Vector<float>), "Vector<float> size mismatch");
+static_assert(sizeof(godot_packed_float64_array) == sizeof(Vector<double>), "Vector<double> size mismatch");
+static_assert(sizeof(godot_packed_string_array) == sizeof(Vector<String>), "Vector<String> size mismatch");
+static_assert(sizeof(godot_packed_vector2_array) == sizeof(Vector<Vector2>), "Vector<Vector2> size mismatch");
+static_assert(sizeof(godot_packed_vector3_array) == sizeof(Vector<Vector3>), "Vector<Vector3> size mismatch");
+static_assert(sizeof(godot_packed_color_array) == sizeof(Vector<Color>), "Vector<Color> size mismatch");
+
#define memnew_placement_custom(m_placement, m_class, m_constr) _post_initialize(new (m_placement, sizeof(m_class), "") m_constr)
// byte
@@ -128,23 +138,191 @@ void GDAPI godot_packed_byte_array_destroy(godot_packed_byte_array *p_self) {
((Vector<uint8_t> *)p_self)->~Vector();
}
-// int
+// int32
+
+void GDAPI godot_packed_int32_array_new(godot_packed_int32_array *r_dest) {
+ Vector<int32_t> *dest = (Vector<int32_t> *)r_dest;
+ memnew_placement(dest, Vector<int32_t>);
+}
+
+void GDAPI godot_packed_int32_array_new_copy(godot_packed_int32_array *r_dest, const godot_packed_int32_array *p_src) {
+ Vector<int32_t> *dest = (Vector<int32_t> *)r_dest;
+ const Vector<int32_t> *src = (const Vector<int32_t> *)p_src;
+ memnew_placement(dest, Vector<int32_t>(*src));
+}
+
+void GDAPI godot_packed_int32_array_new_with_array(godot_packed_int32_array *r_dest, const godot_array *p_a) {
+ Vector<int32_t> *dest = (Vector<int32_t> *)r_dest;
+ Array *a = (Array *)p_a;
+ memnew_placement(dest, Vector<int32_t>);
+
+ dest->resize(a->size());
+ for (int i = 0; i < a->size(); i++) {
+ dest->set(i, (*a)[i]);
+ }
+}
+
+void GDAPI godot_packed_int32_array_append(godot_packed_int32_array *p_self, const int32_t p_data) {
+ Vector<int32_t> *self = (Vector<int32_t> *)p_self;
+ self->push_back(p_data);
+}
+
+void GDAPI godot_packed_int32_array_append_array(godot_packed_int32_array *p_self, const godot_packed_int32_array *p_array) {
+ Vector<int32_t> *self = (Vector<int32_t> *)p_self;
+ Vector<int32_t> *array = (Vector<int32_t> *)p_array;
+ self->append_array(*array);
+}
+
+godot_error GDAPI godot_packed_int32_array_insert(godot_packed_int32_array *p_self, const godot_int p_idx, const int32_t p_data) {
+ Vector<int32_t> *self = (Vector<int32_t> *)p_self;
+ return (godot_error)self->insert(p_idx, p_data);
+}
+
+void GDAPI godot_packed_int32_array_invert(godot_packed_int32_array *p_self) {
+ Vector<int32_t> *self = (Vector<int32_t> *)p_self;
+ self->invert();
+}
+
+void GDAPI godot_packed_int32_array_push_back(godot_packed_int32_array *p_self, const int32_t p_data) {
+ Vector<int32_t> *self = (Vector<int32_t> *)p_self;
+ self->push_back(p_data);
+}
+
+void GDAPI godot_packed_int32_array_remove(godot_packed_int32_array *p_self, const godot_int p_idx) {
+ Vector<int32_t> *self = (Vector<int32_t> *)p_self;
+ self->remove(p_idx);
+}
+
+void GDAPI godot_packed_int32_array_resize(godot_packed_int32_array *p_self, const godot_int p_size) {
+ Vector<int32_t> *self = (Vector<int32_t> *)p_self;
+ self->resize(p_size);
+}
+
+void GDAPI godot_packed_int32_array_set(godot_packed_int32_array *p_self, const godot_int p_idx, const int32_t p_data) {
+ Vector<int32_t> *self = (Vector<int32_t> *)p_self;
+ self->set(p_idx, p_data);
+}
+
+int32_t GDAPI godot_packed_int32_array_get(const godot_packed_int32_array *p_self, const godot_int p_idx) {
+ const Vector<int32_t> *self = (const Vector<int32_t> *)p_self;
+ return self->get(p_idx);
+}
+
+godot_int GDAPI godot_packed_int32_array_size(const godot_packed_int32_array *p_self) {
+ const Vector<int32_t> *self = (const Vector<int32_t> *)p_self;
+ return self->size();
+}
+
+godot_bool GDAPI godot_packed_int32_array_empty(const godot_packed_int32_array *p_self) {
+ const Vector<int32_t> *self = (const Vector<int32_t> *)p_self;
+ return self->empty();
+}
+
+void GDAPI godot_packed_int32_array_destroy(godot_packed_int32_array *p_self) {
+ ((Vector<int32_t> *)p_self)->~Vector();
+}
+
+// int64
+
+void GDAPI godot_packed_int64_array_new(godot_packed_int64_array *r_dest) {
+ Vector<int64_t> *dest = (Vector<int64_t> *)r_dest;
+ memnew_placement(dest, Vector<int64_t>);
+}
+
+void GDAPI godot_packed_int64_array_new_copy(godot_packed_int64_array *r_dest, const godot_packed_int64_array *p_src) {
+ Vector<int64_t> *dest = (Vector<int64_t> *)r_dest;
+ const Vector<int64_t> *src = (const Vector<int64_t> *)p_src;
+ memnew_placement(dest, Vector<int64_t>(*src));
+}
+
+void GDAPI godot_packed_int64_array_new_with_array(godot_packed_int64_array *r_dest, const godot_array *p_a) {
+ Vector<int64_t> *dest = (Vector<int64_t> *)r_dest;
+ Array *a = (Array *)p_a;
+ memnew_placement(dest, Vector<int64_t>);
+
+ dest->resize(a->size());
+ for (int i = 0; i < a->size(); i++) {
+ dest->set(i, (*a)[i]);
+ }
+}
+
+void GDAPI godot_packed_int64_array_append(godot_packed_int64_array *p_self, const int64_t p_data) {
+ Vector<int64_t> *self = (Vector<int64_t> *)p_self;
+ self->push_back(p_data);
+}
+
+void GDAPI godot_packed_int64_array_append_array(godot_packed_int64_array *p_self, const godot_packed_int64_array *p_array) {
+ Vector<int64_t> *self = (Vector<int64_t> *)p_self;
+ Vector<int64_t> *array = (Vector<int64_t> *)p_array;
+ self->append_array(*array);
+}
+
+godot_error GDAPI godot_packed_int64_array_insert(godot_packed_int64_array *p_self, const godot_int p_idx, const int64_t p_data) {
+ Vector<int64_t> *self = (Vector<int64_t> *)p_self;
+ return (godot_error)self->insert(p_idx, p_data);
+}
+
+void GDAPI godot_packed_int64_array_invert(godot_packed_int64_array *p_self) {
+ Vector<int64_t> *self = (Vector<int64_t> *)p_self;
+ self->invert();
+}
+
+void GDAPI godot_packed_int64_array_push_back(godot_packed_int64_array *p_self, const int64_t p_data) {
+ Vector<int64_t> *self = (Vector<int64_t> *)p_self;
+ self->push_back(p_data);
+}
+
+void GDAPI godot_packed_int64_array_remove(godot_packed_int64_array *p_self, const godot_int p_idx) {
+ Vector<int64_t> *self = (Vector<int64_t> *)p_self;
+ self->remove(p_idx);
+}
+
+void GDAPI godot_packed_int64_array_resize(godot_packed_int64_array *p_self, const godot_int p_size) {
+ Vector<int64_t> *self = (Vector<int64_t> *)p_self;
+ self->resize(p_size);
+}
+
+void GDAPI godot_packed_int64_array_set(godot_packed_int64_array *p_self, const godot_int p_idx, const int64_t p_data) {
+ Vector<int64_t> *self = (Vector<int64_t> *)p_self;
+ self->set(p_idx, p_data);
+}
+
+int64_t GDAPI godot_packed_int64_array_get(const godot_packed_int64_array *p_self, const godot_int p_idx) {
+ const Vector<int64_t> *self = (const Vector<int64_t> *)p_self;
+ return self->get(p_idx);
+}
+
+godot_int GDAPI godot_packed_int64_array_size(const godot_packed_int64_array *p_self) {
+ const Vector<int64_t> *self = (const Vector<int64_t> *)p_self;
+ return self->size();
+}
+
+godot_bool GDAPI godot_packed_int64_array_empty(const godot_packed_int64_array *p_self) {
+ const Vector<int64_t> *self = (const Vector<int64_t> *)p_self;
+ return self->empty();
+}
+
+void GDAPI godot_packed_int64_array_destroy(godot_packed_int64_array *p_self) {
+ ((Vector<int64_t> *)p_self)->~Vector();
+}
+
+// float32
-void GDAPI godot_packed_int_array_new(godot_packed_int_array *r_dest) {
- Vector<godot_int> *dest = (Vector<godot_int> *)r_dest;
- memnew_placement(dest, Vector<godot_int>);
+void GDAPI godot_packed_float32_array_new(godot_packed_float32_array *r_dest) {
+ Vector<float> *dest = (Vector<float> *)r_dest;
+ memnew_placement(dest, Vector<float>);
}
-void GDAPI godot_packed_int_array_new_copy(godot_packed_int_array *r_dest, const godot_packed_int_array *p_src) {
- Vector<godot_int> *dest = (Vector<godot_int> *)r_dest;
- const Vector<godot_int> *src = (const Vector<godot_int> *)p_src;
- memnew_placement(dest, Vector<godot_int>(*src));
+void GDAPI godot_packed_float32_array_new_copy(godot_packed_float32_array *r_dest, const godot_packed_float32_array *p_src) {
+ Vector<float> *dest = (Vector<float> *)r_dest;
+ const Vector<float> *src = (const Vector<float> *)p_src;
+ memnew_placement(dest, Vector<float>(*src));
}
-void GDAPI godot_packed_int_array_new_with_array(godot_packed_int_array *r_dest, const godot_array *p_a) {
- Vector<godot_int> *dest = (Vector<godot_int> *)r_dest;
+void GDAPI godot_packed_float32_array_new_with_array(godot_packed_float32_array *r_dest, const godot_array *p_a) {
+ Vector<float> *dest = (Vector<float> *)r_dest;
Array *a = (Array *)p_a;
- memnew_placement(dest, Vector<godot_int>);
+ memnew_placement(dest, Vector<float>);
dest->resize(a->size());
for (int i = 0; i < a->size(); i++) {
@@ -152,83 +330,83 @@ void GDAPI godot_packed_int_array_new_with_array(godot_packed_int_array *r_dest,
}
}
-void GDAPI godot_packed_int_array_append(godot_packed_int_array *p_self, const godot_int p_data) {
- Vector<godot_int> *self = (Vector<godot_int> *)p_self;
+void GDAPI godot_packed_float32_array_append(godot_packed_float32_array *p_self, const float p_data) {
+ Vector<float> *self = (Vector<float> *)p_self;
self->push_back(p_data);
}
-void GDAPI godot_packed_int_array_append_array(godot_packed_int_array *p_self, const godot_packed_int_array *p_array) {
- Vector<godot_int> *self = (Vector<godot_int> *)p_self;
- Vector<godot_int> *array = (Vector<godot_int> *)p_array;
+void GDAPI godot_packed_float32_array_append_array(godot_packed_float32_array *p_self, const godot_packed_float32_array *p_array) {
+ Vector<float> *self = (Vector<float> *)p_self;
+ Vector<float> *array = (Vector<float> *)p_array;
self->append_array(*array);
}
-godot_error GDAPI godot_packed_int_array_insert(godot_packed_int_array *p_self, const godot_int p_idx, const godot_int p_data) {
- Vector<godot_int> *self = (Vector<godot_int> *)p_self;
+godot_error GDAPI godot_packed_float32_array_insert(godot_packed_float32_array *p_self, const godot_int p_idx, const float p_data) {
+ Vector<float> *self = (Vector<float> *)p_self;
return (godot_error)self->insert(p_idx, p_data);
}
-void GDAPI godot_packed_int_array_invert(godot_packed_int_array *p_self) {
- Vector<godot_int> *self = (Vector<godot_int> *)p_self;
+void GDAPI godot_packed_float32_array_invert(godot_packed_float32_array *p_self) {
+ Vector<float> *self = (Vector<float> *)p_self;
self->invert();
}
-void GDAPI godot_packed_int_array_push_back(godot_packed_int_array *p_self, const godot_int p_data) {
- Vector<godot_int> *self = (Vector<godot_int> *)p_self;
+void GDAPI godot_packed_float32_array_push_back(godot_packed_float32_array *p_self, const float p_data) {
+ Vector<float> *self = (Vector<float> *)p_self;
self->push_back(p_data);
}
-void GDAPI godot_packed_int_array_remove(godot_packed_int_array *p_self, const godot_int p_idx) {
- Vector<godot_int> *self = (Vector<godot_int> *)p_self;
+void GDAPI godot_packed_float32_array_remove(godot_packed_float32_array *p_self, const godot_int p_idx) {
+ Vector<float> *self = (Vector<float> *)p_self;
self->remove(p_idx);
}
-void GDAPI godot_packed_int_array_resize(godot_packed_int_array *p_self, const godot_int p_size) {
- Vector<godot_int> *self = (Vector<godot_int> *)p_self;
+void GDAPI godot_packed_float32_array_resize(godot_packed_float32_array *p_self, const godot_int p_size) {
+ Vector<float> *self = (Vector<float> *)p_self;
self->resize(p_size);
}
-void GDAPI godot_packed_int_array_set(godot_packed_int_array *p_self, const godot_int p_idx, const godot_int p_data) {
- Vector<godot_int> *self = (Vector<godot_int> *)p_self;
+void GDAPI godot_packed_float32_array_set(godot_packed_float32_array *p_self, const godot_int p_idx, const float p_data) {
+ Vector<float> *self = (Vector<float> *)p_self;
self->set(p_idx, p_data);
}
-godot_int GDAPI godot_packed_int_array_get(const godot_packed_int_array *p_self, const godot_int p_idx) {
- const Vector<godot_int> *self = (const Vector<godot_int> *)p_self;
+float GDAPI godot_packed_float32_array_get(const godot_packed_float32_array *p_self, const godot_int p_idx) {
+ const Vector<float> *self = (const Vector<float> *)p_self;
return self->get(p_idx);
}
-godot_int GDAPI godot_packed_int_array_size(const godot_packed_int_array *p_self) {
- const Vector<godot_int> *self = (const Vector<godot_int> *)p_self;
+godot_int GDAPI godot_packed_float32_array_size(const godot_packed_float32_array *p_self) {
+ const Vector<float> *self = (const Vector<float> *)p_self;
return self->size();
}
-godot_bool GDAPI godot_packed_int_array_empty(const godot_packed_int_array *p_self) {
- const Vector<godot_int> *self = (const Vector<godot_int> *)p_self;
+godot_bool GDAPI godot_packed_float32_array_empty(const godot_packed_float32_array *p_self) {
+ const Vector<float> *self = (const Vector<float> *)p_self;
return self->empty();
}
-void GDAPI godot_packed_int_array_destroy(godot_packed_int_array *p_self) {
- ((Vector<godot_int> *)p_self)->~Vector();
+void GDAPI godot_packed_float32_array_destroy(godot_packed_float32_array *p_self) {
+ ((Vector<float> *)p_self)->~Vector();
}
-// real
+// float64
-void GDAPI godot_packed_real_array_new(godot_packed_real_array *r_dest) {
- Vector<godot_real> *dest = (Vector<godot_real> *)r_dest;
- memnew_placement(dest, Vector<godot_real>);
+void GDAPI godot_packed_float64_array_new(godot_packed_float64_array *r_dest) {
+ Vector<double> *dest = (Vector<double> *)r_dest;
+ memnew_placement(dest, Vector<double>);
}
-void GDAPI godot_packed_real_array_new_copy(godot_packed_real_array *r_dest, const godot_packed_real_array *p_src) {
- Vector<godot_real> *dest = (Vector<godot_real> *)r_dest;
- const Vector<godot_real> *src = (const Vector<godot_real> *)p_src;
- memnew_placement(dest, Vector<godot_real>(*src));
+void GDAPI godot_packed_float64_array_new_copy(godot_packed_float64_array *r_dest, const godot_packed_float64_array *p_src) {
+ Vector<double> *dest = (Vector<double> *)r_dest;
+ const Vector<double> *src = (const Vector<double> *)p_src;
+ memnew_placement(dest, Vector<double>(*src));
}
-void GDAPI godot_packed_real_array_new_with_array(godot_packed_real_array *r_dest, const godot_array *p_a) {
- Vector<godot_real> *dest = (Vector<godot_real> *)r_dest;
+void GDAPI godot_packed_float64_array_new_with_array(godot_packed_float64_array *r_dest, const godot_array *p_a) {
+ Vector<double> *dest = (Vector<double> *)r_dest;
Array *a = (Array *)p_a;
- memnew_placement(dest, Vector<godot_real>);
+ memnew_placement(dest, Vector<double>);
dest->resize(a->size());
for (int i = 0; i < a->size(); i++) {
@@ -236,64 +414,64 @@ void GDAPI godot_packed_real_array_new_with_array(godot_packed_real_array *r_des
}
}
-void GDAPI godot_packed_real_array_append(godot_packed_real_array *p_self, const godot_real p_data) {
- Vector<godot_real> *self = (Vector<godot_real> *)p_self;
+void GDAPI godot_packed_float64_array_append(godot_packed_float64_array *p_self, const double p_data) {
+ Vector<double> *self = (Vector<double> *)p_self;
self->push_back(p_data);
}
-void GDAPI godot_packed_real_array_append_array(godot_packed_real_array *p_self, const godot_packed_real_array *p_array) {
- Vector<godot_real> *self = (Vector<godot_real> *)p_self;
- Vector<godot_real> *array = (Vector<godot_real> *)p_array;
+void GDAPI godot_packed_float64_array_append_array(godot_packed_float64_array *p_self, const godot_packed_float64_array *p_array) {
+ Vector<double> *self = (Vector<double> *)p_self;
+ Vector<double> *array = (Vector<double> *)p_array;
self->append_array(*array);
}
-godot_error GDAPI godot_packed_real_array_insert(godot_packed_real_array *p_self, const godot_int p_idx, const godot_real p_data) {
- Vector<godot_real> *self = (Vector<godot_real> *)p_self;
+godot_error GDAPI godot_packed_float64_array_insert(godot_packed_float64_array *p_self, const godot_int p_idx, const double p_data) {
+ Vector<double> *self = (Vector<double> *)p_self;
return (godot_error)self->insert(p_idx, p_data);
}
-void GDAPI godot_packed_real_array_invert(godot_packed_real_array *p_self) {
- Vector<godot_real> *self = (Vector<godot_real> *)p_self;
+void GDAPI godot_packed_float64_array_invert(godot_packed_float64_array *p_self) {
+ Vector<double> *self = (Vector<double> *)p_self;
self->invert();
}
-void GDAPI godot_packed_real_array_push_back(godot_packed_real_array *p_self, const godot_real p_data) {
- Vector<godot_real> *self = (Vector<godot_real> *)p_self;
+void GDAPI godot_packed_float64_array_push_back(godot_packed_float64_array *p_self, const double p_data) {
+ Vector<double> *self = (Vector<double> *)p_self;
self->push_back(p_data);
}
-void GDAPI godot_packed_real_array_remove(godot_packed_real_array *p_self, const godot_int p_idx) {
- Vector<godot_real> *self = (Vector<godot_real> *)p_self;
+void GDAPI godot_packed_float64_array_remove(godot_packed_float64_array *p_self, const godot_int p_idx) {
+ Vector<double> *self = (Vector<double> *)p_self;
self->remove(p_idx);
}
-void GDAPI godot_packed_real_array_resize(godot_packed_real_array *p_self, const godot_int p_size) {
- Vector<godot_real> *self = (Vector<godot_real> *)p_self;
+void GDAPI godot_packed_float64_array_resize(godot_packed_float64_array *p_self, const godot_int p_size) {
+ Vector<double> *self = (Vector<double> *)p_self;
self->resize(p_size);
}
-void GDAPI godot_packed_real_array_set(godot_packed_real_array *p_self, const godot_int p_idx, const godot_real p_data) {
- Vector<godot_real> *self = (Vector<godot_real> *)p_self;
+void GDAPI godot_packed_float64_array_set(godot_packed_float64_array *p_self, const godot_int p_idx, const double p_data) {
+ Vector<double> *self = (Vector<double> *)p_self;
self->set(p_idx, p_data);
}
-godot_real GDAPI godot_packed_real_array_get(const godot_packed_real_array *p_self, const godot_int p_idx) {
- const Vector<godot_real> *self = (const Vector<godot_real> *)p_self;
+double GDAPI godot_packed_float64_array_get(const godot_packed_float64_array *p_self, const godot_int p_idx) {
+ const Vector<double> *self = (const Vector<double> *)p_self;
return self->get(p_idx);
}
-godot_int GDAPI godot_packed_real_array_size(const godot_packed_real_array *p_self) {
- const Vector<godot_real> *self = (const Vector<godot_real> *)p_self;
+godot_int GDAPI godot_packed_float64_array_size(const godot_packed_float64_array *p_self) {
+ const Vector<double> *self = (const Vector<double> *)p_self;
return self->size();
}
-godot_bool GDAPI godot_packed_real_array_empty(const godot_packed_real_array *p_self) {
- const Vector<godot_real> *self = (const Vector<godot_real> *)p_self;
+godot_bool GDAPI godot_packed_float64_array_empty(const godot_packed_float64_array *p_self) {
+ const Vector<double> *self = (const Vector<double> *)p_self;
return self->empty();
}
-void GDAPI godot_packed_real_array_destroy(godot_packed_real_array *p_self) {
- ((Vector<godot_real> *)p_self)->~Vector();
+void GDAPI godot_packed_float64_array_destroy(godot_packed_float64_array *p_self) {
+ ((Vector<double> *)p_self)->~Vector();
}
// string
diff --git a/modules/gdnative/gdnative/plane.cpp b/modules/gdnative/gdnative/plane.cpp
index 923308dc34..663937f906 100644
--- a/modules/gdnative/gdnative/plane.cpp
+++ b/modules/gdnative/gdnative/plane.cpp
@@ -37,6 +37,8 @@
extern "C" {
#endif
+static_assert(sizeof(godot_plane) == sizeof(Plane), "Plane size mismatch");
+
void GDAPI godot_plane_new_with_reals(godot_plane *r_dest, const godot_real p_a, const godot_real p_b, const godot_real p_c, const godot_real p_d) {
Plane *dest = (Plane *)r_dest;
*dest = Plane(p_a, p_b, p_c, p_d);
diff --git a/modules/gdnative/gdnative/quat.cpp b/modules/gdnative/gdnative/quat.cpp
index 15c04f7191..de6308ad2a 100644
--- a/modules/gdnative/gdnative/quat.cpp
+++ b/modules/gdnative/gdnative/quat.cpp
@@ -37,6 +37,8 @@
extern "C" {
#endif
+static_assert(sizeof(godot_quat) == sizeof(Quat), "Quat size mismatch");
+
void GDAPI godot_quat_new(godot_quat *r_dest, const godot_real p_x, const godot_real p_y, const godot_real p_z, const godot_real p_w) {
Quat *dest = (Quat *)r_dest;
*dest = Quat(p_x, p_y, p_z, p_w);
diff --git a/modules/gdnative/gdnative/rect2.cpp b/modules/gdnative/gdnative/rect2.cpp
index a2f735172f..516f4d75ce 100644
--- a/modules/gdnative/gdnative/rect2.cpp
+++ b/modules/gdnative/gdnative/rect2.cpp
@@ -37,6 +37,11 @@
extern "C" {
#endif
+static_assert(sizeof(godot_rect2) == sizeof(Rect2), "Rect2 size mismatch");
+static_assert(sizeof(godot_rect2i) == sizeof(Rect2i), "Rect2i size mismatch");
+
+// Rect2
+
void GDAPI godot_rect2_new_with_position_and_size(godot_rect2 *r_dest, const godot_vector2 *p_pos, const godot_vector2 *p_size) {
const Vector2 *position = (const Vector2 *)p_pos;
const Vector2 *size = (const Vector2 *)p_size;
@@ -56,6 +61,13 @@ godot_string GDAPI godot_rect2_as_string(const godot_rect2 *p_self) {
return ret;
}
+godot_rect2i GDAPI godot_rect2_as_rect2i(const godot_rect2 *p_self) {
+ godot_rect2i dest;
+ const Rect2 *self = (const Rect2 *)p_self;
+ *((Rect2i *)&dest) = Rect2i(*self);
+ return dest;
+}
+
godot_real GDAPI godot_rect2_get_area(const godot_rect2 *p_self) {
const Rect2 *self = (const Rect2 *)p_self;
return self->get_area();
@@ -171,6 +183,149 @@ void GDAPI godot_rect2_set_size(godot_rect2 *p_self, const godot_vector2 *p_size
self->set_size(*size);
}
+// Rect2i
+
+void GDAPI godot_rect2i_new_with_position_and_size(godot_rect2i *r_dest, const godot_vector2i *p_pos, const godot_vector2i *p_size) {
+ const Vector2i *position = (const Vector2i *)p_pos;
+ const Vector2i *size = (const Vector2i *)p_size;
+ Rect2i *dest = (Rect2i *)r_dest;
+ *dest = Rect2i(*position, *size);
+}
+
+void GDAPI godot_rect2i_new(godot_rect2i *r_dest, const godot_int p_x, const godot_int p_y, const godot_int p_width, const godot_int p_height) {
+ Rect2i *dest = (Rect2i *)r_dest;
+ *dest = Rect2i(p_x, p_y, p_width, p_height);
+}
+
+godot_string GDAPI godot_rect2i_as_string(const godot_rect2i *p_self) {
+ godot_string ret;
+ const Rect2i *self = (const Rect2i *)p_self;
+ memnew_placement(&ret, String(*self));
+ return ret;
+}
+
+godot_rect2 GDAPI godot_rect2i_as_rect2(const godot_rect2i *p_self) {
+ godot_rect2 dest;
+ const Rect2i *self = (const Rect2i *)p_self;
+ *((Rect2 *)&dest) = Rect2(*self);
+ return dest;
+}
+
+godot_int GDAPI godot_rect2i_get_area(const godot_rect2i *p_self) {
+ const Rect2i *self = (const Rect2i *)p_self;
+ return self->get_area();
+}
+
+godot_bool GDAPI godot_rect2i_intersects(const godot_rect2i *p_self, const godot_rect2i *p_b) {
+ const Rect2i *self = (const Rect2i *)p_self;
+ const Rect2i *b = (const Rect2i *)p_b;
+ return self->intersects(*b);
+}
+
+godot_bool GDAPI godot_rect2i_encloses(const godot_rect2i *p_self, const godot_rect2i *p_b) {
+ const Rect2i *self = (const Rect2i *)p_self;
+ const Rect2i *b = (const Rect2i *)p_b;
+ return self->encloses(*b);
+}
+
+godot_bool GDAPI godot_rect2i_has_no_area(const godot_rect2i *p_self) {
+ const Rect2i *self = (const Rect2i *)p_self;
+ return self->has_no_area();
+}
+
+godot_rect2i GDAPI godot_rect2i_clip(const godot_rect2i *p_self, const godot_rect2i *p_b) {
+ godot_rect2i dest;
+ const Rect2i *self = (const Rect2i *)p_self;
+ const Rect2i *b = (const Rect2i *)p_b;
+ *((Rect2i *)&dest) = self->clip(*b);
+ return dest;
+}
+
+godot_rect2i GDAPI godot_rect2i_merge(const godot_rect2i *p_self, const godot_rect2i *p_b) {
+ godot_rect2i dest;
+ const Rect2i *self = (const Rect2i *)p_self;
+ const Rect2i *b = (const Rect2i *)p_b;
+ *((Rect2i *)&dest) = self->merge(*b);
+ return dest;
+}
+
+godot_bool GDAPI godot_rect2i_has_point(const godot_rect2i *p_self, const godot_vector2i *p_point) {
+ const Rect2i *self = (const Rect2i *)p_self;
+ const Vector2i *point = (const Vector2i *)p_point;
+ return self->has_point(*point);
+}
+
+godot_rect2i GDAPI godot_rect2i_grow(const godot_rect2i *p_self, const godot_int p_by) {
+ godot_rect2i dest;
+ const Rect2i *self = (const Rect2i *)p_self;
+
+ *((Rect2i *)&dest) = self->grow(p_by);
+ return dest;
+}
+
+godot_rect2i GDAPI godot_rect2i_grow_individual(const godot_rect2i *p_self, const godot_int p_left, const godot_int p_top, const godot_int p_right, const godot_int p_bottom) {
+ godot_rect2i dest;
+ const Rect2i *self = (const Rect2i *)p_self;
+ *((Rect2i *)&dest) = self->grow_individual(p_left, p_top, p_right, p_bottom);
+ return dest;
+}
+
+godot_rect2i GDAPI godot_rect2i_grow_margin(const godot_rect2i *p_self, const godot_int p_margin, const godot_int p_by) {
+ godot_rect2i dest;
+ const Rect2i *self = (const Rect2i *)p_self;
+ *((Rect2i *)&dest) = self->grow_margin((Margin)p_margin, p_by);
+ return dest;
+}
+
+godot_rect2i GDAPI godot_rect2i_abs(const godot_rect2i *p_self) {
+ godot_rect2i dest;
+ const Rect2i *self = (const Rect2i *)p_self;
+ *((Rect2i *)&dest) = self->abs();
+ return dest;
+}
+
+godot_rect2i GDAPI godot_rect2i_expand(const godot_rect2i *p_self, const godot_vector2i *p_to) {
+ godot_rect2i dest;
+ const Rect2i *self = (const Rect2i *)p_self;
+ const Vector2i *to = (const Vector2i *)p_to;
+ *((Rect2i *)&dest) = self->expand(*to);
+ return dest;
+}
+
+godot_bool GDAPI godot_rect2i_operator_equal(const godot_rect2i *p_self, const godot_rect2i *p_b) {
+ const Rect2i *self = (const Rect2i *)p_self;
+ const Rect2i *b = (const Rect2i *)p_b;
+ return *self == *b;
+}
+
+godot_vector2i GDAPI godot_rect2i_get_position(const godot_rect2i *p_self) {
+ godot_vector2i dest;
+ Vector2i *d = (Vector2i *)&dest;
+ const Rect2i *self = (const Rect2i *)p_self;
+ *d = self->get_position();
+ return dest;
+}
+
+godot_vector2i GDAPI godot_rect2i_get_size(const godot_rect2i *p_self) {
+ godot_vector2i dest;
+ Vector2i *d = (Vector2i *)&dest;
+ const Rect2i *self = (const Rect2i *)p_self;
+ *d = self->get_size();
+ return dest;
+}
+
+void GDAPI godot_rect2i_set_position(godot_rect2i *p_self, const godot_vector2i *p_pos) {
+ Rect2i *self = (Rect2i *)p_self;
+ const Vector2i *position = (const Vector2i *)p_pos;
+ self->set_position(*position);
+}
+
+void GDAPI godot_rect2i_set_size(godot_rect2i *p_self, const godot_vector2i *p_size) {
+ Rect2i *self = (Rect2i *)p_self;
+ const Vector2i *size = (const Vector2i *)p_size;
+ self->set_size(*size);
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/modules/gdnative/gdnative/rid.cpp b/modules/gdnative/gdnative/rid.cpp
index 7ea80123a3..d7a63f33a7 100644
--- a/modules/gdnative/gdnative/rid.cpp
+++ b/modules/gdnative/gdnative/rid.cpp
@@ -38,6 +38,8 @@
extern "C" {
#endif
+static_assert(sizeof(godot_rid) == sizeof(RID), "RID size mismatch");
+
void GDAPI godot_rid_new(godot_rid *r_dest) {
RID *dest = (RID *)r_dest;
memnew_placement(dest, RID);
diff --git a/modules/gdnative/gdnative/string.cpp b/modules/gdnative/gdnative/string.cpp
index a22af89edc..724a4b56cb 100644
--- a/modules/gdnative/gdnative/string.cpp
+++ b/modules/gdnative/gdnative/string.cpp
@@ -40,6 +40,10 @@
extern "C" {
#endif
+static_assert(sizeof(godot_char_string) == sizeof(CharString), "CharString size mismatch");
+static_assert(sizeof(godot_string) == sizeof(String), "String size mismatch");
+static_assert(sizeof(godot_char_type) == sizeof(CharType), "CharType size mismatch");
+
godot_int GDAPI godot_char_string_length(const godot_char_string *p_cs) {
const CharString *cs = (const CharString *)p_cs;
diff --git a/modules/gdnative/gdnative/string_name.cpp b/modules/gdnative/gdnative/string_name.cpp
index 1abb4486b1..7bbaaeeaa0 100644
--- a/modules/gdnative/gdnative/string_name.cpp
+++ b/modules/gdnative/gdnative/string_name.cpp
@@ -39,6 +39,8 @@
extern "C" {
#endif
+static_assert(sizeof(godot_string_name) == sizeof(StringName), "StringName size mismatch");
+
void GDAPI godot_string_name_new(godot_string_name *r_dest, const godot_string *p_name) {
StringName *dest = (StringName *)r_dest;
const String *name = (const String *)p_name;
diff --git a/modules/gdnative/gdnative/transform.cpp b/modules/gdnative/gdnative/transform.cpp
index c9b3e37fb2..d19de93e9b 100644
--- a/modules/gdnative/gdnative/transform.cpp
+++ b/modules/gdnative/gdnative/transform.cpp
@@ -37,6 +37,8 @@
extern "C" {
#endif
+static_assert(sizeof(godot_transform) == sizeof(Transform), "Transform size mismatch");
+
void GDAPI godot_transform_new_with_axis_origin(godot_transform *r_dest, const godot_vector3 *p_x_axis, const godot_vector3 *p_y_axis, const godot_vector3 *p_z_axis, const godot_vector3 *p_origin) {
const Vector3 *x_axis = (const Vector3 *)p_x_axis;
const Vector3 *y_axis = (const Vector3 *)p_y_axis;
diff --git a/modules/gdnative/gdnative/transform2d.cpp b/modules/gdnative/gdnative/transform2d.cpp
index 26a71333b1..c0f7878eb0 100644
--- a/modules/gdnative/gdnative/transform2d.cpp
+++ b/modules/gdnative/gdnative/transform2d.cpp
@@ -37,6 +37,8 @@
extern "C" {
#endif
+static_assert(sizeof(godot_transform2d) == sizeof(Transform2D), "Transform2D size mismatch");
+
void GDAPI godot_transform2d_new(godot_transform2d *r_dest, const godot_real p_rot, const godot_vector2 *p_pos) {
const Vector2 *pos = (const Vector2 *)p_pos;
Transform2D *dest = (Transform2D *)r_dest;
diff --git a/modules/gdnative/gdnative/variant.cpp b/modules/gdnative/gdnative/variant.cpp
index f0fc44ae8a..dac4feb0e5 100644
--- a/modules/gdnative/gdnative/variant.cpp
+++ b/modules/gdnative/gdnative/variant.cpp
@@ -37,6 +37,8 @@
extern "C" {
#endif
+static_assert(sizeof(godot_variant) == sizeof(Variant), "Variant size mismatch");
+
// Workaround GCC ICE on armv7hl which was affected GCC 6.0 up to 8.0 (GH-16100).
// It was fixed upstream in 8.1, and a fix was backported to 7.4.
// This can be removed once no supported distro ships with versions older than 7.4.
@@ -97,24 +99,48 @@ void GDAPI godot_variant_new_string(godot_variant *r_dest, const godot_string *p
memnew_placement_custom(dest, Variant, Variant(*s));
}
+void GDAPI godot_variant_new_string_name(godot_variant *r_dest, const godot_string_name *p_s) {
+ Variant *dest = (Variant *)r_dest;
+ StringName *s = (StringName *)p_s;
+ memnew_placement_custom(dest, Variant, Variant(*s));
+}
+
void GDAPI godot_variant_new_vector2(godot_variant *r_dest, const godot_vector2 *p_v2) {
Variant *dest = (Variant *)r_dest;
Vector2 *v2 = (Vector2 *)p_v2;
memnew_placement_custom(dest, Variant, Variant(*v2));
}
+void GDAPI godot_variant_new_vector2i(godot_variant *r_dest, const godot_vector2i *p_v2) {
+ Variant *dest = (Variant *)r_dest;
+ Vector2i *v2 = (Vector2i *)p_v2;
+ memnew_placement_custom(dest, Variant, Variant(*v2));
+}
+
void GDAPI godot_variant_new_rect2(godot_variant *r_dest, const godot_rect2 *p_rect2) {
Variant *dest = (Variant *)r_dest;
Rect2 *rect2 = (Rect2 *)p_rect2;
memnew_placement_custom(dest, Variant, Variant(*rect2));
}
+void GDAPI godot_variant_new_rect2i(godot_variant *r_dest, const godot_rect2i *p_rect2) {
+ Variant *dest = (Variant *)r_dest;
+ Rect2i *rect2 = (Rect2i *)p_rect2;
+ memnew_placement_custom(dest, Variant, Variant(*rect2));
+}
+
void GDAPI godot_variant_new_vector3(godot_variant *r_dest, const godot_vector3 *p_v3) {
Variant *dest = (Variant *)r_dest;
Vector3 *v3 = (Vector3 *)p_v3;
memnew_placement_custom(dest, Variant, Variant(*v3));
}
+void GDAPI godot_variant_new_vector3i(godot_variant *r_dest, const godot_vector3i *p_v3) {
+ Variant *dest = (Variant *)r_dest;
+ Vector3i *v3 = (Vector3i *)p_v3;
+ memnew_placement_custom(dest, Variant, Variant(*v3));
+}
+
void GDAPI godot_variant_new_transform2d(godot_variant *r_dest, const godot_transform2d *p_t2d) {
Variant *dest = (Variant *)r_dest;
Transform2D *t2d = (Transform2D *)p_t2d;
@@ -169,6 +195,18 @@ void GDAPI godot_variant_new_rid(godot_variant *r_dest, const godot_rid *p_rid)
memnew_placement_custom(dest, Variant, Variant(*rid));
}
+void GDAPI godot_variant_new_callable(godot_variant *r_dest, const godot_callable *p_cb) {
+ Variant *dest = (Variant *)r_dest;
+ Callable *cb = (Callable *)p_cb;
+ memnew_placement_custom(dest, Variant, Variant(*cb));
+}
+
+void GDAPI godot_variant_new_signal(godot_variant *r_dest, const godot_signal *p_signal) {
+ Variant *dest = (Variant *)r_dest;
+ Signal *signal = (Signal *)p_signal;
+ memnew_placement_custom(dest, Variant, Variant(*signal));
+}
+
void GDAPI godot_variant_new_object(godot_variant *r_dest, const godot_object *p_obj) {
Variant *dest = (Variant *)r_dest;
Object *obj = (Object *)p_obj;
@@ -207,18 +245,30 @@ void GDAPI godot_variant_new_packed_byte_array(godot_variant *r_dest, const godo
memnew_placement_custom(dest, Variant, Variant(*pba));
}
-void GDAPI godot_variant_new_packed_int_array(godot_variant *r_dest, const godot_packed_int_array *p_pia) {
+void GDAPI godot_variant_new_packed_int32_array(godot_variant *r_dest, const godot_packed_int32_array *p_pia) {
Variant *dest = (Variant *)r_dest;
PackedInt32Array *pia = (PackedInt32Array *)p_pia;
memnew_placement_custom(dest, Variant, Variant(*pia));
}
-void GDAPI godot_variant_new_packed_real_array(godot_variant *r_dest, const godot_packed_real_array *p_pra) {
+void GDAPI godot_variant_new_packed_int64_array(godot_variant *r_dest, const godot_packed_int64_array *p_pia) {
+ Variant *dest = (Variant *)r_dest;
+ PackedInt64Array *pia = (PackedInt64Array *)p_pia;
+ memnew_placement_custom(dest, Variant, Variant(*pia));
+}
+
+void GDAPI godot_variant_new_packed_float32_array(godot_variant *r_dest, const godot_packed_float32_array *p_pra) {
Variant *dest = (Variant *)r_dest;
PackedFloat32Array *pra = (PackedFloat32Array *)p_pra;
memnew_placement_custom(dest, Variant, Variant(*pra));
}
+void GDAPI godot_variant_new_packed_float64_array(godot_variant *r_dest, const godot_packed_float64_array *p_pra) {
+ Variant *dest = (Variant *)r_dest;
+ PackedFloat64Array *pra = (PackedFloat64Array *)p_pra;
+ memnew_placement_custom(dest, Variant, Variant(*pra));
+}
+
void GDAPI godot_variant_new_packed_string_array(godot_variant *r_dest, const godot_packed_string_array *p_psa) {
Variant *dest = (Variant *)r_dest;
PackedStringArray *psa = (PackedStringArray *)p_psa;
@@ -271,6 +321,14 @@ godot_string GDAPI godot_variant_as_string(const godot_variant *p_self) {
return raw_dest;
}
+godot_string_name GDAPI godot_variant_as_string_name(const godot_variant *p_self) {
+ godot_string_name raw_dest;
+ const Variant *self = (const Variant *)p_self;
+ StringName *dest = (StringName *)&raw_dest;
+ memnew_placement(dest, StringName(self->operator StringName())); // operator = is overloaded by StringName
+ return raw_dest;
+}
+
godot_vector2 GDAPI godot_variant_as_vector2(const godot_variant *p_self) {
godot_vector2 raw_dest;
const Variant *self = (const Variant *)p_self;
@@ -279,6 +337,14 @@ godot_vector2 GDAPI godot_variant_as_vector2(const godot_variant *p_self) {
return raw_dest;
}
+godot_vector2i GDAPI godot_variant_as_vector2i(const godot_variant *p_self) {
+ godot_vector2i raw_dest;
+ const Variant *self = (const Variant *)p_self;
+ Vector2i *dest = (Vector2i *)&raw_dest;
+ *dest = *self;
+ return raw_dest;
+}
+
godot_rect2 GDAPI godot_variant_as_rect2(const godot_variant *p_self) {
godot_rect2 raw_dest;
const Variant *self = (const Variant *)p_self;
@@ -287,6 +353,14 @@ godot_rect2 GDAPI godot_variant_as_rect2(const godot_variant *p_self) {
return raw_dest;
}
+godot_rect2i GDAPI godot_variant_as_rect2i(const godot_variant *p_self) {
+ godot_rect2i raw_dest;
+ const Variant *self = (const Variant *)p_self;
+ Rect2i *dest = (Rect2i *)&raw_dest;
+ *dest = *self;
+ return raw_dest;
+}
+
godot_vector3 GDAPI godot_variant_as_vector3(const godot_variant *p_self) {
godot_vector3 raw_dest;
const Variant *self = (const Variant *)p_self;
@@ -295,6 +369,14 @@ godot_vector3 GDAPI godot_variant_as_vector3(const godot_variant *p_self) {
return raw_dest;
}
+godot_vector3i GDAPI godot_variant_as_vector3i(const godot_variant *p_self) {
+ godot_vector3i raw_dest;
+ const Variant *self = (const Variant *)p_self;
+ Vector3i *dest = (Vector3i *)&raw_dest;
+ *dest = *self;
+ return raw_dest;
+}
+
godot_transform2d GDAPI godot_variant_as_transform2d(const godot_variant *p_self) {
godot_transform2d raw_dest;
const Variant *self = (const Variant *)p_self;
@@ -367,6 +449,22 @@ godot_rid GDAPI godot_variant_as_rid(const godot_variant *p_self) {
return raw_dest;
}
+godot_callable GDAPI godot_variant_as_callable(const godot_variant *p_self) {
+ godot_callable raw_dest;
+ const Variant *self = (const Variant *)p_self;
+ Callable *dest = (Callable *)&raw_dest;
+ *dest = *self;
+ return raw_dest;
+}
+
+godot_signal GDAPI godot_variant_as_signal(const godot_variant *p_self) {
+ godot_signal raw_dest;
+ const Variant *self = (const Variant *)p_self;
+ Signal *dest = (Signal *)&raw_dest;
+ *dest = *self;
+ return raw_dest;
+}
+
godot_object GDAPI *godot_variant_as_object(const godot_variant *p_self) {
const Variant *self = (const Variant *)p_self;
Object *dest;
@@ -399,8 +497,8 @@ godot_packed_byte_array GDAPI godot_variant_as_packed_byte_array(const godot_var
return raw_dest;
}
-godot_packed_int_array GDAPI godot_variant_as_packed_int_array(const godot_variant *p_self) {
- godot_packed_int_array raw_dest;
+godot_packed_int32_array GDAPI godot_variant_as_packed_int32_array(const godot_variant *p_self) {
+ godot_packed_int32_array raw_dest;
const Variant *self = (const Variant *)p_self;
PackedInt32Array *dest = (PackedInt32Array *)&raw_dest;
memnew_placement(dest, PackedInt32Array(self->operator PackedInt32Array())); // operator = is overloaded by PackedInt32Array
@@ -408,8 +506,17 @@ godot_packed_int_array GDAPI godot_variant_as_packed_int_array(const godot_varia
return raw_dest;
}
-godot_packed_real_array GDAPI godot_variant_as_packed_real_array(const godot_variant *p_self) {
- godot_packed_real_array raw_dest;
+godot_packed_int64_array GDAPI godot_variant_as_packed_int64_array(const godot_variant *p_self) {
+ godot_packed_int64_array raw_dest;
+ const Variant *self = (const Variant *)p_self;
+ PackedInt64Array *dest = (PackedInt64Array *)&raw_dest;
+ memnew_placement(dest, PackedInt64Array(self->operator PackedInt64Array())); // operator = is overloaded by PackedInt64Array
+ *dest = *self;
+ return raw_dest;
+}
+
+godot_packed_float32_array GDAPI godot_variant_as_packed_float32_array(const godot_variant *p_self) {
+ godot_packed_float32_array raw_dest;
const Variant *self = (const Variant *)p_self;
PackedFloat32Array *dest = (PackedFloat32Array *)&raw_dest;
memnew_placement(dest, PackedFloat32Array(self->operator PackedFloat32Array())); // operator = is overloaded by PackedFloat32Array
@@ -417,6 +524,15 @@ godot_packed_real_array GDAPI godot_variant_as_packed_real_array(const godot_var
return raw_dest;
}
+godot_packed_float64_array GDAPI godot_variant_as_packed_float64_array(const godot_variant *p_self) {
+ godot_packed_float64_array raw_dest;
+ const Variant *self = (const Variant *)p_self;
+ PackedFloat64Array *dest = (PackedFloat64Array *)&raw_dest;
+ memnew_placement(dest, PackedFloat64Array(self->operator PackedFloat64Array())); // operator = is overloaded by PackedFloat64Array
+ *dest = *self;
+ return raw_dest;
+}
+
godot_packed_string_array GDAPI godot_variant_as_packed_string_array(const godot_variant *p_self) {
godot_packed_string_array raw_dest;
const Variant *self = (const Variant *)p_self;
@@ -487,6 +603,11 @@ godot_bool GDAPI godot_variant_operator_less(const godot_variant *p_self, const
return self->operator<(*other);
}
+uint32_t GDAPI godot_variant_hash(const godot_variant *p_self) {
+ const Variant *self = (const Variant *)p_self;
+ return self->hash();
+}
+
godot_bool GDAPI godot_variant_hash_compare(const godot_variant *p_self, const godot_variant *p_other) {
const Variant *self = (const Variant *)p_self;
const Variant *other = (const Variant *)p_other;
diff --git a/modules/gdnative/gdnative/vector2.cpp b/modules/gdnative/gdnative/vector2.cpp
index b6c3569f42..1ee716df86 100644
--- a/modules/gdnative/gdnative/vector2.cpp
+++ b/modules/gdnative/gdnative/vector2.cpp
@@ -37,6 +37,11 @@
extern "C" {
#endif
+static_assert(sizeof(godot_vector2) == sizeof(Vector2), "Vector2 size mismatch");
+static_assert(sizeof(godot_vector2i) == sizeof(Vector2i), "Vector2i size mismatch");
+
+// Vector2
+
void GDAPI godot_vector2_new(godot_vector2 *r_dest, const godot_real p_x, const godot_real p_y) {
Vector2 *dest = (Vector2 *)r_dest;
*dest = Vector2(p_x, p_y);
@@ -49,6 +54,13 @@ godot_string GDAPI godot_vector2_as_string(const godot_vector2 *p_self) {
return ret;
}
+godot_vector2i GDAPI godot_vector2_as_vector2i(const godot_vector2 *p_self) {
+ godot_vector2i dest;
+ const Vector2 *self = (const Vector2 *)p_self;
+ *((Vector2i *)&dest) = Vector2i(*self);
+ return dest;
+}
+
godot_vector2 GDAPI godot_vector2_normalized(const godot_vector2 *p_self) {
godot_vector2 dest;
const Vector2 *self = (const Vector2 *)p_self;
@@ -156,6 +168,13 @@ godot_vector2 GDAPI godot_vector2_floor(const godot_vector2 *p_self) {
return dest;
}
+godot_vector2 GDAPI godot_vector2_sign(const godot_vector2 *p_self) {
+ godot_vector2 dest;
+ const Vector2 *self = (const Vector2 *)p_self;
+ *((Vector2 *)&dest) = self->sign();
+ return dest;
+}
+
godot_vector2 GDAPI godot_vector2_snapped(const godot_vector2 *p_self, const godot_vector2 *p_by) {
godot_vector2 dest;
const Vector2 *self = (const Vector2 *)p_self;
@@ -306,6 +325,138 @@ godot_real GDAPI godot_vector2_get_y(const godot_vector2 *p_self) {
return self->y;
}
+// Vector2i
+
+void GDAPI godot_vector2i_new(godot_vector2i *r_dest, const godot_int p_x, const godot_int p_y) {
+ Vector2i *dest = (Vector2i *)r_dest;
+ *dest = Vector2i(p_x, p_y);
+}
+
+godot_string GDAPI godot_vector2i_as_string(const godot_vector2i *p_self) {
+ godot_string ret;
+ const Vector2i *self = (const Vector2i *)p_self;
+ memnew_placement(&ret, String(*self));
+ return ret;
+}
+
+godot_vector2 GDAPI godot_vector2i_as_vector2(const godot_vector2i *p_self) {
+ godot_vector2 dest;
+ const Vector2i *self = (const Vector2i *)p_self;
+ *((Vector2 *)&dest) = Vector2(*self);
+ return dest;
+}
+
+godot_real GDAPI godot_vector2i_aspect(const godot_vector2i *p_self) {
+ const Vector2i *self = (const Vector2i *)p_self;
+ return self->aspect();
+}
+
+godot_vector2i GDAPI godot_vector2i_abs(const godot_vector2i *p_self) {
+ godot_vector2i dest;
+ const Vector2i *self = (const Vector2i *)p_self;
+ *((Vector2i *)&dest) = self->abs();
+ return dest;
+}
+
+godot_vector2i GDAPI godot_vector2i_sign(const godot_vector2i *p_self) {
+ godot_vector2i dest;
+ const Vector2i *self = (const Vector2i *)p_self;
+ *((Vector2i *)&dest) = self->sign();
+ return dest;
+}
+
+godot_vector2i GDAPI godot_vector2i_operator_add(const godot_vector2i *p_self, const godot_vector2i *p_b) {
+ godot_vector2i raw_dest;
+ Vector2i *dest = (Vector2i *)&raw_dest;
+ const Vector2i *self = (const Vector2i *)p_self;
+ const Vector2i *b = (const Vector2i *)p_b;
+ *dest = *self + *b;
+ return raw_dest;
+}
+
+godot_vector2i GDAPI godot_vector2i_operator_subtract(const godot_vector2i *p_self, const godot_vector2i *p_b) {
+ godot_vector2i raw_dest;
+ Vector2i *dest = (Vector2i *)&raw_dest;
+ const Vector2i *self = (const Vector2i *)p_self;
+ const Vector2i *b = (const Vector2i *)p_b;
+ *dest = *self - *b;
+ return raw_dest;
+}
+
+godot_vector2i GDAPI godot_vector2i_operator_multiply_vector(const godot_vector2i *p_self, const godot_vector2i *p_b) {
+ godot_vector2i raw_dest;
+ Vector2i *dest = (Vector2i *)&raw_dest;
+ const Vector2i *self = (const Vector2i *)p_self;
+ const Vector2i *b = (const Vector2i *)p_b;
+ *dest = *self * *b;
+ return raw_dest;
+}
+
+godot_vector2i GDAPI godot_vector2i_operator_multiply_scalar(const godot_vector2i *p_self, const godot_int p_b) {
+ godot_vector2i raw_dest;
+ Vector2i *dest = (Vector2i *)&raw_dest;
+ const Vector2i *self = (const Vector2i *)p_self;
+ *dest = *self * p_b;
+ return raw_dest;
+}
+
+godot_vector2i GDAPI godot_vector2i_operator_divide_vector(const godot_vector2i *p_self, const godot_vector2i *p_b) {
+ godot_vector2i raw_dest;
+ Vector2i *dest = (Vector2i *)&raw_dest;
+ const Vector2i *self = (const Vector2i *)p_self;
+ const Vector2i *b = (const Vector2i *)p_b;
+ *dest = *self / *b;
+ return raw_dest;
+}
+
+godot_vector2i GDAPI godot_vector2i_operator_divide_scalar(const godot_vector2i *p_self, const godot_int p_b) {
+ godot_vector2i raw_dest;
+ Vector2i *dest = (Vector2i *)&raw_dest;
+ const Vector2i *self = (const Vector2i *)p_self;
+ *dest = *self / p_b;
+ return raw_dest;
+}
+
+godot_bool GDAPI godot_vector2i_operator_equal(const godot_vector2i *p_self, const godot_vector2i *p_b) {
+ const Vector2i *self = (const Vector2i *)p_self;
+ const Vector2i *b = (const Vector2i *)p_b;
+ return *self == *b;
+}
+
+godot_bool GDAPI godot_vector2i_operator_less(const godot_vector2i *p_self, const godot_vector2i *p_b) {
+ const Vector2i *self = (const Vector2i *)p_self;
+ const Vector2i *b = (const Vector2i *)p_b;
+ return *self < *b;
+}
+
+godot_vector2i GDAPI godot_vector2i_operator_neg(const godot_vector2i *p_self) {
+ godot_vector2i raw_dest;
+ Vector2i *dest = (Vector2i *)&raw_dest;
+ const Vector2i *self = (const Vector2i *)p_self;
+ *dest = -(*self);
+ return raw_dest;
+}
+
+void GDAPI godot_vector2i_set_x(godot_vector2i *p_self, const godot_int p_x) {
+ Vector2i *self = (Vector2i *)p_self;
+ self->x = p_x;
+}
+
+void GDAPI godot_vector2i_set_y(godot_vector2i *p_self, const godot_int p_y) {
+ Vector2i *self = (Vector2i *)p_self;
+ self->y = p_y;
+}
+
+godot_int GDAPI godot_vector2i_get_x(const godot_vector2i *p_self) {
+ const Vector2i *self = (const Vector2i *)p_self;
+ return self->x;
+}
+
+godot_int GDAPI godot_vector2i_get_y(const godot_vector2i *p_self) {
+ const Vector2i *self = (const Vector2i *)p_self;
+ return self->y;
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/modules/gdnative/gdnative/vector3.cpp b/modules/gdnative/gdnative/vector3.cpp
index 3e272ae9df..32cad30c17 100644
--- a/modules/gdnative/gdnative/vector3.cpp
+++ b/modules/gdnative/gdnative/vector3.cpp
@@ -37,6 +37,11 @@
extern "C" {
#endif
+static_assert(sizeof(godot_vector3) == sizeof(Vector3), "Vector3 size mismatch");
+static_assert(sizeof(godot_vector3i) == sizeof(Vector3i), "Vector3i size mismatch");
+
+// Vector3
+
void GDAPI godot_vector3_new(godot_vector3 *r_dest, const godot_real p_x, const godot_real p_y, const godot_real p_z) {
Vector3 *dest = (Vector3 *)r_dest;
*dest = Vector3(p_x, p_y, p_z);
@@ -49,6 +54,13 @@ godot_string GDAPI godot_vector3_as_string(const godot_vector3 *p_self) {
return ret;
}
+godot_vector3i GDAPI godot_vector3_as_vector3i(const godot_vector3 *p_self) {
+ godot_vector3i dest;
+ const Vector3 *self = (const Vector3 *)p_self;
+ *((Vector3i *)&dest) = Vector3i(*self);
+ return dest;
+}
+
godot_int GDAPI godot_vector3_min_axis(const godot_vector3 *p_self) {
const Vector3 *self = (const Vector3 *)p_self;
return self->min_axis();
@@ -167,6 +179,13 @@ godot_vector3 GDAPI godot_vector3_abs(const godot_vector3 *p_self) {
return dest;
}
+godot_vector3 GDAPI godot_vector3_sign(const godot_vector3 *p_self) {
+ godot_vector3 dest;
+ const Vector3 *self = (const Vector3 *)p_self;
+ *((Vector3 *)&dest) = self->sign();
+ return dest;
+}
+
godot_vector3 GDAPI godot_vector3_floor(const godot_vector3 *p_self) {
godot_vector3 dest;
const Vector3 *self = (const Vector3 *)p_self;
@@ -313,6 +332,133 @@ godot_real GDAPI godot_vector3_get_axis(const godot_vector3 *p_self, const godot
return self->get_axis(p_axis);
}
+// Vector3i
+
+void GDAPI godot_vector3i_new(godot_vector3i *r_dest, const godot_int p_x, const godot_int p_y, const godot_int p_z) {
+ Vector3i *dest = (Vector3i *)r_dest;
+ *dest = Vector3i(p_x, p_y, p_z);
+}
+
+godot_string GDAPI godot_vector3i_as_string(const godot_vector3i *p_self) {
+ godot_string ret;
+ const Vector3i *self = (const Vector3i *)p_self;
+ memnew_placement(&ret, String(*self));
+ return ret;
+}
+
+godot_vector3 GDAPI godot_vector3i_as_vector3(const godot_vector3i *p_self) {
+ godot_vector3 dest;
+ const Vector3i *self = (const Vector3i *)p_self;
+ *((Vector3 *)&dest) = Vector3(*self);
+ return dest;
+}
+
+godot_int GDAPI godot_vector3i_min_axis(const godot_vector3i *p_self) {
+ const Vector3i *self = (const Vector3i *)p_self;
+ return self->min_axis();
+}
+
+godot_int GDAPI godot_vector3i_max_axis(const godot_vector3i *p_self) {
+ const Vector3i *self = (const Vector3i *)p_self;
+ return self->max_axis();
+}
+
+godot_vector3i GDAPI godot_vector3i_abs(const godot_vector3i *p_self) {
+ godot_vector3i dest;
+ const Vector3i *self = (const Vector3i *)p_self;
+ *((Vector3i *)&dest) = self->abs();
+ return dest;
+}
+
+godot_vector3i GDAPI godot_vector3i_sign(const godot_vector3i *p_self) {
+ godot_vector3i dest;
+ const Vector3i *self = (const Vector3i *)p_self;
+ *((Vector3i *)&dest) = self->sign();
+ return dest;
+}
+
+godot_vector3i GDAPI godot_vector3i_operator_add(const godot_vector3i *p_self, const godot_vector3i *p_b) {
+ godot_vector3i raw_dest;
+ Vector3i *dest = (Vector3i *)&raw_dest;
+ Vector3i *self = (Vector3i *)p_self;
+ const Vector3i *b = (const Vector3i *)p_b;
+ *dest = *self + *b;
+ return raw_dest;
+}
+
+godot_vector3i GDAPI godot_vector3i_operator_subtract(const godot_vector3i *p_self, const godot_vector3i *p_b) {
+ godot_vector3i raw_dest;
+ Vector3i *dest = (Vector3i *)&raw_dest;
+ Vector3i *self = (Vector3i *)p_self;
+ const Vector3i *b = (const Vector3i *)p_b;
+ *dest = *self - *b;
+ return raw_dest;
+}
+
+godot_vector3i GDAPI godot_vector3i_operator_multiply_vector(const godot_vector3i *p_self, const godot_vector3i *p_b) {
+ godot_vector3i raw_dest;
+ Vector3i *dest = (Vector3i *)&raw_dest;
+ Vector3i *self = (Vector3i *)p_self;
+ const Vector3i *b = (const Vector3i *)p_b;
+ *dest = *self * *b;
+ return raw_dest;
+}
+
+godot_vector3i GDAPI godot_vector3i_operator_multiply_scalar(const godot_vector3i *p_self, const godot_int p_b) {
+ godot_vector3i raw_dest;
+ Vector3i *dest = (Vector3i *)&raw_dest;
+ Vector3i *self = (Vector3i *)p_self;
+ *dest = *self * p_b;
+ return raw_dest;
+}
+
+godot_vector3i GDAPI godot_vector3i_operator_divide_vector(const godot_vector3i *p_self, const godot_vector3i *p_b) {
+ godot_vector3i raw_dest;
+ Vector3i *dest = (Vector3i *)&raw_dest;
+ Vector3i *self = (Vector3i *)p_self;
+ const Vector3i *b = (const Vector3i *)p_b;
+ *dest = *self / *b;
+ return raw_dest;
+}
+
+godot_vector3i GDAPI godot_vector3i_operator_divide_scalar(const godot_vector3i *p_self, const godot_int p_b) {
+ godot_vector3i raw_dest;
+ Vector3i *dest = (Vector3i *)&raw_dest;
+ Vector3i *self = (Vector3i *)p_self;
+ *dest = *self / p_b;
+ return raw_dest;
+}
+
+godot_bool GDAPI godot_vector3i_operator_equal(const godot_vector3i *p_self, const godot_vector3i *p_b) {
+ Vector3i *self = (Vector3i *)p_self;
+ const Vector3i *b = (const Vector3i *)p_b;
+ return *self == *b;
+}
+
+godot_bool GDAPI godot_vector3i_operator_less(const godot_vector3i *p_self, const godot_vector3i *p_b) {
+ Vector3i *self = (Vector3i *)p_self;
+ const Vector3i *b = (const Vector3i *)p_b;
+ return *self < *b;
+}
+
+godot_vector3i GDAPI godot_vector3i_operator_neg(const godot_vector3i *p_self) {
+ godot_vector3i raw_dest;
+ Vector3i *dest = (Vector3i *)&raw_dest;
+ const Vector3i *self = (const Vector3i *)p_self;
+ *dest = -(*self);
+ return raw_dest;
+}
+
+void GDAPI godot_vector3i_set_axis(godot_vector3i *p_self, const godot_vector3_axis p_axis, const godot_int p_val) {
+ Vector3i *self = (Vector3i *)p_self;
+ self->set_axis(p_axis, p_val);
+}
+
+godot_int GDAPI godot_vector3i_get_axis(const godot_vector3i *p_self, const godot_vector3_axis p_axis) {
+ const Vector3i *self = (const Vector3i *)p_self;
+ return self->get_axis(p_axis);
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/modules/gdnative/gdnative_api.json b/modules/gdnative/gdnative_api.json
index d5ab62dc61..9c38c8b58d 100644
--- a/modules/gdnative/gdnative_api.json
+++ b/modules/gdnative/gdnative_api.json
@@ -17,7 +17,1125 @@
"major": 1,
"minor": 2
},
- "next": null,
+ "next": {
+ "type": "CORE",
+ "version": {
+ "major": 1,
+ "minor": 3
+ },
+ "next": null,
+ "api": [
+ {
+ "name": "godot_object_get_instance_id",
+ "return_type": "uint64_t",
+ "arguments": [
+ ["const godot_object *", "p_object"]
+ ]
+ },
+ {
+ "name": "godot_array_new_packed_float64_array",
+ "return_type": "void",
+ "arguments": [
+ ["godot_array *", "r_dest"],
+ ["const godot_packed_float64_array *", "p_pra"]
+ ]
+ },
+ {
+ "name": "godot_array_new_packed_int64_array",
+ "return_type": "void",
+ "arguments": [
+ ["godot_array *", "r_dest"],
+ ["const godot_packed_int64_array *", "p_pia"]
+ ]
+ },
+ {
+ "name": "godot_callable_new_with_object",
+ "return_type": "void",
+ "arguments": [
+ ["godot_callable *", "r_dest"],
+ ["const godot_object *", "p_object"],
+ ["const godot_string_name *", "p_method"]
+ ]
+ },
+ {
+ "name": "godot_callable_new_with_object_id",
+ "return_type": "void",
+ "arguments": [
+ ["godot_callable *", "r_dest"],
+ ["uint64_t", "p_objectid"],
+ ["const godot_string_name *", "p_method"]
+ ]
+ },
+ {
+ "name": "godot_callable_new_copy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_callable *", "r_dest"],
+ ["const godot_callable *", "p_src"]
+ ]
+ },
+ {
+ "name": "godot_callable_destroy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_callable *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_callable_call",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_callable *", "p_self"],
+ ["const godot_variant **", "p_arguments"],
+ ["godot_int", "p_argcount"],
+ ["godot_variant *", "r_return_value"]
+ ]
+ },
+ {
+ "name": "godot_callable_call_deferred",
+ "return_type": "void",
+ "arguments": [
+ ["const godot_callable *", "p_self"],
+ ["const godot_variant **", "p_arguments"],
+ ["godot_int", "p_argcount"]
+ ]
+ },
+ {
+ "name": "godot_callable_is_null",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_callable *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_callable_is_custom",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_callable *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_callable_is_standard",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_callable *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_callable_get_object",
+ "return_type": "godot_object *",
+ "arguments": [
+ ["const godot_callable *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_callable_get_object_id",
+ "return_type": "uint64_t",
+ "arguments": [
+ ["const godot_callable *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_callable_get_method",
+ "return_type": "godot_string_name",
+ "arguments": [
+ ["const godot_callable *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_callable_hash",
+ "return_type": "uint32_t",
+ "arguments": [
+ ["const godot_callable *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_callable_as_string",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_callable *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_callable_operator_equal",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_callable *", "p_self"],
+ ["const godot_callable *", "p_other"]
+ ]
+ },
+ {
+ "name": "godot_callable_operator_less",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_callable *", "p_self"],
+ ["const godot_callable *", "p_other"]
+ ]
+ },
+ {
+ "name": "godot_signal_new_with_object",
+ "return_type": "void",
+ "arguments": [
+ ["godot_signal *", "r_dest"],
+ ["const godot_object *", "p_object"],
+ ["const godot_string_name *", "p_method"]
+ ]
+ },
+ {
+ "name": "godot_signal_new_with_object_id",
+ "return_type": "void",
+ "arguments": [
+ ["godot_signal *", "r_dest"],
+ ["uint64_t", "p_objectid"],
+ ["const godot_string_name *", "p_method"]
+ ]
+ },
+ {
+ "name": "godot_signal_new_copy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_signal *", "r_dest"],
+ ["const godot_signal *", "p_src"]
+ ]
+ },
+ {
+ "name": "godot_signal_destroy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_signal *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_signal_emit",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_signal *", "p_self"],
+ ["const godot_variant **", "p_arguments"],
+ ["godot_int", "p_argcount"]
+ ]
+ },
+ {
+ "name": "godot_signal_connect",
+ "return_type": "godot_int",
+ "arguments": [
+ ["godot_signal *", "p_self"],
+ ["const godot_callable *", "p_callable"],
+ ["const godot_array *", "p_binds"],
+ ["uint32_t", "p_flags"]
+ ]
+ },
+ {
+ "name": "godot_signal_disconnect",
+ "return_type": "void",
+ "arguments": [
+ ["godot_signal *", "p_self"],
+ ["const godot_callable *", "p_callable"]
+ ]
+ },
+ {
+ "name": "godot_signal_is_null",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_signal *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_signal_is_connected",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_signal *", "p_self"],
+ ["const godot_callable *", "p_callable"]
+ ]
+ },
+ {
+ "name": "godot_signal_get_connections",
+ "return_type": "godot_array",
+ "arguments": [
+ ["const godot_signal *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_signal_get_object",
+ "return_type": "godot_object *",
+ "arguments": [
+ ["const godot_signal *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_signal_get_object_id",
+ "return_type": "uint64_t",
+ "arguments": [
+ ["const godot_signal *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_signal_get_name",
+ "return_type": "godot_string_name",
+ "arguments": [
+ ["const godot_signal *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_signal_as_string",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_signal *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_signal_operator_equal",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_signal *", "p_self"],
+ ["const godot_signal *", "p_other"]
+ ]
+ },
+ {
+ "name": "godot_signal_operator_less",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_signal *", "p_self"],
+ ["const godot_signal *", "p_other"]
+ ]
+ },
+ {
+ "name": "godot_packed_int64_array_new",
+ "return_type": "void",
+ "arguments": [
+ ["godot_packed_int64_array *", "r_dest"]
+ ]
+ },
+ {
+ "name": "godot_packed_int64_array_new_copy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_packed_int64_array *", "r_dest"],
+ ["const godot_packed_int64_array *", "p_src"]
+ ]
+ },
+ {
+ "name": "godot_packed_int64_array_new_with_array",
+ "return_type": "void",
+ "arguments": [
+ ["godot_packed_int64_array *", "r_dest"],
+ ["const godot_array *", "p_a"]
+ ]
+ },
+ {
+ "name": "godot_packed_int64_array_append",
+ "return_type": "void",
+ "arguments": [
+ ["godot_packed_int64_array *", "p_self"],
+ ["const int64_t", "p_data"]
+ ]
+ },
+ {
+ "name": "godot_packed_int64_array_append_array",
+ "return_type": "void",
+ "arguments": [
+ ["godot_packed_int64_array *", "p_self"],
+ ["const godot_packed_int64_array *", "p_array"]
+ ]
+ },
+ {
+ "name": "godot_packed_int64_array_insert",
+ "return_type": "godot_error",
+ "arguments": [
+ ["godot_packed_int64_array *", "p_self"],
+ ["const godot_int", "p_idx"],
+ ["const int64_t", "p_data"]
+ ]
+ },
+ {
+ "name": "godot_packed_int64_array_invert",
+ "return_type": "void",
+ "arguments": [
+ ["godot_packed_int64_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_packed_int64_array_push_back",
+ "return_type": "void",
+ "arguments": [
+ ["godot_packed_int64_array *", "p_self"],
+ ["const int64_t", "p_data"]
+ ]
+ },
+ {
+ "name": "godot_packed_int64_array_remove",
+ "return_type": "void",
+ "arguments": [
+ ["godot_packed_int64_array *", "p_self"],
+ ["const godot_int", "p_idx"]
+ ]
+ },
+ {
+ "name": "godot_packed_int64_array_resize",
+ "return_type": "void",
+ "arguments": [
+ ["godot_packed_int64_array *", "p_self"],
+ ["const godot_int", "p_size"]
+ ]
+ },
+ {
+ "name": "godot_packed_int64_array_set",
+ "return_type": "void",
+ "arguments": [
+ ["godot_packed_int64_array *", "p_self"],
+ ["const godot_int", "p_idx"],
+ ["const int64_t", "p_data"]
+ ]
+ },
+ {
+ "name": "godot_packed_int64_array_get",
+ "return_type": "int64_t",
+ "arguments": [
+ ["const godot_packed_int64_array *", "p_self"],
+ ["const godot_int", "p_idx"]
+ ]
+ },
+ {
+ "name": "godot_packed_int64_array_size",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_packed_int64_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_packed_int64_array_destroy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_packed_int64_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_packed_float64_array_new",
+ "return_type": "void",
+ "arguments": [
+ ["godot_packed_float64_array *", "r_dest"]
+ ]
+ },
+ {
+ "name": "godot_packed_float64_array_new_copy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_packed_float64_array *", "r_dest"],
+ ["const godot_packed_float64_array *", "p_src"]
+ ]
+ },
+ {
+ "name": "godot_packed_float64_array_new_with_array",
+ "return_type": "void",
+ "arguments": [
+ ["godot_packed_float64_array *", "r_dest"],
+ ["const godot_array *", "p_a"]
+ ]
+ },
+ {
+ "name": "godot_packed_float64_array_append",
+ "return_type": "void",
+ "arguments": [
+ ["godot_packed_float64_array *", "p_self"],
+ ["const double", "p_data"]
+ ]
+ },
+ {
+ "name": "godot_packed_float64_array_append_array",
+ "return_type": "void",
+ "arguments": [
+ ["godot_packed_float64_array *", "p_self"],
+ ["const godot_packed_float64_array *", "p_array"]
+ ]
+ },
+ {
+ "name": "godot_packed_float64_array_insert",
+ "return_type": "godot_error",
+ "arguments": [
+ ["godot_packed_float64_array *", "p_self"],
+ ["const godot_int", "p_idx"],
+ ["const double", "p_data"]
+ ]
+ },
+ {
+ "name": "godot_packed_float64_array_invert",
+ "return_type": "void",
+ "arguments": [
+ ["godot_packed_float64_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_packed_float64_array_push_back",
+ "return_type": "void",
+ "arguments": [
+ ["godot_packed_float64_array *", "p_self"],
+ ["const double", "p_data"]
+ ]
+ },
+ {
+ "name": "godot_packed_float64_array_remove",
+ "return_type": "void",
+ "arguments": [
+ ["godot_packed_float64_array *", "p_self"],
+ ["const godot_int", "p_idx"]
+ ]
+ },
+ {
+ "name": "godot_packed_float64_array_resize",
+ "return_type": "void",
+ "arguments": [
+ ["godot_packed_float64_array *", "p_self"],
+ ["const godot_int", "p_size"]
+ ]
+ },
+ {
+ "name": "godot_packed_float64_array_set",
+ "return_type": "void",
+ "arguments": [
+ ["godot_packed_float64_array *", "p_self"],
+ ["const godot_int", "p_idx"],
+ ["const double", "p_data"]
+ ]
+ },
+ {
+ "name": "godot_packed_float64_array_get",
+ "return_type": "double",
+ "arguments": [
+ ["const godot_packed_float64_array *", "p_self"],
+ ["const godot_int", "p_idx"]
+ ]
+ },
+ {
+ "name": "godot_packed_float64_array_size",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_packed_float64_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_packed_float64_array_destroy",
+ "return_type": "void",
+ "arguments": [
+ ["godot_packed_float64_array *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_rect2_as_rect2i",
+ "return_type": "godot_rect2i",
+ "arguments": [
+ ["const godot_rect2 *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_rect2i_new_with_position_and_size",
+ "return_type": "void",
+ "arguments": [
+ ["godot_rect2i *", "r_dest"],
+ ["const godot_vector2i *", "p_pos"],
+ ["const godot_vector2i *", "p_size"]
+ ]
+ },
+ {
+ "name": "godot_rect2i_new",
+ "return_type": "void",
+ "arguments": [
+ ["godot_rect2i *", "r_dest"],
+ ["const godot_int", "p_x"],
+ ["const godot_int", "p_y"],
+ ["const godot_int", "p_width"],
+ ["const godot_int", "p_height"]
+ ]
+ },
+ {
+ "name": "godot_rect2i_as_string",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_rect2i *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_rect2i_as_rect2",
+ "return_type": "godot_rect2",
+ "arguments": [
+ ["const godot_rect2i *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_rect2i_get_area",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_rect2i *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_rect2i_intersects",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_rect2i *", "p_self"],
+ ["const godot_rect2i *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_rect2i_encloses",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_rect2i *", "p_self"],
+ ["const godot_rect2i *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_rect2i_has_no_area",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_rect2i *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_rect2i_clip",
+ "return_type": "godot_rect2i",
+ "arguments": [
+ ["const godot_rect2i *", "p_self"],
+ ["const godot_rect2i *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_rect2i_merge",
+ "return_type": "godot_rect2i",
+ "arguments": [
+ ["const godot_rect2i *", "p_self"],
+ ["const godot_rect2i *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_rect2i_has_point",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_rect2i *", "p_self"],
+ ["const godot_vector2i *", "p_point"]
+ ]
+ },
+ {
+ "name": "godot_rect2i_grow",
+ "return_type": "godot_rect2i",
+ "arguments": [
+ ["const godot_rect2i *", "p_self"],
+ ["const godot_int", "p_by"]
+ ]
+ },
+ {
+ "name": "godot_rect2i_grow_individual",
+ "return_type": "godot_rect2i",
+ "arguments": [
+ ["const godot_rect2i *", "p_self"],
+ ["const godot_int", "p_left"],
+ ["const godot_int", "p_top"],
+ ["const godot_int", "p_right"],
+ ["const godot_int", "p_bottom"]
+ ]
+ },
+ {
+ "name": "godot_rect2i_grow_margin",
+ "return_type": "godot_rect2i",
+ "arguments": [
+ ["const godot_rect2i *", "p_self"],
+ ["const godot_int", "p_margin"],
+ ["const godot_int", "p_by"]
+ ]
+ },
+ {
+ "name": "godot_rect2i_abs",
+ "return_type": "godot_rect2i",
+ "arguments": [
+ ["const godot_rect2i *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_rect2i_expand",
+ "return_type": "godot_rect2i",
+ "arguments": [
+ ["const godot_rect2i *", "p_self"],
+ ["const godot_vector2i *", "p_to"]
+ ]
+ },
+ {
+ "name": "godot_rect2i_operator_equal",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_rect2i *", "p_self"],
+ ["const godot_rect2i *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_rect2i_get_position",
+ "return_type": "godot_vector2i",
+ "arguments": [
+ ["const godot_rect2i *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_rect2i_get_size",
+ "return_type": "godot_vector2i",
+ "arguments": [
+ ["const godot_rect2i *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_rect2i_set_position",
+ "return_type": "void",
+ "arguments": [
+ ["godot_rect2i *", "p_self"],
+ ["const godot_vector2i *", "p_pos"]
+ ]
+ },
+ {
+ "name": "godot_rect2i_set_size",
+ "return_type": "void",
+ "arguments": [
+ ["godot_rect2i *", "p_self"],
+ ["const godot_vector2i *", "p_size"]
+ ]
+ },
+ {
+ "name": "godot_variant_new_string_name",
+ "return_type": "void",
+ "arguments": [
+ ["godot_variant *", "r_dest"],
+ ["const godot_string_name *", "p_s"]
+ ]
+ },
+ {
+ "name": "godot_variant_new_vector2i",
+ "return_type": "void",
+ "arguments": [
+ ["godot_variant *", "r_dest"],
+ ["const godot_vector2i *", "p_v2"]
+ ]
+ },
+ {
+ "name": "godot_variant_new_rect2i",
+ "return_type": "void",
+ "arguments": [
+ ["godot_variant *", "r_dest"],
+ ["const godot_rect2i *", "p_rect2"]
+ ]
+ },
+ {
+ "name": "godot_variant_new_vector3i",
+ "return_type": "void",
+ "arguments": [
+ ["godot_variant *", "r_dest"],
+ ["const godot_vector3i *", "p_v3"]
+ ]
+ },
+ {
+ "name": "godot_variant_new_callable",
+ "return_type": "void",
+ "arguments": [
+ ["godot_variant *", "r_dest"],
+ ["const godot_callable *", "p_cb"]
+ ]
+ },
+ {
+ "name": "godot_variant_new_signal",
+ "return_type": "void",
+ "arguments": [
+ ["godot_variant *", "r_dest"],
+ ["const godot_signal *", "p_signal"]
+ ]
+ },
+ {
+ "name": "godot_variant_new_packed_int64_array",
+ "return_type": "void",
+ "arguments": [
+ ["godot_variant *", "r_dest"],
+ ["const godot_packed_int64_array *", "p_pia"]
+ ]
+ },
+ {
+ "name": "godot_variant_new_packed_float64_array",
+ "return_type": "void",
+ "arguments": [
+ ["godot_variant *", "r_dest"],
+ ["const godot_packed_float64_array *", "p_pra"]
+ ]
+ },
+ {
+ "name": "godot_variant_as_string_name",
+ "return_type": "godot_string_name",
+ "arguments": [
+ ["const godot_variant *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_variant_as_vector2i",
+ "return_type": "godot_vector2i",
+ "arguments": [
+ ["const godot_variant *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_variant_as_rect2i",
+ "return_type": "godot_rect2i",
+ "arguments": [
+ ["const godot_variant *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_variant_as_vector3i",
+ "return_type": "godot_vector3i",
+ "arguments": [
+ ["const godot_variant *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_variant_as_callable",
+ "return_type": "godot_callable",
+ "arguments": [
+ ["const godot_variant *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_variant_as_signal",
+ "return_type": "godot_signal",
+ "arguments": [
+ ["const godot_variant *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_variant_as_packed_int64_array",
+ "return_type": "godot_packed_int64_array",
+ "arguments": [
+ ["const godot_variant *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_variant_as_packed_float64_array",
+ "return_type": "godot_packed_float64_array",
+ "arguments": [
+ ["const godot_variant *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_variant_hash",
+ "return_type": "uint32_t",
+ "arguments": [
+ ["const godot_variant *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector2_as_vector2i",
+ "return_type": "godot_vector2i",
+ "arguments": [
+ ["const godot_vector2 *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector2_sign",
+ "return_type": "godot_vector2",
+ "arguments": [
+ ["const godot_vector2 *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector2i_new",
+ "return_type": "void",
+ "arguments": [
+ ["godot_vector2i *", "r_dest"],
+ ["const godot_int", "p_x"],
+ ["const godot_int", "p_y"]
+ ]
+ },
+ {
+ "name": "godot_vector2i_as_string",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_vector2i *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector2i_as_vector2",
+ "return_type": "godot_vector2",
+ "arguments": [
+ ["const godot_vector2i *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector2i_aspect",
+ "return_type": "godot_real",
+ "arguments": [
+ ["const godot_vector2i *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector2i_abs",
+ "return_type": "godot_vector2i",
+ "arguments": [
+ ["const godot_vector2i *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector2i_sign",
+ "return_type": "godot_vector2i",
+ "arguments": [
+ ["const godot_vector2i *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector2i_operator_add",
+ "return_type": "godot_vector2i",
+ "arguments": [
+ ["const godot_vector2i *", "p_self"],
+ ["const godot_vector2i *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_vector2i_operator_subtract",
+ "return_type": "godot_vector2i",
+ "arguments": [
+ ["const godot_vector2i *", "p_self"],
+ ["const godot_vector2i *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_vector2i_operator_multiply_vector",
+ "return_type": "godot_vector2i",
+ "arguments": [
+ ["const godot_vector2i *", "p_self"],
+ ["const godot_vector2i *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_vector2i_operator_multiply_scalar",
+ "return_type": "godot_vector2i",
+ "arguments": [
+ ["const godot_vector2i *", "p_self"],
+ ["const godot_int", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_vector2i_operator_divide_vector",
+ "return_type": "godot_vector2i",
+ "arguments": [
+ ["const godot_vector2i *", "p_self"],
+ ["const godot_vector2i *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_vector2i_operator_divide_scalar",
+ "return_type": "godot_vector2i",
+ "arguments": [
+ ["const godot_vector2i *", "p_self"],
+ ["const godot_int", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_vector2i_operator_equal",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_vector2i *", "p_self"],
+ ["const godot_vector2i *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_vector2i_operator_less",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_vector2i *", "p_self"],
+ ["const godot_vector2i *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_vector2i_operator_neg",
+ "return_type": "godot_vector2i",
+ "arguments": [
+ ["const godot_vector2i *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector2i_set_x",
+ "return_type": "void",
+ "arguments": [
+ ["godot_vector2i *", "p_self"],
+ ["const godot_int", "p_x"]
+ ]
+ },
+ {
+ "name": "godot_vector2i_set_y",
+ "return_type": "void",
+ "arguments": [
+ ["godot_vector2i *", "p_self"],
+ ["const godot_int", "p_y"]
+ ]
+ },
+ {
+ "name": "godot_vector2i_get_x",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_vector2i *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector2i_get_y",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_vector2i *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector3_as_vector3i",
+ "return_type": "godot_vector3i",
+ "arguments": [
+ ["const godot_vector3 *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector3_sign",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_vector3 *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector3i_new",
+ "return_type": "void",
+ "arguments": [
+ ["godot_vector3i *", "r_dest"],
+ ["const godot_int", "p_x"],
+ ["const godot_int", "p_y"],
+ ["const godot_int", "p_z"]
+ ]
+ },
+ {
+ "name": "godot_vector3i_as_string",
+ "return_type": "godot_string",
+ "arguments": [
+ ["const godot_vector3i *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector3i_as_vector3",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_vector3i *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector3i_min_axis",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_vector3i *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector3i_max_axis",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_vector3i *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector3i_abs",
+ "return_type": "godot_vector3i",
+ "arguments": [
+ ["const godot_vector3i *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector3i_sign",
+ "return_type": "godot_vector3i",
+ "arguments": [
+ ["const godot_vector3i *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector3i_operator_add",
+ "return_type": "godot_vector3i",
+ "arguments": [
+ ["const godot_vector3i *", "p_self"],
+ ["const godot_vector3i *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_vector3i_operator_subtract",
+ "return_type": "godot_vector3i",
+ "arguments": [
+ ["const godot_vector3i *", "p_self"],
+ ["const godot_vector3i *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_vector3i_operator_multiply_vector",
+ "return_type": "godot_vector3i",
+ "arguments": [
+ ["const godot_vector3i *", "p_self"],
+ ["const godot_vector3i *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_vector3i_operator_multiply_scalar",
+ "return_type": "godot_vector3i",
+ "arguments": [
+ ["const godot_vector3i *", "p_self"],
+ ["const godot_int", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_vector3i_operator_divide_vector",
+ "return_type": "godot_vector3i",
+ "arguments": [
+ ["const godot_vector3i *", "p_self"],
+ ["const godot_vector3i *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_vector3i_operator_divide_scalar",
+ "return_type": "godot_vector3i",
+ "arguments": [
+ ["const godot_vector3i *", "p_self"],
+ ["const godot_int", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_vector3i_operator_equal",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_vector3i *", "p_self"],
+ ["const godot_vector3i *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_vector3i_operator_less",
+ "return_type": "godot_bool",
+ "arguments": [
+ ["const godot_vector3i *", "p_self"],
+ ["const godot_vector3i *", "p_b"]
+ ]
+ },
+ {
+ "name": "godot_vector3i_operator_neg",
+ "return_type": "godot_vector3i",
+ "arguments": [
+ ["const godot_vector3i *", "p_self"]
+ ]
+ },
+ {
+ "name": "godot_vector3i_set_axis",
+ "return_type": "void",
+ "arguments": [
+ ["godot_vector3i *", "p_self"],
+ ["const godot_vector3_axis", "p_axis"],
+ ["const godot_int", "p_val"]
+ ]
+ },
+ {
+ "name": "godot_vector3i_get_axis",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_vector3i *", "p_self"],
+ ["const godot_vector3_axis", "p_axis"]
+ ]
+ }
+ ]
+ },
"api": [
{
"name": "godot_dictionary_duplicate",
@@ -100,17 +1218,17 @@
]
},
{
- "name": "godot_packed_int_array_empty",
+ "name": "godot_packed_int32_array_empty",
"return_type": "godot_bool",
"arguments": [
- ["const godot_packed_int_array *", "p_self"]
+ ["const godot_packed_int32_array *", "p_self"]
]
},
{
- "name": "godot_packed_real_array_empty",
+ "name": "godot_packed_float32_array_empty",
"return_type": "godot_bool",
"arguments": [
- ["const godot_packed_real_array *", "p_self"]
+ ["const godot_packed_float32_array *", "p_self"]
]
},
{
@@ -160,7 +1278,7 @@
"name": "godot_instance_from_id",
"return_type": "godot_object *",
"arguments": [
- ["godot_int", "p_instance_id"]
+ ["uint64_t", "p_instance_id"]
]
}
]
@@ -1767,223 +2885,223 @@
]
},
{
- "name": "godot_packed_int_array_new",
+ "name": "godot_packed_int32_array_new",
"return_type": "void",
"arguments": [
- ["godot_packed_int_array *", "r_dest"]
+ ["godot_packed_int32_array *", "r_dest"]
]
},
{
- "name": "godot_packed_int_array_new_copy",
+ "name": "godot_packed_int32_array_new_copy",
"return_type": "void",
"arguments": [
- ["godot_packed_int_array *", "r_dest"],
- ["const godot_packed_int_array *", "p_src"]
+ ["godot_packed_int32_array *", "r_dest"],
+ ["const godot_packed_int32_array *", "p_src"]
]
},
{
- "name": "godot_packed_int_array_new_with_array",
+ "name": "godot_packed_int32_array_new_with_array",
"return_type": "void",
"arguments": [
- ["godot_packed_int_array *", "r_dest"],
+ ["godot_packed_int32_array *", "r_dest"],
["const godot_array *", "p_a"]
]
},
{
- "name": "godot_packed_int_array_append",
+ "name": "godot_packed_int32_array_append",
"return_type": "void",
"arguments": [
- ["godot_packed_int_array *", "p_self"],
- ["const godot_int", "p_data"]
+ ["godot_packed_int32_array *", "p_self"],
+ ["const int32_t", "p_data"]
]
},
{
- "name": "godot_packed_int_array_append_array",
+ "name": "godot_packed_int32_array_append_array",
"return_type": "void",
"arguments": [
- ["godot_packed_int_array *", "p_self"],
- ["const godot_packed_int_array *", "p_array"]
+ ["godot_packed_int32_array *", "p_self"],
+ ["const godot_packed_int32_array *", "p_array"]
]
},
{
- "name": "godot_packed_int_array_insert",
+ "name": "godot_packed_int32_array_insert",
"return_type": "godot_error",
"arguments": [
- ["godot_packed_int_array *", "p_self"],
+ ["godot_packed_int32_array *", "p_self"],
["const godot_int", "p_idx"],
- ["const godot_int", "p_data"]
+ ["const int32_t", "p_data"]
]
},
{
- "name": "godot_packed_int_array_invert",
+ "name": "godot_packed_int32_array_invert",
"return_type": "void",
"arguments": [
- ["godot_packed_int_array *", "p_self"]
+ ["godot_packed_int32_array *", "p_self"]
]
},
{
- "name": "godot_packed_int_array_push_back",
+ "name": "godot_packed_int32_array_push_back",
"return_type": "void",
"arguments": [
- ["godot_packed_int_array *", "p_self"],
- ["const godot_int", "p_data"]
+ ["godot_packed_int32_array *", "p_self"],
+ ["const int32_t", "p_data"]
]
},
{
- "name": "godot_packed_int_array_remove",
+ "name": "godot_packed_int32_array_remove",
"return_type": "void",
"arguments": [
- ["godot_packed_int_array *", "p_self"],
+ ["godot_packed_int32_array *", "p_self"],
["const godot_int", "p_idx"]
]
},
{
- "name": "godot_packed_int_array_resize",
+ "name": "godot_packed_int32_array_resize",
"return_type": "void",
"arguments": [
- ["godot_packed_int_array *", "p_self"],
+ ["godot_packed_int32_array *", "p_self"],
["const godot_int", "p_size"]
]
},
{
- "name": "godot_packed_int_array_set",
+ "name": "godot_packed_int32_array_set",
"return_type": "void",
"arguments": [
- ["godot_packed_int_array *", "p_self"],
+ ["godot_packed_int32_array *", "p_self"],
["const godot_int", "p_idx"],
- ["const godot_int", "p_data"]
+ ["const int32_t", "p_data"]
]
},
{
- "name": "godot_packed_int_array_get",
- "return_type": "godot_int",
+ "name": "godot_packed_int32_array_get",
+ "return_type": "int32_t",
"arguments": [
- ["const godot_packed_int_array *", "p_self"],
+ ["const godot_packed_int32_array *", "p_self"],
["const godot_int", "p_idx"]
]
},
{
- "name": "godot_packed_int_array_size",
+ "name": "godot_packed_int32_array_size",
"return_type": "godot_int",
"arguments": [
- ["const godot_packed_int_array *", "p_self"]
+ ["const godot_packed_int32_array *", "p_self"]
]
},
{
- "name": "godot_packed_int_array_destroy",
+ "name": "godot_packed_int32_array_destroy",
"return_type": "void",
"arguments": [
- ["godot_packed_int_array *", "p_self"]
+ ["godot_packed_int32_array *", "p_self"]
]
},
{
- "name": "godot_packed_real_array_new",
+ "name": "godot_packed_float32_array_new",
"return_type": "void",
"arguments": [
- ["godot_packed_real_array *", "r_dest"]
+ ["godot_packed_float32_array *", "r_dest"]
]
},
{
- "name": "godot_packed_real_array_new_copy",
+ "name": "godot_packed_float32_array_new_copy",
"return_type": "void",
"arguments": [
- ["godot_packed_real_array *", "r_dest"],
- ["const godot_packed_real_array *", "p_src"]
+ ["godot_packed_float32_array *", "r_dest"],
+ ["const godot_packed_float32_array *", "p_src"]
]
},
{
- "name": "godot_packed_real_array_new_with_array",
+ "name": "godot_packed_float32_array_new_with_array",
"return_type": "void",
"arguments": [
- ["godot_packed_real_array *", "r_dest"],
+ ["godot_packed_float32_array *", "r_dest"],
["const godot_array *", "p_a"]
]
},
{
- "name": "godot_packed_real_array_append",
+ "name": "godot_packed_float32_array_append",
"return_type": "void",
"arguments": [
- ["godot_packed_real_array *", "p_self"],
- ["const godot_real", "p_data"]
+ ["godot_packed_float32_array *", "p_self"],
+ ["const float", "p_data"]
]
},
{
- "name": "godot_packed_real_array_append_array",
+ "name": "godot_packed_float32_array_append_array",
"return_type": "void",
"arguments": [
- ["godot_packed_real_array *", "p_self"],
- ["const godot_packed_real_array *", "p_array"]
+ ["godot_packed_float32_array *", "p_self"],
+ ["const godot_packed_float32_array *", "p_array"]
]
},
{
- "name": "godot_packed_real_array_insert",
+ "name": "godot_packed_float32_array_insert",
"return_type": "godot_error",
"arguments": [
- ["godot_packed_real_array *", "p_self"],
+ ["godot_packed_float32_array *", "p_self"],
["const godot_int", "p_idx"],
- ["const godot_real", "p_data"]
+ ["const float", "p_data"]
]
},
{
- "name": "godot_packed_real_array_invert",
+ "name": "godot_packed_float32_array_invert",
"return_type": "void",
"arguments": [
- ["godot_packed_real_array *", "p_self"]
+ ["godot_packed_float32_array *", "p_self"]
]
},
{
- "name": "godot_packed_real_array_push_back",
+ "name": "godot_packed_float32_array_push_back",
"return_type": "void",
"arguments": [
- ["godot_packed_real_array *", "p_self"],
- ["const godot_real", "p_data"]
+ ["godot_packed_float32_array *", "p_self"],
+ ["const float", "p_data"]
]
},
{
- "name": "godot_packed_real_array_remove",
+ "name": "godot_packed_float32_array_remove",
"return_type": "void",
"arguments": [
- ["godot_packed_real_array *", "p_self"],
+ ["godot_packed_float32_array *", "p_self"],
["const godot_int", "p_idx"]
]
},
{
- "name": "godot_packed_real_array_resize",
+ "name": "godot_packed_float32_array_resize",
"return_type": "void",
"arguments": [
- ["godot_packed_real_array *", "p_self"],
+ ["godot_packed_float32_array *", "p_self"],
["const godot_int", "p_size"]
]
},
{
- "name": "godot_packed_real_array_set",
+ "name": "godot_packed_float32_array_set",
"return_type": "void",
"arguments": [
- ["godot_packed_real_array *", "p_self"],
+ ["godot_packed_float32_array *", "p_self"],
["const godot_int", "p_idx"],
- ["const godot_real", "p_data"]
+ ["const float", "p_data"]
]
},
{
- "name": "godot_packed_real_array_get",
- "return_type": "godot_real",
+ "name": "godot_packed_float32_array_get",
+ "return_type": "float",
"arguments": [
- ["const godot_packed_real_array *", "p_self"],
+ ["const godot_packed_float32_array *", "p_self"],
["const godot_int", "p_idx"]
]
},
{
- "name": "godot_packed_real_array_size",
+ "name": "godot_packed_float32_array_size",
"return_type": "godot_int",
"arguments": [
- ["const godot_packed_real_array *", "p_self"]
+ ["const godot_packed_float32_array *", "p_self"]
]
},
{
- "name": "godot_packed_real_array_destroy",
+ "name": "godot_packed_float32_array_destroy",
"return_type": "void",
"arguments": [
- ["godot_packed_real_array *", "p_self"]
+ ["godot_packed_float32_array *", "p_self"]
]
},
{
@@ -2474,19 +3592,19 @@
]
},
{
- "name": "godot_array_new_packed_real_array",
+ "name": "godot_array_new_packed_float32_array",
"return_type": "void",
"arguments": [
["godot_array *", "r_dest"],
- ["const godot_packed_real_array *", "p_pra"]
+ ["const godot_packed_float32_array *", "p_pra"]
]
},
{
- "name": "godot_array_new_packed_int_array",
+ "name": "godot_array_new_packed_int32_array",
"return_type": "void",
"arguments": [
["godot_array *", "r_dest"],
- ["const godot_packed_int_array *", "p_pia"]
+ ["const godot_packed_int32_array *", "p_pia"]
]
},
{
@@ -4059,19 +5177,19 @@
]
},
{
- "name": "godot_variant_new_packed_int_array",
+ "name": "godot_variant_new_packed_int32_array",
"return_type": "void",
"arguments": [
["godot_variant *", "r_dest"],
- ["const godot_packed_int_array *", "p_pia"]
+ ["const godot_packed_int32_array *", "p_pia"]
]
},
{
- "name": "godot_variant_new_packed_real_array",
+ "name": "godot_variant_new_packed_float32_array",
"return_type": "void",
"arguments": [
["godot_variant *", "r_dest"],
- ["const godot_packed_real_array *", "p_pra"]
+ ["const godot_packed_float32_array *", "p_pra"]
]
},
{
@@ -4254,15 +5372,15 @@
]
},
{
- "name": "godot_variant_as_packed_int_array",
- "return_type": "godot_packed_int_array",
+ "name": "godot_variant_as_packed_int32_array",
+ "return_type": "godot_packed_int32_array",
"arguments": [
["const godot_variant *", "p_self"]
]
},
{
- "name": "godot_variant_as_packed_real_array",
- "return_type": "godot_packed_real_array",
+ "name": "godot_variant_as_packed_float32_array",
+ "return_type": "godot_packed_float32_array",
"arguments": [
["const godot_variant *", "p_self"]
]
@@ -5869,7 +6987,7 @@
"arguments": [
["void *", "p_gdnative_handle"],
["const char *", "p_name"],
- ["const godot_signal *", "p_signal"]
+ ["const godot_nativescript_signal *", "p_signal"]
]
},
{
diff --git a/modules/gdnative/include/gdnative/array.h b/modules/gdnative/include/gdnative/array.h
index e3114e9348..4db685873f 100644
--- a/modules/gdnative/include/gdnative/array.h
+++ b/modules/gdnative/include/gdnative/array.h
@@ -51,7 +51,7 @@ typedef struct {
}
#endif
-#include <gdnative/pool_arrays.h>
+#include <gdnative/packed_arrays.h>
#include <gdnative/variant.h>
#include <gdnative/gdnative.h>
@@ -66,8 +66,10 @@ void GDAPI godot_array_new_packed_color_array(godot_array *r_dest, const godot_p
void GDAPI godot_array_new_packed_vector3_array(godot_array *r_dest, const godot_packed_vector3_array *p_pv3a);
void GDAPI godot_array_new_packed_vector2_array(godot_array *r_dest, const godot_packed_vector2_array *p_pv2a);
void GDAPI godot_array_new_packed_string_array(godot_array *r_dest, const godot_packed_string_array *p_psa);
-void GDAPI godot_array_new_packed_real_array(godot_array *r_dest, const godot_packed_real_array *p_pra);
-void GDAPI godot_array_new_packed_int_array(godot_array *r_dest, const godot_packed_int_array *p_pia);
+void GDAPI godot_array_new_packed_float32_array(godot_array *r_dest, const godot_packed_float32_array *p_pra);
+void GDAPI godot_array_new_packed_float64_array(godot_array *r_dest, const godot_packed_float64_array *p_pra);
+void GDAPI godot_array_new_packed_int32_array(godot_array *r_dest, const godot_packed_int32_array *p_pia);
+void GDAPI godot_array_new_packed_int64_array(godot_array *r_dest, const godot_packed_int64_array *p_pia);
void GDAPI godot_array_new_packed_byte_array(godot_array *r_dest, const godot_packed_byte_array *p_pba);
void GDAPI godot_array_set(godot_array *p_self, const godot_int p_idx, const godot_variant *p_value);
diff --git a/modules/gdnative/include/gdnative/callable.h b/modules/gdnative/include/gdnative/callable.h
new file mode 100644
index 0000000000..dbb5d02590
--- /dev/null
+++ b/modules/gdnative/include/gdnative/callable.h
@@ -0,0 +1,126 @@
+/*************************************************************************/
+/* callable.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef GODOT_CALLABLE_H
+#define GODOT_CALLABLE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+#define GODOT_CALLABLE_SIZE (16)
+
+#ifndef GODOT_CORE_API_GODOT_CALLABLE_TYPE_DEFINED
+#define GODOT_CORE_API_GODOT_CALLABLE_TYPE_DEFINED
+typedef struct {
+ uint8_t _dont_touch_that[GODOT_CALLABLE_SIZE];
+} godot_callable;
+#endif
+
+#define GODOT_SIGNAL_SIZE (16)
+
+#ifndef GODOT_CORE_API_GODOT_SIGNAL_TYPE_DEFINED
+#define GODOT_CORE_API_GODOT_SIGNAL_TYPE_DEFINED
+typedef struct {
+ uint8_t _dont_touch_that[GODOT_SIGNAL_SIZE];
+} godot_signal;
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#include <gdnative/gdnative.h>
+#include <gdnative/string_name.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Callable
+
+void GDAPI godot_callable_new_with_object(godot_callable *r_dest, const godot_object *p_object, const godot_string_name *p_method);
+void GDAPI godot_callable_new_with_object_id(godot_callable *r_dest, uint64_t p_objectid, const godot_string_name *p_method);
+void GDAPI godot_callable_new_copy(godot_callable *r_dest, const godot_callable *p_src);
+
+void GDAPI godot_callable_destroy(godot_callable *p_self);
+
+godot_int GDAPI godot_callable_call(const godot_callable *p_self, const godot_variant **p_arguments, godot_int p_argcount, godot_variant *r_return_value);
+void GDAPI godot_callable_call_deferred(const godot_callable *p_self, const godot_variant **p_arguments, godot_int p_argcount);
+
+godot_bool GDAPI godot_callable_is_null(const godot_callable *p_self);
+godot_bool GDAPI godot_callable_is_custom(const godot_callable *p_self);
+godot_bool GDAPI godot_callable_is_standard(const godot_callable *p_self);
+
+godot_object GDAPI *godot_callable_get_object(const godot_callable *p_self);
+uint64_t GDAPI godot_callable_get_object_id(const godot_callable *p_self);
+godot_string_name GDAPI godot_callable_get_method(const godot_callable *p_self);
+
+uint32_t GDAPI godot_callable_hash(const godot_callable *p_self);
+
+godot_string GDAPI godot_callable_as_string(const godot_callable *p_self);
+
+godot_bool GDAPI godot_callable_operator_equal(const godot_callable *p_self, const godot_callable *p_other);
+godot_bool GDAPI godot_callable_operator_less(const godot_callable *p_self, const godot_callable *p_other);
+
+// Signal
+
+void GDAPI godot_signal_new_with_object(godot_signal *r_dest, const godot_object *p_object, const godot_string_name *p_name);
+void GDAPI godot_signal_new_with_object_id(godot_signal *r_dest, uint64_t p_objectid, const godot_string_name *p_name);
+void GDAPI godot_signal_new_copy(godot_signal *r_dest, const godot_signal *p_src);
+
+void GDAPI godot_signal_destroy(godot_signal *p_self);
+
+godot_int GDAPI godot_signal_emit(const godot_signal *p_self, const godot_variant **p_arguments, godot_int p_argcount);
+
+godot_int GDAPI godot_signal_connect(godot_signal *p_self, const godot_callable *p_callable, const godot_array *p_binds, uint32_t p_flags);
+void GDAPI godot_signal_disconnect(godot_signal *p_self, const godot_callable *p_callable);
+
+godot_bool GDAPI godot_signal_is_null(const godot_signal *p_self);
+godot_bool GDAPI godot_signal_is_connected(const godot_signal *p_self, const godot_callable *p_callable);
+
+godot_array GDAPI godot_signal_get_connections(const godot_signal *p_self);
+
+godot_object GDAPI *godot_signal_get_object(const godot_signal *p_self);
+uint64_t GDAPI godot_signal_get_object_id(const godot_signal *p_self);
+godot_string_name GDAPI godot_signal_get_name(const godot_signal *p_self);
+
+godot_string GDAPI godot_signal_as_string(const godot_signal *p_self);
+
+godot_bool GDAPI godot_signal_operator_equal(const godot_signal *p_self, const godot_signal *p_other);
+godot_bool GDAPI godot_signal_operator_less(const godot_signal *p_self, const godot_signal *p_other);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/modules/gdnative/include/gdnative/gdnative.h b/modules/gdnative/include/gdnative/gdnative.h
index 6fdca30122..6a0a375da8 100644
--- a/modules/gdnative/include/gdnative/gdnative.h
+++ b/modules/gdnative/include/gdnative/gdnative.h
@@ -144,15 +144,15 @@ typedef void godot_object;
#include <gdnative/string_name.h>
-////// Vector2
+////// Vector2 & Vector2i
#include <gdnative/vector2.h>
-////// Rect2
+////// Rect2 & Rect2i
#include <gdnative/rect2.h>
-////// Vector3
+////// Vector3 & Vector3i
#include <gdnative/vector3.h>
@@ -192,6 +192,10 @@ typedef void godot_object;
#include <gdnative/rid.h>
+/////// Callable & Signal
+
+#include <gdnative/callable.h>
+
/////// Dictionary
#include <gdnative/dictionary.h>
@@ -200,8 +204,8 @@ typedef void godot_object;
#include <gdnative/array.h>
-// single API file for Pool*Array
-#include <gdnative/pool_arrays.h>
+// single API file for Packed*Array
+#include <gdnative/packed_arrays.h>
void GDAPI godot_object_destroy(godot_object *p_o);
@@ -289,7 +293,9 @@ void GDAPI *godot_get_class_tag(const godot_string_name *p_class);
godot_object GDAPI *godot_object_cast_to(const godot_object *p_object, void *p_class_tag);
// equivalent of GDScript's instance_from_id
-godot_object GDAPI *godot_instance_from_id(godot_int p_instance_id);
+godot_object GDAPI *godot_instance_from_id(uint64_t p_instance_id);
+
+uint64_t GDAPI godot_object_get_instance_id(const godot_object *p_object);
#ifdef __cplusplus
}
diff --git a/modules/gdnative/include/gdnative/pool_arrays.h b/modules/gdnative/include/gdnative/packed_arrays.h
index c610377f54..d5bad70bdc 100644
--- a/modules/gdnative/include/gdnative/pool_arrays.h
+++ b/modules/gdnative/include/gdnative/packed_arrays.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* pool_arrays.h */
+/* packed_arrays.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef GODOT_POOL_ARRAYS_H
-#define GODOT_POOL_ARRAYS_H
+#ifndef GODOT_PACKED_ARRAYS_H
+#define GODOT_PACKED_ARRAYS_H
#ifdef __cplusplus
extern "C" {
@@ -39,7 +39,7 @@ extern "C" {
/////// PackedByteArray
-#define GODOT_PACKED_BYTE_ARRAY_SIZE sizeof(void *)
+#define GODOT_PACKED_BYTE_ARRAY_SIZE (2 * sizeof(void *))
#ifndef GODOT_CORE_API_GODOT_PACKED_BYTE_ARRAY_TYPE_DEFINED
#define GODOT_CORE_API_GODOT_PACKED_BYTE_ARRAY_TYPE_DEFINED
@@ -50,29 +50,51 @@ typedef struct {
/////// PackedInt32Array
-#define GODOT_PACKED_INT_ARRAY_SIZE sizeof(void *)
+#define GODOT_PACKED_INT32_ARRAY_SIZE (2 * sizeof(void *))
-#ifndef GODOT_CORE_API_GODOT_PACKED_INT_ARRAY_TYPE_DEFINED
-#define GODOT_CORE_API_GODOT_PACKED_INT_ARRAY_TYPE_DEFINED
+#ifndef GODOT_CORE_API_GODOT_PACKED_INT32_ARRAY_TYPE_DEFINED
+#define GODOT_CORE_API_GODOT_PACKED_INT32_ARRAY_TYPE_DEFINED
typedef struct {
- uint8_t _dont_touch_that[GODOT_PACKED_INT_ARRAY_SIZE];
-} godot_packed_int_array;
+ uint8_t _dont_touch_that[GODOT_PACKED_INT32_ARRAY_SIZE];
+} godot_packed_int32_array;
+#endif
+
+/////// PackedInt64Array
+
+#define GODOT_PACKED_INT64_ARRAY_SIZE (2 * sizeof(void *))
+
+#ifndef GODOT_CORE_API_GODOT_PACKED_INT64_ARRAY_TYPE_DEFINED
+#define GODOT_CORE_API_GODOT_PACKED_INT64_ARRAY_TYPE_DEFINED
+typedef struct {
+ uint8_t _dont_touch_that[GODOT_PACKED_INT64_ARRAY_SIZE];
+} godot_packed_int64_array;
#endif
/////// PackedFloat32Array
-#define GODOT_PACKED_REAL_ARRAY_SIZE sizeof(void *)
+#define GODOT_PACKED_FLOAT32_ARRAY_SIZE (2 * sizeof(void *))
+
+#ifndef GODOT_CORE_API_GODOT_PACKED_FLOAT32_ARRAY_TYPE_DEFINED
+#define GODOT_CORE_API_GODOT_PACKED_FLOAT32_ARRAY_TYPE_DEFINED
+typedef struct {
+ uint8_t _dont_touch_that[GODOT_PACKED_FLOAT32_ARRAY_SIZE];
+} godot_packed_float32_array;
+#endif
+
+/////// PackedFloat64Array
-#ifndef GODOT_CORE_API_GODOT_PACKED_REAL_ARRAY_TYPE_DEFINED
-#define GODOT_CORE_API_GODOT_PACKED_REAL_ARRAY_TYPE_DEFINED
+#define GODOT_PACKED_FLOAT64_ARRAY_SIZE (2 * sizeof(void *))
+
+#ifndef GODOT_CORE_API_GODOT_PACKED_FLOAT64_ARRAY_TYPE_DEFINED
+#define GODOT_CORE_API_GODOT_PACKED_FLOAT64_ARRAY_TYPE_DEFINED
typedef struct {
- uint8_t _dont_touch_that[GODOT_PACKED_REAL_ARRAY_SIZE];
-} godot_packed_real_array;
+ uint8_t _dont_touch_that[GODOT_PACKED_FLOAT64_ARRAY_SIZE];
+} godot_packed_float64_array;
#endif
/////// PackedStringArray
-#define GODOT_PACKED_STRING_ARRAY_SIZE sizeof(void *)
+#define GODOT_PACKED_STRING_ARRAY_SIZE (2 * sizeof(void *))
#ifndef GODOT_CORE_API_GODOT_PACKED_STRING_ARRAY_TYPE_DEFINED
#define GODOT_CORE_API_GODOT_PACKED_STRING_ARRAY_TYPE_DEFINED
@@ -83,7 +105,7 @@ typedef struct {
/////// PackedVector2Array
-#define GODOT_PACKED_VECTOR2_ARRAY_SIZE sizeof(void *)
+#define GODOT_PACKED_VECTOR2_ARRAY_SIZE (2 * sizeof(void *))
#ifndef GODOT_CORE_API_GODOT_PACKED_VECTOR2_ARRAY_TYPE_DEFINED
#define GODOT_CORE_API_GODOT_PACKED_VECTOR2_ARRAY_TYPE_DEFINED
@@ -94,7 +116,7 @@ typedef struct {
/////// PackedVector3Array
-#define GODOT_PACKED_VECTOR3_ARRAY_SIZE sizeof(void *)
+#define GODOT_PACKED_VECTOR3_ARRAY_SIZE (2 * sizeof(void *))
#ifndef GODOT_CORE_API_GODOT_PACKED_VECTOR3_ARRAY_TYPE_DEFINED
#define GODOT_CORE_API_GODOT_PACKED_VECTOR3_ARRAY_TYPE_DEFINED
@@ -105,7 +127,7 @@ typedef struct {
/////// PackedColorArray
-#define GODOT_PACKED_COLOR_ARRAY_SIZE sizeof(void *)
+#define GODOT_PACKED_COLOR_ARRAY_SIZE (2 * sizeof(void *))
#ifndef GODOT_CORE_API_GODOT_PACKED_COLOR_ARRAY_TYPE_DEFINED
#define GODOT_CORE_API_GODOT_PACKED_COLOR_ARRAY_TYPE_DEFINED
@@ -159,63 +181,121 @@ godot_bool GDAPI godot_packed_byte_array_empty(const godot_packed_byte_array *p_
void GDAPI godot_packed_byte_array_destroy(godot_packed_byte_array *p_self);
-// int
+// int32
+
+void GDAPI godot_packed_int32_array_new(godot_packed_int32_array *r_dest);
+void GDAPI godot_packed_int32_array_new_copy(godot_packed_int32_array *r_dest, const godot_packed_int32_array *p_src);
+void GDAPI godot_packed_int32_array_new_with_array(godot_packed_int32_array *r_dest, const godot_array *p_a);
+
+void GDAPI godot_packed_int32_array_append(godot_packed_int32_array *p_self, const int32_t p_data);
+
+void GDAPI godot_packed_int32_array_append_array(godot_packed_int32_array *p_self, const godot_packed_int32_array *p_array);
+
+godot_error GDAPI godot_packed_int32_array_insert(godot_packed_int32_array *p_self, const godot_int p_idx, const int32_t p_data);
+
+void GDAPI godot_packed_int32_array_invert(godot_packed_int32_array *p_self);
+
+void GDAPI godot_packed_int32_array_push_back(godot_packed_int32_array *p_self, const int32_t p_data);
+
+void GDAPI godot_packed_int32_array_remove(godot_packed_int32_array *p_self, const godot_int p_idx);
+
+void GDAPI godot_packed_int32_array_resize(godot_packed_int32_array *p_self, const godot_int p_size);
+
+void GDAPI godot_packed_int32_array_set(godot_packed_int32_array *p_self, const godot_int p_idx, const int32_t p_data);
+int32_t GDAPI godot_packed_int32_array_get(const godot_packed_int32_array *p_self, const godot_int p_idx);
+
+godot_int GDAPI godot_packed_int32_array_size(const godot_packed_int32_array *p_self);
+
+godot_bool GDAPI godot_packed_int32_array_empty(const godot_packed_int32_array *p_self);
+
+void GDAPI godot_packed_int32_array_destroy(godot_packed_int32_array *p_self);
+
+// int64
+
+void GDAPI godot_packed_int64_array_new(godot_packed_int64_array *r_dest);
+void GDAPI godot_packed_int64_array_new_copy(godot_packed_int64_array *r_dest, const godot_packed_int64_array *p_src);
+void GDAPI godot_packed_int64_array_new_with_array(godot_packed_int64_array *r_dest, const godot_array *p_a);
+
+void GDAPI godot_packed_int64_array_append(godot_packed_int64_array *p_self, const int64_t p_data);
+
+void GDAPI godot_packed_int64_array_append_array(godot_packed_int64_array *p_self, const godot_packed_int64_array *p_array);
+
+godot_error GDAPI godot_packed_int64_array_insert(godot_packed_int64_array *p_self, const godot_int p_idx, const int64_t p_data);
+
+void GDAPI godot_packed_int64_array_invert(godot_packed_int64_array *p_self);
+
+void GDAPI godot_packed_int64_array_push_back(godot_packed_int64_array *p_self, const int64_t p_data);
+
+void GDAPI godot_packed_int64_array_remove(godot_packed_int64_array *p_self, const godot_int p_idx);
+
+void GDAPI godot_packed_int64_array_resize(godot_packed_int64_array *p_self, const godot_int p_size);
+
+void GDAPI godot_packed_int64_array_set(godot_packed_int64_array *p_self, const godot_int p_idx, const int64_t p_data);
+int64_t GDAPI godot_packed_int64_array_get(const godot_packed_int64_array *p_self, const godot_int p_idx);
+
+godot_int GDAPI godot_packed_int64_array_size(const godot_packed_int64_array *p_self);
+
+godot_bool GDAPI godot_packed_int64_array_empty(const godot_packed_int64_array *p_self);
+
+void GDAPI godot_packed_int64_array_destroy(godot_packed_int64_array *p_self);
+
+// float32
-void GDAPI godot_packed_int_array_new(godot_packed_int_array *r_dest);
-void GDAPI godot_packed_int_array_new_copy(godot_packed_int_array *r_dest, const godot_packed_int_array *p_src);
-void GDAPI godot_packed_int_array_new_with_array(godot_packed_int_array *r_dest, const godot_array *p_a);
+void GDAPI godot_packed_float32_array_new(godot_packed_float32_array *r_dest);
+void GDAPI godot_packed_float32_array_new_copy(godot_packed_float32_array *r_dest, const godot_packed_float32_array *p_src);
+void GDAPI godot_packed_float32_array_new_with_array(godot_packed_float32_array *r_dest, const godot_array *p_a);
-void GDAPI godot_packed_int_array_append(godot_packed_int_array *p_self, const godot_int p_data);
+void GDAPI godot_packed_float32_array_append(godot_packed_float32_array *p_self, const float p_data);
-void GDAPI godot_packed_int_array_append_array(godot_packed_int_array *p_self, const godot_packed_int_array *p_array);
+void GDAPI godot_packed_float32_array_append_array(godot_packed_float32_array *p_self, const godot_packed_float32_array *p_array);
-godot_error GDAPI godot_packed_int_array_insert(godot_packed_int_array *p_self, const godot_int p_idx, const godot_int p_data);
+godot_error GDAPI godot_packed_float32_array_insert(godot_packed_float32_array *p_self, const godot_int p_idx, const float p_data);
-void GDAPI godot_packed_int_array_invert(godot_packed_int_array *p_self);
+void GDAPI godot_packed_float32_array_invert(godot_packed_float32_array *p_self);
-void GDAPI godot_packed_int_array_push_back(godot_packed_int_array *p_self, const godot_int p_data);
+void GDAPI godot_packed_float32_array_push_back(godot_packed_float32_array *p_self, const float p_data);
-void GDAPI godot_packed_int_array_remove(godot_packed_int_array *p_self, const godot_int p_idx);
+void GDAPI godot_packed_float32_array_remove(godot_packed_float32_array *p_self, const godot_int p_idx);
-void GDAPI godot_packed_int_array_resize(godot_packed_int_array *p_self, const godot_int p_size);
+void GDAPI godot_packed_float32_array_resize(godot_packed_float32_array *p_self, const godot_int p_size);
-void GDAPI godot_packed_int_array_set(godot_packed_int_array *p_self, const godot_int p_idx, const godot_int p_data);
-godot_int GDAPI godot_packed_int_array_get(const godot_packed_int_array *p_self, const godot_int p_idx);
+void GDAPI godot_packed_float32_array_set(godot_packed_float32_array *p_self, const godot_int p_idx, const float p_data);
+float GDAPI godot_packed_float32_array_get(const godot_packed_float32_array *p_self, const godot_int p_idx);
-godot_int GDAPI godot_packed_int_array_size(const godot_packed_int_array *p_self);
+godot_int GDAPI godot_packed_float32_array_size(const godot_packed_float32_array *p_self);
-godot_bool GDAPI godot_packed_int_array_empty(const godot_packed_int_array *p_self);
+godot_bool GDAPI godot_packed_float32_array_empty(const godot_packed_float32_array *p_self);
-void GDAPI godot_packed_int_array_destroy(godot_packed_int_array *p_self);
+void GDAPI godot_packed_float32_array_destroy(godot_packed_float32_array *p_self);
-// real
+// float64
-void GDAPI godot_packed_real_array_new(godot_packed_real_array *r_dest);
-void GDAPI godot_packed_real_array_new_copy(godot_packed_real_array *r_dest, const godot_packed_real_array *p_src);
-void GDAPI godot_packed_real_array_new_with_array(godot_packed_real_array *r_dest, const godot_array *p_a);
+void GDAPI godot_packed_float64_array_new(godot_packed_float64_array *r_dest);
+void GDAPI godot_packed_float64_array_new_copy(godot_packed_float64_array *r_dest, const godot_packed_float64_array *p_src);
+void GDAPI godot_packed_float64_array_new_with_array(godot_packed_float64_array *r_dest, const godot_array *p_a);
-void GDAPI godot_packed_real_array_append(godot_packed_real_array *p_self, const godot_real p_data);
+void GDAPI godot_packed_float64_array_append(godot_packed_float64_array *p_self, const double p_data);
-void GDAPI godot_packed_real_array_append_array(godot_packed_real_array *p_self, const godot_packed_real_array *p_array);
+void GDAPI godot_packed_float64_array_append_array(godot_packed_float64_array *p_self, const godot_packed_float64_array *p_array);
-godot_error GDAPI godot_packed_real_array_insert(godot_packed_real_array *p_self, const godot_int p_idx, const godot_real p_data);
+godot_error GDAPI godot_packed_float64_array_insert(godot_packed_float64_array *p_self, const godot_int p_idx, const double p_data);
-void GDAPI godot_packed_real_array_invert(godot_packed_real_array *p_self);
+void GDAPI godot_packed_float64_array_invert(godot_packed_float64_array *p_self);
-void GDAPI godot_packed_real_array_push_back(godot_packed_real_array *p_self, const godot_real p_data);
+void GDAPI godot_packed_float64_array_push_back(godot_packed_float64_array *p_self, const double p_data);
-void GDAPI godot_packed_real_array_remove(godot_packed_real_array *p_self, const godot_int p_idx);
+void GDAPI godot_packed_float64_array_remove(godot_packed_float64_array *p_self, const godot_int p_idx);
-void GDAPI godot_packed_real_array_resize(godot_packed_real_array *p_self, const godot_int p_size);
+void GDAPI godot_packed_float64_array_resize(godot_packed_float64_array *p_self, const godot_int p_size);
-void GDAPI godot_packed_real_array_set(godot_packed_real_array *p_self, const godot_int p_idx, const godot_real p_data);
-godot_real GDAPI godot_packed_real_array_get(const godot_packed_real_array *p_self, const godot_int p_idx);
+void GDAPI godot_packed_float64_array_set(godot_packed_float64_array *p_self, const godot_int p_idx, const double p_data);
+double GDAPI godot_packed_float64_array_get(const godot_packed_float64_array *p_self, const godot_int p_idx);
-godot_int GDAPI godot_packed_real_array_size(const godot_packed_real_array *p_self);
+godot_int GDAPI godot_packed_float64_array_size(const godot_packed_float64_array *p_self);
-godot_bool GDAPI godot_packed_real_array_empty(const godot_packed_real_array *p_self);
+godot_bool GDAPI godot_packed_float64_array_empty(const godot_packed_float64_array *p_self);
-void GDAPI godot_packed_real_array_destroy(godot_packed_real_array *p_self);
+void GDAPI godot_packed_float64_array_destroy(godot_packed_float64_array *p_self);
// string
diff --git a/modules/gdnative/include/gdnative/rect2.h b/modules/gdnative/include/gdnative/rect2.h
index 0ecf072471..f317afc9da 100644
--- a/modules/gdnative/include/gdnative/rect2.h
+++ b/modules/gdnative/include/gdnative/rect2.h
@@ -44,6 +44,13 @@ typedef struct godot_rect2 {
} godot_rect2;
#endif
+#ifndef GODOT_CORE_API_GODOT_RECT2I_TYPE_DEFINED
+#define GODOT_CORE_API_GODOT_RECT2I_TYPE_DEFINED
+typedef struct godot_rect2i {
+ uint8_t _dont_touch_that[16];
+} godot_rect2i;
+#endif
+
// reduce extern "C" nesting for VS2013
#ifdef __cplusplus
}
@@ -56,11 +63,15 @@ typedef struct godot_rect2 {
extern "C" {
#endif
+// Rect2
+
void GDAPI godot_rect2_new_with_position_and_size(godot_rect2 *r_dest, const godot_vector2 *p_pos, const godot_vector2 *p_size);
void GDAPI godot_rect2_new(godot_rect2 *r_dest, const godot_real p_x, const godot_real p_y, const godot_real p_width, const godot_real p_height);
godot_string GDAPI godot_rect2_as_string(const godot_rect2 *p_self);
+godot_rect2i GDAPI godot_rect2_as_rect2i(const godot_rect2 *p_self);
+
godot_real GDAPI godot_rect2_get_area(const godot_rect2 *p_self);
godot_bool GDAPI godot_rect2_intersects(const godot_rect2 *p_self, const godot_rect2 *p_b);
@@ -95,6 +106,49 @@ void GDAPI godot_rect2_set_position(godot_rect2 *p_self, const godot_vector2 *p_
void GDAPI godot_rect2_set_size(godot_rect2 *p_self, const godot_vector2 *p_size);
+// Rect2I
+
+void GDAPI godot_rect2i_new_with_position_and_size(godot_rect2i *r_dest, const godot_vector2i *p_pos, const godot_vector2i *p_size);
+void GDAPI godot_rect2i_new(godot_rect2i *r_dest, const godot_int p_x, const godot_int p_y, const godot_int p_width, const godot_int p_height);
+
+godot_string GDAPI godot_rect2i_as_string(const godot_rect2i *p_self);
+
+godot_rect2 GDAPI godot_rect2i_as_rect2(const godot_rect2i *p_self);
+
+godot_int GDAPI godot_rect2i_get_area(const godot_rect2i *p_self);
+
+godot_bool GDAPI godot_rect2i_intersects(const godot_rect2i *p_self, const godot_rect2i *p_b);
+
+godot_bool GDAPI godot_rect2i_encloses(const godot_rect2i *p_self, const godot_rect2i *p_b);
+
+godot_bool GDAPI godot_rect2i_has_no_area(const godot_rect2i *p_self);
+
+godot_rect2i GDAPI godot_rect2i_clip(const godot_rect2i *p_self, const godot_rect2i *p_b);
+
+godot_rect2i GDAPI godot_rect2i_merge(const godot_rect2i *p_self, const godot_rect2i *p_b);
+
+godot_bool GDAPI godot_rect2i_has_point(const godot_rect2i *p_self, const godot_vector2i *p_point);
+
+godot_rect2i GDAPI godot_rect2i_grow(const godot_rect2i *p_self, const godot_int p_by);
+
+godot_rect2i GDAPI godot_rect2i_grow_individual(const godot_rect2i *p_self, const godot_int p_left, const godot_int p_top, const godot_int p_right, const godot_int p_bottom);
+
+godot_rect2i GDAPI godot_rect2i_grow_margin(const godot_rect2i *p_self, const godot_int p_margin, const godot_int p_by);
+
+godot_rect2i GDAPI godot_rect2i_abs(const godot_rect2i *p_self);
+
+godot_rect2i GDAPI godot_rect2i_expand(const godot_rect2i *p_self, const godot_vector2i *p_to);
+
+godot_bool GDAPI godot_rect2i_operator_equal(const godot_rect2i *p_self, const godot_rect2i *p_b);
+
+godot_vector2i GDAPI godot_rect2i_get_position(const godot_rect2i *p_self);
+
+godot_vector2i GDAPI godot_rect2i_get_size(const godot_rect2i *p_self);
+
+void GDAPI godot_rect2i_set_position(godot_rect2i *p_self, const godot_vector2i *p_pos);
+
+void GDAPI godot_rect2i_set_size(godot_rect2i *p_self, const godot_vector2i *p_size);
+
#ifdef __cplusplus
}
#endif
diff --git a/modules/gdnative/include/gdnative/rid.h b/modules/gdnative/include/gdnative/rid.h
index 04661cedc8..73b601dc04 100644
--- a/modules/gdnative/include/gdnative/rid.h
+++ b/modules/gdnative/include/gdnative/rid.h
@@ -37,7 +37,7 @@ extern "C" {
#include <stdint.h>
-#define GODOT_RID_SIZE sizeof(void *)
+#define GODOT_RID_SIZE sizeof(uint64_t)
#ifndef GODOT_CORE_API_GODOT_RID_TYPE_DEFINED
#define GODOT_CORE_API_GODOT_RID_TYPE_DEFINED
diff --git a/modules/gdnative/include/gdnative/variant.h b/modules/gdnative/include/gdnative/variant.h
index 934e856fbf..0a611b76e9 100644
--- a/modules/gdnative/include/gdnative/variant.h
+++ b/modules/gdnative/include/gdnative/variant.h
@@ -37,7 +37,7 @@ extern "C" {
#include <stdint.h>
-#define GODOT_VARIANT_SIZE (16 + sizeof(void *))
+#define GODOT_VARIANT_SIZE (16 + sizeof(int64_t))
#ifndef GODOT_CORE_API_GODOT_VARIANT_TYPE_DEFINED
#define GODOT_CORE_API_GODOT_VARIANT_TYPE_DEFINED
@@ -71,16 +71,21 @@ typedef enum godot_variant_type {
// misc types
GODOT_VARIANT_TYPE_COLOR,
+ GODOT_VARIANT_TYPE_STRING_NAME,
GODOT_VARIANT_TYPE_NODE_PATH,
GODOT_VARIANT_TYPE_RID,
GODOT_VARIANT_TYPE_OBJECT,
+ GODOT_VARIANT_TYPE_CALLABLE,
+ GODOT_VARIANT_TYPE_SIGNAL,
GODOT_VARIANT_TYPE_DICTIONARY,
GODOT_VARIANT_TYPE_ARRAY,
// arrays
GODOT_VARIANT_TYPE_PACKED_BYTE_ARRAY,
- GODOT_VARIANT_TYPE_PACKED_INT_ARRAY,
- GODOT_VARIANT_TYPE_PACKED_REAL_ARRAY,
+ GODOT_VARIANT_TYPE_PACKED_INT32_ARRAY,
+ GODOT_VARIANT_TYPE_PACKED_INT64_ARRAY,
+ GODOT_VARIANT_TYPE_PACKED_FLOAT32_ARRAY,
+ GODOT_VARIANT_TYPE_PACKED_FLOAT64_ARRAY,
GODOT_VARIANT_TYPE_PACKED_STRING_ARRAY,
GODOT_VARIANT_TYPE_PACKED_VECTOR2_ARRAY,
GODOT_VARIANT_TYPE_PACKED_VECTOR3_ARRAY,
@@ -149,15 +154,17 @@ typedef enum godot_variant_operator {
#include <gdnative/aabb.h>
#include <gdnative/array.h>
#include <gdnative/basis.h>
+#include <gdnative/callable.h>
#include <gdnative/color.h>
#include <gdnative/dictionary.h>
#include <gdnative/node_path.h>
+#include <gdnative/packed_arrays.h>
#include <gdnative/plane.h>
-#include <gdnative/pool_arrays.h>
#include <gdnative/quat.h>
#include <gdnative/rect2.h>
#include <gdnative/rid.h>
#include <gdnative/string.h>
+#include <gdnative/string_name.h>
#include <gdnative/transform.h>
#include <gdnative/transform2d.h>
#include <gdnative/variant.h>
@@ -181,9 +188,13 @@ void GDAPI godot_variant_new_uint(godot_variant *r_dest, const uint64_t p_i);
void GDAPI godot_variant_new_int(godot_variant *r_dest, const int64_t p_i);
void GDAPI godot_variant_new_real(godot_variant *r_dest, const double p_r);
void GDAPI godot_variant_new_string(godot_variant *r_dest, const godot_string *p_s);
+void GDAPI godot_variant_new_string_name(godot_variant *r_dest, const godot_string_name *p_s);
void GDAPI godot_variant_new_vector2(godot_variant *r_dest, const godot_vector2 *p_v2);
+void GDAPI godot_variant_new_vector2i(godot_variant *r_dest, const godot_vector2i *p_v2);
void GDAPI godot_variant_new_rect2(godot_variant *r_dest, const godot_rect2 *p_rect2);
+void GDAPI godot_variant_new_rect2i(godot_variant *r_dest, const godot_rect2i *p_rect2);
void GDAPI godot_variant_new_vector3(godot_variant *r_dest, const godot_vector3 *p_v3);
+void GDAPI godot_variant_new_vector3i(godot_variant *r_dest, const godot_vector3i *p_v3);
void GDAPI godot_variant_new_transform2d(godot_variant *r_dest, const godot_transform2d *p_t2d);
void GDAPI godot_variant_new_plane(godot_variant *r_dest, const godot_plane *p_plane);
void GDAPI godot_variant_new_quat(godot_variant *r_dest, const godot_quat *p_quat);
@@ -193,12 +204,16 @@ void GDAPI godot_variant_new_transform(godot_variant *r_dest, const godot_transf
void GDAPI godot_variant_new_color(godot_variant *r_dest, const godot_color *p_color);
void GDAPI godot_variant_new_node_path(godot_variant *r_dest, const godot_node_path *p_np);
void GDAPI godot_variant_new_rid(godot_variant *r_dest, const godot_rid *p_rid);
+void GDAPI godot_variant_new_callable(godot_variant *r_dest, const godot_callable *p_callable);
+void GDAPI godot_variant_new_signal(godot_variant *r_dest, const godot_signal *p_signal);
void GDAPI godot_variant_new_object(godot_variant *r_dest, const godot_object *p_obj);
void GDAPI godot_variant_new_dictionary(godot_variant *r_dest, const godot_dictionary *p_dict);
void GDAPI godot_variant_new_array(godot_variant *r_dest, const godot_array *p_arr);
void GDAPI godot_variant_new_packed_byte_array(godot_variant *r_dest, const godot_packed_byte_array *p_pba);
-void GDAPI godot_variant_new_packed_int_array(godot_variant *r_dest, const godot_packed_int_array *p_pia);
-void GDAPI godot_variant_new_packed_real_array(godot_variant *r_dest, const godot_packed_real_array *p_pra);
+void GDAPI godot_variant_new_packed_int32_array(godot_variant *r_dest, const godot_packed_int32_array *p_pia);
+void GDAPI godot_variant_new_packed_int64_array(godot_variant *r_dest, const godot_packed_int64_array *p_pia);
+void GDAPI godot_variant_new_packed_float32_array(godot_variant *r_dest, const godot_packed_float32_array *p_pra);
+void GDAPI godot_variant_new_packed_float64_array(godot_variant *r_dest, const godot_packed_float64_array *p_pra);
void GDAPI godot_variant_new_packed_string_array(godot_variant *r_dest, const godot_packed_string_array *p_psa);
void GDAPI godot_variant_new_packed_vector2_array(godot_variant *r_dest, const godot_packed_vector2_array *p_pv2a);
void GDAPI godot_variant_new_packed_vector3_array(godot_variant *r_dest, const godot_packed_vector3_array *p_pv3a);
@@ -209,9 +224,13 @@ uint64_t GDAPI godot_variant_as_uint(const godot_variant *p_self);
int64_t GDAPI godot_variant_as_int(const godot_variant *p_self);
double GDAPI godot_variant_as_real(const godot_variant *p_self);
godot_string GDAPI godot_variant_as_string(const godot_variant *p_self);
+godot_string_name GDAPI godot_variant_as_string_name(const godot_variant *p_self);
godot_vector2 GDAPI godot_variant_as_vector2(const godot_variant *p_self);
+godot_vector2i GDAPI godot_variant_as_vector2i(const godot_variant *p_self);
godot_rect2 GDAPI godot_variant_as_rect2(const godot_variant *p_self);
+godot_rect2i GDAPI godot_variant_as_rect2i(const godot_variant *p_self);
godot_vector3 GDAPI godot_variant_as_vector3(const godot_variant *p_self);
+godot_vector3i GDAPI godot_variant_as_vector3i(const godot_variant *p_self);
godot_transform2d GDAPI godot_variant_as_transform2d(const godot_variant *p_self);
godot_plane GDAPI godot_variant_as_plane(const godot_variant *p_self);
godot_quat GDAPI godot_variant_as_quat(const godot_variant *p_self);
@@ -221,12 +240,16 @@ godot_transform GDAPI godot_variant_as_transform(const godot_variant *p_self);
godot_color GDAPI godot_variant_as_color(const godot_variant *p_self);
godot_node_path GDAPI godot_variant_as_node_path(const godot_variant *p_self);
godot_rid GDAPI godot_variant_as_rid(const godot_variant *p_self);
+godot_callable GDAPI godot_variant_as_callable(const godot_variant *p_self);
+godot_signal GDAPI godot_variant_as_signal(const godot_variant *p_self);
godot_object GDAPI *godot_variant_as_object(const godot_variant *p_self);
godot_dictionary GDAPI godot_variant_as_dictionary(const godot_variant *p_self);
godot_array GDAPI godot_variant_as_array(const godot_variant *p_self);
godot_packed_byte_array GDAPI godot_variant_as_packed_byte_array(const godot_variant *p_self);
-godot_packed_int_array GDAPI godot_variant_as_packed_int_array(const godot_variant *p_self);
-godot_packed_real_array GDAPI godot_variant_as_packed_real_array(const godot_variant *p_self);
+godot_packed_int32_array GDAPI godot_variant_as_packed_int32_array(const godot_variant *p_self);
+godot_packed_int64_array GDAPI godot_variant_as_packed_int64_array(const godot_variant *p_self);
+godot_packed_float32_array GDAPI godot_variant_as_packed_float32_array(const godot_variant *p_self);
+godot_packed_float64_array GDAPI godot_variant_as_packed_float64_array(const godot_variant *p_self);
godot_packed_string_array GDAPI godot_variant_as_packed_string_array(const godot_variant *p_self);
godot_packed_vector2_array GDAPI godot_variant_as_packed_vector2_array(const godot_variant *p_self);
godot_packed_vector3_array GDAPI godot_variant_as_packed_vector3_array(const godot_variant *p_self);
@@ -239,6 +262,7 @@ godot_bool GDAPI godot_variant_has_method(const godot_variant *p_self, const god
godot_bool GDAPI godot_variant_operator_equal(const godot_variant *p_self, const godot_variant *p_other);
godot_bool GDAPI godot_variant_operator_less(const godot_variant *p_self, const godot_variant *p_other);
+uint32_t GDAPI godot_variant_hash(const godot_variant *p_self);
godot_bool GDAPI godot_variant_hash_compare(const godot_variant *p_self, const godot_variant *p_other);
godot_bool GDAPI godot_variant_booleanize(const godot_variant *p_self);
diff --git a/modules/gdnative/include/gdnative/vector2.h b/modules/gdnative/include/gdnative/vector2.h
index c11e23a586..35b02c5a75 100644
--- a/modules/gdnative/include/gdnative/vector2.h
+++ b/modules/gdnative/include/gdnative/vector2.h
@@ -46,6 +46,15 @@ typedef struct {
} godot_vector2;
#endif
+#define GODOT_VECTOR2I_SIZE 8
+
+#ifndef GODOT_CORE_API_GODOT_VECTOR2I_TYPE_DEFINED
+#define GODOT_CORE_API_GODOT_VECTOR2I_TYPE_DEFINED
+typedef struct {
+ uint8_t _dont_touch_that[GODOT_VECTOR2I_SIZE];
+} godot_vector2i;
+#endif
+
// reduce extern "C" nesting for VS2013
#ifdef __cplusplus
}
@@ -57,10 +66,14 @@ typedef struct {
extern "C" {
#endif
+// Vector2
+
void GDAPI godot_vector2_new(godot_vector2 *r_dest, const godot_real p_x, const godot_real p_y);
godot_string GDAPI godot_vector2_as_string(const godot_vector2 *p_self);
+godot_vector2i GDAPI godot_vector2_as_vector2i(const godot_vector2 *p_self);
+
godot_vector2 GDAPI godot_vector2_normalized(const godot_vector2 *p_self);
godot_real GDAPI godot_vector2_length(const godot_vector2 *p_self);
@@ -93,6 +106,8 @@ godot_vector2 GDAPI godot_vector2_tangent(const godot_vector2 *p_self);
godot_vector2 GDAPI godot_vector2_floor(const godot_vector2 *p_self);
+godot_vector2 GDAPI godot_vector2_sign(const godot_vector2 *p_self);
+
godot_vector2 GDAPI godot_vector2_snapped(const godot_vector2 *p_self, const godot_vector2 *p_by);
godot_real GDAPI godot_vector2_aspect(const godot_vector2 *p_self);
@@ -135,6 +150,46 @@ godot_real GDAPI godot_vector2_get_x(const godot_vector2 *p_self);
godot_real GDAPI godot_vector2_get_y(const godot_vector2 *p_self);
+// Vector2i
+
+void GDAPI godot_vector2i_new(godot_vector2i *r_dest, const godot_int p_x, const godot_int p_y);
+
+godot_string GDAPI godot_vector2i_as_string(const godot_vector2i *p_self);
+
+godot_vector2 GDAPI godot_vector2i_as_vector2(const godot_vector2i *p_self);
+
+godot_real GDAPI godot_vector2i_aspect(const godot_vector2i *p_self);
+
+godot_vector2i GDAPI godot_vector2i_abs(const godot_vector2i *p_self);
+
+godot_vector2i GDAPI godot_vector2i_sign(const godot_vector2i *p_self);
+
+godot_vector2i GDAPI godot_vector2i_operator_add(const godot_vector2i *p_self, const godot_vector2i *p_b);
+
+godot_vector2i GDAPI godot_vector2i_operator_subtract(const godot_vector2i *p_self, const godot_vector2i *p_b);
+
+godot_vector2i GDAPI godot_vector2i_operator_multiply_vector(const godot_vector2i *p_self, const godot_vector2i *p_b);
+
+godot_vector2i GDAPI godot_vector2i_operator_multiply_scalar(const godot_vector2i *p_self, const godot_int p_b);
+
+godot_vector2i GDAPI godot_vector2i_operator_divide_vector(const godot_vector2i *p_self, const godot_vector2i *p_b);
+
+godot_vector2i GDAPI godot_vector2i_operator_divide_scalar(const godot_vector2i *p_self, const godot_int p_b);
+
+godot_bool GDAPI godot_vector2i_operator_equal(const godot_vector2i *p_self, const godot_vector2i *p_b);
+
+godot_bool GDAPI godot_vector2i_operator_less(const godot_vector2i *p_self, const godot_vector2i *p_b);
+
+godot_vector2i GDAPI godot_vector2i_operator_neg(const godot_vector2i *p_self);
+
+void GDAPI godot_vector2i_set_x(godot_vector2i *p_self, const godot_int p_x);
+
+void GDAPI godot_vector2i_set_y(godot_vector2i *p_self, const godot_int p_y);
+
+godot_int GDAPI godot_vector2i_get_x(const godot_vector2i *p_self);
+
+godot_int GDAPI godot_vector2i_get_y(const godot_vector2i *p_self);
+
#ifdef __cplusplus
}
#endif
diff --git a/modules/gdnative/include/gdnative/vector3.h b/modules/gdnative/include/gdnative/vector3.h
index 8ebf15b724..5127b8789b 100644
--- a/modules/gdnative/include/gdnative/vector3.h
+++ b/modules/gdnative/include/gdnative/vector3.h
@@ -46,6 +46,15 @@ typedef struct {
} godot_vector3;
#endif
+#define GODOT_VECTOR3I_SIZE 12
+
+#ifndef GODOT_CORE_API_GODOT_VECTOR3I_TYPE_DEFINED
+#define GODOT_CORE_API_GODOT_VECTOR3I_TYPE_DEFINED
+typedef struct {
+ uint8_t _dont_touch_that[GODOT_VECTOR3I_SIZE];
+} godot_vector3i;
+#endif
+
// reduce extern "C" nesting for VS2013
#ifdef __cplusplus
}
@@ -64,10 +73,14 @@ typedef enum {
GODOT_VECTOR3_AXIS_Z,
} godot_vector3_axis;
+// Vector3
+
void GDAPI godot_vector3_new(godot_vector3 *r_dest, const godot_real p_x, const godot_real p_y, const godot_real p_z);
godot_string GDAPI godot_vector3_as_string(const godot_vector3 *p_self);
+godot_vector3i GDAPI godot_vector3_as_vector3i(const godot_vector3 *p_self);
+
godot_int GDAPI godot_vector3_min_axis(const godot_vector3 *p_self);
godot_int GDAPI godot_vector3_max_axis(const godot_vector3 *p_self);
@@ -102,6 +115,8 @@ godot_basis GDAPI godot_vector3_to_diagonal_matrix(const godot_vector3 *p_self);
godot_vector3 GDAPI godot_vector3_abs(const godot_vector3 *p_self);
+godot_vector3 GDAPI godot_vector3_sign(const godot_vector3 *p_self);
+
godot_vector3 GDAPI godot_vector3_floor(const godot_vector3 *p_self);
godot_vector3 GDAPI godot_vector3_ceil(const godot_vector3 *p_self);
@@ -142,6 +157,44 @@ void GDAPI godot_vector3_set_axis(godot_vector3 *p_self, const godot_vector3_axi
godot_real GDAPI godot_vector3_get_axis(const godot_vector3 *p_self, const godot_vector3_axis p_axis);
+// Vector3i
+
+void GDAPI godot_vector3i_new(godot_vector3i *r_dest, const godot_int p_x, const godot_int p_y, const godot_int p_z);
+
+godot_string GDAPI godot_vector3i_as_string(const godot_vector3i *p_self);
+
+godot_vector3 GDAPI godot_vector3i_as_vector3(const godot_vector3i *p_self);
+
+godot_int GDAPI godot_vector3i_min_axis(const godot_vector3i *p_self);
+
+godot_int GDAPI godot_vector3i_max_axis(const godot_vector3i *p_self);
+
+godot_vector3i GDAPI godot_vector3i_abs(const godot_vector3i *p_self);
+
+godot_vector3i GDAPI godot_vector3i_sign(const godot_vector3i *p_self);
+
+godot_vector3i GDAPI godot_vector3i_operator_add(const godot_vector3i *p_self, const godot_vector3i *p_b);
+
+godot_vector3i GDAPI godot_vector3i_operator_subtract(const godot_vector3i *p_self, const godot_vector3i *p_b);
+
+godot_vector3i GDAPI godot_vector3i_operator_multiply_vector(const godot_vector3i *p_self, const godot_vector3i *p_b);
+
+godot_vector3i GDAPI godot_vector3i_operator_multiply_scalar(const godot_vector3i *p_self, const godot_int p_b);
+
+godot_vector3i GDAPI godot_vector3i_operator_divide_vector(const godot_vector3i *p_self, const godot_vector3i *p_b);
+
+godot_vector3i GDAPI godot_vector3i_operator_divide_scalar(const godot_vector3i *p_self, const godot_int p_b);
+
+godot_bool GDAPI godot_vector3i_operator_equal(const godot_vector3i *p_self, const godot_vector3i *p_b);
+
+godot_bool GDAPI godot_vector3i_operator_less(const godot_vector3i *p_self, const godot_vector3i *p_b);
+
+godot_vector3i GDAPI godot_vector3i_operator_neg(const godot_vector3i *p_self);
+
+void GDAPI godot_vector3i_set_axis(godot_vector3i *p_self, const godot_vector3_axis p_axis, const godot_int p_val);
+
+godot_int GDAPI godot_vector3i_get_axis(const godot_vector3i *p_self, const godot_vector3_axis p_axis);
+
#ifdef __cplusplus
}
#endif
diff --git a/modules/gdnative/include/nativescript/godot_nativescript.h b/modules/gdnative/include/nativescript/godot_nativescript.h
index 0fb5180103..d65b3f91f4 100644
--- a/modules/gdnative/include/nativescript/godot_nativescript.h
+++ b/modules/gdnative/include/nativescript/godot_nativescript.h
@@ -172,17 +172,17 @@ typedef struct {
godot_string hint_string;
godot_property_usage_flags usage;
godot_variant default_value;
-} godot_signal_argument;
+} godot_nativescript_signal_argument;
typedef struct {
godot_string name;
int num_args;
- godot_signal_argument *args;
+ godot_nativescript_signal_argument *args;
int num_default_args;
godot_variant *default_args;
-} godot_signal;
+} godot_nativescript_signal;
-void GDAPI godot_nativescript_register_signal(void *p_gdnative_handle, const char *p_name, const godot_signal *p_signal);
+void GDAPI godot_nativescript_register_signal(void *p_gdnative_handle, const char *p_name, const godot_nativescript_signal *p_signal);
void GDAPI *godot_nativescript_get_userdata(godot_object *p_instance);
diff --git a/modules/gdnative/nativescript/godot_nativescript.cpp b/modules/gdnative/nativescript/godot_nativescript.cpp
index 1bdac0dcb2..1aea8ad160 100644
--- a/modules/gdnative/nativescript/godot_nativescript.cpp
+++ b/modules/gdnative/nativescript/godot_nativescript.cpp
@@ -159,7 +159,7 @@ void GDAPI godot_nativescript_register_property(void *p_gdnative_handle, const c
E->get().properties.insert(p_path, property);
}
-void GDAPI godot_nativescript_register_signal(void *p_gdnative_handle, const char *p_name, const godot_signal *p_signal) {
+void GDAPI godot_nativescript_register_signal(void *p_gdnative_handle, const char *p_name, const godot_nativescript_signal *p_signal) {
String *s = (String *)p_gdnative_handle;
Map<StringName, NativeScriptDesc>::Element *E = NSL->library_classes[*s].find(p_name);
@@ -171,7 +171,7 @@ void GDAPI godot_nativescript_register_signal(void *p_gdnative_handle, const cha
for (int i = 0; i < p_signal->num_args; i++) {
PropertyInfo info;
- godot_signal_argument arg = p_signal->args[i];
+ godot_nativescript_signal_argument arg = p_signal->args[i];
info.hint = (PropertyHint)arg.hint;
info.hint_string = *(String *)&arg.hint_string;
@@ -184,7 +184,7 @@ void GDAPI godot_nativescript_register_signal(void *p_gdnative_handle, const cha
for (int i = 0; i < p_signal->num_default_args; i++) {
Variant *v;
- godot_signal_argument attrib = p_signal->args[i];
+ godot_nativescript_signal_argument attrib = p_signal->args[i];
v = (Variant *)&attrib.default_value;
diff --git a/modules/gdnavigation/nav_map.cpp b/modules/gdnavigation/nav_map.cpp
index c7df6dc1fb..4bea007104 100644
--- a/modules/gdnavigation/nav_map.cpp
+++ b/modules/gdnavigation/nav_map.cpp
@@ -299,7 +299,6 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
left = p->poly->points[prev].pos;
right = p->poly->points[prev_n].pos;
- //if (CLOCK_TANGENT(apex_point,left,(left+right)*0.5).dot(up) < 0){
if (p->poly->clockwise) {
SWAP(left, right);
}
diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp
index 92e07ab874..fc0c4b3138 100644
--- a/modules/gdscript/gdscript_function.cpp
+++ b/modules/gdscript/gdscript_function.cpp
@@ -1818,8 +1818,6 @@ Variant GDScriptFunctionState::resume(const Variant &p_arg) {
state.result = Variant();
if (completed) {
- _clear_stack();
-
if (first_state.is_valid()) {
first_state->emit_signal("completed", ret);
} else {
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index 57531ed13b..0e498f6895 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -3151,6 +3151,8 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
cf_while->body = alloc_node<BlockNode>();
cf_while->body->parent_block = p_block;
+ cf_while->body->can_break = true;
+ cf_while->body->can_continue = true;
p_block->sub_blocks.push_back(cf_while->body);
if (!_enter_indent_block(cf_while->body)) {
@@ -3165,7 +3167,6 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
if (error_set) {
return;
}
- p_block->has_return = cf_while->body->has_return;
p_block->statements.push_back(cf_while);
} break;
case GDScriptTokenizer::TK_CF_FOR: {
@@ -3278,6 +3279,8 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
cf_for->body = alloc_node<BlockNode>();
cf_for->body->parent_block = p_block;
+ cf_for->body->can_break = true;
+ cf_for->body->can_continue = true;
p_block->sub_blocks.push_back(cf_for->body);
if (!_enter_indent_block(cf_for->body)) {
@@ -3304,10 +3307,24 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
if (error_set) {
return;
}
- p_block->has_return = cf_for->body->has_return;
p_block->statements.push_back(cf_for);
} break;
case GDScriptTokenizer::TK_CF_CONTINUE: {
+ BlockNode *upper_block = p_block;
+ bool is_continue_valid = false;
+ while (upper_block) {
+ if (upper_block->can_continue) {
+ is_continue_valid = true;
+ break;
+ }
+ upper_block = upper_block->parent_block;
+ }
+
+ if (!is_continue_valid) {
+ _set_error("Unexpected keyword \"continue\" outside a loop.");
+ return;
+ }
+
_mark_line_as_safe(tokenizer->get_token_line());
tokenizer->advance();
ControlFlowNode *cf_continue = alloc_node<ControlFlowNode>();
@@ -3319,6 +3336,21 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
}
} break;
case GDScriptTokenizer::TK_CF_BREAK: {
+ BlockNode *upper_block = p_block;
+ bool is_break_valid = false;
+ while (upper_block) {
+ if (upper_block->can_break) {
+ is_break_valid = true;
+ break;
+ }
+ upper_block = upper_block->parent_block;
+ }
+
+ if (!is_break_valid) {
+ _set_error("Unexpected keyword \"break\" outside a loop.");
+ return;
+ }
+
_mark_line_as_safe(tokenizer->get_token_line());
tokenizer->advance();
ControlFlowNode *cf_break = alloc_node<ControlFlowNode>();
@@ -3384,6 +3416,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
BlockNode *compiled_branches = alloc_node<BlockNode>();
compiled_branches->parent_block = p_block;
compiled_branches->parent_class = p_block->parent_class;
+ compiled_branches->can_continue = true;
p_block->sub_blocks.push_back(compiled_branches);
@@ -4088,6 +4121,14 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
sig.name = tokenizer->get_token_identifier();
sig.emissions = 0;
sig.line = tokenizer->get_token_line();
+
+ for (int i = 0; i < current_class->_signals.size(); i++) {
+ if (current_class->_signals[i].name == sig.name) {
+ _set_error("The signal \"" + sig.name + "\" already exists in this class (at line: " + itos(current_class->_signals[i].line) + ").");
+ return;
+ }
+ }
+
tokenizer->advance();
if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_OPEN) {
@@ -7913,6 +7954,47 @@ void GDScriptParser::_check_class_level_types(ClassNode *p_class) {
}
}
+ // Signals
+ DataType base = p_class->base_type;
+
+ while (base.kind == DataType::CLASS) {
+ ClassNode *base_class = base.class_type;
+ for (int i = 0; i < p_class->_signals.size(); i++) {
+ for (int j = 0; j < base_class->_signals.size(); j++) {
+ if (p_class->_signals[i].name == base_class->_signals[j].name) {
+ _set_error("The signal \"" + p_class->_signals[i].name + "\" already exists in a parent class.", p_class->_signals[i].line);
+ return;
+ }
+ }
+ }
+ base = base_class->base_type;
+ }
+
+ StringName native;
+ if (base.kind == DataType::GDSCRIPT || base.kind == DataType::SCRIPT) {
+ Ref<Script> scr = base.script_type;
+ if (scr.is_valid() && scr->is_valid()) {
+ native = scr->get_instance_base_type();
+ for (int i = 0; i < p_class->_signals.size(); i++) {
+ if (scr->has_script_signal(p_class->_signals[i].name)) {
+ _set_error("The signal \"" + p_class->_signals[i].name + "\" already exists in a parent class.", p_class->_signals[i].line);
+ return;
+ }
+ }
+ }
+ } else if (base.kind == DataType::NATIVE) {
+ native = base.native_type;
+ }
+
+ if (native != StringName()) {
+ for (int i = 0; i < p_class->_signals.size(); i++) {
+ if (ClassDB::has_signal(native, p_class->_signals[i].name)) {
+ _set_error("The signal \"" + p_class->_signals[i].name + "\" already exists in a parent class.", p_class->_signals[i].line);
+ return;
+ }
+ }
+ }
+
// Inner classes
for (int i = 0; i < p_class->subclasses.size(); i++) {
current_class = p_class->subclasses[i];
diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h
index cfcca9584e..7dedb6d6f9 100644
--- a/modules/gdscript/gdscript_parser.h
+++ b/modules/gdscript/gdscript_parser.h
@@ -231,6 +231,8 @@ public:
List<Node *> statements;
Map<StringName, LocalVarNode *> variables;
bool has_return = false;
+ bool can_break = false;
+ bool can_continue = false;
Node *if_condition = nullptr; //tiny hack to improve code completion on if () blocks
diff --git a/modules/gdscript/language_server/lsp.hpp b/modules/gdscript/language_server/lsp.hpp
index 44a0076107..cf27a1578c 100644
--- a/modules/gdscript/language_server/lsp.hpp
+++ b/modules/gdscript/language_server/lsp.hpp
@@ -486,7 +486,7 @@ struct TextDocumentSyncOptions {
* If present save notifications are sent to the server. If omitted the notification should not be
* sent.
*/
- SaveOptions save;
+ bool save = false;
Dictionary to_json() {
Dictionary dict;
@@ -494,7 +494,7 @@ struct TextDocumentSyncOptions {
dict["willSave"] = willSave;
dict["openClose"] = openClose;
dict["change"] = change;
- dict["save"] = save.to_json();
+ dict["save"] = save;
return dict;
}
};
@@ -1656,7 +1656,7 @@ struct ServerCapabilities {
_FORCE_INLINE_ Dictionary to_json() {
Dictionary dict;
- dict["textDocumentSync"] = (int)textDocumentSync.change;
+ dict["textDocumentSync"] = textDocumentSync.to_json();
dict["completionProvider"] = completionProvider.to_json();
signatureHelpProvider.triggerCharacters.push_back(",");
signatureHelpProvider.triggerCharacters.push_back("(");
diff --git a/modules/jsonrpc/jsonrpc.cpp b/modules/jsonrpc/jsonrpc.cpp
index 6ab5f2d9b3..7bb70b098f 100644
--- a/modules/jsonrpc/jsonrpc.cpp
+++ b/modules/jsonrpc/jsonrpc.cpp
@@ -120,7 +120,7 @@ Variant JSONRPC::process_action(const Variant &p_action, bool p_process_arr_elem
}
if (object == nullptr || !object->has_method(method)) {
- ret = make_response_error(JSONRPC::METHOD_NOT_FOUND, "Method not found", id);
+ ret = make_response_error(JSONRPC::METHOD_NOT_FOUND, "Method not found: " + method, id);
} else {
Variant call_ret = object->callv(method, args);
if (id.get_type() != Variant::NIL) {
diff --git a/modules/lightmapper_rd/lm_blendseams.glsl b/modules/lightmapper_rd/lm_blendseams.glsl
index 8a9ea91311..e47e5fcc51 100644
--- a/modules/lightmapper_rd/lm_blendseams.glsl
+++ b/modules/lightmapper_rd/lm_blendseams.glsl
@@ -1,10 +1,9 @@
-/* clang-format off */
-[versions]
+#[versions]
-lines = "#define MODE_LINES"
-triangles = "#define MODE_TRIANGLES"
+lines = "#define MODE_LINES";
+triangles = "#define MODE_TRIANGLES";
-[vertex]
+#[vertex]
#version 450
@@ -12,22 +11,20 @@ VERSION_DEFINES
#include "lm_common_inc.glsl"
- /* clang-format on */
-
- layout(push_constant, binding = 0, std430) uniform Params {
- uint base_index;
- uint slice;
- vec2 uv_offset;
- bool debug;
- float blend;
- uint pad[2];
- } params;
+layout(push_constant, binding = 0, std430) uniform Params {
+ uint base_index;
+ uint slice;
+ vec2 uv_offset;
+ bool debug;
+ float blend;
+ uint pad[2];
+}
+params;
layout(location = 0) out vec3 uv_interp;
void main() {
#ifdef MODE_TRIANGLES
-
uint triangle_idx = params.base_index + gl_VertexIndex / 3;
uint triangle_subidx = gl_VertexIndex % 3;
@@ -42,7 +39,6 @@ void main() {
uv_interp = vec3(uv, float(params.slice));
gl_Position = vec4((uv + params.uv_offset) * 2.0 - 1.0, 0.0001, 1.0);
-
#endif
#ifdef MODE_LINES
@@ -71,12 +67,10 @@ void main() {
uv_interp = vec3(src_uv, float(params.slice));
gl_Position = vec4(dst_uv * 2.0 - 1.0, 0.0001, 1.0);
- ;
#endif
}
-/* clang-format off */
-[fragment]
+#[fragment]
#version 450
@@ -84,16 +78,15 @@ VERSION_DEFINES
#include "lm_common_inc.glsl"
- /* clang-format on */
-
- layout(push_constant, binding = 0, std430) uniform Params {
- uint base_index;
- uint slice;
- vec2 uv_offset;
- bool debug;
- float blend;
- uint pad[2];
- } params;
+layout(push_constant, binding = 0, std430) uniform Params {
+ uint base_index;
+ uint slice;
+ vec2 uv_offset;
+ bool debug;
+ float blend;
+ uint pad[2];
+}
+params;
layout(location = 0) in vec3 uv_interp;
diff --git a/modules/lightmapper_rd/lm_common_inc.glsl b/modules/lightmapper_rd/lm_common_inc.glsl
index 15946d5327..0ff455936e 100644
--- a/modules/lightmapper_rd/lm_common_inc.glsl
+++ b/modules/lightmapper_rd/lm_common_inc.glsl
@@ -11,7 +11,6 @@ struct Vertex {
layout(set = 0, binding = 1, std430) restrict readonly buffer Vertices {
Vertex data[];
}
-
vertices;
struct Triangle {
@@ -22,7 +21,6 @@ struct Triangle {
layout(set = 0, binding = 2, std430) restrict readonly buffer Triangles {
Triangle data[];
}
-
triangles;
struct Box {
@@ -35,13 +33,11 @@ struct Box {
layout(set = 0, binding = 3, std430) restrict readonly buffer Boxes {
Box data[];
}
-
boxes;
layout(set = 0, binding = 4, std430) restrict readonly buffer GridIndices {
uint data[];
}
-
grid_indices;
#define LIGHT_TYPE_DIRECTIONAL 0
@@ -70,7 +66,6 @@ struct Light {
layout(set = 0, binding = 5, std430) restrict readonly buffer Lights {
Light data[];
}
-
lights;
struct Seam {
@@ -81,13 +76,11 @@ struct Seam {
layout(set = 0, binding = 6, std430) restrict readonly buffer Seams {
Seam data[];
}
-
seams;
layout(set = 0, binding = 7, std430) restrict readonly buffer Probes {
vec4 data[];
}
-
probe_positions;
layout(set = 0, binding = 8) uniform utexture3D grid;
diff --git a/modules/lightmapper_rd/lm_compute.glsl b/modules/lightmapper_rd/lm_compute.glsl
index a442016969..56976bd623 100644
--- a/modules/lightmapper_rd/lm_compute.glsl
+++ b/modules/lightmapper_rd/lm_compute.glsl
@@ -1,13 +1,12 @@
-/* clang-format off */
-[versions]
+#[versions]
-primary = "#define MODE_DIRECT_LIGHT"
-secondary = "#define MODE_BOUNCE_LIGHT"
-dilate = "#define MODE_DILATE"
-unocclude = "#define MODE_UNOCCLUDE"
-light_probes = "#define MODE_LIGHT_PROBES"
+primary = "#define MODE_DIRECT_LIGHT";
+secondary = "#define MODE_BOUNCE_LIGHT";
+dilate = "#define MODE_DILATE";
+unocclude = "#define MODE_UNOCCLUDE";
+light_probes = "#define MODE_LIGHT_PROBES";
-[compute]
+#[compute]
#version 450
@@ -29,14 +28,11 @@ layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
#include "lm_common_inc.glsl"
-/* clang-format on */
-
#ifdef MODE_LIGHT_PROBES
layout(set = 1, binding = 0, std430) restrict buffer LightProbeData {
vec4 data[];
}
-
light_probes;
layout(set = 1, binding = 1) uniform texture2DArray source_light;
@@ -94,7 +90,6 @@ layout(push_constant, binding = 0, std430) uniform Params {
mat3x4 env_transform;
}
-
params;
//check it, but also return distance and barycentric coords (for uv lookup)
@@ -123,7 +118,6 @@ bool trace_ray(vec3 p_from, vec3 p_to
out float r_distance, out vec3 r_normal
#endif
) {
-
/* world coords */
vec3 rel = p_to - p_from;
@@ -149,7 +143,6 @@ bool trace_ray(vec3 p_from, vec3 p_to
while (all(greaterThanEqual(icell, ivec3(0))) && all(lessThan(icell, ivec3(params.grid_size))) && iters < 1000) {
uvec2 cell_data = texelFetch(usampler3D(grid, linear_sampler), icell, 0).xy;
if (cell_data.x > 0) { //triangles here
-
bool hit = false;
#if defined(MODE_UNOCCLUDE)
bool hit_backface = false;
@@ -211,7 +204,6 @@ bool trace_ray(vec3 p_from, vec3 p_to
r_triangle = tidx;
r_barycentric = barycentric;
}
-
#endif
}
}
diff --git a/modules/lightmapper_rd/lm_raster.glsl b/modules/lightmapper_rd/lm_raster.glsl
index 36b706bcd5..6c2904192b 100644
--- a/modules/lightmapper_rd/lm_raster.glsl
+++ b/modules/lightmapper_rd/lm_raster.glsl
@@ -1,5 +1,4 @@
-/* clang-format off */
-[vertex]
+#[vertex]
#version 450
@@ -7,9 +6,7 @@ VERSION_DEFINES
#include "lm_common_inc.glsl"
- /* clang-format on */
-
- layout(location = 0) out vec3 vertex_interp;
+layout(location = 0) out vec3 vertex_interp;
layout(location = 1) out vec3 normal_interp;
layout(location = 2) out vec2 uv_interp;
layout(location = 3) out vec3 barycentric;
@@ -26,11 +23,8 @@ layout(push_constant, binding = 0, std430) uniform Params {
ivec3 grid_size;
uint pad2;
}
-
params;
-/* clang-format on */
-
void main() {
uint triangle_idx = params.base_triangle + gl_VertexIndex / 3;
uint triangle_subidx = gl_VertexIndex % 3;
@@ -56,12 +50,9 @@ void main() {
face_normal = -normalize(cross((vertices.data[vertex_indices.x].position - vertices.data[vertex_indices.y].position), (vertices.data[vertex_indices.x].position - vertices.data[vertex_indices.z].position)));
gl_Position = vec4((uv_interp + params.uv_offset) * 2.0 - 1.0, 0.0001, 1.0);
- ;
}
-/* clang-format off */
-
-[fragment]
+#[fragment]
#version 450
@@ -69,7 +60,6 @@ VERSION_DEFINES
#include "lm_common_inc.glsl"
-
layout(push_constant, binding = 0, std430) uniform Params {
vec2 atlas_size;
vec2 uv_offset;
@@ -79,9 +69,8 @@ layout(push_constant, binding = 0, std430) uniform Params {
float bias;
ivec3 grid_size;
uint pad2;
-} params;
-
-/* clang-format on */
+}
+params;
layout(location = 0) in vec3 vertex_interp;
layout(location = 1) in vec3 normal_interp;
@@ -100,7 +89,6 @@ void main() {
{
// smooth out vertex position by interpolating its projection in the 3 normal planes (normal plane is created by vertex pos and normal)
// because we don't want to interpolate inwards, normals found pointing inwards are pushed out.
-
vec3 pos_a = vertices.data[vertex_indices.x].position;
vec3 pos_b = vertices.data[vertex_indices.y].position;
vec3 pos_c = vertices.data[vertex_indices.z].position;
diff --git a/modules/mobile_vr/mobile_vr_interface.cpp b/modules/mobile_vr/mobile_vr_interface.cpp
index eebb3af709..a2fb443ef0 100644
--- a/modules/mobile_vr/mobile_vr_interface.cpp
+++ b/modules/mobile_vr/mobile_vr_interface.cpp
@@ -448,12 +448,6 @@ void MobileVRInterface::process() {
};
};
-void MobileVRInterface::notification(int p_what){
- _THREAD_SAFE_METHOD_
-
- // nothing to do here, I guess we could pauze our sensors...
-}
-
MobileVRInterface::MobileVRInterface() {
initialized = false;
diff --git a/modules/mobile_vr/mobile_vr_interface.h b/modules/mobile_vr/mobile_vr_interface.h
index 3a9ed1314a..e986a4a3de 100644
--- a/modules/mobile_vr/mobile_vr_interface.h
+++ b/modules/mobile_vr/mobile_vr_interface.h
@@ -142,7 +142,7 @@ public:
virtual void commit_for_eye(XRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect);
virtual void process();
- virtual void notification(int p_what);
+ virtual void notification(int p_what) {}
MobileVRInterface();
~MobileVRInterface();
diff --git a/modules/mono/SCsub b/modules/mono/SCsub
index c723b210cb..e8f3174a0a 100644
--- a/modules/mono/SCsub
+++ b/modules/mono/SCsub
@@ -29,7 +29,7 @@ if env_mono["tools"] or env_mono["target"] != "release":
mono_configure.configure(env, env_mono)
-if env_mono["tools"] and env_mono["mono_glue"]:
+if env_mono["tools"] and env_mono["mono_glue"] and env_mono["build_cil"]:
# Build Godot API solution
import build_scripts.api_solution_build as api_solution_build
diff --git a/modules/mono/config.py b/modules/mono/config.py
index d41f3755b5..7980a86cb3 100644
--- a/modules/mono/config.py
+++ b/modules/mono/config.py
@@ -30,6 +30,7 @@ def configure(env):
)
envvars.Add(BoolVariable("mono_static", "Statically link mono", default_mono_static))
envvars.Add(BoolVariable("mono_glue", "Build with the mono glue sources", True))
+ envvars.Add(BoolVariable("build_cil", "Build C# solutions", True))
envvars.Add(
BoolVariable(
"copy_mono_root", "Make a copy of the mono installation directory to bundle with the editor", False
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index a5aae5175b..958d72adb1 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -2419,15 +2419,22 @@ bool CSharpScript::_update_exports() {
StringName member_name = field->get_name();
member_info[member_name] = prop_info;
+
+ if (exported) {
#ifdef TOOLS_ENABLED
- if (is_editor && exported) {
- exported_members_cache.push_front(prop_info);
+ if (is_editor) {
+ exported_members_cache.push_front(prop_info);
- if (tmp_object) {
- exported_members_defval_cache[member_name] = GDMonoMarshal::mono_object_to_variant(field->get_value(tmp_object));
+ if (tmp_object) {
+ exported_members_defval_cache[member_name] = GDMonoMarshal::mono_object_to_variant(field->get_value(tmp_object));
+ }
}
- }
#endif
+
+#if defined(TOOLS_ENABLED) || defined(DEBUG_ENABLED)
+ exported_members_names.insert(member_name);
+#endif
+ }
}
}
@@ -2440,21 +2447,28 @@ bool CSharpScript::_update_exports() {
StringName member_name = property->get_name();
member_info[member_name] = prop_info;
+
+ if (exported) {
#ifdef TOOLS_ENABLED
- if (is_editor && exported) {
- exported_members_cache.push_front(prop_info);
- if (tmp_object) {
- MonoException *exc = nullptr;
- MonoObject *ret = property->get_value(tmp_object, &exc);
- if (exc) {
- exported_members_defval_cache[member_name] = Variant();
- GDMonoUtils::debug_print_unhandled_exception(exc);
- } else {
- exported_members_defval_cache[member_name] = GDMonoMarshal::mono_object_to_variant(ret);
+ if (is_editor) {
+ exported_members_cache.push_front(prop_info);
+ if (tmp_object) {
+ MonoException *exc = nullptr;
+ MonoObject *ret = property->get_value(tmp_object, &exc);
+ if (exc) {
+ exported_members_defval_cache[member_name] = Variant();
+ GDMonoUtils::debug_print_unhandled_exception(exc);
+ } else {
+ exported_members_defval_cache[member_name] = GDMonoMarshal::mono_object_to_variant(ret);
+ }
}
}
- }
#endif
+
+#if defined(TOOLS_ENABLED) || defined(DEBUG_ENABLED)
+ exported_members_names.insert(member_name);
+#endif
+ }
}
}
@@ -3240,9 +3254,7 @@ Error CSharpScript::reload(bool p_keep_state) {
ERR_FAIL_NULL_V(namespace_, ERR_BUG);
ERR_FAIL_NULL_V(class_name, ERR_BUG);
GDMonoClass *klass = project_assembly->get_class(namespace_->operator String(), class_name->operator String());
- if (klass) {
- bool obj_type = CACHED_CLASS(GodotObject)->is_assignable_from(klass);
- ERR_FAIL_COND_V(!obj_type, ERR_BUG);
+ if (klass && CACHED_CLASS(GodotObject)->is_assignable_from(klass)) {
script_class = klass;
}
} else {
@@ -3593,6 +3605,16 @@ CSharpScript::~CSharpScript() {
#endif
}
+void CSharpScript::get_members(Set<StringName> *p_members) {
+#if defined(TOOLS_ENABLED) || defined(DEBUG_ENABLED)
+ if (p_members) {
+ for (Set<StringName>::Element *E = exported_members_names.front(); E; E = E->next()) {
+ p_members->insert(E->get());
+ }
+ }
+#endif
+}
+
/*************** RESOURCE ***************/
RES ResourceFormatLoaderCSharpScript::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) {
diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h
index 52b0783a6e..0bf08ceafd 100644
--- a/modules/mono/csharp_script.h
+++ b/modules/mono/csharp_script.h
@@ -138,6 +138,10 @@ private:
virtual void _placeholder_erased(PlaceHolderScriptInstance *p_placeholder);
#endif
+#if defined(TOOLS_ENABLED) || defined(DEBUG_ENABLED)
+ Set<StringName> exported_members_names;
+#endif
+
Map<StringName, PropertyInfo> member_info;
void _clear();
@@ -191,6 +195,8 @@ public:
virtual void get_script_property_list(List<PropertyInfo> *p_list) const;
virtual void update_exports();
+ void get_members(Set<StringName> *p_members) override;
+
virtual bool is_tool() const { return tool; }
virtual bool is_valid() const { return valid; }
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index 0218773105..730ffcb945 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -123,8 +123,9 @@ static String snake_to_pascal_case(const String &p_identifier, bool p_input_is_u
if (part.length()) {
part[0] = _find_upper(part[0]);
if (p_input_is_upper) {
- for (int j = 1; j < part.length(); j++)
+ for (int j = 1; j < part.length(); j++) {
part[j] = _find_lower(part[j]);
+ }
}
ret += part;
} else {
@@ -157,8 +158,9 @@ static String snake_to_camel_case(const String &p_identifier, bool p_input_is_up
part[0] = _find_upper(part[0]);
}
if (p_input_is_upper) {
- for (int j = i != 0 ? 1 : 0; j < part.length(); j++)
+ for (int j = i != 0 ? 1 : 0; j < part.length(); j++) {
part[j] = _find_lower(part[j]);
+ }
}
ret += part;
} else {
@@ -182,8 +184,9 @@ static String snake_to_camel_case(const String &p_identifier, bool p_input_is_up
String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterface *p_itype) {
// Based on the version in EditorHelp
- if (p_bbcode.empty())
+ if (p_bbcode.empty()) {
return String();
+ }
DocData *doc = EditorHelp::get_doc_data();
@@ -200,8 +203,9 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf
while (pos < bbcode.length()) {
int brk_pos = bbcode.find("[", pos);
- if (brk_pos < 0)
+ if (brk_pos < 0) {
brk_pos = bbcode.length();
+ }
if (brk_pos > pos) {
String text = bbcode.substr(pos, brk_pos - pos);
@@ -210,19 +214,22 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf
} else {
Vector<String> lines = text.split("\n");
for (int i = 0; i < lines.size(); i++) {
- if (i != 0)
+ if (i != 0) {
xml_output.append("<para>");
+ }
xml_output.append(lines[i].xml_escape());
- if (i != lines.size() - 1)
+ if (i != lines.size() - 1) {
xml_output.append("</para>\n");
+ }
}
}
}
- if (brk_pos == bbcode.length())
+ if (brk_pos == bbcode.length()) {
break; // nothing else to add
+ }
int brk_end = bbcode.find("]", brk_pos + 1);
@@ -233,13 +240,15 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf
} else {
Vector<String> lines = text.split("\n");
for (int i = 0; i < lines.size(); i++) {
- if (i != 0)
+ if (i != 0) {
xml_output.append("<para>");
+ }
xml_output.append(lines[i].xml_escape());
- if (i != lines.size() - 1)
+ if (i != lines.size() - 1) {
xml_output.append("</para>\n");
+ }
}
}
@@ -412,8 +421,9 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf
for (const List<EnumInterface>::Element *E = global_enums.front(); E; E = E->next()) {
target_ienum = &E->get();
target_iconst = find_constant_by_name(target_name, target_ienum->constants);
- if (target_iconst)
+ if (target_iconst) {
break;
+ }
}
if (target_iconst) {
@@ -450,8 +460,9 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf
for (const List<EnumInterface>::Element *E = target_itype->enums.front(); E; E = E->next()) {
target_ienum = &E->get();
target_iconst = find_constant_by_name(target_name, target_ienum->constants);
- if (target_iconst)
+ if (target_iconst) {
break;
+ }
}
if (target_iconst) {
@@ -583,8 +594,9 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf
tag_stack.push_front(tag);
} else if (tag == "url") {
int end = bbcode.find("[", brk_end);
- if (end == -1)
+ if (end == -1) {
end = bbcode.length();
+ }
String url = bbcode.substr(brk_end + 1, end - brk_end - 1);
xml_output.append("<a href=\"");
xml_output.append(url);
@@ -603,8 +615,9 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf
tag_stack.push_front("url");
} else if (tag == "img") {
int end = bbcode.find("[", brk_end);
- if (end == -1)
+ if (end == -1) {
end = bbcode.length();
+ }
String image = bbcode.substr(brk_end + 1, end - brk_end - 1);
// Not supported. Just append the bbcode.
@@ -640,8 +653,9 @@ int BindingsGenerator::_determine_enum_prefix(const EnumInterface &p_ienum) {
Vector<String> front_parts = front_iconstant.name.split("_", /* p_allow_empty: */ true);
int candidate_len = front_parts.size() - 1;
- if (candidate_len == 0)
+ if (candidate_len == 0) {
return 0;
+ }
for (const List<ConstantInterface>::Element *E = p_ienum.constants.front()->next(); E; E = E->next()) {
const ConstantInterface &iconstant = E->get();
@@ -653,14 +667,16 @@ int BindingsGenerator::_determine_enum_prefix(const EnumInterface &p_ienum) {
if (front_parts[i] != parts[i]) {
// HARDCODED: Some Flag enums have the prefix 'FLAG_' for everything except 'FLAGS_DEFAULT' (same for 'METHOD_FLAG_' and'METHOD_FLAGS_DEFAULT').
bool hardcoded_exc = (i == candidate_len - 1 && ((front_parts[i] == "FLAGS" && parts[i] == "FLAG") || (front_parts[i] == "FLAG" && parts[i] == "FLAGS")));
- if (!hardcoded_exc)
+ if (!hardcoded_exc) {
break;
+ }
}
}
candidate_len = i;
- if (candidate_len == 0)
+ if (candidate_len == 0) {
return 0;
+ }
}
return candidate_len;
@@ -677,22 +693,25 @@ void BindingsGenerator::_apply_prefix_to_enum_constants(BindingsGenerator::EnumI
Vector<String> parts = constant_name.split("_", /* p_allow_empty: */ true);
- if (parts.size() <= curr_prefix_length)
+ if (parts.size() <= curr_prefix_length) {
continue;
+ }
if (parts[curr_prefix_length][0] >= '0' && parts[curr_prefix_length][0] <= '9') {
// The name of enum constants may begin with a numeric digit when strip from the enum prefix,
// so we make the prefix for this constant one word shorter in those cases.
for (curr_prefix_length = curr_prefix_length - 1; curr_prefix_length > 0; curr_prefix_length--) {
- if (parts[curr_prefix_length][0] < '0' || parts[curr_prefix_length][0] > '9')
+ if (parts[curr_prefix_length][0] < '0' || parts[curr_prefix_length][0] > '9') {
break;
+ }
}
}
constant_name = "";
for (int i = curr_prefix_length; i < parts.size(); i++) {
- if (i > curr_prefix_length)
+ if (i > curr_prefix_length) {
constant_name += "_";
+ }
constant_name += parts[i];
}
@@ -705,8 +724,9 @@ void BindingsGenerator::_generate_method_icalls(const TypeInterface &p_itype) {
for (const List<MethodInterface>::Element *E = p_itype.methods.front(); E; E = E->next()) {
const MethodInterface &imethod = E->get();
- if (imethod.is_virtual)
+ if (imethod.is_virtual) {
continue;
+ }
const TypeInterface *return_type = _get_type_or_placeholder(imethod.return_type);
@@ -755,8 +775,9 @@ void BindingsGenerator::_generate_method_icalls(const TypeInterface &p_itype) {
List<InternalCall>::Element *match = method_icalls.find(im_icall);
if (match) {
- if (p_itype.api_type != ClassDB::API_EDITOR)
+ if (p_itype.api_type != ClassDB::API_EDITOR) {
match->get().editor_only = false;
+ }
method_icalls_map.insert(&E->get(), &match->get());
} else {
List<InternalCall>::Element *added = method_icalls.push_back(im_icall);
@@ -801,8 +822,9 @@ void BindingsGenerator::_generate_global_constants(StringBuilder &p_output) {
p_output.append(";");
}
- if (!global_constants.empty())
+ if (!global_constants.empty()) {
p_output.append("\n");
+ }
p_output.append(INDENT1 CLOSE_BLOCK); // end of GD class
@@ -864,8 +886,9 @@ void BindingsGenerator::_generate_global_constants(StringBuilder &p_output) {
p_output.append(INDENT1 CLOSE_BLOCK);
- if (enum_in_static_class)
+ if (enum_in_static_class) {
p_output.append(INDENT1 CLOSE_BLOCK);
+ }
}
p_output.append(CLOSE_BLOCK); // end of namespace
@@ -899,8 +922,9 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir) {
_generate_global_constants(constants_source);
String output_file = path::join(base_gen_dir, BINDINGS_GLOBAL_SCOPE_CLASS "_constants.cs");
Error save_err = _save_file(output_file, constants_source);
- if (save_err != OK)
+ if (save_err != OK) {
return save_err;
+ }
compile_items.push_back(output_file);
}
@@ -908,17 +932,20 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir) {
for (OrderedHashMap<StringName, TypeInterface>::Element E = obj_types.front(); E; E = E.next()) {
const TypeInterface &itype = E.get();
- if (itype.api_type == ClassDB::API_EDITOR)
+ if (itype.api_type == ClassDB::API_EDITOR) {
continue;
+ }
String output_file = path::join(godot_objects_gen_dir, itype.proxy_name + ".cs");
Error err = _generate_cs_type(itype, output_file);
- if (err == ERR_SKIP)
+ if (err == ERR_SKIP) {
continue;
+ }
- if (err != OK)
+ if (err != OK) {
return err;
+ }
compile_items.push_back(output_file);
}
@@ -949,10 +976,12 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir) {
cs_icalls_content.append(m_icall.im_sig + ");\n"); \
}
- for (const List<InternalCall>::Element *E = core_custom_icalls.front(); E; E = E->next())
+ for (const List<InternalCall>::Element *E = core_custom_icalls.front(); E; E = E->next()) {
ADD_INTERNAL_CALL(E->get());
- for (const List<InternalCall>::Element *E = method_icalls.front(); E; E = E->next())
+ }
+ for (const List<InternalCall>::Element *E = method_icalls.front(); E; E = E->next()) {
ADD_INTERNAL_CALL(E->get());
+ }
#undef ADD_INTERNAL_CALL
@@ -961,8 +990,9 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir) {
String internal_methods_file = path::join(base_gen_dir, BINDINGS_CLASS_NATIVECALLS ".cs");
Error err = _save_file(internal_methods_file, cs_icalls_content);
- if (err != OK)
+ if (err != OK) {
return err;
+ }
compile_items.push_back(internal_methods_file);
@@ -981,8 +1011,9 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir) {
String includes_props_file = path::join(base_gen_dir, "GeneratedIncludes.props");
err = _save_file(includes_props_file, includes_props_content);
- if (err != OK)
+ if (err != OK) {
return err;
+ }
return OK;
}
@@ -1010,17 +1041,20 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_proj_dir) {
for (OrderedHashMap<StringName, TypeInterface>::Element E = obj_types.front(); E; E = E.next()) {
const TypeInterface &itype = E.get();
- if (itype.api_type != ClassDB::API_EDITOR)
+ if (itype.api_type != ClassDB::API_EDITOR) {
continue;
+ }
String output_file = path::join(godot_objects_gen_dir, itype.proxy_name + ".cs");
Error err = _generate_cs_type(itype, output_file);
- if (err == ERR_SKIP)
+ if (err == ERR_SKIP) {
continue;
+ }
- if (err != OK)
+ if (err != OK) {
return err;
+ }
compile_items.push_back(output_file);
}
@@ -1050,10 +1084,12 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_proj_dir) {
cs_icalls_content.append(m_icall.im_sig + ");\n"); \
}
- for (const List<InternalCall>::Element *E = editor_custom_icalls.front(); E; E = E->next())
+ for (const List<InternalCall>::Element *E = editor_custom_icalls.front(); E; E = E->next()) {
ADD_INTERNAL_CALL(E->get());
- for (const List<InternalCall>::Element *E = method_icalls.front(); E; E = E->next())
+ }
+ for (const List<InternalCall>::Element *E = method_icalls.front(); E; E = E->next()) {
ADD_INTERNAL_CALL(E->get());
+ }
#undef ADD_INTERNAL_CALL
@@ -1062,8 +1098,9 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_proj_dir) {
String internal_methods_file = path::join(base_gen_dir, BINDINGS_CLASS_NATIVECALLS_EDITOR ".cs");
Error err = _save_file(internal_methods_file, cs_icalls_content);
- if (err != OK)
+ if (err != OK) {
return err;
+ }
compile_items.push_back(internal_methods_file);
@@ -1082,8 +1119,9 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_proj_dir) {
String includes_props_file = path::join(base_gen_dir, "GeneratedIncludes.props");
err = _save_file(includes_props_file, includes_props_content);
- if (err != OK)
+ if (err != OK) {
return err;
+ }
return OK;
}
@@ -1210,92 +1248,89 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
output.append(INDENT1 "{");
- if (class_doc) {
- // Add constants
-
- for (const List<ConstantInterface>::Element *E = itype.constants.front(); E; E = E->next()) {
- const ConstantInterface &iconstant = E->get();
+ // Add constants
- if (iconstant.const_doc && iconstant.const_doc->description.size()) {
- String xml_summary = bbcode_to_xml(fix_doc_description(iconstant.const_doc->description), &itype);
- Vector<String> summary_lines = xml_summary.length() ? xml_summary.split("\n") : Vector<String>();
+ for (const List<ConstantInterface>::Element *E = itype.constants.front(); E; E = E->next()) {
+ const ConstantInterface &iconstant = E->get();
- if (summary_lines.size()) {
- output.append(MEMBER_BEGIN "/// <summary>\n");
+ if (iconstant.const_doc && iconstant.const_doc->description.size()) {
+ String xml_summary = bbcode_to_xml(fix_doc_description(iconstant.const_doc->description), &itype);
+ Vector<String> summary_lines = xml_summary.length() ? xml_summary.split("\n") : Vector<String>();
- for (int i = 0; i < summary_lines.size(); i++) {
- output.append(INDENT2 "/// ");
- output.append(summary_lines[i]);
- output.append("\n");
- }
+ if (summary_lines.size()) {
+ output.append(MEMBER_BEGIN "/// <summary>\n");
- output.append(INDENT2 "/// </summary>");
+ for (int i = 0; i < summary_lines.size(); i++) {
+ output.append(INDENT2 "/// ");
+ output.append(summary_lines[i]);
+ output.append("\n");
}
- }
- output.append(MEMBER_BEGIN "public const int ");
- output.append(iconstant.proxy_name);
- output.append(" = ");
- output.append(itos(iconstant.value));
- output.append(";");
+ output.append(INDENT2 "/// </summary>");
+ }
}
- if (itype.constants.size())
- output.append("\n");
+ output.append(MEMBER_BEGIN "public const int ");
+ output.append(iconstant.proxy_name);
+ output.append(" = ");
+ output.append(itos(iconstant.value));
+ output.append(";");
+ }
- // Add enums
+ if (itype.constants.size()) {
+ output.append("\n");
+ }
- for (const List<EnumInterface>::Element *E = itype.enums.front(); E; E = E->next()) {
- const EnumInterface &ienum = E->get();
+ // Add enums
- ERR_FAIL_COND_V(ienum.constants.empty(), ERR_BUG);
+ for (const List<EnumInterface>::Element *E = itype.enums.front(); E; E = E->next()) {
+ const EnumInterface &ienum = E->get();
- output.append(MEMBER_BEGIN "public enum ");
- output.append(ienum.cname.operator String());
- output.append(MEMBER_BEGIN OPEN_BLOCK);
+ ERR_FAIL_COND_V(ienum.constants.empty(), ERR_BUG);
- for (const List<ConstantInterface>::Element *F = ienum.constants.front(); F; F = F->next()) {
- const ConstantInterface &iconstant = F->get();
+ output.append(MEMBER_BEGIN "public enum ");
+ output.append(ienum.cname.operator String());
+ output.append(MEMBER_BEGIN OPEN_BLOCK);
- if (iconstant.const_doc && iconstant.const_doc->description.size()) {
- String xml_summary = bbcode_to_xml(fix_doc_description(iconstant.const_doc->description), &itype);
- Vector<String> summary_lines = xml_summary.length() ? xml_summary.split("\n") : Vector<String>();
+ for (const List<ConstantInterface>::Element *F = ienum.constants.front(); F; F = F->next()) {
+ const ConstantInterface &iconstant = F->get();
- if (summary_lines.size()) {
- output.append(INDENT3 "/// <summary>\n");
+ if (iconstant.const_doc && iconstant.const_doc->description.size()) {
+ String xml_summary = bbcode_to_xml(fix_doc_description(iconstant.const_doc->description), &itype);
+ Vector<String> summary_lines = xml_summary.length() ? xml_summary.split("\n") : Vector<String>();
- for (int i = 0; i < summary_lines.size(); i++) {
- output.append(INDENT3 "/// ");
- output.append(summary_lines[i]);
- output.append("\n");
- }
+ if (summary_lines.size()) {
+ output.append(INDENT3 "/// <summary>\n");
- output.append(INDENT3 "/// </summary>\n");
+ for (int i = 0; i < summary_lines.size(); i++) {
+ output.append(INDENT3 "/// ");
+ output.append(summary_lines[i]);
+ output.append("\n");
}
- }
- output.append(INDENT3);
- output.append(iconstant.proxy_name);
- output.append(" = ");
- output.append(itos(iconstant.value));
- output.append(F != ienum.constants.back() ? ",\n" : "\n");
+ output.append(INDENT3 "/// </summary>\n");
+ }
}
- output.append(INDENT2 CLOSE_BLOCK);
+ output.append(INDENT3);
+ output.append(iconstant.proxy_name);
+ output.append(" = ");
+ output.append(itos(iconstant.value));
+ output.append(F != ienum.constants.back() ? ",\n" : "\n");
}
- // Add properties
-
- for (const List<PropertyInterface>::Element *E = itype.properties.front(); E; E = E->next()) {
- const PropertyInterface &iprop = E->get();
- Error prop_err = _generate_cs_property(itype, iprop, output);
- ERR_FAIL_COND_V_MSG(prop_err != OK, prop_err,
- "Failed to generate property '" + iprop.cname.operator String() +
- "' for class '" + itype.name + "'.");
- }
+ output.append(INDENT2 CLOSE_BLOCK);
}
- // TODO: BINDINGS_NATIVE_NAME_FIELD should be StringName, once we support it in C#
+ // Add properties
+
+ for (const List<PropertyInterface>::Element *E = itype.properties.front(); E; E = E->next()) {
+ const PropertyInterface &iprop = E->get();
+ Error prop_err = _generate_cs_property(itype, iprop, output);
+ ERR_FAIL_COND_V_MSG(prop_err != OK, prop_err,
+ "Failed to generate property '" + iprop.cname.operator String() +
+ "' for class '" + itype.name + "'.");
+ }
if (itype.is_singleton) {
// Add the type name and the singleton pointer as static fields
@@ -1368,15 +1403,17 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
if (itype.is_singleton) {
InternalCall singleton_icall = InternalCall(itype.api_type, ICALL_PREFIX + itype.name + SINGLETON_ICALL_SUFFIX, "IntPtr");
- if (!find_icall_by_name(singleton_icall.name, custom_icalls))
+ if (!find_icall_by_name(singleton_icall.name, custom_icalls)) {
custom_icalls.push_back(singleton_icall);
+ }
}
if (is_derived_type && itype.is_instantiable) {
InternalCall ctor_icall = InternalCall(itype.api_type, ctor_method, "IntPtr", itype.proxy_name + " obj");
- if (!find_icall_by_name(ctor_icall.name, custom_icalls))
+ if (!find_icall_by_name(ctor_icall.name, custom_icalls)) {
custom_icalls.push_back(ctor_icall);
+ }
}
output.append(INDENT1 CLOSE_BLOCK /* class */
@@ -1442,6 +1479,9 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte
const TypeInterface *prop_itype = _get_type_or_null(proptype_name);
ERR_FAIL_NULL_V(prop_itype, ERR_BUG); // Property type not found
+ ERR_FAIL_COND_V_MSG(prop_itype->is_singleton, ERR_BUG,
+ "Property type is a singleton: '" + p_itype.name + "." + String(p_iprop.cname) + "'.");
+
if (p_iprop.prop_doc && p_iprop.prop_doc->description.size()) {
String xml_summary = bbcode_to_xml(fix_doc_description(p_iprop.prop_doc->description), &p_itype);
Vector<String> summary_lines = xml_summary.length() ? xml_summary.split("\n") : Vector<String>();
@@ -1461,8 +1501,9 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte
p_output.append(MEMBER_BEGIN "public ");
- if (p_itype.is_singleton)
+ if (p_itype.is_singleton) {
p_output.append("static ");
+ }
p_output.append(prop_itype->cs_type);
p_output.append(" ");
@@ -1534,6 +1575,9 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte
Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterface &p_itype, const BindingsGenerator::MethodInterface &p_imethod, int &p_method_bind_count, StringBuilder &p_output) {
const TypeInterface *return_type = _get_type_or_placeholder(p_imethod.return_type);
+ ERR_FAIL_COND_V_MSG(return_type->is_singleton, ERR_BUG,
+ "Method return type is a singleton: '" + p_itype.name + "." + p_imethod.name + "'.");
+
String method_bind_field = "__method_bind_" + itos(p_method_bind_count);
String arguments_sig;
@@ -1549,29 +1593,41 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
const ArgumentInterface &iarg = F->get();
const TypeInterface *arg_type = _get_type_or_placeholder(iarg.type);
+ ERR_FAIL_COND_V_MSG(arg_type->is_singleton, ERR_BUG,
+ "Argument type is a singleton: '" + iarg.name + "' of method '" + p_itype.name + "." + p_imethod.name + "'.");
+
+ if (iarg.default_argument.size()) {
+ CRASH_COND_MSG(!_arg_default_value_is_assignable_to_type(iarg.def_param_value, *arg_type),
+ "Invalid default value for parameter '" + iarg.name + "' of method '" + p_itype.name + "." + p_imethod.name + "'.");
+ }
+
// Add the current arguments to the signature
// If the argument has a default value which is not a constant, we will make it Nullable
{
- if (F != p_imethod.arguments.front())
+ if (F != p_imethod.arguments.front()) {
arguments_sig += ", ";
+ }
- if (iarg.def_param_mode == ArgumentInterface::NULLABLE_VAL)
+ if (iarg.def_param_mode == ArgumentInterface::NULLABLE_VAL) {
arguments_sig += "Nullable<";
+ }
arguments_sig += arg_type->cs_type;
- if (iarg.def_param_mode == ArgumentInterface::NULLABLE_VAL)
+ if (iarg.def_param_mode == ArgumentInterface::NULLABLE_VAL) {
arguments_sig += "> ";
- else
+ } else {
arguments_sig += " ";
+ }
arguments_sig += iarg.name;
if (iarg.default_argument.size()) {
- if (iarg.def_param_mode != ArgumentInterface::CONSTANT)
+ if (iarg.def_param_mode != ArgumentInterface::CONSTANT) {
arguments_sig += " = null";
- else
+ } else {
arguments_sig += " = " + sformat(iarg.default_argument, arg_type->cs_type);
+ }
}
}
@@ -1589,17 +1645,19 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
cs_in_statements += " = ";
cs_in_statements += iarg.name;
- if (iarg.def_param_mode == ArgumentInterface::NULLABLE_VAL)
+ if (iarg.def_param_mode == ArgumentInterface::NULLABLE_VAL) {
cs_in_statements += ".HasValue ? ";
- else
+ } else {
cs_in_statements += " != null ? ";
+ }
cs_in_statements += iarg.name;
- if (iarg.def_param_mode == ArgumentInterface::NULLABLE_VAL)
+ if (iarg.def_param_mode == ArgumentInterface::NULLABLE_VAL) {
cs_in_statements += ".Value : ";
- else
+ } else {
cs_in_statements += " : ";
+ }
String def_arg = sformat(iarg.default_argument, arg_type->cs_type);
@@ -1659,8 +1717,9 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
}
if (p_imethod.is_deprecated) {
- if (p_imethod.deprecation_message.empty())
+ if (p_imethod.deprecation_message.empty()) {
WARN_PRINT("An empty deprecation message is discouraged. Method: '" + p_imethod.proxy_name + "'.");
+ }
p_output.append(MEMBER_BEGIN "[Obsolete(\"");
p_output.append(p_imethod.deprecation_message);
@@ -1720,8 +1779,9 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
im_call += ".";
im_call += im_icall->name;
- if (p_imethod.arguments.size())
+ if (p_imethod.arguments.size()) {
p_output.append(cs_in_statements);
+ }
if (return_type->cname == name_cache.type_void) {
p_output.append(im_call + "(" + icall_params + ");\n");
@@ -1748,10 +1808,14 @@ Error BindingsGenerator::_generate_cs_signal(const BindingsGenerator::TypeInterf
const ArgumentInterface &iarg = F->get();
const TypeInterface *arg_type = _get_type_or_placeholder(iarg.type);
+ ERR_FAIL_COND_V_MSG(arg_type->is_singleton, ERR_BUG,
+ "Argument type is a singleton: '" + iarg.name + "' of signal" + p_itype.name + "." + p_isignal.name + "'.");
+
// Add the current arguments to the signature
- if (F != p_isignal.arguments.front())
+ if (F != p_isignal.arguments.front()) {
arguments_sig += ", ";
+ }
arguments_sig += arg_type->cs_type;
arguments_sig += " ";
@@ -1778,8 +1842,9 @@ Error BindingsGenerator::_generate_cs_signal(const BindingsGenerator::TypeInterf
}
if (p_isignal.is_deprecated) {
- if (p_isignal.deprecation_message.empty())
+ if (p_isignal.deprecation_message.empty()) {
WARN_PRINT("An empty deprecation message is discouraged. Signal: '" + p_isignal.proxy_name + "'.");
+ }
p_output.append(MEMBER_BEGIN "[Obsolete(\"");
p_output.append(p_isignal.deprecation_message);
@@ -1810,8 +1875,9 @@ Error BindingsGenerator::_generate_cs_signal(const BindingsGenerator::TypeInterf
// Generate event
p_output.append(MEMBER_BEGIN "[Signal]" MEMBER_BEGIN "public ");
- if (p_itype.is_singleton)
+ if (p_itype.is_singleton) {
p_output.append("static ");
+ }
p_output.append("event ");
p_output.append(delegate_name);
@@ -1819,18 +1885,20 @@ Error BindingsGenerator::_generate_cs_signal(const BindingsGenerator::TypeInterf
p_output.append(p_isignal.proxy_name);
p_output.append("\n" OPEN_BLOCK_L2);
- if (p_itype.is_singleton)
+ if (p_itype.is_singleton) {
p_output.append("add => Singleton.Connect(__signal_name_");
- else
+ } else {
p_output.append("add => Connect(__signal_name_");
+ }
p_output.append(p_isignal.name);
p_output.append(", new Callable(value));\n");
- if (p_itype.is_singleton)
+ if (p_itype.is_singleton) {
p_output.append(INDENT3 "remove => Singleton.Disconnect(__signal_name_");
- else
+ } else {
p_output.append(INDENT3 "remove => Disconnect(__signal_name_");
+ }
p_output.append(p_isignal.name);
p_output.append(", new Callable(value));\n");
@@ -1864,7 +1932,6 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
CRASH_COND(itype.cname != name_cache.type_Object);
CRASH_COND(!itype.is_instantiable);
CRASH_COND(itype.api_type != ClassDB::API_CORE);
- CRASH_COND(itype.is_reference);
CRASH_COND(itype.is_singleton);
}
@@ -1885,8 +1952,9 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
String singleton_icall_name = ICALL_PREFIX + itype.name + SINGLETON_ICALL_SUFFIX;
InternalCall singleton_icall = InternalCall(itype.api_type, singleton_icall_name, "IntPtr");
- if (!find_icall_by_name(singleton_icall.name, custom_icalls))
+ if (!find_icall_by_name(singleton_icall.name, custom_icalls)) {
custom_icalls.push_back(singleton_icall);
+ }
output.append("Object* ");
output.append(singleton_icall_name);
@@ -1898,8 +1966,9 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
if (is_derived_type && itype.is_instantiable) {
InternalCall ctor_icall = InternalCall(itype.api_type, ctor_method, "IntPtr", itype.proxy_name + " obj");
- if (!find_icall_by_name(ctor_icall.name, custom_icalls))
+ if (!find_icall_by_name(ctor_icall.name, custom_icalls)) {
custom_icalls.push_back(ctor_icall);
+ }
output.append("Object* ");
output.append(ctor_method);
@@ -1998,8 +2067,9 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
output.append("\n#endif // MONO_GLUE_ENABLED\n");
Error save_err = _save_file(path::join(p_output_dir, "mono_glue.gen.cpp"), output);
- if (save_err != OK)
+ if (save_err != OK) {
return save_err;
+ }
OS::get_singleton()->print("Mono glue generated successfully\n");
@@ -2022,8 +2092,9 @@ Error BindingsGenerator::_save_file(const String &p_path, const StringBuilder &p
}
Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInterface &p_itype, const BindingsGenerator::MethodInterface &p_imethod, StringBuilder &p_output) {
- if (p_imethod.is_virtual)
+ if (p_imethod.is_virtual) {
return OK; // Ignore
+ }
bool ret_void = p_imethod.return_type.cname == name_cache.type_void;
@@ -2051,10 +2122,12 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte
c_in_statements += sformat(", &%s_in);\n", c_param_name);
}
} else {
- if (i > 0)
+ if (i > 0) {
c_args_var_content += ", ";
- if (arg_type->c_in.size())
+ }
+ if (arg_type->c_in.size()) {
c_in_statements += sformat(arg_type->c_in, arg_type->c_type, c_param_name);
+ }
c_args_var_content += sformat(arg_type->c_arg_in, c_param_name);
}
@@ -2084,8 +2157,9 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte
if (!generated_icall_funcs.find(im_icall)) {
generated_icall_funcs.push_back(im_icall);
- if (im_icall->editor_only)
+ if (im_icall->editor_only) {
p_output.append("#ifdef TOOLS_ENABLED\n");
+ }
// Generate icall function
@@ -2203,8 +2277,9 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte
p_output.append(CLOSE_BLOCK "\n");
- if (im_icall->editor_only)
+ if (im_icall->editor_only) {
p_output.append("#endif // TOOLS_ENABLED\n");
+ }
}
return OK;
@@ -2213,19 +2288,22 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte
const BindingsGenerator::TypeInterface *BindingsGenerator::_get_type_or_null(const TypeReference &p_typeref) {
const Map<StringName, TypeInterface>::Element *builtin_type_match = builtin_types.find(p_typeref.cname);
- if (builtin_type_match)
+ if (builtin_type_match) {
return &builtin_type_match->get();
+ }
const OrderedHashMap<StringName, TypeInterface>::Element obj_type_match = obj_types.find(p_typeref.cname);
- if (obj_type_match)
+ if (obj_type_match) {
return &obj_type_match.get();
+ }
if (p_typeref.is_enum) {
const Map<StringName, TypeInterface>::Element *enum_match = enum_types.find(p_typeref.cname);
- if (enum_match)
+ if (enum_match) {
return &enum_match->get();
+ }
// Enum not found. Most likely because none of its constants were bound, so it's empty. That's fine. Use int instead.
const Map<StringName, TypeInterface>::Element *int_match = builtin_types.find(name_cache.type_int);
@@ -2239,15 +2317,17 @@ const BindingsGenerator::TypeInterface *BindingsGenerator::_get_type_or_null(con
const BindingsGenerator::TypeInterface *BindingsGenerator::_get_type_or_placeholder(const TypeReference &p_typeref) {
const TypeInterface *found = _get_type_or_null(p_typeref);
- if (found)
+ if (found) {
return found;
+ }
ERR_PRINT(String() + "Type not found. Creating placeholder: '" + p_typeref.cname.operator String() + "'.");
const Map<StringName, TypeInterface>::Element *match = placeholder_types.find(p_typeref.cname);
- if (match)
+ if (match) {
return &match->get();
+ }
TypeInterface placeholder;
TypeInterface::create_placeholder_type(placeholder, p_typeref.cname);
@@ -2305,6 +2385,84 @@ StringName BindingsGenerator::_get_float_type_name_from_meta(GodotTypeInfo::Meta
}
}
+bool BindingsGenerator::_arg_default_value_is_assignable_to_type(const Variant &p_val, const TypeInterface &p_arg_type) {
+ if (p_arg_type.name == name_cache.type_Variant) {
+ // Variant can take anything
+ return true;
+ }
+
+ switch (p_val.get_type()) {
+ case Variant::NIL:
+ return p_arg_type.is_object_type ||
+ name_cache.is_nullable_type(p_arg_type.name);
+ case Variant::BOOL:
+ return p_arg_type.name == name_cache.type_bool;
+ case Variant::INT:
+ return p_arg_type.name == name_cache.type_sbyte ||
+ p_arg_type.name == name_cache.type_short ||
+ p_arg_type.name == name_cache.type_int ||
+ p_arg_type.name == name_cache.type_byte ||
+ p_arg_type.name == name_cache.type_ushort ||
+ p_arg_type.name == name_cache.type_uint ||
+ p_arg_type.name == name_cache.type_long ||
+ p_arg_type.name == name_cache.type_ulong ||
+ p_arg_type.name == name_cache.type_float ||
+ p_arg_type.name == name_cache.type_double ||
+ p_arg_type.is_enum;
+ case Variant::FLOAT:
+ return p_arg_type.name == name_cache.type_float ||
+ p_arg_type.name == name_cache.type_double;
+ case Variant::STRING:
+ case Variant::STRING_NAME:
+ return p_arg_type.name == name_cache.type_String ||
+ p_arg_type.name == name_cache.type_StringName ||
+ p_arg_type.name == name_cache.type_NodePath;
+ case Variant::NODE_PATH:
+ return p_arg_type.name == name_cache.type_NodePath;
+ case Variant::TRANSFORM:
+ case Variant::TRANSFORM2D:
+ case Variant::BASIS:
+ case Variant::QUAT:
+ case Variant::PLANE:
+ case Variant::AABB:
+ case Variant::COLOR:
+ case Variant::VECTOR2:
+ case Variant::RECT2:
+ case Variant::VECTOR3:
+ case Variant::_RID:
+ case Variant::ARRAY:
+ case Variant::DICTIONARY:
+ case Variant::PACKED_BYTE_ARRAY:
+ case Variant::PACKED_INT32_ARRAY:
+ case Variant::PACKED_INT64_ARRAY:
+ case Variant::PACKED_FLOAT32_ARRAY:
+ case Variant::PACKED_FLOAT64_ARRAY:
+ case Variant::PACKED_STRING_ARRAY:
+ case Variant::PACKED_VECTOR2_ARRAY:
+ case Variant::PACKED_VECTOR3_ARRAY:
+ case Variant::PACKED_COLOR_ARRAY:
+ case Variant::CALLABLE:
+ case Variant::SIGNAL:
+ return p_arg_type.name == Variant::get_type_name(p_val.get_type());
+ case Variant::OBJECT:
+ return p_arg_type.is_object_type;
+ case Variant::VECTOR2I:
+ return p_arg_type.name == name_cache.type_Vector2 ||
+ p_arg_type.name == Variant::get_type_name(p_val.get_type());
+ case Variant::RECT2I:
+ return p_arg_type.name == name_cache.type_Rect2 ||
+ p_arg_type.name == Variant::get_type_name(p_val.get_type());
+ case Variant::VECTOR3I:
+ return p_arg_type.name == name_cache.type_Vector3 ||
+ p_arg_type.name == Variant::get_type_name(p_val.get_type());
+ default:
+ CRASH_NOW_MSG("Unexpected Variant type: " + itos(p_val.get_type()));
+ break;
+ }
+
+ return false;
+}
+
bool BindingsGenerator::_populate_object_type_interfaces() {
obj_types.clear();
@@ -2367,8 +2525,9 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
for (const List<PropertyInfo>::Element *E = property_list.front(); E; E = E->next()) {
const PropertyInfo &property = E->get();
- if (property.usage & PROPERTY_USAGE_GROUP || property.usage & PROPERTY_USAGE_SUBGROUP || property.usage & PROPERTY_USAGE_CATEGORY)
+ if (property.usage & PROPERTY_USAGE_GROUP || property.usage & PROPERTY_USAGE_SUBGROUP || property.usage & PROPERTY_USAGE_CATEGORY) {
continue;
+ }
if (property.name.find("/") >= 0) {
// Ignore properties with '/' (slash) in the name. These are only meant for use in the inspector.
@@ -2380,10 +2539,12 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
iprop.setter = ClassDB::get_property_setter(type_cname, iprop.cname);
iprop.getter = ClassDB::get_property_getter(type_cname, iprop.cname);
- if (iprop.setter != StringName())
+ if (iprop.setter != StringName()) {
accessor_methods[iprop.setter] = iprop.cname;
- if (iprop.getter != StringName())
+ }
+ if (iprop.getter != StringName()) {
accessor_methods[iprop.getter] = iprop.cname;
+ }
bool valid = false;
iprop.index = ClassDB::get_property_index(type_cname, iprop.cname, &valid);
@@ -2427,20 +2588,23 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
int argc = method_info.arguments.size();
- if (method_info.name.empty())
+ if (method_info.name.empty()) {
continue;
+ }
String cname = method_info.name;
- if (blacklisted_methods.find(itype.cname) && blacklisted_methods[itype.cname].find(cname))
+ if (blacklisted_methods.find(itype.cname) && blacklisted_methods[itype.cname].find(cname)) {
continue;
+ }
MethodInterface imethod;
imethod.name = method_info.name;
imethod.cname = cname;
- if (method_info.flags & METHOD_FLAG_VIRTUAL)
+ if (method_info.flags & METHOD_FLAG_VIRTUAL) {
imethod.is_virtual = true;
+ }
PropertyInfo return_info = method_info.return_val;
@@ -2462,9 +2626,8 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
// We assume the return type is void.
imethod.return_type.cname = name_cache.type_void;
- // Actually, more methods like this may be added in the future,
- // which could actually will return something different.
- // Let's put this to notify us if that ever happens.
+ // Actually, more methods like this may be added in the future, which could return
+ // something different. Let's put this check to notify us if that ever happens.
if (itype.cname != name_cache.type_Object || imethod.name != "free") {
WARN_PRINT("Notification: New unexpected virtual non-overridable method found."
" We only expected Object.free, but found '" +
@@ -2475,13 +2638,12 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
imethod.return_type.is_enum = true;
} else if (return_info.class_name != StringName()) {
imethod.return_type.cname = return_info.class_name;
- if (!imethod.is_virtual && ClassDB::is_parent_class(return_info.class_name, name_cache.type_Reference) && return_info.hint != PROPERTY_HINT_RESOURCE_TYPE) {
- /* clang-format off */
- ERR_PRINT("Return type is reference but hint is not '" _STR(PROPERTY_HINT_RESOURCE_TYPE) "'."
- " Are you returning a reference type by pointer? Method: '" + itype.name + "." + imethod.name + "'.");
- /* clang-format on */
- ERR_FAIL_V(false);
- }
+
+ bool bad_reference_hint = !imethod.is_virtual && return_info.hint != PROPERTY_HINT_RESOURCE_TYPE &&
+ ClassDB::is_parent_class(return_info.class_name, name_cache.type_Reference);
+ ERR_FAIL_COND_V_MSG(bad_reference_hint, false,
+ String() + "Return type is reference but hint is not '" _STR(PROPERTY_HINT_RESOURCE_TYPE) "'." +
+ " Are you returning a reference type by pointer? Method: '" + itype.name + "." + imethod.name + "'.");
} else if (return_info.hint == PROPERTY_HINT_RESOURCE_TYPE) {
imethod.return_type.cname = return_info.hint_string;
} else if (return_info.type == Variant::NIL && return_info.usage & PROPERTY_USAGE_NIL_IS_VARIANT) {
@@ -2572,6 +2734,10 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
}
}
+ ERR_FAIL_COND_V_MSG(itype.find_property_by_name(imethod.cname), false,
+ "Method name conflicts with property: '" + itype.name + "." + imethod.name + "'.");
+
+ // Classes starting with an underscore are ignored unless they're used as a property setter or getter
if (!imethod.is_virtual && imethod.name[0] == '_') {
for (const List<PropertyInterface>::Element *F = itype.properties.front(); F; F = F->next()) {
const PropertyInterface &iprop = F->get();
@@ -2751,7 +2917,8 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
}
bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, ArgumentInterface &r_iarg) {
- r_iarg.default_argument = p_val;
+ r_iarg.def_param_value = p_val;
+ r_iarg.default_argument = p_val.operator String();
switch (p_val.get_type()) {
case Variant::NIL:
@@ -2784,8 +2951,9 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar
}
break;
case Variant::TRANSFORM:
- if (p_val.operator Transform() == Transform())
+ if (p_val.operator Transform() == Transform()) {
r_iarg.default_argument.clear();
+ }
r_iarg.default_argument = "new %s(" + r_iarg.default_argument + ")";
r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL;
break;
@@ -2851,8 +3019,9 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar
break;
}
- if (r_iarg.def_param_mode == ArgumentInterface::CONSTANT && r_iarg.type.cname == name_cache.type_Variant && r_iarg.default_argument != "null")
+ if (r_iarg.def_param_mode == ArgumentInterface::CONSTANT && r_iarg.type.cname == name_cache.type_Variant && r_iarg.default_argument != "null") {
r_iarg.def_param_mode = ArgumentInterface::NULLABLE_REF;
+ }
return true;
}
@@ -3357,8 +3526,9 @@ void BindingsGenerator::_initialize() {
core_custom_icalls.clear();
editor_custom_icalls.clear();
- for (OrderedHashMap<StringName, TypeInterface>::Element E = obj_types.front(); E; E = E.next())
+ for (OrderedHashMap<StringName, TypeInterface>::Element E = obj_types.front(); E; E = E.next()) {
_generate_method_icalls(E.get());
+ }
initialized = true;
}
@@ -3426,21 +3596,25 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args)
}
if (glue_dir_path.length()) {
- if (bindings_generator.generate_glue(glue_dir_path) != OK)
+ if (bindings_generator.generate_glue(glue_dir_path) != OK) {
ERR_PRINT(generate_all_glue_option + ": Failed to generate the C++ glue.");
+ }
- if (bindings_generator.generate_cs_api(glue_dir_path.plus_file(API_SOLUTION_NAME)) != OK)
+ if (bindings_generator.generate_cs_api(glue_dir_path.plus_file(API_SOLUTION_NAME)) != OK) {
ERR_PRINT(generate_all_glue_option + ": Failed to generate the C# API.");
+ }
}
if (cs_dir_path.length()) {
- if (bindings_generator.generate_cs_api(cs_dir_path) != OK)
+ if (bindings_generator.generate_cs_api(cs_dir_path) != OK) {
ERR_PRINT(generate_cs_glue_option + ": Failed to generate the C# API.");
+ }
}
if (cpp_dir_path.length()) {
- if (bindings_generator.generate_glue(cpp_dir_path) != OK)
+ if (bindings_generator.generate_glue(cpp_dir_path) != OK) {
ERR_PRINT(generate_cpp_glue_option + ": Failed to generate the C++ glue.");
+ }
}
// Exit once done
diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h
index aad109e03c..90c1c9f3ee 100644
--- a/modules/mono/editor/bindings_generator.h
+++ b/modules/mono/editor/bindings_generator.h
@@ -102,6 +102,8 @@ class BindingsGenerator {
TypeReference type;
String name;
+
+ Variant def_param_value;
DefaultParamMode def_param_mode = CONSTANT;
/**
@@ -355,8 +357,9 @@ class BindingsGenerator {
const MethodInterface *find_method_by_name(const StringName &p_cname) const {
for (const List<MethodInterface>::Element *E = methods.front(); E; E = E->next()) {
- if (E->get().cname == p_cname)
+ if (E->get().cname == p_cname) {
return &E->get();
+ }
}
return nullptr;
@@ -364,8 +367,9 @@ class BindingsGenerator {
const PropertyInterface *find_property_by_name(const StringName &p_cname) const {
for (const List<PropertyInterface>::Element *E = properties.front(); E; E = E->next()) {
- if (E->get().cname == p_cname)
+ if (E->get().cname == p_cname) {
return &E->get();
+ }
}
return nullptr;
@@ -373,8 +377,9 @@ class BindingsGenerator {
const PropertyInterface *find_property_by_proxy_name(const String &p_proxy_name) const {
for (const List<PropertyInterface>::Element *E = properties.front(); E; E = E->next()) {
- if (E->get().proxy_name == p_proxy_name)
+ if (E->get().proxy_name == p_proxy_name) {
return &E->get();
+ }
}
return nullptr;
@@ -382,8 +387,9 @@ class BindingsGenerator {
const MethodInterface *find_method_by_proxy_name(const String &p_proxy_name) const {
for (const List<MethodInterface>::Element *E = methods.front(); E; E = E->next()) {
- if (E->get().proxy_name == p_proxy_name)
+ if (E->get().proxy_name == p_proxy_name) {
return &E->get();
+ }
}
return nullptr;
@@ -523,58 +529,70 @@ class BindingsGenerator {
void _initialize_blacklisted_methods();
struct NameCache {
- StringName type_void;
- StringName type_Array;
- StringName type_Dictionary;
- StringName type_Variant;
- StringName type_VarArg;
- StringName type_Object;
- StringName type_Reference;
- StringName type_RID;
- StringName type_String;
- StringName type_StringName;
- StringName type_NodePath;
- StringName type_at_GlobalScope;
- StringName enum_Error;
-
- StringName type_sbyte;
- StringName type_short;
- StringName type_int;
- StringName type_long;
- StringName type_byte;
- StringName type_ushort;
- StringName type_uint;
- StringName type_ulong;
- StringName type_float;
- StringName type_double;
-
- NameCache() {
- type_void = StaticCString::create("void");
- type_Array = StaticCString::create("Array");
- type_Dictionary = StaticCString::create("Dictionary");
- type_Variant = StaticCString::create("Variant");
- type_VarArg = StaticCString::create("VarArg");
- type_Object = StaticCString::create("Object");
- type_Reference = StaticCString::create("Reference");
- type_RID = StaticCString::create("RID");
- type_String = StaticCString::create("String");
- type_StringName = StaticCString::create("StringName");
- type_NodePath = StaticCString::create("NodePath");
- type_at_GlobalScope = StaticCString::create("@GlobalScope");
- enum_Error = StaticCString::create("Error");
-
- type_sbyte = StaticCString::create("sbyte");
- type_short = StaticCString::create("short");
- type_int = StaticCString::create("int");
- type_long = StaticCString::create("long");
- type_byte = StaticCString::create("byte");
- type_ushort = StaticCString::create("ushort");
- type_uint = StaticCString::create("uint");
- type_ulong = StaticCString::create("ulong");
- type_float = StaticCString::create("float");
- type_double = StaticCString::create("double");
+ StringName type_void = StaticCString::create("void");
+ StringName type_Variant = StaticCString::create("Variant");
+ StringName type_VarArg = StaticCString::create("VarArg");
+ StringName type_Object = StaticCString::create("Object");
+ StringName type_Reference = StaticCString::create("Reference");
+ StringName type_RID = StaticCString::create("RID");
+ StringName type_String = StaticCString::create("String");
+ StringName type_StringName = StaticCString::create("StringName");
+ StringName type_NodePath = StaticCString::create("NodePath");
+ StringName type_at_GlobalScope = StaticCString::create("@GlobalScope");
+ StringName enum_Error = StaticCString::create("Error");
+
+ StringName type_sbyte = StaticCString::create("sbyte");
+ StringName type_short = StaticCString::create("short");
+ StringName type_int = StaticCString::create("int");
+ StringName type_byte = StaticCString::create("byte");
+ StringName type_ushort = StaticCString::create("ushort");
+ StringName type_uint = StaticCString::create("uint");
+ StringName type_long = StaticCString::create("long");
+ StringName type_ulong = StaticCString::create("ulong");
+
+ StringName type_bool = StaticCString::create("bool");
+ StringName type_float = StaticCString::create("float");
+ StringName type_double = StaticCString::create("double");
+
+ StringName type_Vector2 = StaticCString::create("Vector2");
+ StringName type_Rect2 = StaticCString::create("Rect2");
+ StringName type_Vector3 = StaticCString::create("Vector3");
+
+ // Object not included as it must be checked for all derived classes
+ static constexpr int nullable_types_count = 17;
+ StringName nullable_types[nullable_types_count] = {
+ type_String,
+ type_StringName,
+ type_NodePath,
+
+ StaticCString::create(_STR(Array)),
+ StaticCString::create(_STR(Dictionary)),
+ StaticCString::create(_STR(Callable)),
+ StaticCString::create(_STR(Signal)),
+
+ StaticCString::create(_STR(PackedByteArray)),
+ StaticCString::create(_STR(PackedInt32Array)),
+ StaticCString::create(_STR(PackedInt64rray)),
+ StaticCString::create(_STR(PackedFloat32Array)),
+ StaticCString::create(_STR(PackedFloat64Array)),
+ StaticCString::create(_STR(PackedStringArray)),
+ StaticCString::create(_STR(PackedVector2Array)),
+ StaticCString::create(_STR(PackedVector3Array)),
+ StaticCString::create(_STR(PackedColorArray)),
+ };
+
+ bool is_nullable_type(const StringName &p_type) const {
+ for (int i = 0; i < nullable_types_count; i++) {
+ if (p_type == nullable_types[i]) {
+ return true;
+ }
+ }
+
+ return false;
}
+ NameCache() {}
+
private:
NameCache(const NameCache &);
NameCache &operator=(const NameCache &);
@@ -585,8 +603,9 @@ class BindingsGenerator {
const List<InternalCall>::Element *find_icall_by_name(const String &p_name, const List<InternalCall> &p_list) {
const List<InternalCall>::Element *it = p_list.front();
while (it) {
- if (it->get().name == p_name)
+ if (it->get().name == p_name) {
return it;
+ }
it = it->next();
}
return nullptr;
@@ -594,20 +613,22 @@ class BindingsGenerator {
const ConstantInterface *find_constant_by_name(const String &p_name, const List<ConstantInterface> &p_constants) const {
for (const List<ConstantInterface>::Element *E = p_constants.front(); E; E = E->next()) {
- if (E->get().name == p_name)
+ if (E->get().name == p_name) {
return &E->get();
+ }
}
return nullptr;
}
inline String get_unique_sig(const TypeInterface &p_type) {
- if (p_type.is_reference)
+ if (p_type.is_reference) {
return "Ref";
- else if (p_type.is_object_type)
+ } else if (p_type.is_object_type) {
return "Obj";
- else if (p_type.is_enum)
+ } else if (p_type.is_enum) {
return "int";
+ }
return p_type.name;
}
@@ -626,6 +647,7 @@ class BindingsGenerator {
StringName _get_float_type_name_from_meta(GodotTypeInfo::Metadata p_meta);
bool _arg_default_value_from_variant(const Variant &p_val, ArgumentInterface &r_iarg);
+ bool _arg_default_value_is_assignable_to_type(const Variant &p_val, const TypeInterface &p_arg_type);
bool _populate_object_type_interfaces();
void _populate_builtin_type_interfaces();
diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp
index 080f366692..5f518d0613 100644
--- a/modules/mono/mono_gd/gd_mono.cpp
+++ b/modules/mono/mono_gd/gd_mono.cpp
@@ -424,6 +424,9 @@ void GDMono::initialize_load_assemblies() {
CRASH_COND_MSG(!tool_assemblies_loaded, "Mono: Failed to load '" TOOLS_ASM_NAME "' assemblies.");
#endif
+ if (Main::is_project_manager())
+ return;
+
// Load the project's main assembly. This doesn't necessarily need to succeed.
// The game may not be using .NET at all, or if the project does use .NET and
// we're running in the editor, it may just happen to be it wasn't built yet.
diff --git a/modules/theora/video_stream_theora.cpp b/modules/theora/video_stream_theora.cpp
index 4d83e6a4a5..498391e44a 100644
--- a/modules/theora/video_stream_theora.cpp
+++ b/modules/theora/video_stream_theora.cpp
@@ -581,9 +581,8 @@ bool VideoStreamPlaybackTheora::is_paused() const {
return paused;
};
-void VideoStreamPlaybackTheora::set_loop(bool p_enable){
-
-};
+void VideoStreamPlaybackTheora::set_loop(bool p_enable) {
+}
bool VideoStreamPlaybackTheora::has_loop() const {
return false;
@@ -605,10 +604,8 @@ float VideoStreamPlaybackTheora::get_playback_position() const {
return get_time();
};
-void VideoStreamPlaybackTheora::seek(float p_time){
-
- // no
-};
+void VideoStreamPlaybackTheora::seek(float p_time) {
+}
void VideoStreamPlaybackTheora::set_mix_callback(AudioMixCallback p_callback, void *p_userdata) {
mix_callback = p_callback;
diff --git a/modules/websocket/register_types.cpp b/modules/websocket/register_types.cpp
index 1ad249e1eb..bc50de414e 100644
--- a/modules/websocket/register_types.cpp
+++ b/modules/websocket/register_types.cpp
@@ -42,9 +42,16 @@
#endif
#ifdef TOOLS_ENABLED
#include "editor/debugger/editor_debugger_server.h"
+#include "editor/editor_node.h"
#include "editor_debugger_server_websocket.h"
#endif
+#ifdef TOOLS_ENABLED
+static void _editor_init_callback() {
+ EditorDebuggerServer::register_protocol_handler("ws://", EditorDebuggerServerWebSocket::create);
+}
+#endif
+
void register_websocket_types() {
#ifdef JAVASCRIPT_ENABLED
EMWSPeer::make_default();
@@ -62,7 +69,7 @@ void register_websocket_types() {
ClassDB::register_custom_instance_class<WebSocketPeer>();
#ifdef TOOLS_ENABLED
- EditorDebuggerServer::register_protocol_handler("ws://", EditorDebuggerServerWebSocket::create);
+ EditorNode::add_init_callback(&_editor_init_callback);
#endif
}
diff --git a/modules/xatlas_unwrap/register_types.cpp b/modules/xatlas_unwrap/register_types.cpp
index b996be2a4c..6242009f67 100644
--- a/modules/xatlas_unwrap/register_types.cpp
+++ b/modules/xatlas_unwrap/register_types.cpp
@@ -145,7 +145,7 @@ bool xatlas_mesh_lightmap_unwrap_callback(float p_texel_size, const float *p_ver
ERR_FAIL_COND_V_MSG(err != xatlas::AddMeshError::Enum::Success, false, xatlas::StringForEnum(err));
printf("Generate..\n");
- xatlas::Generate(atlas, chart_options, nullptr, pack_options);
+ xatlas::Generate(atlas, chart_options, xatlas::ParameterizeOptions(), pack_options);
*r_size_hint_x = atlas->width;
*r_size_hint_y = atlas->height;
diff --git a/platform/android/audio_driver_jandroid.cpp b/platform/android/audio_driver_jandroid.cpp
index 0ace7d03a1..09c981b3fa 100644
--- a/platform/android/audio_driver_jandroid.cpp
+++ b/platform/android/audio_driver_jandroid.cpp
@@ -73,9 +73,9 @@ Error AudioDriverAndroid::init() {
// __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device");
JNIEnv *env = ThreadAndroid::get_env();
- int mix_rate = GLOBAL_DEF_RST("audio/mix_rate", 44100);
+ int mix_rate = GLOBAL_GET("audio/mix_rate");
- int latency = GLOBAL_DEF_RST("audio/output_latency", 25);
+ int latency = GLOBAL_GET("audio/output_latency");
unsigned int buffer_size = next_power_of_2(latency * mix_rate / 1000);
print_verbose("Audio buffer size: " + itos(buffer_size));
diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp
index 48c23d3c31..1436d832de 100644
--- a/platform/android/display_server_android.cpp
+++ b/platform/android/display_server_android.cpp
@@ -155,12 +155,12 @@ bool DisplayServerAndroid::screen_is_touchscreen(int p_screen) const {
return true;
}
-void DisplayServerAndroid::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, int p_max_length) {
+void DisplayServerAndroid::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, int p_max_length, int p_cursor_start, int p_cursor_end) {
GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java();
ERR_FAIL_COND(!godot_io_java);
if (godot_io_java->has_vk()) {
- godot_io_java->show_vk(p_existing_text, p_max_length);
+ godot_io_java->show_vk(p_existing_text, p_max_length, p_cursor_start, p_cursor_end);
} else {
ERR_PRINT("Virtual keyboard not available");
}
@@ -367,6 +367,25 @@ void DisplayServerAndroid::register_android_driver() {
register_create_function("android", create_func, get_rendering_drivers_func);
}
+void DisplayServerAndroid::reset_window() {
+#if defined(VULKAN_ENABLED)
+ if (rendering_driver == "vulkan") {
+ ANativeWindow *native_window = OS_Android::get_singleton()->get_native_window();
+ ERR_FAIL_COND(!native_window);
+
+ ERR_FAIL_COND(!context_vulkan);
+ context_vulkan->window_destroy(MAIN_WINDOW_ID);
+
+ Size2i display_size = OS_Android::get_singleton()->get_display_size();
+ if (context_vulkan->window_create(native_window, display_size.width, display_size.height) == -1) {
+ memdelete(context_vulkan);
+ context_vulkan = nullptr;
+ ERR_FAIL_MSG("Failed to reset Vulkan window.");
+ }
+ }
+#endif
+}
+
DisplayServerAndroid::DisplayServerAndroid(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
rendering_driver = p_rendering_driver;
diff --git a/platform/android/display_server_android.h b/platform/android/display_server_android.h
index b2909f258b..d64542df58 100644
--- a/platform/android/display_server_android.h
+++ b/platform/android/display_server_android.h
@@ -106,7 +106,7 @@ public:
virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
- virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), int p_max_length = -1);
+ virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), int p_max_length = -1, int p_cursor_start = -1, int p_cursor_end = -1);
virtual void virtual_keyboard_hide();
virtual int virtual_keyboard_get_height() const;
@@ -166,6 +166,8 @@ public:
static Vector<String> get_rendering_drivers_func();
static void register_android_driver();
+ void reset_window();
+
DisplayServerAndroid(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
~DisplayServerAndroid();
};
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp
index 0b6c6990f3..dfaaf68b69 100644
--- a/platform/android/export/export.cpp
+++ b/platform/android/export/export.cpp
@@ -44,6 +44,7 @@
#include "editor/editor_node.h"
#include "editor/editor_settings.h"
#include "platform/android/logo.gen.h"
+#include "platform/android/plugin/godot_plugin_config.h"
#include "platform/android/run_icon.gen.h"
#include <string.h>
@@ -252,16 +253,45 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
EditorProgress *ep;
};
+ Vector<PluginConfig> plugins;
+ volatile bool plugins_changed;
+ Mutex plugins_lock;
Vector<Device> devices;
volatile bool devices_changed;
Mutex device_lock;
- Thread *device_thread;
+ Thread *check_for_changes_thread;
volatile bool quit_request;
- static void _device_poll_thread(void *ud) {
+ static void _check_for_changes_poll_thread(void *ud) {
EditorExportPlatformAndroid *ea = (EditorExportPlatformAndroid *)ud;
while (!ea->quit_request) {
+ // Check for plugins updates
+ {
+ // Nothing to do if we already know the plugins have changed.
+ if (!ea->plugins_changed) {
+ Vector<PluginConfig> loaded_plugins = get_plugins();
+
+ MutexLock lock(ea->plugins_lock);
+
+ if (ea->plugins.size() != loaded_plugins.size()) {
+ ea->plugins_changed = true;
+ } else {
+ for (int i = 0; i < ea->plugins.size(); i++) {
+ if (ea->plugins[i].name != loaded_plugins[i].name) {
+ ea->plugins_changed = true;
+ break;
+ }
+ }
+ }
+
+ if (ea->plugins_changed) {
+ ea->plugins = loaded_plugins;
+ }
+ }
+ }
+
+ // Check for devices updates
String adb = EditorSettings::get_singleton()->get("export/android/adb");
if (FileAccess::exists(adb)) {
String devices;
@@ -573,6 +603,73 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
return abis;
}
+ /// List the gdap files in the directory specified by the p_path parameter.
+ static Vector<String> list_gdap_files(const String &p_path) {
+ Vector<String> dir_files;
+ DirAccessRef da = DirAccess::open(p_path);
+ if (da) {
+ da->list_dir_begin();
+ while (true) {
+ String file = da->get_next();
+ if (file == "") {
+ break;
+ }
+
+ if (da->current_is_dir() || da->current_is_hidden()) {
+ continue;
+ }
+
+ if (file.ends_with(PLUGIN_CONFIG_EXT)) {
+ dir_files.push_back(file);
+ }
+ }
+ da->list_dir_end();
+ }
+
+ return dir_files;
+ }
+
+ static Vector<PluginConfig> get_plugins() {
+ Vector<PluginConfig> loaded_plugins;
+
+ String plugins_dir = ProjectSettings::get_singleton()->get_resource_path().plus_file("android/plugins");
+
+ // Add the prebuilt plugins
+ loaded_plugins.append_array(get_prebuilt_plugins(plugins_dir));
+
+ if (DirAccess::exists(plugins_dir)) {
+ Vector<String> plugins_filenames = list_gdap_files(plugins_dir);
+
+ if (!plugins_filenames.empty()) {
+ Ref<ConfigFile> config_file = memnew(ConfigFile);
+ for (int i = 0; i < plugins_filenames.size(); i++) {
+ PluginConfig config = load_plugin_config(config_file, plugins_dir.plus_file(plugins_filenames[i]));
+ if (config.valid_config) {
+ loaded_plugins.push_back(config);
+ } else {
+ print_error("Invalid plugin config file " + plugins_filenames[i]);
+ }
+ }
+ }
+ }
+
+ return loaded_plugins;
+ }
+
+ static Vector<PluginConfig> get_enabled_plugins(const Ref<EditorExportPreset> &p_presets) {
+ Vector<PluginConfig> enabled_plugins;
+ Vector<PluginConfig> all_plugins = get_plugins();
+ for (int i = 0; i < all_plugins.size(); i++) {
+ PluginConfig plugin = all_plugins[i];
+ bool enabled = p_presets->get("plugins/" + plugin.name);
+ if (enabled) {
+ enabled_plugins.push_back(plugin);
+ }
+ }
+
+ return enabled_plugins;
+ }
+
static Error store_in_apk(APKExportData *ed, const String &p_path, const Vector<uint8_t> &p_data, int compression_method = Z_DEFLATED) {
zip_fileinfo zipfi = get_zip_fileinfo();
zipOpenNewFileInZip(ed->apk,
@@ -674,7 +771,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
int xr_mode_index = p_preset->get("xr_features/xr_mode");
- String plugins = p_preset->get("custom_template/plugins");
+ String plugins_names = get_plugins_names(get_enabled_plugins(p_preset));
Vector<String> perms;
@@ -829,9 +926,9 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
}
}
- if (tname == "meta-data" && attrname == "value" && value == "custom_template_plugins_value") {
+ if (tname == "meta-data" && attrname == "value" && value == "plugins_value" && !plugins_names.empty()) {
// Update the meta-data 'android:value' attribute with the list of enabled plugins.
- string_table.write[attr_value] = plugins;
+ string_table.write[attr_value] = plugins_names;
}
iofs += 20;
@@ -865,8 +962,8 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
feature_required_list.push_back(hand_tracking_index == 2);
feature_versions.push_back(-1); // no version attribute should be added.
- if (perms.find("oculus.permission.handtracking") == -1) {
- perms.push_back("oculus.permission.handtracking");
+ if (perms.find("com.oculus.permission.HAND_TRACKING") == -1) {
+ perms.push_back("com.oculus.permission.HAND_TRACKING");
}
}
}
@@ -1354,7 +1451,14 @@ public:
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/debug", PROPERTY_HINT_GLOBAL_FILE, "*.apk"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, "*.apk"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "custom_template/use_custom_build"), false));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/plugins", PROPERTY_HINT_PLACEHOLDER_TEXT, "Plugin1,Plugin2,..."), ""));
+
+ Vector<PluginConfig> plugins_configs = get_plugins();
+ for (int i = 0; i < plugins_configs.size(); i++) {
+ print_verbose("Found Android plugin " + plugins_configs[i].name);
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "plugins/" + plugins_configs[i].name), false));
+ }
+ plugins_changed = false;
+
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "command_line/extra_args"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "version/code", PROPERTY_HINT_RANGE, "1,4096,1,or_greater"), 1));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "version/name"), "1.0"));
@@ -1409,6 +1513,15 @@ public:
return logo;
}
+ virtual bool should_update_export_options() {
+ bool export_options_changed = plugins_changed;
+ if (export_options_changed) {
+ // don't clear unless we're reporting true, to avoid race
+ plugins_changed = false;
+ }
+ return export_options_changed;
+ }
+
virtual bool poll_export() {
bool dc = devices_changed;
if (dc) {
@@ -1755,18 +1868,22 @@ public:
#endif
String build_path = ProjectSettings::get_singleton()->get_resource_path().plus_file("android/build");
- String plugins_dir = ProjectSettings::get_singleton()->get_resource_path().plus_file("android/plugins");
build_command = build_path.plus_file(build_command);
String package_name = get_package_name(p_preset->get("package/unique_name"));
- String plugins = p_preset->get("custom_template/plugins");
+
+ Vector<PluginConfig> enabled_plugins = get_enabled_plugins(p_preset);
+ String local_plugins_binaries = get_plugins_binaries(BINARY_TYPE_LOCAL, enabled_plugins);
+ String remote_plugins_binaries = get_plugins_binaries(BINARY_TYPE_REMOTE, enabled_plugins);
+ String custom_maven_repos = get_plugins_custom_maven_repos(enabled_plugins);
List<String> cmdline;
cmdline.push_back("build");
cmdline.push_back("-Pexport_package_name=" + package_name); // argument to specify the package name.
- cmdline.push_back("-Pcustom_template_plugins_dir=" + plugins_dir); // argument to specify the plugins directory.
- cmdline.push_back("-Pcustom_template_plugins=" + plugins); // argument to specify the list of plugins to enable.
+ cmdline.push_back("-Pplugins_local_binaries=" + local_plugins_binaries); // argument to specify the list of plugins local dependencies.
+ cmdline.push_back("-Pplugins_remote_binaries=" + remote_plugins_binaries); // argument to specify the list of plugins remote dependencies.
+ cmdline.push_back("-Pplugins_maven_repos=" + custom_maven_repos); // argument to specify the list of custom maven repos for the plugins dependencies.
cmdline.push_back("-p"); // argument to specify the start directory.
cmdline.push_back(build_path); // start directory.
/*{ used for debug
@@ -2283,14 +2400,15 @@ public:
run_icon->create_from_image(img);
devices_changed = true;
+ plugins_changed = true;
quit_request = false;
- device_thread = Thread::create(_device_poll_thread, this);
+ check_for_changes_thread = Thread::create(_check_for_changes_poll_thread, this);
}
~EditorExportPlatformAndroid() {
quit_request = true;
- Thread::wait_to_finish(device_thread);
- memdelete(device_thread);
+ Thread::wait_to_finish(check_for_changes_thread);
+ memdelete(check_for_changes_thread);
}
};
diff --git a/platform/android/java/app/AndroidManifest.xml b/platform/android/java/app/AndroidManifest.xml
index cc480d1c84..f5b1d29f22 100644
--- a/platform/android/java/app/AndroidManifest.xml
+++ b/platform/android/java/app/AndroidManifest.xml
@@ -32,8 +32,8 @@
<!-- Metadata populated at export time and used by Godot to figure out which plugins must be enabled. -->
<meta-data
- android:name="custom_template_plugins"
- android:value="custom_template_plugins_value"/>
+ android:name="plugins"
+ android:value="plugins_value"/>
<activity
android:name=".GodotApp"
diff --git a/platform/android/java/app/build.gradle b/platform/android/java/app/build.gradle
index 9ae47d6174..ea341b37b1 100644
--- a/platform/android/java/app/build.gradle
+++ b/platform/android/java/app/build.gradle
@@ -21,6 +21,16 @@ allprojects {
mavenCentral()
google()
jcenter()
+
+ // Godot user plugins custom maven repos
+ String[] mavenRepos = getGodotPluginsMavenRepos()
+ if (mavenRepos != null && mavenRepos.size() > 0) {
+ for (String repoUrl : mavenRepos) {
+ maven {
+ url repoUrl
+ }
+ }
+ }
}
}
@@ -40,15 +50,18 @@ dependencies {
releaseImplementation fileTree(dir: 'libs/release', include: ['*.jar', '*.aar'])
}
- // Godot prebuilt plugins
- implementation fileTree(dir: 'libs/plugins', include: ["GodotPayment*.aar"])
+ // Godot user plugins remote dependencies
+ String[] remoteDeps = getGodotPluginsRemoteBinaries()
+ if (remoteDeps != null && remoteDeps.size() > 0) {
+ for (String dep : remoteDeps) {
+ implementation dep
+ }
+ }
- // Godot user plugins dependencies
- String pluginsDir = getGodotPluginsDirectory()
- String[] pluginsBinaries = getGodotPluginsBinaries()
- if (pluginsDir != null && !pluginsDir.isEmpty() &&
- pluginsBinaries != null && pluginsBinaries.size() > 0) {
- implementation fileTree(dir: pluginsDir, include: pluginsBinaries)
+ // Godot user plugins local dependencies
+ String[] pluginsBinaries = getGodotPluginsLocalBinaries()
+ if (pluginsBinaries != null && pluginsBinaries.size() > 0) {
+ implementation files(pluginsBinaries)
}
}
diff --git a/platform/android/java/app/config.gradle b/platform/android/java/app/config.gradle
index aa98194a10..5251bc3066 100644
--- a/platform/android/java/app/config.gradle
+++ b/platform/android/java/app/config.gradle
@@ -4,18 +4,18 @@ ext.versions = [
minSdk : 18,
targetSdk : 29,
buildTools : '29.0.3',
- supportCoreUtils : '28.0.0',
+ supportCoreUtils : '1.0.0',
kotlinVersion : '1.3.61',
- v4Support : '28.0.0'
+ v4Support : '1.0.0'
]
ext.libraries = [
androidGradlePlugin: "com.android.tools.build:gradle:$versions.androidGradlePlugin",
- supportCoreUtils : "com.android.support:support-core-utils:$versions.supportCoreUtils",
+ supportCoreUtils : "androidx.legacy:legacy-support-core-utils:$versions.supportCoreUtils",
kotlinGradlePlugin : "org.jetbrains.kotlin:kotlin-gradle-plugin:$versions.kotlinVersion",
kotlinStdLib : "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$versions.kotlinVersion",
- v4Support : "com.android.support:support-v4:$versions.v4Support"
+ v4Support : "androidx.legacy:legacy-support-v4:$versions.v4Support"
]
ext.getExportPackageName = { ->
@@ -28,39 +28,68 @@ ext.getExportPackageName = { ->
return appId
}
+final String PLUGIN_VALUE_SEPARATOR_REGEX = "\\|"
+
/**
- * Parse the project properties for the 'custom_template_plugins' property and return
- * their binaries for inclusion in the build dependencies.
- *
- * The listed plugins must have their binaries in the project plugins directory.
+ * Parse the project properties for the 'plugins_maven_repos' property and return the list
+ * of maven repos.
*/
-ext.getGodotPluginsBinaries = { ->
- String[] binDeps = []
+ext.getGodotPluginsMavenRepos = { ->
+ Set<String> mavenRepos = []
- // Retrieve the list of enabled plugins.
- if (project.hasProperty("custom_template_plugins")) {
- String pluginsList = project.property("custom_template_plugins")
- if (pluginsList != null && !pluginsList.trim().isEmpty()) {
- for (String plugin : pluginsList.split(",")) {
- binDeps += plugin.trim() + "*.aar"
+ // Retrieve the list of maven repos.
+ if (project.hasProperty("plugins_maven_repos")) {
+ String mavenReposProperty = project.property("plugins_maven_repos")
+ if (mavenReposProperty != null && !mavenReposProperty.trim().isEmpty()) {
+ for (String mavenRepoUrl : mavenReposProperty.split(PLUGIN_VALUE_SEPARATOR_REGEX)) {
+ mavenRepos += mavenRepoUrl.trim()
}
}
}
- return binDeps
+ return mavenRepos
+}
+
+/**
+ * Parse the project properties for the 'plugins_remote_binaries' property and return
+ * it for inclusion in the build dependencies.
+ */
+ext.getGodotPluginsRemoteBinaries = { ->
+ Set<String> remoteDeps = []
+
+ // Retrieve the list of remote plugins binaries.
+ if (project.hasProperty("plugins_remote_binaries")) {
+ String remoteDepsList = project.property("plugins_remote_binaries")
+ if (remoteDepsList != null && !remoteDepsList.trim().isEmpty()) {
+ for (String dep: remoteDepsList.split(PLUGIN_VALUE_SEPARATOR_REGEX)) {
+ remoteDeps += dep.trim()
+ }
+ }
+ }
+ return remoteDeps
}
/**
- * Parse the project properties for the 'custom_template_plugins_dir' property and return
- * its value.
+ * Parse the project properties for the 'plugins_local_binaries' property and return
+ * their binaries for inclusion in the build dependencies.
*
- * The returned value is the directory containing user plugins.
+ * Returns the prebuilt plugins if the 'plugins_local_binaries' property is unavailable.
*/
-ext.getGodotPluginsDirectory = { ->
- // The plugins directory is provided by the 'custom_template_plugins_dir' property.
- String pluginsDir = project.hasProperty("custom_template_plugins_dir")
- ? project.property("custom_template_plugins_dir")
- : ""
+ext.getGodotPluginsLocalBinaries = { ->
+ // Set the prebuilt plugins as default. If custom build is enabled,
+ // the 'plugins_local_binaries' will be defined so we can use it instead.
+ Set<String> binDeps = ["libs/plugins/GodotPayment.release.aar"]
+
+ // Retrieve the list of local plugins binaries.
+ if (project.hasProperty("plugins_local_binaries")) {
+ binDeps.clear()
+ String pluginsList = project.property("plugins_local_binaries")
+ if (pluginsList != null && !pluginsList.trim().isEmpty()) {
+ for (String plugin : pluginsList.split(PLUGIN_VALUE_SEPARATOR_REGEX)) {
+ binDeps += plugin.trim()
+ }
+ }
+ }
- return pluginsDir
+ return binDeps
}
diff --git a/platform/android/java/build.gradle b/platform/android/java/build.gradle
index 865b61956c..01a3607b20 100644
--- a/platform/android/java/build.gradle
+++ b/platform/android/java/build.gradle
@@ -140,7 +140,7 @@ task generateGodotTemplates(type: GradleBuild) {
startParameter.excludedTaskNames += ":lib:" + getSconsTaskName(buildType)
}
- tasks = ["copyGodotPaymentPluginToAppModule"]
+ tasks = []
// Only build the apks and aar files for which we have native shared libraries.
for (String target : supportedTargets) {
@@ -161,6 +161,7 @@ task generateGodotTemplates(type: GradleBuild) {
}
}
+ dependsOn 'copyGodotPaymentPluginToAppModule'
finalizedBy 'zipCustomBuild'
}
diff --git a/platform/android/java/gradle.properties b/platform/android/java/gradle.properties
index aac7c9b461..e14cd5ba5c 100644
--- a/platform/android/java/gradle.properties
+++ b/platform/android/java/gradle.properties
@@ -7,6 +7,9 @@
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
+android.enableJetifier=true
+android.useAndroidX=true
+
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx1536m
diff --git a/platform/android/java/lib/src/com/google/android/vending/expansion/downloader/impl/DownloadNotification.java b/platform/android/java/lib/src/com/google/android/vending/expansion/downloader/impl/DownloadNotification.java
index 0abaf2e052..d481c22204 100644
--- a/platform/android/java/lib/src/com/google/android/vending/expansion/downloader/impl/DownloadNotification.java
+++ b/platform/android/java/lib/src/com/google/android/vending/expansion/downloader/impl/DownloadNotification.java
@@ -29,9 +29,9 @@ import com.google.android.vending.expansion.downloader.IDownloaderClient;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
-import android.os.Build;
import android.os.Messenger;
-import android.support.v4.app.NotificationCompat;
+
+import androidx.core.app.NotificationCompat;
/**
* This class handles displaying the notification associated with the download
diff --git a/platform/android/java/lib/src/org/godotengine/godot/Godot.java b/platform/android/java/lib/src/org/godotengine/godot/Godot.java
index cc9c7a9652..f27d8620ec 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/Godot.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.java
@@ -66,10 +66,6 @@ import android.os.Messenger;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.provider.Settings.Secure;
-import android.support.annotation.CallSuper;
-import android.support.annotation.Keep;
-import android.support.annotation.NonNull;
-import android.support.v4.app.FragmentActivity;
import android.view.Display;
import android.view.KeyEvent;
import android.view.MotionEvent;
@@ -85,6 +81,11 @@ import android.widget.FrameLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
+import androidx.annotation.CallSuper;
+import androidx.annotation.Keep;
+import androidx.annotation.NonNull;
+import androidx.fragment.app.FragmentActivity;
+
import com.google.android.vending.expansion.downloader.DownloadProgressInfo;
import com.google.android.vending.expansion.downloader.DownloaderClientMarshaller;
import com.google.android.vending.expansion.downloader.DownloaderServiceMarshaller;
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java
index 410b93824d..93f4786e83 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java
@@ -460,9 +460,9 @@ public class GodotIO {
return (int)(metrics.density * 160f);
}
- public void showKeyboard(String p_existing_text, int p_max_input_length) {
+ public void showKeyboard(String p_existing_text, int p_max_input_length, int p_cursor_start, int p_cursor_end) {
if (edit != null)
- edit.showKeyboard(p_existing_text, p_max_input_length);
+ edit.showKeyboard(p_existing_text, p_max_input_length, p_cursor_start, p_cursor_end);
//InputMethodManager inputMgr = (InputMethodManager)activity.getSystemService(Context.INPUT_METHOD_SERVICE);
//inputMgr.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java b/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java
index 72198ba123..3693f36557 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java
@@ -66,11 +66,12 @@ public class GodotLib {
/**
* Invoked on the GL thread when the underlying Android surface has changed size.
- * @param width
- * @param height
+ * @param p_surface
+ * @param p_width
+ * @param p_height
* @see android.opengl.GLSurfaceView.Renderer#onSurfaceChanged(GL10, int, int)
*/
- public static native void resize(int width, int height);
+ public static native void resize(Surface p_surface, int p_width, int p_height);
/**
* Invoked on the render thread when the underlying Android surface is created or recreated.
@@ -189,7 +190,7 @@ public class GodotLib {
* @param p_method Name of the method to invoke
* @param p_params Parameters to use for method invocation
*/
- public static native void callobject(int p_id, String p_method, Object[] p_params);
+ public static native void callobject(long p_id, String p_method, Object[] p_params);
/**
* Invoke method |p_method| on the Godot object specified by |p_id| during idle time.
@@ -197,7 +198,7 @@ public class GodotLib {
* @param p_method Name of the method to invoke
* @param p_params Parameters to use for method invocation
*/
- public static native void calldeferred(int p_id, String p_method, Object[] p_params);
+ public static native void calldeferred(long p_id, String p_method, Object[] p_params);
/**
* Forward the results from a permission request.
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotRenderer.java b/platform/android/java/lib/src/org/godotengine/godot/GodotRenderer.java
index 99d3662317..64395f7d1e 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotRenderer.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotRenderer.java
@@ -64,7 +64,7 @@ class GodotRenderer implements GLSurfaceView.Renderer {
}
public void onSurfaceChanged(GL10 gl, int width, int height) {
- GodotLib.resize(width, height);
+ GodotLib.resize(null, width, height);
for (GodotPlugin plugin : pluginRegistry.getAllPlugins()) {
plugin.onGLSurfaceChanged(gl, width, height);
}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java
index 547c093419..7f596575a8 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java
@@ -58,6 +58,7 @@ public class GodotEditText extends EditText {
private GodotTextInputWrapper mInputWrapper;
private EditHandler sHandler = new EditHandler(this);
private String mOriginText;
+ private int mMaxInputLength;
private static class EditHandler extends Handler {
private final WeakReference<GodotEditText> mEdit;
@@ -104,11 +105,18 @@ public class GodotEditText extends EditText {
String text = edit.mOriginText;
if (edit.requestFocus()) {
edit.removeTextChangedListener(edit.mInputWrapper);
+ setMaxInputLength(edit);
edit.setText("");
edit.append(text);
+ if (msg.arg2 != -1) {
+ edit.setSelection(msg.arg1, msg.arg2);
+ edit.mInputWrapper.setSelection(true);
+ } else {
+ edit.mInputWrapper.setSelection(false);
+ }
+
edit.mInputWrapper.setOriginText(text);
edit.addTextChangedListener(edit.mInputWrapper);
- setMaxInputLength(edit, msg.arg1);
final InputMethodManager imm = (InputMethodManager)mRenderView.getView().getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(edit, 0);
}
@@ -125,14 +133,10 @@ public class GodotEditText extends EditText {
}
}
- private void setMaxInputLength(EditText p_edit_text, int p_max_input_length) {
- if (p_max_input_length > 0) {
- InputFilter[] filters = new InputFilter[1];
- filters[0] = new InputFilter.LengthFilter(p_max_input_length);
- p_edit_text.setFilters(filters);
- } else {
- p_edit_text.setFilters(new InputFilter[] {});
- }
+ private void setMaxInputLength(EditText p_edit_text) {
+ InputFilter[] filters = new InputFilter[1];
+ filters[0] = new InputFilter.LengthFilter(this.mMaxInputLength);
+ p_edit_text.setFilters(filters);
}
// ===========================================================
@@ -164,13 +168,24 @@ public class GodotEditText extends EditText {
// ===========================================================
// Methods
// ===========================================================
- public void showKeyboard(String p_existing_text, int p_max_input_length) {
- mOriginText = p_existing_text;
+ public void showKeyboard(String p_existing_text, int p_max_input_length, int p_cursor_start, int p_cursor_end) {
+ int maxInputLength = (p_max_input_length <= 0) ? Integer.MAX_VALUE : p_max_input_length;
+ if (p_cursor_start == -1) { // cursor position not given
+ this.mOriginText = p_existing_text;
+ this.mMaxInputLength = maxInputLength;
+ } else if (p_cursor_end == -1) { // not text selection
+ this.mOriginText = p_existing_text.substring(0, p_cursor_start);
+ this.mMaxInputLength = maxInputLength - (p_existing_text.length() - p_cursor_start);
+ } else {
+ this.mOriginText = p_existing_text.substring(0, p_cursor_end);
+ this.mMaxInputLength = maxInputLength - (p_existing_text.length() - p_cursor_end);
+ }
final Message msg = new Message();
msg.what = HANDLER_OPEN_IME_KEYBOARD;
msg.obj = this;
- msg.arg1 = p_max_input_length;
+ msg.arg1 = p_cursor_start;
+ msg.arg2 = p_cursor_end;
sHandler.sendMessage(msg);
}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java
index 9cd08de529..9c7cf9f341 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java
@@ -53,6 +53,7 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene
private final GodotRenderView mRenderView;
private final GodotEditText mEdit;
private String mOriginText;
+ private boolean mHasSelection;
// ===========================================================
// Constructors
@@ -77,6 +78,10 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene
mOriginText = originText;
}
+ public void setSelection(boolean selection) {
+ mHasSelection = selection;
+ }
+
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
@@ -95,6 +100,11 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene
for (int i = 0; i < count; ++i) {
GodotLib.key(KeyEvent.KEYCODE_DEL, KeyEvent.KEYCODE_DEL, 0, true);
GodotLib.key(KeyEvent.KEYCODE_DEL, KeyEvent.KEYCODE_DEL, 0, false);
+
+ if (mHasSelection) {
+ mHasSelection = false;
+ break;
+ }
}
}
});
diff --git a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java
index a8146a1332..431bd4f5f9 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java
@@ -35,13 +35,13 @@ import org.godotengine.godot.Godot;
import android.app.Activity;
import android.content.Intent;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.text.TextUtils;
import android.util.Log;
import android.view.Surface;
import android.view.View;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
diff --git a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginRegistry.java b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginRegistry.java
index bb11300861..12d2ed09fb 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginRegistry.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginRegistry.java
@@ -35,13 +35,13 @@ import org.godotengine.godot.Godot;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
-import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.Log;
+import androidx.annotation.Nullable;
+
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
-import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
@@ -58,7 +58,9 @@ public final class GodotPluginRegistry {
/**
* Name for the metadata containing the list of Godot plugins to enable.
*/
- private static final String GODOT_ENABLED_PLUGINS_LABEL = "custom_template_plugins";
+ private static final String GODOT_ENABLED_PLUGINS_LABEL = "plugins";
+
+ private static final String PLUGIN_VALUE_SEPARATOR_REGEX = "\\|";
private static GodotPluginRegistry instance;
private final ConcurrentHashMap<String, GodotPlugin> registry;
@@ -128,13 +130,13 @@ public final class GodotPluginRegistry {
}
// When using the Godot editor for building and exporting the apk, this is used to check
- // which plugins to enable since the custom build template may contain prebuilt plugins.
+ // which plugins to enable.
// When using a custom process to generate the apk, the metadata is not needed since
// it's assumed that the developer is aware of the dependencies included in the apk.
final Set<String> enabledPluginsSet;
if (metaData.containsKey(GODOT_ENABLED_PLUGINS_LABEL)) {
String enabledPlugins = metaData.getString(GODOT_ENABLED_PLUGINS_LABEL, "");
- String[] enabledPluginsList = enabledPlugins.split(",");
+ String[] enabledPluginsList = enabledPlugins.split(PLUGIN_VALUE_SEPARATOR_REGEX);
if (enabledPluginsList.length == 0) {
// No plugins to enable. Aborting early.
return;
@@ -158,6 +160,8 @@ public final class GodotPluginRegistry {
continue;
}
+ Log.i(TAG, "Initializing Godot plugin " + pluginName);
+
// Retrieve the plugin class full name.
String pluginHandleClassFullName = metaData.getString(metaDataName);
if (!TextUtils.isEmpty(pluginHandleClassFullName)) {
@@ -177,6 +181,7 @@ public final class GodotPluginRegistry {
"Meta-data plugin name does not match the value returned by the plugin handle: " + pluginName + " =/= " + pluginHandle.getPluginName());
}
registry.put(pluginName, pluginHandle);
+ Log.i(TAG, "Completed initialization for Godot plugin " + pluginHandle.getPluginName());
} catch (ClassNotFoundException e) {
Log.w(TAG, "Unable to load Godot plugin " + pluginName, e);
} catch (IllegalAccessException e) {
diff --git a/platform/android/java/lib/src/org/godotengine/godot/plugin/SignalInfo.java b/platform/android/java/lib/src/org/godotengine/godot/plugin/SignalInfo.java
index 71523d8c27..f82c4d3fa0 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/plugin/SignalInfo.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/plugin/SignalInfo.java
@@ -30,9 +30,10 @@
package org.godotengine.godot.plugin;
-import android.support.annotation.NonNull;
import android.text.TextUtils;
+import androidx.annotation.NonNull;
+
import java.util.Arrays;
/**
diff --git a/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java b/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java
index c34e4c18db..6837e4f147 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java
@@ -37,9 +37,10 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PermissionInfo;
import android.os.Build;
-import android.support.v4.content.ContextCompat;
import android.util.Log;
+import androidx.core.content.ContextCompat;
+
import java.util.ArrayList;
import java.util.List;
diff --git a/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkRenderer.kt b/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkRenderer.kt
index 608ad48df9..aeb4628d5d 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkRenderer.kt
+++ b/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkRenderer.kt
@@ -59,9 +59,7 @@ internal class VkRenderer {
* Called when the surface is created and signals the beginning of rendering.
*/
fun onVkSurfaceCreated(surface: Surface) {
- // TODO: properly implement surface re-creation:
- // GodotLib.newcontext should be called here once it's done.
- //GodotLib.newcontext(surface, false)
+ GodotLib.newcontext(surface, false)
for (plugin in pluginRegistry.getAllPlugins()) {
plugin.onVkSurfaceCreated(surface)
@@ -72,12 +70,7 @@ internal class VkRenderer {
* Called after the surface is created and whenever its size changes.
*/
fun onVkSurfaceChanged(surface: Surface, width: Int, height: Int) {
- GodotLib.resize(width, height)
-
- // TODO: properly implement surface re-creation:
- // Update the native renderer instead of restarting the app.
- // GodotLib.newcontext should not be called here once it's done.
- GodotLib.newcontext(surface, false)
+ GodotLib.resize(surface, width, height)
for (plugin in pluginRegistry.getAllPlugins()) {
plugin.onVkSurfaceChanged(surface, width, height)
diff --git a/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/GodotPayment.java b/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/GodotPayment.java
index 6f76007e1e..e2b12c94a4 100644
--- a/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/GodotPayment.java
+++ b/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/GodotPayment.java
@@ -36,9 +36,10 @@ import org.godotengine.godot.GodotLib;
import org.godotengine.godot.plugin.GodotPlugin;
import android.content.Intent;
-import android.support.annotation.NonNull;
import android.util.Log;
+import androidx.annotation.NonNull;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -47,7 +48,7 @@ import org.json.JSONException;
import org.json.JSONObject;
public class GodotPayment extends GodotPlugin {
- private Integer purchaseCallbackId = 0;
+ private Long purchaseCallbackId = 0L;
private String accessToken;
private String purchaseValidationUrlPrefix;
private String transactionId;
@@ -128,11 +129,11 @@ public class GodotPayment extends GodotPlugin {
GodotLib.calldeferred(purchaseCallbackId, "purchase_owned", new Object[] { sku });
}
- public int getPurchaseCallbackId() {
+ public long getPurchaseCallbackId() {
return purchaseCallbackId;
}
- public void setPurchaseCallbackId(int purchaseCallbackId) {
+ public void setPurchaseCallbackId(long purchaseCallbackId) {
this.purchaseCallbackId = purchaseCallbackId;
}
diff --git a/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/PurchaseTask.java b/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/PurchaseTask.java
index 2742bb15bf..f894bd5132 100644
--- a/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/PurchaseTask.java
+++ b/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/PurchaseTask.java
@@ -56,7 +56,7 @@ abstract public class PurchaseTask {
PaymentsCache pc = new PaymentsCache(context);
Boolean isBlocked = pc.getConsumableFlag("block", sku);
/*
- if(isBlocked){
+ if(isBlocked) {
Log.d("XXX", "Is awaiting payment confirmation");
error("Awaiting payment confirmation");
return;
diff --git a/platform/android/java_godot_io_wrapper.cpp b/platform/android/java_godot_io_wrapper.cpp
index 0da0bd6387..0a42adeaf2 100644
--- a/platform/android/java_godot_io_wrapper.cpp
+++ b/platform/android/java_godot_io_wrapper.cpp
@@ -53,7 +53,7 @@ GodotIOJavaWrapper::GodotIOJavaWrapper(JNIEnv *p_env, jobject p_godot_io_instanc
_get_model = p_env->GetMethodID(cls, "getModel", "()Ljava/lang/String;");
_get_screen_DPI = p_env->GetMethodID(cls, "getScreenDPI", "()I");
_get_unique_id = p_env->GetMethodID(cls, "getUniqueID", "()Ljava/lang/String;");
- _show_keyboard = p_env->GetMethodID(cls, "showKeyboard", "(Ljava/lang/String;I)V");
+ _show_keyboard = p_env->GetMethodID(cls, "showKeyboard", "(Ljava/lang/String;III)V");
_hide_keyboard = p_env->GetMethodID(cls, "hideKeyboard", "()V");
_set_screen_orientation = p_env->GetMethodID(cls, "setScreenOrientation", "(I)V");
_get_screen_orientation = p_env->GetMethodID(cls, "getScreenOrientation", "()I");
@@ -132,11 +132,11 @@ bool GodotIOJavaWrapper::has_vk() {
return (_show_keyboard != 0) && (_hide_keyboard != 0);
}
-void GodotIOJavaWrapper::show_vk(const String &p_existing, int p_max_input_length) {
+void GodotIOJavaWrapper::show_vk(const String &p_existing, int p_max_input_length, int p_cursor_start, int p_cursor_end) {
if (_show_keyboard) {
JNIEnv *env = ThreadAndroid::get_env();
jstring jStr = env->NewStringUTF(p_existing.utf8().get_data());
- env->CallVoidMethod(godot_io_instance, _show_keyboard, jStr, p_max_input_length);
+ env->CallVoidMethod(godot_io_instance, _show_keyboard, jStr, p_max_input_length, p_cursor_start, p_cursor_end);
}
}
diff --git a/platform/android/java_godot_io_wrapper.h b/platform/android/java_godot_io_wrapper.h
index dbb3b564f6..1742021379 100644
--- a/platform/android/java_godot_io_wrapper.h
+++ b/platform/android/java_godot_io_wrapper.h
@@ -70,7 +70,7 @@ public:
int get_screen_dpi();
String get_unique_id();
bool has_vk();
- void show_vk(const String &p_existing, int p_max_input_length);
+ void show_vk(const String &p_existing, int p_max_input_length, int p_cursor_start, int p_cursor_end);
void hide_vk();
int get_vk_height();
void set_vk_height(int p_height);
diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp
index 23e0d24b57..1f61c4a805 100644
--- a/platform/android/java_godot_lib_jni.cpp
+++ b/platform/android/java_godot_lib_jni.cpp
@@ -164,9 +164,20 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jc
ClassDB::register_class<JNISingleton>();
}
-JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_resize(JNIEnv *env, jclass clazz, jint width, jint height) {
- if (os_android)
- os_android->set_display_size(Size2i(width, height));
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_resize(JNIEnv *env, jclass clazz, jobject p_surface, jint p_width, jint p_height) {
+ if (os_android) {
+ os_android->set_display_size(Size2i(p_width, p_height));
+
+ // No need to reset the surface during startup
+ if (step > 0) {
+ if (p_surface) {
+ ANativeWindow *native_window = ANativeWindow_fromSurface(env, p_surface);
+ os_android->set_native_window(native_window);
+
+ DisplayServerAndroid::get_singleton()->reset_window();
+ }
+ }
+ }
}
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_newcontext(JNIEnv *env, jclass clazz, jobject p_surface, jboolean p_32_bits) {
@@ -375,8 +386,8 @@ JNIEXPORT jstring JNICALL Java_org_godotengine_godot_GodotLib_getGlobal(JNIEnv *
return env->NewStringUTF(ProjectSettings::get_singleton()->get(js).operator String().utf8().get_data());
}
-JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_callobject(JNIEnv *env, jclass clazz, jint ID, jstring method, jobjectArray params) {
- Object *obj = ObjectDB::get_instance(ObjectID((uint64_t)ID));
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_callobject(JNIEnv *env, jclass clazz, jlong ID, jstring method, jobjectArray params) {
+ Object *obj = ObjectDB::get_instance(ObjectID(ID));
ERR_FAIL_COND(!obj);
int res = env->PushLocalFrame(16);
@@ -405,8 +416,8 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_callobject(JNIEnv *en
env->PopLocalFrame(nullptr);
}
-JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_calldeferred(JNIEnv *env, jclass clazz, jint ID, jstring method, jobjectArray params) {
- Object *obj = ObjectDB::get_instance(ObjectID((uint64_t)ID));
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_calldeferred(JNIEnv *env, jclass clazz, jlong ID, jstring method, jobjectArray params) {
+ Object *obj = ObjectDB::get_instance(ObjectID(ID));
ERR_FAIL_COND(!obj);
int res = env->PushLocalFrame(16);
diff --git a/platform/android/java_godot_lib_jni.h b/platform/android/java_godot_lib_jni.h
index 221d701e2b..e8be7be0d0 100644
--- a/platform/android/java_godot_lib_jni.h
+++ b/platform/android/java_godot_lib_jni.h
@@ -40,7 +40,7 @@ extern "C" {
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jclass clazz, jobject activity, jobject p_asset_manager, jboolean p_use_apk_expansion);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_ondestroy(JNIEnv *env, jclass clazz, jobject activity);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jclass clazz, jobjectArray p_cmdline);
-JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_resize(JNIEnv *env, jclass clazz, jint width, jint height);
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_resize(JNIEnv *env, jclass clazz, jobject p_surface, jint p_width, jint p_height);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_newcontext(JNIEnv *env, jclass clazz, jobject p_surface, jboolean p_32_bits);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, jclass clazz);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_back(JNIEnv *env, jclass clazz);
@@ -61,8 +61,8 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_gyroscope(JNIEnv *env
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_focusin(JNIEnv *env, jclass clazz);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_focusout(JNIEnv *env, jclass clazz);
JNIEXPORT jstring JNICALL Java_org_godotengine_godot_GodotLib_getGlobal(JNIEnv *env, jclass clazz, jstring path);
-JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_callobject(JNIEnv *env, jclass clazz, jint ID, jstring method, jobjectArray params);
-JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_calldeferred(JNIEnv *env, jclass clazz, jint ID, jstring method, jobjectArray params);
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_callobject(JNIEnv *env, jclass clazz, jlong ID, jstring method, jobjectArray params);
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_calldeferred(JNIEnv *env, jclass clazz, jlong ID, jstring method, jobjectArray params);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setVirtualKeyboardHeight(JNIEnv *env, jclass clazz, jint p_height);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_requestPermissionResult(JNIEnv *env, jclass clazz, jstring p_permission, jboolean p_result);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onRendererResumed(JNIEnv *env, jclass clazz);
diff --git a/platform/android/plugin/godot_plugin_config.h b/platform/android/plugin/godot_plugin_config.h
new file mode 100644
index 0000000000..9ad7de1202
--- /dev/null
+++ b/platform/android/plugin/godot_plugin_config.h
@@ -0,0 +1,251 @@
+/*************************************************************************/
+/* godot_plugin_config.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef GODOT_PLUGIN_CONFIG_H
+#define GODOT_PLUGIN_CONFIG_H
+
+#include "core/error_list.h"
+#include "core/io/config_file.h"
+#include "core/ustring.h"
+
+static const char *PLUGIN_CONFIG_EXT = ".gdap";
+
+static const char *CONFIG_SECTION = "config";
+static const char *CONFIG_NAME_KEY = "name";
+static const char *CONFIG_BINARY_TYPE_KEY = "binary_type";
+static const char *CONFIG_BINARY_KEY = "binary";
+
+static const char *DEPENDENCIES_SECTION = "dependencies";
+static const char *DEPENDENCIES_LOCAL_KEY = "local";
+static const char *DEPENDENCIES_REMOTE_KEY = "remote";
+static const char *DEPENDENCIES_CUSTOM_MAVEN_REPOS_KEY = "custom_maven_repos";
+
+static const char *BINARY_TYPE_LOCAL = "local";
+static const char *BINARY_TYPE_REMOTE = "remote";
+
+static const char *PLUGIN_VALUE_SEPARATOR = "|";
+
+/*
+ The `config` section and fields are required and defined as follow:
+- **name**: name of the plugin
+- **binary_type**: can be either `local` or `remote`. The type affects the **binary** field
+- **binary**:
+ - if **binary_type** is `local`, then this should be the filename of the plugin `aar` file in the `res://android/plugins` directory (e.g: `MyPlugin.aar`).
+ - if **binary_type** is `remote`, then this should be a declaration for a remote gradle binary (e.g: "org.godot.example:my-plugin:0.0.0").
+
+The `dependencies` section and fields are optional and defined as follow:
+- **local**: contains a list of local `.aar` binary files the plugin depends on. The local binary dependencies must also be located in the `res://android/plugins` directory.
+- **remote**: contains a list of remote binary gradle dependencies for the plugin.
+- **custom_maven_repos**: contains a list of urls specifying custom maven repos required for the plugin's dependencies.
+
+ See https://github.com/godotengine/godot/issues/38157#issuecomment-618773871
+ */
+struct PluginConfig {
+ // Set to true when the config file is properly loaded.
+ bool valid_config = false;
+
+ // Required config section
+ String name;
+ String binary_type;
+ String binary;
+
+ // Optional dependencies section
+ Vector<String> local_dependencies;
+ Vector<String> remote_dependencies;
+ Vector<String> custom_maven_repos;
+};
+
+/*
+ * Set of prebuilt plugins.
+ */
+static const PluginConfig GODOT_PAYMENT = {
+ /*.valid_config =*/true,
+ /*.name =*/"GodotPayment",
+ /*.binary_type =*/"local",
+ /*.binary =*/"res://android/build/libs/plugins/GodotPayment.release.aar",
+ /*.local_dependencies =*/{},
+ /*.remote_dependencies =*/{},
+ /*.custom_maven_repos =*/{}
+};
+
+static inline String resolve_local_dependency_path(String plugin_config_dir, String dependency_path) {
+ String absolute_path;
+ if (!dependency_path.empty()) {
+ if (dependency_path.is_abs_path()) {
+ absolute_path = ProjectSettings::get_singleton()->globalize_path(dependency_path);
+ } else {
+ absolute_path = plugin_config_dir.plus_file(dependency_path);
+ }
+ }
+
+ return absolute_path;
+}
+
+static inline PluginConfig resolve_prebuilt_plugin(PluginConfig prebuilt_plugin, String plugin_config_dir) {
+ PluginConfig resolved = prebuilt_plugin;
+ resolved.binary = resolved.binary_type == BINARY_TYPE_LOCAL ? resolve_local_dependency_path(plugin_config_dir, prebuilt_plugin.binary) : prebuilt_plugin.binary;
+ if (!prebuilt_plugin.local_dependencies.empty()) {
+ resolved.local_dependencies.clear();
+ for (int i = 0; i < prebuilt_plugin.local_dependencies.size(); i++) {
+ resolved.local_dependencies.push_back(resolve_local_dependency_path(plugin_config_dir, prebuilt_plugin.local_dependencies[i]));
+ }
+ }
+ return resolved;
+}
+
+static inline Vector<PluginConfig> get_prebuilt_plugins(String plugins_base_dir) {
+ Vector<PluginConfig> prebuilt_plugins;
+ prebuilt_plugins.push_back(resolve_prebuilt_plugin(GODOT_PAYMENT, plugins_base_dir));
+ return prebuilt_plugins;
+}
+
+static inline bool is_plugin_config_valid(PluginConfig plugin_config) {
+ bool valid_name = !plugin_config.name.empty();
+ bool valid_binary_type = plugin_config.binary_type == BINARY_TYPE_LOCAL ||
+ plugin_config.binary_type == BINARY_TYPE_REMOTE;
+
+ bool valid_binary = false;
+ if (valid_binary_type) {
+ valid_binary = !plugin_config.binary.empty() &&
+ (plugin_config.binary_type == BINARY_TYPE_REMOTE ||
+ FileAccess::exists(plugin_config.binary));
+ }
+
+ bool valid_local_dependencies = true;
+ if (!plugin_config.local_dependencies.empty()) {
+ for (int i = 0; i < plugin_config.local_dependencies.size(); i++) {
+ if (!FileAccess::exists(plugin_config.local_dependencies[i])) {
+ valid_local_dependencies = false;
+ break;
+ }
+ }
+ }
+ return valid_name && valid_binary && valid_binary_type && valid_local_dependencies;
+}
+
+static inline PluginConfig load_plugin_config(Ref<ConfigFile> config_file, const String &path) {
+ PluginConfig plugin_config = {};
+
+ if (config_file.is_valid()) {
+ Error err = config_file->load(path);
+ if (err == OK) {
+ String config_base_dir = path.get_base_dir();
+
+ plugin_config.name = config_file->get_value(CONFIG_SECTION, CONFIG_NAME_KEY, String());
+ plugin_config.binary_type = config_file->get_value(CONFIG_SECTION, CONFIG_BINARY_TYPE_KEY, String());
+
+ String binary_path = config_file->get_value(CONFIG_SECTION, CONFIG_BINARY_KEY, String());
+ plugin_config.binary = plugin_config.binary_type == BINARY_TYPE_LOCAL ? resolve_local_dependency_path(config_base_dir, binary_path) : binary_path;
+
+ if (config_file->has_section(DEPENDENCIES_SECTION)) {
+ Vector<String> local_dependencies_paths = config_file->get_value(DEPENDENCIES_SECTION, DEPENDENCIES_LOCAL_KEY, Vector<String>());
+ if (!local_dependencies_paths.empty()) {
+ for (int i = 0; i < local_dependencies_paths.size(); i++) {
+ plugin_config.local_dependencies.push_back(resolve_local_dependency_path(config_base_dir, local_dependencies_paths[i]));
+ }
+ }
+
+ plugin_config.remote_dependencies = config_file->get_value(DEPENDENCIES_SECTION, DEPENDENCIES_REMOTE_KEY, Vector<String>());
+ plugin_config.custom_maven_repos = config_file->get_value(DEPENDENCIES_SECTION, DEPENDENCIES_CUSTOM_MAVEN_REPOS_KEY, Vector<String>());
+ }
+
+ plugin_config.valid_config = is_plugin_config_valid(plugin_config);
+ }
+ }
+
+ return plugin_config;
+}
+
+static inline String get_plugins_binaries(String binary_type, Vector<PluginConfig> plugins_configs) {
+ String plugins_binaries;
+ if (!plugins_configs.empty()) {
+ Vector<String> binaries;
+ for (int i = 0; i < plugins_configs.size(); i++) {
+ PluginConfig config = plugins_configs[i];
+ if (!config.valid_config) {
+ continue;
+ }
+
+ if (config.binary_type == binary_type) {
+ binaries.push_back(config.binary);
+ }
+
+ if (binary_type == BINARY_TYPE_LOCAL) {
+ binaries.append_array(config.local_dependencies);
+ }
+
+ if (binary_type == BINARY_TYPE_REMOTE) {
+ binaries.append_array(config.remote_dependencies);
+ }
+ }
+
+ plugins_binaries = String(PLUGIN_VALUE_SEPARATOR).join(binaries);
+ }
+
+ return plugins_binaries;
+}
+
+static inline String get_plugins_custom_maven_repos(Vector<PluginConfig> plugins_configs) {
+ String custom_maven_repos;
+ if (!plugins_configs.empty()) {
+ Vector<String> repos_urls;
+ for (int i = 0; i < plugins_configs.size(); i++) {
+ PluginConfig config = plugins_configs[i];
+ if (!config.valid_config) {
+ continue;
+ }
+
+ repos_urls.append_array(config.custom_maven_repos);
+ }
+
+ custom_maven_repos = String(PLUGIN_VALUE_SEPARATOR).join(repos_urls);
+ }
+ return custom_maven_repos;
+}
+
+static inline String get_plugins_names(Vector<PluginConfig> plugins_configs) {
+ String plugins_names;
+ if (!plugins_configs.empty()) {
+ Vector<String> names;
+ for (int i = 0; i < plugins_configs.size(); i++) {
+ PluginConfig config = plugins_configs[i];
+ if (!config.valid_config) {
+ continue;
+ }
+
+ names.push_back(config.name);
+ }
+ plugins_names = String(PLUGIN_VALUE_SEPARATOR).join(names);
+ }
+
+ return plugins_names;
+}
+
+#endif // GODOT_PLUGIN_CONFIG_H
diff --git a/platform/haiku/audio_driver_media_kit.cpp b/platform/haiku/audio_driver_media_kit.cpp
index 94c9e83368..2fbbeeb176 100644
--- a/platform/haiku/audio_driver_media_kit.cpp
+++ b/platform/haiku/audio_driver_media_kit.cpp
@@ -39,11 +39,11 @@ int32_t *AudioDriverMediaKit::samples_in = nullptr;
Error AudioDriverMediaKit::init() {
active = false;
- mix_rate = GLOBAL_DEF_RST("audio/mix_rate", DEFAULT_MIX_RATE);
+ mix_rate = GLOBAL_GET("audio/mix_rate");
speaker_mode = SPEAKER_MODE_STEREO;
channels = 2;
- int latency = GLOBAL_DEF_RST("audio/output_latency", DEFAULT_OUTPUT_LATENCY);
+ int latency = GLOBAL_GET("audio/output_latency");
buffer_size = next_power_of_2(latency * mix_rate / 1000);
samples_in = memnew_arr(int32_t, buffer_size * channels);
diff --git a/platform/iphone/os_iphone.cpp b/platform/iphone/os_iphone.cpp
index 107d142757..41dd623e69 100644
--- a/platform/iphone/os_iphone.cpp
+++ b/platform/iphone/os_iphone.cpp
@@ -441,7 +441,7 @@ extern Error _shell_open(String p_uri);
extern void _set_keep_screen_on(bool p_enabled);
extern void _vibrate();
-void OSIPhone::show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect, int p_max_input_length) {
+void OSIPhone::show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect, int p_max_input_length, int p_cursor_start, int p_cursor_end) {
_show_keyboard(p_existing_text);
};
diff --git a/platform/iphone/os_iphone.h b/platform/iphone/os_iphone.h
index a57b8eeb5d..955eb15d57 100644
--- a/platform/iphone/os_iphone.h
+++ b/platform/iphone/os_iphone.h
@@ -170,7 +170,7 @@ public:
virtual bool can_draw() const;
virtual bool has_virtual_keyboard() const;
- virtual void show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), int p_max_input_length = -1);
+ virtual void show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), int p_max_input_length = -1, int p_cursor_start = -1, int p_cursor_end = -1);
virtual void hide_virtual_keyboard();
virtual int get_virtual_keyboard_height() const;
diff --git a/platform/javascript/audio_driver_javascript.cpp b/platform/javascript/audio_driver_javascript.cpp
index 03ca5f78d1..b8914414e6 100644
--- a/platform/javascript/audio_driver_javascript.cpp
+++ b/platform/javascript/audio_driver_javascript.cpp
@@ -30,6 +30,8 @@
#include "audio_driver_javascript.h"
+#include "core/project_settings.h"
+
#include <emscripten.h>
AudioDriverJavaScript *AudioDriverJavaScript::singleton = nullptr;
@@ -62,38 +64,36 @@ void AudioDriverJavaScript::process_capture(float sample) {
}
Error AudioDriverJavaScript::init() {
+ int mix_rate = GLOBAL_GET("audio/mix_rate");
+ int latency = GLOBAL_GET("audio/output_latency");
+
/* clang-format off */
_driver_id = EM_ASM_INT({
+ const MIX_RATE = $0;
+ const LATENCY = $1 / 1000;
return Module.IDHandler.add({
- 'context': new (window.AudioContext || window.webkitAudioContext),
+ 'context': new (window.AudioContext || window.webkitAudioContext)({ sampleRate: MIX_RATE, latencyHint: LATENCY}),
'input': null,
'stream': null,
'script': null
});
- });
+ }, mix_rate, latency);
/* clang-format on */
int channel_count = get_total_channels_by_speaker_mode(get_speaker_mode());
+ buffer_length = closest_power_of_2((latency * mix_rate / 1000) * channel_count);
/* clang-format off */
buffer_length = EM_ASM_INT({
var ref = Module.IDHandler.get($0);
- var ctx = ref['context'];
- var CHANNEL_COUNT = $1;
-
- var channelCount = ctx.destination.channelCount;
- var script = null;
- try {
- // Try letting the browser recommend a buffer length.
- script = ctx.createScriptProcessor(0, 2, channelCount);
- } catch (e) {
- // ...otherwise, default to 4096.
- script = ctx.createScriptProcessor(4096, 2, channelCount);
- }
+ const ctx = ref['context'];
+ const BUFFER_LENGTH = $1;
+ const CHANNEL_COUNT = $2;
+
+ var script = ctx.createScriptProcessor(BUFFER_LENGTH, 2, CHANNEL_COUNT);
script.connect(ctx.destination);
ref['script'] = script;
-
return script.bufferSize;
- }, _driver_id, channel_count);
+ }, _driver_id, buffer_length, channel_count);
/* clang-format on */
if (!buffer_length) {
return FAILED;
@@ -156,6 +156,25 @@ void AudioDriverJavaScript::resume() {
/* clang-format on */
}
+float AudioDriverJavaScript::get_latency() {
+ /* clang-format off */
+ return EM_ASM_DOUBLE({
+ const ref = Module.IDHandler.get($0);
+ var latency = 0;
+ if (ref && ref['context']) {
+ const ctx = ref['context'];
+ if (ctx.baseLatency) {
+ latency += ctx.baseLatency;
+ }
+ if (ctx.outputLatency) {
+ latency += ctx.outputLatency;
+ }
+ }
+ return latency;
+ }, _driver_id);
+ /* clang-format on */
+}
+
int AudioDriverJavaScript::get_mix_rate() const {
/* clang-format off */
return EM_ASM_INT({
diff --git a/platform/javascript/audio_driver_javascript.h b/platform/javascript/audio_driver_javascript.h
index 7d5237998a..9b26be001e 100644
--- a/platform/javascript/audio_driver_javascript.h
+++ b/platform/javascript/audio_driver_javascript.h
@@ -50,6 +50,7 @@ public:
virtual Error init();
virtual void start();
void resume();
+ virtual float get_latency();
virtual int get_mix_rate() const;
virtual SpeakerMode get_speaker_mode() const;
virtual void lock();
diff --git a/platform/osx/display_server_osx.mm b/platform/osx/display_server_osx.mm
index 1cdcdbcaf5..9a1191490c 100644
--- a/platform/osx/display_server_osx.mm
+++ b/platform/osx/display_server_osx.mm
@@ -278,13 +278,17 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
}
- (BOOL)windowShouldClose:(id)sender {
- ERR_FAIL_COND_V(!DS_OSX->windows.has(window_id), YES);
+ if (!DS_OSX || !DS_OSX->windows.has(window_id)) {
+ return YES;
+ }
DS_OSX->_send_window_event(DS_OSX->windows[window_id], DisplayServerOSX::WINDOW_EVENT_CLOSE_REQUEST);
return NO;
}
- (void)windowWillClose:(NSNotification *)notification {
- ERR_FAIL_COND(!DS_OSX->windows.has(window_id));
+ if (!DS_OSX || !DS_OSX->windows.has(window_id)) {
+ return;
+ }
DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id];
while (wd.transient_children.size()) {
@@ -310,7 +314,9 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
}
- (void)windowDidEnterFullScreen:(NSNotification *)notification {
- ERR_FAIL_COND(!DS_OSX->windows.has(window_id));
+ if (!DS_OSX || !DS_OSX->windows.has(window_id)) {
+ return;
+ }
DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id];
wd.fullscreen = true;
@@ -320,8 +326,9 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
}
- (void)windowDidExitFullScreen:(NSNotification *)notification {
- if (!DS_OSX || !DS_OSX->windows.has(window_id))
+ if (!DS_OSX || !DS_OSX->windows.has(window_id)) {
return;
+ }
DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id];
wd.fullscreen = false;
@@ -383,8 +390,9 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
}
- (void)windowDidResize:(NSNotification *)notification {
- if (!DS_OSX || !DS_OSX->windows.has(window_id))
+ if (!DS_OSX || !DS_OSX->windows.has(window_id)) {
return;
+ }
DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id];
#if defined(OPENGL_ENABLED)
@@ -425,11 +433,26 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
}
- (void)windowDidMove:(NSNotification *)notification {
+ if (!DS_OSX || !DS_OSX->windows.has(window_id)) {
+ return;
+ }
+ DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id];
+
DS_OSX->_release_pressed_events();
+
+ if (!wd.rect_changed_callback.is_null()) {
+ Variant size = Rect2i(DS_OSX->window_get_position(window_id), DS_OSX->window_get_size(window_id));
+ Variant *sizep = &size;
+ Variant ret;
+ Callable::CallError ce;
+ wd.rect_changed_callback.call((const Variant **)&sizep, 1, ret, ce);
+ }
}
- (void)windowDidBecomeKey:(NSNotification *)notification {
- ERR_FAIL_COND(!DS_OSX->windows.has(window_id));
+ if (!DS_OSX || !DS_OSX->windows.has(window_id)) {
+ return;
+ }
DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id];
const CGFloat backingScaleFactor = (OS::get_singleton()->is_hidpi_allowed()) ? [wd.window_view backingScaleFactor] : 1.0;
@@ -441,7 +464,9 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
}
- (void)windowDidResignKey:(NSNotification *)notification {
- ERR_FAIL_COND(!DS_OSX->windows.has(window_id));
+ if (!DS_OSX || !DS_OSX->windows.has(window_id)) {
+ return;
+ }
DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id];
DS_OSX->window_focused = false;
@@ -451,7 +476,9 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
}
- (void)windowDidMiniaturize:(NSNotification *)notification {
- ERR_FAIL_COND(!DS_OSX->windows.has(window_id));
+ if (!DS_OSX || !DS_OSX->windows.has(window_id)) {
+ return;
+ }
DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id];
DS_OSX->window_focused = false;
@@ -461,7 +488,9 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
}
- (void)windowDidDeminiaturize:(NSNotification *)notification {
- ERR_FAIL_COND(!DS_OSX->windows.has(window_id));
+ if (!DS_OSX || !DS_OSX->windows.has(window_id)) {
+ return;
+ }
DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id];
DS_OSX->window_focused = true;
@@ -2148,7 +2177,7 @@ Rect2i DisplayServerOSX::screen_get_usable_rect(int p_screen) const {
Point2i position = Point2i(nsrect.origin.x, nsrect.origin.y + nsrect.size.height) * displayScale - _get_screens_origin();
position.y *= -1;
- Size2i size = Size2i(nsrect.size.width, nsrect.size.height) / displayScale;
+ Size2i size = Size2i(nsrect.size.width, nsrect.size.height) * displayScale;
return Rect2i(position, size);
}
diff --git a/platform/osx/export/export.cpp b/platform/osx/export/export.cpp
index b2ef9c0038..784fba75ec 100644
--- a/platform/osx/export/export.cpp
+++ b/platform/osx/export/export.cpp
@@ -57,6 +57,7 @@ class EditorExportPlatformOSX : public EditorExportPlatform {
Error _code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path);
Error _create_dmg(const String &p_dmg_path, const String &p_pkg_name, const String &p_app_path_name);
+ void _zip_folder_recursive(zipFile &p_zip, const String &p_root_path, const String &p_folder, const String &p_pkg_name);
#ifdef OSX_ENABLED
bool use_codesign() const { return true; }
@@ -363,6 +364,7 @@ void EditorExportPlatformOSX::_fix_plist(const Ref<EditorExportPreset> &p_preset
**/
Error EditorExportPlatformOSX::_code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path) {
+#ifdef OSX_ENABLED
List<String> args;
if (p_preset->get("codesign/timestamp")) {
@@ -373,8 +375,7 @@ Error EditorExportPlatformOSX::_code_sign(const Ref<EditorExportPreset> &p_prese
args.push_back("runtime");
}
- if (p_preset->get("codesign/entitlements") != "") {
- /* this should point to our entitlements.plist file that sandboxes our application, I don't know if this should also be placed in our app bundle */
+ if ((p_preset->get("codesign/entitlements") != "") && (p_path.get_extension() != "dmg")) {
args.push_back("--entitlements");
args.push_back(p_preset->get("codesign/entitlements"));
}
@@ -407,6 +408,7 @@ Error EditorExportPlatformOSX::_code_sign(const Ref<EditorExportPreset> &p_prese
EditorNode::add_io_error("codesign: invalid entitlements file");
return FAILED;
}
+#endif
return OK;
}
@@ -500,53 +502,42 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
Error err = OK;
String tmp_app_path_name = "";
- zlib_filefunc_def io2 = io;
- FileAccess *dst_f = nullptr;
- io2.opaque = &dst_f;
- zipFile dst_pkg_zip = nullptr;
DirAccess *tmp_app_path = nullptr;
String export_format = use_dmg() && p_path.ends_with("dmg") ? "dmg" : "zip";
- if (export_format == "dmg") {
- // We're on OSX so we can export to DMG, but first we create our application bundle
- tmp_app_path_name = EditorSettings::get_singleton()->get_cache_dir().plus_file(pkg_name + ".app");
- print_line("Exporting to " + tmp_app_path_name);
- tmp_app_path = DirAccess::create_for_path(tmp_app_path_name);
- if (!tmp_app_path) {
- err = ERR_CANT_CREATE;
- }
- // Create our folder structure or rely on unzip?
- if (err == OK) {
- print_line("Creating " + tmp_app_path_name + "/Contents/MacOS");
- err = tmp_app_path->make_dir_recursive(tmp_app_path_name + "/Contents/MacOS");
- }
+ // Create our application bundle.
+ tmp_app_path_name = EditorSettings::get_singleton()->get_cache_dir().plus_file(pkg_name + ".app");
+ print_line("Exporting to " + tmp_app_path_name);
+ tmp_app_path = DirAccess::create_for_path(tmp_app_path_name);
+ if (!tmp_app_path) {
+ err = ERR_CANT_CREATE;
+ }
- if (err == OK) {
- print_line("Creating " + tmp_app_path_name + "/Contents/Frameworks");
- err = tmp_app_path->make_dir_recursive(tmp_app_path_name + "/Contents/Frameworks");
- }
+ // Create our folder structure.
+ if (err == OK) {
+ print_line("Creating " + tmp_app_path_name + "/Contents/MacOS");
+ err = tmp_app_path->make_dir_recursive(tmp_app_path_name + "/Contents/MacOS");
+ }
- if (err == OK) {
- print_line("Creating " + tmp_app_path_name + "/Contents/Resources");
- err = tmp_app_path->make_dir_recursive(tmp_app_path_name + "/Contents/Resources");
- }
- } else {
- // Open our destination zip file
- dst_pkg_zip = zipOpen2(p_path.utf8().get_data(), APPEND_STATUS_CREATE, nullptr, &io2);
- if (!dst_pkg_zip) {
- err = ERR_CANT_CREATE;
- }
+ if (err == OK) {
+ print_line("Creating " + tmp_app_path_name + "/Contents/Frameworks");
+ err = tmp_app_path->make_dir_recursive(tmp_app_path_name + "/Contents/Frameworks");
}
- // Now process our template
+ if (err == OK) {
+ print_line("Creating " + tmp_app_path_name + "/Contents/Resources");
+ err = tmp_app_path->make_dir_recursive(tmp_app_path_name + "/Contents/Resources");
+ }
+
+ // Now process our template.
bool found_binary = false;
int total_size = 0;
while (ret == UNZ_OK && err == OK) {
bool is_execute = false;
- //get filename
+ // Get filename.
unz_file_info info;
char fname[16384];
ret = unzGetCurrentFileInfo(src_pkg_zip, &info, fname, 16384, nullptr, 0, nullptr, 0);
@@ -556,13 +547,12 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
Vector<uint8_t> data;
data.resize(info.uncompressed_size);
- //read
+ // Read.
unzOpenCurrentFile(src_pkg_zip);
unzReadCurrentFile(src_pkg_zip, data.ptrw(), data.size());
unzCloseCurrentFile(src_pkg_zip);
- //write
-
+ // Write.
file = file.replace_first("osx_template.app/", "");
if (file == "Contents/Info.plist") {
@@ -572,7 +562,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
if (file.begins_with("Contents/MacOS/godot_")) {
if (file != "Contents/MacOS/" + binary_to_use) {
ret = unzGoToNextFile(src_pkg_zip);
- continue; //ignore!
+ continue; // skip
}
found_binary = true;
is_execute = true;
@@ -580,7 +570,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
}
if (file == "Contents/Resources/icon.icns") {
- //see if there is an icon
+ // See if there is an icon.
String iconpath;
if (p_preset->get("application/icon") != "") {
iconpath = p_preset->get("application/icon");
@@ -612,14 +602,14 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
if (file.find("/data.mono.osx.64.release_debug/") != -1) {
if (!p_debug) {
ret = unzGoToNextFile(src_pkg_zip);
- continue; //skip
+ continue; // skip
}
file = file.replace("/data.mono.osx.64.release_debug/", "/data_" + pkg_name_safe + "/");
}
if (file.find("/data.mono.osx.64.release/") != -1) {
if (p_debug) {
ret = unzGoToNextFile(src_pkg_zip);
- continue; //skip
+ continue; // skip
}
file = file.replace("/data.mono.osx.64.release/", "/data_" + pkg_name_safe + "/");
}
@@ -627,62 +617,31 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
print_line("ADDING: " + file + " size: " + itos(data.size()));
total_size += data.size();
- if (export_format == "dmg") {
- // write it into our application bundle
- file = tmp_app_path_name.plus_file(file);
- if (err == OK) {
- err = tmp_app_path->make_dir_recursive(file.get_base_dir());
- }
- if (err == OK) {
- // write the file, need to add chmod
- FileAccess *f = FileAccess::open(file, FileAccess::WRITE);
- if (f) {
- f->store_buffer(data.ptr(), data.size());
- f->close();
- if (is_execute) {
- // Chmod with 0755 if the file is executable
- FileAccess::set_unix_permissions(file, 0755);
- }
- memdelete(f);
- } else {
- err = ERR_CANT_CREATE;
+ // Write it into our application bundle.
+ file = tmp_app_path_name.plus_file(file);
+ if (err == OK) {
+ err = tmp_app_path->make_dir_recursive(file.get_base_dir());
+ }
+ if (err == OK) {
+ FileAccess *f = FileAccess::open(file, FileAccess::WRITE);
+ if (f) {
+ f->store_buffer(data.ptr(), data.size());
+ f->close();
+ if (is_execute) {
+ // chmod with 0755 if the file is executable.
+ FileAccess::set_unix_permissions(file, 0755);
}
+ memdelete(f);
+ } else {
+ err = ERR_CANT_CREATE;
}
- } else {
- // add it to our zip file
- file = pkg_name + ".app/" + file;
-
- zip_fileinfo fi;
- fi.tmz_date.tm_hour = info.tmu_date.tm_hour;
- fi.tmz_date.tm_min = info.tmu_date.tm_min;
- fi.tmz_date.tm_sec = info.tmu_date.tm_sec;
- fi.tmz_date.tm_mon = info.tmu_date.tm_mon;
- fi.tmz_date.tm_mday = info.tmu_date.tm_mday;
- fi.tmz_date.tm_year = info.tmu_date.tm_year;
- fi.dosDate = info.dosDate;
- fi.internal_fa = info.internal_fa;
- fi.external_fa = info.external_fa;
-
- zipOpenNewFileInZip(dst_pkg_zip,
- file.utf8().get_data(),
- &fi,
- nullptr,
- 0,
- nullptr,
- 0,
- nullptr,
- Z_DEFLATED,
- Z_DEFAULT_COMPRESSION);
-
- zipWriteInFileInZip(dst_pkg_zip, data.ptr(), data.size());
- zipCloseFileInZip(dst_pkg_zip);
}
}
ret = unzGoToNextFile(src_pkg_zip);
}
- // we're done with our source zip
+ // We're done with our source zip.
unzClose(src_pkg_zip);
if (!found_binary) {
@@ -695,122 +654,130 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
return ERR_SKIP;
}
- if (export_format == "dmg") {
- String pack_path = tmp_app_path_name + "/Contents/Resources/" + pkg_name + ".pck";
- Vector<SharedObject> shared_objects;
- err = save_pack(p_preset, pack_path, &shared_objects);
+ String pack_path = tmp_app_path_name + "/Contents/Resources/" + pkg_name + ".pck";
+ Vector<SharedObject> shared_objects;
+ err = save_pack(p_preset, pack_path, &shared_objects);
- // see if we can code sign our new package
- bool sign_enabled = p_preset->get("codesign/enable");
+ // See if we can code sign our new package.
+ bool sign_enabled = p_preset->get("codesign/enable");
- if (err == OK) {
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- for (int i = 0; i < shared_objects.size(); i++) {
- err = da->copy(shared_objects[i].path, tmp_app_path_name + "/Contents/Frameworks/" + shared_objects[i].path.get_file());
- if (err == OK && sign_enabled) {
- err = _code_sign(p_preset, tmp_app_path_name + "/Contents/Frameworks/" + shared_objects[i].path.get_file());
- }
+ if (err == OK) {
+ DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ for (int i = 0; i < shared_objects.size(); i++) {
+ err = da->copy(shared_objects[i].path, tmp_app_path_name + "/Contents/Frameworks/" + shared_objects[i].path.get_file());
+ if (err == OK && sign_enabled) {
+ err = _code_sign(p_preset, tmp_app_path_name + "/Contents/Frameworks/" + shared_objects[i].path.get_file());
}
- memdelete(da);
}
+ memdelete(da);
+ }
- if (err == OK && sign_enabled) {
- if (ep.step("Code signing bundle", 2)) {
- return ERR_SKIP;
- }
-
- // the order in which we code sign is important, this is a bit of a shame or we could do this in our loop that extracts the files from our ZIP
-
- // start with our application
- err = _code_sign(p_preset, tmp_app_path_name + "/Contents/MacOS/" + pkg_name);
-
- ///@TODO we should check the contents of /Contents/Frameworks for frameworks to sign
+ if (err == OK && sign_enabled) {
+ if (ep.step("Code signing bundle", 2)) {
+ return ERR_SKIP;
}
+ err = _code_sign(p_preset, tmp_app_path_name + "/Contents/MacOS/" + pkg_name);
+ }
- // and finally create a DMG
+ if (export_format == "dmg") {
+ // Create a DMG.
if (err == OK) {
if (ep.step("Making DMG", 3)) {
return ERR_SKIP;
}
err = _create_dmg(p_path, pkg_name, tmp_app_path_name);
}
-
- // Clean up temporary .app dir
- OS::get_singleton()->move_to_trash(tmp_app_path_name);
-
- } else { // pck
-
- String pack_path = EditorSettings::get_singleton()->get_cache_dir().plus_file(pkg_name + ".pck");
-
- Vector<SharedObject> shared_objects;
- err = save_pack(p_preset, pack_path, &shared_objects);
-
- if (err == OK) {
- zipOpenNewFileInZip(dst_pkg_zip,
- (pkg_name + ".app/Contents/Resources/" + pkg_name + ".pck").utf8().get_data(),
- nullptr,
- nullptr,
- 0,
- nullptr,
- 0,
- nullptr,
- Z_DEFLATED,
- Z_DEFAULT_COMPRESSION);
-
- FileAccess *pf = FileAccess::open(pack_path, FileAccess::READ);
- if (pf) {
- const int BSIZE = 16384;
- uint8_t buf[BSIZE];
-
- while (true) {
- int r = pf->get_buffer(buf, BSIZE);
- if (r <= 0) {
- break;
- }
- zipWriteInFileInZip(dst_pkg_zip, buf, r);
- }
-
- zipCloseFileInZip(dst_pkg_zip);
- memdelete(pf);
- } else {
- err = ERR_CANT_OPEN;
+ // Sign DMG.
+ if (err == OK && sign_enabled) {
+ if (ep.step("Code signing DMG", 3)) {
+ return ERR_SKIP;
}
+ err = _code_sign(p_preset, p_path);
}
-
+ } else {
+ // Create ZIP.
if (err == OK) {
- //add shared objects
- for (int i = 0; i < shared_objects.size(); i++) {
- Vector<uint8_t> file = FileAccess::get_file_as_array(shared_objects[i].path);
- ERR_CONTINUE(file.empty());
-
- zipOpenNewFileInZip(dst_pkg_zip,
- (pkg_name + ".app/Contents/Frameworks/").plus_file(shared_objects[i].path.get_file()).utf8().get_data(),
- nullptr,
- nullptr,
- 0,
- nullptr,
- 0,
- nullptr,
- Z_DEFLATED,
- Z_DEFAULT_COMPRESSION);
-
- zipWriteInFileInZip(dst_pkg_zip, file.ptr(), file.size());
- zipCloseFileInZip(dst_pkg_zip);
+ if (ep.step("Making ZIP", 3)) {
+ return ERR_SKIP;
+ }
+ if (FileAccess::exists(p_path)) {
+ OS::get_singleton()->move_to_trash(p_path);
}
- }
- // Clean up generated file.
- DirAccess::remove_file_or_error(pack_path);
+ FileAccess *dst_f = nullptr;
+ zlib_filefunc_def io_dst = zipio_create_io_from_file(&dst_f);
+ zipFile zip = zipOpen2(p_path.utf8().get_data(), APPEND_STATUS_CREATE, nullptr, &io_dst);
+
+ _zip_folder_recursive(zip, EditorSettings::get_singleton()->get_cache_dir(), pkg_name + ".app", pkg_name);
+
+ zipClose(zip, nullptr);
+ }
}
- }
- if (dst_pkg_zip) {
- zipClose(dst_pkg_zip, nullptr);
+ // Clean up temporary .app dir.
+ OS::get_singleton()->move_to_trash(tmp_app_path_name);
}
return err;
}
+void EditorExportPlatformOSX::_zip_folder_recursive(zipFile &p_zip, const String &p_root_path, const String &p_folder, const String &p_pkg_name) {
+ String dir = p_root_path.plus_file(p_folder);
+
+ DirAccess *da = DirAccess::open(dir);
+ da->list_dir_begin();
+ String f;
+ while ((f = da->get_next()) != "") {
+ if (f == "." || f == "..") {
+ continue;
+ }
+ if (da->current_is_dir()) {
+ _zip_folder_recursive(p_zip, p_root_path, p_folder.plus_file(f), p_pkg_name);
+ } else {
+ bool is_executable = (p_folder.ends_with("MacOS") && (f == p_pkg_name));
+
+ OS::Time time = OS::get_singleton()->get_time();
+ OS::Date date = OS::get_singleton()->get_date();
+
+ zip_fileinfo zipfi;
+ zipfi.tmz_date.tm_hour = time.hour;
+ zipfi.tmz_date.tm_mday = date.day;
+ zipfi.tmz_date.tm_min = time.min;
+ zipfi.tmz_date.tm_mon = date.month;
+ zipfi.tmz_date.tm_sec = time.sec;
+ zipfi.tmz_date.tm_year = date.year;
+ zipfi.dosDate = 0;
+ zipfi.external_fa = (is_executable ? 0755 : 0644) << 16L;
+ zipfi.internal_fa = 0;
+
+ zipOpenNewFileInZip4(p_zip,
+ p_folder.plus_file(f).utf8().get_data(),
+ &zipfi,
+ nullptr,
+ 0,
+ nullptr,
+ 0,
+ nullptr,
+ Z_DEFLATED,
+ Z_DEFAULT_COMPRESSION,
+ 0,
+ -MAX_WBITS,
+ DEF_MEM_LEVEL,
+ Z_DEFAULT_STRATEGY,
+ nullptr,
+ 0,
+ 0x0314, // "version made by", 0x03 - Unix, 0x14 - ZIP specification version 2.0, required to store Unix file permissions
+ 0);
+
+ Vector<uint8_t> array = FileAccess::get_file_as_array(dir.plus_file(f));
+ zipWriteInFileInZip(p_zip, array.ptr(), array.size());
+ zipCloseFileInZip(p_zip);
+ }
+ }
+ da->list_dir_end();
+ memdelete(da);
+}
+
bool EditorExportPlatformOSX::can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const {
String err;
bool valid = false;
diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp
index 7e4d17f5e7..7bd67d3726 100644
--- a/platform/uwp/os_uwp.cpp
+++ b/platform/uwp/os_uwp.cpp
@@ -698,7 +698,7 @@ bool OS_UWP::has_virtual_keyboard() const {
return UIViewSettings::GetForCurrentView()->UserInteractionMode == UserInteractionMode::Touch;
}
-void OS_UWP::show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect, int p_max_input_length) {
+void OS_UWP::show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect, int p_max_input_length, int p_cursor_start, int p_cursor_end) {
InputPane ^ pane = InputPane::GetForCurrentView();
pane->TryShow();
}
diff --git a/platform/uwp/os_uwp.h b/platform/uwp/os_uwp.h
index 1cab38cabe..95359c68b0 100644
--- a/platform/uwp/os_uwp.h
+++ b/platform/uwp/os_uwp.h
@@ -234,7 +234,7 @@ public:
virtual bool has_touchscreen_ui_hint() const;
virtual bool has_virtual_keyboard() const;
- virtual void show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), int p_max_input_length = -1);
+ virtual void show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), int p_max_input_length = -1, int p_cursor_start = -1, int p_cursor_end = -1);
virtual void hide_virtual_keyboard();
virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false);
diff --git a/platform/uwp/thread_uwp.cpp b/platform/uwp/thread_uwp.cpp
index 35a366a173..8e7bb144be 100644
--- a/platform/uwp/thread_uwp.cpp
+++ b/platform/uwp/thread_uwp.cpp
@@ -59,11 +59,3 @@ void ThreadUWP::make_default() {
get_thread_id_func = get_thread_id_func_uwp;
wait_to_finish_func = wait_to_finish_func_uwp;
};
-
-ThreadUWP::ThreadUWP(){
-
-};
-
-ThreadUWP::~ThreadUWP(){
-
-};
diff --git a/platform/uwp/thread_uwp.h b/platform/uwp/thread_uwp.h
index 1f1d85a66a..9b2a2590a8 100644
--- a/platform/uwp/thread_uwp.h
+++ b/platform/uwp/thread_uwp.h
@@ -44,16 +44,16 @@ class ThreadUWP : public Thread {
static ID get_thread_id_func_uwp();
static void wait_to_finish_func_uwp(Thread *p_thread);
- ThreadUWP();
+ ThreadUWP() {}
public:
virtual ID get_id() const;
static void make_default();
- ~ThreadUWP();
+ ~ThreadUWP() {}
};
-#endif
+#endif // UWP_ENABLED
-#endif
+#endif // THREAD_UWP_H
diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp
index 114b64855e..9d8344fa7e 100644
--- a/platform/windows/display_server_windows.cpp
+++ b/platform/windows/display_server_windows.cpp
@@ -521,7 +521,7 @@ void DisplayServerWindows::delete_sub_window(WindowID p_window) {
}
#endif
- if (!OS::get_singleton()->is_wintab_disabled() && wintab_available && windows[p_window].wtctx) {
+ if ((OS::get_singleton()->get_current_tablet_driver() == "wintab") && wintab_available && windows[p_window].wtctx) {
wintab_WTClose(windows[p_window].wtctx);
windows[p_window].wtctx = 0;
}
@@ -1695,6 +1695,12 @@ void DisplayServerWindows::_dispatch_input_events(const Ref<InputEvent> &p_event
}
void DisplayServerWindows::_dispatch_input_event(const Ref<InputEvent> &p_event) {
+ _THREAD_SAFE_METHOD_
+ if (in_dispatch_input_event) {
+ return;
+ }
+
+ in_dispatch_input_event = true;
Variant ev = p_event;
Variant *evp = &ev;
Variant ret;
@@ -1706,6 +1712,7 @@ void DisplayServerWindows::_dispatch_input_event(const Ref<InputEvent> &p_event)
ERR_FAIL_COND(!windows.has(event_from_window->get_window_id()));
Callable callable = windows[event_from_window->get_window_id()].input_event_callback;
if (callable.is_null()) {
+ in_dispatch_input_event = false;
return;
}
callable.call((const Variant **)&evp, 1, ret, ce);
@@ -1719,6 +1726,8 @@ void DisplayServerWindows::_dispatch_input_event(const Ref<InputEvent> &p_event)
callable.call((const Variant **)&evp, 1, ret, ce);
}
}
+
+ in_dispatch_input_event = false;
}
LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
@@ -1782,7 +1791,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
alt_mem = false;
};
- if (!OS::get_singleton()->is_wintab_disabled() && wintab_available && windows[window_id].wtctx) {
+ if ((OS::get_singleton()->get_current_tablet_driver() == "wintab") && wintab_available && windows[window_id].wtctx) {
wintab_WTEnable(windows[window_id].wtctx, GET_WM_ACTIVATE_STATE(wParam, lParam));
}
@@ -1915,7 +1924,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
} break;
case WT_CSRCHANGE:
case WT_PROXIMITY: {
- if (!OS::get_singleton()->is_wintab_disabled() && wintab_available && windows[window_id].wtctx) {
+ if ((OS::get_singleton()->get_current_tablet_driver() == "wintab") && wintab_available && windows[window_id].wtctx) {
AXIS pressure;
if (wintab_WTInfo(WTI_DEVICES + windows[window_id].wtlc.lcDevice, DVC_NPRESSURE, &pressure)) {
windows[window_id].min_pressure = int(pressure.axMin);
@@ -1929,7 +1938,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
}
} break;
case WT_PACKET: {
- if (!OS::get_singleton()->is_wintab_disabled() && wintab_available && windows[window_id].wtctx) {
+ if ((OS::get_singleton()->get_current_tablet_driver() == "wintab") && wintab_available && windows[window_id].wtctx) {
PACKET packet;
if (wintab_WTPacket(windows[window_id].wtctx, wParam, &packet)) {
float pressure = float(packet.pkNormalPressure - windows[window_id].min_pressure) / float(windows[window_id].max_pressure - windows[window_id].min_pressure);
@@ -1998,17 +2007,43 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
old_x = mm->get_position().x;
old_y = mm->get_position().y;
if (windows[window_id].window_has_focus)
- Input::get_singleton()->parse_input_event(mm);
+ Input::get_singleton()->accumulate_input_event(mm);
}
return 0;
}
} break;
+ case WM_POINTERENTER: {
+ if (mouse_mode == MOUSE_MODE_CAPTURED && use_raw_input) {
+ break;
+ }
+
+ if ((OS::get_singleton()->get_current_tablet_driver() != "winink") || !winink_available) {
+ break;
+ }
+
+ uint32_t pointer_id = LOWORD(wParam);
+ POINTER_INPUT_TYPE pointer_type = PT_POINTER;
+ if (!win8p_GetPointerType(pointer_id, &pointer_type)) {
+ break;
+ }
+
+ if (pointer_type != PT_PEN) {
+ break;
+ }
+
+ windows[window_id].block_mm = true;
+ return 0;
+ } break;
+ case WM_POINTERLEAVE: {
+ windows[window_id].block_mm = false;
+ return 0;
+ } break;
case WM_POINTERUPDATE: {
if (mouse_mode == MOUSE_MODE_CAPTURED && use_raw_input) {
break;
}
- if (!win8p_GetPointerType || !win8p_GetPointerPenInfo) {
+ if ((OS::get_singleton()->get_current_tablet_driver() != "winink") || !winink_available) {
break;
}
@@ -2118,12 +2153,16 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
old_x = mm->get_position().x;
old_y = mm->get_position().y;
if (windows[window_id].window_has_focus) {
- Input::get_singleton()->parse_input_event(mm);
+ Input::get_singleton()->accumulate_input_event(mm);
}
return 0; //Pointer event handled return 0 to avoid duplicate WM_MOUSEMOVE event
} break;
case WM_MOUSEMOVE: {
+ if (windows[window_id].block_mm) {
+ break;
+ }
+
if (mouse_mode == MOUSE_MODE_CAPTURED && use_raw_input) {
break;
}
@@ -2168,7 +2207,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
mm->set_shift((wParam & MK_SHIFT) != 0);
mm->set_alt(alt_mem);
- if (!OS::get_singleton()->is_wintab_disabled() && wintab_available && windows[window_id].wtctx) {
+ if ((OS::get_singleton()->get_current_tablet_driver() == "wintab") && wintab_available && windows[window_id].wtctx) {
// Note: WinTab sends both WT_PACKET and WM_xBUTTONDOWN/UP/MOUSEMOVE events, use mouse 1/0 pressure only when last_pressure was not update recently.
if (windows[window_id].last_pressure_update < 10) {
windows[window_id].last_pressure_update++;
@@ -2649,7 +2688,8 @@ void DisplayServerWindows::_process_key_events() {
KeyEvent &ke = key_event_buffer[i];
switch (ke.uMsg) {
case WM_CHAR: {
- if ((i == 0 && ke.uMsg == WM_CHAR) || (i > 0 && key_event_buffer[i - 1].uMsg == WM_CHAR)) {
+ // extended keys should only be processed as WM_KEYDOWN message.
+ if (!KeyMappingWindows::is_extended_key(ke.wParam) && ((i == 0 && ke.uMsg == WM_CHAR) || (i > 0 && key_event_buffer[i - 1].uMsg == WM_CHAR))) {
Ref<InputEventKey> k;
k.instance();
@@ -2719,6 +2759,45 @@ void DisplayServerWindows::_process_key_events() {
key_event_pos = 0;
}
+void DisplayServerWindows::_update_tablet_ctx(const String &p_old_driver, const String &p_new_driver) {
+ for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) {
+ WindowData &wd = E->get();
+ wd.block_mm = false;
+ if ((p_old_driver == "wintab") && wintab_available && wd.wtctx) {
+ wintab_WTEnable(wd.wtctx, false);
+ wintab_WTClose(wd.wtctx);
+ wd.wtctx = 0;
+ }
+ if ((p_new_driver == "wintab") && wintab_available) {
+ wintab_WTInfo(WTI_DEFSYSCTX, 0, &wd.wtlc);
+ wd.wtlc.lcOptions |= CXO_MESSAGES;
+ wd.wtlc.lcPktData = PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE | PK_ORIENTATION;
+ wd.wtlc.lcMoveMask = PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE;
+ wd.wtlc.lcPktMode = 0;
+ wd.wtlc.lcOutOrgX = 0;
+ wd.wtlc.lcOutExtX = wd.wtlc.lcInExtX;
+ wd.wtlc.lcOutOrgY = 0;
+ wd.wtlc.lcOutExtY = -wd.wtlc.lcInExtY;
+ wd.wtctx = wintab_WTOpen(wd.hWnd, &wd.wtlc, false);
+ if (wd.wtctx) {
+ wintab_WTEnable(wd.wtctx, true);
+ AXIS pressure;
+ if (wintab_WTInfo(WTI_DEVICES + wd.wtlc.lcDevice, DVC_NPRESSURE, &pressure)) {
+ wd.min_pressure = int(pressure.axMin);
+ wd.max_pressure = int(pressure.axMax);
+ }
+ AXIS orientation[3];
+ if (wintab_WTInfo(WTI_DEVICES + wd.wtlc.lcDevice, DVC_ORIENTATION, &orientation)) {
+ wd.tilt_supported = orientation[0].axResolution && orientation[1].axResolution;
+ }
+ wintab_WTEnable(wd.wtctx, true);
+ } else {
+ print_verbose("WinTab context creation failed.");
+ }
+ }
+ }
+}
+
DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect) {
DWORD dwExStyle;
DWORD dwStyle;
@@ -2775,7 +2854,7 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
DragAcceptFiles(wd.hWnd, true);
- if (!OS::get_singleton()->is_wintab_disabled() && wintab_available) {
+ if ((OS::get_singleton()->get_current_tablet_driver() == "wintab") && wintab_available) {
wintab_WTInfo(WTI_DEFSYSCTX, 0, &wd.wtlc);
wd.wtlc.lcOptions |= CXO_MESSAGES;
wd.wtlc.lcPktData = PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE | PK_ORIENTATION;
@@ -2834,6 +2913,7 @@ WTPacketPtr DisplayServerWindows::wintab_WTPacket = nullptr;
WTEnablePtr DisplayServerWindows::wintab_WTEnable = nullptr;
// Windows Ink API
+bool DisplayServerWindows::winink_available = false;
GetPointerTypePtr DisplayServerWindows::win8p_GetPointerType = nullptr;
GetPointerPenInfoPtr DisplayServerWindows::win8p_GetPointerPenInfo = nullptr;
@@ -2844,25 +2924,6 @@ typedef enum _SHC_PROCESS_DPI_AWARENESS {
} SHC_PROCESS_DPI_AWARENESS;
DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
- //Note: Wacom WinTab driver API for pen input, for devices incompatible with Windows Ink.
- HMODULE wintab_lib = LoadLibraryW(L"wintab32.dll");
- if (wintab_lib) {
- wintab_WTOpen = (WTOpenPtr)GetProcAddress(wintab_lib, "WTOpenW");
- wintab_WTClose = (WTClosePtr)GetProcAddress(wintab_lib, "WTClose");
- wintab_WTInfo = (WTInfoPtr)GetProcAddress(wintab_lib, "WTInfoW");
- wintab_WTPacket = (WTPacketPtr)GetProcAddress(wintab_lib, "WTPacket");
- wintab_WTEnable = (WTEnablePtr)GetProcAddress(wintab_lib, "WTEnable");
-
- wintab_available = wintab_WTOpen && wintab_WTClose && wintab_WTInfo && wintab_WTPacket && wintab_WTEnable;
- }
-
- //Note: Windows Ink API for pen input, available on Windows 8+ only.
- HMODULE user32_lib = LoadLibraryW(L"user32.dll");
- if (user32_lib) {
- win8p_GetPointerType = (GetPointerTypePtr)GetProcAddress(user32_lib, "GetPointerType");
- win8p_GetPointerPenInfo = (GetPointerPenInfoPtr)GetProcAddress(user32_lib, "GetPointerPenInfo");
- }
-
drop_events = false;
key_event_pos = 0;
@@ -3044,18 +3105,6 @@ DisplayServerWindows::~DisplayServerWindows() {
cursors_cache.clear();
-#if defined(VULKAN_ENABLED)
- if (rendering_driver == "vulkan") {
- if (rendering_device_vulkan) {
- rendering_device_vulkan->finalize();
- memdelete(rendering_device_vulkan);
- }
-
- if (context_vulkan)
- memdelete(context_vulkan);
- }
-#endif
-
if (user_proc) {
SetWindowLongPtr(windows[MAIN_WINDOW_ID].hWnd, GWLP_WNDPROC, (LONG_PTR)user_proc);
};
@@ -3072,4 +3121,16 @@ DisplayServerWindows::~DisplayServerWindows() {
}
DestroyWindow(windows[MAIN_WINDOW_ID].hWnd);
}
+
+#if defined(VULKAN_ENABLED)
+ if (rendering_driver == "vulkan") {
+ if (rendering_device_vulkan) {
+ rendering_device_vulkan->finalize();
+ memdelete(rendering_device_vulkan);
+ }
+
+ if (context_vulkan)
+ memdelete(context_vulkan);
+ }
+#endif
}
diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h
index ea08b1899f..caf8598dc2 100644
--- a/platform/windows/display_server_windows.h
+++ b/platform/windows/display_server_windows.h
@@ -229,6 +229,14 @@ typedef struct tagPOINTER_PEN_INFO {
#define WM_POINTERUPDATE 0x0245
#endif
+#ifndef WM_POINTERENTER
+#define WM_POINTERENTER 0x0249
+#endif
+
+#ifndef WM_POINTERLEAVE
+#define WM_POINTERLEAVE 0x024A
+#endif
+
typedef BOOL(WINAPI *GetPointerTypePtr)(uint32_t p_id, POINTER_INPUT_TYPE *p_type);
typedef BOOL(WINAPI *GetPointerPenInfoPtr)(uint32_t p_id, POINTER_PEN_INFO *p_pen_info);
@@ -256,6 +264,7 @@ class DisplayServerWindows : public DisplayServer {
_THREAD_SAFE_CLASS_
+public:
// WinTab API
static bool wintab_available;
static WTOpenPtr wintab_WTOpen;
@@ -265,9 +274,13 @@ class DisplayServerWindows : public DisplayServer {
static WTEnablePtr wintab_WTEnable;
// Windows Ink API
+ static bool winink_available;
static GetPointerTypePtr win8p_GetPointerType;
static GetPointerPenInfoPtr win8p_GetPointerPenInfo;
+ void _update_tablet_ctx(const String &p_old_driver, const String &p_new_driver);
+
+private:
void GetMaskBitmaps(HBITMAP hSourceBitmap, COLORREF clrTransparent, OUT HBITMAP &hAndMaskBitmap, OUT HBITMAP &hXorMaskBitmap);
enum {
@@ -328,6 +341,7 @@ class DisplayServerWindows : public DisplayServer {
int min_pressure;
int max_pressure;
bool tilt_supported;
+ bool block_mm = false;
int last_pressure_update;
float last_pressure;
@@ -388,6 +402,7 @@ class DisplayServerWindows : public DisplayServer {
uint32_t last_button_state = 0;
bool use_raw_input = false;
bool drop_events = false;
+ bool in_dispatch_input_event = false;
bool console_visible = false;
WNDCLASSEXW wc;
diff --git a/platform/windows/key_mapping_windows.cpp b/platform/windows/key_mapping_windows.cpp
index 1fe7551445..d8d0b13068 100644
--- a/platform/windows/key_mapping_windows.cpp
+++ b/platform/windows/key_mapping_windows.cpp
@@ -411,3 +411,16 @@ unsigned int KeyMappingWindows::get_scansym(unsigned int p_code, bool p_extended
return keycode;
}
+
+bool KeyMappingWindows::is_extended_key(unsigned int p_code) {
+ return p_code == VK_INSERT ||
+ p_code == VK_DELETE ||
+ p_code == VK_HOME ||
+ p_code == VK_END ||
+ p_code == VK_PRIOR ||
+ p_code == VK_NEXT ||
+ p_code == VK_LEFT ||
+ p_code == VK_UP ||
+ p_code == VK_RIGHT ||
+ p_code == VK_DOWN;
+}
diff --git a/platform/windows/key_mapping_windows.h b/platform/windows/key_mapping_windows.h
index 4d0c12c16e..f64f1feb9f 100644
--- a/platform/windows/key_mapping_windows.h
+++ b/platform/windows/key_mapping_windows.h
@@ -43,6 +43,7 @@ class KeyMappingWindows {
public:
static unsigned int get_keysym(unsigned int p_code);
static unsigned int get_scansym(unsigned int p_code, bool p_extended);
+ static bool is_extended_key(unsigned int p_code);
};
#endif // KEY_MAPPING_WINDOWS_H
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index 7c06e93a8a..f11888b26c 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -415,23 +415,30 @@ uint64_t OS_Windows::get_ticks_usec() const {
return time;
}
+String OS_Windows::_quote_command_line_argument(const String &p_text) const {
+ for (int i = 0; i < p_text.size(); i++) {
+ CharType c = p_text[i];
+ if (c == ' ' || c == '&' || c == '(' || c == ')' || c == '[' || c == ']' || c == '{' || c == '}' || c == '^' || c == '=' || c == ';' || c == '!' || c == '\'' || c == '+' || c == ',' || c == '`' || c == '~') {
+ return "\"" + p_text + "\"";
+ }
+ }
+ return p_text;
+}
+
Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr, Mutex *p_pipe_mutex) {
if (p_blocking && r_pipe) {
- String argss;
- argss = "\"\"" + p_path + "\"";
-
+ String argss = _quote_command_line_argument(p_path);
for (const List<String>::Element *E = p_arguments.front(); E; E = E->next()) {
- argss += " \"" + E->get() + "\"";
+ argss += " " + _quote_command_line_argument(E->get());
}
- argss += "\"";
-
if (read_stderr) {
argss += " 2>&1"; // Read stderr too
}
+ // Note: _wpopen is calling command as "cmd.exe /c argss", instead of executing it directly, add extra quotes around full command, to prevent it from stripping quotes in the command.
+ argss = _quote_command_line_argument(argss);
FILE *f = _wpopen(argss.c_str(), L"r");
-
ERR_FAIL_COND_V(!f, ERR_CANT_OPEN);
char buf[65535];
@@ -446,19 +453,19 @@ Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments,
}
int rv = _pclose(f);
- if (r_exitcode)
+ if (r_exitcode) {
*r_exitcode = rv;
+ }
return OK;
}
- String cmdline = "\"" + p_path + "\"";
+ String cmdline = _quote_command_line_argument(p_path);
const List<String>::Element *I = p_arguments.front();
while (I) {
- cmdline += " \"" + I->get() + "\"";
-
+ cmdline += " " + _quote_command_line_argument(I->get());
I = I->next();
- };
+ }
ProcessInfo pi;
ZeroMemory(&pi.si, sizeof(pi.si));
@@ -466,17 +473,20 @@ Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments,
ZeroMemory(&pi.pi, sizeof(pi.pi));
LPSTARTUPINFOW si_w = (LPSTARTUPINFOW)&pi.si;
- Vector<CharType> modstr; //windows wants to change this no idea why
+ Vector<CharType> modstr; // Windows wants to change this no idea why.
modstr.resize(cmdline.size());
- for (int i = 0; i < cmdline.size(); i++)
+ for (int i = 0; i < cmdline.size(); i++) {
modstr.write[i] = cmdline[i];
+ }
+
int ret = CreateProcessW(nullptr, modstr.ptrw(), nullptr, nullptr, 0, NORMAL_PRIORITY_CLASS & CREATE_NO_WINDOW, nullptr, nullptr, si_w, &pi.pi);
ERR_FAIL_COND_V(ret == 0, ERR_CANT_FORK);
if (p_blocking) {
DWORD ret2 = WaitForSingleObject(pi.pi.hProcess, INFINITE);
- if (r_exitcode)
+ if (r_exitcode) {
*r_exitcode = ret2;
+ }
CloseHandle(pi.pi.hProcess);
CloseHandle(pi.pi.hThread);
@@ -484,9 +494,9 @@ Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments,
ProcessID pid = pi.pi.dwProcessId;
if (r_child_id) {
*r_child_id = pid;
- };
+ }
process_map->insert(pid, pi);
- };
+ }
return OK;
};
@@ -768,7 +778,69 @@ Error OS_Windows::move_to_trash(const String &p_path) {
return OK;
}
+int OS_Windows::get_tablet_driver_count() const {
+ return tablet_drivers.size();
+}
+
+String OS_Windows::get_tablet_driver_name(int p_driver) const {
+ if (p_driver < 0 || p_driver >= tablet_drivers.size()) {
+ return "";
+ } else {
+ return tablet_drivers[p_driver];
+ }
+}
+
+String OS_Windows::get_current_tablet_driver() const {
+ return tablet_driver;
+}
+
+void OS_Windows::set_current_tablet_driver(const String &p_driver) {
+ bool found = false;
+ for (int i = 0; i < get_tablet_driver_count(); i++) {
+ if (p_driver == get_tablet_driver_name(i)) {
+ found = true;
+ }
+ }
+ if (found) {
+ if (DisplayServerWindows::get_singleton()) {
+ ((DisplayServerWindows *)DisplayServerWindows::get_singleton())->_update_tablet_ctx(tablet_driver, p_driver);
+ }
+ tablet_driver = p_driver;
+ } else {
+ ERR_PRINT("Unknown tablet driver " + p_driver + ".");
+ }
+}
+
OS_Windows::OS_Windows(HINSTANCE _hInstance) {
+ //Note: Wacom WinTab driver API for pen input, for devices incompatible with Windows Ink.
+ HMODULE wintab_lib = LoadLibraryW(L"wintab32.dll");
+ if (wintab_lib) {
+ DisplayServerWindows::wintab_WTOpen = (WTOpenPtr)GetProcAddress(wintab_lib, "WTOpenW");
+ DisplayServerWindows::wintab_WTClose = (WTClosePtr)GetProcAddress(wintab_lib, "WTClose");
+ DisplayServerWindows::wintab_WTInfo = (WTInfoPtr)GetProcAddress(wintab_lib, "WTInfoW");
+ DisplayServerWindows::wintab_WTPacket = (WTPacketPtr)GetProcAddress(wintab_lib, "WTPacket");
+ DisplayServerWindows::wintab_WTEnable = (WTEnablePtr)GetProcAddress(wintab_lib, "WTEnable");
+
+ DisplayServerWindows::wintab_available = DisplayServerWindows::wintab_WTOpen && DisplayServerWindows::wintab_WTClose && DisplayServerWindows::wintab_WTInfo && DisplayServerWindows::wintab_WTPacket && DisplayServerWindows::wintab_WTEnable;
+ }
+
+ if (DisplayServerWindows::wintab_available) {
+ tablet_drivers.push_back("wintab");
+ }
+
+ //Note: Windows Ink API for pen input, available on Windows 8+ only.
+ HMODULE user32_lib = LoadLibraryW(L"user32.dll");
+ if (user32_lib) {
+ DisplayServerWindows::win8p_GetPointerType = (GetPointerTypePtr)GetProcAddress(user32_lib, "GetPointerType");
+ DisplayServerWindows::win8p_GetPointerPenInfo = (GetPointerPenInfoPtr)GetProcAddress(user32_lib, "GetPointerPenInfo");
+
+ DisplayServerWindows::winink_available = DisplayServerWindows::win8p_GetPointerType && DisplayServerWindows::win8p_GetPointerPenInfo;
+ }
+
+ if (DisplayServerWindows::winink_available) {
+ tablet_drivers.push_back("winink");
+ }
+
force_quit = false;
hInstance = _hInstance;
diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h
index 480a9faa87..11e3533bfd 100644
--- a/platform/windows/os_windows.h
+++ b/platform/windows/os_windows.h
@@ -73,6 +73,9 @@ class OS_Windows : public OS {
HINSTANCE hInstance;
MainLoop *main_loop;
+ String tablet_driver;
+ Vector<String> tablet_drivers;
+
#ifdef WASAPI_ENABLED
AudioDriverWASAPI driver_wasapi;
#endif
@@ -99,6 +102,8 @@ protected:
virtual void finalize_core();
virtual String get_stdin_string(bool p_block);
+ String _quote_command_line_argument(const String &p_text) const;
+
struct ProcessInfo {
STARTUPINFO si;
PROCESS_INFORMATION pi;
@@ -114,6 +119,11 @@ public:
virtual String get_name() const;
+ virtual int get_tablet_driver_count() const;
+ virtual String get_tablet_driver_name(int p_driver) const;
+ virtual String get_current_tablet_driver() const;
+ virtual void set_current_tablet_driver(const String &p_driver);
+
virtual void initialize_joypads() {}
virtual Date get_date(bool utc) const;
diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp
index 385b4e81a8..de8f1eea2e 100644
--- a/scene/3d/physics_body_3d.cpp
+++ b/scene/3d/physics_body_3d.cpp
@@ -1135,6 +1135,11 @@ bool KinematicBody3D::separate_raycast_shapes(bool p_infinite_inertia, Collision
}
void KinematicBody3D::set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool p_lock) {
+ if (p_lock) {
+ locked_axis |= p_axis;
+ } else {
+ locked_axis &= (~p_axis);
+ }
PhysicsServer3D::get_singleton()->body_set_axis_lock(get_rid(), p_axis, p_lock);
}
@@ -1211,9 +1216,10 @@ void KinematicBody3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_slide_count"), &KinematicBody3D::get_slide_count);
ClassDB::bind_method(D_METHOD("get_slide_collision", "slide_idx"), &KinematicBody3D::_get_slide_collision);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "move_lock_x", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_LINEAR_X);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "move_lock_y", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_LINEAR_Y);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "move_lock_z", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_LINEAR_Z);
+ ADD_GROUP("Axis Lock", "axis_lock_");
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_motion_x"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_LINEAR_X);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_motion_y"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_LINEAR_Y);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_motion_z"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_LINEAR_Z);
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision/safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001"), "set_safe_margin", "get_safe_margin");
}
diff --git a/scene/3d/proximity_group_3d.cpp b/scene/3d/proximity_group_3d.cpp
index cdc88abf4c..1a0677c603 100644
--- a/scene/3d/proximity_group_3d.cpp
+++ b/scene/3d/proximity_group_3d.cpp
@@ -179,14 +179,5 @@ void ProximityGroup3D::_bind_methods() {
};
ProximityGroup3D::ProximityGroup3D() {
- group_version = 0;
- dispatch_mode = MODE_PROXY;
-
- cell_size = 1.0;
- grid_radius = Vector3(1, 1, 1);
set_notify_transform(true);
};
-
-ProximityGroup3D::~ProximityGroup3D(){
-
-};
diff --git a/scene/3d/proximity_group_3d.h b/scene/3d/proximity_group_3d.h
index 780c65e92b..dd3a2f0a87 100644
--- a/scene/3d/proximity_group_3d.h
+++ b/scene/3d/proximity_group_3d.h
@@ -49,14 +49,14 @@ public:
void _notification(int p_what);
- DispatchMode dispatch_mode;
+ DispatchMode dispatch_mode = MODE_PROXY;
Map<StringName, uint32_t> groups;
String group_name;
- float cell_size;
- Vector3 grid_radius;
- uint32_t group_version;
+ float cell_size = 1.0;
+ Vector3 grid_radius = Vector3(1, 1, 1);
+ uint32_t group_version = 0;
void add_groups(int *p_cell, String p_base, int p_depth);
void _new_group(StringName p_name);
@@ -78,7 +78,7 @@ public:
void broadcast(String p_name, Variant p_params);
ProximityGroup3D();
- ~ProximityGroup3D();
+ ~ProximityGroup3D() {}
};
VARIANT_ENUM_CAST(ProximityGroup3D::DispatchMode);
diff --git a/scene/3d/xr_nodes.cpp b/scene/3d/xr_nodes.cpp
index f9f6b6905c..f4a514cdd6 100644
--- a/scene/3d/xr_nodes.cpp
+++ b/scene/3d/xr_nodes.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "xr_nodes.h"
+
#include "core/input/input.h"
#include "servers/xr/xr_interface.h"
#include "servers/xr_server.h"
@@ -168,14 +169,6 @@ Vector<Plane> XRCamera3D::get_frustum() const {
return cm.get_projection_planes(get_camera_transform());
};
-XRCamera3D::XRCamera3D(){
- // nothing to do here yet for now..
-};
-
-XRCamera3D::~XRCamera3D(){
- // nothing to do here yet for now..
-};
-
////////////////////////////////////////////////////////////////////////////////////////////////////
void XRController3D::_notification(int p_what) {
@@ -382,16 +375,6 @@ String XRController3D::get_configuration_warning() const {
return String();
};
-XRController3D::XRController3D() {
- controller_id = 1;
- is_active = true;
- button_states = 0;
-};
-
-XRController3D::~XRController3D(){
- // nothing to do here yet for now..
-};
-
////////////////////////////////////////////////////////////////////////////////////////////////////
void XRAnchor3D::_notification(int p_what) {
@@ -522,15 +505,6 @@ Ref<Mesh> XRAnchor3D::get_mesh() const {
return mesh;
}
-XRAnchor3D::XRAnchor3D() {
- anchor_id = 1;
- is_active = true;
-};
-
-XRAnchor3D::~XRAnchor3D(){
- // nothing to do here yet for now..
-};
-
////////////////////////////////////////////////////////////////////////////////////////////////////
String XROrigin3D::get_configuration_warning() const {
@@ -615,11 +589,3 @@ void XROrigin3D::_notification(int p_what) {
}
}
};
-
-XROrigin3D::XROrigin3D() {
- tracked_camera = nullptr;
-};
-
-XROrigin3D::~XROrigin3D(){
- // nothing to do here yet for now..
-};
diff --git a/scene/3d/xr_nodes.h b/scene/3d/xr_nodes.h
index 4685328f16..4d4f82aa38 100644
--- a/scene/3d/xr_nodes.h
+++ b/scene/3d/xr_nodes.h
@@ -57,8 +57,8 @@ public:
virtual Vector3 project_position(const Point2 &p_point, float p_z_depth) const;
virtual Vector<Plane> get_frustum() const;
- XRCamera3D();
- ~XRCamera3D();
+ XRCamera3D() {}
+ ~XRCamera3D() {}
};
/*
@@ -71,9 +71,9 @@ class XRController3D : public Node3D {
GDCLASS(XRController3D, Node3D);
private:
- int controller_id;
- bool is_active;
- int button_states;
+ int controller_id = 1;
+ bool is_active = true;
+ int button_states = 0;
Ref<Mesh> mesh;
protected:
@@ -99,8 +99,8 @@ public:
String get_configuration_warning() const;
- XRController3D();
- ~XRController3D();
+ XRController3D() {}
+ ~XRController3D() {}
};
/*
@@ -112,8 +112,8 @@ class XRAnchor3D : public Node3D {
GDCLASS(XRAnchor3D, Node3D);
private:
- int anchor_id;
- bool is_active;
+ int anchor_id = 1;
+ bool is_active = true;
Vector3 size;
Ref<Mesh> mesh;
@@ -135,8 +135,8 @@ public:
String get_configuration_warning() const;
- XRAnchor3D();
- ~XRAnchor3D();
+ XRAnchor3D() {}
+ ~XRAnchor3D() {}
};
/*
@@ -151,7 +151,7 @@ class XROrigin3D : public Node3D {
GDCLASS(XROrigin3D, Node3D);
private:
- XRCamera3D *tracked_camera;
+ XRCamera3D *tracked_camera = nullptr;
protected:
void _notification(int p_what);
@@ -166,8 +166,8 @@ public:
float get_world_scale() const;
void set_world_scale(float p_world_scale);
- XROrigin3D();
- ~XROrigin3D();
+ XROrigin3D() {}
+ ~XROrigin3D() {}
};
#endif /* XR_NODES_H */
diff --git a/scene/debugger/scene_debugger.cpp b/scene/debugger/scene_debugger.cpp
index 0222585948..f57c8e58db 100644
--- a/scene/debugger/scene_debugger.cpp
+++ b/scene/debugger/scene_debugger.cpp
@@ -361,15 +361,6 @@ void SceneDebuggerObject::serialize(Array &r_arr, int p_max_size) {
RES res = var;
- if (var.get_type() == Variant::OBJECT && var.is_ref()) {
- REF r = var;
- if (r.is_valid()) {
- res = *r;
- } else {
- res = RES();
- }
- }
-
Array prop;
prop.push_back(pi.name);
prop.push_back(pi.type);
diff --git a/scene/gui/container.cpp b/scene/gui/container.cpp
index 18a84ce348..a89eef6209 100644
--- a/scene/gui/container.cpp
+++ b/scene/gui/container.cpp
@@ -140,7 +140,7 @@ void Container::queue_sort() {
return;
}
- MessageQueue::get_singleton()->push_call(this, "_sort_children");
+ MessageQueue::get_singleton()->push_callable(callable_mp(this, &Container::_sort_children));
pending_sort = true;
}
@@ -177,8 +177,6 @@ String Container::get_configuration_warning() const {
}
void Container::_bind_methods() {
- ClassDB::bind_method(D_METHOD("_sort_children"), &Container::_sort_children);
-
ClassDB::bind_method(D_METHOD("queue_sort"), &Container::queue_sort);
ClassDB::bind_method(D_METHOD("fit_child_in_rect", "child", "rect"), &Container::fit_child_in_rect);
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index 5489638125..5080ba74e2 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -768,9 +768,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
if (mm.is_valid() && dragging) {
just_selected = true;
- // TODO: Remove local mouse pos hack if/when InputEventMouseMotion is fixed to support floats
- //drag_accum+=Vector2(mm->get_relative().x,mm->get_relative().y);
- drag_accum = get_local_mouse_position() - drag_origin;
+ drag_accum += mm->get_relative();
for (int i = get_child_count() - 1; i >= 0; i--) {
GraphNode *gn = Object::cast_to<GraphNode>(get_child(i));
if (gn && gn->is_selected()) {
@@ -789,7 +787,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
}
if (mm.is_valid() && box_selecting) {
- box_selecting_to = get_local_mouse_position();
+ box_selecting_to = mm->get_position();
box_selecting_rect = Rect2(MIN(box_selecting_from.x, box_selecting_to.x),
MIN(box_selecting_from.y, box_selecting_to.y),
@@ -849,7 +847,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
if (gn) {
Rect2 r = gn->get_rect();
r.size *= zoom;
- if (r.has_point(get_local_mouse_position())) {
+ if (r.has_point(b->get_position())) {
gn->set_selected(false);
}
}
@@ -887,7 +885,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
continue;
}
- if (gn_selected->has_point(gn_selected->get_local_mouse_position())) {
+ if (gn_selected->has_point(b->get_position() - gn_selected->get_position())) {
gn = gn_selected;
break;
}
@@ -901,7 +899,6 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
dragging = true;
drag_accum = Vector2();
- drag_origin = get_local_mouse_position();
just_selected = !gn->is_selected();
if (!gn->is_selected() && !Input::get_singleton()->is_key_pressed(KEY_CONTROL)) {
for (int i = 0; i < get_child_count(); i++) {
@@ -939,7 +936,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
}
box_selecting = true;
- box_selecting_from = get_local_mouse_position();
+ box_selecting_from = b->get_position();
if (b->get_control()) {
box_selection_mode_additive = true;
previus_selected.clear();
diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h
index 8cfc5d32b9..c632490855 100644
--- a/scene/gui/graph_edit.h
+++ b/scene/gui/graph_edit.h
@@ -97,7 +97,6 @@ private:
bool dragging;
bool just_selected;
Vector2 drag_accum;
- Point2 drag_origin; // Workaround for GH-5907
float zoom;
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index e3c75491f7..fbacb3ed9e 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -119,7 +119,11 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
selection.doubleclick = false;
if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_VIRTUAL_KEYBOARD)) {
- DisplayServer::get_singleton()->virtual_keyboard_show(text, get_global_rect(), max_length);
+ if (selection.enabled) {
+ DisplayServer::get_singleton()->virtual_keyboard_show(text, get_global_rect(), max_length, selection.begin, selection.end);
+ } else {
+ DisplayServer::get_singleton()->virtual_keyboard_show(text, get_global_rect(), max_length, cursor_pos);
+ }
}
}
@@ -918,7 +922,11 @@ void LineEdit::_notification(int p_what) {
}
if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_VIRTUAL_KEYBOARD)) {
- DisplayServer::get_singleton()->virtual_keyboard_show(text, get_global_rect(), max_length);
+ if (selection.enabled) {
+ DisplayServer::get_singleton()->virtual_keyboard_show(text, get_global_rect(), max_length, selection.begin, selection.end);
+ } else {
+ DisplayServer::get_singleton()->virtual_keyboard_show(text, get_global_rect(), max_length, cursor_pos);
+ }
}
} break;
diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp
index e7de0f0912..5780cc5e71 100644
--- a/scene/gui/option_button.cpp
+++ b/scene/gui/option_button.cpp
@@ -334,9 +334,6 @@ OptionButton::OptionButton() {
popup = memnew(PopupMenu);
popup->hide();
add_child(popup);
- // popup->set_pass_on_modal_close_click(false);
- // popup->set_notify_transform(true);
- popup->set_allow_search(true);
popup->connect("index_pressed", callable_mp(this, &OptionButton::_selected));
popup->connect("id_focused", callable_mp(this, &OptionButton::_focused));
popup->connect("popup_hide", callable_mp((BaseButton *)this, &BaseButton::set_pressed), varray(false));
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index b439d85983..6e19b820e0 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -1442,7 +1442,7 @@ PopupMenu::PopupMenu() {
during_grabbed_click = false;
invalidated_click = false;
- allow_search = false;
+ allow_search = true;
search_time_msec = 0;
search_string = "";
diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp
index 97b8362214..8c4d9a5ece 100644
--- a/scene/gui/tab_container.cpp
+++ b/scene/gui/tab_container.cpp
@@ -278,7 +278,7 @@ void TabContainer::_notification(int p_what) {
Color font_color_bg = get_theme_color("font_color_bg");
Color font_color_disabled = get_theme_color("font_color_disabled");
int side_margin = get_theme_constant("side_margin");
- int icon_text_distance = get_theme_constant("hseparation");
+ int icon_text_distance = get_theme_constant("icon_separation");
// Find out start and width of the header area.
int header_x = side_margin;
@@ -465,7 +465,7 @@ int TabContainer::_get_tab_width(int p_index) const {
if (icon.is_valid()) {
width += icon->get_width();
if (text != "") {
- width += get_theme_constant("hseparation");
+ width += get_theme_constant("icon_separation");
}
}
}
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 52aee8f089..e050b3f174 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -1121,9 +1121,7 @@ void TextEdit::_notification(int p_what) {
int ofs_y = (i * get_row_height() + cache.line_spacing / 2) + ofs_readonly;
ofs_y -= cursor.wrap_ofs * get_row_height();
- if (smooth_scroll_enabled) {
- ofs_y += (-get_v_scroll_offset()) * get_row_height();
- }
+ ofs_y -= get_v_scroll_offset() * get_row_height();
// Check if line contains highlighted word.
int highlighted_text_col = -1;
@@ -5449,17 +5447,16 @@ int TextEdit::_get_column_pos_of_word(const String &p_key, const String &p_searc
return col;
}
-Vector<int> TextEdit::_search_bind(const String &p_key, uint32_t p_search_flags, int p_from_line, int p_from_column) const {
+Dictionary TextEdit::_search_bind(const String &p_key, uint32_t p_search_flags, int p_from_line, int p_from_column) const {
int col, line;
if (search(p_key, p_search_flags, p_from_line, p_from_column, line, col)) {
- Vector<int> result;
- result.resize(2);
- result.set(SEARCH_RESULT_COLUMN, col);
- result.set(SEARCH_RESULT_LINE, line);
+ Dictionary result;
+ result["line"] = line;
+ result["column"] = col;
return result;
} else {
- return Vector<int>();
+ return Dictionary();
}
}
@@ -6982,9 +6979,6 @@ void TextEdit::_bind_methods() {
BIND_ENUM_CONSTANT(SEARCH_WHOLE_WORDS);
BIND_ENUM_CONSTANT(SEARCH_BACKWARDS);
- BIND_ENUM_CONSTANT(SEARCH_RESULT_COLUMN);
- BIND_ENUM_CONSTANT(SEARCH_RESULT_LINE);
-
/*
ClassDB::bind_method(D_METHOD("delete_char"),&TextEdit::delete_char);
ClassDB::bind_method(D_METHOD("delete_line"),&TextEdit::delete_line);
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index 689199b6c2..ab78f77d94 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -508,7 +508,7 @@ private:
int _get_column_pos_of_word(const String &p_key, const String &p_search, uint32_t p_search_flags, int p_from_column);
- Vector<int> _search_bind(const String &p_key, uint32_t p_search_flags, int p_from_line, int p_from_column) const;
+ Dictionary _search_bind(const String &p_key, uint32_t p_search_flags, int p_from_line, int p_from_column) const;
PopupMenu *menu;
@@ -561,11 +561,6 @@ public:
SEARCH_BACKWARDS = 4
};
- enum SearchResult {
- SEARCH_RESULT_COLUMN,
- SEARCH_RESULT_LINE,
- };
-
virtual CursorShape get_cursor_shape(const Point2 &p_pos = Point2i()) const;
void _get_mouse_pos(const Point2i &p_mouse, int &r_row, int &r_col) const;
@@ -826,7 +821,6 @@ public:
VARIANT_ENUM_CAST(TextEdit::MenuItems);
VARIANT_ENUM_CAST(TextEdit::SearchFlags);
-VARIANT_ENUM_CAST(TextEdit::SearchResult);
class SyntaxHighlighter {
protected:
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index ad4d3c54be..c9d430c656 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -1234,17 +1234,13 @@ void Node::add_child(Node *p_child, bool p_legible_unique_name) {
_add_child_nocheck(p_child, p_child->data.name);
}
-void Node::add_child_below_node(Node *p_node, Node *p_child, bool p_legible_unique_name) {
- ERR_FAIL_NULL(p_node);
- ERR_FAIL_NULL(p_child);
-
- add_child(p_child, p_legible_unique_name);
+void Node::add_sibling(Node *p_sibling, bool p_legible_unique_name) {
+ ERR_FAIL_NULL(p_sibling);
+ ERR_FAIL_COND_MSG(p_sibling == this, "Can't add sibling '" + p_sibling->get_name() + "' to itself."); // adding to itself!
+ ERR_FAIL_COND_MSG(data.blocked > 0, "Parent node is busy setting up children, add_sibling() failed. Consider using call_deferred(\"add_sibling\", sibling) instead.");
- if (is_a_parent_of(p_node)) {
- move_child(p_child, p_node->get_index() + 1);
- } else {
- WARN_PRINT("Cannot move under node " + p_node->get_name() + " as " + p_child->get_name() + " does not share a parent.");
- }
+ get_parent()->add_child(p_sibling, p_legible_unique_name);
+ get_parent()->move_child(p_sibling, this->get_index() + 1);
}
void Node::_propagate_validate_owner() {
@@ -2710,7 +2706,7 @@ void Node::_bind_methods() {
GLOBAL_DEF("node/name_casing", NAME_CASING_PASCAL_CASE);
ProjectSettings::get_singleton()->set_custom_property_info("node/name_casing", PropertyInfo(Variant::INT, "node/name_casing", PROPERTY_HINT_ENUM, "PascalCase,camelCase,snake_case"));
- ClassDB::bind_method(D_METHOD("add_child_below_node", "preceding_node", "node", "legible_unique_name"), &Node::add_child_below_node, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("add_sibling", "sibling", "legible_unique_name"), &Node::add_sibling, DEFVAL(false));
ClassDB::bind_method(D_METHOD("set_name", "name"), &Node::set_name);
ClassDB::bind_method(D_METHOD("get_name"), &Node::get_name);
diff --git a/scene/main/node.h b/scene/main/node.h
index d1665d1236..7595aabd9a 100644
--- a/scene/main/node.h
+++ b/scene/main/node.h
@@ -266,7 +266,7 @@ public:
void set_name(const String &p_name);
void add_child(Node *p_child, bool p_legible_unique_name = false);
- void add_child_below_node(Node *p_node, Node *p_child, bool p_legible_unique_name = false);
+ void add_sibling(Node *p_sibling, bool p_legible_unique_name = false);
void remove_child(Node *p_child);
int get_child_count() const;
diff --git a/scene/main/window.cpp b/scene/main/window.cpp
index 6565f02503..a9be8a1eff 100644
--- a/scene/main/window.cpp
+++ b/scene/main/window.cpp
@@ -992,7 +992,7 @@ void Window::popup_centered_ratio(float p_ratio) {
ERR_FAIL_COND(!is_inside_tree());
ERR_FAIL_COND_MSG(window_id == DisplayServer::MAIN_WINDOW_ID, "Can't popup the main window.");
- Rect2i parent_rect;
+ Rect2 parent_rect;
if (is_embedded()) {
parent_rect = get_parent_viewport()->get_visible_rect();
@@ -1024,6 +1024,15 @@ void Window::popup(const Rect2i &p_screen_rect) {
set_size(adjust.size);
}
+ int scr = DisplayServer::get_singleton()->get_screen_count();
+ for (int i = 0; i < scr; i++) {
+ Rect2i r = DisplayServer::get_singleton()->screen_get_usable_rect(i);
+ if (r.has_point(position)) {
+ current_screen = i;
+ break;
+ }
+ }
+
set_transient(true);
set_visible(true);
_post_popup();
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index 67617a946f..de39fac627 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -52,20 +52,9 @@ static Ref<StyleBoxTexture> make_stylebox(T p_src, float p_left, float p_top, fl
} else {
texture = Ref<ImageTexture>(memnew(ImageTexture));
Ref<Image> img = memnew(Image(p_src));
-
- if (scale > 1) {
- Size2 orig_size = Size2(img->get_width(), img->get_height());
-
- img->convert(Image::FORMAT_RGBA8);
- img->expand_x2_hq2x();
- if (scale != 2.0) {
- img->resize(orig_size.x * scale, orig_size.y * scale);
- }
- } else if (scale < 1) {
- Size2 orig_size = Size2(img->get_width(), img->get_height());
- img->convert(Image::FORMAT_RGBA8);
- img->resize(orig_size.x * scale, orig_size.y * scale);
- }
+ const Size2 orig_size = Size2(img->get_width(), img->get_height());
+ img->convert(Image::FORMAT_RGBA8);
+ img->resize(orig_size.x * scale, orig_size.y * scale);
texture->create_from_image(img);
(*tex_cache)[p_src] = texture;
@@ -98,19 +87,9 @@ template <class T>
static Ref<Texture2D> make_icon(T p_src) {
Ref<ImageTexture> texture(memnew(ImageTexture));
Ref<Image> img = memnew(Image(p_src));
- if (scale > 1) {
- Size2 orig_size = Size2(img->get_width(), img->get_height());
-
- img->convert(Image::FORMAT_RGBA8);
- img->expand_x2_hq2x();
- if (scale != 2.0) {
- img->resize(orig_size.x * scale, orig_size.y * scale);
- }
- } else if (scale < 1) {
- Size2 orig_size = Size2(img->get_width(), img->get_height());
- img->convert(Image::FORMAT_RGBA8);
- img->resize(orig_size.x * scale, orig_size.y * scale);
- }
+ const Size2 orig_size = Size2(img->get_width(), img->get_height());
+ img->convert(Image::FORMAT_RGBA8);
+ img->resize(orig_size.x * scale, orig_size.y * scale);
texture->create_from_image(img);
return texture;
@@ -702,7 +681,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_color("font_color_disabled", "TabContainer", control_font_color_disabled);
theme->set_constant("side_margin", "TabContainer", 8 * scale);
- theme->set_constant("hseparation", "TabContainer", 4 * scale);
+ theme->set_constant("icon_separation", "TabContainer", 4 * scale);
// Tabs
diff --git a/scene/resources/sky_material.cpp b/scene/resources/sky_material.cpp
index 92c5151d7a..69e8e0b5bd 100644
--- a/scene/resources/sky_material.cpp
+++ b/scene/resources/sky_material.cpp
@@ -410,6 +410,15 @@ float PhysicalSkyMaterial::get_dither_strength() const {
return dither_strength;
}
+void PhysicalSkyMaterial::set_night_sky(const Ref<Texture2D> &p_night_sky) {
+ night_sky = p_night_sky;
+ RS::get_singleton()->material_set_param(_get_material(), "night_sky", night_sky);
+}
+
+Ref<Texture2D> PhysicalSkyMaterial::get_night_sky() const {
+ return night_sky;
+}
+
bool PhysicalSkyMaterial::_can_do_next_pass() const {
return false;
}
@@ -453,6 +462,9 @@ void PhysicalSkyMaterial::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_dither_strength", "strength"), &PhysicalSkyMaterial::set_dither_strength);
ClassDB::bind_method(D_METHOD("get_dither_strength"), &PhysicalSkyMaterial::get_dither_strength);
+ ClassDB::bind_method(D_METHOD("set_night_sky", "night_sky"), &PhysicalSkyMaterial::set_night_sky);
+ ClassDB::bind_method(D_METHOD("get_night_sky"), &PhysicalSkyMaterial::get_night_sky);
+
ADD_GROUP("Rayleigh", "rayleigh_");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rayleigh_coefficient", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_rayleigh_coefficient", "get_rayleigh_coefficient");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "rayleigh_color"), "set_rayleigh_color", "get_rayleigh_color");
@@ -467,6 +479,7 @@ void PhysicalSkyMaterial::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ground_color"), "set_ground_color", "get_ground_color");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "exposure", PROPERTY_HINT_RANGE, "0,128,0.01"), "set_exposure", "get_exposure");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dither_strength", PROPERTY_HINT_RANGE, "0,10,0.01"), "set_dither_strength", "get_dither_strength");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "night_sky", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_night_sky", "get_night_sky");
}
PhysicalSkyMaterial::PhysicalSkyMaterial() {
@@ -484,6 +497,8 @@ PhysicalSkyMaterial::PhysicalSkyMaterial() {
code += "uniform float exposure : hint_range(0, 128) = 0.1;\n";
code += "uniform float dither_strength : hint_range(0, 10) = 1.0;\n\n";
+ code += "uniform sampler2D night_sky : hint_black;";
+
code += "const float PI = 3.141592653589793238462643383279502884197169;\n";
code += "const vec3 UP = vec3( 0.0, 1.0, 0.0 );\n\n";
@@ -547,7 +562,7 @@ PhysicalSkyMaterial::PhysicalSkyMaterial() {
code += "\tfloat sunAngularDiameterCos2 = cos(LIGHT0_SIZE * sun_disk_scale*0.5);\n";
code += "\tfloat sundisk = smoothstep(sunAngularDiameterCos, sunAngularDiameterCos2, cos_theta);\n";
code += "\tvec3 L0 = (sun_energy * 1900.0 * extinction) * sundisk * LIGHT0_COLOR;\n";
- code += "\t// Note: Add nightime here: L0 += night_sky * extinction\n\n";
+ code += "\tL0 += texture(night_sky, SKY_COORDS).xyz * extinction;\n\n";
code += "\tvec3 color = (Lin + L0) * 0.04;\n";
code += "\tCOLOR = pow(color, vec3(1.0 / (1.2 + (1.2 * sun_fade))));\n";
diff --git a/scene/resources/sky_material.h b/scene/resources/sky_material.h
index cd245a2897..e470137d9e 100644
--- a/scene/resources/sky_material.h
+++ b/scene/resources/sky_material.h
@@ -139,6 +139,7 @@ private:
Color ground_color;
float exposure;
float dither_strength;
+ Ref<Texture2D> night_sky;
protected:
static void _bind_methods();
@@ -175,6 +176,9 @@ public:
void set_dither_strength(float p_dither_strength);
float get_dither_strength() const;
+ void set_night_sky(const Ref<Texture2D> &p_night_sky);
+ Ref<Texture2D> get_night_sky() const;
+
virtual Shader::Mode get_shader_mode() const;
RID get_shader_rid() const;
diff --git a/servers/audio/audio_driver_dummy.cpp b/servers/audio/audio_driver_dummy.cpp
index 70d5ebbded..ff0d2cad65 100644
--- a/servers/audio/audio_driver_dummy.cpp
+++ b/servers/audio/audio_driver_dummy.cpp
@@ -39,11 +39,11 @@ Error AudioDriverDummy::init() {
exit_thread = false;
samples_in = nullptr;
- mix_rate = DEFAULT_MIX_RATE;
+ mix_rate = GLOBAL_GET("audio/mix_rate");
speaker_mode = SPEAKER_MODE_STEREO;
channels = 2;
- int latency = GLOBAL_DEF_RST("audio/output_latency", DEFAULT_OUTPUT_LATENCY);
+ int latency = GLOBAL_GET("audio/output_latency");
buffer_frames = closest_power_of_2(latency * mix_rate / 1000);
samples_in = memnew_arr(int32_t, buffer_frames * channels);
@@ -114,11 +114,3 @@ void AudioDriverDummy::finish() {
memdelete(thread);
thread = nullptr;
};
-
-AudioDriverDummy::AudioDriverDummy() {
- thread = nullptr;
-};
-
-AudioDriverDummy::~AudioDriverDummy(){
-
-};
diff --git a/servers/audio/audio_driver_dummy.h b/servers/audio/audio_driver_dummy.h
index 3cf31e8be6..84a566e420 100644
--- a/servers/audio/audio_driver_dummy.h
+++ b/servers/audio/audio_driver_dummy.h
@@ -37,7 +37,7 @@
#include "core/os/thread.h"
class AudioDriverDummy : public AudioDriver {
- Thread *thread;
+ Thread *thread = nullptr;
Mutex mutex;
int32_t *samples_in;
@@ -67,8 +67,8 @@ public:
virtual void unlock();
virtual void finish();
- AudioDriverDummy();
- ~AudioDriverDummy();
+ AudioDriverDummy() {}
+ ~AudioDriverDummy() {}
};
#endif
diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp
index 7b1ac534b4..09d2914e05 100644
--- a/servers/audio_server.cpp
+++ b/servers/audio_server.cpp
@@ -182,6 +182,9 @@ int AudioDriverManager::get_driver_count() {
void AudioDriverManager::initialize(int p_driver) {
GLOBAL_DEF_RST("audio/enable_audio_input", false);
+ GLOBAL_DEF_RST("audio/mix_rate", DEFAULT_MIX_RATE);
+ GLOBAL_DEF_RST("audio/output_latency", DEFAULT_OUTPUT_LATENCY);
+
int failed_driver = -1;
// Check if there is a selected driver
diff --git a/servers/audio_server.h b/servers/audio_server.h
index 71b5ae5946..80e244aacd 100644
--- a/servers/audio_server.h
+++ b/servers/audio_server.h
@@ -80,9 +80,6 @@ public:
SPEAKER_SURROUND_71,
};
- static const int DEFAULT_MIX_RATE = 44100;
- static const int DEFAULT_OUTPUT_LATENCY = 15;
-
static AudioDriver *get_singleton();
void set_singleton();
@@ -129,6 +126,9 @@ class AudioDriverManager {
MAX_DRIVERS = 10
};
+ static const int DEFAULT_MIX_RATE = 44100;
+ static const int DEFAULT_OUTPUT_LATENCY = 15;
+
static AudioDriver *drivers[MAX_DRIVERS];
static int driver_count;
diff --git a/servers/display_server.cpp b/servers/display_server.cpp
index ffb05588cc..cc818cbe04 100644
--- a/servers/display_server.cpp
+++ b/servers/display_server.cpp
@@ -213,7 +213,7 @@ bool DisplayServer::is_console_visible() const {
return false;
}
-void DisplayServer::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, int p_max_legth) {
+void DisplayServer::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, int p_max_length, int p_cursor_start, int p_cursor_end) {
WARN_PRINT("Virtual keyboard not supported by this display server.");
}
@@ -439,7 +439,7 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("console_set_visible", "console_visible"), &DisplayServer::console_set_visible);
ClassDB::bind_method(D_METHOD("is_console_visible"), &DisplayServer::is_console_visible);
- ClassDB::bind_method(D_METHOD("virtual_keyboard_show", "existing_text", "position", "max_length"), &DisplayServer::virtual_keyboard_show, DEFVAL(Rect2i()), DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("virtual_keyboard_show", "existing_text", "position", "max_length", "cursor_start", "cursor_end"), &DisplayServer::virtual_keyboard_show, DEFVAL(Rect2i()), DEFVAL(-1), DEFVAL(-1), DEFVAL(-1));
ClassDB::bind_method(D_METHOD("virtual_keyboard_hide"), &DisplayServer::virtual_keyboard_hide);
ClassDB::bind_method(D_METHOD("virtual_keyboard_get_height"), &DisplayServer::virtual_keyboard_get_height);
diff --git a/servers/display_server.h b/servers/display_server.h
index f6ba26fc6f..b25b1931c8 100644
--- a/servers/display_server.h
+++ b/servers/display_server.h
@@ -280,7 +280,7 @@ public:
virtual void console_set_visible(bool p_enabled);
virtual bool is_console_visible() const;
- virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), int p_max_legth = -1);
+ virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), int p_max_length = -1, int p_cursor_start = -1, int p_cursor_end = -1);
virtual void virtual_keyboard_hide();
// returns height of the currently shown virtual keyboard (0 if keyboard is hidden)
diff --git a/servers/physics_2d/physics_server_2d_sw.cpp b/servers/physics_2d/physics_server_2d_sw.cpp
index e9b2ac6875..a686903763 100644
--- a/servers/physics_2d/physics_server_2d_sw.cpp
+++ b/servers/physics_2d/physics_server_2d_sw.cpp
@@ -1344,7 +1344,3 @@ PhysicsServer2DSW::PhysicsServer2DSW() {
using_threads = int(ProjectSettings::get_singleton()->get("physics/2d/thread_model")) == 2;
flushing_queries = false;
};
-
-PhysicsServer2DSW::~PhysicsServer2DSW(){
-
-};
diff --git a/servers/physics_2d/physics_server_2d_sw.h b/servers/physics_2d/physics_server_2d_sw.h
index d08f836fa9..f9b0bc716c 100644
--- a/servers/physics_2d/physics_server_2d_sw.h
+++ b/servers/physics_2d/physics_server_2d_sw.h
@@ -288,7 +288,7 @@ public:
int get_process_info(ProcessInfo p_info);
PhysicsServer2DSW();
- ~PhysicsServer2DSW();
+ ~PhysicsServer2DSW() {}
};
#endif
diff --git a/servers/physics_3d/physics_server_3d_sw.cpp b/servers/physics_3d/physics_server_3d_sw.cpp
index b625ae2271..1c2329f2dc 100644
--- a/servers/physics_3d/physics_server_3d_sw.cpp
+++ b/servers/physics_3d/physics_server_3d_sw.cpp
@@ -1320,10 +1320,6 @@ void PhysicsServer3DSW::step(real_t p_step) {
#endif
}
-void PhysicsServer3DSW::sync(){
-
-};
-
void PhysicsServer3DSW::flush_queries() {
#ifndef _3D_DISABLED
@@ -1451,7 +1447,3 @@ PhysicsServer3DSW::PhysicsServer3DSW() {
active = true;
flushing_queries = false;
};
-
-PhysicsServer3DSW::~PhysicsServer3DSW(){
-
-};
diff --git a/servers/physics_3d/physics_server_3d_sw.h b/servers/physics_3d/physics_server_3d_sw.h
index 46341bb380..26230ef674 100644
--- a/servers/physics_3d/physics_server_3d_sw.h
+++ b/servers/physics_3d/physics_server_3d_sw.h
@@ -365,7 +365,7 @@ public:
virtual void set_active(bool p_active);
virtual void init();
virtual void step(real_t p_step);
- virtual void sync();
+ virtual void sync() {}
virtual void flush_queries();
virtual void finish();
@@ -374,7 +374,7 @@ public:
int get_process_info(ProcessInfo p_info);
PhysicsServer3DSW();
- ~PhysicsServer3DSW();
+ ~PhysicsServer3DSW() {}
};
#endif
diff --git a/servers/rendering/rasterizer_rd/shaders/bokeh_dof.glsl b/servers/rendering/rasterizer_rd/shaders/bokeh_dof.glsl
index 18555d9672..63f086a83d 100644
--- a/servers/rendering/rasterizer_rd/shaders/bokeh_dof.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/bokeh_dof.glsl
@@ -1,5 +1,4 @@
-/* clang-format off */
-[compute]
+#[compute]
#version 450
@@ -8,7 +7,6 @@ VERSION_DEFINES
#define BLOCK_SIZE 8
layout(local_size_x = BLOCK_SIZE, local_size_y = BLOCK_SIZE, local_size_z = 1) in;
-/* clang-format on */
#ifdef MODE_GEN_BLUR_SIZE
layout(rgba16f, set = 0, binding = 0) uniform restrict image2D color_image;
@@ -51,7 +49,6 @@ layout(push_constant, binding = 1, std430) uniform Params {
float jitter_seed;
uint pad[2];
}
-
params;
//used to work around downsampling filter
diff --git a/servers/rendering/rasterizer_rd/shaders/canvas.glsl b/servers/rendering/rasterizer_rd/shaders/canvas.glsl
index fea36eb65c..e33b3face9 100644
--- a/servers/rendering/rasterizer_rd/shaders/canvas.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/canvas.glsl
@@ -1,5 +1,4 @@
-/* clang-format off */
-[vertex]
+#[vertex]
#version 450
@@ -7,7 +6,6 @@ VERSION_DEFINES
#ifdef USE_ATTRIBUTES
layout(location = 0) in vec2 vertex_attrib;
-/* clang-format on */
layout(location = 3) in vec4 color_attrib;
layout(location = 4) in vec2 uv_attrib;
@@ -87,7 +85,6 @@ void main() {
#if 0
if (draw_data.flags & FLAGS_INSTANCING_ENABLED) {
-
uint offset = draw_data.flags & FLAGS_INSTANCING_STRIDE_MASK;
offset *= gl_InstanceIndex;
mat4 instance_xform = mat4(
@@ -158,7 +155,6 @@ VERTEX_SHADER_CODE
#if 0
if (bool(draw_data.flags & FLAGS_USE_SKELETON) && bone_weights != vec4(0.0)) { //must be a valid bone
//skeleton transform
-
ivec4 bone_indicesi = ivec4(bone_indices);
uvec2 tex_ofs = bone_indicesi.x * 2;
@@ -209,8 +205,7 @@ VERTEX_SHADER_CODE
#endif
}
-/* clang-format off */
-[fragment]
+#[fragment]
#version 450
@@ -219,7 +214,6 @@ VERSION_DEFINES
#include "canvas_uniforms_inc.glsl"
layout(location = 0) in vec2 uv_interp;
-/* clang-format on */
layout(location = 1) in vec4 color_interp;
layout(location = 2) in vec2 vertex_interp;
@@ -342,7 +336,6 @@ void main() {
vec3 normal;
#if defined(NORMAL_USED)
-
bool normal_used = true;
#else
bool normal_used = false;
diff --git a/servers/rendering/rasterizer_rd/shaders/canvas_occlusion.glsl b/servers/rendering/rasterizer_rd/shaders/canvas_occlusion.glsl
index 3e0d5c4ffc..99e70a1976 100644
--- a/servers/rendering/rasterizer_rd/shaders/canvas_occlusion.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/canvas_occlusion.glsl
@@ -1,10 +1,8 @@
-/* clang-format off */
-[vertex]
+#[vertex]
#version 450
layout(location = 0) in highp vec3 vertex;
-/* clang-format on */
layout(push_constant, binding = 0, std430) uniform Constants {
mat4 projection;
@@ -12,7 +10,6 @@ layout(push_constant, binding = 0, std430) uniform Constants {
vec2 direction;
vec2 pad;
}
-
constants;
layout(location = 0) out highp float depth;
@@ -24,13 +21,11 @@ void main() {
gl_Position = constants.projection * vtx;
}
-/* clang-format off */
-[fragment]
+#[fragment]
#version 450
layout(location = 0) in highp float depth;
-/* clang-format on */
layout(location = 0) out highp float distance_buf;
void main() {
diff --git a/servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl b/servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl
index ba05b8b2fb..a39866004b 100644
--- a/servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl
@@ -51,7 +51,6 @@ layout(push_constant, binding = 0, std430) uniform DrawData {
vec2 color_texture_pixel_size;
uint lights[4];
}
-
draw_data;
// The values passed per draw primitives are cached within it
@@ -83,7 +82,6 @@ layout(set = 2, binding = 0, std140) uniform CanvasData {
float time_pad;
//uint light_count;
}
-
canvas_data;
layout(set = 2, binding = 1) uniform textureBuffer skeleton_buffer;
@@ -92,7 +90,6 @@ layout(set = 2, binding = 2, std140) uniform SkeletonData {
mat4 skeleton_transform; //in world coordinates
mat4 skeleton_transform_inverse;
}
-
skeleton_data;
#ifdef USE_LIGHTING
@@ -126,7 +123,6 @@ struct Light {
layout(set = 2, binding = 3, std140) uniform LightData {
Light data[MAX_LIGHTS];
}
-
light_array;
layout(set = 2, binding = 4) uniform texture2D light_textures[MAX_LIGHT_TEXTURES];
@@ -139,7 +135,6 @@ layout(set = 2, binding = 6) uniform sampler shadow_sampler;
layout(set = 2, binding = 7, std430) restrict readonly buffer GlobalVariableData {
vec4 data[];
}
-
global_variables;
/* SET3: Render Target Data */
diff --git a/servers/rendering/rasterizer_rd/shaders/copy.glsl b/servers/rendering/rasterizer_rd/shaders/copy.glsl
index 249e7963d0..eb39c28fa9 100644
--- a/servers/rendering/rasterizer_rd/shaders/copy.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/copy.glsl
@@ -1,12 +1,10 @@
-/* clang-format off */
-[compute]
+#[compute]
#version 450
VERSION_DEFINES
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
-/* clang-format on */
#define FLAG_HORIZONTAL (1 << 0)
#define FLAG_USE_BLUR_SECTION (1 << 1)
@@ -37,7 +35,6 @@ layout(push_constant, binding = 1, std430) uniform Params {
float camera_z_near;
uint pad2[2];
}
-
params;
#ifdef MODE_CUBEMAP_ARRAY_TO_PANORAMA
diff --git a/servers/rendering/rasterizer_rd/shaders/copy_to_fb.glsl b/servers/rendering/rasterizer_rd/shaders/copy_to_fb.glsl
index 5f53045afd..b1cfe1e91e 100644
--- a/servers/rendering/rasterizer_rd/shaders/copy_to_fb.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/copy_to_fb.glsl
@@ -1,12 +1,10 @@
-/* clang-format off */
-[vertex]
+#[vertex]
#version 450
VERSION_DEFINES
layout(location = 0) out vec2 uv_interp;
-/* clang-format on */
layout(push_constant, binding = 1, std430) uniform Params {
vec4 section;
@@ -17,7 +15,6 @@ layout(push_constant, binding = 1, std430) uniform Params {
bool force_luminance;
uint pad[3];
}
-
params;
void main() {
@@ -36,8 +33,7 @@ void main() {
}
}
-/* clang-format off */
-[fragment]
+#[fragment]
#version 450
@@ -52,11 +48,10 @@ layout(push_constant, binding = 1, std430) uniform Params {
bool force_luminance;
bool alpha_to_zero;
uint pad[2];
-} params;
-
+}
+params;
layout(location = 0) in vec2 uv_interp;
-/* clang-format on */
layout(set = 0, binding = 0) uniform sampler2D source_color;
@@ -82,8 +77,9 @@ void main() {
vec2 st = vec2(atan(normal.x, normal.z), acos(normal.y));
- if (st.x < 0.0)
+ if (st.x < 0.0) {
st.x += M_PI * 2.0;
+ }
uv = st / vec2(M_PI * 2.0, M_PI);
diff --git a/servers/rendering/rasterizer_rd/shaders/cube_to_dp.glsl b/servers/rendering/rasterizer_rd/shaders/cube_to_dp.glsl
index 133d97ffcb..54d67db6c6 100644
--- a/servers/rendering/rasterizer_rd/shaders/cube_to_dp.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/cube_to_dp.glsl
@@ -1,12 +1,10 @@
-/* clang-format off */
-[compute]
+#[compute]
#version 450
VERSION_DEFINES
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
-/* clang-format on */
layout(set = 0, binding = 0) uniform samplerCube source_cube;
@@ -18,7 +16,6 @@ layout(push_constant, binding = 1, std430) uniform Params {
float z_near;
bool z_flip;
}
-
params;
layout(r32f, set = 1, binding = 0) uniform restrict writeonly image2D depth_buffer;
diff --git a/servers/rendering/rasterizer_rd/shaders/cubemap_downsampler.glsl b/servers/rendering/rasterizer_rd/shaders/cubemap_downsampler.glsl
index 8d88e46727..7f269b7af3 100644
--- a/servers/rendering/rasterizer_rd/shaders/cubemap_downsampler.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/cubemap_downsampler.glsl
@@ -18,8 +18,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
-/* clang-format off */
-[compute]
+#[compute]
#version 450
@@ -28,7 +27,6 @@ VERSION_DEFINES
#define BLOCK_SIZE 8
layout(local_size_x = BLOCK_SIZE, local_size_y = BLOCK_SIZE, local_size_z = 1) in;
-/* clang-format on */
layout(set = 0, binding = 0) uniform samplerCube source_cubemap;
@@ -37,7 +35,6 @@ layout(rgba16f, set = 1, binding = 0) uniform restrict writeonly imageCube dest_
layout(push_constant, binding = 1, std430) uniform Params {
uint face_size;
}
-
params;
#define M_PI 3.14159265359
diff --git a/servers/rendering/rasterizer_rd/shaders/cubemap_filter.glsl b/servers/rendering/rasterizer_rd/shaders/cubemap_filter.glsl
index 20bc0e2d0d..987545fb76 100644
--- a/servers/rendering/rasterizer_rd/shaders/cubemap_filter.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/cubemap_filter.glsl
@@ -18,8 +18,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
-/* clang-format off */
-[compute]
+#[compute]
#version 450
@@ -28,7 +27,6 @@ VERSION_DEFINES
#define GROUP_SIZE 64
layout(local_size_x = GROUP_SIZE, local_size_y = 1, local_size_z = 1) in;
-/* clang-format on */
layout(set = 0, binding = 0) uniform samplerCube source_cubemap;
layout(rgba16f, set = 2, binding = 0) uniform restrict writeonly imageCube dest_cubemap0;
@@ -51,13 +49,11 @@ layout(rgba16f, set = 2, binding = 6) uniform restrict writeonly imageCube dest_
layout(set = 1, binding = 0, std430) buffer restrict readonly Data {
vec4[7][5][3][24] coeffs;
}
-
data;
#else
layout(set = 1, binding = 0, std430) buffer restrict readonly Data {
vec4[7][5][6] coeffs;
}
-
data;
#endif
diff --git a/servers/rendering/rasterizer_rd/shaders/cubemap_roughness.glsl b/servers/rendering/rasterizer_rd/shaders/cubemap_roughness.glsl
index 0e6e51f0de..5cbb00baa4 100644
--- a/servers/rendering/rasterizer_rd/shaders/cubemap_roughness.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/cubemap_roughness.glsl
@@ -1,5 +1,4 @@
-/* clang-format off */
-[compute]
+#[compute]
#version 450
@@ -8,7 +7,6 @@ VERSION_DEFINES
#define GROUP_SIZE 8
layout(local_size_x = GROUP_SIZE, local_size_y = GROUP_SIZE, local_size_z = 1) in;
-/* clang-format on */
layout(set = 0, binding = 0) uniform samplerCube source_cube;
@@ -21,7 +19,6 @@ layout(push_constant, binding = 1, std430) uniform Params {
bool use_direct_write;
float face_size;
}
-
params;
#define M_PI 3.14159265359
diff --git a/servers/rendering/rasterizer_rd/shaders/giprobe.glsl b/servers/rendering/rasterizer_rd/shaders/giprobe.glsl
index 60c4032d80..ea4237a45e 100644
--- a/servers/rendering/rasterizer_rd/shaders/giprobe.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/giprobe.glsl
@@ -1,5 +1,4 @@
-/* clang-format off */
-[compute]
+#[compute]
#version 450
@@ -10,7 +9,6 @@ layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
#else
layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
#endif
-/* clang-format on */
#ifndef MODE_DYNAMIC
@@ -24,7 +22,6 @@ struct CellChildren {
layout(set = 0, binding = 1, std430) buffer CellChildrenBuffer {
CellChildren data[];
}
-
cell_children;
struct CellData {
@@ -37,7 +34,6 @@ struct CellData {
layout(set = 0, binding = 2, std430) buffer CellDataBuffer {
CellData data[];
}
-
cell_data;
#endif // MODE DYNAMIC
@@ -67,7 +63,6 @@ struct Light {
layout(set = 0, binding = 3, std140) uniform Lights {
Light data[MAX_LIGHTS];
}
-
lights;
#endif // MODE COMPUTE LIGHT
@@ -99,13 +94,11 @@ layout(push_constant, binding = 0, std430) uniform Params {
float aniso_strength;
uint pad;
}
-
params;
layout(set = 0, binding = 4, std430) buffer Outputs {
vec4 data[];
}
-
outputs;
#endif // MODE DYNAMIC
@@ -148,7 +141,6 @@ layout(push_constant, binding = 0, std430) uniform Params {
float propagation;
float pad[3];
}
-
params;
#ifdef MODE_DYNAMIC_LIGHTING
diff --git a/servers/rendering/rasterizer_rd/shaders/giprobe_debug.glsl b/servers/rendering/rasterizer_rd/shaders/giprobe_debug.glsl
index db3043fb28..515cc35507 100644
--- a/servers/rendering/rasterizer_rd/shaders/giprobe_debug.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/giprobe_debug.glsl
@@ -1,5 +1,4 @@
-/* clang-format off */
-[vertex]
+#[vertex]
#version 450
@@ -11,12 +10,10 @@ struct CellData {
uint emission; //rgb normalized with e as multiplier
uint normal; //RGB normal encoded
};
-/* clang-format on */
layout(set = 0, binding = 1, std140) buffer CellDataBuffer {
CellData data[];
}
-
cell_data;
layout(set = 0, binding = 2) uniform texture3D color_tex;
@@ -37,7 +34,6 @@ layout(push_constant, binding = 0, std430) uniform Params {
ivec3 bounds;
uint pad;
}
-
params;
layout(location = 0) out vec4 color_interp;
@@ -172,15 +168,13 @@ void main() {
#endif
}
-/* clang-format off */
-[fragment]
+#[fragment]
#version 450
VERSION_DEFINES
layout(location = 0) in vec4 color_interp;
-/* clang-format on */
layout(location = 0) out vec4 frag_color;
void main() {
diff --git a/servers/rendering/rasterizer_rd/shaders/giprobe_sdf.glsl b/servers/rendering/rasterizer_rd/shaders/giprobe_sdf.glsl
index 37ea673fbe..5b3dec0ee7 100644
--- a/servers/rendering/rasterizer_rd/shaders/giprobe_sdf.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/giprobe_sdf.glsl
@@ -1,12 +1,10 @@
-/* clang-format off */
-[compute]
+#[compute]
#version 450
VERSION_DEFINES
layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in;
-/* clang-format on */
#define MAX_DISTANCE 100000
@@ -20,7 +18,6 @@ struct CellChildren {
layout(set = 0, binding = 1, std430) buffer CellChildrenBuffer {
CellChildren data[];
}
-
cell_children;
struct CellData {
@@ -33,7 +30,6 @@ struct CellData {
layout(set = 0, binding = 2, std430) buffer CellDataBuffer {
CellData data[];
}
-
cell_data;
layout(r8ui, set = 0, binding = 3) uniform restrict writeonly uimage3D sdf_tex;
@@ -44,7 +40,6 @@ layout(push_constant, binding = 0, std430) uniform Params {
uint pad0;
uint pad1;
}
-
params;
void main() {
@@ -73,20 +68,17 @@ void main() {
#if 0
layout(push_constant, binding = 0, std430) uniform Params {
-
ivec3 limits;
uint stack_size;
-} params;
+}
+params;
float distance_to_aabb(ivec3 pos, ivec3 aabb_pos, ivec3 aabb_size) {
-
vec3 delta = vec3(max(ivec3(0), max(aabb_pos - pos, pos - (aabb_pos + aabb_size - ivec3(1)))));
return length(delta);
}
-
void main() {
-
ivec3 pos = ivec3(gl_GlobalInvocationID);
uint stack[10] = uint[](0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@@ -110,7 +102,6 @@ void main() {
int stack_pos = 0;
while (true) {
-
uint index = stack_indices[stack_pos] >> 24;
if (index == 8) {
diff --git a/servers/rendering/rasterizer_rd/shaders/giprobe_write.glsl b/servers/rendering/rasterizer_rd/shaders/giprobe_write.glsl
index 7a79f6a3ac..9c794f1bcc 100644
--- a/servers/rendering/rasterizer_rd/shaders/giprobe_write.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/giprobe_write.glsl
@@ -1,12 +1,10 @@
-/* clang-format off */
-[compute]
+#[compute]
#version 450
VERSION_DEFINES
layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
-/* clang-format on */
#define NO_CHILDREN 0xFFFFFFFF
#define GREY_VEC vec3(0.33333, 0.33333, 0.33333)
@@ -18,7 +16,6 @@ struct CellChildren {
layout(set = 0, binding = 1, std430) buffer CellChildrenBuffer {
CellChildren data[];
}
-
cell_children;
struct CellData {
@@ -31,7 +28,6 @@ struct CellData {
layout(set = 0, binding = 2, std430) buffer CellDataBuffer {
CellData data[];
}
-
cell_data;
#define LIGHT_TYPE_DIRECTIONAL 0
@@ -59,7 +55,6 @@ struct Light {
layout(set = 0, binding = 3, std140) uniform Lights {
Light data[MAX_LIGHTS];
}
-
lights;
#endif
@@ -77,13 +72,11 @@ layout(push_constant, binding = 0, std430) uniform Params {
uint cell_count;
uint pad[2];
}
-
params;
layout(set = 0, binding = 4, std140) uniform Outputs {
vec4 data[];
}
-
output;
#ifdef MODE_COMPUTE_LIGHT
@@ -94,7 +87,6 @@ uint raymarch(float distance, float distance_adv, vec3 from, vec3 direction) {
ivec3 size = ivec3(max(max(params.limits.x, params.limits.y), params.limits.z));
while (distance > -distance_adv) { //use this to avoid precision errors
-
uint cell = 0;
ivec3 pos = ivec3(from);
@@ -120,8 +112,9 @@ uint raymarch(float distance, float distance_adv, vec3 from, vec3 direction) {
}
cell = cell_children.data[cell].children[child];
- if (cell == NO_CHILDREN)
+ if (cell == NO_CHILDREN) {
break;
+ }
half_size >>= ivec3(1);
}
@@ -142,7 +135,6 @@ bool compute_light_vector(uint light, uint cell, vec3 pos, out float attenuation
if (lights.data[light].type == LIGHT_TYPE_DIRECTIONAL) {
light_pos = pos - lights.data[light].direction * length(vec3(params.limits));
attenuation = 1.0;
-
} else {
light_pos = lights.data[light].position;
float distance = length(pos - light_pos);
diff --git a/servers/rendering/rasterizer_rd/shaders/luminance_reduce.glsl b/servers/rendering/rasterizer_rd/shaders/luminance_reduce.glsl
index 060b1a3101..8a11c35b78 100644
--- a/servers/rendering/rasterizer_rd/shaders/luminance_reduce.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/luminance_reduce.glsl
@@ -1,5 +1,4 @@
-/* clang-format off */
-[compute]
+#[compute]
#version 450
@@ -8,7 +7,6 @@ VERSION_DEFINES
#define BLOCK_SIZE 8
layout(local_size_x = BLOCK_SIZE, local_size_y = BLOCK_SIZE, local_size_z = 1) in;
-/* clang-format on */
shared float tmp_data[BLOCK_SIZE * BLOCK_SIZE];
@@ -37,7 +35,6 @@ layout(push_constant, binding = 1, std430) uniform Params {
float exposure_adjust;
float pad[3];
}
-
params;
void main() {
@@ -68,7 +65,6 @@ void main() {
barrier();
size >>= 1;
-
} while (size >= 1);
if (t == 0) {
diff --git a/servers/rendering/rasterizer_rd/shaders/roughness_limiter.glsl b/servers/rendering/rasterizer_rd/shaders/roughness_limiter.glsl
index e59424e3d6..464895928a 100644
--- a/servers/rendering/rasterizer_rd/shaders/roughness_limiter.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/roughness_limiter.glsl
@@ -1,12 +1,10 @@
-/* clang-format off */
-[compute]
+#[compute]
#version 450
VERSION_DEFINES
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
-/* clang-format on */
layout(set = 0, binding = 0) uniform sampler2D source_normal;
layout(r8, set = 1, binding = 0) uniform restrict writeonly image2D dest_roughness;
@@ -16,7 +14,6 @@ layout(push_constant, binding = 1, std430) uniform Params {
float curve;
uint pad;
}
-
params;
#define HALF_PI 1.5707963267948966
@@ -53,14 +50,14 @@ void main() {
float kappa = (3.0f * r - r * r2) / (1.0f - r2);
float variance = 0.25f / kappa;
limit = sqrt(min(2.0f * variance, threshold * threshold));
-//*/
+ */
/*
//Formula based on probability distribution graph
float width = acos(max(0.0,r)); // convert to angle (width)
float roughness = pow(width,1.7)*0.854492; //approximate (crappy) formula to convert to roughness
limit = min(sqrt(roughness), threshold); //convert to perceptual roughness and apply threshold
-//*/
+ */
limit = min(sqrt(pow(acos(max(0.0, r)) / HALF_PI, params.curve)), threshold); //convert to perceptual roughness and apply threshold
diff --git a/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl b/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl
index 86d7ba6f1b..9f42b0f814 100644
--- a/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl
@@ -1,5 +1,4 @@
-/* clang-format off */
-[vertex]
+#[vertex]
#version 450
@@ -10,7 +9,6 @@ VERSION_DEFINES
/* INPUT ATTRIBS */
layout(location = 0) in vec3 vertex_attrib;
-/* clang-format on */
layout(location = 1) in vec3 normal_attrib;
#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED)
layout(location = 2) in vec4 tangent_attrib;
@@ -62,8 +60,6 @@ VERTEX_SHADER_GLOBALS
/* clang-format on */
-// FIXME: This triggers a Mesa bug that breaks rendering, so disabled for now.
-// See GH-13450 and https://bugs.freedesktop.org/show_bug.cgi?id=100316
invariant gl_Position;
layout(location = 7) flat out uint instance_index;
@@ -272,8 +268,7 @@ VERTEX_SHADER_CODE
#endif
}
-/* clang-format off */
-[fragment]
+#[fragment]
#version 450
@@ -284,7 +279,6 @@ VERSION_DEFINES
/* Varyings */
layout(location = 0) in vec3 vertex_interp;
-/* clang-format on */
layout(location = 1) in vec3 normal_interp;
#if defined(COLOR_USED)
diff --git a/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl b/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl
index 93ddcc9dbc..1cac12406a 100644
--- a/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl
@@ -6,7 +6,6 @@ layout(push_constant, binding = 0, std430) uniform DrawCall {
uint pad; //16 bits minimum size
vec2 bake_uv2_offset; //used for bake to uv2, ignored otherwise
}
-
draw_call;
/* Set 0 Scene data that never changes, ever */
@@ -148,7 +147,6 @@ struct InstanceData {
layout(set = 0, binding = 4, std430) restrict readonly buffer Instances {
InstanceData data[];
}
-
instances;
struct LightData { //this structure needs to be as packed as possible
@@ -175,7 +173,6 @@ struct LightData { //this structure needs to be as packed as possible
layout(set = 0, binding = 5, std430) restrict readonly buffer Lights {
LightData data[];
}
-
lights;
struct ReflectionData {
@@ -192,7 +189,6 @@ struct ReflectionData {
layout(set = 0, binding = 6, std140) uniform ReflectionProbeData {
ReflectionData data[MAX_REFLECTION_DATA_STRUCTS];
}
-
reflections;
struct DirectionalLightData {
@@ -231,7 +227,6 @@ struct DirectionalLightData {
layout(set = 0, binding = 7, std140) uniform DirectionalLights {
DirectionalLightData data[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS];
}
-
directional_lights;
struct GIProbeData {
@@ -253,7 +248,6 @@ struct GIProbeData {
layout(set = 0, binding = 8, std140) uniform GIProbes {
GIProbeData data[MAX_GI_PROBES];
}
-
gi_probes;
layout(set = 0, binding = 9) uniform texture3D gi_probe_textures[MAX_GI_PROBE_TEXTURES];
@@ -268,7 +262,6 @@ struct Lightmap {
layout(set = 0, binding = 10, std140) restrict readonly buffer Lightmaps {
Lightmap data[];
}
-
lightmaps;
layout(set = 0, binding = 11) uniform texture2DArray lightmap_textures[MAX_LIGHTMAP_TEXTURES];
@@ -280,7 +273,6 @@ struct LightmapCapture {
layout(set = 0, binding = 12, std140) restrict readonly buffer LightmapCaptures {
LightmapCapture data[];
}
-
lightmap_captures;
#define CLUSTER_COUNTER_SHIFT 20
@@ -311,7 +303,6 @@ struct DecalData {
layout(set = 0, binding = 15, std430) restrict readonly buffer Decals {
DecalData data[];
}
-
decals;
layout(set = 0, binding = 16) uniform utexture3D cluster_texture;
@@ -319,7 +310,6 @@ layout(set = 0, binding = 16) uniform utexture3D cluster_texture;
layout(set = 0, binding = 17, std430) restrict readonly buffer ClusterData {
uint indices[];
}
-
cluster_data;
layout(set = 0, binding = 18) uniform texture2D directional_shadow_atlas;
@@ -327,7 +317,6 @@ layout(set = 0, binding = 18) uniform texture2D directional_shadow_atlas;
layout(set = 0, binding = 19, std430) restrict readonly buffer GlobalVariableData {
vec4 data[];
}
-
global_variables;
// decal atlas
@@ -363,7 +352,6 @@ layout(set = 3, binding = 4) uniform texture2D ao_buffer;
layout(set = 4, binding = 0, std430) restrict readonly buffer Transforms {
vec4 data[];
}
-
transforms;
/* Set 5 User Material */
diff --git a/servers/rendering/rasterizer_rd/shaders/screen_space_reflection.glsl b/servers/rendering/rasterizer_rd/shaders/screen_space_reflection.glsl
index 39b10871ac..084f28d932 100644
--- a/servers/rendering/rasterizer_rd/shaders/screen_space_reflection.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/screen_space_reflection.glsl
@@ -1,16 +1,11 @@
-/* clang-format off */
-[compute]
+#[compute]
#version 450
VERSION_DEFINES
-
-
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
-/* clang-format on */
-
layout(rgba16f, set = 0, binding = 0) uniform restrict readonly image2D source_diffuse;
layout(r32f, set = 0, binding = 1) uniform restrict readonly image2D source_depth;
layout(rgba16f, set = 1, binding = 0) uniform restrict writeonly image2D ssr_image;
@@ -42,7 +37,6 @@ layout(push_constant, binding = 2, std430) uniform Params {
mat4 projection;
}
-
params;
vec2 view_to_screen(vec3 view_pos, out float w) {
diff --git a/servers/rendering/rasterizer_rd/shaders/screen_space_reflection_filter.glsl b/servers/rendering/rasterizer_rd/shaders/screen_space_reflection_filter.glsl
index c36143039c..a5afe74cb2 100644
--- a/servers/rendering/rasterizer_rd/shaders/screen_space_reflection_filter.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/screen_space_reflection_filter.glsl
@@ -1,16 +1,11 @@
-/* clang-format off */
-[compute]
+#[compute]
#version 450
VERSION_DEFINES
-
-
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
-/* clang-format on */
-
layout(rgba16f, set = 0, binding = 0) uniform restrict readonly image2D source_ssr;
layout(r8, set = 0, binding = 1) uniform restrict readonly image2D source_radius;
layout(rgba8, set = 1, binding = 0) uniform restrict readonly image2D source_normal;
@@ -33,7 +28,6 @@ layout(push_constant, binding = 2, std430) uniform Params {
bool vertical;
uint steps;
}
-
params;
#define GAUSS_TABLE_SIZE 15
diff --git a/servers/rendering/rasterizer_rd/shaders/screen_space_reflection_scale.glsl b/servers/rendering/rasterizer_rd/shaders/screen_space_reflection_scale.glsl
index 072f57eb40..218605a962 100644
--- a/servers/rendering/rasterizer_rd/shaders/screen_space_reflection_scale.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/screen_space_reflection_scale.glsl
@@ -1,15 +1,11 @@
-/* clang-format off */
-[compute]
+#[compute]
#version 450
VERSION_DEFINES
-
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
-/* clang-format on */
-
layout(set = 0, binding = 0) uniform sampler2D source_ssr;
layout(set = 1, binding = 0) uniform sampler2D source_depth;
layout(set = 1, binding = 1) uniform sampler2D source_normal;
@@ -26,7 +22,6 @@ layout(push_constant, binding = 1, std430) uniform Params {
bool filtered;
uint pad[2];
}
-
params;
void main() {
@@ -72,7 +67,6 @@ void main() {
color /= 4.0;
depth /= 4.0;
normal = normalize(normal / 4.0) * 0.5 + 0.5;
-
} else {
color = texelFetch(source_ssr, ssC << 1, 0);
depth = texelFetch(source_depth, ssC << 1, 0).r;
diff --git a/servers/rendering/rasterizer_rd/shaders/sky.glsl b/servers/rendering/rasterizer_rd/shaders/sky.glsl
index b0be03fe44..9c59be6841 100644
--- a/servers/rendering/rasterizer_rd/shaders/sky.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/sky.glsl
@@ -1,12 +1,10 @@
-/* clang-format off */
-[vertex]
+#[vertex]
#version 450
VERSION_DEFINES
layout(location = 0) out vec2 uv_interp;
-/* clang-format on */
layout(push_constant, binding = 1, std430) uniform Params {
mat3 orientation;
@@ -14,7 +12,6 @@ layout(push_constant, binding = 1, std430) uniform Params {
vec4 position_multiplier;
float time;
}
-
params;
void main() {
@@ -23,8 +20,7 @@ void main() {
gl_Position = vec4(uv_interp, 1.0, 1.0);
}
-/* clang-format off */
-[fragment]
+#[fragment]
#version 450
@@ -33,7 +29,6 @@ VERSION_DEFINES
#define M_PI 3.14159265359
layout(location = 0) in vec2 uv_interp;
-/* clang-format on */
layout(push_constant, binding = 1, std430) uniform Params {
mat3 orientation;
@@ -41,7 +36,6 @@ layout(push_constant, binding = 1, std430) uniform Params {
vec4 position_multiplier;
float time; //TODO consider adding vec2 screen res, and float radiance size
}
-
params;
#define SAMPLER_NEAREST_CLAMP 0
@@ -62,7 +56,6 @@ layout(set = 0, binding = 0) uniform sampler material_samplers[12];
layout(set = 0, binding = 1, std430) restrict readonly buffer GlobalVariableData {
vec4 data[];
}
-
global_variables;
#ifdef USE_MATERIAL_UNIFORMS
diff --git a/servers/rendering/rasterizer_rd/shaders/specular_merge.glsl b/servers/rendering/rasterizer_rd/shaders/specular_merge.glsl
index c693ea5abc..0b8f406213 100644
--- a/servers/rendering/rasterizer_rd/shaders/specular_merge.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/specular_merge.glsl
@@ -1,12 +1,10 @@
-/* clang-format off */
-[vertex]
+#[vertex]
#version 450
VERSION_DEFINES
layout(location = 0) out vec2 uv_interp;
-/* clang-format on */
void main() {
vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
@@ -15,15 +13,13 @@ void main() {
gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0);
}
-/* clang-format off */
-[fragment]
+#[fragment]
#version 450
VERSION_DEFINES
layout(location = 0) in vec2 uv_interp;
-/* clang-format on */
layout(set = 0, binding = 0) uniform sampler2D specular;
diff --git a/servers/rendering/rasterizer_rd/shaders/ssao.glsl b/servers/rendering/rasterizer_rd/shaders/ssao.glsl
index 764d7eeeac..346338181a 100644
--- a/servers/rendering/rasterizer_rd/shaders/ssao.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/ssao.glsl
@@ -1,12 +1,10 @@
-/* clang-format off */
-[compute]
+#[compute]
#version 450
VERSION_DEFINES
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
-/* clang-format on */
#define TWO_PI 6.283185307179586476925286766559
@@ -49,7 +47,6 @@ const int ROTATIONS[] = int[](
29, 21, 19, 27, 31, 29, 21, 18, 17, 29,
31, 31, 23, 18, 25, 26, 25, 23, 19, 34,
19, 27, 21, 25, 39, 29, 17, 21, 27);
-/* clang-format on */
//#define NUM_SPIRAL_TURNS (7)
const int NUM_SPIRAL_TURNS = ROTATIONS[NUM_SAMPLES - 1];
@@ -78,7 +75,6 @@ layout(push_constant, binding = 1, std430) uniform Params {
float proj_scale;
uint pad;
}
-
params;
vec3 reconstructCSPosition(vec2 S, float z) {
diff --git a/servers/rendering/rasterizer_rd/shaders/ssao_blur.glsl b/servers/rendering/rasterizer_rd/shaders/ssao_blur.glsl
index ca7cc7d71b..3e63e3cb59 100644
--- a/servers/rendering/rasterizer_rd/shaders/ssao_blur.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/ssao_blur.glsl
@@ -1,12 +1,10 @@
-/* clang-format off */
-[compute]
+#[compute]
#version 450
VERSION_DEFINES
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
-/* clang-format on */
layout(set = 0, binding = 0) uniform sampler2D source_ssao;
layout(set = 1, binding = 0) uniform sampler2D source_depth;
@@ -31,7 +29,6 @@ layout(push_constant, binding = 1, std430) uniform Params {
ivec2 axis; /** (1, 0) or (0, 1) */
ivec2 screen_size;
}
-
params;
/** Filter radius in pixels. This will be multiplied by SCALE. */
diff --git a/servers/rendering/rasterizer_rd/shaders/ssao_minify.glsl b/servers/rendering/rasterizer_rd/shaders/ssao_minify.glsl
index c590e406f3..263fca386f 100644
--- a/servers/rendering/rasterizer_rd/shaders/ssao_minify.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/ssao_minify.glsl
@@ -1,12 +1,10 @@
-/* clang-format off */
-[compute]
+#[compute]
#version 450
VERSION_DEFINES
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
-/* clang-format on */
layout(push_constant, binding = 1, std430) uniform Params {
vec2 pixel_size;
@@ -16,7 +14,6 @@ layout(push_constant, binding = 1, std430) uniform Params {
bool orthogonal;
uint pad;
}
-
params;
#ifdef MINIFY_START
diff --git a/servers/rendering/rasterizer_rd/shaders/subsurface_scattering.glsl b/servers/rendering/rasterizer_rd/shaders/subsurface_scattering.glsl
index 9d660c5865..88a953562f 100644
--- a/servers/rendering/rasterizer_rd/shaders/subsurface_scattering.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/subsurface_scattering.glsl
@@ -1,16 +1,11 @@
-/* clang-format off */
-[compute]
+#[compute]
#version 450
VERSION_DEFINES
-
-
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
-/* clang-format on */
-
#ifdef USE_25_SAMPLES
const int kernel_size = 13;
@@ -105,7 +100,6 @@ layout(push_constant, binding = 1, std430) uniform Params {
float depth_scale;
uint pad[3];
}
-
params;
layout(set = 0, binding = 0) uniform sampler2D source_image;
diff --git a/servers/rendering/rasterizer_rd/shaders/tonemap.glsl b/servers/rendering/rasterizer_rd/shaders/tonemap.glsl
index f4754bfea7..b7c46a7d0e 100644
--- a/servers/rendering/rasterizer_rd/shaders/tonemap.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/tonemap.glsl
@@ -1,12 +1,10 @@
-/* clang-format off */
-[vertex]
+#[vertex]
#version 450
VERSION_DEFINES
layout(location = 0) out vec2 uv_interp;
-/* clang-format on */
void main() {
vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
@@ -14,15 +12,13 @@ void main() {
gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0);
}
-/* clang-format off */
-[fragment]
+#[fragment]
#version 450
VERSION_DEFINES
layout(location = 0) in vec2 uv_interp;
-/* clang-format on */
layout(set = 0, binding = 0) uniform sampler2D source_color;
layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure;
@@ -52,7 +48,6 @@ layout(push_constant, binding = 1, std430) uniform Params {
bool use_fxaa;
uint pad;
}
-
params;
layout(location = 0) out vec4 frag_color;
@@ -297,10 +292,11 @@ vec3 do_fxaa(vec3 color, float exposure, vec2 uv_interp) {
textureLod(source_color, uv_interp + dir * 0.5, 0.0).xyz * exposure);
float lumaB = dot(rgbB, luma);
- if ((lumaB < lumaMin) || (lumaB > lumaMax))
+ if ((lumaB < lumaMin) || (lumaB > lumaMax)) {
return rgbA;
- else
+ } else {
return rgbB;
+ }
}
void main() {
diff --git a/servers/rendering/rendering_device_binds.cpp b/servers/rendering/rendering_device_binds.cpp
index 2936843a9c..291f2ff705 100644
--- a/servers/rendering/rendering_device_binds.cpp
+++ b/servers/rendering/rendering_device_binds.cpp
@@ -41,7 +41,7 @@ Error RDShaderFile::parse_versions_from_text(const String &p_text, const String
"fragment",
"tesselation_control",
"tesselation_evaluation",
- "compute"
+ "compute",
};
String stage_code[RD::SHADER_STAGE_MAX];
int stages_found = 0;
@@ -55,14 +55,11 @@ Error RDShaderFile::parse_versions_from_text(const String &p_text, const String
{
String ls = line.strip_edges();
- if (ls.begins_with("#[")) { //workaround for clang format
- ls = ls.replace_first("#[", "[");
- }
- if (ls.begins_with("[") && ls.ends_with("]")) {
- String section = ls.substr(1, ls.length() - 2).strip_edges();
+ if (ls.begins_with("#[") && ls.ends_with("]")) {
+ String section = ls.substr(2, ls.length() - 3).strip_edges();
if (section == "versions") {
if (stages_found) {
- base_error = "Invalid shader file, [version] must be the first section found.";
+ base_error = "Invalid shader file, #[versions] must be the first section found.";
break;
}
reading_versions = true;
@@ -102,22 +99,27 @@ Error RDShaderFile::parse_versions_from_text(const String &p_text, const String
if (reading_versions) {
String l = line.strip_edges();
if (l != "") {
- int eqpos = l.find("=");
- if (eqpos == -1) {
- base_error = "Version syntax is version=\"<defines with C escaping>\".";
+ if (l.find("=") == -1) {
+ base_error = "Missing `=` in '" + l + "'. Version syntax is `version = \"<defines with C escaping>\";`.";
+ break;
+ }
+ if (l.find(";") != -1) {
+ // We don't require a semicolon per se, but it's needed for clang-format to handle things properly.
+ base_error = "Missing `;` in '" + l + "'. Version syntax is `version = \"<defines with C escaping>\";`.";
break;
}
- String version = l.get_slice("=", 0).strip_edges();
+ Vector<String> slices = l.get_slice(";", 0).split("=");
+ String version = slices[0].strip_edges();
if (!version.is_valid_identifier()) {
base_error = "Version names must be valid identifiers, found '" + version + "' instead.";
break;
}
- String define = l.get_slice("=", 1).strip_edges();
+ String define = slices[1].strip_edges();
if (!define.begins_with("\"") || !define.ends_with("\"")) {
base_error = "Version text must be quoted using \"\", instead found '" + define + "'.";
break;
}
- define = "\n" + define.substr(1, define.length() - 2).c_unescape() + "\n"; //add newline before and after jsut in case
+ define = "\n" + define.substr(1, define.length() - 2).c_unescape() + "\n"; // Add newline before and after just in case.
version_texts[version] = define + "\n" + p_defines;
}
diff --git a/servers/xr/xr_interface.cpp b/servers/xr/xr_interface.cpp
index 5ffe50894a..e9858416ec 100644
--- a/servers/xr/xr_interface.cpp
+++ b/servers/xr/xr_interface.cpp
@@ -134,9 +134,9 @@ bool XRInterface::get_anchor_detection_is_enabled() const {
return false;
};
-void XRInterface::set_anchor_detection_is_enabled(bool p_enable){
+void XRInterface::set_anchor_detection_is_enabled(bool p_enable) {
// don't do anything here, this needs to be implemented on AR interface to enable/disable things like plane detection etc.
-};
+}
int XRInterface::get_camera_feed_id() {
// don't do anything here, this needs to be implemented on AR interface to enable/disable things like plane detection etc.
diff --git a/servers/xr/xr_positional_tracker.cpp b/servers/xr/xr_positional_tracker.cpp
index 20853c9027..ad5cee92ea 100644
--- a/servers/xr/xr_positional_tracker.cpp
+++ b/servers/xr/xr_positional_tracker.cpp
@@ -232,7 +232,3 @@ XRPositionalTracker::XRPositionalTracker() {
hand = TRACKER_HAND_UNKNOWN;
rumble = 0.0;
};
-
-XRPositionalTracker::~XRPositionalTracker(){
-
-};
diff --git a/servers/xr/xr_positional_tracker.h b/servers/xr/xr_positional_tracker.h
index d9d1f909e9..515359e9b1 100644
--- a/servers/xr/xr_positional_tracker.h
+++ b/servers/xr/xr_positional_tracker.h
@@ -96,7 +96,7 @@ public:
Transform get_transform(bool p_adjust_by_reference_frame) const;
XRPositionalTracker();
- ~XRPositionalTracker();
+ ~XRPositionalTracker() {}
};
VARIANT_ENUM_CAST(XRPositionalTracker::TrackerHand);
diff --git a/thirdparty/README.md b/thirdparty/README.md
index c000133fe7..64c2ce336d 100644
--- a/thirdparty/README.md
+++ b/thirdparty/README.md
@@ -184,15 +184,13 @@ Patches in the `patches` directory should be re-applied after updates.
## jpeg-compressor
- Upstream: https://github.com/richgel999/jpeg-compressor
-- Version: 2.00 (1eb17d558b9d3b7442d256642a5745974e9eeb1e, 2020)
+- Version: 2.00 (aeb7d3b463aa8228b87a28013c15ee50a7e6fcf3, 2020)
- License: Public domain
Files extracted from upstream source:
- `jpgd*.{c,h}`
-Patches in the `patches` directory should be re-applied after updates.
-
## libogg
@@ -386,7 +384,7 @@ Collection of single-file libraries used in Godot components.
* License: Apache 2.0
- `r128.h`
* Upstream: https://github.com/fahickman/r128
- * Version: 1.4.3 (2019)
+ * Version: git (423f693617faafd01de21e92818add4208eb8bd1, 2020)
* License: Public Domain
- `smaz.{c,h}`
* Upstream: https://github.com/antirez/smaz
@@ -618,7 +616,7 @@ File extracted from upstream release tarball:
## xatlas
- Upstream: https://github.com/jpcy/xatlas
-- Version: git (e12ea82, 2019)
+- Version: git (470576d3516f7e6d8b4554e7c941194a935969fd, 2020)
- License: MIT
Files extracted from upstream source:
diff --git a/thirdparty/jpeg-compressor/patches/fix-msvc-sse2-detection.patch b/thirdparty/jpeg-compressor/patches/fix-msvc-sse2-detection.patch
deleted file mode 100644
index 830b03b0c0..0000000000
--- a/thirdparty/jpeg-compressor/patches/fix-msvc-sse2-detection.patch
+++ /dev/null
@@ -1,44 +0,0 @@
-From ae74fa2fcdef8ec44b925a649f66e8cbefce8315 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?R=C3=A9mi=20Verschelde?= <rverschelde@gmail.com>
-Date: Thu, 7 May 2020 12:14:09 +0200
-Subject: [PATCH] Fix detection of SSE2 with Visual Studio
-
-The previous code assumed that SSE2 is available when building with
-Visual Studio, but that's not accurate on ARM with UWP.
-
-SSE2 could also be enabled on x86 if `_M_IX86_FP == 2`, but it requires
-checking first that it's not actually set to 2 for AVX, AVX2 or AVX512
-(see https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=vs-2019),
-so I left it out for this quick fix.
----
- jpgd.cpp | 16 +++++++---------
- 1 file changed, 7 insertions(+), 9 deletions(-)
-
-diff --git a/jpgd.cpp b/jpgd.cpp
-index 91e66ad..db1f3b4 100644
---- a/jpgd.cpp
-+++ b/jpgd.cpp
-@@ -37,16 +37,14 @@
-
- #ifndef JPGD_USE_SSE2
-
-- #if defined(__GNUC__)
--
-- #if (defined(__x86_64__) || defined(_M_X64))
-- #if defined(__SSE2__)
-- #define JPGD_USE_SSE2 (1)
-- #endif
-+ #if defined(__GNUC__)
-+ #if defined(__SSE2__)
-+ #define JPGD_USE_SSE2 (1)
-+ #endif
-+ #elif defined(_MSC_VER)
-+ #if defined(_M_X64)
-+ #define JPGD_USE_SSE2 (1)
- #endif
--
-- #else
-- #define JPGD_USE_SSE2 (1)
- #endif
-
- #endif
diff --git a/thirdparty/jpeg-compressor/patches/fix-msvc2017-build.patch b/thirdparty/jpeg-compressor/patches/fix-msvc2017-build.patch
deleted file mode 100644
index 7b338de084..0000000000
--- a/thirdparty/jpeg-compressor/patches/fix-msvc2017-build.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-diff --git a/thirdparty/jpeg-compressor/jpgd.cpp b/thirdparty/jpeg-compressor/jpgd.cpp
-index a0c494db61..257d0b7574 100644
---- a/thirdparty/jpeg-compressor/jpgd.cpp
-+++ b/thirdparty/jpeg-compressor/jpgd.cpp
-@@ -2126,7 +2126,7 @@ namespace jpgd {
-
- int jpeg_decoder::decode_next_mcu_row()
- {
-- if (setjmp(m_jmp_state))
-+ if (::setjmp(m_jmp_state))
- return JPGD_FAILED;
-
- const bool chroma_y_filtering = ((m_flags & cFlagBoxChromaFiltering) == 0) && ((m_scan_type == JPGD_YH2V2) || (m_scan_type == JPGD_YH1V2));
-@@ -3042,7 +3042,7 @@ namespace jpgd {
-
- jpeg_decoder::jpeg_decoder(jpeg_decoder_stream* pStream, uint32_t flags)
- {
-- if (setjmp(m_jmp_state))
-+ if (::setjmp(m_jmp_state))
- return;
- decode_init(pStream, flags);
- }
-@@ -3055,7 +3055,7 @@ namespace jpgd {
- if (m_error_code)
- return JPGD_FAILED;
-
-- if (setjmp(m_jmp_state))
-+ if (::setjmp(m_jmp_state))
- return JPGD_FAILED;
-
- decode_start();
diff --git a/thirdparty/misc/cubemap_coeffs.h b/thirdparty/misc/cubemap_coeffs.h
index 1db03ce7c4..15e4e1664b 100644
--- a/thirdparty/misc/cubemap_coeffs.h
+++ b/thirdparty/misc/cubemap_coeffs.h
@@ -21,8 +21,8 @@
#ifndef CUBEMAP_COEFFS_H
#define CUBEMAP_COEFFS_H
-const float low_quality_coeffs[7][5][6][4] = { { { { 0.0002037563, 0.0045063655, -0.0016408688, 0.00012037493 }, { -9.1834951e-05, -0.008947532, -8.1524405e-05, -3.9080094e-05 }, { -2.6038267e-05, -6.8409667e-05, 7.2175702e-05, 0.25492775 }, { -9.9426044e-05, 0.0025427756, -0.00074437925, 1.1773191e-05 }, { -3.2668211e-05, 0.0026930659, -4.824934e-05, -0.0006835048 }, { -0.0002864144, -0.0032220854, 0.0021558286, -0.00014573736 } }, { { 0.00030683201, 0.0026819548, -0.00060011756, -0.0067169226 }, { -0.0030993251, 0.0098575575, 0.0022416671, -8.9075401e-05 }, { 0.00052405626, 0.00057860515, 0.00011654518, -0.048018609 }, { 0.00010850967, -0.0088443512, -0.0018168095, 8.6633128e-05 }, { 0.003333989, -0.0050956447, -8.0414612e-05, 0.0049721239 }, { -4.0961436e-05, -8.5486984e-05, 0.0058683066, 2.2978359e-05 } }, { { 0.99999993, 0.99998625, 0.99999847, 0.99997743 }, { 0.99999519, 0.99991138, 0.99999748, 1 }, { 0.99999986, 0.99999983, 0.99999999, 0.96576708 }, { 0.99999999, 0.99995765, 0.99999807, 1 }, { 0.99999444, 0.99998339, 1, 0.99998741 }, { 0.99999996, 0.99999481, 0.99998046, 0.99999999 } }, { { -0.32267524, -0.65409377, -1.4666488, 0.87153305 }, { -1.264365, 0.89880861, -1.2245906, -0.88501403 }, { -0.31118682, -0.086150323, -0.58811532, 1.1317711 }, { -1.2193493, 1.250379, -1.0871569, -0.12694096 }, { -0.4012249, -0.47436307, -0.59661001, 2.7313005 }, { -1.3109856, 0.60929855, 0.55672643, -0.39880018 } }, { { 0.93273157, 0.59530745, 1.1994788, 0.19102276 }, { 1.2272239, 0.23245736, 1.2577607, 2.5491008 }, { 1.1210098, 0.83074953, 1.3049282, -0.001940633 }, { 1.5839111, 0.10520816, 1.150458, 2.3251789 }, { 0.688692, 0.59807498, 1.3374877, 0.095746692 }, { 1.3054173, 0.36604721, 0.065870226, 1.6496907 } } }, { { { 0.10348445, -4.6771514e-07, -0.011513131, 8.8921052e-05 }, { -0.042152043, 0.013143535, 0.00029120107, 0.036661611 }, { -0.04516036, 0.011438473, -0.0099289792, -0.011707897 }, { -0.034779497, 0.0090981166, -5.4202726e-05, 0.038592793 }, { -0.0071967376, -0.0056614418, -0.012278945, 0.0056867462 }, { -0.037678514, 0.011570177, 0.00029044557, 0.038583909 } }, { { 0.048320869, 1.4603673e-05, 0.0092672368, 0.00033289199 }, { 0.0071001761, -0.0090106091, -0.0027305905, -0.00221479 }, { -0.0027204116, 0.00017921587, 0.015296357, -0.00010306185 }, { 0.0079350203, -0.014772431, -1.2410913e-05, -0.0062296897 }, { 0.025087691, 0.00086046427, 0.015034685, -0.00078224706 }, { 0.00074587265, -0.014602074, 0.00027338224, -0.012848552 } }, { { 0.99345662, 1, 0.99989078, 0.99999994 }, { 0.99908598, 0.99987302, 0.99999623, 0.99932528 }, { 0.99897605, 0.99993456, 0.9998337, 0.99993145 }, { 0.99936351, 0.99984949, 1, 0.9992356 }, { 0.99965935, 0.9999836, 0.99981158, 0.99998352 }, { 0.99928963, 0.99982644, 0.99999992, 0.99917276 } }, { { 3.6882765, 0.15963861, 0.55983965, 0.4075649 }, { 2.1169304, 0.56463157, 0.52957047, 2.0117964 }, { 3.1080461, 0.09682931, 0.42125986, 0.089254784 }, { 1.4247315, 0.48411378, -0.17039102, 1.7431674 }, { 4.0339531, 0.14046159, 0.89848909, 0.011661811 }, { 1.9787852, 0.61750145, 0.63514194, 1.9359003 } }, { { 0.030848793, 1.4472743, 1.4356825, 1.4078009 }, { 0.37639678, 1.0793106, 1.1945413, 0.43983395 }, { 0.27451605, 1.5256415, 1.016769, 1.4850575 }, { 0.54580883, 1.1332879, 3.1331784, 0.60772955 }, { 0.11785158, 1.3928946, 0.94998805, 1.0377182 }, { 0.2842108, 1.0026911, 1.9064553, 0.27147854 } } }, { { { -0.096789259, 0.10326967, 0.0011799959, -0.03077328 }, { 0.08342021, 0.033260738, -0.00045864451, -0.021450568 }, { -0.093369441, -0.05807574, -0.033745214, 0.023817208 }, { 0.056747754, 0.031140512, 0.00019362509, -0.023727797 }, { -0.084538386, -0.040545412, -0.0076838784, 0.03424599 }, { 0.074312056, 0.027619787, 0.0015509082, -0.031043528 } }, { { -0.0085160473, -0.012179292, 0.0049910118, 0.020224799 }, { 0.022559343, -0.016273333, -0.0069382139, 0.00058083224 }, { -0.001115062, 0.035002846, -0.0038974773, -0.039378629 }, { 0.0014921617, -0.00058523872, -0.0011606685, 0.02807528 }, { -0.021454809, 0.052957852, -0.0022083677, -0.027956663 }, { -0.016486487, -0.0040233682, 0.00029949558, 0.021924605 } }, { { 0.99526846, 0.99457883, 0.99998685, 0.99932175 }, { 0.99625908, 0.99931422, 0.99997583, 0.99976974 }, { 0.99563091, 0.99769836, 0.99942287, 0.99894047 }, { 0.99838743, 0.99951485, 0.99999931, 0.99932416 }, { 0.99618922, 0.99777329, 0.99996804, 0.99902234 }, { 0.99709875, 0.9996104, 0.99999875, 0.99927754 } }, { { 3.0342011, 4.8022834, 1.3814123, 1.5280754 }, { 2.9043837, 1.7325954, 1.422223, 2.0569263 }, { 3.0358722, 5.3331504, 1.5680146, 1.6079289 }, { 3.2062833, 1.5368069, 1.0484709, 1.5399477 }, { 2.4471653, 4.0916696, 1.5060688, 1.5807009 }, { 2.6932695, 1.5161537, 1.3991175, 1.6301918 } }, { { 0.50787578, 0.17735471, 1.4006765, 1.0878482 }, { 0.69514518, 1.6765187, 1.2224869, 1.3461327 }, { 0.71381288, 0.17509216, 1.2712934, 0.94575821 }, { 1.1817337, 1.796984, 1.8671538, 1.5708691 }, { 0.55621228, 0.38291359, 1.4128781, 0.82625349 }, { 0.72441647, 1.005794, 1.5522327, 1.6032524 } } }, { { { -0.00041301094, -0.095882618, 0.26932618, -0.25137214 }, { 0.13737415, -0.12694293, -0.0090389663, 0.07227623 }, { -0.005236407, -0.0072961249, 0.27776083, -0.19536433 }, { 0.12781899, -0.042881667, -0.095979169, 0.088937396 }, { 0.037496084, -0.090547583, 0.22112334, -0.21930294 }, { 0.13353408, -0.084346121, -0.011365728, 0.043459312 } }, { { -0.05799135, -0.048612281, 0.02422989, 0.015536268 }, { -0.083144241, 0.039381032, 0.018705957, 0.029297922 }, { 0.026364989, -0.041927591, 0.036718516, 0.0050376168 }, { -0.11562256, 0.043521976, -0.014481644, 0.01529188 }, { -0.047859898, -0.057779647, -0.053171395, -0.0063193506 }, { -0.028781196, 0.041145059, -0.00018523142, 0.053524246 } }, { { 0.998317, 0.99420489, 0.96274416, 0.96776581 }, { 0.98702349, 0.99112796, 0.99978417, 0.99695425 }, { 0.99963867, 0.99909401, 0.95994827, 0.9807178 }, { 0.98503489, 0.99813175, 0.99527799, 0.99591983 }, { 0.99815003, 0.99421459, 0.97379529, 0.97563635 }, { 0.99062621, 0.99558667, 0.99993539, 0.99762039 } }, { { 2.3221943, 2.5383575, 4.3177232, 4.2016467 }, { 3.1936529, 3.0443024, 2.548962, 2.7636456 }, { 2.5923827, 2.3497949, 4.2471014, 4.1975975 }, { 3.3748785, 3.2836577, 2.9220414, 2.7175317 }, { 2.3290083, 2.5560991, 4.3572168, 4.4372585 }, { 3.1512055, 3.2863613, 2.4475378, 2.3620003 } }, { { 0.62833231, 0.52378061, 0.55845033, 0.64883444 }, { 0.76905594, 1.1017801, 1.8714048, 1.5664383 }, { 1.5283278, 1.2423369, 0.62247385, 1.0341956 }, { 0.77484548, 1.6866409, 1.0307399, 1.4224643 }, { 0.85627405, 0.72516079, 0.70094339, 0.7547877 }, { 1.202842, 1.7650605, 1.5938526, 0.97031337 } } }, { { { -0.078108035, -0.049518839, 0.26950139, -0.51522828 }, { 0.43015518, -0.045354216, 0.094550359, -0.2395012 }, { -0.079900522, -0.082582235, 0.24464909, -0.5234896 }, { 0.38422945, -0.023833644, 0.07334288, -0.22827313 }, { -0.075370379, -0.05156594, 0.19883182, -0.45064193 }, { 0.46285395, 0.021899343, 0.10155287, -0.25974773 } }, { { 0.068681419, -0.32175988, 0.15143274, -0.0066205388 }, { -0.17060226, 0.31051319, -0.080511981, -0.1593209 }, { 0.08167251, -0.32517768, 0.10937023, -0.06941926 }, { -0.14580685, 0.32474959, -0.081718057, -0.11068378 }, { 0.053961394, -0.29322836, 0.10408839, -0.02243046 }, { -0.030598471, 0.34332821, -0.091528353, -0.16299796 } }, { { 0.99457629, 0.9455255, 0.95101899, 0.85702741 }, { 0.88648824, 0.94948647, 0.99225906, 0.95773484 }, { 0.99345131, 0.94204015, 0.96342357, 0.84919939 }, { 0.9116513, 0.94549969, 0.99395321, 0.96728511 }, { 0.99569447, 0.95465076, 0.97449039, 0.89242295 }, { 0.88590629, 0.93896015, 0.99061071, 0.95182077 } }, { { 3.6380949, 4.1749529, 4.1351439, 4.8389883 }, { 5.256362, 4.2027959, 3.6096892, 3.9848645 }, { 3.5689427, 3.8620869, 4.0023981, 4.8268584 }, { 5.1128497, 4.468934, 3.5851596, 4.047485 }, { 3.7014988, 4.1310058, 4.2446872, 5.3049323 }, { 4.8659881, 4.3133002, 3.4582876, 3.8863853 } }, { { 1.6276316, 0.7747672, 1.0485958, 0.73900224 }, { 0.72010795, 0.65403093, 1.3179681, 0.65610074 }, { 1.5881174, 0.55108527, 1.0509725, 0.72153362 }, { 1.1389053, 1.0905142, 1.6661598, 0.9987548 }, { 1.977914, 0.83001686, 1.0571479, 0.80249183 }, { 0.94107069, 0.80840873, 0.95379751, 0.50386367 } } }, { { { 0.015525428, -0.48038019, -0.021799698, 0.43629156 }, { 0.045681247, -0.55039024, -0.54573329, 0.57817853 }, { -0.045869129, -0.42209953, -0.14040829, 0.37787106 }, { 0.66327604, -0.70070311, -0.55261635, 0.63446196 }, { 0.015397585, -0.43515767, -0.021927897, 0.4203714 }, { 0.85681772, -0.65394729, -0.67557236, 0.60104142 } }, { { -0.31503888, -0.26745648, 0.26817896, 0.26548747 }, { -0.93282124, -0.033621213, 0.68374802, -0.10858524 }, { -0.21723689, -0.17935495, 0.38521982, 0.2578335 }, { -0.39913153, 0.23555359, 0.59589456, -0.19075103 }, { -0.28851798, -0.24142459, 0.28279261, 0.24766617 }, { -0.29435977, -0.25850549, 0.57790878, -0.200546 } }, { { 0.94895177, 0.83528552, 0.96312243, 0.85974768 }, { 0.35743218, 0.8342303, 0.48442112, 0.80865248 }, { 0.97504059, 0.88863029, 0.9120807, 0.88923301 }, { 0.63305523, 0.67344611, 0.58268761, 0.74904744 }, { 0.95735066, 0.86738225, 0.9589304, 0.87289711 }, { 0.42333878, 0.71100482, 0.45784651, 0.77364753 } }, { { 5.3641275, 5.2550422, 5.3103777, 5.2851215 }, { 5.2657045, 6.2095784, 6.9549598, 4.9205516 }, { 5.163385, 5.3141038, 4.9907618, 5.3583852 }, { 6.1257061, 6.1102338, 6.9549598, 5.3129951 }, { 5.3138838, 5.3257842, 5.3133783, 5.2687156 }, { 5.8915091, 6.153324, 6.9549598, 4.9568971 } }, { { 3.1221918, 1.1882615, 2.6991784, 1.1185048 }, { -0.2322432, -0.16590163, 0.088416958, 0.057399579 }, { 3.4395383, 1.5836276, 2.6242352, 1.2873336 }, { -0.23767634, -0.79425452, 0.20477899, 0.40461516 }, { 2.2521751, 1.1933374, 2.3309484, 1.0185309 }, { -0.099258385, -0.2173726, 0.0736866, 0.15470436 } } }, { { { 0.066050217, -0.33053278, -0.13771479, 0.33278465 }, { 0.00084467977, -0.50077778, -0.30083482, 0.6494273 }, { 0.24880159, -0.30354993, -0.15417892, 0.38203296 }, { -0.073325098, -0.4778777, 0.10779844, 0.66683723 }, { 0.15703809, -0.36335455, -0.15657631, 0.35926503 }, { 0.26127617, -0.29524368, -0.14490804, 0.65461301 } }, { { -0.57970022, -0.33939622, 0.72169742, 0.320959 }, { -0.38698206, -0.12730306, 0.65810895, 0.026509232 }, { -0.6199708, -0.34745658, 0.68683659, 0.34547285 }, { -0.3613378, -0.14006845, 0.65917895, 0.038446867 }, { -0.57778101, -0.35057776, 0.57837882, 0.36488991 }, { -0.50051482, -0.019174387, 0.50816239, 0.02682636 } }, { { 0.8121484, 0.88065787, 0.67837119, 0.88670158 }, { 0.92208686, 0.85616327, 0.69021085, -0.75996148 }, { 0.74413303, 0.88720424, 0.71027063, 0.85714604 }, { 0.92954743, 0.86718726, 0.74421946, -0.74421095 }, { 0.80094204, 0.86317363, 0.8006009, 0.85894353 }, { 0.82536033, 0.95522956, 0.8489833, -0.75548802 } }, { { 5.7725061, 5.1565901, 5.6224483, 5.0847054 }, { 5.7717118, 6.4180057, 6.9797014, -0.03290957 }, { 5.7847117, 5.2015529, 5.614561, 5.2019388 }, { 6.2613999, 6.5807982, 6.9797014, -0.032764603 }, { 5.823775, 5.2332343, 5.826694, 5.197143 }, { 6.3463188, 5.8174311, 6.9797014, -0.032766769 } }, { { 2.96787, 1.3557735, 2.0749129, 1.3066609 }, { -0.92782801, 0.0079162579, -0.33479446, 2.699659e-05 }, { 2.1997063, 3.1083252, 2.6810949, 1.8276262 }, { -0.48654719, -0.10954189, -0.32175132, 5.490092e-05 }, { 3.1970446, 1.787085, 3.062849, 1.6274811 }, { -0.78882801, -0.34050184, -0.59962127, 3.6554198e-05 } } } };
+const float low_quality_coeffs[7][5][6][4] = { { { { 0.0002037563f, 0.0045063655f, -0.0016408688f, 0.00012037493f }, { -9.1834951e-05f, -0.008947532f, -8.1524405e-05f, -3.9080094e-05f }, { -2.6038267e-05f, -6.8409667e-05f, 7.2175702e-05f, 0.25492775f }, { -9.9426044e-05f, 0.0025427756f, -0.00074437925f, 1.1773191e-05f }, { -3.2668211e-05f, 0.0026930659f, -4.824934e-05f, -0.0006835048f }, { -0.0002864144f, -0.0032220854f, 0.0021558286f, -0.00014573736f } }, { { 0.00030683201f, 0.0026819548f, -0.00060011756f, -0.0067169226f }, { -0.0030993251f, 0.0098575575f, 0.0022416671f, -8.9075401e-05f }, { 0.00052405626f, 0.00057860515f, 0.00011654518f, -0.048018609f }, { 0.00010850967f, -0.0088443512f, -0.0018168095f, 8.6633128e-05f }, { 0.003333989f, -0.0050956447f, -8.0414612e-05f, 0.0049721239f }, { -4.0961436e-05f, -8.5486984e-05f, 0.0058683066f, 2.2978359e-05f } }, { { 0.99999993f, 0.99998625f, 0.99999847f, 0.99997743f }, { 0.99999519f, 0.99991138f, 0.99999748f, 1.0f }, { 0.99999986f, 0.99999983f, 0.99999999f, 0.96576708f }, { 0.99999999f, 0.99995765f, 0.99999807f, 1.0f }, { 0.99999444f, 0.99998339f, 1.0f, 0.99998741f }, { 0.99999996f, 0.99999481f, 0.99998046f, 0.99999999f } }, { { -0.32267524f, -0.65409377f, -1.4666488f, 0.87153305f }, { -1.264365f, 0.89880861f, -1.2245906f, -0.88501403f }, { -0.31118682f, -0.086150323f, -0.58811532f, 1.1317711f }, { -1.2193493f, 1.250379f, -1.0871569f, -0.12694096f }, { -0.4012249f, -0.47436307f, -0.59661001f, 2.7313005f }, { -1.3109856f, 0.60929855f, 0.55672643f, -0.39880018f } }, { { 0.93273157f, 0.59530745f, 1.1994788f, 0.19102276f }, { 1.2272239f, 0.23245736f, 1.2577607f, 2.5491008f }, { 1.1210098f, 0.83074953f, 1.3049282f, -0.001940633f }, { 1.5839111f, 0.10520816f, 1.150458f, 2.3251789f }, { 0.688692f, 0.59807498f, 1.3374877f, 0.095746692f }, { 1.3054173f, 0.36604721f, 0.065870226f, 1.6496907f } } }, { { { 0.10348445f, -4.6771514e-07f, -0.011513131f, 8.8921052e-05f }, { -0.042152043f, 0.013143535f, 0.00029120107f, 0.036661611f }, { -0.04516036f, 0.011438473f, -0.0099289792f, -0.011707897f }, { -0.034779497f, 0.0090981166f, -5.4202726e-05f, 0.038592793f }, { -0.0071967376f, -0.0056614418f, -0.012278945f, 0.0056867462f }, { -0.037678514f, 0.011570177f, 0.00029044557f, 0.038583909f } }, { { 0.048320869f, 1.4603673e-05f, 0.0092672368f, 0.00033289199f }, { 0.0071001761f, -0.0090106091f, -0.0027305905f, -0.00221479f }, { -0.0027204116f, 0.00017921587f, 0.015296357f, -0.00010306185f }, { 0.0079350203f, -0.014772431f, -1.2410913e-05f, -0.0062296897f }, { 0.025087691f, 0.00086046427f, 0.015034685f, -0.00078224706f }, { 0.00074587265f, -0.014602074f, 0.00027338224f, -0.012848552f } }, { { 0.99345662f, 1.0f, 0.99989078f, 0.99999994f }, { 0.99908598f, 0.99987302f, 0.99999623f, 0.99932528f }, { 0.99897605f, 0.99993456f, 0.9998337f, 0.99993145f }, { 0.99936351f, 0.99984949f, 1.0f, 0.9992356f }, { 0.99965935f, 0.9999836f, 0.99981158f, 0.99998352f }, { 0.99928963f, 0.99982644f, 0.99999992f, 0.99917276f } }, { { 3.6882765f, 0.15963861f, 0.55983965f, 0.4075649f }, { 2.1169304f, 0.56463157f, 0.52957047f, 2.0117964f }, { 3.1080461f, 0.09682931f, 0.42125986f, 0.089254784f }, { 1.4247315f, 0.48411378f, -0.17039102f, 1.7431674f }, { 4.0339531f, 0.14046159f, 0.89848909f, 0.011661811f }, { 1.9787852f, 0.61750145f, 0.63514194f, 1.9359003f } }, { { 0.030848793f, 1.4472743f, 1.4356825f, 1.4078009f }, { 0.37639678f, 1.0793106f, 1.1945413f, 0.43983395f }, { 0.27451605f, 1.5256415f, 1.016769f, 1.4850575f }, { 0.54580883f, 1.1332879f, 3.1331784f, 0.60772955f }, { 0.11785158f, 1.3928946f, 0.94998805f, 1.0377182f }, { 0.2842108f, 1.0026911f, 1.9064553f, 0.27147854f } } }, { { { -0.096789259f, 0.10326967f, 0.0011799959f, -0.03077328f }, { 0.08342021f, 0.033260738f, -0.00045864451f, -0.021450568f }, { -0.093369441f, -0.05807574f, -0.033745214f, 0.023817208f }, { 0.056747754f, 0.031140512f, 0.00019362509f, -0.023727797f }, { -0.084538386f, -0.040545412f, -0.0076838784f, 0.03424599f }, { 0.074312056f, 0.027619787f, 0.0015509082f, -0.031043528f } }, { { -0.0085160473f, -0.012179292f, 0.0049910118f, 0.020224799f }, { 0.022559343f, -0.016273333f, -0.0069382139f, 0.00058083224f }, { -0.001115062f, 0.035002846f, -0.0038974773f, -0.039378629f }, { 0.0014921617f, -0.00058523872f, -0.0011606685f, 0.02807528f }, { -0.021454809f, 0.052957852f, -0.0022083677f, -0.027956663f }, { -0.016486487f, -0.0040233682f, 0.00029949558f, 0.021924605f } }, { { 0.99526846f, 0.99457883f, 0.99998685f, 0.99932175f }, { 0.99625908f, 0.99931422f, 0.99997583f, 0.99976974f }, { 0.99563091f, 0.99769836f, 0.99942287f, 0.99894047f }, { 0.99838743f, 0.99951485f, 0.99999931f, 0.99932416f }, { 0.99618922f, 0.99777329f, 0.99996804f, 0.99902234f }, { 0.99709875f, 0.9996104f, 0.99999875f, 0.99927754f } }, { { 3.0342011f, 4.8022834f, 1.3814123f, 1.5280754f }, { 2.9043837f, 1.7325954f, 1.422223f, 2.0569263f }, { 3.0358722f, 5.3331504f, 1.5680146f, 1.6079289f }, { 3.2062833f, 1.5368069f, 1.0484709f, 1.5399477f }, { 2.4471653f, 4.0916696f, 1.5060688f, 1.5807009f }, { 2.6932695f, 1.5161537f, 1.3991175f, 1.6301918f } }, { { 0.50787578f, 0.17735471f, 1.4006765f, 1.0878482f }, { 0.69514518f, 1.6765187f, 1.2224869f, 1.3461327f }, { 0.71381288f, 0.17509216f, 1.2712934f, 0.94575821f }, { 1.1817337f, 1.796984f, 1.8671538f, 1.5708691f }, { 0.55621228f, 0.38291359f, 1.4128781f, 0.82625349f }, { 0.72441647f, 1.005794f, 1.5522327f, 1.6032524f } } }, { { { -0.00041301094f, -0.095882618f, 0.26932618f, -0.25137214f }, { 0.13737415f, -0.12694293f, -0.0090389663f, 0.07227623f }, { -0.005236407f, -0.0072961249f, 0.27776083f, -0.19536433f }, { 0.12781899f, -0.042881667f, -0.095979169f, 0.088937396f }, { 0.037496084f, -0.090547583f, 0.22112334f, -0.21930294f }, { 0.13353408f, -0.084346121f, -0.011365728f, 0.043459312f } }, { { -0.05799135f, -0.048612281f, 0.02422989f, 0.015536268f }, { -0.083144241f, 0.039381032f, 0.018705957f, 0.029297922f }, { 0.026364989f, -0.041927591f, 0.036718516f, 0.0050376168f }, { -0.11562256f, 0.043521976f, -0.014481644f, 0.01529188f }, { -0.047859898f, -0.057779647f, -0.053171395f, -0.0063193506f }, { -0.028781196f, 0.041145059f, -0.00018523142f, 0.053524246f } }, { { 0.998317f, 0.99420489f, 0.96274416f, 0.96776581f }, { 0.98702349f, 0.99112796f, 0.99978417f, 0.99695425f }, { 0.99963867f, 0.99909401f, 0.95994827f, 0.9807178f }, { 0.98503489f, 0.99813175f, 0.99527799f, 0.99591983f }, { 0.99815003f, 0.99421459f, 0.97379529f, 0.97563635f }, { 0.99062621f, 0.99558667f, 0.99993539f, 0.99762039f } }, { { 2.3221943f, 2.5383575f, 4.3177232f, 4.2016467f }, { 3.1936529f, 3.0443024f, 2.548962f, 2.7636456f }, { 2.5923827f, 2.3497949f, 4.2471014f, 4.1975975f }, { 3.3748785f, 3.2836577f, 2.9220414f, 2.7175317f }, { 2.3290083f, 2.5560991f, 4.3572168f, 4.4372585f }, { 3.1512055f, 3.2863613f, 2.4475378f, 2.3620003f } }, { { 0.62833231f, 0.52378061f, 0.55845033f, 0.64883444f }, { 0.76905594f, 1.1017801f, 1.8714048f, 1.5664383f }, { 1.5283278f, 1.2423369f, 0.62247385f, 1.0341956f }, { 0.77484548f, 1.6866409f, 1.0307399f, 1.4224643f }, { 0.85627405f, 0.72516079f, 0.70094339f, 0.7547877f }, { 1.202842f, 1.7650605f, 1.5938526f, 0.97031337f } } }, { { { -0.078108035f, -0.049518839f, 0.26950139f, -0.51522828f }, { 0.43015518f, -0.045354216f, 0.094550359f, -0.2395012f }, { -0.079900522f, -0.082582235f, 0.24464909f, -0.5234896f }, { 0.38422945f, -0.023833644f, 0.07334288f, -0.22827313f }, { -0.075370379f, -0.05156594f, 0.19883182f, -0.45064193f }, { 0.46285395f, 0.021899343f, 0.10155287f, -0.25974773f } }, { { 0.068681419f, -0.32175988f, 0.15143274f, -0.0066205388f }, { -0.17060226f, 0.31051319f, -0.080511981f, -0.1593209f }, { 0.08167251f, -0.32517768f, 0.10937023f, -0.06941926f }, { -0.14580685f, 0.32474959f, -0.081718057f, -0.11068378f }, { 0.053961394f, -0.29322836f, 0.10408839f, -0.02243046f }, { -0.030598471f, 0.34332821f, -0.091528353f, -0.16299796f } }, { { 0.99457629f, 0.9455255f, 0.95101899f, 0.85702741f }, { 0.88648824f, 0.94948647f, 0.99225906f, 0.95773484f }, { 0.99345131f, 0.94204015f, 0.96342357f, 0.84919939f }, { 0.9116513f, 0.94549969f, 0.99395321f, 0.96728511f }, { 0.99569447f, 0.95465076f, 0.97449039f, 0.89242295f }, { 0.88590629f, 0.93896015f, 0.99061071f, 0.95182077f } }, { { 3.6380949f, 4.1749529f, 4.1351439f, 4.8389883f }, { 5.256362f, 4.2027959f, 3.6096892f, 3.9848645f }, { 3.5689427f, 3.8620869f, 4.0023981f, 4.8268584f }, { 5.1128497f, 4.468934f, 3.5851596f, 4.047485f }, { 3.7014988f, 4.1310058f, 4.2446872f, 5.3049323f }, { 4.8659881f, 4.3133002f, 3.4582876f, 3.8863853f } }, { { 1.6276316f, 0.7747672f, 1.0485958f, 0.73900224f }, { 0.72010795f, 0.65403093f, 1.3179681f, 0.65610074f }, { 1.5881174f, 0.55108527f, 1.0509725f, 0.72153362f }, { 1.1389053f, 1.0905142f, 1.6661598f, 0.9987548f }, { 1.977914f, 0.83001686f, 1.0571479f, 0.80249183f }, { 0.94107069f, 0.80840873f, 0.95379751f, 0.50386367f } } }, { { { 0.015525428f, -0.48038019f, -0.021799698f, 0.43629156f }, { 0.045681247f, -0.55039024f, -0.54573329f, 0.57817853f }, { -0.045869129f, -0.42209953f, -0.14040829f, 0.37787106f }, { 0.66327604f, -0.70070311f, -0.55261635f, 0.63446196f }, { 0.015397585f, -0.43515767f, -0.021927897f, 0.4203714f }, { 0.85681772f, -0.65394729f, -0.67557236f, 0.60104142f } }, { { -0.31503888f, -0.26745648f, 0.26817896f, 0.26548747f }, { -0.93282124f, -0.033621213f, 0.68374802f, -0.10858524f }, { -0.21723689f, -0.17935495f, 0.38521982f, 0.2578335f }, { -0.39913153f, 0.23555359f, 0.59589456f, -0.19075103f }, { -0.28851798f, -0.24142459f, 0.28279261f, 0.24766617f }, { -0.29435977f, -0.25850549f, 0.57790878f, -0.200546f } }, { { 0.94895177f, 0.83528552f, 0.96312243f, 0.85974768f }, { 0.35743218f, 0.8342303f, 0.48442112f, 0.80865248f }, { 0.97504059f, 0.88863029f, 0.9120807f, 0.88923301f }, { 0.63305523f, 0.67344611f, 0.58268761f, 0.74904744f }, { 0.95735066f, 0.86738225f, 0.9589304f, 0.87289711f }, { 0.42333878f, 0.71100482f, 0.45784651f, 0.77364753f } }, { { 5.3641275f, 5.2550422f, 5.3103777f, 5.2851215f }, { 5.2657045f, 6.2095784f, 6.9549598f, 4.9205516f }, { 5.163385f, 5.3141038f, 4.9907618f, 5.3583852f }, { 6.1257061f, 6.1102338f, 6.9549598f, 5.3129951f }, { 5.3138838f, 5.3257842f, 5.3133783f, 5.2687156f }, { 5.8915091f, 6.153324f, 6.9549598f, 4.9568971f } }, { { 3.1221918f, 1.1882615f, 2.6991784f, 1.1185048f }, { -0.2322432f, -0.16590163f, 0.088416958f, 0.057399579f }, { 3.4395383f, 1.5836276f, 2.6242352f, 1.2873336f }, { -0.23767634f, -0.79425452f, 0.20477899f, 0.40461516f }, { 2.2521751f, 1.1933374f, 2.3309484f, 1.0185309f }, { -0.099258385f, -0.2173726f, 0.0736866f, 0.15470436f } } }, { { { 0.066050217f, -0.33053278f, -0.13771479f, 0.33278465f }, { 0.00084467977f, -0.50077778f, -0.30083482f, 0.6494273f }, { 0.24880159f, -0.30354993f, -0.15417892f, 0.38203296f }, { -0.073325098f, -0.4778777f, 0.10779844f, 0.66683723f }, { 0.15703809f, -0.36335455f, -0.15657631f, 0.35926503f }, { 0.26127617f, -0.29524368f, -0.14490804f, 0.65461301f } }, { { -0.57970022f, -0.33939622f, 0.72169742f, 0.320959f }, { -0.38698206f, -0.12730306f, 0.65810895f, 0.026509232f }, { -0.6199708f, -0.34745658f, 0.68683659f, 0.34547285f }, { -0.3613378f, -0.14006845f, 0.65917895f, 0.038446867f }, { -0.57778101f, -0.35057776f, 0.57837882f, 0.36488991f }, { -0.50051482f, -0.019174387f, 0.50816239f, 0.02682636f } }, { { 0.8121484f, 0.88065787f, 0.67837119f, 0.88670158f }, { 0.92208686f, 0.85616327f, 0.69021085f, -0.75996148f }, { 0.74413303f, 0.88720424f, 0.71027063f, 0.85714604f }, { 0.92954743f, 0.86718726f, 0.74421946f, -0.74421095f }, { 0.80094204f, 0.86317363f, 0.8006009f, 0.85894353f }, { 0.82536033f, 0.95522956f, 0.8489833f, -0.75548802f } }, { { 5.7725061f, 5.1565901f, 5.6224483f, 5.0847054f }, { 5.7717118f, 6.4180057f, 6.9797014f, -0.03290957f }, { 5.7847117f, 5.2015529f, 5.614561f, 5.2019388f }, { 6.2613999f, 6.5807982f, 6.9797014f, -0.032764603f }, { 5.823775f, 5.2332343f, 5.826694f, 5.197143f }, { 6.3463188f, 5.8174311f, 6.9797014f, -0.032766769f } }, { { 2.96787f, 1.3557735f, 2.0749129f, 1.3066609f }, { -0.92782801f, 0.0079162579f, -0.33479446f, 2.699659e-05f }, { 2.1997063f, 3.1083252f, 2.6810949f, 1.8276262f }, { -0.48654719f, -0.10954189f, -0.32175132f, 5.490092e-05f }, { 3.1970446f, 1.787085f, 3.062849f, 1.6274811f }, { -0.78882801f, -0.34050184f, -0.59962127f, 3.6554198e-05f } } } };
-const float high_quality_coeffs[7][5][3][24][4] = { { { { { -4.8355339e-06, -4.4902569e-05, -9.2632249e-05, -0.00053773136 }, { 0.0040143823, -0.00060900339, -0.0095301923, -0.0053956011 }, { -0.0005923892, -3.6901978e-05, -5.6694857e-06, -0.00017018564 }, { 0.0012441402, 0.02236187, 0.022751769, 0.0062788948 }, { 0.00013810055, -2.2709815e-05, 0.0054849671, -1.6599195e-05 }, { -0.020320408, -0.017066319, -0.017457746, 0.022910628 }, { 0.00024171724, 9.7419073e-05, -0.00047804272, -0.00010093683 }, { 7.6988167e-05, 1.8551597e-05, -5.7692813e-05, -3.332362e-05 }, { -0.00062766208, 2.713742e-05, 0.00026511682, 2.3841873e-05 }, { -0.00043656844, 0.0028645469, 0.0049817085, 0.0080221478 }, { -3.3210444e-05, -8.0852386e-05, -2.2111492e-06, -8.4430827e-05 }, { 0.010967284, 0.018811225, 0.017569463, -0.0046944996 }, { -0.00018391248, -0.00010462174, -0.00017726, -0.00018490133 }, { 0.00012591989, 0.015965386, 0.015964059, -0.0078018431 }, { -0.006125333, -8.2224165e-05, -0.00020500151, -0.00025207244 }, { -0.00016320041, -0.0001279242, 0.00014038799, 8.1359421e-05 }, { -0.00064341098, -0.0011265496, -0.0011634792, -0.00081607159 }, { 0.00089294825, 0.0061923653, 0.0052662392, -0.00058227469 }, { -2.4001308e-05, -1.3534224e-05, -1.4720478e-05, -2.5120827e-05 }, { 0.00029964918, -0.0045658543, -0.0045581938, 0.0017106208 }, { 7.5790173e-05, -1.8265415e-05, 1.5918205e-05, 5.8524021e-05 }, { 0.0011669872, -0.00017571882, -0.00017190275, -0.0023833977 }, { 0.0033487264, -0.0066535821, -0.0066413786, -0.0032332601 }, { -3.6468807e-05, -0.00068145131, -9.8190714e-05, -8.7169435e-05 } }, { { -0.0010440653, -8.9750644e-05, 4.971182e-05, 0.0044618878 }, { 0.0078333883, -0.00090884312, -0.00046920549, -0.002465051 }, { -0.0058778609, 0.0026554895, -0.00031880506, -0.00010649091 }, { -0.0015095448, 0.0094026506, 0.009492703, 0.0024572848 }, { 0.0047331786, 0.00070722401, 0.0028798817, -0.00039779892 }, { -0.0089878107, -0.0095474878, -0.0097187652, 0.008765907 }, { -4.0435321e-05, -0.00061813281, -0.0060490143, 0.0016259965 }, { -0.00014720558, -1.0601876e-05, 0.00014757138, 0.00016227641 }, { -0.010428289, -0.00031812813, -0.0016172213, -0.00012022134 }, { 0.0040517131, 0.0072972763, 0.0060433905, 0.0025041645 }, { 0.00014090924, 0.00027612853, 0.00015961665, 0.0002605418 }, { -0.00020653783, -0.00048482867, -0.00058472338, 0.00026413759 }, { 0.00056712638, 0.00026385353, 0.00035484947, 0.00033212447 }, { -0.00094663094, 0.0029891757, 0.0029887838, -0.0026583585 }, { -0.0017400246, 0.00042350567, 0.00086128207, 0.00039863587 }, { 0.00059604848, 0.00027495434, -0.00059956434, -4.4981673e-05 }, { -0.010211343, -0.0080580409, -0.0085333216, 0.0023258717 }, { 0.00042832593, 0.0056750222, 0.0048059635, -0.0092168281 }, { 3.0214612e-05, 4.540924e-06, 1.7239937e-05, 2.783598e-05 }, { 0.00029393335, -4.5128636e-05, -4.3089017e-05, 0.00030682556 }, { -4.7077735e-05, -1.3596835e-05, -0.0015338149, -7.4957991e-05 }, { -0.00097136844, 0.00018564298, 0.00021815754, 0.0015095577 }, { 0.00043929849, -0.0014691094, -0.0014671742, -0.00029365954 }, { 8.8554045e-05, 0.0062500772, 0.0001495049, 0.00021007601 } }, { { 0.0020307077, 0.0020947445, 0.0017438295, 0.0084822342 }, { -0.0069727503, -0.0010131005, 0.0055261321, -0.0020442588 }, { 0.00031035611, 0.00010839441, 3.7359209e-06, 4.3112837e-05 }, { 9.1207794e-05, 0.0050148169, 0.0051071455, 0.0033679057 }, { -0.00090101737, -0.00053793176, -0.0025829621, 0.0003241927 }, { -0.0019244714, -0.0033690472, -0.0035193497, 0.0027653636 }, { -0.00065476293, -0.00017787403, 0.00040383136, -0.00018123957 }, { -0.00030640434, -0.00018961553, -0.00011036218, -0.00015793049 }, { 0.001110592, -0.00021252645, 0.00015849587, -3.7758317e-05 }, { 0.00077967828, -0.0051765235, -0.0078505592, -0.010796339 }, { -1.2024951e-05, 6.48806e-05, -3.9409005e-05, 7.4639306e-05 }, { -0.00017352424, -0.00037802595, -0.00045639468, 0.00016843169 }, { -4.2866244e-05, -4.3730932e-06, 7.3574276e-05, 5.6076779e-05 }, { 0.00024802387, 0.0018053101, 0.0018042994, -0.0016700716 }, { 0.0082698262, -0.00014605077, 0.0004377682, 8.1585074e-05 }, { -4.494343e-06, 0.00019781519, -0.00058910268, -0.00027360572 }, { 0.0013016934, 0.0021020456, 0.0022718598, -0.0059377824 }, { 0.002185371, -0.0080788056, -0.0071952836, 0.0039688918 }, { 0.00013048617, 0.0001738124, 0.00012978924, 0.00013813358 }, { 0.00032386518, 0.00023046021, 0.00023064714, 0.00033762343 }, { 0.00023643771, 0.00019652953, 0.0013083597, 0.00024739959 }, { -0.0063957036, -0.0055319023, -0.0054742301, -0.0037204932 }, { -0.0005510683, -0.0007715413, -0.00077385934, -0.001009415 }, { 0.00017904616, -0.00096137522, 0.00030252599, -2.2478138e-05 } } }, { { { -0.00038948583, -0.00040817153, -0.00041280315, -0.0010985631 }, { 0.0025695337, 0.00042904308, 0.0054649973, -0.0055079106 }, { 0.00052050672, 2.2618679e-05, 0.00024058975, -0.00012632201 }, { -0.013468886, 0.0079396715, 0.0079402246, 0.026283756 }, { -7.922122e-05, -3.4761763e-06, -0.0041716347, 0.0001478739 }, { 0.023716381, -0.016415262, -0.015296927, -0.021050827 }, { 3.7654391e-05, 0.00012765816, -0.0001337099, 0.00051483398 }, { 0.00015671907, 0.00010686796, 2.1421097e-05, -2.2281569e-05 }, { 3.1779413e-06, 0.00010449913, -0.00018303614, 7.5382489e-05 }, { -0.00020526765, -0.0011333575, -0.0050720108, 0.0051482782 }, { 4.0450357e-05, 1.0808158e-05, -2.3316095e-05, 9.7767333e-06 }, { -0.019107229, 0.010907324, 0.0048969594, 0.017851514 }, { 7.4048796e-05, -7.041835e-06, 8.0226174e-05, 5.1714105e-05 }, { -0.016564627, 0.0023486944, 0.0023601429, 0.016005248 }, { -0.004528284, 3.6291049e-05, 2.4229636e-05, 0.0024853948 }, { 5.6882054e-05, 6.8805135e-05, 0.00013119897, 0.00010339801 }, { 0.00021183341, 0.0008203137, -7.204401e-05, 0.00062599728 }, { -0.00099314707, 0.0030198762, -0.0038989955, 0.00055571214 }, { -7.4247984e-05, -8.3993373e-05, -5.9133252e-05, -7.7411989e-05 }, { 0.0054296732, -0.00057858871, -0.00058417754, -0.005072911 }, { -0.00019259782, -0.00018772532, -4.2959783e-05, -0.0001827295 }, { -0.00029351865, 0.00013736372, 0.00016666048, 0.00020873447 }, { 0.0069341659, 0.0027612928, 0.0027538377, -0.0061770317 }, { 4.2584714e-05, -0.00037063589, -9.0693123e-06, 0.00011845784 } }, { { 0.0028834168, 0.0031807308, 0.0031352582, 0.01064051 }, { 0.0049297987, -4.2149356e-05, -0.0014926841, -0.0002300371 }, { 0.0020396303, -0.00066042794, -6.4359283e-05, 0.00017835163 }, { -0.0025767816, 0.0025148152, 0.0025224779, 0.0043006543 }, { -0.00042084416, -0.00013534305, 0.002453623, -4.0707749e-05 }, { -0.0001803055, -0.0010450606, -0.00084380806, 0.00014843677 }, { -0.0064067107, 0.00011012652, -0.0022552747, -0.00080508294 }, { -0.00017778763, -4.296789e-05, 0.00015343883, 0.00025036711 }, { 0.002825978, -0.00031945362, -0.00031987612, -0.00021117763 }, { 0.00032791249, -0.00049524542, 0.0049368722, -0.0017186408 }, { -0.0001685943, -0.00016766033, -0.0001755097, -0.00017067307 }, { 0.00023939157, -0.00011793706, -6.0620575e-05, -0.0002706595 }, { -2.9718673e-05, 3.5950879e-05, 1.839844e-05, -2.8718148e-05 }, { -0.0017260981, 0.00012145435, 0.0001236679, 0.0018292155 }, { 0.0036086706, 0.0001026898, -2.5518889e-05, -0.00019830236 }, { -0.00031546808, -0.00042107458, -0.00059963868, -0.00061472497 }, { -0.0074719522, 0.0015719596, -0.0033624165, -0.0092664101 }, { -0.0011285776, 0.0018601435, 0.00052060704, -1.5554679e-05 }, { 4.9853171e-05, 7.3650922e-05, 3.4080107e-05, 5.4255445e-05 }, { 0.00015102779, -2.58105e-05, -2.5851018e-05, -4.5185316e-05 }, { 0.0002057452, 0.00019037765, 0.0040052198, 0.00020046579 }, { 0.0027727314, 0.0040749211, 0.0036050794, 0.0034635222 }, { 0.00042503689, 0.00056027382, 0.00056052971, -8.2485044e-05 }, { -5.6309634e-05, 0.0019722025, 6.4267434e-05, -0.00020376412 } }, { { 0.0051607661, 0.0047835358, 0.0047658352, 0.0054281814 }, { -0.0040939561, 0.0012119183, -0.0023408179, -0.00055891234 }, { -0.0031939804, -0.0015954053, -0.00018570689, 0.00028849431 }, { -0.0075625096, 0.0033878734, 0.0033797415, 0.010242674 }, { -0.002293562, 0.00024245282, 0.0019455622, 0.0039550747 }, { 0.0090386754, -0.0086947671, -0.0082684939, -0.0075613346 }, { -0.00085735117, 3.4822634e-05, -0.0024653972, -0.00090964985 }, { -0.00013750587, -0.00010089501, 6.3555498e-05, 0.0002758494 }, { 0.0060496328, -0.00032664426, 0.0005979723, -0.00018819024 }, { 0.00072724184, 0.00082242885, 0.0045668772, -0.0054557456 }, { -9.6167811e-05, 7.9856612e-05, 0.00015672473, 8.0901183e-05 }, { 0.00038859448, -0.00025360755, -0.00017624981, -0.00049125519 }, { -8.8277361e-05, 2.4159527e-05, -0.00016014627, -2.7854246e-05 }, { -0.0037308647, 0.00041434141, 0.0004167221, 0.0037190244 }, { 0.00050696744, -4.6752715e-05, 0.00033183668, -0.0025882828 }, { -0.00015915702, -0.0002325901, -0.00036157415, -0.00016391937 }, { 0.00012320153, 0.0026711886, 0.0018414591, -0.0058215223 }, { -0.0029409983, -0.00015460743, 0.0031951665, 0.0074654329 }, { 9.9084813e-05, 9.1785865e-05, 5.9300007e-05, 0.00010463304 }, { 0.00024773341, -2.5723276e-05, -2.5709769e-05, -0.00015357475 }, { 0.000416633, 0.00028749584, -0.0038632071, 0.00039869488 }, { 0.00018344152, 3.0811778e-05, -0.00010240082, 0.00059301197 }, { 0.0019217461, 0.00034404024, 0.00034318823, -0.0015867375 }, { -0.00011928879, 0.001178769, -5.8655983e-05, -0.00028461439 } } }, { { { 0.99999992, 0.99999992, 0.99999991, 0.99999925 }, { 0.99998864, 0.99999972, 0.99993965, 0.99997027 }, { 0.99999969, 1, 0.99999997, 0.99999998 }, { 0.99990852, 0.99971841, 0.99970961, 0.9996348 }, { 0.99999999, 1, 0.99997626, 0.99999999 }, { 0.99951219, 0.9997196, 0.99973058, 0.99951587 }, { 0.99999997, 0.99999999, 0.99999988, 0.99999986 }, { 0.99999998, 0.99999999, 1, 1 }, { 0.9999998, 0.99999999, 0.99999995, 1 }, { 0.99999988, 0.99999525, 0.99997473, 0.99995457 }, { 1, 1, 1, 1 }, { 0.99975729, 0.99976356, 0.99983365, 0.99982963 }, { 0.99999998, 0.99999999, 0.99999998, 0.99999998 }, { 0.99986279, 0.99986979, 0.99986978, 0.99984147 }, { 0.99997099, 1, 0.99999998, 0.99999688 }, { 0.99999999, 0.99999999, 0.99999998, 0.99999999 }, { 0.99999977, 0.99999903, 0.99999932, 0.99999947 }, { 0.99999911, 0.99997627, 0.99997853, 0.99999968 }, { 1, 1, 1, 1 }, { 0.99998521, 0.99998941, 0.99998944, 0.99998567 }, { 0.99999998, 0.99999998, 1, 0.99999998 }, { 0.99999928, 0.99999998, 0.99999997, 0.99999714 }, { 0.99997035, 0.99997405, 0.99997415, 0.99997569 }, { 1, 0.9999997, 1, 0.99999999 } }, { { 0.00015966941, 0.00014262676, 0.00020165066, 0.00021618914 }, { 2.8140907e-06, -0.00020325872, 0.00017736728, 6.0386679e-05 }, { -0.0003187876, 5.8862288e-05, 6.2281085e-05, 1.7339908e-05 }, { -2.6587911e-05, -0.00011609007, -0.00011725093, -7.6114852e-05 }, { 0.00013665042, 5.2703844e-06, -0.00031293536, 3.8693931e-05 }, { -9.8143069e-05, -0.00012816332, -0.00012926252, -0.00010623032 }, { 0.00032342312, -1.9200091e-06, -0.00010691485, 6.3541059e-05 }, { -8.0643542e-06, 9.7622933e-06, 2.9924822e-05, -1.988333e-05 }, { 0.00025318464, 1.2588649e-05, 1.4665927e-05, 9.3294806e-06 }, { 2.6875391e-06, -2.4928123e-05, 2.251878e-05, 0.00011026808 }, { 1.767638e-05, 1.0309044e-05, 2.4765648e-05, 1.4397941e-05 }, { 6.9000935e-06, 1.0637078e-05, 1.087637e-05, 6.3065784e-06 }, { 5.532953e-05, 1.6231463e-05, 4.9564371e-05, 3.6623041e-05 }, { -1.6958729e-05, -3.1627491e-05, -3.1524511e-05, -2.9954116e-05 }, { 8.9045086e-05, 2.1005026e-05, 1.3016463e-05, 8.7863053e-05 }, { -2.75035e-05, -3.0440427e-05, -3.5356286e-05, 5.9609261e-06 }, { 0.0001586274, 4.0711165e-05, 3.1563135e-05, 0.0001385483 }, { 8.5548316e-06, 7.4531928e-05, -3.7017413e-05, 2.6874037e-05 }, { -1.3750655e-05, -8.2756032e-06, -2.7214983e-07, -1.4830115e-05 }, { -7.0798362e-07, -3.3187173e-07, -3.3266762e-07, -5.7113855e-07 }, { 4.3615512e-05, -4.4076433e-06, 8.9239586e-06, 3.7278531e-05 }, { -7.7366773e-06, 4.610399e-06, 4.3762687e-06, -5.64067e-06 }, { -3.2666125e-06, -1.0773146e-05, -1.0861965e-05, -1.3327232e-06 }, { -9.1178305e-06, 0.00030171207, -1.5395234e-05, -2.0695425e-07 } }, { { 0.00017159464, 0.00014699558, 0.00018752678, 0.0002227926 }, { -4.6524822e-05, -0.00010460271, 0.00034735325, 0.00010082238 }, { -6.8269006e-05, 1.4343751e-05, 7.7283393e-06, 2.5347136e-05 }, { -6.6149546e-05, -7.1168993e-05, -7.0621016e-05, -0.00015246746 }, { 7.12022e-05, 3.8790461e-05, -0.00023994449, 6.6792921e-05 }, { -0.00014735813, -0.00012658353, -0.00012162488, -0.00012106777 }, { 0.00015161388, -1.4439153e-05, -3.7629923e-06, 8.3140788e-06 }, { 4.0175416e-05, 2.5380268e-05, -2.2894421e-06, 4.6374378e-06 }, { 0.00028906023, 1.7695243e-05, 5.3790587e-06, 1.631859e-05 }, { 1.8890685e-05, -1.6898275e-05, 2.1007663e-05, 6.5179363e-05 }, { -3.9142595e-06, 2.5745488e-05, 1.0803197e-05, 2.7099749e-05 }, { 9.4245546e-06, 1.0010075e-05, 9.058324e-06, 9.8703427e-06 }, { -2.3441863e-06, 2.5490323e-05, -1.0097654e-05, 4.0554798e-05 }, { -4.1443921e-05, -1.996316e-05, -2.0000841e-05, -4.7495655e-05 }, { 0.00012591695, 5.6179903e-05, -1.8415869e-05, -3.8697972e-05 }, { 2.6719505e-05, 2.4195362e-06, 2.4287424e-05, 3.4703059e-05 }, { 7.3804931e-05, 4.9784871e-05, 3.1159931e-06, 0.00015857197 }, { -0.00010634331, -1.6427658e-05, -7.4874306e-05, -6.2620255e-05 }, { -4.2561214e-06, -1.6123179e-05, -1.5507273e-05, -1.2909924e-05 }, { -1.2210463e-06, 1.1546399e-06, 1.1413892e-06, -1.3465856e-06 }, { 3.4909884e-05, -1.2677793e-05, 0.00011543701, 2.413091e-05 }, { -2.1953323e-05, -4.6244252e-06, -3.5624435e-06, 4.2293671e-06 }, { -1.1392936e-05, -4.3970369e-06, -4.4264864e-06, -1.208518e-05 }, { -4.4002617e-05, 0.00020912348, -3.9617824e-05, -4.1725112e-05 } } }, { { { -0.32504349, -0.32502096, -0.32501094, -0.32423576 }, { -0.65602876, -0.65622598, -0.65567173, -0.65525128 }, { -1.4666488, -1.4666488, -1.4666488, -1.4666488 }, { 0.87168363, 0.87181364, 0.87181792, 0.8718169 }, { -1.264365, -1.264365, -1.264365, -1.264365 }, { 0.89917968, 0.89916889, 0.89916525, 0.89927374 }, { -1.2245906, -1.2245906, -1.2245906, -1.2245906 }, { -0.8885678, -0.88856217, -0.88856327, -0.88855044 }, { -0.31799095, -0.31916566, -0.31907669, -0.31918911 }, { -0.08987958, -0.090342401, -0.090004674, -0.090222398 }, { -0.59425693, -0.59433999, -0.59429118, -0.59433553 }, { 1.1317575, 1.1317475, 1.1317412, 1.1317494 }, { -1.2193493, -1.2193493, -1.2193493, -1.2193493 }, { 1.2506981, 1.250675, 1.250675, 1.2506569 }, { -1.08782, -1.0877793, -1.0878022, -1.0878025 }, { -0.13925598, -0.13932948, -0.13919658, -0.13913403 }, { -0.40394684, -0.4042314, -0.40436178, -0.40402218 }, { -0.47762966, -0.47745572, -0.47767784, -0.47713093 }, { -0.60177181, -0.60176862, -0.60177347, -0.60177079 }, { 2.7311956, 2.7311911, 2.7311911, 2.731191 }, { -1.3109856, -1.3109856, -1.3109856, -1.3109856 }, { 0.60942644, 0.60941369, 0.6094123, 0.60944198 }, { 0.55675448, 0.55672275, 0.55672303, 0.5567542 }, { -0.40637059, -0.4057945, -0.40635768, -0.40636681 } }, { { -0.0016154222, -0.0015930079, -0.0015828998, -0.00087447165 }, { -0.0011262472, -0.001324462, -0.00094895016, -0.00062188189 }, { 0, 0, 0, 0 }, { 9.7616744e-05, 0.00010718899, 0.00010718606, 0.00012665246 }, { 0, 0, 0, 0 }, { 0.00013476236, 6.982272e-05, 6.8208505e-05, 0.00014604742 }, { 0, 0, 0, 0 }, { -0.0031089951, -0.0031071196, -0.0031207245, -0.0031097054 }, { -0.0027808116, -0.0035049857, -0.0034100135, -0.0035192661 }, { -0.0018291474, -0.0019603285, -0.0018919656, -0.0019656229 }, { -0.0034301741, -0.0034912573, -0.0034474395, -0.0034893985 }, { -6.156701e-06, -9.8568527e-06, -1.2383692e-05, -9.9984205e-06 }, { 0, 0, 0, 0 }, { 0.00011838153, 0.00011008679, 0.00011008878, 0.00010536608 }, { -0.0006246638, -0.00058479459, -0.00061327452, -0.00061085433 }, { -0.0059197749, -0.0059778169, -0.0059586015, -0.0058798299 }, { -0.0013246996, -0.0016061786, -0.0016081246, -0.0014374546 }, { -0.001593227, -0.0014706843, -0.0015974008, -0.001341579 }, { -0.0027930604, -0.0027920013, -0.0027939865, -0.0027928528 }, { -1.8908723e-06, -4.266382e-06, -4.2210172e-06, -5.0155215e-06 }, { 0, 0, 0, 0 }, { 0.00018508026, 0.00019774537, 0.00019744661, 0.00019538593 }, { 2.3243747e-05, 1.7291398e-05, 1.7309712e-05, 2.9261396e-05 }, { -0.0041402471, -0.0037085946, -0.0041294876, -0.0041316136 } }, { { -0.0018899732, -0.0018719182, -0.0018661076, -0.0012234594 }, { -0.0012968123, -0.0012971446, -0.00093522854, -0.00066475268 }, { 0, 0, 0, 0 }, { 9.1054464e-05, 0.00014124217, 0.00014156806, 0.00012014953 }, { 0, 0, 0, 0 }, { 0.00017026995, 0.00010528413, 0.00010537941, 0.00015698848 }, { 0, 0, 0, 0 }, { -0.0025812972, -0.0025835894, -0.0025789321, -0.002554949 }, { -0.0035568863, -0.0042988014, -0.0042155548, -0.004312546 }, { -0.0024184575, -0.0025111277, -0.0024654994, -0.0023980076 }, { -0.0036993386, -0.0037113013, -0.0036987284, -0.0037094875 }, { -5.074861e-06, -1.1367399e-05, -1.4819989e-05, -9.2705899e-06 }, { 0, 0, 0, 0 }, { 0.00012570403, 0.00012150272, 0.00012149179, 0.00010579599 }, { -0.00062162762, -0.00058131015, -0.00060837583, -0.00060795256 }, { -0.00775735, -0.0077198081, -0.0078365948, -0.0077749317 }, { -0.0015325554, -0.0017125784, -0.001703195, -0.0015662859 }, { -0.0018130784, -0.00177106, -0.001858095, -0.0015845058 }, { -0.003668417, -0.0036659688, -0.0036693421, -0.0036680526 }, { -9.5804016e-06, -9.6276607e-06, -9.630607e-06, -1.2159056e-05 }, { 0, 0, 0, 0 }, { 0.00017930618, 0.00020084683, 0.00020150104, 0.00020810787 }, { 2.3869269e-05, 1.1024793e-05, 1.1041937e-05, 1.6467357e-05 }, { -0.004690782, -0.0044656761, -0.0046782065, -0.0046921455 } } }, { { { 0.23047932, 0.23043226, 0.23041471, 0.22922185 }, { 0.14990977, 0.15703656, 0.15110771, 0.15149153 }, { 0.30629171, 0.30426701, 0.30400037, 0.30403889 }, { 0.03476576, 0.036188528, 0.036216719, 0.037322097 }, { 0.31066251, 0.31090363, 0.31041565, 0.31057779 }, { 0.04875259, 0.046468595, 0.046486323, 0.046584523 }, { 0.31745458, 0.31874472, 0.32086369, 0.31880207 }, { 0.64054942, 0.64062862, 0.64051973, 0.64059059 }, { 0.27309038, 0.27480819, 0.27477284, 0.27486762 }, { 0.196647, 0.19687982, 0.19607604, 0.1957915 }, { 0.32867362, 0.32858008, 0.32856702, 0.328555 }, { -0.0026873031, -0.0042393446, -0.0057894907, -0.0041858859 }, { 0.40254624, 0.4024247, 0.4025598, 0.40243731 }, { 0.019362807, 0.018146218, 0.018146051, 0.019656613 }, { 0.29328089, 0.29403937, 0.29435036, 0.29403094 }, { 0.57111506, 0.57118505, 0.57099608, 0.57099266 }, { 0.16966612, 0.16993739, 0.17069399, 0.16991136 }, { 0.14989055, 0.1489484, 0.14995985, 0.15015916 }, { 0.33606014, 0.33606294, 0.33606393, 0.33605429 }, { 0.015421206, 0.015180692, 0.01518037, 0.015431139 }, { 0.33165237, 0.33185282, 0.33162592, 0.33166981 }, { 0.078137018, 0.078153855, 0.078165152, 0.078332343 }, { 0.002896946, 0.0026038621, 0.0026029604, 0.0022081151 }, { 0.41064398, 0.40987685, 0.41065341, 0.41059166 } }, { { -0.0024316111, -0.0024732789, -0.0024922144, -0.0035874346 }, { 0.0013306961, 0.004171802, 0.0027660627, 0.0023671465 }, { 0.0034411091, 0.0020878413, 0.0020874456, 0.0022028237 }, { -0.0032873976, -0.0021351911, -0.0021071363, -0.0028424534 }, { 0.0017995208, 0.0022319618, 0.0039270256, 0.0021249365 }, { -0.0019590835, -0.0012526895, -0.0012347747, -0.0021069943 }, { 0.0012319531, 0.002255621, 0.0030193583, 0.0020970822 }, { 0.0015144077, 0.0015110104, 0.0014803089, 0.0015340007 }, { -0.0036679996, -0.0028160114, -0.0028586497, -0.0027953731 }, { -0.005445786, -0.0052624873, -0.0054843188, -0.0053271749 }, { 0.00067154572, 0.0007530775, 0.00067974516, 0.00074462315 }, { -0.0035626119, -0.0034186877, -0.0038720517, -0.0040088745 }, { 0.003455851, 0.0035040061, 0.0034671486, 0.0035069881 }, { -0.0047789747, -0.0047994804, -0.0047996451, -0.0044008337 }, { 0.0032403482, 0.0033627856, 0.003429619, 0.0031153117 }, { -0.005027022, -0.0049812, -0.0049604573, -0.0050556194 }, { -0.0020728991, -0.0014784158, -0.001216894, -0.0019213729 }, { -0.00013808007, -0.00067270623, -0.00024001574, -0.00030691077 }, { 0.0004367104, 0.00043390709, 0.00043548166, 0.00043425516 }, { -0.00082746467, -0.00088151411, -0.00088152334, -0.0008043643 }, { 0.0030277712, 0.003133577, 0.0028529862, 0.0030362271 }, { -0.0058721937, -0.0059816331, -0.0059799345, -0.0058882832 }, { -0.0057032562, -0.0057401855, -0.0057416619, -0.0062417688 }, { -0.0014357888, -0.0020782049, -0.0014346823, -0.0014513767 } }, { { -0.0027051235, -0.0027087245, -0.0027052303, -0.0033594951 }, { 0.0028036195, 0.0030416572, 0.0014306948, 0.0017897371 }, { 0.0031113166, 0.0026432303, 0.0025937824, 0.0025394463 }, { -0.0036032904, -0.003447065, -0.0034344406, -0.0024163572 }, { 0.0023912799, 0.0025281229, 0.0038665087, 0.0024214034 }, { -0.0023543827, -0.0024294943, -0.0024539784, -0.0027742617 }, { 0.0020903896, 0.0026617586, 0.003395249, 0.0026261065 }, { 0.0019031008, 0.0019405475, 0.0019426085, 0.0019404325 }, { -0.0040413326, -0.0030964835, -0.0031020735, -0.0030826754 }, { -0.0064568993, -0.0062342438, -0.0064704698, -0.0065636744 }, { 0.0010788406, 0.0010092051, 0.0010264121, 0.00099891228 }, { -0.0040759201, -0.0059224283, -0.0066809927, -0.0049099348 }, { 0.0042962009, 0.0041909175, 0.0043195236, 0.0041900138 }, { -0.0062728983, -0.0070256154, -0.007025641, -0.0061758746 }, { 0.0036210401, 0.0039723998, 0.0042232048, 0.0042757707 }, { -0.0058693852, -0.0058583303, -0.0058544016, -0.005887725 }, { -0.0023099876, -0.0021136245, -0.0017298078, -0.0022483337 }, { -0.00017851962, -0.00014956209, 8.5676316e-05, -0.00024971669 }, { 0.0003734781, 0.00037078986, 0.00037364181, 0.00037070594 }, { -0.00030648905, -0.00038230535, -0.00038223043, -0.00028623253 }, { 0.0032871423, 0.0034163052, 0.0028276655, 0.0032991918 }, { -0.0061331695, -0.0063319797, -0.0063340119, -0.0064390374 }, { -0.0062172888, -0.0059787106, -0.0059793294, -0.0060406701 }, { -0.0018276142, -0.0022170788, -0.0018293949, -0.0018222824 } } } }, { { { { 0.13218089, -0.11654637, -0.11622196, -0.044208736 }, { 0.0074579257, 0.0038503609, 0.0013201096, 4.0415784e-05 }, { -0.025474487, -0.01209255, -0.016535858, 0.012704547 }, { -0.0016894103, -0.0081312144, -0.0033264609, 0.0011923269 }, { -0.068044876, 0.018276873, -0.074833897, 0.01308348 }, { 0.02665691, 0.013515118, 0.026440814, -0.0077037816 }, { 0.0023286096, -0.0025782652, 0.0021644694, -0.0042955294 }, { 0.051356261, -0.031058382, -0.085382962, -0.033103269 }, { -0.081609229, 0.0035270199, -0.015722417, 0.048773789 }, { 0.0023928418, -0.001243811, 0.011910492, -0.011621478 }, { -0.028953904, -0.029335777, -0.0057891432, 0.013874136 }, { -0.012473582, 0.001772629, -0.013983442, 0.014846792 }, { -0.016111661, 0.0018902323, 0.025910586, 0.042848276 }, { 0.026200626, 0.024007879, 0.0017667146, -0.016394032 }, { -0.0067006429, -0.0017968936, 0.009028659, 0.0044060413 }, { 0.019280611, 0.0449581, -0.042852227, -0.066012332 }, { -0.014451123, -0.047772741, -0.047475406, 0.098434178 }, { -0.0028954635, 0.010521833, -0.015741597, -0.00091666191 }, { 0.0020291956, -0.057966746, -0.04525094, 0.032711614 }, { 0.020563445, -0.0078684621, -0.015282237, -0.0019830466 }, { -0.019504171, 0.071338511, 0.0033729474, -0.0095772339 }, { 0.013056103, 0.018719519, 0.0096002937, -0.028774366 }, { -0.00038728577, -0.0010662982, -0.0014333502, 0.00059135695 }, { 0.073844752, -0.05666013, -0.1007151, -0.030440738 } }, { { 0.00017766639, -9.2398532e-05, -3.9442682e-05, -3.9559848e-05 }, { -0.0043956477, 0.00044042277, -0.00047491077, 9.4171117e-05 }, { -0.0042095545, -0.00910753, -0.0014295282, 0.0042595844 }, { 0.00070989004, -0.0009623012, 0.00084162653, -0.00015925965 }, { -0.0017587638, 0.0033199811, -0.00025544613, 0.00083644978 }, { 0.0051797987, 0.0015691893, -0.002324397, 0.0050776381 }, { 0.003911779, 0.00072639703, 2.102924e-05, -0.0029529332 }, { 0.0050240476, -0.00041452319, 3.1730448e-06, -0.0072697591 }, { -1.5023048e-05, 0.00032491246, -9.2151952e-05, 0.0035851726 }, { 0.0030984373, 0.0016428856, 0.0032974124, -0.0036034289 }, { -0.00044578206, -0.0035916409, 0.0028146658, 0.0068013321 }, { 0.00025716711, -0.0024772152, 0.0029660992, -0.0008783244 }, { -0.005543602, -0.00046453249, 0.006815884, 0.0069207512 }, { -0.0033541738, -0.0015140333, -0.004071746, -0.0020908789 }, { 0.0027932918, -0.0012517158, -0.0033509184, -0.001271572 }, { 0.0043481525, -0.00088858735, -0.0081538059, 0.00027985077 }, { 7.4017523e-05, -7.0080388e-05, -7.1766386e-05, 0.00020468758 }, { 0.00044507396, 0.010179106, -0.0048087449, 0.0013487105 }, { 0.00082148695, -0.00042640153, -0.0024255173, 0.0044486011 }, { -0.00026383509, -0.0031871528, -0.008203704, -0.00053957093 }, { -0.0002996462, 0.00070789605, 7.9300612e-05, -0.00024002209 }, { 0.0013722116, 0.0049176054, 0.0029283062, -0.000849108 }, { 0.00026545039, 0.0011783443, 0.00072103548, -0.0007355776 }, { 0.002192273, -0.00294318, 1.5452606e-05, -0.0020953993 } }, { { 2.4074136e-05, -2.4931598e-05, -1.0893587e-05, 1.080951e-05 }, { -0.0061635883, -0.0042963493, -0.00177783, -0.00080292808 }, { 0.0047868795, -0.0050472436, 0.0082439123, -0.0090979713 }, { 0.0017221077, 0.0067285193, 0.0031011872, -0.0019932567 }, { 0.0010926271, -0.0012170693, 0.00012875612, 0.00016441623 }, { -0.0048786273, -0.0041225634, -0.005591426, 0.0043469593 }, { -0.0070664098, -0.0012625813, -0.00022220241, -0.0026120468 }, { -0.0026689917, 0.00030860545, 1.9297947e-05, 0.001274799 }, { 0.0026769559, 0.00016106032, 0.00013829246, -0.0017239107 }, { -0.0042495789, 0.0010270326, -0.00078224804, -0.0019210019 }, { 0.0072385804, 0.0086418476, 0.0061428272, -0.0027142827 }, { 0.0019768127, -0.00057957046, 0.0047464783, -0.004599565 }, { 0.0093618867, -0.0010476542, -0.0038681572, -0.0065219521 }, { -0.0076406673, -0.0036729355, -0.0068804827, 0.0077571478 }, { 0.0012706397, -0.00042567505, -0.002521821, 6.0288127e-05 }, { -0.002041411, 0.000430125, 0.0073620925, 0.0021579456 }, { 0.00012145466, 4.1276616e-05, 4.2449608e-05, 9.8351262e-05 }, { 0.0014376278, -0.007439719, 0.0039006971, 0.00051135138 }, { -7.1665367e-05, 0.00023856335, 0.00015274881, -0.0096946274 }, { -0.00076804256, 0.0040182915, 0.012603411, -0.00059669891 }, { -0.00010641981, -0.00052355992, 0.00057481361, 0.00016456343 }, { -0.0027623375, -0.0036761364, -0.010480297, 0.0066006902 }, { 0.00049081404, 0.00077264749, 0.0021355718, -0.00029188425 }, { 0.00028566818, 0.00097678458, 0.00089022281, -0.00013760767 } } }, { { { -0.0098123577, 0.11017117, 0.11245143, -0.01173447 }, { 0.0036188505, -0.0025878518, -0.00043343726, -0.0038813197 }, { 0.013109746, -0.016775181, -0.0011093308, 0.00083465721 }, { -0.0042515898, -0.0028159364, 0.00027829209, -0.002907578 }, { -0.0081027554, -0.0019330574, 0.061872524, -0.037539524 }, { -0.012923735, 0.021011524, 0.002680406, 0.0034369108 }, { 0.0027819214, 0.0028657905, -0.0034177203, -0.0037322329 }, { -0.0036178174, 0.065792163, 0.13263475, 0.0055427994 }, { 0.027832309, -0.083372016, -0.058757582, 0.016164879 }, { -0.0082343898, 0.011782416, 0.011496052, -0.0027847616 }, { 0.0012516658, -0.014686832, -0.025073035, -0.020700577 }, { 0.0055718234, -0.011543219, -0.012867689, -0.0049474286 }, { 0.028869265, -0.035431559, 0.024976635, -0.01063055 }, { -0.0010657662, 0.014977146, 0.027109, 0.01612865 }, { -0.0021697493, 0.0044220507, 0.0055654161, -0.0032373397 }, { -0.018500666, -0.01979267, -0.0068480612, 0.03908391 }, { 0.063306878, 0.01934691, 0.019254616, -0.099824471 }, { 7.0580666e-05, -0.0015082457, -0.0056893693, 0.00022726294 }, { 0.0077067654, -0.014018834, -0.021406454, -0.0076589993 }, { -0.0013072394, 2.6765854e-05, 0.0028400803, 0.0037431063 }, { -0.025369581, -0.064039908, -0.020594137, -0.086807367 }, { -0.033639351, 0.010434758, 0.00082983507, 0.013145885 }, { 0.00029373395, 7.8193614e-05, 0.00048496415, 0.00062972215 }, { -0.0041597628, 0.024283117, -0.030148407, 0.011456515 } }, { { -1.3484857e-05, -3.7204145e-05, -1.5660577e-05, -2.4497955e-05 }, { -0.0068070249, 0.0041035892, 0.0034647689, 0.0035918321 }, { -0.0053613309, 0.0080593503, 0.0028507084, -0.0023104987 }, { 0.0048581064, 0.0039720065, -0.0019058129, 0.0047295789 }, { -0.00030675956, -0.0007787587, -0.00025201217, 0.00020777843 }, { -0.00026433336, -0.0093672701, -0.0053201627, -0.0059632173 }, { -0.0063062815, 0.0011995204, 0.0001870407, 0.0028197877 }, { -0.00053247524, -0.00066138217, -1.4959372e-05, -0.00036023628 }, { 0.00027591427, 0.00011309835, 2.2453632e-05, -0.00075736359 }, { 0.0015654886, 0.0018114616, -0.0004503446, -8.5866048e-05 }, { 0.003501393, 0.0037179893, 0.008328543, 0.013411108 }, { -0.0035136609, -0.0015054003, 0.0011903964, 0.0022551358 }, { -0.0083723767, 0.0061303554, -0.008056962, 0.0035035183 }, { -0.0023715655, -0.0070468331, -0.010219655, -0.0057856465 }, { -0.0011406634, -0.00021204595, -0.001693195, 0.0011051597 }, { 0.0011643412, 0.00037557194, 0.0048567739, -0.00063996433 }, { -3.1728174e-05, -2.9073903e-06, -3.0243209e-06, 2.579239e-05 }, { 0.00053152589, 0.0029635352, 0.0040743289, -0.00051381046 }, { -0.0017253584, 0.00012081524, 0.00012243664, -0.00063598215 }, { 0.0026711847, -0.0020733972, -0.0027860744, 0.0017065643 }, { 5.7762902e-05, 0.00092043577, -0.0035278882, 0.0007846087 }, { 0.0056127705, -0.0051893669, -0.0027072408, -0.0025630045 }, { -0.00059289151, -0.0004168408, -8.8118696e-05, -0.00073538101 }, { 0.0003388606, -0.00094234652, 3.013109e-05, -0.0010532484 } }, { { -2.9013996e-05, 6.1983083e-05, 2.8401438e-05, -3.4901557e-05 }, { 0.0045230474, -0.0021369843, -0.00422706, -0.0018918027 }, { 0.00017586142, 0.005389053, 0.0071352982, -0.0018278685 }, { -0.0012135723, -0.0035970727, 0.00078957165, -0.0017065397 }, { -0.00067051937, -1.9501585e-05, 4.1968766e-05, -0.0010958091 }, { -0.0015277626, -0.0039952533, -0.00049631478, 0.0018042745 }, { 0.0039376754, -0.00097834328, 6.5894634e-06, -0.0044189106 }, { -0.00067623039, 0.0004690807, 1.4532105e-07, 0.0032984829 }, { 0.0020787449, -0.0016586579, -0.00062367064, 0.0021545362 }, { 0.0016427801, 2.6710288e-05, 0.0016011535, -0.00077649869 }, { 0.0039999622, -0.0014968097, -0.0025647576, 0.0022783424 }, { 0.001558454, -0.00083803058, 0.0018955692, 0.0010432376 }, { 0.010555722, -0.010395022, 0.0050354965, -0.0016177699 }, { 0.00011370745, -0.009328355, -0.0063009522, 0.0024377458 }, { -0.00024433189, 0.00052920244, -0.0013213352, -0.0013503982 }, { -0.0057620093, 0.00095391746, -0.0034768563, 0.00093990705 }, { 0.00012108024, 4.1007202e-05, 4.2193381e-05, -0.00011043617 }, { 0.0038593696, -0.00074282979, -0.0093457897, 0.00027311164 }, { 0.0021514797, -7.8742315e-05, -0.0018813077, -0.0017625098 }, { 0.0038491118, 0.00022570776, -0.0061331041, 0.00014956617 }, { -0.00014676603, -0.00025053931, 0.003376287, -0.00014730695 }, { 0.0016439646, 0.0060569792, 0.00063058918, -0.0034810156 }, { 0.00011722835, 0.00032237223, -0.0012556553, -0.0006887808 }, { 0.00060814722, 0.0003708376, -0.00056515636, -0.00016801817 } } }, { { { 0.99117704, 0.98705585, 0.98683693, 0.9989534 }, { 0.99996564, 0.99998924, 0.99999903, 0.99999247 }, { 0.99958951, 0.99978616, 0.99986266, 0.99991895 }, { 0.99998953, 0.99996298, 0.99999443, 0.99999506 }, { 0.99764936, 0.9998311, 0.99527468, 0.99920949 }, { 0.9995611, 0.99968788, 0.99964679, 0.99996442 }, { 0.99999342, 0.99999257, 0.99999182, 0.99998381 }, { 0.99867384, 0.99734987, 0.98748052, 0.99943657 }, { 0.99627571, 0.99651225, 0.99814846, 0.99867903 }, { 0.99996323, 0.99992981, 0.99986298, 0.99992859 }, { 0.99957996, 0.99946171, 0.99966886, 0.99968945 }, { 0.99990668, 0.9999318, 0.99981943, 0.99987754 }, { 0.99945334, 0.99937032, 0.99935219, 0.99902503 }, { 0.99965614, 0.99959957, 0.99963092, 0.99973552 }, { 0.9999752, 0.99998861, 0.99994375, 0.99998505 }, { 0.99964293, 0.99879278, 0.99905795, 0.99705307 }, { 0.99788947, 0.99867085, 0.99868681, 0.99012413 }, { 0.99999581, 0.99994351, 0.99985991, 0.99999955 }, { 0.99996824, 0.99822008, 0.99874627, 0.99943549 }, { 0.9997877, 0.99996904, 0.99987919, 0.99999103 }, { 0.99948785, 0.99539425, 0.99978223, 0.99617908 }, { 0.99934875, 0.99977032, 0.99995357, 0.99949949 }, { 0.99999988, 0.99999943, 0.99999886, 0.99999963 }, { 0.99726107, 0.99809817, 0.99445842, 0.99947091 } }, { { -2.3481737e-05, -6.7307406e-06, -2.8605869e-06, -2.0372001e-06 }, { 6.6885689e-05, 4.5630281e-06, 3.5788218e-05, 1.0842484e-05 }, { -4.9278613e-05, -2.4660601e-05, 3.1625301e-06, 0.00019708279 }, { 1.2439158e-05, 3.0347865e-05, 8.6153947e-06, 1.0887256e-05 }, { -0.00012454598, -6.513709e-05, -3.5853483e-06, -3.4708286e-06 }, { -0.00013746339, 0.00013516333, 8.4535039e-05, 5.693766e-05 }, { -2.3674091e-05, -3.4690053e-06, 5.3812265e-07, -1.7613197e-05 }, { -0.00025790043, 3.0475251e-05, 2.1174795e-06, -0.00023630753 }, { -8.8624748e-06, 7.9175589e-06, -2.4258477e-07, -0.00017288313 }, { 4.0061469e-05, 0.00069846663, -0.00060299476, -0.00015396968 }, { 5.0667108e-06, 2.306363e-05, 0.00028636884, 3.6246633e-05 }, { 0.00032740524, -0.00037985037, -0.00014841039, -0.00012676016 }, { 8.7000758e-05, 0.00018530207, 1.7669124e-05, -0.00023199594 }, { 9.2332094e-05, 0.00013487652, 0.00034587506, -3.8853378e-05 }, { 6.9809868e-05, -0.00015411544, 0.0013505166, 1.4531796e-06 }, { -6.3782301e-05, 4.8545135e-05, -0.00027083794, 4.5129465e-05 }, { 3.0912438e-06, -3.2982361e-06, -3.3551612e-06, -1.7781589e-05 }, { 9.872609e-06, -2.9944213e-05, -4.5592652e-05, 1.5950681e-05 }, { 1.4767773e-05, -2.2486726e-05, -0.00010613341, -0.00015794394 }, { 2.4386215e-05, -1.1610334e-05, -4.4456294e-05, -5.0215596e-06 }, { -4.2741558e-06, 8.7714242e-06, -6.6343322e-05, 6.7010735e-05 }, { 0.00016489767, -3.3636771e-05, 5.1610504e-05, 5.2803593e-06 }, { 1.1649256e-05, 2.1169993e-05, 1.9755999e-05, 1.3389438e-05 }, { -0.00015815197, -0.00014316145, 2.6536218e-06, -4.6846396e-05 } }, { { -3.5109783e-06, -9.8530632e-06, -4.5020804e-06, 6.9233235e-08 }, { 9.9938991e-06, -2.0914089e-06, 3.5717699e-05, 3.2813664e-06 }, { 0.00012938219, 1.111062e-05, 8.0858608e-05, 0.00018147439 }, { 4.8657525e-06, 8.6580257e-06, 3.6742927e-06, 3.5828406e-06 }, { 6.9905696e-05, 2.0985073e-05, 6.8866215e-06, -4.2552499e-05 }, { 0.00012100208, 9.7821801e-05, 0.00013576456, 6.3686234e-05 }, { 1.954525e-06, -1.0727343e-06, 5.2332444e-07, -5.4034988e-06 }, { 0.00013699813, -2.226833e-05, 1.4994043e-06, 1.7110377e-05 }, { 0.0001678261, -0.00013844113, -3.4281745e-05, 5.3854072e-05 }, { -1.3018868e-05, 0.00022176303, 0.00016983401, 0.00038109805 }, { 0.00019016068, 0.00023448876, 2.643329e-05, 4.6842203e-05 }, { -1.2492528e-05, -0.00059486605, 0.00012427061, 8.1876965e-05 }, { 8.400564e-05, -0.00029859163, -4.884214e-05, 0.0002631806 }, { 0.00019907281, 0.00014046808, 0.00015482448, 4.0461099e-05 }, { -0.00024349239, 0.00081298441, 0.00084294728, 7.9617963e-05 }, { -6.0040835e-05, 3.2352918e-07, 0.00024295599, 0.00011067283 }, { -6.0027092e-06, 1.1975092e-06, 1.2248893e-06, -2.1293392e-05 }, { 1.4478736e-05, 6.8326918e-05, -7.8693614e-06, 9.2888155e-06 }, { -1.6982828e-05, 1.2094341e-05, -3.1693808e-05, 0.00028574477 }, { 3.4480942e-05, 2.6556008e-05, 0.00016193956, -1.8966503e-06 }, { -5.7726961e-06, 2.1091148e-05, 5.8963955e-05, -1.0834372e-05 }, { 0.0001214393, 1.4174882e-05, 0.0001371836, 0.00021757165 }, { 1.0140226e-05, 6.1641031e-06, 1.0590727e-05, 1.0893212e-05 }, { -1.7442656e-05, 4.2353331e-05, 7.4324714e-05, -1.9484775e-06 } } }, { { { 3.7217719, 3.6900797, 3.6899881, 3.6670816 }, { 0.067826319, 0.16468028, 0.083129199, 0.1336756 }, { 0.66338737, 0.23883566, 0.093361469, 0.10095622 }, { 0.27185537, 0.20781392, 0.32216624, 0.29876595 }, { 2.0776462, 2.0006156, 2.0243138, 2.080345 }, { 0.57695783, 0.18015147, -0.11440889, 0.14229144 }, { 0.63833683, 0.41431062, 0.44752994, 0.47594414 }, { 1.7890608, 1.962584, 1.9322155, 1.6588331 }, { 3.0538128, 3.108267, 3.1001573, 2.9593433 }, { -0.28383051, -0.27708376, -0.042513902, -0.085181891 }, { 0.3873435, 0.41697884, 0.39625427, 0.33250735 }, { -0.33498881, -0.40206929, -0.028905862, -0.48179632 }, { 1.1875033, 1.3535177, 1.2526197, 1.3337495 }, { 0.42579488, 0.24951727, 0.18976118, 0.20605317 }, { -0.53212666, -0.3861028, -0.75685995, -0.23411882 }, { 1.6910165, 1.686815, 1.5906473, 1.6528217 }, { 4.0570657, 4.0349492, 4.0350332, 4.0498099 }, { -0.017225465, -0.032503897, 0.46003211, 0.21602109 }, { 1.1196901, 1.00885, 0.91675568, 0.99635794 }, { -0.093891275, 0.0809352, -0.13783332, 0.27130678 }, { 1.9925136, 1.9829394, 1.8820721, 1.9542026 }, { 0.84563763, 0.48476746, 0.37907152, 0.70267878 }, { 0.37054708, 0.4228574, 0.6329822, 0.26197064 }, { 1.9618393, 1.8405969, 1.9440918, 1.901629 } }, { { -5.6047186e-06, 6.0454847e-06, 2.8365975e-06, 6.0894367e-06 }, { -0.00069876506, -0.00029642785, -0.00059516082, -0.00025400441 }, { -0.00020850504, -0.00012959593, -0.00032902532, -0.00058117893 }, { -0.00037901964, -0.00038062016, -0.00023777964, -0.00033714679 }, { -5.9894351e-05, -9.820791e-05, -5.9867157e-06, -6.258549e-06 }, { -0.00035424038, -8.7146215e-05, 3.0398362e-05, -0.00061406521 }, { 0.00014971442, 4.5936211e-05, -5.6259869e-06, 0.00013567035 }, { -0.00016180211, 3.1840487e-06, 3.8979157e-07, -0.00017131994 }, { -1.9877193e-05, 2.5768261e-05, 9.0577543e-06, -0.00013927462 }, { -0.0012323564, -0.00042892846, 7.2082106e-05, 0.00010999853 }, { -0.00034618449, -0.00017058897, -0.00016535057, -0.00096982024 }, { -0.00028039653, -7.155747e-05, -0.00075796707, 0.00062756458 }, { 6.6596276e-05, -7.9730809e-05, -8.0686754e-05, -2.9532397e-05 }, { -0.00084106867, -0.00036762453, 0.00012523548, -0.00052789663 }, { 7.6718268e-05, -0.0010042005, -0.00042802983, -0.0011951304 }, { -3.6972258e-05, 2.1447505e-06, -0.00035448623, -1.0620008e-05 }, { 2.8326169e-05, 2.2049468e-05, 2.2640575e-05, 1.7574827e-05 }, { -0.00014318496, -0.0004811524, -0.00049293303, -0.00067646484 }, { -2.7469144e-05, -5.9653763e-06, -1.3998899e-05, -0.00018475323 }, { -0.00017314302, -0.00010954727, -0.00040004932, 3.31106e-05 }, { -3.6093435e-06, -1.6125243e-05, -4.9195648e-05, 1.5586886e-05 }, { 0.0002059631, -0.0004024722, -0.00047984678, -9.8485329e-05 }, { -0.00094100913, -0.00073046048, -0.00052500163, -0.00068196784 }, { -2.2820197e-05, -5.9454557e-05, -6.2505468e-06, -2.6569804e-05 } }, { { 2.6015883e-05, 8.5398335e-06, 3.8473185e-06, 9.1409625e-06 }, { -0.00041459247, -0.0001855224, -0.00030529542, -0.00016322166 }, { -8.8427847e-05, -0.0002302048, -0.00038072959, -0.00076801295 }, { -0.00027717792, -0.00028594346, -0.00017910208, -0.00027291164 }, { 2.8409311e-05, -3.8005817e-05, -4.2266878e-06, -1.4520383e-05 }, { -0.0001088827, -0.00021924377, 3.9307406e-05, -0.00032488556 }, { 0.00027997916, 3.5103699e-05, -5.7448764e-06, 0.00010259251 }, { -4.7807894e-06, -2.9470863e-05, 2.6656233e-07, -0.00014346393 }, { 0.00015527098, -6.8528726e-05, -1.1206714e-05, 2.3422595e-05 }, { -0.0012763247, -0.00051503472, 0.00058055106, -0.00068688488 }, { -6.1232076e-06, -1.7073841e-05, -0.00033533389, -0.00078769935 }, { -0.00044113485, -0.00027577451, -0.0012008622, 0.00013071136 }, { 1.834948e-05, -0.00015615102, -0.00016449385, 3.6685217e-05 }, { -0.00063618257, -0.00032641968, -5.0281118e-05, -0.00041378992 }, { -0.0010181884, -0.0003871932, -0.00050061147, -0.0018967455 }, { -5.7650067e-05, -5.1145774e-06, -0.00017409773, 1.9512036e-05 }, { 1.5838743e-05, 2.503655e-05, 2.5679098e-05, 2.0053218e-05 }, { -0.00018055811, -0.00044345237, -7.9049557e-05, -0.00095669161 }, { -4.98611e-05, -1.1320605e-06, 3.7756645e-06, -8.7299215e-05 }, { -0.00011794063, -0.00015778552, -0.00036514881, 4.7288704e-05 }, { -5.1753817e-06, -1.5040527e-06, -2.836739e-05, -9.4945229e-06 }, { 0.00016873335, -0.00031983601, -0.00052281245, 0.00019034815 }, { -0.0011988594, -0.0010684975, -0.00057577023, -0.0009143845 }, { 5.0336006e-05, -1.356148e-05, 1.5582694e-05, -2.0666272e-05 } } }, { { { 0.012207721, 0.0044164612, 0.0022704542, 0.0042008503 }, { 0.29516302, 0.139976, 0.35038027, 0.13748343 }, { 0.1462123, 0.12114907, 0.28473665, 0.45762717 }, { 0.17976664, 0.19141553, 0.1209483, 0.16393769 }, { 0.044254492, 0.11383095, 0.0062726904, 0.023550537 }, { 0.14785458, 0.10151341, 0.045717467, 0.42243971 }, { -0.24205201, -0.033590842, 0.0032064617, -0.093924041 }, { 0.10866955, 0.016299431, 0.00081631108, 0.15856447 }, { 0.10108337, 0.057931152, 0.024463589, 0.21514346 }, { 0.47967783, 0.75472932, 0.5653649, 0.64752457 }, { 0.30082544, 0.15124922, 0.23567284, 0.47161499 }, { 0.54286166, 0.61049777, 0.61641378, 0.51181399 }, { 0.39328762, 0.25557559, 0.25875912, 0.22436901 }, { 0.45699569, 0.16989563, 0.2429263, 0.3924359 }, { 0.92996797, 1.1024806, 0.78045387, 1.2298879 }, { 0.19029829, -0.022675055, 0.28113642, 0.034941166 }, { 0.013203939, 0.013034069, 0.013414649, 0.011688038 }, { 0.076026927, 0.13838472, 0.29961655, 0.31531564 }, { 0.089182386, 0.010401684, 0.029374547, 0.22995838 }, { 0.052198894, 0.039866726, 0.11570972, -0.013818992 }, { 0.0062380932, 0.01788119, -0.20765047, 0.013339281 }, { 0.12436441, 0.17318651, 0.21554136, 0.18600144 }, { 0.38005287, 0.32135548, 0.28632777, 0.29211902 }, { 0.03798742, 0.0450845, 0.010912505, 0.039060104 } }, { { 0.00077914246, 0.00011130803, 8.1110229e-05, -0.00035312557 }, { 0.00051711901, 0.00029701387, 0.00040733345, 0.00034149723 }, { 0.00063893978, -0.00013702086, 0.00030866699, -0.00020070677 }, { 7.5899443e-05, 9.7456273e-05, -4.5352178e-05, 7.6172703e-06 }, { 0.00066250814, -0.00073033349, 0.00015225542, -0.0010197351 }, { 0.00040931533, -0.00043022747, 0.00093333285, 0.0002579685 }, { -0.00067488578, -0.0003706974, -0.00044487256, -0.00056555959 }, { 0.00075838366, -0.0021903789, -0.0026744174, -0.00047135202 }, { -0.00081050821, -0.0010297809, -0.00099480849, -0.00074914246 }, { 0.00063637392, 5.248783e-05, 0.00044645091, 0.00018028446 }, { 0.00067430392, 0.0004762628, -0.00032736685, 0.00041933609 }, { 6.2324555e-05, -1.6709531e-06, 0.00057418116, -0.0010360999 }, { -0.00038256183, -0.0010104012, -0.00045533693, -1.3888404e-05 }, { 0.00068274628, 0.00068411875, -0.00091273333, 0.00016211145 }, { -0.00039440715, 0.00027665323, -0.00035895503, 0.00013423207 }, { -0.00061939017, 0.00012140102, 0.00024178233, 0.00064755788 }, { -0.00052441128, -0.00050994483, -0.00051126044, 0.00066320373 }, { 0.00085915332, 0.0013567332, -0.00014328466, 0.00056098523 }, { -0.0012682676, 0.0029139719, 0.0019812291, -0.00053863027 }, { 0.0021895869, 0.00062956835, 0.0018161156, 0.00011699452 }, { -0.0010337306, 0.00016880497, -0.0014942346, -0.0034402453 }, { -0.0025336946, -0.00019468865, -0.00018045349, -5.4312149e-05 }, { 0.00021491979, 4.7651714e-05, -0.00044921151, 0.00046742044 }, { 0.0019408125, 0.00044842687, 0.0026003265, -0.00090116109 } }, { { -0.0006591255, 0.00022873584, 0.00026313866, -0.00060151354 }, { 0.00027198127, 0.00034252944, 0.00033246896, 0.00035232159 }, { -0.00034460639, -5.9085725e-05, 7.836454e-05, -0.00018946388 }, { 0.00018790551, 0.0001918358, 9.7031467e-05, 0.00015259869 }, { -0.0023033429, -0.0012945186, -0.00080964072, -0.00030432514 }, { -0.001359781, 0.00055828912, -0.00041912301, 0.00019263336 }, { -0.00042789448, -0.00018313775, -0.00030217124, -0.00028437496 }, { -0.0018340159, 0.00030654336, -0.00010781402, -0.0011985455 }, { -0.002103478, 0.00029492518, -0.00042283946, -0.001472689 }, { 0.00064558079, 0.00049703204, -0.00018932594, -0.00038268301 }, { -0.00097813334, -0.00057838807, 0.00079268109, 0.00039650774 }, { -0.00017335252, 0.00074363734, 0.0008194423, -0.00065923207 }, { -0.00075344545, -0.00026114262, -0.00054658657, -0.0013814943 }, { -0.00028279346, 0.00055730283, 0.00048990213, -0.00022186466 }, { 0.00013438509, -0.0001962818, -0.00036195953, 0.00042669461 }, { -0.00089003585, -0.0011600794, -0.0012554286, -0.0012892408 }, { -0.00067007058, -0.0010597247, -0.0010590421, 0.00044132516 }, { 0.0011626727, 0.001261033, -0.00072912018, 0.00076332442 }, { -0.001204702, -0.00011230019, 0.00036178615, -0.0017559004 }, { 0.00096282849, 0.001025959, 0.0011696947, 0.00046633555 }, { -0.00082328571, -0.00075771669, -0.0011629302, 0.00073458863 }, { -0.0016869269, -0.00035239862, -0.0004024204, -0.0016276971 }, { 0.00029053123, 0.00013409355, -0.00049087974, 0.00061969429 }, { -0.0013198997, -0.0018615784, -0.0025724061, -0.0015563017 } } } }, { { { { -0.072246889, -0.043157285, 0.043289306, 0.095998047 }, { 0.12597079, 0.24289541, -0.10930005, -0.24150539 }, { 0.031889347, -0.036238337, -0.014521983, -0.018963885 }, { -0.044155351, -0.0077170425, -0.043781059, 0.047982339 }, { 0.093995001, -0.0079510758, -0.04688882, -0.11125523 }, { 0.01700754, -0.0034361033, 0.055252382, -0.053119426 }, { -0.0014957087, -0.00063057103, 0.037930463, 0.017656646 }, { -0.017388477, -0.084085888, -0.067726647, 0.061397079 }, { -0.070625168, -0.061293011, -0.077366932, 0.11518646 }, { -0.14771316, -0.12543895, 0.052150789, 0.10530462 }, { -0.03609139, 0.001131616, -0.039549928, 0.03805765 }, { 0.064364205, 0.066758929, 0.045537002, -0.05510954 }, { 0.049051369, 0.098312455, -0.01079726, -0.11202623 }, { 0.033012208, -0.0013996988, -0.0049458824, -0.028981527 }, { 0.008617177, -0.00017670863, -0.0052380282, -0.0023438457 }, { -0.05901498, -0.050754807, -0.00011829844, 0.037297411 }, { -0.056264446, -0.03645315, -0.066412698, 0.019549244 }, { -0.11401603, -0.11856524, 0.12275022, 0.11635143 }, { -0.0011999881, -0.0016334327, -0.0056868938, 0.013393766 }, { 0.054526972, 0.033632235, 0.062591094, -0.0025531074 }, { 0.073041316, 0.073735243, -0.06935254, -0.11214186 }, { 0.034872822, -0.015473423, 0.037359975, -0.026829465 }, { -0.015137592, -0.0064462553, 0.011771178, 0.0025042048 }, { -0.038708904, -0.033968131, -0.044070885, 0.024422773 } }, { { -0.047895007, -0.016535938, 0.04855533, 0.018341613 }, { 0.004310087, 0.01519838, -0.0033290683, -0.013597406 }, { 0.0015859181, 0.016869623, -0.019279963, -0.01426933 }, { -0.0061048976, 0.031131561, 0.018085381, -0.017927117 }, { 0.052590378, 0.0066156852, -0.0025756141, -0.037241705 }, { 0.0083512619, 0.0046235666, 0.024122126, -0.013443654 }, { 0.0010672274, 0.00053123301, -0.0016276029, -0.04221993 }, { -0.0048754166, -0.021474788, -0.0039993317, 0.011831691 }, { -0.054685347, -0.050242732, -0.007606251, 0.043061893 }, { -7.5644942e-05, 0.00086632318, 0.0001960729, 0.0013264286 }, { 0.0042413724, -0.0057181522, 0.0065940983, -0.0078263328 }, { 0.0031260881, -0.0013520907, 0.025073658, -0.010841673 }, { 0.038353769, 0.06620308, -0.0072105562, -0.079188681 }, { 0.003099559, -0.0022927921, 0.021982683, -0.018991144 }, { 0.012285675, 0.0091834074, -0.0041874571, -0.032253924 }, { -0.014563556, 0.009843969, -0.010490279, 0.012979866 }, { -0.005492286, 0.064109426, -0.034795617, -0.020395732 }, { -0.023364141, -0.059336321, 0.080710391, 0.038948527 }, { 0.0028384819, 0.001822471, 0.0012903958, 0.012781079 }, { -0.004510518, -0.0020008272, 0.0017752876, 0.0077607089 }, { 0.032279653, 0.0041906079, -0.034682371, 0.0061335907 }, { -0.0082992317, -0.025250117, -0.017026845, -0.028345042 }, { -0.013132125, -0.026688493, -0.0014827793, -0.003236826 }, { 0.01650781, 0.002313574, -0.012897922, 0.026077933 } }, { { 0.062668058, 0.0081578851, 0.018952049, -0.012267283 }, { 0.0008567722, 0.0033246009, -0.0037620102, -0.0096317368 }, { -0.0083012273, 0.01184624, -0.01209373, 0.020208536 }, { 0.013862003, 0.019166381, 0.013235471, -0.026788736 }, { -0.021904217, -0.051018749, 0.0020330268, 0.006626371 }, { -0.015856131, 0.0028024655, -0.032825412, -0.018920906 }, { 0.0020870233, 0.0011616727, -0.0032704368, -0.027327141 }, { 0.01934969, 0.002427195, 0.049925128, -0.0061414889 }, { 0.013158375, 0.022248445, 0.040266734, -0.017583455 }, { 1.9024812e-05, 0.00071602053, 0.0012622199, 0.0018791611 }, { -0.0011857767, 0.0023417924, 0.026237548, -0.014687892 }, { -0.041419782, 0.024942194, -0.029143101, 0.036590943 }, { -0.015470651, -0.035208671, -0.038530514, 0.037434376 }, { -0.0029356279, 0.0023358079, 0.017641055, 0.0038203652 }, { -0.0030449623, -0.010187444, 0.0066142145, 0.0037433206 }, { 0.0080034603, 0.011463159, -0.0058129532, 0.011831147 }, { -0.0091743137, 0.045949289, 0.022412137, -0.0067531419 }, { 0.00069946656, -0.0068974782, 0.0091806954, 0.0022160793 }, { -0.0027530077, 0.00089797627, 0.0066153093, -0.010355635 }, { -0.019399018, -0.0085762573, 0.0208003, -0.027739023 }, { -0.014354809, -0.011971089, -0.0031124986, 0.044710091 }, { -0.011411144, 0.0073253411, -0.0087561348, -0.014838738 }, { 0.018837992, 0.00231775, -0.013982978, -0.0020044658 }, { 0.0012069362, 0.0012202952, 0.029106153, 0.00062793994 } } }, { { { 0.054154158, -0.11603661, -0.025631275, 0.054671866 }, { -0.2359715, 0.093194255, 0.21874866, -0.08378526 }, { 0.0089903397, 0.0087113885, -0.015445726, 0.011142042 }, { -0.0055372249, -0.0041494086, -0.033355186, -0.010136823 }, { -0.015010227, -0.0077144008, 0.13058394, -0.016779666 }, { -0.015855009, 0.014090685, 0.026549575, 0.025677527 }, { -0.00065423811, -0.0011506403, 0.028628751, 0.0086359197 }, { -0.010571292, 0.035861454, -0.025871285, -0.024827688 }, { 0.00010603924, 0.011433504, -0.052819957, -0.020208661 }, { 0.12243361, -0.14574398, -0.10091072, 0.054524772 }, { -0.014659734, -0.02291001, 0.010102434, -0.0099333349 }, { -0.0079939087, 0.023468399, 0.044548395, 0.04568814 }, { -0.048188816, 0.016469102, 0.084818672, -0.040634065 }, { 0.015089138, 0.025396216, 0.017000121, 0.010820807 }, { -0.0098155552, -0.00080001495, 0.0020122754, -0.00046896909 }, { -0.0018906417, -0.03909342, -0.020339049, -0.024007559 }, { -0.0012744487, -0.027829333, -0.05202457, -0.024366779 }, { 0.10406956, -0.092281421, -0.050420166, 0.10716663 }, { -0.0049603976, -0.0055370076, -0.0016910106, 0.012172389 }, { -0.0026486448, 0.038673757, -0.0016176887, 0.052692494 }, { -0.03722357, 0.055455783, 0.067738953, -0.0087990582 }, { -0.0026491637, 0.017275247, 0.010687117, 0.020312052 }, { -0.0016032469, 0.0090272843, -0.0079027514, -0.0050039898 }, { -0.0073653412, -0.033150577, 0.0082912493, -0.021457881 } }, { { -0.0059001999, 0.033600833, 0.066374213, -0.018058548 }, { -0.0037864945, -0.0064946131, 0.0018627774, 0.0044899139 }, { 0.0048961861, -0.0034770968, -0.0002311598, -0.0053935761 }, { 0.0090090757, 0.012149811, 0.0029969663, 0.0049403543 }, { -0.042874682, -0.0083455851, -0.0064437344, 0.0010579362 }, { 0.011866873, -0.017157526, -0.014724976, 0.0054373752 }, { -0.0006329516, -0.00024834697, 0.0015416168, -0.014246989 }, { 0.031530357, -0.052715858, -0.0063186617, -0.0070200141 }, { -0.0082273844, 0.053856605, 0.0096812384, 0.01684635 }, { -0.00017150577, 0.00097354737, 0.0013944706, 0.00085166684 }, { -0.013604545, 0.0089329355, -0.013809086, 0.0025044469 }, { -0.020284731, 0.0004724419, -0.045697697, -0.01844702 }, { 0.017874081, -0.0040537465, -0.023316716, -0.026344708 }, { 0.0092557469, -0.014456327, -0.0092919835, 0.0091758924 }, { 0.016058873, 0.0019220807, 0.0031692823, 0.0024577167 }, { -0.021184352, 0.021287579, -0.0048442696, 0.0095799112 }, { 0.035229915, -0.054291919, -0.013871324, 0.035585241 }, { 0.001275203, 0.011513119, 0.020184769, -0.0061701639 }, { 0.011353237, 0.0052697685, 0.0047637419, -0.020278005 }, { 0.0068266296, -0.01173749, 0.037482577, -0.0083236299 }, { 0.025699221, -0.03651135, -0.032342446, -0.0059784486 }, { 0.0029540635, -0.0021598269, 0.0028168477, 0.0044577193 }, { 0.0038274002, -0.0050806333, 0.007628551, 0.0027461742 }, { 0.0056567464, 0.006846664, -0.031161558, -0.0040832656 } }, { { 0.025668431, 0.0093723617, 7.4324163e-05, -0.023051436 }, { -0.010148124, 0.0018159908, 0.0072269566, 0.00082671261 }, { 0.0069741056, 0.023493533, 0.028507618, -0.026874125 }, { 0.0083316277, -0.024891629, 0.013623217, 0.0038373532 }, { -0.020992516, 0.070912136, -0.0014634877, -0.015680371 }, { 0.02178962, -0.003772636, -0.024578501, -0.047467019 }, { 0.0028586275, 0.0033445767, 0.0049576063, -0.017365739 }, { 0.0075721122, 0.010652219, -0.024031886, -0.0001146548 }, { 0.016381176, -0.044765924, -0.038036229, -0.014041395 }, { -0.00082564842, 0.00033107944, 0.00073792054, 0.0005712734 }, { 0.0080934887, 0.014534447, -0.0071347609, 0.0085413493 }, { -0.018211778, 0.0064443848, 0.017393403, 0.011490985 }, { -0.071531366, 0.030059694, 0.049103287, 0.0074609412 }, { 0.00770209, -0.017999995, -0.040048679, -0.0029073853 }, { 0.020442166, 0.0019454488, -0.019644905, 0.021793285 }, { 0.035171271, 0.0080192155, -0.023151504, 0.014168348 }, { -0.048901887, -0.0039613606, 0.0021703807, 0.030275152 }, { 0.044666116, -0.029756153, -0.015570779, 0.034470632 }, { -0.0078700362, 0.0037551741, 0.0003070052, -0.0031237403 }, { 0.015288427, -0.01284757, -0.0075319169, 0.026981487 }, { -0.0093872483, 0.013517073, -0.030221944, 0.058356065 }, { 0.0042326205, -0.016381154, 0.021475001, 0.01008732 }, { 0.0034929117, 0.020531314, -0.0085114063, 0.004821913 }, { 0.014314413, 0.01127037, -0.017197896, 0.0046932185 } } }, { { { 0.99591552, 0.99230689, 0.99873374, 0.99387895 }, { 0.96356049, 0.96556546, 0.96964041, 0.96677566 }, { 0.99945097, 0.99930521, 0.99977525, 0.99975808 }, { 0.99900933, 0.99996161, 0.99848418, 0.99879675 }, { 0.99545951, 0.99993863, 0.99032786, 0.9936502 }, { 0.99972964, 0.99989482, 0.99811938, 0.99825798 }, { 0.99999867, 0.99999914, 0.9988702, 0.99980681 }, { 0.99979292, 0.99581299, 0.99736843, 0.99780458 }, { 0.99750292, 0.99805433, 0.99560254, 0.9931383 }, { 0.98142286, 0.98133774, 0.99352772, 0.9929441 }, { 0.99924096, 0.99973689, 0.99916652, 0.99922617 }, { 0.99789446, 0.9974931, 0.99796885, 0.99743448 }, { 0.9976331, 0.99501931, 0.9963379, 0.99287411 }, { 0.99934104, 0.99967648, 0.99984325, 0.99952138 }, { 0.9999147, 0.99999966, 0.99998426, 0.99999714 }, { 0.99825531, 0.99794572, 0.99979313, 0.99901579 }, { 0.99841509, 0.99894779, 0.99643504, 0.99951192 }, { 0.98801309, 0.98864879, 0.99115599, 0.98740957 }, { 0.99998698, 0.99998334, 0.9999824, 0.99983621 }, { 0.99850879, 0.99868574, 0.99803794, 0.99860752 }, { 0.99663402, 0.99573479, 0.99528974, 0.99365325 }, { 0.99938825, 0.99973103, 0.99924472, 0.99943364 }, { 0.99988413, 0.99993848, 0.99989949, 0.99998434 }, { 0.99922338, 0.99887297, 0.998994, 0.9994714 } }, { { -0.0050599833, 0.003362263, 0.0035202243, -0.00056864904 }, { -0.0014675187, -0.0029154981, -0.00077796172, -0.0027392627 }, { -0.0010916411, 0.00078232803, 0.0014339533, -0.0020166729 }, { 0.011183745, 0.008298699, 0.011631254, 0.00030693508 }, { -0.0012964861, -0.00028098882, 0.00098513135, -0.0052243577 }, { 0.0091119501, 0.002780703, 0.011045274, 0.00334383 }, { 4.1103001e-05, 5.5767744e-05, 0.0030605577, 0.0022152241 }, { 0.00085375099, 0.0026952672, 0.0071937971, 0.0056504112 }, { -0.003773118, 0.0047936307, -4.5743022e-05, -0.0038357994 }, { 2.3815581e-05, 0.0002468657, 0.00013492048, -0.00018410816 }, { 0.0070959632, -0.00205589, 0.0056417297, 0.0030702073 }, { 0.010671769, 0.0074346008, 0.0012867659, 0.0075437523 }, { -0.0013037272, -0.0058374269, 0.0025899757, -0.0071565118 }, { 0.0030041304, 0.0018011397, 0.0093160386, 0.0082062863 }, { 0.0053156934, 0.0036543193, 0.0048724246, 0.0035118324 }, { -0.0053866158, 0.0024053442, 0.00052459148, 0.0090970513 }, { 0.011239324, -0.0010327051, -0.00097551594, 0.0044180668 }, { -0.0024379533, -0.0088232426, -0.012355568, -0.0031875953 }, { 0.0026244123, 0.0011858999, 0.0028110843, -0.001005442 }, { 0.0059514328, 0.0018892606, 0.0050231625, 0.0046700575 }, { 0.00050741664, 0.0096547476, -0.00079618251, 0.0024532112 }, { 0.0058717468, -0.0017457656, 0.0080261577, -0.00048009588 }, { 0.0025457914, 0.0016788968, 0.0013982313, 0.00073909928 }, { 0.0075035778, 0.011234409, 0.0079271096, 0.006672353 } }, { { 0.0095152396, 0.0011785006, -0.00081996856, 0.0018904938 }, { -0.0025430397, -0.0010236291, -0.0020168276, -0.0021827861 }, { 0.0036295778, 0.005406882, 0.0040788276, -0.0057729163 }, { -0.00029952998, 0.0024548208, 0.0088548836, 0.0019084209 }, { 0.0034184324, -0.0088925589, 0.00023040452, 0.00017437939 }, { 0.0037804595, 0.012156355, 0.0041276361, 0.012721488 }, { 7.4846461e-05, 0.00010580108, 0.013483417, 0.0024239851 }, { 0.00026411032, -0.00059353627, 0.0093564271, 0.0061507538 }, { 0.0016065383, -0.0027764641, 0.0013620195, 0.0010062065 }, { 9.7127925e-05, 0.00017275393, 1.0814607e-05, -0.00022627793 }, { 0.0048710612, -0.00014794569, 0.0082832436, -0.00072595412 }, { -0.0027392579, 0.0066783951, 0.00087397132, 0.001567366 }, { -0.003378151, 0.0025916338, -0.0025553201, 0.0030152022 }, { 0.0096818399, 0.0012695523, 0.0072489949, 0.016881099 }, { 0.0022796191, 0.0051693266, 0.0023373397, -0.0041448561 }, { -0.0002074582, 0.0035962454, -0.0007460719, 0.0025086317 }, { 0.0035784996, 0.003162753, 0.0022592918, 0.00024595998 }, { -0.0051294944, -0.0041428868, -0.0027597, -0.0039539398 }, { 0.0022410392, 0.00031263884, 0.0016376751, -0.0022787113 }, { 0.0025647038, 0.0074733037, 0.0051722028, 0.0024463612 }, { 0.0011787227, 0.0071159753, 0.0017217143, 0.0062717989 }, { 0.0046836737, 0.0038976423, 0.00062832002, 0.0027638154 }, { 0.0014142926, 0.0024903802, 0.0015757227, 0.0011628587 }, { 0.0016928585, 0.0043828548, 0.001653268, 0.011450696 } } }, { { { 2.8886078, 2.8900127, 2.7925705, 2.7895874 }, { 4.5455217, 4.5284714, 4.7042338, 4.6915273 }, { 0.96672505, 0.99303664, 0.98927606, 1.0351588 }, { 1.2743756, 1.2525364, 0.99649566, 0.94572778 }, { 2.6910679, 2.6922168, 2.8503404, 2.8246076 }, { 1.256075, 1.2325025, 1.5911826, 1.6091223 }, { 1.3601759, 1.3606869, 1.2793533, 1.240925 }, { 2.0291828, 2.0506809, 1.7341658, 1.6555689 }, { 2.6663531, 2.6921882, 3.1290975, 3.11849 }, { 5.3676887, 5.3663279, 5.3848664, 5.3852162 }, { 1.0586431, 1.0865889, 0.8196623, 0.8076665 }, { 1.6967251, 1.7305944, 1.5450413, 1.6347879 }, { 3.0908857, 3.0706775, 3.2974343, 3.3053965 }, { 1.2172073, 1.3839086, 1.5086796, 1.4295506 }, { 0.97676668, 1.0856738, 0.98747912, 1.0385491 }, { 1.5662275, 1.4603538, 1.784278, 1.6575438 }, { 2.1085757, 2.2092885, 2.1410448, 2.1518347 }, { 4.0214776, 4.006424, 3.7686967, 3.7771354 }, { 1.2089239, 1.2116036, 1.1244311, 1.0901017 }, { 1.1827246, 1.1472796, 1.7516784, 1.7833976 }, { 2.2113439, 2.197512, 2.2692963, 2.2787751 }, { 0.98819531, 1.057833, 1.3587301, 1.3890421 }, { 1.208957, 1.2247867, 1.2301205, 1.2325178 }, { 1.0499613, 1.1319197, 1.4067885, 1.3209087 } }, { { -0.002860931, -0.0033581281, -0.0047612075, -0.0030481839 }, { -0.0017370907, -0.0065700936, -0.0011051926, -0.0046915938 }, { -0.0006126207, 0.0010791181, -0.022876686, -0.015937275 }, { -0.010040922, -0.016433531, -0.0044976975, -0.029838315 }, { 0.00056888968, -0.0093450028, -0.00041549218, -0.0069079656 }, { -0.029781683, -0.019722587, 0.019472312, 0.0016798037 }, { -0.0015128736, -0.0012250172, -0.0091568262, -0.0091368119 }, { 0.0010846814, 0.0017189068, 0.012975603, -0.0051530971 }, { -0.026042808, -0.0090684857, -0.0021498742, -0.0032938309 }, { -0.0012792901, -0.0010431731, -0.0021366737, -0.0025526365 }, { -0.03218779, -0.013848893, -0.021872476, -0.029443623 }, { 0.008300061, 0.011951182, -0.011139414, 0.0098292843 }, { -0.0065854884, -0.020955083, -9.3843515e-05, -0.0078425688 }, { -0.054726229, -0.0073673428, -0.019267231, -0.03383648 }, { -0.049769726, 0.0065482059, -0.010189395, -0.0050480393 }, { 0.022565943, -0.020311569, 0.0091512717, -0.015600752 }, { -0.014418429, 0.0060070592, -0.0055296743, -0.003361885 }, { 8.8146509e-05, -0.0082609252, 0.0036746024, 0.0040108321 }, { 0.0010230427, 4.8153189e-06, 0.0052893378, -0.0096303521 }, { 0.0032909351, -0.010982824, 0.003880027, 0.0097699095 }, { -0.006528317, -0.012608887, -0.0057088008, -0.003867806 }, { -0.046599771, -0.024701737, -0.001078321, -0.0041018649 }, { -0.021680777, -0.021120711, 0.0055144734, -0.0031337995 }, { -0.030559213, 0.0089872726, -0.011166202, -0.0077587071 } }, { { -0.0059548858, -0.0040070313, -0.0062572119, -0.0047711065 }, { -0.0031938803, -0.005431389, -0.0026376521, -0.0046119366 }, { 0.0064917253, 0.013030824, -0.027850471, -0.011824849 }, { -0.032644485, -0.025045016, -0.0034396539, -0.039827623 }, { -0.007691681, -0.014095643, -0.0008171964, -0.0051336386 }, { -0.035626586, -0.021424668, 0.00035790929, 0.0099705685 }, { -0.0019006762, -0.0014887089, -0.0050782898, -0.0096835564 }, { -0.00087496879, 0.0052586834, 0.017041675, -0.00046753956 }, { -0.022489507, -0.0084834888, 0.0017184219, -0.0023910992 }, { -0.0010618265, -0.00085888729, -0.0020035777, -0.0024245283 }, { -0.029245834, -0.038977066, -0.013385246, -0.030312138 }, { -0.0028497869, 0.014205986, -0.0125692, 0.0037959624 }, { -0.0086377959, -0.019175965, -0.007684309, -0.005037677 }, { -0.063945685, -0.0060751259, -0.0057457302, -0.019079575 }, { -0.043745147, 0.013651906, -0.034067394, 0.0012111497 }, { 0.0086647574, -0.019171418, 0.020745219, -0.0055629951 }, { -0.024541273, 0.0072112135, -0.0078821942, -0.0085072621 }, { -0.0018227939, -0.0021153099, 0.008577002, 0.0043865151 }, { -0.013984752, -0.012209334, 0.00023638151, -0.0085025952 }, { -0.0099800075, -0.0095390578, 0.0081328135, 0.012673433 }, { -0.0099975551, -0.0028467616, -0.010712056, -0.0045012212 }, { -0.011329139, -0.0084709831, -0.0070232966, 0.0015504012 }, { -0.015334801, -0.0075637633, -0.01107439, -0.0094188163 }, { -0.017505269, -0.00013701888, -0.033955823, -0.034192649 } } }, { { { 0.16413327, 0.084074422, 0.10646123, 0.18806073 }, { 0.039511019, 0.058967072, 0.035166958, 0.052296507 }, { 0.26970995, 0.21576211, 0.2954278, 0.29870678 }, { 0.40442043, 0.38744132, 0.14502571, 0.24076804 }, { 0.22655046, 0.20912486, 0.015295019, 0.16442957 }, { 0.69235319, 0.6080183, 0.36756076, 0.23314717 }, { 0.085565328, 0.075535626, 0.22162979, 0.33140596 }, { 0.16109547, 0.11961895, 0.26619212, 0.25941009 }, { 0.27077686, 0.23481238, 0.063446408, 0.11614487 }, { 0.026116057, 0.027491327, 0.030421883, 0.039965345 }, { 0.33922592, 0.38039792, 0.27167385, 0.31510976 }, { 0.32744968, 0.22567102, 0.23116584, 0.18867836 }, { 0.29783431, 0.28054079, 0.26752139, 0.23889932 }, { 0.61721263, 0.60602797, 0.51283622, 0.47601102 }, { 0.51383952, 0.53111455, 0.44519064, 0.42875877 }, { 0.3485879, 0.35374178, 0.53292055, 0.53995494 }, { 0.4366997, 0.35554257, 0.14878367, 0.22083288 }, { 0.12855375, 0.16718264, 0.17583661, 0.11125895 }, { 0.35898096, 0.37222307, 0.35439108, 0.35956111 }, { 0.16773044, 0.25668894, 0.23246756, 0.1506316 }, { 0.36172813, 0.26938211, 0.20069185, 0.1714591 }, { 0.3998571, 0.23607244, 0.34121623, 0.29126696 }, { 0.31471307, 0.29500525, 0.39451396, 0.40013999 }, { 0.29554399, 0.28083636, 0.47190649, 0.47892938 } }, { { 0.01419653, -0.061214452, -0.032506906, 0.0078227125 }, { -0.015799432, 0.0136148, -0.0090824684, 0.013638505 }, { 0.023848919, 0.022034707, 0.022812846, 0.022790329 }, { -0.0026324255, -0.0053566952, 0.00027470228, 0.050203583 }, { 0.0035659857, -0.02015272, -0.039043616, 0.054511651 }, { 0.0052075445, 0.0051043119, -0.011801097, -0.0074336577 }, { 0.020735195, 0.01811747, 0.00808952, 0.01140964 }, { -0.0073139049, 0.011075347, 0.0057685988, 0.010251582 }, { 0.024813488, -0.01629986, -0.012536791, -0.01110061 }, { -0.014508648, -0.021444084, -0.023836972, -0.014258253 }, { 0.0079687141, -0.00092011446, 0.060249601, 0.033199468 }, { -0.020822483, -0.013924875, -0.005068391, -0.016928794 }, { -0.030059, -0.013887475, -0.045329289, -0.04449219 }, { 0.007264541, 0.0015213919, -0.0066322618, -0.0036449174 }, { 0.0057175046, 0.0012159867, -0.00054271896, 0.0020625484 }, { 0.0027083179, -0.0012554897, -0.0044854592, -0.0045242423 }, { -0.017906563, -0.028301884, -0.010139427, 0.0035851304 }, { -0.020245794, 0.01149232, 0.011320484, -0.013561794 }, { 0.0068048997, 0.011957759, 0.0046962412, -0.0015476541 }, { -0.0022514613, 0.019996868, 0.0051520398, -0.023405604 }, { 0.0055213198, 0.0070384134, 0.024405643, -0.02050399 }, { 0.039987541, 0.021127504, -0.012323503, -0.0041538161 }, { 0.0072321478, 0.0053097351, 0.0039966161, 0.013617175 }, { 0.030470642, 0.0044694115, -0.0024591651, -0.0027274707 } }, { { -0.040500402, -0.039657034, -0.017497359, -0.017857145 }, { -0.0015646885, -0.020957371, -0.0057356498, -0.0060587007 }, { 0.0070388709, -0.013205178, -0.00033412934, 0.02192306 }, { -0.0042317723, 0.020620857, -0.012309167, 0.065948811 }, { -0.016686589, 0.013616667, 0.030139062, -0.019023551 }, { 0.015181564, 0.008673659, -0.0014559576, -0.025916054 }, { 0.031630671, 0.027030197, -0.026982415, 0.025214731 }, { -0.003845127, -0.00062884599, -0.029488655, -0.0051457939 }, { -0.0032476351, 0.0021153707, -0.033110808, -0.033629213 }, { -0.0064637077, -0.010805748, -0.014982403, -0.0084641529 }, { 0.0087766042, 0.017780238, 0.026838871, 0.032580257 }, { 0.0010700985, -0.037414784, -0.0053773565, 0.0040969752 }, { -0.02637392, -0.050236074, -0.048422986, -0.069357813 }, { -0.0089483588, 0.0026259727, 0.0040142797, -0.010752754 }, { -0.0025658872, 0.0071106029, 0.015467367, 0.0012536589 }, { -0.0037247444, -0.0036991733, -0.015429566, -0.016148852 }, { -0.024788221, -0.045938054, -0.028679471, 0.011593494 }, { -0.032699114, -0.036800967, -0.033870575, -0.031842203 }, { 0.018156047, 0.02457546, 0.0209432, 0.015057433 }, { 0.0043152638, 0.025831372, -0.019608349, -0.026614397 }, { -0.0057047815, -0.013831909, 0.027613211, -0.043616864 }, { 0.014124478, -0.010786326, 0.010775415, -0.023241344 }, { 0.018337827, 0.0048735321, 0.018371717, 0.022106807 }, { 0.013619207, 0.022051384, 0.0082720974, -0.0030262071 } } } }, { { { { 0.083322661, 0.079807165, 0.03660117, -0.051657142 }, { -0.099216074, -0.0080141573, 0.10637241, 0.0367403 }, { 0.20813681, -0.0001361621, -0.20762563, -0.085913357 }, { -0.22091149, 0.10003156, -0.16122219, 0.31542901 }, { 0.16226908, 0.02665194, -0.012123307, -0.16559939 }, { -0.14025496, 0.025804505, 0.076174345, 0.20548591 }, { 0.0035713609, -0.0092551928, -0.099937652, 0.0038879391 }, { 0.12405732, -0.0053373497, -0.030865175, -0.060934551 }, { -0.0060175826, -0.026583926, -0.075326797, -0.0063155886 }, { 0.036389362, 0.054175433, 0.06490927, -0.038784258 }, { 0.30604876, -0.030813476, 0.011402956, -0.21074796 }, { -0.31769497, 0.046793931, -0.038212559, 0.21137297 }, { 0.12952945, 0.20720126, 0.08525845, -0.14568109 }, { -0.09735197, -0.17799099, -0.12256082, 0.038889119 }, { 0.002114572, 0.026037779, -0.0036772795, 0.13478173 }, { 0.094577863, 0.0057382415, -0.087017736, -0.059444148 }, { 0.054953104, 0.071323301, 0.097417831, 8.3254475e-05 }, { -0.11005534, 0.027214076, 0.0059378205, 0.02443999 }, { 0.27096654, 0.1864966, 0.034810947, -0.25886676 }, { -0.35626794, 0.037256657, -0.17795321, 0.52988269 }, { 0.14913899, -0.0086988732, -0.028760192, -0.21779266 }, { -0.16010301, -0.17699785, 0.017269826, 0.17878541 }, { -0.0049504093, -0.02387924, -0.04034852, -0.060461173 }, { 0.10405347, 0.0072745723, -0.10244372, -0.072981984 } }, { { 0.019363393, 5.327311e-05, 0.0075925373, 0.0019542034 }, { -0.051707557, 0.06554253, 0.0050626046, -0.0061857803 }, { 0.022891698, 0.014872273, -0.020436928, 0.0069081531 }, { -0.044566611, 0.019854557, 0.023600607, -0.0055387351 }, { 0.02283957, -0.067086756, 0.088865856, -0.033915007 }, { 0.0020254431, -0.16422426, 0.032495902, 0.012460808 }, { -0.017316175, 0.023440087, 0.011459595, 0.0043887872 }, { 0.027714908, -0.06907548, 0.013578806, -0.009848884 }, { 0.0044782488, 0.0079432606, 0.010143137, 0.023589488 }, { 0.014325082, 0.0075465848, -0.0079373813, -0.0056032635 }, { 0.025123579, 0.01904807, -0.0092328848, -0.019002052 }, { -0.02633985, -0.019560519, -0.065544737, 0.0073352606 }, { 0.044308433, -0.0032233834, 0.01324206, -0.00047128106 }, { -0.076577611, -0.021853603, -0.020190543, 0.0026420865 }, { -0.0029799448, -0.0083566545, 0.14896601, 0.0078617095 }, { 0.021033237, -0.08234711, -0.020642328, -0.0089829962 }, { 0.043793881, 0.0096494147, 0.035831274, -0.01294602 }, { -0.014064874, 0.066144489, 0.0143429, 0.015113964 }, { 0.043111732, 0.0029232804, -0.016912145, 0.012142059 }, { 0.0014186333, -0.0078590166, 0.065781153, -0.038375123 }, { 0.02255714, -0.030191796, -0.078373164, -0.0017593196 }, { -0.033878798, 0.016266579, 0.013539653, 0.043519216 }, { 0.019046482, 0.0080403173, -0.0010755939, 0.03305222 }, { 0.023206448, -0.054323067, -0.035173093, -0.010873592 } }, { { 0.014068291, -0.026418786, 0.016375695, 0.0048801469 }, { 0.024404214, 0.0073572002, -0.027247654, 0.00093849398 }, { 0.012741523, -0.012913063, 0.0054881373, -0.021780769 }, { -0.020497215, 0.057437717, 0.0031122704, 0.014713732 }, { 0.012765254, -0.052846334, 0.048042201, 0.0016578534 }, { 0.031245254, -0.0469321, -0.057199738, 0.012436479 }, { -0.0022837759, 0.0068501747, 0.010541107, -0.0005227683 }, { -0.0187059, 0.0025631581, -0.0082184266, 0.0026294483 }, { 0.0053899388, -0.0199458, 0.0023448066, 0.016215236 }, { 0.021117204, 0.010868775, -0.016412681, -0.016399297 }, { -0.0026199223, -0.011436548, 0.0031355049, 0.011933919 }, { 0.017940023, 0.090292392, -0.061029038, 0.016388845 }, { 0.0074493061, -0.045849358, -0.082612855, 0.025851315 }, { 0.061276666, -0.024654813, 0.035447334, -0.025952766 }, { -0.0068267167, -0.02207426, 0.003724368, 0.0070458116 }, { 0.021714649, -0.017552721, -0.037105408, 0.024398534 }, { 0.0092901891, -0.021559075, 0.009034776, -0.016574279 }, { -0.017218595, -0.041930302, 0.003369899, 0.017959363 }, { -0.0022510875, 0.028106616, -0.042936548, -0.041948028 }, { -0.017145551, -0.032331654, 0.021486923, -0.020295391 }, { -0.023196465, -0.088353584, 0.010086154, 0.018689553 }, { -0.024508386, -0.00058959302, -0.02867958, 0.019018994 }, { 0.0088748911, 0.012528454, -0.016636351, 0.0078166115 }, { 0.00066772723, 0.001693912, 0.032066885, 0.016951148 } } }, { { { 0.015200105, 0.071414961, -0.020616434, 0.0063982643 }, { -0.084578144, -0.12318522, -0.035470756, 0.057833574 }, { 0.19487946, 0.44043059, 0.10981527, -0.31907303 }, { -0.17774238, -0.30460726, -0.53133003, 0.31186606 }, { -0.1172677, 0.3183613, 0.10375266, -0.066515168 }, { 0.054176263, -0.12382077, -0.033807438, 0.039809238 }, { -5.3634009e-05, 0.004084452, 0.005103199, -0.060697866 }, { 0.06093199, 0.060355274, 0.049176467, -0.060579228 }, { 0.054611799, 9.0520863e-05, -0.048891261, -0.047609349 }, { -0.036428706, 0.06336736, 0.0020843807, 0.033254378 }, { 0.26975732, 0.51328693, 0.29976157, 0.049031141 }, { -0.28383516, -0.48219276, -0.27898799, -0.033028759 }, { -0.078976834, 0.14077934, 0.098587186, 0.051336328 }, { 0.076281206, -0.074223398, -0.053178835, -0.099578331 }, { -0.056377095, -0.00066113896, -0.11597726, 0.058805777 }, { -0.0027130032, 0.12007881, 0.0081935835, -0.10415807 }, { -0.019349408, 0.06206561, -0.0079099126, 0.079363093 }, { -0.059959607, -0.0591041, -0.047505451, -0.0031496967 }, { -0.11419194, 0.20904287, 0.53960104, 0.10467592 }, { -0.21312862, -0.34770872, -0.54593093, 0.23230512 }, { -0.073229448, 0.12913, 0.27728133, -0.050627706 }, { 0.082312471, -0.24529296, -0.12381516, 0.05577292 }, { 0.03015389, -0.0015805638, 0.024306632, -0.080697961 }, { 0.061367564, 0.056058289, 0.041197211, -0.015551356 } }, { { -0.029269776, -0.030251548, 0.01352869, 0.0084860712 }, { 0.053983187, 0.047657625, -0.026379004, 0.022474039 }, { 0.011898439, 0.045120742, -0.024430477, -0.081318878 }, { -0.0012641508, -0.018495044, -0.030127865, -0.0088483264 }, { 0.040728292, 0.010691761, -0.023566342, 0.028045232 }, { 0.014593998, 0.0047006468, -0.049032498, -0.011446808 }, { 0.00045433705, -0.0030610749, -0.010359449, -0.0026455857 }, { -0.0026794352, -0.032142744, 0.010153936, -0.0034586152 }, { 0.0097198782, 0.0051005644, 0.03482872, -0.0043676475 }, { -0.0012381415, -0.025746274, -0.0081178021, 0.0041481596 }, { -0.01598781, 0.0048815642, 0.06313106, -0.0062291669 }, { 0.072970618, -0.041153529, -0.007457013, 0.059776924 }, { 0.0024768493, 0.0093018711, 0.024827984, 0.043842172 }, { -0.012927661, -0.023256709, -0.0035951539, -0.069710027 }, { 0.0064149713, 0.0019783425, 0.010135188, 0.019449636 }, { -0.0071551675, 0.015761815, 0.0086309278, 0.038854386 }, { 0.020978109, -0.0056696814, 0.0025526797, -0.017352926 }, { -0.010711116, -0.0097050903, 0.0022304504, -0.0039308489 }, { 0.036904234, 0.025927127, 0.028330671, 0.051193417 }, { -0.00076391153, -0.077528792, -0.029763477, 0.0033945843 }, { -0.01775202, 0.034507636, 0.065392848, -0.017840909 }, { -0.019567742, -0.019880035, 0.055214211, -0.02206159 }, { 0.01110111, 0.0022938832, -0.011417507, 0.017692635 }, { 0.050208493, -0.028178909, 0.0065276591, -0.0056267473 } }, { { 0.0065622702, -0.0012303136, -0.0081183663, 0.00079383048 }, { 0.030775912, 0.052260356, -0.019758331, -0.020044147 }, { 0.019016537, -0.043070451, 0.035298744, -0.040592775 }, { 0.010468089, 0.00057085185, 0.0081761984, 0.0033382478 }, { 0.047189462, -0.052695409, 0.021849623, 0.033585939 }, { 0.0012065616, -0.050287476, -0.065085924, -0.039012886 }, { -0.012294892, 0.006839242, 0.0051165438, -2.0711078e-05 }, { -0.03292822, 0.015299577, 0.0029119931, 0.0073040242 }, { -0.0086784873, 0.0085910164, -0.0059378411, -0.010259049 }, { -0.014191355, -0.011172486, -0.01299927, 0.015386671 }, { 0.040453224, -0.041489173, 0.015047889, 0.064340197 }, { -0.020000046, 0.058477092, -0.0018150465, 0.048536972 }, { -0.006105982, 0.03437044, 0.0087640339, 0.032868283 }, { -0.027120362, 0.016579996, -0.01708524, 0.011178424 }, { 0.030535528, 0.0058718219, -0.031240404, 0.024241052 }, { 0.003729958, -0.055735848, -0.0055392842, 0.03447519 }, { -0.04084502, -0.01227488, 0.0062970198, -0.021996031 }, { 0.053671675, -0.067787009, 0.0053426012, -0.0080796738 }, { -0.021911856, 0.038395527, -0.07713235, 0.024805484 }, { -0.0034319194, 0.0052741327, 0.026402991, 0.0012916612 }, { -0.033119652, -0.0046506889, 0.045613946, -0.050230593 }, { -0.0054612035, -0.033482221, 0.084267507, -0.0224334 }, { -0.0063348693, -0.0074524817, -0.0029629355, 0.035493958 }, { -0.0073519185, 0.045139911, 0.0022901735, -0.041385515 } } }, { { { 0.99640669, 0.99424882, 0.99911727, 0.99864438 }, { 0.99146493, 0.99235134, 0.99369348, 0.99764995 }, { 0.95848895, 0.89778665, 0.9720248, 0.943828 }, { 0.95896077, 0.9472107, 0.83168251, 0.89623886 }, { 0.97975356, 0.94759472, 0.99452924, 0.98394744 }, { 0.98863213, 0.99196902, 0.99652121, 0.97785007 }, { 0.99999362, 0.99994883, 0.99498061, 0.99814861 }, { 0.99040248, 0.99816269, 0.99831309, 0.99630173 }, { 0.99848953, 0.99964658, 0.9959596, 0.99884607 }, { 0.9986735, 0.99651874, 0.99788899, 0.99869411 }, { 0.91299789, 0.85766372, 0.953946, 0.97631002 }, { 0.90471405, 0.87481454, 0.959534, 0.97684726 }, { 0.9884254, 0.96811612, 0.9914694, 0.98799879 }, { 0.99232241, 0.98122887, 0.99103524, 0.99426948 }, { 0.99840731, 0.99966074, 0.99324506, 0.98912879 }, { 0.99551377, 0.99274778, 0.99617307, 0.9927827 }, { 0.99830144, 0.99552039, 0.99521214, 0.99684577 }, { 0.99211525, 0.9978808, 0.99885333, 0.99969634 }, { 0.95579147, 0.95995838, 0.84120087, 0.96022443 }, { 0.90975235, 0.9368621, 0.81871367, 0.8156339 }, { 0.98610091, 0.99158952, 0.96035822, 0.97468107 }, { 0.98366238, 0.9531543, 0.99215501, 0.98230604 }, { 0.99953301, 0.9997136, 0.99888998, 0.99490315 }, { 0.99267663, 0.998401, 0.99388534, 0.99721201 } }, { { -0.0021537732, 0.010607958, -0.0066166595, -0.0027390442 }, { -0.0069401807, 0.0053215201, 0.0062121114, 0.013403291 }, { -0.0035740125, -0.021839368, 0.00042431197, -0.029478899 }, { -0.007886159, -0.0087705321, -0.010570968, 0.0040635318 }, { -0.0021772698, 0.00025306776, -0.0092725896, -0.0075657706 }, { -0.010438319, -0.0072866821, 0.009272756, 0.0043932916 }, { -0.00058203184, 0.0081284104, 0.027749999, 0.0035426599 }, { -0.003604276, -0.012244348, 0.0072177908, 0.0026686264 }, { 0.011192179, 0.0069527119, 0.017278396, -0.0053058312 }, { -0.020276487, -0.0063228657, 0.013968347, -0.0021534789 }, { -0.0037534313, 0.00061399133, -0.02126817, 0.0085256452 }, { 0.015620795, -0.022637876, 0.00069280338, 0.0054369037 }, { 0.0095244184, -0.0026896982, -0.0057963534, 0.0067237437 }, { -0.0085689961, -0.004816024, -0.00088793436, -0.0034021999 }, { 0.015428153, 0.019777562, -0.011217833, 0.0095744159 }, { -0.003802304, 0.0022643577, 0.0054254827, 0.025560756 }, { -0.0053298651, 0.021621993, -0.01864184, 0.019120967 }, { 0.015380344, -0.0027384467, 0.0010235928, 0.0062792725 }, { -0.001166873, -0.0049586656, -0.014850883, 0.00057841904 }, { 0.0032865456, -0.033386196, 0.0032068954, 0.02854738 }, { 0.010308266, -0.000233004, -0.020287643, 0.0044441043 }, { -0.0040523345, 0.0050367711, 0.01627907, -0.010032412 }, { 0.0073463987, 0.00073274858, 0.002814661, 0.030221018 }, { 0.0057509063, -0.011441338, 0.01894259, 0.0077856453 } }, { { -0.0053054924, 0.0037677068, 0.0066263851, 0.0011220287 }, { -0.02212139, 0.013769097, -0.0013834097, 0.014152363 }, { -0.0008493126, 0.021473024, -0.0039313241, -0.017764981 }, { -0.00081897848, -0.0074161164, 0.0038179092, -0.0035760615 }, { 0.014045643, 0.015317904, 0.0045966739, 0.0075917156 }, { 0.0035574126, -0.00017773424, -0.0010937491, -0.0017762282 }, { 0.0072018344, 0.012586227, 0.0138702, -0.0085424173 }, { -0.0055783456, -0.019909385, 0.01190919, -0.0065821489 }, { 1.7402026e-05, 0.0094513341, 0.015333305, -0.0072158969 }, { -0.0063049905, 0.0021776758, 0.014376378, 0.0072426401 }, { -0.0078049673, 0.028764242, -0.0024169449, 0.0077604105 }, { 0.00047536469, 0.029806623, 0.0017798261, 0.00087410198 }, { -0.0030498401, 0.0044874501, 0.0020382571, -0.0011101062 }, { -0.0057084397, -0.0013428994, -0.001024136, 0.0066188614 }, { 0.039201052, 0.015120258, -0.0082642793, 0.0051985023 }, { -0.0091203243, 0.020790215, 0.0025270937, 0.020092044 }, { -0.0029830063, 0.006602841, -0.00833601, 0.044852353 }, { 0.025206353, -0.0038915173, 0.00045914851, 0.0037840538 }, { 0.0014814254, -0.011573911, 0.046232337, -0.015228958 }, { -0.0071984443, 0.0090004063, 0.022942838, 0.016019787 }, { 0.0050929336, 0.0060892107, -0.0061771339, 0.0047850766 }, { -0.011634853, 0.0010276548, 0.022396644, -0.0021248711 }, { -0.012943002, 0.0016430074, 0.02034928, 0.024289705 }, { 0.0051047037, 0.010052556, 0.0020923265, -0.019043181 } } }, { { { 2.1627647, 2.1788232, 1.9290264, 1.8457806 }, { 2.526488, 2.3020441, 2.538915, 2.03484 }, { 3.9987521, 4.3952121, 3.906821, 4.1693278 }, { 4.0400466, 4.1069844, 5.2512999, 5.4283264 }, { 3.0141968, 3.3306035, 3.2224806, 3.2473051 }, { 2.9840674, 3.1294685, 3.2964833, 3.2929246 }, { 1.8346741, 1.8637353, 2.3037966, 2.0860888 }, { 2.691236, 2.6068079, 1.9349032, 2.1632935 }, { 1.9231956, 1.7251627, 2.1609654, 2.1155629 }, { 2.165771, 2.1908952, 1.777038, 2.0223741 }, { 4.5166991, 4.8674508, 3.918546, 3.378087 }, { 4.4502295, 4.5429338, 3.9552598, 3.3580272 }, { 3.0973598, 3.3953852, 2.2704362, 2.6488177 }, { 3.2110537, 3.3104376, 2.515002, 2.3267785 }, { 1.8303675, 1.7094345, 3.1787979, 2.5960104 }, { 2.4391795, 2.8730077, 2.3730261, 2.1545299 }, { 2.2130903, 2.1899209, 2.4997355, 1.9058674 }, { 2.6472893, 2.5455636, 2.1164596, 1.8341163 }, { 3.9428283, 4.0433678, 4.5430063, 4.2482776 }, { 4.1941673, 4.28852, 4.64044, 4.6644567 }, { 3.0873642, 2.649364, 3.6026133, 3.2426354 }, { 3.2415154, 3.5406745, 3.2976852, 3.3100246 }, { 1.8400289, 1.8404692, 1.889289, 2.0125184 }, { 2.7063995, 2.7229173, 2.6289878, 2.4313709 } }, { { -0.015335928, -0.043382119, -0.0054163805, -0.028249934 }, { -0.017200109, 0.0027582413, -0.079612821, -0.0013966663 }, { -0.027233584, -0.018783395, -0.01183278, -0.020918937 }, { -0.0036358348, -0.015712206, -0.0089146421, -0.0057117233 }, { 0.020392865, 0.017743746, -0.068597326, -0.030425581 }, { -0.041123673, -0.020767538, -0.0087941887, -0.0065248183 }, { -0.0055478408, -0.00082196865, 0.0088521402, -0.045916836 }, { -0.010506485, 0.0078523247, -0.030002306, -0.0015085765 }, { 0.01894068, -0.012424968, -0.034837214, -0.045009941 }, { -0.045299587, 0.02630478, -0.017175711, -0.043601235 }, { -0.046003661, -0.020588165, 0.034398873, -0.054653787 }, { -0.0042534368, 0.01325834, -0.0036369576, -0.079162988 }, { -0.028728556, 0.0051289128, 0.012104313, 0.010686997 }, { -0.066337767, 0.00059928728, -0.080303668, 0.011318772 }, { -0.031879871, 0.0011317962, -0.050259029, 0.0031596552 }, { -0.090121238, -0.011196084, -0.072456123, -0.00079731072 }, { -0.024243475, 0.021401076, -0.018209385, -0.0083196072 }, { -0.079888701, 0.0032806631, -0.12762259, -0.04652308 }, { 0.031806075, -0.034165157, -0.015255921, -0.049164663 }, { -0.0012051123, 0.030788487, 0.022291919, 0.0025694519 }, { 0.035836509, 0.0055365388, 0.026704836, 0.0001547235 }, { -0.012129747, -0.0094322145, -0.040637935, -0.12125388 }, { -0.027044986, 0.04531553, -0.033484589, -0.0059927923 }, { 0.0067188802, -0.051166351, -0.048822794, -0.025926988 } }, { { 0.022049053, 0.021265778, -0.040370641, -0.036232952 }, { -0.0058098424, -0.0042264198, -0.077428509, -0.04241654 }, { -0.0026825379, -0.029453318, -0.016181275, -0.028320229 }, { -0.012541692, -0.01345735, 0.00037814888, -0.0046052489 }, { -0.026527394, 0.020033638, -0.025683861, -0.084207169 }, { -0.0010459945, -0.036745215, -0.039772051, 0.024810839 }, { 0.012134618, 0.0068515798, -0.035286972, 0.043129595 }, { -0.077093357, -0.026872688, 0.032800133, -0.090326706 }, { 0.13930909, 0.0081274014, -0.08349188, -0.012200005 }, { -0.091693797, -0.012567011, -0.069736822, -0.0061444184 }, { -0.053061301, 0.003642159, 0.0052515175, -0.036957472 }, { 0.0043493933, -0.013069332, -0.014708126, -0.032765039 }, { -0.016116105, -0.022907609, -0.043503106, -0.013266465 }, { -0.072759977, -0.077354585, 0.0043827591, -0.013821612 }, { -0.032399073, -0.045305037, -0.021840791, 0.073996542 }, { -0.057239255, -0.056581235, -0.038880927, 0.044102943 }, { -0.026951489, -0.088667645, -0.013659704, 0.033527579 }, { 0.034815442, -0.028634059, -0.036666529, 0.011546036 }, { 0.026688447, -0.0081892129, -0.031138092, -0.041739155 }, { 0.0015665701, -0.012701682, 0.0013533943, -0.002849785 }, { 0.032994636, 0.008802974, 0.019032649, 0.0039042621 }, { -0.044544917, 0.0093201326, -0.017968915, 0.01936344 }, { -0.034794535, 0.043032983, -0.051072531, -0.040148303 }, { -0.0030398597, -0.027112065, -0.064007483, -0.01798277 } } }, { { { 0.22040906, 0.24911942, 0.41660708, 0.23632869 }, { 0.25894466, 0.1416669, 0.41902981, 0.35717608 }, { 0.26918091, 0.14566759, 0.2147652, 0.15769391 }, { 0.22500921, 0.12113361, 0.11151768, 0.12348609 }, { 0.25699055, 0.056819107, 0.3859882, 0.4585378 }, { 0.7304995, 0.20719358, 0.44455636, 0.42226989 }, { 0.43602897, 0.51049581, 0.41978824, 0.62521039 }, { 0.42004119, 0.52912054, 0.33314238, 0.38257921 }, { 0.55092562, 0.43085653, 0.31149977, 0.34391138 }, { 0.40391149, 0.48820255, 0.13569806, 0.36060266 }, { 0.13647907, 0.12061002, 0.20668806, 0.30221394 }, { 0.15583476, 0.13133696, 0.22775202, 0.35653823 }, { 0.56336195, 0.25684627, 0.11118383, 0.23109245 }, { 0.45430401, 0.42843367, 0.25496534, 0.097473509 }, { 0.3420223, 0.39418925, 0.26458947, 0.30588082 }, { 0.51345558, 0.3612731, 0.41151773, 0.25269512 }, { 0.29195176, 0.42659964, 0.47971993, 0.32714756 }, { 0.49222777, 0.28477645, 0.74993827, 0.43781271 }, { 0.098434481, 0.31164923, 0.14486345, 0.11466693 }, { 0.070833248, 0.20569754, 0.10233576, 0.047352701 }, { 0.51050902, 0.15597643, 0.1417112, 0.35581415 }, { 0.48261165, 0.14592221, 0.62554576, 0.5209765 }, { 0.33562628, 0.39920067, 0.28183433, 0.297464 }, { 0.366851, 0.59278666, 0.59095922, 0.48385165 } }, { { 0.13792051, 0.072076744, 0.094800532, 0.026318377 }, { 0.13607414, -0.061382542, 0.061800151, -0.020060553 }, { 0.028096406, 0.069282616, 0.010195109, -0.010461141 }, { 0.018651237, 0.02642439, 0.0077552848, -0.051151646 }, { 0.098299803, -0.0085081153, -0.011764584, 0.087405711 }, { 0.064082346, -0.04626424, -0.071480607, 0.064447268 }, { 0.022766233, 0.0167542, -0.021285286, -0.071637286 }, { -0.0202445, 0.011692601, 0.048325551, 0.0097755172 }, { -0.027775183, 0.016463115, 0.060050391, -0.034226107 }, { 0.019412547, 0.059977501, -0.0041737169, 0.031539317 }, { 0.013192979, 0.036015595, -0.049943198, 0.014112312 }, { -0.013272349, 0.035821037, -0.060503687, 0.095316821 }, { 0.038338785, -0.059038809, -0.044954172, -0.00051347307 }, { -0.039594082, 0.018205882, 0.13413799, 0.012292954 }, { 0.015177594, -0.0082493854, 0.00029420179, 0.010356248 }, { 0.100271, -0.13623174, 0.1121235, 0.068902399 }, { 0.025189636, 0.0014918434, 0.0088847718, -0.053714493 }, { 0.06487698, -0.097217547, -0.069537353, 0.032490984 }, { -0.030729608, 0.048956315, 0.016036034, 0.022485239 }, { 0.049839618, 0.01148525, -0.021032427, -0.019665817 }, { -0.0037762817, -0.030422275, -0.062343207, 0.057994884 }, { 0.014035184, -0.021387762, -0.080846143, -0.020681511 }, { -0.03594567, 0.026862531, 0.078975557, -0.034056659 }, { -0.014490672, 0.026128902, 0.045617611, 0.090192953 } }, { { 0.011904288, -0.014624471, 0.042023114, 0.019592867 }, { 0.032705848, 0.00038558691, 0.031901745, 0.027208951 }, { -0.044369719, -0.039761364, -0.013366816, -0.019308126 }, { -0.019051023, -0.00015767269, -0.082968285, -0.035266053 }, { -0.004775162, 0.010889271, 0.0089521094, 0.027037104 }, { 0.005616143, -0.00099668486, 0.0068716426, -0.12649184 }, { 0.018531199, 0.023881776, -0.053798787, -0.041912909 }, { -0.0036187094, 0.11590788, 0.025140733, 0.022280209 }, { -0.02994342, -0.026293799, -0.017204658, 0.044901944 }, { 0.079892089, 0.10816526, 0.14667807, 0.027301352 }, { -0.045296738, -0.066748968, -0.0099354431, -0.070369692 }, { -0.08357374, -0.043311901, 0.013163375, -0.0881777 }, { -0.065923811, -0.10382274, 0.090440302, -0.013617198 }, { -0.092578587, -0.010178017, -0.01416593, 0.0432333 }, { 0.055172515, 0.10021805, -0.0062782668, -0.11791805 }, { -0.039684132, -0.08934283, 0.020686084, -0.0013788117 }, { 0.064624676, 0.051773746, 0.0045383964, -0.037696971 }, { -0.066296373, 0.020570689, -0.017742721, -0.022651449 }, { -0.0061572447, -0.094510525, -0.094775804, -0.038022514 }, { 0.0055683313, 0.039513342, -0.096815654, -0.0065483011 }, { -0.03311602, -0.018395457, 0.0028464434, -0.088048272 }, { -0.073106109, -0.055187863, -0.093209932, -0.10155137 }, { 0.042841842, -0.005778703, 0.074069607, -0.025841052 }, { -0.018569637, 0.063144303, 0.02291584, 0.005525742 } } } }, { { { { -0.20809663, -0.18346453, -0.072140694, -0.0078104407 }, { -0.19490097, 0.25712922, 0.37640771, 0.11563399 }, { 0.26894915, -0.33477877, -0.093739129, -0.55078405 }, { -0.65794103, 0.09211629, -0.19166986, 0.5574327 }, { 0.45579532, 0.23202083, 0.19626303, -0.64130523 }, { -0.018763975, -0.24981569, -0.32514026, -0.11121342 }, { 0.22376238, 0.09515938, 0.071728264, -0.02790747 }, { -0.3053338, 0.34023365, 0.099862481, 0.26163964 }, { -0.21722968, -0.094881958, -0.086364431, -0.0081863581 }, { -0.16090709, 0.23527698, 0.28947119, 0.11309742 }, { 0.26447184, -0.33536416, -0.096418234, -0.26201294 }, { -0.56343769, -0.041662822, -0.24873841, 0.67122901 }, { 0.35362642, 0.2577592, 0.2009013, -0.74233681 }, { -0.047956299, -0.54973418, -0.4958485, -0.12453303 }, { 0.06917425, 0.080509853, 0.0090863722, -0.023518805 }, { -0.27000602, 0.083167162, 0.12715558, 0.12397839 }, { -0.11376964, -0.079199259, 0.019676685, -0.0094352472 }, { -0.19185851, 0.22193112, 0.28110877, -0.06422845 }, { 0.084091992, -0.16151548, 0.091400556, -0.28257376 }, { -0.53821376, 0.21718328, -0.2234907, 0.52302804 }, { 0.71322306, 0.042728493, 0.13229522, -0.61892094 }, { 0.15270046, -0.26304886, -0.33110633, -0.052728951 }, { 0.072398971, 0.25829764, 0.25881687, -0.020942042 }, { -0.26788161, 0.055822039, 0.33817103, 0.42061402 } }, { { 0.088248648, 0.091306255, 0.020476927, 0.0030144802 }, { 0.0087376707, 0.043816157, 0.0022807168, 0.016745414 }, { -0.13412414, 0.12686539, 0.060531476, 0.044582027 }, { 0.019204757, -0.0070891897, 0.091194602, 0.065258927 }, { -0.10429513, -0.027665602, -0.064350626, 0.0053147478 }, { 0.069218141, -0.035018324, -0.088257571, 0.019279642 }, { -0.073137338, 0.040764456, -0.022352804, 0.031743288 }, { 0.040325697, -0.12840825, -0.009582113, 0.034509657 }, { 0.081971224, -0.0035223125, -0.051728499, 0.0038899717 }, { 0.050968435, 0.022254651, 0.18781134, -0.032392139 }, { 0.024342518, 0.13929014, -0.019175435, -0.0011608234 }, { -0.0021942487, -0.01251222, 0.024263454, -0.063179344 }, { -0.13071776, -0.059221747, -0.034153238, 0.036561209 }, { 0.054124093, 0.070495803, 0.081441614, 0.051900357 }, { 0.027480327, 0.028940343, -0.01469313, 0.032388411 }, { -0.039696828, -0.0069393798, -0.011361641, 0.035031025 }, { -0.039730763, 0.0085971581, -0.0077461932, -0.040735188 }, { 0.10893368, 0.00014757217, 0.025489178, -0.11388774 }, { -0.0013816669, 0.0031148929, 0.10281666, -0.019860642 }, { -0.065093128, -0.11495815, 0.041783056, -0.091373461 }, { -0.044985581, 0.0012713031, -0.16078032, 0.17303747 }, { -0.038132358, -0.02995975, -0.037612782, 0.012575173 }, { 0.0042976619, 0.027014275, 0.017518808, 0.030405184 }, { -0.0015298607, 0.029297664, -0.1034349, 0.023450502 } }, { { 0.028785558, -0.028708377, -0.010459636, 2.8360915e-05 }, { 0.091634877, 0.021214811, 0.12282079, 0.080617943 }, { -0.29287977, 0.045481846, 0.014712563, 0.057317576 }, { -0.10728772, 0.03268482, 0.015167285, -0.011256231 }, { 0.09337321, 0.037150859, 0.052549202, -0.042671474 }, { -0.0041288689, -0.024299997, -0.11357403, -0.022045772 }, { -0.041469935, -0.0071353646, -0.0086607538, 0.008536762 }, { 0.033629272, -0.0070042955, -0.037864853, -0.0055907778 }, { 0.016404597, -0.0055321059, -0.020989839, -0.013771265 }, { 0.042552435, 0.04428518, 0.0030587466, 0.044894182 }, { -0.027600219, 0.026831779, 0.051120849, -0.032184808 }, { 0.13870554, 0.15273282, 0.049260112, 0.043371121 }, { -0.018453269, -0.18061413, 0.24805649, -0.031741165 }, { -0.085137374, 0.025935867, 0.015978067, 0.067726486 }, { 0.072393868, 0.0050430488, 0.0016664585, 0.0072097064 }, { 0.033840162, 0.082225764, -0.079387016, 0.033165625 }, { 0.033170766, 0.0012231618, -0.066984982, 0.051671704 }, { 0.017894231, -0.012267532, 0.045536123, -0.07327109 }, { 0.0073109731, -0.063797898, -0.13446413, 0.1408986 }, { -0.045702456, -0.1647051, -0.14336468, 0.054543693 }, { 0.0042448876, -0.13234456, 0.092181719, -0.10440841 }, { -0.060020212, -0.011098469, -0.030257182, -0.030922037 }, { -0.018118661, 0.00067983745, -0.0061776598, -0.031721273 }, { -0.019885189, 0.094157888, 0.014017961, -0.051373389 } } }, { { { 0.12415319, -0.13611564, -0.029441661, -0.14143497 }, { -0.26074418, 0.011913326, -0.033328425, 0.43248793 }, { 0.19336432, 0.37269586, 0.36803538, -0.51720719 }, { -0.15185913, -0.47431781, -0.6593667, 0.23163184 }, { 0.18276216, 0.19248743, 0.65453332, 0.54748087 }, { 0.17751443, -0.0020337696, 0.08506463, -0.40147769 }, { -0.11370932, 0.11523476, -0.010573025, 0.082295392 }, { -0.13666335, -0.32747478, -0.16897386, 0.15359006 }, { 0.11716326, -0.12259922, 0.0033396256, -0.13240653 }, { -0.27776876, -0.10222241, -0.039920479, 0.35499708 }, { 0.090003723, 0.3313923, 0.1871549, 0.003163675 }, { -0.51626118, -0.76341562, -0.56326874, 0.20153559 }, { -0.34172723, 0.26975563, 0.67520079, -0.1252004 }, { 0.45758078, -0.19142179, 0.064180031, -0.48748431 }, { -0.12800789, 0.1399912, 0.0077954775, 0.14379741 }, { -0.13042104, -0.45670817, -0.18831095, 0.0032738639 }, { 0.12446807, -0.11504524, -0.027331682, 0.03861758 }, { -0.31337986, -0.11842668, 0.033415325, 0.45344231 }, { 0.11463107, 0.077427841, 0.060880794, -0.069619455 }, { -0.37772106, -0.59628905, -0.65426572, 0.065297039 }, { 0.29532991, 0.75920243, 0.53294265, -0.15002562 }, { 0.3618333, 0.10488387, 0.36007528, -0.30963565 }, { -0.13738196, 0.20795596, 0.029274703, 0.18017599 }, { -0.10290023, -0.48517535, -0.33278584, 0.56477854 } }, { { -0.0047891472, 0.024629901, 0.015256654, -0.0084462001 }, { 0.056227746, -0.048057782, -0.15671312, 0.06418471 }, { -0.070093217, -0.018057199, 0.062026545, -0.051053726 }, { -0.0091221476, 0.0020547295, -0.087729813, -0.10164738 }, { 0.098917091, -0.066835916, 0.083151519, 0.006342544 }, { 0.0013540606, 0.038719082, 0.036333261, -0.053178668 }, { 0.0083787438, 0.0028359378, 0.0089872852, 0.031308249 }, { 0.014379686, -0.079563474, -0.079160006, -0.016352226 }, { 0.0091376645, -0.016678006, -0.044636785, -0.0011035265 }, { 0.0099146109, 0.027589302, -0.09494437, 0.07451767 }, { 0.017453983, 0.080674871, 0.06341808, 0.048820473 }, { 0.02794057, 0.058230195, -0.010793601, 0.091813872 }, { -0.049633232, -0.1142016, 0.036984283, 0.0034294865 }, { 0.047712957, 0.10161366, 0.13774722, 0.039503136 }, { 0.014194782, -0.014555183, -0.00053182909, 0.0019143477 }, { 0.0014900262, 0.0056176356, -0.034517871, -0.0010707988 }, { 0.013287784, -0.0073967933, -0.019271341, 0.016354896 }, { -0.10345626, 0.023536634, 0.027943639, -0.015686972 }, { -0.025193395, -0.10224801, 0.078686884, -0.048574399 }, { 0.15797878, -0.0012322757, -0.036096649, -0.23983963 }, { -0.10455507, -0.056368102, -0.06570944, 0.29104616 }, { 0.05155239, -0.040940824, -0.038367594, 0.058174485 }, { 0.010471732, -0.066952904, -0.047763843, -0.021124742 }, { -0.033555686, 0.0049111983, -0.026592789, 0.014438586 } }, { { -0.0048440946, 0.025915095, -0.018325403, 0.022133613 }, { 0.059240081, -0.031272176, -0.12967647, -0.17957913 }, { 0.0574837, 0.067005152, 0.024644254, 0.10786296 }, { 0.067084865, 0.008513386, 0.04077659, 0.10587924 }, { 0.026332643, 0.1072618, -0.098375042, -0.001724609 }, { -0.021386362, -0.0020174921, 0.16800158, 0.081359882 }, { -0.018204146, -0.026432136, -0.0068153455, -0.029997667 }, { -0.043221501, -0.016869967, -0.067406967, -0.024965804 }, { -0.0033879999, 0.031310818, -0.010853802, 0.00088944004 }, { -0.068991006, 0.087874253, -0.15737392, -0.088870044 }, { 0.061763806, -0.00072874343, -0.009915009, -0.0178225 }, { -0.07340717, 0.080339271, -0.0027124572, -0.13078641 }, { -0.023682834, 0.16512313, -0.15784472, 0.047978827 }, { 0.0063250439, -0.09953777, 0.094180888, 0.010565041 }, { 0.010047311, -0.042999009, -0.012483998, -0.016966759 }, { -0.048612679, 0.051708319, 0.015059148, 0.0036776472 }, { -0.011737015, -0.0027276603, 0.026535075, -0.065453876 }, { 0.056388137, 0.061461073, -0.12726984, -0.025578248 }, { 0.0016833003, 0.10878558, 0.13254828, -0.017098914 }, { -0.031606282, -0.072245098, 0.12724789, -0.21852899 }, { -0.062502612, -0.073402771, -0.049624729, 0.069066032 }, { -0.075837195, -0.10297347, -0.07249237, -0.11538062 }, { -0.015644005, 0.039474396, 0.074415075, -0.038881161 }, { -0.040175911, 0.034030267, 0.03947059, 0.014167463 } } }, { { { 0.97019677, 0.97355703, 0.99695983, 0.98991674 }, { 0.94552952, 0.96630359, 0.92585444, 0.89419404 }, { 0.9435447, 0.86545998, 0.92507456, 0.65508294 }, { 0.73759908, 0.87552111, 0.72697883, 0.79725496 }, { 0.87111918, 0.95347518, 0.73011435, 0.53758004 }, { 0.9839393, 0.96829127, 0.94183216, 0.90909143 }, { 0.96798791, 0.98876976, 0.99736817, 0.99621717 }, { 0.9423876, 0.88147679, 0.98054848, 0.95286662 }, { 0.96906348, 0.98791034, 0.99625801, 0.99116169 }, { 0.94707625, 0.9665378, 0.9563539, 0.9280011 }, { 0.96018435, 0.88187869, 0.97758711, 0.96505917 }, { 0.64499021, 0.64456248, 0.78794513, 0.71332673 }, { 0.87073007, 0.92778882, 0.70974824, 0.65822558 }, { 0.88787388, 0.81311133, 0.86603417, 0.86420517 }, { 0.98935782, 0.98687417, 0.99992833, 0.98932764 }, { 0.95398485, 0.88572054, 0.97384313, 0.99227952 }, { 0.98567955, 0.99019799, 0.99943274, 0.99920952 }, { 0.93004482, 0.96784384, 0.95909399, 0.88896838 }, { 0.98984254, 0.98382807, 0.99395144, 0.95671584 }, { 0.75342733, 0.77283296, 0.72248756, 0.84981055 }, { 0.63568318, 0.6494505, 0.83574524, 0.77099234 }, { 0.91965169, 0.95906448, 0.87218942, 0.94939213 }, { 0.98786871, 0.94341754, 0.96548269, 0.98341143 }, { 0.95794101, 0.87263324, 0.8802806, 0.71000638 } }, { { -0.0064390277, 0.051629953, -0.011423447, 0.032337826 }, { 0.055030538, 0.061305324, -0.016012659, 0.083766345 }, { 0.052467122, 0.018425134, -0.00054737782, 0.048038459 }, { 0.076436505, 0.016815709, -0.024174832, -0.00829119 }, { 0.057903371, 0.068822104, -0.0064003131, 0.00010695928 }, { 0.067104151, 0.067284611, 0.0074295447, 0.024215238 }, { 0.073380541, 0.01486405, 0.01523157, 0.012966612 }, { -0.0002536971, 0.010628632, 0.00045031869, 0.041891438 }, { 0.055922922, 0.0090823157, 0.011101162, 0.033807592 }, { -0.040264953, 0.022318628, -0.013682045, -0.016112502 }, { -0.034286564, 4.7089727e-05, -0.013030079, -0.012231424 }, { 0.027756308, 0.084041595, 0.018308393, 0.11564334 }, { 0.0026690817, 0.058149333, -0.013682964, 0.052975934 }, { -0.03852481, 0.063493354, 0.059460027, 0.047740976 }, { 0.026410264, -0.0073902435, 0.022353771, 0.012987341 }, { 0.035217135, -0.0023455309, -0.0055505614, 0.010102857 }, { 0.00075590283, 0.038624793, -0.0040614962, 0.070039437 }, { -0.02318411, 0.04527054, 0.013119286, 0.025335215 }, { 0.021268391, 0.044855911, 0.012622905, 0.04827088 }, { -0.0046678346, -0.01934799, 0.018393432, 0.09750434 }, { 0.12480373, 0.059151139, 0.055196092, 0.26701338 }, { -0.0096669036, 0.065624767, 0.016918517, 0.028425135 }, { 0.026488514, -0.0037618693, 0.0077028717, 0.041713399 }, { 0.018628451, 0.033145064, 0.029067918, -0.000924258 } }, { { -0.043525781, 0.028119778, -0.011653105, -0.020930158 }, { -0.028099186, 0.017594088, -0.099226445, 0.10408808 }, { 0.11750066, -0.0010629746, 0.018381448, 0.096538552 }, { 0.0010069446, 0.013799541, 0.1325137, 0.020820734 }, { -0.053571928, -0.0066793785, 0.14596488, -0.03272949 }, { 0.028507895, 0.015474376, -0.025411653, 0.037264272 }, { 0.033698911, 0.018088387, 0.0038898537, 0.03163178 }, { 0.0057766828, 0.015879322, 0.012557033, 0.071771631 }, { -0.0044521866, 0.0083963511, -0.0020426175, 0.023784146 }, { -0.011508765, 0.0075020051, 0.0018808294, 0.040843424 }, { 0.0085150894, 0.0056891711, 0.010134672, 0.046224768 }, { 0.040825446, 0.10099754, 0.021853299, 0.024507528 }, { -0.0055958303, -0.0060958, 0.1115321, -0.021701014 }, { 0.010487817, -0.010033143, -0.031203025, 0.054265436 }, { 0.0040500672, 0.0053935875, 0.018233022, 0.018797311 }, { 0.064057639, 0.014318185, 0.0199119, 0.014366235 }, { 0.02411682, 0.045454692, 0.0030084434, 0.019464939 }, { 0.012500289, 0.027734846, 0.0025097372, 0.047343669 }, { 0.037625829, -0.00064472688, 0.0557556, 0.04785655 }, { 0.0020433437, 0.019929208, 0.087936103, -0.036738471 }, { 0.020811556, 0.0915387, 0.055445303, -0.065132763 }, { 0.03911814, 0.043721622, 0.0074336204, -0.031370424 }, { 0.014072509, -0.014795458, 0.010517063, 0.022409628 }, { -0.0054107234, 0.055313602, 0.053556404, 0.048574319 } } }, { { { 3.4224197, 3.3162336, 3.1136621, 3.3189801 }, { 4.0715355, 3.5614196, 4.1797877, 4.0959601 }, { 4.3979407, 4.1858272, 4.3116447, 4.5467451 }, { 4.4920032, 4.0716439, 4.6107962, 4.5268016 }, { 5.6570832, 4.9036495, 4.7373547, 4.7259419 }, { 3.3277827, 3.6015237, 4.226646, 3.7939772 }, { 3.4893058, 3.3260638, 3.0626103, 3.1798705 }, { 3.6423735, 4.1092281, 3.3264203, 3.7325301 }, { 3.4756581, 3.2550256, 3.224671, 3.4093307 }, { 3.8511362, 3.4821381, 4.3232597, 3.7357164 }, { 3.6688024, 4.0797971, 3.4140927, 3.6881261 }, { 4.5298469, 4.7472506, 4.4046473, 4.7279944 }, { 4.1614448, 4.1242955, 4.6741969, 5.0037875 }, { 4.3148703, 4.3815566, 4.1976536, 3.9032858 }, { 3.2640506, 3.3214728, 2.9463564, 3.3562068 }, { 3.6729325, 3.9218642, 3.4550701, 3.4833871 }, { 3.435975, 3.3079446, 3.3432341, 3.3632985 }, { 3.8404619, 3.4716915, 3.858149, 3.8677391 }, { 3.3181827, 3.8403872, 4.0363918, 3.9604287 }, { 5.0916792, 5.2773748, 4.5404255, 4.377031 }, { 4.6514614, 4.7569957, 4.1233238, 4.4022582 }, { 3.6884833, 3.6283543, 4.1874612, 4.2963913 }, { 3.456705, 3.6250566, 3.5292789, 3.1420033 }, { 3.5986317, 4.0596074, 4.0696874, 4.5327067 } }, { { -0.12592901, -0.14780788, -0.11051274, -0.18767653 }, { -0.020435093, 0.0055221209, -0.021183195, -0.15159792 }, { 0.022498629, -0.025100789, -0.30939177, 0.016420202 }, { 0.21296442, -0.042976575, 0.082118132, 0.14574735 }, { -0.13608022, 0.16141834, -0.015091164, 0.044951541 }, { -0.08235774, -0.10333151, 0.089785432, -0.036620639 }, { -0.17664465, -0.015842477, -0.083075331, -0.15660828 }, { -0.11292423, -0.072894494, -0.068901923, -0.2283674 }, { -0.19063437, -0.071954393, 0.091375283, -0.26993547 }, { 0.042798331, -0.06495575, 0.050221766, 0.024602586 }, { -0.026228614, 0.0049810367, 0.046584088, -0.13067577 }, { 0.072779737, -0.023369437, -0.030275791, 0.19591126 }, { -0.018649072, 0.029208952, 0.012033439, 0.00094798196 }, { -0.094599446, 0.0070746366, -0.0007115864, -0.040175552 }, { -0.027599009, -0.068747365, 0.19480498, -0.19423733 }, { -0.076671551, 0.0075475135, 0.019853903, -0.012984601 }, { 0.064371855, -0.24044027, -0.043765356, 0.0016424127 }, { -0.076744435, 0.035881398, 0.12967612, 0.081825243 }, { -0.15224256, 0.032665115, -0.027927205, 0.076091133 }, { -0.0057973613, -0.14914213, -0.047678749, -0.037214457 }, { 0.10060085, -0.099197666, -0.22704457, -0.0020812401 }, { -0.070664558, -0.13179176, -0.014217065, -0.030410253 }, { -0.12286487, -0.046623366, -0.10695394, -0.0081383175 }, { -0.14561788, 0.02765909, 0.10439783, 0.033139041 } }, { { 0.0063171031, -0.0047223477, -0.056312039, -0.065065766 }, { -0.0059575982, -0.062348475, 0.069540315, -0.090331962 }, { 0.10218203, 0.050383376, -0.0089914697, -0.037837343 }, { -0.0037657879, 0.18278082, 0.079014627, -0.052587294 }, { -0.33929282, 0.018522098, 0.0078923893, 0.042545349 }, { 0.027294929, -0.086490439, -0.0057363347, -0.035932082 }, { -0.061716003, -0.14470599, 0.033117786, -0.08112808 }, { 0.16414856, 0.082471596, -0.058497326, 0.050552718 }, { -0.07627083, -0.0064181717, -0.031179581, -0.075705068 }, { -0.057808009, -0.00074561624, -0.23990956, 0.018671772 }, { 0.1677602, 0.10757253, 0.028015134, -0.23923178 }, { 0.078827365, 0.068682485, 0.056277532, -0.069749241 }, { 0.079502977, 0.05526585, 0.0089767144, -0.15319341 }, { -0.038594242, -0.055488998, -0.043132461, 0.054313031 }, { 0.12890592, -0.082639555, 0.22520491, -0.026781096 }, { -0.071292391, 0.064592881, -0.050368563, -0.072488866 }, { 0.092998671, 0.12152394, 0.033318795, -0.039691417 }, { -0.0049706273, -0.0014175115, -0.11634604, 0.15219284 }, { -0.012414906, 0.035583927, -0.072463074, -0.058394705 }, { -0.071558898, -0.00093653835, 0.013149622, 0.01495775 }, { -0.057103279, 0.013702583, -0.020242751, 0.04649072 }, { -0.083398977, -0.20123674, 0.062758815, -0.043671819 }, { 0.084479675, 0.17868517, -0.021185269, 0.15711776 }, { 0.11862504, 0.079985297, 0.063556911, 0.14639069 } } }, { { { 0.48018566, 0.17712962, 0.45065949, 0.76214707 }, { 0.37788335, 0.385421, 0.24766167, 0.3647243 }, { 0.45095873, 0.2634498, 0.37824131, 0.10713483 }, { 0.18808611, 0.27852978, 0.23671202, 0.23174978 }, { 0.39404781, -0.7399413, 0.28511918, 0.026007027 }, { 0.46587668, 0.46802177, 0.36697974, 0.23706778 }, { 0.48925391, 0.42086488, 0.49570155, 0.45137287 }, { 0.30655255, 0.35196398, 0.23019387, 0.50586011 }, { 0.45798975, 0.34137244, 0.33289763, 0.54218519 }, { 0.42271216, 0.38700914, 0.48791862, 0.15025833 }, { 0.7282781, 0.37956244, 0.25156645, 0.51632504 }, { 0.084933462, 0.15576738, 0.16469359, 0.29684651 }, { 0.34570877, 0.34912791, 0.26663435, 0.11188061 }, { 0.48552914, 0.19012867, 0.12677402, 0.1234341 }, { 0.2190939, 0.41431469, 0.64823269, 0.51846746 }, { 0.49289149, 0.29829354, 0.29090992, 0.36465152 }, { 0.50568056, 0.64150077, 0.40217634, 0.53523743 }, { 0.24945735, 0.47058801, 0.29099852, 0.25452114 }, { 0.49039753, 0.26327736, 0.39431507, 0.50632023 }, { 0.19678915, 0.031547614, 0.22295107, 0.26300048 }, { 0.12409997, 0.11506147, 0.19327618, 0.2174585 }, { 0.15319333, 0.39177705, 0.38498586, 0.25972804 }, { 0.69027161, 0.37279682, 0.31143504, 0.23440833 }, { 0.39682066, 0.3156927, 0.36369313, 0.14308402 } }, { { 0.15030994, 0.15410005, 0.0072554408, -0.22242826 }, { -0.032421729, 0.22531436, 0.22185899, -0.022703209 }, { 0.070341052, 0.30237173, 0.047916387, 0.03629681 }, { -0.024283222, 0.075614195, 0.013940033, -0.016841468 }, { 0.077729482, 0.19455394, -0.02162282, -0.018761003 }, { -0.22986895, 0.18914992, 0.14483608, 0.11173921 }, { 0.14132894, -0.0081864768, -0.11405791, 0.031777789 }, { 0.38775389, 0.0085565642, -0.057167843, 0.09784167 }, { 0.079102739, 0.030530894, 0.041954967, 0.02957611 }, { 0.076915126, 0.18656729, 0.044218872, 0.22478833 }, { 0.017173879, 0.11961351, -0.085099523, 0.22720323 }, { 0.030466202, 0.095221887, -0.042982583, -0.069264747 }, { 0.041170442, -0.090598444, -0.021082598, -0.028016784 }, { -0.082581617, -0.023712106, 0.32427665, 0.1010696 }, { 0.19197752, 0.10900527, -0.0053794951, 0.068553764 }, { 0.18674269, 0.028895321, -0.053421028, 0.063918058 }, { 0.044090722, -0.054247791, 0.05585954, -0.13406746 }, { 0.08358642, -0.032301886, 0.010371619, 0.099505528 }, { 0.16467816, 0.044994571, -0.0045949279, 0.0626774 }, { 0.12942209, 0.092097891, 0.019866495, 0.10340014 }, { 0.037094903, 0.13829877, 0.15116473, -0.048632499 }, { 0.10749044, 0.14329542, -0.061272024, -0.1536028 }, { 0.097716907, 0.044246181, 0.056664419, 0.15804873 }, { 0.031819999, 0.10132976, 0.079198524, 0.017871462 } }, { { 0.056219172, 0.08683492, -0.061488015, 0.065746152 }, { 0.088983664, 0.19773741, -0.096766599, 0.16352101 }, { -0.0097043787, -0.040925999, 0.097458334, 0.032319634 }, { -0.024873518, 0.057873123, -0.0059256291, -0.057498398 }, { -0.13355098, 0.39190863, 0.017449142, -0.0076009344 }, { 0.10319658, 0.22069551, -0.098795717, 0.10603434 }, { 0.090765308, 0.13803326, -0.070647945, 0.14557561 }, { -0.068457348, 0.058955208, -0.050501105, 0.02914144 }, { 0.10363866, 0.060231993, 0.027681685, 0.079659088 }, { 0.01269983, 0.11977996, -0.049648315, 0.089882363 }, { -0.072877286, 0.019348792, 0.13977764, 0.055396044 }, { 0.028834456, -0.1084196, -0.0043985215, -0.072640844 }, { -0.040232522, 0.051835989, -0.02198193, 0.016421295 }, { -0.087848469, -0.04621504, 0.099259188, -0.0025909067 }, { 0.3000131, 0.10526775, 0.016890366, 0.12892588 }, { -0.021028821, -0.024429075, 0.088067677, -0.084594075 }, { 0.086861805, -0.045902006, 0.0058222123, -0.0075466204 }, { 0.14411905, 0.036488937, 0.05091815, 0.16385101 }, { 0.1576814, 0.043890956, -0.064244298, -0.087234754 }, { -0.071100004, 0.16782304, -0.10860149, -0.1601076 }, { 0.032634641, -0.0025068263, -0.093802703, -0.076176546 }, { 0.1121451, 0.15584236, 0.070074778, 0.083736091 }, { 0.16981897, -0.078106227, 0.12480295, -0.0056807652 }, { -0.20300117, -0.017467249, 0.035504155, 0.056546123 } } } }, { { { { 0.014994926, 0.3118252, 0.12179235, -0.2013765 }, { -0.2622824, 0.28086607, 0.018805882, 0.72058929 }, { -0.0081002049, -0.28176506, -0.592214, -0.15032918 }, { 0.18913426, -0.24000825, 0.0020279072, -0.54749128 }, { 0.010237954, 0.76905205, 0.80173664, -0.016024595 }, { -0.53448318, 0.31204229, -0.16183732, 0.76857439 }, { -0.57639279, -0.63719194, -0.71354849, 0.56346054 }, { 0.49443258, 0.15067585, 0.31864726, -0.30570933 }, { -0.20756322, 0.2544828, -0.005298245, 0.0073796841 }, { -0.61822672, 0.21508574, 0.6362534, 0.30433278 }, { -0.0050327191, -0.278054, -0.3460806, 0.29967778 }, { 0.33983098, -0.11715664, -0.21761592, -0.068273894 }, { 0.5550354, 0.44369709, 0.64019993, -0.026032291 }, { -0.72587268, -0.33528197, -0.33592445, 0.53027141 }, { -0.47623191, -0.61767624, -0.61525655, 0.37823554 }, { 0.82869964, 0.219401, -0.018181789, -0.56937955 }, { -0.051792934, 0.3461701, 0.20915925, 0.078166496 }, { -0.26705611, 0.14439061, 0.0055054648, 0.463243 }, { -0.0019649711, -0.34119962, -0.29306531, -0.040223173 }, { 0.29285811, -0.32824753, -0.24768208, -0.29676955 }, { 0.87604898, 0.25374435, 0.2341931, -0.77851996 }, { -0.80404697, 0.011122158, 0.18899178, 0.55592668 }, { -0.78397618, -0.53690406, -0.59931185, 0.62348293 }, { 0.54613799, 0.080819658, 0.12590931, -0.60614071 } }, { { -0.12307869, -0.20242175, 0.21530167, -0.15608553 }, { 0.00052208688, 0.09998365, -0.067550225, -0.14009319 }, { 0.12621699, -0.089024022, 0.022656689, 0.18947331 }, { 0.34838897, -0.04936051, 0.25527451, -0.18942819 }, { 0.013210249, -0.043957685, -0.19088103, -0.034189573 }, { -0.0027790938, -0.026595097, 0.087083287, -0.12513839 }, { -0.038231564, 0.013328425, -0.0091503894, -0.005743873 }, { 0.17205702, -0.14956835, -0.0088915291, 0.18720588 }, { -0.049670195, 0.39532325, 0.080260299, 0.01811245 }, { 0.043555003, -0.30289197, -0.50878196, 0.27306166 }, { 0.02555972, -0.0068359476, 0.061097702, -0.43822038 }, { -0.10926471, 0.1870906, 0.12419548, 0.1245213 }, { -0.012443149, 0.040036941, 0.18601483, 0.02310445 }, { -0.10442982, 0.057455632, 0.13475314, -0.0019859122 }, { -0.068181593, -0.0033655904, 0.01922998, -0.020393828 }, { -0.10660626, 0.0020812455, 0.081209707, 0.077131932 }, { 0.088733212, -0.10430986, 0.45554817, -0.17113078 }, { 0.0046831409, 0.13247549, -0.1077727, 0.15382275 }, { 0.022346595, 0.022924261, -0.35016323, 0.2437608 }, { 0.029795657, 0.23046877, -0.020493651, -0.33214749 }, { -0.016101582, 0.042296203, 0.046779444, 0.037412394 }, { -0.02214903, -0.025218605, 0.14797485, -0.051723623 }, { 0.021321783, 0.010405115, 0.0075476201, 0.0082410917 }, { 0.040559796, 0.027927916, -0.012812736, -0.0096642379 } }, { { -0.055647079, 0.017595207, 0.34495838, -0.03055759 }, { -0.058415094, 0.027416036, 0.18568916, 0.13044498 }, { 0.01482217, -0.17300703, 0.027540135, -0.2744944 }, { 0.25558424, -0.15324455, -0.29751197, -0.11422984 }, { -0.068936732, -0.11425403, 0.094767025, -0.0020892558 }, { 0.040887892, 0.031622148, -0.095292456, -0.02460001 }, { -0.0026237665, 0.017734103, 0.01213911, 0.0056586962 }, { -0.052138375, 0.052245567, 0.04608449, -0.043004468 }, { -0.17693366, 0.0021023738, 0.13167397, -0.14062006 }, { -0.20900333, 0.0057695127, 0.13057243, 0.046715668 }, { -0.020569928, -0.08439655, -0.09683347, 0.038139385 }, { 0.18196242, 0.44461908, -0.11388512, -0.12413082 }, { 0.072801844, -0.0017236427, -0.0026756083, 0.049805114 }, { -0.092195952, -0.0076195172, -0.22763849, -0.11320887 }, { 0.016234922, 0.007258942, 0.078535592, -0.084829275 }, { -0.15320003, 0.057490618, -0.16065455, -0.17063675 }, { -0.012856124, 0.024818957, 0.097529739, 0.11569844 }, { -0.11141243, 0.26677735, 0.1319403, -0.15699502 }, { -0.021128161, -0.12370585, 0.056198856, -0.1836225 }, { -0.01871806, 0.025525037, 0.063822152, 0.066517944 }, { -0.013759301, 0.11401068, -0.04701374, -0.021321516 }, { 0.032714649, -3.161284e-06, 0.026930697, 0.00019593482 }, { 0.10575127, 0.016956425, 0.016873291, 0.0049304377 }, { -0.11938883, 0.31242334, 0.29347156, -0.19514533 } } }, { { { -0.17374661, -0.028781395, -0.25993234, 0.27242277 }, { -0.13675759, -0.62291002, -0.80742781, 0.54260546 }, { 0.16876581, -0.052588487, 0.22415557, -0.59669887 }, { 0.1769234, 0.64210979, 0.81157479, -0.2718564 }, { -0.99873125, -0.013258174, 0.58939675, 0.99930085 }, { -0.30883355, -0.71116337, -0.76218623, 0.096388818 }, { 0.65749012, -0.54533843, -0.57508599, -0.70359398 }, { -0.27406769, 0.61006308, 0.1873512, 0.2563151 }, { -0.78453523, -0.13585943, -0.048534939, 0.02085237 }, { 0.40938527, -0.76981396, -0.42506866, 0.22362984 }, { 0.29003079, -0.20624421, 0.1151133, -0.50558933 }, { 0.0070051806, 0.20763719, 0.59485798, -0.61562639 }, { -0.4371111, 0.48314196, 0.72981069, 0.99889301 }, { 0.58257878, -0.8603979, -0.94188892, -0.83140889 }, { 0.71858167, -0.49534538, -0.63421799, -0.84488463 }, { 0.016158248, 0.65330502, 0.82883727, -0.127372 }, { -0.50292264, -0.14848746, -0.20836533, 0.2471481 }, { -0.15815031, -0.63472031, -0.79826416, 0.15325573 }, { -0.010424343, -0.022843894, 0.099730136, -0.26040744 }, { 0.15069433, 0.31188588, 0.63836617, -0.25234477 }, { -0.36946506, 0.92093529, 0.96548808, 0.62354203 }, { -0.57070465, -0.99847512, -0.47855156, -0.079970605 }, { 0.077467525, -0.71134336, -0.67172579, -0.66364974 }, { -0.27299386, 0.89512951, 0.61598356, 0.49577277 } }, { { 0.070458859, -0.28774455, 0.21287043, -0.094689772 }, { 0.0029548085, -0.31404605, -0.039280892, -0.3652277 }, { -0.033729607, 0.041215792, 0.065844258, -0.21509418 }, { 0.39270582, 0.067526811, 0.15655351, 0.053346856 }, { 0.052704394, -0.087801294, 0.18655104, 0.056114808 }, { -0.074582751, -0.055177669, -0.22165519, 0.13272162 }, { -0.027850171, 0.0029849066, -0.0062314784, -0.010484316 }, { 0.20753796, -0.0087111988, -0.13875075, -0.06137521 }, { 0.089744421, 0.07271039, 0.099417029, -0.22157272 }, { -0.013209094, 0.048633419, -0.26528065, -0.15253703 }, { 0.052922007, 0.24859103, 0.14406684, 0.13857649 }, { 0.00096142813, 0.32643367, 0.17939549, -0.39761314 }, { 0.013505803, -0.036986517, -0.12729111, 0.15459921 }, { -0.00049722057, -0.047063275, -0.0018666598, 0.1067114 }, { -0.074221027, -0.00927958, -0.029535811, -0.024240068 }, { -0.12387933, 0.06626829, 0.16422781, 0.077740779 }, { 0.14560404, -0.082132455, 0.027268021, 0.18857832 }, { 0.10470732, -0.29519533, -0.23666419, 0.10917064 }, { 0.042550279, 0.02436036, -0.31865644, -0.024987356 }, { -0.030434576, 0.082115299, 0.17770796, 0.020944092 }, { -0.17365377, 0.13807361, 0.12476029, 0.072738061 }, { -0.11503962, -0.04022554, 0.028018434, -0.070211356 }, { -0.043677907, 0.0053361863, 0.0039019898, 0.0027489647 }, { 0.27060899, -0.0016552279, 0.14166067, -0.25461265 } }, { { 0.014703402, 0.094752279, -0.32162049, 0.082335322 }, { -0.31539882, 0.44394592, 0.44316202, -0.031456167 }, { -0.024148679, 0.082370612, -0.0031744796, 0.098610537 }, { 0.46130367, -0.19989896, -0.56118891, 0.11979937 }, { 0.11784636, 0.079971516, -0.16977121, 0.014922099 }, { 0.018367216, -0.076519762, 0.13801492, 0.039682415 }, { -0.0027614728, 0.0010389006, -0.023126227, 0.0027068473 }, { 0.22249856, -0.071302328, 0.23721977, 0.10734273 }, { 0.41478408, -0.36611101, 0.18031261, -0.11176768 }, { 0.15800457, 0.23829725, -0.0016193556, 0.2112867 }, { -0.14793833, -0.15378785, 0.0082778301, 0.27105519 }, { -0.064743588, 0.44794816, -0.12599819, 0.4310022 }, { 0.092725214, 0.033947737, 0.19969884, 0.0072363359 }, { -0.074190657, 0.005985921, 0.300818, -0.090919095 }, { 0.024238118, -0.010955859, -0.068086841, -0.021137349 }, { 0.12196721, -0.19977338, -0.64428422, -0.30808722 }, { 0.46567096, -0.042072501, -0.1778338, 0.34294059 }, { -0.32528695, 0.25699981, 0.49346557, -0.20743316 }, { 0.10422458, 0.049488574, 0.49098274, -0.34871439 }, { 0.16431875, -0.050748897, -0.18464312, -0.61695364 }, { -0.1753479, 0.033238479, -0.046267845, -0.012339883 }, { -0.16098841, 0.080519992, -0.11793031, 0.036790025 }, { 0.017193144, -0.0029212372, -0.0044153187, -0.0057094316 }, { 0.23481771, -0.1556448, -0.18775429, -0.013697353 } } }, { { { 0.98467622, 0.94970347, 0.95791534, 0.9408684 }, { 0.95525144, 0.73013516, 0.58966657, 0.43166004 }, { 0.98562289, 0.95804118, 0.77397471, 0.78825859 }, { 0.96588112, 0.72807352, 0.58424502, 0.79142113 }, { -0.049305848, 0.63904864, 0.099145551, -0.03377918 }, { 0.78673348, 0.62998117, 0.62680207, 0.63245759 }, { 0.48526085, 0.544603, 0.40015579, 0.43297544 }, { 0.82487776, 0.77789448, 0.92917353, 0.91697567 }, { 0.58431326, 0.95748667, 0.99880743, 0.99975533 }, { 0.67096902, 0.60093643, 0.64381538, 0.92594344 }, { 0.95700408, 0.93816272, 0.93111608, 0.80905665 }, { 0.94046044, 0.97116483, 0.77381347, 0.78507504 }, { 0.7077214, 0.7547892, 0.23983411, -0.039180128 }, { 0.3656649, 0.38379871, -0.00015338393, 0.16604667 }, { 0.50679735, 0.6108265, 0.46821675, 0.37829596 }, { 0.55946029, 0.72460731, 0.55919425, 0.81214734 }, { 0.86277825, 0.92634645, 0.95542467, 0.96581976 }, { 0.95061533, 0.75913205, 0.60228234, 0.87287949 }, { 0.99994373, 0.93971324, 0.95087677, 0.96466059 }, { 0.9442062, 0.89161694, 0.72879505, 0.92100486 }, { 0.30989313, 0.29579046, 0.11395771, 0.071428407 }, { 0.16674735, -0.054071458, 0.85747916, 0.82737551 }, { 0.61593841, 0.45356879, 0.43544204, 0.41332561 }, { 0.79196443, 0.43841915, 0.77763172, 0.62193473 } }, { { 0.028699614, 0.071974788, -0.028868668, 0.030119772 }, { -0.16988515, -0.35713152, 0.36877151, 0.37172103 }, { 0.024472009, 0.10373643, 0.052160621, -0.12998364 }, { 0.051999909, -0.1688679, 0.05813266, -0.11063347 }, { 0.026373007, 0.067310776, 0.34433164, 0.0017481699 }, { -0.017659611, -0.10215276, -0.23736187, 0.12678732 }, { -0.0019097928, 0.02067204, -0.030447136, -0.0093192388 }, { 0.10615435, 0.11124023, 0.04473958, 0.14369936 }, { 0.14791062, -0.034502091, 0.041456555, 0.06737059 }, { 0.22389399, 0.2668048, 0.25742349, 0.03724758 }, { 0.0046009946, 0.066632032, 0.097957775, 0.22969631 }, { 0.043253167, -0.013638494, 0.071328387, -0.19249903 }, { -0.023561087, 0.011490741, 0.19824644, -0.04133258 }, { -0.057507532, -0.039265903, 0.060469313, 0.37300659 }, { 0.027051207, -0.0086784396, -0.0055877341, -0.0315352 }, { 0.15724931, 0.0099485187, 0.22462997, 0.14112999 }, { 0.13909905, 0.026199511, -0.12430815, -0.076900423 }, { -0.022327596, -0.1975812, 0.49862652, -0.096026553 }, { 0.076782007, 0.041598482, 0.0033451155, 0.039947963 }, { 0.005353589, 0.070993946, 0.0068174778, -0.17805261 }, { -0.059912765, -0.17027417, -0.060069718, 0.1561139 }, { 0.017122435, 0.048532637, -0.05315926, 0.066962855 }, { 0.058014377, 0.021874362, 0.017248667, -0.0069413843 }, { 0.099274028, 0.040622241, 0.040435904, 0.14191123 } }, { { -0.13453832, 0.071519908, -0.1597656, -0.030758273 }, { -0.13511715, 0.32373425, 0.35851035, -0.18685481 }, { 0.021440457, 0.034442875, 0.14324368, 0.15754565 }, { -0.061440371, 0.16837735, 0.47887644, -0.036265812 }, { 0.55060811, 0.14095672, 0.13077418, 0.25515565 }, { -0.084599968, -0.084002143, 0.1542308, 0.044223437 }, { 0.0017727822, 0.025149715, -0.025479364, -0.0023658361 }, { 0.1619123, 0.069159159, -0.016343512, 0.026108175 }, { 0.3296525, 0.029456656, 0.039715069, 0.015958704 }, { -0.093419591, 0.37051381, -0.063182977, -0.017764112 }, { 0.11962535, 0.062511772, -0.070445145, 0.27768911 }, { 0.07458833, -0.16218828, 0.064111239, 0.43889373 }, { -0.0326486, -0.03666828, -0.17597139, 0.34213144 }, { 0.061334301, -0.0099525239, 0.21497301, 0.0074569296 }, { -0.016749445, 0.00054557189, 0.040331287, 0.066200794 }, { 0.20620866, 0.25268529, 0.46594276, 0.059651923 }, { 0.15170896, 0.041438057, 0.021708506, -0.15049245 }, { -0.14317538, 0.13548996, 0.37297491, 0.13718874 }, { 0.053339004, 0.015014013, -0.10418356, -0.13598877 }, { -0.02227412, 0.045548464, 0.21534467, -0.23828118 }, { -0.055326885, 0.11851609, 0.28938409, 0.041373996 }, { -0.1219532, 0.57338554, -0.094571555, 0.025008596 }, { 0.070380772, 0.016993506, 0.018073937, -0.015404818 }, { 0.17033841, 0.12449473, 0.10847869, -0.11141982 } } }, { { { 4.409738, 4.5071479, 5.4761817, 5.3214091 }, { 5.3741435, 4.6270256, 5.4786338, 5.323679 }, { 4.305776, 4.4890731, 4.6894257, 4.6068436 }, { 5.4930574, 4.9116386, 5.4097636, 4.9225404 }, { 5.1861828, 5.5144226, 5.1307797, 5.0804212 }, { 6.1194597, 6.0655136, 5.7369562, 6.1076578 }, { 6.9549598, 6.9281578, 6.9549598, 6.9549598 }, { 4.5030565, 4.5849566, 4.4830953, 4.4904323 }, { 5.3629211, 5.5524848, 4.5719135, 4.9103175 }, { 4.8906163, 5.3972226, 4.8806206, 5.1834202 }, { 4.5047396, 4.5984947, 4.7039612, 4.3422371 }, { 4.5956963, 5.6294962, 4.46025, 4.4827131 }, { 5.8454206, 6.000743, 5.4594428, 4.9952614 }, { 6.09642, 6.3979283, 4.9784963, 5.6878449 }, { 6.9549598, 6.9752898, 6.9549598, 6.9549598 }, { 6.2053562, 4.9984547, 5.3887395, 4.6221036 }, { 4.5265196, 4.3684629, 5.5819288, 5.4957366 }, { 5.2220057, 4.6118907, 5.5046208, 4.9190037 }, { 4.3408178, 4.4980303, 5.4937404, 5.6154153 }, { 4.4802186, 4.4666194, 4.8546878, 5.1764252 }, { 5.7384024, 5.9048089, 5.4636107, 5.0807017 }, { 5.1013817, 5.2237041, 6.0338955, 5.8869417 }, { 6.9414339, 6.9549598, 6.9549598, 6.9549598 }, { 4.3368412, 4.9692663, 4.7090567, 4.9023075 } }, { { 0.0093525884, -0.33796029, -0.4366682, -0.18161326 }, { -0.34446047, 0.10854359, -0.61563912, -0.16514117 }, { 0.055849315, 0.093045585, 0.36722184, 0.085665647 }, { -0.21881508, -0.036846235, -0.25226403, -0.012790033 }, { -0.14697546, -0.026656628, 0.2559775, 0.026279081 }, { 0.073189287, -0.074472165, -0.15439557, 0.020907645 }, { 0, -0.015078298, 0, 0 }, { 0.027540893, -0.30876053, -0.15680794, -0.18470107 }, { -0.072547269, -0.019227086, -0.26735769, -0.1362069 }, { 0.36907279, -0.28005156, 0.01966203, -0.10277819 }, { -0.26755862, 0.066747173, 0.60834173, -0.23356165 }, { -0.12357338, -0.41742338, 0.081840746, -0.14596222 }, { -0.068599762, -0.004402392, -0.17192993, -0.15797464 }, { -0.072923207, -0.02555551, -0.21075071, 0.047272919 }, { 0, 0.0115085, 0, 0 }, { 0.32527558, 0.066048741, -0.28639187, 0.45171914 }, { -0.158086, -0.049098981, -0.17226122, -0.50289857 }, { -0.39456648, 0.031970902, -0.74883626, 0.20536003 }, { 0.22864705, -0.0095988927, -0.1155595, -0.06240073 }, { 0.12336497, -0.34128076, 0.34341316, 0.083678547 }, { -0.032718317, 0.076359349, -0.30099369, -0.016865529 }, { -0.23491753, -0.17228011, -0.044893186, -0.057411459 }, { -0.0077848677, 0, 0, 0 }, { -0.18713605, -0.11612415, 0.30907006, 0.064707406 } }, { { -0.20768494, -0.15642062, -0.079474216, -0.020948121 }, { -0.18767308, -0.013722599, 0.15827086, -0.27421942 }, { -0.11484158, -0.29325715, 0.24426149, 0.34598577 }, { -0.095599056, 0.16784413, 0.23369965, 0.15036114 }, { 0.058496274, -0.064565923, -0.076598803, -0.11988702 }, { -0.03406356, -0.010863931, -0.036116475, 0.0077051595 }, { 0, -0.015078298, 0, 0 }, { -0.21271534, 0.31678528, 0.084310434, -0.039787477 }, { 0.057420352, -0.60894321, -0.14275706, -0.29178151 }, { -0.21477227, 0.091254596, -0.053659362, -0.13299553 }, { -0.24972574, 0.22261101, -0.59415755, -0.13299464 }, { -0.406027, 0.15018847, 0.33281927, 0.28006105 }, { -0.033198856, 0.013081228, 0.0098634494, -0.18858267 }, { -0.16914457, -0.014917022, -0.15618156, 0.038961385 }, { 0, 0.0115085, 0, 0 }, { 0.047340338, -0.052961301, 0.30193278, 0.38564757 }, { -0.2009302, -0.15247105, -0.32333852, 0.22878398 }, { -0.22934017, 0.022888443, 0.30911154, -0.12420416 }, { 0.21191356, -0.33281926, -0.13523708, -0.038546557 }, { 0.28507859, -0.012777666, 0.16285544, -0.12612215 }, { -0.057034227, 0.01719448, -0.037892291, -0.13064036 }, { -0.075888865, 0.041589292, 0.0089100653, -0.10775402 }, { 0.0075560462, 0, 0, 0 }, { -0.18120766, 0.16485298, 0.58949587, 0.072313493 } } }, { { { 0.60381773, 0.64633179, 0.92301353, 0.23720177 }, { 1.1128727, 0.42172315, 1.6605811, 0.22066721 }, { 0.55829912, 0.7107351, 0.47437673, 0.53646626 }, { 0.75684406, 0.65607146, 1.5264507, 0.12817954 }, { -0.25070514, 0.30263175, -0.21070678, -0.2264813 }, { -0.24745858, -0.26801252, 0.2750925, 0.055035565 }, { -0.018769156, -0.066023008, 0.10111114, 0.0089232736 }, { 0.41152465, 0.52508091, 0.4161358, 0.39058287 }, { 0.90919582, 1.2448772, 0.61547497, 0.51303689 }, { 0.2973136, 1.2348603, 0.24154398, 0.76087607 }, { 0.23369317, 0.68368068, 0.81024353, 0.35451079 }, { 0.69272073, 0.47014545, 0.61401877, 0.43768641 }, { -0.44449894, -0.10123077, -0.19173956, -0.15811184 }, { -0.089717, -0.068601549, -0.16704813, -0.29761406 }, { 0.0055968308, -0.089855929, -0.087150641, 0.2244144 }, { 0.38902787, 0.62620686, 1.3314901, 0.26038797 }, { 0.16776511, 0.32722251, 0.71914611, 0.53556119 }, { 0.63106992, 0.46256454, 1.785895, 0.17339911 }, { 0.72516261, 0.44941094, 0.81174974, 0.61247129 }, { 0.56877815, 0.20989179, 0.7607991, 0.017998645 }, { 0.016372087, 0.26062407, -0.32771461, -0.075930098 }, { -0.11957223, -0.22579003, -0.42587945, -0.0015549589 }, { 0.0049992009, 0.053511694, 0.00053268274, 0.022778575 }, { 0.19356675, 0.5564623, 0.74981777, 0.28733119 } }, { { 0.017029304, 0.22690356, 0.25927682, -0.048136042 }, { 0.52936856, -0.26082526, 0.12568074, -0.046727529 }, { 0.08949554, -0.019090555, 0.31477592, -0.067513409 }, { 0.056302335, -0.011819435, -0.063621104, 0.27092306 }, { 0.053971592, -0.17913246, -0.14991651, -0.044263405 }, { 0.29037749, -0.040498369, -0.33600753, 0.16250066 }, { -0.067102844, -0.17843768, 0.033172168, 0.13638573 }, { 0.057127881, -0.044468822, 0.33005778, 0.34775491 }, { -0.14300931, 0.022121077, -0.045281831, -0.065216583 }, { 0.084931489, 0.06688461, 0.15758114, -0.091330485 }, { -0.014274888, 0.29139103, 0.089163749, -0.18005467 }, { -0.2191522, -0.1333803, -0.31948964, -0.28536602 }, { 0.20298891, -0.0031882515, -0.15749696, -0.014977715 }, { -0.14016857, -0.17278064, 0.01369474, 0.10971499 }, { 0.018219806, 0.080447764, 0.0056022696, -0.043028475 }, { -0.076556403, -0.13038184, -0.23788273, 0.5849635 }, { 0.1038427, 0.18199702, 0.35294355, -0.0023601311 }, { 0.22294845, -0.37427713, 0.2907529, 0.26234219 }, { 0.40809306, 0.12982813, 0.42857338, 0.14064303 }, { 0.4265028, 0.18710053, 0.15310514, 0.067551813 }, { -0.18986488, -0.029676062, -0.087045959, -0.14788626 }, { -0.07865478, 0.011558295, -0.018262356, 0.38992629 }, { 0.22297641, 0.072192947, 0.064119712, 0.12862555 }, { -0.069262467, -0.14990585, 0.31342655, -0.15002022 } }, { { 0.25288162, -0.096551539, 0.051695506, 0.20925392 }, { 0.23093904, 0.096712594, 0.19826434, 0.32530694 }, { 0.14114785, 0.071010138, -0.17642029, 0.092260082 }, { 0.39001648, -0.17666595, 0.088397252, 0.1462816 }, { 0.12484597, 0.066920676, -0.16116194, 0.21758387 }, { 0.15625272, -0.00043631439, -0.07868976, -0.19261141 }, { -0.0142415, 0.06356153, 0.026276923, -0.024546668 }, { 0.097089221, 0.085426402, 0.11936115, 0.012042542 }, { 0.52509109, -0.22465399, -0.11490612, 0.023562122 }, { -0.12418278, 0.11985465, 0.087804943, 0.25283464 }, { 0.10716753, -0.036426901, 0.2469409, -0.095816257 }, { -0.095364501, 0.14001518, -0.068636804, -0.082487255 }, { 0.074490355, 0.25323233, 0.17863748, 0.12482145 }, { -0.019616587, -0.0053326518, 0.047558858, 0.066104462 }, { 0.12647102, 0.25712368, 0.12306783, -0.050252261 }, { -0.13375041, 0.17825067, 0.026649645, -0.33338076 }, { 0.16384463, -0.022241979, 0.17817325, 0.6808721 }, { 0.42075944, -0.024292721, -0.11323318, 0.45027063 }, { -0.023953485, 0.25719992, 0.28680108, 0.33600529 }, { 0.013445546, 0.22504275, 0.17408162, 0.52860686 }, { -0.098839039, -0.27017244, 0.10293505, -0.012472685 }, { 0.074267375, -0.0056418849, 0.17632358, 0.21754089 }, { 0.1491061, 0.017927571, -0.0217757, -0.0039381966 }, { 0.067239102, -0.74624136, 0.12992555, -0.058866581 } } } }, { { { { 0.1270204, 0.7650174, 0.55252173, 0.05956498 }, { -0.36870832, 0.31227245, 0.52167466, 0.4282174 }, { -0.036761861, -0.5477415, -0.76091563, -0.37583127 }, { 0.17129434, -0.14281209, -0.40463148, -0.56367877 }, { 0.07429238, 0.45420144, 0.41919765, 0.019225986 }, { -0.44125436, -0.05567539, 0.080551064, 0.54444995 }, { -0.36600455, -0.55359309, -0.3290331, 0.33946169 }, { 0.65253747, 0.015186649, 0.0665303, -0.64649501 }, { 0.05392469, 0.54355001, 0.7539307, -0.41089455 }, { -0.29264863, 0.49684721, 0.39184208, 0.47737193 }, { 0.10885354, -0.80803227, -0.7443769, -0.3736688 }, { 0.1939378, -0.079590275, -0.42241709, -0.75536039 }, { 0.44776697, 0.44884546, 0.427965, 0.3297221 }, { -0.34595785, 0.27723463, 0.12245317, 0.43884357 }, { 0.18467758, -0.55582608, -0.99421464, -0.0096027817 }, { 0.6672057, -0.038103784, -0.048616141, -0.68508055 }, { -0.016615937, 0.62001729, 0.50530563, -0.22211425 }, { -0.16823123, 0.31934529, 0.47092187, 0.4884373 }, { 0.03194189, -0.5624624, -0.44688229, 0.223814 }, { 0.17828041, -0.080017082, -0.44239439, -0.46726625 }, { 0.19895649, 0.82568772, 0.47859751, 0.064443297 }, { -0.47464217, 0.011895223, 0.01123465, -0.010697203 }, { -0.17670677, -0.66931423, -0.5814681, -0.01325001 }, { 0.65193874, -0.010713062, -0.007915928, -0.65520853 } }, { { -0.01027431, -0.0019056004, 0.0020213958, 0.0064495753 }, { 0.0058416688, 0.0051314639, 0.021497114, 0.005870592 }, { -0.00035518612, -0.00087553938, -0.0029318969, 0.0087577986 }, { -0.0048770476, -0.015949665, -0.034816051, -0.006104917 }, { 0.0015371362, -0.0012591621, 0.01241148, 0.00096621463 }, { 0.0032416133, 0.021025709, 0.0036344622, 0.0015436078 }, { -0.0093946276, 0.0046564763, 0.028177476, -0.01022744 }, { 0.00014675555, 0.030031482, -0.0092302407, -0.001999398 }, { -0.049980321, 0.024752279, 0.016684689, -0.0045230976 }, { 0.0067493834, 0.014071508, 0.0079316435, 0.034593704 }, { 0.01971715, -0.0037227013, -0.013430278, -0.024257585 }, { -0.004342319, 0.024001878, -0.013356442, -0.022792018 }, { -0.0051709665, -0.017029547, 0.040567567, 0.0052520812 }, { 0.0090399102, 0.0079604733, 0.00018765016, -0.0092868977 }, { -0.020304032, 0.0056590257, -0.0045373063, -0.018653318 }, { -9.9636934e-05, 0.002001886, 0.0046843544, 0.0055608043 }, { 0.0018025744, -0.0025962216, 0.0068285574, -0.014851062 }, { 0.00041645221, 0.0054738242, 0.0076769026, -0.013419208 }, { 0.0038347099, -0.0042555066, -0.0066470075, 0.0039146778 }, { -0.009084153, 0.024461537, 0.0034578066, -0.0054827001 }, { 0.0033463477, 0.0045594748, 0.00037604935, -0.01571513 }, { -0.012589588, 0.029678359, -0.019924871, -0.004708459 }, { -0.0002642682, -0.0051057336, -0.0042867302, -0.00041141781 }, { -0.00086487068, -0.0025170841, 0.0030062196, -0.0030385417 } }, { { -0.01027431, -0.0019056004, 0.0020213958, 0.0064495753 }, { 0.0058416688, 0.0051314639, 0.021497114, 0.005870592 }, { -0.00035518612, -0.00087553938, -0.0029318969, 0.0087577986 }, { -0.0048770476, -0.015949665, -0.034816051, -0.006104917 }, { 0.0015371362, -0.0012591621, 0.01241148, 0.00096621463 }, { 0.0032416133, 0.021025709, 0.0036344622, 0.0015436078 }, { -0.0093946276, 0.0046564763, 0.028177476, -0.01022744 }, { 0.00014675555, 0.030031482, -0.0092302407, -0.001999398 }, { -0.049980321, 0.024752279, 0.016684689, -0.0045230976 }, { 0.0067493834, 0.014071508, 0.0079316435, 0.034593704 }, { 0.01971715, -0.0037227013, -0.013430278, -0.024257585 }, { -0.004342319, 0.024001878, -0.013356442, -0.022792018 }, { -0.0051709665, -0.017029547, 0.040567567, 0.0052520812 }, { 0.0090399102, 0.0079604733, 0.00018765016, -0.0092868977 }, { -0.020304032, 0.0056590257, -0.0045373063, -0.018653318 }, { -9.9636934e-05, 0.002001886, 0.0046843544, 0.0055608043 }, { 0.0018025744, -0.0025962216, 0.0068285574, -0.014851062 }, { 0.00041645221, 0.0054738242, 0.0076769026, -0.013419208 }, { 0.0038347099, -0.0042555066, -0.0066470075, 0.0039146778 }, { -0.009084153, 0.024461537, 0.0034578066, -0.0054827001 }, { 0.0033463477, 0.0045594748, 0.00037604935, -0.01571513 }, { -0.012589588, 0.029678359, -0.019924871, -0.004708459 }, { -0.0002642682, -0.0051057336, -0.0042867302, -0.00041141781 }, { -0.00086487068, -0.0025170841, 0.0030062196, -0.0030385417 } } }, { { { -0.68772793, 0.19029367, -0.17427646, 0.60300616 }, { -0.29980532, -0.22397537, -0.4071009, 0.36277983 }, { 0.75628069, -0.13426242, 0.13645381, -0.74653491 }, { 0.14891408, -0.13497977, 0.36807879, -0.39814386 }, { -0.20608987, -0.076497863, -0.19510375, 0.34604256 }, { -0.02421123, -0.4588774, -0.64965351, 0.083039161 }, { 0.51918764, -0.30614677, -0.25791921, -0.40837612 }, { 0.028860181, 0.63152733, 0.5876224, -0.033139773 }, { -0.63418144, 0.046874151, 0.24431924, 0.71662556 }, { -0.29088451, -0.21455586, -0.73980807, 0.65038559 }, { 0.78663226, 0.00020858525, 0.40361403, -0.75720144 }, { 0.1998276, 0.54590973, 0.1773378, -0.35464319 }, { -0.40236144, 0.31362578, -0.34406026, 0.38120073 }, { -0.27845549, -0.46862161, -0.47141499, 0.095899189 }, { 0.6004921, 0.28051621, -0.011378178, -0.98141078 }, { 0.032724674, 0.66798127, 0.66430425, -0.05209965 }, { -0.59603974, -0.083198329, 0.34616224, 0.42082916 }, { -0.14262632, -0.21418442, -0.37504914, 0.32676687 }, { 0.58204273, 0.0067537174, -0.35923481, -0.40792038 }, { 0.15607366, 0.17215007, 0.34414936, -0.33566945 }, { -0.44862333, 0.004919013, 0.0076768115, 0.41897935 }, { -0.022062848, -0.39695079, -0.0062786656, 0.042925103 }, { 0.65953535, -0.15521993, 0.011867978, -0.57721165 }, { 0.031305912, 0.65627006, 0.66779002, -0.029815636 } }, { { 0.011457792, -0.011774949, -0.012205337, 0.0048139052 }, { -0.024024566, 0.018313023, -0.023210623, -0.0046351547 }, { 0.0039133571, 0.0046801024, -0.020590099, -0.0018568631 }, { -0.015369931, -0.0092621276, -0.026149742, 0.0010335971 }, { 0.032555144, -0.01336897, -0.022733265, -0.027997469 }, { -0.028161537, -0.00073877629, -0.023989631, 0.0055660453 }, { -0.012966193, 0.003944376, 0.025685982, -0.0017458044 }, { 0.00015626641, -0.009524206, 0.0083025026, -0.00049753811 }, { -0.02358661, 0.006370149, 0.00087066462, -0.00054248544 }, { -0.0024571244, -0.023218369, -0.010895303, -0.0095647684 }, { 0.0069970393, -0.00093403301, -0.0081922371, -0.00026359768 }, { 0.0065921354, 0.028846533, -0.045676337, 0.006070217 }, { 0.0045248423, -0.0084676847, 0.028756195, 0.020612871 }, { 0.0037691244, -0.0069385161, -0.00029501448, -0.0017839033 }, { -0.0048675353, -0.011930456, 0.0044251285, -0.00016323616 }, { -0.0012291164, -0.0019575288, 0.0078250029, -0.0011151155 }, { 0.00503333, -0.0094538968, 0.0092375183, 0.018207648 }, { 0.0080615812, -0.0073583459, -0.0166794, 0.016416158 }, { 0.002192959, -0.01153759, -0.0048668362, -0.0071123281 }, { -0.010116143, -0.010224552, 0.010897731, 0.00093792816 }, { 0.017199359, -0.0087516179, 0.0021169251, -0.020946959 }, { -0.01570063, 0.020087246, 0.014492818, -0.016014018 }, { 0.0023484072, 0.0015070243, -0.00045616273, -0.001211882 }, { 0.0018090492, -0.0012261901, 0.0012809284, 0.00096488905 } }, { { 0.011457792, -0.011774949, -0.012205337, 0.0048139052 }, { -0.024024566, 0.018313023, -0.023210623, -0.0046351547 }, { 0.0039133571, 0.0046801024, -0.020590099, -0.0018568631 }, { -0.015369931, -0.0092621276, -0.026149742, 0.0010335971 }, { 0.032555144, -0.01336897, -0.022733265, -0.027997469 }, { -0.028161537, -0.00073877629, -0.023989631, 0.0055660453 }, { -0.012966193, 0.003944376, 0.025685982, -0.0017458044 }, { 0.00015626641, -0.009524206, 0.0083025026, -0.00049753811 }, { -0.02358661, 0.006370149, 0.00087066462, -0.00054248544 }, { -0.0024571244, -0.023218369, -0.010895303, -0.0095647684 }, { 0.0069970393, -0.00093403301, -0.0081922371, -0.00026359768 }, { 0.0065921354, 0.028846533, -0.045676337, 0.006070217 }, { 0.0045248423, -0.0084676847, 0.028756195, 0.020612871 }, { 0.0037691244, -0.0069385161, -0.00029501448, -0.0017839033 }, { -0.0048675353, -0.011930456, 0.0044251285, -0.00016323616 }, { -0.0012291164, -0.0019575288, 0.0078250029, -0.0011151155 }, { 0.00503333, -0.0094538968, 0.0092375183, 0.018207648 }, { 0.0080615812, -0.0073583459, -0.0166794, 0.016416158 }, { 0.002192959, -0.01153759, -0.0048668362, -0.0071123281 }, { -0.010116143, -0.010224552, 0.010897731, 0.00093792816 }, { 0.017199359, -0.0087516179, 0.0021169251, -0.020946959 }, { -0.01570063, 0.020087246, 0.014492818, -0.016014018 }, { 0.0023484072, 0.0015070243, -0.00045616273, -0.001211882 }, { 0.0018090492, -0.0012261901, 0.0012809284, 0.00096488905 } } }, { { { 0.71476997, 0.61525336, 0.81507512, 0.79550964 }, { 0.87986984, 0.9232123, 0.74974956, 0.82765975 }, { 0.65321366, 0.82580437, 0.63434042, 0.54903231 }, { 0.97390084, 0.98050251, 0.83713283, 0.72370416 }, { 0.97570877, 0.88760866, 0.88668363, 0.9380218 }, { 0.89705541, 0.88675351, 0.75595095, 0.83467284 }, { 0.77232433, 0.77447327, 0.9084134, 0.84734569 }, { -0.75720667, -0.77520488, -0.80639546, -0.76219811 }, { 0.77130152, 0.83806694, 0.60983327, 0.56357207 }, { 0.91090229, 0.84089752, 0.54694041, 0.59085922 }, { 0.60775044, 0.58913818, 0.53197627, 0.53574024 }, { 0.96044628, 0.83405513, 0.88888419, 0.55105253 }, { 0.79850486, 0.83676557, 0.83574428, 0.86369517 }, { 0.89597751, 0.83876978, 0.87336884, 0.8934314 }, { 0.77801249, 0.78253947, 0.10680725, 0.19167855 }, { -0.74415432, -0.74320194, -0.74587957, -0.72660186 }, { 0.802783, 0.78016447, 0.79046691, 0.87952719 }, { 0.97537479, 0.92311625, 0.79848027, 0.80910594 }, { 0.8125306, 0.82679528, 0.81929639, 0.88516002 }, { 0.97152309, 0.98181547, 0.82815966, 0.81791703 }, { 0.87129411, 0.56410602, 0.87800085, 0.905706 }, { 0.87990229, 0.91776281, 0.99991718, 0.99902102 }, { 0.73060786, 0.72658464, 0.81348263, 0.81648708 }, { -0.75762512, -0.75445002, -0.74430762, -0.75485946 } }, { { 0.018332644, 0.0084005452, -0.0018937689, -0.0035491975 }, { 0.0016556654, 0.0049261013, -0.021796869, 0.0025973591 }, { -0.0019671758, 0.00051947074, 0.0071261223, 0.0056689139 }, { 0.00041901024, -0.0023903288, -0.0035639711, -0.0036673013 }, { 0.009963464, 0.00099195429, -0.0042516892, 0.0092605531 }, { 0.0034813664, 0.0028575465, -0.016343415, -0.0014475905 }, { 0.0053571039, 0.0051116063, 0.016171091, -0.00052744238 }, { 0.00013272575, -0.0095491849, 0.0070156475, 0.0017057538 }, { 0.028067438, -0.0086835729, -0.0087852674, 0.0035321054 }, { 0.0025007808, -0.0075654884, -0.012551417, -0.0068823899 }, { -0.00017607308, 0.002636122, -0.011272055, -0.010314896 }, { 0.010646599, 0.00042804331, 0.013900837, -0.01279076 }, { 0.0059898286, 0.012331371, -0.0073125296, 0.016248603 }, { 0.031579315, -0.0057840222, -0.00018304192, 0.005171422 }, { 0.010928513, 0.0092660887, 0.030404621, 0.0053167707 }, { -0.00014899672, -0.0035246494, 0.0075862845, -0.005861723 }, { 0.0067791918, 0.0021224495, -0.0071755505, -0.010370936 }, { 0.0015352958, -0.0025785166, -0.0092688001, 0.003966373 }, { 0.0036915074, -0.002306452, -0.005736452, -0.0033594125 }, { 0.0065128512, 0.006188005, 0.00088322638, -0.0016227066 }, { 0.0092720771, -0.0046684631, -7.3769604e-05, 0.013807013 }, { -0.0031421984, 0.010622679, 0.00041591214, 0.0032786075 }, { -0.0021421613, -0.0041675589, -0.0029529994, -0.00085350449 }, { -0.00069204344, -0.0010785124, 0.00097549628, 0.0025280456 } }, { { 0.018332644, 0.0084005452, -0.0018937689, -0.0035491975 }, { 0.0016556654, 0.0049261013, -0.021796869, 0.0025973591 }, { -0.0019671758, 0.00051947074, 0.0071261223, 0.0056689139 }, { 0.00041901024, -0.0023903288, -0.0035639711, -0.0036673013 }, { 0.009963464, 0.00099195429, -0.0042516892, 0.0092605531 }, { 0.0034813664, 0.0028575465, -0.016343415, -0.0014475905 }, { 0.0053571039, 0.0051116063, 0.016171091, -0.00052744238 }, { 0.00013272575, -0.0095491849, 0.0070156475, 0.0017057538 }, { 0.028067438, -0.0086835729, -0.0087852674, 0.0035321054 }, { 0.0025007808, -0.0075654884, -0.012551417, -0.0068823899 }, { -0.00017607308, 0.002636122, -0.011272055, -0.010314896 }, { 0.010646599, 0.00042804331, 0.013900837, -0.01279076 }, { 0.0059898286, 0.012331371, -0.0073125296, 0.016248603 }, { 0.031579315, -0.0057840222, -0.00018304192, 0.005171422 }, { 0.010928513, 0.0092660887, 0.030404621, 0.0053167707 }, { -0.00014899672, -0.0035246494, 0.0075862845, -0.005861723 }, { 0.0067791918, 0.0021224495, -0.0071755505, -0.010370936 }, { 0.0015352958, -0.0025785166, -0.0092688001, 0.003966373 }, { 0.0036915074, -0.002306452, -0.005736452, -0.0033594125 }, { 0.0065128512, 0.006188005, 0.00088322638, -0.0016227066 }, { 0.0092720771, -0.0046684631, -7.3769604e-05, 0.013807013 }, { -0.0031421984, 0.010622679, 0.00041591214, 0.0032786075 }, { -0.0021421613, -0.0041675589, -0.0029529994, -0.00085350449 }, { -0.00069204344, -0.0010785124, 0.00097549628, 0.0025280456 } } }, { { { 5.3792285, 5.1960477, 5.5112916, 5.6615254 }, { 5.0489877, 5.2428834, 5.1752035, 5.1109826 }, { 5.5205204, 5.7511938, 5.0202917, 4.9168865 }, { 4.9522523, 4.8880256, 5.1015936, 5.2858816 }, { 5.7256502, 5.7919759, 5.645241, 5.6035708 }, { 6.4076931, 6.4822111, 6.2642633, 6.3925959 }, { 6.9797014, 6.981436, 7.0028674, 6.9976464 }, { -0.03290957, -0.03290957, -0.03290957, -0.03290957 }, { 5.4977854, 5.7684965, 5.3463095, 4.8810492 }, { 4.9869047, 5.4896416, 4.9647805, 4.884877 }, { 5.3141219, 5.3357788, 4.7695434, 4.8709631 }, { 5.2056063, 5.407802, 5.2123857, 4.9428208 }, { 6.2188218, 6.17756, 6.2751008, 6.3672109 }, { 6.9105856, 6.7986798, 6.5712335, 6.5907061 }, { 6.9797014, 6.9797014, 5.6859993, 5.5642483 }, { -0.032764603, -0.032764603, -0.032764603, -0.032764603 }, { 5.7724142, 6.0929556, 5.99581, 5.9265164 }, { 4.9363192, 4.9823732, 5.1732995, 5.2475265 }, { 5.8365191, 5.9972902, 5.9778441, 5.9270668 }, { 4.8706768, 5.0194503, 5.155585, 5.2188041 }, { 6.1569904, 6.0563989, 6.0989699, 6.2139837 }, { 5.8727399, 5.8948086, 5.5734095, 5.5536103 }, { 6.9797014, 6.9797014, 6.9797014, 6.9797014 }, { -0.032766769, -0.032766769, -0.032766769, -0.032766769 } }, { { 0.0011802354, -0.006546101, -0.02103972, 0.0008654047 }, { -0.015460534, 0.017874544, 0.0029121134, 0.023511773 }, { -0.040909245, 0.011927691, 0.011991588, 0.01677931 }, { -0.015633544, -0.0042321141, 0.026623034, 0.0080414514 }, { 0.012614382, 0.0065080145, 0.035716738, -0.0080665814 }, { -0.0057849744, -0.017478461, -0.031219642, 0.00016446523 }, { 0, 0.00032235028, 0, 0 }, { 0, 0, 0, 0 }, { -0.068586697, -0.024228236, -0.012857221, -0.039493706 }, { -0.018078201, -0.015140979, 0.00072119173, -0.051249859 }, { -0.054228277, 0.0097895101, 0.0019832646, -0.011715411 }, { -0.042326208, -0.010160072, 0.037088052, -0.031848667 }, { 0.00067130897, -0.013966717, -0.017268559, -0.0074614576 }, { 0.070515961, 0.012848107, -0.0008396517, 0.0049006506 }, { 0, 0, -0.063014256, -0.0085124986 }, { 0, 0, 0, 0 }, { -0.040302299, 0.0048936307, 0.0064406394, 0.0034044871 }, { -0.010453589, 0.0035820836, -0.017384391, -0.038199947 }, { -0.044968611, -0.0088322127, 0.020303819, 0.0058131005 }, { -0.0056838535, 0.010211409, -0.010999927, -0.027621859 }, { 0.0064753811, -0.0059341242, -0.014902755, 0.0082868118 }, { -0.0013222735, 0.0028492181, -0.023523273, -0.02576271 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } }, { { 0.0011802354, -0.006546101, -0.02103972, 0.00086540469 }, { -0.015460534, 0.017874544, 0.0029121134, 0.023511773 }, { -0.040909245, 0.011927691, 0.011991588, 0.01677931 }, { -0.015633544, -0.0042321141, 0.026623034, 0.0080414514 }, { 0.012614382, 0.0065080145, 0.035716738, -0.0080665814 }, { -0.0057849744, -0.017478461, -0.031219642, 0.00016446523 }, { 0, 0.00032235028, 0, 0 }, { 0, 0, 0, 0 }, { -0.068586697, -0.024228236, -0.012857221, -0.039493706 }, { -0.018078201, -0.015140979, 0.00072119173, -0.051249859 }, { -0.054228277, 0.0097895101, 0.0019832646, -0.011715411 }, { -0.042326208, -0.010160072, 0.037088052, -0.031848667 }, { 0.00067130897, -0.013966717, -0.017268559, -0.0074614576 }, { 0.070515961, 0.012848107, -0.0008396517, 0.0049006506 }, { 0, 0, -0.063014256, -0.0085124986 }, { 0, 0, 0, 0 }, { -0.040302299, 0.0048936307, 0.0064406394, 0.0034044871 }, { -0.010453589, 0.0035820836, -0.017384391, -0.038199947 }, { -0.044968611, -0.0088322127, 0.020303819, 0.0058131005 }, { -0.0056838535, 0.010211409, -0.010999927, -0.027621859 }, { 0.0064753811, -0.0059341242, -0.014902755, 0.0082868118 }, { -0.0013222735, 0.0028492181, -0.023523273, -0.02576271 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } } }, { { { 0.72189984, 0.22069996, 0.71952927, 0.77725949 }, { 0.4054405, 0.20582059, 0.2747016, 0.37612563 }, { 0.58887422, 0.27441131, 0.19468101, 0.21480554 }, { 0.46814145, 0.34317, 0.46068212, 0.13962064 }, { -0.18134132, -0.26668789, -0.60984999, -0.67879259 }, { -0.47870351, -0.34453227, 0.32494779, 0.10292971 }, { 0.087252967, 0.066950358, 0.31813819, 0.071094818 }, { -0.0031436256, 0.038245091, -0.0076651913, -0.015389479 }, { 1.2668531, 1.2894974, 0.40584018, 0.51755806 }, { 1.3207257, 1.3403747, 0.54924634, 0.40282713 }, { 0.78581828, 0.56379328, 0.27901993, 0.56429306 }, { 0.8748226, 1.0271253, 1.0085726, 0.3888545 }, { -0.22577636, -0.32895071, -0.2846317, -0.11679531 }, { 0.26477285, 0.3179447, -0.063393238, 0.024059773 }, { -0.15463395, -0.22721468, -0.20680404, -0.15700788 }, { 0.012107106, -0.0061245949, -0.024224367, 0.005040693 }, { 0.97943693, 0.64840429, 0.45106998, 0.40771935 }, { 0.49907853, 0.1562184, 0.34338458, 0.39710628 }, { 0.95047709, 0.53336107, 0.38318275, 0.44919148 }, { 0.41892697, 0.069965886, 0.45831656, 0.38821529 }, { -0.20216736, -0.43209441, -0.57684857, -0.40189427 }, { -0.63992377, -0.40683032, -0.59207903, -0.57251716 }, { -0.047117438, -0.1880015, -0.12265155, 0.00059988607 }, { -0.011836442, -0.010049497, -0.0026152072, 0.016137736 } }, { { 0.092068993, 0.0045466749, 0.0054574031, 0.02582156 }, { 0.022115456, -0.015664041, -0.022004653, 0.041431654 }, { 0.029951298, -0.0004408542, 0.0087496069, 0.017850027 }, { 0.029086373, 0.022116039, 0.044010315, 0.001644876 }, { 0.016256387, 0.0083249367, 0.019570849, -0.0021276222 }, { 0.0079070076, -0.024696939, 0.044311101, 0.023671132 }, { -0.0081796119, -0.0024995551, 0.033501743, -0.031958988 }, { 0.0065005403, -0.076642001, 0.015736477, 0.030966939 }, { 0.029110717, 0.039154477, -0.074376619, 0.025532063 }, { -0.10980761, 0.0038346834, 0.014449171, -0.030702653 }, { -0.00068350423, -0.037251569, -0.008409224, -0.026322878 }, { 0.035406012, 0.064176275, 0.031437854, -0.0344642 }, { 0.037145809, -0.024909212, 0.041030386, 0.035216105 }, { -0.093276646, -0.013904083, -0.019536023, -0.023834405 }, { 0.042751846, -0.03620164, 0.081115921, 0.018379967 }, { -0.023909625, 0.012833691, 0.048086442, -0.0097340268 }, { 0.039552712, -0.00026806514, 0.011646753, 0.0065939486 }, { 0.058985248, 0.020165701, 0.0076721521, 0.033274221 }, { 0.052889871, 0.0042520093, 0.016490396, 0.009287973 }, { 0.044305975, -0.0016263469, 0.041390177, 0.033541355 }, { 0.014595133, -0.004801042, -0.0049517302, 0.015714264 }, { 0.00075086205, 0.0080838736, -0.037611057, -0.030488441 }, { 0.0019178075, -0.0082517768, -0.002525773, 0.0043993022 }, { 0.023774971, 0.020335611, 0.0056643868, -0.032100338 } }, { { 0.092068993, 0.0045466749, 0.0054574031, 0.02582156 }, { 0.022115456, -0.015664041, -0.022004653, 0.041431654 }, { 0.029951298, -0.0004408542, 0.0087496069, 0.017850027 }, { 0.029086373, 0.022116039, 0.044010315, 0.001644876 }, { 0.016256387, 0.0083249367, 0.019570849, -0.0021276222 }, { 0.0079070076, -0.024696939, 0.044311101, 0.023671132 }, { -0.0081796119, -0.0024995551, 0.033501743, -0.031958988 }, { 0.0065005403, -0.076642001, 0.015736477, 0.030966939 }, { 0.029110717, 0.039154477, -0.074376619, 0.025532063 }, { -0.10980761, 0.0038346834, 0.014449171, -0.030702653 }, { -0.00068350423, -0.037251569, -0.008409224, -0.026322878 }, { 0.035406012, 0.064176275, 0.031437854, -0.0344642 }, { 0.037145809, -0.024909212, 0.041030386, 0.035216105 }, { -0.093276646, -0.013904083, -0.019536023, -0.023834405 }, { 0.042751846, -0.03620164, 0.081115921, 0.018379967 }, { -0.023909625, 0.012833691, 0.048086442, -0.0097340268 }, { 0.039552712, -0.00026806514, 0.011646753, 0.0065939486 }, { 0.058985248, 0.020165701, 0.0076721521, 0.033274221 }, { 0.052889871, 0.0042520093, 0.016490396, 0.009287973 }, { 0.044305975, -0.0016263469, 0.041390177, 0.033541355 }, { 0.014595133, -0.004801042, -0.0049517303, 0.015714264 }, { 0.00075086205, 0.0080838736, -0.037611057, -0.030488441 }, { 0.0019178075, -0.0082517768, -0.002525773, 0.0043993022 }, { 0.023774971, 0.020335611, 0.0056643868, -0.032100338 } } } } };
+const float high_quality_coeffs[7][5][3][24][4] = { { { { { -4.8355339e-06f, -4.4902569e-05f, -9.2632249e-05f, -0.00053773136f }, { 0.0040143823f, -0.00060900339f, -0.0095301923f, -0.0053956011f }, { -0.0005923892f, -3.6901978e-05f, -5.6694857e-06f, -0.00017018564f }, { 0.0012441402f, 0.02236187f, 0.022751769f, 0.0062788948f }, { 0.00013810055f, -2.2709815e-05f, 0.0054849671f, -1.6599195e-05f }, { -0.020320408f, -0.017066319f, -0.017457746f, 0.022910628f }, { 0.00024171724f, 9.7419073e-05f, -0.00047804272f, -0.00010093683f }, { 7.6988167e-05f, 1.8551597e-05f, -5.7692813e-05f, -3.332362e-05f }, { -0.00062766208f, 2.713742e-05f, 0.00026511682f, 2.3841873e-05f }, { -0.00043656844f, 0.0028645469f, 0.0049817085f, 0.0080221478f }, { -3.3210444e-05f, -8.0852386e-05f, -2.2111492e-06f, -8.4430827e-05f }, { 0.010967284f, 0.018811225f, 0.017569463f, -0.0046944996f }, { -0.00018391248f, -0.00010462174f, -0.00017726f, -0.00018490133f }, { 0.00012591989f, 0.015965386f, 0.015964059f, -0.0078018431f }, { -0.006125333f, -8.2224165e-05f, -0.00020500151f, -0.00025207244f }, { -0.00016320041f, -0.0001279242f, 0.00014038799f, 8.1359421e-05f }, { -0.00064341098f, -0.0011265496f, -0.0011634792f, -0.00081607159f }, { 0.00089294825f, 0.0061923653f, 0.0052662392f, -0.00058227469f }, { -2.4001308e-05f, -1.3534224e-05f, -1.4720478e-05f, -2.5120827e-05f }, { 0.00029964918f, -0.0045658543f, -0.0045581938f, 0.0017106208f }, { 7.5790173e-05f, -1.8265415e-05f, 1.5918205e-05f, 5.8524021e-05f }, { 0.0011669872f, -0.00017571882f, -0.00017190275f, -0.0023833977f }, { 0.0033487264f, -0.0066535821f, -0.0066413786f, -0.0032332601f }, { -3.6468807e-05f, -0.00068145131f, -9.8190714e-05f, -8.7169435e-05f } }, { { -0.0010440653f, -8.9750644e-05f, 4.971182e-05f, 0.0044618878f }, { 0.0078333883f, -0.00090884312f, -0.00046920549f, -0.002465051f }, { -0.0058778609f, 0.0026554895f, -0.00031880506f, -0.00010649091f }, { -0.0015095448f, 0.0094026506f, 0.009492703f, 0.0024572848f }, { 0.0047331786f, 0.00070722401f, 0.0028798817f, -0.00039779892f }, { -0.0089878107f, -0.0095474878f, -0.0097187652f, 0.008765907f }, { -4.0435321e-05f, -0.00061813281f, -0.0060490143f, 0.0016259965f }, { -0.00014720558f, -1.0601876e-05f, 0.00014757138f, 0.00016227641f }, { -0.010428289f, -0.00031812813f, -0.0016172213f, -0.00012022134f }, { 0.0040517131f, 0.0072972763f, 0.0060433905f, 0.0025041645f }, { 0.00014090924f, 0.00027612853f, 0.00015961665f, 0.0002605418f }, { -0.00020653783f, -0.00048482867f, -0.00058472338f, 0.00026413759f }, { 0.00056712638f, 0.00026385353f, 0.00035484947f, 0.00033212447f }, { -0.00094663094f, 0.0029891757f, 0.0029887838f, -0.0026583585f }, { -0.0017400246f, 0.00042350567f, 0.00086128207f, 0.00039863587f }, { 0.00059604848f, 0.00027495434f, -0.00059956434f, -4.4981673e-05f }, { -0.010211343f, -0.0080580409f, -0.0085333216f, 0.0023258717f }, { 0.00042832593f, 0.0056750222f, 0.0048059635f, -0.0092168281f }, { 3.0214612e-05f, 4.540924e-06f, 1.7239937e-05f, 2.783598e-05f }, { 0.00029393335f, -4.5128636e-05f, -4.3089017e-05f, 0.00030682556f }, { -4.7077735e-05f, -1.3596835e-05f, -0.0015338149f, -7.4957991e-05f }, { -0.00097136844f, 0.00018564298f, 0.00021815754f, 0.0015095577f }, { 0.00043929849f, -0.0014691094f, -0.0014671742f, -0.00029365954f }, { 8.8554045e-05f, 0.0062500772f, 0.0001495049f, 0.00021007601f } }, { { 0.0020307077f, 0.0020947445f, 0.0017438295f, 0.0084822342f }, { -0.0069727503f, -0.0010131005f, 0.0055261321f, -0.0020442588f }, { 0.00031035611f, 0.00010839441f, 3.7359209e-06f, 4.3112837e-05f }, { 9.1207794e-05f, 0.0050148169f, 0.0051071455f, 0.0033679057f }, { -0.00090101737f, -0.00053793176f, -0.0025829621f, 0.0003241927f }, { -0.0019244714f, -0.0033690472f, -0.0035193497f, 0.0027653636f }, { -0.00065476293f, -0.00017787403f, 0.00040383136f, -0.00018123957f }, { -0.00030640434f, -0.00018961553f, -0.00011036218f, -0.00015793049f }, { 0.001110592f, -0.00021252645f, 0.00015849587f, -3.7758317e-05f }, { 0.00077967828f, -0.0051765235f, -0.0078505592f, -0.010796339f }, { -1.2024951e-05f, 6.48806e-05f, -3.9409005e-05f, 7.4639306e-05f }, { -0.00017352424f, -0.00037802595f, -0.00045639468f, 0.00016843169f }, { -4.2866244e-05f, -4.3730932e-06f, 7.3574276e-05f, 5.6076779e-05f }, { 0.00024802387f, 0.0018053101f, 0.0018042994f, -0.0016700716f }, { 0.0082698262f, -0.00014605077f, 0.0004377682f, 8.1585074e-05f }, { -4.494343e-06f, 0.00019781519f, -0.00058910268f, -0.00027360572f }, { 0.0013016934f, 0.0021020456f, 0.0022718598f, -0.0059377824f }, { 0.002185371f, -0.0080788056f, -0.0071952836f, 0.0039688918f }, { 0.00013048617f, 0.0001738124f, 0.00012978924f, 0.00013813358f }, { 0.00032386518f, 0.00023046021f, 0.00023064714f, 0.00033762343f }, { 0.00023643771f, 0.00019652953f, 0.0013083597f, 0.00024739959f }, { -0.0063957036f, -0.0055319023f, -0.0054742301f, -0.0037204932f }, { -0.0005510683f, -0.0007715413f, -0.00077385934f, -0.001009415f }, { 0.00017904616f, -0.00096137522f, 0.00030252599f, -2.2478138e-05f } } }, { { { -0.00038948583f, -0.00040817153f, -0.00041280315f, -0.0010985631f }, { 0.0025695337f, 0.00042904308f, 0.0054649973f, -0.0055079106f }, { 0.00052050672f, 2.2618679e-05f, 0.00024058975f, -0.00012632201f }, { -0.013468886f, 0.0079396715f, 0.0079402246f, 0.026283756f }, { -7.922122e-05f, -3.4761763e-06f, -0.0041716347f, 0.0001478739f }, { 0.023716381f, -0.016415262f, -0.015296927f, -0.021050827f }, { 3.7654391e-05f, 0.00012765816f, -0.0001337099f, 0.00051483398f }, { 0.00015671907f, 0.00010686796f, 2.1421097e-05f, -2.2281569e-05f }, { 3.1779413e-06f, 0.00010449913f, -0.00018303614f, 7.5382489e-05f }, { -0.00020526765f, -0.0011333575f, -0.0050720108f, 0.0051482782f }, { 4.0450357e-05f, 1.0808158e-05f, -2.3316095e-05f, 9.7767333e-06f }, { -0.019107229f, 0.010907324f, 0.0048969594f, 0.017851514f }, { 7.4048796e-05f, -7.041835e-06f, 8.0226174e-05f, 5.1714105e-05f }, { -0.016564627f, 0.0023486944f, 0.0023601429f, 0.016005248f }, { -0.004528284f, 3.6291049e-05f, 2.4229636e-05f, 0.0024853948f }, { 5.6882054e-05f, 6.8805135e-05f, 0.00013119897f, 0.00010339801f }, { 0.00021183341f, 0.0008203137f, -7.204401e-05f, 0.00062599728f }, { -0.00099314707f, 0.0030198762f, -0.0038989955f, 0.00055571214f }, { -7.4247984e-05f, -8.3993373e-05f, -5.9133252e-05f, -7.7411989e-05f }, { 0.0054296732f, -0.00057858871f, -0.00058417754f, -0.005072911f }, { -0.00019259782f, -0.00018772532f, -4.2959783e-05f, -0.0001827295f }, { -0.00029351865f, 0.00013736372f, 0.00016666048f, 0.00020873447f }, { 0.0069341659f, 0.0027612928f, 0.0027538377f, -0.0061770317f }, { 4.2584714e-05f, -0.00037063589f, -9.0693123e-06f, 0.00011845784f } }, { { 0.0028834168f, 0.0031807308f, 0.0031352582f, 0.01064051f }, { 0.0049297987f, -4.2149356e-05f, -0.0014926841f, -0.0002300371f }, { 0.0020396303f, -0.00066042794f, -6.4359283e-05f, 0.00017835163f }, { -0.0025767816f, 0.0025148152f, 0.0025224779f, 0.0043006543f }, { -0.00042084416f, -0.00013534305f, 0.002453623f, -4.0707749e-05f }, { -0.0001803055f, -0.0010450606f, -0.00084380806f, 0.00014843677f }, { -0.0064067107f, 0.00011012652f, -0.0022552747f, -0.00080508294f }, { -0.00017778763f, -4.296789e-05f, 0.00015343883f, 0.00025036711f }, { 0.002825978f, -0.00031945362f, -0.00031987612f, -0.00021117763f }, { 0.00032791249f, -0.00049524542f, 0.0049368722f, -0.0017186408f }, { -0.0001685943f, -0.00016766033f, -0.0001755097f, -0.00017067307f }, { 0.00023939157f, -0.00011793706f, -6.0620575e-05f, -0.0002706595f }, { -2.9718673e-05f, 3.5950879e-05f, 1.839844e-05f, -2.8718148e-05f }, { -0.0017260981f, 0.00012145435f, 0.0001236679f, 0.0018292155f }, { 0.0036086706f, 0.0001026898f, -2.5518889e-05f, -0.00019830236f }, { -0.00031546808f, -0.00042107458f, -0.00059963868f, -0.00061472497f }, { -0.0074719522f, 0.0015719596f, -0.0033624165f, -0.0092664101f }, { -0.0011285776f, 0.0018601435f, 0.00052060704f, -1.5554679e-05f }, { 4.9853171e-05f, 7.3650922e-05f, 3.4080107e-05f, 5.4255445e-05f }, { 0.00015102779f, -2.58105e-05f, -2.5851018e-05f, -4.5185316e-05f }, { 0.0002057452f, 0.00019037765f, 0.0040052198f, 0.00020046579f }, { 0.0027727314f, 0.0040749211f, 0.0036050794f, 0.0034635222f }, { 0.00042503689f, 0.00056027382f, 0.00056052971f, -8.2485044e-05f }, { -5.6309634e-05f, 0.0019722025f, 6.4267434e-05f, -0.00020376412f } }, { { 0.0051607661f, 0.0047835358f, 0.0047658352f, 0.0054281814f }, { -0.0040939561f, 0.0012119183f, -0.0023408179f, -0.00055891234f }, { -0.0031939804f, -0.0015954053f, -0.00018570689f, 0.00028849431f }, { -0.0075625096f, 0.0033878734f, 0.0033797415f, 0.010242674f }, { -0.002293562f, 0.00024245282f, 0.0019455622f, 0.0039550747f }, { 0.0090386754f, -0.0086947671f, -0.0082684939f, -0.0075613346f }, { -0.00085735117f, 3.4822634e-05f, -0.0024653972f, -0.00090964985f }, { -0.00013750587f, -0.00010089501f, 6.3555498e-05f, 0.0002758494f }, { 0.0060496328f, -0.00032664426f, 0.0005979723f, -0.00018819024f }, { 0.00072724184f, 0.00082242885f, 0.0045668772f, -0.0054557456f }, { -9.6167811e-05f, 7.9856612e-05f, 0.00015672473f, 8.0901183e-05f }, { 0.00038859448f, -0.00025360755f, -0.00017624981f, -0.00049125519f }, { -8.8277361e-05f, 2.4159527e-05f, -0.00016014627f, -2.7854246e-05f }, { -0.0037308647f, 0.00041434141f, 0.0004167221f, 0.0037190244f }, { 0.00050696744f, -4.6752715e-05f, 0.00033183668f, -0.0025882828f }, { -0.00015915702f, -0.0002325901f, -0.00036157415f, -0.00016391937f }, { 0.00012320153f, 0.0026711886f, 0.0018414591f, -0.0058215223f }, { -0.0029409983f, -0.00015460743f, 0.0031951665f, 0.0074654329f }, { 9.9084813e-05f, 9.1785865e-05f, 5.9300007e-05f, 0.00010463304f }, { 0.00024773341f, -2.5723276e-05f, -2.5709769e-05f, -0.00015357475f }, { 0.000416633f, 0.00028749584f, -0.0038632071f, 0.00039869488f }, { 0.00018344152f, 3.0811778e-05f, -0.00010240082f, 0.00059301197f }, { 0.0019217461f, 0.00034404024f, 0.00034318823f, -0.0015867375f }, { -0.00011928879f, 0.001178769f, -5.8655983e-05f, -0.00028461439f } } }, { { { 0.99999992f, 0.99999992f, 0.99999991f, 0.99999925f }, { 0.99998864f, 0.99999972f, 0.99993965f, 0.99997027f }, { 0.99999969f, 1.0f, 0.99999997f, 0.99999998f }, { 0.99990852f, 0.99971841f, 0.99970961f, 0.9996348f }, { 0.99999999f, 1.0f, 0.99997626f, 0.99999999f }, { 0.99951219f, 0.9997196f, 0.99973058f, 0.99951587f }, { 0.99999997f, 0.99999999f, 0.99999988f, 0.99999986f }, { 0.99999998f, 0.99999999f, 1.0f, 1.0f }, { 0.9999998f, 0.99999999f, 0.99999995f, 1.0f }, { 0.99999988f, 0.99999525f, 0.99997473f, 0.99995457f }, { 1.0f, 1.0f, 1.0f, 1.0f }, { 0.99975729f, 0.99976356f, 0.99983365f, 0.99982963f }, { 0.99999998f, 0.99999999f, 0.99999998f, 0.99999998f }, { 0.99986279f, 0.99986979f, 0.99986978f, 0.99984147f }, { 0.99997099f, 1.0f, 0.99999998f, 0.99999688f }, { 0.99999999f, 0.99999999f, 0.99999998f, 0.99999999f }, { 0.99999977f, 0.99999903f, 0.99999932f, 0.99999947f }, { 0.99999911f, 0.99997627f, 0.99997853f, 0.99999968f }, { 1.0f, 1.0f, 1.0f, 1.0f }, { 0.99998521f, 0.99998941f, 0.99998944f, 0.99998567f }, { 0.99999998f, 0.99999998f, 1.0f, 0.99999998f }, { 0.99999928f, 0.99999998f, 0.99999997f, 0.99999714f }, { 0.99997035f, 0.99997405f, 0.99997415f, 0.99997569f }, { 1.0f, 0.9999997f, 1.0f, 0.99999999f } }, { { 0.00015966941f, 0.00014262676f, 0.00020165066f, 0.00021618914f }, { 2.8140907e-06f, -0.00020325872f, 0.00017736728f, 6.0386679e-05f }, { -0.0003187876f, 5.8862288e-05f, 6.2281085e-05f, 1.7339908e-05f }, { -2.6587911e-05f, -0.00011609007f, -0.00011725093f, -7.6114852e-05f }, { 0.00013665042f, 5.2703844e-06f, -0.00031293536f, 3.8693931e-05f }, { -9.8143069e-05f, -0.00012816332f, -0.00012926252f, -0.00010623032f }, { 0.00032342312f, -1.9200091e-06f, -0.00010691485f, 6.3541059e-05f }, { -8.0643542e-06f, 9.7622933e-06f, 2.9924822e-05f, -1.988333e-05f }, { 0.00025318464f, 1.2588649e-05f, 1.4665927e-05f, 9.3294806e-06f }, { 2.6875391e-06f, -2.4928123e-05f, 2.251878e-05f, 0.00011026808f }, { 1.767638e-05f, 1.0309044e-05f, 2.4765648e-05f, 1.4397941e-05f }, { 6.9000935e-06f, 1.0637078e-05f, 1.087637e-05f, 6.3065784e-06f }, { 5.532953e-05f, 1.6231463e-05f, 4.9564371e-05f, 3.6623041e-05f }, { -1.6958729e-05f, -3.1627491e-05f, -3.1524511e-05f, -2.9954116e-05f }, { 8.9045086e-05f, 2.1005026e-05f, 1.3016463e-05f, 8.7863053e-05f }, { -2.75035e-05f, -3.0440427e-05f, -3.5356286e-05f, 5.9609261e-06f }, { 0.0001586274f, 4.0711165e-05f, 3.1563135e-05f, 0.0001385483f }, { 8.5548316e-06f, 7.4531928e-05f, -3.7017413e-05f, 2.6874037e-05f }, { -1.3750655e-05f, -8.2756032e-06f, -2.7214983e-07f, -1.4830115e-05f }, { -7.0798362e-07f, -3.3187173e-07f, -3.3266762e-07f, -5.7113855e-07f }, { 4.3615512e-05f, -4.4076433e-06f, 8.9239586e-06f, 3.7278531e-05f }, { -7.7366773e-06f, 4.610399e-06f, 4.3762687e-06f, -5.64067e-06f }, { -3.2666125e-06f, -1.0773146e-05f, -1.0861965e-05f, -1.3327232e-06f }, { -9.1178305e-06f, 0.00030171207f, -1.5395234e-05f, -2.0695425e-07f } }, { { 0.00017159464f, 0.00014699558f, 0.00018752678f, 0.0002227926f }, { -4.6524822e-05f, -0.00010460271f, 0.00034735325f, 0.00010082238f }, { -6.8269006e-05f, 1.4343751e-05f, 7.7283393e-06f, 2.5347136e-05f }, { -6.6149546e-05f, -7.1168993e-05f, -7.0621016e-05f, -0.00015246746f }, { 7.12022e-05f, 3.8790461e-05f, -0.00023994449f, 6.6792921e-05f }, { -0.00014735813f, -0.00012658353f, -0.00012162488f, -0.00012106777f }, { 0.00015161388f, -1.4439153e-05f, -3.7629923e-06f, 8.3140788e-06f }, { 4.0175416e-05f, 2.5380268e-05f, -2.2894421e-06f, 4.6374378e-06f }, { 0.00028906023f, 1.7695243e-05f, 5.3790587e-06f, 1.631859e-05f }, { 1.8890685e-05f, -1.6898275e-05f, 2.1007663e-05f, 6.5179363e-05f }, { -3.9142595e-06f, 2.5745488e-05f, 1.0803197e-05f, 2.7099749e-05f }, { 9.4245546e-06f, 1.0010075e-05f, 9.058324e-06f, 9.8703427e-06f }, { -2.3441863e-06f, 2.5490323e-05f, -1.0097654e-05f, 4.0554798e-05f }, { -4.1443921e-05f, -1.996316e-05f, -2.0000841e-05f, -4.7495655e-05f }, { 0.00012591695f, 5.6179903e-05f, -1.8415869e-05f, -3.8697972e-05f }, { 2.6719505e-05f, 2.4195362e-06f, 2.4287424e-05f, 3.4703059e-05f }, { 7.3804931e-05f, 4.9784871e-05f, 3.1159931e-06f, 0.00015857197f }, { -0.00010634331f, -1.6427658e-05f, -7.4874306e-05f, -6.2620255e-05f }, { -4.2561214e-06f, -1.6123179e-05f, -1.5507273e-05f, -1.2909924e-05f }, { -1.2210463e-06f, 1.1546399e-06f, 1.1413892e-06f, -1.3465856e-06f }, { 3.4909884e-05f, -1.2677793e-05f, 0.00011543701f, 2.413091e-05f }, { -2.1953323e-05f, -4.6244252e-06f, -3.5624435e-06f, 4.2293671e-06f }, { -1.1392936e-05f, -4.3970369e-06f, -4.4264864e-06f, -1.208518e-05f }, { -4.4002617e-05f, 0.00020912348f, -3.9617824e-05f, -4.1725112e-05f } } }, { { { -0.32504349f, -0.32502096f, -0.32501094f, -0.32423576f }, { -0.65602876f, -0.65622598f, -0.65567173f, -0.65525128f }, { -1.4666488f, -1.4666488f, -1.4666488f, -1.4666488f }, { 0.87168363f, 0.87181364f, 0.87181792f, 0.8718169f }, { -1.264365f, -1.264365f, -1.264365f, -1.264365f }, { 0.89917968f, 0.89916889f, 0.89916525f, 0.89927374f }, { -1.2245906f, -1.2245906f, -1.2245906f, -1.2245906f }, { -0.8885678f, -0.88856217f, -0.88856327f, -0.88855044f }, { -0.31799095f, -0.31916566f, -0.31907669f, -0.31918911f }, { -0.08987958f, -0.090342401f, -0.090004674f, -0.090222398f }, { -0.59425693f, -0.59433999f, -0.59429118f, -0.59433553f }, { 1.1317575f, 1.1317475f, 1.1317412f, 1.1317494f }, { -1.2193493f, -1.2193493f, -1.2193493f, -1.2193493f }, { 1.2506981f, 1.250675f, 1.250675f, 1.2506569f }, { -1.08782f, -1.0877793f, -1.0878022f, -1.0878025f }, { -0.13925598f, -0.13932948f, -0.13919658f, -0.13913403f }, { -0.40394684f, -0.4042314f, -0.40436178f, -0.40402218f }, { -0.47762966f, -0.47745572f, -0.47767784f, -0.47713093f }, { -0.60177181f, -0.60176862f, -0.60177347f, -0.60177079f }, { 2.7311956f, 2.7311911f, 2.7311911f, 2.731191f }, { -1.3109856f, -1.3109856f, -1.3109856f, -1.3109856f }, { 0.60942644f, 0.60941369f, 0.6094123f, 0.60944198f }, { 0.55675448f, 0.55672275f, 0.55672303f, 0.5567542f }, { -0.40637059f, -0.4057945f, -0.40635768f, -0.40636681f } }, { { -0.0016154222f, -0.0015930079f, -0.0015828998f, -0.00087447165f }, { -0.0011262472f, -0.001324462f, -0.00094895016f, -0.00062188189f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 9.7616744e-05f, 0.00010718899f, 0.00010718606f, 0.00012665246f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.00013476236f, 6.982272e-05f, 6.8208505e-05f, 0.00014604742f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { -0.0031089951f, -0.0031071196f, -0.0031207245f, -0.0031097054f }, { -0.0027808116f, -0.0035049857f, -0.0034100135f, -0.0035192661f }, { -0.0018291474f, -0.0019603285f, -0.0018919656f, -0.0019656229f }, { -0.0034301741f, -0.0034912573f, -0.0034474395f, -0.0034893985f }, { -6.156701e-06f, -9.8568527e-06f, -1.2383692e-05f, -9.9984205e-06f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.00011838153f, 0.00011008679f, 0.00011008878f, 0.00010536608f }, { -0.0006246638f, -0.00058479459f, -0.00061327452f, -0.00061085433f }, { -0.0059197749f, -0.0059778169f, -0.0059586015f, -0.0058798299f }, { -0.0013246996f, -0.0016061786f, -0.0016081246f, -0.0014374546f }, { -0.001593227f, -0.0014706843f, -0.0015974008f, -0.001341579f }, { -0.0027930604f, -0.0027920013f, -0.0027939865f, -0.0027928528f }, { -1.8908723e-06f, -4.266382e-06f, -4.2210172e-06f, -5.0155215e-06f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.00018508026f, 0.00019774537f, 0.00019744661f, 0.00019538593f }, { 2.3243747e-05f, 1.7291398e-05f, 1.7309712e-05f, 2.9261396e-05f }, { -0.0041402471f, -0.0037085946f, -0.0041294876f, -0.0041316136f } }, { { -0.0018899732f, -0.0018719182f, -0.0018661076f, -0.0012234594f }, { -0.0012968123f, -0.0012971446f, -0.00093522854f, -0.00066475268f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 9.1054464e-05f, 0.00014124217f, 0.00014156806f, 0.00012014953f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.00017026995f, 0.00010528413f, 0.00010537941f, 0.00015698848f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { -0.0025812972f, -0.0025835894f, -0.0025789321f, -0.002554949f }, { -0.0035568863f, -0.0042988014f, -0.0042155548f, -0.004312546f }, { -0.0024184575f, -0.0025111277f, -0.0024654994f, -0.0023980076f }, { -0.0036993386f, -0.0037113013f, -0.0036987284f, -0.0037094875f }, { -5.074861e-06f, -1.1367399e-05f, -1.4819989e-05f, -9.2705899e-06f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.00012570403f, 0.00012150272f, 0.00012149179f, 0.00010579599f }, { -0.00062162762f, -0.00058131015f, -0.00060837583f, -0.00060795256f }, { -0.00775735f, -0.0077198081f, -0.0078365948f, -0.0077749317f }, { -0.0015325554f, -0.0017125784f, -0.001703195f, -0.0015662859f }, { -0.0018130784f, -0.00177106f, -0.001858095f, -0.0015845058f }, { -0.003668417f, -0.0036659688f, -0.0036693421f, -0.0036680526f }, { -9.5804016e-06f, -9.6276607e-06f, -9.630607e-06f, -1.2159056e-05f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.00017930618f, 0.00020084683f, 0.00020150104f, 0.00020810787f }, { 2.3869269e-05f, 1.1024793e-05f, 1.1041937e-05f, 1.6467357e-05f }, { -0.004690782f, -0.0044656761f, -0.0046782065f, -0.0046921455f } } }, { { { 0.23047932f, 0.23043226f, 0.23041471f, 0.22922185f }, { 0.14990977f, 0.15703656f, 0.15110771f, 0.15149153f }, { 0.30629171f, 0.30426701f, 0.30400037f, 0.30403889f }, { 0.03476576f, 0.036188528f, 0.036216719f, 0.037322097f }, { 0.31066251f, 0.31090363f, 0.31041565f, 0.31057779f }, { 0.04875259f, 0.046468595f, 0.046486323f, 0.046584523f }, { 0.31745458f, 0.31874472f, 0.32086369f, 0.31880207f }, { 0.64054942f, 0.64062862f, 0.64051973f, 0.64059059f }, { 0.27309038f, 0.27480819f, 0.27477284f, 0.27486762f }, { 0.196647f, 0.19687982f, 0.19607604f, 0.1957915f }, { 0.32867362f, 0.32858008f, 0.32856702f, 0.328555f }, { -0.0026873031f, -0.0042393446f, -0.0057894907f, -0.0041858859f }, { 0.40254624f, 0.4024247f, 0.4025598f, 0.40243731f }, { 0.019362807f, 0.018146218f, 0.018146051f, 0.019656613f }, { 0.29328089f, 0.29403937f, 0.29435036f, 0.29403094f }, { 0.57111506f, 0.57118505f, 0.57099608f, 0.57099266f }, { 0.16966612f, 0.16993739f, 0.17069399f, 0.16991136f }, { 0.14989055f, 0.1489484f, 0.14995985f, 0.15015916f }, { 0.33606014f, 0.33606294f, 0.33606393f, 0.33605429f }, { 0.015421206f, 0.015180692f, 0.01518037f, 0.015431139f }, { 0.33165237f, 0.33185282f, 0.33162592f, 0.33166981f }, { 0.078137018f, 0.078153855f, 0.078165152f, 0.078332343f }, { 0.002896946f, 0.0026038621f, 0.0026029604f, 0.0022081151f }, { 0.41064398f, 0.40987685f, 0.41065341f, 0.41059166f } }, { { -0.0024316111f, -0.0024732789f, -0.0024922144f, -0.0035874346f }, { 0.0013306961f, 0.004171802f, 0.0027660627f, 0.0023671465f }, { 0.0034411091f, 0.0020878413f, 0.0020874456f, 0.0022028237f }, { -0.0032873976f, -0.0021351911f, -0.0021071363f, -0.0028424534f }, { 0.0017995208f, 0.0022319618f, 0.0039270256f, 0.0021249365f }, { -0.0019590835f, -0.0012526895f, -0.0012347747f, -0.0021069943f }, { 0.0012319531f, 0.002255621f, 0.0030193583f, 0.0020970822f }, { 0.0015144077f, 0.0015110104f, 0.0014803089f, 0.0015340007f }, { -0.0036679996f, -0.0028160114f, -0.0028586497f, -0.0027953731f }, { -0.005445786f, -0.0052624873f, -0.0054843188f, -0.0053271749f }, { 0.00067154572f, 0.0007530775f, 0.00067974516f, 0.00074462315f }, { -0.0035626119f, -0.0034186877f, -0.0038720517f, -0.0040088745f }, { 0.003455851f, 0.0035040061f, 0.0034671486f, 0.0035069881f }, { -0.0047789747f, -0.0047994804f, -0.0047996451f, -0.0044008337f }, { 0.0032403482f, 0.0033627856f, 0.003429619f, 0.0031153117f }, { -0.005027022f, -0.0049812f, -0.0049604573f, -0.0050556194f }, { -0.0020728991f, -0.0014784158f, -0.001216894f, -0.0019213729f }, { -0.00013808007f, -0.00067270623f, -0.00024001574f, -0.00030691077f }, { 0.0004367104f, 0.00043390709f, 0.00043548166f, 0.00043425516f }, { -0.00082746467f, -0.00088151411f, -0.00088152334f, -0.0008043643f }, { 0.0030277712f, 0.003133577f, 0.0028529862f, 0.0030362271f }, { -0.0058721937f, -0.0059816331f, -0.0059799345f, -0.0058882832f }, { -0.0057032562f, -0.0057401855f, -0.0057416619f, -0.0062417688f }, { -0.0014357888f, -0.0020782049f, -0.0014346823f, -0.0014513767f } }, { { -0.0027051235f, -0.0027087245f, -0.0027052303f, -0.0033594951f }, { 0.0028036195f, 0.0030416572f, 0.0014306948f, 0.0017897371f }, { 0.0031113166f, 0.0026432303f, 0.0025937824f, 0.0025394463f }, { -0.0036032904f, -0.003447065f, -0.0034344406f, -0.0024163572f }, { 0.0023912799f, 0.0025281229f, 0.0038665087f, 0.0024214034f }, { -0.0023543827f, -0.0024294943f, -0.0024539784f, -0.0027742617f }, { 0.0020903896f, 0.0026617586f, 0.003395249f, 0.0026261065f }, { 0.0019031008f, 0.0019405475f, 0.0019426085f, 0.0019404325f }, { -0.0040413326f, -0.0030964835f, -0.0031020735f, -0.0030826754f }, { -0.0064568993f, -0.0062342438f, -0.0064704698f, -0.0065636744f }, { 0.0010788406f, 0.0010092051f, 0.0010264121f, 0.00099891228f }, { -0.0040759201f, -0.0059224283f, -0.0066809927f, -0.0049099348f }, { 0.0042962009f, 0.0041909175f, 0.0043195236f, 0.0041900138f }, { -0.0062728983f, -0.0070256154f, -0.007025641f, -0.0061758746f }, { 0.0036210401f, 0.0039723998f, 0.0042232048f, 0.0042757707f }, { -0.0058693852f, -0.0058583303f, -0.0058544016f, -0.005887725f }, { -0.0023099876f, -0.0021136245f, -0.0017298078f, -0.0022483337f }, { -0.00017851962f, -0.00014956209f, 8.5676316e-05f, -0.00024971669f }, { 0.0003734781f, 0.00037078986f, 0.00037364181f, 0.00037070594f }, { -0.00030648905f, -0.00038230535f, -0.00038223043f, -0.00028623253f }, { 0.0032871423f, 0.0034163052f, 0.0028276655f, 0.0032991918f }, { -0.0061331695f, -0.0063319797f, -0.0063340119f, -0.0064390374f }, { -0.0062172888f, -0.0059787106f, -0.0059793294f, -0.0060406701f }, { -0.0018276142f, -0.0022170788f, -0.0018293949f, -0.0018222824f } } } }, { { { { 0.13218089f, -0.11654637f, -0.11622196f, -0.044208736f }, { 0.0074579257f, 0.0038503609f, 0.0013201096f, 4.0415784e-05f }, { -0.025474487f, -0.01209255f, -0.016535858f, 0.012704547f }, { -0.0016894103f, -0.0081312144f, -0.0033264609f, 0.0011923269f }, { -0.068044876f, 0.018276873f, -0.074833897f, 0.01308348f }, { 0.02665691f, 0.013515118f, 0.026440814f, -0.0077037816f }, { 0.0023286096f, -0.0025782652f, 0.0021644694f, -0.0042955294f }, { 0.051356261f, -0.031058382f, -0.085382962f, -0.033103269f }, { -0.081609229f, 0.0035270199f, -0.015722417f, 0.048773789f }, { 0.0023928418f, -0.001243811f, 0.011910492f, -0.011621478f }, { -0.028953904f, -0.029335777f, -0.0057891432f, 0.013874136f }, { -0.012473582f, 0.001772629f, -0.013983442f, 0.014846792f }, { -0.016111661f, 0.0018902323f, 0.025910586f, 0.042848276f }, { 0.026200626f, 0.024007879f, 0.0017667146f, -0.016394032f }, { -0.0067006429f, -0.0017968936f, 0.009028659f, 0.0044060413f }, { 0.019280611f, 0.0449581f, -0.042852227f, -0.066012332f }, { -0.014451123f, -0.047772741f, -0.047475406f, 0.098434178f }, { -0.0028954635f, 0.010521833f, -0.015741597f, -0.00091666191f }, { 0.0020291956f, -0.057966746f, -0.04525094f, 0.032711614f }, { 0.020563445f, -0.0078684621f, -0.015282237f, -0.0019830466f }, { -0.019504171f, 0.071338511f, 0.0033729474f, -0.0095772339f }, { 0.013056103f, 0.018719519f, 0.0096002937f, -0.028774366f }, { -0.00038728577f, -0.0010662982f, -0.0014333502f, 0.00059135695f }, { 0.073844752f, -0.05666013f, -0.1007151f, -0.030440738f } }, { { 0.00017766639f, -9.2398532e-05f, -3.9442682e-05f, -3.9559848e-05f }, { -0.0043956477f, 0.00044042277f, -0.00047491077f, 9.4171117e-05f }, { -0.0042095545f, -0.00910753f, -0.0014295282f, 0.0042595844f }, { 0.00070989004f, -0.0009623012f, 0.00084162653f, -0.00015925965f }, { -0.0017587638f, 0.0033199811f, -0.00025544613f, 0.00083644978f }, { 0.0051797987f, 0.0015691893f, -0.002324397f, 0.0050776381f }, { 0.003911779f, 0.00072639703f, 2.102924e-05f, -0.0029529332f }, { 0.0050240476f, -0.00041452319f, 3.1730448e-06f, -0.0072697591f }, { -1.5023048e-05f, 0.00032491246f, -9.2151952e-05f, 0.0035851726f }, { 0.0030984373f, 0.0016428856f, 0.0032974124f, -0.0036034289f }, { -0.00044578206f, -0.0035916409f, 0.0028146658f, 0.0068013321f }, { 0.00025716711f, -0.0024772152f, 0.0029660992f, -0.0008783244f }, { -0.005543602f, -0.00046453249f, 0.006815884f, 0.0069207512f }, { -0.0033541738f, -0.0015140333f, -0.004071746f, -0.0020908789f }, { 0.0027932918f, -0.0012517158f, -0.0033509184f, -0.001271572f }, { 0.0043481525f, -0.00088858735f, -0.0081538059f, 0.00027985077f }, { 7.4017523e-05f, -7.0080388e-05f, -7.1766386e-05f, 0.00020468758f }, { 0.00044507396f, 0.010179106f, -0.0048087449f, 0.0013487105f }, { 0.00082148695f, -0.00042640153f, -0.0024255173f, 0.0044486011f }, { -0.00026383509f, -0.0031871528f, -0.008203704f, -0.00053957093f }, { -0.0002996462f, 0.00070789605f, 7.9300612e-05f, -0.00024002209f }, { 0.0013722116f, 0.0049176054f, 0.0029283062f, -0.000849108f }, { 0.00026545039f, 0.0011783443f, 0.00072103548f, -0.0007355776f }, { 0.002192273f, -0.00294318f, 1.5452606e-05f, -0.0020953993f } }, { { 2.4074136e-05f, -2.4931598e-05f, -1.0893587e-05f, 1.080951e-05f }, { -0.0061635883f, -0.0042963493f, -0.00177783f, -0.00080292808f }, { 0.0047868795f, -0.0050472436f, 0.0082439123f, -0.0090979713f }, { 0.0017221077f, 0.0067285193f, 0.0031011872f, -0.0019932567f }, { 0.0010926271f, -0.0012170693f, 0.00012875612f, 0.00016441623f }, { -0.0048786273f, -0.0041225634f, -0.005591426f, 0.0043469593f }, { -0.0070664098f, -0.0012625813f, -0.00022220241f, -0.0026120468f }, { -0.0026689917f, 0.00030860545f, 1.9297947e-05f, 0.001274799f }, { 0.0026769559f, 0.00016106032f, 0.00013829246f, -0.0017239107f }, { -0.0042495789f, 0.0010270326f, -0.00078224804f, -0.0019210019f }, { 0.0072385804f, 0.0086418476f, 0.0061428272f, -0.0027142827f }, { 0.0019768127f, -0.00057957046f, 0.0047464783f, -0.004599565f }, { 0.0093618867f, -0.0010476542f, -0.0038681572f, -0.0065219521f }, { -0.0076406673f, -0.0036729355f, -0.0068804827f, 0.0077571478f }, { 0.0012706397f, -0.00042567505f, -0.002521821f, 6.0288127e-05f }, { -0.002041411f, 0.000430125f, 0.0073620925f, 0.0021579456f }, { 0.00012145466f, 4.1276616e-05f, 4.2449608e-05f, 9.8351262e-05f }, { 0.0014376278f, -0.007439719f, 0.0039006971f, 0.00051135138f }, { -7.1665367e-05f, 0.00023856335f, 0.00015274881f, -0.0096946274f }, { -0.00076804256f, 0.0040182915f, 0.012603411f, -0.00059669891f }, { -0.00010641981f, -0.00052355992f, 0.00057481361f, 0.00016456343f }, { -0.0027623375f, -0.0036761364f, -0.010480297f, 0.0066006902f }, { 0.00049081404f, 0.00077264749f, 0.0021355718f, -0.00029188425f }, { 0.00028566818f, 0.00097678458f, 0.00089022281f, -0.00013760767f } } }, { { { -0.0098123577f, 0.11017117f, 0.11245143f, -0.01173447f }, { 0.0036188505f, -0.0025878518f, -0.00043343726f, -0.0038813197f }, { 0.013109746f, -0.016775181f, -0.0011093308f, 0.00083465721f }, { -0.0042515898f, -0.0028159364f, 0.00027829209f, -0.002907578f }, { -0.0081027554f, -0.0019330574f, 0.061872524f, -0.037539524f }, { -0.012923735f, 0.021011524f, 0.002680406f, 0.0034369108f }, { 0.0027819214f, 0.0028657905f, -0.0034177203f, -0.0037322329f }, { -0.0036178174f, 0.065792163f, 0.13263475f, 0.0055427994f }, { 0.027832309f, -0.083372016f, -0.058757582f, 0.016164879f }, { -0.0082343898f, 0.011782416f, 0.011496052f, -0.0027847616f }, { 0.0012516658f, -0.014686832f, -0.025073035f, -0.020700577f }, { 0.0055718234f, -0.011543219f, -0.012867689f, -0.0049474286f }, { 0.028869265f, -0.035431559f, 0.024976635f, -0.01063055f }, { -0.0010657662f, 0.014977146f, 0.027109f, 0.01612865f }, { -0.0021697493f, 0.0044220507f, 0.0055654161f, -0.0032373397f }, { -0.018500666f, -0.01979267f, -0.0068480612f, 0.03908391f }, { 0.063306878f, 0.01934691f, 0.019254616f, -0.099824471f }, { 7.0580666e-05f, -0.0015082457f, -0.0056893693f, 0.00022726294f }, { 0.0077067654f, -0.014018834f, -0.021406454f, -0.0076589993f }, { -0.0013072394f, 2.6765854e-05f, 0.0028400803f, 0.0037431063f }, { -0.025369581f, -0.064039908f, -0.020594137f, -0.086807367f }, { -0.033639351f, 0.010434758f, 0.00082983507f, 0.013145885f }, { 0.00029373395f, 7.8193614e-05f, 0.00048496415f, 0.00062972215f }, { -0.0041597628f, 0.024283117f, -0.030148407f, 0.011456515f } }, { { -1.3484857e-05f, -3.7204145e-05f, -1.5660577e-05f, -2.4497955e-05f }, { -0.0068070249f, 0.0041035892f, 0.0034647689f, 0.0035918321f }, { -0.0053613309f, 0.0080593503f, 0.0028507084f, -0.0023104987f }, { 0.0048581064f, 0.0039720065f, -0.0019058129f, 0.0047295789f }, { -0.00030675956f, -0.0007787587f, -0.00025201217f, 0.00020777843f }, { -0.00026433336f, -0.0093672701f, -0.0053201627f, -0.0059632173f }, { -0.0063062815f, 0.0011995204f, 0.0001870407f, 0.0028197877f }, { -0.00053247524f, -0.00066138217f, -1.4959372e-05f, -0.00036023628f }, { 0.00027591427f, 0.00011309835f, 2.2453632e-05f, -0.00075736359f }, { 0.0015654886f, 0.0018114616f, -0.0004503446f, -8.5866048e-05f }, { 0.003501393f, 0.0037179893f, 0.008328543f, 0.013411108f }, { -0.0035136609f, -0.0015054003f, 0.0011903964f, 0.0022551358f }, { -0.0083723767f, 0.0061303554f, -0.008056962f, 0.0035035183f }, { -0.0023715655f, -0.0070468331f, -0.010219655f, -0.0057856465f }, { -0.0011406634f, -0.00021204595f, -0.001693195f, 0.0011051597f }, { 0.0011643412f, 0.00037557194f, 0.0048567739f, -0.00063996433f }, { -3.1728174e-05f, -2.9073903e-06f, -3.0243209e-06f, 2.579239e-05f }, { 0.00053152589f, 0.0029635352f, 0.0040743289f, -0.00051381046f }, { -0.0017253584f, 0.00012081524f, 0.00012243664f, -0.00063598215f }, { 0.0026711847f, -0.0020733972f, -0.0027860744f, 0.0017065643f }, { 5.7762902e-05f, 0.00092043577f, -0.0035278882f, 0.0007846087f }, { 0.0056127705f, -0.0051893669f, -0.0027072408f, -0.0025630045f }, { -0.00059289151f, -0.0004168408f, -8.8118696e-05f, -0.00073538101f }, { 0.0003388606f, -0.00094234652f, 3.013109e-05f, -0.0010532484f } }, { { -2.9013996e-05f, 6.1983083e-05f, 2.8401438e-05f, -3.4901557e-05f }, { 0.0045230474f, -0.0021369843f, -0.00422706f, -0.0018918027f }, { 0.00017586142f, 0.005389053f, 0.0071352982f, -0.0018278685f }, { -0.0012135723f, -0.0035970727f, 0.00078957165f, -0.0017065397f }, { -0.00067051937f, -1.9501585e-05f, 4.1968766e-05f, -0.0010958091f }, { -0.0015277626f, -0.0039952533f, -0.00049631478f, 0.0018042745f }, { 0.0039376754f, -0.00097834328f, 6.5894634e-06f, -0.0044189106f }, { -0.00067623039f, 0.0004690807f, 1.4532105e-07f, 0.0032984829f }, { 0.0020787449f, -0.0016586579f, -0.00062367064f, 0.0021545362f }, { 0.0016427801f, 2.6710288e-05f, 0.0016011535f, -0.00077649869f }, { 0.0039999622f, -0.0014968097f, -0.0025647576f, 0.0022783424f }, { 0.001558454f, -0.00083803058f, 0.0018955692f, 0.0010432376f }, { 0.010555722f, -0.010395022f, 0.0050354965f, -0.0016177699f }, { 0.00011370745f, -0.009328355f, -0.0063009522f, 0.0024377458f }, { -0.00024433189f, 0.00052920244f, -0.0013213352f, -0.0013503982f }, { -0.0057620093f, 0.00095391746f, -0.0034768563f, 0.00093990705f }, { 0.00012108024f, 4.1007202e-05f, 4.2193381e-05f, -0.00011043617f }, { 0.0038593696f, -0.00074282979f, -0.0093457897f, 0.00027311164f }, { 0.0021514797f, -7.8742315e-05f, -0.0018813077f, -0.0017625098f }, { 0.0038491118f, 0.00022570776f, -0.0061331041f, 0.00014956617f }, { -0.00014676603f, -0.00025053931f, 0.003376287f, -0.00014730695f }, { 0.0016439646f, 0.0060569792f, 0.00063058918f, -0.0034810156f }, { 0.00011722835f, 0.00032237223f, -0.0012556553f, -0.0006887808f }, { 0.00060814722f, 0.0003708376f, -0.00056515636f, -0.00016801817f } } }, { { { 0.99117704f, 0.98705585f, 0.98683693f, 0.9989534f }, { 0.99996564f, 0.99998924f, 0.99999903f, 0.99999247f }, { 0.99958951f, 0.99978616f, 0.99986266f, 0.99991895f }, { 0.99998953f, 0.99996298f, 0.99999443f, 0.99999506f }, { 0.99764936f, 0.9998311f, 0.99527468f, 0.99920949f }, { 0.9995611f, 0.99968788f, 0.99964679f, 0.99996442f }, { 0.99999342f, 0.99999257f, 0.99999182f, 0.99998381f }, { 0.99867384f, 0.99734987f, 0.98748052f, 0.99943657f }, { 0.99627571f, 0.99651225f, 0.99814846f, 0.99867903f }, { 0.99996323f, 0.99992981f, 0.99986298f, 0.99992859f }, { 0.99957996f, 0.99946171f, 0.99966886f, 0.99968945f }, { 0.99990668f, 0.9999318f, 0.99981943f, 0.99987754f }, { 0.99945334f, 0.99937032f, 0.99935219f, 0.99902503f }, { 0.99965614f, 0.99959957f, 0.99963092f, 0.99973552f }, { 0.9999752f, 0.99998861f, 0.99994375f, 0.99998505f }, { 0.99964293f, 0.99879278f, 0.99905795f, 0.99705307f }, { 0.99788947f, 0.99867085f, 0.99868681f, 0.99012413f }, { 0.99999581f, 0.99994351f, 0.99985991f, 0.99999955f }, { 0.99996824f, 0.99822008f, 0.99874627f, 0.99943549f }, { 0.9997877f, 0.99996904f, 0.99987919f, 0.99999103f }, { 0.99948785f, 0.99539425f, 0.99978223f, 0.99617908f }, { 0.99934875f, 0.99977032f, 0.99995357f, 0.99949949f }, { 0.99999988f, 0.99999943f, 0.99999886f, 0.99999963f }, { 0.99726107f, 0.99809817f, 0.99445842f, 0.99947091f } }, { { -2.3481737e-05f, -6.7307406e-06f, -2.8605869e-06f, -2.0372001e-06f }, { 6.6885689e-05f, 4.5630281e-06f, 3.5788218e-05f, 1.0842484e-05f }, { -4.9278613e-05f, -2.4660601e-05f, 3.1625301e-06f, 0.00019708279f }, { 1.2439158e-05f, 3.0347865e-05f, 8.6153947e-06f, 1.0887256e-05f }, { -0.00012454598f, -6.513709e-05f, -3.5853483e-06f, -3.4708286e-06f }, { -0.00013746339f, 0.00013516333f, 8.4535039e-05f, 5.693766e-05f }, { -2.3674091e-05f, -3.4690053e-06f, 5.3812265e-07f, -1.7613197e-05f }, { -0.00025790043f, 3.0475251e-05f, 2.1174795e-06f, -0.00023630753f }, { -8.8624748e-06f, 7.9175589e-06f, -2.4258477e-07f, -0.00017288313f }, { 4.0061469e-05f, 0.00069846663f, -0.00060299476f, -0.00015396968f }, { 5.0667108e-06f, 2.306363e-05f, 0.00028636884f, 3.6246633e-05f }, { 0.00032740524f, -0.00037985037f, -0.00014841039f, -0.00012676016f }, { 8.7000758e-05f, 0.00018530207f, 1.7669124e-05f, -0.00023199594f }, { 9.2332094e-05f, 0.00013487652f, 0.00034587506f, -3.8853378e-05f }, { 6.9809868e-05f, -0.00015411544f, 0.0013505166f, 1.4531796e-06f }, { -6.3782301e-05f, 4.8545135e-05f, -0.00027083794f, 4.5129465e-05f }, { 3.0912438e-06f, -3.2982361e-06f, -3.3551612e-06f, -1.7781589e-05f }, { 9.872609e-06f, -2.9944213e-05f, -4.5592652e-05f, 1.5950681e-05f }, { 1.4767773e-05f, -2.2486726e-05f, -0.00010613341f, -0.00015794394f }, { 2.4386215e-05f, -1.1610334e-05f, -4.4456294e-05f, -5.0215596e-06f }, { -4.2741558e-06f, 8.7714242e-06f, -6.6343322e-05f, 6.7010735e-05f }, { 0.00016489767f, -3.3636771e-05f, 5.1610504e-05f, 5.2803593e-06f }, { 1.1649256e-05f, 2.1169993e-05f, 1.9755999e-05f, 1.3389438e-05f }, { -0.00015815197f, -0.00014316145f, 2.6536218e-06f, -4.6846396e-05f } }, { { -3.5109783e-06f, -9.8530632e-06f, -4.5020804e-06f, 6.9233235e-08f }, { 9.9938991e-06f, -2.0914089e-06f, 3.5717699e-05f, 3.2813664e-06f }, { 0.00012938219f, 1.111062e-05f, 8.0858608e-05f, 0.00018147439f }, { 4.8657525e-06f, 8.6580257e-06f, 3.6742927e-06f, 3.5828406e-06f }, { 6.9905696e-05f, 2.0985073e-05f, 6.8866215e-06f, -4.2552499e-05f }, { 0.00012100208f, 9.7821801e-05f, 0.00013576456f, 6.3686234e-05f }, { 1.954525e-06f, -1.0727343e-06f, 5.2332444e-07f, -5.4034988e-06f }, { 0.00013699813f, -2.226833e-05f, 1.4994043e-06f, 1.7110377e-05f }, { 0.0001678261f, -0.00013844113f, -3.4281745e-05f, 5.3854072e-05f }, { -1.3018868e-05f, 0.00022176303f, 0.00016983401f, 0.00038109805f }, { 0.00019016068f, 0.00023448876f, 2.643329e-05f, 4.6842203e-05f }, { -1.2492528e-05f, -0.00059486605f, 0.00012427061f, 8.1876965e-05f }, { 8.400564e-05f, -0.00029859163f, -4.884214e-05f, 0.0002631806f }, { 0.00019907281f, 0.00014046808f, 0.00015482448f, 4.0461099e-05f }, { -0.00024349239f, 0.00081298441f, 0.00084294728f, 7.9617963e-05f }, { -6.0040835e-05f, 3.2352918e-07f, 0.00024295599f, 0.00011067283f }, { -6.0027092e-06f, 1.1975092e-06f, 1.2248893e-06f, -2.1293392e-05f }, { 1.4478736e-05f, 6.8326918e-05f, -7.8693614e-06f, 9.2888155e-06f }, { -1.6982828e-05f, 1.2094341e-05f, -3.1693808e-05f, 0.00028574477f }, { 3.4480942e-05f, 2.6556008e-05f, 0.00016193956f, -1.8966503e-06f }, { -5.7726961e-06f, 2.1091148e-05f, 5.8963955e-05f, -1.0834372e-05f }, { 0.0001214393f, 1.4174882e-05f, 0.0001371836f, 0.00021757165f }, { 1.0140226e-05f, 6.1641031e-06f, 1.0590727e-05f, 1.0893212e-05f }, { -1.7442656e-05f, 4.2353331e-05f, 7.4324714e-05f, -1.9484775e-06f } } }, { { { 3.7217719f, 3.6900797f, 3.6899881f, 3.6670816f }, { 0.067826319f, 0.16468028f, 0.083129199f, 0.1336756f }, { 0.66338737f, 0.23883566f, 0.093361469f, 0.10095622f }, { 0.27185537f, 0.20781392f, 0.32216624f, 0.29876595f }, { 2.0776462f, 2.0006156f, 2.0243138f, 2.080345f }, { 0.57695783f, 0.18015147f, -0.11440889f, 0.14229144f }, { 0.63833683f, 0.41431062f, 0.44752994f, 0.47594414f }, { 1.7890608f, 1.962584f, 1.9322155f, 1.6588331f }, { 3.0538128f, 3.108267f, 3.1001573f, 2.9593433f }, { -0.28383051f, -0.27708376f, -0.042513902f, -0.085181891f }, { 0.3873435f, 0.41697884f, 0.39625427f, 0.33250735f }, { -0.33498881f, -0.40206929f, -0.028905862f, -0.48179632f }, { 1.1875033f, 1.3535177f, 1.2526197f, 1.3337495f }, { 0.42579488f, 0.24951727f, 0.18976118f, 0.20605317f }, { -0.53212666f, -0.3861028f, -0.75685995f, -0.23411882f }, { 1.6910165f, 1.686815f, 1.5906473f, 1.6528217f }, { 4.0570657f, 4.0349492f, 4.0350332f, 4.0498099f }, { -0.017225465f, -0.032503897f, 0.46003211f, 0.21602109f }, { 1.1196901f, 1.00885f, 0.91675568f, 0.99635794f }, { -0.093891275f, 0.0809352f, -0.13783332f, 0.27130678f }, { 1.9925136f, 1.9829394f, 1.8820721f, 1.9542026f }, { 0.84563763f, 0.48476746f, 0.37907152f, 0.70267878f }, { 0.37054708f, 0.4228574f, 0.6329822f, 0.26197064f }, { 1.9618393f, 1.8405969f, 1.9440918f, 1.901629f } }, { { -5.6047186e-06f, 6.0454847e-06f, 2.8365975e-06f, 6.0894367e-06f }, { -0.00069876506f, -0.00029642785f, -0.00059516082f, -0.00025400441f }, { -0.00020850504f, -0.00012959593f, -0.00032902532f, -0.00058117893f }, { -0.00037901964f, -0.00038062016f, -0.00023777964f, -0.00033714679f }, { -5.9894351e-05f, -9.820791e-05f, -5.9867157e-06f, -6.258549e-06f }, { -0.00035424038f, -8.7146215e-05f, 3.0398362e-05f, -0.00061406521f }, { 0.00014971442f, 4.5936211e-05f, -5.6259869e-06f, 0.00013567035f }, { -0.00016180211f, 3.1840487e-06f, 3.8979157e-07f, -0.00017131994f }, { -1.9877193e-05f, 2.5768261e-05f, 9.0577543e-06f, -0.00013927462f }, { -0.0012323564f, -0.00042892846f, 7.2082106e-05f, 0.00010999853f }, { -0.00034618449f, -0.00017058897f, -0.00016535057f, -0.00096982024f }, { -0.00028039653f, -7.155747e-05f, -0.00075796707f, 0.00062756458f }, { 6.6596276e-05f, -7.9730809e-05f, -8.0686754e-05f, -2.9532397e-05f }, { -0.00084106867f, -0.00036762453f, 0.00012523548f, -0.00052789663f }, { 7.6718268e-05f, -0.0010042005f, -0.00042802983f, -0.0011951304f }, { -3.6972258e-05f, 2.1447505e-06f, -0.00035448623f, -1.0620008e-05f }, { 2.8326169e-05f, 2.2049468e-05f, 2.2640575e-05f, 1.7574827e-05f }, { -0.00014318496f, -0.0004811524f, -0.00049293303f, -0.00067646484f }, { -2.7469144e-05f, -5.9653763e-06f, -1.3998899e-05f, -0.00018475323f }, { -0.00017314302f, -0.00010954727f, -0.00040004932f, 3.31106e-05f }, { -3.6093435e-06f, -1.6125243e-05f, -4.9195648e-05f, 1.5586886e-05f }, { 0.0002059631f, -0.0004024722f, -0.00047984678f, -9.8485329e-05f }, { -0.00094100913f, -0.00073046048f, -0.00052500163f, -0.00068196784f }, { -2.2820197e-05f, -5.9454557e-05f, -6.2505468e-06f, -2.6569804e-05f } }, { { 2.6015883e-05f, 8.5398335e-06f, 3.8473185e-06f, 9.1409625e-06f }, { -0.00041459247f, -0.0001855224f, -0.00030529542f, -0.00016322166f }, { -8.8427847e-05f, -0.0002302048f, -0.00038072959f, -0.00076801295f }, { -0.00027717792f, -0.00028594346f, -0.00017910208f, -0.00027291164f }, { 2.8409311e-05f, -3.8005817e-05f, -4.2266878e-06f, -1.4520383e-05f }, { -0.0001088827f, -0.00021924377f, 3.9307406e-05f, -0.00032488556f }, { 0.00027997916f, 3.5103699e-05f, -5.7448764e-06f, 0.00010259251f }, { -4.7807894e-06f, -2.9470863e-05f, 2.6656233e-07f, -0.00014346393f }, { 0.00015527098f, -6.8528726e-05f, -1.1206714e-05f, 2.3422595e-05f }, { -0.0012763247f, -0.00051503472f, 0.00058055106f, -0.00068688488f }, { -6.1232076e-06f, -1.7073841e-05f, -0.00033533389f, -0.00078769935f }, { -0.00044113485f, -0.00027577451f, -0.0012008622f, 0.00013071136f }, { 1.834948e-05f, -0.00015615102f, -0.00016449385f, 3.6685217e-05f }, { -0.00063618257f, -0.00032641968f, -5.0281118e-05f, -0.00041378992f }, { -0.0010181884f, -0.0003871932f, -0.00050061147f, -0.0018967455f }, { -5.7650067e-05f, -5.1145774e-06f, -0.00017409773f, 1.9512036e-05f }, { 1.5838743e-05f, 2.503655e-05f, 2.5679098e-05f, 2.0053218e-05f }, { -0.00018055811f, -0.00044345237f, -7.9049557e-05f, -0.00095669161f }, { -4.98611e-05f, -1.1320605e-06f, 3.7756645e-06f, -8.7299215e-05f }, { -0.00011794063f, -0.00015778552f, -0.00036514881f, 4.7288704e-05f }, { -5.1753817e-06f, -1.5040527e-06f, -2.836739e-05f, -9.4945229e-06f }, { 0.00016873335f, -0.00031983601f, -0.00052281245f, 0.00019034815f }, { -0.0011988594f, -0.0010684975f, -0.00057577023f, -0.0009143845f }, { 5.0336006e-05f, -1.356148e-05f, 1.5582694e-05f, -2.0666272e-05f } } }, { { { 0.012207721f, 0.0044164612f, 0.0022704542f, 0.0042008503f }, { 0.29516302f, 0.139976f, 0.35038027f, 0.13748343f }, { 0.1462123f, 0.12114907f, 0.28473665f, 0.45762717f }, { 0.17976664f, 0.19141553f, 0.1209483f, 0.16393769f }, { 0.044254492f, 0.11383095f, 0.0062726904f, 0.023550537f }, { 0.14785458f, 0.10151341f, 0.045717467f, 0.42243971f }, { -0.24205201f, -0.033590842f, 0.0032064617f, -0.093924041f }, { 0.10866955f, 0.016299431f, 0.00081631108f, 0.15856447f }, { 0.10108337f, 0.057931152f, 0.024463589f, 0.21514346f }, { 0.47967783f, 0.75472932f, 0.5653649f, 0.64752457f }, { 0.30082544f, 0.15124922f, 0.23567284f, 0.47161499f }, { 0.54286166f, 0.61049777f, 0.61641378f, 0.51181399f }, { 0.39328762f, 0.25557559f, 0.25875912f, 0.22436901f }, { 0.45699569f, 0.16989563f, 0.2429263f, 0.3924359f }, { 0.92996797f, 1.1024806f, 0.78045387f, 1.2298879f }, { 0.19029829f, -0.022675055f, 0.28113642f, 0.034941166f }, { 0.013203939f, 0.013034069f, 0.013414649f, 0.011688038f }, { 0.076026927f, 0.13838472f, 0.29961655f, 0.31531564f }, { 0.089182386f, 0.010401684f, 0.029374547f, 0.22995838f }, { 0.052198894f, 0.039866726f, 0.11570972f, -0.013818992f }, { 0.0062380932f, 0.01788119f, -0.20765047f, 0.013339281f }, { 0.12436441f, 0.17318651f, 0.21554136f, 0.18600144f }, { 0.38005287f, 0.32135548f, 0.28632777f, 0.29211902f }, { 0.03798742f, 0.0450845f, 0.010912505f, 0.039060104f } }, { { 0.00077914246f, 0.00011130803f, 8.1110229e-05f, -0.00035312557f }, { 0.00051711901f, 0.00029701387f, 0.00040733345f, 0.00034149723f }, { 0.00063893978f, -0.00013702086f, 0.00030866699f, -0.00020070677f }, { 7.5899443e-05f, 9.7456273e-05f, -4.5352178e-05f, 7.6172703e-06f }, { 0.00066250814f, -0.00073033349f, 0.00015225542f, -0.0010197351f }, { 0.00040931533f, -0.00043022747f, 0.00093333285f, 0.0002579685f }, { -0.00067488578f, -0.0003706974f, -0.00044487256f, -0.00056555959f }, { 0.00075838366f, -0.0021903789f, -0.0026744174f, -0.00047135202f }, { -0.00081050821f, -0.0010297809f, -0.00099480849f, -0.00074914246f }, { 0.00063637392f, 5.248783e-05f, 0.00044645091f, 0.00018028446f }, { 0.00067430392f, 0.0004762628f, -0.00032736685f, 0.00041933609f }, { 6.2324555e-05f, -1.6709531e-06f, 0.00057418116f, -0.0010360999f }, { -0.00038256183f, -0.0010104012f, -0.00045533693f, -1.3888404e-05f }, { 0.00068274628f, 0.00068411875f, -0.00091273333f, 0.00016211145f }, { -0.00039440715f, 0.00027665323f, -0.00035895503f, 0.00013423207f }, { -0.00061939017f, 0.00012140102f, 0.00024178233f, 0.00064755788f }, { -0.00052441128f, -0.00050994483f, -0.00051126044f, 0.00066320373f }, { 0.00085915332f, 0.0013567332f, -0.00014328466f, 0.00056098523f }, { -0.0012682676f, 0.0029139719f, 0.0019812291f, -0.00053863027f }, { 0.0021895869f, 0.00062956835f, 0.0018161156f, 0.00011699452f }, { -0.0010337306f, 0.00016880497f, -0.0014942346f, -0.0034402453f }, { -0.0025336946f, -0.00019468865f, -0.00018045349f, -5.4312149e-05f }, { 0.00021491979f, 4.7651714e-05f, -0.00044921151f, 0.00046742044f }, { 0.0019408125f, 0.00044842687f, 0.0026003265f, -0.00090116109f } }, { { -0.0006591255f, 0.00022873584f, 0.00026313866f, -0.00060151354f }, { 0.00027198127f, 0.00034252944f, 0.00033246896f, 0.00035232159f }, { -0.00034460639f, -5.9085725e-05f, 7.836454e-05f, -0.00018946388f }, { 0.00018790551f, 0.0001918358f, 9.7031467e-05f, 0.00015259869f }, { -0.0023033429f, -0.0012945186f, -0.00080964072f, -0.00030432514f }, { -0.001359781f, 0.00055828912f, -0.00041912301f, 0.00019263336f }, { -0.00042789448f, -0.00018313775f, -0.00030217124f, -0.00028437496f }, { -0.0018340159f, 0.00030654336f, -0.00010781402f, -0.0011985455f }, { -0.002103478f, 0.00029492518f, -0.00042283946f, -0.001472689f }, { 0.00064558079f, 0.00049703204f, -0.00018932594f, -0.00038268301f }, { -0.00097813334f, -0.00057838807f, 0.00079268109f, 0.00039650774f }, { -0.00017335252f, 0.00074363734f, 0.0008194423f, -0.00065923207f }, { -0.00075344545f, -0.00026114262f, -0.00054658657f, -0.0013814943f }, { -0.00028279346f, 0.00055730283f, 0.00048990213f, -0.00022186466f }, { 0.00013438509f, -0.0001962818f, -0.00036195953f, 0.00042669461f }, { -0.00089003585f, -0.0011600794f, -0.0012554286f, -0.0012892408f }, { -0.00067007058f, -0.0010597247f, -0.0010590421f, 0.00044132516f }, { 0.0011626727f, 0.001261033f, -0.00072912018f, 0.00076332442f }, { -0.001204702f, -0.00011230019f, 0.00036178615f, -0.0017559004f }, { 0.00096282849f, 0.001025959f, 0.0011696947f, 0.00046633555f }, { -0.00082328571f, -0.00075771669f, -0.0011629302f, 0.00073458863f }, { -0.0016869269f, -0.00035239862f, -0.0004024204f, -0.0016276971f }, { 0.00029053123f, 0.00013409355f, -0.00049087974f, 0.00061969429f }, { -0.0013198997f, -0.0018615784f, -0.0025724061f, -0.0015563017f } } } }, { { { { -0.072246889f, -0.043157285f, 0.043289306f, 0.095998047f }, { 0.12597079f, 0.24289541f, -0.10930005f, -0.24150539f }, { 0.031889347f, -0.036238337f, -0.014521983f, -0.018963885f }, { -0.044155351f, -0.0077170425f, -0.043781059f, 0.047982339f }, { 0.093995001f, -0.0079510758f, -0.04688882f, -0.11125523f }, { 0.01700754f, -0.0034361033f, 0.055252382f, -0.053119426f }, { -0.0014957087f, -0.00063057103f, 0.037930463f, 0.017656646f }, { -0.017388477f, -0.084085888f, -0.067726647f, 0.061397079f }, { -0.070625168f, -0.061293011f, -0.077366932f, 0.11518646f }, { -0.14771316f, -0.12543895f, 0.052150789f, 0.10530462f }, { -0.03609139f, 0.001131616f, -0.039549928f, 0.03805765f }, { 0.064364205f, 0.066758929f, 0.045537002f, -0.05510954f }, { 0.049051369f, 0.098312455f, -0.01079726f, -0.11202623f }, { 0.033012208f, -0.0013996988f, -0.0049458824f, -0.028981527f }, { 0.008617177f, -0.00017670863f, -0.0052380282f, -0.0023438457f }, { -0.05901498f, -0.050754807f, -0.00011829844f, 0.037297411f }, { -0.056264446f, -0.03645315f, -0.066412698f, 0.019549244f }, { -0.11401603f, -0.11856524f, 0.12275022f, 0.11635143f }, { -0.0011999881f, -0.0016334327f, -0.0056868938f, 0.013393766f }, { 0.054526972f, 0.033632235f, 0.062591094f, -0.0025531074f }, { 0.073041316f, 0.073735243f, -0.06935254f, -0.11214186f }, { 0.034872822f, -0.015473423f, 0.037359975f, -0.026829465f }, { -0.015137592f, -0.0064462553f, 0.011771178f, 0.0025042048f }, { -0.038708904f, -0.033968131f, -0.044070885f, 0.024422773f } }, { { -0.047895007f, -0.016535938f, 0.04855533f, 0.018341613f }, { 0.004310087f, 0.01519838f, -0.0033290683f, -0.013597406f }, { 0.0015859181f, 0.016869623f, -0.019279963f, -0.01426933f }, { -0.0061048976f, 0.031131561f, 0.018085381f, -0.017927117f }, { 0.052590378f, 0.0066156852f, -0.0025756141f, -0.037241705f }, { 0.0083512619f, 0.0046235666f, 0.024122126f, -0.013443654f }, { 0.0010672274f, 0.00053123301f, -0.0016276029f, -0.04221993f }, { -0.0048754166f, -0.021474788f, -0.0039993317f, 0.011831691f }, { -0.054685347f, -0.050242732f, -0.007606251f, 0.043061893f }, { -7.5644942e-05f, 0.00086632318f, 0.0001960729f, 0.0013264286f }, { 0.0042413724f, -0.0057181522f, 0.0065940983f, -0.0078263328f }, { 0.0031260881f, -0.0013520907f, 0.025073658f, -0.010841673f }, { 0.038353769f, 0.06620308f, -0.0072105562f, -0.079188681f }, { 0.003099559f, -0.0022927921f, 0.021982683f, -0.018991144f }, { 0.012285675f, 0.0091834074f, -0.0041874571f, -0.032253924f }, { -0.014563556f, 0.009843969f, -0.010490279f, 0.012979866f }, { -0.005492286f, 0.064109426f, -0.034795617f, -0.020395732f }, { -0.023364141f, -0.059336321f, 0.080710391f, 0.038948527f }, { 0.0028384819f, 0.001822471f, 0.0012903958f, 0.012781079f }, { -0.004510518f, -0.0020008272f, 0.0017752876f, 0.0077607089f }, { 0.032279653f, 0.0041906079f, -0.034682371f, 0.0061335907f }, { -0.0082992317f, -0.025250117f, -0.017026845f, -0.028345042f }, { -0.013132125f, -0.026688493f, -0.0014827793f, -0.003236826f }, { 0.01650781f, 0.002313574f, -0.012897922f, 0.026077933f } }, { { 0.062668058f, 0.0081578851f, 0.018952049f, -0.012267283f }, { 0.0008567722f, 0.0033246009f, -0.0037620102f, -0.0096317368f }, { -0.0083012273f, 0.01184624f, -0.01209373f, 0.020208536f }, { 0.013862003f, 0.019166381f, 0.013235471f, -0.026788736f }, { -0.021904217f, -0.051018749f, 0.0020330268f, 0.006626371f }, { -0.015856131f, 0.0028024655f, -0.032825412f, -0.018920906f }, { 0.0020870233f, 0.0011616727f, -0.0032704368f, -0.027327141f }, { 0.01934969f, 0.002427195f, 0.049925128f, -0.0061414889f }, { 0.013158375f, 0.022248445f, 0.040266734f, -0.017583455f }, { 1.9024812e-05f, 0.00071602053f, 0.0012622199f, 0.0018791611f }, { -0.0011857767f, 0.0023417924f, 0.026237548f, -0.014687892f }, { -0.041419782f, 0.024942194f, -0.029143101f, 0.036590943f }, { -0.015470651f, -0.035208671f, -0.038530514f, 0.037434376f }, { -0.0029356279f, 0.0023358079f, 0.017641055f, 0.0038203652f }, { -0.0030449623f, -0.010187444f, 0.0066142145f, 0.0037433206f }, { 0.0080034603f, 0.011463159f, -0.0058129532f, 0.011831147f }, { -0.0091743137f, 0.045949289f, 0.022412137f, -0.0067531419f }, { 0.00069946656f, -0.0068974782f, 0.0091806954f, 0.0022160793f }, { -0.0027530077f, 0.00089797627f, 0.0066153093f, -0.010355635f }, { -0.019399018f, -0.0085762573f, 0.0208003f, -0.027739023f }, { -0.014354809f, -0.011971089f, -0.0031124986f, 0.044710091f }, { -0.011411144f, 0.0073253411f, -0.0087561348f, -0.014838738f }, { 0.018837992f, 0.00231775f, -0.013982978f, -0.0020044658f }, { 0.0012069362f, 0.0012202952f, 0.029106153f, 0.00062793994f } } }, { { { 0.054154158f, -0.11603661f, -0.025631275f, 0.054671866f }, { -0.2359715f, 0.093194255f, 0.21874866f, -0.08378526f }, { 0.0089903397f, 0.0087113885f, -0.015445726f, 0.011142042f }, { -0.0055372249f, -0.0041494086f, -0.033355186f, -0.010136823f }, { -0.015010227f, -0.0077144008f, 0.13058394f, -0.016779666f }, { -0.015855009f, 0.014090685f, 0.026549575f, 0.025677527f }, { -0.00065423811f, -0.0011506403f, 0.028628751f, 0.0086359197f }, { -0.010571292f, 0.035861454f, -0.025871285f, -0.024827688f }, { 0.00010603924f, 0.011433504f, -0.052819957f, -0.020208661f }, { 0.12243361f, -0.14574398f, -0.10091072f, 0.054524772f }, { -0.014659734f, -0.02291001f, 0.010102434f, -0.0099333349f }, { -0.0079939087f, 0.023468399f, 0.044548395f, 0.04568814f }, { -0.048188816f, 0.016469102f, 0.084818672f, -0.040634065f }, { 0.015089138f, 0.025396216f, 0.017000121f, 0.010820807f }, { -0.0098155552f, -0.00080001495f, 0.0020122754f, -0.00046896909f }, { -0.0018906417f, -0.03909342f, -0.020339049f, -0.024007559f }, { -0.0012744487f, -0.027829333f, -0.05202457f, -0.024366779f }, { 0.10406956f, -0.092281421f, -0.050420166f, 0.10716663f }, { -0.0049603976f, -0.0055370076f, -0.0016910106f, 0.012172389f }, { -0.0026486448f, 0.038673757f, -0.0016176887f, 0.052692494f }, { -0.03722357f, 0.055455783f, 0.067738953f, -0.0087990582f }, { -0.0026491637f, 0.017275247f, 0.010687117f, 0.020312052f }, { -0.0016032469f, 0.0090272843f, -0.0079027514f, -0.0050039898f }, { -0.0073653412f, -0.033150577f, 0.0082912493f, -0.021457881f } }, { { -0.0059001999f, 0.033600833f, 0.066374213f, -0.018058548f }, { -0.0037864945f, -0.0064946131f, 0.0018627774f, 0.0044899139f }, { 0.0048961861f, -0.0034770968f, -0.0002311598f, -0.0053935761f }, { 0.0090090757f, 0.012149811f, 0.0029969663f, 0.0049403543f }, { -0.042874682f, -0.0083455851f, -0.0064437344f, 0.0010579362f }, { 0.011866873f, -0.017157526f, -0.014724976f, 0.0054373752f }, { -0.0006329516f, -0.00024834697f, 0.0015416168f, -0.014246989f }, { 0.031530357f, -0.052715858f, -0.0063186617f, -0.0070200141f }, { -0.0082273844f, 0.053856605f, 0.0096812384f, 0.01684635f }, { -0.00017150577f, 0.00097354737f, 0.0013944706f, 0.00085166684f }, { -0.013604545f, 0.0089329355f, -0.013809086f, 0.0025044469f }, { -0.020284731f, 0.0004724419f, -0.045697697f, -0.01844702f }, { 0.017874081f, -0.0040537465f, -0.023316716f, -0.026344708f }, { 0.0092557469f, -0.014456327f, -0.0092919835f, 0.0091758924f }, { 0.016058873f, 0.0019220807f, 0.0031692823f, 0.0024577167f }, { -0.021184352f, 0.021287579f, -0.0048442696f, 0.0095799112f }, { 0.035229915f, -0.054291919f, -0.013871324f, 0.035585241f }, { 0.001275203f, 0.011513119f, 0.020184769f, -0.0061701639f }, { 0.011353237f, 0.0052697685f, 0.0047637419f, -0.020278005f }, { 0.0068266296f, -0.01173749f, 0.037482577f, -0.0083236299f }, { 0.025699221f, -0.03651135f, -0.032342446f, -0.0059784486f }, { 0.0029540635f, -0.0021598269f, 0.0028168477f, 0.0044577193f }, { 0.0038274002f, -0.0050806333f, 0.007628551f, 0.0027461742f }, { 0.0056567464f, 0.006846664f, -0.031161558f, -0.0040832656f } }, { { 0.025668431f, 0.0093723617f, 7.4324163e-05f, -0.023051436f }, { -0.010148124f, 0.0018159908f, 0.0072269566f, 0.00082671261f }, { 0.0069741056f, 0.023493533f, 0.028507618f, -0.026874125f }, { 0.0083316277f, -0.024891629f, 0.013623217f, 0.0038373532f }, { -0.020992516f, 0.070912136f, -0.0014634877f, -0.015680371f }, { 0.02178962f, -0.003772636f, -0.024578501f, -0.047467019f }, { 0.0028586275f, 0.0033445767f, 0.0049576063f, -0.017365739f }, { 0.0075721122f, 0.010652219f, -0.024031886f, -0.0001146548f }, { 0.016381176f, -0.044765924f, -0.038036229f, -0.014041395f }, { -0.00082564842f, 0.00033107944f, 0.00073792054f, 0.0005712734f }, { 0.0080934887f, 0.014534447f, -0.0071347609f, 0.0085413493f }, { -0.018211778f, 0.0064443848f, 0.017393403f, 0.011490985f }, { -0.071531366f, 0.030059694f, 0.049103287f, 0.0074609412f }, { 0.00770209f, -0.017999995f, -0.040048679f, -0.0029073853f }, { 0.020442166f, 0.0019454488f, -0.019644905f, 0.021793285f }, { 0.035171271f, 0.0080192155f, -0.023151504f, 0.014168348f }, { -0.048901887f, -0.0039613606f, 0.0021703807f, 0.030275152f }, { 0.044666116f, -0.029756153f, -0.015570779f, 0.034470632f }, { -0.0078700362f, 0.0037551741f, 0.0003070052f, -0.0031237403f }, { 0.015288427f, -0.01284757f, -0.0075319169f, 0.026981487f }, { -0.0093872483f, 0.013517073f, -0.030221944f, 0.058356065f }, { 0.0042326205f, -0.016381154f, 0.021475001f, 0.01008732f }, { 0.0034929117f, 0.020531314f, -0.0085114063f, 0.004821913f }, { 0.014314413f, 0.01127037f, -0.017197896f, 0.0046932185f } } }, { { { 0.99591552f, 0.99230689f, 0.99873374f, 0.99387895f }, { 0.96356049f, 0.96556546f, 0.96964041f, 0.96677566f }, { 0.99945097f, 0.99930521f, 0.99977525f, 0.99975808f }, { 0.99900933f, 0.99996161f, 0.99848418f, 0.99879675f }, { 0.99545951f, 0.99993863f, 0.99032786f, 0.9936502f }, { 0.99972964f, 0.99989482f, 0.99811938f, 0.99825798f }, { 0.99999867f, 0.99999914f, 0.9988702f, 0.99980681f }, { 0.99979292f, 0.99581299f, 0.99736843f, 0.99780458f }, { 0.99750292f, 0.99805433f, 0.99560254f, 0.9931383f }, { 0.98142286f, 0.98133774f, 0.99352772f, 0.9929441f }, { 0.99924096f, 0.99973689f, 0.99916652f, 0.99922617f }, { 0.99789446f, 0.9974931f, 0.99796885f, 0.99743448f }, { 0.9976331f, 0.99501931f, 0.9963379f, 0.99287411f }, { 0.99934104f, 0.99967648f, 0.99984325f, 0.99952138f }, { 0.9999147f, 0.99999966f, 0.99998426f, 0.99999714f }, { 0.99825531f, 0.99794572f, 0.99979313f, 0.99901579f }, { 0.99841509f, 0.99894779f, 0.99643504f, 0.99951192f }, { 0.98801309f, 0.98864879f, 0.99115599f, 0.98740957f }, { 0.99998698f, 0.99998334f, 0.9999824f, 0.99983621f }, { 0.99850879f, 0.99868574f, 0.99803794f, 0.99860752f }, { 0.99663402f, 0.99573479f, 0.99528974f, 0.99365325f }, { 0.99938825f, 0.99973103f, 0.99924472f, 0.99943364f }, { 0.99988413f, 0.99993848f, 0.99989949f, 0.99998434f }, { 0.99922338f, 0.99887297f, 0.998994f, 0.9994714f } }, { { -0.0050599833f, 0.003362263f, 0.0035202243f, -0.00056864904f }, { -0.0014675187f, -0.0029154981f, -0.00077796172f, -0.0027392627f }, { -0.0010916411f, 0.00078232803f, 0.0014339533f, -0.0020166729f }, { 0.011183745f, 0.008298699f, 0.011631254f, 0.00030693508f }, { -0.0012964861f, -0.00028098882f, 0.00098513135f, -0.0052243577f }, { 0.0091119501f, 0.002780703f, 0.011045274f, 0.00334383f }, { 4.1103001e-05f, 5.5767744e-05f, 0.0030605577f, 0.0022152241f }, { 0.00085375099f, 0.0026952672f, 0.0071937971f, 0.0056504112f }, { -0.003773118f, 0.0047936307f, -4.5743022e-05f, -0.0038357994f }, { 2.3815581e-05f, 0.0002468657f, 0.00013492048f, -0.00018410816f }, { 0.0070959632f, -0.00205589f, 0.0056417297f, 0.0030702073f }, { 0.010671769f, 0.0074346008f, 0.0012867659f, 0.0075437523f }, { -0.0013037272f, -0.0058374269f, 0.0025899757f, -0.0071565118f }, { 0.0030041304f, 0.0018011397f, 0.0093160386f, 0.0082062863f }, { 0.0053156934f, 0.0036543193f, 0.0048724246f, 0.0035118324f }, { -0.0053866158f, 0.0024053442f, 0.00052459148f, 0.0090970513f }, { 0.011239324f, -0.0010327051f, -0.00097551594f, 0.0044180668f }, { -0.0024379533f, -0.0088232426f, -0.012355568f, -0.0031875953f }, { 0.0026244123f, 0.0011858999f, 0.0028110843f, -0.001005442f }, { 0.0059514328f, 0.0018892606f, 0.0050231625f, 0.0046700575f }, { 0.00050741664f, 0.0096547476f, -0.00079618251f, 0.0024532112f }, { 0.0058717468f, -0.0017457656f, 0.0080261577f, -0.00048009588f }, { 0.0025457914f, 0.0016788968f, 0.0013982313f, 0.00073909928f }, { 0.0075035778f, 0.011234409f, 0.0079271096f, 0.006672353f } }, { { 0.0095152396f, 0.0011785006f, -0.00081996856f, 0.0018904938f }, { -0.0025430397f, -0.0010236291f, -0.0020168276f, -0.0021827861f }, { 0.0036295778f, 0.005406882f, 0.0040788276f, -0.0057729163f }, { -0.00029952998f, 0.0024548208f, 0.0088548836f, 0.0019084209f }, { 0.0034184324f, -0.0088925589f, 0.00023040452f, 0.00017437939f }, { 0.0037804595f, 0.012156355f, 0.0041276361f, 0.012721488f }, { 7.4846461e-05f, 0.00010580108f, 0.013483417f, 0.0024239851f }, { 0.00026411032f, -0.00059353627f, 0.0093564271f, 0.0061507538f }, { 0.0016065383f, -0.0027764641f, 0.0013620195f, 0.0010062065f }, { 9.7127925e-05f, 0.00017275393f, 1.0814607e-05f, -0.00022627793f }, { 0.0048710612f, -0.00014794569f, 0.0082832436f, -0.00072595412f }, { -0.0027392579f, 0.0066783951f, 0.00087397132f, 0.001567366f }, { -0.003378151f, 0.0025916338f, -0.0025553201f, 0.0030152022f }, { 0.0096818399f, 0.0012695523f, 0.0072489949f, 0.016881099f }, { 0.0022796191f, 0.0051693266f, 0.0023373397f, -0.0041448561f }, { -0.0002074582f, 0.0035962454f, -0.0007460719f, 0.0025086317f }, { 0.0035784996f, 0.003162753f, 0.0022592918f, 0.00024595998f }, { -0.0051294944f, -0.0041428868f, -0.0027597f, -0.0039539398f }, { 0.0022410392f, 0.00031263884f, 0.0016376751f, -0.0022787113f }, { 0.0025647038f, 0.0074733037f, 0.0051722028f, 0.0024463612f }, { 0.0011787227f, 0.0071159753f, 0.0017217143f, 0.0062717989f }, { 0.0046836737f, 0.0038976423f, 0.00062832002f, 0.0027638154f }, { 0.0014142926f, 0.0024903802f, 0.0015757227f, 0.0011628587f }, { 0.0016928585f, 0.0043828548f, 0.001653268f, 0.011450696f } } }, { { { 2.8886078f, 2.8900127f, 2.7925705f, 2.7895874f }, { 4.5455217f, 4.5284714f, 4.7042338f, 4.6915273f }, { 0.96672505f, 0.99303664f, 0.98927606f, 1.0351588f }, { 1.2743756f, 1.2525364f, 0.99649566f, 0.94572778f }, { 2.6910679f, 2.6922168f, 2.8503404f, 2.8246076f }, { 1.256075f, 1.2325025f, 1.5911826f, 1.6091223f }, { 1.3601759f, 1.3606869f, 1.2793533f, 1.240925f }, { 2.0291828f, 2.0506809f, 1.7341658f, 1.6555689f }, { 2.6663531f, 2.6921882f, 3.1290975f, 3.11849f }, { 5.3676887f, 5.3663279f, 5.3848664f, 5.3852162f }, { 1.0586431f, 1.0865889f, 0.8196623f, 0.8076665f }, { 1.6967251f, 1.7305944f, 1.5450413f, 1.6347879f }, { 3.0908857f, 3.0706775f, 3.2974343f, 3.3053965f }, { 1.2172073f, 1.3839086f, 1.5086796f, 1.4295506f }, { 0.97676668f, 1.0856738f, 0.98747912f, 1.0385491f }, { 1.5662275f, 1.4603538f, 1.784278f, 1.6575438f }, { 2.1085757f, 2.2092885f, 2.1410448f, 2.1518347f }, { 4.0214776f, 4.006424f, 3.7686967f, 3.7771354f }, { 1.2089239f, 1.2116036f, 1.1244311f, 1.0901017f }, { 1.1827246f, 1.1472796f, 1.7516784f, 1.7833976f }, { 2.2113439f, 2.197512f, 2.2692963f, 2.2787751f }, { 0.98819531f, 1.057833f, 1.3587301f, 1.3890421f }, { 1.208957f, 1.2247867f, 1.2301205f, 1.2325178f }, { 1.0499613f, 1.1319197f, 1.4067885f, 1.3209087f } }, { { -0.002860931f, -0.0033581281f, -0.0047612075f, -0.0030481839f }, { -0.0017370907f, -0.0065700936f, -0.0011051926f, -0.0046915938f }, { -0.0006126207f, 0.0010791181f, -0.022876686f, -0.015937275f }, { -0.010040922f, -0.016433531f, -0.0044976975f, -0.029838315f }, { 0.00056888968f, -0.0093450028f, -0.00041549218f, -0.0069079656f }, { -0.029781683f, -0.019722587f, 0.019472312f, 0.0016798037f }, { -0.0015128736f, -0.0012250172f, -0.0091568262f, -0.0091368119f }, { 0.0010846814f, 0.0017189068f, 0.012975603f, -0.0051530971f }, { -0.026042808f, -0.0090684857f, -0.0021498742f, -0.0032938309f }, { -0.0012792901f, -0.0010431731f, -0.0021366737f, -0.0025526365f }, { -0.03218779f, -0.013848893f, -0.021872476f, -0.029443623f }, { 0.008300061f, 0.011951182f, -0.011139414f, 0.0098292843f }, { -0.0065854884f, -0.020955083f, -9.3843515e-05f, -0.0078425688f }, { -0.054726229f, -0.0073673428f, -0.019267231f, -0.03383648f }, { -0.049769726f, 0.0065482059f, -0.010189395f, -0.0050480393f }, { 0.022565943f, -0.020311569f, 0.0091512717f, -0.015600752f }, { -0.014418429f, 0.0060070592f, -0.0055296743f, -0.003361885f }, { 8.8146509e-05f, -0.0082609252f, 0.0036746024f, 0.0040108321f }, { 0.0010230427f, 4.8153189e-06f, 0.0052893378f, -0.0096303521f }, { 0.0032909351f, -0.010982824f, 0.003880027f, 0.0097699095f }, { -0.006528317f, -0.012608887f, -0.0057088008f, -0.003867806f }, { -0.046599771f, -0.024701737f, -0.001078321f, -0.0041018649f }, { -0.021680777f, -0.021120711f, 0.0055144734f, -0.0031337995f }, { -0.030559213f, 0.0089872726f, -0.011166202f, -0.0077587071f } }, { { -0.0059548858f, -0.0040070313f, -0.0062572119f, -0.0047711065f }, { -0.0031938803f, -0.005431389f, -0.0026376521f, -0.0046119366f }, { 0.0064917253f, 0.013030824f, -0.027850471f, -0.011824849f }, { -0.032644485f, -0.025045016f, -0.0034396539f, -0.039827623f }, { -0.007691681f, -0.014095643f, -0.0008171964f, -0.0051336386f }, { -0.035626586f, -0.021424668f, 0.00035790929f, 0.0099705685f }, { -0.0019006762f, -0.0014887089f, -0.0050782898f, -0.0096835564f }, { -0.00087496879f, 0.0052586834f, 0.017041675f, -0.00046753956f }, { -0.022489507f, -0.0084834888f, 0.0017184219f, -0.0023910992f }, { -0.0010618265f, -0.00085888729f, -0.0020035777f, -0.0024245283f }, { -0.029245834f, -0.038977066f, -0.013385246f, -0.030312138f }, { -0.0028497869f, 0.014205986f, -0.0125692f, 0.0037959624f }, { -0.0086377959f, -0.019175965f, -0.007684309f, -0.005037677f }, { -0.063945685f, -0.0060751259f, -0.0057457302f, -0.019079575f }, { -0.043745147f, 0.013651906f, -0.034067394f, 0.0012111497f }, { 0.0086647574f, -0.019171418f, 0.020745219f, -0.0055629951f }, { -0.024541273f, 0.0072112135f, -0.0078821942f, -0.0085072621f }, { -0.0018227939f, -0.0021153099f, 0.008577002f, 0.0043865151f }, { -0.013984752f, -0.012209334f, 0.00023638151f, -0.0085025952f }, { -0.0099800075f, -0.0095390578f, 0.0081328135f, 0.012673433f }, { -0.0099975551f, -0.0028467616f, -0.010712056f, -0.0045012212f }, { -0.011329139f, -0.0084709831f, -0.0070232966f, 0.0015504012f }, { -0.015334801f, -0.0075637633f, -0.01107439f, -0.0094188163f }, { -0.017505269f, -0.00013701888f, -0.033955823f, -0.034192649f } } }, { { { 0.16413327f, 0.084074422f, 0.10646123f, 0.18806073f }, { 0.039511019f, 0.058967072f, 0.035166958f, 0.052296507f }, { 0.26970995f, 0.21576211f, 0.2954278f, 0.29870678f }, { 0.40442043f, 0.38744132f, 0.14502571f, 0.24076804f }, { 0.22655046f, 0.20912486f, 0.015295019f, 0.16442957f }, { 0.69235319f, 0.6080183f, 0.36756076f, 0.23314717f }, { 0.085565328f, 0.075535626f, 0.22162979f, 0.33140596f }, { 0.16109547f, 0.11961895f, 0.26619212f, 0.25941009f }, { 0.27077686f, 0.23481238f, 0.063446408f, 0.11614487f }, { 0.026116057f, 0.027491327f, 0.030421883f, 0.039965345f }, { 0.33922592f, 0.38039792f, 0.27167385f, 0.31510976f }, { 0.32744968f, 0.22567102f, 0.23116584f, 0.18867836f }, { 0.29783431f, 0.28054079f, 0.26752139f, 0.23889932f }, { 0.61721263f, 0.60602797f, 0.51283622f, 0.47601102f }, { 0.51383952f, 0.53111455f, 0.44519064f, 0.42875877f }, { 0.3485879f, 0.35374178f, 0.53292055f, 0.53995494f }, { 0.4366997f, 0.35554257f, 0.14878367f, 0.22083288f }, { 0.12855375f, 0.16718264f, 0.17583661f, 0.11125895f }, { 0.35898096f, 0.37222307f, 0.35439108f, 0.35956111f }, { 0.16773044f, 0.25668894f, 0.23246756f, 0.1506316f }, { 0.36172813f, 0.26938211f, 0.20069185f, 0.1714591f }, { 0.3998571f, 0.23607244f, 0.34121623f, 0.29126696f }, { 0.31471307f, 0.29500525f, 0.39451396f, 0.40013999f }, { 0.29554399f, 0.28083636f, 0.47190649f, 0.47892938f } }, { { 0.01419653f, -0.061214452f, -0.032506906f, 0.0078227125f }, { -0.015799432f, 0.0136148f, -0.0090824684f, 0.013638505f }, { 0.023848919f, 0.022034707f, 0.022812846f, 0.022790329f }, { -0.0026324255f, -0.0053566952f, 0.00027470228f, 0.050203583f }, { 0.0035659857f, -0.02015272f, -0.039043616f, 0.054511651f }, { 0.0052075445f, 0.0051043119f, -0.011801097f, -0.0074336577f }, { 0.020735195f, 0.01811747f, 0.00808952f, 0.01140964f }, { -0.0073139049f, 0.011075347f, 0.0057685988f, 0.010251582f }, { 0.024813488f, -0.01629986f, -0.012536791f, -0.01110061f }, { -0.014508648f, -0.021444084f, -0.023836972f, -0.014258253f }, { 0.0079687141f, -0.00092011446f, 0.060249601f, 0.033199468f }, { -0.020822483f, -0.013924875f, -0.005068391f, -0.016928794f }, { -0.030059f, -0.013887475f, -0.045329289f, -0.04449219f }, { 0.007264541f, 0.0015213919f, -0.0066322618f, -0.0036449174f }, { 0.0057175046f, 0.0012159867f, -0.00054271896f, 0.0020625484f }, { 0.0027083179f, -0.0012554897f, -0.0044854592f, -0.0045242423f }, { -0.017906563f, -0.028301884f, -0.010139427f, 0.0035851304f }, { -0.020245794f, 0.01149232f, 0.011320484f, -0.013561794f }, { 0.0068048997f, 0.011957759f, 0.0046962412f, -0.0015476541f }, { -0.0022514613f, 0.019996868f, 0.0051520398f, -0.023405604f }, { 0.0055213198f, 0.0070384134f, 0.024405643f, -0.02050399f }, { 0.039987541f, 0.021127504f, -0.012323503f, -0.0041538161f }, { 0.0072321478f, 0.0053097351f, 0.0039966161f, 0.013617175f }, { 0.030470642f, 0.0044694115f, -0.0024591651f, -0.0027274707f } }, { { -0.040500402f, -0.039657034f, -0.017497359f, -0.017857145f }, { -0.0015646885f, -0.020957371f, -0.0057356498f, -0.0060587007f }, { 0.0070388709f, -0.013205178f, -0.00033412934f, 0.02192306f }, { -0.0042317723f, 0.020620857f, -0.012309167f, 0.065948811f }, { -0.016686589f, 0.013616667f, 0.030139062f, -0.019023551f }, { 0.015181564f, 0.008673659f, -0.0014559576f, -0.025916054f }, { 0.031630671f, 0.027030197f, -0.026982415f, 0.025214731f }, { -0.003845127f, -0.00062884599f, -0.029488655f, -0.0051457939f }, { -0.0032476351f, 0.0021153707f, -0.033110808f, -0.033629213f }, { -0.0064637077f, -0.010805748f, -0.014982403f, -0.0084641529f }, { 0.0087766042f, 0.017780238f, 0.026838871f, 0.032580257f }, { 0.0010700985f, -0.037414784f, -0.0053773565f, 0.0040969752f }, { -0.02637392f, -0.050236074f, -0.048422986f, -0.069357813f }, { -0.0089483588f, 0.0026259727f, 0.0040142797f, -0.010752754f }, { -0.0025658872f, 0.0071106029f, 0.015467367f, 0.0012536589f }, { -0.0037247444f, -0.0036991733f, -0.015429566f, -0.016148852f }, { -0.024788221f, -0.045938054f, -0.028679471f, 0.011593494f }, { -0.032699114f, -0.036800967f, -0.033870575f, -0.031842203f }, { 0.018156047f, 0.02457546f, 0.0209432f, 0.015057433f }, { 0.0043152638f, 0.025831372f, -0.019608349f, -0.026614397f }, { -0.0057047815f, -0.013831909f, 0.027613211f, -0.043616864f }, { 0.014124478f, -0.010786326f, 0.010775415f, -0.023241344f }, { 0.018337827f, 0.0048735321f, 0.018371717f, 0.022106807f }, { 0.013619207f, 0.022051384f, 0.0082720974f, -0.0030262071f } } } }, { { { { 0.083322661f, 0.079807165f, 0.03660117f, -0.051657142f }, { -0.099216074f, -0.0080141573f, 0.10637241f, 0.0367403f }, { 0.20813681f, -0.0001361621f, -0.20762563f, -0.085913357f }, { -0.22091149f, 0.10003156f, -0.16122219f, 0.31542901f }, { 0.16226908f, 0.02665194f, -0.012123307f, -0.16559939f }, { -0.14025496f, 0.025804505f, 0.076174345f, 0.20548591f }, { 0.0035713609f, -0.0092551928f, -0.099937652f, 0.0038879391f }, { 0.12405732f, -0.0053373497f, -0.030865175f, -0.060934551f }, { -0.0060175826f, -0.026583926f, -0.075326797f, -0.0063155886f }, { 0.036389362f, 0.054175433f, 0.06490927f, -0.038784258f }, { 0.30604876f, -0.030813476f, 0.011402956f, -0.21074796f }, { -0.31769497f, 0.046793931f, -0.038212559f, 0.21137297f }, { 0.12952945f, 0.20720126f, 0.08525845f, -0.14568109f }, { -0.09735197f, -0.17799099f, -0.12256082f, 0.038889119f }, { 0.002114572f, 0.026037779f, -0.0036772795f, 0.13478173f }, { 0.094577863f, 0.0057382415f, -0.087017736f, -0.059444148f }, { 0.054953104f, 0.071323301f, 0.097417831f, 8.3254475e-05f }, { -0.11005534f, 0.027214076f, 0.0059378205f, 0.02443999f }, { 0.27096654f, 0.1864966f, 0.034810947f, -0.25886676f }, { -0.35626794f, 0.037256657f, -0.17795321f, 0.52988269f }, { 0.14913899f, -0.0086988732f, -0.028760192f, -0.21779266f }, { -0.16010301f, -0.17699785f, 0.017269826f, 0.17878541f }, { -0.0049504093f, -0.02387924f, -0.04034852f, -0.060461173f }, { 0.10405347f, 0.0072745723f, -0.10244372f, -0.072981984f } }, { { 0.019363393f, 5.327311e-05f, 0.0075925373f, 0.0019542034f }, { -0.051707557f, 0.06554253f, 0.0050626046f, -0.0061857803f }, { 0.022891698f, 0.014872273f, -0.020436928f, 0.0069081531f }, { -0.044566611f, 0.019854557f, 0.023600607f, -0.0055387351f }, { 0.02283957f, -0.067086756f, 0.088865856f, -0.033915007f }, { 0.0020254431f, -0.16422426f, 0.032495902f, 0.012460808f }, { -0.017316175f, 0.023440087f, 0.011459595f, 0.0043887872f }, { 0.027714908f, -0.06907548f, 0.013578806f, -0.009848884f }, { 0.0044782488f, 0.0079432606f, 0.010143137f, 0.023589488f }, { 0.014325082f, 0.0075465848f, -0.0079373813f, -0.0056032635f }, { 0.025123579f, 0.01904807f, -0.0092328848f, -0.019002052f }, { -0.02633985f, -0.019560519f, -0.065544737f, 0.0073352606f }, { 0.044308433f, -0.0032233834f, 0.01324206f, -0.00047128106f }, { -0.076577611f, -0.021853603f, -0.020190543f, 0.0026420865f }, { -0.0029799448f, -0.0083566545f, 0.14896601f, 0.0078617095f }, { 0.021033237f, -0.08234711f, -0.020642328f, -0.0089829962f }, { 0.043793881f, 0.0096494147f, 0.035831274f, -0.01294602f }, { -0.014064874f, 0.066144489f, 0.0143429f, 0.015113964f }, { 0.043111732f, 0.0029232804f, -0.016912145f, 0.012142059f }, { 0.0014186333f, -0.0078590166f, 0.065781153f, -0.038375123f }, { 0.02255714f, -0.030191796f, -0.078373164f, -0.0017593196f }, { -0.033878798f, 0.016266579f, 0.013539653f, 0.043519216f }, { 0.019046482f, 0.0080403173f, -0.0010755939f, 0.03305222f }, { 0.023206448f, -0.054323067f, -0.035173093f, -0.010873592f } }, { { 0.014068291f, -0.026418786f, 0.016375695f, 0.0048801469f }, { 0.024404214f, 0.0073572002f, -0.027247654f, 0.00093849398f }, { 0.012741523f, -0.012913063f, 0.0054881373f, -0.021780769f }, { -0.020497215f, 0.057437717f, 0.0031122704f, 0.014713732f }, { 0.012765254f, -0.052846334f, 0.048042201f, 0.0016578534f }, { 0.031245254f, -0.0469321f, -0.057199738f, 0.012436479f }, { -0.0022837759f, 0.0068501747f, 0.010541107f, -0.0005227683f }, { -0.0187059f, 0.0025631581f, -0.0082184266f, 0.0026294483f }, { 0.0053899388f, -0.0199458f, 0.0023448066f, 0.016215236f }, { 0.021117204f, 0.010868775f, -0.016412681f, -0.016399297f }, { -0.0026199223f, -0.011436548f, 0.0031355049f, 0.011933919f }, { 0.017940023f, 0.090292392f, -0.061029038f, 0.016388845f }, { 0.0074493061f, -0.045849358f, -0.082612855f, 0.025851315f }, { 0.061276666f, -0.024654813f, 0.035447334f, -0.025952766f }, { -0.0068267167f, -0.02207426f, 0.003724368f, 0.0070458116f }, { 0.021714649f, -0.017552721f, -0.037105408f, 0.024398534f }, { 0.0092901891f, -0.021559075f, 0.009034776f, -0.016574279f }, { -0.017218595f, -0.041930302f, 0.003369899f, 0.017959363f }, { -0.0022510875f, 0.028106616f, -0.042936548f, -0.041948028f }, { -0.017145551f, -0.032331654f, 0.021486923f, -0.020295391f }, { -0.023196465f, -0.088353584f, 0.010086154f, 0.018689553f }, { -0.024508386f, -0.00058959302f, -0.02867958f, 0.019018994f }, { 0.0088748911f, 0.012528454f, -0.016636351f, 0.0078166115f }, { 0.00066772723f, 0.001693912f, 0.032066885f, 0.016951148f } } }, { { { 0.015200105f, 0.071414961f, -0.020616434f, 0.0063982643f }, { -0.084578144f, -0.12318522f, -0.035470756f, 0.057833574f }, { 0.19487946f, 0.44043059f, 0.10981527f, -0.31907303f }, { -0.17774238f, -0.30460726f, -0.53133003f, 0.31186606f }, { -0.1172677f, 0.3183613f, 0.10375266f, -0.066515168f }, { 0.054176263f, -0.12382077f, -0.033807438f, 0.039809238f }, { -5.3634009e-05f, 0.004084452f, 0.005103199f, -0.060697866f }, { 0.06093199f, 0.060355274f, 0.049176467f, -0.060579228f }, { 0.054611799f, 9.0520863e-05f, -0.048891261f, -0.047609349f }, { -0.036428706f, 0.06336736f, 0.0020843807f, 0.033254378f }, { 0.26975732f, 0.51328693f, 0.29976157f, 0.049031141f }, { -0.28383516f, -0.48219276f, -0.27898799f, -0.033028759f }, { -0.078976834f, 0.14077934f, 0.098587186f, 0.051336328f }, { 0.076281206f, -0.074223398f, -0.053178835f, -0.099578331f }, { -0.056377095f, -0.00066113896f, -0.11597726f, 0.058805777f }, { -0.0027130032f, 0.12007881f, 0.0081935835f, -0.10415807f }, { -0.019349408f, 0.06206561f, -0.0079099126f, 0.079363093f }, { -0.059959607f, -0.0591041f, -0.047505451f, -0.0031496967f }, { -0.11419194f, 0.20904287f, 0.53960104f, 0.10467592f }, { -0.21312862f, -0.34770872f, -0.54593093f, 0.23230512f }, { -0.073229448f, 0.12913f, 0.27728133f, -0.050627706f }, { 0.082312471f, -0.24529296f, -0.12381516f, 0.05577292f }, { 0.03015389f, -0.0015805638f, 0.024306632f, -0.080697961f }, { 0.061367564f, 0.056058289f, 0.041197211f, -0.015551356f } }, { { -0.029269776f, -0.030251548f, 0.01352869f, 0.0084860712f }, { 0.053983187f, 0.047657625f, -0.026379004f, 0.022474039f }, { 0.011898439f, 0.045120742f, -0.024430477f, -0.081318878f }, { -0.0012641508f, -0.018495044f, -0.030127865f, -0.0088483264f }, { 0.040728292f, 0.010691761f, -0.023566342f, 0.028045232f }, { 0.014593998f, 0.0047006468f, -0.049032498f, -0.011446808f }, { 0.00045433705f, -0.0030610749f, -0.010359449f, -0.0026455857f }, { -0.0026794352f, -0.032142744f, 0.010153936f, -0.0034586152f }, { 0.0097198782f, 0.0051005644f, 0.03482872f, -0.0043676475f }, { -0.0012381415f, -0.025746274f, -0.0081178021f, 0.0041481596f }, { -0.01598781f, 0.0048815642f, 0.06313106f, -0.0062291669f }, { 0.072970618f, -0.041153529f, -0.007457013f, 0.059776924f }, { 0.0024768493f, 0.0093018711f, 0.024827984f, 0.043842172f }, { -0.012927661f, -0.023256709f, -0.0035951539f, -0.069710027f }, { 0.0064149713f, 0.0019783425f, 0.010135188f, 0.019449636f }, { -0.0071551675f, 0.015761815f, 0.0086309278f, 0.038854386f }, { 0.020978109f, -0.0056696814f, 0.0025526797f, -0.017352926f }, { -0.010711116f, -0.0097050903f, 0.0022304504f, -0.0039308489f }, { 0.036904234f, 0.025927127f, 0.028330671f, 0.051193417f }, { -0.00076391153f, -0.077528792f, -0.029763477f, 0.0033945843f }, { -0.01775202f, 0.034507636f, 0.065392848f, -0.017840909f }, { -0.019567742f, -0.019880035f, 0.055214211f, -0.02206159f }, { 0.01110111f, 0.0022938832f, -0.011417507f, 0.017692635f }, { 0.050208493f, -0.028178909f, 0.0065276591f, -0.0056267473f } }, { { 0.0065622702f, -0.0012303136f, -0.0081183663f, 0.00079383048f }, { 0.030775912f, 0.052260356f, -0.019758331f, -0.020044147f }, { 0.019016537f, -0.043070451f, 0.035298744f, -0.040592775f }, { 0.010468089f, 0.00057085185f, 0.0081761984f, 0.0033382478f }, { 0.047189462f, -0.052695409f, 0.021849623f, 0.033585939f }, { 0.0012065616f, -0.050287476f, -0.065085924f, -0.039012886f }, { -0.012294892f, 0.006839242f, 0.0051165438f, -2.0711078e-05f }, { -0.03292822f, 0.015299577f, 0.0029119931f, 0.0073040242f }, { -0.0086784873f, 0.0085910164f, -0.0059378411f, -0.010259049f }, { -0.014191355f, -0.011172486f, -0.01299927f, 0.015386671f }, { 0.040453224f, -0.041489173f, 0.015047889f, 0.064340197f }, { -0.020000046f, 0.058477092f, -0.0018150465f, 0.048536972f }, { -0.006105982f, 0.03437044f, 0.0087640339f, 0.032868283f }, { -0.027120362f, 0.016579996f, -0.01708524f, 0.011178424f }, { 0.030535528f, 0.0058718219f, -0.031240404f, 0.024241052f }, { 0.003729958f, -0.055735848f, -0.0055392842f, 0.03447519f }, { -0.04084502f, -0.01227488f, 0.0062970198f, -0.021996031f }, { 0.053671675f, -0.067787009f, 0.0053426012f, -0.0080796738f }, { -0.021911856f, 0.038395527f, -0.07713235f, 0.024805484f }, { -0.0034319194f, 0.0052741327f, 0.026402991f, 0.0012916612f }, { -0.033119652f, -0.0046506889f, 0.045613946f, -0.050230593f }, { -0.0054612035f, -0.033482221f, 0.084267507f, -0.0224334f }, { -0.0063348693f, -0.0074524817f, -0.0029629355f, 0.035493958f }, { -0.0073519185f, 0.045139911f, 0.0022901735f, -0.041385515f } } }, { { { 0.99640669f, 0.99424882f, 0.99911727f, 0.99864438f }, { 0.99146493f, 0.99235134f, 0.99369348f, 0.99764995f }, { 0.95848895f, 0.89778665f, 0.9720248f, 0.943828f }, { 0.95896077f, 0.9472107f, 0.83168251f, 0.89623886f }, { 0.97975356f, 0.94759472f, 0.99452924f, 0.98394744f }, { 0.98863213f, 0.99196902f, 0.99652121f, 0.97785007f }, { 0.99999362f, 0.99994883f, 0.99498061f, 0.99814861f }, { 0.99040248f, 0.99816269f, 0.99831309f, 0.99630173f }, { 0.99848953f, 0.99964658f, 0.9959596f, 0.99884607f }, { 0.9986735f, 0.99651874f, 0.99788899f, 0.99869411f }, { 0.91299789f, 0.85766372f, 0.953946f, 0.97631002f }, { 0.90471405f, 0.87481454f, 0.959534f, 0.97684726f }, { 0.9884254f, 0.96811612f, 0.9914694f, 0.98799879f }, { 0.99232241f, 0.98122887f, 0.99103524f, 0.99426948f }, { 0.99840731f, 0.99966074f, 0.99324506f, 0.98912879f }, { 0.99551377f, 0.99274778f, 0.99617307f, 0.9927827f }, { 0.99830144f, 0.99552039f, 0.99521214f, 0.99684577f }, { 0.99211525f, 0.9978808f, 0.99885333f, 0.99969634f }, { 0.95579147f, 0.95995838f, 0.84120087f, 0.96022443f }, { 0.90975235f, 0.9368621f, 0.81871367f, 0.8156339f }, { 0.98610091f, 0.99158952f, 0.96035822f, 0.97468107f }, { 0.98366238f, 0.9531543f, 0.99215501f, 0.98230604f }, { 0.99953301f, 0.9997136f, 0.99888998f, 0.99490315f }, { 0.99267663f, 0.998401f, 0.99388534f, 0.99721201f } }, { { -0.0021537732f, 0.010607958f, -0.0066166595f, -0.0027390442f }, { -0.0069401807f, 0.0053215201f, 0.0062121114f, 0.013403291f }, { -0.0035740125f, -0.021839368f, 0.00042431197f, -0.029478899f }, { -0.007886159f, -0.0087705321f, -0.010570968f, 0.0040635318f }, { -0.0021772698f, 0.00025306776f, -0.0092725896f, -0.0075657706f }, { -0.010438319f, -0.0072866821f, 0.009272756f, 0.0043932916f }, { -0.00058203184f, 0.0081284104f, 0.027749999f, 0.0035426599f }, { -0.003604276f, -0.012244348f, 0.0072177908f, 0.0026686264f }, { 0.011192179f, 0.0069527119f, 0.017278396f, -0.0053058312f }, { -0.020276487f, -0.0063228657f, 0.013968347f, -0.0021534789f }, { -0.0037534313f, 0.00061399133f, -0.02126817f, 0.0085256452f }, { 0.015620795f, -0.022637876f, 0.00069280338f, 0.0054369037f }, { 0.0095244184f, -0.0026896982f, -0.0057963534f, 0.0067237437f }, { -0.0085689961f, -0.004816024f, -0.00088793436f, -0.0034021999f }, { 0.015428153f, 0.019777562f, -0.011217833f, 0.0095744159f }, { -0.003802304f, 0.0022643577f, 0.0054254827f, 0.025560756f }, { -0.0053298651f, 0.021621993f, -0.01864184f, 0.019120967f }, { 0.015380344f, -0.0027384467f, 0.0010235928f, 0.0062792725f }, { -0.001166873f, -0.0049586656f, -0.014850883f, 0.00057841904f }, { 0.0032865456f, -0.033386196f, 0.0032068954f, 0.02854738f }, { 0.010308266f, -0.000233004f, -0.020287643f, 0.0044441043f }, { -0.0040523345f, 0.0050367711f, 0.01627907f, -0.010032412f }, { 0.0073463987f, 0.00073274858f, 0.002814661f, 0.030221018f }, { 0.0057509063f, -0.011441338f, 0.01894259f, 0.0077856453f } }, { { -0.0053054924f, 0.0037677068f, 0.0066263851f, 0.0011220287f }, { -0.02212139f, 0.013769097f, -0.0013834097f, 0.014152363f }, { -0.0008493126f, 0.021473024f, -0.0039313241f, -0.017764981f }, { -0.00081897848f, -0.0074161164f, 0.0038179092f, -0.0035760615f }, { 0.014045643f, 0.015317904f, 0.0045966739f, 0.0075917156f }, { 0.0035574126f, -0.00017773424f, -0.0010937491f, -0.0017762282f }, { 0.0072018344f, 0.012586227f, 0.0138702f, -0.0085424173f }, { -0.0055783456f, -0.019909385f, 0.01190919f, -0.0065821489f }, { 1.7402026e-05f, 0.0094513341f, 0.015333305f, -0.0072158969f }, { -0.0063049905f, 0.0021776758f, 0.014376378f, 0.0072426401f }, { -0.0078049673f, 0.028764242f, -0.0024169449f, 0.0077604105f }, { 0.00047536469f, 0.029806623f, 0.0017798261f, 0.00087410198f }, { -0.0030498401f, 0.0044874501f, 0.0020382571f, -0.0011101062f }, { -0.0057084397f, -0.0013428994f, -0.001024136f, 0.0066188614f }, { 0.039201052f, 0.015120258f, -0.0082642793f, 0.0051985023f }, { -0.0091203243f, 0.020790215f, 0.0025270937f, 0.020092044f }, { -0.0029830063f, 0.006602841f, -0.00833601f, 0.044852353f }, { 0.025206353f, -0.0038915173f, 0.00045914851f, 0.0037840538f }, { 0.0014814254f, -0.011573911f, 0.046232337f, -0.015228958f }, { -0.0071984443f, 0.0090004063f, 0.022942838f, 0.016019787f }, { 0.0050929336f, 0.0060892107f, -0.0061771339f, 0.0047850766f }, { -0.011634853f, 0.0010276548f, 0.022396644f, -0.0021248711f }, { -0.012943002f, 0.0016430074f, 0.02034928f, 0.024289705f }, { 0.0051047037f, 0.010052556f, 0.0020923265f, -0.019043181f } } }, { { { 2.1627647f, 2.1788232f, 1.9290264f, 1.8457806f }, { 2.526488f, 2.3020441f, 2.538915f, 2.03484f }, { 3.9987521f, 4.3952121f, 3.906821f, 4.1693278f }, { 4.0400466f, 4.1069844f, 5.2512999f, 5.4283264f }, { 3.0141968f, 3.3306035f, 3.2224806f, 3.2473051f }, { 2.9840674f, 3.1294685f, 3.2964833f, 3.2929246f }, { 1.8346741f, 1.8637353f, 2.3037966f, 2.0860888f }, { 2.691236f, 2.6068079f, 1.9349032f, 2.1632935f }, { 1.9231956f, 1.7251627f, 2.1609654f, 2.1155629f }, { 2.165771f, 2.1908952f, 1.777038f, 2.0223741f }, { 4.5166991f, 4.8674508f, 3.918546f, 3.378087f }, { 4.4502295f, 4.5429338f, 3.9552598f, 3.3580272f }, { 3.0973598f, 3.3953852f, 2.2704362f, 2.6488177f }, { 3.2110537f, 3.3104376f, 2.515002f, 2.3267785f }, { 1.8303675f, 1.7094345f, 3.1787979f, 2.5960104f }, { 2.4391795f, 2.8730077f, 2.3730261f, 2.1545299f }, { 2.2130903f, 2.1899209f, 2.4997355f, 1.9058674f }, { 2.6472893f, 2.5455636f, 2.1164596f, 1.8341163f }, { 3.9428283f, 4.0433678f, 4.5430063f, 4.2482776f }, { 4.1941673f, 4.28852f, 4.64044f, 4.6644567f }, { 3.0873642f, 2.649364f, 3.6026133f, 3.2426354f }, { 3.2415154f, 3.5406745f, 3.2976852f, 3.3100246f }, { 1.8400289f, 1.8404692f, 1.889289f, 2.0125184f }, { 2.7063995f, 2.7229173f, 2.6289878f, 2.4313709f } }, { { -0.015335928f, -0.043382119f, -0.0054163805f, -0.028249934f }, { -0.017200109f, 0.0027582413f, -0.079612821f, -0.0013966663f }, { -0.027233584f, -0.018783395f, -0.01183278f, -0.020918937f }, { -0.0036358348f, -0.015712206f, -0.0089146421f, -0.0057117233f }, { 0.020392865f, 0.017743746f, -0.068597326f, -0.030425581f }, { -0.041123673f, -0.020767538f, -0.0087941887f, -0.0065248183f }, { -0.0055478408f, -0.00082196865f, 0.0088521402f, -0.045916836f }, { -0.010506485f, 0.0078523247f, -0.030002306f, -0.0015085765f }, { 0.01894068f, -0.012424968f, -0.034837214f, -0.045009941f }, { -0.045299587f, 0.02630478f, -0.017175711f, -0.043601235f }, { -0.046003661f, -0.020588165f, 0.034398873f, -0.054653787f }, { -0.0042534368f, 0.01325834f, -0.0036369576f, -0.079162988f }, { -0.028728556f, 0.0051289128f, 0.012104313f, 0.010686997f }, { -0.066337767f, 0.00059928728f, -0.080303668f, 0.011318772f }, { -0.031879871f, 0.0011317962f, -0.050259029f, 0.0031596552f }, { -0.090121238f, -0.011196084f, -0.072456123f, -0.00079731072f }, { -0.024243475f, 0.021401076f, -0.018209385f, -0.0083196072f }, { -0.079888701f, 0.0032806631f, -0.12762259f, -0.04652308f }, { 0.031806075f, -0.034165157f, -0.015255921f, -0.049164663f }, { -0.0012051123f, 0.030788487f, 0.022291919f, 0.0025694519f }, { 0.035836509f, 0.0055365388f, 0.026704836f, 0.0001547235f }, { -0.012129747f, -0.0094322145f, -0.040637935f, -0.12125388f }, { -0.027044986f, 0.04531553f, -0.033484589f, -0.0059927923f }, { 0.0067188802f, -0.051166351f, -0.048822794f, -0.025926988f } }, { { 0.022049053f, 0.021265778f, -0.040370641f, -0.036232952f }, { -0.0058098424f, -0.0042264198f, -0.077428509f, -0.04241654f }, { -0.0026825379f, -0.029453318f, -0.016181275f, -0.028320229f }, { -0.012541692f, -0.01345735f, 0.00037814888f, -0.0046052489f }, { -0.026527394f, 0.020033638f, -0.025683861f, -0.084207169f }, { -0.0010459945f, -0.036745215f, -0.039772051f, 0.024810839f }, { 0.012134618f, 0.0068515798f, -0.035286972f, 0.043129595f }, { -0.077093357f, -0.026872688f, 0.032800133f, -0.090326706f }, { 0.13930909f, 0.0081274014f, -0.08349188f, -0.012200005f }, { -0.091693797f, -0.012567011f, -0.069736822f, -0.0061444184f }, { -0.053061301f, 0.003642159f, 0.0052515175f, -0.036957472f }, { 0.0043493933f, -0.013069332f, -0.014708126f, -0.032765039f }, { -0.016116105f, -0.022907609f, -0.043503106f, -0.013266465f }, { -0.072759977f, -0.077354585f, 0.0043827591f, -0.013821612f }, { -0.032399073f, -0.045305037f, -0.021840791f, 0.073996542f }, { -0.057239255f, -0.056581235f, -0.038880927f, 0.044102943f }, { -0.026951489f, -0.088667645f, -0.013659704f, 0.033527579f }, { 0.034815442f, -0.028634059f, -0.036666529f, 0.011546036f }, { 0.026688447f, -0.0081892129f, -0.031138092f, -0.041739155f }, { 0.0015665701f, -0.012701682f, 0.0013533943f, -0.002849785f }, { 0.032994636f, 0.008802974f, 0.019032649f, 0.0039042621f }, { -0.044544917f, 0.0093201326f, -0.017968915f, 0.01936344f }, { -0.034794535f, 0.043032983f, -0.051072531f, -0.040148303f }, { -0.0030398597f, -0.027112065f, -0.064007483f, -0.01798277f } } }, { { { 0.22040906f, 0.24911942f, 0.41660708f, 0.23632869f }, { 0.25894466f, 0.1416669f, 0.41902981f, 0.35717608f }, { 0.26918091f, 0.14566759f, 0.2147652f, 0.15769391f }, { 0.22500921f, 0.12113361f, 0.11151768f, 0.12348609f }, { 0.25699055f, 0.056819107f, 0.3859882f, 0.4585378f }, { 0.7304995f, 0.20719358f, 0.44455636f, 0.42226989f }, { 0.43602897f, 0.51049581f, 0.41978824f, 0.62521039f }, { 0.42004119f, 0.52912054f, 0.33314238f, 0.38257921f }, { 0.55092562f, 0.43085653f, 0.31149977f, 0.34391138f }, { 0.40391149f, 0.48820255f, 0.13569806f, 0.36060266f }, { 0.13647907f, 0.12061002f, 0.20668806f, 0.30221394f }, { 0.15583476f, 0.13133696f, 0.22775202f, 0.35653823f }, { 0.56336195f, 0.25684627f, 0.11118383f, 0.23109245f }, { 0.45430401f, 0.42843367f, 0.25496534f, 0.097473509f }, { 0.3420223f, 0.39418925f, 0.26458947f, 0.30588082f }, { 0.51345558f, 0.3612731f, 0.41151773f, 0.25269512f }, { 0.29195176f, 0.42659964f, 0.47971993f, 0.32714756f }, { 0.49222777f, 0.28477645f, 0.74993827f, 0.43781271f }, { 0.098434481f, 0.31164923f, 0.14486345f, 0.11466693f }, { 0.070833248f, 0.20569754f, 0.10233576f, 0.047352701f }, { 0.51050902f, 0.15597643f, 0.1417112f, 0.35581415f }, { 0.48261165f, 0.14592221f, 0.62554576f, 0.5209765f }, { 0.33562628f, 0.39920067f, 0.28183433f, 0.297464f }, { 0.366851f, 0.59278666f, 0.59095922f, 0.48385165f } }, { { 0.13792051f, 0.072076744f, 0.094800532f, 0.026318377f }, { 0.13607414f, -0.061382542f, 0.061800151f, -0.020060553f }, { 0.028096406f, 0.069282616f, 0.010195109f, -0.010461141f }, { 0.018651237f, 0.02642439f, 0.0077552848f, -0.051151646f }, { 0.098299803f, -0.0085081153f, -0.011764584f, 0.087405711f }, { 0.064082346f, -0.04626424f, -0.071480607f, 0.064447268f }, { 0.022766233f, 0.0167542f, -0.021285286f, -0.071637286f }, { -0.0202445f, 0.011692601f, 0.048325551f, 0.0097755172f }, { -0.027775183f, 0.016463115f, 0.060050391f, -0.034226107f }, { 0.019412547f, 0.059977501f, -0.0041737169f, 0.031539317f }, { 0.013192979f, 0.036015595f, -0.049943198f, 0.014112312f }, { -0.013272349f, 0.035821037f, -0.060503687f, 0.095316821f }, { 0.038338785f, -0.059038809f, -0.044954172f, -0.00051347307f }, { -0.039594082f, 0.018205882f, 0.13413799f, 0.012292954f }, { 0.015177594f, -0.0082493854f, 0.00029420179f, 0.010356248f }, { 0.100271f, -0.13623174f, 0.1121235f, 0.068902399f }, { 0.025189636f, 0.0014918434f, 0.0088847718f, -0.053714493f }, { 0.06487698f, -0.097217547f, -0.069537353f, 0.032490984f }, { -0.030729608f, 0.048956315f, 0.016036034f, 0.022485239f }, { 0.049839618f, 0.01148525f, -0.021032427f, -0.019665817f }, { -0.0037762817f, -0.030422275f, -0.062343207f, 0.057994884f }, { 0.014035184f, -0.021387762f, -0.080846143f, -0.020681511f }, { -0.03594567f, 0.026862531f, 0.078975557f, -0.034056659f }, { -0.014490672f, 0.026128902f, 0.045617611f, 0.090192953f } }, { { 0.011904288f, -0.014624471f, 0.042023114f, 0.019592867f }, { 0.032705848f, 0.00038558691f, 0.031901745f, 0.027208951f }, { -0.044369719f, -0.039761364f, -0.013366816f, -0.019308126f }, { -0.019051023f, -0.00015767269f, -0.082968285f, -0.035266053f }, { -0.004775162f, 0.010889271f, 0.0089521094f, 0.027037104f }, { 0.005616143f, -0.00099668486f, 0.0068716426f, -0.12649184f }, { 0.018531199f, 0.023881776f, -0.053798787f, -0.041912909f }, { -0.0036187094f, 0.11590788f, 0.025140733f, 0.022280209f }, { -0.02994342f, -0.026293799f, -0.017204658f, 0.044901944f }, { 0.079892089f, 0.10816526f, 0.14667807f, 0.027301352f }, { -0.045296738f, -0.066748968f, -0.0099354431f, -0.070369692f }, { -0.08357374f, -0.043311901f, 0.013163375f, -0.0881777f }, { -0.065923811f, -0.10382274f, 0.090440302f, -0.013617198f }, { -0.092578587f, -0.010178017f, -0.01416593f, 0.0432333f }, { 0.055172515f, 0.10021805f, -0.0062782668f, -0.11791805f }, { -0.039684132f, -0.08934283f, 0.020686084f, -0.0013788117f }, { 0.064624676f, 0.051773746f, 0.0045383964f, -0.037696971f }, { -0.066296373f, 0.020570689f, -0.017742721f, -0.022651449f }, { -0.0061572447f, -0.094510525f, -0.094775804f, -0.038022514f }, { 0.0055683313f, 0.039513342f, -0.096815654f, -0.0065483011f }, { -0.03311602f, -0.018395457f, 0.0028464434f, -0.088048272f }, { -0.073106109f, -0.055187863f, -0.093209932f, -0.10155137f }, { 0.042841842f, -0.005778703f, 0.074069607f, -0.025841052f }, { -0.018569637f, 0.063144303f, 0.02291584f, 0.005525742f } } } }, { { { { -0.20809663f, -0.18346453f, -0.072140694f, -0.0078104407f }, { -0.19490097f, 0.25712922f, 0.37640771f, 0.11563399f }, { 0.26894915f, -0.33477877f, -0.093739129f, -0.55078405f }, { -0.65794103f, 0.09211629f, -0.19166986f, 0.5574327f }, { 0.45579532f, 0.23202083f, 0.19626303f, -0.64130523f }, { -0.018763975f, -0.24981569f, -0.32514026f, -0.11121342f }, { 0.22376238f, 0.09515938f, 0.071728264f, -0.02790747f }, { -0.3053338f, 0.34023365f, 0.099862481f, 0.26163964f }, { -0.21722968f, -0.094881958f, -0.086364431f, -0.0081863581f }, { -0.16090709f, 0.23527698f, 0.28947119f, 0.11309742f }, { 0.26447184f, -0.33536416f, -0.096418234f, -0.26201294f }, { -0.56343769f, -0.041662822f, -0.24873841f, 0.67122901f }, { 0.35362642f, 0.2577592f, 0.2009013f, -0.74233681f }, { -0.047956299f, -0.54973418f, -0.4958485f, -0.12453303f }, { 0.06917425f, 0.080509853f, 0.0090863722f, -0.023518805f }, { -0.27000602f, 0.083167162f, 0.12715558f, 0.12397839f }, { -0.11376964f, -0.079199259f, 0.019676685f, -0.0094352472f }, { -0.19185851f, 0.22193112f, 0.28110877f, -0.06422845f }, { 0.084091992f, -0.16151548f, 0.091400556f, -0.28257376f }, { -0.53821376f, 0.21718328f, -0.2234907f, 0.52302804f }, { 0.71322306f, 0.042728493f, 0.13229522f, -0.61892094f }, { 0.15270046f, -0.26304886f, -0.33110633f, -0.052728951f }, { 0.072398971f, 0.25829764f, 0.25881687f, -0.020942042f }, { -0.26788161f, 0.055822039f, 0.33817103f, 0.42061402f } }, { { 0.088248648f, 0.091306255f, 0.020476927f, 0.0030144802f }, { 0.0087376707f, 0.043816157f, 0.0022807168f, 0.016745414f }, { -0.13412414f, 0.12686539f, 0.060531476f, 0.044582027f }, { 0.019204757f, -0.0070891897f, 0.091194602f, 0.065258927f }, { -0.10429513f, -0.027665602f, -0.064350626f, 0.0053147478f }, { 0.069218141f, -0.035018324f, -0.088257571f, 0.019279642f }, { -0.073137338f, 0.040764456f, -0.022352804f, 0.031743288f }, { 0.040325697f, -0.12840825f, -0.009582113f, 0.034509657f }, { 0.081971224f, -0.0035223125f, -0.051728499f, 0.0038899717f }, { 0.050968435f, 0.022254651f, 0.18781134f, -0.032392139f }, { 0.024342518f, 0.13929014f, -0.019175435f, -0.0011608234f }, { -0.0021942487f, -0.01251222f, 0.024263454f, -0.063179344f }, { -0.13071776f, -0.059221747f, -0.034153238f, 0.036561209f }, { 0.054124093f, 0.070495803f, 0.081441614f, 0.051900357f }, { 0.027480327f, 0.028940343f, -0.01469313f, 0.032388411f }, { -0.039696828f, -0.0069393798f, -0.011361641f, 0.035031025f }, { -0.039730763f, 0.0085971581f, -0.0077461932f, -0.040735188f }, { 0.10893368f, 0.00014757217f, 0.025489178f, -0.11388774f }, { -0.0013816669f, 0.0031148929f, 0.10281666f, -0.019860642f }, { -0.065093128f, -0.11495815f, 0.041783056f, -0.091373461f }, { -0.044985581f, 0.0012713031f, -0.16078032f, 0.17303747f }, { -0.038132358f, -0.02995975f, -0.037612782f, 0.012575173f }, { 0.0042976619f, 0.027014275f, 0.017518808f, 0.030405184f }, { -0.0015298607f, 0.029297664f, -0.1034349f, 0.023450502f } }, { { 0.028785558f, -0.028708377f, -0.010459636f, 2.8360915e-05f }, { 0.091634877f, 0.021214811f, 0.12282079f, 0.080617943f }, { -0.29287977f, 0.045481846f, 0.014712563f, 0.057317576f }, { -0.10728772f, 0.03268482f, 0.015167285f, -0.011256231f }, { 0.09337321f, 0.037150859f, 0.052549202f, -0.042671474f }, { -0.0041288689f, -0.024299997f, -0.11357403f, -0.022045772f }, { -0.041469935f, -0.0071353646f, -0.0086607538f, 0.008536762f }, { 0.033629272f, -0.0070042955f, -0.037864853f, -0.0055907778f }, { 0.016404597f, -0.0055321059f, -0.020989839f, -0.013771265f }, { 0.042552435f, 0.04428518f, 0.0030587466f, 0.044894182f }, { -0.027600219f, 0.026831779f, 0.051120849f, -0.032184808f }, { 0.13870554f, 0.15273282f, 0.049260112f, 0.043371121f }, { -0.018453269f, -0.18061413f, 0.24805649f, -0.031741165f }, { -0.085137374f, 0.025935867f, 0.015978067f, 0.067726486f }, { 0.072393868f, 0.0050430488f, 0.0016664585f, 0.0072097064f }, { 0.033840162f, 0.082225764f, -0.079387016f, 0.033165625f }, { 0.033170766f, 0.0012231618f, -0.066984982f, 0.051671704f }, { 0.017894231f, -0.012267532f, 0.045536123f, -0.07327109f }, { 0.0073109731f, -0.063797898f, -0.13446413f, 0.1408986f }, { -0.045702456f, -0.1647051f, -0.14336468f, 0.054543693f }, { 0.0042448876f, -0.13234456f, 0.092181719f, -0.10440841f }, { -0.060020212f, -0.011098469f, -0.030257182f, -0.030922037f }, { -0.018118661f, 0.00067983745f, -0.0061776598f, -0.031721273f }, { -0.019885189f, 0.094157888f, 0.014017961f, -0.051373389f } } }, { { { 0.12415319f, -0.13611564f, -0.029441661f, -0.14143497f }, { -0.26074418f, 0.011913326f, -0.033328425f, 0.43248793f }, { 0.19336432f, 0.37269586f, 0.36803538f, -0.51720719f }, { -0.15185913f, -0.47431781f, -0.6593667f, 0.23163184f }, { 0.18276216f, 0.19248743f, 0.65453332f, 0.54748087f }, { 0.17751443f, -0.0020337696f, 0.08506463f, -0.40147769f }, { -0.11370932f, 0.11523476f, -0.010573025f, 0.082295392f }, { -0.13666335f, -0.32747478f, -0.16897386f, 0.15359006f }, { 0.11716326f, -0.12259922f, 0.0033396256f, -0.13240653f }, { -0.27776876f, -0.10222241f, -0.039920479f, 0.35499708f }, { 0.090003723f, 0.3313923f, 0.1871549f, 0.003163675f }, { -0.51626118f, -0.76341562f, -0.56326874f, 0.20153559f }, { -0.34172723f, 0.26975563f, 0.67520079f, -0.1252004f }, { 0.45758078f, -0.19142179f, 0.064180031f, -0.48748431f }, { -0.12800789f, 0.1399912f, 0.0077954775f, 0.14379741f }, { -0.13042104f, -0.45670817f, -0.18831095f, 0.0032738639f }, { 0.12446807f, -0.11504524f, -0.027331682f, 0.03861758f }, { -0.31337986f, -0.11842668f, 0.033415325f, 0.45344231f }, { 0.11463107f, 0.077427841f, 0.060880794f, -0.069619455f }, { -0.37772106f, -0.59628905f, -0.65426572f, 0.065297039f }, { 0.29532991f, 0.75920243f, 0.53294265f, -0.15002562f }, { 0.3618333f, 0.10488387f, 0.36007528f, -0.30963565f }, { -0.13738196f, 0.20795596f, 0.029274703f, 0.18017599f }, { -0.10290023f, -0.48517535f, -0.33278584f, 0.56477854f } }, { { -0.0047891472f, 0.024629901f, 0.015256654f, -0.0084462001f }, { 0.056227746f, -0.048057782f, -0.15671312f, 0.06418471f }, { -0.070093217f, -0.018057199f, 0.062026545f, -0.051053726f }, { -0.0091221476f, 0.0020547295f, -0.087729813f, -0.10164738f }, { 0.098917091f, -0.066835916f, 0.083151519f, 0.006342544f }, { 0.0013540606f, 0.038719082f, 0.036333261f, -0.053178668f }, { 0.0083787438f, 0.0028359378f, 0.0089872852f, 0.031308249f }, { 0.014379686f, -0.079563474f, -0.079160006f, -0.016352226f }, { 0.0091376645f, -0.016678006f, -0.044636785f, -0.0011035265f }, { 0.0099146109f, 0.027589302f, -0.09494437f, 0.07451767f }, { 0.017453983f, 0.080674871f, 0.06341808f, 0.048820473f }, { 0.02794057f, 0.058230195f, -0.010793601f, 0.091813872f }, { -0.049633232f, -0.1142016f, 0.036984283f, 0.0034294865f }, { 0.047712957f, 0.10161366f, 0.13774722f, 0.039503136f }, { 0.014194782f, -0.014555183f, -0.00053182909f, 0.0019143477f }, { 0.0014900262f, 0.0056176356f, -0.034517871f, -0.0010707988f }, { 0.013287784f, -0.0073967933f, -0.019271341f, 0.016354896f }, { -0.10345626f, 0.023536634f, 0.027943639f, -0.015686972f }, { -0.025193395f, -0.10224801f, 0.078686884f, -0.048574399f }, { 0.15797878f, -0.0012322757f, -0.036096649f, -0.23983963f }, { -0.10455507f, -0.056368102f, -0.06570944f, 0.29104616f }, { 0.05155239f, -0.040940824f, -0.038367594f, 0.058174485f }, { 0.010471732f, -0.066952904f, -0.047763843f, -0.021124742f }, { -0.033555686f, 0.0049111983f, -0.026592789f, 0.014438586f } }, { { -0.0048440946f, 0.025915095f, -0.018325403f, 0.022133613f }, { 0.059240081f, -0.031272176f, -0.12967647f, -0.17957913f }, { 0.0574837f, 0.067005152f, 0.024644254f, 0.10786296f }, { 0.067084865f, 0.008513386f, 0.04077659f, 0.10587924f }, { 0.026332643f, 0.1072618f, -0.098375042f, -0.001724609f }, { -0.021386362f, -0.0020174921f, 0.16800158f, 0.081359882f }, { -0.018204146f, -0.026432136f, -0.0068153455f, -0.029997667f }, { -0.043221501f, -0.016869967f, -0.067406967f, -0.024965804f }, { -0.0033879999f, 0.031310818f, -0.010853802f, 0.00088944004f }, { -0.068991006f, 0.087874253f, -0.15737392f, -0.088870044f }, { 0.061763806f, -0.00072874343f, -0.009915009f, -0.0178225f }, { -0.07340717f, 0.080339271f, -0.0027124572f, -0.13078641f }, { -0.023682834f, 0.16512313f, -0.15784472f, 0.047978827f }, { 0.0063250439f, -0.09953777f, 0.094180888f, 0.010565041f }, { 0.010047311f, -0.042999009f, -0.012483998f, -0.016966759f }, { -0.048612679f, 0.051708319f, 0.015059148f, 0.0036776472f }, { -0.011737015f, -0.0027276603f, 0.026535075f, -0.065453876f }, { 0.056388137f, 0.061461073f, -0.12726984f, -0.025578248f }, { 0.0016833003f, 0.10878558f, 0.13254828f, -0.017098914f }, { -0.031606282f, -0.072245098f, 0.12724789f, -0.21852899f }, { -0.062502612f, -0.073402771f, -0.049624729f, 0.069066032f }, { -0.075837195f, -0.10297347f, -0.07249237f, -0.11538062f }, { -0.015644005f, 0.039474396f, 0.074415075f, -0.038881161f }, { -0.040175911f, 0.034030267f, 0.03947059f, 0.014167463f } } }, { { { 0.97019677f, 0.97355703f, 0.99695983f, 0.98991674f }, { 0.94552952f, 0.96630359f, 0.92585444f, 0.89419404f }, { 0.9435447f, 0.86545998f, 0.92507456f, 0.65508294f }, { 0.73759908f, 0.87552111f, 0.72697883f, 0.79725496f }, { 0.87111918f, 0.95347518f, 0.73011435f, 0.53758004f }, { 0.9839393f, 0.96829127f, 0.94183216f, 0.90909143f }, { 0.96798791f, 0.98876976f, 0.99736817f, 0.99621717f }, { 0.9423876f, 0.88147679f, 0.98054848f, 0.95286662f }, { 0.96906348f, 0.98791034f, 0.99625801f, 0.99116169f }, { 0.94707625f, 0.9665378f, 0.9563539f, 0.9280011f }, { 0.96018435f, 0.88187869f, 0.97758711f, 0.96505917f }, { 0.64499021f, 0.64456248f, 0.78794513f, 0.71332673f }, { 0.87073007f, 0.92778882f, 0.70974824f, 0.65822558f }, { 0.88787388f, 0.81311133f, 0.86603417f, 0.86420517f }, { 0.98935782f, 0.98687417f, 0.99992833f, 0.98932764f }, { 0.95398485f, 0.88572054f, 0.97384313f, 0.99227952f }, { 0.98567955f, 0.99019799f, 0.99943274f, 0.99920952f }, { 0.93004482f, 0.96784384f, 0.95909399f, 0.88896838f }, { 0.98984254f, 0.98382807f, 0.99395144f, 0.95671584f }, { 0.75342733f, 0.77283296f, 0.72248756f, 0.84981055f }, { 0.63568318f, 0.6494505f, 0.83574524f, 0.77099234f }, { 0.91965169f, 0.95906448f, 0.87218942f, 0.94939213f }, { 0.98786871f, 0.94341754f, 0.96548269f, 0.98341143f }, { 0.95794101f, 0.87263324f, 0.8802806f, 0.71000638f } }, { { -0.0064390277f, 0.051629953f, -0.011423447f, 0.032337826f }, { 0.055030538f, 0.061305324f, -0.016012659f, 0.083766345f }, { 0.052467122f, 0.018425134f, -0.00054737782f, 0.048038459f }, { 0.076436505f, 0.016815709f, -0.024174832f, -0.00829119f }, { 0.057903371f, 0.068822104f, -0.0064003131f, 0.00010695928f }, { 0.067104151f, 0.067284611f, 0.0074295447f, 0.024215238f }, { 0.073380541f, 0.01486405f, 0.01523157f, 0.012966612f }, { -0.0002536971f, 0.010628632f, 0.00045031869f, 0.041891438f }, { 0.055922922f, 0.0090823157f, 0.011101162f, 0.033807592f }, { -0.040264953f, 0.022318628f, -0.013682045f, -0.016112502f }, { -0.034286564f, 4.7089727e-05f, -0.013030079f, -0.012231424f }, { 0.027756308f, 0.084041595f, 0.018308393f, 0.11564334f }, { 0.0026690817f, 0.058149333f, -0.013682964f, 0.052975934f }, { -0.03852481f, 0.063493354f, 0.059460027f, 0.047740976f }, { 0.026410264f, -0.0073902435f, 0.022353771f, 0.012987341f }, { 0.035217135f, -0.0023455309f, -0.0055505614f, 0.010102857f }, { 0.00075590283f, 0.038624793f, -0.0040614962f, 0.070039437f }, { -0.02318411f, 0.04527054f, 0.013119286f, 0.025335215f }, { 0.021268391f, 0.044855911f, 0.012622905f, 0.04827088f }, { -0.0046678346f, -0.01934799f, 0.018393432f, 0.09750434f }, { 0.12480373f, 0.059151139f, 0.055196092f, 0.26701338f }, { -0.0096669036f, 0.065624767f, 0.016918517f, 0.028425135f }, { 0.026488514f, -0.0037618693f, 0.0077028717f, 0.041713399f }, { 0.018628451f, 0.033145064f, 0.029067918f, -0.000924258f } }, { { -0.043525781f, 0.028119778f, -0.011653105f, -0.020930158f }, { -0.028099186f, 0.017594088f, -0.099226445f, 0.10408808f }, { 0.11750066f, -0.0010629746f, 0.018381448f, 0.096538552f }, { 0.0010069446f, 0.013799541f, 0.1325137f, 0.020820734f }, { -0.053571928f, -0.0066793785f, 0.14596488f, -0.03272949f }, { 0.028507895f, 0.015474376f, -0.025411653f, 0.037264272f }, { 0.033698911f, 0.018088387f, 0.0038898537f, 0.03163178f }, { 0.0057766828f, 0.015879322f, 0.012557033f, 0.071771631f }, { -0.0044521866f, 0.0083963511f, -0.0020426175f, 0.023784146f }, { -0.011508765f, 0.0075020051f, 0.0018808294f, 0.040843424f }, { 0.0085150894f, 0.0056891711f, 0.010134672f, 0.046224768f }, { 0.040825446f, 0.10099754f, 0.021853299f, 0.024507528f }, { -0.0055958303f, -0.0060958f, 0.1115321f, -0.021701014f }, { 0.010487817f, -0.010033143f, -0.031203025f, 0.054265436f }, { 0.0040500672f, 0.0053935875f, 0.018233022f, 0.018797311f }, { 0.064057639f, 0.014318185f, 0.0199119f, 0.014366235f }, { 0.02411682f, 0.045454692f, 0.0030084434f, 0.019464939f }, { 0.012500289f, 0.027734846f, 0.0025097372f, 0.047343669f }, { 0.037625829f, -0.00064472688f, 0.0557556f, 0.04785655f }, { 0.0020433437f, 0.019929208f, 0.087936103f, -0.036738471f }, { 0.020811556f, 0.0915387f, 0.055445303f, -0.065132763f }, { 0.03911814f, 0.043721622f, 0.0074336204f, -0.031370424f }, { 0.014072509f, -0.014795458f, 0.010517063f, 0.022409628f }, { -0.0054107234f, 0.055313602f, 0.053556404f, 0.048574319f } } }, { { { 3.4224197f, 3.3162336f, 3.1136621f, 3.3189801f }, { 4.0715355f, 3.5614196f, 4.1797877f, 4.0959601f }, { 4.3979407f, 4.1858272f, 4.3116447f, 4.5467451f }, { 4.4920032f, 4.0716439f, 4.6107962f, 4.5268016f }, { 5.6570832f, 4.9036495f, 4.7373547f, 4.7259419f }, { 3.3277827f, 3.6015237f, 4.226646f, 3.7939772f }, { 3.4893058f, 3.3260638f, 3.0626103f, 3.1798705f }, { 3.6423735f, 4.1092281f, 3.3264203f, 3.7325301f }, { 3.4756581f, 3.2550256f, 3.224671f, 3.4093307f }, { 3.8511362f, 3.4821381f, 4.3232597f, 3.7357164f }, { 3.6688024f, 4.0797971f, 3.4140927f, 3.6881261f }, { 4.5298469f, 4.7472506f, 4.4046473f, 4.7279944f }, { 4.1614448f, 4.1242955f, 4.6741969f, 5.0037875f }, { 4.3148703f, 4.3815566f, 4.1976536f, 3.9032858f }, { 3.2640506f, 3.3214728f, 2.9463564f, 3.3562068f }, { 3.6729325f, 3.9218642f, 3.4550701f, 3.4833871f }, { 3.435975f, 3.3079446f, 3.3432341f, 3.3632985f }, { 3.8404619f, 3.4716915f, 3.858149f, 3.8677391f }, { 3.3181827f, 3.8403872f, 4.0363918f, 3.9604287f }, { 5.0916792f, 5.2773748f, 4.5404255f, 4.377031f }, { 4.6514614f, 4.7569957f, 4.1233238f, 4.4022582f }, { 3.6884833f, 3.6283543f, 4.1874612f, 4.2963913f }, { 3.456705f, 3.6250566f, 3.5292789f, 3.1420033f }, { 3.5986317f, 4.0596074f, 4.0696874f, 4.5327067f } }, { { -0.12592901f, -0.14780788f, -0.11051274f, -0.18767653f }, { -0.020435093f, 0.0055221209f, -0.021183195f, -0.15159792f }, { 0.022498629f, -0.025100789f, -0.30939177f, 0.016420202f }, { 0.21296442f, -0.042976575f, 0.082118132f, 0.14574735f }, { -0.13608022f, 0.16141834f, -0.015091164f, 0.044951541f }, { -0.08235774f, -0.10333151f, 0.089785432f, -0.036620639f }, { -0.17664465f, -0.015842477f, -0.083075331f, -0.15660828f }, { -0.11292423f, -0.072894494f, -0.068901923f, -0.2283674f }, { -0.19063437f, -0.071954393f, 0.091375283f, -0.26993547f }, { 0.042798331f, -0.06495575f, 0.050221766f, 0.024602586f }, { -0.026228614f, 0.0049810367f, 0.046584088f, -0.13067577f }, { 0.072779737f, -0.023369437f, -0.030275791f, 0.19591126f }, { -0.018649072f, 0.029208952f, 0.012033439f, 0.00094798196f }, { -0.094599446f, 0.0070746366f, -0.0007115864f, -0.040175552f }, { -0.027599009f, -0.068747365f, 0.19480498f, -0.19423733f }, { -0.076671551f, 0.0075475135f, 0.019853903f, -0.012984601f }, { 0.064371855f, -0.24044027f, -0.043765356f, 0.0016424127f }, { -0.076744435f, 0.035881398f, 0.12967612f, 0.081825243f }, { -0.15224256f, 0.032665115f, -0.027927205f, 0.076091133f }, { -0.0057973613f, -0.14914213f, -0.047678749f, -0.037214457f }, { 0.10060085f, -0.099197666f, -0.22704457f, -0.0020812401f }, { -0.070664558f, -0.13179176f, -0.014217065f, -0.030410253f }, { -0.12286487f, -0.046623366f, -0.10695394f, -0.0081383175f }, { -0.14561788f, 0.02765909f, 0.10439783f, 0.033139041f } }, { { 0.0063171031f, -0.0047223477f, -0.056312039f, -0.065065766f }, { -0.0059575982f, -0.062348475f, 0.069540315f, -0.090331962f }, { 0.10218203f, 0.050383376f, -0.0089914697f, -0.037837343f }, { -0.0037657879f, 0.18278082f, 0.079014627f, -0.052587294f }, { -0.33929282f, 0.018522098f, 0.0078923893f, 0.042545349f }, { 0.027294929f, -0.086490439f, -0.0057363347f, -0.035932082f }, { -0.061716003f, -0.14470599f, 0.033117786f, -0.08112808f }, { 0.16414856f, 0.082471596f, -0.058497326f, 0.050552718f }, { -0.07627083f, -0.0064181717f, -0.031179581f, -0.075705068f }, { -0.057808009f, -0.00074561624f, -0.23990956f, 0.018671772f }, { 0.1677602f, 0.10757253f, 0.028015134f, -0.23923178f }, { 0.078827365f, 0.068682485f, 0.056277532f, -0.069749241f }, { 0.079502977f, 0.05526585f, 0.0089767144f, -0.15319341f }, { -0.038594242f, -0.055488998f, -0.043132461f, 0.054313031f }, { 0.12890592f, -0.082639555f, 0.22520491f, -0.026781096f }, { -0.071292391f, 0.064592881f, -0.050368563f, -0.072488866f }, { 0.092998671f, 0.12152394f, 0.033318795f, -0.039691417f }, { -0.0049706273f, -0.0014175115f, -0.11634604f, 0.15219284f }, { -0.012414906f, 0.035583927f, -0.072463074f, -0.058394705f }, { -0.071558898f, -0.00093653835f, 0.013149622f, 0.01495775f }, { -0.057103279f, 0.013702583f, -0.020242751f, 0.04649072f }, { -0.083398977f, -0.20123674f, 0.062758815f, -0.043671819f }, { 0.084479675f, 0.17868517f, -0.021185269f, 0.15711776f }, { 0.11862504f, 0.079985297f, 0.063556911f, 0.14639069f } } }, { { { 0.48018566f, 0.17712962f, 0.45065949f, 0.76214707f }, { 0.37788335f, 0.385421f, 0.24766167f, 0.3647243f }, { 0.45095873f, 0.2634498f, 0.37824131f, 0.10713483f }, { 0.18808611f, 0.27852978f, 0.23671202f, 0.23174978f }, { 0.39404781f, -0.7399413f, 0.28511918f, 0.026007027f }, { 0.46587668f, 0.46802177f, 0.36697974f, 0.23706778f }, { 0.48925391f, 0.42086488f, 0.49570155f, 0.45137287f }, { 0.30655255f, 0.35196398f, 0.23019387f, 0.50586011f }, { 0.45798975f, 0.34137244f, 0.33289763f, 0.54218519f }, { 0.42271216f, 0.38700914f, 0.48791862f, 0.15025833f }, { 0.7282781f, 0.37956244f, 0.25156645f, 0.51632504f }, { 0.084933462f, 0.15576738f, 0.16469359f, 0.29684651f }, { 0.34570877f, 0.34912791f, 0.26663435f, 0.11188061f }, { 0.48552914f, 0.19012867f, 0.12677402f, 0.1234341f }, { 0.2190939f, 0.41431469f, 0.64823269f, 0.51846746f }, { 0.49289149f, 0.29829354f, 0.29090992f, 0.36465152f }, { 0.50568056f, 0.64150077f, 0.40217634f, 0.53523743f }, { 0.24945735f, 0.47058801f, 0.29099852f, 0.25452114f }, { 0.49039753f, 0.26327736f, 0.39431507f, 0.50632023f }, { 0.19678915f, 0.031547614f, 0.22295107f, 0.26300048f }, { 0.12409997f, 0.11506147f, 0.19327618f, 0.2174585f }, { 0.15319333f, 0.39177705f, 0.38498586f, 0.25972804f }, { 0.69027161f, 0.37279682f, 0.31143504f, 0.23440833f }, { 0.39682066f, 0.3156927f, 0.36369313f, 0.14308402f } }, { { 0.15030994f, 0.15410005f, 0.0072554408f, -0.22242826f }, { -0.032421729f, 0.22531436f, 0.22185899f, -0.022703209f }, { 0.070341052f, 0.30237173f, 0.047916387f, 0.03629681f }, { -0.024283222f, 0.075614195f, 0.013940033f, -0.016841468f }, { 0.077729482f, 0.19455394f, -0.02162282f, -0.018761003f }, { -0.22986895f, 0.18914992f, 0.14483608f, 0.11173921f }, { 0.14132894f, -0.0081864768f, -0.11405791f, 0.031777789f }, { 0.38775389f, 0.0085565642f, -0.057167843f, 0.09784167f }, { 0.079102739f, 0.030530894f, 0.041954967f, 0.02957611f }, { 0.076915126f, 0.18656729f, 0.044218872f, 0.22478833f }, { 0.017173879f, 0.11961351f, -0.085099523f, 0.22720323f }, { 0.030466202f, 0.095221887f, -0.042982583f, -0.069264747f }, { 0.041170442f, -0.090598444f, -0.021082598f, -0.028016784f }, { -0.082581617f, -0.023712106f, 0.32427665f, 0.1010696f }, { 0.19197752f, 0.10900527f, -0.0053794951f, 0.068553764f }, { 0.18674269f, 0.028895321f, -0.053421028f, 0.063918058f }, { 0.044090722f, -0.054247791f, 0.05585954f, -0.13406746f }, { 0.08358642f, -0.032301886f, 0.010371619f, 0.099505528f }, { 0.16467816f, 0.044994571f, -0.0045949279f, 0.0626774f }, { 0.12942209f, 0.092097891f, 0.019866495f, 0.10340014f }, { 0.037094903f, 0.13829877f, 0.15116473f, -0.048632499f }, { 0.10749044f, 0.14329542f, -0.061272024f, -0.1536028f }, { 0.097716907f, 0.044246181f, 0.056664419f, 0.15804873f }, { 0.031819999f, 0.10132976f, 0.079198524f, 0.017871462f } }, { { 0.056219172f, 0.08683492f, -0.061488015f, 0.065746152f }, { 0.088983664f, 0.19773741f, -0.096766599f, 0.16352101f }, { -0.0097043787f, -0.040925999f, 0.097458334f, 0.032319634f }, { -0.024873518f, 0.057873123f, -0.0059256291f, -0.057498398f }, { -0.13355098f, 0.39190863f, 0.017449142f, -0.0076009344f }, { 0.10319658f, 0.22069551f, -0.098795717f, 0.10603434f }, { 0.090765308f, 0.13803326f, -0.070647945f, 0.14557561f }, { -0.068457348f, 0.058955208f, -0.050501105f, 0.02914144f }, { 0.10363866f, 0.060231993f, 0.027681685f, 0.079659088f }, { 0.01269983f, 0.11977996f, -0.049648315f, 0.089882363f }, { -0.072877286f, 0.019348792f, 0.13977764f, 0.055396044f }, { 0.028834456f, -0.1084196f, -0.0043985215f, -0.072640844f }, { -0.040232522f, 0.051835989f, -0.02198193f, 0.016421295f }, { -0.087848469f, -0.04621504f, 0.099259188f, -0.0025909067f }, { 0.3000131f, 0.10526775f, 0.016890366f, 0.12892588f }, { -0.021028821f, -0.024429075f, 0.088067677f, -0.084594075f }, { 0.086861805f, -0.045902006f, 0.0058222123f, -0.0075466204f }, { 0.14411905f, 0.036488937f, 0.05091815f, 0.16385101f }, { 0.1576814f, 0.043890956f, -0.064244298f, -0.087234754f }, { -0.071100004f, 0.16782304f, -0.10860149f, -0.1601076f }, { 0.032634641f, -0.0025068263f, -0.093802703f, -0.076176546f }, { 0.1121451f, 0.15584236f, 0.070074778f, 0.083736091f }, { 0.16981897f, -0.078106227f, 0.12480295f, -0.0056807652f }, { -0.20300117f, -0.017467249f, 0.035504155f, 0.056546123f } } } }, { { { { 0.014994926f, 0.3118252f, 0.12179235f, -0.2013765f }, { -0.2622824f, 0.28086607f, 0.018805882f, 0.72058929f }, { -0.0081002049f, -0.28176506f, -0.592214f, -0.15032918f }, { 0.18913426f, -0.24000825f, 0.0020279072f, -0.54749128f }, { 0.010237954f, 0.76905205f, 0.80173664f, -0.016024595f }, { -0.53448318f, 0.31204229f, -0.16183732f, 0.76857439f }, { -0.57639279f, -0.63719194f, -0.71354849f, 0.56346054f }, { 0.49443258f, 0.15067585f, 0.31864726f, -0.30570933f }, { -0.20756322f, 0.2544828f, -0.005298245f, 0.0073796841f }, { -0.61822672f, 0.21508574f, 0.6362534f, 0.30433278f }, { -0.0050327191f, -0.278054f, -0.3460806f, 0.29967778f }, { 0.33983098f, -0.11715664f, -0.21761592f, -0.068273894f }, { 0.5550354f, 0.44369709f, 0.64019993f, -0.026032291f }, { -0.72587268f, -0.33528197f, -0.33592445f, 0.53027141f }, { -0.47623191f, -0.61767624f, -0.61525655f, 0.37823554f }, { 0.82869964f, 0.219401f, -0.018181789f, -0.56937955f }, { -0.051792934f, 0.3461701f, 0.20915925f, 0.078166496f }, { -0.26705611f, 0.14439061f, 0.0055054648f, 0.463243f }, { -0.0019649711f, -0.34119962f, -0.29306531f, -0.040223173f }, { 0.29285811f, -0.32824753f, -0.24768208f, -0.29676955f }, { 0.87604898f, 0.25374435f, 0.2341931f, -0.77851996f }, { -0.80404697f, 0.011122158f, 0.18899178f, 0.55592668f }, { -0.78397618f, -0.53690406f, -0.59931185f, 0.62348293f }, { 0.54613799f, 0.080819658f, 0.12590931f, -0.60614071f } }, { { -0.12307869f, -0.20242175f, 0.21530167f, -0.15608553f }, { 0.00052208688f, 0.09998365f, -0.067550225f, -0.14009319f }, { 0.12621699f, -0.089024022f, 0.022656689f, 0.18947331f }, { 0.34838897f, -0.04936051f, 0.25527451f, -0.18942819f }, { 0.013210249f, -0.043957685f, -0.19088103f, -0.034189573f }, { -0.0027790938f, -0.026595097f, 0.087083287f, -0.12513839f }, { -0.038231564f, 0.013328425f, -0.0091503894f, -0.005743873f }, { 0.17205702f, -0.14956835f, -0.0088915291f, 0.18720588f }, { -0.049670195f, 0.39532325f, 0.080260299f, 0.01811245f }, { 0.043555003f, -0.30289197f, -0.50878196f, 0.27306166f }, { 0.02555972f, -0.0068359476f, 0.061097702f, -0.43822038f }, { -0.10926471f, 0.1870906f, 0.12419548f, 0.1245213f }, { -0.012443149f, 0.040036941f, 0.18601483f, 0.02310445f }, { -0.10442982f, 0.057455632f, 0.13475314f, -0.0019859122f }, { -0.068181593f, -0.0033655904f, 0.01922998f, -0.020393828f }, { -0.10660626f, 0.0020812455f, 0.081209707f, 0.077131932f }, { 0.088733212f, -0.10430986f, 0.45554817f, -0.17113078f }, { 0.0046831409f, 0.13247549f, -0.1077727f, 0.15382275f }, { 0.022346595f, 0.022924261f, -0.35016323f, 0.2437608f }, { 0.029795657f, 0.23046877f, -0.020493651f, -0.33214749f }, { -0.016101582f, 0.042296203f, 0.046779444f, 0.037412394f }, { -0.02214903f, -0.025218605f, 0.14797485f, -0.051723623f }, { 0.021321783f, 0.010405115f, 0.0075476201f, 0.0082410917f }, { 0.040559796f, 0.027927916f, -0.012812736f, -0.0096642379f } }, { { -0.055647079f, 0.017595207f, 0.34495838f, -0.03055759f }, { -0.058415094f, 0.027416036f, 0.18568916f, 0.13044498f }, { 0.01482217f, -0.17300703f, 0.027540135f, -0.2744944f }, { 0.25558424f, -0.15324455f, -0.29751197f, -0.11422984f }, { -0.068936732f, -0.11425403f, 0.094767025f, -0.0020892558f }, { 0.040887892f, 0.031622148f, -0.095292456f, -0.02460001f }, { -0.0026237665f, 0.017734103f, 0.01213911f, 0.0056586962f }, { -0.052138375f, 0.052245567f, 0.04608449f, -0.043004468f }, { -0.17693366f, 0.0021023738f, 0.13167397f, -0.14062006f }, { -0.20900333f, 0.0057695127f, 0.13057243f, 0.046715668f }, { -0.020569928f, -0.08439655f, -0.09683347f, 0.038139385f }, { 0.18196242f, 0.44461908f, -0.11388512f, -0.12413082f }, { 0.072801844f, -0.0017236427f, -0.0026756083f, 0.049805114f }, { -0.092195952f, -0.0076195172f, -0.22763849f, -0.11320887f }, { 0.016234922f, 0.007258942f, 0.078535592f, -0.084829275f }, { -0.15320003f, 0.057490618f, -0.16065455f, -0.17063675f }, { -0.012856124f, 0.024818957f, 0.097529739f, 0.11569844f }, { -0.11141243f, 0.26677735f, 0.1319403f, -0.15699502f }, { -0.021128161f, -0.12370585f, 0.056198856f, -0.1836225f }, { -0.01871806f, 0.025525037f, 0.063822152f, 0.066517944f }, { -0.013759301f, 0.11401068f, -0.04701374f, -0.021321516f }, { 0.032714649f, -3.161284e-06f, 0.026930697f, 0.00019593482f }, { 0.10575127f, 0.016956425f, 0.016873291f, 0.0049304377f }, { -0.11938883f, 0.31242334f, 0.29347156f, -0.19514533f } } }, { { { -0.17374661f, -0.028781395f, -0.25993234f, 0.27242277f }, { -0.13675759f, -0.62291002f, -0.80742781f, 0.54260546f }, { 0.16876581f, -0.052588487f, 0.22415557f, -0.59669887f }, { 0.1769234f, 0.64210979f, 0.81157479f, -0.2718564f }, { -0.99873125f, -0.013258174f, 0.58939675f, 0.99930085f }, { -0.30883355f, -0.71116337f, -0.76218623f, 0.096388818f }, { 0.65749012f, -0.54533843f, -0.57508599f, -0.70359398f }, { -0.27406769f, 0.61006308f, 0.1873512f, 0.2563151f }, { -0.78453523f, -0.13585943f, -0.048534939f, 0.02085237f }, { 0.40938527f, -0.76981396f, -0.42506866f, 0.22362984f }, { 0.29003079f, -0.20624421f, 0.1151133f, -0.50558933f }, { 0.0070051806f, 0.20763719f, 0.59485798f, -0.61562639f }, { -0.4371111f, 0.48314196f, 0.72981069f, 0.99889301f }, { 0.58257878f, -0.8603979f, -0.94188892f, -0.83140889f }, { 0.71858167f, -0.49534538f, -0.63421799f, -0.84488463f }, { 0.016158248f, 0.65330502f, 0.82883727f, -0.127372f }, { -0.50292264f, -0.14848746f, -0.20836533f, 0.2471481f }, { -0.15815031f, -0.63472031f, -0.79826416f, 0.15325573f }, { -0.010424343f, -0.022843894f, 0.099730136f, -0.26040744f }, { 0.15069433f, 0.31188588f, 0.63836617f, -0.25234477f }, { -0.36946506f, 0.92093529f, 0.96548808f, 0.62354203f }, { -0.57070465f, -0.99847512f, -0.47855156f, -0.079970605f }, { 0.077467525f, -0.71134336f, -0.67172579f, -0.66364974f }, { -0.27299386f, 0.89512951f, 0.61598356f, 0.49577277f } }, { { 0.070458859f, -0.28774455f, 0.21287043f, -0.094689772f }, { 0.0029548085f, -0.31404605f, -0.039280892f, -0.3652277f }, { -0.033729607f, 0.041215792f, 0.065844258f, -0.21509418f }, { 0.39270582f, 0.067526811f, 0.15655351f, 0.053346856f }, { 0.052704394f, -0.087801294f, 0.18655104f, 0.056114808f }, { -0.074582751f, -0.055177669f, -0.22165519f, 0.13272162f }, { -0.027850171f, 0.0029849066f, -0.0062314784f, -0.010484316f }, { 0.20753796f, -0.0087111988f, -0.13875075f, -0.06137521f }, { 0.089744421f, 0.07271039f, 0.099417029f, -0.22157272f }, { -0.013209094f, 0.048633419f, -0.26528065f, -0.15253703f }, { 0.052922007f, 0.24859103f, 0.14406684f, 0.13857649f }, { 0.00096142813f, 0.32643367f, 0.17939549f, -0.39761314f }, { 0.013505803f, -0.036986517f, -0.12729111f, 0.15459921f }, { -0.00049722057f, -0.047063275f, -0.0018666598f, 0.1067114f }, { -0.074221027f, -0.00927958f, -0.029535811f, -0.024240068f }, { -0.12387933f, 0.06626829f, 0.16422781f, 0.077740779f }, { 0.14560404f, -0.082132455f, 0.027268021f, 0.18857832f }, { 0.10470732f, -0.29519533f, -0.23666419f, 0.10917064f }, { 0.042550279f, 0.02436036f, -0.31865644f, -0.024987356f }, { -0.030434576f, 0.082115299f, 0.17770796f, 0.020944092f }, { -0.17365377f, 0.13807361f, 0.12476029f, 0.072738061f }, { -0.11503962f, -0.04022554f, 0.028018434f, -0.070211356f }, { -0.043677907f, 0.0053361863f, 0.0039019898f, 0.0027489647f }, { 0.27060899f, -0.0016552279f, 0.14166067f, -0.25461265f } }, { { 0.014703402f, 0.094752279f, -0.32162049f, 0.082335322f }, { -0.31539882f, 0.44394592f, 0.44316202f, -0.031456167f }, { -0.024148679f, 0.082370612f, -0.0031744796f, 0.098610537f }, { 0.46130367f, -0.19989896f, -0.56118891f, 0.11979937f }, { 0.11784636f, 0.079971516f, -0.16977121f, 0.014922099f }, { 0.018367216f, -0.076519762f, 0.13801492f, 0.039682415f }, { -0.0027614728f, 0.0010389006f, -0.023126227f, 0.0027068473f }, { 0.22249856f, -0.071302328f, 0.23721977f, 0.10734273f }, { 0.41478408f, -0.36611101f, 0.18031261f, -0.11176768f }, { 0.15800457f, 0.23829725f, -0.0016193556f, 0.2112867f }, { -0.14793833f, -0.15378785f, 0.0082778301f, 0.27105519f }, { -0.064743588f, 0.44794816f, -0.12599819f, 0.4310022f }, { 0.092725214f, 0.033947737f, 0.19969884f, 0.0072363359f }, { -0.074190657f, 0.005985921f, 0.300818f, -0.090919095f }, { 0.024238118f, -0.010955859f, -0.068086841f, -0.021137349f }, { 0.12196721f, -0.19977338f, -0.64428422f, -0.30808722f }, { 0.46567096f, -0.042072501f, -0.1778338f, 0.34294059f }, { -0.32528695f, 0.25699981f, 0.49346557f, -0.20743316f }, { 0.10422458f, 0.049488574f, 0.49098274f, -0.34871439f }, { 0.16431875f, -0.050748897f, -0.18464312f, -0.61695364f }, { -0.1753479f, 0.033238479f, -0.046267845f, -0.012339883f }, { -0.16098841f, 0.080519992f, -0.11793031f, 0.036790025f }, { 0.017193144f, -0.0029212372f, -0.0044153187f, -0.0057094316f }, { 0.23481771f, -0.1556448f, -0.18775429f, -0.013697353f } } }, { { { 0.98467622f, 0.94970347f, 0.95791534f, 0.9408684f }, { 0.95525144f, 0.73013516f, 0.58966657f, 0.43166004f }, { 0.98562289f, 0.95804118f, 0.77397471f, 0.78825859f }, { 0.96588112f, 0.72807352f, 0.58424502f, 0.79142113f }, { -0.049305848f, 0.63904864f, 0.099145551f, -0.03377918f }, { 0.78673348f, 0.62998117f, 0.62680207f, 0.63245759f }, { 0.48526085f, 0.544603f, 0.40015579f, 0.43297544f }, { 0.82487776f, 0.77789448f, 0.92917353f, 0.91697567f }, { 0.58431326f, 0.95748667f, 0.99880743f, 0.99975533f }, { 0.67096902f, 0.60093643f, 0.64381538f, 0.92594344f }, { 0.95700408f, 0.93816272f, 0.93111608f, 0.80905665f }, { 0.94046044f, 0.97116483f, 0.77381347f, 0.78507504f }, { 0.7077214f, 0.7547892f, 0.23983411f, -0.039180128f }, { 0.3656649f, 0.38379871f, -0.00015338393f, 0.16604667f }, { 0.50679735f, 0.6108265f, 0.46821675f, 0.37829596f }, { 0.55946029f, 0.72460731f, 0.55919425f, 0.81214734f }, { 0.86277825f, 0.92634645f, 0.95542467f, 0.96581976f }, { 0.95061533f, 0.75913205f, 0.60228234f, 0.87287949f }, { 0.99994373f, 0.93971324f, 0.95087677f, 0.96466059f }, { 0.9442062f, 0.89161694f, 0.72879505f, 0.92100486f }, { 0.30989313f, 0.29579046f, 0.11395771f, 0.071428407f }, { 0.16674735f, -0.054071458f, 0.85747916f, 0.82737551f }, { 0.61593841f, 0.45356879f, 0.43544204f, 0.41332561f }, { 0.79196443f, 0.43841915f, 0.77763172f, 0.62193473f } }, { { 0.028699614f, 0.071974788f, -0.028868668f, 0.030119772f }, { -0.16988515f, -0.35713152f, 0.36877151f, 0.37172103f }, { 0.024472009f, 0.10373643f, 0.052160621f, -0.12998364f }, { 0.051999909f, -0.1688679f, 0.05813266f, -0.11063347f }, { 0.026373007f, 0.067310776f, 0.34433164f, 0.0017481699f }, { -0.017659611f, -0.10215276f, -0.23736187f, 0.12678732f }, { -0.0019097928f, 0.02067204f, -0.030447136f, -0.0093192388f }, { 0.10615435f, 0.11124023f, 0.04473958f, 0.14369936f }, { 0.14791062f, -0.034502091f, 0.041456555f, 0.06737059f }, { 0.22389399f, 0.2668048f, 0.25742349f, 0.03724758f }, { 0.0046009946f, 0.066632032f, 0.097957775f, 0.22969631f }, { 0.043253167f, -0.013638494f, 0.071328387f, -0.19249903f }, { -0.023561087f, 0.011490741f, 0.19824644f, -0.04133258f }, { -0.057507532f, -0.039265903f, 0.060469313f, 0.37300659f }, { 0.027051207f, -0.0086784396f, -0.0055877341f, -0.0315352f }, { 0.15724931f, 0.0099485187f, 0.22462997f, 0.14112999f }, { 0.13909905f, 0.026199511f, -0.12430815f, -0.076900423f }, { -0.022327596f, -0.1975812f, 0.49862652f, -0.096026553f }, { 0.076782007f, 0.041598482f, 0.0033451155f, 0.039947963f }, { 0.005353589f, 0.070993946f, 0.0068174778f, -0.17805261f }, { -0.059912765f, -0.17027417f, -0.060069718f, 0.1561139f }, { 0.017122435f, 0.048532637f, -0.05315926f, 0.066962855f }, { 0.058014377f, 0.021874362f, 0.017248667f, -0.0069413843f }, { 0.099274028f, 0.040622241f, 0.040435904f, 0.14191123f } }, { { -0.13453832f, 0.071519908f, -0.1597656f, -0.030758273f }, { -0.13511715f, 0.32373425f, 0.35851035f, -0.18685481f }, { 0.021440457f, 0.034442875f, 0.14324368f, 0.15754565f }, { -0.061440371f, 0.16837735f, 0.47887644f, -0.036265812f }, { 0.55060811f, 0.14095672f, 0.13077418f, 0.25515565f }, { -0.084599968f, -0.084002143f, 0.1542308f, 0.044223437f }, { 0.0017727822f, 0.025149715f, -0.025479364f, -0.0023658361f }, { 0.1619123f, 0.069159159f, -0.016343512f, 0.026108175f }, { 0.3296525f, 0.029456656f, 0.039715069f, 0.015958704f }, { -0.093419591f, 0.37051381f, -0.063182977f, -0.017764112f }, { 0.11962535f, 0.062511772f, -0.070445145f, 0.27768911f }, { 0.07458833f, -0.16218828f, 0.064111239f, 0.43889373f }, { -0.0326486f, -0.03666828f, -0.17597139f, 0.34213144f }, { 0.061334301f, -0.0099525239f, 0.21497301f, 0.0074569296f }, { -0.016749445f, 0.00054557189f, 0.040331287f, 0.066200794f }, { 0.20620866f, 0.25268529f, 0.46594276f, 0.059651923f }, { 0.15170896f, 0.041438057f, 0.021708506f, -0.15049245f }, { -0.14317538f, 0.13548996f, 0.37297491f, 0.13718874f }, { 0.053339004f, 0.015014013f, -0.10418356f, -0.13598877f }, { -0.02227412f, 0.045548464f, 0.21534467f, -0.23828118f }, { -0.055326885f, 0.11851609f, 0.28938409f, 0.041373996f }, { -0.1219532f, 0.57338554f, -0.094571555f, 0.025008596f }, { 0.070380772f, 0.016993506f, 0.018073937f, -0.015404818f }, { 0.17033841f, 0.12449473f, 0.10847869f, -0.11141982f } } }, { { { 4.409738f, 4.5071479f, 5.4761817f, 5.3214091f }, { 5.3741435f, 4.6270256f, 5.4786338f, 5.323679f }, { 4.305776f, 4.4890731f, 4.6894257f, 4.6068436f }, { 5.4930574f, 4.9116386f, 5.4097636f, 4.9225404f }, { 5.1861828f, 5.5144226f, 5.1307797f, 5.0804212f }, { 6.1194597f, 6.0655136f, 5.7369562f, 6.1076578f }, { 6.9549598f, 6.9281578f, 6.9549598f, 6.9549598f }, { 4.5030565f, 4.5849566f, 4.4830953f, 4.4904323f }, { 5.3629211f, 5.5524848f, 4.5719135f, 4.9103175f }, { 4.8906163f, 5.3972226f, 4.8806206f, 5.1834202f }, { 4.5047396f, 4.5984947f, 4.7039612f, 4.3422371f }, { 4.5956963f, 5.6294962f, 4.46025f, 4.4827131f }, { 5.8454206f, 6.000743f, 5.4594428f, 4.9952614f }, { 6.09642f, 6.3979283f, 4.9784963f, 5.6878449f }, { 6.9549598f, 6.9752898f, 6.9549598f, 6.9549598f }, { 6.2053562f, 4.9984547f, 5.3887395f, 4.6221036f }, { 4.5265196f, 4.3684629f, 5.5819288f, 5.4957366f }, { 5.2220057f, 4.6118907f, 5.5046208f, 4.9190037f }, { 4.3408178f, 4.4980303f, 5.4937404f, 5.6154153f }, { 4.4802186f, 4.4666194f, 4.8546878f, 5.1764252f }, { 5.7384024f, 5.9048089f, 5.4636107f, 5.0807017f }, { 5.1013817f, 5.2237041f, 6.0338955f, 5.8869417f }, { 6.9414339f, 6.9549598f, 6.9549598f, 6.9549598f }, { 4.3368412f, 4.9692663f, 4.7090567f, 4.9023075f } }, { { 0.0093525884f, -0.33796029f, -0.4366682f, -0.18161326f }, { -0.34446047f, 0.10854359f, -0.61563912f, -0.16514117f }, { 0.055849315f, 0.093045585f, 0.36722184f, 0.085665647f }, { -0.21881508f, -0.036846235f, -0.25226403f, -0.012790033f }, { -0.14697546f, -0.026656628f, 0.2559775f, 0.026279081f }, { 0.073189287f, -0.074472165f, -0.15439557f, 0.020907645f }, { 0.0f, -0.015078298f, 0.0f, 0.0f }, { 0.027540893f, -0.30876053f, -0.15680794f, -0.18470107f }, { -0.072547269f, -0.019227086f, -0.26735769f, -0.1362069f }, { 0.36907279f, -0.28005156f, 0.01966203f, -0.10277819f }, { -0.26755862f, 0.066747173f, 0.60834173f, -0.23356165f }, { -0.12357338f, -0.41742338f, 0.081840746f, -0.14596222f }, { -0.068599762f, -0.004402392f, -0.17192993f, -0.15797464f }, { -0.072923207f, -0.02555551f, -0.21075071f, 0.047272919f }, { 0.0f, 0.0115085f, 0.0f, 0.0f }, { 0.32527558f, 0.066048741f, -0.28639187f, 0.45171914f }, { -0.158086f, -0.049098981f, -0.17226122f, -0.50289857f }, { -0.39456648f, 0.031970902f, -0.74883626f, 0.20536003f }, { 0.22864705f, -0.0095988927f, -0.1155595f, -0.06240073f }, { 0.12336497f, -0.34128076f, 0.34341316f, 0.083678547f }, { -0.032718317f, 0.076359349f, -0.30099369f, -0.016865529f }, { -0.23491753f, -0.17228011f, -0.044893186f, -0.057411459f }, { -0.0077848677f, 0.0f, 0.0f, 0.0f }, { -0.18713605f, -0.11612415f, 0.30907006f, 0.064707406f } }, { { -0.20768494f, -0.15642062f, -0.079474216f, -0.020948121f }, { -0.18767308f, -0.013722599f, 0.15827086f, -0.27421942f }, { -0.11484158f, -0.29325715f, 0.24426149f, 0.34598577f }, { -0.095599056f, 0.16784413f, 0.23369965f, 0.15036114f }, { 0.058496274f, -0.064565923f, -0.076598803f, -0.11988702f }, { -0.03406356f, -0.010863931f, -0.036116475f, 0.0077051595f }, { 0.0f, -0.015078298f, 0.0f, 0.0f }, { -0.21271534f, 0.31678528f, 0.084310434f, -0.039787477f }, { 0.057420352f, -0.60894321f, -0.14275706f, -0.29178151f }, { -0.21477227f, 0.091254596f, -0.053659362f, -0.13299553f }, { -0.24972574f, 0.22261101f, -0.59415755f, -0.13299464f }, { -0.406027f, 0.15018847f, 0.33281927f, 0.28006105f }, { -0.033198856f, 0.013081228f, 0.0098634494f, -0.18858267f }, { -0.16914457f, -0.014917022f, -0.15618156f, 0.038961385f }, { 0.0f, 0.0115085f, 0.0f, 0.0f }, { 0.047340338f, -0.052961301f, 0.30193278f, 0.38564757f }, { -0.2009302f, -0.15247105f, -0.32333852f, 0.22878398f }, { -0.22934017f, 0.022888443f, 0.30911154f, -0.12420416f }, { 0.21191356f, -0.33281926f, -0.13523708f, -0.038546557f }, { 0.28507859f, -0.012777666f, 0.16285544f, -0.12612215f }, { -0.057034227f, 0.01719448f, -0.037892291f, -0.13064036f }, { -0.075888865f, 0.041589292f, 0.0089100653f, -0.10775402f }, { 0.0075560462f, 0.0f, 0.0f, 0.0f }, { -0.18120766f, 0.16485298f, 0.58949587f, 0.072313493f } } }, { { { 0.60381773f, 0.64633179f, 0.92301353f, 0.23720177f }, { 1.1128727f, 0.42172315f, 1.6605811f, 0.22066721f }, { 0.55829912f, 0.7107351f, 0.47437673f, 0.53646626f }, { 0.75684406f, 0.65607146f, 1.5264507f, 0.12817954f }, { -0.25070514f, 0.30263175f, -0.21070678f, -0.2264813f }, { -0.24745858f, -0.26801252f, 0.2750925f, 0.055035565f }, { -0.018769156f, -0.066023008f, 0.10111114f, 0.0089232736f }, { 0.41152465f, 0.52508091f, 0.4161358f, 0.39058287f }, { 0.90919582f, 1.2448772f, 0.61547497f, 0.51303689f }, { 0.2973136f, 1.2348603f, 0.24154398f, 0.76087607f }, { 0.23369317f, 0.68368068f, 0.81024353f, 0.35451079f }, { 0.69272073f, 0.47014545f, 0.61401877f, 0.43768641f }, { -0.44449894f, -0.10123077f, -0.19173956f, -0.15811184f }, { -0.089717f, -0.068601549f, -0.16704813f, -0.29761406f }, { 0.0055968308f, -0.089855929f, -0.087150641f, 0.2244144f }, { 0.38902787f, 0.62620686f, 1.3314901f, 0.26038797f }, { 0.16776511f, 0.32722251f, 0.71914611f, 0.53556119f }, { 0.63106992f, 0.46256454f, 1.785895f, 0.17339911f }, { 0.72516261f, 0.44941094f, 0.81174974f, 0.61247129f }, { 0.56877815f, 0.20989179f, 0.7607991f, 0.017998645f }, { 0.016372087f, 0.26062407f, -0.32771461f, -0.075930098f }, { -0.11957223f, -0.22579003f, -0.42587945f, -0.0015549589f }, { 0.0049992009f, 0.053511694f, 0.00053268274f, 0.022778575f }, { 0.19356675f, 0.5564623f, 0.74981777f, 0.28733119f } }, { { 0.017029304f, 0.22690356f, 0.25927682f, -0.048136042f }, { 0.52936856f, -0.26082526f, 0.12568074f, -0.046727529f }, { 0.08949554f, -0.019090555f, 0.31477592f, -0.067513409f }, { 0.056302335f, -0.011819435f, -0.063621104f, 0.27092306f }, { 0.053971592f, -0.17913246f, -0.14991651f, -0.044263405f }, { 0.29037749f, -0.040498369f, -0.33600753f, 0.16250066f }, { -0.067102844f, -0.17843768f, 0.033172168f, 0.13638573f }, { 0.057127881f, -0.044468822f, 0.33005778f, 0.34775491f }, { -0.14300931f, 0.022121077f, -0.045281831f, -0.065216583f }, { 0.084931489f, 0.06688461f, 0.15758114f, -0.091330485f }, { -0.014274888f, 0.29139103f, 0.089163749f, -0.18005467f }, { -0.2191522f, -0.1333803f, -0.31948964f, -0.28536602f }, { 0.20298891f, -0.0031882515f, -0.15749696f, -0.014977715f }, { -0.14016857f, -0.17278064f, 0.01369474f, 0.10971499f }, { 0.018219806f, 0.080447764f, 0.0056022696f, -0.043028475f }, { -0.076556403f, -0.13038184f, -0.23788273f, 0.5849635f }, { 0.1038427f, 0.18199702f, 0.35294355f, -0.0023601311f }, { 0.22294845f, -0.37427713f, 0.2907529f, 0.26234219f }, { 0.40809306f, 0.12982813f, 0.42857338f, 0.14064303f }, { 0.4265028f, 0.18710053f, 0.15310514f, 0.067551813f }, { -0.18986488f, -0.029676062f, -0.087045959f, -0.14788626f }, { -0.07865478f, 0.011558295f, -0.018262356f, 0.38992629f }, { 0.22297641f, 0.072192947f, 0.064119712f, 0.12862555f }, { -0.069262467f, -0.14990585f, 0.31342655f, -0.15002022f } }, { { 0.25288162f, -0.096551539f, 0.051695506f, 0.20925392f }, { 0.23093904f, 0.096712594f, 0.19826434f, 0.32530694f }, { 0.14114785f, 0.071010138f, -0.17642029f, 0.092260082f }, { 0.39001648f, -0.17666595f, 0.088397252f, 0.1462816f }, { 0.12484597f, 0.066920676f, -0.16116194f, 0.21758387f }, { 0.15625272f, -0.00043631439f, -0.07868976f, -0.19261141f }, { -0.0142415f, 0.06356153f, 0.026276923f, -0.024546668f }, { 0.097089221f, 0.085426402f, 0.11936115f, 0.012042542f }, { 0.52509109f, -0.22465399f, -0.11490612f, 0.023562122f }, { -0.12418278f, 0.11985465f, 0.087804943f, 0.25283464f }, { 0.10716753f, -0.036426901f, 0.2469409f, -0.095816257f }, { -0.095364501f, 0.14001518f, -0.068636804f, -0.082487255f }, { 0.074490355f, 0.25323233f, 0.17863748f, 0.12482145f }, { -0.019616587f, -0.0053326518f, 0.047558858f, 0.066104462f }, { 0.12647102f, 0.25712368f, 0.12306783f, -0.050252261f }, { -0.13375041f, 0.17825067f, 0.026649645f, -0.33338076f }, { 0.16384463f, -0.022241979f, 0.17817325f, 0.6808721f }, { 0.42075944f, -0.024292721f, -0.11323318f, 0.45027063f }, { -0.023953485f, 0.25719992f, 0.28680108f, 0.33600529f }, { 0.013445546f, 0.22504275f, 0.17408162f, 0.52860686f }, { -0.098839039f, -0.27017244f, 0.10293505f, -0.012472685f }, { 0.074267375f, -0.0056418849f, 0.17632358f, 0.21754089f }, { 0.1491061f, 0.017927571f, -0.0217757f, -0.0039381966f }, { 0.067239102f, -0.74624136f, 0.12992555f, -0.058866581f } } } }, { { { { 0.1270204f, 0.7650174f, 0.55252173f, 0.05956498f }, { -0.36870832f, 0.31227245f, 0.52167466f, 0.4282174f }, { -0.036761861f, -0.5477415f, -0.76091563f, -0.37583127f }, { 0.17129434f, -0.14281209f, -0.40463148f, -0.56367877f }, { 0.07429238f, 0.45420144f, 0.41919765f, 0.019225986f }, { -0.44125436f, -0.05567539f, 0.080551064f, 0.54444995f }, { -0.36600455f, -0.55359309f, -0.3290331f, 0.33946169f }, { 0.65253747f, 0.015186649f, 0.0665303f, -0.64649501f }, { 0.05392469f, 0.54355001f, 0.7539307f, -0.41089455f }, { -0.29264863f, 0.49684721f, 0.39184208f, 0.47737193f }, { 0.10885354f, -0.80803227f, -0.7443769f, -0.3736688f }, { 0.1939378f, -0.079590275f, -0.42241709f, -0.75536039f }, { 0.44776697f, 0.44884546f, 0.427965f, 0.3297221f }, { -0.34595785f, 0.27723463f, 0.12245317f, 0.43884357f }, { 0.18467758f, -0.55582608f, -0.99421464f, -0.0096027817f }, { 0.6672057f, -0.038103784f, -0.048616141f, -0.68508055f }, { -0.016615937f, 0.62001729f, 0.50530563f, -0.22211425f }, { -0.16823123f, 0.31934529f, 0.47092187f, 0.4884373f }, { 0.03194189f, -0.5624624f, -0.44688229f, 0.223814f }, { 0.17828041f, -0.080017082f, -0.44239439f, -0.46726625f }, { 0.19895649f, 0.82568772f, 0.47859751f, 0.064443297f }, { -0.47464217f, 0.011895223f, 0.01123465f, -0.010697203f }, { -0.17670677f, -0.66931423f, -0.5814681f, -0.01325001f }, { 0.65193874f, -0.010713062f, -0.007915928f, -0.65520853f } }, { { -0.01027431f, -0.0019056004f, 0.0020213958f, 0.0064495753f }, { 0.0058416688f, 0.0051314639f, 0.021497114f, 0.005870592f }, { -0.00035518612f, -0.00087553938f, -0.0029318969f, 0.0087577986f }, { -0.0048770476f, -0.015949665f, -0.034816051f, -0.006104917f }, { 0.0015371362f, -0.0012591621f, 0.01241148f, 0.00096621463f }, { 0.0032416133f, 0.021025709f, 0.0036344622f, 0.0015436078f }, { -0.0093946276f, 0.0046564763f, 0.028177476f, -0.01022744f }, { 0.00014675555f, 0.030031482f, -0.0092302407f, -0.001999398f }, { -0.049980321f, 0.024752279f, 0.016684689f, -0.0045230976f }, { 0.0067493834f, 0.014071508f, 0.0079316435f, 0.034593704f }, { 0.01971715f, -0.0037227013f, -0.013430278f, -0.024257585f }, { -0.004342319f, 0.024001878f, -0.013356442f, -0.022792018f }, { -0.0051709665f, -0.017029547f, 0.040567567f, 0.0052520812f }, { 0.0090399102f, 0.0079604733f, 0.00018765016f, -0.0092868977f }, { -0.020304032f, 0.0056590257f, -0.0045373063f, -0.018653318f }, { -9.9636934e-05f, 0.002001886f, 0.0046843544f, 0.0055608043f }, { 0.0018025744f, -0.0025962216f, 0.0068285574f, -0.014851062f }, { 0.00041645221f, 0.0054738242f, 0.0076769026f, -0.013419208f }, { 0.0038347099f, -0.0042555066f, -0.0066470075f, 0.0039146778f }, { -0.009084153f, 0.024461537f, 0.0034578066f, -0.0054827001f }, { 0.0033463477f, 0.0045594748f, 0.00037604935f, -0.01571513f }, { -0.012589588f, 0.029678359f, -0.019924871f, -0.004708459f }, { -0.0002642682f, -0.0051057336f, -0.0042867302f, -0.00041141781f }, { -0.00086487068f, -0.0025170841f, 0.0030062196f, -0.0030385417f } }, { { -0.01027431f, -0.0019056004f, 0.0020213958f, 0.0064495753f }, { 0.0058416688f, 0.0051314639f, 0.021497114f, 0.005870592f }, { -0.00035518612f, -0.00087553938f, -0.0029318969f, 0.0087577986f }, { -0.0048770476f, -0.015949665f, -0.034816051f, -0.006104917f }, { 0.0015371362f, -0.0012591621f, 0.01241148f, 0.00096621463f }, { 0.0032416133f, 0.021025709f, 0.0036344622f, 0.0015436078f }, { -0.0093946276f, 0.0046564763f, 0.028177476f, -0.01022744f }, { 0.00014675555f, 0.030031482f, -0.0092302407f, -0.001999398f }, { -0.049980321f, 0.024752279f, 0.016684689f, -0.0045230976f }, { 0.0067493834f, 0.014071508f, 0.0079316435f, 0.034593704f }, { 0.01971715f, -0.0037227013f, -0.013430278f, -0.024257585f }, { -0.004342319f, 0.024001878f, -0.013356442f, -0.022792018f }, { -0.0051709665f, -0.017029547f, 0.040567567f, 0.0052520812f }, { 0.0090399102f, 0.0079604733f, 0.00018765016f, -0.0092868977f }, { -0.020304032f, 0.0056590257f, -0.0045373063f, -0.018653318f }, { -9.9636934e-05f, 0.002001886f, 0.0046843544f, 0.0055608043f }, { 0.0018025744f, -0.0025962216f, 0.0068285574f, -0.014851062f }, { 0.00041645221f, 0.0054738242f, 0.0076769026f, -0.013419208f }, { 0.0038347099f, -0.0042555066f, -0.0066470075f, 0.0039146778f }, { -0.009084153f, 0.024461537f, 0.0034578066f, -0.0054827001f }, { 0.0033463477f, 0.0045594748f, 0.00037604935f, -0.01571513f }, { -0.012589588f, 0.029678359f, -0.019924871f, -0.004708459f }, { -0.0002642682f, -0.0051057336f, -0.0042867302f, -0.00041141781f }, { -0.00086487068f, -0.0025170841f, 0.0030062196f, -0.0030385417f } } }, { { { -0.68772793f, 0.19029367f, -0.17427646f, 0.60300616f }, { -0.29980532f, -0.22397537f, -0.4071009f, 0.36277983f }, { 0.75628069f, -0.13426242f, 0.13645381f, -0.74653491f }, { 0.14891408f, -0.13497977f, 0.36807879f, -0.39814386f }, { -0.20608987f, -0.076497863f, -0.19510375f, 0.34604256f }, { -0.02421123f, -0.4588774f, -0.64965351f, 0.083039161f }, { 0.51918764f, -0.30614677f, -0.25791921f, -0.40837612f }, { 0.028860181f, 0.63152733f, 0.5876224f, -0.033139773f }, { -0.63418144f, 0.046874151f, 0.24431924f, 0.71662556f }, { -0.29088451f, -0.21455586f, -0.73980807f, 0.65038559f }, { 0.78663226f, 0.00020858525f, 0.40361403f, -0.75720144f }, { 0.1998276f, 0.54590973f, 0.1773378f, -0.35464319f }, { -0.40236144f, 0.31362578f, -0.34406026f, 0.38120073f }, { -0.27845549f, -0.46862161f, -0.47141499f, 0.095899189f }, { 0.6004921f, 0.28051621f, -0.011378178f, -0.98141078f }, { 0.032724674f, 0.66798127f, 0.66430425f, -0.05209965f }, { -0.59603974f, -0.083198329f, 0.34616224f, 0.42082916f }, { -0.14262632f, -0.21418442f, -0.37504914f, 0.32676687f }, { 0.58204273f, 0.0067537174f, -0.35923481f, -0.40792038f }, { 0.15607366f, 0.17215007f, 0.34414936f, -0.33566945f }, { -0.44862333f, 0.004919013f, 0.0076768115f, 0.41897935f }, { -0.022062848f, -0.39695079f, -0.0062786656f, 0.042925103f }, { 0.65953535f, -0.15521993f, 0.011867978f, -0.57721165f }, { 0.031305912f, 0.65627006f, 0.66779002f, -0.029815636f } }, { { 0.011457792f, -0.011774949f, -0.012205337f, 0.0048139052f }, { -0.024024566f, 0.018313023f, -0.023210623f, -0.0046351547f }, { 0.0039133571f, 0.0046801024f, -0.020590099f, -0.0018568631f }, { -0.015369931f, -0.0092621276f, -0.026149742f, 0.0010335971f }, { 0.032555144f, -0.01336897f, -0.022733265f, -0.027997469f }, { -0.028161537f, -0.00073877629f, -0.023989631f, 0.0055660453f }, { -0.012966193f, 0.003944376f, 0.025685982f, -0.0017458044f }, { 0.00015626641f, -0.009524206f, 0.0083025026f, -0.00049753811f }, { -0.02358661f, 0.006370149f, 0.00087066462f, -0.00054248544f }, { -0.0024571244f, -0.023218369f, -0.010895303f, -0.0095647684f }, { 0.0069970393f, -0.00093403301f, -0.0081922371f, -0.00026359768f }, { 0.0065921354f, 0.028846533f, -0.045676337f, 0.006070217f }, { 0.0045248423f, -0.0084676847f, 0.028756195f, 0.020612871f }, { 0.0037691244f, -0.0069385161f, -0.00029501448f, -0.0017839033f }, { -0.0048675353f, -0.011930456f, 0.0044251285f, -0.00016323616f }, { -0.0012291164f, -0.0019575288f, 0.0078250029f, -0.0011151155f }, { 0.00503333f, -0.0094538968f, 0.0092375183f, 0.018207648f }, { 0.0080615812f, -0.0073583459f, -0.0166794f, 0.016416158f }, { 0.002192959f, -0.01153759f, -0.0048668362f, -0.0071123281f }, { -0.010116143f, -0.010224552f, 0.010897731f, 0.00093792816f }, { 0.017199359f, -0.0087516179f, 0.0021169251f, -0.020946959f }, { -0.01570063f, 0.020087246f, 0.014492818f, -0.016014018f }, { 0.0023484072f, 0.0015070243f, -0.00045616273f, -0.001211882f }, { 0.0018090492f, -0.0012261901f, 0.0012809284f, 0.00096488905f } }, { { 0.011457792f, -0.011774949f, -0.012205337f, 0.0048139052f }, { -0.024024566f, 0.018313023f, -0.023210623f, -0.0046351547f }, { 0.0039133571f, 0.0046801024f, -0.020590099f, -0.0018568631f }, { -0.015369931f, -0.0092621276f, -0.026149742f, 0.0010335971f }, { 0.032555144f, -0.01336897f, -0.022733265f, -0.027997469f }, { -0.028161537f, -0.00073877629f, -0.023989631f, 0.0055660453f }, { -0.012966193f, 0.003944376f, 0.025685982f, -0.0017458044f }, { 0.00015626641f, -0.009524206f, 0.0083025026f, -0.00049753811f }, { -0.02358661f, 0.006370149f, 0.00087066462f, -0.00054248544f }, { -0.0024571244f, -0.023218369f, -0.010895303f, -0.0095647684f }, { 0.0069970393f, -0.00093403301f, -0.0081922371f, -0.00026359768f }, { 0.0065921354f, 0.028846533f, -0.045676337f, 0.006070217f }, { 0.0045248423f, -0.0084676847f, 0.028756195f, 0.020612871f }, { 0.0037691244f, -0.0069385161f, -0.00029501448f, -0.0017839033f }, { -0.0048675353f, -0.011930456f, 0.0044251285f, -0.00016323616f }, { -0.0012291164f, -0.0019575288f, 0.0078250029f, -0.0011151155f }, { 0.00503333f, -0.0094538968f, 0.0092375183f, 0.018207648f }, { 0.0080615812f, -0.0073583459f, -0.0166794f, 0.016416158f }, { 0.002192959f, -0.01153759f, -0.0048668362f, -0.0071123281f }, { -0.010116143f, -0.010224552f, 0.010897731f, 0.00093792816f }, { 0.017199359f, -0.0087516179f, 0.0021169251f, -0.020946959f }, { -0.01570063f, 0.020087246f, 0.014492818f, -0.016014018f }, { 0.0023484072f, 0.0015070243f, -0.00045616273f, -0.001211882f }, { 0.0018090492f, -0.0012261901f, 0.0012809284f, 0.00096488905f } } }, { { { 0.71476997f, 0.61525336f, 0.81507512f, 0.79550964f }, { 0.87986984f, 0.9232123f, 0.74974956f, 0.82765975f }, { 0.65321366f, 0.82580437f, 0.63434042f, 0.54903231f }, { 0.97390084f, 0.98050251f, 0.83713283f, 0.72370416f }, { 0.97570877f, 0.88760866f, 0.88668363f, 0.9380218f }, { 0.89705541f, 0.88675351f, 0.75595095f, 0.83467284f }, { 0.77232433f, 0.77447327f, 0.9084134f, 0.84734569f }, { -0.75720667f, -0.77520488f, -0.80639546f, -0.76219811f }, { 0.77130152f, 0.83806694f, 0.60983327f, 0.56357207f }, { 0.91090229f, 0.84089752f, 0.54694041f, 0.59085922f }, { 0.60775044f, 0.58913818f, 0.53197627f, 0.53574024f }, { 0.96044628f, 0.83405513f, 0.88888419f, 0.55105253f }, { 0.79850486f, 0.83676557f, 0.83574428f, 0.86369517f }, { 0.89597751f, 0.83876978f, 0.87336884f, 0.8934314f }, { 0.77801249f, 0.78253947f, 0.10680725f, 0.19167855f }, { -0.74415432f, -0.74320194f, -0.74587957f, -0.72660186f }, { 0.802783f, 0.78016447f, 0.79046691f, 0.87952719f }, { 0.97537479f, 0.92311625f, 0.79848027f, 0.80910594f }, { 0.8125306f, 0.82679528f, 0.81929639f, 0.88516002f }, { 0.97152309f, 0.98181547f, 0.82815966f, 0.81791703f }, { 0.87129411f, 0.56410602f, 0.87800085f, 0.905706f }, { 0.87990229f, 0.91776281f, 0.99991718f, 0.99902102f }, { 0.73060786f, 0.72658464f, 0.81348263f, 0.81648708f }, { -0.75762512f, -0.75445002f, -0.74430762f, -0.75485946f } }, { { 0.018332644f, 0.0084005452f, -0.0018937689f, -0.0035491975f }, { 0.0016556654f, 0.0049261013f, -0.021796869f, 0.0025973591f }, { -0.0019671758f, 0.00051947074f, 0.0071261223f, 0.0056689139f }, { 0.00041901024f, -0.0023903288f, -0.0035639711f, -0.0036673013f }, { 0.009963464f, 0.00099195429f, -0.0042516892f, 0.0092605531f }, { 0.0034813664f, 0.0028575465f, -0.016343415f, -0.0014475905f }, { 0.0053571039f, 0.0051116063f, 0.016171091f, -0.00052744238f }, { 0.00013272575f, -0.0095491849f, 0.0070156475f, 0.0017057538f }, { 0.028067438f, -0.0086835729f, -0.0087852674f, 0.0035321054f }, { 0.0025007808f, -0.0075654884f, -0.012551417f, -0.0068823899f }, { -0.00017607308f, 0.002636122f, -0.011272055f, -0.010314896f }, { 0.010646599f, 0.00042804331f, 0.013900837f, -0.01279076f }, { 0.0059898286f, 0.012331371f, -0.0073125296f, 0.016248603f }, { 0.031579315f, -0.0057840222f, -0.00018304192f, 0.005171422f }, { 0.010928513f, 0.0092660887f, 0.030404621f, 0.0053167707f }, { -0.00014899672f, -0.0035246494f, 0.0075862845f, -0.005861723f }, { 0.0067791918f, 0.0021224495f, -0.0071755505f, -0.010370936f }, { 0.0015352958f, -0.0025785166f, -0.0092688001f, 0.003966373f }, { 0.0036915074f, -0.002306452f, -0.005736452f, -0.0033594125f }, { 0.0065128512f, 0.006188005f, 0.00088322638f, -0.0016227066f }, { 0.0092720771f, -0.0046684631f, -7.3769604e-05f, 0.013807013f }, { -0.0031421984f, 0.010622679f, 0.00041591214f, 0.0032786075f }, { -0.0021421613f, -0.0041675589f, -0.0029529994f, -0.00085350449f }, { -0.00069204344f, -0.0010785124f, 0.00097549628f, 0.0025280456f } }, { { 0.018332644f, 0.0084005452f, -0.0018937689f, -0.0035491975f }, { 0.0016556654f, 0.0049261013f, -0.021796869f, 0.0025973591f }, { -0.0019671758f, 0.00051947074f, 0.0071261223f, 0.0056689139f }, { 0.00041901024f, -0.0023903288f, -0.0035639711f, -0.0036673013f }, { 0.009963464f, 0.00099195429f, -0.0042516892f, 0.0092605531f }, { 0.0034813664f, 0.0028575465f, -0.016343415f, -0.0014475905f }, { 0.0053571039f, 0.0051116063f, 0.016171091f, -0.00052744238f }, { 0.00013272575f, -0.0095491849f, 0.0070156475f, 0.0017057538f }, { 0.028067438f, -0.0086835729f, -0.0087852674f, 0.0035321054f }, { 0.0025007808f, -0.0075654884f, -0.012551417f, -0.0068823899f }, { -0.00017607308f, 0.002636122f, -0.011272055f, -0.010314896f }, { 0.010646599f, 0.00042804331f, 0.013900837f, -0.01279076f }, { 0.0059898286f, 0.012331371f, -0.0073125296f, 0.016248603f }, { 0.031579315f, -0.0057840222f, -0.00018304192f, 0.005171422f }, { 0.010928513f, 0.0092660887f, 0.030404621f, 0.0053167707f }, { -0.00014899672f, -0.0035246494f, 0.0075862845f, -0.005861723f }, { 0.0067791918f, 0.0021224495f, -0.0071755505f, -0.010370936f }, { 0.0015352958f, -0.0025785166f, -0.0092688001f, 0.003966373f }, { 0.0036915074f, -0.002306452f, -0.005736452f, -0.0033594125f }, { 0.0065128512f, 0.006188005f, 0.00088322638f, -0.0016227066f }, { 0.0092720771f, -0.0046684631f, -7.3769604e-05f, 0.013807013f }, { -0.0031421984f, 0.010622679f, 0.00041591214f, 0.0032786075f }, { -0.0021421613f, -0.0041675589f, -0.0029529994f, -0.00085350449f }, { -0.00069204344f, -0.0010785124f, 0.00097549628f, 0.0025280456f } } }, { { { 5.3792285f, 5.1960477f, 5.5112916f, 5.6615254f }, { 5.0489877f, 5.2428834f, 5.1752035f, 5.1109826f }, { 5.5205204f, 5.7511938f, 5.0202917f, 4.9168865f }, { 4.9522523f, 4.8880256f, 5.1015936f, 5.2858816f }, { 5.7256502f, 5.7919759f, 5.645241f, 5.6035708f }, { 6.4076931f, 6.4822111f, 6.2642633f, 6.3925959f }, { 6.9797014f, 6.981436f, 7.0028674f, 6.9976464f }, { -0.03290957f, -0.03290957f, -0.03290957f, -0.03290957f }, { 5.4977854f, 5.7684965f, 5.3463095f, 4.8810492f }, { 4.9869047f, 5.4896416f, 4.9647805f, 4.884877f }, { 5.3141219f, 5.3357788f, 4.7695434f, 4.8709631f }, { 5.2056063f, 5.407802f, 5.2123857f, 4.9428208f }, { 6.2188218f, 6.17756f, 6.2751008f, 6.3672109f }, { 6.9105856f, 6.7986798f, 6.5712335f, 6.5907061f }, { 6.9797014f, 6.9797014f, 5.6859993f, 5.5642483f }, { -0.032764603f, -0.032764603f, -0.032764603f, -0.032764603f }, { 5.7724142f, 6.0929556f, 5.99581f, 5.9265164f }, { 4.9363192f, 4.9823732f, 5.1732995f, 5.2475265f }, { 5.8365191f, 5.9972902f, 5.9778441f, 5.9270668f }, { 4.8706768f, 5.0194503f, 5.155585f, 5.2188041f }, { 6.1569904f, 6.0563989f, 6.0989699f, 6.2139837f }, { 5.8727399f, 5.8948086f, 5.5734095f, 5.5536103f }, { 6.9797014f, 6.9797014f, 6.9797014f, 6.9797014f }, { -0.032766769f, -0.032766769f, -0.032766769f, -0.032766769f } }, { { 0.0011802354f, -0.006546101f, -0.02103972f, 0.0008654047f }, { -0.015460534f, 0.017874544f, 0.0029121134f, 0.023511773f }, { -0.040909245f, 0.011927691f, 0.011991588f, 0.01677931f }, { -0.015633544f, -0.0042321141f, 0.026623034f, 0.0080414514f }, { 0.012614382f, 0.0065080145f, 0.035716738f, -0.0080665814f }, { -0.0057849744f, -0.017478461f, -0.031219642f, 0.00016446523f }, { 0.0f, 0.00032235028f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { -0.068586697f, -0.024228236f, -0.012857221f, -0.039493706f }, { -0.018078201f, -0.015140979f, 0.00072119173f, -0.051249859f }, { -0.054228277f, 0.0097895101f, 0.0019832646f, -0.011715411f }, { -0.042326208f, -0.010160072f, 0.037088052f, -0.031848667f }, { 0.00067130897f, -0.013966717f, -0.017268559f, -0.0074614576f }, { 0.070515961f, 0.012848107f, -0.0008396517f, 0.0049006506f }, { 0.0f, 0.0f, -0.063014256f, -0.0085124986f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { -0.040302299f, 0.0048936307f, 0.0064406394f, 0.0034044871f }, { -0.010453589f, 0.0035820836f, -0.017384391f, -0.038199947f }, { -0.044968611f, -0.0088322127f, 0.020303819f, 0.0058131005f }, { -0.0056838535f, 0.010211409f, -0.010999927f, -0.027621859f }, { 0.0064753811f, -0.0059341242f, -0.014902755f, 0.0082868118f }, { -0.0013222735f, 0.0028492181f, -0.023523273f, -0.02576271f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f, 0.0f } }, { { 0.0011802354f, -0.006546101f, -0.02103972f, 0.00086540469f }, { -0.015460534f, 0.017874544f, 0.0029121134f, 0.023511773f }, { -0.040909245f, 0.011927691f, 0.011991588f, 0.01677931f }, { -0.015633544f, -0.0042321141f, 0.026623034f, 0.0080414514f }, { 0.012614382f, 0.0065080145f, 0.035716738f, -0.0080665814f }, { -0.0057849744f, -0.017478461f, -0.031219642f, 0.00016446523f }, { 0.0f, 0.00032235028f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { -0.068586697f, -0.024228236f, -0.012857221f, -0.039493706f }, { -0.018078201f, -0.015140979f, 0.00072119173f, -0.051249859f }, { -0.054228277f, 0.0097895101f, 0.0019832646f, -0.011715411f }, { -0.042326208f, -0.010160072f, 0.037088052f, -0.031848667f }, { 0.00067130897f, -0.013966717f, -0.017268559f, -0.0074614576f }, { 0.070515961f, 0.012848107f, -0.0008396517f, 0.0049006506f }, { 0.0f, 0.0f, -0.063014256f, -0.0085124986f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { -0.040302299f, 0.0048936307f, 0.0064406394f, 0.0034044871f }, { -0.010453589f, 0.0035820836f, -0.017384391f, -0.038199947f }, { -0.044968611f, -0.0088322127f, 0.020303819f, 0.0058131005f }, { -0.0056838535f, 0.010211409f, -0.010999927f, -0.027621859f }, { 0.0064753811f, -0.0059341242f, -0.014902755f, 0.0082868118f }, { -0.0013222735f, 0.0028492181f, -0.023523273f, -0.02576271f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f, 0.0f } } }, { { { 0.72189984f, 0.22069996f, 0.71952927f, 0.77725949f }, { 0.4054405f, 0.20582059f, 0.2747016f, 0.37612563f }, { 0.58887422f, 0.27441131f, 0.19468101f, 0.21480554f }, { 0.46814145f, 0.34317f, 0.46068212f, 0.13962064f }, { -0.18134132f, -0.26668789f, -0.60984999f, -0.67879259f }, { -0.47870351f, -0.34453227f, 0.32494779f, 0.10292971f }, { 0.087252967f, 0.066950358f, 0.31813819f, 0.071094818f }, { -0.0031436256f, 0.038245091f, -0.0076651913f, -0.015389479f }, { 1.2668531f, 1.2894974f, 0.40584018f, 0.51755806f }, { 1.3207257f, 1.3403747f, 0.54924634f, 0.40282713f }, { 0.78581828f, 0.56379328f, 0.27901993f, 0.56429306f }, { 0.8748226f, 1.0271253f, 1.0085726f, 0.3888545f }, { -0.22577636f, -0.32895071f, -0.2846317f, -0.11679531f }, { 0.26477285f, 0.3179447f, -0.063393238f, 0.024059773f }, { -0.15463395f, -0.22721468f, -0.20680404f, -0.15700788f }, { 0.012107106f, -0.0061245949f, -0.024224367f, 0.005040693f }, { 0.97943693f, 0.64840429f, 0.45106998f, 0.40771935f }, { 0.49907853f, 0.1562184f, 0.34338458f, 0.39710628f }, { 0.95047709f, 0.53336107f, 0.38318275f, 0.44919148f }, { 0.41892697f, 0.069965886f, 0.45831656f, 0.38821529f }, { -0.20216736f, -0.43209441f, -0.57684857f, -0.40189427f }, { -0.63992377f, -0.40683032f, -0.59207903f, -0.57251716f }, { -0.047117438f, -0.1880015f, -0.12265155f, 0.00059988607f }, { -0.011836442f, -0.010049497f, -0.0026152072f, 0.016137736f } }, { { 0.092068993f, 0.0045466749f, 0.0054574031f, 0.02582156f }, { 0.022115456f, -0.015664041f, -0.022004653f, 0.041431654f }, { 0.029951298f, -0.0004408542f, 0.0087496069f, 0.017850027f }, { 0.029086373f, 0.022116039f, 0.044010315f, 0.001644876f }, { 0.016256387f, 0.0083249367f, 0.019570849f, -0.0021276222f }, { 0.0079070076f, -0.024696939f, 0.044311101f, 0.023671132f }, { -0.0081796119f, -0.0024995551f, 0.033501743f, -0.031958988f }, { 0.0065005403f, -0.076642001f, 0.015736477f, 0.030966939f }, { 0.029110717f, 0.039154477f, -0.074376619f, 0.025532063f }, { -0.10980761f, 0.0038346834f, 0.014449171f, -0.030702653f }, { -0.00068350423f, -0.037251569f, -0.008409224f, -0.026322878f }, { 0.035406012f, 0.064176275f, 0.031437854f, -0.0344642f }, { 0.037145809f, -0.024909212f, 0.041030386f, 0.035216105f }, { -0.093276646f, -0.013904083f, -0.019536023f, -0.023834405f }, { 0.042751846f, -0.03620164f, 0.081115921f, 0.018379967f }, { -0.023909625f, 0.012833691f, 0.048086442f, -0.0097340268f }, { 0.039552712f, -0.00026806514f, 0.011646753f, 0.0065939486f }, { 0.058985248f, 0.020165701f, 0.0076721521f, 0.033274221f }, { 0.052889871f, 0.0042520093f, 0.016490396f, 0.009287973f }, { 0.044305975f, -0.0016263469f, 0.041390177f, 0.033541355f }, { 0.014595133f, -0.004801042f, -0.0049517302f, 0.015714264f }, { 0.00075086205f, 0.0080838736f, -0.037611057f, -0.030488441f }, { 0.0019178075f, -0.0082517768f, -0.002525773f, 0.0043993022f }, { 0.023774971f, 0.020335611f, 0.0056643868f, -0.032100338f } }, { { 0.092068993f, 0.0045466749f, 0.0054574031f, 0.02582156f }, { 0.022115456f, -0.015664041f, -0.022004653f, 0.041431654f }, { 0.029951298f, -0.0004408542f, 0.0087496069f, 0.017850027f }, { 0.029086373f, 0.022116039f, 0.044010315f, 0.001644876f }, { 0.016256387f, 0.0083249367f, 0.019570849f, -0.0021276222f }, { 0.0079070076f, -0.024696939f, 0.044311101f, 0.023671132f }, { -0.0081796119f, -0.0024995551f, 0.033501743f, -0.031958988f }, { 0.0065005403f, -0.076642001f, 0.015736477f, 0.030966939f }, { 0.029110717f, 0.039154477f, -0.074376619f, 0.025532063f }, { -0.10980761f, 0.0038346834f, 0.014449171f, -0.030702653f }, { -0.00068350423f, -0.037251569f, -0.008409224f, -0.026322878f }, { 0.035406012f, 0.064176275f, 0.031437854f, -0.0344642f }, { 0.037145809f, -0.024909212f, 0.041030386f, 0.035216105f }, { -0.093276646f, -0.013904083f, -0.019536023f, -0.023834405f }, { 0.042751846f, -0.03620164f, 0.081115921f, 0.018379967f }, { -0.023909625f, 0.012833691f, 0.048086442f, -0.0097340268f }, { 0.039552712f, -0.00026806514f, 0.011646753f, 0.0065939486f }, { 0.058985248f, 0.020165701f, 0.0076721521f, 0.033274221f }, { 0.052889871f, 0.0042520093f, 0.016490396f, 0.009287973f }, { 0.044305975f, -0.0016263469f, 0.041390177f, 0.033541355f }, { 0.014595133f, -0.004801042f, -0.0049517303f, 0.015714264f }, { 0.00075086205f, 0.0080838736f, -0.037611057f, -0.030488441f }, { 0.0019178075f, -0.0082517768f, -0.002525773f, 0.0043993022f }, { 0.023774971f, 0.020335611f, 0.0056643868f, -0.032100338f } } } } };
#endif
diff --git a/thirdparty/misc/hq2x.cpp b/thirdparty/misc/hq2x.cpp
deleted file mode 100644
index 9c089ba85c..0000000000
--- a/thirdparty/misc/hq2x.cpp
+++ /dev/null
@@ -1,2636 +0,0 @@
-/*
- * Copyright 2016 Bruno Ribeiro
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-#include "hq2x.h"
-
-#include "core/math/math_funcs.h"
-
-static const uint32_t AMASK = 0xFF000000;
-static const uint32_t YMASK = 0x00FF0000;
-static const uint32_t UMASK = 0x0000FF00;
-static const uint32_t VMASK = 0x000000FF;
-
-_FORCE_INLINE_ static uint32_t ARGBtoAYUV(
- uint32_t value )
-{
- uint32_t A, R, G, B, Y, U, V;
-//todo big endian check
- A = value >> 24;
- R = (value >> 16) & 0xFF;
- G = (value >> 8) & 0xFF;
- B = value & 0xFF;
-
- Y = Math::fast_ftoi( 0.299 * R + 0.587 * G + 0.114 * B);
- U = Math::fast_ftoi(-0.169 * R - 0.331 * G + 0.5 * B) + 128;
- V = Math::fast_ftoi( 0.5 * R - 0.419 * G - 0.081 * B) + 128;
- return (A << 24) + (Y << 16) + (U << 8) + V;
-}
-
-
-/*
- * Use this function for sharper images (good for cartoon style, used by DOSBOX)
- */
-
-_FORCE_INLINE_ static bool isDifferent(
- uint32_t color1,
- uint32_t color2,
- uint32_t trY,
- uint32_t trU,
- uint32_t trV,
- uint32_t trA )
-{
- color1 = ARGBtoAYUV(color1);
- color2 = ARGBtoAYUV(color2);
-
- uint32_t value;
-
- value = ((color1 & YMASK) - (color2 & YMASK));
- value = (value ^ (value >> 31)) - (value >> 31);
- if (value > trY) return true;
-
- value = ((color1 & UMASK) - (color2 & UMASK));
- value = (value ^ (value >> 31)) - (value >> 31);
- if (value > trU) return true;
-
- value = ((color1 & VMASK) - (color2 & VMASK));
- value = (value ^ (value >> 31)) - (value >> 31);
- if (value > trV) return true;
-
- value = ((color1 & AMASK) - (color2 & AMASK));
- value = (value ^ (value >> 31)) - (value >> 31);
- if (value > trA) return true;
-
- return false;
-
-}
-
-
-
-#define MASK_RB 0x00FF00FF
-#define MASK_G 0x0000FF00
-#define MASK_A 0xFF000000
-
-
-/**
- * @brief Mixes two colors using the given weights.
- */
-#define HQX_MIX_2(C0,C1,W0,W1) \
- ((((C0 & MASK_RB) * W0 + (C1 & MASK_RB) * W1) / (W0 + W1)) & MASK_RB) | \
- ((((C0 & MASK_G) * W0 + (C1 & MASK_G) * W1) / (W0 + W1)) & MASK_G) | \
- ((((((C0 & MASK_A) >> 8) * W0 + ((C1 & MASK_A) >> 8) * W1) / (W0 + W1)) << 8) & MASK_A)
-
-/**
- * @brief Mixes three colors using the given weights.
- */
-#define HQX_MIX_3(C0,C1,C2,W0,W1,W2) \
- ((((C0 & MASK_RB) * W0 + (C1 & MASK_RB) * W1 + (C2 & MASK_RB) * W2) / (W0 + W1 + W2)) & MASK_RB) | \
- ((((C0 & MASK_G) * W0 + (C1 & MASK_G) * W1 + (C2 & MASK_G) * W2) / (W0 + W1 + W2)) & MASK_G) | \
- ((((((C0 & MASK_A) >> 8) * W0 + ((C1 & MASK_A) >> 8) * W1 + ((C2 & MASK_A) >> 8) * W2) / (W0 + W1 + W2)) << 8) & MASK_A)
-
-
-#define MIX_00_4 *output = w[4];
-#define MIX_00_MIX_00_4_0_3_1 *output = HQX_MIX_2(w[4],w[0],3U,1U);
-#define MIX_00_4_3_3_1 *output = HQX_MIX_2(w[4],w[3],3U,1U);
-#define MIX_00_4_1_3_1 *output = HQX_MIX_2(w[4],w[1],3U,1U);
-#define MIX_00_3_1_1_1 *output = HQX_MIX_2(w[3],w[1],1U,1U);
-#define MIX_00_4_3_1_2_1_1 *output = HQX_MIX_3(w[4],w[3],w[1],2U,1U,1U);
-#define MIX_00_4_3_1_2_7_7 *output = HQX_MIX_3(w[4],w[3],w[1],2U,7U,7U);
-#define MIX_00_4_0_1_2_1_1 *output = HQX_MIX_3(w[4],w[0],w[1],2U,1U,1U);
-#define MIX_00_4_0_3_2_1_1 *output = HQX_MIX_3(w[4],w[0],w[3],2U,1U,1U);
-#define MIX_00_4_1_3_5_2_1 *output = HQX_MIX_3(w[4],w[1],w[3],5U,2U,1U);
-#define MIX_00_4_3_1_5_2_1 *output = HQX_MIX_3(w[4],w[3],w[1],5U,2U,1U);
-#define MIX_00_4_3_1_6_1_1 *output = HQX_MIX_3(w[4],w[3],w[1],6U,1U,1U);
-#define MIX_00_4_3_1_2_3_3 *output = HQX_MIX_3(w[4],w[3],w[1],2U,3U,3U);
-#define MIX_00_MIX_00_4_0_3_10 *output = HQX_MIX_3(w[4],w[3],w[1],14U,1U,1U);
-
-#define MIX_01_4 *(output + 1) = w[4];
-#define MIX_01_4_2_3_1 *(output + 1) = HQX_MIX_2(w[4],w[2],3U,1U);
-#define MIX_01_4_1_3_1 *(output + 1) = HQX_MIX_2(w[4],w[1],3U,1U);
-#define MIX_01_1_4_3_1 *(output + 1) = HQX_MIX_2(w[1],w[4],3U,1U);
-#define MIX_01_4_5_3_1 *(output + 1) = HQX_MIX_2(w[4],w[5],3U,1U);
-#define MIX_01_4_1_7_1 *(output + 1) = HQX_MIX_2(w[4],w[1],7U,1U);
-#define MIX_01_4_1_5_2_1_1 *(output + 1) = HQX_MIX_3(w[4],w[1],w[5],2U,1U,1U);
-#define MIX_01_4_2_5_2_1_1 *(output + 1) = HQX_MIX_3(w[4],w[2],w[5],2U,1U,1U);
-#define MIX_01_4_2_1_2_1_1 *(output + 1) = HQX_MIX_3(w[4],w[2],w[1],2U,1U,1U);
-#define MIX_01_4_5_1_5_2_1 *(output + 1) = HQX_MIX_3(w[4],w[5],w[1],5U,2U,1U);
-#define MIX_01_4_1_5_5_2_1 *(output + 1) = HQX_MIX_3(w[4],w[1],w[5],5U,2U,1U);
-#define MIX_01_4_1_5_6_1_1 *(output + 1) = HQX_MIX_3(w[4],w[1],w[5],6U,1U,1U);
-#define MIX_01_4_1_5_2_3_3 *(output + 1) = HQX_MIX_3(w[4],w[1],w[5],2U,3U,3U);
-#define MIX_01_4_2_3_10 *(output + 1) = HQX_MIX_3(w[4],w[1],w[5],14U,1U,1U);
-
-#define MIX_02_4 *(output + 2) = w[4];
-#define MIX_02_4_2_3_1 *(output + 2) = HQX_MIX_2(w[4],w[2],3U,1U);
-#define MIX_02_4_1_3_1 *(output + 2) = HQX_MIX_2(w[4],w[1],3U,1U);
-#define MIX_02_4_5_3_1 *(output + 2) = HQX_MIX_2(w[4],w[5],3U,1U);
-#define MIX_02_4_1_5_2_1_1 *(output + 2) = HQX_MIX_3(w[4],w[1],w[5],2U,1U,1U);
-#define MIX_02_4_1_5_2_7_7 *(output + 2) = HQX_MIX_3(w[4],w[1],w[5],2U,7U,7U);
-#define MIX_02_1_5_1_1 *(output + 2) = HQX_MIX_2(w[1],w[5],1U,1U);
-
-#define MIX_10_4 *(output + lineSize) = w[4];
-#define MIX_10_4_6_3_1 *(output + lineSize) = HQX_MIX_2(w[4],w[6],3U,1U);
-#define MIX_10_4_7_3_1 *(output + lineSize) = HQX_MIX_2(w[4],w[7],3U,1U);
-#define MIX_10_4_3_3_1 *(output + lineSize) = HQX_MIX_2(w[4],w[3],3U,1U);
-#define MIX_10_4_7_3_2_1_1 *(output + lineSize) = HQX_MIX_3(w[4],w[7],w[3],2U,1U,1U);
-#define MIX_10_4_6_3_2_1_1 *(output + lineSize) = HQX_MIX_3(w[4],w[6],w[3],2U,1U,1U);
-#define MIX_10_4_6_7_2_1_1 *(output + lineSize) = HQX_MIX_3(w[4],w[6],w[7],2U,1U,1U);
-#define MIX_10_4_3_7_5_2_1 *(output + lineSize) = HQX_MIX_3(w[4],w[3],w[7],5U,2U,1U);
-#define MIX_10_4_7_3_5_2_1 *(output + lineSize) = HQX_MIX_3(w[4],w[7],w[3],5U,2U,1U);
-#define MIX_10_4_7_3_6_1_1 *(output + lineSize) = HQX_MIX_3(w[4],w[7],w[3],6U,1U,1U);
-#define MIX_10_4_7_3_2_3_3 *(output + lineSize) = HQX_MIX_3(w[4],w[7],w[3],2U,3U,3U);
-#define MIX_10_4_6_3_10 *(output + lineSize) = HQX_MIX_3(w[4],w[7],w[3],14U,1U,1U);
-#define MIX_10_4_3_7_1 *(output + lineSize) = HQX_MIX_2(w[4],w[3],7U,1U);
-#define MIX_10_3_4_3_1 *(output + lineSize) = HQX_MIX_2(w[3],w[4],3U,1U);
-
-#define MIX_11_4 *(output + lineSize + 1) = w[4];
-#define MIX_11_4_8_3_1 *(output + lineSize + 1) = HQX_MIX_2(w[4],w[8],3U,1U);
-#define MIX_11_4_5_3_1 *(output + lineSize + 1) = HQX_MIX_2(w[4],w[5],3U,1U);
-#define MIX_11_4_7_3_1 *(output + lineSize + 1) = HQX_MIX_2(w[4],w[7],3U,1U);
-#define MIX_11_4_5_7_2_1_1 *(output + lineSize + 1) = HQX_MIX_3(w[4],w[5],w[7],2U,1U,1U);
-#define MIX_11_4_8_7_2_1_1 *(output + lineSize + 1) = HQX_MIX_3(w[4],w[8],w[7],2U,1U,1U);
-#define MIX_11_4_8_5_2_1_1 *(output + lineSize + 1) = HQX_MIX_3(w[4],w[8],w[5],2U,1U,1U);
-#define MIX_11_4_7_5_5_2_1 *(output + lineSize + 1) = HQX_MIX_3(w[4],w[7],w[5],5U,2U,1U);
-#define MIX_11_4_5_7_5_2_1 *(output + lineSize + 1) = HQX_MIX_3(w[4],w[5],w[7],5U,2U,1U);
-#define MIX_11_4_5_7_6_1_1 *(output + lineSize + 1) = HQX_MIX_3(w[4],w[5],w[7],6U,1U,1U);
-#define MIX_11_4_5_7_2_3_3 *(output + lineSize + 1) = HQX_MIX_3(w[4],w[5],w[7],2U,3U,3U);
-#define MIX_11_4_8_3_10 *(output + lineSize + 1) = HQX_MIX_3(w[4],w[5],w[7],14U,1U,1U);
-
-#define MIX_12_4 *(output + lineSize + 2) = w[4];
-#define MIX_12_4_5_3_1 *(output + lineSize + 2) = HQX_MIX_2(w[4],w[5],3U,1U);
-#define MIX_12_4_5_7_1 *(output + lineSize + 2) = HQX_MIX_2(w[4],w[5],7U,1U);
-#define MIX_12_5_4_3_1 *(output + lineSize + 2) = HQX_MIX_2(w[5],w[4],3U,1U);
-
-#define MIX_20_4 *(output + lineSize + lineSize) = w[4];
-#define MIX_20_4_6_3_1 *(output + lineSize + lineSize) = HQX_MIX_2(w[4],w[6],3U,1U);
-#define MIX_20_4_7_3_1 *(output + lineSize + lineSize) = HQX_MIX_2(w[4],w[7],3U,1U);
-#define MIX_20_4_3_3_1 *(output + lineSize + lineSize) = HQX_MIX_2(w[4],w[3],3U,1U);
-#define MIX_20_4_7_3_2_1_1 *(output + lineSize + lineSize) = HQX_MIX_3(w[4],w[7],w[3],2U,1U,1U);
-#define MIX_20_4_7_3_2_7_7 *(output + lineSize + lineSize) = HQX_MIX_3(w[4],w[7],w[3],2U,7U,7U);
-#define MIX_20_7_3_1_1 *(output + lineSize + lineSize) = HQX_MIX_2(w[7],w[3],1U,1U);
-
-#define MIX_21_4 *(output + lineSize + lineSize + 1) = w[4];
-#define MIX_21_4_7_3_1 *(output + lineSize + lineSize + 1) = HQX_MIX_2(w[4],w[7],3U,1U);
-#define MIX_21_4_7_7_1 *(output + lineSize + lineSize + 1) = HQX_MIX_2(w[4],w[7],7U,1U);
-#define MIX_21_7_4_3_1 *(output + lineSize + lineSize + 1) = HQX_MIX_2(w[7],w[4],3U,1U);
-
-#define MIX_22_4 *(output + lineSize + lineSize + 2) = w[4];
-#define MIX_22_4_8_3_1 *(output + lineSize + lineSize + 2) = HQX_MIX_2(w[4],w[8],3U,1U);
-#define MIX_22_4_7_3_1 *(output + lineSize + lineSize + 2) = HQX_MIX_2(w[4],w[7],3U,1U);
-#define MIX_22_4_5_3_1 *(output + lineSize + lineSize + 2) = HQX_MIX_2(w[4],w[5],3U,1U);
-#define MIX_22_4_5_7_2_1_1 *(output + lineSize + lineSize + 2) = HQX_MIX_3(w[4],w[5],w[7],2U,1U,1U);
-#define MIX_22_4_5_7_2_7_7 *(output + lineSize + lineSize + 2) = HQX_MIX_3(w[4],w[5],w[7],2U,7U,7U);
-#define MIX_22_5_7_1_1 *(output + lineSize + lineSize + 2) = HQX_MIX_2(w[5],w[7],1U,1U);
-
-
-
-uint32_t *hq2x_resize(
- const uint32_t *image,
- uint32_t width,
- uint32_t height,
- uint32_t *output,
- uint32_t trY,
- uint32_t trU,
- uint32_t trV,
- uint32_t trA,
- bool wrapX,
- bool wrapY )
-{
- int lineSize = width * 2;
-
- int previous, next;
- uint32_t w[9];
-
- trY <<= 16;
- trU <<= 8;
- trA <<= 24;
-
- // iterates between the lines
- for (uint32_t row = 0; row < height; row++)
- {
- /*
- * Note: this function uses a 3x3 sliding window over the original image.
- *
- * +----+----+----+
- * | | | |
- * | w0 | w1 | w2 |
- * +----+----+----+
- * | | | |
- * | w3 | w4 | w5 |
- * +----+----+----+
- * | | | |
- * | w6 | w7 | w8 |
- * +----+----+----+
- */
-
- // adjusts the previous and next line pointers
- if (row > 0)
- previous = -width;
- else
- {
- if (wrapY)
- previous = width * (height - 1);
- else
- previous = 0;
- }
- if (row < height - 1)
- next = width;
- else
- {
- if (wrapY)
- next = -(width * (height - 1));
- else
- next = 0;
- }
-
- // iterates between the columns
- for (uint32_t col = 0; col < width; col++)
- {
- w[1] = *(image + previous);
- w[4] = *image;
- w[7] = *(image + next);
-
- if (col > 0)
- {
- w[0] = *(image + previous - 1);
- w[3] = *(image - 1);
- w[6] = *(image + next - 1);
- }
- else
- {
- if (wrapX)
- {
- w[0] = *(image + previous + width - 1);
- w[3] = *(image + width - 1);
- w[6] = *(image + next + width - 1);
- }
- else
- {
- w[0] = w[1];
- w[3] = w[4];
- w[6] = w[7];
- }
- }
-
- if (col < width - 1)
- {
- w[2] = *(image + previous + 1);
- w[5] = *(image + 1);
- w[8] = *(image + next + 1);
- }
- else
- {
- if (wrapX)
- {
- w[2] = *(image + previous - width + 1);
- w[5] = *(image - width + 1);
- w[8] = *(image + next - width + 1);
- }
- else
- {
- w[2] = w[1];
- w[5] = w[4];
- w[8] = w[7];
- }
- }
-
- int pattern = 0;
-
- // computes the pattern to be used considering the neighbor pixels
- for (int k = 0, flag = 1; k < 9; k++)
- {
- // ignores the central pixel
- if (k == 4) continue;
-
- if (w[k] != w[4])
- if (isDifferent(w[4], w[k], trY, trU, trV, trA)) pattern |= flag;
- flag <<= 1;
- }
-
- switch (pattern)
- {
- case 0:
- case 1:
- case 4:
- case 32:
- case 128:
- case 5:
- case 132:
- case 160:
- case 33:
- case 129:
- case 36:
- case 133:
- case 164:
- case 161:
- case 37:
- case 165:
- MIX_00_4_3_1_2_1_1
- MIX_01_4_1_5_2_1_1
- MIX_10_4_7_3_2_1_1
- MIX_11_4_5_7_2_1_1
- break;
- case 2:
- case 34:
- case 130:
- case 162:
- MIX_00_4_0_3_2_1_1
- MIX_01_4_2_5_2_1_1
- MIX_10_4_7_3_2_1_1
- MIX_11_4_5_7_2_1_1
- break;
- case 16:
- case 17:
- case 48:
- case 49:
- MIX_00_4_3_1_2_1_1
- MIX_01_4_2_1_2_1_1
- MIX_10_4_7_3_2_1_1
- MIX_11_4_8_7_2_1_1
- break;
- case 64:
- case 65:
- case 68:
- case 69:
- MIX_00_4_3_1_2_1_1
- MIX_01_4_1_5_2_1_1
- MIX_10_4_6_3_2_1_1
- MIX_11_4_8_5_2_1_1
- break;
- case 8:
- case 12:
- case 136:
- case 140:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_1_5_2_1_1
- MIX_10_4_6_7_2_1_1
- MIX_11_4_5_7_2_1_1
- break;
- case 3:
- case 35:
- case 131:
- case 163:
- MIX_00_4_3_3_1
- MIX_01_4_2_5_2_1_1
- MIX_10_4_7_3_2_1_1
- MIX_11_4_5_7_2_1_1
- break;
- case 6:
- case 38:
- case 134:
- case 166:
- MIX_00_4_0_3_2_1_1
- MIX_01_4_5_3_1
- MIX_10_4_7_3_2_1_1
- MIX_11_4_5_7_2_1_1
- break;
- case 20:
- case 21:
- case 52:
- case 53:
- MIX_00_4_3_1_2_1_1
- MIX_01_4_1_3_1
- MIX_10_4_7_3_2_1_1
- MIX_11_4_8_7_2_1_1
- break;
- case 144:
- case 145:
- case 176:
- case 177:
- MIX_00_4_3_1_2_1_1
- MIX_01_4_2_1_2_1_1
- MIX_10_4_7_3_2_1_1
- MIX_11_4_7_3_1
- break;
- case 192:
- case 193:
- case 196:
- case 197:
- MIX_00_4_3_1_2_1_1
- MIX_01_4_1_5_2_1_1
- MIX_10_4_6_3_2_1_1
- MIX_11_4_5_3_1
- break;
- case 96:
- case 97:
- case 100:
- case 101:
- MIX_00_4_3_1_2_1_1
- MIX_01_4_1_5_2_1_1
- MIX_10_4_3_3_1
- MIX_11_4_8_5_2_1_1
- break;
- case 40:
- case 44:
- case 168:
- case 172:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_1_5_2_1_1
- MIX_10_4_7_3_1
- MIX_11_4_5_7_2_1_1
- break;
- case 9:
- case 13:
- case 137:
- case 141:
- MIX_00_4_1_3_1
- MIX_01_4_1_5_2_1_1
- MIX_10_4_6_7_2_1_1
- MIX_11_4_5_7_2_1_1
- break;
- case 18:
- case 50:
- MIX_00_4_0_3_2_1_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4_2_3_1
- }
- else
- {
- MIX_01_4_1_5_2_1_1
- }
- MIX_10_4_7_3_2_1_1
- MIX_11_4_8_7_2_1_1
- break;
- case 80:
- case 81:
- MIX_00_4_3_1_2_1_1
- MIX_01_4_2_1_2_1_1
- MIX_10_4_6_3_2_1_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4_8_3_1
- }
- else
- {
- MIX_11_4_5_7_2_1_1
- }
- break;
- case 72:
- case 76:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_1_5_2_1_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4_6_3_1
- }
- else
- {
- MIX_10_4_7_3_2_1_1
- }
- MIX_11_4_8_5_2_1_1
- break;
- case 10:
- case 138:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_MIX_00_4_0_3_1
- }
- else
- {
- MIX_00_4_3_1_2_1_1
- }
- MIX_01_4_2_5_2_1_1
- MIX_10_4_6_7_2_1_1
- MIX_11_4_5_7_2_1_1
- break;
- case 66:
- MIX_00_4_0_3_2_1_1
- MIX_01_4_2_5_2_1_1
- MIX_10_4_6_3_2_1_1
- MIX_11_4_8_5_2_1_1
- break;
- case 24:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_2_1_2_1_1
- MIX_10_4_6_7_2_1_1
- MIX_11_4_8_7_2_1_1
- break;
- case 7:
- case 39:
- case 135:
- MIX_00_4_3_3_1
- MIX_01_4_5_3_1
- MIX_10_4_7_3_2_1_1
- MIX_11_4_5_7_2_1_1
- break;
- case 148:
- case 149:
- case 180:
- MIX_00_4_3_1_2_1_1
- MIX_01_4_1_3_1
- MIX_10_4_7_3_2_1_1
- MIX_11_4_7_3_1
- break;
- case 224:
- case 228:
- case 225:
- MIX_00_4_3_1_2_1_1
- MIX_01_4_1_5_2_1_1
- MIX_10_4_3_3_1
- MIX_11_4_5_3_1
- break;
- case 41:
- case 169:
- case 45:
- MIX_00_4_1_3_1
- MIX_01_4_1_5_2_1_1
- MIX_10_4_7_3_1
- MIX_11_4_5_7_2_1_1
- break;
- case 22:
- case 54:
- MIX_00_4_0_3_2_1_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_1_5_2_1_1
- }
- MIX_10_4_7_3_2_1_1
- MIX_11_4_8_7_2_1_1
- break;
- case 208:
- case 209:
- MIX_00_4_3_1_2_1_1
- MIX_01_4_2_1_2_1_1
- MIX_10_4_6_3_2_1_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_5_7_2_1_1
- }
- break;
- case 104:
- case 108:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_1_5_2_1_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_7_3_2_1_1
- }
- MIX_11_4_8_5_2_1_1
- break;
- case 11:
- case 139:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_4_3_1_2_1_1
- }
- MIX_01_4_2_5_2_1_1
- MIX_10_4_6_7_2_1_1
- MIX_11_4_5_7_2_1_1
- break;
- case 19:
- case 51:
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_00_4_3_3_1
- MIX_01_4_2_3_1
- }
- else
- {
- MIX_00_4_1_3_5_2_1
- MIX_01_4_1_5_2_3_3
- }
- MIX_10_4_7_3_2_1_1
- MIX_11_4_8_7_2_1_1
- break;
- case 146:
- case 178:
- MIX_00_4_0_3_2_1_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4_2_3_1
- MIX_11_4_7_3_1
- }
- else
- {
- MIX_01_4_1_5_2_3_3
- MIX_11_4_5_7_5_2_1
- }
- MIX_10_4_7_3_2_1_1
- break;
- case 84:
- case 85:
- MIX_00_4_3_1_2_1_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_01_4_1_3_1
- MIX_11_4_8_3_1
- }
- else
- {
- MIX_01_4_5_1_5_2_1
- MIX_11_4_5_7_2_3_3
- }
- MIX_10_4_6_3_2_1_1
- break;
- case 112:
- case 113:
- MIX_00_4_3_1_2_1_1
- MIX_01_4_2_1_2_1_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_10_4_3_3_1
- MIX_11_4_8_3_1
- }
- else
- {
- MIX_10_4_7_3_5_2_1
- MIX_11_4_5_7_2_3_3
- }
- break;
- case 200:
- case 204:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_1_5_2_1_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4_6_3_1
- MIX_11_4_5_3_1
- }
- else
- {
- MIX_10_4_7_3_2_3_3
- MIX_11_4_7_5_5_2_1
- }
- break;
- case 73:
- case 77:
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_00_4_1_3_1
- MIX_10_4_6_3_1
- }
- else
- {
- MIX_00_4_3_1_5_2_1
- MIX_10_4_7_3_2_3_3
- }
- MIX_01_4_1_5_2_1_1
- MIX_11_4_8_5_2_1_1
- break;
- case 42:
- case 170:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_MIX_00_4_0_3_1
- MIX_10_4_7_3_1
- }
- else
- {
- MIX_00_4_3_1_2_3_3
- MIX_10_4_3_7_5_2_1
- }
- MIX_01_4_2_5_2_1_1
- MIX_11_4_5_7_2_1_1
- break;
- case 14:
- case 142:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_MIX_00_4_0_3_1
- MIX_01_4_5_3_1
- }
- else
- {
- MIX_00_4_3_1_2_3_3
- MIX_01_4_1_5_5_2_1
- }
- MIX_10_4_6_7_2_1_1
- MIX_11_4_5_7_2_1_1
- break;
- case 67:
- MIX_00_4_3_3_1
- MIX_01_4_2_5_2_1_1
- MIX_10_4_6_3_2_1_1
- MIX_11_4_8_5_2_1_1
- break;
- case 70:
- MIX_00_4_0_3_2_1_1
- MIX_01_4_5_3_1
- MIX_10_4_6_3_2_1_1
- MIX_11_4_8_5_2_1_1
- break;
- case 28:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_1_3_1
- MIX_10_4_6_7_2_1_1
- MIX_11_4_8_7_2_1_1
- break;
- case 152:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_2_1_2_1_1
- MIX_10_4_6_7_2_1_1
- MIX_11_4_7_3_1
- break;
- case 194:
- MIX_00_4_0_3_2_1_1
- MIX_01_4_2_5_2_1_1
- MIX_10_4_6_3_2_1_1
- MIX_11_4_5_3_1
- break;
- case 98:
- MIX_00_4_0_3_2_1_1
- MIX_01_4_2_5_2_1_1
- MIX_10_4_3_3_1
- MIX_11_4_8_5_2_1_1
- break;
- case 56:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_2_1_2_1_1
- MIX_10_4_7_3_1
- MIX_11_4_8_7_2_1_1
- break;
- case 25:
- MIX_00_4_1_3_1
- MIX_01_4_2_1_2_1_1
- MIX_10_4_6_7_2_1_1
- MIX_11_4_8_7_2_1_1
- break;
- case 26:
- case 31:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_4_3_1_2_1_1
- }
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_1_5_2_1_1
- }
- MIX_10_4_6_7_2_1_1
- MIX_11_4_8_7_2_1_1
- break;
- case 82:
- case 214:
- MIX_00_4_0_3_2_1_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_1_5_2_1_1
- }
- MIX_10_4_6_3_2_1_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_5_7_2_1_1
- }
- break;
- case 88:
- case 248:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_2_1_2_1_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_7_3_2_1_1
- }
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_5_7_2_1_1
- }
- break;
- case 74:
- case 107:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_4_3_1_2_1_1
- }
- MIX_01_4_2_5_2_1_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_7_3_2_1_1
- }
- MIX_11_4_8_5_2_1_1
- break;
- case 27:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_4_3_1_2_1_1
- }
- MIX_01_4_2_3_1
- MIX_10_4_6_7_2_1_1
- MIX_11_4_8_7_2_1_1
- break;
- case 86:
- MIX_00_4_0_3_2_1_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_1_5_2_1_1
- }
- MIX_10_4_6_3_2_1_1
- MIX_11_4_8_3_1
- break;
- case 216:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_2_1_2_1_1
- MIX_10_4_6_3_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_5_7_2_1_1
- }
- break;
- case 106:
- MIX_00_MIX_00_4_0_3_1
- MIX_01_4_2_5_2_1_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_7_3_2_1_1
- }
- MIX_11_4_8_5_2_1_1
- break;
- case 30:
- MIX_00_MIX_00_4_0_3_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_1_5_2_1_1
- }
- MIX_10_4_6_7_2_1_1
- MIX_11_4_8_7_2_1_1
- break;
- case 210:
- MIX_00_4_0_3_2_1_1
- MIX_01_4_2_3_1
- MIX_10_4_6_3_2_1_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_5_7_2_1_1
- }
- break;
- case 120:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_2_1_2_1_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_7_3_2_1_1
- }
- MIX_11_4_8_3_1
- break;
- case 75:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_4_3_1_2_1_1
- }
- MIX_01_4_2_5_2_1_1
- MIX_10_4_6_3_1
- MIX_11_4_8_5_2_1_1
- break;
- case 29:
- MIX_00_4_1_3_1
- MIX_01_4_1_3_1
- MIX_10_4_6_7_2_1_1
- MIX_11_4_8_7_2_1_1
- break;
- case 198:
- MIX_00_4_0_3_2_1_1
- MIX_01_4_5_3_1
- MIX_10_4_6_3_2_1_1
- MIX_11_4_5_3_1
- break;
- case 184:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_2_1_2_1_1
- MIX_10_4_7_3_1
- MIX_11_4_7_3_1
- break;
- case 99:
- MIX_00_4_3_3_1
- MIX_01_4_2_5_2_1_1
- MIX_10_4_3_3_1
- MIX_11_4_8_5_2_1_1
- break;
- case 57:
- MIX_00_4_1_3_1
- MIX_01_4_2_1_2_1_1
- MIX_10_4_7_3_1
- MIX_11_4_8_7_2_1_1
- break;
- case 71:
- MIX_00_4_3_3_1
- MIX_01_4_5_3_1
- MIX_10_4_6_3_2_1_1
- MIX_11_4_8_5_2_1_1
- break;
- case 156:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_1_3_1
- MIX_10_4_6_7_2_1_1
- MIX_11_4_7_3_1
- break;
- case 226:
- MIX_00_4_0_3_2_1_1
- MIX_01_4_2_5_2_1_1
- MIX_10_4_3_3_1
- MIX_11_4_5_3_1
- break;
- case 60:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_1_3_1
- MIX_10_4_7_3_1
- MIX_11_4_8_7_2_1_1
- break;
- case 195:
- MIX_00_4_3_3_1
- MIX_01_4_2_5_2_1_1
- MIX_10_4_6_3_2_1_1
- MIX_11_4_5_3_1
- break;
- case 102:
- MIX_00_4_0_3_2_1_1
- MIX_01_4_5_3_1
- MIX_10_4_3_3_1
- MIX_11_4_8_5_2_1_1
- break;
- case 153:
- MIX_00_4_1_3_1
- MIX_01_4_2_1_2_1_1
- MIX_10_4_6_7_2_1_1
- MIX_11_4_7_3_1
- break;
- case 58:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_MIX_00_4_0_3_1
- }
- else
- {
- MIX_00_4_3_1_6_1_1
- }
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4_2_3_1
- }
- else
- {
- MIX_01_4_1_5_6_1_1
- }
- MIX_10_4_7_3_1
- MIX_11_4_8_7_2_1_1
- break;
- case 83:
- MIX_00_4_3_3_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4_2_3_1
- }
- else
- {
- MIX_01_4_1_5_6_1_1
- }
- MIX_10_4_6_3_2_1_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4_8_3_1
- }
- else
- {
- MIX_11_4_5_7_6_1_1
- }
- break;
- case 92:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_1_3_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4_6_3_1
- }
- else
- {
- MIX_10_4_7_3_6_1_1
- }
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4_8_3_1
- }
- else
- {
- MIX_11_4_5_7_6_1_1
- }
- break;
- case 202:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_MIX_00_4_0_3_1
- }
- else
- {
- MIX_00_4_3_1_6_1_1
- }
- MIX_01_4_2_5_2_1_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4_6_3_1
- }
- else
- {
- MIX_10_4_7_3_6_1_1
- }
- MIX_11_4_5_3_1
- break;
- case 78:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_MIX_00_4_0_3_1
- }
- else
- {
- MIX_00_4_3_1_6_1_1
- }
- MIX_01_4_5_3_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4_6_3_1
- }
- else
- {
- MIX_10_4_7_3_6_1_1
- }
- MIX_11_4_8_5_2_1_1
- break;
- case 154:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_MIX_00_4_0_3_1
- }
- else
- {
- MIX_00_4_3_1_6_1_1
- }
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4_2_3_1
- }
- else
- {
- MIX_01_4_1_5_6_1_1
- }
- MIX_10_4_6_7_2_1_1
- MIX_11_4_7_3_1
- break;
- case 114:
- MIX_00_4_0_3_2_1_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4_2_3_1
- }
- else
- {
- MIX_01_4_1_5_6_1_1
- }
- MIX_10_4_3_3_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4_8_3_1
- }
- else
- {
- MIX_11_4_5_7_6_1_1
- }
- break;
- case 89:
- MIX_00_4_1_3_1
- MIX_01_4_2_1_2_1_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4_6_3_1
- }
- else
- {
- MIX_10_4_7_3_6_1_1
- }
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4_8_3_1
- }
- else
- {
- MIX_11_4_5_7_6_1_1
- }
- break;
- case 90:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_MIX_00_4_0_3_1
- }
- else
- {
- MIX_00_4_3_1_6_1_1
- }
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4_2_3_1
- }
- else
- {
- MIX_01_4_1_5_6_1_1
- }
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4_6_3_1
- }
- else
- {
- MIX_10_4_7_3_6_1_1
- }
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4_8_3_1
- }
- else
- {
- MIX_11_4_5_7_6_1_1
- }
- break;
- case 55:
- case 23:
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_00_4_3_3_1
- MIX_01_4
- }
- else
- {
- MIX_00_4_1_3_5_2_1
- MIX_01_4_1_5_2_3_3
- }
- MIX_10_4_7_3_2_1_1
- MIX_11_4_8_7_2_1_1
- break;
- case 182:
- case 150:
- MIX_00_4_0_3_2_1_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- MIX_11_4_7_3_1
- }
- else
- {
- MIX_01_4_1_5_2_3_3
- MIX_11_4_5_7_5_2_1
- }
- MIX_10_4_7_3_2_1_1
- break;
- case 213:
- case 212:
- MIX_00_4_3_1_2_1_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_01_4_1_3_1
- MIX_11_4
- }
- else
- {
- MIX_01_4_5_1_5_2_1
- MIX_11_4_5_7_2_3_3
- }
- MIX_10_4_6_3_2_1_1
- break;
- case 241:
- case 240:
- MIX_00_4_3_1_2_1_1
- MIX_01_4_2_1_2_1_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_10_4_3_3_1
- MIX_11_4
- }
- else
- {
- MIX_10_4_7_3_5_2_1
- MIX_11_4_5_7_2_3_3
- }
- break;
- case 236:
- case 232:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_1_5_2_1_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- MIX_11_4_5_3_1
- }
- else
- {
- MIX_10_4_7_3_2_3_3
- MIX_11_4_7_5_5_2_1
- }
- break;
- case 109:
- case 105:
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_00_4_1_3_1
- MIX_10_4
- }
- else
- {
- MIX_00_4_3_1_5_2_1
- MIX_10_4_7_3_2_3_3
- }
- MIX_01_4_1_5_2_1_1
- MIX_11_4_8_5_2_1_1
- break;
- case 171:
- case 43:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- MIX_10_4_7_3_1
- }
- else
- {
- MIX_00_4_3_1_2_3_3
- MIX_10_4_3_7_5_2_1
- }
- MIX_01_4_2_5_2_1_1
- MIX_11_4_5_7_2_1_1
- break;
- case 143:
- case 15:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- MIX_01_4_5_3_1
- }
- else
- {
- MIX_00_4_3_1_2_3_3
- MIX_01_4_1_5_5_2_1
- }
- MIX_10_4_6_7_2_1_1
- MIX_11_4_5_7_2_1_1
- break;
- case 124:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_1_3_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_7_3_2_1_1
- }
- MIX_11_4_8_3_1
- break;
- case 203:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_4_3_1_2_1_1
- }
- MIX_01_4_2_5_2_1_1
- MIX_10_4_6_3_1
- MIX_11_4_5_3_1
- break;
- case 62:
- MIX_00_MIX_00_4_0_3_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_1_5_2_1_1
- }
- MIX_10_4_7_3_1
- MIX_11_4_8_7_2_1_1
- break;
- case 211:
- MIX_00_4_3_3_1
- MIX_01_4_2_3_1
- MIX_10_4_6_3_2_1_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_5_7_2_1_1
- }
- break;
- case 118:
- MIX_00_4_0_3_2_1_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_1_5_2_1_1
- }
- MIX_10_4_3_3_1
- MIX_11_4_8_3_1
- break;
- case 217:
- MIX_00_4_1_3_1
- MIX_01_4_2_1_2_1_1
- MIX_10_4_6_3_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_5_7_2_1_1
- }
- break;
- case 110:
- MIX_00_MIX_00_4_0_3_1
- MIX_01_4_5_3_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_7_3_2_1_1
- }
- MIX_11_4_8_5_2_1_1
- break;
- case 155:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_4_3_1_2_1_1
- }
- MIX_01_4_2_3_1
- MIX_10_4_6_7_2_1_1
- MIX_11_4_7_3_1
- break;
- case 188:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_1_3_1
- MIX_10_4_7_3_1
- MIX_11_4_7_3_1
- break;
- case 185:
- MIX_00_4_1_3_1
- MIX_01_4_2_1_2_1_1
- MIX_10_4_7_3_1
- MIX_11_4_7_3_1
- break;
- case 61:
- MIX_00_4_1_3_1
- MIX_01_4_1_3_1
- MIX_10_4_7_3_1
- MIX_11_4_8_7_2_1_1
- break;
- case 157:
- MIX_00_4_1_3_1
- MIX_01_4_1_3_1
- MIX_10_4_6_7_2_1_1
- MIX_11_4_7_3_1
- break;
- case 103:
- MIX_00_4_3_3_1
- MIX_01_4_5_3_1
- MIX_10_4_3_3_1
- MIX_11_4_8_5_2_1_1
- break;
- case 227:
- MIX_00_4_3_3_1
- MIX_01_4_2_5_2_1_1
- MIX_10_4_3_3_1
- MIX_11_4_5_3_1
- break;
- case 230:
- MIX_00_4_0_3_2_1_1
- MIX_01_4_5_3_1
- MIX_10_4_3_3_1
- MIX_11_4_5_3_1
- break;
- case 199:
- MIX_00_4_3_3_1
- MIX_01_4_5_3_1
- MIX_10_4_6_3_2_1_1
- MIX_11_4_5_3_1
- break;
- case 220:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_1_3_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4_6_3_1
- }
- else
- {
- MIX_10_4_7_3_6_1_1
- }
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_5_7_2_1_1
- }
- break;
- case 158:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_MIX_00_4_0_3_1
- }
- else
- {
- MIX_00_4_3_1_6_1_1
- }
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_1_5_2_1_1
- }
- MIX_10_4_6_7_2_1_1
- MIX_11_4_7_3_1
- break;
- case 234:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_MIX_00_4_0_3_1
- }
- else
- {
- MIX_00_4_3_1_6_1_1
- }
- MIX_01_4_2_5_2_1_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_7_3_2_1_1
- }
- MIX_11_4_5_3_1
- break;
- case 242:
- MIX_00_4_0_3_2_1_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4_2_3_1
- }
- else
- {
- MIX_01_4_1_5_6_1_1
- }
- MIX_10_4_3_3_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_5_7_2_1_1
- }
- break;
- case 59:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_4_3_1_2_1_1
- }
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4_2_3_1
- }
- else
- {
- MIX_01_4_1_5_6_1_1
- }
- MIX_10_4_7_3_1
- MIX_11_4_8_7_2_1_1
- break;
- case 121:
- MIX_00_4_1_3_1
- MIX_01_4_2_1_2_1_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_7_3_2_1_1
- }
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4_8_3_1
- }
- else
- {
- MIX_11_4_5_7_6_1_1
- }
- break;
- case 87:
- MIX_00_4_3_3_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_1_5_2_1_1
- }
- MIX_10_4_6_3_2_1_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4_8_3_1
- }
- else
- {
- MIX_11_4_5_7_6_1_1
- }
- break;
- case 79:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_4_3_1_2_1_1
- }
- MIX_01_4_5_3_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4_6_3_1
- }
- else
- {
- MIX_10_4_7_3_6_1_1
- }
- MIX_11_4_8_5_2_1_1
- break;
- case 122:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_MIX_00_4_0_3_1
- }
- else
- {
- MIX_00_4_3_1_6_1_1
- }
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4_2_3_1
- }
- else
- {
- MIX_01_4_1_5_6_1_1
- }
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_7_3_2_1_1
- }
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4_8_3_1
- }
- else
- {
- MIX_11_4_5_7_6_1_1
- }
- break;
- case 94:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_MIX_00_4_0_3_1
- }
- else
- {
- MIX_00_4_3_1_6_1_1
- }
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_1_5_2_1_1
- }
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4_6_3_1
- }
- else
- {
- MIX_10_4_7_3_6_1_1
- }
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4_8_3_1
- }
- else
- {
- MIX_11_4_5_7_6_1_1
- }
- break;
- case 218:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_MIX_00_4_0_3_1
- }
- else
- {
- MIX_00_4_3_1_6_1_1
- }
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4_2_3_1
- }
- else
- {
- MIX_01_4_1_5_6_1_1
- }
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4_6_3_1
- }
- else
- {
- MIX_10_4_7_3_6_1_1
- }
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_5_7_2_1_1
- }
- break;
- case 91:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_4_3_1_2_1_1
- }
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4_2_3_1
- }
- else
- {
- MIX_01_4_1_5_6_1_1
- }
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4_6_3_1
- }
- else
- {
- MIX_10_4_7_3_6_1_1
- }
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4_8_3_1
- }
- else
- {
- MIX_11_4_5_7_6_1_1
- }
- break;
- case 229:
- MIX_00_4_3_1_2_1_1
- MIX_01_4_1_5_2_1_1
- MIX_10_4_3_3_1
- MIX_11_4_5_3_1
- break;
- case 167:
- MIX_00_4_3_3_1
- MIX_01_4_5_3_1
- MIX_10_4_7_3_2_1_1
- MIX_11_4_5_7_2_1_1
- break;
- case 173:
- MIX_00_4_1_3_1
- MIX_01_4_1_5_2_1_1
- MIX_10_4_7_3_1
- MIX_11_4_5_7_2_1_1
- break;
- case 181:
- MIX_00_4_3_1_2_1_1
- MIX_01_4_1_3_1
- MIX_10_4_7_3_2_1_1
- MIX_11_4_7_3_1
- break;
- case 186:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_MIX_00_4_0_3_1
- }
- else
- {
- MIX_00_4_3_1_6_1_1
- }
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4_2_3_1
- }
- else
- {
- MIX_01_4_1_5_6_1_1
- }
- MIX_10_4_7_3_1
- MIX_11_4_7_3_1
- break;
- case 115:
- MIX_00_4_3_3_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4_2_3_1
- }
- else
- {
- MIX_01_4_1_5_6_1_1
- }
- MIX_10_4_3_3_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4_8_3_1
- }
- else
- {
- MIX_11_4_5_7_6_1_1
- }
- break;
- case 93:
- MIX_00_4_1_3_1
- MIX_01_4_1_3_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4_6_3_1
- }
- else
- {
- MIX_10_4_7_3_6_1_1
- }
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4_8_3_1
- }
- else
- {
- MIX_11_4_5_7_6_1_1
- }
- break;
- case 206:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_MIX_00_4_0_3_1
- }
- else
- {
- MIX_00_4_3_1_6_1_1
- }
- MIX_01_4_5_3_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4_6_3_1
- }
- else
- {
- MIX_10_4_7_3_6_1_1
- }
- MIX_11_4_5_3_1
- break;
- case 205:
- case 201:
- MIX_00_4_1_3_1
- MIX_01_4_1_5_2_1_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4_6_3_1
- }
- else
- {
- MIX_10_4_7_3_6_1_1
- }
- MIX_11_4_5_3_1
- break;
- case 174:
- case 46:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_MIX_00_4_0_3_1
- }
- else
- {
- MIX_00_4_3_1_6_1_1
- }
- MIX_01_4_5_3_1
- MIX_10_4_7_3_1
- MIX_11_4_5_7_2_1_1
- break;
- case 179:
- case 147:
- MIX_00_4_3_3_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4_2_3_1
- }
- else
- {
- MIX_01_4_1_5_6_1_1
- }
- MIX_10_4_7_3_2_1_1
- MIX_11_4_7_3_1
- break;
- case 117:
- case 116:
- MIX_00_4_3_1_2_1_1
- MIX_01_4_1_3_1
- MIX_10_4_3_3_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4_8_3_1
- }
- else
- {
- MIX_11_4_5_7_6_1_1
- }
- break;
- case 189:
- MIX_00_4_1_3_1
- MIX_01_4_1_3_1
- MIX_10_4_7_3_1
- MIX_11_4_7_3_1
- break;
- case 231:
- MIX_00_4_3_3_1
- MIX_01_4_5_3_1
- MIX_10_4_3_3_1
- MIX_11_4_5_3_1
- break;
- case 126:
- MIX_00_MIX_00_4_0_3_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_1_5_2_1_1
- }
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_7_3_2_1_1
- }
- MIX_11_4_8_3_1
- break;
- case 219:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_4_3_1_2_1_1
- }
- MIX_01_4_2_3_1
- MIX_10_4_6_3_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_5_7_2_1_1
- }
- break;
- case 125:
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_00_4_1_3_1
- MIX_10_4
- }
- else
- {
- MIX_00_4_3_1_5_2_1
- MIX_10_4_7_3_2_3_3
- }
- MIX_01_4_1_3_1
- MIX_11_4_8_3_1
- break;
- case 221:
- MIX_00_4_1_3_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_01_4_1_3_1
- MIX_11_4
- }
- else
- {
- MIX_01_4_5_1_5_2_1
- MIX_11_4_5_7_2_3_3
- }
- MIX_10_4_6_3_1
- break;
- case 207:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- MIX_01_4_5_3_1
- }
- else
- {
- MIX_00_4_3_1_2_3_3
- MIX_01_4_1_5_5_2_1
- }
- MIX_10_4_6_3_1
- MIX_11_4_5_3_1
- break;
- case 238:
- MIX_00_MIX_00_4_0_3_1
- MIX_01_4_5_3_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- MIX_11_4_5_3_1
- }
- else
- {
- MIX_10_4_7_3_2_3_3
- MIX_11_4_7_5_5_2_1
- }
- break;
- case 190:
- MIX_00_MIX_00_4_0_3_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- MIX_11_4_7_3_1
- }
- else
- {
- MIX_01_4_1_5_2_3_3
- MIX_11_4_5_7_5_2_1
- }
- MIX_10_4_7_3_1
- break;
- case 187:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- MIX_10_4_7_3_1
- }
- else
- {
- MIX_00_4_3_1_2_3_3
- MIX_10_4_3_7_5_2_1
- }
- MIX_01_4_2_3_1
- MIX_11_4_7_3_1
- break;
- case 243:
- MIX_00_4_3_3_1
- MIX_01_4_2_3_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_10_4_3_3_1
- MIX_11_4
- }
- else
- {
- MIX_10_4_7_3_5_2_1
- MIX_11_4_5_7_2_3_3
- }
- break;
- case 119:
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_00_4_3_3_1
- MIX_01_4
- }
- else
- {
- MIX_00_4_1_3_5_2_1
- MIX_01_4_1_5_2_3_3
- }
- MIX_10_4_3_3_1
- MIX_11_4_8_3_1
- break;
- case 237:
- case 233:
- MIX_00_4_1_3_1
- MIX_01_4_1_5_2_1_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_6_3_10
- }
- MIX_11_4_5_3_1
- break;
- case 175:
- case 47:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_MIX_00_4_0_3_10
- }
- MIX_01_4_5_3_1
- MIX_10_4_7_3_1
- MIX_11_4_5_7_2_1_1
- break;
- case 183:
- case 151:
- MIX_00_4_3_3_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_2_3_10
- }
- MIX_10_4_7_3_2_1_1
- MIX_11_4_7_3_1
- break;
- case 245:
- case 244:
- MIX_00_4_3_1_2_1_1
- MIX_01_4_1_3_1
- MIX_10_4_3_3_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_8_3_10
- }
- break;
- case 250:
- MIX_00_MIX_00_4_0_3_1
- MIX_01_4_2_3_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_7_3_2_1_1
- }
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_5_7_2_1_1
- }
- break;
- case 123:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_4_3_1_2_1_1
- }
- MIX_01_4_2_3_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_7_3_2_1_1
- }
- MIX_11_4_8_3_1
- break;
- case 95:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_4_3_1_2_1_1
- }
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_1_5_2_1_1
- }
- MIX_10_4_6_3_1
- MIX_11_4_8_3_1
- break;
- case 222:
- MIX_00_MIX_00_4_0_3_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_1_5_2_1_1
- }
- MIX_10_4_6_3_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_5_7_2_1_1
- }
- break;
- case 252:
- MIX_00_4_0_1_2_1_1
- MIX_01_4_1_3_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_7_3_2_1_1
- }
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_8_3_10
- }
- break;
- case 249:
- MIX_00_4_1_3_1
- MIX_01_4_2_1_2_1_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_6_3_10
- }
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_5_7_2_1_1
- }
- break;
- case 235:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_4_3_1_2_1_1
- }
- MIX_01_4_2_5_2_1_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_6_3_10
- }
- MIX_11_4_5_3_1
- break;
- case 111:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_MIX_00_4_0_3_10
- }
- MIX_01_4_5_3_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_7_3_2_1_1
- }
- MIX_11_4_8_5_2_1_1
- break;
- case 63:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_MIX_00_4_0_3_10
- }
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_1_5_2_1_1
- }
- MIX_10_4_7_3_1
- MIX_11_4_8_7_2_1_1
- break;
- case 159:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_4_3_1_2_1_1
- }
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_2_3_10
- }
- MIX_10_4_6_7_2_1_1
- MIX_11_4_7_3_1
- break;
- case 215:
- MIX_00_4_3_3_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_2_3_10
- }
- MIX_10_4_6_3_2_1_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_5_7_2_1_1
- }
- break;
- case 246:
- MIX_00_4_0_3_2_1_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_1_5_2_1_1
- }
- MIX_10_4_3_3_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_8_3_10
- }
- break;
- case 254:
- MIX_00_MIX_00_4_0_3_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_1_5_2_1_1
- }
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_7_3_2_1_1
- }
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_8_3_10
- }
- break;
- case 253:
- MIX_00_4_1_3_1
- MIX_01_4_1_3_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_6_3_10
- }
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_8_3_10
- }
- break;
- case 251:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_4_3_1_2_1_1
- }
- MIX_01_4_2_3_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_6_3_10
- }
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_5_7_2_1_1
- }
- break;
- case 239:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_MIX_00_4_0_3_10
- }
- MIX_01_4_5_3_1
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_6_3_10
- }
- MIX_11_4_5_3_1
- break;
- case 127:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_MIX_00_4_0_3_10
- }
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_1_5_2_1_1
- }
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- {
- MIX_10_4
- }
- else
- {
- MIX_10_4_7_3_2_1_1
- }
- MIX_11_4_8_3_1
- break;
- case 191:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_MIX_00_4_0_3_10
- }
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_2_3_10
- }
- MIX_10_4_7_3_1
- MIX_11_4_7_3_1
- break;
- case 223:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- {
- MIX_00_4
- }
- else
- {
- MIX_00_4_3_1_2_1_1
- }
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_2_3_10
- }
- MIX_10_4_6_3_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_5_7_2_1_1
- }
- break;
- case 247:
- MIX_00_4_3_3_1
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- {
- MIX_01_4
- }
- else
- {
- MIX_01_4_2_3_10
- }
- MIX_10_4_3_3_1
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- {
- MIX_11_4
- }
- else
- {
- MIX_11_4_8_3_10
- }
- break;
- case 255:
- if (isDifferent(w[3], w[1], trY, trU, trV, trA))
- MIX_00_4
- else
- MIX_00_MIX_00_4_0_3_10
-
- if (isDifferent(w[1], w[5], trY, trU, trV, trA))
- MIX_01_4
- else
- MIX_01_4_2_3_10
-
- if (isDifferent(w[7], w[3], trY, trU, trV, trA))
- MIX_10_4
- else
- MIX_10_4_6_3_10
-
- if (isDifferent(w[5], w[7], trY, trU, trV, trA))
- MIX_11_4
- else
- MIX_11_4_8_3_10
- break;
- }
- image++;
- output += 2;
- }
- output += lineSize;
- }
-
- return output;
-}
diff --git a/thirdparty/misc/hq2x.h b/thirdparty/misc/hq2x.h
deleted file mode 100644
index bebd917950..0000000000
--- a/thirdparty/misc/hq2x.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef HQ2X_H
-#define HQ2X_H
-
-#include "core/typedefs.h"
-
-
-uint32_t *hq2x_resize(
- const uint32_t *image,
- uint32_t width,
- uint32_t height,
- uint32_t *output,
- uint32_t trY = 0x30,
- uint32_t trU = 0x07,
- uint32_t trV = 0x06,
- uint32_t trA = 0x50,
- bool wrapX = false,
- bool wrapY = false );
-
-#endif // HQ2X_H
diff --git a/thirdparty/misc/r128.h b/thirdparty/misc/r128.h
index be7cd3024d..1f7aab78fb 100644
--- a/thirdparty/misc/r128.h
+++ b/thirdparty/misc/r128.h
@@ -665,7 +665,7 @@ static int r128__clz64(R128_U64 x)
// 32*32->64
static R128_U64 r128__umul64(R128_U32 a, R128_U32 b)
{
-# if defined(_M_IX86) && !defined(R128_STDC_ONLY)
+# if defined(_M_IX86) && !defined(R128_STDC_ONLY) && !defined(__MINGW32__)
return __emulu(a, b);
# elif defined(_M_ARM) && !defined(R128_STDC_ONLY)
return _arm_umull(a, b);
@@ -680,7 +680,7 @@ static R128_U32 r128__udiv64(R128_U32 nlo, R128_U32 nhi, R128_U32 d, R128_U32 *r
# if defined(_M_IX86) && (_MSC_VER >= 1920) && !defined(R128_STDC_ONLY)
unsigned __int64 n = ((unsigned __int64)nhi << 32) | nlo;
return _udiv64(n, d, rem);
-# elif defined(_M_IX86) && !defined(R128_STDC_ONLY)
+# elif defined(_M_IX86) && !defined(R128_STDC_ONLY) && !defined(__MINGW32__)
__asm {
mov eax, nlo
mov edx, nhi
@@ -795,7 +795,7 @@ static void r128__umul128(R128 *dst, R128_U64 a, R128_U64 b)
}
// 128/64->64
-#if defined(_M_X64) && (_MSC_VER < 1920) && !defined(R128_STDC_ONLY)
+#if defined(_M_X64) && (_MSC_VER < 1920) && !defined(R128_STDC_ONLY) && !defined(__MINGW32__)
// MSVC x64 provides neither inline assembly nor (pre-2019) a div intrinsic, so we do fake
// "inline assembly" to avoid long division or outline assembly.
#pragma code_seg(".text")
@@ -810,7 +810,7 @@ static const r128__udiv128Proc r128__udiv128 = (r128__udiv128Proc)(void*)r128__u
#else
static R128_U64 r128__udiv128(R128_U64 nlo, R128_U64 nhi, R128_U64 d, R128_U64 *rem)
{
-#if defined(_M_X64) && !defined(R128_STDC_ONLY)
+#if defined(_M_X64) && !defined(R128_STDC_ONLY) && !defined(__MINGW32__)
return _udiv128(nhi, nlo, d, rem);
#elif defined(__x86_64__) && !defined(R128_STDC_ONLY)
R128_U64 q, r;
@@ -1602,7 +1602,7 @@ void r128Shl(R128 *dst, const R128 *src, int amount)
R128_ASSERT(dst != NULL);
R128_ASSERT(src != NULL);
-#if defined(_M_IX86) && !defined(R128_STDC_ONLY)
+#if defined(_M_IX86) && !defined(R128_STDC_ONLY) && !defined(__MINGW32__)
__asm {
// load src
mov edx, dword ptr[src]
@@ -1664,7 +1664,7 @@ void r128Shr(R128 *dst, const R128 *src, int amount)
R128_ASSERT(dst != NULL);
R128_ASSERT(src != NULL);
-#if defined(_M_IX86) && !defined(R128_STDC_ONLY)
+#if defined(_M_IX86) && !defined(R128_STDC_ONLY) && !defined(__MINGW32__)
__asm {
// load src
mov edx, dword ptr[src]
@@ -1726,7 +1726,7 @@ void r128Sar(R128 *dst, const R128 *src, int amount)
R128_ASSERT(dst != NULL);
R128_ASSERT(src != NULL);
-#if defined(_M_IX86) && !defined(R128_STDC_ONLY)
+#if defined(_M_IX86) && !defined(R128_STDC_ONLY) && !defined(__MINGW32__)
__asm {
// load src
mov edx, dword ptr[src]
diff --git a/thirdparty/oidn/0001-window.h-case-sensitive.patch b/thirdparty/oidn/0001-window.h-case-sensitive.patch
new file mode 100644
index 0000000000..7b9c8e96c1
--- /dev/null
+++ b/thirdparty/oidn/0001-window.h-case-sensitive.patch
@@ -0,0 +1,13 @@
+diff --git a/thirdparty/oidn/common/platform.h b/thirdparty/oidn/common/platform.h
+index 205ac8981d..9373b617b5 100644
+--- a/thirdparty/oidn/common/platform.h
++++ b/thirdparty/oidn/common/platform.h
+@@ -19,7 +19,7 @@
+ #if defined(_WIN32)
+ #define WIN32_LEAN_AND_MEAN
+ #define NOMINMAX
+- #include <Windows.h>
++ #include <windows.h>
+ #elif defined(__APPLE__)
+ #include <sys/sysctl.h>
+ #endif
diff --git a/thirdparty/oidn/common/platform.h b/thirdparty/oidn/common/platform.h
index 205ac8981d..9373b617b5 100644
--- a/thirdparty/oidn/common/platform.h
+++ b/thirdparty/oidn/common/platform.h
@@ -19,7 +19,7 @@
#if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
- #include <Windows.h>
+ #include <windows.h>
#elif defined(__APPLE__)
#include <sys/sysctl.h>
#endif
diff --git a/thirdparty/xatlas/LICENSE b/thirdparty/xatlas/LICENSE
index 9e61e15fb7..7af8b33238 100644
--- a/thirdparty/xatlas/LICENSE
+++ b/thirdparty/xatlas/LICENSE
@@ -1,6 +1,6 @@
MIT License
-Copyright (c) 2018-2019 Jonathan Young
+Copyright (c) 2018-2020 Jonathan Young
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/xatlas/xatlas.cpp b/thirdparty/xatlas/xatlas.cpp
index b1cbeb980f..43aec33a9f 100644
--- a/thirdparty/xatlas/xatlas.cpp
+++ b/thirdparty/xatlas/xatlas.cpp
@@ -1,7 +1,7 @@
/*
MIT License
-Copyright (c) 2018-2019 Jonathan Young
+Copyright (c) 2018-2020 Jonathan Young
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -33,19 +33,19 @@ https://github.com/brandonpelfrey/Fast-BVH
MIT License
Copyright (c) 2012 Brandon Pelfrey
*/
-#include <assert.h>
-#include <float.h> // FLT_MAX
-#include <limits.h>
-#include <math.h>
#include <atomic>
#include <condition_variable>
#include <mutex>
#include <thread>
+#include <assert.h>
+#include <float.h> // FLT_MAX
+#include <limits.h>
+#include <math.h>
#define __STDC_LIMIT_MACROS
-#include "xatlas.h"
#include <stdint.h>
#include <stdio.h>
#include <string.h>
+#include "xatlas.h"
#ifndef XA_DEBUG
#ifdef NDEBUG
@@ -70,10 +70,7 @@ Copyright (c) 2012 Brandon Pelfrey
#define XA_XSTR(x) XA_STR(x)
#ifndef XA_ASSERT
-#define XA_ASSERT(exp) \
- if (!(exp)) { \
- XA_PRINT_WARNING("\rASSERT: %s %s %d\n", XA_XSTR(exp), __FILE__, __LINE__); \
- }
+#define XA_ASSERT(exp) if (!(exp)) { XA_PRINT_WARNING("\rASSERT: %s %s %d\n", XA_XSTR(exp), __FILE__, __LINE__); }
#endif
#ifndef XA_DEBUG_ASSERT
@@ -81,20 +78,20 @@ Copyright (c) 2012 Brandon Pelfrey
#endif
#ifndef XA_PRINT
-#define XA_PRINT(...) \
+#define XA_PRINT(...) \
if (xatlas::internal::s_print && xatlas::internal::s_printVerbose) \
xatlas::internal::s_print(__VA_ARGS__);
#endif
#ifndef XA_PRINT_WARNING
-#define XA_PRINT_WARNING(...) \
+#define XA_PRINT_WARNING(...) \
if (xatlas::internal::s_print) \
xatlas::internal::s_print(__VA_ARGS__);
#endif
#define XA_ALLOC(tag, type) (type *)internal::Realloc(nullptr, sizeof(type), tag, __FILE__, __LINE__)
-#define XA_ALLOC_ARRAY(tag, type, num) (type *)internal::Realloc(nullptr, sizeof(type) * num, tag, __FILE__, __LINE__)
-#define XA_REALLOC(tag, ptr, type, num) (type *)internal::Realloc(ptr, sizeof(type) * num, tag, __FILE__, __LINE__)
+#define XA_ALLOC_ARRAY(tag, type, num) (type *)internal::Realloc(nullptr, sizeof(type) * (num), tag, __FILE__, __LINE__)
+#define XA_REALLOC(tag, ptr, type, num) (type *)internal::Realloc(ptr, sizeof(type) * (num), tag, __FILE__, __LINE__)
#define XA_REALLOC_SIZE(tag, ptr, size) (uint8_t *)internal::Realloc(ptr, size, tag, __FILE__, __LINE__)
#define XA_FREE(ptr) internal::Realloc(ptr, 0, internal::MemTag::Default, __FILE__, __LINE__)
#define XA_NEW(tag, type) new (XA_ALLOC(tag, type)) type()
@@ -125,11 +122,12 @@ Copyright (c) 2012 Brandon Pelfrey
#define XA_DEBUG_HEAP 0
#define XA_DEBUG_SINGLE_CHART 0
+#define XA_DEBUG_ALL_CHARTS_INVALID 0
#define XA_DEBUG_EXPORT_ATLAS_IMAGES 0
#define XA_DEBUG_EXPORT_ATLAS_IMAGES_PER_CHART 0 // Export an atlas image after each chart is added.
#define XA_DEBUG_EXPORT_BOUNDARY_GRID 0
#define XA_DEBUG_EXPORT_TGA (XA_DEBUG_EXPORT_ATLAS_IMAGES || XA_DEBUG_EXPORT_BOUNDARY_GRID)
-#define XA_DEBUG_EXPORT_OBJ_SOURCE_MESHES 0
+#define XA_DEBUG_EXPORT_OBJ_FACE_GROUPS 0
#define XA_DEBUG_EXPORT_OBJ_CHART_GROUPS 0
#define XA_DEBUG_EXPORT_OBJ_PLANAR_REGIONS 0
#define XA_DEBUG_EXPORT_OBJ_CHARTS 0
@@ -139,13 +137,19 @@ Copyright (c) 2012 Brandon Pelfrey
#define XA_DEBUG_EXPORT_OBJ_INVALID_PARAMETERIZATION 0
#define XA_DEBUG_EXPORT_OBJ_RECOMPUTED_CHARTS 0
-#define XA_DEBUG_EXPORT_OBJ (0 || XA_DEBUG_EXPORT_OBJ_SOURCE_MESHES || XA_DEBUG_EXPORT_OBJ_CHART_GROUPS || XA_DEBUG_EXPORT_OBJ_PLANAR_REGIONS || XA_DEBUG_EXPORT_OBJ_CHARTS || XA_DEBUG_EXPORT_OBJ_BEFORE_FIX_TJUNCTION || XA_DEBUG_EXPORT_OBJ_CLOSE_HOLES_ERROR || XA_DEBUG_EXPORT_OBJ_CHARTS_AFTER_PARAMETERIZATION || XA_DEBUG_EXPORT_OBJ_INVALID_PARAMETERIZATION || XA_DEBUG_EXPORT_OBJ_RECOMPUTED_CHARTS)
+#define XA_DEBUG_EXPORT_OBJ (0 \
+ || XA_DEBUG_EXPORT_OBJ_FACE_GROUPS \
+ || XA_DEBUG_EXPORT_OBJ_CHART_GROUPS \
+ || XA_DEBUG_EXPORT_OBJ_PLANAR_REGIONS \
+ || XA_DEBUG_EXPORT_OBJ_CHARTS \
+ || XA_DEBUG_EXPORT_OBJ_BEFORE_FIX_TJUNCTION \
+ || XA_DEBUG_EXPORT_OBJ_CLOSE_HOLES_ERROR \
+ || XA_DEBUG_EXPORT_OBJ_CHARTS_AFTER_PARAMETERIZATION \
+ || XA_DEBUG_EXPORT_OBJ_INVALID_PARAMETERIZATION \
+ || XA_DEBUG_EXPORT_OBJ_RECOMPUTED_CHARTS)
#ifdef _MSC_VER
-#define XA_FOPEN(_file, _filename, _mode) \
- { \
- if (fopen_s(&_file, _filename, _mode) != 0) _file = NULL; \
- }
+#define XA_FOPEN(_file, _filename, _mode) { if (fopen_s(&_file, _filename, _mode) != 0) _file = NULL; }
#define XA_SPRINTF(_buffer, _size, _format, ...) sprintf_s(_buffer, _size, _format, __VA_ARGS__)
#else
#define XA_FOPEN(_file, _filename, _mode) _file = fopen(_filename, _mode)
@@ -160,12 +164,90 @@ static FreeFunc s_free = free;
static PrintFunc s_print = printf;
static bool s_printVerbose = false;
-struct MemTag {
- enum {
+#if XA_PROFILE
+#define XA_PROFILE_START(var) const clock_t var##Start = clock();
+#define XA_PROFILE_END(var) internal::s_profile.var += clock() - var##Start;
+#define XA_PROFILE_PRINT_AND_RESET(label, var) XA_PRINT("%s%.2f seconds (%g ms)\n", label, internal::clockToSeconds(internal::s_profile.var), internal::clockToMs(internal::s_profile.var)); internal::s_profile.var = 0;
+#define XA_PROFILE_ALLOC 0
+
+struct ProfileData
+{
+#if XA_PROFILE_ALLOC
+ std::atomic<clock_t> alloc;
+#endif
+ clock_t addMeshReal;
+ clock_t addMeshCopyData;
+ std::atomic<clock_t> addMeshThread;
+ std::atomic<clock_t> addMeshCreateColocals;
+ clock_t computeChartsReal;
+ std::atomic<clock_t> computeChartsThread;
+ std::atomic<clock_t> createFaceGroups;
+ std::atomic<clock_t> extractInvalidMeshGeometry;
+ std::atomic<clock_t> chartGroupComputeChartsReal;
+ std::atomic<clock_t> chartGroupComputeChartsThread;
+ std::atomic<clock_t> createChartGroupMesh;
+ std::atomic<clock_t> createChartGroupMeshColocals;
+ std::atomic<clock_t> createChartGroupMeshBoundaries;
+ std::atomic<clock_t> buildAtlas;
+ std::atomic<clock_t> buildAtlasInit;
+ std::atomic<clock_t> planarCharts;
+ std::atomic<clock_t> clusteredCharts;
+ std::atomic<clock_t> clusteredChartsPlaceSeeds;
+ std::atomic<clock_t> clusteredChartsPlaceSeedsBoundaryIntersection;
+ std::atomic<clock_t> clusteredChartsRelocateSeeds;
+ std::atomic<clock_t> clusteredChartsReset;
+ std::atomic<clock_t> clusteredChartsGrow;
+ std::atomic<clock_t> clusteredChartsGrowBoundaryIntersection;
+ std::atomic<clock_t> clusteredChartsMerge;
+ std::atomic<clock_t> clusteredChartsFillHoles;
+ std::atomic<clock_t> copyChartFaces;
+ clock_t parameterizeChartsReal;
+ std::atomic<clock_t> parameterizeChartsThread;
+ std::atomic<clock_t> createChartMesh;
+ std::atomic<clock_t> fixChartMeshTJunctions;
+ std::atomic<clock_t> closeChartMeshHoles;
+ std::atomic<clock_t> parameterizeChartsOrthogonal;
+ std::atomic<clock_t> parameterizeChartsLSCM;
+ std::atomic<clock_t> parameterizeChartsRecompute;
+ std::atomic<clock_t> parameterizeChartsPiecewise;
+ std::atomic<clock_t> parameterizeChartsPiecewiseBoundaryIntersection;
+ std::atomic<clock_t> parameterizeChartsEvaluateQuality;
+ clock_t packCharts;
+ clock_t packChartsAddCharts;
+ std::atomic<clock_t> packChartsAddChartsThread;
+ std::atomic<clock_t> packChartsAddChartsRestoreTexcoords;
+ clock_t packChartsRasterize;
+ clock_t packChartsDilate;
+ clock_t packChartsFindLocation;
+ clock_t packChartsBlit;
+ clock_t buildOutputMeshes;
+};
+
+static ProfileData s_profile;
+
+static double clockToMs(clock_t c)
+{
+ return c * 1000.0 / CLOCKS_PER_SEC;
+}
+
+static double clockToSeconds(clock_t c)
+{
+ return c / (double)CLOCKS_PER_SEC;
+}
+#else
+#define XA_PROFILE_START(var)
+#define XA_PROFILE_END(var)
+#define XA_PROFILE_PRINT_AND_RESET(label, var)
+#define XA_PROFILE_ALLOC 0
+#endif
+
+struct MemTag
+{
+ enum
+ {
Default,
BitImage,
BVH,
- FullVector,
Matrix,
Mesh,
MeshBoundaries,
@@ -175,6 +257,7 @@ struct MemTag {
MeshNormals,
MeshPositions,
MeshTexcoords,
+ OpenNL,
SegmentAtlasChartCandidates,
SegmentAtlasChartFaces,
SegmentAtlasMeshData,
@@ -184,7 +267,8 @@ struct MemTag {
};
#if XA_DEBUG_HEAP
-struct AllocHeader {
+struct AllocHeader
+{
size_t size;
const char *file;
int line;
@@ -197,10 +281,11 @@ struct AllocHeader {
static std::mutex s_allocMutex;
static AllocHeader *s_allocRoot = nullptr;
static size_t s_allocTotalCount = 0, s_allocTotalSize = 0, s_allocPeakSize = 0, s_allocCount[MemTag::Count] = { 0 }, s_allocTotalTagSize[MemTag::Count] = { 0 }, s_allocPeakTagSize[MemTag::Count] = { 0 };
-static uint32_t s_allocId = 0;
+static uint32_t s_allocId =0 ;
static constexpr uint32_t kAllocRedzone = 0x12345678;
-static void *Realloc(void *ptr, size_t size, int tag, const char *file, int line) {
+static void *Realloc(void *ptr, size_t size, int tag, const char *file, int line)
+{
std::unique_lock<std::mutex> lock(s_allocMutex);
if (!size && !ptr)
return nullptr;
@@ -261,7 +346,8 @@ static void *Realloc(void *ptr, size_t size, int tag, const char *file, int line
return newPtr + sizeof(AllocHeader);
}
-static void ReportLeaks() {
+static void ReportLeaks()
+{
printf("Checking for memory leaks...\n");
bool anyLeaks = false;
AllocHeader *header = s_allocRoot;
@@ -289,14 +375,14 @@ static void ReportLeaks() {
s_allocTotalTagSize[i] = s_allocPeakTagSize[i] = 0;
}
-static void PrintMemoryUsage() {
+static void PrintMemoryUsage()
+{
XA_PRINT("Total allocations: %zu\n", s_allocTotalCount);
XA_PRINT("Memory usage: %0.2fMB current, %0.2fMB peak\n", internal::s_allocTotalSize / 1024.0f / 1024.0f, internal::s_allocPeakSize / 1024.0f / 1024.0f);
static const char *labels[] = { // Sync with MemTag
"Default",
"BitImage",
"BVH",
- "FullVector",
"Matrix",
"Mesh",
"MeshBoundaries",
@@ -306,6 +392,7 @@ static void PrintMemoryUsage() {
"MeshNormals",
"MeshPositions",
"MeshTexcoords",
+ "OpenNL",
"SegmentAtlasChartCandidates",
"SegmentAtlasChartFaces",
"SegmentAtlasMeshData",
@@ -318,158 +405,116 @@ static void PrintMemoryUsage() {
#define XA_PRINT_MEM_USAGE internal::PrintMemoryUsage();
#else
-static void *Realloc(void *ptr, size_t size, int /*tag*/, const char * /*file*/, int /*line*/) {
+static void *Realloc(void *ptr, size_t size, int /*tag*/, const char * /*file*/, int /*line*/)
+{
if (size == 0 && !ptr)
return nullptr;
if (size == 0 && s_free) {
s_free(ptr);
return nullptr;
}
+#if XA_PROFILE_ALLOC
+ XA_PROFILE_START(alloc)
+#endif
void *mem = s_realloc(ptr, size);
- if (size > 0) {
- XA_DEBUG_ASSERT(mem);
- }
+#if XA_PROFILE_ALLOC
+ XA_PROFILE_END(alloc)
+#endif
+ XA_DEBUG_ASSERT(size <= 0 || (size > 0 && mem));
return mem;
}
#define XA_PRINT_MEM_USAGE
#endif
-#if XA_PROFILE
-#define XA_PROFILE_START(var) const clock_t var##Start = clock();
-#define XA_PROFILE_END(var) internal::s_profile.var += clock() - var##Start;
-#define XA_PROFILE_PRINT_AND_RESET(label, var) \
- XA_PRINT("%s%.2f seconds (%g ms)\n", label, internal::clockToSeconds(internal::s_profile.var), internal::clockToMs(internal::s_profile.var)); \
- internal::s_profile.var = 0;
-
-struct ProfileData {
- clock_t addMeshReal;
- clock_t addMeshCopyData;
- std::atomic<clock_t> addMeshThread;
- std::atomic<clock_t> addMeshCreateColocals;
- std::atomic<clock_t> addMeshCreateFaceGroups;
- std::atomic<clock_t> addMeshCreateChartGroupsReal;
- std::atomic<clock_t> addMeshCreateChartGroupsThread;
- clock_t computeChartsReal;
- std::atomic<clock_t> computeChartsThread;
- std::atomic<clock_t> buildAtlas;
- std::atomic<clock_t> buildAtlasInit;
- std::atomic<clock_t> buildAtlasPlaceSeeds;
- std::atomic<clock_t> buildAtlasRelocateSeeds;
- std::atomic<clock_t> buildAtlasResetCharts;
- std::atomic<clock_t> buildAtlasGrowCharts;
- std::atomic<clock_t> buildAtlasMergeCharts;
- std::atomic<clock_t> buildAtlasFillHoles;
- std::atomic<clock_t> createChartMeshesReal;
- std::atomic<clock_t> createChartMeshesThread;
- std::atomic<clock_t> fixChartMeshTJunctions;
- std::atomic<clock_t> closeChartMeshHoles;
- clock_t parameterizeChartsReal;
- std::atomic<clock_t> parameterizeChartsThread;
- std::atomic<clock_t> parameterizeChartsOrthogonal;
- std::atomic<clock_t> parameterizeChartsLSCM;
- std::atomic<clock_t> parameterizeChartsEvaluateQuality;
- clock_t packCharts;
- clock_t packChartsAddCharts;
- std::atomic<clock_t> packChartsAddChartsThread;
- std::atomic<clock_t> packChartsAddChartsRestoreTexcoords;
- clock_t packChartsRasterize;
- clock_t packChartsDilate;
- clock_t packChartsFindLocation;
- clock_t packChartsBlit;
- clock_t buildOutputMeshes;
-};
-
-static ProfileData s_profile;
-
-static double clockToMs(clock_t c) {
- return c * 1000.0 / CLOCKS_PER_SEC;
-}
-
-static double clockToSeconds(clock_t c) {
- return c / (double)CLOCKS_PER_SEC;
-}
-#else
-#define XA_PROFILE_START(var)
-#define XA_PROFILE_END(var)
-#define XA_PROFILE_PRINT_AND_RESET(label, var)
-#endif
-
static constexpr float kPi = 3.14159265358979323846f;
static constexpr float kPi2 = 6.28318530717958647692f;
-static constexpr float kPi4 = 12.56637061435917295384f;
static constexpr float kEpsilon = 0.0001f;
static constexpr float kAreaEpsilon = FLT_EPSILON;
static constexpr float kNormalEpsilon = 0.001f;
-static int align(int x, int a) {
+static int align(int x, int a)
+{
return (x + a - 1) & ~(a - 1);
}
template <typename T>
-static T max(const T &a, const T &b) {
+static T max(const T &a, const T &b)
+{
return a > b ? a : b;
}
template <typename T>
-static T min(const T &a, const T &b) {
+static T min(const T &a, const T &b)
+{
return a < b ? a : b;
}
template <typename T>
-static T max3(const T &a, const T &b, const T &c) {
+static T max3(const T &a, const T &b, const T &c)
+{
return max(a, max(b, c));
}
/// Return the maximum of the three arguments.
template <typename T>
-static T min3(const T &a, const T &b, const T &c) {
+static T min3(const T &a, const T &b, const T &c)
+{
return min(a, min(b, c));
}
/// Clamp between two values.
template <typename T>
-static T clamp(const T &x, const T &a, const T &b) {
+static T clamp(const T &x, const T &a, const T &b)
+{
return min(max(x, a), b);
}
template <typename T>
-static void swap(T &a, T &b) {
+static void swap(T &a, T &b)
+{
T temp = a;
a = b;
b = temp;
}
-union FloatUint32 {
+union FloatUint32
+{
float f;
uint32_t u;
};
-static bool isFinite(float f) {
+static bool isFinite(float f)
+{
FloatUint32 fu;
fu.f = f;
return fu.u != 0x7F800000u && fu.u != 0x7F800001u;
}
-static bool isNan(float f) {
+static bool isNan(float f)
+{
return f != f;
}
// Robust floating point comparisons:
// http://realtimecollisiondetection.net/blog/?p=89
-static bool equal(const float f0, const float f1, const float epsilon) {
+static bool equal(const float f0, const float f1, const float epsilon)
+{
//return fabs(f0-f1) <= epsilon;
return fabs(f0 - f1) <= epsilon * max3(1.0f, fabsf(f0), fabsf(f1));
}
-static int ftoi_ceil(float val) {
+static int ftoi_ceil(float val)
+{
return (int)ceilf(val);
}
-static bool isZero(const float f, const float epsilon) {
+static bool isZero(const float f, const float epsilon)
+{
return fabs(f) <= epsilon;
}
-static float square(float f) {
+static float square(float f)
+{
return f * f;
}
@@ -479,8 +524,9 @@ static float square(float f) {
* @note isPowerOfTwo(x) == true -> nextPowerOfTwo(x) == x
* @note nextPowerOfTwo(x) = 2 << log2(x-1)
*/
-static uint32_t nextPowerOfTwo(uint32_t x) {
- XA_DEBUG_ASSERT(x != 0);
+static uint32_t nextPowerOfTwo(uint32_t x)
+{
+ XA_DEBUG_ASSERT( x != 0 );
// On modern CPUs this is supposed to be as fast as using the bsr instruction.
x--;
x |= x >> 1;
@@ -491,59 +537,38 @@ static uint32_t nextPowerOfTwo(uint32_t x) {
return x + 1;
}
-static uint32_t sdbmHash(const void *data_in, uint32_t size, uint32_t h = 5381) {
- const uint8_t *data = (const uint8_t *)data_in;
- uint32_t i = 0;
- while (i < size) {
- h = (h << 16) + (h << 6) - h + (uint32_t)data[i++];
- }
- return h;
-}
-
-template <typename T>
-static uint32_t hash(const T &t, uint32_t h = 5381) {
- return sdbmHash(&t, sizeof(T), h);
-}
-
-// Functors for hash table:
-template <typename Key>
-struct Hash {
- uint32_t operator()(const Key &k) const { return hash(k); }
-};
-
-template <typename Key>
-struct Equal {
- bool operator()(const Key &k0, const Key &k1) const { return k0 == k1; }
-};
-
-class Vector2 {
+class Vector2
+{
public:
Vector2() {}
- explicit Vector2(float f) :
- x(f), y(f) {}
- Vector2(float x, float y) :
- x(x), y(y) {}
+ explicit Vector2(float f) : x(f), y(f) {}
+ Vector2(float x, float y): x(x), y(y) {}
- Vector2 operator-() const {
+ Vector2 operator-() const
+ {
return Vector2(-x, -y);
}
- void operator+=(const Vector2 &v) {
+ void operator+=(const Vector2 &v)
+ {
x += v.x;
y += v.y;
}
- void operator-=(const Vector2 &v) {
+ void operator-=(const Vector2 &v)
+ {
x -= v.x;
y -= v.y;
}
- void operator*=(float s) {
+ void operator*=(float s)
+ {
x *= s;
y *= s;
}
- void operator*=(const Vector2 &v) {
+ void operator*=(const Vector2 &v)
+ {
x *= v.x;
y *= v.y;
}
@@ -551,11 +576,13 @@ public:
float x, y;
};
-static bool operator==(const Vector2 &a, const Vector2 &b) {
+static bool operator==(const Vector2 &a, const Vector2 &b)
+{
return a.x == b.x && a.y == b.y;
}
-static bool operator!=(const Vector2 &a, const Vector2 &b) {
+static bool operator!=(const Vector2 &a, const Vector2 &b)
+{
return a.x != b.x || a.y != b.y;
}
@@ -564,33 +591,40 @@ static bool operator!=(const Vector2 &a, const Vector2 &b) {
return Vector2(a.x + b.x, a.y + b.y);
}*/
-static Vector2 operator-(const Vector2 &a, const Vector2 &b) {
+static Vector2 operator-(const Vector2 &a, const Vector2 &b)
+{
return Vector2(a.x - b.x, a.y - b.y);
}
-static Vector2 operator*(const Vector2 &v, float s) {
+static Vector2 operator*(const Vector2 &v, float s)
+{
return Vector2(v.x * s, v.y * s);
}
-static float dot(const Vector2 &a, const Vector2 &b) {
+static float dot(const Vector2 &a, const Vector2 &b)
+{
return a.x * b.x + a.y * b.y;
}
-static float lengthSquared(const Vector2 &v) {
+static float lengthSquared(const Vector2 &v)
+{
return v.x * v.x + v.y * v.y;
}
-static float length(const Vector2 &v) {
+static float length(const Vector2 &v)
+{
return sqrtf(lengthSquared(v));
}
#if XA_DEBUG
-static bool isNormalized(const Vector2 &v, float epsilon = kNormalEpsilon) {
+static bool isNormalized(const Vector2 &v, float epsilon = kNormalEpsilon)
+{
return equal(length(v), 1, epsilon);
}
#endif
-static Vector2 normalize(const Vector2 &v, float epsilon) {
+static Vector2 normalize(const Vector2 &v, float epsilon)
+{
float l = length(v);
XA_DEBUG_ASSERT(!isZero(l, epsilon));
XA_UNUSED(epsilon);
@@ -599,30 +633,36 @@ static Vector2 normalize(const Vector2 &v, float epsilon) {
return n;
}
-static Vector2 normalizeSafe(const Vector2 &v, const Vector2 &fallback, float epsilon) {
+static Vector2 normalizeSafe(const Vector2 &v, const Vector2 &fallback, float epsilon)
+{
float l = length(v);
if (isZero(l, epsilon))
return fallback;
return v * (1.0f / l);
}
-static bool equal(const Vector2 &v1, const Vector2 &v2, float epsilon) {
+static bool equal(const Vector2 &v1, const Vector2 &v2, float epsilon)
+{
return equal(v1.x, v2.x, epsilon) && equal(v1.y, v2.y, epsilon);
}
-static Vector2 min(const Vector2 &a, const Vector2 &b) {
+static Vector2 min(const Vector2 &a, const Vector2 &b)
+{
return Vector2(min(a.x, b.x), min(a.y, b.y));
}
-static Vector2 max(const Vector2 &a, const Vector2 &b) {
+static Vector2 max(const Vector2 &a, const Vector2 &b)
+{
return Vector2(max(a.x, b.x), max(a.y, b.y));
}
-static bool isFinite(const Vector2 &v) {
+static bool isFinite(const Vector2 &v)
+{
return isFinite(v.x) && isFinite(v.y);
}
-static float triangleArea(const Vector2 &a, const Vector2 &b, const Vector2 &c) {
+static float triangleArea(const Vector2 &a, const Vector2 &b, const Vector2 &c)
+{
// IC: While it may be appealing to use the following expression:
//return (c.x * a.y + a.x * b.y + b.x * c.y - b.x * a.y - c.x * b.y - a.x * c.y) * 0.5f;
// That's actually a terrible idea. Small triangles far from the origin can end up producing fairly large floating point
@@ -636,7 +676,8 @@ static float triangleArea(const Vector2 &a, const Vector2 &b, const Vector2 &c)
return (v0.x * v1.y - v0.y * v1.x) * 0.5f;
}
-static bool linesIntersect(const Vector2 &a1, const Vector2 &a2, const Vector2 &b1, const Vector2 &b2, float epsilon) {
+static bool linesIntersect(const Vector2 &a1, const Vector2 &a2, const Vector2 &b1, const Vector2 &b2, float epsilon)
+{
const Vector2 v0 = a2 - a1;
const Vector2 v1 = b2 - b1;
const float denom = -v1.x * v0.y + v0.x * v1.y;
@@ -644,70 +685,76 @@ static bool linesIntersect(const Vector2 &a1, const Vector2 &a2, const Vector2 &
return false;
const float s = (-v0.y * (a1.x - b1.x) + v0.x * (a1.y - b1.y)) / denom;
if (s > epsilon && s < 1.0f - epsilon) {
- const float t = (v1.x * (a1.y - b1.y) - v1.y * (a1.x - b1.x)) / denom;
+ const float t = ( v1.x * (a1.y - b1.y) - v1.y * (a1.x - b1.x)) / denom;
return t > epsilon && t < 1.0f - epsilon;
}
return false;
}
-struct Vector2i {
+struct Vector2i
+{
Vector2i() {}
- Vector2i(int32_t x, int32_t y) :
- x(x), y(y) {}
+ Vector2i(int32_t x, int32_t y) : x(x), y(y) {}
int32_t x, y;
};
-class Vector3 {
+class Vector3
+{
public:
Vector3() {}
- explicit Vector3(float f) :
- x(f), y(f), z(f) {}
- Vector3(float x, float y, float z) :
- x(x), y(y), z(z) {}
- Vector3(const Vector2 &v, float z) :
- x(v.x), y(v.y), z(z) {}
-
- Vector2 xy() const {
+ explicit Vector3(float f) : x(f), y(f), z(f) {}
+ Vector3(float x, float y, float z) : x(x), y(y), z(z) {}
+ Vector3(const Vector2 &v, float z) : x(v.x), y(v.y), z(z) {}
+
+ Vector2 xy() const
+ {
return Vector2(x, y);
}
- Vector3 operator-() const {
+ Vector3 operator-() const
+ {
return Vector3(-x, -y, -z);
}
- void operator+=(const Vector3 &v) {
+ void operator+=(const Vector3 &v)
+ {
x += v.x;
y += v.y;
z += v.z;
}
- void operator-=(const Vector3 &v) {
+ void operator-=(const Vector3 &v)
+ {
x -= v.x;
y -= v.y;
z -= v.z;
}
- void operator*=(float s) {
+ void operator*=(float s)
+ {
x *= s;
y *= s;
z *= s;
}
- void operator/=(float s) {
+ void operator/=(float s)
+ {
float is = 1.0f / s;
x *= is;
y *= is;
z *= is;
}
- void operator*=(const Vector3 &v) {
+ void operator*=(const Vector3 &v)
+ {
x *= v.x;
y *= v.y;
z *= v.z;
}
- void operator/=(const Vector3 &v) {
+ void operator/=(const Vector3 &v)
+ {
x /= v.x;
y /= v.y;
z /= v.z;
@@ -716,43 +763,53 @@ public:
float x, y, z;
};
-static Vector3 operator+(const Vector3 &a, const Vector3 &b) {
+static Vector3 operator+(const Vector3 &a, const Vector3 &b)
+{
return Vector3(a.x + b.x, a.y + b.y, a.z + b.z);
}
-static Vector3 operator-(const Vector3 &a, const Vector3 &b) {
+static Vector3 operator-(const Vector3 &a, const Vector3 &b)
+{
return Vector3(a.x - b.x, a.y - b.y, a.z - b.z);
}
-static Vector3 cross(const Vector3 &a, const Vector3 &b) {
+static Vector3 cross(const Vector3 &a, const Vector3 &b)
+{
return Vector3(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x);
}
-static Vector3 operator*(const Vector3 &v, float s) {
+static Vector3 operator*(const Vector3 &v, float s)
+{
return Vector3(v.x * s, v.y * s, v.z * s);
}
-static Vector3 operator/(const Vector3 &v, float s) {
+static Vector3 operator/(const Vector3 &v, float s)
+{
return v * (1.0f / s);
}
-static float dot(const Vector3 &a, const Vector3 &b) {
+static float dot(const Vector3 &a, const Vector3 &b)
+{
return a.x * b.x + a.y * b.y + a.z * b.z;
}
-static float lengthSquared(const Vector3 &v) {
+static float lengthSquared(const Vector3 &v)
+{
return v.x * v.x + v.y * v.y + v.z * v.z;
}
-static float length(const Vector3 &v) {
+static float length(const Vector3 &v)
+{
return sqrtf(lengthSquared(v));
}
-static bool isNormalized(const Vector3 &v, float epsilon = kNormalEpsilon) {
+static bool isNormalized(const Vector3 &v, float epsilon = kNormalEpsilon)
+{
return equal(length(v), 1, epsilon);
}
-static Vector3 normalize(const Vector3 &v, float epsilon) {
+static Vector3 normalize(const Vector3 &v, float epsilon)
+{
float l = length(v);
XA_DEBUG_ASSERT(!isZero(l, epsilon));
XA_UNUSED(epsilon);
@@ -761,7 +818,8 @@ static Vector3 normalize(const Vector3 &v, float epsilon) {
return n;
}
-static Vector3 normalizeSafe(const Vector3 &v, const Vector3 &fallback, float epsilon) {
+static Vector3 normalizeSafe(const Vector3 &v, const Vector3 &fallback, float epsilon)
+{
float l = length(v);
if (isZero(l, epsilon)) {
return fallback;
@@ -769,59 +827,80 @@ static Vector3 normalizeSafe(const Vector3 &v, const Vector3 &fallback, float ep
return v * (1.0f / l);
}
-static bool equal(const Vector3 &v0, const Vector3 &v1, float epsilon) {
+static bool equal(const Vector3 &v0, const Vector3 &v1, float epsilon)
+{
return fabs(v0.x - v1.x) <= epsilon && fabs(v0.y - v1.y) <= epsilon && fabs(v0.z - v1.z) <= epsilon;
}
-static Vector3 min(const Vector3 &a, const Vector3 &b) {
+static Vector3 min(const Vector3 &a, const Vector3 &b)
+{
return Vector3(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z));
}
-static Vector3 max(const Vector3 &a, const Vector3 &b) {
+static Vector3 max(const Vector3 &a, const Vector3 &b)
+{
return Vector3(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z));
}
#if XA_DEBUG
-bool isFinite(const Vector3 &v) {
+bool isFinite(const Vector3 &v)
+{
return isFinite(v.x) && isFinite(v.y) && isFinite(v.z);
}
#endif
-struct Extents2 {
+struct Extents2
+{
Vector2 min, max;
- void reset() {
+ Extents2() {}
+
+ Extents2(Vector2 p1, Vector2 p2)
+ {
+ min = xatlas::internal::min(p1, p2);
+ max = xatlas::internal::max(p1, p2);
+ }
+
+ void reset()
+ {
min.x = min.y = FLT_MAX;
max.x = max.y = -FLT_MAX;
}
- void add(Vector2 p) {
+ void add(Vector2 p)
+ {
min = xatlas::internal::min(min, p);
max = xatlas::internal::max(max, p);
}
- Vector2 midpoint() const {
+ Vector2 midpoint() const
+ {
return Vector2(min.x + (max.x - min.x) * 0.5f, min.y + (max.y - min.y) * 0.5f);
}
- static bool intersect(Extents2 e1, Extents2 e2) {
+ static bool intersect(const Extents2 &e1, const Extents2 &e2)
+ {
return e1.min.x <= e2.max.x && e1.max.x >= e2.min.x && e1.min.y <= e2.max.y && e1.max.y >= e2.min.y;
}
};
-struct Plane {
+struct Plane
+{
Plane() = default;
-
- Plane(const Vector3 &p1, const Vector3 &p2, const Vector3 &p3) {
+
+ Plane(const Vector3 &p1, const Vector3 &p2, const Vector3 &p3)
+ {
normal = cross(p2 - p1, p3 - p1);
dist = dot(normal, p1);
}
- float distance(const Vector3 &p) const {
+ float distance(const Vector3 &p) const
+ {
return dot(normal, p) - dist;
}
- void normalize() {
+ void normalize()
+ {
const float len = length(normal);
if (len > 0.0f) {
const float il = 1.0f / len;
@@ -834,7 +913,8 @@ struct Plane {
float dist;
};
-static bool lineIntersectsPoint(const Vector3 &point, const Vector3 &lineStart, const Vector3 &lineEnd, float *t, float epsilon) {
+static bool lineIntersectsPoint(const Vector3 &point, const Vector3 &lineStart, const Vector3 &lineEnd, float *t, float epsilon)
+{
float tt;
if (!t)
t = &tt;
@@ -851,19 +931,22 @@ static bool lineIntersectsPoint(const Vector3 &point, const Vector3 &lineStart,
return *t > kEpsilon && *t < 1.0f - kEpsilon;
}
-static bool sameSide(const Vector3 &p1, const Vector3 &p2, const Vector3 &a, const Vector3 &b) {
+static bool sameSide(const Vector3 &p1, const Vector3 &p2, const Vector3 &a, const Vector3 &b)
+{
const Vector3 &ab = b - a;
return dot(cross(ab, p1 - a), cross(ab, p2 - a)) >= 0.0f;
}
// http://blackpawn.com/texts/pointinpoly/default.html
-static bool pointInTriangle(const Vector3 &p, const Vector3 &a, const Vector3 &b, const Vector3 &c) {
+static bool pointInTriangle(const Vector3 &p, const Vector3 &a, const Vector3 &b, const Vector3 &c)
+{
return sameSide(p, a, b, c) && sameSide(p, b, a, c) && sameSide(p, c, a, b);
}
#if XA_CLOSE_HOLES_CHECK_EDGE_INTERSECTION
// https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm
-static bool rayIntersectsTriangle(const Vector3 &rayOrigin, const Vector3 &rayDir, const Vector3 *tri, float *t) {
+static bool rayIntersectsTriangle(const Vector3 &rayOrigin, const Vector3 &rayDir, const Vector3 *tri, float *t)
+{
*t = 0.0f;
const Vector3 &edge1 = tri[1] - tri[0];
const Vector3 &edge2 = tri[2] - tri[0];
@@ -890,47 +973,50 @@ static bool rayIntersectsTriangle(const Vector3 &rayOrigin, const Vector3 &rayDi
#endif
// From Fast-BVH
-struct AABB {
- AABB() :
- min(FLT_MAX, FLT_MAX, FLT_MAX), max(-FLT_MAX, -FLT_MAX, -FLT_MAX) {}
- AABB(const Vector3 &min, const Vector3 &max) :
- min(min), max(max) {}
- AABB(const Vector3 &p, float radius = 0.0f) :
- min(p), max(p) {
- if (radius > 0.0f) expand(radius);
- }
+struct AABB
+{
+ AABB() : min(FLT_MAX, FLT_MAX, FLT_MAX), max(-FLT_MAX, -FLT_MAX, -FLT_MAX) {}
+ AABB(const Vector3 &min, const Vector3 &max) : min(min), max(max) { }
+ AABB(const Vector3 &p, float radius = 0.0f) : min(p), max(p) { if (radius > 0.0f) expand(radius); }
- bool intersect(const AABB &other) const {
+ bool intersect(const AABB &other) const
+ {
return min.x <= other.max.x && max.x >= other.min.x && min.y <= other.max.y && max.y >= other.min.y && min.z <= other.max.z && max.z >= other.min.z;
}
- void expandToInclude(const Vector3 &p) {
+ void expandToInclude(const Vector3 &p)
+ {
min = internal::min(min, p);
max = internal::max(max, p);
}
- void expandToInclude(const AABB &aabb) {
+ void expandToInclude(const AABB &aabb)
+ {
min = internal::min(min, aabb.min);
max = internal::max(max, aabb.max);
}
- void expand(float amount) {
+ void expand(float amount)
+ {
min -= Vector3(amount);
max += Vector3(amount);
}
- Vector3 centroid() const {
+ Vector3 centroid() const
+ {
return min + (max - min) * 0.5f;
}
- uint32_t maxDimension() const {
+ uint32_t maxDimension() const
+ {
const Vector3 extent = max - min;
uint32_t result = 0;
if (extent.y > extent.x) {
result = 1;
if (extent.z > extent.y)
result = 2;
- } else if (extent.z > extent.x)
+ }
+ else if(extent.z > extent.x)
result = 2;
return result;
}
@@ -938,9 +1024,10 @@ struct AABB {
Vector3 min, max;
};
-struct ArrayBase {
- ArrayBase(uint32_t elementSize, int memTag = MemTag::Default) :
- buffer(nullptr), elementSize(elementSize), size(0), capacity(0) {
+struct ArrayBase
+{
+ ArrayBase(uint32_t elementSize, int memTag = MemTag::Default) : buffer(nullptr), elementSize(elementSize), size(0), capacity(0)
+ {
#if XA_DEBUG_HEAP
this->memTag = memTag;
#else
@@ -948,26 +1035,31 @@ struct ArrayBase {
#endif
}
- ~ArrayBase() {
+ ~ArrayBase()
+ {
XA_FREE(buffer);
}
- XA_INLINE void clear() {
+ XA_INLINE void clear()
+ {
size = 0;
}
- void copyFrom(const uint8_t *data, uint32_t length) {
+ void copyFrom(const uint8_t *data, uint32_t length)
+ {
resize(length, true);
memcpy(buffer, data, length * elementSize);
}
- void copyTo(ArrayBase &other) const {
+ void copyTo(ArrayBase &other) const
+ {
XA_DEBUG_ASSERT(elementSize == other.elementSize);
other.resize(size, true);
memcpy(other.buffer, buffer, size * elementSize);
}
- void destroy() {
+ void destroy()
+ {
size = 0;
XA_FREE(buffer);
buffer = nullptr;
@@ -976,7 +1068,8 @@ struct ArrayBase {
}
// Insert the given element at the given index shifting all the elements up.
- void insertAt(uint32_t index, const uint8_t *value) {
+ void insertAt(uint32_t index, const uint8_t *value)
+ {
XA_DEBUG_ASSERT(index >= 0 && index <= size);
resize(size + 1, false);
if (index < size - 1)
@@ -984,7 +1077,8 @@ struct ArrayBase {
memcpy(&buffer[index * elementSize], value, elementSize);
}
- void moveTo(ArrayBase &other) {
+ void moveTo(ArrayBase &other)
+ {
XA_DEBUG_ASSERT(elementSize == other.elementSize);
other.destroy();
other.buffer = buffer;
@@ -998,18 +1092,21 @@ struct ArrayBase {
elementSize = size = capacity = 0;
}
- void pop_back() {
+ void pop_back()
+ {
XA_DEBUG_ASSERT(size > 0);
resize(size - 1, false);
}
- void push_back(const uint8_t *value) {
+ void push_back(const uint8_t *value)
+ {
XA_DEBUG_ASSERT(value < buffer || value >= buffer + size);
resize(size + 1, false);
memcpy(&buffer[(size - 1) * elementSize], value, elementSize);
}
- void push_back(const ArrayBase &other) {
+ void push_back(const ArrayBase &other)
+ {
XA_DEBUG_ASSERT(elementSize == other.elementSize);
if (other.size == 0)
return;
@@ -1019,19 +1116,31 @@ struct ArrayBase {
}
// Remove the element at the given index. This is an expensive operation!
- void removeAt(uint32_t index) {
+ void removeAt(uint32_t index)
+ {
XA_DEBUG_ASSERT(index >= 0 && index < size);
if (size != 1)
memmove(buffer + elementSize * index, buffer + elementSize * (index + 1), elementSize * (size - 1 - index));
size--;
}
- void reserve(uint32_t desiredSize) {
+ // Element at index is swapped with the last element, then the array length is decremented.
+ void removeAtFast(uint32_t index)
+ {
+ XA_DEBUG_ASSERT(index >= 0 && index < size);
+ if (size != 1 && index != size - 1)
+ memcpy(buffer + elementSize * index, buffer + elementSize * (size - 1), elementSize);
+ size--;
+ }
+
+ void reserve(uint32_t desiredSize)
+ {
if (desiredSize > capacity)
setArrayCapacity(desiredSize);
}
- void resize(uint32_t newSize, bool exact) {
+ void resize(uint32_t newSize, bool exact)
+ {
size = newSize;
if (size > capacity) {
// First allocation is always exact. Otherwise, following allocations grow array to 150% of desired size.
@@ -1044,7 +1153,8 @@ struct ArrayBase {
}
}
- void setArrayCapacity(uint32_t newCapacity) {
+ void setArrayCapacity(uint32_t newCapacity)
+ {
XA_DEBUG_ASSERT(newCapacity >= size);
if (newCapacity == 0) {
// free the buffer.
@@ -1064,8 +1174,9 @@ struct ArrayBase {
}
#if XA_DEBUG_HEAP
- void setMemTag(int memTag) {
- this->memTag = memTag;
+ void setMemTag(int _memTag)
+ {
+ this->memTag = _memTag;
}
#endif
@@ -1078,25 +1189,28 @@ struct ArrayBase {
#endif
};
-template <typename T>
-class Array {
+template<typename T>
+class Array
+{
public:
- Array(int memTag = MemTag::Default) :
- m_base(sizeof(T), memTag) {}
- Array(const Array &) = delete;
+ Array(int memTag = MemTag::Default) : m_base(sizeof(T), memTag) {}
+ Array(const Array&) = delete;
Array &operator=(const Array &) = delete;
- XA_INLINE const T &operator[](uint32_t index) const {
+ XA_INLINE const T &operator[](uint32_t index) const
+ {
XA_DEBUG_ASSERT(index < m_base.size);
return ((const T *)m_base.buffer)[index];
}
- XA_INLINE T &operator[](uint32_t index) {
+ XA_INLINE T &operator[](uint32_t index)
+ {
XA_DEBUG_ASSERT(index < m_base.size);
return ((T *)m_base.buffer)[index];
}
- XA_INLINE const T &back() const {
+ XA_INLINE const T &back() const
+ {
XA_DEBUG_ASSERT(!isEmpty());
return ((const T *)m_base.buffer)[m_base.size - 1];
}
@@ -1104,7 +1218,8 @@ public:
XA_INLINE T *begin() { return (T *)m_base.buffer; }
XA_INLINE void clear() { m_base.clear(); }
- bool contains(const T &value) const {
+ bool contains(const T &value) const
+ {
for (uint32_t i = 0; i < m_base.size; i++) {
if (((const T *)m_base.buffer)[i] == value)
return true;
@@ -1116,6 +1231,7 @@ public:
void copyTo(Array &other) const { m_base.copyTo(other.m_base); }
XA_INLINE const T *data() const { return (const T *)m_base.buffer; }
XA_INLINE T *data() { return (T *)m_base.buffer; }
+ void destroy() { m_base.destroy(); }
XA_INLINE T *end() { return (T *)m_base.buffer + m_base.size; }
XA_INLINE bool isEmpty() const { return m_base.size == 0; }
void insertAt(uint32_t index, const T &value) { m_base.insertAt(index, (const uint8_t *)&value); }
@@ -1124,25 +1240,34 @@ public:
void push_back(const Array &other) { m_base.push_back(other.m_base); }
void pop_back() { m_base.pop_back(); }
void removeAt(uint32_t index) { m_base.removeAt(index); }
+ void removeAtFast(uint32_t index) { m_base.removeAtFast(index); }
void reserve(uint32_t desiredSize) { m_base.reserve(desiredSize); }
void resize(uint32_t newSize) { m_base.resize(newSize, true); }
- void runCtors() {
+ void runCtors()
+ {
for (uint32_t i = 0; i < m_base.size; i++)
new (&((T *)m_base.buffer)[i]) T;
}
- void runDtors() {
+ void runDtors()
+ {
for (uint32_t i = 0; i < m_base.size; i++)
((T *)m_base.buffer)[i].~T();
}
- void setAll(const T &value) {
+ void fill(const T &value)
+ {
auto buffer = (T *)m_base.buffer;
for (uint32_t i = 0; i < m_base.size; i++)
buffer[i] = value;
}
+ void fillBytes(uint8_t value)
+ {
+ memset(m_base.buffer, (int)value, m_base.size * m_base.elementSize);
+ }
+
#if XA_DEBUG_HEAP
void setMemTag(int memTag) { m_base.setMemTag(memTag); }
#endif
@@ -1154,47 +1279,35 @@ private:
ArrayBase m_base;
};
-template <typename T>
-struct ArrayView {
- ArrayView(Array<T> &a) :
- data(a.data()), length(a.size()) {}
- ArrayView(T *data, uint32_t length) :
- data(data), length(length) {}
- ArrayView &operator=(Array<T> &a) {
- data = a.data();
- length = a.size();
- return *this;
- }
- XA_INLINE const T &operator[](uint32_t index) const {
- XA_DEBUG_ASSERT(index < length);
- return data[index];
- }
+template<typename T>
+struct ArrayView
+{
+ ArrayView() : data(nullptr), length(0) {}
+ ArrayView(Array<T> &a) : data(a.data()), length(a.size()) {}
+ ArrayView(T *data, uint32_t length) : data(data), length(length) {}
+ ArrayView &operator=(Array<T> &a) { data = a.data(); length = a.size(); return *this; }
+ XA_INLINE const T &operator[](uint32_t index) const { XA_DEBUG_ASSERT(index < length); return data[index]; }
T *data;
uint32_t length;
};
-template <typename T>
-struct ConstArrayView {
- ConstArrayView(const Array<T> &a) :
- data(a.data()), length(a.size()) {}
- ConstArrayView(const T *data, uint32_t length) :
- data(data), length(length) {}
- ConstArrayView &operator=(const Array<T> &a) {
- data = a.data();
- length = a.size();
- return *this;
- }
- XA_INLINE const T &operator[](uint32_t index) const {
- XA_DEBUG_ASSERT(index < length);
- return data[index];
- }
+template<typename T>
+struct ConstArrayView
+{
+ ConstArrayView() : data(nullptr), length(0) {}
+ ConstArrayView(const Array<T> &a) : data(a.data()), length(a.size()) {}
+ ConstArrayView(const T *data, uint32_t length) : data(data), length(length) {}
+ ConstArrayView &operator=(const Array<T> &a) { data = a.data(); length = a.size(); return *this; }
+ XA_INLINE const T &operator[](uint32_t index) const { XA_DEBUG_ASSERT(index < length); return data[index]; }
const T *data;
uint32_t length;
};
/// Basis class to compute tangent space basis, ortogonalizations and to transform vectors from one space to another.
-struct Basis {
- XA_NODISCARD static Vector3 computeTangent(const Vector3 &normal) {
+struct Basis
+{
+ XA_NODISCARD static Vector3 computeTangent(const Vector3 &normal)
+ {
XA_ASSERT(isNormalized(normal));
// Choose minimum axis.
Vector3 tangent;
@@ -1210,7 +1323,8 @@ struct Basis {
return tangent;
}
- XA_NODISCARD static Vector3 computeBitangent(const Vector3 &normal, const Vector3 &tangent) {
+ XA_NODISCARD static Vector3 computeBitangent(const Vector3 &normal, const Vector3 &tangent)
+ {
return cross(normal, tangent);
}
@@ -1220,31 +1334,42 @@ struct Basis {
};
// Simple bit array.
-class BitArray {
+class BitArray
+{
public:
- BitArray() :
- m_size(0) {}
+ BitArray() : m_size(0) {}
- BitArray(uint32_t sz) {
+ BitArray(uint32_t sz)
+ {
resize(sz);
}
- void resize(uint32_t new_size) {
+ void resize(uint32_t new_size)
+ {
m_size = new_size;
m_wordArray.resize((m_size + 31) >> 5);
}
- bool get(uint32_t index) const {
+ bool get(uint32_t index) const
+ {
XA_DEBUG_ASSERT(index < m_size);
return (m_wordArray[index >> 5] & (1 << (index & 31))) != 0;
}
- void set(uint32_t index) {
+ void set(uint32_t index)
+ {
XA_DEBUG_ASSERT(index < m_size);
m_wordArray[index >> 5] |= (1 << (index & 31));
}
- void zeroOutMemory() {
+ void unset(uint32_t index)
+ {
+ XA_DEBUG_ASSERT(index < m_size);
+ m_wordArray[index >> 5] &= ~(1 << (index & 31));
+ }
+
+ void zeroOutMemory()
+ {
m_wordArray.zeroOutMemory();
}
@@ -1253,13 +1378,13 @@ private:
Array<uint32_t> m_wordArray;
};
-class BitImage {
+class BitImage
+{
public:
- BitImage() :
- m_width(0), m_height(0), m_rowStride(0), m_data(MemTag::BitImage) {}
+ BitImage() : m_width(0), m_height(0), m_rowStride(0), m_data(MemTag::BitImage) {}
- BitImage(uint32_t w, uint32_t h) :
- m_width(w), m_height(h), m_data(MemTag::BitImage) {
+ BitImage(uint32_t w, uint32_t h) : m_width(w), m_height(h), m_data(MemTag::BitImage)
+ {
m_rowStride = (m_width + 63) >> 6;
m_data.resize(m_rowStride * m_height);
m_data.zeroOutMemory();
@@ -1270,14 +1395,16 @@ public:
uint32_t width() const { return m_width; }
uint32_t height() const { return m_height; }
- void copyTo(BitImage &other) {
+ void copyTo(BitImage &other)
+ {
other.m_width = m_width;
other.m_height = m_height;
other.m_rowStride = m_rowStride;
m_data.copyTo(other.m_data);
}
- void resize(uint32_t w, uint32_t h, bool discard) {
+ void resize(uint32_t w, uint32_t h, bool discard)
+ {
const uint32_t rowStride = (w + 63) >> 6;
if (discard) {
m_data.resize(rowStride * h);
@@ -1301,24 +1428,28 @@ public:
m_rowStride = rowStride;
}
- bool get(uint32_t x, uint32_t y) const {
+ bool get(uint32_t x, uint32_t y) const
+ {
XA_DEBUG_ASSERT(x < m_width && y < m_height);
const uint32_t index = (x >> 6) + y * m_rowStride;
return (m_data[index] & (UINT64_C(1) << (uint64_t(x) & UINT64_C(63)))) != 0;
}
- void set(uint32_t x, uint32_t y) {
+ void set(uint32_t x, uint32_t y)
+ {
XA_DEBUG_ASSERT(x < m_width && y < m_height);
const uint32_t index = (x >> 6) + y * m_rowStride;
m_data[index] |= UINT64_C(1) << (uint64_t(x) & UINT64_C(63));
XA_DEBUG_ASSERT(get(x, y));
}
- void zeroOutMemory() {
+ void zeroOutMemory()
+ {
m_data.zeroOutMemory();
}
- bool canBlit(const BitImage &image, uint32_t offsetX, uint32_t offsetY) const {
+ bool canBlit(const BitImage &image, uint32_t offsetX, uint32_t offsetY) const
+ {
for (uint32_t y = 0; y < image.m_height; y++) {
const uint32_t thisY = y + offsetY;
if (thisY >= m_height)
@@ -1342,7 +1473,8 @@ public:
return true;
}
- void dilate(uint32_t padding) {
+ void dilate(uint32_t padding)
+ {
BitImage tmp(m_width, m_height);
for (uint32_t p = 0; p < padding; p++) {
tmp.zeroOutMemory();
@@ -1379,10 +1511,11 @@ private:
};
// From Fast-BVH
-class BVH {
+class BVH
+{
public:
- BVH(const Array<AABB> &objectAabbs, uint32_t leafSize = 4) :
- m_objectIds(MemTag::BVH), m_nodes(MemTag::BVH) {
+ BVH(const Array<AABB> &objectAabbs, uint32_t leafSize = 4) : m_objectIds(MemTag::BVH), m_nodes(MemTag::BVH)
+ {
m_objectAabbs = &objectAabbs;
if (m_objectAabbs->isEmpty())
return;
@@ -1402,7 +1535,7 @@ public:
Node node;
m_nodes.reserve(objectAabbs.size() * 2);
uint32_t nNodes = 0;
- while (stackptr > 0) {
+ while(stackptr > 0) {
// Pop the next item off of the stack
const BuildEntry &bnode = todo[--stackptr];
const uint32_t start = bnode.start;
@@ -1415,7 +1548,7 @@ public:
// Calculate the bounding box for this node
AABB bb(objectAabbs[m_objectIds[start]]);
AABB bc(objectAabbs[m_objectIds[start]].centroid());
- for (uint32_t p = start + 1; p < end; ++p) {
+ for(uint32_t p = start + 1; p < end; ++p) {
bb.expandToInclude(objectAabbs[m_objectIds[p]]);
bc.expandToInclude(objectAabbs[m_objectIds[p]].centroid());
}
@@ -1431,7 +1564,7 @@ public:
m_nodes[bnode.parent].rightOffset--;
// When this is the second touch, this is the right child.
// The right child sets up the offset for the flat tree.
- if (m_nodes[bnode.parent].rightOffset == kTouchedTwice)
+ if (m_nodes[bnode.parent].rightOffset == kTouchedTwice )
m_nodes[bnode.parent].rightOffset = nNodes - 1 - bnode.parent;
}
// If this is a leaf, no need to subdivide.
@@ -1466,20 +1599,21 @@ public:
}
}
- void query(const AABB &queryAabb, Array<uint32_t> &result) const {
+ void query(const AABB &queryAabb, Array<uint32_t> &result) const
+ {
result.clear();
// Working set
uint32_t todo[64];
int32_t stackptr = 0;
// "Push" on the root node to the working set
todo[stackptr] = 0;
- while (stackptr >= 0) {
+ while(stackptr >= 0) {
// Pop off the next node to work on.
const int ni = todo[stackptr--];
const Node &node = m_nodes[ni];
// Is leaf -> Intersect
if (node.rightOffset == 0) {
- for (uint32_t o = 0; o < node.nPrims; ++o) {
+ for(uint32_t o = 0; o < node.nPrims; ++o) {
const uint32_t obj = node.start + o;
if (queryAabb.intersect((*m_objectAabbs)[m_objectIds[obj]]))
result.push_back(m_objectIds[obj]);
@@ -1496,12 +1630,14 @@ public:
}
private:
- struct BuildEntry {
+ struct BuildEntry
+ {
uint32_t parent; // If non-zero then this is the index of the parent. (used in offsets)
uint32_t start, end; // The range of objects in the object list covered by this node.
};
- struct Node {
+ struct Node
+ {
AABB aabb;
uint32_t start, nPrims, rightOffset;
};
@@ -1511,8 +1647,10 @@ private:
Array<Node> m_nodes;
};
-struct Fit {
- static bool computeBasis(const Vector3 *points, uint32_t pointsCount, Basis *basis) {
+struct Fit
+{
+ static bool computeBasis(const Vector3 *points, uint32_t pointsCount, Basis *basis)
+ {
if (computeLeastSquaresNormal(points, pointsCount, &basis->normal)) {
basis->tangent = Basis::computeTangent(basis->normal);
basis->bitangent = Basis::computeBitangent(basis->normal, basis->tangent);
@@ -1526,7 +1664,8 @@ private:
// Fast, and accurate to within a few degrees.
// Returns None if the points do not span a plane.
// https://www.ilikebigbits.com/2015_03_04_plane_from_points.html
- static bool computeLeastSquaresNormal(const Vector3 *points, uint32_t pointsCount, Vector3 *normal) {
+ static bool computeLeastSquaresNormal(const Vector3 *points, uint32_t pointsCount, Vector3 *normal)
+ {
XA_DEBUG_ASSERT(pointsCount >= 3);
if (pointsCount == 3) {
*normal = normalize(cross(points[2] - points[0], points[1] - points[0]), kEpsilon);
@@ -1591,7 +1730,7 @@ private:
// Pick path with best conditioning:
Vector3 dir(0.0f);
if (det_max == det_x)
- dir = Vector3(det_x, xz * yz - xy * zz, xy * yz - xz * yy);
+ dir = Vector3(det_x,xz * yz - xy * zz,xy * yz - xz * yy);
else if (det_max == det_y)
dir = Vector3(xz * yz - xy * zz, det_y, xy * xz - yz * xx);
else if (det_max == det_z)
@@ -1604,7 +1743,8 @@ private:
return isNormalized(*normal);
}
- static bool computeEigen(const Vector3 *points, uint32_t pointsCount, Basis *basis) {
+ static bool computeEigen(const Vector3 *points, uint32_t pointsCount, Basis *basis)
+ {
float matrix[6];
computeCovariance(pointsCount, points, matrix);
if (matrix[0] == 0 && matrix[3] == 0 && matrix[5] == 0)
@@ -1619,7 +1759,8 @@ private:
return true;
}
- static Vector3 computeCentroid(int n, const Vector3 *points) {
+ static Vector3 computeCentroid(int n, const Vector3 * points)
+ {
Vector3 centroid(0.0f);
for (int i = 0; i < n; i++) {
centroid += points[i];
@@ -1628,7 +1769,8 @@ private:
return centroid;
}
- static Vector3 computeCovariance(int n, const Vector3 *points, float *covariance) {
+ static Vector3 computeCovariance(int n, const Vector3 * points, float * covariance)
+ {
// compute the centroid
Vector3 centroid = computeCentroid(n, points);
// compute covariance matrix
@@ -1650,7 +1792,8 @@ private:
// Tridiagonal solver from Charles Bloom.
// Householder transforms followed by QL decomposition.
// Seems to be based on the code from Numerical Recipes in C.
- static bool eigenSolveSymmetric3(const float matrix[6], float eigenValues[3], Vector3 eigenVectors[3]) {
+ static bool eigenSolveSymmetric3(const float matrix[6], float eigenValues[3], Vector3 eigenVectors[3])
+ {
XA_DEBUG_ASSERT(matrix != nullptr && eigenValues != nullptr && eigenVectors != nullptr);
float subd[3];
float diag[3];
@@ -1675,7 +1818,7 @@ private:
// eigenvectors are the columns; make them the rows :
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
- (&eigenVectors[j].x)[i] = (float)work[i][j];
+ (&eigenVectors[j].x)[i] = (float) work[i][j];
}
}
// shuffle to sort by singular value :
@@ -1697,7 +1840,8 @@ private:
}
private:
- static void EigenSolver3_Tridiagonal(float mat[3][3], float *diag, float *subd) {
+ static void EigenSolver3_Tridiagonal(float mat[3][3], float *diag, float *subd)
+ {
// Householder reduction T = Q^t M Q
// Input:
// mat, symmetric 3x3 matrix M
@@ -1749,7 +1893,8 @@ private:
}
}
- static bool EigenSolver3_QLAlgorithm(float mat[3][3], float *diag, float *subd) {
+ static bool EigenSolver3_QLAlgorithm(float mat[3][3], float *diag, float *subd)
+ {
// QL iteration with implicit shifting to reduce matrix from tridiagonal
// to diagonal
const int maxiter = 32;
@@ -1759,21 +1904,21 @@ private:
int m;
for (m = ell; m <= 1; m++) {
float dd = fabsf(diag[m]) + fabsf(diag[m + 1]);
- if (fabsf(subd[m]) + dd == dd)
+ if ( fabsf(subd[m]) + dd == dd )
break;
}
- if (m == ell)
+ if ( m == ell )
break;
float g = (diag[ell + 1] - diag[ell]) / (2 * subd[ell]);
float r = sqrtf(g * g + 1);
- if (g < 0)
+ if ( g < 0 )
g = diag[m] - diag[ell] + subd[ell] / (g - r);
else
g = diag[m] - diag[ell] + subd[ell] / (g + r);
float s = 1, c = 1, p = 0;
for (int i = m - 1; i >= ell; i--) {
float f = s * subd[i], b = c * subd[i];
- if (fabsf(f) >= fabsf(g)) {
+ if ( fabsf(f) >= fabsf(g) ) {
c = g / f;
r = sqrtf(c * c + 1);
subd[i + 1] = f * r;
@@ -1799,7 +1944,7 @@ private:
subd[ell] = g;
subd[m] = 0;
}
- if (iter == maxiter)
+ if ( iter == maxiter )
// should not get here under normal circumstances
return false;
}
@@ -1807,50 +1952,77 @@ private:
}
};
-/// Fixed size vector class.
-class FullVector {
-public:
- FullVector(uint32_t dim) :
- m_array(MemTag::FullVector) { m_array.resize(dim); }
- FullVector(const FullVector &v) :
- m_array(MemTag::FullVector) { v.m_array.copyTo(m_array); }
- FullVector &operator=(const FullVector &v) = delete;
- XA_INLINE uint32_t dimension() const { return m_array.size(); }
- XA_INLINE const float &operator[](uint32_t index) const { return m_array[index]; }
- XA_INLINE float &operator[](uint32_t index) { return m_array[index]; }
-
- void fill(float f) {
- const uint32_t dim = dimension();
- for (uint32_t i = 0; i < dim; i++)
- m_array[i] = f;
+static uint32_t sdbmHash(const void *data_in, uint32_t size, uint32_t h = 5381)
+{
+ const uint8_t *data = (const uint8_t *) data_in;
+ uint32_t i = 0;
+ while (i < size) {
+ h = (h << 16) + (h << 6) - h + (uint32_t ) data[i++];
}
+ return h;
+}
-private:
- Array<float> m_array;
+template <typename T>
+static uint32_t hash(const T &t, uint32_t h = 5381)
+{
+ return sdbmHash(&t, sizeof(T), h);
+}
+
+template <typename Key>
+struct Hash
+{
+ uint32_t operator()(const Key &k) const { return hash(k); }
};
-template <typename Key, typename H = Hash<Key>, typename E = Equal<Key>>
-class HashMap {
+template <typename Key>
+struct PassthroughHash
+{
+ uint32_t operator()(const Key &k) const { return (uint32_t)k; }
+};
+
+template <typename Key>
+struct Equal
+{
+ bool operator()(const Key &k0, const Key &k1) const { return k0 == k1; }
+};
+
+template<typename Key, typename H = Hash<Key>, typename E = Equal<Key> >
+class HashMap
+{
public:
- HashMap(int memTag, uint32_t size) :
- m_memTag(memTag), m_size(size), m_numSlots(0), m_slots(nullptr), m_keys(memTag), m_next(memTag) {
+ HashMap(int memTag, uint32_t size) : m_memTag(memTag), m_size(size), m_numSlots(0), m_slots(nullptr), m_keys(memTag), m_next(memTag)
+ {
}
- ~HashMap() {
+ ~HashMap()
+ {
if (m_slots)
XA_FREE(m_slots);
}
- void add(const Key &key) {
+ void destroy()
+ {
+ if (m_slots) {
+ XA_FREE(m_slots);
+ m_slots = nullptr;
+ }
+ m_keys.destroy();
+ m_next.destroy();
+ }
+
+ uint32_t add(const Key &key)
+ {
if (!m_slots)
alloc();
const uint32_t hash = computeHash(key);
m_keys.push_back(key);
m_next.push_back(m_slots[hash]);
m_slots[hash] = m_next.size() - 1;
+ return m_keys.size() - 1;
}
- uint32_t get(const Key &key) const {
+ uint32_t get(const Key &key) const
+ {
if (!m_slots)
return UINT32_MAX;
const uint32_t hash = computeHash(key);
@@ -1864,7 +2036,8 @@ public:
return UINT32_MAX;
}
- uint32_t getNext(uint32_t current) const {
+ uint32_t getNext(uint32_t current) const
+ {
uint32_t i = m_next[current];
E equal;
while (i != UINT32_MAX) {
@@ -1876,7 +2049,8 @@ public:
}
private:
- void alloc() {
+ void alloc()
+ {
XA_DEBUG_ASSERT(m_size > 0);
m_numSlots = nextPowerOfTwo(m_size);
auto minNumSlots = uint32_t(m_size * 1.3);
@@ -1889,7 +2063,8 @@ private:
m_next.reserve(m_size);
}
- uint32_t computeHash(const Key &key) const {
+ uint32_t computeHash(const Key &key) const
+ {
H hash;
return hash(key) & (m_numSlots - 1);
}
@@ -1902,8 +2077,9 @@ private:
Array<uint32_t> m_next;
};
-template <typename T>
-static void insertionSort(T *data, uint32_t length) {
+template<typename T>
+static void insertionSort(T *data, uint32_t length)
+{
for (int32_t i = 1; i < (int32_t)length; i++) {
T x = data[i];
int32_t j = i - 1;
@@ -1915,18 +2091,21 @@ static void insertionSort(T *data, uint32_t length) {
}
}
-class KISSRng {
+class KISSRng
+{
public:
KISSRng() { reset(); }
- void reset() {
+ void reset()
+ {
x = 123456789;
y = 362436000;
z = 521288629;
c = 7654321;
}
- uint32_t getRange(uint32_t range) {
+ uint32_t getRange(uint32_t range)
+ {
if (range == 0)
return 0;
x = 69069 * x + 12345;
@@ -1935,7 +2114,7 @@ public:
y ^= (y << 5);
uint64_t t = 698769069ULL * z + c;
c = (t >> 32);
- return (x + y + (z = (uint32_t)t)) % range;
+ return (x + y + (z = (uint32_t)t)) % (range + 1);
}
private:
@@ -1945,76 +2124,70 @@ private:
// Based on Pierre Terdiman's and Michael Herf's source code.
// http://www.codercorner.com/RadixSortRevisited.htm
// http://www.stereopsis.com/radix.html
-class RadixSort {
+class RadixSort
+{
public:
- RadixSort() :
- m_size(0), m_ranks(nullptr), m_ranks2(nullptr), m_validRanks(false) {}
-
- ~RadixSort() {
- // Release everything
- XA_FREE(m_ranks2);
- XA_FREE(m_ranks);
- }
-
- RadixSort &sort(const float *input, uint32_t count) {
- if (input == nullptr || count == 0) return *this;
- // Resize lists if needed
- if (count != m_size) {
- if (count > m_size) {
- m_ranks2 = XA_REALLOC(MemTag::Default, m_ranks2, uint32_t, count);
- m_ranks = XA_REALLOC(MemTag::Default, m_ranks, uint32_t, count);
- }
- m_size = count;
- m_validRanks = false;
+ void sort(const float *input, uint32_t count)
+ {
+ if (input == nullptr || count == 0) {
+ m_buffer1.clear();
+ m_buffer2.clear();
+ m_ranks = m_buffer1.data();
+ m_ranks2 = m_buffer2.data();
+ return;
}
- if (count < 32) {
+ // Resize lists if needed
+ m_buffer1.resize(count);
+ m_buffer2.resize(count);
+ m_ranks = m_buffer1.data();
+ m_ranks2 = m_buffer2.data();
+ m_validRanks = false;
+ if (count < 32)
insertionSort(input, count);
- } else {
+ else {
// @@ Avoid touching the input multiple times.
for (uint32_t i = 0; i < count; i++) {
- FloatFlip((uint32_t &)input[i]);
+ floatFlip((uint32_t &)input[i]);
}
radixSort<uint32_t>((const uint32_t *)input, count);
for (uint32_t i = 0; i < count; i++) {
- IFloatFlip((uint32_t &)input[i]);
+ ifloatFlip((uint32_t &)input[i]);
}
}
- return *this;
}
- RadixSort &sort(const Array<float> &input) {
- return sort(input.data(), input.size());
+ void sort(const Array<float> &input)
+ {
+ sort(input.data(), input.size());
}
// Access to results. m_ranks is a list of indices in sorted order, i.e. in the order you may further process your data
- const uint32_t *ranks() const {
- XA_DEBUG_ASSERT(m_validRanks);
- return m_ranks;
- }
-
- uint32_t *ranks() {
+ const uint32_t *ranks() const
+ {
XA_DEBUG_ASSERT(m_validRanks);
return m_ranks;
}
private:
- uint32_t m_size;
- uint32_t *m_ranks;
- uint32_t *m_ranks2;
+ uint32_t *m_ranks, *m_ranks2;
+ Array<uint32_t> m_buffer1, m_buffer2;
bool m_validRanks;
- void FloatFlip(uint32_t &f) {
+ void floatFlip(uint32_t &f)
+ {
int32_t mask = (int32_t(f) >> 31) | 0x80000000; // Warren Hunt, Manchor Ko.
f ^= mask;
}
- void IFloatFlip(uint32_t &f) {
+ void ifloatFlip(uint32_t &f)
+ {
uint32_t mask = ((f >> 31) - 1) | 0x80000000; // Michael Herf.
f ^= mask;
}
- template <typename T>
- void createHistograms(const T *buffer, uint32_t count, uint32_t *histogram) {
+ template<typename T>
+ void createHistograms(const T *buffer, uint32_t count, uint32_t *histogram)
+ {
const uint32_t bucketCount = sizeof(T); // (8 * sizeof(T)) / log2(radix)
// Init bucket pointers.
uint32_t *h[bucketCount];
@@ -2022,10 +2195,10 @@ private:
h[i] = histogram + 256 * i;
}
// Clear histograms.
- memset(histogram, 0, 256 * bucketCount * sizeof(uint32_t));
+ memset(histogram, 0, 256 * bucketCount * sizeof(uint32_t ));
// @@ Add support for signed integers.
// Build histograms.
- const uint8_t *p = (const uint8_t *)buffer; // @@ Does this break aliasing rules?
+ const uint8_t *p = (const uint8_t *)buffer; // @@ Does this break aliasing rules?
const uint8_t *pe = p + count * sizeof(T);
while (p != pe) {
h[0][*p++]++, h[1][*p++]++, h[2][*p++]++, h[3][*p++]++;
@@ -2041,7 +2214,8 @@ private:
}
template <typename T>
- void insertionSort(const T *input, uint32_t count) {
+ void insertionSort(const T *input, uint32_t count)
+ {
if (!m_validRanks) {
m_ranks[0] = 0;
for (uint32_t i = 1; i != count; ++i) {
@@ -2072,7 +2246,8 @@ private:
}
template <typename T>
- void radixSort(const T *input, uint32_t count) {
+ void radixSort(const T *input, uint32_t count)
+ {
const uint32_t P = sizeof(T); // pass count
// Allocate histograms & offsets on the stack
uint32_t histogram[256 * P];
@@ -2090,8 +2265,7 @@ private:
}
// Create offsets
link[0] = m_ranks2;
- for (uint32_t i = 1; i < 256; i++)
- link[i] = link[i - 1] + h[i - 1];
+ for (uint32_t i = 1; i < 256; i++) link[i] = link[i - 1] + h[i - 1];
// Perform Radix Sort
if (!m_validRanks) {
for (uint32_t i = 0; i < count; i++) {
@@ -2109,30 +2283,33 @@ private:
}
// All values were equal, generate linear ranks.
if (!m_validRanks) {
- for (uint32_t i = 0; i < count; i++) {
+ for (uint32_t i = 0; i < count; i++)
m_ranks[i] = i;
- }
m_validRanks = true;
}
}
};
// Wrapping this in a class allows temporary arrays to be re-used.
-class BoundingBox2D {
+class BoundingBox2D
+{
public:
Vector2 majorAxis, minorAxis, minCorner, maxCorner;
- void clear() {
+ void clear()
+ {
m_boundaryVertices.clear();
}
- void appendBoundaryVertex(Vector2 v) {
+ void appendBoundaryVertex(Vector2 v)
+ {
m_boundaryVertices.push_back(v);
}
// This should compute convex hull and use rotating calipers to find the best box. Currently it uses a brute force method.
// If vertices is null or vertexCount is 0, the boundary vertices are used.
- void compute(const Vector2 *vertices = nullptr, uint32_t vertexCount = 0) {
+ void compute(const Vector2 *vertices = nullptr, uint32_t vertexCount = 0)
+ {
if (!vertices || vertexCount == 0) {
vertices = m_boundaryVertices.data();
vertexCount = m_boundaryVertices.size();
@@ -2180,13 +2357,13 @@ public:
private:
// Compute the convex hull using Graham Scan.
- void convexHull(const Vector2 *input, uint32_t inputCount, Array<Vector2> &output, float epsilon) {
+ void convexHull(const Vector2 *input, uint32_t inputCount, Array<Vector2> &output, float epsilon)
+ {
m_coords.resize(inputCount);
for (uint32_t i = 0; i < inputCount; i++)
m_coords[i] = input[i].x;
- RadixSort radix;
- radix.sort(m_coords);
- const uint32_t *ranks = radix.ranks();
+ m_radix.sort(m_coords);
+ const uint32_t *ranks = m_radix.ranks();
m_top.clear();
m_bottom.clear();
m_top.reserve(inputCount);
@@ -2210,7 +2387,7 @@ private:
XA_DEBUG_ASSERT(m_top.size() >= 2);
output.push_back(m_top[0]);
output.push_back(m_top[1]);
- for (uint32_t i = 2; i < m_top.size();) {
+ for (uint32_t i = 2; i < m_top.size(); ) {
Vector2 a = output[output.size() - 2];
Vector2 b = output[output.size() - 1];
Vector2 c = m_top[i];
@@ -2226,7 +2403,7 @@ private:
XA_DEBUG_ASSERT(m_bottom.size() >= 2);
output.push_back(m_bottom[1]);
// Filter bottom list.
- for (uint32_t i = 2; i < m_bottom.size();) {
+ for (uint32_t i = 2; i < m_bottom.size(); ) {
Vector2 a = output[output.size() - 2];
Vector2 b = output[output.size() - 1];
Vector2 c = m_bottom[i];
@@ -2246,51 +2423,49 @@ private:
Array<Vector2> m_boundaryVertices;
Array<float> m_coords;
Array<Vector2> m_top, m_bottom, m_hull;
+ RadixSort m_radix;
};
-static uint32_t meshEdgeFace(uint32_t edge) {
- return edge / 3;
-}
-static uint32_t meshEdgeIndex0(uint32_t edge) {
- return edge;
-}
+static uint32_t meshEdgeFace(uint32_t edge) { return edge / 3; }
+static uint32_t meshEdgeIndex0(uint32_t edge) { return edge; }
-static uint32_t meshEdgeIndex1(uint32_t edge) {
+static uint32_t meshEdgeIndex1(uint32_t edge)
+{
const uint32_t faceFirstEdge = edge / 3 * 3;
return faceFirstEdge + (edge - faceFirstEdge + 1) % 3;
}
-struct MeshFlags {
- enum {
- HasFaceGroups = 1 << 0,
- HasIgnoredFaces = 1 << 1,
- HasNormals = 1 << 2
+struct MeshFlags
+{
+ enum
+ {
+ HasIgnoredFaces = 1<<0,
+ HasNormals = 1<<1
};
};
class Mesh;
static void meshGetBoundaryLoops(const Mesh &mesh, Array<uint32_t> &boundaryLoops);
-class Mesh {
+class Mesh
+{
public:
- Mesh(float epsilon, uint32_t approxVertexCount, uint32_t approxFaceCount, uint32_t flags = 0, uint32_t id = UINT32_MAX) :
- m_epsilon(epsilon), m_flags(flags), m_id(id), m_faceIgnore(MemTag::Mesh), m_ignoredFaceCount(0), m_indices(MemTag::MeshIndices), m_positions(MemTag::MeshPositions), m_normals(MemTag::MeshNormals), m_texcoords(MemTag::MeshTexcoords), m_faceGroups(MemTag::Mesh), m_faceGroupFirstFace(MemTag::Mesh), m_faceGroupNextFace(MemTag::Mesh), m_faceGroupFaceCounts(MemTag::Mesh), m_colocalVertexCount(0), m_nextColocalVertex(MemTag::MeshColocals), m_boundaryEdges(MemTag::MeshBoundaries), m_oppositeEdges(MemTag::MeshBoundaries), m_nextBoundaryEdges(MemTag::MeshBoundaries), m_edgeMap(MemTag::MeshEdgeMap, approxFaceCount * 3) {
+ Mesh(float epsilon, uint32_t approxVertexCount, uint32_t approxFaceCount, uint32_t flags = 0, uint32_t id = UINT32_MAX) : m_epsilon(epsilon), m_flags(flags), m_id(id), m_faceIgnore(MemTag::Mesh), m_indices(MemTag::MeshIndices), m_positions(MemTag::MeshPositions), m_normals(MemTag::MeshNormals), m_texcoords(MemTag::MeshTexcoords), m_nextColocalVertex(MemTag::MeshColocals), m_boundaryEdges(MemTag::MeshBoundaries), m_oppositeEdges(MemTag::MeshBoundaries), m_nextBoundaryEdges(MemTag::MeshBoundaries), m_edgeMap(MemTag::MeshEdgeMap, approxFaceCount * 3)
+ {
m_indices.reserve(approxFaceCount * 3);
m_positions.reserve(approxVertexCount);
m_texcoords.reserve(approxVertexCount);
- if (m_flags & MeshFlags::HasFaceGroups)
- m_faceGroups.reserve(approxFaceCount);
if (m_flags & MeshFlags::HasIgnoredFaces)
m_faceIgnore.reserve(approxFaceCount);
if (m_flags & MeshFlags::HasNormals)
m_normals.reserve(approxVertexCount);
}
- static constexpr uint16_t kInvalidFaceGroup = UINT16_MAX;
uint32_t flags() const { return m_flags; }
uint32_t id() const { return m_id; }
- void addVertex(const Vector3 &pos, const Vector3 &normal = Vector3(0.0f), const Vector2 &texcoord = Vector2(0.0f)) {
+ void addVertex(const Vector3 &pos, const Vector3 &normal = Vector3(0.0f), const Vector2 &texcoord = Vector2(0.0f))
+ {
XA_DEBUG_ASSERT(isFinite(pos));
m_positions.push_back(pos);
if (m_flags & MeshFlags::HasNormals)
@@ -2298,47 +2473,45 @@ public:
m_texcoords.push_back(texcoord);
}
- struct AddFaceResult {
- enum Enum {
+ struct AddFaceResult
+ {
+ enum Enum
+ {
OK,
DuplicateEdge = 1
};
};
- AddFaceResult::Enum addFace(uint32_t v0, uint32_t v1, uint32_t v2, bool ignore = false, bool hashEdge = true) {
+ AddFaceResult::Enum addFace(uint32_t v0, uint32_t v1, uint32_t v2, bool ignore = false)
+ {
uint32_t indexArray[3];
indexArray[0] = v0;
indexArray[1] = v1;
indexArray[2] = v2;
- return addFace(indexArray, ignore, hashEdge);
+ return addFace(indexArray, ignore);
}
- AddFaceResult::Enum addFace(const uint32_t *indices, bool ignore = false, bool hashEdge = true) {
+ AddFaceResult::Enum addFace(const uint32_t *indices, bool ignore = false)
+ {
AddFaceResult::Enum result = AddFaceResult::OK;
- if (m_flags & MeshFlags::HasFaceGroups)
- m_faceGroups.push_back(kInvalidFaceGroup);
- if (m_flags & MeshFlags::HasIgnoredFaces) {
+ if (m_flags & MeshFlags::HasIgnoredFaces)
m_faceIgnore.push_back(ignore);
- if (ignore)
- m_ignoredFaceCount++;
- }
const uint32_t firstIndex = m_indices.size();
for (uint32_t i = 0; i < 3; i++)
m_indices.push_back(indices[i]);
- if (hashEdge) {
- for (uint32_t i = 0; i < 3; i++) {
- const uint32_t vertex0 = m_indices[firstIndex + i];
- const uint32_t vertex1 = m_indices[firstIndex + (i + 1) % 3];
- const EdgeKey key(vertex0, vertex1);
- if (m_edgeMap.get(key) != UINT32_MAX)
- result = AddFaceResult::DuplicateEdge;
- m_edgeMap.add(key);
- }
+ for (uint32_t i = 0; i < 3; i++) {
+ const uint32_t vertex0 = m_indices[firstIndex + i];
+ const uint32_t vertex1 = m_indices[firstIndex + (i + 1) % 3];
+ const EdgeKey key(vertex0, vertex1);
+ if (m_edgeMap.get(key) != UINT32_MAX)
+ result = AddFaceResult::DuplicateEdge;
+ m_edgeMap.add(key);
}
return result;
}
- void createColocals() {
+ void createColocals()
+ {
const uint32_t vertexCount = m_positions.size();
Array<AABB> aabbs(MemTag::BVH);
aabbs.resize(vertexCount);
@@ -2347,10 +2520,8 @@ public:
BVH bvh(aabbs);
Array<uint32_t> colocals(MemTag::MeshColocals);
Array<uint32_t> potential(MemTag::MeshColocals);
- m_colocalVertexCount = 0;
m_nextColocalVertex.resize(vertexCount);
- for (uint32_t i = 0; i < vertexCount; i++)
- m_nextColocalVertex[i] = UINT32_MAX;
+ m_nextColocalVertex.fillBytes(0xff);
for (uint32_t i = 0; i < vertexCount; i++) {
if (m_nextColocalVertex[i] != UINT32_MAX)
continue; // Already linked.
@@ -2366,9 +2537,8 @@ public:
if (colocals.size() == 1) {
// No colocals for this vertex.
m_nextColocalVertex[i] = i;
- continue;
+ continue;
}
- m_colocalVertexCount += colocals.size();
// Link in ascending order.
insertionSort(colocals.data(), colocals.size());
for (uint32_t j = 0; j < colocals.size(); j++)
@@ -2377,98 +2547,8 @@ public:
}
}
- // Check if the face duplicates any edges of any face already in the group.
- bool faceDuplicatesGroupEdge(uint16_t group, uint32_t face) const {
- for (FaceEdgeIterator edgeIt(this, face); !edgeIt.isDone(); edgeIt.advance()) {
- for (ColocalEdgeIterator colocalEdgeIt(this, edgeIt.vertex0(), edgeIt.vertex1()); !colocalEdgeIt.isDone(); colocalEdgeIt.advance()) {
- if (m_faceGroups[meshEdgeFace(colocalEdgeIt.edge())] == group)
- return true;
- }
- }
- return false;
- }
-
- void createFaceGroups() {
- uint32_t firstUnassignedFace = 0;
- uint16_t group = 0;
- Array<uint32_t> growFaces;
- const uint32_t n = faceCount();
- m_faceGroupNextFace.resize(n);
- for (;;) {
- // Find an unassigned face.
- uint32_t face = UINT32_MAX;
- for (uint32_t f = firstUnassignedFace; f < n; f++) {
- if (m_faceGroups[f] == kInvalidFaceGroup && !isFaceIgnored(f)) {
- face = f;
- firstUnassignedFace = f + 1;
- break;
- }
- }
- if (face == UINT32_MAX)
- break; // All faces assigned to a group (except ignored faces).
- m_faceGroups[face] = group;
- m_faceGroupNextFace[face] = UINT32_MAX;
- m_faceGroupFirstFace.push_back(face);
- growFaces.clear();
- growFaces.push_back(face);
- uint32_t prevFace = face, groupFaceCount = 1;
- // Find faces connected to the face and assign them to the same group as the face, unless they are already assigned to another group.
- for (;;) {
- if (growFaces.isEmpty())
- break;
- const uint32_t f = growFaces.back();
- growFaces.pop_back();
- for (FaceEdgeIterator edgeIt(this, f); !edgeIt.isDone(); edgeIt.advance()) {
- // Iterate opposite edges. There may be more than one - non-manifold geometry can have duplicate edges.
- // Prioritize the one with exact vertex match, not just colocal.
- // If *any* of the opposite edges are already assigned to this group, don't do anything.
- bool alreadyAssignedToThisGroup = false;
- uint32_t bestConnectedFace = UINT32_MAX;
- for (ColocalEdgeIterator oppositeEdgeIt(this, edgeIt.vertex1(), edgeIt.vertex0()); !oppositeEdgeIt.isDone(); oppositeEdgeIt.advance()) {
- const uint32_t oppositeEdge = oppositeEdgeIt.edge();
- const uint32_t oppositeFace = meshEdgeFace(oppositeEdge);
- if (isFaceIgnored(oppositeFace))
- continue; // Don't add ignored faces to group.
- if (m_faceGroups[oppositeFace] == group) {
- alreadyAssignedToThisGroup = true;
- break;
- }
- if (m_faceGroups[oppositeFace] != kInvalidFaceGroup)
- continue; // Connected face is already assigned to another group.
- if (faceDuplicatesGroupEdge(group, oppositeFace))
- continue; // Don't want duplicate edges in a group.
- const uint32_t oppositeVertex0 = m_indices[meshEdgeIndex0(oppositeEdge)];
- const uint32_t oppositeVertex1 = m_indices[meshEdgeIndex1(oppositeEdge)];
- if (bestConnectedFace == UINT32_MAX || (oppositeVertex0 == edgeIt.vertex1() && oppositeVertex1 == edgeIt.vertex0()))
- bestConnectedFace = oppositeFace;
-#if 0
- else {
- // Choose the opposite face with the smallest dihedral angle.
- const float d1 = 1.0f - dot(computeFaceNormal(f), computeFaceNormal(bestConnectedFace));
- const float d2 = 1.0f - dot(computeFaceNormal(f), computeFaceNormal(oppositeFace));
- if (d2 < d1)
- bestConnectedFace = oppositeFace;
- }
-#endif
- }
- if (!alreadyAssignedToThisGroup && bestConnectedFace != UINT32_MAX) {
- m_faceGroups[bestConnectedFace] = group;
- m_faceGroupNextFace[bestConnectedFace] = UINT32_MAX;
- if (prevFace != UINT32_MAX)
- m_faceGroupNextFace[prevFace] = bestConnectedFace;
- prevFace = bestConnectedFace;
- groupFaceCount++;
- growFaces.push_back(bestConnectedFace);
- }
- }
- }
- m_faceGroupFaceCounts.push_back(groupFaceCount);
- group++;
- XA_ASSERT(group < kInvalidFaceGroup);
- }
- }
-
- void createBoundaries() {
+ void createBoundaries()
+ {
const uint32_t edgeCount = m_indices.size();
const uint32_t vertexCount = m_positions.size();
m_oppositeEdges.resize(edgeCount);
@@ -2498,7 +2578,8 @@ public:
}
}
- void linkBoundaries() {
+ void linkBoundaries()
+ {
const uint32_t edgeCount = m_indices.size();
HashMap<uint32_t> vertexToEdgeMap(MemTag::Mesh, edgeCount); // Edge is index / 2
for (uint32_t i = 0; i < edgeCount; i++) {
@@ -2591,7 +2672,8 @@ public:
}
/// Find edge, test all colocals.
- uint32_t findEdge(uint32_t vertex0, uint32_t vertex1) const {
+ uint32_t findEdge(uint32_t vertex0, uint32_t vertex1) const
+ {
uint32_t result = UINT32_MAX;
if (m_nextColocalVertex.isEmpty()) {
EdgeKey key(vertex0, vertex1);
@@ -2629,8 +2711,18 @@ public:
return result;
}
+ // Edge map can be destroyed when no longer used to reduce memory usage. It's used by:
+ // * Mesh::createBoundaries()
+ // * Mesh::ColocalEdgeIterator (used by MeshFaceGroups)
+ // * meshCloseHole()
+ void destroyEdgeMap()
+ {
+ m_edgeMap.destroy();
+ }
+
#if XA_DEBUG_EXPORT_OBJ
- void writeObjVertices(FILE *file) const {
+ void writeObjVertices(FILE *file) const
+ {
for (uint32_t i = 0; i < m_positions.size(); i++)
fprintf(file, "v %g %g %g\n", m_positions[i].x, m_positions[i].y, m_positions[i].z);
if (m_flags & MeshFlags::HasNormals) {
@@ -2641,15 +2733,17 @@ public:
fprintf(file, "vt %g %g\n", m_texcoords[i].x, m_texcoords[i].y);
}
- void writeObjFace(FILE *file, uint32_t face) const {
+ void writeObjFace(FILE *file, uint32_t face, uint32_t offset = 0) const
+ {
fprintf(file, "f ");
for (uint32_t j = 0; j < 3; j++) {
- const uint32_t index = m_indices[face * 3 + j] + 1; // 1-indexed
+ const uint32_t index = m_indices[face * 3 + j] + 1 + offset; // 1-indexed
fprintf(file, "%d/%d/%d%c", index, index, index, j == 2 ? '\n' : ' ');
}
}
- void writeObjBoundaryEges(FILE *file) const {
+ void writeObjBoundaryEges(FILE *file) const
+ {
if (m_oppositeEdges.isEmpty())
return; // Boundaries haven't been created.
fprintf(file, "o boundary_edges\n");
@@ -2660,7 +2754,8 @@ public:
}
}
- void writeObjLinkedBoundaries(FILE *file) const {
+ void writeObjLinkedBoundaries(FILE *file) const
+ {
if (m_oppositeEdges.isEmpty() || m_nextBoundaryEdges.isEmpty())
return; // Boundaries haven't been created and/or linked.
Array<uint32_t> boundaryLoops;
@@ -2682,7 +2777,8 @@ public:
}
}
- void writeObjFile(const char *filename) const {
+ void writeObjFile(const char *filename) const
+ {
FILE *file;
XA_FOPEN(file, filename, "w");
if (!file)
@@ -2698,7 +2794,8 @@ public:
}
#endif
- float computeSurfaceArea() const {
+ float computeSurfaceArea() const
+ {
float area = 0;
for (uint32_t f = 0; f < faceCount(); f++)
area += computeFaceArea(f);
@@ -2706,21 +2803,25 @@ public:
return area;
}
- float computeParametricArea() const {
+ // Returned value is always positive, even if some triangles are flipped.
+ float computeParametricArea() const
+ {
float area = 0;
for (uint32_t f = 0; f < faceCount(); f++)
- area += computeFaceParametricArea(f);
- return fabsf(area); // May be negative, depends on texcoord winding.
+ area += fabsf(computeFaceParametricArea(f)); // May be negative, depends on texcoord winding.
+ return area;
}
- float computeFaceArea(uint32_t face) const {
+ float computeFaceArea(uint32_t face) const
+ {
const Vector3 &p0 = m_positions[m_indices[face * 3 + 0]];
const Vector3 &p1 = m_positions[m_indices[face * 3 + 1]];
const Vector3 &p2 = m_positions[m_indices[face * 3 + 2]];
return length(cross(p1 - p0, p2 - p0)) * 0.5f;
}
- Vector3 computeFaceCentroid(uint32_t face) const {
+ Vector3 computeFaceCentroid(uint32_t face) const
+ {
Vector3 sum(0.0f);
for (uint32_t i = 0; i < 3; i++)
sum += m_positions[m_indices[face * 3 + i]];
@@ -2729,7 +2830,8 @@ public:
// Average of the edge midpoints weighted by the edge length.
// I want a point inside the triangle, but closer to the cirumcenter.
- Vector3 computeFaceCenter(uint32_t face) const {
+ Vector3 computeFaceCenter(uint32_t face) const
+ {
const Vector3 &p0 = m_positions[m_indices[face * 3 + 0]];
const Vector3 &p1 = m_positions[m_indices[face * 3 + 1]];
const Vector3 &p2 = m_positions[m_indices[face * 3 + 2]];
@@ -2742,7 +2844,8 @@ public:
return m0 + m1 + m2;
}
- Vector3 computeFaceNormal(uint32_t face) const {
+ Vector3 computeFaceNormal(uint32_t face) const
+ {
const Vector3 &p0 = m_positions[m_indices[face * 3 + 0]];
const Vector3 &p1 = m_positions[m_indices[face * 3 + 1]];
const Vector3 &p2 = m_positions[m_indices[face * 3 + 2]];
@@ -2752,15 +2855,17 @@ public:
return normalizeSafe(normalAreaScaled, Vector3(0, 0, 1), 0.0f);
}
- float computeFaceParametricArea(uint32_t face) const {
+ float computeFaceParametricArea(uint32_t face) const
+ {
const Vector2 &t0 = m_texcoords[m_indices[face * 3 + 0]];
const Vector2 &t1 = m_texcoords[m_indices[face * 3 + 1]];
const Vector2 &t2 = m_texcoords[m_indices[face * 3 + 2]];
return triangleArea(t0, t1, t2);
}
-
+
// @@ This is not exactly accurate, we should compare the texture coordinates...
- bool isSeam(uint32_t edge) const {
+ bool isSeam(uint32_t edge) const
+ {
const uint32_t oppositeEdge = m_oppositeEdges[edge];
if (oppositeEdge == UINT32_MAX)
return false; // boundary edge
@@ -2771,7 +2876,8 @@ public:
return m_indices[e0] != m_indices[oe1] || m_indices[e1] != m_indices[oe0];
}
- bool isTextureSeam(uint32_t edge) const {
+ bool isTextureSeam(uint32_t edge) const
+ {
const uint32_t oppositeEdge = m_oppositeEdges[edge];
if (oppositeEdge == UINT32_MAX)
return false; // boundary edge
@@ -2782,7 +2888,8 @@ public:
return m_texcoords[m_indices[e0]] != m_texcoords[m_indices[oe1]] || m_texcoords[m_indices[e1]] != m_texcoords[m_indices[oe0]];
}
- uint32_t firstColocal(uint32_t vertex) const {
+ uint32_t firstColocal(uint32_t vertex) const
+ {
for (ColocalVertexIterator it(this, vertex); !it.isDone(); it.advance()) {
if (it.vertex() < vertex)
vertex = it.vertex();
@@ -2790,7 +2897,8 @@ public:
return vertex;
}
- bool areColocal(uint32_t vertex0, uint32_t vertex1) const {
+ bool areColocal(uint32_t vertex0, uint32_t vertex1) const
+ {
if (vertex0 == vertex1)
return true;
if (m_nextColocalVertex.isEmpty())
@@ -2808,60 +2916,32 @@ public:
XA_INLINE bool isBoundaryEdge(uint32_t edge) const { return m_oppositeEdges[edge] == UINT32_MAX; }
XA_INLINE const Array<uint32_t> &boundaryEdges() const { return m_boundaryEdges; }
XA_INLINE bool isBoundaryVertex(uint32_t vertex) const { return m_isBoundaryVertex.get(vertex); }
- XA_INLINE uint32_t colocalVertexCount() const { return m_colocalVertexCount; }
XA_INLINE uint32_t vertexCount() const { return m_positions.size(); }
XA_INLINE uint32_t vertexAt(uint32_t i) const { return m_indices[i]; }
XA_INLINE const Vector3 &position(uint32_t vertex) const { return m_positions[vertex]; }
- XA_INLINE const Vector3 &normal(uint32_t vertex) const {
- XA_DEBUG_ASSERT(m_flags & MeshFlags::HasNormals);
- return m_normals[vertex];
- }
+ XA_INLINE const Vector3 *positions() const { return m_positions.data(); }
+ XA_INLINE const Vector3 &normal(uint32_t vertex) const { XA_DEBUG_ASSERT(m_flags & MeshFlags::HasNormals); return m_normals[vertex]; }
XA_INLINE const Vector2 &texcoord(uint32_t vertex) const { return m_texcoords[vertex]; }
XA_INLINE Vector2 &texcoord(uint32_t vertex) { return m_texcoords[vertex]; }
XA_INLINE const Vector2 *texcoords() const { return m_texcoords.data(); }
XA_INLINE Vector2 *texcoords() { return m_texcoords.data(); }
- XA_INLINE uint32_t ignoredFaceCount() const { return m_ignoredFaceCount; }
XA_INLINE uint32_t faceCount() const { return m_indices.size() / 3; }
- XA_INLINE uint16_t faceGroupAt(uint32_t face) const {
- XA_DEBUG_ASSERT(m_flags & MeshFlags::HasFaceGroups);
- return m_faceGroups[face];
- }
- XA_INLINE uint32_t faceGroupCount() const {
- XA_DEBUG_ASSERT(m_flags & MeshFlags::HasFaceGroups);
- return m_faceGroupFaceCounts.size();
- }
- XA_INLINE uint32_t faceGroupNextFace(uint32_t face) const {
- XA_DEBUG_ASSERT(m_flags & MeshFlags::HasFaceGroups);
- return m_faceGroupNextFace[face];
- }
- XA_INLINE uint32_t faceGroupFaceCount(uint32_t group) const {
- XA_DEBUG_ASSERT(m_flags & MeshFlags::HasFaceGroups);
- return m_faceGroupFaceCounts[group];
- }
XA_INLINE const uint32_t *indices() const { return m_indices.data(); }
XA_INLINE uint32_t indexCount() const { return m_indices.size(); }
+ XA_INLINE bool isFaceIgnored(uint32_t face) const { return (m_flags & MeshFlags::HasIgnoredFaces) && m_faceIgnore[face]; }
private:
- bool isFaceIgnored(uint32_t face) const { return (m_flags & MeshFlags::HasIgnoredFaces) && m_faceIgnore[face]; }
float m_epsilon;
uint32_t m_flags;
uint32_t m_id;
Array<bool> m_faceIgnore;
- uint32_t m_ignoredFaceCount;
Array<uint32_t> m_indices;
Array<Vector3> m_positions;
Array<Vector3> m_normals;
Array<Vector2> m_texcoords;
- // Populated by createFaceGroups
- Array<uint16_t> m_faceGroups;
- Array<uint32_t> m_faceGroupFirstFace;
- Array<uint32_t> m_faceGroupNextFace; // In: face. Out: the next face in the same group.
- Array<uint32_t> m_faceGroupFaceCounts; // In: face group. Out: number of faces in the group.
-
// Populated by createColocals
- uint32_t m_colocalVertexCount;
Array<uint32_t> m_nextColocalVertex; // In: vertex index. Out: the vertex index of the next colocal position.
// Populated by createBoundaries
@@ -2872,45 +2952,48 @@ private:
// Populated by linkBoundaries
Array<uint32_t> m_nextBoundaryEdges; // The index of the next boundary edge. UINT32_MAX if the edge is not a boundary edge.
- struct EdgeKey {
- EdgeKey() {}
- EdgeKey(const EdgeKey &k) :
- v0(k.v0), v1(k.v1) {}
- EdgeKey(uint32_t v0, uint32_t v1) :
- v0(v0), v1(v1) {}
+ struct EdgeKey
+ {
+ EdgeKey(const EdgeKey &k) : v0(k.v0), v1(k.v1) {}
+ EdgeKey(uint32_t v0, uint32_t v1) : v0(v0), v1(v1) {}
bool operator==(const EdgeKey &k) const { return v0 == k.v0 && v1 == k.v1; }
uint32_t v0;
uint32_t v1;
};
- struct EdgeHash {
+ struct EdgeHash
+ {
uint32_t operator()(const EdgeKey &k) const { return k.v0 * 32768u + k.v1; }
};
HashMap<EdgeKey, EdgeHash> m_edgeMap;
public:
- class BoundaryLoopEdgeIterator {
+ class BoundaryLoopEdgeIterator
+ {
public:
- BoundaryLoopEdgeIterator(const Mesh *mesh, uint32_t edge) :
- m_mesh(mesh), m_first(UINT32_MAX), m_current(edge) {}
+ BoundaryLoopEdgeIterator(const Mesh *mesh, uint32_t edge) : m_mesh(mesh), m_first(UINT32_MAX), m_current(edge) {}
- void advance() {
+ void advance()
+ {
if (m_first == UINT32_MAX)
m_first = m_current;
m_current = m_mesh->m_nextBoundaryEdges[m_current];
}
- bool isDone() const {
+ bool isDone() const
+ {
return m_first == m_current || m_current == UINT32_MAX;
}
- uint32_t edge() const {
+ uint32_t edge() const
+ {
return m_current;
}
- uint32_t nextEdge() const {
+ uint32_t nextEdge() const
+ {
return m_mesh->m_nextBoundaryEdges[m_current];
}
@@ -2920,27 +3003,31 @@ public:
uint32_t m_current;
};
- class ColocalVertexIterator {
+ class ColocalVertexIterator
+ {
public:
- ColocalVertexIterator(const Mesh *mesh, uint32_t v) :
- m_mesh(mesh), m_first(UINT32_MAX), m_current(v) {}
+ ColocalVertexIterator(const Mesh *mesh, uint32_t v) : m_mesh(mesh), m_first(UINT32_MAX), m_current(v) {}
- void advance() {
+ void advance()
+ {
if (m_first == UINT32_MAX)
m_first = m_current;
if (!m_mesh->m_nextColocalVertex.isEmpty())
m_current = m_mesh->m_nextColocalVertex[m_current];
}
- bool isDone() const {
+ bool isDone() const
+ {
return m_first == m_current;
}
- uint32_t vertex() const {
+ uint32_t vertex() const
+ {
return m_current;
}
- const Vector3 *pos() const {
+ const Vector3 *pos() const
+ {
return &m_mesh->m_positions[m_current];
}
@@ -2950,33 +3037,39 @@ public:
uint32_t m_current;
};
- class ColocalEdgeIterator {
+ class ColocalEdgeIterator
+ {
public:
- ColocalEdgeIterator(const Mesh *mesh, uint32_t vertex0, uint32_t vertex1) :
- m_mesh(mesh), m_vertex0It(mesh, vertex0), m_vertex1It(mesh, vertex1), m_vertex1(vertex1) {
+ ColocalEdgeIterator(const Mesh *mesh, uint32_t vertex0, uint32_t vertex1) : m_mesh(mesh), m_vertex0It(mesh, vertex0), m_vertex1It(mesh, vertex1), m_vertex1(vertex1)
+ {
do {
if (!resetElement()) {
advanceVertex1();
- } else {
+ }
+ else {
break;
}
} while (!isDone());
}
- void advance() {
+ void advance()
+ {
advanceElement();
}
- bool isDone() const {
+ bool isDone() const
+ {
return m_vertex0It.isDone() && m_vertex1It.isDone() && m_edge == UINT32_MAX;
}
- uint32_t edge() const {
+ uint32_t edge() const
+ {
return m_edge;
}
private:
- bool resetElement() {
+ bool resetElement()
+ {
m_edge = m_mesh->m_edgeMap.get(Mesh::EdgeKey(m_vertex0It.vertex(), m_vertex1It.vertex()));
while (m_edge != UINT32_MAX) {
if (!isIgnoredFace())
@@ -2989,7 +3082,8 @@ public:
return true;
}
- void advanceElement() {
+ void advanceElement()
+ {
for (;;) {
m_edge = m_mesh->m_edgeMap.getNext(m_edge);
if (m_edge == UINT32_MAX)
@@ -3001,15 +3095,17 @@ public:
advanceVertex1();
}
- void advanceVertex1() {
+ void advanceVertex1()
+ {
auto successful = false;
- while (!successful) {
+ while (!successful) {
m_vertex1It.advance();
if (m_vertex1It.isDone()) {
if (!m_vertex0It.isDone()) {
m_vertex0It.advance();
m_vertex1It = ColocalVertexIterator(m_mesh, m_vertex1);
- } else {
+ }
+ else {
return;
}
}
@@ -3017,7 +3113,8 @@ public:
}
}
- bool isIgnoredFace() const {
+ bool isIgnoredFace() const
+ {
return m_mesh->m_faceIgnore[meshEdgeFace(m_edge)];
}
@@ -3027,21 +3124,24 @@ public:
uint32_t m_edge;
};
- class FaceEdgeIterator {
+ class FaceEdgeIterator
+ {
public:
- FaceEdgeIterator(const Mesh *mesh, uint32_t face) :
- m_mesh(mesh), m_face(face), m_relativeEdge(0) {
+ FaceEdgeIterator (const Mesh *mesh, uint32_t face) : m_mesh(mesh), m_face(face), m_relativeEdge(0)
+ {
m_edge = m_face * 3;
}
- void advance() {
+ void advance()
+ {
if (m_relativeEdge < 3) {
m_edge++;
m_relativeEdge++;
}
}
- bool isDone() const {
+ bool isDone() const
+ {
return m_relativeEdge == 3;
}
@@ -3052,8 +3152,9 @@ public:
uint32_t relativeEdge() const { return m_relativeEdge; }
uint32_t face() const { return m_face; }
uint32_t oppositeEdge() const { return m_mesh->m_oppositeEdges[m_edge]; }
-
- uint32_t oppositeFace() const {
+
+ uint32_t oppositeFace() const
+ {
const uint32_t oedge = m_mesh->m_oppositeEdges[m_edge];
if (oedge == UINT32_MAX)
return UINT32_MAX;
@@ -3075,36 +3176,164 @@ public:
uint32_t m_edge;
uint32_t m_relativeEdge;
};
+};
+
+struct MeshFaceGroups
+{
+ typedef uint32_t Handle;
+ static constexpr Handle kInvalid = UINT32_MAX;
+
+ MeshFaceGroups(const Mesh *mesh) : m_mesh(mesh), m_groups(MemTag::Mesh), m_firstFace(MemTag::Mesh), m_nextFace(MemTag::Mesh), m_faceCount(MemTag::Mesh) {}
+ XA_INLINE Handle groupAt(uint32_t face) const { return m_groups[face]; }
+ XA_INLINE uint32_t groupCount() const { return m_faceCount.size(); }
+ XA_INLINE uint32_t nextFace(uint32_t face) const { return m_nextFace[face]; }
+ XA_INLINE uint32_t faceCount(uint32_t group) const { return m_faceCount[group]; }
+
+ void compute()
+ {
+ m_groups.resize(m_mesh->faceCount());
+ m_groups.fillBytes(0xff); // Set all faces to kInvalid
+ uint32_t firstUnassignedFace = 0;
+ Handle group = 0;
+ Array<uint32_t> growFaces;
+ const uint32_t n = m_mesh->faceCount();
+ m_nextFace.resize(n);
+ for (;;) {
+ // Find an unassigned face.
+ uint32_t face = UINT32_MAX;
+ for (uint32_t f = firstUnassignedFace; f < n; f++) {
+ if (m_groups[f] == kInvalid && !m_mesh->isFaceIgnored(f)) {
+ face = f;
+ firstUnassignedFace = f + 1;
+ break;
+ }
+ }
+ if (face == UINT32_MAX)
+ break; // All faces assigned to a group (except ignored faces).
+ m_groups[face] = group;
+ m_nextFace[face] = UINT32_MAX;
+ m_firstFace.push_back(face);
+ growFaces.clear();
+ growFaces.push_back(face);
+ uint32_t prevFace = face, groupFaceCount = 1;
+ // Find faces connected to the face and assign them to the same group as the face, unless they are already assigned to another group.
+ for (;;) {
+ if (growFaces.isEmpty())
+ break;
+ const uint32_t f = growFaces.back();
+ growFaces.pop_back();
+ for (Mesh::FaceEdgeIterator edgeIt(m_mesh, f); !edgeIt.isDone(); edgeIt.advance()) {
+ // Iterate opposite edges. There may be more than one - non-manifold geometry can have duplicate edges.
+ // Prioritize the one with exact vertex match, not just colocal.
+ // If *any* of the opposite edges are already assigned to this group, don't do anything.
+ bool alreadyAssignedToThisGroup = false;
+ uint32_t bestConnectedFace = UINT32_MAX;
+ for (Mesh::ColocalEdgeIterator oppositeEdgeIt(m_mesh, edgeIt.vertex1(), edgeIt.vertex0()); !oppositeEdgeIt.isDone(); oppositeEdgeIt.advance()) {
+ const uint32_t oppositeEdge = oppositeEdgeIt.edge();
+ const uint32_t oppositeFace = meshEdgeFace(oppositeEdge);
+#if 0
+ // Reject opposite face if dihedral angle >= 90 degrees.
+ {
+ Vector3 a = m_mesh->computeFaceNormal(f);
+ Vector3 b = m_mesh->computeFaceNormal(oppositeFace);
+ if (dot(a, b) <= 0.0f)
+ continue;
+ }
+#endif
+ if (m_mesh->isFaceIgnored(oppositeFace))
+ continue; // Don't add ignored faces to group.
+ if (m_groups[oppositeFace] == group) {
+ alreadyAssignedToThisGroup = true;
+ break;
+ }
+ if (m_groups[oppositeFace] != kInvalid)
+ continue; // Connected face is already assigned to another group.
+ if (faceDuplicatesGroupEdge(group, oppositeFace))
+ continue; // Don't want duplicate edges in a group.
+ const uint32_t oppositeVertex0 = m_mesh->vertexAt(meshEdgeIndex0(oppositeEdge));
+ const uint32_t oppositeVertex1 = m_mesh->vertexAt(meshEdgeIndex1(oppositeEdge));
+ if (bestConnectedFace == UINT32_MAX || (oppositeVertex0 == edgeIt.vertex1() && oppositeVertex1 == edgeIt.vertex0()))
+ bestConnectedFace = oppositeFace;
+#if 0
+ else {
+ // Choose the opposite face with the smallest dihedral angle.
+ const float d1 = 1.0f - dot(computeFaceNormal(f), computeFaceNormal(bestConnectedFace));
+ const float d2 = 1.0f - dot(computeFaceNormal(f), computeFaceNormal(oppositeFace));
+ if (d2 < d1)
+ bestConnectedFace = oppositeFace;
+ }
+#endif
+ }
+ if (!alreadyAssignedToThisGroup && bestConnectedFace != UINT32_MAX) {
+ m_groups[bestConnectedFace] = group;
+ m_nextFace[bestConnectedFace] = UINT32_MAX;
+ if (prevFace != UINT32_MAX)
+ m_nextFace[prevFace] = bestConnectedFace;
+ prevFace = bestConnectedFace;
+ groupFaceCount++;
+ growFaces.push_back(bestConnectedFace);
+ }
+ }
+ }
+ m_faceCount.push_back(groupFaceCount);
+ group++;
+ XA_ASSERT(group < kInvalid);
+ }
+ }
- class GroupFaceIterator {
+ class Iterator
+ {
public:
- GroupFaceIterator(const Mesh *mesh, uint32_t group) :
- m_mesh(mesh) {
- XA_DEBUG_ASSERT(group != UINT32_MAX);
- m_current = mesh->m_faceGroupFirstFace[group];
+ Iterator(const MeshFaceGroups *meshFaceGroups, Handle group) : m_meshFaceGroups(meshFaceGroups)
+ {
+ XA_DEBUG_ASSERT(group != kInvalid);
+ m_current = m_meshFaceGroups->m_firstFace[group];
}
- void advance() {
- m_current = m_mesh->m_faceGroupNextFace[m_current];
+ void advance()
+ {
+ m_current = m_meshFaceGroups->m_nextFace[m_current];
}
- bool isDone() const {
+ bool isDone() const
+ {
return m_current == UINT32_MAX;
}
- uint32_t face() const {
+ uint32_t face() const
+ {
return m_current;
}
private:
- const Mesh *m_mesh;
+ const MeshFaceGroups *m_meshFaceGroups;
uint32_t m_current;
};
+
+private:
+ // Check if the face duplicates any edges of any face already in the group.
+ bool faceDuplicatesGroupEdge(Handle group, uint32_t face) const
+ {
+ for (Mesh::FaceEdgeIterator edgeIt(m_mesh, face); !edgeIt.isDone(); edgeIt.advance()) {
+ for (Mesh::ColocalEdgeIterator colocalEdgeIt(m_mesh, edgeIt.vertex0(), edgeIt.vertex1()); !colocalEdgeIt.isDone(); colocalEdgeIt.advance()) {
+ if (m_groups[meshEdgeFace(colocalEdgeIt.edge())] == group)
+ return true;
+ }
+ }
+ return false;
+ }
+
+ const Mesh *m_mesh;
+ Array<Handle> m_groups;
+ Array<uint32_t> m_firstFace;
+ Array<uint32_t> m_nextFace; // In: face. Out: the next face in the same group.
+ Array<uint32_t> m_faceCount; // In: face group. Out: number of faces in the group.
};
-constexpr uint16_t Mesh::kInvalidFaceGroup;
+constexpr MeshFaceGroups::Handle MeshFaceGroups::kInvalid;
-static bool meshCloseHole(Mesh *mesh, const Array<uint32_t> &holeVertices, const Vector3 &normal) {
+static bool meshCloseHole(Mesh *mesh, const Array<uint32_t> &holeVertices, const Vector3 &normal)
+{
#if XA_CLOSE_HOLES_CHECK_EDGE_INTERSECTION
const uint32_t faceCount = mesh->faceCount();
#endif
@@ -3230,7 +3459,8 @@ static bool meshCloseHole(Mesh *mesh, const Array<uint32_t> &holeVertices, const
return true;
}
-static bool meshCloseHoles(Mesh *mesh, const Array<uint32_t> &boundaryLoops, const Vector3 &normal, uint32_t *holeCount, Array<uint32_t> *holeFaceCounts) {
+static bool meshCloseHoles(Mesh *mesh, const Array<uint32_t> &boundaryLoops, const Vector3 &normal, uint32_t *holeCount, Array<uint32_t> *holeFaceCounts)
+{
if (holeFaceCounts)
holeFaceCounts->clear();
// Compute lengths.
@@ -3286,7 +3516,8 @@ static bool meshCloseHoles(Mesh *mesh, const Array<uint32_t> &boundaryLoops, con
return result;
}
-static bool meshIsPlanar(const Mesh &mesh) {
+static bool meshIsPlanar(const Mesh &mesh)
+{
const Vector3 p1 = mesh.position(mesh.vertexAt(0));
const Vector3 p2 = mesh.position(mesh.vertexAt(1));
const Vector3 p3 = mesh.position(mesh.vertexAt(2));
@@ -3312,12 +3543,14 @@ Fixing T-junctions.
- Split edge.
*/
-struct SplitEdge {
+struct SplitEdge
+{
uint32_t edge;
float t;
uint32_t vertex;
- bool operator<(const SplitEdge &other) const {
+ bool operator<(const SplitEdge &other) const
+ {
if (edge < other.edge)
return true;
else if (edge == other.edge) {
@@ -3329,7 +3562,8 @@ struct SplitEdge {
};
// Returns nullptr if there were no t-junctions to fix.
-static Mesh *meshFixTJunctions(const Mesh &inputMesh, bool *duplicatedEdge, bool *failed, uint32_t *fixedTJunctionsCount) {
+static Mesh *meshFixTJunctions(const Mesh &inputMesh, bool *duplicatedEdge, bool *failed, uint32_t *fixedTJunctionsCount)
+{
if (duplicatedEdge)
*duplicatedEdge = false;
if (failed)
@@ -3404,7 +3638,8 @@ static Mesh *meshFixTJunctions(const Mesh &inputMesh, bool *duplicatedEdge, bool
}
// boundaryLoops are the first edges for each boundary loop.
-static void meshGetBoundaryLoops(const Mesh &mesh, Array<uint32_t> &boundaryLoops) {
+static void meshGetBoundaryLoops(const Mesh &mesh, Array<uint32_t> &boundaryLoops)
+{
const uint32_t edgeCount = mesh.edgeCount();
BitArray bitFlags(edgeCount);
bitFlags.zeroOutMemory();
@@ -3419,23 +3654,26 @@ static void meshGetBoundaryLoops(const Mesh &mesh, Array<uint32_t> &boundaryLoop
}
}
-struct Progress {
- Progress(ProgressCategory::Enum category, ProgressFunc func, void *userData, uint32_t maxValue) :
- value(0), cancel(false), m_category(category), m_func(func), m_userData(userData), m_maxValue(maxValue), m_progress(0) {
+struct Progress
+{
+ Progress(ProgressCategory::Enum category, ProgressFunc func, void *userData, uint32_t maxValue) : value(0), cancel(false), m_category(category), m_func(func), m_userData(userData), m_maxValue(maxValue), m_progress(0)
+ {
if (m_func) {
if (!m_func(category, 0, userData))
cancel = true;
}
}
- ~Progress() {
+ ~Progress()
+ {
if (m_func) {
if (!m_func(m_category, 100, m_userData))
cancel = true;
}
}
- void update() {
+ void update()
+ {
if (!m_func)
return;
m_mutex.lock();
@@ -3448,7 +3686,8 @@ struct Progress {
m_mutex.unlock();
}
- void setMaxValue(uint32_t maxValue) {
+ void setMaxValue(uint32_t maxValue)
+ {
m_mutex.lock();
m_maxValue = maxValue;
m_mutex.unlock();
@@ -3466,31 +3705,32 @@ private:
std::mutex m_mutex;
};
-struct Spinlock {
- void lock() {
- while (m_lock.test_and_set(std::memory_order_acquire)) {
- }
- }
+struct Spinlock
+{
+ void lock() { while(m_lock.test_and_set(std::memory_order_acquire)) {} }
void unlock() { m_lock.clear(std::memory_order_release); }
private:
std::atomic_flag m_lock = ATOMIC_FLAG_INIT;
};
-struct TaskGroupHandle {
+struct TaskGroupHandle
+{
uint32_t value = UINT32_MAX;
};
-struct Task {
+struct Task
+{
void (*func)(void *userData);
void *userData;
};
#if XA_MULTITHREADED
-class TaskScheduler {
+class TaskScheduler
+{
public:
- TaskScheduler() :
- m_shutdown(false) {
+ TaskScheduler() : m_shutdown(false)
+ {
m_threadIndex = 0;
// Max with current task scheduler usage is 1 per thread + 1 deep nesting, but allow for some slop.
m_maxGroups = std::thread::hardware_concurrency() * 4;
@@ -3508,7 +3748,8 @@ public:
}
}
- ~TaskScheduler() {
+ ~TaskScheduler()
+ {
m_shutdown = true;
for (uint32_t i = 0; i < m_workers.size(); i++) {
Worker &worker = m_workers[i];
@@ -3526,11 +3767,13 @@ public:
XA_FREE(m_groups);
}
- uint32_t threadCount() const {
+ uint32_t threadCount() const
+ {
return max(1u, std::thread::hardware_concurrency()); // Including the main thread.
}
- TaskGroupHandle createTaskGroup(uint32_t reserveSize = 0) {
+ TaskGroupHandle createTaskGroup(uint32_t reserveSize = 0)
+ {
// Claim the first free group.
for (uint32_t i = 0; i < m_maxGroups; i++) {
TaskGroup &group = m_groups[i];
@@ -3552,7 +3795,8 @@ public:
return handle;
}
- void run(TaskGroupHandle handle, Task task) {
+ void run(TaskGroupHandle handle, const Task &task)
+ {
XA_DEBUG_ASSERT(handle.value != UINT32_MAX);
TaskGroup &group = m_groups[handle.value];
group.queueLock.lock();
@@ -3566,7 +3810,8 @@ public:
}
}
- void wait(TaskGroupHandle *handle) {
+ void wait(TaskGroupHandle *handle)
+ {
if (handle->value == UINT32_MAX) {
XA_DEBUG_ASSERT(false);
return;
@@ -3594,7 +3839,8 @@ public:
static uint32_t currentThreadIndex() { return m_threadIndex; }
private:
- struct TaskGroup {
+ struct TaskGroup
+ {
std::atomic<bool> free;
Array<Task> queue; // Items are never removed. queueHead is incremented to pop items.
uint32_t queueHead = 0;
@@ -3602,7 +3848,8 @@ private:
std::atomic<uint32_t> ref; // Increment when a task is enqueued, decrement when a task finishes.
};
- struct Worker {
+ struct Worker
+ {
std::thread *thread = nullptr;
std::mutex mutex;
std::condition_variable cv;
@@ -3610,16 +3857,17 @@ private:
};
TaskGroup *m_groups;
- uint32_t m_maxGroups;
Array<Worker> m_workers;
std::atomic<bool> m_shutdown;
+ uint32_t m_maxGroups;
static thread_local uint32_t m_threadIndex;
- static void workerThread(TaskScheduler *scheduler, Worker *worker, uint32_t threadIndex) {
+ static void workerThread(TaskScheduler *scheduler, Worker *worker, uint32_t threadIndex)
+ {
m_threadIndex = threadIndex;
std::unique_lock<std::mutex> lock(worker->mutex);
for (;;) {
- worker->cv.wait(lock, [=] { return worker->wakeup.load(); });
+ worker->cv.wait(lock, [=]{ return worker->wakeup.load(); });
worker->wakeup = false;
for (;;) {
if (scheduler->m_shutdown)
@@ -3650,18 +3898,22 @@ private:
thread_local uint32_t TaskScheduler::m_threadIndex;
#else
-class TaskScheduler {
+class TaskScheduler
+{
public:
- ~TaskScheduler() {
+ ~TaskScheduler()
+ {
for (uint32_t i = 0; i < m_groups.size(); i++)
destroyGroup({ i });
}
- uint32_t threadCount() const {
+ uint32_t threadCount() const
+ {
return 1;
}
- TaskGroupHandle createTaskGroup(uint32_t reserveSize = 0) {
+ TaskGroupHandle createTaskGroup(uint32_t reserveSize = 0)
+ {
TaskGroup *group = XA_NEW(MemTag::Default, TaskGroup);
group->queue.reserve(reserveSize);
m_groups.push_back(group);
@@ -3670,11 +3922,13 @@ public:
return handle;
}
- void run(TaskGroupHandle handle, Task task) {
+ void run(TaskGroupHandle handle, Task task)
+ {
m_groups[handle.value]->queue.push_back(task);
}
- void wait(TaskGroupHandle *handle) {
+ void wait(TaskGroupHandle *handle)
+ {
if (handle->value == UINT32_MAX) {
XA_DEBUG_ASSERT(false);
return;
@@ -3690,7 +3944,8 @@ public:
static uint32_t currentThreadIndex() { return 0; }
private:
- void destroyGroup(TaskGroupHandle handle) {
+ void destroyGroup(TaskGroupHandle handle)
+ {
TaskGroup *group = m_groups[handle.value];
if (group) {
group->~TaskGroup();
@@ -3699,7 +3954,8 @@ private:
}
}
- struct TaskGroup {
+ struct TaskGroup
+ {
Array<Task> queue;
};
@@ -3712,7 +3968,8 @@ const uint8_t TGA_TYPE_RGB = 2;
const uint8_t TGA_ORIGIN_UPPER = 0x20;
#pragma pack(push, 1)
-struct TgaHeader {
+struct TgaHeader
+{
uint8_t id_length;
uint8_t colormap_type;
uint8_t image_type;
@@ -3729,7 +3986,8 @@ struct TgaHeader {
};
#pragma pack(pop)
-static void WriteTga(const char *filename, const uint8_t *data, uint32_t width, uint32_t height) {
+static void WriteTga(const char *filename, const uint8_t *data, uint32_t width, uint32_t height)
+{
XA_DEBUG_ASSERT(sizeof(TgaHeader) == TgaHeader::Size);
FILE *f;
XA_FOPEN(f, filename, "wb");
@@ -3754,10 +4012,12 @@ static void WriteTga(const char *filename, const uint8_t *data, uint32_t width,
}
#endif
-template <typename T>
-class ThreadLocal {
+template<typename T>
+class ThreadLocal
+{
public:
- ThreadLocal() {
+ ThreadLocal()
+ {
#if XA_MULTITHREADED
const uint32_t n = std::thread::hardware_concurrency();
#else
@@ -3768,7 +4028,8 @@ public:
new (&m_array[i]) T;
}
- ~ThreadLocal() {
+ ~ThreadLocal()
+ {
#if XA_MULTITHREADED
const uint32_t n = std::thread::hardware_concurrency();
#else
@@ -3779,7 +4040,8 @@ public:
XA_FREE(m_array);
}
- T &get() const {
+ T &get() const
+ {
return m_array[TaskScheduler::currentThreadIndex()];
}
@@ -3787,9 +4049,11 @@ private:
T *m_array;
};
-class UniformGrid2 {
+class UniformGrid2
+{
public:
- void reset(const Vector2 *positions, const uint32_t *indices = nullptr, uint32_t reserveEdgeCount = 0) {
+ void reset(const Vector2 *positions, const uint32_t *indices = nullptr, uint32_t reserveEdgeCount = 0)
+ {
m_edges.clear();
if (reserveEdgeCount > 0)
m_edges.reserve(reserveEdgeCount);
@@ -3798,14 +4062,16 @@ public:
m_cellDataOffsets.clear();
}
- void append(uint32_t edge) {
+ void append(uint32_t edge)
+ {
XA_DEBUG_ASSERT(m_cellDataOffsets.isEmpty());
m_edges.push_back(edge);
}
- bool intersect(Vector2 v1, Vector2 v2, float epsilon) {
+ bool intersect(Vector2 v1, Vector2 v2, float epsilon)
+ {
const uint32_t edgeCount = m_edges.size();
- bool bruteForce = edgeCount <= 64;
+ bool bruteForce = edgeCount <= 20;
if (!bruteForce && m_cellDataOffsets.isEmpty())
bruteForce = !createGrid();
if (bruteForce) {
@@ -3829,37 +4095,80 @@ public:
return false;
}
- bool intersectSelf(float epsilon) {
- const uint32_t edgeCount = m_edges.size();
- bool bruteForce = edgeCount <= 64;
+ // If edges is empty, checks for intersection with all edges in the grid.
+ bool intersect(float epsilon, ConstArrayView<uint32_t> edges = ConstArrayView<uint32_t>(), ConstArrayView<uint32_t> ignoreEdges = ConstArrayView<uint32_t>())
+ {
+ bool bruteForce = m_edges.size() <= 20;
if (!bruteForce && m_cellDataOffsets.isEmpty())
bruteForce = !createGrid();
- for (uint32_t i = 0; i < edgeCount; i++) {
- const uint32_t edge1 = m_edges[i];
+ const uint32_t *edges1, *edges2 = nullptr;
+ uint32_t edges1Count, edges2Count = 0;
+ if (edges.length == 0) {
+ edges1 = m_edges.data();
+ edges1Count = m_edges.size();
+ } else {
+ edges1 = edges.data;
+ edges1Count = edges.length;
+ }
+ if (bruteForce) {
+ edges2 = m_edges.data();
+ edges2Count = m_edges.size();
+ }
+ for (uint32_t i = 0; i < edges1Count; i++) {
+ const uint32_t edge1 = edges1[i];
+ const uint32_t edge1Vertex[2] = { vertexAt(meshEdgeIndex0(edge1)), vertexAt(meshEdgeIndex1(edge1)) };
+ const Vector2 &edge1Position1 = m_positions[edge1Vertex[0]];
+ const Vector2 &edge1Position2 = m_positions[edge1Vertex[1]];
+ const Extents2 edge1Extents(edge1Position1, edge1Position2);
+ uint32_t j = 0;
if (bruteForce) {
- for (uint32_t j = 0; j < edgeCount; j++) {
- const uint32_t edge2 = m_edges[j];
- if (edgesIntersect(edge1, edge2, epsilon))
- return true;
+ // If checking against self, test each edge pair only once.
+ if (edges.length == 0) {
+ j = i + 1;
+ if (j == edges1Count)
+ break;
}
} else {
computePotentialEdges(edgePosition0(edge1), edgePosition1(edge1));
- uint32_t prevEdge = UINT32_MAX;
- for (uint32_t j = 0; j < m_potentialEdges.size(); j++) {
- const uint32_t edge2 = m_potentialEdges[j];
- if (edge2 == prevEdge)
- continue;
- if (edgesIntersect(edge1, edge2, epsilon))
- return true;
- prevEdge = edge2;
+ edges2 = m_potentialEdges.data();
+ edges2Count = m_potentialEdges.size();
+ }
+ uint32_t prevEdge = UINT32_MAX; // Handle potential edges duplicates.
+ for (; j < edges2Count; j++) {
+ const uint32_t edge2 = edges2[j];
+ if (edge1 == edge2)
+ continue;
+ if (edge2 == prevEdge)
+ continue;
+ prevEdge = edge2;
+ // Check if edge2 is ignored.
+ bool ignore = false;
+ for (uint32_t k = 0; k < ignoreEdges.length; k++) {
+ if (edge2 == ignoreEdges[k]) {
+ ignore = true;
+ break;
+ }
}
+ if (ignore)
+ continue;
+ const uint32_t edge2Vertex[2] = { vertexAt(meshEdgeIndex0(edge2)), vertexAt(meshEdgeIndex1(edge2)) };
+ // Ignore connected edges, since they can't intersect (only overlap), and may be detected as false positives.
+ if (edge1Vertex[0] == edge2Vertex[0] || edge1Vertex[0] == edge2Vertex[1] || edge1Vertex[1] == edge2Vertex[0] || edge1Vertex[1] == edge2Vertex[1])
+ continue;
+ const Vector2 &edge2Position1 = m_positions[edge2Vertex[0]];
+ const Vector2 &edge2Position2 = m_positions[edge2Vertex[1]];
+ if (!Extents2::intersect(edge1Extents, Extents2(edge2Position1, edge2Position2)))
+ continue;
+ if (linesIntersect(edge1Position1, edge1Position2, edge2Position1, edge2Position2, epsilon))
+ return true;
}
}
return false;
}
#if XA_DEBUG_EXPORT_BOUNDARY_GRID
- void debugExport(const char *filename) {
+ void debugExport(const char *filename)
+ {
Array<uint8_t> image;
image.resize(m_gridWidth * m_gridHeight * 3);
for (uint32_t y = 0; y < m_gridHeight; y++) {
@@ -3881,7 +4190,8 @@ public:
#endif
private:
- bool createGrid() {
+ bool createGrid()
+ {
// Compute edge extents. Min will be the grid origin.
const uint32_t edgeCount = m_edges.size();
Extents2 edgeExtents;
@@ -3933,7 +4243,8 @@ private:
return true;
}
- void computePotentialEdges(Vector2 p1, Vector2 p2) {
+ void computePotentialEdges(Vector2 p1, Vector2 p2)
+ {
m_potentialEdges.clear();
traverse(p1, p2);
for (uint32_t j = 0; j < m_traversedCellOffsets.size(); j++) {
@@ -3951,7 +4262,8 @@ private:
}
// "A Fast Voxel Traversal Algorithm for Ray Tracing"
- void traverse(Vector2 p1, Vector2 p2) {
+ void traverse(Vector2 p1, Vector2 p2)
+ {
const Vector2 dir = p2 - p1;
const Vector2 normal = normalizeSafe(dir, Vector2(0.0f), kEpsilon);
const int stepX = dir.x >= 0 ? 1 : -1;
@@ -3972,12 +4284,14 @@ private:
if (normal.x > kEpsilon || normal.x < -kEpsilon) {
tMaxX = (distToNextCellX * stepX) / normal.x;
tDeltaX = (m_cellSize * stepX) / normal.x;
- } else
+ }
+ else
tMaxX = tDeltaX = FLT_MAX;
if (normal.y > kEpsilon || normal.y < -kEpsilon) {
tMaxY = (distToNextCellY * stepY) / normal.y;
tDeltaY = (m_cellSize * stepY) / normal.y;
- } else
+ }
+ else
tMaxY = tDeltaY = FLT_MAX;
m_traversedCellOffsets.clear();
m_traversedCellOffsets.push_back(firstCell[0] + firstCell[1] * m_gridWidth);
@@ -3992,11 +4306,11 @@ private:
}
if (currentCell[0] >= m_gridWidth || currentCell[1] >= m_gridHeight)
break;
- if (stepX == 0 && currentCell[0] < lastCell[0])
+ if (stepX == -1 && currentCell[0] < lastCell[0])
break;
if (stepX == 1 && currentCell[0] > lastCell[0])
break;
- if (stepY == 0 && currentCell[1] < lastCell[1])
+ if (stepY == -1 && currentCell[1] < lastCell[1])
break;
if (stepY == 1 && currentCell[1] > lastCell[1])
break;
@@ -4004,34 +4318,28 @@ private:
}
}
- bool edgesIntersect(uint32_t edge1, uint32_t edge2, float epsilon) const {
- if (edge1 == edge2)
- return false;
- const uint32_t ai[2] = { vertexAt(meshEdgeIndex0(edge1)), vertexAt(meshEdgeIndex1(edge1)) };
- const uint32_t bi[2] = { vertexAt(meshEdgeIndex0(edge2)), vertexAt(meshEdgeIndex1(edge2)) };
- // Ignore connected edges, since they can't intersect (only overlap), and may be detected as false positives.
- if (ai[0] == bi[0] || ai[0] == bi[1] || ai[1] == bi[0] || ai[1] == bi[1])
- return false;
- return linesIntersect(m_positions[ai[0]], m_positions[ai[1]], m_positions[bi[0]], m_positions[bi[1]], epsilon);
- }
-
- uint32_t cellX(float x) const {
+ uint32_t cellX(float x) const
+ {
return min((uint32_t)max(0.0f, (x - m_gridOrigin.x) / m_cellSize), m_gridWidth - 1u);
}
- uint32_t cellY(float y) const {
+ uint32_t cellY(float y) const
+ {
return min((uint32_t)max(0.0f, (y - m_gridOrigin.y) / m_cellSize), m_gridHeight - 1u);
}
- Vector2 edgePosition0(uint32_t edge) const {
+ Vector2 edgePosition0(uint32_t edge) const
+ {
return m_positions[vertexAt(meshEdgeIndex0(edge))];
}
- Vector2 edgePosition1(uint32_t edge) const {
+ Vector2 edgePosition1(uint32_t edge) const
+ {
return m_positions[vertexAt(meshEdgeIndex1(edge))];
}
- uint32_t vertexAt(uint32_t index) const {
+ uint32_t vertexAt(uint32_t index) const
+ {
return m_indices ? m_indices[index] : index;
}
@@ -4047,29 +4355,835 @@ private:
Array<uint32_t> m_traversedCellOffsets;
};
-struct UvMeshChart {
+struct UvMeshChart
+{
Array<uint32_t> faces;
Array<uint32_t> indices;
uint32_t material;
};
-struct UvMesh {
+struct UvMesh
+{
UvMeshDecl decl;
Array<uint32_t> indices;
Array<UvMeshChart *> charts;
Array<uint32_t> vertexToChartMap;
};
-struct UvMeshInstance {
+struct UvMeshInstance
+{
UvMesh *mesh;
Array<Vector2> texcoords;
bool rotateCharts;
};
+/*
+ * Copyright (c) 2004-2010, Bruno Levy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the ALICE Project-Team nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * If you modify this software, you should include a notice giving the
+ * name of the person performing the modification, the date of modification,
+ * and the reason for such modification.
+ *
+ * Contact: Bruno Levy
+ *
+ * levy@loria.fr
+ *
+ * ALICE Project
+ * LORIA, INRIA Lorraine,
+ * Campus Scientifique, BP 239
+ * 54506 VANDOEUVRE LES NANCY CEDEX
+ * FRANCE
+ */
+namespace opennl {
+#define NL_NEW(T) XA_ALLOC(MemTag::OpenNL, T)
+#define NL_NEW_ARRAY(T,NB) XA_ALLOC_ARRAY(MemTag::OpenNL, T, NB)
+#define NL_RENEW_ARRAY(T,x,NB) XA_REALLOC(MemTag::OpenNL, x, T, NB)
+#define NL_DELETE(x) XA_FREE(x); x = nullptr
+#define NL_DELETE_ARRAY(x) XA_FREE(x); x = nullptr
+#define NL_CLEAR(x, T) memset(x, 0, sizeof(T));
+#define NL_CLEAR_ARRAY(T,x,NB) memset(x, 0, (size_t)(NB)*sizeof(T))
+#define NL_NEW_VECTOR(dim) XA_ALLOC_ARRAY(MemTag::OpenNL, double, dim)
+#define NL_DELETE_VECTOR(ptr) XA_FREE(ptr)
+
+struct NLMatrixStruct;
+typedef NLMatrixStruct * NLMatrix;
+typedef void (*NLDestroyMatrixFunc)(NLMatrix M);
+typedef void (*NLMultMatrixVectorFunc)(NLMatrix M, const double* x, double* y);
+
+#define NL_MATRIX_SPARSE_DYNAMIC 0x1001
+#define NL_MATRIX_CRS 0x1002
+#define NL_MATRIX_OTHER 0x1006
+
+struct NLMatrixStruct
+{
+ uint32_t m;
+ uint32_t n;
+ uint32_t type;
+ NLDestroyMatrixFunc destroy_func;
+ NLMultMatrixVectorFunc mult_func;
+};
+
+/* Dynamic arrays for sparse row/columns */
+
+struct NLCoeff
+{
+ uint32_t index;
+ double value;
+};
+
+struct NLRowColumn
+{
+ uint32_t size;
+ uint32_t capacity;
+ NLCoeff* coeff;
+};
+
+/* Compressed Row Storage */
+
+struct NLCRSMatrix
+{
+ uint32_t m;
+ uint32_t n;
+ uint32_t type;
+ NLDestroyMatrixFunc destroy_func;
+ NLMultMatrixVectorFunc mult_func;
+ double* val;
+ uint32_t* rowptr;
+ uint32_t* colind;
+ uint32_t nslices;
+ uint32_t* sliceptr;
+};
+
+/* SparseMatrix data structure */
+
+struct NLSparseMatrix
+{
+ uint32_t m;
+ uint32_t n;
+ uint32_t type;
+ NLDestroyMatrixFunc destroy_func;
+ NLMultMatrixVectorFunc mult_func;
+ uint32_t diag_size;
+ uint32_t diag_capacity;
+ NLRowColumn* row;
+ NLRowColumn* column;
+ double* diag;
+ uint32_t row_capacity;
+ uint32_t column_capacity;
+};
+
+/* NLContext data structure */
+
+struct NLBufferBinding
+{
+ void* base_address;
+ uint32_t stride;
+};
+
+#define NL_BUFFER_ITEM(B,i) *(double*)((void*)((char*)((B).base_address)+((i)*(B).stride)))
+
+struct NLContext
+{
+ NLBufferBinding *variable_buffer;
+ double *variable_value;
+ bool *variable_is_locked;
+ uint32_t *variable_index;
+ uint32_t n;
+ NLMatrix M;
+ NLMatrix P;
+ NLMatrix B;
+ NLRowColumn af;
+ NLRowColumn al;
+ double *x;
+ double *b;
+ uint32_t nb_variables;
+ uint32_t nb_systems;
+ uint32_t current_row;
+ uint32_t max_iterations;
+ bool max_iterations_defined;
+ double threshold;
+ double omega;
+ uint32_t used_iterations;
+ double error;
+};
+
+static void nlDeleteMatrix(NLMatrix M)
+{
+ if (!M)
+ return;
+ M->destroy_func(M);
+ NL_DELETE(M);
+}
+
+static void nlMultMatrixVector(NLMatrix M, const double* x, double* y)
+{
+ M->mult_func(M, x, y);
+}
+
+static void nlRowColumnConstruct(NLRowColumn* c)
+{
+ c->size = 0;
+ c->capacity = 0;
+ c->coeff = nullptr;
+}
+
+static void nlRowColumnDestroy(NLRowColumn* c)
+{
+ NL_DELETE_ARRAY(c->coeff);
+ c->size = 0;
+ c->capacity = 0;
+}
+
+static void nlRowColumnGrow(NLRowColumn* c)
+{
+ if (c->capacity != 0) {
+ c->capacity = 2 * c->capacity;
+ c->coeff = NL_RENEW_ARRAY(NLCoeff, c->coeff, c->capacity);
+ } else {
+ c->capacity = 4;
+ c->coeff = NL_NEW_ARRAY(NLCoeff, c->capacity);
+ NL_CLEAR_ARRAY(NLCoeff, c->coeff, c->capacity);
+ }
+}
+
+static void nlRowColumnAdd(NLRowColumn* c, uint32_t index, double value)
+{
+ for (uint32_t i = 0; i < c->size; i++) {
+ if (c->coeff[i].index == index) {
+ c->coeff[i].value += value;
+ return;
+ }
+ }
+ if (c->size == c->capacity)
+ nlRowColumnGrow(c);
+ c->coeff[c->size].index = index;
+ c->coeff[c->size].value = value;
+ c->size++;
+}
+
+/* Does not check whether the index already exists */
+static void nlRowColumnAppend(NLRowColumn* c, uint32_t index, double value)
+{
+ if (c->size == c->capacity)
+ nlRowColumnGrow(c);
+ c->coeff[c->size].index = index;
+ c->coeff[c->size].value = value;
+ c->size++;
+}
+
+static void nlRowColumnZero(NLRowColumn* c)
+{
+ c->size = 0;
+}
+
+static void nlRowColumnClear(NLRowColumn* c)
+{
+ c->size = 0;
+ c->capacity = 0;
+ NL_DELETE_ARRAY(c->coeff);
+}
+
+static int nlCoeffCompare(const void* p1, const void* p2)
+{
+ return (((NLCoeff*)(p2))->index < ((NLCoeff*)(p1))->index);
+}
+
+static void nlRowColumnSort(NLRowColumn* c)
+{
+ qsort(c->coeff, c->size, sizeof(NLCoeff), nlCoeffCompare);
+}
+
+/* CRSMatrix data structure */
+
+static void nlCRSMatrixDestroy(NLCRSMatrix* M)
+{
+ NL_DELETE_ARRAY(M->val);
+ NL_DELETE_ARRAY(M->rowptr);
+ NL_DELETE_ARRAY(M->colind);
+ NL_DELETE_ARRAY(M->sliceptr);
+ M->m = 0;
+ M->n = 0;
+ M->nslices = 0;
+}
+
+static void nlCRSMatrixMultSlice(NLCRSMatrix* M, const double* x, double* y, uint32_t Ibegin, uint32_t Iend)
+{
+ for (uint32_t i = Ibegin; i < Iend; ++i) {
+ double sum = 0.0;
+ for (uint32_t j = M->rowptr[i]; j < M->rowptr[i + 1]; ++j)
+ sum += M->val[j] * x[M->colind[j]];
+ y[i] = sum;
+ }
+}
+
+static void nlCRSMatrixMult(NLCRSMatrix* M, const double* x, double* y)
+{
+ int nslices = (int)(M->nslices);
+ for (int slice = 0; slice < nslices; ++slice)
+ nlCRSMatrixMultSlice(M, x, y, M->sliceptr[slice], M->sliceptr[slice + 1]);
+}
+
+static void nlCRSMatrixConstruct(NLCRSMatrix* M, uint32_t m, uint32_t n, uint32_t nnz, uint32_t nslices)
+{
+ M->m = m;
+ M->n = n;
+ M->type = NL_MATRIX_CRS;
+ M->destroy_func = (NLDestroyMatrixFunc)nlCRSMatrixDestroy;
+ M->mult_func = (NLMultMatrixVectorFunc)nlCRSMatrixMult;
+ M->nslices = nslices;
+ M->val = NL_NEW_ARRAY(double, nnz);
+ NL_CLEAR_ARRAY(double, M->val, nnz);
+ M->rowptr = NL_NEW_ARRAY(uint32_t, m + 1);
+ NL_CLEAR_ARRAY(uint32_t, M->rowptr, m + 1);
+ M->colind = NL_NEW_ARRAY(uint32_t, nnz);
+ NL_CLEAR_ARRAY(uint32_t, M->colind, nnz);
+ M->sliceptr = NL_NEW_ARRAY(uint32_t, nslices + 1);
+ NL_CLEAR_ARRAY(uint32_t, M->sliceptr, nslices + 1);
+}
+
+/* SparseMatrix data structure */
+
+static void nlSparseMatrixDestroyRowColumns(NLSparseMatrix* M)
+{
+ for (uint32_t i = 0; i < M->m; i++)
+ nlRowColumnDestroy(&(M->row[i]));
+ NL_DELETE_ARRAY(M->row);
+}
+
+static void nlSparseMatrixDestroy(NLSparseMatrix* M)
+{
+ XA_DEBUG_ASSERT(M->type == NL_MATRIX_SPARSE_DYNAMIC);
+ nlSparseMatrixDestroyRowColumns(M);
+ NL_DELETE_ARRAY(M->diag);
+}
+
+static void nlSparseMatrixAdd(NLSparseMatrix* M, uint32_t i, uint32_t j, double value)
+{
+ XA_DEBUG_ASSERT(i >= 0 && i <= M->m - 1);
+ XA_DEBUG_ASSERT(j >= 0 && j <= M->n - 1);
+ if (i == j)
+ M->diag[i] += value;
+ nlRowColumnAdd(&(M->row[i]), j, value);
+}
+
+/* Returns the number of non-zero coefficients */
+static uint32_t nlSparseMatrixNNZ(NLSparseMatrix* M)
+{
+ uint32_t nnz = 0;
+ for (uint32_t i = 0; i < M->m; i++)
+ nnz += M->row[i].size;
+ return nnz;
+}
+
+static void nlSparseMatrixSort(NLSparseMatrix* M)
+{
+ for (uint32_t i = 0; i < M->m; i++)
+ nlRowColumnSort(&(M->row[i]));
+}
+
+/* SparseMatrix x Vector routines, internal helper routines */
+
+static void nlSparseMatrix_mult_rows(NLSparseMatrix* A, const double* x, double* y)
+{
+ /*
+ * Note: OpenMP does not like unsigned ints
+ * (causes some floating point exceptions),
+ * therefore I use here signed ints for all
+ * indices.
+ */
+ int m = (int)(A->m);
+ NLCoeff* c = nullptr;
+ NLRowColumn* Ri = nullptr;
+ for (int i = 0; i < m; i++) {
+ Ri = &(A->row[i]);
+ y[i] = 0;
+ for (int ij = 0; ij < (int)(Ri->size); ij++) {
+ c = &(Ri->coeff[ij]);
+ y[i] += c->value * x[c->index];
+ }
+ }
+}
+
+static void nlSparseMatrixMult(NLSparseMatrix* A, const double* x, double* y)
+{
+ XA_DEBUG_ASSERT(A->type == NL_MATRIX_SPARSE_DYNAMIC);
+ nlSparseMatrix_mult_rows(A, x, y);
+}
+
+static void nlSparseMatrixConstruct(NLSparseMatrix* M, uint32_t m, uint32_t n)
+{
+ M->m = m;
+ M->n = n;
+ M->type = NL_MATRIX_SPARSE_DYNAMIC;
+ M->destroy_func = (NLDestroyMatrixFunc)nlSparseMatrixDestroy;
+ M->mult_func = (NLMultMatrixVectorFunc)nlSparseMatrixMult;
+ M->row = NL_NEW_ARRAY(NLRowColumn, m);
+ NL_CLEAR_ARRAY(NLRowColumn, M->row, m);
+ M->row_capacity = m;
+ for (uint32_t i = 0; i < n; i++)
+ nlRowColumnConstruct(&(M->row[i]));
+ M->row_capacity = 0;
+ M->column = nullptr;
+ M->column_capacity = 0;
+ M->diag_size = min(m, n);
+ M->diag_capacity = M->diag_size;
+ M->diag = NL_NEW_ARRAY(double, M->diag_size);
+ NL_CLEAR_ARRAY(double, M->diag, M->diag_size);
+}
+
+static NLMatrix nlCRSMatrixNewFromSparseMatrix(NLSparseMatrix* M)
+{
+ uint32_t nnz = nlSparseMatrixNNZ(M);
+ uint32_t nslices = 8; /* TODO: get number of cores */
+ uint32_t slice, cur_bound, cur_NNZ, cur_row;
+ uint32_t k;
+ uint32_t slice_size = nnz / nslices;
+ NLCRSMatrix* CRS = NL_NEW(NLCRSMatrix);
+ NL_CLEAR(CRS, NLCRSMatrix);
+ nlCRSMatrixConstruct(CRS, M->m, M->n, nnz, nslices);
+ nlSparseMatrixSort(M);
+ /* Convert matrix to CRS format */
+ k = 0;
+ for (uint32_t i = 0; i < M->m; ++i) {
+ NLRowColumn* Ri = &(M->row[i]);
+ CRS->rowptr[i] = k;
+ for (uint32_t ij = 0; ij < Ri->size; ij++) {
+ NLCoeff* c = &(Ri->coeff[ij]);
+ CRS->val[k] = c->value;
+ CRS->colind[k] = c->index;
+ ++k;
+ }
+ }
+ CRS->rowptr[M->m] = k;
+ /* Create "slices" to be used by parallel sparse matrix vector product */
+ if (CRS->sliceptr) {
+ cur_bound = slice_size;
+ cur_NNZ = 0;
+ cur_row = 0;
+ CRS->sliceptr[0] = 0;
+ for (slice = 1; slice < nslices; ++slice) {
+ while (cur_NNZ < cur_bound && cur_row < M->m) {
+ ++cur_row;
+ cur_NNZ += CRS->rowptr[cur_row + 1] - CRS->rowptr[cur_row];
+ }
+ CRS->sliceptr[slice] = cur_row;
+ cur_bound += slice_size;
+ }
+ CRS->sliceptr[nslices] = M->m;
+ }
+ return (NLMatrix)CRS;
+}
+
+static void nlMatrixCompress(NLMatrix* M)
+{
+ NLMatrix CRS = nullptr;
+ if ((*M)->type != NL_MATRIX_SPARSE_DYNAMIC)
+ return;
+ CRS = nlCRSMatrixNewFromSparseMatrix((NLSparseMatrix*)*M);
+ nlDeleteMatrix(*M);
+ *M = CRS;
+}
+
+static NLContext *nlNewContext()
+{
+ NLContext* result = NL_NEW(NLContext);
+ NL_CLEAR(result, NLContext);
+ result->max_iterations = 100;
+ result->threshold = 1e-6;
+ result->omega = 1.5;
+ result->nb_systems = 1;
+ return result;
+}
+
+static void nlDeleteContext(NLContext *context)
+{
+ nlDeleteMatrix(context->M);
+ context->M = nullptr;
+ nlDeleteMatrix(context->P);
+ context->P = nullptr;
+ nlDeleteMatrix(context->B);
+ context->B = nullptr;
+ nlRowColumnDestroy(&context->af);
+ nlRowColumnDestroy(&context->al);
+ NL_DELETE_ARRAY(context->variable_value);
+ NL_DELETE_ARRAY(context->variable_buffer);
+ NL_DELETE_ARRAY(context->variable_is_locked);
+ NL_DELETE_ARRAY(context->variable_index);
+ NL_DELETE_ARRAY(context->x);
+ NL_DELETE_ARRAY(context->b);
+ NL_DELETE(context);
+}
+
+static double ddot(int n, const double *x, const double *y)
+{
+ double sum = 0.0;
+ for (int i = 0; i < n; i++)
+ sum += x[i] * y[i];
+ return sum;
+}
+
+static void daxpy(int n, double a, const double *x, double *y)
+{
+ for (int i = 0; i < n; i++)
+ y[i] = a * x[i] + y[i];
+}
+
+static void dscal(int n, double a, double *x)
+{
+ for (int i = 0; i < n; i++)
+ x[i] *= a;
+}
+
+/*
+ * The implementation of the solvers is inspired by
+ * the lsolver library, by Christian Badura, available from:
+ * http://www.mathematik.uni-freiburg.de
+ * /IAM/Research/projectskr/lin_solver/
+ *
+ * About the Conjugate Gradient, details can be found in:
+ * Ashby, Manteuffel, Saylor
+ * A taxononmy for conjugate gradient methods
+ * SIAM J Numer Anal 27, 1542-1568 (1990)
+ *
+ * This version is completely abstract, the same code can be used for
+ * CPU/GPU, dense matrix / sparse matrix etc...
+ * Abstraction is realized through:
+ * - Abstract matrix interface (NLMatrix), that can implement different
+ * versions of matrix x vector product (CPU/GPU, sparse/dense ...)
+ */
+
+static uint32_t nlSolveSystem_PRE_CG(NLMatrix M, NLMatrix P, double* b, double* x, double eps, uint32_t max_iter, double *sq_bnorm, double *sq_rnorm)
+{
+ int N = (int)M->n;
+ double* r = NL_NEW_VECTOR(N);
+ double* d = NL_NEW_VECTOR(N);
+ double* h = NL_NEW_VECTOR(N);
+ double *Ad = h;
+ uint32_t its = 0;
+ double rh, alpha, beta;
+ double b_square = ddot(N, b, b);
+ double err = eps * eps*b_square;
+ double curr_err;
+ nlMultMatrixVector(M, x, r);
+ daxpy(N, -1., b, r);
+ nlMultMatrixVector(P, r, d);
+ memcpy(h, d, N * sizeof(double));
+ rh = ddot(N, r, h);
+ curr_err = ddot(N, r, r);
+ while (curr_err > err && its < max_iter) {
+ nlMultMatrixVector(M, d, Ad);
+ alpha = rh / ddot(N, d, Ad);
+ daxpy(N, -alpha, d, x);
+ daxpy(N, -alpha, Ad, r);
+ nlMultMatrixVector(P, r, h);
+ beta = 1. / rh;
+ rh = ddot(N, r, h);
+ beta *= rh;
+ dscal(N, beta, d);
+ daxpy(N, 1., h, d);
+ ++its;
+ curr_err = ddot(N, r, r);
+ }
+ NL_DELETE_VECTOR(r);
+ NL_DELETE_VECTOR(d);
+ NL_DELETE_VECTOR(h);
+ *sq_bnorm = b_square;
+ *sq_rnorm = curr_err;
+ return its;
+}
+
+static uint32_t nlSolveSystemIterative(NLContext *context, NLMatrix M, NLMatrix P, double* b_in, double* x_in, double eps, uint32_t max_iter)
+{
+ uint32_t result = 0;
+ double rnorm = 0.0;
+ double bnorm = 0.0;
+ double* b = b_in;
+ double* x = x_in;
+ XA_DEBUG_ASSERT(M->m == M->n);
+ double sq_bnorm, sq_rnorm;
+ result = nlSolveSystem_PRE_CG(M, P, b, x, eps, max_iter, &sq_bnorm, &sq_rnorm);
+ /* Get residual norm and rhs norm */
+ bnorm = sqrt(sq_bnorm);
+ rnorm = sqrt(sq_rnorm);
+ if (bnorm == 0.0)
+ context->error = rnorm;
+ else
+ context->error = rnorm / bnorm;
+ context->used_iterations = result;
+ return result;
+}
+
+static bool nlSolveIterative(NLContext *context)
+{
+ double* b = context->b;
+ double* x = context->x;
+ uint32_t n = context->n;
+ NLMatrix M = context->M;
+ NLMatrix P = context->P;
+ for (uint32_t k = 0; k < context->nb_systems; ++k) {
+ nlSolveSystemIterative(context, M, P, b, x, context->threshold, context->max_iterations);
+ b += n;
+ x += n;
+ }
+ return true;
+}
+
+struct NLJacobiPreconditioner
+{
+ uint32_t m;
+ uint32_t n;
+ uint32_t type;
+ NLDestroyMatrixFunc destroy_func;
+ NLMultMatrixVectorFunc mult_func;
+ double* diag_inv;
+};
+
+static void nlJacobiPreconditionerDestroy(NLJacobiPreconditioner* M)
+{
+ NL_DELETE_ARRAY(M->diag_inv);
+}
+
+static void nlJacobiPreconditionerMult(NLJacobiPreconditioner* M, const double* x, double* y)
+{
+ for (uint32_t i = 0; i < M->n; ++i)
+ y[i] = x[i] * M->diag_inv[i];
+}
+
+static NLMatrix nlNewJacobiPreconditioner(NLMatrix M_in)
+{
+ NLSparseMatrix* M = nullptr;
+ NLJacobiPreconditioner* result = nullptr;
+ XA_DEBUG_ASSERT(M_in->type == NL_MATRIX_SPARSE_DYNAMIC);
+ XA_DEBUG_ASSERT(M_in->m == M_in->n);
+ M = (NLSparseMatrix*)M_in;
+ result = NL_NEW(NLJacobiPreconditioner);
+ NL_CLEAR(result, NLJacobiPreconditioner);
+ result->m = M->m;
+ result->n = M->n;
+ result->type = NL_MATRIX_OTHER;
+ result->destroy_func = (NLDestroyMatrixFunc)nlJacobiPreconditionerDestroy;
+ result->mult_func = (NLMultMatrixVectorFunc)nlJacobiPreconditionerMult;
+ result->diag_inv = NL_NEW_ARRAY(double, M->n);
+ NL_CLEAR_ARRAY(double, result->diag_inv, M->n);
+ for (uint32_t i = 0; i < M->n; ++i)
+ result->diag_inv[i] = (M->diag[i] == 0.0) ? 1.0 : 1.0 / M->diag[i];
+ return (NLMatrix)result;
+}
+
+#define NL_NB_VARIABLES 0x101
+#define NL_MAX_ITERATIONS 0x103
+
+static void nlSolverParameteri(NLContext *context, uint32_t pname, int param)
+{
+ if (pname == NL_NB_VARIABLES) {
+ XA_DEBUG_ASSERT(param > 0);
+ context->nb_variables = (uint32_t)param;
+ } else if (pname == NL_MAX_ITERATIONS) {
+ XA_DEBUG_ASSERT(param > 0);
+ context->max_iterations = (uint32_t)param;
+ context->max_iterations_defined = true;
+ }
+}
+
+static void nlSetVariable(NLContext *context, uint32_t index, double value)
+{
+ XA_DEBUG_ASSERT(index >= 0 && index <= context->nb_variables - 1);
+ NL_BUFFER_ITEM(context->variable_buffer[0], index) = value;
+}
+
+static double nlGetVariable(NLContext *context, uint32_t index)
+{
+ XA_DEBUG_ASSERT(index >= 0 && index <= context->nb_variables - 1);
+ return NL_BUFFER_ITEM(context->variable_buffer[0], index);
+}
+
+static void nlLockVariable(NLContext *context, uint32_t index)
+{
+ XA_DEBUG_ASSERT(index >= 0 && index <= context->nb_variables - 1);
+ context->variable_is_locked[index] = true;
+}
+
+static void nlVariablesToVector(NLContext *context)
+{
+ uint32_t n = context->n;
+ XA_DEBUG_ASSERT(context->x);
+ for (uint32_t k = 0; k < context->nb_systems; ++k) {
+ for (uint32_t i = 0; i < context->nb_variables; ++i) {
+ if (!context->variable_is_locked[i]) {
+ uint32_t index = context->variable_index[i];
+ XA_DEBUG_ASSERT(index < context->n);
+ double value = NL_BUFFER_ITEM(context->variable_buffer[k], i);
+ context->x[index + k * n] = value;
+ }
+ }
+ }
+}
+
+static void nlVectorToVariables(NLContext *context)
+{
+ uint32_t n = context->n;
+ XA_DEBUG_ASSERT(context->x);
+ for (uint32_t k = 0; k < context->nb_systems; ++k) {
+ for (uint32_t i = 0; i < context->nb_variables; ++i) {
+ if (!context->variable_is_locked[i]) {
+ uint32_t index = context->variable_index[i];
+ XA_DEBUG_ASSERT(index < context->n);
+ double value = context->x[index + k * n];
+ NL_BUFFER_ITEM(context->variable_buffer[k], i) = value;
+ }
+ }
+ }
+}
+
+static void nlCoefficient(NLContext *context, uint32_t index, double value)
+{
+ XA_DEBUG_ASSERT(index >= 0 && index <= context->nb_variables - 1);
+ if (context->variable_is_locked[index]) {
+ /*
+ * Note: in al, indices are NLvariable indices,
+ * within [0..nb_variables-1]
+ */
+ nlRowColumnAppend(&(context->al), index, value);
+ } else {
+ /*
+ * Note: in af, indices are system indices,
+ * within [0..n-1]
+ */
+ nlRowColumnAppend(&(context->af), context->variable_index[index], value);
+ }
+}
+
+#define NL_SYSTEM 0x0
+#define NL_MATRIX 0x1
+#define NL_ROW 0x2
+
+static void nlBegin(NLContext *context, uint32_t prim)
+{
+ if (prim == NL_SYSTEM) {
+ XA_DEBUG_ASSERT(context->nb_variables > 0);
+ context->variable_buffer = NL_NEW_ARRAY(NLBufferBinding, context->nb_systems);
+ NL_CLEAR_ARRAY(NLBufferBinding, context->variable_buffer, context->nb_systems);
+ context->variable_value = NL_NEW_ARRAY(double, context->nb_variables * context->nb_systems);
+ NL_CLEAR_ARRAY(double, context->variable_value, context->nb_variables * context->nb_systems);
+ for (uint32_t k = 0; k < context->nb_systems; ++k) {
+ context->variable_buffer[k].base_address =
+ context->variable_value +
+ k * context->nb_variables;
+ context->variable_buffer[k].stride = sizeof(double);
+ }
+ context->variable_is_locked = NL_NEW_ARRAY(bool, context->nb_variables);
+ NL_CLEAR_ARRAY(bool, context->variable_is_locked, context->nb_variables);
+ context->variable_index = NL_NEW_ARRAY(uint32_t, context->nb_variables);
+ NL_CLEAR_ARRAY(uint32_t, context->variable_index, context->nb_variables);
+ } else if (prim == NL_MATRIX) {
+ if (context->M)
+ return;
+ uint32_t n = 0;
+ for (uint32_t i = 0; i < context->nb_variables; i++) {
+ if (!context->variable_is_locked[i]) {
+ context->variable_index[i] = n;
+ n++;
+ } else
+ context->variable_index[i] = (uint32_t)~0;
+ }
+ context->n = n;
+ if (!context->max_iterations_defined)
+ context->max_iterations = n * 5;
+ context->M = (NLMatrix)(NL_NEW(NLSparseMatrix));
+ NL_CLEAR(context->M, NLSparseMatrix);
+ nlSparseMatrixConstruct((NLSparseMatrix*)(context->M), n, n);
+ context->x = NL_NEW_ARRAY(double, n*context->nb_systems);
+ NL_CLEAR_ARRAY(double, context->x, n*context->nb_systems);
+ context->b = NL_NEW_ARRAY(double, n*context->nb_systems);
+ NL_CLEAR_ARRAY(double, context->b, n*context->nb_systems);
+ nlVariablesToVector(context);
+ nlRowColumnConstruct(&context->af);
+ nlRowColumnConstruct(&context->al);
+ context->current_row = 0;
+ } else if (prim == NL_ROW) {
+ nlRowColumnZero(&context->af);
+ nlRowColumnZero(&context->al);
+ }
+}
+
+static void nlEnd(NLContext *context, uint32_t prim)
+{
+ if (prim == NL_MATRIX) {
+ nlRowColumnClear(&context->af);
+ nlRowColumnClear(&context->al);
+ } else if (prim == NL_ROW) {
+ NLRowColumn* af = &context->af;
+ NLRowColumn* al = &context->al;
+ NLSparseMatrix* M = (NLSparseMatrix*)context->M;
+ double* b = context->b;
+ uint32_t nf = af->size;
+ uint32_t nl = al->size;
+ uint32_t n = context->n;
+ double S;
+ /*
+ * least_squares : we want to solve
+ * A'A x = A'b
+ */
+ for (uint32_t i = 0; i < nf; i++) {
+ for (uint32_t j = 0; j < nf; j++) {
+ nlSparseMatrixAdd(M, af->coeff[i].index, af->coeff[j].index, af->coeff[i].value * af->coeff[j].value);
+ }
+ }
+ for (uint32_t k = 0; k < context->nb_systems; ++k) {
+ S = 0.0;
+ for (uint32_t jj = 0; jj < nl; ++jj) {
+ uint32_t j = al->coeff[jj].index;
+ S += al->coeff[jj].value * NL_BUFFER_ITEM(context->variable_buffer[k], j);
+ }
+ for (uint32_t jj = 0; jj < nf; jj++)
+ b[k*n + af->coeff[jj].index] -= af->coeff[jj].value * S;
+ }
+ context->current_row++;
+ }
+}
+
+static bool nlSolve(NLContext *context)
+{
+ nlDeleteMatrix(context->P);
+ context->P = nlNewJacobiPreconditioner(context->M);
+ nlMatrixCompress(&context->M);
+ bool result = nlSolveIterative(context);
+ nlVectorToVariables(context);
+ return result;
+}
+} // namespace opennl
+
namespace raster {
-class ClippedTriangle {
+class ClippedTriangle
+{
public:
- ClippedTriangle(const Vector2 &a, const Vector2 &b, const Vector2 &c) {
+ ClippedTriangle(const Vector2 &a, const Vector2 &b, const Vector2 &c)
+ {
m_numVertices = 3;
m_activeVertexBuffer = 0;
m_verticesA[0] = a;
@@ -4077,21 +5191,23 @@ public:
m_verticesA[2] = c;
m_vertexBuffers[0] = m_verticesA;
m_vertexBuffers[1] = m_verticesB;
+ m_area = 0;
}
- void clipHorizontalPlane(float offset, float clipdirection) {
- Vector2 *v = m_vertexBuffers[m_activeVertexBuffer];
+ void clipHorizontalPlane(float offset, float clipdirection)
+ {
+ Vector2 *v = m_vertexBuffers[m_activeVertexBuffer];
m_activeVertexBuffer ^= 1;
Vector2 *v2 = m_vertexBuffers[m_activeVertexBuffer];
v[m_numVertices] = v[0];
- float dy2, dy1 = offset - v[0].y;
- int dy2in, dy1in = clipdirection * dy1 >= 0;
- uint32_t p = 0;
+ float dy2, dy1 = offset - v[0].y;
+ int dy2in, dy1in = clipdirection * dy1 >= 0;
+ uint32_t p = 0;
for (uint32_t k = 0; k < m_numVertices; k++) {
- dy2 = offset - v[k + 1].y;
+ dy2 = offset - v[k + 1].y;
dy2in = clipdirection * dy2 >= 0;
if (dy1in) v2[p++] = v[k];
- if (dy1in + dy2in == 1) { // not both in/out
+ if ( dy1in + dy2in == 1 ) { // not both in/out
float dx = v[k + 1].x - v[k].x;
float dy = v[k + 1].y - v[k].y;
v2[p++] = Vector2(v[k].x + dy1 * (dx / dy), offset);
@@ -4102,19 +5218,20 @@ public:
m_numVertices = p;
}
- void clipVerticalPlane(float offset, float clipdirection) {
- Vector2 *v = m_vertexBuffers[m_activeVertexBuffer];
+ void clipVerticalPlane(float offset, float clipdirection)
+ {
+ Vector2 *v = m_vertexBuffers[m_activeVertexBuffer];
m_activeVertexBuffer ^= 1;
Vector2 *v2 = m_vertexBuffers[m_activeVertexBuffer];
v[m_numVertices] = v[0];
- float dx2, dx1 = offset - v[0].x;
- int dx2in, dx1in = clipdirection * dx1 >= 0;
- uint32_t p = 0;
+ float dx2, dx1 = offset - v[0].x;
+ int dx2in, dx1in = clipdirection * dx1 >= 0;
+ uint32_t p = 0;
for (uint32_t k = 0; k < m_numVertices; k++) {
dx2 = offset - v[k + 1].x;
dx2in = clipdirection * dx2 >= 0;
if (dx1in) v2[p++] = v[k];
- if (dx1in + dx2in == 1) { // not both in/out
+ if ( dx1in + dx2in == 1 ) { // not both in/out
float dx = v[k + 1].x - v[k].x;
float dy = v[k + 1].y - v[k].y;
v2[p++] = Vector2(offset, v[k].y + dx1 * (dy / dx));
@@ -4125,8 +5242,9 @@ public:
m_numVertices = p;
}
- void computeArea() {
- Vector2 *v = m_vertexBuffers[m_activeVertexBuffer];
+ void computeArea()
+ {
+ Vector2 *v = m_vertexBuffers[m_activeVertexBuffer];
v[m_numVertices] = v[0];
m_area = 0;
float centroidx = 0, centroidy = 0;
@@ -4140,7 +5258,8 @@ public:
m_area = 0.5f * fabsf(m_area);
}
- void clipAABox(float x0, float y0, float x1, float y1) {
+ void clipAABox(float x0, float y0, float x1, float y1)
+ {
clipVerticalPlane(x0, -1);
clipHorizontalPlane(y0, -1);
clipVerticalPlane(x1, 1);
@@ -4148,7 +5267,8 @@ public:
computeArea();
}
- float area() const {
+ float area() const
+ {
return m_area;
}
@@ -4165,12 +5285,10 @@ private:
typedef bool (*SamplingCallback)(void *param, int x, int y);
/// A triangle for rasterization.
-struct Triangle {
- Triangle(const Vector2 &v0, const Vector2 &v1, const Vector2 &v2) {
- // Init vertices.
- this->v1 = v0;
- this->v2 = v2;
- this->v3 = v1;
+struct Triangle
+{
+ Triangle(const Vector2 &_v0, const Vector2 &_v1, const Vector2 &_v2) : v1(_v0), v2(_v2), v3(_v1)
+ {
// make sure every triangle is front facing.
flipBackface();
// Compute deltas.
@@ -4178,7 +5296,8 @@ struct Triangle {
computeUnitInwardNormals();
}
- bool isValid() {
+ bool isValid()
+ {
const Vector2 e0 = v3 - v1;
const Vector2 e1 = v2 - v1;
const float area = e0.y * e1.x - e1.y * e0.x;
@@ -4186,17 +5305,18 @@ struct Triangle {
}
// extents has to be multiple of BK_SIZE!!
- bool drawAA(const Vector2 &extents, SamplingCallback cb, void *param) {
- const float PX_INSIDE = 1.0f / sqrtf(2.0f);
- const float PX_OUTSIDE = -1.0f / sqrtf(2.0f);
+ bool drawAA(const Vector2 &extents, SamplingCallback cb, void *param)
+ {
+ const float PX_INSIDE = 1.0f/sqrtf(2.0f);
+ const float PX_OUTSIDE = -1.0f/sqrtf(2.0f);
const float BK_SIZE = 8;
- const float BK_INSIDE = sqrtf(BK_SIZE * BK_SIZE / 2.0f);
- const float BK_OUTSIDE = -sqrtf(BK_SIZE * BK_SIZE / 2.0f);
+ const float BK_INSIDE = sqrtf(BK_SIZE*BK_SIZE/2.0f);
+ const float BK_OUTSIDE = -sqrtf(BK_SIZE*BK_SIZE/2.0f);
// Bounding rectangle
float minx = floorf(max(min3(v1.x, v2.x, v3.x), 0.0f));
float miny = floorf(max(min3(v1.y, v2.y, v3.y), 0.0f));
- float maxx = ceilf(min(max3(v1.x, v2.x, v3.x), extents.x - 1.0f));
- float maxy = ceilf(min(max3(v1.y, v2.y, v3.y), extents.y - 1.0f));
+ float maxx = ceilf( min(max3(v1.x, v2.x, v3.x), extents.x - 1.0f));
+ float maxy = ceilf( min(max3(v1.y, v2.y, v3.y), extents.y - 1.0f));
// There's no reason to align the blocks to the viewport, instead we align them to the origin of the triangle bounds.
minx = floorf(minx);
miny = floorf(miny);
@@ -4221,9 +5341,9 @@ struct Triangle {
float bC = C2 + n2.x * xc + n2.y * yc;
float cC = C3 + n3.x * xc + n3.y * yc;
// Skip block when outside an edge
- if ((aC <= BK_OUTSIDE) || (bC <= BK_OUTSIDE) || (cC <= BK_OUTSIDE)) continue;
+ if ( (aC <= BK_OUTSIDE) || (bC <= BK_OUTSIDE) || (cC <= BK_OUTSIDE) ) continue;
// Accept whole block when totally covered
- if ((aC >= BK_INSIDE) && (bC >= BK_INSIDE) && (cC >= BK_INSIDE)) {
+ if ( (aC >= BK_INSIDE) && (bC >= BK_INSIDE) && (cC >= BK_INSIDE) ) {
for (float y = y0; y < y0 + BK_SIZE; y++) {
for (float x = x0; x < x0 + BK_SIZE; x++) {
if (!cb(param, (int)x, (int)y))
@@ -4266,9 +5386,10 @@ struct Triangle {
}
private:
- void flipBackface() {
+ void flipBackface()
+ {
// check if triangle is backfacing, if so, swap two vertices
- if (((v3.x - v1.x) * (v2.y - v1.y) - (v3.y - v1.y) * (v2.x - v1.x)) < 0) {
+ if ( ((v3.x - v1.x) * (v2.y - v1.y) - (v3.y - v1.y) * (v2.x - v1.x)) < 0 ) {
Vector2 hv = v1;
v1 = v2;
v2 = hv; // swap pos
@@ -4276,7 +5397,8 @@ private:
}
// compute unit inward normals for each edge.
- void computeUnitInwardNormals() {
+ void computeUnitInwardNormals()
+ {
n1 = v1 - v2;
n1 = Vector2(-n1.y, n1.x);
n1 = n1 * (1.0f / sqrtf(dot(n1, n1)));
@@ -4294,7 +5416,8 @@ private:
};
// Process the given triangle. Returns false if rasterization was interrupted by the callback.
-static bool drawTriangle(const Vector2 &extents, const Vector2 v[3], SamplingCallback cb, void *param) {
+static bool drawTriangle(const Vector2 &extents, const Vector2 v[3], SamplingCallback cb, void *param)
+{
Triangle tri(v[0], v[1], v[2]);
// @@ It would be nice to have a conservative drawing mode that enlarges the triangle extents by one texel and is able to handle degenerate triangles.
// @@ Maybe the simplest thing to do would be raster triangle edges.
@@ -4305,251 +5428,26 @@ static bool drawTriangle(const Vector2 &extents, const Vector2 v[3], SamplingCal
} // namespace raster
-// Full and sparse vector and matrix classes. BLAS subset.
-// Pseudo-BLAS interface.
-namespace sparse {
-
-/**
-* Sparse matrix class. The matrix is assumed to be sparse and to have
-* very few non-zero elements, for this reason it's stored in indexed
-* format. To multiply column vectors efficiently, the matrix stores
-* the elements in indexed-column order, there is a list of indexed
-* elements for each row of the matrix. As with the FullVector the
-* dimension of the matrix is constant.
-**/
-class Matrix {
-public:
- // An element of the sparse array.
- struct Coefficient {
- uint32_t x; // column
- float v; // value
- };
-
- Matrix(uint32_t d) :
- m_width(d), m_array(MemTag::Matrix) {
- m_array.resize(d);
- m_array.runCtors();
-#if XA_DEBUG_HEAP
- for (uint32_t i = 0; i < d; i++)
- m_array[i].setMemTag(MemTag::Matrix);
-#endif
- }
-
- Matrix(uint32_t w, uint32_t h) :
- m_width(w), m_array(MemTag::Matrix) {
- m_array.resize(h);
- m_array.runCtors();
-#if XA_DEBUG_HEAP
- for (uint32_t i = 0; i < h; i++)
- m_array[i].setMemTag(MemTag::Matrix);
-#endif
- }
-
- ~Matrix() {
- m_array.runDtors();
- }
-
- Matrix(const Matrix &m) = delete;
- Matrix &operator=(const Matrix &m) = delete;
- uint32_t width() const { return m_width; }
- uint32_t height() const { return m_array.size(); }
- bool isSquare() const { return width() == height(); }
-
- // x is column, y is row
- float getCoefficient(uint32_t x, uint32_t y) const {
- XA_DEBUG_ASSERT(x < width());
- XA_DEBUG_ASSERT(y < height());
- const uint32_t count = m_array[y].size();
- for (uint32_t i = 0; i < count; i++) {
- if (m_array[y][i].x == x) return m_array[y][i].v;
- }
- return 0.0f;
- }
-
- void setCoefficient(uint32_t x, uint32_t y, float f) {
- XA_DEBUG_ASSERT(x < width());
- XA_DEBUG_ASSERT(y < height());
- const uint32_t count = m_array[y].size();
- for (uint32_t i = 0; i < count; i++) {
- if (m_array[y][i].x == x) {
- m_array[y][i].v = f;
- return;
- }
- }
- if (f != 0.0f) {
- Coefficient c = { x, f };
- m_array[y].push_back(c);
- }
- }
-
- float dotRow(uint32_t y, const FullVector &v) const {
- XA_DEBUG_ASSERT(y < height());
- const uint32_t count = m_array[y].size();
- float sum = 0;
- for (uint32_t i = 0; i < count; i++) {
- sum += m_array[y][i].v * v[m_array[y][i].x];
- }
- return sum;
- }
-
- void madRow(uint32_t y, float alpha, FullVector &v) const {
- XA_DEBUG_ASSERT(y < height());
- const uint32_t count = m_array[y].size();
- for (uint32_t i = 0; i < count; i++) {
- v[m_array[y][i].x] += alpha * m_array[y][i].v;
- }
- }
-
- void clearRow(uint32_t y) {
- XA_DEBUG_ASSERT(y < height());
- m_array[y].clear();
- }
-
- const Array<Coefficient> &getRow(uint32_t y) const { return m_array[y]; }
-
-private:
- /// Number of columns.
- const uint32_t m_width;
-
- /// Array of matrix elements.
- Array<Array<Coefficient>> m_array;
-};
-
-// y = a * x + y
-static void saxpy(float a, const FullVector &x, FullVector &y) {
- XA_DEBUG_ASSERT(x.dimension() == y.dimension());
- const uint32_t dim = x.dimension();
- for (uint32_t i = 0; i < dim; i++) {
- y[i] += a * x[i];
- }
-}
-
-static void copy(const FullVector &x, FullVector &y) {
- XA_DEBUG_ASSERT(x.dimension() == y.dimension());
- const uint32_t dim = x.dimension();
- for (uint32_t i = 0; i < dim; i++) {
- y[i] = x[i];
- }
-}
-
-static void scal(float a, FullVector &x) {
- const uint32_t dim = x.dimension();
- for (uint32_t i = 0; i < dim; i++) {
- x[i] *= a;
- }
-}
-
-static float dot(const FullVector &x, const FullVector &y) {
- XA_DEBUG_ASSERT(x.dimension() == y.dimension());
- const uint32_t dim = x.dimension();
- float sum = 0;
- for (uint32_t i = 0; i < dim; i++) {
- sum += x[i] * y[i];
- }
- return sum;
-}
-
-// y = M * x
-static void mult(const Matrix &M, const FullVector &x, FullVector &y) {
- uint32_t w = M.width();
- uint32_t h = M.height();
- XA_DEBUG_ASSERT(w == x.dimension());
- XA_UNUSED(w);
- XA_DEBUG_ASSERT(h == y.dimension());
- for (uint32_t i = 0; i < h; i++)
- y[i] = M.dotRow(i, x);
-}
-
-// y = alpha*A*x + beta*y
-static void sgemv(float alpha, const Matrix &A, const FullVector &x, float beta, FullVector &y) {
- const uint32_t w = A.width();
- const uint32_t h = A.height();
- XA_DEBUG_ASSERT(w == x.dimension());
- XA_DEBUG_ASSERT(h == y.dimension());
- XA_UNUSED(w);
- XA_UNUSED(h);
- for (uint32_t i = 0; i < h; i++)
- y[i] = alpha * A.dotRow(i, x) + beta * y[i];
-}
-
-// dot y-row of A by x-column of B
-static float dotRowColumn(int y, const Matrix &A, int x, const Matrix &B) {
- const Array<Matrix::Coefficient> &row = A.getRow(y);
- const uint32_t count = row.size();
- float sum = 0.0f;
- for (uint32_t i = 0; i < count; i++) {
- const Matrix::Coefficient &c = row[i];
- sum += c.v * B.getCoefficient(x, c.x);
- }
- return sum;
-}
-
-static void transpose(const Matrix &A, Matrix &B) {
- XA_DEBUG_ASSERT(A.width() == B.height());
- XA_DEBUG_ASSERT(B.width() == A.height());
- const uint32_t w = A.width();
- for (uint32_t x = 0; x < w; x++) {
- B.clearRow(x);
- }
- const uint32_t h = A.height();
- for (uint32_t y = 0; y < h; y++) {
- const Array<Matrix::Coefficient> &row = A.getRow(y);
- const uint32_t count = row.size();
- for (uint32_t i = 0; i < count; i++) {
- const Matrix::Coefficient &c = row[i];
- XA_DEBUG_ASSERT(c.x < w);
- B.setCoefficient(y, c.x, c.v);
- }
- }
-}
-
-static void sgemm(float alpha, const Matrix &A, const Matrix &B, float beta, Matrix &C) {
- const uint32_t w = C.width();
- const uint32_t h = C.height();
-#if XA_DEBUG
- const uint32_t aw = A.width();
- const uint32_t ah = A.height();
- const uint32_t bw = B.width();
- const uint32_t bh = B.height();
- XA_DEBUG_ASSERT(aw == bh);
- XA_DEBUG_ASSERT(bw == ah);
- XA_DEBUG_ASSERT(w == bw);
- XA_DEBUG_ASSERT(h == ah);
-#endif
- for (uint32_t y = 0; y < h; y++) {
- for (uint32_t x = 0; x < w; x++) {
- float c = beta * C.getCoefficient(x, y);
- // dot y-row of A by x-column of B.
- c += alpha * dotRowColumn(y, A, x, B);
- C.setCoefficient(x, y, c);
- }
- }
-}
-
-// C = A * B
-static void mult(const Matrix &A, const Matrix &B, Matrix &C) {
- sgemm(1.0f, A, B, 0.0f, C);
-}
-
-} // namespace sparse
-
namespace segment {
// - Insertion is o(n)
// - Smallest element goes at the end, so that popping it is o(1).
-struct CostQueue {
- CostQueue(uint32_t size = UINT32_MAX) :
- m_maxSize(size), m_pairs(MemTag::SegmentAtlasChartCandidates) {}
+struct CostQueue
+{
+ CostQueue(uint32_t size = UINT32_MAX) : m_maxSize(size), m_pairs(MemTag::SegmentAtlasChartCandidates) {}
- float peekCost() const {
+ float peekCost() const
+ {
return m_pairs.back().cost;
}
- uint32_t peekFace() const {
+ uint32_t peekFace() const
+ {
return m_pairs.back().face;
}
- void push(float cost, uint32_t face) {
+ void push(float cost, uint32_t face)
+ {
const Pair p = { cost, face };
if (m_pairs.isEmpty() || cost < peekCost())
m_pairs.push_back(p);
@@ -4566,25 +5464,29 @@ struct CostQueue {
}
}
- uint32_t pop() {
+ uint32_t pop()
+ {
XA_DEBUG_ASSERT(!m_pairs.isEmpty());
uint32_t f = m_pairs.back().face;
m_pairs.pop_back();
return f;
}
- XA_INLINE void clear() {
+ XA_INLINE void clear()
+ {
m_pairs.clear();
}
- XA_INLINE uint32_t count() const {
+ XA_INLINE uint32_t count() const
+ {
return m_pairs.size();
}
private:
const uint32_t m_maxSize;
- struct Pair {
+ struct Pair
+ {
float cost;
uint32_t face;
};
@@ -4592,86 +5494,92 @@ private:
Array<Pair> m_pairs;
};
-struct Chart {
- Chart() :
- faces(MemTag::SegmentAtlasChartFaces) {}
-
- int id = -1;
- Basis basis; // Best fit normal.
- float area = 0.0f;
- float boundaryLength = 0.0f;
- Vector3 centroidSum = Vector3(0.0f); // Sum of chart face centroids.
- Vector3 centroid = Vector3(0.0f); // Average centroid of chart faces.
- Array<uint32_t> seeds;
- Array<uint32_t> faces;
- Array<uint32_t> failedPlanarRegions;
- CostQueue candidates;
-};
-
-struct Atlas {
- Atlas() :
- m_edgeLengths(MemTag::SegmentAtlasMeshData), m_faceAreas(MemTag::SegmentAtlasMeshData), m_faceNormals(MemTag::SegmentAtlasMeshData), m_texcoords(MemTag::SegmentAtlasMeshData), m_bestTriangles(10), m_nextPlanarRegionFace(MemTag::SegmentAtlasPlanarRegions), m_facePlanarRegionId(MemTag::SegmentAtlasPlanarRegions) {}
-
- ~Atlas() {
- const uint32_t chartCount = m_charts.size();
- for (uint32_t i = 0; i < chartCount; i++) {
- m_charts[i]->~Chart();
- XA_FREE(m_charts[i]);
- }
- }
+struct AtlasData
+{
+ ChartOptions options;
+ const Mesh *mesh = nullptr;
+ Array<float> edgeDihedralAngles;
+ Array<float> edgeLengths;
+ Array<float> faceAreas;
+ Array<Vector3> faceNormals;
+ BitArray isFaceInChart;
- uint32_t facesLeft() const { return m_facesLeft; }
- uint32_t chartCount() const { return m_charts.size(); }
- const Array<uint32_t> &chartFaces(uint32_t i) const { return m_charts[i]->faces; }
- const Basis &chartBasis(uint32_t chartIndex) const { return m_charts[chartIndex]->basis; }
+ AtlasData() : edgeDihedralAngles(MemTag::SegmentAtlasMeshData), edgeLengths(MemTag::SegmentAtlasMeshData), faceAreas(MemTag::SegmentAtlasMeshData), faceNormals(MemTag::SegmentAtlasMeshData) {}
- void reset(uint32_t meshId, uint32_t chartGroupId, const Mesh *mesh, const ChartOptions &options) {
- XA_UNUSED(meshId);
- XA_UNUSED(chartGroupId);
- XA_PROFILE_START(buildAtlasInit)
- m_mesh = mesh;
- const uint32_t faceCount = m_mesh->faceCount();
- m_facesLeft = faceCount;
- m_options = options;
- m_rand.reset();
- const uint32_t chartCount = m_charts.size();
- for (uint32_t i = 0; i < chartCount; i++) {
- m_charts[i]->~Chart();
- XA_FREE(m_charts[i]);
- }
- m_charts.clear();
- m_faceCharts.resize(faceCount);
- m_faceCharts.setAll(-1);
- m_texcoords.resize(faceCount * 3);
- // Precompute edge lengths and face areas.
- const uint32_t edgeCount = m_mesh->edgeCount();
- m_edgeLengths.resize(edgeCount);
- m_faceAreas.resize(faceCount);
- m_faceNormals.resize(faceCount);
+ void compute()
+ {
+ const uint32_t faceCount = mesh->faceCount();
+ const uint32_t edgeCount = mesh->edgeCount();
+ edgeDihedralAngles.resize(edgeCount);
+ edgeLengths.resize(edgeCount);
+ faceAreas.resize(faceCount);
+ faceNormals.resize(faceCount);
+ isFaceInChart.resize(faceCount);
+ isFaceInChart.zeroOutMemory();
for (uint32_t f = 0; f < faceCount; f++) {
for (uint32_t i = 0; i < 3; i++) {
const uint32_t edge = f * 3 + i;
- const Vector3 &p0 = mesh->position(m_mesh->vertexAt(meshEdgeIndex0(edge)));
- const Vector3 &p1 = mesh->position(m_mesh->vertexAt(meshEdgeIndex1(edge)));
- m_edgeLengths[edge] = length(p1 - p0);
- XA_DEBUG_ASSERT(m_edgeLengths[edge] > 0.0f);
+ const Vector3 &p0 = mesh->position(mesh->vertexAt(meshEdgeIndex0(edge)));
+ const Vector3 &p1 = mesh->position(mesh->vertexAt(meshEdgeIndex1(edge)));
+ edgeLengths[edge] = length(p1 - p0);
+ XA_DEBUG_ASSERT(edgeLengths[edge] > 0.0f);
+ }
+ faceAreas[f] = mesh->computeFaceArea(f);
+ XA_DEBUG_ASSERT(faceAreas[f] > 0.0f);
+ faceNormals[f] = mesh->computeFaceNormal(f);
+ }
+ for (uint32_t face = 0; face < faceCount; face++) {
+ for (uint32_t i = 0; i < 3; i++) {
+ const uint32_t edge = face * 3 + i;
+ const uint32_t oedge = mesh->oppositeEdge(edge);
+ if (oedge == UINT32_MAX)
+ edgeDihedralAngles[edge] = FLT_MAX;
+ else {
+ const uint32_t oface = meshEdgeFace(oedge);
+ edgeDihedralAngles[edge] = edgeDihedralAngles[oedge] = dot(faceNormals[face], faceNormals[oface]);
+ }
}
- m_faceAreas[f] = m_mesh->computeFaceArea(f);
- XA_DEBUG_ASSERT(m_faceAreas[f] > 0.0f);
- m_faceNormals[f] = m_mesh->computeFaceNormal(f);
}
+ }
+};
+
+#if XA_DEBUG_EXPORT_OBJ_PLANAR_REGIONS
+static uint32_t s_planarRegionsCurrentRegion;
+static uint32_t s_planarRegionsCurrentVertex;
+#endif
+
+struct PlanarCharts
+{
+ PlanarCharts(AtlasData &data) : m_data(data), m_nextRegionFace(MemTag::SegmentAtlasPlanarRegions), m_faceToRegionId(MemTag::SegmentAtlasPlanarRegions) {}
+ const Basis &chartBasis(uint32_t chartIndex) const { return m_chartBasis[chartIndex]; }
+ uint32_t chartCount() const { return m_charts.size(); }
+
+ ConstArrayView<uint32_t> chartFaces(uint32_t chartIndex) const
+ {
+ const Chart &chart = m_charts[chartIndex];
+ return ConstArrayView<uint32_t>(&m_chartFaces[chart.firstFace], chart.faceCount);
+ }
+
+ uint32_t regionIdFromFace(uint32_t face) const { return m_faceToRegionId[face]; }
+ uint32_t nextRegionFace(uint32_t face) const { return m_nextRegionFace[face]; }
+ float regionArea(uint32_t region) const { return m_regionAreas[region]; }
+
+ void compute()
+ {
+ const uint32_t faceCount = m_data.mesh->faceCount();
// Precompute regions of coplanar incident faces.
- m_nextPlanarRegionFace.resize(faceCount);
- m_facePlanarRegionId.resize(faceCount);
+ m_regionFirstFace.clear();
+ m_nextRegionFace.resize(faceCount);
+ m_faceToRegionId.resize(faceCount);
for (uint32_t f = 0; f < faceCount; f++) {
- m_nextPlanarRegionFace[f] = f;
- m_facePlanarRegionId[f] = UINT32_MAX;
+ m_nextRegionFace[f] = f;
+ m_faceToRegionId[f] = UINT32_MAX;
}
Array<uint32_t> faceStack;
faceStack.reserve(min(faceCount, 16u));
- uint32_t planarRegionCount = 0;
+ uint32_t regionCount = 0;
for (uint32_t f = 0; f < faceCount; f++) {
- if (m_nextPlanarRegionFace[f] != f)
+ if (m_nextRegionFace[f] != f)
continue; // Already assigned.
faceStack.clear();
faceStack.push_back(f);
@@ -4679,48 +5587,207 @@ struct Atlas {
if (faceStack.isEmpty())
break;
const uint32_t face = faceStack.back();
- m_facePlanarRegionId[face] = planarRegionCount;
+ m_faceToRegionId[face] = regionCount;
faceStack.pop_back();
- for (Mesh::FaceEdgeIterator it(m_mesh, face); !it.isDone(); it.advance()) {
+ for (Mesh::FaceEdgeIterator it(m_data.mesh, face); !it.isDone(); it.advance()) {
const uint32_t oface = it.oppositeFace();
if (it.isBoundary())
continue;
- if (m_nextPlanarRegionFace[oface] != oface)
+ if (m_nextRegionFace[oface] != oface)
continue; // Already assigned.
- if (!equal(dot(m_faceNormals[face], m_faceNormals[oface]), 1.0f, kEpsilon))
+ if (!equal(dot(m_data.faceNormals[face], m_data.faceNormals[oface]), 1.0f, kEpsilon))
continue; // Not coplanar.
- const uint32_t next = m_nextPlanarRegionFace[face];
- m_nextPlanarRegionFace[face] = oface;
- m_nextPlanarRegionFace[oface] = next;
- m_facePlanarRegionId[oface] = planarRegionCount;
+ const uint32_t next = m_nextRegionFace[face];
+ m_nextRegionFace[face] = oface;
+ m_nextRegionFace[oface] = next;
+ m_faceToRegionId[oface] = regionCount;
faceStack.push_back(oface);
}
}
- planarRegionCount++;
+ m_regionFirstFace.push_back(f);
+ regionCount++;
}
#if XA_DEBUG_EXPORT_OBJ_PLANAR_REGIONS
- char filename[256];
- XA_SPRINTF(filename, sizeof(filename), "debug_mesh_%03u_chartgroup_%03u_planar_regions.obj", meshId, chartGroupId);
- FILE *file;
- XA_FOPEN(file, filename, "w");
- if (file) {
- m_mesh->writeObjVertices(file);
- fprintf(file, "s off\n");
- for (uint32_t i = 0; i < planarRegionCount; i++) {
- fprintf(file, "o region%u\n", i);
- for (uint32_t j = 0; j < faceCount; j++) {
- if (m_facePlanarRegionId[j] == i)
- m_mesh->writeObjFace(file, j);
+ static std::mutex s_mutex;
+ {
+ std::lock_guard<std::mutex> lock(s_mutex);
+ FILE *file;
+ XA_FOPEN(file, "debug_mesh_planar_regions.obj", s_planarRegionsCurrentRegion == 0 ? "w" : "a");
+ if (file) {
+ m_data.mesh->writeObjVertices(file);
+ fprintf(file, "s off\n");
+ for (uint32_t i = 0; i < regionCount; i++) {
+ fprintf(file, "o region%u\n", s_planarRegionsCurrentRegion);
+ for (uint32_t j = 0; j < faceCount; j++) {
+ if (m_faceToRegionId[j] == i)
+ m_data.mesh->writeObjFace(file, j, s_planarRegionsCurrentVertex);
+ }
+ s_planarRegionsCurrentRegion++;
}
+ s_planarRegionsCurrentVertex += m_data.mesh->vertexCount();
+ fclose(file);
}
- fclose(file);
}
#endif
- XA_PROFILE_END(buildAtlasInit)
+ // Precompute planar region areas.
+ m_regionAreas.resize(regionCount);
+ m_regionAreas.zeroOutMemory();
+ for (uint32_t f = 0; f < faceCount; f++)
+ m_regionAreas[m_faceToRegionId[f]] += m_data.faceAreas[f];
+ // Create charts from suitable planar regions.
+ // The dihedral angle of all boundary edges must be >= 90 degrees.
+ m_charts.clear();
+ m_chartFaces.clear();
+ for (uint32_t region = 0; region < regionCount; region++) {
+ const uint32_t firstRegionFace = m_regionFirstFace[region];
+ uint32_t face = firstRegionFace;
+ bool createChart = true;
+ do {
+ for (Mesh::FaceEdgeIterator it(m_data.mesh, face); !it.isDone(); it.advance()) {
+ if (it.isBoundary())
+ continue; // Ignore mesh boundary edges.
+ const uint32_t oface = it.oppositeFace();
+ if (m_faceToRegionId[oface] == region)
+ continue; // Ignore internal edges.
+ const float angle = m_data.edgeDihedralAngles[it.edge()];
+ if (angle > 0.0f && angle < FLT_MAX) { // FLT_MAX on boundaries.
+ createChart = false;
+ break;
+ }
+ }
+ if (!createChart)
+ break;
+ face = m_nextRegionFace[face];
+ }
+ while (face != firstRegionFace);
+ // Create a chart.
+ if (createChart) {
+ Chart chart;
+ chart.firstFace = m_chartFaces.size();
+ chart.faceCount = 0;
+ face = firstRegionFace;
+ do {
+ m_data.isFaceInChart.set(face);
+ m_chartFaces.push_back(face);
+ chart.faceCount++;
+ face = m_nextRegionFace[face];
+ }
+ while (face != firstRegionFace);
+ m_charts.push_back(chart);
+ }
+ }
+ // Compute basis for each chart using the first face normal (all faces have the same normal).
+ m_chartBasis.resize(m_charts.size());
+ for (uint32_t c = 0; c < m_charts.size(); c++)
+ {
+ const uint32_t face = m_chartFaces[m_charts[c].firstFace];
+ Basis &basis = m_chartBasis[c];
+ basis.normal = m_data.faceNormals[face];
+ basis.tangent = Basis::computeTangent(basis.normal);
+ basis.bitangent = Basis::computeBitangent(basis.normal, basis.tangent);
+ }
+ }
+
+private:
+ struct Chart
+ {
+ uint32_t firstFace, faceCount;
+ };
+
+ AtlasData &m_data;
+ Array<uint32_t> m_regionFirstFace;
+ Array<uint32_t> m_nextRegionFace;
+ Array<uint32_t> m_faceToRegionId;
+ Array<float> m_regionAreas;
+ Array<Chart> m_charts;
+ Array<uint32_t> m_chartFaces;
+ Array<Basis> m_chartBasis;
+};
+
+struct ClusteredCharts
+{
+ ClusteredCharts(AtlasData &data, const PlanarCharts &planarCharts) : m_data(data), m_planarCharts(planarCharts), m_texcoords(MemTag::SegmentAtlasMeshData), m_bestTriangles(10), m_placingSeeds(false) {}
+
+ ~ClusteredCharts()
+ {
+ const uint32_t chartCount = m_charts.size();
+ for (uint32_t i = 0; i < chartCount; i++) {
+ m_charts[i]->~Chart();
+ XA_FREE(m_charts[i]);
+ }
}
- void placeSeeds(float threshold) {
- XA_PROFILE_START(buildAtlasPlaceSeeds)
+ uint32_t chartCount() const { return m_charts.size(); }
+ ConstArrayView<uint32_t> chartFaces(uint32_t chartIndex) const { return m_charts[chartIndex]->faces; }
+ const Basis &chartBasis(uint32_t chartIndex) const { return m_charts[chartIndex]->basis; }
+
+ void compute()
+ {
+ const uint32_t faceCount = m_data.mesh->faceCount();
+ m_facesLeft = 0;
+ for (uint32_t i = 0; i < faceCount; i++) {
+ if (!m_data.isFaceInChart.get(i))
+ m_facesLeft++;
+ }
+ const uint32_t chartCount = m_charts.size();
+ for (uint32_t i = 0; i < chartCount; i++) {
+ m_charts[i]->~Chart();
+ XA_FREE(m_charts[i]);
+ }
+ m_charts.clear();
+ m_faceCharts.resize(faceCount);
+ m_faceCharts.fill(-1);
+ m_texcoords.resize(faceCount * 3);
+ if (m_facesLeft == 0)
+ return;
+ // Create initial charts greedely.
+ placeSeeds(m_data.options.maxCost * 0.5f);
+ if (m_data.options.maxIterations == 0) {
+ XA_DEBUG_ASSERT(m_facesLeft == 0);
+ return;
+ }
+ relocateSeeds();
+ resetCharts();
+ // Restart process growing charts in parallel.
+ uint32_t iteration = 0;
+ for (;;) {
+ growCharts(m_data.options.maxCost);
+ // When charts cannot grow more: fill holes, merge charts, relocate seeds and start new iteration.
+ fillHoles(m_data.options.maxCost * 0.5f);
+#if XA_MERGE_CHARTS
+ mergeCharts();
+#endif
+ if (++iteration == m_data.options.maxIterations)
+ break;
+ if (!relocateSeeds())
+ break;
+ resetCharts();
+ }
+ // Make sure no holes are left!
+ XA_DEBUG_ASSERT(m_facesLeft == 0);
+ }
+
+private:
+ struct Chart
+ {
+ Chart() : faces(MemTag::SegmentAtlasChartFaces) {}
+
+ int id = -1;
+ Basis basis; // Best fit normal.
+ float area = 0.0f;
+ float boundaryLength = 0.0f;
+ Vector3 centroidSum = Vector3(0.0f); // Sum of chart face centroids.
+ Vector3 centroid = Vector3(0.0f); // Average centroid of chart faces.
+ Array<uint32_t> faces;
+ Array<uint32_t> failedPlanarRegions;
+ CostQueue candidates;
+ uint32_t seed;
+ };
+
+ void placeSeeds(float threshold)
+ {
+ XA_PROFILE_START(clusteredChartsPlaceSeeds)
+ m_placingSeeds = true;
// Instead of using a predefiened number of seeds:
// - Add seeds one by one, growing chart until a certain treshold.
// - Undo charts and restart growing process.
@@ -4728,13 +5795,15 @@ struct Atlas {
// - those points can be found using a simple flood filling algorithm.
// - how do we weight the probabilities?
while (m_facesLeft > 0)
- createRandomChart(threshold);
- XA_PROFILE_END(buildAtlasPlaceSeeds)
+ createChart(threshold);
+ m_placingSeeds = false;
+ XA_PROFILE_END(clusteredChartsPlaceSeeds)
}
// Returns true if any of the charts can grow more.
- void growCharts(float threshold) {
- XA_PROFILE_START(buildAtlasGrowCharts)
+ void growCharts(float threshold)
+ {
+ XA_PROFILE_START(clusteredChartsGrow)
for (;;) {
if (m_facesLeft == 0)
break;
@@ -4752,7 +5821,7 @@ struct Atlas {
break;
cost = chart->candidates.peekCost();
face = chart->candidates.peekFace();
- if (m_faceCharts[face] == -1)
+ if (!m_data.isFaceInChart.get(face))
break;
else {
// Face belongs to another chart. Pop from queue so the next best candidate can be retrieved.
@@ -4774,21 +5843,28 @@ struct Atlas {
Chart *chart = m_charts[bestChart];
chart->candidates.pop(); // Pop the selected candidate from the queue.
if (!addFaceToChart(chart, bestFace))
- chart->failedPlanarRegions.push_back(m_facePlanarRegionId[bestFace]);
+ chart->failedPlanarRegions.push_back(m_planarCharts.regionIdFromFace(bestFace));
}
- XA_PROFILE_END(buildAtlasGrowCharts)
+ XA_PROFILE_END(clusteredChartsGrow)
}
- void resetCharts() {
- XA_PROFILE_START(buildAtlasResetCharts)
- const uint32_t faceCount = m_mesh->faceCount();
- for (uint32_t i = 0; i < faceCount; i++)
+ void resetCharts()
+ {
+ XA_PROFILE_START(clusteredChartsReset)
+ const uint32_t faceCount = m_data.mesh->faceCount();
+ for (uint32_t i = 0; i < faceCount; i++) {
+ if (m_faceCharts[i] != -1)
+ m_data.isFaceInChart.unset(i);
m_faceCharts[i] = -1;
- m_facesLeft = faceCount;
+ }
+ m_facesLeft = 0;
+ for (uint32_t i = 0; i < faceCount; i++) {
+ if (!m_data.isFaceInChart.get(i))
+ m_facesLeft++;
+ }
const uint32_t chartCount = m_charts.size();
for (uint32_t i = 0; i < chartCount; i++) {
Chart *chart = m_charts[i];
- const uint32_t seed = chart->seeds.back();
chart->area = 0.0f;
chart->boundaryLength = 0.0f;
chart->basis.normal = Vector3(0.0f);
@@ -4799,13 +5875,14 @@ struct Atlas {
chart->faces.clear();
chart->candidates.clear();
chart->failedPlanarRegions.clear();
- addFaceToChart(chart, seed);
+ addFaceToChart(chart, chart->seed);
}
- XA_PROFILE_END(buildAtlasResetCharts)
+ XA_PROFILE_END(clusteredChartsReset)
}
- bool relocateSeeds() {
- XA_PROFILE_START(buildAtlasRelocateSeeds)
+ bool relocateSeeds()
+ {
+ XA_PROFILE_START(clusteredChartsRelocateSeeds)
bool anySeedChanged = false;
const uint32_t chartCount = m_charts.size();
for (uint32_t i = 0; i < chartCount; i++) {
@@ -4813,20 +5890,22 @@ struct Atlas {
anySeedChanged = true;
}
}
- XA_PROFILE_END(buildAtlasRelocateSeeds)
+ XA_PROFILE_END(clusteredChartsRelocateSeeds)
return anySeedChanged;
}
- void fillHoles(float threshold) {
- XA_PROFILE_START(buildAtlasFillHoles)
+ void fillHoles(float threshold)
+ {
+ XA_PROFILE_START(clusteredChartsFillHoles)
while (m_facesLeft > 0)
- createRandomChart(threshold);
- XA_PROFILE_END(buildAtlasFillHoles)
+ createChart(threshold);
+ XA_PROFILE_END(clusteredChartsFillHoles)
}
#if XA_MERGE_CHARTS
- void mergeCharts() {
- XA_PROFILE_START(buildAtlasMergeCharts)
+ void mergeCharts()
+ {
+ XA_PROFILE_START(clusteredChartsMerge)
const uint32_t chartCount = m_charts.size();
// Merge charts progressively until there's none left to merge.
for (;;) {
@@ -4845,13 +5924,15 @@ struct Atlas {
const uint32_t faceCount = chart->faces.size();
for (uint32_t i = 0; i < faceCount; i++) {
const uint32_t f = chart->faces[i];
- for (Mesh::FaceEdgeIterator it(m_mesh, f); !it.isDone(); it.advance()) {
- const float l = m_edgeLengths[it.edge()];
+ for (Mesh::FaceEdgeIterator it(m_data.mesh, f); !it.isDone(); it.advance()) {
+ const float l = m_data.edgeLengths[it.edge()];
if (it.isBoundary()) {
externalBoundaryLength += l;
} else {
const int neighborChart = m_faceCharts[it.oppositeFace()];
- if (m_charts[neighborChart] != chart) {
+ if (neighborChart == -1)
+ externalBoundaryLength += l;
+ else if (m_charts[neighborChart] != chart) {
if ((it.isSeam() && (isNormalSeam(it.edge()) || it.isTextureSeam()))) {
externalBoundaryLength += l;
} else {
@@ -4876,14 +5957,14 @@ struct Atlas {
if (dot(chart2->basis.normal, chart->basis.normal) < XA_MERGE_CHARTS_MIN_NORMAL_DEVIATION)
continue;
// Obey max chart area and boundary length.
- if (m_options.maxChartArea > 0.0f && chart->area + chart2->area > m_options.maxChartArea)
+ if (m_data.options.maxChartArea > 0.0f && chart->area + chart2->area > m_data.options.maxChartArea)
continue;
- if (m_options.maxBoundaryLength > 0.0f && chart->boundaryLength + chart2->boundaryLength - m_sharedBoundaryLengthsNoSeams[cc] > m_options.maxBoundaryLength)
+ if (m_data.options.maxBoundaryLength > 0.0f && chart->boundaryLength + chart2->boundaryLength - m_sharedBoundaryLengthsNoSeams[cc] > m_data.options.maxBoundaryLength)
continue;
// Merge if chart2 has a single face.
// chart1 must have more than 1 face.
// chart2 area must be <= 10% of chart1 area.
- if (m_sharedBoundaryLengthsNoSeams[cc] > 0.0f && chart->faces.size() > 1 && chart2->faces.size() == 1 && chart2->area <= chart->area * 0.1f)
+ if (m_sharedBoundaryLengthsNoSeams[cc] > 0.0f && chart->faces.size() > 1 && chart2->faces.size() == 1 && chart2->area <= chart->area * 0.1f)
goto merge;
// Merge if chart2 has two faces (probably a quad), and chart1 bounds at least 2 of its edges.
if (chart2->faces.size() == 2 && m_sharedBoundaryEdgeCountNoSeams[cc] >= 2)
@@ -4891,8 +5972,8 @@ struct Atlas {
// Merge if chart2 is wholely inside chart1, ignoring seams.
if (m_sharedBoundaryLengthsNoSeams[cc] > 0.0f && equal(m_sharedBoundaryLengthsNoSeams[cc], chart2->boundaryLength, kEpsilon))
goto merge;
- if (m_sharedBoundaryLengths[cc] > 0.2f * max(0.0f, chart->boundaryLength - externalBoundaryLength) ||
- m_sharedBoundaryLengths[cc] > 0.75f * chart2->boundaryLength)
+ if (m_sharedBoundaryLengths[cc] > 0.2f * max(0.0f, chart->boundaryLength - externalBoundaryLength) ||
+ m_sharedBoundaryLengths[cc] > 0.75f * chart2->boundaryLength)
goto merge;
continue;
merge:
@@ -4925,55 +6006,64 @@ struct Atlas {
c++;
}
}
- XA_PROFILE_END(buildAtlasMergeCharts)
+ XA_PROFILE_END(clusteredChartsMerge)
}
#endif
private:
- void createRandomChart(float threshold) {
+ void createChart(float threshold)
+ {
Chart *chart = XA_NEW(MemTag::Default, Chart);
chart->id = (int)m_charts.size();
m_charts.push_back(chart);
- // Pick random face that is not used by any chart yet.
- uint32_t face = m_rand.getRange(m_mesh->faceCount() - 1);
- while (m_faceCharts[face] != -1) {
- if (++face >= m_mesh->faceCount())
- face = 0;
- }
- chart->seeds.push_back(face);
- addFaceToChart(chart, face);
+ // Pick a face not used by any chart yet, belonging to the largest planar region.
+ chart->seed = 0;
+ float largestArea = 0.0f;
+ for (uint32_t f = 0; f < m_data.mesh->faceCount(); f++) {
+ if (m_data.isFaceInChart.get(f))
+ continue;
+ const float area = m_planarCharts.regionArea(m_planarCharts.regionIdFromFace(f));
+ if (area > largestArea) {
+ largestArea = area;
+ chart->seed = f;
+ }
+ }
+ addFaceToChart(chart, chart->seed);
// Grow the chart as much as possible within the given threshold.
for (;;) {
if (chart->candidates.count() == 0 || chart->candidates.peekCost() > threshold)
break;
const uint32_t f = chart->candidates.pop();
- if (m_faceCharts[f] != -1)
+ if (m_data.isFaceInChart.get(f))
continue;
if (!addFaceToChart(chart, f)) {
- chart->failedPlanarRegions.push_back(m_facePlanarRegionId[f]);
+ chart->failedPlanarRegions.push_back(m_planarCharts.regionIdFromFace(f));
continue;
}
}
}
- bool isChartBoundaryEdge(const Chart *chart, uint32_t edge) const {
- const uint32_t oppositeEdge = m_mesh->oppositeEdge(edge);
+ bool isChartBoundaryEdge(const Chart *chart, uint32_t edge) const
+ {
+ const uint32_t oppositeEdge = m_data.mesh->oppositeEdge(edge);
const uint32_t oppositeFace = meshEdgeFace(oppositeEdge);
return oppositeEdge == UINT32_MAX || m_faceCharts[oppositeFace] != chart->id;
}
- bool computeChartBasis(Chart *chart, Basis *basis) {
+ bool computeChartBasis(Chart *chart, Basis *basis)
+ {
const uint32_t faceCount = chart->faces.size();
m_tempPoints.resize(chart->faces.size() * 3);
for (uint32_t i = 0; i < faceCount; i++) {
const uint32_t f = chart->faces[i];
for (uint32_t j = 0; j < 3; j++)
- m_tempPoints[i * 3 + j] = m_mesh->position(m_mesh->vertexAt(f * 3 + j));
+ m_tempPoints[i * 3 + j] = m_data.mesh->position(m_data.mesh->vertexAt(f * 3 + j));
}
return Fit::computeBasis(m_tempPoints.data(), m_tempPoints.size(), basis);
}
- bool isFaceFlipped(uint32_t face) const {
+ bool isFaceFlipped(uint32_t face) const
+ {
const Vector2 &v1 = m_texcoords[face * 3 + 0];
const Vector2 &v2 = m_texcoords[face * 3 + 1];
const Vector2 &v3 = m_texcoords[face * 3 + 2];
@@ -4981,20 +6071,22 @@ private:
return parametricArea < 0.0f;
}
- void parameterizeChart(const Chart *chart) {
+ void parameterizeChart(const Chart *chart)
+ {
const uint32_t faceCount = chart->faces.size();
for (uint32_t i = 0; i < faceCount; i++) {
const uint32_t face = chart->faces[i];
for (uint32_t j = 0; j < 3; j++) {
const uint32_t offset = face * 3 + j;
- const Vector3 &pos = m_mesh->position(m_mesh->vertexAt(offset));
+ const Vector3 &pos = m_data.mesh->position(m_data.mesh->vertexAt(offset));
m_texcoords[offset] = Vector2(dot(chart->basis.tangent, pos), dot(chart->basis.bitangent, pos));
}
}
}
// m_faceCharts for the chart faces must be set to the chart ID. Needed to compute boundary edges.
- bool isChartParameterizationValid(const Chart *chart) {
+ bool isChartParameterizationValid(const Chart *chart)
+ {
const uint32_t faceCount = chart->faces.size();
// Check for flipped faces in the parameterization. OK if all are flipped.
uint32_t flippedFaceCount = 0;
@@ -5005,6 +6097,8 @@ private:
if (flippedFaceCount != 0 && flippedFaceCount != faceCount)
return false;
// Check for boundary intersection in the parameterization.
+ XA_PROFILE_START(clusteredChartsPlaceSeedsBoundaryIntersection)
+ XA_PROFILE_START(clusteredChartsGrowBoundaryIntersection)
m_boundaryGrid.reset(m_texcoords.data());
for (uint32_t i = 0; i < faceCount; i++) {
const uint32_t f = chart->faces[i];
@@ -5014,22 +6108,30 @@ private:
m_boundaryGrid.append(edge);
}
}
- if (m_boundaryGrid.intersectSelf(m_mesh->epsilon()))
+ const bool intersection = m_boundaryGrid.intersect(m_data.mesh->epsilon());
+#if XA_PROFILE
+ if (m_placingSeeds)
+ XA_PROFILE_END(clusteredChartsPlaceSeedsBoundaryIntersection)
+ else
+ XA_PROFILE_END(clusteredChartsGrowBoundaryIntersection)
+#endif
+ if (intersection)
return false;
return true;
}
- bool addFaceToChart(Chart *chart, uint32_t face) {
- XA_DEBUG_ASSERT(m_faceCharts[face] == -1);
+ bool addFaceToChart(Chart *chart, uint32_t face)
+ {
+ XA_DEBUG_ASSERT(!m_data.isFaceInChart.get(face));
const uint32_t oldFaceCount = chart->faces.size();
const bool firstFace = oldFaceCount == 0;
// Append the face and any coplanar connected faces to the chart faces array.
chart->faces.push_back(face);
- uint32_t coplanarFace = m_nextPlanarRegionFace[face];
- while (coplanarFace != face) {
- XA_DEBUG_ASSERT(m_faceCharts[coplanarFace] == -1);
+ uint32_t coplanarFace = m_planarCharts.nextRegionFace(face);
+ while (coplanarFace != face) {
+ XA_DEBUG_ASSERT(!m_data.isFaceInChart.get(coplanarFace));
chart->faces.push_back(coplanarFace);
- coplanarFace = m_nextPlanarRegionFace[coplanarFace];
+ coplanarFace = m_planarCharts.nextRegionFace(coplanarFace);
}
const uint32_t faceCount = chart->faces.size();
// Compute basis.
@@ -5037,8 +6139,8 @@ private:
if (firstFace) {
// Use the first face normal.
// Use any edge as the tangent vector.
- basis.normal = m_faceNormals[face];
- basis.tangent = normalize(m_mesh->position(m_mesh->vertexAt(face * 3 + 0)) - m_mesh->position(m_mesh->vertexAt(face * 3 + 1)), 0);
+ basis.normal = m_data.faceNormals[face];
+ basis.tangent = normalize(m_data.mesh->position(m_data.mesh->vertexAt(face * 3 + 0)) - m_data.mesh->position(m_data.mesh->vertexAt(face * 3 + 1)), kEpsilon);
basis.bitangent = cross(basis.normal, basis.tangent);
} else {
// Use best fit normal.
@@ -5046,7 +6148,7 @@ private:
chart->faces.resize(oldFaceCount);
return false;
}
- if (dot(basis.normal, m_faceNormals[face]) < 0.0f) // Flip normal if oriented in the wrong direction.
+ if (dot(basis.normal, m_data.faceNormals[face]) < 0.0f) // Flip normal if oriented in the wrong direction.
basis.normal = -basis.normal;
}
if (!firstFace) {
@@ -5069,7 +6171,8 @@ private:
const uint32_t f = chart->faces[i];
m_faceCharts[f] = chart->id;
m_facesLeft--;
- chart->centroidSum += m_mesh->computeFaceCenter(f);
+ m_data.isFaceInChart.set(f);
+ chart->centroidSum += m_data.mesh->computeFaceCenter(f);
}
chart->centroid = chart->centroidSum / float(chart->faces.size());
// Refresh candidates.
@@ -5079,15 +6182,15 @@ private:
const uint32_t f = chart->faces[i];
for (uint32_t j = 0; j < 3; j++) {
const uint32_t edge = f * 3 + j;
- const uint32_t oedge = m_mesh->oppositeEdge(edge);
+ const uint32_t oedge = m_data.mesh->oppositeEdge(edge);
if (oedge == UINT32_MAX)
continue; // Boundary edge.
const uint32_t oface = meshEdgeFace(oedge);
- if (m_faceCharts[oface] != -1)
+ if (m_data.isFaceInChart.get(oface))
continue; // Face belongs to another chart.
- if (chart->failedPlanarRegions.contains(m_facePlanarRegionId[oface]))
+ if (chart->failedPlanarRegions.contains(m_planarCharts.regionIdFromFace(oface)))
continue; // Failed to add this faces planar region to the chart before.
- const float cost = evaluateCost(chart, oface);
+ const float cost = computeCost(chart, oface);
if (cost < FLT_MAX)
chart->candidates.push(cost, oface);
}
@@ -5096,76 +6199,62 @@ private:
}
// Returns true if the seed has changed.
- bool relocateSeed(Chart *chart) {
+ bool relocateSeed(Chart *chart)
+ {
// Find the first N triangles that fit the proxy best.
const uint32_t faceCount = chart->faces.size();
m_bestTriangles.clear();
for (uint32_t i = 0; i < faceCount; i++) {
- const float cost = evaluateProxyFitMetric(chart, chart->faces[i]);
+ const float cost = computeNormalDeviationMetric(chart, chart->faces[i]);
m_bestTriangles.push(cost, chart->faces[i]);
}
- // Of those, choose the least central triangle.
- uint32_t leastCentral = 0;
- float maxDistance = -1;
+ // Of those, choose the most central triangle.
+ uint32_t mostCentral = 0;
+ float minDistance = FLT_MAX;
for (;;) {
if (m_bestTriangles.count() == 0)
break;
const uint32_t face = m_bestTriangles.pop();
- Vector3 faceCentroid = m_mesh->computeFaceCenter(face);
+ Vector3 faceCentroid = m_data.mesh->computeFaceCenter(face);
const float distance = length(chart->centroid - faceCentroid);
- if (distance > maxDistance) {
- maxDistance = distance;
- leastCentral = face;
- }
- }
- XA_DEBUG_ASSERT(maxDistance >= 0);
- // In order to prevent k-means cyles we record all the previously chosen seeds.
- for (uint32_t i = 0; i < chart->seeds.size(); i++) {
- // Treat seeds belong to the same planar region as equal.
- if (chart->seeds[i] == leastCentral || m_facePlanarRegionId[chart->seeds[i]] == m_facePlanarRegionId[leastCentral]) {
- // Move new seed to the end of the seed array.
- uint32_t last = chart->seeds.size() - 1;
- swap(chart->seeds[i], chart->seeds[last]);
- return false;
+ if (distance < minDistance) {
+ minDistance = distance;
+ mostCentral = face;
}
}
- // Append new seed.
- chart->seeds.push_back(leastCentral);
+ XA_DEBUG_ASSERT(minDistance < FLT_MAX);
+ if (mostCentral == chart->seed)
+ return false;
+ chart->seed = mostCentral;
return true;
}
- // Evaluate combined metric.
- float evaluateCost(Chart *chart, uint32_t face) const {
- if (dot(m_faceNormals[face], chart->basis.normal) <= 0.26f) // ~75 degrees
- return FLT_MAX;
+ // Cost is combined metrics * weights.
+ float computeCost(Chart *chart, uint32_t face) const
+ {
// Estimate boundary length and area:
- float newChartArea = 0.0f, newBoundaryLength = 0.0f;
- if (m_options.maxChartArea > 0.0f || m_options.roundnessMetricWeight > 0.0f)
- newChartArea = computeArea(chart, face);
- if (m_options.maxBoundaryLength > 0.0f || m_options.roundnessMetricWeight > 0.0f)
- newBoundaryLength = computeBoundaryLength(chart, face);
+ const float newChartArea = computeArea(chart, face);
+ const float newBoundaryLength = computeBoundaryLength(chart, face);
// Enforce limits strictly:
- if (m_options.maxChartArea > 0.0f && newChartArea > m_options.maxChartArea)
+ if (m_data.options.maxChartArea > 0.0f && newChartArea > m_data.options.maxChartArea)
return FLT_MAX;
- if (m_options.maxBoundaryLength > 0.0f && newBoundaryLength > m_options.maxBoundaryLength)
+ if (m_data.options.maxBoundaryLength > 0.0f && newBoundaryLength > m_data.options.maxBoundaryLength)
return FLT_MAX;
+ // Compute metrics.
float cost = 0.0f;
- if (m_options.normalSeamMetricWeight > 0.0f) {
- // Penalize faces that cross seams, reward faces that close seams or reach boundaries.
- // Make sure normal seams are fully respected:
- const float N = evaluateNormalSeamMetric(chart, face);
- if (m_options.normalSeamMetricWeight >= 1000.0f && N > 0.0f)
- return FLT_MAX;
- cost += m_options.normalSeamMetricWeight * N;
- }
- if (m_options.proxyFitMetricWeight > 0.0f)
- cost += m_options.proxyFitMetricWeight * evaluateProxyFitMetric(chart, face);
- if (m_options.roundnessMetricWeight > 0.0f)
- cost += m_options.roundnessMetricWeight * evaluateRoundnessMetric(chart, newBoundaryLength, newChartArea);
- if (m_options.straightnessMetricWeight > 0.0f)
- cost += m_options.straightnessMetricWeight * evaluateStraightnessMetric(chart, face);
- if (m_options.textureSeamMetricWeight > 0.0f)
- cost += m_options.textureSeamMetricWeight * evaluateTextureSeamMetric(chart, face);
+ const float normalDeviation = computeNormalDeviationMetric(chart, face);
+ if (normalDeviation >= 0.707f) // ~75 degrees
+ return FLT_MAX;
+ cost += m_data.options.normalDeviationWeight * normalDeviation;
+ // Penalize faces that cross seams, reward faces that close seams or reach boundaries.
+ // Make sure normal seams are fully respected:
+ const float normalSeam = computeNormalSeamMetric(chart, face);
+ if (m_data.options.normalSeamWeight >= 1000.0f && normalSeam > 0.0f)
+ return FLT_MAX;
+ cost += m_data.options.normalSeamWeight * normalSeam;
+ cost += m_data.options.roundnessWeight * computeRoundnessMetric(chart, newBoundaryLength, newChartArea);
+ cost += m_data.options.straightnessWeight * computeStraightnessMetric(chart, face);
+ cost += m_data.options.textureSeamWeight * computeTextureSeamMetric(chart, face);
//float R = evaluateCompletenessMetric(chart, face);
//float D = evaluateDihedralAngleMetric(chart, face);
// @@ Add a metric based on local dihedral angle.
@@ -5176,100 +6265,108 @@ private:
}
// Returns a value in [0-1].
- float evaluateProxyFitMetric(Chart *chart, uint32_t face) const {
+ // 0 if face normal is coplanar to the chart's best fit normal.
+ // 1 if face normal is perpendicular.
+ float computeNormalDeviationMetric(Chart *chart, uint32_t face) const
+ {
// All faces in coplanar regions have the same normal, can use any face.
- const Vector3 faceNormal = m_faceNormals[face];
+ const Vector3 faceNormal = m_data.faceNormals[face];
// Use plane fitting metric for now:
- return 1 - dot(faceNormal, chart->basis.normal); // @@ normal deviations should be weighted by face area
+ return min(1.0f - dot(faceNormal, chart->basis.normal), 1.0f); // @@ normal deviations should be weighted by face area
}
- float evaluateRoundnessMetric(Chart *chart, float newBoundaryLength, float newChartArea) const {
- const float roundness = square(chart->boundaryLength) / chart->area;
- const float newBoundaryLengthSq = square(newBoundaryLength);
- const float newRoundness = newBoundaryLengthSq / newChartArea;
- if (newRoundness > roundness)
- return newBoundaryLengthSq / (newChartArea * kPi4);
- // Offer no impedance to faces that improve roundness.
- return 0;
+ float computeRoundnessMetric(Chart *chart, float newBoundaryLength, float newChartArea) const
+ {
+ const float oldRoundness = square(chart->boundaryLength) / chart->area;
+ const float newRoundness = square(newBoundaryLength) / newChartArea;
+ return 1.0f - oldRoundness / newRoundness;
}
- float evaluateStraightnessMetric(Chart *chart, uint32_t firstFace) const {
- float l_out = 0.0f, l_in = 0.0f;
- const uint32_t planarRegionId = m_facePlanarRegionId[firstFace];
+ float computeStraightnessMetric(Chart *chart, uint32_t firstFace) const
+ {
+ float l_out = 0.0f; // Length of firstFace planar region boundary that doesn't border the chart.
+ float l_in = 0.0f; // Length that does border the chart.
+ const uint32_t planarRegionId = m_planarCharts.regionIdFromFace(firstFace);
uint32_t face = firstFace;
- for (;;) {
- for (Mesh::FaceEdgeIterator it(m_mesh, face); !it.isDone(); it.advance()) {
- const float l = m_edgeLengths[it.edge()];
+ for (;;) {
+ for (Mesh::FaceEdgeIterator it(m_data.mesh, face); !it.isDone(); it.advance()) {
+ const float l = m_data.edgeLengths[it.edge()];
if (it.isBoundary()) {
l_out += l;
- } else if (m_facePlanarRegionId[it.oppositeFace()] != planarRegionId) {
+ } else if (m_planarCharts.regionIdFromFace(it.oppositeFace()) != planarRegionId) {
if (m_faceCharts[it.oppositeFace()] != chart->id)
l_out += l;
else
l_in += l;
}
}
- face = m_nextPlanarRegionFace[face];
+ face = m_planarCharts.nextRegionFace(face);
if (face == firstFace)
break;
}
+#if 1
XA_DEBUG_ASSERT(l_in != 0.0f); // Candidate face must be adjacent to chart. @@ This is not true if the input mesh has zero-length edges.
float ratio = (l_out - l_in) / (l_out + l_in);
return min(ratio, 0.0f); // Only use the straightness metric to close gaps.
+#else
+ return 1.0f - l_in / l_out;
+#endif
}
- bool isNormalSeam(uint32_t edge) const {
- const uint32_t oppositeEdge = m_mesh->oppositeEdge(edge);
+ bool isNormalSeam(uint32_t edge) const
+ {
+ const uint32_t oppositeEdge = m_data.mesh->oppositeEdge(edge);
if (oppositeEdge == UINT32_MAX)
return false; // boundary edge
- if (m_mesh->flags() & MeshFlags::HasNormals) {
- const uint32_t v0 = m_mesh->vertexAt(meshEdgeIndex0(edge));
- const uint32_t v1 = m_mesh->vertexAt(meshEdgeIndex1(edge));
- const uint32_t ov0 = m_mesh->vertexAt(meshEdgeIndex0(oppositeEdge));
- const uint32_t ov1 = m_mesh->vertexAt(meshEdgeIndex1(oppositeEdge));
+ if (m_data.mesh->flags() & MeshFlags::HasNormals) {
+ const uint32_t v0 = m_data.mesh->vertexAt(meshEdgeIndex0(edge));
+ const uint32_t v1 = m_data.mesh->vertexAt(meshEdgeIndex1(edge));
+ const uint32_t ov0 = m_data.mesh->vertexAt(meshEdgeIndex0(oppositeEdge));
+ const uint32_t ov1 = m_data.mesh->vertexAt(meshEdgeIndex1(oppositeEdge));
if (v0 == ov1 && v1 == ov0)
return false;
- return !equal(m_mesh->normal(v0), m_mesh->normal(ov1), kNormalEpsilon) || !equal(m_mesh->normal(v1), m_mesh->normal(ov0), kNormalEpsilon);
+ return !equal(m_data.mesh->normal(v0), m_data.mesh->normal(ov1), kNormalEpsilon) || !equal(m_data.mesh->normal(v1), m_data.mesh->normal(ov0), kNormalEpsilon);
}
const uint32_t f0 = meshEdgeFace(edge);
const uint32_t f1 = meshEdgeFace(oppositeEdge);
- if (m_facePlanarRegionId[f0] == m_facePlanarRegionId[f1])
+ if (m_planarCharts.regionIdFromFace(f0) == m_planarCharts.regionIdFromFace(f1))
return false;
- return !equal(m_faceNormals[f0], m_faceNormals[f1], kNormalEpsilon);
+ return !equal(m_data.faceNormals[f0], m_data.faceNormals[f1], kNormalEpsilon);
}
- float evaluateNormalSeamMetric(Chart *chart, uint32_t firstFace) const {
+ float computeNormalSeamMetric(Chart *chart, uint32_t firstFace) const
+ {
float seamFactor = 0.0f, totalLength = 0.0f;
uint32_t face = firstFace;
- for (;;) {
- for (Mesh::FaceEdgeIterator it(m_mesh, face); !it.isDone(); it.advance()) {
+ for (;;) {
+ for (Mesh::FaceEdgeIterator it(m_data.mesh, face); !it.isDone(); it.advance()) {
if (it.isBoundary())
continue;
if (m_faceCharts[it.oppositeFace()] != chart->id)
continue;
- float l = m_edgeLengths[it.edge()];
+ float l = m_data.edgeLengths[it.edge()];
totalLength += l;
if (!it.isSeam())
continue;
// Make sure it's a normal seam.
if (isNormalSeam(it.edge())) {
float d;
- if (m_mesh->flags() & MeshFlags::HasNormals) {
- const Vector3 &n0 = m_mesh->normal(it.vertex0());
- const Vector3 &n1 = m_mesh->normal(it.vertex1());
- const Vector3 &on0 = m_mesh->normal(m_mesh->vertexAt(meshEdgeIndex0(it.oppositeEdge())));
- const Vector3 &on1 = m_mesh->normal(m_mesh->vertexAt(meshEdgeIndex1(it.oppositeEdge())));
+ if (m_data.mesh->flags() & MeshFlags::HasNormals) {
+ const Vector3 &n0 = m_data.mesh->normal(it.vertex0());
+ const Vector3 &n1 = m_data.mesh->normal(it.vertex1());
+ const Vector3 &on0 = m_data.mesh->normal(m_data.mesh->vertexAt(meshEdgeIndex0(it.oppositeEdge())));
+ const Vector3 &on1 = m_data.mesh->normal(m_data.mesh->vertexAt(meshEdgeIndex1(it.oppositeEdge())));
const float d0 = clamp(dot(n0, on1), 0.0f, 1.0f);
const float d1 = clamp(dot(n1, on0), 0.0f, 1.0f);
d = (d0 + d1) * 0.5f;
} else {
- d = clamp(dot(m_faceNormals[face], m_faceNormals[meshEdgeFace(it.oppositeEdge())]), 0.0f, 1.0f);
+ d = clamp(dot(m_data.faceNormals[face], m_data.faceNormals[meshEdgeFace(it.oppositeEdge())]), 0.0f, 1.0f);
}
l *= 1 - d;
seamFactor += l;
}
}
- face = m_nextPlanarRegionFace[face];
+ face = m_planarCharts.nextRegionFace(face);
if (face == firstFace)
break;
}
@@ -5278,16 +6375,17 @@ private:
return seamFactor / totalLength;
}
- float evaluateTextureSeamMetric(Chart *chart, uint32_t firstFace) const {
+ float computeTextureSeamMetric(Chart *chart, uint32_t firstFace) const
+ {
float seamLength = 0.0f, totalLength = 0.0f;
uint32_t face = firstFace;
- for (;;) {
- for (Mesh::FaceEdgeIterator it(m_mesh, face); !it.isDone(); it.advance()) {
+ for (;;) {
+ for (Mesh::FaceEdgeIterator it(m_data.mesh, face); !it.isDone(); it.advance()) {
if (it.isBoundary())
continue;
if (m_faceCharts[it.oppositeFace()] != chart->id)
continue;
- float l = m_edgeLengths[it.edge()];
+ float l = m_data.edgeLengths[it.edge()];
totalLength += l;
if (!it.isSeam())
continue;
@@ -5295,7 +6393,7 @@ private:
if (it.isTextureSeam())
seamLength += l;
}
- face = m_nextPlanarRegionFace[face];
+ face = m_planarCharts.nextRegionFace(face);
if (face == firstFace)
break;
}
@@ -5304,43 +6402,46 @@ private:
return seamLength / totalLength;
}
- float computeArea(Chart *chart, uint32_t firstFace) const {
+ float computeArea(Chart *chart, uint32_t firstFace) const
+ {
float area = chart->area;
uint32_t face = firstFace;
- for (;;) {
- area += m_faceAreas[face];
- face = m_nextPlanarRegionFace[face];
+ for (;;) {
+ area += m_data.faceAreas[face];
+ face = m_planarCharts.nextRegionFace(face);
if (face == firstFace)
break;
}
return area;
}
- float computeBoundaryLength(Chart *chart, uint32_t firstFace) const {
+ float computeBoundaryLength(Chart *chart, uint32_t firstFace) const
+ {
float boundaryLength = chart->boundaryLength;
// Add new edges, subtract edges shared with the chart.
- const uint32_t planarRegionId = m_facePlanarRegionId[firstFace];
+ const uint32_t planarRegionId = m_planarCharts.regionIdFromFace(firstFace);
uint32_t face = firstFace;
- for (;;) {
- for (Mesh::FaceEdgeIterator it(m_mesh, face); !it.isDone(); it.advance()) {
- const float edgeLength = m_edgeLengths[it.edge()];
+ for (;;) {
+ for (Mesh::FaceEdgeIterator it(m_data.mesh, face); !it.isDone(); it.advance()) {
+ const float edgeLength = m_data.edgeLengths[it.edge()];
if (it.isBoundary()) {
boundaryLength += edgeLength;
- } else if (m_facePlanarRegionId[it.oppositeFace()] != planarRegionId) {
+ } else if (m_planarCharts.regionIdFromFace(it.oppositeFace()) != planarRegionId) {
if (m_faceCharts[it.oppositeFace()] != chart->id)
boundaryLength += edgeLength;
else
boundaryLength -= edgeLength;
}
}
- face = m_nextPlanarRegionFace[face];
+ face = m_planarCharts.nextRegionFace(face);
if (face == firstFace)
break;
}
- return max(0.0f, boundaryLength); // @@ Hack!
+ return max(0.0f, boundaryLength); // @@ Hack!
}
- bool mergeChart(Chart *owner, Chart *chart, float sharedBoundaryLength) {
+ bool mergeChart(Chart *owner, Chart *chart, float sharedBoundaryLength)
+ {
const uint32_t oldOwnerFaceCount = owner->faces.size();
const uint32_t chartFaceCount = chart->faces.size();
owner->faces.push_back(chart->faces);
@@ -5356,7 +6457,7 @@ private:
m_faceCharts[chart->faces[i]] = chart->id;
return false;
}
- if (dot(basis.normal, m_faceNormals[owner->faces[0]]) < 0.0f) // Flip normal if oriented in the wrong direction.
+ if (dot(basis.normal, m_data.faceNormals[owner->faces[0]]) < 0.0f) // Flip normal if oriented in the wrong direction.
basis.normal = -basis.normal;
// Compute orthogonal parameterization and check that it is valid.
parameterizeChart(owner);
@@ -5379,19 +6480,14 @@ private:
return true;
}
- const Mesh *m_mesh;
- Array<float> m_edgeLengths;
- Array<float> m_faceAreas;
- Array<Vector3> m_faceNormals;
+private:
+ AtlasData &m_data;
+ const PlanarCharts &m_planarCharts;
Array<Vector2> m_texcoords;
uint32_t m_facesLeft;
Array<int> m_faceCharts;
Array<Chart *> m_charts;
CostQueue m_bestTriangles;
- KISSRng m_rand;
- ChartOptions m_options;
- Array<uint32_t> m_nextPlanarRegionFace;
- Array<uint32_t> m_facePlanarRegionId;
Array<Vector3> m_tempPoints;
UniformGrid2 m_boundaryGrid;
#if XA_MERGE_CHARTS
@@ -5400,226 +6496,66 @@ private:
Array<float> m_sharedBoundaryLengthsNoSeams;
Array<uint32_t> m_sharedBoundaryEdgeCountNoSeams;
#endif
+ bool m_placingSeeds;
};
-} // namespace segment
-
-namespace param {
+struct Atlas
+{
+ Atlas() : m_planarCharts(m_data), m_clusteredCharts(m_data, m_planarCharts) {}
-class JacobiPreconditioner {
-public:
- JacobiPreconditioner(const sparse::Matrix &M, bool symmetric) :
- m_inverseDiagonal(M.width()) {
- XA_ASSERT(M.isSquare());
- for (uint32_t x = 0; x < M.width(); x++) {
- float elem = M.getCoefficient(x, x);
- //XA_DEBUG_ASSERT( elem != 0.0f ); // This can be zero in the presence of zero area triangles.
- if (symmetric) {
- m_inverseDiagonal[x] = (elem != 0) ? 1.0f / sqrtf(fabsf(elem)) : 1.0f;
- } else {
- m_inverseDiagonal[x] = (elem != 0) ? 1.0f / elem : 1.0f;
- }
- }
+ uint32_t chartCount() const
+ {
+ return m_planarCharts.chartCount() + m_clusteredCharts.chartCount();
}
- void apply(const FullVector &x, FullVector &y) const {
- XA_DEBUG_ASSERT(x.dimension() == m_inverseDiagonal.dimension());
- XA_DEBUG_ASSERT(y.dimension() == m_inverseDiagonal.dimension());
- // @@ Wrap vector component-wise product into a separate function.
- const uint32_t D = x.dimension();
- for (uint32_t i = 0; i < D; i++) {
- y[i] = m_inverseDiagonal[i] * x[i];
- }
+ ConstArrayView<uint32_t> chartFaces(uint32_t chartIndex) const
+ {
+ if (chartIndex < m_planarCharts.chartCount())
+ return m_planarCharts.chartFaces(chartIndex);
+ chartIndex -= m_planarCharts.chartCount();
+ return m_clusteredCharts.chartFaces(chartIndex);
}
-private:
- FullVector m_inverseDiagonal;
-};
-
-// Linear solvers.
-class Solver {
-public:
- // Solve the symmetric system: At·A·x = At·b
- static bool LeastSquaresSolver(const sparse::Matrix &A, const FullVector &b, FullVector &x, float epsilon = 1e-5f) {
- XA_DEBUG_ASSERT(A.width() == x.dimension());
- XA_DEBUG_ASSERT(A.height() == b.dimension());
- XA_DEBUG_ASSERT(A.height() >= A.width()); // @@ If height == width we could solve it directly...
- const uint32_t D = A.width();
- sparse::Matrix At(A.height(), A.width());
- sparse::transpose(A, At);
- FullVector Atb(D);
- sparse::mult(At, b, Atb);
- sparse::Matrix AtA(D);
- sparse::mult(At, A, AtA);
- return SymmetricSolver(AtA, Atb, x, epsilon);
- }
-
- // See section 10.4.3 in: Mesh Parameterization: Theory and Practice, Siggraph Course Notes, August 2007
- static bool LeastSquaresSolver(const sparse::Matrix &A, const FullVector &b, FullVector &x, const uint32_t *lockedParameters, uint32_t lockedCount, float epsilon = 1e-5f) {
- XA_DEBUG_ASSERT(A.width() == x.dimension());
- XA_DEBUG_ASSERT(A.height() == b.dimension());
- XA_DEBUG_ASSERT(A.height() >= A.width() - lockedCount);
- // @@ This is not the most efficient way of building a system with reduced degrees of freedom. It would be faster to do it on the fly.
- const uint32_t D = A.width() - lockedCount;
- XA_DEBUG_ASSERT(D > 0);
- // Compute: b - Al * xl
- FullVector b_Alxl(b);
- for (uint32_t y = 0; y < A.height(); y++) {
- const uint32_t count = A.getRow(y).size();
- for (uint32_t e = 0; e < count; e++) {
- uint32_t column = A.getRow(y)[e].x;
- bool isFree = true;
- for (uint32_t i = 0; i < lockedCount; i++) {
- isFree &= (lockedParameters[i] != column);
- }
- if (!isFree) {
- b_Alxl[y] -= x[column] * A.getRow(y)[e].v;
- }
- }
- }
- // Remove locked columns from A.
- sparse::Matrix Af(D, A.height());
- for (uint32_t y = 0; y < A.height(); y++) {
- const uint32_t count = A.getRow(y).size();
- for (uint32_t e = 0; e < count; e++) {
- uint32_t column = A.getRow(y)[e].x;
- uint32_t ix = column;
- bool isFree = true;
- for (uint32_t i = 0; i < lockedCount; i++) {
- isFree &= (lockedParameters[i] != column);
- if (column > lockedParameters[i]) ix--; // shift columns
- }
- if (isFree) {
- Af.setCoefficient(ix, y, A.getRow(y)[e].v);
- }
- }
- }
- // Remove elements from x
- FullVector xf(D);
- for (uint32_t i = 0, j = 0; i < A.width(); i++) {
- bool isFree = true;
- for (uint32_t l = 0; l < lockedCount; l++) {
- isFree &= (lockedParameters[l] != i);
- }
- if (isFree) {
- xf[j++] = x[i];
- }
- }
- // Solve reduced system.
- bool result = LeastSquaresSolver(Af, b_Alxl, xf, epsilon);
- // Copy results back to x.
- for (uint32_t i = 0, j = 0; i < A.width(); i++) {
- bool isFree = true;
- for (uint32_t l = 0; l < lockedCount; l++) {
- isFree &= (lockedParameters[l] != i);
- }
- if (isFree) {
- x[i] = xf[j++];
- }
- }
- return result;
+ const Basis &chartBasis(uint32_t chartIndex) const
+ {
+ if (chartIndex < m_planarCharts.chartCount())
+ return m_planarCharts.chartBasis(chartIndex);
+ chartIndex -= m_planarCharts.chartCount();
+ return m_clusteredCharts.chartBasis(chartIndex);
}
-private:
- /**
- * Compute the solution of the sparse linear system Ab=x using the Conjugate
- * Gradient method.
- *
- * Solving sparse linear systems:
- * (1) A·x = b
- *
- * The conjugate gradient algorithm solves (1) only in the case that A is
- * symmetric and positive definite. It is based on the idea of minimizing the
- * function
- *
- * (2) f(x) = 1/2·x·A·x - b·x
- *
- * This function is minimized when its gradient
- *
- * (3) df = A·x - b
- *
- * is zero, which is equivalent to (1). The minimization is carried out by
- * generating a succession of search directions p.k and improved minimizers x.k.
- * At each stage a quantity alfa.k is found that minimizes f(x.k + alfa.k·p.k),
- * and x.k+1 is set equal to the new point x.k + alfa.k·p.k. The p.k and x.k are
- * built up in such a way that x.k+1 is also the minimizer of f over the whole
- * vector space of directions already taken, {p.1, p.2, . . . , p.k}. After N
- * iterations you arrive at the minimizer over the entire vector space, i.e., the
- * solution to (1).
- *
- * For a really good explanation of the method see:
- *
- * "An Introduction to the Conjugate Gradient Method Without the Agonizing Pain",
- * Jonhathan Richard Shewchuk.
- *
- **/
- // Conjugate gradient with preconditioner.
- static bool ConjugateGradientSolver(const JacobiPreconditioner &preconditioner, const sparse::Matrix &A, const FullVector &b, FullVector &x, float epsilon) {
- XA_DEBUG_ASSERT(A.isSquare());
- XA_DEBUG_ASSERT(A.width() == b.dimension());
- XA_DEBUG_ASSERT(A.width() == x.dimension());
- int i = 0;
- const int D = A.width();
- const int i_max = 4 * D; // Convergence should be linear, but in some cases, it's not.
- FullVector r(D); // residual
- FullVector p(D); // search direction
- FullVector q(D); //
- FullVector s(D); // preconditioned
- float delta_0;
- float delta_old;
- float delta_new;
- float alpha;
- float beta;
- // r = b - A·x
- sparse::copy(b, r);
- sparse::sgemv(-1, A, x, 1, r);
- // p = M^-1 · r
- preconditioner.apply(r, p);
- delta_new = sparse::dot(r, p);
- delta_0 = delta_new;
- while (i < i_max && delta_new > epsilon * epsilon * delta_0) {
- i++;
- // q = A·p
- sparse::mult(A, p, q);
- // alpha = delta_new / p·q
- const float pdotq = sparse::dot(p, q);
- if (!isFinite(pdotq) || isNan(pdotq))
- alpha = 0.0f;
- else
- alpha = delta_new / pdotq;
- // x = alfa·p + x
- sparse::saxpy(alpha, p, x);
- if ((i & 31) == 0) { // recompute r after 32 steps
- // r = b - A·x
- sparse::copy(b, r);
- sparse::sgemv(-1, A, x, 1, r);
- } else {
- // r = r - alfa·q
- sparse::saxpy(-alpha, q, r);
- }
- // s = M^-1 · r
- preconditioner.apply(r, s);
- delta_old = delta_new;
- delta_new = sparse::dot(r, s);
- beta = delta_new / delta_old;
- // p = s + beta·p
- sparse::scal(beta, p);
- sparse::saxpy(1, s, p);
- }
- return delta_new <= epsilon * epsilon * delta_0;
+ void reset(const Mesh *mesh, const ChartOptions &options)
+ {
+ XA_PROFILE_START(buildAtlasInit)
+ m_data.options = options;
+ m_data.mesh = mesh;
+ m_data.compute();
+ XA_PROFILE_END(buildAtlasInit)
}
- static bool SymmetricSolver(const sparse::Matrix &A, const FullVector &b, FullVector &x, float epsilon = 1e-5f) {
- XA_DEBUG_ASSERT(A.height() == A.width());
- XA_DEBUG_ASSERT(A.height() == b.dimension());
- XA_DEBUG_ASSERT(b.dimension() == x.dimension());
- JacobiPreconditioner jacobi(A, true);
- return ConjugateGradientSolver(jacobi, A, b, x, epsilon);
+ void compute()
+ {
+ XA_PROFILE_START(planarCharts)
+ m_planarCharts.compute();
+ XA_PROFILE_END(planarCharts)
+ XA_PROFILE_START(clusteredCharts)
+ m_clusteredCharts.compute();
+ XA_PROFILE_END(clusteredCharts)
}
+
+private:
+ AtlasData m_data;
+ PlanarCharts m_planarCharts;
+ ClusteredCharts m_clusteredCharts;
};
+} // namespace segment
+
+namespace param {
+
// Fast sweep in 3 directions
-static bool findApproximateDiameterVertices(Mesh *mesh, uint32_t *a, uint32_t *b) {
+static bool findApproximateDiameterVertices(Mesh *mesh, uint32_t *a, uint32_t *b)
+{
XA_DEBUG_ASSERT(a != nullptr);
XA_DEBUG_ASSERT(b != nullptr);
const uint32_t vertexCount = mesh->vertexCount();
@@ -5674,165 +6610,136 @@ static bool findApproximateDiameterVertices(Mesh *mesh, uint32_t *a, uint32_t *b
return true;
}
-// Conformal relations from Brecht Van Lommel (based on ABF):
-
-static float vec_angle_cos(const Vector3 &v1, const Vector3 &v2, const Vector3 &v3) {
- Vector3 d1 = v1 - v2;
- Vector3 d2 = v3 - v2;
- return clamp(dot(d1, d2) / (length(d1) * length(d2)), -1.0f, 1.0f);
-}
-
-static float vec_angle(const Vector3 &v1, const Vector3 &v2, const Vector3 &v3) {
- float dot = vec_angle_cos(v1, v2, v3);
- return acosf(dot);
-}
-
-static void triangle_angles(const Vector3 &v1, const Vector3 &v2, const Vector3 &v3, float *a1, float *a2, float *a3) {
- *a1 = vec_angle(v3, v1, v2);
- *a2 = vec_angle(v1, v2, v3);
- *a3 = kPi - *a2 - *a1;
-}
-
-static void setup_abf_relations(sparse::Matrix &A, int row, int id0, int id1, int id2, const Vector3 &p0, const Vector3 &p1, const Vector3 &p2) {
- // @@ IC: Wouldn't it be more accurate to return cos and compute 1-cos^2?
- // It does indeed seem to be a little bit more robust.
- // @@ Need to revisit this more carefully!
- float a0, a1, a2;
- triangle_angles(p0, p1, p2, &a0, &a1, &a2);
- float s0 = sinf(a0);
- float s1 = sinf(a1);
- float s2 = sinf(a2);
- if (s1 > s0 && s1 > s2) {
- swap(s1, s2);
- swap(s0, s1);
- swap(a1, a2);
- swap(a0, a1);
- swap(id1, id2);
- swap(id0, id1);
- } else if (s0 > s1 && s0 > s2) {
- swap(s0, s2);
- swap(s0, s1);
- swap(a0, a2);
- swap(a0, a1);
- swap(id0, id2);
- swap(id0, id1);
- }
- float c0 = cosf(a0);
- float ratio = (s2 == 0.0f) ? 1.0f : s1 / s2;
- float cosine = c0 * ratio;
- float sine = s0 * ratio;
- // Note : 2*id + 0 --> u
- // 2*id + 1 --> v
- int u0_id = 2 * id0 + 0;
- int v0_id = 2 * id0 + 1;
- int u1_id = 2 * id1 + 0;
- int v1_id = 2 * id1 + 1;
- int u2_id = 2 * id2 + 0;
- int v2_id = 2 * id2 + 1;
- // Real part
- A.setCoefficient(u0_id, 2 * row + 0, cosine - 1.0f);
- A.setCoefficient(v0_id, 2 * row + 0, -sine);
- A.setCoefficient(u1_id, 2 * row + 0, -cosine);
- A.setCoefficient(v1_id, 2 * row + 0, sine);
- A.setCoefficient(u2_id, 2 * row + 0, 1);
- // Imaginary part
- A.setCoefficient(u0_id, 2 * row + 1, sine);
- A.setCoefficient(v0_id, 2 * row + 1, cosine - 1.0f);
- A.setCoefficient(u1_id, 2 * row + 1, -sine);
- A.setCoefficient(v1_id, 2 * row + 1, -cosine);
- A.setCoefficient(v2_id, 2 * row + 1, 1);
-}
-
-static bool computeLeastSquaresConformalMap(Mesh *mesh) {
- // For this to work properly, mesh should not have colocals that have the same
- // attributes, unless you want the vertices to actually have different texcoords.
- const uint32_t vertexCount = mesh->vertexCount();
- const uint32_t D = 2 * vertexCount;
- const uint32_t N = 2 * mesh->faceCount();
- // N is the number of equations (one per triangle)
- // D is the number of variables (one per vertex; there are 2 pinned vertices).
- if (N < D - 4) {
- return false;
- }
- sparse::Matrix A(D, N);
- FullVector b(N);
- FullVector x(D);
- // Fill b:
- b.fill(0.0f);
- // Fill x:
- uint32_t v0, v1;
- if (!findApproximateDiameterVertices(mesh, &v0, &v1)) {
+// From OpenNL LSCM example.
+// Computes the coordinates of the vertices of a triangle in a local 2D orthonormal basis of the triangle's plane.
+static void projectTriangle(Vector3 p0, Vector3 p1, Vector3 p2, Vector2 *z0, Vector2 *z1, Vector2 *z2, float epsilon)
+{
+ Vector3 X = normalize(p1 - p0, epsilon);
+ Vector3 Z = normalize(cross(X, p2 - p0), epsilon);
+ Vector3 Y = cross(Z, X);
+ Vector3 &O = p0;
+ *z0 = Vector2(0, 0);
+ *z1 = Vector2(length(p1 - O), 0);
+ *z2 = Vector2(dot(p2 - O, X), dot(p2 - O, Y));
+}
+
+static bool computeLeastSquaresConformalMap(Mesh *mesh)
+{
+ uint32_t lockedVertex0, lockedVertex1;
+ if (!findApproximateDiameterVertices(mesh, &lockedVertex0, &lockedVertex1)) {
// Mesh has no boundaries.
return false;
}
- if (mesh->texcoord(v0) == mesh->texcoord(v1)) {
- // LSCM expects an existing parameterization.
+ const uint32_t vertexCount = mesh->vertexCount();
+ opennl::NLContext *context = opennl::nlNewContext();
+ opennl::nlSolverParameteri(context, NL_NB_VARIABLES, int(2 * vertexCount));
+ opennl::nlSolverParameteri(context, NL_MAX_ITERATIONS, int(5 * vertexCount));
+ opennl::nlBegin(context, NL_SYSTEM);
+ const Vector2 *texcoords = mesh->texcoords();
+ for (uint32_t i = 0; i < vertexCount; i++) {
+ opennl::nlSetVariable(context, 2 * i, texcoords[i].x);
+ opennl::nlSetVariable(context, 2 * i + 1, texcoords[i].y);
+ if (i == lockedVertex0 || i == lockedVertex1) {
+ opennl::nlLockVariable(context, 2 * i);
+ opennl::nlLockVariable(context, 2 * i + 1);
+ }
+ }
+ opennl::nlBegin(context, NL_MATRIX);
+ const uint32_t faceCount = mesh->faceCount();
+ const Vector3 *positions = mesh->positions();
+ const uint32_t *indices = mesh->indices();
+ for (uint32_t f = 0; f < faceCount; f++) {
+ const uint32_t v0 = indices[f * 3 + 0];
+ const uint32_t v1 = indices[f * 3 + 1];
+ const uint32_t v2 = indices[f * 3 + 2];
+ Vector2 z0, z1, z2;
+ projectTriangle(positions[v0], positions[v1], positions[v2], &z0, &z1, &z2, mesh->epsilon());
+ double a = z1.x - z0.x;
+ double b = z1.y - z0.y;
+ double c = z2.x - z0.x;
+ double d = z2.y - z0.y;
+ XA_DEBUG_ASSERT(b == 0.0);
+ // Note : 2*id + 0 --> u
+ // 2*id + 1 --> v
+ uint32_t u0_id = 2 * v0;
+ uint32_t v0_id = 2 * v0 + 1;
+ uint32_t u1_id = 2 * v1;
+ uint32_t v1_id = 2 * v1 + 1;
+ uint32_t u2_id = 2 * v2;
+ uint32_t v2_id = 2 * v2 + 1;
+ // Note : b = 0
+ // Real part
+ opennl::nlBegin(context, NL_ROW);
+ opennl::nlCoefficient(context, u0_id, -a+c) ;
+ opennl::nlCoefficient(context, v0_id, b-d) ;
+ opennl::nlCoefficient(context, u1_id, -c) ;
+ opennl::nlCoefficient(context, v1_id, d) ;
+ opennl::nlCoefficient(context, u2_id, a);
+ opennl::nlEnd(context, NL_ROW);
+ // Imaginary part
+ opennl::nlBegin(context, NL_ROW);
+ opennl::nlCoefficient(context, u0_id, -b+d);
+ opennl::nlCoefficient(context, v0_id, -a+c);
+ opennl::nlCoefficient(context, u1_id, -d);
+ opennl::nlCoefficient(context, v1_id, -c);
+ opennl::nlCoefficient(context, v2_id, a);
+ opennl::nlEnd(context, NL_ROW);
+ }
+ opennl::nlEnd(context, NL_MATRIX);
+ opennl::nlEnd(context, NL_SYSTEM);
+ if (!opennl::nlSolve(context)) {
+ opennl::nlDeleteContext(context);
return false;
}
- for (uint32_t v = 0; v < vertexCount; v++) {
- // Initial solution.
- x[2 * v + 0] = mesh->texcoord(v).x;
- x[2 * v + 1] = mesh->texcoord(v).y;
- }
- // Fill A:
- const uint32_t faceCount = mesh->faceCount();
- for (uint32_t f = 0, t = 0; f < faceCount; f++) {
- const uint32_t vertex0 = mesh->vertexAt(f * 3 + 0);
- const uint32_t vertex1 = mesh->vertexAt(f * 3 + 1);
- const uint32_t vertex2 = mesh->vertexAt(f * 3 + 2);
- setup_abf_relations(A, t, vertex0, vertex1, vertex2, mesh->position(vertex0), mesh->position(vertex1), mesh->position(vertex2));
- t++;
- }
- const uint32_t lockedParameters[] = {
- 2 * v0 + 0,
- 2 * v0 + 1,
- 2 * v1 + 0,
- 2 * v1 + 1
- };
- // Solve
- Solver::LeastSquaresSolver(A, b, x, lockedParameters, 4, 0.000001f);
- // Map x back to texcoords:
- for (uint32_t v = 0; v < vertexCount; v++) {
- mesh->texcoord(v) = Vector2(x[2 * v + 0], x[2 * v + 1]);
- XA_DEBUG_ASSERT(!isNan(mesh->texcoord(v).x));
- XA_DEBUG_ASSERT(!isNan(mesh->texcoord(v).y));
+ for (uint32_t i = 0; i < vertexCount; i++) {
+ const double u = opennl::nlGetVariable(context, 2 * i);
+ const double v = opennl::nlGetVariable(context, 2 * i + 1);
+ mesh->texcoord(i) = Vector2((float)u, (float)v);
+ XA_DEBUG_ASSERT(!isNan(mesh->texcoord(i).x));
+ XA_DEBUG_ASSERT(!isNan(mesh->texcoord(i).y));
}
+ opennl::nlDeleteContext(context);
return true;
}
#if XA_RECOMPUTE_CHARTS
-struct PiecewiseParam {
- void reset(const Mesh *mesh, uint32_t faceCount) {
+struct PiecewiseParam
+{
+ void reset(const Mesh *mesh, uint32_t faceCount)
+ {
m_mesh = mesh;
m_faceCount = faceCount;
const uint32_t vertexCount = m_mesh->vertexCount();
m_texcoords.resize(vertexCount);
m_patch.reserve(m_faceCount);
- m_faceAssigned.resize(m_faceCount);
- m_faceAssigned.zeroOutMemory();
+ m_candidates.reserve(m_faceCount);
+ m_faceInAnyPatch.resize(m_faceCount);
+ m_faceInAnyPatch.zeroOutMemory();
m_faceInvalid.resize(m_faceCount);
m_faceInPatch.resize(m_faceCount);
m_vertexInPatch.resize(vertexCount);
- m_faceInCandidates.resize(m_faceCount);
+ m_faceToCandidate.resize(m_faceCount);
}
ConstArrayView<uint32_t> chartFaces() const { return m_patch; }
const Vector2 *texcoords() const { return m_texcoords.data(); }
- bool computeChart() {
+ bool computeChart()
+ {
+ // Clear per-patch state.
m_patch.clear();
+ m_candidates.clear();
+ m_faceToCandidate.zeroOutMemory();
m_faceInvalid.zeroOutMemory();
m_faceInPatch.zeroOutMemory();
m_vertexInPatch.zeroOutMemory();
// Add the seed face (first unassigned face) to the patch.
uint32_t seed = UINT32_MAX;
for (uint32_t f = 0; f < m_faceCount; f++) {
- if (m_faceAssigned.get(f))
+ if (m_faceInAnyPatch.get(f))
continue;
seed = f;
- m_patch.push_back(seed);
- m_faceInPatch.set(seed);
- m_faceAssigned.set(seed);
+ // Add all 3 vertices.
Vector2 texcoords[3];
orthoProjectFace(seed, texcoords);
for (uint32_t i = 0; i < 3; i++) {
@@ -5840,95 +6747,104 @@ struct PiecewiseParam {
m_vertexInPatch.set(vertex);
m_texcoords[vertex] = texcoords[i];
}
+ addFaceToPatch(seed);
+ // Initialize the boundary grid.
+ m_boundaryGrid.reset(m_texcoords.data(), m_mesh->indices());
+ for (Mesh::FaceEdgeIterator it(m_mesh, seed); !it.isDone(); it.advance())
+ m_boundaryGrid.append(it.edge());
break;
}
if (seed == UINT32_MAX)
return false;
for (;;) {
- findCandidates();
- if (m_candidates.isEmpty())
- break;
- for (;;) {
- // Find the candidate with the lowest cost.
- float lowestCost = FLT_MAX;
- uint32_t bestCandidate = UINT32_MAX;
- for (uint32_t i = 0; i < m_candidates.size(); i++) {
- const Candidate &candidate = m_candidates[i];
- if (m_faceInvalid.get(candidate.face)) // A candidate face may be invalidated after is was added.
- continue;
- if (candidate.maxCost < lowestCost) {
- lowestCost = candidate.maxCost;
- bestCandidate = i;
- }
+ // Find the candidate with the lowest cost.
+ float lowestCost = FLT_MAX;
+ Candidate *bestCandidate = nullptr;
+ for (uint32_t i = 0; i < m_candidates.size(); i++) {
+ Candidate *candidate = m_candidates[i];
+ if (candidate->maxCost < lowestCost) {
+ lowestCost = candidate->maxCost;
+ bestCandidate = candidate;
}
- if (bestCandidate == UINT32_MAX)
+ }
+ if (!bestCandidate)
+ break;
+ XA_DEBUG_ASSERT(!bestCandidate->prev); // Must be head of linked candidates.
+ // Compute the position by averaging linked candidates (candidates that share the same free vertex).
+ Vector2 position(0.0f);
+ uint32_t n = 0;
+ for (CandidateIterator it(bestCandidate); !it.isDone(); it.advance()) {
+ position += it.current()->position;
+ n++;
+ }
+ position *= 1.0f / (float)n;
+ const uint32_t freeVertex = bestCandidate->vertex;
+ XA_DEBUG_ASSERT(!isNan(position.x));
+ XA_DEBUG_ASSERT(!isNan(position.y));
+ m_texcoords[freeVertex] = position;
+ // Check for flipped faces. This is also done when candidates are first added, but the averaged position of the free vertex is different now, so check again.
+ bool invalid = false;
+ for (CandidateIterator it(bestCandidate); !it.isDone(); it.advance()) {
+ const uint32_t vertex0 = m_mesh->vertexAt(meshEdgeIndex0(it.current()->patchEdge));
+ const uint32_t vertex1 = m_mesh->vertexAt(meshEdgeIndex1(it.current()->patchEdge));
+ const float freeVertexOrient = orientToEdge(m_texcoords[vertex0], m_texcoords[vertex1], position);
+ if ((it.current()->patchVertexOrient < 0.0f && freeVertexOrient < 0.0f) || (it.current()->patchVertexOrient > 0.0f && freeVertexOrient > 0.0f)) {
+ invalid = true;
break;
- // Compute the position by averaging linked candidates (candidates that share the same free vertex).
- Vector2 position(0.0f);
- uint32_t n = 0;
- for (CandidateIterator it(m_candidates, bestCandidate); !it.isDone(); it.advance()) {
- position += it.current().position;
- n++;
}
- position *= 1.0f / (float)n;
- const uint32_t freeVertex = m_candidates[bestCandidate].vertex;
- XA_DEBUG_ASSERT(!isNan(position.x));
- XA_DEBUG_ASSERT(!isNan(position.y));
- m_texcoords[freeVertex] = position;
- // Check for flipped faces. This is also done when candidates are first added, but the averaged position of the free vertex is different now, so check again.
- bool invalid = false;
- for (CandidateIterator it(m_candidates, bestCandidate); !it.isDone(); it.advance()) {
- const uint32_t vertex0 = m_mesh->vertexAt(meshEdgeIndex0(it.current().patchEdge));
- const uint32_t vertex1 = m_mesh->vertexAt(meshEdgeIndex1(it.current().patchEdge));
- const float freeVertexOrient = orientToEdge(m_texcoords[vertex0], m_texcoords[vertex1], position);
- if ((it.current().patchVertexOrient < 0.0f && freeVertexOrient < 0.0f) || (it.current().patchVertexOrient > 0.0f && freeVertexOrient > 0.0f)) {
- invalid = true;
- break;
- }
- }
- // Check for boundary intersection.
- if (!invalid) {
- m_boundaryGrid.reset(m_texcoords.data(), m_mesh->indices());
- // Add edges on the patch boundary to the grid.
- // Temporarily adding candidate faces to the patch makes it simpler to detect which edges are on the boundary.
- const uint32_t oldPatchSize = m_patch.size();
- for (CandidateIterator it(m_candidates, bestCandidate); !it.isDone(); it.advance())
- m_patch.push_back(it.current().face);
- for (uint32_t i = 0; i < m_patch.size(); i++) {
- for (Mesh::FaceEdgeIterator it(m_mesh, m_patch[i]); !it.isDone(); it.advance()) {
- const uint32_t oface = it.oppositeFace();
- if (oface == UINT32_MAX || oface >= m_faceCount || !m_faceInPatch.get(oface))
- m_boundaryGrid.append(it.edge());
- }
+ }
+ // Check for boundary intersection.
+ if (!invalid) {
+ XA_PROFILE_START(parameterizeChartsPiecewiseBoundaryIntersection)
+ // Test candidate edges that would form part of the new patch boundary.
+ // Ignore boundary edges that would become internal if the candidate faces were added to the patch.
+ Array<uint32_t> newBoundaryEdges, ignoreEdges;
+ for (CandidateIterator candidateIt(bestCandidate); !candidateIt.isDone(); candidateIt.advance()) {
+ for (Mesh::FaceEdgeIterator it(m_mesh, candidateIt.current()->face); !it.isDone(); it.advance()) {
+ const uint32_t oface = it.oppositeFace();
+ if (oface == UINT32_MAX || oface >= m_faceCount || !m_faceInPatch.get(oface))
+ newBoundaryEdges.push_back(it.edge());
+ if (oface != UINT32_MAX && oface < m_faceCount && m_faceInPatch.get(oface))
+ ignoreEdges.push_back(it.oppositeEdge());
}
- invalid = m_boundaryGrid.intersectSelf(m_mesh->epsilon());
- m_patch.resize(oldPatchSize);
- }
- if (invalid) {
- // Mark all faces of linked candidates as invalid.
- for (CandidateIterator it(m_candidates, bestCandidate); !it.isDone(); it.advance())
- m_faceInvalid.set(it.current().face);
- continue;
- }
- // Add faces to the patch.
- for (CandidateIterator it(m_candidates, bestCandidate); !it.isDone(); it.advance()) {
- m_patch.push_back(it.current().face);
- m_faceInPatch.set(it.current().face);
- m_faceAssigned.set(it.current().face);
}
+ invalid = m_boundaryGrid.intersect(m_mesh->epsilon(), newBoundaryEdges, ignoreEdges);
+ XA_PROFILE_END(parameterizeChartsPiecewiseBoundaryIntersection)
+ }
+ if (invalid) {
+ // Mark all faces of linked candidates as invalid.
+ for (CandidateIterator it(bestCandidate); !it.isDone(); it.advance())
+ m_faceInvalid.set(it.current()->face);
+ removeLinkedCandidates(bestCandidate);
+ } else {
// Add vertex to the patch.
m_vertexInPatch.set(freeVertex);
+ // Add faces to the patch.
+ for (CandidateIterator it(bestCandidate); !it.isDone(); it.advance())
+ addFaceToPatch(it.current()->face);
// Successfully added candidate face(s) to patch.
- break;
+ removeLinkedCandidates(bestCandidate);
+ // Reset the grid with all edges on the patch boundary.
+ XA_PROFILE_START(parameterizeChartsPiecewiseBoundaryIntersection)
+ m_boundaryGrid.reset(m_texcoords.data(), m_mesh->indices());
+ for (uint32_t i = 0; i < m_patch.size(); i++) {
+ for (Mesh::FaceEdgeIterator it(m_mesh, m_patch[i]); !it.isDone(); it.advance()) {
+ const uint32_t oface = it.oppositeFace();
+ if (oface == UINT32_MAX || oface >= m_faceCount || !m_faceInPatch.get(oface))
+ m_boundaryGrid.append(it.edge());
+ }
+ }
+ XA_PROFILE_END(parameterizeChartsPiecewiseBoundaryIntersection)
}
}
return true;
}
private:
- struct Candidate {
+ struct Candidate
+ {
uint32_t face, vertex;
- uint32_t next; // The next candidate with the same vertex.
+ Candidate *prev, *next; // The previous/next candidate with the same vertex.
Vector2 position;
float cost;
float maxCost; // Of all linked candidates.
@@ -5936,90 +6852,70 @@ private:
float patchVertexOrient;
};
- struct CandidateIterator {
- CandidateIterator(Array<Candidate> &candidates, uint32_t first) :
- m_candidates(candidates), m_current(first) {}
- void advance() {
- if (m_current != UINT32_MAX) m_current = m_candidates[m_current].next;
- }
- bool isDone() const { return m_current == UINT32_MAX; }
- Candidate &current() { return m_candidates[m_current]; }
+ struct CandidateIterator
+ {
+ CandidateIterator(Candidate *head) : m_current(head) { XA_DEBUG_ASSERT(!head->prev); }
+ void advance() { if (m_current != nullptr) { m_current = m_current->next; } }
+ bool isDone() const { return !m_current; }
+ Candidate *current() { return m_current; }
private:
- Array<Candidate> &m_candidates;
- uint32_t m_current;
+ Candidate *m_current;
};
const Mesh *m_mesh;
uint32_t m_faceCount;
Array<Vector2> m_texcoords;
- Array<Candidate> m_candidates;
- BitArray m_faceInCandidates;
- Array<uint32_t> m_patch;
- BitArray m_faceAssigned; // Face is assigned to a previous chart or the current patch.
- BitArray m_faceInPatch, m_vertexInPatch;
+ BitArray m_faceInAnyPatch; // Face is in a previous chart patch or the current patch.
+ Array<Candidate *> m_candidates; // Incident faces to the patch.
+ Array<Candidate *> m_faceToCandidate;
+ Array<uint32_t> m_patch; // The current chart patch.
+ BitArray m_faceInPatch, m_vertexInPatch; // Face/vertex is in the current patch.
BitArray m_faceInvalid; // Face cannot be added to the patch - flipped, cost too high or causes boundary intersection.
UniformGrid2 m_boundaryGrid;
- // Find candidate faces on the patch front.
- void findCandidates() {
- m_candidates.clear();
- m_faceInCandidates.zeroOutMemory();
- for (uint32_t i = 0; i < m_patch.size(); i++) {
- for (Mesh::FaceEdgeIterator it(m_mesh, m_patch[i]); !it.isDone(); it.advance()) {
- const uint32_t oface = it.oppositeFace();
- if (oface == UINT32_MAX || oface >= m_faceCount || m_faceAssigned.get(oface) || m_faceInCandidates.get(oface))
- continue;
- // Found an active edge on the patch front.
- // Find the free vertex (the vertex that isn't on the active edge).
- // Compute the orientation of the other patch face vertex to the active edge.
- uint32_t freeVertex = UINT32_MAX;
- float orient = 0.0f;
- for (uint32_t j = 0; j < 3; j++) {
- const uint32_t vertex = m_mesh->vertexAt(oface * 3 + j);
- if (vertex != it.vertex0() && vertex != it.vertex1()) {
- freeVertex = vertex;
- orient = orientToEdge(m_texcoords[it.vertex0()], m_texcoords[it.vertex1()], m_texcoords[m_mesh->vertexAt(m_patch[i] * 3 + j)]);
- break;
- }
- }
- XA_DEBUG_ASSERT(freeVertex != UINT32_MAX);
- // If the free vertex is already in the patch, the face is enclosed by the patch. Add the face to the patch - don't need to assign texcoords.
- if (m_vertexInPatch.get(freeVertex)) {
- freeVertex = UINT32_MAX;
- m_patch.push_back(oface);
- m_faceAssigned.set(oface);
- continue;
- }
- // Check this here rather than above so faces enclosed by the patch are always added.
- if (m_faceInvalid.get(oface))
- continue;
- addCandidateFace(it.edge(), orient, oface, it.oppositeEdge(), freeVertex);
- }
- }
- // Link candidates that share the same vertex.
- for (uint32_t i = 0; i < m_candidates.size(); i++) {
- if (m_candidates[i].next != UINT32_MAX)
+ void addFaceToPatch(uint32_t face)
+ {
+ XA_DEBUG_ASSERT(!m_faceInPatch.get(face));
+ XA_DEBUG_ASSERT(!m_faceInAnyPatch.get(face));
+ m_patch.push_back(face);
+ m_faceInPatch.set(face);
+ m_faceInAnyPatch.set(face);
+ // Find new candidate faces on the patch incident to the newly added face.
+ for (Mesh::FaceEdgeIterator it(m_mesh, face); !it.isDone(); it.advance()) {
+ const uint32_t oface = it.oppositeFace();
+ if (oface == UINT32_MAX || oface >= m_faceCount || m_faceInAnyPatch.get(oface) || m_faceToCandidate[oface])
continue;
- uint32_t current = i;
- for (uint32_t j = i + 1; j < m_candidates.size(); j++) {
- if (m_candidates[j].vertex == m_candidates[current].vertex) {
- m_candidates[current].next = j;
- current = j;
+ // Found an active edge on the patch front.
+ // Find the free vertex (the vertex that isn't on the active edge).
+ // Compute the orientation of the other patch face vertex to the active edge.
+ uint32_t freeVertex = UINT32_MAX;
+ float orient = 0.0f;
+ for (uint32_t j = 0; j < 3; j++) {
+ const uint32_t vertex = m_mesh->vertexAt(oface * 3 + j);
+ if (vertex != it.vertex0() && vertex != it.vertex1()) {
+ freeVertex = vertex;
+ orient = orientToEdge(m_texcoords[it.vertex0()], m_texcoords[it.vertex1()], m_texcoords[m_mesh->vertexAt(face * 3 + j)]);
+ break;
}
}
- }
- // Set max cost for linked candidates.
- for (uint32_t i = 0; i < m_candidates.size(); i++) {
- float maxCost = 0.0f;
- for (CandidateIterator it(m_candidates, i); !it.isDone(); it.advance())
- maxCost = max(maxCost, it.current().cost);
- for (CandidateIterator it(m_candidates, i); !it.isDone(); it.advance())
- it.current().maxCost = maxCost;
+ XA_DEBUG_ASSERT(freeVertex != UINT32_MAX);
+ // If the free vertex is already in the patch, the face is enclosed by the patch. Add the face to the patch - don't need to assign texcoords.
+ /*if (m_vertexInPatch.get(freeVertex)) {
+ freeVertex = UINT32_MAX;
+ addFaceToPatch(oface, false);
+ continue;
+ }*/
+ // Check this here rather than above so faces enclosed by the patch are always added.
+ if (m_faceInvalid.get(oface))
+ continue;
+ addCandidateFace(it.edge(), orient, oface, it.oppositeEdge(), freeVertex);
}
}
- void addCandidateFace(uint32_t patchEdge, float patchVertexOrient, uint32_t face, uint32_t edge, uint32_t freeVertex) {
+ void addCandidateFace(uint32_t patchEdge, float patchVertexOrient, uint32_t face, uint32_t edge, uint32_t freeVertex)
+ {
+ XA_DEBUG_ASSERT(!m_faceToCandidate[face]);
Vector2 texcoords[3];
orthoProjectFace(face, texcoords);
// Find corresponding vertices between the patch edge and candidate edge.
@@ -6040,8 +6936,9 @@ private:
const Vector2 localEdgeVec = texcoords[localVertex1] - texcoords[localVertex0];
const float len1 = length(patchEdgeVec);
const float len2 = length(localEdgeVec);
+ if (len1 <= 0.0f || len2 <= 0.0f)
+ return; // Zero length edge.
const float scale = len1 / len2;
- XA_ASSERT(scale > 0.0f);
for (uint32_t i = 0; i < 3; i++)
texcoords[i] *= scale;
// Translate to the first vertex on the patch edge.
@@ -6063,6 +6960,8 @@ private:
uv.x = x + texcoords[localVertex0].x;
uv.y = y + texcoords[localVertex0].y;
}
+ if (isNan(texcoords[localFreeVertex].x) || isNan(texcoords[localFreeVertex].y))
+ return;
// Check for local overlap (flipped triangle).
// The patch face vertex that isn't on the active edge and the free vertex should be oriented on opposite sides to the active edge.
const float freeVertexOrient = orientToEdge(m_texcoords[vertex0], m_texcoords[vertex1], texcoords[localFreeVertex]);
@@ -6083,19 +6982,72 @@ private:
}
#endif
// Add the candidate.
- Candidate candidate;
- candidate.face = face;
- candidate.vertex = freeVertex;
- candidate.position = texcoords[localFreeVertex];
- candidate.next = UINT32_MAX;
- candidate.cost = cost;
- candidate.patchEdge = patchEdge;
- candidate.patchVertexOrient = patchVertexOrient;
+ Candidate *candidate = XA_ALLOC(MemTag::Default, Candidate);
+ candidate->face = face;
+ candidate->vertex = freeVertex;
+ candidate->position = texcoords[localFreeVertex];
+ candidate->prev = candidate->next = nullptr;
+ candidate->cost = candidate->maxCost = cost;
+ candidate->patchEdge = patchEdge;
+ candidate->patchVertexOrient = patchVertexOrient;
m_candidates.push_back(candidate);
- m_faceInCandidates.set(face);
+ m_faceToCandidate[face] = candidate;
+ // Link with candidates that share the same vertex. Append to tail.
+ for (uint32_t i = 0; i < m_candidates.size() - 1; i++) {
+ if (m_candidates[i]->vertex == candidate->vertex) {
+ Candidate *tail = m_candidates[i];
+ for (;;) {
+ if (tail->next)
+ tail = tail->next;
+ else
+ break;
+ }
+ candidate->prev = tail;
+ candidate->next = nullptr;
+ tail->next = candidate;
+ break;
+ }
+ }
+ // Set max cost for linked candidates.
+ Candidate *head = linkedCandidateHead(candidate);
+ float maxCost = 0.0f;
+ for (CandidateIterator it(head); !it.isDone(); it.advance())
+ maxCost = max(maxCost, it.current()->cost);
+ for (CandidateIterator it(head); !it.isDone(); it.advance())
+ it.current()->maxCost = maxCost;
+ }
+
+ Candidate *linkedCandidateHead(Candidate *candidate)
+ {
+ Candidate *current = candidate;
+ for (;;) {
+ if (!current->prev)
+ break;
+ current = current->prev;
+ }
+ return current;
}
- void orthoProjectFace(uint32_t face, Vector2 *texcoords) const {
+ void removeLinkedCandidates(Candidate *head)
+ {
+ XA_DEBUG_ASSERT(!head->prev);
+ Candidate *current = head;
+ while (current) {
+ Candidate *next = current->next;
+ m_faceToCandidate[current->face] = nullptr;
+ for (uint32_t i = 0; i < m_candidates.size(); i++) {
+ if (m_candidates[i] == current) {
+ m_candidates.removeAt(i);
+ break;
+ }
+ }
+ XA_FREE(current);
+ current = next;
+ }
+ }
+
+ void orthoProjectFace(uint32_t face, Vector2 *texcoords) const
+ {
const Vector3 normal = m_mesh->computeFaceNormal(face);
const Vector3 tangent = normalize(m_mesh->position(m_mesh->vertexAt(face * 3 + 1)) - m_mesh->position(m_mesh->vertexAt(face * 3 + 0)), kEpsilon);
const Vector3 bitangent = cross(normal, tangent);
@@ -6105,14 +7057,16 @@ private:
}
}
- float parametricArea(const Vector2 *texcoords) const {
+ float parametricArea(const Vector2 *texcoords) const
+ {
const Vector2 &v1 = texcoords[0];
const Vector2 &v2 = texcoords[1];
const Vector2 &v3 = texcoords[2];
return ((v2.x - v1.x) * (v3.y - v1.y) - (v3.x - v1.x) * (v2.y - v1.y)) * 0.5f;
}
- float computeStretch(Vector3 p1, Vector3 p2, Vector3 p3, Vector2 t1, Vector2 t2, Vector2 t3) const {
+ float computeStretch(Vector3 p1, Vector3 p2, Vector3 p3, Vector2 t1, Vector2 t2, Vector2 t3) const
+ {
float parametricArea = ((t2.y - t1.y) * (t3.x - t1.x) - (t3.y - t1.y) * (t2.x - t1.x)) * 0.5f;
if (isZero(parametricArea, kAreaEpsilon))
return FLT_MAX;
@@ -6126,14 +7080,16 @@ private:
}
// Return value is positive if the point is one side of the edge, negative if on the other side.
- float orientToEdge(Vector2 edgeVertex0, Vector2 edgeVertex1, Vector2 point) const {
+ float orientToEdge(Vector2 edgeVertex0, Vector2 edgeVertex1, Vector2 point) const
+ {
return (edgeVertex0.x - point.x) * (edgeVertex1.y - point.y) - (edgeVertex0.y - point.y) * (edgeVertex1.x - point.x);
}
};
#endif
// Estimate quality of existing parameterization.
-struct Quality {
+struct Quality
+{
// computeBoundaryIntersection
bool boundaryIntersection = false;
@@ -6150,13 +7106,14 @@ struct Quality {
float conformalMetric = 0.0f;
float authalicMetric = 0.0f;
- void computeBoundaryIntersection(const Mesh *mesh, UniformGrid2 &boundaryGrid) {
+ void computeBoundaryIntersection(const Mesh *mesh, UniformGrid2 &boundaryGrid)
+ {
const Array<uint32_t> &boundaryEdges = mesh->boundaryEdges();
const uint32_t boundaryEdgeCount = boundaryEdges.size();
boundaryGrid.reset(mesh->texcoords(), mesh->indices(), boundaryEdgeCount);
for (uint32_t i = 0; i < boundaryEdgeCount; i++)
boundaryGrid.append(boundaryEdges[i]);
- boundaryIntersection = boundaryGrid.intersectSelf(mesh->epsilon());
+ boundaryIntersection = boundaryGrid.intersect(mesh->epsilon());
#if XA_DEBUG_EXPORT_BOUNDARY_GRID
static int exportIndex = 0;
char filename[256];
@@ -6166,7 +7123,8 @@ struct Quality {
#endif
}
- void computeFlippedFaces(const Mesh *mesh, uint32_t faceCount, Array<uint32_t> *flippedFaces) {
+ void computeFlippedFaces(const Mesh *mesh, uint32_t faceCount, Array<uint32_t> *flippedFaces)
+ {
totalTriangleCount = flippedTriangleCount = zeroAreaTriangleCount = 0;
if (flippedFaces)
flippedFaces->clear();
@@ -6201,7 +7159,8 @@ struct Quality {
flippedFaces->clear();
flippedTriangleCount = 0;
}
- if (flippedTriangleCount > totalTriangleCount / 2) {
+ if (flippedTriangleCount > totalTriangleCount / 2)
+ {
// If more than half the triangles are flipped, reverse the flipped / not flipped classification.
flippedTriangleCount = totalTriangleCount - flippedTriangleCount;
if (flippedFaces) {
@@ -6223,7 +7182,8 @@ struct Quality {
}
}
- void computeMetrics(const Mesh *mesh, uint32_t faceCount) {
+ void computeMetrics(const Mesh *mesh, uint32_t faceCount)
+ {
totalGeometricArea = totalParametricArea = 0.0f;
stretchMetric = maxStretchMetric = conformalMetric = authalicMetric = 0.0f;
for (uint32_t f = 0; f < faceCount; f++) {
@@ -6254,7 +7214,7 @@ struct Quality {
const float a = dot(Ss, Ss); // E
const float b = dot(Ss, St); // F
const float c = dot(St, St); // G
- // Compute eigen-values of the first fundamental form:
+ // Compute eigen-values of the first fundamental form:
const float sigma1 = sqrtf(0.5f * max(0.0f, a + c - sqrtf(square(a - c) + 4 * square(b)))); // gamma uppercase, min eigenvalue.
const float sigma2 = sqrtf(0.5f * max(0.0f, a + c + sqrtf(square(a - c) + 4 * square(b)))); // gamma lowercase, max eigenvalue.
XA_ASSERT(sigma2 > sigma1 || equal(sigma1, sigma2, kEpsilon));
@@ -6285,62 +7245,59 @@ struct Quality {
if (totalGeometricArea > 0.0f) {
const float normFactor = sqrtf(totalParametricArea / totalGeometricArea);
stretchMetric = sqrtf(stretchMetric / totalGeometricArea) * normFactor;
- maxStretchMetric *= normFactor;
+ maxStretchMetric *= normFactor;
conformalMetric = sqrtf(conformalMetric / totalGeometricArea);
authalicMetric = sqrtf(authalicMetric / totalGeometricArea);
}
}
};
-struct ChartWarningFlags {
- enum Enum {
- CloseHolesFailed = 1 << 1,
- FixTJunctionsDuplicatedEdge = 1 << 2,
- FixTJunctionsFailed = 1 << 3,
- TriangulateDuplicatedEdge = 1 << 4,
+struct ChartWarningFlags
+{
+ enum Enum
+ {
+ CloseHolesFailed = 1<<1,
+ FixTJunctionsDuplicatedEdge = 1<<2,
+ FixTJunctionsFailed = 1<<3,
+ TriangulateDuplicatedEdge = 1<<4,
};
};
-struct ChartCtorBuffers {
+struct ChartCtorBuffers
+{
Array<uint32_t> chartMeshIndices;
Array<uint32_t> unifiedMeshIndices;
Array<uint32_t> boundaryLoops;
};
-/// A chart is a connected set of faces with a certain topology (usually a disk).
-class Chart {
+class Chart
+{
public:
- Chart(ChartCtorBuffers &buffers, const Basis &basis, ConstArrayView<uint32_t> faces, const Mesh *originalMesh, uint32_t meshId, uint32_t chartGroupId, uint32_t chartId) :
- m_basis(basis), m_mesh(nullptr), m_unifiedMesh(nullptr), m_unmodifiedUnifiedMesh(nullptr), m_type(ChartType::LSCM), m_warningFlags(0), m_closedHolesCount(0), m_fixedTJunctionsCount(0) {
- XA_UNUSED(meshId);
+ Chart(ChartCtorBuffers &buffers, const ParameterizeOptions &options, const Basis &basis, ConstArrayView<uint32_t> faces, const Mesh *sourceMesh, uint32_t chartGroupId, uint32_t chartId) : m_basis(basis), m_mesh(nullptr), m_unifiedMesh(nullptr), m_unmodifiedUnifiedMesh(nullptr), m_type(ChartType::LSCM), m_warningFlags(0), m_closedHolesCount(0), m_fixedTJunctionsCount(0), m_isInvalid(false)
+ {
XA_UNUSED(chartGroupId);
XA_UNUSED(chartId);
- m_faceArray.copyFrom(faces.data, faces.length);
- // Copy face indices.
- m_mesh = XA_NEW_ARGS(MemTag::Mesh, Mesh, originalMesh->epsilon(), m_faceArray.size() * 3, m_faceArray.size());
- m_unifiedMesh = XA_NEW_ARGS(MemTag::Mesh, Mesh, originalMesh->epsilon(), m_faceArray.size() * 3, m_faceArray.size());
- Array<uint32_t> &chartMeshIndices = buffers.chartMeshIndices;
- chartMeshIndices.resize(originalMesh->vertexCount());
- chartMeshIndices.setAll(UINT32_MAX);
- Array<uint32_t> &unifiedMeshIndices = buffers.unifiedMeshIndices;
- unifiedMeshIndices.resize(originalMesh->vertexCount());
- unifiedMeshIndices.setAll(UINT32_MAX);
+ m_faceToSourceFaceMap.copyFrom(faces.data, faces.length);
+ const uint32_t approxVertexCount = min(faces.length * 3, sourceMesh->vertexCount());
+ m_mesh = XA_NEW_ARGS(MemTag::Mesh, Mesh, sourceMesh->epsilon(), approxVertexCount, faces.length);
+ m_unifiedMesh = XA_NEW_ARGS(MemTag::Mesh, Mesh, sourceMesh->epsilon(), approxVertexCount, faces.length);
+ HashMap<uint32_t, PassthroughHash<uint32_t>> sourceVertexToUnifiedVertexMap(MemTag::Mesh, approxVertexCount), sourceVertexToChartVertexMap(MemTag::Mesh, approxVertexCount);
// Add vertices.
- const uint32_t faceCount = m_initialFaceCount = m_faceArray.size();
+ const uint32_t faceCount = m_initialFaceCount = faces.length;
for (uint32_t f = 0; f < faceCount; f++) {
for (uint32_t i = 0; i < 3; i++) {
- const uint32_t vertex = originalMesh->vertexAt(m_faceArray[f] * 3 + i);
- const uint32_t unifiedVertex = originalMesh->firstColocal(vertex);
- if (unifiedMeshIndices[unifiedVertex] == (uint32_t)~0) {
- unifiedMeshIndices[unifiedVertex] = m_unifiedMesh->vertexCount();
- XA_DEBUG_ASSERT(equal(originalMesh->position(vertex), originalMesh->position(unifiedVertex), originalMesh->epsilon()));
- m_unifiedMesh->addVertex(originalMesh->position(vertex));
+ const uint32_t sourceVertex = sourceMesh->vertexAt(m_faceToSourceFaceMap[f] * 3 + i);
+ const uint32_t sourceUnifiedVertex = sourceMesh->firstColocal(sourceVertex);
+ uint32_t unifiedVertex = sourceVertexToUnifiedVertexMap.get(sourceUnifiedVertex);
+ if (unifiedVertex == UINT32_MAX) {
+ unifiedVertex = sourceVertexToUnifiedVertexMap.add(sourceUnifiedVertex);
+ m_unifiedMesh->addVertex(sourceMesh->position(sourceVertex));
}
- if (chartMeshIndices[vertex] == (uint32_t)~0) {
- chartMeshIndices[vertex] = m_mesh->vertexCount();
- m_chartToOriginalMap.push_back(vertex);
- m_chartToUnifiedMap.push_back(unifiedMeshIndices[unifiedVertex]);
- m_mesh->addVertex(originalMesh->position(vertex), Vector3(0.0f), originalMesh->texcoord(vertex));
+ if (sourceVertexToChartVertexMap.get(sourceVertex) == UINT32_MAX) {
+ sourceVertexToChartVertexMap.add(sourceVertex);
+ m_vertexToSourceVertexMap.push_back(sourceVertex);
+ m_chartVertexToUnifiedVertexMap.push_back(unifiedVertex);
+ m_mesh->addVertex(sourceMesh->position(sourceVertex), Vector3(0.0f), sourceMesh->texcoord(sourceVertex));
}
}
}
@@ -6348,9 +7305,12 @@ public:
for (uint32_t f = 0; f < faceCount; f++) {
uint32_t indices[3], unifiedIndices[3];
for (uint32_t i = 0; i < 3; i++) {
- const uint32_t vertex = originalMesh->vertexAt(m_faceArray[f] * 3 + i);
- indices[i] = chartMeshIndices[vertex];
- unifiedIndices[i] = unifiedMeshIndices[originalMesh->firstColocal(vertex)];
+ const uint32_t sourceVertex = sourceMesh->vertexAt(m_faceToSourceFaceMap[f] * 3 + i);
+ const uint32_t sourceUnifiedVertex = sourceMesh->firstColocal(sourceVertex);
+ indices[i] = sourceVertexToChartVertexMap.get(sourceVertex);
+ XA_DEBUG_ASSERT(indices[i] != UINT32_MAX);
+ unifiedIndices[i] = sourceVertexToUnifiedVertexMap.get(sourceUnifiedVertex);
+ XA_DEBUG_ASSERT(unifiedIndices[i] != UINT32_MAX);
}
Mesh::AddFaceResult::Enum result = m_mesh->addFace(indices);
XA_UNUSED(result);
@@ -6368,15 +7328,18 @@ public:
XA_DEBUG_ASSERT(result == Mesh::AddFaceResult::OK);
}
m_mesh->createBoundaries(); // For AtlasPacker::computeBoundingBox
+ m_mesh->destroyEdgeMap(); // Only needed it for createBoundaries.
m_unifiedMesh->createBoundaries();
- if (meshIsPlanar(*m_unifiedMesh))
+ if (meshIsPlanar(*m_unifiedMesh)) {
m_type = ChartType::Planar;
- else {
- m_unifiedMesh->linkBoundaries();
+ return;
+ }
+ m_unifiedMesh->linkBoundaries();
#if XA_DEBUG_EXPORT_OBJ_BEFORE_FIX_TJUNCTION
- m_unifiedMesh->writeObjFile("debug_before_fix_tjunction.obj");
+ m_unifiedMesh->writeObjFile("debug_before_fix_tjunction.obj");
#endif
- bool duplicatedEdge = false, failed = false;
+ bool duplicatedEdge = false, failed = false;
+ if (options.fixTJunctions) {
XA_PROFILE_START(fixChartMeshTJunctions)
Mesh *fixedUnifiedMesh = meshFixTJunctions(*m_unifiedMesh, &duplicatedEdge, &failed, &m_fixedTJunctionsCount);
XA_PROFILE_END(fixChartMeshTJunctions)
@@ -6391,6 +7354,8 @@ public:
m_unifiedMesh->linkBoundaries();
m_initialFaceCount = m_unifiedMesh->faceCount(); // Fixing t-junctions rewrites faces.
}
+ }
+ if (options.closeHoles) {
// See if there are any holes that need closing.
Array<uint32_t> &boundaryLoops = buffers.boundaryLoops;
meshGetBoundaryLoops(*m_unifiedMesh, boundaryLoops);
@@ -6421,7 +7386,7 @@ public:
#if XA_DEBUG_EXPORT_OBJ_CLOSE_HOLES_ERROR
if (m_warningFlags & ChartWarningFlags::CloseHolesFailed) {
char filename[256];
- XA_SPRINTF(filename, sizeof(filename), "debug_mesh_%03u_chartgroup_%03u_chart_%03u_close_holes_error.obj", meshId, chartGroupId, chartId);
+ XA_SPRINTF(filename, sizeof(filename), "debug_mesh_%03u_chartgroup_%03u_chart_%03u_close_holes_error.obj", sourceMesh->id(), chartGroupId, chartId);
FILE *file;
XA_FOPEN(file, filename, "w");
if (file) {
@@ -6450,88 +7415,57 @@ public:
}
#if XA_RECOMPUTE_CHARTS
- Chart(ChartCtorBuffers &buffers, const Chart *parent, const Mesh *parentMesh, ConstArrayView<uint32_t> faces, const Vector2 *texcoords, const Mesh *originalMesh, uint32_t meshId, uint32_t chartGroupId, uint32_t chartId) :
- m_mesh(nullptr), m_unifiedMesh(nullptr), m_unmodifiedUnifiedMesh(nullptr), m_type(ChartType::Piecewise), m_warningFlags(0), m_closedHolesCount(0), m_fixedTJunctionsCount(0) {
- XA_UNUSED(meshId);
- XA_UNUSED(chartGroupId);
- XA_UNUSED(chartId);
+ Chart(ChartCtorBuffers &buffers, const Chart *parent, const Mesh *parentMesh, ConstArrayView<uint32_t> faces, const Vector2 *texcoords, const Mesh *sourceMesh) : m_mesh(nullptr), m_unifiedMesh(nullptr), m_unmodifiedUnifiedMesh(nullptr), m_type(ChartType::Piecewise), m_warningFlags(0), m_closedHolesCount(0), m_fixedTJunctionsCount(0), m_isInvalid(false)
+ {
const uint32_t faceCount = m_initialFaceCount = faces.length;
- m_faceArray.resize(faceCount);
+ m_faceToSourceFaceMap.resize(faceCount);
for (uint32_t i = 0; i < faceCount; i++)
- m_faceArray[i] = parent->m_faceArray[faces[i]]; // Map faces to parent chart original mesh.
+ m_faceToSourceFaceMap[i] = parent->m_faceToSourceFaceMap[faces[i]]; // Map faces to parent chart source mesh.
// Copy face indices.
- m_mesh = XA_NEW_ARGS(MemTag::Mesh, Mesh, originalMesh->epsilon(), m_faceArray.size() * 3, m_faceArray.size());
- m_unifiedMesh = XA_NEW_ARGS(MemTag::Mesh, Mesh, originalMesh->epsilon(), m_faceArray.size() * 3, m_faceArray.size());
+ m_mesh = XA_NEW_ARGS(MemTag::Mesh, Mesh, sourceMesh->epsilon(), m_faceToSourceFaceMap.size() * 3, m_faceToSourceFaceMap.size());
Array<uint32_t> &chartMeshIndices = buffers.chartMeshIndices;
- chartMeshIndices.resize(originalMesh->vertexCount());
- chartMeshIndices.setAll(UINT32_MAX);
- Array<uint32_t> &unifiedMeshIndices = buffers.unifiedMeshIndices;
- unifiedMeshIndices.resize(originalMesh->vertexCount());
- unifiedMeshIndices.setAll(UINT32_MAX);
+ chartMeshIndices.resize(sourceMesh->vertexCount());
+ chartMeshIndices.fillBytes(0xff);
// Add vertices.
for (uint32_t f = 0; f < faceCount; f++) {
for (uint32_t i = 0; i < 3; i++) {
- const uint32_t vertex = originalMesh->vertexAt(m_faceArray[f] * 3 + i);
- const uint32_t unifiedVertex = originalMesh->firstColocal(vertex);
+ const uint32_t vertex = sourceMesh->vertexAt(m_faceToSourceFaceMap[f] * 3 + i);
const uint32_t parentVertex = parentMesh->vertexAt(faces[f] * 3 + i);
- if (unifiedMeshIndices[unifiedVertex] == (uint32_t)~0) {
- unifiedMeshIndices[unifiedVertex] = m_unifiedMesh->vertexCount();
- XA_DEBUG_ASSERT(equal(originalMesh->position(vertex), originalMesh->position(unifiedVertex), originalMesh->epsilon()));
- m_unifiedMesh->addVertex(originalMesh->position(vertex), Vector3(0.0f), texcoords[parentVertex]);
- }
if (chartMeshIndices[vertex] == (uint32_t)~0) {
chartMeshIndices[vertex] = m_mesh->vertexCount();
- m_chartToOriginalMap.push_back(vertex);
- m_chartToUnifiedMap.push_back(unifiedMeshIndices[unifiedVertex]);
- m_mesh->addVertex(originalMesh->position(vertex), Vector3(0.0f), texcoords[parentVertex]);
+ m_vertexToSourceVertexMap.push_back(vertex);
+ m_mesh->addVertex(sourceMesh->position(vertex), Vector3(0.0f), texcoords[parentVertex]);
}
}
}
// Add faces.
for (uint32_t f = 0; f < faceCount; f++) {
- uint32_t indices[3], unifiedIndices[3];
+ uint32_t indices[3];
for (uint32_t i = 0; i < 3; i++) {
- const uint32_t vertex = originalMesh->vertexAt(m_faceArray[f] * 3 + i);
+ const uint32_t vertex = sourceMesh->vertexAt(m_faceToSourceFaceMap[f] * 3 + i);
indices[i] = chartMeshIndices[vertex];
- unifiedIndices[i] = unifiedMeshIndices[originalMesh->firstColocal(vertex)];
}
Mesh::AddFaceResult::Enum result = m_mesh->addFace(indices);
XA_UNUSED(result);
XA_DEBUG_ASSERT(result == Mesh::AddFaceResult::OK);
-#if XA_DEBUG
- // Unifying colocals may create degenerate edges. e.g. if two triangle vertices are colocal.
- for (int i = 0; i < 3; i++) {
- const uint32_t index1 = unifiedIndices[i];
- const uint32_t index2 = unifiedIndices[(i + 1) % 3];
- XA_DEBUG_ASSERT(index1 != index2);
- }
-#endif
- result = m_unifiedMesh->addFace(unifiedIndices);
- XA_UNUSED(result);
- XA_DEBUG_ASSERT(result == Mesh::AddFaceResult::OK);
}
m_mesh->createBoundaries(); // For AtlasPacker::computeBoundingBox
- m_unifiedMesh->createBoundaries();
- m_unifiedMesh->linkBoundaries();
+ m_mesh->destroyEdgeMap(); // Only needed it for createBoundaries.
+ // Need to store texcoords for backup/restore so packing can be run multiple times.
+ backupTexcoords();
}
#endif
- ~Chart() {
+ ~Chart()
+ {
if (m_mesh) {
m_mesh->~Mesh();
XA_FREE(m_mesh);
}
- if (m_unifiedMesh) {
- m_unifiedMesh->~Mesh();
- XA_FREE(m_unifiedMesh);
- }
- if (m_unmodifiedUnifiedMesh) {
- m_unmodifiedUnifiedMesh->~Mesh();
- XA_FREE(m_unmodifiedUnifiedMesh);
- }
+ destroyUnifiedMesh();
}
- const Basis &basis() const { return m_basis; }
+ bool isInvalid() const { return m_isInvalid; }
ChartType::Enum type() const { return m_type; }
uint32_t warningFlags() const { return m_warningFlags; }
uint32_t closedHolesCount() const { return m_closedHolesCount; }
@@ -6541,45 +7475,71 @@ public:
#if XA_DEBUG_EXPORT_OBJ_INVALID_PARAMETERIZATION
const Array<uint32_t> &paramFlippedFaces() const { return m_paramFlippedFaces; }
#endif
- uint32_t mapFaceToSourceFace(uint32_t i) const { return m_faceArray[i]; }
+ uint32_t mapFaceToSourceFace(uint32_t i) const { return m_faceToSourceFaceMap[i]; }
+ uint32_t mapChartVertexToSourceVertex(uint32_t i) const { return m_vertexToSourceVertexMap[i]; }
const Mesh *mesh() const { return m_mesh; }
Mesh *mesh() { return m_mesh; }
const Mesh *unifiedMesh() const { return m_unifiedMesh; }
- Mesh *unifiedMesh() { return m_unifiedMesh; }
const Mesh *unmodifiedUnifiedMesh() const { return m_unmodifiedUnifiedMesh; }
- uint32_t mapChartVertexToOriginalVertex(uint32_t i) const { return m_chartToOriginalMap[i]; }
-
- void evaluateOrthoQuality(UniformGrid2 &boundaryGrid) {
- XA_PROFILE_START(parameterizeChartsEvaluateQuality)
- m_quality.computeBoundaryIntersection(m_unifiedMesh, boundaryGrid);
- m_quality.computeFlippedFaces(m_unifiedMesh, m_initialFaceCount, nullptr);
- m_quality.computeMetrics(m_unifiedMesh, m_initialFaceCount);
- XA_PROFILE_END(parameterizeChartsEvaluateQuality)
- // Use orthogonal parameterization if quality is acceptable.
- if (!m_quality.boundaryIntersection && m_quality.totalGeometricArea > 0.0f && m_quality.stretchMetric <= 1.1f && m_quality.maxStretchMetric <= 1.25f)
- m_type = ChartType::Ortho;
- }
-
- void evaluateQuality(UniformGrid2 &boundaryGrid) {
- XA_PROFILE_START(parameterizeChartsEvaluateQuality)
- m_quality.computeBoundaryIntersection(m_unifiedMesh, boundaryGrid);
+
+ void parameterize(const ParameterizeOptions &options, UniformGrid2 &boundaryGrid)
+ {
+ XA_PROFILE_START(parameterizeChartsOrthogonal)
+ {
+ // Project vertices to plane.
+ const uint32_t vertexCount = m_unifiedMesh->vertexCount();
+ for (uint32_t i = 0; i < vertexCount; i++)
+ m_unifiedMesh->texcoord(i) = Vector2(dot(m_basis.tangent, m_unifiedMesh->position(i)), dot(m_basis.bitangent, m_unifiedMesh->position(i)));
+ }
+ XA_PROFILE_END(parameterizeChartsOrthogonal)
+ // Computing charts checks for flipped triangles and boundary intersection. Don't need to do that again here if chart is planar.
+ if (m_type != ChartType::Planar) {
+ XA_PROFILE_START(parameterizeChartsEvaluateQuality)
+ m_quality.computeBoundaryIntersection(m_unifiedMesh, boundaryGrid);
+ m_quality.computeFlippedFaces(m_unifiedMesh, m_initialFaceCount, nullptr);
+ m_quality.computeMetrics(m_unifiedMesh, m_initialFaceCount);
+ XA_PROFILE_END(parameterizeChartsEvaluateQuality)
+ // Use orthogonal parameterization if quality is acceptable.
+ if (!m_quality.boundaryIntersection && m_quality.flippedTriangleCount == 0 && m_quality.totalGeometricArea > 0.0f && m_quality.stretchMetric <= 1.1f && m_quality.maxStretchMetric <= 1.25f)
+ m_type = ChartType::Ortho;
+ }
+ if (m_type == ChartType::LSCM) {
+ XA_PROFILE_START(parameterizeChartsLSCM)
+ if (options.func) {
+ options.func(&m_unifiedMesh->position(0).x, &m_unifiedMesh->texcoord(0).x, m_unifiedMesh->vertexCount(), m_unifiedMesh->indices(), m_unifiedMesh->indexCount());
+ }
+ else
+ computeLeastSquaresConformalMap(m_unifiedMesh);
+ XA_PROFILE_END(parameterizeChartsLSCM)
+ XA_PROFILE_START(parameterizeChartsEvaluateQuality)
+ m_quality.computeBoundaryIntersection(m_unifiedMesh, boundaryGrid);
#if XA_DEBUG_EXPORT_OBJ_INVALID_PARAMETERIZATION
- m_quality.computeFlippedFaces(m_unifiedMesh, m_initialFaceCount, &m_paramFlippedFaces);
+ m_quality.computeFlippedFaces(m_unifiedMesh, m_initialFaceCount, &m_paramFlippedFaces);
#else
- m_quality.computeFlippedFaces(m_unifiedMesh, m_initialFaceCount, nullptr);
+ m_quality.computeFlippedFaces(m_unifiedMesh, m_initialFaceCount, nullptr);
#endif
- // Don't need to call computeMetrics here, that's only used in evaluateOrthoQuality to determine if quality is acceptable enough to use ortho projection.
- XA_PROFILE_END(parameterizeChartsEvaluateQuality)
- }
-
- // Transfer parameterization from unified mesh to chart mesh.
- void transferParameterization() {
+ // Don't need to call computeMetrics here, that's only used in evaluateOrthoQuality to determine if quality is acceptable enough to use ortho projection.
+ if (m_quality.boundaryIntersection || m_quality.flippedTriangleCount > 0)
+ m_isInvalid = true;
+ XA_PROFILE_END(parameterizeChartsEvaluateQuality)
+ }
+#if XA_DEBUG_ALL_CHARTS_INVALID
+ m_isInvalid = true;
+#endif
+ // Transfer parameterization from unified mesh to chart mesh.
const uint32_t vertexCount = m_mesh->vertexCount();
for (uint32_t v = 0; v < vertexCount; v++)
- m_mesh->texcoord(v) = m_unifiedMesh->texcoord(m_chartToUnifiedMap[v]);
+ m_mesh->texcoord(v) = m_unifiedMesh->texcoord(m_chartVertexToUnifiedVertexMap[v]);
+ // Can destroy unified mesh now.
+ // But not if the parameterization is invalid, the unified mesh will be needed for PiecewiseParameterization.
+ if (!m_isInvalid)
+ destroyUnifiedMesh();
+ // Need to store texcoords for backup/restore so packing can be run multiple times.
+ backupTexcoords();
}
- Vector2 computeParametricBounds() const {
+ Vector2 computeParametricBounds() const
+ {
Vector2 minCorner(FLT_MAX, FLT_MAX);
Vector2 maxCorner(-FLT_MAX, -FLT_MAX);
const uint32_t vertexCount = m_mesh->vertexCount();
@@ -6590,7 +7550,34 @@ public:
return (maxCorner - minCorner) * 0.5f;
}
+ void restoreTexcoords()
+ {
+ memcpy(m_mesh->texcoords(), m_backupTexcoords.data(), m_mesh->vertexCount() * sizeof(Vector2));
+ }
+
private:
+ void backupTexcoords()
+ {
+ m_backupTexcoords.resize(m_mesh->vertexCount());
+ memcpy(m_backupTexcoords.data(), m_mesh->texcoords(), m_mesh->vertexCount() * sizeof(Vector2));
+ }
+
+ void destroyUnifiedMesh()
+ {
+ if (m_unifiedMesh) {
+ m_unifiedMesh->~Mesh();
+ XA_FREE(m_unifiedMesh);
+ m_unifiedMesh = nullptr;
+ }
+ if (m_unmodifiedUnifiedMesh) {
+ m_unmodifiedUnifiedMesh->~Mesh();
+ XA_FREE(m_unmodifiedUnifiedMesh);
+ m_unmodifiedUnifiedMesh = nullptr;
+ }
+ // Don't need this when unified meshes are destroyed.
+ m_chartVertexToUnifiedVertexMap.destroy();
+ }
+
Basis m_basis;
Mesh *m_mesh;
Mesh *m_unifiedMesh;
@@ -6600,467 +7587,511 @@ private:
uint32_t m_initialFaceCount; // Before fixing T-junctions and/or closing holes.
uint32_t m_closedHolesCount, m_fixedTJunctionsCount;
- // List of faces of the original mesh that belong to this chart.
- Array<uint32_t> m_faceArray;
+ // List of faces of the source mesh that belong to this chart.
+ Array<uint32_t> m_faceToSourceFaceMap;
- // Map vertices of the chart mesh to vertices of the original mesh.
- Array<uint32_t> m_chartToOriginalMap;
+ // Map vertices of the chart mesh to vertices of the source mesh.
+ Array<uint32_t> m_vertexToSourceVertexMap;
- Array<uint32_t> m_chartToUnifiedMap;
+ Array<uint32_t> m_chartVertexToUnifiedVertexMap;
+
+ Array<Vector2> m_backupTexcoords;
Quality m_quality;
#if XA_DEBUG_EXPORT_OBJ_INVALID_PARAMETERIZATION
Array<uint32_t> m_paramFlippedFaces;
#endif
+ bool m_isInvalid;
};
-struct CreateChartTaskArgs {
- const Mesh *mesh;
+struct CreateAndParameterizeChartTaskArgs
+{
const Basis *basis;
+ ThreadLocal<UniformGrid2> *boundaryGrid;
+ Chart *chart; // output
+ Array<Chart *> charts; // output (if more than one chart)
+ ThreadLocal<ChartCtorBuffers> *chartBuffers;
+ const Mesh *mesh;
+ const ParameterizeOptions *options;
+#if XA_RECOMPUTE_CHARTS
+ ThreadLocal<PiecewiseParam> *pp;
+#endif
ConstArrayView<uint32_t> faces;
- uint32_t meshId;
uint32_t chartGroupId;
uint32_t chartId;
- ThreadLocal<ChartCtorBuffers> *chartBuffers;
- Chart **chart;
};
-static void runCreateChartTask(void *userData) {
- XA_PROFILE_START(createChartMeshesThread)
- auto args = (CreateChartTaskArgs *)userData;
- *(args->chart) = XA_NEW_ARGS(MemTag::Default, Chart, args->chartBuffers->get(), *(args->basis), args->faces, args->mesh, args->meshId, args->chartGroupId, args->chartId);
- XA_PROFILE_END(createChartMeshesThread)
-}
-
-struct ParameterizeChartTaskArgs {
- Chart *chart;
- ParameterizeFunc func;
- ThreadLocal<UniformGrid2> *boundaryGrid;
-};
-
-static void runParameterizeChartTask(void *userData) {
- auto args = (ParameterizeChartTaskArgs *)userData;
- Mesh *mesh = args->chart->unifiedMesh();
- XA_PROFILE_START(parameterizeChartsOrthogonal) {
- // Project vertices to plane.
- const uint32_t vertexCount = mesh->vertexCount();
- const Basis &basis = args->chart->basis();
- for (uint32_t i = 0; i < vertexCount; i++)
- mesh->texcoord(i) = Vector2(dot(basis.tangent, mesh->position(i)), dot(basis.bitangent, mesh->position(i)));
- }
- XA_PROFILE_END(parameterizeChartsOrthogonal)
- // Computing charts checks for flipped triangles and boundary intersection. Don't need to do that again here if chart is planar.
- if (args->chart->type() != ChartType::Planar)
- args->chart->evaluateOrthoQuality(args->boundaryGrid->get());
- if (args->chart->type() == ChartType::LSCM) {
- XA_PROFILE_START(parameterizeChartsLSCM)
- if (args->func)
- args->func(&mesh->position(0).x, &mesh->texcoord(0).x, mesh->vertexCount(), mesh->indices(), mesh->indexCount());
- else
- computeLeastSquaresConformalMap(mesh);
- XA_PROFILE_END(parameterizeChartsLSCM)
- args->chart->evaluateQuality(args->boundaryGrid->get());
+static void runCreateAndParameterizeChartTask(void *userData)
+{
+ auto args = (CreateAndParameterizeChartTaskArgs *)userData;
+ XA_PROFILE_START(createChartMesh)
+ args->chart = XA_NEW_ARGS(MemTag::Default, Chart, args->chartBuffers->get(), *args->options, *args->basis, args->faces, args->mesh, args->chartGroupId, args->chartId);
+ XA_PROFILE_END(createChartMesh)
+ args->chart->parameterize(*args->options, args->boundaryGrid->get());
+#if XA_RECOMPUTE_CHARTS
+ if (!args->chart->isInvalid())
+ return;
+ // Recompute charts with invalid parameterizations.
+ XA_PROFILE_START(parameterizeChartsRecompute)
+ Chart *invalidChart = args->chart;
+ // Fixing t-junctions rewrites unified mesh faces, and we need to map faces back to input mesh. So use the unmodified unified mesh.
+ const Mesh *invalidMesh = invalidChart->unmodifiedUnifiedMesh();
+ uint32_t faceCount = 0;
+ if (invalidMesh) {
+ faceCount = invalidMesh->faceCount();
+ } else {
+ invalidMesh = invalidChart->unifiedMesh();
+ faceCount = invalidChart->initialFaceCount(); // Not invalidMesh->faceCount(). Don't want faces added by hole closing.
}
- // Transfer parameterization from unified mesh to chart mesh.
- args->chart->transferParameterization();
-}
-
-// Set of charts corresponding to mesh faces in the same face group.
-class ChartGroup {
-public:
- ChartGroup(uint32_t id, const Mesh *sourceMesh, uint16_t faceGroup) :
- m_sourceId(sourceMesh->id()), m_id(id), m_isVertexMap(faceGroup == Mesh::kInvalidFaceGroup), m_paramAddedChartsCount(0), m_paramDeletedChartsCount(0) {
- // Create new mesh from the source mesh, using faces that belong to this group.
- const uint32_t sourceFaceCount = sourceMesh->faceCount();
- if (!m_isVertexMap) {
- m_faceToSourceFaceMap.reserve(sourceMesh->faceGroupFaceCount(faceGroup));
- for (Mesh::GroupFaceIterator it(sourceMesh, faceGroup); !it.isDone(); it.advance())
- m_faceToSourceFaceMap.push_back(it.face());
- } else {
- for (uint32_t f = 0; f < sourceFaceCount; f++) {
- if (sourceMesh->faceGroupAt(f) == faceGroup)
- m_faceToSourceFaceMap.push_back(f);
+ PiecewiseParam &pp = args->pp->get();
+ pp.reset(invalidMesh, faceCount);
+#if XA_DEBUG_EXPORT_OBJ_RECOMPUTED_CHARTS
+ char filename[256];
+ XA_SPRINTF(filename, sizeof(filename), "debug_mesh_%03u_chartgroup_%03u_chart_%03u_recomputed.obj", args->mesh->id(), args->chartGroupId, args->chartId);
+ FILE *file;
+ XA_FOPEN(file, filename, "w");
+ uint32_t subChartIndex = 0;
+#endif
+ for (;;) {
+ XA_PROFILE_START(parameterizeChartsPiecewise)
+ const bool facesRemaining = pp.computeChart();
+ XA_PROFILE_END(parameterizeChartsPiecewise)
+ if (!facesRemaining)
+ break;
+ Chart *chart = XA_NEW_ARGS(MemTag::Default, Chart, args->chartBuffers->get(), invalidChart, invalidMesh, pp.chartFaces(), pp.texcoords(), args->mesh);
+ args->charts.push_back(chart);
+#if XA_DEBUG_EXPORT_OBJ_RECOMPUTED_CHARTS
+ if (file) {
+ for (uint32_t j = 0; j < invalidMesh->vertexCount(); j++) {
+ fprintf(file, "v %g %g %g\n", invalidMesh->position(j).x, invalidMesh->position(j).y, invalidMesh->position(j).z);
+ fprintf(file, "vt %g %g\n", pp.texcoords()[j].x, pp.texcoords()[j].y);
}
- }
- // Only initial meshes have face groups and ignored faces. The only flag we care about is HasNormals.
- const uint32_t faceCount = m_faceToSourceFaceMap.size();
- XA_DEBUG_ASSERT(faceCount > 0);
- const uint32_t approxVertexCount = faceCount * 3;
- m_mesh = XA_NEW_ARGS(MemTag::Mesh, Mesh, sourceMesh->epsilon(), approxVertexCount, faceCount, sourceMesh->flags() & MeshFlags::HasNormals);
- m_vertexToSourceVertexMap.reserve(approxVertexCount);
- HashMap<uint32_t> sourceVertexToVertexMap(MemTag::Mesh, approxVertexCount);
- for (uint32_t f = 0; f < faceCount; f++) {
- const uint32_t face = m_faceToSourceFaceMap[f];
- for (uint32_t i = 0; i < 3; i++) {
- const uint32_t vertex = sourceMesh->vertexAt(face * 3 + i);
- if (sourceVertexToVertexMap.get(vertex) == UINT32_MAX) {
- sourceVertexToVertexMap.add(vertex);
- m_vertexToSourceVertexMap.push_back(vertex);
- Vector3 normal(0.0f);
- if (sourceMesh->flags() & MeshFlags::HasNormals)
- normal = sourceMesh->normal(vertex);
- m_mesh->addVertex(sourceMesh->position(vertex), normal, sourceMesh->texcoord(vertex));
+ fprintf(file, "o chart%03u\n", subChartIndex);
+ fprintf(file, "s off\n");
+ for (uint32_t f = 0; f < pp.chartFaces().length; f++) {
+ fprintf(file, "f ");
+ const uint32_t face = pp.chartFaces()[f];
+ for (uint32_t j = 0; j < 3; j++) {
+ const uint32_t index = invalidMesh->vertexCount() * subChartIndex + invalidMesh->vertexAt(face * 3 + j) + 1; // 1-indexed
+ fprintf(file, "%d/%d/%c", index, index, j == 2 ? '\n' : ' ');
}
}
}
- // Add faces.
- for (uint32_t f = 0; f < faceCount; f++) {
- const uint32_t face = m_faceToSourceFaceMap[f];
- uint32_t indices[3];
- for (uint32_t i = 0; i < 3; i++) {
- const uint32_t vertex = sourceMesh->vertexAt(face * 3 + i);
- indices[i] = sourceVertexToVertexMap.get(vertex);
- XA_DEBUG_ASSERT(indices[i] != UINT32_MAX);
- }
- // Don't copy flags, it doesn't matter if a face is ignored after this point. All ignored faces get their own vertex map (m_isVertexMap) ChartGroup.
- // Don't hash edges if m_isVertexMap, they may be degenerate.
- Mesh::AddFaceResult::Enum result = m_mesh->addFace(indices, false, !m_isVertexMap);
- XA_UNUSED(result);
- XA_DEBUG_ASSERT(result == Mesh::AddFaceResult::OK);
- }
- if (!m_isVertexMap) {
- m_mesh->createColocals();
- m_mesh->createBoundaries();
- }
-#if XA_DEBUG_EXPORT_OBJ_CHART_GROUPS
- char filename[256];
- XA_SPRINTF(filename, sizeof(filename), "debug_mesh_%03u_chartgroup_%03u.obj", m_sourceId, m_id);
- m_mesh->writeObjFile(filename);
-#else
- XA_UNUSED(m_id);
+ subChartIndex++;
+#endif
+ }
+#if XA_DEBUG_EXPORT_OBJ_RECOMPUTED_CHARTS
+ if (file)
+ fclose(file);
#endif
+ XA_PROFILE_END(parameterizeChartsRecompute)
+#endif // XA_RECOMPUTE_CHARTS
+}
+
+// Set of charts corresponding to mesh faces in the same face group.
+class ChartGroup
+{
+public:
+ ChartGroup(uint32_t id, const Mesh *sourceMesh, const MeshFaceGroups *sourceMeshFaceGroups, MeshFaceGroups::Handle faceGroup) : m_id(id), m_sourceMesh(sourceMesh), m_sourceMeshFaceGroups(sourceMeshFaceGroups), m_faceGroup(faceGroup), m_faceCount(0), m_paramAddedChartsCount(0), m_paramDeletedChartsCount(0)
+ {
}
- ~ChartGroup() {
- m_mesh->~Mesh();
- XA_FREE(m_mesh);
+ ~ChartGroup()
+ {
for (uint32_t i = 0; i < m_charts.size(); i++) {
m_charts[i]->~Chart();
XA_FREE(m_charts[i]);
}
}
+ uint32_t segmentChartCount() const { return m_chartBasis.size(); }
uint32_t chartCount() const { return m_charts.size(); }
Chart *chartAt(uint32_t i) const { return m_charts[i]; }
+ uint32_t faceCount() const { return m_faceCount; }
uint32_t paramAddedChartsCount() const { return m_paramAddedChartsCount; }
uint32_t paramDeletedChartsCount() const { return m_paramDeletedChartsCount; }
- bool isVertexMap() const { return m_isVertexMap; }
- uint32_t mapFaceToSourceFace(uint32_t face) const { return m_faceToSourceFaceMap[face]; }
- uint32_t mapVertexToSourceVertex(uint32_t i) const { return m_vertexToSourceVertexMap[i]; }
- const Mesh *mesh() const { return m_mesh; }
- /*
- Compute charts using a simple segmentation algorithm.
-
- LSCM:
- - identify sharp features using local dihedral angles.
- - identify seed faces farthest from sharp features.
- - grow charts from these seeds.
-
- MCGIM:
- - phase 1: chart growth
- - grow all charts simultaneously using dijkstra search on the dual graph of the mesh.
- - graph edges are weighted based on planarity metric.
- - metric uses distance to global chart normal.
- - terminate when all faces have been assigned.
- - phase 2: seed computation:
- - place new seed of the chart at the most interior face.
- - most interior is evaluated using distance metric only.
-
- - method repeates the two phases, until the location of the seeds does not change.
- - cycles are detected by recording all the previous seeds and chartification terminates.
-
- D-Charts:
-
- - Uniaxial conic metric:
- - N_c = axis of the generalized cone that best fits the chart. (cone can a be cylinder or a plane).
- - omega_c = angle between the face normals and the axis.
- - Fitting error between chart C and tringle t: F(c,t) = (N_c*n_t - cos(omega_c))^2
-
- - Compactness metrics:
- - Roundness:
- - C(c,t) = pi * D(S_c,t)^2 / A_c
- - S_c = chart seed.
- - D(S_c,t) = length of the shortest path inside the chart betwen S_c and t.
- - A_c = chart area.
- - Straightness:
- - P(c,t) = l_out(c,t) / l_in(c,t)
- - l_out(c,t) = lenght of the edges not shared between C and t.
- - l_in(c,t) = lenght of the edges shared between C and t.
-
- - Combined metric:
- - Cost(c,t) = F(c,t)^alpha + C(c,t)^beta + P(c,t)^gamma
- - alpha = 1, beta = 0.7, gamma = 0.5
-
- Our basic approach:
- - Just one iteration of k-means?
- - Avoid dijkstra by greedily growing charts until a threshold is met. Increase threshold and repeat until no faces left.
- - If distortion metric is too high, split chart, add two seeds.
- - If chart size is low, try removing chart.
-
- Postprocess:
- - If topology is not disk:
- - Fill holes, if new faces fit proxy.
- - Find best cut, otherwise.
- - After parameterization:
- - If boundary self-intersects:
- - cut chart along the closest two diametral boundary vertices, repeat parametrization.
- - what if the overlap is on an appendix? How do we find that out and cut appropiately?
- - emphasize roundness metrics to prevent those cases.
- - If interior self-overlaps: preserve boundary parameterization and use mean-value map.
- */
- void computeCharts(TaskScheduler *taskScheduler, const ChartOptions &options, segment::Atlas &atlas, ThreadLocal<ChartCtorBuffers> *chartBuffers) {
- m_chartOptions = options;
- // This function may be called multiple times, so destroy existing charts.
- for (uint32_t i = 0; i < m_charts.size(); i++) {
- m_charts[i]->~Chart();
- XA_FREE(m_charts[i]);
- }
- m_charts.clear();
+ void computeChartFaces(const ChartOptions &options, segment::Atlas &atlas)
+ {
+ // Create mesh from source mesh, using only the faces in this face group.
+ XA_PROFILE_START(createChartGroupMesh)
+ Mesh *mesh = createMesh();
+ XA_PROFILE_END(createChartGroupMesh)
+ // Segment mesh into charts (arrays of faces).
#if XA_DEBUG_SINGLE_CHART
- Array<uint32_t> chartFaces;
- chartFaces.resize(m_mesh->faceCount());
- for (uint32_t i = 0; i < chartFaces.size(); i++)
- chartFaces[i] = i;
- Chart *chart = XA_NEW_ARGS(MemTag::Default, Chart, m_mesh, chartFaces, m_sourceId, m_id, 0);
- m_charts.push_back(chart);
+ m_chartBasis.resize(1);
+ Fit::computeBasis(&mesh->position(0), mesh->vertexCount(), &m_chartBasis[0]);
+ m_chartFaces.resize(1 + mesh->faceCount());
+ m_chartFaces[0] = mesh->faceCount();
+ for (uint32_t i = 0; i < m_chartFaces.size(); i++)
+ m_chartFaces[i + 1] = i;
#else
XA_PROFILE_START(buildAtlas)
- atlas.reset(m_sourceId, m_id, m_mesh, options);
- buildAtlas(atlas, options);
+ atlas.reset(mesh, options);
+ atlas.compute();
XA_PROFILE_END(buildAtlas)
- const uint32_t chartCount = atlas.chartCount();
- m_charts.resize(chartCount);
- Array<CreateChartTaskArgs> taskArgs;
- taskArgs.resize(chartCount);
- for (uint32_t i = 0; i < chartCount; i++) {
- CreateChartTaskArgs &args = taskArgs[i];
- args.basis = &atlas.chartBasis(i);
- args.faces = atlas.chartFaces(i);
- args.mesh = m_mesh;
- args.meshId = m_sourceId;
- args.chartGroupId = m_id;
- args.chartId = i;
- args.chartBuffers = chartBuffers;
- args.chart = &m_charts[i];
- }
- XA_PROFILE_START(createChartMeshesReal)
- TaskGroupHandle taskGroup = taskScheduler->createTaskGroup(chartCount);
- for (uint32_t i = 0; i < chartCount; i++) {
- Task task;
- task.userData = &taskArgs[i];
- task.func = runCreateChartTask;
- taskScheduler->run(taskGroup, task);
- }
- taskScheduler->wait(&taskGroup);
- XA_PROFILE_END(createChartMeshesReal)
-#endif
#if XA_DEBUG_EXPORT_OBJ_CHARTS
char filename[256];
- XA_SPRINTF(filename, sizeof(filename), "debug_mesh_%03u_chartgroup_%03u_charts.obj", m_sourceId, m_id);
+ XA_SPRINTF(filename, sizeof(filename), "debug_mesh_%03u_chartgroup_%03u_charts.obj", m_sourceMesh->id(), m_id);
FILE *file;
XA_FOPEN(file, filename, "w");
if (file) {
- m_mesh->writeObjVertices(file);
- for (uint32_t i = 0; i < chartCount; i++) {
+ mesh->writeObjVertices(file);
+ for (uint32_t i = 0; i < atlas.chartCount(); i++) {
fprintf(file, "o chart_%04d\n", i);
fprintf(file, "s off\n");
- const Array<uint32_t> &faces = builder.chartFaces(i);
- for (uint32_t f = 0; f < faces.size(); f++)
- m_mesh->writeObjFace(file, faces[f]);
+ ConstArrayView<uint32_t> faces = atlas.chartFaces(i);
+ for (uint32_t f = 0; f < faces.length; f++)
+ mesh->writeObjFace(file, faces[f]);
}
- m_mesh->writeObjBoundaryEges(file);
- m_mesh->writeObjLinkedBoundaries(file);
+ mesh->writeObjBoundaryEges(file);
+ mesh->writeObjLinkedBoundaries(file);
fclose(file);
}
#endif
+ // Destroy mesh.
+ const uint32_t faceCount = mesh->faceCount();
+ mesh->~Mesh();
+ XA_FREE(mesh);
+ XA_PROFILE_START(copyChartFaces)
+ // Copy basis.
+ const uint32_t chartCount = atlas.chartCount();
+ m_chartBasis.resize(chartCount);
+ for (uint32_t i = 0; i < chartCount; i++)
+ m_chartBasis[i] = atlas.chartBasis(i);
+ // Copy faces from segment::Atlas to m_chartFaces array with <chart 0 face count> <face 0> <face n> <chart 1 face count> etc. encoding.
+ // segment::Atlas faces refer to the chart group mesh. Map them to the input mesh instead.
+ m_chartFaces.resize(chartCount + faceCount);
+ uint32_t offset = 0;
+ for (uint32_t i = 0; i < chartCount; i++) {
+ ConstArrayView<uint32_t> faces = atlas.chartFaces(i);
+ m_chartFaces[offset++] = faces.length;
+ for (uint32_t j = 0; j < faces.length; j++)
+ m_chartFaces[offset++] = m_faceToSourceFaceMap[faces[j]];
+ }
+ XA_PROFILE_END(copyChartFaces)
+#endif
}
#if XA_RECOMPUTE_CHARTS
- void parameterizeCharts(TaskScheduler *taskScheduler, ParameterizeFunc func, ThreadLocal<UniformGrid2> *boundaryGrid, ThreadLocal<ChartCtorBuffers> *chartBuffers, ThreadLocal<PiecewiseParam> *piecewiseParam)
+ void parameterizeCharts(TaskScheduler *taskScheduler, const ParameterizeOptions &options, ThreadLocal<UniformGrid2> *boundaryGrid, ThreadLocal<ChartCtorBuffers> *chartBuffers, ThreadLocal<PiecewiseParam> *piecewiseParam)
#else
- void parameterizeCharts(TaskScheduler *taskScheduler, ParameterizeFunc func, ThreadLocal<UniformGrid2> *boundaryGrid, ThreadLocal<ChartCtorBuffers> * /*chartBuffers*/)
+ void parameterizeCharts(TaskScheduler* taskScheduler, const ParameterizeOptions &options, ThreadLocal<UniformGrid2>* boundaryGrid, ThreadLocal<ChartCtorBuffers>* chartBuffers)
#endif
{
+ // This function may be called multiple times, so destroy existing charts.
+ for (uint32_t i = 0; i < m_charts.size(); i++) {
+ m_charts[i]->~Chart();
+ XA_FREE(m_charts[i]);
+ }
m_paramAddedChartsCount = 0;
- const uint32_t chartCount = m_charts.size();
- Array<ParameterizeChartTaskArgs> taskArgs;
+ const uint32_t chartCount = m_chartBasis.size();
+ Array<CreateAndParameterizeChartTaskArgs> taskArgs;
taskArgs.resize(chartCount);
+ taskArgs.runCtors(); // Has Array member.
TaskGroupHandle taskGroup = taskScheduler->createTaskGroup(chartCount);
+ uint32_t offset = 0;
for (uint32_t i = 0; i < chartCount; i++) {
- ParameterizeChartTaskArgs &args = taskArgs[i];
- args.chart = m_charts[i];
- args.func = func;
+ CreateAndParameterizeChartTaskArgs &args = taskArgs[i];
+ args.basis = &m_chartBasis[i];
args.boundaryGrid = boundaryGrid;
+ args.chart = nullptr;
+ args.chartGroupId = m_id;
+ args.chartId = i;
+ args.chartBuffers = chartBuffers;
+ const uint32_t faceCount = m_chartFaces[offset++];
+ args.faces = ConstArrayView<uint32_t>(&m_chartFaces[offset], faceCount);
+ offset += faceCount;
+ args.mesh = m_sourceMesh;
+ args.options = &options;
+#if XA_RECOMPUTE_CHARTS
+ args.pp = piecewiseParam;
+#endif
Task task;
task.userData = &args;
- task.func = runParameterizeChartTask;
+ task.func = runCreateAndParameterizeChartTask;
taskScheduler->run(taskGroup, task);
}
taskScheduler->wait(&taskGroup);
#if XA_RECOMPUTE_CHARTS
- // Find charts with invalid parameterizations.
- Array<Chart *> invalidCharts;
+ // Count charts. Skip invalid ones and include new ones added by recomputing.
+ uint32_t newChartCount = 0;
for (uint32_t i = 0; i < chartCount; i++) {
- Chart *chart = m_charts[i];
- const Quality &quality = chart->quality();
- if (quality.boundaryIntersection || quality.flippedTriangleCount > 0)
- invalidCharts.push_back(chart);
+ if (taskArgs[i].chart->isInvalid())
+ newChartCount += taskArgs[i].charts.size();
+ else
+ newChartCount++;
}
- if (invalidCharts.isEmpty())
- return;
- // Recompute charts with invalid parameterizations.
- PiecewiseParam &pp = piecewiseParam->get();
- for (uint32_t i = 0; i < invalidCharts.size(); i++) {
- Chart *invalidChart = invalidCharts[i];
- // Fixing t-junctions rewrites unified mesh faces, and we need to map faces back to input mesh. So use the unmodified unified mesh.
- const Mesh *invalidMesh = invalidChart->unmodifiedUnifiedMesh();
- uint32_t faceCount = 0;
- if (invalidMesh) {
- faceCount = invalidMesh->faceCount();
- } else {
- invalidMesh = invalidChart->unifiedMesh();
- faceCount = invalidChart->initialFaceCount(); // Not invalidMesh->faceCount(). Don't want faces added by hole closing.
+ m_charts.resize(newChartCount);
+ // Add valid charts first. Destroy invalid ones.
+ uint32_t current = 0;
+ for (uint32_t i = 0; i < chartCount; i++) {
+ Chart *chart = taskArgs[i].chart;
+ if (chart->isInvalid()) {
+ chart->~Chart();
+ XA_FREE(chart);
+ m_paramDeletedChartsCount++;
+ continue;
}
- pp.reset(invalidMesh, faceCount);
-#if XA_DEBUG_EXPORT_OBJ_RECOMPUTED_CHARTS
- char filename[256];
- XA_SPRINTF(filename, sizeof(filename), "debug_mesh_%03u_chartgroup_%03u_recomputed_chart_%03u.obj", m_sourceId, m_id, m_paramAddedChartsCount);
- FILE *file;
- XA_FOPEN(file, filename, "w");
- uint32_t subChartIndex = 0;
-#endif
- for (;;) {
- if (!pp.computeChart())
- break;
- Chart *chart = XA_NEW_ARGS(MemTag::Default, Chart, chartBuffers->get(), invalidChart, invalidMesh, pp.chartFaces(), pp.texcoords(), m_mesh, m_sourceId, m_id, m_charts.size());
- m_charts.push_back(chart);
-#if XA_DEBUG_EXPORT_OBJ_RECOMPUTED_CHARTS
- if (file) {
- for (uint32_t j = 0; j < invalidMesh->vertexCount(); j++) {
- fprintf(file, "v %g %g %g\n", invalidMesh->position(j).x, invalidMesh->position(j).y, invalidMesh->position(j).z);
- fprintf(file, "vt %g %g\n", pp.texcoords()[j].x, pp.texcoords()[j].y);
- }
- fprintf(file, "o chart%03u\n", subChartIndex);
- fprintf(file, "s off\n");
- for (uint32_t f = 0; f < pp.chartFaces().length; f++) {
- fprintf(file, "f ");
- const uint32_t face = pp.chartFaces()[f];
- for (uint32_t j = 0; j < 3; j++) {
- const uint32_t index = invalidMesh->vertexCount() * subChartIndex + invalidMesh->vertexAt(face * 3 + j) + 1; // 1-indexed
- fprintf(file, "%d/%d/%c", index, index, j == 2 ? '\n' : ' ');
- }
- }
- }
- subChartIndex++;
-#endif
+ m_charts[current++] = chart;
+ }
+ // Now add new charts.
+ for (uint32_t i = 0; i < chartCount; i++) {
+ CreateAndParameterizeChartTaskArgs &args = taskArgs[i];
+ for (uint32_t j = 0; j < args.charts.size(); j++) {
+ m_charts[current++] = args.charts[j];
m_paramAddedChartsCount++;
}
-#if XA_DEBUG_EXPORT_OBJ_RECOMPUTED_CHARTS
- if (file)
- fclose(file);
-#endif
- }
- // Remove and delete the invalid charts.
- for (uint32_t i = 0; i < invalidCharts.size(); i++) {
- Chart *chart = invalidCharts[i];
- removeChart(chart);
- chart->~Chart();
- XA_FREE(chart);
- m_paramDeletedChartsCount++;
}
+#else // XA_RECOMPUTE_CHARTS
+ m_charts.resize(chartCount);
+ for (uint32_t i = 0; i < chartCount; i++)
+ m_charts[i] = taskArgs[i].chart;
#endif // XA_RECOMPUTE_CHARTS
+ taskArgs.runDtors(); // Has Array member.
}
private:
- void buildAtlas(segment::Atlas &atlas, const ChartOptions &options) {
- if (atlas.facesLeft() == 0)
- return;
- // Create initial charts greedely.
- atlas.placeSeeds(options.maxThreshold * 0.5f);
- if (options.maxIterations == 0) {
- XA_DEBUG_ASSERT(atlas.facesLeft() == 0);
- return;
- }
- atlas.relocateSeeds();
- atlas.resetCharts();
- // Restart process growing charts in parallel.
- uint32_t iteration = 0;
- for (;;) {
- atlas.growCharts(options.maxThreshold);
- // When charts cannot grow more: fill holes, merge charts, relocate seeds and start new iteration.
- atlas.fillHoles(options.maxThreshold * 0.5f);
-#if XA_MERGE_CHARTS
- atlas.mergeCharts();
-#endif
- if (++iteration == options.maxIterations)
- break;
- if (!atlas.relocateSeeds())
- break;
- atlas.resetCharts();
+ Mesh *createMesh()
+ {
+ XA_DEBUG_ASSERT(m_faceGroup != MeshFaceGroups::kInvalid);
+ // Create new mesh from the source mesh, using faces that belong to this group.
+ m_faceToSourceFaceMap.reserve(m_sourceMeshFaceGroups->faceCount(m_faceGroup));
+ for (MeshFaceGroups::Iterator it(m_sourceMeshFaceGroups, m_faceGroup); !it.isDone(); it.advance())
+ m_faceToSourceFaceMap.push_back(it.face());
+ // Only initial meshes has ignored faces. The only flag we care about is HasNormals.
+ const uint32_t faceCount = m_faceCount = m_faceToSourceFaceMap.size();
+ XA_DEBUG_ASSERT(faceCount > 0);
+ const uint32_t approxVertexCount = min(faceCount * 3, m_sourceMesh->vertexCount());
+ Mesh *mesh = XA_NEW_ARGS(MemTag::Mesh, Mesh, m_sourceMesh->epsilon(), approxVertexCount, faceCount, m_sourceMesh->flags() & MeshFlags::HasNormals);
+ HashMap<uint32_t, PassthroughHash<uint32_t>> sourceVertexToVertexMap(MemTag::Mesh, approxVertexCount);
+ for (uint32_t f = 0; f < faceCount; f++) {
+ const uint32_t face = m_faceToSourceFaceMap[f];
+ for (uint32_t i = 0; i < 3; i++) {
+ const uint32_t vertex = m_sourceMesh->vertexAt(face * 3 + i);
+ if (sourceVertexToVertexMap.get(vertex) == UINT32_MAX) {
+ sourceVertexToVertexMap.add(vertex);
+ Vector3 normal(0.0f);
+ if (m_sourceMesh->flags() & MeshFlags::HasNormals)
+ normal = m_sourceMesh->normal(vertex);
+ mesh->addVertex(m_sourceMesh->position(vertex), normal, m_sourceMesh->texcoord(vertex));
+ }
+ }
}
- // Make sure no holes are left!
- XA_DEBUG_ASSERT(atlas.facesLeft() == 0);
- }
-
- void removeChart(const Chart *chart) {
- for (uint32_t i = 0; i < m_charts.size(); i++) {
- if (m_charts[i] == chart) {
- m_charts.removeAt(i);
- return;
+ // Add faces.
+ for (uint32_t f = 0; f < faceCount; f++) {
+ const uint32_t face = m_faceToSourceFaceMap[f];
+ XA_DEBUG_ASSERT(!m_sourceMesh->isFaceIgnored(face));
+ uint32_t indices[3];
+ for (uint32_t i = 0; i < 3; i++) {
+ const uint32_t vertex = m_sourceMesh->vertexAt(face * 3 + i);
+ indices[i] = sourceVertexToVertexMap.get(vertex);
+ XA_DEBUG_ASSERT(indices[i] != UINT32_MAX);
}
+ // Don't copy flags - ignored faces aren't used by chart groups, they are handled by InvalidMeshGeometry.
+ Mesh::AddFaceResult::Enum result = mesh->addFace(indices);
+ XA_UNUSED(result);
+ XA_DEBUG_ASSERT(result == Mesh::AddFaceResult::OK);
}
+ XA_PROFILE_START(createChartGroupMeshColocals)
+ mesh->createColocals();
+ XA_PROFILE_END(createChartGroupMeshColocals)
+ XA_PROFILE_START(createChartGroupMeshBoundaries)
+ mesh->createBoundaries();
+ mesh->destroyEdgeMap(); // Only needed it for createBoundaries.
+ XA_PROFILE_END(createChartGroupMeshBoundaries)
+#if XA_DEBUG_EXPORT_OBJ_CHART_GROUPS
+ char filename[256];
+ XA_SPRINTF(filename, sizeof(filename), "debug_mesh_%03u_chartgroup_%03u.obj", m_sourceMesh->id(), m_id);
+ mesh->writeObjFile(filename);
+#endif
+ return mesh;
}
- uint32_t m_sourceId, m_id;
- bool m_isVertexMap;
- Mesh *m_mesh;
+ const uint32_t m_id;
+ const Mesh * const m_sourceMesh;
+ const MeshFaceGroups * const m_sourceMeshFaceGroups;
+ const MeshFaceGroups::Handle m_faceGroup;
Array<uint32_t> m_faceToSourceFaceMap; // List of faces of the source mesh that belong to this chart group.
- Array<uint32_t> m_vertexToSourceVertexMap; // Map vertices of the mesh to vertices of the source mesh.
+ Array<Basis> m_chartBasis; // Copied from segment::Atlas.
+ Array<uint32_t> m_chartFaces; // Copied from segment::Atlas. Encoding: <chart 0 face count> <face 0> <face n> <chart 1 face count> etc.
Array<Chart *> m_charts;
- ChartOptions m_chartOptions;
+ uint32_t m_faceCount; // Set by createMesh(). Used for sorting.
uint32_t m_paramAddedChartsCount; // Number of new charts added by recomputing charts with invalid parameterizations.
uint32_t m_paramDeletedChartsCount; // Number of charts with invalid parameterizations that were deleted, after charts were recomputed.
};
-struct CreateChartGroupTaskArgs {
- uint16_t faceGroup;
- uint32_t groupId;
- const Mesh *mesh;
- ChartGroup **chartGroup;
+// References invalid faces and vertices in a mesh.
+struct InvalidMeshGeometry
+{
+ // Invalid faces have the face groups MeshFaceGroups::kInvalid.
+ void extract(const Mesh *mesh, const MeshFaceGroups *meshFaceGroups)
+ {
+ // Copy invalid faces.
+ m_faces.clear();
+ const uint32_t meshFaceCount = mesh->faceCount();
+ for (uint32_t f = 0; f < meshFaceCount; f++) {
+ if (meshFaceGroups->groupAt(f) == MeshFaceGroups::kInvalid)
+ m_faces.push_back(f);
+ }
+ // Create *unique* list of vertices of invalid faces.
+ const uint32_t faceCount = m_faces.size();
+ m_indices.resize(faceCount * 3);
+ const uint32_t approxVertexCount = min(faceCount * 3, mesh->vertexCount());
+ m_vertexToSourceVertexMap.clear();
+ m_vertexToSourceVertexMap.reserve(approxVertexCount);
+ HashMap<uint32_t, PassthroughHash<uint32_t>> sourceVertexToVertexMap(MemTag::Mesh, approxVertexCount);
+ for (uint32_t f = 0; f < faceCount; f++) {
+ const uint32_t face = m_faces[f];
+ for (uint32_t i = 0; i < 3; i++) {
+ const uint32_t vertex = mesh->vertexAt(face * 3 + i);
+ uint32_t newVertex = sourceVertexToVertexMap.get(vertex);
+ if (newVertex == UINT32_MAX) {
+ newVertex = sourceVertexToVertexMap.add(vertex);
+ m_vertexToSourceVertexMap.push_back(vertex);
+ }
+ m_indices[f * 3 + i] = newVertex;
+ }
+ }
+ }
+
+ ConstArrayView<uint32_t> faces() const { return m_faces; }
+ ConstArrayView<uint32_t> indices() const { return m_indices; }
+ ConstArrayView<uint32_t> vertices() const { return m_vertexToSourceVertexMap; }
+
+private:
+ Array<uint32_t> m_faces, m_indices;
+ Array<uint32_t> m_vertexToSourceVertexMap; // Map face vertices to vertices of the source mesh.
};
-static void runCreateChartGroupTask(void *userData) {
- XA_PROFILE_START(addMeshCreateChartGroupsThread)
- auto args = (CreateChartGroupTaskArgs *)userData;
- *(args->chartGroup) = XA_NEW_ARGS(MemTag::Default, ChartGroup, args->groupId, args->mesh, args->faceGroup);
- XA_PROFILE_END(addMeshCreateChartGroupsThread)
+struct ChartGroupComputeChartFacesTaskArgs
+{
+ ThreadLocal<segment::Atlas> *atlas;
+ ChartGroup *chartGroup;
+ const ChartOptions *options;
+ Progress *progress;
+};
+
+static void runChartGroupComputeChartFacesJob(void *userData)
+{
+ auto args = (ChartGroupComputeChartFacesTaskArgs *)userData;
+ if (args->progress->cancel)
+ return;
+ XA_PROFILE_START(chartGroupComputeChartsThread)
+ args->chartGroup->computeChartFaces(*args->options, args->atlas->get());
+ XA_PROFILE_END(chartGroupComputeChartsThread)
}
-struct ComputeChartsTaskArgs {
- TaskScheduler *taskScheduler;
- ChartGroup *chartGroup;
+struct MeshComputeChartFacesTaskArgs
+{
+ Array<ChartGroup *> *chartGroups; // output
+ InvalidMeshGeometry *invalidMeshGeometry; // output
ThreadLocal<segment::Atlas> *atlas;
- ThreadLocal<ChartCtorBuffers> *chartBuffers;
const ChartOptions *options;
Progress *progress;
+ const Mesh *sourceMesh;
+ TaskScheduler *taskScheduler;
};
-static void runComputeChartsJob(void *userData) {
- auto args = (ComputeChartsTaskArgs *)userData;
+#if XA_DEBUG_EXPORT_OBJ_FACE_GROUPS
+static uint32_t s_faceGroupsCurrentVertex = 0;
+#endif
+
+static void runMeshComputeChartFacesJob(void *userData)
+{
+ auto args = (MeshComputeChartFacesTaskArgs *)userData;
if (args->progress->cancel)
return;
XA_PROFILE_START(computeChartsThread)
- args->chartGroup->computeCharts(args->taskScheduler, *args->options, args->atlas->get(), args->chartBuffers);
+ // Create face groups.
+ XA_PROFILE_START(createFaceGroups)
+ MeshFaceGroups *meshFaceGroups = XA_NEW_ARGS(MemTag::Mesh, MeshFaceGroups, args->sourceMesh);
+ meshFaceGroups->compute();
+ const uint32_t chartGroupCount = meshFaceGroups->groupCount();
+ XA_PROFILE_END(createFaceGroups)
+ if (args->progress->cancel)
+ goto cleanup;
+#if XA_DEBUG_EXPORT_OBJ_FACE_GROUPS
+ {
+ static std::mutex s_mutex;
+ std::lock_guard<std::mutex> lock(s_mutex);
+ char filename[256];
+ XA_SPRINTF(filename, sizeof(filename), "debug_face_groups.obj");
+ FILE *file;
+ XA_FOPEN(file, filename, s_faceGroupsCurrentVertex == 0 ? "w" : "a");
+ if (file) {
+ const Mesh *mesh = args->sourceMesh;
+ mesh->writeObjVertices(file);
+ // groups
+ uint32_t numGroups = 0;
+ for (uint32_t i = 0; i < mesh->faceCount(); i++) {
+ if (meshFaceGroups->groupAt(i) != MeshFaceGroups::kInvalid)
+ numGroups = max(numGroups, meshFaceGroups->groupAt(i) + 1);
+ }
+ for (uint32_t i = 0; i < numGroups; i++) {
+ fprintf(file, "o mesh_%03u_group_%04d\n", mesh->id(), i);
+ fprintf(file, "s off\n");
+ for (uint32_t f = 0; f < mesh->faceCount(); f++) {
+ if (meshFaceGroups->groupAt(f) == i)
+ mesh->writeObjFace(file, f, s_faceGroupsCurrentVertex);
+ }
+ }
+ fprintf(file, "o mesh_%03u_group_ignored\n", mesh->id());
+ fprintf(file, "s off\n");
+ for (uint32_t f = 0; f < mesh->faceCount(); f++) {
+ if (meshFaceGroups->groupAt(f) == MeshFaceGroups::kInvalid)
+ mesh->writeObjFace(file, f, s_faceGroupsCurrentVertex);
+ }
+ mesh->writeObjBoundaryEges(file);
+ s_faceGroupsCurrentVertex += mesh->vertexCount();
+ fclose(file);
+ }
+ }
+#endif
+ // Create a chart group for each face group.
+ args->chartGroups->resize(chartGroupCount);
+ for (uint32_t i = 0; i < chartGroupCount; i++)
+ (*args->chartGroups)[i] = XA_NEW_ARGS(MemTag::Default, ChartGroup, i, args->sourceMesh, meshFaceGroups, MeshFaceGroups::Handle(i));
+ // Extract invalid geometry via the invalid face group (MeshFaceGroups::kInvalid).
+ XA_PROFILE_START(extractInvalidMeshGeometry)
+ args->invalidMeshGeometry->extract(args->sourceMesh, meshFaceGroups);
+ XA_PROFILE_END(extractInvalidMeshGeometry)
+ // One task for each chart group - compute chart faces.
+ {
+ XA_PROFILE_START(chartGroupComputeChartsReal)
+ Array<ChartGroupComputeChartFacesTaskArgs> taskArgs;
+ taskArgs.resize(chartGroupCount);
+ for (uint32_t i = 0; i < chartGroupCount; i++) {
+ taskArgs[i].atlas = args->atlas;
+ taskArgs[i].chartGroup = (*args->chartGroups)[i];
+ taskArgs[i].options = args->options;
+ taskArgs[i].progress = args->progress;
+ }
+ TaskGroupHandle taskGroup = args->taskScheduler->createTaskGroup(chartGroupCount);
+ for (uint32_t i = 0; i < chartGroupCount; i++) {
+ Task task;
+ task.userData = &taskArgs[i];
+ task.func = runChartGroupComputeChartFacesJob;
+ args->taskScheduler->run(taskGroup, task);
+ }
+ args->taskScheduler->wait(&taskGroup);
+ XA_PROFILE_END(chartGroupComputeChartsReal)
+ }
XA_PROFILE_END(computeChartsThread)
args->progress->value++;
args->progress->update();
+cleanup:
+ if (meshFaceGroups) {
+ meshFaceGroups->~MeshFaceGroups();
+ XA_FREE(meshFaceGroups);
+ }
}
-struct ParameterizeChartsTaskArgs {
+struct ParameterizeChartsTaskArgs
+{
TaskScheduler *taskScheduler;
ChartGroup *chartGroup;
- ParameterizeFunc func;
+ const ParameterizeOptions *options;
ThreadLocal<UniformGrid2> *boundaryGrid;
ThreadLocal<ChartCtorBuffers> *chartBuffers;
#if XA_RECOMPUTE_CHARTS
@@ -7069,15 +8100,16 @@ struct ParameterizeChartsTaskArgs {
Progress *progress;
};
-static void runParameterizeChartsJob(void *userData) {
+static void runParameterizeChartsJob(void *userData)
+{
auto args = (ParameterizeChartsTaskArgs *)userData;
if (args->progress->cancel)
return;
XA_PROFILE_START(parameterizeChartsThread)
#if XA_RECOMPUTE_CHARTS
- args->chartGroup->parameterizeCharts(args->taskScheduler, args->func, args->boundaryGrid, args->chartBuffers, args->piecewiseParam);
+ args->chartGroup->parameterizeCharts(args->taskScheduler, *args->options, args->boundaryGrid, args->chartBuffers, args->piecewiseParam);
#else
- args->chartGroup->parameterizeCharts(args->taskScheduler, args->func, args->boundaryGrid, args->chartBuffers);
+ args->chartGroup->parameterizeCharts(args->taskScheduler, *args->options, args->boundaryGrid, args->chartBuffers);
#endif
XA_PROFILE_END(parameterizeChartsThread)
args->progress->value++;
@@ -7085,137 +8117,86 @@ static void runParameterizeChartsJob(void *userData) {
}
/// An atlas is a set of chart groups.
-class Atlas {
+class Atlas
+{
public:
- Atlas() :
- m_meshCount(0), m_chartsComputed(false), m_chartsParameterized(false) {}
+ Atlas() : m_chartsComputed(false), m_chartsParameterized(false) {}
- ~Atlas() {
- for (uint32_t i = 0; i < m_chartGroups.size(); i++) {
- m_chartGroups[i]->~ChartGroup();
- XA_FREE(m_chartGroups[i]);
+ ~Atlas()
+ {
+ for (uint32_t i = 0; i < m_meshChartGroups.size(); i++) {
+ for (uint32_t j = 0; j < m_meshChartGroups[i].size(); j++) {
+ m_meshChartGroups[i][j]->~ChartGroup();
+ XA_FREE(m_meshChartGroups[i][j]);
+ }
}
+ m_meshChartGroups.runDtors();
+ m_invalidMeshGeometry.runDtors();
}
+ uint32_t meshCount() const { return m_meshes.size(); }
+ const InvalidMeshGeometry &invalidMeshGeometry(uint32_t meshIndex) const { return m_invalidMeshGeometry[meshIndex]; }
bool chartsComputed() const { return m_chartsComputed; }
bool chartsParameterized() const { return m_chartsParameterized; }
- uint32_t chartGroupCount() const { return m_chartGroups.size(); }
- const ChartGroup *chartGroupAt(uint32_t index) const { return m_chartGroups[index]; }
-
- uint32_t chartGroupCount(uint32_t mesh) const {
- uint32_t count = 0;
- for (uint32_t i = 0; i < m_chartGroups.size(); i++) {
- if (m_chartGroupSourceMeshes[i] == mesh)
- count++;
- }
- return count;
- }
-
- const ChartGroup *chartGroupAt(uint32_t mesh, uint32_t group) const {
- for (uint32_t c = 0; c < m_chartGroups.size(); c++) {
- if (m_chartGroupSourceMeshes[c] != mesh)
- continue;
- if (group == 0)
- return m_chartGroups[c];
- group--;
- }
- return nullptr;
- }
+ uint32_t chartGroupCount(uint32_t mesh) const { return m_meshChartGroups[mesh].size(); }
+ const ChartGroup *chartGroupAt(uint32_t mesh, uint32_t group) const { return m_meshChartGroups[mesh][group]; }
- // This function is thread safe.
- void addMesh(TaskScheduler *taskScheduler, const Mesh *mesh) {
- // Create one chart group per face group.
- // If there's any ignored faces in the mesh, create an extra face group for that (vertex map).
- // Chart group creation is slow since it copies a chunk of the source mesh, so use tasks.
- Array<ChartGroup *> chartGroups;
- chartGroups.resize(mesh->faceGroupCount() + (mesh->ignoredFaceCount() > 0 ? 1 : 0));
- Array<CreateChartGroupTaskArgs> taskArgs;
- taskArgs.resize(chartGroups.size());
- for (uint32_t g = 0; g < chartGroups.size(); g++) {
- CreateChartGroupTaskArgs &args = taskArgs[g];
- args.chartGroup = &chartGroups[g];
- args.faceGroup = uint16_t(g < mesh->faceGroupCount() ? g : Mesh::kInvalidFaceGroup);
- args.groupId = g;
- args.mesh = mesh;
- }
- TaskGroupHandle taskGroup = taskScheduler->createTaskGroup(chartGroups.size());
- for (uint32_t g = 0; g < chartGroups.size(); g++) {
- Task task;
- task.userData = &taskArgs[g];
- task.func = runCreateChartGroupTask;
- taskScheduler->run(taskGroup, task);
- }
- taskScheduler->wait(&taskGroup);
- // Thread-safe append.
- m_addMeshMutex.lock();
- for (uint32_t g = 0; g < chartGroups.size(); g++) {
- m_chartGroups.push_back(chartGroups[g]);
- m_chartGroupSourceMeshes.push_back(mesh->id());
- }
- m_meshCount++;
- m_addMeshMutex.unlock();
- }
-
- // Chart id/index is determined by depth-first hierarchy of mesh -> chart group -> chart.
- // For chart index to be consistent here, chart groups needs to sorted by mesh index. Since addMesh is called by multithreaded tasks, order is indeterminate, so chart groups need to be explicitly sorted after all meshes are added.
- void sortChartGroups() {
- Array<ChartGroup *> oldChartGroups;
- oldChartGroups.resize(m_chartGroups.size());
- memcpy(oldChartGroups.data(), m_chartGroups.data(), sizeof(ChartGroup *) * m_chartGroups.size());
- Array<uint32_t> oldChartGroupSourceMeshes;
- oldChartGroupSourceMeshes.resize(m_chartGroupSourceMeshes.size());
- memcpy(oldChartGroupSourceMeshes.data(), m_chartGroupSourceMeshes.data(), sizeof(uint32_t) * m_chartGroupSourceMeshes.size());
- uint32_t current = 0;
- for (uint32_t i = 0; i < m_meshCount; i++) {
- for (uint32_t j = 0; j < oldChartGroups.size(); j++) {
- if (oldChartGroupSourceMeshes[j] == i) {
- m_chartGroups[current] = oldChartGroups[j];
- m_chartGroupSourceMeshes[current] = oldChartGroupSourceMeshes[j];
- current++;
- }
- }
- }
+ void addMesh(const Mesh *mesh)
+ {
+ m_meshes.push_back(mesh);
}
- bool computeCharts(TaskScheduler *taskScheduler, const ChartOptions &options, ProgressFunc progressFunc, void *progressUserData) {
+ bool computeCharts(TaskScheduler *taskScheduler, const ChartOptions &options, ProgressFunc progressFunc, void *progressUserData)
+ {
+#if XA_DEBUG_EXPORT_OBJ_PLANAR_REGIONS
+ segment::s_planarRegionsCurrentRegion = segment::s_planarRegionsCurrentVertex = 0;
+#endif
m_chartsComputed = false;
m_chartsParameterized = false;
- // Ignore vertex maps.
- uint32_t chartGroupCount = 0;
- for (uint32_t i = 0; i < m_chartGroups.size(); i++) {
- if (!m_chartGroups[i]->isVertexMap())
- chartGroupCount++;
+ // Clear chart groups, since this function may be called multiple times.
+ if (!m_meshChartGroups.isEmpty()) {
+ for (uint32_t i = 0; i < m_meshChartGroups.size(); i++) {
+ for (uint32_t j = 0; j < m_meshChartGroups[i].size(); j++) {
+ m_meshChartGroups[i][j]->~ChartGroup();
+ XA_FREE(m_meshChartGroups[i][j]);
+ }
+ m_meshChartGroups[i].clear();
+ }
+ XA_ASSERT(m_meshChartGroups.size() == m_meshes.size()); // The number of meshes shouldn't have changed.
}
- Progress progress(ProgressCategory::ComputeCharts, progressFunc, progressUserData, chartGroupCount);
+ m_meshChartGroups.resize(m_meshes.size());
+ m_meshChartGroups.runCtors();
+ m_invalidMeshGeometry.resize(m_meshes.size());
+ m_invalidMeshGeometry.runCtors();
+ // One task per mesh.
+ const uint32_t meshCount = m_meshes.size();
+ Progress progress(ProgressCategory::ComputeCharts, progressFunc, progressUserData, meshCount);
ThreadLocal<segment::Atlas> atlas;
- ThreadLocal<ChartCtorBuffers> chartBuffers;
- Array<ComputeChartsTaskArgs> taskArgs;
- taskArgs.reserve(chartGroupCount);
- for (uint32_t i = 0; i < m_chartGroups.size(); i++) {
- if (!m_chartGroups[i]->isVertexMap()) {
- ComputeChartsTaskArgs args;
- args.taskScheduler = taskScheduler;
- args.chartGroup = m_chartGroups[i];
- args.atlas = &atlas;
- args.chartBuffers = &chartBuffers;
- args.options = &options;
- args.progress = &progress;
- taskArgs.push_back(args);
- }
- }
- // Sort chart groups by mesh indexCount.
- m_chartGroupsRadix = RadixSort();
- Array<float> chartGroupSortData;
- chartGroupSortData.resize(chartGroupCount);
- for (uint32_t i = 0; i < chartGroupCount; i++)
- chartGroupSortData[i] = (float)taskArgs[i].chartGroup->mesh()->indexCount();
- m_chartGroupsRadix.sort(chartGroupSortData);
- // Larger chart group meshes are added first to reduce the chance of thread starvation.
- TaskGroupHandle taskGroup = taskScheduler->createTaskGroup(chartGroupCount);
- for (uint32_t i = 0; i < chartGroupCount; i++) {
+ Array<MeshComputeChartFacesTaskArgs> taskArgs;
+ taskArgs.resize(meshCount);
+ for (uint32_t i = 0; i < meshCount; i++) {
+ MeshComputeChartFacesTaskArgs &args = taskArgs[i];
+ args.atlas = &atlas;
+ args.chartGroups = &m_meshChartGroups[i];
+ args.invalidMeshGeometry = &m_invalidMeshGeometry[i];
+ args.options = &options;
+ args.progress = &progress;
+ args.sourceMesh = m_meshes[i];
+ args.taskScheduler = taskScheduler;
+ }
+ // Sort meshes by indexCount.
+ Array<float> meshSortData;
+ meshSortData.resize(meshCount);
+ for (uint32_t i = 0; i < meshCount; i++)
+ meshSortData[i] = (float)m_meshes[i]->indexCount();
+ RadixSort meshSort;
+ meshSort.sort(meshSortData);
+ // Larger meshes are added first to reduce the chance of thread starvation.
+ TaskGroupHandle taskGroup = taskScheduler->createTaskGroup(meshCount);
+ for (uint32_t i = 0; i < meshCount; i++) {
Task task;
- task.userData = &taskArgs[m_chartGroupsRadix.ranks()[chartGroupCount - i - 1]];
- task.func = runComputeChartsJob;
+ task.userData = &taskArgs[meshSort.ranks()[meshCount - i - 1]];
+ task.func = runMeshComputeChartFacesJob;
taskScheduler->run(taskGroup, task);
}
taskScheduler->wait(&taskGroup);
@@ -7225,14 +8206,12 @@ public:
return true;
}
- bool parameterizeCharts(TaskScheduler *taskScheduler, ParameterizeFunc func, ProgressFunc progressFunc, void *progressUserData) {
+ bool parameterizeCharts(TaskScheduler *taskScheduler, const ParameterizeOptions &options, ProgressFunc progressFunc, void *progressUserData)
+ {
m_chartsParameterized = false;
- // Ignore vertex maps.
uint32_t chartGroupCount = 0;
- for (uint32_t i = 0; i < m_chartGroups.size(); i++) {
- if (!m_chartGroups[i]->isVertexMap())
- chartGroupCount++;
- }
+ for (uint32_t i = 0; i < m_meshChartGroups.size(); i++)
+ chartGroupCount += m_meshChartGroups[i].size();
Progress progress(ProgressCategory::ParameterizeCharts, progressFunc, progressUserData, chartGroupCount);
ThreadLocal<UniformGrid2> boundaryGrid; // For Quality boundary intersection.
ThreadLocal<ChartCtorBuffers> chartBuffers;
@@ -7240,27 +8219,45 @@ public:
ThreadLocal<PiecewiseParam> piecewiseParam;
#endif
Array<ParameterizeChartsTaskArgs> taskArgs;
- taskArgs.reserve(chartGroupCount);
- for (uint32_t i = 0; i < m_chartGroups.size(); i++) {
- if (!m_chartGroups[i]->isVertexMap()) {
- ParameterizeChartsTaskArgs args;
- args.taskScheduler = taskScheduler;
- args.chartGroup = m_chartGroups[i];
- args.func = func;
- args.boundaryGrid = &boundaryGrid;
- args.chartBuffers = &chartBuffers;
+ taskArgs.resize(chartGroupCount);
+ {
+ uint32_t k = 0;
+ for (uint32_t i = 0; i < m_meshChartGroups.size(); i++) {
+ const uint32_t count = m_meshChartGroups[i].size();
+ for (uint32_t j = 0; j < count; j++) {
+ ParameterizeChartsTaskArgs &args = taskArgs[k];
+ args.taskScheduler = taskScheduler;
+ args.chartGroup = m_meshChartGroups[i][j];
+ args.options = &options;
+ args.boundaryGrid = &boundaryGrid;
+ args.chartBuffers = &chartBuffers;
#if XA_RECOMPUTE_CHARTS
- args.piecewiseParam = &piecewiseParam;
+ args.piecewiseParam = &piecewiseParam;
#endif
- args.progress = &progress;
- taskArgs.push_back(args);
+ args.progress = &progress;
+ k++;
+ }
}
}
- // Larger chart group meshes are added first to reduce the chance of thread starvation.
+ // Sort chart groups by face count.
+ Array<float> chartGroupSortData;
+ chartGroupSortData.resize(chartGroupCount);
+ {
+ uint32_t k = 0;
+ for (uint32_t i = 0; i < m_meshChartGroups.size(); i++) {
+ const uint32_t count = m_meshChartGroups[i].size();
+ for (uint32_t j = 0; j < count; j++) {
+ chartGroupSortData[k++] = (float)m_meshChartGroups[i][j]->faceCount();
+ }
+ }
+ }
+ RadixSort chartGroupSort;
+ chartGroupSort.sort(chartGroupSortData);
+ // Larger chart groups are added first to reduce the chance of thread starvation.
TaskGroupHandle taskGroup = taskScheduler->createTaskGroup(chartGroupCount);
for (uint32_t i = 0; i < chartGroupCount; i++) {
Task task;
- task.userData = &taskArgs[m_chartGroupsRadix.ranks()[chartGroupCount - i - 1]];
+ task.userData = &taskArgs[chartGroupSort.ranks()[chartGroupCount - i - 1]];
task.func = runParameterizeChartsJob;
taskScheduler->run(taskGroup, task);
}
@@ -7272,28 +8269,28 @@ public:
}
private:
- std::mutex m_addMeshMutex;
- uint32_t m_meshCount;
+ Array<const Mesh *> m_meshes;
+ Array<InvalidMeshGeometry> m_invalidMeshGeometry; // 1 per mesh.
+ Array<Array<ChartGroup *> > m_meshChartGroups;
bool m_chartsComputed;
bool m_chartsParameterized;
- Array<ChartGroup *> m_chartGroups;
- RadixSort m_chartGroupsRadix; // By mesh indexCount.
- Array<uint32_t> m_chartGroupSourceMeshes;
};
} // namespace param
namespace pack {
-class AtlasImage {
+class AtlasImage
+{
public:
- AtlasImage(uint32_t width, uint32_t height) :
- m_width(width), m_height(height) {
+ AtlasImage(uint32_t width, uint32_t height) : m_width(width), m_height(height)
+ {
m_data.resize(m_width * m_height);
memset(m_data.data(), 0, sizeof(uint32_t) * m_data.size());
}
- void resize(uint32_t width, uint32_t height) {
+ void resize(uint32_t width, uint32_t height)
+ {
Array<uint32_t> data;
data.resize(width * height);
memset(data.data(), 0, sizeof(uint32_t) * data.size());
@@ -7304,7 +8301,8 @@ public:
data.moveTo(m_data);
}
- void addChart(uint32_t chartIndex, const BitImage *image, const BitImage *imageBilinear, const BitImage *imagePadding, int atlas_w, int atlas_h, int offset_x, int offset_y) {
+ void addChart(uint32_t chartIndex, const BitImage *image, const BitImage *imageBilinear, const BitImage *imagePadding, int atlas_w, int atlas_h, int offset_x, int offset_y)
+ {
const int w = image->width();
const int h = image->height();
for (int y = 0; y < h; y++) {
@@ -7330,13 +8328,15 @@ public:
}
}
- void copyTo(uint32_t *dest, uint32_t destWidth, uint32_t destHeight, int padding) const {
+ void copyTo(uint32_t *dest, uint32_t destWidth, uint32_t destHeight, int padding) const
+ {
for (uint32_t y = 0; y < destHeight; y++)
memcpy(&dest[y * destWidth], &m_data[padding + (y + padding) * m_width], destWidth * sizeof(uint32_t));
}
#if XA_DEBUG_EXPORT_ATLAS_IMAGES
- void writeTga(const char *filename, uint32_t width, uint32_t height) const {
+ void writeTga(const char *filename, uint32_t width, uint32_t height) const
+ {
Array<uint8_t> image;
image.resize(width * height * 3);
for (uint32_t y = 0; y < height; y++) {
@@ -7378,7 +8378,8 @@ private:
Array<uint32_t> m_data;
};
-struct Chart {
+struct Chart
+{
int32_t atlasIndex;
uint32_t material;
uint32_t indexCount;
@@ -7400,18 +8401,20 @@ struct Chart {
uint32_t uniqueVertexCount() const { return uniqueVertices.isEmpty() ? vertexCount : uniqueVertices.size(); }
};
-struct AddChartTaskArgs {
+struct AddChartTaskArgs
+{
ThreadLocal<BoundingBox2D> *boundingBox;
param::Chart *paramChart;
Chart *chart; // out
};
-static void runAddChartTask(void *userData) {
+static void runAddChartTask(void *userData)
+{
XA_PROFILE_START(packChartsAddChartsThread)
auto args = (AddChartTaskArgs *)userData;
param::Chart *paramChart = args->paramChart;
XA_PROFILE_START(packChartsAddChartsRestoreTexcoords)
- paramChart->transferParameterization();
+ paramChart->restoreTexcoords();
XA_PROFILE_END(packChartsAddChartsRestoreTexcoords)
Mesh *mesh = paramChart->mesh();
Chart *chart = args->chart = XA_NEW(MemTag::Default, Chart);
@@ -7445,8 +8448,10 @@ static void runAddChartTask(void *userData) {
XA_PROFILE_END(packChartsAddChartsThread)
}
-struct Atlas {
- ~Atlas() {
+struct Atlas
+{
+ ~Atlas()
+ {
for (uint32_t i = 0; i < m_atlasImages.size(); i++) {
m_atlasImages[i]->~AtlasImage();
XA_FREE(m_atlasImages[i]);
@@ -7470,15 +8475,16 @@ struct Atlas {
const Array<AtlasImage *> &getImages() const { return m_atlasImages; }
float getUtilization(uint32_t atlas) const { return m_utilization[atlas]; }
- void addCharts(TaskScheduler *taskScheduler, param::Atlas *paramAtlas) {
+ void addCharts(TaskScheduler *taskScheduler, param::Atlas *paramAtlas)
+ {
// Count charts.
uint32_t chartCount = 0;
- const uint32_t chartGroupsCount = paramAtlas->chartGroupCount();
- for (uint32_t i = 0; i < chartGroupsCount; i++) {
- const param::ChartGroup *chartGroup = paramAtlas->chartGroupAt(i);
- if (chartGroup->isVertexMap())
- continue;
- chartCount += chartGroup->chartCount();
+ for (uint32_t i = 0; i < paramAtlas->meshCount(); i++) {
+ const uint32_t chartGroupsCount = paramAtlas->chartGroupCount(i);
+ for (uint32_t j = 0; j < chartGroupsCount; j++) {
+ const param::ChartGroup *chartGroup = paramAtlas->chartGroupAt(i, j);
+ chartCount += chartGroup->chartCount();
+ }
}
if (chartCount == 0)
return;
@@ -7488,20 +8494,21 @@ struct Atlas {
TaskGroupHandle taskGroup = taskScheduler->createTaskGroup(chartCount);
uint32_t chartIndex = 0;
ThreadLocal<BoundingBox2D> boundingBox;
- for (uint32_t i = 0; i < chartGroupsCount; i++) {
- const param::ChartGroup *chartGroup = paramAtlas->chartGroupAt(i);
- if (chartGroup->isVertexMap())
- continue;
- const uint32_t count = chartGroup->chartCount();
- for (uint32_t j = 0; j < count; j++) {
- AddChartTaskArgs &args = taskArgs[chartIndex];
- args.boundingBox = &boundingBox;
- args.paramChart = chartGroup->chartAt(j);
- Task task;
- task.userData = &taskArgs[chartIndex];
- task.func = runAddChartTask;
- taskScheduler->run(taskGroup, task);
- chartIndex++;
+ for (uint32_t i = 0; i < paramAtlas->meshCount(); i++) {
+ const uint32_t chartGroupsCount = paramAtlas->chartGroupCount(i);
+ for (uint32_t j = 0; j < chartGroupsCount; j++) {
+ const param::ChartGroup *chartGroup = paramAtlas->chartGroupAt(i, j);
+ const uint32_t count = chartGroup->chartCount();
+ for (uint32_t k = 0; k < count; k++) {
+ AddChartTaskArgs &args = taskArgs[chartIndex];
+ args.boundingBox = &boundingBox;
+ args.paramChart = chartGroup->chartAt(k);
+ Task task;
+ task.userData = &taskArgs[chartIndex];
+ task.func = runAddChartTask;
+ taskScheduler->run(taskGroup, task);
+ chartIndex++;
+ }
}
}
taskScheduler->wait(&taskGroup);
@@ -7511,7 +8518,8 @@ struct Atlas {
m_charts[i] = taskArgs[i].chart;
}
- void addUvMeshCharts(UvMeshInstance *mesh) {
+ void addUvMeshCharts(UvMeshInstance *mesh)
+ {
BitArray vertexUsed(mesh->texcoords.size());
BoundingBox2D boundingBox;
for (uint32_t c = 0; c < mesh->mesh->charts.size(); c++) {
@@ -7572,7 +8580,8 @@ struct Atlas {
}
// Pack charts in the smallest possible rectangle.
- bool packCharts(const PackOptions &options, ProgressFunc progressFunc, void *progressUserData) {
+ bool packCharts(const PackOptions &options, ProgressFunc progressFunc, void *progressUserData)
+ {
if (progressFunc) {
if (!progressFunc(ProgressCategory::PackCharts, 0, progressUserData))
return false;
@@ -7699,7 +8708,6 @@ struct Atlas {
maxChartPerimeter = max(maxChartPerimeter, chartOrderArray[c]);
}
// Sort charts by perimeter.
- m_radix = RadixSort();
m_radix.sort(chartOrderArray);
const uint32_t *ranks = m_radix.ranks();
// Divide chart perimeter range into buckets.
@@ -7807,7 +8815,8 @@ struct Atlas {
int best_x = 0, best_y = 0;
int best_cw = 0, best_ch = 0;
int best_r = 0;
- for (;;) {
+ for (;;)
+ {
bool firstChartInBitImage = false;
XA_UNUSED(firstChartInBitImage);
if (currentAtlas + 1 > m_bitImages.size()) {
@@ -7840,7 +8849,8 @@ struct Atlas {
if (best_x + best_cw > atlasSizes[currentAtlas].x || best_y + best_ch > atlasSizes[currentAtlas].y) {
for (uint32_t j = 0; j < chartStartPositions.size(); j++)
chartStartPositions[j] = Vector2i(0, 0);
- } else {
+ }
+ else {
chartStartPositions[currentAtlas] = Vector2i(best_x, best_y);
}
}
@@ -7892,10 +8902,8 @@ struct Atlas {
}
texcoord.x = best_x + t.x;
texcoord.y = best_y + t.y;
- if (!options.blockAlign) {
- texcoord.x -= (float)options.padding;
- texcoord.y -= (float)options.padding;
- }
+ texcoord.x -= (float)options.padding;
+ texcoord.y -= (float)options.padding;
XA_ASSERT(texcoord.x >= 0 && texcoord.y >= 0);
XA_ASSERT(isFinite(texcoord.x) && isFinite(texcoord.y));
}
@@ -7908,21 +8916,12 @@ struct Atlas {
}
}
}
- if (options.blockAlign) {
- if (maxResolution == 0) {
- m_width = max(0, atlasSizes[0].x);
- m_height = max(0, atlasSizes[0].y);
- } else {
- m_width = m_height = maxResolution;
- }
+ // Remove padding from outer edges.
+ if (maxResolution == 0) {
+ m_width = max(0, atlasSizes[0].x - (int)options.padding * 2);
+ m_height = max(0, atlasSizes[0].y - (int)options.padding * 2);
} else {
- // Remove padding from outer edges.
- if (maxResolution == 0) {
- m_width = max(0, atlasSizes[0].x - (int)options.padding * 2);
- m_height = max(0, atlasSizes[0].y - (int)options.padding * 2);
- } else {
- m_width = m_height = maxResolution - (int)options.padding * 2;
- }
+ m_width = m_height = maxResolution - (int)options.padding * 2;
}
XA_PRINT(" %dx%d resolution\n", m_width, m_height);
m_utilization.resize(m_bitImages.size());
@@ -7939,7 +8938,8 @@ struct Atlas {
}
if (m_utilization.size() > 1) {
XA_PRINT(" %u: %f%% utilization\n", i, m_utilization[i] * 100.0f);
- } else {
+ }
+ else {
XA_PRINT(" %f%% utilization\n", m_utilization[i] * 100.0f);
}
}
@@ -7962,14 +8962,16 @@ private:
// is occupied at this point. At the end we have many small charts and a large atlas with sparse holes. Finding those holes randomly is slow. A better approach would be to
// start stacking large charts as if they were tetris pieces. Once charts get small try to place them randomly. It may be interesting to try a intermediate strategy, first try
// along one axis and then try exhaustively along that axis.
- bool findChartLocation(const Vector2i &startPosition, bool bruteForce, const BitImage *atlasBitImage, const BitImage *chartBitImage, const BitImage *chartBitImageRotated, int w, int h, int *best_x, int *best_y, int *best_w, int *best_h, int *best_r, bool blockAligned, uint32_t maxResolution, bool allowRotate) {
+ bool findChartLocation(const Vector2i &startPosition, bool bruteForce, const BitImage *atlasBitImage, const BitImage *chartBitImage, const BitImage *chartBitImageRotated, int w, int h, int *best_x, int *best_y, int *best_w, int *best_h, int *best_r, bool blockAligned, uint32_t maxResolution, bool allowRotate)
+ {
const int attempts = 4096;
if (bruteForce || attempts >= w * h)
return findChartLocation_bruteForce(startPosition, atlasBitImage, chartBitImage, chartBitImageRotated, w, h, best_x, best_y, best_w, best_h, best_r, blockAligned, maxResolution, allowRotate);
return findChartLocation_random(atlasBitImage, chartBitImage, chartBitImageRotated, w, h, best_x, best_y, best_w, best_h, best_r, attempts, blockAligned, maxResolution, allowRotate);
}
- bool findChartLocation_bruteForce(const Vector2i &startPosition, const BitImage *atlasBitImage, const BitImage *chartBitImage, const BitImage *chartBitImageRotated, int w, int h, int *best_x, int *best_y, int *best_w, int *best_h, int *best_r, bool blockAligned, uint32_t maxResolution, bool allowRotate) {
+ bool findChartLocation_bruteForce(const Vector2i &startPosition, const BitImage *atlasBitImage, const BitImage *chartBitImage, const BitImage *chartBitImageRotated, int w, int h, int *best_x, int *best_y, int *best_w, int *best_h, int *best_r, bool blockAligned, uint32_t maxResolution, bool allowRotate)
+ {
const int stepSize = blockAligned ? 4 : 1;
int best_metric = INT_MAX;
// Try two different orientations.
@@ -8014,7 +9016,8 @@ private:
return best_metric != INT_MAX;
}
- bool findChartLocation_random(const BitImage *atlasBitImage, const BitImage *chartBitImage, const BitImage *chartBitImageRotated, int w, int h, int *best_x, int *best_y, int *best_w, int *best_h, int *best_r, int minTrialCount, bool blockAligned, uint32_t maxResolution, bool allowRotate) {
+ bool findChartLocation_random(const BitImage *atlasBitImage, const BitImage *chartBitImage, const BitImage *chartBitImageRotated, int w, int h, int *best_x, int *best_y, int *best_w, int *best_h, int *best_r, int minTrialCount, bool blockAligned, uint32_t maxResolution, bool allowRotate)
+ {
bool result = false;
const int BLOCK_SIZE = 4;
int best_metric = INT_MAX;
@@ -8069,7 +9072,8 @@ private:
return result;
}
- void addChart(BitImage *atlasBitImage, const BitImage *chartBitImage, const BitImage *chartBitImageRotated, int atlas_w, int atlas_h, int offset_x, int offset_y, int r) {
+ void addChart(BitImage *atlasBitImage, const BitImage *chartBitImage, const BitImage *chartBitImageRotated, int atlas_w, int atlas_h, int offset_x, int offset_y, int r)
+ {
XA_DEBUG_ASSERT(r == 0 || r == 1);
const BitImage *image = r == 0 ? chartBitImage : chartBitImageRotated;
const int w = image->width();
@@ -8092,7 +9096,8 @@ private:
}
}
- void bilinearExpand(const Chart *chart, BitImage *source, BitImage *dest, BitImage *destRotated, UniformGrid2 &boundaryEdgeGrid) const {
+ void bilinearExpand(const Chart *chart, BitImage *source, BitImage *dest, BitImage *destRotated, UniformGrid2 &boundaryEdgeGrid) const
+ {
boundaryEdgeGrid.reset(chart->vertices, chart->indices);
if (chart->boundaryEdges) {
const uint32_t edgeCount = chart->boundaryEdges->size();
@@ -8147,11 +9152,13 @@ private:
}
}
- struct DrawTriangleCallbackArgs {
+ struct DrawTriangleCallbackArgs
+ {
BitImage *chartBitImage, *chartBitImageRotated;
};
- static bool drawTriangleCallback(void *param, int x, int y) {
+ static bool drawTriangleCallback(void *param, int x, int y)
+ {
auto args = (DrawTriangleCallbackArgs *)param;
args->chartBitImage->set(x, y);
if (args->chartBitImageRotated)
@@ -8173,48 +9180,52 @@ private:
} // namespace pack
} // namespace internal
-struct Context {
+struct Context
+{
Atlas atlas;
- uint32_t meshCount = 0;
internal::Progress *addMeshProgress = nullptr;
internal::TaskGroupHandle addMeshTaskGroup;
internal::param::Atlas paramAtlas;
ProgressFunc progressFunc = nullptr;
void *progressUserData = nullptr;
internal::TaskScheduler *taskScheduler;
+ internal::Array<internal::Mesh *> meshes;
internal::Array<internal::UvMesh *> uvMeshes;
internal::Array<internal::UvMeshInstance *> uvMeshInstances;
};
-Atlas *Create() {
+Atlas *Create()
+{
Context *ctx = XA_NEW(internal::MemTag::Default, Context);
memset(&ctx->atlas, 0, sizeof(Atlas));
ctx->taskScheduler = XA_NEW(internal::MemTag::Default, internal::TaskScheduler);
return &ctx->atlas;
}
-static void DestroyOutputMeshes(Context *ctx) {
+static void DestroyOutputMeshes(Context *ctx)
+{
if (!ctx->atlas.meshes)
return;
for (int i = 0; i < (int)ctx->atlas.meshCount; i++) {
Mesh &mesh = ctx->atlas.meshes[i];
- for (uint32_t j = 0; j < mesh.chartCount; j++) {
- if (mesh.chartArray[j].faceArray)
- XA_FREE(mesh.chartArray[j].faceArray);
- }
- if (mesh.chartArray)
+ if (mesh.chartArray) {
+ for (uint32_t j = 0; j < mesh.chartCount; j++) {
+ if (mesh.chartArray[j].faceArray)
+ XA_FREE(mesh.chartArray[j].faceArray);
+ }
XA_FREE(mesh.chartArray);
+ }
if (mesh.vertexArray)
XA_FREE(mesh.vertexArray);
if (mesh.indexArray)
XA_FREE(mesh.indexArray);
}
- if (ctx->atlas.meshes)
- XA_FREE(ctx->atlas.meshes);
+ XA_FREE(ctx->atlas.meshes);
ctx->atlas.meshes = nullptr;
}
-void Destroy(Atlas *atlas) {
+void Destroy(Atlas *atlas)
+{
XA_DEBUG_ASSERT(atlas);
Context *ctx = (Context *)atlas;
if (atlas->utilization)
@@ -8228,6 +9239,11 @@ void Destroy(Atlas *atlas) {
}
ctx->taskScheduler->~TaskScheduler();
XA_FREE(ctx->taskScheduler);
+ for (uint32_t i = 0; i < ctx->meshes.size(); i++) {
+ internal::Mesh *mesh = ctx->meshes[i];
+ mesh->~Mesh();
+ XA_FREE(mesh);
+ }
for (uint32_t i = 0; i < ctx->uvMeshes.size(); i++) {
internal::UvMesh *mesh = ctx->uvMeshes[i];
for (uint32_t j = 0; j < mesh->charts.size(); j++) {
@@ -8249,12 +9265,14 @@ void Destroy(Atlas *atlas) {
#endif
}
-struct AddMeshTaskArgs {
+struct AddMeshTaskArgs
+{
Context *ctx;
internal::Mesh *mesh;
};
-static void runAddMeshTask(void *userData) {
+static void runAddMeshTask(void *userData)
+{
XA_PROFILE_START(addMeshThread)
auto args = (AddMeshTaskArgs *)userData; // Responsible for freeing this.
internal::Mesh *mesh = args->mesh;
@@ -8268,87 +9286,45 @@ static void runAddMeshTask(void *userData) {
}
if (progress->cancel)
goto cleanup;
- {
- XA_PROFILE_START(addMeshCreateFaceGroups)
- mesh->createFaceGroups();
- XA_PROFILE_END(addMeshCreateFaceGroups)
- }
- if (progress->cancel)
- goto cleanup;
-#if XA_DEBUG_EXPORT_OBJ_SOURCE_MESHES
- char filename[256];
- XA_SPRINTF(filename, sizeof(filename), "debug_mesh_%03u.obj", mesh->id());
- FILE *file;
- XA_FOPEN(file, filename, "w");
- if (file) {
- mesh->writeObjVertices(file);
- // groups
- uint32_t numGroups = 0;
- for (uint32_t i = 0; i < mesh->faceCount(); i++) {
- if (mesh->faceGroupAt(i) != Mesh::kInvalidFaceGroup)
- numGroups = internal::max(numGroups, mesh->faceGroupAt(i) + 1);
- }
- for (uint32_t i = 0; i < numGroups; i++) {
- fprintf(file, "o group_%04d\n", i);
- fprintf(file, "s off\n");
- for (uint32_t f = 0; f < mesh->faceCount(); f++) {
- if (mesh->faceGroupAt(f) == i)
- mesh->writeObjFace(file, f);
- }
- }
- fprintf(file, "o group_ignored\n");
- fprintf(file, "s off\n");
- for (uint32_t f = 0; f < mesh->faceCount(); f++) {
- if (mesh->faceGroupAt(f) == Mesh::kInvalidFaceGroup)
- mesh->writeObjFace(file, f);
- }
- mesh->writeObjBoundaryEges(file);
- fclose(file);
- }
-#endif
- {
- XA_PROFILE_START(addMeshCreateChartGroupsReal)
- args->ctx->paramAtlas.addMesh(args->ctx->taskScheduler, mesh); // addMesh is thread safe
- XA_PROFILE_END(addMeshCreateChartGroupsReal)
- }
- if (progress->cancel)
- goto cleanup;
progress->value++;
progress->update();
cleanup:
- mesh->~Mesh();
- XA_FREE(mesh);
args->~AddMeshTaskArgs();
XA_FREE(args);
XA_PROFILE_END(addMeshThread)
}
-static internal::Vector3 DecodePosition(const MeshDecl &meshDecl, uint32_t index) {
+static internal::Vector3 DecodePosition(const MeshDecl &meshDecl, uint32_t index)
+{
XA_DEBUG_ASSERT(meshDecl.vertexPositionData);
XA_DEBUG_ASSERT(meshDecl.vertexPositionStride > 0);
return *((const internal::Vector3 *)&((const uint8_t *)meshDecl.vertexPositionData)[meshDecl.vertexPositionStride * index]);
}
-static internal::Vector3 DecodeNormal(const MeshDecl &meshDecl, uint32_t index) {
+static internal::Vector3 DecodeNormal(const MeshDecl &meshDecl, uint32_t index)
+{
XA_DEBUG_ASSERT(meshDecl.vertexNormalData);
XA_DEBUG_ASSERT(meshDecl.vertexNormalStride > 0);
return *((const internal::Vector3 *)&((const uint8_t *)meshDecl.vertexNormalData)[meshDecl.vertexNormalStride * index]);
}
-static internal::Vector2 DecodeUv(const MeshDecl &meshDecl, uint32_t index) {
+static internal::Vector2 DecodeUv(const MeshDecl &meshDecl, uint32_t index)
+{
XA_DEBUG_ASSERT(meshDecl.vertexUvData);
XA_DEBUG_ASSERT(meshDecl.vertexUvStride > 0);
return *((const internal::Vector2 *)&((const uint8_t *)meshDecl.vertexUvData)[meshDecl.vertexUvStride * index]);
}
-static uint32_t DecodeIndex(IndexFormat::Enum format, const void *indexData, int32_t offset, uint32_t i) {
+static uint32_t DecodeIndex(IndexFormat::Enum format, const void *indexData, int32_t offset, uint32_t i)
+{
XA_DEBUG_ASSERT(indexData);
if (format == IndexFormat::UInt16)
return uint16_t((int32_t)((const uint16_t *)indexData)[i] + offset);
return uint32_t((int32_t)((const uint32_t *)indexData)[i] + offset);
}
-AddMeshError::Enum AddMesh(Atlas *atlas, const MeshDecl &meshDecl, uint32_t meshCountHint) {
+AddMeshError::Enum AddMesh(Atlas *atlas, const MeshDecl &meshDecl, uint32_t meshCountHint)
+{
XA_DEBUG_ASSERT(atlas);
if (!atlas) {
XA_PRINT_WARNING("AddMesh: atlas is null.\n");
@@ -8360,19 +9336,20 @@ AddMeshError::Enum AddMesh(Atlas *atlas, const MeshDecl &meshDecl, uint32_t mesh
return AddMeshError::Error;
}
#if XA_PROFILE
- if (ctx->meshCount == 0)
+ if (ctx->meshes.isEmpty())
internal::s_profile.addMeshReal = clock();
#endif
// Don't know how many times AddMesh will be called, so progress needs to adjusted each time.
if (!ctx->addMeshProgress) {
ctx->addMeshProgress = XA_NEW_ARGS(internal::MemTag::Default, internal::Progress, ProgressCategory::AddMesh, ctx->progressFunc, ctx->progressUserData, 1);
- } else {
- ctx->addMeshProgress->setMaxValue(internal::max(ctx->meshCount + 1, meshCountHint));
+ }
+ else {
+ ctx->addMeshProgress->setMaxValue(internal::max(ctx->meshes.size() + 1, meshCountHint));
}
XA_PROFILE_START(addMeshCopyData)
const bool hasIndices = meshDecl.indexCount > 0;
const uint32_t indexCount = hasIndices ? meshDecl.indexCount : meshDecl.vertexCount;
- XA_PRINT("Adding mesh %d: %u vertices, %u triangles\n", ctx->meshCount, meshDecl.vertexCount, indexCount / 3);
+ XA_PRINT("Adding mesh %d: %u vertices, %u triangles\n", ctx->meshes.size(), meshDecl.vertexCount, indexCount / 3);
// Expecting triangle faces.
if ((indexCount % 3) != 0)
return AddMeshError::InvalidIndexCount;
@@ -8384,10 +9361,10 @@ AddMeshError::Enum AddMesh(Atlas *atlas, const MeshDecl &meshDecl, uint32_t mesh
return AddMeshError::IndexOutOfRange;
}
}
- uint32_t meshFlags = internal::MeshFlags::HasFaceGroups | internal::MeshFlags::HasIgnoredFaces;
+ uint32_t meshFlags = internal::MeshFlags::HasIgnoredFaces;
if (meshDecl.vertexNormalData)
meshFlags |= internal::MeshFlags::HasNormals;
- internal::Mesh *mesh = XA_NEW_ARGS(internal::MemTag::Mesh, internal::Mesh, meshDecl.epsilon, meshDecl.vertexCount, indexCount / 3, meshFlags, ctx->meshCount);
+ internal::Mesh *mesh = XA_NEW_ARGS(internal::MemTag::Mesh, internal::Mesh, meshDecl.epsilon, meshDecl.vertexCount, indexCount / 3, meshFlags, ctx->meshes.size());
for (uint32_t i = 0; i < meshDecl.vertexCount; i++) {
internal::Vector3 normal(0.0f);
internal::Vector2 texcoord(0.0f);
@@ -8397,6 +9374,8 @@ AddMeshError::Enum AddMesh(Atlas *atlas, const MeshDecl &meshDecl, uint32_t mesh
texcoord = DecodeUv(meshDecl, i);
mesh->addVertex(DecodePosition(meshDecl, i), normal, texcoord);
}
+ const uint32_t kMaxWarnings = 50;
+ uint32_t warningCount = 0;
for (uint32_t i = 0; i < indexCount / 3; i++) {
uint32_t tri[3];
for (int j = 0; j < 3; j++)
@@ -8408,14 +9387,16 @@ AddMeshError::Enum AddMesh(Atlas *atlas, const MeshDecl &meshDecl, uint32_t mesh
const uint32_t index2 = tri[(j + 1) % 3];
if (index1 == index2) {
ignore = true;
- XA_PRINT(" Degenerate edge: index %d, index %d\n", index1, index2);
+ if (++warningCount <= kMaxWarnings)
+ XA_PRINT(" Degenerate edge: index %d, index %d\n", index1, index2);
break;
}
const internal::Vector3 &pos1 = mesh->position(index1);
const internal::Vector3 &pos2 = mesh->position(index2);
if (internal::length(pos2 - pos1) <= 0.0f) {
ignore = true;
- XA_PRINT(" Zero length edge: index %d position (%g %g %g), index %d position (%g %g %g)\n", index1, pos1.x, pos1.y, pos1.z, index2, pos2.x, pos2.y, pos2.z);
+ if (++warningCount <= kMaxWarnings)
+ XA_PRINT(" Zero length edge: index %d position (%g %g %g), index %d position (%g %g %g)\n", index1, pos1.x, pos1.y, pos1.z, index2, pos2.x, pos2.y, pos2.z);
break;
}
}
@@ -8424,14 +9405,16 @@ AddMeshError::Enum AddMesh(Atlas *atlas, const MeshDecl &meshDecl, uint32_t mesh
for (int j = 0; j < 3; j++) {
const internal::Vector3 &pos = mesh->position(tri[j]);
if (internal::isNan(pos.x) || internal::isNan(pos.y) || internal::isNan(pos.z)) {
- XA_PRINT(" NAN position in face: %d\n", i);
+ if (++warningCount <= kMaxWarnings)
+ XA_PRINT(" NAN position in face: %d\n", i);
ignore = true;
break;
}
if (meshDecl.vertexNormalData) {
const internal::Vector3 &normal = mesh->normal(tri[j]);
if (internal::isNan(normal.x) || internal::isNan(normal.y) || internal::isNan(normal.z)) {
- XA_PRINT(" NAN normal in face: %d\n", i);
+ if (++warningCount <= kMaxWarnings)
+ XA_PRINT(" NAN normal in face: %d\n", i);
ignore = true;
break;
}
@@ -8439,7 +9422,8 @@ AddMeshError::Enum AddMesh(Atlas *atlas, const MeshDecl &meshDecl, uint32_t mesh
if (meshDecl.vertexUvData) {
const internal::Vector2 &uv = mesh->texcoord(tri[j]);
if (internal::isNan(uv.x) || internal::isNan(uv.y)) {
- XA_PRINT(" NAN texture coordinate in face: %d\n", i);
+ if (++warningCount <= kMaxWarnings)
+ XA_PRINT(" NAN texture coordinate in face: %d\n", i);
ignore = true;
break;
}
@@ -8455,20 +9439,26 @@ AddMeshError::Enum AddMesh(Atlas *atlas, const MeshDecl &meshDecl, uint32_t mesh
area = internal::length(internal::cross(b - a, c - a)) * 0.5f;
if (area <= internal::kAreaEpsilon) {
ignore = true;
- XA_PRINT(" Zero area face: %d, indices (%d %d %d), area is %f\n", i, tri[0], tri[1], tri[2], area);
+ if (++warningCount <= kMaxWarnings)
+ XA_PRINT(" Zero area face: %d, indices (%d %d %d), area is %f\n", i, tri[0], tri[1], tri[2], area);
}
}
if (!ignore) {
if (internal::equal(a, b, meshDecl.epsilon) || internal::equal(a, c, meshDecl.epsilon) || internal::equal(b, c, meshDecl.epsilon)) {
ignore = true;
- XA_PRINT(" Degenerate face: %d, area is %f\n", i, area);
+ if (++warningCount <= kMaxWarnings)
+ XA_PRINT(" Degenerate face: %d, area is %f\n", i, area);
}
}
if (meshDecl.faceIgnoreData && meshDecl.faceIgnoreData[i])
ignore = true;
mesh->addFace(tri[0], tri[1], tri[2], ignore);
}
+ if (warningCount > kMaxWarnings)
+ XA_PRINT(" %u additional warnings truncated\n", warningCount - kMaxWarnings);
XA_PROFILE_END(addMeshCopyData)
+ ctx->meshes.push_back(mesh);
+ ctx->paramAtlas.addMesh(mesh);
if (ctx->addMeshTaskGroup.value == UINT32_MAX)
ctx->addMeshTaskGroup = ctx->taskScheduler->createTaskGroup();
AddMeshTaskArgs *taskArgs = XA_NEW(internal::MemTag::Default, AddMeshTaskArgs); // The task frees this.
@@ -8478,11 +9468,11 @@ AddMeshError::Enum AddMesh(Atlas *atlas, const MeshDecl &meshDecl, uint32_t mesh
task.userData = taskArgs;
task.func = runAddMeshTask;
ctx->taskScheduler->run(ctx->addMeshTaskGroup, task);
- ctx->meshCount++;
return AddMeshError::Success;
}
-void AddMeshJoin(Atlas *atlas) {
+void AddMeshJoin(Atlas *atlas)
+{
XA_DEBUG_ASSERT(atlas);
if (!atlas) {
XA_PRINT_WARNING("AddMeshJoin: atlas is null.\n");
@@ -8495,41 +9485,43 @@ void AddMeshJoin(Atlas *atlas) {
ctx->addMeshProgress->~Progress();
XA_FREE(ctx->addMeshProgress);
ctx->addMeshProgress = nullptr;
- ctx->paramAtlas.sortChartGroups();
#if XA_PROFILE
- XA_PRINT("Added %u meshes\n", ctx->meshCount);
+ XA_PRINT("Added %u meshes\n", ctx->meshes.size());
internal::s_profile.addMeshReal = clock() - internal::s_profile.addMeshReal;
#endif
XA_PROFILE_PRINT_AND_RESET(" Total (real): ", addMeshReal)
XA_PROFILE_PRINT_AND_RESET(" Copy data: ", addMeshCopyData)
XA_PROFILE_PRINT_AND_RESET(" Total (thread): ", addMeshThread)
XA_PROFILE_PRINT_AND_RESET(" Create colocals: ", addMeshCreateColocals)
- XA_PROFILE_PRINT_AND_RESET(" Create face groups: ", addMeshCreateFaceGroups)
- XA_PROFILE_PRINT_AND_RESET(" Create chart groups (real): ", addMeshCreateChartGroupsReal)
- XA_PROFILE_PRINT_AND_RESET(" Create chart groups (thread): ", addMeshCreateChartGroupsThread)
+#if XA_PROFILE_ALLOC
+ XA_PROFILE_PRINT_AND_RESET(" Alloc: ", alloc)
+#endif
XA_PRINT_MEM_USAGE
+#if XA_DEBUG_EXPORT_OBJ_FACE_GROUPS
+ internal::param::s_faceGroupsCurrentVertex = 0;
+#endif
}
-struct EdgeKey {
+struct EdgeKey
+{
EdgeKey() {}
- EdgeKey(const EdgeKey &k) :
- v0(k.v0), v1(k.v1) {}
- EdgeKey(uint32_t v0, uint32_t v1) :
- v0(v0), v1(v1) {}
+ EdgeKey(const EdgeKey &k) : v0(k.v0), v1(k.v1) {}
+ EdgeKey(uint32_t v0, uint32_t v1) : v0(v0), v1(v1) {}
bool operator==(const EdgeKey &k) const { return v0 == k.v0 && v1 == k.v1; }
uint32_t v0;
uint32_t v1;
};
-AddMeshError::Enum AddUvMesh(Atlas *atlas, const UvMeshDecl &decl) {
+AddMeshError::Enum AddUvMesh(Atlas *atlas, const UvMeshDecl &decl)
+{
XA_DEBUG_ASSERT(atlas);
if (!atlas) {
XA_PRINT_WARNING("AddUvMesh: atlas is null.\n");
return AddMeshError::Error;
}
Context *ctx = (Context *)atlas;
- if (ctx->meshCount > 0) {
+ if (!ctx->meshes.isEmpty()) {
XA_PRINT_WARNING("AddUvMesh: Meshes and UV meshes cannot be added to the same atlas.\n");
return AddMeshError::Error;
}
@@ -8632,7 +9624,8 @@ AddMeshError::Enum AddUvMesh(Atlas *atlas, const UvMeshDecl &decl) {
return AddMeshError::Success;
}
-void ComputeCharts(Atlas *atlas, ChartOptions chartOptions) {
+void ComputeCharts(Atlas *atlas, ChartOptions options)
+{
if (!atlas) {
XA_PRINT_WARNING("ComputeCharts: atlas is null.\n");
return;
@@ -8643,69 +9636,66 @@ void ComputeCharts(Atlas *atlas, ChartOptions chartOptions) {
return;
}
AddMeshJoin(atlas);
- if (ctx->meshCount == 0) {
+ if (ctx->meshes.isEmpty()) {
XA_PRINT_WARNING("ComputeCharts: No meshes. Call AddMesh first.\n");
return;
}
XA_PRINT("Computing charts\n");
- uint32_t chartCount = 0, chartsWithHolesCount = 0, holesCount = 0, chartsWithTJunctionsCount = 0, tJunctionsCount = 0;
XA_PROFILE_START(computeChartsReal)
- if (!ctx->paramAtlas.computeCharts(ctx->taskScheduler, chartOptions, ctx->progressFunc, ctx->progressUserData)) {
+ if (!ctx->paramAtlas.computeCharts(ctx->taskScheduler, options, ctx->progressFunc, ctx->progressUserData)) {
XA_PRINT(" Cancelled by user\n");
return;
}
XA_PROFILE_END(computeChartsReal)
- // Count charts and print warnings.
- for (uint32_t i = 0; i < ctx->meshCount; i++) {
+ // Count charts.
+ uint32_t chartCount = 0;
+ const uint32_t meshCount = ctx->meshes.size();
+ for (uint32_t i = 0; i < meshCount; i++) {
for (uint32_t j = 0; j < ctx->paramAtlas.chartGroupCount(i); j++) {
const internal::param::ChartGroup *chartGroup = ctx->paramAtlas.chartGroupAt(i, j);
- if (chartGroup->isVertexMap())
- continue;
- for (uint32_t k = 0; k < chartGroup->chartCount(); k++) {
- const internal::param::Chart *chart = chartGroup->chartAt(k);
-#if XA_PRINT_CHART_WARNINGS
- if (chart->warningFlags() & internal::param::ChartWarningFlags::CloseHolesFailed)
- XA_PRINT_WARNING(" Chart %u (mesh %u, group %u, id %u): failed to close holes\n", chartCount, i, j, k);
- if (chart->warningFlags() & internal::param::ChartWarningFlags::FixTJunctionsDuplicatedEdge)
- XA_PRINT_WARNING(" Chart %u (mesh %u, group %u, id %u): fixing t-junctions created non-manifold geometry\n", chartCount, i, j, k);
- if (chart->warningFlags() & internal::param::ChartWarningFlags::FixTJunctionsFailed)
- XA_PRINT_WARNING(" Chart %u (mesh %u, group %u, id %u): fixing t-junctions failed\n", chartCount, i, j, k);
- if (chart->warningFlags() & internal::param::ChartWarningFlags::TriangulateDuplicatedEdge)
- XA_PRINT_WARNING(" Chart %u (mesh %u, group %u, id %u): triangulation created non-manifold geometry\n", chartCount, i, j, k);
-#endif
- holesCount += chart->closedHolesCount();
- if (chart->closedHolesCount() > 0)
- chartsWithHolesCount++;
- tJunctionsCount += chart->fixedTJunctionsCount();
- if (chart->fixedTJunctionsCount() > 0)
- chartsWithTJunctionsCount++;
- chartCount++;
- }
+ chartCount += chartGroup->segmentChartCount();
}
}
- if (holesCount > 0)
- XA_PRINT(" Closed %u holes in %u charts\n", holesCount, chartsWithHolesCount);
- if (tJunctionsCount > 0)
- XA_PRINT(" Fixed %u t-junctions in %u charts\n", tJunctionsCount, chartsWithTJunctionsCount);
XA_PRINT(" %u charts\n", chartCount);
+#if XA_PROFILE
+ XA_PRINT(" Chart groups\n");
+ uint32_t chartGroupCount = 0;
+ for (uint32_t i = 0; i < meshCount; i++) {
+ XA_PRINT(" Mesh %u: %u chart groups\n", i, ctx->paramAtlas.chartGroupCount(i));
+ chartGroupCount += ctx->paramAtlas.chartGroupCount(i);
+ }
+ XA_PRINT(" %u total\n", chartGroupCount);
+#endif
XA_PROFILE_PRINT_AND_RESET(" Total (real): ", computeChartsReal)
XA_PROFILE_PRINT_AND_RESET(" Total (thread): ", computeChartsThread)
- XA_PROFILE_PRINT_AND_RESET(" Build atlas: ", buildAtlas)
- XA_PROFILE_PRINT_AND_RESET(" Init: ", buildAtlasInit)
- XA_PROFILE_PRINT_AND_RESET(" Place seeds: ", buildAtlasPlaceSeeds)
- XA_PROFILE_PRINT_AND_RESET(" Relocate seeds: ", buildAtlasRelocateSeeds)
- XA_PROFILE_PRINT_AND_RESET(" Reset charts: ", buildAtlasResetCharts)
- XA_PROFILE_PRINT_AND_RESET(" Grow charts: ", buildAtlasGrowCharts)
- XA_PROFILE_PRINT_AND_RESET(" Merge charts: ", buildAtlasMergeCharts)
- XA_PROFILE_PRINT_AND_RESET(" Fill holes: ", buildAtlasFillHoles)
- XA_PROFILE_PRINT_AND_RESET(" Create chart meshes (real): ", createChartMeshesReal)
- XA_PROFILE_PRINT_AND_RESET(" Create chart meshes (thread): ", createChartMeshesThread)
- XA_PROFILE_PRINT_AND_RESET(" Fix t-junctions: ", fixChartMeshTJunctions)
- XA_PROFILE_PRINT_AND_RESET(" Close holes: ", closeChartMeshHoles)
+ XA_PROFILE_PRINT_AND_RESET(" Create face groups: ", createFaceGroups)
+ XA_PROFILE_PRINT_AND_RESET(" Extract invalid mesh geometry: ", extractInvalidMeshGeometry)
+ XA_PROFILE_PRINT_AND_RESET(" Chart group compute charts (real): ", chartGroupComputeChartsReal)
+ XA_PROFILE_PRINT_AND_RESET(" Chart group compute charts (thread): ", chartGroupComputeChartsThread)
+ XA_PROFILE_PRINT_AND_RESET(" Create chart group mesh: ", createChartGroupMesh)
+ XA_PROFILE_PRINT_AND_RESET(" Create colocals: ", createChartGroupMeshColocals)
+ XA_PROFILE_PRINT_AND_RESET(" Create boundaries: ", createChartGroupMeshBoundaries)
+ XA_PROFILE_PRINT_AND_RESET(" Build atlas: ", buildAtlas)
+ XA_PROFILE_PRINT_AND_RESET(" Init: ", buildAtlasInit)
+ XA_PROFILE_PRINT_AND_RESET(" Planar charts: ", planarCharts)
+ XA_PROFILE_PRINT_AND_RESET(" Clustered charts: ", clusteredCharts)
+ XA_PROFILE_PRINT_AND_RESET(" Place seeds: ", clusteredChartsPlaceSeeds)
+ XA_PROFILE_PRINT_AND_RESET(" Boundary intersection: ", clusteredChartsPlaceSeedsBoundaryIntersection)
+ XA_PROFILE_PRINT_AND_RESET(" Relocate seeds: ", clusteredChartsRelocateSeeds)
+ XA_PROFILE_PRINT_AND_RESET(" Reset: ", clusteredChartsReset)
+ XA_PROFILE_PRINT_AND_RESET(" Grow: ", clusteredChartsGrow)
+ XA_PROFILE_PRINT_AND_RESET(" Boundary intersection: ", clusteredChartsGrowBoundaryIntersection)
+ XA_PROFILE_PRINT_AND_RESET(" Merge: ", clusteredChartsMerge)
+ XA_PROFILE_PRINT_AND_RESET(" Fill holes: ", clusteredChartsFillHoles)
+ XA_PROFILE_PRINT_AND_RESET(" Copy chart faces: ", copyChartFaces)
+#if XA_PROFILE_ALLOC
+ XA_PROFILE_PRINT_AND_RESET(" Alloc: ", alloc)
+#endif
XA_PRINT_MEM_USAGE
}
-void ParameterizeCharts(Atlas *atlas, ParameterizeFunc func) {
+void ParameterizeCharts(Atlas *atlas, ParameterizeOptions options)
+{
if (!atlas) {
XA_PRINT_WARNING("ParameterizeCharts: atlas is null.\n");
return;
@@ -8734,19 +9724,34 @@ void ParameterizeCharts(Atlas *atlas, ParameterizeFunc func) {
DestroyOutputMeshes(ctx);
XA_PRINT("Parameterizing charts\n");
XA_PROFILE_START(parameterizeChartsReal)
- if (!ctx->paramAtlas.parameterizeCharts(ctx->taskScheduler, func, ctx->progressFunc, ctx->progressUserData)) {
+ if (!ctx->paramAtlas.parameterizeCharts(ctx->taskScheduler, options, ctx->progressFunc, ctx->progressUserData)) {
XA_PRINT(" Cancelled by user\n");
- return;
+ return;
}
XA_PROFILE_END(parameterizeChartsReal)
- uint32_t chartCount = 0, orthoChartsCount = 0, planarChartsCount = 0, lscmChartsCount = 0, piecewiseChartsCount = 0, chartsAddedCount = 0, chartsDeletedCount = 0;
- for (uint32_t i = 0; i < ctx->meshCount; i++) {
+ const uint32_t meshCount = ctx->meshes.size();
+ uint32_t chartCount = 0, chartsWithHolesCount = 0, holesCount = 0, chartsWithTJunctionsCount = 0, tJunctionsCount = 0, orthoChartsCount = 0, planarChartsCount = 0, lscmChartsCount = 0, piecewiseChartsCount = 0, chartsAddedCount = 0, chartsDeletedCount = 0;
+ for (uint32_t i = 0; i < meshCount; i++) {
for (uint32_t j = 0; j < ctx->paramAtlas.chartGroupCount(i); j++) {
const internal::param::ChartGroup *chartGroup = ctx->paramAtlas.chartGroupAt(i, j);
- if (chartGroup->isVertexMap())
- continue;
for (uint32_t k = 0; k < chartGroup->chartCount(); k++) {
const internal::param::Chart *chart = chartGroup->chartAt(k);
+#if XA_PRINT_CHART_WARNINGS
+ if (chart->warningFlags() & internal::param::ChartWarningFlags::CloseHolesFailed)
+ XA_PRINT_WARNING(" Chart %u (mesh %u, group %u, id %u): failed to close holes\n", chartCount, i, j, k);
+ if (chart->warningFlags() & internal::param::ChartWarningFlags::FixTJunctionsDuplicatedEdge)
+ XA_PRINT_WARNING(" Chart %u (mesh %u, group %u, id %u): fixing t-junctions created non-manifold geometry\n", chartCount, i, j, k);
+ if (chart->warningFlags() & internal::param::ChartWarningFlags::FixTJunctionsFailed)
+ XA_PRINT_WARNING(" Chart %u (mesh %u, group %u, id %u): fixing t-junctions failed\n", chartCount, i, j, k);
+ if (chart->warningFlags() & internal::param::ChartWarningFlags::TriangulateDuplicatedEdge)
+ XA_PRINT_WARNING(" Chart %u (mesh %u, group %u, id %u): triangulation created non-manifold geometry\n", chartCount, i, j, k);
+#endif
+ holesCount += chart->closedHolesCount();
+ if (chart->closedHolesCount() > 0)
+ chartsWithHolesCount++;
+ tJunctionsCount += chart->fixedTJunctionsCount();
+ if (chart->fixedTJunctionsCount() > 0)
+ chartsWithTJunctionsCount++;
if (chart->type() == ChartType::Planar)
planarChartsCount++;
else if (chart->type() == ChartType::Ortho)
@@ -8761,19 +9766,21 @@ void ParameterizeCharts(Atlas *atlas, ParameterizeFunc func) {
chartsDeletedCount += chartGroup->paramDeletedChartsCount();
}
}
+ if (holesCount > 0)
+ XA_PRINT(" %u holes closed in %u charts\n", holesCount, chartsWithHolesCount);
+ if (tJunctionsCount > 0)
+ XA_PRINT(" %u t-junctions fixed in %u charts\n", tJunctionsCount, chartsWithTJunctionsCount);
XA_PRINT(" %u planar charts, %u ortho charts, %u LSCM charts, %u piecewise charts\n", planarChartsCount, orthoChartsCount, lscmChartsCount, piecewiseChartsCount);
if (chartsDeletedCount > 0) {
XA_PRINT(" %u charts with invalid parameterizations replaced with %u new charts\n", chartsDeletedCount, chartsAddedCount);
XA_PRINT(" %u charts\n", chartCount);
}
uint32_t chartIndex = 0, invalidParamCount = 0;
- for (uint32_t i = 0; i < ctx->meshCount; i++) {
+ for (uint32_t i = 0; i < meshCount; i++) {
for (uint32_t j = 0; j < ctx->paramAtlas.chartGroupCount(i); j++) {
const internal::param::ChartGroup *chartGroup = ctx->paramAtlas.chartGroupAt(i, j);
- if (chartGroup->isVertexMap())
- continue;
for (uint32_t k = 0; k < chartGroup->chartCount(); k++) {
- const internal::param::Chart *chart = chartGroup->chartAt(k);
+ internal::param::Chart *chart = chartGroup->chartAt(k);
const internal::param::Quality &quality = chart->quality();
#if XA_DEBUG_EXPORT_OBJ_CHARTS_AFTER_PARAMETERIZATION
{
@@ -8782,7 +9789,6 @@ void ParameterizeCharts(Atlas *atlas, ParameterizeFunc func) {
chart->unifiedMesh()->writeObjFile(filename);
}
#endif
- bool invalid = false;
const char *type = "LSCM";
if (chart->type() == ChartType::Planar)
type = "planar";
@@ -8790,18 +9796,15 @@ void ParameterizeCharts(Atlas *atlas, ParameterizeFunc func) {
type = "ortho";
else if (chart->type() == ChartType::Piecewise)
type = "piecewise";
- if (quality.boundaryIntersection) {
- invalid = true;
- XA_PRINT_WARNING(" Chart %u (mesh %u, group %u, id %u) (%s): invalid parameterization, self-intersecting boundary.\n", chartIndex, i, j, k, type);
- }
- if (quality.flippedTriangleCount > 0) {
- invalid = true;
- XA_PRINT_WARNING(" Chart %u (mesh %u, group %u, id %u) (%s): invalid parameterization, %u / %u flipped triangles.\n", chartIndex, i, j, k, type, quality.flippedTriangleCount, quality.totalTriangleCount);
- }
- if (invalid)
+ if (chart->isInvalid()) {
+ if (quality.boundaryIntersection) {
+ XA_PRINT_WARNING(" Chart %u (mesh %u, group %u, id %u) (%s): invalid parameterization, self-intersecting boundary.\n", chartIndex, i, j, k, type);
+ }
+ if (quality.flippedTriangleCount > 0) {
+ XA_PRINT_WARNING(" Chart %u (mesh %u, group %u, id %u) (%s): invalid parameterization, %u / %u flipped triangles.\n", chartIndex, i, j, k, type, quality.flippedTriangleCount, quality.totalTriangleCount);
+ }
invalidParamCount++;
#if XA_DEBUG_EXPORT_OBJ_INVALID_PARAMETERIZATION
- if (invalid) {
char filename[256];
XA_SPRINTF(filename, sizeof(filename), "debug_chart_%03u_invalid_parameterization.obj", chartIndex);
const internal::Mesh *mesh = chart->unifiedMesh();
@@ -8822,8 +9825,8 @@ void ParameterizeCharts(Atlas *atlas, ParameterizeFunc func) {
mesh->writeObjLinkedBoundaries(file);
fclose(file);
}
- }
#endif
+ }
chartIndex++;
}
}
@@ -8832,20 +9835,30 @@ void ParameterizeCharts(Atlas *atlas, ParameterizeFunc func) {
XA_PRINT_WARNING(" %u charts with invalid parameterizations\n", invalidParamCount);
XA_PROFILE_PRINT_AND_RESET(" Total (real): ", parameterizeChartsReal)
XA_PROFILE_PRINT_AND_RESET(" Total (thread): ", parameterizeChartsThread)
+ XA_PROFILE_PRINT_AND_RESET(" Create chart mesh: ", createChartMesh)
+ XA_PROFILE_PRINT_AND_RESET(" Fix t-junctions: ", fixChartMeshTJunctions)
+ XA_PROFILE_PRINT_AND_RESET(" Close holes: ", closeChartMeshHoles)
XA_PROFILE_PRINT_AND_RESET(" Orthogonal: ", parameterizeChartsOrthogonal)
XA_PROFILE_PRINT_AND_RESET(" LSCM: ", parameterizeChartsLSCM)
+ XA_PROFILE_PRINT_AND_RESET(" Recompute: ", parameterizeChartsRecompute)
+ XA_PROFILE_PRINT_AND_RESET(" Piecewise: ", parameterizeChartsPiecewise)
+ XA_PROFILE_PRINT_AND_RESET(" Boundary intersection: ", parameterizeChartsPiecewiseBoundaryIntersection)
XA_PROFILE_PRINT_AND_RESET(" Evaluate quality: ", parameterizeChartsEvaluateQuality)
+#if XA_PROFILE_ALLOC
+ XA_PROFILE_PRINT_AND_RESET(" Alloc: ", alloc)
+#endif
XA_PRINT_MEM_USAGE
}
-void PackCharts(Atlas *atlas, PackOptions packOptions) {
+void PackCharts(Atlas *atlas, PackOptions packOptions)
+{
// Validate arguments and context state.
if (!atlas) {
XA_PRINT_WARNING("PackCharts: atlas is null.\n");
return;
}
Context *ctx = (Context *)atlas;
- if (ctx->meshCount == 0 && ctx->uvMeshInstances.isEmpty()) {
+ if (ctx->meshes.isEmpty() && ctx->uvMeshInstances.isEmpty()) {
XA_PRINT_WARNING("PackCharts: No meshes. Call AddMesh or AddUvMesh first.\n");
return;
}
@@ -8880,7 +9893,8 @@ void PackCharts(Atlas *atlas, PackOptions packOptions) {
if (!ctx->uvMeshInstances.isEmpty()) {
for (uint32_t i = 0; i < ctx->uvMeshInstances.size(); i++)
packAtlas.addUvMeshCharts(ctx->uvMeshInstances[i]);
- } else
+ }
+ else
packAtlas.addCharts(ctx->taskScheduler, &ctx->paramAtlas);
XA_PROFILE_END(packChartsAddCharts)
XA_PROFILE_START(packCharts)
@@ -8901,7 +9915,7 @@ void PackCharts(Atlas *atlas, PackOptions packOptions) {
if (packOptions.createImage) {
atlas->image = XA_ALLOC_ARRAY(internal::MemTag::Default, uint32_t, atlas->atlasCount * atlas->width * atlas->height);
for (uint32_t i = 0; i < atlas->atlasCount; i++)
- packAtlas.getImages()[i]->copyTo(&atlas->image[atlas->width * atlas->height * i], atlas->width, atlas->height, packOptions.blockAlign ? 0 : packOptions.padding);
+ packAtlas.getImages()[i]->copyTo(&atlas->image[atlas->width * atlas->height * i], atlas->width, atlas->height, packOptions.padding);
}
XA_PROFILE_PRINT_AND_RESET(" Total: ", packCharts)
XA_PROFILE_PRINT_AND_RESET(" Add charts (real): ", packChartsAddCharts)
@@ -8911,6 +9925,9 @@ void PackCharts(Atlas *atlas, PackOptions packOptions) {
XA_PROFILE_PRINT_AND_RESET(" Dilate (padding): ", packChartsDilate)
XA_PROFILE_PRINT_AND_RESET(" Find location: ", packChartsFindLocation)
XA_PROFILE_PRINT_AND_RESET(" Blit: ", packChartsBlit)
+#if XA_PROFILE_ALLOC
+ XA_PROFILE_PRINT_AND_RESET(" Alloc: ", alloc)
+#endif
XA_PRINT_MEM_USAGE
XA_PRINT("Building output meshes\n");
XA_PROFILE_START(buildOutputMeshes)
@@ -8920,91 +9937,92 @@ void PackCharts(Atlas *atlas, PackOptions packOptions) {
return;
}
if (ctx->uvMeshInstances.isEmpty())
- atlas->meshCount = ctx->meshCount;
+ atlas->meshCount = ctx->meshes.size();
else
atlas->meshCount = ctx->uvMeshInstances.size();
atlas->meshes = XA_ALLOC_ARRAY(internal::MemTag::Default, Mesh, atlas->meshCount);
memset(atlas->meshes, 0, sizeof(Mesh) * atlas->meshCount);
if (ctx->uvMeshInstances.isEmpty()) {
uint32_t chartIndex = 0;
- for (uint32_t i = 0; i < ctx->meshCount; i++) {
+ for (uint32_t i = 0; i < atlas->meshCount; i++) {
Mesh &outputMesh = atlas->meshes[i];
- // Count and alloc arrays. Ignore vertex mapped chart groups in Mesh::chartCount, since they're ignored faces.
+ // Count and alloc arrays.
+ const internal::param::InvalidMeshGeometry &invalid = ctx->paramAtlas.invalidMeshGeometry(i);
+ outputMesh.vertexCount += invalid.vertices().length;
+ outputMesh.indexCount += invalid.faces().length * 3;
for (uint32_t cg = 0; cg < ctx->paramAtlas.chartGroupCount(i); cg++) {
const internal::param::ChartGroup *chartGroup = ctx->paramAtlas.chartGroupAt(i, cg);
- if (chartGroup->isVertexMap()) {
- outputMesh.vertexCount += chartGroup->mesh()->vertexCount();
- outputMesh.indexCount += chartGroup->mesh()->faceCount() * 3;
- } else {
- for (uint32_t c = 0; c < chartGroup->chartCount(); c++) {
- const internal::param::Chart *chart = chartGroup->chartAt(c);
- outputMesh.vertexCount += chart->mesh()->vertexCount();
- outputMesh.indexCount += chart->mesh()->faceCount() * 3;
- outputMesh.chartCount++;
- }
+ for (uint32_t c = 0; c < chartGroup->chartCount(); c++) {
+ const internal::param::Chart *chart = chartGroup->chartAt(c);
+ outputMesh.vertexCount += chart->mesh()->vertexCount();
+ outputMesh.indexCount += chart->mesh()->faceCount() * 3;
+ outputMesh.chartCount++;
}
}
outputMesh.vertexArray = XA_ALLOC_ARRAY(internal::MemTag::Default, Vertex, outputMesh.vertexCount);
outputMesh.indexArray = XA_ALLOC_ARRAY(internal::MemTag::Default, uint32_t, outputMesh.indexCount);
outputMesh.chartArray = XA_ALLOC_ARRAY(internal::MemTag::Default, Chart, outputMesh.chartCount);
- XA_PRINT(" mesh %u: %u vertices, %u triangles, %u charts\n", i, outputMesh.vertexCount, outputMesh.indexCount / 3, outputMesh.chartCount);
+ XA_PRINT(" Mesh %u: %u vertices, %u triangles, %u charts\n", i, outputMesh.vertexCount, outputMesh.indexCount / 3, outputMesh.chartCount);
// Copy mesh data.
- uint32_t firstVertex = 0, meshChartIndex = 0;
+ uint32_t firstVertex = 0;
+ {
+ const internal::param::InvalidMeshGeometry &mesh = ctx->paramAtlas.invalidMeshGeometry(i);
+ internal::ConstArrayView<uint32_t> faces = mesh.faces();
+ internal::ConstArrayView<uint32_t> indices = mesh.indices();
+ internal::ConstArrayView<uint32_t> vertices = mesh.vertices();
+ // Vertices.
+ for (uint32_t v = 0; v < vertices.length; v++) {
+ Vertex &vertex = outputMesh.vertexArray[v];
+ vertex.atlasIndex = -1;
+ vertex.chartIndex = -1;
+ vertex.uv[0] = vertex.uv[1] = 0.0f;
+ vertex.xref = vertices[v];
+ }
+ // Indices.
+ for (uint32_t f = 0; f < faces.length; f++) {
+ const uint32_t indexOffset = faces[f] * 3;
+ for (uint32_t j = 0; j < 3; j++)
+ outputMesh.indexArray[indexOffset + j] = indices[f * 3 + j];
+ }
+ firstVertex = vertices.length;
+ }
+ uint32_t meshChartIndex = 0;
for (uint32_t cg = 0; cg < ctx->paramAtlas.chartGroupCount(i); cg++) {
const internal::param::ChartGroup *chartGroup = ctx->paramAtlas.chartGroupAt(i, cg);
- if (chartGroup->isVertexMap()) {
- const internal::Mesh *mesh = chartGroup->mesh();
+ for (uint32_t c = 0; c < chartGroup->chartCount(); c++) {
+ const internal::param::Chart *chart = chartGroup->chartAt(c);
+ const internal::Mesh *mesh = chart->mesh();
// Vertices.
for (uint32_t v = 0; v < mesh->vertexCount(); v++) {
Vertex &vertex = outputMesh.vertexArray[firstVertex + v];
- vertex.atlasIndex = -1;
- vertex.chartIndex = -1;
- vertex.uv[0] = vertex.uv[1] = 0.0f;
- vertex.xref = chartGroup->mapVertexToSourceVertex(v);
+ vertex.atlasIndex = packAtlas.getChart(chartIndex)->atlasIndex;
+ XA_DEBUG_ASSERT(vertex.atlasIndex >= 0);
+ vertex.chartIndex = (int32_t)chartIndex;
+ const internal::Vector2 &uv = mesh->texcoord(v);
+ vertex.uv[0] = internal::max(0.0f, uv.x);
+ vertex.uv[1] = internal::max(0.0f, uv.y);
+ vertex.xref = chart->mapChartVertexToSourceVertex(v);
}
// Indices.
for (uint32_t f = 0; f < mesh->faceCount(); f++) {
- const uint32_t indexOffset = chartGroup->mapFaceToSourceFace(f) * 3;
+ const uint32_t indexOffset = chart->mapFaceToSourceFace(f) * 3;
for (uint32_t j = 0; j < 3; j++)
outputMesh.indexArray[indexOffset + j] = firstVertex + mesh->vertexAt(f * 3 + j);
}
+ // Charts.
+ Chart *outputChart = &outputMesh.chartArray[meshChartIndex];
+ const int32_t atlasIndex = packAtlas.getChart(chartIndex)->atlasIndex;
+ XA_DEBUG_ASSERT(atlasIndex >= 0);
+ outputChart->atlasIndex = (uint32_t)atlasIndex;
+ outputChart->type = chart->isInvalid() ? ChartType::Invalid : chart->type();
+ outputChart->faceCount = mesh->faceCount();
+ outputChart->faceArray = XA_ALLOC_ARRAY(internal::MemTag::Default, uint32_t, outputChart->faceCount);
+ for (uint32_t f = 0; f < outputChart->faceCount; f++)
+ outputChart->faceArray[f] = chart->mapFaceToSourceFace(f);
+ outputChart->material = 0;
+ meshChartIndex++;
+ chartIndex++;
firstVertex += mesh->vertexCount();
- } else {
- for (uint32_t c = 0; c < chartGroup->chartCount(); c++) {
- const internal::param::Chart *chart = chartGroup->chartAt(c);
- const internal::Mesh *mesh = chart->mesh();
- // Vertices.
- for (uint32_t v = 0; v < mesh->vertexCount(); v++) {
- Vertex &vertex = outputMesh.vertexArray[firstVertex + v];
- vertex.atlasIndex = packAtlas.getChart(chartIndex)->atlasIndex;
- XA_DEBUG_ASSERT(vertex.atlasIndex >= 0);
- vertex.chartIndex = (int32_t)chartIndex;
- const internal::Vector2 &uv = mesh->texcoord(v);
- vertex.uv[0] = internal::max(0.0f, uv.x);
- vertex.uv[1] = internal::max(0.0f, uv.y);
- vertex.xref = chartGroup->mapVertexToSourceVertex(chart->mapChartVertexToOriginalVertex(v));
- }
- // Indices.
- for (uint32_t f = 0; f < mesh->faceCount(); f++) {
- const uint32_t indexOffset = chartGroup->mapFaceToSourceFace(chart->mapFaceToSourceFace(f)) * 3;
- for (uint32_t j = 0; j < 3; j++)
- outputMesh.indexArray[indexOffset + j] = firstVertex + mesh->vertexAt(f * 3 + j);
- }
- // Charts.
- Chart *outputChart = &outputMesh.chartArray[meshChartIndex];
- const int32_t atlasIndex = packAtlas.getChart(chartIndex)->atlasIndex;
- XA_DEBUG_ASSERT(atlasIndex >= 0);
- outputChart->atlasIndex = (uint32_t)atlasIndex;
- outputChart->type = chart->type();
- outputChart->faceCount = mesh->faceCount();
- outputChart->faceArray = XA_ALLOC_ARRAY(internal::MemTag::Default, uint32_t, outputChart->faceCount);
- for (uint32_t f = 0; f < outputChart->faceCount; f++)
- outputChart->faceArray[f] = chartGroup->mapFaceToSourceFace(chart->mapFaceToSourceFace(f));
- outputChart->material = 0;
- meshChartIndex++;
- chartIndex++;
- firstVertex += mesh->vertexCount();
- }
}
}
XA_DEBUG_ASSERT(outputMesh.vertexCount == firstVertex);
@@ -9078,10 +10096,14 @@ void PackCharts(Atlas *atlas, PackOptions packOptions) {
ctx->progressFunc(ProgressCategory::BuildOutputMeshes, 100, ctx->progressUserData);
XA_PROFILE_END(buildOutputMeshes)
XA_PROFILE_PRINT_AND_RESET(" Total: ", buildOutputMeshes)
+#if XA_PROFILE_ALLOC
+ XA_PROFILE_PRINT_AND_RESET(" Alloc: ", alloc)
+#endif
XA_PRINT_MEM_USAGE
}
-void Generate(Atlas *atlas, ChartOptions chartOptions, ParameterizeFunc paramFunc, PackOptions packOptions) {
+void Generate(Atlas *atlas, ChartOptions chartOptions, ParameterizeOptions parameterizeOptions, PackOptions packOptions)
+{
if (!atlas) {
XA_PRINT_WARNING("Generate: atlas is null.\n");
return;
@@ -9091,16 +10113,17 @@ void Generate(Atlas *atlas, ChartOptions chartOptions, ParameterizeFunc paramFun
XA_PRINT_WARNING("Generate: This function should not be called with UV meshes.\n");
return;
}
- if (ctx->meshCount == 0) {
+ if (ctx->meshes.isEmpty()) {
XA_PRINT_WARNING("Generate: No meshes. Call AddMesh first.\n");
return;
}
ComputeCharts(atlas, chartOptions);
- ParameterizeCharts(atlas, paramFunc);
+ ParameterizeCharts(atlas, parameterizeOptions);
PackCharts(atlas, packOptions);
}
-void SetProgressCallback(Atlas *atlas, ProgressFunc progressFunc, void *progressUserData) {
+void SetProgressCallback(Atlas *atlas, ProgressFunc progressFunc, void *progressUserData)
+{
if (!atlas) {
XA_PRINT_WARNING("SetProgressCallback: atlas is null.\n");
return;
@@ -9110,17 +10133,20 @@ void SetProgressCallback(Atlas *atlas, ProgressFunc progressFunc, void *progress
ctx->progressUserData = progressUserData;
}
-void SetAlloc(ReallocFunc reallocFunc, FreeFunc freeFunc) {
+void SetAlloc(ReallocFunc reallocFunc, FreeFunc freeFunc)
+{
internal::s_realloc = reallocFunc;
internal::s_free = freeFunc;
}
-void SetPrint(PrintFunc print, bool verbose) {
+void SetPrint(PrintFunc print, bool verbose)
+{
internal::s_print = print;
internal::s_printVerbose = verbose;
}
-const char *StringForEnum(AddMeshError::Enum error) {
+const char *StringForEnum(AddMeshError::Enum error)
+{
if (error == AddMeshError::Error)
return "Unspecified error";
if (error == AddMeshError::IndexOutOfRange)
@@ -9130,7 +10156,8 @@ const char *StringForEnum(AddMeshError::Enum error) {
return "Success";
}
-const char *StringForEnum(ProgressCategory::Enum category) {
+const char *StringForEnum(ProgressCategory::Enum category)
+{
if (category == ProgressCategory::AddMesh)
return "Adding mesh(es)";
if (category == ProgressCategory::ComputeCharts)
diff --git a/thirdparty/xatlas/xatlas.h b/thirdparty/xatlas/xatlas.h
index e59f493287..cc47f4837e 100644
--- a/thirdparty/xatlas/xatlas.h
+++ b/thirdparty/xatlas/xatlas.h
@@ -1,7 +1,7 @@
/*
MIT License
-Copyright (c) 2018-2019 Jonathan Young
+Copyright (c) 2018-2020 Jonathan Young
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -42,18 +42,19 @@ struct ChartType
Planar,
Ortho,
LSCM,
- Piecewise
+ Piecewise,
+ Invalid
};
};
// A group of connected faces, belonging to a single atlas.
struct Chart
{
- uint32_t atlasIndex; // Sub-atlas index.
uint32_t *faceArray;
+ uint32_t atlasIndex; // Sub-atlas index.
uint32_t faceCount;
- uint32_t material;
ChartType::Enum type;
+ uint32_t material;
};
// Output vertex.
@@ -69,10 +70,10 @@ struct Vertex
struct Mesh
{
Chart *chartArray;
- uint32_t chartCount;
uint32_t *indexArray;
- uint32_t indexCount;
Vertex *vertexArray;
+ uint32_t chartCount;
+ uint32_t indexCount;
uint32_t vertexCount;
};
@@ -84,15 +85,15 @@ static const uint32_t kImageIsPaddingBit = 0x20000000;
// Empty on creation. Populated after charts are packed.
struct Atlas
{
+ uint32_t *image;
+ Mesh *meshes; // The output meshes, corresponding to each AddMesh call.
uint32_t width; // Atlas width in texels.
uint32_t height; // Atlas height in texels.
uint32_t atlasCount; // Number of sub-atlases. Equal to 0 unless PackOptions resolution is changed from default (0).
uint32_t chartCount; // Total number of charts in all meshes.
uint32_t meshCount; // Number of output meshes. Equal to the number of times AddMesh was called.
- Mesh *meshes; // The output meshes, corresponding to each AddMesh call.
float *utilization; // Normalized atlas texel utilization array. E.g. a value of 0.8 means 20% empty space. atlasCount in length.
float texelsPerUnit; // Equal to PackOptions texelsPerUnit if texelsPerUnit > 0, otherwise an estimated value to match PackOptions resolution.
- uint32_t *image;
};
// Create an empty atlas.
@@ -112,22 +113,23 @@ struct IndexFormat
// Input mesh declaration.
struct MeshDecl
{
- uint32_t vertexCount = 0;
const void *vertexPositionData = nullptr;
- uint32_t vertexPositionStride = 0;
const void *vertexNormalData = nullptr; // optional
- uint32_t vertexNormalStride = 0; // optional
const void *vertexUvData = nullptr; // optional. The input UVs are provided as a hint to the chart generator.
- uint32_t vertexUvStride = 0; // optional
- uint32_t indexCount = 0;
const void *indexData = nullptr; // optional
- int32_t indexOffset = 0; // optional. Add this offset to all indices.
- IndexFormat::Enum indexFormat = IndexFormat::UInt16;
// Optional. indexCount / 3 (triangle count) in length.
// Don't atlas faces set to true. Ignored faces still exist in the output meshes, Vertex uv is set to (0, 0) and Vertex atlasIndex to -1.
const bool *faceIgnoreData = nullptr;
+ uint32_t vertexCount = 0;
+ uint32_t vertexPositionStride = 0;
+ uint32_t vertexNormalStride = 0; // optional
+ uint32_t vertexUvStride = 0; // optional
+ uint32_t indexCount = 0;
+ int32_t indexOffset = 0; // optional. Add this offset to all indices.
+ IndexFormat::Enum indexFormat = IndexFormat::UInt16;
+
// Vertex positions within epsilon distance of each other are considered colocal.
float epsilon = 1.192092896e-07F;
};
@@ -151,14 +153,14 @@ void AddMeshJoin(Atlas *atlas);
struct UvMeshDecl
{
+ const void *vertexUvData = nullptr;
+ const void *indexData = nullptr; // optional
+ const uint32_t *faceMaterialData = nullptr; // Optional. Faces with different materials won't be assigned to the same chart. Must be indexCount / 3 in length.
uint32_t vertexCount = 0;
uint32_t vertexStride = 0;
- const void *vertexUvData = nullptr;
uint32_t indexCount = 0;
- const void *indexData = nullptr; // optional
int32_t indexOffset = 0; // optional. Add this offset to all indices.
IndexFormat::Enum indexFormat = IndexFormat::UInt16;
- const uint32_t *faceMaterialData = nullptr; // Optional. Faces with different materials won't be assigned to the same chart. Must be indexCount / 3 in length.
bool rotateCharts = true;
};
@@ -170,24 +172,31 @@ struct ChartOptions
float maxBoundaryLength = 0.0f; // Don't grow charts to have a longer boundary than this. 0 means no limit.
// Weights determine chart growth. Higher weights mean higher cost for that metric.
- float proxyFitMetricWeight = 2.0f; // Angle between face and average chart normal.
- float roundnessMetricWeight = 0.01f;
- float straightnessMetricWeight = 6.0f;
- float normalSeamMetricWeight = 4.0f; // If > 1000, normal seams are fully respected.
- float textureSeamMetricWeight = 0.5f;
+ float normalDeviationWeight = 2.0f; // Angle between face and average chart normal.
+ float roundnessWeight = 0.01f;
+ float straightnessWeight = 6.0f;
+ float normalSeamWeight = 4.0f; // If > 1000, normal seams are fully respected.
+ float textureSeamWeight = 0.5f;
- float maxThreshold = 2.0f; // If total of all metrics * weights > maxThreshold, don't grow chart. Lower values result in more charts.
+ float maxCost = 2.0f; // If total of all metrics * weights > maxCost, don't grow chart. Lower values result in more charts.
uint32_t maxIterations = 1; // Number of iterations of the chart growing and seeding phases. Higher values result in better charts.
};
// Call after all AddMesh calls. Can be called multiple times to recompute charts with different options.
-void ComputeCharts(Atlas *atlas, ChartOptions chartOptions = ChartOptions());
+void ComputeCharts(Atlas *atlas, ChartOptions options = ChartOptions());
// Custom parameterization function. texcoords initial values are an orthogonal parameterization.
typedef void (*ParameterizeFunc)(const float *positions, float *texcoords, uint32_t vertexCount, const uint32_t *indices, uint32_t indexCount);
+struct ParameterizeOptions
+{
+ ParameterizeFunc func = nullptr;
+ bool closeHoles = true; // If the custom parameterization function works with multiple boundaries, this can be set to false to improve performance.
+ bool fixTJunctions = true; // If meshes don't have T-junctions, this can be set to false to improve performance.
+};
+
// Call after ComputeCharts. Can be called multiple times to re-parameterize charts with a different ParameterizeFunc.
-void ParameterizeCharts(Atlas *atlas, ParameterizeFunc func = nullptr);
+void ParameterizeCharts(Atlas *atlas, ParameterizeOptions options = ParameterizeOptions());
struct PackOptions
{
@@ -224,7 +233,7 @@ struct PackOptions
void PackCharts(Atlas *atlas, PackOptions packOptions = PackOptions());
// Equivalent to calling ComputeCharts, ParameterizeCharts and PackCharts in sequence. Can be called multiple times to regenerate with different options.
-void Generate(Atlas *atlas, ChartOptions chartOptions = ChartOptions(), ParameterizeFunc paramFunc = nullptr, PackOptions packOptions = PackOptions());
+void Generate(Atlas *atlas, ChartOptions chartOptions = ChartOptions(), ParameterizeOptions parameterizeOptions = ParameterizeOptions(), PackOptions packOptions = PackOptions());
// Progress tracking.
struct ProgressCategory