For the perspective case we have two different routes: using Mperpar*Nper or using Nper. Whichever you use you should getthe same picture on the screen. This does not mean that you will getthe same 2D calls when you enter lib2d.c
To see this, note that if you use Nper you end up calling set_window_2d(zproj,zproj,-zproj,-zproj) where -1 <= zproj < 0 is the position of the final projection screen.
As a result all your 2D lines will be in this size of window.
On the other hand, if you use Mperpar*Nper then you end up calling: set_window(-1,-1,1,1) and as a result all of your 2D lines will be in this (larger) size of window. The lines will all be longer and have different start and end points in 2D than for the other case.
However when you finally go to the screen, the integer screen coords will be the same because lib2d will shrink the -1,-1,1,1 window more than the smaller window and so the longer lines will end up shorter.
So to compare the two perspective routes, never look atthe 2D line calls being generated, but only the integer X11 coords that are finally requested.
Since my test_3d_transform allows you to choose either method, and shows the final integer coords generated, in file out2, you can actually use it to debug everything down to that level.