准备用OBB绑定于3D游戏中人物的骨骼块来做碰撞,在3D动作或格斗游戏用的较多,碰撞算法在网上找的,比较复杂,先拿来用吧,写了个简单的OBB类。
OrientedBoundingBox
#pragma once
#include "GSMatrix4X4.h"
#include "GSVector3D.h"
using namespace GSFrameWork;
#include <GL/gl.h>
class COrientedBoundingBox
{
public:
COrientedBoundingBox()
{
mVel.set(0,0,0);
mPosition.set(0,0,0);
mTransforms.identity();
mRotate.set(0,0,0);
mAngleVel.set(0,0,0);
}
COrientedBoundingBox(GSVector3D_f _min,GSVector3D_f _max)
{
set(_min,_max);
mTransforms.identity();
mRotate.set(0,0,0);
mAngleVel.set(0,0,0);
}
~COrientedBoundingBox()
{}
void set(GSVector3D_f _min,GSVector3D_f _max)
{
mMin = _min;
mMax = _max;
update();
}
void render()
{
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glMultMatrixf(mTransforms.m);
float halfSize = mSize * 0.5f;
glBegin(GL_QUADS);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f( halfSize, halfSize,-halfSize);
glVertex3f(-halfSize, halfSize,-halfSize);
glVertex3f(-halfSize, halfSize, halfSize);
glVertex3f( halfSize, halfSize, halfSize);
glColor3f(1.0f,0.5f,0.0f);
glVertex3f( halfSize,-halfSize, halfSize);
glVertex3f(-halfSize,-halfSize, halfSize);
glVertex3f(-halfSize,-halfSize,-halfSize);
glVertex3f( halfSize,-halfSize,-halfSize);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f( halfSize, halfSize, halfSize);
glVertex3f(-halfSize, halfSize, halfSize);
glVertex3f(-halfSize,-halfSize, halfSize);
glVertex3f( halfSize,-halfSize, halfSize);
glColor3f(1.0f,1.0f,0.0f);
glVertex3f( halfSize,-halfSize,-halfSize);
glVertex3f(-halfSize,-halfSize,-halfSize);
glVertex3f(-halfSize, halfSize,-halfSize);
glVertex3f( halfSize, halfSize,-halfSize);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f(-halfSize, halfSize, halfSize);
glVertex3f(-halfSize, halfSize,-halfSize);
glVertex3f(-halfSize,-halfSize,-halfSize);
glVertex3f(-halfSize,-halfSize, halfSize);
glColor3f(1.0f,0.0f,1.0f);
glVertex3f( halfSize, halfSize,-halfSize);
glVertex3f( halfSize, halfSize, halfSize);
glVertex3f( halfSize,-halfSize, halfSize);
glVertex3f( halfSize,-halfSize,-halfSize);
glEnd();
glPopMatrix();
}
bool intersects(COrientedBoundingBox &obb)
{
updateMatrix();
GSMatrix4X4_f invertMe = mTransforms;
invertMe.invert();
GSMatrix4X4_f t = obb.mTransforms * invertMe;
GSVector3D_f obbCenter = t * obb.mCenter;
GSVector3D_f obbExtents = obb.mExtents;
GSVector3D_f separation = obbCenter - mCenter;
GSMatrix4X4_f rotations(t);
GSMatrix4X4_f absrotations = rotations.abs();
float r,r0,r1,r01;
//
r = fabs(separation.x);
r1 = obbExtents.dotProduct(absrotations.col(0));
r01 = mExtents.x + r1;
if(r > r01) return false;
r = fabs(separation.y);
r1 = obbExtents.dotProduct(absrotations.col(1));
r01 = mExtents.y + r1;
if(r > r01) return false;
r = fabs(separation.z);
r1 = obbExtents.dotProduct(absrotations.col(2));
r01 = mExtents.z + r1;
if(r > r01) return false;
//
r = fabs(rotations.row(0).dotProduct(separation));
r0 = mExtents.dotProduct(absrotations.row(0));
r01 = r0 + obbExtents.x;
if(r > r01) return false;
r = fabs(rotations.row(1).dotProduct(separation));
r0 = mExtents.dotProduct(absrotations.row(1));
r01 = r0 + obbExtents.y;
if(r > r01) return false;
r = fabs(rotations.row(2).dotProduct(separation));
r0 = mExtents.dotProduct(absrotations.row(2));
r01 = r0 + obbExtents.z;
if(r > r01) return false;
//
r = fabs(separation.z * rotations.mm[0][1] - separation.y * rotations.mm[0][2]);
r0 = mExtents.y * absrotations.mm[0][2] + mExtents.z * absrotations.mm[0][1];
r1 = obbExtents.y + absrotations.mm[2][0] + obbExtents.z * absrotations.mm[1][0];
r01 = r0 + r1;
if(r > r01) return false;
r = fabs(separation.z * rotations.mm[1][1] - separation.y * rotations.mm[1][2]);
r0 = mExtents.y * absrotations.mm[1][2] + mExtents.z * absrotations.mm[1][1];
r1 = obbExtents.x + absrotations.mm[2][0] + obbExtents.z * absrotations.mm[0][0];
r01 = r0 + r1;
if(r > r01) return false;
r = fabs(separation.z * rotations.mm[2][1] - separation.y * rotations.mm[2][2]);
r0 = mExtents.y * absrotations.mm[2][2] + mExtents.z * absrotations.mm[2][1];
r1 = obbExtents.x + absrotations.mm[1][0] + obbExtents.y * absrotations.mm[0][0];
r01 = r0 + r1;
if(r > r01) return false;
//
r = fabs(separation.x * rotations.mm[0][2] - separation.z * rotations.mm[0][0]);
r0 = mExtents.x * absrotations.mm[0][2] + mExtents.z * absrotations.mm[0][0];
r1 = obbExtents.y * absrotations.mm[2][1] + obbExtents.z * absrotations.mm[1][1];
r01 = r0 + r1;
if(r > r01) return false;
r = fabs(separation.x * rotations.mm[1][2] - separation.z * rotations.mm[1][0]);
r0 = mExtents.x * absrotations.mm[1][2] + mExtents.z * absrotations.mm[1][0];
r1 = obbExtents.x * absrotations.mm[2][1] + obbExtents.z * absrotations.mm[0][1];
r01 = r0 + r1;
if(r > r01) return false;
r = fabs(separation.x * rotations.mm[2][2] - separation.z * rotations.mm[2][0]);
r0 = mExtents.x * absrotations.mm[2][2] + mExtents.z * absrotations.mm[2][0];
r1 = obbExtents.x * absrotations.mm[1][1] + obbExtents.y * absrotations.mm[0][1];
r01 = r0 + r1;
if(r > r01) return false;
//
r = fabs(separation.y * rotations.mm[0][0] - separation.x * rotations.mm[0][1]);
r0 = mExtents.x * absrotations.mm[0][1] + mExtents.y * absrotations.mm[0][0];
r1 = obbExtents.y * absrotations.mm[2][2] + obbExtents.z * absrotations.mm[1][2];
r01 = r0 + r1;
if (r > r01) return false;
r = fabs(separation.y * rotations.mm[1][0] - separation.x * rotations.mm[1][1]);
r0 = mExtents.x * absrotations.mm[1][1] + mExtents.y * absrotations.mm[1][0];
r1 = obbExtents.x * absrotations.mm[2][2] + obbExtents.z * absrotations.mm[0][2];
r01 = r0 + r1;
if (r > r01) return false;
r =fabs(separation.y * rotations.mm[2][0] - separation.x * rotations.mm[2][1]);
r0 = mExtents.x * absrotations.mm[2][1] + mExtents.y * absrotations.mm[2][0];
r1 = obbExtents.x * absrotations.mm[1][2] + obbExtents.y * absrotations.mm[0][2];
r01 = r0 + r1;
if (r > r01) return false;
return true;
}
void setSize(float size)
{
mSize = size;
float halfSize = mSize * 0.5f;
mMin.set(-halfSize,-halfSize,-halfSize);
mMax.set(halfSize,halfSize,halfSize);
update();
}
void update()
{
mCenter = (mMin + mMax) * 0.5f;
mExtents = (mMax - mMin) * 0.5f;
mPosition += mVel;
mRotate += mAngleVel;
updateMatrix();
}
void updateMatrix()
{
mTransforms.identity();
mTransforms.translate(mPosition.x,mPosition.y,mPosition.z);
if(mRotate.x)
mTransforms.rotate_x(mRotate.x);
if(mRotate.y)
mTransforms.rotate_y(mRotate.y);
if(mRotate.z)
mTransforms.rotate_z(mRotate.z);
}
GSMatrix4X4_f mTransforms;
GSVector3D_f mMin;
GSVector3D_f mMax;
GSVector3D_f mCenter;
GSVector3D_f mExtents;
GSVector3D_f mPosition;
GSVector3D_f mRotate;
GSVector3D_f mVel;
GSVector3D_f mAngleVel;
float mSize;
};