From 45c7af98625a1751f2a97aaf2a4a17d808b61092 Mon Sep 17 00:00:00 2001 From: PouleyKetchoupp Date: Tue, 17 Aug 2021 10:15:11 -0700 Subject: 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 ++ .../plugins/collision_shape_2d_editor_plugin.cpp | 41 +++++++ editor/plugins/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 ++++++++++ servers/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 + servers/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 ++++++ servers/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 + servers/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 1df2fd0158..ae6b5fda51 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 33eb0de698..a5234e90e7 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 0000000000..432c650074 --- /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 0000000000..9839044c30 --- /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 0000000000..aa8cee1210 --- /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 0000000000..44d32fe83b --- /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 2b03ad928c..ef5e124ad9 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 c2684305ef..bfb7a68c35 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 056e1b5b7d..eab80a419b 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 5d1b4d8ead..a23886b9e7 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 2cea3c2337..f0b799e4d2 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 0000000000..fb8f4b9985 --- /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 0000000000..56ecfa2722 --- /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 0000000000..5446b4daab --- /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 0000000000..2da6311321 --- /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 30a99d3d74..3dde881c4d 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 8f8a4a862c..1946dae2e3 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 88c097453e..0954f3a174 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 3610f43f93..1926eaac84 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 b93178919d..0ebccc2614 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 b3e4ca84c3..be2f83b705 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 45d3379dfa..d1640b39cf 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 6e6a2cb9e7..547f5f3e47 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 dcecac1c73..c61b9cbd4e 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 fbb374bd74..a1d776922e 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 6e59a77e89..f2322a0e76 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 75174628bf..d807e73731 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 664308ed7b..42a0fb32b2 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 ca58900111..9f18b83f07 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 c96f85446c..42b3daab28 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 4c559dd7bd..b6fb17b1c9 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 1f46a96b27..582acaefe8 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 5201e76498..b8cbceacc7 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; -- cgit v1.2.3 From 829fb4fba12d167ffe2280998d2f50431b2ccab3 Mon Sep 17 00:00:00 2001 From: PouleyKetchoupp Date: Tue, 17 Aug 2021 18:41:21 -0700 Subject: 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 91d747b492..8bcc4609f4 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 1946dae2e3..34c94150e2 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 17c0c2fe70..c2f13d0e13 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 be2f83b705..a82f0c2e6f 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 d1640b39cf..6813e25a0b 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 f04f3ab583..61ec48c090 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 c61b9cbd4e..8803b355d4 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 a5dd7d48eb..cbde9ce18f 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); -- cgit v1.2.3 From d9720d439545792bd742645f3c6e3f7c29327aa8 Mon Sep 17 00:00:00 2001 From: PouleyKetchoupp Date: Thu, 19 Aug 2021 08:28:04 -0700 Subject: 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 ae6b5fda51..758ffb9b14 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 a5234e90e7..cf353e1073 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 a9d4877cbb..8a9d28ae43 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 a999317953..885f0ace05 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 d34331e1d8..a8a755972f 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 26b9a39047..17e688451d 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 0954f3a174..5cb67d5ab9 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 1926eaac84..6ea5e445bc 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 0ebccc2614..7b1cda169d 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 61ec48c090..169c419b3b 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 3be36852b0..392df9b025 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 a1d776922e..1cf6b12623 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 f2322a0e76..341ce06a5d 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 d807e73731..24bf203d51 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 f9e55ad525..7ed17d6284 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 9b5b4de069..1c3d1cf9f6 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 42b3daab28..2132a7c93d 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 b6fb17b1c9..4a453564f1 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 582acaefe8..76d908b529 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 b8cbceacc7..c92e6629df 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 */ -- cgit v1.2.3 From aa4791735d2fe92d747a39529aebb410f96cf38f Mon Sep 17 00:00:00 2001 From: PouleyKetchoupp Date: Thu, 19 Aug 2021 11:02:40 -0700 Subject: 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 432c650074..50b89a0922 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 9839044c30..e0b19e1a44 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 fb8f4b9985..2390a13bfa 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 56ecfa2722..0895605ddf 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 5446b4daab..5d73fb8d80 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 2da6311321..5369408185 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 34c94150e2..5337c8af56 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 a82f0c2e6f..dae5669488 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 6813e25a0b..541d35dae9 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 169c419b3b..92b87cea23 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 8803b355d4..4a6a07534b 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 42a0fb32b2..fcc97f56a3 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 9f18b83f07..a693288f7e 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 7ed17d6284..4ec03529cf 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; } } -- cgit v1.2.3 From 3d5dc80348b9b377f6d8a33c7101d54b337396a5 Mon Sep 17 00:00:00 2001 From: PouleyKetchoupp Date: Thu, 19 Aug 2021 11:21:56 -0700 Subject: Rename RayShape to SeparationRayShape Makes it clearer that it's used for special cases when picking a collision shape. --- doc/classes/PhysicsServer2D.xml | 9 +- doc/classes/PhysicsServer3D.xml | 6 +- doc/classes/RayShape2D.xml | 24 ----- doc/classes/RayShape3D.xml | 24 ----- doc/classes/SeparationRayShape2D.xml | 24 +++++ doc/classes/SeparationRayShape3D.xml | 24 +++++ editor/icons/RayShape2D.svg | 1 - editor/icons/RayShape3D.svg | 1 - editor/icons/SeparationRayShape2D.svg | 1 + editor/icons/SeparationRayShape3D.svg | 1 + editor/import/resource_importer_scene.cpp | 4 +- .../plugins/collision_shape_2d_editor_plugin.cpp | 22 ++-- editor/plugins/collision_shape_2d_editor_plugin.h | 2 +- editor/plugins/node_3d_editor_gizmos.cpp | 22 ++-- scene/register_scene_types.cpp | 11 +- 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 ---------- scene/resources/separation_ray_shape_2d.cpp | 119 +++++++++++++++++++++ scene/resources/separation_ray_shape_2d.h | 61 +++++++++++ scene/resources/separation_ray_shape_3d.cpp | 91 ++++++++++++++++ scene/resources/separation_ray_shape_3d.h | 56 ++++++++++ servers/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 +- servers/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 +- servers/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 +- servers/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 +- 45 files changed, 514 insertions(+), 512 deletions(-) delete mode 100644 doc/classes/RayShape2D.xml delete mode 100644 doc/classes/RayShape3D.xml create mode 100644 doc/classes/SeparationRayShape2D.xml create mode 100644 doc/classes/SeparationRayShape3D.xml delete mode 100644 editor/icons/RayShape2D.svg delete mode 100644 editor/icons/RayShape3D.svg create mode 100644 editor/icons/SeparationRayShape2D.svg create mode 100644 editor/icons/SeparationRayShape3D.svg delete mode 100644 scene/resources/ray_shape_2d.cpp delete mode 100644 scene/resources/ray_shape_2d.h delete mode 100644 scene/resources/ray_shape_3d.cpp delete mode 100644 scene/resources/ray_shape_3d.h create mode 100644 scene/resources/separation_ray_shape_2d.cpp create mode 100644 scene/resources/separation_ray_shape_2d.h create mode 100644 scene/resources/separation_ray_shape_3d.cpp create mode 100644 scene/resources/separation_ray_shape_3d.h diff --git a/doc/classes/PhysicsServer2D.xml b/doc/classes/PhysicsServer2D.xml index 758ffb9b14..d0ae665139 100644 --- a/doc/classes/PhysicsServer2D.xml +++ b/doc/classes/PhysicsServer2D.xml @@ -717,17 +717,17 @@ Sets a joint parameter. See [enum JointParam] for a list of available parameters. - + - + - + @@ -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 cf353e1073..c47a311161 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/RayShape2D.xml b/doc/classes/RayShape2D.xml deleted file mode 100644 index 50b89a0922..0000000000 --- a/doc/classes/RayShape2D.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - 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]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 deleted file mode 100644 index e0b19e1a44..0000000000 --- a/doc/classes/RayShape3D.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - 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]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/SeparationRayShape2D.xml b/doc/classes/SeparationRayShape2D.xml new file mode 100644 index 0000000000..fb90606577 --- /dev/null +++ b/doc/classes/SeparationRayShape2D.xml @@ -0,0 +1,24 @@ + + + + Separation ray shape for 2D collisions. + + + 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. + + + 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/SeparationRayShape3D.xml b/doc/classes/SeparationRayShape3D.xml new file mode 100644 index 0000000000..ea57e4eb59 --- /dev/null +++ b/doc/classes/SeparationRayShape3D.xml @@ -0,0 +1,24 @@ + + + + Separation ray shape for 3D collisions. + + + 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. + + + 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/editor/icons/RayShape2D.svg b/editor/icons/RayShape2D.svg deleted file mode 100644 index aa8cee1210..0000000000 --- a/editor/icons/RayShape2D.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/editor/icons/RayShape3D.svg b/editor/icons/RayShape3D.svg deleted file mode 100644 index 44d32fe83b..0000000000 --- a/editor/icons/RayShape3D.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/editor/icons/SeparationRayShape2D.svg b/editor/icons/SeparationRayShape2D.svg new file mode 100644 index 0000000000..aa8cee1210 --- /dev/null +++ b/editor/icons/SeparationRayShape2D.svg @@ -0,0 +1 @@ + diff --git a/editor/icons/SeparationRayShape3D.svg b/editor/icons/SeparationRayShape3D.svg new file mode 100644 index 0000000000..44d32fe83b --- /dev/null +++ b/editor/icons/SeparationRayShape3D.svg @@ -0,0 +1 @@ + diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index ef5e124ad9..c2244befa1 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 bfb7a68c35..bfcc293625 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 eab80a419b..421e674df8 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 a23886b9e7..d04e88e915 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 f0b799e4d2..25d3f6a3e7 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/ray_shape_2d.cpp deleted file mode 100644 index 2390a13bfa..0000000000 --- a/scene/resources/ray_shape_2d.cpp +++ /dev/null @@ -1,119 +0,0 @@ -/*************************************************************************/ -/* 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["slide_on_slope"] = slide_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_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, "slide_on_slope"), "set_slide_on_slope", "get_slide_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_slide_on_slope(bool p_active) { - slide_on_slope = p_active; - _update_shape(); -} - -bool RayShape2D::get_slide_on_slope() const { - return slide_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 deleted file mode 100644 index 0895605ddf..0000000000 --- a/scene/resources/ray_shape_2d.h +++ /dev/null @@ -1,61 +0,0 @@ -/*************************************************************************/ -/* 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 slide_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_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; - 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 deleted file mode 100644 index 5d73fb8d80..0000000000 --- a/scene/resources/ray_shape_3d.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/*************************************************************************/ -/* 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["slide_on_slope"] = slide_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_slide_on_slope(bool p_active) { - slide_on_slope = p_active; - _update_shape(); - notify_change_to_owners(); -} - -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_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, "slide_on_slope"), "set_slide_on_slope", "get_slide_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 deleted file mode 100644 index 5369408185..0000000000 --- a/scene/resources/ray_shape_3d.h +++ /dev/null @@ -1,56 +0,0 @@ -/*************************************************************************/ -/* 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 slide_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_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; - - RayShape3D(); -}; -#endif // RAY_SHAPE_H diff --git a/scene/resources/separation_ray_shape_2d.cpp b/scene/resources/separation_ray_shape_2d.cpp new file mode 100644 index 0000000000..0acd6d268d --- /dev/null +++ b/scene/resources/separation_ray_shape_2d.cpp @@ -0,0 +1,119 @@ +/*************************************************************************/ +/* separation_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 "separation_ray_shape_2d.h" + +#include "servers/physics_server_2d.h" +#include "servers/rendering_server.h" + +void SeparationRayShape2D::_update_shape() { + Dictionary d; + d["length"] = length; + d["slide_on_slope"] = slide_on_slope; + PhysicsServer2D::get_singleton()->shape_set_data(get_rid(), d); + emit_changed(); +} + +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; + 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 SeparationRayShape2D::get_rect() const { + Rect2 rect; + rect.position = Vector2(); + rect.expand_to(Vector2(0, length)); + rect = rect.grow(Math_SQRT12 * 4); + return rect; +} + +real_t SeparationRayShape2D::get_enclosing_radius() const { + return 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"), &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 SeparationRayShape2D::set_length(real_t p_length) { + length = p_length; + _update_shape(); +} + +real_t SeparationRayShape2D::get_length() const { + return length; +} + +void SeparationRayShape2D::set_slide_on_slope(bool p_active) { + slide_on_slope = p_active; + _update_shape(); +} + +bool SeparationRayShape2D::get_slide_on_slope() const { + return slide_on_slope; +} + +SeparationRayShape2D::SeparationRayShape2D() : + Shape2D(PhysicsServer2D::get_singleton()->separation_ray_shape_create()) { + _update_shape(); +} diff --git a/scene/resources/separation_ray_shape_2d.h b/scene/resources/separation_ray_shape_2d.h new file mode 100644 index 0000000000..5b74e6c727 --- /dev/null +++ b/scene/resources/separation_ray_shape_2d.h @@ -0,0 +1,61 @@ +/*************************************************************************/ +/* separation_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 SEPARATION_RAY_SHAPE_2D_H +#define SEPARATION_RAY_SHAPE_2D_H + +#include "scene/resources/shape_2d.h" + +class SeparationRayShape2D : public Shape2D { + GDCLASS(SeparationRayShape2D, Shape2D); + + real_t length = 20.0; + bool slide_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_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; + virtual real_t get_enclosing_radius() const override; + + SeparationRayShape2D(); +}; + +#endif // SEPARATION_RAY_SHAPE_2D_H diff --git a/scene/resources/separation_ray_shape_3d.cpp b/scene/resources/separation_ray_shape_3d.cpp new file mode 100644 index 0000000000..376e04c844 --- /dev/null +++ b/scene/resources/separation_ray_shape_3d.cpp @@ -0,0 +1,91 @@ +/*************************************************************************/ +/* separation_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 "separation_ray_shape_3d.h" + +#include "servers/physics_server_3d.h" + +Vector SeparationRayShape3D::get_debug_mesh_lines() const { + Vector points; + points.push_back(Vector3()); + points.push_back(Vector3(0, 0, get_length())); + + return points; +} + +real_t SeparationRayShape3D::get_enclosing_radius() const { + return length; +} + +void SeparationRayShape3D::_update_shape() { + Dictionary d; + d["length"] = length; + d["slide_on_slope"] = slide_on_slope; + PhysicsServer3D::get_singleton()->shape_set_data(get_shape(), d); + Shape3D::_update_shape(); +} + +void SeparationRayShape3D::set_length(float p_length) { + length = p_length; + _update_shape(); + notify_change_to_owners(); +} + +float SeparationRayShape3D::get_length() const { + return length; +} + +void SeparationRayShape3D::set_slide_on_slope(bool p_active) { + slide_on_slope = p_active; + _update_shape(); + notify_change_to_owners(); +} + +bool SeparationRayShape3D::get_slide_on_slope() const { + return slide_on_slope; +} + +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"), &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"); +} + +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/separation_ray_shape_3d.h b/scene/resources/separation_ray_shape_3d.h new file mode 100644 index 0000000000..54058b6095 --- /dev/null +++ b/scene/resources/separation_ray_shape_3d.h @@ -0,0 +1,56 @@ +/*************************************************************************/ +/* separation_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 SEPARATION_RAY_SHAPE_H +#define SEPARATION_RAY_SHAPE_H +#include "scene/resources/shape_3d.h" + +class SeparationRayShape3D : public Shape3D { + GDCLASS(SeparationRayShape3D, Shape3D); + float length = 1.0; + bool slide_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_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; + + SeparationRayShape3D(); +}; +#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 3dde881c4d..b1aee01bde 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 5337c8af56..f7a8593c50 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 c2f13d0e13..0678e3526c 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 5cb67d5ab9..813e5ddc17 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 6ea5e445bc..c5b6d550d7 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 7b1cda169d..05d4ac64b0 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 dae5669488..757b2e0583 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 541d35dae9..bc321adb42 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 92b87cea23..c0493749e0 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 547f5f3e47..de81348b4e 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 4a6a07534b..e7b79e8450 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 cbde9ce18f..c1a69e708f 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 1cf6b12623..fbc6f7eee8 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 341ce06a5d..a18593c90c 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 24bf203d51..674c52d4a3 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 fcc97f56a3..0794e7888e 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 a693288f7e..dc35c3b172 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 4ec03529cf..37dee436df 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 2132a7c93d..4660b83f4d 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 4a453564f1..9afac0cbd1 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 76d908b529..6cde4977f4 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 c92e6629df..8f83e360f2 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; -- cgit v1.2.3