C++ opengl中的有界盒碰撞检测

C++ opengl中的有界盒碰撞检测,c++,opengl,collision-detection,C++,Opengl,Collision Detection,这是程序的覆盖图。我在Visual Studio 10,C++中使用OpenGL/GLUT工作。我正在尝试创建一个迷宫(由输入文件生成)。然后我使用obj加载程序(glm)从3dstudio max导入两个模型。其中一个模型(mo)将在迷宫中移动。所以我在他周围和迷宫的墙壁周围加了一个边界框。我还在mo周围画了一个框,它似乎随着角色移动/旋转。但由于某种原因(也许我没有在正确的地方做),碰撞测试从未检测到任何东西。我会让代码来说话,如果你有任何问题,我会很高兴把它们理顺。现在就准备代码 //bo

这是程序的覆盖图。我在Visual Studio 10,C++中使用OpenGL/GLUT工作。我正在尝试创建一个迷宫(由输入文件生成)。然后我使用obj加载程序(glm)从3dstudio max导入两个模型。其中一个模型(mo)将在迷宫中移动。所以我在他周围和迷宫的墙壁周围加了一个边界框。我还在mo周围画了一个框,它似乎随着角色移动/旋转。但由于某种原因(也许我没有在正确的地方做),碰撞测试从未检测到任何东西。我会让代码来说话,如果你有任何问题,我会很高兴把它们理顺。现在就准备代码

//bounding boxes
struct BoundingBox
{
    Vector3D max;
    Vector3D min;
};
BoundingBox *box_mo;
BoundingBox *static_box[400];

void initbox(BoundingBox *b){
    b->min.x=100000;
    b->min.y=100000;
    b->min.z=100000;
    b->max.x=-100000;
    b->max.y=-100000;
    b->max.z=-100000;
}

BoundingBox *CreateCollisionBox(GLMmodel *model,GLMgroup *object){
/* GLM doesn't store each vertex together with the object that owns it. It doesn't have that notion. In GLM object don't have vertex, they have triangles. And each triangle is actually an index in the triangle list of the object.*/
    BoundingBox *boxx=(BoundingBox*)malloc(sizeof(BoundingBox));
    initbox(boxx);
    for(int i=0;i<object->numtriangles;i++){
// for each vertex of the triangle pmodel1->triangles[object->triangles[i]]
// calculate min and max
        for(int j=0;j<3;j++){
            GLuint index=model->triangles[object->triangles[i]].vindices[j];
            GLfloat x = model->vertices[index*3 +0];
            GLfloat y = model->vertices[index*3 +1];
            GLfloat z = model->vertices[index*3 +2];
            if(boxx->min.x>x) boxx->min.x =x;
            if(boxx->min.y>y) boxx->min.y =y;
            if(boxx->min.z>z) boxx->min.z =z;

            if(boxx->max.x<x) boxx->max.x =x;
            if(boxx->max.y<y) boxx->max.y =y;
            if(boxx->max.z<z) boxx->max.z =z;
        }
    }
    return boxx;
}

void AddCollisionBox(GLMmodel *model,GLMgroup *object){
    //box[boxindex]=CreateCollisionBox(model,object);
    box_mo=CreateCollisionBox(model,object);
    //boxindex++;
}
// A GLMmodel has a chained list of groups, each group representing an object. 
// Each object has a name (the name you gave it in 3D Studio Max or Gmax).
// Let's you have 10 walls in your scene a few other objects as well and you want to 
// create collision boxes just for the walls and you do not want to make a collision box 
// for one of your objects. You could name all your walls
// like this: Wall1, Wall2, ..., Wall10. If you wanted to add collision boxes just to them 
// you could go through all objects in the scene and if their name contains "Wall" add them.
// with this one: strstr
// Basicly this function does just that: if you want to add boxes for the walls you would call it like this: DefineCollisionBoxes(model,"Wall"); 
void DefineCollisionBoxes(GLMmodel *model,char *name){
    GLMgroup *group = model->groups;
    while(group){
        if(strstr(group->name,name))
            AddCollisionBox(model,group);
        group=group->next;
    }
}

bool Collision(BoundingBox *b,GLfloat x,GLfloat y,GLfloat z){
    return x <= b->max.x && x>= b->min.x && y<= b->max.y && y>= b->min.y && z<= b->max.z && z >= b->min.z;
}

bool CollisionTest(BoundingBox *a,BoundingBox *b){
    /*bool collision=false;
    for(int i=0;i<static_boxes;i++){
        for(float x=static_box[i]->min.x, y=static_box[i]->min.y,z=static_box[i]->min.z ;x<=static_box[i]->max.x && y<=static_box[i]->max.y && z<=static_box[i]->max.z;x+=0.1,y+=0.1,z+=0.1){
            if(Collision(a,x,y,z) == true)
                collision=true;
        }
    }
    return collision;*/
    if(a->min.x <= b->max.x && a->max.x >= b->min.x && a->min.z <= b->max.z && a->max.z >= b->min.z && a->min.y <= b->max.y && a->max.y >= b->min.y)
        return true;
    return false;
}

