home *** CD-ROM | disk | FTP | other *** search
- /* tc-11.c */
- /* Draws a computer-shaded sphere using the
- plane equation method of hidden surface removal and the
- surface normal method od halftone shading
-
- REQUIRES EITHER EGA OR VGA!! */
-
- /* ----------------------------------------------------------------------- */
- /* INCLUDE FILES */
- #include <process.h>
- #include <bios.h>
- #include <stdio.h>
- #include <graphics.h>
- #include <math.h>
-
- /* ----------------------------------------------------------------------- */
- /* DECLARATIONS */
-
- float x=0.0,y=0.0,z=0.0; /* world coordinates */
- float x1=0.0,x2=0.0,x3=0.0,x4=0.0; /* polygon vertices */
- float y01=0.0,y2=0.0,y3=0.0,y4=0.0; /* polygon vertices */
- float z1=0.0,z2=0.0,z3=0.0,z4=0.0; /* polygon vertices */
- float sx1=0.0,sx2=0.0,sx3=0.0,sx4=0.0,sx5=0.0; /* display coordinaes */
- float sy1=0.0,sy2=0.0,sy3=0.0,sy4=0.0,sy5=0.0; /* display coordinates */
- float sx=0.0,sy=0.0; /* output of 3d perspective formulas */
- float xa=0.0,ya=0.0,za=0.0; /* temporary values in 3d formulas */
- float d=1000.0; /* angular perspective value */
- double r1=6.19592; /* yaw angle in radians */
- double r2=.523590; /* roll angle in radians */
- double r3=5.39778; /* pitch angle in radians */
- double sr1=0.0,sr2=0.0,sr3=0.0; /* sine rotation factors */
- double cr1=0.0,cr2=0.0,cr3=0.0; /* cosine rotation factors */
- float mx=0.0,my=0.0,mz=-150.0; /* viewpoint position */
- int maxx=639,minx=0,maxy=199,miny=0; /* scaling viewport */
- float screen_x=639,screen_y=199; /* dimensions of screen mode */
- int C0=0,C1=1,C2=2,C3=3,C4=4,C5=5,C6=6,C7=7,C8=8, /* color varariables */
- C9=9,C10=10,C11=11,C12=12,C13=13,C14=14,C15=15,
- mode_flag=0;
- float rx=0.0,ry=0.0; /* scaling values used in mapping routine */
- int t=0,t1=0,t2=0; /* loop counters */
- int p1=0; /* array indexer */
- int key_matte_clr=6; /* exclusive key matte color */
- int edge_clr=7; /* used to draw edges on models */
- int solid_clr=0; /* used to fill surfaces of solid models */
- int design_clr=1; /* used to draw the design on the model */
- float x_res,y_res; /* used for 2d mappinf from 640*480 template */
- float sp=0.0; /* visibility factor in hidden surface routine */
- float sp1=0.0,sp2=0.0,sp3=0.0; /* temporary values of sp */
- float xlarge=0.0,xsmall=0.0; /* when finding polygon center (not used) */
- float ylarge=0.0,ysmall=0.0;
- float zlarge=0.0,zsmall=0.0;
- float x6=0.0,x7=0.0,y6=0.0,y7=0.0,z6=0.0,z7=0.0;
-
- int NORM_HUE=0; /* halftoning color */
- int BASE_CLR=0; /* prep cooor for dithering */
- int CC4=0; /* underlay color for dithering */
- int CC5=0; /* overlay color for dithering */
- unsigned short CC6=0xffff; /* pattern for dithering */
- float xx1=0,yy1=.0,zz1=1; /* location of light source - elevation 45 degrees, compas 135 degrees {{REDIFINED !!}}*/
- float v4=0.0; /* illumination factor 0 to 1 range */
- int v5=0; /* illumination factor base 1 range */
- int v6=11; /* VGA and EGA illumination range */
- int v7=0; /* temporary varaible used for illumination range */
- float xu=0.0,yu=0.0,zu=0.0; /* vector from vertex one to vertex two */
- float xv=0.0,yv=0.0,zv=0.0; /* vector from vertex 1 to vertex 3 */
- float xn=0.0,y0n=0.0,zn=0.0; /* surface perpendicular factor */
- float v1=0.0,v2=0.0; /* length of surface perpendicular vector */
- float v3=0.0; /* ratio of length to unit vector magnitude */
- float xw=0.0,yw=0.0,zw=0.0; /* surface perpendicual unit vector */
- int polary[4][2]; /* used in my 3d solid polygon draw routine */
-
- /* define halftone codes */
- char fill_0[]={0,0,0,0,0,0,0,0}; /* 0% fill */
- char fill_3[]={0,32,0,0,0,2,0,0}; /* 3% fill */
- char fill_6[]={32,0,2,0,128,0,8,0}; /* 6% fill */
- char fill_12[]={32,2,128,8,32,2,128,8}; /* 12% fill */
- char fill_25[]={68,17,68,17,68,17,68,17}; /* 25% fill */
- char fill_37[]={170,68,170,17,170,68,170,17}; /* 37% fill */
- char fill_50[]={85,170,85,170,85,170,85,170}; /* 50% fill */
- char fill_62[]={85,187,85,238,85,187,85,238}; /* 62% fill */
- char fill_75[]={187,238,187,238,187,238,187,238}; /* 75% fill */
- char fill_87[]={223,253,127,247,223,253,127,247}; /* 87% fill */
- char fill_93[]={255,223,255,223,255,223,255,223}; /* 93% fill */
- char fill_100[]={255,255,255,255,255,255,255,255}; /* 100% fill */
-
- int q=0,q1=0,q2=0; /* sphere surface & vertex counters */
- double r4=6.28319,r5=6.28319; /* spherical coordinate angles */
- float B11[36][3]; /* 36 sets of xyz view coordinates, upper */
- float B12[36][3]; /* 36 sets of xyz view coordinates, lower */
- float B21[36][2]; /* 36 sets of sx,sy display coordinates, upper */
- float B22[36][2]; /* 36 sets of sx,sy display coordinates, lower */
- double sr4=0.0,cr4=0.0,sr5=0.0,cr5=0.0; /* rotation factors */
-
- /* declare global subroutines */
- void keyboard(void);void quit_pgm(void);void calc_3d(void);
- void rotation(void);void window(void);void graphics_setup(void);
- void coords(void);void draw_poly(void);void notice (int x,int y);
- void visibility_test(void);void polycenter(void);
- void illumination(void);void dither(void);void shade(void);
- void values(void);
-
- void sphere_coords(void);void draw_4poly(void);
- void draw_3polynorth(void);void draw_3polysouth(void);
- void upper_coords(void);void lower_coords(void);
-
- /* ----------------------------------------------------------------------- */
- /* MAIN ROUTINE */
-
- main(){
- graphics_setup();
- setviewport(0,0,maxx,maxy,1);
- key_matte_clr=C6;
- edge_clr=C7;solid_clr=C3;
- NORM_HUE=C11;
-
- rotation();
-
- /* DRAW NORTH POLAR REGION */
- r5=0.0;r4=0.0;x=30;sphere_coords();calc_3d();window();
- B11[0][0]=x;B11[0][1]=y;B11[0][2]=z;
- B21[0][0]=sx;B21[0][1]=sy;
- x=-30;r5=.17453;r4=0.0;lower_coords();
- for (q1=0;q1<=35;q1++){
- q2=q1+1;if (q2>35) q2=0;
- draw_3polynorth();
- keyboard();
- }
-
- /* DRAW POLYGONS ALONG BELTS OF SPHERES */
- r5=.17453;
- for (t2=1;t2<=16;t2++){
- x=30;r4=0.0;upper_coords();
- x=30;r5=r5+.17453;r4=0.0;lower_coords();
- for (q1=0;q1<=35;q1++){
- q2=q1+1;if (q2>35) q2=0;
- draw_4poly();
- keyboard();
- }
- }
-
- /* DRAW SOUTH POLAR REGIONS */
- r5=3.14159;r4=0.0;x=30;sphere_coords();calc_3d();window();
- B21[0][0]=x;B21[0][1]=y;B21[0][2]=z;
- B22[0][0]=sx;B22[0][1]=sy;
- x=30;r5=2.96706;r4=0.0;upper_coords();
- for (q1=0;q1<=35;q1++){
- q2=q1+1;if (q2>35) q2=0;
- draw_3polysouth();
- keyboard();
- }
-
- setcolor(C7);notice(0,0);
- for (t1=1;t1!=2;) keyboard();
- quit_pgm();
- }
-
- /* ----------------------------------------------------------------------- */
- /* SUBROUTINE: CALCULATE AND STORE COORDS FOR BELT */
-
- void upper_coords(void){
- for (t=0;t<=35;t++){
- x=30;sphere_coords();calc_3d();window();
- B11[t][0]=x;B11[t][1]=y;B11[t][2]=z;
- B21[t][0]=sx;B21[t][1]=sy;
- r4=r4+.17453;
- keyboard();}
- return;}
-
- void lower_coords(void){
- for (t=0;t<=35;t++){
- x=30;sphere_coords();calc_3d();window();
- B12[t][0]=x;B12[t][1]=y;B12[t][2]=z;
- B22[t][0]=sx;B22[t][1]=sy;
- r4=r4+.17453;
- keyboard();}
- return;}
-
- /* ----------------------------------------------------------------------- */
- /* SUBROUTINE: CALCULATE WORLD COORDINATES FOR SPHERE */
-
- void sphere_coords(void){
- sr4=sin(r4);cr4=cos(r4);sr5=sin(r5);
- cr5=cos(r5);x1=sr5*x;y=cr5*x;x=cr4*x1;z=sr4*x1;return;}
-
- /* ----------------------------------------------------------------------- */
- /* SUBROUTINE: DRAW 4 SIDED POLYGON SURFACE ON SPHERE */
-
- void draw_4poly(void){
- x1=B11[q1][0];y01=B11[q1][1];z1=B11[q1][2];
- x2=B11[q2][0];y2=B11[q2][1];z2=B11[q2][2];
- x3=B12[q2][0];y3=B12[q2][1];z3=B12[q2][2];
- x4=B12[q1][0];y4=B12[q1][1];z4=B12[q1][2];
- visibility_test();if (sp>-100) return;
- sx1=B21[q1][0];sy1=B21[q1][1];
- sx2=B21[q2][0];sy2=B21[q2][1];
- sx3=B22[q2][0];sy3=B22[q2][1];
- sx4=B22[q1][0];sy4=B22[q1][1];
- polycenter();
- draw_poly();
- illumination();shade();dither();
- return;}
-
- /* ----------------------------------------------------------------------- */
- /* SUBROUTINE: DRAW 3 SIDED POLYGONAL SURFACE ON SPHERE */
-
- void draw_3polynorth(void){
- x1=B12[q2][0];y01=B12[q2][1];z1=B12[q2][2];
- x2=B12[q1][0];y2=B12[q1][1];z2=B12[q1][2];
- x3=B11[0][0];y3=B11[0][1];z3=B11[0][2];
- visibility_test();if (sp>0) return;
- sx1=B22[q2][0];sy1=B22[q2][1];
- sx2=B22[q1][0];sy2=B22[q1][1];
- sx3=B21[0][0];sy3=B21[0][1];
- sx4=sx1;sy4=sy1;
- x4=x1+.5*(x2-x1);y4=y01+.5*(y2-y01);z4=z1+.5*(z2-z1);
- x=x3+.85*(x4-x3);y=y3+.85*(y4-y3);z=z3+.85*(z4-z3);
- sx=d*x/z;sy=d*y/z;window();sx5=sx;sy5=sy;
- polycenter();
- draw_poly();
- illumination();shade();dither();
- return;}
-
- void draw_3polysouth(void){
- x1=B12[q1][0];y01=B12[q1][1];z1=B12[q1][2];
- x2=B12[q2][0];y2=B12[q2][1];z2=B12[q2][2];
- x3=B11[0][0];y3=B11[0][1];z3=B11[0][2];
- visibility_test(); if (sp>0) return;
- sx1=B21[q2][0];sy1=B21[q2][1];
- sx2=B21[q1][0];sy2=B21[q1][1];
- sx3=B22[0][0];sy3=B22[0][1];
- sx4=sx1;sy4=sy1;
- x4=x1+.5*(x2-x1);y4=y01+.5*(y2-y01);z4=z1+.5*(z2-z1);
- x=x3+.85*(x4-x3);y=y3+.85*(y4-y3);z=z3+.85*(z4-z3);
- sx=d*x/z;sy=d*y/z;window();sx5=sx;sy5=sy;
- draw_poly();
- illumination();shade();dither();
- return;}
- /* ----------------------------------------------------------------------- */
- /* SUBROUTINE: IDENTIFY CENTER OF POLYGON - not used */
-
- void polycenter(void){x6=x2+.5*(x1-x2);y6=y2+.5*(y01-y2);
- z6=z2+.5*(z1-z2);x7=x3+.5*(x4-x3);y7=y3+.5*(y4-y3);z7=z3+.5*(z4-z3);
- x=x7+.5*(x6-x7);y=y7+.5*(y6-y7);z=z7+.5*(z6-z7);sx=d*x/z;sy=d*y/z;
- window();sx5=sx;sy5=sy;return;}
-
- /* ----------------------------------------------------------------------- */
- /* SUBROUTINE: CALCULATE SIN,COS FACTORS */
-
- void rotation(void){
- sr1=sin(r1);sr2=sin(r2);sr3=sin(r3);cr1=cos(r1);cr2=cos(r2);
- cr3=cos(r3);return;}
-
- /* ----------------------------------------------------------------------- */
- /* SUBROUTINE: STANDARD 3D FORMULAS */
- /* Pass: x,y,z cartesian world coordinates.
- Returns: sx,sy cartesian display coordinates.
- x,y,z catesian view coordinates */
-
- void calc_3d(void){
- x=(-1)*x;xa=cr1*x-sr1*z;za=sr1*x+cr1*z;x=cr2*xa+sr2*y;
- ya=cr2*y-sr2*xa;z=cr3*za-sr3*ya;y=sr3*za+cr3*ya;x=x+mx;y=y+my;
- z=z+mz;sx=d*x/z;sy=d*y/z;return;}
-
- /* ----------------------------------------------------------------------- */
- /* HIDDEN SURFACE VISIBILTY TEST */
- void visibility_test(void){
- sp1=x1*(y2*z3-y3*z2);sp1=(-1)*sp1;sp2=x2*(y3*z1-y01*z3);
- sp3=x3*(y01*z2-y2*z1);sp=sp1-sp2-sp3;return;}
-
- /* ----------------------------------------------------------------------- */
- /* SUBROUTINE: DRAW 4-SIDED SOLID POLYGON IN 3D SPACE */
-
- void draw_poly(void){
- setlinestyle(USERBIT_LINE,0xffff,NORM_WIDTH);
- setfillstyle(SOLID_FILL,solid_clr);
- setcolor(edge_clr);
-
- polary[0][0]=sx1;polary[0][1]=sy1;polary[1][0]=sx2;polary[1][1]=sy2;
- polary[2][0]=sx3;polary[2][1]=sy3;polary[3][0]=sx4;polary[3][1]=sy4;
-
- fillpoly (4,(int far*) polary);
- return;
- }
-
- /* ----------------------------------------------------------------------- */
- /* SUBROUTINES: CALCULATE ILLUMINATION LEVEL */
-
- void illumination(void){
- xu=x2-x1;yu=y2-y01;zu=z2-z1; /* vector from vertex 1 to vertex 2 */
- xv=x3-x1;yv=y3-y01;zv=z3-z1; /* vector from vertex 1 to vertex 3 */
- xn=(yu*zv)-(zu*yv);y0n=(zu*xv)-(xu*zv);
- zn=(xu*yv)-(yu*xv); /* surface perpendicular vector */
- y0n=y0n*(-1);zn=zn*(-1); /* convert to cartesian system */
- v1=(xn*xn)+(y0n*y0n)+(zn*zn);
- v2=sqrt(v1); /* magnitude of surface perpendicular vector */
- v3=1/v2; /* ratio of magnitude to length of unit vector */
- xw=v3*xn;yw=v3*y0n;zw=v3*zn; /* surface perpendicular to unit vector */
- v4=(xw*xx1)+(yw*yy1)+(zw*zz1); /* illumination factor 0 to 1 */
- v4=v4*v6; /* expand illumination range from base 0 */
- v7=v4; /* convert illumination range to integer */
- v5=v7+1; /* illumination range from base 1 */
- return;
- }
-
- /* ----------------------------------------------------------------------- */
- /* SUBROUTINE: ILLUMINATION MATRIX */
-
- void shade(void){
- switch (v5){
- case 1:setfillpattern(fill_6,NORM_HUE);CC6=0x1010;values();return;
- case 2:setfillpattern(fill_6,NORM_HUE);CC6=0x1010;values();return;
- case 3:setfillpattern(fill_6,NORM_HUE);CC6=0x1010;values();return;
- case 4:setfillpattern(fill_12,NORM_HUE);CC6=0x2020;values();return;
- case 5:setfillpattern(fill_25,NORM_HUE);CC6=0x2222;values();return;
- case 6:setfillpattern(fill_37,NORM_HUE);CC6=0xaaaa;values();return;
- case 7:setfillpattern(fill_50,NORM_HUE);CC6=0xaaaa;values();return;
- case 8:setfillpattern(fill_62,NORM_HUE);CC6=0xaaaa;values();return;
- case 9:setfillpattern(fill_75,NORM_HUE);CC6=0xbbbb;values();return;
- case 10:setfillpattern(fill_87,NORM_HUE);CC6=0xdddd;values();return;
- case 11:setfillpattern(fill_93,NORM_HUE);CC6=0xefef;values();return;
- case 12:setfillpattern(fill_100,NORM_HUE);CC6=0xffff;values();return;
- defualt:setfillpattern(fill_6,NORM_HUE);CC6=0x1010;values();}
- return;}
-
- /* ----------------------------------------------------------------------- */
- /* LOCAL SUBROUTINE: prep fill and set dithering variables */
- void values(void){
- floodfill(sx5,sy5,edge_clr);CC4=BASE_CLR;CC5=NORM_HUE;return;}
-
- /* ----------------------------------------------------------------------- */
- /* SUBROUTINE: APPLY DITHERING */
-
- void dither(void){
- setlinestyle(USERBIT_LINE,0xffff,NORM_WIDTH);setcolor(CC4);
- moveto (sx1,sy1);lineto(sx2,sy2);lineto(sx3,sy3);
- lineto(sx4,sy4);lineto(sx1,sy1);
- setlinestyle(USERBIT_LINE,CC6,NORM_WIDTH);setcolor(CC5);
- moveto(sx1,sy1);lineto(sx2,sy2);lineto(sx3,sy3);
- lineto(sx4,sy4);lineto(sx1,sy1);
- return;
- }
- /* ----------------------------------------------------------------------- */
- /* SUBROUTINE: MAP CARTESIAN COORDS TO PHYSICAL SCREEN COORDS */
-
- void window(void){
- sx=sx+399;sy=sy+299;rx=screen_x/799;ry=screen_y/599;sx=sx*rx;
- sy=sy*ry;return;}
-
- /* ----------------------------------------------------------------------- */
- /* SUBROUTINE: CHACK THE KEYBOARD BUFFER */
- void keyboard(void){
- if (bioskey(1)==0) return; else quit_pgm();}
-
- /* ----------------------------------------------------------------------- */
- /* SUBROUTINE: GRACEFUL EXIT FROM PROGRAM */
-
- void quit_pgm(void){
- cleardevice();restorecrtmode();exit(0);}
-
- /* ----------------------------------------------------------------------- */
- /* SUBROUTINE: VGA/EGA/MCGA/CGA COMPATIBILITY MODULE */
-
- void graphics_setup(void){
- int graphics_adapter,graphics_mode;
- detectgraph(&graphics_adapter,&graphics_mode);
- if (graphics_adapter==VGA) goto VGA_mode;
- if (graphics_mode==EGAHI) goto EGA_ECD_mode;
- if (graphics_mode==EGALO) goto EGA_SCD_mode;
- if (graphics_adapter==CGA) goto abort_message;
- if (graphics_adapter==MCGA) goto abort_message;
- goto abort_message;
-
- VGA_mode:
- graphics_adapter=VGA;graphics_mode=VGAHI;
- initgraph(&graphics_adapter,&graphics_mode,"");
- x_res=640;y_res=480;mode_flag=1;
- maxx=639;minx=0;maxy=479;miny=0;screen_x=639;screen_y=479;
- setcolor(7);moveto(0,472);
- outtext("Revisions by A. Helder");
- moveto(472,472);
- outtext("Press any key to quit");
- moveto(160,0);
- outtext("USING C TO GENERATE A 3D SHADED SPHERE");
- return;
-
- EGA_ECD_mode:
- graphics_adapter=EGA;graphics_mode=EGAHI;
- initgraph(&graphics_adapter,&graphics_mode,"");
- x_res=640;y_res=350;mode_flag=2;
- maxx=639;minx=0;maxy=349;miny=0;screen_x=639;screen_y=349;
- setcolor(7);moveto(0,342);
- outtext("Revisions by A. Helder");
- moveto(472,342);
- outtext ("Press any key to quit");
- moveto(160,0);
- outtext("USING C TO GENERATE A 3D SHADED SPHERE");
- return;
-
- EGA_SCD_mode:
- graphics_adapter=EGA;graphics_mode=EGALO;
- initgraph(&graphics_adapter,&graphics_mode,"");
- x_res=640;y_res=200;mode_flag=3;
- maxx=639;minx=0;maxy=199;miny=0;screen_x=639;screen_y=199;
- setcolor(7);moveto(0,192);
- outtext("Revisions by A. Helder");
- moveto(472,192);
- outtext("PRESS ANY KEY TO QUIT");
- moveto(160,0);
- outtext("USING C TO GENERATE A 3D SHADED SPHERE");
- return;
-
- abort_message:
- printf("\n\nUnable to proceed - Requires VGA,EGA adapter");
- printf("\nWith appropriate monitor");
- exit(0);
- }
-
- /* ----------------------------------------------------------------------- */
- /* SUBROUTINE: MAP 640*480 TEMPLATE TO 2D SCREEN */
- void coords(void)
- {
- sx=sx*(x_res/640);sy=sy*(y_res/480);return;
- }
-
- /* ----------------------------------------------------------------------- */
- /* SUBROUTINE: COPYRIGHT NOTICE */
-
- int copyright[][3]={0x7c00,0x0000,0x0000,0x8231,
- 0x819c,0x645e,0xba4a,0x4252,0x96d0,0xa231,0x8252,0x955e,0xba4a,
- 0x43d2,0xf442,0x8231,0x825c,0x945e,0x7c00,0x0000,0x0000};
-
- void notice(int x, int y){
- int a,b,c; int t1=0;
-
- for (t1=0;t1<=6;t1++)
- {
- a=copyright[t1][0];b=copyright[t1][1];
- c=copyright[t1][2];
- setlinestyle(USERBIT_LINE,a,NORM_WIDTH);
- moveto(x,y);lineto(x+15,y);
- setlinestyle(USERBIT_LINE,b,NORM_WIDTH);
- moveto(x+16,y);lineto(x+31,y);
- setlinestyle(USERBIT_LINE,c,NORM_WIDTH);
- moveto(x+32,y);lineto(x+47,y);y++;
- };
- setlinestyle(USERBIT_LINE,0xFFFF,NORM_WIDTH);
- return;}
-