新增RealtimeCollisions.testCircleBox用于检测园与方框是否重叠并返回point交点

This commit is contained in:
yhh
2020-12-04 16:48:33 +08:00
parent c8096e3334
commit 8b3b645fbb
4 changed files with 86 additions and 21 deletions

View File

@@ -2691,6 +2691,19 @@ declare module es {
declare module es {
class RealtimeCollisions {
static intersectMovingCircleBox(s: Circle, b: Box, movement: Vector2, time: Ref<number>): boolean;
/**
* 支持函数返回索引为n的矩形vert
* @param b
* @param n
*/
static corner(b: Rectangle, n: number): Vector2;
/**
* 检查圆是否与方框重叠并返回point交点
* @param cirlce
* @param box
* @param point
*/
static testCircleBox(cirlce: Circle, box: Box, point: Vector2): boolean;
}
}
declare module es {

View File

@@ -6656,16 +6656,16 @@ var es;
function RealtimeCollisions() {
}
RealtimeCollisions.intersectMovingCircleBox = function (s, b, movement, time) {
// 计算球面半径r inflate b得到的AABB
// 计算将b按球面半径r扩大后的AABB
var e = b.bounds;
e.inflate(s.radius, s.radius);
// 射线与展开矩形e相交如果射线错过了e则退出不相交,否则得到交点p和时间t
// 射线与展开矩形e相交如果射线错过了e以无交点退出否则得到交点p和时间t作为结果。
var ray = new es.Ray2D(es.Vector2.subtract(s.position, movement), s.position);
if (!e.rayIntersects(ray, time) && time.value > 1)
return false;
// 求交点
var point = es.Vector2.add(ray.start, es.Vector2.add(ray.direction, new es.Vector2(time.value)));
// 计算b的最小面和最大面p的交点在哪个面之外。注意u和v不能有相同的位集它们之间必须至少有一个位集。
// 计算交点p位于b的哪个最小面和最大面之外。注意u和v不能有相同的位集它们之间必须至少有一个位集。
var u, v = 0;
if (point.x < b.bounds.left)
u |= 1;
@@ -6675,22 +6675,46 @@ var es;
u |= 2;
if (point.y > b.bounds.bottom)
v |= 2;
// 将所有位集合成位掩码(注意u + v == u | v)
// 'or'将所有的比特集合在一起,形成一个比特掩码(注意u + v == u | v)
var m = u + v;
// 如果所有的3位都被设置,那么点在一个顶点区域
// 如果这3个比特都被设置,那么该点就在顶点区域内。
if (m == 3) {
// 现在必须相交的部分,如果一个或多个击中对胶囊的两边会合在斜面和返回最佳时间
// TODO: 需要实现这个
// 如果有一条或多条命中,则必须在两条边的顶点相交,并返回最佳时间
console.log("m == 3. corner " + es.Time.frameCount);
}
// 如果m中只设置了一个位那么在一个面区域
// 如果m中只设置了一个位那么该点就在一个面区域
if ((m & (m - 1)) == 0) {
// 什么也不做。从扩展矩形交集的时间是正确的时间
// 从扩大的矩形交点开始的时间是正确的时间
return true;
}
// 点在边缘区域上。与边缘相交。
// 点在边缘区域与边缘相交。
return true;
};
/**
* 支持函数返回索引为n的矩形vert
* @param b
* @param n
*/
RealtimeCollisions.corner = function (b, n) {
var p = new es.Vector2();
p.x = (n & 1) == 0 ? b.right : b.left;
p.y = (n & 1) == 0 ? b.bottom : b.top;
return p;
};
/**
* 检查圆是否与方框重叠并返回point交点
* @param cirlce
* @param box
* @param point
*/
RealtimeCollisions.testCircleBox = function (cirlce, box, point) {
// 找出离球心最近的点
point = box.bounds.getClosestPointOnRectangleToPoint(cirlce.position);
// 圆和方块相交,如果圆心到点的距离小于圆的半径,则圆和方块相交
var v = es.Vector2.subtract(point, cirlce.position);
var dist = es.Vector2.dot(v, v);
return dist <= cirlce.radius * cirlce.radius;
};
return RealtimeCollisions;
}());
es.RealtimeCollisions = RealtimeCollisions;

File diff suppressed because one or more lines are too long

View File

@@ -1,11 +1,11 @@
module es {
export class RealtimeCollisions {
public static intersectMovingCircleBox(s: Circle, b: Box, movement: Vector2, time: Ref<number>): boolean {
// 计算球面半径r inflate b得到的AABB
// 计算将b按球面半径r扩大后的AABB
let e = b.bounds;
e.inflate(s.radius, s.radius);
// 射线与展开矩形e相交如果射线错过了e则退出不相交,否则得到交点p和时间t
// 射线与展开矩形e相交如果射线错过了e以无交点退出否则得到交点p和时间t作为结果。
let ray = new Ray2D(Vector2.subtract(s.position, movement), s.position);
if (!e.rayIntersects(ray, time) && time.value > 1)
return false;
@@ -13,7 +13,7 @@ module es {
// 求交点
let point = Vector2.add(ray.start, Vector2.add(ray.direction, new Vector2(time.value)));
// 计算b的最小面和最大面p的交点在哪个面之外。注意u和v不能有相同的位集它们之间必须至少有一个位集。
// 计算交点p位于b的哪个最小面和最大面之外。注意u和v不能有相同的位集它们之间必须至少有一个位集。
let u, v = 0;
if (point.x < b.bounds.left)
u |= 1;
@@ -24,24 +24,52 @@ module es {
if (point.y > b.bounds.bottom)
v |= 2;
// 将所有位集合成位掩码(注意u + v == u | v)
// 'or'将所有的比特集合在一起,形成一个比特掩码(注意u + v == u | v)
let m = u + v;
// 如果所有的3位都被设置,那么点在一个顶点区域
// 如果这3个比特都被设置,那么该点就在顶点区域内。
if (m == 3){
// 现在必须相交的部分,如果一个或多个击中对胶囊的两边会合在斜面和返回最佳时间
// TODO: 需要实现这个
// 如果有一条或多条命中,则必须在两条边的顶点相交,并返回最佳时间
console.log(`m == 3. corner ${Time.frameCount}`);
}
// 如果m中只设置了一个位那么在一个面区域
// 如果m中只设置了一个位那么该点就在一个面区域
if ((m & (m - 1)) == 0){
// 什么也不做。从扩展矩形交集的时间是正确的时间
// 从扩大的矩形交点开始的时间是正确的时间
return true;
}
// 点在边缘区域上。与边缘相交。
// 点在边缘区域与边缘相交。
return true;
}
/**
* 支持函数返回索引为n的矩形vert
* @param b
* @param n
*/
public static corner(b: Rectangle, n: number){
let p = new Vector2();
p.x = (n & 1) == 0 ? b.right : b.left;
p.y = (n & 1) == 0 ? b.bottom : b.top;
return p;
}
/**
* 检查圆是否与方框重叠并返回point交点
* @param cirlce
* @param box
* @param point
*/
public static testCircleBox(cirlce: Circle, box: Box, point: Vector2) {
// 找出离球心最近的点
point = box.bounds.getClosestPointOnRectangleToPoint(cirlce.position);
// 圆和方块相交,如果圆心到点的距离小于圆的半径,则圆和方块相交
let v = Vector2.subtract(point, cirlce.position);
let dist = Vector2.dot(v, v);
return dist <= cirlce.radius * cirlce.radius;
}
}
}