I ran your test_3d_transform last night and compared the results. The pictures that I am getting are not the same as yours. I looked at your out3 and out2 files. Everything that I am doing in my lib3d is correct i.e all my transformation matrices and transformed points that I send to lib2d are exactly the same as yours. But in lib2d, when I convert the points into device coordinates, I am not getting the same results as you are. I noticed that there is a tranformation matrix in out2 file. What is that matrix? If I multiply the points in lib2d with that matrix, I get the same results. Can you please explain how you get that matrix? I am probably missing an important point here.
Good question. The out2 file is created entirely by my lib2d.c. All I do is create a 3x3 transformation N (for 2D graphics) that takes 2D world coords x,y into 2D screen coords s,t. You may well do this differently in your lib2d - for example you may take world to NDC and then NDC to screen, and you probably do not use 2D homogeneous coords or compute a transformation matrix N. As a result the initial part of file out2 may be confusing. I will explain it below, but only after I explain how to use out2 effectively.
In out2 you will see at the top the requested 2D window and viewport and the screen size which is (0,511) to (511,0) ie bottom left of screen is at s=0 t=511 and top right is at s=511,t=0.
What you will see in out2 is: ####### Entered init_graphics() Calling _init_graphics Calling _enquire_device Screen coordinates bounded by: 0 511 511 0 Returning from init_graphics
set_window(-0.568375,-0.568375,0.568375,0.568375) ####### The call to set_viewport(0) is somewhere further down (and causes a recomputation of the transform). The screen size is obtained from libx.c using an enquire_device() call. The window, viewport and screen size determines the needed transformation. You can then skip directly to the first drawing item in the file which will look like:
###### line(0.0233574,0.091422, -0.116729,0.0160765) x1=0.0233574 y1=0.091422 x2=-0.116729 y2=0.0160765 ixs=265 iys=214 ixe=203 iye=248 ######
Here ixs, iye are the integer screen coords that I transform the start of the line x1,y1 into and similarly for the end of the line, ixe, iye.
As long as you have the same window, viewport and screen size as I do then however your code works, you should still get the same integer endpoints that I do - apart from small roundoff effects due to truncating integers (which could produce a difference of at most 1 in the end points calculated).
So if you want to use my out2 file for debugging (only do so after you have full agreement of out3) you should skip over all the transformation stuff in the file.
If you really want to debug my 2D transformation code too, then here is what it does:
Suppose the requested 2D window is xmin,ymin, to xmax,ymax, the 2D viewport is from umin,vmin to umax,vmax and the screen runs from smin,tmin to smax,tmax (which in my case is (0,511) to (511,0) since the t coordinate in X11 runs down from the top. Then the area of the screen that our window will map to will be: Smin,Tmin to Smax,Tmax where: Smin = smin + umin*(smax-smin), Tmin = tmin + vmin*(tmax-tmin) Smax = smin + umax*(smax-smin), Tmax = tmin + vax*(tmax-tmin)
So I create a transformation N in 2D homogeneous coords, that takes xmin,tmin into Smin,Tmin and takes xmax,tmax into Smax,Tmax. I do this as follows.
The transformation matrix N is made from three pieces: Tw, S and Tv which get printed out. Tw translates the bottom left corner of the window to the origin: i.e. xmin,ymin => 0,0. S scales the window about the origin to make it of size Smax-Smin and Tmax-Tmin in the two directions, so the scaling is by sx = (Smax-Smin)/(xmax-xmin) and sy = (Tmax-Tmin)/(ymax-ymin). Tv translates the resulting screen window to its correct location, so that it translates (0,0) to (Smin,Tmin). Each of those 3x3 matrices Tw, S, Tv are printed so you can check them, as is the final product which is N = Tv*S*Tw.
When the user calls line(x1,y1,x2,y2) I create P = (x1,y1,1), compute Q = N*P, and define ixs = Q/Q +.00001, iys = Q/Q + .00001 (here ixs, iys are integers and I add .00001 to ensure that if they rounded down slightly that I get them back up to an integer). Then I call the libx routine to draw a line with ixs and iys as start. Note that the division by Q is overkill as it will always be 1.0, but who cares.
So here is what out2 reports for the transformation computation:
set=3 ALL_SET=3 is_set=1 Can now proceed to compute Transformations Current 2D N matrix: 1.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 1.000000
Current 2D Tw matrix: 1.000000 0.000000 0.568375 0.000000 1.000000 0.568375 0.000000 0.000000 1.000000
Current 2D N matrix: 1.000000 0.000000 0.568375 0.000000 1.000000 0.568375 0.000000 0.000000 1.000000
Current 2D S matrix: 449.527242 0.000000 0.000000 0.000000 -449.527242 0.000000 0.000000 0.000000 1.000000
Current 2D N matrix: 449.527242 0.000000 255.500000 0.000000 -449.527242 -255.500000 0.000000 0.000000 1.000000
Current 2D Tv matrix: 1.000000 0.000000 0.000000 0.000000 1.000000 511.000000 0.000000 0.000000 1.000000
Current 2D N matrix: 449.527242 0.000000 255.500000 0.000000 -449.527242 255.500000 0.000000 0.000000 1.000000