OK, before I start I need to tell you something: I have no experience with linear algebra :( . I am pretty good at programming, and regular algebra, but I am totally clueless about the linear stuff.
I have several flat quads, at 90º angles. I need some balls to bounce off them :)
Here goes: My collision detection just don't work. It's as if it's not there. Let me show you a few code samples:
Definition of some types first:
- point3d holds a 3d point
- plane3d is not really a plane. :) It's got point 3d points[4] for holding a quad, float normal x, y, z for the plane normal, and float distance for the plane distance
My function used for calculating distances:
Notice that the code above only calculates the distance of the plane; the plane normals and coordinates are hand-typed. (I probably could've used a loop, but I was too lazy.)Code:void calculate_plane(plane3d *theplane) {
point3d *v1 = &theplane->points[0];
point3d *v2 = &theplane->points[1];
point3d *v3 = &theplane->points[2];
theplane->distance = -(v1->x * (v2->y * v3->z - v3->y * v2->z) +
v2->x * (v3->y * v1->z - v1->y * v3->z) +
v3->x * (v1->y * v2->z - v2->y * v1->z) );
}
So far, so good, right?
Now I need a function to figure out which side of the plane a point is on:
Where PLANE_FRONT, PLANE_BACK, and PLANE_COINCIDE are 99, 100, and 101, repectively. But the values don't really matter; as long as they're different.Code:int classify_point(plane3d *plane, point3d *dest_pt )
{
float p = dot_product( &plane->normal, dest_pt ) + plane->distance;
if( p > 0.0f ) return PLANE_FRONT;
else
if( p < 0.0f ) return PLANE_BACK;
return PLANE_COINCIDE;
}
Now, I know that the ball will always be inside the walls (the 4 walls enclose the ball), so that means that I can skip the process of finding where exactly the collision point on the plane is, right?
All that is left is to find which wall it hit, and then reverse the correct axis:
Where tube is really plane3d tube[4], and so notice that I check to see which wall of the tube it collided into before reversing the appropriate axis. (tube[0] and tube[2] are the bottom and top, respectively. And of course tube[1] and tube[3] are the left and back, respectively.)Code:void ball_collision(ball *theball) {
// note that we don't actually make sure that the collision point is on the quad; because this
// is such a simple game, that's all the checking we need to do :)
point3d ¤t_pos = theball->pos; // grab the ball's current position
point3d dest_pos; // this will hold where the ball would go
// from the current velocity, calculate where the ball would go (its destination)
dest_pos.x = theball->pos.x + theball->vel.x;
dest_pos.y = theball->pos.y + theball->vel.y;
dest_pos.z = theball->pos.z + theball->vel.z;
// run through each plane in tube
for (int i=0; i<4; i++) {
int dest_side = classify_point(&tube[i], &dest_pos);
int current_side = classify_point(&tube[i], ¤t_pos);
// check to see if the destintation point and the current point are on the same sides of the plane (quad)
if (dest_side != current_side) {
// find which wall it collided into
if (i == 0 || i == 2) {
// ball collided on the y axis, so reverse it
theball->pos.y = -theball->pos.y;
return;
}
else {
// ball collided on the x axis
theball->pos.x = -theball->pos.x;
return;
}
}
// keep going
}
}
Then I actually run the collision function here:
But whenever I run the program, the ball keeps going through the walls as if I was never calling the functions. I looked at what the variables are doing, and classify_point always returns PLANE_FRONT, even when the ball is going to fly into the wall.Code:void ball_draw(ball *theball) {
// make sure the ball didn't collide with anything
ball_collision(theball);
glTranslatef(theball->pos.x, theball->pos.y, theball->pos.z);
glColor3f(0.5f, 0.5f, 0.5f);
gluSphere(quadratic, ball_radius, ball_subdiv_x, ball_subdiv_y);
}
Can anyone much smarter than me see where I went wrong? :confused: