这是程序的覆盖图。我在 Visual Studio 10 中工作,使用 opengl/glut 的 c++。我正在尝试创建一个迷宫(我从输入文件生成)。然后我使用 obj loader(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();
}