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

  1. /*
  2.  * balls.c - Also known as "sphereflake".  Create a set of shiny spheres, with
  3.  *    each sphere blooming sets of 9 more spheres with 1/3rd radius.
  4.  *    A square floor polygon is added.  Three light sources.
  5.  *
  6.  * Author:  Eric Haines, 3D/Eye, Inc.
  7.  *
  8.  * size_factor determines the number of objects output.
  9.  *    Total spheres = sum of n=0,SF of (9**SF).
  10.  *
  11.  *    size_factor    # spheres    # squares
  12.  *         1            10             1
  13.  *         2            91             1
  14.  *         3           820             1
  15.  *
  16.  *         4          7381             1
  17.  */
  18.  
  19. #include <stdio.h>
  20. #include <math.h>
  21. #include <stdlib.h>    /* atoi */
  22. #include "def.h"
  23. #include "drv.h"    /* display_close() */
  24. #include "lib.h"
  25.  
  26. /* These may be read from the command line */
  27. static int size_factor      = 4;
  28. static int raytracer_format = OUTPUT_RT_DEFAULT;
  29. static int output_format    = OUTPUT_CURVES;
  30.  
  31.  
  32. #ifdef OUTPUT_TO_FILE
  33. static FILE * stdout_file = NULL;
  34. #else
  35. #define stdout_file stdout
  36. #endif /* OUTPUT_TO_FILE */
  37.  
  38. static    COORD4    objset[9] ;
  39.  
  40. /*
  41.  * Output the parent sphere, then output the children of the sphere.
  42.  * Uses global 'objset'.
  43.  */
  44. void
  45. output_object(depth, center, direction)
  46.     int depth;
  47.     COORD4 center, direction;
  48. {
  49.     double  angle;
  50.     COORD4  axis, z_axis;
  51.     COORD4  child_pt, child_dir;
  52.     MATRIX  mx;
  53.     long    num_vert;
  54.     double  scale;
  55.  
  56.     PLATFORM_MULTITASK();
  57.  
  58.     /* output sphere at location & radius defined by center */
  59.     lib_output_sphere(center, output_format);
  60.  
  61.     /* check if children should be generated */
  62.     if (depth > 0) {
  63.     --depth ;
  64.  
  65.     /* rotation matrix to new axis from +Z axis */
  66.     if ( direction[Z] >= 1.0 ) {
  67.         /* identity matrix */
  68.         lib_create_identity_matrix(mx);
  69.         }
  70.     else if ( direction[Z] <= -1.0 ) {
  71.         lib_create_rotate_matrix(mx, Y_AXIS, PI);
  72.         }
  73.     else {
  74.         SET_COORD3(z_axis, 0.0, 0.0, 1.0);
  75.         CROSS(axis, z_axis, direction);
  76.         lib_normalize_vector(axis);
  77.         angle = acos((double)DOT_PRODUCT(z_axis, direction));
  78.         lib_create_axis_rotate_matrix(mx, axis, angle);
  79.         }
  80.  
  81.     /* scale down location of new spheres */
  82.     scale = center[W] * (1.0 + direction[W]);
  83.  
  84.     for ( num_vert = 0 ; num_vert < 9 ; ++num_vert ) {
  85.         lib_transform_coord(child_pt, objset[num_vert], mx);
  86.         child_pt[X] = child_pt[X] * scale + center[X];
  87.         child_pt[Y] = child_pt[Y] * scale + center[Y];
  88.         child_pt[Z] = child_pt[Z] * scale + center[Z];
  89.         /* scale down radius */
  90.         child_pt[W] = center[W] * direction[W];
  91.         SUB3_COORD3( child_dir, child_pt, center);
  92.         child_dir[X] /= scale;
  93.         child_dir[Y] /= scale;
  94.         child_dir[Z] /= scale;
  95.         child_dir[W] = direction[W];
  96.         output_object(depth, child_pt, child_dir);
  97.     }
  98.     }
  99. }
  100.  
  101. /* Create the set of 9 vectors needed to generate the sphere set. */
  102. /* Uses global 'objset' */
  103. void
  104. create_objset()
  105. {
  106.     COORD4  axis, temp_pt, trio_dir[3];
  107.     double  dist;
  108.     MATRIX  mx;
  109.     long    num_set, num_vert;
  110.  
  111.     dist = 1.0 / sqrt((double)2.0);
  112.  
  113.     SET_COORD4(trio_dir[0], dist, dist,   0.0, 0.0);
  114.     SET_COORD4(trio_dir[1], dist,  0.0, -dist, 0.0);
  115.     SET_COORD4(trio_dir[2],  0.0, dist, -dist, 0.0);
  116.  
  117.     SET_COORD3(axis, 1.0, -1.0, 0.0);
  118.     lib_normalize_vector(axis);
  119.     lib_create_axis_rotate_matrix(mx, axis,
  120.                   asin((double)(2.0/sqrt((double)6.0))));
  121.  
  122.     for (num_vert=0;num_vert<3;++num_vert) {
  123.     lib_transform_coord(temp_pt, trio_dir[num_vert], mx);
  124.     COPY_COORD4(trio_dir[num_vert], temp_pt);
  125.     }
  126.  
  127.     for (num_set=0;num_set<3;++num_set) {
  128.     lib_create_rotate_matrix(mx, Z_AXIS, num_set*2.0*PI/3.0);
  129.     for (num_vert=0;num_vert<3;++num_vert) {
  130.         lib_transform_coord(objset[num_set*3+num_vert],
  131.                 trio_dir[num_vert], mx);
  132.     }
  133.     }
  134. }
  135.  
  136. int
  137. main(argc,argv)
  138.     int argc ;
  139.     char *argv[] ;
  140. {
  141.     COORD3 back_color, obj_color;
  142.     COORD3 backg[5], bvec;
  143.     COORD3 from, at, up;
  144.     COORD4 light;
  145.     COORD4 center_pt, direction;
  146.     double radius, lscale;
  147.  
  148.     PLATFORM_INIT(SPD_BALLS);
  149.  
  150.     /* Start by defining which raytracer we will be using */
  151.     if ( lib_gen_get_opts( argc, argv,
  152.             &size_factor, &raytracer_format, &output_format ) ) {
  153.     return EXIT_FAIL;
  154.     }
  155.  
  156.     if ( lib_open( raytracer_format, "Balls.out" ) ) {
  157.     return EXIT_FAIL;
  158.     }
  159.  
  160.     /* set radius of sphere which would enclose entire object */
  161.     radius = 1.0 ;
  162.  
  163.     /* output background color - UNC sky blue */
  164.     /* NOTE: Do this BEFORE lib_output_viewpoint(), for display_init() */
  165.     SET_COORD3(back_color, 0.078, 0.361, 0.753);
  166.     lib_output_background_color(back_color);
  167.  
  168.     /* output viewpoint */
  169.     SET_COORD3(from, 2.1, 1.3, 1.7);
  170.     SET_COORD3(at, 0.0, 0.0, 0.0);
  171.     SET_COORD3(up, 0.0, 0.0, 1.0);
  172.     lib_output_viewpoint(from, at, up, 45.0, 1.0, 0.01, 512, 512);
  173.  
  174.     /* For raytracers that don't scale the light intensity, we will do
  175.        it for them */
  176.     lscale = ( ((raytracer_format == OUTPUT_NFF) ||
  177.            (raytracer_format == OUTPUT_RTRACE)) ? 1.0 : 1.0 / sqrt(3.0));
  178.  
  179.     /* output light sources */
  180.     SET_COORD4(light, 4.0, 3.0, 2.0, lscale);
  181.     lib_output_light(light);
  182.     SET_COORD4(light, 1.0, -4.0, 4.0, lscale);
  183.     lib_output_light(light);
  184.     SET_COORD4(light, -3.0, 1.0, 5.0, lscale);
  185.     lib_output_light(light);
  186.  
  187.     /* output floor polygon - beige */
  188.     SET_COORD3(back_color, 1.0, 0.75, 0.33);
  189.     lib_output_color(NULL, back_color, 0.2, 0.8, 0.0, 0.0, 0.0, 0.0, 1.0);
  190.     SET_COORD3(bvec, 12.0 * radius, 12.0 * radius, -radius / 2.0);
  191.     SET_COORD3(backg[0],  bvec[X],  bvec[Y], bvec[Z]);
  192.     SET_COORD3(backg[1], -bvec[X],  bvec[Y], bvec[Z]);
  193.     SET_COORD3(backg[2], -bvec[X], -bvec[Y], bvec[Z]);
  194.     SET_COORD3(backg[3],  bvec[X], -bvec[Y], bvec[Z]);
  195.     SET_COORD3(backg[4],  bvec[X],  bvec[Y], bvec[Z]);
  196.     lib_output_polygon(4, backg);
  197.  
  198.     /* set up object color - mirrored */
  199.     SET_COORD3(obj_color, 1.0, 0.9, 0.7);
  200.     lib_output_color(NULL, obj_color, 0.0, 0.5, 0.5, 0.5, 5.0, 0.0, 1.0);
  201.  
  202.     /* create set of spawned points */
  203.     create_objset();
  204.  
  205.     /* compute and output object */
  206.     SET_COORD4(center_pt, 0.0, 0.0, 0.0, radius / 2.0);
  207.     SET_COORD4(direction, 0.0, 0.0, 1.0, 1.0/3.0);
  208.     output_object(size_factor, center_pt, direction);
  209.  
  210.     lib_close();
  211.  
  212.     PLATFORM_SHUTDOWN();
  213.     return EXIT_SUCCESS;
  214. }
  215.