home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / p / ply15dat.zip / MOUNTAIN.C < prev    next >
C/C++ Source or Header  |  1992-09-19  |  7KB  |  203 lines

  1. /*
  2.  * mountain.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.  None of the spheres are clipped.
  5.  *     A few of the polygons are clipped.  One light source.
  6.  *
  7.  * Version:  2.2 (11/17/87)
  8.  * Author:  Eric Haines, 3D/Eye, Inc.
  9.  *
  10.  * SIZE_FACTOR determines the number of objects output.
  11.  *     Total triangular polygons = 2 * (4**SIZE_FACTOR)
  12.  *
  13.  *     SIZE_FACTOR     # triangles     # spheres
  14.  *         1                8               4
  15.  *         2               32               4
  16.  *         3              128               4
  17.  *
  18.  *         6             8192               4
  19.  */
  20.  
  21.  
  22. #include <stdio.h>
  23. #include <math.h>
  24. #include "def.h"
  25. #include "lib.h"
  26.  
  27. /* size factor determines number of polygons */
  28. #define SIZE_FACTOR 4
  29.  
  30. /* fractal dimension - affects variance of z.  Between 2 and 3 */
  31. #define FRACTAL_DIMENSION 2.2
  32.  
  33. /* change MOUNTAIN_NO to get a different mountain */
  34. #define MOUNTAIN_NO 21
  35.  
  36. /* lower left corner and width of mountain definitions */
  37. #define X_CORNER  -1.0
  38. #define Y_CORNER  -1.0
  39. #define WIDTH      2.0
  40.  
  41. /* hashing function to get a seed for the random number generator */
  42. #define hash_rand(A,B,C) ( ( ((A)<<(23-(C))) + ((B)<<(15-(C)))\
  43.                             + ((A)<<(7-(C))) ) & 0xffff )
  44.  
  45. static   long    num_pts ;
  46. static  double roughness ;
  47.  
  48. /* create a pyramid of crystal spheres */
  49. static void
  50. create_spheres(COORD4 *center)
  51. {
  52.     double  angle ;
  53.     COORD4  axis, new_pt, pt, sphere ;
  54.     long    i ;
  55.     MATRIX  mx ;
  56.  
  57.     SET_COORD( axis, 1.0, 1.0, 0.0 ) ;
  58.     lib_normalize_coord3( &axis ) ;
  59.     angle = acos( (double)( -1.0/3.0 ) ) ;
  60.  
  61.     /* set center of pyramid and radius */
  62.     SET_COORD4( pt, 0.0, 0.0, center->w * sqrt( (double)( 3.0/2.0 ) ), 0.0 ) ;
  63.     COPY_COORD( sphere, pt ) ;
  64.     ADD2_COORD( sphere, *center ) ;
  65.     sphere.w = center->w ;
  66.     lib_output_sphere( &sphere, OUTPUT_CURVES ) ;
  67.     lib_create_axis_rotate_matrix( mx, &axis, angle ) ;
  68.     lib_transform_coord( &new_pt, &pt, mx ) ;
  69.  
  70.     for ( i = 0 ; i < 3 ; ++i ) {
  71.        lib_create_rotate_matrix( mx, Z_AXIS, (double)i * 2.0 * PI / 3.0 ) ;
  72.        lib_transform_coord( &sphere, &new_pt, mx ) ;
  73.        ADD2_COORD( sphere, *center ) ;
  74.        sphere.w = center->w ;
  75.        lib_output_sphere( &sphere, OUTPUT_CURVES ) ;
  76.        }
  77. }
  78.  
  79. /*
  80.  * Build mountain section.  If at width > 1, split quadrilateral into four
  81.  * parts.  Else if at width == 1, output quadrilateral as two triangles.
  82.  */
  83. static void
  84. grow_mountain(long width, long ll_x, long ll_y,
  85.               double ll_fz, double lr_fz, double ur_fz, double ul_fz)
  86. {
  87.     long    half_width, iz ;
  88.     double  l_fx, r_fx, l_fy, u_fy ;
  89.     double  lower_fz, right_fz, upper_fz, left_fz, middle_fz ;
  90.     long    num_tri, num_tri_vert, num_vert ;
  91.     double  rise_height, hside_length ;
  92.     COORD4  tri_vert[3] ;
  93.  
  94.    if ( width == 1 ) {
  95.       /* calculate x and y coordinates of corners */
  96.       l_fx = X_CORNER + (double)ll_x * WIDTH / (double)num_pts;
  97.       r_fx = X_CORNER + (double)(ll_x+1) * WIDTH / (double)num_pts;
  98.       l_fy = Y_CORNER + (double)ll_y * WIDTH / (double)num_pts;
  99.       u_fy = Y_CORNER + (double)(ll_y+1) * WIDTH / (double)num_pts;
  100.  
  101.       /* output two triangles for section */
  102.       for (num_tri=0;num_tri<2;++num_tri) {
  103.          for (num_vert=0;num_vert<3;++num_vert) {
  104.             num_tri_vert = (num_vert + num_tri * 2) % 4;
  105.             if (num_tri_vert == 0) {
  106.                SET_COORD(tri_vert[num_vert], l_fx, l_fy, ll_fz);
  107.                }
  108.             else if ( num_tri_vert == 1 ) {
  109.                SET_COORD( tri_vert[num_vert], r_fx, l_fy, lr_fz ) ;
  110.                }
  111.             else if ( num_tri_vert == 2 ) {
  112.                SET_COORD( tri_vert[num_vert], r_fx, u_fy, ur_fz ) ;
  113.                }
  114.             else {
  115.                SET_COORD( tri_vert[num_vert], l_fx, u_fy, ul_fz ) ;
  116.                }
  117.             }
  118.          lib_output_polygon( 3, tri_vert) ;
  119.          }
  120.       }
  121.    else {
  122.       /* subdivide edges and move in z direction */
  123.       half_width = width>>1 ;
  124.       hside_length = (double)half_width * WIDTH / (double)num_pts ;
  125.       rise_height = hside_length * roughness ;
  126.  
  127.       /* for each midpoint, find z */
  128.       iz = MOUNTAIN_NO + hash_rand( ll_x + half_width, ll_y, SIZE_FACTOR ) ;
  129.       lower_fz = ( ll_fz + lr_fz ) / 2.0 +
  130.                                     rise_height * lib_gauss_rand( iz ) ;
  131.       iz = MOUNTAIN_NO +
  132.               hash_rand( ll_x + width, ll_y + half_width, SIZE_FACTOR ) ;
  133.       right_fz = ( lr_fz + ur_fz ) / 2.0 +
  134.                                     rise_height * lib_gauss_rand( iz ) ;
  135.       iz = MOUNTAIN_NO +
  136.               hash_rand( ll_x + half_width, ll_y + width, SIZE_FACTOR ) ;
  137.       upper_fz = ( ur_fz + ul_fz ) / 2.0 +
  138.                                     rise_height * lib_gauss_rand( iz ) ;
  139.       iz = MOUNTAIN_NO + hash_rand( ll_x, ll_y + half_width, SIZE_FACTOR ) ;
  140.       left_fz  = (ul_fz + ll_fz ) / 2.0 + rise_height * lib_gauss_rand( iz ) ;
  141.       iz = MOUNTAIN_NO +
  142.           hash_rand( ll_x + half_width, ll_y + half_width, SIZE_FACTOR ) ;
  143.       middle_fz = ( ll_fz + lr_fz + ur_fz + ul_fz ) / 4.0 +
  144.                        1.4142136 * rise_height * lib_gauss_rand( iz ) ;
  145.  
  146.       /* check subsections for subdivision or output */
  147.       grow_mountain(half_width, ll_x, ll_y, ll_fz,
  148.                     lower_fz, middle_fz, left_fz) ;
  149.       grow_mountain(half_width, ll_x+half_width, ll_y, lower_fz,
  150.                     lr_fz, right_fz, middle_fz) ;
  151.       grow_mountain(half_width, ll_x+half_width, ll_y+half_width,
  152.                     middle_fz, right_fz, ur_fz, upper_fz) ;
  153.       grow_mountain(half_width, ll_x, ll_y+half_width,
  154.                     left_fz, middle_fz, upper_fz, ul_fz) ;
  155.  
  156.       }
  157. }
  158.  
  159. void
  160. main(int argc, char *argv[])
  161. {
  162.     COORD4  back_color, obj_color ;
  163.     COORD4  center, light ;
  164.     COORD4  from, at, up, dir;
  165.     double  ratio ;
  166.  
  167.    /* We are using Polyray */
  168.    lib_set_raytracer(OUTPUT_POLYRAY);
  169.  
  170.     /* output viewpoint */
  171.     SET_COORD( from, -1.6, 1.6, 1.7 ) ;
  172.     SET_COORD( at, 0.0, 0.0, 0.0 ) ;
  173.     SET_COORD( up, 0.0, 0.0, 1.0 ) ;
  174.     lib_output_viewpoint( &from, &at, &up, 45.0, 1.0, 0.1, 256, 256);
  175.  
  176.     /* output background color - UNC sky blue */
  177.     SET_COORD( back_color, 0.078, 0.361, 0.753 ) ;
  178.     lib_output_background_color( &back_color ) ;
  179.  
  180.     /* output light sources */
  181.     SET_COORD4( light, -100.0, -100.0, 100.0, 0.5 ) ;
  182.     lib_output_light( &light ) ;
  183.  
  184.     /* set up crystal sphere color - clear white */
  185.     SET_COORD( obj_color, 1.0, 1.0, 1.0 ) ;
  186.     lib_output_color( &obj_color, 0.0, 0.1, 0.0, 0.9, 2.0, 0.9, 1.5 ) ;
  187.  
  188.     /* output crystal spheres */
  189.     SET_COORD4( center, -0.8, 0.8, 1.00, 0.17 ) ;
  190.     create_spheres( ¢er ) ;
  191.  
  192.     /* set up mountain color - grey */
  193.     SET_COORD( obj_color, 0.5, 0.45, 0.35 ) ;
  194.     lib_output_color( &obj_color, 0.2, 0.8, 0.0, 0.0, 0.0, 0.0, 0.0) ;
  195.  
  196.     /* grow mountain */
  197.     num_pts = 1<<SIZE_FACTOR ;
  198.     ratio = 2.0 /
  199.          exp( (double)( log( (double)2.0 ) / (FRACTAL_DIMENSION-1.0) ) ) ;
  200.     roughness = sqrt( (double)( SQR(ratio) - 1.0 ) ) ;
  201.     grow_mountain( num_pts, 0, 0, 0.0, 0.0, 0.0, 0.0) ;
  202. }
  203.