Search code examples
copenglcollision-detection

Simple collision detection?


Edit: Turns out I just had some values -switched-.


I'm working with OpenGL and coding with C on my Windows computer, and I'm trying to get a really, really basic collision detection going on. Right now, I'm trying this to see if a point Ox,Oz is inside of two boxes:

int collision(int box[2][4]) {
    int col;
    int i;
    for (i=0;i<2;i++){
    col = 0;
    printf("x1:%.0f y1:%.0f x2:%.0f y2:%.0f \n",colbox[i][0],colbox[i][1],colbox[i][2],colbox[i][3]);
    printf("Ox:%.1f Oy:%.1f Oz:%.1f \n" , Ox,here,Oz);
    if ((colbox[i][0] < Ox) && (Ox < colbox[i][2])&& (colbox[i][1] < Oz) && (colbox[i][3] > Oz)) 
        return 1;
    else
        return 0;
    }

}   

I've also tried variations, like having nothing pass through to the function, putting the loop outside the function, etc. The problem seems to be with equality check?

At the very lowest level of what I'm trying to do is to see if a point (the camera) is within a boundary (which is a set of 4 points kept in a 2D array), and if it is in -any- of the boundaries listed, return 1. If the point is NOT in any of the boundaries, return 0.

When this does work, it only does it for one area, IE if I move over to the first listed bounded area, it returns properly, but the second area doesn't return properly.

Full Code if it's really helpful:

//  Values
double Ox=0, Oz=0;
float Oy=1.0;
double asp=1;       //  Aspect ratio
double dim=20;      //  Size of world
double fov=55;      //  Field of View
double ph,th = 0;
// angle of rotation for the camera direction
float angle = 0.0;
// actual vector representing the camera's direction
float lx=0.0,lz=-1.0;
// the key states. These variables will be zero
//when no key is being presses
float deltaAngle = 0.0;
float deltaMove = 0;
double here;
int collide;

// {x1,y1,x2,y2}
double colbox[2][4] = {
    {3,3,6,6},  
    {-1,-14,-3,-16}
};

//front-1 back-2 left-3 right-4
int collision(double box[2][4]) {
    int i;
    for (i=0;i<2;i++){
    col = 0;
    printf("x1:%.0f y1:%.0f x2:%.0f y2:%.0f \n",colbox[i][0],colbox[i][1],colbox[i][2],colbox[i][3]);
    printf("Ox:%.1f Oy:%.1f Oz:%.1f \n" , Ox,here,Oz);
    if ((colbox[i][0] < Ox) && (Ox < colbox[i][2])&& (colbox[i][1] < Oz) && (colbox[i][3] > Oz)) 
        return 1;
    else
        return 0;
    }

}               

//test
static void ball(double x,double y,double z,double r)
{
   //  Save transformation
   glPushMatrix();
   //  Offset, scale and rotate
   glTranslated(x,y,z);
   glScaled(r,r,r);
   //  White ball
   glColor3f(1,1,1);
   glutSolidSphere(1.0,16,16);
   //  Undo transofrmations
   glPopMatrix();
}
static void square(double r) {
    glPushMatrix();
    glScaled(r,r,r);
    glColor3f(1,0,0);
    glBegin(GL_QUADS);
    glVertex3f(-1,0,-1);
    glVertex3f(1,0,-1);
    glVertex3f(1,0,1);
    glVertex3f(-1,0,1);
    glEnd();
    glPopMatrix();
}

//test
void computePos(float deltaMove) {
    Ox += deltaMove * lx * 0.1f;
    Oz += deltaMove * lz * 0.1f;
}
void computeDir(float deltaAngle) {
    angle += deltaAngle;
    lx = sin(angle);
    lz = -cos(angle);
}


