home *** CD-ROM | disk | FTP | other *** search
- // chap2_12.cpp;
-
- #include <iostream.h>
- #include <graphics.h>
- #include <math.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <conio.h>
-
- #define PI 3.141592654
-
-
- const xoffset=640/2;
- const yoffset=480/2;
- const xscale=1;
- const yscale=-1;
- const persp=500;
-
- struct point
- {
- float xw, yw, zw;
- int xs, ys, zs;
- } vertex[18];
-
- typedef float matrix_4x4[4][4];
- int faces[13][6]; /*First entry is face colour*/
- int face_list[13][2]; /*First entry is face, second is depth*/
- int polygon[20];
- FILE *fp;
- int c, c2, hither=600;
- char ch;
- matrix_4x4 w2v, temp, temp2;
-
- void initialise_graphics()
- {
- int gdriver=DETECT, gmode, errorcode;
-
- initgraph(&gdriver, &gmode,"");
- errorcode=graphresult();
- if (errorcode!=grOk)
- {
- printf("Graphics Error: %s\n",grapherrormsg(errorcode));
- printf("Program Aborted \n");
- exit(1);
- }
- setlinestyle(0,0,3);
- setcolor(WHITE);
-
- }
-
- void translate(float x, float y, float z, matrix_4x4 m)
- {
- m[0][0]=1; m[1][0]=0; m[2][0]=0; m[3][0]=0;
- m[0][1]=0; m[1][1]=1; m[2][1]=0; m[3][1]=0;
- m[0][2]=0; m[1][2]=0; m[2][2]=1; m[3][2]=0;
- m[0][3]=x; m[1][3]=y; m[2][3]=z; m[3][3]=1;
- };
-
- void rotate_x(float t, matrix_4x4 m)
- {
- m[0][0]=1; m[1][0]=0; m[2][0]=0; m[3][0]=0;
- m[0][1]=0; m[1][1]=cos(t); m[2][1]=sin(t); m[3][1]=0;
- m[0][2]=0; m[1][2]=-sin(t); m[2][2]=cos(t); m[3][2]=0;
- m[0][3]=0; m[1][3]=0; m[2][3]=0; m[3][3]=1;
- };
-
-
- void rotate_y(float t, matrix_4x4 m)
- {
- m[0][0]=cos(t); m[1][0]=0; m[2][0]=-sin(t); m[3][0]=0;
- m[0][1]=0; m[1][1]=1; m[2][1]=0; m[3][1]=0;
- m[0][2]=sin(t); m[1][2]=0; m[2][2]=cos(t); m[3][2]=0;
- m[0][3]=0; m[1][3]=0; m[2][3]=0; m[3][3]=1;
- };
-
- void rotate_z(float t, matrix_4x4 m)
- {
- m[0][0]=cos(t); m[1][0]=sin(t); m[2][0]=0; m[3][0]=0;
- m[0][1]=-sin(t); m[1][1]=cos(t); m[2][1]=0; m[3][1]=0;
- m[0][2]=0; m[1][2]=0; m[2][2]=1; m[3][2]=0;
- m[0][3]=0; m[1][3]=0; m[2][3]=0; m[3][3]=1;
- };
-
- void copy_4x4(matrix_4x4 in, matrix_4x4 out)
- {
- int c, r;
- for (r=0; r<4; r++)
- for (c=0; c<4; c++)
- out[r][c]=in[r][c];
- }
-
- void mult_4x4(matrix_4x4 a, matrix_4x4 b, matrix_4x4 m)
- {
- int c;
- for (c=0; c<4; c++)
- m[c][0]=a[0][0]*b[c][0]+a[1][0]*b[c][1]+a[2][0]*b[c][2]+a[3][0]*b[c][3];
- for (c=0; c<4; c++)
- m[c][1]=a[0][1]*b[c][0]+a[1][1]*b[c][1]+a[2][1]*b[c][2]+a[3][1]*b[c][3];
- for (c=0; c<4; c++)
- m[c][2]=a[0][2]*b[c][0]+a[1][2]*b[c][1]+a[2][2]*b[c][2]+a[3][2]*b[c][3];
- for (c=0; c<4; c++)
- m[c][3]=a[0][3]*b[c][0]+a[1][3]*b[c][1]+a[2][3]*b[c][2]+a[3][3]*b[c][3];
- };
-
- void draw_face(int face)
- {
- int x1,y1,z1,x2,y2,z2, xlast, ylast, zlast;
- float xa,xb,ya,yb;
- int count, c;
- float zn;
-
- count=0;
- // Check for back face
- xa=vertex[faces[face][2]-1].xs-vertex[faces[face][1]-1].xs;
- ya=vertex[faces[face][2]-1].ys-vertex[faces[face][1]-1].ys;
- xb=vertex[faces[face][2]-1].xs-vertex[faces[face][3]-1].xs;
- yb=vertex[faces[face][2]-1].ys-vertex[faces[face][3]-1].ys;
- zn=xa*yb-ya*xb;
-
- if (zn>0)
- {
- // Copy vertices to polygon and clip
- for (c=1; c<5; c++)
- {
- if ((faces[face][c+1])!=0)
- {
- x1=vertex[faces[face][c]-1].xs;
- y1=vertex[faces[face][c]-1].ys;
- z1=vertex[faces[face][c]-1].zs;
- x2=vertex[faces[face][c+1]-1].xs;
- y2=vertex[faces[face][c+1]-1].ys;
- z2=vertex[faces[face][c+1]-1].zs;
- xlast=x2; ylast=y2; zlast=z2;
- if ((z2>hither)||(z1>hither))
- {
- if (z1<hither)
- {
- x1=x1+((x2-x1)*float(hither-z1)/float(z2-z1));
- y1=y1+((y2-y1)*float(hither-z1)/float(z2-z1));
- z1=hither;
- };
- if (z2<hither)
- {
- x2=x2+((x1-x2)*float(hither-z2)/float(z1-z2));
- y2=y2+((y1-y2)*float(hither-z2)/float(z1-z2));
- z2=hither;
- }
- if (count==0)
- {
- polygon[0]=x1;
- polygon[1]=y1;
- count++;
- }
- else
- if ((polygon[(count-1)*2]!=x1)&&(polygon[(count-1)*2+1]!=y1))
- {
- polygon[count*2]=x1;
- polygon[count*2+1]=y1;
- count++;
- };
- polygon[count*2]=x2;
- polygon[count*2+1]=y2;
- count++;
- }
- }
- }
-
- x1=xlast;
- y1=ylast;
- z1=zlast;
- x2=vertex[faces[face][1]-1].xs;
- y2=vertex[faces[face][1]-1].ys;
- z2=vertex[faces[face][1]-1].zs;
- if ((z2>hither)||(z1>hither))
- {
- if (z1<hither)
- {
- x1=x1+((x2-x1)*float(hither-z1)/float(z2-z1));
- y1=y1+((y2-y1)*float(hither-z1)/float(z2-z1));
- z1=hither;
- };
- if (z2<hither)
- {
- x2=x2+((x1-x2)*float(hither-z2)/float(z1-z2));
- y2=y2+((y1-y2)*float(hither-z2)/float(z1-z2));
- z2=hither;
- };
- if (count==0)
- {
- polygon[0]=x1;
- polygon[1]=y1;
- count++;
- }
- else
- if ((polygon[(count-1)*2]!=x1)&&(polygon[(count-1)*2+1]!=y1))
- {
- polygon[count*2]=x1;
- polygon[count*2+1]=y1;
- count++;
- }
- polygon[count*2]=x2;
- polygon[count*2+1]=y2;
- count++;
- }
-
- // Draw the polygon
- setfillstyle(1,(faces[face][0]));
- if (count!=0) fillpoly(count,polygon);
- }
- };
-
- void draw_picture()
- {
- int c, c2, max_z;
- short int any_swapped;
- /* Put faces into a list and find each's furthest distance */
- for (c=0; c<13; c++)
- {
- face_list[c][0]=c;
- max_z=-9999;
- for (c2=1; c2<6; c2++)
- {
- if (faces[c][c2]!=0)
- if (vertex[faces[c][c2]-1].zs>max_z) max_z=vertex[faces[c][c2]-1].zs;
- };
- face_list[c][1]=max_z;
- };
-
- /* Bubble sort into decreasing depth order} */
- do
- {
- any_swapped=0;
- for (c=0; c<12; c++)
- {
- if (face_list[c+1][1]>face_list[c][1])
- {
- /* Swap Entries */
- c2=face_list[c+1][1];
- face_list[c+1][1]=face_list[c][1];
- face_list[c][1]=c2;
- c2=face_list[c+1][0];
- face_list[c+1][0]=face_list[c][0];
- face_list[c][0]=c2;
- any_swapped=1;
- };
- };
- }
- while (any_swapped!=0);
-
- cleardevice();
- for (c=0;c<13;c++)
- draw_face(face_list[c][0]);
- };
-
- void transform(matrix_4x4 m)
- {
- for (c=0; c<18; c++)
- {
- vertex[c].zs=(vertex[c].xw*m[2][0]+vertex[c].yw*m[2][1]+vertex[c].zw*m[2][2]+m[2][3]);
- vertex[c].xs=(((vertex[c].xw*m[0][0]+vertex[c].yw*m[0][1]+vertex[c].zw*m[0][2]+m[0][3])
- *(persp/float(vertex[c].zs))*xscale)+xoffset);
- vertex[c].ys=(((vertex[c].xw*m[1][0]+vertex[c].yw*m[1][1]+vertex[c].zw*m[1][2]+m[1][3])
- *(persp/float(vertex[c].zs))*yscale)+yoffset);
- };
- };
-
- void main()
- {
- clrscr();
- printf("\n"); printf("\n"); printf("\n");
- printf("This is from Chapter 2 Step 12 of the Virtual Reality Homebrewer''s Handbook \n");
- printf("and shows how to move around a virtual shape drawn with depth sorted, \n");
- printf("flat shaded faces, clipped to the hither plane, with back faces removed. \n");
- printf("\n");
- printf("To show the effect of clipping, the hither plane is almost at the object. \n");
- printf("Move it back if you just want to move around - or the object will disappear! \n");
- printf("\n");
- printf("\n");
- printf("Controls: 8/2 - move forwards/back \n");
- printf(" 4/6 - move left/back \n");
- printf(" 7/1 - move up/down \n");
- printf(" o/l - pitch up/down \n");
- printf(" </> - yaw left/right \n");
- printf(" n/m - roll left/right \n");
- printf(" =/- - move hither plane forwards/back \n");
- printf("\n");
- printf(" q - quit \n");
- printf("\n");
- printf(" Press any key to continue \n");
- ch=getch();
-
- // Read in vertex data
- if ((fp=fopen("points.dat","r"))==NULL)
- {
- puts("Can't open points.dat");
- exit(0);
- }
- for (c=0; c<18; c++)
- {
- fscanf(fp,"%f %f %f \n",&vertex[c].xw,&vertex[c].yw,&vertex[c].zw);
- }
- fclose(fp);
- // Move to z=500
- for (c=0; c<18; c++)
- vertex[c].zw=vertex[c].zw+500;
-
- // Read in face data
- if ((fp=fopen("faces.dat","r"))==NULL)
- {
- puts("Can't open faces.dat");
- exit(0);
- }
- for (c=0; c<13; c++)
- for (c2=0; c2<6; c2++)
- fscanf(fp,"%d", &faces[c][c2]);
- fclose(fp);
-
- initialise_graphics();
-
- translate(-500,-400,0,w2v);
- rotate_y((PI/5.0),temp);
- mult_4x4(w2v,temp,temp2);
- rotate_x(-PI/6,temp);
- mult_4x4(temp2,temp,w2v);
-
- transform(w2v);
- draw_picture();
- do
- {
- ch=getch();
- switch (ch)
- {
- case '8': {
- translate(0,0,-10,temp);
- mult_4x4(w2v,temp,temp2);
- copy_4x4(temp2,w2v);
- break;
- };
- case '2': {
- translate(0,0,10,temp);
- mult_4x4(w2v,temp,temp2);
- copy_4x4(temp2,w2v);
- break;
- };
- case '4': {
- translate(10,0,0,temp);
- mult_4x4(w2v,temp,temp2);
- copy_4x4(temp2,w2v);
- break;
- };
- case '6': {
- translate(-10,0,0,temp);
- mult_4x4(w2v,temp,temp2);
- copy_4x4(temp2,w2v);
- break;
- };
- case '1': {
- translate(0,10,0,temp);
- mult_4x4(w2v,temp,temp2);
- copy_4x4(temp2,w2v);
- break;
- };
- case '7': {
- translate(0,-10,0,temp);
- mult_4x4(w2v,temp,temp2);
- copy_4x4(temp2,w2v);
- break;
- };
- case ',': {
- rotate_y(PI/180.0,temp);
- mult_4x4(w2v,temp,temp2);
- copy_4x4(temp2,w2v);
- break;
- };
- case '.': {
- rotate_y(-PI/180.0,temp);
- mult_4x4(w2v,temp,temp2);
- copy_4x4(temp2,w2v);
- break;
- };
- case 'm': {
- rotate_z(PI/180.0,temp);
- mult_4x4(w2v,temp,temp2);
- copy_4x4(temp2,w2v);
- break;
- };
- case 'n': {
- rotate_z(-PI/180.0,temp);
- mult_4x4(w2v,temp,temp2);
- copy_4x4(temp2,w2v);
- break;
- };
- case 'o': {
- rotate_x(PI/180.0,temp);
- mult_4x4(w2v,temp,temp2);
- copy_4x4(temp2,w2v);
- break;
- };
- case 'l': {
- rotate_x(-PI/180.0,temp);
- mult_4x4(w2v,temp,temp2);
- copy_4x4(temp2,w2v);
- break;
- };
- case '=': hither=hither+10; break;
- case '-': hither=hither-10; break;
- };
- transform(w2v);
- draw_picture();
- }
- while (ch!='q');
- closegraph();
- }