To understand this issue, we have to consider what it means for OpenGL that something "is not visible":

After the vertices of the primitives that you draw got transformed via the modelview and projection matrices, they are within or without an area called the "clipping area" or "clipping box".

If all vertices of the primitive are within that box, they will be drawn, otherwise they will be "clipped" (that is, either not drawn at all or partially drawn).

Now, how does OpenGL decide whether a vertex is within or without that box? Well, that's a basic test of whether the co-ordinates of that transformed vertex are within ([-1, 1], [-1, 1], [-1, 1]). So, the clipping box is always centered at (0, 0, 0) and has a extend of 1 in each direction.

So, let's replay what happens when you setup the OpenGL matrices as you did and how the vertices will be transformed by each step:

0. Original:

(-0.5, -0.5, 0.5)

(-0.5, 0.5, 0.5)

(0.5, 0.5, 0.5)

(0.5, -0.5, 0.5)

1. modelview:

You are basically flipping the z-value so the modelview-transformed vertices will be

(-0.5, -0.5, -0.5)

(-0.5, 0.5, -0.5)

(0.5, 0.5, -0.5)

(0.5, -0.5, -0.5)

2. projection:

This is where the modelview-transformed vertices will be fitted into the "clipping box".

Everything in that clipping box then represents the viewing frustum of the camera and hence will be visible in the final scene.

Since per default this is the identity transformation, we still have:

(-0.5, -0.5, -0.5)

(-0.5, 0.5, -0.5)

(0.5, 0.5, -0.5)

(0.5, -0.5, -0.5)

3. clipping box test

Question: Are all vertices within ([-1, 1], [-1, 1], [-1, 1])? -> Yes!

So all vertices will be drawn!

Easy solution to that:

Specify the camera's viewing frustum via glOrtho or gluPerspective. What these methods do is to shift and stretch the clipping box so that only vertices with a z-value bigger as the min-z clipping plane will be drawn.