void drawBox(BoundingBox *b){
    glColor3f(1,1,1);
    glBegin(GL_LINE_LOOP);
    glVertex3f(b->max.x,b->max.y,b->min.z);
    glVertex3f(b->min.x,b->max.y,b->min.z);
    glVertex3f(b->min.x,b->min.y,b->min.z);
    glVertex3f(b->max.x,b->min.y,b->min.z);
    glEnd();

    glBegin(GL_LINE_LOOP);
    glVertex3f(b->max.x,b->min.y,b->max.z);
    glVertex3f(b->max.x,b->max.y,b->max.z);
    glVertex3f(b->min.x,b->max.y,b->max.z);
    glVertex3f(b->min.x,b->min.y,b->max.z);
    glEnd();

    glBegin(GL_LINE_LOOP);
    glVertex3f(b->max.x,b->max.y,b->min.z);
    glVertex3f(b->max.x,b->max.y,b->max.z);
    glVertex3f(b->min.x,b->max.y,b->max.z);
    glVertex3f(b->min.x,b->max.y,b->min.z);
    glEnd();

    glBegin(GL_LINE_LOOP);
    glVertex3f(b->max.x,b->min.y,b->max.z);
    glVertex3f(b->min.x,b->min.y,b->max.z);
    glVertex3f(b->min.x,b->min.y,b->min.z);
    glVertex3f(b->max.x,b->min.y,b->min.z);
    glEnd();
}


