home *** CD-ROM | disk | FTP | other *** search
/ gondwana.ecr.mu.oz.au/pub/ / Graphics.tar / Graphics / SPD.3.0.shar.gz / SPD.3.0.shar / gears.c < prev    next >
C/C++ Source or Header  |  1991-01-13  |  7KB  |  231 lines

  1. /*
  2.  * gears.c - Create a set of gears.  Each gear face has 144 vertices, and
  3.  *    contains concavities.  Note that the first 3 vertices of all polygons
  4.  *    define the two edges of a convex section of the polygon.  Background
  5.  *    square floor is reflective.  Five light sources.  
  6.  *
  7.  * Author:  Eric Haines, 3D/Eye, Inc.
  8.  *
  9.  * SizeFactor determines the number of polygons output.
  10.  *    Total gears = SF**3:  concave polygons = 2 * SF**3
  11.  *    rectangles = 4*TEETH * SF**3
  12.  *
  13.  *    SizeFactor    # gears       # gear faces    # rectangles
  14.  *         1            1          2        144
  15.  *         2            8         16           1152
  16.  *         3           27         54           3888
  17.  *
  18.  *         4           64        128           9216
  19.  */
  20.  
  21. #include <stdio.h>
  22. #include <math.h>
  23. #include "def.h"
  24. #include "lib.h"
  25.  
  26. static    int    SizeFactor = 4 ;
  27.  
  28. /* define number of teeth on a gear - must be a multiple of 4 */
  29. #define    TEETH            36
  30. /* define ratio of radius taken up by teeth and the gear thickness */
  31. /* the outer radius is made slightly smaller that the full radius to create
  32.  * a finite separation between intermeshing gears.  This gets rid of the bug
  33.  * of having two surfaces occupy exactly the same space.  Note that if these
  34.  * are changed, the gears may interpenetrate.
  35.  */
  36. #define    OUTER_EDGE_RATIO    0.995
  37. #define    INNER_EDGE_RATIO    0.9
  38. #define    EDGE_DIFF        ( 1.0 - INNER_EDGE_RATIO )
  39. /* ratio of width of gear to thickness */
  40. #define    DEPTH_RATIO        0.1
  41.  
  42. main(argc,argv)
  43. int    argc ;
  44. char    *argv[] ;
  45. {
  46. int    ix, iy, iz ;
  47. double    angle, color_scale, outer_radius, thickness ;
  48. COORD3    back_color, gear_color ;
  49. COORD3    from, at, up ;
  50. COORD3    ground[4], light, offset, zero_pt, center ;
  51.  
  52.     if ( !lib_get_size( argc, argv, &SizeFactor ) ) {
  53.     fprintf( stderr, "usage: %s [size]\n", *argv ) ;
  54.     exit(EXIT_FAIL) ;
  55.     }
  56.  
  57.     /* output viewpoint */
  58.     SET_COORD3( from, -1.1, -2.1, 2.6 ) ;
  59.     SET_COORD3( at, 0.0, 0.0, 0.0 ) ;
  60.     SET_COORD3( up, 0.0, 0.0, 1.0 ) ;
  61.     lib_output_viewpoint( from, at, up, 45.0, 1.0, 512, 512 ) ;
  62.  
  63.     /* output background color - UNC sky blue */
  64.     SET_COORD3( back_color, 0.078, 0.361, 0.753 ) ;
  65.     lib_output_background_color( back_color ) ;
  66.  
  67.     /* output light sources */
  68.     SET_COORD3( light, 2.0, 4.0, 4.0 ) ;
  69.     lib_output_light( light ) ;
  70.     SET_COORD3( light, -2.0, 4.0, 3.0 ) ;
  71.     lib_output_light( light ) ;
  72.     SET_COORD3( light, 2.0, -2.5, 2.5 ) ;
  73.     lib_output_light( light ) ;
  74.     SET_COORD3( light, -1.0, -4.0, 2.0 ) ;
  75.     lib_output_light( light ) ;
  76.     /* just behind the eye */
  77.     SET_COORD3( light, -1.111, -2.121, 2.626 ) ;
  78.     lib_output_light( light ) ;
  79.  
  80.     /* output ground polygon - off white */
  81.     SET_COORD3( back_color, 1.0, 0.85, 0.7 ) ;
  82.     lib_output_color( back_color, 0.75, 0.25, 25.0, 0.0, 0.0 ) ;
  83.     SET_COORD3( ground[0], 2.0, 2.0, 0.0 ) ;
  84.     SET_COORD3( ground[1], -2.0, 2.0, 0.0 ) ;
  85.     SET_COORD3( ground[2], -2.0, -2.0, 0.0 ) ;
  86.     SET_COORD3( ground[3], 2.0, -2.0, 0.0 ) ;
  87.     lib_output_polygon( 4, ground ) ;
  88.  
  89.     outer_radius = 1.0 /
  90.     ( (double)SizeFactor - (double)(SizeFactor-1) * EDGE_DIFF / 2.0 ) ;
  91.     /* calculate first gear center */
  92.     zero_pt[X] = zero_pt[Y] = -1.0 + outer_radius ;
  93.     zero_pt[Z] = 1.0 ;
  94.     /* calculate offset */
  95.     offset[X] = offset[Y] = outer_radius * ( 2.0 - EDGE_DIFF ) ;
  96.     offset[Z] = -1.0 / (double)SizeFactor ;
  97.  
  98.     /* create gears */
  99.     for ( iz = 0 ; iz < SizeFactor ; ++iz ) {
  100.     center[Z] = zero_pt[Z] + (double)iz * offset[Z] ;
  101.     for ( iy = 0 ; iy < SizeFactor ; ++iy ) {
  102.         center[Y] = zero_pt[Y] + (double)iy * offset[Y] ;
  103.         for ( ix = 0 ; ix < SizeFactor ; ++ix ) {
  104.         center[X] = zero_pt[X] + (double)ix * offset[X] ;
  105.  
  106.         /* output pseudo-random gear color */
  107.         SET_COORD3( gear_color
  108.               , 0.01 + FRACTION( (double)(ix*3+iy*2+iz+1)*5.0/7.0 )
  109.               , 0.01 + FRACTION( (double)(iy*3+iz*2+ix+1)*3.0/7.0 )
  110.               , 0.01 + FRACTION( (double)(iz*3+ix*2+iy+1)*2.0/7.0 )
  111.               ) ;
  112.         color_scale = MAX_COORD3( gear_color ) ;
  113.         gear_color[X] /= color_scale ;
  114.         gear_color[Y] /= color_scale ;
  115.         gear_color[Z] /= color_scale ;
  116.         if ( ( ix*4 + iy*2 + iz ) % 5 == 0 ) {
  117.             lib_output_color( gear_color,
  118.                         0.75, 0.25, 50.0, 0.95, 1.1 ) ;
  119.         }
  120.         else {
  121.             lib_output_color( gear_color,
  122.                         1.0, 0.0, 0.0, 0.0, 0.0 ) ;
  123.         }
  124.  
  125.         /* output gear */
  126.         angle = PI * (double)( (ix+iy+iz) % 2 ) / (double)(TEETH) ;
  127.         thickness =
  128.             MIN( DEPTH_RATIO, 1.0 / ( 2.0 * (double)SizeFactor ) ) ;
  129.         create_gear( center,
  130.                  angle,
  131.                  OUTER_EDGE_RATIO * outer_radius,
  132.                  (1.0 - EDGE_DIFF) * outer_radius,
  133.                  thickness ) ;
  134.         }
  135.     }
  136.     }
  137.     exit(EXIT_SUCCESS) ;
  138. }
  139.  
  140. /* Create gear */
  141. create_gear( center, offset_angle, outer_radius, inner_radius, thickness )
  142. COORD3    center ;
  143. double    offset_angle ;
  144. double    outer_radius ;
  145. double    inner_radius ;
  146. double    thickness ;
  147. {
  148. int    next_side, num_side, num_teeth ;
  149. double    gear_angle, tooth_angle ;
  150. COORD3    side_pts[4], gear_pts[4*TEETH], outer_pt, inner_pt ;
  151.  
  152.     SET_COORD3( outer_pt, outer_radius, 0.0, 0.0 ) ;
  153.     SET_COORD3( inner_pt, inner_radius, 0.0, 0.0 ) ;
  154.  
  155.     tooth_angle = 2.0 * PI / (double)TEETH ;
  156.  
  157.     /* output gear top */
  158.     for ( num_teeth = 0 ; num_teeth < TEETH ; ++num_teeth ) {
  159.     gear_angle = offset_angle +
  160.         2.0 * PI * (double)num_teeth / (double)TEETH ;
  161.     create_tooth( gear_angle
  162.             , tooth_angle
  163.             , center
  164.             , outer_pt
  165.             , inner_pt
  166.             , (COORD3 *)gear_pts[num_teeth*4]
  167.             ) ;
  168.     }
  169.     lib_output_polygon( 4*TEETH, gear_pts ) ;
  170.  
  171.     /* output teeth */
  172.     for ( num_side = 0 ; num_side < 4 * TEETH ; ++num_side ) {
  173.     next_side = ( num_side + 1 ) % ( 4 * TEETH ) ;
  174.     COPY_COORD3( side_pts[0], gear_pts[num_side] ) ;
  175.     COPY_COORD3( side_pts[1], gear_pts[num_side] ) ;
  176.     side_pts[1][Z] -= thickness ;
  177.     COPY_COORD3( side_pts[2], gear_pts[next_side] ) ;
  178.     side_pts[2][Z] -= thickness ;
  179.     COPY_COORD3( side_pts[3], gear_pts[next_side] ) ;
  180.     lib_output_polygon( 4, side_pts ) ;
  181.     }
  182.  
  183.     /* output gear bottom */
  184.     outer_pt[Z] = inner_pt[Z] = -thickness ;
  185.     for ( num_teeth = 0 ; num_teeth < TEETH ; ++num_teeth ) {
  186.     gear_angle = offset_angle -
  187.         2.0 * PI * (double)num_teeth / (double)TEETH ;
  188.     create_tooth( gear_angle
  189.             , -tooth_angle
  190.             , center
  191.             , outer_pt
  192.             , inner_pt
  193.             , (COORD3 *)gear_pts[num_teeth*4]
  194.             ) ;
  195.     }
  196.     lib_output_polygon( 4*TEETH, gear_pts ) ;
  197. }
  198.  
  199. /* Create gear tooth */
  200. create_tooth( gear_angle, tooth_angle, center, outer_pt, inner_pt, edge_pts )
  201. double    gear_angle ;
  202. double    tooth_angle ;
  203. COORD3    center ;
  204. COORD3    outer_pt ;
  205. COORD3    inner_pt ;
  206. COORD3    edge_pts[] ;
  207. {
  208. MATRIX    mx ;
  209.  
  210.     lib_create_rotate_matrix( mx
  211.                 , Z_AXIS
  212.                 , gear_angle - 0.19 * tooth_angle ) ;
  213.     lib_transform_coord( edge_pts[0], outer_pt, mx ) ;
  214.     ADD2_COORD3( edge_pts[0], center ) ;
  215.     lib_create_rotate_matrix( mx
  216.                 , Z_AXIS
  217.                 , gear_angle + 0.19 * tooth_angle ) ;
  218.     lib_transform_coord( edge_pts[1], outer_pt, mx ) ;
  219.     ADD2_COORD3( edge_pts[1], center ) ;
  220.     lib_create_rotate_matrix( mx
  221.                 , Z_AXIS
  222.                 , gear_angle + 0.3 * tooth_angle ) ;
  223.     lib_transform_coord( edge_pts[2], inner_pt, mx ) ;
  224.     ADD2_COORD3( edge_pts[2], center ) ;
  225.     lib_create_rotate_matrix( mx
  226.                 , Z_AXIS
  227.                 , gear_angle + 0.7 * tooth_angle ) ;
  228.     lib_transform_coord( edge_pts[3], inner_pt, mx ) ;
  229.     ADD2_COORD3( edge_pts[3], center ) ;
  230. }
  231.