home *** CD-ROM | disk | FTP | other *** search
- /* g3 - three dimensional graphics interface
-
- history...
- 4 Jul 85 Renamed to set_linestyle(), set_linewidth, etc. per
- revised CORE standard. Corrected clipping parameters for small viewports.
- 21 Apr 85 Removed declarations of draw_line and erase_line, since
- they weren't used.
- 18 Apr 85 Initializing linestyle and linewidth.
- 9 Mar 85 hid (*erase_line)() references behind #ifdef's. changed
- init() references to init_graphics(), removed inquire_current_color().
-
- bugs...
- */
-
- #include "math.h"
-
- /* variables defined in file of hardware-dependent
- routines, such as gz.c */
-
- extern int pixels_wide,pixels_high; /* device size in pixels */
- extern double best_width,best_height; /* device height/width (proportional
- to actual dimensions in inches, but one of these *must* be 1,
- and the other must be in the range 0 to 1) */
- extern clear_graphics(); /* clears screen */
- extern init_graphics();
- extern finish_graphics();
-
-
- /* variables */
-
- int debugging=0;
-
- int
- clipping=0, /* nonzero if clipping is enabled */
- front_clipping=0, /* nonzero if front clipping is enabled */
- back_clipping=0, /* nonzero if back clipping is enabled */
- graphics_level=1, /* level of CORE graphics requested */
- need_depth, /* nonzero if depth must be calculated (perspective
- projection or depth clipping */
- num_segments=0, /* number of segments that still exist */
- persp_proj=0, /* nonzero if perspective projection requested */
- segment_open=0, /* nonzero if a segment is open */
- wmin1,wmax1, /* minimum & maximum x values in device coordinates */
- wmin2,wmax2; /* minimum & maximum y values in device coordinates */
-
- double
- aspect_ratio, /* height/width ratio of display */
- left_handed=1., /* 1 for LH world coordinate system, -1 for RH */
- vdist=0., /* distance from viewpoint along view plane normal to
- viewplane */
- c_bottom[4],c_top[4], /* clip vectors...if x is visible, then */
- c_left[4],c_right[4], /* x[0]*c[0] + x[1]*c[1] + x[2]*c[2] > c[3] */
- c_near[4],c_far[4], /* for c equal to each of these six arrays */
- cur_x, cur_y, cur_z, /* current position (world coordinates) */
- uu, vv, nn, /* current position (viewport coordinates) */
- norm1=0., norm2=0., norm3=1., /* view plane normal */
- p1=0., p2=0., p3=1., /* direction for parallel projection, or
- center of projection */
- up1=0., up2=1., up3=0., /* view up vector */
- vrp1=0., vrp2=0., vrp3=0., /* view reference point */
-
- umin=0., umax=1., /* window in world coordinates */
- vmin=0., vmax=1.,
- wmin=0., wmax=1.,
- vp_xmin=0., vp_xmax=1., /* requested viewport in NDC */
- vp_ymin=0., vp_ymax=1.,
- vp_zmin=0., vp_zmax=1.,
- ndc_width=1., ndc_height=1., ndc_depth=1., /* requested limits on NDC values */
-
- rot11, rot12, rot13, rot14, /* rotation & projection matrix */
- rot21, rot22, rot23, rot24,
- rot31, rot32, rot33, rot34; /* (3rd row is for perspective projections) */
-
- /* CORE graphics routines */
-
- /* clip_window - enable clipping if i is nonzero */
- clip_window(i) int i; {clipping=i; reset_line();}
-
- /* close_temporary_segment - close the current segment */
- close_temporary_segment()
- { segment_open=0;
- }
-
- /* coordinate_system_type - set to RH coordinates if i is nonzero */
- coordinate_system_type(i) int i; {left_handed=(i?-1.:1.);
- }
-
- /* create_temporary_segment - create a new segment */
- create_temporary_segment()
- { static double
- skew13, skew23, skew33,
- size, p_lnth,
- vp11, vp22, vp13, vp23, vp14, vp24, vp33,
- n1, n2, n3, n4, /* view plane unit normal */
- u1, u2, u3, u4, /* horizontal unit vector in rotated system */
- v1, v2, v3, v4, /* vertical unit vector in rotated system */
- width_used,height_used,
- xscale,yscale;
-
- if(debugging)
- {printf("persp_proj = %d, p = (%f,%f,%f)\n",persp_proj,p1,p2,p3);
- }
- set_linestyle(0); /* SOLID line */
- set_linewidth(1);
- segment_open=1;
- num_segments++;
- size=sqrt(norm1*norm1 + norm2*norm2 + norm3*norm3);
- if(size==0.) /* ensure finite vpn */
- {puts("view plane normal has no length\n");
- n1=0.; n2=0.; n3=1.;
- }
- else {n1=norm1/size; n2=norm2/size; n3=norm3/size;}
- if((up1==0.)&&(up2==0.)&&(up3==0.)) /* ensure finite up vector */
- {puts("up vector has no length\n");
- up1=0.; up2=1.; up3=0.;
- }
- if(debugging) printf("up = (%10f,%10f,%10f) \n",up1,up2,up3);
- u1=up2*n3 - up3*n2; /* find horizontal unit vector u in */
- u2=up3*n1 - up1*n3; /* rotated system = up CROSS n */
- u3=up1*n2 - up2*n1;
- size=sqrt(u1*u1 + u2*u2 + u3*u3);
- if(size==0.)
- {puts("view plane normal and up vector are in same direction\n");
- u1=1.; u2=0.; u3=0.; v1=0.; v2=1.; v3=0.;
- }
- else
- {u1=u1/size; u2=u2/size; u3=u3/size;
- v1=n2*u3 - n3*u2; /* find vertical unit vector v in */
- v2=n3*u1 - n1*u3; /* rotated system = n CROSS u */
- v3=n1*u2 - n2*u1;
- size=sqrt(v1*v1 + v2*v2 + v3*v3); /* u & n finite & normal, */
- v1=v1/size; v2=v2/size; v3=v3/size; /* so size is nonzero */
- }
- p_lnth=sqrt(p1*p1 + p2*p2 + p3*p3);
- if(p_lnth==0.) /* ensure p vector has finite length */
- {puts("parallel/perspective vector has no length\n");
- p1=0.; p2=0.; p3=1.; p_lnth=1.;
- }
- /* For parallel projection, the transformation is...
-
- (rot11 rot12 rot13 rot14) (x)
- (rot21 rot22 rot23 rot24) (y) =
- (z)
- (1)
- (u1 u2 u3 0) (1 -vrp1) (x)
- (1 0 skew13 0) (v1 v2 v3 0) ( 1 -vrp2) (y)
- (vp11 0 vp13) (0 1 skew23 0) (n1 n2 n3 0) ( 1 -vrp3) (z)
- ( 0 vp22 vp23) (0 0 0 1) (0 0 0 1) ( 1 ) (1)
- ...where the rightmost matrix shifts the input point to account for the view
- reference point location, the next rotates it to the u, v, n coordinates, the
- "skew" matrix accounts for oblique projection, and the "vp" matrix transforms
- to the viewport in device coordinates.
-
- For perspective projections, the transformation is:
-
- (r) (a/c) (a) (rot11 rot12 rot13 rot14) (x)
- (s) = (b/c), (b) = (rot21 rot22 rot23 rot24) (y) =
- (c) (rot31 rot32 rot33 rot34) (z)
- (1)
- ( 1 -vrp1) (x)
- (vp11 0 vp13) ( 1 skew13 ) ( u1 u2 u3 u4 ) ( 1 -vrp2) (y)
- ( 0 vp22 vp23) ( 1 skew23 ) ( v1 v2 v3 v4 ) ( 1 -vrp3) (z)
- ( 0 0 1 ) ( skew33 ) ( n1 n2 n3 n4 ) ( 1 ) (1)
-
- c is the depth coordinate, scaled so that 0 is the same depth as the center of
- perspective, and 1 is the depth of the viewplane.
- */
- u4=-(u1*p1 + u2*p2 + u3*p3);
- v4=-(v1*p1 + v2*p2 + v3*p3);
- skew13=u4;
- skew23=v4;
- aspect_ratio=best_height/best_width;
- if((0.>=ndc_width)|(0.>=ndc_height))
- {puts("invalid ndc coordinate limits");
- ndc_width=ndc_height=1.;
- }
- if((0.>vp_xmin)|(vp_xmin>vp_xmax)|(vp_xmax>ndc_width)|
- (0.>vp_ymin)|(vp_ymin>vp_ymax)|(vp_ymax>ndc_height))
- {puts("invalid viewport");
- vp_xmin=0.; vp_xmax=ndc_width;
- vp_ymin=0.; vp_ymax=ndc_height;
- }
- if(ndc_height/ndc_width>aspect_ratio) /* user isn't using all the width */
- {height_used=(double)pixels_high-1;
- width_used=(double)(pixels_wide-1)
- *aspect_ratio*ndc_width/ndc_height;
- }
- else /* user isn't using all the height */
- {height_used=(double)(pixels_high-1)
- /aspect_ratio/(ndc_width/ndc_height);
- width_used=(double)pixels_wide-1;
- }
- xscale=width_used/ndc_width;
- yscale=height_used/ndc_height;
- wmin1=(int)(xscale*vp_xmin);
- wmax1=(int)(xscale*vp_xmax);
- wmin2=(int)(yscale*(ndc_height-vp_ymax));
- wmax2=(int)(yscale*(ndc_height-vp_ymin));
- vp11= xscale*(vp_xmax-vp_xmin)/(umax-umin);
- vp22=-yscale*(vp_ymax-vp_ymin)/(vmax-vmin);
- vp14=vp13= xscale*(umax*vp_xmin-umin*vp_xmax)/(umax-umin);
- vp24=vp23=-yscale*(vmax*vp_ymin-vmin*vp_ymax)/(vmax-vmin) + height_used;
- if(debugging)
- {printf("vp = %10f %10f \n",vp11,vp13);
- printf( " %10f %10f \n",vp22,vp23);
- printf( " 1 \n");
- }
- if(persp_proj) /* perspective projection */
- {n4=-(n1*p1 + n2*p2 + n3*p3);
- if(fabs(n4)<.001*p_lnth)
- {puts("can\'t project view reference point onto view plane \n");
- n4=1.;
- }
- skew13=-skew13/n4;
- skew23=-skew23/n4;
- if(fabs(n4+vdist)<1.e-10)
- {puts("center of projection is in view plane \n");
- vdist=0.;
- }
- vp33=skew33=1./(n4+vdist);
- vp13=vp11*skew13 + vp13*skew33;
- vp23=vp22*skew23 + vp23*skew33;
- /* vp is now the product of the 1st 2 matrices */
- rot11= vp11*u1 + vp13*n1;
- rot12= vp11*u2 + vp13*n2;
- rot13=(vp11*u3 + vp13*n3) *left_handed;
- rot14= vp11*u4 + vp13*n4;
- rot21= vp22*v1 + vp23*n1;
- rot22= vp22*v2 + vp23*n2;
- rot23=(vp22*v3 + vp23*n3) *left_handed;
- rot24= vp22*v4 + vp23*n4;
- rot31= vp33*n1;
- rot32= vp33*n2;
- rot33= vp33*n3 *left_handed;
- rot34= vp33*n4;
- rot14= rot14 - (rot11*vrp1 + rot12*vrp2 + rot13*vrp3);
- rot24= rot24 - (rot21*vrp1 + rot22*vrp2 + rot23*vrp3);
- rot34= rot34 - (rot31*vrp1 + rot32*vrp2 + rot33*vrp3);
- c_bottom[0]=0.; /* (umin,vmin,1) CROSS (umax,vmin,1) */
- c_bottom[1]=umin-umax;
- c_bottom[2]=vmin*(umin-umax);
- c_bottom[3]=0.;
- c_top[0]=0.; /* (umax,vmax,1) CROSS (umin,vmax,1) */
- c_top[1]=umin-umax;
- c_top[2]=vmax*(umax-umin);
- c_top[3]=0.;
- c_left[0]=vmax-vmin; /* (umin,vmax,1) CROSS (umin,vmin,1) */
- c_left[1]=0.;
- c_left[2]=umin*(vmin-vmax);
- c_left[3]=0.;
- c_right[0]=vmin-vmax; /* (umax,vmin,1) CROSS (umax,vmax,1) */
- c_right[1]=0.;
- c_right[2]=umax*(vmax-vmin);
- c_right[3]=0.;
- }
- else /* parallel projection */
- {
- /*
- vp13=vp11*skew13;
- vp23=vp22*skew23;
- rot11= vp11*u1 + vp13*n1;
- rot21= vp22*v1 + vp23*n1;
- rot12= vp11*u2 + vp13*n2;
- rot22= vp22*v2 + vp23*n2;
- rot13=(vp11*u3 + vp13*n3) *left_handed;
- rot23=(vp22*v3 + vp23*n3) *left_handed;
- rot14=-(rot11*vrp1 + rot12*vrp2 + rot13*vrp3) + vp14;
- rot24=-(rot21*vrp1 + rot22*vrp2 + rot23*vrp3) + vp24;
- */
- rot11=(u1 + skew13*n1)*vp11;
- rot21=(v1 + skew23*n1)*vp22;
- rot12=(u2 + skew13*n2)*vp11;
- rot22=(v2 + skew23*n2)*vp22;
- rot13=(u3 + skew13*n3)*vp11 *left_handed;
- rot23=(v3 + skew23*n3)*vp22 *left_handed;
- rot14=-(rot11*vrp1 + rot12*vrp2 + rot13*vrp3) + vp13;
- rot24=-(rot21*vrp1 + rot22*vrp2 + rot23*vrp3) + vp23;
- }
- c_near[0]=c_near[1]=0.; c_near[2]=1.; c_near[3]=wmin;
- c_far[0]=c_far[1]=0.; c_far[2]=-1.; c_far[3]=-wmax;
- if(debugging)
- {printf("skew = 1 %10f \n",skew13);
- printf(" 1 %10f \n",skew23);
- printf(" %10f \n",skew33);
- printf("u,v,n= %10f %10f %10f %10f \n",u1,u2,u3,u4);
- printf(" %10f %10f %10f %10f \n",v1,v2,v3,v4);
- printf(" %10f %10f %10f %10f \n",n1,n2,n3,n4);
- printf("vrp = 1 %10f \n",-vrp1);
- printf(" 1 %10f \n",-vrp2);
- printf(" 1 %10f \n",-vrp3);
- printf(" 1 \n");
- printf("rot= %10f %10f %10f %10f \n",rot11,rot12,rot13,rot14);
- printf(" %10f %10f %10f %10f \n",rot21,rot22,rot23,rot24);
- printf(" %10f %10f %10f %10f \n",rot31,rot32,rot33,rot34);
- printf("width_used= %5.1f height_used= %5.1f \n",
- width_used, height_used);
- printf("xscale= %5f yscale= %5f \n",xscale, yscale);
- getchar();
- show_clipping();
- }
- move_abs_3(0.,0.,0.);
- }
-
- show_clipping()
- { printf("umin = %f vmin = %f wmin = %f \n",umin,vmin,wmin);
- printf("umax = %f vmax = %f wmax = %f \n",umax,vmax,wmax);
- printf("vp_xmin = %f vp_ymin = %f vp_zmin = %f \n",vp_xmin,vp_ymin,vp_zmin);
- printf("vp_xmax = %f vp_ymax = %f vp_zmax = %f \n",vp_xmax,vp_ymax,vp_zmax);
- printf("ndc_width = %f ndc_height = %f ndc_depth = %f \n",ndc_width,ndc_height,ndc_depth);
- printf("wmin1 = %d wmin2 = %d \n",wmin1,wmin2);
- printf("wmax1 = %d wmax2 = %d \n",wmax1,wmax2);
- printf("c_left = (%10f,%10f,%10f,%10f) \n",c_left[0],c_left[1],c_left[2],c_left[3]);
- printf("c_right = (%10f,%10f,%10f,%10f) \n",c_right[0],c_right[1],c_right[2],c_right[3]);
- printf("c_bottom = (%10f,%10f,%10f,%10f) \n",c_bottom[0],c_bottom[1],c_bottom[2],c_bottom[3]);
- printf("c_top = (%10f,%10f,%10f,%10f) \n",c_top[0],c_top[1],c_top[2],c_top[3]);
- printf("c_near = (%10f,%10f,%10f,%10f) \n",c_near[0],c_near[1],c_near[2],c_near[3]);
- printf("c_far = (%10f,%10f,%10f,%10f) \n",c_far[0],c_far[1],c_far[2],c_far[3]);
- getchar();
- }
-
- /* initialize_core - initialize everything */
- initialize_core(out,in,dimension)
- int out, /* 0=basic 1=buffered 2=dynamic a 3=dynamic b 4=dynamic c */
- in, /* 0=none 1=synchronous 2=complete */
- dimension; /* 2=2D 3=3D */
- { if(out>1 || in>1)
- {puts("WARNING: no retained segments or input primitives supported\n");
- getchar();
- }
- }