Add ability to get barycentric coordinates from ray

This commit is contained in:
PrecisionRender 2023-03-05 15:59:22 -06:00
parent 262d1eaa63
commit af7f787c6e
16 changed files with 78 additions and 30 deletions

View File

@ -961,6 +961,11 @@ Vector3 Geometry3D::get_closest_point_to_segment_uncapped(const Vector3 &p_point
return ::Geometry3D::get_closest_point_to_segment_uncapped(p_point, s); return ::Geometry3D::get_closest_point_to_segment_uncapped(p_point, s);
} }
Vector3 Geometry3D::get_triangle_barycentric_coords(const Vector3 &p_point, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2) {
Vector3 res = ::Geometry3D::triangle_get_barycentric_coords(p_v0, p_v1, p_v2, p_point);
return res;
}
Variant Geometry3D::ray_intersects_triangle(const Vector3 &p_from, const Vector3 &p_dir, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2) { Variant Geometry3D::ray_intersects_triangle(const Vector3 &p_from, const Vector3 &p_dir, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2) {
Vector3 res; Vector3 res;
if (::Geometry3D::ray_intersects_triangle(p_from, p_dir, p_v0, p_v1, p_v2, &res)) { if (::Geometry3D::ray_intersects_triangle(p_from, p_dir, p_v0, p_v1, p_v2, &res)) {
@ -1034,6 +1039,8 @@ void Geometry3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_closest_point_to_segment_uncapped", "point", "s1", "s2"), &Geometry3D::get_closest_point_to_segment_uncapped); ClassDB::bind_method(D_METHOD("get_closest_point_to_segment_uncapped", "point", "s1", "s2"), &Geometry3D::get_closest_point_to_segment_uncapped);
ClassDB::bind_method(D_METHOD("get_triangle_barycentric_coords", "point", "a", "b", "c"), &Geometry3D::get_triangle_barycentric_coords);
ClassDB::bind_method(D_METHOD("ray_intersects_triangle", "from", "dir", "a", "b", "c"), &Geometry3D::ray_intersects_triangle); ClassDB::bind_method(D_METHOD("ray_intersects_triangle", "from", "dir", "a", "b", "c"), &Geometry3D::ray_intersects_triangle);
ClassDB::bind_method(D_METHOD("segment_intersects_triangle", "from", "to", "a", "b", "c"), &Geometry3D::segment_intersects_triangle); ClassDB::bind_method(D_METHOD("segment_intersects_triangle", "from", "to", "a", "b", "c"), &Geometry3D::segment_intersects_triangle);
ClassDB::bind_method(D_METHOD("segment_intersects_sphere", "from", "to", "sphere_position", "sphere_radius"), &Geometry3D::segment_intersects_sphere); ClassDB::bind_method(D_METHOD("segment_intersects_sphere", "from", "to", "sphere_position", "sphere_radius"), &Geometry3D::segment_intersects_sphere);

View File

@ -326,6 +326,7 @@ public:
Vector<Vector3> get_closest_points_between_segments(const Vector3 &p1, const Vector3 &p2, const Vector3 &q1, const Vector3 &q2); Vector<Vector3> get_closest_points_between_segments(const Vector3 &p1, const Vector3 &p2, const Vector3 &q1, const Vector3 &q2);
Vector3 get_closest_point_to_segment(const Vector3 &p_point, const Vector3 &p_a, const Vector3 &p_b); Vector3 get_closest_point_to_segment(const Vector3 &p_point, const Vector3 &p_a, const Vector3 &p_b);
Vector3 get_closest_point_to_segment_uncapped(const Vector3 &p_point, const Vector3 &p_a, const Vector3 &p_b); Vector3 get_closest_point_to_segment_uncapped(const Vector3 &p_point, const Vector3 &p_a, const Vector3 &p_b);
Vector3 get_triangle_barycentric_coords(const Vector3 &p_point, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2);
Variant ray_intersects_triangle(const Vector3 &p_from, const Vector3 &p_dir, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2); Variant ray_intersects_triangle(const Vector3 &p_from, const Vector3 &p_dir, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2);
Variant segment_intersects_triangle(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2); Variant segment_intersects_triangle(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2);

View File

@ -73,6 +73,17 @@
Given the two 3D segments ([param p1], [param p2]) and ([param q1], [param q2]), finds those two points on the two segments that are closest to each other. Returns a [PackedVector3Array] that contains this point on ([param p1], [param p2]) as well the accompanying point on ([param q1], [param q2]). Given the two 3D segments ([param p1], [param p2]) and ([param q1], [param q2]), finds those two points on the two segments that are closest to each other. Returns a [PackedVector3Array] that contains this point on ([param p1], [param p2]) as well the accompanying point on ([param q1], [param q2]).
</description> </description>
</method> </method>
<method name="get_triangle_barycentric_coords">
<return type="Vector3" />
<param index="0" name="point" type="Vector3" />
<param index="1" name="a" type="Vector3" />
<param index="2" name="b" type="Vector3" />
<param index="3" name="c" type="Vector3" />
<description>
Returns a [Vector3] containing weights based on how close a 3D position ([param point]) is to a triangle's different vertices ([param a], [param b] and [param c]). This is useful for interpolating between the data of different vertices in a triangle. One example use case is using this to smoothly rotate over a mesh instead of relying solely on face normals.
[url=https://en.wikipedia.org/wiki/Barycentric_coordinate_system]Here is a more detailed explanation of barycentric coordinates.[/url]
</description>
</method>
<method name="ray_intersects_triangle"> <method name="ray_intersects_triangle">
<return type="Variant" /> <return type="Variant" />
<param index="0" name="from" type="Vector3" /> <param index="0" name="from" type="Vector3" />

View File

@ -67,6 +67,8 @@
[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, 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]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]face_index[/code]: The face index at the intersection point.
[b]Note:[/b] Returns a valid number only if the intersected shape is a [ConcavePolygonShape3D]. Otherwise, [code]-1[/code] is returned.
[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.
If the ray did not intersect anything, then an empty dictionary is returned instead. If the ray did not intersect anything, then an empty dictionary is returned instead.

View File

@ -59,6 +59,12 @@
Returns the shape ID of the first object that the ray intersects, or [code]0[/code] if no object is intersecting the ray (i.e. [method is_colliding] returns [code]false[/code]). Returns the shape ID of the first object that the ray intersects, or [code]0[/code] if no object is intersecting the ray (i.e. [method is_colliding] returns [code]false[/code]).
</description> </description>
</method> </method>
<method name="get_collision_face_index" qualifiers="const">
<return type="int" />
<description>
Returns the collision object's face index at the collision point, or [code]-1[/code] if the shape intersecting the ray is not a [ConcavePolygonShape3D].
</description>
</method>
<method name="get_collision_mask_value" qualifiers="const"> <method name="get_collision_mask_value" qualifiers="const">
<return type="bool" /> <return type="bool" />
<param index="0" name="layer_number" type="int" /> <param index="0" name="layer_number" type="int" />

View File

@ -104,6 +104,10 @@ Vector3 RayCast3D::get_collision_normal() const {
return collision_normal; return collision_normal;
} }
int RayCast3D::get_collision_face_index() const {
return collision_face_index;
}
void RayCast3D::set_enabled(bool p_enabled) { void RayCast3D::set_enabled(bool p_enabled) {
enabled = p_enabled; enabled = p_enabled;
update_gizmos(); update_gizmos();
@ -232,6 +236,7 @@ void RayCast3D::_update_raycast_state() {
against_rid = rr.rid; against_rid = rr.rid;
collision_point = rr.position; collision_point = rr.position;
collision_normal = rr.normal; collision_normal = rr.normal;
collision_face_index = rr.face_index;
against_shape = rr.shape; against_shape = rr.shape;
} else { } else {
collided = false; collided = false;
@ -321,6 +326,7 @@ void RayCast3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_collider_shape"), &RayCast3D::get_collider_shape); ClassDB::bind_method(D_METHOD("get_collider_shape"), &RayCast3D::get_collider_shape);
ClassDB::bind_method(D_METHOD("get_collision_point"), &RayCast3D::get_collision_point); ClassDB::bind_method(D_METHOD("get_collision_point"), &RayCast3D::get_collision_point);
ClassDB::bind_method(D_METHOD("get_collision_normal"), &RayCast3D::get_collision_normal); ClassDB::bind_method(D_METHOD("get_collision_normal"), &RayCast3D::get_collision_normal);
ClassDB::bind_method(D_METHOD("get_collision_face_index"), &RayCast3D::get_collision_face_index);
ClassDB::bind_method(D_METHOD("add_exception_rid", "rid"), &RayCast3D::add_exception_rid); ClassDB::bind_method(D_METHOD("add_exception_rid", "rid"), &RayCast3D::add_exception_rid);
ClassDB::bind_method(D_METHOD("add_exception", "node"), &RayCast3D::add_exception); ClassDB::bind_method(D_METHOD("add_exception", "node"), &RayCast3D::add_exception);

View File

@ -45,6 +45,7 @@ class RayCast3D : public Node3D {
int against_shape = 0; int against_shape = 0;
Vector3 collision_point; Vector3 collision_point;
Vector3 collision_normal; Vector3 collision_normal;
int collision_face_index = -1;
Vector3 target_position = Vector3(0, -1, 0); Vector3 target_position = Vector3(0, -1, 0);
HashSet<RID> exclude; HashSet<RID> exclude;
@ -122,6 +123,7 @@ public:
int get_collider_shape() const; int get_collider_shape() const;
Vector3 get_collision_point() const; Vector3 get_collision_point() const;
Vector3 get_collision_normal() const; Vector3 get_collision_normal() const;
int get_collision_face_index() const;
void add_exception_rid(const RID &p_rid); void add_exception_rid(const RID &p_rid);
void add_exception(const CollisionObject3D *p_node); void add_exception(const CollisionObject3D *p_node);

View File

@ -168,7 +168,6 @@ void GodotBodyPair3D::validate_contacts() {
// adjust the velocity of A down so that it will just slightly intersect the collider instead of blowing right past it. // adjust the velocity of A down so that it will just slightly intersect the collider instead of blowing right past it.
bool GodotBodyPair3D::_test_ccd(real_t p_step, GodotBody3D *p_A, int p_shape_A, const Transform3D &p_xform_A, GodotBody3D *p_B, int p_shape_B, const Transform3D &p_xform_B) { bool GodotBodyPair3D::_test_ccd(real_t p_step, GodotBody3D *p_A, int p_shape_A, const Transform3D &p_xform_A, GodotBody3D *p_B, int p_shape_B, const Transform3D &p_xform_B) {
GodotShape3D *shape_A_ptr = p_A->get_shape(p_shape_A); GodotShape3D *shape_A_ptr = p_A->get_shape(p_shape_A);
GodotShape3D *shape_B_ptr = p_B->get_shape(p_shape_B);
Vector3 motion = p_A->get_linear_velocity() * p_step; Vector3 motion = p_A->get_linear_velocity() * p_step;
real_t mlen = motion.length(); real_t mlen = motion.length();
@ -221,7 +220,8 @@ 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 (shape_B_ptr->intersect_segment(local_from, local_to, rpos, rnorm, true)) { int fi = -1;
if (p_B->get_shape(p_shape_B)->intersect_segment(local_from, local_to, rpos, rnorm, fi, true)) {
float hit_length = local_from.distance_to(rpos); float hit_length = local_from.distance_to(rpos);
if (hit_length < segment_hit_length) { if (hit_length < segment_hit_length) {
segment_support_idx = i; segment_support_idx = i;

View File

@ -106,7 +106,8 @@ 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, true)) { int fi = -1;
if (!p_shape_B->intersect_segment(from, to, p, n, fi, true)) {
return false; return false;
} }

View File

@ -126,7 +126,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, bool p_hit_back_faces) const { bool GodotWorldBoundaryShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, int &r_face_index, 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;
@ -207,7 +207,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, bool p_hit_back_faces) const { bool GodotSeparationRayShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, int &r_face_index, bool p_hit_back_faces) const {
return false; //simply not possible return false; //simply not possible
} }
@ -275,7 +275,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, bool p_hit_back_faces) const { bool GodotSphereShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, int &r_face_index, 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);
} }
@ -417,7 +417,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, bool p_hit_back_faces) const { bool GodotBoxShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, int &r_face_index, bool p_hit_back_faces) const {
AABB aabb_ext(-half_extents, half_extents * 2.0); AABB aabb_ext(-half_extents, half_extents * 2.0);
return aabb_ext.intersects_segment(p_begin, p_end, &r_result, &r_normal); return aabb_ext.intersects_segment(p_begin, p_end, &r_result, &r_normal);
@ -551,7 +551,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, bool p_hit_back_faces) const { bool GodotCapsuleShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, int &r_face_index, 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;
@ -743,7 +743,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, bool p_hit_back_faces) const { bool GodotCylinderShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, int &r_face_index, 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);
} }
@ -975,7 +975,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, bool p_hit_back_faces) const { bool GodotConvexPolygonShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, int &r_face_index, 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();
@ -1252,7 +1252,7 @@ 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, bool p_hit_back_faces) const { bool GodotFaceShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, int &r_face_index, 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;
@ -1362,12 +1362,14 @@ 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, true)) { int face_index = params_bvh->face_index;
if (face->intersect_segment(p_params->from, p_params->to, res, normal, face_index, 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;
p_params->result = res; p_params->result = res;
p_params->normal = normal; p_params->normal = normal;
p_params->face_index = face_index;
p_params->collisions++; p_params->collisions++;
} }
} }
@ -1381,7 +1383,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, bool p_hit_back_faces) const { bool GodotConcavePolygonShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, int &r_face_index, bool p_hit_back_faces) const {
if (faces.size() == 0) { if (faces.size() == 0) {
return false; return false;
} }
@ -1411,6 +1413,7 @@ bool GodotConcavePolygonShape3D::intersect_segment(const Vector3 &p_begin, const
if (params.collisions > 0) { if (params.collisions > 0) {
r_result = params.result; r_result = params.result;
r_normal = params.normal; r_normal = params.normal;
r_face_index = params.face_index;
return true; return true;
} else { } else {
return false; return false;
@ -1734,9 +1737,11 @@ 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, true)) { int fi = -1;
if (p_params.face->intersect_segment(p_params.from, p_params.to, res, normal, fi, true)) {
p_params.result = res; p_params.result = res;
p_params.normal = normal; p_params.normal = normal;
return true; return true;
} }
@ -1940,7 +1945,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, bool p_hit_back_faces) const { bool GodotHeightMapShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal, int &r_face_index, bool p_hit_back_faces) const {
if (heights.is_empty()) { if (heights.is_empty()) {
return false; return false;
} }

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, bool p_hit_back_faces) const = 0; virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal, int &r_face_index, 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, bool p_hit_back_faces) const override; virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, int &r_face_index, 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, bool p_hit_back_faces) const override; virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, int &r_face_index, 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, bool p_hit_back_faces) const override; virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, int &r_face_index, 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, bool p_hit_back_faces) const override; virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, int &r_face_index, 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, bool p_hit_back_faces) const override; virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, int &r_face_index, 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, bool p_hit_back_faces) const override; virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, int &r_face_index, 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;
@ -290,7 +290,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, bool p_hit_back_faces) const override; virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, int &r_face_index, 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;
@ -347,6 +347,7 @@ struct GodotConcavePolygonShape3D : public GodotConcaveShape3D {
Vector3 result; Vector3 result;
Vector3 normal; Vector3 normal;
int face_index = -1;
real_t min_d = 1e20; real_t min_d = 1e20;
int collisions = 0; int collisions = 0;
}; };
@ -368,7 +369,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, bool p_hit_back_faces) const override; virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, int &r_face_index, 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;
@ -431,7 +432,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, bool p_hit_back_faces) const override; virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal, int &r_face_index, 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;
@ -459,7 +460,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, bool p_hit_back_faces) const override; virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, int &r_face_index, 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;
@ -498,7 +499,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, bool p_hit_back_faces) const override { return false; } virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, int &r_face_index, 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