//display function
void display(){
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    //setup view
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    camera.render
    //read from file, create walls and characters 
    //place model mo in front of the third person camera always
    Vector3D positionn;
    positionn = camera.position + camera.forward*5;

    glPushMatrix();
    glColor3f(0.88f,0.75f,0.49f);
    //here i move my character and calculate bounding box at each frame for him
    glTranslatef(positionn.x,-0.42f,positionn.z);
    glScalef(0.7f,0.7f,0.7f);
    glRotatef(angle,0,1,0);
    drawMo();
    DefineCollisionBoxes(pmodel1,"body"); // actual function call
    drawBox(box_mo); //draw bounding box
    glPopMatrix();

    //test if the character collides with any of the walls - not working
    for(int i=0;i<static_boxes;i++){
        if(CollisionTest(box_mo,static_box[i]) == true){
            printf("collision");
        }
    }


    //swap buffers
    glutSwapBuffers();
}
//边界框
结构边界框
{
向量3D最大值;
向量3d-min;
};
边界框*box\u-mo;
边界框*静态_框[400];
无效初始框(边界框*b){
b->min.x=100000;
b->min.y=100000;
b->min.z=100000;
b->max.x=-100000;
b->max.y=-100000;
b->max.z=-100000;
}
BoundingBox*CreateCollisionBox(GLMmodel*模型,GLMgroup*对象){
/*GLM不会将每个顶点与拥有它的对象一起存储。它没有这个概念。在GLM中,对象没有顶点,它们有三角形。每个三角形实际上是对象三角形列表中的一个索引*/
BoundingBox*boxx=(BoundingBox*)malloc(sizeof(BoundingBox));
initbox(boxx);
for(int i=0;inumtriangles;i++){
//对于三角形的每个顶点,pmodel1->三角形[对象->三角形[i]]
//计算最小值和最大值
对于(int j=0;jtriangles[object->triangles[i]]。vindices[j];
GLfloat x=模型->顶点[索引*3+0];
GLfloat y=模型->顶点[索引*3+1];
GLfloat z=模型->顶点[索引*3+2];
如果(boxx->min.x>x)boxx->min.x=x;
如果(boxx->min.y>y)boxx->min.y=y;
如果(boxx->min.z>z)boxx->min.z=z;
如果(boxx->max.xmax.x=x;
如果(box x->max.ymax.y=y;
如果(boxx->max.zmax.z=z;
}
}
返回框X;
}
void AddCollisionBox(GLMmodel*模型,GLMgroup*对象){
//box[boxindex]=CreateCollisionBox(模型、对象);
box\u mo=CreateCollisionBox(模型、对象);
//boxindex++;
}
//GLMmodel具有组的链式列表,每个组表示一个对象。
//每个对象都有一个名称(您在3D Studio Max或Gmax中为其指定的名称)。
//让我们在场景中有10面墙,还有一些其他对象,您希望
//仅为墙创建碰撞框,而不希望创建碰撞框
//对于你的一个对象,你可以命名你所有的墙
//比如:Wall1,Wall2,…,Wall10。如果你想在它们上面添加碰撞框
//您可以浏览场景中的所有对象,如果它们的名称包含“墙”,则添加它们。
//用这个:strstr
//基本上这个函数就是这样做的:如果你想为墙添加框,你可以这样调用它:defineCollisionBox(model,“Wall”);
void defineCollisionBox(GLMmodel*模型,字符*名称){
GLMgroup*group=模型->组;
while(组){
if(strstr(组->名称,名称))
AddCollisionBox(模型、组);
组=组->下一步;
}
}
布尔碰撞(边界框*b、GLfloat x、GLfloat y、GLfloat z){
返回x max.x&&x>=b->min.x&&ymax.y&&y>=b->min.y&&zmax.z&&z>=b->min.z;
}
布尔碰撞测试(边界框*a,边界框*b){
/*布尔碰撞=假;
对于(int i=0;imin.x,y=static_-box[i]>min.y,z=static_-box[i]>min.z;xmax.x&&ymax.y&&zmax.z;x+=0.1,y+=0.1,z+=0.1){
if(碰撞(a,x,y,z)=真)
碰撞=真;
}
}
返回碰撞*/
如果(a->min.x max.x&&a->max.x>=b->min.x&&a->min.z max.z&&a->max.z>=b->min.z&&a->min.y max.y&&a->max.y>=b->min.y)
返回true;
返回false;
}
空心绘图框(边界框*b){
gl3f(1,1,1);
glBegin(GL_线_环);
glVertex3f(b->max.x,b->max.y,b->min.z);
glVertex3f(b->min.x,b->max.y,b->min.z);
glVertex3f(b->min.x,b->min.y,b->min.z);
glVertex3f(b->max.x,b->min.y,b->min.z);
格伦德();
glBegin(GL_线_环);
glVertex3f(b->max.x,b->min.y,b->max.z);
glVertex3f(b->max.x,b->max.y,b->max.z);
glVertex3f(b->min.x,b->max.y,b->max.z);
glVertex3f(b->min.x,b->min.y,b->max.z);
格伦德();
glBegin(GL_线_环);
glVertex3f(b->max.x,b->max.y,b->min.z);
glVertex3f(b->max.x,b->max.y,b->max.z);
glVertex3f(b->min.x,b->max.y,b->max.z);
glVertex3f(b->min.x,b->max.y,b->min.z);
格伦德();
glBegin(GL_线_环);
glVertex3f(b->max.x,b->min.y,b->max.z);
glVertex3f(b->min.x,b->min.y,b->max.z);
glVertex3f(b->min.x,b->min.y,b->min.z);
glVertex3f(b->max.x,b->min.y,b->min.z);
格伦德();
}
//显示功能
无效显示(){
glClear(GL_颜色_缓冲_位| GL_深度_缓冲_位);
//设置视图
glMatrixMode(GLU模型视图);
glLoadIdentity();
摄影机渲染
//从文件中读取,创建墙和角色
//始终将模型mo放在第三人称摄影机前面
矢量三维定位;
位置n=摄像机位置+摄像机向前*5;
glPushMatrix();
GL3F(0.88f、0.75f、0.49f);
//在这里,我移动我的角色,并为他计算每一帧的边界框
GLTRANSTEF(位置N.x,-0.42f,位置N.z);
glScalef(0.7f,0.7f,0.7f);
glRotatef(角度,0,1,0);
drawMo();
DefineCollisionBox(pmodel1,“body”);//实际函数调用
drawBox(box_-mo);//绘制边界框
glPopMatrix();
//测试角色是否与任何墙碰撞-不工作

对于(int i=0;i我将尝试给出如何解决碰撞问题的概要。为简单起见,我将做出以下假设:

  • 我们有一个迷宫所在的坐标系
  • 相机和模型都转换到该坐标系中
  • 为了使墙达到该坐标系,对墙执行的唯一变换是纯平移,而不进行任何转换
    GLfloat model[16]; 
    glGetFloatv(GL_MODELVIEW_MATRIX, model); 
    
    void drawCharacter(Matrix4f const & charMatrix);
    void drawMaze(Matrix4f const & mazeMatrix);
    //Will return MAX_FLT to indicate out of rectangle condition
    float distanceToRectangle(Vector3f const & point, Rectangle3df const & plane);
    vector<Rectangle3df> wallPlanes;
    Vector3f centerOfCharSphere;
    Vector3f pointOnCharSphere;
    //Initialization
    /*
    1. Go Over maze create planes for all walls
    2. Calculate character sphere and extract two points: The center of the sphere and a point on the sphere
    */
    
    //Render
    /*
    Calculate the charMatrix - The matrix that takes the character from object CRS to maze CRS
    Calculate the translation matrix for the maze (mazeMatrix) - the matrix that translates the maze into place
    */
    
    Vector3f transformedSphereCenter = charMatrix.transform(centerOfCharSphere);
    Vector3f transformedPointOnSphere = charMatrix.transform(pointOnCharSphere);
    Vector3f R = transformedPointOnSphere - transformedSphereCenter;
    float safeDistance = R.length();
    for(vector<Plane3f>::const_iterator it = wallPlanes.begin(); it != wallPlanes.end(); it++)
    {
        if(distanceToRectangle(transformedSphereCenter, *it) <= safeDistance)
           printf("collided\n");
    }
    
    /*
    Setup projection matrix
    Setup the modelview matrix for the camera
    */
    drawMaze(mazeMatrix);
    drawCharacter(charMatrix);