Prevent camera from moving through walls (no engine or framework)

I'm building a fairly basic 3D first-person puzzle game. The only objects for which collisions matter are walls, and all walls are at convenient 90 degree angles aligned with the coordinate axes.

Unfortunately, I cannot consistently prevent the camera from moving through walls. There is no off-the-shelf game engine or framework involved, so I have to implement all this from scratch.

Currently, my algorithm (in GLSL-ish psuedo code) looks something like this:

void update_position(seconds){
vec3 ray = Raycast(position, speed, map.grid);
float xmax = max(ray.x-.01,0);
float ymax = max(ray.y-.01,0);
float zmax = max(ray.z-.01,0);

float dx = speed.x * seconds;
float dy = speed.y * seconds;
float dz = speed.z * seconds;

if(abs(dx) > xmax){
dx = (dx > 0 ? xmax : -xmax);
speed.x = 0;
}
if(abs(dy) > ymax){
dy = (dy > 0 ? ymax : -ymax);
speed.y = 0;
}
if(abs(dz) > zmax){
dz = (dz > 0 ? zmax : -zmax);
speed.z = 0;
}

position.x += dx;
position.y += dy;
position.z += dz;
}


In prose: I cast a ray from the player's/camera's current position along the speed vector, which extends until it hits wall. (The Raycast function is used elsewhere, so I already know it works correctly.) I then define the maximum distance the player is permitted to move in each dimension to be slightly less than the component of the ray in that dimension (so that we never end up exactly on a wall). I then compute a provisional set of deltas to add to the current position based on the speed and the time since the last frame (in fractional seconds), and check to see if any of them exceed the maximum allowed magnitude which would take the player through the wall. If they do, I clamp the magnitude of the offending component to its max value, and set the component of speed in that direction to 0; so, the player should end up just barely outside the wall, and sliding along it.

This usually works pretty well if you happen to run straight into a wall, but it fails frequently but unpredictably (as in, sometimes it doesn't fail) near corners, and especially near three-way corners (where two walls and a ceiling or floor come together).

So, what is wrong with this algorithm, and how do I fix it?

• Use standard collision detection treating your camera as a small sphere Dec 20, 2016 at 4:11
• Can you be more specific than "standard collision detection"? I don't have an engine here that I can tell "my camera is a small sphere, please handle collisions". Is there a standard reference for this I should know about that will tel me how to roll it from scratch? Dec 20, 2016 at 4:48
• For my turn based strategy game I let the players move around with a first person 3D camera. I don't try to prevent them from going through walls, and think of it more like an omnipotence feature. What I'm trying to say is, ensure your game actually needs a camera like what you're intending. If anything I will just be clamping the depth Y value to prevent them from going under the level. Dec 21, 2016 at 16:46

bool intersecting_or_behind_plane = (dot(position, plane_normal) - plane_d) <= sphere_radius