Add raycast options to hit when starting inside / hit back faces

Makes the results consistent for all shape types with options to set
the desired behavior.
This commit is contained in:
PouleyKetchoupp 2021-11-10 15:57:11 -07:00
parent 3668312e78
commit c3ae7ddedd
22 changed files with 164 additions and 55 deletions

View File

@ -64,7 +64,7 @@
Intersects a ray in a given space. Ray position and other parameters are defined through [PhysicsRayQueryParameters2D]. The returned object is a dictionary with the following fields: Intersects a ray in a given space. Ray position and other parameters are defined through [PhysicsRayQueryParameters2D]. The returned object is a dictionary with the following fields:
[code]collider[/code]: The colliding object. [code]collider[/code]: The colliding object.
[code]collider_id[/code]: The colliding object's ID. [code]collider_id[/code]: The colliding object's ID.
[code]normal[/code]: The object's surface normal at the intersection point. [code]normal[/code]: The object's surface normal at the intersection point, or [code]Vector2(0, 0)[/code] if the ray starts inside the shape and [member PhysicsRayQueryParameters2D.hit_from_inside] is [code]true[/code].
[code]position[/code]: The intersection point. [code]position[/code]: The intersection point.
[code]rid[/code]: The intersecting object's [RID]. [code]rid[/code]: The intersecting object's [RID].
[code]shape[/code]: The shape index of the colliding shape. [code]shape[/code]: The shape index of the colliding shape.

View File

@ -65,7 +65,7 @@
Intersects a ray in a given space. Ray position and other parameters are defined through [PhysicsRayQueryParameters3D]. The returned object is a dictionary with the following fields: Intersects a ray in a given space. Ray position and other parameters are defined through [PhysicsRayQueryParameters3D]. The returned object is a dictionary with the following fields:
[code]collider[/code]: The colliding object. [code]collider[/code]: The colliding object.
[code]collider_id[/code]: The colliding object's ID. [code]collider_id[/code]: The colliding object's ID.
[code]normal[/code]: The object's surface normal at the intersection point. [code]normal[/code]: The object's surface normal at the intersection point, or [code]Vector3(0, 0, 0)[/code] if the ray starts inside the shape and [member PhysicsRayQueryParameters3D.hit_from_inside] is [code]true[/code].
[code]position[/code]: The intersection point. [code]position[/code]: The intersection point.
[code]rid[/code]: The intersecting object's [RID]. [code]rid[/code]: The intersecting object's [RID].
[code]shape[/code]: The shape index of the colliding shape. [code]shape[/code]: The shape index of the colliding shape.

View File

@ -24,6 +24,9 @@
<member name="from" type="Vector2" setter="set_from" getter="get_from" default="Vector2(0, 0)"> <member name="from" type="Vector2" setter="set_from" getter="get_from" default="Vector2(0, 0)">
The starting point of the ray being queried for, in global coordinates. The starting point of the ray being queried for, in global coordinates.
</member> </member>
<member name="hit_from_inside" type="bool" setter="set_hit_from_inside" getter="is_hit_from_inside_enabled" default="false">
If [code]true[/code], the query will detect a hit when starting inside shapes. In this case the collision normal will be [code]Vector2(0, 0)[/code]. Does not affect concave polygon shapes.
</member>
<member name="to" type="Vector2" setter="set_to" getter="get_to" default="Vector2(0, 0)"> <member name="to" type="Vector2" setter="set_to" getter="get_to" default="Vector2(0, 0)">
The ending point of the ray being queried for, in global coordinates. The ending point of the ray being queried for, in global coordinates.
</member> </member>

View File

@ -24,6 +24,12 @@
<member name="from" type="Vector3" setter="set_from" getter="get_from" default="Vector3(0, 0, 0)"> <member name="from" type="Vector3" setter="set_from" getter="get_from" default="Vector3(0, 0, 0)">
The starting point of the ray being queried for, in global coordinates. The starting point of the ray being queried for, in global coordinates.
</member> </member>
<member name="hit_back_faces" type="bool" setter="set_hit_back_faces" getter="is_hit_back_faces_enabled" default="true">
If [code]true[/code], the query will hit back faces with concave polygon shapes with back face enabled or heightmap shapes.
</member>
<member name="hit_from_inside" type="bool" setter="set_hit_from_inside" getter="is_hit_from_inside_enabled" default="false">
If [code]true[/code], the query will detect a hit when starting inside shapes. In this case the collision normal will be [code]Vector3(0, 0, 0)[/code]. Does not affect concave polygon shapes or heightmap shapes.
</member>
<member name="to" type="Vector3" setter="set_to" getter="get_to" default="Vector3(0, 0, 0)"> <member name="to" type="Vector3" setter="set_to" getter="get_to" default="Vector3(0, 0, 0)">
The ending point of the ray being queried for, in global coordinates. The ending point of the ray being queried for, in global coordinates.
</member> </member>

View File

