home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 March / macformat-022.iso / Shareware City / Graphics / SPD / Sources / gears.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-10  |  7.8 KB  |  241 lines  |  [TEXT/R*ch]

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