Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 4 of 4

Thread: Character collision

  1. #1
    Junior Member Newbie
    Join Date
    Nov 2012
    Posts
    4

    Character collision

    Hi guys, i'm having trouble with adding collision detection for my character.Basically what i have is a few walls(created in glut) ,and a character imported from an obj file created in 3ds max. I add bounded boxes to them but here is where i have a problem. When i draw my character, i create a box around him. But even if i move my character the box stays in the same place , even though i call the function every frame. What seems to be the problem , what am i calculating/doing wrong ? I'll post the code below, thank you.

    Code :
    //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();
    }

  2. #2
    Senior Member OpenGL Pro
    Join Date
    Jan 2012
    Location
    Australia
    Posts
    1,105
    I can't see your problem but this code only needs to be called once since it's data never changes.


    Code :
    DefineCollisionBoxes(pmodel1,"body"); // actual function call

    Do you get the same problem if you call drawBox prior to drawMo. Maybe drawMo is popping the transformation matrix.

  3. #3
    Junior Member Newbie
    Join Date
    Nov 2012
    Posts
    4
    Thank you for your reply, yes i tried that too and it can't be called before drawMo. The problem is that in the pmodel1 pointer, the vertices are the values from the .obj file so they never change, at least that's what i think. I tried with bounding spheres and it works. What i do is i don't even encapsulate the character, i just create the sphere at his position and update its structure according to positionn vector like i do for drawMo . Now i can do the same for the box ( try to estimate the initial min-max) then translate the center(calculated from min-max.x/z/y) and recalculate min-max values, but i don't know how to calculate them if i rotate the box as well. Any advise is greatly appreciated , thanx

  4. #4
    Junior Member Newbie yoyonel's Avatar
    Join Date
    Sep 2010
    Location
    Paris
    Posts
    23
    Hi !

    You need to apply your transformation local object space -> world space to your AABBOX to have the AABBOX in world space (it's the space where you're compute the interaction with others objects).

    So ... i think the method is:
    (1) with the local vertices (in .obj) compute a local (object) AABBOX
    (2) when you do rendering/physic computations, retrieve the ModelView Matrix (local object -> world space) and transform your 6 vertices of AABBox (local space) with this matrix. (local -> world)
    (3) Use this AABBox in World Space to do your job (physic stuffs, collision, intersection, respond collision, etc ...)
    (4) for the rendering (of AABBox): use the local AABOX (compute in (1)) and apply the same transformation of your model rendering

    I hope i'm understandable ^^
    My english is horrible, but it's not the main contribution ;-)

    Good Luck dude,
    YoYOOoOOo

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •