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.
This commit is contained in:
PouleyKetchoupp 2021-08-17 10:15:11 -07:00
parent c89a5fb8be
commit 45c7af9862
33 changed files with 842 additions and 26 deletions

View file

@ -716,6 +716,11 @@
Sets a joint parameter. See [enum JointParam] for a list of available parameters.
</description>
</method>
<method name="ray_shape_create">
<return type="RID" />
<description>
</description>
</method>
<method name="rectangle_shape_create">
<return type="RID" />
<description>
@ -840,25 +845,27 @@
<constant name="SHAPE_WORLD_MARGIN" value="0" enum="ShapeType">
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.
</constant>
<constant name="SHAPE_SEGMENT" value="1" enum="ShapeType">
<constant name="SHAPE_RAY" value="1" enum="ShapeType">
</constant>
<constant name="SHAPE_SEGMENT" value="2" enum="ShapeType">
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.
</constant>
<constant name="SHAPE_CIRCLE" value="2" enum="ShapeType">
<constant name="SHAPE_CIRCLE" value="3" enum="ShapeType">
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.
</constant>
<constant name="SHAPE_RECTANGLE" value="3" enum="ShapeType">
<constant name="SHAPE_RECTANGLE" value="4" enum="ShapeType">
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.
</constant>
<constant name="SHAPE_CAPSULE" value="4" enum="ShapeType">
<constant name="SHAPE_CAPSULE" value="5" enum="ShapeType">
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.
</constant>
<constant name="SHAPE_CONVEX_POLYGON" value="5" enum="ShapeType">
<constant name="SHAPE_CONVEX_POLYGON" value="6" enum="ShapeType">
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.
</constant>
<constant name="SHAPE_CONCAVE_POLYGON" value="6" enum="ShapeType">
<constant name="SHAPE_CONCAVE_POLYGON" value="7" enum="ShapeType">
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.
</constant>
<constant name="SHAPE_CUSTOM" value="7" enum="ShapeType">
<constant name="SHAPE_CUSTOM" value="8" enum="ShapeType">
This constant is used internally by the engine. Any attempt to create this kind of shape results in an error.
</constant>
<constant name="AREA_PARAM_GRAVITY" value="0" enum="AreaParameter">

View file

@ -849,6 +849,11 @@
<description>
</description>
</method>
<method name="ray_shape_create">
<return type="RID" />
<description>
</description>
</method>
<method name="set_active">
<return type="void" />
<argument index="0" name="active" type="bool" />
@ -1171,31 +1176,34 @@
<constant name="SHAPE_PLANE" value="0" enum="ShapeType">
The [Shape3D] is a [WorldMarginShape3D].
</constant>
<constant name="SHAPE_SPHERE" value="1" enum="ShapeType">
<constant name="SHAPE_RAY" value="1" enum="ShapeType">
The [Shape3D] is a [RayShape3D].
</constant>
<constant name="SHAPE_SPHERE" value="2" enum="ShapeType">
The [Shape3D] is a [SphereShape3D].
</constant>
<constant name="SHAPE_BOX" value="2" enum="ShapeType">
<constant name="SHAPE_BOX" value="3" enum="ShapeType">
The [Shape3D] is a [BoxShape3D].
</constant>
<constant name="SHAPE_CAPSULE" value="3" enum="ShapeType">
<constant name="SHAPE_CAPSULE" value="4" enum="ShapeType">
The [Shape3D] is a [CapsuleShape3D].
</constant>
<constant name="SHAPE_CYLINDER" value="4" enum="ShapeType">
<constant name="SHAPE_CYLINDER" value="5" enum="ShapeType">
The [Shape3D] is a [CylinderShape3D].
</constant>
<constant name="SHAPE_CONVEX_POLYGON" value="5" enum="ShapeType">
<constant name="SHAPE_CONVEX_POLYGON" value="6" enum="ShapeType">
The [Shape3D] is a [ConvexPolygonShape3D].
</constant>
<constant name="SHAPE_CONCAVE_POLYGON" value="6" enum="ShapeType">
<constant name="SHAPE_CONCAVE_POLYGON" value="7" enum="ShapeType">
The [Shape3D] is a [ConcavePolygonShape3D].
</constant>
<constant name="SHAPE_HEIGHTMAP" value="7" enum="ShapeType">
<constant name="SHAPE_HEIGHTMAP" value="8" enum="ShapeType">
The [Shape3D] is a [HeightMapShape3D].
</constant>
<constant name="SHAPE_SOFT_BODY" value="8" enum="ShapeType">
<constant name="SHAPE_SOFT_BODY" value="9" enum="ShapeType">
The [Shape3D] is a [SoftBody3D].
</constant>
<constant name="SHAPE_CUSTOM" value="9" enum="ShapeType">
<constant name="SHAPE_CUSTOM" value="10" enum="ShapeType">
This constant is used internally by the engine. Any attempt to create this kind of shape results in an error.
</constant>
<constant name="AREA_PARAM_GRAVITY" value="0" enum="AreaParameter">

