Skip to content

Commit

Permalink
新增射线检测
Browse files Browse the repository at this point in the history
  • Loading branch information
esengine committed Aug 3, 2020
1 parent bc66268 commit c692f01
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 0 deletions.
48 changes: 48 additions & 0 deletions source/src/Physics/Shapes/RealtimeCollisions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
module es {
export class RealtimeCollisions {
public static intersectMovingCircleToBox(s: Circle, b: Box, movement: Vector2): number {
// 计算用球面半径r inflate b得到的AABB
let e = b.bounds;
e.inflate(s.radius, s.radius);

// 射线与展开矩形e相交。如果射线错过了e,则退出不相交,否则得到相交点p和时间t
let ray = new Ray2D(Vector2.subtract(s.position, movement), s.position);
let time = e.rayIntersects(ray);
if (time > 1)
return time;

// 求交点
let point = Vector2.add(ray.start, Vector2.add(ray.direction, new Vector2(time)));

// 计算b的最小面和最大面p的交点在哪个面之外。注意,u和v不能有相同的位集,它们之间必须至少有一个位集。
let u, v = 0;
if (point.x < b.bounds.left)
u |= 1;
if (point.x > b.bounds.right)
v |= 1;
if (point.y < b.bounds.top)
u |= 2;
if (point.y > b.bounds.bottom)
v |= 2;

// 将所有位集合成位掩码(注意u + v == u | v)
let m = u + v;

// 如果所有的3位都被设置,那么点在一个顶点区域
if (m == 3){
// 现在必须相交的部分,如果一个或多个击中对胶囊的两边会合在斜面和返回的最佳时间
// TODO: 需要实现这个
console.log(`m == 3. corner ${Time.frameCount}`);
}

// 如果m中只设置了一个位,那么点在一个面区域
if ((m & (m - 1)) == 0){
// 什么也不做。从扩展矩形交集的时间是正确的时间
return time;
}

// 点在边缘区域上。与边缘相交。
return time;
}
}
}
45 changes: 45 additions & 0 deletions source/src/Physics/Shapes/ShapeCollisions/ShapeCollisions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
module es {
/**
* 各种形状的碰撞例程
* 大多数人都希望第一个形状位于第二个形状的空间内(即shape1)
* pos应该设置为shape1。pos - shape2.pos)。
*/
export class ShapeCollisions {
/**
* 检查两个多边形之间的碰撞
Expand Down Expand Up @@ -306,5 +311,45 @@ module es {

return new Rectangle(topLeft.x, topLeft.y, fullSize.x, fullSize.y)
}

/**
* 用second检查被deltaMovement移动的框的结果
* @param first
* @param second
* @param movement
* @param hit
*/
public static boxToBoxCast(first: Box, second: Box, movement: Vector2, hit: RaycastHit): boolean{
// 首先,我们检查是否有重叠。如果有重叠,我们就不做扫描测试
let minkowskiDiff = this.minkowskiDifference(first, second);
if (minkowskiDiff.contains(0, 0)){
// 计算MTV。如果它是零,我们就可以称它为非碰撞
let mtv = minkowskiDiff.getClosestPointOnBoundsToOrigin();
if (mtv.equals(Vector2.zero))
return false;

hit.normal = new Vector2(-mtv.x);
hit.normal = hit.normal.normalize();
hit.distance = 0;
hit.fraction = 0;

return true;
}else{
// 射线投射移动矢量
let ray = new Ray2D(Vector2.zero, new Vector2(-movement.x));
let fraction: number = minkowskiDiff.rayIntersects(ray);
if (fraction <= 1){
hit.fraction = fraction;
hit.distance = movement.length() * fraction;
hit.normal = new Vector2(-movement.x);
hit.normal = hit.normal.normalize();
hit.centroid = Vector2.add(first.bounds.center, Vector2.multiply(movement, new Vector2(fraction)));

return true;
}
}

return false;
}
}
}

0 comments on commit c692f01

Please sign in to comment.