@ -63,7 +63,7 @@
<method name="get_collision_normal" qualifiers="const"> <method name="get_collision_normal" qualifiers="const">
<return type="Vector2" /> <return type="Vector2" />
<description> <description>
Returns the normal of the intersecting object's shape at the collision point. Returns the normal of the intersecting object's shape at the collision point, or [code]Vector2(0, 0)[/code] if the ray starts inside the shape and [member hit_from_inside] is [code]true[/code].
</description> </description>
</method> </method>
<method name="get_collision_point" qualifiers="const"> <method name="get_collision_point" qualifiers="const">
@ -118,6 +118,9 @@
<member name="exclude_parent" type="bool" setter="set_exclude_parent_body" getter="get_exclude_parent_body" default="true"> <member name="exclude_parent" type="bool" setter="set_exclude_parent_body" getter="get_exclude_parent_body" default="true">
If [code]true[/code], the parent node will be excluded from collision detection. If [code]true[/code], the parent node will be excluded from collision detection.
</member> </member>
<member name="hit_from_inside" type="bool" setter="set_hit_from_inside" getter="is_hit_from_inside_enabled" default="false">
If [code]true[/code], the ray will detect a hit when starting inside shapes. In this case the collision normal will be [code]Vector2(0, 0)[/code]. Does not affect concave polygon shapes.
</member>
<member name="target_position" type="Vector2" setter="set_target_position" getter="get_target_position" default="Vector2(0, 50)"> <member name="target_position" type="Vector2" setter="set_target_position" getter="get_target_position" default="Vector2(0, 50)">
The ray's destination point, relative to the RayCast's [code]position[/code]. The ray's destination point, relative to the RayCast's [code]position[/code].
</member> </member>

View File

@ -65,7 +65,7 @@
<method name="get_collision_normal" qualifiers="const"> <method name="get_collision_normal" qualifiers="const">
<return type="Vector3" /> <return type="Vector3" />
<description> <description>
Returns the normal of the intersecting object's shape at the collision point. Returns the normal of the intersecting object's shape at the collision point, or [code]Vector3(0, 0, 0)[/code] if the ray starts inside the shape and [member hit_from_inside] is [code]true[/code].
</description> </description>
</method> </method>
<method name="get_collision_point" qualifiers="const"> <method name="get_collision_point" qualifiers="const">
@ -127,6 +127,9 @@
<member name="exclude_parent" type="bool" setter="set_exclude_parent_body" getter="get_exclude_parent_body" default="true"> <member name="exclude_parent" type="bool" setter="set_exclude_parent_body" getter="get_exclude_parent_body" default="true">
If [code]true[/code], collisions will be ignored for this RayCast3D's immediate parent. If [code]true[/code], collisions will be ignored for this RayCast3D's immediate parent.
</member> </member>
<member name="hit_from_inside" type="bool" setter="set_hit_from_inside" getter="is_hit_from_inside_enabled" default="false">
If [code]true[/code], the ray will detect a hit when starting inside shapes. In this case the collision normal will be [code]Vector3(0, 0, 0)[/code]. Does not affect shapes with no volume like concave polygon or heightmap.
</member>
<member name="target_position" type="Vector3" setter="set_target_position" getter="get_target_position" default="Vector3(0, -1, 0)"> <member name="target_position" type="Vector3" setter="set_target_position" getter="get_target_position" default="Vector3(0, -1, 0)">
The ray's destination point, relative to the RayCast's [code]position[/code]. The ray's destination point, relative to the RayCast's [code]position[/code].
</member> </member>

View File

