collision_check will now return 1 if there is a collision, and write collision data to the new out variables
This commit is contained in:
parent
f237da1b93
commit
b7721baeb7
|
@ -8,7 +8,7 @@
|
||||||
typedef struct Range {float min; float max; } Range;
|
typedef struct Range {float min; float max; } Range;
|
||||||
|
|
||||||
static
|
static
|
||||||
Range _shape_get_range_on_axis(PhysicsEntity self, Vector axis) {
|
Range _internal_collision_get_range_on_axis(PhysicsEntity self, Vector axis) {
|
||||||
Vector point = shape_get_point_transformed(self.tc->get_shape(self.data), 0, *self.transformable->get_transform(self.data));
|
Vector point = shape_get_point_transformed(self.tc->get_shape(self.data), 0, *self.transformable->get_transform(self.data));
|
||||||
float dot = vdotf(axis, point);
|
float dot = vdotf(axis, point);
|
||||||
Range range = {dot, dot};
|
Range range = {dot, dot};
|
||||||
|
@ -26,9 +26,9 @@ Range _shape_get_range_on_axis(PhysicsEntity self, Vector axis) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
Vector _shape_overlap_on_axis(PhysicsEntity self, PhysicsEntity other, Vector axis) {
|
Vector _internal_collision_overlap_on_axis(PhysicsEntity self, PhysicsEntity other, Vector axis) {
|
||||||
Range a_range = _shape_get_range_on_axis(self, axis);
|
Range a_range = _internal_collision_get_range_on_axis(self, axis);
|
||||||
Range b_range = _shape_get_range_on_axis(other, axis);
|
Range b_range = _internal_collision_get_range_on_axis(other, axis);
|
||||||
|
|
||||||
if(a_range.min <= b_range.max && b_range.min <= b_range.max)
|
if(a_range.min <= b_range.max && b_range.min <= b_range.max)
|
||||||
return vmulff(axis, fminf(b_range.max - b_range.min, b_range.min - a_range.max));
|
return vmulff(axis, fminf(b_range.max - b_range.min, b_range.min - a_range.max));
|
||||||
|
@ -37,27 +37,31 @@ Vector _shape_overlap_on_axis(PhysicsEntity self, PhysicsEntity other, Vector ax
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
Collision _shape_get_overlap_internal(PhysicsEntity self, PhysicsEntity other) {
|
int _internal_collision_get_overlap(PhysicsEntity self, PhysicsEntity other, Collision* out) {
|
||||||
// The shortest escape vector found so far
|
// get components used
|
||||||
|
Shape* self_shape = self.tc->get_shape(self.data);
|
||||||
|
Transform* self_transform = self.transformable->get_transform(self.data);
|
||||||
|
|
||||||
|
// the shortest distance to solve collision found so far
|
||||||
Vector shortest_escape = InfinityVector;
|
Vector shortest_escape = InfinityVector;
|
||||||
// the squared length of the shortest escape vector found so far
|
// the squared length of the shortest escape vector found so far
|
||||||
float shortest_sqrmag = INFINITY;
|
float shortest_sqrmag = INFINITY;
|
||||||
// the first index of the points on the edge
|
// the first index of the points on the edge
|
||||||
size_t shortest_escape_edge = 0;
|
size_t shortest_escape_edge = 0;
|
||||||
// the number of points in the shape of self
|
// the number of points in the shape of self
|
||||||
size_t self_point_count = shape_get_points_count(self.tc->get_shape(self.data));
|
size_t self_point_count = shape_get_points_count(self_shape);
|
||||||
|
|
||||||
for(size_t point_index = 0; point_index < self_point_count; ++point_index) {
|
for(size_t point_index = 0; point_index < self_point_count; ++point_index) {
|
||||||
// the next point on the line
|
// the next point on the line
|
||||||
size_t next_index = (point_index + 1) % self_point_count;
|
size_t next_index = (point_index + 1) % self_point_count;
|
||||||
// get the two points defining the collision edge
|
// get the two points defining the collision edge
|
||||||
Vector a = shape_get_point_transformed(self.tc->get_shape(self.data), point_index, *self.transformable->get_transform(self.data));
|
Vector a = shape_get_point_transformed(self.tc->get_shape(self.data), point_index, *self_transform);
|
||||||
Vector b = shape_get_point_transformed(self.tc->get_shape(self.data), next_index, *self.transformable->get_transform(self.data));
|
Vector b = shape_get_point_transformed(self.tc->get_shape(self.data), next_index, *self_transform);
|
||||||
// the direction of the line
|
// the direction of the line
|
||||||
Vector diff = vsubf(b, a);
|
Vector diff = vsubf(b, a);
|
||||||
|
|
||||||
// the smallest escape vector on this axis
|
// the smallest escape vector on this axis
|
||||||
Vector escape = _shape_overlap_on_axis(self, other, vnormalizedf(diff));
|
Vector escape = _internal_collision_overlap_on_axis(self, other, vnormalizedf(diff));
|
||||||
float sqr_mag = vsqrmagnitudef(escape);
|
float sqr_mag = vsqrmagnitudef(escape);
|
||||||
if(sqr_mag < shortest_sqrmag) {
|
if(sqr_mag < shortest_sqrmag) {
|
||||||
shortest_sqrmag = sqr_mag;
|
shortest_sqrmag = sqr_mag;
|
||||||
|
@ -69,20 +73,51 @@ Collision _shape_get_overlap_internal(PhysicsEntity self, PhysicsEntity other) {
|
||||||
RigidBody* rba = self.tc->get_rigidbody(self.data);
|
RigidBody* rba = self.tc->get_rigidbody(self.data);
|
||||||
RigidBody* rbb = self.tc->get_rigidbody(self.data);
|
RigidBody* rbb = self.tc->get_rigidbody(self.data);
|
||||||
|
|
||||||
return (Collision) {
|
*out = (Collision) {
|
||||||
.edge_left = shortest_escape_edge,
|
|
||||||
.edge_right = (1 + shortest_escape_edge) % self_point_count,
|
|
||||||
.normal = vnormalizedf(shortest_escape),
|
|
||||||
.velocity = vsubf(rigidbody_get_velocity(rba), rigidbody_get_velocity(rbb)),
|
|
||||||
.other = other,
|
.other = other,
|
||||||
.separation_force = shortest_escape
|
|
||||||
|
.point = InfinityVector,
|
||||||
|
.normal = vnormalizedf(shortest_escape),
|
||||||
|
|
||||||
|
.velocity = vsubf(rigidbody_get_velocity(rba), rigidbody_get_velocity(rbb)),
|
||||||
|
.separation_force = shortest_escape,
|
||||||
|
|
||||||
|
.edge_left = shape_get_point_transformed(self_shape, shortest_escape_edge, *self_transform),
|
||||||
|
.edge_right = shape_get_point_transformed(self_shape, (1 + shortest_escape_edge) % self_point_count, *self_transform),
|
||||||
|
};
|
||||||
|
|
||||||
|
return shortest_sqrmag != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
Collision _internal_collision_invert(Collision collision_a, PhysicsEntity a) {
|
||||||
|
return (Collision){
|
||||||
|
.other = a,
|
||||||
|
.point = collision_a.point,
|
||||||
|
.normal = vinvf(collision_a.normal),
|
||||||
|
.velocity = vinvf(collision_a.velocity),
|
||||||
|
.separation_force = vinvf(collision_a.separation_force),
|
||||||
|
.edge_left = collision_a.edge_left,
|
||||||
|
.edge_right = collision_a.edge_right,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Collision get_collision(PhysicsEntity a, PhysicsEntity b) {
|
int collision_check(PhysicsEntity a, PhysicsEntity b, Collision* out_a, Collision* out_b) {
|
||||||
Collision self_first = _shape_get_overlap_internal(a, b);
|
Collision collision_a, collision_b;
|
||||||
Collision other_first = _shape_get_overlap_internal(b, a);
|
int collision_a_overlaps = _internal_collision_get_overlap(a, b, &collision_a);
|
||||||
return vsqrmagnitudef(self_first.separation_force) < vsqrmagnitudef(other_first.separation_force)
|
int collision_b_overlaps = _internal_collision_get_overlap(b, a, &collision_b);
|
||||||
? self_first
|
|
||||||
: other_first;
|
if(!collision_a_overlaps && !collision_b_overlaps) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(vsqrmagnitudef(collision_a.separation_force) < vsqrmagnitudef(collision_b.separation_force)) {
|
||||||
|
collision_b = _internal_collision_invert(collision_a, a);
|
||||||
|
} else {
|
||||||
|
collision_a = _internal_collision_invert(collision_b, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_a = collision_a;
|
||||||
|
*out_b = collision_b;
|
||||||
|
return 1;
|
||||||
}
|
}
|
|
@ -7,14 +7,17 @@
|
||||||
|
|
||||||
typedef struct Collision {
|
typedef struct Collision {
|
||||||
PhysicsEntity other;
|
PhysicsEntity other;
|
||||||
|
|
||||||
Vector point;
|
Vector point;
|
||||||
Vector normal;
|
Vector normal;
|
||||||
|
|
||||||
Vector velocity;
|
Vector velocity;
|
||||||
Vector separation_force;
|
Vector separation_force;
|
||||||
size_t edge_left;
|
|
||||||
size_t edge_right;
|
Vector edge_left;
|
||||||
|
Vector edge_right;
|
||||||
} Collision;
|
} Collision;
|
||||||
|
|
||||||
extern Collision get_collision(PhysicsEntity a, PhysicsEntity b);
|
extern int collision_check(PhysicsEntity a, PhysicsEntity b, Collision* out_a, Collision* out_b);
|
||||||
|
|
||||||
#endif // !_fencer_collision_h
|
#endif // !_fencer_collision_h
|
||||||
|
|
Loading…
Reference in a new issue