// display
void display() {
    here = 2.0f*Oy;
    if (deltaMove)
        computePos(deltaMove);
    if (deltaAngle)
        computeDir(deltaAngle);
                const double len=2.0;
    //  Erase the window and the depth buffer
    glClearColor(0.3,0.5,1.0,1);
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
    //  Enable Z-buffering in OpenGL
    glEnable(GL_DEPTH_TEST);
    //  Set perspective
    glLoadIdentity();
    gluLookAt(Ox,2,Oz, Ox+lx, here, Oz+lz, 0,1,0);

    ball(5,5,5,2); ball(-2,0,-15,1);
    square(15);
    glColor3f(1,1,1);
      glBegin(GL_LINES);
      glVertex3d(0.0,0.0,0.0);
      glVertex3d(len,0.0,0.0);
      glVertex3d(0.0,0.0,0.0);
      glVertex3d(0.0,len,0.0);
      glVertex3d(0.0,0.0,0.0);
      glVertex3d(0.0,0.0,len);
      glEnd();
      //  Label axes
      glRasterPos3d(len,0.0,0.0);
      Print("X");
      glRasterPos3d(0.0,len,0.0);
      Print("Y");
      glRasterPos3d(0.0,0.0,len);
      Print("Z");
    //  Render the scene and make it visible
    glColor3f(0,0,0);
    glWindowPos2i(5,5);
    Print("Ox:%.1f Oy:%.1f Oz:%.1f  lx:%.1f lz:%.1f Collide:%d", Ox,here,Oz,lx,lz,collide);
    ErrCheck("display");
    glFlush();
    glutSwapBuffers();
}


void key(unsigned char ch,int x,int y) {
    //  Exit on ESC
    if (ch == 27)
        exit(0);
    // WASD controls
    else if (ch == 'a' || ch == 'A')
        deltaAngle = -0.05;
    else if (ch == 'd' || ch == 'D')
        deltaAngle = 0.05;
    else if (ch == 'w' || ch == 'W') {
            collide=collision(colbox);
            deltaMove = 1; }

    else if (ch == 's' || ch == 'S') {
            collide=collision(colbox);
            deltaMove = -1; }

    else if ((ch == 'e' || ch == 'E') && here < 4)
        Oy += 0.01;
    else if ((ch == 'c' || ch == 'C') && here > .5)
        Oy -= 0.01;

    Project(fov,asp,dim);
    glutPostRedisplay();
}

void reshape(int width,int height) {
    //  Ratio of the width to the height of the window
    asp = (height>0) ? (double)width/height : 1;
    //  Set the viewport to the entire window
    glViewport(0,0, width,height);
    //  Set projection
    Project(fov,asp,dim);
}

void releaseKey(unsigned char ch, int x, int y) {
    if (ch == 'a' || ch == 'A')
        deltaAngle = 0;
    else if (ch == 'd' || ch == 'D')
        deltaAngle = 0;
    else if (ch == 'w' || ch == 'W')
        deltaMove = 0;
    else if (ch == 's' || ch == 'S')
        deltaMove = 0;
    Project(fov,asp,dim);
    glutPostRedisplay();
}


int main(int argc,char* argv[]) {
   //  Initialize GLUT
   glutInit(&argc,argv);
   //  Request double buffered, true color window with Z buffering at 600x600
   glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
   glutInitWindowSize(800,500);
   glutCreateWindow("Haunted House");
   //  Set callbacks
   glutDisplayFunc(display);
   glutReshapeFunc(reshape);
//   glutSpecialFunc(special);
   glutKeyboardFunc(key);

    glutKeyboardUpFunc(releaseKey);
   //  Pass control to GLUT so it can interact with the user
   ErrCheck("init");
   glutMainLoop();
   return 0;
}

Solution

  • I think when you have i=1 the second line

    if ((colbox[i+1][0] < Ox) && (Ox < colbox[i+1][2])&& (colbox[i+1][1] < Oz) && (colbox[i+1][3] > Oz))
    

    walks off of the array of size 2. (Since the max index for this is 1.)

    So, given that it's reading memory that's not inside the array (Which I think is generally ok) you will find that condition probably fails a lot, maybe even most of the time since it's working with essentially random data. So it then returns 0.