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

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