summaryrefslogtreecommitdiff
path: root/servers
diff options
context:
space:
mode:
Diffstat (limited to 'servers')
-rw-r--r--servers/audio/audio_driver_dummy.cpp4
-rw-r--r--servers/audio/audio_driver_dummy.h4
-rw-r--r--servers/audio/audio_effect.cpp4
-rw-r--r--servers/audio/audio_effect.h4
-rw-r--r--servers/audio/audio_filter_sw.cpp18
-rw-r--r--servers/audio/audio_filter_sw.h4
-rw-r--r--servers/audio/audio_rb_resampler.cpp6
-rw-r--r--servers/audio/audio_rb_resampler.h4
-rw-r--r--servers/audio/audio_stream.cpp4
-rw-r--r--servers/audio/audio_stream.h4
-rw-r--r--servers/audio/effects/audio_effect_amplify.cpp4
-rw-r--r--servers/audio/effects/audio_effect_amplify.h4
-rw-r--r--servers/audio/effects/audio_effect_capture.cpp4
-rw-r--r--servers/audio/effects/audio_effect_capture.h4
-rw-r--r--servers/audio/effects/audio_effect_chorus.cpp4
-rw-r--r--servers/audio/effects/audio_effect_chorus.h4
-rw-r--r--servers/audio/effects/audio_effect_compressor.cpp4
-rw-r--r--servers/audio/effects/audio_effect_compressor.h4
-rw-r--r--servers/audio/effects/audio_effect_delay.cpp4
-rw-r--r--servers/audio/effects/audio_effect_delay.h4
-rw-r--r--servers/audio/effects/audio_effect_distortion.cpp4
-rw-r--r--servers/audio/effects/audio_effect_distortion.h4
-rw-r--r--servers/audio/effects/audio_effect_eq.cpp4
-rw-r--r--servers/audio/effects/audio_effect_eq.h4
-rw-r--r--servers/audio/effects/audio_effect_filter.cpp4
-rw-r--r--servers/audio/effects/audio_effect_filter.h4
-rw-r--r--servers/audio/effects/audio_effect_limiter.cpp4
-rw-r--r--servers/audio/effects/audio_effect_limiter.h6
-rw-r--r--servers/audio/effects/audio_effect_panner.cpp4
-rw-r--r--servers/audio/effects/audio_effect_panner.h4
-rw-r--r--servers/audio/effects/audio_effect_phaser.cpp4
-rw-r--r--servers/audio/effects/audio_effect_phaser.h4
-rw-r--r--servers/audio/effects/audio_effect_pitch_shift.cpp4
-rw-r--r--servers/audio/effects/audio_effect_pitch_shift.h4
-rw-r--r--servers/audio/effects/audio_effect_record.cpp4
-rw-r--r--servers/audio/effects/audio_effect_record.h5
-rw-r--r--servers/audio/effects/audio_effect_reverb.cpp4
-rw-r--r--servers/audio/effects/audio_effect_reverb.h6
-rw-r--r--servers/audio/effects/audio_effect_spectrum_analyzer.cpp4
-rw-r--r--servers/audio/effects/audio_effect_spectrum_analyzer.h4
-rw-r--r--servers/audio/effects/audio_effect_stereo_enhance.cpp4
-rw-r--r--servers/audio/effects/audio_effect_stereo_enhance.h4
-rw-r--r--servers/audio/effects/audio_stream_generator.cpp4
-rw-r--r--servers/audio/effects/audio_stream_generator.h4
-rw-r--r--servers/audio/effects/eq.cpp4
-rw-r--r--servers/audio/effects/eq.h12
-rw-r--r--servers/audio/effects/reverb.cpp4
-rw-r--r--servers/audio/effects/reverb.h8
-rw-r--r--servers/audio_server.cpp34
-rw-r--r--servers/audio_server.h4
-rw-r--r--servers/camera/camera_feed.cpp4
-rw-r--r--servers/camera/camera_feed.h8
-rw-r--r--servers/camera_server.cpp6
-rw-r--r--servers/camera_server.h8
-rw-r--r--servers/display_server.cpp43
-rw-r--r--servers/display_server.h16
-rw-r--r--servers/display_server_headless.h20
-rw-r--r--servers/navigation_server_2d.cpp11
-rw-r--r--servers/navigation_server_2d.h16
-rw-r--r--servers/navigation_server_3d.cpp10
-rw-r--r--servers/navigation_server_3d.h16
-rw-r--r--servers/physics_2d/body_direct_state_2d_sw.cpp178
-rw-r--r--servers/physics_2d/godot_area_2d.cpp (renamed from servers/physics_2d/area_2d_sw.cpp)196
-rw-r--r--servers/physics_2d/godot_area_2d.h (renamed from servers/physics_2d/area_2d_sw.h)85
-rw-r--r--servers/physics_2d/godot_area_pair_2d.cpp (renamed from servers/physics_2d/area_pair_2d_sw.cpp)64
-rw-r--r--servers/physics_2d/godot_area_pair_2d.h (renamed from servers/physics_2d/area_pair_2d_sw.h)41
-rw-r--r--servers/physics_2d/godot_body_2d.cpp (renamed from servers/physics_2d/body_2d_sw.cpp)300
-rw-r--r--servers/physics_2d/godot_body_2d.h (renamed from servers/physics_2d/body_2d_sw.h)153
-rw-r--r--servers/physics_2d/godot_body_direct_state_2d.cpp219
-rw-r--r--servers/physics_2d/godot_body_direct_state_2d.h (renamed from servers/physics_2d/body_direct_state_2d_sw.h)38
-rw-r--r--servers/physics_2d/godot_body_pair_2d.cpp (renamed from servers/physics_2d/body_pair_2d_sw.cpp)262
-rw-r--r--servers/physics_2d/godot_body_pair_2d.h (renamed from servers/physics_2d/body_pair_2d_sw.h)36
-rw-r--r--servers/physics_2d/godot_broad_phase_2d.cpp (renamed from servers/physics_2d/broad_phase_2d_sw.cpp)12
-rw-r--r--servers/physics_2d/godot_broad_phase_2d.h (renamed from servers/physics_2d/broad_phase_2d_sw.h)32
-rw-r--r--servers/physics_2d/godot_broad_phase_2d_bvh.cpp (renamed from servers/physics_2d/broad_phase_2d_bvh.cpp)52
-rw-r--r--servers/physics_2d/godot_broad_phase_2d_bvh.h (renamed from servers/physics_2d/broad_phase_2d_bvh.h)35
-rw-r--r--servers/physics_2d/godot_collision_object_2d.cpp (renamed from servers/physics_2d/collision_object_2d_sw.cpp)54
-rw-r--r--servers/physics_2d/godot_collision_object_2d.h (renamed from servers/physics_2d/collision_object_2d_sw.h)51
-rw-r--r--servers/physics_2d/godot_collision_solver_2d.cpp (renamed from servers/physics_2d/collision_solver_2d_sw.cpp)30
-rw-r--r--servers/physics_2d/godot_collision_solver_2d.h (renamed from servers/physics_2d/collision_solver_2d_sw.h)26
-rw-r--r--servers/physics_2d/godot_collision_solver_2d_sat.cpp (renamed from servers/physics_2d/collision_solver_2d_sat.cpp)138
-rw-r--r--servers/physics_2d/godot_collision_solver_2d_sat.h (renamed from servers/physics_2d/collision_solver_2d_sat.h)16
-rw-r--r--servers/physics_2d/godot_constraint_2d.h (renamed from servers/physics_2d/constraint_2d_sw.h)24
-rw-r--r--servers/physics_2d/godot_joints_2d.cpp (renamed from servers/physics_2d/joints_2d_sw.cpp)62
-rw-r--r--servers/physics_2d/godot_joints_2d.h (renamed from servers/physics_2d/joints_2d_sw.h)58
-rw-r--r--servers/physics_2d/godot_physics_server_2d.cpp1366
-rw-r--r--servers/physics_2d/godot_physics_server_2d.h (renamed from servers/physics_2d/physics_server_2d_sw.h)89
-rw-r--r--servers/physics_2d/godot_shape_2d.cpp (renamed from servers/physics_2d/shape_2d_sw.cpp)132
-rw-r--r--servers/physics_2d/godot_shape_2d.h (renamed from servers/physics_2d/shape_2d_sw.h)74
-rw-r--r--servers/physics_2d/godot_space_2d.cpp (renamed from servers/physics_2d/space_2d_sw.cpp)396
-rw-r--r--servers/physics_2d/godot_space_2d.h214
-rw-r--r--servers/physics_2d/godot_step_2d.cpp (renamed from servers/physics_2d/step_2d_sw.cpp)86
-rw-r--r--servers/physics_2d/godot_step_2d.h (renamed from servers/physics_2d/step_2d_sw.h)34
-rw-r--r--servers/physics_2d/physics_server_2d_sw.cpp1349
-rw-r--r--servers/physics_2d/space_2d_sw.h211
-rw-r--r--servers/physics_3d/body_direct_state_3d_sw.cpp190
-rw-r--r--servers/physics_3d/gjk_epa.cpp32
-rw-r--r--servers/physics_3d/gjk_epa.h12
-rw-r--r--servers/physics_3d/godot_area_3d.cpp (renamed from servers/physics_3d/area_3d_sw.cpp)199
-rw-r--r--servers/physics_3d/godot_area_3d.h (renamed from servers/physics_3d/area_3d_sw.h)102
-rw-r--r--servers/physics_3d/godot_area_pair_3d.cpp (renamed from servers/physics_3d/area_pair_3d_sw.cpp)94
-rw-r--r--servers/physics_3d/godot_area_pair_3d.h (renamed from servers/physics_3d/area_pair_3d_sw.h)54
-rw-r--r--servers/physics_3d/godot_body_3d.cpp (renamed from servers/physics_3d/body_3d_sw.cpp)316
-rw-r--r--servers/physics_3d/godot_body_3d.h (renamed from servers/physics_3d/body_3d_sw.h)115
-rw-r--r--servers/physics_3d/godot_body_direct_state_3d.cpp231
-rw-r--r--servers/physics_3d/godot_body_direct_state_3d.h (renamed from servers/physics_3d/body_direct_state_3d_sw.h)38
-rw-r--r--servers/physics_3d/godot_body_pair_3d.cpp (renamed from servers/physics_3d/body_pair_3d_sw.cpp)280
-rw-r--r--servers/physics_3d/godot_body_pair_3d.h (renamed from servers/physics_3d/body_pair_3d_sw.h)55
-rw-r--r--servers/physics_3d/godot_broad_phase_3d.cpp (renamed from servers/physics_3d/broad_phase_3d_sw.cpp)12
-rw-r--r--servers/physics_3d/godot_broad_phase_3d.h (renamed from servers/physics_3d/broad_phase_3d_sw.h)34
-rw-r--r--servers/physics_3d/godot_broad_phase_3d_bvh.cpp (renamed from servers/physics_3d/broad_phase_3d_bvh.cpp)55
-rw-r--r--servers/physics_3d/godot_broad_phase_3d_bvh.h (renamed from servers/physics_3d/broad_phase_3d_bvh.h)37
-rw-r--r--servers/physics_3d/godot_collision_object_3d.cpp (renamed from servers/physics_3d/collision_object_3d_sw.cpp)57
-rw-r--r--servers/physics_3d/godot_collision_object_3d.h (renamed from servers/physics_3d/collision_object_3d_sw.h)51
-rw-r--r--servers/physics_3d/godot_collision_solver_3d.cpp (renamed from servers/physics_3d/collision_solver_3d_sw.cpp)84
-rw-r--r--servers/physics_3d/godot_collision_solver_3d.h (renamed from servers/physics_3d/collision_solver_3d_sw.h)36
-rw-r--r--servers/physics_3d/godot_collision_solver_3d_sat.cpp (renamed from servers/physics_3d/collision_solver_3d_sat.cpp)286
-rw-r--r--servers/physics_3d/godot_collision_solver_3d_sat.h (renamed from servers/physics_3d/collision_solver_3d_sat.h)16
-rw-r--r--servers/physics_3d/godot_constraint_3d.h (renamed from servers/physics_3d/constraint_3d_sw.h)28
-rw-r--r--servers/physics_3d/godot_joint_3d.h (renamed from servers/physics_3d/joints_3d_sw.h)28
-rw-r--r--servers/physics_3d/godot_physics_server_3d.cpp1763
-rw-r--r--servers/physics_3d/godot_physics_server_3d.h (renamed from servers/physics_3d/physics_server_3d_sw.h)88
-rw-r--r--servers/physics_3d/godot_shape_3d.cpp (renamed from servers/physics_3d/shape_3d_sw.cpp)358
-rw-r--r--servers/physics_3d/godot_shape_3d.h (renamed from servers/physics_3d/shape_3d_sw.h)143
-rw-r--r--servers/physics_3d/godot_soft_body_3d.cpp (renamed from servers/physics_3d/soft_body_3d_sw.cpp)258
-rw-r--r--servers/physics_3d/godot_soft_body_3d.h (renamed from servers/physics_3d/soft_body_3d_sw.h)77
-rw-r--r--servers/physics_3d/godot_space_3d.cpp (renamed from servers/physics_3d/space_3d_sw.cpp)394
-rw-r--r--servers/physics_3d/godot_space_3d.h218
-rw-r--r--servers/physics_3d/godot_step_3d.cpp (renamed from servers/physics_3d/step_3d_sw.cpp)111
-rw-r--r--servers/physics_3d/godot_step_3d.h (renamed from servers/physics_3d/step_3d_sw.h)36
-rw-r--r--servers/physics_3d/joints/godot_cone_twist_joint_3d.cpp (renamed from servers/physics_3d/joints/cone_twist_joint_3d_sw.cpp)51
-rw-r--r--servers/physics_3d/joints/godot_cone_twist_joint_3d.h (renamed from servers/physics_3d/joints/cone_twist_joint_3d_sw.h)32
-rw-r--r--servers/physics_3d/joints/godot_generic_6dof_joint_3d.cpp (renamed from servers/physics_3d/joints/generic_6dof_joint_3d_sw.cpp)106
-rw-r--r--servers/physics_3d/joints/godot_generic_6dof_joint_3d.h (renamed from servers/physics_3d/joints/generic_6dof_joint_3d_sw.h)135
-rw-r--r--servers/physics_3d/joints/godot_hinge_joint_3d.cpp (renamed from servers/physics_3d/joints/hinge_joint_3d_sw.cpp)102
-rw-r--r--servers/physics_3d/joints/godot_hinge_joint_3d.h (renamed from servers/physics_3d/joints/hinge_joint_3d_sw.h)32
-rw-r--r--servers/physics_3d/joints/godot_jacobian_entry_3d.h (renamed from servers/physics_3d/joints/jacobian_entry_3d_sw.h)32
-rw-r--r--servers/physics_3d/joints/godot_pin_joint_3d.cpp (renamed from servers/physics_3d/joints/pin_joint_3d_sw.cpp)44
-rw-r--r--servers/physics_3d/joints/godot_pin_joint_3d.h (renamed from servers/physics_3d/joints/pin_joint_3d_sw.h)30
-rw-r--r--servers/physics_3d/joints/godot_slider_joint_3d.cpp (renamed from servers/physics_3d/joints/slider_joint_3d_sw.cpp)84
-rw-r--r--servers/physics_3d/joints/godot_slider_joint_3d.h (renamed from servers/physics_3d/joints/slider_joint_3d_sw.h)34
-rw-r--r--servers/physics_3d/physics_server_3d_sw.cpp1748
-rw-r--r--servers/physics_3d/space_3d_sw.h216
-rw-r--r--servers/physics_server_2d.cpp321
-rw-r--r--servers/physics_server_2d.h289
-rw-r--r--servers/physics_server_2d_wrap_mt.cpp (renamed from servers/physics_2d/physics_server_2d_wrap_mt.cpp)4
-rw-r--r--servers/physics_server_2d_wrap_mt.h (renamed from servers/physics_2d/physics_server_2d_wrap_mt.h)44
-rw-r--r--servers/physics_server_3d.cpp281
-rw-r--r--servers/physics_server_3d.h295
-rw-r--r--servers/physics_server_3d_wrap_mt.cpp (renamed from servers/physics_3d/physics_server_3d_wrap_mt.cpp)4
-rw-r--r--servers/physics_server_3d_wrap_mt.h (renamed from servers/physics_3d/physics_server_3d_wrap_mt.h)44
-rw-r--r--servers/register_server_types.cpp25
-rw-r--r--servers/register_server_types.h4
-rw-r--r--servers/rendering/rasterizer_dummy.h50
-rw-r--r--servers/rendering/renderer_canvas_cull.cpp15
-rw-r--r--servers/rendering/renderer_canvas_cull.h6
-rw-r--r--servers/rendering/renderer_canvas_render.cpp4
-rw-r--r--servers/rendering/renderer_canvas_render.h4
-rw-r--r--servers/rendering/renderer_compositor.cpp4
-rw-r--r--servers/rendering/renderer_compositor.h7
-rw-r--r--servers/rendering/renderer_rd/cluster_builder_rd.cpp12
-rw-r--r--servers/rendering/renderer_rd/cluster_builder_rd.h6
-rw-r--r--servers/rendering/renderer_rd/effects_rd.cpp845
-rw-r--r--servers/rendering/renderer_rd/effects_rd.h226
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp298
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h42
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp124
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h32
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp124
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h23
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp43
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h13
-rw-r--r--servers/rendering/renderer_rd/pipeline_cache_rd.cpp4
-rw-r--r--servers/rendering/renderer_rd/pipeline_cache_rd.h4
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp56
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.h15
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.cpp14
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.h6
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp15
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_environment_rd.h25
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp59
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_gi_rd.h24
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp1472
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.h273
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp55
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_sky_rd.h13
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.cpp516
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.h82
-rw-r--r--servers/rendering/renderer_rd/shader_rd.cpp13
-rw-r--r--servers/rendering/renderer_rd/shader_rd.h11
-rw-r--r--servers/rendering/renderer_rd/shaders/canvas.glsl45
-rw-r--r--servers/rendering/renderer_rd/shaders/copy.glsl20
-rw-r--r--servers/rendering/renderer_rd/shaders/fsr_upscale.glsl173
-rw-r--r--servers/rendering/renderer_rd/shaders/gi.glsl18
-rw-r--r--servers/rendering/renderer_rd/shaders/giprobe_write.glsl1
-rw-r--r--servers/rendering/renderer_rd/shaders/particles.glsl10
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_aa_inc.glsl5
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl148
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl29
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl63
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl66
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl3
-rw-r--r--servers/rendering/renderer_rd/shaders/screen_space_reflection.glsl1
-rw-r--r--servers/rendering/renderer_rd/shaders/sdfgi_preprocess.glsl4
-rw-r--r--servers/rendering/renderer_rd/shaders/ss_effects_downsample.glsl (renamed from servers/rendering/renderer_rd/shaders/ssao_downsample.glsl)23
-rw-r--r--servers/rendering/renderer_rd/shaders/ssao.glsl3
-rw-r--r--servers/rendering/renderer_rd/shaders/ssao_blur.glsl14
-rw-r--r--servers/rendering/renderer_rd/shaders/ssao_importance_map.glsl7
-rw-r--r--servers/rendering/renderer_rd/shaders/ssil.glsl444
-rw-r--r--servers/rendering/renderer_rd/shaders/ssil_blur.glsl124
-rw-r--r--servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl124
-rw-r--r--servers/rendering/renderer_rd/shaders/ssil_interleave.glsl102
-rw-r--r--servers/rendering/renderer_rd/shaders/tonemap.glsl6
-rw-r--r--servers/rendering/renderer_rd/shaders/volumetric_fog.glsl755
-rw-r--r--servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl785
-rw-r--r--servers/rendering/renderer_rd/shaders/voxel_gi.glsl1
-rw-r--r--servers/rendering/renderer_rd/shaders/voxel_gi_debug.glsl56
-rw-r--r--servers/rendering/renderer_rd/shaders/voxel_gi_sdf.glsl5
-rw-r--r--servers/rendering/renderer_scene.cpp4
-rw-r--r--servers/rendering/renderer_scene.h23
-rw-r--r--servers/rendering/renderer_scene_cull.cpp321
-rw-r--r--servers/rendering/renderer_scene_cull.h67
-rw-r--r--servers/rendering/renderer_scene_occlusion_cull.cpp4
-rw-r--r--servers/rendering/renderer_scene_occlusion_cull.h4
-rw-r--r--servers/rendering/renderer_scene_render.cpp12
-rw-r--r--servers/rendering/renderer_scene_render.h26
-rw-r--r--servers/rendering/renderer_storage.cpp4
-rw-r--r--servers/rendering/renderer_storage.h26
-rw-r--r--servers/rendering/renderer_thread_pool.cpp4
-rw-r--r--servers/rendering/renderer_thread_pool.h4
-rw-r--r--servers/rendering/renderer_viewport.cpp147
-rw-r--r--servers/rendering/renderer_viewport.h23
-rw-r--r--servers/rendering/rendering_device.cpp39
-rw-r--r--servers/rendering/rendering_device.h32
-rw-r--r--servers/rendering/rendering_device_binds.cpp20
-rw-r--r--servers/rendering/rendering_device_binds.h10
-rw-r--r--servers/rendering/rendering_server_default.cpp34
-rw-r--r--servers/rendering/rendering_server_default.h51
-rw-r--r--servers/rendering/rendering_server_globals.cpp4
-rw-r--r--servers/rendering/rendering_server_globals.h4
-rw-r--r--servers/rendering/shader_compiler.cpp (renamed from servers/rendering/renderer_rd/shader_compiler_rd.cpp)261
-rw-r--r--servers/rendering/shader_compiler.h (renamed from servers/rendering/renderer_rd/shader_compiler_rd.h)17
-rw-r--r--servers/rendering/shader_language.cpp2136
-rw-r--r--servers/rendering/shader_language.h172
-rw-r--r--servers/rendering/shader_types.cpp162
-rw-r--r--servers/rendering/shader_types.h8
-rw-r--r--servers/rendering/shader_warnings.cpp34
-rw-r--r--servers/rendering/shader_warnings.h13
-rw-r--r--servers/rendering_server.cpp227
-rw-r--r--servers/rendering_server.h142
-rw-r--r--servers/server_wrap_mt_common.h4
-rw-r--r--servers/text/text_server_extension.cpp120
-rw-r--r--servers/text/text_server_extension.h46
-rw-r--r--servers/text_server.cpp293
-rw-r--r--servers/text_server.h49
-rw-r--r--servers/xr/xr_interface.cpp71
-rw-r--r--servers/xr/xr_interface.h41
-rw-r--r--servers/xr/xr_interface_extension.cpp74
-rw-r--r--servers/xr/xr_interface_extension.h23
-rw-r--r--servers/xr/xr_pose.cpp126
-rw-r--r--servers/xr/xr_pose.h81
-rw-r--r--servers/xr/xr_positional_tracker.cpp252
-rw-r--r--servers/xr/xr_positional_tracker.h50
-rw-r--r--servers/xr_server.cpp235
-rw-r--r--servers/xr_server.h31
265 files changed, 17704 insertions, 11776 deletions
diff --git a/servers/audio/audio_driver_dummy.cpp b/servers/audio/audio_driver_dummy.cpp
index 47799dce96..1ba0afd8a1 100644
--- a/servers/audio/audio_driver_dummy.cpp
+++ b/servers/audio/audio_driver_dummy.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/audio/audio_driver_dummy.h b/servers/audio/audio_driver_dummy.h
index 7d84e7ffc8..6324e2f5d3 100644
--- a/servers/audio/audio_driver_dummy.h
+++ b/servers/audio/audio_driver_dummy.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/audio/audio_effect.cpp b/servers/audio/audio_effect.cpp
index 3035828c95..b9eca14a4c 100644
--- a/servers/audio/audio_effect.cpp
+++ b/servers/audio/audio_effect.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/audio/audio_effect.h b/servers/audio/audio_effect.h
index bea7292b8e..00a5d6c004 100644
--- a/servers/audio/audio_effect.h
+++ b/servers/audio/audio_effect.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/audio/audio_filter_sw.cpp b/servers/audio/audio_filter_sw.cpp
index bcfa4c4c37..082931647a 100644
--- a/servers/audio/audio_filter_sw.cpp
+++ b/servers/audio/audio_filter_sw.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -173,28 +173,20 @@ void AudioFilterSW::prepare_coefficients(Coeffs *p_coeffs) {
p_coeffs->a2 = ((tmpgain + 1.0) - (tmpgain - 1.0) * cos_v - beta * sin_v);
} break;
- };
+ }
p_coeffs->b0 /= a0;
p_coeffs->b1 /= a0;
p_coeffs->b2 /= a0;
p_coeffs->a1 /= 0.0 - a0;
p_coeffs->a2 /= 0.0 - a0;
-
- //undenormalise
- /* p_coeffs->b0=undenormalise(p_coeffs->b0);
- p_coeffs->b1=undenormalise(p_coeffs->b1);
- p_coeffs->b2=undenormalise(p_coeffs->b2);
- p_coeffs->a1=undenormalise(p_coeffs->a1);
- p_coeffs->a2=undenormalise(p_coeffs->a2);*/
}
-void AudioFilterSW::set_stages(int p_stages) { //adjust for multiple stages
-
+void AudioFilterSW::set_stages(int p_stages) {
stages = p_stages;
}
-/* Fouriertransform kernel to obtain response */
+/* Fourier transform kernel to obtain response */
float AudioFilterSW::get_response(float p_freq, Coeffs *p_coeffs) {
float freq = p_freq / sampling_rate * Math_TAU;
diff --git a/servers/audio/audio_filter_sw.h b/servers/audio/audio_filter_sw.h
index 540d6368e3..9e55662d0a 100644
--- a/servers/audio/audio_filter_sw.h
+++ b/servers/audio/audio_filter_sw.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/audio/audio_rb_resampler.cpp b/servers/audio/audio_rb_resampler.cpp
index d9c442facf..0cfba17563 100644
--- a/servers/audio/audio_rb_resampler.cpp
+++ b/servers/audio/audio_rb_resampler.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -43,7 +43,7 @@ int AudioRBResampler::get_channel_count() const {
// Linear interpolation based sample rate conversion (low quality)
// Note that AudioStreamPlaybackResampled::mix has better algorithm,
-// but it wasn't obvious to integrate that with VideoPlayer
+// but it wasn't obvious to integrate that with VideoStreamPlayer
template <int C>
uint32_t AudioRBResampler::_resample(AudioFrame *p_dest, int p_todo, int32_t p_increment) {
uint32_t read = offset & MIX_FRAC_MASK;
diff --git a/servers/audio/audio_rb_resampler.h b/servers/audio/audio_rb_resampler.h
index c0f981704b..3fbe684c3e 100644
--- a/servers/audio/audio_rb_resampler.h
+++ b/servers/audio/audio_rb_resampler.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/audio/audio_stream.cpp b/servers/audio/audio_stream.cpp
index c098a97906..170a7ef967 100644
--- a/servers/audio/audio_stream.cpp
+++ b/servers/audio/audio_stream.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/audio/audio_stream.h b/servers/audio/audio_stream.h
index 12d4343f5c..32159e96ef 100644
--- a/servers/audio/audio_stream.h
+++ b/servers/audio/audio_stream.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/audio/effects/audio_effect_amplify.cpp b/servers/audio/effects/audio_effect_amplify.cpp
index 79788d334b..b01160ea5c 100644
--- a/servers/audio/effects/audio_effect_amplify.cpp
+++ b/servers/audio/effects/audio_effect_amplify.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/audio/effects/audio_effect_amplify.h b/servers/audio/effects/audio_effect_amplify.h
index 9d3facc230..bd0fcaa94d 100644
--- a/servers/audio/effects/audio_effect_amplify.h
+++ b/servers/audio/effects/audio_effect_amplify.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/audio/effects/audio_effect_capture.cpp b/servers/audio/effects/audio_effect_capture.cpp
index 065065042e..f605cfc9d4 100644
--- a/servers/audio/effects/audio_effect_capture.cpp
+++ b/servers/audio/effects/audio_effect_capture.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/audio/effects/audio_effect_capture.h b/servers/audio/effects/audio_effect_capture.h
index bb1d03be8c..3935f7d473 100644
--- a/servers/audio/effects/audio_effect_capture.h
+++ b/servers/audio/effects/audio_effect_capture.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/audio/effects/audio_effect_chorus.cpp b/servers/audio/effects/audio_effect_chorus.cpp
index 9af3ed30cc..8b1fe9cfd2 100644
--- a/servers/audio/effects/audio_effect_chorus.cpp
+++ b/servers/audio/effects/audio_effect_chorus.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/audio/effects/audio_effect_chorus.h b/servers/audio/effects/audio_effect_chorus.h
index f81bebb0ae..19035222c5 100644
--- a/servers/audio/effects/audio_effect_chorus.h
+++ b/servers/audio/effects/audio_effect_chorus.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/audio/effects/audio_effect_compressor.cpp b/servers/audio/effects/audio_effect_compressor.cpp
index cfa2ae6f79..f75d092dd3 100644
--- a/servers/audio/effects/audio_effect_compressor.cpp
+++ b/servers/audio/effects/audio_effect_compressor.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/audio/effects/audio_effect_compressor.h b/servers/audio/effects/audio_effect_compressor.h
index dae4618a64..53c448e5db 100644
--- a/servers/audio/effects/audio_effect_compressor.h
+++ b/servers/audio/effects/audio_effect_compressor.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/audio/effects/audio_effect_delay.cpp b/servers/audio/effects/audio_effect_delay.cpp
index 07475e1ed4..bddd235204 100644
--- a/servers/audio/effects/audio_effect_delay.cpp
+++ b/servers/audio/effects/audio_effect_delay.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/audio/effects/audio_effect_delay.h b/servers/audio/effects/audio_effect_delay.h
index 50a2233e5f..5cc6d72c99 100644
--- a/servers/audio/effects/audio_effect_delay.h
+++ b/servers/audio/effects/audio_effect_delay.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/audio/effects/audio_effect_distortion.cpp b/servers/audio/effects/audio_effect_distortion.cpp
index 188b7a3301..afc4353bd7 100644
--- a/servers/audio/effects/audio_effect_distortion.cpp
+++ b/servers/audio/effects/audio_effect_distortion.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/audio/effects/audio_effect_distortion.h b/servers/audio/effects/audio_effect_distortion.h
index 3a762f8cf6..487babbdda 100644
--- a/servers/audio/effects/audio_effect_distortion.h
+++ b/servers/audio/effects/audio_effect_distortion.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/audio/effects/audio_effect_eq.cpp b/servers/audio/effects/audio_effect_eq.cpp
index e87944b74b..cc317031d4 100644
--- a/servers/audio/effects/audio_effect_eq.cpp
+++ b/servers/audio/effects/audio_effect_eq.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/audio/effects/audio_effect_eq.h b/servers/audio/effects/audio_effect_eq.h
index b99727d7c0..252f931e6c 100644
--- a/servers/audio/effects/audio_effect_eq.h
+++ b/servers/audio/effects/audio_effect_eq.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/audio/effects/audio_effect_filter.cpp b/servers/audio/effects/audio_effect_filter.cpp
index 1db8b1f1b5..06e66f22b1 100644
--- a/servers/audio/effects/audio_effect_filter.cpp
+++ b/servers/audio/effects/audio_effect_filter.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/audio/effects/audio_effect_filter.h b/servers/audio/effects/audio_effect_filter.h
index 1fa3df1570..d5d58ddaa3 100644
--- a/servers/audio/effects/audio_effect_filter.h
+++ b/servers/audio/effects/audio_effect_filter.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/audio/effects/audio_effect_limiter.cpp b/servers/audio/effects/audio_effect_limiter.cpp
index 280411641b..5923cf8cf5 100644
--- a/servers/audio/effects/audio_effect_limiter.cpp
+++ b/servers/audio/effects/audio_effect_limiter.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/audio/effects/audio_effect_limiter.h b/servers/audio/effects/audio_effect_limiter.h
index d5def670a4..f84a0ae103 100644
--- a/servers/audio/effects/audio_effect_limiter.h
+++ b/servers/audio/effects/audio_effect_limiter.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -72,8 +72,6 @@ public:
float get_soft_clip_ratio() const;
Ref<AudioEffectInstance> instantiate() override;
- void set_volume_db(float p_volume);
- float get_volume_db() const;
AudioEffectLimiter();
};
diff --git a/servers/audio/effects/audio_effect_panner.cpp b/servers/audio/effects/audio_effect_panner.cpp
index e2062609b9..278acda86c 100644
--- a/servers/audio/effects/audio_effect_panner.cpp
+++ b/servers/audio/effects/audio_effect_panner.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/audio/effects/audio_effect_panner.h b/servers/audio/effects/audio_effect_panner.h
index d75bcaeb95..d05c9902af 100644
--- a/servers/audio/effects/audio_effect_panner.h
+++ b/servers/audio/effects/audio_effect_panner.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/audio/effects/audio_effect_phaser.cpp b/servers/audio/effects/audio_effect_phaser.cpp
index c76692eed7..af5dce707e 100644
--- a/servers/audio/effects/audio_effect_phaser.cpp
+++ b/servers/audio/effects/audio_effect_phaser.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/audio/effects/audio_effect_phaser.h b/servers/audio/effects/audio_effect_phaser.h
index 2a0ed64805..80b7742835 100644
--- a/servers/audio/effects/audio_effect_phaser.h
+++ b/servers/audio/effects/audio_effect_phaser.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/audio/effects/audio_effect_pitch_shift.cpp b/servers/audio/effects/audio_effect_pitch_shift.cpp
index d6c396e0a5..3c53887931 100644
--- a/servers/audio/effects/audio_effect_pitch_shift.cpp
+++ b/servers/audio/effects/audio_effect_pitch_shift.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/audio/effects/audio_effect_pitch_shift.h b/servers/audio/effects/audio_effect_pitch_shift.h
index 3ed096cd94..0478d05ceb 100644
--- a/servers/audio/effects/audio_effect_pitch_shift.h
+++ b/servers/audio/effects/audio_effect_pitch_shift.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/audio/effects/audio_effect_record.cpp b/servers/audio/effects/audio_effect_record.cpp
index f71679d30f..569832b8a8 100644
--- a/servers/audio/effects/audio_effect_record.cpp
+++ b/servers/audio/effects/audio_effect_record.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/audio/effects/audio_effect_record.h b/servers/audio/effects/audio_effect_record.h
index 1a89821f80..18b5d4d83c 100644
--- a/servers/audio/effects/audio_effect_record.h
+++ b/servers/audio/effects/audio_effect_record.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -93,7 +93,6 @@ class AudioEffectRecord : public AudioEffect {
protected:
static void _bind_methods();
- static void debug(uint64_t time_diff, int p_frame_count);
public:
Ref<AudioEffectInstance> instantiate() override;
diff --git a/servers/audio/effects/audio_effect_reverb.cpp b/servers/audio/effects/audio_effect_reverb.cpp
index 819f906773..0d4eb14e6a 100644
--- a/servers/audio/effects/audio_effect_reverb.cpp
+++ b/servers/audio/effects/audio_effect_reverb.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/audio/effects/audio_effect_reverb.h b/servers/audio/effects/audio_effect_reverb.h
index d01d1120bd..90694c5492 100644
--- a/servers/audio/effects/audio_effect_reverb.h
+++ b/servers/audio/effects/audio_effect_reverb.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -90,8 +90,6 @@ public:
float get_hpf() const;
Ref<AudioEffectInstance> instantiate() override;
- void set_volume_db(float p_volume);
- float get_volume_db() const;
AudioEffectReverb();
};
diff --git a/servers/audio/effects/audio_effect_spectrum_analyzer.cpp b/servers/audio/effects/audio_effect_spectrum_analyzer.cpp
index 6f9e7ac67d..10627be74c 100644
--- a/servers/audio/effects/audio_effect_spectrum_analyzer.cpp
+++ b/servers/audio/effects/audio_effect_spectrum_analyzer.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/audio/effects/audio_effect_spectrum_analyzer.h b/servers/audio/effects/audio_effect_spectrum_analyzer.h
index 3c5ae4a5e8..982c20d4a4 100644
--- a/servers/audio/effects/audio_effect_spectrum_analyzer.h
+++ b/servers/audio/effects/audio_effect_spectrum_analyzer.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/audio/effects/audio_effect_stereo_enhance.cpp b/servers/audio/effects/audio_effect_stereo_enhance.cpp
index 3a016b06b8..757edd6d43 100644
--- a/servers/audio/effects/audio_effect_stereo_enhance.cpp
+++ b/servers/audio/effects/audio_effect_stereo_enhance.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/audio/effects/audio_effect_stereo_enhance.h b/servers/audio/effects/audio_effect_stereo_enhance.h
index e0f9d79a94..8b8b7b47a0 100644
--- a/servers/audio/effects/audio_effect_stereo_enhance.h
+++ b/servers/audio/effects/audio_effect_stereo_enhance.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/audio/effects/audio_stream_generator.cpp b/servers/audio/effects/audio_stream_generator.cpp
index 447acf53a4..6c917f3eb6 100644
--- a/servers/audio/effects/audio_stream_generator.cpp
+++ b/servers/audio/effects/audio_stream_generator.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/audio/effects/audio_stream_generator.h b/servers/audio/effects/audio_stream_generator.h
index 918589f6d0..51288262b3 100644
--- a/servers/audio/effects/audio_stream_generator.h
+++ b/servers/audio/effects/audio_stream_generator.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/audio/effects/eq.cpp b/servers/audio/effects/eq.cpp
index e0c3eb6d3a..2123284b3b 100644
--- a/servers/audio/effects/eq.cpp
+++ b/servers/audio/effects/eq.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/audio/effects/eq.h b/servers/audio/effects/eq.h
index afd5bf5334..d6293bf875 100644
--- a/servers/audio/effects/eq.h
+++ b/servers/audio/effects/eq.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,18 +28,12 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-// Author: reduzio@gmail.com (C) 2006
-
#ifndef EQ_FILTER_H
#define EQ_FILTER_H
#include "core/templates/vector.h"
#include "core/typedefs.h"
-/**
-@author Juan Linietsky
-*/
-
class EQ {
public:
enum Preset {
@@ -105,4 +99,4 @@ inline void EQ::BandProcess::process_one(float &p_data) {
history.b2 = history.b1;
}
-#endif
+#endif // EQ_FILTER_H
diff --git a/servers/audio/effects/reverb.cpp b/servers/audio/effects/reverb.cpp
index 1d97de5205..4b5b9ab79f 100644
--- a/servers/audio/effects/reverb.cpp
+++ b/servers/audio/effects/reverb.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/audio/effects/reverb.h b/servers/audio/effects/reverb.h
index e7ce55098d..ff59ab8d82 100644
--- a/servers/audio/effects/reverb.h
+++ b/servers/audio/effects/reverb.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,8 +28,6 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-// Author: Juan Linietsky <reduzio@gmail.com>, (C) 2006
-
#ifndef REVERB_H
#define REVERB_H
@@ -120,4 +118,4 @@ public:
~Reverb();
};
-#endif
+#endif // REVERB_H
diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp
index a420134626..c89f811678 100644
--- a/servers/audio_server.cpp
+++ b/servers/audio_server.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -762,7 +762,7 @@ void AudioServer::remove_bus(int p_index) {
lock();
bus_map.erase(buses[p_index]->name);
memdelete(buses[p_index]);
- buses.remove(p_index);
+ buses.remove_at(p_index);
unlock();
emit_signal(SNAME("bus_layout_changed"));
@@ -833,7 +833,7 @@ void AudioServer::move_bus(int p_bus, int p_to_pos) {
}
Bus *bus = buses[p_bus];
- buses.remove(p_bus);
+ buses.remove_at(p_bus);
if (p_to_pos == -1) {
buses.push_back(bus);
@@ -1026,7 +1026,7 @@ void AudioServer::remove_bus_effect(int p_bus, int p_effect) {
lock();
- buses[p_bus]->effects.remove(p_effect);
+ buses[p_bus]->effects.remove_at(p_effect);
_update_bus_effects(p_bus);
unlock();
@@ -1131,8 +1131,10 @@ void AudioServer::start_playback_stream(Ref<AudioStreamPlayback> p_playback, Map
AudioStreamPlaybackBusDetails *new_bus_details = new AudioStreamPlaybackBusDetails();
int idx = 0;
for (KeyValue<StringName, Vector<AudioFrame>> pair : p_bus_volumes) {
- ERR_FAIL_COND(pair.value.size() < channel_count);
- ERR_FAIL_COND(pair.value.size() != MAX_CHANNELS_PER_BUS);
+ if (pair.value.size() < channel_count || pair.value.size() != MAX_CHANNELS_PER_BUS) {
+ delete new_bus_details;
+ ERR_FAIL();
+ }
new_bus_details->bus_active[idx] = true;
new_bus_details->bus[idx] = pair.key;
@@ -1589,7 +1591,7 @@ void AudioServer::set_bus_layout(const Ref<AudioBusLayout> &p_bus_layout) {
Bus::Effect bfx;
bfx.effect = fx;
bfx.enabled = p_bus_layout->buses[i].effects[j].enabled;
-#if DEBUG_ENABLED
+#ifdef DEBUG_ENABLED
bfx.prof_time = 0;
#endif
bus->effects.push_back(bfx);
@@ -1862,16 +1864,16 @@ bool AudioBusLayout::_get(const StringName &p_name, Variant &r_ret) const {
void AudioBusLayout::_get_property_list(List<PropertyInfo> *p_list) const {
for (int i = 0; i < buses.size(); i++) {
- p_list->push_back(PropertyInfo(Variant::STRING, "bus/" + itos(i) + "/name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
- p_list->push_back(PropertyInfo(Variant::BOOL, "bus/" + itos(i) + "/solo", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
- p_list->push_back(PropertyInfo(Variant::BOOL, "bus/" + itos(i) + "/mute", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
- p_list->push_back(PropertyInfo(Variant::BOOL, "bus/" + itos(i) + "/bypass_fx", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
- p_list->push_back(PropertyInfo(Variant::FLOAT, "bus/" + itos(i) + "/volume_db", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
- p_list->push_back(PropertyInfo(Variant::FLOAT, "bus/" + itos(i) + "/send", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
+ p_list->push_back(PropertyInfo(Variant::STRING, "bus/" + itos(i) + "/name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL));
+ p_list->push_back(PropertyInfo(Variant::BOOL, "bus/" + itos(i) + "/solo", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL));
+ p_list->push_back(PropertyInfo(Variant::BOOL, "bus/" + itos(i) + "/mute", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL));
+ p_list->push_back(PropertyInfo(Variant::BOOL, "bus/" + itos(i) + "/bypass_fx", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "bus/" + itos(i) + "/volume_db", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "bus/" + itos(i) + "/send", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL));
for (int j = 0; j < buses[i].effects.size(); j++) {
- p_list->push_back(PropertyInfo(Variant::OBJECT, "bus/" + itos(i) + "/effect/" + itos(j) + "/effect", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
- p_list->push_back(PropertyInfo(Variant::BOOL, "bus/" + itos(i) + "/effect/" + itos(j) + "/enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
+ p_list->push_back(PropertyInfo(Variant::OBJECT, "bus/" + itos(i) + "/effect/" + itos(j) + "/effect", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL));
+ p_list->push_back(PropertyInfo(Variant::BOOL, "bus/" + itos(i) + "/effect/" + itos(j) + "/enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL));
}
}
}
diff --git a/servers/audio_server.h b/servers/audio_server.h
index 46873845dc..0c150427f2 100644
--- a/servers/audio_server.h
+++ b/servers/audio_server.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/camera/camera_feed.cpp b/servers/camera/camera_feed.cpp
index 9f8e8a8106..3aab995857 100644
--- a/servers/camera/camera_feed.cpp
+++ b/servers/camera/camera_feed.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/camera/camera_feed.h b/servers/camera/camera_feed.h
index 1f80d15e30..e86605a89b 100644
--- a/servers/camera/camera_feed.h
+++ b/servers/camera/camera_feed.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -37,8 +37,6 @@
#include "servers/rendering_server.h"
/**
- @author Bastiaan Olij <mux213@gmail.com>
-
The camera server is a singleton object that gives access to the various
camera feeds that can be used as the background for our environment.
**/
@@ -111,4 +109,4 @@ public:
VARIANT_ENUM_CAST(CameraFeed::FeedDataType);
VARIANT_ENUM_CAST(CameraFeed::FeedPosition);
-#endif /* !CAMERA_FEED_H */
+#endif // CAMERA_FEED_H
diff --git a/servers/camera_server.cpp b/servers/camera_server.cpp
index 6f506d0f7a..91df3afadd 100644
--- a/servers/camera_server.cpp
+++ b/servers/camera_server.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -124,7 +124,7 @@ void CameraServer::remove_feed(const Ref<CameraFeed> &p_feed) {
#endif
// remove it from our array, if this results in our feed being unreferenced it will be destroyed
- feeds.remove(i);
+ feeds.remove_at(i);
// let whomever is interested know
emit_signal(SNAME("camera_feed_removed"), feed_id);
diff --git a/servers/camera_server.h b/servers/camera_server.h
index 7390129df9..b70938c34f 100644
--- a/servers/camera_server.h
+++ b/servers/camera_server.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -38,8 +38,6 @@
#include "core/variant/variant.h"
/**
- @author Bastiaan Olij <mux213@gmail.com>
-
The camera server is a singleton object that gives access to the various
camera feeds that can be used as the background for our environment.
**/
@@ -113,4 +111,4 @@ public:
VARIANT_ENUM_CAST(CameraServer::FeedImage);
-#endif /* CAMERA_SERVER_H */
+#endif // CAMERA_SERVER_H
diff --git a/servers/display_server.cpp b/servers/display_server.cpp
index 3897e5e7c2..d4ff42bc34 100644
--- a/servers/display_server.cpp
+++ b/servers/display_server.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -139,16 +139,12 @@ void DisplayServer::mouse_warp_to_position(const Point2i &p_to) {
WARN_PRINT("Mouse warping is not supported by this display server.");
}
-Point2i DisplayServer::mouse_get_absolute_position() const {
- ERR_FAIL_V_MSG(Point2i(), "Mouse is not supported by this display server.");
-}
-
Point2i DisplayServer::mouse_get_position() const {
ERR_FAIL_V_MSG(Point2i(), "Mouse is not supported by this display server.");
}
MouseButton DisplayServer::mouse_get_button_state() const {
- ERR_FAIL_V_MSG(MOUSE_BUTTON_NONE, "Mouse is not supported by this display server.");
+ ERR_FAIL_V_MSG(MouseButton::NONE, "Mouse is not supported by this display server.");
}
void DisplayServer::clipboard_set(const String &p_text) {
@@ -159,6 +155,18 @@ String DisplayServer::clipboard_get() const {
ERR_FAIL_V_MSG(String(), "Clipboard is not supported by this display server.");
}
+bool DisplayServer::clipboard_has() const {
+ return !clipboard_get().is_empty();
+}
+
+void DisplayServer::clipboard_set_primary(const String &p_text) {
+ WARN_PRINT("Primary clipboard is not supported by this display server.");
+}
+
+String DisplayServer::clipboard_get_primary() const {
+ ERR_FAIL_V_MSG(String(), "Primary clipboard is not supported by this display server.");
+}
+
void DisplayServer::screen_set_orientation(ScreenOrientation p_orientation, int p_screen) {
WARN_PRINT("Orientation not supported by this display server.");
}
@@ -200,6 +208,10 @@ void DisplayServer::window_set_mouse_passthrough(const Vector<Vector2> &p_region
ERR_FAIL_MSG("Mouse passthrough not supported by this display server.");
}
+void DisplayServer::gl_window_make_current(DisplayServer::WindowID p_window_id) {
+ // noop except in gles
+}
+
void DisplayServer::window_set_ime_active(const bool p_active, WindowID p_window) {
WARN_PRINT("IME not supported by this display server.");
}
@@ -216,14 +228,6 @@ String DisplayServer::ime_get_text() const {
ERR_FAIL_V_MSG(String(), "IME or NOTIFICATION_WM_IME_UPDATEnot supported by this display server.");
}
-void DisplayServer::console_set_visible(bool p_enabled) {
- WARN_PRINT("Console window not supported by this display server.");
-}
-
-bool DisplayServer::is_console_visible() const {
- return false;
-}
-
void DisplayServer::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, bool p_multiline, int p_max_length, int p_cursor_start, int p_cursor_end) {
WARN_PRINT("Virtual keyboard not supported by this display server.");
}
@@ -355,11 +359,13 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("mouse_warp_to_position", "position"), &DisplayServer::mouse_warp_to_position);
ClassDB::bind_method(D_METHOD("mouse_get_position"), &DisplayServer::mouse_get_position);
- ClassDB::bind_method(D_METHOD("mouse_get_absolute_position"), &DisplayServer::mouse_get_absolute_position);
ClassDB::bind_method(D_METHOD("mouse_get_button_state"), &DisplayServer::mouse_get_button_state);
ClassDB::bind_method(D_METHOD("clipboard_set", "clipboard"), &DisplayServer::clipboard_set);
ClassDB::bind_method(D_METHOD("clipboard_get"), &DisplayServer::clipboard_get);
+ ClassDB::bind_method(D_METHOD("clipboard_has"), &DisplayServer::clipboard_has);
+ ClassDB::bind_method(D_METHOD("clipboard_set_primary", "clipboard_primary"), &DisplayServer::clipboard_set_primary);
+ ClassDB::bind_method(D_METHOD("clipboard_get_primary"), &DisplayServer::clipboard_get_primary);
ClassDB::bind_method(D_METHOD("get_screen_count"), &DisplayServer::get_screen_count);
ClassDB::bind_method(D_METHOD("screen_get_position", "screen"), &DisplayServer::screen_get_position, DEFVAL(SCREEN_OF_MAIN_WINDOW));
@@ -432,9 +438,6 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("ime_get_selection"), &DisplayServer::ime_get_selection);
ClassDB::bind_method(D_METHOD("ime_get_text"), &DisplayServer::ime_get_text);
- 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", "multiline", "max_length", "cursor_start", "cursor_end"), &DisplayServer::virtual_keyboard_show, DEFVAL(Rect2i()), DEFVAL(false), DEFVAL(-1), DEFVAL(-1), DEFVAL(-1));
ClassDB::bind_method(D_METHOD("virtual_keyboard_hide"), &DisplayServer::virtual_keyboard_hide);
@@ -479,7 +482,6 @@ void DisplayServer::_bind_methods() {
BIND_ENUM_CONSTANT(FEATURE_CURSOR_SHAPE);
BIND_ENUM_CONSTANT(FEATURE_CUSTOM_CURSOR_SHAPE);
BIND_ENUM_CONSTANT(FEATURE_NATIVE_DIALOG);
- BIND_ENUM_CONSTANT(FEATURE_CONSOLE_WINDOW);
BIND_ENUM_CONSTANT(FEATURE_IME);
BIND_ENUM_CONSTANT(FEATURE_WINDOW_TRANSPARENCY);
BIND_ENUM_CONSTANT(FEATURE_HIDPI);
@@ -487,6 +489,7 @@ void DisplayServer::_bind_methods() {
BIND_ENUM_CONSTANT(FEATURE_NATIVE_ICON);
BIND_ENUM_CONSTANT(FEATURE_ORIENTATION);
BIND_ENUM_CONSTANT(FEATURE_SWAP_BUFFERS);
+ BIND_ENUM_CONSTANT(FEATURE_CLIPBOARD_PRIMARY);
BIND_ENUM_CONSTANT(MOUSE_MODE_VISIBLE);
BIND_ENUM_CONSTANT(MOUSE_MODE_HIDDEN);
diff --git a/servers/display_server.h b/servers/display_server.h
index f411a72aa3..0c2bc5dd3a 100644
--- a/servers/display_server.h
+++ b/servers/display_server.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -105,7 +105,6 @@ public:
FEATURE_CURSOR_SHAPE,
FEATURE_CUSTOM_CURSOR_SHAPE,
FEATURE_NATIVE_DIALOG,
- FEATURE_CONSOLE_WINDOW,
FEATURE_IME,
FEATURE_WINDOW_TRANSPARENCY,
FEATURE_HIDPI,
@@ -114,6 +113,7 @@ public:
FEATURE_ORIENTATION,
FEATURE_SWAP_BUFFERS,
FEATURE_KEEP_SCREEN_ON,
+ FEATURE_CLIPBOARD_PRIMARY,
};
virtual bool has_feature(Feature p_feature) const = 0;
@@ -156,11 +156,13 @@ public:
virtual void mouse_warp_to_position(const Point2i &p_to);
virtual Point2i mouse_get_position() const;
- virtual Point2i mouse_get_absolute_position() const;
virtual MouseButton mouse_get_button_state() const;
virtual void clipboard_set(const String &p_text);
virtual String clipboard_get() const;
+ virtual bool clipboard_has() const;
+ virtual void clipboard_set_primary(const String &p_text);
+ virtual String clipboard_get_primary() const;
enum {
SCREEN_OF_MAIN_WINDOW = -1
@@ -295,12 +297,12 @@ public:
virtual void window_set_ime_active(const bool p_active, WindowID p_window = MAIN_WINDOW_ID);
virtual void window_set_ime_position(const Point2i &p_pos, WindowID p_window = MAIN_WINDOW_ID);
+ // necessary for GL focus, may be able to use one of the existing functions for this, not sure yet
+ virtual void gl_window_make_current(DisplayServer::WindowID p_window_id);
+
virtual Point2i ime_get_selection() const;
virtual String ime_get_text() const;
- 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(), bool p_multiline = false, int p_max_length = -1, int p_cursor_start = -1, int p_cursor_end = -1);
virtual void virtual_keyboard_hide();
diff --git a/servers/display_server_headless.h b/servers/display_server_headless.h
index d9ee91084f..4ef9dc622f 100644
--- a/servers/display_server_headless.h
+++ b/servers/display_server_headless.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -65,7 +65,11 @@ public:
Vector<DisplayServer::WindowID> get_window_list() const override { return Vector<DisplayServer::WindowID>(); }
- WindowID get_window_at_screen_position(const Point2i &p_position) const override { return -1; }
+ WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i()) override { return 0; }
+ void show_window(WindowID p_id) override {}
+ void delete_sub_window(WindowID p_id) override {}
+
+ WindowID get_window_at_screen_position(const Point2i &p_position) const override { return 0; }
void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID) override {}
ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const override { return ObjectID(); }
@@ -93,7 +97,7 @@ public:
Size2i window_get_max_size(WindowID p_window = MAIN_WINDOW_ID) const override { return Size2i(); }
void window_set_min_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override {}
- Size2i window_get_min_size(WindowID p_window = MAIN_WINDOW_ID) const override { return Size2i(); };
+ Size2i window_get_min_size(WindowID p_window = MAIN_WINDOW_ID) const override { return Size2i(); }
void window_set_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override {}
Size2i window_get_size(WindowID p_window = MAIN_WINDOW_ID) const override { return Size2i(); }
@@ -102,10 +106,13 @@ public:
void window_set_mode(WindowMode p_mode, WindowID p_window = MAIN_WINDOW_ID) override {}
WindowMode window_get_mode(WindowID p_window = MAIN_WINDOW_ID) const override { return WINDOW_MODE_MINIMIZED; }
+ void window_set_vsync_mode(VSyncMode p_vsync_mode, WindowID p_window = MAIN_WINDOW_ID) override {}
+ VSyncMode window_get_vsync_mode(WindowID p_window) const override { return VSyncMode::VSYNC_ENABLED; }
+
bool window_is_maximize_allowed(WindowID p_window = MAIN_WINDOW_ID) const override { return false; }
void window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window = MAIN_WINDOW_ID) override {}
- virtual bool window_get_flag(WindowFlags p_flag, WindowID p_window = MAIN_WINDOW_ID) const override { return false; }
+ bool window_get_flag(WindowFlags p_flag, WindowID p_window = MAIN_WINDOW_ID) const override { return false; }
void window_request_attention(WindowID p_window = MAIN_WINDOW_ID) override {}
void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID) override {}
@@ -114,6 +121,9 @@ public:
bool can_any_window_draw() const override { return false; }
+ void window_set_ime_active(const bool p_active, WindowID p_window = MAIN_WINDOW_ID) override {}
+ void window_set_ime_position(const Point2i &p_pos, WindowID p_window = MAIN_WINDOW_ID) override {}
+
void process_events() override {}
void set_icon(const Ref<Image> &p_icon) override {}
diff --git a/servers/navigation_server_2d.cpp b/servers/navigation_server_2d.cpp
index 85b12f1585..ee196673a3 100644
--- a/servers/navigation_server_2d.cpp
+++ b/servers/navigation_server_2d.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -29,14 +29,11 @@
/*************************************************************************/
#include "servers/navigation_server_2d.h"
+
#include "core/math/transform_2d.h"
#include "core/math/transform_3d.h"
#include "servers/navigation_server_3d.h"
-/**
- @author AndreaCatania
-*/
-
NavigationServer2D *NavigationServer2D::singleton = nullptr;
#define FORWARD_0_C(FUNC_NAME) \
@@ -204,7 +201,7 @@ void NavigationServer2D::_bind_methods() {
NavigationServer2D::NavigationServer2D() {
singleton = this;
ERR_FAIL_COND_MSG(!NavigationServer3D::get_singleton(), "The Navigation3D singleton should be initialized before the 2D one.");
- NavigationServer3D::get_singleton()->connect("map_changed", callable_mp(this, &NavigationServer2D::_emit_map_changed));
+ NavigationServer3D::get_singleton_mut()->connect("map_changed", callable_mp(this, &NavigationServer2D::_emit_map_changed));
}
NavigationServer2D::~NavigationServer2D() {
diff --git a/servers/navigation_server_2d.h b/servers/navigation_server_2d.h
index d56c719839..7350eeb5b1 100644
--- a/servers/navigation_server_2d.h
+++ b/servers/navigation_server_2d.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,12 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-/**
- @author AndreaCatania
-*/
-
-#ifndef NAVIGATION_2D_SERVER_H
-#define NAVIGATION_2D_SERVER_H
+#ifndef NAVIGATION_SERVER_2D_H
+#define NAVIGATION_SERVER_2D_H
#include "core/object/class_db.h"
#include "core/templates/rid.h"
@@ -52,7 +48,7 @@ protected:
public:
/// Thread safe, can be used across many threads.
- static NavigationServer2D *get_singleton() { return singleton; }
+ static const NavigationServer2D *get_singleton() { return singleton; }
/// MUST be used in single thread!
static NavigationServer2D *get_singleton_mut() { return singleton; }
@@ -171,4 +167,4 @@ public:
virtual ~NavigationServer2D();
};
-#endif
+#endif // NAVIGATION_SERVER_2D_H
diff --git a/servers/navigation_server_3d.cpp b/servers/navigation_server_3d.cpp
index b0047a250a..d18777869a 100644
--- a/servers/navigation_server_3d.cpp
+++ b/servers/navigation_server_3d.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,10 +28,6 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-/**
- @author AndreaCatania
-*/
-
#include "navigation_server_3d.h"
NavigationServer3D *NavigationServer3D::singleton = nullptr;
@@ -84,7 +80,7 @@ void NavigationServer3D::_bind_methods() {
ADD_SIGNAL(MethodInfo("map_changed", PropertyInfo(Variant::RID, "map")));
}
-NavigationServer3D *NavigationServer3D::get_singleton() {
+const NavigationServer3D *NavigationServer3D::get_singleton() {
return singleton;
}
diff --git a/servers/navigation_server_3d.h b/servers/navigation_server_3d.h
index 3aef693ac8..0a75b07931 100644
--- a/servers/navigation_server_3d.h
+++ b/servers/navigation_server_3d.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,12 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-/**
- @author AndreaCatania
-*/
-
-#ifndef NAVIGATION_SERVER_H
-#define NAVIGATION_SERVER_H
+#ifndef NAVIGATION_SERVER_3D_H
+#define NAVIGATION_SERVER_3D_H
#include "core/object/class_db.h"
#include "core/templates/rid.h"
@@ -55,7 +51,7 @@ protected:
public:
/// Thread safe, can be used across many threads.
- static NavigationServer3D *get_singleton();
+ static const NavigationServer3D *get_singleton();
/// MUST be used in single thread!
static NavigationServer3D *get_singleton_mut();
@@ -205,4 +201,4 @@ public:
static NavigationServer3D *new_default_server();
};
-#endif
+#endif // NAVIGATION_SERVER_3D_H
diff --git a/servers/physics_2d/body_direct_state_2d_sw.cpp b/servers/physics_2d/body_direct_state_2d_sw.cpp
deleted file mode 100644
index b0673b9006..0000000000
--- a/servers/physics_2d/body_direct_state_2d_sw.cpp
+++ /dev/null
@@ -1,178 +0,0 @@
-/*************************************************************************/
-/* body_direct_state_2d_sw.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 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 "body_direct_state_2d_sw.h"
-
-#include "body_2d_sw.h"
-#include "physics_server_2d_sw.h"
-#include "space_2d_sw.h"
-
-Vector2 PhysicsDirectBodyState2DSW::get_total_gravity() const {
- return body->gravity;
-}
-
-real_t PhysicsDirectBodyState2DSW::get_total_angular_damp() const {
- return body->area_angular_damp;
-}
-
-real_t PhysicsDirectBodyState2DSW::get_total_linear_damp() const {
- return body->area_linear_damp;
-}
-
-Vector2 PhysicsDirectBodyState2DSW::get_center_of_mass() const {
- return body->get_center_of_mass();
-}
-
-real_t PhysicsDirectBodyState2DSW::get_inverse_mass() const {
- return body->get_inv_mass();
-}
-
-real_t PhysicsDirectBodyState2DSW::get_inverse_inertia() const {
- return body->get_inv_inertia();
-}
-
-void PhysicsDirectBodyState2DSW::set_linear_velocity(const Vector2 &p_velocity) {
- body->wakeup();
- body->set_linear_velocity(p_velocity);
-}
-
-Vector2 PhysicsDirectBodyState2DSW::get_linear_velocity() const {
- return body->get_linear_velocity();
-}
-
-void PhysicsDirectBodyState2DSW::set_angular_velocity(real_t p_velocity) {
- body->wakeup();
- body->set_angular_velocity(p_velocity);
-}
-
-real_t PhysicsDirectBodyState2DSW::get_angular_velocity() const {
- return body->get_angular_velocity();
-}
-
-void PhysicsDirectBodyState2DSW::set_transform(const Transform2D &p_transform) {
- body->set_state(PhysicsServer2D::BODY_STATE_TRANSFORM, p_transform);
-}
-
-Transform2D PhysicsDirectBodyState2DSW::get_transform() const {
- return body->get_transform();
-}
-
-Vector2 PhysicsDirectBodyState2DSW::get_velocity_at_local_position(const Vector2 &p_position) const {
- return body->get_velocity_in_local_point(p_position);
-}
-
-void PhysicsDirectBodyState2DSW::add_central_force(const Vector2 &p_force) {
- body->wakeup();
- body->add_central_force(p_force);
-}
-
-void PhysicsDirectBodyState2DSW::add_force(const Vector2 &p_force, const Vector2 &p_position) {
- body->wakeup();
- body->add_force(p_force, p_position);
-}
-
-void PhysicsDirectBodyState2DSW::add_torque(real_t p_torque) {
- body->wakeup();
- body->add_torque(p_torque);
-}
-
-void PhysicsDirectBodyState2DSW::apply_central_impulse(const Vector2 &p_impulse) {
- body->wakeup();
- body->apply_central_impulse(p_impulse);
-}
-
-void PhysicsDirectBodyState2DSW::apply_impulse(const Vector2 &p_impulse, const Vector2 &p_position) {
- body->wakeup();
- body->apply_impulse(p_impulse, p_position);
-}
-
-void PhysicsDirectBodyState2DSW::apply_torque_impulse(real_t p_torque) {
- body->wakeup();
- body->apply_torque_impulse(p_torque);
-}
-
-void PhysicsDirectBodyState2DSW::set_sleep_state(bool p_enable) {
- body->set_active(!p_enable);
-}
-
-bool PhysicsDirectBodyState2DSW::is_sleeping() const {
- return !body->is_active();
-}
-
-int PhysicsDirectBodyState2DSW::get_contact_count() const {
- return body->contact_count;
-}
-
-Vector2 PhysicsDirectBodyState2DSW::get_contact_local_position(int p_contact_idx) const {
- ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector2());
- return body->contacts[p_contact_idx].local_pos;
-}
-
-Vector2 PhysicsDirectBodyState2DSW::get_contact_local_normal(int p_contact_idx) const {
- ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector2());
- return body->contacts[p_contact_idx].local_normal;
-}
-
-int PhysicsDirectBodyState2DSW::get_contact_local_shape(int p_contact_idx) const {
- ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, -1);
- return body->contacts[p_contact_idx].local_shape;
-}
-
-RID PhysicsDirectBodyState2DSW::get_contact_collider(int p_contact_idx) const {
- ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, RID());
- return body->contacts[p_contact_idx].collider;
-}
-Vector2 PhysicsDirectBodyState2DSW::get_contact_collider_position(int p_contact_idx) const {
- ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector2());
- return body->contacts[p_contact_idx].collider_pos;
-}
-
-ObjectID PhysicsDirectBodyState2DSW::get_contact_collider_id(int p_contact_idx) const {
- ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, ObjectID());
- return body->contacts[p_contact_idx].collider_instance_id;
-}
-
-int PhysicsDirectBodyState2DSW::get_contact_collider_shape(int p_contact_idx) const {
- ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, 0);
- return body->contacts[p_contact_idx].collider_shape;
-}
-
-Vector2 PhysicsDirectBodyState2DSW::get_contact_collider_velocity_at_position(int p_contact_idx) const {
- ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector2());
- return body->contacts[p_contact_idx].collider_velocity_at_pos;
-}
-
-PhysicsDirectSpaceState2D *PhysicsDirectBodyState2DSW::get_space_state() {
- return body->get_space()->get_direct_state();
-}
-
-real_t PhysicsDirectBodyState2DSW::get_step() const {
- return body->get_space()->get_last_step();
-}
diff --git a/servers/physics_2d/area_2d_sw.cpp b/servers/physics_2d/godot_area_2d.cpp
index c85b1575e3..9937178550 100644
--- a/servers/physics_2d/area_2d_sw.cpp
+++ b/servers/physics_2d/godot_area_2d.cpp
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* area_2d_sw.cpp */
+/* godot_area_2d.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,31 +28,31 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "area_2d_sw.h"
-#include "body_2d_sw.h"
-#include "space_2d_sw.h"
+#include "godot_area_2d.h"
+#include "godot_body_2d.h"
+#include "godot_space_2d.h"
-Area2DSW::BodyKey::BodyKey(Body2DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape) {
+GodotArea2D::BodyKey::BodyKey(GodotBody2D *p_body, uint32_t p_body_shape, uint32_t p_area_shape) {
rid = p_body->get_self();
instance_id = p_body->get_instance_id();
body_shape = p_body_shape;
area_shape = p_area_shape;
}
-Area2DSW::BodyKey::BodyKey(Area2DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape) {
+GodotArea2D::BodyKey::BodyKey(GodotArea2D *p_body, uint32_t p_body_shape, uint32_t p_area_shape) {
rid = p_body->get_self();
instance_id = p_body->get_instance_id();
body_shape = p_body_shape;
area_shape = p_area_shape;
}
-void Area2DSW::_shapes_changed() {
+void GodotArea2D::_shapes_changed() {
if (!moved_list.in_list() && get_space()) {
get_space()->area_add_to_moved_list(&moved_list);
}
}
-void Area2DSW::set_transform(const Transform2D &p_transform) {
+void GodotArea2D::set_transform(const Transform2D &p_transform) {
if (!moved_list.in_list() && get_space()) {
get_space()->area_add_to_moved_list(&moved_list);
}
@@ -61,7 +61,7 @@ void Area2DSW::set_transform(const Transform2D &p_transform) {
_set_inv_transform(p_transform.affine_inverse());
}
-void Area2DSW::set_space(Space2DSW *p_space) {
+void GodotArea2D::set_space(GodotSpace2D *p_space) {
if (get_space()) {
if (monitor_query_list.in_list()) {
get_space()->area_remove_from_monitor_query_list(&monitor_query_list);
@@ -77,16 +77,17 @@ void Area2DSW::set_space(Space2DSW *p_space) {
_set_space(p_space);
}
-void Area2DSW::set_monitor_callback(ObjectID p_id, const StringName &p_method) {
- if (p_id == monitor_callback_id) {
- monitor_callback_method = p_method;
+void GodotArea2D::set_monitor_callback(const Callable &p_callback) {
+ ObjectID id = p_callback.get_object_id();
+
+ if (id == monitor_callback.get_object_id()) {
+ monitor_callback = p_callback;
return;
}
_unregister_shapes();
- monitor_callback_id = p_id;
- monitor_callback_method = p_method;
+ monitor_callback = p_callback;
monitored_bodies.clear();
monitored_areas.clear();
@@ -98,16 +99,17 @@ void Area2DSW::set_monitor_callback(ObjectID p_id, const StringName &p_method) {
}
}
-void Area2DSW::set_area_monitor_callback(ObjectID p_id, const StringName &p_method) {
- if (p_id == area_monitor_callback_id) {
- area_monitor_callback_method = p_method;
+void GodotArea2D::set_area_monitor_callback(const Callable &p_callback) {
+ ObjectID id = p_callback.get_object_id();
+
+ if (id == area_monitor_callback.get_object_id()) {
+ area_monitor_callback = p_callback;
return;
}
_unregister_shapes();
- area_monitor_callback_id = p_id;
- area_monitor_callback_method = p_method;
+ area_monitor_callback = p_callback;
monitored_bodies.clear();
monitored_areas.clear();
@@ -119,18 +121,21 @@ void Area2DSW::set_area_monitor_callback(ObjectID p_id, const StringName &p_meth
}
}
-void Area2DSW::set_space_override_mode(PhysicsServer2D::AreaSpaceOverrideMode p_mode) {
- bool do_override = p_mode != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED;
- if (do_override == (space_override_mode != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED)) {
+void GodotArea2D::_set_space_override_mode(PhysicsServer2D::AreaSpaceOverrideMode &r_mode, PhysicsServer2D::AreaSpaceOverrideMode p_new_mode) {
+ bool do_override = p_new_mode != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED;
+ if (do_override == (r_mode != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED)) {
return;
}
_unregister_shapes();
- space_override_mode = p_mode;
+ r_mode = p_new_mode;
_shape_changed();
}
-void Area2DSW::set_param(PhysicsServer2D::AreaParameter p_param, const Variant &p_value) {
+void GodotArea2D::set_param(PhysicsServer2D::AreaParameter p_param, const Variant &p_value) {
switch (p_param) {
+ case PhysicsServer2D::AREA_PARAM_GRAVITY_OVERRIDE_MODE:
+ _set_space_override_mode(gravity_override_mode, (PhysicsServer2D::AreaSpaceOverrideMode)(int)p_value);
+ break;
case PhysicsServer2D::AREA_PARAM_GRAVITY:
gravity = p_value;
break;
@@ -146,9 +151,15 @@ void Area2DSW::set_param(PhysicsServer2D::AreaParameter p_param, const Variant &
case PhysicsServer2D::AREA_PARAM_GRAVITY_POINT_ATTENUATION:
point_attenuation = p_value;
break;
+ case PhysicsServer2D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE:
+ _set_space_override_mode(linear_damping_override_mode, (PhysicsServer2D::AreaSpaceOverrideMode)(int)p_value);
+ break;
case PhysicsServer2D::AREA_PARAM_LINEAR_DAMP:
linear_damp = p_value;
break;
+ case PhysicsServer2D::AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE:
+ _set_space_override_mode(angular_damping_override_mode, (PhysicsServer2D::AreaSpaceOverrideMode)(int)p_value);
+ break;
case PhysicsServer2D::AREA_PARAM_ANGULAR_DAMP:
angular_damp = p_value;
break;
@@ -158,8 +169,10 @@ void Area2DSW::set_param(PhysicsServer2D::AreaParameter p_param, const Variant &
}
}
-Variant Area2DSW::get_param(PhysicsServer2D::AreaParameter p_param) const {
+Variant GodotArea2D::get_param(PhysicsServer2D::AreaParameter p_param) const {
switch (p_param) {
+ case PhysicsServer2D::AREA_PARAM_GRAVITY_OVERRIDE_MODE:
+ return gravity_override_mode;
case PhysicsServer2D::AREA_PARAM_GRAVITY:
return gravity;
case PhysicsServer2D::AREA_PARAM_GRAVITY_VECTOR:
@@ -170,8 +183,12 @@ Variant Area2DSW::get_param(PhysicsServer2D::AreaParameter p_param) const {
return gravity_distance_scale;
case PhysicsServer2D::AREA_PARAM_GRAVITY_POINT_ATTENUATION:
return point_attenuation;
+ case PhysicsServer2D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE:
+ return linear_damping_override_mode;
case PhysicsServer2D::AREA_PARAM_LINEAR_DAMP:
return linear_damp;
+ case PhysicsServer2D::AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE:
+ return angular_damping_override_mode;
case PhysicsServer2D::AREA_PARAM_ANGULAR_DAMP:
return angular_damp;
case PhysicsServer2D::AREA_PARAM_PRIORITY:
@@ -181,7 +198,7 @@ Variant Area2DSW::get_param(PhysicsServer2D::AreaParameter p_param) const {
return Variant();
}
-void Area2DSW::_queue_monitor_update() {
+void GodotArea2D::_queue_monitor_update() {
ERR_FAIL_COND(!get_space());
if (!monitor_query_list.in_list()) {
@@ -189,92 +206,91 @@ void Area2DSW::_queue_monitor_update() {
}
}
-void Area2DSW::set_monitorable(bool p_monitorable) {
+void GodotArea2D::set_monitorable(bool p_monitorable) {
if (monitorable == p_monitorable) {
return;
}
monitorable = p_monitorable;
_set_static(!monitorable);
+ _shapes_changed();
}
-void Area2DSW::call_queries() {
- if (monitor_callback_id.is_valid() && !monitored_bodies.is_empty()) {
- Variant res[5];
- Variant *resptr[5];
- for (int i = 0; i < 5; i++) {
- resptr[i] = &res[i];
- }
+void GodotArea2D::call_queries() {
+ if (!monitor_callback.is_null() && !monitored_bodies.is_empty()) {
+ if (monitor_callback.is_valid()) {
+ Variant res[5];
+ Variant *resptr[5];
+ for (int i = 0; i < 5; i++) {
+ resptr[i] = &res[i];
+ }
- Object *obj = ObjectDB::get_instance(monitor_callback_id);
- if (!obj) {
- monitored_bodies.clear();
- monitor_callback_id = ObjectID();
- return;
- }
+ for (Map<BodyKey, BodyState>::Element *E = monitored_bodies.front(); E;) {
+ if (E->get().state == 0) { // Nothing happened
+ Map<BodyKey, BodyState>::Element *next = E->next();
+ monitored_bodies.erase(E);
+ E = next;
+ continue;
+ }
+
+ res[0] = E->get().state > 0 ? PhysicsServer2D::AREA_BODY_ADDED : PhysicsServer2D::AREA_BODY_REMOVED;
+ res[1] = E->key().rid;
+ res[2] = E->key().instance_id;
+ res[3] = E->key().body_shape;
+ res[4] = E->key().area_shape;
- for (Map<BodyKey, BodyState>::Element *E = monitored_bodies.front(); E;) {
- if (E->get().state == 0) { // Nothing happened
Map<BodyKey, BodyState>::Element *next = E->next();
monitored_bodies.erase(E);
E = next;
- continue;
- }
- res[0] = E->get().state > 0 ? PhysicsServer2D::AREA_BODY_ADDED : PhysicsServer2D::AREA_BODY_REMOVED;
- res[1] = E->key().rid;
- res[2] = E->key().instance_id;
- res[3] = E->key().body_shape;
- res[4] = E->key().area_shape;
-
- Map<BodyKey, BodyState>::Element *next = E->next();
- monitored_bodies.erase(E);
- E = next;
-
- Callable::CallError ce;
- obj->call(monitor_callback_method, (const Variant **)resptr, 5, ce);
+ Callable::CallError ce;
+ Variant ret;
+ monitor_callback.call((const Variant **)resptr, 5, ret, ce);
+ }
+ } else {
+ monitored_bodies.clear();
+ monitor_callback = Callable();
}
}
- if (area_monitor_callback_id.is_valid() && !monitored_areas.is_empty()) {
- Variant res[5];
- Variant *resptr[5];
- for (int i = 0; i < 5; i++) {
- resptr[i] = &res[i];
- }
+ if (!area_monitor_callback.is_null() && !monitored_areas.is_empty()) {
+ if (area_monitor_callback.is_valid()) {
+ Variant res[5];
+ Variant *resptr[5];
+ for (int i = 0; i < 5; i++) {
+ resptr[i] = &res[i];
+ }
- Object *obj = ObjectDB::get_instance(area_monitor_callback_id);
- if (!obj) {
- monitored_areas.clear();
- area_monitor_callback_id = ObjectID();
- return;
- }
+ for (Map<BodyKey, BodyState>::Element *E = monitored_areas.front(); E;) {
+ if (E->get().state == 0) { // Nothing happened
+ Map<BodyKey, BodyState>::Element *next = E->next();
+ monitored_areas.erase(E);
+ E = next;
+ continue;
+ }
+
+ res[0] = E->get().state > 0 ? PhysicsServer2D::AREA_BODY_ADDED : PhysicsServer2D::AREA_BODY_REMOVED;
+ res[1] = E->key().rid;
+ res[2] = E->key().instance_id;
+ res[3] = E->key().body_shape;
+ res[4] = E->key().area_shape;
- for (Map<BodyKey, BodyState>::Element *E = monitored_areas.front(); E;) {
- if (E->get().state == 0) { // Nothing happened
Map<BodyKey, BodyState>::Element *next = E->next();
monitored_areas.erase(E);
E = next;
- continue;
- }
-
- res[0] = E->get().state > 0 ? PhysicsServer2D::AREA_BODY_ADDED : PhysicsServer2D::AREA_BODY_REMOVED;
- res[1] = E->key().rid;
- res[2] = E->key().instance_id;
- res[3] = E->key().body_shape;
- res[4] = E->key().area_shape;
-
- Map<BodyKey, BodyState>::Element *next = E->next();
- monitored_areas.erase(E);
- E = next;
- Callable::CallError ce;
- obj->call(area_monitor_callback_method, (const Variant **)resptr, 5, ce);
+ Callable::CallError ce;
+ Variant ret;
+ area_monitor_callback.call((const Variant **)resptr, 5, ret, ce);
+ }
+ } else {
+ monitored_areas.clear();
+ area_monitor_callback = Callable();
}
}
}
-void Area2DSW::compute_gravity(const Vector2 &p_position, Vector2 &r_gravity) const {
+void GodotArea2D::compute_gravity(const Vector2 &p_position, Vector2 &r_gravity) const {
if (is_gravity_point()) {
const real_t gravity_distance_scale = get_gravity_distance_scale();
Vector2 v = get_transform().xform(get_gravity_vector()) - p_position;
@@ -294,12 +310,12 @@ void Area2DSW::compute_gravity(const Vector2 &p_position, Vector2 &r_gravity) co
}
}
-Area2DSW::Area2DSW() :
- CollisionObject2DSW(TYPE_AREA),
+GodotArea2D::GodotArea2D() :
+ GodotCollisionObject2D(TYPE_AREA),
monitor_query_list(this),
moved_list(this) {
_set_static(true); //areas are not active by default
}
-Area2DSW::~Area2DSW() {
+GodotArea2D::~GodotArea2D() {
}
diff --git a/servers/physics_2d/area_2d_sw.h b/servers/physics_2d/godot_area_2d.h
index 0b7c791ed5..6e8078909b 100644
--- a/servers/physics_2d/area_2d_sw.h
+++ b/servers/physics_2d/godot_area_2d.h
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* area_2d_sw.h */
+/* godot_area_2d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,19 +28,23 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AREA_2D_SW_H
-#define AREA_2D_SW_H
+#ifndef GODOT_AREA_2D_H
+#define GODOT_AREA_2D_H
+
+#include "godot_collision_object_2d.h"
-#include "collision_object_2d_sw.h"
#include "core/templates/self_list.h"
#include "servers/physics_server_2d.h"
-class Space2DSW;
-class Body2DSW;
-class Constraint2DSW;
+class GodotSpace2D;
+class GodotBody2D;
+class GodotConstraint2D;
+
+class GodotArea2D : public GodotCollisionObject2D {
+ PhysicsServer2D::AreaSpaceOverrideMode gravity_override_mode = PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED;
+ PhysicsServer2D::AreaSpaceOverrideMode linear_damping_override_mode = PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED;
+ PhysicsServer2D::AreaSpaceOverrideMode angular_damping_override_mode = PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED;
-class Area2DSW : public CollisionObject2DSW {
- PhysicsServer2D::AreaSpaceOverrideMode space_override_mode = PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED;
real_t gravity = 9.80665;
Vector2 gravity_vector = Vector2(0, -1);
bool gravity_is_point = false;
@@ -51,14 +55,12 @@ class Area2DSW : public CollisionObject2DSW {
int priority = 0;
bool monitorable = false;
- ObjectID monitor_callback_id;
- StringName monitor_callback_method;
+ Callable monitor_callback;
- ObjectID area_monitor_callback_id;
- StringName area_monitor_callback_method;
+ Callable area_monitor_callback;
- SelfList<Area2DSW> monitor_query_list;
- SelfList<Area2DSW> moved_list;
+ SelfList<GodotArea2D> monitor_query_list;
+ SelfList<GodotArea2D> moved_list;
struct BodyKey {
RID rid;
@@ -79,8 +81,8 @@ class Area2DSW : public CollisionObject2DSW {
}
_FORCE_INLINE_ BodyKey() {}
- BodyKey(Body2DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape);
- BodyKey(Area2DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape);
+ BodyKey(GodotBody2D *p_body, uint32_t p_body_shape, uint32_t p_area_shape);
+ BodyKey(GodotArea2D *p_body, uint32_t p_body_shape, uint32_t p_area_shape);
};
struct BodyState {
@@ -92,30 +94,29 @@ class Area2DSW : public CollisionObject2DSW {
Map<BodyKey, BodyState> monitored_bodies;
Map<BodyKey, BodyState> monitored_areas;
- Set<Constraint2DSW *> constraints;
+ Set<GodotConstraint2D *> constraints;
virtual void _shapes_changed();
void _queue_monitor_update();
+ void _set_space_override_mode(PhysicsServer2D::AreaSpaceOverrideMode &r_mode, PhysicsServer2D::AreaSpaceOverrideMode p_new_mode);
+
public:
- void set_monitor_callback(ObjectID p_id, const StringName &p_method);
- _FORCE_INLINE_ bool has_monitor_callback() const { return monitor_callback_id.is_valid(); }
+ void set_monitor_callback(const Callable &p_callback);
+ _FORCE_INLINE_ bool has_monitor_callback() const { return !monitor_callback.is_null(); }
- void set_area_monitor_callback(ObjectID p_id, const StringName &p_method);
- _FORCE_INLINE_ bool has_area_monitor_callback() const { return area_monitor_callback_id.is_valid(); }
+ void set_area_monitor_callback(const Callable &p_callback);
+ _FORCE_INLINE_ bool has_area_monitor_callback() const { return !area_monitor_callback.is_null(); }
- _FORCE_INLINE_ void add_body_to_query(Body2DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape);
- _FORCE_INLINE_ void remove_body_from_query(Body2DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape);
+ _FORCE_INLINE_ void add_body_to_query(GodotBody2D *p_body, uint32_t p_body_shape, uint32_t p_area_shape);
+ _FORCE_INLINE_ void remove_body_from_query(GodotBody2D *p_body, uint32_t p_body_shape, uint32_t p_area_shape);
- _FORCE_INLINE_ void add_area_to_query(Area2DSW *p_area, uint32_t p_area_shape, uint32_t p_self_shape);
- _FORCE_INLINE_ void remove_area_from_query(Area2DSW *p_area, uint32_t p_area_shape, uint32_t p_self_shape);
+ _FORCE_INLINE_ void add_area_to_query(GodotArea2D *p_area, uint32_t p_area_shape, uint32_t p_self_shape);
+ _FORCE_INLINE_ void remove_area_from_query(GodotArea2D *p_area, uint32_t p_area_shape, uint32_t p_self_shape);
void set_param(PhysicsServer2D::AreaParameter p_param, const Variant &p_value);
Variant get_param(PhysicsServer2D::AreaParameter p_param) const;
- void set_space_override_mode(PhysicsServer2D::AreaSpaceOverrideMode p_mode);
- PhysicsServer2D::AreaSpaceOverrideMode get_space_override_mode() const { return space_override_mode; }
-
_FORCE_INLINE_ void set_gravity(real_t p_gravity) { gravity = p_gravity; }
_FORCE_INLINE_ real_t get_gravity() const { return gravity; }
@@ -140,9 +141,9 @@ public:
_FORCE_INLINE_ void set_priority(int p_priority) { priority = p_priority; }
_FORCE_INLINE_ int get_priority() const { return priority; }
- _FORCE_INLINE_ void add_constraint(Constraint2DSW *p_constraint) { constraints.insert(p_constraint); }
- _FORCE_INLINE_ void remove_constraint(Constraint2DSW *p_constraint) { constraints.erase(p_constraint); }
- _FORCE_INLINE_ const Set<Constraint2DSW *> &get_constraints() const { return constraints; }
+ _FORCE_INLINE_ void add_constraint(GodotConstraint2D *p_constraint) { constraints.insert(p_constraint); }
+ _FORCE_INLINE_ void remove_constraint(GodotConstraint2D *p_constraint) { constraints.erase(p_constraint); }
+ _FORCE_INLINE_ const Set<GodotConstraint2D *> &get_constraints() const { return constraints; }
_FORCE_INLINE_ void clear_constraints() { constraints.clear(); }
void set_monitorable(bool p_monitorable);
@@ -150,17 +151,17 @@ public:
void set_transform(const Transform2D &p_transform);
- void set_space(Space2DSW *p_space);
+ void set_space(GodotSpace2D *p_space);
void call_queries();
void compute_gravity(const Vector2 &p_position, Vector2 &r_gravity) const;
- Area2DSW();
- ~Area2DSW();
+ GodotArea2D();
+ ~GodotArea2D();
};
-void Area2DSW::add_body_to_query(Body2DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape) {
+void GodotArea2D::add_body_to_query(GodotBody2D *p_body, uint32_t p_body_shape, uint32_t p_area_shape) {
BodyKey bk(p_body, p_body_shape, p_area_shape);
monitored_bodies[bk].inc();
if (!monitor_query_list.in_list()) {
@@ -168,7 +169,7 @@ void Area2DSW::add_body_to_query(Body2DSW *p_body, uint32_t p_body_shape, uint32
}
}
-void Area2DSW::remove_body_from_query(Body2DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape) {
+void GodotArea2D::remove_body_from_query(GodotBody2D *p_body, uint32_t p_body_shape, uint32_t p_area_shape) {
BodyKey bk(p_body, p_body_shape, p_area_shape);
monitored_bodies[bk].dec();
if (!monitor_query_list.in_list()) {
@@ -176,7 +177,7 @@ void Area2DSW::remove_body_from_query(Body2DSW *p_body, uint32_t p_body_shape, u
}
}
-void Area2DSW::add_area_to_query(Area2DSW *p_area, uint32_t p_area_shape, uint32_t p_self_shape) {
+void GodotArea2D::add_area_to_query(GodotArea2D *p_area, uint32_t p_area_shape, uint32_t p_self_shape) {
BodyKey bk(p_area, p_area_shape, p_self_shape);
monitored_areas[bk].inc();
if (!monitor_query_list.in_list()) {
@@ -184,7 +185,7 @@ void Area2DSW::add_area_to_query(Area2DSW *p_area, uint32_t p_area_shape, uint32
}
}
-void Area2DSW::remove_area_from_query(Area2DSW *p_area, uint32_t p_area_shape, uint32_t p_self_shape) {
+void GodotArea2D::remove_area_from_query(GodotArea2D *p_area, uint32_t p_area_shape, uint32_t p_self_shape) {
BodyKey bk(p_area, p_area_shape, p_self_shape);
monitored_areas[bk].dec();
if (!monitor_query_list.in_list()) {
@@ -192,4 +193,4 @@ void Area2DSW::remove_area_from_query(Area2DSW *p_area, uint32_t p_area_shape, u
}
}
-#endif // AREA_2D_SW_H
+#endif // GODOT_AREA_2D_H
diff --git a/servers/physics_2d/area_pair_2d_sw.cpp b/servers/physics_2d/godot_area_pair_2d.cpp
index 4f1148c26f..72208d7dff 100644
--- a/servers/physics_2d/area_pair_2d_sw.cpp
+++ b/servers/physics_2d/godot_area_pair_2d.cpp
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* area_pair_2d_sw.cpp */
+/* godot_area_pair_2d.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,20 +28,28 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "area_pair_2d_sw.h"
-#include "collision_solver_2d_sw.h"
+#include "godot_area_pair_2d.h"
+#include "godot_collision_solver_2d.h"
-bool AreaPair2DSW::setup(real_t p_step) {
+bool GodotAreaPair2D::setup(real_t p_step) {
bool result = false;
- if (area->collides_with(body) && CollisionSolver2DSW::solve(body->get_shape(body_shape), body->get_transform() * body->get_shape_transform(body_shape), Vector2(), area->get_shape(area_shape), area->get_transform() * area->get_shape_transform(area_shape), Vector2(), nullptr, this)) {
+ if (area->collides_with(body) && GodotCollisionSolver2D::solve(body->get_shape(body_shape), body->get_transform() * body->get_shape_transform(body_shape), Vector2(), area->get_shape(area_shape), area->get_transform() * area->get_shape_transform(area_shape), Vector2(), nullptr, this)) {
result = true;
}
process_collision = false;
+ has_space_override = false;
if (result != colliding) {
- if (area->get_space_override_mode() != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) {
- process_collision = true;
- } else if (area->has_monitor_callback()) {
+ if ((int)area->get_param(PhysicsServer2D::AREA_PARAM_GRAVITY_OVERRIDE_MODE) != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) {
+ has_space_override = true;
+ } else if ((int)area->get_param(PhysicsServer2D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE) != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) {
+ has_space_override = true;
+ } else if ((int)area->get_param(PhysicsServer2D::AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE) != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) {
+ has_space_override = true;
+ }
+ process_collision = has_space_override;
+
+ if (area->has_monitor_callback()) {
process_collision = true;
}
@@ -51,13 +59,13 @@ bool AreaPair2DSW::setup(real_t p_step) {
return process_collision;
}
-bool AreaPair2DSW::pre_solve(real_t p_step) {
+bool GodotAreaPair2D::pre_solve(real_t p_step) {
if (!process_collision) {
return false;
}
if (colliding) {
- if (area->get_space_override_mode() != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) {
+ if (has_space_override) {
body->add_area(area);
}
@@ -65,7 +73,7 @@ bool AreaPair2DSW::pre_solve(real_t p_step) {
area->add_body_to_query(body, body_shape, area_shape);
}
} else {
- if (area->get_space_override_mode() != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) {
+ if (has_space_override) {
body->remove_area(area);
}
@@ -77,11 +85,11 @@ bool AreaPair2DSW::pre_solve(real_t p_step) {
return false; // Never do any post solving.
}
-void AreaPair2DSW::solve(real_t p_step) {
+void GodotAreaPair2D::solve(real_t p_step) {
// Nothing to do.
}
-AreaPair2DSW::AreaPair2DSW(Body2DSW *p_body, int p_body_shape, Area2DSW *p_area, int p_area_shape) {
+GodotAreaPair2D::GodotAreaPair2D(GodotBody2D *p_body, int p_body_shape, GodotArea2D *p_area, int p_area_shape) {
body = p_body;
area = p_area;
body_shape = p_body_shape;
@@ -93,9 +101,9 @@ AreaPair2DSW::AreaPair2DSW(Body2DSW *p_body, int p_body_shape, Area2DSW *p_area,
}
}
-AreaPair2DSW::~AreaPair2DSW() {
+GodotAreaPair2D::~GodotAreaPair2D() {
if (colliding) {
- if (area->get_space_override_mode() != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) {
+ if (has_space_override) {
body->remove_area(area);
}
if (area->has_monitor_callback()) {
@@ -108,10 +116,10 @@ AreaPair2DSW::~AreaPair2DSW() {
//////////////////////////////////
-bool Area2Pair2DSW::setup(real_t p_step) {
+bool GodotArea2Pair2D::setup(real_t p_step) {
bool result_a = area_a->collides_with(area_b);
bool result_b = area_b->collides_with(area_a);
- if ((result_a || result_b) && !CollisionSolver2DSW::solve(area_a->get_shape(shape_a), area_a->get_transform() * area_a->get_shape_transform(shape_a), Vector2(), area_b->get_shape(shape_b), area_b->get_transform() * area_b->get_shape_transform(shape_b), Vector2(), nullptr, this)) {
+ if ((result_a || result_b) && !GodotCollisionSolver2D::solve(area_a->get_shape(shape_a), area_a->get_transform() * area_a->get_shape_transform(shape_a), Vector2(), area_b->get_shape(shape_b), area_b->get_transform() * area_b->get_shape_transform(shape_b), Vector2(), nullptr, this)) {
result_a = false;
result_b = false;
}
@@ -120,7 +128,7 @@ bool Area2Pair2DSW::setup(real_t p_step) {
process_collision_a = false;
if (result_a != colliding_a) {
- if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) {
+ if (area_a->has_area_monitor_callback() && area_b_monitorable) {
process_collision_a = true;
process_collision = true;
}
@@ -129,7 +137,7 @@ bool Area2Pair2DSW::setup(real_t p_step) {
process_collision_b = false;
if (result_b != colliding_b) {
- if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) {
+ if (area_b->has_area_monitor_callback() && area_a_monitorable) {
process_collision_b = true;
process_collision = true;
}
@@ -139,7 +147,7 @@ bool Area2Pair2DSW::setup(real_t p_step) {
return process_collision;
}
-bool Area2Pair2DSW::pre_solve(real_t p_step) {
+bool GodotArea2Pair2D::pre_solve(real_t p_step) {
if (process_collision_a) {
if (colliding_a) {
area_a->add_area_to_query(area_b, shape_b, shape_a);
@@ -159,28 +167,30 @@ bool Area2Pair2DSW::pre_solve(real_t p_step) {
return false; // Never do any post solving.
}
-void Area2Pair2DSW::solve(real_t p_step) {
+void GodotArea2Pair2D::solve(real_t p_step) {
// Nothing to do.
}
-Area2Pair2DSW::Area2Pair2DSW(Area2DSW *p_area_a, int p_shape_a, Area2DSW *p_area_b, int p_shape_b) {
+GodotArea2Pair2D::GodotArea2Pair2D(GodotArea2D *p_area_a, int p_shape_a, GodotArea2D *p_area_b, int p_shape_b) {
area_a = p_area_a;
area_b = p_area_b;
shape_a = p_shape_a;
shape_b = p_shape_b;
+ area_a_monitorable = area_a->is_monitorable();
+ area_b_monitorable = area_b->is_monitorable();
area_a->add_constraint(this);
area_b->add_constraint(this);
}
-Area2Pair2DSW::~Area2Pair2DSW() {
+GodotArea2Pair2D::~GodotArea2Pair2D() {
if (colliding_a) {
- if (area_a->has_area_monitor_callback()) {
+ if (area_a->has_area_monitor_callback() && area_b_monitorable) {
area_a->remove_area_from_query(area_b, shape_b, shape_a);
}
}
if (colliding_b) {
- if (area_b->has_area_monitor_callback()) {
+ if (area_b->has_area_monitor_callback() && area_a_monitorable) {
area_b->remove_area_from_query(area_a, shape_a, shape_b);
}
}
diff --git a/servers/physics_2d/area_pair_2d_sw.h b/servers/physics_2d/godot_area_pair_2d.h
index 66e9f1afee..ef6c774bc3 100644
--- a/servers/physics_2d/area_pair_2d_sw.h
+++ b/servers/physics_2d/godot_area_pair_2d.h
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* area_pair_2d_sw.h */
+/* godot_area_pair_2d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,19 +28,20 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AREA_PAIR_2D_SW_H
-#define AREA_PAIR_2D_SW_H
+#ifndef GODOT_AREA_PAIR_2D_H
+#define GODOT_AREA_PAIR_2D_H
-#include "area_2d_sw.h"
-#include "body_2d_sw.h"
-#include "constraint_2d_sw.h"
+#include "godot_area_2d.h"
+#include "godot_body_2d.h"
+#include "godot_constraint_2d.h"
-class AreaPair2DSW : public Constraint2DSW {
- Body2DSW *body = nullptr;
- Area2DSW *area = nullptr;
+class GodotAreaPair2D : public GodotConstraint2D {
+ GodotBody2D *body = nullptr;
+ GodotArea2D *area = nullptr;
int body_shape = 0;
int area_shape = 0;
bool colliding = false;
+ bool has_space_override = false;
bool process_collision = false;
public:
@@ -48,27 +49,29 @@ public:
virtual bool pre_solve(real_t p_step) override;
virtual void solve(real_t p_step) override;
- AreaPair2DSW(Body2DSW *p_body, int p_body_shape, Area2DSW *p_area, int p_area_shape);
- ~AreaPair2DSW();
+ GodotAreaPair2D(GodotBody2D *p_body, int p_body_shape, GodotArea2D *p_area, int p_area_shape);
+ ~GodotAreaPair2D();
};
-class Area2Pair2DSW : public Constraint2DSW {
- Area2DSW *area_a = nullptr;
- Area2DSW *area_b = nullptr;
+class GodotArea2Pair2D : public GodotConstraint2D {
+ GodotArea2D *area_a = nullptr;
+ GodotArea2D *area_b = nullptr;
int shape_a = 0;
int shape_b = 0;
bool colliding_a = false;
bool colliding_b = false;
bool process_collision_a = false;
bool process_collision_b = false;
+ bool area_a_monitorable;
+ bool area_b_monitorable;
public:
virtual bool setup(real_t p_step) override;
virtual bool pre_solve(real_t p_step) override;
virtual void solve(real_t p_step) override;
- Area2Pair2DSW(Area2DSW *p_area_a, int p_shape_a, Area2DSW *p_area_b, int p_shape_b);
- ~Area2Pair2DSW();
+ GodotArea2Pair2D(GodotArea2D *p_area_a, int p_shape_a, GodotArea2D *p_area_b, int p_shape_b);
+ ~GodotArea2Pair2D();
};
-#endif // AREA_PAIR_2D_SW_H
+#endif // GODOT_AREA_PAIR_2D_H
diff --git a/servers/physics_2d/body_2d_sw.cpp b/servers/physics_2d/godot_body_2d.cpp
index 38b98b7bca..6873504f70 100644
--- a/servers/physics_2d/body_2d_sw.cpp
+++ b/servers/physics_2d/godot_body_2d.cpp
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* body_2d_sw.cpp */
+/* godot_body_2d.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,19 +28,19 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "body_2d_sw.h"
+#include "godot_body_2d.h"
-#include "area_2d_sw.h"
-#include "body_direct_state_2d_sw.h"
-#include "space_2d_sw.h"
+#include "godot_area_2d.h"
+#include "godot_body_direct_state_2d.h"
+#include "godot_space_2d.h"
-void Body2DSW::_mass_properties_changed() {
+void GodotBody2D::_mass_properties_changed() {
if (get_space() && !mass_properties_update_list.in_list() && (calculate_inertia || calculate_center_of_mass)) {
get_space()->body_add_to_mass_properties_update_list(&mass_properties_update_list);
}
}
-void Body2DSW::update_mass_properties() {
+void GodotBody2D::update_mass_properties() {
//update shapes and motions
switch (mode) {
@@ -55,7 +55,7 @@ void Body2DSW::update_mass_properties() {
if (calculate_center_of_mass) {
// We have to recompute the center of mass.
- center_of_mass = Vector2();
+ center_of_mass_local = Vector2();
if (total_area != 0.0) {
for (int i = 0; i < get_shape_count(); i++) {
@@ -68,10 +68,10 @@ void Body2DSW::update_mass_properties() {
real_t mass = area * this->mass / total_area;
// NOTE: we assume that the shape origin is also its center of mass.
- center_of_mass += mass * get_shape_transform(i).get_origin();
+ center_of_mass_local += mass * get_shape_transform(i).get_origin();
}
- center_of_mass /= mass;
+ center_of_mass_local /= mass;
}
}
@@ -83,7 +83,7 @@ void Body2DSW::update_mass_properties() {
continue;
}
- const Shape2DSW *shape = get_shape(i);
+ const GodotShape2D *shape = get_shape(i);
real_t area = get_shape_aabb(i).get_area();
if (area == 0.0) {
@@ -94,7 +94,7 @@ void Body2DSW::update_mass_properties() {
Transform2D mtx = get_shape_transform(i);
Vector2 scale = mtx.get_scale();
- Vector2 shape_origin = mtx.get_origin() - center_of_mass;
+ Vector2 shape_origin = mtx.get_origin() - center_of_mass_local;
inertia += shape->get_moment_of_inertia(mass, scale) + mass * shape_origin.length_squared();
}
}
@@ -119,15 +119,17 @@ void Body2DSW::update_mass_properties() {
} break;
}
+
+ _update_transform_dependent();
}
-void Body2DSW::reset_mass_properties() {
+void GodotBody2D::reset_mass_properties() {
calculate_inertia = true;
calculate_center_of_mass = true;
_mass_properties_changed();
}
-void Body2DSW::set_active(bool p_active) {
+void GodotBody2D::set_active(bool p_active) {
if (active == p_active) {
return;
}
@@ -146,7 +148,7 @@ void Body2DSW::set_active(bool p_active) {
}
}
-void Body2DSW::set_param(PhysicsServer2D::BodyParameter p_param, const Variant &p_value) {
+void GodotBody2D::set_param(PhysicsServer2D::BodyParameter p_param, const Variant &p_value) {
switch (p_param) {
case PhysicsServer2D::BODY_PARAM_BOUNCE: {
bounce = p_value;
@@ -179,11 +181,23 @@ void Body2DSW::set_param(PhysicsServer2D::BodyParameter p_param, const Variant &
} break;
case PhysicsServer2D::BODY_PARAM_CENTER_OF_MASS: {
calculate_center_of_mass = false;
- center_of_mass = p_value;
+ center_of_mass_local = p_value;
+ _update_transform_dependent();
} break;
case PhysicsServer2D::BODY_PARAM_GRAVITY_SCALE: {
+ if (Math::is_zero_approx(gravity_scale)) {
+ wakeup();
+ }
gravity_scale = p_value;
} break;
+ case PhysicsServer2D::BODY_PARAM_LINEAR_DAMP_MODE: {
+ int mode_value = p_value;
+ linear_damp_mode = (PhysicsServer2D::BodyDampMode)mode_value;
+ } break;
+ case PhysicsServer2D::BODY_PARAM_ANGULAR_DAMP_MODE: {
+ int mode_value = p_value;
+ angular_damp_mode = (PhysicsServer2D::BodyDampMode)mode_value;
+ } break;
case PhysicsServer2D::BODY_PARAM_LINEAR_DAMP: {
linear_damp = p_value;
} break;
@@ -195,7 +209,7 @@ void Body2DSW::set_param(PhysicsServer2D::BodyParameter p_param, const Variant &
}
}
-Variant Body2DSW::get_param(PhysicsServer2D::BodyParameter p_param) const {
+Variant GodotBody2D::get_param(PhysicsServer2D::BodyParameter p_param) const {
switch (p_param) {
case PhysicsServer2D::BODY_PARAM_BOUNCE: {
return bounce;
@@ -210,11 +224,17 @@ Variant Body2DSW::get_param(PhysicsServer2D::BodyParameter p_param) const {
return inertia;
}
case PhysicsServer2D::BODY_PARAM_CENTER_OF_MASS: {
- return center_of_mass;
+ return center_of_mass_local;
}
case PhysicsServer2D::BODY_PARAM_GRAVITY_SCALE: {
return gravity_scale;
}
+ case PhysicsServer2D::BODY_PARAM_LINEAR_DAMP_MODE: {
+ return linear_damp_mode;
+ }
+ case PhysicsServer2D::BODY_PARAM_ANGULAR_DAMP_MODE: {
+ return angular_damp_mode;
+ }
case PhysicsServer2D::BODY_PARAM_LINEAR_DAMP: {
return linear_damp;
}
@@ -228,7 +248,7 @@ Variant Body2DSW::get_param(PhysicsServer2D::BodyParameter p_param) const {
return 0;
}
-void Body2DSW::set_mode(PhysicsServer2D::BodyMode p_mode) {
+void GodotBody2D::set_mode(PhysicsServer2D::BodyMode p_mode) {
PhysicsServer2D::BodyMode prev = mode;
mode = p_mode;
@@ -267,16 +287,17 @@ void Body2DSW::set_mode(PhysicsServer2D::BodyMode p_mode) {
}
}
-PhysicsServer2D::BodyMode Body2DSW::get_mode() const {
+PhysicsServer2D::BodyMode GodotBody2D::get_mode() const {
return mode;
}
-void Body2DSW::_shapes_changed() {
+void GodotBody2D::_shapes_changed() {
_mass_properties_changed();
+ wakeup();
wakeup_neighbours();
}
-void Body2DSW::set_state(PhysicsServer2D::BodyState p_state, const Variant &p_variant) {
+void GodotBody2D::set_state(PhysicsServer2D::BodyState p_state, const Variant &p_variant) {
switch (p_state) {
case PhysicsServer2D::BODY_STATE_TRANSFORM: {
if (mode == PhysicsServer2D::BODY_MODE_KINEMATIC) {
@@ -301,6 +322,7 @@ void Body2DSW::set_state(PhysicsServer2D::BodyState p_state, const Variant &p_va
}
_set_transform(t);
_set_inv_transform(get_transform().inverse());
+ _update_transform_dependent();
}
wakeup();
@@ -344,7 +366,7 @@ void Body2DSW::set_state(PhysicsServer2D::BodyState p_state, const Variant &p_va
}
}
-Variant Body2DSW::get_state(PhysicsServer2D::BodyState p_state) const {
+Variant GodotBody2D::get_state(PhysicsServer2D::BodyState p_state) const {
switch (p_state) {
case PhysicsServer2D::BODY_STATE_TRANSFORM: {
return get_transform();
@@ -366,7 +388,7 @@ Variant Body2DSW::get_state(PhysicsServer2D::BodyState p_state) const {
return Variant();
}
-void Body2DSW::set_space(Space2DSW *p_space) {
+void GodotBody2D::set_space(GodotSpace2D *p_space) {
if (get_space()) {
wakeup_neighbours();
@@ -391,75 +413,144 @@ void Body2DSW::set_space(Space2DSW *p_space) {
}
}
-void Body2DSW::_compute_area_gravity_and_damping(const Area2DSW *p_area) {
- Vector2 area_gravity;
- p_area->compute_gravity(get_transform().get_origin(), area_gravity);
- gravity += area_gravity;
-
- area_linear_damp += p_area->get_linear_damp();
- area_angular_damp += p_area->get_angular_damp();
+void GodotBody2D::_update_transform_dependent() {
+ center_of_mass = get_transform().basis_xform(center_of_mass_local);
}
-void Body2DSW::integrate_forces(real_t p_step) {
+void GodotBody2D::integrate_forces(real_t p_step) {
if (mode == PhysicsServer2D::BODY_MODE_STATIC) {
return;
}
- Area2DSW *def_area = get_space()->get_default_area();
- // Area2DSW *damp_area = def_area;
- ERR_FAIL_COND(!def_area);
+ ERR_FAIL_COND(!get_space());
int ac = areas.size();
+
+ bool gravity_done = false;
+ bool linear_damp_done = false;
+ bool angular_damp_done = false;
+
bool stopped = false;
+
gravity = Vector2(0, 0);
- area_angular_damp = 0;
- area_linear_damp = 0;
+
+ total_linear_damp = 0.0;
+ total_angular_damp = 0.0;
+
+ // Combine gravity and damping from overlapping areas in priority order.
if (ac) {
areas.sort();
const AreaCMP *aa = &areas[0];
- // damp_area = aa[ac-1].area;
for (int i = ac - 1; i >= 0 && !stopped; i--) {
- PhysicsServer2D::AreaSpaceOverrideMode mode = aa[i].area->get_space_override_mode();
- switch (mode) {
- case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE:
- case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: {
- _compute_area_gravity_and_damping(aa[i].area);
- stopped = mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE;
- } break;
- case PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE:
- case PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: {
- gravity = Vector2(0, 0);
- area_angular_damp = 0;
- area_linear_damp = 0;
- _compute_area_gravity_and_damping(aa[i].area);
- stopped = mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE;
- } break;
- default: {
+ if (!gravity_done) {
+ PhysicsServer2D::AreaSpaceOverrideMode area_gravity_mode = (PhysicsServer2D::AreaSpaceOverrideMode)(int)aa[i].area->get_param(PhysicsServer2D::AREA_PARAM_GRAVITY_OVERRIDE_MODE);
+ if (area_gravity_mode != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) {
+ Vector2 area_gravity;
+ aa[i].area->compute_gravity(get_transform().get_origin(), area_gravity);
+ switch (area_gravity_mode) {
+ case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE:
+ case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: {
+ gravity += area_gravity;
+ gravity_done = area_gravity_mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE;
+ } break;
+ case PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE:
+ case PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: {
+ gravity = area_gravity;
+ gravity_done = area_gravity_mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE;
+ } break;
+ default: {
+ }
+ }
+ }
+ }
+ if (!linear_damp_done) {
+ PhysicsServer2D::AreaSpaceOverrideMode area_linear_damp_mode = (PhysicsServer2D::AreaSpaceOverrideMode)(int)aa[i].area->get_param(PhysicsServer2D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE);
+ if (area_linear_damp_mode != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) {
+ real_t area_linear_damp = aa[i].area->get_linear_damp();
+ switch (area_linear_damp_mode) {
+ case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE:
+ case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: {
+ total_linear_damp += area_linear_damp;
+ linear_damp_done = area_linear_damp_mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE;
+ } break;
+ case PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE:
+ case PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: {
+ total_linear_damp = area_linear_damp;
+ linear_damp_done = area_linear_damp_mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE;
+ } break;
+ default: {
+ }
+ }
+ }
+ }
+ if (!angular_damp_done) {
+ PhysicsServer2D::AreaSpaceOverrideMode area_angular_damp_mode = (PhysicsServer2D::AreaSpaceOverrideMode)(int)aa[i].area->get_param(PhysicsServer2D::AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE);
+ if (area_angular_damp_mode != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) {
+ real_t area_angular_damp = aa[i].area->get_angular_damp();
+ switch (area_angular_damp_mode) {
+ case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE:
+ case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: {
+ total_angular_damp += area_angular_damp;
+ angular_damp_done = area_angular_damp_mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE;
+ } break;
+ case PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE:
+ case PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: {
+ total_angular_damp = area_angular_damp;
+ angular_damp_done = area_angular_damp_mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE;
+ } break;
+ default: {
+ }
+ }
}
}
+ stopped = gravity_done && linear_damp_done && angular_damp_done;
}
}
+
+ // Add default gravity and damping from space area.
if (!stopped) {
- _compute_area_gravity_and_damping(def_area);
+ GodotArea2D *default_area = get_space()->get_default_area();
+ ERR_FAIL_COND(!default_area);
+
+ if (!gravity_done) {
+ Vector2 default_gravity;
+ default_area->compute_gravity(get_transform().get_origin(), default_gravity);
+ gravity += default_gravity;
+ }
+
+ if (!linear_damp_done) {
+ total_linear_damp += default_area->get_linear_damp();
+ }
+
+ if (!angular_damp_done) {
+ total_angular_damp += default_area->get_angular_damp();
+ }
}
- gravity *= gravity_scale;
- // If less than 0, override dampenings with that of the Body2D
- if (angular_damp >= 0) {
- area_angular_damp = angular_damp;
+ // Override linear damping with body's value.
+ switch (linear_damp_mode) {
+ case PhysicsServer2D::BODY_DAMP_MODE_COMBINE: {
+ total_linear_damp += linear_damp;
+ } break;
+ case PhysicsServer2D::BODY_DAMP_MODE_REPLACE: {
+ total_linear_damp = linear_damp;
+ } break;
}
- /*
- else
- area_angular_damp=damp_area->get_angular_damp();
- */
- if (linear_damp >= 0) {
- area_linear_damp = linear_damp;
+ // Override angular damping with body's value.
+ switch (angular_damp_mode) {
+ case PhysicsServer2D::BODY_DAMP_MODE_COMBINE: {
+ total_angular_damp += angular_damp;
+ } break;
+ case PhysicsServer2D::BODY_DAMP_MODE_REPLACE: {
+ total_angular_damp = angular_damp;
+ } break;
}
- /*
- else
- area_linear_damp=damp_area->get_linear_damp();
- */
+
+ gravity *= gravity_scale;
+
+ prev_linear_velocity = linear_velocity;
+ prev_angular_velocity = angular_velocity;
Vector2 motion;
bool do_motion = false;
@@ -474,28 +565,20 @@ void Body2DSW::integrate_forces(real_t p_step) {
do_motion = true;
- /*
- for(int i=0;i<get_shape_count();i++) {
- set_shape_kinematic_advance(i,Vector2());
- set_shape_kinematic_retreat(i,0);
- }
- */
-
} else {
if (!omit_force_integration) {
//overridden by direct state query
- Vector2 force = gravity * mass;
- force += applied_force;
- real_t torque = applied_torque;
+ Vector2 force = gravity * mass + applied_force + constant_force;
+ real_t torque = applied_torque + constant_torque;
- real_t damp = 1.0 - p_step * area_linear_damp;
+ real_t damp = 1.0 - p_step * total_linear_damp;
if (damp < 0) { // reached zero in the given time
damp = 0;
}
- real_t angular_damp = 1.0 - p_step * area_angular_damp;
+ real_t angular_damp = 1.0 - p_step * total_angular_damp;
if (angular_damp < 0) { // reached zero in the given time
angular_damp = 0;
@@ -514,21 +597,20 @@ void Body2DSW::integrate_forces(real_t p_step) {
}
}
- //motion=linear_velocity*p_step;
+ applied_force = Vector2();
+ applied_torque = 0.0;
- biased_angular_velocity = 0;
+ biased_angular_velocity = 0.0;
biased_linear_velocity = Vector2();
if (do_motion) { //shapes temporarily extend for raycast
_update_shapes_with_motion(motion);
}
- // damp_area=nullptr; // clear the area, so it is set in the next frame
- def_area = nullptr; // clear the area, so it is set in the next frame
contact_count = 0;
}
-void Body2DSW::integrate_velocities(real_t p_step) {
+void GodotBody2D::integrate_velocities(real_t p_step) {
if (mode == PhysicsServer2D::BODY_MODE_STATIC) {
return;
}
@@ -549,17 +631,13 @@ void Body2DSW::integrate_velocities(real_t p_step) {
real_t total_angular_velocity = angular_velocity + biased_angular_velocity;
Vector2 total_linear_velocity = linear_velocity + biased_linear_velocity;
- real_t angle = get_transform().get_rotation() + total_angular_velocity * p_step;
+ real_t angle_delta = total_angular_velocity * p_step;
+ real_t angle = get_transform().get_rotation() + angle_delta;
Vector2 pos = get_transform().get_origin() + total_linear_velocity * p_step;
- real_t center_of_mass_distance = center_of_mass.length();
- if (center_of_mass_distance > CMP_EPSILON) {
+ if (center_of_mass.length_squared() > CMP_EPSILON2) {
// Calculate displacement due to center of mass offset.
- real_t prev_angle = get_transform().get_rotation();
- real_t angle_base = Math::atan2(center_of_mass.y, center_of_mass.x);
- Vector2 point1(Math::cos(angle_base + prev_angle), Math::sin(angle_base + prev_angle));
- Vector2 point2(Math::cos(angle_base + angle), Math::sin(angle_base + angle));
- pos += center_of_mass_distance * (point1 - point2);
+ pos += center_of_mass - center_of_mass.rotated(angle_delta);
}
_set_transform(Transform2D(angle, pos), continuous_cd_mode == PhysicsServer2D::CCD_MODE_DISABLED);
@@ -568,19 +646,21 @@ void Body2DSW::integrate_velocities(real_t p_step) {
if (continuous_cd_mode != PhysicsServer2D::CCD_MODE_DISABLED) {
new_transform = get_transform();
}
+
+ _update_transform_dependent();
}
-void Body2DSW::wakeup_neighbours() {
- for (const Pair<Constraint2DSW *, int> &E : constraint_list) {
- const Constraint2DSW *c = E.first;
- Body2DSW **n = c->get_body_ptr();
+void GodotBody2D::wakeup_neighbours() {
+ for (const Pair<GodotConstraint2D *, int> &E : constraint_list) {
+ const GodotConstraint2D *c = E.first;
+ GodotBody2D **n = c->get_body_ptr();
int bc = c->get_body_count();
for (int i = 0; i < bc; i++) {
if (i == E.second) {
continue;
}
- Body2DSW *b = n[i];
+ GodotBody2D *b = n[i];
if (b->mode < PhysicsServer2D::BODY_MODE_DYNAMIC) {
continue;
}
@@ -592,7 +672,7 @@ void Body2DSW::wakeup_neighbours() {
}
}
-void Body2DSW::call_queries() {
+void GodotBody2D::call_queries() {
if (fi_callback_data) {
if (!fi_callback_data->callable.get_object()) {
set_force_integration_callback(Callable());
@@ -616,7 +696,7 @@ void Body2DSW::call_queries() {
}
}
-bool Body2DSW::sleep_test(real_t p_step) {
+bool GodotBody2D::sleep_test(real_t p_step) {
if (mode == PhysicsServer2D::BODY_MODE_STATIC || mode == PhysicsServer2D::BODY_MODE_KINEMATIC) {
return true;
} else if (!can_sleep) {
@@ -633,12 +713,12 @@ bool Body2DSW::sleep_test(real_t p_step) {
}
}
-void Body2DSW::set_state_sync_callback(void *p_instance, PhysicsServer2D::BodyStateCallback p_callback) {
+void GodotBody2D::set_state_sync_callback(void *p_instance, PhysicsServer2D::BodyStateCallback p_callback) {
body_state_callback_instance = p_instance;
body_state_callback = p_callback;
}
-void Body2DSW::set_force_integration_callback(const Callable &p_callable, const Variant &p_udata) {
+void GodotBody2D::set_force_integration_callback(const Callable &p_callable, const Variant &p_udata) {
if (p_callable.get_object()) {
if (!fi_callback_data) {
fi_callback_data = memnew(ForceIntegrationCallbackData);
@@ -651,23 +731,23 @@ void Body2DSW::set_force_integration_callback(const Callable &p_callable, const
}
}
-PhysicsDirectBodyState2DSW *Body2DSW::get_direct_state() {
+GodotPhysicsDirectBodyState2D *GodotBody2D::get_direct_state() {
if (!direct_state) {
- direct_state = memnew(PhysicsDirectBodyState2DSW);
+ direct_state = memnew(GodotPhysicsDirectBodyState2D);
direct_state->body = this;
}
return direct_state;
}
-Body2DSW::Body2DSW() :
- CollisionObject2DSW(TYPE_BODY),
+GodotBody2D::GodotBody2D() :
+ GodotCollisionObject2D(TYPE_BODY),
active_list(this),
mass_properties_update_list(this),
direct_state_query_list(this) {
_set_static(false);
}
-Body2DSW::~Body2DSW() {
+GodotBody2D::~GodotBody2D() {
if (fi_callback_data) {
memdelete(fi_callback_data);
}
diff --git a/servers/physics_2d/body_2d_sw.h b/servers/physics_2d/godot_body_2d.h
index 822ff76fae..1335a19126 100644
--- a/servers/physics_2d/body_2d_sw.h
+++ b/servers/physics_2d/godot_body_2d.h
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* body_2d_sw.h */
+/* godot_body_2d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,19 +28,20 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef BODY_2D_SW_H
-#define BODY_2D_SW_H
+#ifndef GODOT_BODY_2D_H
+#define GODOT_BODY_2D_H
+
+#include "godot_area_2d.h"
+#include "godot_collision_object_2d.h"
-#include "area_2d_sw.h"
-#include "collision_object_2d_sw.h"
#include "core/templates/list.h"
#include "core/templates/pair.h"
#include "core/templates/vset.h"
-class Constraint2DSW;
-class PhysicsDirectBodyState2DSW;
+class GodotConstraint2D;
+class GodotPhysicsDirectBodyState2D;
-class Body2DSW : public CollisionObject2DSW {
+class GodotBody2D : public GodotCollisionObject2D {
PhysicsServer2D::BodyMode mode = PhysicsServer2D::BODY_MODE_DYNAMIC;
Vector2 biased_linear_velocity;
@@ -49,11 +50,21 @@ class Body2DSW : public CollisionObject2DSW {
Vector2 linear_velocity;
real_t angular_velocity = 0.0;
+ Vector2 prev_linear_velocity;
+ real_t prev_angular_velocity = 0.0;
+
Vector2 constant_linear_velocity;
real_t constant_angular_velocity = 0.0;
- real_t linear_damp = -1.0;
- real_t angular_damp = -1.0;
+ PhysicsServer2D::BodyDampMode linear_damp_mode = PhysicsServer2D::BODY_DAMP_MODE_COMBINE;
+ PhysicsServer2D::BodyDampMode angular_damp_mode = PhysicsServer2D::BODY_DAMP_MODE_COMBINE;
+
+ real_t linear_damp = 0.0;
+ real_t angular_damp = 0.0;
+
+ real_t total_linear_damp = 0.0;
+ real_t total_angular_damp = 0.0;
+
real_t gravity_scale = 1.0;
real_t bounce = 0.0;
@@ -65,23 +76,25 @@ class Body2DSW : public CollisionObject2DSW {
real_t inertia = 0.0;
real_t _inv_inertia = 0.0;
+ Vector2 center_of_mass_local;
Vector2 center_of_mass;
bool calculate_inertia = true;
bool calculate_center_of_mass = true;
Vector2 gravity;
- real_t area_linear_damp = 0.0;
- real_t area_angular_damp = 0.0;
real_t still_time = 0.0;
Vector2 applied_force;
real_t applied_torque = 0.0;
- SelfList<Body2DSW> active_list;
- SelfList<Body2DSW> mass_properties_update_list;
- SelfList<Body2DSW> direct_state_query_list;
+ Vector2 constant_force;
+ real_t constant_torque = 0.0;
+
+ SelfList<GodotBody2D> active_list;
+ SelfList<GodotBody2D> mass_properties_update_list;
+ SelfList<GodotBody2D> direct_state_query_list;
VSet<RID> exceptions;
PhysicsServer2D::CCDMode continuous_cd_mode = PhysicsServer2D::CCD_MODE_DISABLED;
@@ -93,15 +106,15 @@ class Body2DSW : public CollisionObject2DSW {
virtual void _shapes_changed();
Transform2D new_transform;
- List<Pair<Constraint2DSW *, int>> constraint_list;
+ List<Pair<GodotConstraint2D *, int>> constraint_list;
struct AreaCMP {
- Area2DSW *area = nullptr;
+ GodotArea2D *area = nullptr;
int refCount = 0;
_FORCE_INLINE_ bool operator==(const AreaCMP &p_cmp) const { return area->get_self() == p_cmp.area->get_self(); }
_FORCE_INLINE_ bool operator<(const AreaCMP &p_cmp) const { return area->get_priority() < p_cmp.area->get_priority(); }
_FORCE_INLINE_ AreaCMP() {}
- _FORCE_INLINE_ AreaCMP(Area2DSW *p_area) {
+ _FORCE_INLINE_ AreaCMP(GodotArea2D *p_area) {
area = p_area;
refCount = 1;
}
@@ -134,21 +147,21 @@ class Body2DSW : public CollisionObject2DSW {
ForceIntegrationCallbackData *fi_callback_data = nullptr;
- PhysicsDirectBodyState2DSW *direct_state = nullptr;
+ GodotPhysicsDirectBodyState2D *direct_state = nullptr;
uint64_t island_step = 0;
- _FORCE_INLINE_ void _compute_area_gravity_and_damping(const Area2DSW *p_area);
+ void _update_transform_dependent();
- friend class PhysicsDirectBodyState2DSW; // i give up, too many functions to expose
+ friend class GodotPhysicsDirectBodyState2D; // i give up, too many functions to expose
public:
void set_state_sync_callback(void *p_instance, PhysicsServer2D::BodyStateCallback p_callback);
void set_force_integration_callback(const Callable &p_callable, const Variant &p_udata = Variant());
- PhysicsDirectBodyState2DSW *get_direct_state();
+ GodotPhysicsDirectBodyState2D *get_direct_state();
- _FORCE_INLINE_ void add_area(Area2DSW *p_area) {
+ _FORCE_INLINE_ void add_area(GodotArea2D *p_area) {
int index = areas.find(AreaCMP(p_area));
if (index > -1) {
areas.write[index].refCount += 1;
@@ -157,12 +170,12 @@ public:
}
}
- _FORCE_INLINE_ void remove_area(Area2DSW *p_area) {
+ _FORCE_INLINE_ void remove_area(GodotArea2D *p_area) {
int index = areas.find(AreaCMP(p_area));
if (index > -1) {
areas.write[index].refCount -= 1;
if (areas[index].refCount < 1) {
- areas.remove(index);
+ areas.remove_at(index);
}
}
}
@@ -188,9 +201,9 @@ public:
_FORCE_INLINE_ uint64_t get_island_step() const { return island_step; }
_FORCE_INLINE_ void set_island_step(uint64_t p_step) { island_step = p_step; }
- _FORCE_INLINE_ void add_constraint(Constraint2DSW *p_constraint, int p_pos) { constraint_list.push_back({ p_constraint, p_pos }); }
- _FORCE_INLINE_ void remove_constraint(Constraint2DSW *p_constraint, int p_pos) { constraint_list.erase({ p_constraint, p_pos }); }
- const List<Pair<Constraint2DSW *, int>> &get_constraint_list() const { return constraint_list; }
+ _FORCE_INLINE_ void add_constraint(GodotConstraint2D *p_constraint, int p_pos) { constraint_list.push_back({ p_constraint, p_pos }); }
+ _FORCE_INLINE_ void remove_constraint(GodotConstraint2D *p_constraint, int p_pos) { constraint_list.erase({ p_constraint, p_pos }); }
+ const List<Pair<GodotConstraint2D *, int>> &get_constraint_list() const { return constraint_list; }
_FORCE_INLINE_ void clear_constraint_list() { constraint_list.clear(); }
_FORCE_INLINE_ void set_omit_force_integration(bool p_omit_force_integration) { omit_force_integration = p_omit_force_integration; }
@@ -202,6 +215,9 @@ public:
_FORCE_INLINE_ void set_angular_velocity(real_t p_velocity) { angular_velocity = p_velocity; }
_FORCE_INLINE_ real_t get_angular_velocity() const { return angular_velocity; }
+ _FORCE_INLINE_ Vector2 get_prev_linear_velocity() const { return prev_linear_velocity; }
+ _FORCE_INLINE_ real_t get_prev_angular_velocity() const { return prev_angular_velocity; }
+
_FORCE_INLINE_ void set_biased_linear_velocity(const Vector2 &p_velocity) { biased_linear_velocity = p_velocity; }
_FORCE_INLINE_ Vector2 get_biased_linear_velocity() const { return biased_linear_velocity; }
@@ -221,11 +237,49 @@ public:
angular_velocity += _inv_inertia * p_torque;
}
- _FORCE_INLINE_ void apply_bias_impulse(const Vector2 &p_impulse, const Vector2 &p_position = Vector2()) {
+ _FORCE_INLINE_ void apply_bias_impulse(const Vector2 &p_impulse, const Vector2 &p_position = Vector2(), real_t p_max_delta_av = -1.0) {
biased_linear_velocity += p_impulse * _inv_mass;
- biased_angular_velocity += _inv_inertia * (p_position - center_of_mass).cross(p_impulse);
+ if (p_max_delta_av != 0.0) {
+ real_t delta_av = _inv_inertia * (p_position - center_of_mass).cross(p_impulse);
+ if (p_max_delta_av > 0 && delta_av > p_max_delta_av) {
+ delta_av = p_max_delta_av;
+ }
+ biased_angular_velocity += delta_av;
+ }
+ }
+
+ _FORCE_INLINE_ void apply_central_force(const Vector2 &p_force) {
+ applied_force += p_force;
+ }
+
+ _FORCE_INLINE_ void apply_force(const Vector2 &p_force, const Vector2 &p_position = Vector2()) {
+ applied_force += p_force;
+ applied_torque += (p_position - center_of_mass).cross(p_force);
}
+ _FORCE_INLINE_ void apply_torque(real_t p_torque) {
+ applied_torque += p_torque;
+ }
+
+ _FORCE_INLINE_ void add_constant_central_force(const Vector2 &p_force) {
+ constant_force += p_force;
+ }
+
+ _FORCE_INLINE_ void add_constant_force(const Vector2 &p_force, const Vector2 &p_position = Vector2()) {
+ constant_force += p_force;
+ constant_torque += (p_position - center_of_mass).cross(p_force);
+ }
+
+ _FORCE_INLINE_ void add_constant_torque(real_t p_torque) {
+ constant_torque += p_torque;
+ }
+
+ void set_constant_force(const Vector2 &p_force) { constant_force = p_force; }
+ Vector2 get_constant_force() const { return constant_force; }
+
+ void set_constant_torque(real_t p_torque) { constant_torque = p_torque; }
+ real_t get_constant_torque() const { return constant_torque; }
+
void set_active(bool p_active);
_FORCE_INLINE_ bool is_active() const { return active; }
@@ -245,41 +299,20 @@ public:
void set_state(PhysicsServer2D::BodyState p_state, const Variant &p_variant);
Variant get_state(PhysicsServer2D::BodyState p_state) const;
- void set_applied_force(const Vector2 &p_force) { applied_force = p_force; }
- Vector2 get_applied_force() const { return applied_force; }
-
- void set_applied_torque(real_t p_torque) { applied_torque = p_torque; }
- real_t get_applied_torque() const { return applied_torque; }
-
- _FORCE_INLINE_ void add_central_force(const Vector2 &p_force) {
- applied_force += p_force;
- }
-
- _FORCE_INLINE_ void add_force(const Vector2 &p_force, const Vector2 &p_position = Vector2()) {
- applied_force += p_force;
- applied_torque += (p_position - center_of_mass).cross(p_force);
- }
-
- _FORCE_INLINE_ void add_torque(real_t p_torque) {
- applied_torque += p_torque;
- }
-
_FORCE_INLINE_ void set_continuous_collision_detection_mode(PhysicsServer2D::CCDMode p_mode) { continuous_cd_mode = p_mode; }
_FORCE_INLINE_ PhysicsServer2D::CCDMode get_continuous_collision_detection_mode() const { return continuous_cd_mode; }
- void set_space(Space2DSW *p_space);
+ void set_space(GodotSpace2D *p_space);
void update_mass_properties();
void reset_mass_properties();
- _FORCE_INLINE_ Vector2 get_center_of_mass() const { return center_of_mass; }
+ _FORCE_INLINE_ const Vector2 &get_center_of_mass() const { return center_of_mass; }
+ _FORCE_INLINE_ const Vector2 &get_center_of_mass_local() const { return center_of_mass_local; }
_FORCE_INLINE_ real_t get_inv_mass() const { return _inv_mass; }
_FORCE_INLINE_ real_t get_inv_inertia() const { return _inv_inertia; }
_FORCE_INLINE_ real_t get_friction() const { return friction; }
- _FORCE_INLINE_ Vector2 get_gravity() const { return gravity; }
_FORCE_INLINE_ real_t get_bounce() const { return bounce; }
- _FORCE_INLINE_ real_t get_linear_damp() const { return linear_damp; }
- _FORCE_INLINE_ real_t get_angular_damp() const { return angular_damp; }
void integrate_forces(real_t p_step);
void integrate_velocities(real_t p_step);
@@ -302,13 +335,13 @@ public:
bool sleep_test(real_t p_step);
- Body2DSW();
- ~Body2DSW();
+ GodotBody2D();
+ ~GodotBody2D();
};
//add contact inline
-void Body2DSW::add_contact(const Vector2 &p_local_pos, const Vector2 &p_local_normal, real_t p_depth, int p_local_shape, const Vector2 &p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID &p_collider, const Vector2 &p_collider_velocity_at_pos) {
+void GodotBody2D::add_contact(const Vector2 &p_local_pos, const Vector2 &p_local_normal, real_t p_depth, int p_local_shape, const Vector2 &p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID &p_collider, const Vector2 &p_collider_velocity_at_pos) {
int c_max = contacts.size();
if (c_max == 0) {
@@ -350,4 +383,4 @@ void Body2DSW::add_contact(const Vector2 &p_local_pos, const Vector2 &p_local_no
c[idx].collider_velocity_at_pos = p_collider_velocity_at_pos;
}
-#endif // BODY_2D_SW_H
+#endif // GODOT_BODY_2D_H
diff --git a/servers/physics_2d/godot_body_direct_state_2d.cpp b/servers/physics_2d/godot_body_direct_state_2d.cpp
new file mode 100644
index 0000000000..cde6e8c991
--- /dev/null
+++ b/servers/physics_2d/godot_body_direct_state_2d.cpp
@@ -0,0 +1,219 @@
+/*************************************************************************/
+/* godot_body_direct_state_2d.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 "godot_body_direct_state_2d.h"
+
+#include "godot_body_2d.h"
+#include "godot_physics_server_2d.h"
+#include "godot_space_2d.h"
+
+Vector2 GodotPhysicsDirectBodyState2D::get_total_gravity() const {
+ return body->gravity;
+}
+
+real_t GodotPhysicsDirectBodyState2D::get_total_angular_damp() const {
+ return body->total_angular_damp;
+}
+
+real_t GodotPhysicsDirectBodyState2D::get_total_linear_damp() const {
+ return body->total_linear_damp;
+}
+
+Vector2 GodotPhysicsDirectBodyState2D::get_center_of_mass() const {
+ return body->get_center_of_mass();
+}
+
+Vector2 GodotPhysicsDirectBodyState2D::get_center_of_mass_local() const {
+ return body->get_center_of_mass_local();
+}
+
+real_t GodotPhysicsDirectBodyState2D::get_inverse_mass() const {
+ return body->get_inv_mass();
+}
+
+real_t GodotPhysicsDirectBodyState2D::get_inverse_inertia() const {
+ return body->get_inv_inertia();
+}
+
+void GodotPhysicsDirectBodyState2D::set_linear_velocity(const Vector2 &p_velocity) {
+ body->wakeup();
+ body->set_linear_velocity(p_velocity);
+}
+
+Vector2 GodotPhysicsDirectBodyState2D::get_linear_velocity() const {
+ return body->get_linear_velocity();
+}
+
+void GodotPhysicsDirectBodyState2D::set_angular_velocity(real_t p_velocity) {
+ body->wakeup();
+ body->set_angular_velocity(p_velocity);
+}
+
+real_t GodotPhysicsDirectBodyState2D::get_angular_velocity() const {
+ return body->get_angular_velocity();
+}
+
+void GodotPhysicsDirectBodyState2D::set_transform(const Transform2D &p_transform) {
+ body->set_state(PhysicsServer2D::BODY_STATE_TRANSFORM, p_transform);
+}
+
+Transform2D GodotPhysicsDirectBodyState2D::get_transform() const {
+ return body->get_transform();
+}
+
+Vector2 GodotPhysicsDirectBodyState2D::get_velocity_at_local_position(const Vector2 &p_position) const {
+ return body->get_velocity_in_local_point(p_position);
+}
+
+void GodotPhysicsDirectBodyState2D::apply_central_impulse(const Vector2 &p_impulse) {
+ body->wakeup();
+ body->apply_central_impulse(p_impulse);
+}
+
+void GodotPhysicsDirectBodyState2D::apply_impulse(const Vector2 &p_impulse, const Vector2 &p_position) {
+ body->wakeup();
+ body->apply_impulse(p_impulse, p_position);
+}
+
+void GodotPhysicsDirectBodyState2D::apply_torque_impulse(real_t p_torque) {
+ body->wakeup();
+ body->apply_torque_impulse(p_torque);
+}
+
+void GodotPhysicsDirectBodyState2D::apply_central_force(const Vector2 &p_force) {
+ body->wakeup();
+ body->apply_central_force(p_force);
+}
+
+void GodotPhysicsDirectBodyState2D::apply_force(const Vector2 &p_force, const Vector2 &p_position) {
+ body->wakeup();
+ body->apply_force(p_force, p_position);
+}
+
+void GodotPhysicsDirectBodyState2D::apply_torque(real_t p_torque) {
+ body->wakeup();
+ body->apply_torque(p_torque);
+}
+
+void GodotPhysicsDirectBodyState2D::add_constant_central_force(const Vector2 &p_force) {
+ body->wakeup();
+ body->add_constant_central_force(p_force);
+}
+
+void GodotPhysicsDirectBodyState2D::add_constant_force(const Vector2 &p_force, const Vector2 &p_position) {
+ body->wakeup();
+ body->add_constant_force(p_force, p_position);
+}
+
+void GodotPhysicsDirectBodyState2D::add_constant_torque(real_t p_torque) {
+ body->wakeup();
+ body->add_constant_torque(p_torque);
+}
+
+void GodotPhysicsDirectBodyState2D::set_constant_force(const Vector2 &p_force) {
+ if (!p_force.is_equal_approx(Vector2())) {
+ body->wakeup();
+ }
+ body->set_constant_force(p_force);
+}
+
+Vector2 GodotPhysicsDirectBodyState2D::get_constant_force() const {
+ return body->get_constant_force();
+}
+
+void GodotPhysicsDirectBodyState2D::set_constant_torque(real_t p_torque) {
+ if (!Math::is_zero_approx(p_torque)) {
+ body->wakeup();
+ }
+ body->set_constant_torque(p_torque);
+}
+
+real_t GodotPhysicsDirectBodyState2D::get_constant_torque() const {
+ return body->get_constant_torque();
+}
+
+void GodotPhysicsDirectBodyState2D::set_sleep_state(bool p_enable) {
+ body->set_active(!p_enable);
+}
+
+bool GodotPhysicsDirectBodyState2D::is_sleeping() const {
+ return !body->is_active();
+}
+
+int GodotPhysicsDirectBodyState2D::get_contact_count() const {
+ return body->contact_count;
+}
+
+Vector2 GodotPhysicsDirectBodyState2D::get_contact_local_position(int p_contact_idx) const {
+ ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector2());
+ return body->contacts[p_contact_idx].local_pos;
+}
+
+Vector2 GodotPhysicsDirectBodyState2D::get_contact_local_normal(int p_contact_idx) const {
+ ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector2());
+ return body->contacts[p_contact_idx].local_normal;
+}
+
+int GodotPhysicsDirectBodyState2D::get_contact_local_shape(int p_contact_idx) const {
+ ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, -1);
+ return body->contacts[p_contact_idx].local_shape;
+}
+
+RID GodotPhysicsDirectBodyState2D::get_contact_collider(int p_contact_idx) const {
+ ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, RID());
+ return body->contacts[p_contact_idx].collider;
+}
+Vector2 GodotPhysicsDirectBodyState2D::get_contact_collider_position(int p_contact_idx) const {
+ ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector2());
+ return body->contacts[p_contact_idx].collider_pos;
+}
+
+ObjectID GodotPhysicsDirectBodyState2D::get_contact_collider_id(int p_contact_idx) const {
+ ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, ObjectID());
+ return body->contacts[p_contact_idx].collider_instance_id;
+}
+
+int GodotPhysicsDirectBodyState2D::get_contact_collider_shape(int p_contact_idx) const {
+ ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, 0);
+ return body->contacts[p_contact_idx].collider_shape;
+}
+
+Vector2 GodotPhysicsDirectBodyState2D::get_contact_collider_velocity_at_position(int p_contact_idx) const {
+ ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector2());
+ return body->contacts[p_contact_idx].collider_velocity_at_pos;
+}
+
+PhysicsDirectSpaceState2D *GodotPhysicsDirectBodyState2D::get_space_state() {
+ return body->get_space()->get_direct_state();
+}
+
+real_t GodotPhysicsDirectBodyState2D::get_step() const {
+ return body->get_space()->get_last_step();
+}
diff --git a/servers/physics_2d/body_direct_state_2d_sw.h b/servers/physics_2d/godot_body_direct_state_2d.h
index 4266b24842..a2c0a87989 100644
--- a/servers/physics_2d/body_direct_state_2d_sw.h
+++ b/servers/physics_2d/godot_body_direct_state_2d.h
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* body_direct_state_2d_sw.h */
+/* godot_body_direct_state_2d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,24 +28,25 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef BODY_DIRECT_STATE_2D_SW_H
-#define BODY_DIRECT_STATE_2D_SW_H
+#ifndef GODOT_BODY_DIRECT_STATE_2D_H
+#define GODOT_BODY_DIRECT_STATE_2D_H
#include "servers/physics_server_2d.h"
-class Body2DSW;
+class GodotBody2D;
-class PhysicsDirectBodyState2DSW : public PhysicsDirectBodyState2D {
- GDCLASS(PhysicsDirectBodyState2DSW, PhysicsDirectBodyState2D);
+class GodotPhysicsDirectBodyState2D : public PhysicsDirectBodyState2D {
+ GDCLASS(GodotPhysicsDirectBodyState2D, PhysicsDirectBodyState2D);
public:
- Body2DSW *body = nullptr;
+ GodotBody2D *body = nullptr;
virtual Vector2 get_total_gravity() const override;
virtual real_t get_total_angular_damp() const override;
virtual real_t get_total_linear_damp() const override;
virtual Vector2 get_center_of_mass() const override;
+ virtual Vector2 get_center_of_mass_local() const override;
virtual real_t get_inverse_mass() const override;
virtual real_t get_inverse_inertia() const override;
@@ -60,13 +61,24 @@ public:
virtual Vector2 get_velocity_at_local_position(const Vector2 &p_position) const override;
- virtual void add_central_force(const Vector2 &p_force) override;
- virtual void add_force(const Vector2 &p_force, const Vector2 &p_position = Vector2()) override;
- virtual void add_torque(real_t p_torque) override;
virtual void apply_central_impulse(const Vector2 &p_impulse) override;
virtual void apply_impulse(const Vector2 &p_impulse, const Vector2 &p_position = Vector2()) override;
virtual void apply_torque_impulse(real_t p_torque) override;
+ virtual void apply_central_force(const Vector2 &p_force) override;
+ virtual void apply_force(const Vector2 &p_force, const Vector2 &p_position = Vector2()) override;
+ virtual void apply_torque(real_t p_torque) override;
+
+ virtual void add_constant_central_force(const Vector2 &p_force) override;
+ virtual void add_constant_force(const Vector2 &p_force, const Vector2 &p_position = Vector2()) override;
+ virtual void add_constant_torque(real_t p_torque) override;
+
+ virtual void set_constant_force(const Vector2 &p_force) override;
+ virtual Vector2 get_constant_force() const override;
+
+ virtual void set_constant_torque(real_t p_torque) override;
+ virtual real_t get_constant_torque() const override;
+
virtual void set_sleep_state(bool p_enable) override;
virtual bool is_sleeping() const override;
@@ -88,4 +100,4 @@ public:
virtual real_t get_step() const override;
};
-#endif // BODY_2D_SW_H
+#endif // GODOT_BODY_DIRECT_STATE_2D_H
diff --git a/servers/physics_2d/body_pair_2d_sw.cpp b/servers/physics_2d/godot_body_pair_2d.cpp
index 8bcc4609f4..1986191cc3 100644
--- a/servers/physics_2d/body_pair_2d_sw.cpp
+++ b/servers/physics_2d/godot_body_pair_2d.cpp
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* body_pair_2d_sw.cpp */
+/* godot_body_pair_2d.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,22 +28,22 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "body_pair_2d_sw.h"
-#include "collision_solver_2d_sw.h"
-#include "space_2d_sw.h"
+#include "godot_body_pair_2d.h"
+#include "godot_collision_solver_2d.h"
+#include "godot_space_2d.h"
-#define POSITION_CORRECTION
#define ACCUMULATE_IMPULSES
-void BodyPair2DSW::_add_contact(const Vector2 &p_point_A, const Vector2 &p_point_B, void *p_self) {
- BodyPair2DSW *self = (BodyPair2DSW *)p_self;
+#define MIN_VELOCITY 0.001
+#define MAX_BIAS_ROTATION (Math_PI / 8)
+
+void GodotBodyPair2D::_add_contact(const Vector2 &p_point_A, const Vector2 &p_point_B, void *p_self) {
+ GodotBodyPair2D *self = (GodotBodyPair2D *)p_self;
self->_contact_added_callback(p_point_A, p_point_B);
}
-void BodyPair2DSW::_contact_added_callback(const Vector2 &p_point_A, const Vector2 &p_point_B) {
- // check if we already have the contact
-
+void GodotBodyPair2D::_contact_added_callback(const Vector2 &p_point_A, const Vector2 &p_point_B) {
Vector2 local_A = A->get_inv_transform().basis_xform(p_point_A);
Vector2 local_B = B->get_inv_transform().basis_xform(p_point_B - offset_B);
@@ -52,46 +52,48 @@ void BodyPair2DSW::_contact_added_callback(const Vector2 &p_point_A, const Vecto
ERR_FAIL_COND(new_index >= (MAX_CONTACTS + 1));
Contact contact;
-
- contact.acc_normal_impulse = 0;
- contact.acc_bias_impulse = 0;
- contact.acc_tangent_impulse = 0;
contact.local_A = local_A;
contact.local_B = local_B;
- contact.reused = true;
contact.normal = (p_point_A - p_point_B).normalized();
- contact.mass_normal = 0; // will be computed in setup()
-
- // attempt to determine if the contact will be reused
+ contact.used = true;
+ // Attempt to determine if the contact will be reused.
real_t recycle_radius_2 = space->get_contact_recycle_radius() * space->get_contact_recycle_radius();
for (int i = 0; i < contact_count; i++) {
Contact &c = contacts[i];
- if (
- c.local_A.distance_squared_to(local_A) < (recycle_radius_2) &&
+ if (c.local_A.distance_squared_to(local_A) < (recycle_radius_2) &&
c.local_B.distance_squared_to(local_B) < (recycle_radius_2)) {
contact.acc_normal_impulse = c.acc_normal_impulse;
contact.acc_tangent_impulse = c.acc_tangent_impulse;
contact.acc_bias_impulse = c.acc_bias_impulse;
- new_index = i;
- break;
+ contact.acc_bias_impulse_center_of_mass = c.acc_bias_impulse_center_of_mass;
+ c = contact;
+ return;
}
}
- // figure out if the contact amount must be reduced to fit the new contact
-
+ // Figure out if the contact amount must be reduced to fit the new contact.
if (new_index == MAX_CONTACTS) {
- // remove the contact with the minimum depth
-
- int least_deep = -1;
- real_t min_depth = 1e10;
+ // Remove the contact with the minimum depth.
const Transform2D &transform_A = A->get_transform();
const Transform2D &transform_B = B->get_transform();
- for (int i = 0; i <= contact_count; i++) {
- Contact &c = (i == contact_count) ? contact : contacts[i];
+ int least_deep = -1;
+ real_t min_depth;
+
+ // Start with depth for new contact.
+ {
+ Vector2 global_A = transform_A.basis_xform(contact.local_A);
+ Vector2 global_B = transform_B.basis_xform(contact.local_B) + offset_B;
+
+ Vector2 axis = global_A - global_B;
+ min_depth = axis.dot(contact.normal);
+ }
+
+ for (int i = 0; i < contact_count; i++) {
+ const Contact &c = contacts[i];
Vector2 global_A = transform_A.basis_xform(c.local_A);
Vector2 global_B = transform_B.basis_xform(c.local_B) + offset_B;
@@ -104,10 +106,8 @@ void BodyPair2DSW::_contact_added_callback(const Vector2 &p_point_A, const Vecto
}
}
- ERR_FAIL_COND(least_deep == -1);
-
- if (least_deep < contact_count) { //replace the last deep contact by the new one
-
+ if (least_deep > -1) {
+ // Replace the least deep contact by the new one.
contacts[least_deep] = contact;
}
@@ -115,15 +115,11 @@ void BodyPair2DSW::_contact_added_callback(const Vector2 &p_point_A, const Vecto
}
contacts[new_index] = contact;
-
- if (new_index == contact_count) {
- contact_count++;
- }
+ contact_count++;
}
-void BodyPair2DSW::_validate_contacts() {
- //make sure to erase contacts that are no longer valid
-
+void GodotBodyPair2D::_validate_contacts() {
+ // Make sure to erase contacts that are no longer valid.
real_t max_separation = space->get_contact_max_separation();
real_t max_separation2 = max_separation * max_separation;
@@ -134,11 +130,11 @@ void BodyPair2DSW::_validate_contacts() {
Contact &c = contacts[i];
bool erase = false;
- if (!c.reused) {
- //was left behind in previous frame
+ if (!c.used) {
+ // Was left behind in previous frame.
erase = true;
} else {
- c.reused = false;
+ c.used = false;
Vector2 global_A = transform_A.basis_xform(c.local_A);
Vector2 global_B = transform_B.basis_xform(c.local_B) + offset_B;
@@ -151,10 +147,10 @@ void BodyPair2DSW::_validate_contacts() {
}
if (erase) {
- // contact no longer needed, remove
+ // Contact no longer needed, remove.
if ((i + 1) < contact_count) {
- // swap with the last one
+ // Swap with the last one.
SWAP(contacts[i], contacts[contact_count - 1]);
}
@@ -164,7 +160,7 @@ void BodyPair2DSW::_validate_contacts() {
}
}
-bool BodyPair2DSW::_test_ccd(real_t p_step, Body2DSW *p_A, int p_shape_A, const Transform2D &p_xform_A, Body2DSW *p_B, int p_shape_B, const Transform2D &p_xform_B, bool p_swap_result) {
+bool GodotBodyPair2D::_test_ccd(real_t p_step, GodotBody2D *p_A, int p_shape_A, const Transform2D &p_xform_A, GodotBody2D *p_B, int p_shape_B, const Transform2D &p_xform_B) {
Vector2 motion = p_A->get_linear_velocity() * p_step;
real_t mlen = motion.length();
if (mlen < CMP_EPSILON) {
@@ -175,14 +171,18 @@ bool BodyPair2DSW::_test_ccd(real_t p_step, Body2DSW *p_A, int p_shape_A, const
real_t min, max;
p_A->get_shape(p_shape_A)->project_rangev(mnormal, p_xform_A, min, max);
- bool fast_object = mlen > (max - min) * 0.3; //going too fast in that direction
- if (!fast_object) { //did it move enough in this direction to even attempt raycast? let's say it should move more than 1/3 the size of the object in that axis
+ // Did it move enough in this direction to even attempt raycast?
+ // Let's say it should move more than 1/3 the size of the object in that axis.
+ bool fast_object = mlen > (max - min) * 0.3;
+ if (!fast_object) {
return false;
}
- //cast a segment from support in motion normal, in the same direction of motion by motion length
- //support is the worst case collision point, so real collision happened before
+ // Going too fast in that direction.
+
+ // Cast a segment from support in motion normal, in the same direction of motion by motion length.
+ // Support is the worst case collision point, so real collision happened before.
int a;
Vector2 s[2];
p_A->get_shape(p_shape_A)->get_supports(p_xform_A.basis_xform(mnormal).normalized(), s, a);
@@ -191,7 +191,8 @@ bool BodyPair2DSW::_test_ccd(real_t p_step, Body2DSW *p_A, int p_shape_A, const
Transform2D from_inv = p_xform_B.affine_inverse();
- Vector2 local_from = from_inv.xform(from - mnormal * mlen * 0.1); //start from a little inside the bounding box
+ // Start from a little inside the bounding box.
+ Vector2 local_from = from_inv.xform(from - mnormal * mlen * 0.1);
Vector2 local_to = from_inv.xform(to);
Vector2 rpos, rnorm;
@@ -199,33 +200,37 @@ bool BodyPair2DSW::_test_ccd(real_t p_step, Body2DSW *p_A, int p_shape_A, const
return false;
}
- //ray hit something
+ // Check one-way collision based on motion direction.
+ if (p_A->get_shape(p_shape_A)->allows_one_way_collision() && p_B->is_shape_set_as_one_way_collision(p_shape_B)) {
+ Vector2 direction = p_xform_B.get_axis(1).normalized();
+ if (direction.dot(mnormal) < CMP_EPSILON) {
+ collided = false;
+ oneway_disabled = true;
+ return false;
+ }
+ }
+ // Shorten the linear velocity so it does not hit, but gets close enough,
+ // next frame will hit softly or soft enough.
Vector2 hitpos = p_xform_B.xform(rpos);
- Vector2 contact_A = to;
- Vector2 contact_B = hitpos;
-
- //create a contact
-
- if (p_swap_result) {
- _contact_added_callback(contact_B, contact_A);
- } else {
- _contact_added_callback(contact_A, contact_B);
- }
+ real_t newlen = hitpos.distance_to(from) - (max - min) * 0.01;
+ p_A->set_linear_velocity(mnormal * (newlen / p_step));
return true;
}
-real_t combine_bounce(Body2DSW *A, Body2DSW *B) {
+real_t combine_bounce(GodotBody2D *A, GodotBody2D *B) {
return CLAMP(A->get_bounce() + B->get_bounce(), 0, 1);
}
-real_t combine_friction(Body2DSW *A, Body2DSW *B) {
+real_t combine_friction(GodotBody2D *A, GodotBody2D *B) {
return ABS(MIN(A->get_friction(), B->get_friction()));
}
-bool BodyPair2DSW::setup(real_t p_step) {
+bool GodotBodyPair2D::setup(real_t p_step) {
+ check_ccd = false;
+
if (!A->interacts_with(B) || A->has_exception(B->get_self()) || B->has_exception(A->get_self())) {
collided = false;
return false;
@@ -257,8 +262,8 @@ bool BodyPair2DSW::setup(real_t p_step) {
xform_Bu.elements[2] -= offset_A;
Transform2D xform_B = xform_Bu * B->get_shape_transform(shape_B);
- Shape2DSW *shape_A_ptr = A->get_shape(shape_A);
- Shape2DSW *shape_B_ptr = B->get_shape(shape_B);
+ GodotShape2D *shape_A_ptr = A->get_shape(shape_A);
+ GodotShape2D *shape_B_ptr = B->get_shape(shape_B);
Vector2 motion_A, motion_B;
@@ -271,26 +276,21 @@ bool BodyPair2DSW::setup(real_t p_step) {
bool prev_collided = collided;
- collided = CollisionSolver2DSW::solve(shape_A_ptr, xform_A, motion_A, shape_B_ptr, xform_B, motion_B, _add_contact, this, &sep_axis);
+ collided = GodotCollisionSolver2D::solve(shape_A_ptr, xform_A, motion_A, shape_B_ptr, xform_B, motion_B, _add_contact, this, &sep_axis);
if (!collided) {
- //test ccd (currently just a raycast)
+ oneway_disabled = false;
if (A->get_continuous_collision_detection_mode() == PhysicsServer2D::CCD_MODE_CAST_RAY && collide_A) {
- if (_test_ccd(p_step, A, shape_A, xform_A, B, shape_B, xform_B)) {
- collided = true;
- }
+ check_ccd = true;
+ return true;
}
if (B->get_continuous_collision_detection_mode() == PhysicsServer2D::CCD_MODE_CAST_RAY && collide_B) {
- if (_test_ccd(p_step, B, shape_B, xform_B, A, shape_A, xform_A, true)) {
- collided = true;
- }
+ check_ccd = true;
+ return true;
}
- if (!collided) {
- oneway_disabled = false;
- return false;
- }
+ return false;
}
if (oneway_disabled) {
@@ -303,9 +303,6 @@ bool BodyPair2DSW::setup(real_t p_step) {
bool valid = false;
for (int i = 0; i < contact_count; i++) {
Contact &c = contacts[i];
- if (!c.reused) {
- continue;
- }
if (c.normal.dot(direction) > -CMP_EPSILON) { //greater (normal inverted)
continue;
}
@@ -324,9 +321,6 @@ bool BodyPair2DSW::setup(real_t p_step) {
bool valid = false;
for (int i = 0; i < contact_count; i++) {
Contact &c = contacts[i];
- if (!c.reused) {
- continue;
- }
if (c.normal.dot(direction) < CMP_EPSILON) { //less (normal ok)
continue;
}
@@ -344,17 +338,39 @@ bool BodyPair2DSW::setup(real_t p_step) {
return true;
}
-bool BodyPair2DSW::pre_solve(real_t p_step) {
- if (!collided || oneway_disabled) {
+bool GodotBodyPair2D::pre_solve(real_t p_step) {
+ if (oneway_disabled) {
+ return false;
+ }
+
+ if (!collided) {
+ if (check_ccd) {
+ const Vector2 &offset_A = A->get_transform().get_origin();
+ Transform2D xform_Au = A->get_transform().untranslated();
+ Transform2D xform_A = xform_Au * A->get_shape_transform(shape_A);
+
+ Transform2D xform_Bu = B->get_transform();
+ xform_Bu.elements[2] -= offset_A;
+ Transform2D xform_B = xform_Bu * B->get_shape_transform(shape_B);
+
+ if (A->get_continuous_collision_detection_mode() == PhysicsServer2D::CCD_MODE_CAST_RAY && collide_A) {
+ _test_ccd(p_step, A, shape_A, xform_A, B, shape_B, xform_B);
+ }
+
+ if (B->get_continuous_collision_detection_mode() == PhysicsServer2D::CCD_MODE_CAST_RAY && collide_B) {
+ _test_ccd(p_step, B, shape_B, xform_B, A, shape_A, xform_A);
+ }
+ }
+
return false;
}
real_t max_penetration = space->get_contact_max_allowed_penetration();
- real_t bias = 0.3;
+ real_t bias = space->get_contact_bias();
- Shape2DSW *shape_A_ptr = A->get_shape(shape_A);
- Shape2DSW *shape_B_ptr = B->get_shape(shape_B);
+ GodotShape2D *shape_A_ptr = A->get_shape(shape_A);
+ GodotShape2D *shape_B_ptr = B->get_shape(shape_B);
if (shape_A_ptr->get_custom_bias() || shape_B_ptr->get_custom_bias()) {
if (shape_A_ptr->get_custom_bias() == 0) {
@@ -390,7 +406,7 @@ bool BodyPair2DSW::pre_solve(real_t p_step) {
Vector2 axis = global_A - global_B;
real_t depth = axis.dot(c.normal);
- if (depth <= 0.0 || !c.reused) {
+ if (depth <= 0.0) {
continue;
}
@@ -401,8 +417,8 @@ bool BodyPair2DSW::pre_solve(real_t p_step) {
}
#endif
- c.rA = global_A;
- c.rB = global_B - offset_B;
+ c.rA = global_A - A->get_center_of_mass();
+ c.rB = global_B - B->get_center_of_mass() - offset_B;
if (A->can_report_contacts()) {
Vector2 crB(-B->get_angular_velocity() * c.rB.y, B->get_angular_velocity() * c.rB.x);
@@ -435,7 +451,6 @@ bool BodyPair2DSW::pre_solve(real_t p_step) {
c.bias = -bias * inv_dt * MIN(0.0f, -depth + max_penetration);
c.depth = depth;
- //c.acc_bias_impulse=0;
#ifdef ACCUMULATE_IMPULSES
{
@@ -443,19 +458,19 @@ bool BodyPair2DSW::pre_solve(real_t p_step) {
Vector2 P = c.acc_normal_impulse * c.normal + c.acc_tangent_impulse * tangent;
if (collide_A) {
- A->apply_impulse(-P, c.rA);
+ A->apply_impulse(-P, c.rA + A->get_center_of_mass());
}
if (collide_B) {
- B->apply_impulse(P, c.rB);
+ B->apply_impulse(P, c.rB + B->get_center_of_mass());
}
}
#endif
c.bounce = combine_bounce(A, B);
if (c.bounce) {
- Vector2 crA(-A->get_angular_velocity() * c.rA.y, A->get_angular_velocity() * c.rA.x);
- Vector2 crB(-B->get_angular_velocity() * c.rB.y, B->get_angular_velocity() * c.rB.x);
- Vector2 dv = B->get_linear_velocity() + crB - A->get_linear_velocity() - crA;
+ Vector2 crA(-A->get_prev_angular_velocity() * c.rA.y, A->get_prev_angular_velocity() * c.rA.x);
+ Vector2 crB(-B->get_prev_angular_velocity() * c.rB.y, B->get_prev_angular_velocity() * c.rB.x);
+ Vector2 dv = B->get_prev_linear_velocity() + crB - A->get_prev_linear_velocity() - crA;
c.bounce = c.bounce * dv.dot(c.normal);
}
@@ -466,11 +481,16 @@ bool BodyPair2DSW::pre_solve(real_t p_step) {
return do_process;
}
-void BodyPair2DSW::solve(real_t p_step) {
+void GodotBodyPair2D::solve(real_t p_step) {
if (!collided || oneway_disabled) {
return;
}
+ const real_t max_bias_av = MAX_BIAS_ROTATION / p_step;
+
+ real_t inv_mass_A = collide_A ? A->get_inv_mass() : 0.0;
+ real_t inv_mass_B = collide_B ? B->get_inv_mass() : 0.0;
+
for (int i = 0; i < contact_count; ++i) {
Contact &c = contacts[i];
@@ -490,6 +510,7 @@ void BodyPair2DSW::solve(real_t p_step) {
real_t vn = dv.dot(c.normal);
real_t vbn = dbv.dot(c.normal);
+
Vector2 tangent = c.normal.orthogonal();
real_t vt = dv.dot(tangent);
@@ -500,10 +521,31 @@ void BodyPair2DSW::solve(real_t p_step) {
Vector2 jb = c.normal * (c.acc_bias_impulse - jbnOld);
if (collide_A) {
- A->apply_bias_impulse(-jb, c.rA);
+ A->apply_bias_impulse(-jb, c.rA + A->get_center_of_mass(), max_bias_av);
}
if (collide_B) {
- B->apply_bias_impulse(jb, c.rB);
+ B->apply_bias_impulse(jb, c.rB + B->get_center_of_mass(), max_bias_av);
+ }
+
+ crbA = Vector2(-A->get_biased_angular_velocity() * c.rA.y, A->get_biased_angular_velocity() * c.rA.x);
+ crbB = Vector2(-B->get_biased_angular_velocity() * c.rB.y, B->get_biased_angular_velocity() * c.rB.x);
+ dbv = B->get_biased_linear_velocity() + crbB - A->get_biased_linear_velocity() - crbA;
+
+ vbn = dbv.dot(c.normal);
+
+ if (Math::abs(-vbn + c.bias) > MIN_VELOCITY) {
+ real_t jbn_com = (-vbn + c.bias) / (inv_mass_A + inv_mass_B);
+ real_t jbnOld_com = c.acc_bias_impulse_center_of_mass;
+ c.acc_bias_impulse_center_of_mass = MAX(jbnOld_com + jbn_com, 0.0f);
+
+ Vector2 jb_com = c.normal * (c.acc_bias_impulse_center_of_mass - jbnOld_com);
+
+ if (collide_A) {
+ A->apply_bias_impulse(-jb_com, A->get_center_of_mass(), 0.0f);
+ }
+ if (collide_B) {
+ B->apply_bias_impulse(jb_com, B->get_center_of_mass(), 0.0f);
+ }
}
real_t jn = -(c.bounce + vn) * c.mass_normal;
@@ -520,16 +562,16 @@ void BodyPair2DSW::solve(real_t p_step) {
Vector2 j = c.normal * (c.acc_normal_impulse - jnOld) + tangent * (c.acc_tangent_impulse - jtOld);
if (collide_A) {
- A->apply_impulse(-j, c.rA);
+ A->apply_impulse(-j, c.rA + A->get_center_of_mass());
}
if (collide_B) {
- B->apply_impulse(j, c.rB);
+ B->apply_impulse(j, c.rB + B->get_center_of_mass());
}
}
}
-BodyPair2DSW::BodyPair2DSW(Body2DSW *p_A, int p_shape_A, Body2DSW *p_B, int p_shape_B) :
- Constraint2DSW(_arr, 2) {
+GodotBodyPair2D::GodotBodyPair2D(GodotBody2D *p_A, int p_shape_A, GodotBody2D *p_B, int p_shape_B) :
+ GodotConstraint2D(_arr, 2) {
A = p_A;
B = p_B;
shape_A = p_shape_A;
@@ -539,7 +581,7 @@ BodyPair2DSW::BodyPair2DSW(Body2DSW *p_A, int p_shape_A, Body2DSW *p_B, int p_sh
B->add_constraint(this, 1);
}
-BodyPair2DSW::~BodyPair2DSW() {
+GodotBodyPair2D::~GodotBodyPair2D() {
A->remove_constraint(this, 0);
B->remove_constraint(this, 1);
}
diff --git a/servers/physics_2d/body_pair_2d_sw.h b/servers/physics_2d/godot_body_pair_2d.h
index db4f3eba69..1c0f61be26 100644
--- a/servers/physics_2d/body_pair_2d_sw.h
+++ b/servers/physics_2d/godot_body_pair_2d.h
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* body_pair_2d_sw.h */
+/* godot_body_pair_2d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,23 +28,23 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef BODY_PAIR_2D_SW_H
-#define BODY_PAIR_2D_SW_H
+#ifndef GODOT_BODY_PAIR_2D_H
+#define GODOT_BODY_PAIR_2D_H
-#include "body_2d_sw.h"
-#include "constraint_2d_sw.h"
+#include "godot_body_2d.h"
+#include "godot_constraint_2d.h"
-class BodyPair2DSW : public Constraint2DSW {
+class GodotBodyPair2D : public GodotConstraint2D {
enum {
MAX_CONTACTS = 2
};
union {
struct {
- Body2DSW *A;
- Body2DSW *B;
+ GodotBody2D *A;
+ GodotBody2D *B;
};
- Body2DSW *_arr[2] = { nullptr, nullptr };
+ GodotBody2D *_arr[2] = { nullptr, nullptr };
};
int shape_A = 0;
@@ -53,7 +53,7 @@ class BodyPair2DSW : public Constraint2DSW {
bool collide_A = false;
bool collide_B = false;
- Space2DSW *space = nullptr;
+ GodotSpace2D *space = nullptr;
struct Contact {
Vector2 position;
@@ -62,13 +62,14 @@ class BodyPair2DSW : public Constraint2DSW {
real_t acc_normal_impulse = 0.0; // accumulated normal impulse (Pn)
real_t acc_tangent_impulse = 0.0; // accumulated tangent impulse (Pt)
real_t acc_bias_impulse = 0.0; // accumulated normal impulse for position bias (Pnb)
+ real_t acc_bias_impulse_center_of_mass = 0.0; // accumulated normal impulse for position bias applied to com
real_t mass_normal, mass_tangent = 0.0;
real_t bias = 0.0;
real_t depth = 0.0;
bool active = false;
+ bool used = false;
Vector2 rA, rB;
- bool reused = false;
real_t bounce = 0.0;
};
@@ -78,10 +79,11 @@ class BodyPair2DSW : public Constraint2DSW {
Contact contacts[MAX_CONTACTS];
int contact_count = 0;
bool collided = false;
+ bool check_ccd = false;
bool oneway_disabled = false;
bool report_contacts_only = false;
- bool _test_ccd(real_t p_step, Body2DSW *p_A, int p_shape_A, const Transform2D &p_xform_A, Body2DSW *p_B, int p_shape_B, const Transform2D &p_xform_B, bool p_swap_result = false);
+ bool _test_ccd(real_t p_step, GodotBody2D *p_A, int p_shape_A, const Transform2D &p_xform_A, GodotBody2D *p_B, int p_shape_B, const Transform2D &p_xform_B);
void _validate_contacts();
static void _add_contact(const Vector2 &p_point_A, const Vector2 &p_point_B, void *p_self);
_FORCE_INLINE_ void _contact_added_callback(const Vector2 &p_point_A, const Vector2 &p_point_B);
@@ -91,8 +93,8 @@ public:
virtual bool pre_solve(real_t p_step) override;
virtual void solve(real_t p_step) override;
- BodyPair2DSW(Body2DSW *p_A, int p_shape_A, Body2DSW *p_B, int p_shape_B);
- ~BodyPair2DSW();
+ GodotBodyPair2D(GodotBody2D *p_A, int p_shape_A, GodotBody2D *p_B, int p_shape_B);
+ ~GodotBodyPair2D();
};
-#endif // BODY_PAIR_2D_SW_H
+#endif // GODOT_BODY_PAIR_2D_H
diff --git a/servers/physics_2d/broad_phase_2d_sw.cpp b/servers/physics_2d/godot_broad_phase_2d.cpp
index 7f0af48b1f..e734c24f88 100644
--- a/servers/physics_2d/broad_phase_2d_sw.cpp
+++ b/servers/physics_2d/godot_broad_phase_2d.cpp
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* broad_phase_2d_sw.cpp */
+/* godot_broad_phase_2d.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,9 +28,9 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "broad_phase_2d_sw.h"
+#include "godot_broad_phase_2d.h"
-BroadPhase2DSW::CreateFunction BroadPhase2DSW::create_func = nullptr;
+GodotBroadPhase2D::CreateFunction GodotBroadPhase2D::create_func = nullptr;
-BroadPhase2DSW::~BroadPhase2DSW() {
+GodotBroadPhase2D::~GodotBroadPhase2D() {
}
diff --git a/servers/physics_2d/broad_phase_2d_sw.h b/servers/physics_2d/godot_broad_phase_2d.h
index 0f82f06b9c..abab087045 100644
--- a/servers/physics_2d/broad_phase_2d_sw.h
+++ b/servers/physics_2d/godot_broad_phase_2d.h
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* broad_phase_2d_sw.h */
+/* godot_broad_phase_2d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,44 +28,44 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef BROAD_PHASE_2D_SW_H
-#define BROAD_PHASE_2D_SW_H
+#ifndef GODOT_BROAD_PHASE_2D_H
+#define GODOT_BROAD_PHASE_2D_H
#include "core/math/math_funcs.h"
#include "core/math/rect2.h"
-class CollisionObject2DSW;
+class GodotCollisionObject2D;
-class BroadPhase2DSW {
+class GodotBroadPhase2D {
public:
- typedef BroadPhase2DSW *(*CreateFunction)();
+ typedef GodotBroadPhase2D *(*CreateFunction)();
static CreateFunction create_func;
typedef uint32_t ID;
- typedef void *(*PairCallback)(CollisionObject2DSW *A, int p_subindex_A, CollisionObject2DSW *B, int p_subindex_B, void *p_userdata);
- typedef void (*UnpairCallback)(CollisionObject2DSW *A, int p_subindex_A, CollisionObject2DSW *B, int p_subindex_B, void *p_data, void *p_userdata);
+ typedef void *(*PairCallback)(GodotCollisionObject2D *A, int p_subindex_A, GodotCollisionObject2D *B, int p_subindex_B, void *p_userdata);
+ typedef void (*UnpairCallback)(GodotCollisionObject2D *A, int p_subindex_A, GodotCollisionObject2D *B, int p_subindex_B, void *p_data, void *p_userdata);
// 0 is an invalid ID
- virtual ID create(CollisionObject2DSW *p_object_, int p_subindex = 0, const Rect2 &p_aabb = Rect2(), bool p_static = false) = 0;
+ virtual ID create(GodotCollisionObject2D *p_object_, int p_subindex = 0, const Rect2 &p_aabb = Rect2(), bool p_static = false) = 0;
virtual void move(ID p_id, const Rect2 &p_aabb) = 0;
virtual void set_static(ID p_id, bool p_static) = 0;
virtual void remove(ID p_id) = 0;
- virtual CollisionObject2DSW *get_object(ID p_id) const = 0;
+ virtual GodotCollisionObject2D *get_object(ID p_id) const = 0;
virtual bool is_static(ID p_id) const = 0;
virtual int get_subindex(ID p_id) const = 0;
- virtual int cull_segment(const Vector2 &p_from, const Vector2 &p_to, CollisionObject2DSW **p_results, int p_max_results, int *p_result_indices = nullptr) = 0;
- virtual int cull_aabb(const Rect2 &p_aabb, CollisionObject2DSW **p_results, int p_max_results, int *p_result_indices = nullptr) = 0;
+ virtual int cull_segment(const Vector2 &p_from, const Vector2 &p_to, GodotCollisionObject2D **p_results, int p_max_results, int *p_result_indices = nullptr) = 0;
+ virtual int cull_aabb(const Rect2 &p_aabb, GodotCollisionObject2D **p_results, int p_max_results, int *p_result_indices = nullptr) = 0;
virtual void set_pair_callback(PairCallback p_pair_callback, void *p_userdata) = 0;
virtual void set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata) = 0;
virtual void update() = 0;
- virtual ~BroadPhase2DSW();
+ virtual ~GodotBroadPhase2D();
};
-#endif // BROAD_PHASE_2D_SW_H
+#endif // GODOT_BROAD_PHASE_2D_H
diff --git a/servers/physics_2d/broad_phase_2d_bvh.cpp b/servers/physics_2d/godot_broad_phase_2d_bvh.cpp
index 0df7086c5a..5a96dae8ca 100644
--- a/servers/physics_2d/broad_phase_2d_bvh.cpp
+++ b/servers/physics_2d/godot_broad_phase_2d_bvh.cpp
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* broad_phase_2d_bvh.cpp */
+/* godot_broad_phase_2d_bvh.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,51 +28,51 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "broad_phase_2d_bvh.h"
-#include "collision_object_2d_sw.h"
+#include "godot_broad_phase_2d_bvh.h"
+#include "godot_collision_object_2d.h"
-BroadPhase2DSW::ID BroadPhase2DBVH::create(CollisionObject2DSW *p_object, int p_subindex, const Rect2 &p_aabb, bool p_static) {
+GodotBroadPhase2D::ID GodotBroadPhase2DBVH::create(GodotCollisionObject2D *p_object, int p_subindex, const Rect2 &p_aabb, bool p_static) {
ID oid = bvh.create(p_object, true, p_aabb, p_subindex, !p_static, 1 << p_object->get_type(), p_static ? 0 : 0xFFFFF); // Pair everything, don't care?
return oid + 1;
}
-void BroadPhase2DBVH::move(ID p_id, const Rect2 &p_aabb) {
+void GodotBroadPhase2DBVH::move(ID p_id, const Rect2 &p_aabb) {
bvh.move(p_id - 1, p_aabb);
}
-void BroadPhase2DBVH::set_static(ID p_id, bool p_static) {
- CollisionObject2DSW *it = bvh.get(p_id - 1);
+void GodotBroadPhase2DBVH::set_static(ID p_id, bool p_static) {
+ GodotCollisionObject2D *it = bvh.get(p_id - 1);
bvh.set_pairable(p_id - 1, !p_static, 1 << it->get_type(), p_static ? 0 : 0xFFFFF, false); // Pair everything, don't care?
}
-void BroadPhase2DBVH::remove(ID p_id) {
+void GodotBroadPhase2DBVH::remove(ID p_id) {
bvh.erase(p_id - 1);
}
-CollisionObject2DSW *BroadPhase2DBVH::get_object(ID p_id) const {
- CollisionObject2DSW *it = bvh.get(p_id - 1);
+GodotCollisionObject2D *GodotBroadPhase2DBVH::get_object(ID p_id) const {
+ GodotCollisionObject2D *it = bvh.get(p_id - 1);
ERR_FAIL_COND_V(!it, nullptr);
return it;
}
-bool BroadPhase2DBVH::is_static(ID p_id) const {
+bool GodotBroadPhase2DBVH::is_static(ID p_id) const {
return !bvh.is_pairable(p_id - 1);
}
-int BroadPhase2DBVH::get_subindex(ID p_id) const {
+int GodotBroadPhase2DBVH::get_subindex(ID p_id) const {
return bvh.get_subindex(p_id - 1);
}
-int BroadPhase2DBVH::cull_segment(const Vector2 &p_from, const Vector2 &p_to, CollisionObject2DSW **p_results, int p_max_results, int *p_result_indices) {
+int GodotBroadPhase2DBVH::cull_segment(const Vector2 &p_from, const Vector2 &p_to, GodotCollisionObject2D **p_results, int p_max_results, int *p_result_indices) {
return bvh.cull_segment(p_from, p_to, p_results, p_max_results, p_result_indices);
}
-int BroadPhase2DBVH::cull_aabb(const Rect2 &p_aabb, CollisionObject2DSW **p_results, int p_max_results, int *p_result_indices) {
+int GodotBroadPhase2DBVH::cull_aabb(const Rect2 &p_aabb, GodotCollisionObject2D **p_results, int p_max_results, int *p_result_indices) {
return bvh.cull_aabb(p_aabb, p_results, p_max_results, p_result_indices);
}
-void *BroadPhase2DBVH::_pair_callback(void *self, uint32_t p_A, CollisionObject2DSW *p_object_A, int subindex_A, uint32_t p_B, CollisionObject2DSW *p_object_B, int subindex_B) {
- BroadPhase2DBVH *bpo = (BroadPhase2DBVH *)(self);
+void *GodotBroadPhase2DBVH::_pair_callback(void *self, uint32_t p_A, GodotCollisionObject2D *p_object_A, int subindex_A, uint32_t p_B, GodotCollisionObject2D *p_object_B, int subindex_B) {
+ GodotBroadPhase2DBVH *bpo = (GodotBroadPhase2DBVH *)(self);
if (!bpo->pair_callback) {
return nullptr;
}
@@ -80,8 +80,8 @@ void *BroadPhase2DBVH::_pair_callback(void *self, uint32_t p_A, CollisionObject2
return bpo->pair_callback(p_object_A, subindex_A, p_object_B, subindex_B, bpo->pair_userdata);
}
-void BroadPhase2DBVH::_unpair_callback(void *self, uint32_t p_A, CollisionObject2DSW *p_object_A, int subindex_A, uint32_t p_B, CollisionObject2DSW *p_object_B, int subindex_B, void *pairdata) {
- BroadPhase2DBVH *bpo = (BroadPhase2DBVH *)(self);
+void GodotBroadPhase2DBVH::_unpair_callback(void *self, uint32_t p_A, GodotCollisionObject2D *p_object_A, int subindex_A, uint32_t p_B, GodotCollisionObject2D *p_object_B, int subindex_B, void *pairdata) {
+ GodotBroadPhase2DBVH *bpo = (GodotBroadPhase2DBVH *)(self);
if (!bpo->unpair_callback) {
return;
}
@@ -89,25 +89,25 @@ void BroadPhase2DBVH::_unpair_callback(void *self, uint32_t p_A, CollisionObject
bpo->unpair_callback(p_object_A, subindex_A, p_object_B, subindex_B, pairdata, bpo->unpair_userdata);
}
-void BroadPhase2DBVH::set_pair_callback(PairCallback p_pair_callback, void *p_userdata) {
+void GodotBroadPhase2DBVH::set_pair_callback(PairCallback p_pair_callback, void *p_userdata) {
pair_callback = p_pair_callback;
pair_userdata = p_userdata;
}
-void BroadPhase2DBVH::set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata) {
+void GodotBroadPhase2DBVH::set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata) {
unpair_callback = p_unpair_callback;
unpair_userdata = p_userdata;
}
-void BroadPhase2DBVH::update() {
+void GodotBroadPhase2DBVH::update() {
bvh.update();
}
-BroadPhase2DSW *BroadPhase2DBVH::_create() {
- return memnew(BroadPhase2DBVH);
+GodotBroadPhase2D *GodotBroadPhase2DBVH::_create() {
+ return memnew(GodotBroadPhase2DBVH);
}
-BroadPhase2DBVH::BroadPhase2DBVH() {
+GodotBroadPhase2DBVH::GodotBroadPhase2DBVH() {
bvh.set_pair_callback(_pair_callback, this);
bvh.set_unpair_callback(_unpair_callback, this);
}
diff --git a/servers/physics_2d/broad_phase_2d_bvh.h b/servers/physics_2d/godot_broad_phase_2d_bvh.h
index ea02a98417..d77e0574eb 100644
--- a/servers/physics_2d/broad_phase_2d_bvh.h
+++ b/servers/physics_2d/godot_broad_phase_2d_bvh.h
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* broad_phase_2d_bvh.h */
+/* godot_broad_phase_2d_bvh.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,19 +28,20 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef BROAD_PHASE_2D_BVH_H
-#define BROAD_PHASE_2D_BVH_H
+#ifndef GODOT_BROAD_PHASE_2D_BVH_H
+#define GODOT_BROAD_PHASE_2D_BVH_H
+
+#include "godot_broad_phase_2d.h"
-#include "broad_phase_2d_sw.h"
#include "core/math/bvh.h"
#include "core/math/rect2.h"
#include "core/math/vector2.h"
-class BroadPhase2DBVH : public BroadPhase2DSW {
- BVH_Manager<CollisionObject2DSW, true, 128, Rect2, Vector2> bvh;
+class GodotBroadPhase2DBVH : public GodotBroadPhase2D {
+ BVH_Manager<GodotCollisionObject2D, true, 128, Rect2, Vector2> bvh;
- static void *_pair_callback(void *, uint32_t, CollisionObject2DSW *, int, uint32_t, CollisionObject2DSW *, int);
- static void _unpair_callback(void *, uint32_t, CollisionObject2DSW *, int, uint32_t, CollisionObject2DSW *, int, void *);
+ static void *_pair_callback(void *, uint32_t, GodotCollisionObject2D *, int, uint32_t, GodotCollisionObject2D *, int);
+ static void _unpair_callback(void *, uint32_t, GodotCollisionObject2D *, int, uint32_t, GodotCollisionObject2D *, int, void *);
PairCallback pair_callback = nullptr;
void *pair_userdata = nullptr;
@@ -49,25 +50,25 @@ class BroadPhase2DBVH : public BroadPhase2DSW {
public:
// 0 is an invalid ID
- virtual ID create(CollisionObject2DSW *p_object, int p_subindex = 0, const Rect2 &p_aabb = Rect2(), bool p_static = false);
+ virtual ID create(GodotCollisionObject2D *p_object, int p_subindex = 0, const Rect2 &p_aabb = Rect2(), bool p_static = false);
virtual void move(ID p_id, const Rect2 &p_aabb);
virtual void set_static(ID p_id, bool p_static);
virtual void remove(ID p_id);
- virtual CollisionObject2DSW *get_object(ID p_id) const;
+ virtual GodotCollisionObject2D *get_object(ID p_id) const;
virtual bool is_static(ID p_id) const;
virtual int get_subindex(ID p_id) const;
- virtual int cull_segment(const Vector2 &p_from, const Vector2 &p_to, CollisionObject2DSW **p_results, int p_max_results, int *p_result_indices = nullptr);
- virtual int cull_aabb(const Rect2 &p_aabb, CollisionObject2DSW **p_results, int p_max_results, int *p_result_indices = nullptr);
+ virtual int cull_segment(const Vector2 &p_from, const Vector2 &p_to, GodotCollisionObject2D **p_results, int p_max_results, int *p_result_indices = nullptr);
+ virtual int cull_aabb(const Rect2 &p_aabb, GodotCollisionObject2D **p_results, int p_max_results, int *p_result_indices = nullptr);
virtual void set_pair_callback(PairCallback p_pair_callback, void *p_userdata);
virtual void set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata);
virtual void update();
- static BroadPhase2DSW *_create();
- BroadPhase2DBVH();
+ static GodotBroadPhase2D *_create();
+ GodotBroadPhase2DBVH();
};
-#endif // BROAD_PHASE_2D_BVH_H
+#endif // GODOT_BROAD_PHASE_2D_BVH_H
diff --git a/servers/physics_2d/collision_object_2d_sw.cpp b/servers/physics_2d/godot_collision_object_2d.cpp
index bc7d277152..35027e0f69 100644
--- a/servers/physics_2d/collision_object_2d_sw.cpp
+++ b/servers/physics_2d/godot_collision_object_2d.cpp
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* collision_object_2d_sw.cpp */
+/* godot_collision_object_2d.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,11 +28,11 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "collision_object_2d_sw.h"
-#include "servers/physics_2d/physics_server_2d_sw.h"
-#include "space_2d_sw.h"
+#include "godot_collision_object_2d.h"
+#include "godot_physics_server_2d.h"
+#include "godot_space_2d.h"
-void CollisionObject2DSW::add_shape(Shape2DSW *p_shape, const Transform2D &p_transform, bool p_disabled) {
+void GodotCollisionObject2D::add_shape(GodotShape2D *p_shape, const Transform2D &p_transform, bool p_disabled) {
Shape s;
s.shape = p_shape;
s.xform = p_transform;
@@ -45,11 +45,11 @@ void CollisionObject2DSW::add_shape(Shape2DSW *p_shape, const Transform2D &p_tra
p_shape->add_owner(this);
if (!pending_shape_update_list.in_list()) {
- PhysicsServer2DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list);
+ GodotPhysicsServer2D::godot_singleton->pending_shape_update_list.add(&pending_shape_update_list);
}
}
-void CollisionObject2DSW::set_shape(int p_index, Shape2DSW *p_shape) {
+void GodotCollisionObject2D::set_shape(int p_index, GodotShape2D *p_shape) {
ERR_FAIL_INDEX(p_index, shapes.size());
shapes[p_index].shape->remove_owner(this);
shapes.write[p_index].shape = p_shape;
@@ -57,25 +57,25 @@ void CollisionObject2DSW::set_shape(int p_index, Shape2DSW *p_shape) {
p_shape->add_owner(this);
if (!pending_shape_update_list.in_list()) {
- PhysicsServer2DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list);
+ GodotPhysicsServer2D::godot_singleton->pending_shape_update_list.add(&pending_shape_update_list);
}
}
-void CollisionObject2DSW::set_shape_transform(int p_index, const Transform2D &p_transform) {
+void GodotCollisionObject2D::set_shape_transform(int p_index, const Transform2D &p_transform) {
ERR_FAIL_INDEX(p_index, shapes.size());
shapes.write[p_index].xform = p_transform;
shapes.write[p_index].xform_inv = p_transform.affine_inverse();
if (!pending_shape_update_list.in_list()) {
- PhysicsServer2DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list);
+ GodotPhysicsServer2D::godot_singleton->pending_shape_update_list.add(&pending_shape_update_list);
}
}
-void CollisionObject2DSW::set_shape_disabled(int p_idx, bool p_disabled) {
+void GodotCollisionObject2D::set_shape_disabled(int p_idx, bool p_disabled) {
ERR_FAIL_INDEX(p_idx, shapes.size());
- CollisionObject2DSW::Shape &shape = shapes.write[p_idx];
+ GodotCollisionObject2D::Shape &shape = shapes.write[p_idx];
if (shape.disabled == p_disabled) {
return;
}
@@ -90,16 +90,16 @@ void CollisionObject2DSW::set_shape_disabled(int p_idx, bool p_disabled) {
space->get_broadphase()->remove(shape.bpid);
shape.bpid = 0;
if (!pending_shape_update_list.in_list()) {
- PhysicsServer2DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list);
+ GodotPhysicsServer2D::godot_singleton->pending_shape_update_list.add(&pending_shape_update_list);
}
} else if (!p_disabled && shape.bpid == 0) {
if (!pending_shape_update_list.in_list()) {
- PhysicsServer2DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list);
+ GodotPhysicsServer2D::godot_singleton->pending_shape_update_list.add(&pending_shape_update_list);
}
}
}
-void CollisionObject2DSW::remove_shape(Shape2DSW *p_shape) {
+void GodotCollisionObject2D::remove_shape(GodotShape2D *p_shape) {
//remove a shape, all the times it appears
for (int i = 0; i < shapes.size(); i++) {
if (shapes[i].shape == p_shape) {
@@ -109,7 +109,7 @@ void CollisionObject2DSW::remove_shape(Shape2DSW *p_shape) {
}
}
-void CollisionObject2DSW::remove_shape(int p_index) {
+void GodotCollisionObject2D::remove_shape(int p_index) {
//remove anything from shape to be erased to end, so subindices don't change
ERR_FAIL_INDEX(p_index, shapes.size());
for (int i = p_index; i < shapes.size(); i++) {
@@ -121,16 +121,16 @@ void CollisionObject2DSW::remove_shape(int p_index) {
shapes.write[i].bpid = 0;
}
shapes[p_index].shape->remove_owner(this);
- shapes.remove(p_index);
+ shapes.remove_at(p_index);
if (!pending_shape_update_list.in_list()) {
- PhysicsServer2DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list);
+ GodotPhysicsServer2D::godot_singleton->pending_shape_update_list.add(&pending_shape_update_list);
}
// _update_shapes();
// _shapes_changed();
}
-void CollisionObject2DSW::_set_static(bool p_static) {
+void GodotCollisionObject2D::_set_static(bool p_static) {
if (_static == p_static) {
return;
}
@@ -147,7 +147,7 @@ void CollisionObject2DSW::_set_static(bool p_static) {
}
}
-void CollisionObject2DSW::_unregister_shapes() {
+void GodotCollisionObject2D::_unregister_shapes() {
for (int i = 0; i < shapes.size(); i++) {
Shape &s = shapes.write[i];
if (s.bpid > 0) {
@@ -157,7 +157,7 @@ void CollisionObject2DSW::_unregister_shapes() {
}
}
-void CollisionObject2DSW::_update_shapes() {
+void GodotCollisionObject2D::_update_shapes() {
if (!space) {
return;
}
@@ -184,7 +184,7 @@ void CollisionObject2DSW::_update_shapes() {
}
}
-void CollisionObject2DSW::_update_shapes_with_motion(const Vector2 &p_motion) {
+void GodotCollisionObject2D::_update_shapes_with_motion(const Vector2 &p_motion) {
if (!space) {
return;
}
@@ -211,7 +211,7 @@ void CollisionObject2DSW::_update_shapes_with_motion(const Vector2 &p_motion) {
}
}
-void CollisionObject2DSW::_set_space(Space2DSW *p_space) {
+void GodotCollisionObject2D::_set_space(GodotSpace2D *p_space) {
if (space) {
space->remove_object(this);
@@ -232,12 +232,12 @@ void CollisionObject2DSW::_set_space(Space2DSW *p_space) {
}
}
-void CollisionObject2DSW::_shape_changed() {
+void GodotCollisionObject2D::_shape_changed() {
_update_shapes();
_shapes_changed();
}
-CollisionObject2DSW::CollisionObject2DSW(Type p_type) :
+GodotCollisionObject2D::GodotCollisionObject2D(Type p_type) :
pending_shape_update_list(this) {
type = p_type;
}
diff --git a/servers/physics_2d/collision_object_2d_sw.h b/servers/physics_2d/godot_collision_object_2d.h
index ca258a906a..1e9baad8d9 100644
--- a/servers/physics_2d/collision_object_2d_sw.h
+++ b/servers/physics_2d/godot_collision_object_2d.h
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* collision_object_2d_sw.h */
+/* godot_collision_object_2d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,17 +28,18 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef COLLISION_OBJECT_2D_SW_H
-#define COLLISION_OBJECT_2D_SW_H
+#ifndef GODOT_COLLISION_OBJECT_2D_H
+#define GODOT_COLLISION_OBJECT_2D_H
+
+#include "godot_broad_phase_2d.h"
+#include "godot_shape_2d.h"
-#include "broad_phase_2d_sw.h"
#include "core/templates/self_list.h"
#include "servers/physics_server_2d.h"
-#include "shape_2d_sw.h"
-class Space2DSW;
+class GodotSpace2D;
-class CollisionObject2DSW : public ShapeOwner2DSW {
+class GodotCollisionObject2D : public GodotShapeOwner2D {
public:
enum Type {
TYPE_AREA,
@@ -55,23 +56,23 @@ private:
struct Shape {
Transform2D xform;
Transform2D xform_inv;
- BroadPhase2DSW::ID bpid = 0;
+ GodotBroadPhase2D::ID bpid = 0;
Rect2 aabb_cache; //for rayqueries
- Shape2DSW *shape = nullptr;
+ GodotShape2D *shape = nullptr;
bool disabled = false;
bool one_way_collision = false;
real_t one_way_collision_margin = 0.0;
};
Vector<Shape> shapes;
- Space2DSW *space = nullptr;
+ GodotSpace2D *space = nullptr;
Transform2D transform;
Transform2D inv_transform;
uint32_t collision_mask = 1;
uint32_t collision_layer = 1;
bool _static = true;
- SelfList<CollisionObject2DSW> pending_shape_update_list;
+ SelfList<GodotCollisionObject2D> pending_shape_update_list;
void _update_shapes();
@@ -89,9 +90,9 @@ protected:
void _set_static(bool p_static);
virtual void _shapes_changed() = 0;
- void _set_space(Space2DSW *p_space);
+ void _set_space(GodotSpace2D *p_space);
- CollisionObject2DSW(Type p_type);
+ GodotCollisionObject2D(Type p_type);
public:
_FORCE_INLINE_ void set_self(const RID &p_self) { self = p_self; }
@@ -106,12 +107,12 @@ public:
void _shape_changed();
_FORCE_INLINE_ Type get_type() const { return type; }
- void add_shape(Shape2DSW *p_shape, const Transform2D &p_transform = Transform2D(), bool p_disabled = false);
- void set_shape(int p_index, Shape2DSW *p_shape);
+ void add_shape(GodotShape2D *p_shape, const Transform2D &p_transform = Transform2D(), bool p_disabled = false);
+ void set_shape(int p_index, GodotShape2D *p_shape);
void set_shape_transform(int p_index, const Transform2D &p_transform);
_FORCE_INLINE_ int get_shape_count() const { return shapes.size(); }
- _FORCE_INLINE_ Shape2DSW *get_shape(int p_index) const {
+ _FORCE_INLINE_ GodotShape2D *get_shape(int p_index) const {
CRASH_BAD_INDEX(p_index, shapes.size());
return shapes[p_index].shape;
}
@@ -130,7 +131,7 @@ public:
_FORCE_INLINE_ const Transform2D &get_transform() const { return transform; }
_FORCE_INLINE_ const Transform2D &get_inv_transform() const { return inv_transform; }
- _FORCE_INLINE_ Space2DSW *get_space() const { return space; }
+ _FORCE_INLINE_ GodotSpace2D *get_space() const { return space; }
void set_shape_disabled(int p_idx, bool p_disabled);
_FORCE_INLINE_ bool is_shape_disabled(int p_idx) const {
@@ -165,25 +166,25 @@ public:
}
_FORCE_INLINE_ uint32_t get_collision_layer() const { return collision_layer; }
- void remove_shape(Shape2DSW *p_shape);
+ void remove_shape(GodotShape2D *p_shape);
void remove_shape(int p_index);
- virtual void set_space(Space2DSW *p_space) = 0;
+ virtual void set_space(GodotSpace2D *p_space) = 0;
_FORCE_INLINE_ bool is_static() const { return _static; }
void set_pickable(bool p_pickable) { pickable = p_pickable; }
_FORCE_INLINE_ bool is_pickable() const { return pickable; }
- _FORCE_INLINE_ bool collides_with(CollisionObject2DSW *p_other) const {
+ _FORCE_INLINE_ bool collides_with(GodotCollisionObject2D *p_other) const {
return p_other->collision_layer & collision_mask;
}
- _FORCE_INLINE_ bool interacts_with(CollisionObject2DSW *p_other) const {
+ _FORCE_INLINE_ bool interacts_with(GodotCollisionObject2D *p_other) const {
return collision_layer & p_other->collision_mask || p_other->collision_layer & collision_mask;
}
- virtual ~CollisionObject2DSW() {}
+ virtual ~GodotCollisionObject2D() {}
};
-#endif // COLLISION_OBJECT_2D_SW_H
+#endif // GODOT_COLLISION_OBJECT_2D_H
diff --git a/servers/physics_2d/collision_solver_2d_sw.cpp b/servers/physics_2d/godot_collision_solver_2d.cpp
index 527bb1b0b2..263d6d939f 100644
--- a/servers/physics_2d/collision_solver_2d_sw.cpp
+++ b/servers/physics_2d/godot_collision_solver_2d.cpp
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* collision_solver_2d_sw.cpp */
+/* godot_collision_solver_2d.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,14 +28,14 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "collision_solver_2d_sw.h"
-#include "collision_solver_2d_sat.h"
+#include "godot_collision_solver_2d.h"
+#include "godot_collision_solver_2d_sat.h"
#define collision_solver sat_2d_calculate_penetration
//#define collision_solver gjk_epa_calculate_penetration
-bool CollisionSolver2DSW::solve_static_world_boundary(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result) {
- const WorldBoundaryShape2DSW *world_boundary = static_cast<const WorldBoundaryShape2DSW *>(p_shape_A);
+bool GodotCollisionSolver2D::solve_static_world_boundary(const GodotShape2D *p_shape_A, const Transform2D &p_transform_A, const GodotShape2D *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result) {
+ const GodotWorldBoundaryShape2D *world_boundary = static_cast<const GodotWorldBoundaryShape2D *>(p_shape_A);
if (p_shape_B->get_type() == PhysicsServer2D::SHAPE_WORLD_BOUNDARY) {
return false;
}
@@ -73,8 +73,8 @@ bool CollisionSolver2DSW::solve_static_world_boundary(const Shape2DSW *p_shape_A
return found;
}
-bool CollisionSolver2DSW::solve_separation_ray(const Shape2DSW *p_shape_A, const Vector2 &p_motion_A, const Transform2D &p_transform_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *r_sep_axis, real_t p_margin) {
- const SeparationRayShape2DSW *ray = static_cast<const SeparationRayShape2DSW *>(p_shape_A);
+bool GodotCollisionSolver2D::solve_separation_ray(const GodotShape2D *p_shape_A, const Vector2 &p_motion_A, const Transform2D &p_transform_A, const GodotShape2D *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *r_sep_axis, real_t p_margin) {
+ const GodotSeparationRayShape2D *ray = static_cast<const GodotSeparationRayShape2D *>(p_shape_A);
if (p_shape_B->get_type() == PhysicsServer2D::SHAPE_SEPARATION_RAY) {
return false;
}
@@ -134,13 +134,13 @@ bool CollisionSolver2DSW::solve_separation_ray(const Shape2DSW *p_shape_A, const
struct _ConcaveCollisionInfo2D {
const Transform2D *transform_A = nullptr;
- const Shape2DSW *shape_A = nullptr;
+ const GodotShape2D *shape_A = nullptr;
const Transform2D *transform_B = nullptr;
Vector2 motion_A;
Vector2 motion_B;
real_t margin_A = 0.0;
real_t margin_B = 0.0;
- CollisionSolver2DSW::CallbackResult result_callback;
+ GodotCollisionSolver2D::CallbackResult result_callback;
void *userdata = nullptr;
bool swap_result = false;
bool collided = false;
@@ -149,7 +149,7 @@ struct _ConcaveCollisionInfo2D {
Vector2 *sep_axis = nullptr;
};
-bool CollisionSolver2DSW::concave_callback(void *p_userdata, Shape2DSW *p_convex) {
+bool GodotCollisionSolver2D::concave_callback(void *p_userdata, GodotShape2D *p_convex) {
_ConcaveCollisionInfo2D &cinfo = *(_ConcaveCollisionInfo2D *)(p_userdata);
cinfo.aabb_tests++;
@@ -165,8 +165,8 @@ bool CollisionSolver2DSW::concave_callback(void *p_userdata, Shape2DSW *p_convex
return !cinfo.result_callback;
}
-bool CollisionSolver2DSW::solve_concave(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *r_sep_axis, real_t p_margin_A, real_t p_margin_B) {
- const ConcaveShape2DSW *concave_B = static_cast<const ConcaveShape2DSW *>(p_shape_B);
+bool GodotCollisionSolver2D::solve_concave(const GodotShape2D *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const GodotShape2D *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *r_sep_axis, real_t p_margin_A, real_t p_margin_B) {
+ const GodotConcaveShape2D *concave_B = static_cast<const GodotConcaveShape2D *>(p_shape_B);
_ConcaveCollisionInfo2D cinfo;
cinfo.transform_A = &p_transform_A;
@@ -209,7 +209,7 @@ bool CollisionSolver2DSW::solve_concave(const Shape2DSW *p_shape_A, const Transf
return cinfo.collided;
}
-bool CollisionSolver2DSW::solve(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CallbackResult p_result_callback, void *p_userdata, Vector2 *r_sep_axis, real_t p_margin_A, real_t p_margin_B) {
+bool GodotCollisionSolver2D::solve(const GodotShape2D *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const GodotShape2D *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CallbackResult p_result_callback, void *p_userdata, Vector2 *r_sep_axis, real_t p_margin_A, real_t p_margin_B) {
PhysicsServer2D::ShapeType type_A = p_shape_A->get_type();
PhysicsServer2D::ShapeType type_B = p_shape_B->get_type();
bool concave_A = p_shape_A->is_concave();
diff --git a/servers/physics_2d/collision_solver_2d_sw.h b/servers/physics_2d/godot_collision_solver_2d.h
index b87247b89a..bd90641f04 100644
--- a/servers/physics_2d/collision_solver_2d_sw.h
+++ b/servers/physics_2d/godot_collision_solver_2d.h
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* collision_solver_2d_sw.h */
+/* godot_collision_solver_2d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,23 +28,23 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef COLLISION_SOLVER_2D_SW_H
-#define COLLISION_SOLVER_2D_SW_H
+#ifndef GODOT_COLLISION_SOLVER_2D_H
+#define GODOT_COLLISION_SOLVER_2D_H
-#include "shape_2d_sw.h"
+#include "godot_shape_2d.h"
-class CollisionSolver2DSW {
+class GodotCollisionSolver2D {
public:
typedef void (*CallbackResult)(const Vector2 &p_point_A, const Vector2 &p_point_B, void *p_userdata);
private:
- static bool solve_static_world_boundary(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result);
- static bool concave_callback(void *p_userdata, Shape2DSW *p_convex);
- static bool solve_concave(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *r_sep_axis = nullptr, real_t p_margin_A = 0, real_t p_margin_B = 0);
- static bool solve_separation_ray(const Shape2DSW *p_shape_A, const Vector2 &p_motion_A, const Transform2D &p_transform_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *r_sep_axis = nullptr, real_t p_margin = 0);
+ static bool solve_static_world_boundary(const GodotShape2D *p_shape_A, const Transform2D &p_transform_A, const GodotShape2D *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result);
+ static bool concave_callback(void *p_userdata, GodotShape2D *p_convex);
+ static bool solve_concave(const GodotShape2D *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const GodotShape2D *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *r_sep_axis = nullptr, real_t p_margin_A = 0, real_t p_margin_B = 0);
+ static bool solve_separation_ray(const GodotShape2D *p_shape_A, const Vector2 &p_motion_A, const Transform2D &p_transform_A, const GodotShape2D *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *r_sep_axis = nullptr, real_t p_margin = 0);
public:
- static bool solve(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CallbackResult p_result_callback, void *p_userdata, Vector2 *r_sep_axis = nullptr, real_t p_margin_A = 0, real_t p_margin_B = 0);
+ static bool solve(const GodotShape2D *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const GodotShape2D *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CallbackResult p_result_callback, void *p_userdata, Vector2 *r_sep_axis = nullptr, real_t p_margin_A = 0, real_t p_margin_B = 0);
};
-#endif // COLLISION_SOLVER_2D_SW_H
+#endif // GODOT_COLLISION_SOLVER_2D_H
diff --git a/servers/physics_2d/collision_solver_2d_sat.cpp b/servers/physics_2d/godot_collision_solver_2d_sat.cpp
index 2e67cc6520..a965795bee 100644
--- a/servers/physics_2d/collision_solver_2d_sat.cpp
+++ b/servers/physics_2d/godot_collision_solver_2d_sat.cpp
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* collision_solver_2d_sat.cpp */
+/* godot_collision_solver_2d_sat.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,12 +28,12 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "collision_solver_2d_sat.h"
+#include "godot_collision_solver_2d_sat.h"
#include "core/math/geometry_2d.h"
struct _CollectorCallback2D {
- CollisionSolver2DSW::CallbackResult callback;
+ GodotCollisionSolver2D::CallbackResult callback;
void *userdata = nullptr;
bool swap = false;
bool collided = false;
@@ -384,14 +384,14 @@ public:
(castB && !separator.test_axis(((m_a) - ((m_b) + p_motion_b)).normalized())) || \
(castA && castB && !separator.test_axis(((m_a) + p_motion_a - ((m_b) + p_motion_b)).normalized())))
-typedef void (*CollisionFunc)(const Shape2DSW *, const Transform2D &, const Shape2DSW *, const Transform2D &, _CollectorCallback2D *p_collector, const Vector2 &, const Vector2 &, real_t, real_t);
+typedef void (*CollisionFunc)(const GodotShape2D *, const Transform2D &, const GodotShape2D *, const Transform2D &, _CollectorCallback2D *p_collector, const Vector2 &, const Vector2 &, real_t, real_t);
template <bool castA, bool castB, bool withMargin>
-static void _collision_segment_segment(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
- const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW *>(p_a);
- const SegmentShape2DSW *segment_B = static_cast<const SegmentShape2DSW *>(p_b);
+static void _collision_segment_segment(const GodotShape2D *p_a, const Transform2D &p_transform_a, const GodotShape2D *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
+ const GodotSegmentShape2D *segment_A = static_cast<const GodotSegmentShape2D *>(p_a);
+ const GodotSegmentShape2D *segment_B = static_cast<const GodotSegmentShape2D *>(p_b);
- SeparatorAxisTest2D<SegmentShape2DSW, SegmentShape2DSW, castA, castB, withMargin> separator(segment_A, p_transform_a, segment_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
+ SeparatorAxisTest2D<GodotSegmentShape2D, GodotSegmentShape2D, castA, castB, withMargin> separator(segment_A, p_transform_a, segment_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
if (!separator.test_previous_axis()) {
return;
@@ -430,11 +430,11 @@ static void _collision_segment_segment(const Shape2DSW *p_a, const Transform2D &
}
template <bool castA, bool castB, bool withMargin>
-static void _collision_segment_circle(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
- const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW *>(p_a);
- const CircleShape2DSW *circle_B = static_cast<const CircleShape2DSW *>(p_b);
+static void _collision_segment_circle(const GodotShape2D *p_a, const Transform2D &p_transform_a, const GodotShape2D *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
+ const GodotSegmentShape2D *segment_A = static_cast<const GodotSegmentShape2D *>(p_a);
+ const GodotCircleShape2D *circle_B = static_cast<const GodotCircleShape2D *>(p_b);
- SeparatorAxisTest2D<SegmentShape2DSW, CircleShape2DSW, castA, castB, withMargin> separator(segment_A, p_transform_a, circle_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
+ SeparatorAxisTest2D<GodotSegmentShape2D, GodotCircleShape2D, castA, castB, withMargin> separator(segment_A, p_transform_a, circle_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
if (!separator.test_previous_axis()) {
return;
@@ -463,11 +463,11 @@ static void _collision_segment_circle(const Shape2DSW *p_a, const Transform2D &p
}
template <bool castA, bool castB, bool withMargin>
-static void _collision_segment_rectangle(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
- const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW *>(p_a);
- const RectangleShape2DSW *rectangle_B = static_cast<const RectangleShape2DSW *>(p_b);
+static void _collision_segment_rectangle(const GodotShape2D *p_a, const Transform2D &p_transform_a, const GodotShape2D *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
+ const GodotSegmentShape2D *segment_A = static_cast<const GodotSegmentShape2D *>(p_a);
+ const GodotRectangleShape2D *rectangle_B = static_cast<const GodotRectangleShape2D *>(p_b);
- SeparatorAxisTest2D<SegmentShape2DSW, RectangleShape2DSW, castA, castB, withMargin> separator(segment_A, p_transform_a, rectangle_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
+ SeparatorAxisTest2D<GodotSegmentShape2D, GodotRectangleShape2D, castA, castB, withMargin> separator(segment_A, p_transform_a, rectangle_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
if (!separator.test_previous_axis()) {
return;
@@ -534,11 +534,11 @@ static void _collision_segment_rectangle(const Shape2DSW *p_a, const Transform2D
}
template <bool castA, bool castB, bool withMargin>
-static void _collision_segment_capsule(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
- const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW *>(p_a);
- const CapsuleShape2DSW *capsule_B = static_cast<const CapsuleShape2DSW *>(p_b);
+static void _collision_segment_capsule(const GodotShape2D *p_a, const Transform2D &p_transform_a, const GodotShape2D *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
+ const GodotSegmentShape2D *segment_A = static_cast<const GodotSegmentShape2D *>(p_a);
+ const GodotCapsuleShape2D *capsule_B = static_cast<const GodotCapsuleShape2D *>(p_b);
- SeparatorAxisTest2D<SegmentShape2DSW, CapsuleShape2DSW, castA, castB, withMargin> separator(segment_A, p_transform_a, capsule_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
+ SeparatorAxisTest2D<GodotSegmentShape2D, GodotCapsuleShape2D, castA, castB, withMargin> separator(segment_A, p_transform_a, capsule_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
if (!separator.test_previous_axis()) {
return;
@@ -575,11 +575,11 @@ static void _collision_segment_capsule(const Shape2DSW *p_a, const Transform2D &
}
template <bool castA, bool castB, bool withMargin>
-static void _collision_segment_convex_polygon(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
- const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW *>(p_a);
- const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW *>(p_b);
+static void _collision_segment_convex_polygon(const GodotShape2D *p_a, const Transform2D &p_transform_a, const GodotShape2D *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
+ const GodotSegmentShape2D *segment_A = static_cast<const GodotSegmentShape2D *>(p_a);
+ const GodotConvexPolygonShape2D *convex_B = static_cast<const GodotConvexPolygonShape2D *>(p_b);
- SeparatorAxisTest2D<SegmentShape2DSW, ConvexPolygonShape2DSW, castA, castB, withMargin> separator(segment_A, p_transform_a, convex_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
+ SeparatorAxisTest2D<GodotSegmentShape2D, GodotConvexPolygonShape2D, castA, castB, withMargin> separator(segment_A, p_transform_a, convex_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
if (!separator.test_previous_axis()) {
return;
@@ -614,11 +614,11 @@ static void _collision_segment_convex_polygon(const Shape2DSW *p_a, const Transf
/////////
template <bool castA, bool castB, bool withMargin>
-static void _collision_circle_circle(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
- const CircleShape2DSW *circle_A = static_cast<const CircleShape2DSW *>(p_a);
- const CircleShape2DSW *circle_B = static_cast<const CircleShape2DSW *>(p_b);
+static void _collision_circle_circle(const GodotShape2D *p_a, const Transform2D &p_transform_a, const GodotShape2D *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
+ const GodotCircleShape2D *circle_A = static_cast<const GodotCircleShape2D *>(p_a);
+ const GodotCircleShape2D *circle_B = static_cast<const GodotCircleShape2D *>(p_b);
- SeparatorAxisTest2D<CircleShape2DSW, CircleShape2DSW, castA, castB, withMargin> separator(circle_A, p_transform_a, circle_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
+ SeparatorAxisTest2D<GodotCircleShape2D, GodotCircleShape2D, castA, castB, withMargin> separator(circle_A, p_transform_a, circle_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
if (!separator.test_previous_axis()) {
return;
@@ -636,11 +636,11 @@ static void _collision_circle_circle(const Shape2DSW *p_a, const Transform2D &p_
}
template <bool castA, bool castB, bool withMargin>
-static void _collision_circle_rectangle(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
- const CircleShape2DSW *circle_A = static_cast<const CircleShape2DSW *>(p_a);
- const RectangleShape2DSW *rectangle_B = static_cast<const RectangleShape2DSW *>(p_b);
+static void _collision_circle_rectangle(const GodotShape2D *p_a, const Transform2D &p_transform_a, const GodotShape2D *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
+ const GodotCircleShape2D *circle_A = static_cast<const GodotCircleShape2D *>(p_a);
+ const GodotRectangleShape2D *rectangle_B = static_cast<const GodotRectangleShape2D *>(p_b);
- SeparatorAxisTest2D<CircleShape2DSW, RectangleShape2DSW, castA, castB, withMargin> separator(circle_A, p_transform_a, rectangle_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
+ SeparatorAxisTest2D<GodotCircleShape2D, GodotRectangleShape2D, castA, castB, withMargin> separator(circle_A, p_transform_a, rectangle_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
if (!separator.test_previous_axis()) {
return;
@@ -694,11 +694,11 @@ static void _collision_circle_rectangle(const Shape2DSW *p_a, const Transform2D
}
template <bool castA, bool castB, bool withMargin>
-static void _collision_circle_capsule(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
- const CircleShape2DSW *circle_A = static_cast<const CircleShape2DSW *>(p_a);
- const CapsuleShape2DSW *capsule_B = static_cast<const CapsuleShape2DSW *>(p_b);
+static void _collision_circle_capsule(const GodotShape2D *p_a, const Transform2D &p_transform_a, const GodotShape2D *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
+ const GodotCircleShape2D *circle_A = static_cast<const GodotCircleShape2D *>(p_a);
+ const GodotCapsuleShape2D *capsule_B = static_cast<const GodotCapsuleShape2D *>(p_b);
- SeparatorAxisTest2D<CircleShape2DSW, CapsuleShape2DSW, castA, castB, withMargin> separator(circle_A, p_transform_a, capsule_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
+ SeparatorAxisTest2D<GodotCircleShape2D, GodotCapsuleShape2D, castA, castB, withMargin> separator(circle_A, p_transform_a, capsule_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
if (!separator.test_previous_axis()) {
return;
@@ -727,11 +727,11 @@ static void _collision_circle_capsule(const Shape2DSW *p_a, const Transform2D &p
}
template <bool castA, bool castB, bool withMargin>
-static void _collision_circle_convex_polygon(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
- const CircleShape2DSW *circle_A = static_cast<const CircleShape2DSW *>(p_a);
- const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW *>(p_b);
+static void _collision_circle_convex_polygon(const GodotShape2D *p_a, const Transform2D &p_transform_a, const GodotShape2D *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
+ const GodotCircleShape2D *circle_A = static_cast<const GodotCircleShape2D *>(p_a);
+ const GodotConvexPolygonShape2D *convex_B = static_cast<const GodotConvexPolygonShape2D *>(p_b);
- SeparatorAxisTest2D<CircleShape2DSW, ConvexPolygonShape2DSW, castA, castB, withMargin> separator(circle_A, p_transform_a, convex_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
+ SeparatorAxisTest2D<GodotCircleShape2D, GodotConvexPolygonShape2D, castA, castB, withMargin> separator(circle_A, p_transform_a, convex_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
if (!separator.test_previous_axis()) {
return;
@@ -758,11 +758,11 @@ static void _collision_circle_convex_polygon(const Shape2DSW *p_a, const Transfo
/////////
template <bool castA, bool castB, bool withMargin>
-static void _collision_rectangle_rectangle(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
- const RectangleShape2DSW *rectangle_A = static_cast<const RectangleShape2DSW *>(p_a);
- const RectangleShape2DSW *rectangle_B = static_cast<const RectangleShape2DSW *>(p_b);
+static void _collision_rectangle_rectangle(const GodotShape2D *p_a, const Transform2D &p_transform_a, const GodotShape2D *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
+ const GodotRectangleShape2D *rectangle_A = static_cast<const GodotRectangleShape2D *>(p_a);
+ const GodotRectangleShape2D *rectangle_B = static_cast<const GodotRectangleShape2D *>(p_b);
- SeparatorAxisTest2D<RectangleShape2DSW, RectangleShape2DSW, castA, castB, withMargin> separator(rectangle_A, p_transform_a, rectangle_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
+ SeparatorAxisTest2D<GodotRectangleShape2D, GodotRectangleShape2D, castA, castB, withMargin> separator(rectangle_A, p_transform_a, rectangle_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
if (!separator.test_previous_axis()) {
return;
@@ -832,11 +832,11 @@ static void _collision_rectangle_rectangle(const Shape2DSW *p_a, const Transform
}
template <bool castA, bool castB, bool withMargin>
-static void _collision_rectangle_capsule(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
- const RectangleShape2DSW *rectangle_A = static_cast<const RectangleShape2DSW *>(p_a);
- const CapsuleShape2DSW *capsule_B = static_cast<const CapsuleShape2DSW *>(p_b);
+static void _collision_rectangle_capsule(const GodotShape2D *p_a, const Transform2D &p_transform_a, const GodotShape2D *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
+ const GodotRectangleShape2D *rectangle_A = static_cast<const GodotRectangleShape2D *>(p_a);
+ const GodotCapsuleShape2D *capsule_B = static_cast<const GodotCapsuleShape2D *>(p_b);
- SeparatorAxisTest2D<RectangleShape2DSW, CapsuleShape2DSW, castA, castB, withMargin> separator(rectangle_A, p_transform_a, capsule_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
+ SeparatorAxisTest2D<GodotRectangleShape2D, GodotCapsuleShape2D, castA, castB, withMargin> separator(rectangle_A, p_transform_a, capsule_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
if (!separator.test_previous_axis()) {
return;
@@ -910,11 +910,11 @@ static void _collision_rectangle_capsule(const Shape2DSW *p_a, const Transform2D
}
template <bool castA, bool castB, bool withMargin>
-static void _collision_rectangle_convex_polygon(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
- const RectangleShape2DSW *rectangle_A = static_cast<const RectangleShape2DSW *>(p_a);
- const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW *>(p_b);
+static void _collision_rectangle_convex_polygon(const GodotShape2D *p_a, const Transform2D &p_transform_a, const GodotShape2D *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
+ const GodotRectangleShape2D *rectangle_A = static_cast<const GodotRectangleShape2D *>(p_a);
+ const GodotConvexPolygonShape2D *convex_B = static_cast<const GodotConvexPolygonShape2D *>(p_b);
- SeparatorAxisTest2D<RectangleShape2DSW, ConvexPolygonShape2DSW, castA, castB, withMargin> separator(rectangle_A, p_transform_a, convex_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
+ SeparatorAxisTest2D<GodotRectangleShape2D, GodotConvexPolygonShape2D, castA, castB, withMargin> separator(rectangle_A, p_transform_a, convex_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
if (!separator.test_previous_axis()) {
return;
@@ -972,11 +972,11 @@ static void _collision_rectangle_convex_polygon(const Shape2DSW *p_a, const Tran
/////////
template <bool castA, bool castB, bool withMargin>
-static void _collision_capsule_capsule(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
- const CapsuleShape2DSW *capsule_A = static_cast<const CapsuleShape2DSW *>(p_a);
- const CapsuleShape2DSW *capsule_B = static_cast<const CapsuleShape2DSW *>(p_b);
+static void _collision_capsule_capsule(const GodotShape2D *p_a, const Transform2D &p_transform_a, const GodotShape2D *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
+ const GodotCapsuleShape2D *capsule_A = static_cast<const GodotCapsuleShape2D *>(p_a);
+ const GodotCapsuleShape2D *capsule_B = static_cast<const GodotCapsuleShape2D *>(p_b);
- SeparatorAxisTest2D<CapsuleShape2DSW, CapsuleShape2DSW, castA, castB, withMargin> separator(capsule_A, p_transform_a, capsule_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
+ SeparatorAxisTest2D<GodotCapsuleShape2D, GodotCapsuleShape2D, castA, castB, withMargin> separator(capsule_A, p_transform_a, capsule_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
if (!separator.test_previous_axis()) {
return;
@@ -1020,11 +1020,11 @@ static void _collision_capsule_capsule(const Shape2DSW *p_a, const Transform2D &
}
template <bool castA, bool castB, bool withMargin>
-static void _collision_capsule_convex_polygon(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
- const CapsuleShape2DSW *capsule_A = static_cast<const CapsuleShape2DSW *>(p_a);
- const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW *>(p_b);
+static void _collision_capsule_convex_polygon(const GodotShape2D *p_a, const Transform2D &p_transform_a, const GodotShape2D *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
+ const GodotCapsuleShape2D *capsule_A = static_cast<const GodotCapsuleShape2D *>(p_a);
+ const GodotConvexPolygonShape2D *convex_B = static_cast<const GodotConvexPolygonShape2D *>(p_b);
- SeparatorAxisTest2D<CapsuleShape2DSW, ConvexPolygonShape2DSW, castA, castB, withMargin> separator(capsule_A, p_transform_a, convex_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
+ SeparatorAxisTest2D<GodotCapsuleShape2D, GodotConvexPolygonShape2D, castA, castB, withMargin> separator(capsule_A, p_transform_a, convex_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
if (!separator.test_previous_axis()) {
return;
@@ -1066,11 +1066,11 @@ static void _collision_capsule_convex_polygon(const Shape2DSW *p_a, const Transf
/////////
template <bool castA, bool castB, bool withMargin>
-static void _collision_convex_polygon_convex_polygon(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
- const ConvexPolygonShape2DSW *convex_A = static_cast<const ConvexPolygonShape2DSW *>(p_a);
- const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW *>(p_b);
+static void _collision_convex_polygon_convex_polygon(const GodotShape2D *p_a, const Transform2D &p_transform_a, const GodotShape2D *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
+ const GodotConvexPolygonShape2D *convex_A = static_cast<const GodotConvexPolygonShape2D *>(p_a);
+ const GodotConvexPolygonShape2D *convex_B = static_cast<const GodotConvexPolygonShape2D *>(p_b);
- SeparatorAxisTest2D<ConvexPolygonShape2DSW, ConvexPolygonShape2DSW, castA, castB, withMargin> separator(convex_A, p_transform_a, convex_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
+ SeparatorAxisTest2D<GodotConvexPolygonShape2D, GodotConvexPolygonShape2D, castA, castB, withMargin> separator(convex_A, p_transform_a, convex_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
if (!separator.test_previous_axis()) {
return;
@@ -1107,7 +1107,7 @@ static void _collision_convex_polygon_convex_polygon(const Shape2DSW *p_a, const
////////
-bool sat_2d_calculate_penetration(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CollisionSolver2DSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap, Vector2 *sep_axis, real_t p_margin_A, real_t p_margin_B) {
+bool sat_2d_calculate_penetration(const GodotShape2D *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const GodotShape2D *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, GodotCollisionSolver2D::CallbackResult p_result_callback, void *p_userdata, bool p_swap, Vector2 *sep_axis, real_t p_margin_A, real_t p_margin_B) {
PhysicsServer2D::ShapeType type_A = p_shape_A->get_type();
ERR_FAIL_COND_V(type_A == PhysicsServer2D::SHAPE_WORLD_BOUNDARY, false);
@@ -1359,8 +1359,8 @@ bool sat_2d_calculate_penetration(const Shape2DSW *p_shape_A, const Transform2D
callback.collided = false;
callback.sep_axis = sep_axis;
- const Shape2DSW *A = p_shape_A;
- const Shape2DSW *B = p_shape_B;
+ const GodotShape2D *A = p_shape_A;
+ const GodotShape2D *B = p_shape_B;
const Transform2D *transform_A = &p_transform_A;
const Transform2D *transform_B = &p_transform_B;
const Vector2 *motion_A = &p_motion_A;
diff --git a/servers/physics_2d/collision_solver_2d_sat.h b/servers/physics_2d/godot_collision_solver_2d_sat.h
index 49cc5176f9..3d8e29c41a 100644
--- a/servers/physics_2d/collision_solver_2d_sat.h
+++ b/servers/physics_2d/godot_collision_solver_2d_sat.h
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* collision_solver_2d_sat.h */
+/* godot_collision_solver_2d_sat.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,11 +28,11 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef COLLISION_SOLVER_2D_SAT_H
-#define COLLISION_SOLVER_2D_SAT_H
+#ifndef GODOT_COLLISION_SOLVER_2D_SAT_H
+#define GODOT_COLLISION_SOLVER_2D_SAT_H
-#include "collision_solver_2d_sw.h"
+#include "godot_collision_solver_2d.h"
-bool sat_2d_calculate_penetration(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CollisionSolver2DSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap = false, Vector2 *sep_axis = nullptr, real_t p_margin_A = 0, real_t p_margin_B = 0);
+bool sat_2d_calculate_penetration(const GodotShape2D *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const GodotShape2D *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, GodotCollisionSolver2D::CallbackResult p_result_callback, void *p_userdata, bool p_swap = false, Vector2 *sep_axis = nullptr, real_t p_margin_A = 0, real_t p_margin_B = 0);
-#endif // COLLISION_SOLVER_2D_SAT_H
+#endif // GODOT_COLLISION_SOLVER_2D_SAT_H
diff --git a/servers/physics_2d/constraint_2d_sw.h b/servers/physics_2d/godot_constraint_2d.h
index df300d666d..d9bf035c2b 100644
--- a/servers/physics_2d/constraint_2d_sw.h
+++ b/servers/physics_2d/godot_constraint_2d.h
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* constraint_2d_sw.h */
+/* godot_constraint_2d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,13 +28,13 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef CONSTRAINT_2D_SW_H
-#define CONSTRAINT_2D_SW_H
+#ifndef GODOT_CONSTRAINT_2D_H
+#define GODOT_CONSTRAINT_2D_H
-#include "body_2d_sw.h"
+#include "godot_body_2d.h"
-class Constraint2DSW {
- Body2DSW **_body_ptr;
+class GodotConstraint2D {
+ GodotBody2D **_body_ptr;
int _body_count;
uint64_t island_step = 0;
bool disabled_collisions_between_bodies = true;
@@ -42,7 +42,7 @@ class Constraint2DSW {
RID self;
protected:
- Constraint2DSW(Body2DSW **p_body_ptr = nullptr, int p_body_count = 0) {
+ GodotConstraint2D(GodotBody2D **p_body_ptr = nullptr, int p_body_count = 0) {
_body_ptr = p_body_ptr;
_body_count = p_body_count;
}
@@ -54,7 +54,7 @@ public:
_FORCE_INLINE_ uint64_t get_island_step() const { return island_step; }
_FORCE_INLINE_ void set_island_step(uint64_t p_step) { island_step = p_step; }
- _FORCE_INLINE_ Body2DSW **get_body_ptr() const { return _body_ptr; }
+ _FORCE_INLINE_ GodotBody2D **get_body_ptr() const { return _body_ptr; }
_FORCE_INLINE_ int get_body_count() const { return _body_count; }
_FORCE_INLINE_ void disable_collisions_between_bodies(const bool p_disabled) { disabled_collisions_between_bodies = p_disabled; }
@@ -64,7 +64,7 @@ public:
virtual bool pre_solve(real_t p_step) = 0;
virtual void solve(real_t p_step) = 0;
- virtual ~Constraint2DSW() {}
+ virtual ~GodotConstraint2D() {}
};
-#endif // CONSTRAINT_2D_SW_H
+#endif // GODOT_CONSTRAINT_2D_H
diff --git a/servers/physics_2d/joints_2d_sw.cpp b/servers/physics_2d/godot_joints_2d.cpp
index b46397b8e6..0876184d8c 100644
--- a/servers/physics_2d/joints_2d_sw.cpp
+++ b/servers/physics_2d/godot_joints_2d.cpp
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* joints_2d_sw.cpp */
+/* godot_joints_2d.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,9 +28,9 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "joints_2d_sw.h"
+#include "godot_joints_2d.h"
-#include "space_2d_sw.h"
+#include "godot_space_2d.h"
//based on chipmunk joint constraints
@@ -55,7 +55,7 @@
* SOFTWARE.
*/
-void Joint2DSW::copy_settings_from(Joint2DSW *p_joint) {
+void GodotJoint2D::copy_settings_from(GodotJoint2D *p_joint) {
set_self(p_joint->get_self());
set_max_force(p_joint->get_max_force());
set_bias(p_joint->get_bias());
@@ -63,7 +63,7 @@ void Joint2DSW::copy_settings_from(Joint2DSW *p_joint) {
disable_collisions_between_bodies(p_joint->is_disabled_collisions_between_bodies());
}
-static inline real_t k_scalar(Body2DSW *a, Body2DSW *b, const Vector2 &rA, const Vector2 &rB, const Vector2 &n) {
+static inline real_t k_scalar(GodotBody2D *a, GodotBody2D *b, const Vector2 &rA, const Vector2 &rB, const Vector2 &n) {
real_t value = 0.0;
{
@@ -82,7 +82,7 @@ static inline real_t k_scalar(Body2DSW *a, Body2DSW *b, const Vector2 &rA, const
}
static inline Vector2
-relative_velocity(Body2DSW *a, Body2DSW *b, Vector2 rA, Vector2 rB) {
+relative_velocity(GodotBody2D *a, GodotBody2D *b, Vector2 rA, Vector2 rB) {
Vector2 sum = a->get_linear_velocity() - (rA - a->get_center_of_mass()).orthogonal() * a->get_angular_velocity();
if (b) {
return (b->get_linear_velocity() - (rB - b->get_center_of_mass()).orthogonal() * b->get_angular_velocity()) - sum;
@@ -92,11 +92,11 @@ relative_velocity(Body2DSW *a, Body2DSW *b, Vector2 rA, Vector2 rB) {
}
static inline real_t
-normal_relative_velocity(Body2DSW *a, Body2DSW *b, Vector2 rA, Vector2 rB, Vector2 n) {
+normal_relative_velocity(GodotBody2D *a, GodotBody2D *b, Vector2 rA, Vector2 rB, Vector2 n) {
return relative_velocity(a, b, rA, rB).dot(n);
}
-bool PinJoint2DSW::setup(real_t p_step) {
+bool GodotPinJoint2D::setup(real_t p_step) {
dynamic_A = (A->get_mode() > PhysicsServer2D::BODY_MODE_KINEMATIC);
dynamic_B = (B->get_mode() > PhysicsServer2D::BODY_MODE_KINEMATIC);
@@ -104,7 +104,7 @@ bool PinJoint2DSW::setup(real_t p_step) {
return false;
}
- Space2DSW *space = A->get_space();
+ GodotSpace2D *space = A->get_space();
ERR_FAIL_COND_V(!space, false);
rA = A->get_transform().basis_xform(anchor_A);
@@ -158,7 +158,7 @@ inline Vector2 custom_cross(const Vector2 &p_vec, real_t p_other) {
return Vector2(p_other * p_vec.y, -p_other * p_vec.x);
}
-bool PinJoint2DSW::pre_solve(real_t p_step) {
+bool GodotPinJoint2D::pre_solve(real_t p_step) {
// Apply accumulated impulse.
if (dynamic_A) {
A->apply_impulse(-P, rA);
@@ -170,7 +170,7 @@ bool PinJoint2DSW::pre_solve(real_t p_step) {
return true;
}
-void PinJoint2DSW::solve(real_t p_step) {
+void GodotPinJoint2D::solve(real_t p_step) {
// compute relative velocity
Vector2 vA = A->get_linear_velocity() - custom_cross(rA - A->get_center_of_mass(), A->get_angular_velocity());
@@ -193,21 +193,21 @@ void PinJoint2DSW::solve(real_t p_step) {
P += impulse;
}
-void PinJoint2DSW::set_param(PhysicsServer2D::PinJointParam p_param, real_t p_value) {
+void GodotPinJoint2D::set_param(PhysicsServer2D::PinJointParam p_param, real_t p_value) {
if (p_param == PhysicsServer2D::PIN_JOINT_SOFTNESS) {
softness = p_value;
}
}
-real_t PinJoint2DSW::get_param(PhysicsServer2D::PinJointParam p_param) const {
+real_t GodotPinJoint2D::get_param(PhysicsServer2D::PinJointParam p_param) const {
if (p_param == PhysicsServer2D::PIN_JOINT_SOFTNESS) {
return softness;
}
ERR_FAIL_V(0);
}
-PinJoint2DSW::PinJoint2DSW(const Vector2 &p_pos, Body2DSW *p_body_a, Body2DSW *p_body_b) :
- Joint2DSW(_arr, p_body_b ? 2 : 1) {
+GodotPinJoint2D::GodotPinJoint2D(const Vector2 &p_pos, GodotBody2D *p_body_a, GodotBody2D *p_body_b) :
+ GodotJoint2D(_arr, p_body_b ? 2 : 1) {
A = p_body_a;
B = p_body_b;
anchor_A = p_body_a->get_inv_transform().xform(p_pos);
@@ -224,7 +224,7 @@ PinJoint2DSW::PinJoint2DSW(const Vector2 &p_pos, Body2DSW *p_body_a, Body2DSW *p
//////////////////////////////////////////////
static inline void
-k_tensor(Body2DSW *a, Body2DSW *b, Vector2 r1, Vector2 r2, Vector2 *k1, Vector2 *k2) {
+k_tensor(GodotBody2D *a, GodotBody2D *b, Vector2 r1, Vector2 r2, Vector2 *k1, Vector2 *k2) {
// calculate mass matrix
// If I wasn't lazy and wrote a proper matrix class, this wouldn't be so gross...
real_t k11, k12, k21, k22;
@@ -273,7 +273,7 @@ mult_k(const Vector2 &vr, const Vector2 &k1, const Vector2 &k2) {
return Vector2(vr.dot(k1), vr.dot(k2));
}
-bool GrooveJoint2DSW::setup(real_t p_step) {
+bool GodotGrooveJoint2D::setup(real_t p_step) {
dynamic_A = (A->get_mode() > PhysicsServer2D::BODY_MODE_KINEMATIC);
dynamic_B = (B->get_mode() > PhysicsServer2D::BODY_MODE_KINEMATIC);
@@ -281,7 +281,7 @@ bool GrooveJoint2DSW::setup(real_t p_step) {
return false;
}
- Space2DSW *space = A->get_space();
+ GodotSpace2D *space = A->get_space();
ERR_FAIL_COND_V(!space, false);
// calculate endpoints in worldspace
@@ -329,7 +329,7 @@ bool GrooveJoint2DSW::setup(real_t p_step) {
return true;
}
-bool GrooveJoint2DSW::pre_solve(real_t p_step) {
+bool GodotGrooveJoint2D::pre_solve(real_t p_step) {
// Apply accumulated impulse.
if (dynamic_A) {
A->apply_impulse(-jn_acc, rA);
@@ -341,7 +341,7 @@ bool GrooveJoint2DSW::pre_solve(real_t p_step) {
return true;
}
-void GrooveJoint2DSW::solve(real_t p_step) {
+void GodotGrooveJoint2D::solve(real_t p_step) {
// compute impulse
Vector2 vr = relative_velocity(A, B, rA, rB);
@@ -361,8 +361,8 @@ void GrooveJoint2DSW::solve(real_t p_step) {
}
}
-GrooveJoint2DSW::GrooveJoint2DSW(const Vector2 &p_a_groove1, const Vector2 &p_a_groove2, const Vector2 &p_b_anchor, Body2DSW *p_body_a, Body2DSW *p_body_b) :
- Joint2DSW(_arr, 2) {
+GodotGrooveJoint2D::GodotGrooveJoint2D(const Vector2 &p_a_groove1, const Vector2 &p_a_groove2, const Vector2 &p_b_anchor, GodotBody2D *p_body_a, GodotBody2D *p_body_b) :
+ GodotJoint2D(_arr, 2) {
A = p_body_a;
B = p_body_b;
@@ -379,7 +379,7 @@ GrooveJoint2DSW::GrooveJoint2DSW(const Vector2 &p_a_groove1, const Vector2 &p_a_
//////////////////////////////////////////////
//////////////////////////////////////////////
-bool DampedSpringJoint2DSW::setup(real_t p_step) {
+bool GodotDampedSpringJoint2D::setup(real_t p_step) {
dynamic_A = (A->get_mode() > PhysicsServer2D::BODY_MODE_KINEMATIC);
dynamic_B = (B->get_mode() > PhysicsServer2D::BODY_MODE_KINEMATIC);
@@ -412,7 +412,7 @@ bool DampedSpringJoint2DSW::setup(real_t p_step) {
return true;
}
-bool DampedSpringJoint2DSW::pre_solve(real_t p_step) {
+bool GodotDampedSpringJoint2D::pre_solve(real_t p_step) {
// Apply spring force.
if (dynamic_A) {
A->apply_impulse(-j, rA);
@@ -424,7 +424,7 @@ bool DampedSpringJoint2DSW::pre_solve(real_t p_step) {
return true;
}
-void DampedSpringJoint2DSW::solve(real_t p_step) {
+void GodotDampedSpringJoint2D::solve(real_t p_step) {
// compute relative velocity
real_t vrn = normal_relative_velocity(A, B, rA, rB, n) - target_vrn;
@@ -442,7 +442,7 @@ void DampedSpringJoint2DSW::solve(real_t p_step) {
}
}
-void DampedSpringJoint2DSW::set_param(PhysicsServer2D::DampedSpringParam p_param, real_t p_value) {
+void GodotDampedSpringJoint2D::set_param(PhysicsServer2D::DampedSpringParam p_param, real_t p_value) {
switch (p_param) {
case PhysicsServer2D::DAMPED_SPRING_REST_LENGTH: {
rest_length = p_value;
@@ -456,7 +456,7 @@ void DampedSpringJoint2DSW::set_param(PhysicsServer2D::DampedSpringParam p_param
}
}
-real_t DampedSpringJoint2DSW::get_param(PhysicsServer2D::DampedSpringParam p_param) const {
+real_t GodotDampedSpringJoint2D::get_param(PhysicsServer2D::DampedSpringParam p_param) const {
switch (p_param) {
case PhysicsServer2D::DAMPED_SPRING_REST_LENGTH: {
return rest_length;
@@ -472,8 +472,8 @@ real_t DampedSpringJoint2DSW::get_param(PhysicsServer2D::DampedSpringParam p_par
ERR_FAIL_V(0);
}
-DampedSpringJoint2DSW::DampedSpringJoint2DSW(const Vector2 &p_anchor_a, const Vector2 &p_anchor_b, Body2DSW *p_body_a, Body2DSW *p_body_b) :
- Joint2DSW(_arr, 2) {
+GodotDampedSpringJoint2D::GodotDampedSpringJoint2D(const Vector2 &p_anchor_a, const Vector2 &p_anchor_b, GodotBody2D *p_body_a, GodotBody2D *p_body_b) :
+ GodotJoint2D(_arr, 2) {
A = p_body_a;
B = p_body_b;
anchor_A = A->get_inv_transform().xform(p_anchor_a);
diff --git a/servers/physics_2d/joints_2d_sw.h b/servers/physics_2d/godot_joints_2d.h
index e2a7c0c91e..acaaf0f629 100644
--- a/servers/physics_2d/joints_2d_sw.h
+++ b/servers/physics_2d/godot_joints_2d.h
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* joints_2d_sw.h */
+/* godot_joints_2d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,13 +28,13 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef JOINTS_2D_SW_H
-#define JOINTS_2D_SW_H
+#ifndef GODOT_JOINTS_2D_H
+#define GODOT_JOINTS_2D_H
-#include "body_2d_sw.h"
-#include "constraint_2d_sw.h"
+#include "godot_body_2d.h"
+#include "godot_constraint_2d.h"
-class Joint2DSW : public Constraint2DSW {
+class GodotJoint2D : public GodotConstraint2D {
real_t bias = 0;
real_t max_bias = 3.40282e+38;
real_t max_force = 3.40282e+38;
@@ -57,15 +57,15 @@ public:
virtual bool pre_solve(real_t p_step) override { return false; }
virtual void solve(real_t p_step) override {}
- void copy_settings_from(Joint2DSW *p_joint);
+ void copy_settings_from(GodotJoint2D *p_joint);
virtual PhysicsServer2D::JointType get_type() const { return PhysicsServer2D::JOINT_TYPE_MAX; }
- Joint2DSW(Body2DSW **p_body_ptr = nullptr, int p_body_count = 0) :
- Constraint2DSW(p_body_ptr, p_body_count) {}
+ GodotJoint2D(GodotBody2D **p_body_ptr = nullptr, int p_body_count = 0) :
+ GodotConstraint2D(p_body_ptr, p_body_count) {}
- virtual ~Joint2DSW() {
+ virtual ~GodotJoint2D() {
for (int i = 0; i < get_body_count(); i++) {
- Body2DSW *body = get_body_ptr()[i];
+ GodotBody2D *body = get_body_ptr()[i];
if (body) {
body->remove_constraint(this, i);
}
@@ -73,14 +73,14 @@ public:
};
};
-class PinJoint2DSW : public Joint2DSW {
+class GodotPinJoint2D : public GodotJoint2D {
union {
struct {
- Body2DSW *A;
- Body2DSW *B;
+ GodotBody2D *A;
+ GodotBody2D *B;
};
- Body2DSW *_arr[2] = { nullptr, nullptr };
+ GodotBody2D *_arr[2] = { nullptr, nullptr };
};
Transform2D M;
@@ -101,17 +101,17 @@ public:
void set_param(PhysicsServer2D::PinJointParam p_param, real_t p_value);
real_t get_param(PhysicsServer2D::PinJointParam p_param) const;
- PinJoint2DSW(const Vector2 &p_pos, Body2DSW *p_body_a, Body2DSW *p_body_b = nullptr);
+ GodotPinJoint2D(const Vector2 &p_pos, GodotBody2D *p_body_a, GodotBody2D *p_body_b = nullptr);
};
-class GrooveJoint2DSW : public Joint2DSW {
+class GodotGrooveJoint2D : public GodotJoint2D {
union {
struct {
- Body2DSW *A;
- Body2DSW *B;
+ GodotBody2D *A;
+ GodotBody2D *B;
};
- Body2DSW *_arr[2] = { nullptr, nullptr };
+ GodotBody2D *_arr[2] = { nullptr, nullptr };
};
Vector2 A_groove_1;
@@ -135,17 +135,17 @@ public:
virtual bool pre_solve(real_t p_step) override;
virtual void solve(real_t p_step) override;
- GrooveJoint2DSW(const Vector2 &p_a_groove1, const Vector2 &p_a_groove2, const Vector2 &p_b_anchor, Body2DSW *p_body_a, Body2DSW *p_body_b);
+ GodotGrooveJoint2D(const Vector2 &p_a_groove1, const Vector2 &p_a_groove2, const Vector2 &p_b_anchor, GodotBody2D *p_body_a, GodotBody2D *p_body_b);
};
-class DampedSpringJoint2DSW : public Joint2DSW {
+class GodotDampedSpringJoint2D : public GodotJoint2D {
union {
struct {
- Body2DSW *A;
- Body2DSW *B;
+ GodotBody2D *A;
+ GodotBody2D *B;
};
- Body2DSW *_arr[2] = { nullptr, nullptr };
+ GodotBody2D *_arr[2] = { nullptr, nullptr };
};
Vector2 anchor_A;
@@ -172,7 +172,7 @@ public:
void set_param(PhysicsServer2D::DampedSpringParam p_param, real_t p_value);
real_t get_param(PhysicsServer2D::DampedSpringParam p_param) const;
- DampedSpringJoint2DSW(const Vector2 &p_anchor_a, const Vector2 &p_anchor_b, Body2DSW *p_body_a, Body2DSW *p_body_b);
+ GodotDampedSpringJoint2D(const Vector2 &p_anchor_a, const Vector2 &p_anchor_b, GodotBody2D *p_body_a, GodotBody2D *p_body_b);
};
-#endif // JOINTS_2D_SW_H
+#endif // GODOT_JOINTS_2D_H
diff --git a/servers/physics_2d/godot_physics_server_2d.cpp b/servers/physics_2d/godot_physics_server_2d.cpp
new file mode 100644
index 0000000000..5e099e27ec
--- /dev/null
+++ b/servers/physics_2d/godot_physics_server_2d.cpp
@@ -0,0 +1,1366 @@
+/*************************************************************************/
+/* godot_physics_server_2d.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 "godot_physics_server_2d.h"
+
+#include "godot_body_direct_state_2d.h"
+#include "godot_broad_phase_2d_bvh.h"
+#include "godot_collision_solver_2d.h"
+
+#include "core/config/project_settings.h"
+#include "core/debugger/engine_debugger.h"
+#include "core/os/os.h"
+
+#define FLUSH_QUERY_CHECK(m_object) \
+ ERR_FAIL_COND_MSG(m_object->get_space() && flushing_queries, "Can't change this state while flushing queries. Use call_deferred() or set_deferred() to change monitoring state instead.");
+
+RID GodotPhysicsServer2D::_shape_create(ShapeType p_shape) {
+ GodotShape2D *shape = nullptr;
+ switch (p_shape) {
+ case SHAPE_WORLD_BOUNDARY: {
+ shape = memnew(GodotWorldBoundaryShape2D);
+ } break;
+ case SHAPE_SEPARATION_RAY: {
+ shape = memnew(GodotSeparationRayShape2D);
+ } break;
+ case SHAPE_SEGMENT: {
+ shape = memnew(GodotSegmentShape2D);
+ } break;
+ case SHAPE_CIRCLE: {
+ shape = memnew(GodotCircleShape2D);
+ } break;
+ case SHAPE_RECTANGLE: {
+ shape = memnew(GodotRectangleShape2D);
+ } break;
+ case SHAPE_CAPSULE: {
+ shape = memnew(GodotCapsuleShape2D);
+ } break;
+ case SHAPE_CONVEX_POLYGON: {
+ shape = memnew(GodotConvexPolygonShape2D);
+ } break;
+ case SHAPE_CONCAVE_POLYGON: {
+ shape = memnew(GodotConcavePolygonShape2D);
+ } break;
+ case SHAPE_CUSTOM: {
+ ERR_FAIL_V(RID());
+
+ } break;
+ }
+
+ RID id = shape_owner.make_rid(shape);
+ shape->set_self(id);
+
+ return id;
+}
+
+RID GodotPhysicsServer2D::world_boundary_shape_create() {
+ return _shape_create(SHAPE_WORLD_BOUNDARY);
+}
+
+RID GodotPhysicsServer2D::separation_ray_shape_create() {
+ return _shape_create(SHAPE_SEPARATION_RAY);
+}
+
+RID GodotPhysicsServer2D::segment_shape_create() {
+ return _shape_create(SHAPE_SEGMENT);
+}
+
+RID GodotPhysicsServer2D::circle_shape_create() {
+ return _shape_create(SHAPE_CIRCLE);
+}
+
+RID GodotPhysicsServer2D::rectangle_shape_create() {
+ return _shape_create(SHAPE_RECTANGLE);
+}
+
+RID GodotPhysicsServer2D::capsule_shape_create() {
+ return _shape_create(SHAPE_CAPSULE);
+}
+
+RID GodotPhysicsServer2D::convex_polygon_shape_create() {
+ return _shape_create(SHAPE_CONVEX_POLYGON);
+}
+
+RID GodotPhysicsServer2D::concave_polygon_shape_create() {
+ return _shape_create(SHAPE_CONCAVE_POLYGON);
+}
+
+void GodotPhysicsServer2D::shape_set_data(RID p_shape, const Variant &p_data) {
+ GodotShape2D *shape = shape_owner.get_or_null(p_shape);
+ ERR_FAIL_COND(!shape);
+ shape->set_data(p_data);
+};
+
+void GodotPhysicsServer2D::shape_set_custom_solver_bias(RID p_shape, real_t p_bias) {
+ GodotShape2D *shape = shape_owner.get_or_null(p_shape);
+ ERR_FAIL_COND(!shape);
+ shape->set_custom_bias(p_bias);
+}
+
+PhysicsServer2D::ShapeType GodotPhysicsServer2D::shape_get_type(RID p_shape) const {
+ const GodotShape2D *shape = shape_owner.get_or_null(p_shape);
+ ERR_FAIL_COND_V(!shape, SHAPE_CUSTOM);
+ return shape->get_type();
+};
+
+Variant GodotPhysicsServer2D::shape_get_data(RID p_shape) const {
+ const GodotShape2D *shape = shape_owner.get_or_null(p_shape);
+ ERR_FAIL_COND_V(!shape, Variant());
+ ERR_FAIL_COND_V(!shape->is_configured(), Variant());
+ return shape->get_data();
+};
+
+real_t GodotPhysicsServer2D::shape_get_custom_solver_bias(RID p_shape) const {
+ const GodotShape2D *shape = shape_owner.get_or_null(p_shape);
+ ERR_FAIL_COND_V(!shape, 0);
+ return shape->get_custom_bias();
+}
+
+void GodotPhysicsServer2D::_shape_col_cbk(const Vector2 &p_point_A, const Vector2 &p_point_B, void *p_userdata) {
+ CollCbkData *cbk = (CollCbkData *)p_userdata;
+
+ if (cbk->max == 0) {
+ return;
+ }
+
+ Vector2 rel_dir = (p_point_A - p_point_B);
+ real_t rel_length2 = rel_dir.length_squared();
+ if (cbk->valid_dir != Vector2()) {
+ if (cbk->valid_depth < 10e20) {
+ if (rel_length2 > cbk->valid_depth * cbk->valid_depth ||
+ (rel_length2 > CMP_EPSILON && cbk->valid_dir.dot(rel_dir.normalized()) < CMP_EPSILON)) {
+ cbk->invalid_by_dir++;
+ return;
+ }
+ } else {
+ if (rel_length2 > 0 && cbk->valid_dir.dot(rel_dir.normalized()) < CMP_EPSILON) {
+ return;
+ }
+ }
+ }
+
+ if (cbk->amount == cbk->max) {
+ //find least deep
+ real_t min_depth = 1e20;
+ int min_depth_idx = 0;
+ for (int i = 0; i < cbk->amount; i++) {
+ real_t d = cbk->ptr[i * 2 + 0].distance_squared_to(cbk->ptr[i * 2 + 1]);
+ if (d < min_depth) {
+ min_depth = d;
+ min_depth_idx = i;
+ }
+ }
+
+ if (rel_length2 < min_depth) {
+ return;
+ }
+ cbk->ptr[min_depth_idx * 2 + 0] = p_point_A;
+ cbk->ptr[min_depth_idx * 2 + 1] = p_point_B;
+ cbk->passed++;
+
+ } else {
+ cbk->ptr[cbk->amount * 2 + 0] = p_point_A;
+ cbk->ptr[cbk->amount * 2 + 1] = p_point_B;
+ cbk->amount++;
+ cbk->passed++;
+ }
+}
+
+bool GodotPhysicsServer2D::shape_collide(RID p_shape_A, const Transform2D &p_xform_A, const Vector2 &p_motion_A, RID p_shape_B, const Transform2D &p_xform_B, const Vector2 &p_motion_B, Vector2 *r_results, int p_result_max, int &r_result_count) {
+ GodotShape2D *shape_A = shape_owner.get_or_null(p_shape_A);
+ ERR_FAIL_COND_V(!shape_A, false);
+ GodotShape2D *shape_B = shape_owner.get_or_null(p_shape_B);
+ ERR_FAIL_COND_V(!shape_B, false);
+
+ if (p_result_max == 0) {
+ return GodotCollisionSolver2D::solve(shape_A, p_xform_A, p_motion_A, shape_B, p_xform_B, p_motion_B, nullptr, nullptr);
+ }
+
+ CollCbkData cbk;
+ cbk.max = p_result_max;
+ cbk.amount = 0;
+ cbk.passed = 0;
+ cbk.ptr = r_results;
+
+ bool res = GodotCollisionSolver2D::solve(shape_A, p_xform_A, p_motion_A, shape_B, p_xform_B, p_motion_B, _shape_col_cbk, &cbk);
+ r_result_count = cbk.amount;
+ return res;
+}
+
+RID GodotPhysicsServer2D::space_create() {
+ GodotSpace2D *space = memnew(GodotSpace2D);
+ RID id = space_owner.make_rid(space);
+ space->set_self(id);
+ RID area_id = area_create();
+ GodotArea2D *area = area_owner.get_or_null(area_id);
+ ERR_FAIL_COND_V(!area, RID());
+ space->set_default_area(area);
+ area->set_space(space);
+ area->set_priority(-1);
+
+ return id;
+};
+
+void GodotPhysicsServer2D::space_set_active(RID p_space, bool p_active) {
+ GodotSpace2D *space = space_owner.get_or_null(p_space);
+ ERR_FAIL_COND(!space);
+ if (p_active) {
+ active_spaces.insert(space);
+ } else {
+ active_spaces.erase(space);
+ }
+}
+
+bool GodotPhysicsServer2D::space_is_active(RID p_space) const {
+ const GodotSpace2D *space = space_owner.get_or_null(p_space);
+ ERR_FAIL_COND_V(!space, false);
+
+ return active_spaces.has(space);
+}
+
+void GodotPhysicsServer2D::space_set_param(RID p_space, SpaceParameter p_param, real_t p_value) {
+ GodotSpace2D *space = space_owner.get_or_null(p_space);
+ ERR_FAIL_COND(!space);
+
+ space->set_param(p_param, p_value);
+}
+
+real_t GodotPhysicsServer2D::space_get_param(RID p_space, SpaceParameter p_param) const {
+ const GodotSpace2D *space = space_owner.get_or_null(p_space);
+ ERR_FAIL_COND_V(!space, 0);
+ return space->get_param(p_param);
+}
+
+void GodotPhysicsServer2D::space_set_debug_contacts(RID p_space, int p_max_contacts) {
+ GodotSpace2D *space = space_owner.get_or_null(p_space);
+ ERR_FAIL_COND(!space);
+ space->set_debug_contacts(p_max_contacts);
+}
+
+Vector<Vector2> GodotPhysicsServer2D::space_get_contacts(RID p_space) const {
+ GodotSpace2D *space = space_owner.get_or_null(p_space);
+ ERR_FAIL_COND_V(!space, Vector<Vector2>());
+ return space->get_debug_contacts();
+}
+
+int GodotPhysicsServer2D::space_get_contact_count(RID p_space) const {
+ GodotSpace2D *space = space_owner.get_or_null(p_space);
+ ERR_FAIL_COND_V(!space, 0);
+ return space->get_debug_contact_count();
+}
+
+PhysicsDirectSpaceState2D *GodotPhysicsServer2D::space_get_direct_state(RID p_space) {
+ GodotSpace2D *space = space_owner.get_or_null(p_space);
+ ERR_FAIL_COND_V(!space, nullptr);
+ ERR_FAIL_COND_V_MSG((using_threads && !doing_sync) || space->is_locked(), nullptr, "Space state is inaccessible right now, wait for iteration or physics process notification.");
+
+ return space->get_direct_state();
+}
+
+RID GodotPhysicsServer2D::area_create() {
+ GodotArea2D *area = memnew(GodotArea2D);
+ RID rid = area_owner.make_rid(area);
+ area->set_self(rid);
+ return rid;
+}
+
+void GodotPhysicsServer2D::area_set_space(RID p_area, RID p_space) {
+ GodotArea2D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND(!area);
+
+ GodotSpace2D *space = nullptr;
+ if (p_space.is_valid()) {
+ space = space_owner.get_or_null(p_space);
+ ERR_FAIL_COND(!space);
+ }
+
+ if (area->get_space() == space) {
+ return; //pointless
+ }
+
+ area->clear_constraints();
+ area->set_space(space);
+}
+
+RID GodotPhysicsServer2D::area_get_space(RID p_area) const {
+ GodotArea2D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND_V(!area, RID());
+
+ GodotSpace2D *space = area->get_space();
+ if (!space) {
+ return RID();
+ }
+ return space->get_self();
+}
+
+void GodotPhysicsServer2D::area_add_shape(RID p_area, RID p_shape, const Transform2D &p_transform, bool p_disabled) {
+ GodotArea2D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND(!area);
+
+ GodotShape2D *shape = shape_owner.get_or_null(p_shape);
+ ERR_FAIL_COND(!shape);
+
+ area->add_shape(shape, p_transform, p_disabled);
+}
+
+void GodotPhysicsServer2D::area_set_shape(RID p_area, int p_shape_idx, RID p_shape) {
+ GodotArea2D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND(!area);
+
+ GodotShape2D *shape = shape_owner.get_or_null(p_shape);
+ ERR_FAIL_COND(!shape);
+ ERR_FAIL_COND(!shape->is_configured());
+
+ area->set_shape(p_shape_idx, shape);
+}
+
+void GodotPhysicsServer2D::area_set_shape_transform(RID p_area, int p_shape_idx, const Transform2D &p_transform) {
+ GodotArea2D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND(!area);
+
+ area->set_shape_transform(p_shape_idx, p_transform);
+}
+
+void GodotPhysicsServer2D::area_set_shape_disabled(RID p_area, int p_shape, bool p_disabled) {
+ GodotArea2D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND(!area);
+ ERR_FAIL_INDEX(p_shape, area->get_shape_count());
+ FLUSH_QUERY_CHECK(area);
+
+ area->set_shape_disabled(p_shape, p_disabled);
+}
+
+int GodotPhysicsServer2D::area_get_shape_count(RID p_area) const {
+ GodotArea2D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND_V(!area, -1);
+
+ return area->get_shape_count();
+}
+
+RID GodotPhysicsServer2D::area_get_shape(RID p_area, int p_shape_idx) const {
+ GodotArea2D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND_V(!area, RID());
+
+ GodotShape2D *shape = area->get_shape(p_shape_idx);
+ ERR_FAIL_COND_V(!shape, RID());
+
+ return shape->get_self();
+}
+
+Transform2D GodotPhysicsServer2D::area_get_shape_transform(RID p_area, int p_shape_idx) const {
+ GodotArea2D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND_V(!area, Transform2D());
+
+ return area->get_shape_transform(p_shape_idx);
+}
+
+void GodotPhysicsServer2D::area_remove_shape(RID p_area, int p_shape_idx) {
+ GodotArea2D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND(!area);
+
+ area->remove_shape(p_shape_idx);
+}
+
+void GodotPhysicsServer2D::area_clear_shapes(RID p_area) {
+ GodotArea2D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND(!area);
+
+ while (area->get_shape_count()) {
+ area->remove_shape(0);
+ }
+}
+
+void GodotPhysicsServer2D::area_attach_object_instance_id(RID p_area, ObjectID p_id) {
+ if (space_owner.owns(p_area)) {
+ GodotSpace2D *space = space_owner.get_or_null(p_area);
+ p_area = space->get_default_area()->get_self();
+ }
+ GodotArea2D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND(!area);
+ area->set_instance_id(p_id);
+}
+
+ObjectID GodotPhysicsServer2D::area_get_object_instance_id(RID p_area) const {
+ if (space_owner.owns(p_area)) {
+ GodotSpace2D *space = space_owner.get_or_null(p_area);
+ p_area = space->get_default_area()->get_self();
+ }
+ GodotArea2D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND_V(!area, ObjectID());
+ return area->get_instance_id();
+}
+
+void GodotPhysicsServer2D::area_attach_canvas_instance_id(RID p_area, ObjectID p_id) {
+ if (space_owner.owns(p_area)) {
+ GodotSpace2D *space = space_owner.get_or_null(p_area);
+ p_area = space->get_default_area()->get_self();
+ }
+ GodotArea2D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND(!area);
+ area->set_canvas_instance_id(p_id);
+}
+
+ObjectID GodotPhysicsServer2D::area_get_canvas_instance_id(RID p_area) const {
+ if (space_owner.owns(p_area)) {
+ GodotSpace2D *space = space_owner.get_or_null(p_area);
+ p_area = space->get_default_area()->get_self();
+ }
+ GodotArea2D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND_V(!area, ObjectID());
+ return area->get_canvas_instance_id();
+}
+
+void GodotPhysicsServer2D::area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value) {
+ if (space_owner.owns(p_area)) {
+ GodotSpace2D *space = space_owner.get_or_null(p_area);
+ p_area = space->get_default_area()->get_self();
+ }
+ GodotArea2D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND(!area);
+ area->set_param(p_param, p_value);
+};
+
+void GodotPhysicsServer2D::area_set_transform(RID p_area, const Transform2D &p_transform) {
+ GodotArea2D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND(!area);
+ area->set_transform(p_transform);
+};
+
+Variant GodotPhysicsServer2D::area_get_param(RID p_area, AreaParameter p_param) const {
+ if (space_owner.owns(p_area)) {
+ GodotSpace2D *space = space_owner.get_or_null(p_area);
+ p_area = space->get_default_area()->get_self();
+ }
+ GodotArea2D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND_V(!area, Variant());
+
+ return area->get_param(p_param);
+};
+
+Transform2D GodotPhysicsServer2D::area_get_transform(RID p_area) const {
+ GodotArea2D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND_V(!area, Transform2D());
+
+ return area->get_transform();
+};
+
+void GodotPhysicsServer2D::area_set_pickable(RID p_area, bool p_pickable) {
+ GodotArea2D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND(!area);
+ area->set_pickable(p_pickable);
+}
+
+void GodotPhysicsServer2D::area_set_monitorable(RID p_area, bool p_monitorable) {
+ GodotArea2D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND(!area);
+ FLUSH_QUERY_CHECK(area);
+
+ area->set_monitorable(p_monitorable);
+}
+
+void GodotPhysicsServer2D::area_set_collision_mask(RID p_area, uint32_t p_mask) {
+ GodotArea2D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND(!area);
+
+ area->set_collision_mask(p_mask);
+}
+
+void GodotPhysicsServer2D::area_set_collision_layer(RID p_area, uint32_t p_layer) {
+ GodotArea2D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND(!area);
+
+ area->set_collision_layer(p_layer);
+}
+
+void GodotPhysicsServer2D::area_set_monitor_callback(RID p_area, const Callable &p_callback) {
+ GodotArea2D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND(!area);
+
+ area->set_monitor_callback(p_callback.is_valid() ? p_callback : Callable());
+}
+
+void GodotPhysicsServer2D::area_set_area_monitor_callback(RID p_area, const Callable &p_callback) {
+ GodotArea2D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND(!area);
+
+ area->set_area_monitor_callback(p_callback.is_valid() ? p_callback : Callable());
+}
+
+/* BODY API */
+
+RID GodotPhysicsServer2D::body_create() {
+ GodotBody2D *body = memnew(GodotBody2D);
+ RID rid = body_owner.make_rid(body);
+ body->set_self(rid);
+ return rid;
+}
+
+void GodotPhysicsServer2D::body_set_space(RID p_body, RID p_space) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+ GodotSpace2D *space = nullptr;
+ if (p_space.is_valid()) {
+ space = space_owner.get_or_null(p_space);
+ ERR_FAIL_COND(!space);
+ }
+
+ if (body->get_space() == space) {
+ return; //pointless
+ }
+
+ body->clear_constraint_list();
+ body->set_space(space);
+};
+
+RID GodotPhysicsServer2D::body_get_space(RID p_body) const {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, RID());
+
+ GodotSpace2D *space = body->get_space();
+ if (!space) {
+ return RID();
+ }
+ return space->get_self();
+};
+
+void GodotPhysicsServer2D::body_set_mode(RID p_body, BodyMode p_mode) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+ FLUSH_QUERY_CHECK(body);
+
+ body->set_mode(p_mode);
+};
+
+PhysicsServer2D::BodyMode GodotPhysicsServer2D::body_get_mode(RID p_body) const {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, BODY_MODE_STATIC);
+
+ return body->get_mode();
+};
+
+void GodotPhysicsServer2D::body_add_shape(RID p_body, RID p_shape, const Transform2D &p_transform, bool p_disabled) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ GodotShape2D *shape = shape_owner.get_or_null(p_shape);
+ ERR_FAIL_COND(!shape);
+
+ body->add_shape(shape, p_transform, p_disabled);
+}
+
+void GodotPhysicsServer2D::body_set_shape(RID p_body, int p_shape_idx, RID p_shape) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ GodotShape2D *shape = shape_owner.get_or_null(p_shape);
+ ERR_FAIL_COND(!shape);
+ ERR_FAIL_COND(!shape->is_configured());
+
+ body->set_shape(p_shape_idx, shape);
+}
+
+void GodotPhysicsServer2D::body_set_shape_transform(RID p_body, int p_shape_idx, const Transform2D &p_transform) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->set_shape_transform(p_shape_idx, p_transform);
+}
+
+int GodotPhysicsServer2D::body_get_shape_count(RID p_body) const {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, -1);
+
+ return body->get_shape_count();
+}
+
+RID GodotPhysicsServer2D::body_get_shape(RID p_body, int p_shape_idx) const {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, RID());
+
+ GodotShape2D *shape = body->get_shape(p_shape_idx);
+ ERR_FAIL_COND_V(!shape, RID());
+
+ return shape->get_self();
+}
+
+Transform2D GodotPhysicsServer2D::body_get_shape_transform(RID p_body, int p_shape_idx) const {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, Transform2D());
+
+ return body->get_shape_transform(p_shape_idx);
+}
+
+void GodotPhysicsServer2D::body_remove_shape(RID p_body, int p_shape_idx) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->remove_shape(p_shape_idx);
+}
+
+void GodotPhysicsServer2D::body_clear_shapes(RID p_body) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ while (body->get_shape_count()) {
+ body->remove_shape(0);
+ }
+}
+
+void GodotPhysicsServer2D::body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+ ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count());
+ FLUSH_QUERY_CHECK(body);
+
+ body->set_shape_disabled(p_shape_idx, p_disabled);
+}
+
+void GodotPhysicsServer2D::body_set_shape_as_one_way_collision(RID p_body, int p_shape_idx, bool p_enable, real_t p_margin) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+ ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count());
+ FLUSH_QUERY_CHECK(body);
+
+ body->set_shape_as_one_way_collision(p_shape_idx, p_enable, p_margin);
+}
+
+void GodotPhysicsServer2D::body_set_continuous_collision_detection_mode(RID p_body, CCDMode p_mode) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+ body->set_continuous_collision_detection_mode(p_mode);
+}
+
+GodotPhysicsServer2D::CCDMode GodotPhysicsServer2D::body_get_continuous_collision_detection_mode(RID p_body) const {
+ const GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, CCD_MODE_DISABLED);
+
+ return body->get_continuous_collision_detection_mode();
+}
+
+void GodotPhysicsServer2D::body_attach_object_instance_id(RID p_body, ObjectID p_id) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->set_instance_id(p_id);
+}
+
+ObjectID GodotPhysicsServer2D::body_get_object_instance_id(RID p_body) const {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, ObjectID());
+
+ return body->get_instance_id();
+}
+
+void GodotPhysicsServer2D::body_attach_canvas_instance_id(RID p_body, ObjectID p_id) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->set_canvas_instance_id(p_id);
+}
+
+ObjectID GodotPhysicsServer2D::body_get_canvas_instance_id(RID p_body) const {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, ObjectID());
+
+ return body->get_canvas_instance_id();
+}
+
+void GodotPhysicsServer2D::body_set_collision_layer(RID p_body, uint32_t p_layer) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+ body->set_collision_layer(p_layer);
+}
+
+uint32_t GodotPhysicsServer2D::body_get_collision_layer(RID p_body) const {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, 0);
+
+ return body->get_collision_layer();
+}
+
+void GodotPhysicsServer2D::body_set_collision_mask(RID p_body, uint32_t p_mask) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+ body->set_collision_mask(p_mask);
+}
+
+uint32_t GodotPhysicsServer2D::body_get_collision_mask(RID p_body) const {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, 0);
+
+ return body->get_collision_mask();
+}
+
+void GodotPhysicsServer2D::body_set_param(RID p_body, BodyParameter p_param, const Variant &p_value) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->set_param(p_param, p_value);
+}
+
+Variant GodotPhysicsServer2D::body_get_param(RID p_body, BodyParameter p_param) const {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, 0);
+
+ return body->get_param(p_param);
+}
+
+void GodotPhysicsServer2D::body_reset_mass_properties(RID p_body) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ return body->reset_mass_properties();
+}
+
+void GodotPhysicsServer2D::body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->set_state(p_state, p_variant);
+}
+
+Variant GodotPhysicsServer2D::body_get_state(RID p_body, BodyState p_state) const {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, Variant());
+
+ return body->get_state(p_state);
+}
+
+void GodotPhysicsServer2D::body_apply_central_impulse(RID p_body, const Vector2 &p_impulse) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->apply_central_impulse(p_impulse);
+ body->wakeup();
+}
+
+void GodotPhysicsServer2D::body_apply_torque_impulse(RID p_body, real_t p_torque) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ _update_shapes();
+
+ body->apply_torque_impulse(p_torque);
+ body->wakeup();
+}
+
+void GodotPhysicsServer2D::body_apply_impulse(RID p_body, const Vector2 &p_impulse, const Vector2 &p_position) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ _update_shapes();
+
+ body->apply_impulse(p_impulse, p_position);
+ body->wakeup();
+}
+
+void GodotPhysicsServer2D::body_apply_central_force(RID p_body, const Vector2 &p_force) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->apply_central_force(p_force);
+ body->wakeup();
+}
+
+void GodotPhysicsServer2D::body_apply_force(RID p_body, const Vector2 &p_force, const Vector2 &p_position) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->apply_force(p_force, p_position);
+ body->wakeup();
+}
+
+void GodotPhysicsServer2D::body_apply_torque(RID p_body, real_t p_torque) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->apply_torque(p_torque);
+ body->wakeup();
+}
+
+void GodotPhysicsServer2D::body_add_constant_central_force(RID p_body, const Vector2 &p_force) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->add_constant_central_force(p_force);
+ body->wakeup();
+}
+
+void GodotPhysicsServer2D::body_add_constant_force(RID p_body, const Vector2 &p_force, const Vector2 &p_position) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->add_constant_force(p_force, p_position);
+ body->wakeup();
+}
+
+void GodotPhysicsServer2D::body_add_constant_torque(RID p_body, real_t p_torque) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->add_constant_torque(p_torque);
+ body->wakeup();
+}
+
+void GodotPhysicsServer2D::body_set_constant_force(RID p_body, const Vector2 &p_force) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->set_constant_force(p_force);
+ if (!p_force.is_equal_approx(Vector2())) {
+ body->wakeup();
+ }
+}
+
+Vector2 GodotPhysicsServer2D::body_get_constant_force(RID p_body) const {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, Vector2());
+ return body->get_constant_force();
+}
+
+void GodotPhysicsServer2D::body_set_constant_torque(RID p_body, real_t p_torque) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->set_constant_torque(p_torque);
+ if (!Math::is_zero_approx(p_torque)) {
+ body->wakeup();
+ }
+}
+
+real_t GodotPhysicsServer2D::body_get_constant_torque(RID p_body) const {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, 0);
+
+ return body->get_constant_torque();
+}
+
+void GodotPhysicsServer2D::body_set_axis_velocity(RID p_body, const Vector2 &p_axis_velocity) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ _update_shapes();
+
+ Vector2 v = body->get_linear_velocity();
+ Vector2 axis = p_axis_velocity.normalized();
+ v -= axis * axis.dot(v);
+ v += p_axis_velocity;
+ body->set_linear_velocity(v);
+ body->wakeup();
+};
+
+void GodotPhysicsServer2D::body_add_collision_exception(RID p_body, RID p_body_b) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->add_exception(p_body_b);
+ body->wakeup();
+};
+
+void GodotPhysicsServer2D::body_remove_collision_exception(RID p_body, RID p_body_b) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->remove_exception(p_body_b);
+ body->wakeup();
+};
+
+void GodotPhysicsServer2D::body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ for (int i = 0; i < body->get_exceptions().size(); i++) {
+ p_exceptions->push_back(body->get_exceptions()[i]);
+ }
+};
+
+void GodotPhysicsServer2D::body_set_contacts_reported_depth_threshold(RID p_body, real_t p_threshold) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+};
+
+real_t GodotPhysicsServer2D::body_get_contacts_reported_depth_threshold(RID p_body) const {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, 0);
+ return 0;
+};
+
+void GodotPhysicsServer2D::body_set_omit_force_integration(RID p_body, bool p_omit) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->set_omit_force_integration(p_omit);
+};
+
+bool GodotPhysicsServer2D::body_is_omitting_force_integration(RID p_body) const {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, false);
+ return body->get_omit_force_integration();
+};
+
+void GodotPhysicsServer2D::body_set_max_contacts_reported(RID p_body, int p_contacts) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+ body->set_max_contacts_reported(p_contacts);
+}
+
+int GodotPhysicsServer2D::body_get_max_contacts_reported(RID p_body) const {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, -1);
+ return body->get_max_contacts_reported();
+}
+
+void GodotPhysicsServer2D::body_set_state_sync_callback(RID p_body, void *p_instance, BodyStateCallback p_callback) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+ body->set_state_sync_callback(p_instance, p_callback);
+}
+
+void GodotPhysicsServer2D::body_set_force_integration_callback(RID p_body, const Callable &p_callable, const Variant &p_udata) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+ body->set_force_integration_callback(p_callable, p_udata);
+}
+
+bool GodotPhysicsServer2D::body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, false);
+ ERR_FAIL_INDEX_V(p_body_shape, body->get_shape_count(), false);
+
+ return shape_collide(body->get_shape(p_body_shape)->get_self(), body->get_transform() * body->get_shape_transform(p_body_shape), Vector2(), p_shape, p_shape_xform, p_motion, r_results, p_result_max, r_result_count);
+}
+
+void GodotPhysicsServer2D::body_set_pickable(RID p_body, bool p_pickable) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+ body->set_pickable(p_pickable);
+}
+
+bool GodotPhysicsServer2D::body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, false);
+ ERR_FAIL_COND_V(!body->get_space(), false);
+ ERR_FAIL_COND_V(body->get_space()->is_locked(), false);
+
+ _update_shapes();
+
+ return body->get_space()->test_body_motion(body, p_parameters, r_result);
+}
+
+PhysicsDirectBodyState2D *GodotPhysicsServer2D::body_get_direct_state(RID p_body) {
+ ERR_FAIL_COND_V_MSG((using_threads && !doing_sync), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification.");
+
+ if (!body_owner.owns(p_body)) {
+ return nullptr;
+ }
+
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, nullptr);
+
+ if (!body->get_space()) {
+ return nullptr;
+ }
+
+ ERR_FAIL_COND_V_MSG(body->get_space()->is_locked(), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification.");
+
+ return body->get_direct_state();
+}
+
+/* JOINT API */
+
+RID GodotPhysicsServer2D::joint_create() {
+ GodotJoint2D *joint = memnew(GodotJoint2D);
+ RID joint_rid = joint_owner.make_rid(joint);
+ joint->set_self(joint_rid);
+ return joint_rid;
+}
+
+void GodotPhysicsServer2D::joint_clear(RID p_joint) {
+ GodotJoint2D *joint = joint_owner.get_or_null(p_joint);
+ if (joint->get_type() != JOINT_TYPE_MAX) {
+ GodotJoint2D *empty_joint = memnew(GodotJoint2D);
+ empty_joint->copy_settings_from(joint);
+
+ joint_owner.replace(p_joint, empty_joint);
+ memdelete(joint);
+ }
+}
+
+void GodotPhysicsServer2D::joint_set_param(RID p_joint, JointParam p_param, real_t p_value) {
+ GodotJoint2D *joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_COND(!joint);
+
+ switch (p_param) {
+ case JOINT_PARAM_BIAS:
+ joint->set_bias(p_value);
+ break;
+ case JOINT_PARAM_MAX_BIAS:
+ joint->set_max_bias(p_value);
+ break;
+ case JOINT_PARAM_MAX_FORCE:
+ joint->set_max_force(p_value);
+ break;
+ }
+}
+
+real_t GodotPhysicsServer2D::joint_get_param(RID p_joint, JointParam p_param) const {
+ const GodotJoint2D *joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_COND_V(!joint, -1);
+
+ switch (p_param) {
+ case JOINT_PARAM_BIAS:
+ return joint->get_bias();
+ break;
+ case JOINT_PARAM_MAX_BIAS:
+ return joint->get_max_bias();
+ break;
+ case JOINT_PARAM_MAX_FORCE:
+ return joint->get_max_force();
+ break;
+ }
+
+ return 0;
+}
+
+void GodotPhysicsServer2D::joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) {
+ GodotJoint2D *joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_COND(!joint);
+
+ joint->disable_collisions_between_bodies(p_disable);
+
+ if (2 == joint->get_body_count()) {
+ GodotBody2D *body_a = *joint->get_body_ptr();
+ GodotBody2D *body_b = *(joint->get_body_ptr() + 1);
+
+ if (p_disable) {
+ body_add_collision_exception(body_a->get_self(), body_b->get_self());
+ body_add_collision_exception(body_b->get_self(), body_a->get_self());
+ } else {
+ body_remove_collision_exception(body_a->get_self(), body_b->get_self());
+ body_remove_collision_exception(body_b->get_self(), body_a->get_self());
+ }
+ }
+}
+
+bool GodotPhysicsServer2D::joint_is_disabled_collisions_between_bodies(RID p_joint) const {
+ const GodotJoint2D *joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_COND_V(!joint, true);
+
+ return joint->is_disabled_collisions_between_bodies();
+}
+
+void GodotPhysicsServer2D::joint_make_pin(RID p_joint, const Vector2 &p_pos, RID p_body_a, RID p_body_b) {
+ GodotBody2D *A = body_owner.get_or_null(p_body_a);
+ ERR_FAIL_COND(!A);
+ GodotBody2D *B = nullptr;
+ if (body_owner.owns(p_body_b)) {
+ B = body_owner.get_or_null(p_body_b);
+ ERR_FAIL_COND(!B);
+ }
+
+ GodotJoint2D *prev_joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_COND(prev_joint == nullptr);
+
+ GodotJoint2D *joint = memnew(GodotPinJoint2D(p_pos, A, B));
+
+ joint_owner.replace(p_joint, joint);
+ joint->copy_settings_from(prev_joint);
+ memdelete(prev_joint);
+}
+
+void GodotPhysicsServer2D::joint_make_groove(RID p_joint, const Vector2 &p_a_groove1, const Vector2 &p_a_groove2, const Vector2 &p_b_anchor, RID p_body_a, RID p_body_b) {
+ GodotBody2D *A = body_owner.get_or_null(p_body_a);
+ ERR_FAIL_COND(!A);
+
+ GodotBody2D *B = body_owner.get_or_null(p_body_b);
+ ERR_FAIL_COND(!B);
+
+ GodotJoint2D *prev_joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_COND(prev_joint == nullptr);
+
+ GodotJoint2D *joint = memnew(GodotGrooveJoint2D(p_a_groove1, p_a_groove2, p_b_anchor, A, B));
+
+ joint_owner.replace(p_joint, joint);
+ joint->copy_settings_from(prev_joint);
+ memdelete(prev_joint);
+}
+
+void GodotPhysicsServer2D::joint_make_damped_spring(RID p_joint, const Vector2 &p_anchor_a, const Vector2 &p_anchor_b, RID p_body_a, RID p_body_b) {
+ GodotBody2D *A = body_owner.get_or_null(p_body_a);
+ ERR_FAIL_COND(!A);
+
+ GodotBody2D *B = body_owner.get_or_null(p_body_b);
+ ERR_FAIL_COND(!B);
+
+ GodotJoint2D *prev_joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_COND(prev_joint == nullptr);
+
+ GodotJoint2D *joint = memnew(GodotDampedSpringJoint2D(p_anchor_a, p_anchor_b, A, B));
+
+ joint_owner.replace(p_joint, joint);
+ joint->copy_settings_from(prev_joint);
+ memdelete(prev_joint);
+}
+
+void GodotPhysicsServer2D::pin_joint_set_param(RID p_joint, PinJointParam p_param, real_t p_value) {
+ GodotJoint2D *j = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_COND(!j);
+ ERR_FAIL_COND(j->get_type() != JOINT_TYPE_PIN);
+
+ GodotPinJoint2D *pin_joint = static_cast<GodotPinJoint2D *>(j);
+ pin_joint->set_param(p_param, p_value);
+}
+
+real_t GodotPhysicsServer2D::pin_joint_get_param(RID p_joint, PinJointParam p_param) const {
+ GodotJoint2D *j = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_COND_V(!j, 0);
+ ERR_FAIL_COND_V(j->get_type() != JOINT_TYPE_PIN, 0);
+
+ GodotPinJoint2D *pin_joint = static_cast<GodotPinJoint2D *>(j);
+ return pin_joint->get_param(p_param);
+}
+
+void GodotPhysicsServer2D::damped_spring_joint_set_param(RID p_joint, DampedSpringParam p_param, real_t p_value) {
+ GodotJoint2D *j = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_COND(!j);
+ ERR_FAIL_COND(j->get_type() != JOINT_TYPE_DAMPED_SPRING);
+
+ GodotDampedSpringJoint2D *dsj = static_cast<GodotDampedSpringJoint2D *>(j);
+ dsj->set_param(p_param, p_value);
+}
+
+real_t GodotPhysicsServer2D::damped_spring_joint_get_param(RID p_joint, DampedSpringParam p_param) const {
+ GodotJoint2D *j = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_COND_V(!j, 0);
+ ERR_FAIL_COND_V(j->get_type() != JOINT_TYPE_DAMPED_SPRING, 0);
+
+ GodotDampedSpringJoint2D *dsj = static_cast<GodotDampedSpringJoint2D *>(j);
+ return dsj->get_param(p_param);
+}
+
+PhysicsServer2D::JointType GodotPhysicsServer2D::joint_get_type(RID p_joint) const {
+ GodotJoint2D *joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_COND_V(!joint, JOINT_TYPE_PIN);
+
+ return joint->get_type();
+}
+
+void GodotPhysicsServer2D::free(RID p_rid) {
+ _update_shapes(); // just in case
+
+ if (shape_owner.owns(p_rid)) {
+ GodotShape2D *shape = shape_owner.get_or_null(p_rid);
+
+ while (shape->get_owners().size()) {
+ GodotShapeOwner2D *so = shape->get_owners().front()->key();
+ so->remove_shape(shape);
+ }
+
+ shape_owner.free(p_rid);
+ memdelete(shape);
+ } else if (body_owner.owns(p_rid)) {
+ GodotBody2D *body = body_owner.get_or_null(p_rid);
+
+ /*
+ if (body->get_state_query())
+ _clear_query(body->get_state_query());
+
+ if (body->get_direct_state_query())
+ _clear_query(body->get_direct_state_query());
+ */
+
+ body_set_space(p_rid, RID());
+
+ while (body->get_shape_count()) {
+ body->remove_shape(0);
+ }
+
+ body_owner.free(p_rid);
+ memdelete(body);
+
+ } else if (area_owner.owns(p_rid)) {
+ GodotArea2D *area = area_owner.get_or_null(p_rid);
+
+ /*
+ if (area->get_monitor_query())
+ _clear_query(area->get_monitor_query());
+ */
+
+ area->set_space(nullptr);
+
+ while (area->get_shape_count()) {
+ area->remove_shape(0);
+ }
+
+ area_owner.free(p_rid);
+ memdelete(area);
+ } else if (space_owner.owns(p_rid)) {
+ GodotSpace2D *space = space_owner.get_or_null(p_rid);
+
+ while (space->get_objects().size()) {
+ GodotCollisionObject2D *co = (GodotCollisionObject2D *)space->get_objects().front()->get();
+ co->set_space(nullptr);
+ }
+
+ active_spaces.erase(space);
+ free(space->get_default_area()->get_self());
+ space_owner.free(p_rid);
+ memdelete(space);
+ } else if (joint_owner.owns(p_rid)) {
+ GodotJoint2D *joint = joint_owner.get_or_null(p_rid);
+
+ joint_owner.free(p_rid);
+ memdelete(joint);
+
+ } else {
+ ERR_FAIL_MSG("Invalid ID.");
+ }
+}
+
+void GodotPhysicsServer2D::set_active(bool p_active) {
+ active = p_active;
+}
+
+void GodotPhysicsServer2D::init() {
+ doing_sync = false;
+ stepper = memnew(GodotStep2D);
+}
+
+void GodotPhysicsServer2D::step(real_t p_step) {
+ if (!active) {
+ return;
+ }
+
+ _update_shapes();
+
+ island_count = 0;
+ active_objects = 0;
+ collision_pairs = 0;
+ for (Set<const GodotSpace2D *>::Element *E = active_spaces.front(); E; E = E->next()) {
+ stepper->step((GodotSpace2D *)E->get(), p_step);
+ island_count += E->get()->get_island_count();
+ active_objects += E->get()->get_active_objects();
+ collision_pairs += E->get()->get_collision_pairs();
+ }
+}
+
+void GodotPhysicsServer2D::sync() {
+ doing_sync = true;
+}
+
+void GodotPhysicsServer2D::flush_queries() {
+ if (!active) {
+ return;
+ }
+
+ flushing_queries = true;
+
+ uint64_t time_beg = OS::get_singleton()->get_ticks_usec();
+
+ for (Set<const GodotSpace2D *>::Element *E = active_spaces.front(); E; E = E->next()) {
+ GodotSpace2D *space = (GodotSpace2D *)E->get();
+ space->call_queries();
+ }
+
+ flushing_queries = false;
+
+ if (EngineDebugger::is_profiling("servers")) {
+ uint64_t total_time[GodotSpace2D::ELAPSED_TIME_MAX];
+ static const char *time_name[GodotSpace2D::ELAPSED_TIME_MAX] = {
+ "integrate_forces",
+ "generate_islands",
+ "setup_constraints",
+ "solve_constraints",
+ "integrate_velocities"
+ };
+
+ for (int i = 0; i < GodotSpace2D::ELAPSED_TIME_MAX; i++) {
+ total_time[i] = 0;
+ }
+
+ for (Set<const GodotSpace2D *>::Element *E = active_spaces.front(); E; E = E->next()) {
+ for (int i = 0; i < GodotSpace2D::ELAPSED_TIME_MAX; i++) {
+ total_time[i] += E->get()->get_elapsed_time(GodotSpace2D::ElapsedTime(i));
+ }
+ }
+
+ Array values;
+ values.resize(GodotSpace2D::ELAPSED_TIME_MAX * 2);
+ for (int i = 0; i < GodotSpace2D::ELAPSED_TIME_MAX; i++) {
+ values[i * 2 + 0] = time_name[i];
+ values[i * 2 + 1] = USEC_TO_SEC(total_time[i]);
+ }
+ values.push_back("flush_queries");
+ values.push_back(USEC_TO_SEC(OS::get_singleton()->get_ticks_usec() - time_beg));
+
+ values.push_front("physics_2d");
+ EngineDebugger::profiler_add_frame_data("servers", values);
+ }
+}
+
+void GodotPhysicsServer2D::end_sync() {
+ doing_sync = false;
+}
+
+void GodotPhysicsServer2D::finish() {
+ memdelete(stepper);
+}
+
+void GodotPhysicsServer2D::_update_shapes() {
+ while (pending_shape_update_list.first()) {
+ pending_shape_update_list.first()->self()->_shape_changed();
+ pending_shape_update_list.remove(pending_shape_update_list.first());
+ }
+}
+
+int GodotPhysicsServer2D::get_process_info(ProcessInfo p_info) {
+ switch (p_info) {
+ case INFO_ACTIVE_OBJECTS: {
+ return active_objects;
+ } break;
+ case INFO_COLLISION_PAIRS: {
+ return collision_pairs;
+ } break;
+ case INFO_ISLAND_COUNT: {
+ return island_count;
+ } break;
+ }
+
+ return 0;
+}
+
+GodotPhysicsServer2D *GodotPhysicsServer2D::godot_singleton = nullptr;
+
+GodotPhysicsServer2D::GodotPhysicsServer2D(bool p_using_threads) {
+ godot_singleton = this;
+ GodotBroadPhase2D::create_func = GodotBroadPhase2DBVH::_create;
+
+ using_threads = p_using_threads;
+}
diff --git a/servers/physics_2d/physics_server_2d_sw.h b/servers/physics_2d/godot_physics_server_2d.h
index b8e375a087..0a84caadc5 100644
--- a/servers/physics_2d/physics_server_2d_sw.h
+++ b/servers/physics_2d/godot_physics_server_2d.h
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* physics_server_2d_sw.h */
+/* godot_physics_server_2d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,23 +28,23 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef PHYSICS_2D_SERVER_SW
-#define PHYSICS_2D_SERVER_SW
+#ifndef GODOT_PHYSICS_SERVER_2D_H
+#define GODOT_PHYSICS_SERVER_2D_H
+
+#include "godot_joints_2d.h"
+#include "godot_shape_2d.h"
+#include "godot_space_2d.h"
+#include "godot_step_2d.h"
#include "core/templates/rid_owner.h"
-#include "joints_2d_sw.h"
#include "servers/physics_server_2d.h"
-#include "shape_2d_sw.h"
-#include "space_2d_sw.h"
-#include "step_2d_sw.h"
-class PhysicsServer2DSW : public PhysicsServer2D {
- GDCLASS(PhysicsServer2DSW, PhysicsServer2D);
+class GodotPhysicsServer2D : public PhysicsServer2D {
+ GDCLASS(GodotPhysicsServer2D, PhysicsServer2D);
- friend class PhysicsDirectSpaceState2DSW;
- friend class PhysicsDirectBodyState2DSW;
+ friend class GodotPhysicsDirectSpaceState2D;
+ friend class GodotPhysicsDirectBodyState2D;
bool active = true;
- int iterations = 0;
bool doing_sync = false;
int island_count = 0;
@@ -55,20 +55,19 @@ class PhysicsServer2DSW : public PhysicsServer2D {
bool flushing_queries = false;
- Step2DSW *stepper = nullptr;
- Set<const Space2DSW *> active_spaces;
+ GodotStep2D *stepper = nullptr;
+ Set<const GodotSpace2D *> active_spaces;
- mutable RID_PtrOwner<Shape2DSW, true> shape_owner;
- mutable RID_PtrOwner<Space2DSW, true> space_owner;
- mutable RID_PtrOwner<Area2DSW, true> area_owner;
- mutable RID_PtrOwner<Body2DSW, true> body_owner;
- mutable RID_PtrOwner<Joint2DSW, true> joint_owner;
+ mutable RID_PtrOwner<GodotShape2D, true> shape_owner;
+ mutable RID_PtrOwner<GodotSpace2D, true> space_owner;
+ mutable RID_PtrOwner<GodotArea2D, true> area_owner;
+ mutable RID_PtrOwner<GodotBody2D, true> body_owner;
+ mutable RID_PtrOwner<GodotJoint2D, true> joint_owner;
- static PhysicsServer2DSW *singletonsw;
+ static GodotPhysicsServer2D *godot_singleton;
- //void _clear_query(Query2DSW *p_query);
- friend class CollisionObject2DSW;
- SelfList<CollisionObject2DSW>::List pending_shape_update_list;
+ friend class GodotCollisionObject2D;
+ SelfList<GodotCollisionObject2D>::List pending_shape_update_list;
void _update_shapes();
RID _shape_create(ShapeType p_shape);
@@ -124,9 +123,6 @@ public:
virtual RID area_create() override;
- virtual void area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) override;
- virtual AreaSpaceOverrideMode area_get_space_override_mode(RID p_area) const override;
-
virtual void area_set_space(RID p_area, RID p_space) override;
virtual RID area_get_space(RID p_area) const override;
@@ -158,8 +154,8 @@ public:
virtual void area_set_collision_mask(RID p_area, uint32_t p_mask) override;
virtual void area_set_collision_layer(RID p_area, uint32_t p_layer) override;
- virtual void area_set_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) override;
- virtual void area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) override;
+ virtual void area_set_monitor_callback(RID p_area, const Callable &p_callback) override;
+ virtual void area_set_area_monitor_callback(RID p_area, const Callable &p_callback) override;
virtual void area_set_pickable(RID p_area, bool p_pickable) override;
@@ -211,19 +207,24 @@ public:
virtual void body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) override;
virtual Variant body_get_state(RID p_body, BodyState p_state) const override;
- virtual void body_set_applied_force(RID p_body, const Vector2 &p_force) override;
- virtual Vector2 body_get_applied_force(RID p_body) const override;
-
- virtual void body_set_applied_torque(RID p_body, real_t p_torque) override;
- virtual real_t body_get_applied_torque(RID p_body) const override;
-
- virtual void body_add_central_force(RID p_body, const Vector2 &p_force) override;
- virtual void body_add_force(RID p_body, const Vector2 &p_force, const Vector2 &p_position = Vector2()) override;
- virtual void body_add_torque(RID p_body, real_t p_torque) override;
-
virtual void body_apply_central_impulse(RID p_body, const Vector2 &p_impulse) override;
virtual void body_apply_torque_impulse(RID p_body, real_t p_torque) override;
virtual void body_apply_impulse(RID p_body, const Vector2 &p_impulse, const Vector2 &p_position = Vector2()) override;
+
+ virtual void body_apply_central_force(RID p_body, const Vector2 &p_force) override;
+ virtual void body_apply_force(RID p_body, const Vector2 &p_force, const Vector2 &p_position = Vector2()) override;
+ virtual void body_apply_torque(RID p_body, real_t p_torque) override;
+
+ virtual void body_add_constant_central_force(RID p_body, const Vector2 &p_force) override;
+ virtual void body_add_constant_force(RID p_body, const Vector2 &p_force, const Vector2 &p_position = Vector2()) override;
+ virtual void body_add_constant_torque(RID p_body, real_t p_torque) override;
+
+ virtual void body_set_constant_force(RID p_body, const Vector2 &p_force) override;
+ virtual Vector2 body_get_constant_force(RID p_body) const override;
+
+ virtual void body_set_constant_torque(RID p_body, real_t p_torque) override;
+ virtual real_t body_get_constant_torque(RID p_body) const override;
+
virtual void body_set_axis_velocity(RID p_body, const Vector2 &p_axis_velocity) override;
virtual void body_add_collision_exception(RID p_body, RID p_body_b) override;
@@ -286,14 +287,12 @@ public:
virtual void end_sync() override;
virtual void finish() override;
- virtual void set_collision_iterations(int p_iterations) override;
-
virtual bool is_flushing_queries() const override { return flushing_queries; }
int get_process_info(ProcessInfo p_info) override;
- PhysicsServer2DSW(bool p_using_threads = false);
- ~PhysicsServer2DSW() {}
+ GodotPhysicsServer2D(bool p_using_threads = false);
+ ~GodotPhysicsServer2D() {}
};
-#endif
+#endif // GODOT_PHYSICS_SERVER_2D_H
diff --git a/servers/physics_2d/shape_2d_sw.cpp b/servers/physics_2d/godot_shape_2d.cpp
index bde882ac24..1e8799a727 100644
--- a/servers/physics_2d/shape_2d_sw.cpp
+++ b/servers/physics_2d/godot_shape_2d.cpp
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* shape_2d_sw.cpp */
+/* godot_shape_2d.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,29 +28,29 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "shape_2d_sw.h"
+#include "godot_shape_2d.h"
#include "core/math/geometry_2d.h"
#include "core/templates/sort_array.h"
-void Shape2DSW::configure(const Rect2 &p_aabb) {
+void GodotShape2D::configure(const Rect2 &p_aabb) {
aabb = p_aabb;
configured = true;
- for (const KeyValue<ShapeOwner2DSW *, int> &E : owners) {
- ShapeOwner2DSW *co = (ShapeOwner2DSW *)E.key;
+ for (const KeyValue<GodotShapeOwner2D *, int> &E : owners) {
+ GodotShapeOwner2D *co = (GodotShapeOwner2D *)E.key;
co->_shape_changed();
}
}
-Vector2 Shape2DSW::get_support(const Vector2 &p_normal) const {
+Vector2 GodotShape2D::get_support(const Vector2 &p_normal) const {
Vector2 res[2];
int amnt;
get_supports(p_normal, res, amnt);
return res[0];
}
-void Shape2DSW::add_owner(ShapeOwner2DSW *p_owner) {
- Map<ShapeOwner2DSW *, int>::Element *E = owners.find(p_owner);
+void GodotShape2D::add_owner(GodotShapeOwner2D *p_owner) {
+ Map<GodotShapeOwner2D *, int>::Element *E = owners.find(p_owner);
if (E) {
E->get()++;
} else {
@@ -58,8 +58,8 @@ void Shape2DSW::add_owner(ShapeOwner2DSW *p_owner) {
}
}
-void Shape2DSW::remove_owner(ShapeOwner2DSW *p_owner) {
- Map<ShapeOwner2DSW *, int>::Element *E = owners.find(p_owner);
+void GodotShape2D::remove_owner(GodotShapeOwner2D *p_owner) {
+ Map<GodotShapeOwner2D *, int>::Element *E = owners.find(p_owner);
ERR_FAIL_COND(!E);
E->get()--;
if (E->get() == 0) {
@@ -67,15 +67,15 @@ void Shape2DSW::remove_owner(ShapeOwner2DSW *p_owner) {
}
}
-bool Shape2DSW::is_owner(ShapeOwner2DSW *p_owner) const {
+bool GodotShape2D::is_owner(GodotShapeOwner2D *p_owner) const {
return owners.has(p_owner);
}
-const Map<ShapeOwner2DSW *, int> &Shape2DSW::get_owners() const {
+const Map<GodotShapeOwner2D *, int> &GodotShape2D::get_owners() const {
return owners;
}
-Shape2DSW::~Shape2DSW() {
+GodotShape2D::~GodotShape2D() {
ERR_FAIL_COND(owners.size());
}
@@ -83,15 +83,15 @@ Shape2DSW::~Shape2DSW() {
/*********************************************************/
/*********************************************************/
-void WorldBoundaryShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const {
+void GodotWorldBoundaryShape2D::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const {
r_amount = 0;
}
-bool WorldBoundaryShape2DSW::contains_point(const Vector2 &p_point) const {
+bool GodotWorldBoundaryShape2D::contains_point(const Vector2 &p_point) const {
return normal.dot(p_point) < d;
}
-bool WorldBoundaryShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const {
+bool GodotWorldBoundaryShape2D::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const {
Vector2 segment = p_begin - p_end;
real_t den = normal.dot(segment);
@@ -113,11 +113,11 @@ bool WorldBoundaryShape2DSW::intersect_segment(const Vector2 &p_begin, const Vec
return true;
}
-real_t WorldBoundaryShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const {
+real_t GodotWorldBoundaryShape2D::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const {
return 0;
}
-void WorldBoundaryShape2DSW::set_data(const Variant &p_data) {
+void GodotWorldBoundaryShape2D::set_data(const Variant &p_data) {
ERR_FAIL_COND(p_data.get_type() != Variant::ARRAY);
Array arr = p_data;
ERR_FAIL_COND(arr.size() != 2);
@@ -126,7 +126,7 @@ void WorldBoundaryShape2DSW::set_data(const Variant &p_data) {
configure(Rect2(Vector2(-1e4, -1e4), Vector2(1e4 * 2, 1e4 * 2)));
}
-Variant WorldBoundaryShape2DSW::get_data() const {
+Variant GodotWorldBoundaryShape2D::get_data() const {
Array arr;
arr.resize(2);
arr[0] = normal;
@@ -138,7 +138,7 @@ Variant WorldBoundaryShape2DSW::get_data() const {
/*********************************************************/
/*********************************************************/
-void SeparationRayShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const {
+void GodotSeparationRayShape2D::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const {
r_amount = 1;
if (p_normal.y > 0) {
@@ -148,26 +148,26 @@ void SeparationRayShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_su
}
}
-bool SeparationRayShape2DSW::contains_point(const Vector2 &p_point) const {
+bool GodotSeparationRayShape2D::contains_point(const Vector2 &p_point) const {
return false;
}
-bool SeparationRayShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const {
+bool GodotSeparationRayShape2D::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const {
return false; //rays can't be intersected
}
-real_t SeparationRayShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const {
+real_t GodotSeparationRayShape2D::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const {
return 0; //rays are mass-less
}
-void SeparationRayShape2DSW::set_data(const Variant &p_data) {
+void GodotSeparationRayShape2D::set_data(const Variant &p_data) {
Dictionary d = p_data;
length = d["length"];
slide_on_slope = d["slide_on_slope"];
configure(Rect2(0, 0, 0.001, length));
}
-Variant SeparationRayShape2DSW::get_data() const {
+Variant GodotSeparationRayShape2D::get_data() const {
Dictionary d;
d["length"] = length;
d["slide_on_slope"] = slide_on_slope;
@@ -178,7 +178,7 @@ Variant SeparationRayShape2DSW::get_data() const {
/*********************************************************/
/*********************************************************/
-void SegmentShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const {
+void GodotSegmentShape2D::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const {
if (Math::abs(p_normal.dot(n)) > _SEGMENT_IS_VALID_SUPPORT_THRESHOLD) {
r_supports[0] = a;
r_supports[1] = b;
@@ -195,11 +195,11 @@ void SegmentShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_supports
r_amount = 1;
}
-bool SegmentShape2DSW::contains_point(const Vector2 &p_point) const {
+bool GodotSegmentShape2D::contains_point(const Vector2 &p_point) const {
return false;
}
-bool SegmentShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const {
+bool GodotSegmentShape2D::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const {
if (!Geometry2D::segment_intersects_segment(p_begin, p_end, a, b, &r_point)) {
return false;
}
@@ -213,11 +213,11 @@ bool SegmentShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &
return true;
}
-real_t SegmentShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const {
+real_t GodotSegmentShape2D::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const {
return p_mass * ((a * p_scale).distance_squared_to(b * p_scale)) / 12;
}
-void SegmentShape2DSW::set_data(const Variant &p_data) {
+void GodotSegmentShape2D::set_data(const Variant &p_data) {
ERR_FAIL_COND(p_data.get_type() != Variant::RECT2);
Rect2 r = p_data;
@@ -237,7 +237,7 @@ void SegmentShape2DSW::set_data(const Variant &p_data) {
configure(aabb);
}
-Variant SegmentShape2DSW::get_data() const {
+Variant GodotSegmentShape2D::get_data() const {
Rect2 r;
r.position = a;
r.size = b;
@@ -248,16 +248,16 @@ Variant SegmentShape2DSW::get_data() const {
/*********************************************************/
/*********************************************************/
-void CircleShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const {
+void GodotCircleShape2D::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const {
r_amount = 1;
*r_supports = p_normal * radius;
}
-bool CircleShape2DSW::contains_point(const Vector2 &p_point) const {
+bool GodotCircleShape2D::contains_point(const Vector2 &p_point) const {
return p_point.length_squared() < radius * radius;
}
-bool CircleShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const {
+bool GodotCircleShape2D::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const {
Vector2 line_vec = p_end - p_begin;
real_t a, b, c;
@@ -283,19 +283,19 @@ bool CircleShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &p
return true;
}
-real_t CircleShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const {
+real_t GodotCircleShape2D::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const {
real_t a = radius * p_scale.x;
real_t b = radius * p_scale.y;
return p_mass * (a * a + b * b) / 4;
}
-void CircleShape2DSW::set_data(const Variant &p_data) {
+void GodotCircleShape2D::set_data(const Variant &p_data) {
ERR_FAIL_COND(!p_data.is_num());
radius = p_data;
configure(Rect2(-radius, -radius, radius * 2, radius * 2));
}
-Variant CircleShape2DSW::get_data() const {
+Variant GodotCircleShape2D::get_data() const {
return radius;
}
@@ -303,7 +303,7 @@ Variant CircleShape2DSW::get_data() const {
/*********************************************************/
/*********************************************************/
-void RectangleShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const {
+void GodotRectangleShape2D::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const {
for (int i = 0; i < 2; i++) {
Vector2 ag;
ag[i] = 1.0;
@@ -333,7 +333,7 @@ void RectangleShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_suppor
(p_normal.y < 0) ? -half_extents.y : half_extents.y);
}
-bool RectangleShape2DSW::contains_point(const Vector2 &p_point) const {
+bool GodotRectangleShape2D::contains_point(const Vector2 &p_point) const {
real_t x = p_point.x;
real_t y = p_point.y;
real_t edge_x = half_extents.x;
@@ -341,23 +341,23 @@ bool RectangleShape2DSW::contains_point(const Vector2 &p_point) const {
return (x >= -edge_x) && (x < edge_x) && (y >= -edge_y) && (y < edge_y);
}
-bool RectangleShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const {
+bool GodotRectangleShape2D::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const {
return get_aabb().intersects_segment(p_begin, p_end, &r_point, &r_normal);
}
-real_t RectangleShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const {
+real_t GodotRectangleShape2D::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const {
Vector2 he2 = half_extents * 2 * p_scale;
return p_mass * he2.dot(he2) / 12.0;
}
-void RectangleShape2DSW::set_data(const Variant &p_data) {
+void GodotRectangleShape2D::set_data(const Variant &p_data) {
ERR_FAIL_COND(p_data.get_type() != Variant::VECTOR2);
half_extents = p_data;
configure(Rect2(-half_extents, half_extents * 2.0));
}
-Variant RectangleShape2DSW::get_data() const {
+Variant GodotRectangleShape2D::get_data() const {
return half_extents;
}
@@ -365,7 +365,7 @@ Variant RectangleShape2DSW::get_data() const {
/*********************************************************/
/*********************************************************/
-void CapsuleShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const {
+void GodotCapsuleShape2D::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const {
Vector2 n = p_normal;
real_t d = n.y;
@@ -392,7 +392,7 @@ void CapsuleShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_supports
}
}
-bool CapsuleShape2DSW::contains_point(const Vector2 &p_point) const {
+bool GodotCapsuleShape2D::contains_point(const Vector2 &p_point) const {
Vector2 p = p_point;
p.y = Math::abs(p.y);
p.y -= height * 0.5 - radius;
@@ -403,7 +403,7 @@ bool CapsuleShape2DSW::contains_point(const Vector2 &p_point) const {
return p.length_squared() < radius * radius;
}
-bool CapsuleShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const {
+bool GodotCapsuleShape2D::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const {
real_t d = 1e10;
Vector2 n = (p_end - p_begin).normalized();
bool collided = false;
@@ -463,12 +463,12 @@ bool CapsuleShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &
return collided; //todo
}
-real_t CapsuleShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const {
+real_t GodotCapsuleShape2D::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const {
Vector2 he2 = Vector2(radius * 2, height) * p_scale;
return p_mass * he2.dot(he2) / 12.0;
}
-void CapsuleShape2DSW::set_data(const Variant &p_data) {
+void GodotCapsuleShape2D::set_data(const Variant &p_data) {
ERR_FAIL_COND(p_data.get_type() != Variant::ARRAY && p_data.get_type() != Variant::VECTOR2);
if (p_data.get_type() == Variant::ARRAY) {
@@ -486,7 +486,7 @@ void CapsuleShape2DSW::set_data(const Variant &p_data) {
configure(Rect2(-he, he * 2));
}
-Variant CapsuleShape2DSW::get_data() const {
+Variant GodotCapsuleShape2D::get_data() const {
return Point2(height, radius);
}
@@ -494,7 +494,7 @@ Variant CapsuleShape2DSW::get_data() const {
/*********************************************************/
/*********************************************************/
-void ConvexPolygonShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const {
+void GodotConvexPolygonShape2D::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const {
int support_idx = -1;
real_t d = -1e10;
r_amount = 0;
@@ -522,7 +522,7 @@ void ConvexPolygonShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_su
r_supports[0] = points[support_idx].pos;
}
-bool ConvexPolygonShape2DSW::contains_point(const Vector2 &p_point) const {
+bool GodotConvexPolygonShape2D::contains_point(const Vector2 &p_point) const {
bool out = false;
bool in = false;
@@ -538,7 +538,7 @@ bool ConvexPolygonShape2DSW::contains_point(const Vector2 &p_point) const {
return in != out;
}
-bool ConvexPolygonShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const {
+bool GodotConvexPolygonShape2D::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const {
Vector2 n = (p_end - p_begin).normalized();
real_t d = 1e10;
bool inters = false;
@@ -568,7 +568,7 @@ bool ConvexPolygonShape2DSW::intersect_segment(const Vector2 &p_begin, const Vec
return inters;
}
-real_t ConvexPolygonShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const {
+real_t GodotConvexPolygonShape2D::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const {
ERR_FAIL_COND_V_MSG(point_count == 0, 0, "Convex polygon shape has no points.");
Rect2 aabb;
aabb.position = points[0].pos * p_scale;
@@ -579,7 +579,7 @@ real_t ConvexPolygonShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2
return p_mass * aabb.size.dot(aabb.size) / 12.0;
}
-void ConvexPolygonShape2DSW::set_data(const Variant &p_data) {
+void GodotConvexPolygonShape2D::set_data(const Variant &p_data) {
#ifdef REAL_T_IS_DOUBLE
ERR_FAIL_COND(p_data.get_type() != Variant::PACKED_VECTOR2_ARRAY && p_data.get_type() != Variant::PACKED_FLOAT64_ARRAY);
#else
@@ -635,7 +635,7 @@ void ConvexPolygonShape2DSW::set_data(const Variant &p_data) {
configure(aabb);
}
-Variant ConvexPolygonShape2DSW::get_data() const {
+Variant GodotConvexPolygonShape2D::get_data() const {
Vector<Vector2> dvr;
dvr.resize(point_count);
@@ -647,7 +647,7 @@ Variant ConvexPolygonShape2DSW::get_data() const {
return dvr;
}
-ConvexPolygonShape2DSW::~ConvexPolygonShape2DSW() {
+GodotConvexPolygonShape2D::~GodotConvexPolygonShape2D() {
if (points) {
memdelete_arr(points);
}
@@ -655,7 +655,7 @@ ConvexPolygonShape2DSW::~ConvexPolygonShape2DSW() {
//////////////////////////////////////////////////
-void ConcavePolygonShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const {
+void GodotConcavePolygonShape2D::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const {
real_t d = -1e10;
int idx = -1;
for (int i = 0; i < points.size(); i++) {
@@ -671,11 +671,11 @@ void ConcavePolygonShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_s
*r_supports = points[idx];
}
-bool ConcavePolygonShape2DSW::contains_point(const Vector2 &p_point) const {
+bool GodotConcavePolygonShape2D::contains_point(const Vector2 &p_point) const {
return false; //sorry
}
-bool ConcavePolygonShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const {
+bool GodotConcavePolygonShape2D::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const {
if (segments.size() == 0 || points.size() == 0) {
return false;
}
@@ -783,7 +783,7 @@ bool ConcavePolygonShape2DSW::intersect_segment(const Vector2 &p_begin, const Ve
return inters;
}
-int ConcavePolygonShape2DSW::_generate_bvh(BVH *p_bvh, int p_len, int p_depth) {
+int GodotConcavePolygonShape2D::_generate_bvh(BVH *p_bvh, int p_len, int p_depth) {
if (p_len == 1) {
bvh_depth = MAX(p_depth, bvh_depth);
bvh.push_back(*p_bvh);
@@ -821,7 +821,7 @@ int ConcavePolygonShape2DSW::_generate_bvh(BVH *p_bvh, int p_len, int p_depth) {
return node_idx;
}
-void ConcavePolygonShape2DSW::set_data(const Variant &p_data) {
+void GodotConcavePolygonShape2D::set_data(const Variant &p_data) {
#ifdef REAL_T_IS_DOUBLE
ERR_FAIL_COND(p_data.get_type() != Variant::PACKED_VECTOR2_ARRAY && p_data.get_type() != Variant::PACKED_FLOAT64_ARRAY);
#else
@@ -898,7 +898,7 @@ void ConcavePolygonShape2DSW::set_data(const Variant &p_data) {
configure(aabb);
}
-Variant ConcavePolygonShape2DSW::get_data() const {
+Variant GodotConcavePolygonShape2D::get_data() const {
Vector<Vector2> rsegments;
int len = segments.size();
rsegments.resize(len * 2);
@@ -911,7 +911,7 @@ Variant ConcavePolygonShape2DSW::get_data() const {
return rsegments;
}
-void ConcavePolygonShape2DSW::cull(const Rect2 &p_local_aabb, QueryCallback p_callback, void *p_userdata) const {
+void GodotConcavePolygonShape2D::cull(const Rect2 &p_local_aabb, QueryCallback p_callback, void *p_userdata) const {
uint32_t *stack = (uint32_t *)alloca(sizeof(int) * bvh_depth);
enum {
@@ -957,7 +957,7 @@ void ConcavePolygonShape2DSW::cull(const Rect2 &p_local_aabb, QueryCallback p_ca
Vector2 a = pointptr[s.points[0]];
Vector2 b = pointptr[s.points[1]];
- SegmentShape2DSW ss(a, b, (b - a).orthogonal().normalized());
+ GodotSegmentShape2D ss(a, b, (b - a).orthogonal().normalized());
if (p_callback(p_userdata, &ss)) {
return;
diff --git a/servers/physics_2d/shape_2d_sw.h b/servers/physics_2d/godot_shape_2d.h
index c118826284..fb52cbce20 100644
--- a/servers/physics_2d/shape_2d_sw.h
+++ b/servers/physics_2d/godot_shape_2d.h
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* shape_2d_sw.h */
+/* godot_shape_2d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,29 +28,29 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SHAPE_2D_2DSW_H
-#define SHAPE_2D_2DSW_H
+#ifndef GODOT_SHAPE_2D_H
+#define GODOT_SHAPE_2D_H
#include "servers/physics_server_2d.h"
#define _SEGMENT_IS_VALID_SUPPORT_THRESHOLD 0.99998
-class Shape2DSW;
+class GodotShape2D;
-class ShapeOwner2DSW {
+class GodotShapeOwner2D {
public:
virtual void _shape_changed() = 0;
- virtual void remove_shape(Shape2DSW *p_shape) = 0;
+ virtual void remove_shape(GodotShape2D *p_shape) = 0;
- virtual ~ShapeOwner2DSW() {}
+ virtual ~GodotShapeOwner2D() {}
};
-class Shape2DSW {
+class GodotShape2D {
RID self;
Rect2 aabb;
bool configured = false;
real_t custom_bias = 0.0;
- Map<ShapeOwner2DSW *, int> owners;
+ Map<GodotShapeOwner2D *, int> owners;
protected:
void configure(const Rect2 &p_aabb);
@@ -83,10 +83,10 @@ public:
_FORCE_INLINE_ void set_custom_bias(real_t p_bias) { custom_bias = p_bias; }
_FORCE_INLINE_ real_t get_custom_bias() const { return custom_bias; }
- void add_owner(ShapeOwner2DSW *p_owner);
- void remove_owner(ShapeOwner2DSW *p_owner);
- bool is_owner(ShapeOwner2DSW *p_owner) const;
- const Map<ShapeOwner2DSW *, int> &get_owners() const;
+ void add_owner(GodotShapeOwner2D *p_owner);
+ void remove_owner(GodotShapeOwner2D *p_owner);
+ bool is_owner(GodotShapeOwner2D *p_owner) const;
+ const Map<GodotShapeOwner2D *, int> &get_owners() const;
_FORCE_INLINE_ void get_supports_transformed_cast(const Vector2 &p_cast, const Vector2 &p_normal, const Transform2D &p_xform, Vector2 *r_supports, int &r_amount) const {
get_supports(p_xform.basis_xform_inv(p_normal).normalized(), r_supports, r_amount);
@@ -121,8 +121,8 @@ public:
}
}
}
- Shape2DSW() {}
- virtual ~Shape2DSW();
+ GodotShape2D() {}
+ virtual ~GodotShape2D();
};
//let the optimizer do the magic
@@ -141,7 +141,7 @@ public:
r_max = MAX(maxa, maxb); \
}
-class WorldBoundaryShape2DSW : public Shape2DSW {
+class GodotWorldBoundaryShape2D : public GodotShape2D {
Vector2 normal;
real_t d = 0.0;
@@ -178,7 +178,7 @@ public:
}
};
-class SeparationRayShape2DSW : public Shape2DSW {
+class GodotSeparationRayShape2D : public GodotShape2D {
real_t length = 0.0;
bool slide_on_slope = false;
@@ -211,11 +211,11 @@ public:
DEFAULT_PROJECT_RANGE_CAST
- _FORCE_INLINE_ SeparationRayShape2DSW() {}
- _FORCE_INLINE_ SeparationRayShape2DSW(real_t p_length) { length = p_length; }
+ _FORCE_INLINE_ GodotSeparationRayShape2D() {}
+ _FORCE_INLINE_ GodotSeparationRayShape2D(real_t p_length) { length = p_length; }
};
-class SegmentShape2DSW : public Shape2DSW {
+class GodotSegmentShape2D : public GodotShape2D {
Vector2 a;
Vector2 b;
Vector2 n;
@@ -251,15 +251,15 @@ public:
DEFAULT_PROJECT_RANGE_CAST
- _FORCE_INLINE_ SegmentShape2DSW() {}
- _FORCE_INLINE_ SegmentShape2DSW(const Vector2 &p_a, const Vector2 &p_b, const Vector2 &p_n) {
+ _FORCE_INLINE_ GodotSegmentShape2D() {}
+ _FORCE_INLINE_ GodotSegmentShape2D(const Vector2 &p_a, const Vector2 &p_b, const Vector2 &p_n) {
a = p_a;
b = p_b;
n = p_n;
}
};
-class CircleShape2DSW : public Shape2DSW {
+class GodotCircleShape2D : public GodotShape2D {
real_t radius;
public:
@@ -292,7 +292,7 @@ public:
DEFAULT_PROJECT_RANGE_CAST
};
-class RectangleShape2DSW : public Shape2DSW {
+class GodotRectangleShape2D : public GodotShape2D {
Vector2 half_extents;
public:
@@ -336,7 +336,7 @@ public:
return (p_xform.xform(he) - p_circle).normalized();
}
- _FORCE_INLINE_ Vector2 get_box_axis(const Transform2D &p_xform, const Transform2D &p_xform_inv, const RectangleShape2DSW *p_B, const Transform2D &p_B_xform, const Transform2D &p_B_xform_inv) const {
+ _FORCE_INLINE_ Vector2 get_box_axis(const Transform2D &p_xform, const Transform2D &p_xform_inv, const GodotRectangleShape2D *p_B, const Transform2D &p_B_xform, const Transform2D &p_B_xform_inv) const {
Vector2 a, b;
{
@@ -364,7 +364,7 @@ public:
DEFAULT_PROJECT_RANGE_CAST
};
-class CapsuleShape2DSW : public Shape2DSW {
+class GodotCapsuleShape2D : public GodotShape2D {
real_t radius = 0.0;
real_t height = 0.0;
@@ -405,7 +405,7 @@ public:
DEFAULT_PROJECT_RANGE_CAST
};
-class ConvexPolygonShape2DSW : public Shape2DSW {
+class GodotConvexPolygonShape2D : public GodotShape2D {
struct Point {
Vector2 pos;
Vector2 normal; //normal to next segment
@@ -457,21 +457,21 @@ public:
DEFAULT_PROJECT_RANGE_CAST
- ConvexPolygonShape2DSW() {}
- ~ConvexPolygonShape2DSW();
+ GodotConvexPolygonShape2D() {}
+ ~GodotConvexPolygonShape2D();
};
-class ConcaveShape2DSW : public Shape2DSW {
+class GodotConcaveShape2D : public GodotShape2D {
public:
virtual bool is_concave() const override { return true; }
// Returns true to stop the query.
- typedef bool (*QueryCallback)(void *p_userdata, Shape2DSW *p_convex);
+ typedef bool (*QueryCallback)(void *p_userdata, GodotShape2D *p_convex);
virtual void cull(const Rect2 &p_local_aabb, QueryCallback p_callback, void *p_userdata) const = 0;
};
-class ConcavePolygonShape2DSW : public ConcaveShape2DSW {
+class GodotConcavePolygonShape2D : public GodotConcaveShape2D {
struct Segment {
int points[2] = {};
};
@@ -507,13 +507,13 @@ public:
virtual void project_rangev(const Vector2 &p_normal, const Transform2D &p_transform, real_t &r_min, real_t &r_max) const override {
r_min = 0;
r_max = 0;
- ERR_FAIL_MSG("Unsupported call to project_rangev in ConcavePolygonShape2DSW");
+ ERR_FAIL_MSG("Unsupported call to project_rangev in GodotConcavePolygonShape2D");
}
void project_range(const Vector2 &p_normal, const Transform2D &p_transform, real_t &r_min, real_t &r_max) const {
r_min = 0;
r_max = 0;
- ERR_FAIL_MSG("Unsupported call to project_range in ConcavePolygonShape2DSW");
+ ERR_FAIL_MSG("Unsupported call to project_range in GodotConcavePolygonShape2D");
}
virtual void get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const override;
@@ -533,4 +533,4 @@ public:
#undef DEFAULT_PROJECT_RANGE_CAST
-#endif // SHAPE_2D_2DSW_H
+#endif // GODOT_SHAPE_2D_H
diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/godot_space_2d.cpp
index dd0780b5ff..5c2bda340b 100644
--- a/servers/physics_2d/space_2d_sw.cpp
+++ b/servers/physics_2d/godot_space_2d.cpp
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* space_2d_sw.cpp */
+/* godot_space_2d.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,68 +28,70 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "space_2d_sw.h"
+#include "godot_space_2d.h"
+
+#include "godot_collision_solver_2d.h"
+#include "godot_physics_server_2d.h"
-#include "collision_solver_2d_sw.h"
#include "core/os/os.h"
#include "core/templates/pair.h"
-#include "physics_server_2d_sw.h"
+#define TEST_MOTION_MARGIN_MIN_VALUE 0.0001
#define TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR 0.05
-_FORCE_INLINE_ static bool _can_collide_with(CollisionObject2DSW *p_object, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
+_FORCE_INLINE_ static bool _can_collide_with(GodotCollisionObject2D *p_object, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
if (!(p_object->get_collision_layer() & p_collision_mask)) {
return false;
}
- if (p_object->get_type() == CollisionObject2DSW::TYPE_AREA && !p_collide_with_areas) {
+ if (p_object->get_type() == GodotCollisionObject2D::TYPE_AREA && !p_collide_with_areas) {
return false;
}
- if (p_object->get_type() == CollisionObject2DSW::TYPE_BODY && !p_collide_with_bodies) {
+ if (p_object->get_type() == GodotCollisionObject2D::TYPE_BODY && !p_collide_with_bodies) {
return false;
}
return true;
}
-int PhysicsDirectSpaceState2DSW::_intersect_point_impl(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_point, bool p_filter_by_canvas, ObjectID p_canvas_instance_id) {
+int GodotPhysicsDirectSpaceState2D::intersect_point(const PointParameters &p_parameters, ShapeResult *r_results, int p_result_max) {
if (p_result_max <= 0) {
return 0;
}
Rect2 aabb;
- aabb.position = p_point - Vector2(0.00001, 0.00001);
+ aabb.position = p_parameters.position - Vector2(0.00001, 0.00001);
aabb.size = Vector2(0.00002, 0.00002);
- int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, Space2DSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results);
+ int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, GodotSpace2D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results);
int cc = 0;
for (int i = 0; i < amount; i++) {
- if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) {
+ if (!_can_collide_with(space->intersection_query_results[i], p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas)) {
continue;
}
- if (p_exclude.has(space->intersection_query_results[i]->get_self())) {
+ if (p_parameters.exclude.has(space->intersection_query_results[i]->get_self())) {
continue;
}
- const CollisionObject2DSW *col_obj = space->intersection_query_results[i];
+ const GodotCollisionObject2D *col_obj = space->intersection_query_results[i];
- if (p_pick_point && !col_obj->is_pickable()) {
+ if (p_parameters.pick_point && !col_obj->is_pickable()) {
continue;
}
- if (p_filter_by_canvas && col_obj->get_canvas_instance_id() != p_canvas_instance_id) {
+ if (p_parameters.canvas_instance_id.is_valid() && col_obj->get_canvas_instance_id() != p_parameters.canvas_instance_id) {
continue;
}
int shape_idx = space->intersection_query_subindex_results[i];
- Shape2DSW *shape = col_obj->get_shape(shape_idx);
+ GodotShape2D *shape = col_obj->get_shape(shape_idx);
- Vector2 local_point = (col_obj->get_transform() * col_obj->get_shape_transform(shape_idx)).affine_inverse().xform(p_point);
+ Vector2 local_point = (col_obj->get_transform() * col_obj->get_shape_transform(shape_idx)).affine_inverse().xform(p_parameters.position);
if (!shape->contains_point(local_point)) {
continue;
@@ -112,43 +114,35 @@ int PhysicsDirectSpaceState2DSW::_intersect_point_impl(const Vector2 &p_point, S
return cc;
}
-int PhysicsDirectSpaceState2DSW::intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_point) {
- return _intersect_point_impl(p_point, r_results, p_result_max, p_exclude, p_collision_mask, p_collide_with_bodies, p_collide_with_areas, p_pick_point);
-}
-
-int PhysicsDirectSpaceState2DSW::intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_instance_id, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_point) {
- return _intersect_point_impl(p_point, r_results, p_result_max, p_exclude, p_collision_mask, p_collide_with_bodies, p_collide_with_areas, p_pick_point, true, p_canvas_instance_id);
-}
-
-bool PhysicsDirectSpaceState2DSW::intersect_ray(const Vector2 &p_from, const Vector2 &p_to, RayResult &r_result, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
+bool GodotPhysicsDirectSpaceState2D::intersect_ray(const RayParameters &p_parameters, RayResult &r_result) {
ERR_FAIL_COND_V(space->locked, false);
Vector2 begin, end;
Vector2 normal;
- begin = p_from;
- end = p_to;
+ begin = p_parameters.from;
+ end = p_parameters.to;
normal = (end - begin).normalized();
- int amount = space->broadphase->cull_segment(begin, end, space->intersection_query_results, Space2DSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results);
+ int amount = space->broadphase->cull_segment(begin, end, space->intersection_query_results, GodotSpace2D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results);
//todo, create another array that references results, compute AABBs and check closest point to ray origin, sort, and stop evaluating results when beyond first collision
bool collided = false;
Vector2 res_point, res_normal;
int res_shape;
- const CollisionObject2DSW *res_obj;
+ const GodotCollisionObject2D *res_obj;
real_t min_d = 1e10;
for (int i = 0; i < amount; i++) {
- if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) {
+ if (!_can_collide_with(space->intersection_query_results[i], p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas)) {
continue;
}
- if (p_exclude.has(space->intersection_query_results[i]->get_self())) {
+ if (p_parameters.exclude.has(space->intersection_query_results[i]->get_self())) {
continue;
}
- const CollisionObject2DSW *col_obj = space->intersection_query_results[i];
+ const GodotCollisionObject2D *col_obj = space->intersection_query_results[i];
int shape_idx = space->intersection_query_subindex_results[i];
Transform2D inv_xform = col_obj->get_shape_inv_transform(shape_idx) * col_obj->get_inv_transform();
@@ -156,16 +150,26 @@ bool PhysicsDirectSpaceState2DSW::intersect_ray(const Vector2 &p_from, const Vec
Vector2 local_from = inv_xform.xform(begin);
Vector2 local_to = inv_xform.xform(end);
- /*local_from = col_obj->get_inv_transform().xform(begin);
- local_from = col_obj->get_shape_inv_transform(shape_idx).xform(local_from);
-
- local_to = col_obj->get_inv_transform().xform(end);
- local_to = col_obj->get_shape_inv_transform(shape_idx).xform(local_to);*/
-
- const Shape2DSW *shape = col_obj->get_shape(shape_idx);
+ const GodotShape2D *shape = col_obj->get_shape(shape_idx);
Vector2 shape_point, shape_normal;
+ if (shape->contains_point(local_from)) {
+ if (p_parameters.hit_from_inside) {
+ // Hit shape at starting point.
+ min_d = 0;
+ res_point = local_from;
+ res_normal = Vector2();
+ res_shape = shape_idx;
+ res_obj = col_obj;
+ collided = true;
+ break;
+ } else {
+ // Ignore shape when starting inside.
+ continue;
+ }
+ }
+
if (shape->intersect_segment(local_from, local_to, shape_point, shape_normal)) {
Transform2D xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
shape_point = xform.xform(shape_point);
@@ -199,18 +203,19 @@ bool PhysicsDirectSpaceState2DSW::intersect_ray(const Vector2 &p_from, const Vec
return true;
}
-int PhysicsDirectSpaceState2DSW::intersect_shape(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
+int GodotPhysicsDirectSpaceState2D::intersect_shape(const ShapeParameters &p_parameters, ShapeResult *r_results, int p_result_max) {
if (p_result_max <= 0) {
return 0;
}
- Shape2DSW *shape = PhysicsServer2DSW::singletonsw->shape_owner.get_or_null(p_shape);
+ GodotShape2D *shape = GodotPhysicsServer2D::godot_singleton->shape_owner.get_or_null(p_parameters.shape_rid);
ERR_FAIL_COND_V(!shape, 0);
- Rect2 aabb = p_xform.xform(shape->get_aabb());
- aabb = aabb.grow(p_margin);
+ Rect2 aabb = p_parameters.transform.xform(shape->get_aabb());
+ aabb = aabb.merge(Rect2(aabb.position + p_parameters.motion, aabb.size)); //motion
+ aabb = aabb.grow(p_parameters.margin);
- int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, Space2DSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results);
+ int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, GodotSpace2D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results);
int cc = 0;
@@ -219,18 +224,18 @@ int PhysicsDirectSpaceState2DSW::intersect_shape(const RID &p_shape, const Trans
break;
}
- if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) {
+ if (!_can_collide_with(space->intersection_query_results[i], p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas)) {
continue;
}
- if (p_exclude.has(space->intersection_query_results[i]->get_self())) {
+ if (p_parameters.exclude.has(space->intersection_query_results[i]->get_self())) {
continue;
}
- const CollisionObject2DSW *col_obj = space->intersection_query_results[i];
+ const GodotCollisionObject2D *col_obj = space->intersection_query_results[i];
int shape_idx = space->intersection_query_subindex_results[i];
- if (!CollisionSolver2DSW::solve(shape, p_xform, p_motion, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), nullptr, nullptr, nullptr, p_margin)) {
+ if (!GodotCollisionSolver2D::solve(shape, p_parameters.transform, p_parameters.motion, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), nullptr, nullptr, nullptr, p_parameters.margin)) {
continue;
}
@@ -247,43 +252,43 @@ int PhysicsDirectSpaceState2DSW::intersect_shape(const RID &p_shape, const Trans
return cc;
}
-bool PhysicsDirectSpaceState2DSW::cast_motion(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
- Shape2DSW *shape = PhysicsServer2DSW::singletonsw->shape_owner.get_or_null(p_shape);
+bool GodotPhysicsDirectSpaceState2D::cast_motion(const ShapeParameters &p_parameters, real_t &p_closest_safe, real_t &p_closest_unsafe) {
+ GodotShape2D *shape = GodotPhysicsServer2D::godot_singleton->shape_owner.get_or_null(p_parameters.shape_rid);
ERR_FAIL_COND_V(!shape, false);
- Rect2 aabb = p_xform.xform(shape->get_aabb());
- aabb = aabb.merge(Rect2(aabb.position + p_motion, aabb.size)); //motion
- aabb = aabb.grow(p_margin);
+ Rect2 aabb = p_parameters.transform.xform(shape->get_aabb());
+ aabb = aabb.merge(Rect2(aabb.position + p_parameters.motion, aabb.size)); //motion
+ aabb = aabb.grow(p_parameters.margin);
- int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, Space2DSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results);
+ int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, GodotSpace2D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results);
real_t best_safe = 1;
real_t best_unsafe = 1;
for (int i = 0; i < amount; i++) {
- if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) {
+ if (!_can_collide_with(space->intersection_query_results[i], p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas)) {
continue;
}
- if (p_exclude.has(space->intersection_query_results[i]->get_self())) {
+ if (p_parameters.exclude.has(space->intersection_query_results[i]->get_self())) {
continue; //ignore excluded
}
- const CollisionObject2DSW *col_obj = space->intersection_query_results[i];
+ const GodotCollisionObject2D *col_obj = space->intersection_query_results[i];
int shape_idx = space->intersection_query_subindex_results[i];
Transform2D col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
//test initial overlap, does it collide if going all the way?
- if (!CollisionSolver2DSW::solve(shape, p_xform, p_motion, col_obj->get_shape(shape_idx), col_obj_xform, Vector2(), nullptr, nullptr, nullptr, p_margin)) {
+ if (!GodotCollisionSolver2D::solve(shape, p_parameters.transform, p_parameters.motion, col_obj->get_shape(shape_idx), col_obj_xform, Vector2(), nullptr, nullptr, nullptr, p_parameters.margin)) {
continue;
}
//test initial overlap, ignore objects it's inside of.
- if (CollisionSolver2DSW::solve(shape, p_xform, Vector2(), col_obj->get_shape(shape_idx), col_obj_xform, Vector2(), nullptr, nullptr, nullptr, p_margin)) {
+ if (GodotCollisionSolver2D::solve(shape, p_parameters.transform, Vector2(), col_obj->get_shape(shape_idx), col_obj_xform, Vector2(), nullptr, nullptr, nullptr, p_parameters.margin)) {
continue;
}
- Vector2 mnormal = p_motion.normalized();
+ Vector2 mnormal = p_parameters.motion.normalized();
//just do kinematic solving
real_t low = 0.0;
@@ -293,7 +298,7 @@ bool PhysicsDirectSpaceState2DSW::cast_motion(const RID &p_shape, const Transfor
real_t fraction = low + (hi - low) * fraction_coeff;
Vector2 sep = mnormal; //important optimization for this to work fast enough
- bool collided = CollisionSolver2DSW::solve(shape, p_xform, p_motion * fraction, col_obj->get_shape(shape_idx), col_obj_xform, Vector2(), nullptr, nullptr, &sep, p_margin);
+ bool collided = GodotCollisionSolver2D::solve(shape, p_parameters.transform, p_parameters.motion * fraction, col_obj->get_shape(shape_idx), col_obj_xform, Vector2(), nullptr, nullptr, &sep, p_parameters.margin);
if (collided) {
hi = fraction;
@@ -330,40 +335,40 @@ bool PhysicsDirectSpaceState2DSW::cast_motion(const RID &p_shape, const Transfor
return true;
}
-bool PhysicsDirectSpaceState2DSW::collide_shape(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, Vector2 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
+bool GodotPhysicsDirectSpaceState2D::collide_shape(const ShapeParameters &p_parameters, Vector2 *r_results, int p_result_max, int &r_result_count) {
if (p_result_max <= 0) {
return false;
}
- Shape2DSW *shape = PhysicsServer2DSW::singletonsw->shape_owner.get_or_null(p_shape);
+ GodotShape2D *shape = GodotPhysicsServer2D::godot_singleton->shape_owner.get_or_null(p_parameters.shape_rid);
ERR_FAIL_COND_V(!shape, 0);
- Rect2 aabb = p_shape_xform.xform(shape->get_aabb());
- aabb = aabb.merge(Rect2(aabb.position + p_motion, aabb.size)); //motion
- aabb = aabb.grow(p_margin);
+ Rect2 aabb = p_parameters.transform.xform(shape->get_aabb());
+ aabb = aabb.merge(Rect2(aabb.position + p_parameters.motion, aabb.size)); //motion
+ aabb = aabb.grow(p_parameters.margin);
- int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, Space2DSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results);
+ int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, GodotSpace2D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results);
bool collided = false;
r_result_count = 0;
- PhysicsServer2DSW::CollCbkData cbk;
+ GodotPhysicsServer2D::CollCbkData cbk;
cbk.max = p_result_max;
cbk.amount = 0;
cbk.passed = 0;
cbk.ptr = r_results;
- CollisionSolver2DSW::CallbackResult cbkres = PhysicsServer2DSW::_shape_col_cbk;
+ GodotCollisionSolver2D::CallbackResult cbkres = GodotPhysicsServer2D::_shape_col_cbk;
- PhysicsServer2DSW::CollCbkData *cbkptr = &cbk;
+ GodotPhysicsServer2D::CollCbkData *cbkptr = &cbk;
for (int i = 0; i < amount; i++) {
- if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) {
+ if (!_can_collide_with(space->intersection_query_results[i], p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas)) {
continue;
}
- const CollisionObject2DSW *col_obj = space->intersection_query_results[i];
+ const GodotCollisionObject2D *col_obj = space->intersection_query_results[i];
- if (p_exclude.has(col_obj->get_self())) {
+ if (p_parameters.exclude.has(col_obj->get_self())) {
continue;
}
@@ -372,7 +377,7 @@ bool PhysicsDirectSpaceState2DSW::collide_shape(RID p_shape, const Transform2D &
cbk.valid_dir = Vector2();
cbk.valid_depth = 0;
- if (CollisionSolver2DSW::solve(shape, p_shape_xform, p_motion, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), cbkres, cbkptr, nullptr, p_margin)) {
+ if (GodotCollisionSolver2D::solve(shape, p_parameters.transform, p_parameters.motion, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), cbkres, cbkptr, nullptr, p_parameters.margin)) {
collided = cbk.amount > 0;
}
}
@@ -383,8 +388,8 @@ bool PhysicsDirectSpaceState2DSW::collide_shape(RID p_shape, const Transform2D &
}
struct _RestCallbackData2D {
- const CollisionObject2DSW *object = nullptr;
- const CollisionObject2DSW *best_object = nullptr;
+ const GodotCollisionObject2D *object = nullptr;
+ const GodotCollisionObject2D *best_object = nullptr;
int local_shape = 0;
int best_local_shape = 0;
int shape = 0;
@@ -431,32 +436,33 @@ static void _rest_cbk_result(const Vector2 &p_point_A, const Vector2 &p_point_B,
rd->best_local_shape = rd->local_shape;
}
-bool PhysicsDirectSpaceState2DSW::rest_info(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
- Shape2DSW *shape = PhysicsServer2DSW::singletonsw->shape_owner.get_or_null(p_shape);
+bool GodotPhysicsDirectSpaceState2D::rest_info(const ShapeParameters &p_parameters, ShapeRestInfo *r_info) {
+ GodotShape2D *shape = GodotPhysicsServer2D::godot_singleton->shape_owner.get_or_null(p_parameters.shape_rid);
ERR_FAIL_COND_V(!shape, 0);
- real_t min_contact_depth = p_margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR;
+ real_t margin = MAX(p_parameters.margin, TEST_MOTION_MARGIN_MIN_VALUE);
- Rect2 aabb = p_shape_xform.xform(shape->get_aabb());
- aabb = aabb.merge(Rect2(aabb.position + p_motion, aabb.size)); //motion
- aabb = aabb.grow(p_margin);
+ Rect2 aabb = p_parameters.transform.xform(shape->get_aabb());
+ aabb = aabb.merge(Rect2(aabb.position + p_parameters.motion, aabb.size)); //motion
+ aabb = aabb.grow(margin);
- int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, Space2DSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results);
+ int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, GodotSpace2D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results);
_RestCallbackData2D rcd;
- rcd.best_len = 0;
- rcd.best_object = nullptr;
- rcd.best_shape = 0;
- rcd.min_allowed_depth = min_contact_depth;
+
+ // Allowed depth can't be lower than motion length, in order to handle contacts at low speed.
+ real_t motion_length = p_parameters.motion.length();
+ real_t min_contact_depth = margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR;
+ rcd.min_allowed_depth = MIN(motion_length, min_contact_depth);
for (int i = 0; i < amount; i++) {
- if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) {
+ if (!_can_collide_with(space->intersection_query_results[i], p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas)) {
continue;
}
- const CollisionObject2DSW *col_obj = space->intersection_query_results[i];
+ const GodotCollisionObject2D *col_obj = space->intersection_query_results[i];
- if (p_exclude.has(col_obj->get_self())) {
+ if (p_parameters.exclude.has(col_obj->get_self())) {
continue;
}
@@ -466,7 +472,7 @@ bool PhysicsDirectSpaceState2DSW::rest_info(RID p_shape, const Transform2D &p_sh
rcd.object = col_obj;
rcd.shape = shape_idx;
rcd.local_shape = 0;
- bool sc = CollisionSolver2DSW::solve(shape, p_shape_xform, p_motion, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), _rest_cbk_result, &rcd, nullptr, p_margin);
+ bool sc = GodotCollisionSolver2D::solve(shape, p_parameters.transform, p_parameters.motion, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), _rest_cbk_result, &rcd, nullptr, margin);
if (!sc) {
continue;
}
@@ -481,8 +487,8 @@ bool PhysicsDirectSpaceState2DSW::rest_info(RID p_shape, const Transform2D &p_sh
r_info->normal = rcd.best_normal;
r_info->point = rcd.best_contact;
r_info->rid = rcd.best_object->get_self();
- if (rcd.best_object->get_type() == CollisionObject2DSW::TYPE_BODY) {
- const Body2DSW *body = static_cast<const Body2DSW *>(rcd.best_object);
+ if (rcd.best_object->get_type() == GodotCollisionObject2D::TYPE_BODY) {
+ const GodotBody2D *body = static_cast<const GodotBody2D *>(rcd.best_object);
Vector2 rel_vec = r_info->point - (body->get_transform().get_origin() + body->get_center_of_mass());
r_info->linear_velocity = Vector2(-body->get_angular_velocity() * rel_vec.y, body->get_angular_velocity() * rel_vec.x) + body->get_linear_velocity();
@@ -495,7 +501,7 @@ bool PhysicsDirectSpaceState2DSW::rest_info(RID p_shape, const Transform2D &p_sh
////////////////////////////////////////////////////////////////////////////////////////////////////////////
-int Space2DSW::_cull_aabb_for_body(Body2DSW *p_body, const Rect2 &p_aabb) {
+int GodotSpace2D::_cull_aabb_for_body(GodotBody2D *p_body, const Rect2 &p_aabb) {
int amount = broadphase->cull_aabb(p_aabb, intersection_query_results, INTERSECTION_QUERY_MAX, intersection_query_subindex_results);
for (int i = 0; i < amount; i++) {
@@ -503,11 +509,11 @@ int Space2DSW::_cull_aabb_for_body(Body2DSW *p_body, const Rect2 &p_aabb) {
if (intersection_query_results[i] == p_body) {
keep = false;
- } else if (intersection_query_results[i]->get_type() == CollisionObject2DSW::TYPE_AREA) {
+ } else if (intersection_query_results[i]->get_type() == GodotCollisionObject2D::TYPE_AREA) {
keep = false;
- } else if (!p_body->collides_with(static_cast<Body2DSW *>(intersection_query_results[i]))) {
+ } else if (!p_body->collides_with(static_cast<GodotBody2D *>(intersection_query_results[i]))) {
keep = false;
- } else if (static_cast<Body2DSW *>(intersection_query_results[i])->has_exception(p_body->get_self()) || p_body->has_exception(intersection_query_results[i]->get_self())) {
+ } else if (static_cast<GodotBody2D *>(intersection_query_results[i])->has_exception(p_body->get_self()) || p_body->has_exception(intersection_query_results[i]->get_self())) {
keep = false;
}
@@ -525,7 +531,7 @@ int Space2DSW::_cull_aabb_for_body(Body2DSW *p_body, const Rect2 &p_aabb) {
return amount;
}
-bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::MotionParameters &p_parameters, PhysicsServer2D::MotionResult *r_result) {
+bool GodotSpace2D::test_body_motion(GodotBody2D *p_body, const PhysicsServer2D::MotionParameters &p_parameters, PhysicsServer2D::MotionResult *r_result) {
//give me back regular physics engine logic
//this is madness
//and most people using this function will think
@@ -537,6 +543,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::Motion
r_result->collider_id = ObjectID();
r_result->collider_shape = 0;
}
+
Rect2 body_aabb;
bool shapes_found = false;
@@ -562,15 +569,17 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::Motion
return false;
}
+ real_t margin = MAX(p_parameters.margin, TEST_MOTION_MARGIN_MIN_VALUE);
+
// Undo the currently transform the physics server is aware of and apply the provided one
body_aabb = p_parameters.from.xform(p_body->get_inv_transform().xform(body_aabb));
- body_aabb = body_aabb.grow(p_parameters.margin);
+ body_aabb = body_aabb.grow(margin);
static const int max_excluded_shape_pairs = 32;
ExcludedShapeSW excluded_shape_pairs[max_excluded_shape_pairs];
int excluded_shape_pair_count = 0;
- real_t min_contact_depth = p_parameters.margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR;
+ real_t min_contact_depth = margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR;
real_t motion_length = p_parameters.motion.length();
Vector2 motion_normal = p_parameters.motion / motion_length;
@@ -587,7 +596,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::Motion
Vector2 sr[max_results * 2];
do {
- PhysicsServer2DSW::CollCbkData cbk;
+ GodotPhysicsServer2D::CollCbkData cbk;
cbk.max = max_results;
cbk.amount = 0;
cbk.passed = 0;
@@ -595,8 +604,8 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::Motion
cbk.invalid_by_dir = 0;
excluded_shape_pair_count = 0; //last step is the one valid
- PhysicsServer2DSW::CollCbkData *cbkptr = &cbk;
- CollisionSolver2DSW::CallbackResult cbkres = PhysicsServer2DSW::_shape_col_cbk;
+ GodotPhysicsServer2D::CollCbkData *cbkptr = &cbk;
+ GodotCollisionSolver2D::CallbackResult cbkres = GodotPhysicsServer2D::_shape_col_cbk;
bool collided = false;
@@ -607,11 +616,11 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::Motion
continue;
}
- Shape2DSW *body_shape = p_body->get_shape(j);
+ GodotShape2D *body_shape = p_body->get_shape(j);
Transform2D body_shape_xform = body_transform * p_body->get_shape_transform(j);
for (int i = 0; i < amount; i++) {
- const CollisionObject2DSW *col_obj = intersection_query_results[i];
+ const GodotCollisionObject2D *col_obj = intersection_query_results[i];
if (p_parameters.exclude_bodies.has(col_obj->get_self())) {
continue;
}
@@ -627,11 +636,11 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::Motion
cbk.valid_dir = col_obj_shape_xform.get_axis(1).normalized();
real_t owc_margin = col_obj->get_shape_one_way_collision_margin(shape_idx);
- cbk.valid_depth = MAX(owc_margin, p_parameters.margin); //user specified, but never less than actual margin or it won't work
+ cbk.valid_depth = MAX(owc_margin, margin); //user specified, but never less than actual margin or it won't work
cbk.invalid_by_dir = 0;
- if (col_obj->get_type() == CollisionObject2DSW::TYPE_BODY) {
- const Body2DSW *b = static_cast<const Body2DSW *>(col_obj);
+ if (col_obj->get_type() == GodotCollisionObject2D::TYPE_BODY) {
+ const GodotBody2D *b = static_cast<const GodotBody2D *>(col_obj);
if (b->get_mode() == PhysicsServer2D::BODY_MODE_KINEMATIC || b->get_mode() == PhysicsServer2D::BODY_MODE_DYNAMIC) {
//fix for moving platforms (kinematic and dynamic), margin is increased by how much it moved in the given direction
Vector2 lv = b->get_linear_velocity();
@@ -651,8 +660,8 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::Motion
int current_passed = cbk.passed; //save how many points passed collision
bool did_collide = false;
- Shape2DSW *against_shape = col_obj->get_shape(shape_idx);
- if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), cbkres, cbkptr, nullptr, p_parameters.margin)) {
+ GodotShape2D *against_shape = col_obj->get_shape(shape_idx);
+ if (GodotCollisionSolver2D::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), cbkres, cbkptr, nullptr, margin)) {
did_collide = cbk.passed > current_passed; //more passed, so collision actually existed
}
@@ -727,13 +736,13 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::Motion
continue;
}
- Shape2DSW *body_shape = p_body->get_shape(body_shape_idx);
+ GodotShape2D *body_shape = p_body->get_shape(body_shape_idx);
// Colliding separation rays allows to properly snap to the ground,
// otherwise it's not needed in regular motion.
if (!p_parameters.collide_separation_ray && (body_shape->get_type() == PhysicsServer2D::SHAPE_SEPARATION_RAY)) {
// When slide on slope is on, separation ray shape acts like a regular shape.
- if (!static_cast<SeparationRayShape2DSW *>(body_shape)->get_slide_on_slope()) {
+ if (!static_cast<GodotSeparationRayShape2D *>(body_shape)->get_slide_on_slope()) {
continue;
}
}
@@ -746,7 +755,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::Motion
real_t best_unsafe = 1;
for (int i = 0; i < amount; i++) {
- const CollisionObject2DSW *col_obj = intersection_query_results[i];
+ const GodotCollisionObject2D *col_obj = intersection_query_results[i];
if (p_parameters.exclude_bodies.has(col_obj->get_self())) {
continue;
}
@@ -755,7 +764,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::Motion
}
int col_shape_idx = intersection_query_subindex_results[i];
- Shape2DSW *against_shape = col_obj->get_shape(col_shape_idx);
+ GodotShape2D *against_shape = col_obj->get_shape(col_shape_idx);
bool excluded = false;
@@ -772,12 +781,12 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::Motion
Transform2D col_obj_shape_xform = col_obj->get_transform() * col_obj->get_shape_transform(col_shape_idx);
//test initial overlap, does it collide if going all the way?
- if (!CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_parameters.motion, against_shape, col_obj_shape_xform, Vector2(), nullptr, nullptr, nullptr, 0)) {
+ if (!GodotCollisionSolver2D::solve(body_shape, body_shape_xform, p_parameters.motion, against_shape, col_obj_shape_xform, Vector2(), nullptr, nullptr, nullptr, 0)) {
continue;
}
//test initial overlap
- if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), nullptr, nullptr, nullptr, 0)) {
+ if (GodotCollisionSolver2D::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), nullptr, nullptr, nullptr, 0)) {
if (body_shape->allows_one_way_collision() && col_obj->is_shape_set_as_one_way_collision(col_shape_idx)) {
Vector2 direction = col_obj_shape_xform.get_axis(1).normalized();
if (motion_normal.dot(direction) < 0) {
@@ -797,7 +806,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::Motion
real_t fraction = low + (hi - low) * fraction_coeff;
Vector2 sep = motion_normal; //important optimization for this to work fast enough
- bool collided = CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_parameters.motion * fraction, against_shape, col_obj_shape_xform, Vector2(), nullptr, nullptr, &sep, 0);
+ bool collided = GodotCollisionSolver2D::solve(body_shape, body_shape_xform, p_parameters.motion * fraction, against_shape, col_obj_shape_xform, Vector2(), nullptr, nullptr, &sep, 0);
if (collided) {
hi = fraction;
@@ -824,7 +833,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::Motion
if (body_shape->allows_one_way_collision() && col_obj->is_shape_set_as_one_way_collision(col_shape_idx)) {
Vector2 cd[2];
- PhysicsServer2DSW::CollCbkData cbk;
+ GodotPhysicsServer2D::CollCbkData cbk;
cbk.max = 1;
cbk.amount = 0;
cbk.passed = 0;
@@ -834,7 +843,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::Motion
cbk.valid_depth = 10e20;
Vector2 sep = motion_normal; //important optimization for this to work fast enough
- bool collided = CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_parameters.motion * (hi + contact_max_allowed_penetration), col_obj->get_shape(col_shape_idx), col_obj_shape_xform, Vector2(), PhysicsServer2DSW::_shape_col_cbk, &cbk, &sep, 0);
+ bool collided = GodotCollisionSolver2D::solve(body_shape, body_shape_xform, p_parameters.motion * (hi + contact_max_allowed_penetration), col_obj->get_shape(col_shape_idx), col_obj_shape_xform, Vector2(), GodotPhysicsServer2D::_shape_col_cbk, &cbk, &sep, 0);
if (!collided || cbk.amount == 0) {
continue;
}
@@ -875,9 +884,6 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::Motion
ugt.elements[2] += p_parameters.motion * unsafe;
_RestCallbackData2D rcd;
- rcd.best_len = 0;
- rcd.best_object = nullptr;
- rcd.best_shape = 0;
// Allowed depth can't be lower than motion length, in order to handle contacts at low speed.
rcd.min_allowed_depth = MIN(motion_length, min_contact_depth);
@@ -891,14 +897,14 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::Motion
}
Transform2D body_shape_xform = ugt * p_body->get_shape_transform(j);
- Shape2DSW *body_shape = p_body->get_shape(j);
+ GodotShape2D *body_shape = p_body->get_shape(j);
body_aabb.position += p_parameters.motion * unsafe;
int amount = _cull_aabb_for_body(p_body, body_aabb);
for (int i = 0; i < amount; i++) {
- const CollisionObject2DSW *col_obj = intersection_query_results[i];
+ const GodotCollisionObject2D *col_obj = intersection_query_results[i];
if (p_parameters.exclude_bodies.has(col_obj->get_self())) {
continue;
}
@@ -908,7 +914,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::Motion
int shape_idx = intersection_query_subindex_results[i];
- Shape2DSW *against_shape = col_obj->get_shape(shape_idx);
+ GodotShape2D *against_shape = col_obj->get_shape(shape_idx);
bool excluded = false;
for (int k = 0; k < excluded_shape_pair_count; k++) {
@@ -927,10 +933,10 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::Motion
rcd.valid_dir = col_obj_shape_xform.get_axis(1).normalized();
real_t owc_margin = col_obj->get_shape_one_way_collision_margin(shape_idx);
- rcd.valid_depth = MAX(owc_margin, p_parameters.margin); //user specified, but never less than actual margin or it won't work
+ rcd.valid_depth = MAX(owc_margin, margin); //user specified, but never less than actual margin or it won't work
- if (col_obj->get_type() == CollisionObject2DSW::TYPE_BODY) {
- const Body2DSW *b = static_cast<const Body2DSW *>(col_obj);
+ if (col_obj->get_type() == GodotCollisionObject2D::TYPE_BODY) {
+ const GodotBody2D *b = static_cast<const GodotBody2D *>(col_obj);
if (b->get_mode() == PhysicsServer2D::BODY_MODE_KINEMATIC || b->get_mode() == PhysicsServer2D::BODY_MODE_DYNAMIC) {
//fix for moving platforms (kinematic and dynamic), margin is increased by how much it moved in the given direction
Vector2 lv = b->get_linear_velocity();
@@ -949,7 +955,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::Motion
rcd.object = col_obj;
rcd.shape = shape_idx;
rcd.local_shape = j;
- bool sc = CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), _rest_cbk_result, &rcd, nullptr, p_parameters.margin);
+ bool sc = GodotCollisionSolver2D::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), _rest_cbk_result, &rcd, nullptr, margin);
if (!sc) {
continue;
}
@@ -968,7 +974,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::Motion
r_result->collision_safe_fraction = safe;
r_result->collision_unsafe_fraction = unsafe;
- const Body2DSW *body = static_cast<const Body2DSW *>(rcd.best_object);
+ const GodotBody2D *body = static_cast<const GodotBody2D *>(rcd.best_object);
Vector2 rel_vec = r_result->collision_point - (body->get_transform().get_origin() + body->get_center_of_mass());
r_result->collider_velocity = Vector2(-body->get_angular_velocity() * rel_vec.y, body->get_angular_velocity() * rel_vec.x) + body->get_linear_velocity();
@@ -990,134 +996,134 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::Motion
return collided;
}
-void *Space2DSW::_broadphase_pair(CollisionObject2DSW *A, int p_subindex_A, CollisionObject2DSW *B, int p_subindex_B, void *p_self) {
+void *GodotSpace2D::_broadphase_pair(GodotCollisionObject2D *A, int p_subindex_A, GodotCollisionObject2D *B, int p_subindex_B, void *p_self) {
if (!A->interacts_with(B)) {
return nullptr;
}
- CollisionObject2DSW::Type type_A = A->get_type();
- CollisionObject2DSW::Type type_B = B->get_type();
+ GodotCollisionObject2D::Type type_A = A->get_type();
+ GodotCollisionObject2D::Type type_B = B->get_type();
if (type_A > type_B) {
SWAP(A, B);
SWAP(p_subindex_A, p_subindex_B);
SWAP(type_A, type_B);
}
- Space2DSW *self = (Space2DSW *)p_self;
+ GodotSpace2D *self = (GodotSpace2D *)p_self;
self->collision_pairs++;
- if (type_A == CollisionObject2DSW::TYPE_AREA) {
- Area2DSW *area = static_cast<Area2DSW *>(A);
- if (type_B == CollisionObject2DSW::TYPE_AREA) {
- Area2DSW *area_b = static_cast<Area2DSW *>(B);
- Area2Pair2DSW *area2_pair = memnew(Area2Pair2DSW(area_b, p_subindex_B, area, p_subindex_A));
+ if (type_A == GodotCollisionObject2D::TYPE_AREA) {
+ GodotArea2D *area = static_cast<GodotArea2D *>(A);
+ if (type_B == GodotCollisionObject2D::TYPE_AREA) {
+ GodotArea2D *area_b = static_cast<GodotArea2D *>(B);
+ GodotArea2Pair2D *area2_pair = memnew(GodotArea2Pair2D(area_b, p_subindex_B, area, p_subindex_A));
return area2_pair;
} else {
- Body2DSW *body = static_cast<Body2DSW *>(B);
- AreaPair2DSW *area_pair = memnew(AreaPair2DSW(body, p_subindex_B, area, p_subindex_A));
+ GodotBody2D *body = static_cast<GodotBody2D *>(B);
+ GodotAreaPair2D *area_pair = memnew(GodotAreaPair2D(body, p_subindex_B, area, p_subindex_A));
return area_pair;
}
} else {
- BodyPair2DSW *b = memnew(BodyPair2DSW((Body2DSW *)A, p_subindex_A, (Body2DSW *)B, p_subindex_B));
+ GodotBodyPair2D *b = memnew(GodotBodyPair2D((GodotBody2D *)A, p_subindex_A, (GodotBody2D *)B, p_subindex_B));
return b;
}
return nullptr;
}
-void Space2DSW::_broadphase_unpair(CollisionObject2DSW *A, int p_subindex_A, CollisionObject2DSW *B, int p_subindex_B, void *p_data, void *p_self) {
+void GodotSpace2D::_broadphase_unpair(GodotCollisionObject2D *A, int p_subindex_A, GodotCollisionObject2D *B, int p_subindex_B, void *p_data, void *p_self) {
if (!p_data) {
return;
}
- Space2DSW *self = (Space2DSW *)p_self;
+ GodotSpace2D *self = (GodotSpace2D *)p_self;
self->collision_pairs--;
- Constraint2DSW *c = (Constraint2DSW *)p_data;
+ GodotConstraint2D *c = (GodotConstraint2D *)p_data;
memdelete(c);
}
-const SelfList<Body2DSW>::List &Space2DSW::get_active_body_list() const {
+const SelfList<GodotBody2D>::List &GodotSpace2D::get_active_body_list() const {
return active_list;
}
-void Space2DSW::body_add_to_active_list(SelfList<Body2DSW> *p_body) {
+void GodotSpace2D::body_add_to_active_list(SelfList<GodotBody2D> *p_body) {
active_list.add(p_body);
}
-void Space2DSW::body_remove_from_active_list(SelfList<Body2DSW> *p_body) {
+void GodotSpace2D::body_remove_from_active_list(SelfList<GodotBody2D> *p_body) {
active_list.remove(p_body);
}
-void Space2DSW::body_add_to_mass_properties_update_list(SelfList<Body2DSW> *p_body) {
+void GodotSpace2D::body_add_to_mass_properties_update_list(SelfList<GodotBody2D> *p_body) {
mass_properties_update_list.add(p_body);
}
-void Space2DSW::body_remove_from_mass_properties_update_list(SelfList<Body2DSW> *p_body) {
+void GodotSpace2D::body_remove_from_mass_properties_update_list(SelfList<GodotBody2D> *p_body) {
mass_properties_update_list.remove(p_body);
}
-BroadPhase2DSW *Space2DSW::get_broadphase() {
+GodotBroadPhase2D *GodotSpace2D::get_broadphase() {
return broadphase;
}
-void Space2DSW::add_object(CollisionObject2DSW *p_object) {
+void GodotSpace2D::add_object(GodotCollisionObject2D *p_object) {
ERR_FAIL_COND(objects.has(p_object));
objects.insert(p_object);
}
-void Space2DSW::remove_object(CollisionObject2DSW *p_object) {
+void GodotSpace2D::remove_object(GodotCollisionObject2D *p_object) {
ERR_FAIL_COND(!objects.has(p_object));
objects.erase(p_object);
}
-const Set<CollisionObject2DSW *> &Space2DSW::get_objects() const {
+const Set<GodotCollisionObject2D *> &GodotSpace2D::get_objects() const {
return objects;
}
-void Space2DSW::body_add_to_state_query_list(SelfList<Body2DSW> *p_body) {
+void GodotSpace2D::body_add_to_state_query_list(SelfList<GodotBody2D> *p_body) {
state_query_list.add(p_body);
}
-void Space2DSW::body_remove_from_state_query_list(SelfList<Body2DSW> *p_body) {
+void GodotSpace2D::body_remove_from_state_query_list(SelfList<GodotBody2D> *p_body) {
state_query_list.remove(p_body);
}
-void Space2DSW::area_add_to_monitor_query_list(SelfList<Area2DSW> *p_area) {
+void GodotSpace2D::area_add_to_monitor_query_list(SelfList<GodotArea2D> *p_area) {
monitor_query_list.add(p_area);
}
-void Space2DSW::area_remove_from_monitor_query_list(SelfList<Area2DSW> *p_area) {
+void GodotSpace2D::area_remove_from_monitor_query_list(SelfList<GodotArea2D> *p_area) {
monitor_query_list.remove(p_area);
}
-void Space2DSW::area_add_to_moved_list(SelfList<Area2DSW> *p_area) {
+void GodotSpace2D::area_add_to_moved_list(SelfList<GodotArea2D> *p_area) {
area_moved_list.add(p_area);
}
-void Space2DSW::area_remove_from_moved_list(SelfList<Area2DSW> *p_area) {
+void GodotSpace2D::area_remove_from_moved_list(SelfList<GodotArea2D> *p_area) {
area_moved_list.remove(p_area);
}
-const SelfList<Area2DSW>::List &Space2DSW::get_moved_area_list() const {
+const SelfList<GodotArea2D>::List &GodotSpace2D::get_moved_area_list() const {
return area_moved_list;
}
-void Space2DSW::call_queries() {
+void GodotSpace2D::call_queries() {
while (state_query_list.first()) {
- Body2DSW *b = state_query_list.first()->self();
+ GodotBody2D *b = state_query_list.first()->self();
state_query_list.remove(state_query_list.first());
b->call_queries();
}
while (monitor_query_list.first()) {
- Area2DSW *a = monitor_query_list.first()->self();
+ GodotArea2D *a = monitor_query_list.first()->self();
monitor_query_list.remove(monitor_query_list.first());
a->call_queries();
}
}
-void Space2DSW::setup() {
+void GodotSpace2D::setup() {
contact_debug_count = 0;
while (mass_properties_update_list.first()) {
@@ -1126,11 +1132,11 @@ void Space2DSW::setup() {
}
}
-void Space2DSW::update() {
+void GodotSpace2D::update() {
broadphase->update();
}
-void Space2DSW::set_param(PhysicsServer2D::SpaceParameter p_param, real_t p_value) {
+void GodotSpace2D::set_param(PhysicsServer2D::SpaceParameter p_param, real_t p_value) {
switch (p_param) {
case PhysicsServer2D::SPACE_PARAM_CONTACT_RECYCLE_RADIUS:
contact_recycle_radius = p_value;
@@ -1138,9 +1144,12 @@ void Space2DSW::set_param(PhysicsServer2D::SpaceParameter p_param, real_t p_valu
case PhysicsServer2D::SPACE_PARAM_CONTACT_MAX_SEPARATION:
contact_max_separation = p_value;
break;
- case PhysicsServer2D::SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION:
+ case PhysicsServer2D::SPACE_PARAM_CONTACT_MAX_ALLOWED_PENETRATION:
contact_max_allowed_penetration = p_value;
break;
+ case PhysicsServer2D::SPACE_PARAM_CONTACT_DEFAULT_BIAS:
+ contact_bias = p_value;
+ break;
case PhysicsServer2D::SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD:
body_linear_velocity_sleep_threshold = p_value;
break;
@@ -1153,17 +1162,22 @@ void Space2DSW::set_param(PhysicsServer2D::SpaceParameter p_param, real_t p_valu
case PhysicsServer2D::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS:
constraint_bias = p_value;
break;
+ case PhysicsServer2D::SPACE_PARAM_SOLVER_ITERATIONS:
+ solver_iterations = p_value;
+ break;
}
}
-real_t Space2DSW::get_param(PhysicsServer2D::SpaceParameter p_param) const {
+real_t GodotSpace2D::get_param(PhysicsServer2D::SpaceParameter p_param) const {
switch (p_param) {
case PhysicsServer2D::SPACE_PARAM_CONTACT_RECYCLE_RADIUS:
return contact_recycle_radius;
case PhysicsServer2D::SPACE_PARAM_CONTACT_MAX_SEPARATION:
return contact_max_separation;
- case PhysicsServer2D::SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION:
+ case PhysicsServer2D::SPACE_PARAM_CONTACT_MAX_ALLOWED_PENETRATION:
return contact_max_allowed_penetration;
+ case PhysicsServer2D::SPACE_PARAM_CONTACT_DEFAULT_BIAS:
+ return contact_bias;
case PhysicsServer2D::SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD:
return body_linear_velocity_sleep_threshold;
case PhysicsServer2D::SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD:
@@ -1172,41 +1186,61 @@ real_t Space2DSW::get_param(PhysicsServer2D::SpaceParameter p_param) const {
return body_time_to_sleep;
case PhysicsServer2D::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS:
return constraint_bias;
+ case PhysicsServer2D::SPACE_PARAM_SOLVER_ITERATIONS:
+ return solver_iterations;
}
return 0;
}
-void Space2DSW::lock() {
+void GodotSpace2D::lock() {
locked = true;
}
-void Space2DSW::unlock() {
+void GodotSpace2D::unlock() {
locked = false;
}
-bool Space2DSW::is_locked() const {
+bool GodotSpace2D::is_locked() const {
return locked;
}
-PhysicsDirectSpaceState2DSW *Space2DSW::get_direct_state() {
+GodotPhysicsDirectSpaceState2D *GodotSpace2D::get_direct_state() {
return direct_access;
}
-Space2DSW::Space2DSW() {
+GodotSpace2D::GodotSpace2D() {
body_linear_velocity_sleep_threshold = GLOBAL_DEF("physics/2d/sleep_threshold_linear", 2.0);
body_angular_velocity_sleep_threshold = GLOBAL_DEF("physics/2d/sleep_threshold_angular", Math::deg2rad(8.0));
body_time_to_sleep = GLOBAL_DEF("physics/2d/time_before_sleep", 0.5);
ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/time_before_sleep", PropertyInfo(Variant::FLOAT, "physics/2d/time_before_sleep", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater"));
- broadphase = BroadPhase2DSW::create_func();
+ solver_iterations = GLOBAL_DEF("physics/2d/solver/solver_iterations", 16);
+ ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/solver/solver_iterations", PropertyInfo(Variant::INT, "physics/2d/solver/solver_iterations", PROPERTY_HINT_RANGE, "1,32,1,or_greater"));
+
+ contact_recycle_radius = GLOBAL_DEF("physics/2d/solver/contact_recycle_radius", 1.0);
+ ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/solver/contact_recycle_radius", PropertyInfo(Variant::FLOAT, "physics/2d/solver/contact_max_separation", PROPERTY_HINT_RANGE, "0,10,0.01,or_greater"));
+
+ contact_max_separation = GLOBAL_DEF("physics/2d/solver/contact_max_separation", 1.5);
+ ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/solver/contact_max_separation", PropertyInfo(Variant::FLOAT, "physics/2d/solver/contact_max_separation", PROPERTY_HINT_RANGE, "0,10,0.01,or_greater"));
+
+ contact_max_allowed_penetration = GLOBAL_DEF("physics/2d/solver/contact_max_allowed_penetration", 0.3);
+ ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/solver/contact_max_allowed_penetration", PropertyInfo(Variant::FLOAT, "physics/2d/solver/contact_max_allowed_penetration", PROPERTY_HINT_RANGE, "0,10,0.01,or_greater"));
+
+ contact_bias = GLOBAL_DEF("physics/2d/solver/default_contact_bias", 0.8);
+ ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/solver/default_contact_bias", PropertyInfo(Variant::FLOAT, "physics/2d/solver/default_contact_bias", PROPERTY_HINT_RANGE, "0,1,0.01"));
+
+ constraint_bias = GLOBAL_DEF("physics/2d/solver/default_constraint_bias", 0.2);
+ ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/solver/default_constraint_bias", PropertyInfo(Variant::FLOAT, "physics/2d/solver/default_constraint_bias", PROPERTY_HINT_RANGE, "0,1,0.01"));
+
+ broadphase = GodotBroadPhase2D::create_func();
broadphase->set_pair_callback(_broadphase_pair, this);
broadphase->set_unpair_callback(_broadphase_unpair, this);
- direct_access = memnew(PhysicsDirectSpaceState2DSW);
+ direct_access = memnew(GodotPhysicsDirectSpaceState2D);
direct_access->space = this;
}
-Space2DSW::~Space2DSW() {
+GodotSpace2D::~GodotSpace2D() {
memdelete(broadphase);
memdelete(direct_access);
}
diff --git a/servers/physics_2d/godot_space_2d.h b/servers/physics_2d/godot_space_2d.h
new file mode 100644
index 0000000000..5d97721176
--- /dev/null
+++ b/servers/physics_2d/godot_space_2d.h
@@ -0,0 +1,214 @@
+/*************************************************************************/
+/* godot_space_2d.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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_SPACE_2D_H
+#define GODOT_SPACE_2D_H
+
+#include "godot_area_2d.h"
+#include "godot_area_pair_2d.h"
+#include "godot_body_2d.h"
+#include "godot_body_pair_2d.h"
+#include "godot_broad_phase_2d.h"
+#include "godot_collision_object_2d.h"
+
+#include "core/config/project_settings.h"
+#include "core/templates/hash_map.h"
+#include "core/typedefs.h"
+
+class GodotPhysicsDirectSpaceState2D : public PhysicsDirectSpaceState2D {
+ GDCLASS(GodotPhysicsDirectSpaceState2D, PhysicsDirectSpaceState2D);
+
+public:
+ GodotSpace2D *space = nullptr;
+
+ virtual int intersect_point(const PointParameters &p_parameters, ShapeResult *r_results, int p_result_max) override;
+ virtual bool intersect_ray(const RayParameters &p_parameters, RayResult &r_result) override;
+ virtual int intersect_shape(const ShapeParameters &p_parameters, ShapeResult *r_results, int p_result_max) override;
+ virtual bool cast_motion(const ShapeParameters &p_parameters, real_t &p_closest_safe, real_t &p_closest_unsafe) override;
+ virtual bool collide_shape(const ShapeParameters &p_parameters, Vector2 *r_results, int p_result_max, int &r_result_count) override;
+ virtual bool rest_info(const ShapeParameters &p_parameters, ShapeRestInfo *r_info) override;
+
+ GodotPhysicsDirectSpaceState2D() {}
+};
+
+class GodotSpace2D {
+public:
+ enum ElapsedTime {
+ ELAPSED_TIME_INTEGRATE_FORCES,
+ ELAPSED_TIME_GENERATE_ISLANDS,
+ ELAPSED_TIME_SETUP_CONSTRAINTS,
+ ELAPSED_TIME_SOLVE_CONSTRAINTS,
+ ELAPSED_TIME_INTEGRATE_VELOCITIES,
+ ELAPSED_TIME_MAX
+
+ };
+
+private:
+ struct ExcludedShapeSW {
+ GodotShape2D *local_shape = nullptr;
+ const GodotCollisionObject2D *against_object = nullptr;
+ int against_shape_index = 0;
+ };
+
+ uint64_t elapsed_time[ELAPSED_TIME_MAX] = {};
+
+ GodotPhysicsDirectSpaceState2D *direct_access = nullptr;
+ RID self;
+
+ GodotBroadPhase2D *broadphase = nullptr;
+ SelfList<GodotBody2D>::List active_list;
+ SelfList<GodotBody2D>::List mass_properties_update_list;
+ SelfList<GodotBody2D>::List state_query_list;
+ SelfList<GodotArea2D>::List monitor_query_list;
+ SelfList<GodotArea2D>::List area_moved_list;
+
+ static void *_broadphase_pair(GodotCollisionObject2D *A, int p_subindex_A, GodotCollisionObject2D *B, int p_subindex_B, void *p_self);
+ static void _broadphase_unpair(GodotCollisionObject2D *A, int p_subindex_A, GodotCollisionObject2D *B, int p_subindex_B, void *p_data, void *p_self);
+
+ Set<GodotCollisionObject2D *> objects;
+
+ GodotArea2D *area = nullptr;
+
+ int solver_iterations = 0;
+
+ real_t contact_recycle_radius = 0.0;
+ real_t contact_max_separation = 0.0;
+ real_t contact_max_allowed_penetration = 0.0;
+ real_t contact_bias = 0.0;
+ real_t constraint_bias = 0.0;
+
+ enum {
+ INTERSECTION_QUERY_MAX = 2048
+ };
+
+ GodotCollisionObject2D *intersection_query_results[INTERSECTION_QUERY_MAX];
+ int intersection_query_subindex_results[INTERSECTION_QUERY_MAX];
+
+ real_t body_linear_velocity_sleep_threshold = 0.0;
+ real_t body_angular_velocity_sleep_threshold = 0.0;
+ real_t body_time_to_sleep = 0.0;
+
+ bool locked = false;
+
+ real_t last_step = 0.001;
+
+ int island_count = 0;
+ int active_objects = 0;
+ int collision_pairs = 0;
+
+ int _cull_aabb_for_body(GodotBody2D *p_body, const Rect2 &p_aabb);
+
+ Vector<Vector2> contact_debug;
+ int contact_debug_count = 0;
+
+ friend class GodotPhysicsDirectSpaceState2D;
+
+public:
+ _FORCE_INLINE_ void set_self(const RID &p_self) { self = p_self; }
+ _FORCE_INLINE_ RID get_self() const { return self; }
+
+ void set_default_area(GodotArea2D *p_area) { area = p_area; }
+ GodotArea2D *get_default_area() const { return area; }
+
+ const SelfList<GodotBody2D>::List &get_active_body_list() const;
+ void body_add_to_active_list(SelfList<GodotBody2D> *p_body);
+ void body_remove_from_active_list(SelfList<GodotBody2D> *p_body);
+ void body_add_to_mass_properties_update_list(SelfList<GodotBody2D> *p_body);
+ void body_remove_from_mass_properties_update_list(SelfList<GodotBody2D> *p_body);
+ void area_add_to_moved_list(SelfList<GodotArea2D> *p_area);
+ void area_remove_from_moved_list(SelfList<GodotArea2D> *p_area);
+ const SelfList<GodotArea2D>::List &get_moved_area_list() const;
+
+ void body_add_to_state_query_list(SelfList<GodotBody2D> *p_body);
+ void body_remove_from_state_query_list(SelfList<GodotBody2D> *p_body);
+
+ void area_add_to_monitor_query_list(SelfList<GodotArea2D> *p_area);
+ void area_remove_from_monitor_query_list(SelfList<GodotArea2D> *p_area);
+
+ GodotBroadPhase2D *get_broadphase();
+
+ void add_object(GodotCollisionObject2D *p_object);
+ void remove_object(GodotCollisionObject2D *p_object);
+ const Set<GodotCollisionObject2D *> &get_objects() const;
+
+ _FORCE_INLINE_ int get_solver_iterations() const { return solver_iterations; }
+ _FORCE_INLINE_ real_t get_contact_recycle_radius() const { return contact_recycle_radius; }
+ _FORCE_INLINE_ real_t get_contact_max_separation() const { return contact_max_separation; }
+ _FORCE_INLINE_ real_t get_contact_max_allowed_penetration() const { return contact_max_allowed_penetration; }
+ _FORCE_INLINE_ real_t get_contact_bias() const { return contact_bias; }
+ _FORCE_INLINE_ real_t get_constraint_bias() const { return constraint_bias; }
+ _FORCE_INLINE_ real_t get_body_linear_velocity_sleep_threshold() const { return body_linear_velocity_sleep_threshold; }
+ _FORCE_INLINE_ real_t get_body_angular_velocity_sleep_threshold() const { return body_angular_velocity_sleep_threshold; }
+ _FORCE_INLINE_ real_t get_body_time_to_sleep() const { return body_time_to_sleep; }
+
+ void update();
+ void setup();
+ void call_queries();
+
+ bool is_locked() const;
+ void lock();
+ void unlock();
+
+ real_t get_last_step() const { return last_step; }
+ void set_last_step(real_t p_step) { last_step = p_step; }
+
+ void set_param(PhysicsServer2D::SpaceParameter p_param, real_t p_value);
+ real_t get_param(PhysicsServer2D::SpaceParameter p_param) const;
+
+ void set_island_count(int p_island_count) { island_count = p_island_count; }
+ int get_island_count() const { return island_count; }
+
+ void set_active_objects(int p_active_objects) { active_objects = p_active_objects; }
+ int get_active_objects() const { return active_objects; }
+
+ int get_collision_pairs() const { return collision_pairs; }
+
+ bool test_body_motion(GodotBody2D *p_body, const PhysicsServer2D::MotionParameters &p_parameters, PhysicsServer2D::MotionResult *r_result);
+
+ void set_debug_contacts(int p_amount) { contact_debug.resize(p_amount); }
+ _FORCE_INLINE_ bool is_debugging_contacts() const { return !contact_debug.is_empty(); }
+ _FORCE_INLINE_ void add_debug_contact(const Vector2 &p_contact) {
+ if (contact_debug_count < contact_debug.size()) {
+ contact_debug.write[contact_debug_count++] = p_contact;
+ }
+ }
+ _FORCE_INLINE_ Vector<Vector2> get_debug_contacts() { return contact_debug; }
+ _FORCE_INLINE_ int get_debug_contact_count() { return contact_debug_count; }
+
+ GodotPhysicsDirectSpaceState2D *get_direct_state();
+
+ void set_elapsed_time(ElapsedTime p_time, uint64_t p_msec) { elapsed_time[p_time] = p_msec; }
+ uint64_t get_elapsed_time(ElapsedTime p_time) const { return elapsed_time[p_time]; }
+
+ GodotSpace2D();
+ ~GodotSpace2D();
+};
+
+#endif // GODOT_SPACE_2D_H
diff --git a/servers/physics_2d/step_2d_sw.cpp b/servers/physics_2d/godot_step_2d.cpp
index a03e30f850..866c415440 100644
--- a/servers/physics_2d/step_2d_sw.cpp
+++ b/servers/physics_2d/godot_step_2d.cpp
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* step_2d_sw.cpp */
+/* godot_step_2d.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "step_2d_sw.h"
+#include "godot_step_2d.h"
#include "core/os/os.h"
@@ -38,7 +38,7 @@
#define ISLAND_SIZE_RESERVE 512
#define CONSTRAINT_COUNT_RESERVE 1024
-void Step2DSW::_populate_island(Body2DSW *p_body, LocalVector<Body2DSW *> &p_body_island, LocalVector<Constraint2DSW *> &p_constraint_island) {
+void GodotStep2D::_populate_island(GodotBody2D *p_body, LocalVector<GodotBody2D *> &p_body_island, LocalVector<GodotConstraint2D *> &p_constraint_island) {
p_body->set_island_step(_step);
if (p_body->get_mode() > PhysicsServer2D::BODY_MODE_KINEMATIC) {
@@ -46,8 +46,8 @@ void Step2DSW::_populate_island(Body2DSW *p_body, LocalVector<Body2DSW *> &p_bod
p_body_island.push_back(p_body);
}
- for (const Pair<Constraint2DSW *, int> &E : p_body->get_constraint_list()) {
- Constraint2DSW *constraint = (Constraint2DSW *)E.first;
+ for (const Pair<GodotConstraint2D *, int> &E : p_body->get_constraint_list()) {
+ GodotConstraint2D *constraint = (GodotConstraint2D *)E.first;
if (constraint->get_island_step() == _step) {
continue; // Already processed.
}
@@ -59,7 +59,7 @@ void Step2DSW::_populate_island(Body2DSW *p_body, LocalVector<Body2DSW *> &p_bod
if (i == E.second) {
continue;
}
- Body2DSW *other_body = constraint->get_body_ptr()[i];
+ GodotBody2D *other_body = constraint->get_body_ptr()[i];
if (other_body->get_island_step() == _step) {
continue; // Already processed.
}
@@ -71,16 +71,16 @@ void Step2DSW::_populate_island(Body2DSW *p_body, LocalVector<Body2DSW *> &p_bod
}
}
-void Step2DSW::_setup_contraint(uint32_t p_constraint_index, void *p_userdata) {
- Constraint2DSW *constraint = all_constraints[p_constraint_index];
+void GodotStep2D::_setup_contraint(uint32_t p_constraint_index, void *p_userdata) {
+ GodotConstraint2D *constraint = all_constraints[p_constraint_index];
constraint->setup(delta);
}
-void Step2DSW::_pre_solve_island(LocalVector<Constraint2DSW *> &p_constraint_island) const {
+void GodotStep2D::_pre_solve_island(LocalVector<GodotConstraint2D *> &p_constraint_island) const {
uint32_t constraint_count = p_constraint_island.size();
uint32_t valid_constraint_count = 0;
for (uint32_t constraint_index = 0; constraint_index < constraint_count; ++constraint_index) {
- Constraint2DSW *constraint = p_constraint_island[constraint_index];
+ GodotConstraint2D *constraint = p_constraint_island[constraint_index];
if (p_constraint_island[constraint_index]->pre_solve(delta)) {
// Keep this constraint for solving.
p_constraint_island[valid_constraint_count++] = constraint;
@@ -89,8 +89,8 @@ void Step2DSW::_pre_solve_island(LocalVector<Constraint2DSW *> &p_constraint_isl
p_constraint_island.resize(valid_constraint_count);
}
-void Step2DSW::_solve_island(uint32_t p_island_index, void *p_userdata) const {
- const LocalVector<Constraint2DSW *> &constraint_island = constraint_islands[p_island_index];
+void GodotStep2D::_solve_island(uint32_t p_island_index, void *p_userdata) const {
+ const LocalVector<GodotConstraint2D *> &constraint_island = constraint_islands[p_island_index];
for (int i = 0; i < iterations; i++) {
uint32_t constraint_count = constraint_island.size();
@@ -100,12 +100,12 @@ void Step2DSW::_solve_island(uint32_t p_island_index, void *p_userdata) const {
}
}
-void Step2DSW::_check_suspend(LocalVector<Body2DSW *> &p_body_island) const {
+void GodotStep2D::_check_suspend(LocalVector<GodotBody2D *> &p_body_island) const {
bool can_sleep = true;
uint32_t body_count = p_body_island.size();
for (uint32_t body_index = 0; body_index < body_count; ++body_index) {
- Body2DSW *body = p_body_island[body_index];
+ GodotBody2D *body = p_body_island[body_index];
if (!body->sleep_test(delta)) {
can_sleep = false;
@@ -114,7 +114,7 @@ void Step2DSW::_check_suspend(LocalVector<Body2DSW *> &p_body_island) const {
// Put all to sleep or wake up everyone.
for (uint32_t body_index = 0; body_index < body_count; ++body_index) {
- Body2DSW *body = p_body_island[body_index];
+ GodotBody2D *body = p_body_island[body_index];
bool active = body->is_active();
@@ -124,17 +124,17 @@ void Step2DSW::_check_suspend(LocalVector<Body2DSW *> &p_body_island) const {
}
}
-void Step2DSW::step(Space2DSW *p_space, real_t p_delta, int p_iterations) {
+void GodotStep2D::step(GodotSpace2D *p_space, real_t p_delta) {
p_space->lock(); // can't access space during this
p_space->setup(); //update inertias, etc
p_space->set_last_step(p_delta);
- iterations = p_iterations;
+ iterations = p_space->get_solver_iterations();
delta = p_delta;
- const SelfList<Body2DSW>::List *body_list = &p_space->get_active_body_list();
+ const SelfList<GodotBody2D>::List *body_list = &p_space->get_active_body_list();
/* INTEGRATE FORCES */
@@ -143,7 +143,7 @@ void Step2DSW::step(Space2DSW *p_space, real_t p_delta, int p_iterations) {
int active_count = 0;
- const SelfList<Body2DSW> *b = body_list->first();
+ const SelfList<GodotBody2D> *b = body_list->first();
while (b) {
b->self()->integrate_forces(p_delta);
b = b->next();
@@ -152,9 +152,12 @@ void Step2DSW::step(Space2DSW *p_space, real_t p_delta, int p_iterations) {
p_space->set_active_objects(active_count);
+ // Update the broadphase to register collision pairs.
+ p_space->update();
+
{ //profile
profile_endtime = OS::get_singleton()->get_ticks_usec();
- p_space->set_elapsed_time(Space2DSW::ELAPSED_TIME_INTEGRATE_FORCES, profile_endtime - profile_begtime);
+ p_space->set_elapsed_time(GodotSpace2D::ELAPSED_TIME_INTEGRATE_FORCES, profile_endtime - profile_begtime);
profile_begtime = profile_endtime;
}
@@ -162,11 +165,11 @@ void Step2DSW::step(Space2DSW *p_space, real_t p_delta, int p_iterations) {
uint32_t island_count = 0;
- const SelfList<Area2DSW>::List &aml = p_space->get_moved_area_list();
+ const SelfList<GodotArea2D>::List &aml = p_space->get_moved_area_list();
while (aml.first()) {
- for (const Set<Constraint2DSW *>::Element *E = aml.first()->self()->get_constraints().front(); E; E = E->next()) {
- Constraint2DSW *constraint = E->get();
+ for (const Set<GodotConstraint2D *>::Element *E = aml.first()->self()->get_constraints().front(); E; E = E->next()) {
+ GodotConstraint2D *constraint = E->get();
if (constraint->get_island_step() == _step) {
continue;
}
@@ -177,13 +180,13 @@ void Step2DSW::step(Space2DSW *p_space, real_t p_delta, int p_iterations) {
if (constraint_islands.size() < island_count) {
constraint_islands.resize(island_count);
}
- LocalVector<Constraint2DSW *> &constraint_island = constraint_islands[island_count - 1];
+ LocalVector<GodotConstraint2D *> &constraint_island = constraint_islands[island_count - 1];
constraint_island.clear();
all_constraints.push_back(constraint);
constraint_island.push_back(constraint);
}
- p_space->area_remove_from_moved_list((SelfList<Area2DSW> *)aml.first()); //faster to remove here
+ p_space->area_remove_from_moved_list((SelfList<GodotArea2D> *)aml.first()); //faster to remove here
}
/* GENERATE CONSTRAINT ISLANDS FOR ACTIVE RIGID BODIES */
@@ -193,14 +196,14 @@ void Step2DSW::step(Space2DSW *p_space, real_t p_delta, int p_iterations) {
uint32_t body_island_count = 0;
while (b) {
- Body2DSW *body = b->self();
+ GodotBody2D *body = b->self();
if (body->get_island_step() != _step) {
++body_island_count;
if (body_islands.size() < body_island_count) {
body_islands.resize(body_island_count);
}
- LocalVector<Body2DSW *> &body_island = body_islands[body_island_count - 1];
+ LocalVector<GodotBody2D *> &body_island = body_islands[body_island_count - 1];
body_island.clear();
body_island.reserve(BODY_ISLAND_SIZE_RESERVE);
@@ -208,7 +211,7 @@ void Step2DSW::step(Space2DSW *p_space, real_t p_delta, int p_iterations) {
if (constraint_islands.size() < island_count) {
constraint_islands.resize(island_count);
}
- LocalVector<Constraint2DSW *> &constraint_island = constraint_islands[island_count - 1];
+ LocalVector<GodotConstraint2D *> &constraint_island = constraint_islands[island_count - 1];
constraint_island.clear();
constraint_island.reserve(ISLAND_SIZE_RESERVE);
@@ -229,18 +232,18 @@ void Step2DSW::step(Space2DSW *p_space, real_t p_delta, int p_iterations) {
{ //profile
profile_endtime = OS::get_singleton()->get_ticks_usec();
- p_space->set_elapsed_time(Space2DSW::ELAPSED_TIME_GENERATE_ISLANDS, profile_endtime - profile_begtime);
+ p_space->set_elapsed_time(GodotSpace2D::ELAPSED_TIME_GENERATE_ISLANDS, profile_endtime - profile_begtime);
profile_begtime = profile_endtime;
}
/* SETUP CONSTRAINTS / PROCESS COLLISIONS */
uint32_t total_contraint_count = all_constraints.size();
- work_pool.do_work(total_contraint_count, this, &Step2DSW::_setup_contraint, nullptr);
+ work_pool.do_work(total_contraint_count, this, &GodotStep2D::_setup_contraint, nullptr);
{ //profile
profile_endtime = OS::get_singleton()->get_ticks_usec();
- p_space->set_elapsed_time(Space2DSW::ELAPSED_TIME_SETUP_CONSTRAINTS, profile_endtime - profile_begtime);
+ p_space->set_elapsed_time(GodotSpace2D::ELAPSED_TIME_SETUP_CONSTRAINTS, profile_endtime - profile_begtime);
profile_begtime = profile_endtime;
}
@@ -255,15 +258,11 @@ void Step2DSW::step(Space2DSW *p_space, real_t p_delta, int p_iterations) {
// Warning: _solve_island modifies the constraint islands for optimization purpose,
// their content is not reliable after these calls and shouldn't be used anymore.
- if (island_count > 1) {
- work_pool.do_work(island_count, this, &Step2DSW::_solve_island, nullptr);
- } else if (island_count > 0) {
- _solve_island(0);
- }
+ work_pool.do_work(island_count, this, &GodotStep2D::_solve_island, nullptr);
{ //profile
profile_endtime = OS::get_singleton()->get_ticks_usec();
- p_space->set_elapsed_time(Space2DSW::ELAPSED_TIME_SOLVE_CONSTRAINTS, profile_endtime - profile_begtime);
+ p_space->set_elapsed_time(GodotSpace2D::ELAPSED_TIME_SOLVE_CONSTRAINTS, profile_endtime - profile_begtime);
profile_begtime = profile_endtime;
}
@@ -271,7 +270,7 @@ void Step2DSW::step(Space2DSW *p_space, real_t p_delta, int p_iterations) {
b = body_list->first();
while (b) {
- const SelfList<Body2DSW> *n = b->next();
+ const SelfList<GodotBody2D> *n = b->next();
b->self()->integrate_velocities(p_delta);
b = n; // in case it shuts itself down
}
@@ -284,18 +283,17 @@ void Step2DSW::step(Space2DSW *p_space, real_t p_delta, int p_iterations) {
{ //profile
profile_endtime = OS::get_singleton()->get_ticks_usec();
- p_space->set_elapsed_time(Space2DSW::ELAPSED_TIME_INTEGRATE_VELOCITIES, profile_endtime - profile_begtime);
+ p_space->set_elapsed_time(GodotSpace2D::ELAPSED_TIME_INTEGRATE_VELOCITIES, profile_endtime - profile_begtime);
//profile_begtime=profile_endtime;
}
all_constraints.clear();
- p_space->update();
p_space->unlock();
_step++;
}
-Step2DSW::Step2DSW() {
+GodotStep2D::GodotStep2D() {
body_islands.reserve(BODY_ISLAND_COUNT_RESERVE);
constraint_islands.reserve(ISLAND_COUNT_RESERVE);
all_constraints.reserve(CONSTRAINT_COUNT_RESERVE);
@@ -303,6 +301,6 @@ Step2DSW::Step2DSW() {
work_pool.init();
}
-Step2DSW::~Step2DSW() {
+GodotStep2D::~GodotStep2D() {
work_pool.finish();
}
diff --git a/servers/physics_2d/step_2d_sw.h b/servers/physics_2d/godot_step_2d.h
index de8e76cc99..9a6d8caf9b 100644
--- a/servers/physics_2d/step_2d_sw.h
+++ b/servers/physics_2d/godot_step_2d.h
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* step_2d_sw.h */
+/* godot_step_2d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,15 +28,15 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef STEP_2D_SW_H
-#define STEP_2D_SW_H
+#ifndef GODOT_STEP_2D_H
+#define GODOT_STEP_2D_H
-#include "space_2d_sw.h"
+#include "godot_space_2d.h"
#include "core/templates/local_vector.h"
#include "core/templates/thread_work_pool.h"
-class Step2DSW {
+class GodotStep2D {
uint64_t _step = 1;
int iterations = 0;
@@ -44,20 +44,20 @@ class Step2DSW {
ThreadWorkPool work_pool;
- LocalVector<LocalVector<Body2DSW *>> body_islands;
- LocalVector<LocalVector<Constraint2DSW *>> constraint_islands;
- LocalVector<Constraint2DSW *> all_constraints;
+ LocalVector<LocalVector<GodotBody2D *>> body_islands;
+ LocalVector<LocalVector<GodotConstraint2D *>> constraint_islands;
+ LocalVector<GodotConstraint2D *> all_constraints;
- void _populate_island(Body2DSW *p_body, LocalVector<Body2DSW *> &p_body_island, LocalVector<Constraint2DSW *> &p_constraint_island);
+ void _populate_island(GodotBody2D *p_body, LocalVector<GodotBody2D *> &p_body_island, LocalVector<GodotConstraint2D *> &p_constraint_island);
void _setup_contraint(uint32_t p_constraint_index, void *p_userdata = nullptr);
- void _pre_solve_island(LocalVector<Constraint2DSW *> &p_constraint_island) const;
+ void _pre_solve_island(LocalVector<GodotConstraint2D *> &p_constraint_island) const;
void _solve_island(uint32_t p_island_index, void *p_userdata = nullptr) const;
- void _check_suspend(LocalVector<Body2DSW *> &p_body_island) const;
+ void _check_suspend(LocalVector<GodotBody2D *> &p_body_island) const;
public:
- void step(Space2DSW *p_space, real_t p_delta, int p_iterations);
- Step2DSW();
- ~Step2DSW();
+ void step(GodotSpace2D *p_space, real_t p_delta);
+ GodotStep2D();
+ ~GodotStep2D();
};
-#endif // STEP_2D_SW_H
+#endif // GODOT_STEP_2D_H
diff --git a/servers/physics_2d/physics_server_2d_sw.cpp b/servers/physics_2d/physics_server_2d_sw.cpp
deleted file mode 100644
index c2205e33b0..0000000000
--- a/servers/physics_2d/physics_server_2d_sw.cpp
+++ /dev/null
@@ -1,1349 +0,0 @@
-/*************************************************************************/
-/* physics_server_2d_sw.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 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 "physics_server_2d_sw.h"
-
-#include "body_direct_state_2d_sw.h"
-#include "broad_phase_2d_bvh.h"
-#include "collision_solver_2d_sw.h"
-#include "core/config/project_settings.h"
-#include "core/debugger/engine_debugger.h"
-#include "core/os/os.h"
-
-#define FLUSH_QUERY_CHECK(m_object) \
- ERR_FAIL_COND_MSG(m_object->get_space() && flushing_queries, "Can't change this state while flushing queries. Use call_deferred() or set_deferred() to change monitoring state instead.");
-
-RID PhysicsServer2DSW::_shape_create(ShapeType p_shape) {
- Shape2DSW *shape = nullptr;
- switch (p_shape) {
- case SHAPE_WORLD_BOUNDARY: {
- shape = memnew(WorldBoundaryShape2DSW);
- } break;
- case SHAPE_SEPARATION_RAY: {
- shape = memnew(SeparationRayShape2DSW);
- } break;
- case SHAPE_SEGMENT: {
- shape = memnew(SegmentShape2DSW);
- } break;
- case SHAPE_CIRCLE: {
- shape = memnew(CircleShape2DSW);
- } break;
- case SHAPE_RECTANGLE: {
- shape = memnew(RectangleShape2DSW);
- } break;
- case SHAPE_CAPSULE: {
- shape = memnew(CapsuleShape2DSW);
- } break;
- case SHAPE_CONVEX_POLYGON: {
- shape = memnew(ConvexPolygonShape2DSW);
- } break;
- case SHAPE_CONCAVE_POLYGON: {
- shape = memnew(ConcavePolygonShape2DSW);
- } break;
- case SHAPE_CUSTOM: {
- ERR_FAIL_V(RID());
-
- } break;
- }
-
- RID id = shape_owner.make_rid(shape);
- shape->set_self(id);
-
- return id;
-}
-
-RID PhysicsServer2DSW::world_boundary_shape_create() {
- return _shape_create(SHAPE_WORLD_BOUNDARY);
-}
-
-RID PhysicsServer2DSW::separation_ray_shape_create() {
- return _shape_create(SHAPE_SEPARATION_RAY);
-}
-
-RID PhysicsServer2DSW::segment_shape_create() {
- return _shape_create(SHAPE_SEGMENT);
-}
-
-RID PhysicsServer2DSW::circle_shape_create() {
- return _shape_create(SHAPE_CIRCLE);
-}
-
-RID PhysicsServer2DSW::rectangle_shape_create() {
- return _shape_create(SHAPE_RECTANGLE);
-}
-
-RID PhysicsServer2DSW::capsule_shape_create() {
- return _shape_create(SHAPE_CAPSULE);
-}
-
-RID PhysicsServer2DSW::convex_polygon_shape_create() {
- return _shape_create(SHAPE_CONVEX_POLYGON);
-}
-
-RID PhysicsServer2DSW::concave_polygon_shape_create() {
- return _shape_create(SHAPE_CONCAVE_POLYGON);
-}
-
-void PhysicsServer2DSW::shape_set_data(RID p_shape, const Variant &p_data) {
- Shape2DSW *shape = shape_owner.get_or_null(p_shape);
- ERR_FAIL_COND(!shape);
- shape->set_data(p_data);
-};
-
-void PhysicsServer2DSW::shape_set_custom_solver_bias(RID p_shape, real_t p_bias) {
- Shape2DSW *shape = shape_owner.get_or_null(p_shape);
- ERR_FAIL_COND(!shape);
- shape->set_custom_bias(p_bias);
-}
-
-PhysicsServer2D::ShapeType PhysicsServer2DSW::shape_get_type(RID p_shape) const {
- const Shape2DSW *shape = shape_owner.get_or_null(p_shape);
- ERR_FAIL_COND_V(!shape, SHAPE_CUSTOM);
- return shape->get_type();
-};
-
-Variant PhysicsServer2DSW::shape_get_data(RID p_shape) const {
- const Shape2DSW *shape = shape_owner.get_or_null(p_shape);
- ERR_FAIL_COND_V(!shape, Variant());
- ERR_FAIL_COND_V(!shape->is_configured(), Variant());
- return shape->get_data();
-};
-
-real_t PhysicsServer2DSW::shape_get_custom_solver_bias(RID p_shape) const {
- const Shape2DSW *shape = shape_owner.get_or_null(p_shape);
- ERR_FAIL_COND_V(!shape, 0);
- return shape->get_custom_bias();
-}
-
-void PhysicsServer2DSW::_shape_col_cbk(const Vector2 &p_point_A, const Vector2 &p_point_B, void *p_userdata) {
- CollCbkData *cbk = (CollCbkData *)p_userdata;
-
- if (cbk->max == 0) {
- return;
- }
-
- Vector2 rel_dir = (p_point_A - p_point_B);
- real_t rel_length2 = rel_dir.length_squared();
- if (cbk->valid_dir != Vector2()) {
- if (cbk->valid_depth < 10e20) {
- if (rel_length2 > cbk->valid_depth * cbk->valid_depth ||
- (rel_length2 > CMP_EPSILON && cbk->valid_dir.dot(rel_dir.normalized()) < CMP_EPSILON)) {
- cbk->invalid_by_dir++;
- return;
- }
- } else {
- if (rel_length2 > 0 && cbk->valid_dir.dot(rel_dir.normalized()) < CMP_EPSILON) {
- return;
- }
- }
- }
-
- if (cbk->amount == cbk->max) {
- //find least deep
- real_t min_depth = 1e20;
- int min_depth_idx = 0;
- for (int i = 0; i < cbk->amount; i++) {
- real_t d = cbk->ptr[i * 2 + 0].distance_squared_to(cbk->ptr[i * 2 + 1]);
- if (d < min_depth) {
- min_depth = d;
- min_depth_idx = i;
- }
- }
-
- if (rel_length2 < min_depth) {
- return;
- }
- cbk->ptr[min_depth_idx * 2 + 0] = p_point_A;
- cbk->ptr[min_depth_idx * 2 + 1] = p_point_B;
- cbk->passed++;
-
- } else {
- cbk->ptr[cbk->amount * 2 + 0] = p_point_A;
- cbk->ptr[cbk->amount * 2 + 1] = p_point_B;
- cbk->amount++;
- cbk->passed++;
- }
-}
-
-bool PhysicsServer2DSW::shape_collide(RID p_shape_A, const Transform2D &p_xform_A, const Vector2 &p_motion_A, RID p_shape_B, const Transform2D &p_xform_B, const Vector2 &p_motion_B, Vector2 *r_results, int p_result_max, int &r_result_count) {
- Shape2DSW *shape_A = shape_owner.get_or_null(p_shape_A);
- ERR_FAIL_COND_V(!shape_A, false);
- Shape2DSW *shape_B = shape_owner.get_or_null(p_shape_B);
- ERR_FAIL_COND_V(!shape_B, false);
-
- if (p_result_max == 0) {
- return CollisionSolver2DSW::solve(shape_A, p_xform_A, p_motion_A, shape_B, p_xform_B, p_motion_B, nullptr, nullptr);
- }
-
- CollCbkData cbk;
- cbk.max = p_result_max;
- cbk.amount = 0;
- cbk.passed = 0;
- cbk.ptr = r_results;
-
- bool res = CollisionSolver2DSW::solve(shape_A, p_xform_A, p_motion_A, shape_B, p_xform_B, p_motion_B, _shape_col_cbk, &cbk);
- r_result_count = cbk.amount;
- return res;
-}
-
-RID PhysicsServer2DSW::space_create() {
- Space2DSW *space = memnew(Space2DSW);
- RID id = space_owner.make_rid(space);
- space->set_self(id);
- RID area_id = area_create();
- Area2DSW *area = area_owner.get_or_null(area_id);
- ERR_FAIL_COND_V(!area, RID());
- space->set_default_area(area);
- area->set_space(space);
- area->set_priority(-1);
-
- return id;
-};
-
-void PhysicsServer2DSW::space_set_active(RID p_space, bool p_active) {
- Space2DSW *space = space_owner.get_or_null(p_space);
- ERR_FAIL_COND(!space);
- if (p_active) {
- active_spaces.insert(space);
- } else {
- active_spaces.erase(space);
- }
-}
-
-bool PhysicsServer2DSW::space_is_active(RID p_space) const {
- const Space2DSW *space = space_owner.get_or_null(p_space);
- ERR_FAIL_COND_V(!space, false);
-
- return active_spaces.has(space);
-}
-
-void PhysicsServer2DSW::space_set_param(RID p_space, SpaceParameter p_param, real_t p_value) {
- Space2DSW *space = space_owner.get_or_null(p_space);
- ERR_FAIL_COND(!space);
-
- space->set_param(p_param, p_value);
-}
-
-real_t PhysicsServer2DSW::space_get_param(RID p_space, SpaceParameter p_param) const {
- const Space2DSW *space = space_owner.get_or_null(p_space);
- ERR_FAIL_COND_V(!space, 0);
- return space->get_param(p_param);
-}
-
-void PhysicsServer2DSW::space_set_debug_contacts(RID p_space, int p_max_contacts) {
- Space2DSW *space = space_owner.get_or_null(p_space);
- ERR_FAIL_COND(!space);
- space->set_debug_contacts(p_max_contacts);
-}
-
-Vector<Vector2> PhysicsServer2DSW::space_get_contacts(RID p_space) const {
- Space2DSW *space = space_owner.get_or_null(p_space);
- ERR_FAIL_COND_V(!space, Vector<Vector2>());
- return space->get_debug_contacts();
-}
-
-int PhysicsServer2DSW::space_get_contact_count(RID p_space) const {
- Space2DSW *space = space_owner.get_or_null(p_space);
- ERR_FAIL_COND_V(!space, 0);
- return space->get_debug_contact_count();
-}
-
-PhysicsDirectSpaceState2D *PhysicsServer2DSW::space_get_direct_state(RID p_space) {
- Space2DSW *space = space_owner.get_or_null(p_space);
- ERR_FAIL_COND_V(!space, nullptr);
- ERR_FAIL_COND_V_MSG((using_threads && !doing_sync) || space->is_locked(), nullptr, "Space state is inaccessible right now, wait for iteration or physics process notification.");
-
- return space->get_direct_state();
-}
-
-RID PhysicsServer2DSW::area_create() {
- Area2DSW *area = memnew(Area2DSW);
- RID rid = area_owner.make_rid(area);
- area->set_self(rid);
- return rid;
-};
-
-void PhysicsServer2DSW::area_set_space(RID p_area, RID p_space) {
- Area2DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND(!area);
-
- Space2DSW *space = nullptr;
- if (p_space.is_valid()) {
- space = space_owner.get_or_null(p_space);
- ERR_FAIL_COND(!space);
- }
-
- if (area->get_space() == space) {
- return; //pointless
- }
-
- area->clear_constraints();
- area->set_space(space);
-};
-
-RID PhysicsServer2DSW::area_get_space(RID p_area) const {
- Area2DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND_V(!area, RID());
-
- Space2DSW *space = area->get_space();
- if (!space) {
- return RID();
- }
- return space->get_self();
-};
-
-void PhysicsServer2DSW::area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) {
- Area2DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND(!area);
-
- area->set_space_override_mode(p_mode);
-}
-
-PhysicsServer2D::AreaSpaceOverrideMode PhysicsServer2DSW::area_get_space_override_mode(RID p_area) const {
- const Area2DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND_V(!area, AREA_SPACE_OVERRIDE_DISABLED);
-
- return area->get_space_override_mode();
-}
-
-void PhysicsServer2DSW::area_add_shape(RID p_area, RID p_shape, const Transform2D &p_transform, bool p_disabled) {
- Area2DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND(!area);
-
- Shape2DSW *shape = shape_owner.get_or_null(p_shape);
- ERR_FAIL_COND(!shape);
-
- area->add_shape(shape, p_transform, p_disabled);
-}
-
-void PhysicsServer2DSW::area_set_shape(RID p_area, int p_shape_idx, RID p_shape) {
- Area2DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND(!area);
-
- Shape2DSW *shape = shape_owner.get_or_null(p_shape);
- ERR_FAIL_COND(!shape);
- ERR_FAIL_COND(!shape->is_configured());
-
- area->set_shape(p_shape_idx, shape);
-}
-
-void PhysicsServer2DSW::area_set_shape_transform(RID p_area, int p_shape_idx, const Transform2D &p_transform) {
- Area2DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND(!area);
-
- area->set_shape_transform(p_shape_idx, p_transform);
-}
-
-void PhysicsServer2DSW::area_set_shape_disabled(RID p_area, int p_shape, bool p_disabled) {
- Area2DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND(!area);
- ERR_FAIL_INDEX(p_shape, area->get_shape_count());
- FLUSH_QUERY_CHECK(area);
-
- area->set_shape_disabled(p_shape, p_disabled);
-}
-
-int PhysicsServer2DSW::area_get_shape_count(RID p_area) const {
- Area2DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND_V(!area, -1);
-
- return area->get_shape_count();
-}
-
-RID PhysicsServer2DSW::area_get_shape(RID p_area, int p_shape_idx) const {
- Area2DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND_V(!area, RID());
-
- Shape2DSW *shape = area->get_shape(p_shape_idx);
- ERR_FAIL_COND_V(!shape, RID());
-
- return shape->get_self();
-}
-
-Transform2D PhysicsServer2DSW::area_get_shape_transform(RID p_area, int p_shape_idx) const {
- Area2DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND_V(!area, Transform2D());
-
- return area->get_shape_transform(p_shape_idx);
-}
-
-void PhysicsServer2DSW::area_remove_shape(RID p_area, int p_shape_idx) {
- Area2DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND(!area);
-
- area->remove_shape(p_shape_idx);
-}
-
-void PhysicsServer2DSW::area_clear_shapes(RID p_area) {
- Area2DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND(!area);
-
- while (area->get_shape_count()) {
- area->remove_shape(0);
- }
-}
-
-void PhysicsServer2DSW::area_attach_object_instance_id(RID p_area, ObjectID p_id) {
- if (space_owner.owns(p_area)) {
- Space2DSW *space = space_owner.get_or_null(p_area);
- p_area = space->get_default_area()->get_self();
- }
- Area2DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND(!area);
- area->set_instance_id(p_id);
-}
-
-ObjectID PhysicsServer2DSW::area_get_object_instance_id(RID p_area) const {
- if (space_owner.owns(p_area)) {
- Space2DSW *space = space_owner.get_or_null(p_area);
- p_area = space->get_default_area()->get_self();
- }
- Area2DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND_V(!area, ObjectID());
- return area->get_instance_id();
-}
-
-void PhysicsServer2DSW::area_attach_canvas_instance_id(RID p_area, ObjectID p_id) {
- if (space_owner.owns(p_area)) {
- Space2DSW *space = space_owner.get_or_null(p_area);
- p_area = space->get_default_area()->get_self();
- }
- Area2DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND(!area);
- area->set_canvas_instance_id(p_id);
-}
-
-ObjectID PhysicsServer2DSW::area_get_canvas_instance_id(RID p_area) const {
- if (space_owner.owns(p_area)) {
- Space2DSW *space = space_owner.get_or_null(p_area);
- p_area = space->get_default_area()->get_self();
- }
- Area2DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND_V(!area, ObjectID());
- return area->get_canvas_instance_id();
-}
-
-void PhysicsServer2DSW::area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value) {
- if (space_owner.owns(p_area)) {
- Space2DSW *space = space_owner.get_or_null(p_area);
- p_area = space->get_default_area()->get_self();
- }
- Area2DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND(!area);
- area->set_param(p_param, p_value);
-};
-
-void PhysicsServer2DSW::area_set_transform(RID p_area, const Transform2D &p_transform) {
- Area2DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND(!area);
- area->set_transform(p_transform);
-};
-
-Variant PhysicsServer2DSW::area_get_param(RID p_area, AreaParameter p_param) const {
- if (space_owner.owns(p_area)) {
- Space2DSW *space = space_owner.get_or_null(p_area);
- p_area = space->get_default_area()->get_self();
- }
- Area2DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND_V(!area, Variant());
-
- return area->get_param(p_param);
-};
-
-Transform2D PhysicsServer2DSW::area_get_transform(RID p_area) const {
- Area2DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND_V(!area, Transform2D());
-
- return area->get_transform();
-};
-
-void PhysicsServer2DSW::area_set_pickable(RID p_area, bool p_pickable) {
- Area2DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND(!area);
- area->set_pickable(p_pickable);
-}
-
-void PhysicsServer2DSW::area_set_monitorable(RID p_area, bool p_monitorable) {
- Area2DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND(!area);
- FLUSH_QUERY_CHECK(area);
-
- area->set_monitorable(p_monitorable);
-}
-
-void PhysicsServer2DSW::area_set_collision_mask(RID p_area, uint32_t p_mask) {
- Area2DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND(!area);
-
- area->set_collision_mask(p_mask);
-}
-
-void PhysicsServer2DSW::area_set_collision_layer(RID p_area, uint32_t p_layer) {
- Area2DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND(!area);
-
- area->set_collision_layer(p_layer);
-}
-
-void PhysicsServer2DSW::area_set_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) {
- Area2DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND(!area);
-
- area->set_monitor_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method);
-}
-
-void PhysicsServer2DSW::area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) {
- Area2DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND(!area);
-
- area->set_area_monitor_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method);
-}
-
-/* BODY API */
-
-RID PhysicsServer2DSW::body_create() {
- Body2DSW *body = memnew(Body2DSW);
- RID rid = body_owner.make_rid(body);
- body->set_self(rid);
- return rid;
-}
-
-void PhysicsServer2DSW::body_set_space(RID p_body, RID p_space) {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
- Space2DSW *space = nullptr;
- if (p_space.is_valid()) {
- space = space_owner.get_or_null(p_space);
- ERR_FAIL_COND(!space);
- }
-
- if (body->get_space() == space) {
- return; //pointless
- }
-
- body->clear_constraint_list();
- body->set_space(space);
-};
-
-RID PhysicsServer2DSW::body_get_space(RID p_body) const {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!body, RID());
-
- Space2DSW *space = body->get_space();
- if (!space) {
- return RID();
- }
- return space->get_self();
-};
-
-void PhysicsServer2DSW::body_set_mode(RID p_body, BodyMode p_mode) {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
- FLUSH_QUERY_CHECK(body);
-
- body->set_mode(p_mode);
-};
-
-PhysicsServer2D::BodyMode PhysicsServer2DSW::body_get_mode(RID p_body) const {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!body, BODY_MODE_STATIC);
-
- return body->get_mode();
-};
-
-void PhysicsServer2DSW::body_add_shape(RID p_body, RID p_shape, const Transform2D &p_transform, bool p_disabled) {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- Shape2DSW *shape = shape_owner.get_or_null(p_shape);
- ERR_FAIL_COND(!shape);
-
- body->add_shape(shape, p_transform, p_disabled);
-}
-
-void PhysicsServer2DSW::body_set_shape(RID p_body, int p_shape_idx, RID p_shape) {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- Shape2DSW *shape = shape_owner.get_or_null(p_shape);
- ERR_FAIL_COND(!shape);
- ERR_FAIL_COND(!shape->is_configured());
-
- body->set_shape(p_shape_idx, shape);
-}
-
-void PhysicsServer2DSW::body_set_shape_transform(RID p_body, int p_shape_idx, const Transform2D &p_transform) {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- body->set_shape_transform(p_shape_idx, p_transform);
-}
-
-int PhysicsServer2DSW::body_get_shape_count(RID p_body) const {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!body, -1);
-
- return body->get_shape_count();
-}
-
-RID PhysicsServer2DSW::body_get_shape(RID p_body, int p_shape_idx) const {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!body, RID());
-
- Shape2DSW *shape = body->get_shape(p_shape_idx);
- ERR_FAIL_COND_V(!shape, RID());
-
- return shape->get_self();
-}
-
-Transform2D PhysicsServer2DSW::body_get_shape_transform(RID p_body, int p_shape_idx) const {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!body, Transform2D());
-
- return body->get_shape_transform(p_shape_idx);
-}
-
-void PhysicsServer2DSW::body_remove_shape(RID p_body, int p_shape_idx) {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- body->remove_shape(p_shape_idx);
-}
-
-void PhysicsServer2DSW::body_clear_shapes(RID p_body) {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- while (body->get_shape_count()) {
- body->remove_shape(0);
- }
-}
-
-void PhysicsServer2DSW::body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
- ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count());
- FLUSH_QUERY_CHECK(body);
-
- body->set_shape_disabled(p_shape_idx, p_disabled);
-}
-
-void PhysicsServer2DSW::body_set_shape_as_one_way_collision(RID p_body, int p_shape_idx, bool p_enable, real_t p_margin) {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
- ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count());
- FLUSH_QUERY_CHECK(body);
-
- body->set_shape_as_one_way_collision(p_shape_idx, p_enable, p_margin);
-}
-
-void PhysicsServer2DSW::body_set_continuous_collision_detection_mode(RID p_body, CCDMode p_mode) {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
- body->set_continuous_collision_detection_mode(p_mode);
-}
-
-PhysicsServer2DSW::CCDMode PhysicsServer2DSW::body_get_continuous_collision_detection_mode(RID p_body) const {
- const Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!body, CCD_MODE_DISABLED);
-
- return body->get_continuous_collision_detection_mode();
-}
-
-void PhysicsServer2DSW::body_attach_object_instance_id(RID p_body, ObjectID p_id) {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- body->set_instance_id(p_id);
-};
-
-ObjectID PhysicsServer2DSW::body_get_object_instance_id(RID p_body) const {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!body, ObjectID());
-
- return body->get_instance_id();
-};
-
-void PhysicsServer2DSW::body_attach_canvas_instance_id(RID p_body, ObjectID p_id) {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- body->set_canvas_instance_id(p_id);
-};
-
-ObjectID PhysicsServer2DSW::body_get_canvas_instance_id(RID p_body) const {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!body, ObjectID());
-
- return body->get_canvas_instance_id();
-};
-
-void PhysicsServer2DSW::body_set_collision_layer(RID p_body, uint32_t p_layer) {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
- body->set_collision_layer(p_layer);
-};
-
-uint32_t PhysicsServer2DSW::body_get_collision_layer(RID p_body) const {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!body, 0);
-
- return body->get_collision_layer();
-};
-
-void PhysicsServer2DSW::body_set_collision_mask(RID p_body, uint32_t p_mask) {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
- body->set_collision_mask(p_mask);
-};
-
-uint32_t PhysicsServer2DSW::body_get_collision_mask(RID p_body) const {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!body, 0);
-
- return body->get_collision_mask();
-};
-
-void PhysicsServer2DSW::body_set_param(RID p_body, BodyParameter p_param, const Variant &p_value) {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- body->set_param(p_param, p_value);
-};
-
-Variant PhysicsServer2DSW::body_get_param(RID p_body, BodyParameter p_param) const {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!body, 0);
-
- return body->get_param(p_param);
-};
-
-void PhysicsServer2DSW::body_reset_mass_properties(RID p_body) {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- return body->reset_mass_properties();
-}
-
-void PhysicsServer2DSW::body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- body->set_state(p_state, p_variant);
-};
-
-Variant PhysicsServer2DSW::body_get_state(RID p_body, BodyState p_state) const {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!body, Variant());
-
- return body->get_state(p_state);
-};
-
-void PhysicsServer2DSW::body_set_applied_force(RID p_body, const Vector2 &p_force) {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- body->set_applied_force(p_force);
- body->wakeup();
-};
-
-Vector2 PhysicsServer2DSW::body_get_applied_force(RID p_body) const {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!body, Vector2());
- return body->get_applied_force();
-};
-
-void PhysicsServer2DSW::body_set_applied_torque(RID p_body, real_t p_torque) {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- body->set_applied_torque(p_torque);
- body->wakeup();
-};
-
-real_t PhysicsServer2DSW::body_get_applied_torque(RID p_body) const {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!body, 0);
-
- return body->get_applied_torque();
-};
-
-void PhysicsServer2DSW::body_apply_central_impulse(RID p_body, const Vector2 &p_impulse) {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- body->apply_central_impulse(p_impulse);
- body->wakeup();
-}
-
-void PhysicsServer2DSW::body_apply_torque_impulse(RID p_body, real_t p_torque) {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- _update_shapes();
-
- body->apply_torque_impulse(p_torque);
- body->wakeup();
-}
-
-void PhysicsServer2DSW::body_apply_impulse(RID p_body, const Vector2 &p_impulse, const Vector2 &p_position) {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- _update_shapes();
-
- body->apply_impulse(p_impulse, p_position);
- body->wakeup();
-};
-
-void PhysicsServer2DSW::body_add_central_force(RID p_body, const Vector2 &p_force) {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- body->add_central_force(p_force);
- body->wakeup();
-};
-
-void PhysicsServer2DSW::body_add_force(RID p_body, const Vector2 &p_force, const Vector2 &p_position) {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- body->add_force(p_force, p_position);
- body->wakeup();
-};
-
-void PhysicsServer2DSW::body_add_torque(RID p_body, real_t p_torque) {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- body->add_torque(p_torque);
- body->wakeup();
-};
-
-void PhysicsServer2DSW::body_set_axis_velocity(RID p_body, const Vector2 &p_axis_velocity) {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- _update_shapes();
-
- Vector2 v = body->get_linear_velocity();
- Vector2 axis = p_axis_velocity.normalized();
- v -= axis * axis.dot(v);
- v += p_axis_velocity;
- body->set_linear_velocity(v);
- body->wakeup();
-};
-
-void PhysicsServer2DSW::body_add_collision_exception(RID p_body, RID p_body_b) {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- body->add_exception(p_body_b);
- body->wakeup();
-};
-
-void PhysicsServer2DSW::body_remove_collision_exception(RID p_body, RID p_body_b) {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- body->remove_exception(p_body_b);
- body->wakeup();
-};
-
-void PhysicsServer2DSW::body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions) {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- for (int i = 0; i < body->get_exceptions().size(); i++) {
- p_exceptions->push_back(body->get_exceptions()[i]);
- }
-};
-
-void PhysicsServer2DSW::body_set_contacts_reported_depth_threshold(RID p_body, real_t p_threshold) {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-};
-
-real_t PhysicsServer2DSW::body_get_contacts_reported_depth_threshold(RID p_body) const {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!body, 0);
- return 0;
-};
-
-void PhysicsServer2DSW::body_set_omit_force_integration(RID p_body, bool p_omit) {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- body->set_omit_force_integration(p_omit);
-};
-
-bool PhysicsServer2DSW::body_is_omitting_force_integration(RID p_body) const {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!body, false);
- return body->get_omit_force_integration();
-};
-
-void PhysicsServer2DSW::body_set_max_contacts_reported(RID p_body, int p_contacts) {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
- body->set_max_contacts_reported(p_contacts);
-}
-
-int PhysicsServer2DSW::body_get_max_contacts_reported(RID p_body) const {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!body, -1);
- return body->get_max_contacts_reported();
-}
-
-void PhysicsServer2DSW::body_set_state_sync_callback(RID p_body, void *p_instance, BodyStateCallback p_callback) {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
- body->set_state_sync_callback(p_instance, p_callback);
-}
-
-void PhysicsServer2DSW::body_set_force_integration_callback(RID p_body, const Callable &p_callable, const Variant &p_udata) {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
- body->set_force_integration_callback(p_callable, p_udata);
-}
-
-bool PhysicsServer2DSW::body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count) {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!body, false);
- ERR_FAIL_INDEX_V(p_body_shape, body->get_shape_count(), false);
-
- return shape_collide(body->get_shape(p_body_shape)->get_self(), body->get_transform() * body->get_shape_transform(p_body_shape), Vector2(), p_shape, p_shape_xform, p_motion, r_results, p_result_max, r_result_count);
-}
-
-void PhysicsServer2DSW::body_set_pickable(RID p_body, bool p_pickable) {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
- body->set_pickable(p_pickable);
-}
-
-bool PhysicsServer2DSW::body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result) {
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!body, false);
- ERR_FAIL_COND_V(!body->get_space(), false);
- ERR_FAIL_COND_V(body->get_space()->is_locked(), false);
-
- _update_shapes();
-
- return body->get_space()->test_body_motion(body, p_parameters, r_result);
-}
-
-PhysicsDirectBodyState2D *PhysicsServer2DSW::body_get_direct_state(RID p_body) {
- ERR_FAIL_COND_V_MSG((using_threads && !doing_sync), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification.");
-
- Body2DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!body, nullptr);
-
- ERR_FAIL_COND_V(!body->get_space(), nullptr);
- ERR_FAIL_COND_V_MSG(body->get_space()->is_locked(), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification.");
-
- return body->get_direct_state();
-}
-
-/* JOINT API */
-
-RID PhysicsServer2DSW::joint_create() {
- Joint2DSW *joint = memnew(Joint2DSW);
- RID joint_rid = joint_owner.make_rid(joint);
- joint->set_self(joint_rid);
- return joint_rid;
-}
-
-void PhysicsServer2DSW::joint_clear(RID p_joint) {
- Joint2DSW *joint = joint_owner.get_or_null(p_joint);
- if (joint->get_type() != JOINT_TYPE_MAX) {
- Joint2DSW *empty_joint = memnew(Joint2DSW);
- empty_joint->copy_settings_from(joint);
-
- joint_owner.replace(p_joint, empty_joint);
- memdelete(joint);
- }
-}
-
-void PhysicsServer2DSW::joint_set_param(RID p_joint, JointParam p_param, real_t p_value) {
- Joint2DSW *joint = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND(!joint);
-
- switch (p_param) {
- case JOINT_PARAM_BIAS:
- joint->set_bias(p_value);
- break;
- case JOINT_PARAM_MAX_BIAS:
- joint->set_max_bias(p_value);
- break;
- case JOINT_PARAM_MAX_FORCE:
- joint->set_max_force(p_value);
- break;
- }
-}
-
-real_t PhysicsServer2DSW::joint_get_param(RID p_joint, JointParam p_param) const {
- const Joint2DSW *joint = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND_V(!joint, -1);
-
- switch (p_param) {
- case JOINT_PARAM_BIAS:
- return joint->get_bias();
- break;
- case JOINT_PARAM_MAX_BIAS:
- return joint->get_max_bias();
- break;
- case JOINT_PARAM_MAX_FORCE:
- return joint->get_max_force();
- break;
- }
-
- return 0;
-}
-
-void PhysicsServer2DSW::joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) {
- Joint2DSW *joint = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND(!joint);
-
- joint->disable_collisions_between_bodies(p_disable);
-
- if (2 == joint->get_body_count()) {
- Body2DSW *body_a = *joint->get_body_ptr();
- Body2DSW *body_b = *(joint->get_body_ptr() + 1);
-
- if (p_disable) {
- body_add_collision_exception(body_a->get_self(), body_b->get_self());
- body_add_collision_exception(body_b->get_self(), body_a->get_self());
- } else {
- body_remove_collision_exception(body_a->get_self(), body_b->get_self());
- body_remove_collision_exception(body_b->get_self(), body_a->get_self());
- }
- }
-}
-
-bool PhysicsServer2DSW::joint_is_disabled_collisions_between_bodies(RID p_joint) const {
- const Joint2DSW *joint = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND_V(!joint, true);
-
- return joint->is_disabled_collisions_between_bodies();
-}
-
-void PhysicsServer2DSW::joint_make_pin(RID p_joint, const Vector2 &p_pos, RID p_body_a, RID p_body_b) {
- Body2DSW *A = body_owner.get_or_null(p_body_a);
- ERR_FAIL_COND(!A);
- Body2DSW *B = nullptr;
- if (body_owner.owns(p_body_b)) {
- B = body_owner.get_or_null(p_body_b);
- ERR_FAIL_COND(!B);
- }
-
- Joint2DSW *prev_joint = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND(prev_joint == nullptr);
-
- Joint2DSW *joint = memnew(PinJoint2DSW(p_pos, A, B));
-
- joint_owner.replace(p_joint, joint);
- joint->copy_settings_from(prev_joint);
- memdelete(prev_joint);
-}
-
-void PhysicsServer2DSW::joint_make_groove(RID p_joint, const Vector2 &p_a_groove1, const Vector2 &p_a_groove2, const Vector2 &p_b_anchor, RID p_body_a, RID p_body_b) {
- Body2DSW *A = body_owner.get_or_null(p_body_a);
- ERR_FAIL_COND(!A);
-
- Body2DSW *B = body_owner.get_or_null(p_body_b);
- ERR_FAIL_COND(!B);
-
- Joint2DSW *prev_joint = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND(prev_joint == nullptr);
-
- Joint2DSW *joint = memnew(GrooveJoint2DSW(p_a_groove1, p_a_groove2, p_b_anchor, A, B));
-
- joint_owner.replace(p_joint, joint);
- joint->copy_settings_from(prev_joint);
- memdelete(prev_joint);
-}
-
-void PhysicsServer2DSW::joint_make_damped_spring(RID p_joint, const Vector2 &p_anchor_a, const Vector2 &p_anchor_b, RID p_body_a, RID p_body_b) {
- Body2DSW *A = body_owner.get_or_null(p_body_a);
- ERR_FAIL_COND(!A);
-
- Body2DSW *B = body_owner.get_or_null(p_body_b);
- ERR_FAIL_COND(!B);
-
- Joint2DSW *prev_joint = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND(prev_joint == nullptr);
-
- Joint2DSW *joint = memnew(DampedSpringJoint2DSW(p_anchor_a, p_anchor_b, A, B));
-
- joint_owner.replace(p_joint, joint);
- joint->copy_settings_from(prev_joint);
- memdelete(prev_joint);
-}
-
-void PhysicsServer2DSW::pin_joint_set_param(RID p_joint, PinJointParam p_param, real_t p_value) {
- Joint2DSW *j = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND(!j);
- ERR_FAIL_COND(j->get_type() != JOINT_TYPE_PIN);
-
- PinJoint2DSW *pin_joint = static_cast<PinJoint2DSW *>(j);
- pin_joint->set_param(p_param, p_value);
-}
-
-real_t PhysicsServer2DSW::pin_joint_get_param(RID p_joint, PinJointParam p_param) const {
- Joint2DSW *j = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND_V(!j, 0);
- ERR_FAIL_COND_V(j->get_type() != JOINT_TYPE_PIN, 0);
-
- PinJoint2DSW *pin_joint = static_cast<PinJoint2DSW *>(j);
- return pin_joint->get_param(p_param);
-}
-
-void PhysicsServer2DSW::damped_spring_joint_set_param(RID p_joint, DampedSpringParam p_param, real_t p_value) {
- Joint2DSW *j = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND(!j);
- ERR_FAIL_COND(j->get_type() != JOINT_TYPE_DAMPED_SPRING);
-
- DampedSpringJoint2DSW *dsj = static_cast<DampedSpringJoint2DSW *>(j);
- dsj->set_param(p_param, p_value);
-}
-
-real_t PhysicsServer2DSW::damped_spring_joint_get_param(RID p_joint, DampedSpringParam p_param) const {
- Joint2DSW *j = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND_V(!j, 0);
- ERR_FAIL_COND_V(j->get_type() != JOINT_TYPE_DAMPED_SPRING, 0);
-
- DampedSpringJoint2DSW *dsj = static_cast<DampedSpringJoint2DSW *>(j);
- return dsj->get_param(p_param);
-}
-
-PhysicsServer2D::JointType PhysicsServer2DSW::joint_get_type(RID p_joint) const {
- Joint2DSW *joint = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND_V(!joint, JOINT_TYPE_PIN);
-
- return joint->get_type();
-}
-
-void PhysicsServer2DSW::free(RID p_rid) {
- _update_shapes(); // just in case
-
- if (shape_owner.owns(p_rid)) {
- Shape2DSW *shape = shape_owner.get_or_null(p_rid);
-
- while (shape->get_owners().size()) {
- ShapeOwner2DSW *so = shape->get_owners().front()->key();
- so->remove_shape(shape);
- }
-
- shape_owner.free(p_rid);
- memdelete(shape);
- } else if (body_owner.owns(p_rid)) {
- Body2DSW *body = body_owner.get_or_null(p_rid);
-
- /*
- if (body->get_state_query())
- _clear_query(body->get_state_query());
-
- if (body->get_direct_state_query())
- _clear_query(body->get_direct_state_query());
- */
-
- body_set_space(p_rid, RID());
-
- while (body->get_shape_count()) {
- body->remove_shape(0);
- }
-
- body_owner.free(p_rid);
- memdelete(body);
-
- } else if (area_owner.owns(p_rid)) {
- Area2DSW *area = area_owner.get_or_null(p_rid);
-
- /*
- if (area->get_monitor_query())
- _clear_query(area->get_monitor_query());
- */
-
- area->set_space(nullptr);
-
- while (area->get_shape_count()) {
- area->remove_shape(0);
- }
-
- area_owner.free(p_rid);
- memdelete(area);
- } else if (space_owner.owns(p_rid)) {
- Space2DSW *space = space_owner.get_or_null(p_rid);
-
- while (space->get_objects().size()) {
- CollisionObject2DSW *co = (CollisionObject2DSW *)space->get_objects().front()->get();
- co->set_space(nullptr);
- }
-
- active_spaces.erase(space);
- free(space->get_default_area()->get_self());
- space_owner.free(p_rid);
- memdelete(space);
- } else if (joint_owner.owns(p_rid)) {
- Joint2DSW *joint = joint_owner.get_or_null(p_rid);
-
- joint_owner.free(p_rid);
- memdelete(joint);
-
- } else {
- ERR_FAIL_MSG("Invalid ID.");
- }
-};
-
-void PhysicsServer2DSW::set_active(bool p_active) {
- active = p_active;
-};
-
-void PhysicsServer2DSW::set_collision_iterations(int p_iterations) {
- iterations = p_iterations;
-};
-
-void PhysicsServer2DSW::init() {
- doing_sync = false;
- iterations = 8; // 8?
- stepper = memnew(Step2DSW);
-};
-
-void PhysicsServer2DSW::step(real_t p_step) {
- if (!active) {
- return;
- }
-
- _update_shapes();
-
- island_count = 0;
- active_objects = 0;
- collision_pairs = 0;
- for (Set<const Space2DSW *>::Element *E = active_spaces.front(); E; E = E->next()) {
- stepper->step((Space2DSW *)E->get(), p_step, iterations);
- island_count += E->get()->get_island_count();
- active_objects += E->get()->get_active_objects();
- collision_pairs += E->get()->get_collision_pairs();
- }
-};
-
-void PhysicsServer2DSW::sync() {
- doing_sync = true;
-};
-
-void PhysicsServer2DSW::flush_queries() {
- if (!active) {
- return;
- }
-
- flushing_queries = true;
-
- uint64_t time_beg = OS::get_singleton()->get_ticks_usec();
-
- for (Set<const Space2DSW *>::Element *E = active_spaces.front(); E; E = E->next()) {
- Space2DSW *space = (Space2DSW *)E->get();
- space->call_queries();
- }
-
- flushing_queries = false;
-
- if (EngineDebugger::is_profiling("servers")) {
- uint64_t total_time[Space2DSW::ELAPSED_TIME_MAX];
- static const char *time_name[Space2DSW::ELAPSED_TIME_MAX] = {
- "integrate_forces",
- "generate_islands",
- "setup_constraints",
- "solve_constraints",
- "integrate_velocities"
- };
-
- for (int i = 0; i < Space2DSW::ELAPSED_TIME_MAX; i++) {
- total_time[i] = 0;
- }
-
- for (Set<const Space2DSW *>::Element *E = active_spaces.front(); E; E = E->next()) {
- for (int i = 0; i < Space2DSW::ELAPSED_TIME_MAX; i++) {
- total_time[i] += E->get()->get_elapsed_time(Space2DSW::ElapsedTime(i));
- }
- }
-
- Array values;
- values.resize(Space2DSW::ELAPSED_TIME_MAX * 2);
- for (int i = 0; i < Space2DSW::ELAPSED_TIME_MAX; i++) {
- values[i * 2 + 0] = time_name[i];
- values[i * 2 + 1] = USEC_TO_SEC(total_time[i]);
- }
- values.push_back("flush_queries");
- values.push_back(USEC_TO_SEC(OS::get_singleton()->get_ticks_usec() - time_beg));
-
- values.push_front("physics_2d");
- EngineDebugger::profiler_add_frame_data("servers", values);
- }
-}
-
-void PhysicsServer2DSW::end_sync() {
- doing_sync = false;
-}
-
-void PhysicsServer2DSW::finish() {
- memdelete(stepper);
-};
-
-void PhysicsServer2DSW::_update_shapes() {
- while (pending_shape_update_list.first()) {
- pending_shape_update_list.first()->self()->_shape_changed();
- pending_shape_update_list.remove(pending_shape_update_list.first());
- }
-}
-
-int PhysicsServer2DSW::get_process_info(ProcessInfo p_info) {
- switch (p_info) {
- case INFO_ACTIVE_OBJECTS: {
- return active_objects;
- } break;
- case INFO_COLLISION_PAIRS: {
- return collision_pairs;
- } break;
- case INFO_ISLAND_COUNT: {
- return island_count;
- } break;
- }
-
- return 0;
-}
-
-PhysicsServer2DSW *PhysicsServer2DSW::singletonsw = nullptr;
-
-PhysicsServer2DSW::PhysicsServer2DSW(bool p_using_threads) {
- singletonsw = this;
- BroadPhase2DSW::create_func = BroadPhase2DBVH::_create;
-
- using_threads = p_using_threads;
-};
diff --git a/servers/physics_2d/space_2d_sw.h b/servers/physics_2d/space_2d_sw.h
deleted file mode 100644
index 746b5c6c9a..0000000000
--- a/servers/physics_2d/space_2d_sw.h
+++ /dev/null
@@ -1,211 +0,0 @@
-/*************************************************************************/
-/* space_2d_sw.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 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 SPACE_2D_SW_H
-#define SPACE_2D_SW_H
-
-#include "area_2d_sw.h"
-#include "area_pair_2d_sw.h"
-#include "body_2d_sw.h"
-#include "body_pair_2d_sw.h"
-#include "broad_phase_2d_sw.h"
-#include "collision_object_2d_sw.h"
-#include "core/config/project_settings.h"
-#include "core/templates/hash_map.h"
-#include "core/typedefs.h"
-
-class PhysicsDirectSpaceState2DSW : public PhysicsDirectSpaceState2D {
- GDCLASS(PhysicsDirectSpaceState2DSW, PhysicsDirectSpaceState2D);
-
- int _intersect_point_impl(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_point, bool p_filter_by_canvas = false, ObjectID p_canvas_instance_id = ObjectID());
-
-public:
- Space2DSW *space = nullptr;
-
- virtual int intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false) override;
- virtual int intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_instance_id, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false) override;
- virtual bool intersect_ray(const Vector2 &p_from, const Vector2 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
- virtual int intersect_shape(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
- virtual bool cast_motion(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
- virtual bool collide_shape(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, Vector2 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
- virtual bool rest_info(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
-
- PhysicsDirectSpaceState2DSW() {}
-};
-
-class Space2DSW {
-public:
- enum ElapsedTime {
- ELAPSED_TIME_INTEGRATE_FORCES,
- ELAPSED_TIME_GENERATE_ISLANDS,
- ELAPSED_TIME_SETUP_CONSTRAINTS,
- ELAPSED_TIME_SOLVE_CONSTRAINTS,
- ELAPSED_TIME_INTEGRATE_VELOCITIES,
- ELAPSED_TIME_MAX
-
- };
-
-private:
- struct ExcludedShapeSW {
- Shape2DSW *local_shape = nullptr;
- const CollisionObject2DSW *against_object = nullptr;
- int against_shape_index = 0;
- };
-
- uint64_t elapsed_time[ELAPSED_TIME_MAX] = {};
-
- PhysicsDirectSpaceState2DSW *direct_access = nullptr;
- RID self;
-
- BroadPhase2DSW *broadphase;
- SelfList<Body2DSW>::List active_list;
- SelfList<Body2DSW>::List mass_properties_update_list;
- SelfList<Body2DSW>::List state_query_list;
- SelfList<Area2DSW>::List monitor_query_list;
- SelfList<Area2DSW>::List area_moved_list;
-
- static void *_broadphase_pair(CollisionObject2DSW *A, int p_subindex_A, CollisionObject2DSW *B, int p_subindex_B, void *p_self);
- static void _broadphase_unpair(CollisionObject2DSW *A, int p_subindex_A, CollisionObject2DSW *B, int p_subindex_B, void *p_data, void *p_self);
-
- Set<CollisionObject2DSW *> objects;
-
- Area2DSW *area = nullptr;
-
- real_t contact_recycle_radius = 1.0;
- real_t contact_max_separation = 1.5;
- real_t contact_max_allowed_penetration = 0.3;
- real_t constraint_bias = 0.2;
-
- enum {
- INTERSECTION_QUERY_MAX = 2048
- };
-
- CollisionObject2DSW *intersection_query_results[INTERSECTION_QUERY_MAX];
- int intersection_query_subindex_results[INTERSECTION_QUERY_MAX];
-
- real_t body_linear_velocity_sleep_threshold = 0.0;
- real_t body_angular_velocity_sleep_threshold = 0.0;
- real_t body_time_to_sleep = 0.0;
-
- bool locked = false;
-
- real_t last_step = 0.001;
-
- int island_count = 0;
- int active_objects = 0;
- int collision_pairs = 0;
-
- int _cull_aabb_for_body(Body2DSW *p_body, const Rect2 &p_aabb);
-
- Vector<Vector2> contact_debug;
- int contact_debug_count = 0;
-
- friend class PhysicsDirectSpaceState2DSW;
-
-public:
- _FORCE_INLINE_ void set_self(const RID &p_self) { self = p_self; }
- _FORCE_INLINE_ RID get_self() const { return self; }
-
- void set_default_area(Area2DSW *p_area) { area = p_area; }
- Area2DSW *get_default_area() const { return area; }
-
- const SelfList<Body2DSW>::List &get_active_body_list() const;
- void body_add_to_active_list(SelfList<Body2DSW> *p_body);
- void body_remove_from_active_list(SelfList<Body2DSW> *p_body);
- void body_add_to_mass_properties_update_list(SelfList<Body2DSW> *p_body);
- void body_remove_from_mass_properties_update_list(SelfList<Body2DSW> *p_body);
- void area_add_to_moved_list(SelfList<Area2DSW> *p_area);
- void area_remove_from_moved_list(SelfList<Area2DSW> *p_area);
- const SelfList<Area2DSW>::List &get_moved_area_list() const;
-
- void body_add_to_state_query_list(SelfList<Body2DSW> *p_body);
- void body_remove_from_state_query_list(SelfList<Body2DSW> *p_body);
-
- void area_add_to_monitor_query_list(SelfList<Area2DSW> *p_area);
- void area_remove_from_monitor_query_list(SelfList<Area2DSW> *p_area);
-
- BroadPhase2DSW *get_broadphase();
-
- void add_object(CollisionObject2DSW *p_object);
- void remove_object(CollisionObject2DSW *p_object);
- const Set<CollisionObject2DSW *> &get_objects() const;
-
- _FORCE_INLINE_ real_t get_contact_recycle_radius() const { return contact_recycle_radius; }
- _FORCE_INLINE_ real_t get_contact_max_separation() const { return contact_max_separation; }
- _FORCE_INLINE_ real_t get_contact_max_allowed_penetration() const { return contact_max_allowed_penetration; }
- _FORCE_INLINE_ real_t get_constraint_bias() const { return constraint_bias; }
- _FORCE_INLINE_ real_t get_body_linear_velocity_sleep_threshold() const { return body_linear_velocity_sleep_threshold; }
- _FORCE_INLINE_ real_t get_body_angular_velocity_sleep_threshold() const { return body_angular_velocity_sleep_threshold; }
- _FORCE_INLINE_ real_t get_body_time_to_sleep() const { return body_time_to_sleep; }
-
- void update();
- void setup();
- void call_queries();
-
- bool is_locked() const;
- void lock();
- void unlock();
-
- real_t get_last_step() const { return last_step; }
- void set_last_step(real_t p_step) { last_step = p_step; }
-
- void set_param(PhysicsServer2D::SpaceParameter p_param, real_t p_value);
- real_t get_param(PhysicsServer2D::SpaceParameter p_param) const;
-
- void set_island_count(int p_island_count) { island_count = p_island_count; }
- int get_island_count() const { return island_count; }
-
- void set_active_objects(int p_active_objects) { active_objects = p_active_objects; }
- int get_active_objects() const { return active_objects; }
-
- int get_collision_pairs() const { return collision_pairs; }
-
- bool test_body_motion(Body2DSW *p_body, const PhysicsServer2D::MotionParameters &p_parameters, PhysicsServer2D::MotionResult *r_result);
-
- void set_debug_contacts(int p_amount) { contact_debug.resize(p_amount); }
- _FORCE_INLINE_ bool is_debugging_contacts() const { return !contact_debug.is_empty(); }
- _FORCE_INLINE_ void add_debug_contact(const Vector2 &p_contact) {
- if (contact_debug_count < contact_debug.size()) {
- contact_debug.write[contact_debug_count++] = p_contact;
- }
- }
- _FORCE_INLINE_ Vector<Vector2> get_debug_contacts() { return contact_debug; }
- _FORCE_INLINE_ int get_debug_contact_count() { return contact_debug_count; }
-
- PhysicsDirectSpaceState2DSW *get_direct_state();
-
- void set_elapsed_time(ElapsedTime p_time, uint64_t p_msec) { elapsed_time[p_time] = p_msec; }
- uint64_t get_elapsed_time(ElapsedTime p_time) const { return elapsed_time[p_time]; }
-
- Space2DSW();
- ~Space2DSW();
-};
-
-#endif // SPACE_2D_SW_H
diff --git a/servers/physics_3d/body_direct_state_3d_sw.cpp b/servers/physics_3d/body_direct_state_3d_sw.cpp
deleted file mode 100644
index d61a6ac8e4..0000000000
--- a/servers/physics_3d/body_direct_state_3d_sw.cpp
+++ /dev/null
@@ -1,190 +0,0 @@
-/*************************************************************************/
-/* body_direct_state_3d_sw.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 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 "body_direct_state_3d_sw.h"
-
-#include "body_3d_sw.h"
-#include "space_3d_sw.h"
-
-Vector3 PhysicsDirectBodyState3DSW::get_total_gravity() const {
- return body->gravity;
-}
-
-real_t PhysicsDirectBodyState3DSW::get_total_angular_damp() const {
- return body->area_angular_damp;
-}
-
-real_t PhysicsDirectBodyState3DSW::get_total_linear_damp() const {
- return body->area_linear_damp;
-}
-
-Vector3 PhysicsDirectBodyState3DSW::get_center_of_mass() const {
- return body->get_center_of_mass();
-}
-
-Basis PhysicsDirectBodyState3DSW::get_principal_inertia_axes() const {
- return body->get_principal_inertia_axes();
-}
-
-real_t PhysicsDirectBodyState3DSW::get_inverse_mass() const {
- return body->get_inv_mass();
-}
-
-Vector3 PhysicsDirectBodyState3DSW::get_inverse_inertia() const {
- return body->get_inv_inertia();
-}
-
-Basis PhysicsDirectBodyState3DSW::get_inverse_inertia_tensor() const {
- return body->get_inv_inertia_tensor();
-}
-
-void PhysicsDirectBodyState3DSW::set_linear_velocity(const Vector3 &p_velocity) {
- body->wakeup();
- body->set_linear_velocity(p_velocity);
-}
-
-Vector3 PhysicsDirectBodyState3DSW::get_linear_velocity() const {
- return body->get_linear_velocity();
-}
-
-void PhysicsDirectBodyState3DSW::set_angular_velocity(const Vector3 &p_velocity) {
- body->wakeup();
- body->set_angular_velocity(p_velocity);
-}
-
-Vector3 PhysicsDirectBodyState3DSW::get_angular_velocity() const {
- return body->get_angular_velocity();
-}
-
-void PhysicsDirectBodyState3DSW::set_transform(const Transform3D &p_transform) {
- body->set_state(PhysicsServer3D::BODY_STATE_TRANSFORM, p_transform);
-}
-
-Transform3D PhysicsDirectBodyState3DSW::get_transform() const {
- return body->get_transform();
-}
-
-Vector3 PhysicsDirectBodyState3DSW::get_velocity_at_local_position(const Vector3 &p_position) const {
- return body->get_velocity_in_local_point(p_position);
-}
-
-void PhysicsDirectBodyState3DSW::add_central_force(const Vector3 &p_force) {
- body->wakeup();
- body->add_central_force(p_force);
-}
-
-void PhysicsDirectBodyState3DSW::add_force(const Vector3 &p_force, const Vector3 &p_position) {
- body->wakeup();
- body->add_force(p_force, p_position);
-}
-
-void PhysicsDirectBodyState3DSW::add_torque(const Vector3 &p_torque) {
- body->wakeup();
- body->add_torque(p_torque);
-}
-
-void PhysicsDirectBodyState3DSW::apply_central_impulse(const Vector3 &p_impulse) {
- body->wakeup();
- body->apply_central_impulse(p_impulse);
-}
-
-void PhysicsDirectBodyState3DSW::apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position) {
- body->wakeup();
- body->apply_impulse(p_impulse, p_position);
-}
-
-void PhysicsDirectBodyState3DSW::apply_torque_impulse(const Vector3 &p_impulse) {
- body->wakeup();
- body->apply_torque_impulse(p_impulse);
-}
-
-void PhysicsDirectBodyState3DSW::set_sleep_state(bool p_sleep) {
- body->set_active(!p_sleep);
-}
-
-bool PhysicsDirectBodyState3DSW::is_sleeping() const {
- return !body->is_active();
-}
-
-int PhysicsDirectBodyState3DSW::get_contact_count() const {
- return body->contact_count;
-}
-
-Vector3 PhysicsDirectBodyState3DSW::get_contact_local_position(int p_contact_idx) const {
- ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector3());
- return body->contacts[p_contact_idx].local_pos;
-}
-
-Vector3 PhysicsDirectBodyState3DSW::get_contact_local_normal(int p_contact_idx) const {
- ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector3());
- return body->contacts[p_contact_idx].local_normal;
-}
-
-real_t PhysicsDirectBodyState3DSW::get_contact_impulse(int p_contact_idx) const {
- return 0.0f; // Only implemented for bullet
-}
-
-int PhysicsDirectBodyState3DSW::get_contact_local_shape(int p_contact_idx) const {
- ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, -1);
- return body->contacts[p_contact_idx].local_shape;
-}
-
-RID PhysicsDirectBodyState3DSW::get_contact_collider(int p_contact_idx) const {
- ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, RID());
- return body->contacts[p_contact_idx].collider;
-}
-
-Vector3 PhysicsDirectBodyState3DSW::get_contact_collider_position(int p_contact_idx) const {
- ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector3());
- return body->contacts[p_contact_idx].collider_pos;
-}
-
-ObjectID PhysicsDirectBodyState3DSW::get_contact_collider_id(int p_contact_idx) const {
- ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, ObjectID());
- return body->contacts[p_contact_idx].collider_instance_id;
-}
-
-int PhysicsDirectBodyState3DSW::get_contact_collider_shape(int p_contact_idx) const {
- ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, 0);
- return body->contacts[p_contact_idx].collider_shape;
-}
-
-Vector3 PhysicsDirectBodyState3DSW::get_contact_collider_velocity_at_position(int p_contact_idx) const {
- ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector3());
- return body->contacts[p_contact_idx].collider_velocity_at_pos;
-}
-
-PhysicsDirectSpaceState3D *PhysicsDirectBodyState3DSW::get_space_state() {
- return body->get_space()->get_direct_state();
-}
-
-real_t PhysicsDirectBodyState3DSW::get_step() const {
- return body->get_space()->get_last_step();
-}
diff --git a/servers/physics_3d/gjk_epa.cpp b/servers/physics_3d/gjk_epa.cpp
index a1dbdd0a70..928ffe0980 100644
--- a/servers/physics_3d/gjk_epa.cpp
+++ b/servers/physics_3d/gjk_epa.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -105,7 +105,7 @@ typedef unsigned char U1;
// MinkowskiDiff
struct MinkowskiDiff {
- const Shape3DSW* m_shapes[2];
+ const GodotShape3D* m_shapes[2];
Transform3D transform_A;
Transform3D transform_B;
@@ -113,10 +113,10 @@ struct MinkowskiDiff {
real_t margin_A = 0.0;
real_t margin_B = 0.0;
- Vector3 (*get_support)(const Shape3DSW*, const Vector3&, real_t);
+ Vector3 (*get_support)(const GodotShape3D*, const Vector3&, real_t);
- void Initialize(const Shape3DSW* shape0, const Transform3D& wtrs0, const real_t margin0,
- const Shape3DSW* shape1, const Transform3D& wtrs1, const real_t margin1) {
+ void Initialize(const GodotShape3D* shape0, const Transform3D& wtrs0, const real_t margin0,
+ const GodotShape3D* shape1, const Transform3D& wtrs1, const real_t margin1) {
m_shapes[0] = shape0;
m_shapes[1] = shape1;
transform_A = wtrs0;
@@ -131,11 +131,11 @@ struct MinkowskiDiff {
}
}
- static Vector3 get_support_without_margin(const Shape3DSW* p_shape, const Vector3& p_dir, real_t p_margin) {
+ static Vector3 get_support_without_margin(const GodotShape3D* p_shape, const Vector3& p_dir, real_t p_margin) {
return p_shape->get_support(p_dir.normalized());
}
- static Vector3 get_support_with_margin(const Shape3DSW* p_shape, const Vector3& p_dir, real_t p_margin) {
+ static Vector3 get_support_with_margin(const GodotShape3D* p_shape, const Vector3& p_dir, real_t p_margin) {
Vector3 local_dir_norm = p_dir;
if (local_dir_norm.length_squared() < CMP_EPSILON2) {
local_dir_norm = Vector3(-1.0, -1.0, -1.0);
@@ -862,8 +862,8 @@ struct GJK
};
//
- static void Initialize( const Shape3DSW* shape0, const Transform3D& wtrs0, real_t margin0,
- const Shape3DSW* shape1, const Transform3D& wtrs1, real_t margin1,
+ static void Initialize( const GodotShape3D* shape0, const Transform3D& wtrs0, real_t margin0,
+ const GodotShape3D* shape1, const Transform3D& wtrs1, real_t margin1,
sResults& results,
tShape& shape)
{
@@ -884,10 +884,10 @@ struct GJK
//
//
-bool Distance( const Shape3DSW* shape0,
+bool Distance( const GodotShape3D* shape0,
const Transform3D& wtrs0,
real_t margin0,
- const Shape3DSW* shape1,
+ const GodotShape3D* shape1,
const Transform3D& wtrs1,
real_t margin1,
const Vector3& guess,
@@ -925,10 +925,10 @@ bool Distance( const Shape3DSW* shape0,
//
-bool Penetration( const Shape3DSW* shape0,
+bool Penetration( const GodotShape3D* shape0,
const Transform3D& wtrs0,
real_t margin0,
- const Shape3DSW* shape1,
+ const GodotShape3D* shape1,
const Transform3D& wtrs1,
real_t margin1,
const Vector3& guess,
@@ -993,7 +993,7 @@ bool Penetration( const Shape3DSW* shape0,
/* clang-format on */
-bool gjk_epa_calculate_distance(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, Vector3 &r_result_A, Vector3 &r_result_B) {
+bool gjk_epa_calculate_distance(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, Vector3 &r_result_A, Vector3 &r_result_B) {
GjkEpa2::sResults res;
if (GjkEpa2::Distance(p_shape_A, p_transform_A, 0.0, p_shape_B, p_transform_B, 0.0, p_transform_B.origin - p_transform_A.origin, res)) {
@@ -1005,7 +1005,7 @@ bool gjk_epa_calculate_distance(const Shape3DSW *p_shape_A, const Transform3D &p
return false;
}
-bool gjk_epa_calculate_penetration(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CollisionSolver3DSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap, real_t p_margin_A, real_t p_margin_B) {
+bool gjk_epa_calculate_penetration(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, GodotCollisionSolver3D::CallbackResult p_result_callback, void *p_userdata, bool p_swap, real_t p_margin_A, real_t p_margin_B) {
GjkEpa2::sResults res;
if (GjkEpa2::Penetration(p_shape_A, p_transform_A, p_margin_A, p_shape_B, p_transform_B, p_margin_B, p_transform_B.origin - p_transform_A.origin, res)) {
diff --git a/servers/physics_3d/gjk_epa.h b/servers/physics_3d/gjk_epa.h
index 69e85d2bc0..01a47f222e 100644
--- a/servers/physics_3d/gjk_epa.h
+++ b/servers/physics_3d/gjk_epa.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -31,10 +31,10 @@
#ifndef GJK_EPA_H
#define GJK_EPA_H
-#include "collision_solver_3d_sw.h"
-#include "shape_3d_sw.h"
+#include "godot_collision_solver_3d.h"
+#include "godot_shape_3d.h"
-bool gjk_epa_calculate_penetration(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CollisionSolver3DSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap = false, real_t p_margin_A = 0.0, real_t p_margin_B = 0.0);
-bool gjk_epa_calculate_distance(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, Vector3 &r_result_A, Vector3 &r_result_B);
+bool gjk_epa_calculate_penetration(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, GodotCollisionSolver3D::CallbackResult p_result_callback, void *p_userdata, bool p_swap = false, real_t p_margin_A = 0.0, real_t p_margin_B = 0.0);
+bool gjk_epa_calculate_distance(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, Vector3 &r_result_A, Vector3 &r_result_B);
#endif
diff --git a/servers/physics_3d/area_3d_sw.cpp b/servers/physics_3d/godot_area_3d.cpp
index 630ab7e229..e7df23d0d8 100644
--- a/servers/physics_3d/area_3d_sw.cpp
+++ b/servers/physics_3d/godot_area_3d.cpp
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* area_3d_sw.cpp */
+/* godot_area_3d.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,39 +28,40 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "area_3d_sw.h"
-#include "body_3d_sw.h"
-#include "soft_body_3d_sw.h"
-#include "space_3d_sw.h"
+#include "godot_area_3d.h"
-Area3DSW::BodyKey::BodyKey(SoftBody3DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape) {
+#include "godot_body_3d.h"
+#include "godot_soft_body_3d.h"
+#include "godot_space_3d.h"
+
+GodotArea3D::BodyKey::BodyKey(GodotSoftBody3D *p_body, uint32_t p_body_shape, uint32_t p_area_shape) {
rid = p_body->get_self();
instance_id = p_body->get_instance_id();
body_shape = p_body_shape;
area_shape = p_area_shape;
}
-Area3DSW::BodyKey::BodyKey(Body3DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape) {
+GodotArea3D::BodyKey::BodyKey(GodotBody3D *p_body, uint32_t p_body_shape, uint32_t p_area_shape) {
rid = p_body->get_self();
instance_id = p_body->get_instance_id();
body_shape = p_body_shape;
area_shape = p_area_shape;
}
-Area3DSW::BodyKey::BodyKey(Area3DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape) {
+GodotArea3D::BodyKey::BodyKey(GodotArea3D *p_body, uint32_t p_body_shape, uint32_t p_area_shape) {
rid = p_body->get_self();
instance_id = p_body->get_instance_id();
body_shape = p_body_shape;
area_shape = p_area_shape;
}
-void Area3DSW::_shapes_changed() {
+void GodotArea3D::_shapes_changed() {
if (!moved_list.in_list() && get_space()) {
get_space()->area_add_to_moved_list(&moved_list);
}
}
-void Area3DSW::set_transform(const Transform3D &p_transform) {
+void GodotArea3D::set_transform(const Transform3D &p_transform) {
if (!moved_list.in_list() && get_space()) {
get_space()->area_add_to_moved_list(&moved_list);
}
@@ -69,7 +70,7 @@ void Area3DSW::set_transform(const Transform3D &p_transform) {
_set_inv_transform(p_transform.affine_inverse());
}
-void Area3DSW::set_space(Space3DSW *p_space) {
+void GodotArea3D::set_space(GodotSpace3D *p_space) {
if (get_space()) {
if (monitor_query_list.in_list()) {
get_space()->area_remove_from_monitor_query_list(&monitor_query_list);
@@ -85,16 +86,16 @@ void Area3DSW::set_space(Space3DSW *p_space) {
_set_space(p_space);
}
-void Area3DSW::set_monitor_callback(ObjectID p_id, const StringName &p_method) {
- if (p_id == monitor_callback_id) {
- monitor_callback_method = p_method;
+void GodotArea3D::set_monitor_callback(const Callable &p_callback) {
+ ObjectID id = p_callback.get_object_id();
+ if (id == monitor_callback.get_object_id()) {
+ monitor_callback = p_callback;
return;
}
_unregister_shapes();
- monitor_callback_id = p_id;
- monitor_callback_method = p_method;
+ monitor_callback = p_callback;
monitored_bodies.clear();
monitored_areas.clear();
@@ -106,16 +107,16 @@ void Area3DSW::set_monitor_callback(ObjectID p_id, const StringName &p_method) {
}
}
-void Area3DSW::set_area_monitor_callback(ObjectID p_id, const StringName &p_method) {
- if (p_id == area_monitor_callback_id) {
- area_monitor_callback_method = p_method;
+void GodotArea3D::set_area_monitor_callback(const Callable &p_callback) {
+ ObjectID id = p_callback.get_object_id();
+ if (id == area_monitor_callback.get_object_id()) {
+ area_monitor_callback = p_callback;
return;
}
_unregister_shapes();
- area_monitor_callback_id = p_id;
- area_monitor_callback_method = p_method;
+ area_monitor_callback = p_callback;
monitored_bodies.clear();
monitored_areas.clear();
@@ -127,18 +128,21 @@ void Area3DSW::set_area_monitor_callback(ObjectID p_id, const StringName &p_meth
}
}
-void Area3DSW::set_space_override_mode(PhysicsServer3D::AreaSpaceOverrideMode p_mode) {
- bool do_override = p_mode != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED;
- if (do_override == (space_override_mode != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED)) {
+void GodotArea3D::_set_space_override_mode(PhysicsServer3D::AreaSpaceOverrideMode &r_mode, PhysicsServer3D::AreaSpaceOverrideMode p_new_mode) {
+ bool do_override = p_new_mode != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED;
+ if (do_override == (r_mode != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED)) {
return;
}
_unregister_shapes();
- space_override_mode = p_mode;
+ r_mode = p_new_mode;
_shape_changed();
}
-void Area3DSW::set_param(PhysicsServer3D::AreaParameter p_param, const Variant &p_value) {
+void GodotArea3D::set_param(PhysicsServer3D::AreaParameter p_param, const Variant &p_value) {
switch (p_param) {
+ case PhysicsServer3D::AREA_PARAM_GRAVITY_OVERRIDE_MODE:
+ _set_space_override_mode(gravity_override_mode, (PhysicsServer3D::AreaSpaceOverrideMode)(int)p_value);
+ break;
case PhysicsServer3D::AREA_PARAM_GRAVITY:
gravity = p_value;
break;
@@ -154,9 +158,15 @@ void Area3DSW::set_param(PhysicsServer3D::AreaParameter p_param, const Variant &
case PhysicsServer3D::AREA_PARAM_GRAVITY_POINT_ATTENUATION:
point_attenuation = p_value;
break;
+ case PhysicsServer3D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE:
+ _set_space_override_mode(linear_damping_override_mode, (PhysicsServer3D::AreaSpaceOverrideMode)(int)p_value);
+ break;
case PhysicsServer3D::AREA_PARAM_LINEAR_DAMP:
linear_damp = p_value;
break;
+ case PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE:
+ _set_space_override_mode(angular_damping_override_mode, (PhysicsServer3D::AreaSpaceOverrideMode)(int)p_value);
+ break;
case PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP:
angular_damp = p_value;
break;
@@ -180,8 +190,10 @@ void Area3DSW::set_param(PhysicsServer3D::AreaParameter p_param, const Variant &
}
}
-Variant Area3DSW::get_param(PhysicsServer3D::AreaParameter p_param) const {
+Variant GodotArea3D::get_param(PhysicsServer3D::AreaParameter p_param) const {
switch (p_param) {
+ case PhysicsServer3D::AREA_PARAM_GRAVITY_OVERRIDE_MODE:
+ return gravity_override_mode;
case PhysicsServer3D::AREA_PARAM_GRAVITY:
return gravity;
case PhysicsServer3D::AREA_PARAM_GRAVITY_VECTOR:
@@ -192,8 +204,12 @@ Variant Area3DSW::get_param(PhysicsServer3D::AreaParameter p_param) const {
return gravity_distance_scale;
case PhysicsServer3D::AREA_PARAM_GRAVITY_POINT_ATTENUATION:
return point_attenuation;
+ case PhysicsServer3D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE:
+ return linear_damping_override_mode;
case PhysicsServer3D::AREA_PARAM_LINEAR_DAMP:
return linear_damp;
+ case PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE:
+ return angular_damping_override_mode;
case PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP:
return angular_damp;
case PhysicsServer3D::AREA_PARAM_PRIORITY:
@@ -211,7 +227,7 @@ Variant Area3DSW::get_param(PhysicsServer3D::AreaParameter p_param) const {
return Variant();
}
-void Area3DSW::_queue_monitor_update() {
+void GodotArea3D::_queue_monitor_update() {
ERR_FAIL_COND(!get_space());
if (!monitor_query_list.in_list()) {
@@ -219,92 +235,91 @@ void Area3DSW::_queue_monitor_update() {
}
}
-void Area3DSW::set_monitorable(bool p_monitorable) {
+void GodotArea3D::set_monitorable(bool p_monitorable) {
if (monitorable == p_monitorable) {
return;
}
monitorable = p_monitorable;
_set_static(!monitorable);
+ _shapes_changed();
}
-void Area3DSW::call_queries() {
- if (monitor_callback_id.is_valid() && !monitored_bodies.is_empty()) {
- Variant res[5];
- Variant *resptr[5];
- for (int i = 0; i < 5; i++) {
- resptr[i] = &res[i];
- }
+void GodotArea3D::call_queries() {
+ if (!monitor_callback.is_null() && !monitored_bodies.is_empty()) {
+ if (monitor_callback.is_valid()) {
+ Variant res[5];
+ Variant *resptr[5];
+ for (int i = 0; i < 5; i++) {
+ resptr[i] = &res[i];
+ }
- Object *obj = ObjectDB::get_instance(monitor_callback_id);
- if (!obj) {
- monitored_bodies.clear();
- monitor_callback_id = ObjectID();
- return;
- }
+ for (Map<BodyKey, BodyState>::Element *E = monitored_bodies.front(); E;) {
+ if (E->get().state == 0) { // Nothing happened
+ Map<BodyKey, BodyState>::Element *next = E->next();
+ monitored_bodies.erase(E);
+ E = next;
+ continue;
+ }
+
+ res[0] = E->get().state > 0 ? PhysicsServer3D::AREA_BODY_ADDED : PhysicsServer3D::AREA_BODY_REMOVED;
+ res[1] = E->key().rid;
+ res[2] = E->key().instance_id;
+ res[3] = E->key().body_shape;
+ res[4] = E->key().area_shape;
- for (Map<BodyKey, BodyState>::Element *E = monitored_bodies.front(); E;) {
- if (E->get().state == 0) { // Nothing happened
Map<BodyKey, BodyState>::Element *next = E->next();
monitored_bodies.erase(E);
E = next;
- continue;
- }
- res[0] = E->get().state > 0 ? PhysicsServer3D::AREA_BODY_ADDED : PhysicsServer3D::AREA_BODY_REMOVED;
- res[1] = E->key().rid;
- res[2] = E->key().instance_id;
- res[3] = E->key().body_shape;
- res[4] = E->key().area_shape;
-
- Map<BodyKey, BodyState>::Element *next = E->next();
- monitored_bodies.erase(E);
- E = next;
-
- Callable::CallError ce;
- obj->call(monitor_callback_method, (const Variant **)resptr, 5, ce);
+ Callable::CallError ce;
+ Variant ret;
+ monitor_callback.call((const Variant **)resptr, 5, ret, ce);
+ }
+ } else {
+ monitored_bodies.clear();
+ monitor_callback = Callable();
}
}
- if (area_monitor_callback_id.is_valid() && !monitored_areas.is_empty()) {
- Variant res[5];
- Variant *resptr[5];
- for (int i = 0; i < 5; i++) {
- resptr[i] = &res[i];
- }
+ if (!area_monitor_callback.is_null() && !monitored_areas.is_empty()) {
+ if (area_monitor_callback.is_valid()) {
+ Variant res[5];
+ Variant *resptr[5];
+ for (int i = 0; i < 5; i++) {
+ resptr[i] = &res[i];
+ }
- Object *obj = ObjectDB::get_instance(area_monitor_callback_id);
- if (!obj) {
- monitored_areas.clear();
- area_monitor_callback_id = ObjectID();
- return;
- }
+ for (Map<BodyKey, BodyState>::Element *E = monitored_areas.front(); E;) {
+ if (E->get().state == 0) { // Nothing happened
+ Map<BodyKey, BodyState>::Element *next = E->next();
+ monitored_areas.erase(E);
+ E = next;
+ continue;
+ }
+
+ res[0] = E->get().state > 0 ? PhysicsServer3D::AREA_BODY_ADDED : PhysicsServer3D::AREA_BODY_REMOVED;
+ res[1] = E->key().rid;
+ res[2] = E->key().instance_id;
+ res[3] = E->key().body_shape;
+ res[4] = E->key().area_shape;
- for (Map<BodyKey, BodyState>::Element *E = monitored_areas.front(); E;) {
- if (E->get().state == 0) { // Nothing happened
Map<BodyKey, BodyState>::Element *next = E->next();
monitored_areas.erase(E);
E = next;
- continue;
- }
-
- res[0] = E->get().state > 0 ? PhysicsServer3D::AREA_BODY_ADDED : PhysicsServer3D::AREA_BODY_REMOVED;
- res[1] = E->key().rid;
- res[2] = E->key().instance_id;
- res[3] = E->key().body_shape;
- res[4] = E->key().area_shape;
-
- Map<BodyKey, BodyState>::Element *next = E->next();
- monitored_areas.erase(E);
- E = next;
- Callable::CallError ce;
- obj->call(area_monitor_callback_method, (const Variant **)resptr, 5, ce);
+ Callable::CallError ce;
+ Variant ret;
+ area_monitor_callback.call((const Variant **)resptr, 5, ret, ce);
+ }
+ } else {
+ monitored_areas.clear();
+ area_monitor_callback = Callable();
}
}
}
-void Area3DSW::compute_gravity(const Vector3 &p_position, Vector3 &r_gravity) const {
+void GodotArea3D::compute_gravity(const Vector3 &p_position, Vector3 &r_gravity) const {
if (is_gravity_point()) {
const real_t gravity_distance_scale = get_gravity_distance_scale();
Vector3 v = get_transform().xform(get_gravity_vector()) - p_position;
@@ -324,13 +339,13 @@ void Area3DSW::compute_gravity(const Vector3 &p_position, Vector3 &r_gravity) co
}
}
-Area3DSW::Area3DSW() :
- CollisionObject3DSW(TYPE_AREA),
+GodotArea3D::GodotArea3D() :
+ GodotCollisionObject3D(TYPE_AREA),
monitor_query_list(this),
moved_list(this) {
_set_static(true); //areas are never active
set_ray_pickable(false);
}
-Area3DSW::~Area3DSW() {
+GodotArea3D::~GodotArea3D() {
}
diff --git a/servers/physics_3d/area_3d_sw.h b/servers/physics_3d/godot_area_3d.h
index af5c23949c..ce64fc802a 100644
--- a/servers/physics_3d/area_3d_sw.h
+++ b/servers/physics_3d/godot_area_3d.h
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* area_3d_sw.h */
+/* godot_area_3d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,20 +28,24 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AREA_SW_H
-#define AREA_SW_H
+#ifndef GODOT_AREA_3D_H
+#define GODOT_AREA_3D_H
+
+#include "godot_collision_object_3d.h"
-#include "collision_object_3d_sw.h"
#include "core/templates/self_list.h"
#include "servers/physics_server_3d.h"
-class Space3DSW;
-class Body3DSW;
-class SoftBody3DSW;
-class Constraint3DSW;
+class GodotSpace3D;
+class GodotBody3D;
+class GodotSoftBody3D;
+class GodotConstraint3D;
+
+class GodotArea3D : public GodotCollisionObject3D {
+ PhysicsServer3D::AreaSpaceOverrideMode gravity_override_mode = PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED;
+ PhysicsServer3D::AreaSpaceOverrideMode linear_damping_override_mode = PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED;
+ PhysicsServer3D::AreaSpaceOverrideMode angular_damping_override_mode = PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED;
-class Area3DSW : public CollisionObject3DSW {
- PhysicsServer3D::AreaSpaceOverrideMode space_override_mode = PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED;
real_t gravity = 9.80665;
Vector3 gravity_vector = Vector3(0, -1, 0);
bool gravity_is_point = false;
@@ -56,14 +60,11 @@ class Area3DSW : public CollisionObject3DSW {
int priority = 0;
bool monitorable = false;
- ObjectID monitor_callback_id;
- StringName monitor_callback_method;
-
- ObjectID area_monitor_callback_id;
- StringName area_monitor_callback_method;
+ Callable monitor_callback;
+ Callable area_monitor_callback;
- SelfList<Area3DSW> monitor_query_list;
- SelfList<Area3DSW> moved_list;
+ SelfList<GodotArea3D> monitor_query_list;
+ SelfList<GodotArea3D> moved_list;
struct BodyKey {
RID rid;
@@ -84,9 +85,9 @@ class Area3DSW : public CollisionObject3DSW {
}
_FORCE_INLINE_ BodyKey() {}
- BodyKey(SoftBody3DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape);
- BodyKey(Body3DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape);
- BodyKey(Area3DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape);
+ BodyKey(GodotSoftBody3D *p_body, uint32_t p_body_shape, uint32_t p_area_shape);
+ BodyKey(GodotBody3D *p_body, uint32_t p_body_shape, uint32_t p_area_shape);
+ BodyKey(GodotArea3D *p_body, uint32_t p_body_shape, uint32_t p_area_shape);
};
struct BodyState {
@@ -99,33 +100,32 @@ class Area3DSW : public CollisionObject3DSW {
Map<BodyKey, BodyState> monitored_bodies;
Map<BodyKey, BodyState> monitored_areas;
- Set<Constraint3DSW *> constraints;
+ Set<GodotConstraint3D *> constraints;
virtual void _shapes_changed();
void _queue_monitor_update();
+ void _set_space_override_mode(PhysicsServer3D::AreaSpaceOverrideMode &r_mode, PhysicsServer3D::AreaSpaceOverrideMode p_new_mode);
+
public:
- void set_monitor_callback(ObjectID p_id, const StringName &p_method);
- _FORCE_INLINE_ bool has_monitor_callback() const { return monitor_callback_id.is_valid(); }
+ void set_monitor_callback(const Callable &p_callback);
+ _FORCE_INLINE_ bool has_monitor_callback() const { return !monitor_callback.is_null(); }
- void set_area_monitor_callback(ObjectID p_id, const StringName &p_method);
- _FORCE_INLINE_ bool has_area_monitor_callback() const { return area_monitor_callback_id.is_valid(); }
+ void set_area_monitor_callback(const Callable &p_callback);
+ _FORCE_INLINE_ bool has_area_monitor_callback() const { return !area_monitor_callback.is_null(); }
- _FORCE_INLINE_ void add_body_to_query(Body3DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape);
- _FORCE_INLINE_ void remove_body_from_query(Body3DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape);
+ _FORCE_INLINE_ void add_body_to_query(GodotBody3D *p_body, uint32_t p_body_shape, uint32_t p_area_shape);
+ _FORCE_INLINE_ void remove_body_from_query(GodotBody3D *p_body, uint32_t p_body_shape, uint32_t p_area_shape);
- _FORCE_INLINE_ void add_soft_body_to_query(SoftBody3DSW *p_soft_body, uint32_t p_soft_body_shape, uint32_t p_area_shape);
- _FORCE_INLINE_ void remove_soft_body_from_query(SoftBody3DSW *p_soft_body, uint32_t p_soft_body_shape, uint32_t p_area_shape);
+ _FORCE_INLINE_ void add_soft_body_to_query(GodotSoftBody3D *p_soft_body, uint32_t p_soft_body_shape, uint32_t p_area_shape);
+ _FORCE_INLINE_ void remove_soft_body_from_query(GodotSoftBody3D *p_soft_body, uint32_t p_soft_body_shape, uint32_t p_area_shape);
- _FORCE_INLINE_ void add_area_to_query(Area3DSW *p_area, uint32_t p_area_shape, uint32_t p_self_shape);
- _FORCE_INLINE_ void remove_area_from_query(Area3DSW *p_area, uint32_t p_area_shape, uint32_t p_self_shape);
+ _FORCE_INLINE_ void add_area_to_query(GodotArea3D *p_area, uint32_t p_area_shape, uint32_t p_self_shape);
+ _FORCE_INLINE_ void remove_area_from_query(GodotArea3D *p_area, uint32_t p_area_shape, uint32_t p_self_shape);
void set_param(PhysicsServer3D::AreaParameter p_param, const Variant &p_value);
Variant get_param(PhysicsServer3D::AreaParameter p_param) const;
- void set_space_override_mode(PhysicsServer3D::AreaSpaceOverrideMode p_mode);
- PhysicsServer3D::AreaSpaceOverrideMode get_space_override_mode() const { return space_override_mode; }
-
_FORCE_INLINE_ void set_gravity(real_t p_gravity) { gravity = p_gravity; }
_FORCE_INLINE_ real_t get_gravity() const { return gravity; }
@@ -162,9 +162,9 @@ public:
_FORCE_INLINE_ void set_wind_direction(const Vector3 &p_wind_direction) { wind_direction = p_wind_direction; }
_FORCE_INLINE_ const Vector3 &get_wind_direction() const { return wind_direction; }
- _FORCE_INLINE_ void add_constraint(Constraint3DSW *p_constraint) { constraints.insert(p_constraint); }
- _FORCE_INLINE_ void remove_constraint(Constraint3DSW *p_constraint) { constraints.erase(p_constraint); }
- _FORCE_INLINE_ const Set<Constraint3DSW *> &get_constraints() const { return constraints; }
+ _FORCE_INLINE_ void add_constraint(GodotConstraint3D *p_constraint) { constraints.insert(p_constraint); }
+ _FORCE_INLINE_ void remove_constraint(GodotConstraint3D *p_constraint) { constraints.erase(p_constraint); }
+ _FORCE_INLINE_ const Set<GodotConstraint3D *> &get_constraints() const { return constraints; }
_FORCE_INLINE_ void clear_constraints() { constraints.clear(); }
void set_monitorable(bool p_monitorable);
@@ -172,17 +172,17 @@ public:
void set_transform(const Transform3D &p_transform);
- void set_space(Space3DSW *p_space);
+ void set_space(GodotSpace3D *p_space);
void call_queries();
void compute_gravity(const Vector3 &p_position, Vector3 &r_gravity) const;
- Area3DSW();
- ~Area3DSW();
+ GodotArea3D();
+ ~GodotArea3D();
};
-void Area3DSW::add_soft_body_to_query(SoftBody3DSW *p_soft_body, uint32_t p_soft_body_shape, uint32_t p_area_shape) {
+void GodotArea3D::add_soft_body_to_query(GodotSoftBody3D *p_soft_body, uint32_t p_soft_body_shape, uint32_t p_area_shape) {
BodyKey bk(p_soft_body, p_soft_body_shape, p_area_shape);
monitored_soft_bodies[bk].inc();
if (!monitor_query_list.in_list()) {
@@ -190,7 +190,7 @@ void Area3DSW::add_soft_body_to_query(SoftBody3DSW *p_soft_body, uint32_t p_soft
}
}
-void Area3DSW::remove_soft_body_from_query(SoftBody3DSW *p_soft_body, uint32_t p_soft_body_shape, uint32_t p_area_shape) {
+void GodotArea3D::remove_soft_body_from_query(GodotSoftBody3D *p_soft_body, uint32_t p_soft_body_shape, uint32_t p_area_shape) {
BodyKey bk(p_soft_body, p_soft_body_shape, p_area_shape);
monitored_soft_bodies[bk].dec();
if (!monitor_query_list.in_list()) {
@@ -198,7 +198,7 @@ void Area3DSW::remove_soft_body_from_query(SoftBody3DSW *p_soft_body, uint32_t p
}
}
-void Area3DSW::add_body_to_query(Body3DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape) {
+void GodotArea3D::add_body_to_query(GodotBody3D *p_body, uint32_t p_body_shape, uint32_t p_area_shape) {
BodyKey bk(p_body, p_body_shape, p_area_shape);
monitored_bodies[bk].inc();
if (!monitor_query_list.in_list()) {
@@ -206,7 +206,7 @@ void Area3DSW::add_body_to_query(Body3DSW *p_body, uint32_t p_body_shape, uint32
}
}
-void Area3DSW::remove_body_from_query(Body3DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape) {
+void GodotArea3D::remove_body_from_query(GodotBody3D *p_body, uint32_t p_body_shape, uint32_t p_area_shape) {
BodyKey bk(p_body, p_body_shape, p_area_shape);
monitored_bodies[bk].dec();
if (!monitor_query_list.in_list()) {
@@ -214,7 +214,7 @@ void Area3DSW::remove_body_from_query(Body3DSW *p_body, uint32_t p_body_shape, u
}
}
-void Area3DSW::add_area_to_query(Area3DSW *p_area, uint32_t p_area_shape, uint32_t p_self_shape) {
+void GodotArea3D::add_area_to_query(GodotArea3D *p_area, uint32_t p_area_shape, uint32_t p_self_shape) {
BodyKey bk(p_area, p_area_shape, p_self_shape);
monitored_areas[bk].inc();
if (!monitor_query_list.in_list()) {
@@ -222,7 +222,7 @@ void Area3DSW::add_area_to_query(Area3DSW *p_area, uint32_t p_area_shape, uint32
}
}
-void Area3DSW::remove_area_from_query(Area3DSW *p_area, uint32_t p_area_shape, uint32_t p_self_shape) {
+void GodotArea3D::remove_area_from_query(GodotArea3D *p_area, uint32_t p_area_shape, uint32_t p_self_shape) {
BodyKey bk(p_area, p_area_shape, p_self_shape);
monitored_areas[bk].dec();
if (!monitor_query_list.in_list()) {
@@ -231,15 +231,15 @@ void Area3DSW::remove_area_from_query(Area3DSW *p_area, uint32_t p_area_shape, u
}
struct AreaCMP {
- Area3DSW *area = nullptr;
+ GodotArea3D *area = nullptr;
int refCount = 0;
_FORCE_INLINE_ bool operator==(const AreaCMP &p_cmp) const { return area->get_self() == p_cmp.area->get_self(); }
_FORCE_INLINE_ bool operator<(const AreaCMP &p_cmp) const { return area->get_priority() < p_cmp.area->get_priority(); }
_FORCE_INLINE_ AreaCMP() {}
- _FORCE_INLINE_ AreaCMP(Area3DSW *p_area) {
+ _FORCE_INLINE_ AreaCMP(GodotArea3D *p_area) {
area = p_area;
refCount = 1;
}
};
-#endif // AREA__SW_H
+#endif // GODOT_AREA_3D_H
diff --git a/servers/physics_3d/area_pair_3d_sw.cpp b/servers/physics_3d/godot_area_pair_3d.cpp
index bf4f0035b4..a75cb74f60 100644
--- a/servers/physics_3d/area_pair_3d_sw.cpp
+++ b/servers/physics_3d/godot_area_pair_3d.cpp
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* area_pair_3d_sw.cpp */
+/* godot_area_pair_3d.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,20 +28,29 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "area_pair_3d_sw.h"
-#include "collision_solver_3d_sw.h"
+#include "godot_area_pair_3d.h"
-bool AreaPair3DSW::setup(real_t p_step) {
+#include "godot_collision_solver_3d.h"
+
+bool GodotAreaPair3D::setup(real_t p_step) {
bool result = false;
- if (area->collides_with(body) && CollisionSolver3DSW::solve_static(body->get_shape(body_shape), body->get_transform() * body->get_shape_transform(body_shape), area->get_shape(area_shape), area->get_transform() * area->get_shape_transform(area_shape), nullptr, this)) {
+ if (area->collides_with(body) && GodotCollisionSolver3D::solve_static(body->get_shape(body_shape), body->get_transform() * body->get_shape_transform(body_shape), area->get_shape(area_shape), area->get_transform() * area->get_shape_transform(area_shape), nullptr, this)) {
result = true;
}
process_collision = false;
+ has_space_override = false;
if (result != colliding) {
- if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) {
- process_collision = true;
- } else if (area->has_monitor_callback()) {
+ if ((int)area->get_param(PhysicsServer3D::AREA_PARAM_GRAVITY_OVERRIDE_MODE) != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) {
+ has_space_override = true;
+ } else if ((int)area->get_param(PhysicsServer3D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE) != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) {
+ has_space_override = true;
+ } else if ((int)area->get_param(PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE) != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) {
+ has_space_override = true;
+ }
+ process_collision = has_space_override;
+
+ if (area->has_monitor_callback()) {
process_collision = true;
}
@@ -51,13 +60,13 @@ bool AreaPair3DSW::setup(real_t p_step) {
return process_collision;
}
-bool AreaPair3DSW::pre_solve(real_t p_step) {
+bool GodotAreaPair3D::pre_solve(real_t p_step) {
if (!process_collision) {
return false;
}
if (colliding) {
- if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) {
+ if (has_space_override) {
body->add_area(area);
}
@@ -65,7 +74,7 @@ bool AreaPair3DSW::pre_solve(real_t p_step) {
area->add_body_to_query(body, body_shape, area_shape);
}
} else {
- if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) {
+ if (has_space_override) {
body->remove_area(area);
}
@@ -77,11 +86,11 @@ bool AreaPair3DSW::pre_solve(real_t p_step) {
return false; // Never do any post solving.
}
-void AreaPair3DSW::solve(real_t p_step) {
+void GodotAreaPair3D::solve(real_t p_step) {
// Nothing to do.
}
-AreaPair3DSW::AreaPair3DSW(Body3DSW *p_body, int p_body_shape, Area3DSW *p_area, int p_area_shape) {
+GodotAreaPair3D::GodotAreaPair3D(GodotBody3D *p_body, int p_body_shape, GodotArea3D *p_area, int p_area_shape) {
body = p_body;
area = p_area;
body_shape = p_body_shape;
@@ -93,9 +102,9 @@ AreaPair3DSW::AreaPair3DSW(Body3DSW *p_body, int p_body_shape, Area3DSW *p_area,
}
}
-AreaPair3DSW::~AreaPair3DSW() {
+GodotAreaPair3D::~GodotAreaPair3D() {
if (colliding) {
- if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) {
+ if (has_space_override) {
body->remove_area(area);
}
if (area->has_monitor_callback()) {
@@ -108,10 +117,10 @@ AreaPair3DSW::~AreaPair3DSW() {
////////////////////////////////////////////////////
-bool Area2Pair3DSW::setup(real_t p_step) {
+bool GodotArea2Pair3D::setup(real_t p_step) {
bool result_a = area_a->collides_with(area_b);
bool result_b = area_b->collides_with(area_a);
- if ((result_a || result_b) && !CollisionSolver3DSW::solve_static(area_a->get_shape(shape_a), area_a->get_transform() * area_a->get_shape_transform(shape_a), area_b->get_shape(shape_b), area_b->get_transform() * area_b->get_shape_transform(shape_b), nullptr, this)) {
+ if ((result_a || result_b) && !GodotCollisionSolver3D::solve_static(area_a->get_shape(shape_a), area_a->get_transform() * area_a->get_shape_transform(shape_a), area_b->get_shape(shape_b), area_b->get_transform() * area_b->get_shape_transform(shape_b), nullptr, this)) {
result_a = false;
result_b = false;
}
@@ -120,7 +129,7 @@ bool Area2Pair3DSW::setup(real_t p_step) {
process_collision_a = false;
if (result_a != colliding_a) {
- if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) {
+ if (area_a->has_area_monitor_callback() && area_b_monitorable) {
process_collision_a = true;
process_collision = true;
}
@@ -129,7 +138,7 @@ bool Area2Pair3DSW::setup(real_t p_step) {
process_collision_b = false;
if (result_b != colliding_b) {
- if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) {
+ if (area_b->has_area_monitor_callback() && area_a_monitorable) {
process_collision_b = true;
process_collision = true;
}
@@ -139,7 +148,7 @@ bool Area2Pair3DSW::setup(real_t p_step) {
return process_collision;
}
-bool Area2Pair3DSW::pre_solve(real_t p_step) {
+bool GodotArea2Pair3D::pre_solve(real_t p_step) {
if (process_collision_a) {
if (colliding_a) {
area_a->add_area_to_query(area_b, shape_b, shape_a);
@@ -159,28 +168,30 @@ bool Area2Pair3DSW::pre_solve(real_t p_step) {
return false; // Never do any post solving.
}
-void Area2Pair3DSW::solve(real_t p_step) {
+void GodotArea2Pair3D::solve(real_t p_step) {
// Nothing to do.
}
-Area2Pair3DSW::Area2Pair3DSW(Area3DSW *p_area_a, int p_shape_a, Area3DSW *p_area_b, int p_shape_b) {
+GodotArea2Pair3D::GodotArea2Pair3D(GodotArea3D *p_area_a, int p_shape_a, GodotArea3D *p_area_b, int p_shape_b) {
area_a = p_area_a;
area_b = p_area_b;
shape_a = p_shape_a;
shape_b = p_shape_b;
+ area_a_monitorable = area_a->is_monitorable();
+ area_b_monitorable = area_b->is_monitorable();
area_a->add_constraint(this);
area_b->add_constraint(this);
}
-Area2Pair3DSW::~Area2Pair3DSW() {
+GodotArea2Pair3D::~GodotArea2Pair3D() {
if (colliding_a) {
- if (area_a->has_area_monitor_callback()) {
+ if (area_a->has_area_monitor_callback() && area_b_monitorable) {
area_a->remove_area_from_query(area_b, shape_b, shape_a);
}
}
if (colliding_b) {
- if (area_b->has_area_monitor_callback()) {
+ if (area_b->has_area_monitor_callback() && area_a_monitorable) {
area_b->remove_area_from_query(area_a, shape_a, shape_b);
}
}
@@ -191,11 +202,11 @@ Area2Pair3DSW::~Area2Pair3DSW() {
////////////////////////////////////////////////////
-bool AreaSoftBodyPair3DSW::setup(real_t p_step) {
+bool GodotAreaSoftBodyPair3D::setup(real_t p_step) {
bool result = false;
if (
area->collides_with(soft_body) &&
- CollisionSolver3DSW::solve_static(
+ GodotCollisionSolver3D::solve_static(
soft_body->get_shape(soft_body_shape),
soft_body->get_transform() * soft_body->get_shape_transform(soft_body_shape),
area->get_shape(area_shape),
@@ -206,10 +217,15 @@ bool AreaSoftBodyPair3DSW::setup(real_t p_step) {
}
process_collision = false;
+ has_space_override = false;
if (result != colliding) {
- if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) {
- process_collision = true;
- } else if (area->has_monitor_callback()) {
+ if ((int)area->get_param(PhysicsServer3D::AREA_PARAM_GRAVITY_OVERRIDE_MODE) != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) {
+ has_space_override = true;
+ } else if (area->get_wind_force_magnitude() > CMP_EPSILON) {
+ has_space_override = true;
+ }
+
+ if (area->has_monitor_callback()) {
process_collision = true;
}
@@ -219,13 +235,13 @@ bool AreaSoftBodyPair3DSW::setup(real_t p_step) {
return process_collision;
}
-bool AreaSoftBodyPair3DSW::pre_solve(real_t p_step) {
+bool GodotAreaSoftBodyPair3D::pre_solve(real_t p_step) {
if (!process_collision) {
return false;
}
if (colliding) {
- if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) {
+ if (has_space_override) {
soft_body->add_area(area);
}
@@ -233,7 +249,7 @@ bool AreaSoftBodyPair3DSW::pre_solve(real_t p_step) {
area->add_soft_body_to_query(soft_body, soft_body_shape, area_shape);
}
} else {
- if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) {
+ if (has_space_override) {
soft_body->remove_area(area);
}
@@ -245,11 +261,11 @@ bool AreaSoftBodyPair3DSW::pre_solve(real_t p_step) {
return false; // Never do any post solving.
}
-void AreaSoftBodyPair3DSW::solve(real_t p_step) {
+void GodotAreaSoftBodyPair3D::solve(real_t p_step) {
// Nothing to do.
}
-AreaSoftBodyPair3DSW::AreaSoftBodyPair3DSW(SoftBody3DSW *p_soft_body, int p_soft_body_shape, Area3DSW *p_area, int p_area_shape) {
+GodotAreaSoftBodyPair3D::GodotAreaSoftBodyPair3D(GodotSoftBody3D *p_soft_body, int p_soft_body_shape, GodotArea3D *p_area, int p_area_shape) {
soft_body = p_soft_body;
area = p_area;
soft_body_shape = p_soft_body_shape;
@@ -258,9 +274,9 @@ AreaSoftBodyPair3DSW::AreaSoftBodyPair3DSW(SoftBody3DSW *p_soft_body, int p_soft
area->add_constraint(this);
}
-AreaSoftBodyPair3DSW::~AreaSoftBodyPair3DSW() {
+GodotAreaSoftBodyPair3D::~GodotAreaSoftBodyPair3D() {
if (colliding) {
- if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) {
+ if (has_space_override) {
soft_body->remove_area(area);
}
if (area->has_monitor_callback()) {
diff --git a/servers/physics_3d/area_pair_3d_sw.h b/servers/physics_3d/godot_area_pair_3d.h
index 4572dcbb23..c416477204 100644
--- a/servers/physics_3d/area_pair_3d_sw.h
+++ b/servers/physics_3d/godot_area_pair_3d.h
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* area_pair_3d_sw.h */
+/* godot_area_pair_3d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,65 +28,69 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AREA_PAIR_SW_H
-#define AREA_PAIR_SW_H
+#ifndef GODOT_AREA_PAIR_3D_H
+#define GODOT_AREA_PAIR_3D_H
-#include "area_3d_sw.h"
-#include "body_3d_sw.h"
-#include "constraint_3d_sw.h"
-#include "soft_body_3d_sw.h"
+#include "godot_area_3d.h"
+#include "godot_body_3d.h"
+#include "godot_constraint_3d.h"
+#include "godot_soft_body_3d.h"
-class AreaPair3DSW : public Constraint3DSW {
- Body3DSW *body;
- Area3DSW *area;
+class GodotAreaPair3D : public GodotConstraint3D {
+ GodotBody3D *body;
+ GodotArea3D *area;
int body_shape;
int area_shape;
bool colliding = false;
bool process_collision = false;
+ bool has_space_override = false;
public:
virtual bool setup(real_t p_step) override;
virtual bool pre_solve(real_t p_step) override;
virtual void solve(real_t p_step) override;
- AreaPair3DSW(Body3DSW *p_body, int p_body_shape, Area3DSW *p_area, int p_area_shape);
- ~AreaPair3DSW();
+ GodotAreaPair3D(GodotBody3D *p_body, int p_body_shape, GodotArea3D *p_area, int p_area_shape);
+ ~GodotAreaPair3D();
};
-class Area2Pair3DSW : public Constraint3DSW {
- Area3DSW *area_a;
- Area3DSW *area_b;
+class GodotArea2Pair3D : public GodotConstraint3D {
+ GodotArea3D *area_a;
+ GodotArea3D *area_b;
int shape_a;
int shape_b;
bool colliding_a = false;
bool colliding_b = false;
bool process_collision_a = false;
bool process_collision_b = false;
+ bool area_a_monitorable;
+ bool area_b_monitorable;
public:
virtual bool setup(real_t p_step) override;
virtual bool pre_solve(real_t p_step) override;
virtual void solve(real_t p_step) override;
- Area2Pair3DSW(Area3DSW *p_area_a, int p_shape_a, Area3DSW *p_area_b, int p_shape_b);
- ~Area2Pair3DSW();
+ GodotArea2Pair3D(GodotArea3D *p_area_a, int p_shape_a, GodotArea3D *p_area_b, int p_shape_b);
+ ~GodotArea2Pair3D();
};
-class AreaSoftBodyPair3DSW : public Constraint3DSW {
- SoftBody3DSW *soft_body;
- Area3DSW *area;
+class GodotAreaSoftBodyPair3D : public GodotConstraint3D {
+ GodotSoftBody3D *soft_body;
+ GodotArea3D *area;
int soft_body_shape;
int area_shape;
bool colliding = false;
bool process_collision = false;
+ bool has_space_override = false;
public:
virtual bool setup(real_t p_step) override;
virtual bool pre_solve(real_t p_step) override;
virtual void solve(real_t p_step) override;
- AreaSoftBodyPair3DSW(SoftBody3DSW *p_sof_body, int p_soft_body_shape, Area3DSW *p_area, int p_area_shape);
- ~AreaSoftBodyPair3DSW();
+ GodotAreaSoftBodyPair3D(GodotSoftBody3D *p_sof_body, int p_soft_body_shape, GodotArea3D *p_area, int p_area_shape);
+ ~GodotAreaSoftBodyPair3D();
};
-#endif // AREA_PAIR__SW_H
+#endif // GODOT_AREA_PAIR_3D_H
diff --git a/servers/physics_3d/body_3d_sw.cpp b/servers/physics_3d/godot_body_3d.cpp
index 069374d122..ad97533f44 100644
--- a/servers/physics_3d/body_3d_sw.cpp
+++ b/servers/physics_3d/godot_body_3d.cpp
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* body_3d_sw.cpp */
+/* godot_body_3d.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,19 +28,19 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "body_3d_sw.h"
+#include "godot_body_3d.h"
-#include "area_3d_sw.h"
-#include "body_direct_state_3d_sw.h"
-#include "space_3d_sw.h"
+#include "godot_area_3d.h"
+#include "godot_body_direct_state_3d.h"
+#include "godot_space_3d.h"
-void Body3DSW::_mass_properties_changed() {
+void GodotBody3D::_mass_properties_changed() {
if (get_space() && !mass_properties_update_list.in_list() && (calculate_inertia || calculate_center_of_mass)) {
get_space()->body_add_to_mass_properties_update_list(&mass_properties_update_list);
}
}
-void Body3DSW::_update_transform_dependant() {
+void GodotBody3D::_update_transform_dependent() {
center_of_mass = get_transform().basis.xform(center_of_mass_local);
principal_inertia_axes = get_transform().basis * principal_inertia_axes_local;
@@ -52,7 +52,7 @@ void Body3DSW::_update_transform_dependant() {
_inv_inertia_tensor = tb * diag * tbt;
}
-void Body3DSW::update_mass_properties() {
+void GodotBody3D::update_mass_properties() {
// Update shapes and motions.
switch (mode) {
@@ -106,7 +106,7 @@ void Body3DSW::update_mass_properties() {
inertia_set = true;
- const Shape3DSW *shape = get_shape(i);
+ const GodotShape3D *shape = get_shape(i);
real_t mass = area * this->mass / total_area;
@@ -161,16 +161,16 @@ void Body3DSW::update_mass_properties() {
} break;
}
- _update_transform_dependant();
+ _update_transform_dependent();
}
-void Body3DSW::reset_mass_properties() {
+void GodotBody3D::reset_mass_properties() {
calculate_inertia = true;
calculate_center_of_mass = true;
_mass_properties_changed();
}
-void Body3DSW::set_active(bool p_active) {
+void GodotBody3D::set_active(bool p_active) {
if (active == p_active) {
return;
}
@@ -189,7 +189,7 @@ void Body3DSW::set_active(bool p_active) {
}
}
-void Body3DSW::set_param(PhysicsServer3D::BodyParameter p_param, const Variant &p_value) {
+void GodotBody3D::set_param(PhysicsServer3D::BodyParameter p_param, const Variant &p_value) {
switch (p_param) {
case PhysicsServer3D::BODY_PARAM_BOUNCE: {
bounce = p_value;
@@ -217,18 +217,29 @@ void Body3DSW::set_param(PhysicsServer3D::BodyParameter p_param, const Variant &
if (mode == PhysicsServer3D::BODY_MODE_DYNAMIC) {
principal_inertia_axes_local = Basis();
_inv_inertia = inertia.inverse();
- _update_transform_dependant();
+ _update_transform_dependent();
}
}
} break;
case PhysicsServer3D::BODY_PARAM_CENTER_OF_MASS: {
calculate_center_of_mass = false;
center_of_mass_local = p_value;
- _update_transform_dependant();
+ _update_transform_dependent();
} break;
case PhysicsServer3D::BODY_PARAM_GRAVITY_SCALE: {
+ if (Math::is_zero_approx(gravity_scale)) {
+ wakeup();
+ }
gravity_scale = p_value;
} break;
+ case PhysicsServer3D::BODY_PARAM_LINEAR_DAMP_MODE: {
+ int mode_value = p_value;
+ linear_damp_mode = (PhysicsServer3D::BodyDampMode)mode_value;
+ } break;
+ case PhysicsServer3D::BODY_PARAM_ANGULAR_DAMP_MODE: {
+ int mode_value = p_value;
+ angular_damp_mode = (PhysicsServer3D::BodyDampMode)mode_value;
+ } break;
case PhysicsServer3D::BODY_PARAM_LINEAR_DAMP: {
linear_damp = p_value;
} break;
@@ -240,7 +251,7 @@ void Body3DSW::set_param(PhysicsServer3D::BodyParameter p_param, const Variant &
}
}
-Variant Body3DSW::get_param(PhysicsServer3D::BodyParameter p_param) const {
+Variant GodotBody3D::get_param(PhysicsServer3D::BodyParameter p_param) const {
switch (p_param) {
case PhysicsServer3D::BODY_PARAM_BOUNCE: {
return bounce;
@@ -259,11 +270,17 @@ Variant Body3DSW::get_param(PhysicsServer3D::BodyParameter p_param) const {
}
} break;
case PhysicsServer3D::BODY_PARAM_CENTER_OF_MASS: {
- return center_of_mass;
+ return center_of_mass_local;
} break;
case PhysicsServer3D::BODY_PARAM_GRAVITY_SCALE: {
return gravity_scale;
} break;
+ case PhysicsServer3D::BODY_PARAM_LINEAR_DAMP_MODE: {
+ return linear_damp_mode;
+ }
+ case PhysicsServer3D::BODY_PARAM_ANGULAR_DAMP_MODE: {
+ return angular_damp_mode;
+ }
case PhysicsServer3D::BODY_PARAM_LINEAR_DAMP: {
return linear_damp;
} break;
@@ -278,7 +295,7 @@ Variant Body3DSW::get_param(PhysicsServer3D::BodyParameter p_param) const {
return 0;
}
-void Body3DSW::set_mode(PhysicsServer3D::BodyMode p_mode) {
+void GodotBody3D::set_mode(PhysicsServer3D::BodyMode p_mode) {
PhysicsServer3D::BodyMode prev = mode;
mode = p_mode;
@@ -295,7 +312,7 @@ void Body3DSW::set_mode(PhysicsServer3D::BodyMode p_mode) {
if (mode == PhysicsServer3D::BODY_MODE_KINEMATIC && prev != mode) {
first_time_kinematic = true;
}
- _update_transform_dependant();
+ _update_transform_dependent();
} break;
case PhysicsServer3D::BODY_MODE_DYNAMIC: {
@@ -303,7 +320,7 @@ void Body3DSW::set_mode(PhysicsServer3D::BodyMode p_mode) {
if (!calculate_inertia) {
principal_inertia_axes_local = Basis();
_inv_inertia = inertia.inverse();
- _update_transform_dependant();
+ _update_transform_dependent();
}
_mass_properties_changed();
_set_static(false);
@@ -314,22 +331,24 @@ void Body3DSW::set_mode(PhysicsServer3D::BodyMode p_mode) {
_inv_mass = mass > 0 ? (1.0 / mass) : 0;
_inv_inertia = Vector3();
angular_velocity = Vector3();
- _update_transform_dependant();
+ _update_transform_dependent();
_set_static(false);
set_active(true);
}
}
}
-PhysicsServer3D::BodyMode Body3DSW::get_mode() const {
+PhysicsServer3D::BodyMode GodotBody3D::get_mode() const {
return mode;
}
-void Body3DSW::_shapes_changed() {
+void GodotBody3D::_shapes_changed() {
_mass_properties_changed();
+ wakeup();
+ wakeup_neighbours();
}
-void Body3DSW::set_state(PhysicsServer3D::BodyState p_state, const Variant &p_variant) {
+void GodotBody3D::set_state(PhysicsServer3D::BodyState p_state, const Variant &p_variant) {
switch (p_state) {
case PhysicsServer3D::BODY_STATE_TRANSFORM: {
if (mode == PhysicsServer3D::BODY_MODE_KINEMATIC) {
@@ -355,6 +374,7 @@ void Body3DSW::set_state(PhysicsServer3D::BodyState p_state, const Variant &p_va
}
_set_transform(t);
_set_inv_transform(get_transform().inverse());
+ _update_transform_dependent();
}
wakeup();
@@ -395,7 +415,7 @@ void Body3DSW::set_state(PhysicsServer3D::BodyState p_state, const Variant &p_va
}
}
-Variant Body3DSW::get_state(PhysicsServer3D::BodyState p_state) const {
+Variant GodotBody3D::get_state(PhysicsServer3D::BodyState p_state) const {
switch (p_state) {
case PhysicsServer3D::BODY_STATE_TRANSFORM: {
return get_transform();
@@ -417,7 +437,7 @@ Variant Body3DSW::get_state(PhysicsServer3D::BodyState p_state) const {
return Variant();
}
-void Body3DSW::set_space(Space3DSW *p_space) {
+void GodotBody3D::set_space(GodotSpace3D *p_space) {
if (get_space()) {
if (mass_properties_update_list.in_list()) {
get_space()->body_remove_from_mass_properties_update_list(&mass_properties_update_list);
@@ -440,16 +460,7 @@ void Body3DSW::set_space(Space3DSW *p_space) {
}
}
-void Body3DSW::_compute_area_gravity_and_damping(const Area3DSW *p_area) {
- Vector3 area_gravity;
- p_area->compute_gravity(get_transform().get_origin(), area_gravity);
- gravity += area_gravity;
-
- area_linear_damp += p_area->get_linear_damp();
- area_angular_damp += p_area->get_angular_damp();
-}
-
-void Body3DSW::set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool lock) {
+void GodotBody3D::set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool lock) {
if (lock) {
locked_axis |= p_axis;
} else {
@@ -457,73 +468,144 @@ void Body3DSW::set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool lock) {
}
}
-bool Body3DSW::is_axis_locked(PhysicsServer3D::BodyAxis p_axis) const {
+bool GodotBody3D::is_axis_locked(PhysicsServer3D::BodyAxis p_axis) const {
return locked_axis & p_axis;
}
-void Body3DSW::integrate_forces(real_t p_step) {
+void GodotBody3D::integrate_forces(real_t p_step) {
if (mode == PhysicsServer3D::BODY_MODE_STATIC) {
return;
}
- Area3DSW *def_area = get_space()->get_default_area();
- // AreaSW *damp_area = def_area;
-
- ERR_FAIL_COND(!def_area);
+ ERR_FAIL_COND(!get_space());
int ac = areas.size();
+
+ bool gravity_done = false;
+ bool linear_damp_done = false;
+ bool angular_damp_done = false;
+
bool stopped = false;
+
gravity = Vector3(0, 0, 0);
- area_linear_damp = 0;
- area_angular_damp = 0;
+
+ total_linear_damp = 0.0;
+ total_angular_damp = 0.0;
+
+ // Combine gravity and damping from overlapping areas in priority order.
if (ac) {
areas.sort();
const AreaCMP *aa = &areas[0];
- // damp_area = aa[ac-1].area;
for (int i = ac - 1; i >= 0 && !stopped; i--) {
- PhysicsServer3D::AreaSpaceOverrideMode mode = aa[i].area->get_space_override_mode();
- switch (mode) {
- case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE:
- case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: {
- _compute_area_gravity_and_damping(aa[i].area);
- stopped = mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE;
- } break;
- case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE:
- case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: {
- gravity = Vector3(0, 0, 0);
- area_angular_damp = 0;
- area_linear_damp = 0;
- _compute_area_gravity_and_damping(aa[i].area);
- stopped = mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE;
- } break;
- default: {
+ if (!gravity_done) {
+ PhysicsServer3D::AreaSpaceOverrideMode area_gravity_mode = (PhysicsServer3D::AreaSpaceOverrideMode)(int)aa[i].area->get_param(PhysicsServer3D::AREA_PARAM_GRAVITY_OVERRIDE_MODE);
+ if (area_gravity_mode != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) {
+ Vector3 area_gravity;
+ aa[i].area->compute_gravity(get_transform().get_origin(), area_gravity);
+ switch (area_gravity_mode) {
+ case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE:
+ case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: {
+ gravity += area_gravity;
+ gravity_done = area_gravity_mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE;
+ } break;
+ case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE:
+ case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: {
+ gravity = area_gravity;
+ gravity_done = area_gravity_mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE;
+ } break;
+ default: {
+ }
+ }
+ }
+ }
+ if (!linear_damp_done) {
+ PhysicsServer3D::AreaSpaceOverrideMode area_linear_damp_mode = (PhysicsServer3D::AreaSpaceOverrideMode)(int)aa[i].area->get_param(PhysicsServer3D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE);
+ if (area_linear_damp_mode != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) {
+ real_t area_linear_damp = aa[i].area->get_linear_damp();
+ switch (area_linear_damp_mode) {
+ case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE:
+ case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: {
+ total_linear_damp += area_linear_damp;
+ linear_damp_done = area_linear_damp_mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE;
+ } break;
+ case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE:
+ case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: {
+ total_linear_damp = area_linear_damp;
+ linear_damp_done = area_linear_damp_mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE;
+ } break;
+ default: {
+ }
+ }
}
}
+ if (!angular_damp_done) {
+ PhysicsServer3D::AreaSpaceOverrideMode area_angular_damp_mode = (PhysicsServer3D::AreaSpaceOverrideMode)(int)aa[i].area->get_param(PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE);
+ if (area_angular_damp_mode != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) {
+ real_t area_angular_damp = aa[i].area->get_angular_damp();
+ switch (area_angular_damp_mode) {
+ case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE:
+ case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: {
+ total_angular_damp += area_angular_damp;
+ angular_damp_done = area_angular_damp_mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE;
+ } break;
+ case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE:
+ case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: {
+ total_angular_damp = area_angular_damp;
+ angular_damp_done = area_angular_damp_mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE;
+ } break;
+ default: {
+ }
+ }
+ }
+ }
+ stopped = gravity_done && linear_damp_done && angular_damp_done;
}
}
+ // Add default gravity and damping from space area.
if (!stopped) {
- _compute_area_gravity_and_damping(def_area);
- }
+ GodotArea3D *default_area = get_space()->get_default_area();
+ ERR_FAIL_COND(!default_area);
- gravity *= gravity_scale;
+ if (!gravity_done) {
+ Vector3 default_gravity;
+ default_area->compute_gravity(get_transform().get_origin(), default_gravity);
+ gravity += default_gravity;
+ }
+
+ if (!linear_damp_done) {
+ total_linear_damp += default_area->get_linear_damp();
+ }
- // If less than 0, override dampenings with that of the Body
- if (angular_damp >= 0) {
- area_angular_damp = angular_damp;
+ if (!angular_damp_done) {
+ total_angular_damp += default_area->get_angular_damp();
+ }
}
- /*
- else
- area_angular_damp=damp_area->get_angular_damp();
- */
- if (linear_damp >= 0) {
- area_linear_damp = linear_damp;
+ // Override linear damping with body's value.
+ switch (linear_damp_mode) {
+ case PhysicsServer3D::BODY_DAMP_MODE_COMBINE: {
+ total_linear_damp += linear_damp;
+ } break;
+ case PhysicsServer3D::BODY_DAMP_MODE_REPLACE: {
+ total_linear_damp = linear_damp;
+ } break;
}
- /*
- else
- area_linear_damp=damp_area->get_linear_damp();
- */
+
+ // Override angular damping with body's value.
+ switch (angular_damp_mode) {
+ case PhysicsServer3D::BODY_DAMP_MODE_COMBINE: {
+ total_angular_damp += angular_damp;
+ } break;
+ case PhysicsServer3D::BODY_DAMP_MODE_REPLACE: {
+ total_angular_damp = angular_damp;
+ } break;
+ }
+
+ gravity *= gravity_scale;
+
+ prev_linear_velocity = linear_velocity;
+ prev_angular_velocity = angular_velocity;
Vector3 motion;
bool do_motion = false;
@@ -546,17 +628,16 @@ void Body3DSW::integrate_forces(real_t p_step) {
if (!omit_force_integration) {
//overridden by direct state query
- Vector3 force = gravity * mass;
- force += applied_force;
- Vector3 torque = applied_torque;
+ Vector3 force = gravity * mass + applied_force + constant_force;
+ Vector3 torque = applied_torque + constant_torque;
- real_t damp = 1.0 - p_step * area_linear_damp;
+ real_t damp = 1.0 - p_step * total_linear_damp;
if (damp < 0) { // reached zero in the given time
damp = 0;
}
- real_t angular_damp = 1.0 - p_step * area_angular_damp;
+ real_t angular_damp = 1.0 - p_step * total_angular_damp;
if (angular_damp < 0) { // reached zero in the given time
angular_damp = 0;
@@ -578,8 +659,6 @@ void Body3DSW::integrate_forces(real_t p_step) {
applied_force = Vector3();
applied_torque = Vector3();
- //motion=linear_velocity*p_step;
-
biased_angular_velocity = Vector3();
biased_linear_velocity = Vector3();
@@ -587,11 +666,10 @@ void Body3DSW::integrate_forces(real_t p_step) {
_update_shapes_with_motion(motion);
}
- def_area = nullptr; // clear the area, so it is set in the next frame
contact_count = 0;
}
-void Body3DSW::integrate_velocities(real_t p_step) {
+void GodotBody3D::integrate_velocities(real_t p_step) {
if (mode == PhysicsServer3D::BODY_MODE_STATIC) {
return;
}
@@ -652,52 +730,20 @@ void Body3DSW::integrate_velocities(real_t p_step) {
_set_transform(transform);
_set_inv_transform(get_transform().inverse());
- _update_transform_dependant();
+ _update_transform_dependent();
}
-/*
-void BodySW::simulate_motion(const Transform3D& p_xform,real_t p_step) {
- Transform3D inv_xform = p_xform.affine_inverse();
- if (!get_space()) {
- _set_transform(p_xform);
- _set_inv_transform(inv_xform);
-
- return;
- }
-
- //compute a FAKE linear velocity - this is easy
-
- linear_velocity=(p_xform.origin - get_transform().origin)/p_step;
-
- //compute a FAKE angular velocity, not so easy
- Basis rot=get_transform().basis.orthonormalized().transposed() * p_xform.basis.orthonormalized();
- Vector3 axis;
- real_t angle;
-
- rot.get_axis_angle(axis,angle);
- axis.normalize();
- angular_velocity=axis.normalized() * (angle/p_step);
- linear_velocity = (p_xform.origin - get_transform().origin)/p_step;
-
- if (!direct_state_query_list.in_list())// - callalways, so lv and av are cleared && (state_query || direct_state_query))
- get_space()->body_add_to_state_query_list(&direct_state_query_list);
- simulated_motion=true;
- _set_transform(p_xform);
-}
-
-*/
-
-void Body3DSW::wakeup_neighbours() {
- for (const KeyValue<Constraint3DSW *, int> &E : constraint_map) {
- const Constraint3DSW *c = E.key;
- Body3DSW **n = c->get_body_ptr();
+void GodotBody3D::wakeup_neighbours() {
+ for (const KeyValue<GodotConstraint3D *, int> &E : constraint_map) {
+ const GodotConstraint3D *c = E.key;
+ GodotBody3D **n = c->get_body_ptr();
int bc = c->get_body_count();
for (int i = 0; i < bc; i++) {
if (i == E.value) {
continue;
}
- Body3DSW *b = n[i];
+ GodotBody3D *b = n[i];
if (b->mode < PhysicsServer3D::BODY_MODE_DYNAMIC) {
continue;
}
@@ -709,7 +755,7 @@ void Body3DSW::wakeup_neighbours() {
}
}
-void Body3DSW::call_queries() {
+void GodotBody3D::call_queries() {
if (fi_callback_data) {
if (!fi_callback_data->callable.get_object()) {
set_force_integration_callback(Callable());
@@ -729,7 +775,7 @@ void Body3DSW::call_queries() {
}
}
-bool Body3DSW::sleep_test(real_t p_step) {
+bool GodotBody3D::sleep_test(real_t p_step) {
if (mode == PhysicsServer3D::BODY_MODE_STATIC || mode == PhysicsServer3D::BODY_MODE_KINEMATIC) {
return true;
} else if (!can_sleep) {
@@ -746,12 +792,12 @@ bool Body3DSW::sleep_test(real_t p_step) {
}
}
-void Body3DSW::set_state_sync_callback(void *p_instance, PhysicsServer3D::BodyStateCallback p_callback) {
+void GodotBody3D::set_state_sync_callback(void *p_instance, PhysicsServer3D::BodyStateCallback p_callback) {
body_state_callback_instance = p_instance;
body_state_callback = p_callback;
}
-void Body3DSW::set_force_integration_callback(const Callable &p_callable, const Variant &p_udata) {
+void GodotBody3D::set_force_integration_callback(const Callable &p_callable, const Variant &p_udata) {
if (p_callable.get_object()) {
if (!fi_callback_data) {
fi_callback_data = memnew(ForceIntegrationCallbackData);
@@ -764,23 +810,23 @@ void Body3DSW::set_force_integration_callback(const Callable &p_callable, const
}
}
-PhysicsDirectBodyState3DSW *Body3DSW::get_direct_state() {
+GodotPhysicsDirectBodyState3D *GodotBody3D::get_direct_state() {
if (!direct_state) {
- direct_state = memnew(PhysicsDirectBodyState3DSW);
+ direct_state = memnew(GodotPhysicsDirectBodyState3D);
direct_state->body = this;
}
return direct_state;
}
-Body3DSW::Body3DSW() :
- CollisionObject3DSW(TYPE_BODY),
+GodotBody3D::GodotBody3D() :
+ GodotCollisionObject3D(TYPE_BODY),
active_list(this),
mass_properties_update_list(this),
direct_state_query_list(this) {
_set_static(false);
}
-Body3DSW::~Body3DSW() {
+GodotBody3D::~GodotBody3D() {
if (fi_callback_data) {
memdelete(fi_callback_data);
}
diff --git a/servers/physics_3d/body_3d_sw.h b/servers/physics_3d/godot_body_3d.h
index fc47040389..1906e8aab1 100644
--- a/servers/physics_3d/body_3d_sw.h
+++ b/servers/physics_3d/godot_body_3d.h
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* body_3d_sw.h */
+/* godot_body_3d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,22 +28,26 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef BODY_3D_SW_H
-#define BODY_3D_SW_H
+#ifndef GODOT_BODY_3D_H
+#define GODOT_BODY_3D_H
+
+#include "godot_area_3d.h"
+#include "godot_collision_object_3d.h"
-#include "area_3d_sw.h"
-#include "collision_object_3d_sw.h"
#include "core/templates/vset.h"
-class Constraint3DSW;
-class PhysicsDirectBodyState3DSW;
+class GodotConstraint3D;
+class GodotPhysicsDirectBodyState3D;
-class Body3DSW : public CollisionObject3DSW {
+class GodotBody3D : public GodotCollisionObject3D {
PhysicsServer3D::BodyMode mode = PhysicsServer3D::BODY_MODE_DYNAMIC;
Vector3 linear_velocity;
Vector3 angular_velocity;
+ Vector3 prev_linear_velocity;
+ Vector3 prev_angular_velocity;
+
Vector3 constant_linear_velocity;
Vector3 constant_angular_velocity;
@@ -54,8 +58,15 @@ class Body3DSW : public CollisionObject3DSW {
real_t friction = 1.0;
Vector3 inertia;
- real_t linear_damp = -1.0;
- real_t angular_damp = -1.0;
+ PhysicsServer3D::BodyDampMode linear_damp_mode = PhysicsServer3D::BODY_DAMP_MODE_COMBINE;
+ PhysicsServer3D::BodyDampMode angular_damp_mode = PhysicsServer3D::BODY_DAMP_MODE_COMBINE;
+
+ real_t linear_damp = 0.0;
+ real_t angular_damp = 0.0;
+
+ real_t total_linear_damp = 0.0;
+ real_t total_angular_damp = 0.0;
+
real_t gravity_scale = 1.0;
uint16_t locked_axis = 0;
@@ -82,12 +93,12 @@ class Body3DSW : public CollisionObject3DSW {
Vector3 applied_force;
Vector3 applied_torque;
- real_t area_angular_damp = 0.0;
- real_t area_linear_damp = 0.0;
+ Vector3 constant_force;
+ Vector3 constant_torque;
- SelfList<Body3DSW> active_list;
- SelfList<Body3DSW> mass_properties_update_list;
- SelfList<Body3DSW> direct_state_query_list;
+ SelfList<GodotBody3D> active_list;
+ SelfList<GodotBody3D> mass_properties_update_list;
+ SelfList<GodotBody3D> direct_state_query_list;
VSet<RID> exceptions;
bool omit_force_integration = false;
@@ -101,7 +112,7 @@ class Body3DSW : public CollisionObject3DSW {
virtual void _shapes_changed();
Transform3D new_transform;
- Map<Constraint3DSW *, int> constraint_map;
+ Map<GodotConstraint3D *, int> constraint_map;
Vector<AreaCMP> areas;
@@ -130,23 +141,21 @@ class Body3DSW : public CollisionObject3DSW {
ForceIntegrationCallbackData *fi_callback_data = nullptr;
- PhysicsDirectBodyState3DSW *direct_state = nullptr;
+ GodotPhysicsDirectBodyState3D *direct_state = nullptr;
uint64_t island_step = 0;
- _FORCE_INLINE_ void _compute_area_gravity_and_damping(const Area3DSW *p_area);
+ void _update_transform_dependent();
- _FORCE_INLINE_ void _update_transform_dependant();
-
- friend class PhysicsDirectBodyState3DSW; // i give up, too many functions to expose
+ friend class GodotPhysicsDirectBodyState3D; // i give up, too many functions to expose
public:
void set_state_sync_callback(void *p_instance, PhysicsServer3D::BodyStateCallback p_callback);
void set_force_integration_callback(const Callable &p_callable, const Variant &p_udata = Variant());
- PhysicsDirectBodyState3DSW *get_direct_state();
+ GodotPhysicsDirectBodyState3D *get_direct_state();
- _FORCE_INLINE_ void add_area(Area3DSW *p_area) {
+ _FORCE_INLINE_ void add_area(GodotArea3D *p_area) {
int index = areas.find(AreaCMP(p_area));
if (index > -1) {
areas.write[index].refCount += 1;
@@ -155,12 +164,12 @@ public:
}
}
- _FORCE_INLINE_ void remove_area(Area3DSW *p_area) {
+ _FORCE_INLINE_ void remove_area(GodotArea3D *p_area) {
int index = areas.find(AreaCMP(p_area));
if (index > -1) {
areas.write[index].refCount -= 1;
if (areas[index].refCount < 1) {
- areas.remove(index);
+ areas.remove_at(index);
}
}
}
@@ -185,9 +194,9 @@ public:
_FORCE_INLINE_ uint64_t get_island_step() const { return island_step; }
_FORCE_INLINE_ void set_island_step(uint64_t p_step) { island_step = p_step; }
- _FORCE_INLINE_ void add_constraint(Constraint3DSW *p_constraint, int p_pos) { constraint_map[p_constraint] = p_pos; }
- _FORCE_INLINE_ void remove_constraint(Constraint3DSW *p_constraint) { constraint_map.erase(p_constraint); }
- const Map<Constraint3DSW *, int> &get_constraint_map() const { return constraint_map; }
+ _FORCE_INLINE_ void add_constraint(GodotConstraint3D *p_constraint, int p_pos) { constraint_map[p_constraint] = p_pos; }
+ _FORCE_INLINE_ void remove_constraint(GodotConstraint3D *p_constraint) { constraint_map.erase(p_constraint); }
+ const Map<GodotConstraint3D *, int> &get_constraint_map() const { return constraint_map; }
_FORCE_INLINE_ void clear_constraint_map() { constraint_map.clear(); }
_FORCE_INLINE_ void set_omit_force_integration(bool p_omit_force_integration) { omit_force_integration = p_omit_force_integration; }
@@ -195,6 +204,7 @@ public:
_FORCE_INLINE_ Basis get_principal_inertia_axes() const { return principal_inertia_axes; }
_FORCE_INLINE_ Vector3 get_center_of_mass() const { return center_of_mass; }
+ _FORCE_INLINE_ Vector3 get_center_of_mass_local() const { return center_of_mass_local; }
_FORCE_INLINE_ Vector3 xform_local_to_principal(const Vector3 &p_pos) const { return principal_inertia_axes_local.xform(p_pos - center_of_mass_local); }
_FORCE_INLINE_ void set_linear_velocity(const Vector3 &p_velocity) { linear_velocity = p_velocity; }
@@ -203,6 +213,9 @@ public:
_FORCE_INLINE_ void set_angular_velocity(const Vector3 &p_velocity) { angular_velocity = p_velocity; }
_FORCE_INLINE_ Vector3 get_angular_velocity() const { return angular_velocity; }
+ _FORCE_INLINE_ Vector3 get_prev_linear_velocity() const { return prev_linear_velocity; }
+ _FORCE_INLINE_ Vector3 get_prev_angular_velocity() const { return prev_angular_velocity; }
+
_FORCE_INLINE_ const Vector3 &get_biased_linear_velocity() const { return biased_linear_velocity; }
_FORCE_INLINE_ const Vector3 &get_biased_angular_velocity() const { return biased_angular_velocity; }
@@ -234,19 +247,38 @@ public:
biased_angular_velocity += _inv_inertia_tensor.xform(p_impulse);
}
- _FORCE_INLINE_ void add_central_force(const Vector3 &p_force) {
+ _FORCE_INLINE_ void apply_central_force(const Vector3 &p_force) {
applied_force += p_force;
}
- _FORCE_INLINE_ void add_force(const Vector3 &p_force, const Vector3 &p_position = Vector3()) {
+ _FORCE_INLINE_ void apply_force(const Vector3 &p_force, const Vector3 &p_position = Vector3()) {
applied_force += p_force;
applied_torque += (p_position - center_of_mass).cross(p_force);
}
- _FORCE_INLINE_ void add_torque(const Vector3 &p_torque) {
+ _FORCE_INLINE_ void apply_torque(const Vector3 &p_torque) {
applied_torque += p_torque;
}
+ _FORCE_INLINE_ void add_constant_central_force(const Vector3 &p_force) {
+ constant_force += p_force;
+ }
+
+ _FORCE_INLINE_ void add_constant_force(const Vector3 &p_force, const Vector3 &p_position = Vector3()) {
+ constant_force += p_force;
+ constant_torque += (p_position - center_of_mass).cross(p_force);
+ }
+
+ _FORCE_INLINE_ void add_constant_torque(const Vector3 &p_torque) {
+ constant_torque += p_torque;
+ }
+
+ void set_constant_force(const Vector3 &p_force) { constant_force = p_force; }
+ Vector3 get_constant_force() const { return constant_force; }
+
+ void set_constant_torque(const Vector3 &p_torque) { constant_torque = p_torque; }
+ Vector3 get_constant_torque() const { return constant_torque; }
+
void set_active(bool p_active);
_FORCE_INLINE_ bool is_active() const { return active; }
@@ -266,16 +298,10 @@ public:
void set_state(PhysicsServer3D::BodyState p_state, const Variant &p_variant);
Variant get_state(PhysicsServer3D::BodyState p_state) const;
- void set_applied_force(const Vector3 &p_force) { applied_force = p_force; }
- Vector3 get_applied_force() const { return applied_force; }
-
- void set_applied_torque(const Vector3 &p_torque) { applied_torque = p_torque; }
- Vector3 get_applied_torque() const { return applied_torque; }
-
_FORCE_INLINE_ void set_continuous_collision_detection(bool p_enable) { continuous_cd = p_enable; }
_FORCE_INLINE_ bool is_continuous_collision_detection_enabled() const { return continuous_cd; }
- void set_space(Space3DSW *p_space);
+ void set_space(GodotSpace3D *p_space);
void update_mass_properties();
void reset_mass_properties();
@@ -284,7 +310,6 @@ public:
_FORCE_INLINE_ const Vector3 &get_inv_inertia() const { return _inv_inertia; }
_FORCE_INLINE_ const Basis &get_inv_inertia_tensor() const { return _inv_inertia_tensor; }
_FORCE_INLINE_ real_t get_friction() const { return friction; }
- _FORCE_INLINE_ const Vector3 &get_gravity() const { return gravity; }
_FORCE_INLINE_ real_t get_bounce() const { return bounce; }
void set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool lock);
@@ -317,13 +342,13 @@ public:
bool sleep_test(real_t p_step);
- Body3DSW();
- ~Body3DSW();
+ GodotBody3D();
+ ~GodotBody3D();
};
//add contact inline
-void Body3DSW::add_contact(const Vector3 &p_local_pos, const Vector3 &p_local_normal, real_t p_depth, int p_local_shape, const Vector3 &p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID &p_collider, const Vector3 &p_collider_velocity_at_pos) {
+void GodotBody3D::add_contact(const Vector3 &p_local_pos, const Vector3 &p_local_normal, real_t p_depth, int p_local_shape, const Vector3 &p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID &p_collider, const Vector3 &p_collider_velocity_at_pos) {
int c_max = contacts.size();
if (c_max == 0) {
@@ -365,4 +390,4 @@ void Body3DSW::add_contact(const Vector3 &p_local_pos, const Vector3 &p_local_no
c[idx].collider_velocity_at_pos = p_collider_velocity_at_pos;
}
-#endif // BODY_3D_SW_H
+#endif // GODOT_BODY_3D_H
diff --git a/servers/physics_3d/godot_body_direct_state_3d.cpp b/servers/physics_3d/godot_body_direct_state_3d.cpp
new file mode 100644
index 0000000000..a8c6086e1c
--- /dev/null
+++ b/servers/physics_3d/godot_body_direct_state_3d.cpp
@@ -0,0 +1,231 @@
+/*************************************************************************/
+/* godot_body_direct_state_3d.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 "godot_body_direct_state_3d.h"
+
+#include "godot_body_3d.h"
+#include "godot_space_3d.h"
+
+Vector3 GodotPhysicsDirectBodyState3D::get_total_gravity() const {
+ return body->gravity;
+}
+
+real_t GodotPhysicsDirectBodyState3D::get_total_angular_damp() const {
+ return body->total_angular_damp;
+}
+
+real_t GodotPhysicsDirectBodyState3D::get_total_linear_damp() const {
+ return body->total_linear_damp;
+}
+
+Vector3 GodotPhysicsDirectBodyState3D::get_center_of_mass() const {
+ return body->get_center_of_mass();
+}
+
+Vector3 GodotPhysicsDirectBodyState3D::get_center_of_mass_local() const {
+ return body->get_center_of_mass_local();
+}
+
+Basis GodotPhysicsDirectBodyState3D::get_principal_inertia_axes() const {
+ return body->get_principal_inertia_axes();
+}
+
+real_t GodotPhysicsDirectBodyState3D::get_inverse_mass() const {
+ return body->get_inv_mass();
+}
+
+Vector3 GodotPhysicsDirectBodyState3D::get_inverse_inertia() const {
+ return body->get_inv_inertia();
+}
+
+Basis GodotPhysicsDirectBodyState3D::get_inverse_inertia_tensor() const {
+ return body->get_inv_inertia_tensor();
+}
+
+void GodotPhysicsDirectBodyState3D::set_linear_velocity(const Vector3 &p_velocity) {
+ body->wakeup();
+ body->set_linear_velocity(p_velocity);
+}
+
+Vector3 GodotPhysicsDirectBodyState3D::get_linear_velocity() const {
+ return body->get_linear_velocity();
+}
+
+void GodotPhysicsDirectBodyState3D::set_angular_velocity(const Vector3 &p_velocity) {
+ body->wakeup();
+ body->set_angular_velocity(p_velocity);
+}
+
+Vector3 GodotPhysicsDirectBodyState3D::get_angular_velocity() const {
+ return body->get_angular_velocity();
+}
+
+void GodotPhysicsDirectBodyState3D::set_transform(const Transform3D &p_transform) {
+ body->set_state(PhysicsServer3D::BODY_STATE_TRANSFORM, p_transform);
+}
+
+Transform3D GodotPhysicsDirectBodyState3D::get_transform() const {
+ return body->get_transform();
+}
+
+Vector3 GodotPhysicsDirectBodyState3D::get_velocity_at_local_position(const Vector3 &p_position) const {
+ return body->get_velocity_in_local_point(p_position);
+}
+
+void GodotPhysicsDirectBodyState3D::apply_central_impulse(const Vector3 &p_impulse) {
+ body->wakeup();
+ body->apply_central_impulse(p_impulse);
+}
+
+void GodotPhysicsDirectBodyState3D::apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position) {
+ body->wakeup();
+ body->apply_impulse(p_impulse, p_position);
+}
+
+void GodotPhysicsDirectBodyState3D::apply_torque_impulse(const Vector3 &p_impulse) {
+ body->wakeup();
+ body->apply_torque_impulse(p_impulse);
+}
+
+void GodotPhysicsDirectBodyState3D::apply_central_force(const Vector3 &p_force) {
+ body->wakeup();
+ body->apply_central_force(p_force);
+}
+
+void GodotPhysicsDirectBodyState3D::apply_force(const Vector3 &p_force, const Vector3 &p_position) {
+ body->wakeup();
+ body->apply_force(p_force, p_position);
+}
+
+void GodotPhysicsDirectBodyState3D::apply_torque(const Vector3 &p_torque) {
+ body->wakeup();
+ body->apply_torque(p_torque);
+}
+
+void GodotPhysicsDirectBodyState3D::add_constant_central_force(const Vector3 &p_force) {
+ body->wakeup();
+ body->add_constant_central_force(p_force);
+}
+
+void GodotPhysicsDirectBodyState3D::add_constant_force(const Vector3 &p_force, const Vector3 &p_position) {
+ body->wakeup();
+ body->add_constant_force(p_force, p_position);
+}
+
+void GodotPhysicsDirectBodyState3D::add_constant_torque(const Vector3 &p_torque) {
+ body->wakeup();
+ body->add_constant_torque(p_torque);
+}
+
+void GodotPhysicsDirectBodyState3D::set_constant_force(const Vector3 &p_force) {
+ if (!p_force.is_equal_approx(Vector3())) {
+ body->wakeup();
+ }
+ body->set_constant_force(p_force);
+}
+
+Vector3 GodotPhysicsDirectBodyState3D::get_constant_force() const {
+ return body->get_constant_force();
+}
+
+void GodotPhysicsDirectBodyState3D::set_constant_torque(const Vector3 &p_torque) {
+ if (!p_torque.is_equal_approx(Vector3())) {
+ body->wakeup();
+ }
+ body->set_constant_torque(p_torque);
+}
+
+Vector3 GodotPhysicsDirectBodyState3D::get_constant_torque() const {
+ return body->get_constant_torque();
+}
+
+void GodotPhysicsDirectBodyState3D::set_sleep_state(bool p_sleep) {
+ body->set_active(!p_sleep);
+}
+
+bool GodotPhysicsDirectBodyState3D::is_sleeping() const {
+ return !body->is_active();
+}
+
+int GodotPhysicsDirectBodyState3D::get_contact_count() const {
+ return body->contact_count;
+}
+
+Vector3 GodotPhysicsDirectBodyState3D::get_contact_local_position(int p_contact_idx) const {
+ ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector3());
+ return body->contacts[p_contact_idx].local_pos;
+}
+
+Vector3 GodotPhysicsDirectBodyState3D::get_contact_local_normal(int p_contact_idx) const {
+ ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector3());
+ return body->contacts[p_contact_idx].local_normal;
+}
+
+real_t GodotPhysicsDirectBodyState3D::get_contact_impulse(int p_contact_idx) const {
+ return 0.0f; // Only implemented for bullet
+}
+
+int GodotPhysicsDirectBodyState3D::get_contact_local_shape(int p_contact_idx) const {
+ ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, -1);
+ return body->contacts[p_contact_idx].local_shape;
+}
+
+RID GodotPhysicsDirectBodyState3D::get_contact_collider(int p_contact_idx) const {
+ ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, RID());
+ return body->contacts[p_contact_idx].collider;
+}
+
+Vector3 GodotPhysicsDirectBodyState3D::get_contact_collider_position(int p_contact_idx) const {
+ ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector3());
+ return body->contacts[p_contact_idx].collider_pos;
+}
+
+ObjectID GodotPhysicsDirectBodyState3D::get_contact_collider_id(int p_contact_idx) const {
+ ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, ObjectID());
+ return body->contacts[p_contact_idx].collider_instance_id;
+}
+
+int GodotPhysicsDirectBodyState3D::get_contact_collider_shape(int p_contact_idx) const {
+ ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, 0);
+ return body->contacts[p_contact_idx].collider_shape;
+}
+
+Vector3 GodotPhysicsDirectBodyState3D::get_contact_collider_velocity_at_position(int p_contact_idx) const {
+ ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector3());
+ return body->contacts[p_contact_idx].collider_velocity_at_pos;
+}
+
+PhysicsDirectSpaceState3D *GodotPhysicsDirectBodyState3D::get_space_state() {
+ return body->get_space()->get_direct_state();
+}
+
+real_t GodotPhysicsDirectBodyState3D::get_step() const {
+ return body->get_space()->get_last_step();
+}
diff --git a/servers/physics_3d/body_direct_state_3d_sw.h b/servers/physics_3d/godot_body_direct_state_3d.h
index 5132376715..483cfb9298 100644
--- a/servers/physics_3d/body_direct_state_3d_sw.h
+++ b/servers/physics_3d/godot_body_direct_state_3d.h
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* body_direct_state_3d_sw.h */
+/* godot_body_direct_state_3d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,24 +28,25 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef BODY_DIRECT_STATE_3D_SW_H
-#define BODY_DIRECT_STATE_3D_SW_H
+#ifndef GODOT_BODY_DIRECT_STATE_3D_H
+#define GODOT_BODY_DIRECT_STATE_3D_H
#include "servers/physics_server_3d.h"
-class Body3DSW;
+class GodotBody3D;
-class PhysicsDirectBodyState3DSW : public PhysicsDirectBodyState3D {
- GDCLASS(PhysicsDirectBodyState3DSW, PhysicsDirectBodyState3D);
+class GodotPhysicsDirectBodyState3D : public PhysicsDirectBodyState3D {
+ GDCLASS(GodotPhysicsDirectBodyState3D, PhysicsDirectBodyState3D);
public:
- Body3DSW *body = nullptr;
+ GodotBody3D *body = nullptr;
virtual Vector3 get_total_gravity() const override;
virtual real_t get_total_angular_damp() const override;
virtual real_t get_total_linear_damp() const override;
virtual Vector3 get_center_of_mass() const override;
+ virtual Vector3 get_center_of_mass_local() const override;
virtual Basis get_principal_inertia_axes() const override;
virtual real_t get_inverse_mass() const override;
@@ -63,13 +64,24 @@ public:
virtual Vector3 get_velocity_at_local_position(const Vector3 &p_position) const override;
- virtual void add_central_force(const Vector3 &p_force) override;
- virtual void add_force(const Vector3 &p_force, const Vector3 &p_position = Vector3()) override;
- virtual void add_torque(const Vector3 &p_torque) override;
virtual void apply_central_impulse(const Vector3 &p_impulse) override;
virtual void apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position = Vector3()) override;
virtual void apply_torque_impulse(const Vector3 &p_impulse) override;
+ virtual void apply_central_force(const Vector3 &p_force) override;
+ virtual void apply_force(const Vector3 &p_force, const Vector3 &p_position = Vector3()) override;
+ virtual void apply_torque(const Vector3 &p_torque) override;
+
+ virtual void add_constant_central_force(const Vector3 &p_force) override;
+ virtual void add_constant_force(const Vector3 &p_force, const Vector3 &p_position = Vector3()) override;
+ virtual void add_constant_torque(const Vector3 &p_torque) override;
+
+ virtual void set_constant_force(const Vector3 &p_force) override;
+ virtual Vector3 get_constant_force() const override;
+
+ virtual void set_constant_torque(const Vector3 &p_torque) override;
+ virtual Vector3 get_constant_torque() const override;
+
virtual void set_sleep_state(bool p_sleep) override;
virtual bool is_sleeping() const override;
@@ -91,4 +103,4 @@ public:
virtual real_t get_step() const override;
};
-#endif // BODY_DIRECT_STATE_3D_SW_H
+#endif // GODOT_BODY_DIRECT_STATE_3D_H
diff --git a/servers/physics_3d/body_pair_3d_sw.cpp b/servers/physics_3d/godot_body_pair_3d.cpp
index c27a2ecced..89d5d59161 100644
--- a/servers/physics_3d/body_pair_3d_sw.cpp
+++ b/servers/physics_3d/godot_body_pair_3d.cpp
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* body_pair_3d_sw.cpp */
+/* godot_body_pair_3d.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,38 +28,22 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "body_pair_3d_sw.h"
+#include "godot_body_pair_3d.h"
-#include "collision_solver_3d_sw.h"
-#include "core/os/os.h"
-#include "space_3d_sw.h"
-
-/*
-#define NO_ACCUMULATE_IMPULSES
-#define NO_SPLIT_IMPULSES
+#include "godot_collision_solver_3d.h"
+#include "godot_space_3d.h"
-#define NO_FRICTION
-*/
-
-#define NO_TANGENTIALS
-/* BODY PAIR */
+#include "core/os/os.h"
-//#define ALLOWED_PENETRATION 0.01
-#define RELAXATION_TIMESTEPS 3
#define MIN_VELOCITY 0.0001
#define MAX_BIAS_ROTATION (Math_PI / 8)
-void BodyPair3DSW::_contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) {
- BodyPair3DSW *pair = (BodyPair3DSW *)p_userdata;
+void GodotBodyPair3D::_contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) {
+ GodotBodyPair3D *pair = (GodotBodyPair3D *)p_userdata;
pair->contact_added_callback(p_point_A, p_index_A, p_point_B, p_index_B);
}
-void BodyPair3DSW::contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B) {
- // check if we already have the contact
-
- //Vector3 local_A = A->get_inv_transform().xform(p_point_A);
- //Vector3 local_B = B->get_inv_transform().xform(p_point_B);
-
+void GodotBodyPair3D::contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B) {
Vector3 local_A = A->get_inv_transform().basis.xform(p_point_A);
Vector3 local_B = B->get_inv_transform().basis.xform(p_point_B - offset_B);
@@ -68,19 +52,14 @@ void BodyPair3DSW::contact_added_callback(const Vector3 &p_point_A, int p_index_
ERR_FAIL_COND(new_index >= (MAX_CONTACTS + 1));
Contact contact;
-
- contact.acc_normal_impulse = 0;
- contact.acc_bias_impulse = 0;
- contact.acc_bias_impulse_center_of_mass = 0;
- contact.acc_tangent_impulse = Vector3();
contact.index_A = p_index_A;
contact.index_B = p_index_B;
contact.local_A = local_A;
contact.local_B = local_B;
contact.normal = (p_point_A - p_point_B).normalized();
- contact.mass_normal = 0; // will be computed in setup()
+ contact.used = true;
- // attempt to determine if the contact will be reused
+ // Attempt to determine if the contact will be reused.
real_t contact_recycle_radius = space->get_contact_recycle_radius();
for (int i = 0; i < contact_count; i++) {
@@ -91,23 +70,34 @@ void BodyPair3DSW::contact_added_callback(const Vector3 &p_point_A, int p_index_
contact.acc_bias_impulse = c.acc_bias_impulse;
contact.acc_bias_impulse_center_of_mass = c.acc_bias_impulse_center_of_mass;
contact.acc_tangent_impulse = c.acc_tangent_impulse;
- new_index = i;
- break;
+ c = contact;
+ return;
}
}
- // figure out if the contact amount must be reduced to fit the new contact
-
+ // Figure out if the contact amount must be reduced to fit the new contact.
if (new_index == MAX_CONTACTS) {
- // remove the contact with the minimum depth
+ // Remove the contact with the minimum depth.
+
+ const Basis &basis_A = A->get_transform().basis;
+ const Basis &basis_B = B->get_transform().basis;
int least_deep = -1;
- real_t min_depth = 1e10;
+ real_t min_depth;
- for (int i = 0; i <= contact_count; i++) {
- Contact &c = (i == contact_count) ? contact : contacts[i];
- Vector3 global_A = A->get_transform().basis.xform(c.local_A);
- Vector3 global_B = B->get_transform().basis.xform(c.local_B) + offset_B;
+ // Start with depth for new contact.
+ {
+ Vector3 global_A = basis_A.xform(contact.local_A);
+ Vector3 global_B = basis_B.xform(contact.local_B) + offset_B;
+
+ Vector3 axis = global_A - global_B;
+ min_depth = axis.dot(contact.normal);
+ }
+
+ for (int i = 0; i < contact_count; i++) {
+ const Contact &c = contacts[i];
+ Vector3 global_A = basis_A.xform(c.local_A);
+ Vector3 global_B = basis_B.xform(c.local_B) + offset_B;
Vector3 axis = global_A - global_B;
real_t depth = axis.dot(c.normal);
@@ -118,10 +108,8 @@ void BodyPair3DSW::contact_added_callback(const Vector3 &p_point_A, int p_index_
}
}
- ERR_FAIL_COND(least_deep == -1);
-
- if (least_deep < contact_count) { //replace the last deep contact by the new one
-
+ if (least_deep > -1) {
+ // Replace the least deep contact by the new one.
contacts[least_deep] = contact;
}
@@ -129,29 +117,41 @@ void BodyPair3DSW::contact_added_callback(const Vector3 &p_point_A, int p_index_
}
contacts[new_index] = contact;
-
- if (new_index == contact_count) {
- contact_count++;
- }
+ contact_count++;
}
-void BodyPair3DSW::validate_contacts() {
- //make sure to erase contacts that are no longer valid
+void GodotBodyPair3D::validate_contacts() {
+ // Make sure to erase contacts that are no longer valid.
+ real_t max_separation = space->get_contact_max_separation();
+ real_t max_separation2 = max_separation * max_separation;
+
+ const Basis &basis_A = A->get_transform().basis;
+ const Basis &basis_B = B->get_transform().basis;
- real_t contact_max_separation = space->get_contact_max_separation();
for (int i = 0; i < contact_count; i++) {
Contact &c = contacts[i];
- Vector3 global_A = A->get_transform().basis.xform(c.local_A);
- Vector3 global_B = B->get_transform().basis.xform(c.local_B) + offset_B;
- Vector3 axis = global_A - global_B;
- real_t depth = axis.dot(c.normal);
+ bool erase = false;
+ if (!c.used) {
+ // Was left behind in previous frame.
+ erase = true;
+ } else {
+ c.used = false;
+
+ Vector3 global_A = basis_A.xform(c.local_A);
+ Vector3 global_B = basis_B.xform(c.local_B) + offset_B;
+ Vector3 axis = global_A - global_B;
+ real_t depth = axis.dot(c.normal);
- if (depth < -contact_max_separation || (global_B + c.normal * depth - global_A).length() > contact_max_separation) {
- // contact no longer needed, remove
+ if (depth < -max_separation || (global_B + c.normal * depth - global_A).length_squared() > max_separation2) {
+ erase = true;
+ }
+ }
+ if (erase) {
+ // Contact no longer needed, remove.
if ((i + 1) < contact_count) {
- // swap with the last one
+ // Swap with the last one.
SWAP(contacts[i], contacts[contact_count - 1]);
}
@@ -161,7 +161,7 @@ void BodyPair3DSW::validate_contacts() {
}
}
-bool BodyPair3DSW::_test_ccd(real_t p_step, Body3DSW *p_A, int p_shape_A, const Transform3D &p_xform_A, Body3DSW *p_B, int p_shape_B, const Transform3D &p_xform_B) {
+bool GodotBodyPair3D::_test_ccd(real_t p_step, GodotBody3D *p_A, int p_shape_A, const Transform3D &p_xform_A, GodotBody3D *p_B, int p_shape_B, const Transform3D &p_xform_B) {
Vector3 motion = p_A->get_linear_velocity() * p_step;
real_t mlen = motion.length();
if (mlen < CMP_EPSILON) {
@@ -172,29 +172,35 @@ bool BodyPair3DSW::_test_ccd(real_t p_step, Body3DSW *p_A, int p_shape_A, const
real_t min, max;
p_A->get_shape(p_shape_A)->project_range(mnormal, p_xform_A, min, max);
- bool fast_object = mlen > (max - min) * 0.3; //going too fast in that direction
- if (!fast_object) { //did it move enough in this direction to even attempt raycast? let's say it should move more than 1/3 the size of the object in that axis
+ // Did it move enough in this direction to even attempt raycast?
+ // Let's say it should move more than 1/3 the size of the object in that axis.
+ bool fast_object = mlen > (max - min) * 0.3;
+ if (!fast_object) {
return false;
}
- //cast a segment from support in motion normal, in the same direction of motion by motion length
- //support is the worst case collision point, so real collision happened before
+ // Going too fast in that direction.
+
+ // Cast a segment from support in motion normal, in the same direction of motion by motion length.
+ // Support is the worst case collision point, so real collision happened before.
Vector3 s = p_A->get_shape(p_shape_A)->get_support(p_xform_A.basis.xform(mnormal).normalized());
Vector3 from = p_xform_A.xform(s);
Vector3 to = from + motion;
Transform3D from_inv = p_xform_B.affine_inverse();
- Vector3 local_from = from_inv.xform(from - mnormal * mlen * 0.1); //start from a little inside the bounding box
+ // Start from a little inside the bounding box.
+ Vector3 local_from = from_inv.xform(from - mnormal * mlen * 0.1);
Vector3 local_to = from_inv.xform(to);
Vector3 rpos, rnorm;
- if (!p_B->get_shape(p_shape_B)->intersect_segment(local_from, local_to, rpos, rnorm)) {
+ if (!p_B->get_shape(p_shape_B)->intersect_segment(local_from, local_to, rpos, rnorm, true)) {
return false;
}
- //shorten the linear velocity so it does not hit, but gets close enough, next frame will hit softly or soft enough
+ // Shorten the linear velocity so it does not hit, but gets close enough,
+ // next frame will hit softly or soft enough.
Vector3 hitpos = p_xform_B.xform(rpos);
real_t newlen = hitpos.distance_to(from) - (max - min) * 0.01;
@@ -203,15 +209,17 @@ bool BodyPair3DSW::_test_ccd(real_t p_step, Body3DSW *p_A, int p_shape_A, const
return true;
}
-real_t combine_bounce(Body3DSW *A, Body3DSW *B) {
+real_t combine_bounce(GodotBody3D *A, GodotBody3D *B) {
return CLAMP(A->get_bounce() + B->get_bounce(), 0, 1);
}
-real_t combine_friction(Body3DSW *A, Body3DSW *B) {
+real_t combine_friction(GodotBody3D *A, GodotBody3D *B) {
return ABS(MIN(A->get_friction(), B->get_friction()));
}
-bool BodyPair3DSW::setup(real_t p_step) {
+bool GodotBodyPair3D::setup(real_t p_step) {
+ check_ccd = false;
+
if (!A->interacts_with(B) || A->has_exception(B->get_self()) || B->has_exception(A->get_self())) {
collided = false;
return false;
@@ -242,20 +250,20 @@ bool BodyPair3DSW::setup(real_t p_step) {
xform_Bu.origin -= offset_A;
Transform3D xform_B = xform_Bu * B->get_shape_transform(shape_B);
- Shape3DSW *shape_A_ptr = A->get_shape(shape_A);
- Shape3DSW *shape_B_ptr = B->get_shape(shape_B);
+ GodotShape3D *shape_A_ptr = A->get_shape(shape_A);
+ GodotShape3D *shape_B_ptr = B->get_shape(shape_B);
- collided = CollisionSolver3DSW::solve_static(shape_A_ptr, xform_A, shape_B_ptr, xform_B, _contact_added_callback, this, &sep_axis);
+ collided = GodotCollisionSolver3D::solve_static(shape_A_ptr, xform_A, shape_B_ptr, xform_B, _contact_added_callback, this, &sep_axis);
if (!collided) {
- //test ccd (currently just a raycast)
-
if (A->is_continuous_collision_detection_enabled() && collide_A) {
- _test_ccd(p_step, A, shape_A, xform_A, B, shape_B, xform_B);
+ check_ccd = true;
+ return true;
}
if (B->is_continuous_collision_detection_enabled() && collide_B) {
- _test_ccd(p_step, B, shape_B, xform_B, A, shape_A, xform_A);
+ check_ccd = true;
+ return true;
}
return false;
@@ -264,17 +272,35 @@ bool BodyPair3DSW::setup(real_t p_step) {
return true;
}
-bool BodyPair3DSW::pre_solve(real_t p_step) {
+bool GodotBodyPair3D::pre_solve(real_t p_step) {
if (!collided) {
+ if (check_ccd) {
+ const Vector3 &offset_A = A->get_transform().get_origin();
+ Transform3D xform_Au = Transform3D(A->get_transform().basis, Vector3());
+ Transform3D xform_A = xform_Au * A->get_shape_transform(shape_A);
+
+ Transform3D xform_Bu = B->get_transform();
+ xform_Bu.origin -= offset_A;
+ Transform3D xform_B = xform_Bu * B->get_shape_transform(shape_B);
+
+ if (A->is_continuous_collision_detection_enabled() && collide_A) {
+ _test_ccd(p_step, A, shape_A, xform_A, B, shape_B, xform_B);
+ }
+
+ if (B->is_continuous_collision_detection_enabled() && collide_B) {
+ _test_ccd(p_step, B, shape_B, xform_B, A, shape_A, xform_A);
+ }
+ }
+
return false;
}
real_t max_penetration = space->get_contact_max_allowed_penetration();
- real_t bias = (real_t)0.3;
+ real_t bias = 0.8;
- Shape3DSW *shape_A_ptr = A->get_shape(shape_A);
- Shape3DSW *shape_B_ptr = B->get_shape(shape_B);
+ GodotShape3D *shape_A_ptr = A->get_shape(shape_A);
+ GodotShape3D *shape_B_ptr = B->get_shape(shape_B);
if (shape_A_ptr->get_custom_bias() || shape_B_ptr->get_custom_bias()) {
if (shape_A_ptr->get_custom_bias() == 0) {
@@ -364,15 +390,12 @@ bool BodyPair3DSW::pre_solve(real_t p_step) {
if (collide_B) {
B->apply_impulse(j_vec, c.rB + B->get_center_of_mass());
}
- c.acc_bias_impulse = 0;
- c.acc_bias_impulse_center_of_mass = 0;
c.bounce = combine_bounce(A, B);
if (c.bounce) {
- Vector3 crA = A->get_angular_velocity().cross(c.rA);
- Vector3 crB = B->get_angular_velocity().cross(c.rB);
- Vector3 dv = B->get_linear_velocity() + crB - A->get_linear_velocity() - crA;
- //normal impule
+ Vector3 crA = A->get_prev_angular_velocity().cross(c.rA);
+ Vector3 crB = B->get_prev_angular_velocity().cross(c.rB);
+ Vector3 dv = B->get_prev_linear_velocity() + crB - A->get_prev_linear_velocity() - crA;
c.bounce = c.bounce * dv.dot(c.normal);
}
}
@@ -380,7 +403,7 @@ bool BodyPair3DSW::pre_solve(real_t p_step) {
return do_process;
}
-void BodyPair3DSW::solve(real_t p_step) {
+void GodotBodyPair3D::solve(real_t p_step) {
if (!collided) {
return;
}
@@ -494,8 +517,7 @@ void BodyPair3DSW::solve(real_t p_step) {
Vector3 temp1 = inv_inertia_tensor_A.xform(c.rA.cross(tv));
Vector3 temp2 = inv_inertia_tensor_B.xform(c.rB.cross(tv));
- real_t t = -tvl /
- (inv_mass_A + inv_mass_B + tv.dot(temp1.cross(c.rA) + temp2.cross(c.rB)));
+ real_t t = -tvl / (inv_mass_A + inv_mass_B + tv.dot(temp1.cross(c.rA) + temp2.cross(c.rB)));
Vector3 jt = t * tv;
@@ -523,8 +545,8 @@ void BodyPair3DSW::solve(real_t p_step) {
}
}
-BodyPair3DSW::BodyPair3DSW(Body3DSW *p_A, int p_shape_A, Body3DSW *p_B, int p_shape_B) :
- BodyContact3DSW(_arr, 2) {
+GodotBodyPair3D::GodotBodyPair3D(GodotBody3D *p_A, int p_shape_A, GodotBody3D *p_B, int p_shape_B) :
+ GodotBodyContact3D(_arr, 2) {
A = p_A;
B = p_B;
shape_A = p_shape_A;
@@ -534,31 +556,27 @@ BodyPair3DSW::BodyPair3DSW(Body3DSW *p_A, int p_shape_A, Body3DSW *p_B, int p_sh
B->add_constraint(this, 1);
}
-BodyPair3DSW::~BodyPair3DSW() {
+GodotBodyPair3D::~GodotBodyPair3D() {
A->remove_constraint(this);
B->remove_constraint(this);
}
-void BodySoftBodyPair3DSW::_contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) {
- BodySoftBodyPair3DSW *pair = (BodySoftBodyPair3DSW *)p_userdata;
+void GodotBodySoftBodyPair3D::_contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) {
+ GodotBodySoftBodyPair3D *pair = (GodotBodySoftBodyPair3D *)p_userdata;
pair->contact_added_callback(p_point_A, p_index_A, p_point_B, p_index_B);
}
-void BodySoftBodyPair3DSW::contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B) {
+void GodotBodySoftBodyPair3D::contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B) {
Vector3 local_A = body->get_inv_transform().xform(p_point_A);
Vector3 local_B = p_point_B - soft_body->get_node_position(p_index_B);
Contact contact;
contact.index_A = p_index_A;
contact.index_B = p_index_B;
- contact.acc_normal_impulse = 0;
- contact.acc_bias_impulse = 0;
- contact.acc_bias_impulse_center_of_mass = 0;
- contact.acc_tangent_impulse = Vector3();
contact.local_A = local_A;
contact.local_B = local_B;
contact.normal = (p_point_A - p_point_B).normalized();
- contact.mass_normal = 0;
+ contact.used = true;
// Attempt to determine if the contact will be reused.
real_t contact_recycle_radius = space->get_contact_recycle_radius();
@@ -582,22 +600,35 @@ void BodySoftBodyPair3DSW::contact_added_callback(const Vector3 &p_point_A, int
contacts.push_back(contact);
}
-void BodySoftBodyPair3DSW::validate_contacts() {
+void GodotBodySoftBodyPair3D::validate_contacts() {
// Make sure to erase contacts that are no longer valid.
- const Transform3D &transform_A = body->get_transform();
+ real_t max_separation = space->get_contact_max_separation();
+ real_t max_separation2 = max_separation * max_separation;
- real_t contact_max_separation = space->get_contact_max_separation();
+ const Transform3D &transform_A = body->get_transform();
uint32_t contact_count = contacts.size();
for (uint32_t contact_index = 0; contact_index < contact_count; ++contact_index) {
Contact &c = contacts[contact_index];
- Vector3 global_A = transform_A.xform(c.local_A);
- Vector3 global_B = soft_body->get_node_position(c.index_B) + c.local_B;
- Vector3 axis = global_A - global_B;
- real_t depth = axis.dot(c.normal);
+ bool erase = false;
+ if (!c.used) {
+ // Was left behind in previous frame.
+ erase = true;
+ } else {
+ c.used = false;
+
+ Vector3 global_A = transform_A.xform(c.local_A);
+ Vector3 global_B = soft_body->get_node_position(c.index_B) + c.local_B;
+ Vector3 axis = global_A - global_B;
+ real_t depth = axis.dot(c.normal);
+
+ if (depth < -max_separation || (global_B + c.normal * depth - global_A).length_squared() > max_separation2) {
+ erase = true;
+ }
+ }
- if (depth < -contact_max_separation || (global_B + c.normal * depth - global_A).length() > contact_max_separation) {
+ if (erase) {
// Contact no longer needed, remove.
if ((contact_index + 1) < contact_count) {
// Swap with the last one.
@@ -612,7 +643,7 @@ void BodySoftBodyPair3DSW::validate_contacts() {
contacts.resize(contact_count);
}
-bool BodySoftBodyPair3DSW::setup(real_t p_step) {
+bool GodotBodySoftBodyPair3D::setup(real_t p_step) {
if (!body->interacts_with(soft_body) || body->has_exception(soft_body->get_self()) || soft_body->has_exception(body->get_self())) {
collided = false;
return false;
@@ -638,24 +669,24 @@ bool BodySoftBodyPair3DSW::setup(real_t p_step) {
validate_contacts();
- Shape3DSW *shape_A_ptr = body->get_shape(body_shape);
- Shape3DSW *shape_B_ptr = soft_body->get_shape(0);
+ GodotShape3D *shape_A_ptr = body->get_shape(body_shape);
+ GodotShape3D *shape_B_ptr = soft_body->get_shape(0);
- collided = CollisionSolver3DSW::solve_static(shape_A_ptr, xform_A, shape_B_ptr, xform_B, _contact_added_callback, this, &sep_axis);
+ collided = GodotCollisionSolver3D::solve_static(shape_A_ptr, xform_A, shape_B_ptr, xform_B, _contact_added_callback, this, &sep_axis);
return collided;
}
-bool BodySoftBodyPair3DSW::pre_solve(real_t p_step) {
+bool GodotBodySoftBodyPair3D::pre_solve(real_t p_step) {
if (!collided) {
return false;
}
real_t max_penetration = space->get_contact_max_allowed_penetration();
- real_t bias = (real_t)0.3;
+ real_t bias = space->get_contact_bias();
- Shape3DSW *shape_A_ptr = body->get_shape(body_shape);
+ GodotShape3D *shape_A_ptr = body->get_shape(body_shape);
if (shape_A_ptr->get_custom_bias()) {
bias = shape_A_ptr->get_custom_bias();
@@ -736,8 +767,6 @@ bool BodySoftBodyPair3DSW::pre_solve(real_t p_step) {
if (soft_body_collides) {
soft_body->apply_node_impulse(c.index_B, j_vec);
}
- c.acc_bias_impulse = 0;
- c.acc_bias_impulse_center_of_mass = 0;
c.bounce = body->get_bounce();
@@ -753,7 +782,7 @@ bool BodySoftBodyPair3DSW::pre_solve(real_t p_step) {
return do_process;
}
-void BodySoftBodyPair3DSW::solve(real_t p_step) {
+void GodotBodySoftBodyPair3D::solve(real_t p_step) {
if (!collided) {
return;
}
@@ -862,8 +891,7 @@ void BodySoftBodyPair3DSW::solve(real_t p_step) {
Vector3 temp1 = body_inv_inertia_tensor.xform(c.rA.cross(tv));
- real_t t = -tvl /
- (body_inv_mass + node_inv_mass + tv.dot(temp1.cross(c.rA)));
+ real_t t = -tvl / (body_inv_mass + node_inv_mass + tv.dot(temp1.cross(c.rA)));
Vector3 jt = t * tv;
@@ -891,8 +919,8 @@ void BodySoftBodyPair3DSW::solve(real_t p_step) {
}
}
-BodySoftBodyPair3DSW::BodySoftBodyPair3DSW(Body3DSW *p_A, int p_shape_A, SoftBody3DSW *p_B) :
- BodyContact3DSW(&body, 1) {
+GodotBodySoftBodyPair3D::GodotBodySoftBodyPair3D(GodotBody3D *p_A, int p_shape_A, GodotSoftBody3D *p_B) :
+ GodotBodyContact3D(&body, 1) {
body = p_A;
soft_body = p_B;
body_shape = p_shape_A;
@@ -901,7 +929,7 @@ BodySoftBodyPair3DSW::BodySoftBodyPair3DSW(Body3DSW *p_A, int p_shape_A, SoftBod
soft_body->add_constraint(this);
}
-BodySoftBodyPair3DSW::~BodySoftBodyPair3DSW() {
+GodotBodySoftBodyPair3D::~GodotBodySoftBodyPair3D() {
body->remove_constraint(this);
soft_body->remove_constraint(this);
}
diff --git a/servers/physics_3d/body_pair_3d_sw.h b/servers/physics_3d/godot_body_pair_3d.h
index 01afb07e13..7a7309f9d5 100644
--- a/servers/physics_3d/body_pair_3d_sw.h
+++ b/servers/physics_3d/godot_body_pair_3d.h
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* body_pair_3d_sw.h */
+/* godot_body_pair_3d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,15 +28,16 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef BODY_PAIR_3D_SW_H
-#define BODY_PAIR_3D_SW_H
+#ifndef GODOT_BODY_PAIR_3D_H
+#define GODOT_BODY_PAIR_3D_H
+
+#include "godot_body_3d.h"
+#include "godot_constraint_3d.h"
+#include "godot_soft_body_3d.h"
-#include "body_3d_sw.h"
-#include "constraint_3d_sw.h"
#include "core/templates/local_vector.h"
-#include "soft_body_3d_sw.h"
-class BodyContact3DSW : public Constraint3DSW {
+class GodotBodyContact3D : public GodotConstraint3D {
protected:
struct Contact {
Vector3 position;
@@ -53,31 +54,33 @@ protected:
real_t depth = 0.0;
bool active = false;
+ bool used = false;
Vector3 rA, rB; // Offset in world orientation with respect to center of mass
};
Vector3 sep_axis;
bool collided = false;
+ bool check_ccd = false;
- Space3DSW *space = nullptr;
+ GodotSpace3D *space = nullptr;
- BodyContact3DSW(Body3DSW **p_body_ptr = nullptr, int p_body_count = 0) :
- Constraint3DSW(p_body_ptr, p_body_count) {
+ GodotBodyContact3D(GodotBody3D **p_body_ptr = nullptr, int p_body_count = 0) :
+ GodotConstraint3D(p_body_ptr, p_body_count) {
}
};
-class BodyPair3DSW : public BodyContact3DSW {
+class GodotBodyPair3D : public GodotBodyContact3D {
enum {
MAX_CONTACTS = 4
};
union {
struct {
- Body3DSW *A;
- Body3DSW *B;
+ GodotBody3D *A;
+ GodotBody3D *B;
};
- Body3DSW *_arr[2] = { nullptr, nullptr };
+ GodotBody3D *_arr[2] = { nullptr, nullptr };
};
int shape_A = 0;
@@ -98,20 +101,20 @@ class BodyPair3DSW : public BodyContact3DSW {
void contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B);
void validate_contacts();
- bool _test_ccd(real_t p_step, Body3DSW *p_A, int p_shape_A, const Transform3D &p_xform_A, Body3DSW *p_B, int p_shape_B, const Transform3D &p_xform_B);
+ bool _test_ccd(real_t p_step, GodotBody3D *p_A, int p_shape_A, const Transform3D &p_xform_A, GodotBody3D *p_B, int p_shape_B, const Transform3D &p_xform_B);
public:
virtual bool setup(real_t p_step) override;
virtual bool pre_solve(real_t p_step) override;
virtual void solve(real_t p_step) override;
- BodyPair3DSW(Body3DSW *p_A, int p_shape_A, Body3DSW *p_B, int p_shape_B);
- ~BodyPair3DSW();
+ GodotBodyPair3D(GodotBody3D *p_A, int p_shape_A, GodotBody3D *p_B, int p_shape_B);
+ ~GodotBodyPair3D();
};
-class BodySoftBodyPair3DSW : public BodyContact3DSW {
- Body3DSW *body = nullptr;
- SoftBody3DSW *soft_body = nullptr;
+class GodotBodySoftBodyPair3D : public GodotBodyContact3D {
+ GodotBody3D *body = nullptr;
+ GodotSoftBody3D *soft_body = nullptr;
int body_shape = 0;
@@ -133,11 +136,11 @@ public:
virtual bool pre_solve(real_t p_step) override;
virtual void solve(real_t p_step) override;
- virtual SoftBody3DSW *get_soft_body_ptr(int p_index) const override { return soft_body; }
+ virtual GodotSoftBody3D *get_soft_body_ptr(int p_index) const override { return soft_body; }
virtual int get_soft_body_count() const override { return 1; }
- BodySoftBodyPair3DSW(Body3DSW *p_A, int p_shape_A, SoftBody3DSW *p_B);
- ~BodySoftBodyPair3DSW();
+ GodotBodySoftBodyPair3D(GodotBody3D *p_A, int p_shape_A, GodotSoftBody3D *p_B);
+ ~GodotBodySoftBodyPair3D();
};
-#endif // BODY_PAIR_3D_SW_H
+#endif // GODOT_BODY_PAIR_3D_H
diff --git a/servers/physics_3d/broad_phase_3d_sw.cpp b/servers/physics_3d/godot_broad_phase_3d.cpp
index 8aa64034ec..115a01a0c5 100644
--- a/servers/physics_3d/broad_phase_3d_sw.cpp
+++ b/servers/physics_3d/godot_broad_phase_3d.cpp
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* broad_phase_3d_sw.cpp */
+/* godot_broad_phase_3d.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,9 +28,9 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "broad_phase_3d_sw.h"
+#include "godot_broad_phase_3d.h"
-BroadPhase3DSW::CreateFunction BroadPhase3DSW::create_func = nullptr;
+GodotBroadPhase3D::CreateFunction GodotBroadPhase3D::create_func = nullptr;
-BroadPhase3DSW::~BroadPhase3DSW() {
+GodotBroadPhase3D::~GodotBroadPhase3D() {
}
diff --git a/servers/physics_3d/broad_phase_3d_sw.h b/servers/physics_3d/godot_broad_phase_3d.h
index 98313cb216..75196cbd1b 100644
--- a/servers/physics_3d/broad_phase_3d_sw.h
+++ b/servers/physics_3d/godot_broad_phase_3d.h
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* broad_phase_3d_sw.h */
+/* godot_broad_phase_3d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,45 +28,45 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef BROAD_PHASE_SW_H
-#define BROAD_PHASE_SW_H
+#ifndef GODOT_BROAD_PHASE_3D_H
+#define GODOT_BROAD_PHASE_3D_H
#include "core/math/aabb.h"
#include "core/math/math_funcs.h"
-class CollisionObject3DSW;
+class GodotCollisionObject3D;
-class BroadPhase3DSW {
+class GodotBroadPhase3D {
public:
- typedef BroadPhase3DSW *(*CreateFunction)();
+ typedef GodotBroadPhase3D *(*CreateFunction)();
static CreateFunction create_func;
typedef uint32_t ID;
- typedef void *(*PairCallback)(CollisionObject3DSW *A, int p_subindex_A, CollisionObject3DSW *B, int p_subindex_B, void *p_userdata);
- typedef void (*UnpairCallback)(CollisionObject3DSW *A, int p_subindex_A, CollisionObject3DSW *B, int p_subindex_B, void *p_data, void *p_userdata);
+ typedef void *(*PairCallback)(GodotCollisionObject3D *A, int p_subindex_A, GodotCollisionObject3D *B, int p_subindex_B, void *p_userdata);
+ typedef void (*UnpairCallback)(GodotCollisionObject3D *A, int p_subindex_A, GodotCollisionObject3D *B, int p_subindex_B, void *p_data, void *p_userdata);
// 0 is an invalid ID
- virtual ID create(CollisionObject3DSW *p_object_, int p_subindex = 0, const AABB &p_aabb = AABB(), bool p_static = false) = 0;
+ virtual ID create(GodotCollisionObject3D *p_object_, int p_subindex = 0, const AABB &p_aabb = AABB(), bool p_static = false) = 0;
virtual void move(ID p_id, const AABB &p_aabb) = 0;
virtual void set_static(ID p_id, bool p_static) = 0;
virtual void remove(ID p_id) = 0;
- virtual CollisionObject3DSW *get_object(ID p_id) const = 0;
+ virtual GodotCollisionObject3D *get_object(ID p_id) const = 0;
virtual bool is_static(ID p_id) const = 0;
virtual int get_subindex(ID p_id) const = 0;
- virtual int cull_point(const Vector3 &p_point, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices = nullptr) = 0;
- virtual int cull_segment(const Vector3 &p_from, const Vector3 &p_to, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices = nullptr) = 0;
- virtual int cull_aabb(const AABB &p_aabb, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices = nullptr) = 0;
+ virtual int cull_point(const Vector3 &p_point, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices = nullptr) = 0;
+ virtual int cull_segment(const Vector3 &p_from, const Vector3 &p_to, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices = nullptr) = 0;
+ virtual int cull_aabb(const AABB &p_aabb, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices = nullptr) = 0;
virtual void set_pair_callback(PairCallback p_pair_callback, void *p_userdata) = 0;
virtual void set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata) = 0;
virtual void update() = 0;
- virtual ~BroadPhase3DSW();
+ virtual ~GodotBroadPhase3D();
};
-#endif // BROAD_PHASE__SW_H
+#endif // GODOT_BROAD_PHASE_3D_H
diff --git a/servers/physics_3d/broad_phase_3d_bvh.cpp b/servers/physics_3d/godot_broad_phase_3d_bvh.cpp
index d89e0e1f6d..9a6b96c411 100644
--- a/servers/physics_3d/broad_phase_3d_bvh.cpp
+++ b/servers/physics_3d/godot_broad_phase_3d_bvh.cpp
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* broad_phase_3d_bvh.cpp */
+/* godot_broad_phase_3d_bvh.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,55 +28,56 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "broad_phase_3d_bvh.h"
-#include "collision_object_3d_sw.h"
+#include "godot_broad_phase_3d_bvh.h"
-BroadPhase3DBVH::ID BroadPhase3DBVH::create(CollisionObject3DSW *p_object, int p_subindex, const AABB &p_aabb, bool p_static) {
+#include "godot_collision_object_3d.h"
+
+GodotBroadPhase3DBVH::ID GodotBroadPhase3DBVH::create(GodotCollisionObject3D *p_object, int p_subindex, const AABB &p_aabb, bool p_static) {
ID oid = bvh.create(p_object, true, p_aabb, p_subindex, !p_static, 1 << p_object->get_type(), p_static ? 0 : 0xFFFFF); // Pair everything, don't care?
return oid + 1;
}
-void BroadPhase3DBVH::move(ID p_id, const AABB &p_aabb) {
+void GodotBroadPhase3DBVH::move(ID p_id, const AABB &p_aabb) {
bvh.move(p_id - 1, p_aabb);
}
-void BroadPhase3DBVH::set_static(ID p_id, bool p_static) {
- CollisionObject3DSW *it = bvh.get(p_id - 1);
+void GodotBroadPhase3DBVH::set_static(ID p_id, bool p_static) {
+ GodotCollisionObject3D *it = bvh.get(p_id - 1);
bvh.set_pairable(p_id - 1, !p_static, 1 << it->get_type(), p_static ? 0 : 0xFFFFF, false); // Pair everything, don't care?
}
-void BroadPhase3DBVH::remove(ID p_id) {
+void GodotBroadPhase3DBVH::remove(ID p_id) {
bvh.erase(p_id - 1);
}
-CollisionObject3DSW *BroadPhase3DBVH::get_object(ID p_id) const {
- CollisionObject3DSW *it = bvh.get(p_id - 1);
+GodotCollisionObject3D *GodotBroadPhase3DBVH::get_object(ID p_id) const {
+ GodotCollisionObject3D *it = bvh.get(p_id - 1);
ERR_FAIL_COND_V(!it, nullptr);
return it;
}
-bool BroadPhase3DBVH::is_static(ID p_id) const {
+bool GodotBroadPhase3DBVH::is_static(ID p_id) const {
return !bvh.is_pairable(p_id - 1);
}
-int BroadPhase3DBVH::get_subindex(ID p_id) const {
+int GodotBroadPhase3DBVH::get_subindex(ID p_id) const {
return bvh.get_subindex(p_id - 1);
}
-int BroadPhase3DBVH::cull_point(const Vector3 &p_point, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices) {
+int GodotBroadPhase3DBVH::cull_point(const Vector3 &p_point, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices) {
return bvh.cull_point(p_point, p_results, p_max_results, p_result_indices);
}
-int BroadPhase3DBVH::cull_segment(const Vector3 &p_from, const Vector3 &p_to, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices) {
+int GodotBroadPhase3DBVH::cull_segment(const Vector3 &p_from, const Vector3 &p_to, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices) {
return bvh.cull_segment(p_from, p_to, p_results, p_max_results, p_result_indices);
}
-int BroadPhase3DBVH::cull_aabb(const AABB &p_aabb, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices) {
+int GodotBroadPhase3DBVH::cull_aabb(const AABB &p_aabb, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices) {
return bvh.cull_aabb(p_aabb, p_results, p_max_results, p_result_indices);
}
-void *BroadPhase3DBVH::_pair_callback(void *self, uint32_t p_A, CollisionObject3DSW *p_object_A, int subindex_A, uint32_t p_B, CollisionObject3DSW *p_object_B, int subindex_B) {
- BroadPhase3DBVH *bpo = (BroadPhase3DBVH *)(self);
+void *GodotBroadPhase3DBVH::_pair_callback(void *self, uint32_t p_A, GodotCollisionObject3D *p_object_A, int subindex_A, uint32_t p_B, GodotCollisionObject3D *p_object_B, int subindex_B) {
+ GodotBroadPhase3DBVH *bpo = (GodotBroadPhase3DBVH *)(self);
if (!bpo->pair_callback) {
return nullptr;
}
@@ -84,8 +85,8 @@ void *BroadPhase3DBVH::_pair_callback(void *self, uint32_t p_A, CollisionObject3
return bpo->pair_callback(p_object_A, subindex_A, p_object_B, subindex_B, bpo->pair_userdata);
}
-void BroadPhase3DBVH::_unpair_callback(void *self, uint32_t p_A, CollisionObject3DSW *p_object_A, int subindex_A, uint32_t p_B, CollisionObject3DSW *p_object_B, int subindex_B, void *pairdata) {
- BroadPhase3DBVH *bpo = (BroadPhase3DBVH *)(self);
+void GodotBroadPhase3DBVH::_unpair_callback(void *self, uint32_t p_A, GodotCollisionObject3D *p_object_A, int subindex_A, uint32_t p_B, GodotCollisionObject3D *p_object_B, int subindex_B, void *pairdata) {
+ GodotBroadPhase3DBVH *bpo = (GodotBroadPhase3DBVH *)(self);
if (!bpo->unpair_callback) {
return;
}
@@ -93,25 +94,25 @@ void BroadPhase3DBVH::_unpair_callback(void *self, uint32_t p_A, CollisionObject
bpo->unpair_callback(p_object_A, subindex_A, p_object_B, subindex_B, pairdata, bpo->unpair_userdata);
}
-void BroadPhase3DBVH::set_pair_callback(PairCallback p_pair_callback, void *p_userdata) {
+void GodotBroadPhase3DBVH::set_pair_callback(PairCallback p_pair_callback, void *p_userdata) {
pair_callback = p_pair_callback;
pair_userdata = p_userdata;
}
-void BroadPhase3DBVH::set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata) {
+void GodotBroadPhase3DBVH::set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata) {
unpair_callback = p_unpair_callback;
unpair_userdata = p_userdata;
}
-void BroadPhase3DBVH::update() {
+void GodotBroadPhase3DBVH::update() {
bvh.update();
}
-BroadPhase3DSW *BroadPhase3DBVH::_create() {
- return memnew(BroadPhase3DBVH);
+GodotBroadPhase3D *GodotBroadPhase3DBVH::_create() {
+ return memnew(GodotBroadPhase3DBVH);
}
-BroadPhase3DBVH::BroadPhase3DBVH() {
+GodotBroadPhase3DBVH::GodotBroadPhase3DBVH() {
bvh.set_pair_callback(_pair_callback, this);
bvh.set_unpair_callback(_unpair_callback, this);
}
diff --git a/servers/physics_3d/broad_phase_3d_bvh.h b/servers/physics_3d/godot_broad_phase_3d_bvh.h
index 03131c9db2..7138019a9c 100644
--- a/servers/physics_3d/broad_phase_3d_bvh.h
+++ b/servers/physics_3d/godot_broad_phase_3d_bvh.h
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* broad_phase_3d_bvh.h */
+/* godot_broad_phase_3d_bvh.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,17 +28,18 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef BROAD_PHASE_3D_BVH_H
-#define BROAD_PHASE_3D_BVH_H
+#ifndef GODOT_BROAD_PHASE_3D_BVH_H
+#define GODOT_BROAD_PHASE_3D_BVH_H
+
+#include "godot_broad_phase_3d.h"
-#include "broad_phase_3d_sw.h"
#include "core/math/bvh.h"
-class BroadPhase3DBVH : public BroadPhase3DSW {
- BVH_Manager<CollisionObject3DSW, true, 128> bvh;
+class GodotBroadPhase3DBVH : public GodotBroadPhase3D {
+ BVH_Manager<GodotCollisionObject3D, true, 128> bvh;
- static void *_pair_callback(void *, uint32_t, CollisionObject3DSW *, int, uint32_t, CollisionObject3DSW *, int);
- static void _unpair_callback(void *, uint32_t, CollisionObject3DSW *, int, uint32_t, CollisionObject3DSW *, int, void *);
+ static void *_pair_callback(void *, uint32_t, GodotCollisionObject3D *, int, uint32_t, GodotCollisionObject3D *, int);
+ static void _unpair_callback(void *, uint32_t, GodotCollisionObject3D *, int, uint32_t, GodotCollisionObject3D *, int, void *);
PairCallback pair_callback = nullptr;
void *pair_userdata = nullptr;
@@ -47,26 +48,26 @@ class BroadPhase3DBVH : public BroadPhase3DSW {
public:
// 0 is an invalid ID
- virtual ID create(CollisionObject3DSW *p_object, int p_subindex = 0, const AABB &p_aabb = AABB(), bool p_static = false);
+ virtual ID create(GodotCollisionObject3D *p_object, int p_subindex = 0, const AABB &p_aabb = AABB(), bool p_static = false);
virtual void move(ID p_id, const AABB &p_aabb);
virtual void set_static(ID p_id, bool p_static);
virtual void remove(ID p_id);
- virtual CollisionObject3DSW *get_object(ID p_id) const;
+ virtual GodotCollisionObject3D *get_object(ID p_id) const;
virtual bool is_static(ID p_id) const;
virtual int get_subindex(ID p_id) const;
- virtual int cull_point(const Vector3 &p_point, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices = nullptr);
- virtual int cull_segment(const Vector3 &p_from, const Vector3 &p_to, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices = nullptr);
- virtual int cull_aabb(const AABB &p_aabb, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices = nullptr);
+ virtual int cull_point(const Vector3 &p_point, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices = nullptr);
+ virtual int cull_segment(const Vector3 &p_from, const Vector3 &p_to, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices = nullptr);
+ virtual int cull_aabb(const AABB &p_aabb, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices = nullptr);
virtual void set_pair_callback(PairCallback p_pair_callback, void *p_userdata);
virtual void set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata);
virtual void update();
- static BroadPhase3DSW *_create();
- BroadPhase3DBVH();
+ static GodotBroadPhase3D *_create();
+ GodotBroadPhase3DBVH();
};
-#endif // BROAD_PHASE_3D_BVH_H
+#endif // GODOT_BROAD_PHASE_3D_BVH_H
diff --git a/servers/physics_3d/collision_object_3d_sw.cpp b/servers/physics_3d/godot_collision_object_3d.cpp
index 098f627d11..63284aeca5 100644
--- a/servers/physics_3d/collision_object_3d_sw.cpp
+++ b/servers/physics_3d/godot_collision_object_3d.cpp
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* collision_object_3d_sw.cpp */
+/* godot_collision_object_3d.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,11 +28,12 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "collision_object_3d_sw.h"
-#include "servers/physics_3d/physics_server_3d_sw.h"
-#include "space_3d_sw.h"
+#include "godot_collision_object_3d.h"
-void CollisionObject3DSW::add_shape(Shape3DSW *p_shape, const Transform3D &p_transform, bool p_disabled) {
+#include "godot_physics_server_3d.h"
+#include "godot_space_3d.h"
+
+void GodotCollisionObject3D::add_shape(GodotShape3D *p_shape, const Transform3D &p_transform, bool p_disabled) {
Shape s;
s.shape = p_shape;
s.xform = p_transform;
@@ -43,35 +44,35 @@ void CollisionObject3DSW::add_shape(Shape3DSW *p_shape, const Transform3D &p_tra
p_shape->add_owner(this);
if (!pending_shape_update_list.in_list()) {
- PhysicsServer3DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list);
+ GodotPhysicsServer3D::godot_singleton->pending_shape_update_list.add(&pending_shape_update_list);
}
}
-void CollisionObject3DSW::set_shape(int p_index, Shape3DSW *p_shape) {
+void GodotCollisionObject3D::set_shape(int p_index, GodotShape3D *p_shape) {
ERR_FAIL_INDEX(p_index, shapes.size());
shapes[p_index].shape->remove_owner(this);
shapes.write[p_index].shape = p_shape;
p_shape->add_owner(this);
if (!pending_shape_update_list.in_list()) {
- PhysicsServer3DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list);
+ GodotPhysicsServer3D::godot_singleton->pending_shape_update_list.add(&pending_shape_update_list);
}
}
-void CollisionObject3DSW::set_shape_transform(int p_index, const Transform3D &p_transform) {
+void GodotCollisionObject3D::set_shape_transform(int p_index, const Transform3D &p_transform) {
ERR_FAIL_INDEX(p_index, shapes.size());
shapes.write[p_index].xform = p_transform;
shapes.write[p_index].xform_inv = p_transform.affine_inverse();
if (!pending_shape_update_list.in_list()) {
- PhysicsServer3DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list);
+ GodotPhysicsServer3D::godot_singleton->pending_shape_update_list.add(&pending_shape_update_list);
}
}
-void CollisionObject3DSW::set_shape_disabled(int p_idx, bool p_disabled) {
+void GodotCollisionObject3D::set_shape_disabled(int p_idx, bool p_disabled) {
ERR_FAIL_INDEX(p_idx, shapes.size());
- CollisionObject3DSW::Shape &shape = shapes.write[p_idx];
+ GodotCollisionObject3D::Shape &shape = shapes.write[p_idx];
if (shape.disabled == p_disabled) {
return;
}
@@ -86,16 +87,16 @@ void CollisionObject3DSW::set_shape_disabled(int p_idx, bool p_disabled) {
space->get_broadphase()->remove(shape.bpid);
shape.bpid = 0;
if (!pending_shape_update_list.in_list()) {
- PhysicsServer3DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list);
+ GodotPhysicsServer3D::godot_singleton->pending_shape_update_list.add(&pending_shape_update_list);
}
} else if (!p_disabled && shape.bpid == 0) {
if (!pending_shape_update_list.in_list()) {
- PhysicsServer3DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list);
+ GodotPhysicsServer3D::godot_singleton->pending_shape_update_list.add(&pending_shape_update_list);
}
}
}
-void CollisionObject3DSW::remove_shape(Shape3DSW *p_shape) {
+void GodotCollisionObject3D::remove_shape(GodotShape3D *p_shape) {
//remove a shape, all the times it appears
for (int i = 0; i < shapes.size(); i++) {
if (shapes[i].shape == p_shape) {
@@ -105,7 +106,7 @@ void CollisionObject3DSW::remove_shape(Shape3DSW *p_shape) {
}
}
-void CollisionObject3DSW::remove_shape(int p_index) {
+void GodotCollisionObject3D::remove_shape(int p_index) {
//remove anything from shape to be erased to end, so subindices don't change
ERR_FAIL_INDEX(p_index, shapes.size());
for (int i = p_index; i < shapes.size(); i++) {
@@ -117,14 +118,14 @@ void CollisionObject3DSW::remove_shape(int p_index) {
shapes.write[i].bpid = 0;
}
shapes[p_index].shape->remove_owner(this);
- shapes.remove(p_index);
+ shapes.remove_at(p_index);
if (!pending_shape_update_list.in_list()) {
- PhysicsServer3DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list);
+ GodotPhysicsServer3D::godot_singleton->pending_shape_update_list.add(&pending_shape_update_list);
}
}
-void CollisionObject3DSW::_set_static(bool p_static) {
+void GodotCollisionObject3D::_set_static(bool p_static) {
if (_static == p_static) {
return;
}
@@ -141,7 +142,7 @@ void CollisionObject3DSW::_set_static(bool p_static) {
}
}
-void CollisionObject3DSW::_unregister_shapes() {
+void GodotCollisionObject3D::_unregister_shapes() {
for (int i = 0; i < shapes.size(); i++) {
Shape &s = shapes.write[i];
if (s.bpid > 0) {
@@ -151,7 +152,7 @@ void CollisionObject3DSW::_unregister_shapes() {
}
}
-void CollisionObject3DSW::_update_shapes() {
+void GodotCollisionObject3D::_update_shapes() {
if (!space) {
return;
}
@@ -170,7 +171,7 @@ void CollisionObject3DSW::_update_shapes() {
s.aabb_cache = shape_aabb;
Vector3 scale = xform.get_basis().get_scale();
- s.area_cache = s.shape->get_area() * scale.x * scale.y * scale.z;
+ s.area_cache = s.shape->get_volume() * scale.x * scale.y * scale.z;
if (s.bpid == 0) {
s.bpid = space->get_broadphase()->create(this, i, shape_aabb, _static);
@@ -181,7 +182,7 @@ void CollisionObject3DSW::_update_shapes() {
}
}
-void CollisionObject3DSW::_update_shapes_with_motion(const Vector3 &p_motion) {
+void GodotCollisionObject3D::_update_shapes_with_motion(const Vector3 &p_motion) {
if (!space) {
return;
}
@@ -208,7 +209,7 @@ void CollisionObject3DSW::_update_shapes_with_motion(const Vector3 &p_motion) {
}
}
-void CollisionObject3DSW::_set_space(Space3DSW *p_space) {
+void GodotCollisionObject3D::_set_space(GodotSpace3D *p_space) {
if (space) {
space->remove_object(this);
@@ -229,12 +230,12 @@ void CollisionObject3DSW::_set_space(Space3DSW *p_space) {
}
}
-void CollisionObject3DSW::_shape_changed() {
+void GodotCollisionObject3D::_shape_changed() {
_update_shapes();
_shapes_changed();
}
-CollisionObject3DSW::CollisionObject3DSW(Type p_type) :
+GodotCollisionObject3D::GodotCollisionObject3D(Type p_type) :
pending_shape_update_list(this) {
type = p_type;
}
diff --git a/servers/physics_3d/collision_object_3d_sw.h b/servers/physics_3d/godot_collision_object_3d.h
index 3aa48946b7..0178838a25 100644
--- a/servers/physics_3d/collision_object_3d_sw.h
+++ b/servers/physics_3d/godot_collision_object_3d.h
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* collision_object_3d_sw.h */
+/* godot_collision_object_3d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,13 +28,14 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef COLLISION_OBJECT_SW_H
-#define COLLISION_OBJECT_SW_H
+#ifndef GODOT_COLLISION_OBJECT_3D_H
+#define GODOT_COLLISION_OBJECT_3D_H
+
+#include "godot_broad_phase_3d.h"
+#include "godot_shape_3d.h"
-#include "broad_phase_3d_sw.h"
#include "core/templates/self_list.h"
#include "servers/physics_server_3d.h"
-#include "shape_3d_sw.h"
#ifdef DEBUG_ENABLED
#define MAX_OBJECT_DISTANCE 3.1622776601683791e+18
@@ -42,9 +43,9 @@
#define MAX_OBJECT_DISTANCE_X2 (MAX_OBJECT_DISTANCE * MAX_OBJECT_DISTANCE)
#endif
-class Space3DSW;
+class GodotSpace3D;
-class CollisionObject3DSW : public ShapeOwner3DSW {
+class GodotCollisionObject3D : public GodotShapeOwner3D {
public:
enum Type {
TYPE_AREA,
@@ -62,20 +63,20 @@ private:
struct Shape {
Transform3D xform;
Transform3D xform_inv;
- BroadPhase3DSW::ID bpid;
+ GodotBroadPhase3D::ID bpid;
AABB aabb_cache; //for rayqueries
real_t area_cache = 0.0;
- Shape3DSW *shape = nullptr;
+ GodotShape3D *shape = nullptr;
bool disabled = false;
};
Vector<Shape> shapes;
- Space3DSW *space = nullptr;
+ GodotSpace3D *space = nullptr;
Transform3D transform;
Transform3D inv_transform;
bool _static = true;
- SelfList<CollisionObject3DSW> pending_shape_update_list;
+ SelfList<GodotCollisionObject3D> pending_shape_update_list;
void _update_shapes();
@@ -98,11 +99,11 @@ protected:
void _set_static(bool p_static);
virtual void _shapes_changed() = 0;
- void _set_space(Space3DSW *p_space);
+ void _set_space(GodotSpace3D *p_space);
bool ray_pickable = true;
- CollisionObject3DSW(Type p_type);
+ GodotCollisionObject3D(Type p_type);
public:
_FORCE_INLINE_ void set_self(const RID &p_self) { self = p_self; }
@@ -114,11 +115,11 @@ public:
void _shape_changed();
_FORCE_INLINE_ Type get_type() const { return type; }
- void add_shape(Shape3DSW *p_shape, const Transform3D &p_transform = Transform3D(), bool p_disabled = false);
- void set_shape(int p_index, Shape3DSW *p_shape);
+ void add_shape(GodotShape3D *p_shape, const Transform3D &p_transform = Transform3D(), bool p_disabled = false);
+ void set_shape(int p_index, GodotShape3D *p_shape);
void set_shape_transform(int p_index, const Transform3D &p_transform);
_FORCE_INLINE_ int get_shape_count() const { return shapes.size(); }
- _FORCE_INLINE_ Shape3DSW *get_shape(int p_index) const {
+ _FORCE_INLINE_ GodotShape3D *get_shape(int p_index) const {
CRASH_BAD_INDEX(p_index, shapes.size());
return shapes[p_index].shape;
}
@@ -141,7 +142,7 @@ public:
_FORCE_INLINE_ const Transform3D &get_transform() const { return transform; }
_FORCE_INLINE_ const Transform3D &get_inv_transform() const { return inv_transform; }
- _FORCE_INLINE_ Space3DSW *get_space() const { return space; }
+ _FORCE_INLINE_ GodotSpace3D *get_space() const { return space; }
_FORCE_INLINE_ void set_ray_pickable(bool p_enable) { ray_pickable = p_enable; }
_FORCE_INLINE_ bool is_ray_pickable() const { return ray_pickable; }
@@ -164,22 +165,22 @@ public:
}
_FORCE_INLINE_ uint32_t get_collision_mask() const { return collision_mask; }
- _FORCE_INLINE_ bool collides_with(CollisionObject3DSW *p_other) const {
+ _FORCE_INLINE_ bool collides_with(GodotCollisionObject3D *p_other) const {
return p_other->collision_layer & collision_mask;
}
- _FORCE_INLINE_ bool interacts_with(CollisionObject3DSW *p_other) const {
+ _FORCE_INLINE_ bool interacts_with(GodotCollisionObject3D *p_other) const {
return collision_layer & p_other->collision_mask || p_other->collision_layer & collision_mask;
}
- void remove_shape(Shape3DSW *p_shape);
+ void remove_shape(GodotShape3D *p_shape);
void remove_shape(int p_index);
- virtual void set_space(Space3DSW *p_space) = 0;
+ virtual void set_space(GodotSpace3D *p_space) = 0;
_FORCE_INLINE_ bool is_static() const { return _static; }
- virtual ~CollisionObject3DSW() {}
+ virtual ~GodotCollisionObject3D() {}
};
-#endif // COLLISION_OBJECT_SW_H
+#endif // GODOT_COLLISION_OBJECT_3D_H
diff --git a/servers/physics_3d/collision_solver_3d_sw.cpp b/servers/physics_3d/godot_collision_solver_3d.cpp
index dcc363638e..81e1a88366 100644
--- a/servers/physics_3d/collision_solver_3d_sw.cpp
+++ b/servers/physics_3d/godot_collision_solver_3d.cpp
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* collision_solver_3d_sw.cpp */
+/* godot_collision_solver_3d.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,17 +28,17 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "collision_solver_3d_sw.h"
-#include "collision_solver_3d_sat.h"
-#include "soft_body_3d_sw.h"
+#include "godot_collision_solver_3d.h"
+#include "godot_collision_solver_3d_sat.h"
+#include "godot_soft_body_3d.h"
#include "gjk_epa.h"
#define collision_solver sat_calculate_penetration
//#define collision_solver gjk_epa_calculate_penetration
-bool CollisionSolver3DSW::solve_static_world_boundary(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result) {
- const WorldBoundaryShape3DSW *world_boundary = static_cast<const WorldBoundaryShape3DSW *>(p_shape_A);
+bool GodotCollisionSolver3D::solve_static_world_boundary(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result) {
+ const GodotWorldBoundaryShape3D *world_boundary = static_cast<const GodotWorldBoundaryShape3D *>(p_shape_A);
if (p_shape_B->get_type() == PhysicsServer3D::SHAPE_WORLD_BOUNDARY) {
return false;
}
@@ -47,10 +47,10 @@ bool CollisionSolver3DSW::solve_static_world_boundary(const Shape3DSW *p_shape_A
static const int max_supports = 16;
Vector3 supports[max_supports];
int support_count;
- Shape3DSW::FeatureType support_type;
+ GodotShape3D::FeatureType support_type;
p_shape_B->get_supports(p_transform_B.basis.xform_inv(-p.normal).normalized(), max_supports, supports, support_count, support_type);
- if (support_type == Shape3DSW::FEATURE_CIRCLE) {
+ if (support_type == GodotShape3D::FEATURE_CIRCLE) {
ERR_FAIL_COND_V(support_count != 3, false);
Vector3 circle_pos = supports[0];
@@ -89,8 +89,8 @@ bool CollisionSolver3DSW::solve_static_world_boundary(const Shape3DSW *p_shape_A
return found;
}
-bool CollisionSolver3DSW::solve_separation_ray(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin) {
- const SeparationRayShape3DSW *ray = static_cast<const SeparationRayShape3DSW *>(p_shape_A);
+bool GodotCollisionSolver3D::solve_separation_ray(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin) {
+ const GodotSeparationRayShape3D *ray = static_cast<const GodotSeparationRayShape3D *>(p_shape_A);
Vector3 from = p_transform_A.origin;
Vector3 to = from + p_transform_A.basis.get_axis(2) * (ray->get_length() + p_margin);
@@ -102,7 +102,7 @@ bool CollisionSolver3DSW::solve_separation_ray(const Shape3DSW *p_shape_A, const
to = ai.xform(to);
Vector3 p, n;
- if (!p_shape_B->intersect_segment(from, to, p, n)) {
+ if (!p_shape_B->intersect_segment(from, to, p, n, true)) {
return false;
}
@@ -134,13 +134,13 @@ bool CollisionSolver3DSW::solve_separation_ray(const Shape3DSW *p_shape_A, const
struct _SoftBodyContactCollisionInfo {
int node_index = 0;
- CollisionSolver3DSW::CallbackResult result_callback = nullptr;
+ GodotCollisionSolver3D::CallbackResult result_callback = nullptr;
void *userdata = nullptr;
bool swap_result = false;
int contact_count = 0;
};
-void CollisionSolver3DSW::soft_body_contact_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) {
+void GodotCollisionSolver3D::soft_body_contact_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) {
_SoftBodyContactCollisionInfo &cinfo = *(_SoftBodyContactCollisionInfo *)(p_userdata);
++cinfo.contact_count;
@@ -157,9 +157,9 @@ void CollisionSolver3DSW::soft_body_contact_callback(const Vector3 &p_point_A, i
}
struct _SoftBodyQueryInfo {
- SoftBody3DSW *soft_body = nullptr;
- const Shape3DSW *shape_A = nullptr;
- const Shape3DSW *shape_B = nullptr;
+ GodotSoftBody3D *soft_body = nullptr;
+ const GodotShape3D *shape_A = nullptr;
+ const GodotShape3D *shape_B = nullptr;
Transform3D transform_A;
Transform3D node_transform;
_SoftBodyContactCollisionInfo contact_info;
@@ -169,7 +169,7 @@ struct _SoftBodyQueryInfo {
#endif
};
-bool CollisionSolver3DSW::soft_body_query_callback(uint32_t p_node_index, void *p_userdata) {
+bool GodotCollisionSolver3D::soft_body_query_callback(uint32_t p_node_index, void *p_userdata) {
_SoftBodyQueryInfo &query_cinfo = *(_SoftBodyQueryInfo *)(p_userdata);
Vector3 node_position = query_cinfo.soft_body->get_node_position(p_node_index);
@@ -188,7 +188,7 @@ bool CollisionSolver3DSW::soft_body_query_callback(uint32_t p_node_index, void *
return (collided && !query_cinfo.contact_info.result_callback);
}
-bool CollisionSolver3DSW::soft_body_concave_callback(void *p_userdata, Shape3DSW *p_convex) {
+bool GodotCollisionSolver3D::soft_body_concave_callback(void *p_userdata, GodotShape3D *p_convex) {
_SoftBodyQueryInfo &query_cinfo = *(_SoftBodyQueryInfo *)(p_userdata);
query_cinfo.shape_A = p_convex;
@@ -220,15 +220,15 @@ bool CollisionSolver3DSW::soft_body_concave_callback(void *p_userdata, Shape3DSW
return (collided && !query_cinfo.contact_info.result_callback);
}
-bool CollisionSolver3DSW::solve_soft_body(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result) {
- const SoftBodyShape3DSW *soft_body_shape_B = static_cast<const SoftBodyShape3DSW *>(p_shape_B);
+bool GodotCollisionSolver3D::solve_soft_body(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result) {
+ const GodotSoftBodyShape3D *soft_body_shape_B = static_cast<const GodotSoftBodyShape3D *>(p_shape_B);
- SoftBody3DSW *soft_body = soft_body_shape_B->get_soft_body();
+ GodotSoftBody3D *soft_body = soft_body_shape_B->get_soft_body();
const Transform3D &world_to_local = soft_body->get_inv_transform();
const real_t collision_margin = soft_body->get_collision_margin();
- SphereShape3DSW sphere_shape;
+ GodotSphereShape3D sphere_shape;
sphere_shape.set_data(collision_margin);
_SoftBodyQueryInfo query_cinfo;
@@ -243,7 +243,7 @@ bool CollisionSolver3DSW::solve_soft_body(const Shape3DSW *p_shape_A, const Tran
if (p_shape_A->is_concave()) {
// In case of concave shape, query convex shapes first.
- const ConcaveShape3DSW *concave_shape_A = static_cast<const ConcaveShape3DSW *>(p_shape_A);
+ const GodotConcaveShape3D *concave_shape_A = static_cast<const GodotConcaveShape3D *>(p_shape_A);
AABB soft_body_aabb = soft_body->get_bounds();
soft_body_aabb.grow_by(collision_margin);
@@ -264,7 +264,7 @@ bool CollisionSolver3DSW::solve_soft_body(const Shape3DSW *p_shape_A, const Tran
local_aabb.size[i] = smax - smin;
}
- concave_shape_A->cull(local_aabb, soft_body_concave_callback, &query_cinfo);
+ concave_shape_A->cull(local_aabb, soft_body_concave_callback, &query_cinfo, true);
} else {
AABB shape_aabb = p_transform_A.xform(p_shape_A->get_aabb());
shape_aabb.grow_by(collision_margin);
@@ -277,9 +277,9 @@ bool CollisionSolver3DSW::solve_soft_body(const Shape3DSW *p_shape_A, const Tran
struct _ConcaveCollisionInfo {
const Transform3D *transform_A;
- const Shape3DSW *shape_A;
+ const GodotShape3D *shape_A;
const Transform3D *transform_B;
- CollisionSolver3DSW::CallbackResult result_callback;
+ GodotCollisionSolver3D::CallbackResult result_callback;
void *userdata;
bool swap_result;
bool collided;
@@ -291,7 +291,7 @@ struct _ConcaveCollisionInfo {
Vector3 close_A, close_B;
};
-bool CollisionSolver3DSW::concave_callback(void *p_userdata, Shape3DSW *p_convex) {
+bool GodotCollisionSolver3D::concave_callback(void *p_userdata, GodotShape3D *p_convex) {
_ConcaveCollisionInfo &cinfo = *(_ConcaveCollisionInfo *)(p_userdata);
cinfo.aabb_tests++;
@@ -307,8 +307,8 @@ bool CollisionSolver3DSW::concave_callback(void *p_userdata, Shape3DSW *p_convex
return !cinfo.result_callback;
}
-bool CollisionSolver3DSW::solve_concave(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin_A, real_t p_margin_B) {
- const ConcaveShape3DSW *concave_B = static_cast<const ConcaveShape3DSW *>(p_shape_B);
+bool GodotCollisionSolver3D::solve_concave(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin_A, real_t p_margin_B) {
+ const GodotConcaveShape3D *concave_B = static_cast<const GodotConcaveShape3D *>(p_shape_B);
_ConcaveCollisionInfo cinfo;
cinfo.transform_A = &p_transform_A;
@@ -346,12 +346,12 @@ bool CollisionSolver3DSW::solve_concave(const Shape3DSW *p_shape_A, const Transf
local_aabb.size[i] = smax - smin;
}
- concave_B->cull(local_aabb, concave_callback, &cinfo);
+ concave_B->cull(local_aabb, concave_callback, &cinfo, false);
return cinfo.collided;
}
-bool CollisionSolver3DSW::solve_static(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, Vector3 *r_sep_axis, real_t p_margin_A, real_t p_margin_B) {
+bool GodotCollisionSolver3D::solve_static(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, Vector3 *r_sep_axis, real_t p_margin_A, real_t p_margin_B) {
PhysicsServer3D::ShapeType type_A = p_shape_A->get_type();
PhysicsServer3D::ShapeType type_B = p_shape_B->get_type();
bool concave_A = p_shape_A->is_concave();
@@ -421,7 +421,7 @@ bool CollisionSolver3DSW::solve_static(const Shape3DSW *p_shape_A, const Transfo
}
}
-bool CollisionSolver3DSW::concave_distance_callback(void *p_userdata, Shape3DSW *p_convex) {
+bool GodotCollisionSolver3D::concave_distance_callback(void *p_userdata, GodotShape3D *p_convex) {
_ConcaveCollisionInfo &cinfo = *(_ConcaveCollisionInfo *)(p_userdata);
cinfo.aabb_tests++;
@@ -443,8 +443,8 @@ bool CollisionSolver3DSW::concave_distance_callback(void *p_userdata, Shape3DSW
return false;
}
-bool CollisionSolver3DSW::solve_distance_world_boundary(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B) {
- const WorldBoundaryShape3DSW *world_boundary = static_cast<const WorldBoundaryShape3DSW *>(p_shape_A);
+bool GodotCollisionSolver3D::solve_distance_world_boundary(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B) {
+ const GodotWorldBoundaryShape3D *world_boundary = static_cast<const GodotWorldBoundaryShape3D *>(p_shape_A);
if (p_shape_B->get_type() == PhysicsServer3D::SHAPE_WORLD_BOUNDARY) {
return false;
}
@@ -453,11 +453,11 @@ bool CollisionSolver3DSW::solve_distance_world_boundary(const Shape3DSW *p_shape
static const int max_supports = 16;
Vector3 supports[max_supports];
int support_count;
- Shape3DSW::FeatureType support_type;
+ GodotShape3D::FeatureType support_type;
p_shape_B->get_supports(p_transform_B.basis.xform_inv(-p.normal).normalized(), max_supports, supports, support_count, support_type);
- if (support_type == Shape3DSW::FEATURE_CIRCLE) {
+ if (support_type == GodotShape3D::FEATURE_CIRCLE) {
ERR_FAIL_COND_V(support_count != 3, false);
Vector3 circle_pos = supports[0];
@@ -495,7 +495,7 @@ bool CollisionSolver3DSW::solve_distance_world_boundary(const Shape3DSW *p_shape
return collided;
}
-bool CollisionSolver3DSW::solve_distance(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B, const AABB &p_concave_hint, Vector3 *r_sep_axis) {
+bool GodotCollisionSolver3D::solve_distance(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B, const AABB &p_concave_hint, Vector3 *r_sep_axis) {
if (p_shape_A->is_concave()) {
return false;
}
@@ -512,7 +512,7 @@ bool CollisionSolver3DSW::solve_distance(const Shape3DSW *p_shape_A, const Trans
return false;
}
- const ConcaveShape3DSW *concave_B = static_cast<const ConcaveShape3DSW *>(p_shape_B);
+ const GodotConcaveShape3D *concave_B = static_cast<const GodotConcaveShape3D *>(p_shape_B);
_ConcaveCollisionInfo cinfo;
cinfo.transform_A = &p_transform_A;
@@ -547,7 +547,7 @@ bool CollisionSolver3DSW::solve_distance(const Shape3DSW *p_shape_A, const Trans
real_t smin, smax;
if (use_cc_hint) {
- cc_hint_aabb.project_range_in_plane(Plane(axis, 0), smin, smax);
+ cc_hint_aabb.project_range_in_plane(Plane(axis), smin, smax);
} else {
p_shape_A->project_range(axis, rel_transform, smin, smax);
}
@@ -559,7 +559,7 @@ bool CollisionSolver3DSW::solve_distance(const Shape3DSW *p_shape_A, const Trans
local_aabb.size[i] = smax - smin;
}
- concave_B->cull(local_aabb, concave_distance_callback, &cinfo);
+ concave_B->cull(local_aabb, concave_distance_callback, &cinfo, false);
if (!cinfo.collided) {
r_point_A = cinfo.close_A;
r_point_B = cinfo.close_B;
diff --git a/servers/physics_3d/collision_solver_3d_sw.h b/servers/physics_3d/godot_collision_solver_3d.h
index 0a9ea7c0eb..a6a0ebfead 100644
--- a/servers/physics_3d/collision_solver_3d_sw.h
+++ b/servers/physics_3d/godot_collision_solver_3d.h
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* collision_solver_3d_sw.h */
+/* godot_collision_solver_3d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,30 +28,30 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef COLLISION_SOLVER_SW_H
-#define COLLISION_SOLVER_SW_H
+#ifndef GODOT_COLLISION_SOLVER_3D_H
+#define GODOT_COLLISION_SOLVER_3D_H
-#include "shape_3d_sw.h"
+#include "godot_shape_3d.h"
-class CollisionSolver3DSW {
+class GodotCollisionSolver3D {
public:
typedef void (*CallbackResult)(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata);
private:
static bool soft_body_query_callback(uint32_t p_node_index, void *p_userdata);
static void soft_body_contact_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata);
- static bool soft_body_concave_callback(void *p_userdata, Shape3DSW *p_convex);
- static bool concave_callback(void *p_userdata, Shape3DSW *p_convex);
- static bool solve_static_world_boundary(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result);
- static bool solve_separation_ray(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin = 0);
- static bool solve_soft_body(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result);
- static bool solve_concave(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin_A = 0, real_t p_margin_B = 0);
- static bool concave_distance_callback(void *p_userdata, Shape3DSW *p_convex);
- static bool solve_distance_world_boundary(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B);
+ static bool soft_body_concave_callback(void *p_userdata, GodotShape3D *p_convex);
+ static bool concave_callback(void *p_userdata, GodotShape3D *p_convex);
+ static bool solve_static_world_boundary(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result);
+ static bool solve_separation_ray(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin = 0);
+ static bool solve_soft_body(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result);
+ static bool solve_concave(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin_A = 0, real_t p_margin_B = 0);
+ static bool concave_distance_callback(void *p_userdata, GodotShape3D *p_convex);
+ static bool solve_distance_world_boundary(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B);
public:
- static bool solve_static(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, Vector3 *r_sep_axis = nullptr, real_t p_margin_A = 0, real_t p_margin_B = 0);
- static bool solve_distance(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B, const AABB &p_concave_hint, Vector3 *r_sep_axis = nullptr);
+ static bool solve_static(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, Vector3 *r_sep_axis = nullptr, real_t p_margin_A = 0, real_t p_margin_B = 0);
+ static bool solve_distance(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B, const AABB &p_concave_hint, Vector3 *r_sep_axis = nullptr);
};
-#endif // COLLISION_SOLVER__SW_H
+#endif // GODOT_COLLISION_SOLVER_3D_H
diff --git a/servers/physics_3d/collision_solver_3d_sat.cpp b/servers/physics_3d/godot_collision_solver_3d_sat.cpp
index 76738bb746..82e04a7e31 100644
--- a/servers/physics_3d/collision_solver_3d_sat.cpp
+++ b/servers/physics_3d/godot_collision_solver_3d_sat.cpp
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* collision_solver_3d_sat.cpp */
+/* godot_collision_solver_3d_sat.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,13 +28,16 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "collision_solver_3d_sat.h"
-#include "core/math/geometry_3d.h"
+#include "godot_collision_solver_3d_sat.h"
#include "gjk_epa.h"
+#include "core/math/geometry_3d.h"
+
#define fallback_collision_solver gjk_epa_calculate_penetration
+#define _BACKFACE_NORMAL_THRESHOLD -0.0002
+
// Cylinder SAT analytic methods and face-circle contact points for cylinder-trimesh and cylinder-box collision are based on ODE colliders.
/*
@@ -65,7 +68,7 @@
*************************************************************************/
struct _CollectorCallback {
- CollisionSolver3DSW::CallbackResult callback;
+ GodotCollisionSolver3D::CallbackResult callback;
void *userdata = nullptr;
bool swap = false;
bool collided = false;
@@ -183,7 +186,7 @@ static void _generate_contacts_edge_circle(const Vector3 *p_points_A, int p_poin
real_t circle_B_radius = circle_B_line_1.length();
Vector3 circle_B_normal = circle_B_line_1.cross(circle_B_line_2).normalized();
- Plane circle_plane(circle_B_pos, circle_B_normal);
+ Plane circle_plane(circle_B_normal, circle_B_pos);
static const int max_clip = 2;
Vector3 contact_points[max_clip];
@@ -299,7 +302,7 @@ static void _generate_contacts_face_face(const Vector3 *p_points_A, int p_point_
Vector3 clip_normal = (edge0_B - edge1_B).cross(plane_B.normal).normalized();
// make a clip plane
- Plane clip(edge0_B, clip_normal);
+ Plane clip(clip_normal, edge0_B);
// avoid double clip if A is edge
int dst_idx = 0;
bool edge = clipbuf_len == 2;
@@ -385,7 +388,7 @@ static void _generate_contacts_face_circle(const Vector3 *p_points_A, int p_poin
// Clip face with circle plane.
Vector3 circle_B_normal = circle_B_line_1.cross(circle_B_line_2).normalized();
- Plane circle_plane(circle_B_pos, circle_B_normal);
+ Plane circle_plane(circle_B_normal, circle_B_pos);
static const int max_clip = 32;
Vector3 contact_points[max_clip];
@@ -522,7 +525,7 @@ static void _generate_contacts_circle_circle(const Vector3 *p_points_A, int p_po
}
}
- Plane circle_B_plane(circle_B_pos, circle_B_normal);
+ Plane circle_B_plane(circle_B_normal, circle_B_pos);
// Generate contact points.
for (int i = 0; i < num_points; i++) {
@@ -539,7 +542,7 @@ static void _generate_contacts_circle_circle(const Vector3 *p_points_A, int p_po
}
}
-static void _generate_contacts_from_supports(const Vector3 *p_points_A, int p_point_count_A, Shape3DSW::FeatureType p_feature_type_A, const Vector3 *p_points_B, int p_point_count_B, Shape3DSW::FeatureType p_feature_type_B, _CollectorCallback *p_callback) {
+static void _generate_contacts_from_supports(const Vector3 *p_points_A, int p_point_count_A, GodotShape3D::FeatureType p_feature_type_A, const Vector3 *p_points_B, int p_point_count_B, GodotShape3D::FeatureType p_feature_type_B, _CollectorCallback *p_callback) {
#ifdef DEBUG_ENABLED
ERR_FAIL_COND(p_point_count_A < 1);
ERR_FAIL_COND(p_point_count_B < 1);
@@ -611,13 +614,14 @@ class SeparatorAxisTest {
const Transform3D *transform_A = nullptr;
const Transform3D *transform_B = nullptr;
real_t best_depth = 1e15;
- Vector3 best_axis;
_CollectorCallback *callback = nullptr;
real_t margin_A = 0.0;
real_t margin_B = 0.0;
Vector3 separator_axis;
public:
+ Vector3 best_axis;
+
_FORCE_INLINE_ bool test_previous_axis() {
if (callback && callback->prev_axis && *callback->prev_axis != Vector3()) {
return test_axis(*callback->prev_axis);
@@ -626,7 +630,7 @@ public:
}
}
- _FORCE_INLINE_ bool test_axis(const Vector3 &p_axis, bool p_directional = false) {
+ _FORCE_INLINE_ bool test_axis(const Vector3 &p_axis) {
Vector3 axis = p_axis;
if (axis.is_equal_approx(Vector3())) {
@@ -660,12 +664,7 @@ public:
//use the smallest depth
if (min_B < 0.0) { // could be +0.0, we don't want it to become -0.0
- if (p_directional) {
- min_B = max_B;
- axis = -axis;
- } else {
- min_B = -min_B;
- }
+ min_B = -min_B;
}
if (max_B < min_B) {
@@ -713,7 +712,7 @@ public:
Vector3 supports_A[max_supports];
int support_count_A;
- Shape3DSW::FeatureType support_type_A;
+ GodotShape3D::FeatureType support_type_A;
shape_A->get_supports(transform_A->basis.xform_inv(-best_axis).normalized(), max_supports, supports_A, support_count_A, support_type_A);
for (int i = 0; i < support_count_A; i++) {
supports_A[i] = transform_A->xform(supports_A[i]);
@@ -727,7 +726,7 @@ public:
Vector3 supports_B[max_supports];
int support_count_B;
- Shape3DSW::FeatureType support_type_B;
+ GodotShape3D::FeatureType support_type_B;
shape_B->get_supports(transform_B->basis.xform_inv(best_axis).normalized(), max_supports, supports_B, support_count_B, support_type_B);
for (int i = 0; i < support_count_B; i++) {
supports_B[i] = transform_B->xform(supports_B[i]);
@@ -761,14 +760,14 @@ public:
/****** SAT TESTS *******/
-typedef void (*CollisionFunc)(const Shape3DSW *, const Transform3D &, const Shape3DSW *, const Transform3D &, _CollectorCallback *p_callback, real_t, real_t);
+typedef void (*CollisionFunc)(const GodotShape3D *, const Transform3D &, const GodotShape3D *, const Transform3D &, _CollectorCallback *p_callback, real_t, real_t);
template <bool withMargin>
-static void _collision_sphere_sphere(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
- const SphereShape3DSW *sphere_A = static_cast<const SphereShape3DSW *>(p_a);
- const SphereShape3DSW *sphere_B = static_cast<const SphereShape3DSW *>(p_b);
+static void _collision_sphere_sphere(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+ const GodotSphereShape3D *sphere_A = static_cast<const GodotSphereShape3D *>(p_a);
+ const GodotSphereShape3D *sphere_B = static_cast<const GodotSphereShape3D *>(p_b);
- SeparatorAxisTest<SphereShape3DSW, SphereShape3DSW, withMargin> separator(sphere_A, p_transform_a, sphere_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
+ SeparatorAxisTest<GodotSphereShape3D, GodotSphereShape3D, withMargin> separator(sphere_A, p_transform_a, sphere_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
// previous axis
@@ -784,11 +783,11 @@ static void _collision_sphere_sphere(const Shape3DSW *p_a, const Transform3D &p_
}
template <bool withMargin>
-static void _collision_sphere_box(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
- const SphereShape3DSW *sphere_A = static_cast<const SphereShape3DSW *>(p_a);
- const BoxShape3DSW *box_B = static_cast<const BoxShape3DSW *>(p_b);
+static void _collision_sphere_box(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+ const GodotSphereShape3D *sphere_A = static_cast<const GodotSphereShape3D *>(p_a);
+ const GodotBoxShape3D *box_B = static_cast<const GodotBoxShape3D *>(p_b);
- SeparatorAxisTest<SphereShape3DSW, BoxShape3DSW, withMargin> separator(sphere_A, p_transform_a, box_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
+ SeparatorAxisTest<GodotSphereShape3D, GodotBoxShape3D, withMargin> separator(sphere_A, p_transform_a, box_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
if (!separator.test_previous_axis()) {
return;
@@ -835,11 +834,11 @@ static void _collision_sphere_box(const Shape3DSW *p_a, const Transform3D &p_tra
}
template <bool withMargin>
-static void _collision_sphere_capsule(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
- const SphereShape3DSW *sphere_A = static_cast<const SphereShape3DSW *>(p_a);
- const CapsuleShape3DSW *capsule_B = static_cast<const CapsuleShape3DSW *>(p_b);
+static void _collision_sphere_capsule(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+ const GodotSphereShape3D *sphere_A = static_cast<const GodotSphereShape3D *>(p_a);
+ const GodotCapsuleShape3D *capsule_B = static_cast<const GodotCapsuleShape3D *>(p_b);
- SeparatorAxisTest<SphereShape3DSW, CapsuleShape3DSW, withMargin> separator(sphere_A, p_transform_a, capsule_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
+ SeparatorAxisTest<GodotSphereShape3D, GodotCapsuleShape3D, withMargin> separator(sphere_A, p_transform_a, capsule_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
if (!separator.test_previous_axis()) {
return;
@@ -877,11 +876,11 @@ static void _collision_sphere_capsule(const Shape3DSW *p_a, const Transform3D &p
}
template <bool withMargin>
-static void _collision_sphere_cylinder(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
- const SphereShape3DSW *sphere_A = static_cast<const SphereShape3DSW *>(p_a);
- const CylinderShape3DSW *cylinder_B = static_cast<const CylinderShape3DSW *>(p_b);
+static void _collision_sphere_cylinder(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+ const GodotSphereShape3D *sphere_A = static_cast<const GodotSphereShape3D *>(p_a);
+ const GodotCylinderShape3D *cylinder_B = static_cast<const GodotCylinderShape3D *>(p_b);
- SeparatorAxisTest<SphereShape3DSW, CylinderShape3DSW, withMargin> separator(sphere_A, p_transform_a, cylinder_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
+ SeparatorAxisTest<GodotSphereShape3D, GodotCylinderShape3D, withMargin> separator(sphere_A, p_transform_a, cylinder_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
if (!separator.test_previous_axis()) {
return;
@@ -936,11 +935,11 @@ static void _collision_sphere_cylinder(const Shape3DSW *p_a, const Transform3D &
}
template <bool withMargin>
-static void _collision_sphere_convex_polygon(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
- const SphereShape3DSW *sphere_A = static_cast<const SphereShape3DSW *>(p_a);
- const ConvexPolygonShape3DSW *convex_polygon_B = static_cast<const ConvexPolygonShape3DSW *>(p_b);
+static void _collision_sphere_convex_polygon(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+ const GodotSphereShape3D *sphere_A = static_cast<const GodotSphereShape3D *>(p_a);
+ const GodotConvexPolygonShape3D *convex_polygon_B = static_cast<const GodotConvexPolygonShape3D *>(p_b);
- SeparatorAxisTest<SphereShape3DSW, ConvexPolygonShape3DSW, withMargin> separator(sphere_A, p_transform_a, convex_polygon_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
+ SeparatorAxisTest<GodotSphereShape3D, GodotConvexPolygonShape3D, withMargin> separator(sphere_A, p_transform_a, convex_polygon_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
if (!separator.test_previous_axis()) {
return;
@@ -999,11 +998,11 @@ static void _collision_sphere_convex_polygon(const Shape3DSW *p_a, const Transfo
}
template <bool withMargin>
-static void _collision_sphere_face(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
- const SphereShape3DSW *sphere_A = static_cast<const SphereShape3DSW *>(p_a);
- const FaceShape3DSW *face_B = static_cast<const FaceShape3DSW *>(p_b);
+static void _collision_sphere_face(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+ const GodotSphereShape3D *sphere_A = static_cast<const GodotSphereShape3D *>(p_a);
+ const GodotFaceShape3D *face_B = static_cast<const GodotFaceShape3D *>(p_b);
- SeparatorAxisTest<SphereShape3DSW, FaceShape3DSW, withMargin> separator(sphere_A, p_transform_a, face_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
+ SeparatorAxisTest<GodotSphereShape3D, GodotFaceShape3D, withMargin> separator(sphere_A, p_transform_a, face_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
Vector3 vertex[3] = {
p_transform_b.xform(face_B->vertex[0]),
@@ -1013,7 +1012,7 @@ static void _collision_sphere_face(const Shape3DSW *p_a, const Transform3D &p_tr
Vector3 normal = (vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized();
- if (!separator.test_axis(normal, !face_B->backface_collision)) {
+ if (!separator.test_axis(normal)) {
return;
}
@@ -1040,15 +1039,26 @@ static void _collision_sphere_face(const Shape3DSW *p_a, const Transform3D &p_tr
}
}
+ if (!face_B->backface_collision) {
+ if (separator.best_axis.dot(normal) < _BACKFACE_NORMAL_THRESHOLD) {
+ if (face_B->invert_backface_collision) {
+ separator.best_axis = separator.best_axis.bounce(normal);
+ } else {
+ // Just ignore backface collision.
+ return;
+ }
+ }
+ }
+
separator.generate_contacts();
}
template <bool withMargin>
-static void _collision_box_box(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
- const BoxShape3DSW *box_A = static_cast<const BoxShape3DSW *>(p_a);
- const BoxShape3DSW *box_B = static_cast<const BoxShape3DSW *>(p_b);
+static void _collision_box_box(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+ const GodotBoxShape3D *box_A = static_cast<const GodotBoxShape3D *>(p_a);
+ const GodotBoxShape3D *box_B = static_cast<const GodotBoxShape3D *>(p_b);
- SeparatorAxisTest<BoxShape3DSW, BoxShape3DSW, withMargin> separator(box_A, p_transform_a, box_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
+ SeparatorAxisTest<GodotBoxShape3D, GodotBoxShape3D, withMargin> separator(box_A, p_transform_a, box_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
if (!separator.test_previous_axis()) {
return;
@@ -1142,11 +1152,11 @@ static void _collision_box_box(const Shape3DSW *p_a, const Transform3D &p_transf
}
template <bool withMargin>
-static void _collision_box_capsule(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
- const BoxShape3DSW *box_A = static_cast<const BoxShape3DSW *>(p_a);
- const CapsuleShape3DSW *capsule_B = static_cast<const CapsuleShape3DSW *>(p_b);
+static void _collision_box_capsule(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+ const GodotBoxShape3D *box_A = static_cast<const GodotBoxShape3D *>(p_a);
+ const GodotCapsuleShape3D *capsule_B = static_cast<const GodotCapsuleShape3D *>(p_b);
- SeparatorAxisTest<BoxShape3DSW, CapsuleShape3DSW, withMargin> separator(box_A, p_transform_a, capsule_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
+ SeparatorAxisTest<GodotBoxShape3D, GodotCapsuleShape3D, withMargin> separator(box_A, p_transform_a, capsule_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
if (!separator.test_previous_axis()) {
return;
@@ -1194,7 +1204,7 @@ static void _collision_box_capsule(const Shape3DSW *p_a, const Transform3D &p_tr
}
//Vector3 axis = (point - cyl_axis * cyl_axis.dot(point)).normalized();
- Vector3 axis = Plane(cyl_axis, 0).project(point).normalized();
+ Vector3 axis = Plane(cyl_axis).project(point).normalized();
if (!separator.test_axis(axis)) {
return;
@@ -1240,11 +1250,11 @@ static void _collision_box_capsule(const Shape3DSW *p_a, const Transform3D &p_tr
}
template <bool withMargin>
-static void _collision_box_cylinder(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
- const BoxShape3DSW *box_A = static_cast<const BoxShape3DSW *>(p_a);
- const CylinderShape3DSW *cylinder_B = static_cast<const CylinderShape3DSW *>(p_b);
+static void _collision_box_cylinder(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+ const GodotBoxShape3D *box_A = static_cast<const GodotBoxShape3D *>(p_a);
+ const GodotCylinderShape3D *cylinder_B = static_cast<const GodotCylinderShape3D *>(p_b);
- SeparatorAxisTest<BoxShape3DSW, CylinderShape3DSW, withMargin> separator(box_A, p_transform_a, cylinder_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
+ SeparatorAxisTest<GodotBoxShape3D, GodotCylinderShape3D, withMargin> separator(box_A, p_transform_a, cylinder_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
if (!separator.test_previous_axis()) {
return;
@@ -1303,7 +1313,7 @@ static void _collision_box_cylinder(const Shape3DSW *p_a, const Transform3D &p_t
// Points of A, cylinder lateral surface.
for (int i = 0; i < 8; i++) {
const Vector3 &point = vertices_A[i];
- Vector3 axis = Plane(cyl_axis, 0).project(point).normalized();
+ Vector3 axis = Plane(cyl_axis).project(point).normalized();
if (!separator.test_axis(axis)) {
return;
@@ -1353,11 +1363,11 @@ static void _collision_box_cylinder(const Shape3DSW *p_a, const Transform3D &p_t
}
template <bool withMargin>
-static void _collision_box_convex_polygon(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
- const BoxShape3DSW *box_A = static_cast<const BoxShape3DSW *>(p_a);
- const ConvexPolygonShape3DSW *convex_polygon_B = static_cast<const ConvexPolygonShape3DSW *>(p_b);
+static void _collision_box_convex_polygon(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+ const GodotBoxShape3D *box_A = static_cast<const GodotBoxShape3D *>(p_a);
+ const GodotConvexPolygonShape3D *convex_polygon_B = static_cast<const GodotConvexPolygonShape3D *>(p_b);
- SeparatorAxisTest<BoxShape3DSW, ConvexPolygonShape3DSW, withMargin> separator(box_A, p_transform_a, convex_polygon_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
+ SeparatorAxisTest<GodotBoxShape3D, GodotConvexPolygonShape3D, withMargin> separator(box_A, p_transform_a, convex_polygon_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
if (!separator.test_previous_axis()) {
return;
@@ -1471,11 +1481,11 @@ static void _collision_box_convex_polygon(const Shape3DSW *p_a, const Transform3
}
template <bool withMargin>
-static void _collision_box_face(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
- const BoxShape3DSW *box_A = static_cast<const BoxShape3DSW *>(p_a);
- const FaceShape3DSW *face_B = static_cast<const FaceShape3DSW *>(p_b);
+static void _collision_box_face(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+ const GodotBoxShape3D *box_A = static_cast<const GodotBoxShape3D *>(p_a);
+ const GodotFaceShape3D *face_B = static_cast<const GodotFaceShape3D *>(p_b);
- SeparatorAxisTest<BoxShape3DSW, FaceShape3DSW, withMargin> separator(box_A, p_transform_a, face_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
+ SeparatorAxisTest<GodotBoxShape3D, GodotFaceShape3D, withMargin> separator(box_A, p_transform_a, face_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
Vector3 vertex[3] = {
p_transform_b.xform(face_B->vertex[0]),
@@ -1485,7 +1495,7 @@ static void _collision_box_face(const Shape3DSW *p_a, const Transform3D &p_trans
Vector3 normal = (vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized();
- if (!separator.test_axis(normal, !face_B->backface_collision)) {
+ if (!separator.test_axis(normal)) {
return;
}
@@ -1590,15 +1600,26 @@ static void _collision_box_face(const Shape3DSW *p_a, const Transform3D &p_trans
}
}
+ if (!face_B->backface_collision) {
+ if (separator.best_axis.dot(normal) < _BACKFACE_NORMAL_THRESHOLD) {
+ if (face_B->invert_backface_collision) {
+ separator.best_axis = separator.best_axis.bounce(normal);
+ } else {
+ // Just ignore backface collision.
+ return;
+ }
+ }
+ }
+
separator.generate_contacts();
}
template <bool withMargin>
-static void _collision_capsule_capsule(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
- const CapsuleShape3DSW *capsule_A = static_cast<const CapsuleShape3DSW *>(p_a);
- const CapsuleShape3DSW *capsule_B = static_cast<const CapsuleShape3DSW *>(p_b);
+static void _collision_capsule_capsule(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+ const GodotCapsuleShape3D *capsule_A = static_cast<const GodotCapsuleShape3D *>(p_a);
+ const GodotCapsuleShape3D *capsule_B = static_cast<const GodotCapsuleShape3D *>(p_b);
- SeparatorAxisTest<CapsuleShape3DSW, CapsuleShape3DSW, withMargin> separator(capsule_A, p_transform_a, capsule_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
+ SeparatorAxisTest<GodotCapsuleShape3D, GodotCapsuleShape3D, withMargin> separator(capsule_A, p_transform_a, capsule_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
if (!separator.test_previous_axis()) {
return;
@@ -1658,11 +1679,11 @@ static void _collision_capsule_capsule(const Shape3DSW *p_a, const Transform3D &
}
template <bool withMargin>
-static void _collision_capsule_cylinder(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
- const CapsuleShape3DSW *capsule_A = static_cast<const CapsuleShape3DSW *>(p_a);
- const CylinderShape3DSW *cylinder_B = static_cast<const CylinderShape3DSW *>(p_b);
+static void _collision_capsule_cylinder(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+ const GodotCapsuleShape3D *capsule_A = static_cast<const GodotCapsuleShape3D *>(p_a);
+ const GodotCylinderShape3D *cylinder_B = static_cast<const GodotCylinderShape3D *>(p_b);
- SeparatorAxisTest<CapsuleShape3DSW, CylinderShape3DSW, withMargin> separator(capsule_A, p_transform_a, cylinder_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
+ SeparatorAxisTest<GodotCapsuleShape3D, GodotCylinderShape3D, withMargin> separator(capsule_A, p_transform_a, cylinder_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
if (!separator.test_previous_axis()) {
return;
@@ -1709,7 +1730,7 @@ static void _collision_capsule_cylinder(const Shape3DSW *p_a, const Transform3D
return;
}
- CollisionSolver3DSW::CallbackResult callback = SeparatorAxisTest<CapsuleShape3DSW, CylinderShape3DSW, withMargin>::test_contact_points;
+ GodotCollisionSolver3D::CallbackResult callback = SeparatorAxisTest<GodotCapsuleShape3D, GodotCylinderShape3D, withMargin>::test_contact_points;
// Fallback to generic algorithm to find the best separating axis.
if (!fallback_collision_solver(p_a, p_transform_a, p_b, p_transform_b, callback, &separator, false, p_margin_a, p_margin_b)) {
@@ -1720,11 +1741,11 @@ static void _collision_capsule_cylinder(const Shape3DSW *p_a, const Transform3D
}
template <bool withMargin>
-static void _collision_capsule_convex_polygon(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
- const CapsuleShape3DSW *capsule_A = static_cast<const CapsuleShape3DSW *>(p_a);
- const ConvexPolygonShape3DSW *convex_polygon_B = static_cast<const ConvexPolygonShape3DSW *>(p_b);
+static void _collision_capsule_convex_polygon(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+ const GodotCapsuleShape3D *capsule_A = static_cast<const GodotCapsuleShape3D *>(p_a);
+ const GodotConvexPolygonShape3D *convex_polygon_B = static_cast<const GodotConvexPolygonShape3D *>(p_b);
- SeparatorAxisTest<CapsuleShape3DSW, ConvexPolygonShape3DSW, withMargin> separator(capsule_A, p_transform_a, convex_polygon_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
+ SeparatorAxisTest<GodotCapsuleShape3D, GodotConvexPolygonShape3D, withMargin> separator(capsule_A, p_transform_a, convex_polygon_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
if (!separator.test_previous_axis()) {
return;
@@ -1787,11 +1808,11 @@ static void _collision_capsule_convex_polygon(const Shape3DSW *p_a, const Transf
}
template <bool withMargin>
-static void _collision_capsule_face(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
- const CapsuleShape3DSW *capsule_A = static_cast<const CapsuleShape3DSW *>(p_a);
- const FaceShape3DSW *face_B = static_cast<const FaceShape3DSW *>(p_b);
+static void _collision_capsule_face(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+ const GodotCapsuleShape3D *capsule_A = static_cast<const GodotCapsuleShape3D *>(p_a);
+ const GodotFaceShape3D *face_B = static_cast<const GodotFaceShape3D *>(p_b);
- SeparatorAxisTest<CapsuleShape3DSW, FaceShape3DSW, withMargin> separator(capsule_A, p_transform_a, face_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
+ SeparatorAxisTest<GodotCapsuleShape3D, GodotFaceShape3D, withMargin> separator(capsule_A, p_transform_a, face_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
Vector3 vertex[3] = {
p_transform_b.xform(face_B->vertex[0]),
@@ -1801,7 +1822,7 @@ static void _collision_capsule_face(const Shape3DSW *p_a, const Transform3D &p_t
Vector3 normal = (vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized();
- if (!separator.test_axis(normal, !face_B->backface_collision)) {
+ if (!separator.test_axis(normal)) {
return;
}
@@ -1857,15 +1878,26 @@ static void _collision_capsule_face(const Shape3DSW *p_a, const Transform3D &p_t
}
}
+ if (!face_B->backface_collision) {
+ if (separator.best_axis.dot(normal) < _BACKFACE_NORMAL_THRESHOLD) {
+ if (face_B->invert_backface_collision) {
+ separator.best_axis = separator.best_axis.bounce(normal);
+ } else {
+ // Just ignore backface collision.
+ return;
+ }
+ }
+ }
+
separator.generate_contacts();
}
template <bool withMargin>
-static void _collision_cylinder_cylinder(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
- const CylinderShape3DSW *cylinder_A = static_cast<const CylinderShape3DSW *>(p_a);
- const CylinderShape3DSW *cylinder_B = static_cast<const CylinderShape3DSW *>(p_b);
+static void _collision_cylinder_cylinder(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+ const GodotCylinderShape3D *cylinder_A = static_cast<const GodotCylinderShape3D *>(p_a);
+ const GodotCylinderShape3D *cylinder_B = static_cast<const GodotCylinderShape3D *>(p_b);
- SeparatorAxisTest<CylinderShape3DSW, CylinderShape3DSW, withMargin> separator(cylinder_A, p_transform_a, cylinder_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
+ SeparatorAxisTest<GodotCylinderShape3D, GodotCylinderShape3D, withMargin> separator(cylinder_A, p_transform_a, cylinder_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
Vector3 cylinder_A_axis = p_transform_a.basis.get_axis(1);
Vector3 cylinder_B_axis = p_transform_b.basis.get_axis(1);
@@ -1904,7 +1936,7 @@ static void _collision_cylinder_cylinder(const Shape3DSW *p_a, const Transform3D
return;
}
- CollisionSolver3DSW::CallbackResult callback = SeparatorAxisTest<CylinderShape3DSW, CylinderShape3DSW, withMargin>::test_contact_points;
+ GodotCollisionSolver3D::CallbackResult callback = SeparatorAxisTest<GodotCylinderShape3D, GodotCylinderShape3D, withMargin>::test_contact_points;
// Fallback to generic algorithm to find the best separating axis.
if (!fallback_collision_solver(p_a, p_transform_a, p_b, p_transform_b, callback, &separator, false, p_margin_a, p_margin_b)) {
@@ -1915,13 +1947,13 @@ static void _collision_cylinder_cylinder(const Shape3DSW *p_a, const Transform3D
}
template <bool withMargin>
-static void _collision_cylinder_convex_polygon(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
- const CylinderShape3DSW *cylinder_A = static_cast<const CylinderShape3DSW *>(p_a);
- const ConvexPolygonShape3DSW *convex_polygon_B = static_cast<const ConvexPolygonShape3DSW *>(p_b);
+static void _collision_cylinder_convex_polygon(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+ const GodotCylinderShape3D *cylinder_A = static_cast<const GodotCylinderShape3D *>(p_a);
+ const GodotConvexPolygonShape3D *convex_polygon_B = static_cast<const GodotConvexPolygonShape3D *>(p_b);
- SeparatorAxisTest<CylinderShape3DSW, ConvexPolygonShape3DSW, withMargin> separator(cylinder_A, p_transform_a, convex_polygon_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
+ SeparatorAxisTest<GodotCylinderShape3D, GodotConvexPolygonShape3D, withMargin> separator(cylinder_A, p_transform_a, convex_polygon_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
- CollisionSolver3DSW::CallbackResult callback = SeparatorAxisTest<CylinderShape3DSW, ConvexPolygonShape3DSW, withMargin>::test_contact_points;
+ GodotCollisionSolver3D::CallbackResult callback = SeparatorAxisTest<GodotCylinderShape3D, GodotConvexPolygonShape3D, withMargin>::test_contact_points;
// Fallback to generic algorithm to find the best separating axis.
if (!fallback_collision_solver(p_a, p_transform_a, p_b, p_transform_b, callback, &separator, false, p_margin_a, p_margin_b)) {
@@ -1932,11 +1964,11 @@ static void _collision_cylinder_convex_polygon(const Shape3DSW *p_a, const Trans
}
template <bool withMargin>
-static void _collision_cylinder_face(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
- const CylinderShape3DSW *cylinder_A = static_cast<const CylinderShape3DSW *>(p_a);
- const FaceShape3DSW *face_B = static_cast<const FaceShape3DSW *>(p_b);
+static void _collision_cylinder_face(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+ const GodotCylinderShape3D *cylinder_A = static_cast<const GodotCylinderShape3D *>(p_a);
+ const GodotFaceShape3D *face_B = static_cast<const GodotFaceShape3D *>(p_b);
- SeparatorAxisTest<CylinderShape3DSW, FaceShape3DSW, withMargin> separator(cylinder_A, p_transform_a, face_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
+ SeparatorAxisTest<GodotCylinderShape3D, GodotFaceShape3D, withMargin> separator(cylinder_A, p_transform_a, face_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
if (!separator.test_previous_axis()) {
return;
@@ -1951,7 +1983,7 @@ static void _collision_cylinder_face(const Shape3DSW *p_a, const Transform3D &p_
Vector3 normal = (vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized();
// Face B normal.
- if (!separator.test_axis(normal, !face_B->backface_collision)) {
+ if (!separator.test_axis(normal)) {
return;
}
@@ -1985,7 +2017,7 @@ static void _collision_cylinder_face(const Shape3DSW *p_a, const Transform3D &p_
// Points of B, cylinder lateral surface.
for (int i = 0; i < 3; i++) {
const Vector3 &point = vertex[i];
- Vector3 axis = Plane(cyl_axis, 0).project(point).normalized();
+ Vector3 axis = Plane(cyl_axis).project(point).normalized();
if (axis.dot(normal) < 0.0) {
axis *= -1.0;
}
@@ -2033,15 +2065,26 @@ static void _collision_cylinder_face(const Shape3DSW *p_a, const Transform3D &p_
}
}
+ if (!face_B->backface_collision) {
+ if (separator.best_axis.dot(normal) < _BACKFACE_NORMAL_THRESHOLD) {
+ if (face_B->invert_backface_collision) {
+ separator.best_axis = separator.best_axis.bounce(normal);
+ } else {
+ // Just ignore backface collision.
+ return;
+ }
+ }
+ }
+
separator.generate_contacts();
}
template <bool withMargin>
-static void _collision_convex_polygon_convex_polygon(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
- const ConvexPolygonShape3DSW *convex_polygon_A = static_cast<const ConvexPolygonShape3DSW *>(p_a);
- const ConvexPolygonShape3DSW *convex_polygon_B = static_cast<const ConvexPolygonShape3DSW *>(p_b);
+static void _collision_convex_polygon_convex_polygon(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+ const GodotConvexPolygonShape3D *convex_polygon_A = static_cast<const GodotConvexPolygonShape3D *>(p_a);
+ const GodotConvexPolygonShape3D *convex_polygon_B = static_cast<const GodotConvexPolygonShape3D *>(p_b);
- SeparatorAxisTest<ConvexPolygonShape3DSW, ConvexPolygonShape3DSW, withMargin> separator(convex_polygon_A, p_transform_a, convex_polygon_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
+ SeparatorAxisTest<GodotConvexPolygonShape3D, GodotConvexPolygonShape3D, withMargin> separator(convex_polygon_A, p_transform_a, convex_polygon_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
if (!separator.test_previous_axis()) {
return;
@@ -2150,11 +2193,11 @@ static void _collision_convex_polygon_convex_polygon(const Shape3DSW *p_a, const
}
template <bool withMargin>
-static void _collision_convex_polygon_face(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
- const ConvexPolygonShape3DSW *convex_polygon_A = static_cast<const ConvexPolygonShape3DSW *>(p_a);
- const FaceShape3DSW *face_B = static_cast<const FaceShape3DSW *>(p_b);
+static void _collision_convex_polygon_face(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
+ const GodotConvexPolygonShape3D *convex_polygon_A = static_cast<const GodotConvexPolygonShape3D *>(p_a);
+ const GodotFaceShape3D *face_B = static_cast<const GodotFaceShape3D *>(p_b);
- SeparatorAxisTest<ConvexPolygonShape3DSW, FaceShape3DSW, withMargin> separator(convex_polygon_A, p_transform_a, face_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
+ SeparatorAxisTest<GodotConvexPolygonShape3D, GodotFaceShape3D, withMargin> separator(convex_polygon_A, p_transform_a, face_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
const Geometry3D::MeshData &mesh = convex_polygon_A->get_mesh();
@@ -2173,7 +2216,7 @@ static void _collision_convex_polygon_face(const Shape3DSW *p_a, const Transform
Vector3 normal = (vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized();
- if (!separator.test_axis(normal, !face_B->backface_collision)) {
+ if (!separator.test_axis(normal)) {
return;
}
@@ -2265,10 +2308,21 @@ static void _collision_convex_polygon_face(const Shape3DSW *p_a, const Transform
}
}
+ if (!face_B->backface_collision) {
+ if (separator.best_axis.dot(normal) < _BACKFACE_NORMAL_THRESHOLD) {
+ if (face_B->invert_backface_collision) {
+ separator.best_axis = separator.best_axis.bounce(normal);
+ } else {
+ // Just ignore backface collision.
+ return;
+ }
+ }
+ }
+
separator.generate_contacts();
}
-bool sat_calculate_penetration(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CollisionSolver3DSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap, Vector3 *r_prev_axis, real_t p_margin_a, real_t p_margin_b) {
+bool sat_calculate_penetration(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, GodotCollisionSolver3D::CallbackResult p_result_callback, void *p_userdata, bool p_swap, Vector3 *r_prev_axis, real_t p_margin_a, real_t p_margin_b) {
PhysicsServer3D::ShapeType type_A = p_shape_A->get_type();
ERR_FAIL_COND_V(type_A == PhysicsServer3D::SHAPE_WORLD_BOUNDARY, false);
@@ -2366,8 +2420,8 @@ bool sat_calculate_penetration(const Shape3DSW *p_shape_A, const Transform3D &p_
callback.collided = false;
callback.prev_axis = r_prev_axis;
- const Shape3DSW *A = p_shape_A;
- const Shape3DSW *B = p_shape_B;
+ const GodotShape3D *A = p_shape_A;
+ const GodotShape3D *B = p_shape_B;
const Transform3D *transform_A = &p_transform_A;
const Transform3D *transform_B = &p_transform_B;
real_t margin_A = p_margin_a;
diff --git a/servers/physics_3d/collision_solver_3d_sat.h b/servers/physics_3d/godot_collision_solver_3d_sat.h
index e50da7b101..3eb7aa4c9e 100644
--- a/servers/physics_3d/collision_solver_3d_sat.h
+++ b/servers/physics_3d/godot_collision_solver_3d_sat.h
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* collision_solver_3d_sat.h */
+/* godot_collision_solver_3d_sat.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,11 +28,11 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef COLLISION_SOLVER_SAT_H
-#define COLLISION_SOLVER_SAT_H
+#ifndef GODOT_COLLISION_SOLVER_SAT_H
+#define GODOT_COLLISION_SOLVER_SAT_H
-#include "collision_solver_3d_sw.h"
+#include "godot_collision_solver_3d.h"
-bool sat_calculate_penetration(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CollisionSolver3DSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap = false, Vector3 *r_prev_axis = nullptr, real_t p_margin_a = 0, real_t p_margin_b = 0);
+bool sat_calculate_penetration(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, GodotCollisionSolver3D::CallbackResult p_result_callback, void *p_userdata, bool p_swap = false, Vector3 *r_prev_axis = nullptr, real_t p_margin_a = 0, real_t p_margin_b = 0);
-#endif // COLLISION_SOLVER_SAT_H
+#endif // GODOT_COLLISION_SOLVER_SAT_H
diff --git a/servers/physics_3d/constraint_3d_sw.h b/servers/physics_3d/godot_constraint_3d.h
index 7b44726ef5..217955047f 100644
--- a/servers/physics_3d/constraint_3d_sw.h
+++ b/servers/physics_3d/godot_constraint_3d.h
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* constraint_3d_sw.h */
+/* godot_constraint_3d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,14 +28,14 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef CONSTRAINT_SW_H
-#define CONSTRAINT_SW_H
+#ifndef GODOT_CONSTRAINT_3D_H
+#define GODOT_CONSTRAINT_3D_H
-class Body3DSW;
-class SoftBody3DSW;
+class GodotBody3D;
+class GodotSoftBody3D;
-class Constraint3DSW {
- Body3DSW **_body_ptr;
+class GodotConstraint3D {
+ GodotBody3D **_body_ptr;
int _body_count;
uint64_t island_step;
int priority;
@@ -44,7 +44,7 @@ class Constraint3DSW {
RID self;
protected:
- Constraint3DSW(Body3DSW **p_body_ptr = nullptr, int p_body_count = 0) {
+ GodotConstraint3D(GodotBody3D **p_body_ptr = nullptr, int p_body_count = 0) {
_body_ptr = p_body_ptr;
_body_count = p_body_count;
island_step = 0;
@@ -59,10 +59,10 @@ public:
_FORCE_INLINE_ uint64_t get_island_step() const { return island_step; }
_FORCE_INLINE_ void set_island_step(uint64_t p_step) { island_step = p_step; }
- _FORCE_INLINE_ Body3DSW **get_body_ptr() const { return _body_ptr; }
+ _FORCE_INLINE_ GodotBody3D **get_body_ptr() const { return _body_ptr; }
_FORCE_INLINE_ int get_body_count() const { return _body_count; }
- virtual SoftBody3DSW *get_soft_body_ptr(int p_index) const { return nullptr; }
+ virtual GodotSoftBody3D *get_soft_body_ptr(int p_index) const { return nullptr; }
virtual int get_soft_body_count() const { return 0; }
_FORCE_INLINE_ void set_priority(int p_priority) { priority = p_priority; }
@@ -75,7 +75,7 @@ public:
virtual bool pre_solve(real_t p_step) = 0;
virtual void solve(real_t p_step) = 0;
- virtual ~Constraint3DSW() {}
+ virtual ~GodotConstraint3D() {}
};
-#endif // CONSTRAINT__SW_H
+#endif // GODOT_CONSTRAINT_3D_H
diff --git a/servers/physics_3d/joints_3d_sw.h b/servers/physics_3d/godot_joint_3d.h
index e2514674ea..d4b719fc5e 100644
--- a/servers/physics_3d/joints_3d_sw.h
+++ b/servers/physics_3d/godot_joint_3d.h
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* joints_3d_sw.h */
+/* godot_joint_3d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,13 +28,13 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef JOINTS_SW_H
-#define JOINTS_SW_H
+#ifndef GODOT_JOINT_3D_H
+#define GODOT_JOINT_3D_H
-#include "body_3d_sw.h"
-#include "constraint_3d_sw.h"
+#include "godot_body_3d.h"
+#include "godot_constraint_3d.h"
-class Joint3DSW : public Constraint3DSW {
+class GodotJoint3D : public GodotConstraint3D {
protected:
bool dynamic_A = false;
bool dynamic_B = false;
@@ -44,20 +44,20 @@ public:
virtual bool pre_solve(real_t p_step) override { return true; }
virtual void solve(real_t p_step) override {}
- void copy_settings_from(Joint3DSW *p_joint) {
+ void copy_settings_from(GodotJoint3D *p_joint) {
set_self(p_joint->get_self());
set_priority(p_joint->get_priority());
disable_collisions_between_bodies(p_joint->is_disabled_collisions_between_bodies());
}
virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_TYPE_MAX; }
- _FORCE_INLINE_ Joint3DSW(Body3DSW **p_body_ptr = nullptr, int p_body_count = 0) :
- Constraint3DSW(p_body_ptr, p_body_count) {
+ _FORCE_INLINE_ GodotJoint3D(GodotBody3D **p_body_ptr = nullptr, int p_body_count = 0) :
+ GodotConstraint3D(p_body_ptr, p_body_count) {
}
- virtual ~Joint3DSW() {
+ virtual ~GodotJoint3D() {
for (int i = 0; i < get_body_count(); i++) {
- Body3DSW *body = get_body_ptr()[i];
+ GodotBody3D *body = get_body_ptr()[i];
if (body) {
body->remove_constraint(this);
}
@@ -65,4 +65,4 @@ public:
}
};
-#endif // JOINTS_SW_H
+#endif // GODOT_JOINT_3D_H
diff --git a/servers/physics_3d/godot_physics_server_3d.cpp b/servers/physics_3d/godot_physics_server_3d.cpp
new file mode 100644
index 0000000000..4e1680e6ac
--- /dev/null
+++ b/servers/physics_3d/godot_physics_server_3d.cpp
@@ -0,0 +1,1763 @@
+/*************************************************************************/
+/* godot_physics_server_3d.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 "godot_physics_server_3d.h"
+
+#include "godot_body_direct_state_3d.h"
+#include "godot_broad_phase_3d_bvh.h"
+#include "joints/godot_cone_twist_joint_3d.h"
+#include "joints/godot_generic_6dof_joint_3d.h"
+#include "joints/godot_hinge_joint_3d.h"
+#include "joints/godot_pin_joint_3d.h"
+#include "joints/godot_slider_joint_3d.h"
+
+#include "core/debugger/engine_debugger.h"
+#include "core/os/os.h"
+
+#define FLUSH_QUERY_CHECK(m_object) \
+ ERR_FAIL_COND_MSG(m_object->get_space() && flushing_queries, "Can't change this state while flushing queries. Use call_deferred() or set_deferred() to change monitoring state instead.");
+
+RID GodotPhysicsServer3D::world_boundary_shape_create() {
+ GodotShape3D *shape = memnew(GodotWorldBoundaryShape3D);
+ RID rid = shape_owner.make_rid(shape);
+ shape->set_self(rid);
+ return rid;
+}
+RID GodotPhysicsServer3D::separation_ray_shape_create() {
+ GodotShape3D *shape = memnew(GodotSeparationRayShape3D);
+ RID rid = shape_owner.make_rid(shape);
+ shape->set_self(rid);
+ return rid;
+}
+RID GodotPhysicsServer3D::sphere_shape_create() {
+ GodotShape3D *shape = memnew(GodotSphereShape3D);
+ RID rid = shape_owner.make_rid(shape);
+ shape->set_self(rid);
+ return rid;
+}
+RID GodotPhysicsServer3D::box_shape_create() {
+ GodotShape3D *shape = memnew(GodotBoxShape3D);
+ RID rid = shape_owner.make_rid(shape);
+ shape->set_self(rid);
+ return rid;
+}
+RID GodotPhysicsServer3D::capsule_shape_create() {
+ GodotShape3D *shape = memnew(GodotCapsuleShape3D);
+ RID rid = shape_owner.make_rid(shape);
+ shape->set_self(rid);
+ return rid;
+}
+RID GodotPhysicsServer3D::cylinder_shape_create() {
+ GodotShape3D *shape = memnew(GodotCylinderShape3D);
+ RID rid = shape_owner.make_rid(shape);
+ shape->set_self(rid);
+ return rid;
+}
+RID GodotPhysicsServer3D::convex_polygon_shape_create() {
+ GodotShape3D *shape = memnew(GodotConvexPolygonShape3D);
+ RID rid = shape_owner.make_rid(shape);
+ shape->set_self(rid);
+ return rid;
+}
+RID GodotPhysicsServer3D::concave_polygon_shape_create() {
+ GodotShape3D *shape = memnew(GodotConcavePolygonShape3D);
+ RID rid = shape_owner.make_rid(shape);
+ shape->set_self(rid);
+ return rid;
+}
+RID GodotPhysicsServer3D::heightmap_shape_create() {
+ GodotShape3D *shape = memnew(GodotHeightMapShape3D);
+ RID rid = shape_owner.make_rid(shape);
+ shape->set_self(rid);
+ return rid;
+}
+RID GodotPhysicsServer3D::custom_shape_create() {
+ ERR_FAIL_V(RID());
+}
+
+void GodotPhysicsServer3D::shape_set_data(RID p_shape, const Variant &p_data) {
+ GodotShape3D *shape = shape_owner.get_or_null(p_shape);
+ ERR_FAIL_COND(!shape);
+ shape->set_data(p_data);
+};
+
+void GodotPhysicsServer3D::shape_set_custom_solver_bias(RID p_shape, real_t p_bias) {
+ GodotShape3D *shape = shape_owner.get_or_null(p_shape);
+ ERR_FAIL_COND(!shape);
+ shape->set_custom_bias(p_bias);
+}
+
+PhysicsServer3D::ShapeType GodotPhysicsServer3D::shape_get_type(RID p_shape) const {
+ const GodotShape3D *shape = shape_owner.get_or_null(p_shape);
+ ERR_FAIL_COND_V(!shape, SHAPE_CUSTOM);
+ return shape->get_type();
+};
+
+Variant GodotPhysicsServer3D::shape_get_data(RID p_shape) const {
+ const GodotShape3D *shape = shape_owner.get_or_null(p_shape);
+ ERR_FAIL_COND_V(!shape, Variant());
+ ERR_FAIL_COND_V(!shape->is_configured(), Variant());
+ return shape->get_data();
+};
+
+void GodotPhysicsServer3D::shape_set_margin(RID p_shape, real_t p_margin) {
+}
+
+real_t GodotPhysicsServer3D::shape_get_margin(RID p_shape) const {
+ return 0.0;
+}
+
+real_t GodotPhysicsServer3D::shape_get_custom_solver_bias(RID p_shape) const {
+ const GodotShape3D *shape = shape_owner.get_or_null(p_shape);
+ ERR_FAIL_COND_V(!shape, 0);
+ return shape->get_custom_bias();
+}
+
+RID GodotPhysicsServer3D::space_create() {
+ GodotSpace3D *space = memnew(GodotSpace3D);
+ RID id = space_owner.make_rid(space);
+ space->set_self(id);
+ RID area_id = area_create();
+ GodotArea3D *area = area_owner.get_or_null(area_id);
+ ERR_FAIL_COND_V(!area, RID());
+ space->set_default_area(area);
+ area->set_space(space);
+ area->set_priority(-1);
+ RID sgb = body_create();
+ body_set_space(sgb, id);
+ body_set_mode(sgb, BODY_MODE_STATIC);
+ space->set_static_global_body(sgb);
+
+ return id;
+};
+
+void GodotPhysicsServer3D::space_set_active(RID p_space, bool p_active) {
+ GodotSpace3D *space = space_owner.get_or_null(p_space);
+ ERR_FAIL_COND(!space);
+ if (p_active) {
+ active_spaces.insert(space);
+ } else {
+ active_spaces.erase(space);
+ }
+}
+
+bool GodotPhysicsServer3D::space_is_active(RID p_space) const {
+ const GodotSpace3D *space = space_owner.get_or_null(p_space);
+ ERR_FAIL_COND_V(!space, false);
+
+ return active_spaces.has(space);
+}
+
+void GodotPhysicsServer3D::space_set_param(RID p_space, SpaceParameter p_param, real_t p_value) {
+ GodotSpace3D *space = space_owner.get_or_null(p_space);
+ ERR_FAIL_COND(!space);
+
+ space->set_param(p_param, p_value);
+}
+
+real_t GodotPhysicsServer3D::space_get_param(RID p_space, SpaceParameter p_param) const {
+ const GodotSpace3D *space = space_owner.get_or_null(p_space);
+ ERR_FAIL_COND_V(!space, 0);
+ return space->get_param(p_param);
+}
+
+PhysicsDirectSpaceState3D *GodotPhysicsServer3D::space_get_direct_state(RID p_space) {
+ GodotSpace3D *space = space_owner.get_or_null(p_space);
+ ERR_FAIL_COND_V(!space, nullptr);
+ ERR_FAIL_COND_V_MSG((using_threads && !doing_sync) || space->is_locked(), nullptr, "Space state is inaccessible right now, wait for iteration or physics process notification.");
+
+ return space->get_direct_state();
+}
+
+void GodotPhysicsServer3D::space_set_debug_contacts(RID p_space, int p_max_contacts) {
+ GodotSpace3D *space = space_owner.get_or_null(p_space);
+ ERR_FAIL_COND(!space);
+ space->set_debug_contacts(p_max_contacts);
+}
+
+Vector<Vector3> GodotPhysicsServer3D::space_get_contacts(RID p_space) const {
+ GodotSpace3D *space = space_owner.get_or_null(p_space);
+ ERR_FAIL_COND_V(!space, Vector<Vector3>());
+ return space->get_debug_contacts();
+}
+
+int GodotPhysicsServer3D::space_get_contact_count(RID p_space) const {
+ GodotSpace3D *space = space_owner.get_or_null(p_space);
+ ERR_FAIL_COND_V(!space, 0);
+ return space->get_debug_contact_count();
+}
+
+RID GodotPhysicsServer3D::area_create() {
+ GodotArea3D *area = memnew(GodotArea3D);
+ RID rid = area_owner.make_rid(area);
+ area->set_self(rid);
+ return rid;
+}
+
+void GodotPhysicsServer3D::area_set_space(RID p_area, RID p_space) {
+ GodotArea3D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND(!area);
+
+ GodotSpace3D *space = nullptr;
+ if (p_space.is_valid()) {
+ space = space_owner.get_or_null(p_space);
+ ERR_FAIL_COND(!space);
+ }
+
+ if (area->get_space() == space) {
+ return; //pointless
+ }
+
+ area->clear_constraints();
+ area->set_space(space);
+}
+
+RID GodotPhysicsServer3D::area_get_space(RID p_area) const {
+ GodotArea3D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND_V(!area, RID());
+
+ GodotSpace3D *space = area->get_space();
+ if (!space) {
+ return RID();
+ }
+ return space->get_self();
+}
+
+void GodotPhysicsServer3D::area_add_shape(RID p_area, RID p_shape, const Transform3D &p_transform, bool p_disabled) {
+ GodotArea3D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND(!area);
+
+ GodotShape3D *shape = shape_owner.get_or_null(p_shape);
+ ERR_FAIL_COND(!shape);
+
+ area->add_shape(shape, p_transform, p_disabled);
+}
+
+void GodotPhysicsServer3D::area_set_shape(RID p_area, int p_shape_idx, RID p_shape) {
+ GodotArea3D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND(!area);
+
+ GodotShape3D *shape = shape_owner.get_or_null(p_shape);
+ ERR_FAIL_COND(!shape);
+ ERR_FAIL_COND(!shape->is_configured());
+
+ area->set_shape(p_shape_idx, shape);
+}
+
+void GodotPhysicsServer3D::area_set_shape_transform(RID p_area, int p_shape_idx, const Transform3D &p_transform) {
+ GodotArea3D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND(!area);
+
+ area->set_shape_transform(p_shape_idx, p_transform);
+}
+
+int GodotPhysicsServer3D::area_get_shape_count(RID p_area) const {
+ GodotArea3D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND_V(!area, -1);
+
+ return area->get_shape_count();
+}
+
+RID GodotPhysicsServer3D::area_get_shape(RID p_area, int p_shape_idx) const {
+ GodotArea3D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND_V(!area, RID());
+
+ GodotShape3D *shape = area->get_shape(p_shape_idx);
+ ERR_FAIL_COND_V(!shape, RID());
+
+ return shape->get_self();
+}
+
+Transform3D GodotPhysicsServer3D::area_get_shape_transform(RID p_area, int p_shape_idx) const {
+ GodotArea3D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND_V(!area, Transform3D());
+
+ return area->get_shape_transform(p_shape_idx);
+}
+
+void GodotPhysicsServer3D::area_remove_shape(RID p_area, int p_shape_idx) {
+ GodotArea3D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND(!area);
+
+ area->remove_shape(p_shape_idx);
+}
+
+void GodotPhysicsServer3D::area_clear_shapes(RID p_area) {
+ GodotArea3D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND(!area);
+
+ while (area->get_shape_count()) {
+ area->remove_shape(0);
+ }
+}
+
+void GodotPhysicsServer3D::area_set_shape_disabled(RID p_area, int p_shape_idx, bool p_disabled) {
+ GodotArea3D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND(!area);
+ ERR_FAIL_INDEX(p_shape_idx, area->get_shape_count());
+ FLUSH_QUERY_CHECK(area);
+ area->set_shape_disabled(p_shape_idx, p_disabled);
+}
+
+void GodotPhysicsServer3D::area_attach_object_instance_id(RID p_area, ObjectID p_id) {
+ if (space_owner.owns(p_area)) {
+ GodotSpace3D *space = space_owner.get_or_null(p_area);
+ p_area = space->get_default_area()->get_self();
+ }
+ GodotArea3D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND(!area);
+ area->set_instance_id(p_id);
+}
+
+ObjectID GodotPhysicsServer3D::area_get_object_instance_id(RID p_area) const {
+ if (space_owner.owns(p_area)) {
+ GodotSpace3D *space = space_owner.get_or_null(p_area);
+ p_area = space->get_default_area()->get_self();
+ }
+ GodotArea3D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND_V(!area, ObjectID());
+ return area->get_instance_id();
+}
+
+void GodotPhysicsServer3D::area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value) {
+ if (space_owner.owns(p_area)) {
+ GodotSpace3D *space = space_owner.get_or_null(p_area);
+ p_area = space->get_default_area()->get_self();
+ }
+ GodotArea3D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND(!area);
+ area->set_param(p_param, p_value);
+};
+
+void GodotPhysicsServer3D::area_set_transform(RID p_area, const Transform3D &p_transform) {
+ GodotArea3D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND(!area);
+ area->set_transform(p_transform);
+};
+
+Variant GodotPhysicsServer3D::area_get_param(RID p_area, AreaParameter p_param) const {
+ if (space_owner.owns(p_area)) {
+ GodotSpace3D *space = space_owner.get_or_null(p_area);
+ p_area = space->get_default_area()->get_self();
+ }
+ GodotArea3D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND_V(!area, Variant());
+
+ return area->get_param(p_param);
+};
+
+Transform3D GodotPhysicsServer3D::area_get_transform(RID p_area) const {
+ GodotArea3D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND_V(!area, Transform3D());
+
+ return area->get_transform();
+};
+
+void GodotPhysicsServer3D::area_set_collision_layer(RID p_area, uint32_t p_layer) {
+ GodotArea3D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND(!area);
+
+ area->set_collision_layer(p_layer);
+}
+
+void GodotPhysicsServer3D::area_set_collision_mask(RID p_area, uint32_t p_mask) {
+ GodotArea3D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND(!area);
+
+ area->set_collision_mask(p_mask);
+}
+
+void GodotPhysicsServer3D::area_set_monitorable(RID p_area, bool p_monitorable) {
+ GodotArea3D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND(!area);
+ FLUSH_QUERY_CHECK(area);
+
+ area->set_monitorable(p_monitorable);
+}
+
+void GodotPhysicsServer3D::area_set_monitor_callback(RID p_area, const Callable &p_callback) {
+ GodotArea3D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND(!area);
+
+ area->set_monitor_callback(p_callback.is_valid() ? p_callback : Callable());
+}
+
+void GodotPhysicsServer3D::area_set_ray_pickable(RID p_area, bool p_enable) {
+ GodotArea3D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND(!area);
+
+ area->set_ray_pickable(p_enable);
+}
+
+void GodotPhysicsServer3D::area_set_area_monitor_callback(RID p_area, const Callable &p_callback) {
+ GodotArea3D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND(!area);
+
+ area->set_area_monitor_callback(p_callback.is_valid() ? p_callback : Callable());
+}
+
+/* BODY API */
+
+RID GodotPhysicsServer3D::body_create() {
+ GodotBody3D *body = memnew(GodotBody3D);
+ RID rid = body_owner.make_rid(body);
+ body->set_self(rid);
+ return rid;
+};
+
+void GodotPhysicsServer3D::body_set_space(RID p_body, RID p_space) {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ GodotSpace3D *space = nullptr;
+ if (p_space.is_valid()) {
+ space = space_owner.get_or_null(p_space);
+ ERR_FAIL_COND(!space);
+ }
+
+ if (body->get_space() == space) {
+ return; //pointless
+ }
+
+ body->clear_constraint_map();
+ body->set_space(space);
+};
+
+RID GodotPhysicsServer3D::body_get_space(RID p_body) const {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, RID());
+
+ GodotSpace3D *space = body->get_space();
+ if (!space) {
+ return RID();
+ }
+ return space->get_self();
+};
+
+void GodotPhysicsServer3D::body_set_mode(RID p_body, BodyMode p_mode) {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->set_mode(p_mode);
+};
+
+PhysicsServer3D::BodyMode GodotPhysicsServer3D::body_get_mode(RID p_body) const {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, BODY_MODE_STATIC);
+
+ return body->get_mode();
+};
+
+void GodotPhysicsServer3D::body_add_shape(RID p_body, RID p_shape, const Transform3D &p_transform, bool p_disabled) {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ GodotShape3D *shape = shape_owner.get_or_null(p_shape);
+ ERR_FAIL_COND(!shape);
+
+ body->add_shape(shape, p_transform, p_disabled);
+}
+
+void GodotPhysicsServer3D::body_set_shape(RID p_body, int p_shape_idx, RID p_shape) {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ GodotShape3D *shape = shape_owner.get_or_null(p_shape);
+ ERR_FAIL_COND(!shape);
+ ERR_FAIL_COND(!shape->is_configured());
+
+ body->set_shape(p_shape_idx, shape);
+}
+void GodotPhysicsServer3D::body_set_shape_transform(RID p_body, int p_shape_idx, const Transform3D &p_transform) {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->set_shape_transform(p_shape_idx, p_transform);
+}
+
+int GodotPhysicsServer3D::body_get_shape_count(RID p_body) const {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, -1);
+
+ return body->get_shape_count();
+}
+
+RID GodotPhysicsServer3D::body_get_shape(RID p_body, int p_shape_idx) const {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, RID());
+
+ GodotShape3D *shape = body->get_shape(p_shape_idx);
+ ERR_FAIL_COND_V(!shape, RID());
+
+ return shape->get_self();
+}
+
+void GodotPhysicsServer3D::body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+ ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count());
+ FLUSH_QUERY_CHECK(body);
+
+ body->set_shape_disabled(p_shape_idx, p_disabled);
+}
+
+Transform3D GodotPhysicsServer3D::body_get_shape_transform(RID p_body, int p_shape_idx) const {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, Transform3D());
+
+ return body->get_shape_transform(p_shape_idx);
+}
+
+void GodotPhysicsServer3D::body_remove_shape(RID p_body, int p_shape_idx) {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->remove_shape(p_shape_idx);
+}
+
+void GodotPhysicsServer3D::body_clear_shapes(RID p_body) {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ while (body->get_shape_count()) {
+ body->remove_shape(0);
+ }
+}
+
+void GodotPhysicsServer3D::body_set_enable_continuous_collision_detection(RID p_body, bool p_enable) {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->set_continuous_collision_detection(p_enable);
+}
+
+bool GodotPhysicsServer3D::body_is_continuous_collision_detection_enabled(RID p_body) const {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, false);
+
+ return body->is_continuous_collision_detection_enabled();
+}
+
+void GodotPhysicsServer3D::body_set_collision_layer(RID p_body, uint32_t p_layer) {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->set_collision_layer(p_layer);
+}
+
+uint32_t GodotPhysicsServer3D::body_get_collision_layer(RID p_body) const {
+ const GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, 0);
+
+ return body->get_collision_layer();
+}
+
+void GodotPhysicsServer3D::body_set_collision_mask(RID p_body, uint32_t p_mask) {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->set_collision_mask(p_mask);
+}
+
+uint32_t GodotPhysicsServer3D::body_get_collision_mask(RID p_body) const {
+ const GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, 0);
+
+ return body->get_collision_mask();
+}
+
+void GodotPhysicsServer3D::body_attach_object_instance_id(RID p_body, ObjectID p_id) {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ if (body) {
+ body->set_instance_id(p_id);
+ return;
+ }
+
+ GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body);
+ if (soft_body) {
+ soft_body->set_instance_id(p_id);
+ return;
+ }
+
+ ERR_FAIL_MSG("Invalid ID.");
+}
+
+ObjectID GodotPhysicsServer3D::body_get_object_instance_id(RID p_body) const {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, ObjectID());
+
+ return body->get_instance_id();
+}
+
+void GodotPhysicsServer3D::body_set_user_flags(RID p_body, uint32_t p_flags) {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+}
+
+uint32_t GodotPhysicsServer3D::body_get_user_flags(RID p_body) const {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, 0);
+
+ return 0;
+}
+
+void GodotPhysicsServer3D::body_set_param(RID p_body, BodyParameter p_param, const Variant &p_value) {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->set_param(p_param, p_value);
+}
+
+Variant GodotPhysicsServer3D::body_get_param(RID p_body, BodyParameter p_param) const {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, 0);
+
+ return body->get_param(p_param);
+}
+
+void GodotPhysicsServer3D::body_reset_mass_properties(RID p_body) {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ return body->reset_mass_properties();
+}
+
+void GodotPhysicsServer3D::body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->set_state(p_state, p_variant);
+}
+
+Variant GodotPhysicsServer3D::body_get_state(RID p_body, BodyState p_state) const {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, Variant());
+
+ return body->get_state(p_state);
+}
+
+void GodotPhysicsServer3D::body_apply_central_impulse(RID p_body, const Vector3 &p_impulse) {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ _update_shapes();
+
+ body->apply_central_impulse(p_impulse);
+ body->wakeup();
+}
+
+void GodotPhysicsServer3D::body_apply_impulse(RID p_body, const Vector3 &p_impulse, const Vector3 &p_position) {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ _update_shapes();
+
+ body->apply_impulse(p_impulse, p_position);
+ body->wakeup();
+}
+
+void GodotPhysicsServer3D::body_apply_torque_impulse(RID p_body, const Vector3 &p_impulse) {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ _update_shapes();
+
+ body->apply_torque_impulse(p_impulse);
+ body->wakeup();
+}
+
+void GodotPhysicsServer3D::body_apply_central_force(RID p_body, const Vector3 &p_force) {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->apply_central_force(p_force);
+ body->wakeup();
+}
+
+void GodotPhysicsServer3D::body_apply_force(RID p_body, const Vector3 &p_force, const Vector3 &p_position) {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->apply_force(p_force, p_position);
+ body->wakeup();
+}
+
+void GodotPhysicsServer3D::body_apply_torque(RID p_body, const Vector3 &p_torque) {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->apply_torque(p_torque);
+ body->wakeup();
+}
+
+void GodotPhysicsServer3D::body_add_constant_central_force(RID p_body, const Vector3 &p_force) {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->add_constant_central_force(p_force);
+ body->wakeup();
+}
+
+void GodotPhysicsServer3D::body_add_constant_force(RID p_body, const Vector3 &p_force, const Vector3 &p_position) {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->add_constant_force(p_force, p_position);
+ body->wakeup();
+}
+
+void GodotPhysicsServer3D::body_add_constant_torque(RID p_body, const Vector3 &p_torque) {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->add_constant_torque(p_torque);
+ body->wakeup();
+}
+
+void GodotPhysicsServer3D::body_set_constant_force(RID p_body, const Vector3 &p_force) {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->set_constant_force(p_force);
+ if (!p_force.is_equal_approx(Vector3())) {
+ body->wakeup();
+ }
+}
+
+Vector3 GodotPhysicsServer3D::body_get_constant_force(RID p_body) const {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, Vector3());
+ return body->get_constant_force();
+}
+
+void GodotPhysicsServer3D::body_set_constant_torque(RID p_body, const Vector3 &p_torque) {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->set_constant_torque(p_torque);
+ if (!p_torque.is_equal_approx(Vector3())) {
+ body->wakeup();
+ }
+}
+
+Vector3 GodotPhysicsServer3D::body_get_constant_torque(RID p_body) const {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, Vector3());
+
+ return body->get_constant_torque();
+}
+
+void GodotPhysicsServer3D::body_set_axis_velocity(RID p_body, const Vector3 &p_axis_velocity) {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ _update_shapes();
+
+ Vector3 v = body->get_linear_velocity();
+ Vector3 axis = p_axis_velocity.normalized();
+ v -= axis * axis.dot(v);
+ v += p_axis_velocity;
+ body->set_linear_velocity(v);
+ body->wakeup();
+}
+
+void GodotPhysicsServer3D::body_set_axis_lock(RID p_body, BodyAxis p_axis, bool p_lock) {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->set_axis_lock(p_axis, p_lock);
+ body->wakeup();
+}
+
+bool GodotPhysicsServer3D::body_is_axis_locked(RID p_body, BodyAxis p_axis) const {
+ const GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, 0);
+ return body->is_axis_locked(p_axis);
+}
+
+void GodotPhysicsServer3D::body_add_collision_exception(RID p_body, RID p_body_b) {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->add_exception(p_body_b);
+ body->wakeup();
+};
+
+void GodotPhysicsServer3D::body_remove_collision_exception(RID p_body, RID p_body_b) {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->remove_exception(p_body_b);
+ body->wakeup();
+};
+
+void GodotPhysicsServer3D::body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions) {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ for (int i = 0; i < body->get_exceptions().size(); i++) {
+ p_exceptions->push_back(body->get_exceptions()[i]);
+ }
+};
+
+void GodotPhysicsServer3D::body_set_contacts_reported_depth_threshold(RID p_body, real_t p_threshold) {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+};
+
+real_t GodotPhysicsServer3D::body_get_contacts_reported_depth_threshold(RID p_body) const {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, 0);
+ return 0;
+};
+
+void GodotPhysicsServer3D::body_set_omit_force_integration(RID p_body, bool p_omit) {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->set_omit_force_integration(p_omit);
+};
+
+bool GodotPhysicsServer3D::body_is_omitting_force_integration(RID p_body) const {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, false);
+ return body->get_omit_force_integration();
+};
+
+void GodotPhysicsServer3D::body_set_max_contacts_reported(RID p_body, int p_contacts) {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+ body->set_max_contacts_reported(p_contacts);
+}
+
+int GodotPhysicsServer3D::body_get_max_contacts_reported(RID p_body) const {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, -1);
+ return body->get_max_contacts_reported();
+}
+
+void GodotPhysicsServer3D::body_set_state_sync_callback(RID p_body, void *p_instance, BodyStateCallback p_callback) {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+ body->set_state_sync_callback(p_instance, p_callback);
+}
+
+void GodotPhysicsServer3D::body_set_force_integration_callback(RID p_body, const Callable &p_callable, const Variant &p_udata) {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+ body->set_force_integration_callback(p_callable, p_udata);
+}
+
+void GodotPhysicsServer3D::body_set_ray_pickable(RID p_body, bool p_enable) {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+ body->set_ray_pickable(p_enable);
+}
+
+bool GodotPhysicsServer3D::body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result) {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, false);
+ ERR_FAIL_COND_V(!body->get_space(), false);
+ ERR_FAIL_COND_V(body->get_space()->is_locked(), false);
+
+ _update_shapes();
+
+ return body->get_space()->test_body_motion(body, p_parameters, r_result);
+}
+
+PhysicsDirectBodyState3D *GodotPhysicsServer3D::body_get_direct_state(RID p_body) {
+ ERR_FAIL_COND_V_MSG((using_threads && !doing_sync), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification.");
+
+ if (!body_owner.owns(p_body)) {
+ return nullptr;
+ }
+
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_NULL_V(body, nullptr);
+
+ if (!body->get_space()) {
+ return nullptr;
+ }
+
+ ERR_FAIL_COND_V_MSG(body->get_space()->is_locked(), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification.");
+
+ return body->get_direct_state();
+}
+
+/* SOFT BODY */
+
+RID GodotPhysicsServer3D::soft_body_create() {
+ GodotSoftBody3D *soft_body = memnew(GodotSoftBody3D);
+ RID rid = soft_body_owner.make_rid(soft_body);
+ soft_body->set_self(rid);
+ return rid;
+}
+
+void GodotPhysicsServer3D::soft_body_update_rendering_server(RID p_body, RenderingServerHandler *p_rendering_server_handler) {
+ GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!soft_body);
+
+ soft_body->update_rendering_server(p_rendering_server_handler);
+}
+
+void GodotPhysicsServer3D::soft_body_set_space(RID p_body, RID p_space) {
+ GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!soft_body);
+
+ GodotSpace3D *space = nullptr;
+ if (p_space.is_valid()) {
+ space = space_owner.get_or_null(p_space);
+ ERR_FAIL_COND(!space);
+ }
+
+ if (soft_body->get_space() == space) {
+ return;
+ }
+
+ soft_body->set_space(space);
+}
+
+RID GodotPhysicsServer3D::soft_body_get_space(RID p_body) const {
+ GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!soft_body, RID());
+
+ GodotSpace3D *space = soft_body->get_space();
+ if (!space) {
+ return RID();
+ }
+ return space->get_self();
+}
+
+void GodotPhysicsServer3D::soft_body_set_collision_layer(RID p_body, uint32_t p_layer) {
+ GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!soft_body);
+
+ soft_body->set_collision_layer(p_layer);
+}
+
+uint32_t GodotPhysicsServer3D::soft_body_get_collision_layer(RID p_body) const {
+ GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!soft_body, 0);
+
+ return soft_body->get_collision_layer();
+}
+
+void GodotPhysicsServer3D::soft_body_set_collision_mask(RID p_body, uint32_t p_mask) {
+ GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!soft_body);
+
+ soft_body->set_collision_mask(p_mask);
+}
+
+uint32_t GodotPhysicsServer3D::soft_body_get_collision_mask(RID p_body) const {
+ GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!soft_body, 0);
+
+ return soft_body->get_collision_mask();
+}
+
+void GodotPhysicsServer3D::soft_body_add_collision_exception(RID p_body, RID p_body_b) {
+ GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!soft_body);
+
+ soft_body->add_exception(p_body_b);
+}
+
+void GodotPhysicsServer3D::soft_body_remove_collision_exception(RID p_body, RID p_body_b) {
+ GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!soft_body);
+
+ soft_body->remove_exception(p_body_b);
+}
+
+void GodotPhysicsServer3D::soft_body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions) {
+ GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!soft_body);
+
+ for (int i = 0; i < soft_body->get_exceptions().size(); i++) {
+ p_exceptions->push_back(soft_body->get_exceptions()[i]);
+ }
+}
+
+void GodotPhysicsServer3D::soft_body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) {
+ GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!soft_body);
+
+ soft_body->set_state(p_state, p_variant);
+}
+
+Variant GodotPhysicsServer3D::soft_body_get_state(RID p_body, BodyState p_state) const {
+ GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!soft_body, Variant());
+
+ return soft_body->get_state(p_state);
+}
+
+void GodotPhysicsServer3D::soft_body_set_transform(RID p_body, const Transform3D &p_transform) {
+ GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!soft_body);
+
+ soft_body->set_state(BODY_STATE_TRANSFORM, p_transform);
+}
+
+void GodotPhysicsServer3D::soft_body_set_ray_pickable(RID p_body, bool p_enable) {
+ GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!soft_body);
+
+ soft_body->set_ray_pickable(p_enable);
+}
+
+void GodotPhysicsServer3D::soft_body_set_simulation_precision(RID p_body, int p_simulation_precision) {
+ GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!soft_body);
+
+ soft_body->set_iteration_count(p_simulation_precision);
+}
+
+int GodotPhysicsServer3D::soft_body_get_simulation_precision(RID p_body) const {
+ GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!soft_body, 0.f);
+
+ return soft_body->get_iteration_count();
+}
+
+void GodotPhysicsServer3D::soft_body_set_total_mass(RID p_body, real_t p_total_mass) {
+ GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!soft_body);
+
+ soft_body->set_total_mass(p_total_mass);
+}
+
+real_t GodotPhysicsServer3D::soft_body_get_total_mass(RID p_body) const {
+ GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!soft_body, 0.f);
+
+ return soft_body->get_total_mass();
+}
+
+void GodotPhysicsServer3D::soft_body_set_linear_stiffness(RID p_body, real_t p_stiffness) {
+ GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!soft_body);
+
+ soft_body->set_linear_stiffness(p_stiffness);
+}
+
+real_t GodotPhysicsServer3D::soft_body_get_linear_stiffness(RID p_body) const {
+ GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!soft_body, 0.f);
+
+ return soft_body->get_linear_stiffness();
+}
+
+void GodotPhysicsServer3D::soft_body_set_pressure_coefficient(RID p_body, real_t p_pressure_coefficient) {
+ GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!soft_body);
+
+ soft_body->set_pressure_coefficient(p_pressure_coefficient);
+}
+
+real_t GodotPhysicsServer3D::soft_body_get_pressure_coefficient(RID p_body) const {
+ GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!soft_body, 0.f);
+
+ return soft_body->get_pressure_coefficient();
+}
+
+void GodotPhysicsServer3D::soft_body_set_damping_coefficient(RID p_body, real_t p_damping_coefficient) {
+ GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!soft_body);
+
+ soft_body->set_damping_coefficient(p_damping_coefficient);
+}
+
+real_t GodotPhysicsServer3D::soft_body_get_damping_coefficient(RID p_body) const {
+ GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!soft_body, 0.f);
+
+ return soft_body->get_damping_coefficient();
+}
+
+void GodotPhysicsServer3D::soft_body_set_drag_coefficient(RID p_body, real_t p_drag_coefficient) {
+ GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!soft_body);
+
+ soft_body->set_drag_coefficient(p_drag_coefficient);
+}
+
+real_t GodotPhysicsServer3D::soft_body_get_drag_coefficient(RID p_body) const {
+ GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!soft_body, 0.f);
+
+ return soft_body->get_drag_coefficient();
+}
+
+void GodotPhysicsServer3D::soft_body_set_mesh(RID p_body, RID p_mesh) {
+ GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!soft_body);
+
+ soft_body->set_mesh(p_mesh);
+}
+
+AABB GodotPhysicsServer3D::soft_body_get_bounds(RID p_body) const {
+ GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!soft_body, AABB());
+
+ return soft_body->get_bounds();
+}
+
+void GodotPhysicsServer3D::soft_body_move_point(RID p_body, int p_point_index, const Vector3 &p_global_position) {
+ GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!soft_body);
+
+ soft_body->set_vertex_position(p_point_index, p_global_position);
+}
+
+Vector3 GodotPhysicsServer3D::soft_body_get_point_global_position(RID p_body, int p_point_index) const {
+ GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!soft_body, Vector3());
+
+ return soft_body->get_vertex_position(p_point_index);
+}
+
+void GodotPhysicsServer3D::soft_body_remove_all_pinned_points(RID p_body) {
+ GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!soft_body);
+
+ soft_body->unpin_all_vertices();
+}
+
+void GodotPhysicsServer3D::soft_body_pin_point(RID p_body, int p_point_index, bool p_pin) {
+ GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!soft_body);
+
+ if (p_pin) {
+ soft_body->pin_vertex(p_point_index);
+ } else {
+ soft_body->unpin_vertex(p_point_index);
+ }
+}
+
+bool GodotPhysicsServer3D::soft_body_is_point_pinned(RID p_body, int p_point_index) const {
+ GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!soft_body, false);
+
+ return soft_body->is_vertex_pinned(p_point_index);
+}
+
+/* JOINT API */
+
+RID GodotPhysicsServer3D::joint_create() {
+ GodotJoint3D *joint = memnew(GodotJoint3D);
+ RID rid = joint_owner.make_rid(joint);
+ joint->set_self(rid);
+ return rid;
+}
+
+void GodotPhysicsServer3D::joint_clear(RID p_joint) {
+ GodotJoint3D *joint = joint_owner.get_or_null(p_joint);
+ if (joint->get_type() != JOINT_TYPE_MAX) {
+ GodotJoint3D *empty_joint = memnew(GodotJoint3D);
+ empty_joint->copy_settings_from(joint);
+
+ joint_owner.replace(p_joint, empty_joint);
+ memdelete(joint);
+ }
+}
+
+void GodotPhysicsServer3D::joint_make_pin(RID p_joint, RID p_body_A, const Vector3 &p_local_A, RID p_body_B, const Vector3 &p_local_B) {
+ GodotBody3D *body_A = body_owner.get_or_null(p_body_A);
+ ERR_FAIL_COND(!body_A);
+
+ if (!p_body_B.is_valid()) {
+ ERR_FAIL_COND(!body_A->get_space());
+ p_body_B = body_A->get_space()->get_static_global_body();
+ }
+
+ GodotBody3D *body_B = body_owner.get_or_null(p_body_B);
+ ERR_FAIL_COND(!body_B);
+
+ ERR_FAIL_COND(body_A == body_B);
+
+ GodotJoint3D *prev_joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_COND(prev_joint == nullptr);
+
+ GodotJoint3D *joint = memnew(GodotPinJoint3D(body_A, p_local_A, body_B, p_local_B));
+
+ joint->copy_settings_from(prev_joint);
+ joint_owner.replace(p_joint, joint);
+ memdelete(prev_joint);
+}
+
+void GodotPhysicsServer3D::pin_joint_set_param(RID p_joint, PinJointParam p_param, real_t p_value) {
+ GodotJoint3D *joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_COND(!joint);
+ ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_PIN);
+ GodotPinJoint3D *pin_joint = static_cast<GodotPinJoint3D *>(joint);
+ pin_joint->set_param(p_param, p_value);
+}
+
+real_t GodotPhysicsServer3D::pin_joint_get_param(RID p_joint, PinJointParam p_param) const {
+ GodotJoint3D *joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_COND_V(!joint, 0);
+ ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_PIN, 0);
+ GodotPinJoint3D *pin_joint = static_cast<GodotPinJoint3D *>(joint);
+ return pin_joint->get_param(p_param);
+}
+
+void GodotPhysicsServer3D::pin_joint_set_local_a(RID p_joint, const Vector3 &p_A) {
+ GodotJoint3D *joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_COND(!joint);
+ ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_PIN);
+ GodotPinJoint3D *pin_joint = static_cast<GodotPinJoint3D *>(joint);
+ pin_joint->set_pos_a(p_A);
+}
+
+Vector3 GodotPhysicsServer3D::pin_joint_get_local_a(RID p_joint) const {
+ GodotJoint3D *joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_COND_V(!joint, Vector3());
+ ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_PIN, Vector3());
+ GodotPinJoint3D *pin_joint = static_cast<GodotPinJoint3D *>(joint);
+ return pin_joint->get_position_a();
+}
+
+void GodotPhysicsServer3D::pin_joint_set_local_b(RID p_joint, const Vector3 &p_B) {
+ GodotJoint3D *joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_COND(!joint);
+ ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_PIN);
+ GodotPinJoint3D *pin_joint = static_cast<GodotPinJoint3D *>(joint);
+ pin_joint->set_pos_b(p_B);
+}
+
+Vector3 GodotPhysicsServer3D::pin_joint_get_local_b(RID p_joint) const {
+ GodotJoint3D *joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_COND_V(!joint, Vector3());
+ ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_PIN, Vector3());
+ GodotPinJoint3D *pin_joint = static_cast<GodotPinJoint3D *>(joint);
+ return pin_joint->get_position_b();
+}
+
+void GodotPhysicsServer3D::joint_make_hinge(RID p_joint, RID p_body_A, const Transform3D &p_frame_A, RID p_body_B, const Transform3D &p_frame_B) {
+ GodotBody3D *body_A = body_owner.get_or_null(p_body_A);
+ ERR_FAIL_COND(!body_A);
+
+ if (!p_body_B.is_valid()) {
+ ERR_FAIL_COND(!body_A->get_space());
+ p_body_B = body_A->get_space()->get_static_global_body();
+ }
+
+ GodotBody3D *body_B = body_owner.get_or_null(p_body_B);
+ ERR_FAIL_COND(!body_B);
+
+ ERR_FAIL_COND(body_A == body_B);
+
+ GodotJoint3D *prev_joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_COND(prev_joint == nullptr);
+
+ GodotJoint3D *joint = memnew(GodotHingeJoint3D(body_A, body_B, p_frame_A, p_frame_B));
+
+ joint->copy_settings_from(prev_joint);
+ joint_owner.replace(p_joint, joint);
+ memdelete(prev_joint);
+}
+
+void GodotPhysicsServer3D::joint_make_hinge_simple(RID p_joint, RID p_body_A, const Vector3 &p_pivot_A, const Vector3 &p_axis_A, RID p_body_B, const Vector3 &p_pivot_B, const Vector3 &p_axis_B) {
+ GodotBody3D *body_A = body_owner.get_or_null(p_body_A);
+ ERR_FAIL_COND(!body_A);
+
+ if (!p_body_B.is_valid()) {
+ ERR_FAIL_COND(!body_A->get_space());
+ p_body_B = body_A->get_space()->get_static_global_body();
+ }
+
+ GodotBody3D *body_B = body_owner.get_or_null(p_body_B);
+ ERR_FAIL_COND(!body_B);
+
+ ERR_FAIL_COND(body_A == body_B);
+
+ GodotJoint3D *prev_joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_COND(prev_joint == nullptr);
+
+ GodotJoint3D *joint = memnew(GodotHingeJoint3D(body_A, body_B, p_pivot_A, p_pivot_B, p_axis_A, p_axis_B));
+
+ joint->copy_settings_from(prev_joint);
+ joint_owner.replace(p_joint, joint);
+ memdelete(prev_joint);
+}
+
+void GodotPhysicsServer3D::hinge_joint_set_param(RID p_joint, HingeJointParam p_param, real_t p_value) {
+ GodotJoint3D *joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_COND(!joint);
+ ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_HINGE);
+ GodotHingeJoint3D *hinge_joint = static_cast<GodotHingeJoint3D *>(joint);
+ hinge_joint->set_param(p_param, p_value);
+}
+
+real_t GodotPhysicsServer3D::hinge_joint_get_param(RID p_joint, HingeJointParam p_param) const {
+ GodotJoint3D *joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_COND_V(!joint, 0);
+ ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_HINGE, 0);
+ GodotHingeJoint3D *hinge_joint = static_cast<GodotHingeJoint3D *>(joint);
+ return hinge_joint->get_param(p_param);
+}
+
+void GodotPhysicsServer3D::hinge_joint_set_flag(RID p_joint, HingeJointFlag p_flag, bool p_value) {
+ GodotJoint3D *joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_COND(!joint);
+ ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_HINGE);
+ GodotHingeJoint3D *hinge_joint = static_cast<GodotHingeJoint3D *>(joint);
+ hinge_joint->set_flag(p_flag, p_value);
+}
+
+bool GodotPhysicsServer3D::hinge_joint_get_flag(RID p_joint, HingeJointFlag p_flag) const {
+ GodotJoint3D *joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_COND_V(!joint, false);
+ ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_HINGE, false);
+ GodotHingeJoint3D *hinge_joint = static_cast<GodotHingeJoint3D *>(joint);
+ return hinge_joint->get_flag(p_flag);
+}
+
+void GodotPhysicsServer3D::joint_set_solver_priority(RID p_joint, int p_priority) {
+ GodotJoint3D *joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_COND(!joint);
+ joint->set_priority(p_priority);
+}
+
+int GodotPhysicsServer3D::joint_get_solver_priority(RID p_joint) const {
+ GodotJoint3D *joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_COND_V(!joint, 0);
+ return joint->get_priority();
+}
+
+void GodotPhysicsServer3D::joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) {
+ GodotJoint3D *joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_COND(!joint);
+
+ joint->disable_collisions_between_bodies(p_disable);
+
+ if (2 == joint->get_body_count()) {
+ GodotBody3D *body_a = *joint->get_body_ptr();
+ GodotBody3D *body_b = *(joint->get_body_ptr() + 1);
+
+ if (p_disable) {
+ body_add_collision_exception(body_a->get_self(), body_b->get_self());
+ body_add_collision_exception(body_b->get_self(), body_a->get_self());
+ } else {
+ body_remove_collision_exception(body_a->get_self(), body_b->get_self());
+ body_remove_collision_exception(body_b->get_self(), body_a->get_self());
+ }
+ }
+}
+
+bool GodotPhysicsServer3D::joint_is_disabled_collisions_between_bodies(RID p_joint) const {
+ GodotJoint3D *joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_COND_V(!joint, true);
+
+ return joint->is_disabled_collisions_between_bodies();
+}
+
+GodotPhysicsServer3D::JointType GodotPhysicsServer3D::joint_get_type(RID p_joint) const {
+ GodotJoint3D *joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_COND_V(!joint, JOINT_TYPE_PIN);
+ return joint->get_type();
+}
+
+void GodotPhysicsServer3D::joint_make_slider(RID p_joint, RID p_body_A, const Transform3D &p_local_frame_A, RID p_body_B, const Transform3D &p_local_frame_B) {
+ GodotBody3D *body_A = body_owner.get_or_null(p_body_A);
+ ERR_FAIL_COND(!body_A);
+
+ if (!p_body_B.is_valid()) {
+ ERR_FAIL_COND(!body_A->get_space());
+ p_body_B = body_A->get_space()->get_static_global_body();
+ }
+
+ GodotBody3D *body_B = body_owner.get_or_null(p_body_B);
+ ERR_FAIL_COND(!body_B);
+
+ ERR_FAIL_COND(body_A == body_B);
+
+ GodotJoint3D *prev_joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_COND(prev_joint == nullptr);
+
+ GodotJoint3D *joint = memnew(GodotSliderJoint3D(body_A, body_B, p_local_frame_A, p_local_frame_B));
+
+ joint->copy_settings_from(prev_joint);
+ joint_owner.replace(p_joint, joint);
+ memdelete(prev_joint);
+}
+
+void GodotPhysicsServer3D::slider_joint_set_param(RID p_joint, SliderJointParam p_param, real_t p_value) {
+ GodotJoint3D *joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_COND(!joint);
+ ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_SLIDER);
+ GodotSliderJoint3D *slider_joint = static_cast<GodotSliderJoint3D *>(joint);
+ slider_joint->set_param(p_param, p_value);
+}
+
+real_t GodotPhysicsServer3D::slider_joint_get_param(RID p_joint, SliderJointParam p_param) const {
+ GodotJoint3D *joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_COND_V(!joint, 0);
+ ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_CONE_TWIST, 0);
+ GodotSliderJoint3D *slider_joint = static_cast<GodotSliderJoint3D *>(joint);
+ return slider_joint->get_param(p_param);
+}
+
+void GodotPhysicsServer3D::joint_make_cone_twist(RID p_joint, RID p_body_A, const Transform3D &p_local_frame_A, RID p_body_B, const Transform3D &p_local_frame_B) {
+ GodotBody3D *body_A = body_owner.get_or_null(p_body_A);
+ ERR_FAIL_COND(!body_A);
+
+ if (!p_body_B.is_valid()) {
+ ERR_FAIL_COND(!body_A->get_space());
+ p_body_B = body_A->get_space()->get_static_global_body();
+ }
+
+ GodotBody3D *body_B = body_owner.get_or_null(p_body_B);
+ ERR_FAIL_COND(!body_B);
+
+ ERR_FAIL_COND(body_A == body_B);
+
+ GodotJoint3D *prev_joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_COND(prev_joint == nullptr);
+
+ GodotJoint3D *joint = memnew(GodotConeTwistJoint3D(body_A, body_B, p_local_frame_A, p_local_frame_B));
+
+ joint->copy_settings_from(prev_joint);
+ joint_owner.replace(p_joint, joint);
+ memdelete(prev_joint);
+}
+
+void GodotPhysicsServer3D::cone_twist_joint_set_param(RID p_joint, ConeTwistJointParam p_param, real_t p_value) {
+ GodotJoint3D *joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_COND(!joint);
+ ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_CONE_TWIST);
+ GodotConeTwistJoint3D *cone_twist_joint = static_cast<GodotConeTwistJoint3D *>(joint);
+ cone_twist_joint->set_param(p_param, p_value);
+}
+
+real_t GodotPhysicsServer3D::cone_twist_joint_get_param(RID p_joint, ConeTwistJointParam p_param) const {
+ GodotJoint3D *joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_COND_V(!joint, 0);
+ ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_CONE_TWIST, 0);
+ GodotConeTwistJoint3D *cone_twist_joint = static_cast<GodotConeTwistJoint3D *>(joint);
+ return cone_twist_joint->get_param(p_param);
+}
+
+void GodotPhysicsServer3D::joint_make_generic_6dof(RID p_joint, RID p_body_A, const Transform3D &p_local_frame_A, RID p_body_B, const Transform3D &p_local_frame_B) {
+ GodotBody3D *body_A = body_owner.get_or_null(p_body_A);
+ ERR_FAIL_COND(!body_A);
+
+ if (!p_body_B.is_valid()) {
+ ERR_FAIL_COND(!body_A->get_space());
+ p_body_B = body_A->get_space()->get_static_global_body();
+ }
+
+ GodotBody3D *body_B = body_owner.get_or_null(p_body_B);
+ ERR_FAIL_COND(!body_B);
+
+ ERR_FAIL_COND(body_A == body_B);
+
+ GodotJoint3D *prev_joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_COND(prev_joint == nullptr);
+
+ GodotJoint3D *joint = memnew(GodotGeneric6DOFJoint3D(body_A, body_B, p_local_frame_A, p_local_frame_B, true));
+
+ joint->copy_settings_from(prev_joint);
+ joint_owner.replace(p_joint, joint);
+ memdelete(prev_joint);
+}
+
+void GodotPhysicsServer3D::generic_6dof_joint_set_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param, real_t p_value) {
+ GodotJoint3D *joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_COND(!joint);
+ ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_6DOF);
+ GodotGeneric6DOFJoint3D *generic_6dof_joint = static_cast<GodotGeneric6DOFJoint3D *>(joint);
+ generic_6dof_joint->set_param(p_axis, p_param, p_value);
+}
+
+real_t GodotPhysicsServer3D::generic_6dof_joint_get_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param) const {
+ GodotJoint3D *joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_COND_V(!joint, 0);
+ ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_6DOF, 0);
+ GodotGeneric6DOFJoint3D *generic_6dof_joint = static_cast<GodotGeneric6DOFJoint3D *>(joint);
+ return generic_6dof_joint->get_param(p_axis, p_param);
+}
+
+void GodotPhysicsServer3D::generic_6dof_joint_set_flag(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisFlag p_flag, bool p_enable) {
+ GodotJoint3D *joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_COND(!joint);
+ ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_6DOF);
+ GodotGeneric6DOFJoint3D *generic_6dof_joint = static_cast<GodotGeneric6DOFJoint3D *>(joint);
+ generic_6dof_joint->set_flag(p_axis, p_flag, p_enable);
+}
+
+bool GodotPhysicsServer3D::generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisFlag p_flag) const {
+ GodotJoint3D *joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_COND_V(!joint, false);
+ ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_6DOF, false);
+ GodotGeneric6DOFJoint3D *generic_6dof_joint = static_cast<GodotGeneric6DOFJoint3D *>(joint);
+ return generic_6dof_joint->get_flag(p_axis, p_flag);
+}
+
+void GodotPhysicsServer3D::free(RID p_rid) {
+ _update_shapes(); //just in case
+
+ if (shape_owner.owns(p_rid)) {
+ GodotShape3D *shape = shape_owner.get_or_null(p_rid);
+
+ while (shape->get_owners().size()) {
+ GodotShapeOwner3D *so = shape->get_owners().front()->key();
+ so->remove_shape(shape);
+ }
+
+ shape_owner.free(p_rid);
+ memdelete(shape);
+ } else if (body_owner.owns(p_rid)) {
+ GodotBody3D *body = body_owner.get_or_null(p_rid);
+
+ /*
+ if (body->get_state_query())
+ _clear_query(body->get_state_query());
+
+ if (body->get_direct_state_query())
+ _clear_query(body->get_direct_state_query());
+ */
+
+ body->set_space(nullptr);
+
+ while (body->get_shape_count()) {
+ body->remove_shape(0);
+ }
+
+ body_owner.free(p_rid);
+ memdelete(body);
+ } else if (soft_body_owner.owns(p_rid)) {
+ GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_rid);
+
+ soft_body->set_space(nullptr);
+
+ soft_body_owner.free(p_rid);
+ memdelete(soft_body);
+ } else if (area_owner.owns(p_rid)) {
+ GodotArea3D *area = area_owner.get_or_null(p_rid);
+
+ /*
+ if (area->get_monitor_query())
+ _clear_query(area->get_monitor_query());
+ */
+
+ area->set_space(nullptr);
+
+ while (area->get_shape_count()) {
+ area->remove_shape(0);
+ }
+
+ area_owner.free(p_rid);
+ memdelete(area);
+ } else if (space_owner.owns(p_rid)) {
+ GodotSpace3D *space = space_owner.get_or_null(p_rid);
+
+ while (space->get_objects().size()) {
+ GodotCollisionObject3D *co = (GodotCollisionObject3D *)space->get_objects().front()->get();
+ co->set_space(nullptr);
+ }
+
+ active_spaces.erase(space);
+ free(space->get_default_area()->get_self());
+ free(space->get_static_global_body());
+
+ space_owner.free(p_rid);
+ memdelete(space);
+ } else if (joint_owner.owns(p_rid)) {
+ GodotJoint3D *joint = joint_owner.get_or_null(p_rid);
+
+ joint_owner.free(p_rid);
+ memdelete(joint);
+
+ } else {
+ ERR_FAIL_MSG("Invalid ID.");
+ }
+}
+
+void GodotPhysicsServer3D::set_active(bool p_active) {
+ active = p_active;
+}
+
+void GodotPhysicsServer3D::init() {
+ stepper = memnew(GodotStep3D);
+}
+
+void GodotPhysicsServer3D::step(real_t p_step) {
+#ifndef _3D_DISABLED
+
+ if (!active) {
+ return;
+ }
+
+ _update_shapes();
+
+ island_count = 0;
+ active_objects = 0;
+ collision_pairs = 0;
+ for (Set<const GodotSpace3D *>::Element *E = active_spaces.front(); E; E = E->next()) {
+ stepper->step((GodotSpace3D *)E->get(), p_step);
+ island_count += E->get()->get_island_count();
+ active_objects += E->get()->get_active_objects();
+ collision_pairs += E->get()->get_collision_pairs();
+ }
+#endif
+}
+
+void GodotPhysicsServer3D::sync() {
+ doing_sync = true;
+}
+
+void GodotPhysicsServer3D::flush_queries() {
+#ifndef _3D_DISABLED
+
+ if (!active) {
+ return;
+ }
+
+ flushing_queries = true;
+
+ uint64_t time_beg = OS::get_singleton()->get_ticks_usec();
+
+ for (Set<const GodotSpace3D *>::Element *E = active_spaces.front(); E; E = E->next()) {
+ GodotSpace3D *space = (GodotSpace3D *)E->get();
+ space->call_queries();
+ }
+
+ flushing_queries = false;
+
+ if (EngineDebugger::is_profiling("servers")) {
+ uint64_t total_time[GodotSpace3D::ELAPSED_TIME_MAX];
+ static const char *time_name[GodotSpace3D::ELAPSED_TIME_MAX] = {
+ "integrate_forces",
+ "generate_islands",
+ "setup_constraints",
+ "solve_constraints",
+ "integrate_velocities"
+ };
+
+ for (int i = 0; i < GodotSpace3D::ELAPSED_TIME_MAX; i++) {
+ total_time[i] = 0;
+ }
+
+ for (Set<const GodotSpace3D *>::Element *E = active_spaces.front(); E; E = E->next()) {
+ for (int i = 0; i < GodotSpace3D::ELAPSED_TIME_MAX; i++) {
+ total_time[i] += E->get()->get_elapsed_time(GodotSpace3D::ElapsedTime(i));
+ }
+ }
+
+ Array values;
+ values.resize(GodotSpace3D::ELAPSED_TIME_MAX * 2);
+ for (int i = 0; i < GodotSpace3D::ELAPSED_TIME_MAX; i++) {
+ values[i * 2 + 0] = time_name[i];
+ values[i * 2 + 1] = USEC_TO_SEC(total_time[i]);
+ }
+ values.push_back("flush_queries");
+ values.push_back(USEC_TO_SEC(OS::get_singleton()->get_ticks_usec() - time_beg));
+
+ values.push_front("physics");
+ EngineDebugger::profiler_add_frame_data("servers", values);
+ }
+#endif
+}
+
+void GodotPhysicsServer3D::end_sync() {
+ doing_sync = false;
+}
+
+void GodotPhysicsServer3D::finish() {
+ memdelete(stepper);
+}
+
+int GodotPhysicsServer3D::get_process_info(ProcessInfo p_info) {
+ switch (p_info) {
+ case INFO_ACTIVE_OBJECTS: {
+ return active_objects;
+ } break;
+ case INFO_COLLISION_PAIRS: {
+ return collision_pairs;
+ } break;
+ case INFO_ISLAND_COUNT: {
+ return island_count;
+ } break;
+ }
+
+ return 0;
+}
+
+void GodotPhysicsServer3D::_update_shapes() {
+ while (pending_shape_update_list.first()) {
+ pending_shape_update_list.first()->self()->_shape_changed();
+ pending_shape_update_list.remove(pending_shape_update_list.first());
+ }
+}
+
+void GodotPhysicsServer3D::_shape_col_cbk(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) {
+ CollCbkData *cbk = (CollCbkData *)p_userdata;
+
+ if (cbk->max == 0) {
+ return;
+ }
+
+ if (cbk->amount == cbk->max) {
+ //find least deep
+ real_t min_depth = 1e20;
+ int min_depth_idx = 0;
+ for (int i = 0; i < cbk->amount; i++) {
+ real_t d = cbk->ptr[i * 2 + 0].distance_squared_to(cbk->ptr[i * 2 + 1]);
+ if (d < min_depth) {
+ min_depth = d;
+ min_depth_idx = i;
+ }
+ }
+
+ real_t d = p_point_A.distance_squared_to(p_point_B);
+ if (d < min_depth) {
+ return;
+ }
+ cbk->ptr[min_depth_idx * 2 + 0] = p_point_A;
+ cbk->ptr[min_depth_idx * 2 + 1] = p_point_B;
+
+ } else {
+ cbk->ptr[cbk->amount * 2 + 0] = p_point_A;
+ cbk->ptr[cbk->amount * 2 + 1] = p_point_B;
+ cbk->amount++;
+ }
+}
+
+GodotPhysicsServer3D *GodotPhysicsServer3D::godot_singleton = nullptr;
+GodotPhysicsServer3D::GodotPhysicsServer3D(bool p_using_threads) {
+ godot_singleton = this;
+ GodotBroadPhase3D::create_func = GodotBroadPhase3DBVH::_create;
+
+ using_threads = p_using_threads;
+};
diff --git a/servers/physics_3d/physics_server_3d_sw.h b/servers/physics_3d/godot_physics_server_3d.h
index 54a787198d..b903f4808c 100644
--- a/servers/physics_3d/physics_server_3d_sw.h
+++ b/servers/physics_3d/godot_physics_server_3d.h
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* physics_server_3d_sw.h */
+/* godot_physics_server_3d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,22 +28,22 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef PHYSICS_SERVER_SW
-#define PHYSICS_SERVER_SW
+#ifndef GODOT_PHYSICS_SERVER_3D_H
+#define GODOT_PHYSICS_SERVER_3D_H
+
+#include "godot_joint_3d.h"
+#include "godot_shape_3d.h"
+#include "godot_space_3d.h"
+#include "godot_step_3d.h"
#include "core/templates/rid_owner.h"
-#include "joints_3d_sw.h"
#include "servers/physics_server_3d.h"
-#include "shape_3d_sw.h"
-#include "space_3d_sw.h"
-#include "step_3d_sw.h"
-class PhysicsServer3DSW : public PhysicsServer3D {
- GDCLASS(PhysicsServer3DSW, PhysicsServer3D);
+class GodotPhysicsServer3D : public PhysicsServer3D {
+ GDCLASS(GodotPhysicsServer3D, PhysicsServer3D);
- friend class PhysicsDirectSpaceState3DSW;
+ friend class GodotPhysicsDirectSpaceState3D;
bool active = true;
- int iterations = 0;
int island_count = 0;
int active_objects = 0;
@@ -53,22 +53,22 @@ class PhysicsServer3DSW : public PhysicsServer3D {
bool doing_sync = false;
bool flushing_queries = false;
- Step3DSW *stepper = nullptr;
- Set<const Space3DSW *> active_spaces;
+ GodotStep3D *stepper = nullptr;
+ Set<const GodotSpace3D *> active_spaces;
- mutable RID_PtrOwner<Shape3DSW, true> shape_owner;
- mutable RID_PtrOwner<Space3DSW, true> space_owner;
- mutable RID_PtrOwner<Area3DSW, true> area_owner;
- mutable RID_PtrOwner<Body3DSW, true> body_owner;
- mutable RID_PtrOwner<SoftBody3DSW, true> soft_body_owner;
- mutable RID_PtrOwner<Joint3DSW, true> joint_owner;
+ mutable RID_PtrOwner<GodotShape3D, true> shape_owner;
+ mutable RID_PtrOwner<GodotSpace3D, true> space_owner;
+ mutable RID_PtrOwner<GodotArea3D, true> area_owner;
+ mutable RID_PtrOwner<GodotBody3D, true> body_owner;
+ mutable RID_PtrOwner<GodotSoftBody3D, true> soft_body_owner;
+ mutable RID_PtrOwner<GodotJoint3D, true> joint_owner;
//void _clear_query(QuerySW *p_query);
- friend class CollisionObject3DSW;
- SelfList<CollisionObject3DSW>::List pending_shape_update_list;
+ friend class GodotCollisionObject3D;
+ SelfList<GodotCollisionObject3D>::List pending_shape_update_list;
void _update_shapes();
- static PhysicsServer3DSW *singletonsw;
+ static GodotPhysicsServer3D *godot_singleton;
public:
struct CollCbkData {
@@ -121,9 +121,6 @@ public:
virtual RID area_create() override;
- virtual void area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) override;
- virtual AreaSpaceOverrideMode area_get_space_override_mode(RID p_area) const override;
-
virtual void area_set_space(RID p_area, RID p_space) override;
virtual RID area_get_space(RID p_area) const override;
@@ -156,8 +153,8 @@ public:
virtual void area_set_monitorable(RID p_area, bool p_monitorable) override;
- virtual void area_set_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) override;
- virtual void area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) override;
+ virtual void area_set_monitor_callback(RID p_area, const Callable &p_callback) override;
+ virtual void area_set_area_monitor_callback(RID p_area, const Callable &p_callback) override;
/* BODY API */
@@ -206,19 +203,24 @@ public:
virtual void body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) override;
virtual Variant body_get_state(RID p_body, BodyState p_state) const override;
- virtual void body_set_applied_force(RID p_body, const Vector3 &p_force) override;
- virtual Vector3 body_get_applied_force(RID p_body) const override;
-
- virtual void body_set_applied_torque(RID p_body, const Vector3 &p_torque) override;
- virtual Vector3 body_get_applied_torque(RID p_body) const override;
-
- virtual void body_add_central_force(RID p_body, const Vector3 &p_force) override;
- virtual void body_add_force(RID p_body, const Vector3 &p_force, const Vector3 &p_position = Vector3()) override;
- virtual void body_add_torque(RID p_body, const Vector3 &p_torque) override;
-
virtual void body_apply_central_impulse(RID p_body, const Vector3 &p_impulse) override;
virtual void body_apply_impulse(RID p_body, const Vector3 &p_impulse, const Vector3 &p_position = Vector3()) override;
virtual void body_apply_torque_impulse(RID p_body, const Vector3 &p_impulse) override;
+
+ virtual void body_apply_central_force(RID p_body, const Vector3 &p_force) override;
+ virtual void body_apply_force(RID p_body, const Vector3 &p_force, const Vector3 &p_position = Vector3()) override;
+ virtual void body_apply_torque(RID p_body, const Vector3 &p_torque) override;
+
+ virtual void body_add_constant_central_force(RID p_body, const Vector3 &p_force) override;
+ virtual void body_add_constant_force(RID p_body, const Vector3 &p_force, const Vector3 &p_position = Vector3()) override;
+ virtual void body_add_constant_torque(RID p_body, const Vector3 &p_torque) override;
+
+ virtual void body_set_constant_force(RID p_body, const Vector3 &p_force) override;
+ virtual Vector3 body_get_constant_force(RID p_body) const override;
+
+ virtual void body_set_constant_torque(RID p_body, const Vector3 &p_torque) override;
+ virtual Vector3 body_get_constant_torque(RID p_body) const override;
+
virtual void body_set_axis_velocity(RID p_body, const Vector3 &p_axis_velocity) override;
virtual void body_set_axis_lock(RID p_body, BodyAxis p_axis, bool p_lock) override;
@@ -366,14 +368,12 @@ public:
virtual void end_sync() override;
virtual void finish() override;
- virtual void set_collision_iterations(int p_iterations) override;
-
virtual bool is_flushing_queries() const override { return flushing_queries; }
int get_process_info(ProcessInfo p_info) override;
- PhysicsServer3DSW(bool p_using_threads = false);
- ~PhysicsServer3DSW() {}
+ GodotPhysicsServer3D(bool p_using_threads = false);
+ ~GodotPhysicsServer3D() {}
};
-#endif
+#endif // GODOT_PHYSICS_SERVER_3D_H
diff --git a/servers/physics_3d/shape_3d_sw.cpp b/servers/physics_3d/godot_shape_3d.cpp
index 0fb6d582c8..26fa470233 100644
--- a/servers/physics_3d/shape_3d_sw.cpp
+++ b/servers/physics_3d/godot_shape_3d.cpp
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* shape_3d_sw.cpp */
+/* godot_shape_3d.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,14 +28,14 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "shape_3d_sw.h"
+#include "godot_shape_3d.h"
#include "core/io/image.h"
#include "core/math/convex_hull.h"
#include "core/math/geometry_3d.h"
#include "core/templates/sort_array.h"
-// HeightMapShape3DSW is based on Bullet btHeightfieldTerrainShape.
+// GodotHeightMapShape3D is based on Bullet btHeightfieldTerrainShape.
/*
Bullet Continuous Collision Detection and Physics Library
@@ -58,16 +58,16 @@ subject to the following restrictions:
#define _CYLINDER_EDGE_IS_VALID_SUPPORT_THRESHOLD 0.002
#define _CYLINDER_FACE_IS_VALID_SUPPORT_THRESHOLD 0.999
-void Shape3DSW::configure(const AABB &p_aabb) {
+void GodotShape3D::configure(const AABB &p_aabb) {
aabb = p_aabb;
configured = true;
- for (const KeyValue<ShapeOwner3DSW *, int> &E : owners) {
- ShapeOwner3DSW *co = (ShapeOwner3DSW *)E.key;
+ for (const KeyValue<GodotShapeOwner3D *, int> &E : owners) {
+ GodotShapeOwner3D *co = (GodotShapeOwner3D *)E.key;
co->_shape_changed();
}
}
-Vector3 Shape3DSW::get_support(const Vector3 &p_normal) const {
+Vector3 GodotShape3D::get_support(const Vector3 &p_normal) const {
Vector3 res;
int amnt;
FeatureType type;
@@ -75,8 +75,8 @@ Vector3 Shape3DSW::get_support(const Vector3 &p_normal) const {
return res;
}
-void Shape3DSW::add_owner(ShapeOwner3DSW *p_owner) {
- Map<ShapeOwner3DSW *, int>::Element *E = owners.find(p_owner);
+void GodotShape3D::add_owner(GodotShapeOwner3D *p_owner) {
+ Map<GodotShapeOwner3D *, int>::Element *E = owners.find(p_owner);
if (E) {
E->get()++;
} else {
@@ -84,8 +84,8 @@ void Shape3DSW::add_owner(ShapeOwner3DSW *p_owner) {
}
}
-void Shape3DSW::remove_owner(ShapeOwner3DSW *p_owner) {
- Map<ShapeOwner3DSW *, int>::Element *E = owners.find(p_owner);
+void GodotShape3D::remove_owner(GodotShapeOwner3D *p_owner) {
+ Map<GodotShapeOwner3D *, int>::Element *E = owners.find(p_owner);
ERR_FAIL_COND(!E);
E->get()--;
if (E->get() == 0) {
@@ -93,33 +93,33 @@ void Shape3DSW::remove_owner(ShapeOwner3DSW *p_owner) {
}
}
-bool Shape3DSW::is_owner(ShapeOwner3DSW *p_owner) const {
+bool GodotShape3D::is_owner(GodotShapeOwner3D *p_owner) const {
return owners.has(p_owner);
}
-const Map<ShapeOwner3DSW *, int> &Shape3DSW::get_owners() const {
+const Map<GodotShapeOwner3D *, int> &GodotShape3D::get_owners() const {
return owners;
}
-Shape3DSW::~Shape3DSW() {
+GodotShape3D::~GodotShape3D() {
ERR_FAIL_COND(owners.size());
}
-Plane WorldBoundaryShape3DSW::get_plane() const {
+Plane GodotWorldBoundaryShape3D::get_plane() const {
return plane;
}
-void WorldBoundaryShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const {
+void GodotWorldBoundaryShape3D::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const {
// gibberish, a plane is infinity
r_min = -1e7;
r_max = 1e7;
}
-Vector3 WorldBoundaryShape3DSW::get_support(const Vector3 &p_normal) const {
+Vector3 GodotWorldBoundaryShape3D::get_support(const Vector3 &p_normal) const {
return p_normal * 1e15;
}
-bool WorldBoundaryShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const {
+bool GodotWorldBoundaryShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const {
bool inters = plane.intersects_segment(p_begin, p_end, &r_result);
if (inters) {
r_normal = plane.normal;
@@ -127,11 +127,11 @@ bool WorldBoundaryShape3DSW::intersect_segment(const Vector3 &p_begin, const Vec
return inters;
}
-bool WorldBoundaryShape3DSW::intersect_point(const Vector3 &p_point) const {
+bool GodotWorldBoundaryShape3D::intersect_point(const Vector3 &p_point) const {
return plane.distance_to(p_point) < 0;
}
-Vector3 WorldBoundaryShape3DSW::get_closest_point_to(const Vector3 &p_point) const {
+Vector3 GodotWorldBoundaryShape3D::get_closest_point_to(const Vector3 &p_point) const {
if (plane.is_point_over(p_point)) {
return plane.project(p_point);
} else {
@@ -139,43 +139,43 @@ Vector3 WorldBoundaryShape3DSW::get_closest_point_to(const Vector3 &p_point) con
}
}
-Vector3 WorldBoundaryShape3DSW::get_moment_of_inertia(real_t p_mass) const {
+Vector3 GodotWorldBoundaryShape3D::get_moment_of_inertia(real_t p_mass) const {
return Vector3(); // not applicable.
}
-void WorldBoundaryShape3DSW::_setup(const Plane &p_plane) {
+void GodotWorldBoundaryShape3D::_setup(const Plane &p_plane) {
plane = p_plane;
configure(AABB(Vector3(-1e4, -1e4, -1e4), Vector3(1e4 * 2, 1e4 * 2, 1e4 * 2)));
}
-void WorldBoundaryShape3DSW::set_data(const Variant &p_data) {
+void GodotWorldBoundaryShape3D::set_data(const Variant &p_data) {
_setup(p_data);
}
-Variant WorldBoundaryShape3DSW::get_data() const {
+Variant GodotWorldBoundaryShape3D::get_data() const {
return plane;
}
-WorldBoundaryShape3DSW::WorldBoundaryShape3DSW() {
+GodotWorldBoundaryShape3D::GodotWorldBoundaryShape3D() {
}
//
-real_t SeparationRayShape3DSW::get_length() const {
+real_t GodotSeparationRayShape3D::get_length() const {
return length;
}
-bool SeparationRayShape3DSW::get_slide_on_slope() const {
+bool GodotSeparationRayShape3D::get_slide_on_slope() const {
return slide_on_slope;
}
-void SeparationRayShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const {
+void GodotSeparationRayShape3D::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const {
// don't think this will be even used
r_min = 0;
r_max = 1;
}
-Vector3 SeparationRayShape3DSW::get_support(const Vector3 &p_normal) const {
+Vector3 GodotSeparationRayShape3D::get_support(const Vector3 &p_normal) const {
if (p_normal.z > 0) {
return Vector3(0, 0, length);
} else {
@@ -183,7 +183,7 @@ Vector3 SeparationRayShape3DSW::get_support(const Vector3 &p_normal) const {
}
}
-void SeparationRayShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const {
+void GodotSeparationRayShape3D::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const {
if (Math::abs(p_normal.z) < _EDGE_IS_VALID_SUPPORT_THRESHOLD) {
r_amount = 2;
r_type = FEATURE_EDGE;
@@ -200,15 +200,15 @@ void SeparationRayShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Ve
}
}
-bool SeparationRayShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const {
+bool GodotSeparationRayShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const {
return false; //simply not possible
}
-bool SeparationRayShape3DSW::intersect_point(const Vector3 &p_point) const {
+bool GodotSeparationRayShape3D::intersect_point(const Vector3 &p_point) const {
return false; //simply not possible
}
-Vector3 SeparationRayShape3DSW::get_closest_point_to(const Vector3 &p_point) const {
+Vector3 GodotSeparationRayShape3D::get_closest_point_to(const Vector3 &p_point) const {
Vector3 s[2] = {
Vector3(0, 0, 0),
Vector3(0, 0, length)
@@ -217,37 +217,37 @@ Vector3 SeparationRayShape3DSW::get_closest_point_to(const Vector3 &p_point) con
return Geometry3D::get_closest_point_to_segment(p_point, s);
}
-Vector3 SeparationRayShape3DSW::get_moment_of_inertia(real_t p_mass) const {
+Vector3 GodotSeparationRayShape3D::get_moment_of_inertia(real_t p_mass) const {
return Vector3();
}
-void SeparationRayShape3DSW::_setup(real_t p_length, bool p_slide_on_slope) {
+void GodotSeparationRayShape3D::_setup(real_t p_length, bool p_slide_on_slope) {
length = p_length;
slide_on_slope = p_slide_on_slope;
configure(AABB(Vector3(0, 0, 0), Vector3(0.1, 0.1, length)));
}
-void SeparationRayShape3DSW::set_data(const Variant &p_data) {
+void GodotSeparationRayShape3D::set_data(const Variant &p_data) {
Dictionary d = p_data;
_setup(d["length"], d["slide_on_slope"]);
}
-Variant SeparationRayShape3DSW::get_data() const {
+Variant GodotSeparationRayShape3D::get_data() const {
Dictionary d;
d["length"] = length;
d["slide_on_slope"] = slide_on_slope;
return d;
}
-SeparationRayShape3DSW::SeparationRayShape3DSW() {}
+GodotSeparationRayShape3D::GodotSeparationRayShape3D() {}
/********** SPHERE *************/
-real_t SphereShape3DSW::get_radius() const {
+real_t GodotSphereShape3D::get_radius() const {
return radius;
}
-void SphereShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const {
+void GodotSphereShape3D::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const {
real_t d = p_normal.dot(p_transform.origin);
// figure out scale at point
@@ -258,25 +258,25 @@ void SphereShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &
r_max = d + (radius)*scale;
}
-Vector3 SphereShape3DSW::get_support(const Vector3 &p_normal) const {
+Vector3 GodotSphereShape3D::get_support(const Vector3 &p_normal) const {
return p_normal * radius;
}
-void SphereShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const {
+void GodotSphereShape3D::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const {
*r_supports = p_normal * radius;
r_amount = 1;
r_type = FEATURE_POINT;
}
-bool SphereShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const {
+bool GodotSphereShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const {
return Geometry3D::segment_intersects_sphere(p_begin, p_end, Vector3(), radius, &r_result, &r_normal);
}
-bool SphereShape3DSW::intersect_point(const Vector3 &p_point) const {
+bool GodotSphereShape3D::intersect_point(const Vector3 &p_point) const {
return p_point.length() < radius;
}
-Vector3 SphereShape3DSW::get_closest_point_to(const Vector3 &p_point) const {
+Vector3 GodotSphereShape3D::get_closest_point_to(const Vector3 &p_point) const {
Vector3 p = p_point;
real_t l = p.length();
if (l < radius) {
@@ -285,29 +285,29 @@ Vector3 SphereShape3DSW::get_closest_point_to(const Vector3 &p_point) const {
return (p / l) * radius;
}
-Vector3 SphereShape3DSW::get_moment_of_inertia(real_t p_mass) const {
+Vector3 GodotSphereShape3D::get_moment_of_inertia(real_t p_mass) const {
real_t s = 0.4 * p_mass * radius * radius;
return Vector3(s, s, s);
}
-void SphereShape3DSW::_setup(real_t p_radius) {
+void GodotSphereShape3D::_setup(real_t p_radius) {
radius = p_radius;
configure(AABB(Vector3(-radius, -radius, -radius), Vector3(radius * 2.0, radius * 2.0, radius * 2.0)));
}
-void SphereShape3DSW::set_data(const Variant &p_data) {
+void GodotSphereShape3D::set_data(const Variant &p_data) {
_setup(p_data);
}
-Variant SphereShape3DSW::get_data() const {
+Variant GodotSphereShape3D::get_data() const {
return radius;
}
-SphereShape3DSW::SphereShape3DSW() {}
+GodotSphereShape3D::GodotSphereShape3D() {}
/********** BOX *************/
-void BoxShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const {
+void GodotBoxShape3D::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const {
// no matter the angle, the box is mirrored anyway
Vector3 local_normal = p_transform.basis.xform_inv(p_normal);
@@ -318,7 +318,7 @@ void BoxShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_t
r_max = distance + length;
}
-Vector3 BoxShape3DSW::get_support(const Vector3 &p_normal) const {
+Vector3 GodotBoxShape3D::get_support(const Vector3 &p_normal) const {
Vector3 point(
(p_normal.x < 0) ? -half_extents.x : half_extents.x,
(p_normal.y < 0) ? -half_extents.y : half_extents.y,
@@ -327,7 +327,7 @@ Vector3 BoxShape3DSW::get_support(const Vector3 &p_normal) const {
return point;
}
-void BoxShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const {
+void GodotBoxShape3D::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const {
static const int next[3] = { 1, 2, 0 };
static const int next2[3] = { 2, 0, 1 };
@@ -410,17 +410,17 @@ void BoxShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_s
r_supports[0] = point;
}
-bool BoxShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const {
+bool GodotBoxShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const {
AABB aabb(-half_extents, half_extents * 2.0);
return aabb.intersects_segment(p_begin, p_end, &r_result, &r_normal);
}
-bool BoxShape3DSW::intersect_point(const Vector3 &p_point) const {
+bool GodotBoxShape3D::intersect_point(const Vector3 &p_point) const {
return (Math::abs(p_point.x) < half_extents.x && Math::abs(p_point.y) < half_extents.y && Math::abs(p_point.z) < half_extents.z);
}
-Vector3 BoxShape3DSW::get_closest_point_to(const Vector3 &p_point) const {
+Vector3 GodotBoxShape3D::get_closest_point_to(const Vector3 &p_point) const {
int outside = 0;
Vector3 min_point;
@@ -430,7 +430,7 @@ Vector3 BoxShape3DSW::get_closest_point_to(const Vector3 &p_point) const {
if (outside == 1) {
//use plane if only one side matches
Vector3 n;
- n[i] = SGN(p_point[i]);
+ n[i] = SIGN(p_point[i]);
Plane p(n, half_extents[i]);
min_point = p.project(p_point);
@@ -470,7 +470,7 @@ Vector3 BoxShape3DSW::get_closest_point_to(const Vector3 &p_point) const {
return min_point;
}
-Vector3 BoxShape3DSW::get_moment_of_inertia(real_t p_mass) const {
+Vector3 GodotBoxShape3D::get_moment_of_inertia(real_t p_mass) const {
real_t lx = half_extents.x;
real_t ly = half_extents.y;
real_t lz = half_extents.z;
@@ -478,25 +478,25 @@ Vector3 BoxShape3DSW::get_moment_of_inertia(real_t p_mass) const {
return Vector3((p_mass / 3.0) * (ly * ly + lz * lz), (p_mass / 3.0) * (lx * lx + lz * lz), (p_mass / 3.0) * (lx * lx + ly * ly));
}
-void BoxShape3DSW::_setup(const Vector3 &p_half_extents) {
+void GodotBoxShape3D::_setup(const Vector3 &p_half_extents) {
half_extents = p_half_extents.abs();
configure(AABB(-half_extents, half_extents * 2));
}
-void BoxShape3DSW::set_data(const Variant &p_data) {
+void GodotBoxShape3D::set_data(const Variant &p_data) {
_setup(p_data);
}
-Variant BoxShape3DSW::get_data() const {
+Variant GodotBoxShape3D::get_data() const {
return half_extents;
}
-BoxShape3DSW::BoxShape3DSW() {}
+GodotBoxShape3D::GodotBoxShape3D() {}
/********** CAPSULE *************/
-void CapsuleShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const {
+void GodotCapsuleShape3D::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const {
Vector3 n = p_transform.basis.xform_inv(p_normal).normalized();
real_t h = height * 0.5 - radius;
@@ -507,7 +507,7 @@ void CapsuleShape3DSW::project_range(const Vector3 &p_normal, const Transform3D
r_min = p_normal.dot(p_transform.xform(-n));
}
-Vector3 CapsuleShape3DSW::get_support(const Vector3 &p_normal) const {
+Vector3 GodotCapsuleShape3D::get_support(const Vector3 &p_normal) const {
Vector3 n = p_normal;
real_t h = height * 0.5 - radius;
@@ -517,7 +517,7 @@ Vector3 CapsuleShape3DSW::get_support(const Vector3 &p_normal) const {
return n;
}
-void CapsuleShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const {
+void GodotCapsuleShape3D::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const {
Vector3 n = p_normal;
real_t d = n.y;
@@ -546,7 +546,7 @@ void CapsuleShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3
}
}
-bool CapsuleShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const {
+bool GodotCapsuleShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const {
Vector3 norm = (p_end - p_begin).normalized();
real_t min_d = 1e20;
@@ -602,7 +602,7 @@ bool CapsuleShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &
return collision;
}
-bool CapsuleShape3DSW::intersect_point(const Vector3 &p_point) const {
+bool GodotCapsuleShape3D::intersect_point(const Vector3 &p_point) const {
if (Math::abs(p_point.y) < height * 0.5 - radius) {
return Vector3(p_point.x, 0, p_point.z).length() < radius;
} else {
@@ -612,7 +612,7 @@ bool CapsuleShape3DSW::intersect_point(const Vector3 &p_point) const {
}
}
-Vector3 CapsuleShape3DSW::get_closest_point_to(const Vector3 &p_point) const {
+Vector3 GodotCapsuleShape3D::get_closest_point_to(const Vector3 &p_point) const {
Vector3 s[2] = {
Vector3(0, -height * 0.5 + radius, 0),
Vector3(0, height * 0.5 - radius, 0),
@@ -627,7 +627,7 @@ Vector3 CapsuleShape3DSW::get_closest_point_to(const Vector3 &p_point) const {
return p + (p_point - p).normalized() * radius;
}
-Vector3 CapsuleShape3DSW::get_moment_of_inertia(real_t p_mass) const {
+Vector3 GodotCapsuleShape3D::get_moment_of_inertia(real_t p_mass) const {
// use bad AABB approximation
Vector3 extents = get_aabb().size * 0.5;
@@ -637,31 +637,31 @@ Vector3 CapsuleShape3DSW::get_moment_of_inertia(real_t p_mass) const {
(p_mass / 3.0) * (extents.x * extents.x + extents.y * extents.y));
}
-void CapsuleShape3DSW::_setup(real_t p_height, real_t p_radius) {
+void GodotCapsuleShape3D::_setup(real_t p_height, real_t p_radius) {
height = p_height;
radius = p_radius;
configure(AABB(Vector3(-radius, -height * 0.5, -radius), Vector3(radius * 2, height, radius * 2)));
}
-void CapsuleShape3DSW::set_data(const Variant &p_data) {
+void GodotCapsuleShape3D::set_data(const Variant &p_data) {
Dictionary d = p_data;
ERR_FAIL_COND(!d.has("radius"));
ERR_FAIL_COND(!d.has("height"));
_setup(d["height"], d["radius"]);
}
-Variant CapsuleShape3DSW::get_data() const {
+Variant GodotCapsuleShape3D::get_data() const {
Dictionary d;
d["radius"] = radius;
d["height"] = height;
return d;
}
-CapsuleShape3DSW::CapsuleShape3DSW() {}
+GodotCapsuleShape3D::GodotCapsuleShape3D() {}
/********** CYLINDER *************/
-void CylinderShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const {
+void GodotCylinderShape3D::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const {
Vector3 cylinder_axis = p_transform.basis.get_axis(1).normalized();
real_t axis_dot = cylinder_axis.dot(p_normal);
@@ -683,7 +683,7 @@ void CylinderShape3DSW::project_range(const Vector3 &p_normal, const Transform3D
r_max = distance + length;
}
-Vector3 CylinderShape3DSW::get_support(const Vector3 &p_normal) const {
+Vector3 GodotCylinderShape3D::get_support(const Vector3 &p_normal) const {
Vector3 n = p_normal;
real_t h = (n.y > 0) ? height : -height;
real_t s = Math::sqrt(n.x * n.x + n.z * n.z);
@@ -701,7 +701,7 @@ Vector3 CylinderShape3DSW::get_support(const Vector3 &p_normal) const {
return n;
}
-void CylinderShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const {
+void GodotCylinderShape3D::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const {
real_t d = p_normal.y;
if (Math::abs(d) > _CYLINDER_FACE_IS_VALID_SUPPORT_THRESHOLD) {
real_t h = (d > 0) ? height : -height;
@@ -761,23 +761,23 @@ void CylinderShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3
}
}
-bool CylinderShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const {
+bool GodotCylinderShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const {
return Geometry3D::segment_intersects_cylinder(p_begin, p_end, height, radius, &r_result, &r_normal, 1);
}
-bool CylinderShape3DSW::intersect_point(const Vector3 &p_point) const {
+bool GodotCylinderShape3D::intersect_point(const Vector3 &p_point) const {
if (Math::abs(p_point.y) < height * 0.5) {
return Vector3(p_point.x, 0, p_point.z).length() < radius;
}
return false;
}
-Vector3 CylinderShape3DSW::get_closest_point_to(const Vector3 &p_point) const {
+Vector3 GodotCylinderShape3D::get_closest_point_to(const Vector3 &p_point) const {
if (Math::absf(p_point.y) > height * 0.5) {
// Project point to top disk.
real_t dir = p_point.y > 0.0 ? 1.0 : -1.0;
Vector3 circle_pos(0.0, dir * height * 0.5, 0.0);
- Plane circle_plane(circle_pos, Vector3(0.0, dir, 0.0));
+ Plane circle_plane(Vector3(0.0, dir, 0.0), circle_pos);
Vector3 proj_point = circle_plane.project(p_point);
// Clip position.
@@ -805,7 +805,7 @@ Vector3 CylinderShape3DSW::get_closest_point_to(const Vector3 &p_point) const {
}
}
-Vector3 CylinderShape3DSW::get_moment_of_inertia(real_t p_mass) const {
+Vector3 GodotCylinderShape3D::get_moment_of_inertia(real_t p_mass) const {
// use bad AABB approximation
Vector3 extents = get_aabb().size * 0.5;
@@ -815,31 +815,31 @@ Vector3 CylinderShape3DSW::get_moment_of_inertia(real_t p_mass) const {
(p_mass / 3.0) * (extents.x * extents.x + extents.y * extents.y));
}
-void CylinderShape3DSW::_setup(real_t p_height, real_t p_radius) {
+void GodotCylinderShape3D::_setup(real_t p_height, real_t p_radius) {
height = p_height;
radius = p_radius;
configure(AABB(Vector3(-radius, -height * 0.5, -radius), Vector3(radius * 2.0, height, radius * 2.0)));
}
-void CylinderShape3DSW::set_data(const Variant &p_data) {
+void GodotCylinderShape3D::set_data(const Variant &p_data) {
Dictionary d = p_data;
ERR_FAIL_COND(!d.has("radius"));
ERR_FAIL_COND(!d.has("height"));
_setup(d["height"], d["radius"]);
}
-Variant CylinderShape3DSW::get_data() const {
+Variant GodotCylinderShape3D::get_data() const {
Dictionary d;
d["radius"] = radius;
d["height"] = height;
return d;
}
-CylinderShape3DSW::CylinderShape3DSW() {}
+GodotCylinderShape3D::GodotCylinderShape3D() {}
/********** CONVEX POLYGON *************/
-void ConvexPolygonShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const {
+void GodotConvexPolygonShape3D::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const {
int vertex_count = mesh.vertices.size();
if (vertex_count == 0) {
return;
@@ -859,7 +859,7 @@ void ConvexPolygonShape3DSW::project_range(const Vector3 &p_normal, const Transf
}
}
-Vector3 ConvexPolygonShape3DSW::get_support(const Vector3 &p_normal) const {
+Vector3 GodotConvexPolygonShape3D::get_support(const Vector3 &p_normal) const {
Vector3 n = p_normal;
int vert_support_idx = -1;
@@ -884,7 +884,7 @@ Vector3 ConvexPolygonShape3DSW::get_support(const Vector3 &p_normal) const {
return vrts[vert_support_idx];
}
-void ConvexPolygonShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const {
+void GodotConvexPolygonShape3D::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const {
const Geometry3D::MeshData::Face *faces = mesh.faces.ptr();
int fc = mesh.faces.size();
@@ -954,7 +954,7 @@ void ConvexPolygonShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Ve
r_type = FEATURE_POINT;
}
-bool ConvexPolygonShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const {
+bool GodotConvexPolygonShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const {
const Geometry3D::MeshData::Face *faces = mesh.faces.ptr();
int fc = mesh.faces.size();
@@ -992,7 +992,7 @@ bool ConvexPolygonShape3DSW::intersect_segment(const Vector3 &p_begin, const Vec
return col;
}
-bool ConvexPolygonShape3DSW::intersect_point(const Vector3 &p_point) const {
+bool GodotConvexPolygonShape3D::intersect_point(const Vector3 &p_point) const {
const Geometry3D::MeshData::Face *faces = mesh.faces.ptr();
int fc = mesh.faces.size();
@@ -1005,7 +1005,7 @@ bool ConvexPolygonShape3DSW::intersect_point(const Vector3 &p_point) const {
return true;
}
-Vector3 ConvexPolygonShape3DSW::get_closest_point_to(const Vector3 &p_point) const {
+Vector3 GodotConvexPolygonShape3D::get_closest_point_to(const Vector3 &p_point) const {
const Geometry3D::MeshData::Face *faces = mesh.faces.ptr();
int fc = mesh.faces.size();
const Vector3 *vertices = mesh.vertices.ptr();
@@ -1025,7 +1025,7 @@ Vector3 ConvexPolygonShape3DSW::get_closest_point_to(const Vector3 &p_point) con
Vector3 a = vertices[indices[j]];
Vector3 b = vertices[indices[(j + 1) % ic]];
Vector3 n = (a - b).cross(faces[i].plane.normal).normalized();
- if (Plane(a, n).is_point_over(p_point)) {
+ if (Plane(n, a).is_point_over(p_point)) {
is_inside = false;
break;
}
@@ -1063,7 +1063,7 @@ Vector3 ConvexPolygonShape3DSW::get_closest_point_to(const Vector3 &p_point) con
return min_point;
}
-Vector3 ConvexPolygonShape3DSW::get_moment_of_inertia(real_t p_mass) const {
+Vector3 GodotConvexPolygonShape3D::get_moment_of_inertia(real_t p_mass) const {
// use bad AABB approximation
Vector3 extents = get_aabb().size * 0.5;
@@ -1073,7 +1073,7 @@ Vector3 ConvexPolygonShape3DSW::get_moment_of_inertia(real_t p_mass) const {
(p_mass / 3.0) * (extents.x * extents.x + extents.y * extents.y));
}
-void ConvexPolygonShape3DSW::_setup(const Vector<Vector3> &p_vertices) {
+void GodotConvexPolygonShape3D::_setup(const Vector<Vector3> &p_vertices) {
Error err = ConvexHullComputer::convex_hull(p_vertices, mesh);
if (err != OK) {
ERR_PRINT("Failed to build convex hull");
@@ -1092,20 +1092,20 @@ void ConvexPolygonShape3DSW::_setup(const Vector<Vector3> &p_vertices) {
configure(_aabb);
}
-void ConvexPolygonShape3DSW::set_data(const Variant &p_data) {
+void GodotConvexPolygonShape3D::set_data(const Variant &p_data) {
_setup(p_data);
}
-Variant ConvexPolygonShape3DSW::get_data() const {
+Variant GodotConvexPolygonShape3D::get_data() const {
return mesh.vertices;
}
-ConvexPolygonShape3DSW::ConvexPolygonShape3DSW() {
+GodotConvexPolygonShape3D::GodotConvexPolygonShape3D() {
}
/********** FACE POLYGON *************/
-void FaceShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const {
+void GodotFaceShape3D::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const {
for (int i = 0; i < 3; i++) {
Vector3 v = p_transform.xform(vertex[i]);
real_t d = p_normal.dot(v);
@@ -1120,7 +1120,7 @@ void FaceShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_
}
}
-Vector3 FaceShape3DSW::get_support(const Vector3 &p_normal) const {
+Vector3 GodotFaceShape3D::get_support(const Vector3 &p_normal) const {
int vert_support_idx = -1;
real_t support_max = 0;
@@ -1136,7 +1136,7 @@ Vector3 FaceShape3DSW::get_support(const Vector3 &p_normal) const {
return vertex[vert_support_idx];
}
-void FaceShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const {
+void GodotFaceShape3D::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const {
Vector3 n = p_normal;
/** TEST FACE AS SUPPORT **/
@@ -1188,12 +1188,12 @@ void FaceShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_
r_supports[0] = vertex[vert_support_idx];
}
-bool FaceShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const {
+bool GodotFaceShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const {
bool c = Geometry3D::segment_intersects_triangle(p_begin, p_end, vertex[0], vertex[1], vertex[2], &r_result);
if (c) {
r_normal = Plane(vertex[0], vertex[1], vertex[2]).normal;
if (r_normal.dot(p_end - p_begin) > 0) {
- if (backface_collision) {
+ if (backface_collision && p_hit_back_faces) {
r_normal = -r_normal;
} else {
c = false;
@@ -1204,23 +1204,23 @@ bool FaceShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_e
return c;
}
-bool FaceShape3DSW::intersect_point(const Vector3 &p_point) const {
+bool GodotFaceShape3D::intersect_point(const Vector3 &p_point) const {
return false; //face is flat
}
-Vector3 FaceShape3DSW::get_closest_point_to(const Vector3 &p_point) const {
+Vector3 GodotFaceShape3D::get_closest_point_to(const Vector3 &p_point) const {
return Face3(vertex[0], vertex[1], vertex[2]).get_closest_point_to(p_point);
}
-Vector3 FaceShape3DSW::get_moment_of_inertia(real_t p_mass) const {
+Vector3 GodotFaceShape3D::get_moment_of_inertia(real_t p_mass) const {
return Vector3(); // Sorry, but i don't think anyone cares, FaceShape!
}
-FaceShape3DSW::FaceShape3DSW() {
+GodotFaceShape3D::GodotFaceShape3D() {
configure(AABB());
}
-Vector<Vector3> ConcavePolygonShape3DSW::get_faces() const {
+Vector<Vector3> GodotConcavePolygonShape3D::get_faces() const {
Vector<Vector3> rfaces;
rfaces.resize(faces.size() * 3);
@@ -1235,7 +1235,7 @@ Vector<Vector3> ConcavePolygonShape3DSW::get_faces() const {
return rfaces;
}
-void ConcavePolygonShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const {
+void GodotConcavePolygonShape3D::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const {
int count = vertices.size();
if (count == 0) {
r_min = 0;
@@ -1256,7 +1256,7 @@ void ConcavePolygonShape3DSW::project_range(const Vector3 &p_normal, const Trans
}
}
-Vector3 ConcavePolygonShape3DSW::get_support(const Vector3 &p_normal) const {
+Vector3 GodotConcavePolygonShape3D::get_support(const Vector3 &p_normal) const {
int count = vertices.size();
if (count == 0) {
return Vector3();
@@ -1281,7 +1281,7 @@ Vector3 ConcavePolygonShape3DSW::get_support(const Vector3 &p_normal) const {
return vptr[vert_support_idx];
}
-void ConcavePolygonShape3DSW::_cull_segment(int p_idx, _SegmentCullParams *p_params) const {
+void GodotConcavePolygonShape3D::_cull_segment(int p_idx, _SegmentCullParams *p_params) const {
const BVH *bvh = &p_params->bvh[p_idx];
/*
@@ -1296,7 +1296,7 @@ void ConcavePolygonShape3DSW::_cull_segment(int p_idx, _SegmentCullParams *p_par
if (bvh->face_index >= 0) {
const Face *f = &p_params->faces[bvh->face_index];
- FaceShape3DSW *face = p_params->face;
+ GodotFaceShape3D *face = p_params->face;
face->normal = f->normal;
face->vertex[0] = p_params->vertices[f->indices[0]];
face->vertex[1] = p_params->vertices[f->indices[1]];
@@ -1304,7 +1304,7 @@ void ConcavePolygonShape3DSW::_cull_segment(int p_idx, _SegmentCullParams *p_par
Vector3 res;
Vector3 normal;
- if (face->intersect_segment(p_params->from, p_params->to, res, normal)) {
+ if (face->intersect_segment(p_params->from, p_params->to, res, normal, true)) {
real_t d = p_params->dir.dot(res) - p_params->dir.dot(p_params->from);
if ((d > 0) && (d < p_params->min_d)) {
p_params->min_d = d;
@@ -1323,7 +1323,7 @@ void ConcavePolygonShape3DSW::_cull_segment(int p_idx, _SegmentCullParams *p_par
}
}
-bool ConcavePolygonShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const {
+bool GodotConcavePolygonShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const {
if (faces.size() == 0) {
return false;
}
@@ -1333,8 +1333,8 @@ bool ConcavePolygonShape3DSW::intersect_segment(const Vector3 &p_begin, const Ve
const Vector3 *vr = vertices.ptr();
const BVH *br = bvh.ptr();
- FaceShape3DSW face;
- face.backface_collision = backface_collision;
+ GodotFaceShape3D face;
+ face.backface_collision = backface_collision && p_hit_back_faces;
_SegmentCullParams params;
params.from = p_begin;
@@ -1359,15 +1359,15 @@ bool ConcavePolygonShape3DSW::intersect_segment(const Vector3 &p_begin, const Ve
}
}
-bool ConcavePolygonShape3DSW::intersect_point(const Vector3 &p_point) const {
+bool GodotConcavePolygonShape3D::intersect_point(const Vector3 &p_point) const {
return false; //face is flat
}
-Vector3 ConcavePolygonShape3DSW::get_closest_point_to(const Vector3 &p_point) const {
+Vector3 GodotConcavePolygonShape3D::get_closest_point_to(const Vector3 &p_point) const {
return Vector3();
}
-bool ConcavePolygonShape3DSW::_cull(int p_idx, _CullParams *p_params) const {
+bool GodotConcavePolygonShape3D::_cull(int p_idx, _CullParams *p_params) const {
const BVH *bvh = &p_params->bvh[p_idx];
if (!p_params->aabb.intersects(bvh->aabb)) {
@@ -1376,7 +1376,7 @@ bool ConcavePolygonShape3DSW::_cull(int p_idx, _CullParams *p_params) const {
if (bvh->face_index >= 0) {
const Face *f = &p_params->faces[bvh->face_index];
- FaceShape3DSW *face = p_params->face;
+ GodotFaceShape3D *face = p_params->face;
face->normal = f->normal;
face->vertex[0] = p_params->vertices[f->indices[0]];
face->vertex[1] = p_params->vertices[f->indices[1]];
@@ -1401,7 +1401,7 @@ bool ConcavePolygonShape3DSW::_cull(int p_idx, _CullParams *p_params) const {
return false;
}
-void ConcavePolygonShape3DSW::cull(const AABB &p_local_aabb, QueryCallback p_callback, void *p_userdata) const {
+void GodotConcavePolygonShape3D::cull(const AABB &p_local_aabb, QueryCallback p_callback, void *p_userdata, bool p_invert_backface_collision) const {
// make matrix local to concave
if (faces.size() == 0) {
return;
@@ -1414,8 +1414,9 @@ void ConcavePolygonShape3DSW::cull(const AABB &p_local_aabb, QueryCallback p_cal
const Vector3 *vr = vertices.ptr();
const BVH *br = bvh.ptr();
- FaceShape3DSW face; // use this to send in the callback
+ GodotFaceShape3D face; // use this to send in the callback
face.backface_collision = backface_collision;
+ face.invert_backface_collision = p_invert_backface_collision;
_CullParams params;
params.aabb = local_aabb;
@@ -1430,7 +1431,7 @@ void ConcavePolygonShape3DSW::cull(const AABB &p_local_aabb, QueryCallback p_cal
_cull(0, &params);
}
-Vector3 ConcavePolygonShape3DSW::get_moment_of_inertia(real_t p_mass) const {
+Vector3 GodotConcavePolygonShape3D::get_moment_of_inertia(real_t p_mass) const {
// use bad AABB approximation
Vector3 extents = get_aabb().size * 0.5;
@@ -1440,40 +1441,40 @@ Vector3 ConcavePolygonShape3DSW::get_moment_of_inertia(real_t p_mass) const {
(p_mass / 3.0) * (extents.x * extents.x + extents.y * extents.y));
}
-struct _VolumeSW_BVH_Element {
+struct _Volume_BVH_Element {
AABB aabb;
Vector3 center;
int face_index;
};
-struct _VolumeSW_BVH_CompareX {
- _FORCE_INLINE_ bool operator()(const _VolumeSW_BVH_Element &a, const _VolumeSW_BVH_Element &b) const {
+struct _Volume_BVH_CompareX {
+ _FORCE_INLINE_ bool operator()(const _Volume_BVH_Element &a, const _Volume_BVH_Element &b) const {
return a.center.x < b.center.x;
}
};
-struct _VolumeSW_BVH_CompareY {
- _FORCE_INLINE_ bool operator()(const _VolumeSW_BVH_Element &a, const _VolumeSW_BVH_Element &b) const {
+struct _Volume_BVH_CompareY {
+ _FORCE_INLINE_ bool operator()(const _Volume_BVH_Element &a, const _Volume_BVH_Element &b) const {
return a.center.y < b.center.y;
}
};
-struct _VolumeSW_BVH_CompareZ {
- _FORCE_INLINE_ bool operator()(const _VolumeSW_BVH_Element &a, const _VolumeSW_BVH_Element &b) const {
+struct _Volume_BVH_CompareZ {
+ _FORCE_INLINE_ bool operator()(const _Volume_BVH_Element &a, const _Volume_BVH_Element &b) const {
return a.center.z < b.center.z;
}
};
-struct _VolumeSW_BVH {
+struct _Volume_BVH {
AABB aabb;
- _VolumeSW_BVH *left;
- _VolumeSW_BVH *right;
+ _Volume_BVH *left;
+ _Volume_BVH *right;
int face_index;
};
-_VolumeSW_BVH *_volume_sw_build_bvh(_VolumeSW_BVH_Element *p_elements, int p_size, int &count) {
- _VolumeSW_BVH *bvh = memnew(_VolumeSW_BVH);
+_Volume_BVH *_volume_build_bvh(_Volume_BVH_Element *p_elements, int p_size, int &count) {
+ _Volume_BVH *bvh = memnew(_Volume_BVH);
if (p_size == 1) {
//leaf
@@ -1498,30 +1499,30 @@ _VolumeSW_BVH *_volume_sw_build_bvh(_VolumeSW_BVH_Element *p_elements, int p_siz
bvh->aabb = aabb;
switch (aabb.get_longest_axis_index()) {
case 0: {
- SortArray<_VolumeSW_BVH_Element, _VolumeSW_BVH_CompareX> sort_x;
+ SortArray<_Volume_BVH_Element, _Volume_BVH_CompareX> sort_x;
sort_x.sort(p_elements, p_size);
} break;
case 1: {
- SortArray<_VolumeSW_BVH_Element, _VolumeSW_BVH_CompareY> sort_y;
+ SortArray<_Volume_BVH_Element, _Volume_BVH_CompareY> sort_y;
sort_y.sort(p_elements, p_size);
} break;
case 2: {
- SortArray<_VolumeSW_BVH_Element, _VolumeSW_BVH_CompareZ> sort_z;
+ SortArray<_Volume_BVH_Element, _Volume_BVH_CompareZ> sort_z;
sort_z.sort(p_elements, p_size);
} break;
}
int split = p_size / 2;
- bvh->left = _volume_sw_build_bvh(p_elements, split, count);
- bvh->right = _volume_sw_build_bvh(&p_elements[split], p_size - split, count);
+ bvh->left = _volume_build_bvh(p_elements, split, count);
+ bvh->right = _volume_build_bvh(&p_elements[split], p_size - split, count);
//printf("branch at %p - %i: %i\n",bvh,count,bvh->face_index);
count++;
return bvh;
}
-void ConcavePolygonShape3DSW::_fill_bvh(_VolumeSW_BVH *p_bvh_tree, BVH *p_bvh_array, int &p_idx) {
+void GodotConcavePolygonShape3D::_fill_bvh(_Volume_BVH *p_bvh_tree, BVH *p_bvh_array, int &p_idx) {
int idx = p_idx;
p_bvh_array[idx].aabb = p_bvh_tree->aabb;
@@ -1547,7 +1548,7 @@ void ConcavePolygonShape3DSW::_fill_bvh(_VolumeSW_BVH *p_bvh_tree, BVH *p_bvh_ar
memdelete(p_bvh_tree);
}
-void ConcavePolygonShape3DSW::_setup(const Vector<Vector3> &p_faces, bool p_backface_collision) {
+void GodotConcavePolygonShape3D::_setup(const Vector<Vector3> &p_faces, bool p_backface_collision) {
int src_face_count = p_faces.size();
if (src_face_count == 0) {
configure(AABB());
@@ -1558,10 +1559,10 @@ void ConcavePolygonShape3DSW::_setup(const Vector<Vector3> &p_faces, bool p_back
const Vector3 *facesr = p_faces.ptr();
- Vector<_VolumeSW_BVH_Element> bvh_array;
+ Vector<_Volume_BVH_Element> bvh_array;
bvh_array.resize(src_face_count);
- _VolumeSW_BVH_Element *bvh_arrayw = bvh_array.ptrw();
+ _Volume_BVH_Element *bvh_arrayw = bvh_array.ptrw();
faces.resize(src_face_count);
Face *facesw = faces.ptrw();
@@ -1593,7 +1594,7 @@ void ConcavePolygonShape3DSW::_setup(const Vector<Vector3> &p_faces, bool p_back
}
int count = 0;
- _VolumeSW_BVH *bvh_tree = _volume_sw_build_bvh(bvh_arrayw, src_face_count, count);
+ _Volume_BVH *bvh_tree = _volume_build_bvh(bvh_arrayw, src_face_count, count);
bvh.resize(count + 1);
@@ -1607,14 +1608,14 @@ void ConcavePolygonShape3DSW::_setup(const Vector<Vector3> &p_faces, bool p_back
configure(_aabb); // this type of shape has no margin
}
-void ConcavePolygonShape3DSW::set_data(const Variant &p_data) {
+void GodotConcavePolygonShape3D::set_data(const Variant &p_data) {
Dictionary d = p_data;
ERR_FAIL_COND(!d.has("faces"));
_setup(d["faces"], d["backface_collision"]);
}
-Variant ConcavePolygonShape3DSW::get_data() const {
+Variant GodotConcavePolygonShape3D::get_data() const {
Dictionary d;
d["faces"] = get_faces();
d["backface_collision"] = backface_collision;
@@ -1622,29 +1623,29 @@ Variant ConcavePolygonShape3DSW::get_data() const {
return d;
}
-ConcavePolygonShape3DSW::ConcavePolygonShape3DSW() {
+GodotConcavePolygonShape3D::GodotConcavePolygonShape3D() {
}
/* HEIGHT MAP SHAPE */
-Vector<real_t> HeightMapShape3DSW::get_heights() const {
+Vector<real_t> GodotHeightMapShape3D::get_heights() const {
return heights;
}
-int HeightMapShape3DSW::get_width() const {
+int GodotHeightMapShape3D::get_width() const {
return width;
}
-int HeightMapShape3DSW::get_depth() const {
+int GodotHeightMapShape3D::get_depth() const {
return depth;
}
-void HeightMapShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const {
+void GodotHeightMapShape3D::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const {
//not very useful, but not very used either
- p_transform.xform(get_aabb()).project_range_in_plane(Plane(p_normal, 0), r_min, r_max);
+ p_transform.xform(get_aabb()).project_range_in_plane(Plane(p_normal), r_min, r_max);
}
-Vector3 HeightMapShape3DSW::get_support(const Vector3 &p_normal) const {
+Vector3 GodotHeightMapShape3D::get_support(const Vector3 &p_normal) const {
//not very useful, but not very used either
return get_aabb().get_support(p_normal);
}
@@ -1657,8 +1658,8 @@ struct _HeightmapSegmentCullParams {
Vector3 result;
Vector3 normal;
- const HeightMapShape3DSW *heightmap = nullptr;
- FaceShape3DSW *face = nullptr;
+ const GodotHeightMapShape3D *heightmap = nullptr;
+ GodotFaceShape3D *face = nullptr;
};
struct _HeightmapGridCullState {
@@ -1675,7 +1676,7 @@ struct _HeightmapGridCullState {
_FORCE_INLINE_ bool _heightmap_face_cull_segment(_HeightmapSegmentCullParams &p_params) {
Vector3 res;
Vector3 normal;
- if (p_params.face->intersect_segment(p_params.from, p_params.to, res, normal)) {
+ if (p_params.face->intersect_segment(p_params.from, p_params.to, res, normal, true)) {
p_params.result = res;
p_params.normal = normal;
return true;
@@ -1706,7 +1707,7 @@ _FORCE_INLINE_ bool _heightmap_cell_cull_segment(_HeightmapSegmentCullParams &p_
}
_FORCE_INLINE_ bool _heightmap_chunk_cull_segment(_HeightmapSegmentCullParams &p_params, const _HeightmapGridCullState &p_state) {
- const HeightMapShape3DSW::Range &chunk = p_params.heightmap->_get_bounds_chunk(p_state.x, p_state.z);
+ const GodotHeightMapShape3D::Range &chunk = p_params.heightmap->_get_bounds_chunk(p_state.x, p_state.z);
Vector3 enter_pos;
Vector3 exit_pos;
@@ -1725,8 +1726,8 @@ _FORCE_INLINE_ bool _heightmap_chunk_cull_segment(_HeightmapSegmentCullParams &p
}
// Transform positions to heightmap space.
- enter_pos *= HeightMapShape3DSW::BOUNDS_CHUNK_SIZE;
- exit_pos *= HeightMapShape3DSW::BOUNDS_CHUNK_SIZE;
+ enter_pos *= GodotHeightMapShape3D::BOUNDS_CHUNK_SIZE;
+ exit_pos *= GodotHeightMapShape3D::BOUNDS_CHUNK_SIZE;
// We did enter the flat projection of the AABB,
// but we have to check if we intersect it on the vertical axis.
@@ -1741,7 +1742,7 @@ _FORCE_INLINE_ bool _heightmap_chunk_cull_segment(_HeightmapSegmentCullParams &p
}
template <typename ProcessFunction>
-bool HeightMapShape3DSW::_intersect_grid_segment(ProcessFunction &p_process, const Vector3 &p_begin, const Vector3 &p_end, int p_width, int p_depth, const Vector3 &offset, Vector3 &r_point, Vector3 &r_normal) const {
+bool GodotHeightMapShape3D::_intersect_grid_segment(ProcessFunction &p_process, const Vector3 &p_begin, const Vector3 &p_end, int p_width, int p_depth, const Vector3 &offset, Vector3 &r_point, Vector3 &r_normal) const {
Vector3 delta = (p_end - p_begin);
real_t length = delta.length();
@@ -1751,7 +1752,7 @@ bool HeightMapShape3DSW::_intersect_grid_segment(ProcessFunction &p_process, con
Vector3 local_begin = p_begin + offset;
- FaceShape3DSW face;
+ GodotFaceShape3D face;
face.backface_collision = false;
_HeightmapSegmentCullParams params;
@@ -1881,7 +1882,7 @@ bool HeightMapShape3DSW::_intersect_grid_segment(ProcessFunction &p_process, con
return false;
}
-bool HeightMapShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal) const {
+bool GodotHeightMapShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal, bool p_hit_back_faces) const {
if (heights.is_empty()) {
return false;
}
@@ -1898,8 +1899,8 @@ bool HeightMapShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3
if ((begin_x == end_x) && (begin_z == end_z)) {
// Simple case for rays that don't traverse the grid horizontally.
// Just perform a test on the given cell.
- FaceShape3DSW face;
- face.backface_collision = false;
+ GodotFaceShape3D face;
+ face.backface_collision = p_hit_back_faces;
_HeightmapSegmentCullParams params;
params.from = p_begin;
@@ -1938,15 +1939,15 @@ bool HeightMapShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3
return false;
}
-bool HeightMapShape3DSW::intersect_point(const Vector3 &p_point) const {
+bool GodotHeightMapShape3D::intersect_point(const Vector3 &p_point) const {
return false;
}
-Vector3 HeightMapShape3DSW::get_closest_point_to(const Vector3 &p_point) const {
+Vector3 GodotHeightMapShape3D::get_closest_point_to(const Vector3 &p_point) const {
return Vector3();
}
-void HeightMapShape3DSW::_get_cell(const Vector3 &p_point, int &r_x, int &r_y, int &r_z) const {
+void GodotHeightMapShape3D::_get_cell(const Vector3 &p_point, int &r_x, int &r_y, int &r_z) const {
const AABB &aabb = get_aabb();
Vector3 pos_local = aabb.position + local_origin;
@@ -1961,7 +1962,7 @@ void HeightMapShape3DSW::_get_cell(const Vector3 &p_point, int &r_x, int &r_y, i
r_z = (clamped_point.z < 0.0) ? (clamped_point.z - 0.5) : (clamped_point.z + 0.5);
}
-void HeightMapShape3DSW::cull(const AABB &p_local_aabb, QueryCallback p_callback, void *p_userdata) const {
+void GodotHeightMapShape3D::cull(const AABB &p_local_aabb, QueryCallback p_callback, void *p_userdata, bool p_invert_backface_collision) const {
if (heights.is_empty()) {
return;
}
@@ -1987,8 +1988,9 @@ void HeightMapShape3DSW::cull(const AABB &p_local_aabb, QueryCallback p_callback
int start_z = MAX(0, aabb_min[2]);
int end_z = MIN(depth - 1, aabb_max[2]);
- FaceShape3DSW face;
- face.backface_collision = true;
+ GodotFaceShape3D face;
+ face.backface_collision = !p_invert_backface_collision;
+ face.invert_backface_collision = p_invert_backface_collision;
for (int z = start_z; z < end_z; z++) {
for (int x = start_x; x < end_x; x++) {
@@ -2012,7 +2014,7 @@ void HeightMapShape3DSW::cull(const AABB &p_local_aabb, QueryCallback p_callback
}
}
-Vector3 HeightMapShape3DSW::get_moment_of_inertia(real_t p_mass) const {
+Vector3 GodotHeightMapShape3D::get_moment_of_inertia(real_t p_mass) const {
// use bad AABB approximation
Vector3 extents = get_aabb().size * 0.5;
@@ -2022,7 +2024,7 @@ Vector3 HeightMapShape3DSW::get_moment_of_inertia(real_t p_mass) const {
(p_mass / 3.0) * (extents.x * extents.x + extents.y * extents.y));
}
-void HeightMapShape3DSW::_build_accelerator() {
+void GodotHeightMapShape3D::_build_accelerator() {
bounds_grid.clear();
bounds_grid_width = width / BOUNDS_CHUNK_SIZE;
@@ -2091,7 +2093,7 @@ void HeightMapShape3DSW::_build_accelerator() {
}
}
-void HeightMapShape3DSW::_setup(const Vector<real_t> &p_heights, int p_width, int p_depth, real_t p_min_height, real_t p_max_height) {
+void GodotHeightMapShape3D::_setup(const Vector<real_t> &p_heights, int p_width, int p_depth, real_t p_min_height, real_t p_max_height) {
heights = p_heights;
width = p_width;
depth = p_depth;
@@ -2112,7 +2114,7 @@ void HeightMapShape3DSW::_setup(const Vector<real_t> &p_heights, int p_width, in
configure(aabb);
}
-void HeightMapShape3DSW::set_data(const Variant &p_data) {
+void GodotHeightMapShape3D::set_data(const Variant &p_data) {
ERR_FAIL_COND(p_data.get_type() != Variant::DICTIONARY);
Dictionary d = p_data;
@@ -2184,7 +2186,7 @@ void HeightMapShape3DSW::set_data(const Variant &p_data) {
_setup(heights_buffer, width, depth, min_height, max_height);
}
-Variant HeightMapShape3DSW::get_data() const {
+Variant GodotHeightMapShape3D::get_data() const {
Dictionary d;
d["width"] = width;
d["depth"] = depth;
@@ -2198,5 +2200,5 @@ Variant HeightMapShape3DSW::get_data() const {
return d;
}
-HeightMapShape3DSW::HeightMapShape3DSW() {
+GodotHeightMapShape3D::GodotHeightMapShape3D() {
}
diff --git a/servers/physics_3d/shape_3d_sw.h b/servers/physics_3d/godot_shape_3d.h
index 061d66a085..9d171c3928 100644
--- a/servers/physics_3d/shape_3d_sw.h
+++ b/servers/physics_3d/godot_shape_3d.h
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* shape_3d_sw.h */
+/* godot_shape_3d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,30 +28,30 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SHAPE_SW_H
-#define SHAPE_SW_H
+#ifndef GODOT_SHAPE_3D_H
+#define GODOT_SHAPE_3D_H
#include "core/math/geometry_3d.h"
#include "core/templates/local_vector.h"
#include "servers/physics_server_3d.h"
-class Shape3DSW;
+class GodotShape3D;
-class ShapeOwner3DSW {
+class GodotShapeOwner3D {
public:
virtual void _shape_changed() = 0;
- virtual void remove_shape(Shape3DSW *p_shape) = 0;
+ virtual void remove_shape(GodotShape3D *p_shape) = 0;
- virtual ~ShapeOwner3DSW() {}
+ virtual ~GodotShapeOwner3D() {}
};
-class Shape3DSW {
+class GodotShape3D {
RID self;
AABB aabb;
bool configured = false;
real_t custom_bias = 0.0;
- Map<ShapeOwner3DSW *, int> owners;
+ Map<GodotShapeOwner3D *, int> owners;
protected:
void configure(const AABB &p_aabb);
@@ -64,7 +64,7 @@ public:
FEATURE_CIRCLE,
};
- virtual real_t get_area() const { return aabb.get_area(); }
+ virtual real_t get_volume() const { return aabb.get_volume(); }
_FORCE_INLINE_ void set_self(const RID &p_self) { self = p_self; }
_FORCE_INLINE_ RID get_self() const { return self; }
@@ -80,7 +80,7 @@ public:
virtual Vector3 get_support(const Vector3 &p_normal) const;
virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const = 0;
virtual Vector3 get_closest_point_to(const Vector3 &p_point) const = 0;
- virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal) const = 0;
+ virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal, bool p_hit_back_faces) const = 0;
virtual bool intersect_point(const Vector3 &p_point) const = 0;
virtual Vector3 get_moment_of_inertia(real_t p_mass) const = 0;
@@ -90,29 +90,29 @@ public:
_FORCE_INLINE_ void set_custom_bias(real_t p_bias) { custom_bias = p_bias; }
_FORCE_INLINE_ real_t get_custom_bias() const { return custom_bias; }
- void add_owner(ShapeOwner3DSW *p_owner);
- void remove_owner(ShapeOwner3DSW *p_owner);
- bool is_owner(ShapeOwner3DSW *p_owner) const;
- const Map<ShapeOwner3DSW *, int> &get_owners() const;
+ void add_owner(GodotShapeOwner3D *p_owner);
+ void remove_owner(GodotShapeOwner3D *p_owner);
+ bool is_owner(GodotShapeOwner3D *p_owner) const;
+ const Map<GodotShapeOwner3D *, int> &get_owners() const;
- Shape3DSW() {}
- virtual ~Shape3DSW();
+ GodotShape3D() {}
+ virtual ~GodotShape3D();
};
-class ConcaveShape3DSW : public Shape3DSW {
+class GodotConcaveShape3D : public GodotShape3D {
public:
virtual bool is_concave() const override { return true; }
virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override { r_amount = 0; }
// Returns true to stop the query.
- typedef bool (*QueryCallback)(void *p_userdata, Shape3DSW *p_convex);
+ typedef bool (*QueryCallback)(void *p_userdata, GodotShape3D *p_convex);
- virtual void cull(const AABB &p_local_aabb, QueryCallback p_callback, void *p_userdata) const = 0;
+ virtual void cull(const AABB &p_local_aabb, QueryCallback p_callback, void *p_userdata, bool p_invert_backface_collision) const = 0;
- ConcaveShape3DSW() {}
+ GodotConcaveShape3D() {}
};
-class WorldBoundaryShape3DSW : public Shape3DSW {
+class GodotWorldBoundaryShape3D : public GodotShape3D {
Plane plane;
void _setup(const Plane &p_plane);
@@ -120,13 +120,13 @@ class WorldBoundaryShape3DSW : public Shape3DSW {
public:
Plane get_plane() const;
- virtual real_t get_area() const override { return INFINITY; }
+ virtual real_t get_volume() const override { return INFINITY; }
virtual PhysicsServer3D::ShapeType get_type() const override { return PhysicsServer3D::SHAPE_WORLD_BOUNDARY; }
virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override;
virtual Vector3 get_support(const Vector3 &p_normal) const override;
virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override { r_amount = 0; }
- virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override;
+ virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override;
virtual bool intersect_point(const Vector3 &p_point) const override;
virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override;
virtual Vector3 get_moment_of_inertia(real_t p_mass) const override;
@@ -134,10 +134,10 @@ public:
virtual void set_data(const Variant &p_data) override;
virtual Variant get_data() const override;
- WorldBoundaryShape3DSW();
+ GodotWorldBoundaryShape3D();
};
-class SeparationRayShape3DSW : public Shape3DSW {
+class GodotSeparationRayShape3D : public GodotShape3D {
real_t length = 1.0;
bool slide_on_slope = false;
@@ -147,13 +147,13 @@ public:
real_t get_length() const;
bool get_slide_on_slope() const;
- virtual real_t get_area() const override { return 0.0; }
+ virtual real_t get_volume() const override { return 0.0; }
virtual PhysicsServer3D::ShapeType get_type() const override { return PhysicsServer3D::SHAPE_SEPARATION_RAY; }
virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override;
virtual Vector3 get_support(const Vector3 &p_normal) const override;
virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override;
- virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override;
+ virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override;
virtual bool intersect_point(const Vector3 &p_point) const override;
virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override;
@@ -162,10 +162,10 @@ public:
virtual void set_data(const Variant &p_data) override;
virtual Variant get_data() const override;
- SeparationRayShape3DSW();
+ GodotSeparationRayShape3D();
};
-class SphereShape3DSW : public Shape3DSW {
+class GodotSphereShape3D : public GodotShape3D {
real_t radius = 0.0;
void _setup(real_t p_radius);
@@ -173,14 +173,14 @@ class SphereShape3DSW : public Shape3DSW {
public:
real_t get_radius() const;
- virtual real_t get_area() const override { return 4.0 / 3.0 * Math_PI * radius * radius * radius; }
+ virtual real_t get_volume() const override { return 4.0 / 3.0 * Math_PI * radius * radius * radius; }
virtual PhysicsServer3D::ShapeType get_type() const override { return PhysicsServer3D::SHAPE_SPHERE; }
virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override;
virtual Vector3 get_support(const Vector3 &p_normal) const override;
virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override;
- virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override;
+ virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override;
virtual bool intersect_point(const Vector3 &p_point) const override;
virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override;
@@ -189,23 +189,23 @@ public:
virtual void set_data(const Variant &p_data) override;
virtual Variant get_data() const override;
- SphereShape3DSW();
+ GodotSphereShape3D();
};
-class BoxShape3DSW : public Shape3DSW {
+class GodotBoxShape3D : public GodotShape3D {
Vector3 half_extents;
void _setup(const Vector3 &p_half_extents);
public:
_FORCE_INLINE_ Vector3 get_half_extents() const { return half_extents; }
- virtual real_t get_area() const override { return 8 * half_extents.x * half_extents.y * half_extents.z; }
+ virtual real_t get_volume() const override { return 8 * half_extents.x * half_extents.y * half_extents.z; }
virtual PhysicsServer3D::ShapeType get_type() const override { return PhysicsServer3D::SHAPE_BOX; }
virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override;
virtual Vector3 get_support(const Vector3 &p_normal) const override;
virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override;
- virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override;
+ virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override;
virtual bool intersect_point(const Vector3 &p_point) const override;
virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override;
@@ -214,10 +214,10 @@ public:
virtual void set_data(const Variant &p_data) override;
virtual Variant get_data() const override;
- BoxShape3DSW();
+ GodotBoxShape3D();
};
-class CapsuleShape3DSW : public Shape3DSW {
+class GodotCapsuleShape3D : public GodotShape3D {
real_t height = 0.0;
real_t radius = 0.0;
@@ -227,14 +227,14 @@ public:
_FORCE_INLINE_ real_t get_height() const { return height; }
_FORCE_INLINE_ real_t get_radius() const { return radius; }
- virtual real_t get_area() const override { return 4.0 / 3.0 * Math_PI * radius * radius * radius + (height - radius * 2.0) * Math_PI * radius * radius; }
+ virtual real_t get_volume() const override { return 4.0 / 3.0 * Math_PI * radius * radius * radius + (height - radius * 2.0) * Math_PI * radius * radius; }
virtual PhysicsServer3D::ShapeType get_type() const override { return PhysicsServer3D::SHAPE_CAPSULE; }
virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override;
virtual Vector3 get_support(const Vector3 &p_normal) const override;
virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override;
- virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override;
+ virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override;
virtual bool intersect_point(const Vector3 &p_point) const override;
virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override;
@@ -243,10 +243,10 @@ public:
virtual void set_data(const Variant &p_data) override;
virtual Variant get_data() const override;
- CapsuleShape3DSW();
+ GodotCapsuleShape3D();
};
-class CylinderShape3DSW : public Shape3DSW {
+class GodotCylinderShape3D : public GodotShape3D {
real_t height = 0.0;
real_t radius = 0.0;
@@ -256,14 +256,14 @@ public:
_FORCE_INLINE_ real_t get_height() const { return height; }
_FORCE_INLINE_ real_t get_radius() const { return radius; }
- virtual real_t get_area() const override { return 4.0 / 3.0 * Math_PI * radius * radius * radius + height * Math_PI * radius * radius; }
+ virtual real_t get_volume() const override { return height * Math_PI * radius * radius; }
virtual PhysicsServer3D::ShapeType get_type() const override { return PhysicsServer3D::SHAPE_CYLINDER; }
virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override;
virtual Vector3 get_support(const Vector3 &p_normal) const override;
virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override;
- virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override;
+ virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override;
virtual bool intersect_point(const Vector3 &p_point) const override;
virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override;
@@ -272,10 +272,10 @@ public:
virtual void set_data(const Variant &p_data) override;
virtual Variant get_data() const override;
- CylinderShape3DSW();
+ GodotCylinderShape3D();
};
-struct ConvexPolygonShape3DSW : public Shape3DSW {
+struct GodotConvexPolygonShape3D : public GodotShape3D {
Geometry3D::MeshData mesh;
void _setup(const Vector<Vector3> &p_vertices);
@@ -288,7 +288,7 @@ public:
virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override;
virtual Vector3 get_support(const Vector3 &p_normal) const override;
virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override;
- virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override;
+ virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override;
virtual bool intersect_point(const Vector3 &p_point) const override;
virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override;
@@ -297,13 +297,13 @@ public:
virtual void set_data(const Variant &p_data) override;
virtual Variant get_data() const override;
- ConvexPolygonShape3DSW();
+ GodotConvexPolygonShape3D();
};
-struct _VolumeSW_BVH;
-struct FaceShape3DSW;
+struct _Volume_BVH;
+struct GodotFaceShape3D;
-struct ConcavePolygonShape3DSW : public ConcaveShape3DSW {
+struct GodotConcavePolygonShape3D : public GodotConcaveShape3D {
// always a trimesh
struct Face {
@@ -331,7 +331,7 @@ struct ConcavePolygonShape3DSW : public ConcaveShape3DSW {
const Face *faces = nullptr;
const Vector3 *vertices = nullptr;
const BVH *bvh = nullptr;
- FaceShape3DSW *face = nullptr;
+ GodotFaceShape3D *face = nullptr;
};
struct _SegmentCullParams {
@@ -341,7 +341,7 @@ struct ConcavePolygonShape3DSW : public ConcaveShape3DSW {
const Face *faces = nullptr;
const Vector3 *vertices = nullptr;
const BVH *bvh = nullptr;
- FaceShape3DSW *face = nullptr;
+ GodotFaceShape3D *face = nullptr;
Vector3 result;
Vector3 normal;
@@ -354,7 +354,7 @@ struct ConcavePolygonShape3DSW : public ConcaveShape3DSW {
void _cull_segment(int p_idx, _SegmentCullParams *p_params) const;
bool _cull(int p_idx, _CullParams *p_params) const;
- void _fill_bvh(_VolumeSW_BVH *p_bvh_tree, BVH *p_bvh_array, int &p_idx);
+ void _fill_bvh(_Volume_BVH *p_bvh_tree, BVH *p_bvh_array, int &p_idx);
void _setup(const Vector<Vector3> &p_faces, bool p_backface_collision);
@@ -366,21 +366,21 @@ public:
virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override;
virtual Vector3 get_support(const Vector3 &p_normal) const override;
- virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override;
+ virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override;
virtual bool intersect_point(const Vector3 &p_point) const override;
virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override;
- virtual void cull(const AABB &p_local_aabb, QueryCallback p_callback, void *p_userdata) const override;
+ virtual void cull(const AABB &p_local_aabb, QueryCallback p_callback, void *p_userdata, bool p_invert_backface_collision) const override;
virtual Vector3 get_moment_of_inertia(real_t p_mass) const override;
virtual void set_data(const Variant &p_data) override;
virtual Variant get_data() const override;
- ConcavePolygonShape3DSW();
+ GodotConcavePolygonShape3D();
};
-struct HeightMapShape3DSW : public ConcaveShape3DSW {
+struct GodotHeightMapShape3D : public GodotConcaveShape3D {
Vector<real_t> heights;
int width = 0;
int depth = 0;
@@ -429,25 +429,26 @@ public:
virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override;
virtual Vector3 get_support(const Vector3 &p_normal) const override;
- virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal) const override;
+ virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal, bool p_hit_back_faces) const override;
virtual bool intersect_point(const Vector3 &p_point) const override;
virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override;
- virtual void cull(const AABB &p_local_aabb, QueryCallback p_callback, void *p_userdata) const override;
+ virtual void cull(const AABB &p_local_aabb, QueryCallback p_callback, void *p_userdata, bool p_invert_backface_collision) const override;
virtual Vector3 get_moment_of_inertia(real_t p_mass) const override;
virtual void set_data(const Variant &p_data) override;
virtual Variant get_data() const override;
- HeightMapShape3DSW();
+ GodotHeightMapShape3D();
};
//used internally
-struct FaceShape3DSW : public Shape3DSW {
+struct GodotFaceShape3D : public GodotShape3D {
Vector3 normal; //cache
Vector3 vertex[3];
bool backface_collision = false;
+ bool invert_backface_collision = false;
virtual PhysicsServer3D::ShapeType get_type() const override { return PhysicsServer3D::SHAPE_CONCAVE_POLYGON; }
@@ -456,7 +457,7 @@ struct FaceShape3DSW : public Shape3DSW {
virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override;
virtual Vector3 get_support(const Vector3 &p_normal) const override;
virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override;
- virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override;
+ virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override;
virtual bool intersect_point(const Vector3 &p_point) const override;
virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override;
@@ -465,11 +466,11 @@ struct FaceShape3DSW : public Shape3DSW {
virtual void set_data(const Variant &p_data) override {}
virtual Variant get_data() const override { return Variant(); }
- FaceShape3DSW();
+ GodotFaceShape3D();
};
-struct MotionShape3DSW : public Shape3DSW {
- Shape3DSW *shape = nullptr;
+struct GodotMotionShape3D : public GodotShape3D {
+ GodotShape3D *shape = nullptr;
Vector3 motion;
virtual PhysicsServer3D::ShapeType get_type() const override { return PhysicsServer3D::SHAPE_CONVEX_POLYGON; }
@@ -495,7 +496,7 @@ struct MotionShape3DSW : public Shape3DSW {
}
virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override { r_amount = 0; }
- virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override { return false; }
+ virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override { return false; }
virtual bool intersect_point(const Vector3 &p_point) const override { return false; }
virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override { return p_point; }
@@ -504,7 +505,7 @@ struct MotionShape3DSW : public Shape3DSW {
virtual void set_data(const Variant &p_data) override {}
virtual Variant get_data() const override { return Variant(); }
- MotionShape3DSW() { configure(AABB()); }
+ GodotMotionShape3D() { configure(AABB()); }
};
-#endif // SHAPE_SW_H
+#endif // GODOT_SHAPE_3D_H
diff --git a/servers/physics_3d/soft_body_3d_sw.cpp b/servers/physics_3d/godot_soft_body_3d.cpp
index c9166810fe..1de27760d5 100644
--- a/servers/physics_3d/soft_body_3d_sw.cpp
+++ b/servers/physics_3d/godot_soft_body_3d.cpp
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* soft_body_3d_sw.cpp */
+/* godot_soft_body_3d.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,8 +28,9 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "soft_body_3d_sw.h"
-#include "space_3d_sw.h"
+#include "godot_soft_body_3d.h"
+
+#include "godot_space_3d.h"
#include "core/math/geometry_3d.h"
#include "core/templates/map.h"
@@ -53,16 +54,16 @@ subject to the following restrictions:
*/
///btSoftBody implementation by Nathanael Presson
-SoftBody3DSW::SoftBody3DSW() :
- CollisionObject3DSW(TYPE_SOFT_BODY),
+GodotSoftBody3D::GodotSoftBody3D() :
+ GodotCollisionObject3D(TYPE_SOFT_BODY),
active_list(this) {
_set_static(false);
}
-void SoftBody3DSW::_shapes_changed() {
+void GodotSoftBody3D::_shapes_changed() {
}
-void SoftBody3DSW::set_state(PhysicsServer3D::BodyState p_state, const Variant &p_variant) {
+void GodotSoftBody3D::set_state(PhysicsServer3D::BodyState p_state, const Variant &p_variant) {
switch (p_state) {
case PhysicsServer3D::BODY_STATE_TRANSFORM: {
_set_transform(p_variant);
@@ -87,7 +88,7 @@ void SoftBody3DSW::set_state(PhysicsServer3D::BodyState p_state, const Variant &
}
}
-Variant SoftBody3DSW::get_state(PhysicsServer3D::BodyState p_state) const {
+Variant GodotSoftBody3D::get_state(PhysicsServer3D::BodyState p_state) const {
switch (p_state) {
case PhysicsServer3D::BODY_STATE_TRANSFORM: {
return get_transform();
@@ -110,7 +111,7 @@ Variant SoftBody3DSW::get_state(PhysicsServer3D::BodyState p_state) const {
return Variant();
}
-void SoftBody3DSW::set_space(Space3DSW *p_space) {
+void GodotSoftBody3D::set_space(GodotSpace3D *p_space) {
if (get_space()) {
get_space()->soft_body_remove_from_active_list(&active_list);
@@ -128,7 +129,7 @@ void SoftBody3DSW::set_space(Space3DSW *p_space) {
}
}
-void SoftBody3DSW::set_mesh(RID p_mesh) {
+void GodotSoftBody3D::set_mesh(RID p_mesh) {
destroy();
soft_mesh = p_mesh;
@@ -138,6 +139,7 @@ void SoftBody3DSW::set_mesh(RID p_mesh) {
}
Array arrays = RenderingServer::get_singleton()->mesh_surface_get_arrays(soft_mesh, 0);
+ ERR_FAIL_COND(arrays.is_empty());
bool success = create_from_trimesh(arrays[RenderingServer::ARRAY_INDEX], arrays[RenderingServer::ARRAY_VERTEX]);
if (!success) {
@@ -145,7 +147,7 @@ void SoftBody3DSW::set_mesh(RID p_mesh) {
}
}
-void SoftBody3DSW::update_rendering_server(RenderingServerHandler *p_rendering_server_handler) {
+void GodotSoftBody3D::update_rendering_server(RenderingServerHandler *p_rendering_server_handler) {
if (soft_mesh.is_null()) {
return;
}
@@ -164,7 +166,7 @@ void SoftBody3DSW::update_rendering_server(RenderingServerHandler *p_rendering_s
p_rendering_server_handler->set_aabb(bounds);
}
-void SoftBody3DSW::update_normals_and_centroids() {
+void GodotSoftBody3D::update_normals_and_centroids() {
uint32_t i, ni;
for (i = 0, ni = nodes.size(); i < ni; ++i) {
@@ -191,7 +193,7 @@ void SoftBody3DSW::update_normals_and_centroids() {
}
}
-void SoftBody3DSW::update_bounds() {
+void GodotSoftBody3D::update_bounds() {
AABB prev_bounds = bounds;
prev_bounds.grow_by(collision_margin);
@@ -223,13 +225,13 @@ void SoftBody3DSW::update_bounds() {
}
}
-void SoftBody3DSW::update_constants() {
+void GodotSoftBody3D::update_constants() {
reset_link_rest_lengths();
update_link_constants();
update_area();
}
-void SoftBody3DSW::update_area() {
+void GodotSoftBody3D::update_area() {
int i, ni;
// Face area.
@@ -275,7 +277,7 @@ void SoftBody3DSW::update_area() {
}
}
-void SoftBody3DSW::reset_link_rest_lengths() {
+void GodotSoftBody3D::reset_link_rest_lengths() {
for (uint32_t i = 0, ni = links.size(); i < ni; ++i) {
Link &link = links[i];
link.rl = (link.n[0]->x - link.n[1]->x).length();
@@ -283,7 +285,7 @@ void SoftBody3DSW::reset_link_rest_lengths() {
}
}
-void SoftBody3DSW::update_link_constants() {
+void GodotSoftBody3D::update_link_constants() {
real_t inv_linear_stiffness = 1.0 / linear_stiffness;
for (uint32_t i = 0, ni = links.size(); i < ni; ++i) {
Link &link = links[i];
@@ -291,7 +293,7 @@ void SoftBody3DSW::update_link_constants() {
}
}
-void SoftBody3DSW::apply_nodes_transform(const Transform3D &p_transform) {
+void GodotSoftBody3D::apply_nodes_transform(const Transform3D &p_transform) {
if (soft_mesh.is_null()) {
return;
}
@@ -317,7 +319,7 @@ void SoftBody3DSW::apply_nodes_transform(const Transform3D &p_transform) {
update_constants();
}
-Vector3 SoftBody3DSW::get_vertex_position(int p_index) const {
+Vector3 GodotSoftBody3D::get_vertex_position(int p_index) const {
ERR_FAIL_COND_V(p_index < 0, Vector3());
if (soft_mesh.is_null()) {
@@ -331,7 +333,7 @@ Vector3 SoftBody3DSW::get_vertex_position(int p_index) const {
return nodes[node_index].x;
}
-void SoftBody3DSW::set_vertex_position(int p_index, const Vector3 &p_position) {
+void GodotSoftBody3D::set_vertex_position(int p_index, const Vector3 &p_position) {
ERR_FAIL_COND(p_index < 0);
if (soft_mesh.is_null()) {
@@ -347,7 +349,7 @@ void SoftBody3DSW::set_vertex_position(int p_index, const Vector3 &p_position) {
node.x = p_position;
}
-void SoftBody3DSW::pin_vertex(int p_index) {
+void GodotSoftBody3D::pin_vertex(int p_index) {
ERR_FAIL_COND(p_index < 0);
if (is_vertex_pinned(p_index)) {
@@ -366,13 +368,13 @@ void SoftBody3DSW::pin_vertex(int p_index) {
}
}
-void SoftBody3DSW::unpin_vertex(int p_index) {
+void GodotSoftBody3D::unpin_vertex(int p_index) {
ERR_FAIL_COND(p_index < 0);
uint32_t pinned_count = pinned_vertices.size();
for (uint32_t i = 0; i < pinned_count; ++i) {
if (p_index == pinned_vertices[i]) {
- pinned_vertices.remove(i);
+ pinned_vertices.remove_at(i);
if (!soft_mesh.is_null()) {
ERR_FAIL_COND(p_index >= (int)map_visual_to_physics.size());
@@ -390,7 +392,7 @@ void SoftBody3DSW::unpin_vertex(int p_index) {
}
}
-void SoftBody3DSW::unpin_all_vertices() {
+void GodotSoftBody3D::unpin_all_vertices() {
if (!soft_mesh.is_null()) {
real_t inv_node_mass = nodes.size() * inv_total_mass;
uint32_t pinned_count = pinned_vertices.size();
@@ -409,7 +411,7 @@ void SoftBody3DSW::unpin_all_vertices() {
pinned_vertices.clear();
}
-bool SoftBody3DSW::is_vertex_pinned(int p_index) const {
+bool GodotSoftBody3D::is_vertex_pinned(int p_index) const {
ERR_FAIL_COND_V(p_index < 0, false);
uint32_t pinned_count = pinned_vertices.size();
@@ -422,47 +424,47 @@ bool SoftBody3DSW::is_vertex_pinned(int p_index) const {
return false;
}
-uint32_t SoftBody3DSW::get_node_count() const {
+uint32_t GodotSoftBody3D::get_node_count() const {
return nodes.size();
}
-real_t SoftBody3DSW::get_node_inv_mass(uint32_t p_node_index) const {
+real_t GodotSoftBody3D::get_node_inv_mass(uint32_t p_node_index) const {
ERR_FAIL_COND_V(p_node_index >= nodes.size(), 0.0);
return nodes[p_node_index].im;
}
-Vector3 SoftBody3DSW::get_node_position(uint32_t p_node_index) const {
+Vector3 GodotSoftBody3D::get_node_position(uint32_t p_node_index) const {
ERR_FAIL_COND_V(p_node_index >= nodes.size(), Vector3());
return nodes[p_node_index].x;
}
-Vector3 SoftBody3DSW::get_node_velocity(uint32_t p_node_index) const {
+Vector3 GodotSoftBody3D::get_node_velocity(uint32_t p_node_index) const {
ERR_FAIL_COND_V(p_node_index >= nodes.size(), Vector3());
return nodes[p_node_index].v;
}
-Vector3 SoftBody3DSW::get_node_biased_velocity(uint32_t p_node_index) const {
+Vector3 GodotSoftBody3D::get_node_biased_velocity(uint32_t p_node_index) const {
ERR_FAIL_COND_V(p_node_index >= nodes.size(), Vector3());
return nodes[p_node_index].bv;
}
-void SoftBody3DSW::apply_node_impulse(uint32_t p_node_index, const Vector3 &p_impulse) {
+void GodotSoftBody3D::apply_node_impulse(uint32_t p_node_index, const Vector3 &p_impulse) {
ERR_FAIL_COND(p_node_index >= nodes.size());
Node &node = nodes[p_node_index];
node.v += p_impulse * node.im;
}
-void SoftBody3DSW::apply_node_bias_impulse(uint32_t p_node_index, const Vector3 &p_impulse) {
+void GodotSoftBody3D::apply_node_bias_impulse(uint32_t p_node_index, const Vector3 &p_impulse) {
ERR_FAIL_COND(p_node_index >= nodes.size());
Node &node = nodes[p_node_index];
node.bv += p_impulse * node.im;
}
-uint32_t SoftBody3DSW::get_face_count() const {
+uint32_t GodotSoftBody3D::get_face_count() const {
return faces.size();
}
-void SoftBody3DSW::get_face_points(uint32_t p_face_index, Vector3 &r_point_1, Vector3 &r_point_2, Vector3 &r_point_3) const {
+void GodotSoftBody3D::get_face_points(uint32_t p_face_index, Vector3 &r_point_1, Vector3 &r_point_2, Vector3 &r_point_3) const {
ERR_FAIL_COND(p_face_index >= faces.size());
const Face &face = faces[p_face_index];
r_point_1 = face.n[0]->x;
@@ -470,12 +472,12 @@ void SoftBody3DSW::get_face_points(uint32_t p_face_index, Vector3 &r_point_1, Ve
r_point_3 = face.n[2]->x;
}
-Vector3 SoftBody3DSW::get_face_normal(uint32_t p_face_index) const {
+Vector3 GodotSoftBody3D::get_face_normal(uint32_t p_face_index) const {
ERR_FAIL_COND_V(p_face_index >= faces.size(), Vector3());
return faces[p_face_index].normal;
}
-bool SoftBody3DSW::create_from_trimesh(const Vector<int> &p_indices, const Vector<Vector3> &p_vertices) {
+bool GodotSoftBody3D::create_from_trimesh(const Vector<int> &p_indices, const Vector<Vector3> &p_vertices) {
ERR_FAIL_COND_V(p_indices.is_empty(), false);
ERR_FAIL_COND_V(p_vertices.is_empty(), false);
@@ -595,7 +597,7 @@ bool SoftBody3DSW::create_from_trimesh(const Vector<int> &p_indices, const Vecto
return true;
}
-void SoftBody3DSW::generate_bending_constraints(int p_distance) {
+void GodotSoftBody3D::generate_bending_constraints(int p_distance) {
uint32_t i, j;
if (p_distance > 1) {
@@ -708,13 +710,15 @@ void SoftBody3DSW::generate_bending_constraints(int p_distance) {
// A small structure to track lists of dependent link calculations.
class LinkDeps {
public:
- int value; // A link calculation that is dependent on this one
- // Positive values = "input A" while negative values = "input B"
- LinkDeps *next; // Next dependence in the list
+ // A link calculation that is dependent on this one.
+ // Positive values = "input A" while negative values = "input B".
+ int value;
+ // Next dependence in the list.
+ LinkDeps *next;
};
typedef LinkDeps *LinkDepsPtr;
-void SoftBody3DSW::reoptimize_link_order() {
+void GodotSoftBody3D::reoptimize_link_order() {
const int reop_not_dependent = -1;
const int reop_node_complete = -2;
@@ -823,7 +827,7 @@ void SoftBody3DSW::reoptimize_link_order() {
memdelete_arr(link_buffer);
}
-void SoftBody3DSW::append_link(uint32_t p_node1, uint32_t p_node2) {
+void GodotSoftBody3D::append_link(uint32_t p_node1, uint32_t p_node2) {
if (p_node1 == p_node2) {
return;
}
@@ -839,7 +843,7 @@ void SoftBody3DSW::append_link(uint32_t p_node1, uint32_t p_node2) {
links.push_back(link);
}
-void SoftBody3DSW::append_face(uint32_t p_node1, uint32_t p_node2, uint32_t p_node3) {
+void GodotSoftBody3D::append_face(uint32_t p_node1, uint32_t p_node2, uint32_t p_node3) {
if (p_node1 == p_node2) {
return;
}
@@ -864,11 +868,11 @@ void SoftBody3DSW::append_face(uint32_t p_node1, uint32_t p_node2, uint32_t p_no
faces.push_back(face);
}
-void SoftBody3DSW::set_iteration_count(int p_val) {
+void GodotSoftBody3D::set_iteration_count(int p_val) {
iteration_count = p_val;
}
-void SoftBody3DSW::set_total_mass(real_t p_val) {
+void GodotSoftBody3D::set_total_mass(real_t p_val) {
ERR_FAIL_COND(p_val < 0.0);
inv_total_mass = 1.0 / p_val;
@@ -884,27 +888,27 @@ void SoftBody3DSW::set_total_mass(real_t p_val) {
update_constants();
}
-void SoftBody3DSW::set_collision_margin(real_t p_val) {
+void GodotSoftBody3D::set_collision_margin(real_t p_val) {
collision_margin = p_val;
}
-void SoftBody3DSW::set_linear_stiffness(real_t p_val) {
+void GodotSoftBody3D::set_linear_stiffness(real_t p_val) {
linear_stiffness = p_val;
}
-void SoftBody3DSW::set_pressure_coefficient(real_t p_val) {
+void GodotSoftBody3D::set_pressure_coefficient(real_t p_val) {
pressure_coefficient = p_val;
}
-void SoftBody3DSW::set_damping_coefficient(real_t p_val) {
+void GodotSoftBody3D::set_damping_coefficient(real_t p_val) {
damping_coefficient = p_val;
}
-void SoftBody3DSW::set_drag_coefficient(real_t p_val) {
+void GodotSoftBody3D::set_drag_coefficient(real_t p_val) {
drag_coefficient = p_val;
}
-void SoftBody3DSW::add_velocity(const Vector3 &p_velocity) {
+void GodotSoftBody3D::add_velocity(const Vector3 &p_velocity) {
for (uint32_t i = 0, ni = nodes.size(); i < ni; ++i) {
Node &node = nodes[i];
if (node.im > 0) {
@@ -913,9 +917,7 @@ void SoftBody3DSW::add_velocity(const Vector3 &p_velocity) {
}
}
-void SoftBody3DSW::apply_forces(bool p_has_wind_forces) {
- int ac = areas.size();
-
+void GodotSoftBody3D::apply_forces(const LocalVector<GodotArea3D *> &p_wind_areas) {
if (nodes.is_empty()) {
return;
}
@@ -928,7 +930,6 @@ void SoftBody3DSW::apply_forces(bool p_has_wind_forces) {
// Iterate over faces (try not to iterate elsewhere if possible).
for (i = 0, ni = faces.size(); i < ni; ++i) {
- bool stopped = false;
const Face &face = faces[i];
Vector3 wind_force(0, 0, 0);
@@ -937,24 +938,10 @@ void SoftBody3DSW::apply_forces(bool p_has_wind_forces) {
volume += vec3_dot(face.n[0]->x - org, vec3_cross(face.n[1]->x - org, face.n[2]->x - org));
// Compute nodal forces from area winds.
- if (ac && p_has_wind_forces) {
- const AreaCMP *aa = &areas[0];
- for (j = ac - 1; j >= 0 && !stopped; j--) {
- PhysicsServer3D::AreaSpaceOverrideMode mode = aa[j].area->get_space_override_mode();
- switch (mode) {
- case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE:
- case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: {
- wind_force += _compute_area_windforce(aa[j].area, &face);
- stopped = mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE;
- } break;
- case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE:
- case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: {
- wind_force = _compute_area_windforce(aa[j].area, &face);
- stopped = mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE;
- } break;
- default: {
- }
- }
+ int wind_area_count = p_wind_areas.size();
+ if (wind_area_count > 0) {
+ for (j = 0; j < wind_area_count; j++) {
+ wind_force += _compute_area_windforce(p_wind_areas[j], &face);
}
for (j = 0; j < 3; j++) {
@@ -977,13 +964,7 @@ void SoftBody3DSW::apply_forces(bool p_has_wind_forces) {
}
}
-void SoftBody3DSW::_compute_area_gravity(const Area3DSW *p_area) {
- Vector3 area_gravity;
- p_area->compute_gravity(get_transform().get_origin(), area_gravity);
- gravity += area_gravity;
-}
-
-Vector3 SoftBody3DSW::_compute_area_windforce(const Area3DSW *p_area, const Face *p_face) {
+Vector3 GodotSoftBody3D::_compute_area_windforce(const GodotArea3D *p_area, const Face *p_face) {
real_t wfm = p_area->get_wind_force_magnitude();
real_t waf = p_area->get_wind_attenuation_factor();
const Vector3 &wd = p_area->get_wind_direction();
@@ -995,49 +976,64 @@ Vector3 SoftBody3DSW::_compute_area_windforce(const Area3DSW *p_area, const Face
return nodal_force_magnitude * p_face->normal;
}
-void SoftBody3DSW::predict_motion(real_t p_delta) {
+void GodotSoftBody3D::predict_motion(real_t p_delta) {
const real_t inv_delta = 1.0 / p_delta;
ERR_FAIL_COND(!get_space());
- Area3DSW *def_area = get_space()->get_default_area();
- ERR_FAIL_COND(!def_area);
- gravity = def_area->get_gravity_vector() * def_area->get_gravity();
+ bool gravity_done = false;
+ Vector3 gravity;
- int ac = areas.size();
- bool stopped = false;
- bool has_wind_forces = false;
+ LocalVector<GodotArea3D *> wind_areas;
+ int ac = areas.size();
if (ac) {
areas.sort();
const AreaCMP *aa = &areas[0];
- for (int i = ac - 1; i >= 0 && !stopped; i--) {
- // Avoids unnecessary loop in apply_forces().
- has_wind_forces = has_wind_forces || aa[i].area->get_wind_force_magnitude() > CMP_EPSILON;
-
- PhysicsServer3D::AreaSpaceOverrideMode mode = aa[i].area->get_space_override_mode();
- switch (mode) {
- case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE:
- case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: {
- _compute_area_gravity(aa[i].area);
- stopped = mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE;
- } break;
- case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE:
- case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: {
- gravity = Vector3(0, 0, 0);
- _compute_area_gravity(aa[i].area);
- stopped = mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE;
- } break;
- default: {
+ for (int i = ac - 1; i >= 0; i--) {
+ if (!gravity_done) {
+ PhysicsServer3D::AreaSpaceOverrideMode area_gravity_mode = (PhysicsServer3D::AreaSpaceOverrideMode)(int)aa[i].area->get_param(PhysicsServer3D::AREA_PARAM_GRAVITY_OVERRIDE_MODE);
+ if (area_gravity_mode != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) {
+ Vector3 area_gravity;
+ aa[i].area->compute_gravity(get_transform().get_origin(), area_gravity);
+ switch (area_gravity_mode) {
+ case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE:
+ case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: {
+ gravity += area_gravity;
+ gravity_done = area_gravity_mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE;
+ } break;
+ case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE:
+ case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: {
+ gravity = Vector3(0, 0, 0);
+ gravity = area_gravity;
+ gravity_done = area_gravity_mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE;
+ } break;
+ default: {
+ }
+ }
}
}
+
+ if (aa[i].area->get_wind_force_magnitude() > CMP_EPSILON) {
+ wind_areas.push_back(aa[i].area);
+ }
}
}
+ // Add default gravity and damping from space area.
+ if (!gravity_done) {
+ GodotArea3D *default_area = get_space()->get_default_area();
+ ERR_FAIL_COND(!default_area);
+
+ Vector3 default_gravity;
+ default_area->compute_gravity(get_transform().get_origin(), default_gravity);
+ gravity += default_gravity;
+ }
+
// Apply forces.
add_velocity(gravity * p_delta);
- if (pressure_coefficient > CMP_EPSILON || has_wind_forces) {
- apply_forces(has_wind_forces);
+ if (pressure_coefficient > CMP_EPSILON || !wind_areas.is_empty()) {
+ apply_forces(wind_areas);
}
// Avoid soft body from 'exploding' so use some upper threshold of maximum motion
@@ -1083,7 +1079,7 @@ void SoftBody3DSW::predict_motion(real_t p_delta) {
face_tree.optimize_incremental(1);
}
-void SoftBody3DSW::solve_constraints(real_t p_delta) {
+void GodotSoftBody3D::solve_constraints(real_t p_delta) {
const real_t inv_delta = 1.0 / p_delta;
uint32_t i, ni;
@@ -1120,7 +1116,7 @@ void SoftBody3DSW::solve_constraints(real_t p_delta) {
update_normals_and_centroids();
}
-void SoftBody3DSW::solve_links(real_t kst, real_t ti) {
+void GodotSoftBody3D::solve_links(real_t kst, real_t ti) {
for (uint32_t i = 0, ni = links.size(); i < ni; ++i) {
Link &link = links[i];
if (link.c0 > 0) {
@@ -1138,16 +1134,16 @@ void SoftBody3DSW::solve_links(real_t kst, real_t ti) {
}
struct AABBQueryResult {
- const SoftBody3DSW *soft_body = nullptr;
+ const GodotSoftBody3D *soft_body = nullptr;
void *userdata = nullptr;
- SoftBody3DSW::QueryResultCallback result_callback = nullptr;
+ GodotSoftBody3D::QueryResultCallback result_callback = nullptr;
_FORCE_INLINE_ bool operator()(void *p_data) {
return result_callback(soft_body->get_node_index(p_data), userdata);
};
};
-void SoftBody3DSW::query_aabb(const AABB &p_aabb, SoftBody3DSW::QueryResultCallback p_result_callback, void *p_userdata) {
+void GodotSoftBody3D::query_aabb(const AABB &p_aabb, GodotSoftBody3D::QueryResultCallback p_result_callback, void *p_userdata) {
AABBQueryResult query_result;
query_result.soft_body = this;
query_result.result_callback = p_result_callback;
@@ -1157,16 +1153,16 @@ void SoftBody3DSW::query_aabb(const AABB &p_aabb, SoftBody3DSW::QueryResultCallb
}
struct RayQueryResult {
- const SoftBody3DSW *soft_body = nullptr;
+ const GodotSoftBody3D *soft_body = nullptr;
void *userdata = nullptr;
- SoftBody3DSW::QueryResultCallback result_callback = nullptr;
+ GodotSoftBody3D::QueryResultCallback result_callback = nullptr;
_FORCE_INLINE_ bool operator()(void *p_data) {
return result_callback(soft_body->get_face_index(p_data), userdata);
};
};
-void SoftBody3DSW::query_ray(const Vector3 &p_from, const Vector3 &p_to, SoftBody3DSW::QueryResultCallback p_result_callback, void *p_userdata) {
+void GodotSoftBody3D::query_ray(const Vector3 &p_from, const Vector3 &p_to, GodotSoftBody3D::QueryResultCallback p_result_callback, void *p_userdata) {
if (face_tree.is_empty()) {
initialize_face_tree();
}
@@ -1179,7 +1175,7 @@ void SoftBody3DSW::query_ray(const Vector3 &p_from, const Vector3 &p_to, SoftBod
face_tree.ray_query(p_from, p_to, query_result);
}
-void SoftBody3DSW::initialize_face_tree() {
+void GodotSoftBody3D::initialize_face_tree() {
face_tree.clear();
for (uint32_t i = 0; i < faces.size(); ++i) {
Face &face = faces[i];
@@ -1196,7 +1192,7 @@ void SoftBody3DSW::initialize_face_tree() {
}
}
-void SoftBody3DSW::update_face_tree(real_t p_delta) {
+void GodotSoftBody3D::update_face_tree(real_t p_delta) {
for (uint32_t i = 0; i < faces.size(); ++i) {
const Face &face = faces[i];
@@ -1220,25 +1216,25 @@ void SoftBody3DSW::update_face_tree(real_t p_delta) {
}
}
-void SoftBody3DSW::initialize_shape(bool p_force_move) {
+void GodotSoftBody3D::initialize_shape(bool p_force_move) {
if (get_shape_count() == 0) {
- SoftBodyShape3DSW *soft_body_shape = memnew(SoftBodyShape3DSW(this));
+ GodotSoftBodyShape3D *soft_body_shape = memnew(GodotSoftBodyShape3D(this));
add_shape(soft_body_shape);
} else if (p_force_move) {
- SoftBodyShape3DSW *soft_body_shape = static_cast<SoftBodyShape3DSW *>(get_shape(0));
+ GodotSoftBodyShape3D *soft_body_shape = static_cast<GodotSoftBodyShape3D *>(get_shape(0));
soft_body_shape->update_bounds();
}
}
-void SoftBody3DSW::deinitialize_shape() {
+void GodotSoftBody3D::deinitialize_shape() {
if (get_shape_count() > 0) {
- Shape3DSW *shape = get_shape(0);
+ GodotShape3D *shape = get_shape(0);
remove_shape(shape);
memdelete(shape);
}
}
-void SoftBody3DSW::destroy() {
+void GodotSoftBody3D::destroy() {
soft_mesh = RID();
map_visual_to_physics.clear();
@@ -1254,7 +1250,7 @@ void SoftBody3DSW::destroy() {
deinitialize_shape();
}
-void SoftBodyShape3DSW::update_bounds() {
+void GodotSoftBodyShape3D::update_bounds() {
ERR_FAIL_COND(!soft_body);
AABB collision_aabb = soft_body->get_bounds();
@@ -1262,13 +1258,13 @@ void SoftBodyShape3DSW::update_bounds() {
configure(collision_aabb);
}
-SoftBodyShape3DSW::SoftBodyShape3DSW(SoftBody3DSW *p_soft_body) {
+GodotSoftBodyShape3D::GodotSoftBodyShape3D(GodotSoftBody3D *p_soft_body) {
soft_body = p_soft_body;
update_bounds();
}
struct _SoftBodyIntersectSegmentInfo {
- const SoftBody3DSW *soft_body = nullptr;
+ const GodotSoftBody3D *soft_body = nullptr;
Vector3 from;
Vector3 dir;
Vector3 hit_position;
@@ -1296,7 +1292,7 @@ struct _SoftBodyIntersectSegmentInfo {
}
};
-bool SoftBodyShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const {
+bool GodotSoftBodyShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const {
_SoftBodyIntersectSegmentInfo query_info;
query_info.soft_body = soft_body;
query_info.from = p_begin;
@@ -1313,10 +1309,10 @@ bool SoftBodyShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3
return false;
}
-bool SoftBodyShape3DSW::intersect_point(const Vector3 &p_point) const {
+bool GodotSoftBodyShape3D::intersect_point(const Vector3 &p_point) const {
return false;
}
-Vector3 SoftBodyShape3DSW::get_closest_point_to(const Vector3 &p_point) const {
+Vector3 GodotSoftBodyShape3D::get_closest_point_to(const Vector3 &p_point) const {
ERR_FAIL_V_MSG(Vector3(), "Get closest point is not supported for soft bodies.");
}
diff --git a/servers/physics_3d/soft_body_3d_sw.h b/servers/physics_3d/godot_soft_body_3d.h
index 7d4b83d0ee..5028e81dd8 100644
--- a/servers/physics_3d/soft_body_3d_sw.h
+++ b/servers/physics_3d/godot_soft_body_3d.h
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* soft_body_3d_sw.h */
+/* godot_soft_body_3d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,11 +28,11 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SOFT_BODY_3D_SW_H
-#define SOFT_BODY_3D_SW_H
+#ifndef GODOT_SOFT_BODY_3D_H
+#define GODOT_SOFT_BODY_3D_H
-#include "area_3d_sw.h"
-#include "collision_object_3d_sw.h"
+#include "godot_area_3d.h"
+#include "godot_collision_object_3d.h"
#include "core/math/aabb.h"
#include "core/math/dynamic_bvh.h"
@@ -41,9 +41,9 @@
#include "core/templates/set.h"
#include "core/templates/vset.h"
-class Constraint3DSW;
+class GodotConstraint3D;
-class SoftBody3DSW : public CollisionObject3DSW {
+class GodotSoftBody3D : public GodotCollisionObject3D {
RID soft_mesh;
struct Node {
@@ -101,11 +101,9 @@ class SoftBody3DSW : public CollisionObject3DSW {
real_t drag_coefficient = 0.0; // [0,1]
LocalVector<int> pinned_vertices;
- Vector3 gravity;
+ SelfList<GodotSoftBody3D> active_list;
- SelfList<SoftBody3DSW> active_list;
-
- Set<Constraint3DSW *> constraints;
+ Set<GodotConstraint3D *> constraints;
Vector<AreaCMP> areas;
@@ -113,20 +111,19 @@ class SoftBody3DSW : public CollisionObject3DSW {
uint64_t island_step = 0;
- _FORCE_INLINE_ void _compute_area_gravity(const Area3DSW *p_area);
- _FORCE_INLINE_ Vector3 _compute_area_windforce(const Area3DSW *p_area, const Face *p_face);
+ _FORCE_INLINE_ Vector3 _compute_area_windforce(const GodotArea3D *p_area, const Face *p_face);
public:
- SoftBody3DSW();
+ GodotSoftBody3D();
const AABB &get_bounds() const { return bounds; }
void set_state(PhysicsServer3D::BodyState p_state, const Variant &p_variant);
Variant get_state(PhysicsServer3D::BodyState p_state) const;
- _FORCE_INLINE_ void add_constraint(Constraint3DSW *p_constraint) { constraints.insert(p_constraint); }
- _FORCE_INLINE_ void remove_constraint(Constraint3DSW *p_constraint) { constraints.erase(p_constraint); }
- _FORCE_INLINE_ const Set<Constraint3DSW *> &get_constraints() const { return constraints; }
+ _FORCE_INLINE_ void add_constraint(GodotConstraint3D *p_constraint) { constraints.insert(p_constraint); }
+ _FORCE_INLINE_ void remove_constraint(GodotConstraint3D *p_constraint) { constraints.erase(p_constraint); }
+ _FORCE_INLINE_ const Set<GodotConstraint3D *> &get_constraints() const { return constraints; }
_FORCE_INLINE_ void clear_constraints() { constraints.clear(); }
_FORCE_INLINE_ void add_exception(const RID &p_exception) { exceptions.insert(p_exception); }
@@ -137,7 +134,7 @@ public:
_FORCE_INLINE_ uint64_t get_island_step() const { return island_step; }
_FORCE_INLINE_ void set_island_step(uint64_t p_step) { island_step = p_step; }
- _FORCE_INLINE_ void add_area(Area3DSW *p_area) {
+ _FORCE_INLINE_ void add_area(GodotArea3D *p_area) {
int index = areas.find(AreaCMP(p_area));
if (index > -1) {
areas.write[index].refCount += 1;
@@ -146,17 +143,17 @@ public:
}
}
- _FORCE_INLINE_ void remove_area(Area3DSW *p_area) {
+ _FORCE_INLINE_ void remove_area(GodotArea3D *p_area) {
int index = areas.find(AreaCMP(p_area));
if (index > -1) {
areas.write[index].refCount -= 1;
if (areas[index].refCount < 1) {
- areas.remove(index);
+ areas.remove_at(index);
}
}
}
- virtual void set_space(Space3DSW *p_space);
+ virtual void set_space(GodotSpace3D *p_space);
void set_mesh(RID p_mesh);
@@ -232,7 +229,7 @@ private:
void add_velocity(const Vector3 &p_velocity);
- void apply_forces(bool p_has_wind_forces);
+ void apply_forces(const LocalVector<GodotArea3D *> &p_wind_areas);
bool create_from_trimesh(const Vector<int> &p_indices, const Vector<Vector3> &p_vertices);
void generate_bending_constraints(int p_distance);
@@ -251,29 +248,29 @@ private:
void destroy();
};
-class SoftBodyShape3DSW : public Shape3DSW {
- SoftBody3DSW *soft_body = nullptr;
+class GodotSoftBodyShape3D : public GodotShape3D {
+ GodotSoftBody3D *soft_body = nullptr;
public:
- SoftBody3DSW *get_soft_body() const { return soft_body; }
+ GodotSoftBody3D *get_soft_body() const { return soft_body; }
- virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_SOFT_BODY; }
- virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const { r_min = r_max = 0.0; }
- virtual Vector3 get_support(const Vector3 &p_normal) const { return Vector3(); }
- virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const { r_amount = 0; }
+ virtual PhysicsServer3D::ShapeType get_type() const override { return PhysicsServer3D::SHAPE_SOFT_BODY; }
+ virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override { r_min = r_max = 0.0; }
+ virtual Vector3 get_support(const Vector3 &p_normal) const override { return Vector3(); }
+ virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override { r_amount = 0; }
- virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const;
- virtual bool intersect_point(const Vector3 &p_point) const;
- virtual Vector3 get_closest_point_to(const Vector3 &p_point) const;
- virtual Vector3 get_moment_of_inertia(real_t p_mass) const { return Vector3(); }
+ virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override;
+ virtual bool intersect_point(const Vector3 &p_point) const override;
+ virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override;
+ virtual Vector3 get_moment_of_inertia(real_t p_mass) const override { return Vector3(); }
- virtual void set_data(const Variant &p_data) {}
- virtual Variant get_data() const { return Variant(); }
+ virtual void set_data(const Variant &p_data) override {}
+ virtual Variant get_data() const override { return Variant(); }
void update_bounds();
- SoftBodyShape3DSW(SoftBody3DSW *p_soft_body);
- ~SoftBodyShape3DSW() {}
+ GodotSoftBodyShape3D(GodotSoftBody3D *p_soft_body);
+ ~GodotSoftBodyShape3D() {}
};
-#endif // SOFT_BODY_3D_SW_H
+#endif // GODOT_SOFT_BODY_3D_H
diff --git a/servers/physics_3d/space_3d_sw.cpp b/servers/physics_3d/godot_space_3d.cpp
index c88747c017..ed756a7f9d 100644
--- a/servers/physics_3d/space_3d_sw.cpp
+++ b/servers/physics_3d/godot_space_3d.cpp
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* space_3d_sw.cpp */
+/* godot_space_3d.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,37 +28,39 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "space_3d_sw.h"
+#include "godot_space_3d.h"
+
+#include "godot_collision_solver_3d.h"
+#include "godot_physics_server_3d.h"
-#include "collision_solver_3d_sw.h"
#include "core/config/project_settings.h"
-#include "physics_server_3d_sw.h"
+#define TEST_MOTION_MARGIN_MIN_VALUE 0.0001
#define TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR 0.05
-_FORCE_INLINE_ static bool _can_collide_with(CollisionObject3DSW *p_object, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
+_FORCE_INLINE_ static bool _can_collide_with(GodotCollisionObject3D *p_object, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
if (!(p_object->get_collision_layer() & p_collision_mask)) {
return false;
}
- if (p_object->get_type() == CollisionObject3DSW::TYPE_AREA && !p_collide_with_areas) {
+ if (p_object->get_type() == GodotCollisionObject3D::TYPE_AREA && !p_collide_with_areas) {
return false;
}
- if (p_object->get_type() == CollisionObject3DSW::TYPE_BODY && !p_collide_with_bodies) {
+ if (p_object->get_type() == GodotCollisionObject3D::TYPE_BODY && !p_collide_with_bodies) {
return false;
}
- if (p_object->get_type() == CollisionObject3DSW::TYPE_SOFT_BODY && !p_collide_with_bodies) {
+ if (p_object->get_type() == GodotCollisionObject3D::TYPE_SOFT_BODY && !p_collide_with_bodies) {
return false;
}
return true;
}
-int PhysicsDirectSpaceState3DSW::intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
+int GodotPhysicsDirectSpaceState3D::intersect_point(const PointParameters &p_parameters, ShapeResult *r_results, int p_result_max) {
ERR_FAIL_COND_V(space->locked, false);
- int amount = space->broadphase->cull_point(p_point, space->intersection_query_results, Space3DSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results);
+ int amount = space->broadphase->cull_point(p_parameters.position, space->intersection_query_results, GodotSpace3D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results);
int cc = 0;
//Transform3D ai = p_xform.affine_inverse();
@@ -68,23 +70,23 @@ int PhysicsDirectSpaceState3DSW::intersect_point(const Vector3 &p_point, ShapeRe
break;
}
- if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) {
+ if (!_can_collide_with(space->intersection_query_results[i], p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas)) {
continue;
}
//area can't be picked by ray (default)
- if (p_exclude.has(space->intersection_query_results[i]->get_self())) {
+ if (p_parameters.exclude.has(space->intersection_query_results[i]->get_self())) {
continue;
}
- const CollisionObject3DSW *col_obj = space->intersection_query_results[i];
+ const GodotCollisionObject3D *col_obj = space->intersection_query_results[i];
int shape_idx = space->intersection_query_subindex_results[i];
Transform3D inv_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
inv_xform.affine_invert();
- if (!col_obj->get_shape(shape_idx)->intersect_point(inv_xform.xform(p_point))) {
+ if (!col_obj->get_shape(shape_idx)->intersect_point(inv_xform.xform(p_parameters.position))) {
continue;
}
@@ -103,39 +105,39 @@ int PhysicsDirectSpaceState3DSW::intersect_point(const Vector3 &p_point, ShapeRe
return cc;
}
-bool PhysicsDirectSpaceState3DSW::intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_ray) {
+bool GodotPhysicsDirectSpaceState3D::intersect_ray(const RayParameters &p_parameters, RayResult &r_result) {
ERR_FAIL_COND_V(space->locked, false);
Vector3 begin, end;
Vector3 normal;
- begin = p_from;
- end = p_to;
+ begin = p_parameters.from;
+ end = p_parameters.to;
normal = (end - begin).normalized();
- int amount = space->broadphase->cull_segment(begin, end, space->intersection_query_results, Space3DSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results);
+ int amount = space->broadphase->cull_segment(begin, end, space->intersection_query_results, GodotSpace3D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results);
//todo, create another array that references results, compute AABBs and check closest point to ray origin, sort, and stop evaluating results when beyond first collision
bool collided = false;
Vector3 res_point, res_normal;
int res_shape;
- const CollisionObject3DSW *res_obj;
+ const GodotCollisionObject3D *res_obj;
real_t min_d = 1e10;
for (int i = 0; i < amount; i++) {
- if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) {
+ if (!_can_collide_with(space->intersection_query_results[i], p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas)) {
continue;
}
- if (p_pick_ray && !(space->intersection_query_results[i]->is_ray_pickable())) {
+ if (p_parameters.pick_ray && !(space->intersection_query_results[i]->is_ray_pickable())) {
continue;
}
- if (p_exclude.has(space->intersection_query_results[i]->get_self())) {
+ if (p_parameters.exclude.has(space->intersection_query_results[i]->get_self())) {
continue;
}
- const CollisionObject3DSW *col_obj = space->intersection_query_results[i];
+ const GodotCollisionObject3D *col_obj = space->intersection_query_results[i];
int shape_idx = space->intersection_query_subindex_results[i];
Transform3D inv_xform = col_obj->get_shape_inv_transform(shape_idx) * col_obj->get_inv_transform();
@@ -143,11 +145,27 @@ bool PhysicsDirectSpaceState3DSW::intersect_ray(const Vector3 &p_from, const Vec
Vector3 local_from = inv_xform.xform(begin);
Vector3 local_to = inv_xform.xform(end);
- const Shape3DSW *shape = col_obj->get_shape(shape_idx);
+ const GodotShape3D *shape = col_obj->get_shape(shape_idx);
Vector3 shape_point, shape_normal;
- if (shape->intersect_segment(local_from, local_to, shape_point, shape_normal)) {
+ if (shape->intersect_point(local_from)) {
+ if (p_parameters.hit_from_inside) {
+ // Hit shape at starting point.
+ min_d = 0;
+ res_point = local_from;
+ res_normal = Vector3();
+ res_shape = shape_idx;
+ res_obj = col_obj;
+ collided = true;
+ break;
+ } else {
+ // Ignore shape when starting inside.
+ continue;
+ }
+ }
+
+ if (shape->intersect_segment(local_from, local_to, shape_point, shape_normal, p_parameters.hit_back_faces)) {
Transform3D xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
shape_point = xform.xform(shape_point);
@@ -182,17 +200,17 @@ bool PhysicsDirectSpaceState3DSW::intersect_ray(const Vector3 &p_from, const Vec
return true;
}
-int PhysicsDirectSpaceState3DSW::intersect_shape(const RID &p_shape, const Transform3D &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
+int GodotPhysicsDirectSpaceState3D::intersect_shape(const ShapeParameters &p_parameters, ShapeResult *r_results, int p_result_max) {
if (p_result_max <= 0) {
return 0;
}
- Shape3DSW *shape = PhysicsServer3DSW::singletonsw->shape_owner.get_or_null(p_shape);
+ GodotShape3D *shape = GodotPhysicsServer3D::godot_singleton->shape_owner.get_or_null(p_parameters.shape_rid);
ERR_FAIL_COND_V(!shape, 0);
- AABB aabb = p_xform.xform(shape->get_aabb());
+ AABB aabb = p_parameters.transform.xform(shape->get_aabb());
- int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, Space3DSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results);
+ int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, GodotSpace3D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results);
int cc = 0;
@@ -203,20 +221,20 @@ int PhysicsDirectSpaceState3DSW::intersect_shape(const RID &p_shape, const Trans
break;
}
- if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) {
+ if (!_can_collide_with(space->intersection_query_results[i], p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas)) {
continue;
}
//area can't be picked by ray (default)
- if (p_exclude.has(space->intersection_query_results[i]->get_self())) {
+ if (p_parameters.exclude.has(space->intersection_query_results[i]->get_self())) {
continue;
}
- const CollisionObject3DSW *col_obj = space->intersection_query_results[i];
+ const GodotCollisionObject3D *col_obj = space->intersection_query_results[i];
int shape_idx = space->intersection_query_subindex_results[i];
- if (!CollisionSolver3DSW::solve_static(shape, p_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), nullptr, nullptr, nullptr, p_margin, 0)) {
+ if (!GodotCollisionSolver3D::solve_static(shape, p_parameters.transform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), nullptr, nullptr, nullptr, p_parameters.margin, 0)) {
continue;
}
@@ -237,40 +255,40 @@ int PhysicsDirectSpaceState3DSW::intersect_shape(const RID &p_shape, const Trans
return cc;
}
-bool PhysicsDirectSpaceState3DSW::cast_motion(const RID &p_shape, const Transform3D &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, ShapeRestInfo *r_info) {
- Shape3DSW *shape = PhysicsServer3DSW::singletonsw->shape_owner.get_or_null(p_shape);
+bool GodotPhysicsDirectSpaceState3D::cast_motion(const ShapeParameters &p_parameters, real_t &p_closest_safe, real_t &p_closest_unsafe, ShapeRestInfo *r_info) {
+ GodotShape3D *shape = GodotPhysicsServer3D::godot_singleton->shape_owner.get_or_null(p_parameters.shape_rid);
ERR_FAIL_COND_V(!shape, false);
- AABB aabb = p_xform.xform(shape->get_aabb());
- aabb = aabb.merge(AABB(aabb.position + p_motion, aabb.size)); //motion
- aabb = aabb.grow(p_margin);
+ AABB aabb = p_parameters.transform.xform(shape->get_aabb());
+ aabb = aabb.merge(AABB(aabb.position + p_parameters.motion, aabb.size)); //motion
+ aabb = aabb.grow(p_parameters.margin);
- int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, Space3DSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results);
+ int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, GodotSpace3D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results);
real_t best_safe = 1;
real_t best_unsafe = 1;
- Transform3D xform_inv = p_xform.affine_inverse();
- MotionShape3DSW mshape;
+ Transform3D xform_inv = p_parameters.transform.affine_inverse();
+ GodotMotionShape3D mshape;
mshape.shape = shape;
- mshape.motion = xform_inv.basis.xform(p_motion);
+ mshape.motion = xform_inv.basis.xform(p_parameters.motion);
bool best_first = true;
- Vector3 motion_normal = p_motion.normalized();
+ Vector3 motion_normal = p_parameters.motion.normalized();
Vector3 closest_A, closest_B;
for (int i = 0; i < amount; i++) {
- if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) {
+ if (!_can_collide_with(space->intersection_query_results[i], p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas)) {
continue;
}
- if (p_exclude.has(space->intersection_query_results[i]->get_self())) {
+ if (p_parameters.exclude.has(space->intersection_query_results[i]->get_self())) {
continue; //ignore excluded
}
- const CollisionObject3DSW *col_obj = space->intersection_query_results[i];
+ const GodotCollisionObject3D *col_obj = space->intersection_query_results[i];
int shape_idx = space->intersection_query_subindex_results[i];
Vector3 point_A, point_B;
@@ -278,14 +296,14 @@ bool PhysicsDirectSpaceState3DSW::cast_motion(const RID &p_shape, const Transfor
Transform3D col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
//test initial overlap, does it collide if going all the way?
- if (CollisionSolver3DSW::solve_distance(&mshape, p_xform, col_obj->get_shape(shape_idx), col_obj_xform, point_A, point_B, aabb, &sep_axis)) {
+ if (GodotCollisionSolver3D::solve_distance(&mshape, p_parameters.transform, col_obj->get_shape(shape_idx), col_obj_xform, point_A, point_B, aabb, &sep_axis)) {
continue;
}
//test initial overlap, ignore objects it's inside of.
sep_axis = motion_normal;
- if (!CollisionSolver3DSW::solve_distance(shape, p_xform, col_obj->get_shape(shape_idx), col_obj_xform, point_A, point_B, aabb, &sep_axis)) {
+ if (!GodotCollisionSolver3D::solve_distance(shape, p_parameters.transform, col_obj->get_shape(shape_idx), col_obj_xform, point_A, point_B, aabb, &sep_axis)) {
continue;
}
@@ -296,11 +314,11 @@ bool PhysicsDirectSpaceState3DSW::cast_motion(const RID &p_shape, const Transfor
for (int j = 0; j < 8; j++) { //steps should be customizable..
real_t fraction = low + (hi - low) * fraction_coeff;
- mshape.motion = xform_inv.basis.xform(p_motion * fraction);
+ mshape.motion = xform_inv.basis.xform(p_parameters.motion * fraction);
Vector3 lA, lB;
Vector3 sep = motion_normal; //important optimization for this to work fast enough
- bool collided = !CollisionSolver3DSW::solve_distance(&mshape, p_xform, col_obj->get_shape(shape_idx), col_obj_xform, lA, lB, aabb, &sep);
+ bool collided = !GodotCollisionSolver3D::solve_distance(&mshape, p_parameters.transform, col_obj->get_shape(shape_idx), col_obj_xform, lA, lB, aabb, &sep);
if (collided) {
hi = fraction;
@@ -342,8 +360,8 @@ bool PhysicsDirectSpaceState3DSW::cast_motion(const RID &p_shape, const Transfor
r_info->point = closest_B;
r_info->normal = (closest_A - closest_B).normalized();
best_first = false;
- if (col_obj->get_type() == CollisionObject3DSW::TYPE_BODY) {
- const Body3DSW *body = static_cast<const Body3DSW *>(col_obj);
+ if (col_obj->get_type() == GodotCollisionObject3D::TYPE_BODY) {
+ const GodotBody3D *body = static_cast<const GodotBody3D *>(col_obj);
Vector3 rel_vec = closest_B - (body->get_transform().origin + body->get_center_of_mass());
r_info->linear_velocity = body->get_linear_velocity() + (body->get_angular_velocity()).cross(rel_vec);
}
@@ -356,44 +374,44 @@ bool PhysicsDirectSpaceState3DSW::cast_motion(const RID &p_shape, const Transfor
return true;
}
-bool PhysicsDirectSpaceState3DSW::collide_shape(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
+bool GodotPhysicsDirectSpaceState3D::collide_shape(const ShapeParameters &p_parameters, Vector3 *r_results, int p_result_max, int &r_result_count) {
if (p_result_max <= 0) {
return false;
}
- Shape3DSW *shape = PhysicsServer3DSW::singletonsw->shape_owner.get_or_null(p_shape);
+ GodotShape3D *shape = GodotPhysicsServer3D::godot_singleton->shape_owner.get_or_null(p_parameters.shape_rid);
ERR_FAIL_COND_V(!shape, 0);
- AABB aabb = p_shape_xform.xform(shape->get_aabb());
- aabb = aabb.grow(p_margin);
+ AABB aabb = p_parameters.transform.xform(shape->get_aabb());
+ aabb = aabb.grow(p_parameters.margin);
- int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, Space3DSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results);
+ int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, GodotSpace3D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results);
bool collided = false;
r_result_count = 0;
- PhysicsServer3DSW::CollCbkData cbk;
+ GodotPhysicsServer3D::CollCbkData cbk;
cbk.max = p_result_max;
cbk.amount = 0;
cbk.ptr = r_results;
- CollisionSolver3DSW::CallbackResult cbkres = PhysicsServer3DSW::_shape_col_cbk;
+ GodotCollisionSolver3D::CallbackResult cbkres = GodotPhysicsServer3D::_shape_col_cbk;
- PhysicsServer3DSW::CollCbkData *cbkptr = &cbk;
+ GodotPhysicsServer3D::CollCbkData *cbkptr = &cbk;
for (int i = 0; i < amount; i++) {
- if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) {
+ if (!_can_collide_with(space->intersection_query_results[i], p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas)) {
continue;
}
- const CollisionObject3DSW *col_obj = space->intersection_query_results[i];
+ const GodotCollisionObject3D *col_obj = space->intersection_query_results[i];
- if (p_exclude.has(col_obj->get_self())) {
+ if (p_parameters.exclude.has(col_obj->get_self())) {
continue;
}
int shape_idx = space->intersection_query_subindex_results[i];
- if (CollisionSolver3DSW::solve_static(shape, p_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), cbkres, cbkptr, nullptr, p_margin)) {
+ if (GodotCollisionSolver3D::solve_static(shape, p_parameters.transform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), cbkres, cbkptr, nullptr, p_parameters.margin)) {
collided = true;
}
}
@@ -404,7 +422,7 @@ bool PhysicsDirectSpaceState3DSW::collide_shape(RID p_shape, const Transform3D &
}
struct _RestResultData {
- const CollisionObject3DSW *object = nullptr;
+ const GodotCollisionObject3D *object = nullptr;
int local_shape = 0;
int shape = 0;
Vector3 contact;
@@ -413,7 +431,7 @@ struct _RestResultData {
};
struct _RestCallbackData {
- const CollisionObject3DSW *object = nullptr;
+ const GodotCollisionObject3D *object = nullptr;
int local_shape = 0;
int shape = 0;
@@ -486,28 +504,32 @@ static void _rest_cbk_result(const Vector3 &p_point_A, int p_index_A, const Vect
rd->best_result.local_shape = rd->local_shape;
}
-bool PhysicsDirectSpaceState3DSW::rest_info(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
- Shape3DSW *shape = PhysicsServer3DSW::singletonsw->shape_owner.get_or_null(p_shape);
+bool GodotPhysicsDirectSpaceState3D::rest_info(const ShapeParameters &p_parameters, ShapeRestInfo *r_info) {
+ GodotShape3D *shape = GodotPhysicsServer3D::godot_singleton->shape_owner.get_or_null(p_parameters.shape_rid);
ERR_FAIL_COND_V(!shape, 0);
- real_t min_contact_depth = p_margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR;
+ real_t margin = MAX(p_parameters.margin, TEST_MOTION_MARGIN_MIN_VALUE);
- AABB aabb = p_shape_xform.xform(shape->get_aabb());
- aabb = aabb.grow(p_margin);
+ AABB aabb = p_parameters.transform.xform(shape->get_aabb());
+ aabb = aabb.grow(margin);
- int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, Space3DSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results);
+ int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, GodotSpace3D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results);
_RestCallbackData rcd;
- rcd.min_allowed_depth = min_contact_depth;
+
+ // Allowed depth can't be lower than motion length, in order to handle contacts at low speed.
+ real_t motion_length = p_parameters.motion.length();
+ real_t min_contact_depth = margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR;
+ rcd.min_allowed_depth = MIN(motion_length, min_contact_depth);
for (int i = 0; i < amount; i++) {
- if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) {
+ if (!_can_collide_with(space->intersection_query_results[i], p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas)) {
continue;
}
- const CollisionObject3DSW *col_obj = space->intersection_query_results[i];
+ const GodotCollisionObject3D *col_obj = space->intersection_query_results[i];
- if (p_exclude.has(col_obj->get_self())) {
+ if (p_parameters.exclude.has(col_obj->get_self())) {
continue;
}
@@ -515,7 +537,7 @@ bool PhysicsDirectSpaceState3DSW::rest_info(RID p_shape, const Transform3D &p_sh
rcd.object = col_obj;
rcd.shape = shape_idx;
- bool sc = CollisionSolver3DSW::solve_static(shape, p_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), _rest_cbk_result, &rcd, nullptr, p_margin);
+ bool sc = GodotCollisionSolver3D::solve_static(shape, p_parameters.transform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), _rest_cbk_result, &rcd, nullptr, margin);
if (!sc) {
continue;
}
@@ -530,8 +552,8 @@ bool PhysicsDirectSpaceState3DSW::rest_info(RID p_shape, const Transform3D &p_sh
r_info->normal = rcd.best_result.normal;
r_info->point = rcd.best_result.contact;
r_info->rid = rcd.best_result.object->get_self();
- if (rcd.best_result.object->get_type() == CollisionObject3DSW::TYPE_BODY) {
- const Body3DSW *body = static_cast<const Body3DSW *>(rcd.best_result.object);
+ if (rcd.best_result.object->get_type() == GodotCollisionObject3D::TYPE_BODY) {
+ const GodotBody3D *body = static_cast<const GodotBody3D *>(rcd.best_result.object);
Vector3 rel_vec = rcd.best_result.contact - (body->get_transform().origin + body->get_center_of_mass());
r_info->linear_velocity = body->get_linear_velocity() + (body->get_angular_velocity()).cross(rel_vec);
@@ -542,10 +564,10 @@ bool PhysicsDirectSpaceState3DSW::rest_info(RID p_shape, const Transform3D &p_sh
return true;
}
-Vector3 PhysicsDirectSpaceState3DSW::get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const {
- CollisionObject3DSW *obj = PhysicsServer3DSW::singletonsw->area_owner.get_or_null(p_object);
+Vector3 GodotPhysicsDirectSpaceState3D::get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const {
+ GodotCollisionObject3D *obj = GodotPhysicsServer3D::godot_singleton->area_owner.get_or_null(p_object);
if (!obj) {
- obj = PhysicsServer3DSW::singletonsw->body_owner.get_or_null(p_object);
+ obj = GodotPhysicsServer3D::godot_singleton->body_owner.get_or_null(p_object);
}
ERR_FAIL_COND_V(!obj, Vector3());
@@ -562,7 +584,7 @@ Vector3 PhysicsDirectSpaceState3DSW::get_closest_point_to_object_volume(RID p_ob
}
Transform3D shape_xform = obj->get_transform() * obj->get_shape_transform(i);
- Shape3DSW *shape = obj->get_shape(i);
+ GodotShape3D *shape = obj->get_shape(i);
Vector3 point = shape->get_closest_point_to(shape_xform.affine_inverse().xform(p_point));
point = shape_xform.xform(point);
@@ -582,13 +604,13 @@ Vector3 PhysicsDirectSpaceState3DSW::get_closest_point_to_object_volume(RID p_ob
}
}
-PhysicsDirectSpaceState3DSW::PhysicsDirectSpaceState3DSW() {
+GodotPhysicsDirectSpaceState3D::GodotPhysicsDirectSpaceState3D() {
space = nullptr;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
-int Space3DSW::_cull_aabb_for_body(Body3DSW *p_body, const AABB &p_aabb) {
+int GodotSpace3D::_cull_aabb_for_body(GodotBody3D *p_body, const AABB &p_aabb) {
int amount = broadphase->cull_aabb(p_aabb, intersection_query_results, INTERSECTION_QUERY_MAX, intersection_query_subindex_results);
for (int i = 0; i < amount; i++) {
@@ -596,13 +618,13 @@ int Space3DSW::_cull_aabb_for_body(Body3DSW *p_body, const AABB &p_aabb) {
if (intersection_query_results[i] == p_body) {
keep = false;
- } else if (intersection_query_results[i]->get_type() == CollisionObject3DSW::TYPE_AREA) {
+ } else if (intersection_query_results[i]->get_type() == GodotCollisionObject3D::TYPE_AREA) {
keep = false;
- } else if (intersection_query_results[i]->get_type() == CollisionObject3DSW::TYPE_SOFT_BODY) {
+ } else if (intersection_query_results[i]->get_type() == GodotCollisionObject3D::TYPE_SOFT_BODY) {
keep = false;
- } else if (!p_body->collides_with(static_cast<Body3DSW *>(intersection_query_results[i]))) {
+ } else if (!p_body->collides_with(static_cast<GodotBody3D *>(intersection_query_results[i]))) {
keep = false;
- } else if (static_cast<Body3DSW *>(intersection_query_results[i])->has_exception(p_body->get_self()) || p_body->has_exception(intersection_query_results[i]->get_self())) {
+ } else if (static_cast<GodotBody3D *>(intersection_query_results[i])->has_exception(p_body->get_self()) || p_body->has_exception(intersection_query_results[i]->get_self())) {
keep = false;
}
@@ -620,7 +642,7 @@ int Space3DSW::_cull_aabb_for_body(Body3DSW *p_body, const AABB &p_aabb) {
return amount;
}
-bool Space3DSW::test_body_motion(Body3DSW *p_body, const PhysicsServer3D::MotionParameters &p_parameters, PhysicsServer3D::MotionResult *r_result) {
+bool GodotSpace3D::test_body_motion(GodotBody3D *p_body, const PhysicsServer3D::MotionParameters &p_parameters, PhysicsServer3D::MotionResult *r_result) {
//give me back regular physics engine logic
//this is madness
//and most people using this function will think
@@ -658,11 +680,13 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const PhysicsServer3D::Motion
return false;
}
+ real_t margin = MAX(p_parameters.margin, TEST_MOTION_MARGIN_MIN_VALUE);
+
// Undo the currently transform the physics server is aware of and apply the provided one
body_aabb = p_parameters.from.xform(p_body->get_inv_transform().xform(body_aabb));
- body_aabb = body_aabb.grow(p_parameters.margin);
+ body_aabb = body_aabb.grow(margin);
- real_t min_contact_depth = p_parameters.margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR;
+ real_t min_contact_depth = margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR;
real_t motion_length = p_parameters.motion.length();
Vector3 motion_normal = p_parameters.motion / motion_length;
@@ -679,13 +703,13 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const PhysicsServer3D::Motion
Vector3 sr[max_results * 2];
do {
- PhysicsServer3DSW::CollCbkData cbk;
+ GodotPhysicsServer3D::CollCbkData cbk;
cbk.max = max_results;
cbk.amount = 0;
cbk.ptr = sr;
- PhysicsServer3DSW::CollCbkData *cbkptr = &cbk;
- CollisionSolver3DSW::CallbackResult cbkres = PhysicsServer3DSW::_shape_col_cbk;
+ GodotPhysicsServer3D::CollCbkData *cbkptr = &cbk;
+ GodotCollisionSolver3D::CallbackResult cbkres = GodotPhysicsServer3D::_shape_col_cbk;
bool collided = false;
@@ -697,10 +721,10 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const PhysicsServer3D::Motion
}
Transform3D body_shape_xform = body_transform * p_body->get_shape_transform(j);
- Shape3DSW *body_shape = p_body->get_shape(j);
+ GodotShape3D *body_shape = p_body->get_shape(j);
for (int i = 0; i < amount; i++) {
- const CollisionObject3DSW *col_obj = intersection_query_results[i];
+ const GodotCollisionObject3D *col_obj = intersection_query_results[i];
if (p_parameters.exclude_bodies.has(col_obj->get_self())) {
continue;
}
@@ -710,7 +734,7 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const PhysicsServer3D::Motion
int shape_idx = intersection_query_subindex_results[i];
- if (CollisionSolver3DSW::solve_static(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), cbkres, cbkptr, nullptr, p_parameters.margin)) {
+ if (GodotCollisionSolver3D::solve_static(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), cbkres, cbkptr, nullptr, margin)) {
collided = cbk.amount > 0;
}
}
@@ -770,13 +794,13 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const PhysicsServer3D::Motion
continue;
}
- Shape3DSW *body_shape = p_body->get_shape(j);
+ GodotShape3D *body_shape = p_body->get_shape(j);
// Colliding separation rays allows to properly snap to the ground,
// otherwise it's not needed in regular motion.
if (!p_parameters.collide_separation_ray && (body_shape->get_type() == PhysicsServer3D::SHAPE_SEPARATION_RAY)) {
// When slide on slope is on, separation ray shape acts like a regular shape.
- if (!static_cast<SeparationRayShape3DSW *>(body_shape)->get_slide_on_slope()) {
+ if (!static_cast<GodotSeparationRayShape3D *>(body_shape)->get_slide_on_slope()) {
continue;
}
}
@@ -784,7 +808,7 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const PhysicsServer3D::Motion
Transform3D body_shape_xform = body_transform * p_body->get_shape_transform(j);
Transform3D body_shape_xform_inv = body_shape_xform.affine_inverse();
- MotionShape3DSW mshape;
+ GodotMotionShape3D mshape;
mshape.shape = body_shape;
mshape.motion = body_shape_xform_inv.basis.xform(p_parameters.motion);
@@ -794,7 +818,7 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const PhysicsServer3D::Motion
real_t best_unsafe = 1;
for (int i = 0; i < amount; i++) {
- const CollisionObject3DSW *col_obj = intersection_query_results[i];
+ const GodotCollisionObject3D *col_obj = intersection_query_results[i];
if (p_parameters.exclude_bodies.has(col_obj->get_self())) {
continue;
}
@@ -810,12 +834,12 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const PhysicsServer3D::Motion
Transform3D col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
//test initial overlap, does it collide if going all the way?
- if (CollisionSolver3DSW::solve_distance(&mshape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj_xform, point_A, point_B, motion_aabb, &sep_axis)) {
+ if (GodotCollisionSolver3D::solve_distance(&mshape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj_xform, point_A, point_B, motion_aabb, &sep_axis)) {
continue;
}
sep_axis = motion_normal;
- if (!CollisionSolver3DSW::solve_distance(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj_xform, point_A, point_B, motion_aabb, &sep_axis)) {
+ if (!GodotCollisionSolver3D::solve_distance(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj_xform, point_A, point_B, motion_aabb, &sep_axis)) {
stuck = true;
break;
}
@@ -831,7 +855,7 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const PhysicsServer3D::Motion
Vector3 lA, lB;
Vector3 sep = motion_normal; //important optimization for this to work fast enough
- bool collided = !CollisionSolver3DSW::solve_distance(&mshape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj_xform, lA, lB, motion_aabb, &sep);
+ bool collided = !GodotCollisionSolver3D::solve_distance(&mshape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj_xform, lA, lB, motion_aabb, &sep);
if (collided) {
hi = fraction;
@@ -911,14 +935,14 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const PhysicsServer3D::Motion
}
Transform3D body_shape_xform = ugt * p_body->get_shape_transform(j);
- Shape3DSW *body_shape = p_body->get_shape(j);
+ GodotShape3D *body_shape = p_body->get_shape(j);
body_aabb.position += p_parameters.motion * unsafe;
int amount = _cull_aabb_for_body(p_body, body_aabb);
for (int i = 0; i < amount; i++) {
- const CollisionObject3DSW *col_obj = intersection_query_results[i];
+ const GodotCollisionObject3D *col_obj = intersection_query_results[i];
if (p_parameters.exclude_bodies.has(col_obj->get_self())) {
continue;
}
@@ -930,7 +954,7 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const PhysicsServer3D::Motion
rcd.object = col_obj;
rcd.shape = shape_idx;
- bool sc = CollisionSolver3DSW::solve_static(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), _rest_cbk_result, &rcd, nullptr, p_parameters.margin);
+ bool sc = GodotCollisionSolver3D::solve_static(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), _rest_cbk_result, &rcd, nullptr, margin);
if (!sc) {
continue;
}
@@ -952,7 +976,7 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const PhysicsServer3D::Motion
collision.position = result.contact;
collision.depth = result.len;
- const Body3DSW *body = static_cast<const Body3DSW *>(result.object);
+ const GodotBody3D *body = static_cast<const GodotBody3D *>(result.object);
Vector3 rel_vec = result.contact - (body->get_transform().origin + body->get_center_of_mass());
collision.collider_velocity = body->get_linear_velocity() + (body->get_angular_velocity()).cross(rel_vec);
@@ -984,44 +1008,44 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const PhysicsServer3D::Motion
return collided;
}
-void *Space3DSW::_broadphase_pair(CollisionObject3DSW *A, int p_subindex_A, CollisionObject3DSW *B, int p_subindex_B, void *p_self) {
+void *GodotSpace3D::_broadphase_pair(GodotCollisionObject3D *A, int p_subindex_A, GodotCollisionObject3D *B, int p_subindex_B, void *p_self) {
if (!A->interacts_with(B)) {
return nullptr;
}
- CollisionObject3DSW::Type type_A = A->get_type();
- CollisionObject3DSW::Type type_B = B->get_type();
+ GodotCollisionObject3D::Type type_A = A->get_type();
+ GodotCollisionObject3D::Type type_B = B->get_type();
if (type_A > type_B) {
SWAP(A, B);
SWAP(p_subindex_A, p_subindex_B);
SWAP(type_A, type_B);
}
- Space3DSW *self = (Space3DSW *)p_self;
+ GodotSpace3D *self = (GodotSpace3D *)p_self;
self->collision_pairs++;
- if (type_A == CollisionObject3DSW::TYPE_AREA) {
- Area3DSW *area = static_cast<Area3DSW *>(A);
- if (type_B == CollisionObject3DSW::TYPE_AREA) {
- Area3DSW *area_b = static_cast<Area3DSW *>(B);
- Area2Pair3DSW *area2_pair = memnew(Area2Pair3DSW(area_b, p_subindex_B, area, p_subindex_A));
+ if (type_A == GodotCollisionObject3D::TYPE_AREA) {
+ GodotArea3D *area = static_cast<GodotArea3D *>(A);
+ if (type_B == GodotCollisionObject3D::TYPE_AREA) {
+ GodotArea3D *area_b = static_cast<GodotArea3D *>(B);
+ GodotArea2Pair3D *area2_pair = memnew(GodotArea2Pair3D(area_b, p_subindex_B, area, p_subindex_A));
return area2_pair;
- } else if (type_B == CollisionObject3DSW::TYPE_SOFT_BODY) {
- SoftBody3DSW *softbody = static_cast<SoftBody3DSW *>(B);
- AreaSoftBodyPair3DSW *soft_area_pair = memnew(AreaSoftBodyPair3DSW(softbody, p_subindex_B, area, p_subindex_A));
+ } else if (type_B == GodotCollisionObject3D::TYPE_SOFT_BODY) {
+ GodotSoftBody3D *softbody = static_cast<GodotSoftBody3D *>(B);
+ GodotAreaSoftBodyPair3D *soft_area_pair = memnew(GodotAreaSoftBodyPair3D(softbody, p_subindex_B, area, p_subindex_A));
return soft_area_pair;
} else {
- Body3DSW *body = static_cast<Body3DSW *>(B);
- AreaPair3DSW *area_pair = memnew(AreaPair3DSW(body, p_subindex_B, area, p_subindex_A));
+ GodotBody3D *body = static_cast<GodotBody3D *>(B);
+ GodotAreaPair3D *area_pair = memnew(GodotAreaPair3D(body, p_subindex_B, area, p_subindex_A));
return area_pair;
}
- } else if (type_A == CollisionObject3DSW::TYPE_BODY) {
- if (type_B == CollisionObject3DSW::TYPE_SOFT_BODY) {
- BodySoftBodyPair3DSW *soft_pair = memnew(BodySoftBodyPair3DSW((Body3DSW *)A, p_subindex_A, (SoftBody3DSW *)B));
+ } else if (type_A == GodotCollisionObject3D::TYPE_BODY) {
+ if (type_B == GodotCollisionObject3D::TYPE_SOFT_BODY) {
+ GodotBodySoftBodyPair3D *soft_pair = memnew(GodotBodySoftBodyPair3D((GodotBody3D *)A, p_subindex_A, (GodotSoftBody3D *)B));
return soft_pair;
} else {
- BodyPair3DSW *b = memnew(BodyPair3DSW((Body3DSW *)A, p_subindex_A, (Body3DSW *)B, p_subindex_B));
+ GodotBodyPair3D *b = memnew(GodotBodyPair3D((GodotBody3D *)A, p_subindex_A, (GodotBody3D *)B, p_subindex_B));
return b;
}
} else {
@@ -1031,110 +1055,110 @@ void *Space3DSW::_broadphase_pair(CollisionObject3DSW *A, int p_subindex_A, Coll
return nullptr;
}
-void Space3DSW::_broadphase_unpair(CollisionObject3DSW *A, int p_subindex_A, CollisionObject3DSW *B, int p_subindex_B, void *p_data, void *p_self) {
+void GodotSpace3D::_broadphase_unpair(GodotCollisionObject3D *A, int p_subindex_A, GodotCollisionObject3D *B, int p_subindex_B, void *p_data, void *p_self) {
if (!p_data) {
return;
}
- Space3DSW *self = (Space3DSW *)p_self;
+ GodotSpace3D *self = (GodotSpace3D *)p_self;
self->collision_pairs--;
- Constraint3DSW *c = (Constraint3DSW *)p_data;
+ GodotConstraint3D *c = (GodotConstraint3D *)p_data;
memdelete(c);
}
-const SelfList<Body3DSW>::List &Space3DSW::get_active_body_list() const {
+const SelfList<GodotBody3D>::List &GodotSpace3D::get_active_body_list() const {
return active_list;
}
-void Space3DSW::body_add_to_active_list(SelfList<Body3DSW> *p_body) {
+void GodotSpace3D::body_add_to_active_list(SelfList<GodotBody3D> *p_body) {
active_list.add(p_body);
}
-void Space3DSW::body_remove_from_active_list(SelfList<Body3DSW> *p_body) {
+void GodotSpace3D::body_remove_from_active_list(SelfList<GodotBody3D> *p_body) {
active_list.remove(p_body);
}
-void Space3DSW::body_add_to_mass_properties_update_list(SelfList<Body3DSW> *p_body) {
+void GodotSpace3D::body_add_to_mass_properties_update_list(SelfList<GodotBody3D> *p_body) {
mass_properties_update_list.add(p_body);
}
-void Space3DSW::body_remove_from_mass_properties_update_list(SelfList<Body3DSW> *p_body) {
+void GodotSpace3D::body_remove_from_mass_properties_update_list(SelfList<GodotBody3D> *p_body) {
mass_properties_update_list.remove(p_body);
}
-BroadPhase3DSW *Space3DSW::get_broadphase() {
+GodotBroadPhase3D *GodotSpace3D::get_broadphase() {
return broadphase;
}
-void Space3DSW::add_object(CollisionObject3DSW *p_object) {
+void GodotSpace3D::add_object(GodotCollisionObject3D *p_object) {
ERR_FAIL_COND(objects.has(p_object));
objects.insert(p_object);
}
-void Space3DSW::remove_object(CollisionObject3DSW *p_object) {
+void GodotSpace3D::remove_object(GodotCollisionObject3D *p_object) {
ERR_FAIL_COND(!objects.has(p_object));
objects.erase(p_object);
}
-const Set<CollisionObject3DSW *> &Space3DSW::get_objects() const {
+const Set<GodotCollisionObject3D *> &GodotSpace3D::get_objects() const {
return objects;
}
-void Space3DSW::body_add_to_state_query_list(SelfList<Body3DSW> *p_body) {
+void GodotSpace3D::body_add_to_state_query_list(SelfList<GodotBody3D> *p_body) {
state_query_list.add(p_body);
}
-void Space3DSW::body_remove_from_state_query_list(SelfList<Body3DSW> *p_body) {
+void GodotSpace3D::body_remove_from_state_query_list(SelfList<GodotBody3D> *p_body) {
state_query_list.remove(p_body);
}
-void Space3DSW::area_add_to_monitor_query_list(SelfList<Area3DSW> *p_area) {
+void GodotSpace3D::area_add_to_monitor_query_list(SelfList<GodotArea3D> *p_area) {
monitor_query_list.add(p_area);
}
-void Space3DSW::area_remove_from_monitor_query_list(SelfList<Area3DSW> *p_area) {
+void GodotSpace3D::area_remove_from_monitor_query_list(SelfList<GodotArea3D> *p_area) {
monitor_query_list.remove(p_area);
}
-void Space3DSW::area_add_to_moved_list(SelfList<Area3DSW> *p_area) {
+void GodotSpace3D::area_add_to_moved_list(SelfList<GodotArea3D> *p_area) {
area_moved_list.add(p_area);
}
-void Space3DSW::area_remove_from_moved_list(SelfList<Area3DSW> *p_area) {
+void GodotSpace3D::area_remove_from_moved_list(SelfList<GodotArea3D> *p_area) {
area_moved_list.remove(p_area);
}
-const SelfList<Area3DSW>::List &Space3DSW::get_moved_area_list() const {
+const SelfList<GodotArea3D>::List &GodotSpace3D::get_moved_area_list() const {
return area_moved_list;
}
-const SelfList<SoftBody3DSW>::List &Space3DSW::get_active_soft_body_list() const {
+const SelfList<GodotSoftBody3D>::List &GodotSpace3D::get_active_soft_body_list() const {
return active_soft_body_list;
}
-void Space3DSW::soft_body_add_to_active_list(SelfList<SoftBody3DSW> *p_soft_body) {
+void GodotSpace3D::soft_body_add_to_active_list(SelfList<GodotSoftBody3D> *p_soft_body) {
active_soft_body_list.add(p_soft_body);
}
-void Space3DSW::soft_body_remove_from_active_list(SelfList<SoftBody3DSW> *p_soft_body) {
+void GodotSpace3D::soft_body_remove_from_active_list(SelfList<GodotSoftBody3D> *p_soft_body) {
active_soft_body_list.remove(p_soft_body);
}
-void Space3DSW::call_queries() {
+void GodotSpace3D::call_queries() {
while (state_query_list.first()) {
- Body3DSW *b = state_query_list.first()->self();
+ GodotBody3D *b = state_query_list.first()->self();
state_query_list.remove(state_query_list.first());
b->call_queries();
}
while (monitor_query_list.first()) {
- Area3DSW *a = monitor_query_list.first()->self();
+ GodotArea3D *a = monitor_query_list.first()->self();
monitor_query_list.remove(monitor_query_list.first());
a->call_queries();
}
}
-void Space3DSW::setup() {
+void GodotSpace3D::setup() {
contact_debug_count = 0;
while (mass_properties_update_list.first()) {
mass_properties_update_list.first()->self()->update_mass_properties();
@@ -1142,11 +1166,11 @@ void Space3DSW::setup() {
}
}
-void Space3DSW::update() {
+void GodotSpace3D::update() {
broadphase->update();
}
-void Space3DSW::set_param(PhysicsServer3D::SpaceParameter p_param, real_t p_value) {
+void GodotSpace3D::set_param(PhysicsServer3D::SpaceParameter p_param, real_t p_value) {
switch (p_param) {
case PhysicsServer3D::SPACE_PARAM_CONTACT_RECYCLE_RADIUS:
contact_recycle_radius = p_value;
@@ -1154,9 +1178,12 @@ void Space3DSW::set_param(PhysicsServer3D::SpaceParameter p_param, real_t p_valu
case PhysicsServer3D::SPACE_PARAM_CONTACT_MAX_SEPARATION:
contact_max_separation = p_value;
break;
- case PhysicsServer3D::SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION:
+ case PhysicsServer3D::SPACE_PARAM_CONTACT_MAX_ALLOWED_PENETRATION:
contact_max_allowed_penetration = p_value;
break;
+ case PhysicsServer3D::SPACE_PARAM_CONTACT_DEFAULT_BIAS:
+ contact_bias = p_value;
+ break;
case PhysicsServer3D::SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD:
body_linear_velocity_sleep_threshold = p_value;
break;
@@ -1166,69 +1193,80 @@ void Space3DSW::set_param(PhysicsServer3D::SpaceParameter p_param, real_t p_valu
case PhysicsServer3D::SPACE_PARAM_BODY_TIME_TO_SLEEP:
body_time_to_sleep = p_value;
break;
- case PhysicsServer3D::SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO:
- body_angular_velocity_damp_ratio = p_value;
- break;
- case PhysicsServer3D::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS:
- constraint_bias = p_value;
+ case PhysicsServer3D::SPACE_PARAM_SOLVER_ITERATIONS:
+ solver_iterations = p_value;
break;
}
}
-real_t Space3DSW::get_param(PhysicsServer3D::SpaceParameter p_param) const {
+real_t GodotSpace3D::get_param(PhysicsServer3D::SpaceParameter p_param) const {
switch (p_param) {
case PhysicsServer3D::SPACE_PARAM_CONTACT_RECYCLE_RADIUS:
return contact_recycle_radius;
case PhysicsServer3D::SPACE_PARAM_CONTACT_MAX_SEPARATION:
return contact_max_separation;
- case PhysicsServer3D::SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION:
+ case PhysicsServer3D::SPACE_PARAM_CONTACT_MAX_ALLOWED_PENETRATION:
return contact_max_allowed_penetration;
+ case PhysicsServer3D::SPACE_PARAM_CONTACT_DEFAULT_BIAS:
+ return contact_bias;
case PhysicsServer3D::SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD:
return body_linear_velocity_sleep_threshold;
case PhysicsServer3D::SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD:
return body_angular_velocity_sleep_threshold;
case PhysicsServer3D::SPACE_PARAM_BODY_TIME_TO_SLEEP:
return body_time_to_sleep;
- case PhysicsServer3D::SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO:
- return body_angular_velocity_damp_ratio;
- case PhysicsServer3D::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS:
- return constraint_bias;
+ case PhysicsServer3D::SPACE_PARAM_SOLVER_ITERATIONS:
+ return solver_iterations;
}
return 0;
}
-void Space3DSW::lock() {
+void GodotSpace3D::lock() {
locked = true;
}
-void Space3DSW::unlock() {
+void GodotSpace3D::unlock() {
locked = false;
}
-bool Space3DSW::is_locked() const {
+bool GodotSpace3D::is_locked() const {
return locked;
}
-PhysicsDirectSpaceState3DSW *Space3DSW::get_direct_state() {
+GodotPhysicsDirectSpaceState3D *GodotSpace3D::get_direct_state() {
return direct_access;
}
-Space3DSW::Space3DSW() {
+GodotSpace3D::GodotSpace3D() {
body_linear_velocity_sleep_threshold = GLOBAL_DEF("physics/3d/sleep_threshold_linear", 0.1);
body_angular_velocity_sleep_threshold = GLOBAL_DEF("physics/3d/sleep_threshold_angular", Math::deg2rad(8.0));
body_time_to_sleep = GLOBAL_DEF("physics/3d/time_before_sleep", 0.5);
ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/time_before_sleep", PropertyInfo(Variant::FLOAT, "physics/3d/time_before_sleep", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater"));
- body_angular_velocity_damp_ratio = 10;
- broadphase = BroadPhase3DSW::create_func();
+ solver_iterations = GLOBAL_DEF("physics/3d/solver/solver_iterations", 16);
+ ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/solver/solver_iterations", PropertyInfo(Variant::INT, "physics/3d/solver/solver_iterations", PROPERTY_HINT_RANGE, "1,32,1,or_greater"));
+
+ contact_recycle_radius = GLOBAL_DEF("physics/3d/solver/contact_recycle_radius", 0.01);
+ ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/solver/contact_recycle_radius", PropertyInfo(Variant::FLOAT, "physics/3d/solver/contact_max_separation", PROPERTY_HINT_RANGE, "0,0.1,0.01,or_greater"));
+
+ contact_max_separation = GLOBAL_DEF("physics/3d/solver/contact_max_separation", 0.05);
+ ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/solver/contact_max_separation", PropertyInfo(Variant::FLOAT, "physics/3d/solver/contact_max_separation", PROPERTY_HINT_RANGE, "0,0.1,0.01,or_greater"));
+
+ contact_max_allowed_penetration = GLOBAL_DEF("physics/3d/solver/contact_max_allowed_penetration", 0.01);
+ ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/solver/contact_max_allowed_penetration", PropertyInfo(Variant::FLOAT, "physics/3d/solver/contact_max_allowed_penetration", PROPERTY_HINT_RANGE, "0,0.1,0.01,or_greater"));
+
+ contact_bias = GLOBAL_DEF("physics/3d/solver/default_contact_bias", 0.8);
+ ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/solver/default_contact_bias", PropertyInfo(Variant::FLOAT, "physics/3d/solver/default_contact_bias", PROPERTY_HINT_RANGE, "0,1,0.01"));
+
+ broadphase = GodotBroadPhase3D::create_func();
broadphase->set_pair_callback(_broadphase_pair, this);
broadphase->set_unpair_callback(_broadphase_unpair, this);
- direct_access = memnew(PhysicsDirectSpaceState3DSW);
+ direct_access = memnew(GodotPhysicsDirectSpaceState3D);
direct_access->space = this;
}
-Space3DSW::~Space3DSW() {
+GodotSpace3D::~GodotSpace3D() {
memdelete(broadphase);
memdelete(direct_access);
}
diff --git a/servers/physics_3d/godot_space_3d.h b/servers/physics_3d/godot_space_3d.h
new file mode 100644
index 0000000000..ac54c8bf69
--- /dev/null
+++ b/servers/physics_3d/godot_space_3d.h
@@ -0,0 +1,218 @@
+/*************************************************************************/
+/* godot_space_3d.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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_SPACE_3D_H
+#define GODOT_SPACE_3D_H
+
+#include "godot_area_3d.h"
+#include "godot_area_pair_3d.h"
+#include "godot_body_3d.h"
+#include "godot_body_pair_3d.h"
+#include "godot_broad_phase_3d.h"
+#include "godot_collision_object_3d.h"
+#include "godot_soft_body_3d.h"
+
+#include "core/config/project_settings.h"
+#include "core/templates/hash_map.h"
+#include "core/typedefs.h"
+
+class GodotPhysicsDirectSpaceState3D : public PhysicsDirectSpaceState3D {
+ GDCLASS(GodotPhysicsDirectSpaceState3D, PhysicsDirectSpaceState3D);
+
+public:
+ GodotSpace3D *space;
+
+ virtual int intersect_point(const PointParameters &p_parameters, ShapeResult *r_results, int p_result_max) override;
+ virtual bool intersect_ray(const RayParameters &p_parameters, RayResult &r_result) override;
+ virtual int intersect_shape(const ShapeParameters &p_parameters, ShapeResult *r_results, int p_result_max) override;
+ virtual bool cast_motion(const ShapeParameters &p_parameters, real_t &p_closest_safe, real_t &p_closest_unsafe, ShapeRestInfo *r_info = nullptr) override;
+ virtual bool collide_shape(const ShapeParameters &p_parameters, Vector3 *r_results, int p_result_max, int &r_result_count) override;
+ virtual bool rest_info(const ShapeParameters &p_parameters, ShapeRestInfo *r_info) override;
+ virtual Vector3 get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const override;
+
+ GodotPhysicsDirectSpaceState3D();
+};
+
+class GodotSpace3D {
+public:
+ enum ElapsedTime {
+ ELAPSED_TIME_INTEGRATE_FORCES,
+ ELAPSED_TIME_GENERATE_ISLANDS,
+ ELAPSED_TIME_SETUP_CONSTRAINTS,
+ ELAPSED_TIME_SOLVE_CONSTRAINTS,
+ ELAPSED_TIME_INTEGRATE_VELOCITIES,
+ ELAPSED_TIME_MAX
+
+ };
+
+private:
+ uint64_t elapsed_time[ELAPSED_TIME_MAX] = {};
+
+ GodotPhysicsDirectSpaceState3D *direct_access = nullptr;
+ RID self;
+
+ GodotBroadPhase3D *broadphase = nullptr;
+ SelfList<GodotBody3D>::List active_list;
+ SelfList<GodotBody3D>::List mass_properties_update_list;
+ SelfList<GodotBody3D>::List state_query_list;
+ SelfList<GodotArea3D>::List monitor_query_list;
+ SelfList<GodotArea3D>::List area_moved_list;
+ SelfList<GodotSoftBody3D>::List active_soft_body_list;
+
+ static void *_broadphase_pair(GodotCollisionObject3D *A, int p_subindex_A, GodotCollisionObject3D *B, int p_subindex_B, void *p_self);
+ static void _broadphase_unpair(GodotCollisionObject3D *A, int p_subindex_A, GodotCollisionObject3D *B, int p_subindex_B, void *p_data, void *p_self);
+
+ Set<GodotCollisionObject3D *> objects;
+
+ GodotArea3D *area = nullptr;
+
+ int solver_iterations = 0;
+
+ real_t contact_recycle_radius = 0.0;
+ real_t contact_max_separation = 0.0;
+ real_t contact_max_allowed_penetration = 0.0;
+ real_t contact_bias = 0.0;
+
+ enum {
+ INTERSECTION_QUERY_MAX = 2048
+ };
+
+ GodotCollisionObject3D *intersection_query_results[INTERSECTION_QUERY_MAX];
+ int intersection_query_subindex_results[INTERSECTION_QUERY_MAX];
+
+ real_t body_linear_velocity_sleep_threshold = 0.0;
+ real_t body_angular_velocity_sleep_threshold = 0.0;
+ real_t body_time_to_sleep = 0.0;
+
+ bool locked = false;
+
+ real_t last_step = 0.001;
+
+ int island_count = 0;
+ int active_objects = 0;
+ int collision_pairs = 0;
+
+ RID static_global_body;
+
+ Vector<Vector3> contact_debug;
+ int contact_debug_count = 0;
+
+ friend class GodotPhysicsDirectSpaceState3D;
+
+ int _cull_aabb_for_body(GodotBody3D *p_body, const AABB &p_aabb);
+
+public:
+ _FORCE_INLINE_ void set_self(const RID &p_self) { self = p_self; }
+ _FORCE_INLINE_ RID get_self() const { return self; }
+
+ void set_default_area(GodotArea3D *p_area) { area = p_area; }
+ GodotArea3D *get_default_area() const { return area; }
+
+ const SelfList<GodotBody3D>::List &get_active_body_list() const;
+ void body_add_to_active_list(SelfList<GodotBody3D> *p_body);
+ void body_remove_from_active_list(SelfList<GodotBody3D> *p_body);
+ void body_add_to_mass_properties_update_list(SelfList<GodotBody3D> *p_body);
+ void body_remove_from_mass_properties_update_list(SelfList<GodotBody3D> *p_body);
+
+ void body_add_to_state_query_list(SelfList<GodotBody3D> *p_body);
+ void body_remove_from_state_query_list(SelfList<GodotBody3D> *p_body);
+
+ void area_add_to_monitor_query_list(SelfList<GodotArea3D> *p_area);
+ void area_remove_from_monitor_query_list(SelfList<GodotArea3D> *p_area);
+ void area_add_to_moved_list(SelfList<GodotArea3D> *p_area);
+ void area_remove_from_moved_list(SelfList<GodotArea3D> *p_area);
+ const SelfList<GodotArea3D>::List &get_moved_area_list() const;
+
+ const SelfList<GodotSoftBody3D>::List &get_active_soft_body_list() const;
+ void soft_body_add_to_active_list(SelfList<GodotSoftBody3D> *p_soft_body);
+ void soft_body_remove_from_active_list(SelfList<GodotSoftBody3D> *p_soft_body);
+
+ GodotBroadPhase3D *get_broadphase();
+
+ void add_object(GodotCollisionObject3D *p_object);
+ void remove_object(GodotCollisionObject3D *p_object);
+ const Set<GodotCollisionObject3D *> &get_objects() const;
+
+ _FORCE_INLINE_ int get_solver_iterations() const { return solver_iterations; }
+ _FORCE_INLINE_ real_t get_contact_recycle_radius() const { return contact_recycle_radius; }
+ _FORCE_INLINE_ real_t get_contact_max_separation() const { return contact_max_separation; }
+ _FORCE_INLINE_ real_t get_contact_max_allowed_penetration() const { return contact_max_allowed_penetration; }
+ _FORCE_INLINE_ real_t get_contact_bias() const { return contact_bias; }
+ _FORCE_INLINE_ real_t get_body_linear_velocity_sleep_threshold() const { return body_linear_velocity_sleep_threshold; }
+ _FORCE_INLINE_ real_t get_body_angular_velocity_sleep_threshold() const { return body_angular_velocity_sleep_threshold; }
+ _FORCE_INLINE_ real_t get_body_time_to_sleep() const { return body_time_to_sleep; }
+
+ void update();
+ void setup();
+ void call_queries();
+
+ bool is_locked() const;
+ void lock();
+ void unlock();
+
+ real_t get_last_step() const { return last_step; }
+ void set_last_step(real_t p_step) { last_step = p_step; }
+
+ void set_param(PhysicsServer3D::SpaceParameter p_param, real_t p_value);
+ real_t get_param(PhysicsServer3D::SpaceParameter p_param) const;
+
+ void set_island_count(int p_island_count) { island_count = p_island_count; }
+ int get_island_count() const { return island_count; }
+
+ void set_active_objects(int p_active_objects) { active_objects = p_active_objects; }
+ int get_active_objects() const { return active_objects; }
+
+ int get_collision_pairs() const { return collision_pairs; }
+
+ GodotPhysicsDirectSpaceState3D *get_direct_state();
+
+ void set_debug_contacts(int p_amount) { contact_debug.resize(p_amount); }
+ _FORCE_INLINE_ bool is_debugging_contacts() const { return !contact_debug.is_empty(); }
+ _FORCE_INLINE_ void add_debug_contact(const Vector3 &p_contact) {
+ if (contact_debug_count < contact_debug.size()) {
+ contact_debug.write[contact_debug_count++] = p_contact;
+ }
+ }
+ _FORCE_INLINE_ Vector<Vector3> get_debug_contacts() { return contact_debug; }
+ _FORCE_INLINE_ int get_debug_contact_count() { return contact_debug_count; }
+
+ void set_static_global_body(RID p_body) { static_global_body = p_body; }
+ RID get_static_global_body() { return static_global_body; }
+
+ void set_elapsed_time(ElapsedTime p_time, uint64_t p_msec) { elapsed_time[p_time] = p_msec; }
+ uint64_t get_elapsed_time(ElapsedTime p_time) const { return elapsed_time[p_time]; }
+
+ bool test_body_motion(GodotBody3D *p_body, const PhysicsServer3D::MotionParameters &p_parameters, PhysicsServer3D::MotionResult *r_result);
+
+ GodotSpace3D();
+ ~GodotSpace3D();
+};
+
+#endif // GODOT_SPACE_3D_H
diff --git a/servers/physics_3d/step_3d_sw.cpp b/servers/physics_3d/godot_step_3d.cpp
index 6572d58c91..63635b224b 100644
--- a/servers/physics_3d/step_3d_sw.cpp
+++ b/servers/physics_3d/godot_step_3d.cpp
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* step_3d_sw.cpp */
+/* godot_step_3d.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,8 +28,9 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "step_3d_sw.h"
-#include "joints_3d_sw.h"
+#include "godot_step_3d.h"
+
+#include "godot_joint_3d.h"
#include "core/os/os.h"
@@ -39,7 +40,7 @@
#define ISLAND_SIZE_RESERVE 512
#define CONSTRAINT_COUNT_RESERVE 1024
-void Step3DSW::_populate_island(Body3DSW *p_body, LocalVector<Body3DSW *> &p_body_island, LocalVector<Constraint3DSW *> &p_constraint_island) {
+void GodotStep3D::_populate_island(GodotBody3D *p_body, LocalVector<GodotBody3D *> &p_body_island, LocalVector<GodotConstraint3D *> &p_constraint_island) {
p_body->set_island_step(_step);
if (p_body->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC) {
@@ -47,8 +48,8 @@ void Step3DSW::_populate_island(Body3DSW *p_body, LocalVector<Body3DSW *> &p_bod
p_body_island.push_back(p_body);
}
- for (const KeyValue<Constraint3DSW *, int> &E : p_body->get_constraint_map()) {
- Constraint3DSW *constraint = (Constraint3DSW *)E.key;
+ for (const KeyValue<GodotConstraint3D *, int> &E : p_body->get_constraint_map()) {
+ GodotConstraint3D *constraint = (GodotConstraint3D *)E.key;
if (constraint->get_island_step() == _step) {
continue; // Already processed.
}
@@ -62,7 +63,7 @@ void Step3DSW::_populate_island(Body3DSW *p_body, LocalVector<Body3DSW *> &p_bod
if (i == E.value) {
continue;
}
- Body3DSW *other_body = constraint->get_body_ptr()[i];
+ GodotBody3D *other_body = constraint->get_body_ptr()[i];
if (other_body->get_island_step() == _step) {
continue; // Already processed.
}
@@ -74,7 +75,7 @@ void Step3DSW::_populate_island(Body3DSW *p_body, LocalVector<Body3DSW *> &p_bod
// Find connected soft bodies.
for (int i = 0; i < constraint->get_soft_body_count(); i++) {
- SoftBody3DSW *soft_body = constraint->get_soft_body_ptr(i);
+ GodotSoftBody3D *soft_body = constraint->get_soft_body_ptr(i);
if (soft_body->get_island_step() == _step) {
continue; // Already processed.
}
@@ -83,11 +84,11 @@ void Step3DSW::_populate_island(Body3DSW *p_body, LocalVector<Body3DSW *> &p_bod
}
}
-void Step3DSW::_populate_island_soft_body(SoftBody3DSW *p_soft_body, LocalVector<Body3DSW *> &p_body_island, LocalVector<Constraint3DSW *> &p_constraint_island) {
+void GodotStep3D::_populate_island_soft_body(GodotSoftBody3D *p_soft_body, LocalVector<GodotBody3D *> &p_body_island, LocalVector<GodotConstraint3D *> &p_constraint_island) {
p_soft_body->set_island_step(_step);
- for (Set<Constraint3DSW *>::Element *E = p_soft_body->get_constraints().front(); E; E = E->next()) {
- Constraint3DSW *constraint = (Constraint3DSW *)E->get();
+ for (Set<GodotConstraint3D *>::Element *E = p_soft_body->get_constraints().front(); E; E = E->next()) {
+ GodotConstraint3D *constraint = (GodotConstraint3D *)E->get();
if (constraint->get_island_step() == _step) {
continue; // Already processed.
}
@@ -98,7 +99,7 @@ void Step3DSW::_populate_island_soft_body(SoftBody3DSW *p_soft_body, LocalVector
// Find connected rigid bodies.
for (int i = 0; i < constraint->get_body_count(); i++) {
- Body3DSW *body = constraint->get_body_ptr()[i];
+ GodotBody3D *body = constraint->get_body_ptr()[i];
if (body->get_island_step() == _step) {
continue; // Already processed.
}
@@ -110,16 +111,16 @@ void Step3DSW::_populate_island_soft_body(SoftBody3DSW *p_soft_body, LocalVector
}
}
-void Step3DSW::_setup_contraint(uint32_t p_constraint_index, void *p_userdata) {
- Constraint3DSW *constraint = all_constraints[p_constraint_index];
+void GodotStep3D::_setup_contraint(uint32_t p_constraint_index, void *p_userdata) {
+ GodotConstraint3D *constraint = all_constraints[p_constraint_index];
constraint->setup(delta);
}
-void Step3DSW::_pre_solve_island(LocalVector<Constraint3DSW *> &p_constraint_island) const {
+void GodotStep3D::_pre_solve_island(LocalVector<GodotConstraint3D *> &p_constraint_island) const {
uint32_t constraint_count = p_constraint_island.size();
uint32_t valid_constraint_count = 0;
for (uint32_t constraint_index = 0; constraint_index < constraint_count; ++constraint_index) {
- Constraint3DSW *constraint = p_constraint_island[constraint_index];
+ GodotConstraint3D *constraint = p_constraint_island[constraint_index];
if (p_constraint_island[constraint_index]->pre_solve(delta)) {
// Keep this constraint for solving.
p_constraint_island[valid_constraint_count++] = constraint;
@@ -128,8 +129,8 @@ void Step3DSW::_pre_solve_island(LocalVector<Constraint3DSW *> &p_constraint_isl
p_constraint_island.resize(valid_constraint_count);
}
-void Step3DSW::_solve_island(uint32_t p_island_index, void *p_userdata) {
- LocalVector<Constraint3DSW *> &constraint_island = constraint_islands[p_island_index];
+void GodotStep3D::_solve_island(uint32_t p_island_index, void *p_userdata) {
+ LocalVector<GodotConstraint3D *> &constraint_island = constraint_islands[p_island_index];
int current_priority = 1;
@@ -146,7 +147,7 @@ void Step3DSW::_solve_island(uint32_t p_island_index, void *p_userdata) {
uint32_t priority_constraint_count = 0;
++current_priority;
for (uint32_t constraint_index = 0; constraint_index < constraint_count; ++constraint_index) {
- Constraint3DSW *constraint = constraint_island[constraint_index];
+ GodotConstraint3D *constraint = constraint_island[constraint_index];
if (constraint->get_priority() >= current_priority) {
// Keep this constraint for the next iteration.
constraint_island[priority_constraint_count++] = constraint;
@@ -156,12 +157,12 @@ void Step3DSW::_solve_island(uint32_t p_island_index, void *p_userdata) {
}
}
-void Step3DSW::_check_suspend(const LocalVector<Body3DSW *> &p_body_island) const {
+void GodotStep3D::_check_suspend(const LocalVector<GodotBody3D *> &p_body_island) const {
bool can_sleep = true;
uint32_t body_count = p_body_island.size();
for (uint32_t body_index = 0; body_index < body_count; ++body_index) {
- Body3DSW *body = p_body_island[body_index];
+ GodotBody3D *body = p_body_island[body_index];
if (!body->sleep_test(delta)) {
can_sleep = false;
@@ -170,7 +171,7 @@ void Step3DSW::_check_suspend(const LocalVector<Body3DSW *> &p_body_island) cons
// Put all to sleep or wake up everyone.
for (uint32_t body_index = 0; body_index < body_count; ++body_index) {
- Body3DSW *body = p_body_island[body_index];
+ GodotBody3D *body = p_body_island[body_index];
bool active = body->is_active();
@@ -180,19 +181,19 @@ void Step3DSW::_check_suspend(const LocalVector<Body3DSW *> &p_body_island) cons
}
}
-void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) {
+void GodotStep3D::step(GodotSpace3D *p_space, real_t p_delta) {
p_space->lock(); // can't access space during this
p_space->setup(); //update inertias, etc
p_space->set_last_step(p_delta);
- iterations = p_iterations;
+ iterations = p_space->get_solver_iterations();
delta = p_delta;
- const SelfList<Body3DSW>::List *body_list = &p_space->get_active_body_list();
+ const SelfList<GodotBody3D>::List *body_list = &p_space->get_active_body_list();
- const SelfList<SoftBody3DSW>::List *soft_body_list = &p_space->get_active_soft_body_list();
+ const SelfList<GodotSoftBody3D>::List *soft_body_list = &p_space->get_active_soft_body_list();
/* INTEGRATE FORCES */
@@ -201,7 +202,7 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) {
int active_count = 0;
- const SelfList<Body3DSW> *b = body_list->first();
+ const SelfList<GodotBody3D> *b = body_list->first();
while (b) {
b->self()->integrate_forces(p_delta);
b = b->next();
@@ -210,7 +211,7 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) {
/* UPDATE SOFT BODY MOTION */
- const SelfList<SoftBody3DSW> *sb = soft_body_list->first();
+ const SelfList<GodotSoftBody3D> *sb = soft_body_list->first();
while (sb) {
sb->self()->predict_motion(p_delta);
sb = sb->next();
@@ -219,9 +220,12 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) {
p_space->set_active_objects(active_count);
+ // Update the broadphase to register collision pairs.
+ p_space->update();
+
{ //profile
profile_endtime = OS::get_singleton()->get_ticks_usec();
- p_space->set_elapsed_time(Space3DSW::ELAPSED_TIME_INTEGRATE_FORCES, profile_endtime - profile_begtime);
+ p_space->set_elapsed_time(GodotSpace3D::ELAPSED_TIME_INTEGRATE_FORCES, profile_endtime - profile_begtime);
profile_begtime = profile_endtime;
}
@@ -229,11 +233,11 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) {
uint32_t island_count = 0;
- const SelfList<Area3DSW>::List &aml = p_space->get_moved_area_list();
+ const SelfList<GodotArea3D>::List &aml = p_space->get_moved_area_list();
while (aml.first()) {
- for (const Set<Constraint3DSW *>::Element *E = aml.first()->self()->get_constraints().front(); E; E = E->next()) {
- Constraint3DSW *constraint = E->get();
+ for (const Set<GodotConstraint3D *>::Element *E = aml.first()->self()->get_constraints().front(); E; E = E->next()) {
+ GodotConstraint3D *constraint = E->get();
if (constraint->get_island_step() == _step) {
continue;
}
@@ -244,13 +248,13 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) {
if (constraint_islands.size() < island_count) {
constraint_islands.resize(island_count);
}
- LocalVector<Constraint3DSW *> &constraint_island = constraint_islands[island_count - 1];
+ LocalVector<GodotConstraint3D *> &constraint_island = constraint_islands[island_count - 1];
constraint_island.clear();
all_constraints.push_back(constraint);
constraint_island.push_back(constraint);
}
- p_space->area_remove_from_moved_list((SelfList<Area3DSW> *)aml.first()); //faster to remove here
+ p_space->area_remove_from_moved_list((SelfList<GodotArea3D> *)aml.first()); //faster to remove here
}
/* GENERATE CONSTRAINT ISLANDS FOR ACTIVE RIGID BODIES */
@@ -260,14 +264,14 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) {
uint32_t body_island_count = 0;
while (b) {
- Body3DSW *body = b->self();
+ GodotBody3D *body = b->self();
if (body->get_island_step() != _step) {
++body_island_count;
if (body_islands.size() < body_island_count) {
body_islands.resize(body_island_count);
}
- LocalVector<Body3DSW *> &body_island = body_islands[body_island_count - 1];
+ LocalVector<GodotBody3D *> &body_island = body_islands[body_island_count - 1];
body_island.clear();
body_island.reserve(BODY_ISLAND_SIZE_RESERVE);
@@ -275,7 +279,7 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) {
if (constraint_islands.size() < island_count) {
constraint_islands.resize(island_count);
}
- LocalVector<Constraint3DSW *> &constraint_island = constraint_islands[island_count - 1];
+ LocalVector<GodotConstraint3D *> &constraint_island = constraint_islands[island_count - 1];
constraint_island.clear();
constraint_island.reserve(ISLAND_SIZE_RESERVE);
@@ -296,14 +300,14 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) {
sb = soft_body_list->first();
while (sb) {
- SoftBody3DSW *soft_body = sb->self();
+ GodotSoftBody3D *soft_body = sb->self();
if (soft_body->get_island_step() != _step) {
++body_island_count;
if (body_islands.size() < body_island_count) {
body_islands.resize(body_island_count);
}
- LocalVector<Body3DSW *> &body_island = body_islands[body_island_count - 1];
+ LocalVector<GodotBody3D *> &body_island = body_islands[body_island_count - 1];
body_island.clear();
body_island.reserve(BODY_ISLAND_SIZE_RESERVE);
@@ -311,7 +315,7 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) {
if (constraint_islands.size() < island_count) {
constraint_islands.resize(island_count);
}
- LocalVector<Constraint3DSW *> &constraint_island = constraint_islands[island_count - 1];
+ LocalVector<GodotConstraint3D *> &constraint_island = constraint_islands[island_count - 1];
constraint_island.clear();
constraint_island.reserve(ISLAND_SIZE_RESERVE);
@@ -332,18 +336,18 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) {
{ //profile
profile_endtime = OS::get_singleton()->get_ticks_usec();
- p_space->set_elapsed_time(Space3DSW::ELAPSED_TIME_GENERATE_ISLANDS, profile_endtime - profile_begtime);
+ p_space->set_elapsed_time(GodotSpace3D::ELAPSED_TIME_GENERATE_ISLANDS, profile_endtime - profile_begtime);
profile_begtime = profile_endtime;
}
/* SETUP CONSTRAINTS / PROCESS COLLISIONS */
uint32_t total_contraint_count = all_constraints.size();
- work_pool.do_work(total_contraint_count, this, &Step3DSW::_setup_contraint, nullptr);
+ work_pool.do_work(total_contraint_count, this, &GodotStep3D::_setup_contraint, nullptr);
{ //profile
profile_endtime = OS::get_singleton()->get_ticks_usec();
- p_space->set_elapsed_time(Space3DSW::ELAPSED_TIME_SETUP_CONSTRAINTS, profile_endtime - profile_begtime);
+ p_space->set_elapsed_time(GodotSpace3D::ELAPSED_TIME_SETUP_CONSTRAINTS, profile_endtime - profile_begtime);
profile_begtime = profile_endtime;
}
@@ -358,15 +362,11 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) {
// Warning: _solve_island modifies the constraint islands for optimization purpose,
// their content is not reliable after these calls and shouldn't be used anymore.
- if (island_count > 1) {
- work_pool.do_work(island_count, this, &Step3DSW::_solve_island, nullptr);
- } else if (island_count > 0) {
- _solve_island(0);
- }
+ work_pool.do_work(island_count, this, &GodotStep3D::_solve_island, nullptr);
{ //profile
profile_endtime = OS::get_singleton()->get_ticks_usec();
- p_space->set_elapsed_time(Space3DSW::ELAPSED_TIME_SOLVE_CONSTRAINTS, profile_endtime - profile_begtime);
+ p_space->set_elapsed_time(GodotSpace3D::ELAPSED_TIME_SOLVE_CONSTRAINTS, profile_endtime - profile_begtime);
profile_begtime = profile_endtime;
}
@@ -374,7 +374,7 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) {
b = body_list->first();
while (b) {
- const SelfList<Body3DSW> *n = b->next();
+ const SelfList<GodotBody3D> *n = b->next();
b->self()->integrate_velocities(p_delta);
b = n;
}
@@ -395,18 +395,17 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) {
{ //profile
profile_endtime = OS::get_singleton()->get_ticks_usec();
- p_space->set_elapsed_time(Space3DSW::ELAPSED_TIME_INTEGRATE_VELOCITIES, profile_endtime - profile_begtime);
+ p_space->set_elapsed_time(GodotSpace3D::ELAPSED_TIME_INTEGRATE_VELOCITIES, profile_endtime - profile_begtime);
profile_begtime = profile_endtime;
}
all_constraints.clear();
- p_space->update();
p_space->unlock();
_step++;
}
-Step3DSW::Step3DSW() {
+GodotStep3D::GodotStep3D() {
body_islands.reserve(BODY_ISLAND_COUNT_RESERVE);
constraint_islands.reserve(ISLAND_COUNT_RESERVE);
all_constraints.reserve(CONSTRAINT_COUNT_RESERVE);
@@ -414,6 +413,6 @@ Step3DSW::Step3DSW() {
work_pool.init();
}
-Step3DSW::~Step3DSW() {
+GodotStep3D::~GodotStep3D() {
work_pool.finish();
}
diff --git a/servers/physics_3d/step_3d_sw.h b/servers/physics_3d/godot_step_3d.h
index f2f879104a..6d975b0dd3 100644
--- a/servers/physics_3d/step_3d_sw.h
+++ b/servers/physics_3d/godot_step_3d.h
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* step_3d_sw.h */
+/* godot_step_3d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,15 +28,15 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef STEP_SW_H
-#define STEP_SW_H
+#ifndef GODOT_STEP_3D_H
+#define GODOT_STEP_3D_H
-#include "space_3d_sw.h"
+#include "godot_space_3d.h"
#include "core/templates/local_vector.h"
#include "core/templates/thread_work_pool.h"
-class Step3DSW {
+class GodotStep3D {
uint64_t _step = 1;
int iterations = 0;
@@ -44,21 +44,21 @@ class Step3DSW {
ThreadWorkPool work_pool;
- LocalVector<LocalVector<Body3DSW *>> body_islands;
- LocalVector<LocalVector<Constraint3DSW *>> constraint_islands;
- LocalVector<Constraint3DSW *> all_constraints;
+ LocalVector<LocalVector<GodotBody3D *>> body_islands;
+ LocalVector<LocalVector<GodotConstraint3D *>> constraint_islands;
+ LocalVector<GodotConstraint3D *> all_constraints;
- void _populate_island(Body3DSW *p_body, LocalVector<Body3DSW *> &p_body_island, LocalVector<Constraint3DSW *> &p_constraint_island);
- void _populate_island_soft_body(SoftBody3DSW *p_soft_body, LocalVector<Body3DSW *> &p_body_island, LocalVector<Constraint3DSW *> &p_constraint_island);
+ void _populate_island(GodotBody3D *p_body, LocalVector<GodotBody3D *> &p_body_island, LocalVector<GodotConstraint3D *> &p_constraint_island);
+ void _populate_island_soft_body(GodotSoftBody3D *p_soft_body, LocalVector<GodotBody3D *> &p_body_island, LocalVector<GodotConstraint3D *> &p_constraint_island);
void _setup_contraint(uint32_t p_constraint_index, void *p_userdata = nullptr);
- void _pre_solve_island(LocalVector<Constraint3DSW *> &p_constraint_island) const;
+ void _pre_solve_island(LocalVector<GodotConstraint3D *> &p_constraint_island) const;
void _solve_island(uint32_t p_island_index, void *p_userdata = nullptr);
- void _check_suspend(const LocalVector<Body3DSW *> &p_body_island) const;
+ void _check_suspend(const LocalVector<GodotBody3D *> &p_body_island) const;
public:
- void step(Space3DSW *p_space, real_t p_delta, int p_iterations);
- Step3DSW();
- ~Step3DSW();
+ void step(GodotSpace3D *p_space, real_t p_delta);
+ GodotStep3D();
+ ~GodotStep3D();
};
-#endif // STEP__SW_H
+#endif // GODOT_STEP_3D_H
diff --git a/servers/physics_3d/joints/cone_twist_joint_3d_sw.cpp b/servers/physics_3d/joints/godot_cone_twist_joint_3d.cpp
index bb9cc1bf67..dc4858ff9a 100644
--- a/servers/physics_3d/joints/cone_twist_joint_3d_sw.cpp
+++ b/servers/physics_3d/joints/godot_cone_twist_joint_3d.cpp
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* cone_twist_joint_3d_sw.cpp */
+/* godot_cone_twist_joint_3d.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -49,7 +49,7 @@ subject to the following restrictions:
Written by: Marcus Hennix
*/
-#include "cone_twist_joint_3d_sw.h"
+#include "godot_cone_twist_joint_3d.h"
static void plane_space(const Vector3 &n, Vector3 &p, Vector3 &q) {
if (Math::abs(n.z) > Math_SQRT12) {
@@ -84,8 +84,8 @@ static _FORCE_INLINE_ real_t atan2fast(real_t y, real_t x) {
return (y < 0.0f) ? -angle : angle;
}
-ConeTwistJoint3DSW::ConeTwistJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform3D &rbAFrame, const Transform3D &rbBFrame) :
- Joint3DSW(_arr, 2) {
+GodotConeTwistJoint3D::GodotConeTwistJoint3D(GodotBody3D *rbA, GodotBody3D *rbB, const Transform3D &rbAFrame, const Transform3D &rbBFrame) :
+ GodotJoint3D(_arr, 2) {
A = rbA;
B = rbB;
@@ -96,7 +96,7 @@ ConeTwistJoint3DSW::ConeTwistJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Trans
B->add_constraint(this, 1);
}
-bool ConeTwistJoint3DSW::setup(real_t p_timestep) {
+bool GodotConeTwistJoint3D::setup(real_t p_timestep) {
dynamic_A = (A->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC);
dynamic_B = (B->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC);
@@ -129,16 +129,18 @@ bool ConeTwistJoint3DSW::setup(real_t p_timestep) {
plane_space(normal[0], normal[1], normal[2]);
for (int i = 0; i < 3; i++) {
- memnew_placement(&m_jac[i], JacobianEntry3DSW(
- A->get_principal_inertia_axes().transposed(),
- B->get_principal_inertia_axes().transposed(),
- pivotAInW - A->get_transform().origin - A->get_center_of_mass(),
- pivotBInW - B->get_transform().origin - B->get_center_of_mass(),
- normal[i],
- A->get_inv_inertia(),
- A->get_inv_mass(),
- B->get_inv_inertia(),
- B->get_inv_mass()));
+ memnew_placement(
+ &m_jac[i],
+ GodotJacobianEntry3D(
+ A->get_principal_inertia_axes().transposed(),
+ B->get_principal_inertia_axes().transposed(),
+ pivotAInW - A->get_transform().origin - A->get_center_of_mass(),
+ pivotBInW - B->get_transform().origin - B->get_center_of_mass(),
+ normal[i],
+ A->get_inv_inertia(),
+ A->get_inv_mass(),
+ B->get_inv_inertia(),
+ B->get_inv_mass()));
}
}
@@ -192,8 +194,7 @@ bool ConeTwistJoint3DSW::setup(real_t p_timestep) {
real_t swingAxisSign = (b2Axis1.dot(b1Axis1) >= 0.0f) ? 1.0f : -1.0f;
m_swingAxis *= swingAxisSign;
- m_kSwing = real_t(1.) / (A->compute_angular_impulse_denominator(m_swingAxis) +
- B->compute_angular_impulse_denominator(m_swingAxis));
+ m_kSwing = real_t(1.) / (A->compute_angular_impulse_denominator(m_swingAxis) + B->compute_angular_impulse_denominator(m_swingAxis));
}
// Twist limits
@@ -212,8 +213,7 @@ bool ConeTwistJoint3DSW::setup(real_t p_timestep) {
m_twistAxis.normalize();
m_twistAxis *= -1.0f;
- m_kTwist = real_t(1.) / (A->compute_angular_impulse_denominator(m_twistAxis) +
- B->compute_angular_impulse_denominator(m_twistAxis));
+ m_kTwist = real_t(1.) / (A->compute_angular_impulse_denominator(m_twistAxis) + B->compute_angular_impulse_denominator(m_twistAxis));
} else if (twist > m_twistSpan * lockedFreeFactor) {
m_twistCorrection = (twist - m_twistSpan);
@@ -222,15 +222,14 @@ bool ConeTwistJoint3DSW::setup(real_t p_timestep) {
m_twistAxis = (b2Axis1 + b1Axis1) * 0.5f;
m_twistAxis.normalize();
- m_kTwist = real_t(1.) / (A->compute_angular_impulse_denominator(m_twistAxis) +
- B->compute_angular_impulse_denominator(m_twistAxis));
+ m_kTwist = real_t(1.) / (A->compute_angular_impulse_denominator(m_twistAxis) + B->compute_angular_impulse_denominator(m_twistAxis));
}
}
return true;
}
-void ConeTwistJoint3DSW::solve(real_t p_timestep) {
+void GodotConeTwistJoint3D::solve(real_t p_timestep) {
Vector3 pivotAInW = A->get_transform().xform(m_rbAFrame.origin);
Vector3 pivotBInW = B->get_transform().xform(m_rbBFrame.origin);
@@ -312,7 +311,7 @@ void ConeTwistJoint3DSW::solve(real_t p_timestep) {
}
}
-void ConeTwistJoint3DSW::set_param(PhysicsServer3D::ConeTwistJointParam p_param, real_t p_value) {
+void GodotConeTwistJoint3D::set_param(PhysicsServer3D::ConeTwistJointParam p_param, real_t p_value) {
switch (p_param) {
case PhysicsServer3D::CONE_TWIST_JOINT_SWING_SPAN: {
m_swingSpan1 = p_value;
@@ -335,7 +334,7 @@ void ConeTwistJoint3DSW::set_param(PhysicsServer3D::ConeTwistJointParam p_param,
}
}
-real_t ConeTwistJoint3DSW::get_param(PhysicsServer3D::ConeTwistJointParam p_param) const {
+real_t GodotConeTwistJoint3D::get_param(PhysicsServer3D::ConeTwistJointParam p_param) const {
switch (p_param) {
case PhysicsServer3D::CONE_TWIST_JOINT_SWING_SPAN: {
return m_swingSpan1;
diff --git a/servers/physics_3d/joints/cone_twist_joint_3d_sw.h b/servers/physics_3d/joints/godot_cone_twist_joint_3d.h
index bf7e593820..fdcc2ceea3 100644
--- a/servers/physics_3d/joints/cone_twist_joint_3d_sw.h
+++ b/servers/physics_3d/joints/godot_cone_twist_joint_3d.h
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* cone_twist_joint_3d_sw.h */
+/* godot_cone_twist_joint_3d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -34,7 +34,7 @@ Adapted to Godot from the Bullet library.
/*
Bullet Continuous Collision Detection and Physics Library
-ConeTwistJointSW is Copyright (c) 2007 Starbreeze Studios
+GodotConeTwistJoint3D is Copyright (c) 2007 Starbreeze Studios
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
@@ -49,28 +49,28 @@ subject to the following restrictions:
Written by: Marcus Hennix
*/
-#ifndef CONE_TWIST_JOINT_SW_H
-#define CONE_TWIST_JOINT_SW_H
+#ifndef GODOT_CONE_TWIST_JOINT_3D_H
+#define GODOT_CONE_TWIST_JOINT_3D_H
-#include "servers/physics_3d/joints/jacobian_entry_3d_sw.h"
-#include "servers/physics_3d/joints_3d_sw.h"
+#include "servers/physics_3d/godot_joint_3d.h"
+#include "servers/physics_3d/joints/godot_jacobian_entry_3d.h"
-///ConeTwistJointSW can be used to simulate ragdoll joints (upper arm, leg etc)
-class ConeTwistJoint3DSW : public Joint3DSW {
+// GodotConeTwistJoint3D can be used to simulate ragdoll joints (upper arm, leg etc).
+class GodotConeTwistJoint3D : public GodotJoint3D {
#ifdef IN_PARALLELL_SOLVER
public:
#endif
union {
struct {
- Body3DSW *A;
- Body3DSW *B;
+ GodotBody3D *A;
+ GodotBody3D *B;
};
- Body3DSW *_arr[2] = { nullptr, nullptr };
+ GodotBody3D *_arr[2] = { nullptr, nullptr };
};
- JacobianEntry3DSW m_jac[3] = {}; //3 orthogonal linear constraints
+ GodotJacobianEntry3D m_jac[3] = {}; //3 orthogonal linear constraints
real_t m_appliedImpulse = 0.0;
Transform3D m_rbAFrame;
@@ -107,7 +107,7 @@ public:
virtual bool setup(real_t p_step) override;
virtual void solve(real_t p_step) override;
- ConeTwistJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform3D &rbAFrame, const Transform3D &rbBFrame);
+ GodotConeTwistJoint3D(GodotBody3D *rbA, GodotBody3D *rbB, const Transform3D &rbAFrame, const Transform3D &rbBFrame);
void setAngularOnly(bool angularOnly) {
m_angularOnly = angularOnly;
@@ -139,4 +139,4 @@ public:
real_t get_param(PhysicsServer3D::ConeTwistJointParam p_param) const;
};
-#endif // CONE_TWIST_JOINT_SW_H
+#endif // GODOT_CONE_TWIST_JOINT_3D_H
diff --git a/servers/physics_3d/joints/generic_6dof_joint_3d_sw.cpp b/servers/physics_3d/joints/godot_generic_6dof_joint_3d.cpp
index 56aba24b42..41e9bf06bb 100644
--- a/servers/physics_3d/joints/generic_6dof_joint_3d_sw.cpp
+++ b/servers/physics_3d/joints/godot_generic_6dof_joint_3d.cpp
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* generic_6dof_joint_3d_sw.cpp */
+/* godot_generic_6dof_joint_3d.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -49,18 +49,18 @@ subject to the following restrictions:
/*
2007-09-09
-Generic6DOFJointSW Refactored by Francisco Le?n
+GodotGeneric6DOFJoint3D Refactored by Francisco Le?n
email: projectileman@yahoo.com
http://gimpact.sf.net
*/
-#include "generic_6dof_joint_3d_sw.h"
+#include "godot_generic_6dof_joint_3d.h"
#define GENERIC_D6_DISABLE_WARMSTARTING 1
-//////////////////////////// G6DOFRotationalLimitMotorSW ////////////////////////////////////
+//////////////////////////// GodotG6DOFRotationalLimitMotor3D ////////////////////////////////////
-int G6DOFRotationalLimitMotor3DSW::testLimitValue(real_t test_value) {
+int GodotG6DOFRotationalLimitMotor3D::testLimitValue(real_t test_value) {
if (m_loLimit > m_hiLimit) {
m_currentLimit = 0; //Free from violation
return 0;
@@ -80,9 +80,9 @@ int G6DOFRotationalLimitMotor3DSW::testLimitValue(real_t test_value) {
return 0;
}
-real_t G6DOFRotationalLimitMotor3DSW::solveAngularLimits(
+real_t GodotG6DOFRotationalLimitMotor3D::solveAngularLimits(
real_t timeStep, Vector3 &axis, real_t jacDiagABInv,
- Body3DSW *body0, Body3DSW *body1, bool p_body0_dynamic, bool p_body1_dynamic) {
+ GodotBody3D *body0, GodotBody3D *body1, bool p_body0_dynamic, bool p_body1_dynamic) {
if (!needApplyTorques()) {
return 0.0f;
}
@@ -148,14 +148,13 @@ real_t G6DOFRotationalLimitMotor3DSW::solveAngularLimits(
return clippedMotorImpulse;
}
-//////////////////////////// End G6DOFRotationalLimitMotorSW ////////////////////////////////////
+//////////////////////////// GodotG6DOFTranslationalLimitMotor3D ////////////////////////////////////
-//////////////////////////// G6DOFTranslationalLimitMotorSW ////////////////////////////////////
-real_t G6DOFTranslationalLimitMotor3DSW::solveLinearAxis(
+real_t GodotG6DOFTranslationalLimitMotor3D::solveLinearAxis(
real_t timeStep,
real_t jacDiagABInv,
- Body3DSW *body1, const Vector3 &pointInA,
- Body3DSW *body2, const Vector3 &pointInB,
+ GodotBody3D *body1, const Vector3 &pointInA,
+ GodotBody3D *body2, const Vector3 &pointInB,
bool p_body1_dynamic, bool p_body2_dynamic,
int limit_index,
const Vector3 &axis_normal_on_a,
@@ -217,10 +216,10 @@ real_t G6DOFTranslationalLimitMotor3DSW::solveLinearAxis(
return normalImpulse;
}
-//////////////////////////// G6DOFTranslationalLimitMotorSW ////////////////////////////////////
+//////////////////////////// GodotGeneric6DOFJoint3D ////////////////////////////////////
-Generic6DOFJoint3DSW::Generic6DOFJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform3D &frameInA, const Transform3D &frameInB, bool useLinearReferenceFrameA) :
- Joint3DSW(_arr, 2),
+GodotGeneric6DOFJoint3D::GodotGeneric6DOFJoint3D(GodotBody3D *rbA, GodotBody3D *rbB, const Transform3D &frameInA, const Transform3D &frameInB, bool useLinearReferenceFrameA) :
+ GodotJoint3D(_arr, 2),
m_frameInA(frameInA),
m_frameInB(frameInB),
m_useLinearReferenceFrameA(useLinearReferenceFrameA) {
@@ -230,10 +229,10 @@ Generic6DOFJoint3DSW::Generic6DOFJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const T
B->add_constraint(this, 1);
}
-void Generic6DOFJoint3DSW::calculateAngleInfo() {
+void GodotGeneric6DOFJoint3D::calculateAngleInfo() {
Basis relative_frame = m_calculatedTransformB.basis.inverse() * m_calculatedTransformA.basis;
- m_calculatedAxisAngleDiff = relative_frame.get_euler_xyz();
+ m_calculatedAxisAngleDiff = relative_frame.get_euler(Basis::EULER_ORDER_XYZ);
// in euler angle mode we do not actually constrain the angular velocity
// along the axes axis[0] and axis[2] (although we do use axis[1]) :
@@ -270,38 +269,43 @@ void Generic6DOFJoint3DSW::calculateAngleInfo() {
*/
}
-void Generic6DOFJoint3DSW::calculateTransforms() {
+void GodotGeneric6DOFJoint3D::calculateTransforms() {
m_calculatedTransformA = A->get_transform() * m_frameInA;
m_calculatedTransformB = B->get_transform() * m_frameInB;
calculateAngleInfo();
}
-void Generic6DOFJoint3DSW::buildLinearJacobian(
- JacobianEntry3DSW &jacLinear, const Vector3 &normalWorld,
+void GodotGeneric6DOFJoint3D::buildLinearJacobian(
+ GodotJacobianEntry3D &jacLinear, const Vector3 &normalWorld,
const Vector3 &pivotAInW, const Vector3 &pivotBInW) {
- memnew_placement(&jacLinear, JacobianEntry3DSW(
- A->get_principal_inertia_axes().transposed(),
- B->get_principal_inertia_axes().transposed(),
- pivotAInW - A->get_transform().origin - A->get_center_of_mass(),
- pivotBInW - B->get_transform().origin - B->get_center_of_mass(),
- normalWorld,
- A->get_inv_inertia(),
- A->get_inv_mass(),
- B->get_inv_inertia(),
- B->get_inv_mass()));
+ memnew_placement(
+ &jacLinear,
+ GodotJacobianEntry3D(
+ A->get_principal_inertia_axes().transposed(),
+ B->get_principal_inertia_axes().transposed(),
+ pivotAInW - A->get_transform().origin - A->get_center_of_mass(),
+ pivotBInW - B->get_transform().origin - B->get_center_of_mass(),
+ normalWorld,
+ A->get_inv_inertia(),
+ A->get_inv_mass(),
+ B->get_inv_inertia(),
+ B->get_inv_mass()));
}
-void Generic6DOFJoint3DSW::buildAngularJacobian(
- JacobianEntry3DSW &jacAngular, const Vector3 &jointAxisW) {
- memnew_placement(&jacAngular, JacobianEntry3DSW(jointAxisW,
- A->get_principal_inertia_axes().transposed(),
- B->get_principal_inertia_axes().transposed(),
- A->get_inv_inertia(),
- B->get_inv_inertia()));
+void GodotGeneric6DOFJoint3D::buildAngularJacobian(
+ GodotJacobianEntry3D &jacAngular, const Vector3 &jointAxisW) {
+ memnew_placement(
+ &jacAngular,
+ GodotJacobianEntry3D(
+ jointAxisW,
+ A->get_principal_inertia_axes().transposed(),
+ B->get_principal_inertia_axes().transposed(),
+ A->get_inv_inertia(),
+ B->get_inv_inertia()));
}
-bool Generic6DOFJoint3DSW::testAngularLimitMotor(int axis_index) {
+bool GodotGeneric6DOFJoint3D::testAngularLimitMotor(int axis_index) {
real_t angle = m_calculatedAxisAngleDiff[axis_index];
//test limits
@@ -309,7 +313,7 @@ bool Generic6DOFJoint3DSW::testAngularLimitMotor(int axis_index) {
return m_angularLimits[axis_index].needApplyTorques();
}
-bool Generic6DOFJoint3DSW::setup(real_t p_timestep) {
+bool GodotGeneric6DOFJoint3D::setup(real_t p_timestep) {
dynamic_A = (A->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC);
dynamic_B = (B->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC);
@@ -365,7 +369,7 @@ bool Generic6DOFJoint3DSW::setup(real_t p_timestep) {
return true;
}
-void Generic6DOFJoint3DSW::solve(real_t p_timestep) {
+void GodotGeneric6DOFJoint3D::solve(real_t p_timestep) {
m_timeStep = p_timestep;
//calculateTransforms();
@@ -414,19 +418,19 @@ void Generic6DOFJoint3DSW::solve(real_t p_timestep) {
}
}
-void Generic6DOFJoint3DSW::updateRHS(real_t timeStep) {
+void GodotGeneric6DOFJoint3D::updateRHS(real_t timeStep) {
(void)timeStep;
}
-Vector3 Generic6DOFJoint3DSW::getAxis(int axis_index) const {
+Vector3 GodotGeneric6DOFJoint3D::getAxis(int axis_index) const {
return m_calculatedAxis[axis_index];
}
-real_t Generic6DOFJoint3DSW::getAngle(int axis_index) const {
+real_t GodotGeneric6DOFJoint3D::getAngle(int axis_index) const {
return m_calculatedAxisAngleDiff[axis_index];
}
-void Generic6DOFJoint3DSW::calcAnchorPos() {
+void GodotGeneric6DOFJoint3D::calcAnchorPos() {
real_t imA = A->get_inv_mass();
real_t imB = B->get_inv_mass();
real_t weight;
@@ -438,9 +442,9 @@ void Generic6DOFJoint3DSW::calcAnchorPos() {
const Vector3 &pA = m_calculatedTransformA.origin;
const Vector3 &pB = m_calculatedTransformB.origin;
m_AnchorPos = pA * weight + pB * (real_t(1.0) - weight);
-} // Generic6DOFJointSW::calcAnchorPos()
+}
-void Generic6DOFJoint3DSW::set_param(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisParam p_param, real_t p_value) {
+void GodotGeneric6DOFJoint3D::set_param(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisParam p_param, real_t p_value) {
ERR_FAIL_INDEX(p_axis, 3);
switch (p_param) {
case PhysicsServer3D::G6DOF_JOINT_LINEAR_LOWER_LIMIT: {
@@ -527,7 +531,7 @@ void Generic6DOFJoint3DSW::set_param(Vector3::Axis p_axis, PhysicsServer3D::G6DO
}
}
-real_t Generic6DOFJoint3DSW::get_param(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisParam p_param) const {
+real_t GodotGeneric6DOFJoint3D::get_param(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisParam p_param) const {
ERR_FAIL_INDEX_V(p_axis, 3, 0);
switch (p_param) {
case PhysicsServer3D::G6DOF_JOINT_LINEAR_LOWER_LIMIT: {
@@ -615,7 +619,7 @@ real_t Generic6DOFJoint3DSW::get_param(Vector3::Axis p_axis, PhysicsServer3D::G6
return 0;
}
-void Generic6DOFJoint3DSW::set_flag(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisFlag p_flag, bool p_value) {
+void GodotGeneric6DOFJoint3D::set_flag(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisFlag p_flag, bool p_value) {
ERR_FAIL_INDEX(p_axis, 3);
switch (p_flag) {
@@ -642,7 +646,7 @@ void Generic6DOFJoint3DSW::set_flag(Vector3::Axis p_axis, PhysicsServer3D::G6DOF
}
}
-bool Generic6DOFJoint3DSW::get_flag(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisFlag p_flag) const {
+bool GodotGeneric6DOFJoint3D::get_flag(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisFlag p_flag) const {
ERR_FAIL_INDEX_V(p_axis, 3, 0);
switch (p_flag) {
case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT: {
diff --git a/servers/physics_3d/joints/generic_6dof_joint_3d_sw.h b/servers/physics_3d/joints/godot_generic_6dof_joint_3d.h
index 6492e40393..bcf2d18647 100644
--- a/servers/physics_3d/joints/generic_6dof_joint_3d_sw.h
+++ b/servers/physics_3d/joints/godot_generic_6dof_joint_3d.h
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* generic_6dof_joint_3d_sw.h */
+/* godot_generic_6dof_joint_3d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -32,11 +32,11 @@
Adapted to Godot from the Bullet library.
*/
-#ifndef GENERIC_6DOF_JOINT_SW_H
-#define GENERIC_6DOF_JOINT_SW_H
+#ifndef GODOT_GENERIC_6DOF_JOINT_3D_H
+#define GODOT_GENERIC_6DOF_JOINT_3D_H
-#include "servers/physics_3d/joints/jacobian_entry_3d_sw.h"
-#include "servers/physics_3d/joints_3d_sw.h"
+#include "servers/physics_3d/godot_joint_3d.h"
+#include "servers/physics_3d/joints/godot_jacobian_entry_3d.h"
/*
Bullet Continuous Collision Detection and Physics Library
@@ -55,13 +55,13 @@ subject to the following restrictions:
/*
2007-09-09
-Generic6DOFJointSW Refactored by Francisco Le?n
+GodotGeneric6DOFJoint3D Refactored by Francisco Le?n
email: projectileman@yahoo.com
http://gimpact.sf.net
*/
//! Rotation Limit structure for generic joints
-class G6DOFRotationalLimitMotor3DSW {
+class GodotG6DOFRotationalLimitMotor3D {
public:
//! limit_parameters
//!@{
@@ -86,29 +86,25 @@ public:
real_t m_accumulatedImpulse = 0.0;
//!@}
- G6DOFRotationalLimitMotor3DSW() {}
+ GodotG6DOFRotationalLimitMotor3D() {}
- //! Is limited
bool isLimited() {
return (m_loLimit < m_hiLimit);
}
- //! Need apply correction
+ // Need apply correction.
bool needApplyTorques() {
return (m_enableMotor || m_currentLimit != 0);
}
- //! calculates error
- /*!
- calculates m_currentLimit and m_currentLimitError.
- */
+ // Calculates m_currentLimit and m_currentLimitError.
int testLimitValue(real_t test_value);
- //! apply the correction impulses for two bodies
- real_t solveAngularLimits(real_t timeStep, Vector3 &axis, real_t jacDiagABInv, Body3DSW *body0, Body3DSW *body1, bool p_body0_dynamic, bool p_body1_dynamic);
+ // Apply the correction impulses for two bodies.
+ real_t solveAngularLimits(real_t timeStep, Vector3 &axis, real_t jacDiagABInv, GodotBody3D *body0, GodotBody3D *body1, bool p_body0_dynamic, bool p_body1_dynamic);
};
-class G6DOFTranslationalLimitMotor3DSW {
+class GodotG6DOFTranslationalLimitMotor3D {
public:
Vector3 m_lowerLimit = Vector3(0.0, 0.0, 0.0); //!< the constraint lower limits
Vector3 m_upperLimit = Vector3(0.0, 0.0, 0.0); //!< the constraint upper limits
@@ -123,11 +119,11 @@ public:
//! Test limit
/*!
- - free means upper < lower,
- - locked means upper == lower
- - limited means upper > lower
- - limitIndex: first 3 are linear, next 3 are angular
- */
+ * - free means upper < lower,
+ * - locked means upper == lower
+ * - limited means upper > lower
+ * - limitIndex: first 3 are linear, next 3 are angular
+ */
inline bool isLimited(int limitIndex) {
return (m_upperLimit[limitIndex] >= m_lowerLimit[limitIndex]);
}
@@ -135,23 +131,23 @@ public:
real_t solveLinearAxis(
real_t timeStep,
real_t jacDiagABInv,
- Body3DSW *body1, const Vector3 &pointInA,
- Body3DSW *body2, const Vector3 &pointInB,
+ GodotBody3D *body1, const Vector3 &pointInA,
+ GodotBody3D *body2, const Vector3 &pointInB,
bool p_body1_dynamic, bool p_body2_dynamic,
int limit_index,
const Vector3 &axis_normal_on_a,
const Vector3 &anchorPos);
};
-class Generic6DOFJoint3DSW : public Joint3DSW {
+class GodotGeneric6DOFJoint3D : public GodotJoint3D {
protected:
union {
struct {
- Body3DSW *A;
- Body3DSW *B;
+ GodotBody3D *A;
+ GodotBody3D *B;
};
- Body3DSW *_arr[2] = { nullptr, nullptr };
+ GodotBody3D *_arr[2] = { nullptr, nullptr };
};
//! relative_frames
@@ -162,18 +158,18 @@ protected:
//! Jacobians
//!@{
- JacobianEntry3DSW m_jacLinear[3]; //!< 3 orthogonal linear constraints
- JacobianEntry3DSW m_jacAng[3]; //!< 3 orthogonal angular constraints
+ GodotJacobianEntry3D m_jacLinear[3]; //!< 3 orthogonal linear constraints
+ GodotJacobianEntry3D m_jacAng[3]; //!< 3 orthogonal angular constraints
//!@}
//! Linear_Limit_parameters
//!@{
- G6DOFTranslationalLimitMotor3DSW m_linearLimits;
+ GodotG6DOFTranslationalLimitMotor3D m_linearLimits;
//!@}
//! hinge_parameters
//!@{
- G6DOFRotationalLimitMotor3DSW m_angularLimits[3];
+ GodotG6DOFRotationalLimitMotor3D m_angularLimits[3];
//!@}
protected:
@@ -191,45 +187,35 @@ protected:
//!@}
- Generic6DOFJoint3DSW(Generic6DOFJoint3DSW const &) = delete;
- void operator=(Generic6DOFJoint3DSW const &) = delete;
+ GodotGeneric6DOFJoint3D(GodotGeneric6DOFJoint3D const &) = delete;
+ void operator=(GodotGeneric6DOFJoint3D const &) = delete;
void buildLinearJacobian(
- JacobianEntry3DSW &jacLinear, const Vector3 &normalWorld,
+ GodotJacobianEntry3D &jacLinear, const Vector3 &normalWorld,
const Vector3 &pivotAInW, const Vector3 &pivotBInW);
- void buildAngularJacobian(JacobianEntry3DSW &jacAngular, const Vector3 &jointAxisW);
+ void buildAngularJacobian(GodotJacobianEntry3D &jacAngular, const Vector3 &jointAxisW);
//! calcs the euler angles between the two bodies.
void calculateAngleInfo();
public:
- Generic6DOFJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform3D &frameInA, const Transform3D &frameInB, bool useLinearReferenceFrameA);
+ GodotGeneric6DOFJoint3D(GodotBody3D *rbA, GodotBody3D *rbB, const Transform3D &frameInA, const Transform3D &frameInB, bool useLinearReferenceFrameA);
virtual PhysicsServer3D::JointType get_type() const override { return PhysicsServer3D::JOINT_TYPE_6DOF; }
virtual bool setup(real_t p_step) override;
virtual void solve(real_t p_step) override;
- //! Calcs global transform of the offsets
- /*!
- Calcs the global transform for the joint offset for body A an B, and also calcs the agle differences between the bodies.
- \sa Generic6DOFJointSW.getCalculatedTransformA , Generic6DOFJointSW.getCalculatedTransformB, Generic6DOFJointSW.calculateAngleInfo
- */
+ // Calcs the global transform for the joint offset for body A an B, and also calcs the angle differences between the bodies.
void calculateTransforms();
- //! Gets the global transform of the offset for body A
- /*!
- \sa Generic6DOFJointSW.getFrameOffsetA, Generic6DOFJointSW.getFrameOffsetB, Generic6DOFJointSW.calculateAngleInfo.
- */
+ // Gets the global transform of the offset for body A.
const Transform3D &getCalculatedTransformA() const {
return m_calculatedTransformA;
}
- //! Gets the global transform of the offset for body B
- /*!
- \sa Generic6DOFJointSW.getFrameOffsetA, Generic6DOFJointSW.getFrameOffsetB, Generic6DOFJointSW.calculateAngleInfo.
- */
+ // Gets the global transform of the offset for body B.
const Transform3D &getCalculatedTransformB() const {
return m_calculatedTransformB;
}
@@ -250,27 +236,16 @@ public:
return m_frameInB;
}
- //! performs Jacobian calculation, and also calculates angle differences and axis
-
+ // Performs Jacobian calculation, and also calculates angle differences and axis.
void updateRHS(real_t timeStep);
- //! Get the rotation axis in global coordinates
- /*!
- \pre Generic6DOFJointSW.buildJacobian must be called previously.
- */
+ // Get the rotation axis in global coordinates.
Vector3 getAxis(int axis_index) const;
- //! Get the relative Euler angle
- /*!
- \pre Generic6DOFJointSW.buildJacobian must be called previously.
- */
+ // Get the relative Euler angle.
real_t getAngle(int axis_index) const;
- //! Test angular limit.
- /*!
- Calculates angular correction and returns true if limit needs to be corrected.
- \pre Generic6DOFJointSW.buildJacobian must be called previously.
- */
+ // Calculates angular correction and returns true if limit needs to be corrected.
bool testAngularLimitMotor(int axis_index);
void setLinearLowerLimit(const Vector3 &linearLower) {
@@ -293,17 +268,17 @@ public:
m_angularLimits[2].m_hiLimit = angularUpper.z;
}
- //! Retrieves the angular limit information.
- G6DOFRotationalLimitMotor3DSW *getRotationalLimitMotor(int index) {
+ // Retrieves the angular limit information.
+ GodotG6DOFRotationalLimitMotor3D *getRotationalLimitMotor(int index) {
return &m_angularLimits[index];
}
- //! Retrieves the limit information.
- G6DOFTranslationalLimitMotor3DSW *getTranslationalLimitMotor() {
+ // Retrieves the limit information.
+ GodotG6DOFTranslationalLimitMotor3D *getTranslationalLimitMotor() {
return &m_linearLimits;
}
- //first 3 are linear, next 3 are angular
+ // First 3 are linear, next 3 are angular.
void setLimit(int axis, real_t lo, real_t hi) {
if (axis < 3) {
m_linearLimits.m_lowerLimit[axis] = lo;
@@ -316,11 +291,11 @@ public:
//! Test limit
/*!
- - free means upper < lower,
- - locked means upper == lower
- - limited means upper > lower
- - limitIndex: first 3 are linear, next 3 are angular
- */
+ * - free means upper < lower,
+ * - locked means upper == lower
+ * - limited means upper > lower
+ * - limitIndex: first 3 are linear, next 3 are angular
+ */
bool isLimited(int limitIndex) {
if (limitIndex < 3) {
return m_linearLimits.isLimited(limitIndex);
@@ -328,10 +303,10 @@ public:
return m_angularLimits[limitIndex - 3].isLimited();
}
- const Body3DSW *getRigidBodyA() const {
+ const GodotBody3D *getRigidBodyA() const {
return A;
}
- const Body3DSW *getRigidBodyB() const {
+ const GodotBody3D *getRigidBodyB() const {
return B;
}
@@ -344,4 +319,4 @@ public:
bool get_flag(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisFlag p_flag) const;
};
-#endif // GENERIC_6DOF_JOINT_SW_H
+#endif // GODOT_GENERIC_6DOF_JOINT_3D_H
diff --git a/servers/physics_3d/joints/hinge_joint_3d_sw.cpp b/servers/physics_3d/joints/godot_hinge_joint_3d.cpp
index a45fcf7eb5..a7a7843499 100644
--- a/servers/physics_3d/joints/hinge_joint_3d_sw.cpp
+++ b/servers/physics_3d/joints/godot_hinge_joint_3d.cpp
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* hinge_joint_3d_sw.cpp */
+/* godot_hinge_joint_3d.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -47,7 +47,7 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-#include "hinge_joint_3d_sw.h"
+#include "godot_hinge_joint_3d.h"
static void plane_space(const Vector3 &n, Vector3 &p, Vector3 &q) {
if (Math::abs(n.z) > Math_SQRT12) {
@@ -67,8 +67,8 @@ static void plane_space(const Vector3 &n, Vector3 &p, Vector3 &q) {
}
}
-HingeJoint3DSW::HingeJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform3D &frameA, const Transform3D &frameB) :
- Joint3DSW(_arr, 2) {
+GodotHingeJoint3D::GodotHingeJoint3D(GodotBody3D *rbA, GodotBody3D *rbB, const Transform3D &frameA, const Transform3D &frameB) :
+ GodotJoint3D(_arr, 2) {
A = rbA;
B = rbB;
@@ -83,9 +83,9 @@ HingeJoint3DSW::HingeJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform3D &
B->add_constraint(this, 1);
}
-HingeJoint3DSW::HingeJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Vector3 &pivotInA, const Vector3 &pivotInB,
+GodotHingeJoint3D::GodotHingeJoint3D(GodotBody3D *rbA, GodotBody3D *rbB, const Vector3 &pivotInA, const Vector3 &pivotInB,
const Vector3 &axisInA, const Vector3 &axisInB) :
- Joint3DSW(_arr, 2) {
+ GodotJoint3D(_arr, 2) {
A = rbA;
B = rbB;
@@ -124,7 +124,7 @@ HingeJoint3DSW::HingeJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Vector3 &pivo
B->add_constraint(this, 1);
}
-bool HingeJoint3DSW::setup(real_t p_step) {
+bool GodotHingeJoint3D::setup(real_t p_step) {
dynamic_A = (A->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC);
dynamic_B = (B->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC);
@@ -149,16 +149,18 @@ bool HingeJoint3DSW::setup(real_t p_step) {
plane_space(normal[0], normal[1], normal[2]);
for (int i = 0; i < 3; i++) {
- memnew_placement(&m_jac[i], JacobianEntry3DSW(
- A->get_principal_inertia_axes().transposed(),
- B->get_principal_inertia_axes().transposed(),
- pivotAInW - A->get_transform().origin - A->get_center_of_mass(),
- pivotBInW - B->get_transform().origin - B->get_center_of_mass(),
- normal[i],
- A->get_inv_inertia(),
- A->get_inv_mass(),
- B->get_inv_inertia(),
- B->get_inv_mass()));
+ memnew_placement(
+ &m_jac[i],
+ GodotJacobianEntry3D(
+ A->get_principal_inertia_axes().transposed(),
+ B->get_principal_inertia_axes().transposed(),
+ pivotAInW - A->get_transform().origin - A->get_center_of_mass(),
+ pivotBInW - B->get_transform().origin - B->get_center_of_mass(),
+ normal[i],
+ A->get_inv_inertia(),
+ A->get_inv_mass(),
+ B->get_inv_inertia(),
+ B->get_inv_mass()));
}
}
@@ -175,23 +177,32 @@ bool HingeJoint3DSW::setup(real_t p_step) {
Vector3 jointAxis1 = A->get_transform().basis.xform(jointAxis1local);
Vector3 hingeAxisWorld = A->get_transform().basis.xform(m_rbAFrame.basis.get_axis(2));
- memnew_placement(&m_jacAng[0], JacobianEntry3DSW(jointAxis0,
- A->get_principal_inertia_axes().transposed(),
- B->get_principal_inertia_axes().transposed(),
- A->get_inv_inertia(),
- B->get_inv_inertia()));
-
- memnew_placement(&m_jacAng[1], JacobianEntry3DSW(jointAxis1,
- A->get_principal_inertia_axes().transposed(),
- B->get_principal_inertia_axes().transposed(),
- A->get_inv_inertia(),
- B->get_inv_inertia()));
-
- memnew_placement(&m_jacAng[2], JacobianEntry3DSW(hingeAxisWorld,
- A->get_principal_inertia_axes().transposed(),
- B->get_principal_inertia_axes().transposed(),
- A->get_inv_inertia(),
- B->get_inv_inertia()));
+ memnew_placement(
+ &m_jacAng[0],
+ GodotJacobianEntry3D(
+ jointAxis0,
+ A->get_principal_inertia_axes().transposed(),
+ B->get_principal_inertia_axes().transposed(),
+ A->get_inv_inertia(),
+ B->get_inv_inertia()));
+
+ memnew_placement(
+ &m_jacAng[1],
+ GodotJacobianEntry3D(
+ jointAxis1,
+ A->get_principal_inertia_axes().transposed(),
+ B->get_principal_inertia_axes().transposed(),
+ A->get_inv_inertia(),
+ B->get_inv_inertia()));
+
+ memnew_placement(
+ &m_jacAng[2],
+ GodotJacobianEntry3D(
+ hingeAxisWorld,
+ A->get_principal_inertia_axes().transposed(),
+ B->get_principal_inertia_axes().transposed(),
+ A->get_inv_inertia(),
+ B->get_inv_inertia()));
// Compute limit information
real_t hingeAngle = get_hinge_angle();
@@ -220,13 +231,12 @@ bool HingeJoint3DSW::setup(real_t p_step) {
//Compute K = J*W*J' for hinge axis
Vector3 axisA = A->get_transform().basis.xform(m_rbAFrame.basis.get_axis(2));
- m_kHinge = 1.0f / (A->compute_angular_impulse_denominator(axisA) +
- B->compute_angular_impulse_denominator(axisA));
+ m_kHinge = 1.0f / (A->compute_angular_impulse_denominator(axisA) + B->compute_angular_impulse_denominator(axisA));
return true;
}
-void HingeJoint3DSW::solve(real_t p_step) {
+void GodotHingeJoint3D::solve(real_t p_step) {
Vector3 pivotAInW = A->get_transform().xform(m_rbAFrame.origin);
Vector3 pivotBInW = B->get_transform().xform(m_rbBFrame.origin);
@@ -284,7 +294,7 @@ void HingeJoint3DSW::solve(real_t p_step) {
if (len > real_t(0.00001)) {
Vector3 normal = velrelOrthog.normalized();
real_t denom = A->compute_angular_impulse_denominator(normal) +
- B->compute_angular_impulse_denominator(normal);
+ B->compute_angular_impulse_denominator(normal);
// scale for mass and relaxation
velrelOrthog *= (real_t(1.) / denom) * m_relaxationFactor;
}
@@ -295,7 +305,7 @@ void HingeJoint3DSW::solve(real_t p_step) {
if (len2 > real_t(0.00001)) {
Vector3 normal2 = angularError.normalized();
real_t denom2 = A->compute_angular_impulse_denominator(normal2) +
- B->compute_angular_impulse_denominator(normal2);
+ B->compute_angular_impulse_denominator(normal2);
angularError *= (real_t(1.) / denom2) * relaxation;
}
@@ -377,7 +387,7 @@ static _FORCE_INLINE_ real_t atan2fast(real_t y, real_t x) {
return (y < 0.0f) ? -angle : angle;
}
-real_t HingeJoint3DSW::get_hinge_angle() {
+real_t GodotHingeJoint3D::get_hinge_angle() {
const Vector3 refAxis0 = A->get_transform().basis.xform(m_rbAFrame.basis.get_axis(0));
const Vector3 refAxis1 = A->get_transform().basis.xform(m_rbAFrame.basis.get_axis(1));
const Vector3 swingAxis = B->get_transform().basis.xform(m_rbBFrame.basis.get_axis(1));
@@ -385,7 +395,7 @@ real_t HingeJoint3DSW::get_hinge_angle() {
return atan2fast(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1));
}
-void HingeJoint3DSW::set_param(PhysicsServer3D::HingeJointParam p_param, real_t p_value) {
+void GodotHingeJoint3D::set_param(PhysicsServer3D::HingeJointParam p_param, real_t p_value) {
switch (p_param) {
case PhysicsServer3D::HINGE_JOINT_BIAS:
tau = p_value;
@@ -416,7 +426,7 @@ void HingeJoint3DSW::set_param(PhysicsServer3D::HingeJointParam p_param, real_t
}
}
-real_t HingeJoint3DSW::get_param(PhysicsServer3D::HingeJointParam p_param) const {
+real_t GodotHingeJoint3D::get_param(PhysicsServer3D::HingeJointParam p_param) const {
switch (p_param) {
case PhysicsServer3D::HINGE_JOINT_BIAS:
return tau;
@@ -441,7 +451,7 @@ real_t HingeJoint3DSW::get_param(PhysicsServer3D::HingeJointParam p_param) const
return 0;
}
-void HingeJoint3DSW::set_flag(PhysicsServer3D::HingeJointFlag p_flag, bool p_value) {
+void GodotHingeJoint3D::set_flag(PhysicsServer3D::HingeJointFlag p_flag, bool p_value) {
switch (p_flag) {
case PhysicsServer3D::HINGE_JOINT_FLAG_USE_LIMIT:
m_useLimit = p_value;
@@ -454,7 +464,7 @@ void HingeJoint3DSW::set_flag(PhysicsServer3D::HingeJointFlag p_flag, bool p_val
}
}
-bool HingeJoint3DSW::get_flag(PhysicsServer3D::HingeJointFlag p_flag) const {
+bool GodotHingeJoint3D::get_flag(PhysicsServer3D::HingeJointFlag p_flag) const {
switch (p_flag) {
case PhysicsServer3D::HINGE_JOINT_FLAG_USE_LIMIT:
return m_useLimit;
diff --git a/servers/physics_3d/joints/hinge_joint_3d_sw.h b/servers/physics_3d/joints/godot_hinge_joint_3d.h
index a4ceff9ffe..b934540e8d 100644
--- a/servers/physics_3d/joints/hinge_joint_3d_sw.h
+++ b/servers/physics_3d/joints/godot_hinge_joint_3d.h
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* hinge_joint_3d_sw.h */
+/* godot_hinge_joint_3d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -32,11 +32,11 @@
Adapted to Godot from the Bullet library.
*/
-#ifndef HINGE_JOINT_SW_H
-#define HINGE_JOINT_SW_H
+#ifndef GODOT_HINGE_JOINT_3D_H
+#define GODOT_HINGE_JOINT_3D_H
-#include "servers/physics_3d/joints/jacobian_entry_3d_sw.h"
-#include "servers/physics_3d/joints_3d_sw.h"
+#include "servers/physics_3d/godot_joint_3d.h"
+#include "servers/physics_3d/joints/godot_jacobian_entry_3d.h"
/*
Bullet Continuous Collision Detection and Physics Library
@@ -53,18 +53,18 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-class HingeJoint3DSW : public Joint3DSW {
+class GodotHingeJoint3D : public GodotJoint3D {
union {
struct {
- Body3DSW *A;
- Body3DSW *B;
+ GodotBody3D *A;
+ GodotBody3D *B;
};
- Body3DSW *_arr[2] = {};
+ GodotBody3D *_arr[2] = {};
};
- JacobianEntry3DSW m_jac[3]; //3 orthogonal linear constraints
- JacobianEntry3DSW m_jacAng[3]; //2 orthogonal angular constraints+ 1 for limit/motor
+ GodotJacobianEntry3D m_jac[3]; //3 orthogonal linear constraints
+ GodotJacobianEntry3D m_jacAng[3]; //2 orthogonal angular constraints+ 1 for limit/motor
Transform3D m_rbAFrame; // constraint axii. Assumes z is hinge axis.
Transform3D m_rbBFrame;
@@ -109,8 +109,8 @@ public:
void set_flag(PhysicsServer3D::HingeJointFlag p_flag, bool p_value);
bool get_flag(PhysicsServer3D::HingeJointFlag p_flag) const;
- HingeJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform3D &frameA, const Transform3D &frameB);
- HingeJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Vector3 &pivotInA, const Vector3 &pivotInB, const Vector3 &axisInA, const Vector3 &axisInB);
+ GodotHingeJoint3D(GodotBody3D *rbA, GodotBody3D *rbB, const Transform3D &frameA, const Transform3D &frameB);
+ GodotHingeJoint3D(GodotBody3D *rbA, GodotBody3D *rbB, const Vector3 &pivotInA, const Vector3 &pivotInB, const Vector3 &axisInA, const Vector3 &axisInB);
};
-#endif // HINGE_JOINT_SW_H
+#endif // GODOT_HINGE_JOINT_3D_H
diff --git a/servers/physics_3d/joints/jacobian_entry_3d_sw.h b/servers/physics_3d/joints/godot_jacobian_entry_3d.h
index 7294ff78e3..0fe15751d5 100644
--- a/servers/physics_3d/joints/jacobian_entry_3d_sw.h
+++ b/servers/physics_3d/joints/godot_jacobian_entry_3d.h
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* jacobian_entry_3d_sw.h */
+/* godot_jacobian_entry_3d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -32,8 +32,8 @@
Adapted to Godot from the Bullet library.
*/
-#ifndef JACOBIAN_ENTRY_SW_H
-#define JACOBIAN_ENTRY_SW_H
+#ifndef GODOT_JACOBIAN_ENTRY_3D_H
+#define GODOT_JACOBIAN_ENTRY_3D_H
/*
Bullet Continuous Collision Detection and Physics Library
@@ -52,11 +52,11 @@ subject to the following restrictions:
#include "core/math/transform_3d.h"
-class JacobianEntry3DSW {
+class GodotJacobianEntry3D {
public:
- JacobianEntry3DSW() {}
+ GodotJacobianEntry3D() {}
//constraint between two different rigidbodies
- JacobianEntry3DSW(
+ GodotJacobianEntry3D(
const Basis &world2A,
const Basis &world2B,
const Vector3 &rel_pos1, const Vector3 &rel_pos2,
@@ -76,7 +76,7 @@ public:
}
//angular constraint between two different rigidbodies
- JacobianEntry3DSW(const Vector3 &jointAxis,
+ GodotJacobianEntry3D(const Vector3 &jointAxis,
const Basis &world2A,
const Basis &world2B,
const Vector3 &inertiaInvA,
@@ -92,7 +92,7 @@ public:
}
//angular constraint between two different rigidbodies
- JacobianEntry3DSW(const Vector3 &axisInA,
+ GodotJacobianEntry3D(const Vector3 &axisInA,
const Vector3 &axisInB,
const Vector3 &inertiaInvA,
const Vector3 &inertiaInvB) :
@@ -107,7 +107,7 @@ public:
}
//constraint on one rigidbody
- JacobianEntry3DSW(
+ GodotJacobianEntry3D(
const Basis &world2A,
const Vector3 &rel_pos1, const Vector3 &rel_pos2,
const Vector3 &jointAxis,
@@ -126,16 +126,16 @@ public:
real_t getDiagonal() const { return m_Adiag; }
// for two constraints on the same rigidbody (for example vehicle friction)
- real_t getNonDiagonal(const JacobianEntry3DSW &jacB, const real_t massInvA) const {
- const JacobianEntry3DSW &jacA = *this;
+ real_t getNonDiagonal(const GodotJacobianEntry3D &jacB, const real_t massInvA) const {
+ const GodotJacobianEntry3D &jacA = *this;
real_t lin = massInvA * jacA.m_linearJointAxis.dot(jacB.m_linearJointAxis);
real_t ang = jacA.m_0MinvJt.dot(jacB.m_aJ);
return lin + ang;
}
// for two constraints on sharing two same rigidbodies (for example two contact points between two rigidbodies)
- real_t getNonDiagonal(const JacobianEntry3DSW &jacB, const real_t massInvA, const real_t massInvB) const {
- const JacobianEntry3DSW &jacA = *this;
+ real_t getNonDiagonal(const GodotJacobianEntry3D &jacB, const real_t massInvA, const real_t massInvB) const {
+ const GodotJacobianEntry3D &jacA = *this;
Vector3 lin = jacA.m_linearJointAxis * jacB.m_linearJointAxis;
Vector3 ang0 = jacA.m_0MinvJt * jacB.m_aJ;
Vector3 ang1 = jacA.m_1MinvJt * jacB.m_bJ;
@@ -166,4 +166,4 @@ public:
real_t m_Adiag = 1.0;
};
-#endif // JACOBIAN_ENTRY_SW_H
+#endif // GODOT_JACOBIAN_ENTRY_3D_H
diff --git a/servers/physics_3d/joints/pin_joint_3d_sw.cpp b/servers/physics_3d/joints/godot_pin_joint_3d.cpp
index f41151ec0e..c52ea2665c 100644
--- a/servers/physics_3d/joints/pin_joint_3d_sw.cpp
+++ b/servers/physics_3d/joints/godot_pin_joint_3d.cpp
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* pin_joint_3d_sw.cpp */
+/* godot_pin_joint_3d.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -47,9 +47,9 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-#include "pin_joint_3d_sw.h"
+#include "godot_pin_joint_3d.h"
-bool PinJoint3DSW::setup(real_t p_step) {
+bool GodotPinJoint3D::setup(real_t p_step) {
dynamic_A = (A->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC);
dynamic_B = (B->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC);
@@ -63,23 +63,25 @@ bool PinJoint3DSW::setup(real_t p_step) {
for (int i = 0; i < 3; i++) {
normal[i] = 1;
- memnew_placement(&m_jac[i], JacobianEntry3DSW(
- A->get_principal_inertia_axes().transposed(),
- B->get_principal_inertia_axes().transposed(),
- A->get_transform().xform(m_pivotInA) - A->get_transform().origin - A->get_center_of_mass(),
- B->get_transform().xform(m_pivotInB) - B->get_transform().origin - B->get_center_of_mass(),
- normal,
- A->get_inv_inertia(),
- A->get_inv_mass(),
- B->get_inv_inertia(),
- B->get_inv_mass()));
+ memnew_placement(
+ &m_jac[i],
+ GodotJacobianEntry3D(
+ A->get_principal_inertia_axes().transposed(),
+ B->get_principal_inertia_axes().transposed(),
+ A->get_transform().xform(m_pivotInA) - A->get_transform().origin - A->get_center_of_mass(),
+ B->get_transform().xform(m_pivotInB) - B->get_transform().origin - B->get_center_of_mass(),
+ normal,
+ A->get_inv_inertia(),
+ A->get_inv_mass(),
+ B->get_inv_inertia(),
+ B->get_inv_mass()));
normal[i] = 0;
}
return true;
}
-void PinJoint3DSW::solve(real_t p_step) {
+void GodotPinJoint3D::solve(real_t p_step) {
Vector3 pivotAInW = A->get_transform().xform(m_pivotInA);
Vector3 pivotBInW = B->get_transform().xform(m_pivotInB);
@@ -137,7 +139,7 @@ void PinJoint3DSW::solve(real_t p_step) {
}
}
-void PinJoint3DSW::set_param(PhysicsServer3D::PinJointParam p_param, real_t p_value) {
+void GodotPinJoint3D::set_param(PhysicsServer3D::PinJointParam p_param, real_t p_value) {
switch (p_param) {
case PhysicsServer3D::PIN_JOINT_BIAS:
m_tau = p_value;
@@ -151,7 +153,7 @@ void PinJoint3DSW::set_param(PhysicsServer3D::PinJointParam p_param, real_t p_va
}
}
-real_t PinJoint3DSW::get_param(PhysicsServer3D::PinJointParam p_param) const {
+real_t GodotPinJoint3D::get_param(PhysicsServer3D::PinJointParam p_param) const {
switch (p_param) {
case PhysicsServer3D::PIN_JOINT_BIAS:
return m_tau;
@@ -164,8 +166,8 @@ real_t PinJoint3DSW::get_param(PhysicsServer3D::PinJointParam p_param) const {
return 0;
}
-PinJoint3DSW::PinJoint3DSW(Body3DSW *p_body_a, const Vector3 &p_pos_a, Body3DSW *p_body_b, const Vector3 &p_pos_b) :
- Joint3DSW(_arr, 2) {
+GodotPinJoint3D::GodotPinJoint3D(GodotBody3D *p_body_a, const Vector3 &p_pos_a, GodotBody3D *p_body_b, const Vector3 &p_pos_b) :
+ GodotJoint3D(_arr, 2) {
A = p_body_a;
B = p_body_b;
m_pivotInA = p_pos_a;
@@ -175,5 +177,5 @@ PinJoint3DSW::PinJoint3DSW(Body3DSW *p_body_a, const Vector3 &p_pos_a, Body3DSW
B->add_constraint(this, 1);
}
-PinJoint3DSW::~PinJoint3DSW() {
+GodotPinJoint3D::~GodotPinJoint3D() {
}
diff --git a/servers/physics_3d/joints/pin_joint_3d_sw.h b/servers/physics_3d/joints/godot_pin_joint_3d.h
index 79af48f2a5..eeeaa650bd 100644
--- a/servers/physics_3d/joints/pin_joint_3d_sw.h
+++ b/servers/physics_3d/joints/godot_pin_joint_3d.h
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* pin_joint_3d_sw.h */
+/* godot_pin_joint_3d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -32,11 +32,11 @@
Adapted to Godot from the Bullet library.
*/
-#ifndef PIN_JOINT_SW_H
-#define PIN_JOINT_SW_H
+#ifndef GODOT_PIN_JOINT_3D_H
+#define GODOT_PIN_JOINT_3D_H
-#include "servers/physics_3d/joints/jacobian_entry_3d_sw.h"
-#include "servers/physics_3d/joints_3d_sw.h"
+#include "servers/physics_3d/godot_joint_3d.h"
+#include "servers/physics_3d/joints/godot_jacobian_entry_3d.h"
/*
Bullet Continuous Collision Detection and Physics Library
@@ -53,14 +53,14 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-class PinJoint3DSW : public Joint3DSW {
+class GodotPinJoint3D : public GodotJoint3D {
union {
struct {
- Body3DSW *A;
- Body3DSW *B;
+ GodotBody3D *A;
+ GodotBody3D *B;
};
- Body3DSW *_arr[2] = {};
+ GodotBody3D *_arr[2] = {};
};
real_t m_tau = 0.3; //bias
@@ -68,7 +68,7 @@ class PinJoint3DSW : public Joint3DSW {
real_t m_impulseClamp = 0.0;
real_t m_appliedImpulse = 0.0;
- JacobianEntry3DSW m_jac[3] = {}; //3 orthogonal linear constraints
+ GodotJacobianEntry3D m_jac[3] = {}; //3 orthogonal linear constraints
Vector3 m_pivotInA;
Vector3 m_pivotInB;
@@ -88,8 +88,8 @@ public:
Vector3 get_position_a() { return m_pivotInA; }
Vector3 get_position_b() { return m_pivotInB; }
- PinJoint3DSW(Body3DSW *p_body_a, const Vector3 &p_pos_a, Body3DSW *p_body_b, const Vector3 &p_pos_b);
- ~PinJoint3DSW();
+ GodotPinJoint3D(GodotBody3D *p_body_a, const Vector3 &p_pos_a, GodotBody3D *p_body_b, const Vector3 &p_pos_b);
+ ~GodotPinJoint3D();
};
-#endif // PIN_JOINT_SW_H
+#endif // GODOT_PIN_JOINT_3D_H
diff --git a/servers/physics_3d/joints/slider_joint_3d_sw.cpp b/servers/physics_3d/joints/godot_slider_joint_3d.cpp
index e10ed436d5..f175421304 100644
--- a/servers/physics_3d/joints/slider_joint_3d_sw.cpp
+++ b/servers/physics_3d/joints/godot_slider_joint_3d.cpp
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* slider_joint_3d_sw.cpp */
+/* godot_slider_joint_3d.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -53,7 +53,7 @@ April 04, 2008
*/
-#include "slider_joint_3d_sw.h"
+#include "godot_slider_joint_3d.h"
//-----------------------------------------------------------------------------
@@ -76,8 +76,8 @@ static _FORCE_INLINE_ real_t atan2fast(real_t y, real_t x) {
//-----------------------------------------------------------------------------
-SliderJoint3DSW::SliderJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform3D &frameInA, const Transform3D &frameInB) :
- Joint3DSW(_arr, 2),
+GodotSliderJoint3D::GodotSliderJoint3D(GodotBody3D *rbA, GodotBody3D *rbB, const Transform3D &frameInA, const Transform3D &frameInB) :
+ GodotJoint3D(_arr, 2),
m_frameInA(frameInA),
m_frameInB(frameInB) {
A = rbA;
@@ -85,11 +85,11 @@ SliderJoint3DSW::SliderJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform3D
A->add_constraint(this, 0);
B->add_constraint(this, 1);
-} // SliderJointSW::SliderJointSW()
+}
//-----------------------------------------------------------------------------
-bool SliderJoint3DSW::setup(real_t p_step) {
+bool GodotSliderJoint3D::setup(real_t p_step) {
dynamic_A = (A->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC);
dynamic_B = (B->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC);
@@ -112,16 +112,18 @@ bool SliderJoint3DSW::setup(real_t p_step) {
//linear part
for (i = 0; i < 3; i++) {
normalWorld = m_calculatedTransformA.basis.get_axis(i);
- memnew_placement(&m_jacLin[i], JacobianEntry3DSW(
- A->get_principal_inertia_axes().transposed(),
- B->get_principal_inertia_axes().transposed(),
- m_relPosA - A->get_center_of_mass(),
- m_relPosB - B->get_center_of_mass(),
- normalWorld,
- A->get_inv_inertia(),
- A->get_inv_mass(),
- B->get_inv_inertia(),
- B->get_inv_mass()));
+ memnew_placement(
+ &m_jacLin[i],
+ GodotJacobianEntry3D(
+ A->get_principal_inertia_axes().transposed(),
+ B->get_principal_inertia_axes().transposed(),
+ m_relPosA - A->get_center_of_mass(),
+ m_relPosB - B->get_center_of_mass(),
+ normalWorld,
+ A->get_inv_inertia(),
+ A->get_inv_mass(),
+ B->get_inv_inertia(),
+ B->get_inv_mass()));
m_jacLinDiagABInv[i] = real_t(1.) / m_jacLin[i].getDiagonal();
m_depth[i] = m_delta.dot(normalWorld);
}
@@ -129,12 +131,14 @@ bool SliderJoint3DSW::setup(real_t p_step) {
// angular part
for (i = 0; i < 3; i++) {
normalWorld = m_calculatedTransformA.basis.get_axis(i);
- memnew_placement(&m_jacAng[i], JacobianEntry3DSW(
- normalWorld,
- A->get_principal_inertia_axes().transposed(),
- B->get_principal_inertia_axes().transposed(),
- A->get_inv_inertia(),
- B->get_inv_inertia()));
+ memnew_placement(
+ &m_jacAng[i],
+ GodotJacobianEntry3D(
+ normalWorld,
+ A->get_principal_inertia_axes().transposed(),
+ B->get_principal_inertia_axes().transposed(),
+ A->get_inv_inertia(),
+ B->get_inv_inertia()));
}
testAngLimits();
Vector3 axisA = m_calculatedTransformA.basis.get_axis(0);
@@ -144,11 +148,11 @@ bool SliderJoint3DSW::setup(real_t p_step) {
m_accumulatedAngMotorImpulse = real_t(0.0);
return true;
-} // SliderJointSW::buildJacobianInt()
+}
//-----------------------------------------------------------------------------
-void SliderJoint3DSW::solve(real_t p_step) {
+void GodotSliderJoint3D::solve(real_t p_step) {
int i;
// linear
Vector3 velA = A->get_velocity_in_local_point(m_relPosA);
@@ -284,13 +288,11 @@ void SliderJoint3DSW::solve(real_t p_step) {
}
}
}
-} // SliderJointSW::solveConstraint()
-
-//-----------------------------------------------------------------------------
+}
//-----------------------------------------------------------------------------
-void SliderJoint3DSW::calculateTransforms() {
+void GodotSliderJoint3D::calculateTransforms() {
m_calculatedTransformA = A->get_transform() * m_frameInA;
m_calculatedTransformB = B->get_transform() * m_frameInB;
m_realPivotAInW = m_calculatedTransformA.origin;
@@ -305,11 +307,11 @@ void SliderJoint3DSW::calculateTransforms() {
normalWorld = m_calculatedTransformA.basis.get_axis(i);
m_depth[i] = m_delta.dot(normalWorld);
}
-} // SliderJointSW::calculateTransforms()
+}
//-----------------------------------------------------------------------------
-void SliderJoint3DSW::testLinLimits() {
+void GodotSliderJoint3D::testLinLimits() {
m_solveLinLim = false;
m_linPos = m_depth[0];
if (m_lowerLinLimit <= m_upperLinLimit) {
@@ -325,11 +327,11 @@ void SliderJoint3DSW::testLinLimits() {
} else {
m_depth[0] = real_t(0.);
}
-} // SliderJointSW::testLinLimits()
+}
//-----------------------------------------------------------------------------
-void SliderJoint3DSW::testAngLimits() {
+void GodotSliderJoint3D::testAngLimits() {
m_angDepth = real_t(0.);
m_solveAngLim = false;
if (m_lowerAngLimit <= m_upperAngLimit) {
@@ -345,26 +347,26 @@ void SliderJoint3DSW::testAngLimits() {
m_solveAngLim = true;
}
}
-} // SliderJointSW::testAngLimits()
+}
//-----------------------------------------------------------------------------
-Vector3 SliderJoint3DSW::getAncorInA() {
+Vector3 GodotSliderJoint3D::getAncorInA() {
Vector3 ancorInA;
ancorInA = m_realPivotAInW + (m_lowerLinLimit + m_upperLinLimit) * real_t(0.5) * m_sliderAxis;
ancorInA = A->get_transform().inverse().xform(ancorInA);
return ancorInA;
-} // SliderJointSW::getAncorInA()
+}
//-----------------------------------------------------------------------------
-Vector3 SliderJoint3DSW::getAncorInB() {
+Vector3 GodotSliderJoint3D::getAncorInB() {
Vector3 ancorInB;
ancorInB = m_frameInB.origin;
return ancorInB;
-} // SliderJointSW::getAncorInB();
+}
-void SliderJoint3DSW::set_param(PhysicsServer3D::SliderJointParam p_param, real_t p_value) {
+void GodotSliderJoint3D::set_param(PhysicsServer3D::SliderJointParam p_param, real_t p_value) {
switch (p_param) {
case PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_UPPER:
m_upperLinLimit = p_value;
@@ -439,7 +441,7 @@ void SliderJoint3DSW::set_param(PhysicsServer3D::SliderJointParam p_param, real_
}
}
-real_t SliderJoint3DSW::get_param(PhysicsServer3D::SliderJointParam p_param) const {
+real_t GodotSliderJoint3D::get_param(PhysicsServer3D::SliderJointParam p_param) const {
switch (p_param) {
case PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_UPPER:
return m_upperLinLimit;
diff --git a/servers/physics_3d/joints/slider_joint_3d_sw.h b/servers/physics_3d/joints/godot_slider_joint_3d.h
index d32ad9469e..f596c9ff75 100644
--- a/servers/physics_3d/joints/slider_joint_3d_sw.h
+++ b/servers/physics_3d/joints/godot_slider_joint_3d.h
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* slider_joint_3d_sw.h */
+/* godot_slider_joint_3d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -32,11 +32,11 @@
Adapted to Godot from the Bullet library.
*/
-#ifndef SLIDER_JOINT_SW_H
-#define SLIDER_JOINT_SW_H
+#ifndef GODOT_SLIDER_JOINT_3D_H
+#define GODOT_SLIDER_JOINT_3D_H
-#include "servers/physics_3d/joints/jacobian_entry_3d_sw.h"
-#include "servers/physics_3d/joints_3d_sw.h"
+#include "servers/physics_3d/godot_joint_3d.h"
+#include "servers/physics_3d/joints/godot_jacobian_entry_3d.h"
/*
Bullet Continuous Collision Detection and Physics Library
@@ -65,15 +65,15 @@ April 04, 2008
//-----------------------------------------------------------------------------
-class SliderJoint3DSW : public Joint3DSW {
+class GodotSliderJoint3D : public GodotJoint3D {
protected:
union {
struct {
- Body3DSW *A;
- Body3DSW *B;
+ GodotBody3D *A;
+ GodotBody3D *B;
};
- Body3DSW *_arr[2] = { nullptr, nullptr };
+ GodotBody3D *_arr[2] = { nullptr, nullptr };
};
Transform3D m_frameInA;
@@ -114,10 +114,10 @@ protected:
bool m_solveLinLim = false;
bool m_solveAngLim = false;
- JacobianEntry3DSW m_jacLin[3] = {};
+ GodotJacobianEntry3D m_jacLin[3] = {};
real_t m_jacLinDiagABInv[3] = {};
- JacobianEntry3DSW m_jacAng[3] = {};
+ GodotJacobianEntry3D m_jacAng[3] = {};
real_t m_timeStep = 0.0;
Transform3D m_calculatedTransformA;
@@ -149,13 +149,13 @@ protected:
public:
// constructors
- SliderJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform3D &frameInA, const Transform3D &frameInB);
+ GodotSliderJoint3D(GodotBody3D *rbA, GodotBody3D *rbB, const Transform3D &frameInA, const Transform3D &frameInB);
//SliderJointSW();
// overrides
// access
- const Body3DSW *getRigidBodyA() const { return A; }
- const Body3DSW *getRigidBodyB() const { return B; }
+ const GodotBody3D *getRigidBodyA() const { return A; }
+ const GodotBody3D *getRigidBodyB() const { return B; }
const Transform3D &getCalculatedTransformA() const { return m_calculatedTransformA; }
const Transform3D &getCalculatedTransformB() const { return m_calculatedTransformB; }
const Transform3D &getFrameOffsetA() const { return m_frameInA; }
@@ -243,4 +243,4 @@ public:
virtual PhysicsServer3D::JointType get_type() const override { return PhysicsServer3D::JOINT_TYPE_SLIDER; }
};
-#endif // SLIDER_JOINT_SW_H
+#endif // GODOT_SLIDER_JOINT_3D_H
diff --git a/servers/physics_3d/physics_server_3d_sw.cpp b/servers/physics_3d/physics_server_3d_sw.cpp
deleted file mode 100644
index b16e199a03..0000000000
--- a/servers/physics_3d/physics_server_3d_sw.cpp
+++ /dev/null
@@ -1,1748 +0,0 @@
-/*************************************************************************/
-/* physics_server_3d_sw.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 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 "physics_server_3d_sw.h"
-
-#include "body_direct_state_3d_sw.h"
-#include "broad_phase_3d_bvh.h"
-#include "core/debugger/engine_debugger.h"
-#include "core/os/os.h"
-#include "joints/cone_twist_joint_3d_sw.h"
-#include "joints/generic_6dof_joint_3d_sw.h"
-#include "joints/hinge_joint_3d_sw.h"
-#include "joints/pin_joint_3d_sw.h"
-#include "joints/slider_joint_3d_sw.h"
-
-#define FLUSH_QUERY_CHECK(m_object) \
- ERR_FAIL_COND_MSG(m_object->get_space() && flushing_queries, "Can't change this state while flushing queries. Use call_deferred() or set_deferred() to change monitoring state instead.");
-
-RID PhysicsServer3DSW::world_boundary_shape_create() {
- Shape3DSW *shape = memnew(WorldBoundaryShape3DSW);
- RID rid = shape_owner.make_rid(shape);
- shape->set_self(rid);
- return rid;
-}
-RID PhysicsServer3DSW::separation_ray_shape_create() {
- Shape3DSW *shape = memnew(SeparationRayShape3DSW);
- RID rid = shape_owner.make_rid(shape);
- shape->set_self(rid);
- return rid;
-}
-RID PhysicsServer3DSW::sphere_shape_create() {
- Shape3DSW *shape = memnew(SphereShape3DSW);
- RID rid = shape_owner.make_rid(shape);
- shape->set_self(rid);
- return rid;
-}
-RID PhysicsServer3DSW::box_shape_create() {
- Shape3DSW *shape = memnew(BoxShape3DSW);
- RID rid = shape_owner.make_rid(shape);
- shape->set_self(rid);
- return rid;
-}
-RID PhysicsServer3DSW::capsule_shape_create() {
- Shape3DSW *shape = memnew(CapsuleShape3DSW);
- RID rid = shape_owner.make_rid(shape);
- shape->set_self(rid);
- return rid;
-}
-RID PhysicsServer3DSW::cylinder_shape_create() {
- Shape3DSW *shape = memnew(CylinderShape3DSW);
- RID rid = shape_owner.make_rid(shape);
- shape->set_self(rid);
- return rid;
-}
-RID PhysicsServer3DSW::convex_polygon_shape_create() {
- Shape3DSW *shape = memnew(ConvexPolygonShape3DSW);
- RID rid = shape_owner.make_rid(shape);
- shape->set_self(rid);
- return rid;
-}
-RID PhysicsServer3DSW::concave_polygon_shape_create() {
- Shape3DSW *shape = memnew(ConcavePolygonShape3DSW);
- RID rid = shape_owner.make_rid(shape);
- shape->set_self(rid);
- return rid;
-}
-RID PhysicsServer3DSW::heightmap_shape_create() {
- Shape3DSW *shape = memnew(HeightMapShape3DSW);
- RID rid = shape_owner.make_rid(shape);
- shape->set_self(rid);
- return rid;
-}
-RID PhysicsServer3DSW::custom_shape_create() {
- ERR_FAIL_V(RID());
-}
-
-void PhysicsServer3DSW::shape_set_data(RID p_shape, const Variant &p_data) {
- Shape3DSW *shape = shape_owner.get_or_null(p_shape);
- ERR_FAIL_COND(!shape);
- shape->set_data(p_data);
-};
-
-void PhysicsServer3DSW::shape_set_custom_solver_bias(RID p_shape, real_t p_bias) {
- Shape3DSW *shape = shape_owner.get_or_null(p_shape);
- ERR_FAIL_COND(!shape);
- shape->set_custom_bias(p_bias);
-}
-
-PhysicsServer3D::ShapeType PhysicsServer3DSW::shape_get_type(RID p_shape) const {
- const Shape3DSW *shape = shape_owner.get_or_null(p_shape);
- ERR_FAIL_COND_V(!shape, SHAPE_CUSTOM);
- return shape->get_type();
-};
-
-Variant PhysicsServer3DSW::shape_get_data(RID p_shape) const {
- const Shape3DSW *shape = shape_owner.get_or_null(p_shape);
- ERR_FAIL_COND_V(!shape, Variant());
- ERR_FAIL_COND_V(!shape->is_configured(), Variant());
- return shape->get_data();
-};
-
-void PhysicsServer3DSW::shape_set_margin(RID p_shape, real_t p_margin) {
-}
-
-real_t PhysicsServer3DSW::shape_get_margin(RID p_shape) const {
- return 0.0;
-}
-
-real_t PhysicsServer3DSW::shape_get_custom_solver_bias(RID p_shape) const {
- const Shape3DSW *shape = shape_owner.get_or_null(p_shape);
- ERR_FAIL_COND_V(!shape, 0);
- return shape->get_custom_bias();
-}
-
-RID PhysicsServer3DSW::space_create() {
- Space3DSW *space = memnew(Space3DSW);
- RID id = space_owner.make_rid(space);
- space->set_self(id);
- RID area_id = area_create();
- Area3DSW *area = area_owner.get_or_null(area_id);
- ERR_FAIL_COND_V(!area, RID());
- space->set_default_area(area);
- area->set_space(space);
- area->set_priority(-1);
- RID sgb = body_create();
- body_set_space(sgb, id);
- body_set_mode(sgb, BODY_MODE_STATIC);
- space->set_static_global_body(sgb);
-
- return id;
-};
-
-void PhysicsServer3DSW::space_set_active(RID p_space, bool p_active) {
- Space3DSW *space = space_owner.get_or_null(p_space);
- ERR_FAIL_COND(!space);
- if (p_active) {
- active_spaces.insert(space);
- } else {
- active_spaces.erase(space);
- }
-}
-
-bool PhysicsServer3DSW::space_is_active(RID p_space) const {
- const Space3DSW *space = space_owner.get_or_null(p_space);
- ERR_FAIL_COND_V(!space, false);
-
- return active_spaces.has(space);
-}
-
-void PhysicsServer3DSW::space_set_param(RID p_space, SpaceParameter p_param, real_t p_value) {
- Space3DSW *space = space_owner.get_or_null(p_space);
- ERR_FAIL_COND(!space);
-
- space->set_param(p_param, p_value);
-}
-
-real_t PhysicsServer3DSW::space_get_param(RID p_space, SpaceParameter p_param) const {
- const Space3DSW *space = space_owner.get_or_null(p_space);
- ERR_FAIL_COND_V(!space, 0);
- return space->get_param(p_param);
-}
-
-PhysicsDirectSpaceState3D *PhysicsServer3DSW::space_get_direct_state(RID p_space) {
- Space3DSW *space = space_owner.get_or_null(p_space);
- ERR_FAIL_COND_V(!space, nullptr);
- ERR_FAIL_COND_V_MSG((using_threads && !doing_sync) || space->is_locked(), nullptr, "Space state is inaccessible right now, wait for iteration or physics process notification.");
-
- return space->get_direct_state();
-}
-
-void PhysicsServer3DSW::space_set_debug_contacts(RID p_space, int p_max_contacts) {
- Space3DSW *space = space_owner.get_or_null(p_space);
- ERR_FAIL_COND(!space);
- space->set_debug_contacts(p_max_contacts);
-}
-
-Vector<Vector3> PhysicsServer3DSW::space_get_contacts(RID p_space) const {
- Space3DSW *space = space_owner.get_or_null(p_space);
- ERR_FAIL_COND_V(!space, Vector<Vector3>());
- return space->get_debug_contacts();
-}
-
-int PhysicsServer3DSW::space_get_contact_count(RID p_space) const {
- Space3DSW *space = space_owner.get_or_null(p_space);
- ERR_FAIL_COND_V(!space, 0);
- return space->get_debug_contact_count();
-}
-
-RID PhysicsServer3DSW::area_create() {
- Area3DSW *area = memnew(Area3DSW);
- RID rid = area_owner.make_rid(area);
- area->set_self(rid);
- return rid;
-};
-
-void PhysicsServer3DSW::area_set_space(RID p_area, RID p_space) {
- Area3DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND(!area);
-
- Space3DSW *space = nullptr;
- if (p_space.is_valid()) {
- space = space_owner.get_or_null(p_space);
- ERR_FAIL_COND(!space);
- }
-
- if (area->get_space() == space) {
- return; //pointless
- }
-
- area->clear_constraints();
- area->set_space(space);
-};
-
-RID PhysicsServer3DSW::area_get_space(RID p_area) const {
- Area3DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND_V(!area, RID());
-
- Space3DSW *space = area->get_space();
- if (!space) {
- return RID();
- }
- return space->get_self();
-};
-
-void PhysicsServer3DSW::area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) {
- Area3DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND(!area);
-
- area->set_space_override_mode(p_mode);
-}
-
-PhysicsServer3D::AreaSpaceOverrideMode PhysicsServer3DSW::area_get_space_override_mode(RID p_area) const {
- const Area3DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND_V(!area, AREA_SPACE_OVERRIDE_DISABLED);
-
- return area->get_space_override_mode();
-}
-
-void PhysicsServer3DSW::area_add_shape(RID p_area, RID p_shape, const Transform3D &p_transform, bool p_disabled) {
- Area3DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND(!area);
-
- Shape3DSW *shape = shape_owner.get_or_null(p_shape);
- ERR_FAIL_COND(!shape);
-
- area->add_shape(shape, p_transform, p_disabled);
-}
-
-void PhysicsServer3DSW::area_set_shape(RID p_area, int p_shape_idx, RID p_shape) {
- Area3DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND(!area);
-
- Shape3DSW *shape = shape_owner.get_or_null(p_shape);
- ERR_FAIL_COND(!shape);
- ERR_FAIL_COND(!shape->is_configured());
-
- area->set_shape(p_shape_idx, shape);
-}
-
-void PhysicsServer3DSW::area_set_shape_transform(RID p_area, int p_shape_idx, const Transform3D &p_transform) {
- Area3DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND(!area);
-
- area->set_shape_transform(p_shape_idx, p_transform);
-}
-
-int PhysicsServer3DSW::area_get_shape_count(RID p_area) const {
- Area3DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND_V(!area, -1);
-
- return area->get_shape_count();
-}
-
-RID PhysicsServer3DSW::area_get_shape(RID p_area, int p_shape_idx) const {
- Area3DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND_V(!area, RID());
-
- Shape3DSW *shape = area->get_shape(p_shape_idx);
- ERR_FAIL_COND_V(!shape, RID());
-
- return shape->get_self();
-}
-
-Transform3D PhysicsServer3DSW::area_get_shape_transform(RID p_area, int p_shape_idx) const {
- Area3DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND_V(!area, Transform3D());
-
- return area->get_shape_transform(p_shape_idx);
-}
-
-void PhysicsServer3DSW::area_remove_shape(RID p_area, int p_shape_idx) {
- Area3DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND(!area);
-
- area->remove_shape(p_shape_idx);
-}
-
-void PhysicsServer3DSW::area_clear_shapes(RID p_area) {
- Area3DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND(!area);
-
- while (area->get_shape_count()) {
- area->remove_shape(0);
- }
-}
-
-void PhysicsServer3DSW::area_set_shape_disabled(RID p_area, int p_shape_idx, bool p_disabled) {
- Area3DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND(!area);
- ERR_FAIL_INDEX(p_shape_idx, area->get_shape_count());
- FLUSH_QUERY_CHECK(area);
- area->set_shape_disabled(p_shape_idx, p_disabled);
-}
-
-void PhysicsServer3DSW::area_attach_object_instance_id(RID p_area, ObjectID p_id) {
- if (space_owner.owns(p_area)) {
- Space3DSW *space = space_owner.get_or_null(p_area);
- p_area = space->get_default_area()->get_self();
- }
- Area3DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND(!area);
- area->set_instance_id(p_id);
-}
-
-ObjectID PhysicsServer3DSW::area_get_object_instance_id(RID p_area) const {
- if (space_owner.owns(p_area)) {
- Space3DSW *space = space_owner.get_or_null(p_area);
- p_area = space->get_default_area()->get_self();
- }
- Area3DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND_V(!area, ObjectID());
- return area->get_instance_id();
-}
-
-void PhysicsServer3DSW::area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value) {
- if (space_owner.owns(p_area)) {
- Space3DSW *space = space_owner.get_or_null(p_area);
- p_area = space->get_default_area()->get_self();
- }
- Area3DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND(!area);
- area->set_param(p_param, p_value);
-};
-
-void PhysicsServer3DSW::area_set_transform(RID p_area, const Transform3D &p_transform) {
- Area3DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND(!area);
- area->set_transform(p_transform);
-};
-
-Variant PhysicsServer3DSW::area_get_param(RID p_area, AreaParameter p_param) const {
- if (space_owner.owns(p_area)) {
- Space3DSW *space = space_owner.get_or_null(p_area);
- p_area = space->get_default_area()->get_self();
- }
- Area3DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND_V(!area, Variant());
-
- return area->get_param(p_param);
-};
-
-Transform3D PhysicsServer3DSW::area_get_transform(RID p_area) const {
- Area3DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND_V(!area, Transform3D());
-
- return area->get_transform();
-};
-
-void PhysicsServer3DSW::area_set_collision_layer(RID p_area, uint32_t p_layer) {
- Area3DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND(!area);
-
- area->set_collision_layer(p_layer);
-}
-
-void PhysicsServer3DSW::area_set_collision_mask(RID p_area, uint32_t p_mask) {
- Area3DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND(!area);
-
- area->set_collision_mask(p_mask);
-}
-
-void PhysicsServer3DSW::area_set_monitorable(RID p_area, bool p_monitorable) {
- Area3DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND(!area);
- FLUSH_QUERY_CHECK(area);
-
- area->set_monitorable(p_monitorable);
-}
-
-void PhysicsServer3DSW::area_set_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) {
- Area3DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND(!area);
-
- area->set_monitor_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method);
-}
-
-void PhysicsServer3DSW::area_set_ray_pickable(RID p_area, bool p_enable) {
- Area3DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND(!area);
-
- area->set_ray_pickable(p_enable);
-}
-
-void PhysicsServer3DSW::area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) {
- Area3DSW *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND(!area);
-
- area->set_area_monitor_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method);
-}
-
-/* BODY API */
-
-RID PhysicsServer3DSW::body_create() {
- Body3DSW *body = memnew(Body3DSW);
- RID rid = body_owner.make_rid(body);
- body->set_self(rid);
- return rid;
-};
-
-void PhysicsServer3DSW::body_set_space(RID p_body, RID p_space) {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- Space3DSW *space = nullptr;
- if (p_space.is_valid()) {
- space = space_owner.get_or_null(p_space);
- ERR_FAIL_COND(!space);
- }
-
- if (body->get_space() == space) {
- return; //pointless
- }
-
- body->clear_constraint_map();
- body->set_space(space);
-};
-
-RID PhysicsServer3DSW::body_get_space(RID p_body) const {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!body, RID());
-
- Space3DSW *space = body->get_space();
- if (!space) {
- return RID();
- }
- return space->get_self();
-};
-
-void PhysicsServer3DSW::body_set_mode(RID p_body, BodyMode p_mode) {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- body->set_mode(p_mode);
-};
-
-PhysicsServer3D::BodyMode PhysicsServer3DSW::body_get_mode(RID p_body) const {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!body, BODY_MODE_STATIC);
-
- return body->get_mode();
-};
-
-void PhysicsServer3DSW::body_add_shape(RID p_body, RID p_shape, const Transform3D &p_transform, bool p_disabled) {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- Shape3DSW *shape = shape_owner.get_or_null(p_shape);
- ERR_FAIL_COND(!shape);
-
- body->add_shape(shape, p_transform, p_disabled);
-}
-
-void PhysicsServer3DSW::body_set_shape(RID p_body, int p_shape_idx, RID p_shape) {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- Shape3DSW *shape = shape_owner.get_or_null(p_shape);
- ERR_FAIL_COND(!shape);
- ERR_FAIL_COND(!shape->is_configured());
-
- body->set_shape(p_shape_idx, shape);
-}
-void PhysicsServer3DSW::body_set_shape_transform(RID p_body, int p_shape_idx, const Transform3D &p_transform) {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- body->set_shape_transform(p_shape_idx, p_transform);
-}
-
-int PhysicsServer3DSW::body_get_shape_count(RID p_body) const {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!body, -1);
-
- return body->get_shape_count();
-}
-
-RID PhysicsServer3DSW::body_get_shape(RID p_body, int p_shape_idx) const {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!body, RID());
-
- Shape3DSW *shape = body->get_shape(p_shape_idx);
- ERR_FAIL_COND_V(!shape, RID());
-
- return shape->get_self();
-}
-
-void PhysicsServer3DSW::body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
- ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count());
- FLUSH_QUERY_CHECK(body);
-
- body->set_shape_disabled(p_shape_idx, p_disabled);
-}
-
-Transform3D PhysicsServer3DSW::body_get_shape_transform(RID p_body, int p_shape_idx) const {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!body, Transform3D());
-
- return body->get_shape_transform(p_shape_idx);
-}
-
-void PhysicsServer3DSW::body_remove_shape(RID p_body, int p_shape_idx) {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- body->remove_shape(p_shape_idx);
-}
-
-void PhysicsServer3DSW::body_clear_shapes(RID p_body) {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- while (body->get_shape_count()) {
- body->remove_shape(0);
- }
-}
-
-void PhysicsServer3DSW::body_set_enable_continuous_collision_detection(RID p_body, bool p_enable) {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- body->set_continuous_collision_detection(p_enable);
-}
-
-bool PhysicsServer3DSW::body_is_continuous_collision_detection_enabled(RID p_body) const {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!body, false);
-
- return body->is_continuous_collision_detection_enabled();
-}
-
-void PhysicsServer3DSW::body_set_collision_layer(RID p_body, uint32_t p_layer) {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- body->set_collision_layer(p_layer);
- body->wakeup();
-}
-
-uint32_t PhysicsServer3DSW::body_get_collision_layer(RID p_body) const {
- const Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!body, 0);
-
- return body->get_collision_layer();
-}
-
-void PhysicsServer3DSW::body_set_collision_mask(RID p_body, uint32_t p_mask) {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- body->set_collision_mask(p_mask);
- body->wakeup();
-}
-
-uint32_t PhysicsServer3DSW::body_get_collision_mask(RID p_body) const {
- const Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!body, 0);
-
- return body->get_collision_mask();
-}
-
-void PhysicsServer3DSW::body_attach_object_instance_id(RID p_body, ObjectID p_id) {
- Body3DSW *body = body_owner.get_or_null(p_body);
- if (body) {
- body->set_instance_id(p_id);
- return;
- }
-
- SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
- if (soft_body) {
- soft_body->set_instance_id(p_id);
- return;
- }
-
- ERR_FAIL_MSG("Invalid ID.");
-};
-
-ObjectID PhysicsServer3DSW::body_get_object_instance_id(RID p_body) const {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!body, ObjectID());
-
- return body->get_instance_id();
-};
-
-void PhysicsServer3DSW::body_set_user_flags(RID p_body, uint32_t p_flags) {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-};
-
-uint32_t PhysicsServer3DSW::body_get_user_flags(RID p_body) const {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!body, 0);
-
- return 0;
-};
-
-void PhysicsServer3DSW::body_set_param(RID p_body, BodyParameter p_param, const Variant &p_value) {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- body->set_param(p_param, p_value);
-};
-
-Variant PhysicsServer3DSW::body_get_param(RID p_body, BodyParameter p_param) const {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!body, 0);
-
- return body->get_param(p_param);
-};
-
-void PhysicsServer3DSW::body_reset_mass_properties(RID p_body) {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- return body->reset_mass_properties();
-}
-
-void PhysicsServer3DSW::body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- body->set_state(p_state, p_variant);
-};
-
-Variant PhysicsServer3DSW::body_get_state(RID p_body, BodyState p_state) const {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!body, Variant());
-
- return body->get_state(p_state);
-};
-
-void PhysicsServer3DSW::body_set_applied_force(RID p_body, const Vector3 &p_force) {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- body->set_applied_force(p_force);
- body->wakeup();
-};
-
-Vector3 PhysicsServer3DSW::body_get_applied_force(RID p_body) const {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!body, Vector3());
- return body->get_applied_force();
-};
-
-void PhysicsServer3DSW::body_set_applied_torque(RID p_body, const Vector3 &p_torque) {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- body->set_applied_torque(p_torque);
- body->wakeup();
-};
-
-Vector3 PhysicsServer3DSW::body_get_applied_torque(RID p_body) const {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!body, Vector3());
-
- return body->get_applied_torque();
-};
-
-void PhysicsServer3DSW::body_add_central_force(RID p_body, const Vector3 &p_force) {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- body->add_central_force(p_force);
- body->wakeup();
-}
-
-void PhysicsServer3DSW::body_add_force(RID p_body, const Vector3 &p_force, const Vector3 &p_position) {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- body->add_force(p_force, p_position);
- body->wakeup();
-};
-
-void PhysicsServer3DSW::body_add_torque(RID p_body, const Vector3 &p_torque) {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- body->add_torque(p_torque);
- body->wakeup();
-};
-
-void PhysicsServer3DSW::body_apply_central_impulse(RID p_body, const Vector3 &p_impulse) {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- _update_shapes();
-
- body->apply_central_impulse(p_impulse);
- body->wakeup();
-}
-
-void PhysicsServer3DSW::body_apply_impulse(RID p_body, const Vector3 &p_impulse, const Vector3 &p_position) {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- _update_shapes();
-
- body->apply_impulse(p_impulse, p_position);
- body->wakeup();
-};
-
-void PhysicsServer3DSW::body_apply_torque_impulse(RID p_body, const Vector3 &p_impulse) {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- _update_shapes();
-
- body->apply_torque_impulse(p_impulse);
- body->wakeup();
-};
-
-void PhysicsServer3DSW::body_set_axis_velocity(RID p_body, const Vector3 &p_axis_velocity) {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- _update_shapes();
-
- Vector3 v = body->get_linear_velocity();
- Vector3 axis = p_axis_velocity.normalized();
- v -= axis * axis.dot(v);
- v += p_axis_velocity;
- body->set_linear_velocity(v);
- body->wakeup();
-};
-
-void PhysicsServer3DSW::body_set_axis_lock(RID p_body, BodyAxis p_axis, bool p_lock) {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- body->set_axis_lock(p_axis, p_lock);
- body->wakeup();
-}
-
-bool PhysicsServer3DSW::body_is_axis_locked(RID p_body, BodyAxis p_axis) const {
- const Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!body, 0);
- return body->is_axis_locked(p_axis);
-}
-
-void PhysicsServer3DSW::body_add_collision_exception(RID p_body, RID p_body_b) {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- body->add_exception(p_body_b);
- body->wakeup();
-};
-
-void PhysicsServer3DSW::body_remove_collision_exception(RID p_body, RID p_body_b) {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- body->remove_exception(p_body_b);
- body->wakeup();
-};
-
-void PhysicsServer3DSW::body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions) {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- for (int i = 0; i < body->get_exceptions().size(); i++) {
- p_exceptions->push_back(body->get_exceptions()[i]);
- }
-};
-
-void PhysicsServer3DSW::body_set_contacts_reported_depth_threshold(RID p_body, real_t p_threshold) {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-};
-
-real_t PhysicsServer3DSW::body_get_contacts_reported_depth_threshold(RID p_body) const {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!body, 0);
- return 0;
-};
-
-void PhysicsServer3DSW::body_set_omit_force_integration(RID p_body, bool p_omit) {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
-
- body->set_omit_force_integration(p_omit);
-};
-
-bool PhysicsServer3DSW::body_is_omitting_force_integration(RID p_body) const {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!body, false);
- return body->get_omit_force_integration();
-};
-
-void PhysicsServer3DSW::body_set_max_contacts_reported(RID p_body, int p_contacts) {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
- body->set_max_contacts_reported(p_contacts);
-}
-
-int PhysicsServer3DSW::body_get_max_contacts_reported(RID p_body) const {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!body, -1);
- return body->get_max_contacts_reported();
-}
-
-void PhysicsServer3DSW::body_set_state_sync_callback(RID p_body, void *p_instance, BodyStateCallback p_callback) {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
- body->set_state_sync_callback(p_instance, p_callback);
-}
-
-void PhysicsServer3DSW::body_set_force_integration_callback(RID p_body, const Callable &p_callable, const Variant &p_udata) {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
- body->set_force_integration_callback(p_callable, p_udata);
-}
-
-void PhysicsServer3DSW::body_set_ray_pickable(RID p_body, bool p_enable) {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!body);
- body->set_ray_pickable(p_enable);
-}
-
-bool PhysicsServer3DSW::body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result) {
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!body, false);
- ERR_FAIL_COND_V(!body->get_space(), false);
- ERR_FAIL_COND_V(body->get_space()->is_locked(), false);
-
- _update_shapes();
-
- return body->get_space()->test_body_motion(body, p_parameters, r_result);
-}
-
-PhysicsDirectBodyState3D *PhysicsServer3DSW::body_get_direct_state(RID p_body) {
- ERR_FAIL_COND_V_MSG((using_threads && !doing_sync), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification.");
-
- Body3DSW *body = body_owner.get_or_null(p_body);
- ERR_FAIL_NULL_V(body, nullptr);
-
- ERR_FAIL_NULL_V(body->get_space(), nullptr);
- ERR_FAIL_COND_V_MSG(body->get_space()->is_locked(), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification.");
-
- return body->get_direct_state();
-}
-
-/* SOFT BODY */
-
-RID PhysicsServer3DSW::soft_body_create() {
- SoftBody3DSW *soft_body = memnew(SoftBody3DSW);
- RID rid = soft_body_owner.make_rid(soft_body);
- soft_body->set_self(rid);
- return rid;
-}
-
-void PhysicsServer3DSW::soft_body_update_rendering_server(RID p_body, RenderingServerHandler *p_rendering_server_handler) {
- SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!soft_body);
-
- soft_body->update_rendering_server(p_rendering_server_handler);
-}
-
-void PhysicsServer3DSW::soft_body_set_space(RID p_body, RID p_space) {
- SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!soft_body);
-
- Space3DSW *space = nullptr;
- if (p_space.is_valid()) {
- space = space_owner.get_or_null(p_space);
- ERR_FAIL_COND(!space);
- }
-
- if (soft_body->get_space() == space) {
- return;
- }
-
- soft_body->set_space(space);
-}
-
-RID PhysicsServer3DSW::soft_body_get_space(RID p_body) const {
- SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!soft_body, RID());
-
- Space3DSW *space = soft_body->get_space();
- if (!space) {
- return RID();
- }
- return space->get_self();
-}
-
-void PhysicsServer3DSW::soft_body_set_collision_layer(RID p_body, uint32_t p_layer) {
- SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!soft_body);
-
- soft_body->set_collision_layer(p_layer);
-}
-
-uint32_t PhysicsServer3DSW::soft_body_get_collision_layer(RID p_body) const {
- SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!soft_body, 0);
-
- return soft_body->get_collision_layer();
-}
-
-void PhysicsServer3DSW::soft_body_set_collision_mask(RID p_body, uint32_t p_mask) {
- SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!soft_body);
-
- soft_body->set_collision_mask(p_mask);
-}
-
-uint32_t PhysicsServer3DSW::soft_body_get_collision_mask(RID p_body) const {
- SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!soft_body, 0);
-
- return soft_body->get_collision_mask();
-}
-
-void PhysicsServer3DSW::soft_body_add_collision_exception(RID p_body, RID p_body_b) {
- SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!soft_body);
-
- soft_body->add_exception(p_body_b);
-}
-
-void PhysicsServer3DSW::soft_body_remove_collision_exception(RID p_body, RID p_body_b) {
- SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!soft_body);
-
- soft_body->remove_exception(p_body_b);
-}
-
-void PhysicsServer3DSW::soft_body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions) {
- SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!soft_body);
-
- for (int i = 0; i < soft_body->get_exceptions().size(); i++) {
- p_exceptions->push_back(soft_body->get_exceptions()[i]);
- }
-}
-
-void PhysicsServer3DSW::soft_body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) {
- SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!soft_body);
-
- soft_body->set_state(p_state, p_variant);
-}
-
-Variant PhysicsServer3DSW::soft_body_get_state(RID p_body, BodyState p_state) const {
- SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!soft_body, Variant());
-
- return soft_body->get_state(p_state);
-}
-
-void PhysicsServer3DSW::soft_body_set_transform(RID p_body, const Transform3D &p_transform) {
- SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!soft_body);
-
- soft_body->set_state(BODY_STATE_TRANSFORM, p_transform);
-}
-
-void PhysicsServer3DSW::soft_body_set_ray_pickable(RID p_body, bool p_enable) {
- SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!soft_body);
-
- soft_body->set_ray_pickable(p_enable);
-}
-
-void PhysicsServer3DSW::soft_body_set_simulation_precision(RID p_body, int p_simulation_precision) {
- SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!soft_body);
-
- soft_body->set_iteration_count(p_simulation_precision);
-}
-
-int PhysicsServer3DSW::soft_body_get_simulation_precision(RID p_body) const {
- SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!soft_body, 0.f);
-
- return soft_body->get_iteration_count();
-}
-
-void PhysicsServer3DSW::soft_body_set_total_mass(RID p_body, real_t p_total_mass) {
- SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!soft_body);
-
- soft_body->set_total_mass(p_total_mass);
-}
-
-real_t PhysicsServer3DSW::soft_body_get_total_mass(RID p_body) const {
- SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!soft_body, 0.f);
-
- return soft_body->get_total_mass();
-}
-
-void PhysicsServer3DSW::soft_body_set_linear_stiffness(RID p_body, real_t p_stiffness) {
- SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!soft_body);
-
- soft_body->set_linear_stiffness(p_stiffness);
-}
-
-real_t PhysicsServer3DSW::soft_body_get_linear_stiffness(RID p_body) const {
- SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!soft_body, 0.f);
-
- return soft_body->get_linear_stiffness();
-}
-
-void PhysicsServer3DSW::soft_body_set_pressure_coefficient(RID p_body, real_t p_pressure_coefficient) {
- SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!soft_body);
-
- soft_body->set_pressure_coefficient(p_pressure_coefficient);
-}
-
-real_t PhysicsServer3DSW::soft_body_get_pressure_coefficient(RID p_body) const {
- SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!soft_body, 0.f);
-
- return soft_body->get_pressure_coefficient();
-}
-
-void PhysicsServer3DSW::soft_body_set_damping_coefficient(RID p_body, real_t p_damping_coefficient) {
- SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!soft_body);
-
- soft_body->set_damping_coefficient(p_damping_coefficient);
-}
-
-real_t PhysicsServer3DSW::soft_body_get_damping_coefficient(RID p_body) const {
- SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!soft_body, 0.f);
-
- return soft_body->get_damping_coefficient();
-}
-
-void PhysicsServer3DSW::soft_body_set_drag_coefficient(RID p_body, real_t p_drag_coefficient) {
- SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!soft_body);
-
- soft_body->set_drag_coefficient(p_drag_coefficient);
-}
-
-real_t PhysicsServer3DSW::soft_body_get_drag_coefficient(RID p_body) const {
- SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!soft_body, 0.f);
-
- return soft_body->get_drag_coefficient();
-}
-
-void PhysicsServer3DSW::soft_body_set_mesh(RID p_body, RID p_mesh) {
- SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!soft_body);
-
- soft_body->set_mesh(p_mesh);
-}
-
-AABB PhysicsServer3DSW::soft_body_get_bounds(RID p_body) const {
- SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!soft_body, AABB());
-
- return soft_body->get_bounds();
-}
-
-void PhysicsServer3DSW::soft_body_move_point(RID p_body, int p_point_index, const Vector3 &p_global_position) {
- SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!soft_body);
-
- soft_body->set_vertex_position(p_point_index, p_global_position);
-}
-
-Vector3 PhysicsServer3DSW::soft_body_get_point_global_position(RID p_body, int p_point_index) const {
- SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!soft_body, Vector3());
-
- return soft_body->get_vertex_position(p_point_index);
-}
-
-void PhysicsServer3DSW::soft_body_remove_all_pinned_points(RID p_body) {
- SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!soft_body);
-
- soft_body->unpin_all_vertices();
-}
-
-void PhysicsServer3DSW::soft_body_pin_point(RID p_body, int p_point_index, bool p_pin) {
- SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
- ERR_FAIL_COND(!soft_body);
-
- if (p_pin) {
- soft_body->pin_vertex(p_point_index);
- } else {
- soft_body->unpin_vertex(p_point_index);
- }
-}
-
-bool PhysicsServer3DSW::soft_body_is_point_pinned(RID p_body, int p_point_index) const {
- SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body);
- ERR_FAIL_COND_V(!soft_body, false);
-
- return soft_body->is_vertex_pinned(p_point_index);
-}
-
-/* JOINT API */
-
-RID PhysicsServer3DSW::joint_create() {
- Joint3DSW *joint = memnew(Joint3DSW);
- RID rid = joint_owner.make_rid(joint);
- joint->set_self(rid);
- return rid;
-}
-
-void PhysicsServer3DSW::joint_clear(RID p_joint) {
- Joint3DSW *joint = joint_owner.get_or_null(p_joint);
- if (joint->get_type() != JOINT_TYPE_MAX) {
- Joint3DSW *empty_joint = memnew(Joint3DSW);
- empty_joint->copy_settings_from(joint);
-
- joint_owner.replace(p_joint, empty_joint);
- memdelete(joint);
- }
-}
-
-void PhysicsServer3DSW::joint_make_pin(RID p_joint, RID p_body_A, const Vector3 &p_local_A, RID p_body_B, const Vector3 &p_local_B) {
- Body3DSW *body_A = body_owner.get_or_null(p_body_A);
- ERR_FAIL_COND(!body_A);
-
- if (!p_body_B.is_valid()) {
- ERR_FAIL_COND(!body_A->get_space());
- p_body_B = body_A->get_space()->get_static_global_body();
- }
-
- Body3DSW *body_B = body_owner.get_or_null(p_body_B);
- ERR_FAIL_COND(!body_B);
-
- ERR_FAIL_COND(body_A == body_B);
-
- Joint3DSW *prev_joint = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND(prev_joint == nullptr);
-
- Joint3DSW *joint = memnew(PinJoint3DSW(body_A, p_local_A, body_B, p_local_B));
-
- joint->copy_settings_from(prev_joint);
- joint_owner.replace(p_joint, joint);
- memdelete(prev_joint);
-}
-
-void PhysicsServer3DSW::pin_joint_set_param(RID p_joint, PinJointParam p_param, real_t p_value) {
- Joint3DSW *joint = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND(!joint);
- ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_PIN);
- PinJoint3DSW *pin_joint = static_cast<PinJoint3DSW *>(joint);
- pin_joint->set_param(p_param, p_value);
-}
-
-real_t PhysicsServer3DSW::pin_joint_get_param(RID p_joint, PinJointParam p_param) const {
- Joint3DSW *joint = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND_V(!joint, 0);
- ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_PIN, 0);
- PinJoint3DSW *pin_joint = static_cast<PinJoint3DSW *>(joint);
- return pin_joint->get_param(p_param);
-}
-
-void PhysicsServer3DSW::pin_joint_set_local_a(RID p_joint, const Vector3 &p_A) {
- Joint3DSW *joint = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND(!joint);
- ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_PIN);
- PinJoint3DSW *pin_joint = static_cast<PinJoint3DSW *>(joint);
- pin_joint->set_pos_a(p_A);
-}
-
-Vector3 PhysicsServer3DSW::pin_joint_get_local_a(RID p_joint) const {
- Joint3DSW *joint = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND_V(!joint, Vector3());
- ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_PIN, Vector3());
- PinJoint3DSW *pin_joint = static_cast<PinJoint3DSW *>(joint);
- return pin_joint->get_position_a();
-}
-
-void PhysicsServer3DSW::pin_joint_set_local_b(RID p_joint, const Vector3 &p_B) {
- Joint3DSW *joint = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND(!joint);
- ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_PIN);
- PinJoint3DSW *pin_joint = static_cast<PinJoint3DSW *>(joint);
- pin_joint->set_pos_b(p_B);
-}
-
-Vector3 PhysicsServer3DSW::pin_joint_get_local_b(RID p_joint) const {
- Joint3DSW *joint = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND_V(!joint, Vector3());
- ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_PIN, Vector3());
- PinJoint3DSW *pin_joint = static_cast<PinJoint3DSW *>(joint);
- return pin_joint->get_position_b();
-}
-
-void PhysicsServer3DSW::joint_make_hinge(RID p_joint, RID p_body_A, const Transform3D &p_frame_A, RID p_body_B, const Transform3D &p_frame_B) {
- Body3DSW *body_A = body_owner.get_or_null(p_body_A);
- ERR_FAIL_COND(!body_A);
-
- if (!p_body_B.is_valid()) {
- ERR_FAIL_COND(!body_A->get_space());
- p_body_B = body_A->get_space()->get_static_global_body();
- }
-
- Body3DSW *body_B = body_owner.get_or_null(p_body_B);
- ERR_FAIL_COND(!body_B);
-
- ERR_FAIL_COND(body_A == body_B);
-
- Joint3DSW *prev_joint = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND(prev_joint == nullptr);
-
- Joint3DSW *joint = memnew(HingeJoint3DSW(body_A, body_B, p_frame_A, p_frame_B));
-
- joint->copy_settings_from(prev_joint);
- joint_owner.replace(p_joint, joint);
- memdelete(prev_joint);
-}
-
-void PhysicsServer3DSW::joint_make_hinge_simple(RID p_joint, RID p_body_A, const Vector3 &p_pivot_A, const Vector3 &p_axis_A, RID p_body_B, const Vector3 &p_pivot_B, const Vector3 &p_axis_B) {
- Body3DSW *body_A = body_owner.get_or_null(p_body_A);
- ERR_FAIL_COND(!body_A);
-
- if (!p_body_B.is_valid()) {
- ERR_FAIL_COND(!body_A->get_space());
- p_body_B = body_A->get_space()->get_static_global_body();
- }
-
- Body3DSW *body_B = body_owner.get_or_null(p_body_B);
- ERR_FAIL_COND(!body_B);
-
- ERR_FAIL_COND(body_A == body_B);
-
- Joint3DSW *prev_joint = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND(prev_joint == nullptr);
-
- Joint3DSW *joint = memnew(HingeJoint3DSW(body_A, body_B, p_pivot_A, p_pivot_B, p_axis_A, p_axis_B));
-
- joint->copy_settings_from(prev_joint);
- joint_owner.replace(p_joint, joint);
- memdelete(prev_joint);
-}
-
-void PhysicsServer3DSW::hinge_joint_set_param(RID p_joint, HingeJointParam p_param, real_t p_value) {
- Joint3DSW *joint = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND(!joint);
- ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_HINGE);
- HingeJoint3DSW *hinge_joint = static_cast<HingeJoint3DSW *>(joint);
- hinge_joint->set_param(p_param, p_value);
-}
-
-real_t PhysicsServer3DSW::hinge_joint_get_param(RID p_joint, HingeJointParam p_param) const {
- Joint3DSW *joint = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND_V(!joint, 0);
- ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_HINGE, 0);
- HingeJoint3DSW *hinge_joint = static_cast<HingeJoint3DSW *>(joint);
- return hinge_joint->get_param(p_param);
-}
-
-void PhysicsServer3DSW::hinge_joint_set_flag(RID p_joint, HingeJointFlag p_flag, bool p_value) {
- Joint3DSW *joint = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND(!joint);
- ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_HINGE);
- HingeJoint3DSW *hinge_joint = static_cast<HingeJoint3DSW *>(joint);
- hinge_joint->set_flag(p_flag, p_value);
-}
-
-bool PhysicsServer3DSW::hinge_joint_get_flag(RID p_joint, HingeJointFlag p_flag) const {
- Joint3DSW *joint = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND_V(!joint, false);
- ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_HINGE, false);
- HingeJoint3DSW *hinge_joint = static_cast<HingeJoint3DSW *>(joint);
- return hinge_joint->get_flag(p_flag);
-}
-
-void PhysicsServer3DSW::joint_set_solver_priority(RID p_joint, int p_priority) {
- Joint3DSW *joint = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND(!joint);
- joint->set_priority(p_priority);
-}
-
-int PhysicsServer3DSW::joint_get_solver_priority(RID p_joint) const {
- Joint3DSW *joint = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND_V(!joint, 0);
- return joint->get_priority();
-}
-
-void PhysicsServer3DSW::joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) {
- Joint3DSW *joint = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND(!joint);
-
- joint->disable_collisions_between_bodies(p_disable);
-
- if (2 == joint->get_body_count()) {
- Body3DSW *body_a = *joint->get_body_ptr();
- Body3DSW *body_b = *(joint->get_body_ptr() + 1);
-
- if (p_disable) {
- body_add_collision_exception(body_a->get_self(), body_b->get_self());
- body_add_collision_exception(body_b->get_self(), body_a->get_self());
- } else {
- body_remove_collision_exception(body_a->get_self(), body_b->get_self());
- body_remove_collision_exception(body_b->get_self(), body_a->get_self());
- }
- }
-}
-
-bool PhysicsServer3DSW::joint_is_disabled_collisions_between_bodies(RID p_joint) const {
- Joint3DSW *joint = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND_V(!joint, true);
-
- return joint->is_disabled_collisions_between_bodies();
-}
-
-PhysicsServer3DSW::JointType PhysicsServer3DSW::joint_get_type(RID p_joint) const {
- Joint3DSW *joint = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND_V(!joint, JOINT_TYPE_PIN);
- return joint->get_type();
-}
-
-void PhysicsServer3DSW::joint_make_slider(RID p_joint, RID p_body_A, const Transform3D &p_local_frame_A, RID p_body_B, const Transform3D &p_local_frame_B) {
- Body3DSW *body_A = body_owner.get_or_null(p_body_A);
- ERR_FAIL_COND(!body_A);
-
- if (!p_body_B.is_valid()) {
- ERR_FAIL_COND(!body_A->get_space());
- p_body_B = body_A->get_space()->get_static_global_body();
- }
-
- Body3DSW *body_B = body_owner.get_or_null(p_body_B);
- ERR_FAIL_COND(!body_B);
-
- ERR_FAIL_COND(body_A == body_B);
-
- Joint3DSW *prev_joint = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND(prev_joint == nullptr);
-
- Joint3DSW *joint = memnew(SliderJoint3DSW(body_A, body_B, p_local_frame_A, p_local_frame_B));
-
- joint->copy_settings_from(prev_joint);
- joint_owner.replace(p_joint, joint);
- memdelete(prev_joint);
-}
-
-void PhysicsServer3DSW::slider_joint_set_param(RID p_joint, SliderJointParam p_param, real_t p_value) {
- Joint3DSW *joint = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND(!joint);
- ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_SLIDER);
- SliderJoint3DSW *slider_joint = static_cast<SliderJoint3DSW *>(joint);
- slider_joint->set_param(p_param, p_value);
-}
-
-real_t PhysicsServer3DSW::slider_joint_get_param(RID p_joint, SliderJointParam p_param) const {
- Joint3DSW *joint = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND_V(!joint, 0);
- ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_CONE_TWIST, 0);
- SliderJoint3DSW *slider_joint = static_cast<SliderJoint3DSW *>(joint);
- return slider_joint->get_param(p_param);
-}
-
-void PhysicsServer3DSW::joint_make_cone_twist(RID p_joint, RID p_body_A, const Transform3D &p_local_frame_A, RID p_body_B, const Transform3D &p_local_frame_B) {
- Body3DSW *body_A = body_owner.get_or_null(p_body_A);
- ERR_FAIL_COND(!body_A);
-
- if (!p_body_B.is_valid()) {
- ERR_FAIL_COND(!body_A->get_space());
- p_body_B = body_A->get_space()->get_static_global_body();
- }
-
- Body3DSW *body_B = body_owner.get_or_null(p_body_B);
- ERR_FAIL_COND(!body_B);
-
- ERR_FAIL_COND(body_A == body_B);
-
- Joint3DSW *prev_joint = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND(prev_joint == nullptr);
-
- Joint3DSW *joint = memnew(ConeTwistJoint3DSW(body_A, body_B, p_local_frame_A, p_local_frame_B));
-
- joint->copy_settings_from(prev_joint);
- joint_owner.replace(p_joint, joint);
- memdelete(prev_joint);
-}
-
-void PhysicsServer3DSW::cone_twist_joint_set_param(RID p_joint, ConeTwistJointParam p_param, real_t p_value) {
- Joint3DSW *joint = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND(!joint);
- ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_CONE_TWIST);
- ConeTwistJoint3DSW *cone_twist_joint = static_cast<ConeTwistJoint3DSW *>(joint);
- cone_twist_joint->set_param(p_param, p_value);
-}
-
-real_t PhysicsServer3DSW::cone_twist_joint_get_param(RID p_joint, ConeTwistJointParam p_param) const {
- Joint3DSW *joint = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND_V(!joint, 0);
- ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_CONE_TWIST, 0);
- ConeTwistJoint3DSW *cone_twist_joint = static_cast<ConeTwistJoint3DSW *>(joint);
- return cone_twist_joint->get_param(p_param);
-}
-
-void PhysicsServer3DSW::joint_make_generic_6dof(RID p_joint, RID p_body_A, const Transform3D &p_local_frame_A, RID p_body_B, const Transform3D &p_local_frame_B) {
- Body3DSW *body_A = body_owner.get_or_null(p_body_A);
- ERR_FAIL_COND(!body_A);
-
- if (!p_body_B.is_valid()) {
- ERR_FAIL_COND(!body_A->get_space());
- p_body_B = body_A->get_space()->get_static_global_body();
- }
-
- Body3DSW *body_B = body_owner.get_or_null(p_body_B);
- ERR_FAIL_COND(!body_B);
-
- ERR_FAIL_COND(body_A == body_B);
-
- Joint3DSW *prev_joint = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND(prev_joint == nullptr);
-
- Joint3DSW *joint = memnew(Generic6DOFJoint3DSW(body_A, body_B, p_local_frame_A, p_local_frame_B, true));
-
- joint->copy_settings_from(prev_joint);
- joint_owner.replace(p_joint, joint);
- memdelete(prev_joint);
-}
-
-void PhysicsServer3DSW::generic_6dof_joint_set_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param, real_t p_value) {
- Joint3DSW *joint = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND(!joint);
- ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_6DOF);
- Generic6DOFJoint3DSW *generic_6dof_joint = static_cast<Generic6DOFJoint3DSW *>(joint);
- generic_6dof_joint->set_param(p_axis, p_param, p_value);
-}
-
-real_t PhysicsServer3DSW::generic_6dof_joint_get_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param) const {
- Joint3DSW *joint = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND_V(!joint, 0);
- ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_6DOF, 0);
- Generic6DOFJoint3DSW *generic_6dof_joint = static_cast<Generic6DOFJoint3DSW *>(joint);
- return generic_6dof_joint->get_param(p_axis, p_param);
-}
-
-void PhysicsServer3DSW::generic_6dof_joint_set_flag(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisFlag p_flag, bool p_enable) {
- Joint3DSW *joint = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND(!joint);
- ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_6DOF);
- Generic6DOFJoint3DSW *generic_6dof_joint = static_cast<Generic6DOFJoint3DSW *>(joint);
- generic_6dof_joint->set_flag(p_axis, p_flag, p_enable);
-}
-
-bool PhysicsServer3DSW::generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisFlag p_flag) const {
- Joint3DSW *joint = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND_V(!joint, false);
- ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_6DOF, false);
- Generic6DOFJoint3DSW *generic_6dof_joint = static_cast<Generic6DOFJoint3DSW *>(joint);
- return generic_6dof_joint->get_flag(p_axis, p_flag);
-}
-
-void PhysicsServer3DSW::free(RID p_rid) {
- _update_shapes(); //just in case
-
- if (shape_owner.owns(p_rid)) {
- Shape3DSW *shape = shape_owner.get_or_null(p_rid);
-
- while (shape->get_owners().size()) {
- ShapeOwner3DSW *so = shape->get_owners().front()->key();
- so->remove_shape(shape);
- }
-
- shape_owner.free(p_rid);
- memdelete(shape);
- } else if (body_owner.owns(p_rid)) {
- Body3DSW *body = body_owner.get_or_null(p_rid);
-
- /*
- if (body->get_state_query())
- _clear_query(body->get_state_query());
-
- if (body->get_direct_state_query())
- _clear_query(body->get_direct_state_query());
- */
-
- body->set_space(nullptr);
-
- while (body->get_shape_count()) {
- body->remove_shape(0);
- }
-
- body_owner.free(p_rid);
- memdelete(body);
- } else if (soft_body_owner.owns(p_rid)) {
- SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_rid);
-
- soft_body->set_space(nullptr);
-
- soft_body_owner.free(p_rid);
- memdelete(soft_body);
- } else if (area_owner.owns(p_rid)) {
- Area3DSW *area = area_owner.get_or_null(p_rid);
-
- /*
- if (area->get_monitor_query())
- _clear_query(area->get_monitor_query());
- */
-
- area->set_space(nullptr);
-
- while (area->get_shape_count()) {
- area->remove_shape(0);
- }
-
- area_owner.free(p_rid);
- memdelete(area);
- } else if (space_owner.owns(p_rid)) {
- Space3DSW *space = space_owner.get_or_null(p_rid);
-
- while (space->get_objects().size()) {
- CollisionObject3DSW *co = (CollisionObject3DSW *)space->get_objects().front()->get();
- co->set_space(nullptr);
- }
-
- active_spaces.erase(space);
- free(space->get_default_area()->get_self());
- free(space->get_static_global_body());
-
- space_owner.free(p_rid);
- memdelete(space);
- } else if (joint_owner.owns(p_rid)) {
- Joint3DSW *joint = joint_owner.get_or_null(p_rid);
-
- joint_owner.free(p_rid);
- memdelete(joint);
-
- } else {
- ERR_FAIL_MSG("Invalid ID.");
- }
-};
-
-void PhysicsServer3DSW::set_active(bool p_active) {
- active = p_active;
-};
-
-void PhysicsServer3DSW::set_collision_iterations(int p_iterations) {
- iterations = p_iterations;
-};
-
-void PhysicsServer3DSW::init() {
- iterations = 8; // 8?
- stepper = memnew(Step3DSW);
-};
-
-void PhysicsServer3DSW::step(real_t p_step) {
-#ifndef _3D_DISABLED
-
- if (!active) {
- return;
- }
-
- _update_shapes();
-
- island_count = 0;
- active_objects = 0;
- collision_pairs = 0;
- for (Set<const Space3DSW *>::Element *E = active_spaces.front(); E; E = E->next()) {
- stepper->step((Space3DSW *)E->get(), p_step, iterations);
- island_count += E->get()->get_island_count();
- active_objects += E->get()->get_active_objects();
- collision_pairs += E->get()->get_collision_pairs();
- }
-#endif
-}
-
-void PhysicsServer3DSW::sync() {
- doing_sync = true;
-};
-
-void PhysicsServer3DSW::flush_queries() {
-#ifndef _3D_DISABLED
-
- if (!active) {
- return;
- }
-
- flushing_queries = true;
-
- uint64_t time_beg = OS::get_singleton()->get_ticks_usec();
-
- for (Set<const Space3DSW *>::Element *E = active_spaces.front(); E; E = E->next()) {
- Space3DSW *space = (Space3DSW *)E->get();
- space->call_queries();
- }
-
- flushing_queries = false;
-
- if (EngineDebugger::is_profiling("servers")) {
- uint64_t total_time[Space3DSW::ELAPSED_TIME_MAX];
- static const char *time_name[Space3DSW::ELAPSED_TIME_MAX] = {
- "integrate_forces",
- "generate_islands",
- "setup_constraints",
- "solve_constraints",
- "integrate_velocities"
- };
-
- for (int i = 0; i < Space3DSW::ELAPSED_TIME_MAX; i++) {
- total_time[i] = 0;
- }
-
- for (Set<const Space3DSW *>::Element *E = active_spaces.front(); E; E = E->next()) {
- for (int i = 0; i < Space3DSW::ELAPSED_TIME_MAX; i++) {
- total_time[i] += E->get()->get_elapsed_time(Space3DSW::ElapsedTime(i));
- }
- }
-
- Array values;
- values.resize(Space3DSW::ELAPSED_TIME_MAX * 2);
- for (int i = 0; i < Space3DSW::ELAPSED_TIME_MAX; i++) {
- values[i * 2 + 0] = time_name[i];
- values[i * 2 + 1] = USEC_TO_SEC(total_time[i]);
- }
- values.push_back("flush_queries");
- values.push_back(USEC_TO_SEC(OS::get_singleton()->get_ticks_usec() - time_beg));
-
- values.push_front("physics");
- EngineDebugger::profiler_add_frame_data("servers", values);
- }
-#endif
-};
-
-void PhysicsServer3DSW::end_sync() {
- doing_sync = false;
-};
-
-void PhysicsServer3DSW::finish() {
- memdelete(stepper);
-};
-
-int PhysicsServer3DSW::get_process_info(ProcessInfo p_info) {
- switch (p_info) {
- case INFO_ACTIVE_OBJECTS: {
- return active_objects;
- } break;
- case INFO_COLLISION_PAIRS: {
- return collision_pairs;
- } break;
- case INFO_ISLAND_COUNT: {
- return island_count;
- } break;
- }
-
- return 0;
-}
-
-void PhysicsServer3DSW::_update_shapes() {
- while (pending_shape_update_list.first()) {
- pending_shape_update_list.first()->self()->_shape_changed();
- pending_shape_update_list.remove(pending_shape_update_list.first());
- }
-}
-
-void PhysicsServer3DSW::_shape_col_cbk(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) {
- CollCbkData *cbk = (CollCbkData *)p_userdata;
-
- if (cbk->max == 0) {
- return;
- }
-
- if (cbk->amount == cbk->max) {
- //find least deep
- real_t min_depth = 1e20;
- int min_depth_idx = 0;
- for (int i = 0; i < cbk->amount; i++) {
- real_t d = cbk->ptr[i * 2 + 0].distance_squared_to(cbk->ptr[i * 2 + 1]);
- if (d < min_depth) {
- min_depth = d;
- min_depth_idx = i;
- }
- }
-
- real_t d = p_point_A.distance_squared_to(p_point_B);
- if (d < min_depth) {
- return;
- }
- cbk->ptr[min_depth_idx * 2 + 0] = p_point_A;
- cbk->ptr[min_depth_idx * 2 + 1] = p_point_B;
-
- } else {
- cbk->ptr[cbk->amount * 2 + 0] = p_point_A;
- cbk->ptr[cbk->amount * 2 + 1] = p_point_B;
- cbk->amount++;
- }
-}
-
-PhysicsServer3DSW *PhysicsServer3DSW::singletonsw = nullptr;
-PhysicsServer3DSW::PhysicsServer3DSW(bool p_using_threads) {
- singletonsw = this;
- BroadPhase3DSW::create_func = BroadPhase3DBVH::_create;
-
- using_threads = p_using_threads;
-};
diff --git a/servers/physics_3d/space_3d_sw.h b/servers/physics_3d/space_3d_sw.h
deleted file mode 100644
index 69cc3c4bbd..0000000000
--- a/servers/physics_3d/space_3d_sw.h
+++ /dev/null
@@ -1,216 +0,0 @@
-/*************************************************************************/
-/* space_3d_sw.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 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 SPACE_SW_H
-#define SPACE_SW_H
-
-#include "area_3d_sw.h"
-#include "area_pair_3d_sw.h"
-#include "body_3d_sw.h"
-#include "body_pair_3d_sw.h"
-#include "broad_phase_3d_sw.h"
-#include "collision_object_3d_sw.h"
-#include "core/config/project_settings.h"
-#include "core/templates/hash_map.h"
-#include "core/typedefs.h"
-#include "soft_body_3d_sw.h"
-
-class PhysicsDirectSpaceState3DSW : public PhysicsDirectSpaceState3D {
- GDCLASS(PhysicsDirectSpaceState3DSW, PhysicsDirectSpaceState3D);
-
-public:
- Space3DSW *space;
-
- virtual int intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
- virtual bool intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_ray = false) override;
- virtual int intersect_shape(const RID &p_shape, const Transform3D &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
- virtual bool cast_motion(const RID &p_shape, const Transform3D &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, ShapeRestInfo *r_info = nullptr) override;
- virtual bool collide_shape(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
- virtual bool rest_info(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
- virtual Vector3 get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const override;
-
- PhysicsDirectSpaceState3DSW();
-};
-
-class Space3DSW {
-public:
- enum ElapsedTime {
- ELAPSED_TIME_INTEGRATE_FORCES,
- ELAPSED_TIME_GENERATE_ISLANDS,
- ELAPSED_TIME_SETUP_CONSTRAINTS,
- ELAPSED_TIME_SOLVE_CONSTRAINTS,
- ELAPSED_TIME_INTEGRATE_VELOCITIES,
- ELAPSED_TIME_MAX
-
- };
-
-private:
- uint64_t elapsed_time[ELAPSED_TIME_MAX] = {};
-
- PhysicsDirectSpaceState3DSW *direct_access;
- RID self;
-
- BroadPhase3DSW *broadphase;
- SelfList<Body3DSW>::List active_list;
- SelfList<Body3DSW>::List mass_properties_update_list;
- SelfList<Body3DSW>::List state_query_list;
- SelfList<Area3DSW>::List monitor_query_list;
- SelfList<Area3DSW>::List area_moved_list;
- SelfList<SoftBody3DSW>::List active_soft_body_list;
-
- static void *_broadphase_pair(CollisionObject3DSW *A, int p_subindex_A, CollisionObject3DSW *B, int p_subindex_B, void *p_self);
- static void _broadphase_unpair(CollisionObject3DSW *A, int p_subindex_A, CollisionObject3DSW *B, int p_subindex_B, void *p_data, void *p_self);
-
- Set<CollisionObject3DSW *> objects;
-
- Area3DSW *area = nullptr;
-
- real_t contact_recycle_radius = 0.01;
- real_t contact_max_separation = 0.05;
- real_t contact_max_allowed_penetration = 0.01;
- real_t constraint_bias = 0.01;
-
- enum {
- INTERSECTION_QUERY_MAX = 2048
- };
-
- CollisionObject3DSW *intersection_query_results[INTERSECTION_QUERY_MAX];
- int intersection_query_subindex_results[INTERSECTION_QUERY_MAX];
-
- real_t body_linear_velocity_sleep_threshold;
- real_t body_angular_velocity_sleep_threshold;
- real_t body_time_to_sleep;
- real_t body_angular_velocity_damp_ratio;
-
- bool locked = false;
-
- real_t last_step = 0.001;
-
- int island_count = 0;
- int active_objects = 0;
- int collision_pairs = 0;
-
- RID static_global_body;
-
- Vector<Vector3> contact_debug;
- int contact_debug_count = 0;
-
- friend class PhysicsDirectSpaceState3DSW;
-
- int _cull_aabb_for_body(Body3DSW *p_body, const AABB &p_aabb);
-
-public:
- _FORCE_INLINE_ void set_self(const RID &p_self) { self = p_self; }
- _FORCE_INLINE_ RID get_self() const { return self; }
-
- void set_default_area(Area3DSW *p_area) { area = p_area; }
- Area3DSW *get_default_area() const { return area; }
-
- const SelfList<Body3DSW>::List &get_active_body_list() const;
- void body_add_to_active_list(SelfList<Body3DSW> *p_body);
- void body_remove_from_active_list(SelfList<Body3DSW> *p_body);
- void body_add_to_mass_properties_update_list(SelfList<Body3DSW> *p_body);
- void body_remove_from_mass_properties_update_list(SelfList<Body3DSW> *p_body);
-
- void body_add_to_state_query_list(SelfList<Body3DSW> *p_body);
- void body_remove_from_state_query_list(SelfList<Body3DSW> *p_body);
-
- void area_add_to_monitor_query_list(SelfList<Area3DSW> *p_area);
- void area_remove_from_monitor_query_list(SelfList<Area3DSW> *p_area);
- void area_add_to_moved_list(SelfList<Area3DSW> *p_area);
- void area_remove_from_moved_list(SelfList<Area3DSW> *p_area);
- const SelfList<Area3DSW>::List &get_moved_area_list() const;
-
- const SelfList<SoftBody3DSW>::List &get_active_soft_body_list() const;
- void soft_body_add_to_active_list(SelfList<SoftBody3DSW> *p_soft_body);
- void soft_body_remove_from_active_list(SelfList<SoftBody3DSW> *p_soft_body);
-
- BroadPhase3DSW *get_broadphase();
-
- void add_object(CollisionObject3DSW *p_object);
- void remove_object(CollisionObject3DSW *p_object);
- const Set<CollisionObject3DSW *> &get_objects() const;
-
- _FORCE_INLINE_ real_t get_contact_recycle_radius() const { return contact_recycle_radius; }
- _FORCE_INLINE_ real_t get_contact_max_separation() const { return contact_max_separation; }
- _FORCE_INLINE_ real_t get_contact_max_allowed_penetration() const { return contact_max_allowed_penetration; }
- _FORCE_INLINE_ real_t get_constraint_bias() const { return constraint_bias; }
- _FORCE_INLINE_ real_t get_body_linear_velocity_sleep_threshold() const { return body_linear_velocity_sleep_threshold; }
- _FORCE_INLINE_ real_t get_body_angular_velocity_sleep_threshold() const { return body_angular_velocity_sleep_threshold; }
- _FORCE_INLINE_ real_t get_body_time_to_sleep() const { return body_time_to_sleep; }
- _FORCE_INLINE_ real_t get_body_angular_velocity_damp_ratio() const { return body_angular_velocity_damp_ratio; }
-
- void update();
- void setup();
- void call_queries();
-
- bool is_locked() const;
- void lock();
- void unlock();
-
- real_t get_last_step() const { return last_step; }
- void set_last_step(real_t p_step) { last_step = p_step; }
-
- void set_param(PhysicsServer3D::SpaceParameter p_param, real_t p_value);
- real_t get_param(PhysicsServer3D::SpaceParameter p_param) const;
-
- void set_island_count(int p_island_count) { island_count = p_island_count; }
- int get_island_count() const { return island_count; }
-
- void set_active_objects(int p_active_objects) { active_objects = p_active_objects; }
- int get_active_objects() const { return active_objects; }
-
- int get_collision_pairs() const { return collision_pairs; }
-
- PhysicsDirectSpaceState3DSW *get_direct_state();
-
- void set_debug_contacts(int p_amount) { contact_debug.resize(p_amount); }
- _FORCE_INLINE_ bool is_debugging_contacts() const { return !contact_debug.is_empty(); }
- _FORCE_INLINE_ void add_debug_contact(const Vector3 &p_contact) {
- if (contact_debug_count < contact_debug.size()) {
- contact_debug.write[contact_debug_count++] = p_contact;
- }
- }
- _FORCE_INLINE_ Vector<Vector3> get_debug_contacts() { return contact_debug; }
- _FORCE_INLINE_ int get_debug_contact_count() { return contact_debug_count; }
-
- void set_static_global_body(RID p_body) { static_global_body = p_body; }
- RID get_static_global_body() { return static_global_body; }
-
- void set_elapsed_time(ElapsedTime p_time, uint64_t p_msec) { elapsed_time[p_time] = p_msec; }
- uint64_t get_elapsed_time(ElapsedTime p_time) const { return elapsed_time[p_time]; }
-
- bool test_body_motion(Body3DSW *p_body, const PhysicsServer3D::MotionParameters &p_parameters, PhysicsServer3D::MotionResult *r_result);
-
- Space3DSW();
- ~Space3DSW();
-};
-
-#endif // SPACE__SW_H
diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp
index a6cb7dbdd9..d8f2a2a780 100644
--- a/servers/physics_server_2d.cpp
+++ b/servers/physics_server_2d.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -78,6 +78,7 @@ void PhysicsDirectBodyState2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_total_angular_damp"), &PhysicsDirectBodyState2D::get_total_angular_damp);
ClassDB::bind_method(D_METHOD("get_center_of_mass"), &PhysicsDirectBodyState2D::get_center_of_mass);
+ ClassDB::bind_method(D_METHOD("get_center_of_mass_local"), &PhysicsDirectBodyState2D::get_center_of_mass_local);
ClassDB::bind_method(D_METHOD("get_inverse_mass"), &PhysicsDirectBodyState2D::get_inverse_mass);
ClassDB::bind_method(D_METHOD("get_inverse_inertia"), &PhysicsDirectBodyState2D::get_inverse_inertia);
@@ -92,13 +93,24 @@ void PhysicsDirectBodyState2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_velocity_at_local_position", "local_position"), &PhysicsDirectBodyState2D::get_velocity_at_local_position);
- ClassDB::bind_method(D_METHOD("add_central_force", "force"), &PhysicsDirectBodyState2D::add_central_force);
- ClassDB::bind_method(D_METHOD("add_force", "force", "position"), &PhysicsDirectBodyState2D::add_force, Vector2());
- ClassDB::bind_method(D_METHOD("add_torque", "torque"), &PhysicsDirectBodyState2D::add_torque);
ClassDB::bind_method(D_METHOD("apply_central_impulse", "impulse"), &PhysicsDirectBodyState2D::apply_central_impulse);
ClassDB::bind_method(D_METHOD("apply_torque_impulse", "impulse"), &PhysicsDirectBodyState2D::apply_torque_impulse);
ClassDB::bind_method(D_METHOD("apply_impulse", "impulse", "position"), &PhysicsDirectBodyState2D::apply_impulse, Vector2());
+ ClassDB::bind_method(D_METHOD("apply_central_force", "force"), &PhysicsDirectBodyState2D::apply_central_force, Vector2());
+ ClassDB::bind_method(D_METHOD("apply_force", "force", "position"), &PhysicsDirectBodyState2D::apply_force, Vector2());
+ ClassDB::bind_method(D_METHOD("apply_torque", "torque"), &PhysicsDirectBodyState2D::apply_torque);
+
+ ClassDB::bind_method(D_METHOD("add_constant_central_force", "force"), &PhysicsDirectBodyState2D::add_constant_central_force, Vector2());
+ ClassDB::bind_method(D_METHOD("add_constant_force", "force", "position"), &PhysicsDirectBodyState2D::add_constant_force, Vector2());
+ ClassDB::bind_method(D_METHOD("add_constant_torque", "torque"), &PhysicsDirectBodyState2D::add_constant_torque);
+
+ ClassDB::bind_method(D_METHOD("set_constant_force", "force"), &PhysicsDirectBodyState2D::set_constant_force);
+ ClassDB::bind_method(D_METHOD("get_constant_force"), &PhysicsDirectBodyState2D::get_constant_force);
+
+ ClassDB::bind_method(D_METHOD("set_constant_torque", "torque"), &PhysicsDirectBodyState2D::set_constant_torque);
+ ClassDB::bind_method(D_METHOD("get_constant_torque"), &PhysicsDirectBodyState2D::get_constant_torque);
+
ClassDB::bind_method(D_METHOD("set_sleep_state", "enabled"), &PhysicsDirectBodyState2D::set_sleep_state);
ClassDB::bind_method(D_METHOD("is_sleeping"), &PhysicsDirectBodyState2D::is_sleeping);
@@ -124,6 +136,7 @@ void PhysicsDirectBodyState2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "total_linear_damp"), "", "get_total_linear_damp");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "total_gravity"), "", "get_total_gravity");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "center_of_mass"), "", "get_center_of_mass");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "center_of_mass_local"), "", "get_center_of_mass_local");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_velocity"), "set_angular_velocity", "get_angular_velocity");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "linear_velocity"), "set_linear_velocity", "get_linear_velocity");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sleeping"), "set_sleep_state", "is_sleeping");
@@ -134,95 +147,136 @@ PhysicsDirectBodyState2D::PhysicsDirectBodyState2D() {}
///////////////////////////////////////////////////////
-void PhysicsShapeQueryParameters2D::set_shape(const RES &p_shape_ref) {
- ERR_FAIL_COND(p_shape_ref.is_null());
- shape_ref = p_shape_ref;
- shape = p_shape_ref->get_rid();
-}
-
-RES PhysicsShapeQueryParameters2D::get_shape() const {
- return shape_ref;
+void PhysicsRayQueryParameters2D::set_exclude(const Vector<RID> &p_exclude) {
+ parameters.exclude.clear();
+ for (int i = 0; i < p_exclude.size(); i++) {
+ parameters.exclude.insert(p_exclude[i]);
+ }
}
-void PhysicsShapeQueryParameters2D::set_shape_rid(const RID &p_shape) {
- if (shape != p_shape) {
- shape_ref = RES();
- shape = p_shape;
+Vector<RID> PhysicsRayQueryParameters2D::get_exclude() const {
+ Vector<RID> ret;
+ ret.resize(parameters.exclude.size());
+ int idx = 0;
+ for (Set<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) {
+ ret.write[idx++] = E->get();
}
+ return ret;
}
-RID PhysicsShapeQueryParameters2D::get_shape_rid() const {
- return shape;
-}
+void PhysicsRayQueryParameters2D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_from", "from"), &PhysicsRayQueryParameters2D::set_from);
+ ClassDB::bind_method(D_METHOD("get_from"), &PhysicsRayQueryParameters2D::get_from);
-void PhysicsShapeQueryParameters2D::set_transform(const Transform2D &p_transform) {
- transform = p_transform;
-}
+ ClassDB::bind_method(D_METHOD("set_to", "to"), &PhysicsRayQueryParameters2D::set_to);
+ ClassDB::bind_method(D_METHOD("get_to"), &PhysicsRayQueryParameters2D::get_to);
-Transform2D PhysicsShapeQueryParameters2D::get_transform() const {
- return transform;
-}
+ ClassDB::bind_method(D_METHOD("set_collision_mask", "collision_mask"), &PhysicsRayQueryParameters2D::set_collision_mask);
+ ClassDB::bind_method(D_METHOD("get_collision_mask"), &PhysicsRayQueryParameters2D::get_collision_mask);
-void PhysicsShapeQueryParameters2D::set_motion(const Vector2 &p_motion) {
- motion = p_motion;
-}
+ ClassDB::bind_method(D_METHOD("set_exclude", "exclude"), &PhysicsRayQueryParameters2D::set_exclude);
+ ClassDB::bind_method(D_METHOD("get_exclude"), &PhysicsRayQueryParameters2D::get_exclude);
-Vector2 PhysicsShapeQueryParameters2D::get_motion() const {
- return motion;
-}
+ ClassDB::bind_method(D_METHOD("set_collide_with_bodies", "enable"), &PhysicsRayQueryParameters2D::set_collide_with_bodies);
+ ClassDB::bind_method(D_METHOD("is_collide_with_bodies_enabled"), &PhysicsRayQueryParameters2D::is_collide_with_bodies_enabled);
-void PhysicsShapeQueryParameters2D::set_margin(real_t p_margin) {
- margin = p_margin;
-}
+ ClassDB::bind_method(D_METHOD("set_collide_with_areas", "enable"), &PhysicsRayQueryParameters2D::set_collide_with_areas);
+ ClassDB::bind_method(D_METHOD("is_collide_with_areas_enabled"), &PhysicsRayQueryParameters2D::is_collide_with_areas_enabled);
-real_t PhysicsShapeQueryParameters2D::get_margin() const {
- return margin;
-}
+ ClassDB::bind_method(D_METHOD("set_hit_from_inside", "enable"), &PhysicsRayQueryParameters2D::set_hit_from_inside);
+ ClassDB::bind_method(D_METHOD("is_hit_from_inside_enabled"), &PhysicsRayQueryParameters2D::is_hit_from_inside_enabled);
-void PhysicsShapeQueryParameters2D::set_collision_mask(uint32_t p_collision_mask) {
- collision_mask = p_collision_mask;
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "from"), "set_from", "get_from");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "to"), "set_to", "get_to");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_mask", "get_collision_mask");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_exclude", "get_exclude");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_bodies"), "set_collide_with_bodies", "is_collide_with_bodies_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas"), "set_collide_with_areas", "is_collide_with_areas_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hit_from_inside"), "set_hit_from_inside", "is_hit_from_inside_enabled");
}
-uint32_t PhysicsShapeQueryParameters2D::get_collision_mask() const {
- return collision_mask;
-}
+///////////////////////////////////////////////////////
-void PhysicsShapeQueryParameters2D::set_exclude(const Vector<RID> &p_exclude) {
- exclude.clear();
+void PhysicsPointQueryParameters2D::set_exclude(const Vector<RID> &p_exclude) {
+ parameters.exclude.clear();
for (int i = 0; i < p_exclude.size(); i++) {
- exclude.insert(p_exclude[i]);
+ parameters.exclude.insert(p_exclude[i]);
}
}
-Vector<RID> PhysicsShapeQueryParameters2D::get_exclude() const {
+Vector<RID> PhysicsPointQueryParameters2D::get_exclude() const {
Vector<RID> ret;
- ret.resize(exclude.size());
+ ret.resize(parameters.exclude.size());
int idx = 0;
- for (Set<RID>::Element *E = exclude.front(); E; E = E->next()) {
+ for (Set<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) {
ret.write[idx++] = E->get();
}
return ret;
}
-void PhysicsShapeQueryParameters2D::set_collide_with_bodies(bool p_enable) {
- collide_with_bodies = p_enable;
+void PhysicsPointQueryParameters2D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_position", "position"), &PhysicsPointQueryParameters2D::set_position);
+ ClassDB::bind_method(D_METHOD("get_position"), &PhysicsPointQueryParameters2D::get_position);
+
+ ClassDB::bind_method(D_METHOD("set_canvas_instance_id", "canvas_instance_id"), &PhysicsPointQueryParameters2D::set_canvas_instance_id);
+ ClassDB::bind_method(D_METHOD("get_canvas_instance_id"), &PhysicsPointQueryParameters2D::get_canvas_instance_id);
+
+ ClassDB::bind_method(D_METHOD("set_collision_mask", "collision_mask"), &PhysicsPointQueryParameters2D::set_collision_mask);
+ ClassDB::bind_method(D_METHOD("get_collision_mask"), &PhysicsPointQueryParameters2D::get_collision_mask);
+
+ ClassDB::bind_method(D_METHOD("set_exclude", "exclude"), &PhysicsPointQueryParameters2D::set_exclude);
+ ClassDB::bind_method(D_METHOD("get_exclude"), &PhysicsPointQueryParameters2D::get_exclude);
+
+ ClassDB::bind_method(D_METHOD("set_collide_with_bodies", "enable"), &PhysicsPointQueryParameters2D::set_collide_with_bodies);
+ ClassDB::bind_method(D_METHOD("is_collide_with_bodies_enabled"), &PhysicsPointQueryParameters2D::is_collide_with_bodies_enabled);
+
+ ClassDB::bind_method(D_METHOD("set_collide_with_areas", "enable"), &PhysicsPointQueryParameters2D::set_collide_with_areas);
+ ClassDB::bind_method(D_METHOD("is_collide_with_areas_enabled"), &PhysicsPointQueryParameters2D::is_collide_with_areas_enabled);
+
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position"), "set_position", "get_position");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "canvas_instance_id", PROPERTY_HINT_OBJECT_ID), "set_canvas_instance_id", "get_canvas_instance_id");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_mask", "get_collision_mask");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_exclude", "get_exclude");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_bodies"), "set_collide_with_bodies", "is_collide_with_bodies_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas"), "set_collide_with_areas", "is_collide_with_areas_enabled");
}
-bool PhysicsShapeQueryParameters2D::is_collide_with_bodies_enabled() const {
- return collide_with_bodies;
+///////////////////////////////////////////////////////
+
+void PhysicsShapeQueryParameters2D::set_shape(const RES &p_shape_ref) {
+ ERR_FAIL_COND(p_shape_ref.is_null());
+ shape_ref = p_shape_ref;
+ parameters.shape_rid = p_shape_ref->get_rid();
}
-void PhysicsShapeQueryParameters2D::set_collide_with_areas(bool p_enable) {
- collide_with_areas = p_enable;
+void PhysicsShapeQueryParameters2D::set_shape_rid(const RID &p_shape) {
+ if (parameters.shape_rid != p_shape) {
+ shape_ref = RES();
+ parameters.shape_rid = p_shape;
+ }
}
-bool PhysicsShapeQueryParameters2D::is_collide_with_areas_enabled() const {
- return collide_with_areas;
+void PhysicsShapeQueryParameters2D::set_exclude(const Vector<RID> &p_exclude) {
+ parameters.exclude.clear();
+ for (int i = 0; i < p_exclude.size(); i++) {
+ parameters.exclude.insert(p_exclude[i]);
+ }
+}
+
+Vector<RID> PhysicsShapeQueryParameters2D::get_exclude() const {
+ Vector<RID> ret;
+ ret.resize(parameters.exclude.size());
+ int idx = 0;
+ for (Set<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) {
+ ret.write[idx++] = E->get();
+ }
+ return ret;
}
void PhysicsShapeQueryParameters2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_shape", "shape"), &PhysicsShapeQueryParameters2D::set_shape);
ClassDB::bind_method(D_METHOD("get_shape"), &PhysicsShapeQueryParameters2D::get_shape);
+
ClassDB::bind_method(D_METHOD("set_shape_rid", "shape"), &PhysicsShapeQueryParameters2D::set_shape_rid);
ClassDB::bind_method(D_METHOD("get_shape_rid"), &PhysicsShapeQueryParameters2D::get_shape_rid);
@@ -248,7 +302,7 @@ void PhysicsShapeQueryParameters2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_collide_with_areas_enabled"), &PhysicsShapeQueryParameters2D::is_collide_with_areas_enabled);
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_mask", "get_collision_mask");
- ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_NONE, itos(Variant::RID) + ":"), "set_exclude", "get_exclude");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_exclude", "get_exclude");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin", PROPERTY_HINT_RANGE, "0,100,0.01"), "set_margin", "get_margin");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion"), "set_motion", "get_motion");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape2D"), "set_shape", "get_shape");
@@ -258,36 +312,58 @@ void PhysicsShapeQueryParameters2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas"), "set_collide_with_areas", "is_collide_with_areas_enabled");
}
-Dictionary PhysicsDirectSpaceState2D::_intersect_ray(const Vector2 &p_from, const Vector2 &p_to, const Vector<RID> &p_exclude, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas) {
- RayResult inters;
- Set<RID> exclude;
- for (int i = 0; i < p_exclude.size(); i++) {
- exclude.insert(p_exclude[i]);
- }
+///////////////////////////////////////////////////////
+
+Dictionary PhysicsDirectSpaceState2D::_intersect_ray(const Ref<PhysicsRayQueryParameters2D> &p_ray_query) {
+ ERR_FAIL_COND_V(!p_ray_query.is_valid(), Dictionary());
- bool res = intersect_ray(p_from, p_to, inters, exclude, p_layers, p_collide_with_bodies, p_collide_with_areas);
+ RayResult result;
+ bool res = intersect_ray(p_ray_query->get_parameters(), result);
if (!res) {
return Dictionary();
}
Dictionary d;
- d["position"] = inters.position;
- d["normal"] = inters.normal;
- d["collider_id"] = inters.collider_id;
- d["collider"] = inters.collider;
- d["shape"] = inters.shape;
- d["rid"] = inters.rid;
+ d["position"] = result.position;
+ d["normal"] = result.normal;
+ d["collider_id"] = result.collider_id;
+ d["collider"] = result.collider;
+ d["shape"] = result.shape;
+ d["rid"] = result.rid;
return d;
}
+Array PhysicsDirectSpaceState2D::_intersect_point(const Ref<PhysicsPointQueryParameters2D> &p_point_query, int p_max_results) {
+ Vector<ShapeResult> ret;
+ ret.resize(p_max_results);
+
+ int rc = intersect_point(p_point_query->get_parameters(), ret.ptrw(), ret.size());
+
+ if (rc == 0) {
+ return Array();
+ }
+
+ Array r;
+ r.resize(rc);
+ for (int i = 0; i < rc; i++) {
+ Dictionary d;
+ d["rid"] = ret[i].rid;
+ d["collider_id"] = ret[i].collider_id;
+ d["collider"] = ret[i].collider;
+ d["shape"] = ret[i].shape;
+ r[i] = d;
+ }
+ return r;
+}
+
Array PhysicsDirectSpaceState2D::_intersect_shape(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query, int p_max_results) {
ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array());
Vector<ShapeResult> sr;
sr.resize(p_max_results);
- int rc = intersect_shape(p_shape_query->shape, p_shape_query->transform, p_shape_query->motion, p_shape_query->margin, sr.ptrw(), sr.size(), p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas);
+ int rc = intersect_shape(p_shape_query->get_parameters(), sr.ptrw(), sr.size());
Array ret;
ret.resize(rc);
for (int i = 0; i < rc; i++) {
@@ -306,7 +382,7 @@ Array PhysicsDirectSpaceState2D::_cast_motion(const Ref<PhysicsShapeQueryParamet
ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array());
real_t closest_safe, closest_unsafe;
- bool res = cast_motion(p_shape_query->shape, p_shape_query->transform, p_shape_query->motion, p_shape_query->margin, closest_safe, closest_unsafe, p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas);
+ bool res = cast_motion(p_shape_query->get_parameters(), closest_safe, closest_unsafe);
if (!res) {
return Array();
}
@@ -317,54 +393,13 @@ Array PhysicsDirectSpaceState2D::_cast_motion(const Ref<PhysicsShapeQueryParamet
return ret;
}
-Array PhysicsDirectSpaceState2D::_intersect_point_impl(const Vector2 &p_point, int p_max_results, const Vector<RID> &p_exclude, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_filter_by_canvas, ObjectID p_canvas_instance_id) {
- Set<RID> exclude;
- for (int i = 0; i < p_exclude.size(); i++) {
- exclude.insert(p_exclude[i]);
- }
-
- Vector<ShapeResult> ret;
- ret.resize(p_max_results);
-
- int rc;
- if (p_filter_by_canvas) {
- rc = intersect_point(p_point, ret.ptrw(), ret.size(), exclude, p_layers, p_collide_with_bodies, p_collide_with_areas);
- } else {
- rc = intersect_point_on_canvas(p_point, p_canvas_instance_id, ret.ptrw(), ret.size(), exclude, p_layers, p_collide_with_bodies, p_collide_with_areas);
- }
-
- if (rc == 0) {
- return Array();
- }
-
- Array r;
- r.resize(rc);
- for (int i = 0; i < rc; i++) {
- Dictionary d;
- d["rid"] = ret[i].rid;
- d["collider_id"] = ret[i].collider_id;
- d["collider"] = ret[i].collider;
- d["shape"] = ret[i].shape;
- r[i] = d;
- }
- return r;
-}
-
-Array PhysicsDirectSpaceState2D::_intersect_point(const Vector2 &p_point, int p_max_results, const Vector<RID> &p_exclude, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas) {
- return _intersect_point_impl(p_point, p_max_results, p_exclude, p_layers, p_collide_with_bodies, p_collide_with_areas);
-}
-
-Array PhysicsDirectSpaceState2D::_intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_intance_id, int p_max_results, const Vector<RID> &p_exclude, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas) {
- return _intersect_point_impl(p_point, p_max_results, p_exclude, p_layers, p_collide_with_bodies, p_collide_with_areas, true, p_canvas_intance_id);
-}
-
Array PhysicsDirectSpaceState2D::_collide_shape(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query, int p_max_results) {
ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array());
Vector<Vector2> ret;
ret.resize(p_max_results * 2);
int rc = 0;
- bool res = collide_shape(p_shape_query->shape, p_shape_query->transform, p_shape_query->motion, p_shape_query->margin, ret.ptrw(), p_max_results, rc, p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas);
+ bool res = collide_shape(p_shape_query->get_parameters(), ret.ptrw(), p_max_results, rc);
if (!res) {
return Array();
}
@@ -381,7 +416,7 @@ Dictionary PhysicsDirectSpaceState2D::_get_rest_info(const Ref<PhysicsShapeQuery
ShapeRestInfo sri;
- bool res = rest_info(p_shape_query->shape, p_shape_query->transform, p_shape_query->motion, p_shape_query->margin, &sri, p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas);
+ bool res = rest_info(p_shape_query->get_parameters(), &sri);
Dictionary r;
if (!res) {
return r;
@@ -401,13 +436,12 @@ PhysicsDirectSpaceState2D::PhysicsDirectSpaceState2D() {
}
void PhysicsDirectSpaceState2D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("intersect_point", "point", "max_results", "exclude", "collision_mask", "collide_with_bodies", "collide_with_areas"), &PhysicsDirectSpaceState2D::_intersect_point, DEFVAL(32), DEFVAL(Array()), DEFVAL(UINT32_MAX), DEFVAL(true), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("intersect_point_on_canvas", "point", "canvas_instance_id", "max_results", "exclude", "collision_mask", "collide_with_bodies", "collide_with_areas"), &PhysicsDirectSpaceState2D::_intersect_point_on_canvas, DEFVAL(32), DEFVAL(Array()), DEFVAL(UINT32_MAX), DEFVAL(true), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("intersect_ray", "from", "to", "exclude", "collision_mask", "collide_with_bodies", "collide_with_areas"), &PhysicsDirectSpaceState2D::_intersect_ray, DEFVAL(Array()), DEFVAL(UINT32_MAX), DEFVAL(true), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("intersect_shape", "shape", "max_results"), &PhysicsDirectSpaceState2D::_intersect_shape, DEFVAL(32));
- ClassDB::bind_method(D_METHOD("cast_motion", "shape"), &PhysicsDirectSpaceState2D::_cast_motion);
- ClassDB::bind_method(D_METHOD("collide_shape", "shape", "max_results"), &PhysicsDirectSpaceState2D::_collide_shape, DEFVAL(32));
- ClassDB::bind_method(D_METHOD("get_rest_info", "shape"), &PhysicsDirectSpaceState2D::_get_rest_info);
+ ClassDB::bind_method(D_METHOD("intersect_point", "parameters", "max_results"), &PhysicsDirectSpaceState2D::_intersect_point, DEFVAL(32));
+ ClassDB::bind_method(D_METHOD("intersect_ray", "parameters"), &PhysicsDirectSpaceState2D::_intersect_ray);
+ ClassDB::bind_method(D_METHOD("intersect_shape", "parameters", "max_results"), &PhysicsDirectSpaceState2D::_intersect_shape, DEFVAL(32));
+ ClassDB::bind_method(D_METHOD("cast_motion", "parameters"), &PhysicsDirectSpaceState2D::_cast_motion);
+ ClassDB::bind_method(D_METHOD("collide_shape", "parameters", "max_results"), &PhysicsDirectSpaceState2D::_collide_shape, DEFVAL(32));
+ ClassDB::bind_method(D_METHOD("get_rest_info", "parameters"), &PhysicsDirectSpaceState2D::_get_rest_info);
}
///////////////////////////////
@@ -473,7 +507,7 @@ void PhysicsTestMotionParameters2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion"), "set_motion", "get_motion");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin"), "set_margin", "get_margin");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_separation_ray"), "set_collide_separation_ray_enabled", "is_collide_separation_ray_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude_bodies"), "set_exclude_bodies", "get_exclude_bodies");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude_bodies", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_exclude_bodies", "get_exclude_bodies");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude_objects"), "set_exclude_objects", "get_exclude_objects");
}
@@ -586,9 +620,6 @@ void PhysicsServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("area_set_space", "area", "space"), &PhysicsServer2D::area_set_space);
ClassDB::bind_method(D_METHOD("area_get_space", "area"), &PhysicsServer2D::area_get_space);
- ClassDB::bind_method(D_METHOD("area_set_space_override_mode", "area", "mode"), &PhysicsServer2D::area_set_space_override_mode);
- ClassDB::bind_method(D_METHOD("area_get_space_override_mode", "area"), &PhysicsServer2D::area_get_space_override_mode);
-
ClassDB::bind_method(D_METHOD("area_add_shape", "area", "shape", "transform", "disabled"), &PhysicsServer2D::area_add_shape, DEFVAL(Transform2D()), DEFVAL(false));
ClassDB::bind_method(D_METHOD("area_set_shape", "area", "shape_idx", "shape"), &PhysicsServer2D::area_set_shape);
ClassDB::bind_method(D_METHOD("area_set_shape_transform", "area", "shape_idx", "transform"), &PhysicsServer2D::area_set_shape_transform);
@@ -616,8 +647,8 @@ void PhysicsServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("area_attach_canvas_instance_id", "area", "id"), &PhysicsServer2D::area_attach_canvas_instance_id);
ClassDB::bind_method(D_METHOD("area_get_canvas_instance_id", "area"), &PhysicsServer2D::area_get_canvas_instance_id);
- ClassDB::bind_method(D_METHOD("area_set_monitor_callback", "area", "receiver", "method"), &PhysicsServer2D::area_set_monitor_callback);
- ClassDB::bind_method(D_METHOD("area_set_area_monitor_callback", "area", "receiver", "method"), &PhysicsServer2D::area_set_area_monitor_callback);
+ ClassDB::bind_method(D_METHOD("area_set_monitor_callback", "area", "callback"), &PhysicsServer2D::area_set_monitor_callback);
+ ClassDB::bind_method(D_METHOD("area_set_area_monitor_callback", "area", "callback"), &PhysicsServer2D::area_set_area_monitor_callback);
ClassDB::bind_method(D_METHOD("area_set_monitorable", "area", "monitorable"), &PhysicsServer2D::area_set_monitorable);
ClassDB::bind_method(D_METHOD("body_create"), &PhysicsServer2D::body_create);
@@ -668,9 +699,21 @@ void PhysicsServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("body_apply_central_impulse", "body", "impulse"), &PhysicsServer2D::body_apply_central_impulse);
ClassDB::bind_method(D_METHOD("body_apply_torque_impulse", "body", "impulse"), &PhysicsServer2D::body_apply_torque_impulse);
ClassDB::bind_method(D_METHOD("body_apply_impulse", "body", "impulse", "position"), &PhysicsServer2D::body_apply_impulse, Vector2());
- ClassDB::bind_method(D_METHOD("body_add_central_force", "body", "force"), &PhysicsServer2D::body_add_central_force);
- ClassDB::bind_method(D_METHOD("body_add_force", "body", "force", "position"), &PhysicsServer2D::body_add_force, Vector2());
- ClassDB::bind_method(D_METHOD("body_add_torque", "body", "torque"), &PhysicsServer2D::body_add_torque);
+
+ ClassDB::bind_method(D_METHOD("body_apply_central_force", "body", "force"), &PhysicsServer2D::body_apply_central_force);
+ ClassDB::bind_method(D_METHOD("body_apply_force", "body", "force", "position"), &PhysicsServer2D::body_apply_force, Vector2());
+ ClassDB::bind_method(D_METHOD("body_apply_torque", "body", "torque"), &PhysicsServer2D::body_apply_torque);
+
+ ClassDB::bind_method(D_METHOD("body_add_constant_central_force", "body", "force"), &PhysicsServer2D::body_add_constant_central_force);
+ ClassDB::bind_method(D_METHOD("body_add_constant_force", "body", "force", "position"), &PhysicsServer2D::body_add_constant_force, Vector2());
+ ClassDB::bind_method(D_METHOD("body_add_constant_torque", "body", "torque"), &PhysicsServer2D::body_add_constant_torque);
+
+ ClassDB::bind_method(D_METHOD("body_set_constant_force", "body", "force"), &PhysicsServer2D::body_set_constant_force);
+ ClassDB::bind_method(D_METHOD("body_get_constant_force", "body"), &PhysicsServer2D::body_get_constant_force);
+
+ ClassDB::bind_method(D_METHOD("body_set_constant_torque", "body", "torque"), &PhysicsServer2D::body_set_constant_torque);
+ ClassDB::bind_method(D_METHOD("body_get_constant_torque", "body"), &PhysicsServer2D::body_get_constant_torque);
+
ClassDB::bind_method(D_METHOD("body_set_axis_velocity", "body", "axis_velocity"), &PhysicsServer2D::body_set_axis_velocity);
ClassDB::bind_method(D_METHOD("body_add_collision_exception", "body", "excepted_body"), &PhysicsServer2D::body_add_collision_exception);
@@ -710,17 +753,17 @@ void PhysicsServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_active", "active"), &PhysicsServer2D::set_active);
- ClassDB::bind_method(D_METHOD("set_collision_iterations", "iterations"), &PhysicsServer2D::set_collision_iterations);
-
ClassDB::bind_method(D_METHOD("get_process_info", "process_info"), &PhysicsServer2D::get_process_info);
BIND_ENUM_CONSTANT(SPACE_PARAM_CONTACT_RECYCLE_RADIUS);
BIND_ENUM_CONSTANT(SPACE_PARAM_CONTACT_MAX_SEPARATION);
- BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION);
+ BIND_ENUM_CONSTANT(SPACE_PARAM_CONTACT_MAX_ALLOWED_PENETRATION);
+ BIND_ENUM_CONSTANT(SPACE_PARAM_CONTACT_DEFAULT_BIAS);
BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD);
BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD);
BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_TIME_TO_SLEEP);
BIND_ENUM_CONSTANT(SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS);
+ BIND_ENUM_CONSTANT(SPACE_PARAM_SOLVER_ITERATIONS);
BIND_ENUM_CONSTANT(SHAPE_WORLD_BOUNDARY);
BIND_ENUM_CONSTANT(SHAPE_SEPARATION_RAY);
@@ -732,12 +775,15 @@ void PhysicsServer2D::_bind_methods() {
BIND_ENUM_CONSTANT(SHAPE_CONCAVE_POLYGON);
BIND_ENUM_CONSTANT(SHAPE_CUSTOM);
+ BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_OVERRIDE_MODE);
BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY);
BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_VECTOR);
BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_IS_POINT);
BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_DISTANCE_SCALE);
BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_POINT_ATTENUATION);
+ BIND_ENUM_CONSTANT(AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE);
BIND_ENUM_CONSTANT(AREA_PARAM_LINEAR_DAMP);
+ BIND_ENUM_CONSTANT(AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE);
BIND_ENUM_CONSTANT(AREA_PARAM_ANGULAR_DAMP);
BIND_ENUM_CONSTANT(AREA_PARAM_PRIORITY);
@@ -758,10 +804,15 @@ void PhysicsServer2D::_bind_methods() {
BIND_ENUM_CONSTANT(BODY_PARAM_INERTIA);
BIND_ENUM_CONSTANT(BODY_PARAM_CENTER_OF_MASS);
BIND_ENUM_CONSTANT(BODY_PARAM_GRAVITY_SCALE);
+ BIND_ENUM_CONSTANT(BODY_PARAM_LINEAR_DAMP_MODE);
+ BIND_ENUM_CONSTANT(BODY_PARAM_ANGULAR_DAMP_MODE);
BIND_ENUM_CONSTANT(BODY_PARAM_LINEAR_DAMP);
BIND_ENUM_CONSTANT(BODY_PARAM_ANGULAR_DAMP);
BIND_ENUM_CONSTANT(BODY_PARAM_MAX);
+ BIND_ENUM_CONSTANT(BODY_DAMP_MODE_COMBINE);
+ BIND_ENUM_CONSTANT(BODY_DAMP_MODE_REPLACE);
+
BIND_ENUM_CONSTANT(BODY_STATE_TRANSFORM);
BIND_ENUM_CONSTANT(BODY_STATE_LINEAR_VELOCITY);
BIND_ENUM_CONSTANT(BODY_STATE_ANGULAR_VELOCITY);
diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h
index 26e1411111..e9faf0a3bf 100644
--- a/servers/physics_server_2d.h
+++ b/servers/physics_server_2d.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef PHYSICS_2D_SERVER_H
-#define PHYSICS_2D_SERVER_H
+#ifndef PHYSICS_SERVER_2D_H
+#define PHYSICS_SERVER_2D_H
#include "core/io/resource.h"
#include "core/object/class_db.h"
@@ -49,6 +49,7 @@ public:
virtual real_t get_total_angular_damp() const = 0; // get density of this body space/area
virtual Vector2 get_center_of_mass() const = 0;
+ virtual Vector2 get_center_of_mass_local() const = 0;
virtual real_t get_inverse_mass() const = 0; // get the mass
virtual real_t get_inverse_inertia() const = 0; // get density of this body space
@@ -63,13 +64,24 @@ public:
virtual Vector2 get_velocity_at_local_position(const Vector2 &p_position) const = 0;
- virtual void add_central_force(const Vector2 &p_force) = 0;
- virtual void add_force(const Vector2 &p_force, const Vector2 &p_position = Vector2()) = 0;
- virtual void add_torque(real_t p_torque) = 0;
virtual void apply_central_impulse(const Vector2 &p_impulse) = 0;
virtual void apply_torque_impulse(real_t p_torque) = 0;
virtual void apply_impulse(const Vector2 &p_impulse, const Vector2 &p_position = Vector2()) = 0;
+ virtual void apply_central_force(const Vector2 &p_force) = 0;
+ virtual void apply_force(const Vector2 &p_force, const Vector2 &p_position = Vector2()) = 0;
+ virtual void apply_torque(real_t p_torque) = 0;
+
+ virtual void add_constant_central_force(const Vector2 &p_force) = 0;
+ virtual void add_constant_force(const Vector2 &p_force, const Vector2 &p_position = Vector2()) = 0;
+ virtual void add_constant_torque(real_t p_torque) = 0;
+
+ virtual void set_constant_force(const Vector2 &p_force) = 0;
+ virtual Vector2 get_constant_force() const = 0;
+
+ virtual void set_constant_torque(real_t p_torque) = 0;
+ virtual real_t get_constant_torque() const = 0;
+
virtual void set_sleep_state(bool p_enable) = 0;
virtual bool is_sleeping() const = 0;
@@ -94,60 +106,15 @@ public:
PhysicsDirectBodyState2D();
};
-//used for script
-class PhysicsShapeQueryParameters2D : public RefCounted {
- GDCLASS(PhysicsShapeQueryParameters2D, RefCounted);
- friend class PhysicsDirectSpaceState2D;
-
- RES shape_ref;
- RID shape;
- Transform2D transform;
- Vector2 motion;
- real_t margin = 0.0;
- Set<RID> exclude;
- uint32_t collision_mask = UINT32_MAX;
-
- bool collide_with_bodies = true;
- bool collide_with_areas = false;
-
-protected:
- static void _bind_methods();
-
-public:
- void set_shape(const RES &p_shape_ref);
- RES get_shape() const;
- void set_shape_rid(const RID &p_shape);
- RID get_shape_rid() const;
-
- void set_transform(const Transform2D &p_transform);
- Transform2D get_transform() const;
-
- void set_motion(const Vector2 &p_motion);
- Vector2 get_motion() const;
-
- void set_margin(real_t p_margin);
- real_t get_margin() const;
-
- void set_collision_mask(uint32_t p_mask);
- uint32_t get_collision_mask() const;
-
- void set_collide_with_bodies(bool p_enable);
- bool is_collide_with_bodies_enabled() const;
-
- void set_collide_with_areas(bool p_enable);
- bool is_collide_with_areas_enabled() const;
-
- void set_exclude(const Vector<RID> &p_exclude);
- Vector<RID> get_exclude() const;
-};
+class PhysicsRayQueryParameters2D;
+class PhysicsPointQueryParameters2D;
+class PhysicsShapeQueryParameters2D;
class PhysicsDirectSpaceState2D : public Object {
GDCLASS(PhysicsDirectSpaceState2D, Object);
- Dictionary _intersect_ray(const Vector2 &p_from, const Vector2 &p_to, const Vector<RID> &p_exclude = Vector<RID>(), uint32_t p_layers = 0, bool p_collide_with_bodies = true, bool p_collide_with_areas = false);
- Array _intersect_point(const Vector2 &p_point, int p_max_results = 32, const Vector<RID> &p_exclude = Vector<RID>(), uint32_t p_layers = 0, bool p_collide_with_bodies = true, bool p_collide_with_areas = false);
- Array _intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_intance_id, int p_max_results = 32, const Vector<RID> &p_exclude = Vector<RID>(), uint32_t p_layers = 0, bool p_collide_with_bodies = true, bool p_collide_with_areas = false);
- Array _intersect_point_impl(const Vector2 &p_point, int p_max_results, const Vector<RID> &p_exclud, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_filter_by_canvas = false, ObjectID p_canvas_instance_id = ObjectID());
+ Dictionary _intersect_ray(const Ref<PhysicsRayQueryParameters2D> &p_ray_query);
+ Array _intersect_point(const Ref<PhysicsPointQueryParameters2D> &p_point_query, int p_max_results = 32);
Array _intersect_shape(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query, int p_max_results = 32);
Array _cast_motion(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query);
Array _collide_shape(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query, int p_max_results = 32);
@@ -157,6 +124,18 @@ protected:
static void _bind_methods();
public:
+ struct RayParameters {
+ Vector2 from;
+ Vector2 to;
+ Set<RID> exclude;
+ uint32_t collision_mask = UINT32_MAX;
+
+ bool collide_with_bodies = true;
+ bool collide_with_areas = false;
+
+ bool hit_from_inside = false;
+ };
+
struct RayResult {
Vector2 position;
Vector2 normal;
@@ -166,7 +145,7 @@ public:
int shape = 0;
};
- virtual bool intersect_ray(const Vector2 &p_from, const Vector2 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
+ virtual bool intersect_ray(const RayParameters &p_parameters, RayResult &r_result) = 0;
struct ShapeResult {
RID rid;
@@ -175,14 +154,31 @@ public:
int shape = 0;
};
- virtual int intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false) = 0;
- virtual int intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_instance_id, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false) = 0;
+ struct PointParameters {
+ Vector2 position;
+ ObjectID canvas_instance_id;
+ Set<RID> exclude;
+ uint32_t collision_mask = UINT32_MAX;
- virtual int intersect_shape(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
+ bool collide_with_bodies = true;
+ bool collide_with_areas = false;
- virtual bool cast_motion(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
+ bool pick_point = false;
+ };
+
+ virtual int intersect_point(const PointParameters &p_parameters, ShapeResult *r_results, int p_result_max) = 0;
+
+ struct ShapeParameters {
+ RID shape_rid;
+ Transform2D transform;
+ Vector2 motion;
+ real_t margin = 0.0;
+ Set<RID> exclude;
+ uint32_t collision_mask = UINT32_MAX;
- virtual bool collide_shape(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, Vector2 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
+ bool collide_with_bodies = true;
+ bool collide_with_areas = false;
+ };
struct ShapeRestInfo {
Vector2 point;
@@ -190,10 +186,13 @@ public:
RID rid;
ObjectID collider_id;
int shape = 0;
- Vector2 linear_velocity; //velocity at contact point
+ Vector2 linear_velocity; // Velocity at contact point.
};
- virtual bool rest_info(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
+ virtual int intersect_shape(const ShapeParameters &p_parameters, ShapeResult *r_results, int p_result_max) = 0;
+ virtual bool cast_motion(const ShapeParameters &p_parameters, real_t &p_closest_safe, real_t &p_closest_unsafe) = 0;
+ virtual bool collide_shape(const ShapeParameters &p_parameters, Vector2 *r_results, int p_result_max, int &r_result_count) = 0;
+ virtual bool rest_info(const ShapeParameters &p_parameters, ShapeRestInfo *r_info) = 0;
PhysicsDirectSpaceState2D();
};
@@ -254,11 +253,13 @@ public:
enum SpaceParameter {
SPACE_PARAM_CONTACT_RECYCLE_RADIUS,
SPACE_PARAM_CONTACT_MAX_SEPARATION,
- SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION,
+ SPACE_PARAM_CONTACT_MAX_ALLOWED_PENETRATION,
+ SPACE_PARAM_CONTACT_DEFAULT_BIAS,
SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD,
SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD,
SPACE_PARAM_BODY_TIME_TO_SLEEP,
SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS,
+ SPACE_PARAM_SOLVER_ITERATIONS,
};
virtual void space_set_param(RID p_space, SpaceParameter p_param, real_t p_value) = 0;
@@ -278,12 +279,15 @@ public:
//missing attenuation? missing better override?
enum AreaParameter {
+ AREA_PARAM_GRAVITY_OVERRIDE_MODE,
AREA_PARAM_GRAVITY,
AREA_PARAM_GRAVITY_VECTOR,
AREA_PARAM_GRAVITY_IS_POINT,
AREA_PARAM_GRAVITY_DISTANCE_SCALE,
AREA_PARAM_GRAVITY_POINT_ATTENUATION,
+ AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE,
AREA_PARAM_LINEAR_DAMP,
+ AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE,
AREA_PARAM_ANGULAR_DAMP,
AREA_PARAM_PRIORITY
};
@@ -301,9 +305,6 @@ public:
AREA_SPACE_OVERRIDE_REPLACE_COMBINE // Discards all previous calculations, then keeps combining
};
- virtual void area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) = 0;
- virtual AreaSpaceOverrideMode area_get_space_override_mode(RID p_area) const = 0;
-
virtual void area_add_shape(RID p_area, RID p_shape, const Transform2D &p_transform = Transform2D(), bool p_disabled = false) = 0;
virtual void area_set_shape(RID p_area, int p_shape_idx, RID p_shape) = 0;
virtual void area_set_shape_transform(RID p_area, int p_shape_idx, const Transform2D &p_transform) = 0;
@@ -335,8 +336,8 @@ public:
virtual void area_set_monitorable(RID p_area, bool p_monitorable) = 0;
virtual void area_set_pickable(RID p_area, bool p_pickable) = 0;
- virtual void area_set_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) = 0;
- virtual void area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) = 0;
+ virtual void area_set_monitor_callback(RID p_area, const Callable &p_callback) = 0;
+ virtual void area_set_area_monitor_callback(RID p_area, const Callable &p_callback) = 0;
/* BODY API */
@@ -400,11 +401,18 @@ public:
BODY_PARAM_INERTIA,
BODY_PARAM_CENTER_OF_MASS,
BODY_PARAM_GRAVITY_SCALE,
+ BODY_PARAM_LINEAR_DAMP_MODE,
+ BODY_PARAM_ANGULAR_DAMP_MODE,
BODY_PARAM_LINEAR_DAMP,
BODY_PARAM_ANGULAR_DAMP,
BODY_PARAM_MAX,
};
+ enum BodyDampMode {
+ BODY_DAMP_MODE_COMBINE,
+ BODY_DAMP_MODE_REPLACE,
+ };
+
virtual void body_set_param(RID p_body, BodyParameter p_param, const Variant &p_value) = 0;
virtual Variant body_get_param(RID p_body, BodyParameter p_param) const = 0;
@@ -422,20 +430,24 @@ public:
virtual void body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) = 0;
virtual Variant body_get_state(RID p_body, BodyState p_state) const = 0;
- //do something about it
- virtual void body_set_applied_force(RID p_body, const Vector2 &p_force) = 0;
- virtual Vector2 body_get_applied_force(RID p_body) const = 0;
-
- virtual void body_set_applied_torque(RID p_body, real_t p_torque) = 0;
- virtual real_t body_get_applied_torque(RID p_body) const = 0;
-
- virtual void body_add_central_force(RID p_body, const Vector2 &p_force) = 0;
- virtual void body_add_force(RID p_body, const Vector2 &p_force, const Vector2 &p_position = Vector2()) = 0;
- virtual void body_add_torque(RID p_body, real_t p_torque) = 0;
-
virtual void body_apply_central_impulse(RID p_body, const Vector2 &p_impulse) = 0;
virtual void body_apply_torque_impulse(RID p_body, real_t p_torque) = 0;
virtual void body_apply_impulse(RID p_body, const Vector2 &p_impulse, const Vector2 &p_position = Vector2()) = 0;
+
+ virtual void body_apply_central_force(RID p_body, const Vector2 &p_force) = 0;
+ virtual void body_apply_force(RID p_body, const Vector2 &p_force, const Vector2 &p_position = Vector2()) = 0;
+ virtual void body_apply_torque(RID p_body, real_t p_torque) = 0;
+
+ virtual void body_add_constant_central_force(RID p_body, const Vector2 &p_force) = 0;
+ virtual void body_add_constant_force(RID p_body, const Vector2 &p_force, const Vector2 &p_position = Vector2()) = 0;
+ virtual void body_add_constant_torque(RID p_body, real_t p_torque) = 0;
+
+ virtual void body_set_constant_force(RID p_body, const Vector2 &p_force) = 0;
+ virtual Vector2 body_get_constant_force(RID p_body) const = 0;
+
+ virtual void body_set_constant_torque(RID p_body, real_t p_torque) = 0;
+ virtual real_t body_get_constant_torque(RID p_body) const = 0;
+
virtual void body_set_axis_velocity(RID p_body, const Vector2 &p_axis_velocity) = 0;
//fix
@@ -571,8 +583,6 @@ public:
virtual bool is_flushing_queries() const = 0;
- virtual void set_collision_iterations(int p_iterations) = 0;
-
enum ProcessInfo {
INFO_ACTIVE_OBJECTS,
INFO_COLLISION_PAIRS,
@@ -585,6 +595,110 @@ public:
~PhysicsServer2D();
};
+class PhysicsRayQueryParameters2D : public RefCounted {
+ GDCLASS(PhysicsRayQueryParameters2D, RefCounted);
+
+ PhysicsDirectSpaceState2D::RayParameters parameters;
+
+protected:
+ static void _bind_methods();
+
+public:
+ const PhysicsDirectSpaceState2D::RayParameters &get_parameters() const { return parameters; }
+
+ void set_from(const Vector2 &p_from) { parameters.from = p_from; }
+ const Vector2 &get_from() const { return parameters.from; }
+
+ void set_to(const Vector2 &p_to) { parameters.to = p_to; }
+ const Vector2 &get_to() const { return parameters.to; }
+
+ void set_collision_mask(uint32_t p_mask) { parameters.collision_mask = p_mask; }
+ uint32_t get_collision_mask() const { return parameters.collision_mask; }
+
+ void set_collide_with_bodies(bool p_enable) { parameters.collide_with_bodies = p_enable; }
+ bool is_collide_with_bodies_enabled() const { return parameters.collide_with_bodies; }
+
+ void set_collide_with_areas(bool p_enable) { parameters.collide_with_areas = p_enable; }
+ bool is_collide_with_areas_enabled() const { return parameters.collide_with_areas; }
+
+ void set_hit_from_inside(bool p_enable) { parameters.hit_from_inside = p_enable; }
+ bool is_hit_from_inside_enabled() const { return parameters.hit_from_inside; }
+
+ void set_exclude(const Vector<RID> &p_exclude);
+ Vector<RID> get_exclude() const;
+};
+
+class PhysicsPointQueryParameters2D : public RefCounted {
+ GDCLASS(PhysicsPointQueryParameters2D, RefCounted);
+
+ PhysicsDirectSpaceState2D::PointParameters parameters;
+
+protected:
+ static void _bind_methods();
+
+public:
+ const PhysicsDirectSpaceState2D::PointParameters &get_parameters() const { return parameters; }
+
+ void set_position(const Vector2 &p_position) { parameters.position = p_position; }
+ const Vector2 &get_position() const { return parameters.position; }
+
+ void set_canvas_instance_id(ObjectID p_canvas_instance_id) { parameters.canvas_instance_id = p_canvas_instance_id; }
+ ObjectID get_canvas_instance_id() const { return parameters.canvas_instance_id; }
+
+ void set_collision_mask(uint32_t p_mask) { parameters.collision_mask = p_mask; }
+ uint32_t get_collision_mask() const { return parameters.collision_mask; }
+
+ void set_collide_with_bodies(bool p_enable) { parameters.collide_with_bodies = p_enable; }
+ bool is_collide_with_bodies_enabled() const { return parameters.collide_with_bodies; }
+
+ void set_collide_with_areas(bool p_enable) { parameters.collide_with_areas = p_enable; }
+ bool is_collide_with_areas_enabled() const { return parameters.collide_with_areas; }
+
+ void set_exclude(const Vector<RID> &p_exclude);
+ Vector<RID> get_exclude() const;
+};
+
+class PhysicsShapeQueryParameters2D : public RefCounted {
+ GDCLASS(PhysicsShapeQueryParameters2D, RefCounted);
+
+ PhysicsDirectSpaceState2D::ShapeParameters parameters;
+
+ RES shape_ref;
+
+protected:
+ static void _bind_methods();
+
+public:
+ const PhysicsDirectSpaceState2D::ShapeParameters &get_parameters() const { return parameters; }
+
+ void set_shape(const RES &p_shape_ref);
+ RES get_shape() const { return shape_ref; }
+
+ void set_shape_rid(const RID &p_shape);
+ RID get_shape_rid() const { return parameters.shape_rid; }
+
+ void set_transform(const Transform2D &p_transform) { parameters.transform = p_transform; }
+ const Transform2D &get_transform() const { return parameters.transform; }
+
+ void set_motion(const Vector2 &p_motion) { parameters.motion = p_motion; }
+ const Vector2 &get_motion() const { return parameters.motion; }
+
+ void set_margin(real_t p_margin) { parameters.margin = p_margin; }
+ real_t get_margin() const { return parameters.margin; }
+
+ void set_collision_mask(uint32_t p_mask) { parameters.collision_mask = p_mask; }
+ uint32_t get_collision_mask() const { return parameters.collision_mask; }
+
+ void set_collide_with_bodies(bool p_enable) { parameters.collide_with_bodies = p_enable; }
+ bool is_collide_with_bodies_enabled() const { return parameters.collide_with_bodies; }
+
+ void set_collide_with_areas(bool p_enable) { parameters.collide_with_areas = p_enable; }
+ bool is_collide_with_areas_enabled() const { return parameters.collide_with_areas; }
+
+ void set_exclude(const Vector<RID> &p_exclude);
+ Vector<RID> get_exclude() const;
+};
+
class PhysicsTestMotionParameters2D : public RefCounted {
GDCLASS(PhysicsTestMotionParameters2D, RefCounted);
@@ -659,10 +773,9 @@ class PhysicsServer2DManager {
name(p_ci.name),
create_callback(p_ci.create_callback) {}
- ClassInfo &operator=(const ClassInfo &p_ci) {
+ void operator=(const ClassInfo &p_ci) {
name = p_ci.name;
create_callback = p_ci.create_callback;
- return *this;
}
};
@@ -692,13 +805,13 @@ VARIANT_ENUM_CAST(PhysicsServer2D::AreaParameter);
VARIANT_ENUM_CAST(PhysicsServer2D::AreaSpaceOverrideMode);
VARIANT_ENUM_CAST(PhysicsServer2D::BodyMode);
VARIANT_ENUM_CAST(PhysicsServer2D::BodyParameter);
+VARIANT_ENUM_CAST(PhysicsServer2D::BodyDampMode);
VARIANT_ENUM_CAST(PhysicsServer2D::BodyState);
VARIANT_ENUM_CAST(PhysicsServer2D::CCDMode);
VARIANT_ENUM_CAST(PhysicsServer2D::JointParam);
VARIANT_ENUM_CAST(PhysicsServer2D::JointType);
VARIANT_ENUM_CAST(PhysicsServer2D::DampedSpringParam);
-//VARIANT_ENUM_CAST( PhysicsServer2D::ObjectType );
VARIANT_ENUM_CAST(PhysicsServer2D::AreaBodyStatus);
VARIANT_ENUM_CAST(PhysicsServer2D::ProcessInfo);
-#endif
+#endif // PHYSICS_SERVER_2D_H
diff --git a/servers/physics_2d/physics_server_2d_wrap_mt.cpp b/servers/physics_server_2d_wrap_mt.cpp
index 33070bf42d..02223b83f0 100644
--- a/servers/physics_2d/physics_server_2d_wrap_mt.cpp
+++ b/servers/physics_server_2d_wrap_mt.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/physics_2d/physics_server_2d_wrap_mt.h b/servers/physics_server_2d_wrap_mt.h
index 8d9e366661..aa3a8bc04a 100644
--- a/servers/physics_2d/physics_server_2d_wrap_mt.h
+++ b/servers/physics_server_2d_wrap_mt.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef PHYSICS2DSERVERWRAPMT_H
-#define PHYSICS2DSERVERWRAPMT_H
+#ifndef PHYSICS_SERVER_2D_WRAP_MT_H
+#define PHYSICS_SERVER_2D_WRAP_MT_H
#include "core/config/project_settings.h"
#include "core/os/thread.h"
@@ -59,9 +59,7 @@ class PhysicsServer2DWrapMT : public PhysicsServer2D {
bool create_thread = false;
Semaphore step_sem;
- int step_pending = 0;
void thread_step(real_t p_delta);
- void thread_flush();
void thread_exit();
@@ -135,9 +133,6 @@ public:
FUNC2(area_set_space, RID, RID);
FUNC1RC(RID, area_get_space, RID);
- FUNC2(area_set_space_override_mode, RID, AreaSpaceOverrideMode);
- FUNC1RC(AreaSpaceOverrideMode, area_get_space_override_mode, RID);
-
FUNC4(area_add_shape, RID, RID, const Transform2D &, bool);
FUNC3(area_set_shape, RID, int, RID);
FUNC3(area_set_shape_transform, RID, int, const Transform2D &);
@@ -167,8 +162,8 @@ public:
FUNC2(area_set_monitorable, RID, bool);
FUNC2(area_set_pickable, RID, bool);
- FUNC3(area_set_monitor_callback, RID, Object *, const StringName &);
- FUNC3(area_set_area_monitor_callback, RID, Object *, const StringName &);
+ FUNC2(area_set_monitor_callback, RID, const Callable &);
+ FUNC2(area_set_area_monitor_callback, RID, const Callable &);
/* BODY API */
@@ -218,18 +213,24 @@ public:
FUNC3(body_set_state, RID, BodyState, const Variant &);
FUNC2RC(Variant, body_get_state, RID, BodyState);
- FUNC2(body_set_applied_force, RID, const Vector2 &);
- FUNC1RC(Vector2, body_get_applied_force, RID);
-
- FUNC2(body_set_applied_torque, RID, real_t);
- FUNC1RC(real_t, body_get_applied_torque, RID);
-
- FUNC2(body_add_central_force, RID, const Vector2 &);
- FUNC3(body_add_force, RID, const Vector2 &, const Vector2 &);
- FUNC2(body_add_torque, RID, real_t);
FUNC2(body_apply_central_impulse, RID, const Vector2 &);
FUNC2(body_apply_torque_impulse, RID, real_t);
FUNC3(body_apply_impulse, RID, const Vector2 &, const Vector2 &);
+
+ FUNC2(body_apply_central_force, RID, const Vector2 &);
+ FUNC3(body_apply_force, RID, const Vector2 &, const Vector2 &);
+ FUNC2(body_apply_torque, RID, real_t);
+
+ FUNC2(body_add_constant_central_force, RID, const Vector2 &);
+ FUNC3(body_add_constant_force, RID, const Vector2 &, const Vector2 &);
+ FUNC2(body_add_constant_torque, RID, real_t);
+
+ FUNC2(body_set_constant_force, RID, const Vector2 &);
+ FUNC1RC(Vector2, body_get_constant_force, RID);
+
+ FUNC2(body_set_constant_torque, RID, real_t);
+ FUNC1RC(real_t, body_get_constant_torque, RID);
+
FUNC2(body_set_axis_velocity, RID, const Vector2 &);
FUNC2(body_add_collision_exception, RID, RID);
@@ -299,7 +300,6 @@ public:
FUNC1(free, RID);
FUNC1(set_active, bool);
- FUNC1(set_collision_iterations, int);
virtual void init() override;
virtual void step(real_t p_step) override;
@@ -330,4 +330,4 @@ public:
#endif
#undef SYNC_DEBUG
-#endif // PHYSICS2DSERVERWRAPMT_H
+#endif // PHYSICS_SERVER_2D_WRAP_MT_H
diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp
index 90922cc250..8fafd07f87 100644
--- a/servers/physics_server_3d.cpp
+++ b/servers/physics_server_3d.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -77,6 +77,7 @@ void PhysicsDirectBodyState3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_total_angular_damp"), &PhysicsDirectBodyState3D::get_total_angular_damp);
ClassDB::bind_method(D_METHOD("get_center_of_mass"), &PhysicsDirectBodyState3D::get_center_of_mass);
+ ClassDB::bind_method(D_METHOD("get_center_of_mass_local"), &PhysicsDirectBodyState3D::get_center_of_mass_local);
ClassDB::bind_method(D_METHOD("get_principal_inertia_axes"), &PhysicsDirectBodyState3D::get_principal_inertia_axes);
ClassDB::bind_method(D_METHOD("get_inverse_mass"), &PhysicsDirectBodyState3D::get_inverse_mass);
@@ -93,13 +94,24 @@ void PhysicsDirectBodyState3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_velocity_at_local_position", "local_position"), &PhysicsDirectBodyState3D::get_velocity_at_local_position);
- ClassDB::bind_method(D_METHOD("add_central_force", "force"), &PhysicsDirectBodyState3D::add_central_force, Vector3());
- ClassDB::bind_method(D_METHOD("add_force", "force", "position"), &PhysicsDirectBodyState3D::add_force, Vector3());
- ClassDB::bind_method(D_METHOD("add_torque", "torque"), &PhysicsDirectBodyState3D::add_torque);
ClassDB::bind_method(D_METHOD("apply_central_impulse", "impulse"), &PhysicsDirectBodyState3D::apply_central_impulse, Vector3());
ClassDB::bind_method(D_METHOD("apply_impulse", "impulse", "position"), &PhysicsDirectBodyState3D::apply_impulse, Vector3());
ClassDB::bind_method(D_METHOD("apply_torque_impulse", "impulse"), &PhysicsDirectBodyState3D::apply_torque_impulse);
+ ClassDB::bind_method(D_METHOD("apply_central_force", "force"), &PhysicsDirectBodyState3D::apply_central_force, Vector3());
+ ClassDB::bind_method(D_METHOD("apply_force", "force", "position"), &PhysicsDirectBodyState3D::apply_force, Vector3());
+ ClassDB::bind_method(D_METHOD("apply_torque", "torque"), &PhysicsDirectBodyState3D::apply_torque);
+
+ ClassDB::bind_method(D_METHOD("add_constant_central_force", "force"), &PhysicsDirectBodyState3D::add_constant_central_force, Vector3());
+ ClassDB::bind_method(D_METHOD("add_constant_force", "force", "position"), &PhysicsDirectBodyState3D::add_constant_force, Vector3());
+ ClassDB::bind_method(D_METHOD("add_constant_torque", "torque"), &PhysicsDirectBodyState3D::add_constant_torque);
+
+ ClassDB::bind_method(D_METHOD("set_constant_force", "force"), &PhysicsDirectBodyState3D::set_constant_force);
+ ClassDB::bind_method(D_METHOD("get_constant_force"), &PhysicsDirectBodyState3D::get_constant_force);
+
+ ClassDB::bind_method(D_METHOD("set_constant_torque", "torque"), &PhysicsDirectBodyState3D::set_constant_torque);
+ ClassDB::bind_method(D_METHOD("get_constant_torque"), &PhysicsDirectBodyState3D::get_constant_torque);
+
ClassDB::bind_method(D_METHOD("set_sleep_state", "enabled"), &PhysicsDirectBodyState3D::set_sleep_state);
ClassDB::bind_method(D_METHOD("is_sleeping"), &PhysicsDirectBodyState3D::is_sleeping);
@@ -126,6 +138,7 @@ void PhysicsDirectBodyState3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "inverse_inertia"), "", "get_inverse_inertia");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "total_gravity"), "", "get_total_gravity");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "center_of_mass"), "", "get_center_of_mass");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "center_of_mass_local"), "", "get_center_of_mass_local");
ADD_PROPERTY(PropertyInfo(Variant::BASIS, "principal_inertia_axes"), "", "get_principal_inertia_axes");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "angular_velocity"), "set_angular_velocity", "get_angular_velocity");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "linear_velocity"), "set_linear_velocity", "get_linear_velocity");
@@ -137,93 +150,145 @@ PhysicsDirectBodyState3D::PhysicsDirectBodyState3D() {}
///////////////////////////////////////////////////////
-void PhysicsShapeQueryParameters3D::set_shape(const RES &p_shape_ref) {
- ERR_FAIL_COND(p_shape_ref.is_null());
- shape_ref = p_shape_ref;
- shape = p_shape_ref->get_rid();
-}
-
-RES PhysicsShapeQueryParameters3D::get_shape() const {
- return shape_ref;
+void PhysicsRayQueryParameters3D::set_exclude(const Vector<RID> &p_exclude) {
+ parameters.exclude.clear();
+ for (int i = 0; i < p_exclude.size(); i++) {
+ parameters.exclude.insert(p_exclude[i]);
+ }
}
-void PhysicsShapeQueryParameters3D::set_shape_rid(const RID &p_shape) {
- if (shape != p_shape) {
- shape_ref = RES();
- shape = p_shape;
+Vector<RID> PhysicsRayQueryParameters3D::get_exclude() const {
+ Vector<RID> ret;
+ ret.resize(parameters.exclude.size());
+ int idx = 0;
+ for (Set<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) {
+ ret.write[idx++] = E->get();
}
+ return ret;
}
-RID PhysicsShapeQueryParameters3D::get_shape_rid() const {
- return shape;
-}
+void PhysicsRayQueryParameters3D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_from", "from"), &PhysicsRayQueryParameters3D::set_from);
+ ClassDB::bind_method(D_METHOD("get_from"), &PhysicsRayQueryParameters3D::get_from);
-void PhysicsShapeQueryParameters3D::set_transform(const Transform3D &p_transform) {
- transform = p_transform;
-}
+ ClassDB::bind_method(D_METHOD("set_to", "to"), &PhysicsRayQueryParameters3D::set_to);
+ ClassDB::bind_method(D_METHOD("get_to"), &PhysicsRayQueryParameters3D::get_to);
-Transform3D PhysicsShapeQueryParameters3D::get_transform() const {
- return transform;
-}
+ ClassDB::bind_method(D_METHOD("set_collision_mask", "collision_mask"), &PhysicsRayQueryParameters3D::set_collision_mask);
+ ClassDB::bind_method(D_METHOD("get_collision_mask"), &PhysicsRayQueryParameters3D::get_collision_mask);
-void PhysicsShapeQueryParameters3D::set_margin(real_t p_margin) {
- margin = p_margin;
-}
+ ClassDB::bind_method(D_METHOD("set_exclude", "exclude"), &PhysicsRayQueryParameters3D::set_exclude);
+ ClassDB::bind_method(D_METHOD("get_exclude"), &PhysicsRayQueryParameters3D::get_exclude);
-real_t PhysicsShapeQueryParameters3D::get_margin() const {
- return margin;
-}
+ ClassDB::bind_method(D_METHOD("set_collide_with_bodies", "enable"), &PhysicsRayQueryParameters3D::set_collide_with_bodies);
+ ClassDB::bind_method(D_METHOD("is_collide_with_bodies_enabled"), &PhysicsRayQueryParameters3D::is_collide_with_bodies_enabled);
-void PhysicsShapeQueryParameters3D::set_collision_mask(uint32_t p_collision_mask) {
- collision_mask = p_collision_mask;
-}
+ ClassDB::bind_method(D_METHOD("set_collide_with_areas", "enable"), &PhysicsRayQueryParameters3D::set_collide_with_areas);
+ ClassDB::bind_method(D_METHOD("is_collide_with_areas_enabled"), &PhysicsRayQueryParameters3D::is_collide_with_areas_enabled);
+
+ ClassDB::bind_method(D_METHOD("set_hit_from_inside", "enable"), &PhysicsRayQueryParameters3D::set_hit_from_inside);
+ ClassDB::bind_method(D_METHOD("is_hit_from_inside_enabled"), &PhysicsRayQueryParameters3D::is_hit_from_inside_enabled);
-uint32_t PhysicsShapeQueryParameters3D::get_collision_mask() const {
- return collision_mask;
+ ClassDB::bind_method(D_METHOD("set_hit_back_faces", "enable"), &PhysicsRayQueryParameters3D::set_hit_back_faces);
+ ClassDB::bind_method(D_METHOD("is_hit_back_faces_enabled"), &PhysicsRayQueryParameters3D::is_hit_back_faces_enabled);
+
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "from"), "set_from", "get_from");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "to"), "set_to", "get_to");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_exclude", "get_exclude");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_bodies"), "set_collide_with_bodies", "is_collide_with_bodies_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas"), "set_collide_with_areas", "is_collide_with_areas_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hit_from_inside"), "set_hit_from_inside", "is_hit_from_inside_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hit_back_faces"), "set_hit_back_faces", "is_hit_back_faces_enabled");
}
-void PhysicsShapeQueryParameters3D::set_exclude(const Vector<RID> &p_exclude) {
- exclude.clear();
+///////////////////////////////////////////////////////
+
+void PhysicsPointQueryParameters3D::set_exclude(const Vector<RID> &p_exclude) {
+ parameters.exclude.clear();
for (int i = 0; i < p_exclude.size(); i++) {
- exclude.insert(p_exclude[i]);
+ parameters.exclude.insert(p_exclude[i]);
}
}
-Vector<RID> PhysicsShapeQueryParameters3D::get_exclude() const {
+Vector<RID> PhysicsPointQueryParameters3D::get_exclude() const {
Vector<RID> ret;
- ret.resize(exclude.size());
+ ret.resize(parameters.exclude.size());
int idx = 0;
- for (Set<RID>::Element *E = exclude.front(); E; E = E->next()) {
+ for (Set<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) {
ret.write[idx++] = E->get();
}
return ret;
}
-void PhysicsShapeQueryParameters3D::set_collide_with_bodies(bool p_enable) {
- collide_with_bodies = p_enable;
+void PhysicsPointQueryParameters3D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_position", "position"), &PhysicsPointQueryParameters3D::set_position);
+ ClassDB::bind_method(D_METHOD("get_position"), &PhysicsPointQueryParameters3D::get_position);
+
+ ClassDB::bind_method(D_METHOD("set_collision_mask", "collision_mask"), &PhysicsPointQueryParameters3D::set_collision_mask);
+ ClassDB::bind_method(D_METHOD("get_collision_mask"), &PhysicsPointQueryParameters3D::get_collision_mask);
+
+ ClassDB::bind_method(D_METHOD("set_exclude", "exclude"), &PhysicsPointQueryParameters3D::set_exclude);
+ ClassDB::bind_method(D_METHOD("get_exclude"), &PhysicsPointQueryParameters3D::get_exclude);
+
+ ClassDB::bind_method(D_METHOD("set_collide_with_bodies", "enable"), &PhysicsPointQueryParameters3D::set_collide_with_bodies);
+ ClassDB::bind_method(D_METHOD("is_collide_with_bodies_enabled"), &PhysicsPointQueryParameters3D::is_collide_with_bodies_enabled);
+
+ ClassDB::bind_method(D_METHOD("set_collide_with_areas", "enable"), &PhysicsPointQueryParameters3D::set_collide_with_areas);
+ ClassDB::bind_method(D_METHOD("is_collide_with_areas_enabled"), &PhysicsPointQueryParameters3D::is_collide_with_areas_enabled);
+
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "position"), "set_position", "get_position");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_exclude", "get_exclude");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_bodies"), "set_collide_with_bodies", "is_collide_with_bodies_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas"), "set_collide_with_areas", "is_collide_with_areas_enabled");
+}
+
+///////////////////////////////////////////////////////
+
+void PhysicsShapeQueryParameters3D::set_shape(const RES &p_shape_ref) {
+ ERR_FAIL_COND(p_shape_ref.is_null());
+ shape_ref = p_shape_ref;
+ parameters.shape_rid = p_shape_ref->get_rid();
}
-bool PhysicsShapeQueryParameters3D::is_collide_with_bodies_enabled() const {
- return collide_with_bodies;
+void PhysicsShapeQueryParameters3D::set_shape_rid(const RID &p_shape) {
+ if (parameters.shape_rid != p_shape) {
+ shape_ref = RES();
+ parameters.shape_rid = p_shape;
+ }
}
-void PhysicsShapeQueryParameters3D::set_collide_with_areas(bool p_enable) {
- collide_with_areas = p_enable;
+void PhysicsShapeQueryParameters3D::set_exclude(const Vector<RID> &p_exclude) {
+ parameters.exclude.clear();
+ for (int i = 0; i < p_exclude.size(); i++) {
+ parameters.exclude.insert(p_exclude[i]);
+ }
}
-bool PhysicsShapeQueryParameters3D::is_collide_with_areas_enabled() const {
- return collide_with_areas;
+Vector<RID> PhysicsShapeQueryParameters3D::get_exclude() const {
+ Vector<RID> ret;
+ ret.resize(parameters.exclude.size());
+ int idx = 0;
+ for (Set<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) {
+ ret.write[idx++] = E->get();
+ }
+ return ret;
}
void PhysicsShapeQueryParameters3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_shape", "shape"), &PhysicsShapeQueryParameters3D::set_shape);
ClassDB::bind_method(D_METHOD("get_shape"), &PhysicsShapeQueryParameters3D::get_shape);
+
ClassDB::bind_method(D_METHOD("set_shape_rid", "shape"), &PhysicsShapeQueryParameters3D::set_shape_rid);
ClassDB::bind_method(D_METHOD("get_shape_rid"), &PhysicsShapeQueryParameters3D::get_shape_rid);
ClassDB::bind_method(D_METHOD("set_transform", "transform"), &PhysicsShapeQueryParameters3D::set_transform);
ClassDB::bind_method(D_METHOD("get_transform"), &PhysicsShapeQueryParameters3D::get_transform);
+ ClassDB::bind_method(D_METHOD("set_motion", "motion"), &PhysicsShapeQueryParameters3D::set_motion);
+ ClassDB::bind_method(D_METHOD("get_motion"), &PhysicsShapeQueryParameters3D::get_motion);
+
ClassDB::bind_method(D_METHOD("set_margin", "margin"), &PhysicsShapeQueryParameters3D::set_margin);
ClassDB::bind_method(D_METHOD("get_margin"), &PhysicsShapeQueryParameters3D::get_margin);
@@ -240,8 +305,9 @@ void PhysicsShapeQueryParameters3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_collide_with_areas_enabled"), &PhysicsShapeQueryParameters3D::is_collide_with_areas_enabled);
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask");
- ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_NONE, itos(Variant::RID) + ":"), "set_exclude", "get_exclude");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_exclude", "get_exclude");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin", PROPERTY_HINT_RANGE, "0,100,0.01"), "set_margin", "get_margin");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion"), "set_motion", "get_motion");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape3D"), "set_shape", "get_shape");
ADD_PROPERTY(PropertyInfo(Variant::RID, "shape_rid"), "set_shape_rid", "get_shape_rid");
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "transform"), "set_transform", "get_transform");
@@ -251,36 +317,56 @@ void PhysicsShapeQueryParameters3D::_bind_methods() {
/////////////////////////////////////
-Dictionary PhysicsDirectSpaceState3D::_intersect_ray(const Vector3 &p_from, const Vector3 &p_to, const Vector<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
- RayResult inters;
- Set<RID> exclude;
- for (int i = 0; i < p_exclude.size(); i++) {
- exclude.insert(p_exclude[i]);
- }
+Dictionary PhysicsDirectSpaceState3D::_intersect_ray(const Ref<PhysicsRayQueryParameters3D> &p_ray_query) {
+ ERR_FAIL_COND_V(!p_ray_query.is_valid(), Dictionary());
- bool res = intersect_ray(p_from, p_to, inters, exclude, p_collision_mask, p_collide_with_bodies, p_collide_with_areas);
+ RayResult result;
+ bool res = intersect_ray(p_ray_query->get_parameters(), result);
if (!res) {
return Dictionary();
}
Dictionary d;
- d["position"] = inters.position;
- d["normal"] = inters.normal;
- d["collider_id"] = inters.collider_id;
- d["collider"] = inters.collider;
- d["shape"] = inters.shape;
- d["rid"] = inters.rid;
+ d["position"] = result.position;
+ d["normal"] = result.normal;
+ d["collider_id"] = result.collider_id;
+ d["collider"] = result.collider;
+ d["shape"] = result.shape;
+ d["rid"] = result.rid;
return d;
}
+Array PhysicsDirectSpaceState3D::_intersect_point(const Ref<PhysicsPointQueryParameters3D> &p_point_query, int p_max_results) {
+ Vector<ShapeResult> ret;
+ ret.resize(p_max_results);
+
+ int rc = intersect_point(p_point_query->get_parameters(), ret.ptrw(), ret.size());
+
+ if (rc == 0) {
+ return Array();
+ }
+
+ Array r;
+ r.resize(rc);
+ for (int i = 0; i < rc; i++) {
+ Dictionary d;
+ d["rid"] = ret[i].rid;
+ d["collider_id"] = ret[i].collider_id;
+ d["collider"] = ret[i].collider;
+ d["shape"] = ret[i].shape;
+ r[i] = d;
+ }
+ return r;
+}
+
Array PhysicsDirectSpaceState3D::_intersect_shape(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, int p_max_results) {
ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array());
Vector<ShapeResult> sr;
sr.resize(p_max_results);
- int rc = intersect_shape(p_shape_query->shape, p_shape_query->transform, p_shape_query->margin, sr.ptrw(), sr.size(), p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas);
+ int rc = intersect_shape(p_shape_query->get_parameters(), sr.ptrw(), sr.size());
Array ret;
ret.resize(rc);
for (int i = 0; i < rc; i++) {
@@ -295,11 +381,11 @@ Array PhysicsDirectSpaceState3D::_intersect_shape(const Ref<PhysicsShapeQueryPar
return ret;
}
-Array PhysicsDirectSpaceState3D::_cast_motion(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, const Vector3 &p_motion) {
+Array PhysicsDirectSpaceState3D::_cast_motion(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query) {
ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array());
real_t closest_safe = 1.0f, closest_unsafe = 1.0f;
- bool res = cast_motion(p_shape_query->shape, p_shape_query->transform, p_motion, p_shape_query->margin, closest_safe, closest_unsafe, p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas);
+ bool res = cast_motion(p_shape_query->get_parameters(), closest_safe, closest_unsafe);
if (!res) {
return Array();
}
@@ -316,7 +402,7 @@ Array PhysicsDirectSpaceState3D::_collide_shape(const Ref<PhysicsShapeQueryParam
Vector<Vector3> ret;
ret.resize(p_max_results * 2);
int rc = 0;
- bool res = collide_shape(p_shape_query->shape, p_shape_query->transform, p_shape_query->margin, ret.ptrw(), p_max_results, rc, p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas);
+ bool res = collide_shape(p_shape_query->get_parameters(), ret.ptrw(), p_max_results, rc);
if (!res) {
return Array();
}
@@ -333,7 +419,7 @@ Dictionary PhysicsDirectSpaceState3D::_get_rest_info(const Ref<PhysicsShapeQuery
ShapeRestInfo sri;
- bool res = rest_info(p_shape_query->shape, p_shape_query->transform, p_shape_query->margin, &sri, p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas);
+ bool res = rest_info(p_shape_query->get_parameters(), &sri);
Dictionary r;
if (!res) {
return r;
@@ -353,11 +439,12 @@ PhysicsDirectSpaceState3D::PhysicsDirectSpaceState3D() {
}
void PhysicsDirectSpaceState3D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("intersect_ray", "from", "to", "exclude", "collision_mask", "collide_with_bodies", "collide_with_areas"), &PhysicsDirectSpaceState3D::_intersect_ray, DEFVAL(Array()), DEFVAL(UINT32_MAX), DEFVAL(true), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("intersect_shape", "shape", "max_results"), &PhysicsDirectSpaceState3D::_intersect_shape, DEFVAL(32));
- ClassDB::bind_method(D_METHOD("cast_motion", "shape", "motion"), &PhysicsDirectSpaceState3D::_cast_motion);
- ClassDB::bind_method(D_METHOD("collide_shape", "shape", "max_results"), &PhysicsDirectSpaceState3D::_collide_shape, DEFVAL(32));
- ClassDB::bind_method(D_METHOD("get_rest_info", "shape"), &PhysicsDirectSpaceState3D::_get_rest_info);
+ ClassDB::bind_method(D_METHOD("intersect_point", "parameters", "max_results"), &PhysicsDirectSpaceState3D::_intersect_point, DEFVAL(32));
+ ClassDB::bind_method(D_METHOD("intersect_ray", "parameters"), &PhysicsDirectSpaceState3D::_intersect_ray);
+ ClassDB::bind_method(D_METHOD("intersect_shape", "parameters", "max_results"), &PhysicsDirectSpaceState3D::_intersect_shape, DEFVAL(32));
+ ClassDB::bind_method(D_METHOD("cast_motion", "parameters"), &PhysicsDirectSpaceState3D::_cast_motion);
+ ClassDB::bind_method(D_METHOD("collide_shape", "parameters", "max_results"), &PhysicsDirectSpaceState3D::_collide_shape, DEFVAL(32));
+ ClassDB::bind_method(D_METHOD("get_rest_info", "parameters"), &PhysicsDirectSpaceState3D::_get_rest_info);
}
///////////////////////////////
@@ -427,7 +514,7 @@ void PhysicsTestMotionParameters3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin"), "set_margin", "get_margin");
ADD_PROPERTY(PropertyInfo(Variant::INT, "max_collisions"), "set_max_collisions", "get_max_collisions");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_separation_ray"), "set_collide_separation_ray_enabled", "is_collide_separation_ray_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude_bodies"), "set_exclude_bodies", "get_exclude_bodies");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude_bodies", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_exclude_bodies", "get_exclude_bodies");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude_objects"), "set_exclude_objects", "get_exclude_objects");
}
@@ -585,9 +672,6 @@ void PhysicsServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("area_set_space", "area", "space"), &PhysicsServer3D::area_set_space);
ClassDB::bind_method(D_METHOD("area_get_space", "area"), &PhysicsServer3D::area_get_space);
- ClassDB::bind_method(D_METHOD("area_set_space_override_mode", "area", "mode"), &PhysicsServer3D::area_set_space_override_mode);
- ClassDB::bind_method(D_METHOD("area_get_space_override_mode", "area"), &PhysicsServer3D::area_get_space_override_mode);
-
ClassDB::bind_method(D_METHOD("area_add_shape", "area", "shape", "transform", "disabled"), &PhysicsServer3D::area_add_shape, DEFVAL(Transform3D()), DEFVAL(false));
ClassDB::bind_method(D_METHOD("area_set_shape", "area", "shape_idx", "shape"), &PhysicsServer3D::area_set_shape);
ClassDB::bind_method(D_METHOD("area_set_shape_transform", "area", "shape_idx", "transform"), &PhysicsServer3D::area_set_shape_transform);
@@ -612,8 +696,8 @@ void PhysicsServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("area_attach_object_instance_id", "area", "id"), &PhysicsServer3D::area_attach_object_instance_id);
ClassDB::bind_method(D_METHOD("area_get_object_instance_id", "area"), &PhysicsServer3D::area_get_object_instance_id);
- ClassDB::bind_method(D_METHOD("area_set_monitor_callback", "area", "receiver", "method"), &PhysicsServer3D::area_set_monitor_callback);
- ClassDB::bind_method(D_METHOD("area_set_area_monitor_callback", "area", "receiver", "method"), &PhysicsServer3D::area_set_area_monitor_callback);
+ ClassDB::bind_method(D_METHOD("area_set_monitor_callback", "area", "callback"), &PhysicsServer3D::area_set_monitor_callback);
+ ClassDB::bind_method(D_METHOD("area_set_area_monitor_callback", "area", "callback"), &PhysicsServer3D::area_set_area_monitor_callback);
ClassDB::bind_method(D_METHOD("area_set_monitorable", "area", "monitorable"), &PhysicsServer3D::area_set_monitorable);
ClassDB::bind_method(D_METHOD("area_set_ray_pickable", "area", "enable"), &PhysicsServer3D::area_set_ray_pickable);
@@ -658,13 +742,24 @@ void PhysicsServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("body_set_state", "body", "state", "value"), &PhysicsServer3D::body_set_state);
ClassDB::bind_method(D_METHOD("body_get_state", "body", "state"), &PhysicsServer3D::body_get_state);
- ClassDB::bind_method(D_METHOD("body_add_central_force", "body", "force"), &PhysicsServer3D::body_add_central_force);
- ClassDB::bind_method(D_METHOD("body_add_force", "body", "force", "position"), &PhysicsServer3D::body_add_force, Vector3());
- ClassDB::bind_method(D_METHOD("body_add_torque", "body", "torque"), &PhysicsServer3D::body_add_torque);
-
ClassDB::bind_method(D_METHOD("body_apply_central_impulse", "body", "impulse"), &PhysicsServer3D::body_apply_central_impulse);
ClassDB::bind_method(D_METHOD("body_apply_impulse", "body", "impulse", "position"), &PhysicsServer3D::body_apply_impulse, Vector3());
ClassDB::bind_method(D_METHOD("body_apply_torque_impulse", "body", "impulse"), &PhysicsServer3D::body_apply_torque_impulse);
+
+ ClassDB::bind_method(D_METHOD("body_apply_central_force", "body", "force"), &PhysicsServer3D::body_apply_central_force);
+ ClassDB::bind_method(D_METHOD("body_apply_force", "body", "force", "position"), &PhysicsServer3D::body_apply_force, Vector3());
+ ClassDB::bind_method(D_METHOD("body_apply_torque", "body", "torque"), &PhysicsServer3D::body_apply_torque);
+
+ ClassDB::bind_method(D_METHOD("body_add_constant_central_force", "body", "force"), &PhysicsServer3D::body_add_constant_central_force);
+ ClassDB::bind_method(D_METHOD("body_add_constant_force", "body", "force", "position"), &PhysicsServer3D::body_add_constant_force, Vector3());
+ ClassDB::bind_method(D_METHOD("body_add_constant_torque", "body", "torque"), &PhysicsServer3D::body_add_constant_torque);
+
+ ClassDB::bind_method(D_METHOD("body_set_constant_force", "body", "force"), &PhysicsServer3D::body_set_constant_force);
+ ClassDB::bind_method(D_METHOD("body_get_constant_force", "body"), &PhysicsServer3D::body_get_constant_force);
+
+ ClassDB::bind_method(D_METHOD("body_set_constant_torque", "body", "torque"), &PhysicsServer3D::body_set_constant_torque);
+ ClassDB::bind_method(D_METHOD("body_get_constant_torque", "body"), &PhysicsServer3D::body_get_constant_torque);
+
ClassDB::bind_method(D_METHOD("body_set_axis_velocity", "body", "axis_velocity"), &PhysicsServer3D::body_set_axis_velocity);
ClassDB::bind_method(D_METHOD("body_set_axis_lock", "body", "axis", "lock"), &PhysicsServer3D::body_set_axis_lock);
@@ -817,8 +912,6 @@ void PhysicsServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_active", "active"), &PhysicsServer3D::set_active);
- ClassDB::bind_method(D_METHOD("set_collision_iterations", "iterations"), &PhysicsServer3D::set_collision_iterations);
-
ClassDB::bind_method(D_METHOD("get_process_info", "process_info"), &PhysicsServer3D::get_process_info);
BIND_ENUM_CONSTANT(SHAPE_WORLD_BOUNDARY);
@@ -833,12 +926,15 @@ void PhysicsServer3D::_bind_methods() {
BIND_ENUM_CONSTANT(SHAPE_SOFT_BODY);
BIND_ENUM_CONSTANT(SHAPE_CUSTOM);
+ BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_OVERRIDE_MODE);
BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY);
BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_VECTOR);
BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_IS_POINT);
BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_DISTANCE_SCALE);
BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_POINT_ATTENUATION);
+ BIND_ENUM_CONSTANT(AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE);
BIND_ENUM_CONSTANT(AREA_PARAM_LINEAR_DAMP);
+ BIND_ENUM_CONSTANT(AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE);
BIND_ENUM_CONSTANT(AREA_PARAM_ANGULAR_DAMP);
BIND_ENUM_CONSTANT(AREA_PARAM_PRIORITY);
BIND_ENUM_CONSTANT(AREA_PARAM_WIND_FORCE_MAGNITUDE);
@@ -863,10 +959,15 @@ void PhysicsServer3D::_bind_methods() {
BIND_ENUM_CONSTANT(BODY_PARAM_INERTIA);
BIND_ENUM_CONSTANT(BODY_PARAM_CENTER_OF_MASS);
BIND_ENUM_CONSTANT(BODY_PARAM_GRAVITY_SCALE);
+ BIND_ENUM_CONSTANT(BODY_PARAM_LINEAR_DAMP_MODE);
+ BIND_ENUM_CONSTANT(BODY_PARAM_ANGULAR_DAMP_MODE);
BIND_ENUM_CONSTANT(BODY_PARAM_LINEAR_DAMP);
BIND_ENUM_CONSTANT(BODY_PARAM_ANGULAR_DAMP);
BIND_ENUM_CONSTANT(BODY_PARAM_MAX);
+ BIND_ENUM_CONSTANT(BODY_DAMP_MODE_COMBINE);
+ BIND_ENUM_CONSTANT(BODY_DAMP_MODE_REPLACE);
+
BIND_ENUM_CONSTANT(BODY_STATE_TRANSFORM);
BIND_ENUM_CONSTANT(BODY_STATE_LINEAR_VELOCITY);
BIND_ENUM_CONSTANT(BODY_STATE_ANGULAR_VELOCITY);
@@ -882,12 +983,12 @@ void PhysicsServer3D::_bind_methods() {
BIND_ENUM_CONSTANT(SPACE_PARAM_CONTACT_RECYCLE_RADIUS);
BIND_ENUM_CONSTANT(SPACE_PARAM_CONTACT_MAX_SEPARATION);
- BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION);
+ BIND_ENUM_CONSTANT(SPACE_PARAM_CONTACT_MAX_ALLOWED_PENETRATION);
+ BIND_ENUM_CONSTANT(SPACE_PARAM_CONTACT_DEFAULT_BIAS);
BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD);
BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD);
BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_TIME_TO_SLEEP);
- BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO);
- BIND_ENUM_CONSTANT(SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS);
+ BIND_ENUM_CONSTANT(SPACE_PARAM_SOLVER_ITERATIONS);
BIND_ENUM_CONSTANT(BODY_AXIS_LINEAR_X);
BIND_ENUM_CONSTANT(BODY_AXIS_LINEAR_Y);
diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h
index c609afc11e..f830c95b58 100644
--- a/servers/physics_server_3d.h
+++ b/servers/physics_server_3d.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef PHYSICS_SERVER_H
-#define PHYSICS_SERVER_H
+#ifndef PHYSICS_SERVER_3D_H
+#define PHYSICS_SERVER_3D_H
#include "core/io/resource.h"
#include "core/object/class_db.h"
@@ -48,6 +48,7 @@ public:
virtual real_t get_total_linear_damp() const = 0;
virtual Vector3 get_center_of_mass() const = 0;
+ virtual Vector3 get_center_of_mass_local() const = 0;
virtual Basis get_principal_inertia_axes() const = 0;
virtual real_t get_inverse_mass() const = 0; // get the mass
virtual Vector3 get_inverse_inertia() const = 0; // get density of this body space
@@ -64,13 +65,24 @@ public:
virtual Vector3 get_velocity_at_local_position(const Vector3 &p_position) const = 0;
- virtual void add_central_force(const Vector3 &p_force) = 0;
- virtual void add_force(const Vector3 &p_force, const Vector3 &p_position = Vector3()) = 0;
- virtual void add_torque(const Vector3 &p_torque) = 0;
virtual void apply_central_impulse(const Vector3 &p_impulse) = 0;
virtual void apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position = Vector3()) = 0;
virtual void apply_torque_impulse(const Vector3 &p_impulse) = 0;
+ virtual void apply_central_force(const Vector3 &p_force) = 0;
+ virtual void apply_force(const Vector3 &p_force, const Vector3 &p_position = Vector3()) = 0;
+ virtual void apply_torque(const Vector3 &p_torque) = 0;
+
+ virtual void add_constant_central_force(const Vector3 &p_force) = 0;
+ virtual void add_constant_force(const Vector3 &p_force, const Vector3 &p_position = Vector3()) = 0;
+ virtual void add_constant_torque(const Vector3 &p_torque) = 0;
+
+ virtual void set_constant_force(const Vector3 &p_force) = 0;
+ virtual Vector3 get_constant_force() const = 0;
+
+ virtual void set_constant_torque(const Vector3 &p_torque) = 0;
+ virtual Vector3 get_constant_torque() const = 0;
+
virtual void set_sleep_state(bool p_sleep) = 0;
virtual bool is_sleeping() const = 0;
@@ -96,55 +108,18 @@ public:
PhysicsDirectBodyState3D();
};
-class PhysicsShapeQueryParameters3D : public RefCounted {
- GDCLASS(PhysicsShapeQueryParameters3D, RefCounted);
- friend class PhysicsDirectSpaceState3D;
-
- RES shape_ref;
- RID shape;
- Transform3D transform;
- real_t margin = 0.0;
- Set<RID> exclude;
- uint32_t collision_mask = UINT32_MAX;
-
- bool collide_with_bodies = true;
- bool collide_with_areas = false;
-
-protected:
- static void _bind_methods();
-
-public:
- void set_shape(const RES &p_shape_ref);
- RES get_shape() const;
- void set_shape_rid(const RID &p_shape);
- RID get_shape_rid() const;
-
- void set_transform(const Transform3D &p_transform);
- Transform3D get_transform() const;
-
- void set_margin(real_t p_margin);
- real_t get_margin() const;
-
- void set_collision_mask(uint32_t p_collision_mask);
- uint32_t get_collision_mask() const;
-
- void set_exclude(const Vector<RID> &p_exclude);
- Vector<RID> get_exclude() const;
-
- void set_collide_with_bodies(bool p_enable);
- bool is_collide_with_bodies_enabled() const;
-
- void set_collide_with_areas(bool p_enable);
- bool is_collide_with_areas_enabled() const;
-};
+class PhysicsRayQueryParameters3D;
+class PhysicsPointQueryParameters3D;
+class PhysicsShapeQueryParameters3D;
class PhysicsDirectSpaceState3D : public Object {
GDCLASS(PhysicsDirectSpaceState3D, Object);
private:
- Dictionary _intersect_ray(const Vector3 &p_from, const Vector3 &p_to, const Vector<RID> &p_exclude = Vector<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false);
+ Dictionary _intersect_ray(const Ref<PhysicsRayQueryParameters3D> &p_ray_query);
+ Array _intersect_point(const Ref<PhysicsPointQueryParameters3D> &p_point_query, int p_max_results = 32);
Array _intersect_shape(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, int p_max_results = 32);
- Array _cast_motion(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, const Vector3 &p_motion);
+ Array _cast_motion(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query);
Array _collide_shape(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, int p_max_results = 32);
Dictionary _get_rest_info(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query);
@@ -152,27 +127,61 @@ protected:
static void _bind_methods();
public:
- struct ShapeResult {
+ struct RayParameters {
+ Vector3 from;
+ Vector3 to;
+ Set<RID> exclude;
+ uint32_t collision_mask = UINT32_MAX;
+
+ bool collide_with_bodies = true;
+ bool collide_with_areas = false;
+
+ bool hit_from_inside = false;
+ bool hit_back_faces = true;
+
+ bool pick_ray = false;
+ };
+
+ struct RayResult {
+ Vector3 position;
+ Vector3 normal;
RID rid;
ObjectID collider_id;
Object *collider = nullptr;
int shape = 0;
};
- virtual int intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
+ virtual bool intersect_ray(const RayParameters &p_parameters, RayResult &r_result) = 0;
- struct RayResult {
- Vector3 position;
- Vector3 normal;
+ struct ShapeResult {
RID rid;
ObjectID collider_id;
Object *collider = nullptr;
int shape = 0;
};
- virtual bool intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_ray = false) = 0;
+ struct PointParameters {
+ Vector3 position;
+ Set<RID> exclude;
+ uint32_t collision_mask = UINT32_MAX;
- virtual int intersect_shape(const RID &p_shape, const Transform3D &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
+ bool collide_with_bodies = true;
+ bool collide_with_areas = false;
+ };
+
+ virtual int intersect_point(const PointParameters &p_parameters, ShapeResult *r_results, int p_result_max) = 0;
+
+ struct ShapeParameters {
+ RID shape_rid;
+ Transform3D transform;
+ Vector3 motion;
+ real_t margin = 0.0;
+ Set<RID> exclude;
+ uint32_t collision_mask = UINT32_MAX;
+
+ bool collide_with_bodies = true;
+ bool collide_with_areas = false;
+ };
struct ShapeRestInfo {
Vector3 point;
@@ -180,14 +189,13 @@ public:
RID rid;
ObjectID collider_id;
int shape = 0;
- Vector3 linear_velocity; //velocity at contact point
+ Vector3 linear_velocity; // Velocity at contact point.
};
- virtual bool cast_motion(const RID &p_shape, const Transform3D &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, ShapeRestInfo *r_info = nullptr) = 0;
-
- virtual bool collide_shape(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
-
- virtual bool rest_info(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
+ virtual int intersect_shape(const ShapeParameters &p_parameters, ShapeResult *r_results, int p_result_max) = 0;
+ virtual bool cast_motion(const ShapeParameters &p_parameters, real_t &p_closest_safe, real_t &p_closest_unsafe, ShapeRestInfo *r_info = nullptr) = 0;
+ virtual bool collide_shape(const ShapeParameters &p_parameters, Vector3 *r_results, int p_result_max, int &r_result_count) = 0;
+ virtual bool rest_info(const ShapeParameters &p_parameters, ShapeRestInfo *r_info) = 0;
virtual Vector3 get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const = 0;
@@ -266,12 +274,12 @@ public:
enum SpaceParameter {
SPACE_PARAM_CONTACT_RECYCLE_RADIUS,
SPACE_PARAM_CONTACT_MAX_SEPARATION,
- SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION,
+ SPACE_PARAM_CONTACT_MAX_ALLOWED_PENETRATION,
+ SPACE_PARAM_CONTACT_DEFAULT_BIAS,
SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD,
SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD,
SPACE_PARAM_BODY_TIME_TO_SLEEP,
- SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO,
- SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS,
+ SPACE_PARAM_SOLVER_ITERATIONS,
};
virtual void space_set_param(RID p_space, SpaceParameter p_param, real_t p_value) = 0;
@@ -291,12 +299,15 @@ public:
//missing attenuation? missing better override?
enum AreaParameter {
+ AREA_PARAM_GRAVITY_OVERRIDE_MODE,
AREA_PARAM_GRAVITY,
AREA_PARAM_GRAVITY_VECTOR,
AREA_PARAM_GRAVITY_IS_POINT,
AREA_PARAM_GRAVITY_DISTANCE_SCALE,
AREA_PARAM_GRAVITY_POINT_ATTENUATION,
+ AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE,
AREA_PARAM_LINEAR_DAMP,
+ AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE,
AREA_PARAM_ANGULAR_DAMP,
AREA_PARAM_PRIORITY,
AREA_PARAM_WIND_FORCE_MAGNITUDE,
@@ -318,9 +329,6 @@ public:
AREA_SPACE_OVERRIDE_REPLACE_COMBINE
};
- virtual void area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) = 0;
- virtual AreaSpaceOverrideMode area_get_space_override_mode(RID p_area) const = 0;
-
virtual void area_add_shape(RID p_area, RID p_shape, const Transform3D &p_transform = Transform3D(), bool p_disabled = false) = 0;
virtual void area_set_shape(RID p_area, int p_shape_idx, RID p_shape) = 0;
virtual void area_set_shape_transform(RID p_area, int p_shape_idx, const Transform3D &p_transform) = 0;
@@ -348,8 +356,8 @@ public:
virtual void area_set_monitorable(RID p_area, bool p_monitorable) = 0;
- virtual void area_set_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) = 0;
- virtual void area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) = 0;
+ virtual void area_set_monitor_callback(RID p_area, const Callable &p_callback) = 0;
+ virtual void area_set_area_monitor_callback(RID p_area, const Callable &p_callback) = 0;
virtual void area_set_ray_pickable(RID p_area, bool p_enable) = 0;
@@ -364,6 +372,11 @@ public:
BODY_MODE_DYNAMIC_LINEAR,
};
+ enum BodyDampMode {
+ BODY_DAMP_MODE_COMBINE,
+ BODY_DAMP_MODE_REPLACE,
+ };
+
virtual RID body_create() = 0;
virtual void body_set_space(RID p_body, RID p_space) = 0;
@@ -408,6 +421,8 @@ public:
BODY_PARAM_INERTIA,
BODY_PARAM_CENTER_OF_MASS,
BODY_PARAM_GRAVITY_SCALE,
+ BODY_PARAM_LINEAR_DAMP_MODE,
+ BODY_PARAM_ANGULAR_DAMP_MODE,
BODY_PARAM_LINEAR_DAMP,
BODY_PARAM_ANGULAR_DAMP,
BODY_PARAM_MAX,
@@ -430,20 +445,24 @@ public:
virtual void body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) = 0;
virtual Variant body_get_state(RID p_body, BodyState p_state) const = 0;
- //do something about it
- virtual void body_set_applied_force(RID p_body, const Vector3 &p_force) = 0;
- virtual Vector3 body_get_applied_force(RID p_body) const = 0;
-
- virtual void body_set_applied_torque(RID p_body, const Vector3 &p_torque) = 0;
- virtual Vector3 body_get_applied_torque(RID p_body) const = 0;
-
- virtual void body_add_central_force(RID p_body, const Vector3 &p_force) = 0;
- virtual void body_add_force(RID p_body, const Vector3 &p_force, const Vector3 &p_position = Vector3()) = 0;
- virtual void body_add_torque(RID p_body, const Vector3 &p_torque) = 0;
-
virtual void body_apply_central_impulse(RID p_body, const Vector3 &p_impulse) = 0;
virtual void body_apply_impulse(RID p_body, const Vector3 &p_impulse, const Vector3 &p_position = Vector3()) = 0;
virtual void body_apply_torque_impulse(RID p_body, const Vector3 &p_impulse) = 0;
+
+ virtual void body_apply_central_force(RID p_body, const Vector3 &p_force) = 0;
+ virtual void body_apply_force(RID p_body, const Vector3 &p_force, const Vector3 &p_position = Vector3()) = 0;
+ virtual void body_apply_torque(RID p_body, const Vector3 &p_torque) = 0;
+
+ virtual void body_add_constant_central_force(RID p_body, const Vector3 &p_force) = 0;
+ virtual void body_add_constant_force(RID p_body, const Vector3 &p_force, const Vector3 &p_position = Vector3()) = 0;
+ virtual void body_add_constant_torque(RID p_body, const Vector3 &p_torque) = 0;
+
+ virtual void body_set_constant_force(RID p_body, const Vector3 &p_force) = 0;
+ virtual Vector3 body_get_constant_force(RID p_body) const = 0;
+
+ virtual void body_set_constant_torque(RID p_body, const Vector3 &p_torque) = 0;
+ virtual Vector3 body_get_constant_torque(RID p_body) const = 0;
+
virtual void body_set_axis_velocity(RID p_body, const Vector3 &p_axis_velocity) = 0;
enum BodyAxis {
@@ -764,8 +783,6 @@ public:
virtual bool is_flushing_queries() const = 0;
- virtual void set_collision_iterations(int p_iterations) = 0;
-
enum ProcessInfo {
INFO_ACTIVE_OBJECTS,
INFO_COLLISION_PAIRS,
@@ -778,6 +795,110 @@ public:
~PhysicsServer3D();
};
+class PhysicsRayQueryParameters3D : public RefCounted {
+ GDCLASS(PhysicsRayQueryParameters3D, RefCounted);
+
+ PhysicsDirectSpaceState3D::RayParameters parameters;
+
+protected:
+ static void _bind_methods();
+
+public:
+ const PhysicsDirectSpaceState3D::RayParameters &get_parameters() const { return parameters; }
+
+ void set_from(const Vector3 &p_from) { parameters.from = p_from; }
+ const Vector3 &get_from() const { return parameters.from; }
+
+ void set_to(const Vector3 &p_to) { parameters.to = p_to; }
+ const Vector3 &get_to() const { return parameters.to; }
+
+ void set_collision_mask(uint32_t p_mask) { parameters.collision_mask = p_mask; }
+ uint32_t get_collision_mask() const { return parameters.collision_mask; }
+
+ void set_collide_with_bodies(bool p_enable) { parameters.collide_with_bodies = p_enable; }
+ bool is_collide_with_bodies_enabled() const { return parameters.collide_with_bodies; }
+
+ void set_collide_with_areas(bool p_enable) { parameters.collide_with_areas = p_enable; }
+ bool is_collide_with_areas_enabled() const { return parameters.collide_with_areas; }
+
+ void set_hit_from_inside(bool p_enable) { parameters.hit_from_inside = p_enable; }
+ bool is_hit_from_inside_enabled() const { return parameters.hit_from_inside; }
+
+ void set_hit_back_faces(bool p_enable) { parameters.hit_back_faces = p_enable; }
+ bool is_hit_back_faces_enabled() const { return parameters.hit_back_faces; }
+
+ void set_exclude(const Vector<RID> &p_exclude);
+ Vector<RID> get_exclude() const;
+};
+
+class PhysicsPointQueryParameters3D : public RefCounted {
+ GDCLASS(PhysicsPointQueryParameters3D, RefCounted);
+
+ PhysicsDirectSpaceState3D::PointParameters parameters;
+
+protected:
+ static void _bind_methods();
+
+public:
+ const PhysicsDirectSpaceState3D::PointParameters &get_parameters() const { return parameters; }
+
+ void set_position(const Vector3 &p_position) { parameters.position = p_position; }
+ const Vector3 &get_position() const { return parameters.position; }
+
+ void set_collision_mask(uint32_t p_mask) { parameters.collision_mask = p_mask; }
+ uint32_t get_collision_mask() const { return parameters.collision_mask; }
+
+ void set_collide_with_bodies(bool p_enable) { parameters.collide_with_bodies = p_enable; }
+ bool is_collide_with_bodies_enabled() const { return parameters.collide_with_bodies; }
+
+ void set_collide_with_areas(bool p_enable) { parameters.collide_with_areas = p_enable; }
+ bool is_collide_with_areas_enabled() const { return parameters.collide_with_areas; }
+
+ void set_exclude(const Vector<RID> &p_exclude);
+ Vector<RID> get_exclude() const;
+};
+
+class PhysicsShapeQueryParameters3D : public RefCounted {
+ GDCLASS(PhysicsShapeQueryParameters3D, RefCounted);
+
+ PhysicsDirectSpaceState3D::ShapeParameters parameters;
+
+ RES shape_ref;
+
+protected:
+ static void _bind_methods();
+
+public:
+ const PhysicsDirectSpaceState3D::ShapeParameters &get_parameters() const { return parameters; }
+
+ void set_shape(const RES &p_shape_ref);
+ RES get_shape() const { return shape_ref; }
+
+ void set_shape_rid(const RID &p_shape);
+ RID get_shape_rid() const { return parameters.shape_rid; }
+
+ void set_transform(const Transform3D &p_transform) { parameters.transform = p_transform; }
+ const Transform3D &get_transform() const { return parameters.transform; }
+
+ void set_motion(const Vector3 &p_motion) { parameters.motion = p_motion; }
+ const Vector3 &get_motion() const { return parameters.motion; }
+
+ void set_margin(real_t p_margin) { parameters.margin = p_margin; }
+ real_t get_margin() const { return parameters.margin; }
+
+ void set_collision_mask(uint32_t p_mask) { parameters.collision_mask = p_mask; }
+ uint32_t get_collision_mask() const { return parameters.collision_mask; }
+
+ void set_collide_with_bodies(bool p_enable) { parameters.collide_with_bodies = p_enable; }
+ bool is_collide_with_bodies_enabled() const { return parameters.collide_with_bodies; }
+
+ void set_collide_with_areas(bool p_enable) { parameters.collide_with_areas = p_enable; }
+ bool is_collide_with_areas_enabled() const { return parameters.collide_with_areas; }
+
+ void set_exclude(const Vector<RID> &p_exclude);
+ Vector<RID> get_exclude() const;
+};
+
class PhysicsTestMotionParameters3D : public RefCounted {
GDCLASS(PhysicsTestMotionParameters3D, RefCounted);
@@ -857,10 +978,9 @@ class PhysicsServer3DManager {
name(p_ci.name),
create_callback(p_ci.create_callback) {}
- ClassInfo &operator=(const ClassInfo &p_ci) {
+ void operator=(const ClassInfo &p_ci) {
name = p_ci.name;
create_callback = p_ci.create_callback;
- return *this;
}
};
@@ -890,6 +1010,7 @@ VARIANT_ENUM_CAST(PhysicsServer3D::AreaParameter);
VARIANT_ENUM_CAST(PhysicsServer3D::AreaSpaceOverrideMode);
VARIANT_ENUM_CAST(PhysicsServer3D::BodyMode);
VARIANT_ENUM_CAST(PhysicsServer3D::BodyParameter);
+VARIANT_ENUM_CAST(PhysicsServer3D::BodyDampMode);
VARIANT_ENUM_CAST(PhysicsServer3D::BodyState);
VARIANT_ENUM_CAST(PhysicsServer3D::BodyAxis);
VARIANT_ENUM_CAST(PhysicsServer3D::PinJointParam);
@@ -903,4 +1024,4 @@ VARIANT_ENUM_CAST(PhysicsServer3D::G6DOFJointAxisFlag);
VARIANT_ENUM_CAST(PhysicsServer3D::AreaBodyStatus);
VARIANT_ENUM_CAST(PhysicsServer3D::ProcessInfo);
-#endif
+#endif // PHYSICS_SERVER_3D_H
diff --git a/servers/physics_3d/physics_server_3d_wrap_mt.cpp b/servers/physics_server_3d_wrap_mt.cpp
index c424100bba..822ca44b72 100644
--- a/servers/physics_3d/physics_server_3d_wrap_mt.cpp
+++ b/servers/physics_server_3d_wrap_mt.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/physics_3d/physics_server_3d_wrap_mt.h b/servers/physics_server_3d_wrap_mt.h
index 17d02addda..ecaef886e1 100644
--- a/servers/physics_3d/physics_server_3d_wrap_mt.h
+++ b/servers/physics_server_3d_wrap_mt.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef PHYSICS3DSERVERWRAPMT_H
-#define PHYSICS3DSERVERWRAPMT_H
+#ifndef PHYSICS_SERVER_3D_WRAP_MT_H
+#define PHYSICS_SERVER_3D_WRAP_MT_H
#include "core/config/project_settings.h"
#include "core/os/thread.h"
@@ -58,9 +58,7 @@ class PhysicsServer3DWrapMT : public PhysicsServer3D {
bool create_thread = false;
Semaphore step_sem;
- int step_pending = 0;
void thread_step(real_t p_delta);
- void thread_flush();
void thread_exit();
@@ -139,9 +137,6 @@ public:
FUNC2(area_set_space, RID, RID);
FUNC1RC(RID, area_get_space, RID);
- FUNC2(area_set_space_override_mode, RID, AreaSpaceOverrideMode);
- FUNC1RC(AreaSpaceOverrideMode, area_get_space_override_mode, RID);
-
FUNC4(area_add_shape, RID, RID, const Transform3D &, bool);
FUNC3(area_set_shape, RID, int, RID);
FUNC3(area_set_shape_transform, RID, int, const Transform3D &);
@@ -168,8 +163,8 @@ public:
FUNC2(area_set_monitorable, RID, bool);
FUNC2(area_set_ray_pickable, RID, bool);
- FUNC3(area_set_monitor_callback, RID, Object *, const StringName &);
- FUNC3(area_set_area_monitor_callback, RID, Object *, const StringName &);
+ FUNC2(area_set_monitor_callback, RID, const Callable &);
+ FUNC2(area_set_area_monitor_callback, RID, const Callable &);
/* BODY API */
@@ -218,18 +213,24 @@ public:
FUNC3(body_set_state, RID, BodyState, const Variant &);
FUNC2RC(Variant, body_get_state, RID, BodyState);
- FUNC2(body_set_applied_force, RID, const Vector3 &);
- FUNC1RC(Vector3, body_get_applied_force, RID);
-
- FUNC2(body_set_applied_torque, RID, const Vector3 &);
- FUNC1RC(Vector3, body_get_applied_torque, RID);
-
- FUNC2(body_add_central_force, RID, const Vector3 &);
- FUNC3(body_add_force, RID, const Vector3 &, const Vector3 &);
- FUNC2(body_add_torque, RID, const Vector3 &);
FUNC2(body_apply_torque_impulse, RID, const Vector3 &);
FUNC2(body_apply_central_impulse, RID, const Vector3 &);
FUNC3(body_apply_impulse, RID, const Vector3 &, const Vector3 &);
+
+ FUNC2(body_apply_central_force, RID, const Vector3 &);
+ FUNC3(body_apply_force, RID, const Vector3 &, const Vector3 &);
+ FUNC2(body_apply_torque, RID, const Vector3 &);
+
+ FUNC2(body_add_constant_central_force, RID, const Vector3 &);
+ FUNC3(body_add_constant_force, RID, const Vector3 &, const Vector3 &);
+ FUNC2(body_add_constant_torque, RID, const Vector3 &);
+
+ FUNC2(body_set_constant_force, RID, const Vector3 &);
+ FUNC1RC(Vector3, body_get_constant_force, RID);
+
+ FUNC2(body_set_constant_torque, RID, const Vector3 &);
+ FUNC1RC(Vector3, body_get_constant_torque, RID);
+
FUNC2(body_set_axis_velocity, RID, const Vector3 &);
FUNC3(body_set_axis_lock, RID, BodyAxis, bool);
@@ -375,7 +376,6 @@ public:
FUNC1(free, RID);
FUNC1(set_active, bool);
- FUNC1(set_collision_iterations, int);
virtual void init() override;
virtual void step(real_t p_step) override;
@@ -406,4 +406,4 @@ public:
#endif
#undef SYNC_DEBUG
-#endif // PHYSICS3DSERVERWRAPMT_H
+#endif // PHYSICS_SERVER_3D_WRAP_MT_H
diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp
index 28cd8374c0..3fbf4fe436 100644
--- a/servers/register_server_types.cpp
+++ b/servers/register_server_types.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -59,12 +59,12 @@
#include "display_server.h"
#include "navigation_server_2d.h"
#include "navigation_server_3d.h"
-#include "physics_2d/physics_server_2d_sw.h"
-#include "physics_2d/physics_server_2d_wrap_mt.h"
-#include "physics_3d/physics_server_3d_sw.h"
-#include "physics_3d/physics_server_3d_wrap_mt.h"
+#include "physics_2d/godot_physics_server_2d.h"
+#include "physics_3d/godot_physics_server_3d.h"
#include "physics_server_2d.h"
+#include "physics_server_2d_wrap_mt.h"
#include "physics_server_3d.h"
+#include "physics_server_3d_wrap_mt.h"
#include "rendering/renderer_compositor.h"
#include "rendering/rendering_device.h"
#include "rendering/rendering_device_binds.h"
@@ -82,7 +82,7 @@ ShaderTypes *shader_types = nullptr;
PhysicsServer3D *_createGodotPhysics3DCallback() {
bool using_threads = GLOBAL_GET("physics/3d/run_on_thread");
- PhysicsServer3D *physics_server = memnew(PhysicsServer3DSW(using_threads));
+ PhysicsServer3D *physics_server = memnew(GodotPhysicsServer3D(using_threads));
return memnew(PhysicsServer3DWrapMT(physics_server, using_threads));
}
@@ -90,7 +90,7 @@ PhysicsServer3D *_createGodotPhysics3DCallback() {
PhysicsServer2D *_createGodotPhysics2DCallback() {
bool using_threads = GLOBAL_GET("physics/2d/run_on_thread");
- PhysicsServer2D *physics_server = memnew(PhysicsServer2DSW(using_threads));
+ PhysicsServer2D *physics_server = memnew(GodotPhysicsServer2D(using_threads));
return memnew(PhysicsServer2DWrapMT(physics_server, using_threads));
}
@@ -133,6 +133,7 @@ void register_server_types() {
GDREGISTER_VIRTUAL_CLASS(XRInterface);
GDREGISTER_CLASS(XRInterfaceExtension); // can't register this as virtual because we need a creation function for our extensions.
+ GDREGISTER_CLASS(XRPose);
GDREGISTER_CLASS(XRPositionalTracker);
GDREGISTER_CLASS(AudioStream);
@@ -208,13 +209,17 @@ void register_server_types() {
GDREGISTER_VIRTUAL_CLASS(PhysicsDirectBodyState2D);
GDREGISTER_VIRTUAL_CLASS(PhysicsDirectSpaceState2D);
+ GDREGISTER_CLASS(PhysicsRayQueryParameters2D);
+ GDREGISTER_CLASS(PhysicsPointQueryParameters2D);
+ GDREGISTER_CLASS(PhysicsShapeQueryParameters2D);
GDREGISTER_CLASS(PhysicsTestMotionParameters2D);
GDREGISTER_CLASS(PhysicsTestMotionResult2D);
- GDREGISTER_CLASS(PhysicsShapeQueryParameters2D);
- GDREGISTER_CLASS(PhysicsShapeQueryParameters3D);
GDREGISTER_VIRTUAL_CLASS(PhysicsDirectBodyState3D);
GDREGISTER_VIRTUAL_CLASS(PhysicsDirectSpaceState3D);
+ GDREGISTER_CLASS(PhysicsRayQueryParameters3D);
+ GDREGISTER_CLASS(PhysicsPointQueryParameters3D);
+ GDREGISTER_CLASS(PhysicsShapeQueryParameters3D);
GDREGISTER_CLASS(PhysicsTestMotionParameters3D);
GDREGISTER_CLASS(PhysicsTestMotionResult3D);
diff --git a/servers/register_server_types.h b/servers/register_server_types.h
index f6a65cb653..cf6364eee3 100644
--- a/servers/register_server_types.h
+++ b/servers/register_server_types.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/rendering/rasterizer_dummy.h b/servers/rendering/rasterizer_dummy.h
index 7821210284..83da8388e4 100644
--- a/servers/rendering/rasterizer_dummy.h
+++ b/servers/rendering/rasterizer_dummy.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -44,6 +44,7 @@ public:
GeometryInstance *geometry_instance_create(RID p_base) override { return nullptr; }
void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override {}
void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override {}
+ void geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_override) override {}
void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_material) override {}
void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) override {}
void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) override {}
@@ -55,6 +56,9 @@ public:
void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) override {}
void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) override {}
void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) override {}
+ void geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) override {}
+ void geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) override {}
+ void geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) override {}
uint32_t geometry_instance_get_pair_mask() override { return 0; }
void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) override {}
@@ -113,8 +117,10 @@ public:
void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) override {}
void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) override {}
void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override {}
+ void environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) override {}
+ void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override {}
- void environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) override {}
+ void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) override {}
void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) override {}
void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) override {}
@@ -125,7 +131,7 @@ public:
void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) override {}
void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) override {}
- void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount) override {}
+ void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) override {}
void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) override {}
void environment_set_volumetric_fog_filter_active(bool p_enable) override {}
@@ -152,6 +158,12 @@ public:
void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override {}
void light_instance_mark_visible(RID p_light_instance) override {}
+ RID fog_volume_instance_create(RID p_fog_volume) override { return RID(); }
+ void fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) override {}
+ void fog_volume_instance_set_active(RID p_fog_volume_instance, bool p_active) override {}
+ RID fog_volume_instance_get_volume(RID p_fog_volume_instance) const override { return RID(); }
+ Vector3 fog_volume_instance_get_position(RID p_fog_volume_instance) const override { return Vector3(); }
+
RID reflection_atlas_create() override { return RID(); }
int reflection_atlas_get_size(RID p_ref_atlas) const override { return 0; }
void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) override {}
@@ -177,7 +189,7 @@ public:
void voxel_gi_set_quality(RS::VoxelGIQuality) override {}
- void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_info = nullptr) override {}
+ void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_info = nullptr) override {}
void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override {}
void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) override {}
@@ -186,7 +198,7 @@ public:
void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) override {}
RID render_buffers_create() override { return RID(); }
- void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) override {}
+ void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) override {}
void gi_set_use_half_resolution(bool p_enable) override {}
void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_curve) override {}
@@ -249,7 +261,7 @@ public:
Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const override { return Ref<Image>(); }
Vector<Ref<Image>> texture_3d_get(RID p_texture) const override { return Vector<Ref<Image>>(); }
- void texture_replace(RID p_texture, RID p_by_texture) override {}
+ void texture_replace(RID p_texture, RID p_by_texture) override { free(p_by_texture); }
void texture_set_size_override(RID p_texture, int p_width, int p_height) override {}
void texture_set_path(RID p_texture, const String &p_path) override {}
@@ -284,8 +296,8 @@ public:
String shader_get_code(RID p_shader) const override { return ""; }
void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const override {}
- void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) override {}
- RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const override { return RID(); }
+ void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) override {}
+ RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const override { return RID(); }
Variant shader_get_param_default(RID p_material, const StringName &p_param) const override { return Variant(); }
RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const override { return RS::ShaderNativeSourceCode(); };
@@ -318,8 +330,8 @@ public:
void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) override {}
void mesh_instance_check_for_update(RID p_mesh_instance) override {}
void update_mesh_instances() override {}
- void reflection_probe_set_lod_threshold(RID p_probe, float p_ratio) override {}
- float reflection_probe_get_lod_threshold(RID p_probe) const override { return 0.0; }
+ void reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) override {}
+ float reflection_probe_get_mesh_lod_threshold(RID p_probe) const override { return 0.0; }
void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) override {}
@@ -607,6 +619,17 @@ public:
void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) override {}
void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) override {}
+ /* FOG VOLUMES */
+
+ RID fog_volume_allocate() override { return RID(); }
+ void fog_volume_initialize(RID p_rid) override {}
+
+ void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) override {}
+ void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) override {}
+ void fog_volume_set_material(RID p_fog_volume, RID p_material) override {}
+ AABB fog_volume_get_aabb(RID p_fog_volume) const override { return AABB(); }
+ RS::FogVolumeShape fog_volume_get_shape(RID p_fog_volume) const override { return RS::FOG_VOLUME_SHAPE_BOX; }
+
/* VISIBILITY NOTIFIER */
virtual RID visibility_notifier_allocate() override { return RID(); }
virtual void visibility_notifier_initialize(RID p_notifier) override {}
@@ -672,7 +695,9 @@ public:
virtual void update_memory_info() override {}
virtual uint64_t get_rendering_info(RS::RenderingInfo p_info) override { return 0; }
- bool has_os_feature(const String &p_feature) const override { return false; }
+ bool has_os_feature(const String &p_feature) const override {
+ return p_feature == "rgtc" || p_feature == "bptc" || p_feature == "s3tc" || p_feature == "etc" || p_feature == "etc2";
+ }
void update_dirty_resources() override {}
@@ -680,6 +705,7 @@ public:
String get_video_adapter_name() const override { return String(); }
String get_video_adapter_vendor() const override { return String(); }
+ RenderingDevice::DeviceType get_video_adapter_type() const override { return RenderingDevice::DeviceType::DEVICE_TYPE_OTHER; }
static RendererStorage *base_singleton;
diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp
index 46683e8e68..418d2bc42e 100644
--- a/servers/rendering/renderer_canvas_cull.cpp
+++ b/servers/rendering/renderer_canvas_cull.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -137,8 +137,7 @@ void RendererCanvasCull::_attach_canvas_item_for_draw(RendererCanvasCull::Item *
// We have two choices now, if user has drawn something, we must assume users wants to draw the "mask", so compute the size based on this.
// If nothing has been drawn, we just take it over and draw it ourselves.
- if (ci->canvas_group->fit_empty && (ci->commands == nullptr ||
- (ci->commands->next == nullptr && ci->commands->type == RendererCanvasCull::Item::Command::TYPE_RECT && (static_cast<RendererCanvasCull::Item::CommandRect *>(ci->commands)->flags & RendererCanvasRender::CANVAS_RECT_IS_GROUP)))) {
+ if (ci->canvas_group->fit_empty && (ci->commands == nullptr || (ci->commands->next == nullptr && ci->commands->type == RendererCanvasCull::Item::Command::TYPE_RECT && (static_cast<RendererCanvasCull::Item::CommandRect *>(ci->commands)->flags & RendererCanvasRender::CANVAS_RECT_IS_GROUP)))) {
// No commands, or sole command is the one used to draw, so we (re)create the draw command.
ci->clear();
@@ -262,6 +261,10 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2
if (ci->clip) {
if (p_canvas_clip != nullptr) {
ci->final_clip_rect = p_canvas_clip->final_clip_rect.intersection(global_rect);
+ if (ci->final_clip_rect == Rect2()) {
+ // Clip rects do not intersect, so don't draw this item.
+ return;
+ }
} else {
ci->final_clip_rect = global_rect;
}
@@ -787,7 +790,7 @@ void RendererCanvasCull::canvas_item_add_texture_rect(RID p_item, const Rect2 &p
if (p_tile) {
rect->flags |= RendererCanvasRender::CANVAS_RECT_TILE;
rect->flags |= RendererCanvasRender::CANVAS_RECT_REGION;
- rect->source = Rect2(0, 0, fabsf(p_rect.size.width), fabsf(p_rect.size.height));
+ rect->source = Rect2(0, 0, ABS(p_rect.size.width), ABS(p_rect.size.height));
}
if (p_rect.size.x < 0) {
@@ -1437,7 +1440,7 @@ void RendererCanvasCull::canvas_light_occluder_set_polygon(RID p_occluder, RID p
ERR_FAIL_COND(!occluder);
if (occluder->polygon.is_valid()) {
- LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get_or_null(p_polygon);
+ LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get_or_null(occluder->polygon);
if (occluder_poly) {
occluder_poly->owners.erase(occluder);
}
diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h
index a2fdf95c76..fc53ce2327 100644
--- a/servers/rendering/renderer_canvas_cull.h
+++ b/servers/rendering/renderer_canvas_cull.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -152,7 +152,7 @@ public:
void erase_item(Item *p_item) {
int idx = find_item(p_item);
if (idx >= 0) {
- child_items.remove(idx);
+ child_items.remove_at(idx);
}
}
diff --git a/servers/rendering/renderer_canvas_render.cpp b/servers/rendering/renderer_canvas_render.cpp
index 1945435586..3b68cd74fd 100644
--- a/servers/rendering/renderer_canvas_render.cpp
+++ b/servers/rendering/renderer_canvas_render.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/rendering/renderer_canvas_render.h b/servers/rendering/renderer_canvas_render.h
index 04ddae4089..1840925f78 100644
--- a/servers/rendering/renderer_canvas_render.h
+++ b/servers/rendering/renderer_canvas_render.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/rendering/renderer_compositor.cpp b/servers/rendering/renderer_compositor.cpp
index 80c4625261..82e8bd6ef9 100644
--- a/servers/rendering/renderer_compositor.cpp
+++ b/servers/rendering/renderer_compositor.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/rendering/renderer_compositor.h b/servers/rendering/renderer_compositor.h
index 1971c3e781..f245af9a4a 100644
--- a/servers/rendering/renderer_compositor.h
+++ b/servers/rendering/renderer_compositor.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -67,6 +67,7 @@ private:
protected:
static RendererCompositor *(*_create_func)();
+ bool back_end = false;
public:
static RendererCompositor *create();
@@ -88,7 +89,7 @@ public:
virtual uint64_t get_frame_number() const = 0;
virtual double get_frame_delta_time() const = 0;
- virtual bool is_low_end() const = 0;
+ _FORCE_INLINE_ virtual bool is_low_end() const { return back_end; };
virtual bool is_xr_enabled() const;
RendererCompositor();
diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.cpp b/servers/rendering/renderer_rd/cluster_builder_rd.cpp
index b952ecbff0..6ad3556969 100644
--- a/servers/rendering/renderer_rd/cluster_builder_rd.cpp
+++ b/servers/rendering/renderer_rd/cluster_builder_rd.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -460,14 +460,6 @@ void ClusterBuilderRD::bake_cluster() {
RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(ClusterBuilderSharedDataRD::ClusterRender::PushConstant));
uint32_t instances = 1;
-#if 0
- for (uint32_t j = i+1; j < element_count; j++) {
- if (elements[i].type!=elements[j].type) {
- break;
- }
- instances++;
- }
-#endif
RD::get_singleton()->draw_list_draw(draw_list, true, instances);
i += instances;
}
diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.h b/servers/rendering/renderer_rd/cluster_builder_rd.h
index c0c03eb26a..7f6750fa7e 100644
--- a/servers/rendering/renderer_rd/cluster_builder_rd.h
+++ b/servers/rendering/renderer_rd/cluster_builder_rd.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -289,7 +289,7 @@ public:
e.touches_near = min_d < z_near;
} else {
//contains camera inside light
- Plane base_plane(xform.origin, -xform.basis.get_axis(Vector3::AXIS_Z));
+ Plane base_plane(-xform.basis.get_axis(Vector3::AXIS_Z), xform.origin);
float dist = base_plane.distance_to(Vector3());
if (dist >= 0 && dist < radius) {
//inside, check angle
diff --git a/servers/rendering/renderer_rd/effects_rd.cpp b/servers/rendering/renderer_rd/effects_rd.cpp
index c69408a30b..4ab50782df 100644
--- a/servers/rendering/renderer_rd/effects_rd.cpp
+++ b/servers/rendering/renderer_rd/effects_rd.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -237,6 +237,43 @@ RID EffectsRD::_get_compute_uniform_set_from_image_pair(RID p_texture1, RID p_te
return uniform_set;
}
+void EffectsRD::fsr_upscale(RID p_source_rd_texture, RID p_secondary_texture, RID p_destination_texture, const Size2i &p_internal_size, const Size2i &p_size, float p_fsr_upscale_sharpness) {
+ memset(&FSR_upscale.push_constant, 0, sizeof(FSRUpscalePushConstant));
+
+ int dispatch_x = (p_size.x + 15) / 16;
+ int dispatch_y = (p_size.y + 15) / 16;
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, FSR_upscale.pipeline);
+
+ FSR_upscale.push_constant.resolution_width = p_internal_size.width;
+ FSR_upscale.push_constant.resolution_height = p_internal_size.height;
+ FSR_upscale.push_constant.upscaled_width = p_size.width;
+ FSR_upscale.push_constant.upscaled_height = p_size.height;
+ FSR_upscale.push_constant.sharpness = p_fsr_upscale_sharpness;
+
+ //FSR Easc
+ FSR_upscale.push_constant.pass = FSR_UPSCALE_PASS_EASU;
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_secondary_texture), 1);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &FSR_upscale.push_constant, sizeof(FSRUpscalePushConstant));
+
+ RD::get_singleton()->compute_list_dispatch(compute_list, dispatch_x, dispatch_y, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ //FSR Rcas
+ FSR_upscale.push_constant.pass = FSR_UPSCALE_PASS_RCAS;
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_secondary_texture), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_destination_texture), 1);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &FSR_upscale.push_constant, sizeof(FSRUpscalePushConstant));
+
+ RD::get_singleton()->compute_list_dispatch(compute_list, dispatch_x, dispatch_y, 1);
+
+ RD::get_singleton()->compute_list_end(compute_list);
+}
+
void EffectsRD::copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_uv_rect, RD::DrawListID p_draw_list, bool p_flip_y, bool p_panorama) {
memset(&copy_to_fb.push_constant, 0, sizeof(CopyToFbPushConstant));
@@ -409,7 +446,7 @@ void EffectsRD::set_color(RID p_dest_texture, const Color &p_color, const Rect2i
}
void EffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_texture, RID p_back_texture, const Rect2i &p_region, bool p_8bit_dst) {
- ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the compute version of the gaussian blur with the mobile renderer.");
+ ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the gaussian blur with the mobile renderer.");
memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
@@ -443,7 +480,7 @@ void EffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_texture, RID p_back
RD::get_singleton()->compute_list_end();
}
-void EffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_treshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) {
+void EffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) {
ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the gaussian glow with the mobile renderer.");
memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
@@ -456,7 +493,7 @@ void EffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const
copy.push_constant.glow_strength = p_strength;
copy.push_constant.glow_bloom = p_bloom;
- copy.push_constant.glow_hdr_threshold = p_hdr_bleed_treshold;
+ copy.push_constant.glow_hdr_threshold = p_hdr_bleed_threshold;
copy.push_constant.glow_hdr_scale = p_hdr_bleed_scale;
copy.push_constant.glow_exposure = p_exposure;
copy.push_constant.glow_white = 0; //actually unused
@@ -479,7 +516,7 @@ void EffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const
RD::get_singleton()->compute_list_end();
}
-void EffectsRD::gaussian_glow_raster(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_treshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) {
+void EffectsRD::gaussian_glow_raster(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) {
ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of the gaussian glow with the clustered renderer.");
memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
@@ -492,7 +529,7 @@ void EffectsRD::gaussian_glow_raster(RID p_source_rd_texture, RID p_framebuffer_
blur_raster.push_constant.glow_strength = p_strength;
blur_raster.push_constant.glow_bloom = p_bloom;
- blur_raster.push_constant.glow_hdr_threshold = p_hdr_bleed_treshold;
+ blur_raster.push_constant.glow_hdr_threshold = p_hdr_bleed_threshold;
blur_raster.push_constant.glow_hdr_scale = p_hdr_bleed_scale;
blur_raster.push_constant.glow_exposure = p_exposure;
blur_raster.push_constant.glow_white = 0; //actually unused
@@ -1278,6 +1315,111 @@ void EffectsRD::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far,
}
}
+void EffectsRD::downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_mipmaps, RS::EnvironmentSSAOQuality p_ssao_quality, RS::EnvironmentSSILQuality p_ssil_quality, bool p_invalidate_uniform_set, bool p_ssao_half_size, bool p_ssil_half_size, Size2i p_full_screen_size, const CameraMatrix &p_projection) {
+ // Downsample and deinterleave the depth buffer for SSAO and SSIL
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+
+ int downsample_pipeline = SS_EFFECTS_DOWNSAMPLE;
+ bool use_mips = p_ssao_quality > RS::ENV_SSAO_QUALITY_MEDIUM || p_ssil_quality > RS::ENV_SSIL_QUALITY_MEDIUM;
+
+ if (p_ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW && p_ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
+ downsample_pipeline = SS_EFFECTS_DOWNSAMPLE_HALF;
+ } else if (use_mips) {
+ downsample_pipeline = SS_EFFECTS_DOWNSAMPLE_MIPMAP;
+ }
+
+ bool use_half_size = false;
+ bool use_full_mips = false;
+
+ if (p_ssao_half_size && p_ssil_half_size) {
+ downsample_pipeline++;
+ use_half_size = true;
+ } else if (p_ssao_half_size != p_ssil_half_size) {
+ if (use_mips) {
+ downsample_pipeline = SS_EFFECTS_DOWNSAMPLE_FULL_MIPS;
+ use_full_mips = true;
+ } else {
+ // Only need the first two mipmaps, but the cost to generate the next two is trivial
+ // TODO investigate the benefit of a shader version to generate only 2 mips
+ downsample_pipeline = SS_EFFECTS_DOWNSAMPLE_MIPMAP;
+ use_mips = true;
+ }
+ }
+
+ int depth_index = use_half_size ? 1 : 0;
+
+ RD::get_singleton()->draw_command_begin_label("Downsample Depth");
+ if (p_invalidate_uniform_set || use_full_mips != ss_effects.used_full_mips_last_frame || use_half_size != ss_effects.used_half_size_last_frame || use_mips != ss_effects.used_mips_last_frame) {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 0;
+ u.ids.push_back(p_depth_mipmaps[depth_index + 1]);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 1;
+ u.ids.push_back(p_depth_mipmaps[depth_index + 2]);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 2;
+ u.ids.push_back(p_depth_mipmaps[depth_index + 3]);
+ uniforms.push_back(u);
+ }
+ if (use_full_mips) {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 3;
+ u.ids.push_back(p_depth_mipmaps[4]);
+ uniforms.push_back(u);
+ }
+ ss_effects.downsample_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, use_full_mips ? 6 : 2), 2);
+ }
+
+ float depth_linearize_mul = -p_projection.matrix[3][2];
+ float depth_linearize_add = p_projection.matrix[2][2];
+ if (depth_linearize_mul * depth_linearize_add < 0) {
+ depth_linearize_add = -depth_linearize_add;
+ }
+
+ ss_effects.downsample_push_constant.orthogonal = p_projection.is_orthogonal();
+ ss_effects.downsample_push_constant.z_near = depth_linearize_mul;
+ ss_effects.downsample_push_constant.z_far = depth_linearize_add;
+ if (ss_effects.downsample_push_constant.orthogonal) {
+ ss_effects.downsample_push_constant.z_near = p_projection.get_z_near();
+ ss_effects.downsample_push_constant.z_far = p_projection.get_z_far();
+ }
+ ss_effects.downsample_push_constant.pixel_size[0] = 1.0 / p_full_screen_size.x;
+ ss_effects.downsample_push_constant.pixel_size[1] = 1.0 / p_full_screen_size.y;
+ ss_effects.downsample_push_constant.radius_sq = 1.0;
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ss_effects.pipelines[downsample_pipeline]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_buffer), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_depth_mipmaps[depth_index + 0]), 1);
+ if (use_mips) {
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ss_effects.downsample_uniform_set, 2);
+ }
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ss_effects.downsample_push_constant, sizeof(SSEffectsDownsamplePushConstant));
+
+ Size2i size(MAX(1, p_full_screen_size.x >> (use_half_size ? 2 : 1)), MAX(1, p_full_screen_size.y >> (use_half_size ? 2 : 1)));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, size.x, size.y, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ RD::get_singleton()->draw_command_end_label();
+
+ RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_COMPUTE);
+
+ ss_effects.used_full_mips_last_frame = use_mips;
+ ss_effects.used_full_mips_last_frame = use_full_mips;
+ ss_effects.used_half_size_last_frame = use_half_size;
+}
+
void EffectsRD::gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set) {
RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_gather_uniform_set, 0);
if ((p_settings.quality == RS::ENV_SSAO_QUALITY_ULTRA) && !p_adaptive_base_pass) {
@@ -1304,82 +1446,12 @@ void EffectsRD::gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID>
RD::get_singleton()->compute_list_add_barrier(p_compute_list);
}
-void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_depth_mipmaps_texture, const Vector<RID> &p_depth_mipmaps, RID p_ao, const Vector<RID> p_ao_slices, RID p_ao_pong, const Vector<RID> p_ao_pong_slices, RID p_upscale_buffer, RID p_importance_map, RID p_importance_map_pong, const CameraMatrix &p_projection, const SSAOSettings &p_settings, bool p_invalidate_uniform_sets, RID &r_downsample_uniform_set, RID &r_gather_uniform_set, RID &r_importance_map_uniform_set) {
+void EffectsRD::generate_ssao(RID p_normal_buffer, RID p_depth_mipmaps_texture, RID p_ao, const Vector<RID> p_ao_slices, RID p_ao_pong, const Vector<RID> p_ao_pong_slices, RID p_upscale_buffer, RID p_importance_map, RID p_importance_map_pong, const CameraMatrix &p_projection, const SSAOSettings &p_settings, bool p_invalidate_uniform_sets, RID &r_gather_uniform_set, RID &r_importance_map_uniform_set) {
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->draw_command_begin_label("SSAO");
+ memset(&ssao.gather_push_constant, 0, sizeof(SSAOGatherPushConstant));
/* FIRST PASS */
- // Downsample and deinterleave the depth buffer.
- {
- RD::get_singleton()->draw_command_begin_label("Downsample Depth");
- if (p_invalidate_uniform_sets) {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 0;
- u.ids.push_back(p_depth_mipmaps[1]);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 1;
- u.ids.push_back(p_depth_mipmaps[2]);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 2;
- u.ids.push_back(p_depth_mipmaps[3]);
- uniforms.push_back(u);
- }
- r_downsample_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.downsample_shader.version_get_shader(ssao.downsample_shader_version, 2), 2);
- }
-
- float depth_linearize_mul = -p_projection.matrix[3][2];
- float depth_linearize_add = p_projection.matrix[2][2];
- if (depth_linearize_mul * depth_linearize_add < 0) {
- depth_linearize_add = -depth_linearize_add;
- }
-
- ssao.downsample_push_constant.orthogonal = p_projection.is_orthogonal();
- ssao.downsample_push_constant.z_near = depth_linearize_mul;
- ssao.downsample_push_constant.z_far = depth_linearize_add;
- if (ssao.downsample_push_constant.orthogonal) {
- ssao.downsample_push_constant.z_near = p_projection.get_z_near();
- ssao.downsample_push_constant.z_far = p_projection.get_z_far();
- }
- ssao.downsample_push_constant.pixel_size[0] = 1.0 / p_settings.full_screen_size.x;
- ssao.downsample_push_constant.pixel_size[1] = 1.0 / p_settings.full_screen_size.y;
- ssao.downsample_push_constant.radius_sq = p_settings.radius * p_settings.radius;
-
- int downsample_pipeline = SSAO_DOWNSAMPLE;
- if (p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {
- downsample_pipeline = SSAO_DOWNSAMPLE_HALF;
- } else if (p_settings.quality > RS::ENV_SSAO_QUALITY_MEDIUM) {
- downsample_pipeline = SSAO_DOWNSAMPLE_MIPMAP;
- }
-
- if (p_settings.half_size) {
- downsample_pipeline++;
- }
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[downsample_pipeline]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_buffer), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_depth_mipmaps[0]), 1);
- if (p_settings.quality > RS::ENV_SSAO_QUALITY_MEDIUM) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, r_downsample_uniform_set, 2);
- }
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.downsample_push_constant, sizeof(SSAODownsamplePushConstant));
-
- Size2i size(MAX(1, p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1)), MAX(1, p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1)));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, size.x, size.y, 1);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- RD::get_singleton()->draw_command_end_label(); // Downsample SSAO
- }
+ RD::get_singleton()->draw_command_begin_label("Process Screen Space Ambient Occlusion");
/* SECOND PASS */
// Sample SSAO
{
@@ -1432,7 +1504,7 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
u.binding = 0;
- u.ids.push_back(ssao.mirror_sampler);
+ u.ids.push_back(default_sampler);
u.ids.push_back(p_depth_mipmaps_texture);
uniforms.push_back(u);
}
@@ -1447,7 +1519,7 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.binding = 2;
- u.ids.push_back(ssao.gather_constants_buffer);
+ u.ids.push_back(ss_effects.gather_constants_buffer);
uniforms.push_back(u);
}
r_gather_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 0), 0);
@@ -1537,6 +1609,7 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep
for (int pass = 0; pass < blur_passes; pass++) {
int blur_pipeline = SSAO_BLUR_PASS;
if (p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW) {
+ blur_pipeline = SSAO_BLUR_PASS_SMART;
if (pass < blur_passes - 2) {
blur_pipeline = SSAO_BLUR_PASS_WIDE;
} else {
@@ -1554,7 +1627,7 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep
if (p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao_slices[i]), 0);
} else {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_and_sampler(p_ao_slices[i], ssao.mirror_sampler), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_and_sampler(p_ao_slices[i], ss_effects.mirror_sampler), 0);
}
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ao_pong_slices[i]), 1);
@@ -1562,7 +1635,7 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep
if (p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao_pong_slices[i]), 0);
} else {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_and_sampler(p_ao_pong_slices[i], ssao.mirror_sampler), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_and_sampler(p_ao_pong_slices[i], ss_effects.mirror_sampler), 0);
}
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ao_slices[i]), 1);
}
@@ -1612,12 +1685,305 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep
RD::get_singleton()->draw_command_end_label(); // Interleave
}
RD::get_singleton()->draw_command_end_label(); //SSAO
- RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_TRANSFER); //wait for upcoming transfer
+ RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER); //wait for upcoming transfer
int zero[1] = { 0 };
RD::get_singleton()->buffer_update(ssao.importance_map_load_counter, 0, sizeof(uint32_t), &zero, 0); //no barrier
}
+void EffectsRD::gather_ssil(RD::ComputeListID p_compute_list, const Vector<RID> p_ssil_slices, const Vector<RID> p_edges_slices, const SSILSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set, RID p_projection_uniform_set) {
+ RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_gather_uniform_set, 0);
+ if ((p_settings.quality == RS::ENV_SSIL_QUALITY_ULTRA) && !p_adaptive_base_pass) {
+ RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_importance_map_uniform_set, 1);
+ }
+ RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_projection_uniform_set, 3);
+
+ for (int i = 0; i < 4; i++) {
+ if ((p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
+ continue;
+ }
+
+ ssil.gather_push_constant.pass_coord_offset[0] = i % 2;
+ ssil.gather_push_constant.pass_coord_offset[1] = i / 2;
+ ssil.gather_push_constant.pass_uv_offset[0] = ((i % 2) - 0.0) / p_settings.full_screen_size.x;
+ ssil.gather_push_constant.pass_uv_offset[1] = ((i / 2) - 0.0) / p_settings.full_screen_size.y;
+ ssil.gather_push_constant.pass = i;
+ RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, _get_compute_uniform_set_from_image_pair(p_ssil_slices[i], p_edges_slices[i]), 2);
+ RD::get_singleton()->compute_list_set_push_constant(p_compute_list, &ssil.gather_push_constant, sizeof(SSILGatherPushConstant));
+
+ Size2i size = Size2i(p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1), p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1));
+
+ RD::get_singleton()->compute_list_dispatch_threads(p_compute_list, size.x, size.y, 1);
+ }
+ RD::get_singleton()->compute_list_add_barrier(p_compute_list);
+}
+
+void EffectsRD::screen_space_indirect_lighting(RID p_diffuse, RID p_destination, RID p_normal_buffer, RID p_depth_mipmaps_texture, RID p_ssil, const Vector<RID> p_ssil_slices, RID p_ssil_pong, const Vector<RID> p_ssil_pong_slices, RID p_importance_map, RID p_importance_map_pong, RID p_edges, const Vector<RID> p_edges_slices, const CameraMatrix &p_projection, const CameraMatrix &p_last_projection, const SSILSettings &p_settings, bool p_invalidate_uniform_sets, RID &r_gather_uniform_set, RID &r_importance_map_uniform_set, RID &r_projection_uniform_set) {
+ RD::get_singleton()->draw_command_begin_label("Process Screen Space Indirect Lighting");
+ //Store projection info before starting the compute list
+ SSILProjectionUniforms projection_uniforms;
+ store_camera(p_last_projection, projection_uniforms.inv_last_frame_projection_matrix);
+
+ RD::get_singleton()->buffer_update(ssil.projection_uniform_buffer, 0, sizeof(SSILProjectionUniforms), &projection_uniforms);
+
+ memset(&ssil.gather_push_constant, 0, sizeof(SSILGatherPushConstant));
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ {
+ RD::get_singleton()->draw_command_begin_label("Gather Samples");
+ ssil.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x;
+ ssil.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y;
+
+ ssil.gather_push_constant.half_screen_pixel_size[0] = 1.0 / p_settings.half_screen_size.x;
+ ssil.gather_push_constant.half_screen_pixel_size[1] = 1.0 / p_settings.half_screen_size.y;
+ float tan_half_fov_x = 1.0 / p_projection.matrix[0][0];
+ float tan_half_fov_y = 1.0 / p_projection.matrix[1][1];
+ ssil.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0;
+ ssil.gather_push_constant.NDC_to_view_mul[1] = tan_half_fov_y * -2.0;
+ ssil.gather_push_constant.NDC_to_view_add[0] = tan_half_fov_x * -1.0;
+ ssil.gather_push_constant.NDC_to_view_add[1] = tan_half_fov_y;
+ ssil.gather_push_constant.z_near = p_projection.get_z_near();
+ ssil.gather_push_constant.z_far = p_projection.get_z_far();
+ ssil.gather_push_constant.is_orthogonal = p_projection.is_orthogonal();
+
+ ssil.gather_push_constant.half_screen_pixel_size_x025[0] = ssil.gather_push_constant.half_screen_pixel_size[0] * 0.25;
+ ssil.gather_push_constant.half_screen_pixel_size_x025[1] = ssil.gather_push_constant.half_screen_pixel_size[1] * 0.25;
+
+ ssil.gather_push_constant.radius = p_settings.radius;
+ float radius_near_limit = (p_settings.radius * 1.2f);
+ if (p_settings.quality <= RS::ENV_SSIL_QUALITY_LOW) {
+ radius_near_limit *= 1.50f;
+
+ if (p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
+ ssil.gather_push_constant.radius *= 0.8f;
+ }
+ }
+ radius_near_limit /= tan_half_fov_y;
+ ssil.gather_push_constant.intensity = p_settings.intensity * Math_PI;
+ ssil.gather_push_constant.fade_out_mul = -1.0 / (p_settings.fadeout_to - p_settings.fadeout_from);
+ ssil.gather_push_constant.fade_out_add = p_settings.fadeout_from / (p_settings.fadeout_to - p_settings.fadeout_from) + 1.0;
+ ssil.gather_push_constant.inv_radius_near_limit = 1.0f / radius_near_limit;
+ ssil.gather_push_constant.neg_inv_radius = -1.0 / ssil.gather_push_constant.radius;
+ ssil.gather_push_constant.normal_rejection_amount = p_settings.normal_rejection;
+
+ ssil.gather_push_constant.load_counter_avg_div = 9.0 / float((p_settings.quarter_screen_size.x) * (p_settings.quarter_screen_size.y) * 255);
+ ssil.gather_push_constant.adaptive_sample_limit = p_settings.adaptive_target;
+
+ ssil.gather_push_constant.quality = MAX(0, p_settings.quality - 1);
+ ssil.gather_push_constant.size_multiplier = p_settings.half_size ? 2 : 1;
+
+ if (p_invalidate_uniform_sets) {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
+ u.binding = 0;
+ u.ids.push_back(default_mipmap_sampler);
+ u.ids.push_back(p_diffuse);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 1;
+ u.ids.push_back(ssil.projection_uniform_buffer);
+ uniforms.push_back(u);
+ }
+ r_projection_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0), 3);
+ }
+
+ if (p_invalidate_uniform_sets) {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
+ u.binding = 0;
+ u.ids.push_back(default_sampler);
+ u.ids.push_back(p_depth_mipmaps_texture);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 1;
+ u.ids.push_back(p_normal_buffer);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 2;
+ u.ids.push_back(ss_effects.gather_constants_buffer);
+ uniforms.push_back(u);
+ }
+ r_gather_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0), 0);
+ }
+
+ if (p_invalidate_uniform_sets) {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 0;
+ u.ids.push_back(p_ssil_pong);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
+ u.binding = 1;
+ u.ids.push_back(default_sampler);
+ u.ids.push_back(p_importance_map);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 2;
+ u.ids.push_back(ssil.importance_map_load_counter);
+ uniforms.push_back(u);
+ }
+ r_importance_map_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 2), 1);
+ }
+
+ if (p_settings.quality == RS::ENV_SSIL_QUALITY_ULTRA) {
+ RD::get_singleton()->draw_command_begin_label("Generate Importance Map");
+ ssil.importance_map_push_constant.half_screen_pixel_size[0] = 1.0 / p_settings.half_screen_size.x;
+ ssil.importance_map_push_constant.half_screen_pixel_size[1] = 1.0 / p_settings.half_screen_size.y;
+ ssil.importance_map_push_constant.intensity = p_settings.intensity * Math_PI;
+ //base pass
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER_BASE]);
+ gather_ssil(compute_list, p_ssil_pong_slices, p_edges_slices, p_settings, true, r_gather_uniform_set, r_importance_map_uniform_set, r_projection_uniform_set);
+ //generate importance map
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GENERATE_IMPORTANCE_MAP]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ssil_pong), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_importance_map), 1);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.quarter_screen_size.x, p_settings.quarter_screen_size.y, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ // process Importance Map A
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_PROCESS_IMPORTANCE_MAPA]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_importance_map), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_importance_map_pong), 1);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.quarter_screen_size.x, p_settings.quarter_screen_size.y, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ // process Importance Map B
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_PROCESS_IMPORTANCE_MAPB]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_importance_map_pong), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_importance_map), 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ssil.counter_uniform_set, 2);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.quarter_screen_size.x, p_settings.quarter_screen_size.y, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ RD::get_singleton()->draw_command_end_label(); // Importance Map
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER_ADAPTIVE]);
+ } else {
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER]);
+ }
+
+ gather_ssil(compute_list, p_ssil_slices, p_edges_slices, p_settings, false, r_gather_uniform_set, r_importance_map_uniform_set, r_projection_uniform_set);
+ RD::get_singleton()->draw_command_end_label(); //Gather
+ }
+
+ {
+ RD::get_singleton()->draw_command_begin_label("Edge Aware Blur");
+ ssil.blur_push_constant.edge_sharpness = 1.0 - p_settings.sharpness;
+ ssil.blur_push_constant.half_screen_pixel_size[0] = 1.0 / p_settings.half_screen_size.x;
+ ssil.blur_push_constant.half_screen_pixel_size[1] = 1.0 / p_settings.half_screen_size.y;
+
+ int blur_passes = p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW ? p_settings.blur_passes : 1;
+
+ for (int pass = 0; pass < blur_passes; pass++) {
+ int blur_pipeline = SSIL_BLUR_PASS;
+ if (p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW) {
+ blur_pipeline = SSIL_BLUR_PASS_SMART;
+ if (pass < blur_passes - 2) {
+ blur_pipeline = SSIL_BLUR_PASS_WIDE;
+ }
+ }
+
+ for (int i = 0; i < 4; i++) {
+ if ((p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
+ continue;
+ }
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[blur_pipeline]);
+ if (pass % 2 == 0) {
+ if (p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ssil_slices[i]), 0);
+ } else {
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_and_sampler(p_ssil_slices[i], ss_effects.mirror_sampler), 0);
+ }
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ssil_pong_slices[i]), 1);
+ } else {
+ if (p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ssil_pong_slices[i]), 0);
+ } else {
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_and_sampler(p_ssil_pong_slices[i], ss_effects.mirror_sampler), 0);
+ }
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ssil_slices[i]), 1);
+ }
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_edges_slices[i]), 2);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.blur_push_constant, sizeof(SSILBlurPushConstant));
+
+ int x_groups = (p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1));
+ int y_groups = (p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, x_groups, y_groups, 1);
+ if (p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW) {
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ }
+ }
+ }
+
+ RD::get_singleton()->draw_command_end_label(); // Blur
+ }
+
+ {
+ RD::get_singleton()->draw_command_begin_label("Interleave Buffers");
+ ssil.interleave_push_constant.inv_sharpness = 1.0 - p_settings.sharpness;
+ ssil.interleave_push_constant.pixel_size[0] = 1.0 / p_settings.full_screen_size.x;
+ ssil.interleave_push_constant.pixel_size[1] = 1.0 / p_settings.full_screen_size.y;
+ ssil.interleave_push_constant.size_modifier = uint32_t(p_settings.half_size ? 4 : 2);
+
+ int interleave_pipeline = SSIL_INTERLEAVE_HALF;
+ if (p_settings.quality == RS::ENV_SSIL_QUALITY_LOW) {
+ interleave_pipeline = SSIL_INTERLEAVE;
+ } else if (p_settings.quality >= RS::ENV_SSIL_QUALITY_MEDIUM) {
+ interleave_pipeline = SSIL_INTERLEAVE_SMART;
+ }
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[interleave_pipeline]);
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_destination), 0);
+
+ if (p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW && p_settings.blur_passes % 2 == 0) {
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ssil), 1);
+ } else {
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ssil_pong), 1);
+ }
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_edges), 2);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.interleave_push_constant, sizeof(SSILInterleavePushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.full_screen_size.x, p_settings.full_screen_size.y, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ RD::get_singleton()->draw_command_end_label(); // Interleave
+ }
+
+ RD::get_singleton()->draw_command_end_label(); // SSIL
+
+ RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER);
+
+ int zero[1] = { 0 };
+ RD::get_singleton()->buffer_update(ssil.importance_map_load_counter, 0, sizeof(uint32_t), &zero, 0); //no barrier
+}
+
void EffectsRD::roughness_limit(RID p_source_normal, RID p_roughness, const Size2i &p_size, float p_curve) {
roughness_limiter.push_constant.screen_size[0] = p_size.x;
roughness_limiter.push_constant.screen_size[1] = p_size.y;
@@ -1888,6 +2254,27 @@ void EffectsRD::sort_buffer(RID p_uniform_set, int p_size) {
}
EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
+ {
+ Vector<String> FSR_upscale_modes;
+
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+ // MoltenVK does not support some of the operations used by the normal mode of FSR. Fallback works just fine though.
+ FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n");
+#else
+ // Everyone else can use normal mode when available.
+ if (RD::get_singleton()->get_device_capabilities()->supports_fsr_half_float) {
+ FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_NORMAL\n");
+ } else {
+ FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n");
+ }
+#endif
+
+ FSR_upscale.shader.initialize(FSR_upscale_modes);
+
+ FSR_upscale.shader_version = FSR_upscale.shader.version_create();
+ FSR_upscale.pipeline = RD::get_singleton()->compute_pipeline_create(FSR_upscale.shader.version_get_shader(FSR_upscale.shader_version, 0));
+ }
+
prefer_raster_effects = p_prefer_raster_effects;
if (prefer_raster_effects) {
@@ -2115,63 +2502,36 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
}
if (!prefer_raster_effects) {
- // Initialize ssao
-
- RD::SamplerState sampler;
- sampler.mag_filter = RD::SAMPLER_FILTER_NEAREST;
- sampler.min_filter = RD::SAMPLER_FILTER_NEAREST;
- sampler.mip_filter = RD::SAMPLER_FILTER_NEAREST;
- sampler.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
- sampler.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
- sampler.repeat_w = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
- sampler.max_lod = 4;
-
- ssao.mirror_sampler = RD::get_singleton()->sampler_create(sampler);
-
- uint32_t pipeline = 0;
- {
- Vector<String> ssao_modes;
- ssao_modes.push_back("\n");
- ssao_modes.push_back("\n#define USE_HALF_SIZE\n");
- ssao_modes.push_back("\n#define GENERATE_MIPS\n");
- ssao_modes.push_back("\n#define GENERATE_MIPS\n#define USE_HALF_SIZE");
- ssao_modes.push_back("\n#define USE_HALF_BUFFERS\n");
- ssao_modes.push_back("\n#define USE_HALF_BUFFERS\n#define USE_HALF_SIZE");
-
- ssao.downsample_shader.initialize(ssao_modes);
-
- ssao.downsample_shader_version = ssao.downsample_shader.version_create();
-
- for (int i = 0; i <= SSAO_DOWNSAMPLE_HALF_RES_HALF; i++) {
- ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.downsample_shader.version_get_shader(ssao.downsample_shader_version, i));
- pipeline++;
- }
- }
{
- Vector<String> ssao_modes;
-
- ssao_modes.push_back("\n");
- ssao_modes.push_back("\n#define SSAO_BASE\n");
- ssao_modes.push_back("\n#define ADAPTIVE\n");
-
- ssao.gather_shader.initialize(ssao_modes);
-
- ssao.gather_shader_version = ssao.gather_shader.version_create();
-
- for (int i = SSAO_GATHER; i <= SSAO_GATHER_ADAPTIVE; i++) {
- ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.gather_shader.version_get_shader(ssao.gather_shader_version, i - SSAO_GATHER));
- pipeline++;
+ // Initialize depth buffer for screen space effects
+ Vector<String> downsampler_modes;
+ downsampler_modes.push_back("\n");
+ downsampler_modes.push_back("\n#define USE_HALF_SIZE\n");
+ downsampler_modes.push_back("\n#define GENERATE_MIPS\n");
+ downsampler_modes.push_back("\n#define GENERATE_MIPS\n#define USE_HALF_SIZE\n");
+ downsampler_modes.push_back("\n#define USE_HALF_BUFFERS\n");
+ downsampler_modes.push_back("\n#define USE_HALF_BUFFERS\n#define USE_HALF_SIZE\n");
+ downsampler_modes.push_back("\n#define GENERATE_MIPS\n#define GENERATE_FULL_MIPS");
+
+ ss_effects.downsample_shader.initialize(downsampler_modes);
+
+ ss_effects.downsample_shader_version = ss_effects.downsample_shader.version_create();
+
+ for (int i = 0; i < SS_EFFECTS_MAX; i++) {
+ ss_effects.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, i));
}
- ssao.gather_constants_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SSAOGatherConstants));
- SSAOGatherConstants gather_constants;
+ ss_effects.gather_constants_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SSEffectsGatherConstants));
+ SSEffectsGatherConstants gather_constants;
const int sub_pass_count = 5;
for (int pass = 0; pass < 4; pass++) {
for (int subPass = 0; subPass < sub_pass_count; subPass++) {
int a = pass;
+ int b = subPass;
+
int spmap[5]{ 0, 1, 4, 3, 2 };
- int b = spmap[subPass];
+ b = spmap[subPass];
float ca, sa;
float angle0 = (float(a) + float(b) / float(sub_pass_count)) * Math_PI * 0.5f;
@@ -2188,72 +2548,105 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
}
}
- RD::get_singleton()->buffer_update(ssao.gather_constants_buffer, 0, sizeof(SSAOGatherConstants), &gather_constants);
+ RD::get_singleton()->buffer_update(ss_effects.gather_constants_buffer, 0, sizeof(SSEffectsGatherConstants), &gather_constants);
}
+
{
- Vector<String> ssao_modes;
- ssao_modes.push_back("\n#define GENERATE_MAP\n");
- ssao_modes.push_back("\n#define PROCESS_MAPA\n");
- ssao_modes.push_back("\n#define PROCESS_MAPB\n");
+ // Initialize ssao
- ssao.importance_map_shader.initialize(ssao_modes);
+ RD::SamplerState sampler;
+ sampler.mag_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler.min_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
+ sampler.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
+ sampler.repeat_w = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
+ sampler.max_lod = 4;
- ssao.importance_map_shader_version = ssao.importance_map_shader.version_create();
+ ss_effects.mirror_sampler = RD::get_singleton()->sampler_create(sampler);
- for (int i = SSAO_GENERATE_IMPORTANCE_MAP; i <= SSAO_PROCESS_IMPORTANCE_MAPB; i++) {
- ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, i - SSAO_GENERATE_IMPORTANCE_MAP));
+ uint32_t pipeline = 0;
+ {
+ Vector<String> ssao_modes;
- pipeline++;
- }
- ssao.importance_map_load_counter = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t));
- int zero[1] = { 0 };
- RD::get_singleton()->buffer_update(ssao.importance_map_load_counter, 0, sizeof(uint32_t), &zero);
- RD::get_singleton()->set_resource_name(ssao.importance_map_load_counter, "Importance Map Load Counter");
+ ssao_modes.push_back("\n");
+ ssao_modes.push_back("\n#define SSAO_BASE\n");
+ ssao_modes.push_back("\n#define ADAPTIVE\n");
- Vector<RD::Uniform> uniforms;
+ ssao.gather_shader.initialize(ssao_modes);
+
+ ssao.gather_shader_version = ssao.gather_shader.version_create();
+
+ for (int i = 0; i <= SSAO_GATHER_ADAPTIVE; i++) {
+ ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.gather_shader.version_get_shader(ssao.gather_shader_version, i));
+ pipeline++;
+ }
+ }
{
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 0;
- u.ids.push_back(ssao.importance_map_load_counter);
- uniforms.push_back(u);
+ Vector<String> ssao_modes;
+ ssao_modes.push_back("\n#define GENERATE_MAP\n");
+ ssao_modes.push_back("\n#define PROCESS_MAPA\n");
+ ssao_modes.push_back("\n#define PROCESS_MAPB\n");
+
+ ssao.importance_map_shader.initialize(ssao_modes);
+
+ ssao.importance_map_shader_version = ssao.importance_map_shader.version_create();
+
+ for (int i = SSAO_GENERATE_IMPORTANCE_MAP; i <= SSAO_PROCESS_IMPORTANCE_MAPB; i++) {
+ ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, i - SSAO_GENERATE_IMPORTANCE_MAP));
+
+ pipeline++;
+ }
+ ssao.importance_map_load_counter = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t));
+ int zero[1] = { 0 };
+ RD::get_singleton()->buffer_update(ssao.importance_map_load_counter, 0, sizeof(uint32_t), &zero);
+ RD::get_singleton()->set_resource_name(ssao.importance_map_load_counter, "Importance Map Load Counter");
+
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 0;
+ u.ids.push_back(ssao.importance_map_load_counter);
+ uniforms.push_back(u);
+ }
+ ssao.counter_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, 2), 2);
+ RD::get_singleton()->set_resource_name(ssao.counter_uniform_set, "Load Counter Uniform Set");
}
- ssao.counter_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, 2), 2);
- RD::get_singleton()->set_resource_name(ssao.counter_uniform_set, "Load Counter Uniform Set");
- }
- {
- Vector<String> ssao_modes;
- ssao_modes.push_back("\n#define MODE_NON_SMART\n");
- ssao_modes.push_back("\n#define MODE_SMART\n");
- ssao_modes.push_back("\n#define MODE_WIDE\n");
+ {
+ Vector<String> ssao_modes;
+ ssao_modes.push_back("\n#define MODE_NON_SMART\n");
+ ssao_modes.push_back("\n#define MODE_SMART\n");
+ ssao_modes.push_back("\n#define MODE_WIDE\n");
- ssao.blur_shader.initialize(ssao_modes);
+ ssao.blur_shader.initialize(ssao_modes);
- ssao.blur_shader_version = ssao.blur_shader.version_create();
+ ssao.blur_shader_version = ssao.blur_shader.version_create();
- for (int i = SSAO_BLUR_PASS; i <= SSAO_BLUR_PASS_WIDE; i++) {
- ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.blur_shader.version_get_shader(ssao.blur_shader_version, i - SSAO_BLUR_PASS));
+ for (int i = SSAO_BLUR_PASS; i <= SSAO_BLUR_PASS_WIDE; i++) {
+ ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.blur_shader.version_get_shader(ssao.blur_shader_version, i - SSAO_BLUR_PASS));
- pipeline++;
+ pipeline++;
+ }
}
- }
- {
- Vector<String> ssao_modes;
- ssao_modes.push_back("\n#define MODE_NON_SMART\n");
- ssao_modes.push_back("\n#define MODE_SMART\n");
- ssao_modes.push_back("\n#define MODE_HALF\n");
-
- ssao.interleave_shader.initialize(ssao_modes);
-
- ssao.interleave_shader_version = ssao.interleave_shader.version_create();
- for (int i = SSAO_INTERLEAVE; i <= SSAO_INTERLEAVE_HALF; i++) {
- ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.interleave_shader.version_get_shader(ssao.interleave_shader_version, i - SSAO_INTERLEAVE));
- RD::get_singleton()->set_resource_name(ssao.pipelines[pipeline], "Interleave Pipeline " + itos(i));
- pipeline++;
+ {
+ Vector<String> ssao_modes;
+ ssao_modes.push_back("\n#define MODE_NON_SMART\n");
+ ssao_modes.push_back("\n#define MODE_SMART\n");
+ ssao_modes.push_back("\n#define MODE_HALF\n");
+
+ ssao.interleave_shader.initialize(ssao_modes);
+
+ ssao.interleave_shader_version = ssao.interleave_shader.version_create();
+ for (int i = SSAO_INTERLEAVE; i <= SSAO_INTERLEAVE_HALF; i++) {
+ ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.interleave_shader.version_get_shader(ssao.interleave_shader_version, i - SSAO_INTERLEAVE));
+ RD::get_singleton()->set_resource_name(ssao.pipelines[pipeline], "Interleave Pipeline " + itos(i));
+ pipeline++;
+ }
}
- }
- ERR_FAIL_COND(pipeline != SSAO_MAX);
+ ERR_FAIL_COND(pipeline != SSAO_MAX);
+ }
}
if (!prefer_raster_effects) {
@@ -2446,6 +2839,79 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
}
{
+ Vector<String> ssil_modes;
+ ssil_modes.push_back("\n");
+ ssil_modes.push_back("\n#define SSIL_BASE\n");
+ ssil_modes.push_back("\n#define ADAPTIVE\n");
+
+ ssil.gather_shader.initialize(ssil_modes);
+
+ ssil.gather_shader_version = ssil.gather_shader.version_create();
+
+ for (int i = SSIL_GATHER; i <= SSIL_GATHER_ADAPTIVE; i++) {
+ ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.gather_shader.version_get_shader(ssil.gather_shader_version, i));
+ }
+ ssil.projection_uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SSILProjectionUniforms));
+ }
+
+ {
+ Vector<String> ssil_modes;
+ ssil_modes.push_back("\n#define GENERATE_MAP\n");
+ ssil_modes.push_back("\n#define PROCESS_MAPA\n");
+ ssil_modes.push_back("\n#define PROCESS_MAPB\n");
+
+ ssil.importance_map_shader.initialize(ssil_modes);
+
+ ssil.importance_map_shader_version = ssil.importance_map_shader.version_create();
+
+ for (int i = SSIL_GENERATE_IMPORTANCE_MAP; i <= SSIL_PROCESS_IMPORTANCE_MAPB; i++) {
+ ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, i - SSIL_GENERATE_IMPORTANCE_MAP));
+ }
+ ssil.importance_map_load_counter = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t));
+ int zero[1] = { 0 };
+ RD::get_singleton()->buffer_update(ssil.importance_map_load_counter, 0, sizeof(uint32_t), &zero);
+ RD::get_singleton()->set_resource_name(ssil.importance_map_load_counter, "Importance Map Load Counter");
+
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 0;
+ u.ids.push_back(ssil.importance_map_load_counter);
+ uniforms.push_back(u);
+ }
+ ssil.counter_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, 2), 2);
+ RD::get_singleton()->set_resource_name(ssil.counter_uniform_set, "Load Counter Uniform Set");
+ }
+ {
+ Vector<String> ssil_modes;
+ ssil_modes.push_back("\n#define MODE_NON_SMART\n");
+ ssil_modes.push_back("\n#define MODE_SMART\n");
+ ssil_modes.push_back("\n#define MODE_WIDE\n");
+
+ ssil.blur_shader.initialize(ssil_modes);
+
+ ssil.blur_shader_version = ssil.blur_shader.version_create();
+ for (int i = SSIL_BLUR_PASS; i <= SSIL_BLUR_PASS_WIDE; i++) {
+ ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.blur_shader.version_get_shader(ssil.blur_shader_version, i - SSIL_BLUR_PASS));
+ }
+ }
+
+ {
+ Vector<String> ssil_modes;
+ ssil_modes.push_back("\n#define MODE_NON_SMART\n");
+ ssil_modes.push_back("\n#define MODE_SMART\n");
+ ssil_modes.push_back("\n#define MODE_HALF\n");
+
+ ssil.interleave_shader.initialize(ssil_modes);
+
+ ssil.interleave_shader_version = ssil.interleave_shader.version_create();
+ for (int i = SSIL_INTERLEAVE; i <= SSIL_INTERLEAVE_HALF; i++) {
+ ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.interleave_shader.version_get_shader(ssil.interleave_shader_version, i - SSIL_INTERLEAVE));
+ }
+ }
+
+ {
Vector<String> resolve_modes;
resolve_modes.push_back("\n#define MODE_RESOLVE_GI\n");
resolve_modes.push_back("\n#define MODE_RESOLVE_GI\n#define VOXEL_GI_RESOLVE\n");
@@ -2523,6 +2989,7 @@ EffectsRD::~EffectsRD() {
RD::get_singleton()->free(index_buffer); //array gets freed as dependency
RD::get_singleton()->free(filter.coefficient_buffer);
+ FSR_upscale.shader.version_free(FSR_upscale.shader_version);
if (prefer_raster_effects) {
blur_raster.shader.version_free(blur_raster.shader_version);
bokeh.raster_shader.version_free(blur_raster.shader_version);
@@ -2541,20 +3008,26 @@ EffectsRD::~EffectsRD() {
copy.shader.version_free(copy.shader_version);
resolve.shader.version_free(resolve.shader_version);
specular_merge.shader.version_free(specular_merge.shader_version);
+ ss_effects.downsample_shader.version_free(ss_effects.downsample_shader_version);
ssao.blur_shader.version_free(ssao.blur_shader_version);
ssao.gather_shader.version_free(ssao.gather_shader_version);
- ssao.downsample_shader.version_free(ssao.downsample_shader_version);
ssao.interleave_shader.version_free(ssao.interleave_shader_version);
ssao.importance_map_shader.version_free(ssao.importance_map_shader_version);
+ ssil.blur_shader.version_free(ssil.blur_shader_version);
+ ssil.gather_shader.version_free(ssil.gather_shader_version);
+ ssil.interleave_shader.version_free(ssil.interleave_shader_version);
+ ssil.importance_map_shader.version_free(ssil.importance_map_shader_version);
roughness_limiter.shader.version_free(roughness_limiter.shader_version);
ssr.shader.version_free(ssr.shader_version);
ssr_filter.shader.version_free(ssr_filter.shader_version);
ssr_scale.shader.version_free(ssr_scale.shader_version);
sss.shader.version_free(sss.shader_version);
- RD::get_singleton()->free(ssao.mirror_sampler);
- RD::get_singleton()->free(ssao.gather_constants_buffer);
+ RD::get_singleton()->free(ss_effects.mirror_sampler);
+ RD::get_singleton()->free(ss_effects.gather_constants_buffer);
RD::get_singleton()->free(ssao.importance_map_load_counter);
+ RD::get_singleton()->free(ssil.importance_map_load_counter);
+ RD::get_singleton()->free(ssil.projection_uniform_buffer);
}
copy_to_fb.shader.version_free(copy_to_fb.shader_version);
cube_to_dp.shader.version_free(cube_to_dp.shader_version);
diff --git a/servers/rendering/renderer_rd/effects_rd.h b/servers/rendering/renderer_rd/effects_rd.h
index 0db0919dbc..a3fb4db3df 100644
--- a/servers/rendering/renderer_rd/effects_rd.h
+++ b/servers/rendering/renderer_rd/effects_rd.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -45,6 +45,7 @@
#include "servers/rendering/renderer_rd/shaders/cubemap_filter_raster.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/cubemap_roughness.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/cubemap_roughness_raster.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/fsr_upscale.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/luminance_reduce.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/luminance_reduce_raster.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/resolve.glsl.gen.h"
@@ -54,11 +55,15 @@
#include "servers/rendering/renderer_rd/shaders/screen_space_reflection_scale.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/sort.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/specular_merge.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/ss_effects_downsample.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/ssao.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/ssao_blur.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/ssao_downsample.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/ssao_importance_map.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/ssao_interleave.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/ssil.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/ssil_blur.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/ssil_interleave.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/subsurface_scattering.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/tonemap.glsl.gen.h"
#include "servers/rendering/renderer_scene_render.h"
@@ -69,6 +74,28 @@ class EffectsRD {
private:
bool prefer_raster_effects;
+ enum FSRUpscalePass {
+ FSR_UPSCALE_PASS_EASU = 0,
+ FSR_UPSCALE_PASS_RCAS = 1
+ };
+
+ struct FSRUpscalePushConstant {
+ float resolution_width;
+ float resolution_height;
+ float upscaled_width;
+ float upscaled_height;
+ float sharpness;
+ int pass;
+ int _unused0, _unused1;
+ };
+
+ struct FSRUpscale {
+ FSRUpscalePushConstant push_constant;
+ FsrUpscaleShaderRD shader;
+ RID shader_version;
+ RID pipeline;
+ } FSR_upscale;
+
enum BlurRasterMode {
BLUR_MIPMAP,
@@ -376,13 +403,47 @@ private:
PipelineCacheRD raster_pipelines[BOKEH_MAX];
} bokeh;
+ struct SSEffectsDownsamplePushConstant {
+ float pixel_size[2];
+ float z_far;
+ float z_near;
+ uint32_t orthogonal;
+ float radius_sq;
+ uint32_t pad[2];
+ };
+
+ enum SSEffectsMode {
+ SS_EFFECTS_DOWNSAMPLE,
+ SS_EFFECTS_DOWNSAMPLE_HALF_RES,
+ SS_EFFECTS_DOWNSAMPLE_MIPMAP,
+ SS_EFFECTS_DOWNSAMPLE_MIPMAP_HALF_RES,
+ SS_EFFECTS_DOWNSAMPLE_HALF,
+ SS_EFFECTS_DOWNSAMPLE_HALF_RES_HALF,
+ SS_EFFECTS_DOWNSAMPLE_FULL_MIPS,
+ SS_EFFECTS_MAX
+ };
+
+ struct SSEffectsGatherConstants {
+ float rotation_matrices[80]; //5 vec4s * 4
+ };
+
+ struct SSEffects {
+ SSEffectsDownsamplePushConstant downsample_push_constant;
+ SsEffectsDownsampleShaderRD downsample_shader;
+ RID downsample_shader_version;
+ RID downsample_uniform_set;
+ bool used_half_size_last_frame = false;
+ bool used_mips_last_frame = false;
+ bool used_full_mips_last_frame = false;
+
+ RID gather_constants_buffer;
+
+ RID mirror_sampler;
+
+ RID pipelines[SS_EFFECTS_MAX];
+ } ss_effects;
+
enum SSAOMode {
- SSAO_DOWNSAMPLE,
- SSAO_DOWNSAMPLE_HALF_RES,
- SSAO_DOWNSAMPLE_MIPMAP,
- SSAO_DOWNSAMPLE_MIPMAP_HALF_RES,
- SSAO_DOWNSAMPLE_HALF,
- SSAO_DOWNSAMPLE_HALF_RES_HALF,
SSAO_GATHER,
SSAO_GATHER_BASE,
SSAO_GATHER_ADAPTIVE,
@@ -398,15 +459,6 @@ private:
SSAO_MAX
};
- struct SSAODownsamplePushConstant {
- float pixel_size[2];
- float z_far;
- float z_near;
- uint32_t orthogonal;
- float radius_sq;
- uint32_t pad[2];
- };
-
struct SSAOGatherPushConstant {
int32_t screen_size[2];
int pass;
@@ -432,7 +484,7 @@ private:
float horizon_angle_threshold;
float inv_radius_near_limit;
- bool is_orthogonal;
+ uint32_t is_orthogonal;
float neg_inv_radius;
float load_counter_avg_div;
float adaptive_sample_limit;
@@ -441,10 +493,6 @@ private:
float pass_uv_offset[2];
};
- struct SSAOGatherConstants {
- float rotation_matrices[80]; //5 vec4s * 4
- };
-
struct SSAOImportanceMapPushConstant {
float half_screen_pixel_size[2];
float intensity;
@@ -464,15 +512,9 @@ private:
};
struct SSAO {
- SSAODownsamplePushConstant downsample_push_constant;
- SsaoDownsampleShaderRD downsample_shader;
- RID downsample_shader_version;
-
SSAOGatherPushConstant gather_push_constant;
SsaoShaderRD gather_shader;
RID gather_shader_version;
- RID gather_constants_buffer;
- bool gather_initialized = false;
SSAOImportanceMapPushConstant importance_map_push_constant;
SsaoImportanceMapShaderRD importance_map_shader;
@@ -488,10 +530,104 @@ private:
SsaoInterleaveShaderRD interleave_shader;
RID interleave_shader_version;
- RID mirror_sampler;
RID pipelines[SSAO_MAX];
} ssao;
+ enum SSILMode {
+ SSIL_GATHER,
+ SSIL_GATHER_BASE,
+ SSIL_GATHER_ADAPTIVE,
+ SSIL_GENERATE_IMPORTANCE_MAP,
+ SSIL_PROCESS_IMPORTANCE_MAPA,
+ SSIL_PROCESS_IMPORTANCE_MAPB,
+ SSIL_BLUR_PASS,
+ SSIL_BLUR_PASS_SMART,
+ SSIL_BLUR_PASS_WIDE,
+ SSIL_INTERLEAVE,
+ SSIL_INTERLEAVE_SMART,
+ SSIL_INTERLEAVE_HALF,
+ SSIL_MAX
+ };
+
+ struct SSILGatherPushConstant {
+ int32_t screen_size[2];
+ int pass;
+ int quality;
+
+ float half_screen_pixel_size[2];
+ float half_screen_pixel_size_x025[2];
+
+ float NDC_to_view_mul[2];
+ float NDC_to_view_add[2];
+
+ float pad2[2];
+ float z_near;
+ float z_far;
+
+ float radius;
+ float intensity;
+ int size_multiplier;
+ int pad;
+
+ float fade_out_mul;
+ float fade_out_add;
+ float normal_rejection_amount;
+ float inv_radius_near_limit;
+
+ uint32_t is_orthogonal;
+ float neg_inv_radius;
+ float load_counter_avg_div;
+ float adaptive_sample_limit;
+
+ int32_t pass_coord_offset[2];
+ float pass_uv_offset[2];
+ };
+
+ struct SSILImportanceMapPushConstant {
+ float half_screen_pixel_size[2];
+ float intensity;
+ float pad;
+ };
+
+ struct SSILBlurPushConstant {
+ float edge_sharpness;
+ float pad;
+ float half_screen_pixel_size[2];
+ };
+
+ struct SSILInterleavePushConstant {
+ float inv_sharpness;
+ uint32_t size_modifier;
+ float pixel_size[2];
+ };
+
+ struct SSILProjectionUniforms {
+ float inv_last_frame_projection_matrix[16];
+ };
+
+ struct SSIL {
+ SSILGatherPushConstant gather_push_constant;
+ SsilShaderRD gather_shader;
+ RID gather_shader_version;
+ RID projection_uniform_buffer;
+
+ SSILImportanceMapPushConstant importance_map_push_constant;
+ SsilImportanceMapShaderRD importance_map_shader;
+ RID importance_map_shader_version;
+ RID importance_map_load_counter;
+ RID counter_uniform_set;
+
+ SSILBlurPushConstant blur_push_constant;
+ SsilBlurShaderRD blur_shader;
+ RID blur_shader_version;
+
+ SSILInterleavePushConstant interleave_push_constant;
+ SsilInterleaveShaderRD interleave_shader;
+ RID interleave_shader_version;
+
+ RID pipelines[SSIL_MAX];
+ } ssil;
+
struct RoughnessLimiterPushConstant {
int32_t screen_size[2];
float curve;
@@ -754,6 +890,7 @@ private:
public:
bool get_prefer_raster_effects();
+ void fsr_upscale(RID p_source_rd_texture, RID p_secondary_texture, RID p_destination_texture, const Size2i &p_internal_size, const Size2i &p_size, float p_fsr_upscale_sharpness);
void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_alpha_to_zero = false, bool p_srgb = false, RID p_secondary = RID());
void copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_all_source = false, bool p_8_bit_dst = false, bool p_alpha_to_one = false);
void copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panorama, const Size2i &p_panorama_size, float p_lod, bool p_is_array);
@@ -762,8 +899,8 @@ public:
void copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_uv_rect, RD::DrawListID p_draw_list, bool p_flip_y = false, bool p_panorama = false);
void gaussian_blur(RID p_source_rd_texture, RID p_texture, RID p_back_texture, const Rect2i &p_region, bool p_8bit_dst = false);
void set_color(RID p_dest_texture, const Color &p_color, const Rect2i &p_region, bool p_8bit_dst = false);
- void gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_treshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
- void gaussian_glow_raster(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_treshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
+ void gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
+ void gaussian_glow_raster(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
void cubemap_roughness(RID p_source_rd_texture, RID p_dest_texture, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size);
void cubemap_roughness_raster(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size);
@@ -855,11 +992,34 @@ public:
Size2i quarter_screen_size = Size2i();
};
+ struct SSILSettings {
+ float radius = 1.0;
+ float intensity = 2.0;
+ float sharpness = 0.98;
+ float normal_rejection = 1.0;
+
+ RS::EnvironmentSSILQuality quality = RS::ENV_SSIL_QUALITY_MEDIUM;
+ bool half_size = true;
+ float adaptive_target = 0.5;
+ int blur_passes = 4;
+ float fadeout_from = 50.0;
+ float fadeout_to = 300.0;
+
+ Size2i full_screen_size = Size2i();
+ Size2i half_screen_size = Size2i();
+ Size2i quarter_screen_size = Size2i();
+ };
+
void tonemapper(RID p_source_color, RID p_dst_framebuffer, const TonemapSettings &p_settings);
void tonemapper(RD::DrawListID p_subpass_draw_list, RID p_source_color, RD::FramebufferFormatID p_dst_format_id, const TonemapSettings &p_settings);
+ void downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_mipmaps, RS::EnvironmentSSAOQuality p_ssao_quality, RS::EnvironmentSSILQuality p_ssil_quality, bool p_invalidate_uniform_set, bool p_ssao_half_size, bool p_ssil_half_size, Size2i p_full_screen_size, const CameraMatrix &p_projection);
+
void gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set);
- void generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_depth_mipmaps_texture, const Vector<RID> &depth_mipmaps, RID p_ao, const Vector<RID> p_ao_slices, RID p_ao_pong, const Vector<RID> p_ao_pong_slices, RID p_upscale_buffer, RID p_importance_map, RID p_importance_map_pong, const CameraMatrix &p_projection, const SSAOSettings &p_settings, bool p_invalidate_uniform_sets, RID &r_downsample_uniform_set, RID &r_gather_uniform_set, RID &r_importance_map_uniform_set);
+ void generate_ssao(RID p_normal_buffer, RID p_depth_mipmaps_texture, RID p_ao, const Vector<RID> p_ao_slices, RID p_ao_pong, const Vector<RID> p_ao_pong_slices, RID p_upscale_buffer, RID p_importance_map, RID p_importance_map_pong, const CameraMatrix &p_projection, const SSAOSettings &p_settings, bool p_invalidate_uniform_sets, RID &r_gather_uniform_set, RID &r_importance_map_uniform_set);
+
+ void gather_ssil(RD::ComputeListID p_compute_list, const Vector<RID> p_ssil_slices, const Vector<RID> p_edges_slices, const SSILSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set, RID p_projection_uniform_set);
+ void screen_space_indirect_lighting(RID p_diffuse, RID p_destination, RID p_normal_buffer, RID p_depth_mipmaps_texture, RID p_ao, const Vector<RID> p_ao_slices, RID p_ao_pong, const Vector<RID> p_ao_pong_slices, RID p_importance_map, RID p_importance_map_pong, RID p_edges, const Vector<RID> p_edges_slices, const CameraMatrix &p_projection, const CameraMatrix &p_last_projection, const SSILSettings &p_settings, bool p_invalidate_uniform_sets, RID &r_gather_uniform_set, RID &r_importance_map_uniform_set, RID &r_projection_uniform_set);
void roughness_limit(RID p_source_normal, RID p_roughness, const Size2i &p_size, float p_curve);
void cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, const Size2i &p_size);
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
index 85ebf076cc..36604073cc 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -328,10 +328,20 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
push_constant.uv_offset = 0;
}
+ bool should_request_redraw = false;
+
for (uint32_t i = p_from_element; i < p_to_element; i++) {
const GeometryInstanceSurfaceDataCache *surf = p_params->elements[i];
const RenderElementInfo &element_info = p_params->element_info[i];
+ if ((p_pass_mode == PASS_MODE_COLOR || p_pass_mode == PASS_MODE_COLOR_SPECULAR) && !(surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE)) {
+ continue; // Objects with "Depth-prepass" transparency are included in both render lists, but should only be rendered in the transparent pass
+ }
+
+ if (surf->owner->instance_count == 0) {
+ continue;
+ }
+
push_constant.base_index = i + p_params->element_offset;
RID material_uniform_set;
@@ -365,6 +375,11 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
continue;
}
+ //request a redraw if one of the shaders uses TIME
+ if (shader->uses_time) {
+ should_request_redraw = true;
+ }
+
//find cull variant
SceneShaderForwardClustered::ShaderData::CullVariant cull_variant;
@@ -381,7 +396,7 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
RS::PrimitiveType primitive = surf->primitive;
RID xforms_uniform_set = surf->owner->transforms_uniform_set;
- SceneShaderForwardClustered::ShaderVersion shader_version = SceneShaderForwardClustered::SHADER_VERSION_MAX; // Assigned to silence wrong -Wmaybe-initialized.
+ SceneShaderForwardClustered::PipelineVersion pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_MAX; // Assigned to silence wrong -Wmaybe-initialized.
uint32_t pipeline_specialization = 0;
@@ -399,48 +414,54 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
}
switch (p_pass_mode) {
- case PASS_MODE_COLOR:
+ case PASS_MODE_COLOR: {
+ if (element_info.uses_lightmap) {
+ pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS;
+ } else {
+ pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_OPAQUE_PASS;
+ }
+ } break;
case PASS_MODE_COLOR_TRANSPARENT: {
if (element_info.uses_lightmap) {
- shader_version = SceneShaderForwardClustered::SHADER_VERSION_LIGHTMAP_COLOR_PASS;
+ pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS;
} else {
if (element_info.uses_forward_gi) {
pipeline_specialization |= SceneShaderForwardClustered::SHADER_SPECIALIZATION_FORWARD_GI;
}
- shader_version = SceneShaderForwardClustered::SHADER_VERSION_COLOR_PASS;
+ pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_TRANSPARENT_PASS;
}
} break;
case PASS_MODE_COLOR_SPECULAR: {
if (element_info.uses_lightmap) {
- shader_version = SceneShaderForwardClustered::SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR;
+ pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS_WITH_SEPARATE_SPECULAR;
} else {
- shader_version = SceneShaderForwardClustered::SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR;
+ pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_OPAQUE_PASS_WITH_SEPARATE_SPECULAR;
}
} break;
case PASS_MODE_SHADOW:
case PASS_MODE_DEPTH: {
- shader_version = SceneShaderForwardClustered::SHADER_VERSION_DEPTH_PASS;
+ pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS;
} break;
case PASS_MODE_SHADOW_DP: {
- shader_version = SceneShaderForwardClustered::SHADER_VERSION_DEPTH_PASS_DP;
+ pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_DP;
} break;
case PASS_MODE_DEPTH_NORMAL_ROUGHNESS: {
- shader_version = SceneShaderForwardClustered::SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS;
+ pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS;
} break;
case PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI: {
- shader_version = SceneShaderForwardClustered::SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI;
+ pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI;
} break;
case PASS_MODE_DEPTH_MATERIAL: {
- shader_version = SceneShaderForwardClustered::SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL;
+ pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_WITH_MATERIAL;
} break;
case PASS_MODE_SDF: {
- shader_version = SceneShaderForwardClustered::SHADER_VERSION_DEPTH_PASS_WITH_SDF;
+ pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_WITH_SDF;
} break;
}
PipelineCacheRD *pipeline = nullptr;
- pipeline = &shader->pipelines[cull_variant][primitive][shader_version];
+ pipeline = &shader->pipelines[cull_variant][primitive][pipeline_version];
RD::VertexFormatID vertex_format = -1;
RID vertex_array_rd;
@@ -500,6 +521,11 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid(), instance_count);
i += element_info.repeat - 1; //skip equal elements
}
+
+ // Make the actual redraw request
+ if (should_request_redraw) {
+ RenderingServerDefault::redraw_request();
+ }
}
void RenderForwardClustered::_render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element) {
@@ -704,7 +730,7 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
scene_state.ubo.ambient_light_color_energy[3] = 1.0;
scene_state.ubo.use_ambient_cubemap = false;
scene_state.ubo.use_reflection_cubemap = false;
- scene_state.ubo.ssao_enabled = false;
+ scene_state.ubo.ss_effects_flags = 0;
} else if (is_environment(p_render_data->environment)) {
RS::EnvironmentBG env_bg = environment_get_background(p_render_data->environment);
@@ -749,9 +775,14 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
scene_state.ubo.use_reflection_cubemap = false;
}
- scene_state.ubo.ssao_enabled = p_opaque_render_buffers && environment_is_ssao_enabled(p_render_data->environment);
scene_state.ubo.ssao_ao_affect = environment_get_ssao_ao_affect(p_render_data->environment);
scene_state.ubo.ssao_light_affect = environment_get_ssao_light_affect(p_render_data->environment);
+ uint32_t ss_flags = 0;
+ if (p_opaque_render_buffers) {
+ ss_flags |= environment_is_ssao_enabled(p_render_data->environment) ? 1 : 0;
+ ss_flags |= environment_is_ssil_enabled(p_render_data->environment) ? 2 : 0;
+ }
+ scene_state.ubo.ss_effects_flags = ss_flags;
scene_state.ubo.fog_enabled = environment_is_fog_enabled(p_render_data->environment);
scene_state.ubo.fog_density = environment_get_fog_density(p_render_data->environment);
@@ -783,7 +814,7 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
scene_state.ubo.use_ambient_cubemap = false;
scene_state.ubo.use_reflection_cubemap = false;
- scene_state.ubo.ssao_enabled = false;
+ scene_state.ubo.ss_effects_flags = 0;
}
scene_state.ubo.roughness_limiter_enabled = p_opaque_render_buffers && screen_space_roughness_limiter_is_active();
@@ -904,7 +935,7 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
}
uint32_t lightmap_captures_used = 0;
- Plane near_plane(p_render_data->cam_transform.origin, -p_render_data->cam_transform.basis.get_axis(Vector3::AXIS_Z));
+ Plane near_plane = Plane(-p_render_data->cam_transform.basis.get_axis(Vector3::AXIS_Z), p_render_data->cam_transform.origin);
near_plane.d += p_render_data->cam_projection.get_z_near();
float z_max = p_render_data->cam_projection.get_z_far() - p_render_data->cam_projection.get_z_near();
@@ -934,10 +965,23 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
}
bool uses_lightmap = false;
bool uses_gi = false;
+ float fade_alpha = 1.0;
+
+ if (inst->fade_near || inst->fade_far) {
+ float fade_dist = inst->transform.origin.distance_to(p_render_data->cam_transform.origin);
+ if (inst->fade_far && fade_dist > inst->fade_far_begin) {
+ fade_alpha = MAX(0.0, 1.0 - (fade_dist - inst->fade_far_begin) / (inst->fade_far_end - inst->fade_far_begin));
+ } else if (inst->fade_near && fade_dist < inst->fade_near_end) {
+ fade_alpha = MAX(0.0, (fade_dist - inst->fade_near_begin) / (inst->fade_near_end - inst->fade_near_begin));
+ }
+ }
- if (p_render_list == RENDER_LIST_OPAQUE) {
- //setup GI
+ fade_alpha *= inst->force_alpha * inst->parent_fade_alpha;
+
+ flags = (flags & ~INSTANCE_DATA_FLAGS_FADE_MASK) | (uint32_t(fade_alpha * 255.0) << INSTANCE_DATA_FLAGS_FADE_SHIFT);
+ if (p_render_list == RENDER_LIST_OPAQUE) {
+ // Setup GI
if (inst->lightmap_instance.is_valid()) {
int32_t lightmap_cull_index = -1;
for (uint32_t j = 0; j < scene_state.lightmaps_used; j++) {
@@ -1018,7 +1062,7 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
// LOD
- if (p_render_data->screen_lod_threshold > 0.0 && storage->mesh_surface_has_lod(surf->surface)) {
+ if (p_render_data->screen_mesh_lod_threshold > 0.0 && storage->mesh_surface_has_lod(surf->surface)) {
//lod
Vector3 lod_support_min = inst->transformed_aabb.get_support(-p_render_data->lod_camera_plane.normal);
Vector3 lod_support_max = inst->transformed_aabb.get_support(p_render_data->lod_camera_plane.normal);
@@ -1038,7 +1082,7 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
}
uint32_t indices;
- surf->sort.lod_index = storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold, &indices);
+ surf->sort.lod_index = storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, &indices);
if (p_render_data->render_info) {
indices = _indices_to_primitives(surf->primitive, indices);
if (p_render_list == RENDER_LIST_OPAQUE) { //opaque
@@ -1068,6 +1112,11 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
#else
bool force_alpha = false;
#endif
+
+ if (fade_alpha < 0.999) {
+ force_alpha = true;
+ }
+
if (!force_alpha && (surf->flags & (GeometryInstanceSurfaceDataCache::FLAG_PASS_DEPTH | GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE))) {
rl->add_element(surf);
}
@@ -1166,6 +1215,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
scene_state.ubo.viewport_size[0] = vp_he.x;
scene_state.ubo.viewport_size[1] = vp_he.y;
scene_state.ubo.directional_light_count = 0;
+ scene_state.ubo.opaque_prepass_threshold = 0.99f;
Size2i screen_size;
RID opaque_framebuffer;
@@ -1180,6 +1230,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
bool using_sdfgi = false;
bool using_voxelgi = false;
bool reverse_cull = false;
+ bool using_ssil = p_render_data->environment.is_valid() && environment_is_ssil_enabled(p_render_data->environment);
if (render_buffer) {
screen_size.x = render_buffer->width;
@@ -1209,7 +1260,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
opaque_specular_framebuffer = render_buffer->color_specular_fb;
}
- } else if (p_render_data->environment.is_valid() && (environment_is_ssao_enabled(p_render_data->environment) || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER)) {
+ } else if (p_render_data->environment.is_valid() && (environment_is_ssao_enabled(p_render_data->environment) || using_ssil || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER)) {
depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS;
}
@@ -1353,7 +1404,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
bool debug_voxelgis = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_ALBEDO || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_LIGHTING || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_EMISSION;
bool debug_sdfgi_probes = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_SDFGI_PROBES;
- bool depth_pre_pass = depth_framebuffer.is_valid();
+ bool depth_pre_pass = bool(GLOBAL_GET("rendering/driver/depth_prepass/enable")) && depth_framebuffer.is_valid();
bool using_ssao = depth_pre_pass && p_render_data->render_buffers.is_valid() && p_render_data->environment.is_valid() && environment_is_ssao_enabled(p_render_data->environment);
bool continue_depth = false;
@@ -1378,7 +1429,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, nullptr, RID());
bool finish_depth = using_ssao || using_sdfgi || using_voxelgi;
- RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, depth_pass_mode, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, depth_pass_mode, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold);
_render_list_with_threads(&render_list_params, depth_framebuffer, needs_pre_resolve ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, needs_pre_resolve ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_CLEAR, finish_depth ? RD::FINAL_ACTION_READ : RD::FINAL_ACTION_CONTINUE, needs_pre_resolve ? Vector<Color>() : depth_pass_clear);
RD::get_singleton()->draw_command_end_label();
@@ -1404,11 +1455,12 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
continue_depth = !finish_depth;
}
- _pre_opaque_render(p_render_data, using_ssao, using_sdfgi || using_voxelgi, render_buffer ? render_buffer->normal_roughness_buffer : RID(), render_buffer ? render_buffer->voxelgi_buffer : RID());
+ _pre_opaque_render(p_render_data, using_ssao, using_ssil, using_sdfgi || using_voxelgi, render_buffer ? render_buffer->normal_roughness_buffer : RID(), render_buffer ? render_buffer->voxelgi_buffer : RID());
RD::get_singleton()->draw_command_begin_label("Render Opaque Pass");
scene_state.ubo.directional_light_count = p_render_data->directional_light_count;
+ scene_state.ubo.opaque_prepass_threshold = 0.0f;
_setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, p_render_data->render_buffers.is_valid());
@@ -1435,7 +1487,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
}
RID framebuffer = using_separate_specular ? opaque_specular_framebuffer : opaque_framebuffer;
- RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, using_separate_specular ? PASS_MODE_COLOR_SPECULAR : PASS_MODE_COLOR, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, using_separate_specular ? PASS_MODE_COLOR_SPECULAR : PASS_MODE_COLOR, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold);
_render_list_with_threads(&render_list_params, framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, depth_pre_pass ? (continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP) : RD::INITIAL_ACTION_CLEAR, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0);
if (will_continue_color && using_separate_specular) {
// close the specular framebuffer, as it's no longer used
@@ -1542,20 +1594,30 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
_setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false);
{
- RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), false, PASS_MODE_COLOR, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), false, PASS_MODE_COLOR_TRANSPARENT, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold);
_render_list_with_threads(&render_list_params, alpha_framebuffer, can_continue_color ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, can_continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ);
}
RD::get_singleton()->draw_command_end_label();
+ RENDER_TIMESTAMP("Resolve");
+
RD::get_singleton()->draw_command_begin_label("Resolve");
if (render_buffer && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) {
RD::get_singleton()->texture_resolve_multisample(render_buffer->color_msaa, render_buffer->color);
+ storage->get_effects()->resolve_depth(render_buffer->depth_msaa, render_buffer->depth, Vector2i(render_buffer->width, render_buffer->height), texture_multisamples[render_buffer->msaa]);
}
RD::get_singleton()->draw_command_end_label();
+ RD::get_singleton()->draw_command_begin_label("Copy framebuffer for SSIL");
+ if (using_ssil) {
+ RENDER_TIMESTAMP("Copy Final Framebuffer");
+ _copy_framebuffer_to_ssil(p_render_data->render_buffers);
+ }
+ RD::get_singleton()->draw_command_end_label();
+
if (p_render_data->render_buffers.is_valid()) {
_debug_draw_cluster(p_render_data->render_buffers);
@@ -1574,7 +1636,7 @@ void RenderForwardClustered::_render_shadow_begin() {
scene_state.instance_data[RENDER_LIST_SECONDARY].clear();
}
-void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end, RendererScene::RenderInfo *p_render_info) {
+void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end, RendererScene::RenderInfo *p_render_info) {
uint32_t shadow_pass_index = scene_state.shadow_passes.size();
SceneState::ShadowPass shadow_pass;
@@ -1592,13 +1654,14 @@ void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const Page
render_data.render_info = p_render_info;
scene_state.ubo.dual_paraboloid_side = p_use_dp_flip ? -1 : 1;
+ scene_state.ubo.opaque_prepass_threshold = 0.1f;
_setup_environment(&render_data, true, Vector2(1, 1), !p_flip_y, Color(), false, p_use_pancake, shadow_pass_index);
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_DISABLE_LOD) {
- render_data.screen_lod_threshold = 0.0;
+ render_data.screen_mesh_lod_threshold = 0.0;
} else {
- render_data.screen_lod_threshold = p_screen_lod_threshold;
+ render_data.screen_mesh_lod_threshold = p_screen_mesh_lod_threshold;
}
PassMode pass_mode = p_use_dp ? PASS_MODE_SHADOW_DP : PASS_MODE_SHADOW;
@@ -1623,7 +1686,7 @@ void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const Page
shadow_pass.rp_uniform_set = RID(); //will be filled later when instance buffer is complete
shadow_pass.camera_plane = p_camera_plane;
- shadow_pass.screen_lod_threshold = render_data.screen_lod_threshold;
+ shadow_pass.screen_mesh_lod_threshold = render_data.screen_mesh_lod_threshold;
shadow_pass.lod_distance_multiplier = render_data.lod_distance_multiplier;
shadow_pass.framebuffer = p_framebuffer;
@@ -1652,7 +1715,7 @@ void RenderForwardClustered::_render_shadow_end(uint32_t p_barrier) {
for (uint32_t i = 0; i < scene_state.shadow_passes.size(); i++) {
SceneState::ShadowPass &shadow_pass = scene_state.shadow_passes[i];
- RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, true, false, shadow_pass.rp_uniform_set, false, Vector2(), shadow_pass.camera_plane, shadow_pass.lod_distance_multiplier, shadow_pass.screen_lod_threshold, shadow_pass.element_from, RD::BARRIER_MASK_NO_BARRIER);
+ RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, true, false, shadow_pass.rp_uniform_set, false, Vector2(), shadow_pass.camera_plane, shadow_pass.lod_distance_multiplier, shadow_pass.screen_mesh_lod_threshold, shadow_pass.element_from, RD::BARRIER_MASK_NO_BARRIER);
_render_list_with_threads(&render_list_parameters, shadow_pass.framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, shadow_pass.initial_depth_action, shadow_pass.final_depth_action, Vector<Color>(), 1.0, 0, shadow_pass.rect);
}
@@ -1678,6 +1741,7 @@ void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, con
_update_render_base_uniform_set();
scene_state.ubo.dual_paraboloid_side = 0;
+ scene_state.ubo.opaque_prepass_threshold = 0.0;
_setup_environment(&render_data, true, Vector2(1, 1), true, Color(), false, false);
@@ -1715,6 +1779,7 @@ void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform
scene_state.ubo.dual_paraboloid_side = 0;
scene_state.ubo.material_uv2_mode = false;
+ scene_state.ubo.opaque_prepass_threshold = 0.0f;
_setup_environment(&render_data, true, Vector2(1, 1), false, Color());
@@ -1730,12 +1795,14 @@ void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform
{
RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, true, false, rp_uniform_set);
//regular forward for now
- Vector<Color> clear;
- clear.push_back(Color(0, 0, 0, 0));
- clear.push_back(Color(0, 0, 0, 0));
- clear.push_back(Color(0, 0, 0, 0));
- clear.push_back(Color(0, 0, 0, 0));
- clear.push_back(Color(0, 0, 0, 0));
+ Vector<Color> clear = {
+ Color(0, 0, 0, 0),
+ Color(0, 0, 0, 0),
+ Color(0, 0, 0, 0),
+ Color(0, 0, 0, 0),
+ Color(0, 0, 0, 0)
+ };
+
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, clear, 1.0, 0, p_region);
_render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), &render_list_params, 0, render_list_params.element_count);
RD::get_singleton()->draw_list_end();
@@ -1758,6 +1825,7 @@ void RenderForwardClustered::_render_uv2(const PagedArray<GeometryInstance *> &p
scene_state.ubo.dual_paraboloid_side = 0;
scene_state.ubo.material_uv2_mode = true;
+ scene_state.ubo.opaque_prepass_threshold = 0.0;
_setup_environment(&render_data, true, Vector2(1, 1), false, Color());
@@ -1773,12 +1841,13 @@ void RenderForwardClustered::_render_uv2(const PagedArray<GeometryInstance *> &p
{
RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, true, false, rp_uniform_set, true);
//regular forward for now
- Vector<Color> clear;
- clear.push_back(Color(0, 0, 0, 0));
- clear.push_back(Color(0, 0, 0, 0));
- clear.push_back(Color(0, 0, 0, 0));
- clear.push_back(Color(0, 0, 0, 0));
- clear.push_back(Color(0, 0, 0, 0));
+ Vector<Color> clear = {
+ Color(0, 0, 0, 0),
+ Color(0, 0, 0, 0),
+ Color(0, 0, 0, 0),
+ Color(0, 0, 0, 0),
+ Color(0, 0, 0, 0)
+ };
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, clear, 1.0, 0, p_region);
const int uv_offset_count = 9;
@@ -1835,11 +1904,12 @@ void RenderForwardClustered::_render_sdfgi(RID p_render_buffers, const Vector3i
Vector3 half_extents = p_bounds.size * 0.5;
Vector3 center = p_bounds.position + half_extents;
- Vector<RID> sbs;
- sbs.push_back(p_albedo_texture);
- sbs.push_back(p_emission_texture);
- sbs.push_back(p_emission_aniso_texture);
- sbs.push_back(p_geom_facing_texture);
+ Vector<RID> sbs = {
+ p_albedo_texture,
+ p_emission_texture,
+ p_emission_aniso_texture,
+ p_geom_facing_texture
+ };
//print_line("re-render " + p_from + " - " + p_size + " bounds " + p_bounds);
for (int i = 0; i < 3; i++) {
@@ -1904,7 +1974,9 @@ void RenderForwardClustered::_base_uniforms_changed() {
}
void RenderForwardClustered::_update_render_base_uniform_set() {
- if (render_base_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set) || (lightmap_texture_array_version != storage->lightmap_array_get_version())) {
+ if (render_base_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set) || (lightmap_texture_array_version != storage->lightmap_array_get_version()) || base_uniform_set_updated) {
+ base_uniform_set_updated = false;
+
if (render_base_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) {
RD::get_singleton()->free(render_base_uniform_set);
}
@@ -1919,18 +1991,18 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
u.binding = 1;
u.ids.resize(12);
RID *ids_ptr = u.ids.ptrw();
- ids_ptr[0] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[1] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[2] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[3] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[4] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[5] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[6] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[7] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[8] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[9] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[10] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[11] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[0] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[1] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[2] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[3] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[4] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[5] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[6] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[7] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[8] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[9] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[10] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[11] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
uniforms.push_back(u);
}
@@ -1949,19 +2021,19 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
RID sampler;
switch (decals_get_filter()) {
case RS::DECAL_FILTER_NEAREST: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::DECAL_FILTER_NEAREST_MIPMAPS: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::DECAL_FILTER_LINEAR: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::DECAL_FILTER_LINEAR_MIPMAPS: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
}
@@ -1976,19 +2048,19 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
RID sampler;
switch (light_projectors_get_filter()) {
case RS::LIGHT_PROJECTOR_FILTER_NEAREST: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::LIGHT_PROJECTOR_FILTER_LINEAR: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
}
@@ -2320,6 +2392,15 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
u.ids.push_back(vfog);
uniforms.push_back(u);
}
+ {
+ RD::Uniform u;
+ u.binding = 19;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ RID ssil = rb ? render_buffers_get_ssil_texture(p_render_data->render_buffers) : RID();
+ RID texture = ssil.is_valid() ? ssil : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
+ u.ids.push_back(texture);
+ uniforms.push_back(u);
+ }
}
if (p_index >= (int)render_pass_uniform_sets.size()) {
@@ -2597,6 +2678,24 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet
sdcache->sort.uses_softshadow = ginstance->using_softshadows;
}
+void RenderForwardClustered::_geometry_instance_add_surface_with_material_chain(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, SceneShaderForwardClustered::MaterialData *p_material, RID p_mat_src, RID p_mesh) {
+ SceneShaderForwardClustered::MaterialData *material = p_material;
+
+ _geometry_instance_add_surface_with_material(ginstance, p_surface, material, p_mat_src.get_local_index(), storage->material_get_shader_id(p_mat_src), p_mesh);
+
+ while (material->next_pass.is_valid()) {
+ RID next_pass = material->next_pass;
+ material = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(next_pass, RendererStorageRD::SHADER_TYPE_3D);
+ if (!material || !material->shader_data->valid) {
+ break;
+ }
+ if (ginstance->data->dirty_dependencies) {
+ storage->material_update_dependency(next_pass, &ginstance->data->dependency_tracker);
+ }
+ _geometry_instance_add_surface_with_material(ginstance, p_surface, material, next_pass.get_local_index(), storage->material_get_shader_id(next_pass), p_mesh);
+ }
+}
+
void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, RID p_material, RID p_mesh) {
RID m_src;
@@ -2622,18 +2721,19 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw
ERR_FAIL_COND(!material);
- _geometry_instance_add_surface_with_material(ginstance, p_surface, material, m_src.get_local_index(), storage->material_get_shader_id(m_src), p_mesh);
+ _geometry_instance_add_surface_with_material_chain(ginstance, p_surface, material, m_src, p_mesh);
- while (material->next_pass.is_valid()) {
- RID next_pass = material->next_pass;
- material = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(next_pass, RendererStorageRD::SHADER_TYPE_3D);
- if (!material || !material->shader_data->valid) {
- break;
- }
- if (ginstance->data->dirty_dependencies) {
- storage->material_update_dependency(next_pass, &ginstance->data->dependency_tracker);
+ if (ginstance->data->material_overlay.is_valid()) {
+ m_src = ginstance->data->material_overlay;
+
+ material = (SceneShaderForwardClustered::MaterialData *)storage->material_get_data(m_src, RendererStorageRD::SHADER_TYPE_3D);
+ if (material && material->shader_data->valid) {
+ if (ginstance->data->dirty_dependencies) {
+ storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
+ }
+
+ _geometry_instance_add_surface_with_material_chain(ginstance, p_surface, material, m_src, p_mesh);
}
- _geometry_instance_add_surface_with_material(ginstance, p_surface, material, next_pass.get_local_index(), storage->material_get_shader_id(next_pass), p_mesh);
}
}
@@ -2842,6 +2942,13 @@ void RenderForwardClustered::geometry_instance_set_material_override(GeometryIns
_geometry_instance_mark_dirty(ginstance);
ginstance->data->dirty_dependencies = true;
}
+void RenderForwardClustered::geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_overlay) {
+ GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
+ ginstance->data->material_overlay = p_overlay;
+ _geometry_instance_mark_dirty(ginstance);
+ ginstance->data->dirty_dependencies = true;
+}
void RenderForwardClustered::geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) {
GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
ERR_FAIL_COND(!ginstance);
@@ -2878,6 +2985,29 @@ void RenderForwardClustered::geometry_instance_set_lod_bias(GeometryInstance *p_
ERR_FAIL_COND(!ginstance);
ginstance->lod_bias = p_lod_bias;
}
+void RenderForwardClustered::geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) {
+ GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
+ ginstance->fade_near = p_enable_near;
+ ginstance->fade_near_begin = p_near_begin;
+ ginstance->fade_near_end = p_near_end;
+ ginstance->fade_far = p_enable_far;
+ ginstance->fade_far_begin = p_far_begin;
+ ginstance->fade_far_end = p_far_end;
+}
+
+void RenderForwardClustered::geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) {
+ GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
+ ginstance->parent_fade_alpha = p_alpha;
+}
+
+void RenderForwardClustered::geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) {
+ GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
+ ginstance->force_alpha = CLAMP(1.0 - p_transparency, 0, 1);
+}
+
void RenderForwardClustered::geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) {
GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
ERR_FAIL_COND(!ginstance);
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
index ff3d2fc6cb..f858887bd0 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -129,6 +129,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
virtual void _base_uniforms_changed() override;
virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) override;
+ bool base_uniform_set_updated = false;
void _update_render_base_uniform_set();
RID _setup_sdfgi_render_pass_uniform_set(RID p_albedo_texture, RID p_emission_texture, RID p_emission_aniso_texture, RID p_geom_facing_texture);
RID _setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, bool p_use_directional_shadow_atlas = false, int p_index = 0);
@@ -161,13 +162,13 @@ class RenderForwardClustered : public RendererSceneRenderRD {
Vector2 uv_offset;
Plane lod_plane;
float lod_distance_multiplier = 0.0;
- float screen_lod_threshold = 0.0;
+ float screen_mesh_lod_threshold = 0.0;
RD::FramebufferFormatID framebuffer_format = 0;
uint32_t element_offset = 0;
uint32_t barrier = RD::BARRIER_MASK_ALL;
bool use_directional_soft_shadow = false;
- RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, bool p_use_directional_soft_shadows, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) {
+ RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, bool p_use_directional_soft_shadows, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) {
elements = p_elements;
element_info = p_element_info;
element_count = p_element_count;
@@ -179,7 +180,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
uv_offset = p_uv_offset;
lod_plane = p_lod_plane;
lod_distance_multiplier = p_lod_distance_multiplier;
- screen_lod_threshold = p_screen_lod_threshold;
+ screen_mesh_lod_threshold = p_screen_mesh_lod_threshold;
element_offset = p_element_offset;
barrier = p_barrier;
use_directional_soft_shadow = p_use_directional_soft_shadows;
@@ -208,6 +209,8 @@ class RenderForwardClustered : public RendererSceneRenderRD {
INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA = 1 << 15,
INSTANCE_DATA_FLAGS_PARTICLE_TRAIL_SHIFT = 16,
INSTANCE_DATA_FLAGS_PARTICLE_TRAIL_MASK = 0xFF,
+ INSTANCE_DATA_FLAGS_FADE_SHIFT = 24,
+ INSTANCE_DATA_FLAGS_FADE_MASK = 0xFF << INSTANCE_DATA_FLAGS_FADE_SHIFT
};
struct SceneState {
@@ -248,14 +251,15 @@ class RenderForwardClustered : public RendererSceneRenderRD {
float z_far;
float z_near;
- uint32_t ssao_enabled;
+ uint32_t ss_effects_flags;
float ssao_light_affect;
float ssao_ao_affect;
uint32_t roughness_limiter_enabled;
float roughness_limiter_amount;
float roughness_limiter_limit;
- uint32_t roughness_limiter_pad[2];
+ float opaque_prepass_threshold;
+ uint32_t roughness_limiter_pad;
float sdf_to_bounds[16];
@@ -338,7 +342,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
RID rp_uniform_set;
Plane camera_plane;
float lod_distance_multiplier;
- float screen_lod_threshold;
+ float screen_mesh_lod_threshold;
RID framebuffer;
RD::InitialAction initial_depth_action;
@@ -466,6 +470,15 @@ class RenderForwardClustered : public RendererSceneRenderRD {
bool can_sdfgi = false;
bool using_projectors = false;
bool using_softshadows = false;
+ bool fade_near = false;
+ float fade_near_begin = 0;
+ float fade_near_end = 0;
+ bool fade_far = false;
+ float fade_far_begin = 0;
+ float fade_far_end = 0;
+ float force_alpha = 1.0;
+ float parent_fade_alpha = 1.0;
+
//used during setup
uint32_t base_flags = 0;
Transform3D transform;
@@ -483,6 +496,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
RID skeleton;
Vector<RID> surface_materials;
RID material_override;
+ RID material_overlay;
AABB aabb;
bool use_dynamic_gi = false;
@@ -510,6 +524,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
PagedAllocator<GeometryInstanceLightmapSH> geometry_instance_lightmap_sh;
void _geometry_instance_add_surface_with_material(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, SceneShaderForwardClustered::MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh);
+ void _geometry_instance_add_surface_with_material_chain(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, SceneShaderForwardClustered::MaterialData *p_material, RID p_mat_src, RID p_mesh);
void _geometry_instance_add_surface(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, RID p_material, RID p_mesh);
void _geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance);
void _geometry_instance_update(GeometryInstance *p_geometry_instance);
@@ -581,7 +596,7 @@ protected:
virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) override;
virtual void _render_shadow_begin() override;
- virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RendererScene::RenderInfo *p_render_info = nullptr) override;
+ virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RendererScene::RenderInfo *p_render_info = nullptr) override;
virtual void _render_shadow_process() override;
virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL) override;
@@ -591,14 +606,23 @@ protected:
virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) override;
public:
+ _FORCE_INLINE_ virtual void update_uniform_sets() override {
+ base_uniform_set_updated = true;
+ _update_render_base_uniform_set();
+ }
+
virtual GeometryInstance *geometry_instance_create(RID p_base) override;
virtual void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override;
virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override;
+ virtual void geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_override) override;
virtual void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) override;
virtual void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) override;
virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) override;
virtual void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) override;
virtual void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) override;
+ virtual void geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) override;
+ virtual void geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) override;
+ virtual void geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) override;
virtual void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) override;
virtual void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) override;
virtual void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override;
diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
index a1c3481ed6..7987a98b0e 100644
--- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -44,11 +44,11 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
uniforms.clear();
uses_screen_texture = false;
- if (code == String()) {
+ if (code.is_empty()) {
return; //just invalid, but no error
}
- ShaderCompilerRD::GeneratedCode gen_code;
+ ShaderCompiler::GeneratedCode gen_code;
int blend_mode = BLEND_MODE_MIX;
int depth_testi = DEPTH_TEST_ENABLED;
@@ -79,10 +79,10 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
int depth_drawi = DEPTH_DRAW_OPAQUE;
- ShaderCompilerRD::IdentifierActions actions;
- actions.entry_point_stages["vertex"] = ShaderCompilerRD::STAGE_VERTEX;
- actions.entry_point_stages["fragment"] = ShaderCompilerRD::STAGE_FRAGMENT;
- actions.entry_point_stages["light"] = ShaderCompilerRD::STAGE_FRAGMENT;
+ ShaderCompiler::IdentifierActions actions;
+ actions.entry_point_stages["vertex"] = ShaderCompiler::STAGE_VERTEX;
+ actions.entry_point_stages["fragment"] = ShaderCompiler::STAGE_FRAGMENT;
+ actions.entry_point_stages["light"] = ShaderCompiler::STAGE_FRAGMENT;
actions.render_mode_values["blend_add"] = Pair<int *, int>(&blend_mode, BLEND_MODE_ADD);
actions.render_mode_values["blend_mix"] = Pair<int *, int>(&blend_mode, BLEND_MODE_MIX);
@@ -157,10 +157,10 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
}
print_line("\n**uniforms:\n" + gen_code.uniforms);
- print_line("\n**vertex_globals:\n" + gen_code.stage_globals[ShaderCompilerRD::STAGE_VERTEX]);
- print_line("\n**fragment_globals:\n" + gen_code.stage_globals[ShaderCompilerRD::STAGE_FRAGMENT]);
+ print_line("\n**vertex_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX]);
+ print_line("\n**fragment_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT]);
#endif
- shader_singleton->shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompilerRD::STAGE_VERTEX], gen_code.stage_globals[ShaderCompilerRD::STAGE_FRAGMENT], gen_code.defines);
+ shader_singleton->shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines);
ERR_FAIL_COND(!shader_singleton->shader.version_is_valid(version));
ubo_size = gen_code.uniform_total_size;
@@ -267,8 +267,26 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
RD::RenderPrimitive primitive_rd = uses_point_size ? RD::RENDER_PRIMITIVE_POINTS : primitive_rd_table[j];
- for (int k = 0; k < SHADER_VERSION_MAX; k++) {
- if (!static_cast<SceneShaderForwardClustered *>(singleton)->shader.is_variant_enabled(k)) {
+ for (int k = 0; k < PIPELINE_VERSION_MAX; k++) {
+ ShaderVersion shader_version;
+ static const ShaderVersion shader_version_table[PIPELINE_VERSION_MAX] = {
+ SHADER_VERSION_DEPTH_PASS,
+ SHADER_VERSION_DEPTH_PASS_DP,
+ SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS,
+ SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI,
+ SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL,
+ SHADER_VERSION_DEPTH_PASS_WITH_SDF,
+ SHADER_VERSION_COLOR_PASS,
+ SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR,
+ SHADER_VERSION_COLOR_PASS,
+ SHADER_VERSION_LIGHTMAP_COLOR_PASS,
+ SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR,
+ SHADER_VERSION_LIGHTMAP_COLOR_PASS,
+ };
+
+ shader_version = shader_version_table[k];
+
+ if (!static_cast<SceneShaderForwardClustered *>(singleton)->shader.is_variant_enabled(shader_version)) {
continue;
}
RD::PipelineRasterizationState raster_state;
@@ -279,8 +297,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
RD::PipelineDepthStencilState depth_stencil = depth_stencil_state;
RD::PipelineMultisampleState multisample_state;
- if (uses_alpha || uses_blend_alpha) {
- // only allow these flags to go through if we have some form of msaa
+ if (k == PIPELINE_VERSION_TRANSPARENT_PASS || k == PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS) {
if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE) {
multisample_state.enable_alpha_to_coverage = true;
} else if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE) {
@@ -288,43 +305,29 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
multisample_state.enable_alpha_to_one = true;
}
- if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) {
- blend_state = blend_state_blend;
- if (depth_draw == DEPTH_DRAW_OPAQUE) {
- depth_stencil.enable_depth_write = false; //alpha does not draw depth
- }
- } else if (uses_depth_pre_pass && (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_DP || k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS || k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL)) {
- if (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_DP) {
- //none, blend state contains nothing
- } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL) {
- blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way
- } else {
- blend_state = blend_state_opaque; //writes to normal and roughness in opaque way
- }
- } else {
- pipelines[i][j][k].clear();
- continue; // do not use this version (will error if using it is attempted)
+ blend_state = blend_state_blend;
+
+ if (depth_draw == DEPTH_DRAW_OPAQUE) {
+ depth_stencil.enable_depth_write = false; //alpha does not draw depth
}
+ } else if (k == PIPELINE_VERSION_OPAQUE_PASS || k == PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS) {
+ blend_state = blend_state_opaque;
+ } else if (k == PIPELINE_VERSION_DEPTH_PASS || k == PIPELINE_VERSION_DEPTH_PASS_DP) {
+ //none, leave empty
+ } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS) {
+ blend_state = blend_state_depth_normal_roughness;
+ } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI) {
+ blend_state = blend_state_depth_normal_roughness_giprobe;
+ } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_MATERIAL) {
+ blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way
+ } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_SDF) {
+ blend_state = RD::PipelineColorBlendState(); //no color targets for SDF
} else {
- if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) {
- blend_state = blend_state_opaque;
- } else if (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_DP) {
- //none, leave empty
- } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS) {
- blend_state = blend_state_depth_normal_roughness;
- } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI) {
- blend_state = blend_state_depth_normal_roughness_giprobe;
- } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL) {
- blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way
- } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_SDF) {
- blend_state = RD::PipelineColorBlendState(); //no color targets for SDF
- } else {
- //specular write
- blend_state = blend_state_opaque_specular;
- }
+ //specular write
+ blend_state = blend_state_opaque_specular;
}
- RID shader_variant = shader_singleton->shader.version_get_shader(version, k);
+ RID shader_variant = shader_singleton->shader.version_get_shader(version, shader_version);
pipelines[i][j][k].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0, singleton->default_specialization_constants);
}
}
@@ -333,11 +336,20 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
valid = true;
}
-void SceneShaderForwardClustered::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) {
+void SceneShaderForwardClustered::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
if (!p_texture.is_valid()) {
- default_texture_params.erase(p_name);
+ if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
+ default_texture_params[p_name].erase(p_index);
+
+ if (default_texture_params[p_name].is_empty()) {
+ default_texture_params.erase(p_name);
+ }
+ }
} else {
- default_texture_params[p_name] = p_texture;
+ if (!default_texture_params.has(p_name)) {
+ default_texture_params[p_name] = Map<int, RID>();
+ }
+ default_texture_params[p_name][p_index] = p_texture;
}
}
@@ -451,7 +463,6 @@ SceneShaderForwardClustered::MaterialData::~MaterialData() {
RendererStorageRD::MaterialData *SceneShaderForwardClustered::_create_material_func(ShaderData *p_shader) {
MaterialData *material_data = memnew(MaterialData);
material_data->shader_data = p_shader;
- material_data->last_frame = false;
//update will happen later anyway so do nothing.
return material_data;
}
@@ -498,7 +509,7 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
{
//shader compiler
- ShaderCompilerRD::DefaultIdentifierActions actions;
+ ShaderCompiler::DefaultIdentifierActions actions;
actions.renames["WORLD_MATRIX"] = "world_matrix";
actions.renames["WORLD_NORMAL_MATRIX"] = "world_normal_matrix";
@@ -519,6 +530,7 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
actions.renames["COLOR"] = "color_interp";
actions.renames["POINT_SIZE"] = "gl_PointSize";
actions.renames["INSTANCE_ID"] = "gl_InstanceIndex";
+ actions.renames["VERTEX_ID"] = "gl_VertexIndex";
actions.renames["ALPHA_SCISSOR_THRESHOLD"] = "alpha_scissor_threshold";
actions.renames["ALPHA_HASH_SCALE"] = "alpha_hash_scale";
@@ -573,6 +585,7 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
actions.renames["CUSTOM1"] = "custom1_attrib";
actions.renames["CUSTOM2"] = "custom2_attrib";
actions.renames["CUSTOM3"] = "custom3_attrib";
+ actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB";
// not implemented but need these just in case code is in the shaders
actions.renames["VIEW_INDEX"] = "0";
@@ -637,6 +650,7 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
actions.render_mode_defines["cull_front"] = "#define DO_SIDE_CHECK\n";
actions.render_mode_defines["cull_disabled"] = "#define DO_SIDE_CHECK\n";
actions.render_mode_defines["particle_trails"] = "#define USE_PARTICLE_TRAILS\n";
+ actions.render_mode_defines["depth_draw_opaque"] = "#define USE_OPAQUE_PREPASS\n";
bool force_lambert = GLOBAL_GET("rendering/shading/overrides/force_lambert_over_burley");
@@ -657,6 +671,10 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
actions.render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_BLINN\n";
}
+ actions.custom_samplers["SCREEN_TEXTURE"] = "material_samplers[3]"; // linear filter with mipmaps
+ actions.custom_samplers["DEPTH_TEXTURE"] = "material_samplers[3]";
+ actions.custom_samplers["NORMAL_ROUGHNESS_TEXTURE"] = "material_samplers[1]"; // linear filter
+
actions.render_mode_defines["specular_blinn"] = "#define SPECULAR_BLINN\n";
actions.render_mode_defines["specular_phong"] = "#define SPECULAR_PHONG\n";
actions.render_mode_defines["specular_toon"] = "#define SPECULAR_TOON\n";
diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
index 09ef425e2e..33049fad9c 100644
--- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -55,10 +55,25 @@ public:
SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR,
SHADER_VERSION_LIGHTMAP_COLOR_PASS,
SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR,
-
SHADER_VERSION_MAX
};
+ enum PipelineVersion {
+ PIPELINE_VERSION_DEPTH_PASS,
+ PIPELINE_VERSION_DEPTH_PASS_DP,
+ PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS,
+ PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI,
+ PIPELINE_VERSION_DEPTH_PASS_WITH_MATERIAL,
+ PIPELINE_VERSION_DEPTH_PASS_WITH_SDF,
+ PIPELINE_VERSION_OPAQUE_PASS,
+ PIPELINE_VERSION_OPAQUE_PASS_WITH_SEPARATE_SPECULAR,
+ PIPELINE_VERSION_TRANSPARENT_PASS,
+ PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS,
+ PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS_WITH_SEPARATE_SPECULAR,
+ PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS,
+ PIPELINE_VERSION_MAX
+ };
+
enum ShaderSpecializations {
SHADER_SPECIALIZATION_FORWARD_GI = 1 << 0,
SHADER_SPECIALIZATION_PROJECTOR = 1 << 1,
@@ -109,18 +124,18 @@ public:
bool valid;
RID version;
uint32_t vertex_input_mask;
- PipelineCacheRD pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][SHADER_VERSION_MAX];
+ PipelineCacheRD pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][PIPELINE_VERSION_MAX];
String path;
Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
- Vector<ShaderCompilerRD::GeneratedCode::Texture> texture_uniforms;
+ Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
Vector<uint32_t> ubo_offsets;
uint32_t ubo_size;
String code;
- Map<StringName, RID> default_texture_params;
+ Map<StringName, Map<int, RID>> default_texture_params;
DepthDraw depth_draw;
DepthTest depth_test;
@@ -151,7 +166,7 @@ public:
uint32_t index = 0;
virtual void set_code(const String &p_Code);
- virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
+ virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
@@ -174,7 +189,6 @@ public:
}
struct MaterialData : public RendererStorageRD::MaterialData {
- uint64_t last_frame;
ShaderData *shader_data;
RID uniform_set;
uint64_t last_pass = 0;
@@ -193,7 +207,7 @@ public:
}
SceneForwardClusteredShaderRD shader;
- ShaderCompilerRD compiler;
+ ShaderCompiler compiler;
RID default_shader;
RID default_material;
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
index 5d80ae6212..b9c51f5461 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -483,6 +483,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
scene_state.ubo.viewport_size[0] = vp_he.x;
scene_state.ubo.viewport_size[1] = vp_he.y;
scene_state.ubo.directional_light_count = 0;
+ scene_state.ubo.opaque_prepass_threshold = 0.0;
// We can only use our full subpass approach if we're:
// - not reading from SCREEN_TEXTURE/DEPTH_TEXTURE
@@ -668,7 +669,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
RD::get_singleton()->draw_command_end_label(); // Setup Sky resolution buffers
}
- _pre_opaque_render(p_render_data, false, false, RID(), RID());
+ _pre_opaque_render(p_render_data, false, false, false, RID(), RID());
uint32_t spec_constant_base_flags = 0;
@@ -729,7 +730,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
}
RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer);
- RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, spec_constant_base_flags, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold, p_render_data->view_count);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, spec_constant_base_flags, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count);
render_list_params.framebuffer_format = fb_format;
if ((uint32_t)render_list_params.element_count > render_list_thread_threshold && false) {
// secondary command buffers need more testing at this time
@@ -793,7 +794,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
if (using_subpass_transparent) {
RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer);
- RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, spec_constant_base_flags, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold, p_render_data->view_count);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, PASS_MODE_COLOR_TRANSPARENT, rp_uniform_set, spec_constant_base_flags, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count);
render_list_params.framebuffer_format = fb_format;
if ((uint32_t)render_list_params.element_count > render_list_thread_threshold && false) {
// secondary command buffers need more testing at this time
@@ -830,7 +831,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
// _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false);
RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer);
- RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, spec_constant_base_flags, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold, p_render_data->view_count);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, spec_constant_base_flags, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count);
render_list_params.framebuffer_format = fb_format;
if ((uint32_t)render_list_params.element_count > render_list_thread_threshold && false) {
// secondary command buffers need more testing at this time
@@ -876,7 +877,7 @@ void RenderForwardMobile::_render_shadow_begin() {
render_list[RENDER_LIST_SECONDARY].clear();
}
-void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end, RendererScene::RenderInfo *p_render_info) {
+void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end, RendererScene::RenderInfo *p_render_info) {
uint32_t shadow_pass_index = scene_state.shadow_passes.size();
SceneState::ShadowPass shadow_pass;
@@ -897,13 +898,14 @@ void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedAr
render_data.lod_distance_multiplier = p_lod_distance_multiplier;
scene_state.ubo.dual_paraboloid_side = p_use_dp_flip ? -1 : 1;
+ scene_state.ubo.opaque_prepass_threshold = 0.1;
_setup_environment(&render_data, true, Vector2(1, 1), !p_flip_y, Color(), false, p_use_pancake, shadow_pass_index);
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_DISABLE_LOD) {
- render_data.screen_lod_threshold = 0.0;
+ render_data.screen_mesh_lod_threshold = 0.0;
} else {
- render_data.screen_lod_threshold = p_screen_lod_threshold;
+ render_data.screen_mesh_lod_threshold = p_screen_mesh_lod_threshold;
}
PassMode pass_mode = p_use_dp ? PASS_MODE_SHADOW_DP : PASS_MODE_SHADOW;
@@ -928,7 +930,7 @@ void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedAr
shadow_pass.rp_uniform_set = RID(); //will be filled later when instance buffer is complete
shadow_pass.camera_plane = p_camera_plane;
- shadow_pass.screen_lod_threshold = render_data.screen_lod_threshold;
+ shadow_pass.screen_mesh_lod_threshold = render_data.screen_mesh_lod_threshold;
shadow_pass.lod_distance_multiplier = render_data.lod_distance_multiplier;
shadow_pass.framebuffer = p_framebuffer;
@@ -957,7 +959,7 @@ void RenderForwardMobile::_render_shadow_end(uint32_t p_barrier) {
for (uint32_t i = 0; i < scene_state.shadow_passes.size(); i++) {
SceneState::ShadowPass &shadow_pass = scene_state.shadow_passes[i];
- RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, shadow_pass.rp_uniform_set, 0, false, Vector2(), shadow_pass.camera_plane, shadow_pass.lod_distance_multiplier, shadow_pass.screen_lod_threshold, 1, shadow_pass.element_from, RD::BARRIER_MASK_NO_BARRIER);
+ RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, shadow_pass.rp_uniform_set, 0, false, Vector2(), shadow_pass.camera_plane, shadow_pass.lod_distance_multiplier, shadow_pass.screen_mesh_lod_threshold, 1, shadow_pass.element_from, RD::BARRIER_MASK_NO_BARRIER);
_render_list_with_threads(&render_list_parameters, shadow_pass.framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, shadow_pass.initial_depth_action, shadow_pass.final_depth_action, Vector<Color>(), 1.0, 0, shadow_pass.rect);
}
@@ -978,6 +980,7 @@ void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, c
scene_state.ubo.dual_paraboloid_side = 0;
scene_state.ubo.material_uv2_mode = false;
+ scene_state.ubo.opaque_prepass_threshold = 0.0f;
RenderDataRD render_data;
render_data.cam_projection = p_cam_projection;
@@ -999,12 +1002,13 @@ void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, c
{
RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, rp_uniform_set, 0);
//regular forward for now
- Vector<Color> clear;
- clear.push_back(Color(0, 0, 0, 0));
- clear.push_back(Color(0, 0, 0, 0));
- clear.push_back(Color(0, 0, 0, 0));
- clear.push_back(Color(0, 0, 0, 0));
- clear.push_back(Color(0, 0, 0, 0));
+ Vector<Color> clear = {
+ Color(0, 0, 0, 0),
+ Color(0, 0, 0, 0),
+ Color(0, 0, 0, 0),
+ Color(0, 0, 0, 0),
+ Color(0, 0, 0, 0)
+ };
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, clear, 1.0, 0, p_region);
_render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), &render_list_params, 0, render_list_params.element_count);
RD::get_singleton()->draw_list_end();
@@ -1040,12 +1044,14 @@ void RenderForwardMobile::_render_uv2(const PagedArray<GeometryInstance *> &p_in
{
RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, rp_uniform_set, true, 0);
//regular forward for now
- Vector<Color> clear;
- clear.push_back(Color(0, 0, 0, 0));
- clear.push_back(Color(0, 0, 0, 0));
- clear.push_back(Color(0, 0, 0, 0));
- clear.push_back(Color(0, 0, 0, 0));
- clear.push_back(Color(0, 0, 0, 0));
+ Vector<Color> clear = {
+ Color(0, 0, 0, 0),
+ Color(0, 0, 0, 0),
+ Color(0, 0, 0, 0),
+ Color(0, 0, 0, 0),
+ Color(0, 0, 0, 0)
+ };
+
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, clear, 1.0, 0, p_region);
const int uv_offset_count = 9;
@@ -1089,6 +1095,7 @@ void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const
_update_render_base_uniform_set();
scene_state.ubo.dual_paraboloid_side = 0;
+ scene_state.ubo.opaque_prepass_threshold = 0.0;
RenderDataRD render_data;
render_data.cam_projection = p_cam_projection;
@@ -1322,7 +1329,7 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const
}
uint32_t lightmap_captures_used = 0;
- Plane near_plane(p_render_data->cam_transform.origin, -p_render_data->cam_transform.basis.get_axis(Vector3::AXIS_Z));
+ Plane near_plane(-p_render_data->cam_transform.basis.get_axis(Vector3::AXIS_Z), p_render_data->cam_transform.origin);
near_plane.d += p_render_data->cam_projection.get_z_near();
float z_max = p_render_data->cam_projection.get_z_far() - p_render_data->cam_projection.get_z_near();
@@ -1403,7 +1410,7 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const
// LOD
- if (p_render_data->screen_lod_threshold > 0.0 && storage->mesh_surface_has_lod(surf->surface)) {
+ if (p_render_data->screen_mesh_lod_threshold > 0.0 && storage->mesh_surface_has_lod(surf->surface)) {
//lod
Vector3 lod_support_min = inst->transformed_aabb.get_support(-p_render_data->lod_camera_plane.normal);
Vector3 lod_support_max = inst->transformed_aabb.get_support(p_render_data->lod_camera_plane.normal);
@@ -1423,7 +1430,7 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const
}
uint32_t indices;
- surf->lod_index = storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold, &indices);
+ surf->lod_index = storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, &indices);
if (p_render_data->render_info) {
indices = _indices_to_primitives(surf->primitive, indices);
if (p_render_list == RENDER_LIST_OPAQUE) { //opaque
@@ -1447,13 +1454,13 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const
}
// ADD Element
- if (p_pass_mode == PASS_MODE_COLOR) {
+ if (p_pass_mode == PASS_MODE_COLOR || p_pass_mode == PASS_MODE_COLOR_TRANSPARENT) {
#ifdef DEBUG_ENABLED
bool force_alpha = unlikely(get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_OVERDRAW);
#else
bool force_alpha = false;
#endif
- if (!force_alpha && (surf->flags & (GeometryInstanceSurfaceDataCache::FLAG_PASS_DEPTH | GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE))) {
+ if (!force_alpha && (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE)) {
rl->add_element(surf);
}
if (force_alpha || (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_ALPHA)) {
@@ -1821,6 +1828,10 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
const RenderElementInfo &element_info = p_params->element_info[i];
const GeometryInstanceForwardMobile *inst = surf->owner;
+ if (inst->instance_count == 0) {
+ continue;
+ }
+
uint32_t base_spec_constants = p_params->spec_constant_base_flags;
// GeometryInstanceForwardMobile::PushConstant push_constant = inst->push_constant;
@@ -2025,6 +2036,15 @@ void RenderForwardMobile::geometry_instance_set_material_override(GeometryInstan
ginstance->data->dirty_dependencies = true;
}
+void RenderForwardMobile::geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_overlay) {
+ GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
+ ginstance->data->material_overlay = p_overlay;
+
+ _geometry_instance_mark_dirty(ginstance);
+ ginstance->data->dirty_dependencies = true;
+}
+
void RenderForwardMobile::geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) {
GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
ERR_FAIL_COND(!ginstance);
@@ -2072,6 +2092,15 @@ void RenderForwardMobile::geometry_instance_set_lod_bias(GeometryInstance *p_geo
ginstance->lod_bias = p_lod_bias;
}
+void RenderForwardMobile::geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) {
+}
+
+void RenderForwardMobile::geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) {
+}
+
+void RenderForwardMobile::geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) {
+}
+
void RenderForwardMobile::geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) {
GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
ERR_FAIL_COND(!ginstance);
@@ -2342,6 +2371,24 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryI
sdcache->sort.priority = p_material->priority;
}
+void RenderForwardMobile::_geometry_instance_add_surface_with_material_chain(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, SceneShaderForwardMobile::MaterialData *p_material, RID p_mat_src, RID p_mesh) {
+ SceneShaderForwardMobile::MaterialData *material = p_material;
+
+ _geometry_instance_add_surface_with_material(ginstance, p_surface, material, p_mat_src.get_local_index(), storage->material_get_shader_id(p_mat_src), p_mesh);
+
+ while (material->next_pass.is_valid()) {
+ RID next_pass = material->next_pass;
+ material = (SceneShaderForwardMobile::MaterialData *)storage->material_get_data(next_pass, RendererStorageRD::SHADER_TYPE_3D);
+ if (!material || !material->shader_data->valid) {
+ break;
+ }
+ if (ginstance->data->dirty_dependencies) {
+ storage->material_update_dependency(next_pass, &ginstance->data->dependency_tracker);
+ }
+ _geometry_instance_add_surface_with_material(ginstance, p_surface, material, next_pass.get_local_index(), storage->material_get_shader_id(next_pass), p_mesh);
+ }
+}
+
void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, RID p_material, RID p_mesh) {
RID m_src;
@@ -2367,18 +2414,19 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward
ERR_FAIL_COND(!material);
- _geometry_instance_add_surface_with_material(ginstance, p_surface, material, m_src.get_local_index(), storage->material_get_shader_id(m_src), p_mesh);
+ _geometry_instance_add_surface_with_material_chain(ginstance, p_surface, material, m_src, p_mesh);
- while (material->next_pass.is_valid()) {
- RID next_pass = material->next_pass;
- material = (SceneShaderForwardMobile::MaterialData *)storage->material_get_data(next_pass, RendererStorageRD::SHADER_TYPE_3D);
- if (!material || !material->shader_data->valid) {
- break;
- }
- if (ginstance->data->dirty_dependencies) {
- storage->material_update_dependency(next_pass, &ginstance->data->dependency_tracker);
+ if (ginstance->data->material_overlay.is_valid()) {
+ m_src = ginstance->data->material_overlay;
+
+ material = (SceneShaderForwardMobile::MaterialData *)storage->material_get_data(m_src, RendererStorageRD::SHADER_TYPE_3D);
+ if (material && material->shader_data->valid) {
+ if (ginstance->data->dirty_dependencies) {
+ storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
+ }
+
+ _geometry_instance_add_surface_with_material_chain(ginstance, p_surface, material, m_src, p_mesh);
}
- _geometry_instance_add_surface_with_material(ginstance, p_surface, material, next_pass.get_local_index(), storage->material_get_shader_id(next_pass), p_mesh);
}
}
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
index 36a92e1464..8274dc3b0c 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -176,13 +176,13 @@ protected:
Plane lod_plane;
uint32_t spec_constant_base_flags = 0;
float lod_distance_multiplier = 0.0;
- float screen_lod_threshold = 0.0;
+ float screen_mesh_lod_threshold = 0.0;
RD::FramebufferFormatID framebuffer_format = 0;
uint32_t element_offset = 0;
uint32_t barrier = RD::BARRIER_MASK_ALL;
uint32_t subpass = 0;
- RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, RID p_render_pass_uniform_set, uint32_t p_spec_constant_base_flags = 0, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) {
+ RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, RID p_render_pass_uniform_set, uint32_t p_spec_constant_base_flags = 0, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) {
elements = p_elements;
element_info = p_element_info;
element_count = p_element_count;
@@ -195,7 +195,7 @@ protected:
uv_offset = p_uv_offset;
lod_plane = p_lod_plane;
lod_distance_multiplier = p_lod_distance_multiplier;
- screen_lod_threshold = p_screen_lod_threshold;
+ screen_mesh_lod_threshold = p_screen_mesh_lod_threshold;
element_offset = p_element_offset;
barrier = p_barrier;
spec_constant_base_flags = p_spec_constant_base_flags;
@@ -210,7 +210,7 @@ protected:
virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) override;
virtual void _render_shadow_begin() override;
- virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RendererScene::RenderInfo *p_render_info = nullptr) override;
+ virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RendererScene::RenderInfo *p_render_info = nullptr) override;
virtual void _render_shadow_process() override;
virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL) override;
@@ -292,7 +292,8 @@ protected:
float roughness_limiter_amount;
float roughness_limiter_limit;
- uint32_t roughness_limiter_pad[2];
+ float opaque_prepass_threshold;
+ uint32_t roughness_limiter_pad;
// Fog
uint32_t fog_enabled;
@@ -345,7 +346,7 @@ protected:
RID rp_uniform_set;
Plane camera_plane;
float lod_distance_multiplier;
- float screen_lod_threshold;
+ float screen_mesh_lod_threshold;
RID framebuffer;
RD::InitialAction initial_depth_action;
@@ -585,6 +586,7 @@ protected:
RID skeleton;
Vector<RID> surface_materials;
RID material_override;
+ RID material_overlay;
AABB aabb;
bool use_baked_light = false;
@@ -619,6 +621,7 @@ public:
PagedAllocator<GeometryInstanceLightmapSH> geometry_instance_lightmap_sh;
void _geometry_instance_add_surface_with_material(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, SceneShaderForwardMobile::MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh);
+ void _geometry_instance_add_surface_with_material_chain(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, SceneShaderForwardMobile::MaterialData *p_material, RID p_mat_src, RID p_mesh);
void _geometry_instance_add_surface(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, RID p_material, RID p_mesh);
void _geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance);
void _geometry_instance_update(GeometryInstance *p_geometry_instance);
@@ -627,11 +630,15 @@ public:
virtual GeometryInstance *geometry_instance_create(RID p_base) override;
virtual void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override;
virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override;
+ virtual void geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_overlay) override;
virtual void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) override;
virtual void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) override;
virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) override;
virtual void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) override;
virtual void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) override;
+ virtual void geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) override;
+ virtual void geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) override;
+ virtual void geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) override;
virtual void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) override;
virtual void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) override;
virtual void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override;
diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
index 16d650a540..0b99948063 100644
--- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -47,11 +47,11 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
uniforms.clear();
uses_screen_texture = false;
- if (code == String()) {
+ if (code.is_empty()) {
return; //just invalid, but no error
}
- ShaderCompilerRD::GeneratedCode gen_code;
+ ShaderCompiler::GeneratedCode gen_code;
int blend_mode = BLEND_MODE_MIX;
int depth_testi = DEPTH_TEST_ENABLED;
@@ -81,10 +81,10 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
int depth_drawi = DEPTH_DRAW_OPAQUE;
- ShaderCompilerRD::IdentifierActions actions;
- actions.entry_point_stages["vertex"] = ShaderCompilerRD::STAGE_VERTEX;
- actions.entry_point_stages["fragment"] = ShaderCompilerRD::STAGE_FRAGMENT;
- actions.entry_point_stages["light"] = ShaderCompilerRD::STAGE_FRAGMENT;
+ ShaderCompiler::IdentifierActions actions;
+ actions.entry_point_stages["vertex"] = ShaderCompiler::STAGE_VERTEX;
+ actions.entry_point_stages["fragment"] = ShaderCompiler::STAGE_FRAGMENT;
+ actions.entry_point_stages["light"] = ShaderCompiler::STAGE_FRAGMENT;
actions.render_mode_values["blend_add"] = Pair<int *, int>(&blend_mode, BLEND_MODE_ADD);
actions.render_mode_values["blend_mix"] = Pair<int *, int>(&blend_mode, BLEND_MODE_MIX);
@@ -159,11 +159,11 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
}
print_line("\n**uniforms:\n" + gen_code.uniforms);
- print_line("\n**vertex_globals:\n" + gen_code.stage_globals[ShaderCompilerRD::STAGE_VERTEX]);
- print_line("\n**fragment_globals:\n" + gen_code.stage_globals[ShaderCompilerRD::STAGE_FRAGMENT]);
+ print_line("\n**vertex_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX]);
+ print_line("\n**fragment_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT]);
#endif
- shader_singleton->shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompilerRD::STAGE_VERTEX], gen_code.stage_globals[ShaderCompilerRD::STAGE_FRAGMENT], gen_code.defines);
+ shader_singleton->shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines);
ERR_FAIL_COND(!shader_singleton->shader.version_is_valid(version));
ubo_size = gen_code.uniform_total_size;
@@ -325,11 +325,20 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
valid = true;
}
-void SceneShaderForwardMobile::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) {
+void SceneShaderForwardMobile::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
if (!p_texture.is_valid()) {
- default_texture_params.erase(p_name);
+ if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
+ default_texture_params[p_name].erase(p_index);
+
+ if (default_texture_params[p_name].is_empty()) {
+ default_texture_params.erase(p_name);
+ }
+ }
} else {
- default_texture_params[p_name] = p_texture;
+ if (!default_texture_params.has(p_name)) {
+ default_texture_params[p_name] = Map<int, RID>();
+ }
+ default_texture_params[p_name][p_index] = p_texture;
}
}
@@ -443,7 +452,6 @@ SceneShaderForwardMobile::MaterialData::~MaterialData() {
RendererStorageRD::MaterialData *SceneShaderForwardMobile::_create_material_func(ShaderData *p_shader) {
MaterialData *material_data = memnew(MaterialData);
material_data->shader_data = p_shader;
- material_data->last_frame = false;
//update will happen later anyway so do nothing.
return material_data;
}
@@ -489,7 +497,7 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
{
//shader compiler
- ShaderCompilerRD::DefaultIdentifierActions actions;
+ ShaderCompiler::DefaultIdentifierActions actions;
actions.renames["WORLD_MATRIX"] = "world_matrix";
actions.renames["WORLD_NORMAL_MATRIX"] = "world_normal_matrix";
@@ -510,6 +518,7 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
actions.renames["COLOR"] = "color_interp";
actions.renames["POINT_SIZE"] = "gl_PointSize";
actions.renames["INSTANCE_ID"] = "gl_InstanceIndex";
+ actions.renames["VERTEX_ID"] = "gl_VertexIndex";
actions.renames["ALPHA_SCISSOR_THRESHOLD"] = "alpha_scissor_threshold";
actions.renames["ALPHA_HASH_SCALE"] = "alpha_hash_scale";
@@ -564,6 +573,7 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
actions.renames["CUSTOM1"] = "custom1_attrib";
actions.renames["CUSTOM2"] = "custom2_attrib";
actions.renames["CUSTOM3"] = "custom3_attrib";
+ actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB";
actions.renames["VIEW_INDEX"] = "ViewIndex";
actions.renames["VIEW_MONO_LEFT"] = "0";
@@ -627,6 +637,7 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
actions.render_mode_defines["cull_front"] = "#define DO_SIDE_CHECK\n";
actions.render_mode_defines["cull_disabled"] = "#define DO_SIDE_CHECK\n";
actions.render_mode_defines["particle_trails"] = "#define USE_PARTICLE_TRAILS\n";
+ actions.render_mode_defines["depth_draw_opaque"] = "#define USE_OPAQUE_PREPASS\n";
bool force_lambert = GLOBAL_GET("rendering/shading/overrides/force_lambert_over_burley");
if (!force_lambert) {
diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
index e1c10f0206..92db15e3b0 100644
--- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -105,13 +105,13 @@ public:
String path;
Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
- Vector<ShaderCompilerRD::GeneratedCode::Texture> texture_uniforms;
+ Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
Vector<uint32_t> ubo_offsets;
uint32_t ubo_size;
String code;
- Map<StringName, RID> default_texture_params;
+ Map<StringName, Map<int, RID>> default_texture_params;
DepthDraw depth_draw;
DepthTest depth_test;
@@ -141,7 +141,7 @@ public:
uint32_t index = 0;
virtual void set_code(const String &p_Code);
- virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
+ virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
@@ -163,7 +163,6 @@ public:
}
struct MaterialData : public RendererStorageRD::MaterialData {
- uint64_t last_frame;
ShaderData *shader_data;
RID uniform_set;
uint64_t last_pass = 0;
@@ -184,7 +183,7 @@ public:
}
SceneForwardMobileShaderRD shader;
- ShaderCompilerRD compiler;
+ ShaderCompiler compiler;
RID default_shader;
RID default_material;
diff --git a/servers/rendering/renderer_rd/pipeline_cache_rd.cpp b/servers/rendering/renderer_rd/pipeline_cache_rd.cpp
index 0d60052666..e812a48d3d 100644
--- a/servers/rendering/renderer_rd/pipeline_cache_rd.cpp
+++ b/servers/rendering/renderer_rd/pipeline_cache_rd.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/rendering/renderer_rd/pipeline_cache_rd.h b/servers/rendering/renderer_rd/pipeline_cache_rd.h
index e52f47fa47..8d82480b38 100644
--- a/servers/rendering/renderer_rd/pipeline_cache_rd.h
+++ b/servers/rendering/renderer_rd/pipeline_cache_rd.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
index c69c9eeadf..0f3daef371 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "renderer_canvas_render_rd.h"
+
#include "core/config/project_settings.h"
#include "core/math/geometry_2d.h"
#include "core/math/math_defs.h"
@@ -280,7 +281,7 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve
vd.stride = 0;
descriptions.write[4] = vd;
- buffers.write[4] = storage->mesh_get_default_rd_buffer(RendererStorageRD::DEFAULT_RD_BUFFER_BONES);
+ buffers.write[4] = storage->mesh_get_default_rd_buffer(RendererStorageRD::DEFAULT_RD_BUFFER_WEIGHTS);
}
//check that everything is as it should be
@@ -757,6 +758,10 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
instance_count = storage->multimesh_get_instances_to_draw(multimesh);
+ if (instance_count == 0) {
+ break;
+ }
+
RID uniform_set = storage->multimesh_get_2d_uniform_set(multimesh, shader.default_version_rd_shader, TRANSFORMS_UNIFORM_SET);
RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, uniform_set, TRANSFORMS_UNIFORM_SET);
push_constant.flags |= 1; //multimesh, trails disabled
@@ -1372,14 +1377,6 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
if (md->shader_data->uses_time) {
time_used = true;
}
- if (md->last_frame != RendererCompositorRD::singleton->get_frame_number()) {
- md->last_frame = RendererCompositorRD::singleton->get_frame_number();
- if (!RD::get_singleton()->uniform_set_is_valid(md->uniform_set)) {
- // uniform set may be gone because a dependency was erased. In this case, it will happen
- // if a texture is deleted, so just re-create it.
- storage->material_force_update_textures(material, RendererStorageRD::SHADER_TYPE_2D);
- }
- }
}
}
@@ -1585,9 +1582,6 @@ void RendererCanvasRenderRD::light_update_shadow(RID p_rid, int p_shadow_index,
push_constant.z_far = p_far;
push_constant.pad = 0;
- /*if (i == 0)
- *p_xform_cache = projection;*/
-
LightOccluderInstance *instance = p_occluders;
while (instance) {
@@ -1951,19 +1945,19 @@ void RendererCanvasRenderRD::ShaderData::set_code(const String &p_code) {
uses_sdf = false;
uses_time = false;
- if (code == String()) {
+ if (code.is_empty()) {
return; //just invalid, but no error
}
- ShaderCompilerRD::GeneratedCode gen_code;
+ ShaderCompiler::GeneratedCode gen_code;
int blend_mode = BLEND_MODE_MIX;
uses_screen_texture = false;
- ShaderCompilerRD::IdentifierActions actions;
- actions.entry_point_stages["vertex"] = ShaderCompilerRD::STAGE_VERTEX;
- actions.entry_point_stages["fragment"] = ShaderCompilerRD::STAGE_FRAGMENT;
- actions.entry_point_stages["light"] = ShaderCompilerRD::STAGE_FRAGMENT;
+ ShaderCompiler::IdentifierActions actions;
+ actions.entry_point_stages["vertex"] = ShaderCompiler::STAGE_VERTEX;
+ actions.entry_point_stages["fragment"] = ShaderCompiler::STAGE_FRAGMENT;
+ actions.entry_point_stages["light"] = ShaderCompiler::STAGE_FRAGMENT;
actions.render_mode_values["blend_add"] = Pair<int *, int>(&blend_mode, BLEND_MODE_ADD);
actions.render_mode_values["blend_mix"] = Pair<int *, int>(&blend_mode, BLEND_MODE_MIX);
@@ -2000,7 +1994,7 @@ void RendererCanvasRenderRD::ShaderData::set_code(const String &p_code) {
print_line("\n**fragment_code:\n" + gen_code.fragment);
print_line("\n**light_code:\n" + gen_code.light);
#endif
- canvas_singleton->shader.canvas_shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompilerRD::STAGE_VERTEX], gen_code.stage_globals[ShaderCompilerRD::STAGE_FRAGMENT], gen_code.defines);
+ canvas_singleton->shader.canvas_shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines);
ERR_FAIL_COND(!canvas_singleton->shader.canvas_shader.version_is_valid(version));
ubo_size = gen_code.uniform_total_size;
@@ -2122,11 +2116,20 @@ void RendererCanvasRenderRD::ShaderData::set_code(const String &p_code) {
valid = true;
}
-void RendererCanvasRenderRD::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) {
+void RendererCanvasRenderRD::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
if (!p_texture.is_valid()) {
- default_texture_params.erase(p_name);
+ if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
+ default_texture_params[p_name].erase(p_index);
+
+ if (default_texture_params[p_name].is_empty()) {
+ default_texture_params.erase(p_name);
+ }
+ }
} else {
- default_texture_params[p_name] = p_texture;
+ if (!default_texture_params.has(p_name)) {
+ default_texture_params[p_name] = Map<int, RID>();
+ }
+ default_texture_params[p_name][p_index] = p_texture;
}
}
@@ -2229,7 +2232,6 @@ RendererCanvasRenderRD::MaterialData::~MaterialData() {
RendererStorageRD::MaterialData *RendererCanvasRenderRD::_create_material_func(ShaderData *p_shader) {
MaterialData *material_data = memnew(MaterialData);
material_data->shader_data = p_shader;
- material_data->last_frame = false;
//update will happen later anyway so do nothing.
return material_data;
}
@@ -2348,7 +2350,7 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
{
//shader compiler
- ShaderCompilerRD::DefaultIdentifierActions actions;
+ ShaderCompiler::DefaultIdentifierActions actions;
actions.renames["VERTEX"] = "vertex";
actions.renames["LIGHT_VERTEX"] = "light_vertex";
@@ -2380,6 +2382,8 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
actions.renames["SCREEN_PIXEL_SIZE"] = "canvas_data.screen_pixel_size";
actions.renames["FRAGCOORD"] = "gl_FragCoord";
actions.renames["POINT_COORD"] = "gl_PointCoord";
+ actions.renames["INSTANCE_ID"] = "gl_InstanceIndex";
+ actions.renames["VERTEX_ID"] = "gl_VertexIndex";
actions.renames["LIGHT_POSITION"] = "light_position";
actions.renames["LIGHT_COLOR"] = "light_color";
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
index ec7d7e2854..84f64b6fda 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -35,10 +35,10 @@
#include "servers/rendering/renderer_compositor.h"
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
-#include "servers/rendering/renderer_rd/shader_compiler_rd.h"
#include "servers/rendering/renderer_rd/shaders/canvas.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/canvas_occlusion.glsl.gen.h"
#include "servers/rendering/rendering_device.h"
+#include "servers/rendering/shader_compiler.h"
class RendererCanvasRenderRD : public RendererCanvasRender {
RendererStorageRD *storage;
@@ -148,7 +148,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
RID default_skeleton_uniform_buffer;
RID default_skeleton_texture_buffer;
- ShaderCompilerRD compiler;
+ ShaderCompiler compiler;
} shader;
struct ShaderData : public RendererStorageRD::ShaderData {
@@ -167,20 +167,20 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
String path;
Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
- Vector<ShaderCompilerRD::GeneratedCode::Texture> texture_uniforms;
+ Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
Vector<uint32_t> ubo_offsets;
uint32_t ubo_size;
String code;
- Map<StringName, RID> default_texture_params;
+ Map<StringName, Map<int, RID>> default_texture_params;
bool uses_screen_texture = false;
bool uses_sdf = false;
bool uses_time = false;
virtual void set_code(const String &p_Code);
- virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
+ virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
@@ -200,7 +200,6 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
}
struct MaterialData : public RendererStorageRD::MaterialData {
- uint64_t last_frame;
ShaderData *shader_data;
RID uniform_set;
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
index 559e6d5ad7..2f8ef696cd 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -240,7 +240,7 @@ RendererCompositorRD *RendererCompositorRD::singleton = nullptr;
RendererCompositorRD::RendererCompositorRD() {
{
String shader_cache_dir = Engine::get_singleton()->get_shader_cache_path();
- if (shader_cache_dir == String()) {
+ if (shader_cache_dir.is_empty()) {
shader_cache_dir = "user://";
}
DirAccessRef da = DirAccess::open(shader_cache_dir);
@@ -261,7 +261,7 @@ RendererCompositorRD::RendererCompositorRD() {
shader_cache_dir = String(); //disable only if not editor
}
- if (shader_cache_dir != String()) {
+ if (!shader_cache_dir.is_empty()) {
bool compress = GLOBAL_GET("rendering/shader_compiler/shader_cache/compress");
bool use_zstd = GLOBAL_GET("rendering/shader_compiler/shader_cache/use_zstd_compression");
bool strip_debug = GLOBAL_GET("rendering/shader_compiler/shader_cache/strip_debug");
@@ -281,12 +281,12 @@ RendererCompositorRD::RendererCompositorRD() {
storage = memnew(RendererStorageRD);
canvas = memnew(RendererCanvasRenderRD(storage));
- uint32_t back_end = GLOBAL_GET("rendering/vulkan/rendering/back_end");
+ back_end = (bool)(int)GLOBAL_GET("rendering/vulkan/rendering/back_end");
uint32_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE);
- if (back_end == 1 || textures_per_stage < 48) {
+ if (back_end || textures_per_stage < 48) {
scene = memnew(RendererSceneRenderImplementation::RenderForwardMobile(storage));
- } else { // back_end == 0
+ } else { // back_end == false
// default to our high end renderer
scene = memnew(RendererSceneRenderImplementation::RenderForwardClustered(storage));
}
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h
index 0230c46800..9a992d5819 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.h
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -116,8 +116,6 @@ public:
_create_func = _create_current;
}
- virtual bool is_low_end() const { return false; }
-
static RendererCompositorRD *singleton;
RendererCompositorRD();
~RendererCompositorRD();
diff --git a/servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp
index bb7fbbcdc2..0d0d7513d0 100644
--- a/servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -68,7 +68,7 @@ void RendererSceneEnvironmentRD::set_glow(bool p_enable, Vector<float> p_levels,
glow_hdr_luminance_cap = p_hdr_luminance_cap;
}
-void RendererSceneEnvironmentRD::set_sdfgi(bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) {
+void RendererSceneEnvironmentRD::set_sdfgi(bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) {
sdfgi_enabled = p_enable;
sdfgi_cascades = p_cascades;
sdfgi_min_cell_size = p_min_cell_size;
@@ -92,16 +92,19 @@ void RendererSceneEnvironmentRD::set_fog(bool p_enable, const Color &p_light_col
fog_aerial_perspective = p_fog_aerial_perspective;
}
-void RendererSceneEnvironmentRD::set_volumetric_fog(bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount) {
+void RendererSceneEnvironmentRD::set_volumetric_fog(bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) {
volumetric_fog_enabled = p_enable;
volumetric_fog_density = p_density;
- volumetric_fog_light = p_light;
- volumetric_fog_light_energy = p_light_energy;
+ volumetric_fog_scattering = p_albedo;
+ volumetric_fog_emission = p_emission;
+ volumetric_fog_emission_energy = p_emission_energy;
+ volumetric_fog_anisotropy = p_anisotropy,
volumetric_fog_length = p_length;
volumetric_fog_detail_spread = p_detail_spread;
volumetric_fog_gi_inject = p_gi_inject;
volumetric_fog_temporal_reprojection = p_temporal_reprojection;
volumetric_fog_temporal_reprojection_amount = p_temporal_reprojection_amount;
+ volumetric_fog_ambient_inject = p_ambient_inject;
}
void RendererSceneEnvironmentRD::set_ssr(bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) {
diff --git a/servers/rendering/renderer_rd/renderer_scene_environment_rd.h b/servers/rendering/renderer_rd/renderer_scene_environment_rd.h
index bc47abbff5..629d224b49 100644
--- a/servers/rendering/renderer_rd/renderer_scene_environment_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_environment_rd.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -79,13 +79,16 @@ public:
///
bool volumetric_fog_enabled = false;
float volumetric_fog_density = 0.01;
- Color volumetric_fog_light = Color(0, 0, 0);
- float volumetric_fog_light_energy = 0.0;
+ Color volumetric_fog_scattering = Color(1, 1, 1);
+ Color volumetric_fog_emission = Color(0, 0, 0);
+ float volumetric_fog_emission_energy = 0.0;
+ float volumetric_fog_anisotropy = 0.2;
float volumetric_fog_length = 64.0;
float volumetric_fog_detail_spread = 2.0;
float volumetric_fog_gi_inject = 0.0;
bool volumetric_fog_temporal_reprojection = true;
float volumetric_fog_temporal_reprojection_amount = 0.9;
+ float volumetric_fog_ambient_inject = 0.0;
/// Glow
@@ -120,9 +123,17 @@ public:
float ssr_fade_out = 2.0;
float ssr_depth_tolerance = 0.2;
+ /// SSIL
+ ///
+ bool ssil_enabled = false;
+ float ssil_radius = 5.0;
+ float ssil_intensity = 1.0;
+ float ssil_sharpness = 0.98;
+ float ssil_normal_rejection = 1.0;
+
/// SDFGI
bool sdfgi_enabled = false;
- RS::EnvironmentSDFGICascades sdfgi_cascades;
+ int sdfgi_cascades = 6;
float sdfgi_min_cell_size = 0.2;
bool sdfgi_use_occlusion = false;
float sdfgi_bounce_feedback = 0.0;
@@ -144,9 +155,9 @@ public:
void set_ambient_light(const Color &p_color, RS::EnvironmentAmbientSource p_ambient, float p_energy, float p_sky_contribution, RS::EnvironmentReflectionSource p_reflection_source);
void set_tonemap(RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale);
void set_glow(bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap);
- void set_sdfgi(bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias);
+ void set_sdfgi(bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias);
void set_fog(bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_fog_aerial_perspective);
- void set_volumetric_fog(bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount);
+ void set_volumetric_fog(bool p_enable, float p_density, const Color &p_scatterin, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject);
void set_ssr(bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance);
void set_ssao(bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect);
};
diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp
index ea73dbf26e..3069b1c379 100644
--- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -42,14 +42,13 @@ const Vector3i RendererSceneGIRD::SDFGI::Cascade::DIRTY_ALL = Vector3i(0x7FFFFFF
void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size, RendererSceneGIRD *p_gi) {
storage = p_gi->storage;
gi = p_gi;
- cascade_mode = p_env->sdfgi_cascades;
+ num_cascades = p_env->sdfgi_cascades;
min_cell_size = p_env->sdfgi_min_cell_size;
uses_occlusion = p_env->sdfgi_use_occlusion;
y_scale_mode = p_env->sdfgi_y_scale;
static const float y_scale[3] = { 1.0, 1.5, 2.0 };
y_mult = y_scale[y_scale_mode];
- static const int cascasde_size[3] = { 4, 6, 8 };
- cascades.resize(cascasde_size[cascade_mode]);
+ cascades.resize(num_cascades);
probe_axis_count = SDFGI::PROBE_DIVISOR + 1;
solid_cell_ratio = gi->sdfgi_solid_cell_ratio;
solid_cell_count = uint32_t(float(cascade_size * cascade_size * cascade_size) * solid_cell_ratio);
@@ -716,7 +715,10 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 13;
RID parent_average;
- if (i < cascades.size() - 1) {
+ if (cascades.size() == 1) {
+ // If there is only one SDFGI cascade, we can't use the previous cascade for blending.
+ parent_average = cascades[i].lightprobe_average_tex;
+ } else if (i < cascades.size() - 1) {
parent_average = cascades[i + 1].lightprobe_average_tex;
} else {
parent_average = cascades[i - 1].lightprobe_average_tex; //to use something, but it won't be used
@@ -1305,7 +1307,6 @@ void RendererSceneGIRD::SDFGI::debug_probes(RD::DrawListID p_draw_list, RID p_fr
RD::get_singleton()->draw_list_draw(p_draw_list, false, total_probes, total_points);
if (gi->sdfgi_debug_probe_dir != Vector3()) {
- print_line("CLICK DEBUG ME?");
uint32_t cascade = 0;
Vector3 offset = Vector3((Vector3i(1, 1, 1) * -int32_t(cascade_size >> 1) + cascades[cascade].position)) * cascades[cascade].cell_size * Vector3(1.0, 1.0 / y_mult, 1.0);
Vector3 probe_size = cascades[cascade].cell_size * (cascade_size / SDFGI::PROBE_DIVISOR) * Vector3(1.0, 1.0 / y_mult, 1.0);
@@ -1333,11 +1334,6 @@ void RendererSceneGIRD::SDFGI::debug_probes(RD::DrawListID p_draw_list, RID p_fr
}
}
- if (gi->sdfgi_debug_probe_enabled) {
- print_line("found: " + gi->sdfgi_debug_probe_index);
- } else {
- print_line("no found");
- }
gi->sdfgi_debug_probe_dir = Vector3();
}
@@ -1864,7 +1860,7 @@ void RendererSceneGIRD::SDFGI::render_region(RID p_render_buffers, int p_region,
Ref<Image> img;
img.instantiate();
for (uint32_t i = 0; i < cascade_size; i++) {
- Vector<uint8_t> subarr = data.subarray(128 * 128 * i, 128 * 128 * (i + 1) - 1);
+ Vector<uint8_t> subarr = data.slice(128 * 128 * i, 128 * 128 * (i + 1));
img->create(cascade_size, cascade_size, false, Image::FORMAT_L8, subarr);
img->save_png("res://cascade_sdf_" + itos(cascade) + "_" + itos(i) + ".png");
}
@@ -1877,7 +1873,7 @@ void RendererSceneGIRD::SDFGI::render_region(RID p_render_buffers, int p_region,
Ref<Image> img;
img.instantiate();
for (uint32_t i = 0; i < cascade_size; i++) {
- Vector<uint8_t> subarr = data.subarray(128 * 128 * i * 2, 128 * 128 * (i + 1) * 2 - 1);
+ Vector<uint8_t> subarr = data.slice(128 * 128 * i * 2, 128 * 128 * (i + 1) * 2);
img->createcascade_size, cascade_size, false, Image::FORMAT_RGB565, subarr);
img->convert(Image::FORMAT_RGBA8);
img->save_png("res://cascade_" + itos(cascade) + "_" + itos(i) + ".png");
@@ -2065,7 +2061,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
for (int i = 0; i < levels.size(); i++) {
VoxelGIInstance::Mipmap mipmap;
- mipmap.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), texture, 0, i, RD::TEXTURE_SLICE_3D);
+ mipmap.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), texture, 0, i, 1, RD::TEXTURE_SLICE_3D);
mipmap.level = levels.size() - i - 1;
mipmap.cell_offset = 0;
for (uint32_t j = 0; j < mipmap.level; j++) {
@@ -2182,8 +2178,9 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
dmap.texture = RD::get_singleton()->texture_create(dtf, RD::TextureView());
if (dynamic_maps.size() == 0) {
- //render depth for first one
- dtf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D32_SFLOAT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D32_SFLOAT : RD::DATA_FORMAT_X8_D24_UNORM_PACK32;
+ // Render depth for first one.
+ // Use 16-bit depth when supported to improve performance.
+ dtf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D16_UNORM, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D16_UNORM : RD::DATA_FORMAT_X8_D24_UNORM_PACK32;
dtf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
dmap.fb_depth = RD::get_singleton()->texture_create(dtf, RD::TextureView());
}
@@ -3098,12 +3095,14 @@ void RendererSceneGIRD::setup_voxel_gi_instances(RID p_render_buffers, const Tra
}
rb->gi.uniform_set = RID();
if (rb->volumetric_fog) {
- if (RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->uniform_set)) {
- RD::get_singleton()->free(rb->volumetric_fog->uniform_set);
- RD::get_singleton()->free(rb->volumetric_fog->uniform_set2);
+ if (RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->fog_uniform_set)) {
+ RD::get_singleton()->free(rb->volumetric_fog->fog_uniform_set);
+ RD::get_singleton()->free(rb->volumetric_fog->process_uniform_set);
+ RD::get_singleton()->free(rb->volumetric_fog->process_uniform_set2);
}
- rb->volumetric_fog->uniform_set = RID();
- rb->volumetric_fog->uniform_set2 = RID();
+ rb->volumetric_fog->fog_uniform_set = RID();
+ rb->volumetric_fog->process_uniform_set = RID();
+ rb->volumetric_fog->process_uniform_set2 = RID();
}
}
@@ -3130,8 +3129,8 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_
RD::TextureFormat tf;
tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- tf.width = rb->width;
- tf.height = rb->height;
+ tf.width = rb->internal_width;
+ tf.height = rb->internal_height;
if (half_resolution) {
tf.width >>= 1;
tf.height >>= 1;
@@ -3144,13 +3143,13 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_
PushConstant push_constant;
- push_constant.screen_size[0] = rb->width;
- push_constant.screen_size[1] = rb->height;
+ push_constant.screen_size[0] = rb->internal_width;
+ push_constant.screen_size[1] = rb->internal_height;
push_constant.z_near = p_projection.get_z_near();
push_constant.z_far = p_projection.get_z_far();
push_constant.orthogonal = p_projection.is_orthogonal();
- push_constant.proj_info[0] = -2.0f / (rb->width * p_projection.matrix[0][0]);
- push_constant.proj_info[1] = -2.0f / (rb->height * p_projection.matrix[1][1]);
+ push_constant.proj_info[0] = -2.0f / (rb->internal_width * p_projection.matrix[0][0]);
+ push_constant.proj_info[1] = -2.0f / (rb->internal_height * p_projection.matrix[1][1]);
push_constant.proj_info[2] = (1.0f - p_projection.matrix[0][2]) / p_projection.matrix[0][0];
push_constant.proj_info[3] = (1.0f + p_projection.matrix[1][2]) / p_projection.matrix[1][1];
push_constant.max_voxel_gi_instances = MIN((uint64_t)MAX_VOXEL_GI_INSTANCES, p_voxel_gi_instances.size());
@@ -3342,9 +3341,9 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant));
if (rb->gi.using_half_size_gi) {
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->width >> 1, rb->height >> 1, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->internal_width >> 1, rb->internal_height >> 1, 1);
} else {
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->width, rb->height, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->internal_width, rb->internal_height, 1);
}
//do barrier later to allow oeverlap
//RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER); //no barriers, let other compute, raster and transfer happen at the same time
diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h
index 9f6fc8a9b7..5e55262798 100644
--- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -495,7 +495,7 @@ public:
float solid_cell_ratio = 0;
uint32_t solid_cell_count = 0;
- RS::EnvironmentSDFGICascades cascade_mode;
+ int num_cascades = 6;
float min_cell_size = 0;
uint32_t probe_axis_count = 0; //amount of probes per axis, this is an odd number because it encloses endpoints
@@ -602,19 +602,15 @@ public:
};
struct VoxelGIData {
- float xform[16];
- float bounds[3];
- float dynamic_range;
+ float xform[16]; // 64 - 64
- float bias;
- float normal_bias;
- uint32_t blend_ambient;
- uint32_t texture_slot;
+ float bounds[3]; // 12 - 76
+ float dynamic_range; // 4 - 80
- uint32_t pad0;
- uint32_t pad1;
- uint32_t pad2;
- uint32_t mipmaps;
+ float bias; // 4 - 84
+ float normal_bias; // 4 - 88
+ uint32_t blend_ambient; // 4 - 92
+ uint32_t mipmaps; // 4 - 96
};
struct PushConstant {
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index bd8e950e70..126f40584a 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -65,7 +65,7 @@ void RendererSceneRenderRD::sdfgi_update(RID p_render_buffers, RID p_environment
static const uint32_t history_frames_to_converge[RS::ENV_SDFGI_CONVERGE_MAX] = { 5, 10, 15, 20, 25, 30 };
uint32_t requested_history_size = history_frames_to_converge[gi.sdfgi_frames_to_converge];
- if (rb->sdfgi && (rb->sdfgi->cascade_mode != env->sdfgi_cascades || rb->sdfgi->min_cell_size != env->sdfgi_min_cell_size || requested_history_size != rb->sdfgi->history_size || rb->sdfgi->uses_occlusion != env->sdfgi_use_occlusion || rb->sdfgi->y_scale_mode != env->sdfgi_y_scale)) {
+ if (rb->sdfgi && (rb->sdfgi->num_cascades != env->sdfgi_cascades || rb->sdfgi->min_cell_size != env->sdfgi_min_cell_size || requested_history_size != rb->sdfgi->history_size || rb->sdfgi->uses_occlusion != env->sdfgi_use_occlusion || rb->sdfgi->y_scale_mode != env->sdfgi_y_scale)) {
//configuration changed, erase
rb->sdfgi->erase();
memdelete(rb->sdfgi);
@@ -303,7 +303,7 @@ void RendererSceneRenderRD::environment_glow_set_use_high_quality(bool p_enable)
glow_high_quality = p_enable;
}
-void RendererSceneRenderRD::environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) {
+void RendererSceneRenderRD::environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) {
RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND(!env);
@@ -365,7 +365,7 @@ float RendererSceneRenderRD::environment_get_fog_aerial_perspective(RID p_env) c
return env->fog_aerial_perspective;
}
-void RendererSceneRenderRD::environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount) {
+void RendererSceneRenderRD::environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) {
RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND(!env);
@@ -373,7 +373,7 @@ void RendererSceneRenderRD::environment_set_volumetric_fog(RID p_env, bool p_ena
return;
}
- env->set_volumetric_fog(p_enable, p_density, p_light, p_light_energy, p_length, p_detail_spread, p_gi_inject, p_temporal_reprojection, p_temporal_reprojection_amount);
+ env->set_volumetric_fog(p_enable, p_density, p_albedo, p_emission, p_emission_energy, p_anisotropy, p_length, p_detail_spread, p_gi_inject, p_temporal_reprojection, p_temporal_reprojection_amount, p_ambient_inject);
}
void RendererSceneRenderRD::environment_set_volumetric_fog_volume_size(int p_size, int p_depth) {
@@ -427,6 +427,26 @@ void RendererSceneRenderRD::environment_set_ssao_quality(RS::EnvironmentSSAOQual
ssao_fadeout_to = p_fadeout_to;
}
+void RendererSceneRenderRD::environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) {
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND(!env);
+
+ env->ssil_enabled = p_enable;
+ env->ssil_radius = p_radius;
+ env->ssil_intensity = p_intensity;
+ env->ssil_sharpness = p_sharpness;
+ env->ssil_normal_rejection = p_normal_rejection;
+}
+
+void RendererSceneRenderRD::environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) {
+ ssil_quality = p_quality;
+ ssil_half_size = p_half_size;
+ ssil_adaptive_target = p_adaptive_target;
+ ssil_blur_passes = p_blur_passes;
+ ssil_fadeout_from = p_fadeout_from;
+ ssil_fadeout_to = p_fadeout_to;
+}
+
bool RendererSceneRenderRD::environment_is_ssao_enabled(RID p_env) const {
RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND_V(!env, false);
@@ -445,6 +465,12 @@ float RendererSceneRenderRD::environment_get_ssao_light_affect(RID p_env) const
return env->ssao_direct_light_affect;
}
+bool RendererSceneRenderRD::environment_is_ssil_enabled(RID p_env) const {
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, false);
+ return env->ssil_enabled;
+}
+
bool RendererSceneRenderRD::environment_is_ssr_enabled(RID p_env) const {
RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND_V(!env, false);
@@ -464,34 +490,63 @@ Ref<Image> RendererSceneRenderRD::environment_bake_panorama(RID p_env, bool p_ba
RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND_V(!env, Ref<Image>());
- if (env->background == RS::ENV_BG_CAMERA_FEED || env->background == RS::ENV_BG_CANVAS || env->background == RS::ENV_BG_KEEP) {
+ RS::EnvironmentBG environment_background = env->background;
+
+ if (environment_background == RS::ENV_BG_CAMERA_FEED || environment_background == RS::ENV_BG_CANVAS || environment_background == RS::ENV_BG_KEEP) {
return Ref<Image>(); //nothing to bake
}
- if (env->background == RS::ENV_BG_CLEAR_COLOR || env->background == RS::ENV_BG_COLOR) {
- Color color;
- if (env->background == RS::ENV_BG_CLEAR_COLOR) {
- color = storage->get_default_clear_color();
- } else {
- color = env->bg_color;
- }
- color.r *= env->bg_energy;
- color.g *= env->bg_energy;
- color.b *= env->bg_energy;
-
- Ref<Image> ret;
- ret.instantiate();
- ret->create(p_size.width, p_size.height, false, Image::FORMAT_RGBAF);
- for (int i = 0; i < p_size.width; i++) {
- for (int j = 0; j < p_size.height; j++) {
- ret->set_pixel(i, j, color);
+ RS::EnvironmentAmbientSource ambient_source = env->ambient_source;
+
+ bool use_ambient_light = false;
+ bool use_cube_map = false;
+ if (ambient_source == RS::ENV_AMBIENT_SOURCE_BG && (environment_background == RS::ENV_BG_CLEAR_COLOR || environment_background == RS::ENV_BG_COLOR)) {
+ use_ambient_light = true;
+ } else {
+ use_cube_map = (ambient_source == RS::ENV_AMBIENT_SOURCE_BG && environment_background == RS::ENV_BG_SKY) || ambient_source == RS::ENV_AMBIENT_SOURCE_SKY;
+ use_ambient_light = use_cube_map || ambient_source == RS::ENV_AMBIENT_SOURCE_COLOR;
+ }
+ use_cube_map = use_cube_map || (environment_background == RS::ENV_BG_SKY && env->sky.is_valid());
+
+ Color ambient_color;
+ float ambient_color_sky_mix;
+ if (use_ambient_light) {
+ ambient_color_sky_mix = env->ambient_sky_contribution;
+ const float ambient_energy = env->ambient_light_energy;
+ ambient_color = env->ambient_light;
+ ambient_color = ambient_color.to_linear();
+ ambient_color.r *= ambient_energy;
+ ambient_color.g *= ambient_energy;
+ ambient_color.b *= ambient_energy;
+ }
+
+ if (use_cube_map) {
+ Ref<Image> panorama = sky_bake_panorama(env->sky, env->bg_energy, p_bake_irradiance, p_size);
+ if (use_ambient_light) {
+ for (int x = 0; x < p_size.width; x++) {
+ for (int y = 0; y < p_size.height; y++) {
+ panorama->set_pixel(x, y, ambient_color.lerp(panorama->get_pixel(x, y), ambient_color_sky_mix));
+ }
}
}
- return ret;
- }
+ return panorama;
+ } else {
+ const float bg_energy = env->bg_energy;
+ Color panorama_color = ((environment_background == RS::ENV_BG_CLEAR_COLOR) ? storage->get_default_clear_color() : env->bg_color);
+ panorama_color = panorama_color.to_linear();
+ panorama_color.r *= bg_energy;
+ panorama_color.g *= bg_energy;
+ panorama_color.b *= bg_energy;
- if (env->background == RS::ENV_BG_SKY && env->sky.is_valid()) {
- return sky_bake_panorama(env->sky, env->bg_energy, p_bake_irradiance, p_size);
+ if (use_ambient_light) {
+ panorama_color = ambient_color.lerp(panorama_color, ambient_color_sky_mix);
+ }
+
+ Ref<Image> panorama;
+ panorama.instantiate();
+ panorama->create(p_size.width, p_size.height, false, Image::FORMAT_RGBAF);
+ panorama->fill(panorama_color);
+ return panorama;
}
return Ref<Image>();
@@ -499,6 +554,37 @@ Ref<Image> RendererSceneRenderRD::environment_bake_panorama(RID p_env, bool p_ba
////////////////////////////////////////////////////////////
+RID RendererSceneRenderRD::fog_volume_instance_create(RID p_fog_volume) {
+ FogVolumeInstance fvi;
+ fvi.volume = p_fog_volume;
+ return fog_volume_instance_owner.make_rid(fvi);
+}
+void RendererSceneRenderRD::fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) {
+ FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance);
+ ERR_FAIL_COND(!fvi);
+ fvi->transform = p_transform;
+}
+void RendererSceneRenderRD::fog_volume_instance_set_active(RID p_fog_volume_instance, bool p_active) {
+ FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance);
+ ERR_FAIL_COND(!fvi);
+ fvi->active = p_active;
+}
+
+RID RendererSceneRenderRD::fog_volume_instance_get_volume(RID p_fog_volume_instance) const {
+ FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance);
+ ERR_FAIL_COND_V(!fvi, RID());
+ return fvi->volume;
+}
+
+Vector3 RendererSceneRenderRD::fog_volume_instance_get_position(RID p_fog_volume_instance) const {
+ FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance);
+ ERR_FAIL_COND_V(!fvi, Vector3());
+
+ return fvi->transform.get_origin();
+}
+
+////////////////////////////////////////////////////////////
+
RID RendererSceneRenderRD::reflection_atlas_create() {
ReflectionAtlas ra;
ra.count = GLOBAL_GET("rendering/reflections/reflection_atlas/reflection_count");
@@ -1472,8 +1558,8 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) {
RD::TextureFormat tf;
tf.format = _render_buffers_get_color_format(); // RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- tf.width = rb->width;
- tf.height = rb->height;
+ tf.width = rb->internal_width;
+ tf.height = rb->internal_height;
tf.texture_type = rb->view_count > 1 ? RD::TEXTURE_TYPE_2D_ARRAY : RD::TEXTURE_TYPE_2D;
tf.array_layers = rb->view_count;
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
@@ -1484,6 +1570,10 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) {
}
tf.mipmaps = mipmaps_required;
+ rb->sss_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
+
+ tf.width = rb->internal_width;
+ tf.height = rb->internal_height;
rb->blur[0].texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
//the second one is smaller (only used for separatable part of blur)
tf.width >>= 1;
@@ -1491,8 +1581,8 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) {
tf.mipmaps--;
rb->blur[1].texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
- int base_width = rb->width;
- int base_height = rb->height;
+ int base_width = rb->internal_width;
+ int base_height = rb->internal_height;
for (uint32_t i = 0; i < mipmaps_required; i++) {
RenderBuffers::Blur::Mipmap mm;
@@ -1546,8 +1636,8 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) {
// create 4 weight textures, 2 full size, 2 half size
tf.format = RD::DATA_FORMAT_R16_SFLOAT; // We could probably use DATA_FORMAT_R8_SNORM if we don't pre-multiply by blur_size but that depends on whether we can remove DEPTH_GAP
- tf.width = rb->width;
- tf.height = rb->height;
+ tf.width = rb->internal_width;
+ tf.height = rb->internal_height;
tf.texture_type = rb->view_count > 1 ? RD::TEXTURE_TYPE_2D_ARRAY : RD::TEXTURE_TYPE_2D;
tf.array_layers = rb->view_count;
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
@@ -1625,8 +1715,8 @@ void RendererSceneRenderRD::_allocate_depth_backbuffer_textures(RenderBuffers *r
void RendererSceneRenderRD::_allocate_luminance_textures(RenderBuffers *rb) {
ERR_FAIL_COND(!rb->luminance.current.is_null());
- int w = rb->width;
- int h = rb->height;
+ int w = rb->internal_width;
+ int h = rb->internal_height;
while (true) {
w = MAX(w / 8, 1);
@@ -1678,9 +1768,26 @@ void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) {
rb->texture_fb = RID();
}
- if (rb->texture.is_valid()) {
- RD::get_singleton()->free(rb->texture);
+ if (rb->internal_texture == rb->texture && rb->internal_texture.is_valid()) {
+ RD::get_singleton()->free(rb->internal_texture);
rb->texture = RID();
+ rb->internal_texture = RID();
+ rb->upscale_texture = RID();
+ } else {
+ if (rb->texture.is_valid()) {
+ RD::get_singleton()->free(rb->texture);
+ rb->texture = RID();
+ }
+
+ if (rb->internal_texture.is_valid()) {
+ RD::get_singleton()->free(rb->internal_texture);
+ rb->internal_texture = RID();
+ }
+
+ if (rb->upscale_texture.is_valid()) {
+ RD::get_singleton()->free(rb->upscale_texture);
+ rb->upscale_texture = RID();
+ }
}
if (rb->depth_texture.is_valid()) {
@@ -1698,6 +1805,11 @@ void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) {
rb->depth_back_texture = RID();
}
+ if (rb->sss_texture.is_valid()) {
+ RD::get_singleton()->free(rb->sss_texture);
+ rb->sss_texture = RID();
+ }
+
for (int i = 0; i < 2; i++) {
for (int m = 0; m < rb->blur[i].mipmaps.size(); m++) {
// do we free the texture slice here? or is it enough to free the main texture?
@@ -1741,24 +1853,51 @@ void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) {
rb->luminance.current = RID();
}
- if (rb->ssao.depth.is_valid()) {
- RD::get_singleton()->free(rb->ssao.depth);
- RD::get_singleton()->free(rb->ssao.ao_deinterleaved);
- RD::get_singleton()->free(rb->ssao.ao_pong);
- RD::get_singleton()->free(rb->ssao.ao_final);
+ if (rb->ss_effects.linear_depth.is_valid()) {
+ RD::get_singleton()->free(rb->ss_effects.linear_depth);
+ rb->ss_effects.linear_depth = RID();
+ rb->ss_effects.linear_depth_slices.clear();
+ }
+
+ if (rb->ss_effects.ssao.ao_final.is_valid()) {
+ RD::get_singleton()->free(rb->ss_effects.ssao.ao_deinterleaved);
+ RD::get_singleton()->free(rb->ss_effects.ssao.ao_pong);
+ RD::get_singleton()->free(rb->ss_effects.ssao.ao_final);
+
+ RD::get_singleton()->free(rb->ss_effects.ssao.importance_map[0]);
+ RD::get_singleton()->free(rb->ss_effects.ssao.importance_map[1]);
- RD::get_singleton()->free(rb->ssao.importance_map[0]);
- RD::get_singleton()->free(rb->ssao.importance_map[1]);
+ rb->ss_effects.ssao.ao_deinterleaved = RID();
+ rb->ss_effects.ssao.ao_pong = RID();
+ rb->ss_effects.ssao.ao_final = RID();
+ rb->ss_effects.ssao.importance_map[0] = RID();
+ rb->ss_effects.ssao.importance_map[1] = RID();
- rb->ssao.depth = RID();
- rb->ssao.ao_deinterleaved = RID();
- rb->ssao.ao_pong = RID();
- rb->ssao.ao_final = RID();
- rb->ssao.importance_map[0] = RID();
- rb->ssao.importance_map[1] = RID();
- rb->ssao.depth_slices.clear();
- rb->ssao.ao_deinterleaved_slices.clear();
- rb->ssao.ao_pong_slices.clear();
+ rb->ss_effects.ssao.ao_deinterleaved_slices.clear();
+ rb->ss_effects.ssao.ao_pong_slices.clear();
+ }
+
+ if (rb->ss_effects.ssil.ssil_final.is_valid()) {
+ RD::get_singleton()->free(rb->ss_effects.ssil.ssil_final);
+ RD::get_singleton()->free(rb->ss_effects.ssil.deinterleaved);
+ RD::get_singleton()->free(rb->ss_effects.ssil.pong);
+ RD::get_singleton()->free(rb->ss_effects.ssil.edges);
+ RD::get_singleton()->free(rb->ss_effects.ssil.importance_map[0]);
+ RD::get_singleton()->free(rb->ss_effects.ssil.importance_map[1]);
+
+ rb->ss_effects.ssil.ssil_final = RID();
+ rb->ss_effects.ssil.deinterleaved = RID();
+ rb->ss_effects.ssil.pong = RID();
+ rb->ss_effects.ssil.edges = RID();
+ rb->ss_effects.ssil.deinterleaved_slices.clear();
+ rb->ss_effects.ssil.pong_slices.clear();
+ rb->ss_effects.ssil.edges_slices.clear();
+ rb->ss_effects.ssil.importance_map[0] = RID();
+ rb->ss_effects.ssil.importance_map[1] = RID();
+
+ RD::get_singleton()->free(rb->ss_effects.last_frame);
+ rb->ss_effects.last_frame = RID();
+ rb->ss_effects.last_frame_slices.clear();
}
if (rb->ssr.blur_radius[0].is_valid()) {
@@ -1787,7 +1926,7 @@ void RendererSceneRenderRD::_process_sss(RID p_render_buffers, const CameraMatri
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb);
- bool can_use_effects = rb->width >= 8 && rb->height >= 8;
+ bool can_use_effects = rb->internal_width >= 8 && rb->internal_height >= 8;
if (!can_use_effects) {
//just copy
@@ -1798,18 +1937,18 @@ void RendererSceneRenderRD::_process_sss(RID p_render_buffers, const CameraMatri
_allocate_blur_textures(rb);
}
- storage->get_effects()->sub_surface_scattering(rb->texture, rb->blur[0].mipmaps[0].texture, rb->depth_texture, p_camera, Size2i(rb->width, rb->height), sss_scale, sss_depth_scale, sss_quality);
+ storage->get_effects()->sub_surface_scattering(rb->internal_texture, rb->sss_texture, rb->depth_texture, p_camera, Size2i(rb->internal_width, rb->internal_height), sss_scale, sss_depth_scale, sss_quality);
}
void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_framebuffer, RID p_normal_buffer, RID p_specular_buffer, RID p_metallic, const Color &p_metallic_mask, RID p_environment, const CameraMatrix &p_projection, bool p_use_additive) {
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb);
- bool can_use_effects = rb->width >= 8 && rb->height >= 8;
+ bool can_use_effects = rb->internal_width >= 8 && rb->internal_height >= 8;
if (!can_use_effects) {
//just copy
- storage->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->texture, RID());
+ storage->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, RID());
return;
}
@@ -1821,8 +1960,8 @@ void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_frameb
if (rb->ssr.depth_scaled.is_null()) {
RD::TextureFormat tf;
tf.format = RD::DATA_FORMAT_R32_SFLOAT;
- tf.width = rb->width / 2;
- tf.height = rb->height / 2;
+ tf.width = rb->internal_width / 2;
+ tf.height = rb->internal_height / 2;
tf.texture_type = RD::TEXTURE_TYPE_2D;
tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT;
@@ -1836,8 +1975,8 @@ void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_frameb
if (ssr_roughness_quality != RS::ENV_SSR_ROUGNESS_QUALITY_DISABLED && !rb->ssr.blur_radius[0].is_valid()) {
RD::TextureFormat tf;
tf.format = RD::DATA_FORMAT_R8_UNORM;
- tf.width = rb->width / 2;
- tf.height = rb->height / 2;
+ tf.width = rb->internal_width / 2;
+ tf.height = rb->internal_height / 2;
tf.texture_type = RD::TEXTURE_TYPE_2D;
tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
@@ -1849,8 +1988,8 @@ void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_frameb
_allocate_blur_textures(rb);
}
- storage->get_effects()->screen_space_reflection(rb->texture, p_normal_buffer, ssr_roughness_quality, rb->ssr.blur_radius[0], rb->ssr.blur_radius[1], p_metallic, p_metallic_mask, rb->depth_texture, rb->ssr.depth_scaled, rb->ssr.normal_scaled, rb->blur[0].mipmaps[1].texture, rb->blur[1].mipmaps[0].texture, Size2i(rb->width / 2, rb->height / 2), env->ssr_max_steps, env->ssr_fade_in, env->ssr_fade_out, env->ssr_depth_tolerance, p_projection);
- storage->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->texture, rb->blur[0].mipmaps[1].texture);
+ storage->get_effects()->screen_space_reflection(rb->internal_texture, p_normal_buffer, ssr_roughness_quality, rb->ssr.blur_radius[0], rb->ssr.blur_radius[1], p_metallic, p_metallic_mask, rb->depth_texture, rb->ssr.depth_scaled, rb->ssr.normal_scaled, rb->blur[0].mipmaps[1].texture, rb->blur[1].mipmaps[0].texture, Size2i(rb->internal_width / 2, rb->internal_height / 2), env->ssr_max_steps, env->ssr_fade_in, env->ssr_fade_out, env->ssr_depth_tolerance, p_projection);
+ storage->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, rb->blur[0].mipmaps[1].texture);
}
void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection) {
@@ -1862,24 +2001,21 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen
RENDER_TIMESTAMP("Process SSAO");
- if (rb->ssao.ao_final.is_valid() && ssao_using_half_size != ssao_half_size) {
- RD::get_singleton()->free(rb->ssao.depth);
- RD::get_singleton()->free(rb->ssao.ao_deinterleaved);
- RD::get_singleton()->free(rb->ssao.ao_pong);
- RD::get_singleton()->free(rb->ssao.ao_final);
+ if (rb->ss_effects.ssao.ao_final.is_valid() && ssao_using_half_size != ssao_half_size) {
+ RD::get_singleton()->free(rb->ss_effects.ssao.ao_deinterleaved);
+ RD::get_singleton()->free(rb->ss_effects.ssao.ao_pong);
+ RD::get_singleton()->free(rb->ss_effects.ssao.ao_final);
- RD::get_singleton()->free(rb->ssao.importance_map[0]);
- RD::get_singleton()->free(rb->ssao.importance_map[1]);
+ RD::get_singleton()->free(rb->ss_effects.ssao.importance_map[0]);
+ RD::get_singleton()->free(rb->ss_effects.ssao.importance_map[1]);
- rb->ssao.depth = RID();
- rb->ssao.ao_deinterleaved = RID();
- rb->ssao.ao_pong = RID();
- rb->ssao.ao_final = RID();
- rb->ssao.importance_map[0] = RID();
- rb->ssao.importance_map[1] = RID();
- rb->ssao.depth_slices.clear();
- rb->ssao.ao_deinterleaved_slices.clear();
- rb->ssao.ao_pong_slices.clear();
+ rb->ss_effects.ssao.ao_deinterleaved = RID();
+ rb->ss_effects.ssao.ao_pong = RID();
+ rb->ss_effects.ssao.ao_final = RID();
+ rb->ss_effects.ssao.importance_map[0] = RID();
+ rb->ss_effects.ssao.importance_map[1] = RID();
+ rb->ss_effects.ssao.ao_deinterleaved_slices.clear();
+ rb->ss_effects.ssao.ao_pong_slices.clear();
}
int buffer_width;
@@ -1887,38 +2023,21 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen
int half_width;
int half_height;
if (ssao_half_size) {
- buffer_width = (rb->width + 3) / 4;
- buffer_height = (rb->height + 3) / 4;
- half_width = (rb->width + 7) / 8;
- half_height = (rb->height + 7) / 8;
+ buffer_width = (rb->internal_width + 3) / 4;
+ buffer_height = (rb->internal_height + 3) / 4;
+ half_width = (rb->internal_width + 7) / 8;
+ half_height = (rb->internal_height + 7) / 8;
} else {
- buffer_width = (rb->width + 1) / 2;
- buffer_height = (rb->height + 1) / 2;
- half_width = (rb->width + 3) / 4;
- half_height = (rb->height + 3) / 4;
+ buffer_width = (rb->internal_width + 1) / 2;
+ buffer_height = (rb->internal_height + 1) / 2;
+ half_width = (rb->internal_width + 3) / 4;
+ half_height = (rb->internal_height + 3) / 4;
}
bool uniform_sets_are_invalid = false;
- if (rb->ssao.depth.is_null()) {
- //allocate depth slices
-
+ if (rb->ss_effects.ssao.ao_deinterleaved.is_null()) {
{
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R16_SFLOAT;
- tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
- tf.width = buffer_width;
- tf.height = buffer_height;
- tf.mipmaps = 4;
- tf.array_layers = 4;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- rb->ssao.depth = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ssao.depth, "SSAO Depth");
- for (uint32_t i = 0; i < tf.mipmaps; i++) {
- RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ssao.depth, 0, i, RD::TEXTURE_SLICE_2D_ARRAY);
- rb->ssao.depth_slices.push_back(slice);
- RD::get_singleton()->set_resource_name(rb->ssao.depth_slices[i], "SSAO Depth Mip " + itos(i) + " ");
- }
+ rb->ss_effects.ssao.depth_texture_view = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.linear_depth, 0, ssao_half_size ? 1 : 0, 4, RD::TEXTURE_SLICE_2D_ARRAY);
}
-
{
RD::TextureFormat tf;
tf.format = RD::DATA_FORMAT_R8G8_UNORM;
@@ -1927,12 +2046,12 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen
tf.height = buffer_height;
tf.array_layers = 4;
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- rb->ssao.ao_deinterleaved = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ssao.ao_deinterleaved, "SSAO De-interleaved Array");
+ rb->ss_effects.ssao.ao_deinterleaved = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(rb->ss_effects.ssao.ao_deinterleaved, "SSAO De-interleaved Array");
for (uint32_t i = 0; i < 4; i++) {
- RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ssao.ao_deinterleaved, i, 0);
- rb->ssao.ao_deinterleaved_slices.push_back(slice);
- RD::get_singleton()->set_resource_name(rb->ssao.ao_deinterleaved_slices[i], "SSAO De-interleaved Array Layer " + itos(i) + " ");
+ RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.ssao.ao_deinterleaved, i, 0);
+ rb->ss_effects.ssao.ao_deinterleaved_slices.push_back(slice);
+ RD::get_singleton()->set_resource_name(slice, "SSAO De-interleaved Array Layer " + itos(i) + " ");
}
}
@@ -1944,12 +2063,12 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen
tf.height = buffer_height;
tf.array_layers = 4;
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- rb->ssao.ao_pong = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ssao.ao_pong, "SSAO De-interleaved Array Pong");
+ rb->ss_effects.ssao.ao_pong = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(rb->ss_effects.ssao.ao_pong, "SSAO De-interleaved Array Pong");
for (uint32_t i = 0; i < 4; i++) {
- RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ssao.ao_pong, i, 0);
- rb->ssao.ao_pong_slices.push_back(slice);
- RD::get_singleton()->set_resource_name(rb->ssao.ao_deinterleaved_slices[i], "SSAO De-interleaved Array Layer " + itos(i) + " Pong");
+ RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.ssao.ao_pong, i, 0);
+ rb->ss_effects.ssao.ao_pong_slices.push_back(slice);
+ RD::get_singleton()->set_resource_name(slice, "SSAO De-interleaved Array Layer " + itos(i) + " Pong");
}
}
@@ -1959,19 +2078,19 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen
tf.width = half_width;
tf.height = half_height;
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- rb->ssao.importance_map[0] = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ssao.importance_map[0], "SSAO Importance Map");
- rb->ssao.importance_map[1] = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ssao.importance_map[1], "SSAO Importance Map Pong");
+ rb->ss_effects.ssao.importance_map[0] = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(rb->ss_effects.ssao.importance_map[0], "SSAO Importance Map");
+ rb->ss_effects.ssao.importance_map[1] = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(rb->ss_effects.ssao.importance_map[1], "SSAO Importance Map Pong");
}
{
RD::TextureFormat tf;
tf.format = RD::DATA_FORMAT_R8_UNORM;
- tf.width = rb->width;
- tf.height = rb->height;
+ tf.width = rb->internal_width;
+ tf.height = rb->internal_height;
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- rb->ssao.ao_final = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ssao.ao_final, "SSAO Final");
+ rb->ss_effects.ssao.ao_final = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(rb->ss_effects.ssao.ao_final, "SSAO Final");
}
ssao_using_half_size = ssao_half_size;
uniform_sets_are_invalid = true;
@@ -1991,11 +2110,191 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen
settings.blur_passes = ssao_blur_passes;
settings.fadeout_from = ssao_fadeout_from;
settings.fadeout_to = ssao_fadeout_to;
+ settings.full_screen_size = Size2i(rb->internal_width, rb->internal_height);
+ settings.half_screen_size = Size2i(buffer_width, buffer_height);
+ settings.quarter_screen_size = Size2i(half_width, half_height);
+
+ storage->get_effects()->generate_ssao(p_normal_buffer, rb->ss_effects.ssao.depth_texture_view, rb->ss_effects.ssao.ao_deinterleaved, rb->ss_effects.ssao.ao_deinterleaved_slices, rb->ss_effects.ssao.ao_pong, rb->ss_effects.ssao.ao_pong_slices, rb->ss_effects.ssao.ao_final, rb->ss_effects.ssao.importance_map[0], rb->ss_effects.ssao.importance_map[1], p_projection, settings, uniform_sets_are_invalid, rb->ss_effects.ssao.gather_uniform_set, rb->ss_effects.ssao.importance_map_uniform_set);
+}
+
+void RendererSceneRenderRD::_process_ssil(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection, const Transform3D &p_transform) {
+ RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
+ ERR_FAIL_COND(!rb);
+
+ RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_environment);
+ ERR_FAIL_COND(!env);
+
+ RENDER_TIMESTAMP("Process SSIL");
+
+ if (rb->ss_effects.ssil.ssil_final.is_valid() && ssil_using_half_size != ssil_half_size) {
+ RD::get_singleton()->free(rb->ss_effects.ssil.ssil_final);
+ RD::get_singleton()->free(rb->ss_effects.ssil.deinterleaved);
+ RD::get_singleton()->free(rb->ss_effects.ssil.pong);
+ RD::get_singleton()->free(rb->ss_effects.ssil.edges);
+ RD::get_singleton()->free(rb->ss_effects.ssil.importance_map[0]);
+ RD::get_singleton()->free(rb->ss_effects.ssil.importance_map[1]);
+
+ rb->ss_effects.ssil.ssil_final = RID();
+ rb->ss_effects.ssil.deinterleaved = RID();
+ rb->ss_effects.ssil.pong = RID();
+ rb->ss_effects.ssil.edges = RID();
+ rb->ss_effects.ssil.deinterleaved_slices.clear();
+ rb->ss_effects.ssil.pong_slices.clear();
+ rb->ss_effects.ssil.edges_slices.clear();
+ rb->ss_effects.ssil.importance_map[0] = RID();
+ rb->ss_effects.ssil.importance_map[1] = RID();
+ }
+
+ int buffer_width;
+ int buffer_height;
+ int half_width;
+ int half_height;
+ if (ssil_half_size) {
+ buffer_width = (rb->width + 3) / 4;
+ buffer_height = (rb->height + 3) / 4;
+ half_width = (rb->width + 7) / 8;
+ half_height = (rb->height + 7) / 8;
+ } else {
+ buffer_width = (rb->width + 1) / 2;
+ buffer_height = (rb->height + 1) / 2;
+ half_width = (rb->width + 3) / 4;
+ half_height = (rb->height + 3) / 4;
+ }
+ bool uniform_sets_are_invalid = false;
+ if (rb->ss_effects.ssil.ssil_final.is_null()) {
+ {
+ rb->ss_effects.ssil.depth_texture_view = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.linear_depth, 0, ssil_half_size ? 1 : 0, 4, RD::TEXTURE_SLICE_2D_ARRAY);
+ }
+ {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ tf.width = rb->width;
+ tf.height = rb->height;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
+ rb->ss_effects.ssil.ssil_final = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(rb->ss_effects.ssil.ssil_final, "SSIL texture");
+ RD::get_singleton()->texture_clear(rb->ss_effects.ssil.ssil_final, Color(0, 0, 0, 0), 0, 1, 0, 1);
+ if (rb->ss_effects.last_frame.is_null()) {
+ tf.mipmaps = 6;
+ rb->ss_effects.last_frame = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(rb->ss_effects.last_frame, "Last Frame Radiance");
+ RD::get_singleton()->texture_clear(rb->ss_effects.last_frame, Color(0, 0, 0, 0), 0, tf.mipmaps, 0, 1);
+ for (uint32_t i = 0; i < 6; i++) {
+ RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.last_frame, 0, i);
+ rb->ss_effects.last_frame_slices.push_back(slice);
+ RD::get_singleton()->set_resource_name(slice, "Last Frame Radiance Mip " + itos(i) + " ");
+ }
+ }
+ }
+ {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ tf.width = buffer_width;
+ tf.height = buffer_height;
+ tf.array_layers = 4;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ rb->ss_effects.ssil.deinterleaved = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(rb->ss_effects.ssil.deinterleaved, "SSIL deinterleaved buffer");
+ for (uint32_t i = 0; i < 4; i++) {
+ RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.ssil.deinterleaved, i, 0);
+ rb->ss_effects.ssil.deinterleaved_slices.push_back(slice);
+ RD::get_singleton()->set_resource_name(slice, "SSIL deinterleaved buffer array " + itos(i) + " ");
+ }
+ }
+
+ {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ tf.width = buffer_width;
+ tf.height = buffer_height;
+ tf.array_layers = 4;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ rb->ss_effects.ssil.pong = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(rb->ss_effects.ssil.pong, "SSIL deinterleaved pong buffer");
+ for (uint32_t i = 0; i < 4; i++) {
+ RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.ssil.pong, i, 0);
+ rb->ss_effects.ssil.pong_slices.push_back(slice);
+ RD::get_singleton()->set_resource_name(slice, "SSIL deinterleaved buffer pong array " + itos(i) + " ");
+ }
+ }
+
+ {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R8_UNORM;
+ tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ tf.width = buffer_width;
+ tf.height = buffer_height;
+ tf.array_layers = 4;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ rb->ss_effects.ssil.edges = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(rb->ss_effects.ssil.edges, "SSIL edges buffer");
+ for (uint32_t i = 0; i < 4; i++) {
+ RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.ssil.edges, i, 0);
+ rb->ss_effects.ssil.edges_slices.push_back(slice);
+ RD::get_singleton()->set_resource_name(slice, "SSIL edges buffer slice " + itos(i) + " ");
+ }
+ }
+
+ {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R8_UNORM;
+ tf.width = half_width;
+ tf.height = half_height;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ rb->ss_effects.ssil.importance_map[0] = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(rb->ss_effects.ssil.importance_map[0], "SSIL Importance Map");
+ rb->ss_effects.ssil.importance_map[1] = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(rb->ss_effects.ssil.importance_map[1], "SSIL Importance Map Pong");
+ }
+ uniform_sets_are_invalid = true;
+ ssil_using_half_size = ssil_half_size;
+ }
+
+ EffectsRD::SSILSettings settings;
+ settings.radius = env->ssil_radius;
+ settings.intensity = env->ssil_intensity;
+ settings.sharpness = env->ssil_sharpness;
+ settings.normal_rejection = env->ssil_normal_rejection;
+
+ settings.quality = ssil_quality;
+ settings.half_size = ssil_half_size;
+ settings.adaptive_target = ssil_adaptive_target;
+ settings.blur_passes = ssil_blur_passes;
+ settings.fadeout_from = ssil_fadeout_from;
+ settings.fadeout_to = ssil_fadeout_to;
settings.full_screen_size = Size2i(rb->width, rb->height);
settings.half_screen_size = Size2i(buffer_width, buffer_height);
settings.quarter_screen_size = Size2i(half_width, half_height);
- storage->get_effects()->generate_ssao(rb->depth_texture, p_normal_buffer, rb->ssao.depth, rb->ssao.depth_slices, rb->ssao.ao_deinterleaved, rb->ssao.ao_deinterleaved_slices, rb->ssao.ao_pong, rb->ssao.ao_pong_slices, rb->ssao.ao_final, rb->ssao.importance_map[0], rb->ssao.importance_map[1], p_projection, settings, uniform_sets_are_invalid, rb->ssao.downsample_uniform_set, rb->ssao.gather_uniform_set, rb->ssao.importance_map_uniform_set);
+ CameraMatrix correction;
+ correction.set_depth_correction(true);
+ CameraMatrix projection = correction * p_projection;
+ Transform3D transform = p_transform;
+ transform.set_origin(Vector3(0.0, 0.0, 0.0));
+ CameraMatrix last_frame_projection = rb->ss_effects.last_frame_projection * CameraMatrix(rb->ss_effects.last_frame_transform.affine_inverse()) * CameraMatrix(transform) * projection.inverse();
+
+ storage->get_effects()->screen_space_indirect_lighting(rb->ss_effects.last_frame, rb->ss_effects.ssil.ssil_final, p_normal_buffer, rb->ss_effects.ssil.depth_texture_view, rb->ss_effects.ssil.deinterleaved, rb->ss_effects.ssil.deinterleaved_slices, rb->ss_effects.ssil.pong, rb->ss_effects.ssil.pong_slices, rb->ss_effects.ssil.importance_map[0], rb->ss_effects.ssil.importance_map[1], rb->ss_effects.ssil.edges, rb->ss_effects.ssil.edges_slices, p_projection, last_frame_projection, settings, uniform_sets_are_invalid, rb->ss_effects.ssil.gather_uniform_set, rb->ss_effects.ssil.importance_map_uniform_set, rb->ss_effects.ssil.projection_uniform_set);
+ rb->ss_effects.last_frame_projection = projection;
+ rb->ss_effects.last_frame_transform = transform;
+}
+
+void RendererSceneRenderRD::_copy_framebuffer_to_ssil(RID p_render_buffers) {
+ RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
+ ERR_FAIL_COND(!rb);
+
+ if (rb->ss_effects.last_frame.is_valid()) {
+ storage->get_effects()->copy_to_rect(rb->texture, rb->ss_effects.last_frame, Rect2i(0, 0, rb->width, rb->height));
+
+ int width = rb->width;
+ int height = rb->height;
+ for (int i = 0; i < rb->ss_effects.last_frame_slices.size() - 1; i++) {
+ width = MAX(1, width >> 1);
+ height = MAX(1, height >> 1);
+ storage->get_effects()->make_mipmap(rb->ss_effects.last_frame_slices[i], rb->ss_effects.last_frame_slices[i + 1], Size2i(width, height));
+ }
+ }
}
void RendererSceneRenderRD::_render_buffers_copy_screen_texture(const RenderDataRD *p_render_data) {
@@ -2055,7 +2354,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
ERR_FAIL_COND(!rb);
RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_render_data->environment);
- //glow (if enabled)
+ // Glow and override exposure (if enabled).
CameraEffects *camfx = camera_effects_owner.get_or_null(p_render_data->camera_effects);
bool can_use_effects = rb->width >= 8 && rb->height >= 8;
@@ -2071,9 +2370,9 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
EffectsRD::BokehBuffers buffers;
- // textures we use
- buffers.base_texture_size = Size2i(rb->width, rb->height);
- buffers.base_texture = rb->texture;
+ // Textures we use
+ buffers.base_texture_size = Size2i(rb->internal_width, rb->internal_height);
+ buffers.base_texture = rb->internal_texture;
buffers.depth_texture = rb->depth_texture;
buffers.secondary_texture = rb->blur[0].mipmaps[0].texture;
buffers.half_texture[0] = rb->blur[1].mipmaps[0].texture;
@@ -2083,7 +2382,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
if (can_use_storage) {
storage->get_effects()->bokeh_dof(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, dof_blur_use_jitter, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_ortogonal);
} else {
- // set framebuffers
+ // Set framebuffers.
buffers.base_fb = rb->texture_fb;
buffers.secondary_fb = rb->weight_buffers[1].fb;
buffers.half_fb[0] = rb->weight_buffers[2].fb;
@@ -2093,7 +2392,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
buffers.weight_texture[2] = rb->weight_buffers[2].weight;
buffers.weight_texture[3] = rb->weight_buffers[3].weight;
- // set weight buffers
+ // Set weight buffers.
buffers.base_weight_fb = rb->base_weight_fb;
storage->get_effects()->bokeh_dof_raster(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_ortogonal);
@@ -2112,17 +2411,17 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
double step = env->auto_exp_speed * time_step;
if (can_use_storage) {
- storage->get_effects()->luminance_reduction(rb->texture, Size2i(rb->width, rb->height), rb->luminance.reduce, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate);
+ storage->get_effects()->luminance_reduction(rb->internal_texture, Size2i(rb->internal_width, rb->internal_height), rb->luminance.reduce, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate);
} else {
- storage->get_effects()->luminance_reduction_raster(rb->texture, Size2i(rb->width, rb->height), rb->luminance.reduce, rb->luminance.fb, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate);
+ storage->get_effects()->luminance_reduction_raster(rb->internal_texture, Size2i(rb->internal_width, rb->internal_height), rb->luminance.reduce, rb->luminance.fb, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate);
}
- //swap final reduce with prev luminance
+ // Swap final reduce with prev luminance.
SWAP(rb->luminance.current, rb->luminance.reduce.write[rb->luminance.reduce.size() - 1]);
if (!can_use_storage) {
SWAP(rb->luminance.current_fb, rb->luminance.fb.write[rb->luminance.fb.size() - 1]);
}
- RenderingServerDefault::redraw_request(); //redraw all the time if auto exposure rendering is on
+ RenderingServerDefault::redraw_request(); // Redraw all the time if auto exposure rendering is on.
RD::get_singleton()->draw_command_end_label();
}
@@ -2157,9 +2456,9 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
luminance_texture = rb->luminance.current;
}
if (can_use_storage) {
- storage->get_effects()->gaussian_glow(rb->texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale);
+ storage->get_effects()->gaussian_glow(rb->internal_texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale);
} else {
- storage->get_effects()->gaussian_glow_raster(rb->texture, rb->blur[1].mipmaps[i].half_fb, rb->blur[1].mipmaps[i].half_texture, rb->blur[1].mipmaps[i].fb, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale);
+ storage->get_effects()->gaussian_glow_raster(rb->internal_texture, rb->blur[1].mipmaps[i].half_fb, rb->blur[1].mipmaps[i].half_texture, rb->blur[1].mipmaps[i].fb, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale);
}
} else {
if (can_use_storage) {
@@ -2176,7 +2475,6 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
{
RD::get_singleton()->draw_command_begin_label("Tonemap");
- //tonemap
EffectsRD::TonemapSettings tonemap;
if (can_use_effects && env && env->auto_exposure && rb->luminance.current.is_valid()) {
@@ -2207,7 +2505,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
}
tonemap.use_debanding = rb->use_debanding;
- tonemap.texture_size = Vector2i(rb->width, rb->height);
+ tonemap.texture_size = Vector2i(rb->internal_width, rb->internal_height);
if (env) {
tonemap.tonemap_mode = env->tone_mapper;
@@ -2215,6 +2513,10 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
tonemap.exposure = env->exposure;
}
+ if (camfx && camfx->override_exposure_enabled) {
+ tonemap.exposure = camfx->override_exposure;
+ }
+
tonemap.use_color_correction = false;
tonemap.use_1d_color_correction = false;
tonemap.color_correction_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
@@ -2234,7 +2536,15 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
tonemap.luminance_multiplier = _render_buffers_get_luminance_multiplier();
tonemap.view_count = p_render_data->view_count;
- storage->get_effects()->tonemapper(rb->texture, storage->render_target_get_rd_framebuffer(rb->render_target), tonemap);
+ storage->get_effects()->tonemapper(rb->internal_texture, storage->render_target_get_rd_framebuffer(rb->render_target), tonemap);
+
+ RD::get_singleton()->draw_command_end_label();
+ }
+
+ if (can_use_effects && can_use_storage && (rb->internal_width != rb->width || rb->internal_height != rb->height)) {
+ RD::get_singleton()->draw_command_begin_label("FSR Upscale");
+
+ storage->get_effects()->fsr_upscale(rb->internal_texture, rb->upscale_texture, rb->texture, Size2i(rb->internal_width, rb->internal_height), Size2i(rb->width, rb->height), rb->fsr_sharpness);
RD::get_singleton()->draw_command_end_label();
}
@@ -2249,6 +2559,8 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr
ERR_FAIL_COND(!rb);
RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_render_data->environment);
+ // Override exposure (if enabled).
+ CameraEffects *camfx = camera_effects_owner.get_or_null(p_render_data->camera_effects);
bool can_use_effects = rb->width >= 8 && rb->height >= 8;
@@ -2262,6 +2574,10 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr
tonemap.white = env->white;
}
+ if (camfx && camfx->override_exposure_enabled) {
+ tonemap.exposure = camfx->override_exposure;
+ }
+
// We don't support glow or auto exposure here, if they are needed, don't use subpasses!
// The problem is that we need to use the result so far and process them before we can
// apply this to our results.
@@ -2353,10 +2669,14 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID
}
}
- if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SSAO && rb->ssao.ao_final.is_valid()) {
+ if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SSAO && rb->ss_effects.ssao.ao_final.is_valid()) {
+ Size2 rtsize = storage->render_target_get_size(rb->render_target);
+ effects->copy_to_fb_rect(rb->ss_effects.ssao.ao_final, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, true);
+ }
+
+ if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SSIL && rb->ss_effects.ssil.ssil_final.is_valid()) {
Size2 rtsize = storage->render_target_get_size(rb->render_target);
- RID ao_buf = rb->ssao.ao_final;
- effects->copy_to_fb_rect(ao_buf, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, true);
+ effects->copy_to_fb_rect(rb->ss_effects.ssil.ssil_final, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false);
}
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER && _render_buffers_get_normal_texture(p_render_buffers).is_valid()) {
@@ -2420,7 +2740,13 @@ RID RendererSceneRenderRD::render_buffers_get_ao_texture(RID p_render_buffers) {
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND_V(!rb, RID());
- return rb->ssao.ao_final;
+ return rb->ss_effects.ssao.ao_final;
+}
+RID RendererSceneRenderRD::render_buffers_get_ssil_texture(RID p_render_buffers) {
+ RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
+ ERR_FAIL_COND_V(!rb, RID());
+
+ return rb->ss_effects.ssil.ssil_final;
}
RID RendererSceneRenderRD::render_buffers_get_voxel_gi_buffer(RID p_render_buffers) {
@@ -2588,14 +2914,28 @@ bool RendererSceneRenderRD::_render_buffers_can_be_storage() {
return true;
}
-void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) {
+void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) {
ERR_FAIL_COND_MSG(p_view_count == 0, "Must have at least 1 view");
+ if (!_render_buffers_can_be_storage()) {
+ p_internal_height = p_height;
+ p_internal_width = p_width;
+ }
+
+ if (p_width != p_internal_width) {
+ float fsr_mipmap_bias = -log2f(p_width / p_internal_width) + p_fsr_mipmap_bias;
+ storage->sampler_rd_configure_custom(fsr_mipmap_bias);
+ update_uniform_sets();
+ }
+
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
// Should we add an overrule per viewport?
+ rb->internal_width = p_internal_width;
+ rb->internal_height = p_internal_height;
rb->width = p_width;
rb->height = p_height;
+ rb->fsr_sharpness = p_fsr_sharpness;
rb->render_target = p_render_target;
rb->msaa = p_msaa;
rb->screen_space_aa = p_screen_space_aa;
@@ -2617,8 +2957,8 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
}
tf.format = _render_buffers_get_color_format();
- tf.width = rb->width;
- tf.height = rb->height;
+ tf.width = rb->internal_width; // If set to rb->width, msaa won't crash
+ tf.height = rb->internal_height; // If set to rb->width, msaa won't crash
tf.array_layers = rb->view_count; // create a layer for every view
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | (_render_buffers_can_be_storage() ? RD::TEXTURE_USAGE_STORAGE_BIT : 0) | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
if (rb->msaa != RS::VIEWPORT_MSAA_DISABLED) {
@@ -2626,7 +2966,17 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
}
tf.usage_bits |= RD::TEXTURE_USAGE_INPUT_ATTACHMENT_BIT; // only needed when using subpasses in the mobile renderer
- rb->texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ rb->internal_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
+
+ if ((p_internal_width != p_width || p_internal_height != p_height)) {
+ tf.width = rb->width;
+ tf.height = rb->height;
+ rb->texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ rb->upscale_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ } else {
+ rb->texture = rb->internal_texture;
+ rb->upscale_texture = rb->internal_texture;
+ }
}
{
@@ -2640,8 +2990,8 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
tf.format = RD::DATA_FORMAT_R32_SFLOAT;
}
- tf.width = rb->width;
- tf.height = rb->height;
+ tf.width = rb->internal_width;
+ tf.height = rb->internal_height;
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT;
tf.array_layers = rb->view_count; // create a layer for every view
@@ -2657,16 +3007,16 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
if (!_render_buffers_can_be_storage()) {
// ONLY USED ON MOBILE RENDERER, ONLY USED FOR POST EFFECTS!
Vector<RID> fb;
- fb.push_back(rb->texture);
+ fb.push_back(rb->internal_texture);
rb->texture_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, rb->view_count);
}
RID target_texture = storage->render_target_get_rd_texture(rb->render_target);
- rb->data->configure(rb->texture, rb->depth_texture, target_texture, rb->width, rb->height, p_msaa, p_view_count);
+ rb->data->configure(rb->internal_texture, rb->depth_texture, target_texture, p_internal_width, p_internal_height, p_msaa, p_view_count);
if (is_clustered_enabled()) {
- rb->cluster_builder->setup(Size2i(rb->width, rb->height), max_cluster_elements, rb->depth_texture, storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED), rb->texture);
+ rb->cluster_builder->setup(Size2i(p_internal_width, p_internal_height), max_cluster_elements, rb->depth_texture, storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED), rb->internal_texture);
}
}
@@ -2696,9 +3046,14 @@ void RendererSceneRenderRD::shadows_quality_set(RS::ShadowQuality p_quality) {
switch (shadows_quality) {
case RS::SHADOW_QUALITY_HARD: {
penumbra_shadow_samples = 4;
- soft_shadow_samples = 1;
+ soft_shadow_samples = 0;
shadows_quality_radius = 1.0;
} break;
+ case RS::SHADOW_QUALITY_SOFT_VERY_LOW: {
+ penumbra_shadow_samples = 4;
+ soft_shadow_samples = 1;
+ shadows_quality_radius = 1.5;
+ } break;
case RS::SHADOW_QUALITY_SOFT_LOW: {
penumbra_shadow_samples = 8;
soft_shadow_samples = 4;
@@ -2738,9 +3093,14 @@ void RendererSceneRenderRD::directional_shadow_quality_set(RS::ShadowQuality p_q
switch (directional_shadow_quality) {
case RS::SHADOW_QUALITY_HARD: {
directional_penumbra_shadow_samples = 4;
- directional_soft_shadow_samples = 1;
+ directional_soft_shadow_samples = 0;
directional_shadow_quality_radius = 1.0;
} break;
+ case RS::SHADOW_QUALITY_SOFT_VERY_LOW: {
+ directional_penumbra_shadow_samples = 4;
+ directional_soft_shadow_samples = 1;
+ directional_shadow_quality_radius = 1.5;
+ } break;
case RS::SHADOW_QUALITY_SOFT_LOW: {
directional_penumbra_shadow_samples = 8;
directional_soft_shadow_samples = 4;
@@ -2886,7 +3246,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
r_positional_light_count = 0;
sky.sky_scene_state.ubo.directional_light_count = 0;
- Plane camera_plane(p_camera_transform.origin, -p_camera_transform.basis.get_axis(Vector3::AXIS_Z).normalized());
+ Plane camera_plane(-p_camera_transform.basis.get_axis(Vector3::AXIS_Z).normalized(), p_camera_transform.origin);
cluster.omni_light_count = 0;
cluster.spot_light_count = 0;
@@ -3026,7 +3386,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
RS::LightDirectionalShadowMode smode = storage->light_directional_get_shadow_mode(base);
int limit = smode == RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL ? 0 : (smode == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS ? 1 : 3);
- light_data.blend_splits = storage->light_directional_get_blend_splits(base);
+ light_data.blend_splits = (smode != RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL) && storage->light_directional_get_blend_splits(base);
for (int j = 0; j < 4; j++) {
Rect2 atlas_rect = li->shadow_transform[j].atlas_rect;
CameraMatrix matrix = li->shadow_transform[j].camera;
@@ -3462,18 +3822,206 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
}
}
+////////////////////////////////////////////////////////////////////////////////
+// FOG SHADER
+
+void RendererSceneRenderRD::FogShaderData::set_code(const String &p_code) {
+ //compile
+
+ code = p_code;
+ valid = false;
+ ubo_size = 0;
+ uniforms.clear();
+
+ if (code.is_empty()) {
+ return; //just invalid, but no error
+ }
+
+ ShaderCompiler::GeneratedCode gen_code;
+ ShaderCompiler::IdentifierActions actions;
+ actions.entry_point_stages["fog"] = ShaderCompiler::STAGE_COMPUTE;
+
+ uses_time = false;
+
+ actions.usage_flag_pointers["TIME"] = &uses_time;
+
+ actions.uniforms = &uniforms;
+
+ RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton;
+
+ Error err = scene_singleton->volumetric_fog.compiler.compile(RS::SHADER_FOG, code, &actions, path, gen_code);
+ ERR_FAIL_COND_MSG(err != OK, "Fog shader compilation failed.");
+
+ if (version.is_null()) {
+ version = scene_singleton->volumetric_fog.shader.version_create();
+ }
+
+ scene_singleton->volumetric_fog.shader.version_set_compute_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_COMPUTE], gen_code.defines);
+ ERR_FAIL_COND(!scene_singleton->volumetric_fog.shader.version_is_valid(version));
+
+ ubo_size = gen_code.uniform_total_size;
+ ubo_offsets = gen_code.uniform_offsets;
+ texture_uniforms = gen_code.texture_uniforms;
+
+ pipeline = RD::get_singleton()->compute_pipeline_create(scene_singleton->volumetric_fog.shader.version_get_shader(version, 0));
+
+ valid = true;
+}
+
+void RendererSceneRenderRD::FogShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
+ if (!p_texture.is_valid()) {
+ if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
+ default_texture_params[p_name].erase(p_index);
+
+ if (default_texture_params[p_name].is_empty()) {
+ default_texture_params.erase(p_name);
+ }
+ }
+ } else {
+ if (!default_texture_params.has(p_name)) {
+ default_texture_params[p_name] = Map<int, RID>();
+ }
+ default_texture_params[p_name][p_index] = p_texture;
+ }
+}
+
+void RendererSceneRenderRD::FogShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
+ Map<int, StringName> order;
+
+ for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) {
+ if (E->get().scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E->get().scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
+ continue;
+ }
+
+ if (E->get().texture_order >= 0) {
+ order[E->get().texture_order + 100000] = E->key();
+ } else {
+ order[E->get().order] = E->key();
+ }
+ }
+
+ for (Map<int, StringName>::Element *E = order.front(); E; E = E->next()) {
+ PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E->get()]);
+ pi.name = E->get();
+ p_param_list->push_back(pi);
+ }
+}
+
+void RendererSceneRenderRD::FogShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const {
+ for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) {
+ if (E->get().scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
+ continue;
+ }
+
+ RendererStorage::InstanceShaderParam p;
+ p.info = ShaderLanguage::uniform_to_property_info(E->get());
+ p.info.name = E->key(); //supply name
+ p.index = E->get().instance_index;
+ p.default_value = ShaderLanguage::constant_value_to_variant(E->get().default_value, E->get().type, E->get().array_size, E->get().hint);
+ p_param_list->push_back(p);
+ }
+}
+
+bool RendererSceneRenderRD::FogShaderData::is_param_texture(const StringName &p_param) const {
+ if (!uniforms.has(p_param)) {
+ return false;
+ }
+
+ return uniforms[p_param].texture_order >= 0;
+}
+
+bool RendererSceneRenderRD::FogShaderData::is_animated() const {
+ return false;
+}
+
+bool RendererSceneRenderRD::FogShaderData::casts_shadows() const {
+ return false;
+}
+
+Variant RendererSceneRenderRD::FogShaderData::get_default_parameter(const StringName &p_parameter) const {
+ if (uniforms.has(p_parameter)) {
+ ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter];
+ Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
+ return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint);
+ }
+ return Variant();
+}
+
+RS::ShaderNativeSourceCode RendererSceneRenderRD::FogShaderData::get_native_source_code() const {
+ RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton;
+
+ return scene_singleton->volumetric_fog.shader.version_get_native_source_code(version);
+}
+
+RendererSceneRenderRD::FogShaderData::FogShaderData() {
+ valid = false;
+}
+
+RendererSceneRenderRD::FogShaderData::~FogShaderData() {
+ RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton;
+ ERR_FAIL_COND(!scene_singleton);
+ //pipeline variants will clear themselves if shader is gone
+ if (version.is_valid()) {
+ scene_singleton->volumetric_fog.shader.version_free(version);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Fog material
+
+bool RendererSceneRenderRD::FogMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
+ RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton;
+
+ uniform_set_updated = true;
+
+ return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, scene_singleton->volumetric_fog.shader.version_get_shader(shader_data->version, 0), VolumetricFogShader::FogSet::FOG_SET_MATERIAL);
+}
+
+RendererSceneRenderRD::FogMaterialData::~FogMaterialData() {
+ free_parameters_uniform_set(uniform_set);
+}
+
+RendererStorageRD::ShaderData *RendererSceneRenderRD::_create_fog_shader_func() {
+ FogShaderData *shader_data = memnew(FogShaderData);
+ return shader_data;
+}
+
+RendererStorageRD::ShaderData *RendererSceneRenderRD::_create_fog_shader_funcs() {
+ return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->_create_fog_shader_func();
+};
+
+RendererStorageRD::MaterialData *RendererSceneRenderRD::_create_fog_material_func(FogShaderData *p_shader) {
+ FogMaterialData *material_data = memnew(FogMaterialData);
+ material_data->shader_data = p_shader;
+ //update will happen later anyway so do nothing.
+ return material_data;
+}
+
+RendererStorageRD::MaterialData *RendererSceneRenderRD::_create_fog_material_funcs(RendererStorageRD::ShaderData *p_shader) {
+ return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->_create_fog_material_func(static_cast<FogShaderData *>(p_shader));
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// Volumetric Fog
+
void RendererSceneRenderRD::_volumetric_fog_erase(RenderBuffers *rb) {
ERR_FAIL_COND(!rb->volumetric_fog);
RD::get_singleton()->free(rb->volumetric_fog->prev_light_density_map);
RD::get_singleton()->free(rb->volumetric_fog->light_density_map);
RD::get_singleton()->free(rb->volumetric_fog->fog_map);
+ RD::get_singleton()->free(rb->volumetric_fog->density_map);
+ RD::get_singleton()->free(rb->volumetric_fog->light_map);
+ RD::get_singleton()->free(rb->volumetric_fog->emissive_map);
- if (rb->volumetric_fog->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->uniform_set)) {
- RD::get_singleton()->free(rb->volumetric_fog->uniform_set);
+ if (rb->volumetric_fog->fog_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->fog_uniform_set)) {
+ RD::get_singleton()->free(rb->volumetric_fog->fog_uniform_set);
+ }
+ if (rb->volumetric_fog->process_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->process_uniform_set)) {
+ RD::get_singleton()->free(rb->volumetric_fog->process_uniform_set);
}
- if (rb->volumetric_fog->uniform_set2.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->uniform_set2)) {
- RD::get_singleton()->free(rb->volumetric_fog->uniform_set2);
+ if (rb->volumetric_fog->process_uniform_set2.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->process_uniform_set2)) {
+ RD::get_singleton()->free(rb->volumetric_fog->process_uniform_set2);
}
if (rb->volumetric_fog->sdfgi_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->sdfgi_uniform_set)) {
RD::get_singleton()->free(rb->volumetric_fog->sdfgi_uniform_set);
@@ -3487,7 +4035,26 @@ void RendererSceneRenderRD::_volumetric_fog_erase(RenderBuffers *rb) {
rb->volumetric_fog = nullptr;
}
-void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count) {
+Vector3i RendererSceneRenderRD::_point_get_position_in_froxel_volume(const Vector3 &p_point, float fog_end, const Vector2 &fog_near_size, const Vector2 &fog_far_size, float volumetric_fog_detail_spread, const Vector3 &fog_size, const Transform3D &p_cam_transform) {
+ Vector3 view_position = p_cam_transform.affine_inverse().xform(p_point);
+ view_position.z = MIN(view_position.z, -0.01); // Clamp to the front of camera
+ Vector3 fog_position = Vector3(0, 0, 0);
+
+ view_position.y = -view_position.y;
+ fog_position.z = -view_position.z / fog_end;
+ fog_position.x = (view_position.x / (2 * (fog_near_size.x * (1.0 - fog_position.z) + fog_far_size.x * fog_position.z))) + 0.5;
+ fog_position.y = (view_position.y / (2 * (fog_near_size.y * (1.0 - fog_position.z) + fog_far_size.y * fog_position.z))) + 0.5;
+ fog_position.z = Math::pow(float(fog_position.z), float(1.0 / volumetric_fog_detail_spread));
+ fog_position = fog_position * fog_size - Vector3(0.5, 0.5, 0.5);
+
+ fog_position.x = CLAMP(fog_position.x, 0.0, fog_size.x);
+ fog_position.y = CLAMP(fog_position.y, 0.0, fog_size.y);
+ fog_position.z = CLAMP(fog_position.z, 0.0, fog_size.z);
+
+ return Vector3i(fog_position);
+}
+
+void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes) {
ERR_FAIL_COND(!is_clustered_enabled()); // can't use volumetric fog without clustered
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb);
@@ -3510,6 +4077,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
}
RENDER_TIMESTAMP(">Volumetric Fog");
+ RD::get_singleton()->draw_command_begin_label("Volumetric Fog");
if (env && env->volumetric_fog_enabled && !rb->volumetric_fog) {
//required volumetric fog but not existing, create
@@ -3527,15 +4095,43 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
rb->volumetric_fog->light_density_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(rb->volumetric_fog->light_density_map, "Fog light-density map");
tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
rb->volumetric_fog->prev_light_density_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(rb->volumetric_fog->prev_light_density_map, "Fog previous light-density map");
RD::get_singleton()->texture_clear(rb->volumetric_fog->prev_light_density_map, Color(0, 0, 0, 0), 0, 1, 0, 1);
tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
rb->volumetric_fog->fog_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(rb->volumetric_fog->fog_map, "Fog map");
+
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+ Vector<uint8_t> dm;
+ dm.resize(target_width * target_height * volumetric_fog_depth * 4);
+ dm.fill(0);
+
+ rb->volumetric_fog->density_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm);
+ RD::get_singleton()->set_resource_name(rb->volumetric_fog->density_map, "Fog density map");
+ rb->volumetric_fog->light_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm);
+ RD::get_singleton()->set_resource_name(rb->volumetric_fog->light_map, "Fog light map");
+ rb->volumetric_fog->emissive_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm);
+ RD::get_singleton()->set_resource_name(rb->volumetric_fog->emissive_map, "Fog emissive map");
+#else
+ tf.format = RD::DATA_FORMAT_R32_UINT;
+ tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
+ rb->volumetric_fog->density_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(rb->volumetric_fog->density_map, "Fog density map");
+ RD::get_singleton()->texture_clear(rb->volumetric_fog->density_map, Color(0, 0, 0, 0), 0, 1, 0, 1);
+ rb->volumetric_fog->light_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(rb->volumetric_fog->light_map, "Fog light map");
+ RD::get_singleton()->texture_clear(rb->volumetric_fog->light_map, Color(0, 0, 0, 0), 0, 1, 0, 1);
+ rb->volumetric_fog->emissive_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(rb->volumetric_fog->emissive_map, "Fog emissive map");
+ RD::get_singleton()->texture_clear(rb->volumetric_fog->emissive_map, Color(0, 0, 0, 0), 0, 1, 0, 1);
+#endif
Vector<RD::Uniform> uniforms;
{
@@ -3549,12 +4145,210 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
rb->volumetric_fog->sky_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sky.sky_shader.default_shader_rd, RendererSceneSkyRD::SKY_SET_FOG);
}
- //update volumetric fog
+ if (p_fog_volumes.size() > 0) {
+ RD::get_singleton()->draw_command_begin_label("Render Volumetric Fog Volumes");
- if (rb->volumetric_fog->uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->uniform_set)) {
- //re create uniform set if needed
+ RENDER_TIMESTAMP("Render Fog Volumes");
+
+ VolumetricFogShader::VolumeUBO params;
+
+ Vector2 frustum_near_size = p_cam_projection.get_viewport_half_extents();
+ Vector2 frustum_far_size = p_cam_projection.get_far_plane_half_extents();
+ float z_near = p_cam_projection.get_z_near();
+ float z_far = p_cam_projection.get_z_far();
+ float fog_end = env->volumetric_fog_length;
+
+ Vector2 fog_far_size = frustum_near_size.lerp(frustum_far_size, (fog_end - z_near) / (z_far - z_near));
+ Vector2 fog_near_size;
+ if (p_cam_projection.is_orthogonal()) {
+ fog_near_size = fog_far_size;
+ } else {
+ fog_near_size = Vector2();
+ }
+
+ params.fog_frustum_size_begin[0] = fog_near_size.x;
+ params.fog_frustum_size_begin[1] = fog_near_size.y;
+
+ params.fog_frustum_size_end[0] = fog_far_size.x;
+ params.fog_frustum_size_end[1] = fog_far_size.y;
+
+ params.fog_frustum_end = fog_end;
+ params.z_near = z_near;
+ params.z_far = z_far;
+ params.time = time;
+
+ params.fog_volume_size[0] = rb->volumetric_fog->width;
+ params.fog_volume_size[1] = rb->volumetric_fog->height;
+ params.fog_volume_size[2] = rb->volumetric_fog->depth;
+
+ params.use_temporal_reprojection = env->volumetric_fog_temporal_reprojection;
+ params.temporal_frame = RSG::rasterizer->get_frame_number() % VolumetricFog::MAX_TEMPORAL_FRAMES;
+ params.detail_spread = env->volumetric_fog_detail_spread;
+ params.temporal_blend = env->volumetric_fog_temporal_reprojection_amount;
+
+ Transform3D to_prev_cam_view = rb->volumetric_fog->prev_cam_transform.affine_inverse() * p_cam_transform;
+ storage->store_transform(to_prev_cam_view, params.to_prev_view);
+ storage->store_transform(p_cam_transform, params.transform);
+
+ RD::get_singleton()->buffer_update(volumetric_fog.volume_ubo, 0, sizeof(VolumetricFogShader::VolumeUBO), &params, RD::BARRIER_MASK_COMPUTE);
+
+ if (rb->volumetric_fog->fog_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->fog_uniform_set)) {
+ Vector<RD::Uniform> uniforms;
+
+ {
+ RD::Uniform u;
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+#else
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+#endif
+ u.binding = 1;
+ u.ids.push_back(rb->volumetric_fog->emissive_map);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 2;
+ u.ids.push_back(volumetric_fog.volume_ubo);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+#else
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+#endif
+ u.binding = 3;
+ u.ids.push_back(rb->volumetric_fog->density_map);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+#else
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+#endif
+ u.binding = 4;
+ u.ids.push_back(rb->volumetric_fog->light_map);
+ uniforms.push_back(u);
+ }
+
+ rb->volumetric_fog->fog_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.default_shader_rd, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS);
+ }
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ bool any_uses_time = false;
+
+ for (int i = 0; i < (int)p_fog_volumes.size(); i++) {
+ FogVolumeInstance *fog_volume_instance = fog_volume_instance_owner.get_or_null(p_fog_volumes[i]);
+ ERR_FAIL_COND(!fog_volume_instance);
+ RID fog_volume = fog_volume_instance->volume;
+
+ RID fog_material = storage->fog_volume_get_material(fog_volume);
+
+ FogMaterialData *material = nullptr;
+
+ if (fog_material.is_valid()) {
+ material = (FogMaterialData *)storage->material_get_data(fog_material, RendererStorageRD::SHADER_TYPE_FOG);
+ if (!material || !material->shader_data->valid) {
+ material = nullptr;
+ }
+ }
+
+ if (!material) {
+ fog_material = volumetric_fog.default_material;
+ material = (FogMaterialData *)storage->material_get_data(fog_material, RendererStorageRD::SHADER_TYPE_FOG);
+ }
+
+ ERR_FAIL_COND(!material);
+
+ FogShaderData *shader_data = material->shader_data;
+
+ ERR_FAIL_COND(!shader_data);
+
+ any_uses_time |= shader_data->uses_time;
+
+ Vector3i min = Vector3i();
+ Vector3i max = Vector3i();
+ Vector3i kernel_size = Vector3i();
+
+ Vector3 position = fog_volume_instance->transform.get_origin();
+ RS::FogVolumeShape volume_type = storage->fog_volume_get_shape(fog_volume);
+ Vector3 extents = storage->fog_volume_get_extents(fog_volume);
+ if (volume_type == RS::FOG_VOLUME_SHAPE_BOX || volume_type == RS::FOG_VOLUME_SHAPE_ELLIPSOID) {
+ Vector3i points[8];
+ points[0] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform);
+ points[1] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform);
+ points[2] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, -extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform);
+ points[3] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, -extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform);
+ points[4] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform);
+ points[5] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform);
+ points[6] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, -extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform);
+ points[7] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, -extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform);
+
+ min = Vector3i(int32_t(rb->volumetric_fog->width) - 1, int32_t(rb->volumetric_fog->height) - 1, int32_t(rb->volumetric_fog->depth) - 1);
+ max = Vector3i(1, 1, 1);
+
+ for (int j = 0; j < 8; j++) {
+ min = Vector3i(MIN(min.x, points[j].x), MIN(min.y, points[j].y), MIN(min.z, points[j].z));
+ max = Vector3i(MAX(max.x, points[j].x), MAX(max.y, points[j].y), MAX(max.z, points[j].z));
+ }
+
+ kernel_size = max - min;
+ } else {
+ // Volume type global runs on all cells
+ extents = Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth);
+ min = Vector3i(0, 0, 0);
+ kernel_size = Vector3i(int32_t(rb->volumetric_fog->width), int32_t(rb->volumetric_fog->height), int32_t(rb->volumetric_fog->depth));
+ }
+
+ if (kernel_size.x == 0 || kernel_size.y == 0 || kernel_size.z == 0) {
+ continue;
+ }
+
+ volumetric_fog.push_constant.position[0] = position.x;
+ volumetric_fog.push_constant.position[1] = position.y;
+ volumetric_fog.push_constant.position[2] = position.z;
+ volumetric_fog.push_constant.extents[0] = extents.x;
+ volumetric_fog.push_constant.extents[1] = extents.y;
+ volumetric_fog.push_constant.extents[2] = extents.z;
+ volumetric_fog.push_constant.corner[0] = min.x;
+ volumetric_fog.push_constant.corner[1] = min.y;
+ volumetric_fog.push_constant.corner[2] = min.z;
+ volumetric_fog.push_constant.shape = uint32_t(storage->fog_volume_get_shape(fog_volume));
+ storage->store_transform(fog_volume_instance->transform.affine_inverse(), volumetric_fog.push_constant.transform);
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, shader_data->pipeline);
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->fog_uniform_set, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &volumetric_fog.push_constant, sizeof(VolumetricFogShader::FogPushConstant));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, volumetric_fog.base_uniform_set, VolumetricFogShader::FogSet::FOG_SET_BASE);
+ if (material->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(material->uniform_set)) { // Material may not have a uniform set.
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, material->uniform_set, VolumetricFogShader::FogSet::FOG_SET_MATERIAL);
+ }
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, kernel_size.x, kernel_size.y, kernel_size.z);
+ }
+ if (any_uses_time || env->volumetric_fog_temporal_reprojection) {
+ RenderingServerDefault::redraw_request();
+ }
+
+ RD::get_singleton()->draw_command_end_label();
+
+ RD::get_singleton()->compute_list_end();
+ }
+
+ if (rb->volumetric_fog->process_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->process_uniform_set)) {
+ //re create uniform set if needed
Vector<RD::Uniform> uniforms;
+ Vector<RD::Uniform> copy_uniforms;
{
RD::Uniform u;
@@ -3568,6 +4362,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
}
uniforms.push_back(u);
+ copy_uniforms.push_back(u);
}
{
@@ -3580,6 +4375,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK));
}
uniforms.push_back(u);
+ copy_uniforms.push_back(u);
}
{
@@ -3588,6 +4384,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
u.binding = 3;
u.ids.push_back(get_omni_light_buffer());
uniforms.push_back(u);
+ copy_uniforms.push_back(u);
}
{
RD::Uniform u;
@@ -3595,6 +4392,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
u.binding = 4;
u.ids.push_back(get_spot_light_buffer());
uniforms.push_back(u);
+ copy_uniforms.push_back(u);
}
{
@@ -3603,6 +4401,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
u.binding = 5;
u.ids.push_back(get_directional_light_buffer());
uniforms.push_back(u);
+ copy_uniforms.push_back(u);
}
{
@@ -3611,6 +4410,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
u.binding = 6;
u.ids.push_back(rb->cluster_builder->get_cluster_buffer());
uniforms.push_back(u);
+ copy_uniforms.push_back(u);
}
{
@@ -3619,6 +4419,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
u.binding = 7;
u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
uniforms.push_back(u);
+ copy_uniforms.push_back(u);
}
{
@@ -3627,6 +4428,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
u.binding = 8;
u.ids.push_back(rb->volumetric_fog->light_density_map);
uniforms.push_back(u);
+ copy_uniforms.push_back(u);
}
{
@@ -3639,10 +4441,19 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
{
RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 9;
+ u.ids.push_back(rb->volumetric_fog->prev_light_density_map);
+ copy_uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
u.binding = 10;
u.ids.push_back(shadow_sampler);
uniforms.push_back(u);
+ copy_uniforms.push_back(u);
}
{
@@ -3651,6 +4462,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
u.binding = 11;
u.ids.push_back(render_buffers_get_voxel_gi_buffer(p_render_buffers));
uniforms.push_back(u);
+ copy_uniforms.push_back(u);
}
{
@@ -3661,6 +4473,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
u.ids.push_back(rb->gi.voxel_gi_textures[i]);
}
uniforms.push_back(u);
+ copy_uniforms.push_back(u);
}
{
RD::Uniform u;
@@ -3668,6 +4481,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
u.binding = 13;
u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
uniforms.push_back(u);
+ copy_uniforms.push_back(u);
}
{
RD::Uniform u;
@@ -3675,6 +4489,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
u.binding = 14;
u.ids.push_back(volumetric_fog.params_ubo);
uniforms.push_back(u);
+ copy_uniforms.push_back(u);
}
{
RD::Uniform u;
@@ -3683,12 +4498,58 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
u.ids.push_back(rb->volumetric_fog->prev_light_density_map);
uniforms.push_back(u);
}
+ {
+ RD::Uniform u;
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+#else
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+#endif
+ u.binding = 16;
+ u.ids.push_back(rb->volumetric_fog->density_map);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+#else
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+#endif
+ u.binding = 17;
+ u.ids.push_back(rb->volumetric_fog->light_map);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+#else
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+#endif
+ u.binding = 18;
+ u.ids.push_back(rb->volumetric_fog->emissive_map);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 19;
+ RID radiance_texture = storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
+ RID sky_texture = env->sky.is_valid() ? sky.sky_get_radiance_texture_rd(env->sky) : RID();
+ u.ids.push_back(sky_texture.is_valid() ? sky_texture : radiance_texture);
+ uniforms.push_back(u);
+ }
+
+ rb->volumetric_fog->copy_uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY), 0);
- rb->volumetric_fog->uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.shader.version_get_shader(volumetric_fog.shader_version, 0), 0);
+ rb->volumetric_fog->process_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY), 0);
SWAP(uniforms.write[7].ids.write[0], uniforms.write[8].ids.write[0]);
- rb->volumetric_fog->uniform_set2 = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.shader.version_get_shader(volumetric_fog.shader_version, 0), 0);
+ rb->volumetric_fog->process_uniform_set2 = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, 0), 0);
}
bool using_sdfgi = env->volumetric_fog_gi_inject > 0.0001 && env->sdfgi_enabled && (rb->sdfgi != nullptr);
@@ -3721,7 +4582,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
uniforms.push_back(u);
}
- rb->volumetric_fog->sdfgi_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.shader.version_get_shader(volumetric_fog.shader_version, VOLUMETRIC_FOG_SHADER_DENSITY_WITH_SDFGI), 1);
+ rb->volumetric_fog->sdfgi_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI), 1);
}
}
@@ -3750,23 +4611,35 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
params.fog_frustum_size_end[0] = fog_far_size.x;
params.fog_frustum_size_end[1] = fog_far_size.y;
- params.z_near = z_near;
+ params.ambient_inject = env->volumetric_fog_ambient_inject * env->ambient_light_energy;
params.z_far = z_far;
params.fog_frustum_end = fog_end;
+ Color ambient_color = env->ambient_light.to_linear();
+ params.ambient_color[0] = ambient_color.r;
+ params.ambient_color[1] = ambient_color.g;
+ params.ambient_color[2] = ambient_color.b;
+ params.sky_contribution = env->ambient_sky_contribution;
+
params.fog_volume_size[0] = rb->volumetric_fog->width;
params.fog_volume_size[1] = rb->volumetric_fog->height;
params.fog_volume_size[2] = rb->volumetric_fog->depth;
params.directional_light_count = p_directional_light_count;
- Color light = env->volumetric_fog_light.to_linear();
- params.light_energy[0] = light.r * env->volumetric_fog_light_energy;
- params.light_energy[1] = light.g * env->volumetric_fog_light_energy;
- params.light_energy[2] = light.b * env->volumetric_fog_light_energy;
+ Color emission = env->volumetric_fog_emission.to_linear();
+ params.base_emission[0] = emission.r * env->volumetric_fog_emission_energy;
+ params.base_emission[1] = emission.g * env->volumetric_fog_emission_energy;
+ params.base_emission[2] = emission.b * env->volumetric_fog_emission_energy;
params.base_density = env->volumetric_fog_density;
+ Color base_scattering = env->volumetric_fog_scattering.to_linear();
+ params.base_scattering[0] = base_scattering.r;
+ params.base_scattering[1] = base_scattering.g;
+ params.base_scattering[2] = base_scattering.b;
+ params.phase_g = env->volumetric_fog_anisotropy;
+
params.detail_spread = env->volumetric_fog_detail_spread;
params.gi_inject = env->volumetric_fog_gi_inject;
@@ -3798,18 +4671,17 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
uint32_t cluster_screen_width = (rb->width - 1) / cluster_size + 1;
uint32_t cluster_screen_height = (rb->height - 1) / cluster_size + 1;
- params.cluster_type_size = cluster_screen_width * cluster_screen_height * (32 + 32);
- params.cluster_width = cluster_screen_width;
params.max_cluster_element_count_div_32 = max_cluster_elements / 32;
+ params.cluster_type_size = cluster_screen_width * cluster_screen_height * (params.max_cluster_element_count_div_32 + 32);
+ params.cluster_width = cluster_screen_width;
params.screen_size[0] = rb->width;
params.screen_size[1] = rb->height;
}
- /* Vector2 dssize = directional_shadow_get_size();
- push_constant.directional_shadow_pixel_size[0] = 1.0 / dssize.x;
- push_constant.directional_shadow_pixel_size[1] = 1.0 / dssize.y;
-*/
+ Basis sky_transform = env->sky_orientation;
+ sky_transform = sky_transform.inverse() * p_cam_transform.basis;
+ RendererStorageRD::store_transform_3x3(sky_transform, params.radiance_inverse_xform);
RD::get_singleton()->draw_command_begin_label("Render Volumetric Fog");
@@ -3818,33 +4690,32 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- bool use_filter = volumetric_fog_filter_active;
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.pipelines[using_sdfgi ? VOLUMETRIC_FOG_SHADER_DENSITY_WITH_SDFGI : VOLUMETRIC_FOG_SHADER_DENSITY]);
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[using_sdfgi ? VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI : VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->uniform_set, 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->process_uniform_set, 0);
if (using_sdfgi) {
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->sdfgi_uniform_set, 1);
}
RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ // Copy fog to history buffer
+ if (env->volumetric_fog_temporal_reprojection) {
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->copy_uniform_set, 0);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ }
RD::get_singleton()->draw_command_end_label();
- RD::get_singleton()->compute_list_end();
-
- RD::get_singleton()->texture_copy(rb->volumetric_fog->light_density_map, rb->volumetric_fog->prev_light_density_map, Vector3(0, 0, 0), Vector3(0, 0, 0), Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), 0, 0, 0, 0);
-
- compute_list = RD::get_singleton()->compute_list_begin();
-
- if (use_filter) {
+ if (volumetric_fog_filter_active) {
RD::get_singleton()->draw_command_begin_label("Filter Fog");
RENDER_TIMESTAMP("Filter Fog");
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.pipelines[VOLUMETRIC_FOG_SHADER_FILTER]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->uniform_set, 0);
-
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->process_uniform_set, 0);
RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth);
RD::get_singleton()->compute_list_end();
@@ -3854,11 +4725,8 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
RD::get_singleton()->buffer_update(volumetric_fog.params_ubo, 0, sizeof(VolumetricFogShader::ParamsUBO), &params);
compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.pipelines[VOLUMETRIC_FOG_SHADER_FILTER]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->uniform_set2, 0);
- if (using_sdfgi) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->sdfgi_uniform_set, 1);
- }
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->process_uniform_set2, 0);
RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth);
RD::get_singleton()->compute_list_add_barrier(compute_list);
@@ -3868,14 +4736,15 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
RENDER_TIMESTAMP("Integrate Fog");
RD::get_singleton()->draw_command_begin_label("Integrate Fog");
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.pipelines[VOLUMETRIC_FOG_SHADER_FOG]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->uniform_set, 0);
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->process_uniform_set, 0);
RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, 1);
RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_RASTER);
RENDER_TIMESTAMP("<Volumetric Fog");
RD::get_singleton()->draw_command_end_label();
+ RD::get_singleton()->draw_command_end_label();
rb->volumetric_fog->prev_cam_transform = p_cam_transform;
}
@@ -3913,7 +4782,7 @@ void RendererSceneRenderRD::_pre_resolve_render(RenderDataRD *p_render_data, boo
}
}
-void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_gi, RID p_normal_roughness_buffer, RID p_voxel_gi_buffer) {
+void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, RID p_normal_roughness_buffer, RID p_voxel_gi_buffer) {
// Render shadows while GI is rendering, due to how barriers are handled, this should happen at the same time
if (p_render_data->render_buffers.is_valid() && p_use_gi) {
@@ -3928,7 +4797,7 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
render_state.shadows.clear();
render_state.directional_shadows.clear();
- Plane camera_plane(p_render_data->cam_transform.origin, -p_render_data->cam_transform.basis.get_axis(Vector3::AXIS_Z));
+ Plane camera_plane(-p_render_data->cam_transform.basis.get_axis(Vector3::AXIS_Z), p_render_data->cam_transform.origin);
float lod_distance_multiplier = p_render_data->cam_projection.get_lod_multiplier();
{
for (int i = 0; i < render_state.render_shadow_count; i++) {
@@ -3945,7 +4814,7 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
//cube shadows are rendered in their own way
for (uint32_t i = 0; i < render_state.cube_shadows.size(); i++) {
- _render_shadow_pass(render_state.render_shadows[render_state.cube_shadows[i]].light, p_render_data->shadow_atlas, render_state.render_shadows[render_state.cube_shadows[i]].pass, render_state.render_shadows[render_state.cube_shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->screen_lod_threshold, true, true, true, p_render_data->render_info);
+ _render_shadow_pass(render_state.render_shadows[render_state.cube_shadows[i]].light, p_render_data->shadow_atlas, render_state.render_shadows[render_state.cube_shadows[i]].pass, render_state.render_shadows[render_state.cube_shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, true, true, true, p_render_data->render_info);
}
if (render_state.directional_shadows.size()) {
@@ -3975,11 +4844,11 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
//render directional shadows
for (uint32_t i = 0; i < render_state.directional_shadows.size(); i++) {
- _render_shadow_pass(render_state.render_shadows[render_state.directional_shadows[i]].light, p_render_data->shadow_atlas, render_state.render_shadows[render_state.directional_shadows[i]].pass, render_state.render_shadows[render_state.directional_shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->screen_lod_threshold, false, i == render_state.directional_shadows.size() - 1, false, p_render_data->render_info);
+ _render_shadow_pass(render_state.render_shadows[render_state.directional_shadows[i]].light, p_render_data->shadow_atlas, render_state.render_shadows[render_state.directional_shadows[i]].pass, render_state.render_shadows[render_state.directional_shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, false, i == render_state.directional_shadows.size() - 1, false, p_render_data->render_info);
}
//render positional shadows
for (uint32_t i = 0; i < render_state.shadows.size(); i++) {
- _render_shadow_pass(render_state.render_shadows[render_state.shadows[i]].light, p_render_data->shadow_atlas, render_state.render_shadows[render_state.shadows[i]].pass, render_state.render_shadows[render_state.shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->screen_lod_threshold, i == 0, i == render_state.shadows.size() - 1, true, p_render_data->render_info);
+ _render_shadow_pass(render_state.render_shadows[render_state.shadows[i]].light, p_render_data->shadow_atlas, render_state.render_shadows[render_state.shadows[i]].pass, render_state.render_shadows[render_state.shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, i == 0, i == render_state.shadows.size() - 1, true, p_render_data->render_info);
}
_render_shadow_process();
@@ -4000,9 +4869,40 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
}
if (p_render_data->render_buffers.is_valid()) {
+ if (p_use_ssao || p_use_ssil) {
+ RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers);
+ ERR_FAIL_COND(!rb);
+
+ bool invalidate_uniform_set = false;
+ if (rb->ss_effects.linear_depth.is_null()) {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R16_SFLOAT;
+ tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ tf.width = (rb->width + 1) / 2;
+ tf.height = (rb->height + 1) / 2;
+ tf.mipmaps = 5;
+ tf.array_layers = 4;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ rb->ss_effects.linear_depth = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(rb->ss_effects.linear_depth, "SS Effects Depth");
+ for (uint32_t i = 0; i < tf.mipmaps; i++) {
+ RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.linear_depth, 0, i, 1, RD::TEXTURE_SLICE_2D_ARRAY);
+ rb->ss_effects.linear_depth_slices.push_back(slice);
+ RD::get_singleton()->set_resource_name(slice, "SS Effects Depth Mip " + itos(i) + " ");
+ }
+ invalidate_uniform_set = true;
+ }
+
+ storage->get_effects()->downsample_depth(rb->depth_texture, rb->ss_effects.linear_depth_slices, ssao_quality, ssil_quality, invalidate_uniform_set, ssao_half_size, ssil_half_size, Size2i(rb->width, rb->height), p_render_data->cam_projection);
+ }
+
if (p_use_ssao) {
_process_ssao(p_render_data->render_buffers, p_render_data->environment, p_normal_roughness_buffer, p_render_data->cam_projection);
}
+
+ if (p_use_ssil) {
+ _process_ssil(p_render_data->render_buffers, p_render_data->environment, p_normal_roughness_buffer, p_render_data->cam_projection, p_render_data->cam_transform);
+ }
}
//full barrier here, we need raster, transfer and compute and it depends from the previous work
@@ -4043,12 +4943,12 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
}
}
if (is_volumetric_supported()) {
- _update_volumetric_fog(p_render_data->render_buffers, p_render_data->environment, p_render_data->cam_projection, p_render_data->cam_transform, p_render_data->shadow_atlas, directional_light_count, directional_shadows, positional_light_count, render_state.voxel_gi_count);
+ _update_volumetric_fog(p_render_data->render_buffers, p_render_data->environment, p_render_data->cam_projection, p_render_data->cam_transform, p_render_data->shadow_atlas, directional_light_count, directional_shadows, positional_light_count, render_state.voxel_gi_count, *p_render_data->fog_volumes);
}
}
}
-void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data, RendererScene::RenderInfo *r_render_info) {
+void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data, RendererScene::RenderInfo *r_render_info) {
// getting this here now so we can direct call a bunch of things more easily
RenderBuffers *rb = nullptr;
if (p_render_buffers.is_valid()) {
@@ -4081,6 +4981,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData
render_data.voxel_gi_instances = &p_voxel_gi_instances;
render_data.decals = &p_decals;
render_data.lightmaps = &p_lightmaps;
+ render_data.fog_volumes = &p_fog_volumes;
render_data.environment = p_environment;
render_data.camera_effects = p_camera_effects;
render_data.shadow_atlas = p_shadow_atlas;
@@ -4090,12 +4991,12 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData
// this should be the same for all cameras..
render_data.lod_distance_multiplier = p_camera_data->main_projection.get_lod_multiplier();
- render_data.lod_camera_plane = Plane(p_camera_data->main_transform.get_origin(), -p_camera_data->main_transform.basis.get_axis(Vector3::AXIS_Z));
+ render_data.lod_camera_plane = Plane(-p_camera_data->main_transform.basis.get_axis(Vector3::AXIS_Z), p_camera_data->main_transform.get_origin());
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_DISABLE_LOD) {
- render_data.screen_lod_threshold = 0.0;
+ render_data.screen_mesh_lod_threshold = 0.0;
} else {
- render_data.screen_lod_threshold = p_screen_lod_threshold;
+ render_data.screen_mesh_lod_threshold = p_screen_mesh_lod_threshold;
}
render_state.render_shadows = p_render_shadows;
@@ -4183,9 +5084,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData
if (p_render_buffers.is_valid()) {
/*
_debug_draw_cluster(p_render_buffers);
-
RENDER_TIMESTAMP("Tonemap");
-
_render_buffers_post_process_and_tonemap(&render_data);
*/
@@ -4223,7 +5122,7 @@ void RendererSceneRenderRD::_debug_draw_cluster(RID p_render_buffers) {
}
}
-void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<GeometryInstance *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold, bool p_open_pass, bool p_close_pass, bool p_clear_region, RendererScene::RenderInfo *p_render_info) {
+void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<GeometryInstance *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, bool p_open_pass, bool p_close_pass, bool p_clear_region, RendererScene::RenderInfo *p_render_info) {
LightInstance *light_instance = light_instance_owner.get_or_null(p_light);
ERR_FAIL_COND(!light_instance);
@@ -4373,7 +5272,7 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
if (render_cubemap) {
//rendering to cubemap
- _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, false, false, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_lod_threshold, Rect2(), false, true, true, true, p_render_info);
+ _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, false, false, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, Rect2(), false, true, true, true, p_render_info);
if (finalize_cubemap) {
_render_shadow_process();
_render_shadow_end();
@@ -4391,7 +5290,7 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
} else {
//render shadow
- _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, using_dual_paraboloid, using_dual_paraboloid_flip, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_lod_threshold, atlas_rect, flip_y, p_clear_region, p_open_pass, p_close_pass, p_render_info);
+ _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, using_dual_paraboloid, using_dual_paraboloid_flip, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, atlas_rect, flip_y, p_clear_region, p_open_pass, p_close_pass, p_render_info);
}
}
@@ -4502,7 +5401,8 @@ bool RendererSceneRenderRD::free(RID p_rid) {
} else if (shadow_atlas_owner.owns(p_rid)) {
shadow_atlas_set_size(p_rid, 0);
shadow_atlas_owner.free(p_rid);
-
+ } else if (fog_volume_instance_owner.owns(p_rid)) {
+ fog_volume_instance_owner.free(p_rid);
} else {
return false;
}
@@ -4743,18 +5643,124 @@ void RendererSceneRenderRD::init() {
}
if (is_volumetric_supported()) {
- String defines = "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(cluster.max_directional_lights) + "\n";
- Vector<String> volumetric_fog_modes;
- volumetric_fog_modes.push_back("\n#define MODE_DENSITY\n");
- volumetric_fog_modes.push_back("\n#define MODE_DENSITY\n#define ENABLE_SDFGI\n");
- volumetric_fog_modes.push_back("\n#define MODE_FILTER\n");
- volumetric_fog_modes.push_back("\n#define MODE_FOG\n");
- volumetric_fog.shader.initialize(volumetric_fog_modes, defines);
- volumetric_fog.shader_version = volumetric_fog.shader.version_create();
- for (int i = 0; i < VOLUMETRIC_FOG_SHADER_MAX; i++) {
- volumetric_fog.pipelines[i] = RD::get_singleton()->compute_pipeline_create(volumetric_fog.shader.version_get_shader(volumetric_fog.shader_version, i));
+ {
+ // Initialize local fog shader
+ Vector<String> volumetric_fog_modes;
+ volumetric_fog_modes.push_back("");
+ volumetric_fog.shader.initialize(volumetric_fog_modes);
+
+ storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_FOG, _create_fog_shader_funcs);
+ storage->material_set_data_request_function(RendererStorageRD::SHADER_TYPE_FOG, _create_fog_material_funcs);
+ volumetric_fog.volume_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(VolumetricFogShader::VolumeUBO));
+ }
+
+ {
+ ShaderCompiler::DefaultIdentifierActions actions;
+
+ actions.renames["TIME"] = "scene_params.time";
+ actions.renames["PI"] = _MKSTR(Math_PI);
+ actions.renames["TAU"] = _MKSTR(Math_TAU);
+ actions.renames["E"] = _MKSTR(Math_E);
+ actions.renames["WORLD_POSITION"] = "world.xyz";
+ actions.renames["OBJECT_POSITION"] = "params.position";
+ actions.renames["UVW"] = "uvw";
+ actions.renames["EXTENTS"] = "params.extents";
+ actions.renames["ALBEDO"] = "albedo";
+ actions.renames["DENSITY"] = "density";
+ actions.renames["EMISSION"] = "emission";
+ actions.renames["SDF"] = "sdf";
+
+ actions.usage_defines["SDF"] = "#define SDF_USED\n";
+ actions.usage_defines["DENSITY"] = "#define DENSITY_USED\n";
+ actions.usage_defines["ALBEDO"] = "#define ALBEDO_USED\n";
+ actions.usage_defines["EMISSION"] = "#define EMISSION_USED\n";
+
+ actions.sampler_array_name = "material_samplers";
+ actions.base_texture_binding_index = 1;
+ actions.texture_layout_set = VolumetricFogShader::FogSet::FOG_SET_MATERIAL;
+ actions.base_uniform_string = "material.";
+
+ actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
+ actions.default_repeat = ShaderLanguage::REPEAT_DISABLE;
+ actions.global_buffer_array_variable = "global_variables.data";
+
+ volumetric_fog.compiler.initialize(actions);
+ }
+
+ {
+ // default material and shader for fog shader
+ volumetric_fog.default_shader = storage->shader_allocate();
+ storage->shader_initialize(volumetric_fog.default_shader);
+ storage->shader_set_code(volumetric_fog.default_shader, R"(
+// Default fog shader.
+
+shader_type fog;
+
+void fog() {
+ DENSITY = 1.0;
+ ALBEDO = vec3(1.0);
+}
+)");
+ volumetric_fog.default_material = storage->material_allocate();
+ storage->material_initialize(volumetric_fog.default_material);
+ storage->material_set_shader(volumetric_fog.default_material, volumetric_fog.default_shader);
+
+ FogMaterialData *md = (FogMaterialData *)storage->material_get_data(volumetric_fog.default_material, RendererStorageRD::SHADER_TYPE_FOG);
+ volumetric_fog.default_shader_rd = volumetric_fog.shader.version_get_shader(md->shader_data->version, 0);
+
+ Vector<RD::Uniform> uniforms;
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
+ u.binding = 1;
+ u.ids.resize(12);
+ RID *ids_ptr = u.ids.ptrw();
+ ids_ptr[0] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[1] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[2] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[3] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[4] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[5] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[6] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[7] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[8] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[9] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[10] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[11] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 2;
+ u.ids.push_back(storage->global_variables_get_storage_buffer());
+ uniforms.push_back(u);
+ }
+
+ volumetric_fog.base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.default_shader_rd, VolumetricFogShader::FogSet::FOG_SET_BASE);
+ }
+ {
+ String defines = "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(cluster.max_directional_lights) + "\n";
+ defines += "\n#define MAX_SKY_LOD " + itos(get_roughness_layers() - 1) + ".0\n";
+ if (is_using_radiance_cubemap_array()) {
+ defines += "\n#define USE_RADIANCE_CUBEMAP_ARRAY \n";
+ }
+ Vector<String> volumetric_fog_modes;
+ volumetric_fog_modes.push_back("\n#define MODE_DENSITY\n");
+ volumetric_fog_modes.push_back("\n#define MODE_DENSITY\n#define ENABLE_SDFGI\n");
+ volumetric_fog_modes.push_back("\n#define MODE_FILTER\n");
+ volumetric_fog_modes.push_back("\n#define MODE_FOG\n");
+ volumetric_fog_modes.push_back("\n#define MODE_COPY\n");
+
+ volumetric_fog.process_shader.initialize(volumetric_fog_modes, defines);
+ volumetric_fog.process_shader_version = volumetric_fog.process_shader.version_create();
+ for (int i = 0; i < VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_MAX; i++) {
+ volumetric_fog.process_pipelines[i] = RD::get_singleton()->compute_pipeline_create(volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, i));
+ }
+ volumetric_fog.params_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(VolumetricFogShader::ParamsUBO));
}
- volumetric_fog.params_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(VolumetricFogShader::ParamsUBO));
}
{
@@ -4778,6 +5784,9 @@ void RendererSceneRenderRD::init() {
sss_quality = RS::SubSurfaceScatteringQuality(int(GLOBAL_GET("rendering/environment/subsurface_scattering/subsurface_scattering_quality")));
sss_scale = GLOBAL_GET("rendering/environment/subsurface_scattering/subsurface_scattering_scale");
sss_depth_scale = GLOBAL_GET("rendering/environment/subsurface_scattering/subsurface_scattering_depth_scale");
+
+ environment_set_ssil_quality(RS::EnvironmentSSILQuality(int(GLOBAL_GET("rendering/environment/ssil/quality"))), GLOBAL_GET("rendering/environment/ssil/half_size"), GLOBAL_GET("rendering/environment/ssil/adaptive_target"), GLOBAL_GET("rendering/environment/ssil/blur_passes"), GLOBAL_GET("rendering/environment/ssil/fadeout_from"), GLOBAL_GET("rendering/environment/ssil/fadeout_to"));
+
directional_penumbra_shadow_kernel = memnew_arr(float, 128);
directional_soft_shadow_kernel = memnew_arr(float, 128);
penumbra_shadow_kernel = memnew_arr(float, 128);
@@ -4805,9 +5814,14 @@ RendererSceneRenderRD::~RendererSceneRenderRD() {
if (is_dynamic_gi_supported()) {
gi.free();
+ }
- volumetric_fog.shader.version_free(volumetric_fog.shader_version);
+ if (is_volumetric_supported()) {
+ volumetric_fog.process_shader.version_free(volumetric_fog.process_shader_version);
+ RD::get_singleton()->free(volumetric_fog.volume_ubo);
RD::get_singleton()->free(volumetric_fog.params_ubo);
+ storage->free(volumetric_fog.default_shader);
+ storage->free(volumetric_fog.default_material);
}
RendererSceneSkyRD::SkyMaterialData *md = (RendererSceneSkyRD::SkyMaterialData *)storage->material_get_data(sky.sky_shader.default_material, RendererStorageRD::SHADER_TYPE_SKY);
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
index d74848f0af..276cb8f229 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -40,6 +40,7 @@
#include "servers/rendering/renderer_rd/renderer_scene_sky_rd.h"
#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
#include "servers/rendering/renderer_rd/shaders/volumetric_fog.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl.gen.h"
#include "servers/rendering/renderer_scene.h"
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering/rendering_device.h"
@@ -64,6 +65,7 @@ struct RenderDataRD {
const PagedArray<RID> *voxel_gi_instances = nullptr;
const PagedArray<RID> *decals = nullptr;
const PagedArray<RID> *lightmaps = nullptr;
+ const PagedArray<RID> *fog_volumes = nullptr;
RID environment = RID();
RID camera_effects = RID();
RID shadow_atlas = RID();
@@ -73,7 +75,7 @@ struct RenderDataRD {
float lod_distance_multiplier = 0.0;
Plane lod_camera_plane = Plane();
- float screen_lod_threshold = 0.0;
+ float screen_mesh_lod_threshold = 0.0;
RID cluster_buffer = RID();
uint32_t cluster_size = 0;
@@ -107,7 +109,7 @@ protected:
virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_color) = 0;
virtual void _render_shadow_begin() = 0;
- virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RendererScene::RenderInfo *p_render_info = nullptr) = 0;
+ virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RendererScene::RenderInfo *p_render_info = nullptr) = 0;
virtual void _render_shadow_process() = 0;
virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL) = 0;
@@ -127,12 +129,15 @@ protected:
void _process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection);
void _process_ssr(RID p_render_buffers, RID p_dest_framebuffer, RID p_normal_buffer, RID p_specular_buffer, RID p_metallic, const Color &p_metallic_mask, RID p_environment, const CameraMatrix &p_projection, bool p_use_additive);
void _process_sss(RID p_render_buffers, const CameraMatrix &p_camera);
+ void _process_ssil(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection, const Transform3D &p_transform);
+ void _copy_framebuffer_to_ssil(RID p_render_buffers);
+ void _ensure_ss_effects(RID p_render_buffers, bool p_using_ssil);
bool _needs_post_prepass_render(RenderDataRD *p_render_data, bool p_use_gi);
void _post_prepass_render(RenderDataRD *p_render_data, bool p_use_gi);
void _pre_resolve_render(RenderDataRD *p_render_data, bool p_use_gi);
- void _pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_gi, RID p_normal_roughness_buffer, RID p_voxel_gi_buffer);
+ void _pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, RID p_normal_roughness_buffer, RID p_voxel_gi_buffer);
void _render_buffers_copy_screen_texture(const RenderDataRD *p_render_data);
void _render_buffers_copy_depth_texture(const RenderDataRD *p_render_data);
@@ -393,6 +398,16 @@ private:
mutable RID_Owner<LightInstance> light_instance_owner;
+ /* FOG VOLUMES */
+
+ struct FogVolumeInstance {
+ RID volume;
+ Transform3D transform;
+ bool active = false;
+ };
+
+ mutable RID_Owner<FogVolumeInstance> fog_volume_instance_owner;
+
/* ENVIRONMENT */
RS::EnvironmentSSAOQuality ssao_quality = RS::ENV_SSAO_QUALITY_MEDIUM;
@@ -403,6 +418,14 @@ private:
float ssao_fadeout_from = 50.0;
float ssao_fadeout_to = 300.0;
+ RS::EnvironmentSSILQuality ssil_quality = RS::ENV_SSIL_QUALITY_MEDIUM;
+ bool ssil_half_size = false;
+ bool ssil_using_half_size = false;
+ float ssil_adaptive_target = 0.5;
+ int ssil_blur_passes = 4;
+ float ssil_fadeout_from = 50.0;
+ float ssil_fadeout_to = 300.0;
+
bool glow_bicubic_upscale = false;
bool glow_high_quality = false;
RS::EnvironmentSSRRoughnessQuality ssr_roughness_quality = RS::ENV_SSR_ROUGNESS_QUALITY_LOW;
@@ -444,7 +467,11 @@ private:
struct RenderBuffers {
RenderBufferData *data = nullptr;
- int width = 0, height = 0;
+ int internal_width = 0;
+ int internal_height = 0;
+ int width = 0;
+ int height = 0;
+ float fsr_sharpness = 0.2f;
RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED;
RS::ViewportScreenSpaceAA screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
bool use_debanding = false;
@@ -454,9 +481,12 @@ private:
uint64_t auto_exposure_version = 1;
- RID texture; //main texture for rendering to, must be filled after done rendering
+ RID sss_texture; //texture for sss. This needs to be a different resolution than blur[0]
+ RID internal_texture; //main texture for rendering to, must be filled after done rendering
+ RID texture; //upscaled version of main texture (This uses the same resource as internal_texture if there is no upscaling)
RID depth_texture; //main depth texture
RID texture_fb; // framebuffer for the main texture, ONLY USED FOR MOBILE RENDERER POST EFFECTS, DO NOT USE FOR RENDERING 3D!!!
+ RID upscale_texture; //used when upscaling internal_texture (This uses the same resource as internal_texture if there is no upscaling)
RendererSceneGIRD::SDFGI *sdfgi = nullptr;
VolumetricFog *volumetric_fog = nullptr;
@@ -505,20 +535,47 @@ private:
RID current_fb;
} luminance;
- struct SSAO {
- RID depth;
- Vector<RID> depth_slices;
- RID ao_deinterleaved;
- Vector<RID> ao_deinterleaved_slices;
- RID ao_pong;
- Vector<RID> ao_pong_slices;
- RID ao_final;
- RID importance_map[2];
+ struct SSEffects {
+ RID linear_depth;
+ Vector<RID> linear_depth_slices;
RID downsample_uniform_set;
- RID gather_uniform_set;
- RID importance_map_uniform_set;
- } ssao;
+
+ RID last_frame;
+ Vector<RID> last_frame_slices;
+
+ CameraMatrix last_frame_projection;
+ Transform3D last_frame_transform;
+
+ struct SSAO {
+ RID ao_deinterleaved;
+ Vector<RID> ao_deinterleaved_slices;
+ RID ao_pong;
+ Vector<RID> ao_pong_slices;
+ RID ao_final;
+ RID importance_map[2];
+ RID depth_texture_view;
+
+ RID gather_uniform_set;
+ RID importance_map_uniform_set;
+ } ssao;
+
+ struct SSIL {
+ RID ssil_final;
+ RID deinterleaved;
+ Vector<RID> deinterleaved_slices;
+ RID pong;
+ Vector<RID> pong_slices;
+ RID edges;
+ Vector<RID> edges_slices;
+ RID importance_map[2];
+ RID depth_texture_view;
+
+ RID gather_uniform_set;
+ RID importance_map_uniform_set;
+ RID projection_uniform_set;
+ } ssil;
+ } ss_effects;
struct SSR {
RID normal_scaled;
@@ -718,10 +775,15 @@ private:
RID light_density_map;
RID prev_light_density_map;
-
RID fog_map;
- RID uniform_set;
- RID uniform_set2;
+ RID density_map;
+ RID light_map;
+ RID emissive_map;
+
+ RID fog_uniform_set;
+ RID copy_uniform_set;
+ RID process_uniform_set;
+ RID process_uniform_set2;
RID sdfgi_uniform_set;
RID sky_uniform_set;
@@ -730,30 +792,91 @@ private:
Transform3D prev_cam_transform;
};
- enum {
- VOLUMETRIC_FOG_SHADER_DENSITY,
- VOLUMETRIC_FOG_SHADER_DENSITY_WITH_SDFGI,
- VOLUMETRIC_FOG_SHADER_FILTER,
- VOLUMETRIC_FOG_SHADER_FOG,
- VOLUMETRIC_FOG_SHADER_MAX,
- };
-
struct VolumetricFogShader {
- struct ParamsUBO {
+ enum FogSet {
+ FOG_SET_BASE,
+ FOG_SET_UNIFORMS,
+ FOG_SET_MATERIAL,
+ FOG_SET_MAX,
+ };
+
+ struct FogPushConstant {
+ float position[3];
+ float pad;
+
+ float extents[3];
+ float pad2;
+
+ int32_t corner[3];
+ uint32_t shape;
+
+ float transform[16];
+ };
+
+ struct VolumeUBO {
float fog_frustum_size_begin[2];
float fog_frustum_size_end[2];
float fog_frustum_end;
float z_near;
float z_far;
+ float time;
+
+ int32_t fog_volume_size[3];
+ uint32_t directional_light_count;
+
+ uint32_t use_temporal_reprojection;
+ uint32_t temporal_frame;
+ float detail_spread;
+ float temporal_blend;
+
+ float to_prev_view[16];
+ float transform[16];
+ };
+
+ ShaderCompiler compiler;
+ VolumetricFogShaderRD shader;
+ FogPushConstant push_constant;
+ RID volume_ubo;
+
+ RID default_shader;
+ RID default_material;
+ RID default_shader_rd;
+
+ RID base_uniform_set;
+
+ RID params_ubo;
+
+ enum {
+ VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY,
+ VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI,
+ VOLUMETRIC_FOG_PROCESS_SHADER_FILTER,
+ VOLUMETRIC_FOG_PROCESS_SHADER_FOG,
+ VOLUMETRIC_FOG_PROCESS_SHADER_COPY,
+ VOLUMETRIC_FOG_PROCESS_SHADER_MAX,
+ };
+
+ struct ParamsUBO {
+ float fog_frustum_size_begin[2];
+ float fog_frustum_size_end[2];
+
+ float fog_frustum_end;
+ float ambient_inject;
+ float z_far;
uint32_t filter_axis;
+ float ambient_color[3];
+ float sky_contribution;
+
int32_t fog_volume_size[3];
uint32_t directional_light_count;
- float light_energy[3];
+ float base_emission[3];
float base_density;
+ float base_scattering[3];
+ float phase_g;
+
float detail_spread;
float gi_inject;
uint32_t max_voxel_gi_instances;
@@ -770,13 +893,13 @@ private:
float cam_rotation[12];
float to_prev_view[16];
+ float radiance_inverse_xform[12];
};
- VolumetricFogShaderRD shader;
+ VolumetricFogProcessShaderRD process_shader;
- RID params_ubo;
- RID shader_version;
- RID pipelines[VOLUMETRIC_FOG_SHADER_MAX];
+ RID process_shader_version;
+ RID process_pipelines[VOLUMETRIC_FOG_PROCESS_SHADER_MAX];
} volumetric_fog;
@@ -784,8 +907,56 @@ private:
uint32_t volumetric_fog_size = 128;
bool volumetric_fog_filter_active = true;
+ Vector3i _point_get_position_in_froxel_volume(const Vector3 &p_point, float fog_end, const Vector2 &fog_near_size, const Vector2 &fog_far_size, float volumetric_fog_detail_spread, const Vector3 &fog_size, const Transform3D &p_cam_transform);
void _volumetric_fog_erase(RenderBuffers *rb);
- void _update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count);
+ void _update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes);
+
+ struct FogShaderData : public RendererStorageRD::ShaderData {
+ bool valid;
+ RID version;
+
+ RID pipeline;
+ Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
+ Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
+
+ Vector<uint32_t> ubo_offsets;
+ uint32_t ubo_size;
+
+ String path;
+ String code;
+ Map<StringName, Map<int, RID>> default_texture_params;
+
+ bool uses_time;
+
+ virtual void set_code(const String &p_Code);
+ virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
+ virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
+ virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
+ virtual bool is_param_texture(const StringName &p_param) const;
+ virtual bool is_animated() const;
+ virtual bool casts_shadows() const;
+ virtual Variant get_default_parameter(const StringName &p_parameter) const;
+ virtual RS::ShaderNativeSourceCode get_native_source_code() const;
+ FogShaderData();
+ virtual ~FogShaderData();
+ };
+
+ struct FogMaterialData : public RendererStorageRD::MaterialData {
+ FogShaderData *shader_data;
+ RID uniform_set;
+ bool uniform_set_updated;
+
+ virtual void set_render_priority(int p_priority) {}
+ virtual void set_next_pass(RID p_pass) {}
+ virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
+ virtual ~FogMaterialData();
+ };
+
+ RendererStorageRD::ShaderData *_create_fog_shader_func();
+ static RendererStorageRD::ShaderData *_create_fog_shader_funcs();
+
+ RendererStorageRD::MaterialData *_create_fog_material_func(FogShaderData *p_shader);
+ static RendererStorageRD::MaterialData *_create_fog_material_funcs(RendererStorageRD::ShaderData *p_shader);
RID shadow_sampler;
@@ -801,7 +972,7 @@ private:
uint32_t max_cluster_elements = 512;
- void _render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<GeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_lod_threshold = 0.0, bool p_open_pass = true, bool p_close_pass = true, bool p_clear_region = true, RendererScene::RenderInfo *p_render_info = nullptr);
+ void _render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<GeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_mesh_lod_threshold = 0.0, bool p_open_pass = true, bool p_close_pass = true, bool p_clear_region = true, RendererScene::RenderInfo *p_render_info = nullptr);
public:
virtual Transform3D geometry_instance_get_transform(GeometryInstance *p_instance) = 0;
@@ -904,7 +1075,7 @@ public:
float environment_get_fog_height_density(RID p_env) const;
float environment_get_fog_aerial_perspective(RID p_env) const;
- virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount) override;
+ virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) override;
virtual void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) override;
virtual void environment_set_volumetric_fog_filter_active(bool p_enable) override;
@@ -912,13 +1083,16 @@ public:
virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) override;
virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) override;
virtual void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override;
+ virtual void environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) override;
+ virtual void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override;
bool environment_is_ssao_enabled(RID p_env) const;
float environment_get_ssao_ao_affect(RID p_env) const;
float environment_get_ssao_light_affect(RID p_env) const;
+ bool environment_is_ssil_enabled(RID p_env) const;
bool environment_is_ssr_enabled(RID p_env) const;
bool environment_is_sdfgi_enabled(RID p_env) const;
- virtual void environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) override;
+ virtual void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) override;
virtual void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) override;
virtual void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) override;
virtual void environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update) override;
@@ -931,6 +1105,8 @@ public:
virtual Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) override;
+ /* CAMERA EFFECTS */
+
virtual RID camera_effects_allocate() override;
virtual void camera_effects_initialize(RID p_rid) override;
@@ -946,6 +1122,8 @@ public:
return camfx && (camfx->dof_blur_near_enabled || camfx->dof_blur_far_enabled) && camfx->dof_blur_amount > 0.0;
}
+ /* LIGHT INSTANCE API */
+
virtual RID light_instance_create(RID p_light) override;
virtual void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) override;
virtual void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) override;
@@ -1082,6 +1260,14 @@ public:
return li->light_type;
}
+ /* FOG VOLUMES */
+
+ virtual RID fog_volume_instance_create(RID p_fog_volume) override;
+ virtual void fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) override;
+ virtual void fog_volume_instance_set_active(RID p_fog_volume_instance, bool p_active) override;
+ virtual RID fog_volume_instance_get_volume(RID p_fog_volume_instance) const override;
+ virtual Vector3 fog_volume_instance_get_position(RID p_fog_volume_instance) const override;
+
virtual RID reflection_atlas_create() override;
virtual void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) override;
virtual int reflection_atlas_get_size(RID p_ref_atlas) const override;
@@ -1193,11 +1379,12 @@ public:
virtual RD::DataFormat _render_buffers_get_color_format();
virtual bool _render_buffers_can_be_storage();
virtual RID render_buffers_create() override;
- virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) override;
+ virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) override;
virtual void gi_set_use_half_resolution(bool p_enable) override;
RID render_buffers_get_depth_texture(RID p_render_buffers);
RID render_buffers_get_ao_texture(RID p_render_buffers);
+ RID render_buffers_get_ssil_texture(RID p_render_buffers);
RID render_buffers_get_back_buffer_texture(RID p_render_buffers);
RID render_buffers_get_back_depth_texture(RID p_render_buffers);
RID render_buffers_get_voxel_gi_buffer(RID p_render_buffers);
@@ -1224,7 +1411,9 @@ public:
float render_buffers_get_volumetric_fog_end(RID p_render_buffers);
float render_buffers_get_volumetric_fog_detail_spread(RID p_render_buffers);
- virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override;
+ virtual void update_uniform_sets(){};
+
+ virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override;
virtual void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
index 5814c164cc..856ea5e74d 100644
--- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -46,13 +46,13 @@ void RendererSceneSkyRD::SkyShaderData::set_code(const String &p_code) {
ubo_size = 0;
uniforms.clear();
- if (code == String()) {
+ if (code.is_empty()) {
return; //just invalid, but no error
}
- ShaderCompilerRD::GeneratedCode gen_code;
- ShaderCompilerRD::IdentifierActions actions;
- actions.entry_point_stages["sky"] = ShaderCompilerRD::STAGE_FRAGMENT;
+ ShaderCompiler::GeneratedCode gen_code;
+ ShaderCompiler::IdentifierActions actions;
+ actions.entry_point_stages["sky"] = ShaderCompiler::STAGE_FRAGMENT;
uses_time = false;
uses_half_res = false;
@@ -112,7 +112,7 @@ void RendererSceneSkyRD::SkyShaderData::set_code(const String &p_code) {
print_line("\n**light_code:\n" + gen_code.light);
#endif
- scene_singleton->sky.sky_shader.shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompilerRD::STAGE_VERTEX], gen_code.stage_globals[ShaderCompilerRD::STAGE_FRAGMENT], gen_code.defines);
+ scene_singleton->sky.sky_shader.shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines);
ERR_FAIL_COND(!scene_singleton->sky.sky_shader.shader.version_is_valid(version));
ubo_size = gen_code.uniform_total_size;
@@ -137,11 +137,20 @@ void RendererSceneSkyRD::SkyShaderData::set_code(const String &p_code) {
valid = true;
}
-void RendererSceneSkyRD::SkyShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) {
+void RendererSceneSkyRD::SkyShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
if (!p_texture.is_valid()) {
- default_texture_params.erase(p_name);
+ if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
+ default_texture_params[p_name].erase(p_index);
+
+ if (default_texture_params[p_name].is_empty()) {
+ default_texture_params.erase(p_name);
+ }
+ }
} else {
- default_texture_params[p_name] = p_texture;
+ if (!default_texture_params.has(p_name)) {
+ default_texture_params[p_name] = Map<int, RID>();
+ }
+ default_texture_params[p_name][p_index] = p_texture;
}
}
@@ -292,7 +301,12 @@ void RendererSceneSkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_uniform_set, 1);
}
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_texture_set, 2);
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, sky_scene_state.fog_uniform_set, 3);
+ // Fog uniform set can be invalidated before drawing, so validate at draw time
+ if (sky_scene_state.fog_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sky_scene_state.fog_uniform_set)) {
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, sky_scene_state.fog_uniform_set, 3);
+ } else {
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, sky_scene_state.default_fog_uniform_set, 3);
+ }
}
RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
@@ -346,7 +360,7 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_data(RendererStorageR
mm.framebuffers[k] = RD::get_singleton()->framebuffer_create(fbtex);
}
- layer.views.write[j] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer + i * 6, j, RD::TEXTURE_SLICE_CUBEMAP);
+ layer.views.write[j] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer + i * 6, j, 1, RD::TEXTURE_SLICE_CUBEMAP);
mmw = MAX(1, mmw >> 1);
mmh = MAX(1, mmh >> 1);
@@ -374,7 +388,7 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_data(RendererStorageR
mm.framebuffers[k] = RD::get_singleton()->framebuffer_create(fbtex);
}
- layer.views.write[j] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer, j, RD::TEXTURE_SLICE_CUBEMAP);
+ layer.views.write[j] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer, j, 1, RD::TEXTURE_SLICE_CUBEMAP);
mmw = MAX(1, mmw >> 1);
mmh = MAX(1, mmh >> 1);
@@ -383,7 +397,7 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_data(RendererStorageR
layers.push_back(layer);
}
- radiance_base_cubemap = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer, 0, RD::TEXTURE_SLICE_CUBEMAP);
+ radiance_base_cubemap = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer, 0, 1, RD::TEXTURE_SLICE_CUBEMAP);
RD::get_singleton()->set_resource_name(radiance_base_cubemap, "radiance base cubemap");
RD::TextureFormat tf;
tf.format = p_texture_format;
@@ -404,7 +418,7 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_data(RendererStorageR
ReflectionData::DownsampleLayer::Mipmap &mm = downsampled_layer.mipmaps.write[j];
mm.size.width = mmw;
mm.size.height = mmh;
- mm.view = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), downsampled_radiance_cubemap, 0, j, RD::TEXTURE_SLICE_CUBEMAP);
+ mm.view = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), downsampled_radiance_cubemap, 0, j, 1, RD::TEXTURE_SLICE_CUBEMAP);
RD::get_singleton()->set_resource_name(mm.view, "Downsampled Radiance Cubemap Mip " + itos(j) + " ");
if (prefer_raster_effects) {
// we need a framebuffer for each side of our cubemap
@@ -736,7 +750,6 @@ RendererStorageRD::ShaderData *RendererSceneSkyRD::_create_sky_shader_funcs() {
RendererStorageRD::MaterialData *RendererSceneSkyRD::_create_sky_material_func(SkyShaderData *p_shader) {
SkyMaterialData *material_data = memnew(SkyMaterialData);
material_data->shader_data = p_shader;
- material_data->last_frame = false;
//update will happen later anyway so do nothing.
return material_data;
}
@@ -793,7 +806,7 @@ void RendererSceneSkyRD::init(RendererStorageRD *p_storage) {
storage->material_set_data_request_function(RendererStorageRD::SHADER_TYPE_SKY, _create_sky_material_funcs);
{
- ShaderCompilerRD::DefaultIdentifierActions actions;
+ ShaderCompiler::DefaultIdentifierActions actions;
actions.renames["COLOR"] = "color";
actions.renames["ALPHA"] = "alpha";
@@ -1165,14 +1178,8 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b
} else {
sky_scene_state.ubo.volumetric_fog_detail_spread = 1.0;
}
- }
- RID fog_uniform_set = p_scene_render->render_buffers_get_volumetric_fog_sky_uniform_set(p_render_buffers);
-
- if (fog_uniform_set != RID()) {
- sky_scene_state.fog_uniform_set = fog_uniform_set;
- } else {
- sky_scene_state.fog_uniform_set = sky_scene_state.default_fog_uniform_set;
+ sky_scene_state.fog_uniform_set = p_scene_render->render_buffers_get_volumetric_fog_sky_uniform_set(p_render_buffers);
}
}
diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
index 7f563c9bc4..d81a415c2d 100644
--- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -111,14 +111,14 @@ private:
PipelineCacheRD pipelines[SKY_VERSION_MAX];
Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
- Vector<ShaderCompilerRD::GeneratedCode::Texture> texture_uniforms;
+ Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
Vector<uint32_t> ubo_offsets;
uint32_t ubo_size;
String path;
String code;
- Map<StringName, RID> default_texture_params;
+ Map<StringName, Map<int, RID>> default_texture_params;
bool uses_time;
bool uses_position;
@@ -127,7 +127,7 @@ private:
bool uses_light;
virtual void set_code(const String &p_Code);
- virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
+ virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
@@ -220,7 +220,7 @@ public:
struct SkyShader {
SkyShaderRD shader;
- ShaderCompilerRD compiler;
+ ShaderCompiler compiler;
RID default_shader;
RID default_material;
@@ -228,7 +228,6 @@ public:
} sky_shader;
struct SkyMaterialData : public RendererStorageRD::MaterialData {
- uint64_t last_frame;
SkyShaderData *shader_data;
RID uniform_set;
bool uniform_set_updated;
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
index a7bfea455d..2e63ac57d9 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -324,75 +324,6 @@ Ref<Image> RendererStorageRD::_validate_texture_format(const Ref<Image> &p_image
r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
} break; //unsigned float bc6hu
- case Image::FORMAT_PVRTC1_2: {
- //this is not properly supported by MoltekVK it seems, so best to use ETC2
- if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
- r_format.format = RD::DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG;
- r_format.format_srgb = RD::DATA_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG;
- } else {
- //not supported, reconvert
- r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
- r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
- image->decompress();
- image->convert(Image::FORMAT_RGBA8);
- }
- r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
- r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
- r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
- r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
-
- } break; //pvrtc
- case Image::FORMAT_PVRTC1_2A: {
- //this is not properly supported by MoltekVK it seems, so best to use ETC2
- if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
- r_format.format = RD::DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG;
- r_format.format_srgb = RD::DATA_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG;
- } else {
- //not supported, reconvert
- r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
- r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
- image->decompress();
- image->convert(Image::FORMAT_RGBA8);
- }
- r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
- r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
- r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
- r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
- } break;
- case Image::FORMAT_PVRTC1_4: {
- //this is not properly supported by MoltekVK it seems, so best to use ETC2
- if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
- r_format.format = RD::DATA_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG;
- r_format.format_srgb = RD::DATA_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG;
- } else {
- //not supported, reconvert
- r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
- r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
- image->decompress();
- image->convert(Image::FORMAT_RGBA8);
- }
- r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
- r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
- r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
- r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
- } break;
- case Image::FORMAT_PVRTC1_4A: {
- //this is not properly supported by MoltekVK it seems, so best to use ETC2
- if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
- r_format.format = RD::DATA_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG;
- r_format.format_srgb = RD::DATA_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG;
- } else {
- //not supported, reconvert
- r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
- r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
- image->decompress();
- image->convert(Image::FORMAT_RGBA8);
- }
- r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
- r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
- r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
- r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
- } break;
case Image::FORMAT_ETC2_R11: {
if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
r_format.format = RD::DATA_FORMAT_EAC_R11_UNORM_BLOCK;
@@ -971,12 +902,7 @@ void RendererStorageRD::texture_2d_placeholder_initialize(RID p_texture) {
Ref<Image> image;
image.instantiate();
image->create(4, 4, false, Image::FORMAT_RGBA8);
-
- for (int i = 0; i < 4; i++) {
- for (int j = 0; j < 4; j++) {
- image->set_pixel(i, j, Color(1, 0, 1, 1));
- }
- }
+ image->fill(Color(1, 0, 1, 1));
texture_2d_initialize(p_texture, image);
}
@@ -987,12 +913,7 @@ void RendererStorageRD::texture_2d_layered_placeholder_initialize(RID p_texture,
Ref<Image> image;
image.instantiate();
image->create(4, 4, false, Image::FORMAT_RGBA8);
-
- for (int i = 0; i < 4; i++) {
- for (int j = 0; j < 4; j++) {
- image->set_pixel(i, j, Color(1, 0, 1, 1));
- }
- }
+ image->fill(Color(1, 0, 1, 1));
Vector<Ref<Image>> images;
if (p_layered_type == RS::TEXTURE_LAYERED_2D_ARRAY) {
@@ -1013,12 +934,7 @@ void RendererStorageRD::texture_3d_placeholder_initialize(RID p_texture) {
Ref<Image> image;
image.instantiate();
image->create(4, 4, false, Image::FORMAT_RGBA8);
-
- for (int i = 0; i < 4; i++) {
- for (int j = 0; j < 4; j++) {
- image->set_pixel(i, j, Color(1, 0, 1, 1));
- }
- }
+ image->fill(Color(1, 0, 1, 1));
Vector<Ref<Image>> images;
//cube
@@ -1034,7 +950,7 @@ Ref<Image> RendererStorageRD::texture_2d_get(RID p_texture) const {
ERR_FAIL_COND_V(!tex, Ref<Image>());
#ifdef TOOLS_ENABLED
- if (tex->image_cache_2d.is_valid()) {
+ if (tex->image_cache_2d.is_valid() && !tex->is_render_target) {
return tex->image_cache_2d;
}
#endif
@@ -1049,7 +965,7 @@ Ref<Image> RendererStorageRD::texture_2d_get(RID p_texture) const {
}
#ifdef TOOLS_ENABLED
- if (Engine::get_singleton()->is_editor_hint()) {
+ if (Engine::get_singleton()->is_editor_hint() && !tex->is_render_target) {
tex->image_cache_2d = image;
}
#endif
@@ -1089,7 +1005,7 @@ Vector<Ref<Image>> RendererStorageRD::texture_3d_get(RID p_texture) const {
const Texture::BufferSlice3D &bs = tex->buffer_slices_3d[i];
ERR_FAIL_COND_V(bs.offset >= (uint32_t)all_data.size(), Vector<Ref<Image>>());
ERR_FAIL_COND_V(bs.offset + bs.buffer_size > (uint32_t)all_data.size(), Vector<Ref<Image>>());
- Vector<uint8_t> sub_region = all_data.subarray(bs.offset, bs.offset + bs.buffer_size - 1);
+ Vector<uint8_t> sub_region = all_data.slice(bs.offset, bs.offset + bs.buffer_size);
Ref<Image> img;
img.instantiate();
@@ -1227,6 +1143,100 @@ RendererStorageRD::CanvasTexture::~CanvasTexture() {
clear_sets();
}
+void RendererStorageRD::sampler_rd_configure_custom(float p_mipmap_bias) {
+ for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
+ for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
+ RD::SamplerState sampler_state;
+ switch (i) {
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler_state.max_lod = 0;
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
+ sampler_state.max_lod = 0;
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
+ if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+ } else {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+ }
+ sampler_state.lod_bias = p_mipmap_bias;
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
+ if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+ } else {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+ }
+ sampler_state.lod_bias = p_mipmap_bias;
+
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
+ if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+ } else {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+ }
+ sampler_state.lod_bias = p_mipmap_bias;
+ sampler_state.use_anisotropy = true;
+ sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level"));
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
+ if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+ } else {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+ }
+ sampler_state.lod_bias = p_mipmap_bias;
+ sampler_state.use_anisotropy = true;
+ sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level"));
+
+ } break;
+ default: {
+ }
+ }
+ switch (j) {
+ case RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED: {
+ sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
+ sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
+ sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
+
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED: {
+ sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_REPEAT;
+ sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_REPEAT;
+ sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_REPEAT;
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR: {
+ sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
+ sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
+ sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
+ } break;
+ default: {
+ }
+ }
+
+ if (custom_rd_samplers[i][j].is_valid()) {
+ RD::get_singleton()->free(custom_rd_samplers[i][j]);
+ }
+
+ custom_rd_samplers[i][j] = RD::get_singleton()->sampler_create(sampler_state);
+ }
+ }
+}
+
RID RendererStorageRD::canvas_texture_allocate() {
return canvas_texture_owner.allocate_rid();
}
@@ -1399,6 +1409,8 @@ void RendererStorageRD::shader_set_code(RID p_shader, const String &p_code) {
new_type = SHADER_TYPE_3D;
} else if (mode_string == "sky") {
new_type = SHADER_TYPE_SKY;
+ } else if (mode_string == "fog") {
+ new_type = SHADER_TYPE_FOG;
} else {
new_type = SHADER_TYPE_MAX;
}
@@ -1438,8 +1450,10 @@ void RendererStorageRD::shader_set_code(RID p_shader, const String &p_code) {
}
if (shader->data) {
- for (const KeyValue<StringName, RID> &E : shader->default_texture_parameter) {
- shader->data->set_default_texture_param(E.key, E.value);
+ for (const KeyValue<StringName, Map<int, RID>> &E : shader->default_texture_parameter) {
+ for (const KeyValue<int, RID> &E2 : E.value) {
+ shader->data->set_default_texture_param(E.key, E2.value, E2.key);
+ }
}
}
}
@@ -1469,17 +1483,26 @@ void RendererStorageRD::shader_get_param_list(RID p_shader, List<PropertyInfo> *
}
}
-void RendererStorageRD::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) {
+void RendererStorageRD::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) {
Shader *shader = shader_owner.get_or_null(p_shader);
ERR_FAIL_COND(!shader);
if (p_texture.is_valid() && texture_owner.owns(p_texture)) {
- shader->default_texture_parameter[p_name] = p_texture;
+ if (!shader->default_texture_parameter.has(p_name)) {
+ shader->default_texture_parameter[p_name] = Map<int, RID>();
+ }
+ shader->default_texture_parameter[p_name][p_index] = p_texture;
} else {
- shader->default_texture_parameter.erase(p_name);
+ if (shader->default_texture_parameter.has(p_name) && shader->default_texture_parameter[p_name].has(p_index)) {
+ shader->default_texture_parameter[p_name].erase(p_index);
+
+ if (shader->default_texture_parameter[p_name].is_empty()) {
+ shader->default_texture_parameter.erase(p_name);
+ }
+ }
}
if (shader->data) {
- shader->data->set_default_texture_param(p_name, p_texture);
+ shader->data->set_default_texture_param(p_name, p_texture, p_index);
}
for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) {
Material *material = E->get();
@@ -1487,11 +1510,11 @@ void RendererStorageRD::shader_set_default_texture_param(RID p_shader, const Str
}
}
-RID RendererStorageRD::shader_get_default_texture_param(RID p_shader, const StringName &p_name) const {
+RID RendererStorageRD::shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const {
Shader *shader = shader_owner.get_or_null(p_shader);
ERR_FAIL_COND_V(!shader, RID());
- if (shader->default_texture_parameter.has(p_name)) {
- return shader->default_texture_parameter[p_name];
+ if (shader->default_texture_parameter.has(p_name) && shader->default_texture_parameter[p_name].has(p_index)) {
+ return shader->default_texture_parameter[p_name][p_index];
}
return RID();
@@ -1532,14 +1555,14 @@ void RendererStorageRD::material_initialize(RID p_rid) {
}
void RendererStorageRD::_material_queue_update(Material *material, bool p_uniform, bool p_texture) {
+ material->uniform_dirty = material->uniform_dirty || p_uniform;
+ material->texture_dirty = material->texture_dirty || p_texture;
+
if (material->update_element.in_list()) {
return;
}
material_update_list.add(&material->update_element);
-
- material->uniform_dirty = material->uniform_dirty || p_uniform;
- material->texture_dirty = material->texture_dirty || p_texture;
}
void RendererStorageRD::material_set_shader(RID p_material, RID p_shader) {
@@ -2520,7 +2543,7 @@ void RendererStorageRD::MaterialData::update_uniform_buffer(const Map<StringName
}
if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
- continue; //instance uniforms don't appear in the bufferr
+ continue; //instance uniforms don't appear in the buffer
}
if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) {
@@ -2545,7 +2568,17 @@ void RendererStorageRD::MaterialData::update_uniform_buffer(const Map<StringName
//regular uniform
uint32_t offset = p_uniform_offsets[E.value.order];
#ifdef DEBUG_ENABLED
- uint32_t size = ShaderLanguage::get_type_size(E.value.type);
+ uint32_t size = 0U;
+ // The following code enforces a 16-byte alignment of uniform arrays.
+ if (E.value.array_size > 0) {
+ size = ShaderLanguage::get_datatype_size(E.value.type) * E.value.array_size;
+ int m = (16 * E.value.array_size);
+ if ((size % m) != 0U) {
+ size += m - (size % m);
+ }
+ } else {
+ size = ShaderLanguage::get_datatype_size(E.value.type);
+ }
ERR_CONTINUE(offset + size > p_buffer_size);
#endif
uint8_t *data = &p_buffer[offset];
@@ -2608,7 +2641,7 @@ RendererStorageRD::MaterialData::~MaterialData() {
}
}
-void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, RID> &p_default_textures, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) {
+void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, Map<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) {
RendererStorageRD *singleton = (RendererStorageRD *)RendererStorage::base_singleton;
#ifdef TOOLS_ENABLED
Texture *roughness_detect_texture = nullptr;
@@ -2671,17 +2704,19 @@ void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Vari
if (uniform_array_size > 0) {
if (textures.size() < uniform_array_size) {
- const Map<StringName, RID>::Element *W = p_default_textures.find(uniform_name);
- if (W) {
- for (int j = textures.size(); j < uniform_array_size; j++) {
- textures.push_back(W->get());
+ const Map<StringName, Map<int, RID>>::Element *W = p_default_textures.find(uniform_name);
+ for (int j = textures.size(); j < uniform_array_size; j++) {
+ if (W && W->get().has(j)) {
+ textures.push_back(W->get()[j]);
+ } else {
+ textures.push_back(RID());
}
}
}
} else if (textures.is_empty()) {
- const Map<StringName, RID>::Element *W = p_default_textures.find(uniform_name);
- if (W) {
- textures.push_back(W->get());
+ const Map<StringName, Map<int, RID>>::Element *W = p_default_textures.find(uniform_name);
+ if (W && W->get().has(0)) {
+ textures.push_back(W->get()[0]);
}
}
}
@@ -2690,23 +2725,62 @@ void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Vari
if (textures.is_empty()) {
//check default usage
- switch (p_texture_uniforms[i].hint) {
- case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK:
- case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: {
- rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_BLACK);
+ switch (p_texture_uniforms[i].type) {
+ case ShaderLanguage::TYPE_ISAMPLER2D:
+ case ShaderLanguage::TYPE_USAMPLER2D:
+ case ShaderLanguage::TYPE_SAMPLER2D: {
+ switch (p_texture_uniforms[i].hint) {
+ case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK:
+ case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: {
+ rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_BLACK);
+ } break;
+ case ShaderLanguage::ShaderNode::Uniform::HINT_ANISOTROPY: {
+ rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_ANISO);
+ } break;
+ case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: {
+ rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL);
+ } break;
+ case ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL: {
+ rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL);
+ } break;
+ default: {
+ rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE);
+ } break;
+ }
} break;
- case ShaderLanguage::ShaderNode::Uniform::HINT_NONE: {
- rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL);
+
+ case ShaderLanguage::TYPE_SAMPLERCUBE: {
+ switch (p_texture_uniforms[i].hint) {
+ case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK:
+ case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: {
+ rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
+ } break;
+ default: {
+ rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_WHITE);
+ } break;
+ }
} break;
- case ShaderLanguage::ShaderNode::Uniform::HINT_ANISO: {
- rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_ANISO);
+ case ShaderLanguage::TYPE_SAMPLERCUBEARRAY: {
+ rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK);
} break;
- default: {
- rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE);
+
+ case ShaderLanguage::TYPE_ISAMPLER3D:
+ case ShaderLanguage::TYPE_USAMPLER3D:
+ case ShaderLanguage::TYPE_SAMPLER3D: {
+ rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_3D_WHITE);
+ } break;
+
+ case ShaderLanguage::TYPE_ISAMPLER2DARRAY:
+ case ShaderLanguage::TYPE_USAMPLER2DARRAY:
+ case ShaderLanguage::TYPE_SAMPLER2DARRAY: {
+ rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
} break;
+
+ default: {
+ }
}
#ifdef TOOLS_ENABLED
- if (roughness_detect_texture && normal_detect_texture && normal_detect_texture->path != String()) {
+ if (roughness_detect_texture && normal_detect_texture && !normal_detect_texture->path.is_empty()) {
roughness_detect_texture->detect_roughness_callback(roughness_detect_texture->detect_roughness_callback_ud, normal_detect_texture->path, roughness_channel);
}
#endif
@@ -2746,7 +2820,7 @@ void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Vari
rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE);
}
#ifdef TOOLS_ENABLED
- if (roughness_detect_texture && normal_detect_texture && normal_detect_texture->path != String()) {
+ if (roughness_detect_texture && normal_detect_texture && !normal_detect_texture->path.is_empty()) {
roughness_detect_texture->detect_roughness_callback(roughness_detect_texture->detect_roughness_callback_ud, normal_detect_texture->path, roughness_channel);
}
#endif
@@ -2793,7 +2867,7 @@ void RendererStorageRD::MaterialData::free_parameters_uniform_set(RID p_uniform_
}
}
-bool RendererStorageRD::MaterialData::update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, RID> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier) {
+bool RendererStorageRD::MaterialData::update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, Map<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier) {
if ((uint32_t)ubo_data.size() != p_ubo_size) {
p_uniform_dirty = true;
if (uniform_buffer.is_valid()) {
@@ -2817,7 +2891,7 @@ bool RendererStorageRD::MaterialData::update_parameters_uniform_set(const Map<St
//check whether buffer changed
if (p_uniform_dirty && ubo_data.size()) {
- update_uniform_buffer(p_uniforms, p_uniform_offsets, p_parameters, ubo_data.ptrw(), ubo_data.size(), false);
+ update_uniform_buffer(p_uniforms, p_uniform_offsets, p_parameters, ubo_data.ptrw(), ubo_data.size(), true);
RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw(), p_barrier);
}
@@ -2888,24 +2962,19 @@ bool RendererStorageRD::MaterialData::update_parameters_uniform_set(const Map<St
return true;
}
-void RendererStorageRD::_material_uniform_set_erased(const RID &p_set, void *p_material) {
+void RendererStorageRD::_material_uniform_set_erased(void *p_material) {
RID rid = *(RID *)p_material;
Material *material = base_singleton->material_owner.get_or_null(rid);
if (material) {
+ if (material->data) {
+ // Uniform set may be gone because a dependency was erased. This happens
+ // if a texture is deleted, so re-create it.
+ base_singleton->_material_queue_update(material, false, true);
+ }
material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);
}
}
-void RendererStorageRD::material_force_update_textures(RID p_material, ShaderType p_shader_type) {
- Material *material = material_owner.get_or_null(p_material);
- if (material->shader_type != p_shader_type) {
- return;
- }
- if (material->data) {
- material->data->update_parameters(material->params, false, true);
- }
-}
-
void RendererStorageRD::_update_queued_materials() {
while (material_update_list.first()) {
Material *material = material_update_list.first()->self();
@@ -3720,7 +3789,7 @@ void RendererStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Surf
} break;
case RS::ARRAY_WEIGHTS: {
//assumed weights too
- vd.format = RD::DATA_FORMAT_R32G32B32A32_UINT;
+ vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
} break;
}
} else {
@@ -4379,7 +4448,8 @@ void RendererStorageRD::_update_dirty_multimeshes() {
if (multimesh->data_cache_dirty_regions[i]) {
uint32_t offset = i * region_size;
uint32_t size = multimesh->stride_cache * (uint32_t)multimesh->instances * (uint32_t)sizeof(float);
- RD::get_singleton()->buffer_update(multimesh->buffer, offset, MIN(region_size, size - offset), &data[i * region_size]);
+ uint32_t region_start_index = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * i;
+ RD::get_singleton()->buffer_update(multimesh->buffer, offset, MIN(region_size, size - offset), &data[region_start_index]);
}
}
}
@@ -5664,14 +5734,14 @@ void RendererStorageRD::ParticlesShaderData::set_code(const String &p_code) {
uniforms.clear();
uses_collision = false;
- if (code == String()) {
+ if (code.is_empty()) {
return; //just invalid, but no error
}
- ShaderCompilerRD::GeneratedCode gen_code;
- ShaderCompilerRD::IdentifierActions actions;
- actions.entry_point_stages["start"] = ShaderCompilerRD::STAGE_COMPUTE;
- actions.entry_point_stages["process"] = ShaderCompilerRD::STAGE_COMPUTE;
+ ShaderCompiler::GeneratedCode gen_code;
+ ShaderCompiler::IdentifierActions actions;
+ actions.entry_point_stages["start"] = ShaderCompiler::STAGE_COMPUTE;
+ actions.entry_point_stages["process"] = ShaderCompiler::STAGE_COMPUTE;
/*
uses_time = false;
@@ -5693,7 +5763,7 @@ void RendererStorageRD::ParticlesShaderData::set_code(const String &p_code) {
version = base_singleton->particles_shader.shader.version_create();
}
- base_singleton->particles_shader.shader.version_set_compute_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompilerRD::STAGE_COMPUTE], gen_code.defines);
+ base_singleton->particles_shader.shader.version_set_compute_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_COMPUTE], gen_code.defines);
ERR_FAIL_COND(!base_singleton->particles_shader.shader.version_is_valid(version));
ubo_size = gen_code.uniform_total_size;
@@ -5707,11 +5777,20 @@ void RendererStorageRD::ParticlesShaderData::set_code(const String &p_code) {
valid = true;
}
-void RendererStorageRD::ParticlesShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) {
+void RendererStorageRD::ParticlesShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
if (!p_texture.is_valid()) {
- default_texture_params.erase(p_name);
+ if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
+ default_texture_params[p_name].erase(p_index);
+
+ if (default_texture_params[p_name].is_empty()) {
+ default_texture_params.erase(p_name);
+ }
+ }
} else {
- default_texture_params[p_name] = p_texture;
+ if (!default_texture_params.has(p_name)) {
+ default_texture_params[p_name] = Map<int, RID>();
+ }
+ default_texture_params[p_name][p_index] = p_texture;
}
}
@@ -5798,8 +5877,6 @@ RendererStorageRD::ShaderData *RendererStorageRD::_create_particles_shader_func(
}
bool RendererStorageRD::ParticlesMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
- uniform_set_updated = true;
-
return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, base_singleton->particles_shader.shader.version_get_shader(shader_data->version, 0), 3);
}
@@ -5810,7 +5887,6 @@ RendererStorageRD::ParticlesMaterialData::~ParticlesMaterialData() {
RendererStorageRD::MaterialData *RendererStorageRD::_create_particles_material_func(ParticlesShaderData *p_shader) {
ParticlesMaterialData *material_data = memnew(ParticlesMaterialData);
material_data->shader_data = p_shader;
- material_data->last_frame = false;
//update will happen later anyway so do nothing.
return material_data;
}
@@ -6000,6 +6076,82 @@ void RendererStorageRD::particles_collision_instance_set_active(RID p_collision_
pci->active = p_active;
}
+/* FOG VOLUMES */
+
+RID RendererStorageRD::fog_volume_allocate() {
+ return fog_volume_owner.allocate_rid();
+}
+void RendererStorageRD::fog_volume_initialize(RID p_rid) {
+ fog_volume_owner.initialize_rid(p_rid, FogVolume());
+}
+
+void RendererStorageRD::fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) {
+ FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
+ ERR_FAIL_COND(!fog_volume);
+
+ if (p_shape == fog_volume->shape) {
+ return;
+ }
+
+ fog_volume->shape = p_shape;
+ fog_volume->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
+}
+
+void RendererStorageRD::fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) {
+ FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
+ ERR_FAIL_COND(!fog_volume);
+
+ fog_volume->extents = p_extents;
+ fog_volume->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
+}
+
+void RendererStorageRD::fog_volume_set_material(RID p_fog_volume, RID p_material) {
+ FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
+ ERR_FAIL_COND(!fog_volume);
+ fog_volume->material = p_material;
+}
+
+RID RendererStorageRD::fog_volume_get_material(RID p_fog_volume) const {
+ FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
+ ERR_FAIL_COND_V(!fog_volume, RID());
+
+ return fog_volume->material;
+}
+
+RS::FogVolumeShape RendererStorageRD::fog_volume_get_shape(RID p_fog_volume) const {
+ FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
+ ERR_FAIL_COND_V(!fog_volume, RS::FOG_VOLUME_SHAPE_BOX);
+
+ return fog_volume->shape;
+}
+
+AABB RendererStorageRD::fog_volume_get_aabb(RID p_fog_volume) const {
+ FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
+ ERR_FAIL_COND_V(!fog_volume, AABB());
+
+ switch (fog_volume->shape) {
+ case RS::FOG_VOLUME_SHAPE_ELLIPSOID:
+ case RS::FOG_VOLUME_SHAPE_BOX: {
+ AABB aabb;
+ aabb.position = -fog_volume->extents;
+ aabb.size = fog_volume->extents * 2;
+ return aabb;
+ }
+ default: {
+ // Need some size otherwise will get culled
+ return AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2));
+ }
+ }
+
+ return AABB();
+}
+
+Vector3 RendererStorageRD::fog_volume_get_extents(RID p_fog_volume) const {
+ const FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
+ ERR_FAIL_COND_V(!fog_volume, Vector3());
+ return fog_volume->extents;
+}
+
/* VISIBILITY NOTIFIER */
RID RendererStorageRD::visibility_notifier_allocate() {
@@ -6636,11 +6788,11 @@ void RendererStorageRD::reflection_probe_set_resolution(RID p_probe, int p_resol
reflection_probe->resolution = p_resolution;
}
-void RendererStorageRD::reflection_probe_set_lod_threshold(RID p_probe, float p_ratio) {
+void RendererStorageRD::reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) {
ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
ERR_FAIL_COND(!reflection_probe);
- reflection_probe->lod_threshold = p_ratio;
+ reflection_probe->mesh_lod_threshold = p_ratio;
reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);
}
@@ -6698,11 +6850,11 @@ float RendererStorageRD::reflection_probe_get_origin_max_distance(RID p_probe) c
return reflection_probe->max_distance;
}
-float RendererStorageRD::reflection_probe_get_lod_threshold(RID p_probe) const {
+float RendererStorageRD::reflection_probe_get_mesh_lod_threshold(RID p_probe) const {
const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
ERR_FAIL_COND_V(!reflection_probe, 0);
- return reflection_probe->lod_threshold;
+ return reflection_probe->mesh_lod_threshold;
}
int RendererStorageRD::reflection_probe_get_resolution(RID p_probe) const {
@@ -8081,6 +8233,9 @@ void RendererStorageRD::base_update_dependency(RID p_base, DependencyTracker *p_
} else if (particles_collision_owner.owns(p_base)) {
ParticlesCollision *pc = particles_collision_owner.get_or_null(p_base);
p_instance->update_dependency(&pc->dependency);
+ } else if (fog_volume_owner.owns(p_base)) {
+ FogVolume *fv = fog_volume_owner.get_or_null(p_base);
+ p_instance->update_dependency(&fv->dependency);
} else if (visibility_notifier_owner.owns(p_base)) {
VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_base);
p_instance->update_dependency(&vn->dependency);
@@ -8122,6 +8277,9 @@ RS::InstanceType RendererStorageRD::get_base_type(RID p_rid) const {
if (particles_collision_owner.owns(p_rid)) {
return RS::INSTANCE_PARTICLES_COLLISION;
}
+ if (fog_volume_owner.owns(p_rid)) {
+ return RS::INSTANCE_FOG_VOLUME;
+ }
if (visibility_notifier_owner.owns(p_rid)) {
return RS::INSTANCE_VISIBLITY_NOTIFIER;
}
@@ -8987,7 +9145,7 @@ void RendererStorageRD::_update_global_variables() {
for (uint32_t i = 0; i < total_regions; i++) {
if (global_variables.buffer_dirty_regions[i]) {
- RD::get_singleton()->buffer_update(global_variables.buffer, i * region_byte_size, region_byte_size, global_variables.buffer_values);
+ RD::get_singleton()->buffer_update(global_variables.buffer, i * region_byte_size, region_byte_size, &global_variables.buffer_values[i * GlobalVariables::BUFFER_DIRTY_REGION_SIZE]);
global_variables.buffer_dirty_regions[i] = false;
}
@@ -9018,7 +9176,6 @@ void RendererStorageRD::_update_global_variables() {
ERR_CONTINUE(!material); //wtf
_material_queue_update(material, false, true);
- print_line("update material texture?");
}
global_variables.must_update_texture_materials = false;
@@ -9050,10 +9207,6 @@ bool RendererStorageRD::has_os_feature(const String &p_feature) const {
return true;
}
- if (p_feature == "pvrtc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG, RD::TEXTURE_USAGE_SAMPLING_BIT)) {
- return true;
- }
-
return false;
}
@@ -9204,6 +9357,10 @@ bool RendererStorageRD::free(RID p_rid) {
visibility_notifier_owner.free(p_rid);
} else if (particles_collision_instance_owner.owns(p_rid)) {
particles_collision_instance_owner.free(p_rid);
+ } else if (fog_volume_owner.owns(p_rid)) {
+ FogVolume *fog_volume = fog_volume_owner.get_or_null(p_rid);
+ fog_volume->dependency.deleted_notify(p_rid);
+ fog_volume_owner.free(p_rid);
} else if (render_target_owner.owns(p_rid)) {
RenderTarget *rt = render_target_owner.get_or_null(p_rid);
@@ -9279,10 +9436,15 @@ uint64_t RendererStorageRD::get_rendering_info(RS::RenderingInfo p_info) {
String RendererStorageRD::get_video_adapter_name() const {
return RenderingDevice::get_singleton()->get_device_name();
}
+
String RendererStorageRD::get_video_adapter_vendor() const {
return RenderingDevice::get_singleton()->get_device_vendor_name();
}
+RenderingDevice::DeviceType RendererStorageRD::get_video_adapter_type() const {
+ return RenderingDevice::get_singleton()->get_device_type();
+}
+
RendererStorageRD *RendererStorageRD::base_singleton = nullptr;
RendererStorageRD::RendererStorageRD() {
@@ -9500,6 +9662,18 @@ RendererStorageRD::RendererStorageRD() {
{
Vector<Vector<uint8_t>> vpv;
vpv.push_back(pv);
+ default_rd_textures[DEFAULT_RD_TEXTURE_3D_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
+ }
+ for (int i = 0; i < 64; i++) {
+ pv.set(i * 4 + 0, 255);
+ pv.set(i * 4 + 1, 255);
+ pv.set(i * 4 + 2, 255);
+ pv.set(i * 4 + 3, 255);
+ }
+
+ {
+ Vector<Vector<uint8_t>> vpv;
+ vpv.push_back(pv);
default_rd_textures[DEFAULT_RD_TEXTURE_3D_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
}
}
@@ -9615,6 +9789,9 @@ RendererStorageRD::RendererStorageRD() {
}
}
+ //custom sampler
+ sampler_rd_configure_custom(0.0f);
+
//default rd buffers
{
Vector<uint8_t> buffer;
@@ -9758,7 +9935,7 @@ RendererStorageRD::RendererStorageRD() {
material_set_data_request_function(RendererStorageRD::SHADER_TYPE_PARTICLES, _create_particles_material_funcs);
{
- ShaderCompilerRD::DefaultIdentifierActions actions;
+ ShaderCompiler::DefaultIdentifierActions actions;
actions.renames["COLOR"] = "PARTICLE.color";
actions.renames["VELOCITY"] = "PARTICLE.velocity";
@@ -9767,7 +9944,7 @@ RendererStorageRD::RendererStorageRD() {
actions.renames["RESTART"] = "restart";
actions.renames["CUSTOM"] = "PARTICLE.custom";
actions.renames["TRANSFORM"] = "PARTICLE.xform";
- actions.renames["TIME"] = "FRAME.time";
+ actions.renames["TIME"] = "frame_history.data[0].time";
actions.renames["PI"] = _MKSTR(Math_PI);
actions.renames["TAU"] = _MKSTR(Math_TAU);
actions.renames["E"] = _MKSTR(Math_E);
@@ -9945,6 +10122,15 @@ RendererStorageRD::~RendererStorageRD() {
}
}
+ //custom samplers
+ for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
+ for (int j = 0; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
+ if (custom_rd_samplers[i][j].is_valid()) {
+ RD::get_singleton()->free(custom_rd_samplers[i][j]);
+ }
+ }
+ }
+
//def buffers
for (int i = 0; i < DEFAULT_RD_BUFFER_MAX; i++) {
RD::get_singleton()->free(mesh_default_rd_buffers[i]);
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h
index d6129bb57b..43bbcf6520 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.h
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -36,7 +36,6 @@
#include "core/templates/rid_owner.h"
#include "servers/rendering/renderer_compositor.h"
#include "servers/rendering/renderer_rd/effects_rd.h"
-#include "servers/rendering/renderer_rd/shader_compiler_rd.h"
#include "servers/rendering/renderer_rd/shaders/canvas_sdf.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/particles.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/particles_copy.glsl.gen.h"
@@ -44,6 +43,7 @@
#include "servers/rendering/renderer_rd/shaders/voxel_gi_sdf.glsl.gen.h"
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering/rendering_device.h"
+#include "servers/rendering/shader_compiler.h"
class RendererStorageRD : public RendererStorage {
public:
static _FORCE_INLINE_ void store_transform(const Transform3D &p_mtx, float *p_array) {
@@ -129,12 +129,13 @@ public:
SHADER_TYPE_3D,
SHADER_TYPE_PARTICLES,
SHADER_TYPE_SKY,
+ SHADER_TYPE_FOG,
SHADER_TYPE_MAX
};
struct ShaderData {
virtual void set_code(const String &p_Code) = 0;
- virtual void set_default_texture_param(const StringName &p_name, RID p_texture) = 0;
+ virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) = 0;
virtual void get_param_list(List<PropertyInfo> *p_param_list) const = 0;
virtual void get_instance_param_list(List<InstanceShaderParam> *p_param_list) const = 0;
@@ -151,7 +152,7 @@ public:
struct MaterialData {
void update_uniform_buffer(const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Map<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color);
- void update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, RID> &p_default_textures, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color);
+ void update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, Map<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color);
virtual void set_render_priority(int p_priority) = 0;
virtual void set_next_pass(RID p_pass) = 0;
@@ -159,7 +160,7 @@ public:
virtual ~MaterialData();
//to be used internally by update_parameters, in the most common configuration of material parameters
- bool update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, RID> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier = RD::BARRIER_MASK_ALL);
+ bool update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, Map<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier = RD::BARRIER_MASK_ALL);
void free_parameters_uniform_set(RID p_uniform_set);
private:
@@ -176,7 +177,7 @@ public:
Vector<RID> texture_cache;
};
typedef MaterialData *(*MaterialDataRequestFunction)(ShaderData *);
- static void _material_uniform_set_erased(const RID &p_set, void *p_material);
+ static void _material_uniform_set_erased(void *p_material);
enum DefaultRDTexture {
DEFAULT_RD_TEXTURE_WHITE,
@@ -188,6 +189,7 @@ public:
DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK,
DEFAULT_RD_TEXTURE_CUBEMAP_WHITE,
DEFAULT_RD_TEXTURE_3D_WHITE,
+ DEFAULT_RD_TEXTURE_3D_BLACK,
DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE,
DEFAULT_RD_TEXTURE_2D_UINT,
DEFAULT_RD_TEXTURE_MAX
@@ -318,6 +320,7 @@ private:
RID default_rd_textures[DEFAULT_RD_TEXTURE_MAX];
RID default_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
+ RID custom_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
RID default_rd_storage_buffer;
/* DECAL ATLAS */
@@ -372,7 +375,7 @@ private:
ShaderData *data;
String code;
ShaderType type;
- Map<StringName, RID> default_texture_parameter;
+ Map<StringName, Map<int, RID>> default_texture_parameter;
Set<Material *> owners;
};
@@ -823,7 +826,7 @@ private:
};
ParticlesShaderRD shader;
- ShaderCompilerRD compiler;
+ ShaderCompiler compiler;
RID default_shader;
RID default_material;
@@ -874,21 +877,21 @@ private:
//PipelineCacheRD pipelines[SKY_VERSION_MAX];
Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
- Vector<ShaderCompilerRD::GeneratedCode::Texture> texture_uniforms;
+ Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
Vector<uint32_t> ubo_offsets;
uint32_t ubo_size;
String path;
String code;
- Map<StringName, RID> default_texture_params;
+ Map<StringName, Map<int, RID>> default_texture_params;
RID pipeline;
bool uses_time;
virtual void set_code(const String &p_Code);
- virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
+ virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
@@ -907,10 +910,8 @@ private:
}
struct ParticlesMaterialData : public MaterialData {
- uint64_t last_frame = 0;
ParticlesShaderData *shader_data = nullptr;
RID uniform_set;
- bool uniform_set_updated = false;
virtual void set_render_priority(int p_priority) {}
virtual void set_next_pass(RID p_pass) {}
@@ -957,6 +958,19 @@ private:
mutable RID_Owner<ParticlesCollisionInstance> particles_collision_instance_owner;
+ /* FOG VOLUMES */
+
+ struct FogVolume {
+ RID material;
+ Vector3 extents = Vector3(1, 1, 1);
+
+ RS::FogVolumeShape shape = RS::FOG_VOLUME_SHAPE_BOX;
+
+ Dependency dependency;
+ };
+
+ mutable RID_Owner<FogVolume, true> fog_volume_owner;
+
/* visibility_notifier */
struct VisibilityNotifier {
@@ -1037,7 +1051,7 @@ private:
bool box_projection = false;
bool enable_shadows = false;
uint32_t cull_mask = (1 << 20) - 1;
- float lod_threshold = 0.01;
+ float mesh_lod_threshold = 0.01;
Dependency dependency;
};
@@ -1083,7 +1097,7 @@ private:
AABB bounds;
Vector3i octree_size;
- float dynamic_range = 4.0;
+ float dynamic_range = 2.0;
float energy = 1.0;
float bias = 1.4;
float normal_bias = 0.0;
@@ -1376,6 +1390,13 @@ public:
_FORCE_INLINE_ RID sampler_rd_get_default(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) {
return default_rd_samplers[p_filter][p_repeat];
}
+ _FORCE_INLINE_ RID sampler_rd_get_custom(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) {
+ return custom_rd_samplers[p_filter][p_repeat];
+ }
+
+ void sampler_rd_configure_custom(float mipmap_bias);
+
+ void sampler_rd_set_default(float p_mipmap_bias);
/* CANVAS TEXTURE API */
@@ -1399,8 +1420,8 @@ public:
String shader_get_code(RID p_shader) const;
void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const;
- void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture);
- RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const;
+ void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index);
+ RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const;
Variant shader_get_param_default(RID p_shader, const StringName &p_param) const;
void shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function);
@@ -1425,7 +1446,6 @@ public:
void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters);
void material_update_dependency(RID p_material, DependencyTracker *p_instance);
- void material_force_update_textures(RID p_material, ShaderType p_shader_type);
void material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function);
@@ -1534,7 +1554,7 @@ public:
return s->index_count ? s->index_count : s->vertex_count;
}
- _FORCE_INLINE_ uint32_t mesh_surface_get_lod(void *p_surface, float p_model_scale, float p_distance_threshold, float p_lod_threshold, uint32_t *r_index_count = nullptr) const {
+ _FORCE_INLINE_ uint32_t mesh_surface_get_lod(void *p_surface, float p_model_scale, float p_distance_threshold, float p_mesh_lod_threshold, uint32_t *r_index_count = nullptr) const {
Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
int32_t current_lod = -1;
@@ -1543,7 +1563,7 @@ public:
}
for (uint32_t i = 0; i < s->lod_count; i++) {
float screen_size = s->lods[i].edge_length * p_model_scale / p_distance_threshold;
- if (screen_size > p_lod_threshold) {
+ if (screen_size > p_mesh_lod_threshold) {
break;
}
current_lod = i;
@@ -1932,7 +1952,7 @@ public:
void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable);
void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers);
void reflection_probe_set_resolution(RID p_probe, int p_resolution);
- void reflection_probe_set_lod_threshold(RID p_probe, float p_ratio);
+ void reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio);
AABB reflection_probe_get_aabb(RID p_probe) const;
RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const;
@@ -1940,7 +1960,7 @@ public:
Vector3 reflection_probe_get_extents(RID p_probe) const;
Vector3 reflection_probe_get_origin_offset(RID p_probe) const;
float reflection_probe_get_origin_max_distance(RID p_probe) const;
- float reflection_probe_get_lod_threshold(RID p_probe) const;
+ float reflection_probe_get_mesh_lod_threshold(RID p_probe) const;
int reflection_probe_get_resolution(RID p_probe) const;
bool reflection_probe_renders_shadows(RID p_probe) const;
@@ -2259,6 +2279,21 @@ public:
virtual bool particles_collision_is_heightfield(RID p_particles_collision) const;
RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const;
+ /* FOG VOLUMES */
+
+ virtual RID fog_volume_allocate();
+ virtual void fog_volume_initialize(RID p_rid);
+
+ virtual void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape);
+ virtual void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents);
+ virtual void fog_volume_set_material(RID p_fog_volume, RID p_material);
+ virtual RS::FogVolumeShape fog_volume_get_shape(RID p_fog_volume) const;
+ virtual RID fog_volume_get_material(RID p_fog_volume) const;
+ virtual AABB fog_volume_get_aabb(RID p_fog_volume) const;
+ virtual Vector3 fog_volume_get_extents(RID p_fog_volume) const;
+
+ /* VISIBILITY NOTIFIER */
+
virtual RID visibility_notifier_allocate();
virtual void visibility_notifier_initialize(RID p_notifier);
virtual void visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb);
@@ -2355,6 +2390,7 @@ public:
String get_video_adapter_name() const;
String get_video_adapter_vendor() const;
+ RenderingDevice::DeviceType get_video_adapter_type() const;
virtual void capture_timestamps_begin();
virtual void capture_timestamp(const String &p_name);
diff --git a/servers/rendering/renderer_rd/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp
index b9a8947fa2..73766d14d8 100644
--- a/servers/rendering/renderer_rd/shader_rd.cpp
+++ b/servers/rendering/renderer_rd/shader_rd.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -79,7 +79,7 @@ void ShaderRD::_add_stage(const char *p_code, StageType p_stage_type) {
}
if (push_chunk) {
- if (text != String()) {
+ if (!text.is_empty()) {
StageTemplate::Chunk text_chunk;
text_chunk.type = StageTemplate::Chunk::TYPE_TEXT;
text_chunk.text = text.utf8();
@@ -90,7 +90,7 @@ void ShaderRD::_add_stage(const char *p_code, StageType p_stage_type) {
}
}
- if (text != String()) {
+ if (!text.is_empty()) {
StageTemplate::Chunk text_chunk;
text_chunk.type = StageTemplate::Chunk::TYPE_TEXT;
text_chunk.text = text.utf8();
@@ -177,6 +177,9 @@ void ShaderRD::_build_variant_code(StringBuilder &builder, uint32_t p_variant, c
for (const KeyValue<StringName, CharString> &E : p_version->code_sections) {
builder.append(String("#define ") + String(E.key) + "_CODE_USED\n");
}
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+ builder.append("#define MOLTENVK_USED\n");
+#endif
} break;
case StageTemplate::Chunk::TYPE_MATERIAL_UNIFORMS: {
builder.append(p_version->uniforms.get_data()); //uniforms (same for vertex and fragment)
@@ -635,7 +638,7 @@ void ShaderRD::initialize(const Vector<String> &p_variant_defines, const String
variants_enabled.push_back(true);
}
- if (shader_cache_dir != String()) {
+ if (!shader_cache_dir.is_empty()) {
StringBuilder hash_build;
hash_build.append("[base_hash]");
diff --git a/servers/rendering/renderer_rd/shader_rd.h b/servers/rendering/renderer_rd/shader_rd.h
index 984b168659..8e57f0d9af 100644
--- a/servers/rendering/renderer_rd/shader_rd.h
+++ b/servers/rendering/renderer_rd/shader_rd.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -40,11 +40,6 @@
#include "core/variant/variant.h"
#include "servers/rendering_server.h"
-#include <stdio.h>
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
class ShaderRD {
//versions
CharString general_defines;
@@ -173,4 +168,4 @@ public:
virtual ~ShaderRD();
};
-#endif
+#endif // SHADER_RD_H
diff --git a/servers/rendering/renderer_rd/shaders/canvas.glsl b/servers/rendering/renderer_rd/shaders/canvas.glsl
index 2911e8b731..65a621b203 100644
--- a/servers/rendering/renderer_rd/shaders/canvas.glsl
+++ b/servers/rendering/renderer_rd/shaders/canvas.glsl
@@ -91,7 +91,6 @@ void main() {
uint instancing = draw_data.flags & FLAGS_INSTANCING_MASK;
#ifdef USE_ATTRIBUTES
-
if (instancing > 1) {
// trails
@@ -128,37 +127,37 @@ void main() {
vertex = new_vertex;
color *= pcolor;
-
} else
#endif // USE_ATTRIBUTES
+ {
+ if (instancing == 1) {
+ uint stride = 2;
+ {
+ if (bool(draw_data.flags & FLAGS_INSTANCING_HAS_COLORS)) {
+ stride += 1;
+ }
+ if (bool(draw_data.flags & FLAGS_INSTANCING_HAS_CUSTOM_DATA)) {
+ stride += 1;
+ }
+ }
+
+ uint offset = stride * gl_InstanceIndex;
+
+ mat4 matrix = mat4(transforms.data[offset + 0], transforms.data[offset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));
+ offset += 2;
- if (instancing == 1) {
- uint stride = 2;
- {
if (bool(draw_data.flags & FLAGS_INSTANCING_HAS_COLORS)) {
- stride += 1;
+ color *= transforms.data[offset];
+ offset += 1;
}
+
if (bool(draw_data.flags & FLAGS_INSTANCING_HAS_CUSTOM_DATA)) {
- stride += 1;
+ instance_custom = transforms.data[offset];
}
- }
-
- uint offset = stride * gl_InstanceIndex;
- mat4 matrix = mat4(transforms.data[offset + 0], transforms.data[offset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));
- offset += 2;
-
- if (bool(draw_data.flags & FLAGS_INSTANCING_HAS_COLORS)) {
- color *= transforms.data[offset];
- offset += 1;
- }
-
- if (bool(draw_data.flags & FLAGS_INSTANCING_HAS_CUSTOM_DATA)) {
- instance_custom = transforms.data[offset];
+ matrix = transpose(matrix);
+ world_matrix = world_matrix * matrix;
}
-
- matrix = transpose(matrix);
- world_matrix = world_matrix * matrix;
}
#if !defined(USE_ATTRIBUTES) && !defined(USE_PRIMITIVE)
diff --git a/servers/rendering/renderer_rd/shaders/copy.glsl b/servers/rendering/renderer_rd/shaders/copy.glsl
index 4110a95ddb..d4d0ed0f56 100644
--- a/servers/rendering/renderer_rd/shaders/copy.glsl
+++ b/servers/rendering/renderer_rd/shaders/copy.glsl
@@ -84,6 +84,8 @@ void main() {
color += texelFetch(source_color, base_pos + ivec2(1, 0), 0);
color += texelFetch(source_color, base_pos + ivec2(1, 1), 0);
color /= 4.0;
+ color = mix(color, vec4(100.0, 100.0, 100.0, 1.0), isinf(color));
+ color = mix(color, vec4(100.0, 100.0, 100.0, 1.0), isnan(color));
imageStore(dest_buffer, pos + params.target, color);
#endif
@@ -132,6 +134,13 @@ void main() {
local_cache[dest_index + 16] = textureLod(source_color, quad_center_uv + vec2(0.0, 1.0 / params.section.w), 0);
local_cache[dest_index + 16 + 1] = textureLod(source_color, quad_center_uv + vec2(1.0 / params.section.zw), 0);
}
+ if (bool(params.flags & FLAG_GLOW_FIRST_PASS)) {
+ // Tonemap initial samples to reduce weight of fireflies: https://graphicrants.blogspot.com/2013/12/tone-mapping.html
+ local_cache[dest_index] /= 1.0 + dot(local_cache[dest_index].rgb, vec3(0.299, 0.587, 0.114));
+ local_cache[dest_index + 1] /= 1.0 + dot(local_cache[dest_index + 1].rgb, vec3(0.299, 0.587, 0.114));
+ local_cache[dest_index + 16] /= 1.0 + dot(local_cache[dest_index + 16].rgb, vec3(0.299, 0.587, 0.114));
+ local_cache[dest_index + 16 + 1] /= 1.0 + dot(local_cache[dest_index + 16 + 1].rgb, vec3(0.299, 0.587, 0.114));
+ }
memoryBarrierShared();
barrier();
@@ -177,6 +186,11 @@ void main() {
color += temp_cache[index - 2] * 0.140367;
color += temp_cache[index - 3] * 0.106595;
+ if (bool(params.flags & FLAG_GLOW_FIRST_PASS)) {
+ // Undo tonemap to restore range: https://graphicrants.blogspot.com/2013/12/tone-mapping.html
+ color /= 1.0 - dot(color.rgb, vec3(0.299, 0.587, 0.114));
+ }
+
color *= params.glow_strength;
if (bool(params.flags & FLAG_GLOW_FIRST_PASS)) {
@@ -186,7 +200,7 @@ void main() {
#endif
color *= params.glow_exposure;
- float luminance = max(color.r, max(color.g, color.b));
+ float luminance = dot(color.rgb, vec3(0.299, 0.587, 0.114));
float feedback = max(smoothstep(params.glow_hdr_threshold, params.glow_hdr_threshold + params.glow_hdr_scale, luminance), params.glow_bloom);
color = min(color * feedback, vec4(params.glow_luminance_cap));
@@ -256,7 +270,9 @@ void main() {
const float PI = 3.14159265359;
vec2 uv = vec2(pos) / vec2(params.section.zw);
- uv.y = 1.0 - uv.y;
+ if (bool(params.flags & FLAG_FLIP_Y)) {
+ uv.y = 1.0 - uv.y;
+ }
float phi = uv.x * 2.0 * PI;
float theta = uv.y * PI;
diff --git a/servers/rendering/renderer_rd/shaders/fsr_upscale.glsl b/servers/rendering/renderer_rd/shaders/fsr_upscale.glsl
new file mode 100644
index 0000000000..54a7790f77
--- /dev/null
+++ b/servers/rendering/renderer_rd/shaders/fsr_upscale.glsl
@@ -0,0 +1,173 @@
+/*************************************************************************/
+/* fsr_upscale.glsl */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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. */
+/*************************************************************************/
+
+#[compute]
+
+#version 450
+
+#VERSION_DEFINES
+
+#define A_GPU
+#define A_GLSL
+
+#ifdef MODE_FSR_UPSCALE_NORMAL
+
+#define A_HALF
+
+#endif
+
+#include "thirdparty/amd-fsr/ffx_a.h"
+
+layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
+
+layout(rgba16f, set = 1, binding = 0) uniform restrict writeonly image2D fsr_image;
+layout(set = 0, binding = 0) uniform sampler2D source_image;
+
+#define FSR_UPSCALE_PASS_TYPE_EASU 0
+#define FSR_UPSCALE_PASS_TYPE_RCAS 1
+
+layout(push_constant, binding = 1, std430) uniform Params {
+ float resolution_width;
+ float resolution_height;
+ float upscaled_width;
+ float upscaled_height;
+ float sharpness;
+ int pass;
+}
+params;
+
+AU4 Const0, Const1, Const2, Const3;
+
+#ifdef MODE_FSR_UPSCALE_FALLBACK
+
+#define FSR_EASU_F
+AF4 FsrEasuRF(AF2 p) {
+ AF4 res = textureGather(source_image, p, 0);
+ return res;
+}
+AF4 FsrEasuGF(AF2 p) {
+ AF4 res = textureGather(source_image, p, 1);
+ return res;
+}
+AF4 FsrEasuBF(AF2 p) {
+ AF4 res = textureGather(source_image, p, 2);
+ return res;
+}
+
+#define FSR_RCAS_F
+AF4 FsrRcasLoadF(ASU2 p) {
+ return AF4(texelFetch(source_image, ASU2(p), 0));
+}
+void FsrRcasInputF(inout AF1 r, inout AF1 g, inout AF1 b) {}
+
+#else
+
+#define FSR_EASU_H
+AH4 FsrEasuRH(AF2 p) {
+ AH4 res = AH4(textureGather(source_image, p, 0));
+ return res;
+}
+AH4 FsrEasuGH(AF2 p) {
+ AH4 res = AH4(textureGather(source_image, p, 1));
+ return res;
+}
+AH4 FsrEasuBH(AF2 p) {
+ AH4 res = AH4(textureGather(source_image, p, 2));
+ return res;
+}
+
+#define FSR_RCAS_H
+AH4 FsrRcasLoadH(ASW2 p) {
+ return AH4(texelFetch(source_image, ASU2(p), 0));
+}
+void FsrRcasInputH(inout AH1 r, inout AH1 g, inout AH1 b) {}
+
+#endif
+
+#include "thirdparty/amd-fsr/ffx_fsr1.h"
+
+void fsr_easu_pass(AU2 pos) {
+#ifdef MODE_FSR_UPSCALE_NORMAL
+
+ AH3 Gamma2Color = AH3(0, 0, 0);
+ FsrEasuH(Gamma2Color, pos, Const0, Const1, Const2, Const3);
+ imageStore(fsr_image, ASU2(pos), AH4(Gamma2Color, 1));
+
+#else
+
+ AF3 Gamma2Color = AF3(0, 0, 0);
+ FsrEasuF(Gamma2Color, pos, Const0, Const1, Const2, Const3);
+ imageStore(fsr_image, ASU2(pos), AF4(Gamma2Color, 1));
+
+#endif
+}
+
+void fsr_rcas_pass(AU2 pos) {
+#ifdef MODE_FSR_UPSCALE_NORMAL
+
+ AH3 Gamma2Color = AH3(0, 0, 0);
+ FsrRcasH(Gamma2Color.r, Gamma2Color.g, Gamma2Color.b, pos, Const0);
+ imageStore(fsr_image, ASU2(pos), AH4(Gamma2Color, 1));
+
+#else
+
+ AF3 Gamma2Color = AF3(0, 0, 0);
+ FsrRcasF(Gamma2Color.r, Gamma2Color.g, Gamma2Color.b, pos, Const0);
+ imageStore(fsr_image, ASU2(pos), AF4(Gamma2Color, 1));
+
+#endif
+}
+
+void fsr_pass(AU2 pos) {
+ if (params.pass == FSR_UPSCALE_PASS_TYPE_EASU) {
+ fsr_easu_pass(pos);
+ } else if (params.pass == FSR_UPSCALE_PASS_TYPE_RCAS) {
+ fsr_rcas_pass(pos);
+ }
+}
+
+void main() {
+ // Clang does not like unused functions. If ffx_a.h is included in the binary, clang will throw a fit and not compile so we must configure FSR in this shader
+ if (params.pass == FSR_UPSCALE_PASS_TYPE_EASU) {
+ FsrEasuCon(Const0, Const1, Const2, Const3, params.resolution_width, params.resolution_height, params.resolution_width, params.resolution_height, params.upscaled_width, params.upscaled_height);
+ } else if (params.pass == FSR_UPSCALE_PASS_TYPE_RCAS) {
+ FsrRcasCon(Const0, params.sharpness);
+ }
+
+ AU2 gxy = ARmp8x8(gl_LocalInvocationID.x) + AU2(gl_WorkGroupID.x << 4u, gl_WorkGroupID.y << 4u);
+
+ fsr_pass(gxy);
+ gxy.x += 8u;
+ fsr_pass(gxy);
+ gxy.y += 8u;
+ fsr_pass(gxy);
+ gxy.x -= 8u;
+ fsr_pass(gxy);
+}
diff --git a/servers/rendering/renderer_rd/shaders/gi.glsl b/servers/rendering/renderer_rd/shaders/gi.glsl
index 5528ea3659..9854f124d7 100644
--- a/servers/rendering/renderer_rd/shaders/gi.glsl
+++ b/servers/rendering/renderer_rd/shaders/gi.glsl
@@ -68,19 +68,15 @@ sdfgi;
#define MAX_VOXEL_GI_INSTANCES 8
struct VoxelGIData {
- mat4 xform;
- vec3 bounds;
- float dynamic_range;
+ mat4 xform; // 64 - 64
- float bias;
- float normal_bias;
- bool blend_ambient;
- uint texture_slot;
+ vec3 bounds; // 12 - 76
+ float dynamic_range; // 4 - 80
- uint pad0;
- uint pad1;
- uint pad2;
- uint mipmaps;
+ float bias; // 4 - 84
+ float normal_bias; // 4 - 88
+ bool blend_ambient; // 4 - 92
+ uint mipmaps; // 4 - 96
};
layout(set = 0, binding = 16, std140) uniform VoxelGIs {
diff --git a/servers/rendering/renderer_rd/shaders/giprobe_write.glsl b/servers/rendering/renderer_rd/shaders/giprobe_write.glsl
index 25d87ca45d..a6d65bffeb 100644
--- a/servers/rendering/renderer_rd/shaders/giprobe_write.glsl
+++ b/servers/rendering/renderer_rd/shaders/giprobe_write.glsl
@@ -7,7 +7,6 @@
layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
#define NO_CHILDREN 0xFFFFFFFF
-#define GREY_VEC vec3(0.33333, 0.33333, 0.33333)
struct CellChildren {
uint children[8];
diff --git a/servers/rendering/renderer_rd/shaders/particles.glsl b/servers/rendering/renderer_rd/shaders/particles.glsl
index 9f8410fd8a..328becbc20 100644
--- a/servers/rendering/renderer_rd/shaders/particles.glsl
+++ b/servers/rendering/renderer_rd/shaders/particles.glsl
@@ -567,11 +567,11 @@ void main() {
depth = particle_size - s;
const float EPSILON = 0.001;
normal = mat3(FRAME.colliders[i].transform) *
- normalize(
- vec3(
- texture(sampler3D(sdf_vec_textures[FRAME.colliders[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos + vec3(EPSILON, 0.0, 0.0)).r - texture(sampler3D(sdf_vec_textures[FRAME.colliders[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos - vec3(EPSILON, 0.0, 0.0)).r,
- texture(sampler3D(sdf_vec_textures[FRAME.colliders[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos + vec3(0.0, EPSILON, 0.0)).r - texture(sampler3D(sdf_vec_textures[FRAME.colliders[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos - vec3(0.0, EPSILON, 0.0)).r,
- texture(sampler3D(sdf_vec_textures[FRAME.colliders[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos + vec3(0.0, 0.0, EPSILON)).r - texture(sampler3D(sdf_vec_textures[FRAME.colliders[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos - vec3(0.0, 0.0, EPSILON)).r));
+ normalize(
+ vec3(
+ texture(sampler3D(sdf_vec_textures[FRAME.colliders[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos + vec3(EPSILON, 0.0, 0.0)).r - texture(sampler3D(sdf_vec_textures[FRAME.colliders[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos - vec3(EPSILON, 0.0, 0.0)).r,
+ texture(sampler3D(sdf_vec_textures[FRAME.colliders[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos + vec3(0.0, EPSILON, 0.0)).r - texture(sampler3D(sdf_vec_textures[FRAME.colliders[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos - vec3(0.0, EPSILON, 0.0)).r,
+ texture(sampler3D(sdf_vec_textures[FRAME.colliders[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos + vec3(0.0, 0.0, EPSILON)).r - texture(sampler3D(sdf_vec_textures[FRAME.colliders[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos - vec3(0.0, 0.0, EPSILON)).r));
}
} break;
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_aa_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_aa_inc.glsl
index 99714b4504..97c913d489 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_aa_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_aa_inc.glsl
@@ -2,7 +2,7 @@
float hash_2d(vec2 p) {
return fract(1.0e4 * sin(17.0 * p.x + 0.1 * p.y) *
- (0.1 + abs(sin(13.0 * p.y + p.x))));
+ (0.1 + abs(sin(13.0 * p.y + p.x))));
}
float hash_3d(vec3 p) {
@@ -29,8 +29,7 @@ float compute_alpha_hash_threshold(vec3 pos, float hash_scale) {
vec3 cases = vec3(a_interp * a_interp / (2.0 * min_lerp * (1.0 - min_lerp)),
(a_interp - 0.5 * min_lerp) / (1.0 - min_lerp),
- 1.0 - ((1.0 - a_interp) * (1.0 - a_interp) /
- (2.0 * min_lerp * (1.0 - min_lerp))));
+ 1.0 - ((1.0 - a_interp) * (1.0 - a_interp) / (2.0 * min_lerp * (1.0 - min_lerp))));
float alpha_hash_threshold =
(lerp_factor < (1.0 - min_lerp)) ? ((lerp_factor < min_lerp) ? cases.x : cases.y) : cases.z;
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
index 5261868155..97f7e0a6e6 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
@@ -6,6 +6,8 @@
#include "scene_forward_clustered_inc.glsl"
+#define SHADER_IS_SRGB false
+
/* INPUT ATTRIBS */
layout(location = 0) in vec3 vertex_attrib;
@@ -95,7 +97,7 @@ layout(location = 8) out float dp_clip;
#endif
-layout(location = 9) out flat uint instance_index;
+layout(location = 9) out flat uint instance_index_interp;
invariant gl_Position;
@@ -107,13 +109,15 @@ void main() {
color_interp = color_attrib;
#endif
- instance_index = draw_call.instance_index;
+ uint instance_index = draw_call.instance_index;
bool is_multimesh = bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH);
if (!is_multimesh) {
instance_index += gl_InstanceIndex;
}
+ instance_index_interp = instance_index;
+
mat4 world_matrix = instances.data[instance_index].transform;
mat3 world_normal_matrix;
@@ -247,7 +251,9 @@ void main() {
vertex = (world_matrix * vec4(vertex, 1.0)).xyz;
+#ifdef NORMAL_USED
normal = world_normal_matrix * normal;
+#endif
#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
@@ -286,12 +292,13 @@ void main() {
#if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED)
vertex = (scene_data.inv_camera_matrix * vec4(vertex, 1.0)).xyz;
- normal = mat3(scene_data.inverse_normal_matrix) * normal;
+#ifdef NORMAL_USED
+ normal = (scene_data.inv_camera_matrix * vec4(normal, 0.0)).xyz;
+#endif
#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
-
- binormal = mat3(scene_data.camera_inverse_binormal_matrix) * binormal;
- tangent = mat3(scene_data.camera_inverse_tangent_matrix) * tangent;
+ binormal = (scene_data.inv_camera_matrix * vec4(binormal, 0.0)).xyz;
+ tangent = (scene_data.inv_camera_matrix * vec4(tangent, 0.0)).xyz;
#endif
#endif
@@ -356,6 +363,8 @@ void main() {
#VERSION_DEFINES
+#define SHADER_IS_SRGB false
+
/* Specialization Constants (Toggles) */
layout(constant_id = 0) const bool sc_use_forward_gi = false;
@@ -410,7 +419,7 @@ layout(location = 8) in float dp_clip;
#endif
-layout(location = 9) in flat uint instance_index;
+layout(location = 9) in flat uint instance_index_interp;
//defines to keep compatibility with vertex
@@ -564,7 +573,9 @@ void main() {
discard;
#endif
- //lay out everything, whathever is unused is optimized away anyway
+ uint instance_index = instance_index_interp;
+
+ //lay out everything, whatever is unused is optimized away anyway
vec3 vertex = vertex_interp;
vec3 view = -normalize(vertex_interp);
vec3 albedo = vec3(1.0);
@@ -593,7 +604,7 @@ void main() {
float ao = 1.0;
float ao_light_affect = 0.0;
- float alpha = 1.0;
+ float alpha = float(instances.data[instance_index].flags >> INSTANCE_FLAGS_FADE_SHIFT) / float(255.0);
#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
vec3 binormal = normalize(binormal_interp);
@@ -687,7 +698,7 @@ void main() {
#endif // ALPHA_ANTIALIASING_EDGE_USED
#ifdef USE_OPAQUE_PREPASS
- if (alpha < opaque_prepass_threshold) {
+ if (alpha < scene_data.opaque_prepass_threshold) {
discard;
}
#endif // USE_OPAQUE_PREPASS
@@ -964,15 +975,15 @@ void main() {
const float c4 = 0.886227;
const float c5 = 0.247708;
ambient_light += (c1 * lightmap_captures.data[index].sh[8].rgb * (wnormal.x * wnormal.x - wnormal.y * wnormal.y) +
- c3 * lightmap_captures.data[index].sh[6].rgb * wnormal.z * wnormal.z +
- c4 * lightmap_captures.data[index].sh[0].rgb -
- c5 * lightmap_captures.data[index].sh[6].rgb +
- 2.0 * c1 * lightmap_captures.data[index].sh[4].rgb * wnormal.x * wnormal.y +
- 2.0 * c1 * lightmap_captures.data[index].sh[7].rgb * wnormal.x * wnormal.z +
- 2.0 * c1 * lightmap_captures.data[index].sh[5].rgb * wnormal.y * wnormal.z +
- 2.0 * c2 * lightmap_captures.data[index].sh[3].rgb * wnormal.x +
- 2.0 * c2 * lightmap_captures.data[index].sh[1].rgb * wnormal.y +
- 2.0 * c2 * lightmap_captures.data[index].sh[2].rgb * wnormal.z);
+ c3 * lightmap_captures.data[index].sh[6].rgb * wnormal.z * wnormal.z +
+ c4 * lightmap_captures.data[index].sh[0].rgb -
+ c5 * lightmap_captures.data[index].sh[6].rgb +
+ 2.0 * c1 * lightmap_captures.data[index].sh[4].rgb * wnormal.x * wnormal.y +
+ 2.0 * c1 * lightmap_captures.data[index].sh[7].rgb * wnormal.x * wnormal.z +
+ 2.0 * c1 * lightmap_captures.data[index].sh[5].rgb * wnormal.y * wnormal.z +
+ 2.0 * c2 * lightmap_captures.data[index].sh[3].rgb * wnormal.x +
+ 2.0 * c2 * lightmap_captures.data[index].sh[1].rgb * wnormal.y +
+ 2.0 * c2 * lightmap_captures.data[index].sh[2].rgb * wnormal.z);
} else if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP)) { // has actual lightmap
bool uses_sh = bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_SH_LIGHTMAP);
@@ -1145,7 +1156,7 @@ void main() {
}
#endif // !USE_LIGHTMAP
- if (scene_data.ssao_enabled) {
+ if (bool(scene_data.ss_effects_flags & SCREEN_SPACE_EFFECTS_FLAGS_USE_SSAO)) {
float ssao = texture(sampler2D(ao_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), screen_uv).r;
ao = min(ao, ssao);
ao_light_affect = mix(ao_light_affect, max(ao_light_affect, scene_data.ssao_light_affect), scene_data.ssao_ao_affect);
@@ -1215,6 +1226,12 @@ void main() {
// convert ao to direct light ao
ao = mix(1.0, ao, ao_light_affect);
+ if (bool(scene_data.ss_effects_flags & SCREEN_SPACE_EFFECTS_FLAGS_USE_SSIL)) {
+ vec4 ssil = textureLod(sampler2D(ssil_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), screen_uv, 0.0);
+ ambient_light *= 1.0 - ssil.a;
+ ambient_light += ssil.rgb * albedo.rgb;
+ }
+
//this saves some VGPRs
vec3 f0 = F0(metallic, specular, albedo);
@@ -1249,9 +1266,10 @@ void main() {
// LIGHTING
#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
- { //directional light
+ { // Directional light.
- // Do shadow and lighting in two passes to reduce register pressure
+ // Do shadow and lighting in two passes to reduce register pressure.
+#ifndef SHADOWS_DISABLED
uint shadow0 = 0;
uint shadow1 = 0;
@@ -1270,21 +1288,21 @@ void main() {
float shadow = 1.0;
- //version with soft shadows, more expensive
if (directional_lights.data[i].shadow_enabled) {
- if (sc_use_directional_soft_shadows && directional_lights.data[i].softshadow_angle > 0) {
- float depth_z = -vertex.z;
-
- vec3 shadow_color = vec3(0.0);
- vec3 light_dir = directional_lights.data[i].direction;
+ float depth_z = -vertex.z;
+ vec3 light_dir = directional_lights.data[i].direction;
+ vec3 base_normal_bias = normalize(normal_interp) * (1.0 - max(0.0, dot(light_dir, -normalize(normal_interp))));
-#define BIAS_FUNC(m_var, m_idx) \
- m_var.xyz += light_dir * directional_lights.data[i].shadow_bias[m_idx]; \
- vec3 normal_bias = normalize(normal_interp) * (1.0 - max(0.0, dot(light_dir, -normalize(normal_interp)))) * directional_lights.data[i].shadow_normal_bias[m_idx]; \
- normal_bias -= light_dir * dot(light_dir, normal_bias); \
+#define BIAS_FUNC(m_var, m_idx) \
+ m_var.xyz += light_dir * directional_lights.data[i].shadow_bias[m_idx]; \
+ vec3 normal_bias = base_normal_bias * directional_lights.data[i].shadow_normal_bias[m_idx]; \
+ normal_bias -= light_dir * dot(light_dir, normal_bias); \
m_var.xyz += normal_bias;
- uint blend_index = 0;
+ //version with soft shadows, more expensive
+ if (sc_use_directional_soft_shadows && directional_lights.data[i].softshadow_angle > 0) {
+ uint blend_count = 0;
+ const uint blend_max = directional_lights.data[i].blend_splits ? 2 : 1;
if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
vec4 v = vec4(vertex, 1.0);
@@ -1299,10 +1317,10 @@ void main() {
float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
vec2 tex_scale = directional_lights.data[i].uv_scale1 * test_radius;
shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
- blend_index++;
+ blend_count++;
}
- if (blend_index < 2 && depth_z < directional_lights.data[i].shadow_split_offsets.y) {
+ if (blend_count < blend_max && depth_z < directional_lights.data[i].shadow_split_offsets.y) {
vec4 v = vec4(vertex, 1.0);
BIAS_FUNC(v, 1)
@@ -1316,7 +1334,7 @@ void main() {
vec2 tex_scale = directional_lights.data[i].uv_scale2 * test_radius;
float s = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
- if (blend_index == 0) {
+ if (blend_count == 0) {
shadow = s;
} else {
//blend
@@ -1324,10 +1342,10 @@ void main() {
shadow = mix(shadow, s, blend);
}
- blend_index++;
+ blend_count++;
}
- if (blend_index < 2 && depth_z < directional_lights.data[i].shadow_split_offsets.z) {
+ if (blend_count < blend_max && depth_z < directional_lights.data[i].shadow_split_offsets.z) {
vec4 v = vec4(vertex, 1.0);
BIAS_FUNC(v, 2)
@@ -1341,7 +1359,7 @@ void main() {
vec2 tex_scale = directional_lights.data[i].uv_scale3 * test_radius;
float s = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
- if (blend_index == 0) {
+ if (blend_count == 0) {
shadow = s;
} else {
//blend
@@ -1349,10 +1367,10 @@ void main() {
shadow = mix(shadow, s, blend);
}
- blend_index++;
+ blend_count++;
}
- if (blend_index < 2) {
+ if (blend_count < blend_max) {
vec4 v = vec4(vertex, 1.0);
BIAS_FUNC(v, 3)
@@ -1366,7 +1384,7 @@ void main() {
vec2 tex_scale = directional_lights.data[i].uv_scale4 * test_radius;
float s = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
- if (blend_index == 0) {
+ if (blend_count == 0) {
shadow = s;
} else {
//blend
@@ -1375,21 +1393,9 @@ void main() {
}
}
-#undef BIAS_FUNC
} else { //no soft shadows
- float depth_z = -vertex.z;
-
vec4 pssm_coord;
- vec3 light_dir = directional_lights.data[i].direction;
- vec3 base_normal_bias = normalize(normal_interp) * (1.0 - max(0.0, dot(light_dir, -normalize(normal_interp))));
-
-#define BIAS_FUNC(m_var, m_idx) \
- m_var.xyz += light_dir * directional_lights.data[i].shadow_bias[m_idx]; \
- vec3 normal_bias = base_normal_bias * directional_lights.data[i].shadow_normal_bias[m_idx]; \
- normal_bias -= light_dir * dot(light_dir, normal_bias); \
- m_var.xyz += normal_bias;
-
if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
vec4 v = vec4(vertex, 1.0);
@@ -1448,11 +1454,11 @@ void main() {
float shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
shadow = mix(shadow, shadow2, pssm_blend);
}
+ }
- shadow = mix(shadow, 1.0, smoothstep(directional_lights.data[i].fade_from, directional_lights.data[i].fade_to, vertex.z)); //done with negative values for performance
+ shadow = mix(shadow, 1.0, smoothstep(directional_lights.data[i].fade_from, directional_lights.data[i].fade_to, vertex.z)); //done with negative values for performance
#undef BIAS_FUNC
- }
} // shadows
if (i < 4) {
@@ -1461,6 +1467,7 @@ void main() {
shadow1 |= uint(clamp(shadow * 255.0, 0.0, 255.0)) << ((i - 4) * 8);
}
}
+#endif // SHADOWS_DISABLED
for (uint i = 0; i < 8; i++) {
if (i >= scene_data.directional_light_count) {
@@ -1523,18 +1530,19 @@ void main() {
#endif
float shadow = 1.0;
-
+#ifndef SHADOWS_DISABLED
if (i < 4) {
shadow = float(shadow0 >> (i * 8) & 0xFF) / 255.0;
} else {
shadow = float(shadow1 >> ((i - 4) * 8) & 0xFF) / 255.0;
}
+#endif
blur_shadow(shadow);
float size_A = sc_use_light_soft_shadows ? directional_lights.data[i].size : 0.0;
- light_compute(normal, directional_lights.data[i].direction, normalize(view), size_A, directional_lights.data[i].color * directional_lights.data[i].energy, shadow, f0, orms, 1.0,
+ light_compute(normal, directional_lights.data[i].direction, normalize(view), size_A, directional_lights.data[i].color * directional_lights.data[i].energy, shadow, f0, orms, 1.0, albedo, alpha,
#ifdef LIGHT_BACKLIGHT_USED
backlight,
#endif
@@ -1545,7 +1553,7 @@ void main() {
transmittance_z,
#endif
#ifdef LIGHT_RIM_USED
- rim, rim_tint, albedo,
+ rim, rim_tint,
#endif
#ifdef LIGHT_CLEARCOAT_USED
clearcoat, clearcoat_gloss,
@@ -1553,9 +1561,6 @@ void main() {
#ifdef LIGHT_ANISOTROPY_USED
binormal, tangent, anisotropy,
#endif
-#ifdef USE_SHADOW_TO_OPACITY
- alpha,
-#endif
diffuse_light,
specular_light);
}
@@ -1608,7 +1613,7 @@ void main() {
shadow = blur_shadow(shadow);
- light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow,
+ light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha,
#ifdef LIGHT_BACKLIGHT_USED
backlight,
#endif
@@ -1620,7 +1625,6 @@ void main() {
#ifdef LIGHT_RIM_USED
rim,
rim_tint,
- albedo,
#endif
#ifdef LIGHT_CLEARCOAT_USED
clearcoat, clearcoat_gloss,
@@ -1628,9 +1632,6 @@ void main() {
#ifdef LIGHT_ANISOTROPY_USED
tangent, binormal, anisotropy,
#endif
-#ifdef USE_SHADOW_TO_OPACITY
- alpha,
-#endif
diffuse_light, specular_light);
}
}
@@ -1684,7 +1685,7 @@ void main() {
shadow = blur_shadow(shadow);
- light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow,
+ light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha,
#ifdef LIGHT_BACKLIGHT_USED
backlight,
#endif
@@ -1696,7 +1697,6 @@ void main() {
#ifdef LIGHT_RIM_USED
rim,
rim_tint,
- albedo,
#endif
#ifdef LIGHT_CLEARCOAT_USED
clearcoat, clearcoat_gloss,
@@ -1704,9 +1704,6 @@ void main() {
#ifdef LIGHT_ANISOTROPY_USED
tangent, binormal, anisotropy,
#endif
-#ifdef USE_SHADOW_TO_OPACITY
- alpha,
-#endif
diffuse_light, specular_light);
}
}
@@ -1723,7 +1720,7 @@ void main() {
#ifdef USE_OPAQUE_PREPASS
- if (alpha < opaque_prepass_threshold) {
+ if (alpha < scene_data.opaque_prepass_threshold) {
discard;
}
@@ -1769,7 +1766,11 @@ void main() {
}
}
+#ifdef MOLTENVK_USED
+ imageStore(geom_facing_grid, grid_pos, uvec4(imageLoad(geom_facing_grid, grid_pos).r | facing_bits)); //store facing bits
+#else
imageAtomicOr(geom_facing_grid, grid_pos, facing_bits); //store facing bits
+#endif
if (length(emission) > 0.001) {
float lumas[6];
@@ -1909,7 +1910,6 @@ void main() {
// Draw "fixed" fog before volumetric fog to ensure volumetric fog can appear in front of the sky.
frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a);
- ;
#endif //MODE_MULTIPLE_RENDER_TARGETS
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl
index b943d81784..0f7cd18534 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl
@@ -68,9 +68,13 @@ layout(set = 0, binding = 4) uniform sampler light_projector_sampler;
#define INSTANCE_FLAGS_MULTIMESH_HAS_COLOR (1 << 14)
#define INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA (1 << 15)
#define INSTANCE_FLAGS_PARTICLE_TRAIL_SHIFT 16
+#define INSTANCE_FLAGS_FADE_SHIFT 24
//3 bits of stride
#define INSTANCE_FLAGS_PARTICLE_TRAIL_MASK 0xFF
+#define SCREEN_SPACE_EFFECTS_FLAGS_USE_SSAO 1
+#define SCREEN_SPACE_EFFECTS_FLAGS_USE_SSIL 2
+
layout(set = 0, binding = 5, std430) restrict readonly buffer OmniLights {
LightData data[];
}
@@ -200,14 +204,15 @@ layout(set = 1, binding = 0, std140) uniform SceneData {
float z_far;
float z_near;
- bool ssao_enabled;
+ uint ss_effects_flags;
float ssao_light_affect;
float ssao_ao_affect;
bool roughness_limiter_enabled;
float roughness_limiter_amount;
float roughness_limiter_limit;
- uvec2 roughness_limiter_pad;
+ float opaque_prepass_threshold;
+ uint roughness_limiter_pad;
mat4 sdf_to_bounds;
@@ -303,19 +308,15 @@ layout(set = 1, binding = 15) uniform texture2DArray sdfgi_lightprobe_texture;
layout(set = 1, binding = 16) uniform texture3D sdfgi_occlusion_cascades;
struct VoxelGIData {
- mat4 xform;
- vec3 bounds;
- float dynamic_range;
+ mat4 xform; // 64 - 64
- float bias;
- float normal_bias;
- bool blend_ambient;
- uint texture_slot;
+ vec3 bounds; // 12 - 76
+ float dynamic_range; // 4 - 80
- float anisotropy_strength;
- float ambient_occlusion;
- float ambient_occlusion_size;
- uint mipmaps;
+ float bias; // 4 - 84
+ float normal_bias; // 4 - 88
+ bool blend_ambient; // 4 - 92
+ uint mipmaps; // 4 - 96
};
layout(set = 1, binding = 17, std140) uniform VoxelGIs {
@@ -325,6 +326,8 @@ voxel_gi_instances;
layout(set = 1, binding = 18) uniform texture3D volumetric_fog_texture;
+layout(set = 1, binding = 19) uniform texture2D ssil_buffer;
+
#endif
/* Set 2 Skeleton & Instancing (can change per item) */
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
index 4d466342f8..d22f936a35 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
@@ -73,7 +73,7 @@ vec3 F0(float metallic, float specular, vec3 albedo) {
return mix(vec3(dielectric), albedo, vec3(metallic));
}
-void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float attenuation, vec3 f0, uint orms, float specular_amount,
+void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float attenuation, vec3 f0, uint orms, float specular_amount, vec3 albedo, inout float alpha,
#ifdef LIGHT_BACKLIGHT_USED
vec3 backlight,
#endif
@@ -84,7 +84,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte
float transmittance_z,
#endif
#ifdef LIGHT_RIM_USED
- float rim, float rim_tint, vec3 rim_color,
+ float rim, float rim_tint,
#endif
#ifdef LIGHT_CLEARCOAT_USED
float clearcoat, float clearcoat_gloss,
@@ -92,9 +92,6 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte
#ifdef LIGHT_ANISOTROPY_USED
vec3 B, vec3 T, float anisotropy,
#endif
-#ifdef USE_SHADOW_TO_OPACITY
- inout float alpha,
-#endif
inout vec3 diffuse_light, inout vec3 specular_light) {
vec4 orms_unpacked = unpackUnorm4x8(orms);
@@ -171,7 +168,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte
#if defined(LIGHT_RIM_USED)
float rim_light = pow(max(0.0, 1.0 - cNdotV), max(0.0, (1.0 - roughness) * 16.0));
- diffuse_light += rim_light * rim * mix(vec3(1.0), rim_color, rim_tint) * light_color;
+ diffuse_light += rim_light * rim * mix(vec3(1.0), albedo, rim_tint) * light_color;
#endif
#ifdef LIGHT_TRANSMITTANCE_USED
@@ -182,11 +179,11 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte
float d = scale * abs(transmittance_z);
float dd = -d * d;
vec3 profile = vec3(0.233, 0.455, 0.649) * exp(dd / 0.0064) +
- vec3(0.1, 0.336, 0.344) * exp(dd / 0.0484) +
- vec3(0.118, 0.198, 0.0) * exp(dd / 0.187) +
- vec3(0.113, 0.007, 0.007) * exp(dd / 0.567) +
- vec3(0.358, 0.004, 0.0) * exp(dd / 1.99) +
- vec3(0.078, 0.0, 0.0) * exp(dd / 7.41);
+ vec3(0.1, 0.336, 0.344) * exp(dd / 0.0484) +
+ vec3(0.118, 0.198, 0.0) * exp(dd / 0.187) +
+ vec3(0.113, 0.007, 0.007) * exp(dd / 0.567) +
+ vec3(0.358, 0.004, 0.0) * exp(dd / 1.99) +
+ vec3(0.078, 0.0, 0.0) * exp(dd / 7.41);
diffuse_light += profile * transmittance_color.a * light_color * clamp(transmittance_boost - NdotL, 0.0, 1.0) * (1.0 / M_PI);
#else
@@ -287,7 +284,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte
#endif //defined(LIGHT_CODE_USED)
}
-#ifndef USE_NO_SHADOWS
+#ifndef SHADOWS_DISABLED
// Interleaved Gradient Noise
// https://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare
@@ -301,7 +298,7 @@ float sample_directional_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, ve
float depth = coord.z;
//if only one sample is taken, take it from the center
- if (sc_directional_soft_shadow_samples == 1) {
+ if (sc_directional_soft_shadow_samples == 0) {
return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
}
@@ -327,7 +324,7 @@ float sample_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec3 coord) {
float depth = coord.z;
//if only one sample is taken, take it from the center
- if (sc_soft_shadow_samples == 1) {
+ if (sc_soft_shadow_samples == 0) {
return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
}
@@ -350,7 +347,7 @@ float sample_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec3 coord) {
float sample_omni_pcf_shadow(texture2D shadow, float blur_scale, vec2 coord, vec4 uv_rect, vec2 flip_offset, float depth) {
//if only one sample is taken, take it from the center
- if (sc_soft_shadow_samples == 1) {
+ if (sc_soft_shadow_samples == 0) {
vec2 pos = coord * 0.5 + 0.5;
pos = uv_rect.xy + pos * uv_rect.zw;
return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
@@ -433,7 +430,7 @@ float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex
}
}
-#endif //USE_NO_SHADOWS
+#endif // SHADOWS_DISABLED
float get_omni_attenuation(float distance, float inv_range, float decay) {
float nd = distance * inv_range;
@@ -445,7 +442,7 @@ float get_omni_attenuation(float distance, float inv_range, float decay) {
}
float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {
-#ifndef USE_NO_SHADOWS
+#ifndef SHADOWS_DISABLED
if (omni_lights.data[idx].shadow_enabled) {
// there is a shadowmap
vec2 texel_size = scene_data.shadow_atlas_pixel_size;
@@ -577,7 +574,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {
return 1.0;
}
-void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 f0, uint orms, float shadow,
+void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 f0, uint orms, float shadow, vec3 albedo, inout float alpha,
#ifdef LIGHT_BACKLIGHT_USED
vec3 backlight,
#endif
@@ -587,7 +584,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
float transmittance_boost,
#endif
#ifdef LIGHT_RIM_USED
- float rim, float rim_tint, vec3 rim_color,
+ float rim, float rim_tint,
#endif
#ifdef LIGHT_CLEARCOAT_USED
float clearcoat, float clearcoat_gloss,
@@ -595,9 +592,6 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
#ifdef LIGHT_ANISOTROPY_USED
vec3 binormal, vec3 tangent, float anisotropy,
#endif
-#ifdef USE_SHADOW_TO_OPACITY
- inout float alpha,
-#endif
inout vec3 diffuse_light, inout vec3 specular_light) {
vec3 light_rel_vec = omni_lights.data[idx].position - vertex;
float light_length = length(light_rel_vec);
@@ -703,7 +697,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
light_attenuation *= shadow;
- light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, light_attenuation, f0, orms, omni_lights.data[idx].specular_amount,
+ light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, light_attenuation, f0, orms, omni_lights.data[idx].specular_amount, albedo, alpha,
#ifdef LIGHT_BACKLIGHT_USED
backlight,
#endif
@@ -714,7 +708,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
transmittance_z,
#endif
#ifdef LIGHT_RIM_USED
- rim * omni_attenuation, rim_tint, rim_color,
+ rim * omni_attenuation, rim_tint,
#endif
#ifdef LIGHT_CLEARCOAT_USED
clearcoat, clearcoat_gloss,
@@ -722,15 +716,12 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
#ifdef LIGHT_ANISOTROPY_USED
binormal, tangent, anisotropy,
#endif
-#ifdef USE_SHADOW_TO_OPACITY
- alpha,
-#endif
diffuse_light,
specular_light);
}
float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) {
-#ifndef USE_NO_SHADOWS
+#ifndef SHADOWS_DISABLED
if (spot_lights.data[idx].shadow_enabled) {
vec3 light_rel_vec = spot_lights.data[idx].position - vertex;
float light_length = length(light_rel_vec);
@@ -806,7 +797,7 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) {
return shadow;
}
-#endif //USE_NO_SHADOWS
+#endif // SHADOWS_DISABLED
return 1.0;
}
@@ -823,7 +814,7 @@ vec2 normal_to_panorama(vec3 n) {
return panorama_coords;
}
-void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 f0, uint orms, float shadow,
+void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 f0, uint orms, float shadow, vec3 albedo, inout float alpha,
#ifdef LIGHT_BACKLIGHT_USED
vec3 backlight,
#endif
@@ -833,7 +824,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
float transmittance_boost,
#endif
#ifdef LIGHT_RIM_USED
- float rim, float rim_tint, vec3 rim_color,
+ float rim, float rim_tint,
#endif
#ifdef LIGHT_CLEARCOAT_USED
float clearcoat, float clearcoat_gloss,
@@ -841,9 +832,6 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
#ifdef LIGHT_ANISOTROPY_USED
vec3 binormal, vec3 tangent, float anisotropy,
#endif
-#ifdef USE_SHADOW_TO_OPACITY
- inout float alpha,
-#endif
inout vec3 diffuse_light,
inout vec3 specular_light) {
vec3 light_rel_vec = spot_lights.data[idx].position - vertex;
@@ -910,7 +898,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
}
light_attenuation *= shadow;
- light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, light_attenuation, f0, orms, spot_lights.data[idx].specular_amount,
+ light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, light_attenuation, f0, orms, spot_lights.data[idx].specular_amount, albedo, alpha,
#ifdef LIGHT_BACKLIGHT_USED
backlight,
#endif
@@ -921,7 +909,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
transmittance_z,
#endif
#ifdef LIGHT_RIM_USED
- rim * spot_attenuation, rim_tint, rim_color,
+ rim * spot_attenuation, rim_tint,
#endif
#ifdef LIGHT_CLEARCOAT_USED
clearcoat, clearcoat_gloss,
@@ -929,9 +917,6 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
#ifdef LIGHT_ANISOTROPY_USED
binormal, tangent, anisotropy,
#endif
-#ifdef USE_SHADOW_TO_OPACITY
- alpha,
-#endif
diffuse_light, specular_light);
}
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
index 0ee68d5e10..4d6a3b5864 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
@@ -7,6 +7,8 @@
/* Include our forward mobile UBOs definitions etc. */
#include "scene_forward_mobile_inc.glsl"
+#define SHADER_IS_SRGB false
+
/* INPUT ATTRIBS */
layout(location = 0) in vec3 vertex_attrib;
@@ -259,7 +261,9 @@ void main() {
vertex = (world_matrix * vec4(vertex, 1.0)).xyz;
+#ifdef NORMAL_USED
normal = world_normal_matrix * normal;
+#endif
#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
@@ -300,12 +304,13 @@ void main() {
#if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED)
vertex = (scene_data.inv_camera_matrix * vec4(vertex, 1.0)).xyz;
- normal = mat3(scene_data.inverse_normal_matrix) * normal;
+#ifdef NORMAL_USED
+ normal = (scene_data.inv_camera_matrix * vec4(normal, 0.0)).xyz;
+#endif
#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
-
- binormal = mat3(scene_data.camera_inverse_binormal_matrix) * binormal;
- tangent = mat3(scene_data.camera_inverse_tangent_matrix) * tangent;
+ binormal = (scene_data.inv_camera_matrix * vec4(binormal, 0.0)).xyz;
+ tangent = (scene_data.inv_camera_matrix * vec4(tangent, 0.0)).xyz;
#endif
#endif
@@ -370,6 +375,8 @@ void main() {
#VERSION_DEFINES
+#define SHADER_IS_SRGB false
+
/* Specialization Constants */
#if !defined(MODE_RENDER_DEPTH)
@@ -574,7 +581,7 @@ void main() {
discard;
#endif
- //lay out everything, whathever is unused is optimized away anyway
+ //lay out everything, whatever is unused is optimized away anyway
vec3 vertex = vertex_interp;
vec3 view = -normalize(vertex_interp);
vec3 albedo = vec3(1.0);
@@ -701,7 +708,7 @@ void main() {
#endif // ALPHA_ANTIALIASING_EDGE_USED
#ifdef USE_OPAQUE_PREPASS
- if (alpha < opaque_prepass_threshold) {
+ if (alpha < scene_data.opaque_prepass_threshold) {
discard;
}
#endif // USE_OPAQUE_PREPASS
@@ -930,15 +937,15 @@ void main() {
const float c4 = 0.886227;
const float c5 = 0.247708;
ambient_light += (c1 * lightmap_captures.data[index].sh[8].rgb * (wnormal.x * wnormal.x - wnormal.y * wnormal.y) +
- c3 * lightmap_captures.data[index].sh[6].rgb * wnormal.z * wnormal.z +
- c4 * lightmap_captures.data[index].sh[0].rgb -
- c5 * lightmap_captures.data[index].sh[6].rgb +
- 2.0 * c1 * lightmap_captures.data[index].sh[4].rgb * wnormal.x * wnormal.y +
- 2.0 * c1 * lightmap_captures.data[index].sh[7].rgb * wnormal.x * wnormal.z +
- 2.0 * c1 * lightmap_captures.data[index].sh[5].rgb * wnormal.y * wnormal.z +
- 2.0 * c2 * lightmap_captures.data[index].sh[3].rgb * wnormal.x +
- 2.0 * c2 * lightmap_captures.data[index].sh[1].rgb * wnormal.y +
- 2.0 * c2 * lightmap_captures.data[index].sh[2].rgb * wnormal.z);
+ c3 * lightmap_captures.data[index].sh[6].rgb * wnormal.z * wnormal.z +
+ c4 * lightmap_captures.data[index].sh[0].rgb -
+ c5 * lightmap_captures.data[index].sh[6].rgb +
+ 2.0 * c1 * lightmap_captures.data[index].sh[4].rgb * wnormal.x * wnormal.y +
+ 2.0 * c1 * lightmap_captures.data[index].sh[7].rgb * wnormal.x * wnormal.z +
+ 2.0 * c1 * lightmap_captures.data[index].sh[5].rgb * wnormal.y * wnormal.z +
+ 2.0 * c2 * lightmap_captures.data[index].sh[3].rgb * wnormal.x +
+ 2.0 * c2 * lightmap_captures.data[index].sh[1].rgb * wnormal.y +
+ 2.0 * c2 * lightmap_captures.data[index].sh[2].rgb * wnormal.z);
} else if (bool(draw_call.flags & INSTANCE_FLAGS_USE_LIGHTMAP)) { // has actual lightmap
bool uses_sh = bool(draw_call.flags & INSTANCE_FLAGS_USE_SH_LIGHTMAP);
@@ -1046,7 +1053,7 @@ void main() {
#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
if (!sc_disable_directional_lights) { //directional light
-
+#ifndef SHADOWS_DISABLED
// Do shadow and lighting in two passes to reduce register pressure
uint shadow0 = 0;
uint shadow1 = 0;
@@ -1322,6 +1329,8 @@ void main() {
}
}
+#endif // SHADOWS_DISABLED
+
for (uint i = 0; i < 8; i++) {
if (i >= scene_data.directional_light_count) {
break;
@@ -1334,16 +1343,16 @@ void main() {
// We're not doing light transmittence
float shadow = 1.0;
-
+#ifndef SHADOWS_DISABLED
if (i < 4) {
shadow = float(shadow0 >> (i * 8) & 0xFF) / 255.0;
} else {
shadow = float(shadow1 >> ((i - 4) * 8) & 0xFF) / 255.0;
}
-
+#endif
blur_shadow(shadow);
- light_compute(normal, directional_lights.data[i].direction, normalize(view), 0.0, directional_lights.data[i].color * directional_lights.data[i].energy, shadow, f0, orms, 1.0,
+ light_compute(normal, directional_lights.data[i].direction, normalize(view), 0.0, directional_lights.data[i].color * directional_lights.data[i].energy, shadow, f0, orms, 1.0, albedo, alpha,
#ifdef LIGHT_BACKLIGHT_USED
backlight,
#endif
@@ -1356,7 +1365,7 @@ void main() {
#endif
*/
#ifdef LIGHT_RIM_USED
- rim, rim_tint, albedo,
+ rim, rim_tint,
#endif
#ifdef LIGHT_CLEARCOAT_USED
clearcoat, clearcoat_gloss,
@@ -1367,9 +1376,6 @@ void main() {
#ifdef USE_SOFT_SHADOW
directional_lights.data[i].size,
#endif
-#ifdef USE_SHADOW_TO_OPACITY
- alpha,
-#endif
diffuse_light,
specular_light);
}
@@ -1393,7 +1399,7 @@ void main() {
shadow = blur_shadow(shadow);
- light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow,
+ light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha,
#ifdef LIGHT_BACKLIGHT_USED
backlight,
#endif
@@ -1407,7 +1413,6 @@ void main() {
#ifdef LIGHT_RIM_USED
rim,
rim_tint,
- albedo,
#endif
#ifdef LIGHT_CLEARCOAT_USED
clearcoat, clearcoat_gloss,
@@ -1415,9 +1420,6 @@ void main() {
#ifdef LIGHT_ANISOTROPY_USED
tangent, binormal, anisotropy,
#endif
-#ifdef USE_SHADOW_TO_OPACITY
- alpha,
-#endif
diffuse_light, specular_light);
}
} //omni lights
@@ -1441,7 +1443,7 @@ void main() {
shadow = blur_shadow(shadow);
- light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow,
+ light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha,
#ifdef LIGHT_BACKLIGHT_USED
backlight,
#endif
@@ -1455,7 +1457,6 @@ void main() {
#ifdef LIGHT_RIM_USED
rim,
rim_tint,
- albedo,
#endif
#ifdef LIGHT_CLEARCOAT_USED
clearcoat, clearcoat_gloss,
@@ -1463,9 +1464,6 @@ void main() {
#ifdef LIGHT_ANISOTROPY_USED
tangent, binormal, anisotropy,
#endif
-#ifdef USE_SHADOW_TO_OPACITY
- alpha,
-#endif
diffuse_light, specular_light);
}
} //spot lights
@@ -1481,7 +1479,7 @@ void main() {
#ifdef USE_OPAQUE_PREPASS
- if (alpha < opaque_prepass_threshold) {
+ if (alpha < scene_data.opaque_prepass_threshold) {
discard;
}
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl
index eb8fb49598..a9a4fce82a 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl
@@ -168,7 +168,8 @@ layout(set = 1, binding = 0, std140) uniform SceneData {
mediump float roughness_limiter_amount;
mediump float roughness_limiter_limit;
- uvec2 roughness_limiter_pad;
+ mediump float opaque_prepass_threshold;
+ uint roughness_limiter_pad;
bool fog_enabled;
highp float fog_density;
diff --git a/servers/rendering/renderer_rd/shaders/screen_space_reflection.glsl b/servers/rendering/renderer_rd/shaders/screen_space_reflection.glsl
index 78e0a85341..fde5688301 100644
--- a/servers/rendering/renderer_rd/shaders/screen_space_reflection.glsl
+++ b/servers/rendering/renderer_rd/shaders/screen_space_reflection.glsl
@@ -223,7 +223,6 @@ void main() {
blur_radius = (a * (sqrt(a2 + fh2) - a)) / (4.0f * h);
}
}
-
final_color = imageLoad(source_diffuse, ivec2((final_pos - 0.5) * pixel_size));
imageStore(blur_radius_image, ssC, vec4(blur_radius / 255.0)); //stored in r8
diff --git a/servers/rendering/renderer_rd/shaders/sdfgi_preprocess.glsl b/servers/rendering/renderer_rd/shaders/sdfgi_preprocess.glsl
index 4d9fa85a74..f6ec249b5e 100644
--- a/servers/rendering/renderer_rd/shaders/sdfgi_preprocess.glsl
+++ b/servers/rendering/renderer_rd/shaders/sdfgi_preprocess.glsl
@@ -102,7 +102,7 @@ dispatch_data;
struct ProcessVoxel {
uint position; // xyz 7 bit packed, extra 11 bits for neighbors.
- uint albedo; //rgb bits 0-15 albedo, bits 16-21 are normal bits (set if geometry exists toward that side), extra 11 bits for neibhbours
+ uint albedo; //rgb bits 0-15 albedo, bits 16-21 are normal bits (set if geometry exists toward that side), extra 11 bits for neighbours
uint light; //rgbe8985 encoded total saved light, extra 2 bits for neighbours
uint light_aniso; //55555 light anisotropy, extra 2 bits for neighbours
//total neighbours: 26
@@ -135,7 +135,7 @@ dispatch_data;
struct ProcessVoxel {
uint position; // xyz 7 bit packed, extra 11 bits for neighbors.
- uint albedo; //rgb bits 0-15 albedo, bits 16-21 are normal bits (set if geometry exists toward that side), extra 11 bits for neibhbours
+ uint albedo; //rgb bits 0-15 albedo, bits 16-21 are normal bits (set if geometry exists toward that side), extra 11 bits for neighbours
uint light; //rgbe8985 encoded total saved light, extra 2 bits for neighbours
uint light_aniso; //55555 light anisotropy, extra 2 bits for neighbours
//total neighbours: 26
diff --git a/servers/rendering/renderer_rd/shaders/ssao_downsample.glsl b/servers/rendering/renderer_rd/shaders/ss_effects_downsample.glsl
index ee0db6a6f0..bdabc146d8 100644
--- a/servers/rendering/renderer_rd/shaders/ssao_downsample.glsl
+++ b/servers/rendering/renderer_rd/shaders/ss_effects_downsample.glsl
@@ -42,6 +42,9 @@ layout(r16f, set = 1, binding = 0) uniform restrict writeonly image2DArray dest_
layout(r16f, set = 2, binding = 0) uniform restrict writeonly image2DArray dest_image1;
layout(r16f, set = 2, binding = 1) uniform restrict writeonly image2DArray dest_image2;
layout(r16f, set = 2, binding = 2) uniform restrict writeonly image2DArray dest_image3;
+#ifdef GENERATE_FULL_MIPS
+layout(r16f, set = 2, binding = 3) uniform restrict writeonly image2DArray dest_image4;
+#endif
#endif
vec4 screen_space_to_view_space_depth(vec4 p_depth) {
@@ -150,7 +153,27 @@ void prepare_depths_and_mips(vec4 p_samples, uvec2 p_output_coord, uvec2 p_gtid)
float avg = mip_smart_average(vec4(sample_00, sample_01, sample_10, sample_11));
imageStore(dest_image3, ivec3(p_output_coord.x, p_output_coord.y, depth_array_index), vec4(avg));
+#ifndef GENERATE_FULL_MIPS
+ }
+#else
+ depth_buffer[depth_array_index][buffer_coord.x][buffer_coord.y] = avg;
}
+ still_alive = p_gtid.x % 16 == depth_array_offset.x && depth_array_offset.y % 16 == depth_array_offset.y;
+
+ p_output_coord /= 2;
+ groupMemoryBarrier();
+ barrier();
+
+ if (still_alive) {
+ float sample_00 = depth_buffer[depth_array_index][buffer_coord.x + 0][buffer_coord.y + 0];
+ float sample_01 = depth_buffer[depth_array_index][buffer_coord.x + 0][buffer_coord.y + 8];
+ float sample_10 = depth_buffer[depth_array_index][buffer_coord.x + 8][buffer_coord.y + 0];
+ float sample_11 = depth_buffer[depth_array_index][buffer_coord.x + 8][buffer_coord.y + 8];
+
+ float avg = mip_smart_average(vec4(sample_00, sample_01, sample_10, sample_11));
+ imageStore(dest_image4, ivec3(p_output_coord.x, p_output_coord.y, depth_array_index), vec4(avg));
+ }
+#endif
}
#else
#ifndef USE_HALF_BUFFERS
diff --git a/servers/rendering/renderer_rd/shaders/ssao.glsl b/servers/rendering/renderer_rd/shaders/ssao.glsl
index 6e945edfcd..18cab75c3b 100644
--- a/servers/rendering/renderer_rd/shaders/ssao.glsl
+++ b/servers/rendering/renderer_rd/shaders/ssao.glsl
@@ -23,8 +23,6 @@
#VERSION_DEFINES
-#define SSAO_ADAPTIVE_TAP_BASE_COUNT 5
-
#define INTELSSAO_MAIN_DISK_SAMPLE_COUNT (32)
const vec4 sample_pattern[INTELSSAO_MAIN_DISK_SAMPLE_COUNT] = {
vec4(0.78488064, 0.56661671, 1.500000, -0.126083), vec4(0.26022232, -0.29575172, 1.500000, -1.064030), vec4(0.10459357, 0.08372527, 1.110000, -2.730563), vec4(-0.68286800, 0.04963045, 1.090000, -0.498827),
@@ -62,7 +60,6 @@ const int num_taps[5] = { 3, 5, 12, 0, 0 };
#define SSAO_REDUCE_RADIUS_NEAR_SCREEN_BORDER_ENABLE_AT_QUALITY_PRESET (1)
#define SSAO_MAX_TAPS 32
-#define SSAO_MAX_REF_TAPS 512
#define SSAO_ADAPTIVE_TAP_BASE_COUNT 5
#define SSAO_ADAPTIVE_TAP_FLEXIBLE_COUNT (SSAO_MAX_TAPS - SSAO_ADAPTIVE_TAP_BASE_COUNT)
#define SSAO_DEPTH_MIP_LEVELS 4
diff --git a/servers/rendering/renderer_rd/shaders/ssao_blur.glsl b/servers/rendering/renderer_rd/shaders/ssao_blur.glsl
index d9cd2b4e85..b154f5e527 100644
--- a/servers/rendering/renderer_rd/shaders/ssao_blur.glsl
+++ b/servers/rendering/renderer_rd/shaders/ssao_blur.glsl
@@ -128,19 +128,19 @@ void main() {
#ifdef MODE_NON_SMART
- vec2 halfPixel = params.half_screen_pixel_size * 0.5f;
+ vec2 half_pixel = params.half_screen_pixel_size * 0.5;
vec2 uv = (vec2(gl_GlobalInvocationID.xy) + vec2(0.5, 0.5)) * params.half_screen_pixel_size;
- vec2 centre = textureLod(source_ssao, vec2(uv), 0.0).xy;
+ vec2 center = textureLod(source_ssao, vec2(uv), 0.0).xy;
vec4 vals;
- vals.x = textureLod(source_ssao, vec2(uv + vec2(-halfPixel.x * 3, -halfPixel.y)), 0.0).x;
- vals.y = textureLod(source_ssao, vec2(uv + vec2(+halfPixel.x, -halfPixel.y * 3)), 0.0).x;
- vals.z = textureLod(source_ssao, vec2(uv + vec2(-halfPixel.x, +halfPixel.y * 3)), 0.0).x;
- vals.w = textureLod(source_ssao, vec2(uv + vec2(+halfPixel.x * 3, +halfPixel.y)), 0.0).x;
+ vals.x = textureLod(source_ssao, vec2(uv + vec2(-half_pixel.x * 3, -half_pixel.y)), 0.0).x;
+ vals.y = textureLod(source_ssao, vec2(uv + vec2(+half_pixel.x, -half_pixel.y * 3)), 0.0).x;
+ vals.z = textureLod(source_ssao, vec2(uv + vec2(-half_pixel.x, +half_pixel.y * 3)), 0.0).x;
+ vals.w = textureLod(source_ssao, vec2(uv + vec2(+half_pixel.x * 3, +half_pixel.y)), 0.0).x;
- vec2 sampled = vec2(dot(vals, vec4(0.2)) + centre.x * 0.2, centre.y);
+ vec2 sampled = vec2(dot(vals, vec4(0.2)) + center.x * 0.2, center.y);
#else
#ifdef MODE_SMART
diff --git a/servers/rendering/renderer_rd/shaders/ssao_importance_map.glsl b/servers/rendering/renderer_rd/shaders/ssao_importance_map.glsl
index 687fe1e6e2..23eba34d63 100644
--- a/servers/rendering/renderer_rd/shaders/ssao_importance_map.glsl
+++ b/servers/rendering/renderer_rd/shaders/ssao_importance_map.glsl
@@ -26,7 +26,7 @@
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
#ifdef GENERATE_MAP
-layout(set = 0, binding = 0) uniform sampler2DArray source_ssao;
+layout(set = 0, binding = 0) uniform sampler2DArray source_texture;
#else
layout(set = 0, binding = 0) uniform sampler2D source_importance;
#endif
@@ -56,11 +56,10 @@ void main() {
vec2 base_uv = (vec2(base_position) + vec2(0.5f, 0.5f)) * params.half_screen_pixel_size;
- float avg = 0.0;
float minV = 1.0;
float maxV = 0.0;
for (int i = 0; i < 4; i++) {
- vec4 vals = textureGather(source_ssao, vec3(base_uv, i));
+ vec4 vals = textureGather(source_texture, vec3(base_uv, i));
// apply the same modifications that would have been applied in the main shader
vals = params.intensity * vals;
@@ -69,8 +68,6 @@ void main() {
vals = pow(clamp(vals, 0.0, 1.0), vec4(params.power));
- avg += dot(vec4(vals.x, vals.y, vals.z, vals.w), vec4(1.0 / 16.0, 1.0 / 16.0, 1.0 / 16.0, 1.0 / 16.0));
-
maxV = max(maxV, max(max(vals.x, vals.y), max(vals.z, vals.w)));
minV = min(minV, min(min(vals.x, vals.y), min(vals.z, vals.w)));
}
diff --git a/servers/rendering/renderer_rd/shaders/ssil.glsl b/servers/rendering/renderer_rd/shaders/ssil.glsl
new file mode 100644
index 0000000000..d1f8f42790
--- /dev/null
+++ b/servers/rendering/renderer_rd/shaders/ssil.glsl
@@ -0,0 +1,444 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2016, Intel Corporation
+// 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.
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// File changes (yyyy-mm-dd)
+// 2016-09-07: filip.strugar@intel.com: first commit
+// 2020-12-05: clayjohn: convert to Vulkan and Godot
+// 2021-05-27: clayjohn: convert SSAO to SSIL
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#[compute]
+
+#version 450
+
+#VERSION_DEFINES
+
+#define SSIL_MAIN_DISK_SAMPLE_COUNT (32)
+const vec4 sample_pattern[SSIL_MAIN_DISK_SAMPLE_COUNT] = {
+ vec4(0.78488064, 0.56661671, 1.500000, -0.126083), vec4(0.26022232, -0.29575172, 1.500000, -1.064030), vec4(0.10459357, 0.08372527, 1.110000, -2.730563), vec4(-0.68286800, 0.04963045, 1.090000, -0.498827),
+ vec4(-0.13570161, -0.64190155, 1.250000, -0.532765), vec4(-0.26193795, -0.08205118, 0.670000, -1.783245), vec4(-0.61177456, 0.66664219, 0.710000, -0.044234), vec4(0.43675563, 0.25119025, 0.610000, -1.167283),
+ vec4(0.07884444, 0.86618668, 0.640000, -0.459002), vec4(-0.12790935, -0.29869005, 0.600000, -1.729424), vec4(-0.04031125, 0.02413622, 0.600000, -4.792042), vec4(0.16201244, -0.52851415, 0.790000, -1.067055),
+ vec4(-0.70991218, 0.47301072, 0.640000, -0.335236), vec4(0.03277707, -0.22349690, 0.600000, -1.982384), vec4(0.68921727, 0.36800742, 0.630000, -0.266718), vec4(0.29251814, 0.37775412, 0.610000, -1.422520),
+ vec4(-0.12224089, 0.96582592, 0.600000, -0.426142), vec4(0.11071457, -0.16131058, 0.600000, -2.165947), vec4(0.46562141, -0.59747696, 0.600000, -0.189760), vec4(-0.51548797, 0.11804193, 0.600000, -1.246800),
+ vec4(0.89141309, -0.42090443, 0.600000, 0.028192), vec4(-0.32402530, -0.01591529, 0.600000, -1.543018), vec4(0.60771245, 0.41635221, 0.600000, -0.605411), vec4(0.02379565, -0.08239821, 0.600000, -3.809046),
+ vec4(0.48951152, -0.23657045, 0.600000, -1.189011), vec4(-0.17611565, -0.81696892, 0.600000, -0.513724), vec4(-0.33930185, -0.20732205, 0.600000, -1.698047), vec4(-0.91974425, 0.05403209, 0.600000, 0.062246),
+ vec4(-0.15064627, -0.14949332, 0.600000, -1.896062), vec4(0.53180975, -0.35210401, 0.600000, -0.758838), vec4(0.41487166, 0.81442589, 0.600000, -0.505648), vec4(-0.24106961, -0.32721516, 0.600000, -1.665244)
+};
+
+// these values can be changed (up to SSIL_MAX_TAPS) with no changes required elsewhere; values for 4th and 5th preset are ignored but array needed to avoid compilation errors
+// the actual number of texture samples is two times this value (each "tap" has two symmetrical depth texture samples)
+const int num_taps[5] = { 3, 5, 12, 0, 0 };
+
+#define SSIL_TILT_SAMPLES_ENABLE_AT_QUALITY_PRESET (99) // to disable simply set to 99 or similar
+#define SSIL_TILT_SAMPLES_AMOUNT (0.4)
+//
+#define SSIL_HALOING_REDUCTION_ENABLE_AT_QUALITY_PRESET (1) // to disable simply set to 99 or similar
+#define SSIL_HALOING_REDUCTION_AMOUNT (0.8) // values from 0.0 - 1.0, 1.0 means max weighting (will cause artifacts, 0.8 is more reasonable)
+//
+#define SSIL_DEPTH_MIPS_ENABLE_AT_QUALITY_PRESET (2)
+#define SSIL_DEPTH_MIPS_GLOBAL_OFFSET (-4.3) // best noise/quality/performance tradeoff, found empirically
+//
+// !!warning!! the edge handling is hard-coded to 'disabled' on quality level 0, and enabled above, on the C++ side; while toggling it here will work for
+// testing purposes, it will not yield performance gains (or correct results)
+#define SSIL_DEPTH_BASED_EDGES_ENABLE_AT_QUALITY_PRESET (1)
+//
+#define SSIL_REDUCE_RADIUS_NEAR_SCREEN_BORDER_ENABLE_AT_QUALITY_PRESET (1)
+
+#define SSIL_MAX_TAPS 32
+#define SSIL_ADAPTIVE_TAP_BASE_COUNT 5
+#define SSIL_ADAPTIVE_TAP_FLEXIBLE_COUNT (SSIL_MAX_TAPS - SSIL_ADAPTIVE_TAP_BASE_COUNT)
+#define SSIL_DEPTH_MIP_LEVELS 4
+
+layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
+
+layout(set = 0, binding = 0) uniform sampler2DArray source_depth_mipmaps;
+layout(rgba8, set = 0, binding = 1) uniform restrict readonly image2D source_normal;
+layout(set = 0, binding = 2) uniform Constants { //get into a lower set
+ vec4 rotation_matrices[20];
+}
+constants;
+
+#ifdef ADAPTIVE
+layout(rgba16, set = 1, binding = 0) uniform restrict readonly image2DArray source_ssil;
+layout(set = 1, binding = 1) uniform sampler2D source_importance;
+layout(set = 1, binding = 2, std430) buffer Counter {
+ uint sum;
+}
+counter;
+#endif
+
+layout(rgba16, set = 2, binding = 0) uniform restrict writeonly image2D dest_image;
+layout(r8, set = 2, binding = 1) uniform image2D edges_weights_image;
+
+layout(set = 3, binding = 0) uniform sampler2D last_frame;
+layout(set = 3, binding = 1) uniform ProjectionConstants {
+ mat4 reprojection;
+}
+projection_constants;
+
+layout(push_constant, binding = 3, std430) uniform Params {
+ ivec2 screen_size;
+ int pass;
+ int quality;
+
+ vec2 half_screen_pixel_size;
+ vec2 half_screen_pixel_size_x025;
+
+ vec2 NDC_to_view_mul;
+ vec2 NDC_to_view_add;
+
+ vec2 pad2;
+ float z_near;
+ float z_far;
+
+ float radius;
+ float intensity;
+ int size_multiplier;
+ int pad;
+
+ float fade_out_mul;
+ float fade_out_add;
+ float normal_rejection_amount;
+ float inv_radius_near_limit;
+
+ bool is_orthogonal;
+ float neg_inv_radius;
+ float load_counter_avg_div;
+ float adaptive_sample_limit;
+
+ ivec2 pass_coord_offset;
+ vec2 pass_uv_offset;
+}
+params;
+
+float pack_edges(vec4 p_edgesLRTB) {
+ p_edgesLRTB = round(clamp(p_edgesLRTB, 0.0, 1.0) * 3.05);
+ return dot(p_edgesLRTB, vec4(64.0 / 255.0, 16.0 / 255.0, 4.0 / 255.0, 1.0 / 255.0));
+}
+
+vec3 NDC_to_view_space(vec2 p_pos, float p_viewspace_depth) {
+ if (params.is_orthogonal) {
+ return vec3((params.NDC_to_view_mul * p_pos.xy + params.NDC_to_view_add), p_viewspace_depth);
+ } else {
+ return vec3((params.NDC_to_view_mul * p_pos.xy + params.NDC_to_view_add) * p_viewspace_depth, p_viewspace_depth);
+ }
+}
+
+// calculate effect radius and fit our screen sampling pattern inside it
+void calculate_radius_parameters(const float p_pix_center_length, const vec2 p_pixel_size_at_center, out float r_lookup_radius, out float r_radius, out float r_fallof_sq) {
+ r_radius = params.radius;
+
+ // when too close, on-screen sampling disk will grow beyond screen size; limit this to avoid closeup temporal artifacts
+ const float too_close_limit = clamp(p_pix_center_length * params.inv_radius_near_limit, 0.0, 1.0) * 0.8 + 0.2;
+
+ r_radius *= too_close_limit;
+
+ // 0.85 is to reduce the radius to allow for more samples on a slope to still stay within influence
+ r_lookup_radius = (0.85 * r_radius) / p_pixel_size_at_center.x;
+
+ // used to calculate falloff (both for AO samples and per-sample weights)
+ r_fallof_sq = -1.0 / (r_radius * r_radius);
+}
+
+vec4 calculate_edges(const float p_center_z, const float p_left_z, const float p_right_z, const float p_top_z, const float p_bottom_z) {
+ // slope-sensitive depth-based edge detection
+ vec4 edgesLRTB = vec4(p_left_z, p_right_z, p_top_z, p_bottom_z) - p_center_z;
+ vec4 edgesLRTB_slope_adjusted = edgesLRTB + edgesLRTB.yxwz;
+ edgesLRTB = min(abs(edgesLRTB), abs(edgesLRTB_slope_adjusted));
+ return clamp((1.3 - edgesLRTB / (p_center_z * 0.040)), 0.0, 1.0);
+}
+
+vec3 decode_normal(vec3 p_encoded_normal) {
+ vec3 normal = p_encoded_normal * 2.0 - 1.0;
+ return normal;
+}
+
+vec3 load_normal(ivec2 p_pos) {
+ vec3 encoded_normal = imageLoad(source_normal, p_pos).xyz;
+ encoded_normal.z = 1.0 - encoded_normal.z;
+ return decode_normal(encoded_normal);
+}
+
+vec3 load_normal(ivec2 p_pos, ivec2 p_offset) {
+ vec3 encoded_normal = imageLoad(source_normal, p_pos + p_offset).xyz;
+ encoded_normal.z = 1.0 - encoded_normal.z;
+ return decode_normal(encoded_normal);
+}
+
+// all vectors in viewspace
+float calculate_pixel_obscurance(vec3 p_pixel_normal, vec3 p_hit_delta, float p_fallof_sq) {
+ float length_sq = dot(p_hit_delta, p_hit_delta);
+ float NdotD = dot(p_pixel_normal, p_hit_delta) / sqrt(length_sq);
+
+ float falloff_mult = max(0.0, length_sq * p_fallof_sq + 1.0);
+
+ return max(0, NdotD - 0.05) * falloff_mult;
+}
+
+void SSIL_tap_inner(const int p_quality_level, inout vec3 r_color_sum, inout float r_obscurance_sum, inout float r_weight_sum, const vec2 p_sampling_uv, const float p_mip_level, const vec3 p_pix_center_pos, vec3 p_pixel_normal, const float p_fallof_sq, const float p_weight_mod) {
+ // get depth at sample
+ float viewspace_sample_z = textureLod(source_depth_mipmaps, vec3(p_sampling_uv, params.pass), p_mip_level).x;
+ vec3 sample_normal = load_normal(ivec2(p_sampling_uv * vec2(params.screen_size)));
+
+ // convert to viewspace
+ vec3 hit_pos = NDC_to_view_space(p_sampling_uv.xy, viewspace_sample_z);
+ vec3 hit_delta = hit_pos - p_pix_center_pos;
+
+ float obscurance = calculate_pixel_obscurance(p_pixel_normal, hit_delta, p_fallof_sq);
+ float weight = 1.0;
+
+ if (p_quality_level >= SSIL_HALOING_REDUCTION_ENABLE_AT_QUALITY_PRESET) {
+ float reduct = max(0, -hit_delta.z);
+ reduct = clamp(reduct * params.neg_inv_radius + 2.0, 0.0, 1.0);
+ weight = SSIL_HALOING_REDUCTION_AMOUNT * reduct + (1.0 - SSIL_HALOING_REDUCTION_AMOUNT);
+ }
+
+ // Translate sampling_uv to last screen's coordinates
+ const vec4 sample_pos = projection_constants.reprojection * vec4(p_sampling_uv * 2.0 - 1.0, (viewspace_sample_z - params.z_near) / (params.z_far - params.z_near) * 2.0 - 1.0, 1.0);
+ vec2 reprojected_sampling_uv = (sample_pos.xy / sample_pos.w) * 0.5 + 0.5;
+
+ weight *= p_weight_mod;
+
+ r_obscurance_sum += obscurance * weight;
+
+ vec3 sample_color = textureLod(last_frame, reprojected_sampling_uv, 5.0).rgb;
+ // Reduce impact of fireflies by tonemapping before averaging: http://graphicrants.blogspot.com/2013/12/tone-mapping.html
+ sample_color /= (1.0 + dot(sample_color, vec3(0.299, 0.587, 0.114)));
+ r_color_sum += sample_color * obscurance * weight * mix(1.0, smoothstep(0.0, 0.1, -dot(sample_normal, normalize(hit_delta))), params.normal_rejection_amount);
+ r_weight_sum += weight;
+}
+
+void SSILTap(const int p_quality_level, inout vec3 r_color_sum, inout float r_obscurance_sum, inout float r_weight_sum, const int p_tap_index, const mat2 p_rot_scale, const vec3 p_pix_center_pos, vec3 p_pixel_normal, const vec2 p_normalized_screen_pos, const float p_mip_offset, const float p_fallof_sq, float p_weight_mod, vec2 p_norm_xy, float p_norm_xy_length) {
+ vec2 sample_offset;
+ float sample_pow_2_len;
+
+ // patterns
+ {
+ vec4 new_sample = sample_pattern[p_tap_index];
+ sample_offset = new_sample.xy * p_rot_scale;
+ sample_pow_2_len = new_sample.w; // precalculated, same as: sample_pow_2_len = log2( length( new_sample.xy ) );
+ p_weight_mod *= new_sample.z;
+ }
+
+ // snap to pixel center (more correct obscurance math, avoids artifacts)
+ sample_offset = round(sample_offset);
+
+ // calculate MIP based on the sample distance from the centre, similar to as described
+ // in http://graphics.cs.williams.edu/papers/SAOHPG12/.
+ float mip_level = (p_quality_level < SSIL_DEPTH_MIPS_ENABLE_AT_QUALITY_PRESET) ? (0) : (sample_pow_2_len + p_mip_offset);
+
+ vec2 sampling_uv = sample_offset * params.half_screen_pixel_size + p_normalized_screen_pos;
+
+ SSIL_tap_inner(p_quality_level, r_color_sum, r_obscurance_sum, r_weight_sum, sampling_uv, mip_level, p_pix_center_pos, p_pixel_normal, p_fallof_sq, p_weight_mod);
+
+ // for the second tap, just use the mirrored offset
+ vec2 sample_offset_mirrored_uv = -sample_offset;
+
+ // tilt the second set of samples so that the disk is effectively rotated by the normal
+ // effective at removing one set of artifacts, but too expensive for lower quality settings
+ if (p_quality_level >= SSIL_TILT_SAMPLES_ENABLE_AT_QUALITY_PRESET) {
+ float dot_norm = dot(sample_offset_mirrored_uv, p_norm_xy);
+ sample_offset_mirrored_uv -= dot_norm * p_norm_xy_length * p_norm_xy;
+ sample_offset_mirrored_uv = round(sample_offset_mirrored_uv);
+ }
+
+ // snap to pixel center (more correct obscurance math, avoids artifacts)
+ vec2 sampling_mirrored_uv = sample_offset_mirrored_uv * params.half_screen_pixel_size + p_normalized_screen_pos;
+
+ SSIL_tap_inner(p_quality_level, r_color_sum, r_obscurance_sum, r_weight_sum, sampling_mirrored_uv, mip_level, p_pix_center_pos, p_pixel_normal, p_fallof_sq, p_weight_mod);
+}
+
+void generate_SSIL(out vec3 r_color, out vec4 r_edges, out float r_obscurance, out float r_weight, const vec2 p_pos, int p_quality_level, bool p_adaptive_base) {
+ vec2 pos_rounded = trunc(p_pos);
+ uvec2 upos = uvec2(pos_rounded);
+
+ const int number_of_taps = (p_adaptive_base) ? (SSIL_ADAPTIVE_TAP_BASE_COUNT) : (num_taps[p_quality_level]);
+ float pix_z, pix_left_z, pix_top_z, pix_right_z, pix_bottom_z;
+
+ vec4 valuesUL = textureGather(source_depth_mipmaps, vec3(pos_rounded * params.half_screen_pixel_size, params.pass));
+ vec4 valuesBR = textureGather(source_depth_mipmaps, vec3((pos_rounded + vec2(1.0)) * params.half_screen_pixel_size, params.pass));
+
+ // get this pixel's viewspace depth
+ pix_z = valuesUL.y;
+
+ // get left right top bottom neighbouring pixels for edge detection (gets compiled out on quality_level == 0)
+ pix_left_z = valuesUL.x;
+ pix_top_z = valuesUL.z;
+ pix_right_z = valuesBR.z;
+ pix_bottom_z = valuesBR.x;
+
+ vec2 normalized_screen_pos = pos_rounded * params.half_screen_pixel_size + params.half_screen_pixel_size_x025;
+ vec3 pix_center_pos = NDC_to_view_space(normalized_screen_pos, pix_z);
+
+ // Load this pixel's viewspace normal
+ uvec2 full_res_coord = upos * 2 * params.size_multiplier + params.pass_coord_offset.xy;
+ vec3 pixel_normal = load_normal(ivec2(full_res_coord));
+
+ const vec2 pixel_size_at_center = NDC_to_view_space(normalized_screen_pos.xy + params.half_screen_pixel_size, pix_center_pos.z).xy - pix_center_pos.xy;
+
+ float pixel_lookup_radius;
+ float fallof_sq;
+
+ // calculate effect radius and fit our screen sampling pattern inside it
+ float viewspace_radius;
+ calculate_radius_parameters(length(pix_center_pos), pixel_size_at_center, pixel_lookup_radius, viewspace_radius, fallof_sq);
+
+ // calculate samples rotation/scaling
+ mat2 rot_scale_matrix;
+ uint pseudo_random_index;
+
+ {
+ vec4 rotation_scale;
+ // reduce effect radius near the screen edges slightly; ideally, one would render a larger depth buffer (5% on each side) instead
+ if (!p_adaptive_base && (p_quality_level >= SSIL_REDUCE_RADIUS_NEAR_SCREEN_BORDER_ENABLE_AT_QUALITY_PRESET)) {
+ float near_screen_border = min(min(normalized_screen_pos.x, 1.0 - normalized_screen_pos.x), min(normalized_screen_pos.y, 1.0 - normalized_screen_pos.y));
+ near_screen_border = clamp(10.0 * near_screen_border + 0.6, 0.0, 1.0);
+ pixel_lookup_radius *= near_screen_border;
+ }
+
+ // load & update pseudo-random rotation matrix
+ pseudo_random_index = uint(pos_rounded.y * 2 + pos_rounded.x) % 5;
+ rotation_scale = constants.rotation_matrices[params.pass * 5 + pseudo_random_index];
+ rot_scale_matrix = mat2(rotation_scale.x * pixel_lookup_radius, rotation_scale.y * pixel_lookup_radius, rotation_scale.z * pixel_lookup_radius, rotation_scale.w * pixel_lookup_radius);
+ }
+
+ // the main obscurance & sample weight storage
+ vec3 color_sum = vec3(0.0);
+ float obscurance_sum = 0.0;
+ float weight_sum = 0.0;
+
+ // edge mask for between this and left/right/top/bottom neighbour pixels - not used in quality level 0 so initialize to "no edge" (1 is no edge, 0 is edge)
+ vec4 edgesLRTB = vec4(1.0, 1.0, 1.0, 1.0);
+
+ // Move center pixel slightly towards camera to avoid imprecision artifacts due to using of 16bit depth buffer; a lot smaller offsets needed when using 32bit floats
+ pix_center_pos *= 0.9992;
+
+ if (!p_adaptive_base && (p_quality_level >= SSIL_DEPTH_BASED_EDGES_ENABLE_AT_QUALITY_PRESET)) {
+ edgesLRTB = calculate_edges(pix_z, pix_left_z, pix_right_z, pix_top_z, pix_bottom_z);
+ }
+
+ const float global_mip_offset = SSIL_DEPTH_MIPS_GLOBAL_OFFSET;
+ float mip_offset = (p_quality_level < SSIL_DEPTH_MIPS_ENABLE_AT_QUALITY_PRESET) ? (0) : (log2(pixel_lookup_radius) + global_mip_offset);
+
+ // Used to tilt the second set of samples so that the disk is effectively rotated by the normal
+ // effective at removing one set of artifacts, but too expensive for lower quality settings
+ vec2 norm_xy = vec2(pixel_normal.x, pixel_normal.y);
+ float norm_xy_length = length(norm_xy);
+ norm_xy /= vec2(norm_xy_length, -norm_xy_length);
+ norm_xy_length *= SSIL_TILT_SAMPLES_AMOUNT;
+
+ // standard, non-adaptive approach
+ if ((p_quality_level != 3) || p_adaptive_base) {
+ for (int i = 0; i < number_of_taps; i++) {
+ SSILTap(p_quality_level, color_sum, obscurance_sum, weight_sum, i, rot_scale_matrix, pix_center_pos, pixel_normal, normalized_screen_pos, mip_offset, fallof_sq, 1.0, norm_xy, norm_xy_length);
+ }
+ }
+#ifdef ADAPTIVE
+ else {
+ // add new ones if needed
+ vec2 full_res_uv = normalized_screen_pos + params.pass_uv_offset.xy;
+ float importance = textureLod(source_importance, full_res_uv, 0.0).x;
+
+ //Need to store obscurance from base pass
+ // load existing base values
+ vec4 base_values = imageLoad(source_ssil, ivec3(upos, params.pass));
+ weight_sum += imageLoad(edges_weights_image, ivec2(upos)).r * float(SSIL_ADAPTIVE_TAP_BASE_COUNT * 4.0);
+ color_sum += (base_values.rgb) * weight_sum;
+ obscurance_sum += (base_values.a) * weight_sum;
+
+ // increase importance around edges
+ float edge_count = dot(1.0 - edgesLRTB, vec4(1.0, 1.0, 1.0, 1.0));
+
+ float avg_total_importance = float(counter.sum) * params.load_counter_avg_div;
+
+ float importance_limiter = clamp(params.adaptive_sample_limit / avg_total_importance, 0.0, 1.0);
+ importance *= importance_limiter;
+
+ float additional_sample_count = SSIL_ADAPTIVE_TAP_FLEXIBLE_COUNT * importance;
+
+ const float blend_range = 3.0;
+ const float blend_range_inv = 1.0 / blend_range;
+
+ additional_sample_count += 0.5;
+ uint additional_samples = uint(additional_sample_count);
+ uint additional_samples_to = min(SSIL_MAX_TAPS, additional_samples + SSIL_ADAPTIVE_TAP_BASE_COUNT);
+
+ for (uint i = SSIL_ADAPTIVE_TAP_BASE_COUNT; i < additional_samples_to; i++) {
+ additional_sample_count -= 1.0f;
+ float weight_mod = clamp(additional_sample_count * blend_range_inv, 0.0, 1.0);
+ SSILTap(p_quality_level, color_sum, obscurance_sum, weight_sum, int(i), rot_scale_matrix, pix_center_pos, pixel_normal, normalized_screen_pos, mip_offset, fallof_sq, weight_mod, norm_xy, norm_xy_length);
+ }
+ }
+#endif
+
+ // Early out for adaptive base
+ if (p_adaptive_base) {
+ vec3 color = color_sum / weight_sum;
+
+ r_color = color;
+ r_edges = vec4(0.0);
+ r_obscurance = obscurance_sum / weight_sum;
+ r_weight = weight_sum;
+ return;
+ }
+
+ // Calculate weighted average
+ vec3 color = color_sum / weight_sum;
+ color /= 1.0 - dot(color, vec3(0.299, 0.587, 0.114));
+
+ // Calculate fadeout (1 close, gradient, 0 far)
+ float fade_out = clamp(pix_center_pos.z * params.fade_out_mul + params.fade_out_add, 0.0, 1.0);
+
+ // Reduce the SSIL if we're on the edge to remove artifacts on edges (we don't care for the lower quality one)
+ if (!p_adaptive_base && (p_quality_level >= SSIL_DEPTH_BASED_EDGES_ENABLE_AT_QUALITY_PRESET)) {
+ // when there's more than 2 opposite edges, start fading out the occlusion to reduce aliasing artifacts
+ float edge_fadeout_factor = clamp((1.0 - edgesLRTB.x - edgesLRTB.y) * 0.35, 0.0, 1.0) + clamp((1.0 - edgesLRTB.z - edgesLRTB.w) * 0.35, 0.0, 1.0);
+
+ fade_out *= clamp(1.0 - edge_fadeout_factor, 0.0, 1.0);
+ }
+
+ color = params.intensity * color;
+
+ color *= fade_out;
+
+ // outputs!
+ r_color = color;
+ r_edges = edgesLRTB; // These are used to prevent blurring across edges, 1 means no edge, 0 means edge, 0.5 means half way there, etc.
+ r_obscurance = clamp((obscurance_sum / weight_sum) * params.intensity, 0.0, 1.0);
+ r_weight = weight_sum;
+}
+
+void main() {
+ vec3 out_color;
+ float out_obscurance;
+ float out_weight;
+ vec4 out_edges;
+ ivec2 ssC = ivec2(gl_GlobalInvocationID.xy);
+ if (any(greaterThanEqual(ssC, params.screen_size))) { //too large, do nothing
+ return;
+ }
+
+ vec2 uv = vec2(gl_GlobalInvocationID) + vec2(0.5);
+#ifdef SSIL_BASE
+ generate_SSIL(out_color, out_edges, out_obscurance, out_weight, uv, params.quality, true);
+
+ imageStore(dest_image, ssC, vec4(out_color, out_obscurance));
+ imageStore(edges_weights_image, ssC, vec4(out_weight / (float(SSIL_ADAPTIVE_TAP_BASE_COUNT) * 4.0)));
+#else
+ generate_SSIL(out_color, out_edges, out_obscurance, out_weight, uv, params.quality, false); // pass in quality levels
+
+ imageStore(dest_image, ssC, vec4(out_color, out_obscurance));
+ imageStore(edges_weights_image, ssC, vec4(pack_edges(out_edges)));
+#endif
+}
diff --git a/servers/rendering/renderer_rd/shaders/ssil_blur.glsl b/servers/rendering/renderer_rd/shaders/ssil_blur.glsl
new file mode 100644
index 0000000000..11861e261f
--- /dev/null
+++ b/servers/rendering/renderer_rd/shaders/ssil_blur.glsl
@@ -0,0 +1,124 @@
+#[compute]
+
+#version 450
+
+#VERSION_DEFINES
+
+layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
+
+layout(set = 0, binding = 0) uniform sampler2D source_ssil;
+
+layout(rgba16, set = 1, binding = 0) uniform restrict writeonly image2D dest_image;
+
+layout(r8, set = 2, binding = 0) uniform restrict readonly image2D source_edges;
+
+layout(push_constant, binding = 1, std430) uniform Params {
+ float edge_sharpness;
+ float pad;
+ vec2 half_screen_pixel_size;
+}
+params;
+
+vec4 unpack_edges(float p_packed_val) {
+ uint packed_val = uint(p_packed_val * 255.5);
+ vec4 edgesLRTB;
+ edgesLRTB.x = float((packed_val >> 6) & 0x03) / 3.0;
+ edgesLRTB.y = float((packed_val >> 4) & 0x03) / 3.0;
+ edgesLRTB.z = float((packed_val >> 2) & 0x03) / 3.0;
+ edgesLRTB.w = float((packed_val >> 0) & 0x03) / 3.0;
+
+ return clamp(edgesLRTB + params.edge_sharpness, 0.0, 1.0);
+}
+
+void add_sample(vec4 p_ssil_value, float p_edge_value, inout vec4 r_sum, inout float r_sum_weight) {
+ float weight = p_edge_value;
+
+ r_sum += (weight * p_ssil_value);
+ r_sum_weight += weight;
+}
+
+#ifdef MODE_WIDE
+vec4 sample_blurred_wide(ivec2 p_pos, vec2 p_coord) {
+ vec4 ssil_value = textureLodOffset(source_ssil, vec2(p_coord), 0.0, ivec2(0, 0));
+ vec4 ssil_valueL = textureLodOffset(source_ssil, vec2(p_coord), 0.0, ivec2(-2, 0));
+ vec4 ssil_valueT = textureLodOffset(source_ssil, vec2(p_coord), 0.0, ivec2(0, -2));
+ vec4 ssil_valueR = textureLodOffset(source_ssil, vec2(p_coord), 0.0, ivec2(2, 0));
+ vec4 ssil_valueB = textureLodOffset(source_ssil, vec2(p_coord), 0.0, ivec2(0, 2));
+
+ vec4 edgesLRTB = unpack_edges(imageLoad(source_edges, p_pos).r);
+ edgesLRTB.x *= unpack_edges(imageLoad(source_edges, p_pos + ivec2(-2, 0)).r).y;
+ edgesLRTB.z *= unpack_edges(imageLoad(source_edges, p_pos + ivec2(0, -2)).r).w;
+ edgesLRTB.y *= unpack_edges(imageLoad(source_edges, p_pos + ivec2(2, 0)).r).x;
+ edgesLRTB.w *= unpack_edges(imageLoad(source_edges, p_pos + ivec2(0, 2)).r).z;
+
+ float sum_weight = 0.8;
+ vec4 sum = ssil_value * sum_weight;
+
+ add_sample(ssil_valueL, edgesLRTB.x, sum, sum_weight);
+ add_sample(ssil_valueR, edgesLRTB.y, sum, sum_weight);
+ add_sample(ssil_valueT, edgesLRTB.z, sum, sum_weight);
+ add_sample(ssil_valueB, edgesLRTB.w, sum, sum_weight);
+
+ vec4 ssil_avg = sum / sum_weight;
+
+ ssil_value = ssil_avg;
+
+ return ssil_value;
+}
+#endif
+
+#ifdef MODE_SMART
+vec4 sample_blurred(ivec2 p_pos, vec2 p_coord) {
+ vec4 vC = textureLodOffset(source_ssil, vec2(p_coord), 0.0, ivec2(0, 0));
+ vec4 vL = textureLodOffset(source_ssil, vec2(p_coord), 0.0, ivec2(-1, 0));
+ vec4 vT = textureLodOffset(source_ssil, vec2(p_coord), 0.0, ivec2(0, -1));
+ vec4 vR = textureLodOffset(source_ssil, vec2(p_coord), 0.0, ivec2(1, 0));
+ vec4 vB = textureLodOffset(source_ssil, vec2(p_coord), 0.0, ivec2(0, 1));
+
+ float packed_edges = imageLoad(source_edges, p_pos).r;
+ vec4 edgesLRTB = unpack_edges(packed_edges);
+
+ float sum_weight = 0.5;
+ vec4 sum = vC * sum_weight;
+
+ add_sample(vL, edgesLRTB.x, sum, sum_weight);
+ add_sample(vR, edgesLRTB.y, sum, sum_weight);
+ add_sample(vT, edgesLRTB.z, sum, sum_weight);
+ add_sample(vB, edgesLRTB.w, sum, sum_weight);
+
+ vec4 ssil_avg = sum / sum_weight;
+
+ vec4 ssil_value = ssil_avg;
+
+ return ssil_value;
+}
+#endif
+
+void main() {
+ // Pixel being shaded
+ ivec2 ssC = ivec2(gl_GlobalInvocationID.xy);
+
+#ifdef MODE_NON_SMART
+
+ vec2 half_pixel = params.half_screen_pixel_size * 0.5;
+
+ vec2 uv = (vec2(gl_GlobalInvocationID.xy) + vec2(0.5, 0.5)) * params.half_screen_pixel_size;
+
+ vec4 centre = textureLod(source_ssil, uv, 0.0);
+
+ vec4 value = textureLod(source_ssil, vec2(uv + vec2(-half_pixel.x * 3, -half_pixel.y)), 0.0) * 0.2;
+ value += textureLod(source_ssil, vec2(uv + vec2(+half_pixel.x, -half_pixel.y * 3)), 0.0) * 0.2;
+ value += textureLod(source_ssil, vec2(uv + vec2(-half_pixel.x, +half_pixel.y * 3)), 0.0) * 0.2;
+ value += textureLod(source_ssil, vec2(uv + vec2(+half_pixel.x * 3, +half_pixel.y)), 0.0) * 0.2;
+
+ vec4 sampled = value + centre * 0.2;
+
+#else
+#ifdef MODE_SMART
+ vec4 sampled = sample_blurred(ssC, (vec2(gl_GlobalInvocationID.xy) + vec2(0.5, 0.5)) * params.half_screen_pixel_size);
+#else // MODE_WIDE
+ vec4 sampled = sample_blurred_wide(ssC, (vec2(gl_GlobalInvocationID.xy) + vec2(0.5, 0.5)) * params.half_screen_pixel_size);
+#endif
+#endif // MODE_NON_SMART
+ imageStore(dest_image, ssC, sampled);
+}
diff --git a/servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl b/servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl
new file mode 100644
index 0000000000..815aa55fd4
--- /dev/null
+++ b/servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl
@@ -0,0 +1,124 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2016, Intel Corporation
+// 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.
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// File changes (yyyy-mm-dd)
+// 2016-09-07: filip.strugar@intel.com: first commit
+// 2020-12-05: clayjohn: convert to Vulkan and Godot
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#[compute]
+
+#version 450
+
+#VERSION_DEFINES
+
+layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
+
+#ifdef GENERATE_MAP
+layout(set = 0, binding = 0) uniform sampler2DArray source_texture;
+#else
+layout(set = 0, binding = 0) uniform sampler2D source_importance;
+#endif
+layout(r8, set = 1, binding = 0) uniform restrict writeonly image2D dest_image;
+
+#ifdef PROCESS_MAPB
+layout(set = 2, binding = 0, std430) buffer Counter {
+ uint sum;
+}
+counter;
+#endif
+
+layout(push_constant, binding = 1, std430) uniform Params {
+ vec2 half_screen_pixel_size;
+ float intensity;
+ float pad;
+}
+params;
+
+void main() {
+ // Pixel being shaded
+ ivec2 ssC = ivec2(gl_GlobalInvocationID.xy);
+
+#ifdef GENERATE_MAP
+ // importance map stuff
+ uvec2 base_position = ssC * 2;
+
+ float avg = 0.0;
+ float minV = 1.0;
+ float maxV = 0.0;
+ for (int i = 0; i < 4; i++) {
+ vec3 value_a = texelFetch(source_texture, ivec3(base_position, i), 0).rgb * params.intensity;
+ vec3 value_b = texelFetch(source_texture, ivec3(base_position, i) + ivec3(0, 1, 0), 0).rgb * params.intensity;
+ vec3 value_c = texelFetch(source_texture, ivec3(base_position, i) + ivec3(1, 0, 0), 0).rgb * params.intensity;
+ vec3 value_d = texelFetch(source_texture, ivec3(base_position, i) + ivec3(1, 1, 0), 0).rgb * params.intensity;
+
+ // Calculate luminance (black and white value)
+ float a = dot(value_a, vec3(0.2125, 0.7154, 0.0721));
+ float b = dot(value_b, vec3(0.2125, 0.7154, 0.0721));
+ float c = dot(value_c, vec3(0.2125, 0.7154, 0.0721));
+ float d = dot(value_d, vec3(0.2125, 0.7154, 0.0721));
+
+ maxV = max(maxV, max(max(a, b), max(c, d)));
+ minV = min(minV, min(min(a, b), min(c, d)));
+ }
+
+ float min_max_diff = maxV - minV;
+
+ imageStore(dest_image, ssC, vec4(pow(clamp(min_max_diff * 2.0, 0.0, 1.0), 0.6)));
+#endif
+
+#ifdef PROCESS_MAPA
+ vec2 uv = (vec2(ssC) + 0.5) * params.half_screen_pixel_size * 2.0;
+
+ float centre = textureLod(source_importance, uv, 0.0).x;
+
+ vec2 half_pixel = params.half_screen_pixel_size;
+
+ vec4 vals;
+ vals.x = textureLod(source_importance, uv + vec2(-half_pixel.x * 3, -half_pixel.y), 0.0).x;
+ vals.y = textureLod(source_importance, uv + vec2(+half_pixel.x, -half_pixel.y * 3), 0.0).x;
+ vals.z = textureLod(source_importance, uv + vec2(+half_pixel.x * 3, +half_pixel.y), 0.0).x;
+ vals.w = textureLod(source_importance, uv + vec2(-half_pixel.x, +half_pixel.y * 3), 0.0).x;
+
+ float avg = dot(vals, vec4(0.25, 0.25, 0.25, 0.25));
+
+ imageStore(dest_image, ssC, vec4(avg));
+#endif
+
+#ifdef PROCESS_MAPB
+ vec2 uv = (vec2(ssC) + 0.5f) * params.half_screen_pixel_size * 2.0;
+
+ float centre = textureLod(source_importance, uv, 0.0).x;
+
+ vec2 half_pixel = params.half_screen_pixel_size;
+
+ vec4 vals;
+ vals.x = textureLod(source_importance, uv + vec2(-half_pixel.x, -half_pixel.y * 3), 0.0).x;
+ vals.y = textureLod(source_importance, uv + vec2(+half_pixel.x * 3, -half_pixel.y), 0.0).x;
+ vals.z = textureLod(source_importance, uv + vec2(+half_pixel.x, +half_pixel.y * 3), 0.0).x;
+ vals.w = textureLod(source_importance, uv + vec2(-half_pixel.x * 3, +half_pixel.y), 0.0).x;
+
+ float avg = dot(vals, vec4(0.25, 0.25, 0.25, 0.25));
+
+ imageStore(dest_image, ssC, vec4(avg));
+
+ // sum the average; to avoid overflowing we assume max AO resolution is not bigger than 16384x16384; so quarter res (used here) will be 4096x4096, which leaves us with 8 bits per pixel
+ uint sum = uint(clamp(avg, 0.0, 1.0) * 255.0 + 0.5);
+
+ // save every 9th to avoid InterlockedAdd congestion - since we're blurring, this is good enough; compensated by multiplying load_counter_avg_div by 9
+ if (((ssC.x % 3) + (ssC.y % 3)) == 0) {
+ atomicAdd(counter.sum, sum);
+ }
+#endif
+}
diff --git a/servers/rendering/renderer_rd/shaders/ssil_interleave.glsl b/servers/rendering/renderer_rd/shaders/ssil_interleave.glsl
new file mode 100644
index 0000000000..8a7a5ae4fd
--- /dev/null
+++ b/servers/rendering/renderer_rd/shaders/ssil_interleave.glsl
@@ -0,0 +1,102 @@
+#[compute]
+
+#version 450
+
+#VERSION_DEFINES
+
+layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
+
+layout(rgba16, set = 0, binding = 0) uniform restrict writeonly image2D dest_image;
+layout(set = 1, binding = 0) uniform sampler2DArray source_texture;
+layout(r8, set = 2, binding = 0) uniform restrict readonly image2DArray source_edges;
+
+layout(push_constant, binding = 1, std430) uniform Params {
+ float inv_sharpness;
+ uint size_modifier;
+ vec2 pixel_size;
+}
+params;
+
+vec4 unpack_edges(float p_packed_val) {
+ uint packed_val = uint(p_packed_val * 255.5);
+ vec4 edgesLRTB;
+ edgesLRTB.x = float((packed_val >> 6) & 0x03) / 3.0;
+ edgesLRTB.y = float((packed_val >> 4) & 0x03) / 3.0;
+ edgesLRTB.z = float((packed_val >> 2) & 0x03) / 3.0;
+ edgesLRTB.w = float((packed_val >> 0) & 0x03) / 3.0;
+
+ return clamp(edgesLRTB + params.inv_sharpness, 0.0, 1.0);
+}
+
+void main() {
+ ivec2 ssC = ivec2(gl_GlobalInvocationID.xy);
+ if (any(greaterThanEqual(ssC, ivec2(1.0 / params.pixel_size)))) { //too large, do nothing
+ return;
+ }
+
+#ifdef MODE_SMART
+ uvec2 pix_pos = uvec2(gl_GlobalInvocationID.xy);
+ vec2 uv = (gl_GlobalInvocationID.xy + vec2(0.5)) * params.pixel_size;
+
+ // calculate index in the four deinterleaved source array texture
+ int mx = int(pix_pos.x % 2);
+ int my = int(pix_pos.y % 2);
+ int index_center = mx + my * 2; // center index
+ int index_horizontal = (1 - mx) + my * 2; // neighbouring, horizontal
+ int index_vertical = mx + (1 - my) * 2; // neighbouring, vertical
+ int index_diagonal = (1 - mx) + (1 - my) * 2; // diagonal
+
+ vec4 color = texelFetch(source_texture, ivec3(pix_pos / uvec2(params.size_modifier), index_center), 0);
+
+ vec4 edgesLRTB = unpack_edges(imageLoad(source_edges, ivec3(pix_pos / uvec2(params.size_modifier), index_center)).r);
+
+ // convert index shifts to sampling offsets
+ float fmx = float(mx);
+ float fmy = float(my);
+
+ // in case of an edge, push sampling offsets away from the edge (towards pixel center)
+ float fmxe = (edgesLRTB.y - edgesLRTB.x);
+ float fmye = (edgesLRTB.w - edgesLRTB.z);
+
+ // calculate final sampling offsets and sample using bilinear filter
+ vec2 uv_horizontal = (gl_GlobalInvocationID.xy + vec2(0.5) + vec2(fmx + fmxe - 0.5, 0.5 - fmy)) * params.pixel_size;
+ vec4 color_horizontal = textureLod(source_texture, vec3(uv_horizontal, index_horizontal), 0.0);
+ vec2 uv_vertical = (gl_GlobalInvocationID.xy + vec2(0.5) + vec2(0.5 - fmx, fmy - 0.5 + fmye)) * params.pixel_size;
+ vec4 color_vertical = textureLod(source_texture, vec3(uv_vertical, index_vertical), 0.0);
+ vec2 uv_diagonal = (gl_GlobalInvocationID.xy + vec2(0.5) + vec2(fmx - 0.5 + fmxe, fmy - 0.5 + fmye)) * params.pixel_size;
+ vec4 color_diagonal = textureLod(source_texture, vec3(uv_diagonal, index_diagonal), 0.0);
+
+ // reduce weight for samples near edge - if the edge is on both sides, weight goes to 0
+ vec4 blendWeights;
+ blendWeights.x = 1.0;
+ blendWeights.y = (edgesLRTB.x + edgesLRTB.y) * 0.5;
+ blendWeights.z = (edgesLRTB.z + edgesLRTB.w) * 0.5;
+ blendWeights.w = (blendWeights.y + blendWeights.z) * 0.5;
+
+ // calculate weighted average
+ float blendWeightsSum = dot(blendWeights, vec4(1.0, 1.0, 1.0, 1.0));
+ color += color_horizontal * blendWeights.y;
+ color += color_vertical * blendWeights.z;
+ color += color_diagonal * blendWeights.w;
+ color /= blendWeightsSum;
+
+ imageStore(dest_image, ivec2(gl_GlobalInvocationID.xy), color);
+#else // !MODE_SMART
+
+ vec2 uv = (gl_GlobalInvocationID.xy + vec2(0.5)) * params.pixel_size;
+#ifdef MODE_HALF
+ vec4 a = textureLod(source_texture, vec3(uv, 0), 0.0);
+ vec4 d = textureLod(source_texture, vec3(uv, 3), 0.0);
+ vec4 avg = (a + d) * 0.5;
+
+#else
+ vec4 a = textureLod(source_texture, vec3(uv, 0), 0.0);
+ vec4 b = textureLod(source_texture, vec3(uv, 1), 0.0);
+ vec4 c = textureLod(source_texture, vec3(uv, 2), 0.0);
+ vec4 d = textureLod(source_texture, vec3(uv, 3), 0.0);
+ vec4 avg = (a + b + c + d) * 0.25;
+
+#endif
+ imageStore(dest_image, ivec2(gl_GlobalInvocationID.xy), avg);
+#endif
+}
diff --git a/servers/rendering/renderer_rd/shaders/tonemap.glsl b/servers/rendering/renderer_rd/shaders/tonemap.glsl
index 1ce3e04421..948c6e1e39 100644
--- a/servers/rendering/renderer_rd/shaders/tonemap.glsl
+++ b/servers/rendering/renderer_rd/shaders/tonemap.glsl
@@ -140,7 +140,7 @@ vec4 texture2D_bicubic(sampler2D tex, vec2 uv, int p_lod) {
vec2 p3 = (vec2(iuv.x + h1x, iuv.y + h1y) - vec2(0.5f)) * pixel_size;
return (g0(fuv.y) * (g0x * textureLod(tex, p0, lod) + g1x * textureLod(tex, p1, lod))) +
- (g1(fuv.y) * (g0x * textureLod(tex, p2, lod) + g1x * textureLod(tex, p3, lod)));
+ (g1(fuv.y) * (g0x * textureLod(tex, p2, lod) + g1x * textureLod(tex, p3, lod)));
}
#define GLOW_TEXTURE_SAMPLE(m_tex, m_uv, m_lod) texture2D_bicubic(m_tex, m_uv, m_lod)
@@ -341,14 +341,14 @@ vec3 do_fxaa(vec3 color, float exposure, vec2 uv_interp) {
dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));
float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) *
- (0.25 * FXAA_REDUCE_MUL),
+ (0.25 * FXAA_REDUCE_MUL),
FXAA_REDUCE_MIN);
float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce);
dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX),
max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),
dir * rcpDirMin)) *
- params.pixel_size;
+ params.pixel_size;
#ifdef MULTIVIEW
vec3 rgbA = 0.5 * exposure * (textureLod(source_color, vec3(uv_interp + dir * (1.0 / 3.0 - 0.5), ViewIndex), 0.0).xyz + textureLod(source_color, vec3(uv_interp + dir * (2.0 / 3.0 - 0.5), ViewIndex), 0.0).xyz) * params.luminance_multiplier;
diff --git a/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl b/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl
index f2010222e5..181d3b272f 100644
--- a/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl
+++ b/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl
@@ -4,219 +4,103 @@
#VERSION_DEFINES
-/* Do not use subgroups here, seems there is not much advantage and causes glitches
-#if defined(has_GL_KHR_shader_subgroup_ballot) && defined(has_GL_KHR_shader_subgroup_arithmetic)
-#extension GL_KHR_shader_subgroup_ballot: enable
-#extension GL_KHR_shader_subgroup_arithmetic: enable
-
-#define USE_SUBGROUPS
-#endif
-*/
-
-#if defined(MODE_FOG) || defined(MODE_FILTER)
-
-layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
-
-#endif
-
-#if defined(MODE_DENSITY)
-
layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in;
-#endif
+#define SAMPLER_NEAREST_CLAMP 0
+#define SAMPLER_LINEAR_CLAMP 1
+#define SAMPLER_NEAREST_WITH_MIPMAPS_CLAMP 2
+#define SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP 3
+#define SAMPLER_NEAREST_WITH_MIPMAPS_ANISOTROPIC_CLAMP 4
+#define SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_CLAMP 5
+#define SAMPLER_NEAREST_REPEAT 6
+#define SAMPLER_LINEAR_REPEAT 7
+#define SAMPLER_NEAREST_WITH_MIPMAPS_REPEAT 8
+#define SAMPLER_LINEAR_WITH_MIPMAPS_REPEAT 9
+#define SAMPLER_NEAREST_WITH_MIPMAPS_ANISOTROPIC_REPEAT 10
+#define SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_REPEAT 11
+
+#define DENSITY_SCALE 1024.0
#include "cluster_data_inc.glsl"
#include "light_data_inc.glsl"
#define M_PI 3.14159265359
-layout(set = 0, binding = 1) uniform texture2D shadow_atlas;
-layout(set = 0, binding = 2) uniform texture2D directional_shadow_atlas;
-
-layout(set = 0, binding = 3, std430) restrict readonly buffer OmniLights {
- LightData data[];
-}
-omni_lights;
-
-layout(set = 0, binding = 4, std430) restrict readonly buffer SpotLights {
- LightData data[];
-}
-spot_lights;
+layout(set = 0, binding = 1) uniform sampler material_samplers[12];
-layout(set = 0, binding = 5, std140) uniform DirectionalLights {
- DirectionalLightData data[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS];
+layout(set = 0, binding = 2, std430) restrict readonly buffer GlobalVariableData {
+ vec4 data[];
}
-directional_lights;
-
-layout(set = 0, binding = 6, std430) buffer restrict readonly ClusterBuffer {
- uint data[];
-}
-cluster_buffer;
-
-layout(set = 0, binding = 7) uniform sampler linear_sampler;
-
-#ifdef MODE_DENSITY
-layout(rgba16f, set = 0, binding = 8) uniform restrict writeonly image3D density_map;
-layout(rgba16f, set = 0, binding = 9) uniform restrict readonly image3D fog_map; //unused
-#endif
-
-#ifdef MODE_FOG
-layout(rgba16f, set = 0, binding = 8) uniform restrict readonly image3D density_map;
-layout(rgba16f, set = 0, binding = 9) uniform restrict writeonly image3D fog_map;
-#endif
-
-#ifdef MODE_FILTER
-layout(rgba16f, set = 0, binding = 8) uniform restrict readonly image3D source_map;
-layout(rgba16f, set = 0, binding = 9) uniform restrict writeonly image3D dest_map;
-#endif
-
-layout(set = 0, binding = 10) uniform sampler shadow_sampler;
-
-#define MAX_VOXEL_GI_INSTANCES 8
-
-struct VoxelGIData {
- mat4 xform;
- vec3 bounds;
- float dynamic_range;
+global_variables;
- float bias;
- float normal_bias;
- bool blend_ambient;
- uint texture_slot;
-
- float anisotropy_strength;
- float ambient_occlusion;
- float ambient_occlusion_size;
- uint mipmaps;
-};
-
-layout(set = 0, binding = 11, std140) uniform VoxelGIs {
- VoxelGIData data[MAX_VOXEL_GI_INSTANCES];
-}
-voxel_gi_instances;
-
-layout(set = 0, binding = 12) uniform texture3D voxel_gi_textures[MAX_VOXEL_GI_INSTANCES];
-
-layout(set = 0, binding = 13) uniform sampler linear_sampler_with_mipmaps;
-
-#ifdef ENABLE_SDFGI
-
-// SDFGI Integration on set 1
-#define SDFGI_MAX_CASCADES 8
-
-struct SDFVoxelGICascadeData {
+layout(push_constant, binding = 0, std430) uniform Params {
vec3 position;
- float to_probe;
- ivec3 probe_world_offset;
- float to_cell; // 1/bounds * grid_size
-};
-
-layout(set = 1, binding = 0, std140) uniform SDFGI {
- vec3 grid_size;
- uint max_cascades;
-
- bool use_occlusion;
- int probe_axis_size;
- float probe_to_uvw;
- float normal_bias;
+ float pad;
- vec3 lightprobe_tex_pixel_size;
- float energy;
+ vec3 extents;
+ float pad2;
- vec3 lightprobe_uv_offset;
- float y_mult;
+ ivec3 corner;
+ uint shape;
- vec3 occlusion_clamp;
- uint pad3;
-
- vec3 occlusion_renormalize;
- uint pad4;
-
- vec3 cascade_probe_size;
- uint pad5;
-
- SDFVoxelGICascadeData cascades[SDFGI_MAX_CASCADES];
+ mat4 transform;
}
-sdfgi;
-
-layout(set = 1, binding = 1) uniform texture2DArray sdfgi_ambient_texture;
-
-layout(set = 1, binding = 2) uniform texture3D sdfgi_occlusion_texture;
+params;
-#endif //SDFGI
+#ifdef MOLTENVK_USED
+layout(set = 1, binding = 1) volatile buffer emissive_only_map_buffer {
+ uint emissive_only_map[];
+};
+#else
+layout(r32ui, set = 1, binding = 1) uniform volatile uimage3D emissive_only_map;
+#endif
-layout(set = 0, binding = 14, std140) uniform Params {
+layout(set = 1, binding = 2, std140) uniform SceneParams {
vec2 fog_frustum_size_begin;
vec2 fog_frustum_size_end;
float fog_frustum_end;
- float z_near;
- float z_far;
- int filter_axis;
+ float z_near; //
+ float z_far; //
+ float time;
ivec3 fog_volume_size;
- uint directional_light_count;
-
- vec3 light_color;
- float base_density;
-
- float detail_spread;
- float gi_inject;
- uint max_voxel_gi_instances;
- uint cluster_type_size;
+ uint directional_light_count; //
- vec2 screen_size;
- uint cluster_shift;
- uint cluster_width;
-
- uint max_cluster_element_count_div_32;
bool use_temporal_reprojection;
uint temporal_frame;
+ float detail_spread;
float temporal_blend;
- mat3x4 cam_rotation;
mat4 to_prev_view;
+ mat4 transform;
}
-params;
-
-layout(set = 0, binding = 15) uniform texture3D prev_density_texture;
+scene_params;
-float get_depth_at_pos(float cell_depth_size, int z) {
- float d = float(z) * cell_depth_size + cell_depth_size * 0.5; //center of voxels
- d = pow(d, params.detail_spread);
- return params.fog_frustum_end * d;
-}
-
-vec3 hash3f(uvec3 x) {
- x = ((x >> 16) ^ x) * 0x45d9f3b;
- x = ((x >> 16) ^ x) * 0x45d9f3b;
- x = (x >> 16) ^ x;
- return vec3(x & 0xFFFFF) / vec3(float(0xFFFFF));
-}
-
-float get_omni_attenuation(float distance, float inv_range, float decay) {
- float nd = distance * inv_range;
- nd *= nd;
- nd *= nd; // nd^4
- nd = max(1.0 - nd, 0.0);
- nd *= nd; // nd^2
- return nd * pow(max(distance, 0.0001), -decay);
-}
+#ifdef MOLTENVK_USED
+layout(set = 1, binding = 3) volatile buffer density_only_map_buffer {
+ uint density_only_map[];
+};
+layout(set = 1, binding = 4) volatile buffer light_only_map_buffer {
+ uint light_only_map[];
+};
+#else
+layout(r32ui, set = 1, binding = 3) uniform volatile uimage3D density_only_map;
+layout(r32ui, set = 1, binding = 4) uniform volatile uimage3D light_only_map;
+#endif
-void cluster_get_item_range(uint p_offset, out uint item_min, out uint item_max, out uint item_from, out uint item_to) {
- uint item_min_max = cluster_buffer.data[p_offset];
- item_min = item_min_max & 0xFFFF;
- item_max = item_min_max >> 16;
- ;
+#ifdef MATERIAL_UNIFORMS_USED
+layout(set = 2, binding = 0, std140) uniform MaterialUniforms{
+#MATERIAL_UNIFORMS
+} material;
+#endif
- item_from = item_min >> 5;
- item_to = (item_max == 0) ? 0 : ((item_max - 1) >> 5) + 1; //side effect of how it is stored, as item_max 0 means no elements
-}
+#GLOBALS
-uint cluster_get_range_clip_mask(uint i, uint z_min, uint z_max) {
- int local_min = clamp(int(z_min) - int(i) * 32, 0, 31);
- int mask_width = min(int(z_max) - int(z_min), 32 - local_min);
- return bitfieldInsert(uint(0), uint(0xFFFFFFFF), local_min, mask_width);
+float get_depth_at_pos(float cell_depth_size, int z) {
+ float d = float(z) * cell_depth_size + cell_depth_size * 0.5; //center of voxels
+ d = pow(d, scene_params.detail_spread);
+ return scene_params.fog_frustum_end * d;
}
#define TEMPORAL_FRAMES 16
@@ -240,464 +124,167 @@ const vec3 halton_map[TEMPORAL_FRAMES] = vec3[](
vec3(0.03125, 0.59259259, 0.32));
void main() {
- vec3 fog_cell_size = 1.0 / vec3(params.fog_volume_size);
+ vec3 fog_cell_size = 1.0 / vec3(scene_params.fog_volume_size);
-#ifdef MODE_DENSITY
-
- ivec3 pos = ivec3(gl_GlobalInvocationID.xyz);
- if (any(greaterThanEqual(pos, params.fog_volume_size))) {
+ ivec3 pos = ivec3(gl_GlobalInvocationID.xyz) + params.corner;
+ if (any(greaterThanEqual(pos, scene_params.fog_volume_size))) {
return; //do not compute
}
+#ifdef MOLTENVK_USED
+ uint lpos = pos.z * scene_params.fog_volume_size.x * scene_params.fog_volume_size.y + pos.y * scene_params.fog_volume_size.x + pos.x;
+#endif
vec3 posf = vec3(pos);
- //posf += mix(vec3(0.0),vec3(1.0),0.3) * hash3f(uvec3(pos)) * 2.0 - 1.0;
-
vec3 fog_unit_pos = posf * fog_cell_size + fog_cell_size * 0.5; //center of voxels
-
- uvec2 screen_pos = uvec2(fog_unit_pos.xy * params.screen_size);
- uvec2 cluster_pos = screen_pos >> params.cluster_shift;
- uint cluster_offset = (params.cluster_width * cluster_pos.y + cluster_pos.x) * (params.max_cluster_element_count_div_32 + 32);
- //positions in screen are too spread apart, no hopes for optimizing with subgroups
-
- fog_unit_pos.z = pow(fog_unit_pos.z, params.detail_spread);
+ fog_unit_pos.z = pow(fog_unit_pos.z, scene_params.detail_spread);
vec3 view_pos;
- view_pos.xy = (fog_unit_pos.xy * 2.0 - 1.0) * mix(params.fog_frustum_size_begin, params.fog_frustum_size_end, vec2(fog_unit_pos.z));
- view_pos.z = -params.fog_frustum_end * fog_unit_pos.z;
+ view_pos.xy = (fog_unit_pos.xy * 2.0 - 1.0) * mix(scene_params.fog_frustum_size_begin, scene_params.fog_frustum_size_end, vec2(fog_unit_pos.z));
+ view_pos.z = -scene_params.fog_frustum_end * fog_unit_pos.z;
view_pos.y = -view_pos.y;
- vec4 reprojected_density = vec4(0.0);
- float reproject_amount = 0.0;
-
- if (params.use_temporal_reprojection) {
- vec3 prev_view = (params.to_prev_view * vec4(view_pos, 1.0)).xyz;
+ if (scene_params.use_temporal_reprojection) {
+ vec3 prev_view = (scene_params.to_prev_view * vec4(view_pos, 1.0)).xyz;
//undo transform into prev view
prev_view.y = -prev_view.y;
//z back to unit size
- prev_view.z /= -params.fog_frustum_end;
+ prev_view.z /= -scene_params.fog_frustum_end;
//xy back to unit size
- prev_view.xy /= mix(params.fog_frustum_size_begin, params.fog_frustum_size_end, vec2(prev_view.z));
+ prev_view.xy /= mix(scene_params.fog_frustum_size_begin, scene_params.fog_frustum_size_end, vec2(prev_view.z));
prev_view.xy = prev_view.xy * 0.5 + 0.5;
//z back to unspread value
- prev_view.z = pow(prev_view.z, 1.0 / params.detail_spread);
+ prev_view.z = pow(prev_view.z, 1.0 / scene_params.detail_spread);
if (all(greaterThan(prev_view, vec3(0.0))) && all(lessThan(prev_view, vec3(1.0)))) {
//reprojectinon fits
-
- reprojected_density = textureLod(sampler3D(prev_density_texture, linear_sampler), prev_view, 0.0);
- reproject_amount = params.temporal_blend;
-
// Since we can reproject, now we must jitter the current view pos.
// This is done here because cells that can't reproject should not jitter.
- fog_unit_pos = posf * fog_cell_size + fog_cell_size * halton_map[params.temporal_frame]; //center of voxels, offset by halton table
-
- screen_pos = uvec2(fog_unit_pos.xy * params.screen_size);
- cluster_pos = screen_pos >> params.cluster_shift;
- cluster_offset = (params.cluster_width * cluster_pos.y + cluster_pos.x) * (params.max_cluster_element_count_div_32 + 32);
- //positions in screen are too spread apart, no hopes for optimizing with subgroups
+ fog_unit_pos = posf * fog_cell_size + fog_cell_size * halton_map[scene_params.temporal_frame]; //center of voxels, offset by halton table
+ fog_unit_pos.z = pow(fog_unit_pos.z, scene_params.detail_spread);
- fog_unit_pos.z = pow(fog_unit_pos.z, params.detail_spread);
-
- view_pos.xy = (fog_unit_pos.xy * 2.0 - 1.0) * mix(params.fog_frustum_size_begin, params.fog_frustum_size_end, vec2(fog_unit_pos.z));
- view_pos.z = -params.fog_frustum_end * fog_unit_pos.z;
+ view_pos.xy = (fog_unit_pos.xy * 2.0 - 1.0) * mix(scene_params.fog_frustum_size_begin, scene_params.fog_frustum_size_end, vec2(fog_unit_pos.z));
+ view_pos.z = -scene_params.fog_frustum_end * fog_unit_pos.z;
view_pos.y = -view_pos.y;
}
}
- uint cluster_z = uint(clamp((abs(view_pos.z) / params.z_far) * 32.0, 0.0, 31.0));
-
- vec3 total_light = params.light_color;
+ float density = 0.0;
+ vec3 emission = vec3(0.0);
+ vec3 albedo = vec3(0.0);
- float total_density = params.base_density;
float cell_depth_size = abs(view_pos.z - get_depth_at_pos(fog_cell_size.z, pos.z + 1));
- //compute directional lights
-
- for (uint i = 0; i < params.directional_light_count; i++) {
- vec3 shadow_attenuation = vec3(1.0);
-
- if (directional_lights.data[i].shadow_enabled) {
- float depth_z = -view_pos.z;
-
- vec4 pssm_coord;
- vec3 shadow_color = directional_lights.data[i].shadow_color1.rgb;
- vec3 light_dir = directional_lights.data[i].direction;
- vec4 v = vec4(view_pos, 1.0);
- float z_range;
-
- if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
- pssm_coord = (directional_lights.data[i].shadow_matrix1 * v);
- pssm_coord /= pssm_coord.w;
- z_range = directional_lights.data[i].shadow_z_range.x;
-
- } else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
- pssm_coord = (directional_lights.data[i].shadow_matrix2 * v);
- pssm_coord /= pssm_coord.w;
- z_range = directional_lights.data[i].shadow_z_range.y;
-
- } else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
- pssm_coord = (directional_lights.data[i].shadow_matrix3 * v);
- pssm_coord /= pssm_coord.w;
- z_range = directional_lights.data[i].shadow_z_range.z;
-
- } else {
- pssm_coord = (directional_lights.data[i].shadow_matrix4 * v);
- pssm_coord /= pssm_coord.w;
- z_range = directional_lights.data[i].shadow_z_range.w;
- }
-
- float depth = texture(sampler2D(directional_shadow_atlas, linear_sampler), pssm_coord.xy).r;
- float shadow = exp(min(0.0, (depth - pssm_coord.z)) * z_range * directional_lights.data[i].shadow_volumetric_fog_fade);
-
- /*
- //float shadow = textureProj(sampler2DShadow(directional_shadow_atlas,shadow_sampler),pssm_coord);
- float shadow = 0.0;
- for(float xi=-1;xi<=1;xi++) {
- for(float yi=-1;yi<=1;yi++) {
- vec2 ofs = vec2(xi,yi) * 1.5 * params.directional_shadow_pixel_size;
- shadow += textureProj(sampler2DShadow(directional_shadow_atlas,shadow_sampler),pssm_coord + vec4(ofs,0.0,0.0));
- }
-
- }
-
- shadow /= 3.0 * 3.0;
-*/
- shadow = mix(shadow, 1.0, smoothstep(directional_lights.data[i].fade_from, directional_lights.data[i].fade_to, view_pos.z)); //done with negative values for performance
-
- shadow_attenuation = mix(shadow_color, vec3(1.0), shadow);
- }
-
- total_light += shadow_attenuation * directional_lights.data[i].color * directional_lights.data[i].energy / M_PI;
+ vec4 world = scene_params.transform * vec4(view_pos, 1.0);
+ world.xyz /= world.w;
+
+ vec3 uvw = fog_unit_pos;
+
+ vec4 local_pos = params.transform * world;
+ local_pos.xyz /= local_pos.w;
+
+ float sdf = -1.0;
+ if (params.shape == 0) {
+ //Ellipsoid
+ // https://www.shadertoy.com/view/tdS3DG
+ float k0 = length(local_pos.xyz / params.extents);
+ float k1 = length(local_pos.xyz / (params.extents * params.extents));
+ sdf = k0 * (k0 - 1.0) / k1;
+ } else if (params.shape == 1) {
+ // Box
+ // https://iquilezles.org/www/articles/distfunctions/distfunctions.htm
+ vec3 q = abs(local_pos.xyz) - params.extents;
+ sdf = length(max(q, 0.0)) + min(max(q.x, max(q.y, q.z)), 0.0);
}
- //compute lights from cluster
-
- { //omni lights
-
- uint cluster_omni_offset = cluster_offset;
-
- uint item_min;
- uint item_max;
- uint item_from;
- uint item_to;
-
- cluster_get_item_range(cluster_omni_offset + params.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to);
-
-#ifdef USE_SUBGROUPS
- item_from = subgroupBroadcastFirst(subgroupMin(item_from));
- item_to = subgroupBroadcastFirst(subgroupMax(item_to));
+ float cull_mask = 1.0; //used to cull cells that do not contribute
+ if (params.shape <= 1) {
+#ifndef SDF_USED
+ cull_mask = 1.0 - smoothstep(-0.1, 0.0, sdf);
#endif
+ uvw = clamp((local_pos.xyz + params.extents) / (2.0 * params.extents), 0.0, 1.0);
+ }
- for (uint i = item_from; i < item_to; i++) {
- uint mask = cluster_buffer.data[cluster_omni_offset + i];
- mask &= cluster_get_range_clip_mask(i, item_min, item_max);
-#ifdef USE_SUBGROUPS
- uint merged_mask = subgroupBroadcastFirst(subgroupOr(mask));
+ if (cull_mask > 0.0) {
+ {
+#CODE : FOG
+ }
+
+#ifdef DENSITY_USED
+ density *= cull_mask;
+ if (abs(density) > 0.001) {
+ int final_density = int(density * DENSITY_SCALE);
+#ifdef MOLTENVK_USED
+ atomicAdd(density_only_map[lpos], uint(final_density));
#else
- uint merged_mask = mask;
+ imageAtomicAdd(density_only_map, pos, uint(final_density));
#endif
- while (merged_mask != 0) {
- uint bit = findMSB(merged_mask);
- merged_mask &= ~(1 << bit);
-#ifdef USE_SUBGROUPS
- if (((1 << bit) & mask) == 0) { //do not process if not originally here
- continue;
- }
+#ifdef EMISSION_USED
+ {
+ emission *= clamp(density, 0.0, 1.0);
+ emission = clamp(emission, vec3(0.0), vec3(4.0));
+ // Scale to fit into R11G11B10 with a range of 0-4
+ uvec3 emission_u = uvec3(emission.r * 511.0, emission.g * 511.0, emission.b * 255.0);
+ // R and G have 11 bits each and B has 10. Then pack them into a 32 bit uint
+ uint final_emission = emission_u.r << 21 | emission_u.g << 10 | emission_u.b;
+#ifdef MOLTENVK_USED
+ uint prev_emission = atomicAdd(emissive_only_map[lpos], final_emission);
+#else
+ uint prev_emission = imageAtomicAdd(emissive_only_map, pos, final_emission);
#endif
- uint light_index = 32 * i + bit;
-
- //if (!bool(omni_omni_lights.data[light_index].mask & draw_call.layer_mask)) {
- // continue; //not masked
- //}
-
- vec3 light_pos = omni_lights.data[light_index].position;
- float d = distance(omni_lights.data[light_index].position, view_pos);
- float shadow_attenuation = 1.0;
-
- if (d * omni_lights.data[light_index].inv_radius < 1.0) {
- float attenuation = get_omni_attenuation(d, omni_lights.data[light_index].inv_radius, omni_lights.data[light_index].attenuation);
-
- vec3 light = omni_lights.data[light_index].color / M_PI;
-
- if (omni_lights.data[light_index].shadow_enabled) {
- //has shadow
- vec4 v = vec4(view_pos, 1.0);
-
- vec4 splane = (omni_lights.data[light_index].shadow_matrix * v);
- float shadow_len = length(splane.xyz); //need to remember shadow len from here
- splane.xyz = normalize(splane.xyz);
- vec4 clamp_rect = omni_lights.data[light_index].atlas_rect;
+ // Adding can lead to colors overflowing, so validate
+ uvec3 prev_emission_u = uvec3(prev_emission >> 21, (prev_emission << 11) >> 21, prev_emission % 1024);
+ uint add_emission = final_emission + prev_emission;
+ uvec3 add_emission_u = uvec3(add_emission >> 21, (add_emission << 11) >> 21, add_emission % 1024);
- if (splane.z >= 0.0) {
- splane.z += 1.0;
+ bvec3 overflowing = lessThan(add_emission_u, prev_emission_u + emission_u);
- clamp_rect.y += clamp_rect.w;
-
- } else {
- splane.z = 1.0 - splane.z;
- }
-
- splane.xy /= splane.z;
-
- splane.xy = splane.xy * 0.5 + 0.5;
- splane.z = shadow_len * omni_lights.data[light_index].inv_radius;
- splane.xy = clamp_rect.xy + splane.xy * clamp_rect.zw;
- splane.w = 1.0; //needed? i think it should be 1 already
-
- float depth = texture(sampler2D(shadow_atlas, linear_sampler), splane.xy).r;
-
- shadow_attenuation = exp(min(0.0, (depth - splane.z)) / omni_lights.data[light_index].inv_radius * omni_lights.data[light_index].shadow_volumetric_fog_fade);
- }
- total_light += light * attenuation * shadow_attenuation;
+ if (any(overflowing)) {
+ uvec3 overflow_factor = mix(uvec3(0), uvec3(2047 << 21, 2047 << 10, 1023), overflowing);
+ uint force_max = overflow_factor.r | overflow_factor.g | overflow_factor.b;
+#ifdef MOLTENVK_USED
+ atomicOr(emissive_only_map[lpos], force_max);
+#else
+ imageAtomicOr(emissive_only_map, pos, force_max);
+#endif
}
}
- }
- }
-
- { //spot lights
-
- uint cluster_spot_offset = cluster_offset + params.cluster_type_size;
-
- uint item_min;
- uint item_max;
- uint item_from;
- uint item_to;
-
- cluster_get_item_range(cluster_spot_offset + params.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to);
-
-#ifdef USE_SUBGROUPS
- item_from = subgroupBroadcastFirst(subgroupMin(item_from));
- item_to = subgroupBroadcastFirst(subgroupMax(item_to));
#endif
-
- for (uint i = item_from; i < item_to; i++) {
- uint mask = cluster_buffer.data[cluster_spot_offset + i];
- mask &= cluster_get_range_clip_mask(i, item_min, item_max);
-#ifdef USE_SUBGROUPS
- uint merged_mask = subgroupBroadcastFirst(subgroupOr(mask));
+#ifdef ALBEDO_USED
+ {
+ vec3 scattering = albedo * clamp(density, 0.0, 1.0);
+ scattering = clamp(scattering, vec3(0.0), vec3(1.0));
+ uvec3 scattering_u = uvec3(scattering.r * 2047.0, scattering.g * 2047.0, scattering.b * 1023.0);
+ // R and G have 11 bits each and B has 10. Then pack them into a 32 bit uint
+ uint final_scattering = scattering_u.r << 21 | scattering_u.g << 10 | scattering_u.b;
+#ifdef MOLTENVK_USED
+ uint prev_scattering = atomicAdd(light_only_map[lpos], final_scattering);
#else
- uint merged_mask = mask;
-#endif
-
- while (merged_mask != 0) {
- uint bit = findMSB(merged_mask);
- merged_mask &= ~(1 << bit);
-#ifdef USE_SUBGROUPS
- if (((1 << bit) & mask) == 0) { //do not process if not originally here
- continue;
- }
+ uint prev_scattering = imageAtomicAdd(light_only_map, pos, final_scattering);
#endif
- //if (!bool(omni_lights.data[light_index].mask & draw_call.layer_mask)) {
- // continue; //not masked
- //}
-
- uint light_index = 32 * i + bit;
-
- vec3 light_pos = spot_lights.data[light_index].position;
- vec3 light_rel_vec = spot_lights.data[light_index].position - view_pos;
- float d = length(light_rel_vec);
- float shadow_attenuation = 1.0;
-
- if (d * spot_lights.data[light_index].inv_radius < 1.0) {
- float attenuation = get_omni_attenuation(d, spot_lights.data[light_index].inv_radius, spot_lights.data[light_index].attenuation);
-
- vec3 spot_dir = spot_lights.data[light_index].direction;
- float scos = max(dot(-normalize(light_rel_vec), spot_dir), spot_lights.data[light_index].cone_angle);
- float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_lights.data[light_index].cone_angle));
- attenuation *= 1.0 - pow(spot_rim, spot_lights.data[light_index].cone_attenuation);
-
- vec3 light = spot_lights.data[light_index].color / M_PI;
-
- if (spot_lights.data[light_index].shadow_enabled) {
- //has shadow
- vec4 v = vec4(view_pos, 1.0);
-
- vec4 splane = (spot_lights.data[light_index].shadow_matrix * v);
- splane /= splane.w;
-
- float depth = texture(sampler2D(shadow_atlas, linear_sampler), splane.xy).r;
-
- shadow_attenuation = exp(min(0.0, (depth - splane.z)) / spot_lights.data[light_index].inv_radius * spot_lights.data[light_index].shadow_volumetric_fog_fade);
- }
-
- total_light += light * attenuation * shadow_attenuation;
- }
- }
- }
- }
-
- vec3 world_pos = mat3(params.cam_rotation) * view_pos;
-
- for (uint i = 0; i < params.max_voxel_gi_instances; i++) {
- vec3 position = (voxel_gi_instances.data[i].xform * vec4(world_pos, 1.0)).xyz;
-
- //this causes corrupted pixels, i have no idea why..
- if (all(bvec2(all(greaterThanEqual(position, vec3(0.0))), all(lessThan(position, voxel_gi_instances.data[i].bounds))))) {
- position /= voxel_gi_instances.data[i].bounds;
-
- vec4 light = vec4(0.0);
- for (uint j = 0; j < voxel_gi_instances.data[i].mipmaps; j++) {
- vec4 slight = textureLod(sampler3D(voxel_gi_textures[i], linear_sampler_with_mipmaps), position, float(j));
- float a = (1.0 - light.a);
- light += a * slight;
- }
-
- light.rgb *= voxel_gi_instances.data[i].dynamic_range * params.gi_inject;
-
- total_light += light.rgb;
- }
- }
-
- //sdfgi
-#ifdef ENABLE_SDFGI
+ // Adding can lead to colors overflowing, so validate
+ uvec3 prev_scattering_u = uvec3(prev_scattering >> 21, (prev_scattering << 11) >> 21, prev_scattering % 1024);
+ uint add_scattering = final_scattering + prev_scattering;
+ uvec3 add_scattering_u = uvec3(add_scattering >> 21, (add_scattering << 11) >> 21, add_scattering % 1024);
- {
- float blend = -1.0;
- vec3 ambient_total = vec3(0.0);
+ bvec3 overflowing = lessThan(add_scattering_u, prev_scattering_u + scattering_u);
- for (uint i = 0; i < sdfgi.max_cascades; i++) {
- vec3 cascade_pos = (world_pos - sdfgi.cascades[i].position) * sdfgi.cascades[i].to_probe;
-
- if (any(lessThan(cascade_pos, vec3(0.0))) || any(greaterThanEqual(cascade_pos, sdfgi.cascade_probe_size))) {
- continue; //skip cascade
- }
-
- vec3 base_pos = floor(cascade_pos);
- ivec3 probe_base_pos = ivec3(base_pos);
-
- vec4 ambient_accum = vec4(0.0);
-
- ivec3 tex_pos = ivec3(probe_base_pos.xy, int(i));
- tex_pos.x += probe_base_pos.z * sdfgi.probe_axis_size;
-
- for (uint j = 0; j < 8; j++) {
- ivec3 offset = (ivec3(j) >> ivec3(0, 1, 2)) & ivec3(1, 1, 1);
- ivec3 probe_posi = probe_base_pos;
- probe_posi += offset;
-
- // Compute weight
-
- vec3 probe_pos = vec3(probe_posi);
- vec3 probe_to_pos = cascade_pos - probe_pos;
-
- vec3 trilinear = vec3(1.0) - abs(probe_to_pos);
- float weight = trilinear.x * trilinear.y * trilinear.z;
-
- // Compute lightprobe occlusion
-
- if (sdfgi.use_occlusion) {
- ivec3 occ_indexv = abs((sdfgi.cascades[i].probe_world_offset + probe_posi) & ivec3(1, 1, 1)) * ivec3(1, 2, 4);
- vec4 occ_mask = mix(vec4(0.0), vec4(1.0), equal(ivec4(occ_indexv.x | occ_indexv.y), ivec4(0, 1, 2, 3)));
-
- vec3 occ_pos = clamp(cascade_pos, probe_pos - sdfgi.occlusion_clamp, probe_pos + sdfgi.occlusion_clamp) * sdfgi.probe_to_uvw;
- occ_pos.z += float(i);
- if (occ_indexv.z != 0) { //z bit is on, means index is >=4, so make it switch to the other half of textures
- occ_pos.x += 1.0;
- }
-
- occ_pos *= sdfgi.occlusion_renormalize;
- float occlusion = dot(textureLod(sampler3D(sdfgi_occlusion_texture, linear_sampler), occ_pos, 0.0), occ_mask);
-
- weight *= max(occlusion, 0.01);
+ if (any(overflowing)) {
+ uvec3 overflow_factor = mix(uvec3(0), uvec3(2047 << 21, 2047 << 10, 1023), overflowing);
+ uint force_max = overflow_factor.r | overflow_factor.g | overflow_factor.b;
+#ifdef MOLTENVK_USED
+ atomicOr(light_only_map[lpos], force_max);
+#else
+ imageAtomicOr(light_only_map, pos, force_max);
+#endif
}
-
- // Compute ambient texture position
-
- ivec3 uvw = tex_pos;
- uvw.xy += offset.xy;
- uvw.x += offset.z * sdfgi.probe_axis_size;
-
- vec3 ambient = texelFetch(sampler2DArray(sdfgi_ambient_texture, linear_sampler), uvw, 0).rgb;
-
- ambient_accum.rgb += ambient * weight;
- ambient_accum.a += weight;
- }
-
- if (ambient_accum.a > 0) {
- ambient_accum.rgb /= ambient_accum.a;
}
- ambient_total = ambient_accum.rgb;
- break;
+#endif // ALBEDO_USED
}
-
- total_light += ambient_total * params.gi_inject;
+#endif // DENSITY_USED
}
-
-#endif
-
- vec4 final_density = vec4(total_light, total_density);
-
- final_density = mix(final_density, reprojected_density, reproject_amount);
-
- imageStore(density_map, pos, final_density);
-#endif
-
-#ifdef MODE_FOG
-
- ivec3 pos = ivec3(gl_GlobalInvocationID.xy, 0);
-
- if (any(greaterThanEqual(pos, params.fog_volume_size))) {
- return; //do not compute
- }
-
- vec4 fog_accum = vec4(0.0);
- float prev_z = 0.0;
-
- float t = 1.0;
-
- for (int i = 0; i < params.fog_volume_size.z; i++) {
- //compute fog position
- ivec3 fog_pos = pos + ivec3(0, 0, i);
- //get fog value
- vec4 fog = imageLoad(density_map, fog_pos);
-
- //get depth at cell pos
- float z = get_depth_at_pos(fog_cell_size.z, i);
- //get distance from previous pos
- float d = abs(prev_z - z);
- //compute exinction based on beer's
- float extinction = t * exp(-d * fog.a);
- //compute alpha based on different of extinctions
- float alpha = t - extinction;
- //update extinction
- t = extinction;
-
- fog_accum += vec4(fog.rgb * alpha, alpha);
- prev_z = z;
-
- vec4 fog_value;
-
- if (fog_accum.a > 0.0) {
- fog_value = vec4(fog_accum.rgb / fog_accum.a, 1.0 - t);
- } else {
- fog_value = vec4(0.0);
- }
-
- imageStore(fog_map, fog_pos, fog_value);
- }
-
-#endif
-
-#ifdef MODE_FILTER
-
- ivec3 pos = ivec3(gl_GlobalInvocationID.xyz);
-
- const float gauss[7] = float[](0.071303, 0.131514, 0.189879, 0.214607, 0.189879, 0.131514, 0.071303);
-
- const ivec3 filter_dir[3] = ivec3[](ivec3(1, 0, 0), ivec3(0, 1, 0), ivec3(0, 0, 1));
- ivec3 offset = filter_dir[params.filter_axis];
-
- vec4 accum = vec4(0.0);
- for (int i = -3; i <= 3; i++) {
- accum += imageLoad(source_map, clamp(pos + offset * i, ivec3(0), params.fog_volume_size - ivec3(1))) * gauss[i + 3];
- }
-
- imageStore(dest_map, pos, accum);
-
-#endif
}
diff --git a/servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl b/servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl
new file mode 100644
index 0000000000..7c8d4f7f99
--- /dev/null
+++ b/servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl
@@ -0,0 +1,785 @@
+#[compute]
+
+#version 450
+
+#VERSION_DEFINES
+
+/* Do not use subgroups here, seems there is not much advantage and causes glitches
+#if defined(has_GL_KHR_shader_subgroup_ballot) && defined(has_GL_KHR_shader_subgroup_arithmetic)
+#extension GL_KHR_shader_subgroup_ballot: enable
+#extension GL_KHR_shader_subgroup_arithmetic: enable
+
+#define USE_SUBGROUPS
+#endif
+*/
+
+#ifdef MODE_DENSITY
+layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in;
+#else
+layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
+#endif
+
+#include "cluster_data_inc.glsl"
+#include "light_data_inc.glsl"
+
+#define M_PI 3.14159265359
+
+#define DENSITY_SCALE 1024.0
+
+layout(set = 0, binding = 1) uniform texture2D shadow_atlas;
+layout(set = 0, binding = 2) uniform texture2D directional_shadow_atlas;
+
+layout(set = 0, binding = 3, std430) restrict readonly buffer OmniLights {
+ LightData data[];
+}
+omni_lights;
+
+layout(set = 0, binding = 4, std430) restrict readonly buffer SpotLights {
+ LightData data[];
+}
+spot_lights;
+
+layout(set = 0, binding = 5, std140) uniform DirectionalLights {
+ DirectionalLightData data[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS];
+}
+directional_lights;
+
+layout(set = 0, binding = 6, std430) buffer restrict readonly ClusterBuffer {
+ uint data[];
+}
+cluster_buffer;
+
+layout(set = 0, binding = 7) uniform sampler linear_sampler;
+
+#ifdef MODE_DENSITY
+layout(rgba16f, set = 0, binding = 8) uniform restrict writeonly image3D density_map;
+layout(rgba16f, set = 0, binding = 9) uniform restrict readonly image3D fog_map; //unused
+#endif
+
+#ifdef MODE_FOG
+layout(rgba16f, set = 0, binding = 8) uniform restrict readonly image3D density_map;
+layout(rgba16f, set = 0, binding = 9) uniform restrict writeonly image3D fog_map;
+#endif
+
+#ifdef MODE_COPY
+layout(rgba16f, set = 0, binding = 8) uniform restrict readonly image3D source_map;
+layout(rgba16f, set = 0, binding = 9) uniform restrict writeonly image3D dest_map;
+#endif
+
+#ifdef MODE_FILTER
+layout(rgba16f, set = 0, binding = 8) uniform restrict readonly image3D source_map;
+layout(rgba16f, set = 0, binding = 9) uniform restrict writeonly image3D dest_map;
+#endif
+
+layout(set = 0, binding = 10) uniform sampler shadow_sampler;
+
+#define MAX_VOXEL_GI_INSTANCES 8
+
+struct VoxelGIData {
+ mat4 xform; // 64 - 64
+
+ vec3 bounds; // 12 - 76
+ float dynamic_range; // 4 - 80
+
+ float bias; // 4 - 84
+ float normal_bias; // 4 - 88
+ bool blend_ambient; // 4 - 92
+ uint mipmaps; // 4 - 96
+};
+
+layout(set = 0, binding = 11, std140) uniform VoxelGIs {
+ VoxelGIData data[MAX_VOXEL_GI_INSTANCES];
+}
+voxel_gi_instances;
+
+layout(set = 0, binding = 12) uniform texture3D voxel_gi_textures[MAX_VOXEL_GI_INSTANCES];
+
+layout(set = 0, binding = 13) uniform sampler linear_sampler_with_mipmaps;
+
+#ifdef ENABLE_SDFGI
+
+// SDFGI Integration on set 1
+#define SDFGI_MAX_CASCADES 8
+
+struct SDFVoxelGICascadeData {
+ vec3 position;
+ float to_probe;
+ ivec3 probe_world_offset;
+ float to_cell; // 1/bounds * grid_size
+};
+
+layout(set = 1, binding = 0, std140) uniform SDFGI {
+ vec3 grid_size;
+ uint max_cascades;
+
+ bool use_occlusion;
+ int probe_axis_size;
+ float probe_to_uvw;
+ float normal_bias;
+
+ vec3 lightprobe_tex_pixel_size;
+ float energy;
+
+ vec3 lightprobe_uv_offset;
+ float y_mult;
+
+ vec3 occlusion_clamp;
+ uint pad3;
+
+ vec3 occlusion_renormalize;
+ uint pad4;
+
+ vec3 cascade_probe_size;
+ uint pad5;
+
+ SDFVoxelGICascadeData cascades[SDFGI_MAX_CASCADES];
+}
+sdfgi;
+
+layout(set = 1, binding = 1) uniform texture2DArray sdfgi_ambient_texture;
+
+layout(set = 1, binding = 2) uniform texture3D sdfgi_occlusion_texture;
+
+#endif //SDFGI
+
+layout(set = 0, binding = 14, std140) uniform Params {
+ vec2 fog_frustum_size_begin;
+ vec2 fog_frustum_size_end;
+
+ float fog_frustum_end;
+ float ambient_inject;
+ float z_far;
+ int filter_axis;
+
+ vec3 ambient_color;
+ float sky_contribution;
+
+ ivec3 fog_volume_size;
+ uint directional_light_count;
+
+ vec3 base_emission;
+ float base_density;
+
+ vec3 base_scattering;
+ float phase_g;
+
+ float detail_spread;
+ float gi_inject;
+ uint max_voxel_gi_instances;
+ uint cluster_type_size;
+
+ vec2 screen_size;
+ uint cluster_shift;
+ uint cluster_width;
+
+ uint max_cluster_element_count_div_32;
+ bool use_temporal_reprojection;
+ uint temporal_frame;
+ float temporal_blend;
+
+ mat3x4 cam_rotation;
+ mat4 to_prev_view;
+
+ mat3 radiance_inverse_xform;
+}
+params;
+#ifndef MODE_COPY
+layout(set = 0, binding = 15) uniform texture3D prev_density_texture;
+
+#ifdef MOLTENVK_USED
+layout(set = 0, binding = 16) buffer density_only_map_buffer {
+ uint density_only_map[];
+};
+layout(set = 0, binding = 17) buffer light_only_map_buffer {
+ uint light_only_map[];
+};
+layout(set = 0, binding = 18) buffer emissive_only_map_buffer {
+ uint emissive_only_map[];
+};
+#else
+layout(r32ui, set = 0, binding = 16) uniform uimage3D density_only_map;
+layout(r32ui, set = 0, binding = 17) uniform uimage3D light_only_map;
+layout(r32ui, set = 0, binding = 18) uniform uimage3D emissive_only_map;
+#endif
+
+#ifdef USE_RADIANCE_CUBEMAP_ARRAY
+layout(set = 0, binding = 19) uniform textureCubeArray sky_texture;
+#else
+layout(set = 0, binding = 19) uniform textureCube sky_texture;
+#endif
+#endif // MODE_COPY
+
+float get_depth_at_pos(float cell_depth_size, int z) {
+ float d = float(z) * cell_depth_size + cell_depth_size * 0.5; //center of voxels
+ d = pow(d, params.detail_spread);
+ return params.fog_frustum_end * d;
+}
+
+vec3 hash3f(uvec3 x) {
+ x = ((x >> 16) ^ x) * 0x45d9f3b;
+ x = ((x >> 16) ^ x) * 0x45d9f3b;
+ x = (x >> 16) ^ x;
+ return vec3(x & 0xFFFFF) / vec3(float(0xFFFFF));
+}
+
+float get_omni_attenuation(float dist, float inv_range, float decay) {
+ float nd = dist * inv_range;
+ nd *= nd;
+ nd *= nd; // nd^4
+ nd = max(1.0 - nd, 0.0);
+ nd *= nd; // nd^2
+ return nd * pow(max(dist, 0.0001), -decay);
+}
+
+void cluster_get_item_range(uint p_offset, out uint item_min, out uint item_max, out uint item_from, out uint item_to) {
+ uint item_min_max = cluster_buffer.data[p_offset];
+ item_min = item_min_max & 0xFFFF;
+ item_max = item_min_max >> 16;
+ ;
+
+ item_from = item_min >> 5;
+ item_to = (item_max == 0) ? 0 : ((item_max - 1) >> 5) + 1; //side effect of how it is stored, as item_max 0 means no elements
+}
+
+uint cluster_get_range_clip_mask(uint i, uint z_min, uint z_max) {
+ int local_min = clamp(int(z_min) - int(i) * 32, 0, 31);
+ int mask_width = min(int(z_max) - int(z_min), 32 - local_min);
+ return bitfieldInsert(uint(0), uint(0xFFFFFFFF), local_min, mask_width);
+}
+
+float henyey_greenstein(float cos_theta, float g) {
+ const float k = 0.0795774715459; // 1 / (4 * PI)
+ return k * (1.0 - g * g) / (pow(1.0 + g * g - 2.0 * g * cos_theta, 1.5));
+}
+
+#define TEMPORAL_FRAMES 16
+
+const vec3 halton_map[TEMPORAL_FRAMES] = vec3[](
+ vec3(0.5, 0.33333333, 0.2),
+ vec3(0.25, 0.66666667, 0.4),
+ vec3(0.75, 0.11111111, 0.6),
+ vec3(0.125, 0.44444444, 0.8),
+ vec3(0.625, 0.77777778, 0.04),
+ vec3(0.375, 0.22222222, 0.24),
+ vec3(0.875, 0.55555556, 0.44),
+ vec3(0.0625, 0.88888889, 0.64),
+ vec3(0.5625, 0.03703704, 0.84),
+ vec3(0.3125, 0.37037037, 0.08),
+ vec3(0.8125, 0.7037037, 0.28),
+ vec3(0.1875, 0.14814815, 0.48),
+ vec3(0.6875, 0.48148148, 0.68),
+ vec3(0.4375, 0.81481481, 0.88),
+ vec3(0.9375, 0.25925926, 0.12),
+ vec3(0.03125, 0.59259259, 0.32));
+
+void main() {
+ vec3 fog_cell_size = 1.0 / vec3(params.fog_volume_size);
+
+#ifdef MODE_DENSITY
+
+ ivec3 pos = ivec3(gl_GlobalInvocationID.xyz);
+ if (any(greaterThanEqual(pos, params.fog_volume_size))) {
+ return; //do not compute
+ }
+#ifdef MOLTENVK_USED
+ uint lpos = pos.z * params.fog_volume_size.x * params.fog_volume_size.y + pos.y * params.fog_volume_size.x + pos.x;
+#endif
+
+ vec3 posf = vec3(pos);
+
+ //posf += mix(vec3(0.0),vec3(1.0),0.3) * hash3f(uvec3(pos)) * 2.0 - 1.0;
+
+ vec3 fog_unit_pos = posf * fog_cell_size + fog_cell_size * 0.5; //center of voxels
+
+ uvec2 screen_pos = uvec2(fog_unit_pos.xy * params.screen_size);
+ uvec2 cluster_pos = screen_pos >> params.cluster_shift;
+ uint cluster_offset = (params.cluster_width * cluster_pos.y + cluster_pos.x) * (params.max_cluster_element_count_div_32 + 32);
+ //positions in screen are too spread apart, no hopes for optimizing with subgroups
+
+ fog_unit_pos.z = pow(fog_unit_pos.z, params.detail_spread);
+
+ vec3 view_pos;
+ view_pos.xy = (fog_unit_pos.xy * 2.0 - 1.0) * mix(params.fog_frustum_size_begin, params.fog_frustum_size_end, vec2(fog_unit_pos.z));
+ view_pos.z = -params.fog_frustum_end * fog_unit_pos.z;
+ view_pos.y = -view_pos.y;
+
+ vec4 reprojected_density = vec4(0.0);
+ float reproject_amount = 0.0;
+
+ if (params.use_temporal_reprojection) {
+ vec3 prev_view = (params.to_prev_view * vec4(view_pos, 1.0)).xyz;
+ //undo transform into prev view
+ prev_view.y = -prev_view.y;
+ //z back to unit size
+ prev_view.z /= -params.fog_frustum_end;
+ //xy back to unit size
+ prev_view.xy /= mix(params.fog_frustum_size_begin, params.fog_frustum_size_end, vec2(prev_view.z));
+ prev_view.xy = prev_view.xy * 0.5 + 0.5;
+ //z back to unspread value
+ prev_view.z = pow(prev_view.z, 1.0 / params.detail_spread);
+
+ if (all(greaterThan(prev_view, vec3(0.0))) && all(lessThan(prev_view, vec3(1.0)))) {
+ //reprojectinon fits
+
+ reprojected_density = textureLod(sampler3D(prev_density_texture, linear_sampler), prev_view, 0.0);
+ reproject_amount = params.temporal_blend;
+
+ // Since we can reproject, now we must jitter the current view pos.
+ // This is done here because cells that can't reproject should not jitter.
+
+ fog_unit_pos = posf * fog_cell_size + fog_cell_size * halton_map[params.temporal_frame]; //center of voxels, offset by halton table
+
+ screen_pos = uvec2(fog_unit_pos.xy * params.screen_size);
+ cluster_pos = screen_pos >> params.cluster_shift;
+ cluster_offset = (params.cluster_width * cluster_pos.y + cluster_pos.x) * (params.max_cluster_element_count_div_32 + 32);
+ //positions in screen are too spread apart, no hopes for optimizing with subgroups
+
+ fog_unit_pos.z = pow(fog_unit_pos.z, params.detail_spread);
+
+ view_pos.xy = (fog_unit_pos.xy * 2.0 - 1.0) * mix(params.fog_frustum_size_begin, params.fog_frustum_size_end, vec2(fog_unit_pos.z));
+ view_pos.z = -params.fog_frustum_end * fog_unit_pos.z;
+ view_pos.y = -view_pos.y;
+ }
+ }
+
+ uint cluster_z = uint(clamp((abs(view_pos.z) / params.z_far) * 32.0, 0.0, 31.0));
+
+ vec3 total_light = vec3(0.0);
+
+ float total_density = params.base_density;
+#ifdef MOLTENVK_USED
+ uint local_density = density_only_map[lpos];
+#else
+ uint local_density = imageLoad(density_only_map, pos).x;
+#endif
+
+ total_density += float(int(local_density)) / DENSITY_SCALE;
+ total_density = max(0.0, total_density);
+
+#ifdef MOLTENVK_USED
+ uint scattering_u = light_only_map[lpos];
+#else
+ uint scattering_u = imageLoad(light_only_map, pos).x;
+#endif
+ vec3 scattering = vec3(scattering_u >> 21, (scattering_u << 11) >> 21, scattering_u % 1024) / vec3(2047.0, 2047.0, 1023.0);
+ scattering += params.base_scattering * params.base_density;
+
+#ifdef MOLTENVK_USED
+ uint emission_u = emissive_only_map[lpos];
+#else
+ uint emission_u = imageLoad(emissive_only_map, pos).x;
+#endif
+ vec3 emission = vec3(emission_u >> 21, (emission_u << 11) >> 21, emission_u % 1024) / vec3(511.0, 511.0, 255.0);
+ emission += params.base_emission * params.base_density;
+
+ float cell_depth_size = abs(view_pos.z - get_depth_at_pos(fog_cell_size.z, pos.z + 1));
+ //compute directional lights
+
+ if (total_density > 0.001) {
+ for (uint i = 0; i < params.directional_light_count; i++) {
+ vec3 shadow_attenuation = vec3(1.0);
+
+ if (directional_lights.data[i].shadow_enabled) {
+ float depth_z = -view_pos.z;
+
+ vec4 pssm_coord;
+ vec3 shadow_color = directional_lights.data[i].shadow_color1.rgb;
+ vec3 light_dir = directional_lights.data[i].direction;
+ vec4 v = vec4(view_pos, 1.0);
+ float z_range;
+
+ if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
+ pssm_coord = (directional_lights.data[i].shadow_matrix1 * v);
+ pssm_coord /= pssm_coord.w;
+ z_range = directional_lights.data[i].shadow_z_range.x;
+
+ } else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
+ pssm_coord = (directional_lights.data[i].shadow_matrix2 * v);
+ pssm_coord /= pssm_coord.w;
+ z_range = directional_lights.data[i].shadow_z_range.y;
+
+ } else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
+ pssm_coord = (directional_lights.data[i].shadow_matrix3 * v);
+ pssm_coord /= pssm_coord.w;
+ z_range = directional_lights.data[i].shadow_z_range.z;
+
+ } else {
+ pssm_coord = (directional_lights.data[i].shadow_matrix4 * v);
+ pssm_coord /= pssm_coord.w;
+ z_range = directional_lights.data[i].shadow_z_range.w;
+ }
+
+ float depth = texture(sampler2D(directional_shadow_atlas, linear_sampler), pssm_coord.xy).r;
+ float shadow = exp(min(0.0, (depth - pssm_coord.z)) * z_range * directional_lights.data[i].shadow_volumetric_fog_fade);
+
+ shadow = mix(shadow, 1.0, smoothstep(directional_lights.data[i].fade_from, directional_lights.data[i].fade_to, view_pos.z)); //done with negative values for performance
+
+ shadow_attenuation = mix(shadow_color, vec3(1.0), shadow);
+ }
+
+ total_light += shadow_attenuation * directional_lights.data[i].color * directional_lights.data[i].energy * henyey_greenstein(dot(normalize(view_pos), normalize(directional_lights.data[i].direction)), params.phase_g);
+ }
+
+ // Compute light from sky
+ if (params.ambient_inject > 0.0) {
+ vec3 isotropic = vec3(0.0);
+ vec3 anisotropic = vec3(0.0);
+ if (params.sky_contribution > 0.0) {
+ float mip_bias = 2.0 + total_density * (MAX_SKY_LOD - 2.0); // Not physically based, but looks nice
+ vec3 scatter_direction = (params.radiance_inverse_xform * normalize(view_pos)) * sign(params.phase_g);
+#ifdef USE_RADIANCE_CUBEMAP_ARRAY
+ isotropic = texture(samplerCubeArray(sky_texture, linear_sampler_with_mipmaps), vec4(0.0, 1.0, 0.0, mip_bias)).rgb;
+ anisotropic = texture(samplerCubeArray(sky_texture, linear_sampler_with_mipmaps), vec4(scatter_direction, mip_bias)).rgb;
+#else
+ isotropic = textureLod(samplerCube(sky_texture, linear_sampler_with_mipmaps), vec3(0.0, 1.0, 0.0), mip_bias).rgb;
+ anisotropic = textureLod(samplerCube(sky_texture, linear_sampler_with_mipmaps), vec3(scatter_direction), mip_bias).rgb;
+#endif //USE_RADIANCE_CUBEMAP_ARRAY
+ }
+
+ total_light += mix(params.ambient_color, mix(isotropic, anisotropic, abs(params.phase_g)), params.sky_contribution) * params.ambient_inject;
+ }
+
+ //compute lights from cluster
+
+ { //omni lights
+
+ uint cluster_omni_offset = cluster_offset;
+
+ uint item_min;
+ uint item_max;
+ uint item_from;
+ uint item_to;
+
+ cluster_get_item_range(cluster_omni_offset + params.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to);
+
+#ifdef USE_SUBGROUPS
+ item_from = subgroupBroadcastFirst(subgroupMin(item_from));
+ item_to = subgroupBroadcastFirst(subgroupMax(item_to));
+#endif
+
+ for (uint i = item_from; i < item_to; i++) {
+ uint mask = cluster_buffer.data[cluster_omni_offset + i];
+ mask &= cluster_get_range_clip_mask(i, item_min, item_max);
+#ifdef USE_SUBGROUPS
+ uint merged_mask = subgroupBroadcastFirst(subgroupOr(mask));
+#else
+ uint merged_mask = mask;
+#endif
+
+ while (merged_mask != 0) {
+ uint bit = findMSB(merged_mask);
+ merged_mask &= ~(1 << bit);
+#ifdef USE_SUBGROUPS
+ if (((1 << bit) & mask) == 0) { //do not process if not originally here
+ continue;
+ }
+#endif
+ uint light_index = 32 * i + bit;
+
+ //if (!bool(omni_omni_lights.data[light_index].mask & draw_call.layer_mask)) {
+ // continue; //not masked
+ //}
+
+ vec3 light_pos = omni_lights.data[light_index].position;
+ float d = distance(omni_lights.data[light_index].position, view_pos);
+ float shadow_attenuation = 1.0;
+
+ if (d * omni_lights.data[light_index].inv_radius < 1.0) {
+ float attenuation = get_omni_attenuation(d, omni_lights.data[light_index].inv_radius, omni_lights.data[light_index].attenuation);
+
+ vec3 light = omni_lights.data[light_index].color;
+
+ if (omni_lights.data[light_index].shadow_enabled) {
+ //has shadow
+ vec4 uv_rect = omni_lights.data[light_index].atlas_rect;
+ vec2 flip_offset = omni_lights.data[light_index].direction.xy;
+
+ vec3 local_vert = (omni_lights.data[light_index].shadow_matrix * vec4(view_pos, 1.0)).xyz;
+
+ float shadow_len = length(local_vert); //need to remember shadow len from here
+ vec3 shadow_sample = normalize(local_vert);
+
+ if (shadow_sample.z >= 0.0) {
+ uv_rect.xy += flip_offset;
+ }
+
+ shadow_sample.z = 1.0 + abs(shadow_sample.z);
+ vec3 pos = vec3(shadow_sample.xy / shadow_sample.z, shadow_len - omni_lights.data[light_index].shadow_bias);
+ pos.z *= omni_lights.data[light_index].inv_radius;
+
+ pos.xy = pos.xy * 0.5 + 0.5;
+ pos.xy = uv_rect.xy + pos.xy * uv_rect.zw;
+
+ float depth = texture(sampler2D(shadow_atlas, linear_sampler), pos.xy).r;
+
+ shadow_attenuation = exp(min(0.0, (depth - pos.z)) / omni_lights.data[light_index].inv_radius * omni_lights.data[light_index].shadow_volumetric_fog_fade);
+ }
+ total_light += light * attenuation * shadow_attenuation * henyey_greenstein(dot(normalize(light_pos - view_pos), normalize(view_pos)), params.phase_g);
+ }
+ }
+ }
+ }
+
+ { //spot lights
+
+ uint cluster_spot_offset = cluster_offset + params.cluster_type_size;
+
+ uint item_min;
+ uint item_max;
+ uint item_from;
+ uint item_to;
+
+ cluster_get_item_range(cluster_spot_offset + params.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to);
+
+#ifdef USE_SUBGROUPS
+ item_from = subgroupBroadcastFirst(subgroupMin(item_from));
+ item_to = subgroupBroadcastFirst(subgroupMax(item_to));
+#endif
+
+ for (uint i = item_from; i < item_to; i++) {
+ uint mask = cluster_buffer.data[cluster_spot_offset + i];
+ mask &= cluster_get_range_clip_mask(i, item_min, item_max);
+#ifdef USE_SUBGROUPS
+ uint merged_mask = subgroupBroadcastFirst(subgroupOr(mask));
+#else
+ uint merged_mask = mask;
+#endif
+
+ while (merged_mask != 0) {
+ uint bit = findMSB(merged_mask);
+ merged_mask &= ~(1 << bit);
+#ifdef USE_SUBGROUPS
+ if (((1 << bit) & mask) == 0) { //do not process if not originally here
+ continue;
+ }
+#endif
+
+ //if (!bool(omni_lights.data[light_index].mask & draw_call.layer_mask)) {
+ // continue; //not masked
+ //}
+
+ uint light_index = 32 * i + bit;
+
+ vec3 light_pos = spot_lights.data[light_index].position;
+ vec3 light_rel_vec = spot_lights.data[light_index].position - view_pos;
+ float d = length(light_rel_vec);
+ float shadow_attenuation = 1.0;
+
+ if (d * spot_lights.data[light_index].inv_radius < 1.0) {
+ float attenuation = get_omni_attenuation(d, spot_lights.data[light_index].inv_radius, spot_lights.data[light_index].attenuation);
+
+ vec3 spot_dir = spot_lights.data[light_index].direction;
+ float scos = max(dot(-normalize(light_rel_vec), spot_dir), spot_lights.data[light_index].cone_angle);
+ float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_lights.data[light_index].cone_angle));
+ attenuation *= 1.0 - pow(spot_rim, spot_lights.data[light_index].cone_attenuation);
+
+ vec3 light = spot_lights.data[light_index].color;
+
+ if (spot_lights.data[light_index].shadow_enabled) {
+ //has shadow
+ vec4 uv_rect = spot_lights.data[light_index].atlas_rect;
+ vec2 flip_offset = spot_lights.data[light_index].direction.xy;
+
+ vec3 local_vert = (spot_lights.data[light_index].shadow_matrix * vec4(view_pos, 1.0)).xyz;
+
+ float shadow_len = length(local_vert); //need to remember shadow len from here
+ vec3 shadow_sample = normalize(local_vert);
+
+ if (shadow_sample.z >= 0.0) {
+ uv_rect.xy += flip_offset;
+ }
+
+ shadow_sample.z = 1.0 + abs(shadow_sample.z);
+ vec3 pos = vec3(shadow_sample.xy / shadow_sample.z, shadow_len - spot_lights.data[light_index].shadow_bias);
+ pos.z *= spot_lights.data[light_index].inv_radius;
+
+ pos.xy = pos.xy * 0.5 + 0.5;
+ pos.xy = uv_rect.xy + pos.xy * uv_rect.zw;
+
+ float depth = texture(sampler2D(shadow_atlas, linear_sampler), pos.xy).r;
+
+ shadow_attenuation = exp(min(0.0, (depth - pos.z)) / spot_lights.data[light_index].inv_radius * spot_lights.data[light_index].shadow_volumetric_fog_fade);
+ }
+ total_light += light * attenuation * shadow_attenuation * henyey_greenstein(dot(normalize(light_rel_vec), normalize(view_pos)), params.phase_g);
+ }
+ }
+ }
+ }
+
+ vec3 world_pos = mat3(params.cam_rotation) * view_pos;
+
+ for (uint i = 0; i < params.max_voxel_gi_instances; i++) {
+ vec3 position = (voxel_gi_instances.data[i].xform * vec4(world_pos, 1.0)).xyz;
+
+ //this causes corrupted pixels, i have no idea why..
+ if (all(bvec2(all(greaterThanEqual(position, vec3(0.0))), all(lessThan(position, voxel_gi_instances.data[i].bounds))))) {
+ position /= voxel_gi_instances.data[i].bounds;
+
+ vec4 light = vec4(0.0);
+ for (uint j = 0; j < voxel_gi_instances.data[i].mipmaps; j++) {
+ vec4 slight = textureLod(sampler3D(voxel_gi_textures[i], linear_sampler_with_mipmaps), position, float(j));
+ float a = (1.0 - light.a);
+ light += a * slight;
+ }
+
+ light.rgb *= voxel_gi_instances.data[i].dynamic_range * params.gi_inject;
+
+ total_light += light.rgb;
+ }
+ }
+
+ //sdfgi
+#ifdef ENABLE_SDFGI
+
+ {
+ float blend = -1.0;
+ vec3 ambient_total = vec3(0.0);
+
+ for (uint i = 0; i < sdfgi.max_cascades; i++) {
+ vec3 cascade_pos = (world_pos - sdfgi.cascades[i].position) * sdfgi.cascades[i].to_probe;
+
+ if (any(lessThan(cascade_pos, vec3(0.0))) || any(greaterThanEqual(cascade_pos, sdfgi.cascade_probe_size))) {
+ continue; //skip cascade
+ }
+
+ vec3 base_pos = floor(cascade_pos);
+ ivec3 probe_base_pos = ivec3(base_pos);
+
+ vec4 ambient_accum = vec4(0.0);
+
+ ivec3 tex_pos = ivec3(probe_base_pos.xy, int(i));
+ tex_pos.x += probe_base_pos.z * sdfgi.probe_axis_size;
+
+ for (uint j = 0; j < 8; j++) {
+ ivec3 offset = (ivec3(j) >> ivec3(0, 1, 2)) & ivec3(1, 1, 1);
+ ivec3 probe_posi = probe_base_pos;
+ probe_posi += offset;
+
+ // Compute weight
+
+ vec3 probe_pos = vec3(probe_posi);
+ vec3 probe_to_pos = cascade_pos - probe_pos;
+
+ vec3 trilinear = vec3(1.0) - abs(probe_to_pos);
+ float weight = trilinear.x * trilinear.y * trilinear.z;
+
+ // Compute lightprobe occlusion
+
+ if (sdfgi.use_occlusion) {
+ ivec3 occ_indexv = abs((sdfgi.cascades[i].probe_world_offset + probe_posi) & ivec3(1, 1, 1)) * ivec3(1, 2, 4);
+ vec4 occ_mask = mix(vec4(0.0), vec4(1.0), equal(ivec4(occ_indexv.x | occ_indexv.y), ivec4(0, 1, 2, 3)));
+
+ vec3 occ_pos = clamp(cascade_pos, probe_pos - sdfgi.occlusion_clamp, probe_pos + sdfgi.occlusion_clamp) * sdfgi.probe_to_uvw;
+ occ_pos.z += float(i);
+ if (occ_indexv.z != 0) { //z bit is on, means index is >=4, so make it switch to the other half of textures
+ occ_pos.x += 1.0;
+ }
+
+ occ_pos *= sdfgi.occlusion_renormalize;
+ float occlusion = dot(textureLod(sampler3D(sdfgi_occlusion_texture, linear_sampler), occ_pos, 0.0), occ_mask);
+
+ weight *= max(occlusion, 0.01);
+ }
+
+ // Compute ambient texture position
+
+ ivec3 uvw = tex_pos;
+ uvw.xy += offset.xy;
+ uvw.x += offset.z * sdfgi.probe_axis_size;
+
+ vec3 ambient = texelFetch(sampler2DArray(sdfgi_ambient_texture, linear_sampler), uvw, 0).rgb;
+
+ ambient_accum.rgb += ambient * weight;
+ ambient_accum.a += weight;
+ }
+
+ if (ambient_accum.a > 0) {
+ ambient_accum.rgb /= ambient_accum.a;
+ }
+ ambient_total = ambient_accum.rgb;
+ break;
+ }
+
+ total_light += ambient_total * params.gi_inject;
+ }
+
+#endif
+ }
+
+ vec4 final_density = vec4(total_light * scattering + emission, total_density);
+
+ final_density = mix(final_density, reprojected_density, reproject_amount);
+
+ imageStore(density_map, pos, final_density);
+#ifdef MOLTENVK_USED
+ density_only_map[lpos] = 0;
+ light_only_map[lpos] = 0;
+ emissive_only_map[lpos] = 0;
+#else
+ imageStore(density_only_map, pos, uvec4(0));
+ imageStore(light_only_map, pos, uvec4(0));
+ imageStore(emissive_only_map, pos, uvec4(0));
+#endif
+#endif
+
+#ifdef MODE_FOG
+
+ ivec3 pos = ivec3(gl_GlobalInvocationID.xy, 0);
+
+ if (any(greaterThanEqual(pos, params.fog_volume_size))) {
+ return; //do not compute
+ }
+
+ vec4 fog_accum = vec4(0.0, 0.0, 0.0, 1.0);
+ float prev_z = 0.0;
+
+ for (int i = 0; i < params.fog_volume_size.z; i++) {
+ //compute fog position
+ ivec3 fog_pos = pos + ivec3(0, 0, i);
+ //get fog value
+ vec4 fog = imageLoad(density_map, fog_pos);
+
+ //get depth at cell pos
+ float z = get_depth_at_pos(fog_cell_size.z, i);
+ //get distance from previous pos
+ float d = abs(prev_z - z);
+ //compute transmittance using beer's law
+ float transmittance = exp(-d * fog.a);
+
+ fog_accum.rgb += ((fog.rgb - fog.rgb * transmittance) / max(fog.a, 0.00001)) * fog_accum.a;
+ fog_accum.a *= transmittance;
+
+ prev_z = z;
+
+ imageStore(fog_map, fog_pos, vec4(fog_accum.rgb, 1.0 - fog_accum.a));
+ }
+
+#endif
+
+#ifdef MODE_FILTER
+
+ ivec3 pos = ivec3(gl_GlobalInvocationID.xyz);
+
+ const float gauss[7] = float[](0.071303, 0.131514, 0.189879, 0.214607, 0.189879, 0.131514, 0.071303);
+
+ const ivec3 filter_dir[3] = ivec3[](ivec3(1, 0, 0), ivec3(0, 1, 0), ivec3(0, 0, 1));
+ ivec3 offset = filter_dir[params.filter_axis];
+
+ vec4 accum = vec4(0.0);
+ for (int i = -3; i <= 3; i++) {
+ accum += imageLoad(source_map, clamp(pos + offset * i, ivec3(0), params.fog_volume_size - ivec3(1))) * gauss[i + 3];
+ }
+
+ imageStore(dest_map, pos, accum);
+
+#endif
+#ifdef MODE_COPY
+ ivec3 pos = ivec3(gl_GlobalInvocationID.xyz);
+ if (any(greaterThanEqual(pos, params.fog_volume_size))) {
+ return; //do not compute
+ }
+
+ imageStore(dest_map, pos, imageLoad(source_map, pos));
+
+#endif
+}
diff --git a/servers/rendering/renderer_rd/shaders/voxel_gi.glsl b/servers/rendering/renderer_rd/shaders/voxel_gi.glsl
index 779f04ed35..73a97d9df1 100644
--- a/servers/rendering/renderer_rd/shaders/voxel_gi.glsl
+++ b/servers/rendering/renderer_rd/shaders/voxel_gi.glsl
@@ -13,7 +13,6 @@ layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
#ifndef MODE_DYNAMIC
#define NO_CHILDREN 0xFFFFFFFF
-#define GREY_VEC vec3(0.33333, 0.33333, 0.33333)
struct CellChildren {
uint children[8];
diff --git a/servers/rendering/renderer_rd/shaders/voxel_gi_debug.glsl b/servers/rendering/renderer_rd/shaders/voxel_gi_debug.glsl
index 281c496df3..3f3437f527 100644
--- a/servers/rendering/renderer_rd/shaders/voxel_gi_debug.glsl
+++ b/servers/rendering/renderer_rd/shaders/voxel_gi_debug.glsl
@@ -90,66 +90,10 @@ void main() {
#endif
#ifdef MODE_DEBUG_LIGHT
-
-#ifdef USE_ANISOTROPY
-
-#define POS_X 0
-#define POS_Y 1
-#define POS_Z 2
-#define NEG_X 3
-#define NEG_Y 4
-#define NEG_Z 5
-
- const uint triangle_aniso[12] = uint[](
- NEG_X,
- NEG_Z,
- NEG_Y,
- NEG_Z,
- NEG_X,
- NEG_Y,
- POS_Z,
- POS_X,
- POS_X,
- POS_Y,
- POS_Y,
- POS_Z);
-
- color_interp.xyz = texelFetch(sampler3D(color_tex, tex_sampler), ivec3(posu), int(params.level)).xyz * params.dynamic_range;
- vec3 aniso_pos = texelFetch(sampler3D(aniso_pos_tex, tex_sampler), ivec3(posu), int(params.level)).xyz;
- vec3 aniso_neg = texelFetch(sampler3D(aniso_neg_tex, tex_sampler), ivec3(posu), int(params.level)).xyz;
- uint side = triangle_aniso[gl_VertexIndex / 3];
-
- float strength = 0.0;
- switch (side) {
- case POS_X:
- strength = aniso_pos.x;
- break;
- case POS_Y:
- strength = aniso_pos.y;
- break;
- case POS_Z:
- strength = aniso_pos.z;
- break;
- case NEG_X:
- strength = aniso_neg.x;
- break;
- case NEG_Y:
- strength = aniso_neg.y;
- break;
- case NEG_Z:
- strength = aniso_neg.z;
- break;
- }
-
- color_interp.xyz *= strength;
-
-#else
color_interp = texelFetch(sampler3D(color_tex, tex_sampler), ivec3(posu), int(params.level));
color_interp.xyz *params.dynamic_range;
-
#endif
-#endif
float scale = (1 << params.level);
gl_Position = params.projection * vec4((vec3(posu) + vertex) * scale, 1.0);
diff --git a/servers/rendering/renderer_rd/shaders/voxel_gi_sdf.glsl b/servers/rendering/renderer_rd/shaders/voxel_gi_sdf.glsl
index e20b3f680d..3bb4421646 100644
--- a/servers/rendering/renderer_rd/shaders/voxel_gi_sdf.glsl
+++ b/servers/rendering/renderer_rd/shaders/voxel_gi_sdf.glsl
@@ -6,10 +6,9 @@
layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in;
-#define MAX_DISTANCE 100000
+#define MAX_DISTANCE 100000.0
#define NO_CHILDREN 0xFFFFFFFF
-#define GREY_VEC vec3(0.33333, 0.33333, 0.33333)
struct CellChildren {
uint children[8];
@@ -44,7 +43,7 @@ params;
void main() {
vec3 pos = vec3(gl_GlobalInvocationID);
- float closest_dist = 100000.0;
+ float closest_dist = MAX_DISTANCE;
for (uint i = params.offset; i < params.end; i++) {
vec3 posu = vec3(uvec3(cell_data.data[i].position & 0x7FF, (cell_data.data[i].position >> 11) & 0x3FF, cell_data.data[i].position >> 21));
diff --git a/servers/rendering/renderer_scene.cpp b/servers/rendering/renderer_scene.cpp
index dd544d4f3f..b3fdd88626 100644
--- a/servers/rendering/renderer_scene.cpp
+++ b/servers/rendering/renderer_scene.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/rendering/renderer_scene.h b/servers/rendering/renderer_scene.h
index 5961f59b6f..426d22f83e 100644
--- a/servers/rendering/renderer_scene.h
+++ b/servers/rendering/renderer_scene.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -76,6 +76,7 @@ public:
virtual void instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight) = 0;
virtual void instance_set_surface_override_material(RID p_instance, int p_surface, RID p_material) = 0;
virtual void instance_set_visible(RID p_instance, bool p_visible) = 0;
+ virtual void instance_geometry_set_transparency(RID p_instance, float p_transparency) = 0;
virtual void instance_set_custom_aabb(RID p_instance, AABB p_aabb) = 0;
@@ -84,6 +85,8 @@ public:
virtual void instance_set_extra_visibility_margin(RID p_instance, real_t p_margin) = 0;
virtual void instance_set_visibility_parent(RID p_instance, RID p_parent_instance) = 0;
+ virtual void instance_set_ignore_culling(RID p_instance, bool p_enabled) = 0;
+
// don't use these in a game!
virtual Vector<ObjectID> instances_cull_aabb(const AABB &p_aabb, RID p_scenario = RID()) const = 0;
virtual Vector<ObjectID> instances_cull_ray(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario = RID()) const = 0;
@@ -92,11 +95,11 @@ public:
virtual void instance_geometry_set_flag(RID p_instance, RS::InstanceFlags p_flags, bool p_enabled) = 0;
virtual void instance_geometry_set_cast_shadows_setting(RID p_instance, RS::ShadowCastingSetting p_shadow_casting_setting) = 0;
virtual void instance_geometry_set_material_override(RID p_instance, RID p_material) = 0;
+ virtual void instance_geometry_set_material_overlay(RID p_instance, RID p_material) = 0;
- virtual void instance_geometry_set_visibility_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin) = 0;
+ virtual void instance_geometry_set_visibility_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin, RS::VisibilityRangeFadeMode p_fade_mode) = 0;
virtual void instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index) = 0;
virtual void instance_geometry_set_lod_bias(RID p_instance, float p_lod_bias) = 0;
-
virtual void instance_geometry_set_shader_parameter(RID p_instance, const StringName &p_parameter, const Variant &p_value) = 0;
virtual void instance_geometry_get_shader_parameter_list(RID p_instance, List<PropertyInfo> *p_parameters) const = 0;
virtual Variant instance_geometry_get_shader_parameter(RID p_instance, const StringName &p_parameter) const = 0;
@@ -132,7 +135,7 @@ public:
virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) = 0;
virtual void environment_glow_set_use_high_quality(bool p_enable) = 0;
- virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount) = 0;
+ virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) = 0;
virtual void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) = 0;
virtual void environment_set_volumetric_fog_filter_active(bool p_enable) = 0;
@@ -141,10 +144,12 @@ public:
virtual void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) = 0;
virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) = 0;
-
virtual void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) = 0;
- virtual void environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) = 0;
+ virtual void environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) = 0;
+ virtual void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) = 0;
+
+ virtual void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) = 0;
virtual void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) = 0;
virtual void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) = 0;
@@ -189,7 +194,7 @@ public:
virtual RID render_buffers_create() = 0;
- virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) = 0;
+ virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) = 0;
virtual void gi_set_use_half_resolution(bool p_enable) = 0;
@@ -206,7 +211,7 @@ public:
int info[RS::VIEWPORT_RENDER_INFO_TYPE_MAX][RS::VIEWPORT_RENDER_INFO_MAX] = {};
};
- virtual void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, float p_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RenderInfo *r_render_info = nullptr) = 0;
+ virtual void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, float p_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RenderInfo *r_render_info = nullptr) = 0;
virtual void update() = 0;
virtual void render_probes() = 0;
diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp
index 558516ac7c..8ded180633 100644
--- a/servers/rendering/renderer_scene_cull.cpp
+++ b/servers/rendering/renderer_scene_cull.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -540,6 +540,10 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(instance->base_data);
RSG::storage->free(collision->instance);
} break;
+ case RS::INSTANCE_FOG_VOLUME: {
+ InstanceFogVolumeData *volume = static_cast<InstanceFogVolumeData *>(instance->base_data);
+ scene_render->free(volume->instance);
+ } break;
case RS::INSTANCE_VISIBLITY_NOTIFIER: {
//none
} break;
@@ -632,6 +636,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
scene_render->geometry_instance_set_skeleton(geom->geometry_instance, instance->skeleton);
scene_render->geometry_instance_set_material_override(geom->geometry_instance, instance->material_override);
+ scene_render->geometry_instance_set_material_overlay(geom->geometry_instance, instance->material_overlay);
scene_render->geometry_instance_set_surface_materials(geom->geometry_instance, instance->materials);
scene_render->geometry_instance_set_transform(geom->geometry_instance, instance->transform, instance->aabb, instance->transformed_aabb);
scene_render->geometry_instance_set_layer_mask(geom->geometry_instance, instance->layer_mask);
@@ -640,10 +645,17 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
scene_render->geometry_instance_set_use_dynamic_gi(geom->geometry_instance, instance->dynamic_gi);
scene_render->geometry_instance_set_cast_double_sided_shadows(geom->geometry_instance, instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED);
scene_render->geometry_instance_set_use_lightmap(geom->geometry_instance, RID(), instance->lightmap_uv_scale, instance->lightmap_slice_index);
+ scene_render->geometry_instance_set_transparency(geom->geometry_instance, instance->transparency);
if (instance->lightmap_sh.size() == 9) {
scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, instance->lightmap_sh.ptr());
}
+ for (Set<Instance *>::Element *E = instance->visibility_dependencies.front(); E; E = E->next()) {
+ Instance *dep_instance = E->get();
+ ERR_CONTINUE(dep_instance->array_index == -1);
+ ERR_CONTINUE(dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index != -1);
+ dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = instance->array_index;
+ }
} break;
case RS::INSTANCE_PARTICLES_COLLISION: {
InstanceParticlesCollisionData *collision = memnew(InstanceParticlesCollisionData);
@@ -651,6 +663,12 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
RSG::storage->particles_collision_instance_set_active(collision->instance, instance->visible);
instance->base_data = collision;
} break;
+ case RS::INSTANCE_FOG_VOLUME: {
+ InstanceFogVolumeData *volume = memnew(InstanceFogVolumeData);
+ volume->instance = scene_render->fog_volume_instance_create(p_base);
+ scene_render->fog_volume_instance_set_active(volume->instance, instance->visible);
+ instance->base_data = volume;
+ } break;
case RS::INSTANCE_VISIBLITY_NOTIFIER: {
InstanceVisibilityNotifierData *vnd = memnew(InstanceVisibilityNotifierData);
vnd->base = p_base;
@@ -819,6 +837,18 @@ void RendererSceneCull::instance_set_layer_mask(RID p_instance, uint32_t p_mask)
}
}
+void RendererSceneCull::instance_geometry_set_transparency(RID p_instance, float p_transparency) {
+ Instance *instance = instance_owner.get_or_null(p_instance);
+ ERR_FAIL_COND(!instance);
+
+ instance->transparency = p_transparency;
+
+ if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
+ scene_render->geometry_instance_set_transparency(geom->geometry_instance, p_transparency);
+ }
+}
+
void RendererSceneCull::instance_set_transform(RID p_instance, const Transform3D &p_transform) {
Instance *instance = instance_owner.get_or_null(p_instance);
ERR_FAIL_COND(!instance);
@@ -914,6 +944,11 @@ void RendererSceneCull::instance_set_visible(RID p_instance, bool p_visible) {
RSG::storage->particles_collision_instance_set_active(collision->instance, p_visible);
}
+ if (instance->base_type == RS::INSTANCE_FOG_VOLUME) {
+ InstanceFogVolumeData *volume = static_cast<InstanceFogVolumeData *>(instance->base_data);
+ scene_render->fog_volume_instance_set_active(volume->instance, p_visible);
+ }
+
if (instance->base_type == RS::INSTANCE_OCCLUDER) {
if (instance->scenario) {
RendererSceneOcclusionCull::get_singleton()->scenario_set_instance(instance->scenario->self, p_instance, instance->base, instance->transform, p_visible);
@@ -983,6 +1018,21 @@ void RendererSceneCull::instance_set_extra_visibility_margin(RID p_instance, rea
_instance_queue_update(instance, true, false);
}
+void RendererSceneCull::instance_set_ignore_culling(RID p_instance, bool p_enabled) {
+ Instance *instance = instance_owner.get_or_null(p_instance);
+ ERR_FAIL_COND(!instance);
+ instance->ignore_all_culling = p_enabled;
+
+ if (instance->scenario && instance->array_index >= 0) {
+ InstanceData &idata = instance->scenario->instance_data[instance->array_index];
+ if (instance->ignore_all_culling) {
+ idata.flags |= InstanceData::FLAG_IGNORE_ALL_CULLING;
+ } else {
+ idata.flags &= ~uint32_t(InstanceData::FLAG_IGNORE_ALL_CULLING);
+ }
+ }
+}
+
Vector<ObjectID> RendererSceneCull::instances_cull_aabb(const AABB &p_aabb, RID p_scenario) const {
Vector<ObjectID> instances;
Scenario *scenario = scenario_owner.get_or_null(p_scenario);
@@ -1139,7 +1189,7 @@ void RendererSceneCull::instance_geometry_set_cast_shadows_setting(RID p_instanc
if (instance->scenario && instance->array_index >= 0) {
InstanceData &idata = instance->scenario->instance_data[instance->array_index];
- if (instance->cast_shadows != RS::SHADOW_CASTING_SETTING_SHADOWS_ONLY) {
+ if (instance->cast_shadows != RS::SHADOW_CASTING_SETTING_OFF) {
idata.flags |= InstanceData::FLAG_CAST_SHADOWS;
} else {
idata.flags &= ~uint32_t(InstanceData::FLAG_CAST_SHADOWS);
@@ -1173,7 +1223,20 @@ void RendererSceneCull::instance_geometry_set_material_override(RID p_instance,
}
}
-void RendererSceneCull::instance_geometry_set_visibility_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin) {
+void RendererSceneCull::instance_geometry_set_material_overlay(RID p_instance, RID p_material) {
+ Instance *instance = instance_owner.get_or_null(p_instance);
+ ERR_FAIL_COND(!instance);
+
+ instance->material_overlay = p_material;
+ _instance_queue_update(instance, false, true);
+
+ if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
+ scene_render->geometry_instance_set_material_overlay(geom->geometry_instance, p_material);
+ }
+}
+
+void RendererSceneCull::instance_geometry_set_visibility_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin, RS::VisibilityRangeFadeMode p_fade_mode) {
Instance *instance = instance_owner.get_or_null(p_instance);
ERR_FAIL_COND(!instance);
@@ -1181,6 +1244,7 @@ void RendererSceneCull::instance_geometry_set_visibility_range(RID p_instance, f
instance->visibility_range_end = p_max;
instance->visibility_range_begin_margin = p_min_margin;
instance->visibility_range_end_margin = p_max_margin;
+ instance->visibility_range_fade_mode = p_fade_mode;
_update_instance_visibility_dependencies(instance);
@@ -1190,6 +1254,7 @@ void RendererSceneCull::instance_geometry_set_visibility_range(RID p_instance, f
vd.range_end = instance->visibility_range_end;
vd.range_begin_margin = instance->visibility_range_begin_margin;
vd.range_end_margin = instance->visibility_range_end_margin;
+ vd.fade_mode = p_fade_mode;
}
}
@@ -1199,53 +1264,48 @@ void RendererSceneCull::instance_set_visibility_parent(RID p_instance, RID p_par
Instance *old_parent = instance->visibility_parent;
if (old_parent) {
- if ((1 << old_parent->base_type) & RS::INSTANCE_GEOMETRY_MASK && old_parent->base_data) {
- InstanceGeometryData *old_parent_geom = static_cast<InstanceGeometryData *>(old_parent->base_data);
- old_parent_geom->visibility_dependencies.erase(instance);
- _update_instance_visibility_depth(old_parent);
- }
+ old_parent->visibility_dependencies.erase(instance);
instance->visibility_parent = nullptr;
+ _update_instance_visibility_depth(old_parent);
}
Instance *parent = instance_owner.get_or_null(p_parent_instance);
ERR_FAIL_COND(p_parent_instance.is_valid() && !parent);
if (parent) {
- if ((1 << parent->base_type) & RS::INSTANCE_GEOMETRY_MASK && parent->base_data) {
- InstanceGeometryData *parent_geom = static_cast<InstanceGeometryData *>(parent->base_data);
- parent_geom->visibility_dependencies.insert(instance);
- _update_instance_visibility_depth(parent);
- }
+ parent->visibility_dependencies.insert(instance);
instance->visibility_parent = parent;
+
+ bool cycle_detected = _update_instance_visibility_depth(parent);
+ if (cycle_detected) {
+ ERR_PRINT("Cycle detected in the visibility dependencies tree. The latest change to visibility_parent will have no effect.");
+ parent->visibility_dependencies.erase(instance);
+ instance->visibility_parent = nullptr;
+ }
}
_update_instance_visibility_dependencies(instance);
}
-void RendererSceneCull::_update_instance_visibility_depth(Instance *p_instance) {
+bool RendererSceneCull::_update_instance_visibility_depth(Instance *p_instance) {
bool cycle_detected = false;
Set<Instance *> traversed_nodes;
{
Instance *instance = p_instance;
- while (instance && ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) && instance->base_data) {
- InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
- if (!geom->visibility_dependencies.is_empty()) {
+ while (instance) {
+ if (!instance->visibility_dependencies.is_empty()) {
uint32_t depth = 0;
- for (Set<Instance *>::Element *E = geom->visibility_dependencies.front(); E; E = E->next()) {
- if (((1 << E->get()->base_type) & RS::INSTANCE_GEOMETRY_MASK) == 0 || !E->get()->base_data) {
- continue;
- }
- InstanceGeometryData *child_geom = static_cast<InstanceGeometryData *>(E->get()->base_data);
- depth = MAX(depth, child_geom->visibility_dependencies_depth);
+ for (Set<Instance *>::Element *E = instance->visibility_dependencies.front(); E; E = E->next()) {
+ depth = MAX(depth, E->get()->visibility_dependencies_depth);
}
- geom->visibility_dependencies_depth = depth + 1;
+ instance->visibility_dependencies_depth = depth + 1;
} else {
- geom->visibility_dependencies_depth = 0;
+ instance->visibility_dependencies_depth = 0;
}
if (instance->scenario && instance->visibility_index != -1) {
- instance->scenario->instance_visibility.move(instance->visibility_index, geom->visibility_dependencies_depth);
+ instance->scenario->instance_visibility.move(instance->visibility_index, instance->visibility_dependencies_depth);
}
traversed_nodes.insert(instance);
@@ -1258,17 +1318,7 @@ void RendererSceneCull::_update_instance_visibility_depth(Instance *p_instance)
}
}
- if (cycle_detected) {
- ERR_PRINT("Cycle detected in the visibility dependencies tree.");
- for (Set<Instance *>::Element *E = traversed_nodes.front(); E; E = E->next()) {
- Instance *instance = E->get();
- InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
- geom->visibility_dependencies_depth = 0;
- if (instance->scenario && instance->visibility_index != -1) {
- instance->scenario->instance_visibility.move(instance->visibility_index, geom->visibility_dependencies_depth);
- }
- }
- }
+ return cycle_detected;
}
void RendererSceneCull::_update_instance_visibility_dependencies(Instance *p_instance) {
@@ -1277,7 +1327,7 @@ void RendererSceneCull::_update_instance_visibility_dependencies(Instance *p_ins
bool needs_visibility_cull = has_visibility_range && is_geometry_instance && p_instance->array_index != -1;
if (!needs_visibility_cull && p_instance->visibility_index != -1) {
- p_instance->scenario->instance_visibility.remove(p_instance->visibility_index);
+ p_instance->scenario->instance_visibility.remove_at(p_instance->visibility_index);
p_instance->visibility_index = -1;
} else if (needs_visibility_cull && p_instance->visibility_index == -1) {
InstanceVisibilityData vd;
@@ -1288,25 +1338,42 @@ void RendererSceneCull::_update_instance_visibility_dependencies(Instance *p_ins
vd.range_end_margin = p_instance->visibility_range_end_margin;
vd.position = p_instance->transformed_aabb.get_center();
vd.array_index = p_instance->array_index;
+ vd.fade_mode = p_instance->visibility_range_fade_mode;
- InstanceGeometryData *geom_data = static_cast<InstanceGeometryData *>(p_instance->base_data);
- p_instance->scenario->instance_visibility.insert(vd, geom_data->visibility_dependencies_depth);
+ p_instance->scenario->instance_visibility.insert(vd, p_instance->visibility_dependencies_depth);
}
if (p_instance->scenario && p_instance->array_index != -1) {
- p_instance->scenario->instance_data[p_instance->array_index].visibility_index = p_instance->visibility_index;
+ InstanceData &idata = p_instance->scenario->instance_data[p_instance->array_index];
+ idata.visibility_index = p_instance->visibility_index;
- InstanceGeometryData *geom_data = static_cast<InstanceGeometryData *>(p_instance->base_data);
- if ((has_visibility_range || p_instance->visibility_parent) && (p_instance->visibility_index == -1 || (geom_data && geom_data->visibility_dependencies_depth == 0))) {
- p_instance->scenario->instance_data[p_instance->array_index].flags |= InstanceData::FLAG_VISIBILITY_DEPENDENCY_NEEDS_CHECK;
+ if (is_geometry_instance) {
+ if (has_visibility_range && p_instance->visibility_range_fade_mode == RS::VISIBILITY_RANGE_FADE_SELF) {
+ bool begin_enabled = p_instance->visibility_range_begin > 0.0f;
+ float begin_min = p_instance->visibility_range_begin - p_instance->visibility_range_begin_margin;
+ float begin_max = p_instance->visibility_range_begin + p_instance->visibility_range_begin_margin;
+ bool end_enabled = p_instance->visibility_range_end > 0.0f;
+ float end_min = p_instance->visibility_range_end - p_instance->visibility_range_end_margin;
+ float end_max = p_instance->visibility_range_end + p_instance->visibility_range_end_margin;
+ scene_render->geometry_instance_set_fade_range(idata.instance_geometry, begin_enabled, begin_min, begin_max, end_enabled, end_min, end_max);
+ } else {
+ scene_render->geometry_instance_set_fade_range(idata.instance_geometry, false, 0.0f, 0.0f, false, 0.0f, 0.0f);
+ }
+ }
+
+ if ((has_visibility_range || p_instance->visibility_parent) && (p_instance->visibility_index == -1 || p_instance->visibility_dependencies_depth == 0)) {
+ idata.flags |= InstanceData::FLAG_VISIBILITY_DEPENDENCY_NEEDS_CHECK;
} else {
- p_instance->scenario->instance_data[p_instance->array_index].flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_NEEDS_CHECK;
+ idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_NEEDS_CHECK;
}
if (p_instance->visibility_parent) {
- p_instance->scenario->instance_data[p_instance->array_index].parent_array_index = p_instance->visibility_parent->array_index;
+ idata.parent_array_index = p_instance->visibility_parent->array_index;
} else {
- p_instance->scenario->instance_data[p_instance->array_index].parent_array_index = -1;
+ idata.parent_array_index = -1;
+ if (is_geometry_instance) {
+ scene_render->geometry_instance_set_parent_fade_alpha(idata.instance_geometry, 1.0f);
+ }
}
}
}
@@ -1471,6 +1538,9 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
heightfield_particle_colliders_update_list.insert(p_instance);
}
RSG::storage->particles_collision_instance_set_transform(collision->instance, p_instance->transform);
+ } else if (p_instance->base_type == RS::INSTANCE_FOG_VOLUME) {
+ InstanceFogVolumeData *volume = static_cast<InstanceFogVolumeData *>(p_instance->base_data);
+ scene_render->fog_volume_instance_set_transform(volume->instance, p_instance->transform);
} else if (p_instance->base_type == RS::INSTANCE_OCCLUDER) {
if (p_instance->scenario) {
RendererSceneOcclusionCull::get_singleton()->scenario_set_instance(p_instance->scenario->self, p_instance->self, p_instance->base, p_instance->transform, p_instance->visible);
@@ -1559,19 +1629,19 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
idata.parent_array_index = p_instance->visibility_parent ? p_instance->visibility_parent->array_index : -1;
idata.visibility_index = p_instance->visibility_index;
+ for (Set<Instance *>::Element *E = p_instance->visibility_dependencies.front(); E; E = E->next()) {
+ Instance *dep_instance = E->get();
+ if (dep_instance->array_index != -1) {
+ dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = p_instance->array_index;
+ }
+ }
+
switch (p_instance->base_type) {
case RS::INSTANCE_MESH:
case RS::INSTANCE_MULTIMESH:
case RS::INSTANCE_PARTICLES: {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
idata.instance_geometry = geom->geometry_instance;
-
- for (Set<Instance *>::Element *E = geom->visibility_dependencies.front(); E; E = E->next()) {
- Instance *dep_instance = E->get();
- if (dep_instance->array_index != -1) {
- dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = p_instance->array_index;
- }
- }
} break;
case RS::INSTANCE_LIGHT: {
InstanceLightData *light_data = static_cast<InstanceLightData *>(p_instance->base_data);
@@ -1592,6 +1662,9 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
case RS::INSTANCE_VOXEL_GI: {
idata.instance_data_rid = static_cast<InstanceVoxelGIData *>(p_instance->base_data)->probe_instance.get_id();
} break;
+ case RS::INSTANCE_FOG_VOLUME: {
+ idata.instance_data_rid = static_cast<InstanceFogVolumeData *>(p_instance->base_data)->instance.get_id();
+ } break;
case RS::INSTANCE_VISIBLITY_NOTIFIER: {
idata.visibility_notifier = static_cast<InstanceVisibilityNotifierData *>(p_instance->base_data);
} break;
@@ -1603,7 +1676,7 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
//always dirty when added
idata.flags |= InstanceData::FLAG_REFLECTION_PROBE_DIRTY;
}
- if (p_instance->cast_shadows != RS::SHADOW_CASTING_SETTING_SHADOWS_ONLY) {
+ if (p_instance->cast_shadows != RS::SHADOW_CASTING_SETTING_OFF) {
idata.flags |= InstanceData::FLAG_CAST_SHADOWS;
}
if (p_instance->cast_shadows == RS::SHADOW_CASTING_SETTING_SHADOWS_ONLY) {
@@ -1622,6 +1695,9 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
if (p_instance->ignore_occlusion_culling) {
idata.flags |= InstanceData::FLAG_IGNORE_OCCLUSION_CULLING;
}
+ if (p_instance->ignore_all_culling) {
+ idata.flags |= InstanceData::FLAG_IGNORE_ALL_CULLING;
+ }
p_instance->scenario->instance_data.push_back(idata);
p_instance->scenario->instance_aabbs.push_back(InstanceBounds(p_instance->transformed_aabb));
@@ -1721,13 +1797,10 @@ void RendererSceneCull::_unpair_instance(Instance *p_instance) {
swapped_instance->scenario->instance_visibility[swapped_instance->visibility_index].array_index = swapped_instance->array_index;
}
- if ((1 << swapped_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
- InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(swapped_instance->base_data);
- for (Set<Instance *>::Element *E = geom->visibility_dependencies.front(); E; E = E->next()) {
- Instance *dep_instance = E->get();
- if (dep_instance != p_instance && dep_instance->array_index != -1) {
- dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = swapped_instance->array_index;
- }
+ for (Set<Instance *>::Element *E = swapped_instance->visibility_dependencies.front(); E; E = E->next()) {
+ Instance *dep_instance = E->get();
+ if (dep_instance != p_instance && dep_instance->array_index != -1) {
+ dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = swapped_instance->array_index;
}
}
}
@@ -1746,11 +1819,14 @@ void RendererSceneCull::_unpair_instance(Instance *p_instance) {
scene_render->geometry_instance_pair_reflection_probe_instances(geom->geometry_instance, nullptr, 0);
scene_render->geometry_instance_pair_decal_instances(geom->geometry_instance, nullptr, 0);
scene_render->geometry_instance_pair_voxel_gi_instances(geom->geometry_instance, nullptr, 0);
+ }
- for (Set<Instance *>::Element *E = geom->visibility_dependencies.front(); E; E = E->next()) {
- Instance *dep_instance = E->get();
- if (dep_instance->array_index != -1) {
- dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = -1;
+ for (Set<Instance *>::Element *E = p_instance->visibility_dependencies.front(); E; E = E->next()) {
+ Instance *dep_instance = E->get();
+ if (dep_instance->array_index != -1) {
+ dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = -1;
+ if ((1 << dep_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
+ scene_render->geometry_instance_set_parent_fade_alpha(dep_instance->scenario->instance_data[dep_instance->array_index].instance_geometry, 1.0f);
}
}
}
@@ -1796,6 +1872,9 @@ void RendererSceneCull::_update_instance_aabb(Instance *p_instance) {
new_aabb = RSG::storage->particles_collision_get_aabb(p_instance->base);
} break;
+ case RenderingServer::INSTANCE_FOG_VOLUME: {
+ new_aabb = RSG::storage->fog_volume_get_aabb(p_instance->base);
+ } break;
case RenderingServer::INSTANCE_VISIBLITY_NOTIFIER: {
new_aabb = RSG::storage->visibility_notifier_get_aabb(p_instance->base);
} break;
@@ -2076,7 +2155,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
// This trick here is what stabilizes the shadow (make potential jaggies to not move)
// at the cost of some wasted resolution. Still, the quality increase is very well worth it.
- const real_t unit = radius * 2.0 / texture_size;
+ const real_t unit = (radius + soft_shadow_expand) * 2.0 / texture_size;
x_max_cam = Math::snapped(x_vec.dot(center) + radius + soft_shadow_expand, unit);
x_min_cam = Math::snapped(x_vec.dot(center) - radius - soft_shadow_expand, unit);
y_max_cam = Math::snapped(y_vec.dot(center) + radius + soft_shadow_expand, unit);
@@ -2128,7 +2207,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
}
}
-bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, const Transform3D p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario, float p_screen_lod_threshold) {
+bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, const Transform3D p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario, float p_screen_mesh_lod_threshold) {
InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data);
Transform3D light_transform = p_instance->transform;
@@ -2351,7 +2430,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
return animated_material_found;
}
-void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, float p_screen_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RenderInfo *r_render_info) {
+void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, float p_screen_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RenderInfo *r_render_info) {
#ifndef _3D_DISABLED
Camera *camera = camera_owner.get_or_null(p_camera);
@@ -2433,7 +2512,7 @@ void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_
// For now just cull on the first camera
RendererSceneOcclusionCull::get_singleton()->buffer_update(p_viewport, camera_data.main_transform, camera_data.main_projection, camera_data.is_ortogonal, RendererThreadPool::singleton->thread_work_pool);
- _render_scene(&camera_data, p_render_buffers, environment, camera->effects, camera->visible_layers, p_scenario, p_viewport, p_shadow_atlas, RID(), -1, p_screen_lod_threshold, true, r_render_info);
+ _render_scene(&camera_data, p_render_buffers, environment, camera->effects, camera->visible_layers, p_scenario, p_viewport, p_shadow_atlas, RID(), -1, p_screen_mesh_lod_threshold, true, r_render_info);
#endif
}
@@ -2453,34 +2532,49 @@ void RendererSceneCull::_visibility_cull(const VisibilityCullData &cull_data, ui
if (idata.parent_array_index >= 0) {
uint32_t parent_flags = scenario->instance_data[idata.parent_array_index].flags;
- if ((parent_flags & InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN) || (parent_flags & InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE) == 0) {
+
+ if ((parent_flags & InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN) || !(parent_flags & (InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE | InstanceData::FLAG_VISIBILITY_DEPENDENCY_FADE_CHILDREN))) {
idata.flags |= InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN;
idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE;
+ idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_FADE_CHILDREN;
continue;
}
}
- int range_check = _visibility_range_check(vd, cull_data.camera_position, cull_data.viewport_mask);
+ int range_check = _visibility_range_check<true>(vd, cull_data.camera_position, cull_data.viewport_mask);
if (range_check == -1) {
idata.flags |= InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN;
idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE;
+ idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_FADE_CHILDREN;
} else if (range_check == 1) {
idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN;
idata.flags |= InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE;
+ idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_FADE_CHILDREN;
} else {
idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN;
idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE;
+ if (range_check == 2) {
+ idata.flags |= InstanceData::FLAG_VISIBILITY_DEPENDENCY_FADE_CHILDREN;
+ } else {
+ idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_FADE_CHILDREN;
+ }
}
}
}
+template <bool p_fade_check>
int RendererSceneCull::_visibility_range_check(InstanceVisibilityData &r_vis_data, const Vector3 &p_camera_pos, uint64_t p_viewport_mask) {
float dist = p_camera_pos.distance_to(r_vis_data.position);
+ const RS::VisibilityRangeFadeMode &fade_mode = r_vis_data.fade_mode;
+
+ float begin_offset = -r_vis_data.range_begin_margin;
+ float end_offset = r_vis_data.range_end_margin;
- bool in_range_last_frame = p_viewport_mask & r_vis_data.viewport_state;
- float begin_offset = in_range_last_frame ? -r_vis_data.range_begin_margin : r_vis_data.range_begin_margin;
- float end_offset = in_range_last_frame ? r_vis_data.range_end_margin : -r_vis_data.range_end_margin;
+ if (fade_mode == RS::VISIBILITY_RANGE_FADE_DISABLED && !(p_viewport_mask & r_vis_data.viewport_state)) {
+ begin_offset = -begin_offset;
+ end_offset = -end_offset;
+ }
if (r_vis_data.range_end > 0.0f && dist > r_vis_data.range_end + end_offset) {
r_vis_data.viewport_state &= ~p_viewport_mask;
@@ -2490,10 +2584,34 @@ int RendererSceneCull::_visibility_range_check(InstanceVisibilityData &r_vis_dat
return 1;
} else {
r_vis_data.viewport_state |= p_viewport_mask;
+ if (p_fade_check) {
+ if (fade_mode != RS::VISIBILITY_RANGE_FADE_DISABLED) {
+ r_vis_data.children_fade_alpha = 1.0f;
+ if (r_vis_data.range_end > 0.0f && dist > r_vis_data.range_end - end_offset) {
+ if (fade_mode == RS::VISIBILITY_RANGE_FADE_DEPENDENCIES) {
+ r_vis_data.children_fade_alpha = MIN(1.0f, (dist - (r_vis_data.range_end - end_offset)) / (2.0f * r_vis_data.range_end_margin));
+ }
+ return 2;
+ } else if (r_vis_data.range_begin > 0.0f && dist < r_vis_data.range_begin - begin_offset) {
+ if (fade_mode == RS::VISIBILITY_RANGE_FADE_DEPENDENCIES) {
+ r_vis_data.children_fade_alpha = MIN(1.0f, 1.0 - (dist - (r_vis_data.range_begin + begin_offset)) / (2.0f * r_vis_data.range_begin_margin));
+ }
+ return 2;
+ }
+ }
+ }
return 0;
}
}
+bool RendererSceneCull::_visibility_parent_check(const CullData &p_cull_data, const InstanceData &p_instance_data) {
+ if (p_instance_data.parent_array_index == -1) {
+ return true;
+ }
+ const uint32_t &parent_flags = p_cull_data.scenario->instance_data[p_instance_data.parent_array_index].flags;
+ return ((parent_flags & InstanceData::FLAG_VISIBILITY_DEPENDENCY_NEEDS_CHECK) == InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE) || (parent_flags & InstanceData::FLAG_VISIBILITY_DEPENDENCY_FADE_CHILDREN);
+}
+
void RendererSceneCull::_scene_cull_threaded(uint32_t p_thread, CullData *cull_data) {
uint32_t cull_total = cull_data->scenario->instance_data.size();
uint32_t total_threads = RendererThreadPool::singleton->thread_work_pool.get_thread_count();
@@ -2519,19 +2637,19 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
bool mesh_visible = false;
InstanceData &idata = cull_data.scenario->instance_data[i];
- uint32_t visibility_flags = idata.flags & (InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE | InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN);
+ uint32_t visibility_flags = idata.flags & (InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE | InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN | InstanceData::FLAG_VISIBILITY_DEPENDENCY_FADE_CHILDREN);
int32_t visibility_check = -1;
#define HIDDEN_BY_VISIBILITY_CHECKS (visibility_flags == InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE || visibility_flags == InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN)
#define LAYER_CHECK (cull_data.visible_layers & idata.layer_mask)
#define IN_FRUSTUM(f) (cull_data.scenario->instance_aabbs[i].in_frustum(f))
-#define VIS_RANGE_CHECK ((idata.visibility_index == -1) || _visibility_range_check(cull_data.scenario->instance_visibility[idata.visibility_index], cull_data.cam_transform.origin, cull_data.visibility_viewport_mask) == 0)
-#define VIS_PARENT_CHECK ((idata.parent_array_index == -1) || ((cull_data.scenario->instance_data[idata.parent_array_index].flags & InstanceData::FLAG_VISIBILITY_DEPENDENCY_NEEDS_CHECK) == InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE))
+#define VIS_RANGE_CHECK ((idata.visibility_index == -1) || _visibility_range_check<false>(cull_data.scenario->instance_visibility[idata.visibility_index], cull_data.cam_transform.origin, cull_data.visibility_viewport_mask) == 0)
+#define VIS_PARENT_CHECK (_visibility_parent_check(cull_data, idata))
#define VIS_CHECK (visibility_check < 0 ? (visibility_check = (visibility_flags != InstanceData::FLAG_VISIBILITY_DEPENDENCY_NEEDS_CHECK || (VIS_RANGE_CHECK && VIS_PARENT_CHECK))) : visibility_check)
#define OCCLUSION_CULLED (cull_data.occlusion_buffer != nullptr && (cull_data.scenario->instance_data[i].flags & InstanceData::FLAG_IGNORE_OCCLUSION_CULLING) == 0 && cull_data.occlusion_buffer->is_occluded(cull_data.scenario->instance_aabbs[i].bounds, cull_data.cam_transform.origin, inv_cam_transform, *cull_data.camera_matrix, z_near))
if (!HIDDEN_BY_VISIBILITY_CHECKS) {
- if (LAYER_CHECK && IN_FRUSTUM(cull_data.cull->frustum) && VIS_CHECK && !OCCLUSION_CULLED) {
+ if ((LAYER_CHECK && IN_FRUSTUM(cull_data.cull->frustum) && VIS_CHECK && !OCCLUSION_CULLED) || (cull_data.scenario->instance_data[i].flags & InstanceData::FLAG_IGNORE_ALL_CULLING)) {
uint32_t base_type = idata.flags & InstanceData::FLAG_BASE_TYPE_MASK;
if (base_type == RS::INSTANCE_LIGHT) {
cull_result.lights.push_back(idata.instance);
@@ -2574,6 +2692,8 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
} else if (base_type == RS::INSTANCE_LIGHTMAP) {
cull_result.lightmaps.push_back(RID::from_uint64(idata.instance_data_rid));
+ } else if (base_type == RS::INSTANCE_FOG_VOLUME) {
+ cull_result.fog_volumes.push_back(RID::from_uint64(idata.instance_data_rid));
} else if (base_type == RS::INSTANCE_VISIBLITY_NOTIFIER) {
InstanceVisibilityNotifierData *vnd = idata.visibility_notifier;
if (!vnd->list_element.in_list()) {
@@ -2607,6 +2727,16 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
}
}
+ if (idata.parent_array_index != -1) {
+ float fade = 1.0f;
+ const uint32_t &parent_flags = cull_data.scenario->instance_data[idata.parent_array_index].flags;
+ if (parent_flags & InstanceData::FLAG_VISIBILITY_DEPENDENCY_FADE_CHILDREN) {
+ const int32_t &parent_idx = cull_data.scenario->instance_data[idata.parent_array_index].visibility_index;
+ fade = cull_data.scenario->instance_visibility[parent_idx].children_fade_alpha;
+ }
+ scene_render->geometry_instance_set_parent_fade_alpha(idata.instance_geometry, fade);
+ }
+
if (geometry_instance_pair_mask & (1 << RS::INSTANCE_LIGHT) && (idata.flags & InstanceData::FLAG_GEOM_LIGHTING_DIRTY)) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
uint32_t idx = 0;
@@ -2746,7 +2876,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
}
}
-void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_camera_data, RID p_render_buffers, RID p_environment, RID p_force_camera_effects, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, bool p_using_shadows, RendererScene::RenderInfo *r_render_info) {
+void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_camera_data, RID p_render_buffers, RID p_environment, RID p_force_camera_effects, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, bool p_using_shadows, RendererScene::RenderInfo *r_render_info) {
Instance *render_reflection_probe = instance_owner.get_or_null(p_reflection_probe); //if null, not rendering to it
Scenario *scenario = scenario_owner.get_or_null(p_scenario);
@@ -2952,7 +3082,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
Transform3D cam_xf = p_camera_data->main_transform;
float zn = p_camera_data->main_projection.get_z_near();
- Plane p(cam_xf.origin + cam_xf.basis.get_axis(2) * -zn, -cam_xf.basis.get_axis(2)); //camera near plane
+ Plane p(-cam_xf.basis.get_axis(2), cam_xf.origin + cam_xf.basis.get_axis(2) * -zn); //camera near plane
// near plane half width and height
Vector2 vp_half_extents = p_camera_data->main_projection.get_viewport_half_extents();
@@ -3026,7 +3156,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
if (redraw && max_shadows_used < MAX_UPDATE_SHADOWS) {
//must redraw!
RENDER_TIMESTAMP(">Rendering Light " + itos(i));
- light->shadow_dirty = _light_instance_update_shadow(ins, p_camera_data->main_transform, p_camera_data->main_projection, p_camera_data->is_ortogonal, p_camera_data->vaspect, p_shadow_atlas, scenario, p_screen_lod_threshold);
+ light->shadow_dirty = _light_instance_update_shadow(ins, p_camera_data->main_transform, p_camera_data->main_projection, p_camera_data->is_ortogonal, p_camera_data->vaspect, p_shadow_atlas, scenario, p_screen_mesh_lod_threshold);
RENDER_TIMESTAMP("<Rendering Light " + itos(i));
} else {
light->shadow_dirty = redraw;
@@ -3088,7 +3218,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
}
RENDER_TIMESTAMP("Render Scene ");
- scene_render->render_scene(p_render_buffers, p_camera_data, scene_cull_result.geometry_instances, scene_cull_result.light_instances, scene_cull_result.reflections, scene_cull_result.voxel_gi_instances, scene_cull_result.decals, scene_cull_result.lightmaps, p_environment, camera_effects, p_shadow_atlas, occluders_tex, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass, p_screen_lod_threshold, render_shadow_data, max_shadows_used, render_sdfgi_data, cull.sdfgi.region_count, &sdfgi_update_data, r_render_info);
+ scene_render->render_scene(p_render_buffers, p_camera_data, scene_cull_result.geometry_instances, scene_cull_result.light_instances, scene_cull_result.reflections, scene_cull_result.voxel_gi_instances, scene_cull_result.decals, scene_cull_result.lightmaps, scene_cull_result.fog_volumes, p_environment, camera_effects, p_shadow_atlas, occluders_tex, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass, p_screen_mesh_lod_threshold, render_shadow_data, max_shadows_used, render_sdfgi_data, cull.sdfgi.region_count, &sdfgi_update_data, r_render_info);
for (uint32_t i = 0; i < max_shadows_used; i++) {
render_shadow_data[i].instances.clear();
@@ -3099,7 +3229,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
render_sdfgi_data[i].instances.clear();
}
- // virtual void render_scene(RID p_render_buffers, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold,const RenderShadowData *p_render_shadows,int p_render_shadow_count,const RenderSDFGIData *p_render_sdfgi_regions,int p_render_sdfgi_region_count,const RenderSDFGIStaticLightData *p_render_sdfgi_static_lights=nullptr) = 0;
+ // virtual void render_scene(RID p_render_buffers, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold,const RenderShadowData *p_render_shadows,int p_render_shadow_count,const RenderSDFGIData *p_render_sdfgi_regions,int p_render_sdfgi_region_count,const RenderSDFGIStaticLightData *p_render_sdfgi_static_lights=nullptr) = 0;
}
RID RendererSceneCull::_render_get_environment(RID p_camera, RID p_scenario) {
@@ -3138,7 +3268,7 @@ void RendererSceneCull::render_empty_scene(RID p_render_buffers, RID p_scenario,
RendererSceneRender::CameraData camera_data;
camera_data.set_camera(Transform3D(), CameraMatrix(), true, false);
- scene_render->render_scene(p_render_buffers, &camera_data, PagedArray<RendererSceneRender::GeometryInstance *>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), RID(), RID(), p_shadow_atlas, RID(), scenario->reflection_atlas, RID(), 0, 0, nullptr, 0, nullptr, 0, nullptr);
+ scene_render->render_scene(p_render_buffers, &camera_data, PagedArray<RendererSceneRender::GeometryInstance *>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), RID(), RID(), p_shadow_atlas, RID(), scenario->reflection_atlas, RID(), 0, 0, nullptr, 0, nullptr, 0, nullptr);
#endif
}
@@ -3177,7 +3307,7 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int
Vector3 origin_offset = RSG::storage->reflection_probe_get_origin_offset(p_instance->base);
float max_distance = RSG::storage->reflection_probe_get_origin_max_distance(p_instance->base);
float size = scene_render->reflection_atlas_get_size(scenario->reflection_atlas);
- float lod_threshold = RSG::storage->reflection_probe_get_lod_threshold(p_instance->base) / size;
+ float mesh_lod_threshold = RSG::storage->reflection_probe_get_mesh_lod_threshold(p_instance->base) / size;
Vector3 edge = view_normals[p_step] * extents;
float distance = ABS(view_normals[p_step].dot(edge) - view_normals[p_step].dot(origin_offset)); //distance from origin offset to actual view distance limit
@@ -3211,7 +3341,7 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int
RendererSceneRender::CameraData camera_data;
camera_data.set_camera(xform, cm, false, false);
- _render_scene(&camera_data, RID(), environment, RID(), RSG::storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, RID(), shadow_atlas, reflection_probe->instance, p_step, lod_threshold, use_shadows);
+ _render_scene(&camera_data, RID(), environment, RID(), RSG::storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, RID(), shadow_atlas, reflection_probe->instance, p_step, mesh_lod_threshold, use_shadows);
} else {
//do roughness postprocess step until it believes it's done
@@ -3540,6 +3670,10 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
RSG::storage->material_update_dependency(p_instance->material_override, &p_instance->dependency_tracker);
}
+ if (p_instance->material_overlay.is_valid()) {
+ RSG::storage->material_update_dependency(p_instance->material_overlay, &p_instance->dependency_tracker);
+ }
+
if (p_instance->base_type == RS::INSTANCE_MESH) {
//remove materials no longer used and un-own them
@@ -3669,6 +3803,12 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
}
}
+ if (p_instance->material_overlay.is_valid()) {
+ can_cast_shadows = can_cast_shadows || RSG::storage->material_casts_shadows(p_instance->material_overlay);
+ is_animated = is_animated || RSG::storage->material_is_animated(p_instance->material_overlay);
+ _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, p_instance->material_overlay);
+ }
+
if (can_cast_shadows != geom->can_cast_shadows) {
//ability to cast shadows change, let lights now
for (Set<Instance *>::Element *E = geom->lights.front(); E; E = E->next()) {
@@ -3742,6 +3882,10 @@ void RendererSceneCull::update() {
}
bool RendererSceneCull::free(RID p_rid) {
+ if (p_rid.is_null()) {
+ return true;
+ }
+
if (scene_render->free(p_rid)) {
return true;
}
@@ -3777,6 +3921,7 @@ bool RendererSceneCull::free(RID p_rid) {
instance_set_scenario(p_rid, RID());
instance_set_base(p_rid, RID());
instance_geometry_set_material_override(p_rid, RID());
+ instance_geometry_set_material_overlay(p_rid, RID());
instance_attach_skeleton(p_rid, RID());
if (instance->instance_allocated_shader_parameters) {
diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h
index 905d0eb558..1e770ef66c 100644
--- a/servers/rendering/renderer_scene_cull.h
+++ b/servers/rendering/renderer_scene_cull.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -267,7 +267,9 @@ public:
FLAG_VISIBILITY_DEPENDENCY_NEEDS_CHECK = (3 << 20), // 2 bits, overlaps with the other vis. dependency flags
FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE = (1 << 20),
FLAG_VISIBILITY_DEPENDENCY_HIDDEN = (1 << 21),
- FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY = (1 << 22),
+ FLAG_VISIBILITY_DEPENDENCY_FADE_CHILDREN = (1 << 22),
+ FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY = (1 << 23),
+ FLAG_IGNORE_ALL_CULLING = (1 << 24),
};
uint32_t flags = 0;
@@ -286,12 +288,14 @@ public:
struct InstanceVisibilityData {
uint64_t viewport_state = 0;
int32_t array_index = -1;
+ RS::VisibilityRangeFadeMode fade_mode = RS::VISIBILITY_RANGE_FADE_DISABLED;
Vector3 position;
Instance *instance = nullptr;
float range_begin = 0.0f;
float range_end = 0.0f;
float range_begin_margin = 0.0f;
float range_end_margin = 0.0f;
+ float children_fade_alpha = 1.0f;
};
class VisibilityArray : public BinSortedArray<InstanceVisibilityData> {
@@ -386,6 +390,7 @@ public:
RID skeleton;
RID material_override;
+ RID material_overlay;
RID mesh_instance; //only used for meshes and when skeleton/blendshapes exist
@@ -394,6 +399,7 @@ public:
float lod_bias;
bool ignore_occlusion_culling;
+ bool ignore_all_culling;
Vector<RID> materials;
@@ -434,14 +440,18 @@ public:
RID self;
//scenario stuff
DynamicBVH::ID indexer_id;
- int32_t array_index;
+ int32_t array_index = -1;
int32_t visibility_index = -1;
- float visibility_range_begin;
- float visibility_range_end;
- float visibility_range_begin_margin;
- float visibility_range_end_margin;
+ float visibility_range_begin = 0.0f;
+ float visibility_range_end = 0.0f;
+ float visibility_range_begin_margin = 0.0f;
+ float visibility_range_end_margin = 0.0f;
+ RS::VisibilityRangeFadeMode visibility_range_fade_mode = RS::VISIBILITY_RANGE_FADE_DISABLED;
Instance *visibility_parent = nullptr;
- Scenario *scenario;
+ Set<Instance *> visibility_dependencies;
+ uint32_t visibility_dependencies_depth = 0;
+ float transparency = 0.0f;
+ Scenario *scenario = nullptr;
SelfList<Instance> scenario_item;
//aabb stuff
@@ -529,6 +539,7 @@ public:
lightmap_cull_index = 0;
lod_bias = 1.0;
ignore_occlusion_culling = false;
+ ignore_all_culling = false;
scenario = nullptr;
@@ -583,8 +594,6 @@ public:
Set<Instance *> reflection_probes;
Set<Instance *> voxel_gi_instances;
Set<Instance *> lightmap_captures;
- Set<Instance *> visibility_dependencies;
- uint32_t visibility_dependencies_depth = 0;
InstanceGeometryData() {
can_cast_shadows = true;
@@ -624,6 +633,11 @@ public:
RID instance;
};
+ struct InstanceFogVolumeData : public InstanceBaseData {
+ RID instance;
+ bool is_global;
+ };
+
struct InstanceVisibilityNotifierData : public InstanceBaseData {
bool just_visible = false;
uint64_t visible_in_frame = 0;
@@ -788,6 +802,7 @@ public:
PagedArray<RID> decals;
PagedArray<RID> voxel_gi_instances;
PagedArray<RID> mesh_instances;
+ PagedArray<RID> fog_volumes;
struct DirectionalShadow {
PagedArray<RendererSceneRender::GeometryInstance *> cascade_geometry_instances[RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES];
@@ -805,6 +820,7 @@ public:
decals.clear();
voxel_gi_instances.clear();
mesh_instances.clear();
+ fog_volumes.clear();
for (int i = 0; i < RendererSceneRender::MAX_DIRECTIONAL_LIGHTS; i++) {
for (int j = 0; j < RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES; j++) {
directional_shadows[i].cascade_geometry_instances[j].clear();
@@ -829,6 +845,7 @@ public:
decals.reset();
voxel_gi_instances.reset();
mesh_instances.reset();
+ fog_volumes.reset();
for (int i = 0; i < RendererSceneRender::MAX_DIRECTIONAL_LIGHTS; i++) {
for (int j = 0; j < RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES; j++) {
directional_shadows[i].cascade_geometry_instances[j].reset();
@@ -853,6 +870,7 @@ public:
decals.merge_unordered(p_cull_result.decals);
voxel_gi_instances.merge_unordered(p_cull_result.voxel_gi_instances);
mesh_instances.merge_unordered(p_cull_result.mesh_instances);
+ fog_volumes.merge_unordered(p_cull_result.fog_volumes);
for (int i = 0; i < RendererSceneRender::MAX_DIRECTIONAL_LIGHTS; i++) {
for (int j = 0; j < RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES; j++) {
@@ -878,6 +896,7 @@ public:
decals.set_page_pool(p_rid_pool);
voxel_gi_instances.set_page_pool(p_rid_pool);
mesh_instances.set_page_pool(p_rid_pool);
+ fog_volumes.set_page_pool(p_rid_pool);
for (int i = 0; i < RendererSceneRender::MAX_DIRECTIONAL_LIGHTS; i++) {
for (int j = 0; j < RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES; j++) {
directional_shadows[i].cascade_geometry_instances[j].set_page_pool(p_geometry_instance_pool);
@@ -920,6 +939,7 @@ public:
virtual void instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight);
virtual void instance_set_surface_override_material(RID p_instance, int p_surface, RID p_material);
virtual void instance_set_visible(RID p_instance, bool p_visible);
+ virtual void instance_geometry_set_transparency(RID p_instance, float p_transparency);
virtual void instance_set_custom_aabb(RID p_instance, AABB p_aabb);
@@ -929,7 +949,9 @@ public:
virtual void instance_set_visibility_parent(RID p_instance, RID p_parent_instance);
- void _update_instance_visibility_depth(Instance *p_instance);
+ virtual void instance_set_ignore_culling(RID p_instance, bool p_enabled);
+
+ bool _update_instance_visibility_depth(Instance *p_instance);
void _update_instance_visibility_dependencies(Instance *p_instance);
// don't use these in a game!
@@ -940,8 +962,9 @@ public:
virtual void instance_geometry_set_flag(RID p_instance, RS::InstanceFlags p_flags, bool p_enabled);
virtual void instance_geometry_set_cast_shadows_setting(RID p_instance, RS::ShadowCastingSetting p_shadow_casting_setting);
virtual void instance_geometry_set_material_override(RID p_instance, RID p_material);
+ virtual void instance_geometry_set_material_overlay(RID p_instance, RID p_material);
- virtual void instance_geometry_set_visibility_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin);
+ virtual void instance_geometry_set_visibility_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin, RS::VisibilityRangeFadeMode p_fade_mode);
virtual void instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index);
virtual void instance_geometry_set_lod_bias(RID p_instance, float p_lod_bias);
@@ -961,7 +984,7 @@ public:
void _light_instance_setup_directional_shadow(int p_shadow_index, Instance *p_instance, const Transform3D p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect);
- _FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform3D p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario, float p_scren_lod_threshold);
+ _FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform3D p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario, float p_scren_mesh_lod_threshold);
RID _render_get_environment(RID p_camera, RID p_scenario);
@@ -1013,7 +1036,7 @@ public:
void _visibility_cull_threaded(uint32_t p_thread, VisibilityCullData *cull_data);
void _visibility_cull(const VisibilityCullData &cull_data, uint64_t p_from, uint64_t p_to);
- _FORCE_INLINE_ void _visibility_cull(const VisibilityCullData &cull_data, uint64_t p_idx);
+ template <bool p_fade_check>
_FORCE_INLINE_ int _visibility_range_check(InstanceVisibilityData &r_vis_data, const Vector3 &p_camera_pos, uint64_t p_viewport_mask);
struct CullData {
@@ -1030,12 +1053,13 @@ public:
void _scene_cull_threaded(uint32_t p_thread, CullData *cull_data);
void _scene_cull(CullData &cull_data, InstanceCullResult &cull_result, uint64_t p_from, uint64_t p_to);
+ _FORCE_INLINE_ bool _visibility_parent_check(const CullData &p_cull_data, const InstanceData &p_instance_data);
bool _render_reflection_probe_step(Instance *p_instance, int p_step);
- void _render_scene(const RendererSceneRender::CameraData *p_camera_data, RID p_render_buffers, RID p_environment, RID p_force_camera_effects, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, bool p_using_shadows = true, RenderInfo *r_render_info = nullptr);
+ void _render_scene(const RendererSceneRender::CameraData *p_camera_data, RID p_render_buffers, RID p_environment, RID p_force_camera_effects, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, bool p_using_shadows = true, RenderInfo *r_render_info = nullptr);
void render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas);
- void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, float p_screen_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RendererScene::RenderInfo *r_render_info = nullptr);
+ void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, float p_screen_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RendererScene::RenderInfo *r_render_info = nullptr);
void update_dirty_instances();
void render_particle_colliders();
@@ -1086,6 +1110,9 @@ public:
PASS10(environment_set_ssao, RID, bool, float, float, float, float, float, float, float, float)
PASS6(environment_set_ssao_quality, RS::EnvironmentSSAOQuality, bool, float, int, float, float)
+ PASS6(environment_set_ssil, RID, bool, float, float, float, float)
+ PASS6(environment_set_ssil_quality, RS::EnvironmentSSILQuality, bool, float, int, float, float)
+
PASS11(environment_set_glow, RID, bool, Vector<float>, float, float, float, float, RS::EnvironmentGlowBlendMode, float, float, float)
PASS1(environment_glow_set_use_bicubic_upscale, bool)
PASS1(environment_glow_set_use_high_quality, bool)
@@ -1095,12 +1122,12 @@ public:
PASS7(environment_set_adjustment, RID, bool, float, float, float, bool, RID)
PASS9(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float)
- PASS10(environment_set_volumetric_fog, RID, bool, float, const Color &, float, float, float, float, bool, float)
+ PASS13(environment_set_volumetric_fog, RID, bool, float, const Color &, const Color &, float, float, float, float, float, bool, float, float)
PASS2(environment_set_volumetric_fog_volume_size, int, int)
PASS1(environment_set_volumetric_fog_filter_active, bool)
- PASS11(environment_set_sdfgi, RID, bool, RS::EnvironmentSDFGICascades, float, RS::EnvironmentSDFGIYScale, bool, float, bool, float, float, float)
+ PASS11(environment_set_sdfgi, RID, bool, int, float, RS::EnvironmentSDFGIYScale, bool, float, bool, float, float, float)
PASS1(environment_set_sdfgi_ray_count, RS::EnvironmentSDFGIRayCount)
PASS1(environment_set_sdfgi_frames_to_converge, RS::EnvironmentSDFGIFramesToConverge)
PASS1(environment_set_sdfgi_frames_to_update_light, RS::EnvironmentSDFGIFramesToUpdateLight)
@@ -1133,7 +1160,7 @@ public:
/* Render Buffers */
PASS0R(RID, render_buffers_create)
- PASS8(render_buffers_configure, RID, RID, int, int, RS::ViewportMSAA, RS::ViewportScreenSpaceAA, bool, uint32_t)
+ PASS12(render_buffers_configure, RID, RID, int, int, int, int, float, float, RS::ViewportMSAA, RS::ViewportScreenSpaceAA, bool, uint32_t)
PASS1(gi_set_use_half_resolution, bool)
/* Shadow Atlas */
diff --git a/servers/rendering/renderer_scene_occlusion_cull.cpp b/servers/rendering/renderer_scene_occlusion_cull.cpp
index 1b8aea36d7..bda0950097 100644
--- a/servers/rendering/renderer_scene_occlusion_cull.cpp
+++ b/servers/rendering/renderer_scene_occlusion_cull.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/rendering/renderer_scene_occlusion_cull.h b/servers/rendering/renderer_scene_occlusion_cull.h
index 4e4b1b94db..48412dab68 100644
--- a/servers/rendering/renderer_scene_occlusion_cull.h
+++ b/servers/rendering/renderer_scene_occlusion_cull.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/rendering/renderer_scene_render.cpp b/servers/rendering/renderer_scene_render.cpp
index 3a230ac89d..c802f72fdf 100644
--- a/servers/rendering/renderer_scene_render.cpp
+++ b/servers/rendering/renderer_scene_render.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -68,7 +68,7 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count
main_transform.basis.set(x, y, z);
// 3. create a horizon plane with one of the eyes and the up vector as normal.
- Plane horizon(p_transforms[0].origin, y);
+ Plane horizon(y, p_transforms[0].origin);
// 4. Intersect horizon, left and right to obtain the combined camera origin.
ERR_FAIL_COND_MSG(
@@ -79,7 +79,7 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count
// 5. figure out far plane, this could use some improvement, we may have our far plane too close like this, not sure if this matters
Vector3 far_center = (planes[0][CameraMatrix::PLANE_FAR].center() + planes[1][CameraMatrix::PLANE_FAR].center()) * 0.5;
- Plane far(far_center, -z);
+ Plane far(-z, far_center);
/////////////////////////////////////////////////////////////////////////////
// Figure out our top/bottom planes
@@ -137,9 +137,9 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count
Plane near;
Vector3 neg_z = -z;
if (neg_z.dot(p_transforms[1].origin) < neg_z.dot(p_transforms[0].origin)) {
- near = Plane(p_transforms[0].origin, neg_z);
+ near = Plane(neg_z, p_transforms[0].origin);
} else {
- near = Plane(p_transforms[1].origin, neg_z);
+ near = Plane(neg_z, p_transforms[1].origin);
}
// 13. Intersect near plane with bottm/left planes, to obtain min_vec then top/right to obtain max_vec
diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h
index 60ba355c03..c34a46d166 100644
--- a/servers/rendering/renderer_scene_render.h
+++ b/servers/rendering/renderer_scene_render.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -51,11 +51,15 @@ public:
virtual GeometryInstance *geometry_instance_create(RID p_base) = 0;
virtual void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) = 0;
virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) = 0;
+ virtual void geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_override) = 0;
virtual void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_material) = 0;
virtual void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) = 0;
virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) = 0;
virtual void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) = 0;
virtual void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) = 0;
+ virtual void geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) = 0;
+ virtual void geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) = 0;
+ virtual void geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) = 0;
virtual void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) = 0;
virtual void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) = 0;
virtual void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) = 0;
@@ -123,7 +127,7 @@ public:
virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) = 0;
virtual void environment_glow_set_use_high_quality(bool p_enable) = 0;
- virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount) = 0;
+ virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) = 0;
virtual void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) = 0;
virtual void environment_set_volumetric_fog_filter_active(bool p_enable) = 0;
@@ -131,10 +135,12 @@ public:
virtual void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) = 0;
virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) = 0;
-
virtual void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) = 0;
- virtual void environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) = 0;
+ virtual void environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) = 0;
+ virtual void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) = 0;
+
+ virtual void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) = 0;
virtual void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) = 0;
virtual void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) = 0;
@@ -173,6 +179,12 @@ public:
return true;
}
+ virtual RID fog_volume_instance_create(RID p_fog_volume) = 0;
+ virtual void fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) = 0;
+ virtual void fog_volume_instance_set_active(RID p_fog_volume_instance, bool p_active) = 0;
+ virtual RID fog_volume_instance_get_volume(RID p_fog_volume_instance) const = 0;
+ virtual Vector3 fog_volume_instance_get_position(RID p_fog_volume_instance) const = 0;
+
virtual RID reflection_atlas_create() = 0;
virtual void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) = 0;
virtual int reflection_atlas_get_size(RID p_ref_atlas) const = 0;
@@ -237,7 +249,7 @@ public:
void set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const CameraMatrix *p_projections, bool p_is_ortogonal, bool p_vaspect);
};
- virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) = 0;
+ virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) = 0;
virtual void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
virtual void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) = 0;
@@ -247,7 +259,7 @@ public:
virtual void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) = 0;
virtual RID render_buffers_create() = 0;
- virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) = 0;
+ virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) = 0;
virtual void gi_set_use_half_resolution(bool p_enable) = 0;
virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_limit) = 0;
diff --git a/servers/rendering/renderer_storage.cpp b/servers/rendering/renderer_storage.cpp
index aa005fac0a..56409ae187 100644
--- a/servers/rendering/renderer_storage.cpp
+++ b/servers/rendering/renderer_storage.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/rendering/renderer_storage.h b/servers/rendering/renderer_storage.h
index 2304394501..43a7778d67 100644
--- a/servers/rendering/renderer_storage.h
+++ b/servers/rendering/renderer_storage.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -183,8 +183,8 @@ public:
virtual String shader_get_code(RID p_shader) const = 0;
virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const = 0;
- virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) = 0;
- virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const = 0;
+ virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) = 0;
+ virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const = 0;
virtual Variant shader_get_param_default(RID p_material, const StringName &p_param) const = 0;
virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const = 0;
@@ -366,7 +366,7 @@ public:
virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) = 0;
virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) = 0;
virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) = 0;
- virtual void reflection_probe_set_lod_threshold(RID p_probe, float p_ratio) = 0;
+ virtual void reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) = 0;
virtual AABB reflection_probe_get_aabb(RID p_probe) const = 0;
virtual RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const = 0;
@@ -375,7 +375,7 @@ public:
virtual Vector3 reflection_probe_get_origin_offset(RID p_probe) const = 0;
virtual float reflection_probe_get_origin_max_distance(RID p_probe) const = 0;
virtual bool reflection_probe_renders_shadows(RID p_probe) const = 0;
- virtual float reflection_probe_get_lod_threshold(RID p_probe) const = 0;
+ virtual float reflection_probe_get_mesh_lod_threshold(RID p_probe) const = 0;
virtual void base_update_dependency(RID p_base, DependencyTracker *p_instance) = 0;
virtual void skeleton_update_dependency(RID p_base, DependencyTracker *p_instance) = 0;
@@ -535,6 +535,19 @@ public:
virtual bool particles_collision_is_heightfield(RID p_particles_collision) const = 0;
virtual RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const = 0;
+ /* FOG VOLUMES */
+
+ virtual RID fog_volume_allocate() = 0;
+ virtual void fog_volume_initialize(RID p_rid) = 0;
+
+ virtual void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) = 0;
+ virtual void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) = 0;
+ virtual void fog_volume_set_material(RID p_fog_volume, RID p_material) = 0;
+ virtual AABB fog_volume_get_aabb(RID p_fog_volume) const = 0;
+ virtual RS::FogVolumeShape fog_volume_get_shape(RID p_fog_volume) const = 0;
+
+ /* VISIBILITY NOTIFIER */
+
virtual RID visibility_notifier_allocate() = 0;
virtual void visibility_notifier_initialize(RID p_notifier) = 0;
virtual void visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) = 0;
@@ -607,6 +620,7 @@ public:
virtual uint64_t get_rendering_info(RS::RenderingInfo p_info) = 0;
virtual String get_video_adapter_name() const = 0;
virtual String get_video_adapter_vendor() const = 0;
+ virtual RenderingDevice::DeviceType get_video_adapter_type() const = 0;
static RendererStorage *base_singleton;
diff --git a/servers/rendering/renderer_thread_pool.cpp b/servers/rendering/renderer_thread_pool.cpp
index 98050dd508..ddf1d1bd00 100644
--- a/servers/rendering/renderer_thread_pool.cpp
+++ b/servers/rendering/renderer_thread_pool.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/rendering/renderer_thread_pool.h b/servers/rendering/renderer_thread_pool.h
index ae25415a0d..4626490d32 100644
--- a/servers/rendering/renderer_thread_pool.h
+++ b/servers/rendering/renderer_thread_pool.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp
index b67b1cd806..17a665922f 100644
--- a/servers/rendering/renderer_viewport.cpp
+++ b/servers/rendering/renderer_viewport.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -77,18 +77,69 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
RSG::scene->free(p_viewport->render_buffers);
p_viewport->render_buffers = RID();
} else {
- float scale_3d = p_viewport->scale_3d;
- if (Engine::get_singleton()->is_editor_hint()) {
- // Ignore the 3D viewport render scaling inside of the editor.
- // The Half Resolution 3D editor viewport option should be used instead.
- scale_3d = 1.0;
+ float scaling_3d_scale = p_viewport->scaling_3d_scale;
+
+ RS::ViewportScaling3DMode scaling_3d_mode = p_viewport->scaling_3d_mode;
+ bool scaling_enabled = true;
+
+ if ((scaling_3d_mode == RS::VIEWPORT_SCALING_3D_MODE_FSR) && (scaling_3d_scale > 1.0)) {
+ // FSR is not design for downsampling.
+ // Throw a warning and fallback to VIEWPORT_SCALING_3D_MODE_BILINEAR
+ WARN_PRINT_ONCE("FSR 3D resolution scaling does not support supersampling. Falling back to bilinear scaling.");
+ scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_BILINEAR;
+ }
+
+ if ((scaling_3d_mode == RS::VIEWPORT_SCALING_3D_MODE_FSR) && !p_viewport->fsr_enabled) {
+ // FSR is not actually available.
+ // Throw a warning and fallback to disable scaling
+ WARN_PRINT_ONCE("FSR 3D resolution scaling is not available. Disabling 3D resolution scaling.");
+ scaling_enabled = false;
+ }
+
+ if (scaling_3d_scale == 1.0) {
+ scaling_enabled = false;
+ }
+
+ int width;
+ int height;
+ int render_width;
+ int render_height;
+
+ if (scaling_enabled) {
+ switch (scaling_3d_mode) {
+ case RS::VIEWPORT_SCALING_3D_MODE_BILINEAR:
+ // Clamp 3D rendering resolution to reasonable values supported on most hardware.
+ // This prevents freezing the engine or outright crashing on lower-end GPUs.
+ width = CLAMP(p_viewport->size.width * scaling_3d_scale, 1, 16384);
+ height = CLAMP(p_viewport->size.height * scaling_3d_scale, 1, 16384);
+ render_width = width;
+ render_height = height;
+ break;
+ case RS::VIEWPORT_SCALING_3D_MODE_FSR:
+ width = p_viewport->size.width;
+ height = p_viewport->size.height;
+ render_width = MAX(width * scaling_3d_scale, 1.0); // width / (width * scaling)
+ render_height = MAX(height * scaling_3d_scale, 1.0);
+ break;
+ default:
+ // This is an unknown mode.
+ WARN_PRINT_ONCE(vformat("Unknown scaling mode: %d. Disabling 3D resolution scaling.", scaling_3d_mode));
+ width = p_viewport->size.width;
+ height = p_viewport->size.height;
+ render_width = width;
+ render_height = height;
+ break;
+ }
+ } else {
+ width = p_viewport->size.width;
+ height = p_viewport->size.height;
+ render_width = width;
+ render_height = height;
}
- // Clamp 3D rendering resolution to reasonable values supported on most hardware.
- // This prevents freezing the engine or outright crashing on lower-end GPUs.
- const int width = CLAMP(p_viewport->size.width * scale_3d, 1, 16384);
- const int height = CLAMP(p_viewport->size.height * scale_3d, 1, 16384);
- RSG::scene->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, width, height, p_viewport->msaa, p_viewport->screen_space_aa, p_viewport->use_debanding, p_viewport->get_view_count());
+ p_viewport->internal_size = Size2(render_width, render_height);
+
+ RSG::scene->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, render_width, render_height, width, height, p_viewport->fsr_sharpness, p_viewport->fsr_mipmap_bias, p_viewport->msaa, p_viewport->screen_space_aa, p_viewport->use_debanding, p_viewport->get_view_count());
}
}
}
@@ -116,8 +167,8 @@ void RendererViewport::_draw_3d(Viewport *p_viewport) {
}
}
- float screen_lod_threshold = p_viewport->lod_threshold / float(p_viewport->size.width);
- RSG::scene->render_camera(p_viewport->render_buffers, p_viewport->camera, p_viewport->scenario, p_viewport->self, p_viewport->size, screen_lod_threshold, p_viewport->shadow_atlas, xr_interface, &p_viewport->render_info);
+ float screen_mesh_lod_threshold = p_viewport->mesh_lod_threshold / float(p_viewport->size.width);
+ RSG::scene->render_camera(p_viewport->render_buffers, p_viewport->camera, p_viewport->scenario, p_viewport->self, p_viewport->internal_size, screen_mesh_lod_threshold, p_viewport->shadow_atlas, xr_interface, &p_viewport->render_info);
RENDER_TIMESTAMP("<End Rendering 3D Scene");
}
@@ -129,6 +180,11 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
timestamp_vp_map[rt_id] = p_viewport->self;
}
+ if (OS::get_singleton()->get_current_rendering_driver_name() == "opengl3") {
+ // This is currently needed for GLES to keep the current window being rendered to up to date
+ DisplayServer::get_singleton()->gl_window_make_current(p_viewport->viewport_to_screen);
+ }
+
/* Camera should always be BEFORE any other 3D */
bool scenario_draw_canvas_bg = false; //draw canvas, or some layer of it, as BG for 3D instead of in front
@@ -495,9 +551,6 @@ void RendererViewport::draw_viewports() {
if (XRServer::get_singleton() != nullptr) {
xr_interface = XRServer::get_singleton()->get_primary_interface();
-
- // process all our active interfaces
- XRServer::get_singleton()->_process();
}
if (Engine::get_singleton()->is_editor_hint()) {
@@ -529,6 +582,21 @@ void RendererViewport::draw_viewports() {
bool visible = vp->viewport_to_screen_rect != Rect2();
+ if (vp->use_xr && xr_interface.is_valid()) {
+ visible = true; // XR viewport is always visible regardless of update mode, output is sent to HMD.
+
+ // Override our size, make sure it matches our required size and is created as a stereo target
+ Size2 xr_size = xr_interface->get_render_target_size();
+
+ // Would have been nice if we could call viewport_set_size here,
+ // but alas that takes our RID and we now have our pointer,
+ // also we only check if view_count changes in render_target_set_size so we need to call that for this to reliably change
+ vp->occlusion_buffer_dirty = vp->occlusion_buffer_dirty || (vp->size != xr_size);
+ vp->size = xr_size;
+ uint32_t view_count = xr_interface->get_view_count();
+ RSG::storage->render_target_set_size(vp->render_target, vp->size.x, vp->size.y, view_count);
+ }
+
if (vp->update_mode == RS::VIEWPORT_UPDATE_ALWAYS || vp->update_mode == RS::VIEWPORT_UPDATE_ONCE) {
visible = true;
}
@@ -566,11 +634,6 @@ void RendererViewport::draw_viewports() {
RSG::storage->render_target_set_as_unused(vp->render_target);
if (vp->use_xr && xr_interface.is_valid()) {
- // override our size, make sure it matches our required size and is created as a stereo target
- vp->size = xr_interface->get_render_target_size();
- uint32_t view_count = xr_interface->get_view_count();
- RSG::storage->render_target_set_size(vp->render_target, vp->size.x, vp->size.y, view_count);
-
// check for an external texture destination (disabled for now, not yet supported)
// RSG::storage->render_target_set_external_texture(vp->render_target, xr_interface->get_external_texture_for_eye(leftOrMono));
RSG::storage->render_target_set_external_texture(vp->render_target, 0);
@@ -660,6 +723,8 @@ void RendererViewport::viewport_initialize(RID p_rid) {
viewport->render_target = RSG::storage->render_target_create();
viewport->shadow_atlas = RSG::scene->shadow_atlas_create();
viewport->viewport_render_direct_to_screen = false;
+
+ viewport->fsr_enabled = !RSG::rasterizer->is_low_end() && !viewport->disable_3d;
}
void RendererViewport::viewport_set_use_xr(RID p_viewport, bool p_use_xr) {
@@ -674,18 +739,42 @@ void RendererViewport::viewport_set_use_xr(RID p_viewport, bool p_use_xr) {
_configure_3d_render_buffers(viewport);
}
-void RendererViewport::viewport_set_scale_3d(RID p_viewport, float p_scale_3d) {
+void RendererViewport::viewport_set_scaling_3d_mode(RID p_viewport, RS::ViewportScaling3DMode p_mode) {
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+ viewport->scaling_3d_mode = p_mode;
+ _configure_3d_render_buffers(viewport);
+}
+
+void RendererViewport::viewport_set_fsr_sharpness(RID p_viewport, float p_sharpness) {
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+ viewport->fsr_sharpness = p_sharpness;
+ _configure_3d_render_buffers(viewport);
+}
+
+void RendererViewport::viewport_set_fsr_mipmap_bias(RID p_viewport, float p_mipmap_bias) {
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+ viewport->fsr_mipmap_bias = p_mipmap_bias;
+ _configure_3d_render_buffers(viewport);
+}
+
+void RendererViewport::viewport_set_scaling_3d_scale(RID p_viewport, float p_scaling_3d_scale) {
Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
// Clamp to reasonable values that are actually useful.
// Values above 2.0 don't serve a practical purpose since the viewport
// isn't displayed with mipmaps.
- if (viewport->scale_3d == CLAMP(p_scale_3d, 0.1, 2.0)) {
+ if (viewport->scaling_3d_scale == CLAMP(p_scaling_3d_scale, 0.1, 2.0)) {
return;
}
- viewport->scale_3d = CLAMP(p_scale_3d, 0.1, 2.0);
+ viewport->scaling_3d_scale = CLAMP(p_scaling_3d_scale, 0.1, 2.0);
_configure_3d_render_buffers(viewport);
}
@@ -711,6 +800,7 @@ void RendererViewport::viewport_set_size(RID p_viewport, int p_width, int p_heig
ERR_FAIL_COND(!viewport);
viewport->size = Size2(p_width, p_height);
+
uint32_t view_count = viewport->get_view_count();
RSG::storage->render_target_set_size(viewport->render_target, p_width, p_height, view_count);
_configure_3d_render_buffers(viewport);
@@ -750,7 +840,7 @@ void RendererViewport::viewport_attach_to_screen(RID p_viewport, const Rect2 &p_
ERR_FAIL_COND(!viewport);
if (p_screen != DisplayServer::INVALID_WINDOW_ID) {
- // If using GLES2 we can optimize this operation by rendering directly to system_fbo
+ // If using OpenGL we can optimize this operation by rendering directly to system_fbo
// instead of rendering to fbo and copying to system_fbo after
if (RSG::rasterizer->is_low_end() && viewport->viewport_render_direct_to_screen) {
RSG::storage->render_target_set_size(viewport->render_target, p_rect.size.x, p_rect.size.y, viewport->get_view_count());
@@ -1004,14 +1094,15 @@ void RendererViewport::viewport_set_occlusion_culling_build_quality(RS::Viewport
RendererSceneOcclusionCull::get_singleton()->set_build_quality(p_quality);
}
-void RendererViewport::viewport_set_lod_threshold(RID p_viewport, float p_pixels) {
+void RendererViewport::viewport_set_mesh_lod_threshold(RID p_viewport, float p_pixels) {
Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
- viewport->lod_threshold = p_pixels;
+ viewport->mesh_lod_threshold = p_pixels;
}
int RendererViewport::viewport_get_render_info(RID p_viewport, RS::ViewportRenderInfoType p_type, RS::ViewportRenderInfo p_info) {
+ ERR_FAIL_INDEX_V(p_type, RS::VIEWPORT_RENDER_INFO_TYPE_MAX, -1);
ERR_FAIL_INDEX_V(p_info, RS::VIEWPORT_RENDER_INFO_MAX, -1);
Viewport *viewport = viewport_owner.get_or_null(p_viewport);
diff --git a/servers/rendering/renderer_viewport.h b/servers/rendering/renderer_viewport.h
index f6e6cc8e84..7bc8f9961b 100644
--- a/servers/rendering/renderer_viewport.h
+++ b/servers/rendering/renderer_viewport.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -49,12 +49,16 @@ public:
bool use_xr; /* use xr interface to override camera positioning and projection matrices and control output */
- float scale_3d = 1.0;
-
+ Size2i internal_size;
Size2i size;
RID camera;
RID scenario;
+ RS::ViewportScaling3DMode scaling_3d_mode;
+ float scaling_3d_scale = 1.0;
+ float fsr_sharpness = 0.2f;
+ float fsr_mipmap_bias = 0.0f;
+ bool fsr_enabled;
RS::ViewportUpdateMode update_mode;
RID render_target;
RID render_target_texture;
@@ -91,7 +95,7 @@ public:
bool sdf_active;
- float lod_threshold = 1.0;
+ float mesh_lod_threshold = 1.0;
uint64_t last_pass = 0;
@@ -207,7 +211,6 @@ public:
void viewport_initialize(RID p_rid);
void viewport_set_use_xr(RID p_viewport, bool p_use_xr);
- void viewport_set_scale_3d(RID p_viewport, float p_scale_3d);
void viewport_set_size(RID p_viewport, int p_width, int p_height);
@@ -216,6 +219,12 @@ public:
void viewport_set_active(RID p_viewport, bool p_active);
void viewport_set_parent_viewport(RID p_viewport, RID p_parent_viewport);
+
+ void viewport_set_scaling_3d_mode(RID p_viewport, RS::ViewportScaling3DMode p_mode);
+ void viewport_set_scaling_3d_scale(RID p_viewport, float p_scaling_3d_scale);
+ void viewport_set_fsr_sharpness(RID p_viewport, float p_sharpness);
+ void viewport_set_fsr_mipmap_bias(RID p_viewport, float p_mipmap_bias);
+
void viewport_set_update_mode(RID p_viewport, RS::ViewportUpdateMode p_mode);
void viewport_set_vflip(RID p_viewport, bool p_enable);
@@ -247,7 +256,7 @@ public:
void viewport_set_use_occlusion_culling(RID p_viewport, bool p_use_occlusion_culling);
void viewport_set_occlusion_rays_per_thread(int p_rays_per_thread);
void viewport_set_occlusion_culling_build_quality(RS::ViewportOcclusionCullingBuildQuality p_quality);
- void viewport_set_lod_threshold(RID p_viewport, float p_pixels);
+ void viewport_set_mesh_lod_threshold(RID p_viewport, float p_pixels);
virtual int viewport_get_render_info(RID p_viewport, RS::ViewportRenderInfoType p_type, RS::ViewportRenderInfo p_info);
virtual void viewport_set_debug_draw(RID p_viewport, RS::ViewportDebugDraw p_draw);
diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp
index d2064a041d..6fc5d0b3e8 100644
--- a/servers/rendering/rendering_device.cpp
+++ b/servers/rendering/rendering_device.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -98,10 +98,10 @@ RID RenderingDevice::_texture_create_shared(const Ref<RDTextureView> &p_view, RI
return texture_create_shared(p_view->base, p_with_texture);
}
-RID RenderingDevice::_texture_create_shared_from_slice(const Ref<RDTextureView> &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, TextureSliceType p_slice_type) {
+RID RenderingDevice::_texture_create_shared_from_slice(const Ref<RDTextureView> &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, uint32_t p_mipmaps, TextureSliceType p_slice_type) {
ERR_FAIL_COND_V(p_view.is_null(), RID());
- return texture_create_shared_from_slice(p_view->base, p_with_texture, p_layer, p_mipmap, p_slice_type);
+ return texture_create_shared_from_slice(p_view->base, p_with_texture, p_layer, p_mipmap, p_mipmaps, p_slice_type);
}
RenderingDevice::FramebufferFormatID RenderingDevice::_framebuffer_format_create(const TypedArray<RDAttachmentFormat> &p_attachments, uint32_t p_view_count) {
@@ -185,9 +185,13 @@ Ref<RDShaderSPIRV> RenderingDevice::_shader_compile_spirv_from_source(const Ref<
String error;
ShaderStage stage = ShaderStage(i);
- Vector<uint8_t> spirv = shader_compile_spirv_from_source(stage, p_source->get_stage_source(stage), p_source->get_language(), &error, p_allow_cache);
- bytecode->set_stage_bytecode(stage, spirv);
- bytecode->set_stage_compile_error(stage, error);
+ String source = p_source->get_stage_source(stage);
+
+ if (!source.is_empty()) {
+ Vector<uint8_t> spirv = shader_compile_spirv_from_source(stage, source, p_source->get_language(), &error, p_allow_cache);
+ bytecode->set_stage_bytecode(stage, spirv);
+ bytecode->set_stage_compile_error(stage, error);
+ }
}
return bytecode;
}
@@ -201,7 +205,7 @@ Vector<uint8_t> RenderingDevice::_shader_compile_binary_from_spirv(const Ref<RDS
ShaderStageSPIRVData sd;
sd.shader_stage = stage;
String error = p_spirv->get_stage_compile_error(stage);
- ERR_FAIL_COND_V_MSG(error != String(), Vector<uint8_t>(), "Can't create a shader from an errored bytecode. Check errors in source bytecode.");
+ ERR_FAIL_COND_V_MSG(!error.is_empty(), Vector<uint8_t>(), "Can't create a shader from an errored bytecode. Check errors in source bytecode.");
sd.spir_v = p_spirv->get_stage_bytecode(stage);
if (sd.spir_v.is_empty()) {
continue;
@@ -221,7 +225,7 @@ RID RenderingDevice::_shader_create_from_spirv(const Ref<RDShaderSPIRV> &p_spirv
ShaderStageSPIRVData sd;
sd.shader_stage = stage;
String error = p_spirv->get_stage_compile_error(stage);
- ERR_FAIL_COND_V_MSG(error != String(), RID(), "Can't create a shader from an errored bytecode. Check errors in source bytecode.");
+ ERR_FAIL_COND_V_MSG(!error.is_empty(), RID(), "Can't create a shader from an errored bytecode. Check errors in source bytecode.");
sd.spir_v = p_spirv->get_stage_bytecode(stage);
if (sd.spir_v.is_empty()) {
continue;
@@ -360,7 +364,7 @@ void RenderingDevice::_compute_list_set_push_constant(ComputeListID p_list, cons
void RenderingDevice::_bind_methods() {
ClassDB::bind_method(D_METHOD("texture_create", "format", "view", "data"), &RenderingDevice::_texture_create, DEFVAL(Array()));
ClassDB::bind_method(D_METHOD("texture_create_shared", "view", "with_texture"), &RenderingDevice::_texture_create_shared);
- ClassDB::bind_method(D_METHOD("texture_create_shared_from_slice", "view", "with_texture", "layer", "mipmap", "slice_type"), &RenderingDevice::_texture_create_shared_from_slice, DEFVAL(TEXTURE_SLICE_2D));
+ ClassDB::bind_method(D_METHOD("texture_create_shared_from_slice", "view", "with_texture", "layer", "mipmap", "mipmaps", "slice_type"), &RenderingDevice::_texture_create_shared_from_slice, DEFVAL(1), DEFVAL(TEXTURE_SLICE_2D));
ClassDB::bind_method(D_METHOD("texture_update", "texture", "layer", "data", "post_barrier"), &RenderingDevice::texture_update, DEFVAL(BARRIER_MASK_ALL));
ClassDB::bind_method(D_METHOD("texture_get_data", "texture", "layer"), &RenderingDevice::texture_get_data);
@@ -486,6 +490,13 @@ void RenderingDevice::_bind_methods() {
BIND_CONSTANT(BARRIER_MASK_ALL);
BIND_CONSTANT(BARRIER_MASK_NO_BARRIER);
+ BIND_ENUM_CONSTANT(DEVICE_TYPE_OTHER);
+ BIND_ENUM_CONSTANT(DEVICE_TYPE_INTEGRATED_GPU);
+ BIND_ENUM_CONSTANT(DEVICE_TYPE_DISCRETE_GPU);
+ BIND_ENUM_CONSTANT(DEVICE_TYPE_VIRTUAL_GPU);
+ BIND_ENUM_CONSTANT(DEVICE_TYPE_CPU);
+ BIND_ENUM_CONSTANT(DEVICE_TYPE_MAX);
+
BIND_ENUM_CONSTANT(DRIVER_RESOURCE_VULKAN_DEVICE);
BIND_ENUM_CONSTANT(DRIVER_RESOURCE_VULKAN_PHYSICAL_DEVICE);
BIND_ENUM_CONSTANT(DRIVER_RESOURCE_VULKAN_INSTANCE);
@@ -718,14 +729,6 @@ void RenderingDevice::_bind_methods() {
BIND_ENUM_CONSTANT(DATA_FORMAT_G16_B16_R16_3PLANE_422_UNORM);
BIND_ENUM_CONSTANT(DATA_FORMAT_G16_B16R16_2PLANE_422_UNORM);
BIND_ENUM_CONSTANT(DATA_FORMAT_G16_B16_R16_3PLANE_444_UNORM);
- BIND_ENUM_CONSTANT(DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG);
- BIND_ENUM_CONSTANT(DATA_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG);
- BIND_ENUM_CONSTANT(DATA_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG);
- BIND_ENUM_CONSTANT(DATA_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG);
- BIND_ENUM_CONSTANT(DATA_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG);
- BIND_ENUM_CONSTANT(DATA_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG);
- BIND_ENUM_CONSTANT(DATA_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG);
- BIND_ENUM_CONSTANT(DATA_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG);
BIND_ENUM_CONSTANT(DATA_FORMAT_MAX);
BIND_ENUM_CONSTANT(TEXTURE_TYPE_1D);
diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h
index 5eb8f1cead..655a32a805 100644
--- a/servers/rendering/rendering_device.h
+++ b/servers/rendering/rendering_device.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -60,6 +60,17 @@ public:
DEVICE_DIRECTX
};
+ // This enum matches VkPhysicalDeviceType (except for `DEVICE_TYPE_MAX`).
+ // Unlike VkPhysicalDeviceType, DeviceType is exposed to the scripting API.
+ enum DeviceType {
+ DEVICE_TYPE_OTHER,
+ DEVICE_TYPE_INTEGRATED_GPU,
+ DEVICE_TYPE_DISCRETE_GPU,
+ DEVICE_TYPE_VIRTUAL_GPU,
+ DEVICE_TYPE_CPU,
+ DEVICE_TYPE_MAX,
+ };
+
enum DriverResource {
DRIVER_RESOURCE_VULKAN_DEVICE = 0,
DRIVER_RESOURCE_VULKAN_PHYSICAL_DEVICE,
@@ -120,6 +131,7 @@ public:
// features
bool supports_multiview = false; // If true this device supports multiview options
+ bool supports_fsr_half_float = false; // If true this device supports FSR scaling 3D in half float mode, otherwise use the fallback mode
};
typedef String (*ShaderSPIRVGetCacheKeyFunction)(const Capabilities *p_capabilities);
@@ -380,14 +392,6 @@ public:
DATA_FORMAT_G16_B16_R16_3PLANE_422_UNORM,
DATA_FORMAT_G16_B16R16_2PLANE_422_UNORM,
DATA_FORMAT_G16_B16_R16_3PLANE_444_UNORM,
- DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG,
- DATA_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG,
- DATA_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG,
- DATA_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG,
- DATA_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG,
- DATA_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG,
- DATA_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG,
- DATA_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG,
DATA_FORMAT_MAX
};
@@ -504,7 +508,7 @@ public:
TEXTURE_SLICE_2D_ARRAY,
};
- virtual RID texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, TextureSliceType p_slice_type = TEXTURE_SLICE_2D) = 0;
+ virtual RID texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, uint32_t p_mipmaps = 1, TextureSliceType p_slice_type = TEXTURE_SLICE_2D) = 0;
virtual Error texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, uint32_t p_post_barrier = BARRIER_MASK_ALL) = 0;
virtual Vector<uint8_t> texture_get_data(RID p_texture, uint32_t p_layer) = 0; // CPU textures will return immediately, while GPU textures will most likely force a flush
@@ -738,7 +742,7 @@ public:
virtual RID uniform_set_create(const Vector<Uniform> &p_uniforms, RID p_shader, uint32_t p_shader_set) = 0;
virtual bool uniform_set_is_valid(RID p_uniform_set) = 0;
- typedef void (*UniformSetInvalidatedCallback)(const RID &, void *);
+ typedef void (*UniformSetInvalidatedCallback)(void *);
virtual void uniform_set_set_invalidation_callback(RID p_uniform_set, UniformSetInvalidatedCallback p_callback, void *p_userdata) = 0;
virtual Error buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const void *p_data, uint32_t p_post_barrier = BARRIER_MASK_ALL) = 0;
@@ -1198,6 +1202,7 @@ public:
virtual String get_device_vendor_name() const = 0;
virtual String get_device_name() const = 0;
+ virtual RenderingDevice::DeviceType get_device_type() const = 0;
virtual String get_device_pipeline_cache_uuid() const = 0;
virtual uint64_t get_driver_resource(DriverResource p_resource, RID p_rid = RID(), uint64_t p_index = 0) = 0;
@@ -1209,7 +1214,7 @@ protected:
//binders to script API
RID _texture_create(const Ref<RDTextureFormat> &p_format, const Ref<RDTextureView> &p_view, const TypedArray<PackedByteArray> &p_data = Array());
RID _texture_create_shared(const Ref<RDTextureView> &p_view, RID p_with_texture);
- RID _texture_create_shared_from_slice(const Ref<RDTextureView> &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, TextureSliceType p_slice_type = TEXTURE_SLICE_2D);
+ RID _texture_create_shared_from_slice(const Ref<RDTextureView> &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, uint32_t p_mipmaps = 1, TextureSliceType p_slice_type = TEXTURE_SLICE_2D);
FramebufferFormatID _framebuffer_format_create(const TypedArray<RDAttachmentFormat> &p_attachments, uint32_t p_view_count);
FramebufferFormatID _framebuffer_format_create_multipass(const TypedArray<RDAttachmentFormat> &p_attachments, const TypedArray<RDFramebufferPass> &p_passes, uint32_t p_view_count);
@@ -1236,6 +1241,7 @@ protected:
Vector<int64_t> _draw_list_switch_to_next_pass_split(uint32_t p_splits);
};
+VARIANT_ENUM_CAST(RenderingDevice::DeviceType)
VARIANT_ENUM_CAST(RenderingDevice::DriverResource)
VARIANT_ENUM_CAST(RenderingDevice::ShaderStage)
VARIANT_ENUM_CAST(RenderingDevice::ShaderLanguage)
diff --git a/servers/rendering/rendering_device_binds.cpp b/servers/rendering/rendering_device_binds.cpp
index a21f28989b..19cde610ba 100644
--- a/servers/rendering/rendering_device_binds.cpp
+++ b/servers/rendering/rendering_device_binds.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -80,7 +80,7 @@ Error RDShaderFile::parse_versions_from_text(const String &p_text, const String
}
}
- if (base_error != String()) {
+ if (!base_error.is_empty()) {
break;
}
}
@@ -89,7 +89,7 @@ Error RDShaderFile::parse_versions_from_text(const String &p_text, const String
}
}
- if (stage == RD::SHADER_STAGE_MAX && line.strip_edges() != "") {
+ if (stage == RD::SHADER_STAGE_MAX && !line.strip_edges().is_empty()) {
line = line.strip_edges();
if (line.begins_with("//") || line.begins_with("/*")) {
continue; //assuming comment (single line)
@@ -98,7 +98,7 @@ Error RDShaderFile::parse_versions_from_text(const String &p_text, const String
if (reading_versions) {
String l = line.strip_edges();
- if (l != "") {
+ if (!l.is_empty()) {
if (l.find("=") == -1) {
base_error = "Missing `=` in '" + l + "'. Version syntax is `version = \"<defines with C escaping>\";`.";
break;
@@ -124,7 +124,7 @@ Error RDShaderFile::parse_versions_from_text(const String &p_text, const String
version_texts[version] = define + "\n" + p_defines;
}
} else {
- if (stage == RD::SHADER_STAGE_MAX && line.strip_edges() != "") {
+ if (stage == RD::SHADER_STAGE_MAX && !line.strip_edges().is_empty()) {
base_error = "Text was found that does not belong to a valid section: " + line;
break;
}
@@ -140,7 +140,7 @@ Error RDShaderFile::parse_versions_from_text(const String &p_text, const String
}
include = include.substr(1, include.length() - 2).strip_edges();
String include_text = p_include_func(include, p_include_func_userdata);
- if (include_text != String()) {
+ if (!include_text.is_empty()) {
stage_code[stage] += "\n" + include_text + "\n";
} else {
base_error = "#include failed for file '" + include + "'";
@@ -158,7 +158,7 @@ Error RDShaderFile::parse_versions_from_text(const String &p_text, const String
Ref<RDShaderFile> shader_file;
shader_file.instantiate();
- if (base_error == "") {
+ if (base_error.is_empty()) {
if (stage_found[RD::SHADER_STAGE_COMPUTE] && stages_found > 1) {
ERR_FAIL_V_MSG(ERR_PARSE_ERROR, "When writing compute shaders, [compute] mustbe the only stage present.");
}
@@ -177,14 +177,14 @@ Error RDShaderFile::parse_versions_from_text(const String &p_text, const String
for (int i = 0; i < RD::SHADER_STAGE_MAX; i++) {
String code = stage_code[i];
- if (code == String()) {
+ if (code.is_empty()) {
continue;
}
code = code.replace("VERSION_DEFINES", E.value);
String error;
Vector<uint8_t> spirv = RenderingDevice::get_singleton()->shader_compile_spirv_from_source(RD::ShaderStage(i), code, RD::SHADER_LANGUAGE_GLSL, &error, false);
bytecode->set_stage_bytecode(RD::ShaderStage(i), spirv);
- if (error != "") {
+ if (!error.is_empty()) {
error += String() + "\n\nStage '" + stage_str[i] + "' source code: \n\n";
Vector<String> sclines = code.split("\n");
for (int j = 0; j < sclines.size(); j++) {
diff --git a/servers/rendering/rendering_device_binds.h b/servers/rendering/rendering_device_binds.h
index da614877c4..b07857364b 100644
--- a/servers/rendering/rendering_device_binds.h
+++ b/servers/rendering/rendering_device_binds.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -368,13 +368,13 @@ public:
}
void print_errors(const String &p_file) {
- if (base_error != "") {
+ if (!base_error.is_empty()) {
ERR_PRINT("Error parsing shader '" + p_file + "':\n\n" + base_error);
} else {
for (KeyValue<StringName, Ref<RDShaderSPIRV>> &E : versions) {
for (int i = 0; i < RD::SHADER_STAGE_MAX; i++) {
String error = E.value->get_stage_compile_error(RD::ShaderStage(i));
- if (error != String()) {
+ if (!error.is_empty()) {
static const char *stage_str[RD::SHADER_STAGE_MAX] = {
"vertex",
"fragment",
@@ -427,7 +427,7 @@ protected:
ClassDB::bind_method(D_METHOD("_set_versions", "versions"), &RDShaderFile::_set_versions);
ClassDB::bind_method(D_METHOD("_get_versions"), &RDShaderFile::_get_versions);
- ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "_versions", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_versions", "_get_versions");
+ ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "_versions", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_versions", "_get_versions");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "base_error"), "set_base_error", "get_base_error");
}
};
diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp
index 107c9f8040..d7e9d210db 100644
--- a/servers/rendering/rendering_server_default.cpp
+++ b/servers/rendering/rendering_server_default.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -64,14 +64,8 @@ void RenderingServerDefault::_free(RID p_rid) {
/* EVENT QUEUING */
-void RenderingServerDefault::request_frame_drawn_callback(Object *p_where, const StringName &p_method, const Variant &p_userdata) {
- ERR_FAIL_NULL(p_where);
- FrameDrawnCallbacks fdc;
- fdc.object = p_where->get_instance_id();
- fdc.method = p_method;
- fdc.param = p_userdata;
-
- frame_drawn_callbacks.push_back(fdc);
+void RenderingServerDefault::request_frame_drawn_callback(const Callable &p_callable) {
+ frame_drawn_callbacks.push_back(p_callable);
}
void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
@@ -103,15 +97,13 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
RSG::scene->update_visibility_notifiers();
while (frame_drawn_callbacks.front()) {
- Object *obj = ObjectDB::get_instance(frame_drawn_callbacks.front()->get().object);
- if (obj) {
- Callable::CallError ce;
- const Variant *v = &frame_drawn_callbacks.front()->get().param;
- obj->call(frame_drawn_callbacks.front()->get().method, &v, 1, ce);
- if (ce.error != Callable::CallError::CALL_OK) {
- String err = Variant::get_call_error_text(obj, frame_drawn_callbacks.front()->get().method, &v, 1, ce);
- ERR_PRINT("Error calling frame drawn function: " + err);
- }
+ Callable c = frame_drawn_callbacks.front()->get();
+ Variant result;
+ Callable::CallError ce;
+ c.call(nullptr, 0, result, ce);
+ if (ce.error != Callable::CallError::CALL_OK) {
+ String err = Variant::get_callable_error_text(c, nullptr, 0, ce);
+ ERR_PRINT("Error calling frame drawn function: " + err);
}
frame_drawn_callbacks.pop_front();
@@ -263,6 +255,10 @@ String RenderingServerDefault::get_video_adapter_vendor() const {
return RSG::storage->get_video_adapter_vendor();
}
+RenderingDevice::DeviceType RenderingServerDefault::get_video_adapter_type() const {
+ return RSG::storage->get_video_adapter_type();
+}
+
void RenderingServerDefault::set_frame_profiling_enabled(bool p_enable) {
RSG::storage->capturing_timestamps = p_enable;
}
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index 911d4c463b..ee684c69ed 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -58,13 +58,7 @@ class RenderingServerDefault : public RenderingServer {
static int changes;
RID test_cube;
- struct FrameDrawnCallbacks {
- ObjectID object;
- StringName method;
- Variant param;
- };
-
- List<FrameDrawnCallbacks> frame_drawn_callbacks;
+ List<Callable> frame_drawn_callbacks;
static void _changes_changed() {}
@@ -229,8 +223,8 @@ public:
FUNC2SC(shader_get_param_list, RID, List<PropertyInfo> *)
- FUNC3(shader_set_default_texture_param, RID, const StringName &, RID)
- FUNC2RC(RID, shader_get_default_texture_param, RID, const StringName &)
+ FUNC4(shader_set_default_texture_param, RID, const StringName &, RID, int)
+ FUNC3RC(RID, shader_get_default_texture_param, RID, const StringName &, int)
FUNC2RC(Variant, shader_get_param_default, RID, const StringName &)
FUNC1RC(ShaderNativeSourceCode, shader_get_native_source_code, RID)
@@ -380,7 +374,7 @@ public:
FUNC2(reflection_probe_set_enable_shadows, RID, bool)
FUNC2(reflection_probe_set_cull_mask, RID, uint32_t)
FUNC2(reflection_probe_set_resolution, RID, int)
- FUNC2(reflection_probe_set_lod_threshold, RID, float)
+ FUNC2(reflection_probe_set_mesh_lod_threshold, RID, float)
/* DECAL API */
@@ -487,6 +481,14 @@ public:
FUNC1(particles_collision_height_field_update, RID)
FUNC2(particles_collision_set_height_field_resolution, RID, ParticlesCollisionHeightfieldResolution)
+ /* FOG VOLUME */
+
+ FUNCRIDSPLIT(fog_volume)
+
+ FUNC2(fog_volume_set_shape, RID, FogVolumeShape)
+ FUNC2(fog_volume_set_extents, RID, const Vector3 &)
+ FUNC2(fog_volume_set_material, RID, RID)
+
/* VISIBILITY_NOTIFIER */
FUNCRIDSPLIT(visibility_notifier)
@@ -526,7 +528,6 @@ public:
FUNCRIDSPLIT(viewport)
FUNC2(viewport_set_use_xr, RID, bool)
- FUNC2(viewport_set_scale_3d, RID, float)
FUNC3(viewport_set_size, RID, int, int)
FUNC2(viewport_set_active, RID, bool)
@@ -537,6 +538,11 @@ public:
FUNC3(viewport_attach_to_screen, RID, const Rect2 &, int)
FUNC2(viewport_set_render_direct_to_screen, RID, bool)
+ FUNC2(viewport_set_scaling_3d_mode, RID, ViewportScaling3DMode)
+ FUNC2(viewport_set_scaling_3d_scale, RID, float)
+ FUNC2(viewport_set_fsr_sharpness, RID, float)
+ FUNC2(viewport_set_fsr_mipmap_bias, RID, float)
+
FUNC2(viewport_set_update_mode, RID, ViewportUpdateMode)
FUNC1RC(RID, viewport_get_texture, RID)
@@ -569,7 +575,7 @@ public:
FUNC2(viewport_set_use_occlusion_culling, RID, bool)
FUNC1(viewport_set_occlusion_rays_per_thread, int)
FUNC1(viewport_set_occlusion_culling_build_quality, ViewportOcclusionCullingBuildQuality)
- FUNC2(viewport_set_lod_threshold, RID, float)
+ FUNC2(viewport_set_mesh_lod_threshold, RID, float)
FUNC3R(int, viewport_get_render_info, RID, ViewportRenderInfoType, ViewportRenderInfo)
FUNC2(viewport_set_debug_draw, RID, ViewportDebugDraw)
@@ -620,6 +626,9 @@ public:
FUNC10(environment_set_ssao, RID, bool, float, float, float, float, float, float, float, float)
FUNC6(environment_set_ssao_quality, EnvironmentSSAOQuality, bool, float, int, float, float)
+ FUNC6(environment_set_ssil, RID, bool, float, float, float, float)
+ FUNC6(environment_set_ssil_quality, EnvironmentSSILQuality, bool, float, int, float, float)
+
FUNC11(environment_set_glow, RID, bool, Vector<float>, float, float, float, float, EnvironmentGlowBlendMode, float, float, float)
FUNC1(environment_glow_set_use_bicubic_upscale, bool)
FUNC1(environment_glow_set_use_high_quality, bool)
@@ -629,12 +638,12 @@ public:
FUNC7(environment_set_adjustment, RID, bool, float, float, float, bool, RID)
FUNC9(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float)
- FUNC10(environment_set_volumetric_fog, RID, bool, float, const Color &, float, float, float, float, bool, float)
+ FUNC13(environment_set_volumetric_fog, RID, bool, float, const Color &, const Color &, float, float, float, float, float, bool, float, float)
FUNC2(environment_set_volumetric_fog_volume_size, int, int)
FUNC1(environment_set_volumetric_fog_filter_active, bool)
- FUNC11(environment_set_sdfgi, RID, bool, EnvironmentSDFGICascades, float, EnvironmentSDFGIYScale, bool, float, bool, float, float, float)
+ FUNC11(environment_set_sdfgi, RID, bool, int, float, EnvironmentSDFGIYScale, bool, float, bool, float, float, float)
FUNC1(environment_set_sdfgi_ray_count, EnvironmentSDFGIRayCount)
FUNC1(environment_set_sdfgi_frames_to_converge, EnvironmentSDFGIFramesToConverge)
FUNC1(environment_set_sdfgi_frames_to_update_light, EnvironmentSDFGIFramesToUpdateLight)
@@ -693,6 +702,8 @@ public:
FUNC2(instance_set_extra_visibility_margin, RID, real_t)
FUNC2(instance_set_visibility_parent, RID, RID)
+ FUNC2(instance_set_ignore_culling, RID, bool)
+
// don't use these in a game!
FUNC2RC(Vector<ObjectID>, instances_cull_aabb, const AABB &, RID)
FUNC3RC(Vector<ObjectID>, instances_cull_ray, const Vector3 &, const Vector3 &, RID)
@@ -701,11 +712,12 @@ public:
FUNC3(instance_geometry_set_flag, RID, InstanceFlags, bool)
FUNC2(instance_geometry_set_cast_shadows_setting, RID, ShadowCastingSetting)
FUNC2(instance_geometry_set_material_override, RID, RID)
+ FUNC2(instance_geometry_set_material_overlay, RID, RID)
- FUNC5(instance_geometry_set_visibility_range, RID, float, float, float, float)
+ FUNC6(instance_geometry_set_visibility_range, RID, float, float, float, float, VisibilityRangeFadeMode)
FUNC4(instance_geometry_set_lightmap, RID, RID, const Rect2 &, int)
FUNC2(instance_geometry_set_lod_bias, RID, float)
-
+ FUNC2(instance_geometry_set_transparency, RID, float)
FUNC3(instance_geometry_set_shader_parameter, RID, const StringName &, const Variant &)
FUNC2RC(Variant, instance_geometry_get_shader_parameter, RID, const StringName &)
FUNC2RC(Variant, instance_geometry_get_shader_parameter_default_value, RID, const StringName &)
@@ -870,7 +882,7 @@ public:
/* EVENT QUEUING */
- virtual void request_frame_drawn_callback(Object *p_where, const StringName &p_method, const Variant &p_userdata) override;
+ virtual void request_frame_drawn_callback(const Callable &p_callable) override;
virtual void draw(bool p_swap_buffers, double frame_step) override;
virtual void sync() override;
@@ -883,6 +895,7 @@ public:
virtual uint64_t get_rendering_info(RenderingInfo p_info) override;
virtual String get_video_adapter_name() const override;
virtual String get_video_adapter_vendor() const override;
+ virtual RenderingDevice::DeviceType get_video_adapter_type() const override;
virtual void set_frame_profiling_enabled(bool p_enable) override;
virtual Vector<FrameProfileArea> get_frame_profile() override;
diff --git a/servers/rendering/rendering_server_globals.cpp b/servers/rendering/rendering_server_globals.cpp
index 2dda506bac..b8b06b5eea 100644
--- a/servers/rendering/rendering_server_globals.cpp
+++ b/servers/rendering/rendering_server_globals.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/rendering/rendering_server_globals.h b/servers/rendering/rendering_server_globals.h
index 63755e6125..4351830a5f 100644
--- a/servers/rendering/rendering_server_globals.h
+++ b/servers/rendering/rendering_server_globals.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/rendering/renderer_rd/shader_compiler_rd.cpp b/servers/rendering/shader_compiler.cpp
index 42d11d8bc1..78e81eac0b 100644
--- a/servers/rendering/renderer_rd/shader_compiler_rd.cpp
+++ b/servers/rendering/shader_compiler.cpp
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* shader_compiler_rd.cpp */
+/* shader_compiler.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,11 +28,11 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "shader_compiler_rd.h"
+#include "shader_compiler.h"
#include "core/config/project_settings.h"
#include "core/os/os.h"
-#include "renderer_storage_rd.h"
+#include "servers/rendering/shader_types.h"
#include "servers/rendering_server.h"
#define SL ShaderLanguage
@@ -54,81 +54,6 @@ static String _typestr(SL::DataType p_type) {
return type;
}
-static int _get_datatype_size(SL::DataType p_type) {
- switch (p_type) {
- case SL::TYPE_VOID:
- return 0;
- case SL::TYPE_BOOL:
- return 4;
- case SL::TYPE_BVEC2:
- return 8;
- case SL::TYPE_BVEC3:
- return 12;
- case SL::TYPE_BVEC4:
- return 16;
- case SL::TYPE_INT:
- return 4;
- case SL::TYPE_IVEC2:
- return 8;
- case SL::TYPE_IVEC3:
- return 12;
- case SL::TYPE_IVEC4:
- return 16;
- case SL::TYPE_UINT:
- return 4;
- case SL::TYPE_UVEC2:
- return 8;
- case SL::TYPE_UVEC3:
- return 12;
- case SL::TYPE_UVEC4:
- return 16;
- case SL::TYPE_FLOAT:
- return 4;
- case SL::TYPE_VEC2:
- return 8;
- case SL::TYPE_VEC3:
- return 12;
- case SL::TYPE_VEC4:
- return 16;
- case SL::TYPE_MAT2:
- return 32; // 4 * 4 + 4 * 4
- case SL::TYPE_MAT3:
- return 48; // 4 * 4 + 4 * 4 + 4 * 4
- case SL::TYPE_MAT4:
- return 64;
- case SL::TYPE_SAMPLER2D:
- return 16;
- case SL::TYPE_ISAMPLER2D:
- return 16;
- case SL::TYPE_USAMPLER2D:
- return 16;
- case SL::TYPE_SAMPLER2DARRAY:
- return 16;
- case SL::TYPE_ISAMPLER2DARRAY:
- return 16;
- case SL::TYPE_USAMPLER2DARRAY:
- return 16;
- case SL::TYPE_SAMPLER3D:
- return 16;
- case SL::TYPE_ISAMPLER3D:
- return 16;
- case SL::TYPE_USAMPLER3D:
- return 16;
- case SL::TYPE_SAMPLERCUBE:
- return 16;
- case SL::TYPE_SAMPLERCUBEARRAY:
- return 16;
- case SL::TYPE_STRUCT:
- return 0;
-
- case SL::TYPE_MAX: {
- ERR_FAIL_V(0);
- };
- }
-
- ERR_FAIL_V(0);
-}
-
static int _get_datatype_alignment(SL::DataType p_type) {
switch (p_type) {
case SL::TYPE_VOID:
@@ -227,6 +152,13 @@ static String _prestr(SL::DataPrecision p_pres, bool p_force_highp = false) {
return "";
}
+static String _constr(bool p_is_const) {
+ if (p_is_const) {
+ return "const ";
+ }
+ return "";
+}
+
static String _qualstr(SL::ArgumentQualifier p_qual) {
switch (p_qual) {
case SL::ARGUMENT_QUALIFIER_IN:
@@ -345,7 +277,7 @@ static String get_constant_text(SL::DataType p_type, const Vector<SL::ConstantNo
}
}
-String ShaderCompilerRD::_get_sampler_name(ShaderLanguage::TextureFilter p_filter, ShaderLanguage::TextureRepeat p_repeat) {
+String ShaderCompiler::_get_sampler_name(ShaderLanguage::TextureFilter p_filter, ShaderLanguage::TextureRepeat p_repeat) {
if (p_filter == ShaderLanguage::FILTER_DEFAULT) {
ERR_FAIL_COND_V(actions.default_filter == ShaderLanguage::FILTER_DEFAULT, String());
p_filter = actions.default_filter;
@@ -357,7 +289,7 @@ String ShaderCompilerRD::_get_sampler_name(ShaderLanguage::TextureFilter p_filte
return actions.sampler_array_name + "[" + itos(p_filter + (p_repeat == ShaderLanguage::REPEAT_ENABLE ? ShaderLanguage::FILTER_DEFAULT : 0)) + "]";
}
-void ShaderCompilerRD::_dump_function_deps(const SL::ShaderNode *p_node, const StringName &p_for_func, const Map<StringName, String> &p_func_code, String &r_to_add, Set<StringName> &added) {
+void ShaderCompiler::_dump_function_deps(const SL::ShaderNode *p_node, const StringName &p_for_func, const Map<StringName, String> &p_func_code, String &r_to_add, Set<StringName> &added) {
int fidx = -1;
for (int i = 0; i < p_node->functions.size(); i++) {
@@ -417,9 +349,7 @@ void ShaderCompilerRD::_dump_function_deps(const SL::ShaderNode *p_node, const S
if (i > 0) {
header += ", ";
}
- if (fnode->arguments[i].is_const) {
- header += "const ";
- }
+ header += _constr(fnode->arguments[i].is_const);
if (fnode->arguments[i].type == SL::TYPE_STRUCT) {
header += _qualstr(fnode->arguments[i].qualifier) + _mkid(fnode->arguments[i].type_str) + " " + _mkid(fnode->arguments[i].name);
} else {
@@ -505,7 +435,7 @@ static String _get_global_variable_from_type_and_index(const String &p_buffer, c
}
}
-String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions &p_actions, const DefaultIdentifierActions &p_default_actions, bool p_assigning, bool p_use_scope) {
+String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions &p_actions, const DefaultIdentifierActions &p_default_actions, bool p_assigning, bool p_use_scope) {
String code;
switch (p_node->type) {
@@ -653,20 +583,22 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
uniform_defines.write[uniform.order] = ucode;
if (is_buffer_global) {
//globals are indices into the global table
- uniform_sizes.write[uniform.order] = _get_datatype_size(ShaderLanguage::TYPE_UINT);
+ uniform_sizes.write[uniform.order] = ShaderLanguage::get_datatype_size(ShaderLanguage::TYPE_UINT);
uniform_alignments.write[uniform.order] = _get_datatype_alignment(ShaderLanguage::TYPE_UINT);
} else {
+ // The following code enforces a 16-byte alignment of uniform arrays.
if (uniform.array_size > 0) {
- int size = _get_datatype_size(uniform.type) * uniform.array_size;
+ int size = ShaderLanguage::get_datatype_size(uniform.type) * uniform.array_size;
int m = (16 * uniform.array_size);
if ((size % m) != 0) {
size += m - (size % m);
}
uniform_sizes.write[uniform.order] = size;
+ uniform_alignments.write[uniform.order] = 16;
} else {
- uniform_sizes.write[uniform.order] = _get_datatype_size(uniform.type);
+ uniform_sizes.write[uniform.order] = ShaderLanguage::get_datatype_size(uniform.type);
+ uniform_alignments.write[uniform.order] = _get_datatype_alignment(uniform.type);
}
- uniform_alignments.write[uniform.order] = _get_datatype_alignment(uniform.type);
}
}
@@ -760,17 +692,36 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
vcode += _prestr(varying.precision, ShaderLanguage::is_float_type(varying.type));
vcode += _typestr(varying.type);
vcode += " " + _mkid(varying_name);
+ uint32_t inc = 1U;
+
if (varying.array_size > 0) {
+ inc = (uint32_t)varying.array_size;
+
vcode += "[";
vcode += itos(varying.array_size);
vcode += "]";
}
+
+ switch (varying.type) {
+ case SL::TYPE_MAT2:
+ inc *= 2U;
+ break;
+ case SL::TYPE_MAT3:
+ inc *= 3U;
+ break;
+ case SL::TYPE_MAT4:
+ inc *= 4U;
+ break;
+ default:
+ break;
+ }
+
vcode += ";\n";
r_gen_code.stage_globals[STAGE_VERTEX] += "layout(location=" + itos(index) + ") " + interp_mode + "out " + vcode;
r_gen_code.stage_globals[STAGE_FRAGMENT] += "layout(location=" + itos(index) + ") " + interp_mode + "in " + vcode;
- index++;
+ index += inc;
}
if (var_frag_to_light.size() > 0) {
@@ -791,7 +742,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
for (int i = 0; i < pnode->vconstants.size(); i++) {
const SL::ShaderNode::Constant &cnode = pnode->vconstants[i];
String gcode;
- gcode += "const ";
+ gcode += _constr(true);
gcode += _prestr(cnode.precision, ShaderLanguage::is_float_type(cnode.type));
if (cnode.type == SL::TYPE_STRUCT) {
gcode += _mkid(cnode.type_str);
@@ -875,24 +826,55 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
SL::VariableDeclarationNode *vdnode = (SL::VariableDeclarationNode *)p_node;
String declaration;
- if (vdnode->is_const) {
- declaration += "const ";
- }
+ declaration += _constr(vdnode->is_const);
if (vdnode->datatype == SL::TYPE_STRUCT) {
declaration += _mkid(vdnode->struct_name);
} else {
declaration += _prestr(vdnode->precision) + _typestr(vdnode->datatype);
}
+ declaration += " ";
for (int i = 0; i < vdnode->declarations.size(); i++) {
+ bool is_array = vdnode->declarations[i].size > 0;
if (i > 0) {
declaration += ",";
- } else {
- declaration += " ";
}
declaration += _mkid(vdnode->declarations[i].name);
- if (vdnode->declarations[i].initializer) {
- declaration += "=";
- declaration += _dump_node_code(vdnode->declarations[i].initializer, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
+ if (is_array) {
+ declaration += "[";
+ if (vdnode->declarations[i].size_expression != nullptr) {
+ declaration += _dump_node_code(vdnode->declarations[i].size_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
+ } else {
+ declaration += itos(vdnode->declarations[i].size);
+ }
+ declaration += "]";
+ }
+
+ if (!is_array || vdnode->declarations[i].single_expression) {
+ if (!vdnode->declarations[i].initializer.is_empty()) {
+ declaration += "=";
+ declaration += _dump_node_code(vdnode->declarations[i].initializer[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
+ }
+ } else {
+ int size = vdnode->declarations[i].initializer.size();
+ if (size > 0) {
+ declaration += "=";
+ if (vdnode->datatype == SL::TYPE_STRUCT) {
+ declaration += _mkid(vdnode->struct_name);
+ } else {
+ declaration += _typestr(vdnode->datatype);
+ }
+ declaration += "[";
+ declaration += itos(size);
+ declaration += "]";
+ declaration += "(";
+ for (int j = 0; j < size; j++) {
+ if (j > 0) {
+ declaration += ",";
+ }
+ declaration += _dump_node_code(vdnode->declarations[i].initializer[j], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
+ }
+ declaration += ")";
+ }
}
}
@@ -994,60 +976,6 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
}
code += ")";
} break;
- case SL::Node::TYPE_ARRAY_DECLARATION: {
- SL::ArrayDeclarationNode *adnode = (SL::ArrayDeclarationNode *)p_node;
- String declaration;
- if (adnode->is_const) {
- declaration += "const ";
- }
- if (adnode->datatype == SL::TYPE_STRUCT) {
- declaration += _mkid(adnode->struct_name);
- } else {
- declaration += _prestr(adnode->precision) + _typestr(adnode->datatype);
- }
- for (int i = 0; i < adnode->declarations.size(); i++) {
- if (i > 0) {
- declaration += ",";
- } else {
- declaration += " ";
- }
- declaration += _mkid(adnode->declarations[i].name);
- declaration += "[";
- if (adnode->size_expression != nullptr) {
- declaration += _dump_node_code(adnode->size_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
- } else {
- declaration += itos(adnode->declarations[i].size);
- }
- declaration += "]";
- if (adnode->declarations[i].single_expression) {
- declaration += "=";
- declaration += _dump_node_code(adnode->declarations[i].initializer[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
- } else {
- int sz = adnode->declarations[i].initializer.size();
- if (sz > 0) {
- declaration += "=";
- if (adnode->datatype == SL::TYPE_STRUCT) {
- declaration += _mkid(adnode->struct_name);
- } else {
- declaration += _typestr(adnode->datatype);
- }
- declaration += "[";
- declaration += itos(sz);
- declaration += "]";
- declaration += "(";
- for (int j = 0; j < sz; j++) {
- declaration += _dump_node_code(adnode->declarations[i].initializer[j], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
- if (j != sz - 1) {
- declaration += ", ";
- }
- }
- declaration += ")";
- }
- }
- }
-
- code += declaration;
- } break;
case SL::Node::TYPE_ARRAY: {
SL::ArrayNode *anode = (SL::ArrayNode *)p_node;
bool use_fragment_varying = false;
@@ -1315,6 +1243,9 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
code += ")";
} break;
+ case SL::OP_EMPTY: {
+ // Semicolon (or empty statement) - ignored.
+ } break;
default: {
if (p_use_scope) {
@@ -1401,13 +1332,19 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
return code;
}
-ShaderLanguage::DataType ShaderCompilerRD::_get_variable_type(const StringName &p_type) {
- RS::GlobalVariableType gvt = ((RendererStorageRD *)(RendererStorage::base_singleton))->global_variable_get_type_internal(p_type);
- return RS::global_variable_type_get_shader_datatype(gvt);
+ShaderLanguage::DataType ShaderCompiler::_get_variable_type(const StringName &p_type) {
+ RS::GlobalVariableType gvt = RS::get_singleton()->global_variable_get_type(p_type);
+ return (ShaderLanguage::DataType)RS::global_variable_type_get_shader_datatype(gvt);
}
-Error ShaderCompilerRD::compile(RS::ShaderMode p_mode, const String &p_code, IdentifierActions *p_actions, const String &p_path, GeneratedCode &r_gen_code) {
- Error err = parser.compile(p_code, ShaderTypes::get_singleton()->get_functions(p_mode), ShaderTypes::get_singleton()->get_modes(p_mode), ShaderLanguage::VaryingFunctionNames(), ShaderTypes::get_singleton()->get_types(), _get_variable_type);
+Error ShaderCompiler::compile(RS::ShaderMode p_mode, const String &p_code, IdentifierActions *p_actions, const String &p_path, GeneratedCode &r_gen_code) {
+ SL::ShaderCompileInfo info;
+ info.functions = ShaderTypes::get_singleton()->get_functions(p_mode);
+ info.render_modes = ShaderTypes::get_singleton()->get_modes(p_mode);
+ info.shader_types = ShaderTypes::get_singleton()->get_types();
+ info.global_variable_type_func = _get_variable_type;
+
+ Error err = parser.compile(p_code, info);
if (err != OK) {
Vector<String> shader = p_code.split("\n");
@@ -1421,7 +1358,7 @@ Error ShaderCompilerRD::compile(RS::ShaderMode p_mode, const String &p_code, Ide
}
}
- _err_print_error(nullptr, p_path.utf8().get_data(), parser.get_error_line(), parser.get_error_text().utf8().get_data(), ERR_HANDLER_SHADER);
+ _err_print_error(nullptr, p_path.utf8().get_data(), parser.get_error_line(), parser.get_error_text().utf8().get_data(), false, ERR_HANDLER_SHADER);
return err;
}
@@ -1446,7 +1383,7 @@ Error ShaderCompilerRD::compile(RS::ShaderMode p_mode, const String &p_code, Ide
return OK;
}
-void ShaderCompilerRD::initialize(DefaultIdentifierActions p_actions) {
+void ShaderCompiler::initialize(DefaultIdentifierActions p_actions) {
actions = p_actions;
time_name = "TIME";
@@ -1468,7 +1405,7 @@ void ShaderCompilerRD::initialize(DefaultIdentifierActions p_actions) {
texture_functions.insert("texelFetch");
}
-ShaderCompilerRD::ShaderCompilerRD() {
+ShaderCompiler::ShaderCompiler() {
#if 0
/** SPATIAL SHADER **/
diff --git a/servers/rendering/renderer_rd/shader_compiler_rd.h b/servers/rendering/shader_compiler.h
index 2ab689c27c..8f0ee664ac 100644
--- a/servers/rendering/renderer_rd/shader_compiler_rd.h
+++ b/servers/rendering/shader_compiler.h
@@ -1,12 +1,12 @@
/*************************************************************************/
-/* shader_compiler_rd.h */
+/* shader_compiler.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -28,15 +28,14 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SHADER_COMPILER_RD_H
-#define SHADER_COMPILER_RD_H
+#ifndef SHADER_COMPILER_H
+#define SHADER_COMPILER_H
#include "core/templates/pair.h"
#include "servers/rendering/shader_language.h"
-#include "servers/rendering/shader_types.h"
#include "servers/rendering_server.h"
-class ShaderCompilerRD {
+class ShaderCompiler {
public:
enum Stage {
STAGE_VERTEX,
@@ -127,7 +126,7 @@ public:
Error compile(RS::ShaderMode p_mode, const String &p_code, IdentifierActions *p_actions, const String &p_path, GeneratedCode &r_gen_code);
void initialize(DefaultIdentifierActions p_actions);
- ShaderCompilerRD();
+ ShaderCompiler();
};
-#endif // SHADERCOMPILERRD_H
+#endif // SHADER_COMPILER_H
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index 9c38bf7606..4e07582187 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -88,7 +88,8 @@ String ShaderLanguage::get_operator_text(Operator p_op) {
"--",
"()",
"construct",
- "index" };
+ "index",
+ "empty" };
return op_names[p_op];
}
@@ -203,7 +204,7 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
"HINT_WHITE_TEXTURE",
"HINT_BLACK_TEXTURE",
"HINT_NORMAL_TEXTURE",
- "HINT_ANISO_TEXTURE",
+ "HINT_ANISOTROPY_TEXTURE",
"HINT_ALBEDO_TEXTURE",
"HINT_BLACK_ALBEDO_TEXTURE",
"HINT_COLOR",
@@ -213,8 +214,8 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
"FILTER_LINEAR",
"FILTER_NEAREST_MIPMAP",
"FILTER_LINEAR_MIPMAP",
- "FILTER_NEAREST_MIPMAP_ANISO",
- "FILTER_LINEAR_MIPMAP_ANISO",
+ "FILTER_NEAREST_MIPMAP_ANISOTROPIC",
+ "FILTER_LINEAR_MIPMAP_ANISOTROPIC",
"REPEAT_ENABLE",
"REPEAT_DISABLE",
"SHADER_TYPE",
@@ -225,7 +226,7 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
String ShaderLanguage::get_token_text(Token p_token) {
String name = token_names[p_token.type];
- if (p_token.type == TK_INT_CONSTANT || p_token.type == TK_FLOAT_CONSTANT) {
+ if (p_token.is_integer_constant() || p_token.type == TK_FLOAT_CONSTANT) {
name += "(" + rtos(p_token.constant) + ")";
} else if (p_token.type == TK_IDENTIFIER) {
name += "(" + String(p_token.text) + ")";
@@ -317,7 +318,7 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
{ TK_HINT_ROUGHNESS_B, "hint_roughness_b" },
{ TK_HINT_ROUGHNESS_A, "hint_roughness_a" },
{ TK_HINT_ROUGHNESS_GRAY, "hint_roughness_gray" },
- { TK_HINT_ANISO_TEXTURE, "hint_aniso" },
+ { TK_HINT_ANISOTROPY_TEXTURE, "hint_anisotropy" },
{ TK_HINT_ALBEDO_TEXTURE, "hint_albedo" },
{ TK_HINT_BLACK_ALBEDO_TEXTURE, "hint_black_albedo" },
{ TK_HINT_COLOR, "hint_color" },
@@ -327,8 +328,8 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
{ TK_FILTER_LINEAR, "filter_linear" },
{ TK_FILTER_NEAREST_MIPMAP, "filter_nearest_mipmap" },
{ TK_FILTER_LINEAR_MIPMAP, "filter_linear_mipmap" },
- { TK_FILTER_NEAREST_MIPMAP_ANISO, "filter_nearest_mipmap_aniso" },
- { TK_FILTER_LINEAR_MIPMAP_ANISO, "filter_linear_mipmap_aniso" },
+ { TK_FILTER_NEAREST_MIPMAP_ANISOTROPIC, "filter_nearest_mipmap_anisotropic" },
+ { TK_FILTER_LINEAR_MIPMAP_ANISOTROPIC, "filter_linear_mipmap_anisotropic" },
{ TK_REPEAT_ENABLE, "repeat_enable" },
{ TK_REPEAT_DISABLE, "repeat_disable" },
{ TK_SHADER_TYPE, "shader_type" },
@@ -474,6 +475,10 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
case ':':
return _make_token(TK_COLON);
case '^':
+ if (GETCHAR(0) == '=') {
+ char_idx++;
+ return _make_token(TK_OP_ASSIGN_BIT_XOR);
+ }
return _make_token(TK_OP_BIT_XOR);
case '~':
return _make_token(TK_OP_BIT_INVERT);
@@ -540,63 +545,113 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
if (_is_number(GETCHAR(0)) || (GETCHAR(0) == '.' && _is_number(GETCHAR(1)))) {
// parse number
+ bool hexa_found = false;
bool period_found = false;
bool exponent_found = false;
- bool hexa_found = false;
- bool sign_found = false;
bool float_suffix_found = false;
+ bool uint_suffix_found = false;
+ bool end_suffix_found = false;
+
+ enum {
+ CASE_ALL,
+ CASE_HEXA_PERIOD,
+ CASE_EXPONENT,
+ CASE_SIGN_AFTER_EXPONENT,
+ CASE_NONE,
+ CASE_MAX,
+ } lut_case = CASE_ALL;
+
+ static bool suffix_lut[CASE_MAX][127];
+
+ if (!is_const_suffix_lut_initialized) {
+ is_const_suffix_lut_initialized = true;
+
+ for (int i = 0; i < 127; i++) {
+ char t = char(i);
+
+ suffix_lut[CASE_ALL][i] = t == '.' || t == 'x' || t == 'e' || t == 'f' || t == 'u' || t == '-' || t == '+';
+ suffix_lut[CASE_HEXA_PERIOD][i] = t == 'e' || t == 'f';
+ suffix_lut[CASE_EXPONENT][i] = t == 'f' || t == '-' || t == '+';
+ suffix_lut[CASE_SIGN_AFTER_EXPONENT][i] = t == 'f';
+ suffix_lut[CASE_NONE][i] = false;
+ }
+ }
String str;
int i = 0;
while (true) {
- if (GETCHAR(i) == '.') {
- if (period_found || exponent_found || hexa_found || float_suffix_found) {
- return _make_token(TK_ERROR, "Invalid numeric constant");
- }
- period_found = true;
- } else if (GETCHAR(i) == 'x') {
- if (hexa_found || str.length() != 1 || str[0] != '0') {
- return _make_token(TK_ERROR, "Invalid numeric constant");
+ const char32_t symbol = String::char_lowercase(GETCHAR(i));
+ bool error = false;
+
+ if (_is_number(symbol)) {
+ if (end_suffix_found) {
+ error = true;
}
- hexa_found = true;
- } else if (GETCHAR(i) == 'e' && !hexa_found) {
- if (exponent_found || float_suffix_found) {
- return _make_token(TK_ERROR, "Invalid numeric constant");
+ } else {
+ if (symbol < 0x7F && suffix_lut[lut_case][symbol]) {
+ if (symbol == 'x') {
+ hexa_found = true;
+ lut_case = CASE_HEXA_PERIOD;
+ } else if (symbol == '.') {
+ period_found = true;
+ lut_case = CASE_HEXA_PERIOD;
+ } else if (symbol == 'e' && !hexa_found) {
+ exponent_found = true;
+ lut_case = CASE_EXPONENT;
+ } else if (symbol == 'f' && !hexa_found) {
+ if (!period_found && !exponent_found) {
+ error = true;
+ }
+ float_suffix_found = true;
+ end_suffix_found = true;
+ lut_case = CASE_NONE;
+ } else if (symbol == 'u') {
+ uint_suffix_found = true;
+ end_suffix_found = true;
+ lut_case = CASE_NONE;
+ } else if (symbol == '-' || symbol == '+') {
+ if (exponent_found) {
+ lut_case = CASE_SIGN_AFTER_EXPONENT;
+ } else {
+ break;
+ }
+ }
+ } else if (!hexa_found || !_is_hex(symbol)) {
+ if (_is_text_char(symbol)) {
+ error = true;
+ } else {
+ break;
+ }
}
- exponent_found = true;
- } else if (GETCHAR(i) == 'f' && !hexa_found) {
- if (exponent_found) {
- return _make_token(TK_ERROR, "Invalid numeric constant");
+ }
+
+ if (error) {
+ if (hexa_found) {
+ return _make_token(TK_ERROR, "Invalid (hexadecimal) numeric constant");
}
- float_suffix_found = true;
- } else if (_is_number(GETCHAR(i))) {
- if (float_suffix_found) {
- return _make_token(TK_ERROR, "Invalid numeric constant");
+ if (period_found || exponent_found || float_suffix_found) {
+ return _make_token(TK_ERROR, "Invalid (float) numeric constant");
}
- } else if (hexa_found && _is_hex(GETCHAR(i))) {
- } else if ((GETCHAR(i) == '-' || GETCHAR(i) == '+') && exponent_found) {
- if (sign_found) {
- return _make_token(TK_ERROR, "Invalid numeric constant");
+ if (uint_suffix_found) {
+ return _make_token(TK_ERROR, "Invalid (unsigned integer) numeric constant");
}
- sign_found = true;
- } else {
- break;
+ return _make_token(TK_ERROR, "Invalid (integer) numeric constant");
}
-
- str += char32_t(GETCHAR(i));
+ str += symbol;
i++;
}
char32_t last_char = str[str.length() - 1];
- if (hexa_found) {
- //integer(hex)
+ if (hexa_found) { // Integer(hex)
if (str.size() > 11 || !str.is_valid_hex_number(true)) { // > 0xFFFFFFFF
return _make_token(TK_ERROR, "Invalid (hexadecimal) numeric constant");
}
- } else if (period_found || exponent_found || float_suffix_found) {
- //floats
+ } else if (period_found || exponent_found || float_suffix_found) { // Float
+ if (exponent_found && (!_is_number(last_char) && last_char != 'f')) { // checks for eg: "2E", "2E-", "2E+"
+ return _make_token(TK_ERROR, "Invalid (float) numeric constant");
+ }
if (period_found) {
if (float_suffix_found) {
//checks for eg "1.f" or "1.99f" notations
@@ -617,22 +672,28 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
}
if (float_suffix_found) {
- //strip the suffix
+ // Strip the suffix.
str = str.left(str.length() - 1);
- //compensate reading cursor position
+ // Compensate reading cursor position.
char_idx += 1;
}
if (!str.is_valid_float()) {
return _make_token(TK_ERROR, "Invalid (float) numeric constant");
}
- } else {
- //integers
- if (!_is_number(last_char)) {
- return _make_token(TK_ERROR, "Invalid (integer) numeric constant");
+ } else { // Integer
+ if (uint_suffix_found) {
+ // Strip the suffix.
+ str = str.left(str.length() - 1);
+ // Compensate reading cursor position.
+ char_idx += 1;
}
if (!str.is_valid_int()) {
- return _make_token(TK_ERROR, "Invalid numeric constant");
+ if (uint_suffix_found) {
+ return _make_token(TK_ERROR, "Invalid (unsigned integer) numeric constant");
+ } else {
+ return _make_token(TK_ERROR, "Invalid (integer) numeric constant");
+ }
}
}
@@ -640,6 +701,8 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
Token tk;
if (period_found || exponent_found || float_suffix_found) {
tk.type = TK_FLOAT_CONSTANT;
+ } else if (uint_suffix_found) {
+ tk.type = TK_UINT_CONSTANT;
} else {
tk.type = TK_INT_CONSTANT;
}
@@ -909,10 +972,10 @@ void ShaderLanguage::clear() {
completion_type = COMPLETION_NONE;
completion_block = nullptr;
completion_function = StringName();
- completion_class = SubClassTag::TAG_GLOBAL;
+ completion_class = TAG_GLOBAL;
completion_struct = StringName();
-
- unknown_varying_usages.clear();
+ completion_base = TYPE_VOID;
+ completion_base_array = false;
#ifdef DEBUG_ENABLED
used_constants.clear();
@@ -2654,6 +2717,8 @@ const ShaderLanguage::BuiltinFuncConstArgs ShaderLanguage::builtin_func_const_ar
{ nullptr, 0, 0, 0 }
};
+bool ShaderLanguage::is_const_suffix_lut_initialized = false;
+
bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionInfo &p_function_info, OperatorNode *p_func, DataType *r_ret_type, StringName *r_ret_type_str) {
ERR_FAIL_COND_V(p_func->op != OP_CALL && p_func->op != OP_CONSTRUCT, false);
@@ -2677,13 +2742,13 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
//stage based function
const StageFunctionInfo &sf = p_function_info.stage_functions[name];
if (argcount != sf.arguments.size()) {
- _set_error(vformat("Invalid number of arguments when calling stage function '%s', which expects %d arguments.", String(name), sf.arguments.size()));
+ _set_error(vformat(RTR("Invalid number of arguments when calling stage function '%s', which expects %d arguments."), String(name), sf.arguments.size()));
return false;
}
//validate arguments
for (int i = 0; i < argcount; i++) {
if (args[i] != sf.arguments[i].type) {
- _set_error(vformat("Invalid argument type when calling stage function '%s', type expected is '%s'.", String(name), String(get_datatype_name(sf.arguments[i].type))));
+ _set_error(vformat(RTR("Invalid argument type when calling stage function '%s', type expected is '%s'."), String(name), get_datatype_name(sf.arguments[i].type)));
return false;
}
}
@@ -2763,6 +2828,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
bool is_const = false;
ConstantNode::Value value;
+ value.sint = -1;
_find_identifier(p_block, false, p_function_info, vn->name, nullptr, nullptr, &is_const, nullptr, nullptr, &value);
if (!is_const || value.sint < min || value.sint > max) {
@@ -2786,7 +2852,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
}
}
if (error) {
- _set_error(vformat("Expected integer constant within %s..%s range.", min, max));
+ _set_error(vformat(RTR("Expected integer constant within [%d..%d] range."), min, max));
return false;
}
}
@@ -2805,7 +2871,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
}
if (arg_idx < argcount) {
if (p_func->arguments[arg_idx + 1]->type != Node::TYPE_VARIABLE && p_func->arguments[arg_idx + 1]->type != Node::TYPE_MEMBER && p_func->arguments[arg_idx + 1]->type != Node::TYPE_ARRAY) {
- _set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' is not a variable, array or member.");
+ _set_error(vformat(RTR("Argument %d of function '%s' is not a variable, array, or member."), arg_idx + 1, String(name)));
return false;
}
@@ -2829,7 +2895,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
fail = true;
} else {
if (shader->varyings.has(varname)) {
- _set_error(vformat("Varyings cannot be passed for '%s' parameter!", "out"));
+ _set_error(vformat(RTR("Varyings cannot be passed for the '%s' parameter."), "out"));
return false;
}
if (p_function_info.built_ins.has(varname)) {
@@ -2842,7 +2908,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
}
}
if (fail) {
- _set_error(vformat("Constant value cannot be passed for '%s' parameter!", "out"));
+ _set_error(vformat(RTR("A constant value cannot be passed for the '%s' parameter."), "out"));
return false;
}
@@ -2855,7 +2921,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
n = static_cast<const MemberNode *>(n)->owner;
}
if (n->type != Node::TYPE_VARIABLE && n->type != Node::TYPE_ARRAY) {
- _set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' is not a variable, array or member.");
+ _set_error(vformat(RTR("Argument %d of function '%s' is not a variable, array, or member."), arg_idx + 1, String(name)));
return false;
}
if (n->type == Node::TYPE_VARIABLE) {
@@ -2885,7 +2951,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
}
if (!valid) {
- _set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' can only take a local variable, array or member.");
+ _set_error(vformat(RTR("Argument %d of function '%s' can only take a local variable, array, or member."), arg_idx + 1, String(name)));
return false;
}
}
@@ -2932,16 +2998,15 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
arglist += get_datatype_name(builtin_func_defs[builtin_idx].args[i]);
}
- String err = "Built-in function \"" + String(name) + "(" + arglist + ")\" is supported only on high-end platform!";
- _set_error(err);
+ _set_error(vformat(RTR("Built-in function \"%s(%s)\" is only supported on high-end platforms."), String(name), arglist));
return false;
}
if (failed_builtin) {
- String err = "Invalid arguments for built-in function: " + String(name) + "(";
+ String arg_list;
for (int i = 0; i < argcount; i++) {
if (i > 0) {
- err += ",";
+ arg_list += ",";
}
String arg_name;
@@ -2955,10 +3020,9 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
arg_name += itos(args3[i]);
arg_name += "]";
}
- err += arg_name;
+ arg_list += arg_name;
}
- err += ")";
- _set_error(err);
+ _set_error(vformat(RTR("Invalid arguments for the built-in function: \"%s(%s)\"."), String(name), arg_list));
return false;
}
@@ -2975,7 +3039,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
}
if (name == exclude_function) {
- _set_error("Recursion is not allowed");
+ _set_error(RTR("Recursion is not allowed."));
return false;
}
@@ -2988,12 +3052,12 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
}
if (!shader->functions[i].callable) {
- _set_error("Function '" + String(name) + " can't be called from source code.");
+ _set_error(vformat(RTR("Function '%s' can't be called from source code."), String(name)));
return false;
}
FunctionNode *pfunc = shader->functions[i].function;
- if (arg_list == "") {
+ if (arg_list.is_empty()) {
for (int j = 0; j < pfunc->arguments.size(); j++) {
if (j > 0) {
arg_list += ", ";
@@ -3047,7 +3111,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
arg_name += "]";
}
- _set_error(vformat("Invalid argument for \"%s(%s)\" function: argument %s should be %s but is %s.", String(name), arg_list, j + 1, func_arg_name, arg_name));
+ _set_error(vformat(RTR("Invalid argument for \"%s(%s)\" function: argument %d should be %s but is %s."), String(name), arg_list, j + 1, func_arg_name, arg_name));
fail = true;
break;
}
@@ -3084,9 +3148,9 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
}
if (last_arg_count > args.size()) {
- _set_error(vformat("Too few arguments for \"%s(%s)\" call. Expected at least %s but received %s.", String(name), arg_list, last_arg_count, args.size()));
+ _set_error(vformat(RTR("Too few arguments for \"%s(%s)\" call. Expected at least %d but received %d."), String(name), arg_list, last_arg_count, args.size()));
} else if (last_arg_count < args.size()) {
- _set_error(vformat("Too many arguments for \"%s(%s)\" call. Expected at most %s but received %s.", String(name), arg_list, last_arg_count, args.size()));
+ _set_error(vformat(RTR("Too many arguments for \"%s(%s)\" call. Expected at most %d but received %d."), String(name), arg_list, last_arg_count, args.size()));
}
return false;
@@ -3124,7 +3188,7 @@ bool ShaderLanguage::_compare_datatypes(DataType p_datatype_a, String p_datatype
type_name2 += "]";
}
- _set_error("Invalid assignment of '" + type_name2 + "' to '" + type_name + "'");
+ _set_error(vformat(RTR("Invalid assignment of '%s' to '%s'."), type_name2, type_name));
}
return result;
}
@@ -3169,7 +3233,7 @@ bool ShaderLanguage::_parse_function_arguments(BlockNode *p_block, const Functio
return true;
} else if (tk.type != TK_COMMA) {
// something is broken
- _set_error("Expected ',' or ')' after argument");
+ _set_error(RTR("Expected ',' or ')' after argument."));
return false;
}
}
@@ -3229,6 +3293,10 @@ bool ShaderLanguage::is_token_operator_assign(TokenType p_type) {
p_type == TK_OP_ASSIGN_BIT_XOR);
}
+bool ShaderLanguage::is_token_hint(TokenType p_type) {
+ return int(p_type) > int(TK_RENDER_MODE) && int(p_type) < int(TK_SHADER_TYPE);
+}
+
bool ShaderLanguage::convert_constant(ConstantNode *p_constant, DataType p_to_type, ConstantNode::Value *p_value) {
if (p_constant->datatype == p_to_type) {
if (p_value) {
@@ -3295,16 +3363,16 @@ bool ShaderLanguage::is_float_type(DataType p_type) {
}
bool ShaderLanguage::is_sampler_type(DataType p_type) {
return p_type == TYPE_SAMPLER2D ||
- p_type == TYPE_ISAMPLER2D ||
- p_type == TYPE_USAMPLER2D ||
- p_type == TYPE_SAMPLER2DARRAY ||
- p_type == TYPE_ISAMPLER2DARRAY ||
- p_type == TYPE_USAMPLER2DARRAY ||
- p_type == TYPE_SAMPLER3D ||
- p_type == TYPE_ISAMPLER3D ||
- p_type == TYPE_USAMPLER3D ||
- p_type == TYPE_SAMPLERCUBE ||
- p_type == TYPE_SAMPLERCUBEARRAY;
+ p_type == TYPE_ISAMPLER2D ||
+ p_type == TYPE_USAMPLER2D ||
+ p_type == TYPE_SAMPLER2DARRAY ||
+ p_type == TYPE_ISAMPLER2DARRAY ||
+ p_type == TYPE_USAMPLER2DARRAY ||
+ p_type == TYPE_SAMPLER3D ||
+ p_type == TYPE_ISAMPLER3D ||
+ p_type == TYPE_USAMPLER3D ||
+ p_type == TYPE_SAMPLERCUBE ||
+ p_type == TYPE_SAMPLERCUBEARRAY;
}
Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::ConstantNode::Value> &p_value, DataType p_type, int p_array_size, ShaderLanguage::ShaderNode::Uniform::Hint p_hint) {
@@ -3796,55 +3864,77 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform
return pi;
}
-uint32_t ShaderLanguage::get_type_size(DataType p_type) {
+uint32_t ShaderLanguage::get_datatype_size(ShaderLanguage::DataType p_type) {
switch (p_type) {
case TYPE_VOID:
return 0;
case TYPE_BOOL:
- case TYPE_INT:
- case TYPE_UINT:
- case TYPE_FLOAT:
return 4;
case TYPE_BVEC2:
- case TYPE_IVEC2:
- case TYPE_UVEC2:
- case TYPE_VEC2:
return 8;
case TYPE_BVEC3:
- case TYPE_IVEC3:
- case TYPE_UVEC3:
- case TYPE_VEC3:
return 12;
case TYPE_BVEC4:
+ return 16;
+ case TYPE_INT:
+ return 4;
+ case TYPE_IVEC2:
+ return 8;
+ case TYPE_IVEC3:
+ return 12;
case TYPE_IVEC4:
+ return 16;
+ case TYPE_UINT:
+ return 4;
+ case TYPE_UVEC2:
+ return 8;
+ case TYPE_UVEC3:
+ return 12;
case TYPE_UVEC4:
+ return 16;
+ case TYPE_FLOAT:
+ return 4;
+ case TYPE_VEC2:
+ return 8;
+ case TYPE_VEC3:
+ return 12;
case TYPE_VEC4:
return 16;
case TYPE_MAT2:
- return 8;
+ return 32; // 4 * 4 + 4 * 4
case TYPE_MAT3:
- return 12;
+ return 48; // 4 * 4 + 4 * 4 + 4 * 4
case TYPE_MAT4:
- return 16;
+ return 64;
case TYPE_SAMPLER2D:
+ return 16;
case TYPE_ISAMPLER2D:
+ return 16;
case TYPE_USAMPLER2D:
+ return 16;
case TYPE_SAMPLER2DARRAY:
+ return 16;
case TYPE_ISAMPLER2DARRAY:
+ return 16;
case TYPE_USAMPLER2DARRAY:
+ return 16;
case TYPE_SAMPLER3D:
+ return 16;
case TYPE_ISAMPLER3D:
+ return 16;
case TYPE_USAMPLER3D:
+ return 16;
case TYPE_SAMPLERCUBE:
+ return 16;
case TYPE_SAMPLERCUBEARRAY:
- return 4; //not really, but useful for indices
+ return 16;
case TYPE_STRUCT:
- // FIXME: Implement.
- return 0;
- case ShaderLanguage::TYPE_MAX:
return 0;
+ case TYPE_MAX: {
+ ERR_FAIL_V(0);
+ };
}
- return 0;
+ ERR_FAIL_V(0);
}
void ShaderLanguage::get_keyword_list(List<String> *r_keywords) {
@@ -3872,16 +3962,16 @@ void ShaderLanguage::get_keyword_list(List<String> *r_keywords) {
bool ShaderLanguage::is_control_flow_keyword(String p_keyword) {
return p_keyword == "break" ||
- p_keyword == "case" ||
- p_keyword == "continue" ||
- p_keyword == "default" ||
- p_keyword == "do" ||
- p_keyword == "else" ||
- p_keyword == "for" ||
- p_keyword == "if" ||
- p_keyword == "return" ||
- p_keyword == "switch" ||
- p_keyword == "while";
+ p_keyword == "case" ||
+ p_keyword == "continue" ||
+ p_keyword == "default" ||
+ p_keyword == "do" ||
+ p_keyword == "else" ||
+ p_keyword == "for" ||
+ p_keyword == "if" ||
+ p_keyword == "return" ||
+ p_keyword == "switch" ||
+ p_keyword == "while";
}
void ShaderLanguage::get_builtin_funcs(List<String> *r_keywords) {
@@ -4050,43 +4140,6 @@ bool ShaderLanguage::_validate_varying_assign(ShaderNode::Varying &p_varying, St
return true;
}
-bool ShaderLanguage::_validate_varying_using(ShaderNode::Varying &p_varying, String *r_message) {
- switch (p_varying.stage) {
- case ShaderNode::Varying::STAGE_UNKNOWN:
- VaryingUsage usage;
- usage.var = &p_varying;
- usage.line = tk_line;
- unknown_varying_usages.push_back(usage);
- break;
- case ShaderNode::Varying::STAGE_VERTEX:
- if (current_function == varying_function_names.fragment || current_function == varying_function_names.light) {
- p_varying.stage = ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT_LIGHT;
- }
- break;
- case ShaderNode::Varying::STAGE_FRAGMENT:
- if (current_function == varying_function_names.light) {
- p_varying.stage = ShaderNode::Varying::STAGE_FRAGMENT_TO_LIGHT;
- }
- break;
- default:
- break;
- }
- return true;
-}
-
-bool ShaderLanguage::_check_varying_usages(int *r_error_line, String *r_error_message) const {
- for (const List<ShaderLanguage::VaryingUsage>::Element *E = unknown_varying_usages.front(); E; E = E->next()) {
- ShaderNode::Varying::Stage stage = E->get().var->stage;
- if (stage != ShaderNode::Varying::STAGE_UNKNOWN && stage != ShaderNode::Varying::STAGE_VERTEX && stage != ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT_LIGHT) {
- *r_error_line = E->get().line;
- *r_error_message = RTR("Fragment-stage varying could not been accessed in custom function!");
- return false;
- }
- }
-
- return true;
-}
-
bool ShaderLanguage::_check_node_constness(const Node *p_node) const {
switch (p_node->type) {
case Node::TYPE_OPERATOR: {
@@ -4192,14 +4245,14 @@ bool ShaderLanguage::_propagate_function_call_sampler_uniform_settings(StringNam
ERR_FAIL_INDEX_V(p_argument, shader->functions[i].function->arguments.size(), false);
FunctionNode::Argument *arg = &shader->functions[i].function->arguments.write[p_argument];
if (arg->tex_builtin_check) {
- _set_error("Sampler argument #" + itos(p_argument) + " of function '" + String(p_name) + "' called more than once using both built-ins and uniform textures, this is not supported (use either one or the other).");
+ _set_error(vformat(RTR("Sampler argument %d of function '%s' called more than once using both built-ins and uniform textures, this is not supported (use either one or the other)."), p_argument, String(p_name)));
return false;
} else if (arg->tex_argument_check) {
//was checked, verify that filter and repeat are the same
if (arg->tex_argument_filter == p_filter && arg->tex_argument_repeat == p_repeat) {
return true;
} else {
- _set_error("Sampler argument #" + itos(p_argument) + " of function '" + String(p_name) + "' called more than once using textures that differ in either filter or repeat setting.");
+ _set_error(vformat(RTR("Sampler argument %d of function '%s' called more than once using textures that differ in either filter or repeat setting."), p_argument, String(p_name)));
return false;
}
} else {
@@ -4226,14 +4279,14 @@ bool ShaderLanguage::_propagate_function_call_sampler_builtin_reference(StringNa
ERR_FAIL_INDEX_V(p_argument, shader->functions[i].function->arguments.size(), false);
FunctionNode::Argument *arg = &shader->functions[i].function->arguments.write[p_argument];
if (arg->tex_argument_check) {
- _set_error("Sampler argument #" + itos(p_argument) + " of function '" + String(p_name) + "' called more than once using both built-ins and uniform textures, this is not supported (use either one or the other).");
+ _set_error(vformat(RTR("Sampler argument %d of function '%s' called more than once using both built-ins and uniform textures, this is not supported (use either one or the other)."), p_argument, String(p_name)));
return false;
} else if (arg->tex_builtin_check) {
//was checked, verify that the built-in is the same
if (arg->tex_builtin == p_builtin) {
return true;
} else {
- _set_error("Sampler argument #" + itos(p_argument) + " of function '" + String(p_name) + "' called more than once using different built-ins. Only calling with the same built-in is supported.");
+ _set_error(vformat(RTR("Sampler argument %d of function '%s' called more than once using different built-ins. Only calling with the same built-in is supported."), p_argument, String(p_name)));
return false;
}
} else {
@@ -4254,113 +4307,87 @@ bool ShaderLanguage::_propagate_function_call_sampler_builtin_reference(StringNa
ERR_FAIL_V(false); //bug? function not found
}
-ShaderLanguage::Node *ShaderLanguage::_parse_array_size(BlockNode *p_block, const FunctionInfo &p_function_info, int &r_array_size) {
- int array_size = 0;
-
- Node *n = _parse_and_reduce_expression(p_block, p_function_info);
- if (n) {
- if (n->type == Node::TYPE_VARIABLE) {
- VariableNode *vn = static_cast<VariableNode *>(n);
- if (vn) {
- ConstantNode::Value v;
- DataType data_type;
- bool is_const = false;
-
- _find_identifier(p_block, false, p_function_info, vn->name, &data_type, nullptr, &is_const, nullptr, nullptr, &v);
-
- if (is_const) {
- if (data_type == TYPE_INT) {
- int32_t value = v.sint;
- if (value > 0) {
- array_size = value;
- }
- } else if (data_type == TYPE_UINT) {
- uint32_t value = v.uint;
- if (value > 0U) {
- array_size = value;
- }
- }
- }
- }
- } else if (n->type == Node::TYPE_OPERATOR) {
- _set_error("Array size expressions are not yet implemented.");
- return nullptr;
- }
- }
-
- r_array_size = array_size;
- return n;
-}
-
-Error ShaderLanguage::_parse_global_array_size(int &r_array_size) {
- if (r_array_size > 0) {
- _set_error("Array size is already defined!");
- return ERR_PARSE_ERROR;
- }
- TkPos pos = _get_tkpos();
- Token tk = _get_token();
-
- int array_size = 0;
-
- if (tk.type != TK_INT_CONSTANT || ((int)tk.constant) <= 0) {
- _set_tkpos(pos);
- Node *n = _parse_array_size(nullptr, FunctionInfo(), array_size);
- if (!n) {
- return ERR_PARSE_ERROR;
- }
- } else if (((int)tk.constant) > 0) {
- array_size = (uint32_t)tk.constant;
+Error ShaderLanguage::_parse_array_size(BlockNode *p_block, const FunctionInfo &p_function_info, bool p_forbid_unknown_size, Node **r_size_expression, int *r_array_size, bool *r_unknown_size) {
+ bool error = false;
+ if (r_array_size != nullptr && *r_array_size > 0) {
+ error = true;
}
-
- if (array_size <= 0) {
- _set_error("Expected single integer constant > 0");
- return ERR_PARSE_ERROR;
+ if (r_unknown_size != nullptr && *r_unknown_size) {
+ error = true;
}
-
- tk = _get_token();
- if (tk.type != TK_BRACKET_CLOSE) {
- _set_error("Expected ']'");
+ if (error) {
+ _set_error(vformat(RTR("Array size is already defined.")));
return ERR_PARSE_ERROR;
}
- r_array_size = array_size;
- return OK;
-}
-
-Error ShaderLanguage::_parse_local_array_size(BlockNode *p_block, const FunctionInfo &p_function_info, ArrayDeclarationNode *p_node, ArrayDeclarationNode::Declaration *p_decl, int &r_array_size, bool &r_is_unknown_size) {
TkPos pos = _get_tkpos();
Token tk = _get_token();
if (tk.type == TK_BRACKET_CLOSE) {
- r_is_unknown_size = true;
+ if (p_forbid_unknown_size) {
+ _set_error(vformat(RTR("Unknown array size is forbidden in that context.")));
+ return ERR_PARSE_ERROR;
+ }
+ if (r_unknown_size != nullptr) {
+ *r_unknown_size = true;
+ }
} else {
- if (tk.type != TK_INT_CONSTANT || ((int)tk.constant) <= 0) {
+ int array_size = 0;
+
+ if (!tk.is_integer_constant() || ((int)tk.constant) <= 0) {
_set_tkpos(pos);
- int array_size = 0;
- Node *n = _parse_array_size(p_block, p_function_info, array_size);
- if (!n) {
- return ERR_PARSE_ERROR;
+ Node *n = _parse_and_reduce_expression(p_block, p_function_info);
+ if (n) {
+ if (n->type == Node::TYPE_VARIABLE) {
+ VariableNode *vn = static_cast<VariableNode *>(n);
+ if (vn) {
+ ConstantNode::Value v;
+ DataType data_type;
+ bool is_const = false;
+
+ _find_identifier(p_block, false, p_function_info, vn->name, &data_type, nullptr, &is_const, nullptr, nullptr, &v);
+
+ if (is_const) {
+ if (data_type == TYPE_INT) {
+ int32_t value = v.sint;
+ if (value > 0) {
+ array_size = value;
+ }
+ } else if (data_type == TYPE_UINT) {
+ uint32_t value = v.uint;
+ if (value > 0U) {
+ array_size = value;
+ }
+ }
+ }
+ }
+ } else if (n->type == Node::TYPE_OPERATOR) {
+ _set_error(vformat(RTR("Array size expressions are not supported.")));
+ return ERR_PARSE_ERROR;
+ }
+ if (r_size_expression != nullptr) {
+ *r_size_expression = n;
+ }
}
- p_decl->size = array_size;
- p_node->size_expression = n;
} else if (((int)tk.constant) > 0) {
- p_decl->size = (uint32_t)tk.constant;
+ array_size = (uint32_t)tk.constant;
}
- if (p_decl->size <= 0) {
- _set_error("Expected single integer constant > 0");
+ if (array_size <= 0) {
+ _set_error(RTR("Expected a positive integer constant."));
return ERR_PARSE_ERROR;
}
tk = _get_token();
if (tk.type != TK_BRACKET_CLOSE) {
- _set_error("Expected ']'");
+ _set_expected_error("]");
return ERR_PARSE_ERROR;
}
- r_array_size = p_decl->size;
+ if (r_array_size != nullptr) {
+ *r_array_size = array_size;
+ }
}
-
return OK;
}
@@ -4380,49 +4407,20 @@ ShaderLanguage::Node *ShaderLanguage::_parse_array_constructor(BlockNode *p_bloc
struct_name = tk.text;
} else {
if (!is_token_variable_datatype(tk.type)) {
- _set_error("Invalid data type for array");
+ _set_error(RTR("Invalid data type for the array."));
return nullptr;
}
type = get_token_datatype(tk.type);
}
tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) {
- TkPos pos = _get_tkpos();
- tk = _get_token();
- if (tk.type == TK_BRACKET_CLOSE) {
- undefined_size = true;
- tk = _get_token();
- } else {
- _set_tkpos(pos);
-
- Node *n = _parse_and_reduce_expression(p_block, p_function_info);
- if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) {
- _set_error("Expected single integer constant > 0");
- return nullptr;
- }
-
- ConstantNode *cnode = (ConstantNode *)n;
- if (cnode->values.size() == 1) {
- array_size = cnode->values[0].sint;
- if (array_size <= 0) {
- _set_error("Expected single integer constant > 0");
- return nullptr;
- }
- } else {
- _set_error("Expected single integer constant > 0");
- return nullptr;
- }
-
- tk = _get_token();
- if (tk.type != TK_BRACKET_CLOSE) {
- _set_error("Expected ']'");
- return nullptr;
- } else {
- tk = _get_token();
- }
+ Error error = _parse_array_size(p_block, p_function_info, false, nullptr, &array_size, &undefined_size);
+ if (error != OK) {
+ return nullptr;
}
+ tk = _get_token();
} else {
- _set_error("Expected '['");
+ _set_expected_error("[");
return nullptr;
}
}
@@ -4460,20 +4458,20 @@ ShaderLanguage::Node *ShaderLanguage::_parse_array_constructor(BlockNode *p_bloc
break;
} else {
if (auto_size) {
- _set_error("Expected '}' or ','");
+ _set_expected_error("}", ",");
} else {
- _set_error("Expected ')' or ','");
+ _set_expected_error(")", ",");
}
return nullptr;
}
idx++;
}
if (!auto_size && !undefined_size && an->initializer.size() != array_size) {
- _set_error("Array size mismatch");
+ _set_error(RTR("Array size mismatch."));
return nullptr;
}
} else {
- _set_error("Expected array initialization!");
+ _set_error(RTR("Expected array initialization."));
return nullptr;
}
@@ -4503,7 +4501,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_array_constructor(BlockNode *p_bloc
Node *n = _parse_and_reduce_expression(p_block, p_function_info);
if (!n) {
- _set_error("Invalid data type for array");
+ _set_error(RTR("Invalid data type for the array."));
return nullptr;
}
@@ -4516,65 +4514,42 @@ ShaderLanguage::Node *ShaderLanguage::_parse_array_constructor(BlockNode *p_bloc
}
tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) {
- TkPos pos = _get_tkpos();
- tk = _get_token();
- if (tk.type == TK_BRACKET_CLOSE) {
+ bool is_unknown_size = false;
+ Error error = _parse_array_size(p_block, p_function_info, false, nullptr, &array_size, &is_unknown_size);
+ if (error != OK) {
+ return nullptr;
+ }
+ if (is_unknown_size) {
array_size = p_array_size;
- tk = _get_token();
- } else {
- _set_tkpos(pos);
-
- Node *n = _parse_and_reduce_expression(p_block, p_function_info);
- if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) {
- _set_error("Expected single integer constant > 0");
- return nullptr;
- }
-
- ConstantNode *cnode = (ConstantNode *)n;
- if (cnode->values.size() == 1) {
- array_size = cnode->values[0].sint;
- if (array_size <= 0) {
- _set_error("Expected single integer constant > 0");
- return nullptr;
- }
- } else {
- _set_error("Expected single integer constant > 0");
- return nullptr;
- }
-
- tk = _get_token();
- if (tk.type != TK_BRACKET_CLOSE) {
- _set_error("Expected ']'");
- return nullptr;
- } else {
- tk = _get_token();
- }
}
+ tk = _get_token();
} else {
- _set_error("Expected '['");
+ _set_expected_error("[");
return nullptr;
}
if (type != p_type || struct_name != p_struct_name || array_size != p_array_size) {
- String error_str = "Cannot convert from '";
+ String from;
if (type == TYPE_STRUCT) {
- error_str += struct_name;
+ from += struct_name;
} else {
- error_str += get_datatype_name(type);
+ from += get_datatype_name(type);
}
- error_str += "[";
- error_str += itos(array_size);
- error_str += "]'";
- error_str += " to '";
+ from += "[";
+ from += itos(array_size);
+ from += "]'";
+
+ String to;
if (type == TYPE_STRUCT) {
- error_str += p_struct_name;
+ to += p_struct_name;
} else {
- error_str += get_datatype_name(p_type);
+ to += get_datatype_name(p_type);
}
- error_str += "[";
- error_str += itos(p_array_size);
- error_str += "]'";
- _set_error(error_str);
+ to += "[";
+ to += itos(p_array_size);
+ to += "]'";
+
+ _set_error(vformat(RTR("Cannot convert from '%s' to '%s'."), from, to));
return nullptr;
}
}
@@ -4605,19 +4580,19 @@ ShaderLanguage::Node *ShaderLanguage::_parse_array_constructor(BlockNode *p_bloc
break;
} else {
if (auto_size) {
- _set_error("Expected '}' or ','");
+ _set_expected_error("}", ",");
} else {
- _set_error("Expected ')' or ','");
+ _set_expected_error(")", ",");
}
return nullptr;
}
}
if (an->initializer.size() != p_array_size) {
- _set_error("Array size mismatch");
+ _set_error(RTR("Array size mismatch."));
return nullptr;
}
} else {
- _set_error("Expected array initialization!");
+ _set_error(RTR("Expected array initialization."));
return nullptr;
}
@@ -4648,7 +4623,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
tk = _get_token();
if (tk.type != TK_PARENTHESIS_CLOSE) {
- _set_error("Expected ')' in expression");
+ _set_error(RTR("Expected ')' in expression."));
return nullptr;
}
@@ -4668,6 +4643,14 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
constant->datatype = TYPE_INT;
expr = constant;
+ } else if (tk.type == TK_UINT_CONSTANT) {
+ ConstantNode *constant = alloc_node<ConstantNode>();
+ ConstantNode::Value v;
+ v.uint = tk.constant;
+ constant->values.push_back(v);
+ constant->datatype = TYPE_UINT;
+ expr = constant;
+
} else if (tk.type == TK_TRUE) {
//handle true constant
ConstantNode *constant = alloc_node<ConstantNode>();
@@ -4688,7 +4671,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
} else if (tk.type == TK_TYPE_VOID) {
//make sure void is not used in expression
- _set_error("Void value not allowed in Expression");
+ _set_error(RTR("Void value not allowed in expression."));
return nullptr;
} else if (is_token_nonvoid_datatype(tk.type) || tk.type == TK_CURLY_BRACKET_OPEN) {
if (tk.type == TK_CURLY_BRACKET_OPEN) {
@@ -4717,7 +4700,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
expr = _parse_array_constructor(p_block, p_function_info);
} else {
if (tk.type != TK_PARENTHESIS_OPEN) {
- _set_error("Expected '(' after type name");
+ _set_error(RTR("Expected '(' after the type name."));
return nullptr;
}
//basic type constructor
@@ -4750,7 +4733,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
if (!_validate_function_call(p_block, p_function_info, func, &func->return_cache, &func->struct_name)) {
- _set_error("No matching constructor found for: '" + String(funcname->name) + "'");
+ _set_error(vformat(RTR("No matching constructor found for: '%s'."), String(funcname->name)));
return nullptr;
}
@@ -4769,11 +4752,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
if (shader->structs.has(identifier)) {
pstruct = shader->structs[identifier].shader_struct;
-#ifdef DEBUG_ENABLED
- if (check_warnings && HAS_WARNING(ShaderWarning::UNUSED_STRUCT_FLAG) && used_structs.has(identifier)) {
- used_structs[identifier].used = true;
- }
-#endif // DEBUG_ENABLED
struct_init = true;
}
@@ -4812,7 +4790,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
if (i + 1 < pstruct->members.size()) {
tk = _get_token();
if (tk.type != TK_COMMA) {
- _set_error("Expected ','");
+ _set_expected_error(",");
return nullptr;
}
}
@@ -4820,7 +4798,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
tk = _get_token();
if (tk.type != TK_PARENTHESIS_CLOSE) {
- _set_error("Expected ')'");
+ _set_expected_error(")");
return nullptr;
}
@@ -4844,7 +4822,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
ShaderLanguage::BlockNode *bnode = p_block;
while (bnode) {
if (bnode->variables.has(name)) {
- _set_error("Expected function name");
+ _set_error(RTR("Expected a function name."));
return nullptr;
}
bnode = bnode->parent_block;
@@ -4881,7 +4859,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
if (!_validate_function_call(p_block, p_function_info, func, &func->return_cache, &func->struct_name)) {
- _set_error("No matching function found for: '" + String(funcname->name) + "'");
+ _set_error(vformat(RTR("No matching function found for: '%s'."), String(funcname->name)));
return nullptr;
}
completion_class = TAG_GLOBAL; // reset sub-class
@@ -4915,53 +4893,104 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
for (int i = 0; i < call_function->arguments.size(); i++) {
int argidx = i + 1;
if (argidx < func->arguments.size()) {
- if (call_function->arguments[i].is_const || call_function->arguments[i].qualifier == ArgumentQualifier::ARGUMENT_QUALIFIER_OUT || call_function->arguments[i].qualifier == ArgumentQualifier::ARGUMENT_QUALIFIER_INOUT) {
- bool error = false;
- Node *n = func->arguments[argidx];
- if (n->type == Node::TYPE_CONSTANT || n->type == Node::TYPE_OPERATOR) {
- error = true;
+ bool error = false;
+ Node *n = func->arguments[argidx];
+ ArgumentQualifier arg_qual = call_function->arguments[i].qualifier;
+ bool is_out_arg = arg_qual != ArgumentQualifier::ARGUMENT_QUALIFIER_IN;
+
+ if (n->type == Node::TYPE_VARIABLE || n->type == Node::TYPE_ARRAY) {
+ StringName varname;
+
+ if (n->type == Node::TYPE_VARIABLE) {
+ VariableNode *vn = static_cast<VariableNode *>(n);
+ varname = vn->name;
+ } else { // TYPE_ARRAY
+ ArrayNode *an = static_cast<ArrayNode *>(n);
+ varname = an->name;
+ }
+
+ if (shader->varyings.has(varname)) {
+ switch (shader->varyings[varname].stage) {
+ case ShaderNode::Varying::STAGE_UNKNOWN: {
+ _set_error(vformat(RTR("Varying '%s' must be assigned in the vertex or fragment function first."), varname));
+ return nullptr;
+ }
+ case ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT_LIGHT:
+ [[fallthrough]];
+ case ShaderNode::Varying::STAGE_VERTEX:
+ if (is_out_arg && current_function != varying_function_names.vertex) { // inout/out
+ error = true;
+ }
+ break;
+ case ShaderNode::Varying::STAGE_FRAGMENT_TO_LIGHT:
+ [[fallthrough]];
+ case ShaderNode::Varying::STAGE_FRAGMENT:
+ if (!is_out_arg) {
+ if (current_function != varying_function_names.fragment && current_function != varying_function_names.light) {
+ error = true;
+ }
+ } else if (current_function != varying_function_names.fragment) { // inout/out
+ error = true;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (error) {
+ _set_error(vformat(RTR("Varying '%s' cannot be passed for the '%s' parameter in that context."), varname, _get_qualifier_str(arg_qual)));
+ return nullptr;
+ }
+ }
+ }
+
+ bool is_const_arg = call_function->arguments[i].is_const;
+
+ if (is_const_arg || is_out_arg) {
+ StringName varname;
+
+ if (n->type == Node::TYPE_CONSTANT || n->type == Node::TYPE_OPERATOR || n->type == Node::TYPE_ARRAY_CONSTRUCT) {
+ if (!is_const_arg) {
+ error = true;
+ }
} else if (n->type == Node::TYPE_ARRAY) {
ArrayNode *an = static_cast<ArrayNode *>(n);
- if (an->call_expression != nullptr || an->is_const) {
+ if (!is_const_arg && (an->call_expression != nullptr || an->is_const)) {
error = true;
}
+ varname = an->name;
} else if (n->type == Node::TYPE_VARIABLE) {
VariableNode *vn = static_cast<VariableNode *>(n);
- if (vn->is_const) {
+ if (vn->is_const && !is_const_arg) {
error = true;
- } else {
- StringName varname = vn->name;
- if (shader->constants.has(varname)) {
- error = true;
- } else if (shader->uniforms.has(varname)) {
- error = true;
- } else {
- if (shader->varyings.has(varname)) {
- _set_error(vformat("Varyings cannot be passed for '%s' parameter!", _get_qualifier_str(call_function->arguments[i].qualifier)));
- return nullptr;
- }
- if (p_function_info.built_ins.has(varname)) {
- BuiltInInfo info = p_function_info.built_ins[varname];
- if (info.constant) {
- error = true;
- }
- }
- }
}
+ varname = vn->name;
} else if (n->type == Node::TYPE_MEMBER) {
MemberNode *mn = static_cast<MemberNode *>(n);
- if (mn->basetype_const) {
+ if (mn->basetype_const && is_out_arg) {
error = true;
}
}
+ if (!error && varname != StringName()) {
+ if (shader->constants.has(varname)) {
+ error = true;
+ } else if (shader->uniforms.has(varname)) {
+ error = true;
+ } else if (p_function_info.built_ins.has(varname)) {
+ BuiltInInfo info = p_function_info.built_ins[varname];
+ if (info.constant) {
+ error = true;
+ }
+ }
+ }
+
if (error) {
- _set_error(vformat("Constant value cannot be passed for '%s' parameter!", _get_qualifier_str(call_function->arguments[i].qualifier)));
+ _set_error(vformat(RTR("A constant value cannot be passed for '%s' parameter."), _get_qualifier_str(arg_qual)));
return nullptr;
}
}
if (is_sampler_type(call_function->arguments[i].type)) {
//let's see where our argument comes from
- Node *n = func->arguments[argidx];
ERR_CONTINUE(n->type != Node::TYPE_VARIABLE); //bug? this should always be a variable
VariableNode *vn = static_cast<VariableNode *>(n);
StringName varname = vn->name;
@@ -5038,12 +5067,12 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
idx++;
}
if (!found) {
- _set_error("Unknown identifier in expression: " + String(identifier));
+ _set_error(vformat(RTR("Unknown identifier in expression: '%s'."), String(identifier)));
return nullptr;
}
} else {
if (!_find_identifier(p_block, false, p_function_info, identifier, &data_type, &ident_type, &is_const, &array_size, &struct_name)) {
- _set_error("Unknown identifier in expression: " + String(identifier));
+ _set_error(vformat(RTR("Unknown identifier in expression: '%s'."), String(identifier)));
return nullptr;
}
if (ident_type == IDENTIFIER_VARYING) {
@@ -5065,15 +5094,27 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
return nullptr;
}
} else {
- if (!_validate_varying_using(shader->varyings[identifier], &error)) {
- _set_error(error);
- return nullptr;
+ ShaderNode::Varying &var = shader->varyings[identifier];
+
+ switch (var.stage) {
+ case ShaderNode::Varying::STAGE_VERTEX:
+ if (current_function == varying_function_names.fragment || current_function == varying_function_names.light) {
+ var.stage = ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT_LIGHT;
+ }
+ break;
+ case ShaderNode::Varying::STAGE_FRAGMENT:
+ if (current_function == varying_function_names.light) {
+ var.stage = ShaderNode::Varying::STAGE_FRAGMENT_TO_LIGHT;
+ }
+ break;
+ default:
+ break;
}
}
}
if (ident_type == IDENTIFIER_FUNCTION) {
- _set_error("Can't use function as identifier: " + String(identifier));
+ _set_error(vformat(RTR("Can't use function as identifier: '%s'."), String(identifier)));
return nullptr;
}
if (is_const) {
@@ -5095,7 +5136,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
if (tk.type == TK_OP_ASSIGN) {
if (is_const) {
- _set_error("Constants cannot be modified.");
+ _set_error(RTR("Constants cannot be modified."));
return nullptr;
}
assign_expression = _parse_array_constructor(p_block, p_function_info, data_type, struct_name, array_size);
@@ -5118,7 +5159,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
if (index_expression->get_array_size() != 0 || (index_expression->get_datatype() != TYPE_INT && index_expression->get_datatype() != TYPE_UINT)) {
- _set_error("Only integer expressions are allowed for indexing.");
+ _set_error(RTR("Only integer expressions are allowed for indexing."));
return nullptr;
}
@@ -5128,7 +5169,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
if (!cnode->values.is_empty()) {
int value = cnode->values[0].sint;
if (value < 0 || value >= array_size) {
- _set_error(vformat("Index [%s] out of range [%s..%s]", value, 0, array_size - 1));
+ _set_error(vformat(RTR("Index [%d] out of range [%d..%d]."), value, 0, array_size - 1));
return nullptr;
}
}
@@ -5137,7 +5178,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
tk = _get_token();
if (tk.type != TK_BRACKET_CLOSE) {
- _set_error("Expected ']'");
+ _set_expected_error("]");
return nullptr;
}
} else {
@@ -5205,9 +5246,21 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
expression.push_back(e);
continue;
} else {
- _set_error("Expected expression, found: " + get_token_text(tk));
- return nullptr;
- //nothing
+ if (tk.type != TK_SEMICOLON) {
+ _set_error(vformat(RTR("Expected expression, found: '%s'."), get_token_text(tk)));
+ return nullptr;
+ } else {
+#ifdef DEBUG_ENABLED
+ if (check_warnings && HAS_WARNING(ShaderWarning::FORMATTING_ERROR_FLAG)) {
+ _add_line_warning(ShaderWarning::FORMATTING_ERROR, RTR("Empty statement. Remove ';' to fix this warning."));
+ }
+#endif // DEBUG_ENABLED
+ _set_tkpos(prepos);
+
+ OperatorNode *func = alloc_node<OperatorNode>();
+ func->op = OP_EMPTY;
+ expr = func;
+ }
}
ERR_FAIL_COND_V(!expr, nullptr);
@@ -5220,7 +5273,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
if (tk.type == TK_CURSOR) {
//do nothing
- } else if (tk.type == TK_IDENTIFIER) {
} else if (tk.type == TK_PERIOD) {
DataType dt = expr->get_datatype();
String st = expr->get_datatype_name();
@@ -5247,7 +5299,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
if (identifier == StringName()) {
- _set_error("Expected identifier as member");
+ _set_error(RTR("Expected an identifier as a member."));
return nullptr;
}
String ident = identifier;
@@ -5492,12 +5544,12 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
if (mix_error) {
- _set_error("Cannot combine symbols from different sets in expression ." + ident);
+ _set_error(vformat(RTR("Cannot combine symbols from different sets in expression '.%s'."), ident));
return nullptr;
}
if (!ok) {
- _set_error("Invalid member for " + (dt == TYPE_STRUCT ? st : get_datatype_name(dt)) + " expression: ." + ident);
+ _set_error(vformat(RTR("Invalid member for '%s' expression: '.%s'."), (dt == TYPE_STRUCT ? st : get_datatype_name(dt)), ident));
return nullptr;
}
@@ -5517,7 +5569,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
tk = _get_token();
if (tk.type == TK_OP_ASSIGN) {
if (last_type == IDENTIFIER_CONSTANT) {
- _set_error("Constants cannot be modified.");
+ _set_error(RTR("Constants cannot be modified."));
return nullptr;
}
Node *assign_expression = _parse_array_constructor(p_block, p_function_info, member_type, member_struct_name, array_size);
@@ -5542,7 +5594,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
if (index_expression->get_array_size() != 0 || (index_expression->get_datatype() != TYPE_INT && index_expression->get_datatype() != TYPE_UINT)) {
- _set_error("Only integer expressions are allowed for indexing.");
+ _set_error(RTR("Only integer expressions are allowed for indexing."));
return nullptr;
}
@@ -5552,7 +5604,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
if (!cnode->values.is_empty()) {
int value = cnode->values[0].sint;
if (value < 0 || value >= array_size) {
- _set_error(vformat("Index [%s] out of range [%s..%s]", value, 0, array_size - 1));
+ _set_error(vformat(RTR("Index [%d] out of range [%d..%d]."), value, 0, array_size - 1));
return nullptr;
}
}
@@ -5561,7 +5613,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
tk = _get_token();
if (tk.type != TK_BRACKET_CLOSE) {
- _set_error("Expected ']'");
+ _set_expected_error("]");
return nullptr;
}
mn->index_expression = index_expression;
@@ -5588,7 +5640,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
if (index->get_array_size() != 0 || (index->get_datatype() != TYPE_INT && index->get_datatype() != TYPE_UINT)) {
- _set_error("Only integer expressions are allowed for indexing.");
+ _set_error(RTR("Only integer expressions are allowed for indexing."));
return nullptr;
}
@@ -5599,7 +5651,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
if (index->type == Node::TYPE_CONSTANT) {
uint32_t index_constant = static_cast<ConstantNode *>(index)->values[0].uint;
if (index_constant >= (uint32_t)expr->get_array_size()) {
- _set_error(vformat("Index [%s] out of range [%s..%s]", index_constant, 0, expr->get_array_size() - 1));
+ _set_error(vformat(RTR("Index [%d] out of range [%d..%d]."), index_constant, 0, expr->get_array_size() - 1));
return nullptr;
}
}
@@ -5617,7 +5669,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
if (index->type == Node::TYPE_CONSTANT) {
uint32_t index_constant = static_cast<ConstantNode *>(index)->values[0].uint;
if (index_constant >= 2) {
- _set_error("Index out of range (0-1)");
+ _set_error(vformat(RTR("Index [%d] out of range [%d..%d]."), index_constant, 0, 1));
return nullptr;
}
}
@@ -5651,7 +5703,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
if (index->type == Node::TYPE_CONSTANT) {
uint32_t index_constant = static_cast<ConstantNode *>(index)->values[0].uint;
if (index_constant >= 3) {
- _set_error("Index out of range (0-2)");
+ _set_error(vformat(RTR("Index [%d] out of range [%d..%d]."), index_constant, 0, 2));
return nullptr;
}
}
@@ -5684,7 +5736,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
if (index->type == Node::TYPE_CONSTANT) {
uint32_t index_constant = static_cast<ConstantNode *>(index)->values[0].uint;
if (index_constant >= 4) {
- _set_error("Index out of range (0-3)");
+ _set_error(vformat(RTR("Index [%d] out of range [%d..%d]."), index_constant, 0, 3));
return nullptr;
}
}
@@ -5710,7 +5762,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
break;
default: {
- _set_error("Object of type '" + (expr->get_datatype() == TYPE_STRUCT ? expr->get_datatype_name() : get_datatype_name(expr->get_datatype())) + "' can't be indexed");
+ _set_error(vformat(RTR("An object of type '%s' can't be indexed."), (expr->get_datatype() == TYPE_STRUCT ? expr->get_datatype_name() : get_datatype_name(expr->get_datatype()))));
return nullptr;
}
}
@@ -5725,7 +5777,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
tk = _get_token();
if (tk.type != TK_BRACKET_CLOSE) {
- _set_error("Expected ']' after indexing expression");
+ _set_expected_error("]");
return nullptr;
}
@@ -5735,12 +5787,12 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
op->arguments.push_back(expr);
if (!_validate_operator(op, &op->return_cache, &op->return_array_size)) {
- _set_error("Invalid base type for increment/decrement operator");
+ _set_error(RTR("Invalid base type for increment/decrement operator."));
return nullptr;
}
if (!_validate_assign(expr, p_function_info)) {
- _set_error("Invalid use of increment/decrement operator in constant expression.");
+ _set_error(RTR("Invalid use of increment/decrement operator in a constant expression."));
return nullptr;
}
expr = op;
@@ -5857,7 +5909,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
o.op = OP_SELECT_ELSE;
break;
default: {
- _set_error("Invalid token for operator: " + get_token_text(tk));
+ _set_error(vformat(RTR("Invalid token for the operator: '%s'."), get_token_text(tk)));
return nullptr;
}
}
@@ -6009,7 +6061,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
ERR_FAIL_V(nullptr); //unexpected operator
}
-#if DEBUG_ENABLED
+#ifdef DEBUG_ENABLED
if (check_warnings && HAS_WARNING(ShaderWarning::FLOAT_COMPARISON_FLAG) && (op == OP_EQUAL || op == OP_NOT_EQUAL) &&
(!expression[i - 1].is_op && !expression[i + 1].is_op) &&
(expression[i - 1].node->get_datatype() == TYPE_FLOAT && expression[i + 1].node->get_datatype() == TYPE_FLOAT)) {
@@ -6036,7 +6088,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
expr_pos++;
if (expr_pos == expression.size()) {
//can happen..
- _set_error("Unexpected end of expression...");
+ _set_error(RTR("Unexpected end of expression."));
return nullptr;
}
}
@@ -6046,7 +6098,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
OperatorNode *op = alloc_node<OperatorNode>();
op->op = expression[i].op;
if ((op->op == OP_INCREMENT || op->op == OP_DECREMENT) && !_validate_assign(expression[i + 1].node, p_function_info)) {
- _set_error("Can't use increment/decrement operator in constant expression.");
+ _set_error(RTR("Can't use increment/decrement operator in a constant expression."));
return nullptr;
}
op->arguments.push_back(expression[i + 1].node);
@@ -6058,7 +6110,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
String at;
for (int j = 0; j < op->arguments.size(); j++) {
if (j > 0) {
- at += " and ";
+ at += ", ";
}
at += get_datatype_name(op->arguments[j]->get_datatype());
if (!op->arguments[j]->is_indexed() && op->arguments[j]->get_array_size() > 0) {
@@ -6067,20 +6119,20 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
at += "]";
}
}
- _set_error("Invalid arguments to unary operator '" + get_operator_text(op->op) + "' :" + at);
+ _set_error(vformat(RTR("Invalid arguments to unary operator '%s': %s."), get_operator_text(op->op), at));
return nullptr;
}
- expression.remove(i + 1);
+ expression.remove_at(i + 1);
}
} else if (is_ternary) {
if (next_op < 1 || next_op >= (expression.size() - 1)) {
- _set_error("Parser bug...");
+ _set_parsing_error();
ERR_FAIL_V(nullptr);
}
if (next_op + 2 >= expression.size() || !expression[next_op + 2].is_op || expression[next_op + 2].op != OP_SELECT_ELSE) {
- _set_error("Missing matching ':' for select operator");
+ _set_error(RTR("Missing matching ':' for select operator."));
return nullptr;
}
@@ -6096,7 +6148,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
String at;
for (int i = 0; i < op->arguments.size(); i++) {
if (i > 0) {
- at += " and ";
+ at += ", ";
}
at += get_datatype_name(op->arguments[i]->get_datatype());
if (!op->arguments[i]->is_indexed() && op->arguments[i]->get_array_size() > 0) {
@@ -6105,17 +6157,17 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
at += "]";
}
}
- _set_error("Invalid argument to ternary ?: operator: " + at);
+ _set_error(vformat(RTR("Invalid argument to ternary operator: '%s'."), at));
return nullptr;
}
for (int i = 0; i < 4; i++) {
- expression.remove(next_op);
+ expression.remove_at(next_op);
}
} else {
if (next_op < 1 || next_op >= (expression.size() - 1)) {
- _set_error("Parser bug...");
+ _set_parsing_error();
ERR_FAIL_V(nullptr);
}
@@ -6123,7 +6175,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
op->op = expression[next_op].op;
if (expression[next_op - 1].is_op) {
- _set_error("Parser bug...");
+ _set_parsing_error();
ERR_FAIL_V(nullptr);
}
@@ -6141,7 +6193,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
// can be followed by a unary op in a valid combination,
// due to how precedence works, unaries will always disappear first
- _set_error("Parser bug...");
+ _set_parsing_error();
}
op->arguments.push_back(expression[next_op - 1].node); //expression goes as left
@@ -6154,7 +6206,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
String at;
for (int i = 0; i < op->arguments.size(); i++) {
if (i > 0) {
- at += " and ";
+ at += ", ";
}
if (op->arguments[i]->get_datatype() == TYPE_STRUCT) {
at += op->arguments[i]->get_datatype_name();
@@ -6167,12 +6219,12 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
at += "]";
}
}
- _set_error("Invalid arguments to operator '" + get_operator_text(op->op) + "' :" + at);
+ _set_error(vformat(RTR("Invalid arguments to operator '%s': '%s'."), get_operator_text(op->op), at));
return nullptr;
}
- expression.remove(next_op);
- expression.remove(next_op);
+ expression.remove_at(next_op);
+ expression.remove_at(next_op);
}
}
@@ -6307,7 +6359,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
if (p_block && p_block->block_type == BlockNode::BLOCK_TYPE_SWITCH) {
if (tk.type != TK_CF_CASE && tk.type != TK_CF_DEFAULT && tk.type != TK_CURLY_BRACKET_CLOSE) {
- _set_error("Switch may contains only case and default blocks");
+ _set_error(vformat(RTR("A switch may only contain '%s' and '%s' blocks."), "case", "default"));
return ERR_PARSE_ERROR;
}
}
@@ -6316,7 +6368,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
if (tk.type == TK_CURLY_BRACKET_CLOSE) { //end of block
if (p_just_one) {
- _set_error("Unexpected '}'");
+ _set_expected_error("}");
return ERR_PARSE_ERROR;
}
@@ -6326,6 +6378,11 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
String struct_name = "";
if (is_struct) {
struct_name = tk.text;
+#ifdef DEBUG_ENABLED
+ if (check_warnings && HAS_WARNING(ShaderWarning::UNUSED_STRUCT_FLAG) && used_structs.has(struct_name)) {
+ used_structs[struct_name].used = true;
+ }
+#endif // DEBUG_ENABLED
}
bool is_const = false;
@@ -6349,18 +6406,18 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
is_struct = shader->structs.has(tk.text); // check again.
}
if (is_struct && precision != PRECISION_DEFAULT) {
- _set_error("Precision modifier cannot be used on structs.");
+ _set_error(RTR("The precision modifier cannot be used on structs."));
return ERR_PARSE_ERROR;
}
if (!is_token_nonvoid_datatype(tk.type)) {
- _set_error("Expected datatype after precision");
+ _set_error(RTR("Expected variable type after precision modifier."));
return ERR_PARSE_ERROR;
}
}
if (!is_struct) {
if (!is_token_variable_datatype(tk.type)) {
- _set_error("Invalid data type for variable (samplers not allowed)");
+ _set_error(RTR("Invalid variable type (samplers are not allowed)."));
return ERR_PARSE_ERROR;
}
}
@@ -6371,61 +6428,60 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
return ERR_PARSE_ERROR;
}
- tk = _get_token();
+ int array_size = 0;
+ bool fixed_array_size = false;
+ bool first = true;
- Node *vardecl = nullptr;
+ VariableDeclarationNode *vdnode = alloc_node<VariableDeclarationNode>();
+ vdnode->precision = precision;
+ if (is_struct) {
+ vdnode->struct_name = struct_name;
+ vdnode->datatype = TYPE_STRUCT;
+ } else {
+ vdnode->datatype = type;
+ };
+ vdnode->is_const = is_const;
- while (true) {
+ do {
bool unknown_size = false;
- int array_size = 0;
-
- ArrayDeclarationNode *anode = nullptr;
- ArrayDeclarationNode::Declaration adecl;
+ VariableDeclarationNode::Declaration decl;
- if (tk.type != TK_IDENTIFIER && tk.type != TK_BRACKET_OPEN) {
- _set_error("Expected identifier or '[' after type.");
- return ERR_PARSE_ERROR;
- }
+ tk = _get_token();
- if (tk.type == TK_BRACKET_OPEN) {
- anode = alloc_node<ArrayDeclarationNode>();
+ if (first) {
+ first = false;
- if (is_struct) {
- anode->struct_name = struct_name;
- anode->datatype = TYPE_STRUCT;
- } else {
- anode->datatype = type;
+ if (tk.type != TK_IDENTIFIER && tk.type != TK_BRACKET_OPEN) {
+ _set_error(RTR("Expected an identifier or '[' after type."));
+ return ERR_PARSE_ERROR;
}
- anode->precision = precision;
- anode->is_const = is_const;
- vardecl = (Node *)anode;
-
- adecl.size = 0U;
- adecl.single_expression = false;
+ if (tk.type == TK_BRACKET_OPEN) {
+ Error error = _parse_array_size(p_block, p_function_info, false, &decl.size_expression, &array_size, &unknown_size);
+ if (error != OK) {
+ return error;
+ }
+ decl.size = array_size;
- Error error = _parse_local_array_size(p_block, p_function_info, anode, &adecl, array_size, unknown_size);
- if (error != OK) {
- return error;
+ fixed_array_size = true;
+ tk = _get_token();
}
- tk = _get_token();
+ }
- if (tk.type != TK_IDENTIFIER) {
- _set_error("Expected identifier!");
- return ERR_PARSE_ERROR;
- }
+ if (tk.type != TK_IDENTIFIER) {
+ _set_error(RTR("Expected an identifier."));
+ return ERR_PARSE_ERROR;
}
StringName name = tk.text;
ShaderLanguage::IdentifierType itype;
if (_find_identifier(p_block, true, p_function_info, name, (ShaderLanguage::DataType *)nullptr, &itype)) {
if (itype != IDENTIFIER_FUNCTION) {
- _set_error("Redefinition of '" + String(name) + "'");
+ _set_redefinition_error(String(name));
return ERR_PARSE_ERROR;
}
}
-
- adecl.name = name;
+ decl.name = name;
#ifdef DEBUG_ENABLED
if (check_warnings && HAS_WARNING(ShaderWarning::UNUSED_LOCAL_VARIABLE_FLAG)) {
@@ -6452,34 +6508,19 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) {
- if (var.array_size > 0 || unknown_size) {
- _set_error("Array size is already defined!");
- return ERR_PARSE_ERROR;
- }
-
if (RenderingServer::get_singleton()->is_low_end() && is_const) {
- _set_error("Local const arrays are supported only on high-end platform!");
+ _set_error(RTR("Local const arrays are only supported on high-end platforms."));
return ERR_PARSE_ERROR;
}
- anode = alloc_node<ArrayDeclarationNode>();
- if (is_struct) {
- anode->struct_name = struct_name;
- anode->datatype = TYPE_STRUCT;
- } else {
- anode->datatype = type;
- }
- anode->precision = precision;
- anode->is_const = is_const;
- vardecl = (Node *)anode;
-
- adecl.size = 0U;
- adecl.single_expression = false;
-
- Error error = _parse_local_array_size(p_block, p_function_info, anode, &adecl, var.array_size, unknown_size);
+ Error error = _parse_array_size(p_block, p_function_info, false, &decl.size_expression, &var.array_size, &unknown_size);
if (error != OK) {
return error;
}
+
+ decl.size = var.array_size;
+ array_size = var.array_size;
+
tk = _get_token();
}
@@ -6488,7 +6529,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
if (tk.type == TK_OP_ASSIGN) {
if (RenderingServer::get_singleton()->is_low_end()) {
- _set_error("Array initialization is supported only on high-end platform!");
+ _set_error(RTR("Array initialization is only supported on high-end platforms."));
return ERR_PARSE_ERROR;
}
@@ -6500,11 +6541,11 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
Node *n = _parse_and_reduce_expression(p_block, p_function_info);
if (!n) {
- _set_error("Expected correct array initializer!");
+ _set_error(RTR("Expected array initializer."));
return ERR_PARSE_ERROR;
} else {
if (unknown_size) {
- adecl.size = n->get_array_size();
+ decl.size = n->get_array_size();
var.array_size = n->get_array_size();
}
@@ -6512,15 +6553,15 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
return ERR_PARSE_ERROR;
}
- adecl.single_expression = true;
- adecl.initializer.push_back(n);
+ decl.single_expression = true;
+ decl.initializer.push_back(n);
}
tk = _get_token();
} else {
if (tk.type != TK_CURLY_BRACKET_OPEN) {
if (unknown_size) {
- _set_error("Expected '{'");
+ _set_expected_error("{");
return ERR_PARSE_ERROR;
}
@@ -6531,11 +6572,11 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
precision2 = get_token_precision(tk.type);
tk = _get_token();
if (shader->structs.has(tk.text)) {
- _set_error("Precision modifier cannot be used on structs.");
+ _set_error(RTR("The precision modifier cannot be used on structs."));
return ERR_PARSE_ERROR;
}
if (!is_token_nonvoid_datatype(tk.type)) {
- _set_error("Expected datatype after precision");
+ _set_error(RTR("Expected data type after precision modifier."));
return ERR_PARSE_ERROR;
}
}
@@ -6548,7 +6589,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
struct_name2 = tk.text;
} else {
if (!is_token_variable_datatype(tk.type)) {
- _set_error("Invalid data type for array");
+ _set_error(RTR("Invalid data type for the array."));
return ERR_PARSE_ERROR;
}
type2 = get_token_datatype(tk.type);
@@ -6558,73 +6599,50 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) {
- TkPos pos2 = _get_tkpos();
- tk = _get_token();
- if (tk.type == TK_BRACKET_CLOSE) {
+ bool is_unknown_size = false;
+ Error error = _parse_array_size(p_block, p_function_info, false, nullptr, &array_size2, &is_unknown_size);
+ if (error != OK) {
+ return error;
+ }
+ if (is_unknown_size) {
array_size2 = var.array_size;
- tk = _get_token();
- } else {
- _set_tkpos(pos2);
-
- Node *n = _parse_and_reduce_expression(p_block, p_function_info);
- if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) {
- _set_error("Expected single integer constant > 0");
- return ERR_PARSE_ERROR;
- }
-
- ConstantNode *cnode = (ConstantNode *)n;
- if (cnode->values.size() == 1) {
- array_size2 = cnode->values[0].sint;
- if (array_size2 <= 0) {
- _set_error("Expected single integer constant > 0");
- return ERR_PARSE_ERROR;
- }
- } else {
- _set_error("Expected single integer constant > 0");
- return ERR_PARSE_ERROR;
- }
-
- tk = _get_token();
- if (tk.type != TK_BRACKET_CLOSE) {
- _set_error("Expected ']'");
- return ERR_PARSE_ERROR;
- } else {
- tk = _get_token();
- }
}
+ tk = _get_token();
} else {
- _set_error("Expected '['");
+ _set_expected_error("[");
return ERR_PARSE_ERROR;
}
if (precision != precision2 || type != type2 || struct_name != struct_name2 || var.array_size != array_size2) {
- String error_str = "Cannot convert from '";
+ String from;
if (precision2 != PRECISION_DEFAULT) {
- error_str += get_precision_name(precision2);
- error_str += " ";
+ from += get_precision_name(precision2);
+ from += " ";
}
if (type2 == TYPE_STRUCT) {
- error_str += struct_name2;
+ from += struct_name2;
} else {
- error_str += get_datatype_name(type2);
+ from += get_datatype_name(type2);
}
- error_str += "[";
- error_str += itos(array_size2);
- error_str += "]'";
- error_str += " to '";
+ from += "[";
+ from += itos(array_size2);
+ from += "]'";
+
+ String to;
if (precision != PRECISION_DEFAULT) {
- error_str += get_precision_name(precision);
- error_str += " ";
+ to += get_precision_name(precision);
+ to += " ";
}
if (type == TYPE_STRUCT) {
- error_str += struct_name;
+ to += struct_name;
} else {
- error_str += get_datatype_name(type);
+ to += get_datatype_name(type);
}
- error_str += "[";
- error_str += itos(var.array_size);
- error_str += "]'";
- _set_error(error_str);
+ to += "[";
+ to += itos(var.array_size);
+ to += "]'";
+
+ _set_error(vformat(RTR("Cannot convert from '%s' to '%s'."), from, to));
return ERR_PARSE_ERROR;
}
}
@@ -6633,13 +6651,13 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
if (unknown_size) {
if (!curly) {
- _set_error("Expected '{'");
+ _set_expected_error("{");
return ERR_PARSE_ERROR;
}
} else {
if (full_def) {
if (curly) {
- _set_error("Expected '('");
+ _set_expected_error("(");
return ERR_PARSE_ERROR;
}
}
@@ -6652,8 +6670,8 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
return ERR_PARSE_ERROR;
}
- if (anode->is_const && n->type == Node::TYPE_OPERATOR && ((OperatorNode *)n)->op == OP_CALL) {
- _set_error("Expected constant expression");
+ if (is_const && n->type == Node::TYPE_OPERATOR && ((OperatorNode *)n)->op == OP_CALL) {
+ _set_error(RTR("Expected a constant expression."));
return ERR_PARSE_ERROR;
}
@@ -6663,28 +6681,28 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
tk = _get_token();
if (tk.type == TK_COMMA) {
- adecl.initializer.push_back(n);
+ decl.initializer.push_back(n);
continue;
} else if (!curly && tk.type == TK_PARENTHESIS_CLOSE) {
- adecl.initializer.push_back(n);
+ decl.initializer.push_back(n);
break;
} else if (curly && tk.type == TK_CURLY_BRACKET_CLOSE) {
- adecl.initializer.push_back(n);
+ decl.initializer.push_back(n);
break;
} else {
if (curly) {
- _set_error("Expected '}' or ','");
+ _set_expected_error("}", ",");
} else {
- _set_error("Expected ')' or ','");
+ _set_expected_error(")", ",");
}
return ERR_PARSE_ERROR;
}
}
if (unknown_size) {
- adecl.size = adecl.initializer.size();
- var.array_size = adecl.initializer.size();
- } else if (adecl.initializer.size() != var.array_size) {
- _set_error("Array size mismatch");
+ decl.size = decl.initializer.size();
+ var.array_size = decl.initializer.size();
+ } else if (decl.initializer.size() != var.array_size) {
+ _set_error(RTR("Array size mismatch."));
return ERR_PARSE_ERROR;
}
tk = _get_token();
@@ -6692,47 +6710,31 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
}
} else {
if (unknown_size) {
- _set_error("Expected array initialization");
+ _set_error(RTR("Expected array initialization."));
return ERR_PARSE_ERROR;
}
- if (anode->is_const) {
- _set_error("Expected initialization of constant");
+ if (is_const) {
+ _set_error(RTR("Expected initialization of constant."));
return ERR_PARSE_ERROR;
}
}
- anode->declarations.push_back(adecl);
+ array_size = var.array_size;
} else if (tk.type == TK_OP_ASSIGN) {
- VariableDeclarationNode *node = alloc_node<VariableDeclarationNode>();
- if (is_struct) {
- node->struct_name = struct_name;
- node->datatype = TYPE_STRUCT;
- } else {
- node->datatype = type;
- }
- node->precision = precision;
- node->is_const = is_const;
- vardecl = (Node *)node;
-
- VariableDeclarationNode::Declaration decl;
- decl.name = name;
- decl.initializer = nullptr;
-
//variable created with assignment! must parse an expression
Node *n = _parse_and_reduce_expression(p_block, p_function_info);
if (!n) {
return ERR_PARSE_ERROR;
}
- if (node->is_const && n->type == Node::TYPE_OPERATOR && ((OperatorNode *)n)->op == OP_CALL) {
+ if (is_const && n->type == Node::TYPE_OPERATOR && ((OperatorNode *)n)->op == OP_CALL) {
OperatorNode *op = ((OperatorNode *)n);
for (int i = 1; i < op->arguments.size(); i++) {
if (!_check_node_constness(op->arguments[i])) {
- _set_error("Expected constant expression for argument '" + itos(i - 1) + "' of function call after '='");
+ _set_error(vformat(RTR("Expected constant expression for argument %d of function call after '='."), i - 1));
return ERR_PARSE_ERROR;
}
}
}
- decl.initializer = n;
if (n->type == Node::TYPE_CONSTANT) {
ConstantNode *const_node = static_cast<ConstantNode *>(n);
@@ -6744,47 +6746,37 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
if (!_compare_datatypes(var.type, var.struct_name, var.array_size, n->get_datatype(), n->get_datatype_name(), n->get_array_size())) {
return ERR_PARSE_ERROR;
}
+
+ decl.initializer.push_back(n);
tk = _get_token();
- node->declarations.push_back(decl);
} else {
if (is_const) {
- _set_error("Expected initialization of constant");
+ _set_error(RTR("Expected initialization of constant."));
return ERR_PARSE_ERROR;
}
+ }
- VariableDeclarationNode *node = alloc_node<VariableDeclarationNode>();
- if (is_struct) {
- node->struct_name = struct_name;
- node->datatype = TYPE_STRUCT;
- } else {
- node->datatype = type;
- }
- node->precision = precision;
- vardecl = (Node *)node;
+ vdnode->declarations.push_back(decl);
+ p_block->variables[name] = var;
- VariableDeclarationNode::Declaration decl;
- decl.name = name;
- decl.initializer = nullptr;
- node->declarations.push_back(decl);
+ if (!fixed_array_size) {
+ array_size = 0;
}
- p_block->statements.push_back(vardecl);
-
- p_block->variables[name] = var;
if (tk.type == TK_COMMA) {
if (p_block->block_type == BlockNode::BLOCK_TYPE_FOR) {
- _set_error("Multiple declarations in 'for' loop are not implemented yet.");
+ _set_error(vformat("Multiple declarations in '%s' loop are not supported.", "for"));
return ERR_PARSE_ERROR;
}
- tk = _get_token();
- //another variable
} else if (tk.type == TK_SEMICOLON) {
break;
} else {
- _set_error("Expected ',' or ';' after variable");
+ _set_expected_error(",", ";");
return ERR_PARSE_ERROR;
}
- }
+ } while (tk.type == TK_COMMA); //another variable
+
+ p_block->statements.push_back((Node *)vdnode);
} else if (tk.type == TK_CURLY_BRACKET_OPEN) {
//a sub block, just because..
BlockNode *block = alloc_node<BlockNode>();
@@ -6797,7 +6789,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
//if () {}
tk = _get_token();
if (tk.type != TK_PARENTHESIS_OPEN) {
- _set_error("Expected '(' after if");
+ _set_expected_after_error("(", "if");
return ERR_PARSE_ERROR;
}
@@ -6809,13 +6801,13 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
}
if (n->get_datatype() != TYPE_BOOL) {
- _set_error("Expected boolean expression");
+ _set_error(RTR("Expected a boolean expression."));
return ERR_PARSE_ERROR;
}
tk = _get_token();
if (tk.type != TK_PARENTHESIS_CLOSE) {
- _set_error("Expected ')' after expression");
+ _set_expected_error(")");
return ERR_PARSE_ERROR;
}
@@ -6837,20 +6829,22 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
block->parent_block = p_block;
cf->blocks.push_back(block);
err = _parse_block(block, p_function_info, true, p_can_break, p_can_continue);
-
+ if (err) {
+ return err;
+ }
} else {
_set_tkpos(pos); //rollback
}
} else if (tk.type == TK_CF_SWITCH) {
if (RenderingServer::get_singleton()->is_low_end()) {
- _set_error("\"switch\" operator is supported only on high-end platform!");
+ _set_error(vformat(RTR("The '%s' operator is only supported on high-end platforms."), "switch"));
return ERR_PARSE_ERROR;
}
// switch() {}
tk = _get_token();
if (tk.type != TK_PARENTHESIS_OPEN) {
- _set_error("Expected '(' after switch");
+ _set_expected_after_error("(", "switch");
return ERR_PARSE_ERROR;
}
ControlFlowNode *cf = alloc_node<ControlFlowNode>();
@@ -6860,17 +6854,17 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
return ERR_PARSE_ERROR;
}
if (n->get_datatype() != TYPE_INT) {
- _set_error("Expected integer expression");
+ _set_error(RTR("Expected an integer expression."));
return ERR_PARSE_ERROR;
}
tk = _get_token();
if (tk.type != TK_PARENTHESIS_CLOSE) {
- _set_error("Expected ')' after expression");
+ _set_expected_error(")");
return ERR_PARSE_ERROR;
}
tk = _get_token();
if (tk.type != TK_CURLY_BRACKET_OPEN) {
- _set_error("Expected '{' after switch statement");
+ _set_expected_after_error("{", "switch");
return ERR_PARSE_ERROR;
}
BlockNode *switch_block = alloc_node<BlockNode>();
@@ -6891,10 +6885,10 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
if (tk.type == TK_CF_CASE || tk.type == TK_CF_DEFAULT) {
if (prev_type == TK_CF_DEFAULT) {
if (tk.type == TK_CF_CASE) {
- _set_error("Cases must be defined before default case.");
+ _set_error(RTR("Cases must be defined before default case."));
return ERR_PARSE_ERROR;
} else if (prev_type == TK_CF_DEFAULT) {
- _set_error("Default case must be defined only once.");
+ _set_error(RTR("Default case must be defined only once."));
return ERR_PARSE_ERROR;
}
}
@@ -6913,7 +6907,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
return ERR_PARSE_ERROR;
}
if (constants.has(cn->values[0].sint)) {
- _set_error("Duplicated case label: '" + itos(cn->values[0].sint) + "'");
+ _set_error(vformat(RTR("Duplicated case label: %d."), cn->values[0].sint));
return ERR_PARSE_ERROR;
}
constants.insert(cn->values[0].sint);
@@ -6925,7 +6919,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
ConstantNode::Value v;
_find_identifier(p_block, false, p_function_info, vn->name, nullptr, nullptr, nullptr, nullptr, nullptr, &v);
if (constants.has(v.sint)) {
- _set_error("Duplicated case label: '" + itos(v.sint) + "'");
+ _set_error(vformat(RTR("Duplicated case label: %d."), v.sint));
return ERR_PARSE_ERROR;
}
constants.insert(v.sint);
@@ -6952,7 +6946,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
}
if (!p_block || (p_block->block_type != BlockNode::BLOCK_TYPE_SWITCH)) {
- _set_error("case must be placed within switch block");
+ _set_error(vformat(RTR("'%s' must be placed within a '%s' block."), "case", "switch"));
return ERR_PARSE_ERROR;
}
@@ -6967,7 +6961,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
Node *n = nullptr;
- if (tk.type != TK_INT_CONSTANT) {
+ if (!tk.is_integer_constant()) {
bool correct_constant_expression = false;
DataType data_type;
@@ -6981,7 +6975,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
}
}
if (!correct_constant_expression) {
- _set_error("Expected integer constant");
+ _set_error(RTR("Expected an integer constant."));
return ERR_PARSE_ERROR;
}
@@ -6990,18 +6984,22 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
n = vn;
} else {
ConstantNode::Value v;
- v.sint = (int)tk.constant * sign;
+ if (tk.type == TK_UINT_CONSTANT) {
+ v.uint = (uint32_t)tk.constant;
+ } else {
+ v.sint = (int)tk.constant * sign;
+ }
ConstantNode *cn = alloc_node<ConstantNode>();
cn->values.push_back(v);
- cn->datatype = TYPE_INT;
+ cn->datatype = (tk.type == TK_UINT_CONSTANT ? TYPE_UINT : TYPE_INT);
n = cn;
}
tk = _get_token();
if (tk.type != TK_COLON) {
- _set_error("Expected ':'");
+ _set_expected_error(":");
return ERR_PARSE_ERROR;
}
@@ -7029,14 +7027,14 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
}
if (!p_block || (p_block->block_type != BlockNode::BLOCK_TYPE_SWITCH)) {
- _set_error("default must be placed within switch block");
+ _set_error(vformat(RTR("'%s' must be placed within a '%s' block."), "default", "switch"));
return ERR_PARSE_ERROR;
}
tk = _get_token();
if (tk.type != TK_COLON) {
- _set_error("Expected ':'");
+ _set_expected_error(":");
return ERR_PARSE_ERROR;
}
@@ -7073,14 +7071,14 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
tk = _get_token();
if (tk.type != TK_CF_WHILE) {
- _set_error("Expected while after do");
+ _set_expected_after_error("while", "do");
return ERR_PARSE_ERROR;
}
}
tk = _get_token();
if (tk.type != TK_PARENTHESIS_OPEN) {
- _set_error("Expected '(' after while");
+ _set_expected_after_error("(", "while");
return ERR_PARSE_ERROR;
}
@@ -7097,7 +7095,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
tk = _get_token();
if (tk.type != TK_PARENTHESIS_CLOSE) {
- _set_error("Expected ')' after expression");
+ _set_expected_error(")");
return ERR_PARSE_ERROR;
}
if (!is_do) {
@@ -7118,7 +7116,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
tk = _get_token();
if (tk.type != TK_SEMICOLON) {
- _set_error("Expected ';'");
+ _set_expected_error(";");
return ERR_PARSE_ERROR;
}
}
@@ -7126,7 +7124,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
// for() {}
tk = _get_token();
if (tk.type != TK_PARENTHESIS_OPEN) {
- _set_error("Expected '(' after for");
+ _set_expected_after_error("(", "for");
return ERR_PARSE_ERROR;
}
@@ -7148,13 +7146,13 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
}
if (n->get_datatype() != TYPE_BOOL) {
- _set_error("Middle expression is expected to be boolean.");
+ _set_error(RTR("The middle expression is expected to be boolean."));
return ERR_PARSE_ERROR;
}
tk = _get_token();
if (tk.type != TK_SEMICOLON) {
- _set_error("Expected ';' after middle expression");
+ _set_expected_error(";");
return ERR_PARSE_ERROR;
}
@@ -7169,7 +7167,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
tk = _get_token();
if (tk.type != TK_PARENTHESIS_CLOSE) {
- _set_error("Expected ')' after third expression");
+ _set_expected_error(")");
return ERR_PARSE_ERROR;
}
@@ -7187,20 +7185,20 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
//check return type
BlockNode *b = p_block;
- if (b && b->parent_function && p_function_info.main_function) {
- _set_error(vformat("Using 'return' in '%s' processor function results in undefined behavior!", b->parent_function->name));
- return ERR_PARSE_ERROR;
- }
-
while (b && !b->parent_function) {
b = b->parent_block;
}
if (!b) {
- _set_error("Bug");
+ _set_parsing_error();
return ERR_BUG;
}
+ if (b && b->parent_function && p_function_info.main_function) {
+ _set_error(vformat(RTR("Using '%s' in the '%s' processor function is incorrect."), "return", b->parent_function->name));
+ return ERR_PARSE_ERROR;
+ }
+
String return_struct_name = String(b->parent_function->return_struct_name);
String array_size_string;
@@ -7216,7 +7214,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
if (tk.type == TK_SEMICOLON) {
//all is good
if (b->parent_function->return_type != TYPE_VOID) {
- _set_error("Expected return with an expression of type '" + (return_struct_name != "" ? return_struct_name : get_datatype_name(b->parent_function->return_type)) + array_size_string + "'");
+ _set_error(vformat(RTR("Expected '%s' with an expression of type '%s'."), "return", (!return_struct_name.is_empty() ? return_struct_name : get_datatype_name(b->parent_function->return_type)) + array_size_string));
return ERR_PARSE_ERROR;
}
} else {
@@ -7228,13 +7226,13 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
}
if (b->parent_function->return_type != expr->get_datatype() || b->parent_function->return_array_size != expr->get_array_size() || return_struct_name != expr->get_datatype_name()) {
- _set_error("Expected return with an expression of type '" + (return_struct_name != "" ? return_struct_name : get_datatype_name(b->parent_function->return_type)) + array_size_string + "'");
+ _set_error(vformat(RTR("Expected return with an expression of type '%s'."), (!return_struct_name.is_empty() ? return_struct_name : get_datatype_name(b->parent_function->return_type)) + array_size_string));
return ERR_PARSE_ERROR;
}
tk = _get_token();
if (tk.type != TK_SEMICOLON) {
- _set_error("Expected ';' after return expression");
+ _set_expected_after_error(";", "return");
return ERR_PARSE_ERROR;
}
@@ -7257,12 +7255,12 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
b = b->parent_block;
}
if (!b) {
- _set_error("Bug");
+ _set_parsing_error();
return ERR_BUG;
}
if (!b->parent_function->can_discard) {
- _set_error("Use of 'discard' is not allowed here.");
+ _set_error(vformat(RTR("Use of '%s' is not allowed here."), "discard"));
return ERR_PARSE_ERROR;
}
@@ -7272,14 +7270,14 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
pos = _get_tkpos();
tk = _get_token();
if (tk.type != TK_SEMICOLON) {
- _set_error("Expected ';' after discard");
+ _set_expected_after_error(";", "discard");
return ERR_PARSE_ERROR;
}
p_block->statements.push_back(flow);
} else if (tk.type == TK_CF_BREAK) {
if (!p_can_break) {
- _set_error("'break' is not allowed outside of a loop or 'switch' statement");
+ _set_error(vformat(RTR("'%s' is not allowed outside of a loop or '%s' statement."), "break", "switch"));
return ERR_PARSE_ERROR;
}
@@ -7289,7 +7287,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
pos = _get_tkpos();
tk = _get_token();
if (tk.type != TK_SEMICOLON) {
- _set_error("Expected ';' after break");
+ _set_expected_after_error(";", "break");
return ERR_PARSE_ERROR;
}
@@ -7305,7 +7303,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
} else if (tk.type == TK_CF_CONTINUE) {
if (!p_can_continue) {
- _set_error("'continue' is not allowed outside of a loop");
+ _set_error(vformat(RTR("'%s' is not allowed outside of a loop."), "continue"));
return ERR_PARSE_ERROR;
}
@@ -7316,7 +7314,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
tk = _get_token();
if (tk.type != TK_SEMICOLON) {
//all is good
- _set_error("Expected ';' after continue");
+ _set_expected_after_error(";", "continue");
return ERR_PARSE_ERROR;
}
@@ -7333,7 +7331,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
tk = _get_token();
if (tk.type != TK_SEMICOLON) {
- _set_error("Expected ';' after statement");
+ _set_expected_error(";");
return ERR_PARSE_ERROR;
}
}
@@ -7350,7 +7348,7 @@ String ShaderLanguage::_get_shader_type_list(const Set<String> &p_shader_types)
// Return a list of shader types as an human-readable string
String valid_types;
for (const Set<String>::Element *E = p_shader_types.front(); E; E = E->next()) {
- if (valid_types != String()) {
+ if (!valid_types.is_empty()) {
valid_types += ", ";
}
@@ -7394,35 +7392,31 @@ Error ShaderLanguage::_validate_datatype(DataType p_type) {
}
if (invalid_type) {
- _set_error(vformat("\"%s\" type is supported only on high-end platform!", get_datatype_name(p_type)));
+ _set_error(vformat(RTR("The \"%s\" type is only supported on high-end platforms."), get_datatype_name(p_type)));
return ERR_UNAVAILABLE;
}
}
return OK;
}
-Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types) {
+Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Vector<ModeInfo> &p_render_modes, const Set<String> &p_shader_types) {
Token tk = _get_token();
TkPos prev_pos;
if (tk.type != TK_SHADER_TYPE) {
- _set_error("Expected 'shader_type' at the beginning of shader. Valid types are: " + _get_shader_type_list(p_shader_types));
+ _set_error(vformat(RTR("Expected '%s' at the beginning of shader. Valid types are: %s."), "shader_type", _get_shader_type_list(p_shader_types)));
return ERR_PARSE_ERROR;
}
- tk = _get_token();
+ StringName shader_type_identifier;
+ _get_completable_identifier(nullptr, COMPLETION_SHADER_TYPE, shader_type_identifier);
- if (tk.type != TK_IDENTIFIER) {
- _set_error("Expected identifier after 'shader_type', indicating type of shader. Valid types are: " + _get_shader_type_list(p_shader_types));
+ if (shader_type_identifier == StringName()) {
+ _set_error(vformat(RTR("Expected an identifier after '%s', indicating the type of shader. Valid types are: %s."), "shader_type", _get_shader_type_list(p_shader_types)));
return ERR_PARSE_ERROR;
}
-
- String shader_type_identifier;
-
- shader_type_identifier = tk.text;
-
if (!p_shader_types.has(shader_type_identifier)) {
- _set_error("Invalid shader type. Valid types are: " + _get_shader_type_list(p_shader_types));
+ _set_error(vformat(RTR("Invalid shader type. Valid types are: %s"), _get_shader_type_list(p_shader_types)));
return ERR_PARSE_ERROR;
}
prev_pos = _get_tkpos();
@@ -7430,7 +7424,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
if (tk.type != TK_SEMICOLON) {
_set_tkpos(prev_pos);
- _set_error("Expected ';' after 'shader_type <type>'.");
+ _set_expected_after_error(";", "shader_type " + String(shader_type_identifier));
return ERR_PARSE_ERROR;
}
@@ -7440,9 +7434,27 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
int texture_binding = 0;
int uniforms = 0;
int instance_index = 0;
+#ifdef DEBUG_ENABLED
+ int uniform_buffer_size = 0;
+ int max_uniform_buffer_size = 0;
+ int uniform_buffer_exceeded_line = -1;
+
+ bool check_device_limit_warnings = false;
+ {
+ RenderingDevice *device = RenderingDevice::get_singleton();
+ if (device != nullptr) {
+ check_device_limit_warnings = check_warnings && HAS_WARNING(ShaderWarning::DEVICE_LIMIT_EXCEEDED_FLAG);
+
+ max_uniform_buffer_size = device->limit_get(RenderingDevice::LIMIT_MAX_UNIFORM_BUFFER_SIZE);
+ }
+ }
+#endif // DEBUG_ENABLED
ShaderNode::Uniform::Scope uniform_scope = ShaderNode::Uniform::SCOPE_LOCAL;
stages = &p_functions;
+ const FunctionInfo &constants = p_functions.has("constants") ? p_functions["constants"] : FunctionInfo();
+
+ Map<String, String> defined_modes;
while (tk.type != TK_EOF) {
switch (tk.type) {
@@ -7452,17 +7464,44 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
_get_completable_identifier(nullptr, COMPLETION_RENDER_MODE, mode);
if (mode == StringName()) {
- _set_error("Expected identifier for render mode");
+ _set_error(RTR("Expected an identifier for render mode."));
return ERR_PARSE_ERROR;
}
- if (p_render_modes.find(mode) == -1) {
- _set_error("Invalid render mode: '" + String(mode) + "'");
+ const String smode = String(mode);
+
+ if (shader->render_modes.find(mode) != -1) {
+ _set_error(vformat(RTR("Duplicated render mode: '%s'."), smode));
return ERR_PARSE_ERROR;
}
- if (shader->render_modes.find(mode) != -1) {
- _set_error("Duplicate render mode: '" + String(mode) + "'");
+ bool found = false;
+
+ for (int i = 0; i < p_render_modes.size(); i++) {
+ const ModeInfo &info = p_render_modes[i];
+ const String name = String(info.name);
+
+ if (smode.begins_with(name)) {
+ if (!info.options.is_empty()) {
+ if (info.options.find(smode.substr(name.length() + 1)) != -1) {
+ found = true;
+
+ if (defined_modes.has(name)) {
+ _set_error(vformat(RTR("Redefinition of render mode: '%s'. The '%s' mode has already been set to '%s'."), smode, name, defined_modes[name]));
+ return ERR_PARSE_ERROR;
+ }
+ defined_modes.insert(name, smode);
+ break;
+ }
+ } else {
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (!found) {
+ _set_error(vformat(RTR("Invalid render mode: '%s'."), smode));
return ERR_PARSE_ERROR;
}
@@ -7474,7 +7513,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
} else if (tk.type == TK_SEMICOLON) {
break; //done
} else {
- _set_error("Unexpected token: " + get_token_text(tk));
+ _set_error(vformat(RTR("Unexpected token: '%s'."), get_token_text(tk)));
return ERR_PARSE_ERROR;
}
}
@@ -7486,17 +7525,17 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
if (tk.type == TK_IDENTIFIER) {
st.name = tk.text;
- if (shader->structs.has(st.name)) {
- _set_error("Redefinition of '" + String(st.name) + "'");
+ if (shader->constants.has(st.name) || shader->structs.has(st.name)) {
+ _set_redefinition_error(String(st.name));
return ERR_PARSE_ERROR;
}
tk = _get_token();
if (tk.type != TK_CURLY_BRACKET_OPEN) {
- _set_error("Expected '{'");
+ _set_expected_error("{");
return ERR_PARSE_ERROR;
}
} else {
- _set_error("Expected struct identifier!");
+ _set_error(RTR("Expected a struct identifier."));
return ERR_PARSE_ERROR;
}
@@ -7516,7 +7555,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
DataPrecision precision = DataPrecision::PRECISION_DEFAULT;
if (tk.type == TK_STRUCT) {
- _set_error("nested structs are not allowed!");
+ _set_error(RTR("Nested structs are not allowed."));
return ERR_PARSE_ERROR;
}
@@ -7528,87 +7567,103 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
if (shader->structs.has(tk.text)) {
struct_name = tk.text;
+#ifdef DEBUG_ENABLED
+ if (check_warnings && HAS_WARNING(ShaderWarning::UNUSED_STRUCT_FLAG) && used_structs.has(struct_name)) {
+ used_structs[struct_name].used = true;
+ }
+#endif // DEBUG_ENABLED
struct_dt = true;
if (use_precision) {
- _set_error("Precision modifier cannot be used on structs.");
+ _set_error(RTR("The precision modifier cannot be used on structs."));
return ERR_PARSE_ERROR;
}
}
if (!is_token_datatype(tk.type) && !struct_dt) {
- _set_error("Expected datatype.");
+ _set_error(RTR("Expected data type."));
return ERR_PARSE_ERROR;
} else {
type = struct_dt ? TYPE_STRUCT : get_token_datatype(tk.type);
- if (is_sampler_type(type)) {
- _set_error("sampler datatype not allowed here");
- return ERR_PARSE_ERROR;
- } else if (type == TYPE_VOID) {
- _set_error("void datatype not allowed here");
- return ERR_PARSE_ERROR;
- }
- tk = _get_token();
-
- if (tk.type != TK_IDENTIFIER && tk.type != TK_BRACKET_OPEN) {
- _set_error("Expected identifier or '['.");
+ if (type == TYPE_VOID || is_sampler_type(type)) {
+ _set_error(vformat(RTR("A '%s' data type is not allowed here."), get_datatype_name(type)));
return ERR_PARSE_ERROR;
}
+ bool first = true;
+ bool fixed_array_size = false;
int array_size = 0;
- if (tk.type == TK_BRACKET_OPEN) {
- Error error = _parse_global_array_size(array_size);
- if (error != OK) {
- return error;
- }
+ do {
tk = _get_token();
- }
- if (tk.type != TK_IDENTIFIER) {
- _set_error("Expected identifier!");
- return ERR_PARSE_ERROR;
- }
+ if (first) {
+ first = false;
- MemberNode *member = alloc_node<MemberNode>();
- member->precision = precision;
- member->datatype = type;
- member->struct_name = struct_name;
- member->name = tk.text;
- member->array_size = array_size;
+ if (tk.type != TK_IDENTIFIER && tk.type != TK_BRACKET_OPEN) {
+ _set_error(RTR("Expected an identifier or '['."));
+ return ERR_PARSE_ERROR;
+ }
- if (member_names.has(member->name)) {
- _set_error("Redefinition of '" + String(member->name) + "'");
- return ERR_PARSE_ERROR;
- }
- member_names.insert(member->name);
- tk = _get_token();
+ if (tk.type == TK_BRACKET_OPEN) {
+ Error error = _parse_array_size(nullptr, constants, true, nullptr, &array_size, nullptr);
+ if (error != OK) {
+ return error;
+ }
+ fixed_array_size = true;
+ tk = _get_token();
+ }
+ }
- if (tk.type == TK_BRACKET_OPEN) {
- Error error = _parse_global_array_size(member->array_size);
- if (error != OK) {
- return error;
+ if (tk.type != TK_IDENTIFIER) {
+ _set_error(RTR("Expected an identifier."));
+ return ERR_PARSE_ERROR;
+ }
+
+ MemberNode *member = alloc_node<MemberNode>();
+ member->precision = precision;
+ member->datatype = type;
+ member->struct_name = struct_name;
+ member->name = tk.text;
+ member->array_size = array_size;
+
+ if (member_names.has(member->name)) {
+ _set_redefinition_error(String(member->name));
+ return ERR_PARSE_ERROR;
}
+ member_names.insert(member->name);
tk = _get_token();
- }
- if (tk.type != TK_SEMICOLON) {
- _set_error("Expected ';'");
- return ERR_PARSE_ERROR;
- }
+ if (tk.type == TK_BRACKET_OPEN) {
+ Error error = _parse_array_size(nullptr, constants, true, nullptr, &member->array_size, nullptr);
+ if (error != OK) {
+ return error;
+ }
+ tk = _get_token();
+ }
+
+ if (!fixed_array_size) {
+ array_size = 0;
+ }
+
+ if (tk.type != TK_SEMICOLON && tk.type != TK_COMMA) {
+ _set_expected_error(",", ";");
+ return ERR_PARSE_ERROR;
+ }
- st_node->members.push_back(member);
- member_count++;
+ st_node->members.push_back(member);
+ member_count++;
+ } while (tk.type == TK_COMMA); // another member
}
}
if (member_count == 0) {
- _set_error("Empty structs are not allowed!");
+ _set_error(RTR("Empty structs are not allowed."));
return ERR_PARSE_ERROR;
}
tk = _get_token();
if (tk.type != TK_SEMICOLON) {
- _set_error("Expected ';'");
+ _set_expected_error(";");
return ERR_PARSE_ERROR;
}
shader->structs[st.name] = st;
@@ -7622,7 +7677,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
case TK_GLOBAL: {
tk = _get_token();
if (tk.type != TK_UNIFORM) {
- _set_error("Expected 'uniform' after 'global'");
+ _set_expected_after_error("uniform", "global");
return ERR_PARSE_ERROR;
}
uniform_scope = ShaderNode::Uniform::SCOPE_GLOBAL;
@@ -7632,7 +7687,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
if (uniform_scope == ShaderNode::Uniform::SCOPE_LOCAL) {
tk = _get_token();
if (tk.type != TK_UNIFORM) {
- _set_error("Expected 'uniform' after 'instance'");
+ _set_expected_after_error("uniform", "instance");
return ERR_PARSE_ERROR;
}
uniform_scope = ShaderNode::Uniform::SCOPE_INSTANCE;
@@ -7644,8 +7699,8 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
bool uniform = tk.type == TK_UNIFORM;
if (!uniform) {
- if (shader_type_identifier == "particles" || shader_type_identifier == "sky") {
- _set_error(vformat("Varyings cannot be used in '%s' shaders!", shader_type_identifier));
+ if (shader_type_identifier == "particles" || shader_type_identifier == "sky" || shader_type_identifier == "fog") {
+ _set_error(vformat(RTR("Varyings cannot be used in '%s' shaders."), shader_type_identifier));
return ERR_PARSE_ERROR;
}
}
@@ -7660,7 +7715,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
if (is_token_interpolation(tk.type)) {
if (uniform) {
- _set_error("Interpolation qualifiers are not supported for uniforms!");
+ _set_error(RTR("Interpolation qualifiers are not supported for uniforms."));
return ERR_PARSE_ERROR;
}
interpolation = get_token_interpolation(tk.type);
@@ -7676,43 +7731,43 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
if (shader->structs.has(tk.text)) {
if (uniform) {
if (precision_defined) {
- _set_error("Precision modifier cannot be used on structs.");
+ _set_error(RTR("The precision modifier cannot be used on structs."));
return ERR_PARSE_ERROR;
}
- _set_error("struct datatype is not yet supported for uniforms!");
+ _set_error(vformat(RTR("The '%s' data type is not supported for uniforms."), "struct"));
return ERR_PARSE_ERROR;
} else {
- _set_error("struct datatype not allowed here");
+ _set_error(vformat(RTR("The '%s' data type not allowed here."), "struct"));
return ERR_PARSE_ERROR;
}
}
if (!is_token_datatype(tk.type)) {
- _set_error("Expected datatype. ");
+ _set_error(RTR("Expected data type."));
return ERR_PARSE_ERROR;
}
type = get_token_datatype(tk.type);
if (type == TYPE_VOID) {
- _set_error("void datatype not allowed here");
+ _set_error(vformat(RTR("The '%s' data type is not allowed here."), "void"));
return ERR_PARSE_ERROR;
}
if (!uniform && (type < TYPE_FLOAT || type > TYPE_MAT4)) {
- _set_error("Invalid type for varying, only float,vec2,vec3,vec4,mat2,mat3,mat4 or array of these types allowed.");
+ _set_error(RTR("Invalid type for varying, only 'float', 'vec2', 'vec3', 'vec4', 'mat2', 'mat3', 'mat4', or arrays of these types are allowed."));
return ERR_PARSE_ERROR;
}
tk = _get_token();
if (tk.type != TK_IDENTIFIER && tk.type != TK_BRACKET_OPEN) {
- _set_error("Expected identifier or '['.");
+ _set_error(RTR("Expected an identifier or '['."));
return ERR_PARSE_ERROR;
}
if (tk.type == TK_BRACKET_OPEN) {
- Error error = _parse_global_array_size(array_size);
+ Error error = _parse_array_size(nullptr, constants, true, nullptr, &array_size, nullptr);
if (error != OK) {
return error;
}
@@ -7720,20 +7775,20 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
if (tk.type != TK_IDENTIFIER) {
- _set_error("Expected identifier!");
+ _set_error(RTR("Expected an identifier."));
return ERR_PARSE_ERROR;
}
prev_pos = _get_tkpos();
name = tk.text;
- if (_find_identifier(nullptr, false, FunctionInfo(), name)) {
- _set_error("Redefinition of '" + String(name) + "'");
+ if (_find_identifier(nullptr, false, constants, name)) {
+ _set_redefinition_error(String(name));
return ERR_PARSE_ERROR;
}
if (has_builtin(p_functions, name)) {
- _set_error("Redefinition of '" + String(name) + "'");
+ _set_redefinition_error(String(name));
return ERR_PARSE_ERROR;
}
@@ -7742,12 +7797,12 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
//validate global uniform
DataType gvtype = global_var_get_type_func(name);
if (gvtype == TYPE_MAX) {
- _set_error("Global uniform '" + String(name) + "' does not exist. Create it in Project Settings.");
+ _set_error(vformat(RTR("Global uniform '%s' does not exist. Create it in Project Settings."), String(name)));
return ERR_PARSE_ERROR;
}
if (type != gvtype) {
- _set_error("Global uniform '" + String(name) + "' must be of type '" + get_datatype_name(gvtype) + "'.");
+ _set_error(vformat(RTR("Global uniform '%s' must be of type '%s'."), String(name), get_datatype_name(gvtype)));
return ERR_PARSE_ERROR;
}
}
@@ -7760,7 +7815,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) {
- Error error = _parse_global_array_size(uniform2.array_size);
+ Error error = _parse_array_size(nullptr, constants, true, nullptr, &uniform2.array_size, nullptr);
if (error != OK) {
return error;
}
@@ -7769,7 +7824,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
if (is_sampler_type(type)) {
if (uniform_scope == ShaderNode::Uniform::SCOPE_INSTANCE) {
- _set_error("Uniforms with 'instance' qualifiers can't be of sampler type.");
+ _set_error(vformat(RTR("Uniforms with '%s' qualifiers can't be of sampler type.", "instance")));
return ERR_PARSE_ERROR;
}
uniform2.texture_order = texture_uniforms++;
@@ -7785,22 +7840,40 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
} else {
if (uniform_scope == ShaderNode::Uniform::SCOPE_INSTANCE && (type == TYPE_MAT2 || type == TYPE_MAT3 || type == TYPE_MAT4)) {
- _set_error("Uniforms with 'instance' qualifiers can't be of matrix type.");
+ _set_error(vformat(RTR("Uniforms with '%s' qualifier can't be of matrix type.", "instance")));
return ERR_PARSE_ERROR;
}
uniform2.texture_order = -1;
if (uniform_scope != ShaderNode::Uniform::SCOPE_INSTANCE) {
uniform2.order = uniforms++;
+#ifdef DEBUG_ENABLED
+ if (check_device_limit_warnings) {
+ if (uniform2.array_size > 0) {
+ int size = get_datatype_size(uniform2.type) * uniform2.array_size;
+ int m = (16 * uniform2.array_size);
+ if ((size % m) != 0U) {
+ size += m - (size % m);
+ }
+ uniform_buffer_size += size;
+ } else {
+ uniform_buffer_size += get_datatype_size(uniform2.type);
+ }
+
+ if (uniform_buffer_exceeded_line == -1 && uniform_buffer_size > max_uniform_buffer_size) {
+ uniform_buffer_exceeded_line = tk_line;
+ }
+ }
+#endif // DEBUG_ENABLED
}
}
if (uniform2.array_size > 0) {
if (uniform_scope == ShaderNode::Uniform::SCOPE_GLOBAL) {
- _set_error("'SCOPE_GLOBAL' qualifier is not yet supported for uniform array!");
+ _set_error(vformat(RTR("The '%s' qualifier is not supported for uniform arrays."), "SCOPE_GLOBAL"));
return ERR_PARSE_ERROR;
}
if (uniform_scope == ShaderNode::Uniform::SCOPE_INSTANCE) {
- _set_error("'SCOPE_INSTANCE' qualifier is not yet supported for uniform array!");
+ _set_error(vformat(RTR("The '%s' qualifier is not supported for uniform arrays."), "SCOPE_INSTANCE"));
return ERR_PARSE_ERROR;
}
}
@@ -7808,13 +7881,23 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
int custom_instance_index = -1;
if (tk.type == TK_COLON) {
+ completion_type = COMPLETION_HINT;
+ completion_base = type;
+ completion_base_array = uniform2.array_size > 0;
+
//hint
do {
tk = _get_token();
+ completion_line = tk.line;
+
+ if (!is_token_hint(tk.type)) {
+ _set_error(RTR("Expected valid type hint after ':'."));
+ return ERR_PARSE_ERROR;
+ }
if (uniform2.array_size > 0) {
if (tk.type != TK_HINT_COLOR) {
- _set_error("This hint is not yet supported for uniform arrays!");
+ _set_error(RTR("This hint is not supported for uniform arrays."));
return ERR_PARSE_ERROR;
}
}
@@ -7837,28 +7920,28 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
uniform2.hint = ShaderNode::Uniform::HINT_ROUGHNESS_A;
} else if (tk.type == TK_HINT_ROUGHNESS_GRAY) {
uniform2.hint = ShaderNode::Uniform::HINT_ROUGHNESS_GRAY;
- } else if (tk.type == TK_HINT_ANISO_TEXTURE) {
- uniform2.hint = ShaderNode::Uniform::HINT_ANISO;
+ } else if (tk.type == TK_HINT_ANISOTROPY_TEXTURE) {
+ uniform2.hint = ShaderNode::Uniform::HINT_ANISOTROPY;
} else if (tk.type == TK_HINT_ALBEDO_TEXTURE) {
uniform2.hint = ShaderNode::Uniform::HINT_ALBEDO;
} else if (tk.type == TK_HINT_BLACK_ALBEDO_TEXTURE) {
uniform2.hint = ShaderNode::Uniform::HINT_BLACK_ALBEDO;
} else if (tk.type == TK_HINT_COLOR) {
if (type != TYPE_VEC4) {
- _set_error("Color hint is for vec4 only");
+ _set_error(vformat(RTR("Color hint is for '%s' only."), "vec4"));
return ERR_PARSE_ERROR;
}
uniform2.hint = ShaderNode::Uniform::HINT_COLOR;
} else if (tk.type == TK_HINT_RANGE) {
uniform2.hint = ShaderNode::Uniform::HINT_RANGE;
if (type != TYPE_FLOAT && type != TYPE_INT) {
- _set_error("Range hint is for float and int only");
+ _set_error(vformat(RTR("Range hint is for '%s' and '%s' only."), "float", "int"));
return ERR_PARSE_ERROR;
}
tk = _get_token();
if (tk.type != TK_PARENTHESIS_OPEN) {
- _set_error("Expected '(' after hint_range");
+ _set_expected_after_error("(", "hint_range");
return ERR_PARSE_ERROR;
}
@@ -7871,8 +7954,8 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
}
- if (tk.type != TK_FLOAT_CONSTANT && tk.type != TK_INT_CONSTANT) {
- _set_error("Expected integer constant");
+ if (tk.type != TK_FLOAT_CONSTANT && !tk.is_integer_constant()) {
+ _set_error(RTR("Expected an integer constant."));
return ERR_PARSE_ERROR;
}
@@ -7882,7 +7965,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
if (tk.type != TK_COMMA) {
- _set_error("Expected ',' after integer constant");
+ _set_error(RTR("Expected ',' after integer constant."));
return ERR_PARSE_ERROR;
}
@@ -7895,8 +7978,8 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
}
- if (tk.type != TK_FLOAT_CONSTANT && tk.type != TK_INT_CONSTANT) {
- _set_error("Expected integer constant after ','");
+ if (tk.type != TK_FLOAT_CONSTANT && !tk.is_integer_constant()) {
+ _set_error(RTR("Expected an integer constant after ','."));
return ERR_PARSE_ERROR;
}
@@ -7908,8 +7991,8 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
if (tk.type == TK_COMMA) {
tk = _get_token();
- if (tk.type != TK_FLOAT_CONSTANT && tk.type != TK_INT_CONSTANT) {
- _set_error("Expected integer constant after ','");
+ if (tk.type != TK_FLOAT_CONSTANT && !tk.is_integer_constant()) {
+ _set_error(RTR("Expected an integer constant after ','."));
return ERR_PARSE_ERROR;
}
@@ -7924,44 +8007,44 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
if (tk.type != TK_PARENTHESIS_CLOSE) {
- _set_error("Expected ')'");
+ _set_expected_error(")");
return ERR_PARSE_ERROR;
}
} else if (tk.type == TK_HINT_INSTANCE_INDEX) {
if (custom_instance_index != -1) {
- _set_error("Can only specify 'instance_index' once.");
+ _set_error(vformat(RTR("Can only specify '%s' once."), "instance_index"));
return ERR_PARSE_ERROR;
}
tk = _get_token();
if (tk.type != TK_PARENTHESIS_OPEN) {
- _set_error("Expected '(' after 'instance_index'");
+ _set_expected_after_error("(", "instance_index");
return ERR_PARSE_ERROR;
}
tk = _get_token();
if (tk.type == TK_OP_SUB) {
- _set_error("The instance index can't be negative.");
+ _set_error(RTR("The instance index can't be negative."));
return ERR_PARSE_ERROR;
}
- if (tk.type != TK_INT_CONSTANT) {
- _set_error("Expected integer constant");
+ if (!tk.is_integer_constant()) {
+ _set_error(RTR("Expected an integer constant."));
return ERR_PARSE_ERROR;
}
custom_instance_index = tk.constant;
if (custom_instance_index >= MAX_INSTANCE_UNIFORM_INDICES) {
- _set_error("Allowed instance uniform indices are 0-" + itos(MAX_INSTANCE_UNIFORM_INDICES - 1));
+ _set_error(vformat(RTR("Allowed instance uniform indices must be within [0..%d] range."), MAX_INSTANCE_UNIFORM_INDICES - 1));
return ERR_PARSE_ERROR;
}
tk = _get_token();
if (tk.type != TK_PARENTHESIS_CLOSE) {
- _set_error("Expected ')'");
+ _set_expected_error(")");
return ERR_PARSE_ERROR;
}
} else if (tk.type == TK_FILTER_LINEAR) {
@@ -7972,20 +8055,18 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
uniform2.filter = FILTER_NEAREST_MIPMAP;
} else if (tk.type == TK_FILTER_LINEAR_MIPMAP) {
uniform2.filter = FILTER_LINEAR_MIPMAP;
- } else if (tk.type == TK_FILTER_NEAREST_MIPMAP_ANISO) {
- uniform2.filter = FILTER_NEAREST_MIPMAP_ANISO;
- } else if (tk.type == TK_FILTER_LINEAR_MIPMAP_ANISO) {
- uniform2.filter = FILTER_LINEAR_MIPMAP_ANISO;
+ } else if (tk.type == TK_FILTER_NEAREST_MIPMAP_ANISOTROPIC) {
+ uniform2.filter = FILTER_NEAREST_MIPMAP_ANISOTROPIC;
+ } else if (tk.type == TK_FILTER_LINEAR_MIPMAP_ANISOTROPIC) {
+ uniform2.filter = FILTER_LINEAR_MIPMAP_ANISOTROPIC;
} else if (tk.type == TK_REPEAT_DISABLE) {
uniform2.repeat = REPEAT_DISABLE;
} else if (tk.type == TK_REPEAT_ENABLE) {
uniform2.repeat = REPEAT_ENABLE;
- } else {
- _set_error("Expected valid type hint after ':'.");
}
if (uniform2.hint != ShaderNode::Uniform::HINT_RANGE && uniform2.hint != ShaderNode::Uniform::HINT_NONE && uniform2.hint != ShaderNode::Uniform::HINT_COLOR && type <= TYPE_MAT4) {
- _set_error("This hint is only for sampler types");
+ _set_error(RTR("This hint is only for sampler types."));
return ERR_PARSE_ERROR;
}
@@ -8000,7 +8081,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
} else {
uniform2.instance_index = instance_index++;
if (instance_index > MAX_INSTANCE_UNIFORM_INDICES) {
- _set_error("Too many 'instance' uniforms in shader, maximum supported is " + itos(MAX_INSTANCE_UNIFORM_INDICES));
+ _set_error(vformat(RTR("Too many '%s' uniforms in shader, maximum supported is %d."), "instance", MAX_INSTANCE_UNIFORM_INDICES));
return ERR_PARSE_ERROR;
}
}
@@ -8010,16 +8091,16 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
if (tk.type == TK_OP_ASSIGN) {
if (uniform2.array_size > 0) {
- _set_error("Setting default value to a uniform array is not yet supported!");
+ _set_error(RTR("Setting default values to uniform arrays is not supported."));
return ERR_PARSE_ERROR;
}
- Node *expr = _parse_and_reduce_expression(nullptr, FunctionInfo());
+ Node *expr = _parse_and_reduce_expression(nullptr, constants);
if (!expr) {
return ERR_PARSE_ERROR;
}
if (expr->type != Node::TYPE_CONSTANT) {
- _set_error("Expected constant expression after '='");
+ _set_error(RTR("Expected constant expression after '='."));
return ERR_PARSE_ERROR;
}
@@ -8028,7 +8109,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
uniform2.default_value.resize(cn->values.size());
if (!convert_constant(cn, uniform2.type, uniform2.default_value.ptrw())) {
- _set_error("Can't convert constant to " + get_datatype_name(uniform2.type));
+ _set_error(vformat(RTR("Can't convert constant to '%s'."), get_datatype_name(uniform2.type)));
return ERR_PARSE_ERROR;
}
tk = _get_token();
@@ -8045,9 +8126,11 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
uniform_scope = ShaderNode::Uniform::SCOPE_LOCAL;
if (tk.type != TK_SEMICOLON) {
- _set_error("Expected ';'");
+ _set_expected_error(";");
return ERR_PARSE_ERROR;
}
+
+ completion_type = COMPLETION_NONE;
} else { // varying
ShaderNode::Varying varying;
varying.type = type;
@@ -8059,37 +8142,19 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
if (tk.type != TK_SEMICOLON && tk.type != TK_BRACKET_OPEN) {
if (array_size == 0) {
- _set_error("Expected ';' or '['");
+ _set_expected_error(";", "[");
} else {
- _set_error("Expected ';'");
+ _set_expected_error(";");
}
return ERR_PARSE_ERROR;
}
if (tk.type == TK_BRACKET_OPEN) {
- if (array_size > 0) {
- _set_error("Array size is already defined!");
- return ERR_PARSE_ERROR;
+ Error error = _parse_array_size(nullptr, constants, true, nullptr, &varying.array_size, nullptr);
+ if (error != OK) {
+ return error;
}
tk = _get_token();
- if (tk.type == TK_INT_CONSTANT && tk.constant > 0) {
- varying.array_size = (int)tk.constant;
-
- tk = _get_token();
- if (tk.type == TK_BRACKET_CLOSE) {
- tk = _get_token();
- if (tk.type != TK_SEMICOLON) {
- _set_error("Expected ';'");
- return ERR_PARSE_ERROR;
- }
- } else {
- _set_error("Expected ']'");
- return ERR_PARSE_ERROR;
- }
- } else {
- _set_error("Expected integer constant > 0");
- return ERR_PARSE_ERROR;
- }
}
shader->varyings[name] = varying;
@@ -8101,6 +8166,10 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
} break;
+ case TK_SHADER_TYPE: {
+ _set_error(RTR("Shader type is already defined."));
+ return ERR_PARSE_ERROR;
+ } break;
default: {
//function or constant variable
@@ -8110,7 +8179,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
DataPrecision precision = PRECISION_DEFAULT;
DataType type;
StringName name;
- int return_array_size = 0;
+ int array_size = 0;
if (tk.type == TK_CONST) {
is_constant = true;
@@ -8124,19 +8193,23 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
if (shader->structs.has(tk.text)) {
if (precision != PRECISION_DEFAULT) {
- _set_error("Precision modifier cannot be used on structs.");
+ _set_error(RTR("The precision modifier cannot be used on structs."));
return ERR_PARSE_ERROR;
}
is_struct = true;
struct_name = tk.text;
} else {
if (!is_token_datatype(tk.type)) {
- _set_error("Expected constant, function, uniform or varying");
+ _set_error(RTR("Expected constant, function, uniform or varying."));
return ERR_PARSE_ERROR;
}
if (!is_token_variable_datatype(tk.type)) {
- _set_error("Invalid data type for constants or function return (samplers not allowed)");
+ if (is_constant) {
+ _set_error(RTR("Invalid constant type (samplers are not allowed)."));
+ } else {
+ _set_error(RTR("Invalid function type (samplers are not allowed)."));
+ }
return ERR_PARSE_ERROR;
}
}
@@ -8149,29 +8222,19 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
prev_pos = _get_tkpos();
tk = _get_token();
- if (tk.type == TK_BRACKET_OPEN) {
- bool error = false;
- tk = _get_token();
+ bool unknown_size = false;
+ bool fixed_array_size = false;
- if (tk.type == TK_INT_CONSTANT) {
- return_array_size = (int)tk.constant;
- if (return_array_size > 0) {
- tk = _get_token();
- if (tk.type != TK_BRACKET_CLOSE) {
- _set_error("Expected ']'");
- return ERR_PARSE_ERROR;
- }
- } else {
- error = true;
- }
- } else {
- error = true;
- }
- if (error) {
- _set_error("Expected integer constant > 0");
+ if (tk.type == TK_BRACKET_OPEN) {
+ if (is_constant && RenderingServer::get_singleton()->is_low_end()) {
+ _set_error(RTR("Global constant arrays are only supported on high-end platforms."));
return ERR_PARSE_ERROR;
}
-
+ Error error = _parse_array_size(nullptr, constants, !is_constant, nullptr, &array_size, &unknown_size);
+ if (error != OK) {
+ return error;
+ }
+ fixed_array_size = true;
prev_pos = _get_tkpos();
}
@@ -8180,29 +8243,27 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
_get_completable_identifier(nullptr, COMPLETION_MAIN_FUNCTION, name);
if (name == StringName()) {
- _set_error("Expected function name after datatype");
- return ERR_PARSE_ERROR;
- }
-
- if (_find_identifier(nullptr, false, FunctionInfo(), name)) {
- _set_error("Redefinition of '" + String(name) + "'");
+ if (is_constant) {
+ _set_error(RTR("Expected an identifier or '[' after type."));
+ } else {
+ _set_error(RTR("Expected a function name after type."));
+ }
return ERR_PARSE_ERROR;
}
- if (has_builtin(p_functions, name)) {
- _set_error("Redefinition of '" + String(name) + "'");
+ if (shader->structs.has(name) || _find_identifier(nullptr, false, constants, name) || has_builtin(p_functions, name)) {
+ _set_redefinition_error(String(name));
return ERR_PARSE_ERROR;
}
tk = _get_token();
if (tk.type != TK_PARENTHESIS_OPEN) {
if (type == TYPE_VOID) {
- _set_error("Expected '(' after function identifier");
+ _set_error(RTR("Expected '(' after function identifier."));
return ERR_PARSE_ERROR;
}
//variable
-
while (true) {
ShaderNode::Constant constant;
constant.name = name;
@@ -8210,44 +8271,30 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
constant.type_str = struct_name;
constant.precision = precision;
constant.initializer = nullptr;
- constant.array_size = 0;
-
- bool unknown_size = false;
+ constant.array_size = array_size;
if (tk.type == TK_BRACKET_OPEN) {
if (RenderingServer::get_singleton()->is_low_end()) {
- _set_error("Global const arrays are supported only on high-end platform!");
+ _set_error(RTR("Global const arrays are only supported on high-end platforms."));
return ERR_PARSE_ERROR;
}
-
- tk = _get_token();
- if (tk.type == TK_BRACKET_CLOSE) {
- unknown_size = true;
- tk = _get_token();
- } else if (tk.type == TK_INT_CONSTANT && ((int)tk.constant) > 0) {
- constant.array_size = (int)tk.constant;
- tk = _get_token();
- if (tk.type != TK_BRACKET_CLOSE) {
- _set_error("Expected ']'");
- return ERR_PARSE_ERROR;
- }
- tk = _get_token();
- } else {
- _set_error("Expected integer constant > 0 or ']'");
- return ERR_PARSE_ERROR;
+ Error error = _parse_array_size(nullptr, constants, false, nullptr, &constant.array_size, &unknown_size);
+ if (error != OK) {
+ return error;
}
+ tk = _get_token();
}
if (tk.type == TK_OP_ASSIGN) {
if (!is_constant) {
- _set_error("Expected 'const' keyword before constant definition");
+ _set_error(vformat(RTR("Global non-constant variables are not supported. Expected '%s' keyword before constant definition."), "const"));
return ERR_PARSE_ERROR;
}
if (constant.array_size > 0 || unknown_size) {
bool full_def = false;
- ArrayDeclarationNode::Declaration decl;
+ VariableDeclarationNode::Declaration decl;
decl.name = name;
decl.size = constant.array_size;
@@ -8255,7 +8302,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
if (tk.type != TK_CURLY_BRACKET_OPEN) {
if (unknown_size) {
- _set_error("Expected '{'");
+ _set_expected_error("{");
return ERR_PARSE_ERROR;
}
@@ -8266,7 +8313,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
precision2 = get_token_precision(tk.type);
tk = _get_token();
if (!is_token_nonvoid_datatype(tk.type)) {
- _set_error("Expected datatype after precision");
+ _set_error(RTR("Expected data type after precision modifier."));
return ERR_PARSE_ERROR;
}
}
@@ -8279,83 +8326,60 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
struct_name2 = tk.text;
} else {
if (!is_token_variable_datatype(tk.type)) {
- _set_error("Invalid data type for array");
+ _set_error(RTR("Invalid data type for the array."));
return ERR_PARSE_ERROR;
}
type2 = get_token_datatype(tk.type);
}
int array_size2 = 0;
-
tk = _get_token();
+
if (tk.type == TK_BRACKET_OPEN) {
- prev_pos = _get_tkpos();
- tk = _get_token();
- if (tk.type == TK_BRACKET_CLOSE) {
+ bool is_unknown_size = false;
+ Error error = _parse_array_size(nullptr, constants, false, nullptr, &array_size2, &is_unknown_size);
+ if (error != OK) {
+ return error;
+ }
+ if (is_unknown_size) {
array_size2 = constant.array_size;
- tk = _get_token();
- } else {
- _set_tkpos(prev_pos);
-
- Node *n = _parse_and_reduce_expression(nullptr, FunctionInfo());
- if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) {
- _set_error("Expected single integer constant > 0");
- return ERR_PARSE_ERROR;
- }
-
- ConstantNode *cnode = (ConstantNode *)n;
- if (cnode->values.size() == 1) {
- array_size2 = cnode->values[0].sint;
- if (array_size2 <= 0) {
- _set_error("Expected single integer constant > 0");
- return ERR_PARSE_ERROR;
- }
- } else {
- _set_error("Expected single integer constant > 0");
- return ERR_PARSE_ERROR;
- }
-
- tk = _get_token();
- if (tk.type != TK_BRACKET_CLOSE) {
- _set_error("Expected ']");
- return ERR_PARSE_ERROR;
- } else {
- tk = _get_token();
- }
}
+ tk = _get_token();
} else {
- _set_error("Expected '[");
+ _set_expected_error("[");
return ERR_PARSE_ERROR;
}
if (constant.precision != precision2 || constant.type != type2 || struct_name != struct_name2 || constant.array_size != array_size2) {
- String error_str = "Cannot convert from '";
+ String from;
if (type2 == TYPE_STRUCT) {
- error_str += struct_name2;
+ from += struct_name2;
} else {
if (precision2 != PRECISION_DEFAULT) {
- error_str += get_precision_name(precision2);
- error_str += " ";
+ from += get_precision_name(precision2);
+ from += " ";
}
- error_str += get_datatype_name(type2);
+ from += get_datatype_name(type2);
}
- error_str += "[";
- error_str += itos(array_size2);
- error_str += "]'";
- error_str += " to '";
+ from += "[";
+ from += itos(array_size2);
+ from += "]'";
+
+ String to;
if (type == TYPE_STRUCT) {
- error_str += struct_name;
+ to += struct_name;
} else {
if (precision != PRECISION_DEFAULT) {
- error_str += get_precision_name(precision);
- error_str += " ";
+ to += get_precision_name(precision);
+ to += " ";
}
- error_str += get_datatype_name(type);
+ to += get_datatype_name(type);
}
- error_str += "[";
- error_str += itos(constant.array_size);
- error_str += "]'";
- _set_error(error_str);
+ to += "[";
+ to += itos(constant.array_size);
+ to += "]'";
+
+ _set_error(vformat(RTR("Cannot convert from '%s' to '%s'."), from, to));
return ERR_PARSE_ERROR;
}
}
@@ -8364,13 +8388,13 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
if (unknown_size) {
if (!curly) {
- _set_error("Expected '{'");
+ _set_expected_error("{");
return ERR_PARSE_ERROR;
}
} else {
if (full_def) {
if (curly) {
- _set_error("Expected '('");
+ _set_expected_error("(");
return ERR_PARSE_ERROR;
}
}
@@ -8378,13 +8402,13 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
if (tk.type == TK_PARENTHESIS_OPEN || curly) { // initialization
while (true) {
- Node *n = _parse_and_reduce_expression(nullptr, FunctionInfo());
+ Node *n = _parse_and_reduce_expression(nullptr, constants);
if (!n) {
return ERR_PARSE_ERROR;
}
if (n->type == Node::TYPE_OPERATOR && ((OperatorNode *)n)->op == OP_CALL) {
- _set_error("Expected constant expression");
+ _set_error(RTR("Expected constant expression."));
return ERR_PARSE_ERROR;
}
@@ -8404,9 +8428,9 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
break;
} else {
if (curly) {
- _set_error("Expected '}' or ','");
+ _set_expected_error("}", ",");
} else {
- _set_error("Expected ')' or ','");
+ _set_expected_error(")", ",");
}
return ERR_PARSE_ERROR;
}
@@ -8415,11 +8439,13 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
decl.size = decl.initializer.size();
constant.array_size = decl.initializer.size();
} else if (decl.initializer.size() != constant.array_size) {
- _set_error("Array size mismatch");
+ _set_error(RTR("Array size mismatch."));
return ERR_PARSE_ERROR;
}
}
+ array_size = constant.array_size;
+
ConstantNode *expr = memnew(ConstantNode);
expr->datatype = constant.type;
@@ -8433,7 +8459,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
constant.initializer = static_cast<ConstantNode *>(expr);
} else {
//variable created with assignment! must parse an expression
- Node *expr = _parse_and_reduce_expression(nullptr, FunctionInfo());
+ Node *expr = _parse_and_reduce_expression(nullptr, constants);
if (!expr) {
return ERR_PARSE_ERROR;
}
@@ -8441,7 +8467,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
OperatorNode *op = ((OperatorNode *)expr);
for (int i = 1; i < op->arguments.size(); i++) {
if (!_check_node_constness(op->arguments[i])) {
- _set_error("Expected constant expression for argument '" + itos(i - 1) + "' of function call after '='");
+ _set_error(vformat(RTR("Expected constant expression for argument %d of function call after '='."), i - 1));
return ERR_PARSE_ERROR;
}
}
@@ -8449,17 +8475,17 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
constant.initializer = static_cast<ConstantNode *>(expr);
- if (!_compare_datatypes(type, struct_name, 0, expr->get_datatype(), expr->get_datatype_name(), 0)) {
+ if (!_compare_datatypes(type, struct_name, 0, expr->get_datatype(), expr->get_datatype_name(), expr->get_array_size())) {
return ERR_PARSE_ERROR;
}
}
tk = _get_token();
} else {
if (constant.array_size > 0 || unknown_size) {
- _set_error("Expected array initialization");
+ _set_error(RTR("Expected array initialization."));
return ERR_PARSE_ERROR;
} else {
- _set_error("Expected initialization of constant");
+ _set_error(RTR("Expected initialization of constant."));
return ERR_PARSE_ERROR;
}
}
@@ -8475,27 +8501,32 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
if (tk.type == TK_COMMA) {
tk = _get_token();
if (tk.type != TK_IDENTIFIER) {
- _set_error("Expected identifier after type");
+ _set_error(RTR("Expected an identifier after type."));
return ERR_PARSE_ERROR;
}
name = tk.text;
- if (_find_identifier(nullptr, false, FunctionInfo(), name)) {
- _set_error("Redefinition of '" + String(name) + "'");
+ if (_find_identifier(nullptr, false, constants, name)) {
+ _set_redefinition_error(String(name));
return ERR_PARSE_ERROR;
}
if (has_builtin(p_functions, name)) {
- _set_error("Redefinition of '" + String(name) + "'");
+ _set_redefinition_error(String(name));
return ERR_PARSE_ERROR;
}
tk = _get_token();
+ if (!fixed_array_size) {
+ array_size = 0;
+ }
+ unknown_size = false;
+
} else if (tk.type == TK_SEMICOLON) {
break;
} else {
- _set_error("Expected ',' or ';' after constant");
+ _set_expected_error(",", ";");
return ERR_PARSE_ERROR;
}
}
@@ -8514,6 +8545,19 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
}
+ if (p_functions.has("constants")) { // Adds global constants: 'PI', 'TAU', 'E'
+ for (const KeyValue<StringName, BuiltInInfo> &E : p_functions["constants"].built_ins) {
+ builtins.built_ins.insert(E.key, E.value);
+ }
+ }
+
+ for (int i = 0; i < shader->functions.size(); i++) {
+ if (!shader->functions[i].callable && shader->functions[i].name == name) {
+ _set_redefinition_error(String(name));
+ return ERR_PARSE_ERROR;
+ }
+ }
+
ShaderNode::Function function;
function.callable = !p_functions.has(name);
@@ -8529,7 +8573,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
func_node->return_type = type;
func_node->return_struct_name = struct_name;
func_node->return_precision = precision;
- func_node->return_array_size = return_array_size;
+ func_node->return_array_size = array_size;
if (p_functions.has(name)) {
func_node->can_discard = p_functions[name].can_discard;
@@ -8564,14 +8608,14 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
} else if (tk.type == TK_ARG_OUT) {
if (is_const) {
- _set_error("'out' qualifier cannot be used within a function parameter declared with 'const'.");
+ _set_error(vformat(RTR("The '%s' qualifier cannot be used within a function parameter declared with '%s'."), "out", "const"));
return ERR_PARSE_ERROR;
}
qualifier = ARGUMENT_QUALIFIER_OUT;
tk = _get_token();
} else if (tk.type == TK_ARG_INOUT) {
if (is_const) {
- _set_error("'inout' qualifier cannot be used within a function parameter declared with 'const'.");
+ _set_error(vformat(RTR("The '%s' qualifier cannot be used within a function parameter declared with '%s'."), "inout", "const"));
return ERR_PARSE_ERROR;
}
qualifier = ARGUMENT_QUALIFIER_INOUT;
@@ -8583,7 +8627,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
StringName param_struct_name;
DataPrecision pprecision = PRECISION_DEFAULT;
bool use_precision = false;
- int array_size = 0;
+ int arg_array_size = 0;
if (is_token_precision(tk.type)) {
pprecision = get_token_precision(tk.type);
@@ -8596,20 +8640,25 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
if (shader->structs.has(tk.text)) {
is_struct = true;
param_struct_name = tk.text;
+#ifdef DEBUG_ENABLED
+ if (check_warnings && HAS_WARNING(ShaderWarning::UNUSED_STRUCT_FLAG) && used_structs.has(param_struct_name)) {
+ used_structs[param_struct_name].used = true;
+ }
+#endif // DEBUG_ENABLED
if (use_precision) {
- _set_error("Precision modifier cannot be used on structs.");
+ _set_error(RTR("The precision modifier cannot be used on structs."));
return ERR_PARSE_ERROR;
}
}
if (!is_struct && !is_token_datatype(tk.type)) {
- _set_error("Expected a valid datatype for argument");
+ _set_error(RTR("Expected a valid data type for argument."));
return ERR_PARSE_ERROR;
}
if (qualifier == ARGUMENT_QUALIFIER_OUT || qualifier == ARGUMENT_QUALIFIER_INOUT) {
if (is_sampler_type(get_token_datatype(tk.type))) {
- _set_error("Opaque types cannot be output parameters.");
+ _set_error(RTR("Opaque types cannot be output parameters."));
return ERR_PARSE_ERROR;
}
}
@@ -8622,7 +8671,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return ERR_PARSE_ERROR;
}
if (ptype == TYPE_VOID) {
- _set_error("void not allowed in argument");
+ _set_error(RTR("Void type not allowed as argument."));
return ERR_PARSE_ERROR;
}
}
@@ -8630,32 +8679,14 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) {
- bool error = false;
- tk = _get_token();
-
- if (tk.type == TK_INT_CONSTANT) {
- array_size = (int)tk.constant;
-
- if (array_size > 0) {
- tk = _get_token();
- if (tk.type != TK_BRACKET_CLOSE) {
- _set_error("Expected ']'");
- return ERR_PARSE_ERROR;
- }
- } else {
- error = true;
- }
- } else {
- error = true;
- }
- if (error) {
- _set_error("Expected integer constant > 0");
- return ERR_PARSE_ERROR;
+ Error error = _parse_array_size(nullptr, constants, true, nullptr, &arg_array_size, nullptr);
+ if (error != OK) {
+ return error;
}
tk = _get_token();
}
if (tk.type != TK_IDENTIFIER) {
- _set_error("Expected identifier for argument name");
+ _set_error(RTR("Expected an identifier for argument name."));
return ERR_PARSE_ERROR;
}
@@ -8664,13 +8695,13 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
ShaderLanguage::IdentifierType itype;
if (_find_identifier(func_node->body, false, builtins, pname, (ShaderLanguage::DataType *)nullptr, &itype)) {
if (itype != IDENTIFIER_FUNCTION) {
- _set_error("Redefinition of '" + String(pname) + "'");
+ _set_redefinition_error(String(pname));
return ERR_PARSE_ERROR;
}
}
if (has_builtin(p_functions, pname)) {
- _set_error("Redefinition of '" + String(pname) + "'");
+ _set_redefinition_error(String(pname));
return ERR_PARSE_ERROR;
}
@@ -8688,44 +8719,21 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) {
- if (array_size > 0) {
- _set_error("Array size is already defined!");
- return ERR_PARSE_ERROR;
- }
- bool error = false;
- tk = _get_token();
-
- if (tk.type == TK_INT_CONSTANT) {
- array_size = (int)tk.constant;
-
- if (array_size > 0) {
- tk = _get_token();
- if (tk.type != TK_BRACKET_CLOSE) {
- _set_error("Expected ']'");
- return ERR_PARSE_ERROR;
- }
- } else {
- error = true;
- }
- } else {
- error = true;
- }
-
- if (error) {
- _set_error("Expected integer constant > 0");
- return ERR_PARSE_ERROR;
+ Error error = _parse_array_size(nullptr, constants, true, nullptr, &arg_array_size, nullptr);
+ if (error != OK) {
+ return error;
}
tk = _get_token();
}
- arg.array_size = array_size;
+ arg.array_size = arg_array_size;
func_node->arguments.push_back(arg);
if (tk.type == TK_COMMA) {
tk = _get_token();
//do none and go on
} else if (tk.type != TK_PARENTHESIS_CLOSE) {
- _set_error("Expected ',' or ')' after identifier");
+ _set_expected_error(",", ")");
return ERR_PARSE_ERROR;
}
}
@@ -8733,11 +8741,11 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
if (p_functions.has(name)) {
//if one of the core functions, make sure they are of the correct form
if (func_node->arguments.size() > 0) {
- _set_error("Function '" + String(name) + "' expects no arguments.");
+ _set_error(vformat(RTR("Function '%s' expects no arguments."), String(name)));
return ERR_PARSE_ERROR;
}
if (func_node->return_type != TYPE_VOID) {
- _set_error("Function '" + String(name) + "' must be of void return type.");
+ _set_error(vformat(RTR("Function '%s' must be of '%s' return type."), String(name), "void"));
return ERR_PARSE_ERROR;
}
}
@@ -8745,7 +8753,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
//all good let's parse inside the function!
tk = _get_token();
if (tk.type != TK_CURLY_BRACKET_OPEN) {
- _set_error("Expected '{' to begin function");
+ _set_error(RTR("Expected a '{' to begin function."));
return ERR_PARSE_ERROR;
}
@@ -8759,7 +8767,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
if (func_node->return_type != DataType::TYPE_VOID) {
BlockNode *block = func_node->body;
if (_find_last_flow_op_in_block(block, FlowOperation::FLOW_OP_RETURN) != OK) {
- _set_error("Expected at least one return statement in a non-void function.");
+ _set_error(vformat(RTR("Expected at least one '%s' statement in a non-void function."), "return"));
return ERR_PARSE_ERROR;
}
}
@@ -8770,14 +8778,11 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
}
- int error_line;
- String error_message;
- if (!_check_varying_usages(&error_line, &error_message)) {
- _set_tkpos({ 0, error_line });
- _set_error(error_message);
- return ERR_PARSE_ERROR;
+#ifdef DEBUG_ENABLED
+ if (check_device_limit_warnings && uniform_buffer_exceeded_line != -1) {
+ _add_warning(ShaderWarning::DEVICE_LIMIT_EXCEEDED, uniform_buffer_exceeded_line, RTR("uniform buffer"), { uniform_buffer_size, max_uniform_buffer_size });
}
-
+#endif // DEBUG_ENABLED
return OK;
}
@@ -8897,7 +8902,7 @@ String ShaderLanguage::get_shader_type(const String &p_code) {
break;
} else if (p_code[i] <= 32) {
- if (cur_identifier != String()) {
+ if (!cur_identifier.is_empty()) {
if (!reading_type) {
if (cur_identifier != "shader_type") {
return String();
@@ -8957,17 +8962,17 @@ uint32_t ShaderLanguage::get_warning_flags() const {
}
#endif // DEBUG_ENABLED
-Error ShaderLanguage::compile(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const VaryingFunctionNames &p_varying_function_names, const Set<String> &p_shader_types, GlobalVariableGetTypeFunc p_global_variable_type_func) {
+Error ShaderLanguage::compile(const String &p_code, const ShaderCompileInfo &p_info) {
clear();
code = p_code;
- global_var_get_type_func = p_global_variable_type_func;
- varying_function_names = p_varying_function_names;
+ global_var_get_type_func = p_info.global_variable_type_func;
+ varying_function_names = p_info.varying_function_names;
nodes = nullptr;
shader = alloc_node<ShaderNode>();
- Error err = _parse_shader(p_functions, p_render_modes, p_shader_types);
+ Error err = _parse_shader(p_info.functions, p_info.render_modes, p_info.shader_types);
#ifdef DEBUG_ENABLED
if (check_warnings) {
@@ -8981,28 +8986,58 @@ Error ShaderLanguage::compile(const String &p_code, const Map<StringName, Functi
return OK;
}
-Error ShaderLanguage::complete(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const VaryingFunctionNames &p_varying_function_names, const Set<String> &p_shader_types, GlobalVariableGetTypeFunc p_global_variable_type_func, List<ScriptCodeCompletionOption> *r_options, String &r_call_hint) {
+Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_info, List<ScriptCodeCompletionOption> *r_options, String &r_call_hint) {
clear();
code = p_code;
- varying_function_names = p_varying_function_names;
+ varying_function_names = p_info.varying_function_names;
nodes = nullptr;
- global_var_get_type_func = p_global_variable_type_func;
+ global_var_get_type_func = p_info.global_variable_type_func;
shader = alloc_node<ShaderNode>();
- _parse_shader(p_functions, p_render_modes, p_shader_types);
+ _parse_shader(p_info.functions, p_info.render_modes, p_info.shader_types);
switch (completion_type) {
case COMPLETION_NONE: {
//do nothing
return OK;
} break;
- case COMPLETION_RENDER_MODE: {
- for (int i = 0; i < p_render_modes.size(); i++) {
- ScriptCodeCompletionOption option(p_render_modes[i], ScriptCodeCompletionOption::KIND_ENUM);
+ case COMPLETION_SHADER_TYPE: {
+ for (const String &shader_type : p_info.shader_types) {
+ ScriptCodeCompletionOption option(shader_type, ScriptCodeCompletionOption::KIND_PLAIN_TEXT);
r_options->push_back(option);
}
+ return OK;
+ } break;
+ case COMPLETION_RENDER_MODE: {
+ for (int i = 0; i < p_info.render_modes.size(); i++) {
+ const ModeInfo &info = p_info.render_modes[i];
+
+ if (!info.options.is_empty()) {
+ bool found = false;
+
+ for (int j = 0; j < info.options.size(); j++) {
+ if (shader->render_modes.has(String(info.name) + "_" + String(info.options[j]))) {
+ found = true;
+ }
+ }
+
+ if (!found) {
+ for (int j = 0; j < info.options.size(); j++) {
+ ScriptCodeCompletionOption option(String(info.name) + "_" + String(info.options[j]), ScriptCodeCompletionOption::KIND_PLAIN_TEXT);
+ r_options->push_back(option);
+ }
+ }
+ } else {
+ const String name = String(info.name);
+
+ if (!shader->render_modes.has(name)) {
+ ScriptCodeCompletionOption option(name, ScriptCodeCompletionOption::KIND_PLAIN_TEXT);
+ r_options->push_back(option);
+ }
+ }
+ }
return OK;
} break;
@@ -9018,7 +9053,7 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
return OK;
} break;
case COMPLETION_MAIN_FUNCTION: {
- for (const KeyValue<StringName, FunctionInfo> &E : p_functions) {
+ for (const KeyValue<StringName, FunctionInfo> &E : p_info.functions) {
ScriptCodeCompletionOption option(E.key, ScriptCodeCompletionOption::KIND_FUNCTION);
r_options->push_back(option);
}
@@ -9054,8 +9089,18 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
}
if (comp_ident) {
- if (p_functions.has("global")) {
- for (const KeyValue<StringName, BuiltInInfo> &E : p_functions["global"].built_ins) {
+ if (p_info.functions.has("global")) {
+ for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions["global"].built_ins) {
+ ScriptCodeCompletionOption::Kind kind = ScriptCodeCompletionOption::KIND_MEMBER;
+ if (E.value.constant) {
+ kind = ScriptCodeCompletionOption::KIND_CONSTANT;
+ }
+ matches.insert(E.key, kind);
+ }
+ }
+
+ if (p_info.functions.has("constants")) {
+ for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions["constants"].built_ins) {
ScriptCodeCompletionOption::Kind kind = ScriptCodeCompletionOption::KIND_MEMBER;
if (E.value.constant) {
kind = ScriptCodeCompletionOption::KIND_CONSTANT;
@@ -9064,8 +9109,8 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
}
}
- if (skip_function != StringName() && p_functions.has(skip_function)) {
- for (const KeyValue<StringName, BuiltInInfo> &E : p_functions[skip_function].built_ins) {
+ if (skip_function != StringName() && p_info.functions.has(skip_function)) {
+ for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions[skip_function].built_ins) {
ScriptCodeCompletionOption::Kind kind = ScriptCodeCompletionOption::KIND_MEMBER;
if (E.value.constant) {
kind = ScriptCodeCompletionOption::KIND_CONSTANT;
@@ -9074,6 +9119,9 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
}
}
+ for (const KeyValue<StringName, ShaderNode::Constant> &E : shader->constants) {
+ matches.insert(E.key, ScriptCodeCompletionOption::KIND_CONSTANT);
+ }
for (const KeyValue<StringName, ShaderNode::Varying> &E : shader->varyings) {
matches.insert(E.key, ScriptCodeCompletionOption::KIND_VARIABLE);
}
@@ -9369,15 +9417,6 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
limit = 4;
} break;
- case TYPE_MAT2:
- limit = 2;
- break;
- case TYPE_MAT3:
- limit = 3;
- break;
- case TYPE_MAT4:
- limit = 4;
- break;
default: {
}
}
@@ -9389,6 +9428,57 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
}
} break;
+ case COMPLETION_HINT: {
+ if (completion_base == DataType::TYPE_VEC4) {
+ ScriptCodeCompletionOption option("hint_color", ScriptCodeCompletionOption::KIND_PLAIN_TEXT);
+ r_options->push_back(option);
+ } else if ((completion_base == DataType::TYPE_INT || completion_base == DataType::TYPE_FLOAT) && !completion_base_array) {
+ ScriptCodeCompletionOption option("hint_range", ScriptCodeCompletionOption::KIND_PLAIN_TEXT);
+
+ if (completion_base == DataType::TYPE_INT) {
+ option.insert_text = "hint_range(0, 100, 1)";
+ } else {
+ option.insert_text = "hint_range(0.0, 1.0, 0.1)";
+ }
+
+ r_options->push_back(option);
+ } else if ((int(completion_base) > int(TYPE_MAT4) && int(completion_base) < int(TYPE_STRUCT)) && !completion_base_array) {
+ static Vector<String> options;
+
+ if (options.is_empty()) {
+ options.push_back("filter_linear");
+ options.push_back("filter_linear_mipmap");
+ options.push_back("filter_linear_mipmap_anisotropic");
+ options.push_back("filter_nearest");
+ options.push_back("filter_nearest_mipmap");
+ options.push_back("filter_nearest_mipmap_anisotropic");
+ options.push_back("hint_albedo");
+ options.push_back("hint_anisotropy");
+ options.push_back("hint_black");
+ options.push_back("hint_black_albedo");
+ options.push_back("hint_normal");
+ options.push_back("hint_roughness_a");
+ options.push_back("hint_roughness_b");
+ options.push_back("hint_roughness_g");
+ options.push_back("hint_roughness_gray");
+ options.push_back("hint_roughness_normal");
+ options.push_back("hint_roughness_r");
+ options.push_back("hint_white");
+ options.push_back("repeat_enable");
+ options.push_back("repeat_disable");
+ }
+
+ for (int i = 0; i < options.size(); i++) {
+ ScriptCodeCompletionOption option(options[i], ScriptCodeCompletionOption::KIND_PLAIN_TEXT);
+ r_options->push_back(option);
+ }
+ }
+ if (!completion_base_array) {
+ ScriptCodeCompletionOption option("instance_index", ScriptCodeCompletionOption::KIND_PLAIN_TEXT);
+ option.insert_text = "instance_index(0)";
+ r_options->push_back(option);
+ }
+ } break;
}
return ERR_PARSE_ERROR;
@@ -9410,7 +9500,7 @@ ShaderLanguage::ShaderLanguage() {
nodes = nullptr;
completion_class = TAG_GLOBAL;
-#if DEBUG_ENABLED
+#ifdef DEBUG_ENABLED
warnings_check_map.insert(ShaderWarning::UNUSED_CONSTANT, &used_constants);
warnings_check_map.insert(ShaderWarning::UNUSED_FUNCTION, &used_functions);
warnings_check_map.insert(ShaderWarning::UNUSED_STRUCT, &used_structs);
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index c82f71d10d..1307eeac2b 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -57,6 +57,7 @@ public:
TK_FALSE,
TK_FLOAT_CONSTANT,
TK_INT_CONSTANT,
+ TK_UINT_CONSTANT,
TK_TYPE_VOID,
TK_TYPE_BOOL,
TK_TYPE_BVEC2,
@@ -168,7 +169,7 @@ public:
TK_HINT_ROUGHNESS_B,
TK_HINT_ROUGHNESS_A,
TK_HINT_ROUGHNESS_GRAY,
- TK_HINT_ANISO_TEXTURE,
+ TK_HINT_ANISOTROPY_TEXTURE,
TK_HINT_ALBEDO_TEXTURE,
TK_HINT_BLACK_ALBEDO_TEXTURE,
TK_HINT_COLOR,
@@ -178,8 +179,8 @@ public:
TK_FILTER_LINEAR,
TK_FILTER_NEAREST_MIPMAP,
TK_FILTER_LINEAR_MIPMAP,
- TK_FILTER_NEAREST_MIPMAP_ANISO,
- TK_FILTER_LINEAR_MIPMAP_ANISO,
+ TK_FILTER_NEAREST_MIPMAP_ANISOTROPIC,
+ TK_FILTER_LINEAR_MIPMAP_ANISOTROPIC,
TK_REPEAT_ENABLE,
TK_REPEAT_DISABLE,
TK_SHADER_TYPE,
@@ -287,6 +288,7 @@ public:
OP_CONSTRUCT,
OP_STRUCT,
OP_INDEX,
+ OP_EMPTY,
OP_MAX
};
@@ -320,8 +322,8 @@ public:
FILTER_LINEAR,
FILTER_NEAREST_MIPMAP,
FILTER_LINEAR_MIPMAP,
- FILTER_NEAREST_MIPMAP_ANISO,
- FILTER_LINEAR_MIPMAP_ANISO,
+ FILTER_NEAREST_MIPMAP_ANISOTROPIC,
+ FILTER_LINEAR_MIPMAP_ANISOTROPIC,
FILTER_DEFAULT,
};
@@ -360,7 +362,6 @@ public:
TYPE_CONTROL_FLOW,
TYPE_MEMBER,
TYPE_ARRAY,
- TYPE_ARRAY_DECLARATION,
TYPE_ARRAY_CONSTRUCT,
TYPE_STRUCT,
};
@@ -426,7 +427,10 @@ public:
struct Declaration {
StringName name;
- Node *initializer;
+ uint32_t size = 0U;
+ Node *size_expression = nullptr;
+ Vector<Node *> initializer;
+ bool single_expression = false;
};
Vector<Declaration> declarations;
@@ -469,27 +473,6 @@ public:
Node(TYPE_ARRAY_CONSTRUCT) {}
};
- struct ArrayDeclarationNode : public Node {
- DataPrecision precision = PRECISION_DEFAULT;
- DataType datatype = TYPE_VOID;
- String struct_name;
- bool is_const = false;
- Node *size_expression = nullptr;
-
- struct Declaration {
- StringName name;
- uint32_t size;
- Vector<Node *> initializer;
- bool single_expression;
- };
- Vector<Declaration> declarations;
-
- virtual DataType get_datatype() const override { return datatype; }
-
- ArrayDeclarationNode() :
- Node(TYPE_ARRAY_DECLARATION) {}
- };
-
struct ConstantNode : public Node {
DataType datatype = TYPE_VOID;
String struct_name = "";
@@ -503,7 +486,7 @@ public:
};
Vector<Value> values;
- Vector<ArrayDeclarationNode::Declaration> array_declarations;
+ Vector<VariableDeclarationNode::Declaration> array_declarations;
virtual DataType get_datatype() const override { return datatype; }
virtual String get_datatype_name() const override { return struct_name; }
@@ -574,7 +557,7 @@ public:
virtual DataType get_datatype() const override { return datatype; }
virtual String get_datatype_name() const override { return String(struct_name); }
- virtual int get_array_size() const override { return array_size; }
+ virtual int get_array_size() const override { return (index_expression || call_expression) ? 0 : array_size; }
virtual bool is_indexed() const override { return index_expression != nullptr || call_expression != nullptr; }
MemberNode() :
@@ -680,7 +663,7 @@ public:
HINT_ROUGHNESS_GRAY,
HINT_BLACK,
HINT_WHITE,
- HINT_ANISO,
+ HINT_ANISOTROPY,
HINT_MAX
};
@@ -740,6 +723,7 @@ public:
enum CompletionType {
COMPLETION_NONE,
+ COMPLETION_SHADER_TYPE,
COMPLETION_RENDER_MODE,
COMPLETION_MAIN_FUNCTION,
COMPLETION_IDENTIFIER,
@@ -747,6 +731,7 @@ public:
COMPLETION_CALL_ARGUMENTS,
COMPLETION_INDEX,
COMPLETION_STRUCT,
+ COMPLETION_HINT,
};
struct Token {
@@ -754,6 +739,9 @@ public:
StringName text;
double constant;
uint16_t line;
+ bool is_integer_constant() const {
+ return type == TK_INT_CONSTANT || type == TK_UINT_CONSTANT;
+ }
};
static String get_operator_text(Operator p_op);
@@ -771,6 +759,7 @@ public:
static bool is_token_nonvoid_datatype(TokenType p_type);
static bool is_token_operator(TokenType p_type);
static bool is_token_operator_assign(TokenType p_type);
+ static bool is_token_hint(TokenType p_type);
static bool convert_constant(ConstantNode *p_constant, DataType p_to_type, ConstantNode::Value *p_value = nullptr);
static DataType get_scalar_type(DataType p_type);
@@ -780,7 +769,7 @@ public:
static bool is_sampler_type(DataType p_type);
static Variant constant_value_to_variant(const Vector<ShaderLanguage::ConstantNode::Value> &p_value, DataType p_type, int p_array_size, ShaderLanguage::ShaderNode::Uniform::Hint p_hint = ShaderLanguage::ShaderNode::Uniform::HINT_NONE);
static PropertyInfo uniform_to_property_info(const ShaderNode::Uniform &p_uniform);
- static uint32_t get_type_size(DataType p_type);
+ static uint32_t get_datatype_size(DataType p_type);
static void get_keyword_list(List<String> *r_keywords);
static bool is_control_flow_keyword(String p_keyword);
@@ -812,6 +801,57 @@ public:
DataType return_type = TYPE_VOID;
};
+ struct ModeInfo {
+ StringName name;
+ Vector<StringName> options;
+
+ ModeInfo() {}
+
+ ModeInfo(const StringName &p_name) :
+ name(p_name) {
+ }
+
+ ModeInfo(const StringName &p_name, const StringName &p_arg1, const StringName &p_arg2) :
+ name(p_name) {
+ options.push_back(p_arg1);
+ options.push_back(p_arg2);
+ }
+
+ ModeInfo(const StringName &p_name, const StringName &p_arg1, const StringName &p_arg2, const StringName &p_arg3) :
+ name(p_name) {
+ options.push_back(p_arg1);
+ options.push_back(p_arg2);
+ options.push_back(p_arg3);
+ }
+
+ ModeInfo(const StringName &p_name, const StringName &p_arg1, const StringName &p_arg2, const StringName &p_arg3, const StringName &p_arg4) :
+ name(p_name) {
+ options.push_back(p_arg1);
+ options.push_back(p_arg2);
+ options.push_back(p_arg3);
+ options.push_back(p_arg4);
+ }
+
+ ModeInfo(const StringName &p_name, const StringName &p_arg1, const StringName &p_arg2, const StringName &p_arg3, const StringName &p_arg4, const StringName &p_arg5) :
+ name(p_name) {
+ options.push_back(p_arg1);
+ options.push_back(p_arg2);
+ options.push_back(p_arg3);
+ options.push_back(p_arg4);
+ options.push_back(p_arg5);
+ }
+
+ ModeInfo(const StringName &p_name, const StringName &p_arg1, const StringName &p_arg2, const StringName &p_arg3, const StringName &p_arg4, const StringName &p_arg5, const StringName &p_arg6) :
+ name(p_name) {
+ options.push_back(p_arg1);
+ options.push_back(p_arg2);
+ options.push_back(p_arg3);
+ options.push_back(p_arg4);
+ options.push_back(p_arg5);
+ options.push_back(p_arg6);
+ }
+ };
+
struct FunctionInfo {
Map<StringName, BuiltInInfo> built_ins;
Map<StringName, StageFunctionInfo> stage_functions;
@@ -861,11 +901,14 @@ private:
bool check_warnings = false;
uint32_t warning_flags;
- void _add_line_warning(ShaderWarning::Code p_code, const StringName &p_subject = "") {
- warnings.push_back(ShaderWarning(p_code, tk_line, p_subject));
+ void _add_line_warning(ShaderWarning::Code p_code, const StringName &p_subject = "", const Vector<Variant> &p_extra_args = Vector<Variant>()) {
+ warnings.push_back(ShaderWarning(p_code, tk_line, p_subject, p_extra_args));
}
- void _add_warning(ShaderWarning::Code p_code, int p_line, const StringName &p_subject = "") {
- warnings.push_back(ShaderWarning(p_code, p_line, p_subject));
+ void _add_global_warning(ShaderWarning::Code p_code, const StringName &p_subject = "", const Vector<Variant> &p_extra_args = Vector<Variant>()) {
+ warnings.push_back(ShaderWarning(p_code, -1, p_subject, p_extra_args));
+ }
+ void _add_warning(ShaderWarning::Code p_code, int p_line, const StringName &p_subject = "", const Vector<Variant> &p_extra_args = Vector<Variant>()) {
+ warnings.push_back(ShaderWarning(p_code, p_line, p_subject, p_extra_args));
}
void _check_warning_accums();
#endif // DEBUG_ENABLED
@@ -880,14 +923,6 @@ private:
VaryingFunctionNames varying_function_names;
- struct VaryingUsage {
- ShaderNode::Varying *var;
- int line;
- };
- List<VaryingUsage> unknown_varying_usages;
-
- bool _check_varying_usages(int *r_error_line, String *r_error_message) const;
-
TkPos _get_tkpos() {
TkPos tkp;
tkp.char_idx = char_idx;
@@ -910,6 +945,26 @@ private:
error_str = p_str;
}
+ void _set_expected_error(const String &p_what) {
+ _set_error(vformat(RTR("Expected a '%s'."), p_what));
+ }
+
+ void _set_expected_error(const String &p_first, const String p_second) {
+ _set_error(vformat(RTR("Expected a '%s' or '%s'."), p_first, p_second));
+ }
+
+ void _set_expected_after_error(const String &p_what, const String &p_after) {
+ _set_error(vformat(RTR("Expected a '%s' after '%s'."), p_what, p_after));
+ }
+
+ void _set_redefinition_error(const String &p_what) {
+ _set_error(vformat(RTR("Redefinition of '%s'."), p_what));
+ }
+
+ void _set_parsing_error() {
+ _set_error("Parser bug.");
+ }
+
static const char *token_names[TK_MAX];
Token _make_token(TokenType p_type, const StringName &p_text = StringName());
@@ -965,10 +1020,12 @@ private:
int completion_line;
BlockNode *completion_block;
DataType completion_base;
+ bool completion_base_array;
SubClassTag completion_class;
StringName completion_function;
StringName completion_struct;
int completion_argument;
+
const Map<StringName, FunctionInfo> *stages = nullptr;
bool _get_completable_identifier(BlockNode *p_block, CompletionType p_type, StringName &identifier);
@@ -976,6 +1033,8 @@ private:
static const BuiltinFuncOutArgs builtin_func_out_args[];
static const BuiltinFuncConstArgs builtin_func_const_args[];
+ static bool is_const_suffix_lut_initialized;
+
Error _validate_datatype(DataType p_type);
bool _compare_datatypes(DataType p_datatype_a, String p_datatype_name_a, int p_array_size_a, DataType p_datatype_b, String p_datatype_name_b, int p_array_size_b);
bool _compare_datatypes_in_nodes(Node *a, Node *b);
@@ -985,14 +1044,10 @@ private:
bool _propagate_function_call_sampler_uniform_settings(StringName p_name, int p_argument, TextureFilter p_filter, TextureRepeat p_repeat);
bool _propagate_function_call_sampler_builtin_reference(StringName p_name, int p_argument, const StringName &p_builtin);
bool _validate_varying_assign(ShaderNode::Varying &p_varying, String *r_message);
- bool _validate_varying_using(ShaderNode::Varying &p_varying, String *r_message);
bool _check_node_constness(const Node *p_node) const;
- Node *_parse_array_size(BlockNode *p_block, const FunctionInfo &p_function_info, int &r_array_size);
- Error _parse_global_array_size(int &r_array_size);
- Error _parse_local_array_size(BlockNode *p_block, const FunctionInfo &p_function_info, ArrayDeclarationNode *p_node, ArrayDeclarationNode::Declaration *p_decl, int &r_array_size, bool &r_is_unknown_size);
-
Node *_parse_expression(BlockNode *p_block, const FunctionInfo &p_function_info);
+ Error _parse_array_size(BlockNode *p_block, const FunctionInfo &p_function_info, bool p_forbid_unknown_size, Node **r_size_expression, int *r_array_size, bool *r_unknown_size);
Node *_parse_array_constructor(BlockNode *p_block, const FunctionInfo &p_function_info);
Node *_parse_array_constructor(BlockNode *p_block, const FunctionInfo &p_function_info, DataType p_type, const StringName &p_struct_name, int p_array_size);
ShaderLanguage::Node *_reduce_expression(BlockNode *p_block, ShaderLanguage::Node *p_node);
@@ -1002,7 +1057,7 @@ private:
String _get_shader_type_list(const Set<String> &p_shader_types) const;
String _get_qualifier_str(ArgumentQualifier p_qualifier) const;
- Error _parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types);
+ Error _parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Vector<ModeInfo> &p_render_modes, const Set<String> &p_shader_types);
Error _find_last_flow_op_in_block(BlockNode *p_block, FlowOperation p_op);
Error _find_last_flow_op_in_op(ControlFlowNode *p_flow, FlowOperation p_op);
@@ -1023,8 +1078,17 @@ public:
void clear();
static String get_shader_type(const String &p_code);
- Error compile(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const VaryingFunctionNames &p_varying_function_names, const Set<String> &p_shader_types, GlobalVariableGetTypeFunc p_global_variable_type_func);
- Error complete(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const VaryingFunctionNames &p_varying_function_names, const Set<String> &p_shader_types, GlobalVariableGetTypeFunc p_global_variable_type_func, List<ScriptCodeCompletionOption> *r_options, String &r_call_hint);
+
+ struct ShaderCompileInfo {
+ Map<StringName, FunctionInfo> functions;
+ Vector<ModeInfo> render_modes;
+ VaryingFunctionNames varying_function_names = VaryingFunctionNames();
+ Set<String> shader_types;
+ GlobalVariableGetTypeFunc global_variable_type_func = nullptr;
+ };
+
+ Error compile(const String &p_code, const ShaderCompileInfo &p_info);
+ Error complete(const String &p_code, const ShaderCompileInfo &p_info, List<ScriptCodeCompletionOption> *r_options, String &r_call_hint);
String get_error_text();
int get_error_line();
diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp
index 0bfcccef28..9ae60c14cb 100644
--- a/servers/rendering/shader_types.cpp
+++ b/servers/rendering/shader_types.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -35,7 +35,7 @@ const Map<StringName, ShaderLanguage::FunctionInfo> &ShaderTypes::get_functions(
return shader_modes[p_mode].functions;
}
-const Vector<StringName> &ShaderTypes::get_modes(RS::ShaderMode p_mode) const {
+const Vector<ShaderLanguage::ModeInfo> &ShaderTypes::get_modes(RS::ShaderMode p_mode) const {
return shader_modes[p_mode].modes;
}
@@ -59,9 +59,9 @@ ShaderTypes::ShaderTypes() {
/*************** SPATIAL ***********************/
shader_modes[RS::SHADER_SPATIAL].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
- shader_modes[RS::SHADER_SPATIAL].functions["global"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT);
- shader_modes[RS::SHADER_SPATIAL].functions["global"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT);
- shader_modes[RS::SHADER_SPATIAL].functions["global"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_SPATIAL].functions["constants"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_SPATIAL].functions["constants"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_SPATIAL].functions["constants"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VERTEX"] = ShaderLanguage::TYPE_VEC3;
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["NORMAL"] = ShaderLanguage::TYPE_VEC3;
@@ -74,6 +74,7 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["POINT_SIZE"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["INSTANCE_ID"] = constt(ShaderLanguage::TYPE_INT);
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["INSTANCE_CUSTOM"] = constt(ShaderLanguage::TYPE_VEC4);
+ shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VERTEX_ID"] = constt(ShaderLanguage::TYPE_INT);
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["ROUGHNESS"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["BONE_INDICES"] = ShaderLanguage::TYPE_UVEC4;
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["BONE_WEIGHTS"] = ShaderLanguage::TYPE_VEC4;
@@ -190,60 +191,36 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SPATIAL].functions["light"].can_discard = true;
shader_modes[RS::SHADER_SPATIAL].functions["light"].main_function = true;
- //order used puts first enum mode (default) first
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("blend_mix");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("blend_add");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("blend_sub");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("blend_mul");
-
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("depth_draw_opaque");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("depth_draw_always");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("depth_draw_never");
-
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("depth_prepass_alpha");
-
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("depth_test_disabled");
-
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("sss_mode_skin");
-
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("cull_back");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("cull_front");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("cull_disabled");
-
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("unshaded");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("wireframe");
-
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("diffuse_lambert");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("diffuse_lambert_wrap");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("diffuse_burley");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("diffuse_toon");
-
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("specular_schlick_ggx");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("specular_blinn");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("specular_phong");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("specular_toon");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("specular_disabled");
-
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("skip_vertex_transform");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("world_vertex_coords");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("ensure_correct_normals");
-
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("shadows_disabled");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("ambient_light_disabled");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("shadow_to_opacity");
-
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("vertex_lighting");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("particle_trails");
-
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("alpha_to_coverage");
- shader_modes[RS::SHADER_SPATIAL].modes.push_back("alpha_to_coverage_and_one");
+ // spatial render modes
+ {
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "blend", "mix", "add", "sub", "mul" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "depth_draw", "opaque", "always", "never" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "depth_prepass_alpha" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "depth_test_disabled" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "sss_mode_skin" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "cull", "back", "front", "disabled" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "unshaded" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "wireframe" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "diffuse", "lambert", "lambert_wrap", "burley", "toon" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "specular", "schlick_ggx", "blinn", "phong", "toon", "disabled" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "skip_vertex_transform" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "world_vertex_coords" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "ensure_correct_normals" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "shadows_disabled" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "ambient_light_disabled" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "shadow_to_opacity" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "vertex_lighting" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "particle_trails" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "alpha_to_coverage" });
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "alpha_to_coverage_and_one" });
+ }
/************ CANVAS ITEM **************************/
shader_modes[RS::SHADER_CANVAS_ITEM].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
- shader_modes[RS::SHADER_CANVAS_ITEM].functions["global"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT);
- shader_modes[RS::SHADER_CANVAS_ITEM].functions["global"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT);
- shader_modes[RS::SHADER_CANVAS_ITEM].functions["global"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_CANVAS_ITEM].functions["constants"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_CANVAS_ITEM].functions["constants"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_CANVAS_ITEM].functions["constants"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["VERTEX"] = ShaderLanguage::TYPE_VEC2;
shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["UV"] = ShaderLanguage::TYPE_VEC2;
@@ -254,6 +231,8 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["CANVAS_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["SCREEN_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["INSTANCE_CUSTOM"] = constt(ShaderLanguage::TYPE_VEC4);
+ shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["INSTANCE_ID"] = constt(ShaderLanguage::TYPE_INT);
+ shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["VERTEX_ID"] = constt(ShaderLanguage::TYPE_INT);
shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["AT_LIGHT_PASS"] = constt(ShaderLanguage::TYPE_BOOL);
shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["TEXTURE_PIXEL_SIZE"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].can_discard = false;
@@ -319,24 +298,20 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].can_discard = true;
shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].main_function = true;
- shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("skip_vertex_transform");
-
- shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("blend_mix");
- shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("blend_add");
- shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("blend_sub");
- shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("blend_mul");
- shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("blend_premul_alpha");
- shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("blend_disabled");
-
- shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("unshaded");
- shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("light_only");
+ // canvasitem render modes
+ {
+ shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back({ "skip_vertex_transform" });
+ shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back({ "blend", "mix", "add", "sub", "mul", "premul_alpha", "disabled" });
+ shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back({ "unshaded" });
+ shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back({ "light_only" });
+ }
/************ PARTICLES **************************/
shader_modes[RS::SHADER_PARTICLES].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
- shader_modes[RS::SHADER_PARTICLES].functions["global"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT);
- shader_modes[RS::SHADER_PARTICLES].functions["global"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT);
- shader_modes[RS::SHADER_PARTICLES].functions["global"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_PARTICLES].functions["constants"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_PARTICLES].functions["constants"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_PARTICLES].functions["constants"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4;
shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["VELOCITY"] = ShaderLanguage::TYPE_VEC3;
@@ -367,7 +342,7 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["LIFETIME"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["DELTA"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["NUMBER"] = constt(ShaderLanguage::TYPE_UINT);
- shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["INDEX"] = constt(ShaderLanguage::TYPE_INT);
+ shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["INDEX"] = constt(ShaderLanguage::TYPE_UINT);
shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["EMISSION_TRANSFORM"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["RANDOM_SEED"] = constt(ShaderLanguage::TYPE_UINT);
shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["FLAG_EMIT_POSITION"] = constt(ShaderLanguage::TYPE_UINT);
@@ -392,17 +367,20 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_PARTICLES].functions["process"].stage_functions["emit_subparticle"] = emit_vertex_func;
}
- shader_modes[RS::SHADER_PARTICLES].modes.push_back("collision_use_scale");
- shader_modes[RS::SHADER_PARTICLES].modes.push_back("disable_force");
- shader_modes[RS::SHADER_PARTICLES].modes.push_back("disable_velocity");
- shader_modes[RS::SHADER_PARTICLES].modes.push_back("keep_data");
+ // particles render modes
+ {
+ shader_modes[RS::SHADER_PARTICLES].modes.push_back({ "collision_use_scale" });
+ shader_modes[RS::SHADER_PARTICLES].modes.push_back({ "disable_force" });
+ shader_modes[RS::SHADER_PARTICLES].modes.push_back({ "disable_velocity" });
+ shader_modes[RS::SHADER_PARTICLES].modes.push_back({ "keep_data" });
+ }
/************ SKY **************************/
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
- shader_modes[RS::SHADER_SKY].functions["global"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT);
- shader_modes[RS::SHADER_SKY].functions["global"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT);
- shader_modes[RS::SHADER_SKY].functions["global"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_SKY].functions["constants"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_SKY].functions["constants"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_SKY].functions["constants"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["POSITION"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["RADIANCE"] = constt(ShaderLanguage::TYPE_SAMPLERCUBE);
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["AT_HALF_RES_PASS"] = constt(ShaderLanguage::TYPE_BOOL);
@@ -439,14 +417,36 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SKY].functions["sky"].built_ins["FOG"] = ShaderLanguage::TYPE_VEC4;
shader_modes[RS::SHADER_SKY].functions["sky"].main_function = true;
- shader_modes[RS::SHADER_SKY].modes.push_back("use_half_res_pass");
- shader_modes[RS::SHADER_SKY].modes.push_back("use_quarter_res_pass");
- shader_modes[RS::SHADER_SKY].modes.push_back("disable_fog");
+ // sky render modes
+ {
+ shader_modes[RS::SHADER_SKY].modes.push_back({ "use_half_res_pass" });
+ shader_modes[RS::SHADER_SKY].modes.push_back({ "use_quarter_res_pass" });
+ shader_modes[RS::SHADER_SKY].modes.push_back({ "disable_fog" });
+ }
+
+ /************ FOG **************************/
+
+ shader_modes[RS::SHADER_FOG].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_FOG].functions["constants"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_FOG].functions["constants"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_FOG].functions["constants"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT);
+
+ shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["WORLD_POSITION"] = constt(ShaderLanguage::TYPE_VEC3);
+ shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["OBJECT_POSITION"] = constt(ShaderLanguage::TYPE_VEC3);
+ shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["UVW"] = constt(ShaderLanguage::TYPE_VEC3);
+ shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["EXTENTS"] = constt(ShaderLanguage::TYPE_VEC3);
+ shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["TRANSFORM"] = constt(ShaderLanguage::TYPE_MAT4);
+ shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["SDF"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["ALBEDO"] = ShaderLanguage::TYPE_VEC3;
+ shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["DENSITY"] = ShaderLanguage::TYPE_FLOAT;
+ shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["EMISSION"] = ShaderLanguage::TYPE_VEC3;
+ shader_modes[RS::SHADER_FOG].functions["fog"].main_function = true;
shader_types_list.push_back("spatial");
shader_types_list.push_back("canvas_item");
shader_types_list.push_back("particles");
shader_types_list.push_back("sky");
+ shader_types_list.push_back("fog");
for (int i = 0; i < shader_types_list.size(); i++) {
shader_types.insert(shader_types_list[i]);
diff --git a/servers/rendering/shader_types.h b/servers/rendering/shader_types.h
index 75a310a1b1..385083b670 100644
--- a/servers/rendering/shader_types.h
+++ b/servers/rendering/shader_types.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -38,7 +38,7 @@
class ShaderTypes {
struct Type {
Map<StringName, ShaderLanguage::FunctionInfo> functions;
- Vector<StringName> modes;
+ Vector<ShaderLanguage::ModeInfo> modes;
};
Map<RS::ShaderMode, Type> shader_modes;
@@ -52,7 +52,7 @@ public:
static ShaderTypes *get_singleton() { return singleton; }
const Map<StringName, ShaderLanguage::FunctionInfo> &get_functions(RS::ShaderMode p_mode) const;
- const Vector<StringName> &get_modes(RS::ShaderMode p_mode) const;
+ const Vector<ShaderLanguage::ModeInfo> &get_modes(RS::ShaderMode p_mode) const;
const Set<String> &get_types() const;
const List<String> &get_types_list() const;
diff --git a/servers/rendering/shader_warnings.cpp b/servers/rendering/shader_warnings.cpp
index 0b8476478c..639b9bd165 100644
--- a/servers/rendering/shader_warnings.cpp
+++ b/servers/rendering/shader_warnings.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -48,19 +48,23 @@ const StringName &ShaderWarning::get_subject() const {
String ShaderWarning::get_message() const {
switch (code) {
case FLOAT_COMPARISON:
- return vformat("Direct floating-point comparison (this may not evaluate to `true` as you expect). Instead, use `abs(a - b) < 0.0001` for an approximate but predictable comparison.");
+ return vformat(RTR("Direct floating-point comparison (this may not evaluate to `true` as you expect). Instead, use `abs(a - b) < 0.0001` for an approximate but predictable comparison."));
case UNUSED_CONSTANT:
- return vformat("The const '%s' is declared but never used.", subject);
+ return vformat(RTR("The const '%s' is declared but never used."), subject);
case UNUSED_FUNCTION:
- return vformat("The function '%s' is declared but never used.", subject);
+ return vformat(RTR("The function '%s' is declared but never used."), subject);
case UNUSED_STRUCT:
- return vformat("The struct '%s' is declared but never used.", subject);
+ return vformat(RTR("The struct '%s' is declared but never used."), subject);
case UNUSED_UNIFORM:
- return vformat("The uniform '%s' is declared but never used.", subject);
+ return vformat(RTR("The uniform '%s' is declared but never used."), subject);
case UNUSED_VARYING:
- return vformat("The varying '%s' is declared but never used.", subject);
+ return vformat(RTR("The varying '%s' is declared but never used."), subject);
case UNUSED_LOCAL_VARIABLE:
- return vformat("The local variable '%s' is declared but never used.", subject);
+ return vformat(RTR("The local variable '%s' is declared but never used."), subject);
+ case FORMATTING_ERROR:
+ return subject;
+ case DEVICE_LIMIT_EXCEEDED:
+ return vformat(RTR("The total size of the %s for this shader on this device has been exceeded (%d/%d). The shader may not work correctly."), subject, (int)extra_args[0], (int)extra_args[1]);
default:
break;
}
@@ -71,6 +75,10 @@ String ShaderWarning::get_name() const {
return get_name_from_code(code);
}
+Vector<Variant> ShaderWarning::get_extra_args() const {
+ return extra_args;
+}
+
String ShaderWarning::get_name_from_code(Code p_code) {
ERR_FAIL_INDEX_V(p_code, WARNING_MAX, String());
@@ -82,6 +90,8 @@ String ShaderWarning::get_name_from_code(Code p_code) {
"UNUSED_UNIFORM",
"UNUSED_VARYING",
"UNUSED_LOCAL_VARIABLE",
+ "FORMATTING_ERROR",
+ "DEVICE_LIMIT_EXCEEDED",
};
static_assert((sizeof(names) / sizeof(*names)) == WARNING_MAX, "Amount of warning types don't match the amount of warning names.");
@@ -110,6 +120,8 @@ static void init_code_to_flags_map() {
code_to_flags_map->insert(ShaderWarning::UNUSED_UNIFORM, ShaderWarning::UNUSED_UNIFORM_FLAG);
code_to_flags_map->insert(ShaderWarning::UNUSED_VARYING, ShaderWarning::UNUSED_VARYING_FLAG);
code_to_flags_map->insert(ShaderWarning::UNUSED_LOCAL_VARIABLE, ShaderWarning::UNUSED_LOCAL_VARIABLE_FLAG);
+ code_to_flags_map->insert(ShaderWarning::FORMATTING_ERROR, ShaderWarning::FORMATTING_ERROR_FLAG);
+ code_to_flags_map->insert(ShaderWarning::DEVICE_LIMIT_EXCEEDED, ShaderWarning::DEVICE_LIMIT_EXCEEDED_FLAG);
}
ShaderWarning::CodeFlags ShaderWarning::get_flags_from_codemap(const Map<Code, bool> &p_map) {
@@ -128,8 +140,8 @@ ShaderWarning::CodeFlags ShaderWarning::get_flags_from_codemap(const Map<Code, b
return (CodeFlags)result;
}
-ShaderWarning::ShaderWarning(Code p_code, int p_line, const StringName &p_subject) :
- code(p_code), line(p_line), subject(p_subject) {
+ShaderWarning::ShaderWarning(Code p_code, int p_line, const StringName &p_subject, const Vector<Variant> &p_extra_args) :
+ code(p_code), line(p_line), subject(p_subject), extra_args(p_extra_args) {
}
#endif // DEBUG_ENABLED
diff --git a/servers/rendering/shader_warnings.h b/servers/rendering/shader_warnings.h
index db872d8fb1..e309907181 100644
--- a/servers/rendering/shader_warnings.h
+++ b/servers/rendering/shader_warnings.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -36,6 +36,7 @@
#include "core/string/string_name.h"
#include "core/templates/list.h"
#include "core/templates/map.h"
+#include "core/variant/variant.h"
class ShaderWarning {
public:
@@ -47,6 +48,8 @@ public:
UNUSED_UNIFORM,
UNUSED_VARYING,
UNUSED_LOCAL_VARIABLE,
+ FORMATTING_ERROR,
+ DEVICE_LIMIT_EXCEEDED,
WARNING_MAX,
};
@@ -59,12 +62,15 @@ public:
UNUSED_UNIFORM_FLAG = 16U,
UNUSED_VARYING_FLAG = 32U,
UNUSED_LOCAL_VARIABLE_FLAG = 64U,
+ FORMATTING_ERROR_FLAG = 128U,
+ DEVICE_LIMIT_EXCEEDED_FLAG = 256U,
};
private:
Code code;
int line;
StringName subject;
+ Vector<Variant> extra_args;
public:
Code get_code() const;
@@ -72,12 +78,13 @@ public:
const StringName &get_subject() const;
String get_message() const;
String get_name() const;
+ Vector<Variant> get_extra_args() const;
static String get_name_from_code(Code p_code);
static Code get_code_from_name(const String &p_name);
static CodeFlags get_flags_from_codemap(const Map<Code, bool> &p_map);
- ShaderWarning(Code p_code = WARNING_MAX, int p_line = -1, const StringName &p_subject = "");
+ ShaderWarning(Code p_code = WARNING_MAX, int p_line = -1, const StringName &p_subject = "", const Vector<Variant> &p_extra_args = Vector<Variant>());
};
#endif // DEBUG_ENABLED
diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp
index b3efe840b6..863aae6e4c 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -32,6 +32,8 @@
#include "core/config/project_settings.h"
#include "servers/rendering/rendering_server_globals.h"
+#include "servers/rendering/shader_language.h"
+
RenderingServer *RenderingServer::singleton = nullptr;
RenderingServer *(*RenderingServer::create_func)() = nullptr;
@@ -199,11 +201,11 @@ RID RenderingServer::_make_test_cube() {
normal_points[j][i % 3] = (i >= 3 ? -1 : 1);
}
- //tri 1
+ // Tri 1
ADD_VTX(0);
ADD_VTX(1);
ADD_VTX(2);
- //tri 2
+ // Tri 2
ADD_VTX(2);
ADD_VTX(3);
ADD_VTX(0);
@@ -317,9 +319,6 @@ RID RenderingServer::get_white_texture() {
return white_texture;
}
-#define SMALL_VEC2 Vector2(0.00001, 0.00001)
-#define SMALL_VEC3 Vector3(0.00001, 0.00001, 0.00001)
-
Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_t *p_offsets, uint32_t p_vertex_stride, uint32_t p_attrib_stride, uint32_t p_skin_stride, Vector<uint8_t> &r_vertex_array, Vector<uint8_t> &r_attrib_array, Vector<uint8_t> &r_skin_array, int p_vertex_array_len, Vector<uint8_t> &r_index_array, int p_index_array_len, AABB &r_aabb, Vector<AABB> &r_bone_aabb) {
uint8_t *vw = r_vertex_array.ptrw();
uint8_t *aw = r_attrib_array.ptrw();
@@ -333,7 +332,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint
int max_bone = 0;
for (int ai = 0; ai < RS::ARRAY_MAX; ai++) {
- if (!(p_format & (1 << ai))) { // no array
+ if (!(p_format & (1 << ai))) { // No array
continue;
}
@@ -345,7 +344,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint
const Vector2 *src = array.ptr();
- // setting vertices means regenerating the AABB
+ // Setting vertices means regenerating the AABB.
Rect2 aabb;
{
@@ -355,7 +354,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint
memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], vector, sizeof(float) * 2);
if (i == 0) {
- aabb = Rect2(src[i], SMALL_VEC2); //must have a bit of size
+ aabb = Rect2(src[i], SMALL_VEC2); // Must have a bit of size.
} else {
aabb.expand_to(src[i]);
}
@@ -370,7 +369,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint
const Vector3 *src = array.ptr();
- // setting vertices means regenerating the AABB
+ // Setting vertices means regenerating the AABB.
AABB aabb;
{
@@ -505,7 +504,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint
case ARRAY_CUSTOM_RGBA8_UNORM:
case ARRAY_CUSTOM_RGBA8_SNORM:
case ARRAY_CUSTOM_RG_HALF: {
- //size 4
+ // Size 4
ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::PACKED_BYTE_ARRAY, ERR_INVALID_PARAMETER);
Vector<uint8_t> array = p_arrays[ai];
@@ -520,7 +519,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint
} break;
case ARRAY_CUSTOM_RGBA_HALF: {
- //size 8
+ // Size 8
ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::PACKED_BYTE_ARRAY, ERR_INVALID_PARAMETER);
Vector<uint8_t> array = p_arrays[ai];
@@ -537,7 +536,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint
case ARRAY_CUSTOM_RG_FLOAT:
case ARRAY_CUSTOM_RGB_FLOAT:
case ARRAY_CUSTOM_RGBA_FLOAT: {
- //RF
+ // RF
ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::PACKED_FLOAT32_ARRAY, ERR_INVALID_PARAMETER);
Vector<float> array = p_arrays[ai];
@@ -646,7 +645,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint
}
if (p_format & RS::ARRAY_FORMAT_BONES) {
- //create AABBs for each detected bone
+ // Create AABBs for each detected bone.
int total_bones = max_bone + 1;
bool first = r_bone_aabb.size() == 0;
@@ -657,7 +656,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint
if (first) {
for (int i = 0; i < total_bones; i++) {
- r_bone_aabb.write[i].size = Vector3(-1, -1, -1); //negative means unused
+ r_bone_aabb.write[i].size = Vector3(-1, -1, -1); // Negative means unused.
}
}
@@ -686,7 +685,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint
ERR_FAIL_INDEX_V(idx, total_bones, ERR_INVALID_DATA);
if (bptr[idx].size.x < 0) {
- //first
+ // First
bptr[idx] = AABB(v, SMALL_VEC3);
any_valid = true;
} else {
@@ -749,7 +748,7 @@ void RenderingServer::mesh_surface_make_offsets_from_format(uint32_t p_format, i
uint32_t *size_accum;
for (int i = 0; i < RS::ARRAY_MAX; i++) {
- r_offsets[i] = 0; //reset
+ r_offsets[i] = 0; // Reset
if (i == RS::ARRAY_VERTEX) {
size_accum = &r_vertex_element_size;
@@ -759,7 +758,7 @@ void RenderingServer::mesh_surface_make_offsets_from_format(uint32_t p_format, i
size_accum = &r_skin_element_size;
}
- if (!(p_format & (1 << i))) { // no array
+ if (!(p_format & (1 << i))) { // No array
continue;
}
@@ -873,7 +872,7 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa
uint32_t format = 0;
- // validation
+ // Validation
int index_array_len = 0;
int array_len = 0;
@@ -921,10 +920,10 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa
}
}
- ERR_FAIL_COND_V((format & RS::ARRAY_FORMAT_VERTEX) == 0, ERR_INVALID_PARAMETER); // mandatory
+ ERR_FAIL_COND_V((format & RS::ARRAY_FORMAT_VERTEX) == 0, ERR_INVALID_PARAMETER); // Mandatory
if (p_blend_shapes.size()) {
- //validate format for morphs
+ // Validate format for morphs.
for (int i = 0; i < p_blend_shapes.size(); i++) {
uint32_t bsformat = 0;
Array arr = p_blend_shapes[i];
@@ -939,7 +938,7 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa
}
for (uint32_t i = 0; i < RS::ARRAY_CUSTOM_COUNT; ++i) {
- // include custom array format type.
+ // Include custom array format type.
if (format & (1 << (ARRAY_CUSTOM0 + i))) {
format |= (RS::ARRAY_FORMAT_CUSTOM_MASK << (RS::ARRAY_FORMAT_CUSTOM_BASE + i * RS::ARRAY_FORMAT_CUSTOM_BITS)) & p_compress_format;
}
@@ -954,7 +953,7 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa
mesh_surface_make_offsets_from_format(format, array_len, index_array_len, offsets, vertex_element_size, attrib_element_size, skin_element_size);
uint32_t mask = (1 << ARRAY_MAX) - 1;
- format |= (~mask) & p_compress_format; //make the full format
+ format |= (~mask) & p_compress_format; // Make the full format.
int vertex_array_size = vertex_element_size * array_len;
int attrib_array_size = attrib_element_size * array_len;
@@ -1010,13 +1009,13 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa
Vector<int> indices = p_lods[E];
ERR_CONTINUE(indices.size() == 0);
uint32_t index_count = indices.size();
- ERR_CONTINUE(index_count >= (uint32_t)index_array_len); //should be smaller..
+ ERR_CONTINUE(index_count >= (uint32_t)index_array_len); // Should be smaller..
const int *r = indices.ptr();
Vector<uint8_t> data;
if (array_len <= 65536) {
- //16 bits indices
+ // 16 bits indices
data.resize(indices.size() * 2);
uint8_t *w = data.ptrw();
uint16_t *index_ptr = (uint16_t *)w;
@@ -1024,7 +1023,7 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa
index_ptr[i] = r[i];
}
} else {
- //32 bits indices
+ // 32 bits indices
data.resize(indices.size() * 4);
uint8_t *w = data.ptrw();
uint32_t *index_ptr = (uint32_t *)w;
@@ -1204,7 +1203,7 @@ Array RenderingServer::_get_array_from_surface(uint32_t p_format, Vector<uint8_t
case ARRAY_CUSTOM_RGBA8_SNORM:
case ARRAY_CUSTOM_RG_HALF:
case ARRAY_CUSTOM_RGBA_HALF: {
- //size 4
+ // Size 4
int s = type == ARRAY_CUSTOM_RGBA_HALF ? 8 : 4;
Vector<uint8_t> arr;
arr.resize(p_vertex_len * s);
@@ -1376,7 +1375,7 @@ Array RenderingServer::mesh_surface_get_blend_shape_arrays(RID p_mesh, int p_sur
Array blend_shape_array;
blend_shape_array.resize(mesh_get_blend_shape_count(p_mesh));
for (uint32_t i = 0; i < blend_shape_count; i++) {
- Vector<uint8_t> bs_data = blend_shape_data.subarray(i * divisor, (i + 1) * divisor - 1);
+ Vector<uint8_t> bs_data = blend_shape_data.slice(i * divisor, (i + 1) * divisor);
Vector<uint8_t> unused;
blend_shape_array.set(i, _get_array_from_surface(bs_format, bs_data, unused, unused, sd.vertex_count, unused, 0));
}
@@ -1413,7 +1412,7 @@ Array RenderingServer::_mesh_surface_get_skeleton_aabb_bind(RID p_mesh, int p_su
}
#endif
-ShaderLanguage::DataType RenderingServer::global_variable_type_get_shader_datatype(GlobalVariableType p_type) {
+int RenderingServer::global_variable_type_get_shader_datatype(GlobalVariableType p_type) {
switch (p_type) {
case RS::GLOBAL_VAR_TYPE_BOOL:
return ShaderLanguage::TYPE_BOOL;
@@ -1472,12 +1471,12 @@ ShaderLanguage::DataType RenderingServer::global_variable_type_get_shader_dataty
case RS::GLOBAL_VAR_TYPE_SAMPLERCUBE:
return ShaderLanguage::TYPE_SAMPLERCUBE;
default:
- return ShaderLanguage::TYPE_MAX; //invalid or not found
+ return ShaderLanguage::TYPE_MAX; // Invalid or not found.
}
}
RenderingDevice *RenderingServer::get_rendering_device() const {
- // return the rendering device we're using globally
+ // Return the rendering device we're using globally.
return RenderingDevice::get_singleton();
}
@@ -1716,13 +1715,14 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("shader_get_param_list", "shader"), &RenderingServer::_shader_get_param_list);
ClassDB::bind_method(D_METHOD("shader_get_param_default", "shader", "param"), &RenderingServer::shader_get_param_default);
- ClassDB::bind_method(D_METHOD("shader_set_default_texture_param", "shader", "param", "texture"), &RenderingServer::shader_set_default_texture_param);
- ClassDB::bind_method(D_METHOD("shader_get_default_texture_param", "shader", "param"), &RenderingServer::shader_get_default_texture_param);
+ ClassDB::bind_method(D_METHOD("shader_set_default_texture_param", "shader", "param", "texture", "index"), &RenderingServer::shader_set_default_texture_param, DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("shader_get_default_texture_param", "shader", "param", "index"), &RenderingServer::shader_get_default_texture_param, DEFVAL(0));
BIND_ENUM_CONSTANT(SHADER_SPATIAL);
BIND_ENUM_CONSTANT(SHADER_CANVAS_ITEM);
BIND_ENUM_CONSTANT(SHADER_PARTICLES);
BIND_ENUM_CONSTANT(SHADER_SKY);
+ BIND_ENUM_CONSTANT(SHADER_FOG);
BIND_ENUM_CONSTANT(SHADER_MAX);
/* MATERIAL */
@@ -1942,6 +1942,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("directional_shadow_atlas_set_size", "size", "is_16bits"), &RenderingServer::directional_shadow_atlas_set_size);
BIND_ENUM_CONSTANT(SHADOW_QUALITY_HARD);
+ BIND_ENUM_CONSTANT(SHADOW_QUALITY_SOFT_VERY_LOW);
BIND_ENUM_CONSTANT(SHADOW_QUALITY_SOFT_LOW);
BIND_ENUM_CONSTANT(SHADOW_QUALITY_SOFT_MEDIUM);
BIND_ENUM_CONSTANT(SHADOW_QUALITY_SOFT_HIGH);
@@ -1964,7 +1965,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("reflection_probe_set_enable_shadows", "probe", "enable"), &RenderingServer::reflection_probe_set_enable_shadows);
ClassDB::bind_method(D_METHOD("reflection_probe_set_cull_mask", "probe", "layers"), &RenderingServer::reflection_probe_set_cull_mask);
ClassDB::bind_method(D_METHOD("reflection_probe_set_resolution", "probe", "resolution"), &RenderingServer::reflection_probe_set_resolution);
- ClassDB::bind_method(D_METHOD("reflection_probe_set_lod_threshold", "probe", "pixels"), &RenderingServer::reflection_probe_set_lod_threshold);
+ ClassDB::bind_method(D_METHOD("reflection_probe_set_mesh_lod_threshold", "probe", "pixels"), &RenderingServer::reflection_probe_set_mesh_lod_threshold);
BIND_ENUM_CONSTANT(REFLECTION_PROBE_UPDATE_ONCE);
BIND_ENUM_CONSTANT(REFLECTION_PROBE_UPDATE_ALWAYS);
@@ -2000,6 +2001,10 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(DECAL_FILTER_LINEAR_MIPMAPS);
BIND_ENUM_CONSTANT(DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC);
+ /* GI API (affects VoxelGI and SDFGI) */
+
+ ClassDB::bind_method(D_METHOD("gi_set_use_half_resolution", "half_resolution"), &RenderingServer::gi_set_use_half_resolution);
+
/* VOXEL GI API */
ClassDB::bind_method(D_METHOD("voxel_gi_create"), &RenderingServer::voxel_gi_create);
@@ -2125,6 +2130,17 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_8192);
BIND_ENUM_CONSTANT(PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_MAX);
+ /* FOG VOLUMES */
+
+ ClassDB::bind_method(D_METHOD("fog_volume_create"), &RenderingServer::fog_volume_create);
+ ClassDB::bind_method(D_METHOD("fog_volume_set_shape", "fog_volume", "shape"), &RenderingServer::fog_volume_set_shape);
+ ClassDB::bind_method(D_METHOD("fog_volume_set_extents", "fog_volume", "extents"), &RenderingServer::fog_volume_set_extents);
+ ClassDB::bind_method(D_METHOD("fog_volume_set_material", "fog_volume", "material"), &RenderingServer::fog_volume_set_material);
+
+ BIND_ENUM_CONSTANT(FOG_VOLUME_SHAPE_ELLIPSOID);
+ BIND_ENUM_CONSTANT(FOG_VOLUME_SHAPE_BOX);
+ BIND_ENUM_CONSTANT(FOG_VOLUME_SHAPE_WORLD);
+
/* VISIBILITY NOTIFIER */
ClassDB::bind_method(D_METHOD("visibility_notifier_create"), &RenderingServer::visibility_notifier_create);
@@ -2152,13 +2168,16 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("viewport_create"), &RenderingServer::viewport_create);
ClassDB::bind_method(D_METHOD("viewport_set_use_xr", "viewport", "use_xr"), &RenderingServer::viewport_set_use_xr);
- ClassDB::bind_method(D_METHOD("viewport_set_scale_3d", "viewport", "scale"), &RenderingServer::viewport_set_scale_3d);
ClassDB::bind_method(D_METHOD("viewport_set_size", "viewport", "width", "height"), &RenderingServer::viewport_set_size);
ClassDB::bind_method(D_METHOD("viewport_set_active", "viewport", "active"), &RenderingServer::viewport_set_active);
ClassDB::bind_method(D_METHOD("viewport_set_parent_viewport", "viewport", "parent_viewport"), &RenderingServer::viewport_set_parent_viewport);
ClassDB::bind_method(D_METHOD("viewport_attach_to_screen", "viewport", "rect", "screen"), &RenderingServer::viewport_attach_to_screen, DEFVAL(Rect2()), DEFVAL(DisplayServer::MAIN_WINDOW_ID));
ClassDB::bind_method(D_METHOD("viewport_set_render_direct_to_screen", "viewport", "enabled"), &RenderingServer::viewport_set_render_direct_to_screen);
+ ClassDB::bind_method(D_METHOD("viewport_set_scaling_3d_mode", "viewport", "scaling_3d_mode"), &RenderingServer::viewport_set_scaling_3d_mode);
+ ClassDB::bind_method(D_METHOD("viewport_set_scaling_3d_scale", "viewport", "scale"), &RenderingServer::viewport_set_scaling_3d_scale);
+ ClassDB::bind_method(D_METHOD("viewport_set_fsr_sharpness", "viewport", "sharpness"), &RenderingServer::viewport_set_fsr_sharpness);
+ ClassDB::bind_method(D_METHOD("viewport_set_fsr_mipmap_bias", "viewport", "mipmap_bias"), &RenderingServer::viewport_set_fsr_mipmap_bias);
ClassDB::bind_method(D_METHOD("viewport_set_update_mode", "viewport", "update_mode"), &RenderingServer::viewport_set_update_mode);
ClassDB::bind_method(D_METHOD("viewport_set_clear_mode", "viewport", "clear_mode"), &RenderingServer::viewport_set_clear_mode);
ClassDB::bind_method(D_METHOD("viewport_get_texture", "viewport"), &RenderingServer::viewport_get_texture);
@@ -2200,9 +2219,13 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("viewport_get_measured_render_time_gpu", "viewport"), &RenderingServer::viewport_get_measured_render_time_gpu);
+ BIND_ENUM_CONSTANT(VIEWPORT_SCALING_3D_MODE_BILINEAR);
+ BIND_ENUM_CONSTANT(VIEWPORT_SCALING_3D_MODE_FSR);
+ BIND_ENUM_CONSTANT(VIEWPORT_SCALING_3D_MODE_MAX);
+
BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_DISABLED);
- BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_ONCE); //then goes to disabled); must be manually updated
- BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_WHEN_VISIBLE); // default
+ BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_ONCE); // Then goes to disabled); must be manually updated.
+ BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_WHEN_VISIBLE); // Default
BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_WHEN_PARENT_VISIBLE);
BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_ALWAYS);
@@ -2257,6 +2280,7 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS);
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_SCENE_LUMINANCE);
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_SSAO);
+ BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_SSIL);
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_PSSM_SPLITS);
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_DECAL_ATLAS);
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_SDFGI);
@@ -2300,12 +2324,13 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("environment_set_ssao", "env", "enable", "radius", "intensity", "power", "detail", "horizon", "sharpness", "light_affect", "ao_channel_affect"), &RenderingServer::environment_set_ssao);
ClassDB::bind_method(D_METHOD("environment_set_fog", "env", "enable", "light_color", "light_energy", "sun_scatter", "density", "height", "height_density", "aerial_perspective"), &RenderingServer::environment_set_fog);
ClassDB::bind_method(D_METHOD("environment_set_sdfgi", "env", "enable", "cascades", "min_cell_size", "y_scale", "use_occlusion", "bounce_feedback", "read_sky", "energy", "normal_bias", "probe_bias"), &RenderingServer::environment_set_sdfgi);
- ClassDB::bind_method(D_METHOD("environment_set_volumetric_fog", "env", "enable", "density", "light", "light_energy", "length", "p_detail_spread", "gi_inject", "temporal_reprojection", "temporal_reprojection_amount"), &RenderingServer::environment_set_volumetric_fog);
+ ClassDB::bind_method(D_METHOD("environment_set_volumetric_fog", "env", "enable", "density", "albedo", "emission", "emission_energy", "anisotropy", "length", "p_detail_spread", "gi_inject", "temporal_reprojection", "temporal_reprojection_amount", "ambient_inject"), &RenderingServer::environment_set_volumetric_fog);
ClassDB::bind_method(D_METHOD("environment_glow_set_use_bicubic_upscale", "enable"), &RenderingServer::environment_glow_set_use_bicubic_upscale);
ClassDB::bind_method(D_METHOD("environment_glow_set_use_high_quality", "enable"), &RenderingServer::environment_glow_set_use_high_quality);
ClassDB::bind_method(D_METHOD("environment_set_ssr_roughness_quality", "quality"), &RenderingServer::environment_set_ssr_roughness_quality);
ClassDB::bind_method(D_METHOD("environment_set_ssao_quality", "quality", "half_size", "adaptive_target", "blur_passes", "fadeout_from", "fadeout_to"), &RenderingServer::environment_set_ssao_quality);
+ ClassDB::bind_method(D_METHOD("environment_set_ssil_quality", "quality", "half_size", "adaptive_target", "blur_passes", "fadeout_from", "fadeout_to"), &RenderingServer::environment_set_ssil_quality);
ClassDB::bind_method(D_METHOD("environment_set_sdfgi_ray_count", "ray_count"), &RenderingServer::environment_set_sdfgi_ray_count);
ClassDB::bind_method(D_METHOD("environment_set_sdfgi_frames_to_converge", "frames"), &RenderingServer::environment_set_sdfgi_frames_to_converge);
ClassDB::bind_method(D_METHOD("environment_set_sdfgi_frames_to_update_light", "frames"), &RenderingServer::environment_set_sdfgi_frames_to_update_light);
@@ -2357,9 +2382,11 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(ENV_SSAO_QUALITY_HIGH);
BIND_ENUM_CONSTANT(ENV_SSAO_QUALITY_ULTRA);
- BIND_ENUM_CONSTANT(ENV_SDFGI_CASCADES_4);
- BIND_ENUM_CONSTANT(ENV_SDFGI_CASCADES_6);
- BIND_ENUM_CONSTANT(ENV_SDFGI_CASCADES_8);
+ BIND_ENUM_CONSTANT(ENV_SSIL_QUALITY_VERY_LOW);
+ BIND_ENUM_CONSTANT(ENV_SSIL_QUALITY_LOW);
+ BIND_ENUM_CONSTANT(ENV_SSIL_QUALITY_MEDIUM);
+ BIND_ENUM_CONSTANT(ENV_SSIL_QUALITY_HIGH);
+ BIND_ENUM_CONSTANT(ENV_SSIL_QUALITY_ULTRA);
BIND_ENUM_CONSTANT(ENV_SDFGI_Y_SCALE_DISABLED);
BIND_ENUM_CONSTANT(ENV_SDFGI_Y_SCALE_75_PERCENT);
@@ -2432,17 +2459,20 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("instance_set_blend_shape_weight", "instance", "shape", "weight"), &RenderingServer::instance_set_blend_shape_weight);
ClassDB::bind_method(D_METHOD("instance_set_surface_override_material", "instance", "surface", "material"), &RenderingServer::instance_set_surface_override_material);
ClassDB::bind_method(D_METHOD("instance_set_visible", "instance", "visible"), &RenderingServer::instance_set_visible);
+ ClassDB::bind_method(D_METHOD("instance_geometry_set_transparency", "instance", "transparency"), &RenderingServer::instance_geometry_set_transparency);
ClassDB::bind_method(D_METHOD("instance_set_custom_aabb", "instance", "aabb"), &RenderingServer::instance_set_custom_aabb);
ClassDB::bind_method(D_METHOD("instance_attach_skeleton", "instance", "skeleton"), &RenderingServer::instance_attach_skeleton);
ClassDB::bind_method(D_METHOD("instance_set_extra_visibility_margin", "instance", "margin"), &RenderingServer::instance_set_extra_visibility_margin);
ClassDB::bind_method(D_METHOD("instance_set_visibility_parent", "instance", "parent"), &RenderingServer::instance_set_visibility_parent);
+ ClassDB::bind_method(D_METHOD("instance_set_ignore_culling", "instance", "enabled"), &RenderingServer::instance_set_ignore_culling);
ClassDB::bind_method(D_METHOD("instance_geometry_set_flag", "instance", "flag", "enabled"), &RenderingServer::instance_geometry_set_flag);
ClassDB::bind_method(D_METHOD("instance_geometry_set_cast_shadows_setting", "instance", "shadow_casting_setting"), &RenderingServer::instance_geometry_set_cast_shadows_setting);
ClassDB::bind_method(D_METHOD("instance_geometry_set_material_override", "instance", "material"), &RenderingServer::instance_geometry_set_material_override);
- ClassDB::bind_method(D_METHOD("instance_geometry_set_visibility_range", "instance", "min", "max", "min_margin", "max_margin"), &RenderingServer::instance_geometry_set_visibility_range);
+ ClassDB::bind_method(D_METHOD("instance_geometry_set_material_overlay", "instance", "material"), &RenderingServer::instance_geometry_set_material_overlay);
+ ClassDB::bind_method(D_METHOD("instance_geometry_set_visibility_range", "instance", "min", "max", "min_margin", "max_margin", "fade_mode"), &RenderingServer::instance_geometry_set_visibility_range);
ClassDB::bind_method(D_METHOD("instance_geometry_set_lightmap", "instance", "lightmap", "lightmap_uv_scale", "lightmap_slice"), &RenderingServer::instance_geometry_set_lightmap);
ClassDB::bind_method(D_METHOD("instance_geometry_set_lod_bias", "instance", "lod_bias"), &RenderingServer::instance_geometry_set_lod_bias);
@@ -2467,6 +2497,7 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(INSTANCE_LIGHTMAP);
BIND_ENUM_CONSTANT(INSTANCE_OCCLUDER);
BIND_ENUM_CONSTANT(INSTANCE_VISIBLITY_NOTIFIER);
+ BIND_ENUM_CONSTANT(INSTANCE_FOG_VOLUME);
BIND_ENUM_CONSTANT(INSTANCE_MAX);
BIND_ENUM_CONSTANT(INSTANCE_GEOMETRY_MASK);
@@ -2482,6 +2513,10 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_DOUBLE_SIDED);
BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_SHADOWS_ONLY);
+ BIND_ENUM_CONSTANT(VISIBILITY_RANGE_FADE_DISABLED);
+ BIND_ENUM_CONSTANT(VISIBILITY_RANGE_FADE_SELF);
+ BIND_ENUM_CONSTANT(VISIBILITY_RANGE_FADE_DEPENDENCIES);
+
/* Bake 3D Object */
ClassDB::bind_method(D_METHOD("bake_render_uv2", "base", "material_overrides", "image_size"), &RenderingServer::bake_render_uv2);
@@ -2526,7 +2561,8 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("canvas_item_set_modulate", "item", "color"), &RenderingServer::canvas_item_set_modulate);
ClassDB::bind_method(D_METHOD("canvas_item_set_self_modulate", "item", "color"), &RenderingServer::canvas_item_set_self_modulate);
ClassDB::bind_method(D_METHOD("canvas_item_set_draw_behind_parent", "item", "enabled"), &RenderingServer::canvas_item_set_draw_behind_parent);
- //primitives
+
+ /* Primitives */
ClassDB::bind_method(D_METHOD("canvas_item_add_line", "item", "from", "to", "color", "width"), &RenderingServer::canvas_item_add_line, DEFVAL(1.0));
ClassDB::bind_method(D_METHOD("canvas_item_add_polyline", "item", "points", "colors", "width", "antialiased"), &RenderingServer::canvas_item_add_polyline, DEFVAL(1.0), DEFVAL(false));
@@ -2677,15 +2713,16 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_MAX);
/* Free */
- ClassDB::bind_method(D_METHOD("free_rid", "rid"), &RenderingServer::free); // shouldn't conflict with Object::free()
+ ClassDB::bind_method(D_METHOD("free_rid", "rid"), &RenderingServer::free); // Shouldn't conflict with Object::free().
/* Misc */
- ClassDB::bind_method(D_METHOD("request_frame_drawn_callback", "where", "method", "userdata"), &RenderingServer::request_frame_drawn_callback);
+ ClassDB::bind_method(D_METHOD("request_frame_drawn_callback", "callable"), &RenderingServer::request_frame_drawn_callback);
ClassDB::bind_method(D_METHOD("has_changed"), &RenderingServer::has_changed);
ClassDB::bind_method(D_METHOD("get_rendering_info", "info"), &RenderingServer::get_rendering_info);
ClassDB::bind_method(D_METHOD("get_video_adapter_name"), &RenderingServer::get_video_adapter_name);
ClassDB::bind_method(D_METHOD("get_video_adapter_vendor"), &RenderingServer::get_video_adapter_vendor);
+ ClassDB::bind_method(D_METHOD("get_video_adapter_type"), &RenderingServer::get_video_adapter_type);
ClassDB::bind_method(D_METHOD("make_sphere_mesh", "latitudes", "longitudes", "radius"), &RenderingServer::make_sphere_mesh);
ClassDB::bind_method(D_METHOD("get_test_cube"), &RenderingServer::get_test_cube);
@@ -2781,7 +2818,6 @@ RenderingServer::RenderingServer() {
GLOBAL_DEF_RST("rendering/textures/vram_compression/import_s3tc", true);
GLOBAL_DEF_RST("rendering/textures/vram_compression/import_etc", false);
GLOBAL_DEF_RST("rendering/textures/vram_compression/import_etc2", true);
- GLOBAL_DEF_RST("rendering/textures/vram_compression/import_pvrtc", false);
GLOBAL_DEF("rendering/textures/lossless_compression/force_png", false);
GLOBAL_DEF("rendering/textures/lossless_compression/webp_compression_level", 2);
@@ -2793,14 +2829,14 @@ RenderingServer::RenderingServer() {
GLOBAL_DEF("rendering/shadows/directional_shadow/size", 4096);
GLOBAL_DEF("rendering/shadows/directional_shadow/size.mobile", 2048);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/directional_shadow/size", PropertyInfo(Variant::INT, "rendering/shadows/directional_shadow/size", PROPERTY_HINT_RANGE, "256,16384"));
- GLOBAL_DEF("rendering/shadows/directional_shadow/soft_shadow_quality", 2);
+ GLOBAL_DEF("rendering/shadows/directional_shadow/soft_shadow_quality", 3);
GLOBAL_DEF("rendering/shadows/directional_shadow/soft_shadow_quality.mobile", 0);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/directional_shadow/soft_shadow_quality", PropertyInfo(Variant::INT, "rendering/shadows/directional_shadow/soft_shadow_quality", PROPERTY_HINT_ENUM, "Hard (Fastest),Soft Low (Fast),Soft Medium (Average),Soft High (Slow),Soft Ultra (Slowest)"));
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/directional_shadow/soft_shadow_quality", PropertyInfo(Variant::INT, "rendering/shadows/directional_shadow/soft_shadow_quality", PROPERTY_HINT_ENUM, "Hard (Fastest),Soft Very Low (Faster),Soft Low (Fast),Soft Medium (Average),Soft High (Slow),Soft Ultra (Slowest)"));
GLOBAL_DEF("rendering/shadows/directional_shadow/16_bits", true);
- GLOBAL_DEF("rendering/shadows/shadows/soft_shadow_quality", 2);
+ GLOBAL_DEF("rendering/shadows/shadows/soft_shadow_quality", 3);
GLOBAL_DEF("rendering/shadows/shadows/soft_shadow_quality.mobile", 0);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/shadows/soft_shadow_quality", PropertyInfo(Variant::INT, "rendering/shadows/shadows/soft_shadow_quality", PROPERTY_HINT_ENUM, "Hard (Fastest),Soft Low (Fast),Soft Medium (Average),Soft High (Slow),Soft Ultra (Slowest)"));
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/shadows/soft_shadow_quality", PropertyInfo(Variant::INT, "rendering/shadows/shadows/soft_shadow_quality", PROPERTY_HINT_ENUM, "Hard (Fastest),Soft Very Low (Faster),Soft Low (Fast),Soft Medium (Average),Soft High (Slow),Soft Ultra (Slowest)"));
GLOBAL_DEF("rendering/2d/shadow_atlas/size", 2048);
@@ -2810,12 +2846,12 @@ RenderingServer::RenderingServer() {
PropertyInfo(Variant::INT,
"rendering/vulkan/rendering/back_end",
PROPERTY_HINT_ENUM, "Forward Clustered (Supports Desktop Only),Forward Mobile (Supports Desktop and Mobile)"));
-
- GLOBAL_DEF("rendering/3d/viewport/scale", 1.0);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/3d/viewport/scale",
- PropertyInfo(Variant::FLOAT,
- "rendering/3d/viewport/scale",
- PROPERTY_HINT_RANGE, "0.25,2.0,0.01"));
+ // Already defined in RenderingDeviceVulkan::initialize which runs before this code.
+ // We re-define them here just for doctool's sake. Make sure to keep default values in sync.
+ GLOBAL_DEF("rendering/vulkan/staging_buffer/block_size_kb", 256);
+ GLOBAL_DEF("rendering/vulkan/staging_buffer/max_size_mb", 128);
+ GLOBAL_DEF("rendering/vulkan/staging_buffer/texture_upload_region_size_px", 64);
+ GLOBAL_DEF("rendering/vulkan/descriptor_pools/max_descriptors_per_pool", 64);
GLOBAL_DEF("rendering/shader_compiler/shader_cache/enabled", true);
GLOBAL_DEF("rendering/shader_compiler/shader_cache/compress", true);
@@ -2824,7 +2860,7 @@ RenderingServer::RenderingServer() {
GLOBAL_DEF("rendering/shader_compiler/shader_cache/strip_debug.release", true);
GLOBAL_DEF("rendering/reflections/sky_reflections/roughness_layers", 8);
- GLOBAL_DEF("rendering/reflections/sky_reflections/texture_array_reflections", true);
+ GLOBAL_DEF_RST("rendering/reflections/sky_reflections/texture_array_reflections", true);
GLOBAL_DEF("rendering/reflections/sky_reflections/texture_array_reflections.mobile", false);
GLOBAL_DEF("rendering/reflections/sky_reflections/ggx_samples", 1024);
GLOBAL_DEF("rendering/reflections/sky_reflections/ggx_samples.mobile", 128);
@@ -2846,7 +2882,6 @@ RenderingServer::RenderingServer() {
GLOBAL_DEF("rendering/shading/overrides/force_blinn_over_ggx.mobile", true);
GLOBAL_DEF("rendering/driver/depth_prepass/enable", true);
- GLOBAL_DEF("rendering/driver/depth_prepass/disable_for_vendors", "PowerVR,Mali,Adreno,Apple");
GLOBAL_DEF_RST("rendering/textures/default_filters/use_nearest_mipmap_filter", false);
GLOBAL_DEF_RST("rendering/textures/default_filters/anisotropic_filtering_level", 2);
@@ -2871,12 +2906,47 @@ RenderingServer::RenderingServer() {
GLOBAL_DEF("rendering/environment/ssao/fadeout_to", 300.0);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/environment/ssao/fadeout_to", PropertyInfo(Variant::FLOAT, "rendering/environment/ssao/fadeout_to", PROPERTY_HINT_RANGE, "64,65536,0.1,or_greater"));
+ GLOBAL_DEF("rendering/environment/ssil/quality", 2);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/environment/ssil/quality", PropertyInfo(Variant::INT, "rendering/environment/ssil/quality", PROPERTY_HINT_ENUM, "Very Low (Fast),Low (Fast),Medium (Average),High (Slow),Ultra (Custom)"));
+ GLOBAL_DEF("rendering/environment/ssil/half_size", true);
+ GLOBAL_DEF("rendering/environment/ssil/adaptive_target", 0.5);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/environment/ssil/adaptive_target", PropertyInfo(Variant::FLOAT, "rendering/environment/ssil/adaptive_target", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"));
+ GLOBAL_DEF("rendering/environment/ssil/blur_passes", 4);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/environment/ssil/blur_passes", PropertyInfo(Variant::INT, "rendering/environment/ssil/blur_passes", PROPERTY_HINT_RANGE, "0,6"));
+ GLOBAL_DEF("rendering/environment/ssil/fadeout_from", 50.0);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/environment/ssil/fadeout_from", PropertyInfo(Variant::FLOAT, "rendering/environment/ssil/fadeout_from", PROPERTY_HINT_RANGE, "0.0,512,0.1,or_greater"));
+ GLOBAL_DEF("rendering/environment/ssil/fadeout_to", 300.0);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/environment/ssil/fadeout_to", PropertyInfo(Variant::FLOAT, "rendering/environment/ssil/fadeout_to", PROPERTY_HINT_RANGE, "64,65536,0.1,or_greater"));
+
GLOBAL_DEF("rendering/anti_aliasing/screen_space_roughness_limiter/enabled", true);
GLOBAL_DEF("rendering/anti_aliasing/screen_space_roughness_limiter/amount", 0.25);
GLOBAL_DEF("rendering/anti_aliasing/screen_space_roughness_limiter/limit", 0.18);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/anti_aliasing/screen_space_roughness_limiter/amount", PropertyInfo(Variant::FLOAT, "rendering/anti_aliasing/screen_space_roughness_limiter/amount", PROPERTY_HINT_RANGE, "0.01,4.0,0.01"));
ProjectSettings::get_singleton()->set_custom_property_info("rendering/anti_aliasing/screen_space_roughness_limiter/limit", PropertyInfo(Variant::FLOAT, "rendering/anti_aliasing/screen_space_roughness_limiter/limit", PROPERTY_HINT_RANGE, "0.01,1.0,0.01"));
+ GLOBAL_DEF_RST("rendering/scaling_3d/mode", 0);
+ GLOBAL_DEF_RST("rendering/scaling_3d/scale", 1.0);
+ GLOBAL_DEF_RST("rendering/scaling_3d/fsr_sharpness", 0.2f);
+ GLOBAL_DEF_RST("rendering/scaling_3d/fsr_mipmap_bias", 0.0f);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/scaling_3d/mode",
+ PropertyInfo(Variant::INT,
+ "rendering/scaling_3d/mode",
+ PROPERTY_HINT_ENUM, "Bilinear (Fastest),FSR (Fast)"));
+
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/scaling_3d/scale",
+ PropertyInfo(Variant::FLOAT,
+ "rendering/scaling_3d/scale",
+ PROPERTY_HINT_RANGE, "0.25,2.0,0.01"));
+
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/scaling_3d/fsr_sharpness",
+ PropertyInfo(Variant::FLOAT,
+ "rendering/scaling_3d/fsr_sharpness",
+ PROPERTY_HINT_RANGE, "0,2,0.1"));
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/scaling_3d/fsr_mipmap_bias",
+ PropertyInfo(Variant::FLOAT,
+ "rendering/scaling_3d/fsr_mipmap_bias",
+ PROPERTY_HINT_RANGE, "-2,2,0.1"));
+
GLOBAL_DEF("rendering/textures/decals/filter", DECAL_FILTER_LINEAR_MIPMAPS);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/textures/decals/filter", PropertyInfo(Variant::INT, "rendering/textures/decals/filter", PROPERTY_HINT_ENUM, "Nearest (Fast),Nearest+Mipmaps,Linear,Linear+Mipmaps,Linear+Mipmaps Anisotropic (Slow)"));
GLOBAL_DEF("rendering/textures/light_projectors/filter", LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS);
@@ -2915,7 +2985,7 @@ RenderingServer::RenderingServer() {
GLOBAL_DEF("rendering/environment/volumetric_fog/volume_size", 64);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/environment/volumetric_fog/volume_size", PropertyInfo(Variant::INT, "rendering/environment/volumetric_fog/volume_size", PROPERTY_HINT_RANGE, "16,512,1"));
- GLOBAL_DEF("rendering/environment/volumetric_fog/volume_depth", 128);
+ GLOBAL_DEF("rendering/environment/volumetric_fog/volume_depth", 64);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/environment/volumetric_fog/volume_depth", PropertyInfo(Variant::INT, "rendering/environment/volumetric_fog/volume_depth", PROPERTY_HINT_RANGE, "16,512,1"));
GLOBAL_DEF("rendering/environment/volumetric_fog/use_filter", 1);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/environment/volumetric_fog/use_filter", PropertyInfo(Variant::INT, "rendering/environment/volumetric_fog/use_filter", PROPERTY_HINT_ENUM, "No (Faster),Yes (Higher Quality)"));
@@ -2931,6 +3001,43 @@ RenderingServer::RenderingServer() {
ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/cluster_builder/max_clustered_elements", PropertyInfo(Variant::FLOAT, "rendering/limits/cluster_builder/max_clustered_elements", PROPERTY_HINT_RANGE, "32,8192,1"));
GLOBAL_DEF_RST("rendering/xr/enabled", false);
+
+ GLOBAL_DEF_RST("rendering/2d/options/use_software_skinning", true);
+ GLOBAL_DEF_RST("rendering/2d/options/ninepatch_mode", 1);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/2d/options/ninepatch_mode", PropertyInfo(Variant::INT, "rendering/2d/options/ninepatch_mode", PROPERTY_HINT_ENUM, "Fixed,Scaling"));
+
+ GLOBAL_DEF_RST("rendering/2d/opengl/batching_send_null", 0);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/2d/opengl/batching_send_null", PropertyInfo(Variant::INT, "rendering/2d/opengl/batching_send_null", PROPERTY_HINT_ENUM, "Default (On),Off,On"));
+ GLOBAL_DEF_RST("rendering/2d/opengl/batching_stream", 0);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/2d/opengl/batching_stream", PropertyInfo(Variant::INT, "rendering/2d/opengl/batching_stream", PROPERTY_HINT_ENUM, "Default (Off),Off,On"));
+ GLOBAL_DEF_RST("rendering/2d/opengl/legacy_orphan_buffers", 0);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/2d/opengl/legacy_orphan_buffers", PropertyInfo(Variant::INT, "rendering/2d/opengl/legacy_orphan_buffers", PROPERTY_HINT_ENUM, "Default (On),Off,On"));
+ GLOBAL_DEF_RST("rendering/2d/opengl/legacy_stream", 0);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/2d/opengl/legacy_stream", PropertyInfo(Variant::INT, "rendering/2d/opengl/legacy_stream", PROPERTY_HINT_ENUM, "Default (On),Off,On"));
+
+ GLOBAL_DEF("rendering/batching/options/use_batching", false);
+ GLOBAL_DEF_RST("rendering/batching/options/use_batching_in_editor", false);
+ GLOBAL_DEF("rendering/batching/options/single_rect_fallback", false);
+ GLOBAL_DEF("rendering/batching/parameters/max_join_item_commands", 16);
+ GLOBAL_DEF("rendering/batching/parameters/colored_vertex_format_threshold", 0.25f);
+ GLOBAL_DEF("rendering/batching/lights/scissor_area_threshold", 1.0f);
+ GLOBAL_DEF("rendering/batching/lights/max_join_items", 32);
+ GLOBAL_DEF("rendering/batching/parameters/batch_buffer_size", 16384);
+ GLOBAL_DEF("rendering/batching/parameters/item_reordering_lookahead", 4);
+ GLOBAL_DEF("rendering/batching/debug/flash_batching", false);
+ GLOBAL_DEF("rendering/batching/debug/diagnose_frame", false);
+ GLOBAL_DEF("rendering/gles2/compatibility/disable_half_float", false);
+ GLOBAL_DEF("rendering/gles2/compatibility/enable_high_float.Android", false);
+ GLOBAL_DEF("rendering/batching/precision/uv_contract", false);
+ GLOBAL_DEF("rendering/batching/precision/uv_contract_amount", 100);
+
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/batching/parameters/max_join_item_commands", PropertyInfo(Variant::INT, "rendering/batching/parameters/max_join_item_commands", PROPERTY_HINT_RANGE, "0,65535"));
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/batching/parameters/colored_vertex_format_threshold", PropertyInfo(Variant::FLOAT, "rendering/batching/parameters/colored_vertex_format_threshold", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"));
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/batching/parameters/batch_buffer_size", PropertyInfo(Variant::INT, "rendering/batching/parameters/batch_buffer_size", PROPERTY_HINT_RANGE, "1024,65535,1024"));
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/batching/lights/scissor_area_threshold", PropertyInfo(Variant::FLOAT, "rendering/batching/lights/scissor_area_threshold", PROPERTY_HINT_RANGE, "0.0,1.0"));
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/batching/lights/max_join_items", PropertyInfo(Variant::INT, "rendering/batching/lights/max_join_items", PROPERTY_HINT_RANGE, "0,512"));
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/batching/parameters/item_reordering_lookahead", PropertyInfo(Variant::INT, "rendering/batching/parameters/item_reordering_lookahead", PROPERTY_HINT_RANGE, "0,256"));
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/batching/precision/uv_contract_amount", PropertyInfo(Variant::INT, "rendering/batching/precision/uv_contract_amount", PROPERTY_HINT_RANGE, "0,10000"));
}
RenderingServer::~RenderingServer() {
diff --git a/servers/rendering_server.h b/servers/rendering_server.h
index b50da66d03..945fd052c6 100644
--- a/servers/rendering_server.h
+++ b/servers/rendering_server.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -41,7 +41,6 @@
#include "servers/display_server.h"
#include "servers/rendering/renderer_thread_pool.h"
#include "servers/rendering/rendering_device.h"
-#include "servers/rendering/shader_language.h"
class RenderingServer : public Object {
GDCLASS(RenderingServer, Object);
@@ -55,6 +54,9 @@ class RenderingServer : public Object {
RendererThreadPool *thread_pool = nullptr;
+ const Vector2 SMALL_VEC2 = Vector2(CMP_EPSILON, CMP_EPSILON);
+ const Vector3 SMALL_VEC3 = Vector3(CMP_EPSILON, CMP_EPSILON, CMP_EPSILON);
+
protected:
RID _make_test_cube();
void _free_internal_rids();
@@ -108,7 +110,7 @@ public:
virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) = 0;
virtual void texture_proxy_update(RID p_texture, RID p_proxy_to) = 0;
- //these two APIs can be used together or in combination with the others.
+ // These two APIs can be used together or in combination with the others.
virtual RID texture_2d_placeholder_create() = 0;
virtual RID texture_2d_layered_placeholder_create(TextureLayeredType p_layered_type) = 0;
virtual RID texture_3d_placeholder_create() = 0;
@@ -161,6 +163,7 @@ public:
SHADER_CANVAS_ITEM,
SHADER_PARTICLES,
SHADER_SKY,
+ SHADER_FOG,
SHADER_MAX
};
@@ -171,8 +174,8 @@ public:
virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const = 0;
virtual Variant shader_get_param_default(RID p_shader, const StringName &p_param) const = 0;
- virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) = 0;
- virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const = 0;
+ virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index = 0) = 0;
+ virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index = 0) const = 0;
struct ShaderNativeSourceCode {
struct Version {
@@ -209,18 +212,18 @@ public:
enum ArrayType {
ARRAY_VERTEX = 0, // RG32F or RGB32F (depending on 2D bit)
- ARRAY_NORMAL = 1, // A2B10G10R10, A is ignored
- ARRAY_TANGENT = 2, // A2B10G10R10, A flips sign of binormal
+ ARRAY_NORMAL = 1, // A2B10G10R10, A is ignored.
+ ARRAY_TANGENT = 2, // A2B10G10R10, A flips sign of binormal.
ARRAY_COLOR = 3, // RGBA8
ARRAY_TEX_UV = 4, // RG32F
ARRAY_TEX_UV2 = 5, // RG32F
- ARRAY_CUSTOM0 = 6, // depends on ArrayCustomFormat
+ ARRAY_CUSTOM0 = 6, // Depends on ArrayCustomFormat.
ARRAY_CUSTOM1 = 7,
ARRAY_CUSTOM2 = 8,
ARRAY_CUSTOM3 = 9,
ARRAY_BONES = 10, // RGBA16UI (x2 if 8 weights)
ARRAY_WEIGHTS = 11, // RGBA16UNORM (x2 if 8 weights)
- ARRAY_INDEX = 12, // 16 or 32 bits depending on length > 0xFFFF
+ ARRAY_INDEX = 12, // 16 or 32 bits depending on length > 0xFFFF.
ARRAY_MAX = 13
};
@@ -242,7 +245,7 @@ public:
enum ArrayFormat {
/* ARRAY FORMAT FLAGS */
- ARRAY_FORMAT_VERTEX = 1 << ARRAY_VERTEX, // mandatory
+ ARRAY_FORMAT_VERTEX = 1 << ARRAY_VERTEX, // Mandatory
ARRAY_FORMAT_NORMAL = 1 << ARRAY_NORMAL,
ARRAY_FORMAT_TANGENT = 1 << ARRAY_TANGENT,
ARRAY_FORMAT_COLOR = 1 << ARRAY_COLOR,
@@ -286,9 +289,9 @@ public:
PrimitiveType primitive = PRIMITIVE_MAX;
uint32_t format = 0;
- Vector<uint8_t> vertex_data; // vertex, normal, tangent (change with skinning, blendshape)
- Vector<uint8_t> attribute_data; // color,uv, uv2, custom0-3
- Vector<uint8_t> skin_data; // bone index, bone weight
+ Vector<uint8_t> vertex_data; // Vertex, Normal, Tangent (change with skinning, blendshape).
+ Vector<uint8_t> attribute_data; // Color, UV, UV2, Custom0-3.
+ Vector<uint8_t> skin_data; // Bone index, Bone weight.
uint32_t vertex_count = 0;
Vector<uint8_t> index_data;
uint32_t index_count = 0;
@@ -451,7 +454,7 @@ public:
virtual void light_set_bake_mode(RID p_light, LightBakeMode p_bake_mode) = 0;
virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) = 0;
- // omni light
+ // Omni light
enum LightOmniShadowMode {
LIGHT_OMNI_SHADOW_DUAL_PARABOLOID,
LIGHT_OMNI_SHADOW_CUBE,
@@ -459,7 +462,7 @@ public:
virtual void light_omni_set_shadow_mode(RID p_light, LightOmniShadowMode p_mode) = 0;
- // directional light
+ // Directional light
enum LightDirectionalShadowMode {
LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL,
LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS,
@@ -474,6 +477,7 @@ public:
enum ShadowQuality {
SHADOW_QUALITY_HARD,
+ SHADOW_QUALITY_SOFT_VERY_LOW,
SHADOW_QUALITY_SOFT_LOW,
SHADOW_QUALITY_SOFT_MEDIUM,
SHADOW_QUALITY_SOFT_HIGH,
@@ -523,7 +527,7 @@ public:
virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) = 0;
virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) = 0;
virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution) = 0;
- virtual void reflection_probe_set_lod_threshold(RID p_probe, float p_pixels) = 0;
+ virtual void reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_pixels) = 0;
/* DECAL API */
@@ -669,7 +673,7 @@ public:
virtual AABB particles_get_current_aabb(RID p_particles) = 0;
- virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) = 0; //this is only used for 2D, in 3D it's automatic
+ virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) = 0; // This is only used for 2D, in 3D it's automatic.
/* PARTICLES COLLISION API */
@@ -687,16 +691,16 @@ public:
virtual void particles_collision_set_collision_type(RID p_particles_collision, ParticlesCollisionType p_type) = 0;
virtual void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) = 0;
- virtual void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) = 0; //for spheres
- virtual void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) = 0; //for non-spheres
+ virtual void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) = 0; // For spheres.
+ virtual void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) = 0; // For non-spheres.
virtual void particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) = 0;
virtual void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) = 0;
virtual void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) = 0;
- virtual void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) = 0; //for SDF and vector field, heightfield is dynamic
+ virtual void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) = 0; // For SDF and vector field, heightfield is dynamic.
- virtual void particles_collision_height_field_update(RID p_particles_collision) = 0; //for SDF and vector field
+ virtual void particles_collision_height_field_update(RID p_particles_collision) = 0; // For SDF and vector field.
- enum ParticlesCollisionHeightfieldResolution { //longest axis resolution
+ enum ParticlesCollisionHeightfieldResolution { // Longest axis resolution.
PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_256,
PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_512,
PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_1024,
@@ -706,7 +710,21 @@ public:
PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_MAX,
};
- virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, ParticlesCollisionHeightfieldResolution p_resolution) = 0; //for SDF and vector field
+ virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, ParticlesCollisionHeightfieldResolution p_resolution) = 0; // For SDF and vector field.
+
+ /* FOG VOLUME API */
+
+ virtual RID fog_volume_create() = 0;
+
+ enum FogVolumeShape {
+ FOG_VOLUME_SHAPE_ELLIPSOID,
+ FOG_VOLUME_SHAPE_BOX,
+ FOG_VOLUME_SHAPE_WORLD,
+ };
+
+ virtual void fog_volume_set_shape(RID p_fog_volume, FogVolumeShape p_shape) = 0;
+ virtual void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) = 0;
+ virtual void fog_volume_set_material(RID p_fog_volume, RID p_material) = 0;
/* VISIBILITY NOTIFIER API */
@@ -734,7 +752,7 @@ public:
/* VIEWPORT API */
enum CanvasItemTextureFilter {
- CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, //uses canvas item setting for draw command, uses global setting for canvas item
+ CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, // Uses canvas item setting for draw command, uses global setting for canvas item.
CANVAS_ITEM_TEXTURE_FILTER_NEAREST,
CANVAS_ITEM_TEXTURE_FILTER_LINEAR,
CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS,
@@ -745,7 +763,7 @@ public:
};
enum CanvasItemTextureRepeat {
- CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, //uses canvas item setting for draw command, uses global setting for canvas item
+ CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, // Uses canvas item setting for draw command, uses global setting for canvas item.
CANVAS_ITEM_TEXTURE_REPEAT_DISABLED,
CANVAS_ITEM_TEXTURE_REPEAT_ENABLED,
CANVAS_ITEM_TEXTURE_REPEAT_MIRROR,
@@ -754,8 +772,13 @@ public:
virtual RID viewport_create() = 0;
+ enum ViewportScaling3DMode {
+ VIEWPORT_SCALING_3D_MODE_BILINEAR,
+ VIEWPORT_SCALING_3D_MODE_FSR,
+ VIEWPORT_SCALING_3D_MODE_MAX
+ };
+
virtual void viewport_set_use_xr(RID p_viewport, bool p_use_xr) = 0;
- virtual void viewport_set_scale_3d(RID p_viewport, float p_scale_3d) = 0;
virtual void viewport_set_size(RID p_viewport, int p_width, int p_height) = 0;
virtual void viewport_set_active(RID p_viewport, bool p_active) = 0;
virtual void viewport_set_parent_viewport(RID p_viewport, RID p_parent_viewport) = 0;
@@ -763,10 +786,15 @@ public:
virtual void viewport_attach_to_screen(RID p_viewport, const Rect2 &p_rect = Rect2(), DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID) = 0;
virtual void viewport_set_render_direct_to_screen(RID p_viewport, bool p_enable) = 0;
+ virtual void viewport_set_scaling_3d_mode(RID p_viewport, ViewportScaling3DMode p_scaling_3d_mode) = 0;
+ virtual void viewport_set_scaling_3d_scale(RID p_viewport, float p_scaling_3d_scale) = 0;
+ virtual void viewport_set_fsr_sharpness(RID p_viewport, float p_fsr_sharpness) = 0;
+ virtual void viewport_set_fsr_mipmap_bias(RID p_viewport, float p_fsr_mipmap_bias) = 0;
+
enum ViewportUpdateMode {
VIEWPORT_UPDATE_DISABLED,
- VIEWPORT_UPDATE_ONCE, //then goes to disabled, must be manually updated
- VIEWPORT_UPDATE_WHEN_VISIBLE, // default
+ VIEWPORT_UPDATE_ONCE, // Then goes to disabled, must be manually updated.
+ VIEWPORT_UPDATE_WHEN_VISIBLE, // Default
VIEWPORT_UPDATE_WHEN_PARENT_VISIBLE,
VIEWPORT_UPDATE_ALWAYS
};
@@ -842,7 +870,7 @@ public:
virtual void viewport_set_use_debanding(RID p_viewport, bool p_use_debanding) = 0;
- virtual void viewport_set_lod_threshold(RID p_viewport, float p_pixels) = 0;
+ virtual void viewport_set_mesh_lod_threshold(RID p_viewport, float p_pixels) = 0;
virtual void viewport_set_use_occlusion_culling(RID p_viewport, bool p_use_debanding) = 0;
virtual void viewport_set_occlusion_rays_per_thread(int p_rays_per_thread) = 0;
@@ -884,6 +912,7 @@ public:
VIEWPORT_DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS,
VIEWPORT_DEBUG_DRAW_SCENE_LUMINANCE,
VIEWPORT_DEBUG_DRAW_SSAO,
+ VIEWPORT_DEBUG_DRAW_SSIL,
VIEWPORT_DEBUG_DRAW_PSSM_SPLITS,
VIEWPORT_DEBUG_DRAW_DECAL_ATLAS,
VIEWPORT_DEBUG_DRAW_SDFGI,
@@ -1000,19 +1029,25 @@ public:
virtual void environment_set_ssao_quality(EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) = 0;
- enum EnvironmentSDFGICascades {
- ENV_SDFGI_CASCADES_4,
- ENV_SDFGI_CASCADES_6,
- ENV_SDFGI_CASCADES_8,
+ virtual void environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) = 0;
+
+ enum EnvironmentSSILQuality {
+ ENV_SSIL_QUALITY_VERY_LOW,
+ ENV_SSIL_QUALITY_LOW,
+ ENV_SSIL_QUALITY_MEDIUM,
+ ENV_SSIL_QUALITY_HIGH,
+ ENV_SSIL_QUALITY_ULTRA,
};
+ virtual void environment_set_ssil_quality(EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) = 0;
+
enum EnvironmentSDFGIYScale {
ENV_SDFGI_Y_SCALE_DISABLED,
ENV_SDFGI_Y_SCALE_75_PERCENT,
ENV_SDFGI_Y_SCALE_50_PERCENT
};
- virtual void environment_set_sdfgi(RID p_env, bool p_enable, EnvironmentSDFGICascades p_cascades, float p_min_cell_size, EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) = 0;
+ virtual void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) = 0;
enum EnvironmentSDFGIRayCount {
ENV_SDFGI_RAY_COUNT_4,
@@ -1052,7 +1087,7 @@ public:
virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) = 0;
- virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount) = 0;
+ virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) = 0;
virtual void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) = 0;
virtual void environment_set_volumetric_fog_filter_active(bool p_enable) = 0;
@@ -1117,6 +1152,7 @@ public:
INSTANCE_LIGHTMAP,
INSTANCE_OCCLUDER,
INSTANCE_VISIBLITY_NOTIFIER,
+ INSTANCE_FOG_VOLUME,
INSTANCE_MAX,
INSTANCE_GEOMETRY_MASK = (1 << INSTANCE_MESH) | (1 << INSTANCE_MULTIMESH) | (1 << INSTANCE_PARTICLES)
@@ -1142,7 +1178,9 @@ public:
virtual void instance_set_extra_visibility_margin(RID p_instance, real_t p_margin) = 0;
virtual void instance_set_visibility_parent(RID p_instance, RID p_parent_instance) = 0;
- // don't use these in a game!
+ virtual void instance_set_ignore_culling(RID p_instance, bool p_enabled) = 0;
+
+ // Don't use these in a game!
virtual Vector<ObjectID> instances_cull_aabb(const AABB &p_aabb, RID p_scenario = RID()) const = 0;
virtual Vector<ObjectID> instances_cull_ray(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario = RID()) const = 0;
virtual Vector<ObjectID> instances_cull_convex(const Vector<Plane> &p_convex, RID p_scenario = RID()) const = 0;
@@ -1166,12 +1204,20 @@ public:
SHADOW_CASTING_SETTING_SHADOWS_ONLY,
};
+ enum VisibilityRangeFadeMode {
+ VISIBILITY_RANGE_FADE_DISABLED,
+ VISIBILITY_RANGE_FADE_SELF,
+ VISIBILITY_RANGE_FADE_DEPENDENCIES,
+ };
+
virtual void instance_geometry_set_flag(RID p_instance, InstanceFlags p_flags, bool p_enabled) = 0;
virtual void instance_geometry_set_cast_shadows_setting(RID p_instance, ShadowCastingSetting p_shadow_casting_setting) = 0;
virtual void instance_geometry_set_material_override(RID p_instance, RID p_material) = 0;
- virtual void instance_geometry_set_visibility_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin) = 0;
+ virtual void instance_geometry_set_material_overlay(RID p_instance, RID p_material) = 0;
+ virtual void instance_geometry_set_visibility_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin, VisibilityRangeFadeMode p_fade_mode) = 0;
virtual void instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice) = 0;
virtual void instance_geometry_set_lod_bias(RID p_instance, float p_lod_bias) = 0;
+ virtual void instance_geometry_set_transparency(RID p_instance, float p_transparency) = 0;
virtual void instance_geometry_set_shader_parameter(RID p_instance, const StringName &, const Variant &p_value) = 0;
virtual Variant instance_geometry_get_shader_parameter(RID p_instance, const StringName &) const = 0;
@@ -1209,7 +1255,7 @@ public:
virtual void canvas_texture_set_channel(RID p_canvas_texture, CanvasTextureChannel p_channel, RID p_texture) = 0;
virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) = 0;
- //takes effect only for new draw commands
+ // Takes effect only for new draw commands.
virtual void canvas_texture_set_texture_filter(RID p_canvas_texture, CanvasItemTextureFilter p_filter) = 0;
virtual void canvas_texture_set_texture_repeat(RID p_canvas_texture, CanvasItemTextureRepeat p_repeat) = 0;
@@ -1403,16 +1449,16 @@ public:
virtual void global_variables_load_settings(bool p_load_textures) = 0;
virtual void global_variables_clear() = 0;
- static ShaderLanguage::DataType global_variable_type_get_shader_datatype(GlobalVariableType p_type);
+ static int global_variable_type_get_shader_datatype(GlobalVariableType p_type);
/* FREE */
- virtual void free(RID p_rid) = 0; ///< free RIDs associated with the rendering server
-
- virtual void request_frame_drawn_callback(Object *p_where, const StringName &p_method, const Variant &p_userdata) = 0;
+ virtual void free(RID p_rid) = 0; // Free RIDs associated with the rendering server.
/* EVENT QUEUING */
+ virtual void request_frame_drawn_callback(const Callable &p_callable) = 0;
+
virtual void draw(bool p_swap_buffers = true, double frame_step = 0.0) = 0;
virtual void sync() = 0;
virtual bool has_changed() const = 0;
@@ -1434,6 +1480,7 @@ public:
virtual uint64_t get_rendering_info(RenderingInfo p_info) = 0;
virtual String get_video_adapter_name() const = 0;
virtual String get_video_adapter_vendor() const = 0;
+ virtual RenderingDevice::DeviceType get_video_adapter_type() const = 0;
struct FrameProfileArea {
String name;
@@ -1493,7 +1540,7 @@ public:
virtual ~RenderingServer();
private:
- //binder helpers
+ // Binder helpers
RID _texture_2d_layered_create(const TypedArray<Image> &p_layers, TextureLayeredType p_layered_type);
RID _texture_3d_create(Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const TypedArray<Image> &p_data);
void _texture_3d_update(RID p_texture, const TypedArray<Image> &p_data);
@@ -1507,7 +1554,7 @@ private:
void _particles_set_trail_bind_poses(RID p_particles, const TypedArray<Transform3D> &p_bind_poses);
};
-// make variant understand the enums
+// Make variant understand the enums.
VARIANT_ENUM_CAST(RenderingServer::TextureLayeredType);
VARIANT_ENUM_CAST(RenderingServer::CubeMapLayer);
VARIANT_ENUM_CAST(RenderingServer::ShaderMode);
@@ -1534,6 +1581,8 @@ VARIANT_ENUM_CAST(RenderingServer::ParticlesDrawOrder);
VARIANT_ENUM_CAST(RenderingServer::ParticlesEmitFlags);
VARIANT_ENUM_CAST(RenderingServer::ParticlesCollisionType);
VARIANT_ENUM_CAST(RenderingServer::ParticlesCollisionHeightfieldResolution);
+VARIANT_ENUM_CAST(RenderingServer::FogVolumeShape);
+VARIANT_ENUM_CAST(RenderingServer::ViewportScaling3DMode);
VARIANT_ENUM_CAST(RenderingServer::ViewportUpdateMode);
VARIANT_ENUM_CAST(RenderingServer::ViewportClearMode);
VARIANT_ENUM_CAST(RenderingServer::ViewportMSAA);
@@ -1552,7 +1601,7 @@ VARIANT_ENUM_CAST(RenderingServer::EnvironmentGlowBlendMode);
VARIANT_ENUM_CAST(RenderingServer::EnvironmentToneMapper);
VARIANT_ENUM_CAST(RenderingServer::EnvironmentSSRRoughnessQuality);
VARIANT_ENUM_CAST(RenderingServer::EnvironmentSSAOQuality);
-VARIANT_ENUM_CAST(RenderingServer::EnvironmentSDFGICascades);
+VARIANT_ENUM_CAST(RenderingServer::EnvironmentSSILQuality);
VARIANT_ENUM_CAST(RenderingServer::EnvironmentSDFGIFramesToConverge);
VARIANT_ENUM_CAST(RenderingServer::EnvironmentSDFGIRayCount);
VARIANT_ENUM_CAST(RenderingServer::EnvironmentSDFGIFramesToUpdateLight);
@@ -1564,6 +1613,7 @@ VARIANT_ENUM_CAST(RenderingServer::ShadowQuality);
VARIANT_ENUM_CAST(RenderingServer::InstanceType);
VARIANT_ENUM_CAST(RenderingServer::InstanceFlags);
VARIANT_ENUM_CAST(RenderingServer::ShadowCastingSetting);
+VARIANT_ENUM_CAST(RenderingServer::VisibilityRangeFadeMode);
VARIANT_ENUM_CAST(RenderingServer::NinePatchAxisMode);
VARIANT_ENUM_CAST(RenderingServer::CanvasItemTextureFilter);
VARIANT_ENUM_CAST(RenderingServer::CanvasItemTextureRepeat);
diff --git a/servers/server_wrap_mt_common.h b/servers/server_wrap_mt_common.h
index 95d2e2254e..2c4aab0784 100644
--- a/servers/server_wrap_mt_common.h
+++ b/servers/server_wrap_mt_common.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
diff --git a/servers/text/text_server_extension.cpp b/servers/text/text_server_extension.cpp
index a44fee7c95..d7e7960496 100644
--- a/servers/text/text_server_extension.cpp
+++ b/servers/text/text_server_extension.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -55,6 +55,15 @@ void TextServerExtension::_bind_methods() {
GDVIRTUAL_BIND(_font_set_data, "font_rid", "data");
GDVIRTUAL_BIND(_font_set_data_ptr, "font_rid", "data_ptr", "data_size");
+ GDVIRTUAL_BIND(_font_set_style, "font_rid", "style");
+ GDVIRTUAL_BIND(_font_get_style, "font_rid");
+
+ GDVIRTUAL_BIND(_font_set_name, "font_rid", "name");
+ GDVIRTUAL_BIND(_font_get_name, "font_rid");
+
+ GDVIRTUAL_BIND(_font_set_style_name, "font_rid", "name_style");
+ GDVIRTUAL_BIND(_font_get_style_name, "font_rid");
+
GDVIRTUAL_BIND(_font_set_antialiased, "font_rid", "antialiased");
GDVIRTUAL_BIND(_font_is_antialiased, "font_rid");
@@ -165,6 +174,9 @@ void TextServerExtension::_bind_methods() {
GDVIRTUAL_BIND(_font_remove_script_support_override, "font_rid", "script");
GDVIRTUAL_BIND(_font_get_script_support_overrides, "font_rid");
+ GDVIRTUAL_BIND(_font_set_opentype_feature_overrides, "font_rid", "overrides");
+ GDVIRTUAL_BIND(_font_get_opentype_feature_overrides, "font_rid");
+
GDVIRTUAL_BIND(_font_supported_feature_list, "font_rid");
GDVIRTUAL_BIND(_font_supported_variation_list, "font_rid");
@@ -182,9 +194,13 @@ void TextServerExtension::_bind_methods() {
GDVIRTUAL_BIND(_shaped_text_set_direction, "shaped", "direction");
GDVIRTUAL_BIND(_shaped_text_get_direction, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_get_inferred_direction, "shaped");
GDVIRTUAL_BIND(_shaped_text_set_bidi_override, "shaped", "override");
+ GDVIRTUAL_BIND(_shaped_text_set_custom_punctuation, "shaped", "punct");
+ GDVIRTUAL_BIND(_shaped_text_get_custom_punctuation, "shaped");
+
GDVIRTUAL_BIND(_shaped_text_set_orientation, "shaped", "orientation");
GDVIRTUAL_BIND(_shaped_text_get_orientation, "shaped");
@@ -248,12 +264,16 @@ void TextServerExtension::_bind_methods() {
GDVIRTUAL_BIND(_shaped_text_draw, "shaped", "canvas", "pos", "clip_l", "clip_r", "color");
GDVIRTUAL_BIND(_shaped_text_draw_outline, "shaped", "canvas", "pos", "clip_l", "clip_r", "outline_size", "color");
+ GDVIRTUAL_BIND(_shaped_text_get_grapheme_bounds, "shaped", "pos");
GDVIRTUAL_BIND(_shaped_text_next_grapheme_pos, "shaped", "pos");
GDVIRTUAL_BIND(_shaped_text_prev_grapheme_pos, "shaped", "pos");
GDVIRTUAL_BIND(_format_number, "string", "language");
GDVIRTUAL_BIND(_parse_number, "string", "language");
GDVIRTUAL_BIND(_percent_sign, "language");
+
+ GDVIRTUAL_BIND(_string_to_upper, "string", "language");
+ GDVIRTUAL_BIND(_string_to_lower, "string", "language");
}
bool TextServerExtension::has_feature(Feature p_feature) const {
@@ -368,6 +388,42 @@ void TextServerExtension::font_set_data_ptr(RID p_font_rid, const uint8_t *p_dat
GDVIRTUAL_CALL(_font_set_data_ptr, p_font_rid, p_data_ptr, p_data_size);
}
+void TextServerExtension::font_set_style(RID p_font_rid, uint32_t /*FontStyle*/ p_style) {
+ GDVIRTUAL_CALL(_font_set_style, p_font_rid, p_style);
+}
+
+uint32_t /*FontStyle*/ TextServerExtension::font_get_style(RID p_font_rid) const {
+ uint32_t ret;
+ if (GDVIRTUAL_CALL(_font_get_style, p_font_rid, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+void TextServerExtension::font_set_style_name(RID p_font_rid, const String &p_name) {
+ GDVIRTUAL_CALL(_font_set_style_name, p_font_rid, p_name);
+}
+
+String TextServerExtension::font_get_style_name(RID p_font_rid) const {
+ String ret;
+ if (GDVIRTUAL_CALL(_font_get_style_name, p_font_rid, ret)) {
+ return ret;
+ }
+ return String();
+}
+
+void TextServerExtension::font_set_name(RID p_font_rid, const String &p_name) {
+ GDVIRTUAL_CALL(_font_set_name, p_font_rid, p_name);
+}
+
+String TextServerExtension::font_get_name(RID p_font_rid) const {
+ String ret;
+ if (GDVIRTUAL_CALL(_font_get_name, p_font_rid, ret)) {
+ return ret;
+ }
+ return String();
+}
+
void TextServerExtension::font_set_antialiased(RID p_font_rid, bool p_antialiased) {
GDVIRTUAL_CALL(_font_set_antialiased, p_font_rid, p_antialiased);
}
@@ -820,6 +876,18 @@ Vector<String> TextServerExtension::font_get_script_support_overrides(RID p_font
return Vector<String>();
}
+void TextServerExtension::font_set_opentype_feature_overrides(RID p_font_rid, const Dictionary &p_overrides) {
+ GDVIRTUAL_CALL(_font_set_opentype_feature_overrides, p_font_rid, p_overrides);
+}
+
+Dictionary TextServerExtension::font_get_opentype_feature_overrides(RID p_font_rid) const {
+ Dictionary ret;
+ if (GDVIRTUAL_CALL(_font_get_opentype_feature_overrides, p_font_rid, ret)) {
+ return ret;
+ }
+ return Dictionary();
+}
+
Dictionary TextServerExtension::font_supported_feature_list(RID p_font_rid) const {
Dictionary ret;
if (GDVIRTUAL_CALL(_font_supported_feature_list, p_font_rid, ret)) {
@@ -890,6 +958,14 @@ TextServer::Direction TextServerExtension::shaped_text_get_direction(RID p_shape
return TextServer::Direction::DIRECTION_AUTO;
}
+TextServer::Direction TextServerExtension::shaped_text_get_inferred_direction(RID p_shaped) const {
+ int ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_inferred_direction, p_shaped, ret)) {
+ return (TextServer::Direction)ret;
+ }
+ return TextServer::Direction::DIRECTION_LTR;
+}
+
void TextServerExtension::shaped_text_set_orientation(RID p_shaped, TextServer::Orientation p_orientation) {
GDVIRTUAL_CALL(_shaped_text_set_orientation, p_shaped, p_orientation);
}
@@ -906,6 +982,18 @@ void TextServerExtension::shaped_text_set_bidi_override(RID p_shaped, const Arra
GDVIRTUAL_CALL(_shaped_text_set_bidi_override, p_shaped, p_override);
}
+void TextServerExtension::shaped_text_set_custom_punctuation(RID p_shaped, const String &p_punct) {
+ GDVIRTUAL_CALL(_shaped_text_set_custom_punctuation, p_shaped, p_punct);
+}
+
+String TextServerExtension::shaped_text_get_custom_punctuation(RID p_shaped) const {
+ String ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_custom_punctuation, p_shaped, ret)) {
+ return ret;
+ }
+ return String();
+}
+
void TextServerExtension::shaped_text_set_preserve_invalid(RID p_shaped, bool p_enabled) {
GDVIRTUAL_CALL(_shaped_text_set_preserve_invalid, p_shaped, p_enabled);
}
@@ -942,7 +1030,7 @@ bool TextServerExtension::shaped_text_add_string(RID p_shaped, const String &p_t
return false;
}
-bool TextServerExtension::shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlign p_inline_align, int p_length) {
+bool TextServerExtension::shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align, int p_length) {
bool ret;
if (GDVIRTUAL_CALL(_shaped_text_add_object, p_shaped, p_key, p_size, p_inline_align, p_length, ret)) {
return ret;
@@ -950,7 +1038,7 @@ bool TextServerExtension::shaped_text_add_object(RID p_shaped, Variant p_key, co
return false;
}
-bool TextServerExtension::shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlign p_inline_align) {
+bool TextServerExtension::shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align) {
bool ret;
if (GDVIRTUAL_CALL(_shaped_text_resize_object, p_shaped, p_key, p_size, p_inline_align, ret)) {
return ret;
@@ -1232,6 +1320,14 @@ void TextServerExtension::shaped_text_draw_outline(RID p_shaped, RID p_canvas, c
shaped_text_draw_outline(p_shaped, p_canvas, p_pos, p_clip_l, p_clip_r, p_outline_size, p_color);
}
+Vector2 TextServerExtension::shaped_text_get_grapheme_bounds(RID p_shaped, int p_pos) const {
+ Vector2 ret;
+ if (GDVIRTUAL_CALL(_shaped_text_get_grapheme_bounds, p_shaped, p_pos, ret)) {
+ return ret;
+ }
+ return TextServer::shaped_text_get_grapheme_bounds(p_shaped, p_pos);
+}
+
int TextServerExtension::shaped_text_next_grapheme_pos(RID p_shaped, int p_pos) const {
int ret;
if (GDVIRTUAL_CALL(_shaped_text_next_grapheme_pos, p_shaped, p_pos, ret)) {
@@ -1272,6 +1368,22 @@ String TextServerExtension::percent_sign(const String &p_language) const {
return TextServer::percent_sign(p_language);
}
+String TextServerExtension::string_to_upper(const String &p_string, const String &p_language) const {
+ String ret;
+ if (GDVIRTUAL_CALL(_string_to_upper, p_string, p_language, ret)) {
+ return ret;
+ }
+ return p_string;
+}
+
+String TextServerExtension::string_to_lower(const String &p_string, const String &p_language) const {
+ String ret;
+ if (GDVIRTUAL_CALL(_string_to_lower, p_string, p_language, ret)) {
+ return ret;
+ }
+ return p_string;
+}
+
TextServerExtension::TextServerExtension() {
//NOP
}
diff --git a/servers/text/text_server_extension.h b/servers/text/text_server_extension.h
index 954b2cf660..6e203f22ee 100644
--- a/servers/text/text_server_extension.h
+++ b/servers/text/text_server_extension.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -84,6 +84,21 @@ public:
GDVIRTUAL2(_font_set_data, RID, const PackedByteArray &);
GDVIRTUAL3(_font_set_data_ptr, RID, GDNativeConstPtr<const uint8_t>, uint64_t);
+ virtual void font_set_style(RID p_font_rid, uint32_t /*FontStyle*/ p_style) override;
+ virtual uint32_t /*FontStyle*/ font_get_style(RID p_font_rid) const override;
+ GDVIRTUAL2(_font_set_style, RID, uint32_t);
+ GDVIRTUAL1RC(uint32_t, _font_get_style, RID);
+
+ virtual void font_set_name(RID p_font_rid, const String &p_name) override;
+ virtual String font_get_name(RID p_font_rid) const override;
+ GDVIRTUAL2(_font_set_name, RID, const String &);
+ GDVIRTUAL1RC(String, _font_get_name, RID);
+
+ virtual void font_set_style_name(RID p_font_rid, const String &p_name) override;
+ virtual String font_get_style_name(RID p_font_rid) const override;
+ GDVIRTUAL2(_font_set_style_name, RID, const String &);
+ GDVIRTUAL1RC(String, _font_get_style_name, RID);
+
virtual void font_set_antialiased(RID p_font_rid, bool p_antialiased) override;
virtual bool font_is_antialiased(RID p_font_rid) const override;
GDVIRTUAL2(_font_set_antialiased, RID, bool);
@@ -270,6 +285,11 @@ public:
GDVIRTUAL2(_font_remove_script_support_override, RID, const String &);
GDVIRTUAL1R(Vector<String>, _font_get_script_support_overrides, RID);
+ virtual void font_set_opentype_feature_overrides(RID p_font_rid, const Dictionary &p_overrides) override;
+ virtual Dictionary font_get_opentype_feature_overrides(RID p_font_rid) const override;
+ GDVIRTUAL2(_font_set_opentype_feature_overrides, RID, const Dictionary &);
+ GDVIRTUAL1RC(Dictionary, _font_get_opentype_feature_overrides, RID);
+
virtual Dictionary font_supported_feature_list(RID p_font_rid) const override;
virtual Dictionary font_supported_variation_list(RID p_font_rid) const override;
GDVIRTUAL1RC(Dictionary, _font_supported_feature_list, RID);
@@ -295,12 +315,19 @@ public:
virtual void shaped_text_set_direction(RID p_shaped, Direction p_direction = DIRECTION_AUTO) override;
virtual Direction shaped_text_get_direction(RID p_shaped) const override;
+ virtual Direction shaped_text_get_inferred_direction(RID p_shaped) const override;
GDVIRTUAL2(_shaped_text_set_direction, RID, Direction);
GDVIRTUAL1RC(/*Direction*/ int, _shaped_text_get_direction, RID);
+ GDVIRTUAL1RC(/*Direction*/ int, _shaped_text_get_inferred_direction, RID);
virtual void shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) override;
GDVIRTUAL2(_shaped_text_set_bidi_override, RID, const Array &);
+ virtual void shaped_text_set_custom_punctuation(RID p_shaped, const String &p_punct) override;
+ virtual String shaped_text_get_custom_punctuation(RID p_shaped) const override;
+ GDVIRTUAL2(_shaped_text_set_custom_punctuation, RID, String);
+ GDVIRTUAL1RC(String, _shaped_text_get_custom_punctuation, RID);
+
virtual void shaped_text_set_orientation(RID p_shaped, Orientation p_orientation = ORIENTATION_HORIZONTAL) override;
virtual Orientation shaped_text_get_orientation(RID p_shaped) const override;
GDVIRTUAL2(_shaped_text_set_orientation, RID, Orientation);
@@ -317,11 +344,11 @@ public:
GDVIRTUAL1RC(bool, _shaped_text_get_preserve_control, RID);
virtual bool shaped_text_add_string(RID p_shaped, const String &p_text, const Vector<RID> &p_fonts, int p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "") override;
- virtual bool shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlign p_inline_align = INLINE_ALIGN_CENTER, int p_length = 1) override;
- virtual bool shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlign p_inline_align = INLINE_ALIGN_CENTER) override;
+ virtual bool shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER, int p_length = 1) override;
+ virtual bool shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER) override;
GDVIRTUAL6R(bool, _shaped_text_add_string, RID, const String &, const Array &, int, const Dictionary &, const String &);
- GDVIRTUAL5R(bool, _shaped_text_add_object, RID, Variant, const Size2 &, InlineAlign, int);
- GDVIRTUAL4R(bool, _shaped_text_resize_object, RID, Variant, const Size2 &, InlineAlign);
+ GDVIRTUAL5R(bool, _shaped_text_add_object, RID, Variant, const Size2 &, InlineAlignment, int);
+ GDVIRTUAL4R(bool, _shaped_text_resize_object, RID, Variant, const Size2 &, InlineAlignment);
virtual RID shaped_text_substr(RID p_shaped, int p_start, int p_length) const override;
virtual RID shaped_text_get_parent(RID p_shaped) const override;
@@ -408,8 +435,10 @@ public:
GDVIRTUAL6C(_shaped_text_draw, RID, RID, const Vector2 &, float, float, const Color &);
GDVIRTUAL7C(_shaped_text_draw_outline, RID, RID, const Vector2 &, float, float, int, const Color &);
+ virtual Vector2 shaped_text_get_grapheme_bounds(RID p_shaped, int p_pos) const override;
virtual int shaped_text_next_grapheme_pos(RID p_shaped, int p_pos) const override;
virtual int shaped_text_prev_grapheme_pos(RID p_shaped, int p_pos) const override;
+ GDVIRTUAL2RC(Vector2, _shaped_text_get_grapheme_bounds, RID, int);
GDVIRTUAL2RC(int, _shaped_text_next_grapheme_pos, RID, int);
GDVIRTUAL2RC(int, _shaped_text_prev_grapheme_pos, RID, int);
@@ -420,6 +449,11 @@ public:
GDVIRTUAL2RC(String, _parse_number, const String &, const String &);
GDVIRTUAL1RC(String, _percent_sign, const String &);
+ virtual String string_to_upper(const String &p_string, const String &p_language = "") const override;
+ virtual String string_to_lower(const String &p_string, const String &p_language = "") const override;
+ GDVIRTUAL2RC(String, _string_to_upper, const String &, const String &);
+ GDVIRTUAL2RC(String, _string_to_lower, const String &, const String &);
+
TextServerExtension();
~TextServerExtension();
};
diff --git a/servers/text_server.cpp b/servers/text_server.cpp
index 5087d32a7f..17840584ee 100644
--- a/servers/text_server.cpp
+++ b/servers/text_server.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -42,7 +42,7 @@ void TextServerManager::_bind_methods() {
ClassDB::bind_method(D_METHOD("find_interface", "name"), &TextServerManager::find_interface);
ClassDB::bind_method(D_METHOD("set_primary_interface", "index"), &TextServerManager::set_primary_interface);
- ClassDB::bind_method(D_METHOD("get_primary_interface"), &TextServerManager::_get_primary_interface);
+ ClassDB::bind_method(D_METHOD("get_primary_interface"), &TextServerManager::get_primary_interface);
ADD_SIGNAL(MethodInfo("interface_added", PropertyInfo(Variant::STRING_NAME, "interface_name")));
ADD_SIGNAL(MethodInfo("interface_removed", PropertyInfo(Variant::STRING_NAME, "interface_name")));
@@ -78,7 +78,7 @@ void TextServerManager::remove_interface(const Ref<TextServer> &p_interface) {
ERR_FAIL_COND(idx == -1);
print_verbose("TextServer: Removed interface \"" + p_interface->get_name() + "\"");
emit_signal(SNAME("interface_removed"), p_interface->get_name());
- interfaces.remove(idx);
+ interfaces.remove_at(idx);
}
int TextServerManager::get_interface_count() const {
@@ -118,10 +118,6 @@ Array TextServerManager::get_interfaces() const {
return ret;
}
-Ref<TextServer> TextServerManager::_get_primary_interface() const {
- return primary_interface;
-}
-
void TextServerManager::set_primary_interface(const Ref<TextServer> &p_primary_interface) {
if (p_primary_interface.is_null()) {
print_verbose("TextServer: Clearing primary interface");
@@ -145,7 +141,7 @@ TextServerManager::~TextServerManager() {
primary_interface.unref();
}
while (interfaces.size() > 0) {
- interfaces.remove(0);
+ interfaces.remove_at(0);
}
singleton = nullptr;
}
@@ -212,6 +208,15 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("font_set_data", "font_rid", "data"), &TextServer::font_set_data);
+ ClassDB::bind_method(D_METHOD("font_set_style", "font_rid", "style"), &TextServer::font_set_style);
+ ClassDB::bind_method(D_METHOD("font_get_style", "font_rid"), &TextServer::font_get_style);
+
+ ClassDB::bind_method(D_METHOD("font_set_name", "font_rid", "name"), &TextServer::font_set_name);
+ ClassDB::bind_method(D_METHOD("font_get_name", "font_rid"), &TextServer::font_get_name);
+
+ ClassDB::bind_method(D_METHOD("font_set_style_name", "font_rid", "name"), &TextServer::font_set_style_name);
+ ClassDB::bind_method(D_METHOD("font_get_style_name", "font_rid"), &TextServer::font_get_style_name);
+
ClassDB::bind_method(D_METHOD("font_set_antialiased", "font_rid", "antialiased"), &TextServer::font_set_antialiased);
ClassDB::bind_method(D_METHOD("font_is_antialiased", "font_rid"), &TextServer::font_is_antialiased);
@@ -322,6 +327,9 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("font_remove_script_support_override", "font_rid", "script"), &TextServer::font_remove_script_support_override);
ClassDB::bind_method(D_METHOD("font_get_script_support_overrides", "font_rid"), &TextServer::font_get_script_support_overrides);
+ ClassDB::bind_method(D_METHOD("font_set_opentype_feature_overrides", "font_rid", "overrides"), &TextServer::font_set_opentype_feature_overrides);
+ ClassDB::bind_method(D_METHOD("font_get_opentype_feature_overrides", "font_rid"), &TextServer::font_get_opentype_feature_overrides);
+
ClassDB::bind_method(D_METHOD("font_supported_feature_list", "font_rid"), &TextServer::font_supported_feature_list);
ClassDB::bind_method(D_METHOD("font_supported_variation_list", "font_rid"), &TextServer::font_supported_variation_list);
@@ -339,9 +347,13 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("shaped_text_set_direction", "shaped", "direction"), &TextServer::shaped_text_set_direction, DEFVAL(DIRECTION_AUTO));
ClassDB::bind_method(D_METHOD("shaped_text_get_direction", "shaped"), &TextServer::shaped_text_get_direction);
+ ClassDB::bind_method(D_METHOD("shaped_text_get_inferred_direction", "shaped"), &TextServer::shaped_text_get_inferred_direction);
ClassDB::bind_method(D_METHOD("shaped_text_set_bidi_override", "shaped", "override"), &TextServer::shaped_text_set_bidi_override);
+ ClassDB::bind_method(D_METHOD("shaped_text_set_custom_punctuation", "shaped", "punct"), &TextServer::shaped_text_set_custom_punctuation);
+ ClassDB::bind_method(D_METHOD("shaped_text_get_custom_punctuation", "shaped"), &TextServer::shaped_text_get_custom_punctuation);
+
ClassDB::bind_method(D_METHOD("shaped_text_set_orientation", "shaped", "orientation"), &TextServer::shaped_text_set_orientation, DEFVAL(ORIENTATION_HORIZONTAL));
ClassDB::bind_method(D_METHOD("shaped_text_get_orientation", "shaped"), &TextServer::shaped_text_get_orientation);
@@ -352,8 +364,8 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("shaped_text_get_preserve_control", "shaped"), &TextServer::shaped_text_get_preserve_control);
ClassDB::bind_method(D_METHOD("shaped_text_add_string", "shaped", "text", "fonts", "size", "opentype_features", "language"), &TextServer::shaped_text_add_string, DEFVAL(Dictionary()), DEFVAL(""));
- ClassDB::bind_method(D_METHOD("shaped_text_add_object", "shaped", "key", "size", "inline_align", "length"), &TextServer::shaped_text_add_object, DEFVAL(INLINE_ALIGN_CENTER), DEFVAL(1));
- ClassDB::bind_method(D_METHOD("shaped_text_resize_object", "shaped", "key", "size", "inline_align"), &TextServer::shaped_text_resize_object, DEFVAL(INLINE_ALIGN_CENTER));
+ ClassDB::bind_method(D_METHOD("shaped_text_add_object", "shaped", "key", "size", "inline_align", "length"), &TextServer::shaped_text_add_object, DEFVAL(INLINE_ALIGNMENT_CENTER), DEFVAL(1));
+ ClassDB::bind_method(D_METHOD("shaped_text_resize_object", "shaped", "key", "size", "inline_align"), &TextServer::shaped_text_resize_object, DEFVAL(INLINE_ALIGNMENT_CENTER));
ClassDB::bind_method(D_METHOD("shaped_text_substr", "shaped", "start", "length"), &TextServer::shaped_text_substr);
ClassDB::bind_method(D_METHOD("shaped_text_get_parent", "shaped"), &TextServer::shaped_text_get_parent);
@@ -395,6 +407,7 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("shaped_text_hit_test_grapheme", "shaped", "coords"), &TextServer::shaped_text_hit_test_grapheme);
ClassDB::bind_method(D_METHOD("shaped_text_hit_test_position", "shaped", "coords"), &TextServer::shaped_text_hit_test_position);
+ ClassDB::bind_method(D_METHOD("shaped_text_get_grapheme_bounds", "shaped", "pos"), &TextServer::shaped_text_get_grapheme_bounds);
ClassDB::bind_method(D_METHOD("shaped_text_next_grapheme_pos", "shaped", "pos"), &TextServer::shaped_text_next_grapheme_pos);
ClassDB::bind_method(D_METHOD("shaped_text_prev_grapheme_pos", "shaped", "pos"), &TextServer::shaped_text_prev_grapheme_pos);
@@ -407,6 +420,11 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("parse_number", "number", "language"), &TextServer::parse_number, DEFVAL(""));
ClassDB::bind_method(D_METHOD("percent_sign", "language"), &TextServer::percent_sign, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("strip_diacritics", "string"), &TextServer::strip_diacritics);
+
+ ClassDB::bind_method(D_METHOD("string_to_upper", "string", "language"), &TextServer::string_to_upper, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("string_to_lower", "string", "language"), &TextServer::string_to_lower, DEFVAL(""));
+
/* Direction */
BIND_ENUM_CONSTANT(DIRECTION_AUTO);
BIND_ENUM_CONSTANT(DIRECTION_LTR);
@@ -465,6 +483,7 @@ void TextServer::_bind_methods() {
BIND_ENUM_CONSTANT(FEATURE_BREAK_ITERATORS);
BIND_ENUM_CONSTANT(FEATURE_FONT_SYSTEM);
BIND_ENUM_CONSTANT(FEATURE_FONT_VARIABLE);
+ BIND_ENUM_CONSTANT(FEATURE_CONTEXT_SENSITIVE_CASE_CONVERSION);
BIND_ENUM_CONSTANT(FEATURE_USE_SUPPORT_DATA);
/* FT Contour Point Types */
@@ -472,17 +491,22 @@ void TextServer::_bind_methods() {
BIND_ENUM_CONSTANT(CONTOUR_CURVE_TAG_OFF_CONIC);
BIND_ENUM_CONSTANT(CONTOUR_CURVE_TAG_OFF_CUBIC);
- /* Font Spacing*/
+ /* Font Spacing */
BIND_ENUM_CONSTANT(SPACING_GLYPH);
BIND_ENUM_CONSTANT(SPACING_SPACE);
BIND_ENUM_CONSTANT(SPACING_TOP);
BIND_ENUM_CONSTANT(SPACING_BOTTOM);
+
+ /* Font Style */
+ BIND_ENUM_CONSTANT(FONT_BOLD);
+ BIND_ENUM_CONSTANT(FONT_ITALIC);
+ BIND_ENUM_CONSTANT(FONT_FIXED_WIDTH);
}
Vector2 TextServer::get_hex_code_box_size(int p_size, char32_t p_index) const {
int w = ((p_index <= 0xFF) ? 1 : ((p_index <= 0xFFFF) ? 2 : 3));
int sp = MAX(0, w - 1);
- int sz = MAX(1, p_size / 15);
+ int sz = MAX(1, Math::round(p_size / 15.f));
return Vector2(4 + 3 * w + sp + 1, 15) * sz;
}
@@ -520,7 +544,7 @@ void TextServer::draw_hex_code_box(RID p_canvas, int p_size, const Vector2 &p_po
int w = ((p_index <= 0xFF) ? 1 : ((p_index <= 0xFFFF) ? 2 : 3));
int sp = MAX(0, w - 1);
- int sz = MAX(1, p_size / 15);
+ int sz = MAX(1, Math::round(p_size / 15.f));
Size2 size = Vector2(4 + 3 * w + sp, 15) * sz;
Point2 pos = p_pos - Point2i(0, size.y * 0.85);
@@ -633,13 +657,13 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(RID p_shaped, const
return lines;
}
-PackedInt32Array TextServer::shaped_text_get_line_breaks(RID p_shaped, real_t p_width, int p_start, uint16_t /*TextBreakFlag*/ p_break_flags) const {
+PackedInt32Array TextServer::shaped_text_get_line_breaks(RID p_shaped, float p_width, int p_start, uint16_t /*TextBreakFlag*/ p_break_flags) const {
PackedInt32Array lines;
const_cast<TextServer *>(this)->shaped_text_update_breaks(p_shaped);
const Vector2i &range = shaped_text_get_range(p_shaped);
- real_t width = 0.f;
+ float width = 0.f;
int line_start = MAX(p_start, range.x);
int last_safe_break = -1;
int word_count = 0;
@@ -973,9 +997,9 @@ Vector<Vector2> TextServer::shaped_text_get_selection(RID p_shaped, int p_start,
}
real_t char_adv = advance / (real_t)(glyphs[i].end - glyphs[i].start);
if ((glyphs[i].flags & GRAPHEME_IS_RTL) == GRAPHEME_IS_RTL) {
- ranges.push_back(Vector2(off, off + char_adv * (start - glyphs[i].start)));
+ ranges.push_back(Vector2(off, off + char_adv * (glyphs[i].end - start)));
} else {
- ranges.push_back(Vector2(off + char_adv * (glyphs[i].end - start), off + advance));
+ ranges.push_back(Vector2(off + char_adv * (start - glyphs[i].start), off + advance));
}
}
// Selection range is within grapheme.
@@ -1008,7 +1032,7 @@ Vector<Vector2> TextServer::shaped_text_get_selection(RID p_shaped, int p_start,
while (j < ranges.size()) {
if (Math::is_equal_approx(ranges[i].y, ranges[j].x, (real_t)UNIT_EPSILON)) {
ranges.write[i].y = ranges[j].y;
- ranges.remove(j);
+ ranges.remove_at(j);
continue;
}
j++;
@@ -1019,9 +1043,9 @@ Vector<Vector2> TextServer::shaped_text_get_selection(RID p_shaped, int p_start,
return ranges;
}
-int TextServer::shaped_text_hit_test_grapheme(RID p_shaped, real_t p_coords) const {
+int TextServer::shaped_text_hit_test_grapheme(RID p_shaped, float p_coords) const {
// Exact grapheme hit test, return -1 if missed.
- real_t off = 0.0f;
+ float off = 0.0f;
int v_size = shaped_text_get_glyph_count(p_shaped);
const Glyph *glyphs = shaped_text_get_glyphs(p_shaped);
@@ -1037,7 +1061,7 @@ int TextServer::shaped_text_hit_test_grapheme(RID p_shaped, real_t p_coords) con
return -1;
}
-int TextServer::shaped_text_hit_test_position(RID p_shaped, real_t p_coords) const {
+int TextServer::shaped_text_hit_test_position(RID p_shaped, float p_coords) const {
int v_size = shaped_text_get_glyph_count(p_shaped);
const Glyph *glyphs = shaped_text_get_glyphs(p_shaped);
@@ -1083,6 +1107,31 @@ int TextServer::shaped_text_hit_test_position(RID p_shaped, real_t p_coords) con
return glyphs[i].start;
}
}
+ // Ligature, handle mid-grapheme hit.
+ if (p_coords >= off && p_coords < off + advance && glyphs[i].end > glyphs[i].start + 1) {
+ int cnt = glyphs[i].end - glyphs[i].start;
+ real_t char_adv = advance / (real_t)(cnt);
+ real_t sub_off = off;
+ for (int j = 0; j < cnt; j++) {
+ // Place caret to the left of clicked sub-grapheme.
+ if (p_coords >= sub_off && p_coords < sub_off + char_adv / 2) {
+ if ((glyphs[i].flags & GRAPHEME_IS_RTL) == GRAPHEME_IS_RTL) {
+ return glyphs[i].end - j;
+ } else {
+ return glyphs[i].start + j;
+ }
+ }
+ // Place caret to the right of clicked sub-grapheme.
+ if (p_coords >= sub_off + char_adv / 2 && p_coords < sub_off + char_adv) {
+ if ((glyphs[i].flags & GRAPHEME_IS_RTL) == GRAPHEME_IS_RTL) {
+ return glyphs[i].start + (cnt - 1) - j;
+ } else {
+ return glyphs[i].end - (cnt - 1) + j;
+ }
+ }
+ sub_off += char_adv;
+ }
+ }
// Place caret to the left of clicked grapheme.
if (p_coords >= off && p_coords < off + advance / 2) {
if ((glyphs[i].flags & GRAPHEME_IS_RTL) == GRAPHEME_IS_RTL) {
@@ -1105,6 +1154,27 @@ int TextServer::shaped_text_hit_test_position(RID p_shaped, real_t p_coords) con
return 0;
}
+Vector2 TextServer::shaped_text_get_grapheme_bounds(RID p_shaped, int p_pos) const {
+ int v_size = shaped_text_get_glyph_count(p_shaped);
+ const Glyph *glyphs = shaped_text_get_glyphs(p_shaped);
+
+ real_t off = 0.0f;
+ for (int i = 0; i < v_size; i++) {
+ if ((glyphs[i].count > 0) && ((glyphs[i].index != 0) || ((glyphs[i].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE))) {
+ if (glyphs[i].start <= p_pos && glyphs[i].end >= p_pos) {
+ real_t advance = 0.f;
+ for (int j = 0; j < glyphs[i].count; j++) {
+ advance += glyphs[i + j].advance;
+ }
+ return Vector2(off, off + advance);
+ }
+ }
+ off += glyphs[i].advance * glyphs[i].repeat;
+ }
+
+ return Vector2();
+}
+
int TextServer::shaped_text_next_grapheme_pos(RID p_shaped, int p_pos) const {
int v_size = shaped_text_get_glyph_count(p_shaped);
const Glyph *glyphs = shaped_text_get_glyphs(p_shaped);
@@ -1128,7 +1198,7 @@ int TextServer::shaped_text_prev_grapheme_pos(RID p_shaped, int p_pos) const {
return p_pos;
}
-void TextServer::shaped_text_draw(RID p_shaped, RID p_canvas, const Vector2 &p_pos, real_t p_clip_l, real_t p_clip_r, const Color &p_color) const {
+void TextServer::shaped_text_draw(RID p_shaped, RID p_canvas, const Vector2 &p_pos, float p_clip_l, float p_clip_r, const Color &p_color) const {
TextServer::Orientation orientation = shaped_text_get_orientation(p_shaped);
bool hex_codes = shaped_text_get_preserve_control(p_shaped) || shaped_text_get_preserve_invalid(p_shaped);
@@ -1159,6 +1229,17 @@ void TextServer::shaped_text_draw(RID p_shaped, RID p_canvas, const Vector2 &p_p
}
// Draw at the baseline.
for (int i = 0; i < v_size; i++) {
+ if (trim_pos >= 0) {
+ if (rtl) {
+ if (i < trim_pos) {
+ continue;
+ }
+ } else {
+ if (i >= trim_pos) {
+ break;
+ }
+ }
+ }
for (int j = 0; j < glyphs[i].repeat; j++) {
if (p_clip_r > 0) {
// Clip right / bottom.
@@ -1186,17 +1267,6 @@ void TextServer::shaped_text_draw(RID p_shaped, RID p_canvas, const Vector2 &p_p
}
}
}
- if (trim_pos >= 0) {
- if (rtl) {
- if (i < trim_pos && (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) {
- continue;
- }
- } else {
- if (i >= trim_pos && (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) {
- break;
- }
- }
- }
if (glyphs[i].font_rid != RID()) {
font_draw_glyph(glyphs[i].font_rid, p_canvas, glyphs[i].font_size, ofs + Vector2(glyphs[i].x_off, glyphs[i].y_off), glyphs[i].index, p_color);
@@ -1225,10 +1295,10 @@ void TextServer::shaped_text_draw(RID p_shaped, RID p_canvas, const Vector2 &p_p
}
}
-void TextServer::shaped_text_draw_outline(RID p_shaped, RID p_canvas, const Vector2 &p_pos, real_t p_clip_l, real_t p_clip_r, int p_outline_size, const Color &p_color) const {
+void TextServer::shaped_text_draw_outline(RID p_shaped, RID p_canvas, const Vector2 &p_pos, float p_clip_l, float p_clip_r, int p_outline_size, const Color &p_color) const {
TextServer::Orientation orientation = shaped_text_get_orientation(p_shaped);
- bool rtl = (shaped_text_get_direction(p_shaped) == DIRECTION_RTL);
+ bool rtl = (shaped_text_get_inferred_direction(p_shaped) == DIRECTION_RTL);
int ellipsis_pos = shaped_text_get_ellipsis_pos(p_shaped);
int trim_pos = shaped_text_get_trim_pos(p_shaped);
@@ -1254,6 +1324,17 @@ void TextServer::shaped_text_draw_outline(RID p_shaped, RID p_canvas, const Vect
}
// Draw at the baseline.
for (int i = 0; i < v_size; i++) {
+ if (trim_pos >= 0) {
+ if (rtl) {
+ if (i < trim_pos) {
+ continue;
+ }
+ } else {
+ if (i >= trim_pos) {
+ break;
+ }
+ }
+ }
for (int j = 0; j < glyphs[i].repeat; j++) {
if (p_clip_r > 0) {
// Clip right / bottom.
@@ -1281,17 +1362,6 @@ void TextServer::shaped_text_draw_outline(RID p_shaped, RID p_canvas, const Vect
}
}
}
- if (trim_pos >= 0) {
- if (rtl) {
- if (i < trim_pos) {
- continue;
- }
- } else {
- if (i >= trim_pos && (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) {
- break;
- }
- }
- }
if (glyphs[i].font_rid != RID()) {
font_draw_glyph_outline(glyphs[i].font_rid, p_canvas, glyphs[i].font_size, p_outline_size, ofs + Vector2(glyphs[i].x_off, glyphs[i].y_off), glyphs[i].index, p_color);
}
@@ -1317,6 +1387,134 @@ void TextServer::shaped_text_draw_outline(RID p_shaped, RID p_canvas, const Vect
}
}
+void TextServer::_diacritics_map_add(const String &p_from, char32_t p_to) {
+ for (int i = 0; i < p_from.size(); i++) {
+ diacritics_map[p_from[i]] = p_to;
+ }
+}
+
+void TextServer::_init_diacritics_map() {
+ diacritics_map.clear();
+
+ // Latin.
+ _diacritics_map_add(U"ÀÁÂÃÄÅĀĂĄǍǞǠǺȀȂȦḀẠẢẤẦẨẪẬẮẰẲẴẶ", U'A');
+ _diacritics_map_add(U"àáâãäåāăąǎǟǡǻȁȃȧḁẚạảấầẩẫậắằẳẵặ", U'a');
+ _diacritics_map_add(U"ǢǼ", U'Æ');
+ _diacritics_map_add(U"ǣǽ", U'æ');
+ _diacritics_map_add(U"ḂḄḆ", U'B');
+ _diacritics_map_add(U"ḃḅḇ", U'b');
+ _diacritics_map_add(U"ÇĆĈĊČḈ", U'C');
+ _diacritics_map_add(U"çćĉċčḉ", U'c');
+ _diacritics_map_add(U"ĎḊḌḎḐḒ", U'D');
+ _diacritics_map_add(U"ďḋḍḏḑḓ", U'd');
+ _diacritics_map_add(U"ÈÉÊËĒĔĖĘĚȆȨḔḖḘḚḜẸẺẼẾỀỂỄỆ", U'E');
+ _diacritics_map_add(U"èéêëēĕėęěȇȩḕḗḙḛḝẹẻẽếềểễệ", U'e');
+ _diacritics_map_add(U"Ḟ", U'F');
+ _diacritics_map_add(U"ḟ", U'f');
+ _diacritics_map_add(U"ĜĞĠĢǦǴḠ", U'G');
+ _diacritics_map_add(U"ĝğġģǧǵḡ", U'g');
+ _diacritics_map_add(U"ĤȞḢḤḦḨḪ", U'H');
+ _diacritics_map_add(U"ĥȟḣḥḧḩḫẖ", U'h');
+ _diacritics_map_add(U"ÌÍÎÏĨĪĬĮİǏȈȊḬḮỈỊ", U'I');
+ _diacritics_map_add(U"ìíîïĩīĭįıǐȉȋḭḯỉị", U'i');
+ _diacritics_map_add(U"Ĵ", U'J');
+ _diacritics_map_add(U"ĵ", U'j');
+ _diacritics_map_add(U"ĶǨḰḲḴ", U'K');
+ _diacritics_map_add(U"ķĸǩḱḳḵ", U'k');
+ _diacritics_map_add(U"ĹĻĽĿḶḸḺḼ", U'L');
+ _diacritics_map_add(U"ĺļľŀḷḹḻḽ", U'l');
+ _diacritics_map_add(U"ḾṀṂ", U'M');
+ _diacritics_map_add(U"ḿṁṃ", U'm');
+ _diacritics_map_add(U"ÑŃŅŇǸṄṆṈṊ", U'N');
+ _diacritics_map_add(U"ñńņňʼnǹṅṇṉṋ", U'n');
+ _diacritics_map_add(U"ÒÓÔÕÖŌŎŐƠǑǪǬȌȎȪȬȮȰṌṎṐṒỌỎỐỒỔỖỘỚỜỞỠỢ", U'O');
+ _diacritics_map_add(U"òóôõöōŏőơǒǫǭȍȏȫȭȯȱṍṏṑṓọỏốồổỗộớờởỡợ", U'o');
+ _diacritics_map_add(U"ṔṖ", U'P');
+ _diacritics_map_add(U"ṗṕ", U'p');
+ _diacritics_map_add(U"ŔŖŘȐȒṘṚṜṞ", U'R');
+ _diacritics_map_add(U"ŕŗřȑȓṙṛṝṟ", U'r');
+ _diacritics_map_add(U"ŚŜŞŠȘṠṢṤṦṨ", U'S');
+ _diacritics_map_add(U"śŝşšſșṡṣṥṧṩẛẜẝ", U's');
+ _diacritics_map_add(U"ŢŤȚṪṬṮṰ", U'T');
+ _diacritics_map_add(U"ţťțṫṭṯṱẗ", U't');
+ _diacritics_map_add(U"ÙÚÛÜŨŪŬŮŰŲƯǓǕǗǙǛȔȖṲṴṶṸṺỤỦỨỪỬỮỰ", U'U');
+ _diacritics_map_add(U"ùúûüũūŭůűųưǔǖǘǚǜȕȗṳṵṷṹṻụủứừửữự", U'u');
+ _diacritics_map_add(U"ṼṾ", U'V');
+ _diacritics_map_add(U"ṽṿ", U'v');
+ _diacritics_map_add(U"ŴẀẂẄẆẈ", U'W');
+ _diacritics_map_add(U"ŵẁẃẅẇẉẘ", U'w');
+ _diacritics_map_add(U"ẊẌ", U'X');
+ _diacritics_map_add(U"ẋẍ", U'x');
+ _diacritics_map_add(U"ÝŶẎỲỴỶỸỾ", U'Y');
+ _diacritics_map_add(U"ýÿŷẏẙỳỵỷỹỿ", U'y');
+ _diacritics_map_add(U"ŹŻŽẐẒẔ", U'Z');
+ _diacritics_map_add(U"źżžẑẓẕ", U'z');
+
+ // Greek.
+ _diacritics_map_add(U"ΆἈἉἊἋἌἍἎἏᾈᾉᾊᾋᾌᾍᾎᾏᾸᾹᾺΆᾼ", U'Α');
+ _diacritics_map_add(U"άἀἁἂἃἄἅἆἇὰάᾀᾁᾂᾃᾄᾅᾆᾇᾰᾱᾲᾳᾴᾶᾷ", U'α');
+ _diacritics_map_add(U"ΈἘἙἚἛἜἝῈΈ", U'Ε');
+ _diacritics_map_add(U"έἐἑἒἓἔἕὲέ", U'ε');
+ _diacritics_map_add(U"ΉἨἩἪἫἬἭἮἯᾘᾙᾚᾛᾜᾝᾞᾟῊΉῌ", U'Η');
+ _diacritics_map_add(U"ήἠἡἢἣἤἥἦἧὴήᾐᾑᾒᾓᾔᾕᾖᾗῂῃῄῆῇ", U'η');
+ _diacritics_map_add(U"ΊΪἸἹἺἻἼἽἾἿῘῙῚΊ", U'Ι');
+ _diacritics_map_add(U"ίΐϊἰἱἲἳἴἵἶἷὶίῐῑῒΐῖῗ", U'ι');
+ _diacritics_map_add(U"ΌὈὉὊὋὌὍῸΌ", U'Ο');
+ _diacritics_map_add(U"όὀὁὂὃὄὅὸό", U'ο');
+ _diacritics_map_add(U"Ῥ", U'Ρ');
+ _diacritics_map_add(U"ῤῥ", U'ρ');
+ _diacritics_map_add(U"ΎΫϓϔὙὛὝὟῨῩῪΎ", U'Υ');
+ _diacritics_map_add(U"ΰϋύὐὑὒὓὔὕὖὗὺύῠῡῢΰῦῧ", U'υ');
+ _diacritics_map_add(U"ΏὨὩὪὫὬὭὮὯᾨᾩᾪᾫᾬᾭᾮᾯῺΏῼ", U'Ω');
+ _diacritics_map_add(U"ώὠὡὢὣὤὥὦὧὼώᾠᾡᾢᾣᾤᾥᾦᾧῲῳῴῶῷ", U'ω');
+
+ // Cyrillic.
+ _diacritics_map_add(U"ӐӒ", U'А');
+ _diacritics_map_add(U"ӑӓ", U'а');
+ _diacritics_map_add(U"ЀЁӖ", U'Е');
+ _diacritics_map_add(U"ѐёӗ", U'е');
+ _diacritics_map_add(U"Ӛ", U'Ә');
+ _diacritics_map_add(U"ӛ", U'ә');
+ _diacritics_map_add(U"Ӝ", U'Ж');
+ _diacritics_map_add(U"ӝ", U'ж');
+ _diacritics_map_add(U"Ӟ", U'З');
+ _diacritics_map_add(U"ӟ", U'з');
+ _diacritics_map_add(U"Ѓ", U'Г');
+ _diacritics_map_add(U"ѓ", U'г');
+ _diacritics_map_add(U"Ї", U'І');
+ _diacritics_map_add(U"ї", U'і');
+ _diacritics_map_add(U"ЍӢӤЙ", U'И');
+ _diacritics_map_add(U"ѝӣӥй", U'и');
+ _diacritics_map_add(U"Ќ", U'К');
+ _diacritics_map_add(U"ќ", U'к');
+ _diacritics_map_add(U"Ӧ", U'О');
+ _diacritics_map_add(U"ӧ", U'о');
+ _diacritics_map_add(U"Ӫ", U'Ө');
+ _diacritics_map_add(U"ӫ", U'ө');
+ _diacritics_map_add(U"Ӭ", U'Э');
+ _diacritics_map_add(U"ӭ", U'э');
+ _diacritics_map_add(U"ЎӮӰӲ", U'У');
+ _diacritics_map_add(U"ўӯӱӳ", U'у');
+ _diacritics_map_add(U"Ӵ", U'Ч');
+ _diacritics_map_add(U"ӵ", U'ч');
+ _diacritics_map_add(U"Ӹ", U'Ы');
+ _diacritics_map_add(U"ӹ", U'ы');
+}
+
+String TextServer::strip_diacritics(const String &p_string) const {
+ String result;
+ for (int i = 0; i < p_string.length(); i++) {
+ if (p_string[i] < 0x02B0 || p_string[i] > 0x036F) { // Skip combining diacritics.
+ if (diacritics_map.has(p_string[i])) {
+ result += diacritics_map[p_string[i]];
+ } else {
+ result += p_string[i];
+ }
+ }
+ }
+ return result;
+}
+
Array TextServer::_shaped_text_get_glyphs_wrapper(RID p_shaped) const {
Array ret;
@@ -1393,6 +1591,7 @@ Array TextServer::_shaped_text_get_ellipsis_glyphs_wrapper(RID p_shaped) const {
}
TextServer::TextServer() {
+ _init_diacritics_map();
}
TextServer::~TextServer() {
diff --git a/servers/text_server.h b/servers/text_server.h
index 3a5f946fbf..599cc3afd0 100644
--- a/servers/text_server.h
+++ b/servers/text_server.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -109,7 +109,8 @@ public:
FEATURE_BREAK_ITERATORS = 1 << 4,
FEATURE_FONT_SYSTEM = 1 << 5,
FEATURE_FONT_VARIABLE = 1 << 6,
- FEATURE_USE_SUPPORT_DATA = 1 << 7
+ FEATURE_CONTEXT_SENSITIVE_CASE_CONVERSION = 1 << 7,
+ FEATURE_USE_SUPPORT_DATA = 1 << 8,
};
enum ContourPointTag {
@@ -125,6 +126,12 @@ public:
SPACING_BOTTOM,
};
+ enum FontStyle {
+ FONT_BOLD = 1 << 0,
+ FONT_ITALIC = 1 << 1,
+ FONT_FIXED_WIDTH = 1 << 2,
+ };
+
void _draw_hex_code_box_number(RID p_canvas, int p_size, const Vector2 &p_pos, uint8_t p_index, const Color &p_color) const;
protected:
@@ -144,6 +151,7 @@ protected:
int end = 0; // Substring end offset in the parent string.
String text;
+ String custom_punct;
TextServer::Direction direction = DIRECTION_LTR; // Desired text direction.
TextServer::Orientation orientation = ORIENTATION_HORIZONTAL;
@@ -163,7 +171,7 @@ protected:
struct EmbeddedObject {
int pos = 0;
- InlineAlign inline_align = INLINE_ALIGN_CENTER;
+ InlineAlignment inline_align = INLINE_ALIGNMENT_CENTER;
Rect2 rect;
};
Map<Variant, EmbeddedObject> objects;
@@ -194,6 +202,10 @@ protected:
Vector<Glyph> glyphs_logical;
};
+ Map<char32_t, char32_t> diacritics_map;
+ void _diacritics_map_add(const String &p_from, char32_t p_to);
+ void _init_diacritics_map();
+
static void _bind_methods();
public:
@@ -220,6 +232,15 @@ public:
virtual void font_set_data(RID p_font_rid, const PackedByteArray &p_data) = 0;
virtual void font_set_data_ptr(RID p_font_rid, const uint8_t *p_data_ptr, size_t p_data_size) = 0;
+ virtual void font_set_style(RID p_font_rid, uint32_t /*FontStyle*/ p_style) = 0;
+ virtual uint32_t /*FontStyle*/ font_get_style(RID p_font_rid) const = 0;
+
+ virtual void font_set_name(RID p_font_rid, const String &p_name) = 0;
+ virtual String font_get_name(RID p_font_rid) const = 0;
+
+ virtual void font_set_style_name(RID p_font_rid, const String &p_name) = 0;
+ virtual String font_get_style_name(RID p_font_rid) const = 0;
+
virtual void font_set_antialiased(RID p_font_rid, bool p_antialiased) = 0;
virtual bool font_is_antialiased(RID p_font_rid) const = 0;
@@ -330,6 +351,9 @@ public:
virtual void font_remove_script_support_override(RID p_font_rid, const String &p_script) = 0;
virtual Vector<String> font_get_script_support_overrides(RID p_font_rid) = 0;
+ virtual void font_set_opentype_feature_overrides(RID p_font_rid, const Dictionary &p_overrides) = 0;
+ virtual Dictionary font_get_opentype_feature_overrides(RID p_font_rid) const = 0;
+
virtual Dictionary font_supported_feature_list(RID p_font_rid) const = 0;
virtual Dictionary font_supported_variation_list(RID p_font_rid) const = 0;
@@ -347,9 +371,13 @@ public:
virtual void shaped_text_set_direction(RID p_shaped, Direction p_direction = DIRECTION_AUTO) = 0;
virtual Direction shaped_text_get_direction(RID p_shaped) const = 0;
+ virtual Direction shaped_text_get_inferred_direction(RID p_shaped) const = 0;
virtual void shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) = 0;
+ virtual void shaped_text_set_custom_punctuation(RID p_shaped, const String &p_punct) = 0;
+ virtual String shaped_text_get_custom_punctuation(RID p_shaped) const = 0;
+
virtual void shaped_text_set_orientation(RID p_shaped, Orientation p_orientation = ORIENTATION_HORIZONTAL) = 0;
virtual Orientation shaped_text_get_orientation(RID p_shaped) const = 0;
@@ -360,8 +388,8 @@ public:
virtual bool shaped_text_get_preserve_control(RID p_shaped) const = 0;
virtual bool shaped_text_add_string(RID p_shaped, const String &p_text, const Vector<RID> &p_fonts, int p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "") = 0;
- virtual bool shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlign p_inline_align = INLINE_ALIGN_CENTER, int p_length = 1) = 0;
- virtual bool shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlign p_inline_align = INLINE_ALIGN_CENTER) = 0;
+ virtual bool shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER, int p_length = 1) = 0;
+ virtual bool shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER) = 0;
virtual RID shaped_text_substr(RID p_shaped, int p_start, int p_length) const = 0; // Copy shaped substring (e.g. line break) without reshaping, but correctly reordered, preservers range.
virtual RID shaped_text_get_parent(RID p_shaped) const = 0;
@@ -415,6 +443,7 @@ public:
virtual int shaped_text_hit_test_grapheme(RID p_shaped, float p_coords) const; // Return grapheme index.
virtual int shaped_text_hit_test_position(RID p_shaped, float p_coords) const; // Return caret/selection position.
+ virtual Vector2 shaped_text_get_grapheme_bounds(RID p_shaped, int p_pos) const;
virtual int shaped_text_next_grapheme_pos(RID p_shaped, int p_pos) const;
virtual int shaped_text_prev_grapheme_pos(RID p_shaped, int p_pos) const;
@@ -427,6 +456,12 @@ public:
virtual String parse_number(const String &p_string, const String &p_language = "") const { return p_string; };
virtual String percent_sign(const String &p_language = "") const { return "%"; };
+ virtual String strip_diacritics(const String &p_string) const;
+
+ // Other string operations.
+ virtual String string_to_upper(const String &p_string, const String &p_language = "") const = 0;
+ virtual String string_to_lower(const String &p_string, const String &p_language = "") const = 0;
+
TextServer();
~TextServer();
};
@@ -509,7 +544,6 @@ public:
_FORCE_INLINE_ Ref<TextServer> get_primary_interface() const {
return primary_interface;
}
- Ref<TextServer> _get_primary_interface() const;
void set_primary_interface(const Ref<TextServer> &p_primary_interface);
TextServerManager();
@@ -530,6 +564,7 @@ VARIANT_ENUM_CAST(TextServer::Hinting);
VARIANT_ENUM_CAST(TextServer::Feature);
VARIANT_ENUM_CAST(TextServer::ContourPointTag);
VARIANT_ENUM_CAST(TextServer::SpacingType);
+VARIANT_ENUM_CAST(TextServer::FontStyle);
GDVIRTUAL_NATIVE_PTR(Glyph);
GDVIRTUAL_NATIVE_PTR(Glyph *);
diff --git a/servers/xr/xr_interface.cpp b/servers/xr/xr_interface.cpp
index bf54158905..758f2416ec 100644
--- a/servers/xr/xr_interface.cpp
+++ b/servers/xr/xr_interface.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -32,6 +32,8 @@
// #include "servers/rendering/renderer_compositor.h"
void XRInterface::_bind_methods() {
+ ADD_SIGNAL(MethodInfo("play_area_changed", PropertyInfo(Variant::INT, "mode")));
+
ClassDB::bind_method(D_METHOD("get_name"), &XRInterface::get_name);
ClassDB::bind_method(D_METHOD("get_capabilities"), &XRInterface::get_capabilities);
@@ -47,12 +49,21 @@ void XRInterface::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_render_target_size"), &XRInterface::get_render_target_size);
ClassDB::bind_method(D_METHOD("get_view_count"), &XRInterface::get_view_count);
+ ClassDB::bind_method(D_METHOD("trigger_haptic_pulse", "action_name", "tracker_name", "frequency", "amplitude", "duration_sec", "delay_sec"), &XRInterface::trigger_haptic_pulse);
+
ADD_GROUP("Interface", "interface_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interface_is_primary"), "set_primary", "is_primary");
- // we don't have any properties specific to VR yet....
+ // methods and properties specific to VR...
+ ClassDB::bind_method(D_METHOD("supports_play_area_mode", "mode"), &XRInterface::supports_play_area_mode);
+ ClassDB::bind_method(D_METHOD("get_play_area_mode"), &XRInterface::get_play_area_mode);
+ ClassDB::bind_method(D_METHOD("set_play_area_mode", "mode"), &XRInterface::set_play_area_mode);
+ ClassDB::bind_method(D_METHOD("get_play_area"), &XRInterface::get_play_area);
+
+ ADD_GROUP("XR", "xr_");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "xr_play_area_mode", PROPERTY_HINT_ENUM, "Unknown,3DOF,Sitting,Roomscale,Stage"), "set_play_area_mode", "get_play_area_mode");
- // but we do have properties specific to AR....
+ // methods and properties specific to AR....
ClassDB::bind_method(D_METHOD("get_anchor_detection_is_enabled"), &XRInterface::get_anchor_detection_is_enabled);
ClassDB::bind_method(D_METHOD("set_anchor_detection_is_enabled", "enable"), &XRInterface::set_anchor_detection_is_enabled);
ClassDB::bind_method(D_METHOD("get_camera_feed_id"), &XRInterface::get_camera_feed_id);
@@ -63,19 +74,23 @@ void XRInterface::_bind_methods() {
BIND_ENUM_CONSTANT(XR_NONE);
BIND_ENUM_CONSTANT(XR_MONO);
BIND_ENUM_CONSTANT(XR_STEREO);
+ BIND_ENUM_CONSTANT(XR_QUAD);
+ BIND_ENUM_CONSTANT(XR_VR);
BIND_ENUM_CONSTANT(XR_AR);
BIND_ENUM_CONSTANT(XR_EXTERNAL);
- BIND_ENUM_CONSTANT(EYE_MONO);
- BIND_ENUM_CONSTANT(EYE_LEFT);
- BIND_ENUM_CONSTANT(EYE_RIGHT);
-
BIND_ENUM_CONSTANT(XR_NORMAL_TRACKING);
BIND_ENUM_CONSTANT(XR_EXCESSIVE_MOTION);
BIND_ENUM_CONSTANT(XR_INSUFFICIENT_FEATURES);
BIND_ENUM_CONSTANT(XR_UNKNOWN_TRACKING);
BIND_ENUM_CONSTANT(XR_NOT_TRACKING);
-}
+
+ BIND_ENUM_CONSTANT(XR_PLAY_AREA_UNKNOWN);
+ BIND_ENUM_CONSTANT(XR_PLAY_AREA_3DOF);
+ BIND_ENUM_CONSTANT(XR_PLAY_AREA_SITTING);
+ BIND_ENUM_CONSTANT(XR_PLAY_AREA_ROOMSCALE);
+ BIND_ENUM_CONSTANT(XR_PLAY_AREA_STAGE);
+};
bool XRInterface::is_primary() {
XRServer *xr_server = XRServer::get_singleton();
@@ -101,6 +116,29 @@ XRInterface::XRInterface() {}
XRInterface::~XRInterface() {}
+// query if this interface supports this play area mode
+bool XRInterface::supports_play_area_mode(XRInterface::PlayAreaMode p_mode) {
+ return p_mode == XR_PLAY_AREA_UNKNOWN;
+}
+
+// get the current play area mode
+XRInterface::PlayAreaMode XRInterface::get_play_area_mode() const {
+ return XR_PLAY_AREA_UNKNOWN;
+}
+
+// change the play area mode, note that this should return false if the mode is not available
+bool XRInterface::set_play_area_mode(XRInterface::PlayAreaMode p_mode) {
+ return p_mode == XR_PLAY_AREA_UNKNOWN;
+}
+
+// if available, returns an array of vectors denoting the play area the player can move around in
+PackedVector3Array XRInterface::get_play_area() const {
+ // Return an empty array by default.
+ // Note implementation is responsible for applying our reference frame and world scale to the raw data.
+ // `play_area_changed` should be emitted if play area data is available and either the reference frame or world scale changes.
+ return PackedVector3Array();
+};
+
/** these will only be implemented on AR interfaces, so we want dummies for VR **/
bool XRInterface::get_anchor_detection_is_enabled() const {
return false;
@@ -114,9 +152,24 @@ int XRInterface::get_camera_feed_id() {
}
/** these are optional, so we want dummies **/
+PackedStringArray XRInterface::get_suggested_tracker_names() const {
+ PackedStringArray arr;
+
+ return arr;
+}
+
+PackedStringArray XRInterface::get_suggested_pose_names(const StringName &p_tracker_name) const {
+ PackedStringArray arr;
+
+ return arr;
+}
+
XRInterface::TrackingStatus XRInterface::get_tracking_status() const {
return XR_UNKNOWN_TRACKING;
}
void XRInterface::notification(int p_what) {
}
+
+void XRInterface::trigger_haptic_pulse(const String &p_action_name, const StringName &p_tracker_name, double p_frequency, double p_amplitude, double p_duration_sec, double p_delay_sec) {
+}
diff --git a/servers/xr/xr_interface.h b/servers/xr/xr_interface.h
index 534fa18d8a..aee98f8fee 100644
--- a/servers/xr/xr_interface.h
+++ b/servers/xr/xr_interface.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -39,8 +39,6 @@
struct BlitToScreen;
/**
- @author Bastiaan Olij <mux213@gmail.com>
-
The XR interface is a template class on top of which we build interface to different AR, VR and tracking SDKs.
The idea is that we subclass this class, implement the logic, and then instantiate a singleton of each interface
when Godot starts. These instances do not initialize themselves but register themselves with the AR/VR server.
@@ -58,14 +56,10 @@ public:
XR_NONE = 0, /* no capabilities */
XR_MONO = 1, /* can be used with mono output */
XR_STEREO = 2, /* can be used with stereo output */
- XR_AR = 4, /* offers a camera feed for AR */
- XR_EXTERNAL = 8 /* renders to external device */
- };
-
- enum Eyes {
- EYE_MONO, /* my son says we should call this EYE_CYCLOPS */
- EYE_LEFT,
- EYE_RIGHT
+ XR_QUAD = 4, /* can be used with quad output (not currently supported) */
+ XR_VR = 8, /* offers VR support */
+ XR_AR = 16, /* offers AR support */
+ XR_EXTERNAL = 32 /* renders to external device */
};
enum TrackingStatus { /* tracking status currently based on AR but we can start doing more with this for VR as well */
@@ -76,7 +70,14 @@ public:
XR_NOT_TRACKING
};
-private:
+ enum PlayAreaMode { /* defines the mode used by the XR interface for tracking */
+ XR_PLAY_AREA_UNKNOWN, /* Area mode not set or not available */
+ XR_PLAY_AREA_3DOF, /* Only support orientation tracking, no positional tracking, area will center around player */
+ XR_PLAY_AREA_SITTING, /* Player is in seated position, limited positional tracking, fixed guardian around player */
+ XR_PLAY_AREA_ROOMSCALE, /* Player is free to move around, full positional tracking */
+ XR_PLAY_AREA_STAGE, /* Same as roomscale but origin point is fixed to the center of the physical space, XRServer.center_on_hmd disabled */
+ };
+
protected:
_THREAD_SAFE_CLASS_
@@ -94,10 +95,18 @@ public:
virtual bool initialize() = 0; /* initialize this interface, if this has an HMD it becomes the primary interface */
virtual void uninitialize() = 0; /* deinitialize this interface */
+ /** input and output **/
+
+ virtual PackedStringArray get_suggested_tracker_names() const; /* return a list of likely/suggested tracker names */
+ virtual PackedStringArray get_suggested_pose_names(const StringName &p_tracker_name) const; /* return a list of likely/suggested action names for this tracker */
virtual TrackingStatus get_tracking_status() const; /* get the status of our current tracking */
+ virtual void trigger_haptic_pulse(const String &p_action_name, const StringName &p_tracker_name, double p_frequency, double p_amplitude, double p_duration_sec, double p_delay_sec = 0); /* trigger a haptic pulse */
/** specific to VR **/
- // nothing yet
+ virtual bool supports_play_area_mode(XRInterface::PlayAreaMode p_mode); /* query if this interface supports this play area mode */
+ virtual XRInterface::PlayAreaMode get_play_area_mode() const; /* get the current play area mode */
+ virtual bool set_play_area_mode(XRInterface::PlayAreaMode p_mode); /* change the play area mode, note that this should return false if the mode is not available */
+ virtual PackedVector3Array get_play_area() const; /* if available, returns an array of vectors denoting the play area the player can move around in */
/** specific to AR **/
virtual bool get_anchor_detection_is_enabled() const;
@@ -124,7 +133,7 @@ public:
};
VARIANT_ENUM_CAST(XRInterface::Capabilities);
-VARIANT_ENUM_CAST(XRInterface::Eyes);
VARIANT_ENUM_CAST(XRInterface::TrackingStatus);
+VARIANT_ENUM_CAST(XRInterface::PlayAreaMode);
-#endif // !XR_INTERFACE_H
+#endif // XR_INTERFACE_H
diff --git a/servers/xr/xr_interface_extension.cpp b/servers/xr/xr_interface_extension.cpp
index 7fdf90770d..9dae3b162d 100644
--- a/servers/xr/xr_interface_extension.cpp
+++ b/servers/xr/xr_interface_extension.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -41,7 +41,10 @@ void XRInterfaceExtension::_bind_methods() {
GDVIRTUAL_BIND(_initialize);
GDVIRTUAL_BIND(_uninitialize);
- GDVIRTUAL_BIND(_get_tracking_status);
+ GDVIRTUAL_BIND(_supports_play_area_mode, "mode");
+ GDVIRTUAL_BIND(_get_play_area_mode);
+ GDVIRTUAL_BIND(_set_play_area_mode, "mode");
+ GDVIRTUAL_BIND(_get_play_area);
GDVIRTUAL_BIND(_get_render_target_size);
GDVIRTUAL_BIND(_get_view_count);
@@ -54,6 +57,13 @@ void XRInterfaceExtension::_bind_methods() {
GDVIRTUAL_BIND(_process);
GDVIRTUAL_BIND(_notification, "what");
+ /** input and output **/
+
+ GDVIRTUAL_BIND(_get_suggested_tracker_names);
+ GDVIRTUAL_BIND(_get_suggested_pose_names, "tracker_name");
+ GDVIRTUAL_BIND(_get_tracking_status);
+ GDVIRTUAL_BIND(_trigger_haptic_pulse, "action_name", "tracker_name", "frequency", "amplitude", "duration_sec", "delay_sec");
+
// we don't have any properties specific to VR yet....
// but we do have properties specific to AR....
@@ -111,6 +121,22 @@ void XRInterfaceExtension::uninitialize() {
GDVIRTUAL_CALL(_uninitialize);
}
+PackedStringArray XRInterfaceExtension::get_suggested_tracker_names() const {
+ PackedStringArray arr;
+
+ GDVIRTUAL_CALL(_get_suggested_tracker_names, arr);
+
+ return arr;
+}
+
+PackedStringArray XRInterfaceExtension::get_suggested_pose_names(const StringName &p_tracker_name) const {
+ PackedStringArray arr;
+
+ GDVIRTUAL_CALL(_get_suggested_pose_names, p_tracker_name, arr);
+
+ return arr;
+}
+
XRInterface::TrackingStatus XRInterfaceExtension::get_tracking_status() const {
uint32_t status;
@@ -121,6 +147,48 @@ XRInterface::TrackingStatus XRInterfaceExtension::get_tracking_status() const {
return XR_UNKNOWN_TRACKING;
}
+void XRInterfaceExtension::trigger_haptic_pulse(const String &p_action_name, const StringName &p_tracker_name, double p_frequency, double p_amplitude, double p_duration_sec, double p_delay_sec) {
+ GDVIRTUAL_CALL(_trigger_haptic_pulse, p_action_name, p_tracker_name, p_frequency, p_amplitude, p_duration_sec, p_delay_sec);
+}
+
+bool XRInterfaceExtension::supports_play_area_mode(XRInterface::PlayAreaMode p_mode) {
+ bool is_supported;
+
+ if (GDVIRTUAL_CALL(_supports_play_area_mode, p_mode, is_supported)) {
+ return is_supported;
+ }
+
+ return false;
+}
+
+XRInterface::PlayAreaMode XRInterfaceExtension::get_play_area_mode() const {
+ uint32_t mode;
+
+ if (GDVIRTUAL_CALL(_get_play_area_mode, mode)) {
+ return XRInterface::PlayAreaMode(mode);
+ }
+
+ return XRInterface::XR_PLAY_AREA_UNKNOWN;
+}
+
+bool XRInterfaceExtension::set_play_area_mode(XRInterface::PlayAreaMode p_mode) {
+ bool success;
+
+ if (GDVIRTUAL_CALL(_set_play_area_mode, p_mode, success)) {
+ return success;
+ }
+
+ return false;
+}
+
+PackedVector3Array XRInterfaceExtension::get_play_area() const {
+ PackedVector3Array arr;
+
+ GDVIRTUAL_CALL(_get_play_area, arr);
+
+ return arr;
+}
+
/** these will only be implemented on AR interfaces, so we want dummies for VR **/
bool XRInterfaceExtension::get_anchor_detection_is_enabled() const {
bool enabled;
diff --git a/servers/xr/xr_interface_extension.h b/servers/xr/xr_interface_extension.h
index 3b7af4c0a2..e22ec2b872 100644
--- a/servers/xr/xr_interface_extension.h
+++ b/servers/xr/xr_interface_extension.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -62,11 +62,28 @@ public:
GDVIRTUAL0R(bool, _initialize);
GDVIRTUAL0(_uninitialize);
+ /** input and output **/
+
+ virtual PackedStringArray get_suggested_tracker_names() const override; /* return a list of likely/suggested tracker names */
+ virtual PackedStringArray get_suggested_pose_names(const StringName &p_tracker_name) const override; /* return a list of likely/suggested action names for this tracker */
virtual TrackingStatus get_tracking_status() const override;
+ virtual void trigger_haptic_pulse(const String &p_action_name, const StringName &p_tracker_name, double p_frequency, double p_amplitude, double p_duration_sec, double p_delay_sec = 0) override;
+
+ GDVIRTUAL0RC(PackedStringArray, _get_suggested_tracker_names);
+ GDVIRTUAL1RC(PackedStringArray, _get_suggested_pose_names, const StringName &);
GDVIRTUAL0RC(uint32_t, _get_tracking_status);
+ GDVIRTUAL6(_trigger_haptic_pulse, const String &, const StringName &, double, double, double, double);
/** specific to VR **/
- // nothing yet
+ virtual bool supports_play_area_mode(XRInterface::PlayAreaMode p_mode) override; /* query if this interface supports this play area mode */
+ virtual XRInterface::PlayAreaMode get_play_area_mode() const override; /* get the current play area mode */
+ virtual bool set_play_area_mode(XRInterface::PlayAreaMode p_mode) override; /* change the play area mode, note that this should return false if the mode is not available */
+ virtual PackedVector3Array get_play_area() const override; /* if available, returns an array of vectors denoting the play area the player can move around in */
+
+ GDVIRTUAL1RC(bool, _supports_play_area_mode, XRInterface::PlayAreaMode);
+ GDVIRTUAL0RC(uint32_t, _get_play_area_mode);
+ GDVIRTUAL1RC(bool, _set_play_area_mode, uint32_t);
+ GDVIRTUAL0RC(PackedVector3Array, _get_play_area);
/** specific to AR **/
virtual bool get_anchor_detection_is_enabled() const override;
diff --git a/servers/xr/xr_pose.cpp b/servers/xr/xr_pose.cpp
new file mode 100644
index 0000000000..400f13b9c2
--- /dev/null
+++ b/servers/xr/xr_pose.cpp
@@ -0,0 +1,126 @@
+/*************************************************************************/
+/* xr_pose.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 "xr_pose.h"
+
+#include "servers/xr_server.h"
+
+void XRPose::_bind_methods() {
+ BIND_ENUM_CONSTANT(XR_TRACKING_CONFIDENCE_NONE);
+ BIND_ENUM_CONSTANT(XR_TRACKING_CONFIDENCE_LOW);
+ BIND_ENUM_CONSTANT(XR_TRACKING_CONFIDENCE_HIGH);
+
+ ClassDB::bind_method(D_METHOD("set_has_tracking_data", "has_tracking_data"), &XRPose::set_has_tracking_data);
+ ClassDB::bind_method(D_METHOD("get_has_tracking_data"), &XRPose::get_has_tracking_data);
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "has_tracking_data"), "set_has_tracking_data", "get_has_tracking_data");
+
+ ClassDB::bind_method(D_METHOD("set_name", "name"), &XRPose::set_name);
+ ClassDB::bind_method(D_METHOD("get_name"), &XRPose::get_name);
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "name"), "set_name", "get_name");
+
+ ClassDB::bind_method(D_METHOD("set_transform", "transform"), &XRPose::set_transform);
+ ClassDB::bind_method(D_METHOD("get_transform"), &XRPose::get_transform);
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "transform"), "set_transform", "get_transform");
+ ClassDB::bind_method(D_METHOD("get_adjusted_transform"), &XRPose::get_adjusted_transform);
+
+ ClassDB::bind_method(D_METHOD("set_linear_velocity", "velocity"), &XRPose::set_linear_velocity);
+ ClassDB::bind_method(D_METHOD("get_linear_velocity"), &XRPose::get_linear_velocity);
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "linear_velocity"), "set_linear_velocity", "get_linear_velocity");
+
+ ClassDB::bind_method(D_METHOD("set_angular_velocity", "velocity"), &XRPose::set_angular_velocity);
+ ClassDB::bind_method(D_METHOD("get_angular_velocity"), &XRPose::get_angular_velocity);
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "angular_velocity"), "set_angular_velocity", "get_angular_velocity");
+
+ ClassDB::bind_method(D_METHOD("set_tracking_confidence", "tracking_confidence"), &XRPose::set_tracking_confidence);
+ ClassDB::bind_method(D_METHOD("get_tracking_confidence"), &XRPose::get_tracking_confidence);
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "tracking_confidence"), "set_tracking_confidence", "get_tracking_confidence");
+}
+
+void XRPose::set_has_tracking_data(const bool p_has_tracking_data) {
+ has_tracking_data = p_has_tracking_data;
+}
+bool XRPose::get_has_tracking_data() const {
+ return has_tracking_data;
+}
+
+void XRPose::set_name(const StringName &p_name) {
+ name = p_name;
+}
+
+StringName XRPose::get_name() const {
+ return name;
+}
+
+void XRPose::set_transform(const Transform3D p_transform) {
+ transform = p_transform;
+}
+
+Transform3D XRPose::get_transform() const {
+ return transform;
+}
+
+Transform3D XRPose::get_adjusted_transform() const {
+ Transform3D adjusted_transform = transform;
+
+ XRServer *xr_server = XRServer::get_singleton();
+ ERR_FAIL_NULL_V(xr_server, transform);
+
+ // apply world scale
+ adjusted_transform.origin *= xr_server->get_world_scale();
+
+ // apply reference frame
+ adjusted_transform = xr_server->get_reference_frame() * adjusted_transform;
+
+ return adjusted_transform;
+}
+
+void XRPose::set_linear_velocity(const Vector3 p_velocity) {
+ linear_velocity = p_velocity;
+}
+
+Vector3 XRPose::get_linear_velocity() const {
+ return linear_velocity;
+}
+
+void XRPose::set_angular_velocity(const Vector3 p_velocity) {
+ angular_velocity = p_velocity;
+}
+
+Vector3 XRPose::get_angular_velocity() const {
+ return angular_velocity;
+}
+
+void XRPose::set_tracking_confidence(const XRPose::TrackingConfidence p_tracking_confidence) {
+ tracking_confidence = p_tracking_confidence;
+}
+
+XRPose::TrackingConfidence XRPose::get_tracking_confidence() const {
+ return tracking_confidence;
+}
diff --git a/servers/xr/xr_pose.h b/servers/xr/xr_pose.h
new file mode 100644
index 0000000000..f306c22390
--- /dev/null
+++ b/servers/xr/xr_pose.h
@@ -0,0 +1,81 @@
+/*************************************************************************/
+/* xr_pose.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 XR_POSE_H
+#define XR_POSE_H
+
+#include "core/object/ref_counted.h"
+
+class XRPose : public RefCounted {
+ GDCLASS(XRPose, RefCounted);
+
+public:
+ // TrackingConfidence gives an indication of how reliable our transform data is.
+ enum TrackingConfidence {
+ XR_TRACKING_CONFIDENCE_NONE, // No tracking information is available for this pose.
+ XR_TRACKING_CONFIDENCE_LOW, // Tracking information may be inaccurate or estimated.
+ XR_TRACKING_CONFIDENCE_HIGH // Tracking information is deemed accurate and up to date.
+ };
+
+private:
+ bool has_tracking_data = false;
+ StringName name;
+ Transform3D transform;
+ Vector3 linear_velocity;
+ Vector3 angular_velocity;
+ TrackingConfidence tracking_confidence = XR_TRACKING_CONFIDENCE_NONE;
+
+protected:
+ static void _bind_methods();
+
+public:
+ void set_has_tracking_data(const bool p_has_tracking_data);
+ bool get_has_tracking_data() const;
+
+ void set_name(const StringName &p_name);
+ StringName get_name() const;
+
+ void set_transform(const Transform3D p_transform);
+ Transform3D get_transform() const;
+ Transform3D get_adjusted_transform() const;
+
+ void set_linear_velocity(const Vector3 p_velocity);
+ Vector3 get_linear_velocity() const;
+
+ void set_angular_velocity(const Vector3 p_velocity);
+ Vector3 get_angular_velocity() const;
+
+ void set_tracking_confidence(const TrackingConfidence p_tracking_confidence);
+ TrackingConfidence get_tracking_confidence() const;
+};
+
+VARIANT_ENUM_CAST(XRPose::TrackingConfidence);
+
+#endif
diff --git a/servers/xr/xr_positional_tracker.cpp b/servers/xr/xr_positional_tracker.cpp
index e9383db941..62e011654e 100644
--- a/servers/xr/xr_positional_tracker.cpp
+++ b/servers/xr/xr_positional_tracker.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -37,29 +37,37 @@ void XRPositionalTracker::_bind_methods() {
BIND_ENUM_CONSTANT(TRACKER_HAND_LEFT);
BIND_ENUM_CONSTANT(TRACKER_HAND_RIGHT);
- // this class is read only from GDScript, so we only have access to getters..
ClassDB::bind_method(D_METHOD("get_tracker_type"), &XRPositionalTracker::get_tracker_type);
- ClassDB::bind_method(D_METHOD("get_tracker_id"), &XRPositionalTracker::get_tracker_id);
+ ClassDB::bind_method(D_METHOD("set_tracker_type", "type"), &XRPositionalTracker::set_tracker_type);
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "type"), "set_tracker_type", "get_tracker_type");
+
ClassDB::bind_method(D_METHOD("get_tracker_name"), &XRPositionalTracker::get_tracker_name);
- ClassDB::bind_method(D_METHOD("get_joy_id"), &XRPositionalTracker::get_joy_id);
- ClassDB::bind_method(D_METHOD("is_tracking_orientation"), &XRPositionalTracker::is_tracking_orientation);
- ClassDB::bind_method(D_METHOD("get_orientation"), &XRPositionalTracker::get_orientation);
- ClassDB::bind_method(D_METHOD("is_tracking_position"), &XRPositionalTracker::is_tracking_position);
- ClassDB::bind_method(D_METHOD("get_position"), &XRPositionalTracker::get_position);
+ ClassDB::bind_method(D_METHOD("set_tracker_name", "name"), &XRPositionalTracker::set_tracker_name);
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "name"), "set_tracker_name", "get_tracker_name");
+
+ ClassDB::bind_method(D_METHOD("get_tracker_desc"), &XRPositionalTracker::get_tracker_desc);
+ ClassDB::bind_method(D_METHOD("set_tracker_desc", "description"), &XRPositionalTracker::set_tracker_desc);
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "description"), "set_tracker_desc", "get_tracker_desc");
+
ClassDB::bind_method(D_METHOD("get_tracker_hand"), &XRPositionalTracker::get_tracker_hand);
- ClassDB::bind_method(D_METHOD("get_transform", "adjust_by_reference_frame"), &XRPositionalTracker::get_transform);
- ClassDB::bind_method(D_METHOD("get_mesh"), &XRPositionalTracker::get_mesh);
-
- // these functions we don't want to expose to normal users but do need to be callable from GDNative
- ClassDB::bind_method(D_METHOD("_set_tracker_type", "type"), &XRPositionalTracker::set_tracker_type);
- ClassDB::bind_method(D_METHOD("_set_tracker_name", "name"), &XRPositionalTracker::set_tracker_name);
- ClassDB::bind_method(D_METHOD("_set_joy_id", "joy_id"), &XRPositionalTracker::set_joy_id);
- ClassDB::bind_method(D_METHOD("_set_orientation", "orientation"), &XRPositionalTracker::set_orientation);
- ClassDB::bind_method(D_METHOD("_set_rw_position", "rw_position"), &XRPositionalTracker::set_rw_position);
- ClassDB::bind_method(D_METHOD("_set_mesh", "mesh"), &XRPositionalTracker::set_mesh);
+ ClassDB::bind_method(D_METHOD("set_tracker_hand", "hand"), &XRPositionalTracker::set_tracker_hand);
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "hand", PROPERTY_HINT_ENUM, "Unknown,Left,Right"), "set_tracker_hand", "get_tracker_hand");
+
+ ClassDB::bind_method(D_METHOD("has_pose", "name"), &XRPositionalTracker::has_pose);
+ ClassDB::bind_method(D_METHOD("get_pose", "name"), &XRPositionalTracker::get_pose);
+ ClassDB::bind_method(D_METHOD("invalidate_pose", "name"), &XRPositionalTracker::invalidate_pose);
+ ClassDB::bind_method(D_METHOD("set_pose", "name", "transform", "linear_velocity", "angular_velocity", "tracking_confidence"), &XRPositionalTracker::set_pose);
+ ADD_SIGNAL(MethodInfo("pose_changed", PropertyInfo(Variant::OBJECT, "pose", PROPERTY_HINT_RESOURCE_TYPE, "XRPose")));
+
+ ClassDB::bind_method(D_METHOD("get_input", "name"), &XRPositionalTracker::get_input);
+ ClassDB::bind_method(D_METHOD("set_input", "name", "value"), &XRPositionalTracker::set_input);
+ ADD_SIGNAL(MethodInfo("button_pressed", PropertyInfo(Variant::STRING, "name")));
+ ADD_SIGNAL(MethodInfo("button_released", PropertyInfo(Variant::STRING, "name")));
+ ADD_SIGNAL(MethodInfo("input_value_changed", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::FLOAT, "value")));
+ ADD_SIGNAL(MethodInfo("input_axis_changed", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::VECTOR2, "vector")));
+
ClassDB::bind_method(D_METHOD("get_rumble"), &XRPositionalTracker::get_rumble);
ClassDB::bind_method(D_METHOD("set_rumble", "rumble"), &XRPositionalTracker::set_rumble);
-
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rumble"), "set_rumble", "get_rumble");
};
@@ -67,13 +75,6 @@ void XRPositionalTracker::set_tracker_type(XRServer::TrackerType p_type) {
if (type != p_type) {
type = p_type;
hand = XRPositionalTracker::TRACKER_HAND_UNKNOWN;
-
- XRServer *xr_server = XRServer::get_singleton();
- ERR_FAIL_NULL(xr_server);
-
- // get a tracker id for our type
- // note if this is a controller this will be 3 or higher but we may change it later.
- tracker_id = xr_server->get_free_tracker_id_for_type(p_type);
};
};
@@ -81,7 +82,8 @@ XRServer::TrackerType XRPositionalTracker::get_tracker_type() const {
return type;
};
-void XRPositionalTracker::set_tracker_name(const String &p_name) {
+void XRPositionalTracker::set_tracker_name(const StringName &p_name) {
+ // Note: this should not be changed after the tracker is registered with the XRServer!
name = p_name;
};
@@ -89,85 +91,13 @@ StringName XRPositionalTracker::get_tracker_name() const {
return name;
};
-int XRPositionalTracker::get_tracker_id() const {
- return tracker_id;
-};
-
-void XRPositionalTracker::set_joy_id(int p_joy_id) {
- joy_id = p_joy_id;
-};
-
-int XRPositionalTracker::get_joy_id() const {
- return joy_id;
-};
-
-bool XRPositionalTracker::is_tracking_orientation() const {
- return tracking_orientation;
-};
-
-void XRPositionalTracker::set_orientation(const Basis &p_orientation) {
- _THREAD_SAFE_METHOD_
-
- tracking_orientation = true; // obviously we have this
- orientation = p_orientation;
-};
-
-Basis XRPositionalTracker::get_orientation() const {
- _THREAD_SAFE_METHOD_
-
- return orientation;
-};
-
-bool XRPositionalTracker::is_tracking_position() const {
- return tracking_position;
-};
-
-void XRPositionalTracker::set_position(const Vector3 &p_position) {
- _THREAD_SAFE_METHOD_
-
- XRServer *xr_server = XRServer::get_singleton();
- ERR_FAIL_NULL(xr_server);
- real_t world_scale = xr_server->get_world_scale();
- ERR_FAIL_COND(world_scale == 0);
-
- tracking_position = true; // obviously we have this
- rw_position = p_position / world_scale;
-};
-
-Vector3 XRPositionalTracker::get_position() const {
- _THREAD_SAFE_METHOD_
-
- XRServer *xr_server = XRServer::get_singleton();
- ERR_FAIL_NULL_V(xr_server, rw_position);
- real_t world_scale = xr_server->get_world_scale();
-
- return rw_position * world_scale;
-};
-
-void XRPositionalTracker::set_rw_position(const Vector3 &p_rw_position) {
- _THREAD_SAFE_METHOD_
-
- tracking_position = true; // obviously we have this
- rw_position = p_rw_position;
-};
-
-Vector3 XRPositionalTracker::get_rw_position() const {
- _THREAD_SAFE_METHOD_
-
- return rw_position;
-};
-
-void XRPositionalTracker::set_mesh(const Ref<Mesh> &p_mesh) {
- _THREAD_SAFE_METHOD_
-
- mesh = p_mesh;
-};
-
-Ref<Mesh> XRPositionalTracker::get_mesh() const {
- _THREAD_SAFE_METHOD_
+void XRPositionalTracker::set_tracker_desc(const String &p_desc) {
+ description = p_desc;
+}
- return mesh;
-};
+String XRPositionalTracker::get_tracker_desc() const {
+ return description;
+}
XRPositionalTracker::TrackerHand XRPositionalTracker::get_tracker_hand() const {
return hand;
@@ -182,33 +112,99 @@ void XRPositionalTracker::set_tracker_hand(const XRPositionalTracker::TrackerHan
ERR_FAIL_COND((type != XRServer::TRACKER_CONTROLLER) && (p_hand != XRPositionalTracker::TRACKER_HAND_UNKNOWN));
hand = p_hand;
- if (hand == XRPositionalTracker::TRACKER_HAND_LEFT) {
- if (!xr_server->is_tracker_id_in_use_for_type(type, 1)) {
- tracker_id = 1;
- };
- } else if (hand == XRPositionalTracker::TRACKER_HAND_RIGHT) {
- if (!xr_server->is_tracker_id_in_use_for_type(type, 2)) {
- tracker_id = 2;
- };
- };
};
};
-Transform3D XRPositionalTracker::get_transform(bool p_adjust_by_reference_frame) const {
- Transform3D new_transform;
+bool XRPositionalTracker::has_pose(const StringName &p_action_name) const {
+ return poses.has(p_action_name);
+}
- new_transform.basis = get_orientation();
- new_transform.origin = get_position();
+Ref<XRPose> XRPositionalTracker::get_pose(const StringName &p_action_name) const {
+ Ref<XRPose> pose;
- if (p_adjust_by_reference_frame) {
- XRServer *xr_server = XRServer::get_singleton();
- ERR_FAIL_NULL_V(xr_server, new_transform);
+ if (poses.has(p_action_name)) {
+ pose = poses[p_action_name];
+ }
- new_transform = xr_server->get_reference_frame() * new_transform;
- };
+ return pose;
+}
- return new_transform;
-};
+void XRPositionalTracker::invalidate_pose(const StringName &p_action_name) {
+ // only update this if we were tracking this pose
+ if (poses.has(p_action_name)) {
+ // We just set tracking data as invalid, we leave our current transform and velocity data as is so controllers don't suddenly jump to origin.
+ poses[p_action_name]->set_has_tracking_data(false);
+ }
+}
+
+void XRPositionalTracker::set_pose(const StringName &p_action_name, const Transform3D &p_transform, const Vector3 &p_linear_velocity, const Vector3 &p_angular_velocity, const XRPose::TrackingConfidence p_tracking_confidence) {
+ Ref<XRPose> new_pose;
+
+ new_pose.instantiate();
+ new_pose->set_name(p_action_name);
+ new_pose->set_has_tracking_data(true);
+ new_pose->set_transform(p_transform);
+ new_pose->set_linear_velocity(p_linear_velocity);
+ new_pose->set_angular_velocity(p_angular_velocity);
+ new_pose->set_tracking_confidence(p_tracking_confidence);
+
+ poses[p_action_name] = new_pose;
+ emit_signal("pose_changed", new_pose);
+
+ // TODO discuss whether we also want to create and emit an InputEventXRPose event
+}
+
+Variant XRPositionalTracker::get_input(const StringName &p_action_name) const {
+ if (inputs.has(p_action_name)) {
+ return inputs[p_action_name];
+ } else {
+ return Variant();
+ }
+}
+
+void XRPositionalTracker::set_input(const StringName &p_action_name, const Variant &p_value) {
+ bool changed = false;
+
+ // XR inputs
+
+ if (inputs.has(p_action_name)) {
+ changed = inputs[p_action_name] != p_value;
+ } else {
+ changed = true;
+ }
+
+ if (changed) {
+ // store the new value
+ inputs[p_action_name] = p_value;
+
+ // emit signals to let the rest of the world know
+ switch (p_value.get_type()) {
+ case Variant::BOOL: {
+ bool pressed = p_value;
+ if (pressed) {
+ emit_signal("button_pressed", p_action_name);
+ } else {
+ emit_signal("button_released", p_action_name);
+ }
+
+ // TODO discuss whether we also want to create and emit an InputEventXRButton event
+ } break;
+ case Variant::FLOAT: {
+ emit_signal("input_value_changed", p_action_name, p_value);
+
+ // TODO discuss whether we also want to create and emit an InputEventXRValue event
+ } break;
+ case Variant::VECTOR2: {
+ emit_signal("input_axis_changed", p_action_name, p_value);
+
+ // TODO discuss whether we also want to create and emit an InputEventXRAxis event
+ } break;
+ default: {
+ // ???
+ } break;
+ }
+ }
+}
real_t XRPositionalTracker::get_rumble() const {
return rumble;
@@ -225,10 +221,6 @@ void XRPositionalTracker::set_rumble(real_t p_rumble) {
XRPositionalTracker::XRPositionalTracker() {
type = XRServer::TRACKER_UNKNOWN;
name = "Unknown";
- joy_id = -1;
- tracker_id = 0;
- tracking_orientation = false;
- tracking_position = false;
hand = TRACKER_HAND_UNKNOWN;
rumble = 0.0;
};
diff --git a/servers/xr/xr_positional_tracker.h b/servers/xr/xr_positional_tracker.h
index 5577582929..2f358cbb21 100644
--- a/servers/xr/xr_positional_tracker.h
+++ b/servers/xr/xr_positional_tracker.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -33,11 +33,10 @@
#include "core/os/thread_safe.h"
#include "scene/resources/mesh.h"
+#include "servers/xr/xr_pose.h"
#include "servers/xr_server.h"
/**
- @author Bastiaan Olij <mux213@gmail.com>
-
The positional tracker object as an object that represents the position and orientation of a tracked object like a controller or headset.
An AR/VR Interface will registered the trackers it manages with our AR/VR server and update its position and orientation.
This is where potentially additional AR/VR interfaces may be active as there are AR/VR SDKs that solely deal with positional tracking.
@@ -57,14 +56,14 @@ public:
private:
XRServer::TrackerType type; // type of tracker
StringName name; // (unique) name of the tracker
- int tracker_id; // tracker index id that is unique per type
+ String description; // description of the tracker, this is interface dependent, for OpenXR this will be the interaction profile bound for to the tracker
+ TrackerHand hand; // if known, the hand this tracker is held in
+
+ Map<StringName, Ref<XRPose>> poses;
+ Map<StringName, Variant> inputs;
+
int joy_id; // if we also have a related joystick entity, the id of the joystick
- bool tracking_orientation; // do we track orientation?
- Basis orientation; // our orientation
- bool tracking_position; // do we track position?
- Vector3 rw_position; // our position "in the real world, so without world_scale applied"
Ref<Mesh> mesh; // when available, a mesh that can be used to render this tracker
- TrackerHand hand; // if known, the hand this tracker is held in
real_t rumble; // rumble strength, 0.0 is off, 1.0 is maximum, note that we only record here, xr_interface is responsible for execution
protected:
@@ -73,27 +72,24 @@ protected:
public:
void set_tracker_type(XRServer::TrackerType p_type);
XRServer::TrackerType get_tracker_type() const;
- void set_tracker_name(const String &p_name);
+ void set_tracker_name(const StringName &p_name);
StringName get_tracker_name() const;
- int get_tracker_id() const;
- void set_joy_id(int p_joy_id);
- int get_joy_id() const;
- bool is_tracking_orientation() const;
- void set_orientation(const Basis &p_orientation);
- Basis get_orientation() const;
- bool is_tracking_position() const;
- void set_position(const Vector3 &p_position); // set position with world_scale applied
- Vector3 get_position() const; // get position with world_scale applied
- void set_rw_position(const Vector3 &p_rw_position);
- Vector3 get_rw_position() const;
+ void set_tracker_desc(const String &p_desc);
+ String get_tracker_desc() const;
XRPositionalTracker::TrackerHand get_tracker_hand() const;
void set_tracker_hand(const XRPositionalTracker::TrackerHand p_hand);
+
+ bool has_pose(const StringName &p_action_name) const;
+ Ref<XRPose> get_pose(const StringName &p_action_name) const;
+ void invalidate_pose(const StringName &p_action_name);
+ void set_pose(const StringName &p_action_name, const Transform3D &p_transform, const Vector3 &p_linear_velocity, const Vector3 &p_angular_velocity, const XRPose::TrackingConfidence p_tracking_confidence = XRPose::XR_TRACKING_CONFIDENCE_HIGH);
+
+ Variant get_input(const StringName &p_action_name) const;
+ void set_input(const StringName &p_action_name, const Variant &p_value);
+
+ // TODO replace by new implementation
real_t get_rumble() const;
void set_rumble(real_t p_rumble);
- void set_mesh(const Ref<Mesh> &p_mesh);
- Ref<Mesh> get_mesh() const;
-
- Transform3D get_transform(bool p_adjust_by_reference_frame) const;
XRPositionalTracker();
~XRPositionalTracker() {}
@@ -101,4 +97,4 @@ public:
VARIANT_ENUM_CAST(XRPositionalTracker::TrackerHand);
-#endif
+#endif // XR_POSITIONAL_TRACKER_H
diff --git a/servers/xr_server.cpp b/servers/xr_server.cpp
index 780bd10fc5..69f4c69b53 100644
--- a/servers/xr_server.cpp
+++ b/servers/xr_server.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -54,10 +54,11 @@ void XRServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_interface", "idx"), &XRServer::get_interface);
ClassDB::bind_method(D_METHOD("get_interfaces"), &XRServer::get_interfaces);
ClassDB::bind_method(D_METHOD("find_interface", "name"), &XRServer::find_interface);
- ClassDB::bind_method(D_METHOD("get_tracker_count"), &XRServer::get_tracker_count);
- ClassDB::bind_method(D_METHOD("get_tracker", "idx"), &XRServer::get_tracker);
+
ClassDB::bind_method(D_METHOD("add_tracker", "tracker"), &XRServer::add_tracker);
ClassDB::bind_method(D_METHOD("remove_tracker", "tracker"), &XRServer::remove_tracker);
+ ClassDB::bind_method(D_METHOD("get_trackers", "tracker_types"), &XRServer::get_trackers);
+ ClassDB::bind_method(D_METHOD("get_tracker", "tracker_name"), &XRServer::get_tracker);
ClassDB::bind_method(D_METHOD("get_primary_interface"), &XRServer::get_primary_interface);
ClassDB::bind_method(D_METHOD("set_primary_interface", "interface"), &XRServer::set_primary_interface);
@@ -68,6 +69,7 @@ void XRServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_last_commit_usec"), &XRServer::get_last_commit_usec);
ClassDB::bind_method(D_METHOD("get_last_frame_usec"), &XRServer::get_last_frame_usec);
+ BIND_ENUM_CONSTANT(TRACKER_HEAD);
BIND_ENUM_CONSTANT(TRACKER_CONTROLLER);
BIND_ENUM_CONSTANT(TRACKER_BASESTATION);
BIND_ENUM_CONSTANT(TRACKER_ANCHOR);
@@ -82,8 +84,9 @@ void XRServer::_bind_methods() {
ADD_SIGNAL(MethodInfo("interface_added", PropertyInfo(Variant::STRING_NAME, "interface_name")));
ADD_SIGNAL(MethodInfo("interface_removed", PropertyInfo(Variant::STRING_NAME, "interface_name")));
- ADD_SIGNAL(MethodInfo("tracker_added", PropertyInfo(Variant::STRING_NAME, "tracker_name"), PropertyInfo(Variant::INT, "type"), PropertyInfo(Variant::INT, "id")));
- ADD_SIGNAL(MethodInfo("tracker_removed", PropertyInfo(Variant::STRING_NAME, "tracker_name"), PropertyInfo(Variant::INT, "type"), PropertyInfo(Variant::INT, "id")));
+ ADD_SIGNAL(MethodInfo("tracker_added", PropertyInfo(Variant::STRING_NAME, "tracker_name"), PropertyInfo(Variant::INT, "type")));
+ ADD_SIGNAL(MethodInfo("tracker_updated", PropertyInfo(Variant::STRING_NAME, "tracker_name"), PropertyInfo(Variant::INT, "type")));
+ ADD_SIGNAL(MethodInfo("tracker_removed", PropertyInfo(Variant::STRING_NAME, "tracker_name"), PropertyInfo(Variant::INT, "type")));
};
double XRServer::get_world_scale() const {
@@ -113,35 +116,43 @@ Transform3D XRServer::get_reference_frame() const {
};
void XRServer::center_on_hmd(RotationMode p_rotation_mode, bool p_keep_height) {
- if (primary_interface != nullptr) {
- // clear our current reference frame or we'll end up double adjusting it
+ if (primary_interface == nullptr) {
+ return;
+ }
+
+ if (primary_interface->get_play_area_mode() == XRInterface::XR_PLAY_AREA_STAGE) {
+ // center_on_hmd is not available in this mode
reference_frame = Transform3D();
+ return;
+ }
- // requesting our EYE_MONO transform should return our current HMD position
- Transform3D new_reference_frame = primary_interface->get_camera_transform();
+ // clear our current reference frame or we'll end up double adjusting it
+ reference_frame = Transform3D();
- // remove our tilt
- if (p_rotation_mode == 1) {
- // take the Y out of our Z
- new_reference_frame.basis.set_axis(2, Vector3(new_reference_frame.basis.elements[0][2], 0.0, new_reference_frame.basis.elements[2][2]).normalized());
+ // requesting our EYE_MONO transform should return our current HMD position
+ Transform3D new_reference_frame = primary_interface->get_camera_transform();
- // Y is straight up
- new_reference_frame.basis.set_axis(1, Vector3(0.0, 1.0, 0.0));
+ // remove our tilt
+ if (p_rotation_mode == 1) {
+ // take the Y out of our Z
+ new_reference_frame.basis.set_axis(2, Vector3(new_reference_frame.basis.elements[0][2], 0.0, new_reference_frame.basis.elements[2][2]).normalized());
- // and X is our cross reference
- new_reference_frame.basis.set_axis(0, new_reference_frame.basis.get_axis(1).cross(new_reference_frame.basis.get_axis(2)).normalized());
- } else if (p_rotation_mode == 2) {
- // remove our rotation, we're only interesting in centering on position
- new_reference_frame.basis = Basis();
- };
+ // Y is straight up
+ new_reference_frame.basis.set_axis(1, Vector3(0.0, 1.0, 0.0));
- // don't negate our height
- if (p_keep_height) {
- new_reference_frame.origin.y = 0.0;
- };
+ // and X is our cross reference
+ new_reference_frame.basis.set_axis(0, new_reference_frame.basis.get_axis(1).cross(new_reference_frame.basis.get_axis(2)).normalized());
+ } else if (p_rotation_mode == 2) {
+ // remove our rotation, we're only interesting in centering on position
+ new_reference_frame.basis = Basis();
+ };
- reference_frame = new_reference_frame.inverse();
+ // don't negate our height
+ if (p_keep_height) {
+ new_reference_frame.origin.y = 0.0;
};
+
+ reference_frame = new_reference_frame.inverse();
};
Transform3D XRServer::get_hmd_transform() {
@@ -182,7 +193,7 @@ void XRServer::remove_interface(const Ref<XRInterface> &p_interface) {
print_verbose("XR: Removed interface" + p_interface->get_name());
emit_signal(SNAME("interface_removed"), p_interface->get_name());
- interfaces.remove(idx);
+ interfaces.remove_at(idx);
};
int XRServer::get_interface_count() const {
@@ -224,106 +235,121 @@ Array XRServer::get_interfaces() const {
return ret;
};
-/*
- A little extra info on the tracker ids, these are unique per tracker type so we get some consistency in recognising our trackers, specifically controllers.
-
- The first controller that is turned of will get ID 1, the second will get ID 2, etc.
- The magic happens when one of the controllers is turned off, say controller 1 turns off, controller 2 will remain controller 2, controller 3 will remain controller 3.
- If controller number 1 is turned on again it again gets ID 1 unless another new controller was turned on since.
-
- The most likely scenario however is a controller that runs out of battery and another controller being used to replace it.
- Because the controllers are often linked to physical objects, say you're holding a shield in controller 1, your left hand, and a gun in controller 2, your right hand, and controller 1 dies:
- - using our tracker index would suddenly make the gun disappear and the shield jump into your right hand because controller 2 becomes controller 1.
- - using this approach the shield disappears or is no longer tracked, but the gun stays firmly in your right hand because that is still controller 2, further more, if controller 1 is replaced the shield will return.
-*/
-
-bool XRServer::is_tracker_id_in_use_for_type(TrackerType p_tracker_type, int p_tracker_id) const {
- for (int i = 0; i < trackers.size(); i++) {
- if (trackers[i]->get_tracker_type() == p_tracker_type && trackers[i]->get_tracker_id() == p_tracker_id) {
- return true;
- };
- };
-
- // all good
- return false;
+Ref<XRInterface> XRServer::get_primary_interface() const {
+ return primary_interface;
};
-int XRServer::get_free_tracker_id_for_type(TrackerType p_tracker_type) {
- // We start checking at 1, 0 means that it's not a controller..
- // Note that for controller we reserve:
- // - 1 for the left hand controller and
- // - 2 for the right hand controller
- // so we start at 3 :)
- int tracker_id = p_tracker_type == XRServer::TRACKER_CONTROLLER ? 3 : 1;
-
- while (is_tracker_id_in_use_for_type(p_tracker_type, tracker_id)) {
- // try the next one
- tracker_id++;
- };
+void XRServer::set_primary_interface(const Ref<XRInterface> &p_primary_interface) {
+ if (p_primary_interface.is_null()) {
+ print_verbose("XR: Clearing primary interface");
+ primary_interface.unref();
+ } else {
+ primary_interface = p_primary_interface;
- return tracker_id;
+ print_verbose("XR: Primary interface set to: " + primary_interface->get_name());
+ }
};
void XRServer::add_tracker(Ref<XRPositionalTracker> p_tracker) {
ERR_FAIL_COND(p_tracker.is_null());
- trackers.push_back(p_tracker);
- emit_signal(SNAME("tracker_added"), p_tracker->get_tracker_name(), p_tracker->get_tracker_type(), p_tracker->get_tracker_id());
+ StringName tracker_name = p_tracker->get_tracker_name();
+ if (trackers.has(tracker_name)) {
+ if (trackers[tracker_name] != p_tracker) {
+ // We already have a tracker with this name, we're going to replace it
+ trackers[tracker_name] = p_tracker;
+ emit_signal(SNAME("tracker_updated"), tracker_name, p_tracker->get_tracker_type());
+ }
+ } else {
+ trackers[tracker_name] = p_tracker;
+ emit_signal(SNAME("tracker_added"), tracker_name, p_tracker->get_tracker_type());
+ }
};
void XRServer::remove_tracker(Ref<XRPositionalTracker> p_tracker) {
ERR_FAIL_COND(p_tracker.is_null());
- int idx = -1;
- for (int i = 0; i < trackers.size(); i++) {
- if (trackers[i] == p_tracker) {
- idx = i;
- break;
- };
- };
-
- ERR_FAIL_COND(idx == -1);
+ StringName tracker_name = p_tracker->get_tracker_name();
+ if (trackers.has(tracker_name)) {
+ // we send the signal right before removing it
+ emit_signal(SNAME("tracker_removed"), p_tracker->get_tracker_name(), p_tracker->get_tracker_type());
- emit_signal(SNAME("tracker_removed"), p_tracker->get_tracker_name(), p_tracker->get_tracker_type(), p_tracker->get_tracker_id());
- trackers.remove(idx);
+ // and remove it
+ trackers.erase(tracker_name);
+ }
};
-int XRServer::get_tracker_count() const {
- return trackers.size();
-};
+Dictionary XRServer::get_trackers(int p_tracker_types) {
+ Dictionary res;
-Ref<XRPositionalTracker> XRServer::get_tracker(int p_index) const {
- ERR_FAIL_INDEX_V(p_index, trackers.size(), Ref<XRPositionalTracker>());
+ for (int i = 0; i < trackers.size(); i++) {
+ Ref<XRPositionalTracker> tracker = trackers.get_value_at_index(i);
+ if (tracker.is_valid() && (tracker->get_tracker_type() & p_tracker_types) != 0) {
+ res[tracker->get_tracker_name()] = tracker;
+ }
+ }
- return trackers[p_index];
+ return res;
+}
+
+Ref<XRPositionalTracker> XRServer::get_tracker(const StringName &p_name) const {
+ if (trackers.has(p_name)) {
+ return trackers[p_name];
+ } else {
+ // tracker hasn't been registered yet, which is fine, no need to spam the error log...
+ return Ref<XRPositionalTracker>();
+ }
};
-Ref<XRPositionalTracker> XRServer::find_by_type_and_id(TrackerType p_tracker_type, int p_tracker_id) const {
- ERR_FAIL_COND_V(p_tracker_id == 0, Ref<XRPositionalTracker>());
+PackedStringArray XRServer::get_suggested_tracker_names() const {
+ PackedStringArray arr;
- for (int i = 0; i < trackers.size(); i++) {
- if (trackers[i]->get_tracker_type() == p_tracker_type && trackers[i]->get_tracker_id() == p_tracker_id) {
- return trackers[i];
- };
- };
+ for (int i = 0; i < interfaces.size(); i++) {
+ Ref<XRInterface> interface = interfaces[i];
+ PackedStringArray interface_arr = interface->get_suggested_tracker_names();
+ for (int a = 0; a < interface_arr.size(); a++) {
+ if (!arr.has(interface_arr[a])) {
+ arr.push_back(interface_arr[a]);
+ }
+ }
+ }
- return Ref<XRPositionalTracker>();
-};
+ if (arr.size() == 0) {
+ // no suggestions from our tracker? include our defaults
+ arr.push_back(String("head"));
+ arr.push_back(String("left_hand"));
+ arr.push_back(String("right_hand"));
+ }
-Ref<XRInterface> XRServer::get_primary_interface() const {
- return primary_interface;
-};
+ return arr;
+}
-void XRServer::set_primary_interface(const Ref<XRInterface> &p_primary_interface) {
- if (p_primary_interface.is_null()) {
- print_verbose("XR: Clearing primary interface");
- primary_interface.unref();
- } else {
- primary_interface = p_primary_interface;
+PackedStringArray XRServer::get_suggested_pose_names(const StringName &p_tracker_name) const {
+ PackedStringArray arr;
- print_verbose("XR: Primary interface set to: " + primary_interface->get_name());
+ for (int i = 0; i < interfaces.size(); i++) {
+ Ref<XRInterface> interface = interfaces[i];
+ PackedStringArray interface_arr = interface->get_suggested_pose_names(p_tracker_name);
+ for (int a = 0; a < interface_arr.size(); a++) {
+ if (!arr.has(interface_arr[a])) {
+ arr.push_back(interface_arr[a]);
+ }
+ }
}
-};
+
+ if (arr.size() == 0) {
+ // no suggestions from our tracker? include our defaults
+ arr.push_back(String("default"));
+
+ if ((p_tracker_name == "left_hand") || (p_tracker_name == "right_hand")) {
+ arr.push_back(String("aim"));
+ arr.push_back(String("grip"));
+ arr.push_back(String("skeleton"));
+ }
+ }
+
+ return arr;
+}
uint64_t XRServer::get_last_process_usec() {
return last_process_usec;
@@ -370,11 +396,12 @@ XRServer::~XRServer() {
primary_interface.unref();
while (interfaces.size() > 0) {
- interfaces.remove(0);
+ interfaces.remove_at(0);
}
+ // TODO pretty sure there is a clear function or something...
while (trackers.size() > 0) {
- trackers.remove(0);
+ trackers.erase(trackers.get_key_at_index(0));
}
singleton = nullptr;
diff --git a/servers/xr_server.h b/servers/xr_server.h
index 6d07263755..a820634bd9 100644
--- a/servers/xr_server.h
+++ b/servers/xr_server.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 */
@@ -41,8 +41,6 @@ class XRInterface;
class XRPositionalTracker;
/**
- @author Bastiaan Olij <mux213@gmail.com>
-
The XR server is a singleton object that gives access to the various
objects and SDKs that are available on the system.
Because there can be multiple SDKs active this is exposed as an array
@@ -60,9 +58,10 @@ class XRServer : public Object {
public:
enum TrackerType {
- TRACKER_CONTROLLER = 0x01, /* tracks a controller */
- TRACKER_BASESTATION = 0x02, /* tracks location of a base station */
- TRACKER_ANCHOR = 0x04, /* tracks an anchor point, used in AR to track a real live location */
+ TRACKER_HEAD = 0x01, /* tracks the position of the players head (or in case of handheld AR, location of the phone) */
+ TRACKER_CONTROLLER = 0x02, /* tracks a controller */
+ TRACKER_BASESTATION = 0x04, /* tracks location of a base station */
+ TRACKER_ANCHOR = 0x08, /* tracks an anchor point, used in AR to track a real live location */
TRACKER_UNKNOWN = 0x80, /* unknown tracker */
TRACKER_ANY_KNOWN = 0x7f, /* all except unknown */
@@ -77,7 +76,7 @@ public:
private:
Vector<Ref<XRInterface>> interfaces;
- Vector<Ref<XRPositionalTracker>> trackers;
+ Dictionary trackers;
Ref<XRInterface> primary_interface; /* we'll identify one interface as primary, this will be used by our viewports */
@@ -164,13 +163,17 @@ public:
Our trackers are objects that expose the orientation and position of physical devices such as controller, anchor points, etc.
They are created and managed by our active AR/VR interfaces.
*/
- bool is_tracker_id_in_use_for_type(TrackerType p_tracker_type, int p_tracker_id) const;
- int get_free_tracker_id_for_type(TrackerType p_tracker_type);
void add_tracker(Ref<XRPositionalTracker> p_tracker);
void remove_tracker(Ref<XRPositionalTracker> p_tracker);
- int get_tracker_count() const;
- Ref<XRPositionalTracker> get_tracker(int p_index) const;
- Ref<XRPositionalTracker> find_by_type_and_id(TrackerType p_tracker_type, int p_tracker_id) const;
+ Dictionary get_trackers(int p_tracker_types);
+ Ref<XRPositionalTracker> get_tracker(const StringName &p_name) const;
+
+ /*
+ We don't know which trackers and actions will existing during runtime but we can request suggested names from our interfaces to help our IDE UI.
+ */
+ PackedStringArray get_suggested_tracker_names() const;
+ PackedStringArray get_suggested_pose_names(const StringName &p_tracker_name) const;
+ // Q: Should we add get_suggested_input_names and get_suggested_haptic_names even though we don't use them for the IDE?
uint64_t get_last_process_usec();
uint64_t get_last_commit_usec();
@@ -188,4 +191,4 @@ public:
VARIANT_ENUM_CAST(XRServer::TrackerType);
VARIANT_ENUM_CAST(XRServer::RotationMode);
-#endif
+#endif // XR_SERVER_H