From 45c7af98625a1751f2a97aaf2a4a17d808b61092 Mon Sep 17 00:00:00 2001 From: PouleyKetchoupp Date: Tue, 17 Aug 2021 10:15:11 -0700 Subject: [PATCH 1/5] Restore RayShape as a regular shape type Partial revert from previously removing ray shapes completely, added back as a shape type but without the specific character controller code. --- doc/classes/PhysicsServer2D.xml | 21 ++-- doc/classes/PhysicsServer3D.xml | 26 ++-- doc/classes/RayShape2D.xml | 23 ++++ doc/classes/RayShape3D.xml | 23 ++++ editor/icons/RayShape2D.svg | 1 + editor/icons/RayShape3D.svg | 1 + editor/import/resource_importer_scene.cpp | 6 + .../collision_shape_2d_editor_plugin.cpp | 41 ++++++ .../collision_shape_2d_editor_plugin.h | 1 + editor/plugins/node_3d_editor_gizmos.cpp | 53 ++++++++ scene/register_scene_types.cpp | 5 + scene/resources/ray_shape_2d.cpp | 119 ++++++++++++++++++ scene/resources/ray_shape_2d.h | 61 +++++++++ scene/resources/ray_shape_3d.cpp | 91 ++++++++++++++ scene/resources/ray_shape_3d.h | 56 +++++++++ .../physics_2d/collision_solver_2d_sat.cpp | 18 +-- servers/physics_2d/collision_solver_2d_sw.cpp | 54 ++++++++ servers/physics_2d/physics_server_2d_sw.cpp | 7 ++ servers/physics_2d/physics_server_2d_sw.h | 1 + .../physics_2d/physics_server_2d_wrap_mt.h | 1 + servers/physics_2d/shape_2d_sw.cpp | 40 ++++++ servers/physics_2d/shape_2d_sw.h | 35 ++++++ .../physics_3d/collision_solver_3d_sat.cpp | 6 +- servers/physics_3d/collision_solver_3d_sw.cpp | 47 +++++++ servers/physics_3d/physics_server_3d_sw.cpp | 6 + servers/physics_3d/physics_server_3d_sw.h | 1 + .../physics_3d/physics_server_3d_wrap_mt.h | 1 + servers/physics_3d/shape_3d_sw.cpp | 85 +++++++++++++ servers/physics_3d/shape_3d_sw.h | 28 +++++ servers/physics_server_2d.cpp | 2 + servers/physics_server_2d.h | 2 + servers/physics_server_3d.cpp | 4 + servers/physics_server_3d.h | 2 + 33 files changed, 842 insertions(+), 26 deletions(-) create mode 100644 doc/classes/RayShape2D.xml create mode 100644 doc/classes/RayShape3D.xml create mode 100644 editor/icons/RayShape2D.svg create mode 100644 editor/icons/RayShape3D.svg create mode 100644 scene/resources/ray_shape_2d.cpp create mode 100644 scene/resources/ray_shape_2d.h create mode 100644 scene/resources/ray_shape_3d.cpp create mode 100644 scene/resources/ray_shape_3d.h diff --git a/doc/classes/PhysicsServer2D.xml b/doc/classes/PhysicsServer2D.xml index 1df2fd0158c..ae6b5fda51f 100644 --- a/doc/classes/PhysicsServer2D.xml +++ b/doc/classes/PhysicsServer2D.xml @@ -716,6 +716,11 @@ Sets a joint parameter. See [enum JointParam] for a list of available parameters. + + + + + @@ -840,25 +845,27 @@ This is the constant for creating world margin shapes. A world margin shape is an [i]infinite[/i] line with an origin point, and a normal. Thus, it can be used for front/behind checks. - + + + This is the constant for creating segment shapes. A segment shape is a [i]finite[/i] line from a point A to a point B. It can be checked for intersections. - + This is the constant for creating circle shapes. A circle shape only has a radius. It can be used for intersections and inside/outside checks. - + This is the constant for creating rectangle shapes. A rectangle shape is defined by a width and a height. It can be used for intersections and inside/outside checks. - + This is the constant for creating capsule shapes. A capsule shape is defined by a radius and a length. It can be used for intersections and inside/outside checks. - + This is the constant for creating convex polygon shapes. A polygon is defined by a list of points. It can be used for intersections and inside/outside checks. Unlike the [member CollisionPolygon2D.polygon] property, polygons modified with [method shape_set_data] do not verify that the points supplied form is a convex polygon. - + This is the constant for creating concave polygon shapes. A polygon is defined by a list of points. It can be used for intersections checks, but not for inside/outside checks. - + This constant is used internally by the engine. Any attempt to create this kind of shape results in an error. diff --git a/doc/classes/PhysicsServer3D.xml b/doc/classes/PhysicsServer3D.xml index 33eb0de698b..a5234e90e7a 100644 --- a/doc/classes/PhysicsServer3D.xml +++ b/doc/classes/PhysicsServer3D.xml @@ -849,6 +849,11 @@ + + + + + @@ -1171,31 +1176,34 @@ The [Shape3D] is a [WorldMarginShape3D]. - + + The [Shape3D] is a [RayShape3D]. + + The [Shape3D] is a [SphereShape3D]. - + The [Shape3D] is a [BoxShape3D]. - + The [Shape3D] is a [CapsuleShape3D]. - + The [Shape3D] is a [CylinderShape3D]. - + The [Shape3D] is a [ConvexPolygonShape3D]. - + The [Shape3D] is a [ConcavePolygonShape3D]. - + The [Shape3D] is a [HeightMapShape3D]. - + The [Shape3D] is a [SoftBody3D]. - + This constant is used internally by the engine. Any attempt to create this kind of shape results in an error. diff --git a/doc/classes/RayShape2D.xml b/doc/classes/RayShape2D.xml new file mode 100644 index 00000000000..432c6500746 --- /dev/null +++ b/doc/classes/RayShape2D.xml @@ -0,0 +1,23 @@ + + + + Ray shape for 2D collisions. + + + Ray shape for 2D collisions. A ray is not really a collision body; instead, it tries to separate itself from whatever is touching its far endpoint. It's often useful for characters. + + + + + + + + The ray's length. + + + If [code]true[/code], allow the shape to return the correct normal. + + + + + diff --git a/doc/classes/RayShape3D.xml b/doc/classes/RayShape3D.xml new file mode 100644 index 00000000000..9839044c30c --- /dev/null +++ b/doc/classes/RayShape3D.xml @@ -0,0 +1,23 @@ + + + + Ray shape for 3D collisions. + + + Ray shape for 3D collisions, which can be set into a [PhysicsBody3D] or [Area3D]. A ray is not really a collision body; instead, it tries to separate itself from whatever is touching its far endpoint. It's often useful for characters. + + + + + + + + The ray's length. + + + If [code]true[/code], allow the shape to return the correct normal. + + + + + diff --git a/editor/icons/RayShape2D.svg b/editor/icons/RayShape2D.svg new file mode 100644 index 00000000000..aa8cee1210c --- /dev/null +++ b/editor/icons/RayShape2D.svg @@ -0,0 +1 @@ + diff --git a/editor/icons/RayShape3D.svg b/editor/icons/RayShape3D.svg new file mode 100644 index 00000000000..44d32fe83bb --- /dev/null +++ b/editor/icons/RayShape3D.svg @@ -0,0 +1 @@ + diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index 2b03ad928c7..ef5e124ad98 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -45,6 +45,7 @@ #include "scene/resources/animation.h" #include "scene/resources/box_shape_3d.h" #include "scene/resources/packed_scene.h" +#include "scene/resources/ray_shape_3d.h" #include "scene/resources/resource_format_text.h" #include "scene/resources/sphere_shape_3d.h" #include "scene/resources/surface_tool.h" @@ -379,6 +380,11 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Mapset_size(Vector3(2, 2, 2)); colshape->set_shape(boxShape); + } else if (empty_draw_type == "SINGLE_ARROW") { + RayShape3D *rayShape = memnew(RayShape3D); + rayShape->set_length(1); + colshape->set_shape(rayShape); + Object::cast_to(sb)->rotate_x(Math_PI / 2); } else if (empty_draw_type == "IMAGE") { WorldMarginShape3D *world_margin_shape = memnew(WorldMarginShape3D); colshape->set_shape(world_margin_shape); diff --git a/editor/plugins/collision_shape_2d_editor_plugin.cpp b/editor/plugins/collision_shape_2d_editor_plugin.cpp index c2684305efb..bfb7a68c357 100644 --- a/editor/plugins/collision_shape_2d_editor_plugin.cpp +++ b/editor/plugins/collision_shape_2d_editor_plugin.cpp @@ -36,6 +36,7 @@ #include "scene/resources/circle_shape_2d.h" #include "scene/resources/concave_polygon_shape_2d.h" #include "scene/resources/convex_polygon_shape_2d.h" +#include "scene/resources/ray_shape_2d.h" #include "scene/resources/rectangle_shape_2d.h" #include "scene/resources/segment_shape_2d.h" #include "scene/resources/world_margin_shape_2d.h" @@ -80,6 +81,15 @@ Variant CollisionShape2DEditor::get_handle_value(int idx) const { } break; + case RAY_SHAPE: { + Ref ray = node->get_shape(); + + if (idx == 0) { + return ray->get_length(); + } + + } break; + case RECTANGLE_SHAPE: { Ref rect = node->get_shape(); @@ -152,6 +162,15 @@ void CollisionShape2DEditor::set_handle(int idx, Point2 &p_point) { } break; + case RAY_SHAPE: { + Ref ray = node->get_shape(); + + ray->set_length(Math::abs(p_point.y)); + + canvas_item_editor->update_viewport(); + + } break; + case RECTANGLE_SHAPE: { if (idx < 8) { Ref rect = node->get_shape(); @@ -253,6 +272,16 @@ void CollisionShape2DEditor::commit_handle(int idx, Variant &p_org) { } break; + case RAY_SHAPE: { + Ref ray = node->get_shape(); + + undo_redo->add_do_method(ray.ptr(), "set_length", ray->get_length()); + undo_redo->add_do_method(canvas_item_editor, "update_viewport"); + undo_redo->add_undo_method(ray.ptr(), "set_length", p_org); + undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); + + } break; + case RECTANGLE_SHAPE: { Ref rect = node->get_shape(); @@ -394,6 +423,8 @@ void CollisionShape2DEditor::_get_current_shape_type() { shape_type = CONVEX_POLYGON_SHAPE; } else if (Object::cast_to(*s)) { shape_type = WORLD_MARGIN_SHAPE; + } else if (Object::cast_to(*s)) { + shape_type = RAY_SHAPE; } else if (Object::cast_to(*s)) { shape_type = RECTANGLE_SHAPE; } else if (Object::cast_to(*s)) { @@ -471,6 +502,16 @@ void CollisionShape2DEditor::forward_canvas_draw_over_viewport(Control *p_overla } break; + case RAY_SHAPE: { + Ref shape = node->get_shape(); + + handles.resize(1); + handles.write[0] = Point2(0, shape->get_length()); + + p_overlay->draw_texture(h, gt.xform(handles[0]) - size); + + } break; + case RECTANGLE_SHAPE: { Ref shape = node->get_shape(); diff --git a/editor/plugins/collision_shape_2d_editor_plugin.h b/editor/plugins/collision_shape_2d_editor_plugin.h index 056e1b5b7d6..eab80a419ba 100644 --- a/editor/plugins/collision_shape_2d_editor_plugin.h +++ b/editor/plugins/collision_shape_2d_editor_plugin.h @@ -47,6 +47,7 @@ class CollisionShape2DEditor : public Control { CONCAVE_POLYGON_SHAPE, CONVEX_POLYGON_SHAPE, WORLD_MARGIN_SHAPE, + RAY_SHAPE, RECTANGLE_SHAPE, SEGMENT_SHAPE }; diff --git a/editor/plugins/node_3d_editor_gizmos.cpp b/editor/plugins/node_3d_editor_gizmos.cpp index 5d1b4d8ead0..a23886b9e78 100644 --- a/editor/plugins/node_3d_editor_gizmos.cpp +++ b/editor/plugins/node_3d_editor_gizmos.cpp @@ -66,6 +66,7 @@ #include "scene/resources/cylinder_shape_3d.h" #include "scene/resources/height_map_shape_3d.h" #include "scene/resources/primitive_meshes.h" +#include "scene/resources/ray_shape_3d.h" #include "scene/resources/sphere_shape_3d.h" #include "scene/resources/surface_tool.h" #include "scene/resources/world_margin_shape_3d.h" @@ -4067,6 +4068,10 @@ String CollisionShape3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_g return p_id == 0 ? "Radius" : "Height"; } + if (Object::cast_to(*s)) { + return "Length"; + } + return ""; } @@ -4098,6 +4103,11 @@ Variant CollisionShape3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p return p_id == 0 ? cs2->get_radius() : cs2->get_height(); } + if (Object::cast_to(*s)) { + Ref cs2 = s; + return cs2->get_length(); + } + return Variant(); } @@ -4133,6 +4143,22 @@ void CollisionShape3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, i ss->set_radius(d); } + if (Object::cast_to(*s)) { + Ref rs = s; + Vector3 ra, rb; + Geometry3D::get_closest_points_between_segments(Vector3(), Vector3(0, 0, 4096), sg[0], sg[1], ra, rb); + float d = ra.z; + if (Node3DEditor::get_singleton()->is_snap_enabled()) { + d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap()); + } + + if (d < 0.001) { + d = 0.001; + } + + rs->set_length(d); + } + if (Object::cast_to(*s)) { Vector3 axis; axis[p_id] = 1.0; @@ -4287,6 +4313,20 @@ void CollisionShape3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo ur->commit_action(); } + + if (Object::cast_to(*s)) { + Ref ss = s; + if (p_cancel) { + ss->set_length(p_restore); + return; + } + + UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo(); + ur->create_action(TTR("Change Ray Shape Length")); + ur->add_do_method(ss.ptr(), "set_length", ss->get_length()); + ur->add_undo_method(ss.ptr(), "set_length", p_restore); + ur->commit_action(); + } } void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { @@ -4557,6 +4597,19 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { p_gizmo->add_collision_segments(cs2->get_debug_mesh_lines()); } + if (Object::cast_to(*s)) { + Ref rs = s; + + Vector points; + points.push_back(Vector3()); + points.push_back(Vector3(0, 0, rs->get_length())); + p_gizmo->add_lines(points, material); + p_gizmo->add_collision_segments(points); + Vector handles; + handles.push_back(Vector3(0, 0, rs->get_length())); + p_gizmo->add_handles(handles, handles_material); + } + if (Object::cast_to(*s)) { Ref hms = s; diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 2cea3c23370..f0b799e4d2d 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -157,6 +157,8 @@ #include "scene/resources/physics_material.h" #include "scene/resources/polygon_path_finder.h" #include "scene/resources/primitive_meshes.h" +#include "scene/resources/ray_shape_2d.h" +#include "scene/resources/ray_shape_3d.h" #include "scene/resources/rectangle_shape_2d.h" #include "scene/resources/resource_format_text.h" #include "scene/resources/segment_shape_2d.h" @@ -752,6 +754,7 @@ void register_scene_types() { OS::get_singleton()->yield(); //may take time to init GDREGISTER_VIRTUAL_CLASS(Shape3D); + GDREGISTER_CLASS(RayShape3D); GDREGISTER_CLASS(SphereShape3D); GDREGISTER_CLASS(BoxShape3D); GDREGISTER_CLASS(CapsuleShape3D); @@ -840,6 +843,7 @@ void register_scene_types() { GDREGISTER_VIRTUAL_CLASS(Shape2D); GDREGISTER_CLASS(WorldMarginShape2D); GDREGISTER_CLASS(SegmentShape2D); + GDREGISTER_CLASS(RayShape2D); GDREGISTER_CLASS(CircleShape2D); GDREGISTER_CLASS(RectangleShape2D); GDREGISTER_CLASS(CapsuleShape2D); @@ -960,6 +964,7 @@ void register_scene_types() { ClassDB::add_compatibility_class("ProceduralSky", "Sky"); ClassDB::add_compatibility_class("ProximityGroup", "ProximityGroup3D"); ClassDB::add_compatibility_class("RayCast", "RayCast3D"); + ClassDB::add_compatibility_class("RayShape", "RayShape3D"); ClassDB::add_compatibility_class("RemoteTransform", "RemoteTransform3D"); ClassDB::add_compatibility_class("RigidBody", "RigidBody3D"); ClassDB::add_compatibility_class("Shape", "Shape3D"); diff --git a/scene/resources/ray_shape_2d.cpp b/scene/resources/ray_shape_2d.cpp new file mode 100644 index 00000000000..fb8f4b99850 --- /dev/null +++ b/scene/resources/ray_shape_2d.cpp @@ -0,0 +1,119 @@ +/*************************************************************************/ +/* ray_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). */ +/* */ +/* 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 "ray_shape_2d.h" + +#include "servers/physics_server_2d.h" +#include "servers/rendering_server.h" + +void RayShape2D::_update_shape() { + Dictionary d; + d["length"] = length; + d["slips_on_slope"] = slips_on_slope; + PhysicsServer2D::get_singleton()->shape_set_data(get_rid(), d); + emit_changed(); +} + +void RayShape2D::draw(const RID &p_to_rid, const Color &p_color) { + const Vector2 target_position = Vector2(0, get_length()); + + const float max_arrow_size = 6; + const float line_width = 1.4; + bool no_line = target_position.length() < line_width; + float arrow_size = CLAMP(target_position.length() * 2 / 3, line_width, max_arrow_size); + + if (no_line) { + arrow_size = target_position.length(); + } else { + RS::get_singleton()->canvas_item_add_line(p_to_rid, Vector2(), target_position - target_position.normalized() * arrow_size, p_color, line_width); + } + + Transform2D xf; + xf.rotate(target_position.angle()); + xf.translate(Vector2(no_line ? 0 : target_position.length() - arrow_size, 0)); + + Vector pts; + pts.push_back(xf.xform(Vector2(arrow_size, 0))); + pts.push_back(xf.xform(Vector2(0, 0.5 * arrow_size))); + pts.push_back(xf.xform(Vector2(0, -0.5 * arrow_size))); + + Vector cols; + for (int i = 0; i < 3; i++) { + cols.push_back(p_color); + } + + RS::get_singleton()->canvas_item_add_primitive(p_to_rid, pts, cols, Vector(), RID()); +} + +Rect2 RayShape2D::get_rect() const { + Rect2 rect; + rect.position = Vector2(); + rect.expand_to(Vector2(0, length)); + rect = rect.grow(Math_SQRT12 * 4); + return rect; +} + +real_t RayShape2D::get_enclosing_radius() const { + return length; +} + +void RayShape2D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_length", "length"), &RayShape2D::set_length); + ClassDB::bind_method(D_METHOD("get_length"), &RayShape2D::get_length); + + ClassDB::bind_method(D_METHOD("set_slips_on_slope", "active"), &RayShape2D::set_slips_on_slope); + ClassDB::bind_method(D_METHOD("get_slips_on_slope"), &RayShape2D::get_slips_on_slope); + + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "length"), "set_length", "get_length"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "slips_on_slope"), "set_slips_on_slope", "get_slips_on_slope"); +} + +void RayShape2D::set_length(real_t p_length) { + length = p_length; + _update_shape(); +} + +real_t RayShape2D::get_length() const { + return length; +} + +void RayShape2D::set_slips_on_slope(bool p_active) { + slips_on_slope = p_active; + _update_shape(); +} + +bool RayShape2D::get_slips_on_slope() const { + return slips_on_slope; +} + +RayShape2D::RayShape2D() : + Shape2D(PhysicsServer2D::get_singleton()->ray_shape_create()) { + _update_shape(); +} diff --git a/scene/resources/ray_shape_2d.h b/scene/resources/ray_shape_2d.h new file mode 100644 index 00000000000..56ecfa2722f --- /dev/null +++ b/scene/resources/ray_shape_2d.h @@ -0,0 +1,61 @@ +/*************************************************************************/ +/* ray_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). */ +/* */ +/* 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 RAY_SHAPE_2D_H +#define RAY_SHAPE_2D_H + +#include "scene/resources/shape_2d.h" + +class RayShape2D : public Shape2D { + GDCLASS(RayShape2D, Shape2D); + + real_t length = 20.0; + bool slips_on_slope = false; + + void _update_shape(); + +protected: + static void _bind_methods(); + +public: + void set_length(real_t p_length); + real_t get_length() const; + + void set_slips_on_slope(bool p_active); + bool get_slips_on_slope() const; + + virtual void draw(const RID &p_to_rid, const Color &p_color) override; + virtual Rect2 get_rect() const override; + virtual real_t get_enclosing_radius() const override; + + RayShape2D(); +}; + +#endif // RAY_SHAPE_2D_H diff --git a/scene/resources/ray_shape_3d.cpp b/scene/resources/ray_shape_3d.cpp new file mode 100644 index 00000000000..5446b4daab3 --- /dev/null +++ b/scene/resources/ray_shape_3d.cpp @@ -0,0 +1,91 @@ +/*************************************************************************/ +/* ray_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). */ +/* */ +/* 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 "ray_shape_3d.h" + +#include "servers/physics_server_3d.h" + +Vector RayShape3D::get_debug_mesh_lines() const { + Vector points; + points.push_back(Vector3()); + points.push_back(Vector3(0, 0, get_length())); + + return points; +} + +real_t RayShape3D::get_enclosing_radius() const { + return length; +} + +void RayShape3D::_update_shape() { + Dictionary d; + d["length"] = length; + d["slips_on_slope"] = slips_on_slope; + PhysicsServer3D::get_singleton()->shape_set_data(get_shape(), d); + Shape3D::_update_shape(); +} + +void RayShape3D::set_length(float p_length) { + length = p_length; + _update_shape(); + notify_change_to_owners(); +} + +float RayShape3D::get_length() const { + return length; +} + +void RayShape3D::set_slips_on_slope(bool p_active) { + slips_on_slope = p_active; + _update_shape(); + notify_change_to_owners(); +} + +bool RayShape3D::get_slips_on_slope() const { + return slips_on_slope; +} + +void RayShape3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_length", "length"), &RayShape3D::set_length); + ClassDB::bind_method(D_METHOD("get_length"), &RayShape3D::get_length); + + ClassDB::bind_method(D_METHOD("set_slips_on_slope", "active"), &RayShape3D::set_slips_on_slope); + ClassDB::bind_method(D_METHOD("get_slips_on_slope"), &RayShape3D::get_slips_on_slope); + + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "length", PROPERTY_HINT_RANGE, "0,4096,0.001"), "set_length", "get_length"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "slips_on_slope"), "set_slips_on_slope", "get_slips_on_slope"); +} + +RayShape3D::RayShape3D() : + Shape3D(PhysicsServer3D::get_singleton()->shape_create(PhysicsServer3D::SHAPE_RAY)) { + /* Code copied from setters to prevent the use of uninitialized variables */ + _update_shape(); + notify_change_to_owners(); +} diff --git a/scene/resources/ray_shape_3d.h b/scene/resources/ray_shape_3d.h new file mode 100644 index 00000000000..2da63113210 --- /dev/null +++ b/scene/resources/ray_shape_3d.h @@ -0,0 +1,56 @@ +/*************************************************************************/ +/* ray_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). */ +/* */ +/* 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 RAY_SHAPE_H +#define RAY_SHAPE_H +#include "scene/resources/shape_3d.h" + +class RayShape3D : public Shape3D { + GDCLASS(RayShape3D, Shape3D); + float length = 1.0; + bool slips_on_slope = false; + +protected: + static void _bind_methods(); + virtual void _update_shape() override; + +public: + void set_length(float p_length); + float get_length() const; + + void set_slips_on_slope(bool p_active); + bool get_slips_on_slope() const; + + virtual Vector get_debug_mesh_lines() const override; + virtual real_t get_enclosing_radius() const override; + + RayShape3D(); +}; +#endif // RAY_SHAPE_H diff --git a/servers/physics_2d/collision_solver_2d_sat.cpp b/servers/physics_2d/collision_solver_2d_sat.cpp index 30a99d3d741..3dde881c4d0 100644 --- a/servers/physics_2d/collision_solver_2d_sat.cpp +++ b/servers/physics_2d/collision_solver_2d_sat.cpp @@ -1115,11 +1115,13 @@ bool sat_2d_calculate_penetration(const Shape2DSW *p_shape_A, const Transform2D PhysicsServer2D::ShapeType type_A = p_shape_A->get_type(); ERR_FAIL_COND_V(type_A == PhysicsServer2D::SHAPE_WORLD_MARGIN, false); + ERR_FAIL_COND_V(type_A == PhysicsServer2D::SHAPE_RAY, false); ERR_FAIL_COND_V(p_shape_A->is_concave(), false); PhysicsServer2D::ShapeType type_B = p_shape_B->get_type(); ERR_FAIL_COND_V(type_B == PhysicsServer2D::SHAPE_WORLD_MARGIN, false); + ERR_FAIL_COND_V(type_B == PhysicsServer2D::SHAPE_RAY, false); ERR_FAIL_COND_V(p_shape_B->is_concave(), false); static const CollisionFunc collision_table[5][5] = { @@ -1382,23 +1384,23 @@ bool sat_2d_calculate_penetration(const Shape2DSW *p_shape_A, const Transform2D if (p_margin_A || p_margin_B) { if (*motion_A == Vector2() && *motion_B == Vector2()) { - collision_func = collision_table_margin[type_A - 1][type_B - 1]; + collision_func = collision_table_margin[type_A - 2][type_B - 2]; } else if (*motion_A != Vector2() && *motion_B == Vector2()) { - collision_func = collision_table_castA_margin[type_A - 1][type_B - 1]; + collision_func = collision_table_castA_margin[type_A - 2][type_B - 2]; } else if (*motion_A == Vector2() && *motion_B != Vector2()) { - collision_func = collision_table_castB_margin[type_A - 1][type_B - 1]; + collision_func = collision_table_castB_margin[type_A - 2][type_B - 2]; } else { - collision_func = collision_table_castA_castB_margin[type_A - 1][type_B - 1]; + collision_func = collision_table_castA_castB_margin[type_A - 2][type_B - 2]; } } else { if (*motion_A == Vector2() && *motion_B == Vector2()) { - collision_func = collision_table[type_A - 1][type_B - 1]; + collision_func = collision_table[type_A - 2][type_B - 2]; } else if (*motion_A != Vector2() && *motion_B == Vector2()) { - collision_func = collision_table_castA[type_A - 1][type_B - 1]; + collision_func = collision_table_castA[type_A - 2][type_B - 2]; } else if (*motion_A == Vector2() && *motion_B != Vector2()) { - collision_func = collision_table_castB[type_A - 1][type_B - 1]; + collision_func = collision_table_castB[type_A - 2][type_B - 2]; } else { - collision_func = collision_table_castA_castB[type_A - 1][type_B - 1]; + collision_func = collision_table_castA_castB[type_A - 2][type_B - 2]; } } diff --git a/servers/physics_2d/collision_solver_2d_sw.cpp b/servers/physics_2d/collision_solver_2d_sw.cpp index 8f8a4a862cc..1946dae2e3d 100644 --- a/servers/physics_2d/collision_solver_2d_sw.cpp +++ b/servers/physics_2d/collision_solver_2d_sw.cpp @@ -73,6 +73,49 @@ bool CollisionSolver2DSW::solve_static_world_margin(const Shape2DSW *p_shape_A, return found; } +bool CollisionSolver2DSW::solve_raycast(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 *sep_axis) { + const RayShape2DSW *ray = static_cast(p_shape_A); + if (p_shape_B->get_type() == PhysicsServer2D::SHAPE_RAY) { + return false; + } + + Vector2 from = p_transform_A.get_origin(); + Vector2 to = from + p_transform_A[1] * ray->get_length(); + if (p_motion_A != Vector2()) { + //not the best but should be enough + Vector2 normal = (to - from).normalized(); + to += normal * MAX(0.0, normal.dot(p_motion_A)); + } + Vector2 support_A = to; + + Transform2D invb = p_transform_B.affine_inverse(); + from = invb.xform(from); + to = invb.xform(to); + + Vector2 p, n; + if (!p_shape_B->intersect_segment(from, to, p, n)) { + if (sep_axis) { + *sep_axis = p_transform_A[1].normalized(); + } + return false; + } + + Vector2 support_B = p_transform_B.xform(p); + if (ray->get_slips_on_slope()) { + Vector2 global_n = invb.basis_xform_inv(n).normalized(); + support_B = support_A + (support_B - support_A).length() * global_n; + } + + if (p_result_callback) { + if (p_swap_result) { + p_result_callback(support_B, support_A, p_userdata); + } else { + p_result_callback(support_A, support_B, p_userdata); + } + } + return true; +} + struct _ConcaveCollisionInfo2D { const Transform2D *transform_A; const Shape2DSW *shape_A; @@ -177,6 +220,17 @@ bool CollisionSolver2DSW::solve(const Shape2DSW *p_shape_A, const Transform2D &p return solve_static_world_margin(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false); } + } else if (type_A == PhysicsServer2D::SHAPE_RAY) { + if (type_B == PhysicsServer2D::SHAPE_RAY) { + return false; //no ray-ray + } + + if (swap) { + return solve_raycast(p_shape_B, p_motion_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true, sep_axis); + } else { + return solve_raycast(p_shape_A, p_motion_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false, sep_axis); + } + } else if (concave_B) { if (concave_A) { return false; diff --git a/servers/physics_2d/physics_server_2d_sw.cpp b/servers/physics_2d/physics_server_2d_sw.cpp index 88c097453e6..0954f3a1748 100644 --- a/servers/physics_2d/physics_server_2d_sw.cpp +++ b/servers/physics_2d/physics_server_2d_sw.cpp @@ -45,6 +45,9 @@ RID PhysicsServer2DSW::_shape_create(ShapeType p_shape) { case SHAPE_WORLD_MARGIN: { shape = memnew(WorldMarginShape2DSW); } break; + case SHAPE_RAY: { + shape = memnew(RayShape2DSW); + } break; case SHAPE_SEGMENT: { shape = memnew(SegmentShape2DSW); } break; @@ -79,6 +82,10 @@ RID PhysicsServer2DSW::world_margin_shape_create() { return _shape_create(SHAPE_WORLD_MARGIN); } +RID PhysicsServer2DSW::ray_shape_create() { + return _shape_create(SHAPE_RAY); +} + RID PhysicsServer2DSW::segment_shape_create() { return _shape_create(SHAPE_SEGMENT); } diff --git a/servers/physics_2d/physics_server_2d_sw.h b/servers/physics_2d/physics_server_2d_sw.h index 3610f43f93c..1926eaac846 100644 --- a/servers/physics_2d/physics_server_2d_sw.h +++ b/servers/physics_2d/physics_server_2d_sw.h @@ -88,6 +88,7 @@ public: }; virtual RID world_margin_shape_create() override; + virtual RID ray_shape_create() override; virtual RID segment_shape_create() override; virtual RID circle_shape_create() override; virtual RID rectangle_shape_create() override; diff --git a/servers/physics_2d/physics_server_2d_wrap_mt.h b/servers/physics_2d/physics_server_2d_wrap_mt.h index b93178919da..0ebccc2614e 100644 --- a/servers/physics_2d/physics_server_2d_wrap_mt.h +++ b/servers/physics_2d/physics_server_2d_wrap_mt.h @@ -80,6 +80,7 @@ public: //FUNC1RID(shape,ShapeType); todo fix FUNCRID(world_margin_shape) + FUNCRID(ray_shape) FUNCRID(segment_shape) FUNCRID(circle_shape) FUNCRID(rectangle_shape) diff --git a/servers/physics_2d/shape_2d_sw.cpp b/servers/physics_2d/shape_2d_sw.cpp index b3e4ca84c3b..be2f83b705a 100644 --- a/servers/physics_2d/shape_2d_sw.cpp +++ b/servers/physics_2d/shape_2d_sw.cpp @@ -143,6 +143,46 @@ Variant WorldMarginShape2DSW::get_data() const { /*********************************************************/ /*********************************************************/ +void RayShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const { + r_amount = 1; + + if (p_normal.y > 0) { + *r_supports = Vector2(0, length); + } else { + *r_supports = Vector2(); + } +} + +bool RayShape2DSW::contains_point(const Vector2 &p_point) const { + return false; +} + +bool RayShape2DSW::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 RayShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const { + return 0; //rays are mass-less +} + +void RayShape2DSW::set_data(const Variant &p_data) { + Dictionary d = p_data; + length = d["length"]; + slips_on_slope = d["slips_on_slope"]; + configure(Rect2(0, 0, 0.001, length)); +} + +Variant RayShape2DSW::get_data() const { + Dictionary d; + d["length"] = length; + d["slips_on_slope"] = slips_on_slope; + return d; +} + +/*********************************************************/ +/*********************************************************/ +/*********************************************************/ + void SegmentShape2DSW::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; diff --git a/servers/physics_2d/shape_2d_sw.h b/servers/physics_2d/shape_2d_sw.h index 45d3379dfa7..d1640b39cf0 100644 --- a/servers/physics_2d/shape_2d_sw.h +++ b/servers/physics_2d/shape_2d_sw.h @@ -177,6 +177,41 @@ public: } }; +class RayShape2DSW : public Shape2DSW { + real_t length; + bool slips_on_slope; + +public: + _FORCE_INLINE_ real_t get_length() const { return length; } + _FORCE_INLINE_ bool get_slips_on_slope() const { return slips_on_slope; } + + virtual PhysicsServer2D::ShapeType get_type() const { return PhysicsServer2D::SHAPE_RAY; } + + virtual void project_rangev(const Vector2 &p_normal, const Transform2D &p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal, p_transform, r_min, r_max); } + virtual void get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const; + + virtual bool contains_point(const Vector2 &p_point) const; + virtual bool intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const; + virtual real_t get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const; + + virtual void set_data(const Variant &p_data); + virtual Variant get_data() const; + + _FORCE_INLINE_ void project_range(const Vector2 &p_normal, const Transform2D &p_transform, real_t &r_min, real_t &r_max) const { + //real large + r_max = p_normal.dot(p_transform.get_origin()); + r_min = p_normal.dot(p_transform.xform(Vector2(0, length))); + if (r_max < r_min) { + SWAP(r_max, r_min); + } + } + + DEFAULT_PROJECT_RANGE_CAST + + _FORCE_INLINE_ RayShape2DSW() {} + _FORCE_INLINE_ RayShape2DSW(real_t p_length) { length = p_length; } +}; + class SegmentShape2DSW : public Shape2DSW { Vector2 a; Vector2 b; diff --git a/servers/physics_3d/collision_solver_3d_sat.cpp b/servers/physics_3d/collision_solver_3d_sat.cpp index 6e6a2cb9e78..547f5f3e47e 100644 --- a/servers/physics_3d/collision_solver_3d_sat.cpp +++ b/servers/physics_3d/collision_solver_3d_sat.cpp @@ -2273,11 +2273,13 @@ bool sat_calculate_penetration(const Shape3DSW *p_shape_A, const Transform3D &p_ PhysicsServer3D::ShapeType type_A = p_shape_A->get_type(); ERR_FAIL_COND_V(type_A == PhysicsServer3D::SHAPE_PLANE, false); + ERR_FAIL_COND_V(type_A == PhysicsServer3D::SHAPE_RAY, false); ERR_FAIL_COND_V(p_shape_A->is_concave(), false); PhysicsServer3D::ShapeType type_B = p_shape_B->get_type(); ERR_FAIL_COND_V(type_B == PhysicsServer3D::SHAPE_PLANE, false); + ERR_FAIL_COND_V(type_B == PhysicsServer3D::SHAPE_RAY, false); ERR_FAIL_COND_V(p_shape_B->is_concave(), false); static const CollisionFunc collision_table[6][6] = { @@ -2382,10 +2384,10 @@ bool sat_calculate_penetration(const Shape3DSW *p_shape_A, const Transform3D &p_ CollisionFunc collision_func; if (margin_A != 0.0 || margin_B != 0.0) { - collision_func = collision_table_margin[type_A - 1][type_B - 1]; + collision_func = collision_table_margin[type_A - 2][type_B - 2]; } else { - collision_func = collision_table[type_A - 1][type_B - 1]; + collision_func = collision_table[type_A - 2][type_B - 2]; } ERR_FAIL_COND_V(!collision_func, false); diff --git a/servers/physics_3d/collision_solver_3d_sw.cpp b/servers/physics_3d/collision_solver_3d_sw.cpp index dcecac1c738..c61b9cbd4eb 100644 --- a/servers/physics_3d/collision_solver_3d_sw.cpp +++ b/servers/physics_3d/collision_solver_3d_sw.cpp @@ -89,6 +89,39 @@ bool CollisionSolver3DSW::solve_static_plane(const Shape3DSW *p_shape_A, const T return found; } +bool CollisionSolver3DSW::solve_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) { + const RayShape3DSW *ray = static_cast(p_shape_A); + + Vector3 from = p_transform_A.origin; + Vector3 to = from + p_transform_A.basis.get_axis(2) * ray->get_length(); + Vector3 support_A = to; + + Transform3D ai = p_transform_B.affine_inverse(); + + from = ai.xform(from); + to = ai.xform(to); + + Vector3 p, n; + if (!p_shape_B->intersect_segment(from, to, p, n)) { + return false; + } + + Vector3 support_B = p_transform_B.xform(p); + if (ray->get_slips_on_slope()) { + Vector3 global_n = ai.basis.xform_inv(n).normalized(); + support_B = support_A + (support_B - support_A).length() * global_n; + } + + if (p_result_callback) { + if (p_swap_result) { + p_result_callback(support_B, 0, support_A, 0, p_userdata); + } else { + p_result_callback(support_A, 0, support_B, 0, p_userdata); + } + } + return true; +} + struct _SoftBodyContactCollisionInfo { int node_index = 0; CollisionSolver3DSW::CallbackResult result_callback = nullptr; @@ -318,6 +351,9 @@ bool CollisionSolver3DSW::solve_static(const Shape3DSW *p_shape_A, const Transfo if (type_B == PhysicsServer3D::SHAPE_PLANE) { return false; } + if (type_B == PhysicsServer3D::SHAPE_RAY) { + return false; + } if (type_B == PhysicsServer3D::SHAPE_SOFT_BODY) { return false; } @@ -328,6 +364,17 @@ bool CollisionSolver3DSW::solve_static(const Shape3DSW *p_shape_A, const Transfo return solve_static_plane(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false); } + } else if (type_A == PhysicsServer3D::SHAPE_RAY) { + if (type_B == PhysicsServer3D::SHAPE_RAY) { + return false; + } + + if (swap) { + return solve_ray(p_shape_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true); + } else { + return solve_ray(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false); + } + } else if (type_B == PhysicsServer3D::SHAPE_SOFT_BODY) { if (type_A == PhysicsServer3D::SHAPE_SOFT_BODY) { // Soft Body / Soft Body not supported. diff --git a/servers/physics_3d/physics_server_3d_sw.cpp b/servers/physics_3d/physics_server_3d_sw.cpp index fbb374bd74f..a1d776922e5 100644 --- a/servers/physics_3d/physics_server_3d_sw.cpp +++ b/servers/physics_3d/physics_server_3d_sw.cpp @@ -48,6 +48,12 @@ RID PhysicsServer3DSW::plane_shape_create() { shape->set_self(rid); return rid; } +RID PhysicsServer3DSW::ray_shape_create() { + Shape3DSW *shape = memnew(RayShape3DSW); + 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); diff --git a/servers/physics_3d/physics_server_3d_sw.h b/servers/physics_3d/physics_server_3d_sw.h index 6e59a77e891..f2322a0e763 100644 --- a/servers/physics_3d/physics_server_3d_sw.h +++ b/servers/physics_3d/physics_server_3d_sw.h @@ -83,6 +83,7 @@ public: static void _shape_col_cbk(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata); virtual RID plane_shape_create() override; + virtual RID ray_shape_create() override; virtual RID sphere_shape_create() override; virtual RID box_shape_create() override; virtual RID capsule_shape_create() override; diff --git a/servers/physics_3d/physics_server_3d_wrap_mt.h b/servers/physics_3d/physics_server_3d_wrap_mt.h index 75174628bf2..d807e737314 100644 --- a/servers/physics_3d/physics_server_3d_wrap_mt.h +++ b/servers/physics_3d/physics_server_3d_wrap_mt.h @@ -79,6 +79,7 @@ public: //FUNC1RID(shape,ShapeType); todo fix FUNCRID(plane_shape) + FUNCRID(ray_shape) FUNCRID(sphere_shape) FUNCRID(box_shape) FUNCRID(capsule_shape) diff --git a/servers/physics_3d/shape_3d_sw.cpp b/servers/physics_3d/shape_3d_sw.cpp index 664308ed7bf..42a0fb32b29 100644 --- a/servers/physics_3d/shape_3d_sw.cpp +++ b/servers/physics_3d/shape_3d_sw.cpp @@ -164,6 +164,91 @@ Variant PlaneShape3DSW::get_data() const { PlaneShape3DSW::PlaneShape3DSW() { } +// + +real_t RayShape3DSW::get_length() const { + return length; +} + +bool RayShape3DSW::get_slips_on_slope() const { + return slips_on_slope; +} + +void RayShape3DSW::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 RayShape3DSW::get_support(const Vector3 &p_normal) const { + if (p_normal.z > 0) { + return Vector3(0, 0, length); + } else { + return Vector3(0, 0, 0); + } +} + +void RayShape3DSW::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; + r_supports[0] = Vector3(0, 0, 0); + r_supports[1] = Vector3(0, 0, length); + } else if (p_normal.z > 0) { + r_amount = 1; + r_type = FEATURE_POINT; + *r_supports = Vector3(0, 0, length); + } else { + r_amount = 1; + r_type = FEATURE_POINT; + *r_supports = Vector3(0, 0, 0); + } +} + +bool RayShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { + return false; //simply not possible +} + +bool RayShape3DSW::intersect_point(const Vector3 &p_point) const { + return false; //simply not possible +} + +Vector3 RayShape3DSW::get_closest_point_to(const Vector3 &p_point) const { + Vector3 s[2] = { + Vector3(0, 0, 0), + Vector3(0, 0, length) + }; + + return Geometry3D::get_closest_point_to_segment(p_point, s); +} + +Vector3 RayShape3DSW::get_moment_of_inertia(real_t p_mass) const { + return Vector3(); +} + +void RayShape3DSW::_setup(real_t p_length, bool p_slips_on_slope) { + length = p_length; + slips_on_slope = p_slips_on_slope; + configure(AABB(Vector3(0, 0, 0), Vector3(0.1, 0.1, length))); +} + +void RayShape3DSW::set_data(const Variant &p_data) { + Dictionary d = p_data; + _setup(d["length"], d["slips_on_slope"]); +} + +Variant RayShape3DSW::get_data() const { + Dictionary d; + d["length"] = length; + d["slips_on_slope"] = slips_on_slope; + return d; +} + +RayShape3DSW::RayShape3DSW() { + length = 1; + slips_on_slope = false; +} + /********** SPHERE *************/ real_t SphereShape3DSW::get_radius() const { diff --git a/servers/physics_3d/shape_3d_sw.h b/servers/physics_3d/shape_3d_sw.h index ca589001115..9f18b83f077 100644 --- a/servers/physics_3d/shape_3d_sw.h +++ b/servers/physics_3d/shape_3d_sw.h @@ -134,6 +134,34 @@ public: PlaneShape3DSW(); }; +class RayShape3DSW : public Shape3DSW { + real_t length; + bool slips_on_slope; + + void _setup(real_t p_length, bool p_slips_on_slope); + +public: + real_t get_length() const; + bool get_slips_on_slope() const; + + virtual real_t get_area() const { return 0.0; } + virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_RAY; } + virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const; + 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; + + 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; + + virtual void set_data(const Variant &p_data); + virtual Variant get_data() const; + + RayShape3DSW(); +}; + class SphereShape3DSW : public Shape3DSW { real_t radius; diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp index c96f85446c6..42b3daab285 100644 --- a/servers/physics_server_2d.cpp +++ b/servers/physics_server_2d.cpp @@ -514,6 +514,7 @@ bool PhysicsServer2D::_body_test_motion(RID p_body, const Transform2D &p_from, c void PhysicsServer2D::_bind_methods() { ClassDB::bind_method(D_METHOD("world_margin_shape_create"), &PhysicsServer2D::world_margin_shape_create); + ClassDB::bind_method(D_METHOD("ray_shape_create"), &PhysicsServer2D::ray_shape_create); ClassDB::bind_method(D_METHOD("segment_shape_create"), &PhysicsServer2D::segment_shape_create); ClassDB::bind_method(D_METHOD("circle_shape_create"), &PhysicsServer2D::circle_shape_create); ClassDB::bind_method(D_METHOD("rectangle_shape_create"), &PhysicsServer2D::rectangle_shape_create); @@ -675,6 +676,7 @@ void PhysicsServer2D::_bind_methods() { BIND_ENUM_CONSTANT(SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH); BIND_ENUM_CONSTANT(SHAPE_WORLD_MARGIN); + BIND_ENUM_CONSTANT(SHAPE_RAY); BIND_ENUM_CONSTANT(SHAPE_SEGMENT); BIND_ENUM_CONSTANT(SHAPE_CIRCLE); BIND_ENUM_CONSTANT(SHAPE_RECTANGLE); diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h index 4c559dd7bdf..b6fb17b1c95 100644 --- a/servers/physics_server_2d.h +++ b/servers/physics_server_2d.h @@ -220,6 +220,7 @@ public: enum ShapeType { SHAPE_WORLD_MARGIN, ///< plane:"plane" + SHAPE_RAY, ///< float:"length" SHAPE_SEGMENT, ///< float:"length" SHAPE_CIRCLE, ///< float:"radius" SHAPE_RECTANGLE, ///< vec3:"extents" @@ -230,6 +231,7 @@ public: }; virtual RID world_margin_shape_create() = 0; + virtual RID ray_shape_create() = 0; virtual RID segment_shape_create() = 0; virtual RID circle_shape_create() = 0; virtual RID rectangle_shape_create() = 0; diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp index 1f46a96b278..582acaefe8f 100644 --- a/servers/physics_server_3d.cpp +++ b/servers/physics_server_3d.cpp @@ -463,6 +463,8 @@ RID PhysicsServer3D::shape_create(ShapeType p_shape) { switch (p_shape) { case SHAPE_PLANE: return plane_shape_create(); + case SHAPE_RAY: + return ray_shape_create(); case SHAPE_SPHERE: return sphere_shape_create(); case SHAPE_BOX: @@ -488,6 +490,7 @@ void PhysicsServer3D::_bind_methods() { #ifndef _3D_DISABLED ClassDB::bind_method(D_METHOD("plane_shape_create"), &PhysicsServer3D::plane_shape_create); + ClassDB::bind_method(D_METHOD("ray_shape_create"), &PhysicsServer3D::ray_shape_create); ClassDB::bind_method(D_METHOD("sphere_shape_create"), &PhysicsServer3D::sphere_shape_create); ClassDB::bind_method(D_METHOD("box_shape_create"), &PhysicsServer3D::box_shape_create); ClassDB::bind_method(D_METHOD("capsule_shape_create"), &PhysicsServer3D::capsule_shape_create); @@ -748,6 +751,7 @@ void PhysicsServer3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_process_info", "process_info"), &PhysicsServer3D::get_process_info); BIND_ENUM_CONSTANT(SHAPE_PLANE); + BIND_ENUM_CONSTANT(SHAPE_RAY); BIND_ENUM_CONSTANT(SHAPE_SPHERE); BIND_ENUM_CONSTANT(SHAPE_BOX); BIND_ENUM_CONSTANT(SHAPE_CAPSULE); diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h index 5201e764980..b8cbceacc77 100644 --- a/servers/physics_server_3d.h +++ b/servers/physics_server_3d.h @@ -222,6 +222,7 @@ public: enum ShapeType { SHAPE_PLANE, ///< plane:"plane" + SHAPE_RAY, ///< float:"length" SHAPE_SPHERE, ///< float:"radius" SHAPE_BOX, ///< vec3:"extents" SHAPE_CAPSULE, ///< dict( float:"radius", float:"height"):capsule @@ -236,6 +237,7 @@ public: RID shape_create(ShapeType p_shape); virtual RID plane_shape_create() = 0; + virtual RID ray_shape_create() = 0; virtual RID sphere_shape_create() = 0; virtual RID box_shape_create() = 0; virtual RID capsule_shape_create() = 0; From 829fb4fba12d167ffe2280998d2f50431b2ccab3 Mon Sep 17 00:00:00 2001 From: PouleyKetchoupp Date: Tue, 17 Aug 2021 18:41:21 -0700 Subject: [PATCH 2/5] Fix RayShape collision detection One-way collision is disabled for both rigid bodies and character bodies. Kinematic margin is now applied to ray shapes to help getting consistent results in slopes and flat surfaces. Convex shapes don't return inverted normals when a segment test starts inside (raycasting will be made consistent in a separate patch). Ray shapes also discard contacts when fully contained inside a shape and when the contact direction is inverted, so the behavior is consistent with all shape types. Now they always separate only when intersecting the top of a shape (for downward rays). --- servers/physics_2d/body_pair_2d_sw.cpp | 4 +- servers/physics_2d/collision_solver_2d_sw.cpp | 40 +++++++++++++------ servers/physics_2d/collision_solver_2d_sw.h | 6 +-- servers/physics_2d/shape_2d_sw.cpp | 9 +---- servers/physics_2d/shape_2d_sw.h | 4 ++ servers/physics_2d/space_2d_sw.cpp | 8 ++-- servers/physics_3d/collision_solver_3d_sw.cpp | 18 +++++++-- servers/physics_3d/collision_solver_3d_sw.h | 2 +- 8 files changed, 57 insertions(+), 34 deletions(-) diff --git a/servers/physics_2d/body_pair_2d_sw.cpp b/servers/physics_2d/body_pair_2d_sw.cpp index 91d747b492e..8bcc4609f47 100644 --- a/servers/physics_2d/body_pair_2d_sw.cpp +++ b/servers/physics_2d/body_pair_2d_sw.cpp @@ -298,7 +298,7 @@ bool BodyPair2DSW::setup(real_t p_step) { } if (!prev_collided) { - if (A->is_shape_set_as_one_way_collision(shape_A)) { + if (shape_B_ptr->allows_one_way_collision() && A->is_shape_set_as_one_way_collision(shape_A)) { Vector2 direction = xform_A.get_axis(1).normalized(); bool valid = false; for (int i = 0; i < contact_count; i++) { @@ -319,7 +319,7 @@ bool BodyPair2DSW::setup(real_t p_step) { } } - if (B->is_shape_set_as_one_way_collision(shape_B)) { + if (shape_A_ptr->allows_one_way_collision() && B->is_shape_set_as_one_way_collision(shape_B)) { Vector2 direction = xform_B.get_axis(1).normalized(); bool valid = false; for (int i = 0; i < contact_count; i++) { diff --git a/servers/physics_2d/collision_solver_2d_sw.cpp b/servers/physics_2d/collision_solver_2d_sw.cpp index 1946dae2e3d..34c94150e2a 100644 --- a/servers/physics_2d/collision_solver_2d_sw.cpp +++ b/servers/physics_2d/collision_solver_2d_sw.cpp @@ -73,14 +73,14 @@ bool CollisionSolver2DSW::solve_static_world_margin(const Shape2DSW *p_shape_A, return found; } -bool CollisionSolver2DSW::solve_raycast(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 *sep_axis) { +bool CollisionSolver2DSW::solve_raycast(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 RayShape2DSW *ray = static_cast(p_shape_A); if (p_shape_B->get_type() == PhysicsServer2D::SHAPE_RAY) { return false; } Vector2 from = p_transform_A.get_origin(); - Vector2 to = from + p_transform_A[1] * ray->get_length(); + Vector2 to = from + p_transform_A[1] * (ray->get_length() + p_margin); if (p_motion_A != Vector2()) { //not the best but should be enough Vector2 normal = (to - from).normalized(); @@ -94,8 +94,24 @@ bool CollisionSolver2DSW::solve_raycast(const Shape2DSW *p_shape_A, const Vector Vector2 p, n; if (!p_shape_B->intersect_segment(from, to, p, n)) { - if (sep_axis) { - *sep_axis = p_transform_A[1].normalized(); + if (r_sep_axis) { + *r_sep_axis = p_transform_A[1].normalized(); + } + return false; + } + + // Discard contacts when the ray is fully contained inside the shape. + if (n == Vector2()) { + if (r_sep_axis) { + *r_sep_axis = p_transform_A[1].normalized(); + } + return false; + } + + // Discard contacts in the wrong direction. + if (n.dot(from - to) < CMP_EPSILON) { + if (r_sep_axis) { + *r_sep_axis = p_transform_A[1].normalized(); } return false; } @@ -149,7 +165,7 @@ void CollisionSolver2DSW::concave_callback(void *p_userdata, Shape2DSW *p_convex cinfo.collisions++; } -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 *sep_axis, real_t p_margin_A, real_t p_margin_B) { +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(p_shape_B); _ConcaveCollisionInfo2D cinfo; @@ -162,7 +178,7 @@ bool CollisionSolver2DSW::solve_concave(const Shape2DSW *p_shape_A, const Transf cinfo.swap_result = p_swap_result; cinfo.collided = false; cinfo.collisions = 0; - cinfo.sep_axis = sep_axis; + cinfo.sep_axis = r_sep_axis; cinfo.margin_A = p_margin_A; cinfo.margin_B = p_margin_B; @@ -193,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 *sep_axis, real_t p_margin_A, real_t p_margin_B) { +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) { 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(); @@ -226,9 +242,9 @@ bool CollisionSolver2DSW::solve(const Shape2DSW *p_shape_A, const Transform2D &p } if (swap) { - return solve_raycast(p_shape_B, p_motion_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true, sep_axis); + return solve_raycast(p_shape_B, p_motion_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true, r_sep_axis, p_margin_B); } else { - return solve_raycast(p_shape_A, p_motion_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false, sep_axis); + return solve_raycast(p_shape_A, p_motion_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false, r_sep_axis, p_margin_A); } } else if (concave_B) { @@ -237,12 +253,12 @@ bool CollisionSolver2DSW::solve(const Shape2DSW *p_shape_A, const Transform2D &p } if (!swap) { - return solve_concave(p_shape_A, p_transform_A, p_motion_A, p_shape_B, p_transform_B, p_motion_B, p_result_callback, p_userdata, false, sep_axis, margin_A, margin_B); + return solve_concave(p_shape_A, p_transform_A, p_motion_A, p_shape_B, p_transform_B, p_motion_B, p_result_callback, p_userdata, false, r_sep_axis, margin_A, margin_B); } else { - return solve_concave(p_shape_B, p_transform_B, p_motion_B, p_shape_A, p_transform_A, p_motion_A, p_result_callback, p_userdata, true, sep_axis, margin_A, margin_B); + return solve_concave(p_shape_B, p_transform_B, p_motion_B, p_shape_A, p_transform_A, p_motion_A, p_result_callback, p_userdata, true, r_sep_axis, margin_A, margin_B); } } else { - return collision_solver(p_shape_A, p_transform_A, p_motion_A, p_shape_B, p_transform_B, p_motion_B, p_result_callback, p_userdata, false, sep_axis, margin_A, margin_B); + return collision_solver(p_shape_A, p_transform_A, p_motion_A, p_shape_B, p_transform_B, p_motion_B, p_result_callback, p_userdata, false, r_sep_axis, margin_A, margin_B); } } diff --git a/servers/physics_2d/collision_solver_2d_sw.h b/servers/physics_2d/collision_solver_2d_sw.h index 17c0c2fe702..c2f13d0e131 100644 --- a/servers/physics_2d/collision_solver_2d_sw.h +++ b/servers/physics_2d/collision_solver_2d_sw.h @@ -40,11 +40,11 @@ public: private: static bool solve_static_world_margin(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 void 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 *sep_axis = nullptr, real_t p_margin_A = 0, real_t p_margin_B = 0); - static bool solve_raycast(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 *sep_axis = nullptr); + 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_raycast(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); 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 *sep_axis = nullptr, real_t p_margin_A = 0, real_t p_margin_B = 0); + 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); }; #endif // COLLISION_SOLVER_2D_SW_H diff --git a/servers/physics_2d/shape_2d_sw.cpp b/servers/physics_2d/shape_2d_sw.cpp index be2f83b705a..a82f0c2e6f8 100644 --- a/servers/physics_2d/shape_2d_sw.cpp +++ b/servers/physics_2d/shape_2d_sw.cpp @@ -570,14 +570,7 @@ bool ConvexPolygonShape2DSW::intersect_segment(const Vector2 &p_begin, const Vec } } - if (inters) { - if (n.dot(r_normal) > 0) { - r_normal = -r_normal; - } - } - - //return get_aabb().intersects_segment(p_begin,p_end,&r_point,&r_normal); - return inters; //todo + return inters; } real_t ConvexPolygonShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const { diff --git a/servers/physics_2d/shape_2d_sw.h b/servers/physics_2d/shape_2d_sw.h index d1640b39cf0..6813e25a0b9 100644 --- a/servers/physics_2d/shape_2d_sw.h +++ b/servers/physics_2d/shape_2d_sw.h @@ -64,6 +64,8 @@ public: _FORCE_INLINE_ Rect2 get_aabb() const { return aabb; } _FORCE_INLINE_ bool is_configured() const { return configured; } + virtual bool allows_one_way_collision() const { return true; } + virtual bool is_concave() const { return false; } virtual bool contains_point(const Vector2 &p_point) const = 0; @@ -187,6 +189,8 @@ public: virtual PhysicsServer2D::ShapeType get_type() const { return PhysicsServer2D::SHAPE_RAY; } + virtual bool allows_one_way_collision() const override { return false; } + virtual void project_rangev(const Vector2 &p_normal, const Transform2D &p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal, p_transform, r_min, r_max); } virtual void get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const; diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp index f04f3ab5835..61ec48c090d 100644 --- a/servers/physics_2d/space_2d_sw.cpp +++ b/servers/physics_2d/space_2d_sw.cpp @@ -621,7 +621,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co Transform2D col_obj_shape_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx); - if (col_obj->is_shape_set_as_one_way_collision(shape_idx)) { + if (body_shape->allows_one_way_collision() && col_obj->is_shape_set_as_one_way_collision(shape_idx)) { 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); @@ -762,7 +762,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co //test initial overlap if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), nullptr, nullptr, nullptr, 0)) { - if (col_obj->is_shape_set_as_one_way_collision(col_shape_idx)) { + 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) { continue; @@ -806,7 +806,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co } } - if (col_obj->is_shape_set_as_one_way_collision(col_shape_idx)) { + 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; cbk.max = 1; @@ -904,7 +904,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co Transform2D col_obj_shape_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx); - if (col_obj->is_shape_set_as_one_way_collision(shape_idx)) { + if (body_shape->allows_one_way_collision() && col_obj->is_shape_set_as_one_way_collision(shape_idx)) { 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); diff --git a/servers/physics_3d/collision_solver_3d_sw.cpp b/servers/physics_3d/collision_solver_3d_sw.cpp index c61b9cbd4eb..8803b355d46 100644 --- a/servers/physics_3d/collision_solver_3d_sw.cpp +++ b/servers/physics_3d/collision_solver_3d_sw.cpp @@ -89,11 +89,11 @@ bool CollisionSolver3DSW::solve_static_plane(const Shape3DSW *p_shape_A, const T return found; } -bool CollisionSolver3DSW::solve_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) { +bool CollisionSolver3DSW::solve_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 RayShape3DSW *ray = static_cast(p_shape_A); Vector3 from = p_transform_A.origin; - Vector3 to = from + p_transform_A.basis.get_axis(2) * ray->get_length(); + Vector3 to = from + p_transform_A.basis.get_axis(2) * (ray->get_length() + p_margin); Vector3 support_A = to; Transform3D ai = p_transform_B.affine_inverse(); @@ -106,6 +106,16 @@ bool CollisionSolver3DSW::solve_ray(const Shape3DSW *p_shape_A, const Transform3 return false; } + // Discard contacts when the ray is fully contained inside the shape. + if (n == Vector3()) { + return false; + } + + // Discard contacts in the wrong direction. + if (n.dot(from - to) < CMP_EPSILON) { + return false; + } + Vector3 support_B = p_transform_B.xform(p); if (ray->get_slips_on_slope()) { Vector3 global_n = ai.basis.xform_inv(n).normalized(); @@ -370,9 +380,9 @@ bool CollisionSolver3DSW::solve_static(const Shape3DSW *p_shape_A, const Transfo } if (swap) { - return solve_ray(p_shape_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true); + return solve_ray(p_shape_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true, p_margin_B); } else { - return solve_ray(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false); + return solve_ray(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false, p_margin_A); } } else if (type_B == PhysicsServer3D::SHAPE_SOFT_BODY) { diff --git a/servers/physics_3d/collision_solver_3d_sw.h b/servers/physics_3d/collision_solver_3d_sw.h index a5dd7d48eba..cbde9ce18fb 100644 --- a/servers/physics_3d/collision_solver_3d_sw.h +++ b/servers/physics_3d/collision_solver_3d_sw.h @@ -43,7 +43,7 @@ private: static void soft_body_concave_callback(void *p_userdata, Shape3DSW *p_convex); static void concave_callback(void *p_userdata, Shape3DSW *p_convex); static bool solve_static_plane(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_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); + static bool solve_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 void concave_distance_callback(void *p_userdata, Shape3DSW *p_convex); From d9720d439545792bd742645f3c6e3f7c29327aa8 Mon Sep 17 00:00:00 2001 From: PouleyKetchoupp Date: Thu, 19 Aug 2021 08:28:04 -0700 Subject: [PATCH 3/5] Fix CharacterBody motion with RayShape Make separation ray shapes work properly in move_and_slide, wihtout the specific code in CharacterBody like before. Now most of the logic is handled inside the physics server. The only thing that's needed is to use ray shapes only for recovery and ignore them when performing the motion itself (unless we're snapping or slips on slope is on). --- doc/classes/PhysicsServer2D.xml | 3 ++- doc/classes/PhysicsServer3D.xml | 3 ++- scene/2d/physics_body_2d.cpp | 10 +++++----- scene/2d/physics_body_2d.h | 2 +- scene/3d/physics_body_3d.cpp | 8 ++++---- scene/3d/physics_body_3d.h | 2 +- servers/physics_2d/physics_server_2d_sw.cpp | 4 ++-- servers/physics_2d/physics_server_2d_sw.h | 2 +- servers/physics_2d/physics_server_2d_wrap_mt.h | 4 ++-- servers/physics_2d/space_2d_sw.cpp | 12 +++++++++++- servers/physics_2d/space_2d_sw.h | 2 +- servers/physics_3d/physics_server_3d_sw.cpp | 4 ++-- servers/physics_3d/physics_server_3d_sw.h | 2 +- servers/physics_3d/physics_server_3d_wrap_mt.h | 4 ++-- servers/physics_3d/space_3d_sw.cpp | 14 ++++++++++++-- servers/physics_3d/space_3d_sw.h | 2 +- servers/physics_server_2d.cpp | 6 +++--- servers/physics_server_2d.h | 4 ++-- servers/physics_server_3d.cpp | 6 +++--- servers/physics_server_3d.h | 4 ++-- 20 files changed, 60 insertions(+), 38 deletions(-) diff --git a/doc/classes/PhysicsServer2D.xml b/doc/classes/PhysicsServer2D.xml index ae6b5fda51f..758ffb9b148 100644 --- a/doc/classes/PhysicsServer2D.xml +++ b/doc/classes/PhysicsServer2D.xml @@ -595,7 +595,8 @@ - + + Returns [code]true[/code] if a collision would result from moving in the given direction from a given point in space. Margin increases the size of the shapes involved in the collision detection. [PhysicsTestMotionResult2D] can be passed to return additional information in. diff --git a/doc/classes/PhysicsServer3D.xml b/doc/classes/PhysicsServer3D.xml index a5234e90e7a..cf353e1073f 100644 --- a/doc/classes/PhysicsServer3D.xml +++ b/doc/classes/PhysicsServer3D.xml @@ -571,7 +571,8 @@ - + + Returns [code]true[/code] if a collision would result from moving in the given direction from a given point in space. Margin increases the size of the shapes involved in the collision detection. [PhysicsTestMotionResult3D] can be passed to return additional information in. diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index a9d4877cbbe..8a9d28ae43f 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -70,12 +70,12 @@ Ref PhysicsBody2D::_move(const Vector2 &p_motion, bool p_t return Ref(); } -bool PhysicsBody2D::move_and_collide(const Vector2 &p_motion, PhysicsServer2D::MotionResult &r_result, real_t p_margin, bool p_test_only, bool p_cancel_sliding, const Set &p_exclude) { +bool PhysicsBody2D::move_and_collide(const Vector2 &p_motion, PhysicsServer2D::MotionResult &r_result, real_t p_margin, bool p_test_only, bool p_cancel_sliding, bool p_collide_separation_ray, const Set &p_exclude) { if (is_only_update_transform_changes_enabled()) { ERR_PRINT("Move functions do not work together with 'sync to physics' option. Please read the documentation."); } Transform2D gt = get_global_transform(); - bool colliding = PhysicsServer2D::get_singleton()->body_test_motion(get_rid(), gt, p_motion, p_margin, &r_result, p_exclude); + bool colliding = PhysicsServer2D::get_singleton()->body_test_motion(get_rid(), gt, p_motion, p_margin, &r_result, p_collide_separation_ray, p_exclude); // Restore direction of motion to be along original motion, // in order to avoid sliding due to recovery, @@ -1075,7 +1075,7 @@ bool CharacterBody2D::move_and_slide() { PhysicsServer2D::MotionResult floor_result; Set exclude; exclude.insert(platform_rid); - if (move_and_collide(current_platform_velocity * delta, floor_result, margin, false, false, exclude)) { + if (move_and_collide(current_platform_velocity * delta, floor_result, margin, false, false, false, exclude)) { motion_results.push_back(floor_result); _set_collision_direction(floor_result); } @@ -1285,7 +1285,7 @@ void CharacterBody2D::_snap_on_floor(bool was_on_floor, bool vel_dir_facing_up) Transform2D gt = get_global_transform(); PhysicsServer2D::MotionResult result; - if (move_and_collide(up_direction * -floor_snap_length, result, margin, true, false)) { + if (move_and_collide(up_direction * -floor_snap_length, result, margin, true, false, true)) { bool apply = true; if (result.get_angle(up_direction) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) { on_floor = true; @@ -1319,7 +1319,7 @@ bool CharacterBody2D::_on_floor_if_snapped(bool was_on_floor, bool vel_dir_facin } PhysicsServer2D::MotionResult result; - if (move_and_collide(up_direction * -floor_snap_length, result, margin, true, false)) { + if (move_and_collide(up_direction * -floor_snap_length, result, margin, true, false, true)) { if (result.get_angle(up_direction) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) { return true; } diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h index a9993179536..885f0ace05f 100644 --- a/scene/2d/physics_body_2d.h +++ b/scene/2d/physics_body_2d.h @@ -50,7 +50,7 @@ protected: Ref _move(const Vector2 &p_motion, bool p_test_only = false, real_t p_margin = 0.08); public: - bool move_and_collide(const Vector2 &p_motion, PhysicsServer2D::MotionResult &r_result, real_t p_margin, bool p_test_only = false, bool p_cancel_sliding = true, const Set &p_exclude = Set()); + bool move_and_collide(const Vector2 &p_motion, PhysicsServer2D::MotionResult &r_result, real_t p_margin, bool p_test_only = false, bool p_cancel_sliding = true, bool p_collide_separation_ray = false, const Set &p_exclude = Set()); bool test_move(const Transform2D &p_from, const Vector2 &p_motion, const Ref &r_collision = Ref(), real_t p_margin = 0.08); TypedArray get_collision_exceptions(); diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp index d34331e1d8f..a8a755972ff 100644 --- a/scene/3d/physics_body_3d.cpp +++ b/scene/3d/physics_body_3d.cpp @@ -111,9 +111,9 @@ Ref PhysicsBody3D::_move(const Vector3 &p_motion, bool p_t return Ref(); } -bool PhysicsBody3D::move_and_collide(const Vector3 &p_motion, PhysicsServer3D::MotionResult &r_result, real_t p_margin, bool p_test_only, bool p_cancel_sliding, const Set &p_exclude) { +bool PhysicsBody3D::move_and_collide(const Vector3 &p_motion, PhysicsServer3D::MotionResult &r_result, real_t p_margin, bool p_test_only, bool p_cancel_sliding, bool p_collide_separation_ray, const Set &p_exclude) { Transform3D gt = get_global_transform(); - bool colliding = PhysicsServer3D::get_singleton()->body_test_motion(get_rid(), gt, p_motion, p_margin, &r_result, p_exclude); + bool colliding = PhysicsServer3D::get_singleton()->body_test_motion(get_rid(), gt, p_motion, p_margin, &r_result, p_collide_separation_ray, p_exclude); // Restore direction of motion to be along original motion, // in order to avoid sliding due to recovery, @@ -1113,7 +1113,7 @@ bool CharacterBody3D::move_and_slide() { PhysicsServer3D::MotionResult floor_result; Set exclude; exclude.insert(on_floor_body); - if (move_and_collide(current_floor_velocity * delta, floor_result, margin, false, false, exclude)) { + if (move_and_collide(current_floor_velocity * delta, floor_result, margin, false, false, false, exclude)) { motion_results.push_back(floor_result); _set_collision_direction(floor_result); } @@ -1174,7 +1174,7 @@ bool CharacterBody3D::move_and_slide() { // Apply snap. Transform3D gt = get_global_transform(); PhysicsServer3D::MotionResult result; - if (move_and_collide(snap, result, margin, true, false)) { + if (move_and_collide(snap, result, margin, true, false, true)) { bool apply = true; if (up_direction != Vector3()) { if (result.get_angle(up_direction) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) { diff --git a/scene/3d/physics_body_3d.h b/scene/3d/physics_body_3d.h index 26b9a390471..17e688451d5 100644 --- a/scene/3d/physics_body_3d.h +++ b/scene/3d/physics_body_3d.h @@ -53,7 +53,7 @@ protected: Ref _move(const Vector3 &p_motion, bool p_test_only = false, real_t p_margin = 0.001); public: - bool move_and_collide(const Vector3 &p_motion, PhysicsServer3D::MotionResult &r_result, real_t p_margin, bool p_test_only = false, bool p_cancel_sliding = true, const Set &p_exclude = Set()); + bool move_and_collide(const Vector3 &p_motion, PhysicsServer3D::MotionResult &r_result, real_t p_margin, bool p_test_only = false, bool p_cancel_sliding = true, bool p_collide_separation_ray = false, const Set &p_exclude = Set()); bool test_move(const Transform3D &p_from, const Vector3 &p_motion, const Ref &r_collision = Ref(), real_t p_margin = 0.001); void set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool p_lock); diff --git a/servers/physics_2d/physics_server_2d_sw.cpp b/servers/physics_2d/physics_server_2d_sw.cpp index 0954f3a1748..5cb67d5ab95 100644 --- a/servers/physics_2d/physics_server_2d_sw.cpp +++ b/servers/physics_2d/physics_server_2d_sw.cpp @@ -946,7 +946,7 @@ void PhysicsServer2DSW::body_set_pickable(RID p_body, bool p_pickable) { body->set_pickable(p_pickable); } -bool PhysicsServer2DSW::body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin, MotionResult *r_result, const Set &p_exclude) { +bool PhysicsServer2DSW::body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin, MotionResult *r_result, bool p_collide_separation_ray, const Set &p_exclude) { Body2DSW *body = body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, false); ERR_FAIL_COND_V(!body->get_space(), false); @@ -954,7 +954,7 @@ bool PhysicsServer2DSW::body_test_motion(RID p_body, const Transform2D &p_from, _update_shapes(); - return body->get_space()->test_body_motion(body, p_from, p_motion, p_margin, r_result, p_exclude); + return body->get_space()->test_body_motion(body, p_from, p_motion, p_margin, r_result, p_collide_separation_ray, p_exclude); } PhysicsDirectBodyState2D *PhysicsServer2DSW::body_get_direct_state(RID p_body) { diff --git a/servers/physics_2d/physics_server_2d_sw.h b/servers/physics_2d/physics_server_2d_sw.h index 1926eaac846..6ea5e445bcf 100644 --- a/servers/physics_2d/physics_server_2d_sw.h +++ b/servers/physics_2d/physics_server_2d_sw.h @@ -247,7 +247,7 @@ public: virtual void body_set_pickable(RID p_body, bool p_pickable) override; - virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin = 0.08, MotionResult *r_result = nullptr, const Set &p_exclude = Set()) override; + virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin = 0.08, MotionResult *r_result = nullptr, bool p_collide_separation_ray = false, const Set &p_exclude = Set()) override; // this function only works on physics process, errors and returns null otherwise virtual PhysicsDirectBodyState2D *body_get_direct_state(RID p_body) override; diff --git a/servers/physics_2d/physics_server_2d_wrap_mt.h b/servers/physics_2d/physics_server_2d_wrap_mt.h index 0ebccc2614e..7b1cda169dc 100644 --- a/servers/physics_2d/physics_server_2d_wrap_mt.h +++ b/servers/physics_2d/physics_server_2d_wrap_mt.h @@ -253,9 +253,9 @@ public: FUNC2(body_set_pickable, RID, bool); - bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin = 0.08, MotionResult *r_result = nullptr, const Set &p_exclude = Set()) override { + bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin = 0.08, MotionResult *r_result = nullptr, bool p_collide_separation_ray = false, const Set &p_exclude = Set()) override { ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false); - return physics_2d_server->body_test_motion(p_body, p_from, p_motion, p_margin, r_result, p_exclude); + return physics_2d_server->body_test_motion(p_body, p_from, p_motion, p_margin, r_result, p_collide_separation_ray, p_exclude); } // this function only works on physics process, errors and returns null otherwise diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp index 61ec48c090d..169c419b3b3 100644 --- a/servers/physics_2d/space_2d_sw.cpp +++ b/servers/physics_2d/space_2d_sw.cpp @@ -528,7 +528,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 Transform2D &p_from, const Vector2 &p_motion, real_t p_margin, PhysicsServer2D::MotionResult *r_result, const Set &p_exclude) { +bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin, PhysicsServer2D::MotionResult *r_result, bool p_collide_separation_ray, const Set &p_exclude) { //give me back regular physics engine logic //this is madness //and most people using this function will think @@ -726,6 +726,16 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co } Shape2DSW *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_collide_separation_ray && (body_shape->get_type() == PhysicsServer2D::SHAPE_RAY)) { + // When slips on slope is on, separation ray shape acts like a regular shape. + if (!static_cast(body_shape)->get_slips_on_slope()) { + continue; + } + } + Transform2D body_shape_xform = body_transform * p_body->get_shape_transform(body_shape_idx); bool stuck = false; diff --git a/servers/physics_2d/space_2d_sw.h b/servers/physics_2d/space_2d_sw.h index 3be36852b0c..392df9b0250 100644 --- a/servers/physics_2d/space_2d_sw.h +++ b/servers/physics_2d/space_2d_sw.h @@ -183,7 +183,7 @@ public: int get_collision_pairs() const { return collision_pairs; } - bool test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin, PhysicsServer2D::MotionResult *r_result, const Set &p_exclude = Set()); + bool test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin, PhysicsServer2D::MotionResult *r_result, bool p_collide_separation_ray = false, const Set &p_exclude = Set()); void set_debug_contacts(int p_amount) { contact_debug.resize(p_amount); } _FORCE_INLINE_ bool is_debugging_contacts() const { return !contact_debug.is_empty(); } diff --git a/servers/physics_3d/physics_server_3d_sw.cpp b/servers/physics_3d/physics_server_3d_sw.cpp index a1d776922e5..1cf6b12623a 100644 --- a/servers/physics_3d/physics_server_3d_sw.cpp +++ b/servers/physics_3d/physics_server_3d_sw.cpp @@ -854,7 +854,7 @@ void PhysicsServer3DSW::body_set_ray_pickable(RID p_body, bool p_enable) { body->set_ray_pickable(p_enable); } -bool PhysicsServer3DSW::body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin, MotionResult *r_result, const Set &p_exclude) { +bool PhysicsServer3DSW::body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin, MotionResult *r_result, bool p_collide_separation_ray, const Set &p_exclude) { Body3DSW *body = body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, false); ERR_FAIL_COND_V(!body->get_space(), false); @@ -862,7 +862,7 @@ bool PhysicsServer3DSW::body_test_motion(RID p_body, const Transform3D &p_from, _update_shapes(); - return body->get_space()->test_body_motion(body, p_from, p_motion, p_margin, r_result, p_exclude); + return body->get_space()->test_body_motion(body, p_from, p_motion, p_margin, r_result, p_collide_separation_ray, p_exclude); } PhysicsDirectBodyState3D *PhysicsServer3DSW::body_get_direct_state(RID p_body) { diff --git a/servers/physics_3d/physics_server_3d_sw.h b/servers/physics_3d/physics_server_3d_sw.h index f2322a0e763..341ce06a5d1 100644 --- a/servers/physics_3d/physics_server_3d_sw.h +++ b/servers/physics_3d/physics_server_3d_sw.h @@ -242,7 +242,7 @@ public: virtual void body_set_ray_pickable(RID p_body, bool p_enable) override; - virtual bool body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin = 0.001, MotionResult *r_result = nullptr, const Set &p_exclude = Set()) override; + virtual bool body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin = 0.001, MotionResult *r_result = nullptr, bool p_collide_separation_ray = false, const Set &p_exclude = Set()) override; // this function only works on physics process, errors and returns null otherwise virtual PhysicsDirectBodyState3D *body_get_direct_state(RID p_body) override; diff --git a/servers/physics_3d/physics_server_3d_wrap_mt.h b/servers/physics_3d/physics_server_3d_wrap_mt.h index d807e737314..24bf203d518 100644 --- a/servers/physics_3d/physics_server_3d_wrap_mt.h +++ b/servers/physics_3d/physics_server_3d_wrap_mt.h @@ -250,9 +250,9 @@ public: FUNC2(body_set_ray_pickable, RID, bool); - bool body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin = 0.001, MotionResult *r_result = nullptr, const Set &p_exclude = Set()) override { + bool body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin = 0.001, MotionResult *r_result = nullptr, bool p_collide_separation_ray = false, const Set &p_exclude = Set()) override { ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false); - return physics_3d_server->body_test_motion(p_body, p_from, p_motion, p_margin, r_result, p_exclude); + return physics_3d_server->body_test_motion(p_body, p_from, p_motion, p_margin, r_result, p_collide_separation_ray, p_exclude); } // this function only works on physics process, errors and returns null otherwise diff --git a/servers/physics_3d/space_3d_sw.cpp b/servers/physics_3d/space_3d_sw.cpp index f9e55ad5254..7ed17d62840 100644 --- a/servers/physics_3d/space_3d_sw.cpp +++ b/servers/physics_3d/space_3d_sw.cpp @@ -569,7 +569,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 Transform3D &p_from, const Vector3 &p_motion, real_t p_margin, PhysicsServer3D::MotionResult *r_result, const Set &p_exclude) { +bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin, PhysicsServer3D::MotionResult *r_result, bool p_collide_separation_ray, const Set &p_exclude) { //give me back regular physics engine logic //this is madness //and most people using this function will think @@ -714,9 +714,19 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co continue; } - Transform3D body_shape_xform = body_transform * p_body->get_shape_transform(j); Shape3DSW *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_collide_separation_ray && (body_shape->get_type() == PhysicsServer3D::SHAPE_RAY)) { + // When slips on slope is on, separation ray shape acts like a regular shape. + if (!static_cast(body_shape)->get_slips_on_slope()) { + continue; + } + } + + Transform3D body_shape_xform = body_transform * p_body->get_shape_transform(j); + Transform3D body_shape_xform_inv = body_shape_xform.affine_inverse(); MotionShape3DSW mshape; mshape.shape = body_shape; diff --git a/servers/physics_3d/space_3d_sw.h b/servers/physics_3d/space_3d_sw.h index 9b5b4de0699..1c3d1cf9f6d 100644 --- a/servers/physics_3d/space_3d_sw.h +++ b/servers/physics_3d/space_3d_sw.h @@ -203,7 +203,7 @@ public: 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 Transform3D &p_from, const Vector3 &p_motion, real_t p_margin, PhysicsServer3D::MotionResult *r_result, const Set &p_exclude = Set()); + bool test_body_motion(Body3DSW *p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin, PhysicsServer3D::MotionResult *r_result, bool p_collide_separation_ray = false, const Set &p_exclude = Set()); Space3DSW(); ~Space3DSW(); diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp index 42b3daab285..2132a7c93df 100644 --- a/servers/physics_server_2d.cpp +++ b/servers/physics_server_2d.cpp @@ -500,7 +500,7 @@ void PhysicsTestMotionResult2D::_bind_methods() { /////////////////////////////////////// -bool PhysicsServer2D::_body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin, const Ref &p_result, const Vector &p_exclude) { +bool PhysicsServer2D::_body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin, const Ref &p_result, bool p_collide_separation_ray, const Vector &p_exclude) { MotionResult *r = nullptr; if (p_result.is_valid()) { r = p_result->get_result_ptr(); @@ -509,7 +509,7 @@ bool PhysicsServer2D::_body_test_motion(RID p_body, const Transform2D &p_from, c for (int i = 0; i < p_exclude.size(); i++) { exclude.insert(p_exclude[i]); } - return body_test_motion(p_body, p_from, p_motion, p_margin, r, exclude); + return body_test_motion(p_body, p_from, p_motion, p_margin, r, p_collide_separation_ray, exclude); } void PhysicsServer2D::_bind_methods() { @@ -636,7 +636,7 @@ void PhysicsServer2D::_bind_methods() { ClassDB::bind_method(D_METHOD("body_set_force_integration_callback", "body", "callable", "userdata"), &PhysicsServer2D::body_set_force_integration_callback, DEFVAL(Variant())); - ClassDB::bind_method(D_METHOD("body_test_motion", "body", "from", "motion", "margin", "result", "exclude"), &PhysicsServer2D::_body_test_motion, DEFVAL(0.08), DEFVAL(Variant()), DEFVAL(Array())); + ClassDB::bind_method(D_METHOD("body_test_motion", "body", "from", "motion", "margin", "result", "collide_separation_ray", "exclude"), &PhysicsServer2D::_body_test_motion, DEFVAL(0.08), DEFVAL(Variant()), DEFVAL(false), DEFVAL(Array())); ClassDB::bind_method(D_METHOD("body_get_direct_state", "body"), &PhysicsServer2D::body_get_direct_state); diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h index b6fb17b1c95..4a453564f1b 100644 --- a/servers/physics_server_2d.h +++ b/servers/physics_server_2d.h @@ -210,7 +210,7 @@ class PhysicsServer2D : public Object { static PhysicsServer2D *singleton; - virtual bool _body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin = 0.08, const Ref &p_result = Ref(), const Vector &p_exclude = Vector()); + virtual bool _body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin = 0.08, const Ref &p_result = Ref(), bool p_collide_separation_ray = false, const Vector &p_exclude = Vector()); protected: static void _bind_methods(); @@ -487,7 +487,7 @@ public: } }; - virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin = 0.08, MotionResult *r_result = nullptr, const Set &p_exclude = Set()) = 0; + virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin = 0.08, MotionResult *r_result = nullptr, bool p_collide_separation_ray = false, const Set &p_exclude = Set()) = 0; struct SeparationResult { real_t collision_depth; diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp index 582acaefe8f..76d908b5298 100644 --- a/servers/physics_server_3d.cpp +++ b/servers/physics_server_3d.cpp @@ -447,7 +447,7 @@ void PhysicsTestMotionResult3D::_bind_methods() { /////////////////////////////////////// -bool PhysicsServer3D::_body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin, const Ref &p_result, const Vector &p_exclude) { +bool PhysicsServer3D::_body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin, const Ref &p_result, bool p_collide_separation_ray, const Vector &p_exclude) { MotionResult *r = nullptr; if (p_result.is_valid()) { r = p_result->get_result_ptr(); @@ -456,7 +456,7 @@ bool PhysicsServer3D::_body_test_motion(RID p_body, const Transform3D &p_from, c for (int i = 0; i < p_exclude.size(); i++) { exclude.insert(p_exclude[i]); } - return body_test_motion(p_body, p_from, p_motion, p_margin, r, exclude); + return body_test_motion(p_body, p_from, p_motion, p_margin, r, p_collide_separation_ray, exclude); } RID PhysicsServer3D::shape_create(ShapeType p_shape) { @@ -612,7 +612,7 @@ void PhysicsServer3D::_bind_methods() { ClassDB::bind_method(D_METHOD("body_set_ray_pickable", "body", "enable"), &PhysicsServer3D::body_set_ray_pickable); - ClassDB::bind_method(D_METHOD("body_test_motion", "body", "from", "motion", "margin", "result", "exclude"), &PhysicsServer3D::_body_test_motion, DEFVAL(0.001), DEFVAL(Variant()), DEFVAL(Array())); + ClassDB::bind_method(D_METHOD("body_test_motion", "body", "from", "motion", "margin", "result", "collide_separation_ray", "exclude"), &PhysicsServer3D::_body_test_motion, DEFVAL(0.001), DEFVAL(Variant()), DEFVAL(false), DEFVAL(Array())); ClassDB::bind_method(D_METHOD("body_get_direct_state", "body"), &PhysicsServer3D::body_get_direct_state); diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h index b8cbceacc77..c92e6629df4 100644 --- a/servers/physics_server_3d.h +++ b/servers/physics_server_3d.h @@ -212,7 +212,7 @@ class PhysicsServer3D : public Object { static PhysicsServer3D *singleton; - virtual bool _body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin = 0.001, const Ref &p_result = Ref(), const Vector &p_exclude = Vector()); + virtual bool _body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin = 0.001, const Ref &p_result = Ref(), bool p_collide_separation_ray = false, const Vector &p_exclude = Vector()); protected: static void _bind_methods(); @@ -499,7 +499,7 @@ public: } }; - virtual bool body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin = 0.001, MotionResult *r_result = nullptr, const Set &p_exclude = Set()) = 0; + virtual bool body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin = 0.001, MotionResult *r_result = nullptr, bool p_collide_separation_ray = false, const Set &p_exclude = Set()) = 0; /* SOFT BODY */ From aa4791735d2fe92d747a39529aebb410f96cf38f Mon Sep 17 00:00:00 2001 From: PouleyKetchoupp Date: Thu, 19 Aug 2021 11:02:40 -0700 Subject: [PATCH 4/5] Rename slips_on_slope to slide_on_slope Also added some precision to the documentation. --- doc/classes/RayShape2D.xml | 5 +++-- doc/classes/RayShape3D.xml | 5 +++-- scene/resources/ray_shape_2d.cpp | 16 ++++++++-------- scene/resources/ray_shape_2d.h | 6 +++--- scene/resources/ray_shape_3d.cpp | 16 ++++++++-------- scene/resources/ray_shape_3d.h | 6 +++--- servers/physics_2d/collision_solver_2d_sw.cpp | 2 +- servers/physics_2d/shape_2d_sw.cpp | 4 ++-- servers/physics_2d/shape_2d_sw.h | 4 ++-- servers/physics_2d/space_2d_sw.cpp | 4 ++-- servers/physics_3d/collision_solver_3d_sw.cpp | 2 +- servers/physics_3d/shape_3d_sw.cpp | 14 +++++++------- servers/physics_3d/shape_3d_sw.h | 6 +++--- servers/physics_3d/space_3d_sw.cpp | 4 ++-- 14 files changed, 48 insertions(+), 46 deletions(-) diff --git a/doc/classes/RayShape2D.xml b/doc/classes/RayShape2D.xml index 432c6500746..50b89a0922b 100644 --- a/doc/classes/RayShape2D.xml +++ b/doc/classes/RayShape2D.xml @@ -14,8 +14,9 @@ The ray's length. - - If [code]true[/code], allow the shape to return the correct normal. + + If [code]false[/code] (default), the shape always separates and returns a normal along its own direction. + If [code]true[/code], the shape can return the correct normal and separate in any direction, allowing sliding motion on slopes. diff --git a/doc/classes/RayShape3D.xml b/doc/classes/RayShape3D.xml index 9839044c30c..e0b19e1a445 100644 --- a/doc/classes/RayShape3D.xml +++ b/doc/classes/RayShape3D.xml @@ -14,8 +14,9 @@ The ray's length. - - If [code]true[/code], allow the shape to return the correct normal. + + If [code]false[/code] (default), the shape always separates and returns a normal along its own direction. + If [code]true[/code], the shape can return the correct normal and separate in any direction, allowing sliding motion on slopes. diff --git a/scene/resources/ray_shape_2d.cpp b/scene/resources/ray_shape_2d.cpp index fb8f4b99850..2390a13bfab 100644 --- a/scene/resources/ray_shape_2d.cpp +++ b/scene/resources/ray_shape_2d.cpp @@ -36,7 +36,7 @@ void RayShape2D::_update_shape() { Dictionary d; d["length"] = length; - d["slips_on_slope"] = slips_on_slope; + d["slide_on_slope"] = slide_on_slope; PhysicsServer2D::get_singleton()->shape_set_data(get_rid(), d); emit_changed(); } @@ -88,11 +88,11 @@ void RayShape2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_length", "length"), &RayShape2D::set_length); ClassDB::bind_method(D_METHOD("get_length"), &RayShape2D::get_length); - ClassDB::bind_method(D_METHOD("set_slips_on_slope", "active"), &RayShape2D::set_slips_on_slope); - ClassDB::bind_method(D_METHOD("get_slips_on_slope"), &RayShape2D::get_slips_on_slope); + ClassDB::bind_method(D_METHOD("set_slide_on_slope", "active"), &RayShape2D::set_slide_on_slope); + ClassDB::bind_method(D_METHOD("get_slide_on_slope"), &RayShape2D::get_slide_on_slope); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "length"), "set_length", "get_length"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "slips_on_slope"), "set_slips_on_slope", "get_slips_on_slope"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "slide_on_slope"), "set_slide_on_slope", "get_slide_on_slope"); } void RayShape2D::set_length(real_t p_length) { @@ -104,13 +104,13 @@ real_t RayShape2D::get_length() const { return length; } -void RayShape2D::set_slips_on_slope(bool p_active) { - slips_on_slope = p_active; +void RayShape2D::set_slide_on_slope(bool p_active) { + slide_on_slope = p_active; _update_shape(); } -bool RayShape2D::get_slips_on_slope() const { - return slips_on_slope; +bool RayShape2D::get_slide_on_slope() const { + return slide_on_slope; } RayShape2D::RayShape2D() : diff --git a/scene/resources/ray_shape_2d.h b/scene/resources/ray_shape_2d.h index 56ecfa2722f..0895605ddf4 100644 --- a/scene/resources/ray_shape_2d.h +++ b/scene/resources/ray_shape_2d.h @@ -37,7 +37,7 @@ class RayShape2D : public Shape2D { GDCLASS(RayShape2D, Shape2D); real_t length = 20.0; - bool slips_on_slope = false; + bool slide_on_slope = false; void _update_shape(); @@ -48,8 +48,8 @@ public: void set_length(real_t p_length); real_t get_length() const; - void set_slips_on_slope(bool p_active); - bool get_slips_on_slope() const; + void set_slide_on_slope(bool p_active); + bool get_slide_on_slope() const; virtual void draw(const RID &p_to_rid, const Color &p_color) override; virtual Rect2 get_rect() const override; diff --git a/scene/resources/ray_shape_3d.cpp b/scene/resources/ray_shape_3d.cpp index 5446b4daab3..5d73fb8d809 100644 --- a/scene/resources/ray_shape_3d.cpp +++ b/scene/resources/ray_shape_3d.cpp @@ -47,7 +47,7 @@ real_t RayShape3D::get_enclosing_radius() const { void RayShape3D::_update_shape() { Dictionary d; d["length"] = length; - d["slips_on_slope"] = slips_on_slope; + d["slide_on_slope"] = slide_on_slope; PhysicsServer3D::get_singleton()->shape_set_data(get_shape(), d); Shape3D::_update_shape(); } @@ -62,25 +62,25 @@ float RayShape3D::get_length() const { return length; } -void RayShape3D::set_slips_on_slope(bool p_active) { - slips_on_slope = p_active; +void RayShape3D::set_slide_on_slope(bool p_active) { + slide_on_slope = p_active; _update_shape(); notify_change_to_owners(); } -bool RayShape3D::get_slips_on_slope() const { - return slips_on_slope; +bool RayShape3D::get_slide_on_slope() const { + return slide_on_slope; } void RayShape3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_length", "length"), &RayShape3D::set_length); ClassDB::bind_method(D_METHOD("get_length"), &RayShape3D::get_length); - ClassDB::bind_method(D_METHOD("set_slips_on_slope", "active"), &RayShape3D::set_slips_on_slope); - ClassDB::bind_method(D_METHOD("get_slips_on_slope"), &RayShape3D::get_slips_on_slope); + ClassDB::bind_method(D_METHOD("set_slide_on_slope", "active"), &RayShape3D::set_slide_on_slope); + ClassDB::bind_method(D_METHOD("get_slide_on_slope"), &RayShape3D::get_slide_on_slope); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "length", PROPERTY_HINT_RANGE, "0,4096,0.001"), "set_length", "get_length"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "slips_on_slope"), "set_slips_on_slope", "get_slips_on_slope"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "slide_on_slope"), "set_slide_on_slope", "get_slide_on_slope"); } RayShape3D::RayShape3D() : diff --git a/scene/resources/ray_shape_3d.h b/scene/resources/ray_shape_3d.h index 2da63113210..53694081850 100644 --- a/scene/resources/ray_shape_3d.h +++ b/scene/resources/ray_shape_3d.h @@ -35,7 +35,7 @@ class RayShape3D : public Shape3D { GDCLASS(RayShape3D, Shape3D); float length = 1.0; - bool slips_on_slope = false; + bool slide_on_slope = false; protected: static void _bind_methods(); @@ -45,8 +45,8 @@ public: void set_length(float p_length); float get_length() const; - void set_slips_on_slope(bool p_active); - bool get_slips_on_slope() const; + void set_slide_on_slope(bool p_active); + bool get_slide_on_slope() const; virtual Vector get_debug_mesh_lines() const override; virtual real_t get_enclosing_radius() const override; diff --git a/servers/physics_2d/collision_solver_2d_sw.cpp b/servers/physics_2d/collision_solver_2d_sw.cpp index 34c94150e2a..5337c8af568 100644 --- a/servers/physics_2d/collision_solver_2d_sw.cpp +++ b/servers/physics_2d/collision_solver_2d_sw.cpp @@ -117,7 +117,7 @@ bool CollisionSolver2DSW::solve_raycast(const Shape2DSW *p_shape_A, const Vector } Vector2 support_B = p_transform_B.xform(p); - if (ray->get_slips_on_slope()) { + if (ray->get_slide_on_slope()) { Vector2 global_n = invb.basis_xform_inv(n).normalized(); support_B = support_A + (support_B - support_A).length() * global_n; } diff --git a/servers/physics_2d/shape_2d_sw.cpp b/servers/physics_2d/shape_2d_sw.cpp index a82f0c2e6f8..dae56694885 100644 --- a/servers/physics_2d/shape_2d_sw.cpp +++ b/servers/physics_2d/shape_2d_sw.cpp @@ -168,14 +168,14 @@ real_t RayShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) void RayShape2DSW::set_data(const Variant &p_data) { Dictionary d = p_data; length = d["length"]; - slips_on_slope = d["slips_on_slope"]; + slide_on_slope = d["slide_on_slope"]; configure(Rect2(0, 0, 0.001, length)); } Variant RayShape2DSW::get_data() const { Dictionary d; d["length"] = length; - d["slips_on_slope"] = slips_on_slope; + d["slide_on_slope"] = slide_on_slope; return d; } diff --git a/servers/physics_2d/shape_2d_sw.h b/servers/physics_2d/shape_2d_sw.h index 6813e25a0b9..541d35dae92 100644 --- a/servers/physics_2d/shape_2d_sw.h +++ b/servers/physics_2d/shape_2d_sw.h @@ -181,11 +181,11 @@ public: class RayShape2DSW : public Shape2DSW { real_t length; - bool slips_on_slope; + bool slide_on_slope; public: _FORCE_INLINE_ real_t get_length() const { return length; } - _FORCE_INLINE_ bool get_slips_on_slope() const { return slips_on_slope; } + _FORCE_INLINE_ bool get_slide_on_slope() const { return slide_on_slope; } virtual PhysicsServer2D::ShapeType get_type() const { return PhysicsServer2D::SHAPE_RAY; } diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp index 169c419b3b3..92b87cea23a 100644 --- a/servers/physics_2d/space_2d_sw.cpp +++ b/servers/physics_2d/space_2d_sw.cpp @@ -730,8 +730,8 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co // Colliding separation rays allows to properly snap to the ground, // otherwise it's not needed in regular motion. if (!p_collide_separation_ray && (body_shape->get_type() == PhysicsServer2D::SHAPE_RAY)) { - // When slips on slope is on, separation ray shape acts like a regular shape. - if (!static_cast(body_shape)->get_slips_on_slope()) { + // When slide on slope is on, separation ray shape acts like a regular shape. + if (!static_cast(body_shape)->get_slide_on_slope()) { continue; } } diff --git a/servers/physics_3d/collision_solver_3d_sw.cpp b/servers/physics_3d/collision_solver_3d_sw.cpp index 8803b355d46..4a6a07534be 100644 --- a/servers/physics_3d/collision_solver_3d_sw.cpp +++ b/servers/physics_3d/collision_solver_3d_sw.cpp @@ -117,7 +117,7 @@ bool CollisionSolver3DSW::solve_ray(const Shape3DSW *p_shape_A, const Transform3 } Vector3 support_B = p_transform_B.xform(p); - if (ray->get_slips_on_slope()) { + if (ray->get_slide_on_slope()) { Vector3 global_n = ai.basis.xform_inv(n).normalized(); support_B = support_A + (support_B - support_A).length() * global_n; } diff --git a/servers/physics_3d/shape_3d_sw.cpp b/servers/physics_3d/shape_3d_sw.cpp index 42a0fb32b29..fcc97f56a33 100644 --- a/servers/physics_3d/shape_3d_sw.cpp +++ b/servers/physics_3d/shape_3d_sw.cpp @@ -170,8 +170,8 @@ real_t RayShape3DSW::get_length() const { return length; } -bool RayShape3DSW::get_slips_on_slope() const { - return slips_on_slope; +bool RayShape3DSW::get_slide_on_slope() const { + return slide_on_slope; } void RayShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const { @@ -226,27 +226,27 @@ Vector3 RayShape3DSW::get_moment_of_inertia(real_t p_mass) const { return Vector3(); } -void RayShape3DSW::_setup(real_t p_length, bool p_slips_on_slope) { +void RayShape3DSW::_setup(real_t p_length, bool p_slide_on_slope) { length = p_length; - slips_on_slope = p_slips_on_slope; + slide_on_slope = p_slide_on_slope; configure(AABB(Vector3(0, 0, 0), Vector3(0.1, 0.1, length))); } void RayShape3DSW::set_data(const Variant &p_data) { Dictionary d = p_data; - _setup(d["length"], d["slips_on_slope"]); + _setup(d["length"], d["slide_on_slope"]); } Variant RayShape3DSW::get_data() const { Dictionary d; d["length"] = length; - d["slips_on_slope"] = slips_on_slope; + d["slide_on_slope"] = slide_on_slope; return d; } RayShape3DSW::RayShape3DSW() { length = 1; - slips_on_slope = false; + slide_on_slope = false; } /********** SPHERE *************/ diff --git a/servers/physics_3d/shape_3d_sw.h b/servers/physics_3d/shape_3d_sw.h index 9f18b83f077..a693288f7eb 100644 --- a/servers/physics_3d/shape_3d_sw.h +++ b/servers/physics_3d/shape_3d_sw.h @@ -136,13 +136,13 @@ public: class RayShape3DSW : public Shape3DSW { real_t length; - bool slips_on_slope; + bool slide_on_slope; - void _setup(real_t p_length, bool p_slips_on_slope); + void _setup(real_t p_length, bool p_slide_on_slope); public: real_t get_length() const; - bool get_slips_on_slope() const; + bool get_slide_on_slope() const; virtual real_t get_area() const { return 0.0; } virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_RAY; } diff --git a/servers/physics_3d/space_3d_sw.cpp b/servers/physics_3d/space_3d_sw.cpp index 7ed17d62840..4ec03529cf6 100644 --- a/servers/physics_3d/space_3d_sw.cpp +++ b/servers/physics_3d/space_3d_sw.cpp @@ -719,8 +719,8 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co // Colliding separation rays allows to properly snap to the ground, // otherwise it's not needed in regular motion. if (!p_collide_separation_ray && (body_shape->get_type() == PhysicsServer3D::SHAPE_RAY)) { - // When slips on slope is on, separation ray shape acts like a regular shape. - if (!static_cast(body_shape)->get_slips_on_slope()) { + // When slide on slope is on, separation ray shape acts like a regular shape. + if (!static_cast(body_shape)->get_slide_on_slope()) { continue; } } From 3d5dc80348b9b377f6d8a33c7101d54b337396a5 Mon Sep 17 00:00:00 2001 From: PouleyKetchoupp Date: Thu, 19 Aug 2021 11:21:56 -0700 Subject: [PATCH 5/5] Rename RayShape to SeparationRayShape Makes it clearer that it's used for special cases when picking a collision shape. --- doc/classes/PhysicsServer2D.xml | 13 ++--- doc/classes/PhysicsServer3D.xml | 6 +-- ...ayShape3D.xml => SeparationRayShape2D.xml} | 8 ++-- ...ayShape2D.xml => SeparationRayShape3D.xml} | 8 ++-- ...ayShape2D.svg => SeparationRayShape2D.svg} | 0 ...ayShape3D.svg => SeparationRayShape3D.svg} | 0 editor/import/resource_importer_scene.cpp | 4 +- .../collision_shape_2d_editor_plugin.cpp | 22 ++++----- .../collision_shape_2d_editor_plugin.h | 2 +- editor/plugins/node_3d_editor_gizmos.cpp | 22 ++++----- scene/register_scene_types.cpp | 11 +++-- ...ape_2d.cpp => separation_ray_shape_2d.cpp} | 34 ++++++------- ...y_shape_2d.h => separation_ray_shape_2d.h} | 14 +++--- ...ape_3d.cpp => separation_ray_shape_3d.cpp} | 32 ++++++------- ...y_shape_3d.h => separation_ray_shape_3d.h} | 14 +++--- .../physics_2d/collision_solver_2d_sat.cpp | 4 +- servers/physics_2d/collision_solver_2d_sw.cpp | 14 +++--- servers/physics_2d/collision_solver_2d_sw.h | 2 +- servers/physics_2d/physics_server_2d_sw.cpp | 8 ++-- servers/physics_2d/physics_server_2d_sw.h | 2 +- .../physics_2d/physics_server_2d_wrap_mt.h | 2 +- servers/physics_2d/shape_2d_sw.cpp | 12 ++--- servers/physics_2d/shape_2d_sw.h | 22 ++++----- servers/physics_2d/space_2d_sw.cpp | 4 +- .../physics_3d/collision_solver_3d_sat.cpp | 4 +- servers/physics_3d/collision_solver_3d_sw.cpp | 14 +++--- servers/physics_3d/collision_solver_3d_sw.h | 2 +- servers/physics_3d/physics_server_3d_sw.cpp | 4 +- servers/physics_3d/physics_server_3d_sw.h | 2 +- .../physics_3d/physics_server_3d_wrap_mt.h | 2 +- servers/physics_3d/shape_3d_sw.cpp | 26 +++++----- servers/physics_3d/shape_3d_sw.h | 48 +++++++++---------- servers/physics_3d/space_3d_sw.cpp | 4 +- servers/physics_server_2d.cpp | 4 +- servers/physics_server_2d.h | 4 +- servers/physics_server_3d.cpp | 8 ++-- servers/physics_server_3d.h | 4 +- 37 files changed, 194 insertions(+), 192 deletions(-) rename doc/classes/{RayShape3D.xml => SeparationRayShape2D.xml} (65%) rename doc/classes/{RayShape2D.xml => SeparationRayShape3D.xml} (75%) rename editor/icons/{RayShape2D.svg => SeparationRayShape2D.svg} (100%) rename editor/icons/{RayShape3D.svg => SeparationRayShape3D.svg} (100%) rename scene/resources/{ray_shape_2d.cpp => separation_ray_shape_2d.cpp} (79%) rename scene/resources/{ray_shape_2d.h => separation_ray_shape_2d.h} (90%) rename scene/resources/{ray_shape_3d.cpp => separation_ray_shape_3d.cpp} (77%) rename scene/resources/{ray_shape_3d.h => separation_ray_shape_3d.h} (90%) diff --git a/doc/classes/PhysicsServer2D.xml b/doc/classes/PhysicsServer2D.xml index 758ffb9b148..d0ae6651395 100644 --- a/doc/classes/PhysicsServer2D.xml +++ b/doc/classes/PhysicsServer2D.xml @@ -717,11 +717,6 @@ Sets a joint parameter. See [enum JointParam] for a list of available parameters. - - - - - @@ -732,6 +727,11 @@ + + + + + @@ -846,7 +846,8 @@ This is the constant for creating world margin shapes. A world margin shape is an [i]infinite[/i] line with an origin point, and a normal. Thus, it can be used for front/behind checks. - + + This is the constant for creating separation ray shapes. A separation ray is defined by a length and separates itself from what is touching its far endpoint. Useful for character controllers. This is the constant for creating segment shapes. A segment shape is a [i]finite[/i] line from a point A to a point B. It can be checked for intersections. diff --git a/doc/classes/PhysicsServer3D.xml b/doc/classes/PhysicsServer3D.xml index cf353e1073f..c47a311161b 100644 --- a/doc/classes/PhysicsServer3D.xml +++ b/doc/classes/PhysicsServer3D.xml @@ -850,7 +850,7 @@ - + @@ -1177,8 +1177,8 @@ The [Shape3D] is a [WorldMarginShape3D]. - - The [Shape3D] is a [RayShape3D]. + + The [Shape3D] is a [SeparationRayShape3D]. The [Shape3D] is a [SphereShape3D]. diff --git a/doc/classes/RayShape3D.xml b/doc/classes/SeparationRayShape2D.xml similarity index 65% rename from doc/classes/RayShape3D.xml rename to doc/classes/SeparationRayShape2D.xml index e0b19e1a445..fb90606577a 100644 --- a/doc/classes/RayShape3D.xml +++ b/doc/classes/SeparationRayShape2D.xml @@ -1,17 +1,17 @@ - + - Ray shape for 3D collisions. + Separation ray shape for 2D collisions. - Ray shape for 3D collisions, which can be set into a [PhysicsBody3D] or [Area3D]. A ray is not really a collision body; instead, it tries to separate itself from whatever is touching its far endpoint. It's often useful for characters. + Separation ray shape for 2D collisions. A ray is not really a collision body; instead, it tries to separate itself from whatever is touching its far endpoint. It's often useful for characters. - + The ray's length. diff --git a/doc/classes/RayShape2D.xml b/doc/classes/SeparationRayShape3D.xml similarity index 75% rename from doc/classes/RayShape2D.xml rename to doc/classes/SeparationRayShape3D.xml index 50b89a0922b..ea57e4eb596 100644 --- a/doc/classes/RayShape2D.xml +++ b/doc/classes/SeparationRayShape3D.xml @@ -1,17 +1,17 @@ - + - Ray shape for 2D collisions. + Separation ray shape for 3D collisions. - Ray shape for 2D collisions. A ray is not really a collision body; instead, it tries to separate itself from whatever is touching its far endpoint. It's often useful for characters. + Separation ray shape for 3D collisions, which can be set into a [PhysicsBody3D] or [Area3D]. A ray is not really a collision body; instead, it tries to separate itself from whatever is touching its far endpoint. It's often useful for characters. - + The ray's length. diff --git a/editor/icons/RayShape2D.svg b/editor/icons/SeparationRayShape2D.svg similarity index 100% rename from editor/icons/RayShape2D.svg rename to editor/icons/SeparationRayShape2D.svg diff --git a/editor/icons/RayShape3D.svg b/editor/icons/SeparationRayShape3D.svg similarity index 100% rename from editor/icons/RayShape3D.svg rename to editor/icons/SeparationRayShape3D.svg diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index ef5e124ad98..c2244befa1a 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -45,8 +45,8 @@ #include "scene/resources/animation.h" #include "scene/resources/box_shape_3d.h" #include "scene/resources/packed_scene.h" -#include "scene/resources/ray_shape_3d.h" #include "scene/resources/resource_format_text.h" +#include "scene/resources/separation_ray_shape_3d.h" #include "scene/resources/sphere_shape_3d.h" #include "scene/resources/surface_tool.h" #include "scene/resources/world_margin_shape_3d.h" @@ -381,7 +381,7 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Mapset_size(Vector3(2, 2, 2)); colshape->set_shape(boxShape); } else if (empty_draw_type == "SINGLE_ARROW") { - RayShape3D *rayShape = memnew(RayShape3D); + SeparationRayShape3D *rayShape = memnew(SeparationRayShape3D); rayShape->set_length(1); colshape->set_shape(rayShape); Object::cast_to(sb)->rotate_x(Math_PI / 2); diff --git a/editor/plugins/collision_shape_2d_editor_plugin.cpp b/editor/plugins/collision_shape_2d_editor_plugin.cpp index bfb7a68c357..bfcc2936250 100644 --- a/editor/plugins/collision_shape_2d_editor_plugin.cpp +++ b/editor/plugins/collision_shape_2d_editor_plugin.cpp @@ -36,9 +36,9 @@ #include "scene/resources/circle_shape_2d.h" #include "scene/resources/concave_polygon_shape_2d.h" #include "scene/resources/convex_polygon_shape_2d.h" -#include "scene/resources/ray_shape_2d.h" #include "scene/resources/rectangle_shape_2d.h" #include "scene/resources/segment_shape_2d.h" +#include "scene/resources/separation_ray_shape_2d.h" #include "scene/resources/world_margin_shape_2d.h" void CollisionShape2DEditor::_node_removed(Node *p_node) { @@ -81,8 +81,8 @@ Variant CollisionShape2DEditor::get_handle_value(int idx) const { } break; - case RAY_SHAPE: { - Ref ray = node->get_shape(); + case SEPARATION_RAY_SHAPE: { + Ref ray = node->get_shape(); if (idx == 0) { return ray->get_length(); @@ -162,8 +162,8 @@ void CollisionShape2DEditor::set_handle(int idx, Point2 &p_point) { } break; - case RAY_SHAPE: { - Ref ray = node->get_shape(); + case SEPARATION_RAY_SHAPE: { + Ref ray = node->get_shape(); ray->set_length(Math::abs(p_point.y)); @@ -272,8 +272,8 @@ void CollisionShape2DEditor::commit_handle(int idx, Variant &p_org) { } break; - case RAY_SHAPE: { - Ref ray = node->get_shape(); + case SEPARATION_RAY_SHAPE: { + Ref ray = node->get_shape(); undo_redo->add_do_method(ray.ptr(), "set_length", ray->get_length()); undo_redo->add_do_method(canvas_item_editor, "update_viewport"); @@ -423,8 +423,8 @@ void CollisionShape2DEditor::_get_current_shape_type() { shape_type = CONVEX_POLYGON_SHAPE; } else if (Object::cast_to(*s)) { shape_type = WORLD_MARGIN_SHAPE; - } else if (Object::cast_to(*s)) { - shape_type = RAY_SHAPE; + } else if (Object::cast_to(*s)) { + shape_type = SEPARATION_RAY_SHAPE; } else if (Object::cast_to(*s)) { shape_type = RECTANGLE_SHAPE; } else if (Object::cast_to(*s)) { @@ -502,8 +502,8 @@ void CollisionShape2DEditor::forward_canvas_draw_over_viewport(Control *p_overla } break; - case RAY_SHAPE: { - Ref shape = node->get_shape(); + case SEPARATION_RAY_SHAPE: { + Ref shape = node->get_shape(); handles.resize(1); handles.write[0] = Point2(0, shape->get_length()); diff --git a/editor/plugins/collision_shape_2d_editor_plugin.h b/editor/plugins/collision_shape_2d_editor_plugin.h index eab80a419ba..421e674df8d 100644 --- a/editor/plugins/collision_shape_2d_editor_plugin.h +++ b/editor/plugins/collision_shape_2d_editor_plugin.h @@ -47,7 +47,7 @@ class CollisionShape2DEditor : public Control { CONCAVE_POLYGON_SHAPE, CONVEX_POLYGON_SHAPE, WORLD_MARGIN_SHAPE, - RAY_SHAPE, + SEPARATION_RAY_SHAPE, RECTANGLE_SHAPE, SEGMENT_SHAPE }; diff --git a/editor/plugins/node_3d_editor_gizmos.cpp b/editor/plugins/node_3d_editor_gizmos.cpp index a23886b9e78..d04e88e915c 100644 --- a/editor/plugins/node_3d_editor_gizmos.cpp +++ b/editor/plugins/node_3d_editor_gizmos.cpp @@ -66,7 +66,7 @@ #include "scene/resources/cylinder_shape_3d.h" #include "scene/resources/height_map_shape_3d.h" #include "scene/resources/primitive_meshes.h" -#include "scene/resources/ray_shape_3d.h" +#include "scene/resources/separation_ray_shape_3d.h" #include "scene/resources/sphere_shape_3d.h" #include "scene/resources/surface_tool.h" #include "scene/resources/world_margin_shape_3d.h" @@ -4068,7 +4068,7 @@ String CollisionShape3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_g return p_id == 0 ? "Radius" : "Height"; } - if (Object::cast_to(*s)) { + if (Object::cast_to(*s)) { return "Length"; } @@ -4103,8 +4103,8 @@ Variant CollisionShape3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p return p_id == 0 ? cs2->get_radius() : cs2->get_height(); } - if (Object::cast_to(*s)) { - Ref cs2 = s; + if (Object::cast_to(*s)) { + Ref cs2 = s; return cs2->get_length(); } @@ -4143,8 +4143,8 @@ void CollisionShape3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, i ss->set_radius(d); } - if (Object::cast_to(*s)) { - Ref rs = s; + if (Object::cast_to(*s)) { + Ref rs = s; Vector3 ra, rb; Geometry3D::get_closest_points_between_segments(Vector3(), Vector3(0, 0, 4096), sg[0], sg[1], ra, rb); float d = ra.z; @@ -4314,15 +4314,15 @@ void CollisionShape3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo ur->commit_action(); } - if (Object::cast_to(*s)) { - Ref ss = s; + if (Object::cast_to(*s)) { + Ref ss = s; if (p_cancel) { ss->set_length(p_restore); return; } UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo(); - ur->create_action(TTR("Change Ray Shape Length")); + ur->create_action(TTR("Change Separation Ray Shape Length")); ur->add_do_method(ss.ptr(), "set_length", ss->get_length()); ur->add_undo_method(ss.ptr(), "set_length", p_restore); ur->commit_action(); @@ -4597,8 +4597,8 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { p_gizmo->add_collision_segments(cs2->get_debug_mesh_lines()); } - if (Object::cast_to(*s)) { - Ref rs = s; + if (Object::cast_to(*s)) { + Ref rs = s; Vector points; points.push_back(Vector3()); diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index f0b799e4d2d..25d3f6a3e76 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -157,11 +157,11 @@ #include "scene/resources/physics_material.h" #include "scene/resources/polygon_path_finder.h" #include "scene/resources/primitive_meshes.h" -#include "scene/resources/ray_shape_2d.h" -#include "scene/resources/ray_shape_3d.h" #include "scene/resources/rectangle_shape_2d.h" #include "scene/resources/resource_format_text.h" #include "scene/resources/segment_shape_2d.h" +#include "scene/resources/separation_ray_shape_2d.h" +#include "scene/resources/separation_ray_shape_3d.h" #include "scene/resources/skeleton_modification_2d.h" #include "scene/resources/skeleton_modification_2d_ccdik.h" #include "scene/resources/skeleton_modification_2d_fabrik.h" @@ -754,7 +754,7 @@ void register_scene_types() { OS::get_singleton()->yield(); //may take time to init GDREGISTER_VIRTUAL_CLASS(Shape3D); - GDREGISTER_CLASS(RayShape3D); + GDREGISTER_CLASS(SeparationRayShape3D); GDREGISTER_CLASS(SphereShape3D); GDREGISTER_CLASS(BoxShape3D); GDREGISTER_CLASS(CapsuleShape3D); @@ -843,7 +843,7 @@ void register_scene_types() { GDREGISTER_VIRTUAL_CLASS(Shape2D); GDREGISTER_CLASS(WorldMarginShape2D); GDREGISTER_CLASS(SegmentShape2D); - GDREGISTER_CLASS(RayShape2D); + GDREGISTER_CLASS(SeparationRayShape2D); GDREGISTER_CLASS(CircleShape2D); GDREGISTER_CLASS(RectangleShape2D); GDREGISTER_CLASS(CapsuleShape2D); @@ -964,7 +964,8 @@ void register_scene_types() { ClassDB::add_compatibility_class("ProceduralSky", "Sky"); ClassDB::add_compatibility_class("ProximityGroup", "ProximityGroup3D"); ClassDB::add_compatibility_class("RayCast", "RayCast3D"); - ClassDB::add_compatibility_class("RayShape", "RayShape3D"); + ClassDB::add_compatibility_class("RayShape", "SeparationRayShape3D"); + ClassDB::add_compatibility_class("RayShape2D", "SeparationRayShape2D"); ClassDB::add_compatibility_class("RemoteTransform", "RemoteTransform3D"); ClassDB::add_compatibility_class("RigidBody", "RigidBody3D"); ClassDB::add_compatibility_class("Shape", "Shape3D"); diff --git a/scene/resources/ray_shape_2d.cpp b/scene/resources/separation_ray_shape_2d.cpp similarity index 79% rename from scene/resources/ray_shape_2d.cpp rename to scene/resources/separation_ray_shape_2d.cpp index 2390a13bfab..0acd6d268d7 100644 --- a/scene/resources/ray_shape_2d.cpp +++ b/scene/resources/separation_ray_shape_2d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* ray_shape_2d.cpp */ +/* separation_ray_shape_2d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,12 +28,12 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "ray_shape_2d.h" +#include "separation_ray_shape_2d.h" #include "servers/physics_server_2d.h" #include "servers/rendering_server.h" -void RayShape2D::_update_shape() { +void SeparationRayShape2D::_update_shape() { Dictionary d; d["length"] = length; d["slide_on_slope"] = slide_on_slope; @@ -41,7 +41,7 @@ void RayShape2D::_update_shape() { emit_changed(); } -void RayShape2D::draw(const RID &p_to_rid, const Color &p_color) { +void SeparationRayShape2D::draw(const RID &p_to_rid, const Color &p_color) { const Vector2 target_position = Vector2(0, get_length()); const float max_arrow_size = 6; @@ -72,7 +72,7 @@ void RayShape2D::draw(const RID &p_to_rid, const Color &p_color) { RS::get_singleton()->canvas_item_add_primitive(p_to_rid, pts, cols, Vector(), RID()); } -Rect2 RayShape2D::get_rect() const { +Rect2 SeparationRayShape2D::get_rect() const { Rect2 rect; rect.position = Vector2(); rect.expand_to(Vector2(0, length)); @@ -80,40 +80,40 @@ Rect2 RayShape2D::get_rect() const { return rect; } -real_t RayShape2D::get_enclosing_radius() const { +real_t SeparationRayShape2D::get_enclosing_radius() const { return length; } -void RayShape2D::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_length", "length"), &RayShape2D::set_length); - ClassDB::bind_method(D_METHOD("get_length"), &RayShape2D::get_length); +void SeparationRayShape2D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_length", "length"), &SeparationRayShape2D::set_length); + ClassDB::bind_method(D_METHOD("get_length"), &SeparationRayShape2D::get_length); - ClassDB::bind_method(D_METHOD("set_slide_on_slope", "active"), &RayShape2D::set_slide_on_slope); - ClassDB::bind_method(D_METHOD("get_slide_on_slope"), &RayShape2D::get_slide_on_slope); + ClassDB::bind_method(D_METHOD("set_slide_on_slope", "active"), &SeparationRayShape2D::set_slide_on_slope); + ClassDB::bind_method(D_METHOD("get_slide_on_slope"), &SeparationRayShape2D::get_slide_on_slope); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "length"), "set_length", "get_length"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "slide_on_slope"), "set_slide_on_slope", "get_slide_on_slope"); } -void RayShape2D::set_length(real_t p_length) { +void SeparationRayShape2D::set_length(real_t p_length) { length = p_length; _update_shape(); } -real_t RayShape2D::get_length() const { +real_t SeparationRayShape2D::get_length() const { return length; } -void RayShape2D::set_slide_on_slope(bool p_active) { +void SeparationRayShape2D::set_slide_on_slope(bool p_active) { slide_on_slope = p_active; _update_shape(); } -bool RayShape2D::get_slide_on_slope() const { +bool SeparationRayShape2D::get_slide_on_slope() const { return slide_on_slope; } -RayShape2D::RayShape2D() : - Shape2D(PhysicsServer2D::get_singleton()->ray_shape_create()) { +SeparationRayShape2D::SeparationRayShape2D() : + Shape2D(PhysicsServer2D::get_singleton()->separation_ray_shape_create()) { _update_shape(); } diff --git a/scene/resources/ray_shape_2d.h b/scene/resources/separation_ray_shape_2d.h similarity index 90% rename from scene/resources/ray_shape_2d.h rename to scene/resources/separation_ray_shape_2d.h index 0895605ddf4..5b74e6c727e 100644 --- a/scene/resources/ray_shape_2d.h +++ b/scene/resources/separation_ray_shape_2d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* ray_shape_2d.h */ +/* separation_ray_shape_2d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,13 +28,13 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RAY_SHAPE_2D_H -#define RAY_SHAPE_2D_H +#ifndef SEPARATION_RAY_SHAPE_2D_H +#define SEPARATION_RAY_SHAPE_2D_H #include "scene/resources/shape_2d.h" -class RayShape2D : public Shape2D { - GDCLASS(RayShape2D, Shape2D); +class SeparationRayShape2D : public Shape2D { + GDCLASS(SeparationRayShape2D, Shape2D); real_t length = 20.0; bool slide_on_slope = false; @@ -55,7 +55,7 @@ public: virtual Rect2 get_rect() const override; virtual real_t get_enclosing_radius() const override; - RayShape2D(); + SeparationRayShape2D(); }; -#endif // RAY_SHAPE_2D_H +#endif // SEPARATION_RAY_SHAPE_2D_H diff --git a/scene/resources/ray_shape_3d.cpp b/scene/resources/separation_ray_shape_3d.cpp similarity index 77% rename from scene/resources/ray_shape_3d.cpp rename to scene/resources/separation_ray_shape_3d.cpp index 5d73fb8d809..376e04c8449 100644 --- a/scene/resources/ray_shape_3d.cpp +++ b/scene/resources/separation_ray_shape_3d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* ray_shape_3d.cpp */ +/* separation_ray_shape_3d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,11 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "ray_shape_3d.h" +#include "separation_ray_shape_3d.h" #include "servers/physics_server_3d.h" -Vector RayShape3D::get_debug_mesh_lines() const { +Vector SeparationRayShape3D::get_debug_mesh_lines() const { Vector points; points.push_back(Vector3()); points.push_back(Vector3(0, 0, get_length())); @@ -40,11 +40,11 @@ Vector RayShape3D::get_debug_mesh_lines() const { return points; } -real_t RayShape3D::get_enclosing_radius() const { +real_t SeparationRayShape3D::get_enclosing_radius() const { return length; } -void RayShape3D::_update_shape() { +void SeparationRayShape3D::_update_shape() { Dictionary d; d["length"] = length; d["slide_on_slope"] = slide_on_slope; @@ -52,39 +52,39 @@ void RayShape3D::_update_shape() { Shape3D::_update_shape(); } -void RayShape3D::set_length(float p_length) { +void SeparationRayShape3D::set_length(float p_length) { length = p_length; _update_shape(); notify_change_to_owners(); } -float RayShape3D::get_length() const { +float SeparationRayShape3D::get_length() const { return length; } -void RayShape3D::set_slide_on_slope(bool p_active) { +void SeparationRayShape3D::set_slide_on_slope(bool p_active) { slide_on_slope = p_active; _update_shape(); notify_change_to_owners(); } -bool RayShape3D::get_slide_on_slope() const { +bool SeparationRayShape3D::get_slide_on_slope() const { return slide_on_slope; } -void RayShape3D::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_length", "length"), &RayShape3D::set_length); - ClassDB::bind_method(D_METHOD("get_length"), &RayShape3D::get_length); +void SeparationRayShape3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_length", "length"), &SeparationRayShape3D::set_length); + ClassDB::bind_method(D_METHOD("get_length"), &SeparationRayShape3D::get_length); - ClassDB::bind_method(D_METHOD("set_slide_on_slope", "active"), &RayShape3D::set_slide_on_slope); - ClassDB::bind_method(D_METHOD("get_slide_on_slope"), &RayShape3D::get_slide_on_slope); + ClassDB::bind_method(D_METHOD("set_slide_on_slope", "active"), &SeparationRayShape3D::set_slide_on_slope); + ClassDB::bind_method(D_METHOD("get_slide_on_slope"), &SeparationRayShape3D::get_slide_on_slope); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "length", PROPERTY_HINT_RANGE, "0,4096,0.001"), "set_length", "get_length"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "slide_on_slope"), "set_slide_on_slope", "get_slide_on_slope"); } -RayShape3D::RayShape3D() : - Shape3D(PhysicsServer3D::get_singleton()->shape_create(PhysicsServer3D::SHAPE_RAY)) { +SeparationRayShape3D::SeparationRayShape3D() : + Shape3D(PhysicsServer3D::get_singleton()->shape_create(PhysicsServer3D::SHAPE_SEPARATION_RAY)) { /* Code copied from setters to prevent the use of uninitialized variables */ _update_shape(); notify_change_to_owners(); diff --git a/scene/resources/ray_shape_3d.h b/scene/resources/separation_ray_shape_3d.h similarity index 90% rename from scene/resources/ray_shape_3d.h rename to scene/resources/separation_ray_shape_3d.h index 53694081850..54058b60952 100644 --- a/scene/resources/ray_shape_3d.h +++ b/scene/resources/separation_ray_shape_3d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* ray_shape_3d.h */ +/* separation_ray_shape_3d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,12 +28,12 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RAY_SHAPE_H -#define RAY_SHAPE_H +#ifndef SEPARATION_RAY_SHAPE_H +#define SEPARATION_RAY_SHAPE_H #include "scene/resources/shape_3d.h" -class RayShape3D : public Shape3D { - GDCLASS(RayShape3D, Shape3D); +class SeparationRayShape3D : public Shape3D { + GDCLASS(SeparationRayShape3D, Shape3D); float length = 1.0; bool slide_on_slope = false; @@ -51,6 +51,6 @@ public: virtual Vector get_debug_mesh_lines() const override; virtual real_t get_enclosing_radius() const override; - RayShape3D(); + SeparationRayShape3D(); }; -#endif // RAY_SHAPE_H +#endif // SEPARATION_RAY_SHAPE_H diff --git a/servers/physics_2d/collision_solver_2d_sat.cpp b/servers/physics_2d/collision_solver_2d_sat.cpp index 3dde881c4d0..b1aee01bde8 100644 --- a/servers/physics_2d/collision_solver_2d_sat.cpp +++ b/servers/physics_2d/collision_solver_2d_sat.cpp @@ -1115,13 +1115,13 @@ bool sat_2d_calculate_penetration(const Shape2DSW *p_shape_A, const Transform2D PhysicsServer2D::ShapeType type_A = p_shape_A->get_type(); ERR_FAIL_COND_V(type_A == PhysicsServer2D::SHAPE_WORLD_MARGIN, false); - ERR_FAIL_COND_V(type_A == PhysicsServer2D::SHAPE_RAY, false); + ERR_FAIL_COND_V(type_A == PhysicsServer2D::SHAPE_SEPARATION_RAY, false); ERR_FAIL_COND_V(p_shape_A->is_concave(), false); PhysicsServer2D::ShapeType type_B = p_shape_B->get_type(); ERR_FAIL_COND_V(type_B == PhysicsServer2D::SHAPE_WORLD_MARGIN, false); - ERR_FAIL_COND_V(type_B == PhysicsServer2D::SHAPE_RAY, false); + ERR_FAIL_COND_V(type_B == PhysicsServer2D::SHAPE_SEPARATION_RAY, false); ERR_FAIL_COND_V(p_shape_B->is_concave(), false); static const CollisionFunc collision_table[5][5] = { diff --git a/servers/physics_2d/collision_solver_2d_sw.cpp b/servers/physics_2d/collision_solver_2d_sw.cpp index 5337c8af568..f7a8593c500 100644 --- a/servers/physics_2d/collision_solver_2d_sw.cpp +++ b/servers/physics_2d/collision_solver_2d_sw.cpp @@ -73,9 +73,9 @@ bool CollisionSolver2DSW::solve_static_world_margin(const Shape2DSW *p_shape_A, return found; } -bool CollisionSolver2DSW::solve_raycast(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 RayShape2DSW *ray = static_cast(p_shape_A); - if (p_shape_B->get_type() == PhysicsServer2D::SHAPE_RAY) { +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(p_shape_A); + if (p_shape_B->get_type() == PhysicsServer2D::SHAPE_SEPARATION_RAY) { return false; } @@ -236,15 +236,15 @@ bool CollisionSolver2DSW::solve(const Shape2DSW *p_shape_A, const Transform2D &p return solve_static_world_margin(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false); } - } else if (type_A == PhysicsServer2D::SHAPE_RAY) { - if (type_B == PhysicsServer2D::SHAPE_RAY) { + } else if (type_A == PhysicsServer2D::SHAPE_SEPARATION_RAY) { + if (type_B == PhysicsServer2D::SHAPE_SEPARATION_RAY) { return false; //no ray-ray } if (swap) { - return solve_raycast(p_shape_B, p_motion_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true, r_sep_axis, p_margin_B); + return solve_separation_ray(p_shape_B, p_motion_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true, r_sep_axis, p_margin_B); } else { - return solve_raycast(p_shape_A, p_motion_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false, r_sep_axis, p_margin_A); + return solve_separation_ray(p_shape_A, p_motion_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false, r_sep_axis, p_margin_A); } } else if (concave_B) { diff --git a/servers/physics_2d/collision_solver_2d_sw.h b/servers/physics_2d/collision_solver_2d_sw.h index c2f13d0e131..0678e3526c7 100644 --- a/servers/physics_2d/collision_solver_2d_sw.h +++ b/servers/physics_2d/collision_solver_2d_sw.h @@ -41,7 +41,7 @@ private: static bool solve_static_world_margin(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 void 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_raycast(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_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); 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); diff --git a/servers/physics_2d/physics_server_2d_sw.cpp b/servers/physics_2d/physics_server_2d_sw.cpp index 5cb67d5ab95..813e5ddc177 100644 --- a/servers/physics_2d/physics_server_2d_sw.cpp +++ b/servers/physics_2d/physics_server_2d_sw.cpp @@ -45,8 +45,8 @@ RID PhysicsServer2DSW::_shape_create(ShapeType p_shape) { case SHAPE_WORLD_MARGIN: { shape = memnew(WorldMarginShape2DSW); } break; - case SHAPE_RAY: { - shape = memnew(RayShape2DSW); + case SHAPE_SEPARATION_RAY: { + shape = memnew(SeparationRayShape2DSW); } break; case SHAPE_SEGMENT: { shape = memnew(SegmentShape2DSW); @@ -82,8 +82,8 @@ RID PhysicsServer2DSW::world_margin_shape_create() { return _shape_create(SHAPE_WORLD_MARGIN); } -RID PhysicsServer2DSW::ray_shape_create() { - return _shape_create(SHAPE_RAY); +RID PhysicsServer2DSW::separation_ray_shape_create() { + return _shape_create(SHAPE_SEPARATION_RAY); } RID PhysicsServer2DSW::segment_shape_create() { diff --git a/servers/physics_2d/physics_server_2d_sw.h b/servers/physics_2d/physics_server_2d_sw.h index 6ea5e445bcf..c5b6d550d7a 100644 --- a/servers/physics_2d/physics_server_2d_sw.h +++ b/servers/physics_2d/physics_server_2d_sw.h @@ -88,7 +88,7 @@ public: }; virtual RID world_margin_shape_create() override; - virtual RID ray_shape_create() override; + virtual RID separation_ray_shape_create() override; virtual RID segment_shape_create() override; virtual RID circle_shape_create() override; virtual RID rectangle_shape_create() override; diff --git a/servers/physics_2d/physics_server_2d_wrap_mt.h b/servers/physics_2d/physics_server_2d_wrap_mt.h index 7b1cda169dc..05d4ac64b0b 100644 --- a/servers/physics_2d/physics_server_2d_wrap_mt.h +++ b/servers/physics_2d/physics_server_2d_wrap_mt.h @@ -80,7 +80,7 @@ public: //FUNC1RID(shape,ShapeType); todo fix FUNCRID(world_margin_shape) - FUNCRID(ray_shape) + FUNCRID(separation_ray_shape) FUNCRID(segment_shape) FUNCRID(circle_shape) FUNCRID(rectangle_shape) diff --git a/servers/physics_2d/shape_2d_sw.cpp b/servers/physics_2d/shape_2d_sw.cpp index dae56694885..757b2e05839 100644 --- a/servers/physics_2d/shape_2d_sw.cpp +++ b/servers/physics_2d/shape_2d_sw.cpp @@ -143,7 +143,7 @@ Variant WorldMarginShape2DSW::get_data() const { /*********************************************************/ /*********************************************************/ -void RayShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const { +void SeparationRayShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const { r_amount = 1; if (p_normal.y > 0) { @@ -153,26 +153,26 @@ void RayShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_supports, in } } -bool RayShape2DSW::contains_point(const Vector2 &p_point) const { +bool SeparationRayShape2DSW::contains_point(const Vector2 &p_point) const { return false; } -bool RayShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const { +bool SeparationRayShape2DSW::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 RayShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const { +real_t SeparationRayShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const { return 0; //rays are mass-less } -void RayShape2DSW::set_data(const Variant &p_data) { +void SeparationRayShape2DSW::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 RayShape2DSW::get_data() const { +Variant SeparationRayShape2DSW::get_data() const { Dictionary d; d["length"] = length; d["slide_on_slope"] = slide_on_slope; diff --git a/servers/physics_2d/shape_2d_sw.h b/servers/physics_2d/shape_2d_sw.h index 541d35dae92..bc321adb420 100644 --- a/servers/physics_2d/shape_2d_sw.h +++ b/servers/physics_2d/shape_2d_sw.h @@ -179,7 +179,7 @@ public: } }; -class RayShape2DSW : public Shape2DSW { +class SeparationRayShape2DSW : public Shape2DSW { real_t length; bool slide_on_slope; @@ -187,19 +187,19 @@ public: _FORCE_INLINE_ real_t get_length() const { return length; } _FORCE_INLINE_ bool get_slide_on_slope() const { return slide_on_slope; } - virtual PhysicsServer2D::ShapeType get_type() const { return PhysicsServer2D::SHAPE_RAY; } + virtual PhysicsServer2D::ShapeType get_type() const override { return PhysicsServer2D::SHAPE_SEPARATION_RAY; } virtual bool allows_one_way_collision() const override { return false; } - virtual void project_rangev(const Vector2 &p_normal, const Transform2D &p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal, p_transform, r_min, r_max); } - virtual void get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const; + virtual void project_rangev(const Vector2 &p_normal, const Transform2D &p_transform, real_t &r_min, real_t &r_max) const override { project_range(p_normal, p_transform, r_min, r_max); } + virtual void get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const override; - virtual bool contains_point(const Vector2 &p_point) const; - virtual bool intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const; - virtual real_t get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const; + virtual bool contains_point(const Vector2 &p_point) const override; + virtual bool intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const override; + virtual real_t get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const override; - virtual void set_data(const Variant &p_data); - virtual Variant get_data() const; + virtual void set_data(const Variant &p_data) override; + virtual Variant get_data() const override; _FORCE_INLINE_ void project_range(const Vector2 &p_normal, const Transform2D &p_transform, real_t &r_min, real_t &r_max) const { //real large @@ -212,8 +212,8 @@ public: DEFAULT_PROJECT_RANGE_CAST - _FORCE_INLINE_ RayShape2DSW() {} - _FORCE_INLINE_ RayShape2DSW(real_t p_length) { length = p_length; } + _FORCE_INLINE_ SeparationRayShape2DSW() {} + _FORCE_INLINE_ SeparationRayShape2DSW(real_t p_length) { length = p_length; } }; class SegmentShape2DSW : public Shape2DSW { diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp index 92b87cea23a..c0493749e03 100644 --- a/servers/physics_2d/space_2d_sw.cpp +++ b/servers/physics_2d/space_2d_sw.cpp @@ -729,9 +729,9 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co // Colliding separation rays allows to properly snap to the ground, // otherwise it's not needed in regular motion. - if (!p_collide_separation_ray && (body_shape->get_type() == PhysicsServer2D::SHAPE_RAY)) { + if (!p_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(body_shape)->get_slide_on_slope()) { + if (!static_cast(body_shape)->get_slide_on_slope()) { continue; } } diff --git a/servers/physics_3d/collision_solver_3d_sat.cpp b/servers/physics_3d/collision_solver_3d_sat.cpp index 547f5f3e47e..de81348b4ef 100644 --- a/servers/physics_3d/collision_solver_3d_sat.cpp +++ b/servers/physics_3d/collision_solver_3d_sat.cpp @@ -2273,13 +2273,13 @@ bool sat_calculate_penetration(const Shape3DSW *p_shape_A, const Transform3D &p_ PhysicsServer3D::ShapeType type_A = p_shape_A->get_type(); ERR_FAIL_COND_V(type_A == PhysicsServer3D::SHAPE_PLANE, false); - ERR_FAIL_COND_V(type_A == PhysicsServer3D::SHAPE_RAY, false); + ERR_FAIL_COND_V(type_A == PhysicsServer3D::SHAPE_SEPARATION_RAY, false); ERR_FAIL_COND_V(p_shape_A->is_concave(), false); PhysicsServer3D::ShapeType type_B = p_shape_B->get_type(); ERR_FAIL_COND_V(type_B == PhysicsServer3D::SHAPE_PLANE, false); - ERR_FAIL_COND_V(type_B == PhysicsServer3D::SHAPE_RAY, false); + ERR_FAIL_COND_V(type_B == PhysicsServer3D::SHAPE_SEPARATION_RAY, false); ERR_FAIL_COND_V(p_shape_B->is_concave(), false); static const CollisionFunc collision_table[6][6] = { diff --git a/servers/physics_3d/collision_solver_3d_sw.cpp b/servers/physics_3d/collision_solver_3d_sw.cpp index 4a6a07534be..e7b79e84503 100644 --- a/servers/physics_3d/collision_solver_3d_sw.cpp +++ b/servers/physics_3d/collision_solver_3d_sw.cpp @@ -89,8 +89,8 @@ bool CollisionSolver3DSW::solve_static_plane(const Shape3DSW *p_shape_A, const T return found; } -bool CollisionSolver3DSW::solve_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 RayShape3DSW *ray = static_cast(p_shape_A); +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(p_shape_A); Vector3 from = p_transform_A.origin; Vector3 to = from + p_transform_A.basis.get_axis(2) * (ray->get_length() + p_margin); @@ -361,7 +361,7 @@ bool CollisionSolver3DSW::solve_static(const Shape3DSW *p_shape_A, const Transfo if (type_B == PhysicsServer3D::SHAPE_PLANE) { return false; } - if (type_B == PhysicsServer3D::SHAPE_RAY) { + if (type_B == PhysicsServer3D::SHAPE_SEPARATION_RAY) { return false; } if (type_B == PhysicsServer3D::SHAPE_SOFT_BODY) { @@ -374,15 +374,15 @@ bool CollisionSolver3DSW::solve_static(const Shape3DSW *p_shape_A, const Transfo return solve_static_plane(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false); } - } else if (type_A == PhysicsServer3D::SHAPE_RAY) { - if (type_B == PhysicsServer3D::SHAPE_RAY) { + } else if (type_A == PhysicsServer3D::SHAPE_SEPARATION_RAY) { + if (type_B == PhysicsServer3D::SHAPE_SEPARATION_RAY) { return false; } if (swap) { - return solve_ray(p_shape_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true, p_margin_B); + return solve_separation_ray(p_shape_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true, p_margin_B); } else { - return solve_ray(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false, p_margin_A); + return solve_separation_ray(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false, p_margin_A); } } else if (type_B == PhysicsServer3D::SHAPE_SOFT_BODY) { diff --git a/servers/physics_3d/collision_solver_3d_sw.h b/servers/physics_3d/collision_solver_3d_sw.h index cbde9ce18fb..c1a69e708fc 100644 --- a/servers/physics_3d/collision_solver_3d_sw.h +++ b/servers/physics_3d/collision_solver_3d_sw.h @@ -43,7 +43,7 @@ private: static void soft_body_concave_callback(void *p_userdata, Shape3DSW *p_convex); static void concave_callback(void *p_userdata, Shape3DSW *p_convex); static bool solve_static_plane(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_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_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 void concave_distance_callback(void *p_userdata, Shape3DSW *p_convex); diff --git a/servers/physics_3d/physics_server_3d_sw.cpp b/servers/physics_3d/physics_server_3d_sw.cpp index 1cf6b12623a..fbc6f7eee82 100644 --- a/servers/physics_3d/physics_server_3d_sw.cpp +++ b/servers/physics_3d/physics_server_3d_sw.cpp @@ -48,8 +48,8 @@ RID PhysicsServer3DSW::plane_shape_create() { shape->set_self(rid); return rid; } -RID PhysicsServer3DSW::ray_shape_create() { - Shape3DSW *shape = memnew(RayShape3DSW); +RID PhysicsServer3DSW::separation_ray_shape_create() { + Shape3DSW *shape = memnew(SeparationRayShape3DSW); RID rid = shape_owner.make_rid(shape); shape->set_self(rid); return rid; diff --git a/servers/physics_3d/physics_server_3d_sw.h b/servers/physics_3d/physics_server_3d_sw.h index 341ce06a5d1..a18593c90c3 100644 --- a/servers/physics_3d/physics_server_3d_sw.h +++ b/servers/physics_3d/physics_server_3d_sw.h @@ -83,7 +83,7 @@ public: static void _shape_col_cbk(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata); virtual RID plane_shape_create() override; - virtual RID ray_shape_create() override; + virtual RID separation_ray_shape_create() override; virtual RID sphere_shape_create() override; virtual RID box_shape_create() override; virtual RID capsule_shape_create() override; diff --git a/servers/physics_3d/physics_server_3d_wrap_mt.h b/servers/physics_3d/physics_server_3d_wrap_mt.h index 24bf203d518..674c52d4a3e 100644 --- a/servers/physics_3d/physics_server_3d_wrap_mt.h +++ b/servers/physics_3d/physics_server_3d_wrap_mt.h @@ -79,7 +79,7 @@ public: //FUNC1RID(shape,ShapeType); todo fix FUNCRID(plane_shape) - FUNCRID(ray_shape) + FUNCRID(separation_ray_shape) FUNCRID(sphere_shape) FUNCRID(box_shape) FUNCRID(capsule_shape) diff --git a/servers/physics_3d/shape_3d_sw.cpp b/servers/physics_3d/shape_3d_sw.cpp index fcc97f56a33..0794e7888e7 100644 --- a/servers/physics_3d/shape_3d_sw.cpp +++ b/servers/physics_3d/shape_3d_sw.cpp @@ -166,21 +166,21 @@ PlaneShape3DSW::PlaneShape3DSW() { // -real_t RayShape3DSW::get_length() const { +real_t SeparationRayShape3DSW::get_length() const { return length; } -bool RayShape3DSW::get_slide_on_slope() const { +bool SeparationRayShape3DSW::get_slide_on_slope() const { return slide_on_slope; } -void RayShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const { +void SeparationRayShape3DSW::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 RayShape3DSW::get_support(const Vector3 &p_normal) const { +Vector3 SeparationRayShape3DSW::get_support(const Vector3 &p_normal) const { if (p_normal.z > 0) { return Vector3(0, 0, length); } else { @@ -188,7 +188,7 @@ Vector3 RayShape3DSW::get_support(const Vector3 &p_normal) const { } } -void RayShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const { +void SeparationRayShape3DSW::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; @@ -205,15 +205,15 @@ void RayShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_s } } -bool RayShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { +bool SeparationRayShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { return false; //simply not possible } -bool RayShape3DSW::intersect_point(const Vector3 &p_point) const { +bool SeparationRayShape3DSW::intersect_point(const Vector3 &p_point) const { return false; //simply not possible } -Vector3 RayShape3DSW::get_closest_point_to(const Vector3 &p_point) const { +Vector3 SeparationRayShape3DSW::get_closest_point_to(const Vector3 &p_point) const { Vector3 s[2] = { Vector3(0, 0, 0), Vector3(0, 0, length) @@ -222,29 +222,29 @@ Vector3 RayShape3DSW::get_closest_point_to(const Vector3 &p_point) const { return Geometry3D::get_closest_point_to_segment(p_point, s); } -Vector3 RayShape3DSW::get_moment_of_inertia(real_t p_mass) const { +Vector3 SeparationRayShape3DSW::get_moment_of_inertia(real_t p_mass) const { return Vector3(); } -void RayShape3DSW::_setup(real_t p_length, bool p_slide_on_slope) { +void SeparationRayShape3DSW::_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 RayShape3DSW::set_data(const Variant &p_data) { +void SeparationRayShape3DSW::set_data(const Variant &p_data) { Dictionary d = p_data; _setup(d["length"], d["slide_on_slope"]); } -Variant RayShape3DSW::get_data() const { +Variant SeparationRayShape3DSW::get_data() const { Dictionary d; d["length"] = length; d["slide_on_slope"] = slide_on_slope; return d; } -RayShape3DSW::RayShape3DSW() { +SeparationRayShape3DSW::SeparationRayShape3DSW() { length = 1; slide_on_slope = false; } diff --git a/servers/physics_3d/shape_3d_sw.h b/servers/physics_3d/shape_3d_sw.h index a693288f7eb..dc35c3b172f 100644 --- a/servers/physics_3d/shape_3d_sw.h +++ b/servers/physics_3d/shape_3d_sw.h @@ -117,24 +117,24 @@ class PlaneShape3DSW : public Shape3DSW { public: Plane get_plane() const; - virtual real_t get_area() const { return INFINITY; } - virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_PLANE; } - virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const; - 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 { r_amount = 0; } + virtual real_t get_area() const override { return INFINITY; } + virtual PhysicsServer3D::ShapeType get_type() const override { return PhysicsServer3D::SHAPE_PLANE; } + 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; - 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; + virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) 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; - virtual void set_data(const Variant &p_data); - virtual Variant get_data() const; + virtual void set_data(const Variant &p_data) override; + virtual Variant get_data() const override; PlaneShape3DSW(); }; -class RayShape3DSW : public Shape3DSW { +class SeparationRayShape3DSW : public Shape3DSW { real_t length; bool slide_on_slope; @@ -144,22 +144,22 @@ public: real_t get_length() const; bool get_slide_on_slope() const; - virtual real_t get_area() const { return 0.0; } - virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_RAY; } - virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const; - 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; + virtual real_t get_area() 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; - virtual bool intersect_point(const Vector3 &p_point) const; - virtual Vector3 get_closest_point_to(const Vector3 &p_point) const; + virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) 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; + virtual Vector3 get_moment_of_inertia(real_t p_mass) const override; - virtual void set_data(const Variant &p_data); - virtual Variant get_data() const; + virtual void set_data(const Variant &p_data) override; + virtual Variant get_data() const override; - RayShape3DSW(); + SeparationRayShape3DSW(); }; class SphereShape3DSW : public Shape3DSW { diff --git a/servers/physics_3d/space_3d_sw.cpp b/servers/physics_3d/space_3d_sw.cpp index 4ec03529cf6..37dee436df3 100644 --- a/servers/physics_3d/space_3d_sw.cpp +++ b/servers/physics_3d/space_3d_sw.cpp @@ -718,9 +718,9 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co // Colliding separation rays allows to properly snap to the ground, // otherwise it's not needed in regular motion. - if (!p_collide_separation_ray && (body_shape->get_type() == PhysicsServer3D::SHAPE_RAY)) { + if (!p_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(body_shape)->get_slide_on_slope()) { + if (!static_cast(body_shape)->get_slide_on_slope()) { continue; } } diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp index 2132a7c93df..4660b83f4d0 100644 --- a/servers/physics_server_2d.cpp +++ b/servers/physics_server_2d.cpp @@ -514,7 +514,7 @@ bool PhysicsServer2D::_body_test_motion(RID p_body, const Transform2D &p_from, c void PhysicsServer2D::_bind_methods() { ClassDB::bind_method(D_METHOD("world_margin_shape_create"), &PhysicsServer2D::world_margin_shape_create); - ClassDB::bind_method(D_METHOD("ray_shape_create"), &PhysicsServer2D::ray_shape_create); + ClassDB::bind_method(D_METHOD("separation_ray_shape_create"), &PhysicsServer2D::separation_ray_shape_create); ClassDB::bind_method(D_METHOD("segment_shape_create"), &PhysicsServer2D::segment_shape_create); ClassDB::bind_method(D_METHOD("circle_shape_create"), &PhysicsServer2D::circle_shape_create); ClassDB::bind_method(D_METHOD("rectangle_shape_create"), &PhysicsServer2D::rectangle_shape_create); @@ -676,7 +676,7 @@ void PhysicsServer2D::_bind_methods() { BIND_ENUM_CONSTANT(SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH); BIND_ENUM_CONSTANT(SHAPE_WORLD_MARGIN); - BIND_ENUM_CONSTANT(SHAPE_RAY); + BIND_ENUM_CONSTANT(SHAPE_SEPARATION_RAY); BIND_ENUM_CONSTANT(SHAPE_SEGMENT); BIND_ENUM_CONSTANT(SHAPE_CIRCLE); BIND_ENUM_CONSTANT(SHAPE_RECTANGLE); diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h index 4a453564f1b..9afac0cbd15 100644 --- a/servers/physics_server_2d.h +++ b/servers/physics_server_2d.h @@ -220,7 +220,7 @@ public: enum ShapeType { SHAPE_WORLD_MARGIN, ///< plane:"plane" - SHAPE_RAY, ///< float:"length" + SHAPE_SEPARATION_RAY, ///< float:"length" SHAPE_SEGMENT, ///< float:"length" SHAPE_CIRCLE, ///< float:"radius" SHAPE_RECTANGLE, ///< vec3:"extents" @@ -231,7 +231,7 @@ public: }; virtual RID world_margin_shape_create() = 0; - virtual RID ray_shape_create() = 0; + virtual RID separation_ray_shape_create() = 0; virtual RID segment_shape_create() = 0; virtual RID circle_shape_create() = 0; virtual RID rectangle_shape_create() = 0; diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp index 76d908b5298..6cde4977f49 100644 --- a/servers/physics_server_3d.cpp +++ b/servers/physics_server_3d.cpp @@ -463,8 +463,8 @@ RID PhysicsServer3D::shape_create(ShapeType p_shape) { switch (p_shape) { case SHAPE_PLANE: return plane_shape_create(); - case SHAPE_RAY: - return ray_shape_create(); + case SHAPE_SEPARATION_RAY: + return separation_ray_shape_create(); case SHAPE_SPHERE: return sphere_shape_create(); case SHAPE_BOX: @@ -490,7 +490,7 @@ void PhysicsServer3D::_bind_methods() { #ifndef _3D_DISABLED ClassDB::bind_method(D_METHOD("plane_shape_create"), &PhysicsServer3D::plane_shape_create); - ClassDB::bind_method(D_METHOD("ray_shape_create"), &PhysicsServer3D::ray_shape_create); + ClassDB::bind_method(D_METHOD("separation_ray_shape_create"), &PhysicsServer3D::separation_ray_shape_create); ClassDB::bind_method(D_METHOD("sphere_shape_create"), &PhysicsServer3D::sphere_shape_create); ClassDB::bind_method(D_METHOD("box_shape_create"), &PhysicsServer3D::box_shape_create); ClassDB::bind_method(D_METHOD("capsule_shape_create"), &PhysicsServer3D::capsule_shape_create); @@ -751,7 +751,7 @@ void PhysicsServer3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_process_info", "process_info"), &PhysicsServer3D::get_process_info); BIND_ENUM_CONSTANT(SHAPE_PLANE); - BIND_ENUM_CONSTANT(SHAPE_RAY); + BIND_ENUM_CONSTANT(SHAPE_SEPARATION_RAY); BIND_ENUM_CONSTANT(SHAPE_SPHERE); BIND_ENUM_CONSTANT(SHAPE_BOX); BIND_ENUM_CONSTANT(SHAPE_CAPSULE); diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h index c92e6629df4..8f83e360f22 100644 --- a/servers/physics_server_3d.h +++ b/servers/physics_server_3d.h @@ -222,7 +222,7 @@ public: enum ShapeType { SHAPE_PLANE, ///< plane:"plane" - SHAPE_RAY, ///< float:"length" + SHAPE_SEPARATION_RAY, ///< float:"length" SHAPE_SPHERE, ///< float:"radius" SHAPE_BOX, ///< vec3:"extents" SHAPE_CAPSULE, ///< dict( float:"radius", float:"height"):capsule @@ -237,7 +237,7 @@ public: RID shape_create(ShapeType p_shape); virtual RID plane_shape_create() = 0; - virtual RID ray_shape_create() = 0; + virtual RID separation_ray_shape_create() = 0; virtual RID sphere_shape_create() = 0; virtual RID box_shape_create() = 0; virtual RID capsule_shape_create() = 0;