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 / mount.c < prev    next >
C/C++ Source or Header  |  1991-01-13  |  8KB  |  245 lines

  1. /*
  2.  * mount.c - creates a fractal mountain, using Carpenter's method with a
  3.  *    different extension to square grids.  A pyramid of 4 glass spheres
  4.  *    is added in front of the mountain.  One light source.
  5.  *
  6.  *    NOTE: the hashing function used to generate the database originally is
  7.  *    faulty.  The function causes repetition to occur within the fractal
  8.  *    mountain (obviously not very fractal behavior!).  A new hashing
  9.  *    function is included immediately after the old one:  merely define
  10.  *    NEW_HASH if you want to use a better hashing function.  To perform ray
  11.  *    tracing comparison tests you should still use the old, faulty database
  12.  *    (it may have repetition, but it's still a good test image).
  13.  *     
  14.  * Author:  Eric Haines, 3D/Eye, Inc.
  15.  *
  16.  * SizeFactor determines the number of objects output.
  17.  *    Total triangular polygons = 2 * (4**SizeFactor)
  18.  *
  19.  *    SizeFactor    # triangles    # spheres
  20.  *         1             8             4
  21.  *         2            32             4
  22.  *         3           128             4
  23.  *
  24.  *         6          8192             4
  25.  */
  26.  
  27. #include <stdio.h>
  28. #include <math.h>
  29. #include "def.h"
  30. #include "lib.h"
  31.  
  32. static    int    SizeFactor = 6 ;
  33.  
  34. #define    OUTPUT_FORMAT        OUTPUT_CURVES
  35.  
  36. /* to use the corrected hashing function, uncomment this next line */
  37. /* #define NEW_HASH */
  38.  
  39. /* fractal dimension - affects variance of z.  Between 2 and 3 */
  40. #define    FRACTAL_DIMENSION    2.2
  41. /* change MOUNTAIN_NO to get a different mountain */
  42. #define    MOUNTAIN_NO        21
  43.  
  44. /* lower left corner and width of mountain definitions */
  45. #define    X_CORNER    -1.0
  46. #define    Y_CORNER    -1.0
  47. #define    WIDTH         2.0
  48.  
  49. #ifndef NEW_HASH
  50.  
  51. /* Hashing function to get a seed for the random number generator. */
  52. /* This is the old, buggy hashing function - use it if you wish to
  53.  * obtain the same image as in the November 1987 IEEE CG&A article. */
  54. #define    hash_rand(A,B,C)    ( ( (((unsigned long)(A))<<(23-(C))) +    \
  55.                     (((unsigned long)(B))<<(15-(C)))    \
  56.                   + (((unsigned long)(A))<<(7-(C))) ) & 0xffff)
  57. #else
  58.  
  59. /* New, corrected hashing function.  Use for a true fractal mountain */
  60. /* 134456 is M1 in routine lib_gauss_rand() */
  61. #define    hash_rand(A,B,C)    ( ( C <= 15 ) ?                \
  62.                   ( ABSOLUTE(                \
  63.                     (((unsigned long)(A))<<(31-(C))) +    \
  64.                     (((unsigned long)(B))<<(15-(C))) )    \
  65.                   % 134456 ) :                \
  66.                   ( ABSOLUTE(                \
  67.                     (((unsigned long)(A))<<(31-(C))) +    \
  68.                     (((unsigned long)(B))>>((C)-15)) )    \
  69.                   % 134456 ) )
  70.                   )
  71. #endif
  72.  
  73. static  double    Roughness ;
  74.  
  75. main(argc,argv)
  76. int    argc ;
  77. char    *argv[] ;
  78. {
  79. int    num_pts ;
  80. double    ratio ;
  81. COORD3    back_color, obj_color ;
  82. COORD3    from, at, up, light ;
  83. COORD4    center ;
  84.  
  85.     if ( !lib_get_size( argc, argv, &SizeFactor ) ) {
  86.     fprintf( stderr, "usage: %s [size]\n", *argv ) ;
  87.     exit(EXIT_FAIL) ;
  88.     }
  89.  
  90.     /* output viewpoint */
  91.     SET_COORD3( from, -1.6, 1.6, 1.7 ) ;
  92.     SET_COORD3( at, 0.0, 0.0, 0.0 ) ;
  93.     SET_COORD3( up, 0.0, 0.0, 1.0 ) ;
  94.     lib_output_viewpoint( from, at, up, 45.0, 0.5, 512, 512 ) ;
  95.  
  96.     /* output background color - UNC sky blue */
  97.     SET_COORD3( back_color, 0.078, 0.361, 0.753 ) ;
  98.     lib_output_background_color( back_color ) ;
  99.  
  100.     /* output light sources */
  101.     SET_COORD3( light, -100.0, -100.0, 100.0 ) ;
  102.     lib_output_light( light ) ;
  103.  
  104.     /* set up crystal sphere color - clear white */
  105.     SET_COORD3( obj_color, 1.0, 1.0, 1.0 ) ;
  106.     lib_output_color( obj_color, 0.1, 0.9, 100.0, 0.9, 1.5 ) ;
  107.  
  108.     /* output crystal spheres */
  109.     SET_COORD4( center, -0.8, 0.8, 1.00, 0.17 ) ;
  110.     create_spheres( center ) ;
  111.  
  112.     /* set up mountain color - grey */
  113.     SET_COORD3( obj_color, 0.5, 0.45, 0.35 ) ;
  114.     lib_output_color( obj_color, 1.0, 0.0, 0.0, 0.0, 0.0 ) ;
  115.  
  116.     /* grow mountain */
  117.     num_pts = 1<<SizeFactor ;
  118.     ratio = 2.0 /
  119.         exp( (double)( log( (double)2.0 ) / (FRACTAL_DIMENSION-1.0) ) ) ;
  120.     Roughness = sqrt( (double)( SQR(ratio) - 1.0 ) ) ;
  121.     grow_mountain( (double)num_pts, num_pts, 0, 0, 0.0, 0.0, 0.0, 0.0 ) ;
  122.  
  123.     exit(EXIT_SUCCESS) ;
  124. }
  125.  
  126. /* create a pyramid of crystal spheres */
  127. create_spheres( center )
  128. COORD4    center ;
  129. {
  130. int    i ;
  131. double    angle ;
  132. COORD3    axis, pt, new_pt ;
  133. COORD4    sphere ;
  134. MATRIX    mx ;
  135.  
  136.     SET_COORD3( axis, 1.0, 1.0, 0.0 ) ;
  137.     (void)lib_normalize_vector( axis ) ;
  138.     angle = acos( (double)( -1.0/3.0 ) ) ;
  139.  
  140.     /* set center of pyramid */
  141.     SET_COORD3( pt, 0.0, 0.0, center[W] * sqrt( (double)( 3.0/2.0 ) ) ) ;
  142.  
  143.     COPY_COORD4( sphere, center ) ;
  144.     ADD2_COORD3( sphere, pt ) ;
  145.     lib_output_sphere( sphere, OUTPUT_FORMAT ) ;
  146.  
  147.     lib_create_axis_rotate_matrix( mx, axis, angle ) ;
  148.     lib_transform_vector( new_pt, pt, mx ) ;
  149.  
  150.     for ( i = 0 ; i < 3 ; ++i ) {
  151.     lib_create_rotate_matrix( mx, Z_AXIS, (double)i * 2.0 * PI / 3.0 ) ;
  152.     lib_transform_vector( sphere, new_pt, mx ) ;
  153.     ADD2_COORD3( sphere, center ) ;
  154.     lib_output_sphere( sphere, OUTPUT_FORMAT ) ;
  155.     }
  156. }
  157.  
  158. /*
  159.  * Build mountain section.  If at width > 1, split quadrilateral into four
  160.  * parts.  Else if at width == 1, output quadrilateral as two triangles.
  161.  */
  162. grow_mountain( fnum_pts, width, ll_x, ll_y, ll_fz, lr_fz, ur_fz, ul_fz )
  163. double    fnum_pts ;
  164. int    width ;
  165. int    ll_x ;
  166. int    ll_y ;
  167. double    ll_fz ;
  168. double    lr_fz ;
  169. double    ur_fz ;
  170. double    ul_fz ;
  171. {
  172. int    half_width, iz, num_tri, num_tri_vert, num_vert ;
  173. double    l_fx, r_fx, l_fy, u_fy ;
  174. double    lower_fz, right_fz, upper_fz, left_fz, middle_fz ;
  175. double    rise_height, hside_length ;
  176. COORD3    tri_vert[3] ;
  177.  
  178.     if ( width == 1 ) {
  179.     /* calculate x and y coordinates of corners */
  180.     l_fx = X_CORNER + (double)ll_x * WIDTH / fnum_pts ;
  181.     r_fx = X_CORNER + (double)(ll_x+1) * WIDTH / fnum_pts ;
  182.     l_fy = Y_CORNER + (double)ll_y * WIDTH / fnum_pts ;
  183.     u_fy = Y_CORNER + (double)(ll_y+1) * WIDTH / fnum_pts ;
  184.  
  185.     /* output two triangles for section */
  186.     for ( num_tri = 0 ; num_tri < 2 ; ++num_tri ) {
  187.         for ( num_vert = 0 ; num_vert < 3 ; ++num_vert ) {
  188.         num_tri_vert = ( num_vert + num_tri * 2 ) % 4 ;
  189.         switch ( num_tri_vert ) {
  190.         case 0:
  191.             SET_COORD3( tri_vert[num_vert], l_fx, l_fy, ll_fz ) ;
  192.             break ;
  193.         case 1:
  194.             SET_COORD3( tri_vert[num_vert], r_fx, l_fy, lr_fz ) ;
  195.             break ;
  196.         case 2:
  197.             SET_COORD3( tri_vert[num_vert], r_fx, u_fy, ur_fz ) ;
  198.             break ;
  199.         case 3:
  200.             SET_COORD3( tri_vert[num_vert], l_fx, u_fy, ul_fz ) ;
  201.             break ;
  202.         }
  203.         }
  204.         lib_output_polygon( 3, tri_vert ) ;
  205.     }
  206.     }
  207.  
  208.     else {
  209.     /* subdivide edges and move in z direction */
  210.     half_width = width>>1 ;
  211.     hside_length = (double)half_width * WIDTH / fnum_pts ;
  212.     rise_height = hside_length * Roughness ;
  213.  
  214.     /* for each midpoint, find z */
  215.     iz = MOUNTAIN_NO + hash_rand( ll_x + half_width, ll_y, SizeFactor ) ;
  216.     lower_fz = ( ll_fz + lr_fz ) / 2.0 +
  217.                     rise_height * lib_gauss_rand( iz ) ;
  218.     iz = MOUNTAIN_NO +
  219.         hash_rand( ll_x + width, ll_y + half_width, SizeFactor ) ;
  220.     right_fz = ( lr_fz + ur_fz ) / 2.0 +
  221.                     rise_height * lib_gauss_rand( iz ) ;
  222.     iz = MOUNTAIN_NO +
  223.         hash_rand( ll_x + half_width, ll_y + width, SizeFactor ) ;
  224.     upper_fz = ( ur_fz + ul_fz ) / 2.0 +
  225.                     rise_height * lib_gauss_rand( iz ) ;
  226.     iz = MOUNTAIN_NO + hash_rand( ll_x, ll_y + half_width, SizeFactor ) ;
  227.     left_fz  = ( ul_fz + ll_fz ) / 2.0 +
  228.                     rise_height * lib_gauss_rand( iz ) ;
  229.     iz = MOUNTAIN_NO +
  230.         hash_rand( ll_x + half_width, ll_y + half_width, SizeFactor ) ;
  231.     middle_fz = ( ll_fz + lr_fz + ur_fz + ul_fz ) / 4.0 +
  232.                 1.4142136 * rise_height * lib_gauss_rand( iz ) ;
  233.  
  234.     /* check subsections for subdivision or output */
  235.     grow_mountain( fnum_pts, half_width, ll_x, ll_y,
  236.                     ll_fz, lower_fz, middle_fz, left_fz ) ;
  237.     grow_mountain( fnum_pts, half_width, ll_x+half_width, ll_y,
  238.                     lower_fz, lr_fz, right_fz, middle_fz ) ;
  239.     grow_mountain( fnum_pts, half_width, ll_x+half_width, ll_y+half_width,
  240.                     middle_fz, right_fz, ur_fz, upper_fz ) ;
  241.     grow_mountain( fnum_pts, half_width, ll_x, ll_y+half_width,
  242.                     left_fz, middle_fz, upper_fz, ul_fz ) ;
  243.     }
  244. }
  245.