如何计算与aabbosg碰撞检测并行计算范围

Cocos2d-x教程(34)-三维物体OBB碰撞检测算法
欢迎加入Cocos2d-x 交流群:转载时请注明原文出处 :http://blog.csdn.net/u/article/details/----------------------------------------------------------------------------------------------------------------------------------------
在上一篇文章中讲解了AABB包围盒碰撞检测的原理,并在文章末尾提到了Cocos2d-x 3.3beta0版本中小乌龟碰撞检测的例子,这个例子使用的并非是AABB碰撞检测,而是比AABB包围盒更加精确的OBB包围盒的碰撞检测方法,本篇文章将对OBB包围盒及其碰撞检测方法进行介绍。1. OBB包围盒
OBB(Oriented Bounding Box)包围盒也被称作有向包围盒或定向包围盒,它会随着物体的移动、缩放、旋转。简单来说,它就是一个能够旋转的AABB包围盒。在Cocos2d-x中使用过物理引擎的开发者一定见过当我们在物理世界中创建一个物体并开启调试模式时,这个物体会被红色的矩形包围,当物体做平移或旋转时,这个红色矩形也会做同样的操作,这个红色矩形正是该物体的OBB包围盒。如图1-1所示:
相对于AABB包围盒来讲,OBB在碰撞精度上要高于AABB,但是精确度的提高同时带来的就是效率的降低,OBB的算法无疑是要比AABB复杂的,同样内存消耗也会更大,这个问题我们可以从OBB的表达式来得到结论。
OBB包围盒的表达式:
表达一个AABB包围盒或OBB包围盒都有若干种方式,但是无疑需要选中里面最优的一种。对于AABB来说,通常只要使用两个顶点的坐标信息标识一个AABB包围盒就可以了,其它的顶点信息都可以通过计算得出。但是对于OBB包围盒的表达方式只有两点信息显然是不够的。
想要唯一标识一个OBB包围盒我们大概会想到,使用8个顶点的集合、6个面的集合、1个顶点和3各彼此正交的边向量,又或者是1个中心点、1个旋转矩阵和3个1/2边长(注:一个旋转矩阵包含了三个旋转轴,若是二维的OBB包围盒则是一个中心点,两个旋转轴,两个1/2边长)。
上述最后一种方法就是最常用的方法,下面来看一段Cocos2d-x 3.3beta0中CCOBB.h中的代码:
以下三个变量为正交单位向量,
定义了当前OBB包围盒的x,y,z轴
用于计算矢量投影
// 包围盒x轴方向单位矢量
// 包围盒y轴方向单位矢量
// 包围盒z轴方向单位矢量
// 3个1/2边长,半长、半宽、半高
Cocos2d-x 3.0beta0在CCOBB.h中定义了五个成员变量,每一个数据类型都是一个三维向量,包含了3个浮点数。也就是说,表达一个OBB包围盒需要15个float类型的变量,占用60个字节,然而表示一个AABB包围盒仅需要两个顶点,24个字节,从这一点上来说,OBB的内存消耗算很高了。
一种减少开销的方案是:只存储旋转矩阵的两个轴,只是在测试时利用叉积计算第三个轴,这样可以减少CPU操作开销并节省3个浮点数分量,降低20%内存消耗。
OBB包围盒的创建:
如何用一个高效的算法构建一个紧密包围的OBB包围盒或是AABB包围盒是一个很复杂的问题,因为不同的形状物体的包围是不同的,这里我们不去探讨构建OBB包围盒的原理,只了解一下Cocos2d-x 3.3beta0 中为我们提供的构建方法。
在Cocos2d-x 中使用了两种方法去计算OBB,第一种方法是一种简化的OBB构建算法,由一个AABB包围盒来确定最终OBB包围盒,另外一种方法是通过协方差矩阵来确定一个方向包围盒(实际上无论是AABB包围盒还是OBB包围盒,真正的难点便在于包围盒的构建上)。
在Cocos2d-x中第一种方法用起来更为简单一些,例如: AABB aabb = _sprite->getAABB();//获取一个Sprite3D对象的aabb包围盒
_obbt = OBB(aabb);//创建obb包围盒2. OBB包围盒的碰撞检测方法
OBB包围盒的碰撞检测方法常采用的是分离轴定理,首先简单说明一下分离轴定理(separating axis theorem),通过分离轴定理我们可以得到如下结论:
如果能找到一个轴,两个凸形状在该轴上的投影不重叠,则这两个形状不相交。如果这个轴不存在,并且那些形状是凸形的,则可以确定两个形状相交(凹形不适用,比如月牙形状,即使找不到分离轴,两个月牙形也可能不相交)。
这个定理也可以这样理解,如果能找到一条直线,令包围盒A完全在直线的一边,包围盒B完全在另一边,则两包围盒不重叠。而这条直线便成为分离线(在三维世界中被称为分离面),并且一定垂直于分离轴。
这里我们还是先来用二维世界中的OBB来进行演示,明白其中原理之后三维物体的OBB便十分容易理解了,如图2-1所示:
在图2-1中,针对某一分离轴L,如果包围盒A与包围盒B在轴L上的投影的半径和小于包围盒中心点间距在L的投影距离,那么包围盒A与包围盒B处于分离状态。使用运算式来表达就是:"T * L|>rA + rB。在Cocos2d-x 3.3beta0中验证相交时采用的并非这个方法,Cocos2d-x选用的方法是,取物体A及物体B的最大点和最小点的投影坐标,然后比较A的最大点与B的最小点,B的最小点与A的最大点。注意,尽管这是一个二维图像,但是实际上三维的图面体在分离轴上的投影跟二维的原理是一样的,都是一个线段。
现在知道了分离轴定理的原理,下面则是如何选取分离轴。由于潜在的分离轴可能存在无数种,所以我们并非去要逐个验证,而是选取几个可测试的轴即可。例如Cocos2d-x中所选用的OBB包围盒的凸面体均为长方体,我们就以长方体的碰撞为例,两个长方体的碰撞可以将其归结为以下几种组合:面-面碰撞、面-边碰撞、边-边碰撞(顶点视为边的一部分)。所以实际上在取分离轴的时候,只需要分别取第一个包围盒的3个坐标轴,第二个包围盒的3个坐标轴,以及垂直于某一轴的9个轴(其他的分离轴都是跟这15个分离轴中的某一个轴平行的轴,投影所得线段值都一样,无需再验证)。
这里再解释以下什么是垂直于某一轴的9个轴,具体的做法就是,首先取包围盒A的x轴方向的某一边矢量,再取包围盒B的x轴方向的某一边矢量,对两个矢量做叉积,求出一个垂直于A的矢量与B的矢量的方向矢量,这个结果就是需要使用的分离轴。按照这种做法,取A的x轴方向的边矢量分别与B的三个轴方向的边矢量做叉积,再取A的y轴方向与B的三个轴方向的边矢量做叉积,再取A的z轴方向的边矢量与B的三个轴方向的边矢量做叉积,结果一共3*3个分离轴。如图2-2所示:vc/ytcTKuMG/09DO3sr9uPajrM7Sw8fWu9DoyKHSu7j2tPqx7dDUtcTTw8C0vMbL47Lmu/28tL/JoaM8YnIgLz4gICAgICAg1+6689TaQ29jb3MyZC14IDMuM2JldGEwsOaxvtbQtcRPQkLF9teyvOyy4rqvyv0gYm9vbCBPQkI6OmludGVyc2VjdHMoY29uc3QgT0JCJmFtcDsgYm94KSBjb25zdCDW0NP2tb3By9K7tePQoc7KzOKjrNTa1+6687XEMyozsd/KuMG/x/O31sDr1uG1xMqxuvIyZC141tDDssvGtffTw7Ttwcu3vbeoo6zI1Mi7xOO199PDtcTKx8ihyP249tf4serW4df2t9bA69bho6yxytXfz8LD5tf2wcvSu9Cp0N64xKOs1+6687i9yc/UtMLroaMgICAgICAgICAgICAgQ0NPQkIuaLT6wuvI58/Co7o8cHJlIGNsYXNzPQ=="brush:">#ifndef __CC_OBB_H__
#define __CC_OBB_H__
#include "CCAABB.h"
#include "3d/3dExport.h"
NS_CC_BEGIN
class CC_3D_DLL OBB
OBB();//默认构造函数
* 构造函数 根据一个AABB包围盒初始化一个OBB包围盒
OBB(const AABB& aabb);
* 构造函数 根据点信息初始化一个OBB包围盒
OBB(const Vec3* verts, int num);
* 判断点是否在一个OBB包围盒内
bool containPoint(const Vec3& point)
* 指定OBB各成员变量的值
void set(const Vec3& center, const Vec3& _xAxis, const Vec3& _yAxis, const Vec3& _zAxis, const Vec3& _extents);
* 复位函数 将当前OBB对象所占用的内存块置零
void reset();
/* 面向包围盒z轴负方向
* verts[0] : 左上点坐标
* verts[1] : 左下点坐标
* verts[2] : 右下点坐标
* verts[3] : 右上点坐标
* 面向包围盒z轴正方向
* verts[4] : 右上点坐标
* verts[5] : 右下点坐标
* verts[6] : 左下点坐标
* verts[7] : 左上点坐标
void getCorners(Vec3* verts)
*检测是否和其他OBB盒碰撞
bool intersects(const OBB& box)
* 由给定的变换矩阵变换OBB包围盒
void transform(const Mat4& mat);
protected:
* 将点投影到目标轴
float projectPoint(const Vec3& point, const Vec3& axis)
* 计算最大和最小投影值
void getInterval(const OBB& box, const Vec3& axis, float &min, float &max)
* 取边的矢量 获取分离轴使用
Vec3 getEdgeDirection(int index)
* 取面的方向矢量 获取分离轴时使用
Vec3 getFaceDirection(int index)
以下三个变量为正交单位向量,
定义了当前OBB包围盒的x,y,z轴
用于计算矢量投影
// 包围盒x轴方向单位矢量
// 包围盒y轴方向单位矢量
// 包围盒z轴方向单位矢量
// 3个1/2边长,半长、半宽、半高
CCOBB.cpp代码如下:#include "3d/CCOBB.h"
NS_CC_BEGIN
#define ROTATE(a,i,j,k,l) g=a.m[i + 4 * j]; h=a.m[k + 4 * l]; a.m[i + 4 * j]=(float)(g-s*(h+g*tau)); a.m[k + 4 * l]=(float)(h+s*(g-h*tau));
//生成协方差矩阵
static Mat4 _getConvarianceMatrix(const Vec3* vertPos, int vertCount)
double S1[3];
double S2[3][3];
S1[0] = S1[1] = S1[2] = 0.0;
S2[0][0] = S2[1][0] = S2[2][0] = 0.0;
S2[0][1] = S2[1][1] = S2[2][1] = 0.0;
S2[0][2] = S2[1][2] = S2[2][2] = 0.0;
// get center of mass
for(i=0; i<vertC i++)
S1[0] += vertPos[i].x;
S1[1] += vertPos[i].y;
S1[2] += vertPos[i].z;
S2[0][0] += vertPos[i].x * vertPos[i].x;
S2[1][1] += vertPos[i].y * vertPos[i].y;
S2[2][2] += vertPos[i].z * vertPos[i].z;
S2[0][1] += vertPos[i].x * vertPos[i].y;
S2[0][2] += vertPos[i].x * vertPos[i].z;
S2[1][2] += vertPos[i].y * vertPos[i].z;
float n = (float)vertC
// now get covariances
Cov.m[0] = (float)(S2[0][0] - S1[0]*S1[0] / n) /
Cov.m[5] = (float)(S2[1][1] - S1[1]*S1[1] / n) /
Cov.m[10] = (float)(S2[2][2] - S1[2]*S1[2] / n) /
Cov.m[4] = (float)(S2[0][1] - S1[0]*S1[1] / n) /
Cov.m[9] = (float)(S2[1][2] - S1[1]*S1[2] / n) /
Cov.m[8] = (float)(S2[0][2] - S1[0]*S1[2] / n) /
Cov.m[1] = Cov.m[4];
Cov.m[2] = Cov.m[8];
Cov.m[6] = Cov.m[9];
//获取一个矢量在某个轴的分量
static float& _getElement( Vec3& point, int index)
if (index == 0)
return point.x;
if (index == 1)
return point.y;
if (index == 2)
return point.z;
CC_ASSERT(0);
return point.x;
//获取特征向量
static void _getEigenVectors(Mat4* vout, Vec3* dout, Mat4 a)
int n = 3;
int j,iq,ip,i;
double tresh, theta, tau, t, sm, s, h, g,
v = Mat4::IDENTITY;
for(ip = 0; ip < ip++)
_getElement(b, ip) = a.m[ip + 4 * ip];
_getElement(d, ip) = a.m[ip + 4 * ip];
_getElement(z, ip) = 0.0;
for(i = 0; i < 50; i++)
for(ip = 0; ip < ip++) for(iq = ip+1; iq < iq++) sm += fabs(a.m[ip + 4 * iq]);
if( fabs(sm) < FLT_EPSILON )
v.transpose();
if (i < 3)
tresh = 0.2 * sm / (n*n);
tresh = 0.0;
for(ip = 0; ip < ip++)
for(iq = ip + 1; iq 3 && fabs(dmip) + g == fabs(dmip) && fabs(dmiq) + g == fabs(dmiq) )
a.m[ip + 4 * iq] = 0.0;
else if (fabs(a.m[ip + 4 * iq]) > tresh)
h = dmiq -
if (fabs(h) + g == fabs(h))
t=(a.m[ip + 4 * iq])/h;
theta = 0.5 * h / (a.m[ip + 4 * iq]);
t=1.0 / (fabs(theta) + sqrt(1.0 + theta * theta));
if (theta < 0.0) t = -t;
c = 1.0 / sqrt(1+t*t);
tau = s / (1.0+c);
h = t * a.m[ip + 4 * iq];
_getElement(z, ip) -= (float)h;
_getElement(z, iq) += (float)h;
_getElement(d, ip) -= (float)h;
_getElement(d, iq) += (float)h;
a.m[ip + 4 * iq]=0.0;
for(j = 0; j < j++) { ROTATE(a,j,ip,j,iq); }
for(j = ip + 1; j < j++) { ROTATE(a,ip,j,j,iq); }
for(j = iq + 1; j < j++) { ROTATE(a,ip,j,iq,j); }
for(j = 0; j < j++) { ROTATE(v,j,ip,j,iq); }
for(ip = 0; ip < ip++)
_getElement(b, ip) += _getElement(z, ip);
_getElement(d, ip) = _getElement(b, ip);
_getElement(z, ip) = 0.0f;
v.transpose();
//创建OBB包围盒取向矩阵
static Mat4 _getOBBOrientation(const Vec3* vertPos, int num)
Mat4 C //创建一个 4*4 矩阵
if (num <= 0)
return Mat4::IDENTITY; //返回单位矩阵
Cov = _getConvarianceMatrix(vertPos, num); //创建协方差矩阵
// now get eigenvectors
_getEigenVectors(&Evecs, &Evals, Cov); //求特征向量
Evecs.transpose(); //转置
//默认构造函数
OBB::OBB()
//数据复位
//由一个AABB包围盒生成OBB包围盒
OBB::OBB(const AABB& aabb)
//数据复位
_center = (aabb._min + aabb._max);
_center.scale(0.5f);
//各轴旋转矩阵的单位矩阵
_xAxis = Vec3(1.0f, 0.0f, 0.0f);
_yAxis = Vec3(0.0f, 1.0f, 0.0f);
_zAxis = Vec3(0.0f, 0.0f, 1.0f);
//半尺存 半长 半宽 半高
_extents = aabb._max - aabb._
_extents.scale(0.5f);
//构造函数 根据点信息初始化一个OBB包围盒
OBB::OBB(const Vec3* verts, int num)
if (!verts) //如果verts不存在 返回
reset(); //数据复位
Mat4 matTransform = _getOBBOrientation(verts, num); //创建包围盒取向矩阵
matTransform是一个正交矩阵,所以它的逆矩阵就是它的转置;
AA'=E(E为单位矩阵,A'表示“矩阵A的转置矩阵”) A称为正交矩阵
matTransform.transpose(); //计算matTransform矩阵的转置(此处相当于求逆矩)
Vec3 vecMax = matTransform * Vec3(verts[0].x, verts[0].y, verts[0].z);
Vec3 vecMin = vecM
for (int i = 1; i
vect.x ? vecMax.x : vect.x;
vecMax.y = vecMax.y > vect.y ? vecMax.y : vect.y;
vecMax.z = vecMax.z > vect.z ? vecMax.z : vect.z;
vecMin.x = vecMin.x < vect.x ? vecMin.x : vect.x;
vecMin.y = vecMin.y < vect.y ? vecMin.y : vect.y;
vecMin.z = vecMin.z
_extents.x || d
_extents.y || d
_extents.z || d < -_extents.z)
//指定OBB包围盒的变量值
void OBB::set(const Vec3& center, const Vec3& xAxis, const Vec3& yAxis, const Vec3& zAxis, const Vec3& extents)
_xAxis = xA
_yAxis = yA
_zAxis = zA
_extents =
void OBB::reset()
memset(this, 0, sizeof(OBB)); //将OBB所在内存块置零
//获取顶点信息
void OBB::getCorners(Vec3* verts) const
Vec3 extX = _xAxis * _extents.x;
//x方向分量
Vec3 extY = _yAxis * _extents.y;
//y方向分量
Vec3 extZ = _zAxis * _extents.z;
//z方向分量
//z轴正方向的面
verts[0] = _center - extX + extY + extZ;
// 左上顶点坐标
verts[1] = _center - extX - extY + extZ;
// 左下顶点坐标
verts[2] = _center + extX - extY + extZ;
// 右下顶点坐标
verts[3] = _center + extX + extY + extZ;
// 右上顶点坐标
//z轴负方向的面
verts[4] = _center + extX + extY - extZ;
// 右上顶点坐标
verts[5] = _center + extX - extY - extZ;
// 右下顶点坐标
verts[6] = _center - extX - extY - extZ;
// 左下顶点坐标
verts[7] = _center - extX + extY - extZ;
// 左上顶点坐标
//将点投影到坐标轴
float OBB::projectPoint(const Vec3& point, const Vec3& axis)const
float dot = axis.dot(point); //点积
float ret = dot * point.length();
//计算最大最小投影值
void OBB::getInterval(const OBB& box, const Vec3& axis, float &min, float &max)const
Vec3 corners[8];
box.getCorners(corners);//获取包围盒顶点信息
//分别投影八个点,取最大和最小值
min = max = projectPoint(axis, corners[0]);
for(int i = 1; i 右下点的矢量
v1 = corners[0] - corners[1]; //
左下点->左上点的矢量
两个矢量的叉积得到的结果
是垂直于原来两个相乘矢量的矢量
Vec3::cross(v0, v1, &faceDirection); //计算v0,v1的叉积 结果存储到faceDirection
此处相当于求x,y轴所在平面的法矢量
faceDirection.normalize();
case 1:// 左/右 计算结果为一个与x轴平行的矢量
v0 = corners[5] - corners[2];
v1 = corners[3] - corners[2];
Vec3::cross(v0, v1, &faceDirection);
faceDirection.normalize();
case 2:// 上/下 计算结果为一个与y轴平行的矢量
v0 = corners[1] - corners[2];
v1 = corners[5] - corners[2];
Vec3::cross(v0, v1, &faceDirection);
faceDirection.normalize();
CCASSERT(0, "Invalid index!");
return faceD //返回方向矢量
//检测两个OBB包围盒是否重合
bool OBB::intersects(const OBB& box) const
float min1, max1, min2, max2;
//当前包围盒的三个面方向 相当于取包围盒的三个坐标轴为分离轴并计算投影作比较
for (int i = 0; i < 3; i++)
getInterval(*this, getFaceDirection(i), min1, max1);//计算当前包围盒在某轴上的最大最小投影值
getInterval(box, getFaceDirection(i), min2, max2);//计算另一个包围盒在某轴上的最大最小投影值
if (max1 < min2 || max2 < min1) //判断分离轴上投影是否重合
//box包围盒的三个面方向
for (int i = 0; i < 3; i++)
getInterval(*this, box.getFaceDirection(i), min1, max1);
getInterval(box, box.getFaceDirection(i), min2, max2);
if (max1 < min2 || max2 < min1)
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
//Vec3::cross(getFaceDirection(i), box.getFaceDirection(j), &axis); //2d-x源代码
Vec3::cross(getEdgeDirection(i), box.getEdgeDirection(j), &axis); //修改,这里应该边的矢量并做叉积
getInterval(*this, axis, min1, max1);
getInterval(box, axis, min2, max2);
if (max1 < min2 || max2 < min1)
//由一个给定矩阵对OBB包围盒进行变换
void OBB::transform(const Mat4& mat)
// 新的中心点
Vec4 newcenter = mat * Vec4(_center.x, _center.y, _center.z, 1.0f);
_center.x = newcenter.x;
_center.y = newcenter.y;
_center.z = newcenter.z;
//变换向量
_xAxis = mat * _xA
_yAxis = mat * _yA
_zAxis = mat * _zA
_xAxis.normalize();
_yAxis.normalize();
_zAxis.normalize();
Vec3 scale,
//四元数 单位长度的四元数可以表示三维旋转
mat.decompose(&scale, &quat, &trans);
//半长 半宽 半高
_extents.x *= scale.x;
_extents.y *= scale.y;
_extents.z *= scale.z;
(window.slotbydup=window.slotbydup || []).push({
id: '2467140',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467141',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467143',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467148',
container: s,
size: '1000,90',
display: 'inlay-fix'&#xe621; 上传我的文档
&#xe602; 下载
&#xe60c; 收藏
该文档贡献者很忙,什么也没留下。
&#xe602; 下载此文档
正在努力加载中...
三维空间中碰撞检测算法的研究
下载积分:1998
内容提示:三维空间中碰撞检测算法的研究
文档格式:PDF|
浏览次数:27|
上传日期: 09:41:05|
文档星级:&#xe60b;&#xe612;&#xe612;&#xe612;&#xe612;
该用户还上传了这些文档
三维空间中碰撞检测算法的研究
官方公共微信您的位置: &
基于AABB树的碰撞检测算法的内存优化
优质期刊推荐9286人阅读
游戏开发(14)
最近需要用到射线和运动AABB的实时碰撞检测算法,作为基础看了下box2d的碰撞检测。
box2d使用了一种叫做slab的碰撞检测算法。所谓slab是指两个平行平面之间的空间,由此我们可以把3D空间中的AABB盒子看做是由AABB的3组平行面形成的3个方向的slab的交集。根据这个定义,我们可以得到以下两个结论:
1.如果一个点在AABB中,那么这个点必定同时在这3个slab中。
2.如果一条射线和AABB相交,那么这条射线和3个slab的相交部分必定有重合部分。
这很容易理解,如果射线和3个slab的相交线段没有重合,那么这些线段就不可能同时存在于3个slab中,也就不可能在AABB盒子中。下图展示了2D空间中射线R1和R2与AABB相交的情形。R1在x-slab和y-slab中的线段没有重合部分,因此R1和AABB不相交。R2在x-slab和y-slab中的线段有重合部分,因此R2和AABB相交。
根据上述原理,检查2D中射线和AABB的碰撞,只需要检查射线和x-slab,y-slab的交线是否有重合。
首先我们需要得到射线和slab边界平面的交点。射线可以用参数方程表示为R(t) =&P0&&#43;&t&d&, (其中P0为射线起点,d为射线的方向向量),平面由隐式定义方程X·n=D, (其中X为平面上的点,n为平面法向量,D为原点到平面的距离)给出。将平面方程中的X用P0&&#43;&t&d替换解得交点的参数t=(D-P0·n)/(d·n).由于AABB的slab平面都分别和两个坐标轴平行,公式可以进一步简化:设P0=(px,py,pz), d=(dx,dy,dz),
t和x-slab面的交点的参数计算公式可化简为t=(D-px)/dx,而此处的D就是AABB的边界面x坐标。
理解了原理再来看box2d的代码就很容易了
/// Ray-cast input data. The ray extends from p1 to p1 + maxFraction * (p2 - p1).
struct b2RayCastInput
b2Vec2 p1, p2;
float32 maxF
/// Ray-cast output data. The ray hits at p1 + fraction * (p2 - p1), where p1 and p2
/// come from b2RayCastInput.
struct b2RayCastOutput
bool b2AABB::RayCast(b2RayCastOutput* output, const b2RayCastInput& input) const
float32 tmin = -b2_maxF
float32 tmax = b2_maxF
b2Vec2 p = input.p1;
b2Vec2 d = input.p2 - input.p1;
b2Vec2 absD = b2Abs(d);
for (int32 i = 0; i & 2; ++i)
if (absD(i) & b2_epsilon)
// Parallel.
if (p(i) & lowerBound(i) || upperBound(i) & p(i))
float32 inv_d = 1.0f / d(i);
float32 t1 = (lowerBound(i) - p(i)) * inv_d;
float32 t2 = (upperBound(i) - p(i)) * inv_d;
// Sign of the normal vector.
float32 s = -1.0f;
if (t1 & t2)
b2Swap(t1, t2);
// Push the min up
if (t1 & tmin)
normal.SetZero();
normal(i) =
tmin = t1;
// Pull the max down
tmax = b2Min(tmax, t2);
if (tmin & tmax)
// Does the ray start inside the box?
// Does the ray intersect beyond the max fraction?
if (tmin & 0.0f || input.maxFraction & tmin)
// Intersection.
output-&fraction =
output-&normal =
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:186407次
积分:1899
积分:1899
排名:第13829名
原创:24篇
评论:106条
(2)(2)(4)(1)(1)(2)(2)(3)(1)(1)(1)(1)(1)(1)(1)}

我要回帖

更多关于 碰撞后两球的速度范围 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信