home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / programm.ing / spin3d.lzh / SPIN5.C < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-29  |  8.9 KB  |  299 lines

  1. /*   *** SPIN5.C ***
  2.      ***************
  3.      Will spin ==========>  A triangle in 3 space <===============
  4.              
  5.      This uses the code from SPIN4.c PLUS it implements 
  6.      PERSPECTIVE VIEWING.
  7.  
  8.     
  9.      Perspective Viewing 
  10.      -------------------
  11.      Lets assume a righ-handed coord system, with horizontal 
  12.      screen the x axis, vertical screen the Y axis and the positive
  13.      z axis sticking out of the screen.
  14.  
  15.      In all the other programs,we have been using what is called
  16.      PARALLEL projections, you can't tell depth from them. To be 
  17.      exact, we have been using Orthographic projections(a subset of 
  18.      Parallel projections) All we had to do is drop the z coord
  19.      to project onto the xy axis, or drop the x coord to project
  20.      onto the yz axis, etc. 
  21.  
  22.      But what if we want more realism?? We use Perspective projections of course!
  23.      The basic idea behind it that if a point has a small z coordinate value, it is 
  24.      further away from the viewer, and hence smaller. This gives the illusion of 'depth'
  25.      
  26.       To do this we could just divide x and y by the z value, but this gives a rather
  27.       strange effect. You will notice that the CRT(screen) is some distance 'd' away from
  28.       your eyes, we need to take this into account.
  29.  
  30.       Let 'pdist' = distance from your eyes to the screen(in pixels) a good value is around 200
  31.        
  32.       Then the equations we need are:
  33.  
  34.             x' = (x / (z+pdist)) * pdist
  35.             y' = (y / (z+pdist)) * pdist
  36.      
  37.          z + pdist moves your view(eye) away from the middle of the object
  38.          to a distance 'pdist' away from it.
  39.  
  40.  
  41.                  So lets try this out!!
  42.  
  43.                        March 28 ,1994  jeff bilger 
  44.                          jbilger@cs.tamu.edu
  45.  
  46. */
  47.  
  48.                         /* define our perspective stuff */
  49. float pdist= 200.;
  50.  
  51. #define perx(p) \
  52.         (perspective ? ((p.x/(p.z+pdist))*pdist):p.x)
  53. #define pery(p) \
  54.         (perspective ? ((p.y/(p.z+pdist))*pdist):p.y)
  55.  
  56.  
  57.  
  58. #include <math.h>
  59. #include <linea.h>
  60. #include <osbind.h>
  61. int pts[4][2] = { 
  62.     320, 050,
  63.     120, 150,
  64.     520, 150,
  65.     320, 050
  66. };
  67. lineaport *theport;
  68.  
  69. long mu_global_s();                     /* prototype, tells our 
  70.                                           Assembly language function
  71.                                            to return a long int  */
  72. long mu_global_c();  /* multiply 32 bit global w/ a precomputed sin or cos value */
  73.  
  74.  
  75. #define SCALE 2048L       /* so far 2048 is the upper bounds scale
  76.                               i can get W/O overflow */
  77. #define BITSH 11        /* what to shift (ie DIVIDE) by. this number
  78.                            2^11 = 2048 */
  79.  
  80.  
  81. typedef struct {long x,y,z;} point3d;   /* our faithful structure that defines a point in 3 space*/
  82.  
  83.           
  84. /* these are used to allocate size of arrays */
  85. #define NPTS   25                 /* max allowable points */
  86. #define NLINES 50                
  87. #define NFACES 50                
  88.  
  89.  
  90. #define I ( SCALE  )           /* set up a SCALE factor */
  91.  
  92. point3d point_[NPTS] =         /* define our triangle in 3d */
  93.         { 
  94.           I,I,I,     3*I,I,I, 2*I,I,-I,  2*I,-I,I/2,
  95.  },
  96.         drawpt1[NPTS],drawpt2[NPTS];     /* for fast draw/erasing look up */
  97.  
  98.  
  99.  
  100. int 
  101.     npts  = 4,         /* linefrom, lineto for drawing lines */                                                                                            
  102.     linefrom[NLINES] = {0,1,2,0,1,2},     /* set up lines to draw */
  103.     lineto[NLINES]   = {1,2,0,3,3,3}, 
  104.     nlines = 6,         /* number of lines */
  105.     x_offset=320,       /* for viewport mapping */
  106.     y_offset=100,
  107.     z_offset=1;
  108.  
  109. long cos_2=2048;    /* cos of 3 degrees * scale of 2048 */
  110. long sin_2=107;     /* sin of 3 degrees * scale of 2048 */
  111.  
  112. main()
  113. {
  114. register int i,j;   /* use em for FOR loops */
  115. point3d pointi;     /* declare one instance of our point3d struct */
  116. int color =1;       /* color to draw triangle */
  117. char com;           /* for user input */
  118.  
  119.  
  120. puts("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
  121. puts("1-Spin Y  2-Spin X  3-Spin Z  9-Quit\n");
  122.  
  123. theport = a_init();                   /* line a invokage */    
  124.     theport -> plane0 = 1;
  125.     theport -> plane1 = 0;
  126.     theport -> plane2 = 0;
  127.     theport -> plane3 = 0;
  128.  
  129.  
  130.    
  131. for(i=0;i<nlines;i++)  /* set up points-to-connect lookup table*/
  132. { drawpt1[i] = point_[linefrom[i]];
  133.   drawpt2[i] = point_[lineto[i]];  
  134. }
  135.  
  136. com = 0x32;                       /* set to spin about x */
  137.  
  138. while( com != 0x39)
  139. {
  140. if( Bconstat(2) )       /* if keypress */
  141.  com = Bconin(2);       /* get input */
  142.  
  143.  
  144.                                   /* The main loop */
  145.  for(i=0;i<npts;i++)
  146.    {
  147.    pointi = point_[i];        /* get current point data. We do this for efficiency, since we will use this value many times within one loop
  148.                                  it's more efficient to compute it's value only once */
  149.    
  150.     if(com == 0x31) {              /* spin y */
  151.                point_[i].x =( mu_global_c(pointi.x)  -
  152.                               mu_global_s(pointi.z))>>BITSH; /* since our points are scaled AND or trig angles, sin&cos values are scaled we must divide by scale once here*/
  153.                point_[i].z =( mu_global_s(pointi.x) +
  154.                               mu_global_c(pointi.z))>>BITSH;
  155.  
  156.                     }
  157.     if(com == 0x32) {              /* spin x */
  158.                 point_[i].y =( mu_global_c(pointi.y)  +
  159.                                mu_global_s(pointi.z))>>BITSH;
  160.                 point_[i].z =( -(mu_global_s(pointi.y)) +
  161.                                  mu_global_c(pointi.z))>>BITSH;
  162.                     }
  163.     if(com == 0x33) {              /* spin z */
  164.                 point_[i].x =( mu_global_c(pointi.x)  +
  165.                                mu_global_s(pointi.y))>>BITSH;
  166.                 point_[i].y =( mu_global_c(pointi.y)  -
  167.                                mu_global_s(pointi.x))>>BITSH;
  168.                     }
  169.   
  170.  
  171.    }
  172.  
  173.                               /* draw and erase triangle */
  174.   for(i=0;i<nlines;i++)
  175.    { draw3dline(drawpt1[i],drawpt2[i],0);  /*erase */
  176.      draw3dline(drawpt1[i]=point_[linefrom[i]],drawpt2[i]=point_[lineto[i]],color);
  177.      /* draw it */
  178.   }
  179.    
  180.  
  181. }/* end of while */
  182.  
  183.  
  184.  
  185. } /* end of main */
  186.  
  187. /*******************************/
  188.  
  189. draw3dline(p1,p2,color)
  190. point3d p1,p2;
  191. int color;
  192. {
  193.  int x1,y1,x2,y2,z1,z2;
  194.   
  195.  
  196.  x1 = p1.x >>BITSH-5;        /* scale down the coords */
  197.  y1 = p1.y >>BITSH-5;
  198.  x2 = p2.x >>BITSH-5;
  199.  y2 = p2.y >>BITSH-5;
  200.  z1 = p1.z >>BITSH-5;
  201.  z2 = p2.z >>BITSH-5;
  202.  
  203.  
  204.  /* project onto the xy plane */
  205.  
  206.             /* compute the perspective view */
  207.  x1 = (float)((x1/(z1+pdist)) * pdist);
  208.  y1 = (float)((y1/(z1+pdist)) * pdist);
  209.  x2 = (float)((x2/(z2+pdist)) * pdist);
  210.  y2 = (float)((y2/(z2+pdist)) * pdist);
  211.  
  212.  
  213. /* add viewport transformation */
  214. x1 +=x_offset;
  215. y1 +=y_offset;
  216. x2 +=x_offset;
  217. y2 +=y_offset; 
  218.  
  219. theport -> plane0 = color;
  220.  
  221.  
  222. a_line(x1,y1,x2,y2);
  223.  
  224. }
  225.  
  226.  
  227.  
  228. /***************************************************************/
  229. /* We will now modify the assembly mult. routine to be as efficient
  230.    as possible. We will make 2 mult. routines, one to multiply 
  231.    by a precomputed SINE value, and one to multiply by a precomputed
  232.    COSINE value
  233.    ************************************************************/
  234.  
  235. /*******************************************************/
  236. /* Multiply 1 16 bit(GLOBAL) SIGNED number b by a precomputed 
  237.    SINE value of 3 degrees (then the sine value was * SCALE where
  238.    scale was 2048 )
  239.  
  240.   and return the 32 bit result in D0
  241.  
  242.    *** BIG NOTE:: b MUST be a GLOBAL var!!!!!!!!!!!!!!!!!
  243.  
  244.    * WARNING * No test is made on the overflow bit (V) to see if 
  245.                the result in c is indeed correct. 
  246.  
  247.    Send arguments to this prodecure by: c=multiply(b) 
  248. */
  249.  
  250. long mu_global_s(b)
  251. register long b;  /* extern variables so b is placed in D7,*/          
  252. {
  253.  asm
  254.     { 
  255.   
  256.       muls   #107,b    /* generates  muls #107,d7 */
  257.       move.l b,D0  /* generates   move.l A7,(A5) */
  258.                     /* Note: You MUST specify the size (.l) cause
  259.                              if you just write 'move b,d0' Laser
  260.                              C will assume move.w as the default */
  261.      
  262.     }
  263.  
  264. }
  265.  
  266. /*************************************************
  267.  multiplies a number 'b' by a precomputed COSINE value
  268.  The Cos value is ===> cosine of 2 degrees * SCALE factor
  269.  where scale factor is defined. In our case the precomputed cos value 
  270.  is 2045 */
  271.  
  272. long mu_global_c(b)
  273. register long b;  /* extern variable so b is placed in D7*/
  274. {
  275.  asm
  276.     { 
  277.   
  278.       muls   #2045,b    /* generates  muls #2045,d7 */
  279.       move.l b,D0  /* generates   move.l A7,(A5) */
  280.                     /* Note: You MUST specify the size (.l) cause
  281.                              if you just write 'move b,d0' Laser
  282.                              C will assume move.w as the default */
  283.      
  284.     }
  285.  
  286. }
  287.  
  288.  
  289.  
  290. di(a,b)
  291. register long int a,b;
  292. {
  293.  asm
  294.     {
  295.      move.l a,D0
  296.      move.l b,D1
  297.     }
  298. }
  299.