home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1996 September / macformat-041.iso / mac / Shareware City / Graphics / MacSPD / Sources / gears.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-30  |  7.7 KB  |  236 lines  |  [TEXT/MMCC]

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