First of all, well done for actually trying the math. It's very easy to use a ready made 3D system and it saves a lot of time, but you don't learn anything that way. People who do that inevitably reach a point where they want to do something that exceeds the system they've been using, and then they don't know how to progress.

In this case everything looks OK at first glance. The first thing that might be wrong is matrix order. You do world*view*projection to calculate positions, that depends on whether the matrices are pre or post multiplied, which also depends on them being or row or column order correctly. If either of these factors is wrong you will get the wrong result. In this case, it appears to have applied the perspective scaling from right to left, which makes me suspect the matrix order.

Ufnortunately I don't know how the python matrix classes work so I can't be more precise than that. OpenGL and DirectX use different matrix order and that often confuses people. The majority of other systems seems to use the OpenGL order rather than the DirectX order.

http://en.wikipedia.org/wiki/Row-major_order

In this case everything looks OK at first glance. The first thing that might be wrong is matrix order. You do world*view*projection to calculate positions, that depends on whether the matrices are pre or post multiplied, which also depends on them being or row or column order correctly. If either of these factors is wrong you will get the wrong result. In this case, it appears to have applied the perspective scaling from right to left, which makes me suspect the matrix order.

Ufnortunately I don't know how the python matrix classes work so I can't be more precise than that. OpenGL and DirectX use different matrix order and that often confuses people. The majority of other systems seems to use the OpenGL order rather than the DirectX order.

http://en.wikipedia.org/wi