@ -1266,7 +1266,7 @@ struct _SoftBodyIntersectSegmentInfo {
} }
}; };
bool GodotSoftBodyShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const { bool GodotSoftBodyShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, int &r_face_index, 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

@ -259,7 +259,7 @@ public:
virtual Vector3 get_support(const Vector3 &p_normal) const override { 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 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, bool p_hit_back_faces) const override; virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, int &r_face_index, 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 { return Vector3(); } virtual Vector3 get_moment_of_inertia(real_t p_mass) const override { return Vector3(); }

View File

@ -120,6 +120,7 @@ bool GodotPhysicsDirectSpaceState3D::intersect_ray(const RayParameters &p_parame
bool collided = false; bool collided = false;
Vector3 res_point, res_normal; Vector3 res_point, res_normal;
int res_face_index = -1;
int res_shape = -1; int res_shape = -1;
const GodotCollisionObject3D *res_obj = nullptr; const GodotCollisionObject3D *res_obj = nullptr;
real_t min_d = 1e10; real_t min_d = 1e10;
@ -148,6 +149,7 @@ bool GodotPhysicsDirectSpaceState3D::intersect_ray(const RayParameters &p_parame
const GodotShape3D *shape = col_obj->get_shape(shape_idx); const GodotShape3D *shape = col_obj->get_shape(shape_idx);
Vector3 shape_point, shape_normal; Vector3 shape_point, shape_normal;
int shape_face_index = -1;
if (shape->intersect_point(local_from)) { if (shape->intersect_point(local_from)) {
if (p_parameters.hit_from_inside) { if (p_parameters.hit_from_inside) {
@ -165,7 +167,7 @@ bool GodotPhysicsDirectSpaceState3D::intersect_ray(const RayParameters &p_parame
} }
} }
if (shape->intersect_segment(local_from, local_to, shape_point, shape_normal, p_parameters.hit_back_faces)) { if (shape->intersect_segment(local_from, local_to, shape_point, shape_normal, shape_face_index, 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);
@ -175,6 +177,7 @@ bool GodotPhysicsDirectSpaceState3D::intersect_ray(const RayParameters &p_parame
min_d = ld; min_d = ld;
res_point = shape_point; res_point = shape_point;
res_normal = inv_xform.basis.xform_inv(shape_normal).normalized(); res_normal = inv_xform.basis.xform_inv(shape_normal).normalized();
res_face_index = shape_face_index;
res_shape = shape_idx; res_shape = shape_idx;
res_obj = col_obj; res_obj = col_obj;
collided = true; collided = true;
@ -194,6 +197,7 @@ bool GodotPhysicsDirectSpaceState3D::intersect_ray(const RayParameters &p_parame
r_result.collider = nullptr; r_result.collider = nullptr;
} }
r_result.normal = res_normal; r_result.normal = res_normal;
r_result.face_index = res_face_index;
r_result.position = res_point; r_result.position = res_point;
r_result.rid = res_obj->get_self(); r_result.rid = res_obj->get_self();
r_result.shape = res_shape; r_result.shape = res_shape;

View File

@ -362,6 +362,7 @@ Dictionary PhysicsDirectSpaceState3D::_intersect_ray(const Ref<PhysicsRayQueryPa
Dictionary d; Dictionary d;
d["position"] = result.position; d["position"] = result.position;
d["normal"] = result.normal; d["normal"] = result.normal;
d["face_index"] = result.face_index;
d["collider_id"] = result.collider_id; d["collider_id"] = result.collider_id;
d["collider"] = result.collider; d["collider"] = result.collider;
d["shape"] = result.shape; d["shape"] = result.shape;

View File

@ -151,6 +151,7 @@ public:
struct RayResult { struct RayResult {
Vector3 position; Vector3 position;
Vector3 normal; Vector3 normal;
int face_index = -1;
RID rid; RID rid;
ObjectID collider_id; ObjectID collider_id;
Object *collider = nullptr; Object *collider = nullptr;