PDA

View Full Version : collision-detection



mathias_123
02-24-2002, 02:42 AM
Hello World!
I'm trying to check if my camera collides with a cube. My camera is represented as a sphere.
The cube is represented as six infinite planes. The function SphereInStaticObj(...) checks whether
the sphere is in front of all six planes or not. I think this sounds ok, but however, it does not really
work. I've never had matrices or vectors in maths at school, and all I know about it, I've collected
in several tutorials in the net. That's why I do not find the mistake in my equations, and so I'm asking
you more advanced people for help (once more).

The problem:
The cube is correctly detected, when the camera moves inside it. But in some positions of the camera, the
function returns "true" although it's outside the cube.

THE HEADER:


//------------------------------------------------------------------------------------------------------------------------------------

typedef float BOX[6][4]; // 6 planes, containing 3 values for a point on the plane, and the 4th value for the distance.
// The BOX-values are extracted automatically by the function "NewStaticObj(...)".
typedef float BOXpoints[18]; // Here you can store the 6 points of the box.
typedef float BOXnormals[18]; // Here you can store the 6 normals of the box. The order must be the same as in BOXpoints (first
// BOXpoints must fit to the first BOXnormal).

class Collision
{
private:
Vectorz *vect; // This is a vector-class, from which only the dot-product is used.
BOX *staticObj; // staticObj is a dynamic array of BOX to store some BOXes.

public:
Collision(int num) { staticObj = new BOX[num]; vect = new Vectorz(); } //the constructor requires the number of the BOXes
//that we want to create, for setting the size of the statcObj-array.

~Collision() { delete[] staticObj; delete vect; }

void NewStaticObj(int, BOXpoints, BOXnormals); // This function extracts the points and normals of the box and calculates
//the distances from the six points to the origin and the six points. These values are stored in the
//staticObj-array. The int-parameter is just an indey for the number of the box.

bool SphereInStaticObj(float, float, float, float, int); // The first three params are the point of the sphere. The 4th
//param is the distance of the sphere. The 5th param is the number of the BOX we want to check.
};

//------------------------------------------------------------------------------------------------------------------------------------


CPP - FILE:



//------------------------------------------------------------------------------------------------------------------------------------

void Collision::NewStaticObj(int num, BOXpoints p, BOXnormals n)
{
BOX box;
VECTOR N, P; //VECTOR is defined as an array of three values. N stands for normal, P for point.
float dist;

for (int i=0; i < 6; i++)
{
N[0] = n[i*3 + 0]; // ...put the BOXpoints ans BOXnormals in VECTOR-arrays to make them valid
N[1] = n[i*3 + 1]; // params for the dot-function.
N[2] = n[i*3 + 2];
P[0] = p[i*3 + 0];
P[1] = p[i*3 + 1];
P[2] = p[i*3 + 2];

dist = vect->Dot(P, N); // This should produce the negated distance of the plane from the origin.
box[i][0] = P[0];
box[i][1] = P[1];
box[i][2] = P[2];
box[i][3] = dist;
}

memcpy(staticObj[num], box, sizeof(box)); // Now we've extracted the values to store in a BOX of the staticObj-array.
}

bool Collision::SphereInStaticObj(float x, float y, float z, float r, int num)
{
for (int p = 0; p < 6; p++) // check if the distance is smaller than the negated radius of the sphere.
if (staticObj[num][p][0] * x + staticObj[num][p][1] * y + staticObj[num][p][2] * z + staticObj[num][p][3] <= -r)
return false;
return true;
}

//------------------------------------------------------------------------------------------------------------------------------------


I've commented the code as good as possible, you see that everything is based on the plane-equation
Ax+Bx+Cx+d=0.

Thaks in advance for your help !!!!
_____________________________

mathias_123

mathias_123
02-24-2002, 03:42 AM
Hello again,
I've just found something new, that doen't work...

I've tried to expand the function NewStaticObj(...) with three new params. This should make it simpler
to work with translated boxes. For example, if I build a box around the origin and want to draw it somwhere
translated in the scene, then I can give the original values of the box to the function, and enter three
translation values into the new three params. Now, the function should add the x-translation value to all
x-values given in the BOXpoints, and the same procedure with the y and z values.
But when I then check the collision, NOTHING seems to work. I receive a collision almost everywhere in the
scene.

I thought about this to be a problem with the way I perform my camera-translations. Because I want to
make translations like an aeroplane would produce, I have to rotate in 1-degree-steps and then multiply
the matrix of the rotations with the current matrix. This should be a solution to avoid the Gimbal Lock.
But might it be the reason for my problems?

Here, the modified NewStaticObj(...)-function:



void Collision::NewStaticObj(int num, BOXpoints p, BOXnormals n, float x, float y, float z)
{
BOX box;
VECTOR N, P; //VECTOR is defined as an array of three values. N stands for normal, P for point.
float dist;

for (int i=0; i < 18; i+=3)
{
p[i+0] += x;
p[i+1] += y;
p[i+2] += z;
}

for (int i=0; i < 6; i++)
{
N[0] = n[i*3 + 0]; // ...put the BOXpoints ans BOXnormals in VECTOR-arrays to make them valid
N[1] = n[i*3 + 1]; // params for the dot-function.
N[2] = n[i*3 + 2];
P[0] = p[i*3 + 0];
P[1] = p[i*3 + 1];
P[2] = p[i*3 + 2];

dist = vect->Dot(P, N); // This should produce the negated distance of the plane from the origin.
box[i][0] = P[0];
box[i][1] = P[1];
box[i][2] = P[2];
box[i][3] = dist;
}

memcpy(staticObj[num], box, sizeof(box)); // Now we've extracted the values to store in a BOX of the staticObj-array.
}


Thanks for your help,

Mathias.

richardve
02-24-2002, 03:49 AM
Your problem is that you're not using any GL functions..

mathias_123
02-24-2002, 09:43 AM
Although I'm not using any GL functions, I didn't know any other forum where I could post my question, and in this forum have already been other topics on collision-detection although it's actually no part of OpenGL. But anyway - I've found the misstake in the code, and if someones interested in it, here's the corrected function:


void Collision::NewStaticObj(int num, BOXpoints p, BOXnormals n, float x, float y, float z)
{
BOX box;
VECTOR N, P; //VECTOR is defined as an array of three values. N stands for normal, P for point.
float dist;

for (int i=0; i < 18; i+=3)
{
p[i+0] += x;
p[i+1] += y;
p[i+2] += z;
}

for (int i=0; i < 6; i++)
{
N[0] = n[i*3 + 0]; // ...put the BOXpoints ans BOXnormals in VECTOR-arrays to make them valid
N[1] = n[i*3 + 1]; // params for the dot-function.
N[2] = n[i*3 + 2];
P[0] = p[i*3 + 0];
P[1] = p[i*3 + 1];
P[2] = p[i*3 + 2];

dist = vect->Dot(P, N); // This should produce the negated distance of the plane from the origin.
box[i][0] = N[0]; // HERE WAS THE ERROR
box[i][1] = N[1];
box[i][2] = N[2];
box[i][3] = dist;
}

memcpy(staticObj[num], box, sizeof(box)); // Now we've extracted the values to store in a BOX of the staticObj-array.
}


bye,

mathias

richardve
02-24-2002, 10:49 AM
Originally posted by mathias_123:
I didn't know any other forum where I could post my question

www.gamedev.net (http://www.gamedev.net)
www.flipcode.com (http://www.flipcode.com)
www.cfxweb.net (http://www.cfxweb.net)


[This message has been edited by richardve (edited 02-24-2002).]