# 3D collision physics. Response when hitting wall, floor or roof

I am having problem with the most basic physic response when the player collide with static wall, floor or roof. I have a simple 3D maze, true means solid while false means air:

``````bool bMap[100][100][100];
``````

The player is a sphere. I have keys for moving x++, x--, y++, y-- and diagonal at speed 0.1f (0.1 * ftime). The player can also jump. And there is gravity pulling the player down. Relative movement is saved in: relx, rely and relz.

One solid cube on the map is exactly 1.0f width, height and depth. The problem I have is to adjust the player position when colliding with solids, I don't want it to bounce or anything like that, just stop. But if moving diagonal left/up and hitting solid up, the player should continue moving left, sliding along the wall.

Before moving the player I save the old player position:

``````    oxpos = xpos;
oypos = ypos;
ozpos = zpos;

vec3 direction;
direction = vec3(relx, rely, relz);

xpos += direction.x*ftime;
ypos += direction.y*ftime;
zpos += direction.z*ftime;

gx = floor(xpos+0.25);
gy = floor(ypos+0.25);
gz = floor(zpos+0.25);
if (bMap[gx][gy][gz] == true) {

vec3 normal = vec3(0.0, 0.0, 1.0); // <- Problem.
vec3 invNormal = vec3(-normal.x, -normal.y, -normal.z) * length(direction * normal);
vec3 wallDir = direction - invNormal;
xpos = oxpos + wallDir.x;
ypos = oypos + wallDir.y;
zpos = ozpos + wallDir.z;
}
``````

The problem with my version is that I do not know how to chose the correct normal for the cube side. I only have the bool array to look at, nothing else. One theory I have is to use old values of gx, gy and gz, but I do not know have to use them to calculate the correct cube side normal.

-
You might want to cut the noise out of this question and just ask your base question. I imagine you could get rid of most of the question and you'd be more likely to get a response. Also, you can calculate the normal you need by comparing the position you're colliding with to the player position before collision. – Byte56 Apr 13 '14 at 15:38
@Byte56 Thanks. I am not sure what you mean comparing positions, like: old_gx, old_gy and old_gz? That will not work since old_gz will almost always be different from gz because of gravity. When player moves in xy-plane every time moving across a cube to another I have old_gx diff from gx and old_gz diff from gz. If I calc normal from that the player will bounce diagonally backwards, not continuing moving forward in XY-plane. – GlamCasvaluir Apr 13 '14 at 16:01

Forgive me if I didn't understand your question (just comment below and I can modify my answer) but it sounds like what you need to implement is something like a "Slide along wall" if you detect that the player is going to hit a wall.

Usually I would implement this as a swept-sphere against plane test, or a capsule for plane test. I'm sure you can find source code for this in Ericson's Real-Time Collision Detection book, where the source is free to download online.

The idea is to compute the closest point on a line-segment to each plane of a cube. This line segment is the center of one sphere to the center of the swept sphere. Then you compare the computed distance from segment to plane with the radius of the sphere itself.

If a collision is detected with a plane you can move your sphere to the time of impact, and then take the leftover translation and project it onto the collision plane. This would require some sort of "slide along wall" function. The slide along wall function can use projection or the outer product to perform a projection, whichever is your preference. Given a plane with the normal `u`, you can project any vector `v` onto the plane corresponding to `u` like so:

``````(I - (u * u))v
``````

Where that * symbol is the outer product. The outer product produces a matrix. I believe the inner product form would look like:

``````v - u(u ∙ v)
``````
-

You dont need complex math for this simple thing. To get the slide collision response do this: move along x axis, if collision=true adjust x position (stop the x movement). Pick this new positon add y movement and test collision. If true adjust y position. Pick this new position and add the z movement adjust z movement in case of collision. The key to slide is move one axis at a time, adjusting positions.

Sorry my poor english...

-
that's right. but on a pure code maintenance point of view, one should apply the "ifless principle", or like the zen of python says "Special cases aren't special enough to break the rules.". Which means, if you can eliminate 6 ifs (cubic directions) and replace it with one math formula using a dot product to make a projection along the free direction, you have won a Zen award ! – v.oddou Sep 11 '14 at 6:24