新增Ref类型

This commit is contained in:
yhh
2020-08-25 14:21:37 +08:00
parent 27f9e78fe5
commit 27dea50026
16 changed files with 258 additions and 150 deletions

View File

@@ -163,8 +163,8 @@ module es {
* @param distanceSquared
* @param edgeNormal
*/
public static getClosestPointOnPolygonToPoint(points: Vector2[], point: Vector2, distanceSquared: Number, edgeNormal: Vector2): Vector2 {
distanceSquared = Number.MAX_VALUE;
public static getClosestPointOnPolygonToPoint(points: Vector2[], point: Vector2, distanceSquared: Ref<number>, edgeNormal: Vector2): Vector2 {
distanceSquared.value = Number.MAX_VALUE;
edgeNormal.x = 0;
edgeNormal.y = 0;
let closestPoint = new Vector2(0, 0);
@@ -178,8 +178,8 @@ module es {
let closest = ShapeCollisions.closestPointOnLine(points[i], points[j], point);
tempDistanceSquared = Vector2.distanceSquared(point, closest);
if (tempDistanceSquared < distanceSquared) {
distanceSquared = tempDistanceSquared;
if (tempDistanceSquared < distanceSquared.value) {
distanceSquared.value = tempDistanceSquared;
closestPoint = closest;
// 求直线的法线

View File

@@ -1,18 +1,17 @@
module es {
export class RealtimeCollisions {
public static intersectMovingCircleToBox(s: Circle, b: Box, movement: Vector2): number {
public static intersectMovingCircleBox(s: Circle, b: Box, movement: Vector2, time: Ref<number>): boolean {
// 计算用球面半径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;
if (!e.rayIntersects(ray, time) && time.value > 1)
return false;
// 求交点
let point = Vector2.add(ray.start, Vector2.add(ray.direction, new Vector2(time)));
let point = Vector2.add(ray.start, Vector2.add(ray.direction, new Vector2(time.value)));
// 计算b的最小面和最大面p的交点在哪个面之外。注意u和v不能有相同的位集它们之间必须至少有一个位集。
let u, v = 0;
@@ -38,11 +37,11 @@ module es {
// 如果m中只设置了一个位那么点在一个面区域
if ((m & (m - 1)) == 0){
// 什么也不做。从扩展矩形交集的时间是正确的时间
return time;
return true;
}
// 点在边缘区域上。与边缘相交。
return time;
return true;
}
}
}

View File

@@ -125,22 +125,22 @@ module es {
public static circleToPolygon(circle: Circle, polygon: Polygon, result: CollisionResult): boolean {
let poly2Circle = Vector2.subtract(circle.position, polygon.position);
let distanceSquared = 0;
let distanceSquared = new Ref(0);
let closestPoint = Polygon.getClosestPointOnPolygonToPoint(polygon.points, poly2Circle, distanceSquared, result.normal);
let circleCenterInsidePoly = polygon.containsPoint(circle.position);
if (distanceSquared > circle.radius * circle.radius && !circleCenterInsidePoly)
if (distanceSquared.value > circle.radius * circle.radius && !circleCenterInsidePoly)
return false;
let mtv: Vector2;
if (circleCenterInsidePoly) {
mtv = Vector2.multiply(result.normal, new Vector2(Math.sqrt(distanceSquared) - circle.radius));
mtv = Vector2.multiply(result.normal, new Vector2(Math.sqrt(distanceSquared.value) - circle.radius));
} else {
if (distanceSquared == 0) {
if (distanceSquared.value == 0) {
mtv = Vector2.multiply(result.normal, new Vector2(circle.radius));
} else {
let distance = Math.sqrt(distanceSquared);
mtv = Vector2.multiply(new Vector2(-Vector2.subtract(poly2Circle, closestPoint)), new Vector2((circle.radius - distanceSquared) / distance));
let distance = Math.sqrt(distanceSquared.value);
mtv = Vector2.multiply(new Vector2(-Vector2.subtract(poly2Circle, closestPoint)), new Vector2((circle.radius - distanceSquared.value) / distance));
}
}
@@ -245,10 +245,10 @@ module es {
*/
public static pointToPoly(point: Vector2, poly: Polygon, result: CollisionResult): boolean {
if (poly.containsPoint(point)) {
let distanceSquared: number = 0;
let distanceSquared = new Ref(0);
let closestPoint = Polygon.getClosestPointOnPolygonToPoint(poly.points, Vector2.subtract(point, poly.position), distanceSquared, result.normal);
result.minimumTranslationVector = Vector2.multiply(result.normal, new Vector2(Math.sqrt(distanceSquared), Math.sqrt(distanceSquared)));
result.minimumTranslationVector = Vector2.multiply(result.normal, new Vector2(Math.sqrt(distanceSquared.value), Math.sqrt(distanceSquared.value)));
result.point = Vector2.add(closestPoint, poly.position);
return true;
@@ -295,7 +295,7 @@ module es {
return false;
result.normal = new Vector2(-result.minimumTranslationVector.x, -result.minimumTranslationVector.y);
result.normal = result.normal.normalize();
result.normal.normalize();
return true;
}
@@ -342,7 +342,7 @@ module es {
}
if (hasIntersection){
normal = normal.normalize();
normal.normalize();
let distance = Vector2.distance(start, intersectionPoint);
hit.setValuesNonCollider(fraction, distance, intersectionPoint, normal);
return true;
@@ -423,7 +423,7 @@ module es {
return false;
hit.normal = new Vector2(-mtv.x);
hit.normal = hit.normal.normalize();
hit.normal.normalize();
hit.distance = 0;
hit.fraction = 0;
@@ -431,13 +431,13 @@ module es {
}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)));
let fraction = new Ref(0);
if (minkowskiDiff.rayIntersects(ray, fraction) && fraction.value <= 1){
hit.fraction = fraction.value;
hit.distance = movement.length() * fraction.value;
hit.normal = new Vector2(-movement.x, -movement.y);
hit.normal.normalize();
hit.centroid = Vector2.add(first.bounds.center, Vector2.multiply(movement, new Vector2(fraction.value)));
return true;
}

View File

@@ -355,7 +355,7 @@ module es {
* @param cell
*/
public checkRayIntersection(cellX: number, cellY: number, cell: Collider[]): boolean {
let fraction: number = 0;
let fraction: Ref<number> = new Ref(0);
for (let i = 0; i < cell.length; i++) {
let potential = cell[i];
@@ -376,8 +376,7 @@ module es {
// TODO: 如果边界检查返回更多数据我们就不需要为BoxCollider检查做任何事情
// 在做形状测试之前先做一个边界检查
let colliderBounds = potential.bounds;
let fraction = colliderBounds.rayIntersects(this._ray);
if (fraction <= 1) {
if (colliderBounds.rayIntersects(this._ray, fraction) && fraction.value <= 1){
if (potential.shape.collidesWithLine(this._ray.start, this._ray.end, this._tempHit)) {
// 检查一下我们应该排除这些射线射线cast是否在碰撞器中开始
if (!Physics.raycastsStartInColliders && potential.shape.containsPoint(this._ray.start))