Find plane (walls, floor, ceiling) that a falling car will land on
Don't hardcode values
There are lots of magic values that you are using in your code, from the terminal velocity, the wall coordinates to the numbering of the walls. Try to give everything a name: declare constants for the coordinates and terminal velocity, and create an enum for the six faces of the enclosing box:
enum Face {
    FACE_RIGHT,
    FACE_LEFT,
    FACE_BACK,
    FACE_FRONT,
    FACE_TOP,
    FACE_BOTTOM,
};

static const double terminal_velocity = 2300;
static const double right_wall_position = 4080;
...

It's a little bit more typing, but there are several benefits. In particular, it makes the code more self-documenting. Consider the return type of find_landing_plane():
enum Face find_landing_plane(...) {
    ...
    if (l.x &gt; right_wall_position)
        return FACE_RIGHT;
    ...
}

You also don't need to add a comment to this line anymore:
if (magnitude(v) &lt; terminal_velocity)

Consider using arrays to avoid repetition
You could get rid of the repeated if-statements by treating the vector as an array, and also having an array to encode the positions of the planes. It would look like this:
static const double plane_positions[6] = {4080, -4080, 5110, -5110, 2030, 20};
...
enum Face find_landing_plane(Vector car_location, Vector *car_velocity, double *gravity)
{
    ...
    while (1)
    {
        // update l
        ...
        
        double *l_vec = &amp;l.x;

        for (int i = 0; i &lt; 6; i++) {
            if (i % 2 == 0 ? l_vec[i / 2] &gt;= plane_positions[i] : l_vec[i / 2] &lt;= plane_positions[i])
                return i;
        }
    }
}   

However, I'm not sure it is all that better, as it uses a complex expression and no longer uses the enum values by name, making it harder to understand and easier to make mistakes.
Solve the problem analytically
Finding the plane the car hits by updating the position in a loop is inefficient. The problem can be solved analytically. The trajectory the car follows is a parabola up to the point the terminal velocity is reached. You can solve for time the parabola intersects each of the the six planes, and also solve for the time the terminal velocity is reached. If the earliest time found that is not in the past is a plane, you know that plane was hit first. If the earliest time is when the terminal velocity is reached, you then now that the rest of the trajectory is a straight line, so you can then do the even easier step of solving for the intersection of a straight line with six planes.
This is more code to write, although here you could also make an array with the parameters describing each of the six planes, and use a for-loop to check for the intersection with each of them. The advantage is that it should be much more efficient and much more precise (consider that you have a bias in your algorithm when the car hits very close to a corner).
Add a better description of the special exception
Why is fabs(l.y) &gt; 5120 special? You commented that it is an exception, but that still doesn't tell me why. Why is it 5120 (consider making a constant for that as well), and why do you need to handle this case at all, when it looks like the rest of the code would handle that fine?