home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / d / dots151.zip / GRAPHSRC.ZIP / G31.C < prev    next >
C/C++ Source or Header  |  1990-03-24  |  14KB  |  364 lines

  1. /*    
  2.     g3 - three dimensional graphics interface
  3.  
  4.     history...
  5.         24 Mar 90    Added function prototypes
  6.         13 Jul 89    Hid debugging code behind #ifdef's
  7.         4 Jul 85    Renamed to set_linestyle(), set_linewidth, etc. per
  8.     revised CORE standard.  Corrected clipping parameters for small viewports.
  9.         21 Apr 85    Removed declarations of draw_line and erase_line, since
  10.     they weren't used.
  11.         18 Apr 85    Initializing linestyle and linewidth.
  12.         9 Mar 85    hid (*erase_line)() references behind #ifdef's. changed
  13.     init() references to init_graphics(), removed inquire_current_color().
  14.  
  15.     bugs... (from Jim Knutson)
  16. Also, I noticed some interesting problems when trying to get it to
  17. compile.  First of all, the debugging print code takes up a lot of space.
  18. I couldn't get g31.c to compile because it said function too big.  I got
  19. around the problem by #ifdefing the debugging prints rather than using
  20. the C if construct.  Secondly, I noticed that there are a lot of externs
  21. in g32.c that are defined there as well as in g.h.  Not only that
  22. but g32.c has some externs that are declared twice and some that are
  23. ifdefed but are in g.h anyway (notable erase_line).
  24. */
  25.  
  26. #include <stdio.h>
  27. #include <math.h>
  28.  
  29. #define DEFAULT_MODE 0
  30.  
  31. /*        variables defined in file of hardware-dependent
  32.         routines, such as gz.c                                    */
  33.  
  34. extern int pixels_wide,pixels_high;    /* device size in pixels */
  35. extern double best_width,best_height;    /* device height/width (proportional
  36.                 to actual dimensions in inches, but one of these *must* be 1,
  37.                 and the other must be in the range 0 to 1) */
  38. extern clear_graphics();        /* clears screen */
  39. extern init_graphics();
  40. extern finish_graphics();
  41.  
  42.  
  43. /*        variables        */
  44.  
  45. int debugging=0;
  46.  
  47. int
  48. clipping=0,                /* nonzero if clipping is enabled    */
  49. front_clipping=0,        /* nonzero if front clipping is enabled */
  50. back_clipping=0,        /* nonzero if back clipping is enabled */
  51. graphics_level=1,        /* level of CORE graphics requested */
  52. initialized = 0,        /* nonzero after output driver is initialized       */
  53. mode = 0,
  54. need_depth,                /* nonzero if depth must be calculated (perspective
  55.                             projection or depth clipping */
  56. num_segments=0,            /* number of segments that still exist */
  57. persp_proj=0,            /* nonzero if perspective projection requested */
  58. segment_open=0,            /* nonzero if a segment is open    */
  59. wmin1,wmax1,            /* minimum & maximum x values in device coordinates */
  60. wmin2,wmax2;            /* minimum & maximum y values in device coordinates */
  61.  
  62. double
  63. aspect_ratio,            /* height/width ratio of display */
  64. left_handed=1.,            /* 1 for LH world coordinate system, -1 for RH */
  65. vdist=0.,                /* distance from viewpoint along view plane normal to
  66.                             viewplane    */
  67. c_bottom[4],c_top[4],    /* clip vectors...if x is visible, then            */
  68. c_left[4],c_right[4],    /* x[0]*c[0] + x[1]*c[1] + x[2]*c[2] > c[3]        */
  69. c_near[4],c_far[4],        /* for c equal to each of these six arrays        */
  70. cur_x, cur_y, cur_z,            /* current position (world coordinates) */
  71. uu, vv, nn,                        /* current position (viewport coordinates) */
  72. norm1=0., norm2=0., norm3=1.,    /* view plane normal */
  73. p1=0., p2=0., p3=1.,            /* direction for parallel projection, or
  74.                                     center of projection */
  75. up1=0., up2=1., up3=0.,            /* view up vector */
  76. vrp1=0., vrp2=0., vrp3=0.,        /* view reference point */
  77.  
  78. umin=0., umax=1.,                /* window in world coordinates */
  79. vmin=0., vmax=1.,
  80. wmin=0., wmax=1.,
  81. vp_xmin=0., vp_xmax=1.,            /* requested viewport in NDC */
  82. vp_ymin=0., vp_ymax=1.,
  83. vp_zmin=0., vp_zmax=1.,
  84. ndc_width=1., ndc_height=1., ndc_depth=1.,    /* requested limits on NDC values */
  85.  
  86. rot11, rot12, rot13, rot14,     /* rotation & projection matrix */
  87. rot21, rot22, rot23, rot24,
  88. rot31, rot32, rot33, rot34;  /* (3rd row is for perspective projections) */
  89.  
  90. /*        CORE graphics routines        */
  91.  
  92. /*    clip_window - enable clipping if i is nonzero */
  93. clip_window(i) int i; {clipping=i; reset_line();}
  94.  
  95. /*    close_temporary_segment - close the current segment */
  96. close_temporary_segment()
  97. {    segment_open=0;
  98. }
  99.  
  100. /*    coordinate_system_type - set to RH coordinates if i is nonzero */
  101. coordinate_system_type(i) int i; {left_handed=(i?-1.:1.);
  102. }
  103.  
  104. /*    create_temporary_segment - create a new segment */
  105. create_temporary_segment()
  106. {    static double
  107.     skew13, skew23,    skew33,
  108.     size, p_lnth,
  109.     vp11, vp22, vp13, vp23, vp14, vp24, vp33,
  110.     n1, n2, n3,    n4,            /* view plane unit normal */
  111.     u1, u2, u3, u4,            /* horizontal unit vector in rotated system */
  112.     v1, v2, v3, v4,            /* vertical unit vector in rotated system */
  113.     width_used,height_used,
  114.     xscale,yscale;
  115.  
  116. #ifdef DEBUG
  117.     if(debugging)
  118.         {printf("persp_proj = %d, p = (%f,%f,%f)\n",persp_proj,p1,p2,p3);
  119.         }
  120. #endif
  121.     set_linestyle(0);    /* SOLID line */
  122.     set_linewidth(1);
  123.     segment_open=1;
  124.     num_segments++;
  125.     size=sqrt(norm1*norm1 + norm2*norm2 + norm3*norm3);
  126.     if(size==0.)                            /* ensure finite vpn */
  127.         {puts("view plane normal has no length\n");
  128.         n1=0.; n2=0.; n3=1.;
  129.         }
  130.     else {n1=norm1/size; n2=norm2/size; n3=norm3/size;}
  131.     if((up1==0.)&&(up2==0.)&&(up3==0.))        /* ensure finite up vector  */
  132.         {puts("up vector has no length\n");
  133.         up1=0.; up2=1.; up3=0.;
  134.         }
  135. #ifdef DEBUG
  136.     if(debugging) printf("up = (%10f,%10f,%10f) \n",up1,up2,up3);
  137. #endif
  138.     u1=up2*n3 - up3*n2;        /* find horizontal unit vector u in */
  139.     u2=up3*n1 - up1*n3;        /* rotated system = up CROSS n */
  140.     u3=up1*n2 - up2*n1;
  141.     size=sqrt(u1*u1 + u2*u2 + u3*u3);
  142.     if(size==0.)
  143.         {puts("view plane normal and up vector are in same direction\n");
  144.         u1=1.; u2=0.; u3=0.; v1=0.; v2=1.; v3=0.;
  145.         }
  146.     else
  147.         {u1=u1/size; u2=u2/size; u3=u3/size;
  148.         v1=n2*u3 - n3*u2;    /* find vertical unit vector v in */
  149.         v2=n3*u1 - n1*u3;    /* rotated system = n CROSS u */
  150.         v3=n1*u2 - n2*u1;
  151.         size=sqrt(v1*v1 + v2*v2 + v3*v3);        /* u & n finite & normal, */
  152.         v1=v1/size; v2=v2/size; v3=v3/size;     /* so size is nonzero */
  153.         }
  154.     p_lnth=sqrt(p1*p1 + p2*p2 + p3*p3);
  155.     if(p_lnth==0.)                    /* ensure p vector has finite length */
  156.         {puts("parallel/perspective vector has no length\n");
  157.         p1=0.; p2=0.; p3=1.; p_lnth=1.;
  158.         }
  159. /*            For parallel projection, the transformation is...
  160.  
  161.     (rot11 rot12 rot13 rot14)  (x)
  162.     (rot21 rot22 rot23 rot24)  (y) =
  163.                                (z)
  164.                                (1)
  165.                                     (u1  u2  u3  0)  (1       -vrp1)  (x)
  166.                    (1  0 skew13 0)  (v1  v2  v3  0)  (   1    -vrp2)  (y)
  167.   (vp11  0  vp13)  (0  1 skew23 0)  (n1  n2  n3  0)  (      1 -vrp3)  (z)
  168.   ( 0  vp22 vp23)  (0  0   0    1)  (0   0   0   1)  (          1  )  (1)
  169. ...where the rightmost matrix shifts the input point to account for the view
  170. reference point location, the next rotates it to the u, v, n coordinates, the
  171. "skew" matrix accounts for oblique projection, and the "vp" matrix transforms
  172. to the viewport in device coordinates.
  173.  
  174. For perspective projections, the transformation is:
  175.  
  176. (r)   (a/c)     (a)     (rot11 rot12 rot13 rot14)  (x)
  177. (s) = (b/c),    (b)  =  (rot21 rot22 rot23 rot24)  (y) =
  178.                 (c)     (rot31 rot32 rot33 rot34)  (z)
  179.                                                    (1)
  180.                                                        ( 1      -vrp1)  (x)
  181. (vp11  0  vp13)  ( 1     skew13 )  ( u1  u2  u3  u4 )  (   1    -vrp2)  (y)
  182. ( 0  vp22 vp23)  (    1  skew23 )  ( v1  v2  v3  v4 )  (      1 -vrp3)  (z)
  183. ( 0    0    1 )  (       skew33 )  ( n1  n2  n3  n4 )  (          1  )  (1)
  184.  
  185. c is the depth coordinate, scaled so that 0 is the same depth as the center of
  186. perspective, and 1 is the depth of the viewplane.
  187. */
  188.     u4=-(u1*p1 + u2*p2 + u3*p3);
  189.     v4=-(v1*p1 + v2*p2 + v3*p3);
  190.     skew13=u4;
  191.     skew23=v4;
  192.     aspect_ratio=best_height/best_width;
  193.     if((0.>=ndc_width)|(0.>=ndc_height))
  194.         {puts("invalid ndc coordinate limits");
  195.         ndc_width=ndc_height=1.;
  196.         }
  197.     if((-.001>vp_xmin)||(vp_xmin>=vp_xmax)||(vp_xmax>ndc_width+.001)||
  198.     (-.001>vp_ymin)||(vp_ymin>=vp_ymax)||(vp_ymax>ndc_height+.001))
  199.         {puts("invalid viewport");
  200.         printf("\n need 0 <= %f=vp_xmin < %f=vp_xmax <= %f=ndc_width",
  201.             vp_xmin, vp_xmax, ndc_width);
  202.         printf("\n  and 0 <= %f=vp_ymin < %f=vp_ymax <= %f=ndc_height",
  203.             vp_ymin, vp_ymax, ndc_height);
  204.         vp_xmin=0.; vp_xmax=ndc_width;
  205.         vp_ymin=0.; vp_ymax=ndc_height;
  206.         }
  207.     if(ndc_height/ndc_width>aspect_ratio)  /* user isn't using all the width */
  208.         {height_used=(double)pixels_high-1;
  209.         width_used=(double)(pixels_wide-1)
  210.             *aspect_ratio*ndc_width/ndc_height;
  211.         }
  212.     else                                /* user isn't using all the height */
  213.         {height_used=(double)(pixels_high-1)
  214.             /aspect_ratio/(ndc_width/ndc_height);
  215.         width_used=(double)pixels_wide-1;
  216.         }
  217.     xscale=width_used/ndc_width;
  218.     yscale=height_used/ndc_height;
  219.     wmin1=(int)(xscale*vp_xmin);
  220.     wmax1=(int)(xscale*vp_xmax);
  221.     wmin2=(int)(yscale*(ndc_height-vp_ymax));
  222.     wmax2=(int)(yscale*(ndc_height-vp_ymin));
  223.     vp11= xscale*(vp_xmax-vp_xmin)/(umax-umin); 
  224.     vp22=-yscale*(vp_ymax-vp_ymin)/(vmax-vmin);
  225.     vp14=vp13= xscale*(umax*vp_xmin-umin*vp_xmax)/(umax-umin);
  226.     vp24=vp23=-yscale*(vmax*vp_ymin-vmin*vp_ymax)/(vmax-vmin) + height_used;
  227. #ifdef DEBUG
  228.     if(debugging)
  229.         {printf("vp = %10f              %10f \n",vp11,vp13);
  230.         printf( "                 %10f  %10f \n",vp22,vp23);
  231.         printf( "                                   1    \n");
  232.         }
  233. #endif
  234.     if(persp_proj)                         /* perspective projection */
  235.         {n4=-(n1*p1 + n2*p2 + n3*p3);
  236.         if(fabs(n4)<.001*p_lnth)
  237.             {puts("can\'t project view reference point onto view plane \n");
  238.             n4=1.;
  239.             }
  240.         skew13=-skew13/n4;
  241.         skew23=-skew23/n4;
  242.         if(fabs(n4+vdist)<1.e-10)
  243.             {puts("center of projection is in view plane \n");
  244.             vdist=0.;
  245.             }
  246.         vp33=skew33=1./(n4+vdist);
  247.         vp13=vp11*skew13 + vp13*skew33;
  248.         vp23=vp22*skew23 + vp23*skew33;
  249.                         /* vp is now the product of the 1st 2 matrices */
  250.         rot11= vp11*u1 + vp13*n1;
  251.         rot12= vp11*u2 + vp13*n2;
  252.         rot13=(vp11*u3 + vp13*n3) *left_handed;
  253.         rot14= vp11*u4 + vp13*n4;
  254.         rot21= vp22*v1 + vp23*n1;
  255.         rot22= vp22*v2 + vp23*n2;
  256.         rot23=(vp22*v3 + vp23*n3) *left_handed;
  257.         rot24= vp22*v4 + vp23*n4;
  258.         rot31= vp33*n1;
  259.         rot32= vp33*n2;
  260.         rot33= vp33*n3            *left_handed;
  261.         rot34= vp33*n4;
  262.         rot14= rot14 - (rot11*vrp1 + rot12*vrp2 + rot13*vrp3);
  263.         rot24= rot24 - (rot21*vrp1 + rot22*vrp2 + rot23*vrp3);
  264.         rot34= rot34 - (rot31*vrp1 + rot32*vrp2 + rot33*vrp3);
  265.         c_bottom[0]=0.;                /* (umin,vmin,1) CROSS (umax,vmin,1) */
  266.         c_bottom[1]=umin-umax;
  267.         c_bottom[2]=vmin*(umin-umax);
  268.         c_bottom[3]=0.;
  269.         c_top[0]=0.;                /* (umax,vmax,1) CROSS (umin,vmax,1) */
  270.         c_top[1]=umin-umax;
  271.         c_top[2]=vmax*(umax-umin);
  272.         c_top[3]=0.;
  273.         c_left[0]=vmax-vmin;        /* (umin,vmax,1) CROSS (umin,vmin,1) */
  274.         c_left[1]=0.;
  275.         c_left[2]=umin*(vmin-vmax);
  276.         c_left[3]=0.;
  277.         c_right[0]=vmin-vmax;        /* (umax,vmin,1) CROSS (umax,vmax,1) */
  278.         c_right[1]=0.;
  279.         c_right[2]=umax*(vmax-vmin);
  280.         c_right[3]=0.;
  281.         }
  282.     else                                 /* parallel projection */
  283.         {
  284.     /*
  285.         vp13=vp11*skew13;
  286.         vp23=vp22*skew23;
  287.         rot11= vp11*u1 + vp13*n1;
  288.         rot21= vp22*v1 + vp23*n1;
  289.         rot12= vp11*u2 + vp13*n2;
  290.         rot22= vp22*v2 + vp23*n2;
  291.         rot13=(vp11*u3 + vp13*n3) *left_handed;
  292.         rot23=(vp22*v3 + vp23*n3) *left_handed;
  293.         rot14=-(rot11*vrp1 + rot12*vrp2 + rot13*vrp3) + vp14;
  294.         rot24=-(rot21*vrp1 + rot22*vrp2 + rot23*vrp3) + vp24;
  295.     */
  296.         rot11=(u1 + skew13*n1)*vp11;
  297.         rot21=(v1 + skew23*n1)*vp22;
  298.         rot12=(u2 + skew13*n2)*vp11;
  299.         rot22=(v2 + skew23*n2)*vp22;
  300.         rot13=(u3 + skew13*n3)*vp11 *left_handed;
  301.         rot23=(v3 + skew23*n3)*vp22 *left_handed;
  302.         rot14=-(rot11*vrp1 + rot12*vrp2 + rot13*vrp3) + vp13;
  303.         rot24=-(rot21*vrp1 + rot22*vrp2 + rot23*vrp3) + vp23;
  304.         }
  305.     c_near[0]=c_near[1]=0.; c_near[2]=1.; c_near[3]=wmin;
  306.     c_far[0]=c_far[1]=0.; c_far[2]=-1.; c_far[3]=-wmax;
  307. #ifdef DEBUG
  308.     if(debugging)
  309.         {printf("skew = 1       %10f \n",skew13);
  310.         printf("          1    %10f \n",skew23);
  311.         printf("               %10f \n",skew33);
  312.         printf("u,v,n=  %10f  %10f  %10f  %10f \n",u1,u2,u3,u4);
  313.         printf("        %10f  %10f  %10f  %10f \n",v1,v2,v3,v4);
  314.         printf("        %10f  %10f  %10f  %10f \n",n1,n2,n3,n4);
  315.         printf("vrp = 1          %10f \n",-vrp1);
  316.         printf("          1      %10f \n",-vrp2);
  317.         printf("              1  %10f \n",-vrp3);
  318.         printf("                  1  \n");
  319.         printf("rot= %10f  %10f  %10f  %10f \n",rot11,rot12,rot13,rot14);
  320.         printf("     %10f  %10f  %10f  %10f \n",rot21,rot22,rot23,rot24);
  321.         printf("     %10f  %10f  %10f  %10f \n",rot31,rot32,rot33,rot34);
  322.         printf("width_used= %5.1f  height_used= %5.1f \n",
  323.             width_used, height_used);
  324.         printf("xscale= %5f  yscale= %5f \n",xscale, yscale);
  325.         getchar();
  326.         show_clipping();
  327.         }
  328. #endif
  329.     move_abs_3(0.,0.,0.);
  330. }
  331.  
  332. #ifdef DEBUG
  333. show_clipping()
  334. {    printf("umin = %f       vmin = %f        wmin = %f \n",umin,vmin,wmin);
  335.     printf("umax = %f       vmax = %f        wmax = %f \n",umax,vmax,wmax);
  336.     printf("vp_xmin = %f    vp_ymin = %f     vp_zmin = %f \n",vp_xmin,vp_ymin,vp_zmin);
  337.     printf("vp_xmax = %f    vp_ymax = %f     vp_zmax = %f \n",vp_xmax,vp_ymax,vp_zmax);
  338.     printf("ndc_width = %f  ndc_height = %f  ndc_depth = %f \n",ndc_width,ndc_height,ndc_depth);
  339.     printf("wmin1 = %d   wmin2 = %d \n",wmin1,wmin2);
  340.     printf("wmax1 = %d   wmax2 = %d \n",wmax1,wmax2);
  341.     printf("c_left   = (%10f,%10f,%10f,%10f) \n",c_left[0],c_left[1],c_left[2],c_left[3]);
  342.     printf("c_right  = (%10f,%10f,%10f,%10f) \n",c_right[0],c_right[1],c_right[2],c_right[3]);
  343.     printf("c_bottom = (%10f,%10f,%10f,%10f) \n",c_bottom[0],c_bottom[1],c_bottom[2],c_bottom[3]);
  344.     printf("c_top    = (%10f,%10f,%10f,%10f) \n",c_top[0],c_top[1],c_top[2],c_top[3]);
  345.     printf("c_near   = (%10f,%10f,%10f,%10f) \n",c_near[0],c_near[1],c_near[2],c_near[3]);
  346.     printf("c_far    = (%10f,%10f,%10f,%10f) \n",c_far[0],c_far[1],c_far[2],c_far[3]);
  347.     getchar();
  348. }
  349. #endif
  350.  
  351. /*    initialize_core - initialize everything */
  352. initialize_core(out,in,dimension)
  353. int out,    /* 0=basic  1=buffered  2=dynamic a  3=dynamic b  4=dynamic c */
  354. in,            /* 0=none  1=synchronous  2=complete */
  355. dimension;    /* 2=2D  3=3D */
  356. {    if(out>1 || in>1)
  357.         {puts("WARNING: no retained segments or input primitives supported\n");
  358.         getchar();
  359.         }
  360.     if(!initialized) init_graphics(DEFAULT_MODE);
  361.     initialized=1;
  362. }
  363.  
  364.