本资源提供了一个基于GJK算法的C++实现示例,用于高效地检测和处理二维或三维空间中的物体碰撞。该代码简洁明了,易于集成到游戏开发与机器人路径规划等项目中。
GJK碰撞检测代码应用
以下是基于GarageGames.com, Inc.的Torque 3D引擎中的干扰检测库SOLID 2.0的核心算法编写的GJK(Gilbert-Johnson-Keerthi)碰撞检测实现。
```cpp
#include core/dataChunker.h
#include collision/collision.h
#include sceneGraph/sceneObject.h
#include collision/convex.h
#include collision/gjk.h
static F32 rel_error = 1E-5f; // 相对误差,用于计算距离
static F32 sTolerance = 1E-3f; // 距离容差
static F32 sEpsilon2 = 1E-20f; // 零长度向量
static U32 sIteration = 15; // 如果陷入循环,可以调整此值
S32 num_iterations = 0;
S32 num_irregularities = 0;
// GjkCollisionState类的构造函数和析构函数定义
GjkCollisionState::GjkCollisionState() {
a = b = 0;
}
GjkCollisionState::~GjkCollisionState() {}
void GjkCollisionState::swap(){
Convex* t = a;
a = b;
b = t;
CollisionStateList* l = mLista;
mLista = mListb;
mListb = l;
v.neg();
}
// 计算行列式
void GjkCollisionState::compute_det(){
// 这里略去了具体实现,因为代码较长且复杂。
}
inline void GjkCollisionState::compute_vector(int bits, VectorF& v){
F32 sum = 0;
v.set(0, 0, 0);
for (int i = 0, bit = 1; i < 4; ++i, bit <<= 1) {
if (bits & bit) {
sum += det[bits][i];
v += y[i] * det[bits][i];
}
}
v *= 1 / sum;
}
inline bool GjkCollisionState::valid(int s){
// 这里略去了具体实现,因为代码较长且复杂。
return true;
}
// 寻找最近点
inline bool GjkCollisionState::closest(VectorF& v) {
compute_det();
for (int s = bits; s; --s) {
if ((s & bits) == s && valid(s | last_bit)) {
bits = s | last_bit;
if(bits != 15)
compute_vector(bits, v);
return true;
}
}
if (valid(last_bit)) {
bits = last_bit;
v = y[last];
return true;
}
return false;
}
// 判断退化情况
inline bool GjkCollisionState::degenerate(const VectorF& w) {
for(int i=0, bit=1;i<4;++i,bit<<=1)
if ((all_bits & bit))
if (y[i] == w) return true;
return false;
}
// 移动到下一个位
inline void GjkCollisionState::nextBit() {
last = 0;
last_bit = 1;
while(bits & last_bit){
++last;
last_bit <<= 1;
}
}
void GjkCollisionState::set(Convex* aa, Convex* bb, const MatrixF& a2w, const MatrixF& b2w) {
a = aa;
b = bb;
bits = 0; all_bits = 0;
reset(a2w,b2w);
mLista = CollisionStateList::alloc(); mLista->mState = this;
mListb = CollisionStateList::alloc(); mListb->mState = this;
}
void GjkCollisionState::reset(const MatrixF& a2w, const MatrixF& b2w) {
VectorF zero(0, 0, 0), sa, sb;
a2w.mulP(a->support(zero), &sa);
b2w.mulP(b->support(zero), &sb);
v = sa - sb;
dist = v.len();
}
void GjkCollisionState::getCollisionInfo(const MatrixF& mat, Collision* info) {
AssertFatal(false, GjkCollisionState::getCollisionInfo() - There remain scaling problems here.);
if (bits){
getClosestPoints(pa,pb);
mat.mulP(pa,&info->point);
b->getTransform().mulP(pb,&pa);
info->normal = info