View file

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="RayShape2D" inherits="Shape2D" version="4.0">
<brief_description>
Ray shape for 2D collisions.
</brief_description>
<description>
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.
</description>
<tutorials>
</tutorials>
<methods>
</methods>
<members>
<member name="length" type="float" setter="set_length" getter="get_length" default="20.0">
The ray's length.
</member>
<member name="slips_on_slope" type="bool" setter="set_slips_on_slope" getter="get_slips_on_slope" default="false">
If [code]true[/code], allow the shape to return the correct normal.
</member>
</members>
<constants>
</constants>
</class>

View file

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="RayShape3D" inherits="Shape3D" version="4.0">
<brief_description>
Ray shape for 3D collisions.
</brief_description>
<description>
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.
</description>
<tutorials>
</tutorials>
<methods>
</methods>
<members>
<member name="length" type="float" setter="set_length" getter="get_length" default="1.0">
The ray's length.
</member>
<member name="slips_on_slope" type="bool" setter="set_slips_on_slope" getter="get_slips_on_slope" default="false">
If [code]true[/code], allow the shape to return the correct normal.
</member>
</members>
<constants>
</constants>
</class>

View file

@ -0,0 +1 @@
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a1 1 0 0 0 -1 1v9.5859l-1.293-1.293a1 1 0 0 0 -.7207-.29102 1 1 0 0 0 -.69336.29102 1 1 0 0 0 0 1.4141l3 3a1.0001 1.0001 0 0 0 .0039062.003907 1 1 0 0 0 .050781.044921 1.0001 1.0001 0 0 0 .03125.027344 1 1 0 0 0 .048828.035156 1.0001 1.0001 0 0 0 .023438.015625 1 1 0 0 0 .076172.044922 1.0001 1.0001 0 0 0 .0058593.003906 1 1 0 0 0 .013672.007813 1.0001 1.0001 0 0 0 .078125.035156 1 1 0 0 0 .074219.025391 1.0001 1.0001 0 0 0 .025391.009766 1 1 0 0 0 .039062.009765 1.0001 1.0001 0 0 0 .068359.013672 1.0001 1.0001 0 0 0 .097656.011719 1.0001 1.0001 0 0 0 .0078125 0 1 1 0 0 0 .0625.003906 1 1 0 0 0 .015625-.001953 1.0001 1.0001 0 0 0 .083984-.003906 1 1 0 0 0 .015625-.001953 1.0001 1.0001 0 0 0 .083984-.013672 1.0001 1.0001 0 0 0 .052734-.013672 1 1 0 0 0 .058594-.015625 1.0001 1.0001 0 0 0 .078125-.029297 1 1 0 0 0 .013672-.00586 1.0001 1.0001 0 0 0 .076172-.037109 1 1 0 0 0 .013672-.007812 1.0001 1.0001 0 0 0 .072266-.044922 1 1 0 0 0 .011719-.007813 1.0001 1.0001 0 0 0 .068359-.052734 1 1 0 0 0 .011719-.009766 1.0001 1.0001 0 0 0 .050781-.046875l.0097657-.011719 2.9902-2.9883a1 1 0 0 0 0-1.4141 1 1 0 0 0 -1.4141 0l-1.293 1.293v-9.5859a1 1 0 0 0 -1-1z" fill="#68b6ff" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View file

@ -0,0 +1 @@
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill-rule="evenodd"><path d="m8 1-6 5 4 2.666v4.334l2 2v-5-2z" fill="#a2d2ff"/><path d="m8 1v7 2l-2-1.334v1.334l2 1.5v3.5l2-2v-4.334l4-2.666z" fill="#2998ff"/></g></svg>

After

Width:  |  Height:  |  Size: 256 B

View file

@ -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, Map<Ref<E
BoxShape3D *boxShape = memnew(BoxShape3D);
boxShape->set_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<Node3D>(sb)->rotate_x(Math_PI / 2);
} else if (empty_draw_type == "IMAGE") {
WorldMarginShape3D *world_margin_shape = memnew(WorldMarginShape3D);
colshape->set_shape(world_margin_shape);

View file

@ -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<RayShape2D> ray = node->get_shape();
if (idx == 0) {
return ray->get_length();
}
} break;
case RECTANGLE_SHAPE: {
Ref<RectangleShape2D> rect = node->get_shape();
@ -152,6 +162,15 @@ void CollisionShape2DEditor::set_handle(int idx, Point2 &p_point) {
} break;
case RAY_SHAPE: {
Ref<RayShape2D> 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<RectangleShape2D> rect = node->get_shape();
@ -253,6 +272,16 @@ void CollisionShape2DEditor::commit_handle(int idx, Variant &p_org) {
} break;
case RAY_SHAPE: {
Ref<RayShape2D> 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<RectangleShape2D> rect = node->get_shape();
@ -394,6 +423,8 @@ void CollisionShape2DEditor::_get_current_shape_type() {
shape_type = CONVEX_POLYGON_SHAPE;
} else if (Object::cast_to<WorldMarginShape2D>(*s)) {
shape_type = WORLD_MARGIN_SHAPE;
} else if (Object::cast_to<RayShape2D>(*s)) {
shape_type = RAY_SHAPE;
} else if (Object::cast_to<RectangleShape2D>(*s)) {
shape_type = RECTANGLE_SHAPE;
} else if (Object::cast_to<SegmentShape2D>(*s)) {
@ -471,6 +502,16 @@ void CollisionShape2DEditor::forward_canvas_draw_over_viewport(Control *p_overla
} break;
case RAY_SHAPE: {
Ref<RayShape2D> 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<RectangleShape2D> shape = node->get_shape();

View file

@ -47,6 +47,7 @@ class CollisionShape2DEditor : public Control {
CONCAVE_POLYGON_SHAPE,
CONVEX_POLYGON_SHAPE,
WORLD_MARGIN_SHAPE,
RAY_SHAPE,
RECTANGLE_SHAPE,
SEGMENT_SHAPE
};

View file

@ -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<RayShape3D>(*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<RayShape3D>(*s)) {
Ref<RayShape3D> 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<RayShape3D>(*s)) {
Ref<RayShape3D> 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<BoxShape3D>(*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<RayShape3D>(*s)) {
Ref<RayShape3D> 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<RayShape3D>(*s)) {
Ref<RayShape3D> rs = s;
Vector<Vector3> 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<Vector3> handles;
handles.push_back(Vector3(0, 0, rs->get_length()));
p_gizmo->add_handles(handles, handles_material);
}
if (Object::cast_to<HeightMapShape3D>(*s)) {
Ref<HeightMapShape3D> hms = s;

View file

@ -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");

View file

@ -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<Vector2> 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<Color> 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<Point2>(), 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();
}

View file

@ -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

View file

@ -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<Vector3> RayShape3D::get_debug_mesh_lines() const {
Vector<Vector3> 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();
}

View file

@ -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<Vector3> get_debug_mesh_lines() const override;
virtual real_t get_enclosing_radius() const override;
RayShape3D();
};
#endif // RAY_SHAPE_H

View file

@ -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];
}
}

View file

@ -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<const RayShape2DSW *>(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;

View file

@ -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);
}

View file

@ -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;

View file

@ -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)

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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<const RayShape3DSW *>(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.

View file

@ -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);

View file

@ -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;

View file

@ -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)

View file

@ -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 {

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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;