Restore RayShape as a regular shape type
Partial revert from previously removing ray shapes completely, added back as a shape type but without the specific character controller code.
This commit is contained in:
parent
c89a5fb8be
commit
45c7af9862
33 changed files with 842 additions and 26 deletions
|
|
@ -1115,11 +1115,13 @@ bool sat_2d_calculate_penetration(const Shape2DSW *p_shape_A, const Transform2D
|
|||
PhysicsServer2D::ShapeType type_A = p_shape_A->get_type();
|
||||
|
||||
ERR_FAIL_COND_V(type_A == PhysicsServer2D::SHAPE_WORLD_MARGIN, false);
|
||||
ERR_FAIL_COND_V(type_A == PhysicsServer2D::SHAPE_RAY, false);
|
||||
ERR_FAIL_COND_V(p_shape_A->is_concave(), false);
|
||||
|
||||
PhysicsServer2D::ShapeType type_B = p_shape_B->get_type();
|
||||
|
||||
ERR_FAIL_COND_V(type_B == PhysicsServer2D::SHAPE_WORLD_MARGIN, false);
|
||||
ERR_FAIL_COND_V(type_B == PhysicsServer2D::SHAPE_RAY, false);
|
||||
ERR_FAIL_COND_V(p_shape_B->is_concave(), false);
|
||||
|
||||
static const CollisionFunc collision_table[5][5] = {
|
||||
|
|
@ -1382,23 +1384,23 @@ bool sat_2d_calculate_penetration(const Shape2DSW *p_shape_A, const Transform2D
|
|||
|
||||
if (p_margin_A || p_margin_B) {
|
||||
if (*motion_A == Vector2() && *motion_B == Vector2()) {
|
||||
collision_func = collision_table_margin[type_A - 1][type_B - 1];
|
||||
collision_func = collision_table_margin[type_A - 2][type_B - 2];
|
||||
} else if (*motion_A != Vector2() && *motion_B == Vector2()) {
|
||||
collision_func = collision_table_castA_margin[type_A - 1][type_B - 1];
|
||||
collision_func = collision_table_castA_margin[type_A - 2][type_B - 2];
|
||||
} else if (*motion_A == Vector2() && *motion_B != Vector2()) {
|
||||
collision_func = collision_table_castB_margin[type_A - 1][type_B - 1];
|
||||
collision_func = collision_table_castB_margin[type_A - 2][type_B - 2];
|
||||
} else {
|
||||
collision_func = collision_table_castA_castB_margin[type_A - 1][type_B - 1];
|
||||
collision_func = collision_table_castA_castB_margin[type_A - 2][type_B - 2];
|
||||
}
|
||||
} else {
|
||||
if (*motion_A == Vector2() && *motion_B == Vector2()) {
|
||||
collision_func = collision_table[type_A - 1][type_B - 1];
|
||||
collision_func = collision_table[type_A - 2][type_B - 2];
|
||||
} else if (*motion_A != Vector2() && *motion_B == Vector2()) {
|
||||
collision_func = collision_table_castA[type_A - 1][type_B - 1];
|
||||
collision_func = collision_table_castA[type_A - 2][type_B - 2];
|
||||
} else if (*motion_A == Vector2() && *motion_B != Vector2()) {
|
||||
collision_func = collision_table_castB[type_A - 1][type_B - 1];
|
||||
collision_func = collision_table_castB[type_A - 2][type_B - 2];
|
||||
} else {
|
||||
collision_func = collision_table_castA_castB[type_A - 1][type_B - 1];
|
||||
collision_func = collision_table_castA_castB[type_A - 2][type_B - 2];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -73,6 +73,49 @@ bool CollisionSolver2DSW::solve_static_world_margin(const Shape2DSW *p_shape_A,
|
|||
return found;
|
||||
}
|
||||
|
||||
bool CollisionSolver2DSW::solve_raycast(const Shape2DSW *p_shape_A, const Vector2 &p_motion_A, const Transform2D &p_transform_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *sep_axis) {
|
||||
const RayShape2DSW *ray = static_cast<const RayShape2DSW *>(p_shape_A);
|
||||
if (p_shape_B->get_type() == PhysicsServer2D::SHAPE_RAY) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Vector2 from = p_transform_A.get_origin();
|
||||
Vector2 to = from + p_transform_A[1] * ray->get_length();
|
||||
if (p_motion_A != Vector2()) {
|
||||
//not the best but should be enough
|
||||
Vector2 normal = (to - from).normalized();
|
||||
to += normal * MAX(0.0, normal.dot(p_motion_A));
|
||||
}
|
||||
Vector2 support_A = to;
|
||||
|
||||
Transform2D invb = p_transform_B.affine_inverse();
|
||||
from = invb.xform(from);
|
||||
to = invb.xform(to);
|
||||
|
||||
Vector2 p, n;
|
||||
if (!p_shape_B->intersect_segment(from, to, p, n)) {
|
||||
if (sep_axis) {
|
||||
*sep_axis = p_transform_A[1].normalized();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Vector2 support_B = p_transform_B.xform(p);
|
||||
if (ray->get_slips_on_slope()) {
|
||||
Vector2 global_n = invb.basis_xform_inv(n).normalized();
|
||||
support_B = support_A + (support_B - support_A).length() * global_n;
|
||||
}
|
||||
|
||||
if (p_result_callback) {
|
||||
if (p_swap_result) {
|
||||
p_result_callback(support_B, support_A, p_userdata);
|
||||
} else {
|
||||
p_result_callback(support_A, support_B, p_userdata);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
struct _ConcaveCollisionInfo2D {
|
||||
const Transform2D *transform_A;
|
||||
const Shape2DSW *shape_A;
|
||||
|
|
@ -177,6 +220,17 @@ bool CollisionSolver2DSW::solve(const Shape2DSW *p_shape_A, const Transform2D &p
|
|||
return solve_static_world_margin(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false);
|
||||
}
|
||||
|
||||
} else if (type_A == PhysicsServer2D::SHAPE_RAY) {
|
||||
if (type_B == PhysicsServer2D::SHAPE_RAY) {
|
||||
return false; //no ray-ray
|
||||
}
|
||||
|
||||
if (swap) {
|
||||
return solve_raycast(p_shape_B, p_motion_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true, sep_axis);
|
||||
} else {
|
||||
return solve_raycast(p_shape_A, p_motion_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false, sep_axis);
|
||||
}
|
||||
|
||||
} else if (concave_B) {
|
||||
if (concave_A) {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -45,6 +45,9 @@ RID PhysicsServer2DSW::_shape_create(ShapeType p_shape) {
|
|||
case SHAPE_WORLD_MARGIN: {
|
||||
shape = memnew(WorldMarginShape2DSW);
|
||||
} break;
|
||||
case SHAPE_RAY: {
|
||||
shape = memnew(RayShape2DSW);
|
||||
} break;
|
||||
case SHAPE_SEGMENT: {
|
||||
shape = memnew(SegmentShape2DSW);
|
||||
} break;
|
||||
|
|
@ -79,6 +82,10 @@ RID PhysicsServer2DSW::world_margin_shape_create() {
|
|||
return _shape_create(SHAPE_WORLD_MARGIN);
|
||||
}
|
||||
|
||||
RID PhysicsServer2DSW::ray_shape_create() {
|
||||
return _shape_create(SHAPE_RAY);
|
||||
}
|
||||
|
||||
RID PhysicsServer2DSW::segment_shape_create() {
|
||||
return _shape_create(SHAPE_SEGMENT);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ public:
|
|||
};
|
||||
|
||||
virtual RID world_margin_shape_create() override;
|
||||
virtual RID ray_shape_create() override;
|
||||
virtual RID segment_shape_create() override;
|
||||
virtual RID circle_shape_create() override;
|
||||
virtual RID rectangle_shape_create() override;
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ public:
|
|||
|
||||
//FUNC1RID(shape,ShapeType); todo fix
|
||||
FUNCRID(world_margin_shape)
|
||||
FUNCRID(ray_shape)
|
||||
FUNCRID(segment_shape)
|
||||
FUNCRID(circle_shape)
|
||||
FUNCRID(rectangle_shape)
|
||||
|
|
|
|||
|
|
@ -143,6 +143,46 @@ Variant WorldMarginShape2DSW::get_data() const {
|
|||
/*********************************************************/
|
||||
/*********************************************************/
|
||||
|
||||
void RayShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const {
|
||||
r_amount = 1;
|
||||
|
||||
if (p_normal.y > 0) {
|
||||
*r_supports = Vector2(0, length);
|
||||
} else {
|
||||
*r_supports = Vector2();
|
||||
}
|
||||
}
|
||||
|
||||
bool RayShape2DSW::contains_point(const Vector2 &p_point) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RayShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const {
|
||||
return false; //rays can't be intersected
|
||||
}
|
||||
|
||||
real_t RayShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const {
|
||||
return 0; //rays are mass-less
|
||||
}
|
||||
|
||||
void RayShape2DSW::set_data(const Variant &p_data) {
|
||||
Dictionary d = p_data;
|
||||
length = d["length"];
|
||||
slips_on_slope = d["slips_on_slope"];
|
||||
configure(Rect2(0, 0, 0.001, length));
|
||||
}
|
||||
|
||||
Variant RayShape2DSW::get_data() const {
|
||||
Dictionary d;
|
||||
d["length"] = length;
|
||||
d["slips_on_slope"] = slips_on_slope;
|
||||
return d;
|
||||
}
|
||||
|
||||
/*********************************************************/
|
||||
/*********************************************************/
|
||||
/*********************************************************/
|
||||
|
||||
void SegmentShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const {
|
||||
if (Math::abs(p_normal.dot(n)) > _SEGMENT_IS_VALID_SUPPORT_THRESHOLD) {
|
||||
r_supports[0] = a;
|
||||
|
|
|
|||
|
|
@ -177,6 +177,41 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class RayShape2DSW : public Shape2DSW {
|
||||
real_t length;
|
||||
bool slips_on_slope;
|
||||
|
||||
public:
|
||||
_FORCE_INLINE_ real_t get_length() const { return length; }
|
||||
_FORCE_INLINE_ bool get_slips_on_slope() const { return slips_on_slope; }
|
||||
|
||||
virtual PhysicsServer2D::ShapeType get_type() const { return PhysicsServer2D::SHAPE_RAY; }
|
||||
|
||||
virtual void project_rangev(const Vector2 &p_normal, const Transform2D &p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal, p_transform, r_min, r_max); }
|
||||
virtual void get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const;
|
||||
|
||||
virtual bool contains_point(const Vector2 &p_point) const;
|
||||
virtual bool intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const;
|
||||
virtual real_t get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const;
|
||||
|
||||
virtual void set_data(const Variant &p_data);
|
||||
virtual Variant get_data() const;
|
||||
|
||||
_FORCE_INLINE_ void project_range(const Vector2 &p_normal, const Transform2D &p_transform, real_t &r_min, real_t &r_max) const {
|
||||
//real large
|
||||
r_max = p_normal.dot(p_transform.get_origin());
|
||||
r_min = p_normal.dot(p_transform.xform(Vector2(0, length)));
|
||||
if (r_max < r_min) {
|
||||
SWAP(r_max, r_min);
|
||||
}
|
||||
}
|
||||
|
||||
DEFAULT_PROJECT_RANGE_CAST
|
||||
|
||||
_FORCE_INLINE_ RayShape2DSW() {}
|
||||
_FORCE_INLINE_ RayShape2DSW(real_t p_length) { length = p_length; }
|
||||
};
|
||||
|
||||
class SegmentShape2DSW : public Shape2DSW {
|
||||
Vector2 a;
|
||||
Vector2 b;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue