home *** CD-ROM | disk | FTP | other *** search
/ Virtual Reality Homebrewer's Handbook / vr.iso / 3dgraph / c / chap2_12.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-03-19  |  10.6 KB  |  413 lines

  1. // chap2_12.cpp;
  2.  
  3. #include <iostream.h>
  4. #include <graphics.h>
  5. #include <math.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <conio.h>
  9.  
  10. #define PI 3.141592654
  11.  
  12.  
  13. const xoffset=640/2;
  14. const yoffset=480/2;
  15. const xscale=1;
  16. const yscale=-1;
  17. const persp=500;
  18.  
  19. struct point
  20. {
  21.     float xw, yw, zw;
  22.     int   xs, ys, zs;
  23. }   vertex[18];
  24.  
  25. typedef float  matrix_4x4[4][4];
  26. int    faces[13][6];  /*First entry is face colour*/
  27. int    face_list[13][2]; /*First entry is face, second is depth*/
  28. int    polygon[20];
  29. FILE   *fp;
  30. int    c, c2, hither=600;
  31. char   ch;
  32. matrix_4x4   w2v, temp, temp2;
  33.  
  34. void initialise_graphics()
  35. {
  36.      int gdriver=DETECT, gmode, errorcode;
  37.  
  38.      initgraph(&gdriver, &gmode,"");
  39.      errorcode=graphresult();
  40.      if (errorcode!=grOk)
  41.      {
  42.       printf("Graphics Error: %s\n",grapherrormsg(errorcode));
  43.       printf("Program Aborted \n");
  44.       exit(1);
  45.      }
  46.      setlinestyle(0,0,3);
  47.      setcolor(WHITE);
  48.  
  49. }
  50.  
  51. void translate(float x, float y, float z, matrix_4x4 m)
  52. {
  53.      m[0][0]=1; m[1][0]=0; m[2][0]=0; m[3][0]=0;
  54.      m[0][1]=0; m[1][1]=1; m[2][1]=0; m[3][1]=0;
  55.      m[0][2]=0; m[1][2]=0; m[2][2]=1; m[3][2]=0;
  56.      m[0][3]=x; m[1][3]=y; m[2][3]=z; m[3][3]=1;
  57. };
  58.  
  59. void rotate_x(float t, matrix_4x4 m)
  60. {
  61.      m[0][0]=1; m[1][0]=0;       m[2][0]=0;      m[3][0]=0;
  62.      m[0][1]=0; m[1][1]=cos(t);  m[2][1]=sin(t); m[3][1]=0;
  63.      m[0][2]=0; m[1][2]=-sin(t); m[2][2]=cos(t); m[3][2]=0;
  64.      m[0][3]=0; m[1][3]=0;       m[2][3]=0;      m[3][3]=1;
  65. };
  66.  
  67.  
  68. void rotate_y(float t, matrix_4x4 m)
  69. {
  70.      m[0][0]=cos(t); m[1][0]=0; m[2][0]=-sin(t); m[3][0]=0;
  71.      m[0][1]=0;      m[1][1]=1; m[2][1]=0;       m[3][1]=0;
  72.      m[0][2]=sin(t); m[1][2]=0; m[2][2]=cos(t);  m[3][2]=0;
  73.      m[0][3]=0;      m[1][3]=0; m[2][3]=0;       m[3][3]=1;
  74. };
  75.  
  76. void rotate_z(float t, matrix_4x4 m)
  77. {
  78.      m[0][0]=cos(t);  m[1][0]=sin(t); m[2][0]=0; m[3][0]=0;
  79.      m[0][1]=-sin(t); m[1][1]=cos(t); m[2][1]=0; m[3][1]=0;
  80.      m[0][2]=0;       m[1][2]=0;      m[2][2]=1; m[3][2]=0;
  81.      m[0][3]=0;       m[1][3]=0;      m[2][3]=0; m[3][3]=1;
  82. };
  83.  
  84. void copy_4x4(matrix_4x4 in, matrix_4x4 out)
  85. {
  86.       int c, r;
  87.       for (r=0; r<4; r++)
  88.       for (c=0; c<4; c++)
  89.           out[r][c]=in[r][c];
  90. }
  91.  
  92. void mult_4x4(matrix_4x4 a, matrix_4x4 b, matrix_4x4 m)
  93. {
  94.       int c;
  95.       for (c=0; c<4; c++)
  96.       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];
  97.       for (c=0; c<4; c++)
  98.       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];
  99.       for (c=0; c<4; c++)
  100.       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];
  101.       for (c=0; c<4; c++)
  102.       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];
  103. };
  104.  
  105. void draw_face(int face)
  106. {
  107.     int x1,y1,z1,x2,y2,z2, xlast, ylast, zlast;
  108.     float xa,xb,ya,yb;
  109.     int count, c;
  110.     float zn;
  111.  
  112.      count=0;
  113. //   Check for back face
  114.      xa=vertex[faces[face][2]-1].xs-vertex[faces[face][1]-1].xs;
  115.      ya=vertex[faces[face][2]-1].ys-vertex[faces[face][1]-1].ys;
  116.      xb=vertex[faces[face][2]-1].xs-vertex[faces[face][3]-1].xs;
  117.      yb=vertex[faces[face][2]-1].ys-vertex[faces[face][3]-1].ys;
  118.      zn=xa*yb-ya*xb;
  119.  
  120.      if (zn>0)
  121.      {
  122. //   Copy vertices to polygon and clip
  123.      for (c=1; c<5; c++)
  124.      {
  125.       if ((faces[face][c+1])!=0)
  126.       {
  127.            x1=vertex[faces[face][c]-1].xs;
  128.            y1=vertex[faces[face][c]-1].ys;
  129.            z1=vertex[faces[face][c]-1].zs;
  130.            x2=vertex[faces[face][c+1]-1].xs;
  131.            y2=vertex[faces[face][c+1]-1].ys;
  132.            z2=vertex[faces[face][c+1]-1].zs;
  133.            xlast=x2; ylast=y2; zlast=z2;
  134.            if ((z2>hither)||(z1>hither))
  135.            {
  136.             if (z1<hither)
  137.             {
  138.              x1=x1+((x2-x1)*float(hither-z1)/float(z2-z1));
  139.              y1=y1+((y2-y1)*float(hither-z1)/float(z2-z1));
  140.              z1=hither;
  141.             };
  142.             if (z2<hither)
  143.             {
  144.              x2=x2+((x1-x2)*float(hither-z2)/float(z1-z2));
  145.              y2=y2+((y1-y2)*float(hither-z2)/float(z1-z2));
  146.              z2=hither;
  147.             }
  148.             if (count==0)
  149.             {
  150.              polygon[0]=x1;
  151.              polygon[1]=y1;
  152.              count++;
  153.             }
  154.             else
  155.             if ((polygon[(count-1)*2]!=x1)&&(polygon[(count-1)*2+1]!=y1))
  156.             {
  157.              polygon[count*2]=x1;
  158.              polygon[count*2+1]=y1;
  159.              count++;
  160.             };
  161.             polygon[count*2]=x2;
  162.             polygon[count*2+1]=y2;
  163.             count++;
  164.            }
  165.       }
  166.      }
  167.  
  168.      x1=xlast;
  169.      y1=ylast;
  170.      z1=zlast;
  171.      x2=vertex[faces[face][1]-1].xs;
  172.      y2=vertex[faces[face][1]-1].ys;
  173.      z2=vertex[faces[face][1]-1].zs;
  174.      if ((z2>hither)||(z1>hither))
  175.      {
  176.       if (z1<hither)
  177.       {
  178.            x1=x1+((x2-x1)*float(hither-z1)/float(z2-z1));
  179.            y1=y1+((y2-y1)*float(hither-z1)/float(z2-z1));
  180.            z1=hither;
  181.       };
  182.       if (z2<hither)
  183.       {
  184.            x2=x2+((x1-x2)*float(hither-z2)/float(z1-z2));
  185.            y2=y2+((y1-y2)*float(hither-z2)/float(z1-z2));
  186.            z2=hither;
  187.       };
  188.       if (count==0)
  189.       {
  190.            polygon[0]=x1;
  191.            polygon[1]=y1;
  192.            count++;
  193.       }
  194.       else
  195.       if ((polygon[(count-1)*2]!=x1)&&(polygon[(count-1)*2+1]!=y1))
  196.       {
  197.            polygon[count*2]=x1;
  198.            polygon[count*2+1]=y1;
  199.            count++;
  200.       }
  201.       polygon[count*2]=x2;
  202.       polygon[count*2+1]=y2;
  203.       count++;
  204.      }
  205.  
  206. //   Draw the polygon
  207.      setfillstyle(1,(faces[face][0]));
  208.      if (count!=0) fillpoly(count,polygon);
  209.      }
  210. };
  211.  
  212. void draw_picture()
  213. {
  214.      int c, c2, max_z;
  215.      short int any_swapped;
  216.      /* Put faces into a list and find each's furthest distance */
  217.      for (c=0; c<13; c++)
  218.      {
  219.       face_list[c][0]=c;
  220.       max_z=-9999;
  221.       for (c2=1; c2<6; c2++)
  222.       {
  223.            if (faces[c][c2]!=0)
  224.           if (vertex[faces[c][c2]-1].zs>max_z) max_z=vertex[faces[c][c2]-1].zs;
  225.       };
  226.       face_list[c][1]=max_z;
  227.      };
  228.  
  229.      /* Bubble sort into decreasing depth order} */
  230.      do
  231.      {
  232.        any_swapped=0;
  233.        for (c=0; c<12; c++)
  234.        {
  235.         if (face_list[c+1][1]>face_list[c][1])
  236.         {
  237.              /* Swap Entries */
  238.              c2=face_list[c+1][1];
  239.              face_list[c+1][1]=face_list[c][1];
  240.              face_list[c][1]=c2;
  241.              c2=face_list[c+1][0];
  242.              face_list[c+1][0]=face_list[c][0];
  243.              face_list[c][0]=c2;
  244.              any_swapped=1;
  245.         };
  246.        };
  247.      }
  248.      while (any_swapped!=0);
  249.  
  250.      cleardevice();
  251.      for (c=0;c<13;c++)
  252.      draw_face(face_list[c][0]);
  253. };
  254.  
  255. void transform(matrix_4x4 m)
  256. {
  257.      for (c=0; c<18; c++)
  258.      {
  259.      vertex[c].zs=(vertex[c].xw*m[2][0]+vertex[c].yw*m[2][1]+vertex[c].zw*m[2][2]+m[2][3]);
  260.      vertex[c].xs=(((vertex[c].xw*m[0][0]+vertex[c].yw*m[0][1]+vertex[c].zw*m[0][2]+m[0][3])
  261.                *(persp/float(vertex[c].zs))*xscale)+xoffset);
  262.      vertex[c].ys=(((vertex[c].xw*m[1][0]+vertex[c].yw*m[1][1]+vertex[c].zw*m[1][2]+m[1][3])
  263.                *(persp/float(vertex[c].zs))*yscale)+yoffset);
  264.      };
  265. };
  266.  
  267. void main()
  268. {
  269.      clrscr();
  270.      printf("\n"); printf("\n"); printf("\n");
  271.      printf("This is from Chapter 2 Step 12 of the Virtual Reality Homebrewer''s Handbook \n");
  272.      printf("and shows how to move around a virtual shape drawn with depth sorted,  \n");
  273.      printf("flat shaded faces, clipped to the hither plane, with back faces removed. \n");
  274.      printf("\n");
  275.      printf("To show the effect of clipping, the hither plane is almost at the object. \n");
  276.      printf("Move it back if you just want to move around - or the object will disappear! \n");
  277.      printf("\n");
  278.      printf("\n");
  279.      printf("Controls:       8/2  - move forwards/back \n");
  280.      printf("                4/6  - move left/back \n");
  281.      printf("                7/1  - move up/down \n");
  282.      printf("                o/l  - pitch up/down \n");
  283.      printf("                </>  - yaw left/right \n");
  284.      printf("                n/m  - roll left/right \n");
  285.      printf("                =/-  - move hither plane forwards/back \n");
  286.      printf("\n");
  287.      printf("                q    - quit \n");
  288.      printf("\n");
  289.      printf("                Press any key to continue \n");
  290.      ch=getch();
  291.  
  292. //   Read in vertex data
  293.      if ((fp=fopen("points.dat","r"))==NULL)
  294.      {
  295.       puts("Can't open points.dat");
  296.       exit(0);
  297.      }
  298.      for (c=0; c<18; c++)
  299.      {
  300.       fscanf(fp,"%f %f %f \n",&vertex[c].xw,&vertex[c].yw,&vertex[c].zw);
  301.      }
  302.      fclose(fp);
  303. //   Move to z=500
  304.      for (c=0; c<18; c++)
  305.       vertex[c].zw=vertex[c].zw+500;
  306.  
  307. //   Read in face data
  308.      if ((fp=fopen("faces.dat","r"))==NULL)
  309.      {
  310.       puts("Can't open faces.dat");
  311.       exit(0);
  312.      }
  313.      for (c=0; c<13; c++)
  314.      for (c2=0; c2<6; c2++)
  315.          fscanf(fp,"%d", &faces[c][c2]);
  316.      fclose(fp);
  317.  
  318.      initialise_graphics();
  319.  
  320.      translate(-500,-400,0,w2v);
  321.      rotate_y((PI/5.0),temp);
  322.      mult_4x4(w2v,temp,temp2);
  323.      rotate_x(-PI/6,temp);
  324.      mult_4x4(temp2,temp,w2v);
  325.  
  326.      transform(w2v);
  327.      draw_picture();
  328.      do
  329.      {
  330.        ch=getch();
  331.        switch (ch)
  332.        {
  333.        case '8': {
  334.                translate(0,0,-10,temp);
  335.                mult_4x4(w2v,temp,temp2);
  336.                copy_4x4(temp2,w2v);
  337.                break;
  338.              };
  339.        case    '2': {
  340.                translate(0,0,10,temp);
  341.                mult_4x4(w2v,temp,temp2);
  342.                copy_4x4(temp2,w2v);
  343.                break;
  344.              };
  345.        case    '4': {
  346.                translate(10,0,0,temp);
  347.                mult_4x4(w2v,temp,temp2);
  348.                copy_4x4(temp2,w2v);
  349.                break;
  350.              };
  351.        case    '6': {
  352.                translate(-10,0,0,temp);
  353.                mult_4x4(w2v,temp,temp2);
  354.                copy_4x4(temp2,w2v);
  355.                break;
  356.              };
  357.        case    '1': {
  358.                translate(0,10,0,temp);
  359.                mult_4x4(w2v,temp,temp2);
  360.                copy_4x4(temp2,w2v);
  361.                break;
  362.              };
  363.        case    '7': {
  364.                translate(0,-10,0,temp);
  365.                mult_4x4(w2v,temp,temp2);
  366.                copy_4x4(temp2,w2v);
  367.                break;
  368.              };
  369.        case    ',': {
  370.                rotate_y(PI/180.0,temp);
  371.                mult_4x4(w2v,temp,temp2);
  372.                copy_4x4(temp2,w2v);
  373.                break;
  374.              };
  375.        case    '.': {
  376.                rotate_y(-PI/180.0,temp);
  377.                mult_4x4(w2v,temp,temp2);
  378.                copy_4x4(temp2,w2v);
  379.                break;
  380.              };
  381.        case    'm': {
  382.                rotate_z(PI/180.0,temp);
  383.                mult_4x4(w2v,temp,temp2);
  384.                copy_4x4(temp2,w2v);
  385.                break;
  386.              };
  387.        case    'n': {
  388.                rotate_z(-PI/180.0,temp);
  389.                mult_4x4(w2v,temp,temp2);
  390.                copy_4x4(temp2,w2v);
  391.                break;
  392.              };
  393.        case    'o': {
  394.                rotate_x(PI/180.0,temp);
  395.                mult_4x4(w2v,temp,temp2);
  396.                copy_4x4(temp2,w2v);
  397.                break;
  398.              };
  399.        case    'l': {
  400.                rotate_x(-PI/180.0,temp);
  401.                mult_4x4(w2v,temp,temp2);
  402.                copy_4x4(temp2,w2v);
  403.                break;
  404.              };
  405.        case    '=': hither=hither+10; break;
  406.        case    '-': hither=hither-10; break;
  407.        };
  408.        transform(w2v);
  409.        draw_picture();
  410.      }
  411.      while (ch!='q');
  412.      closegraph();
  413. }