• 注册
当前位置:1313e > 默认分类 >正文

碰撞检測之OBB-OBB的SweepTest

提要

当物体在运动的时候。普通的每帧进行碰撞检測已经无法满足要求,比方子弹的运动


两帧的位置已经直接将中间的板子穿过了,所以 t 时刻和 t +1 时刻的检測都是失效的。这时候须要用到的就是sweep检測了。

今天要处理的就是AABB的Sweep检測。



2D情况

例如以下图。当前位置是蓝色Box所在位置,目的位置是绿色框所在位置。



2D情况仅仅用处理x,y方向的,利用SAP理论。分别在各个轴向计算能够移动的距离。

代码例如以下

 public static Vector2 SweepTest(OBB from, OBB other, Vector2 movement)
{float deltaX = movement.x;float deltaY = movement.y;if (from.max.y > other.min.y && from.min.y < other.max.y){float d1;if (deltaX > 0.0D && from.max.x <= other.min.x){d1 = other.min.x - from.max.x;if (d1 < deltaX){deltaX = d1;}}else if (deltaX < 0.0D && from.min.x >= other.max.x){d1 = other.max.x - from.min.x;if (d1 > deltaX){deltaX = d1;}}}if (from.max.x > other.min.x && from.min.x < other.max.x){float d1;if (deltaY > 0f && from.max.y <= other.min.y){d1 = other.min.y - from.max.y;if (d1 < deltaY){deltaY = d1;}}else if (deltaY < 0f && from.min.y >= other.max.y){d1 = other.max.y - from.min.y;if (d1 > deltaY){deltaY = d1;}}}return Vector2(deltaX, deltaY);
}

输入是两个OBB,from是要运动的OBB,movement是要进行的位移,返回的是终于的位移。

简单说一下X方向的推断,

首先

if (from.max.y > other.min.y && from.min.y < other.max.y)

要推断的是两个OBB在Y方向的投影是否有重叠,假设没有就直接返回movement 的x分量,由于在X方向不可能发生碰撞。

接下来推断的是假设from在other的左边。看是否有足够的空间给它运动,没有的话直接贴到other的边边上。from在other的右边的情况做相同的检測。


3D情况

仅仅要简单的扩展到3D情况就能够了。

    public static Vector3 SweepTest(Bounds from, Bounds other, Vector3 movement){float deltaX = movement.x;float deltaY = movement.y;float deltaZ = movement.z;if (from.max.y > other.min.y && from.min.y < other.max.y && from.max.z > other.min.z && from.min.z < other.max.z){float d1;if (deltaX > 0.0D && from.max.x <= other.min.x){d1 = other.min.x - from.max.x;if (d1 < deltaX){deltaX = d1;}}else if (deltaX < 0.0D && from.min.x >= other.max.x){d1 = other.max.x - from.min.x;if (d1 > deltaX){deltaX = d1;}}}if (from.max.x > other.min.x && from.min.x < other.max.x && from.max.z > other.min.z && from.min.z < other.max.z){float d1;if (deltaY > 0f && from.max.y <= other.min.y){d1 = other.min.y - from.max.y;if (d1 < deltaY){deltaY = d1;}}else if (deltaY < 0f && from.min.y >= other.max.y){d1 = other.max.y - from.min.y;if (d1 > deltaY){deltaY = d1;}}}if (from.max.x > other.min.x && from.min.x < other.max.x && from.max.y > other.min.y && from.min.y < other.max.y){float d1;if (deltaZ > 0.0D && from.max.z <= other.min.z){d1 = other.min.z - from.max.z;if (d1 < deltaZ){deltaZ = d1;}}else if (deltaZ < 0.0D && from.min.z >= other.max.z){d1 = other.max.z - from.min.z;if (d1 > deltaZ){deltaZ = d1;}}}return new Vector3(deltaX, deltaY, deltaZ);}


測试代码

using UnityEngine;
using System.Collections;
using NPhysX;
public class BoxBoxSweepTester : MonoBehaviour {public Vector3 direction;public float speed;public GameObject box;public GameObject box1;Box _box;Box _box1;// Use this for initializationvoid Start(){_box = new Box();_box1 = new Box();direction = Vector3.one;}// Update is called once per framevoid Update () {Vector3 moveVector = speed * direction;Vector3 realMove = NSweepTests.SweepTest(box.GetComponent().bounds, box1.GetComponent().bounds, moveVector);box.transform.position += realMove;}
}


測试结果


參考

Swept AABB Collision Detection and Response - http://www.gamedev.net/page/resources/_/technical/game-programming/swept-aabb-collision-detection-and-response-r3084



本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 162202241@qq.com 举报,一经查实,本站将立刻删除。

最新评论

欢迎您发表评论:

请登录之后再进行评论

登录