@ -200,6 +200,7 @@ void RayCast2D::_update_raycast_state() {
ray_params.collision_mask = collision_mask; ray_params.collision_mask = collision_mask;
ray_params.collide_with_bodies = collide_with_bodies; ray_params.collide_with_bodies = collide_with_bodies;
ray_params.collide_with_areas = collide_with_areas; ray_params.collide_with_areas = collide_with_areas;
ray_params.hit_from_inside = hit_from_inside;
if (dss->intersect_ray(ray_params, rr)) { if (dss->intersect_ray(ray_params, rr)) {
collided = true; collided = true;
@ -290,22 +291,30 @@ void RayCast2D::clear_exceptions() {
exclude.clear(); exclude.clear();
} }
void RayCast2D::set_collide_with_areas(bool p_clip) { void RayCast2D::set_collide_with_areas(bool p_enabled) {
collide_with_areas = p_clip; collide_with_areas = p_enabled;
} }
bool RayCast2D::is_collide_with_areas_enabled() const { bool RayCast2D::is_collide_with_areas_enabled() const {
return collide_with_areas; return collide_with_areas;
} }
void RayCast2D::set_collide_with_bodies(bool p_clip) { void RayCast2D::set_collide_with_bodies(bool p_enabled) {
collide_with_bodies = p_clip; collide_with_bodies = p_enabled;
} }
bool RayCast2D::is_collide_with_bodies_enabled() const { bool RayCast2D::is_collide_with_bodies_enabled() const {
return collide_with_bodies; return collide_with_bodies;
} }
void RayCast2D::set_hit_from_inside(bool p_enabled) {
hit_from_inside = p_enabled;
}
bool RayCast2D::is_hit_from_inside_enabled() const {
return hit_from_inside;
}
void RayCast2D::_bind_methods() { void RayCast2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &RayCast2D::set_enabled); ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &RayCast2D::set_enabled);
ClassDB::bind_method(D_METHOD("is_enabled"), &RayCast2D::is_enabled); ClassDB::bind_method(D_METHOD("is_enabled"), &RayCast2D::is_enabled);
@ -344,10 +353,14 @@ void RayCast2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_collide_with_bodies", "enable"), &RayCast2D::set_collide_with_bodies); ClassDB::bind_method(D_METHOD("set_collide_with_bodies", "enable"), &RayCast2D::set_collide_with_bodies);
ClassDB::bind_method(D_METHOD("is_collide_with_bodies_enabled"), &RayCast2D::is_collide_with_bodies_enabled); ClassDB::bind_method(D_METHOD("is_collide_with_bodies_enabled"), &RayCast2D::is_collide_with_bodies_enabled);
ClassDB::bind_method(D_METHOD("set_hit_from_inside", "enable"), &RayCast2D::set_hit_from_inside);
ClassDB::bind_method(D_METHOD("is_hit_from_inside_enabled"), &RayCast2D::is_hit_from_inside_enabled);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "exclude_parent"), "set_exclude_parent_body", "get_exclude_parent_body"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "exclude_parent"), "set_exclude_parent_body", "get_exclude_parent_body");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "target_position"), "set_target_position", "get_target_position"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "target_position"), "set_target_position", "get_target_position");
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_mask", "get_collision_mask"); ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_mask", "get_collision_mask");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hit_from_inside"), "set_hit_from_inside", "is_hit_from_inside_enabled");
ADD_GROUP("Collide With", "collide_with"); ADD_GROUP("Collide With", "collide_with");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collide_with_areas", "is_collide_with_areas_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collide_with_areas", "is_collide_with_areas_enabled");

View File

@ -51,6 +51,8 @@ class RayCast2D : public Node2D {
bool collide_with_areas = false; bool collide_with_areas = false;
bool collide_with_bodies = true; bool collide_with_bodies = true;
bool hit_from_inside = false;
void _draw_debug_shape(); void _draw_debug_shape();
protected: protected:
@ -65,6 +67,9 @@ public:
void set_collide_with_bodies(bool p_clip); void set_collide_with_bodies(bool p_clip);
bool is_collide_with_bodies_enabled() const; bool is_collide_with_bodies_enabled() const;
void set_hit_from_inside(bool p_enable);
bool is_hit_from_inside_enabled() const;
void set_enabled(bool p_enabled); void set_enabled(bool p_enabled);
bool is_enabled() const; bool is_enabled() const;

View File

@ -219,6 +219,7 @@ void RayCast3D::_update_raycast_state() {
ray_params.collision_mask = collision_mask; ray_params.collision_mask = collision_mask;
ray_params.collide_with_bodies = collide_with_bodies; ray_params.collide_with_bodies = collide_with_bodies;
ray_params.collide_with_areas = collide_with_areas; ray_params.collide_with_areas = collide_with_areas;
ray_params.hit_from_inside = hit_from_inside;
PhysicsDirectSpaceState3D::RayResult rr; PhysicsDirectSpaceState3D::RayResult rr;
if (dss->intersect_ray(ray_params, rr)) { if (dss->intersect_ray(ray_params, rr)) {
@ -268,22 +269,30 @@ void RayCast3D::clear_exceptions() {
exclude.clear(); exclude.clear();
} }
void RayCast3D::set_collide_with_areas(bool p_clip) { void RayCast3D::set_collide_with_areas(bool p_enabled) {
collide_with_areas = p_clip; collide_with_areas = p_enabled;
} }
bool RayCast3D::is_collide_with_areas_enabled() const { bool RayCast3D::is_collide_with_areas_enabled() const {
return collide_with_areas; return collide_with_areas;
} }
void RayCast3D::set_collide_with_bodies(bool p_clip) { void RayCast3D::set_collide_with_bodies(bool p_enabled) {
collide_with_bodies = p_clip; collide_with_bodies = p_enabled;
} }
bool RayCast3D::is_collide_with_bodies_enabled() const { bool RayCast3D::is_collide_with_bodies_enabled() const {
return collide_with_bodies; return collide_with_bodies;
} }
void RayCast3D::set_hit_from_inside(bool p_enabled) {
hit_from_inside = p_enabled;
}
bool RayCast3D::is_hit_from_inside_enabled() const {
return hit_from_inside;
}
void RayCast3D::_bind_methods() { void RayCast3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &RayCast3D::set_enabled); ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &RayCast3D::set_enabled);
ClassDB::bind_method(D_METHOD("is_enabled"), &RayCast3D::is_enabled); ClassDB::bind_method(D_METHOD("is_enabled"), &RayCast3D::is_enabled);
@ -322,6 +331,9 @@ void RayCast3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_collide_with_bodies", "enable"), &RayCast3D::set_collide_with_bodies); ClassDB::bind_method(D_METHOD("set_collide_with_bodies", "enable"), &RayCast3D::set_collide_with_bodies);
ClassDB::bind_method(D_METHOD("is_collide_with_bodies_enabled"), &RayCast3D::is_collide_with_bodies_enabled); ClassDB::bind_method(D_METHOD("is_collide_with_bodies_enabled"), &RayCast3D::is_collide_with_bodies_enabled);
ClassDB::bind_method(D_METHOD("set_hit_from_inside", "enable"), &RayCast3D::set_hit_from_inside);
ClassDB::bind_method(D_METHOD("is_hit_from_inside_enabled"), &RayCast3D::is_hit_from_inside_enabled);
ClassDB::bind_method(D_METHOD("set_debug_shape_custom_color", "debug_shape_custom_color"), &RayCast3D::set_debug_shape_custom_color); ClassDB::bind_method(D_METHOD("set_debug_shape_custom_color", "debug_shape_custom_color"), &RayCast3D::set_debug_shape_custom_color);
ClassDB::bind_method(D_METHOD("get_debug_shape_custom_color"), &RayCast3D::get_debug_shape_custom_color); ClassDB::bind_method(D_METHOD("get_debug_shape_custom_color"), &RayCast3D::get_debug_shape_custom_color);
@ -332,6 +344,7 @@ void RayCast3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "exclude_parent"), "set_exclude_parent_body", "get_exclude_parent_body"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "exclude_parent"), "set_exclude_parent_body", "get_exclude_parent_body");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "target_position"), "set_target_position", "get_target_position"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "target_position"), "set_target_position", "get_target_position");
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hit_from_inside"), "set_hit_from_inside", "is_hit_from_inside_enabled");
ADD_GROUP("Collide With", "collide_with"); ADD_GROUP("Collide With", "collide_with");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collide_with_areas", "is_collide_with_areas_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collide_with_areas", "is_collide_with_areas_enabled");

