Wall collision detection
As far as I see, you expect to find some tutorial named “Wall collision detection in OpenGL”; this rarely happens.
Engineering simply is applying stuff; an engineer applies stuff, he learns concepts & facts and makes something useful out of them.
John carmack - after Wolfenstein - found a paper on BSP trees, the paper was just discussing BSP trees. He invested this knowledge and made his DOOM engine (which was and is a bit famous). The paper wasn't entitled “Using BSP trees to sort geometry in an advanced raycasting engine as well as doing collision detection checks”, because this is his job - as a software engineer. The paper only introduced the concepts.
Now, those tutorials I pointed you to should've given you the following info (as well as some more, but let's just limit ourselves to these) :
1 - AABB - AABB (Axis-aligned bounding box) collision detection.
2 - Sphere - AABB collision detection.
3 - Plane - Sphere collision detection.
4 - Plane - AABB collision detection (I'm not sure whether this was in one of the tutorials, yet it can be easily deduced from the plane-sphere collision detection).
Using 1 & 2, you can do collision detection between your objects.
Using 3 & 4, you can do collision detection between objects & walls.
How?
We'll examine 4 as an example of the approach to solving such a problem. Please note that the following is definitely not the best/correct way to do it. It's the solution from my point of view based on my current knowledge of the subject. Experienced programmers will have better solutions (i.e This is not the standard solution). Additionally, there might be bugs :
Code:
Requirement specification (Problem description)
Detecting whether an object and a wall are colliding or not in a 3D world.
Given some walls and a player, we have to detect whether the player's colliding with any of the walls.
Analysis
Input(s) :
1 - A pool of vertices defining the world. Each 4 consecutive vertices define a wall.
2 - A player
Output(s) :
1 - Result of collision check
Design
// For each wall, we want to create a plane for that wall to
// be used in collision detection as well as a bounding
// volume.
// The reason we need a bounding volume (sphere or box) is
// that a plane collision
// check checks the collision between an object & the plane of
// the wall (thus it acts as if your wall is infinitely long
// in all directions, while it definitely isn't).
// Bounding volumes act as a first line-of-defense, they
// prevent false collision detections with planes. See the
// attached image)
// We need the following info for a wall:
Wall_t
Plane
Sphere
FirstVertexIndex
End Wall_t
Procedure : Init
Input(s) : A vertex pool
// We first have to create a wall pool. The number of elements
// in this pool is the number of vertices we have divided by
// 4.
Create wall array of NumVertices/4 elements
// Now, we need to the fill each wall with proper info
for each 4 vertices in vertex pool
CorrespondingWall.Plane = CreatePlane v1,v2,v3
CorrespondingWall.Sphere = CalculateSphere v1,v2,v3,v4
CorrespondingWall.FirstVertexIndex = IndexOf v1
end for
End Procedure
Procedure : Destroy
Destroy wall pool
End Procedure
Procedure : CheckPlayerCollision
Input(s) : PlayerSphere
Output(s) : Result
// Now you have an array of properly filled Wall_t's. You
// need to have a bounding sphere around your player. On any
// frame update, you check the player's position in
// some heirarchial organization of your map (BSP/OCT/QUAD
// tree) in order to know which walls are close enough to do
// collision checking with (you won't check all the walls,
// otherwise the engine would be slow)
WallList = GetNearWallsFromTree(PlayerSphere)
// Assume no collision
Result = false
// Loop through walls
for each wall in WallList
if true == SphereSphereCheck(PlayerSphere,Wall.Sphere)
if true == SpherePlaneCheck(PlayerSphere,Wall.Plane)
Result = true
End if
End if
End for
End Procedure
Detailed design
Procedure : CreatePlane
Input(s) : v1,v2,v3
Output(s) : Plane
Vector Plane.Normal = (v3 - v1) Cross (v2 - v1)
Normalize Plane.Normal
Plane.D = - (v1) Dot (Plane.Normal)
End Procedure
Procedure : CalculateSphere
Input(s) : v1,v2,v3,v4
Output(s) : Sphere
Sphere.Center = (v1 + v2 + v3 + v4)/4;
Vector FarthestPoint = FarthestVectorFromCenter(Center,v1,v2,v3,v4)
Sphere.Radius = VectorLength( FarthestPoint - Center )
End Procedure
Procedure : FarthestVectorFromCenter
Input(s) : Center,v1,v2,v3,v4
Output(s) : vOut
Vector vOut = v1
Distance = VectorLength(v1 - Center)
if Distance < VectorLength(v2 - Center)
Distance = VectorLength(v2 - Center)
vOut = v2
End if
if Distance < VectorLength(v3 - Center)
Distance = VectorLength(v3 - Center)
vOut = v3
End if
if Distance < VectorLength(v4 - Center)
Distance = VectorLength(v4 - Center)
vOut = v4
End if
End Procedure
Procedure : SphereSphereCheck
Input(s) : Sphere1,Sphere2
Output(s) : Result
Distance = VectorLength(Sphere1.Center - Sphere2.Center)
If Distance >= Sphere1.Radius + Sphere2.Radius
Result = false
Else
Result = true
End Procedure
Procedure : SpherePlaneCheck
Input(s) : Sphere, Plane
Output(s) : Result
Distance = Sphere.Center Dot Plane.Normal + Plane.D
if Distance >= Sphere.Radius
Result = false
Else
Result = true
// Now we know it's a collision, you can either
// stop your object (thus preventing it from penetrating
// the wall), or
// make it slide along the wall (read Paul Nettle's
// article to know how. If you still can't figure out
// how, tell me)
End Procedure
Implementation
// Code everything
.
.
.
Testing & debugging
When you do this, you're done.
Notes :
1 - You'll need to make your player slide along a wall when he hits it, otherwise he won't be able to walk on any inclined ground.
2 - This test won't work for fast objects. If an object moves a great distance in one frame, such that it penetrates a wall and becomes on the other side, collision won't be reported. That's why you'll need to perform sweep tests (discussed in the 9 simple intersection tests for games article on Gamasutra).
Sorry for any bugs in the design.
Hope this helps
See you