View File

@ -65,18 +65,23 @@ class RayCast3D : public Node3D {
bool collide_with_areas = false; bool collide_with_areas = false;
bool collide_with_bodies = true; bool collide_with_bodies = true;
bool hit_from_inside = false;
protected: protected:
void _notification(int p_what); void _notification(int p_what);
void _update_raycast_state(); void _update_raycast_state();
static void _bind_methods(); static void _bind_methods();
public: public:
void set_collide_with_areas(bool p_clip); void set_collide_with_areas(bool p_enabled);
bool is_collide_with_areas_enabled() const; bool is_collide_with_areas_enabled() const;
void set_collide_with_bodies(bool p_clip); void set_collide_with_bodies(bool p_enabled);
bool is_collide_with_bodies_enabled() const; bool is_collide_with_bodies_enabled() const;
void set_hit_from_inside(bool p_enabled);
bool is_hit_from_inside_enabled() const;
void set_enabled(bool p_enabled); void set_enabled(bool p_enabled);
bool is_enabled() const; bool is_enabled() const;

View File

@ -153,6 +153,22 @@ bool GodotPhysicsDirectSpaceState2D::intersect_ray(const RayParameters &p_parame
Vector2 shape_point, shape_normal; Vector2 shape_point, shape_normal;
if (shape->contains_point(local_from)) {
if (p_parameters.hit_from_inside) {
// Hit shape at starting point.
min_d = 0;
res_point = local_from;
res_normal = Vector2();
res_shape = shape_idx;
res_obj = col_obj;
collided = true;
break;
} else {
// Ignore shape when starting inside.
continue;
}
}
if (shape->intersect_segment(local_from, local_to, shape_point, shape_normal)) { if (shape->intersect_segment(local_from, local_to, shape_point, shape_normal)) {
Transform2D xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx); Transform2D xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
shape_point = xform.xform(shape_point); shape_point = xform.xform(shape_point);

View File

@ -191,7 +191,7 @@ bool GodotBodyPair3D::_test_ccd(real_t p_step, GodotBody3D *p_A, int p_shape_A,
Vector3 local_to = from_inv.xform(to); Vector3 local_to = from_inv.xform(to);
Vector3 rpos, rnorm; Vector3 rpos, rnorm;
if (!p_B->get_shape(p_shape_B)->intersect_segment(local_from, local_to, rpos, rnorm)) { if (!p_B->get_shape(p_shape_B)->intersect_segment(local_from, local_to, rpos, rnorm, true)) {
return false; return false;
} }

View File

@ -102,7 +102,7 @@ bool GodotCollisionSolver3D::solve_separation_ray(const GodotShape3D *p_shape_A,
to = ai.xform(to); to = ai.xform(to);
Vector3 p, n; Vector3 p, n;
if (!p_shape_B->intersect_segment(from, to, p, n)) { if (!p_shape_B->intersect_segment(from, to, p, n, true)) {
return false; return false;
} }

View File

@ -119,7 +119,7 @@ Vector3 GodotWorldBoundaryShape3D::get_support(const Vector3 &p_normal) const {
return p_normal * 1e15; return p_normal * 1e15;
} }
bool GodotWorldBoundaryShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { bool GodotWorldBoundaryShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const {
bool inters = plane.intersects_segment(p_begin, p_end, &r_result); bool inters = plane.intersects_segment(p_begin, p_end, &r_result);
if (inters) { if (inters) {
r_normal = plane.normal; r_normal = plane.normal;
@ -200,7 +200,7 @@ void GodotSeparationRayShape3D::get_supports(const Vector3 &p_normal, int p_max,
} }
} }
bool GodotSeparationRayShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { bool GodotSeparationRayShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const {
return false; //simply not possible return false; //simply not possible
} }
@ -268,7 +268,7 @@ void GodotSphereShape3D::get_supports(const Vector3 &p_normal, int p_max, Vector
r_type = FEATURE_POINT; r_type = FEATURE_POINT;
} }
bool GodotSphereShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { bool GodotSphereShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const {
return Geometry3D::segment_intersects_sphere(p_begin, p_end, Vector3(), radius, &r_result, &r_normal); return Geometry3D::segment_intersects_sphere(p_begin, p_end, Vector3(), radius, &r_result, &r_normal);
} }
@ -410,7 +410,7 @@ void GodotBoxShape3D::get_supports(const Vector3 &p_normal, int p_max, Vector3 *
r_supports[0] = point; r_supports[0] = point;
} }
bool GodotBoxShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { bool GodotBoxShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const {
AABB aabb(-half_extents, half_extents * 2.0); AABB aabb(-half_extents, half_extents * 2.0);
return aabb.intersects_segment(p_begin, p_end, &r_result, &r_normal); return aabb.intersects_segment(p_begin, p_end, &r_result, &r_normal);
@ -546,7 +546,7 @@ void GodotCapsuleShape3D::get_supports(const Vector3 &p_normal, int p_max, Vecto
} }
} }
bool GodotCapsuleShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { bool GodotCapsuleShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const {
Vector3 norm = (p_end - p_begin).normalized(); Vector3 norm = (p_end - p_begin).normalized();
real_t min_d = 1e20; real_t min_d = 1e20;
@ -761,7 +761,7 @@ void GodotCylinderShape3D::get_supports(const Vector3 &p_normal, int p_max, Vect
} }
} }
bool GodotCylinderShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { bool GodotCylinderShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const {
return Geometry3D::segment_intersects_cylinder(p_begin, p_end, height, radius, &r_result, &r_normal, 1); return Geometry3D::segment_intersects_cylinder(p_begin, p_end, height, radius, &r_result, &r_normal, 1);
} }
@ -954,7 +954,7 @@ void GodotConvexPolygonShape3D::get_supports(const Vector3 &p_normal, int p_max,
r_type = FEATURE_POINT; r_type = FEATURE_POINT;
} }
bool GodotConvexPolygonShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { bool GodotConvexPolygonShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const {
const Geometry3D::MeshData::Face *faces = mesh.faces.ptr(); const Geometry3D::MeshData::Face *faces = mesh.faces.ptr();
int fc = mesh.faces.size(); int fc = mesh.faces.size();
@ -1188,12 +1188,12 @@ void GodotFaceShape3D::get_supports(const Vector3 &p_normal, int p_max, Vector3
r_supports[0] = vertex[vert_support_idx]; r_supports[0] = vertex[vert_support_idx];
} }
bool GodotFaceShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { bool GodotFaceShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const {
bool c = Geometry3D::segment_intersects_triangle(p_begin, p_end, vertex[0], vertex[1], vertex[2], &r_result); bool c = Geometry3D::segment_intersects_triangle(p_begin, p_end, vertex[0], vertex[1], vertex[2], &r_result);
if (c) { if (c) {
r_normal = Plane(vertex[0], vertex[1], vertex[2]).normal; r_normal = Plane(vertex[0], vertex[1], vertex[2]).normal;
if (r_normal.dot(p_end - p_begin) > 0) { if (r_normal.dot(p_end - p_begin) > 0) {
if (backface_collision) { if (backface_collision && p_hit_back_faces) {
r_normal = -r_normal; r_normal = -r_normal;
} else { } else {
c = false; c = false;
@ -1304,7 +1304,7 @@ void GodotConcavePolygonShape3D::_cull_segment(int p_idx, _SegmentCullParams *p_
Vector3 res; Vector3 res;
Vector3 normal; Vector3 normal;
if (face->intersect_segment(p_params->from, p_params->to, res, normal)) { if (face->intersect_segment(p_params->from, p_params->to, res, normal, true)) {
real_t d = p_params->dir.dot(res) - p_params->dir.dot(p_params->from); real_t d = p_params->dir.dot(res) - p_params->dir.dot(p_params->from);
if ((d > 0) && (d < p_params->min_d)) { if ((d > 0) && (d < p_params->min_d)) {
p_params->min_d = d; p_params->min_d = d;
@ -1323,7 +1323,7 @@ void GodotConcavePolygonShape3D::_cull_segment(int p_idx, _SegmentCullParams *p_
} }
} }
bool GodotConcavePolygonShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { bool GodotConcavePolygonShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const {
if (faces.size() == 0) { if (faces.size() == 0) {
return false; return false;
} }
@ -1334,7 +1334,7 @@ bool GodotConcavePolygonShape3D::intersect_segment(const Vector3 &p_begin, const
const BVH *br = bvh.ptr(); const BVH *br = bvh.ptr();
GodotFaceShape3D face; GodotFaceShape3D face;
face.backface_collision = backface_collision; face.backface_collision = backface_collision && p_hit_back_faces;
_SegmentCullParams params; _SegmentCullParams params;
params.from = p_begin; params.from = p_begin;
@ -1675,7 +1675,7 @@ struct _HeightmapGridCullState {
_FORCE_INLINE_ bool _heightmap_face_cull_segment(_HeightmapSegmentCullParams &p_params) { _FORCE_INLINE_ bool _heightmap_face_cull_segment(_HeightmapSegmentCullParams &p_params) {
Vector3 res; Vector3 res;
Vector3 normal; Vector3 normal;
if (p_params.face->intersect_segment(p_params.from, p_params.to, res, normal)) { if (p_params.face->intersect_segment(p_params.from, p_params.to, res, normal, true)) {
p_params.result = res; p_params.result = res;
p_params.normal = normal; p_params.normal = normal;
return true; return true;
@ -1881,7 +1881,7 @@ bool GodotHeightMapShape3D::_intersect_grid_segment(ProcessFunction &p_process,
return false; return false;
} }
bool GodotHeightMapShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal) const { bool GodotHeightMapShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal, bool p_hit_back_faces) const {
if (heights.is_empty()) { if (heights.is_empty()) {
return false; return false;
} }
@ -1899,7 +1899,7 @@ bool GodotHeightMapShape3D::intersect_segment(const Vector3 &p_begin, const Vect
// Simple case for rays that don't traverse the grid horizontally. // Simple case for rays that don't traverse the grid horizontally.
// Just perform a test on the given cell. // Just perform a test on the given cell.
GodotFaceShape3D face; GodotFaceShape3D face;
face.backface_collision = false; face.backface_collision = p_hit_back_faces;
_HeightmapSegmentCullParams params; _HeightmapSegmentCullParams params;
params.from = p_begin; params.from = p_begin;

View File

@ -80,7 +80,7 @@ public:
virtual Vector3 get_support(const Vector3 &p_normal) 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 = 0; virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const = 0;
virtual Vector3 get_closest_point_to(const Vector3 &p_point) const = 0; virtual Vector3 get_closest_point_to(const Vector3 &p_point) const = 0;
virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal) const = 0; virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal, bool p_hit_back_faces) const = 0;
virtual bool intersect_point(const Vector3 &p_point) const = 0; virtual bool intersect_point(const Vector3 &p_point) const = 0;
virtual Vector3 get_moment_of_inertia(real_t p_mass) const = 0; virtual Vector3 get_moment_of_inertia(real_t p_mass) const = 0;
@ -126,7 +126,7 @@ public:
virtual Vector3 get_support(const Vector3 &p_normal) 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 void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override { r_amount = 0; }
virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override; virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override;
virtual bool intersect_point(const Vector3 &p_point) const override; virtual bool intersect_point(const Vector3 &p_point) const override;
virtual Vector3 get_closest_point_to(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 Vector3 get_moment_of_inertia(real_t p_mass) const override;
@ -153,7 +153,7 @@ public:
virtual Vector3 get_support(const Vector3 &p_normal) 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 void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override;
virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override; virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override;
virtual bool intersect_point(const Vector3 &p_point) const override; virtual bool intersect_point(const Vector3 &p_point) const override;
virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override; virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override;
@ -180,7 +180,7 @@ public:
virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override; virtual 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 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 void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override;
virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override; virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override;
virtual bool intersect_point(const Vector3 &p_point) const override; virtual bool intersect_point(const Vector3 &p_point) const override;
virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override; virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override;
@ -205,7 +205,7 @@ public:
virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override; virtual 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 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 void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override;
virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override; virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override;
virtual bool intersect_point(const Vector3 &p_point) const override; virtual bool intersect_point(const Vector3 &p_point) const override;
virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override; virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override;
@ -234,7 +234,7 @@ public:
virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override; virtual 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 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 void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override;
virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override; virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override;
virtual bool intersect_point(const Vector3 &p_point) const override; virtual bool intersect_point(const Vector3 &p_point) const override;
virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override; virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override;
@ -263,7 +263,7 @@ public:
virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override; virtual 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 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 void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override;
virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override; virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override;
virtual bool intersect_point(const Vector3 &p_point) const override; virtual bool intersect_point(const Vector3 &p_point) const override;
virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override; virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override;
@ -288,7 +288,7 @@ public:
virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override; virtual 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 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 void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override;
virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override; virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override;
virtual bool intersect_point(const Vector3 &p_point) const override; virtual bool intersect_point(const Vector3 &p_point) const override;
virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override; virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override;
@ -366,7 +366,7 @@ public:
virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override; virtual 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 Vector3 get_support(const Vector3 &p_normal) const override;
virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override; virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override;
virtual bool intersect_point(const Vector3 &p_point) const override; virtual bool intersect_point(const Vector3 &p_point) const override;
virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override; virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override;
@ -429,7 +429,7 @@ public:
virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override; virtual 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 Vector3 get_support(const Vector3 &p_normal) const override;
virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal) const override; virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal, bool p_hit_back_faces) const override;
virtual bool intersect_point(const Vector3 &p_point) const override; virtual bool intersect_point(const Vector3 &p_point) const override;
virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override; virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override;
@ -456,7 +456,7 @@ struct GodotFaceShape3D : public GodotShape3D {
virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override; 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 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 void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override;
virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override; virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override;
virtual bool intersect_point(const Vector3 &p_point) const override; virtual bool intersect_point(const Vector3 &p_point) const override;
virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override; virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override;
@ -495,7 +495,7 @@ struct GodotMotionShape3D : public GodotShape3D {
} }
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 void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override { r_amount = 0; }
virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const override { return false; } virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override { return false; }
virtual bool intersect_point(const Vector3 &p_point) const override { return false; } virtual bool intersect_point(const Vector3 &p_point) const override { return false; }
virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override { return p_point; } virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override { return p_point; }

View File

@ -1300,7 +1300,7 @@ struct _SoftBodyIntersectSegmentInfo {
} }
}; };
bool GodotSoftBodyShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { bool GodotSoftBodyShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const {
_SoftBodyIntersectSegmentInfo query_info; _SoftBodyIntersectSegmentInfo query_info;
query_info.soft_body = soft_body; query_info.soft_body = soft_body;
query_info.from = p_begin; query_info.from = p_begin;

View File

@ -257,18 +257,18 @@ class GodotSoftBodyShape3D : public GodotShape3D {
public: public:
GodotSoftBody3D *get_soft_body() const { return soft_body; } GodotSoftBody3D *get_soft_body() const { return soft_body; }
virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_SOFT_BODY; } virtual PhysicsServer3D::ShapeType get_type() const override { return PhysicsServer3D::SHAPE_SOFT_BODY; }
virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const { r_min = r_max = 0.0; } virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override { r_min = r_max = 0.0; }
virtual Vector3 get_support(const Vector3 &p_normal) const { return Vector3(); } virtual Vector3 get_support(const Vector3 &p_normal) const override { return Vector3(); }
virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const { r_amount = 0; } 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_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const override;
virtual bool intersect_point(const Vector3 &p_point) const; virtual bool intersect_point(const Vector3 &p_point) const override;
virtual Vector3 get_closest_point_to(const Vector3 &p_point) const; virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override;
virtual Vector3 get_moment_of_inertia(real_t p_mass) const { return Vector3(); } virtual Vector3 get_moment_of_inertia(real_t p_mass) const override { return Vector3(); }
virtual void set_data(const Variant &p_data) {} virtual void set_data(const Variant &p_data) override {}
virtual Variant get_data() const { return Variant(); } virtual Variant get_data() const override { return Variant(); }
void update_bounds(); void update_bounds();

View File

@ -148,7 +148,23 @@ bool GodotPhysicsDirectSpaceState3D::intersect_ray(const RayParameters &p_parame
Vector3 shape_point, shape_normal; Vector3 shape_point, shape_normal;
if (shape->intersect_segment(local_from, local_to, shape_point, shape_normal)) { if (shape->intersect_point(local_from)) {
if (p_parameters.hit_from_inside) {
// Hit shape at starting point.
min_d = 0;
res_point = local_from;
res_normal = Vector3();
res_shape = shape_idx;
res_obj = col_obj;
collided = true;
break;
} else {
// Ignore shape when starting inside.
continue;
}
}
if (shape->intersect_segment(local_from, local_to, shape_point, shape_normal, p_parameters.hit_back_faces)) {
Transform3D xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx); Transform3D xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
shape_point = xform.xform(shape_point); shape_point = xform.xform(shape_point);

View File

@ -172,12 +172,16 @@ void PhysicsRayQueryParameters2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_collide_with_areas", "enable"), &PhysicsRayQueryParameters2D::set_collide_with_areas); ClassDB::bind_method(D_METHOD("set_collide_with_areas", "enable"), &PhysicsRayQueryParameters2D::set_collide_with_areas);
ClassDB::bind_method(D_METHOD("is_collide_with_areas_enabled"), &PhysicsRayQueryParameters2D::is_collide_with_areas_enabled); ClassDB::bind_method(D_METHOD("is_collide_with_areas_enabled"), &PhysicsRayQueryParameters2D::is_collide_with_areas_enabled);
ClassDB::bind_method(D_METHOD("set_hit_from_inside", "enable"), &PhysicsRayQueryParameters2D::set_hit_from_inside);
ClassDB::bind_method(D_METHOD("is_hit_from_inside_enabled"), &PhysicsRayQueryParameters2D::is_hit_from_inside_enabled);
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "from"), "set_from", "get_from"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "from"), "set_from", "get_from");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "to"), "set_to", "get_to"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "to"), "set_to", "get_to");
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_mask", "get_collision_mask"); ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_mask", "get_collision_mask");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_exclude", "get_exclude"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_exclude", "get_exclude");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_bodies"), "set_collide_with_bodies", "is_collide_with_bodies_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_bodies"), "set_collide_with_bodies", "is_collide_with_bodies_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas"), "set_collide_with_areas", "is_collide_with_areas_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas"), "set_collide_with_areas", "is_collide_with_areas_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hit_from_inside"), "set_hit_from_inside", "is_hit_from_inside_enabled");
} }
/////////////////////////////////////////////////////// ///////////////////////////////////////////////////////

View File

@ -121,6 +121,8 @@ public:
bool collide_with_bodies = true; bool collide_with_bodies = true;
bool collide_with_areas = false; bool collide_with_areas = false;
bool hit_from_inside = false;
}; };
struct RayResult { struct RayResult {
@ -604,6 +606,9 @@ public:
void set_collide_with_areas(bool p_enable) { parameters.collide_with_areas = p_enable; } void set_collide_with_areas(bool p_enable) { parameters.collide_with_areas = p_enable; }
bool is_collide_with_areas_enabled() const { return parameters.collide_with_areas; } bool is_collide_with_areas_enabled() const { return parameters.collide_with_areas; }
void set_hit_from_inside(bool p_enable) { parameters.hit_from_inside = p_enable; }
bool is_hit_from_inside_enabled() const { return parameters.hit_from_inside; }
void set_exclude(const Vector<RID> &p_exclude); void set_exclude(const Vector<RID> &p_exclude);
Vector<RID> get_exclude() const; Vector<RID> get_exclude() const;
}; };

View File

@ -175,12 +175,20 @@ void PhysicsRayQueryParameters3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_collide_with_areas", "enable"), &PhysicsRayQueryParameters3D::set_collide_with_areas); ClassDB::bind_method(D_METHOD("set_collide_with_areas", "enable"), &PhysicsRayQueryParameters3D::set_collide_with_areas);
ClassDB::bind_method(D_METHOD("is_collide_with_areas_enabled"), &PhysicsRayQueryParameters3D::is_collide_with_areas_enabled); ClassDB::bind_method(D_METHOD("is_collide_with_areas_enabled"), &PhysicsRayQueryParameters3D::is_collide_with_areas_enabled);
ClassDB::bind_method(D_METHOD("set_hit_from_inside", "enable"), &PhysicsRayQueryParameters3D::set_hit_from_inside);
ClassDB::bind_method(D_METHOD("is_hit_from_inside_enabled"), &PhysicsRayQueryParameters3D::is_hit_from_inside_enabled);
ClassDB::bind_method(D_METHOD("set_hit_back_faces", "enable"), &PhysicsRayQueryParameters3D::set_hit_back_faces);
ClassDB::bind_method(D_METHOD("is_hit_back_faces_enabled"), &PhysicsRayQueryParameters3D::is_hit_back_faces_enabled);
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "from"), "set_from", "get_from"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "from"), "set_from", "get_from");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "to"), "set_to", "get_to"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "to"), "set_to", "get_to");
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_exclude", "get_exclude"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_exclude", "get_exclude");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_bodies"), "set_collide_with_bodies", "is_collide_with_bodies_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_bodies"), "set_collide_with_bodies", "is_collide_with_bodies_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas"), "set_collide_with_areas", "is_collide_with_areas_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas"), "set_collide_with_areas", "is_collide_with_areas_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hit_from_inside"), "set_hit_from_inside", "is_hit_from_inside_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hit_back_faces"), "set_hit_back_faces", "is_hit_back_faces_enabled");
} }
/////////////////////////////////////////////////////// ///////////////////////////////////////////////////////

View File

@ -125,6 +125,9 @@ public:
bool collide_with_bodies = true; bool collide_with_bodies = true;
bool collide_with_areas = false; bool collide_with_areas = false;
bool hit_from_inside = false;
bool hit_back_faces = true;
bool pick_ray = false; bool pick_ray = false;
}; };
@ -805,6 +808,12 @@ public:
void set_collide_with_areas(bool p_enable) { parameters.collide_with_areas = p_enable; } void set_collide_with_areas(bool p_enable) { parameters.collide_with_areas = p_enable; }
bool is_collide_with_areas_enabled() const { return parameters.collide_with_areas; } bool is_collide_with_areas_enabled() const { return parameters.collide_with_areas; }
void set_hit_from_inside(bool p_enable) { parameters.hit_from_inside = p_enable; }
bool is_hit_from_inside_enabled() const { return parameters.hit_from_inside; }
void set_hit_back_faces(bool p_enable) { parameters.hit_back_faces = p_enable; }
bool is_hit_back_faces_enabled() const { return parameters.hit_back_faces; }
void set_exclude(const Vector<RID> &p_exclude); void set_exclude(const Vector<RID> &p_exclude);
Vector<RID> get_exclude() const; Vector<RID> get_exclude() const;
}; };