Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!uunet!seismo!mcnc!ece-csc!ncrcae!ncr-sd!hp-sdd!hplabs!hplabsb!spach From: spach@hplabsb.UUCP (Susan Spach) Newsgroups: comp.graphics Subject: Standard Procedural Databases (Part 2 of 2) Message-ID: <4210@hplabsb.UUCP> Date: Fri, 17-Jul-87 11:50:01 EDT Article-I.D.: hplabsb.4210 Posted: Fri Jul 17 11:50:01 1987 Date-Received: Sat, 18-Jul-87 14:58:16 EDT Organization: Hewlett-Packard Laboratories Lines: 1979 Keywords: raytracing, hidden-surface algorithms, benchmarking ---------------------------------------------------------------------- From Eric Haines, 3D/Eye, INC. PART 2 of 2: Standard Procedural Databases This software is a set of basic test images for ray tracing and hidden surface algorithms. ---------------------------------------------------------------------- # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # # Wrapped by eye!erich on July 9, 1987 # part 2 of 2 - Standard Procedural Databases # Contents: makefile definitions.h lib.h lib.c # balls.c gears.c mountain.c rings.c tetra.c tree.c echo x - makefile sed 's/^@//' > "makefile" <<'@//E*O*F makefile//' # makefile for standard procedural databases # Version: 2.0 (7/9/87) # Author: Eric Haines, 3D/Eye, Inc. # Works on the HP 300 machines--probably needs to be modified to your system # cc = C compiler # -c compile only, do not try to link CC=cc -c INC=definitions.h lib.h BASELIB=-lm -lmalloc /usr/lib/end.o all: balls gears mountain rings tetra tree lib.o: $(INC) lib.c $(CC) lib.c balls: lib.o balls.o cc -o balls balls.o lib.o $(BASELIB) balls.o: $(INC) balls.c $(CC) balls.c gears: lib.o gears.o cc -o gears gears.o lib.o $(BASELIB) gears.o: $(INC) gears.c $(CC) gears.c mountain: lib.o mountain.o cc -o mountain mountain.o lib.o $(BASELIB) mountain.o: $(INC) mountain.c $(CC) mountain.c rings: lib.o rings.o cc -o rings rings.o lib.o $(BASELIB) rings.o: $(INC) rings.c $(CC) rings.c tetra: lib.o tetra.o cc -o tetra tetra.o lib.o $(BASELIB) tetra.o: $(INC) tetra.c $(CC) tetra.c tree: lib.o tree.o cc -o tree tree.o lib.o $(BASELIB) tree.o: $(INC) tree.c $(CC) tree.c @//E*O*F makefile// chmod u=rw,g=r,o= makefile echo x - definitions.h sed 's/^@//' > "definitions.h" <<'@//E*O*F definitions.h//' /* * definitions.h contains some useful definitions for "C" programs. * * Version: 2.0 (7/9/87) * Author: Eric Haines, 3D/Eye, Inc. */ #define EPSILON 5.0e-6 #ifndef FALSE #define FALSE 0 #endif #ifndef NULL #define NULL 0 #endif #ifndef TRUE #define TRUE 1 #endif #ifndef PI #define PI 3.141592653589793 #endif typedef double MATRIX[4][4] ; /* row major form */ typedef struct { double x ; double y ; double z ; double w ; } COORD4, *COORD4_P ; #define ABSOLUTE(A) ( (A) < 0 ? -(A) : (A) ) #define FRACTION(A) ( (A) - (long)(A) ) #define MAX(A,B) ( (A) > (B) ? (A) : (B) ) #define MAX3(A,B,C) ( MAX( MAX( A,B ), C ) ) #define MIN(A,B) ( (A) < (B) ? (A) : (B) ) #define MIN3(A,B,C) ( MIN( MIN( A,B ), C ) ) #define SQR(A) ( (A) * (A) ) #define ADD2_COORD(r,a) { (r).x += (a).x; (r).y += (a).y;\ (r).z += (a).z; } #define ADD3_COORD(r,a,b) { (r).x = (a).x + (b).x;\ (r).y = (a).y + (b).y;\ (r).z = (a).z + (b).z; } #define COPY_COORD(r,a) { (r).x = (a).x; (r).y = (a).y; (r).z = (a).z; } #define COPY_COORD4(r,a) { (r).x = (a).x; (r).y = (a).y; (r).z = (a).z;\ (r).w = (a).w; } #define CROSS(r,a,b) { (r).x = (a).y * (b).z - (a).z * (b).y;\ (r).y = (a).z * (b).x - (a).x * (b).z;\ (r).z = (a).x * (b).y - (a).y * (b).x; } #define DOT_PRODUCT(a,b) ( (a).x * (b).x +\ (a).y * (b).y +\ (a).z * (b).z ) #define SET_COORD(r,a,b,c) { (r).x = (a); (r).y = (b); (r).z = (c); } #define SET_COORD4(r,a,b,c,d) { (r).x = (a); (r).y = (b); (r).z = (c);\ (r).w = (d); } #define SUB2_COORD(r,a) { (r).x -= (a).x; (r).y -= (a).y;\ (r).z -= (a).z; } #define SUB3_COORD(r,a,b) { (r).x = (a).x - (b).x;\ (r).y = (a).y - (b).y;\ (r).z = (a).z - (b).z; } @//E*O*F definitions.h// chmod u=rw,g=r,o= definitions.h echo x - lib.h sed 's/^@//' > "lib.h" <<'@//E*O*F lib.h//' /* * lib.h - vector library definitions * * Version: 2.0 (7/9/87) * Author: Eric Haines, 3D/Eye, Inc. */ #define X_AXIS 0 #define Y_AXIS 1 #define Z_AXIS 2 /* Output library definitions */ #define OUTPUT_CURVES 0 /* true curve output */ #define OUTPUT_PATCHES 1 /* polygonal patches output */ #define OUTPUT_RESOLUTION 4 /* amount of polygonalization */ double lib_normalize_coord3() ; double lib_gauss_rand() ; @//E*O*F lib.h// chmod u=rw,g=r,o= lib.h echo x - lib.c sed 's/^@//' > "lib.c" <<'@//E*O*F lib.c//' /* * lib.c - a library of vector operations, a random number generator, and * object output routines. * * Version: 2.0 (7/9/87) * Author: Eric Haines, 3D/Eye, Inc. */ #include #include #include #include "definitions.h" #include "lib.h" /* * Normalize the vector (X,Y,Z) so that X*X + Y*Y + Z*Z = 1. * * The normalization divisor is returned. If the divisor is zero, no * normalization occurs. * */ double lib_normalize_coord3( cvec ) COORD4 *cvec; { double divisor; divisor = sqrt( (double)DOT_PRODUCT( (*cvec), (*cvec) ) ) ; if ( divisor != 0.0 ) { cvec->x /= divisor; cvec->y /= divisor; cvec->z /= divisor; } return( divisor ); } /* * Set all matrix elements to zero. */ lib_zero_matrix( mx ) MATRIX mx ; { long i, j ; for ( i = 0 ; i < 4 ; ++i ) { for ( j = 0 ; j < 4 ; ++j ) { mx[i][j] = 0.0 ; } } } /* * Create identity matrix. */ lib_create_identity_matrix( mx ) MATRIX mx ; { long i ; lib_zero_matrix( mx ) ; for ( i = 0 ; i < 4 ; ++i ) { mx[i][i] = 1.0 ; } } /* * Create a rotation matrix along the given axis by the given angle in radians. */ lib_create_rotate_matrix( mx, axis, angle ) MATRIX mx ; long axis ; double angle ; { double cosine ; double sine ; lib_zero_matrix( mx ) ; cosine = cos( (double)angle ) ; sine = sin( (double)angle ) ; switch ( axis ) { case X_AXIS: mx[0][0] = 1.0 ; mx[1][1] = mx[2][2] = cosine ; mx[1][2] = sine ; mx[2][1] = -sine ; break ; case Y_AXIS: mx[1][1] = 1.0 ; mx[0][0] = mx[2][2] = cosine ; mx[2][0] = sine ; mx[0][2] = -sine ; break ; case Z_AXIS: mx[2][2] = 1.0 ; mx[0][0] = mx[1][1] = cosine ; mx[0][1] = sine ; mx[1][0] = -sine ; break ; } mx[3][3] = 1.0 ; } /* * Create a rotation matrix along the given axis by the given angle in radians. * The axis is a set of direction cosines. */ lib_create_arbitrary_rotate_matrix( mx, rvec, angle ) MATRIX mx ; COORD4 *rvec ; double angle ; { COORD4 axis ; double cosine ; double one_minus_cosine ; double sine ; lib_zero_matrix( mx ) ; COPY_COORD( axis, (*rvec) ) ; cosine = cos( (double)angle ) ; sine = sin( (double)angle ) ; one_minus_cosine = 1.0 - cosine ; mx[0][0] = SQR(axis.x) + (1.0 - SQR(axis.x)) * cosine ; mx[0][1] = axis.x * axis.y * one_minus_cosine + axis.z * sine ; mx[0][2] = axis.x * axis.z * one_minus_cosine - axis.y * sine ; mx[1][0] = axis.x * axis.y * one_minus_cosine - axis.z * sine ; mx[1][1] = SQR(axis.y) + (1.0 - SQR(axis.y)) * cosine ; mx[1][2] = axis.y * axis.z * one_minus_cosine + axis.x * sine ; mx[2][0] = axis.x * axis.z * one_minus_cosine + axis.y * sine ; mx[2][1] = axis.y * axis.z * one_minus_cosine - axis.x * sine ; mx[2][2] = SQR(axis.z) + (1.0 - SQR(axis.z)) * cosine ; mx[3][3] = 1.0 ; } /* * Multiply a 4 element vector by a matrix. */ lib_transform_coord( vres, vec, mx ) COORD4 *vres ; COORD4 *vec ; MATRIX mx ; { vres->x = vec->x*mx[0][0] + vec->y*mx[1][0] + vec->z*mx[2][0] + vec->w*mx[3][0] ; vres->y = vec->x*mx[0][1] + vec->y*mx[1][1] + vec->z*mx[2][1] + vec->w*mx[3][1] ; vres->z = vec->x*mx[0][2] + vec->y*mx[1][2] + vec->z*mx[2][2] + vec->w*mx[3][2] ; vres->w = vec->x*mx[0][3] + vec->y*mx[1][3] + vec->z*mx[2][3] + vec->w*mx[3][3] ; } /* * Multiply two 4x4 matrices. */ lib_matrix_multiply( mxres, mx1, mx2 ) MATRIX mxres ; MATRIX mx1 ; MATRIX mx2 ; { long i ; long j ; for ( i = 0; i < 4; i++ ) { for ( j = 0; j < 4; j++ ) { mxres[i][j] = mx1[i][0]*mx2[0][j] + mx1[i][1]*mx2[1][j] + mx1[i][2]*mx2[2][j] + mx1[i][3]*mx2[3][j] ; } } } /* * Rotate a vector pointing towards the major-axis faces (i.e. the major-axis * component of the vector is defined as the largest value) 90 degrees to * another cube face. Mod_face is a face number. * * If the routine is called six times, with mod_face=0..5, the vector will be * rotated to each face of a cube. Rotations are: * mod_face = 0 mod 3, +Z axis rotate * mod_face = 1 mod 3, +X axis rotate * mod_face = 2 mod 3, -Y axis rotate */ lib_rotate_cube_face( vec, major_axis, mod_face ) COORD4 *vec ; long major_axis ; long mod_face ; { double swap ; mod_face = (mod_face+major_axis) % 3 ; if ( mod_face == 0 ) { swap = vec->x ; vec->x = -vec->y ; vec->y = swap ; } else if ( mod_face == 1 ) { swap = vec->y ; vec->y = -vec->z ; vec->z = swap ; } else { swap = vec->x ; vec->x = -vec->z ; vec->z = swap ; } } /* * Portable gaussian random number generator (from "Numerical Recipes", GASDEV) * Returns a uniform random deviate between 0.0 and 1.0. 'iseed' must be * less than M1 to avoid repetition, and less than (2^31-C1)/A1 [= 300718] * to avoid overflow. */ #define M1 134456 #define IA1 8121 #define IC1 28411 #define RM1 1.0/M1 double lib_gauss_rand(iseed) long iseed ; { double fac ; long ix1, ix2 ; double r ; double v1, v2 ; ix2 = iseed ; do { ix1 = (IC1+ix2*IA1) % M1 ; ix2 = (IC1+ix1*IA1) % M1 ; v1 = ix1 * 2.0 * RM1 - 1.0 ; v2 = ix2 * 2.0 * RM1 - 1.0 ; r = v1*v1 + v2*v2 ; } while ( r >= 1.0 ) ; fac = sqrt( (double)( -2.0 * log( (double)r ) / r ) ) ; return( v1 * fac ) ; } /* OUTPUT ROUTINES * * Files are output as lines of text. For each entity, the first line * defines its type. The rest of the first line and possibly other lines * contain further information about the entity. Entities include: * * "v" - viewing vectors and angles * "l" - positional light location * "b" - background color * "f" - object material properties * "c" - cone or cylinder primitive * "s" - sphere primitive * "p" - polygon primitive * "pp" - polygonal patch primitive */ /* * Output viewpoint location. The parameters are: * From: the eye location. * At: a position to be at the center of the image. A.k.a. "lookat" * Up: a vector defining which direction is up. * * Note that no assumptions are made about normalizing the data (e.g. the * from-at distance does not have to be 1). Also, vectors are not * required to be perpendicular to each other. * * For all databases some viewing parameters are always the same: * * Viewing angle is defined as from the center of top pixel row to bottom * pixel row and left column to right column. * Yon is "at infinity." * Resolution is always 512 x 512. */ lib_output_viewpoint( from, at, up, angle, hither, resx, resy ) COORD4 *from ; COORD4 *at ; COORD4 *up ; double angle ; double hither ; long resx ; long resy ; { printf( "v\n" ) ; printf( "from %g %g %g\n", from->x, from->y, from->z ) ; printf( "at %g %g %g\n", at->x, at->y, at->z ) ; printf( "up %g %g %g\n", up->x, up->y, up->z ) ; printf( "angle %g\n", angle ) ; printf( "hither %g\n", hither ) ; printf( "resolution %d %d\n", resx, resy ) ; } /* * Output light. A light is defined by position. All lights have the same * intensity. * */ lib_output_light( center_pt ) COORD4 *center_pt ; { printf( "l %g %g %g\n", center_pt->x, center_pt->y, center_pt->z ) ; } /* * Output background color. A color is simply RGB (monitor dependent, but * that's life). The format is: * "b" red green blue */ lib_output_background_color( color ) COORD4 *color ; { printf( "b %g %g %g\n", color->x, color->y, color->z ) ; } /* * Output a color and shading parameters for the object in the format: * "f" red green blue Kd Ks Shine T index_of_refraction * * Kd is the diffuse component, Ks the specular, Shine is the Phong cosine * power for highlights, T is transmittance (fraction of light passed per unit). * 0 <= Kd <= 1 and 0 <= Ks <= 1, though it is not required that Kd + Ks == 1. * * The fill color is used to color the objects following it until a new color * is assigned or the file ends. */ lib_output_color( color, kd, ks, shine, t, i_of_r ) COORD4 *color ; double kd ; double ks ; double shine ; double t ; double i_of_r ; { printf( "f %g %g %g %g %g %g %g %g\n", color->x, color->y, color->z, kd, ks, shine, t, i_of_r ) ; } /* * Output cylinder or cone. A cylinder is defined as having a radius and an * axis defined by two points, which also define the top and bottom edge of the * cylinder. A cone is defined similarly, the difference being that the apex * and base radii are different. The apex radius is defined as being smaller * than the base radius. Note that the surface exists without endcaps. * * If format=OUTPUT_CURVES, output the cylinder/cone in format: * "c" * base.x base.y base.z base_radius * apex.x apex.y apex.z apex_radius * * If the format=OUTPUT_POLYGONS, the surface is polygonalized and output. * (4*OUTPUT_RESOLUTION) polygons are output as rectangles by * lib_output_polypatch. */ lib_output_cylcone( base_pt, apex_pt, format ) COORD4 *base_pt ; COORD4 *apex_pt ; long format ; { double angle ; COORD4 axis ; COORD4 dir ; double divisor ; COORD4 lip_norm[4], lip_pt[4] ; MATRIX mx ; COORD4 norm_axis ; long num_pol ; COORD4 start_norm, start_radius[4] ; if ( format == OUTPUT_CURVES ) { printf( "c\n" ) ; printf( "%g %g %g %g\n", base_pt->x, base_pt->y, base_pt->z, base_pt->w) ; printf( "%g %g %g %g\n", apex_pt->x, apex_pt->y, apex_pt->z, apex_pt->w ) ; } else { SUB3_COORD( axis, (*apex_pt), (*base_pt) ) ; COPY_COORD( norm_axis, axis ) ; lib_normalize_coord3( &norm_axis ) ; dir.x = 0.0 ; dir.y = 0.0 ; dir.z = 1.0 ; dir.w = 0.0 ; CROSS( start_norm, axis, dir ) ; divisor = lib_normalize_coord3( &start_norm ) ; if ( ABSOLUTE( divisor ) < EPSILON ) { dir.x = 1.0 ; dir.y = 0.0 ; dir.z = 0.0 ; CROSS( start_norm, axis, dir ) ; lib_normalize_coord3( &start_norm ) ; } start_radius[0].x = start_norm.x * base_pt->w ; start_radius[0].y = start_norm.y * base_pt->w ; start_radius[0].z = start_norm.z * base_pt->w ; start_radius[0].w = 0.0 ; ADD3_COORD( lip_pt[0], (*base_pt), start_radius[0] ) ; start_radius[1].x = start_norm.x * apex_pt->w ; start_radius[1].y = start_norm.y * apex_pt->w ; start_radius[1].z = start_norm.z * apex_pt->w ; start_radius[1].w = 0.0 ; ADD3_COORD( lip_pt[1], (*apex_pt), start_radius[1] ) ; COPY_COORD4( lip_norm[0], start_norm ) ; COPY_COORD4( lip_norm[1], start_norm ) ; for ( num_pol = 0 ; num_pol < 4*OUTPUT_RESOLUTION ; ++num_pol ) { COPY_COORD4( lip_pt[3], lip_pt[0] ) ; COPY_COORD4( lip_pt[2], lip_pt[1] ) ; COPY_COORD4( lip_norm[3], lip_norm[0] ) ; COPY_COORD4( lip_norm[2], lip_norm[1] ) ; angle = 2.0 * PI * (double)( num_pol+1 ) / (double)( 4*OUTPUT_RESOLUTION ) ; lib_create_arbitrary_rotate_matrix( mx, &norm_axis, angle ) ; lib_transform_coord( &lip_pt[0], &start_radius[0], mx ) ; ADD2_COORD( lip_pt[0], (*base_pt) ) ; lib_transform_coord( &lip_pt[1], &start_radius[1], mx ) ; ADD2_COORD( lip_pt[1], (*apex_pt) ) ; lib_transform_coord( &lip_norm[0], &start_norm, mx ) ; COPY_COORD4( lip_norm[1], lip_norm[0] ) ; lib_output_polypatch( 4, lip_pt, lip_norm ) ; } } } /* * Output sphere. A sphere is defined by a radius and center position. * * If format=OUTPUT_CURVES, output the sphere in format: * "s" center.x center.y center.z radius * * If the format=OUTPUT_POLYGONS, the sphere is polygonalized and output. * The sphere is polygonalized by splitting it into 6 faces (of a cube * projected onto the sphere) and dividing these faces by equally spaced * great circles. OUTPUT_RESOLUTION affects the number of great circles. * (6*2*OUTPUT_RESOLUTION*OUTPUT_RESOLUTION) polygons are output as triangles * using lib_output_polypatch. */ lib_output_sphere( center_pt, format ) COORD4 *center_pt ; long format ; { double angle ; COORD4 edge_norm[3], edge_pt[3] ; long num_face, num_edge, num_tri, num_vert ; COORD4 x_axis[OUTPUT_RESOLUTION+1], y_axis[OUTPUT_RESOLUTION+1] ; COORD4 pt[OUTPUT_RESOLUTION+1][OUTPUT_RESOLUTION+1] ; COORD4 mid_axis ; MATRIX rot_mx ; long u_pol, v_pol ; if ( format == OUTPUT_CURVES ) { printf( "s %g %g %g %g\n", center_pt->x, center_pt->y, center_pt->z, center_pt->w ) ; } else { /* calculate axes used to find grid points */ for ( num_edge = 0 ; num_edge <= OUTPUT_RESOLUTION ; ++num_edge ) { angle = (PI/4.0) * (2.0*(double)num_edge/OUTPUT_RESOLUTION - 1.0) ; mid_axis.w = 0.0 ; mid_axis.x = 1.0 ; mid_axis.y = 0.0 ; mid_axis.z = 0.0 ; lib_create_rotate_matrix( rot_mx, Y_AXIS, angle ) ; lib_transform_coord( &x_axis[num_edge], &mid_axis, rot_mx ) ; mid_axis.x = 0.0 ; mid_axis.y = 1.0 ; mid_axis.z = 0.0 ; lib_create_rotate_matrix( rot_mx, X_AXIS, angle ) ; lib_transform_coord( &y_axis[num_edge], &mid_axis, rot_mx ) ; } /* set up grid of points on +Z sphere surface */ for ( u_pol = 0 ; u_pol <= OUTPUT_RESOLUTION ; ++u_pol ) { for ( v_pol = 0 ; v_pol <= OUTPUT_RESOLUTION ; ++v_pol ) { CROSS( pt[u_pol][v_pol], x_axis[u_pol], y_axis[v_pol] ) ; lib_normalize_coord3( &pt[u_pol][v_pol] ) ; pt[u_pol][v_pol].w = 1.0 ; } } for ( num_face = 0 ; num_face < 6 ; ++num_face ) { /* transform points to cube face */ for ( u_pol = 0 ; u_pol <= OUTPUT_RESOLUTION ; ++u_pol ) { for ( v_pol = 0 ; v_pol <= OUTPUT_RESOLUTION ; ++v_pol ) { lib_rotate_cube_face( &pt[u_pol][v_pol] , Z_AXIS , num_face ) ; } } /* output grid */ for ( u_pol = 0 ; u_pol < OUTPUT_RESOLUTION ; ++u_pol ) { for ( v_pol = 0 ; v_pol < OUTPUT_RESOLUTION ; ++v_pol ) { for ( num_tri = 0 ; num_tri < 2 ; ++num_tri ) { for ( num_edge = 0 ; num_edge < 3 ; ++num_edge ) { num_vert = (num_tri*2 + num_edge) % 4 ; if ( num_vert == 0 ) { COPY_COORD4( edge_pt[num_edge], pt[u_pol][v_pol] ) ; } else if ( num_vert == 1 ) { COPY_COORD4( edge_pt[num_edge], pt[u_pol][v_pol+1] ) ; } else if ( num_vert == 2 ) { COPY_COORD4( edge_pt[num_edge], pt[u_pol+1][v_pol+1] ) ; } else { COPY_COORD4( edge_pt[num_edge], pt[u_pol+1][v_pol] ) ; } COPY_COORD4( edge_norm[num_edge], edge_pt[num_edge] ) ; edge_pt[num_edge].x = edge_pt[num_edge].x * center_pt->w + center_pt->x ; edge_pt[num_edge].y = edge_pt[num_edge].y * center_pt->w + center_pt->y ; edge_pt[num_edge].z = edge_pt[num_edge].z * center_pt->w + center_pt->z ; } lib_output_polypatch( 3, edge_pt, edge_norm ) ; } } } } } } /* * Output polygon. A polygon is defined by a set of vertices. With these * databases, a polygon is defined to have all points coplanar. A polygon has * only one side, with the order of the vertices being counterclockwise as you * face the polygon (right-handed coordinate system). * * The output format is always: * "p" total_vertices * vert1.x vert1.y vert1.z * [etc. for total_vertices polygons] * */ lib_output_polygon( tot_vert, vert ) long tot_vert ; COORD4 *vert ; { long num_vert ; printf( "p %d\n", tot_vert ) ; for ( num_vert = 0 ; num_vert < tot_vert ; ++num_vert ) { printf( "%g %g %g\n", vert[num_vert].x , vert[num_vert].y , vert[num_vert].z ) ; } } /* * Output polygonal patch. A patch is defined by a set of vertices and their * normals. With these databases, a patch is defined to have all points * coplanar. A patch has only one side, with the order of the vertices being * counterclockwise as you face the patch (right-handed coordinate system). * * The output format is always: * "pp" total_vertices * vert1.x vert1.y vert1.z norm1.x norm1.y norm1.z * [etc. for total_vertices polygonal patches] * */ lib_output_polypatch( tot_vert, vert, norm ) long tot_vert ; COORD4 *vert ; COORD4 *norm ; { long num_vert ; printf( "pp %d\n", tot_vert ) ; for ( num_vert = 0 ; num_vert < tot_vert ; ++num_vert ) { printf( "%g %g %g %g %g %g\n", vert[num_vert].x , vert[num_vert].y , vert[num_vert].z , norm[num_vert].x , norm[num_vert].y , norm[num_vert].z ) ; } } @//E*O*F lib.c// chmod u=rw,g=r,o= lib.c echo x - balls.c sed 's/^@//' > "balls.c" <<'@//E*O*F balls.c//' /* * balls.c - Create a set of shiny spheres, with each sphere blooming sets of * 9 more spheres with 1/3rd radius. None of the spheres are clipped. A * square floor polygon is added. Three light sources. * * Version: 2.0 (7/9/87) * Author: Eric Haines, 3D/Eye, Inc. * * SIZE_FACTOR determines the number of objects output. * Total spheres = sum of n=0,SF of (9**SF). * * SIZE_FACTOR # spheres # squares * 1 10 1 * 2 91 1 * 3 820 1 * * 4 7381 1 */ #include #include #include #include "definitions.h" #include "lib.h" #define OUTPUT_FORMAT OUTPUT_CURVES #define SIZE_FACTOR 4 static COORD4 objset[9] ; main(argc,argv) int argc; char *argv[]; { COORD4 back_color, obj_color ; COORD4 backg[4], bvec, light ; COORD4 from, at, up ; COORD4 center_pt, direction ; double radius ; /* set radius of sphere which would enclose entire object */ radius = 1.0 ; /* output viewpoint */ SET_COORD( from, 2.1, 1.3, 1.7 ) ; SET_COORD( at, 0.0, 0.0, 0.0 ) ; SET_COORD( up, 0.0, 0.0, 1.0 ) ; lib_output_viewpoint( &from, &at, &up, 45.0, 1.0, 512, 512 ) ; /* output background color - UNC sky blue */ SET_COORD( back_color, 0.078, 0.361, 0.753 ) ; lib_output_background_color( &back_color ) ; /* output light sources */ SET_COORD( light, 4.0, 3.0, 2.0 ) ; lib_output_light( &light ) ; SET_COORD( light, 1.0, -4.0, 4.0 ) ; lib_output_light( &light ) ; SET_COORD( light, -3.0, 1.0, 5.0 ) ; lib_output_light( &light ) ; /* output floor polygon - beige */ SET_COORD( back_color, 1.0, 0.75, 0.33 ) ; lib_output_color( &back_color, 1.0, 0.0, 0.0, 0.0, 0.0 ) ; bvec.x = bvec.y = radius * 12.0 ; bvec.z = -radius / 2.0 ; SET_COORD( backg[0], bvec.x, bvec.y, bvec.z ) ; SET_COORD( backg[1], -bvec.x, bvec.y, bvec.z ) ; SET_COORD( backg[2], -bvec.x, -bvec.y, bvec.z ) ; SET_COORD( backg[3], bvec.x, -bvec.y, bvec.z ) ; lib_output_polygon( 4, backg ) ; /* set up object color - off white */ SET_COORD( obj_color, 1.0, 0.9, 0.7 ) ; lib_output_color( &obj_color, 0.5, 0.5, 3.0, 0.0, 0.0 ) ; /* create set of spawned points */ create_objset() ; /* compute and output object */ SET_COORD4( center_pt, 0.0, 0.0, 0.0, radius / 2.0 ) ; SET_COORD4( direction, 0.0, 0.0, 1.0, 1.0/3.0 ) ; output_object( SIZE_FACTOR, ¢er_pt, &direction ) ; } /* Create the set of 9 vectors needed to generate the sphere set. */ /* Uses global 'objset' */ create_objset() { COORD4 axis, temp_pt, trio_dir[3] ; double dist ; MATRIX mx ; long num_set, num_vert ; dist = 1.0 / sqrt( (double)2.0 ) ; SET_COORD4( trio_dir[0], dist, dist, 0.0, 0.0 ) ; SET_COORD4( trio_dir[1], dist, 0.0, -dist, 0.0 ) ; SET_COORD4( trio_dir[2], 0.0, dist, -dist, 0.0 ) ; SET_COORD( axis, 1.0, -1.0, 0.0 ) ; lib_normalize_coord3( &axis ) ; lib_create_arbitrary_rotate_matrix( mx, &axis, asin( (double) ( 2.0 / sqrt( (double)6.0 ) ) ) ) ; for ( num_vert = 0 ; num_vert < 3 ; ++num_vert ) { lib_transform_coord( &temp_pt, &trio_dir[num_vert], mx ) ; COPY_COORD( trio_dir[num_vert], temp_pt ) ; } for ( num_set = 0 ; num_set < 3 ; ++num_set ) { lib_create_rotate_matrix( mx, Z_AXIS, num_set*2.0*PI/3.0 ) ; for ( num_vert = 0 ; num_vert < 3 ; ++num_vert ) { lib_transform_coord( &objset[num_set*3+num_vert], &trio_dir[num_vert], mx ) ; } } } /* * Output the parent sphere, then output the children of the sphere. * Uses global 'objset'. */ output_object( depth, center, direction ) long depth ; COORD4 *center ; COORD4 *direction ; { double angle ; COORD4 axis, z_axis ; COORD4 child_pt, child_dir ; MATRIX mx ; long num_vert ; double scale ; /* output sphere at location & radius defined by center */ lib_output_sphere( center, OUTPUT_FORMAT ) ; /* check if children should be generated */ if ( depth > 0 ) { --depth ; /* rotation matrix to new axis from +Z axis */ if ( direction->z >= 1.0 ) { /* identity matrix */ lib_create_identity_matrix( mx ) ; } else if ( direction->z <= -1.0 ) { lib_create_rotate_matrix( mx, Y_AXIS, PI ) ; } else { SET_COORD( z_axis, 0.0, 0.0, 1.0 ) ; CROSS( axis, z_axis, (*direction) ) ; lib_normalize_coord3( &axis ) ; angle = acos( (double)DOT_PRODUCT( z_axis, (*direction) ) ) ; lib_create_arbitrary_rotate_matrix( mx, &axis, angle ) ; } /* scale down location of new spheres */ scale = center->w * (1.0 + direction->w ) ; for ( num_vert = 0 ; num_vert < 9 ; ++num_vert ) { lib_transform_coord( &child_pt, &objset[num_vert], mx ) ; child_pt.x = child_pt.x * scale + center->x ; child_pt.y = child_pt.y * scale + center->y ; child_pt.z = child_pt.z * scale + center->z ; /* scale down radius */ child_pt.w = center->w * direction->w ; SUB3_COORD( child_dir, child_pt, (*center) ) ; child_dir.x /= scale ; child_dir.y /= scale ; child_dir.z /= scale ; child_dir.w = direction->w ; output_object( depth, &child_pt, &child_dir ) ; } } } @//E*O*F balls.c// chmod u=rw,g=r,o= balls.c echo x - gears.c sed 's/^@//' > "gears.c" <<'@//E*O*F gears.c//' /* * gears.c - Create a set of gears. Each gear face has 144 vertices, and * contains concavities. Note that the first 3 vertices of all polygons * define the two edges of a convex section of the polygon. Background * square floor is reflective. Some gears are clipped. * Five light sources. * * Version: 2.0 (7/9/87) * Author: Eric Haines, 3D/Eye, Inc. * * SIZE_FACTOR determines the number of polygons output. * Total gears = SF**3: concave polygons = 2 * SF**3 * rectangles = 4*TEETH * SF**3 * * SIZE_FACTOR # gears # gear faces # rectangles * 1 1 2 144 * 2 8 16 1152 * 3 27 54 3888 * 4 64 128 9216 */ #include #include #include #include "definitions.h" #include "lib.h" #define SIZE_FACTOR 4 /* define number of teeth on a gear - must be a multiple of 4 */ #define TEETH 36 /* define ratio of radius taken up by teeth and the gear thickness */ #define EDGE_RATIO 0.1 #define DEPTH_RATIO 0.1 main(argc,argv) int argc; char *argv[]; { COORD4 back_color, gear_color ; COORD4 center_pt, floor[4], light, offset, zero_pt ; COORD4 from, at, up ; double angle, color_scale, outer_radius, thickness ; long ix, iy, iz ; /* output viewpoint */ SET_COORD( from, -1.1, -2.1, 2.6 ) ; SET_COORD( at, 0.0, 0.0, 0.0 ) ; SET_COORD( up, 0.0, 0.0, 1.0 ) ; lib_output_viewpoint( &from, &at, &up, 45.0, 1.0, 512, 512 ) ; /* output background color - UNC sky blue */ SET_COORD( back_color, 0.078, 0.361, 0.753 ) ; lib_output_background_color( &back_color ) ; /* output light sources */ SET_COORD( light, 2.0, 4.0, 4.0 ) ; lib_output_light( &light ) ; SET_COORD( light, -2.0, 4.0, 3.0 ) ; lib_output_light( &light ) ; SET_COORD( light, 2.0, -2.5, 2.5 ) ; lib_output_light( &light ) ; SET_COORD( light, -1.0, -4.0, 2.0 ) ; lib_output_light( &light ) ; /* just behind the eye */ SET_COORD( light, -1.111, -2.121, 2.626 ) ; lib_output_light( &light ) ; /* output floor polygon - off white */ SET_COORD( back_color, 1.0, 0.85, 0.7 ) ; lib_output_color( &back_color, 0.75, 0.25, 25.0, 0.0, 0.0 ) ; SET_COORD( floor[0], 2.0, 2.0, 0.0 ) ; SET_COORD( floor[1], -2.0, 2.0, 0.0 ) ; SET_COORD( floor[2], -2.0, -2.0, 0.0 ) ; SET_COORD( floor[3], 2.0, -2.0, 0.0 ) ; lib_output_polygon( 4, floor ) ; outer_radius = 1.0 / ( (double)SIZE_FACTOR - (double)(SIZE_FACTOR-1) * EDGE_RATIO / 2.0 ) ; /* calculate first gear center */ zero_pt.x = zero_pt.y = -1.0 + outer_radius ; zero_pt.z = 1.0 ; /* calculate offset */ offset.x = offset.y = outer_radius * ( 2.0 - EDGE_RATIO ) ; offset.z = -1.0 / (double)SIZE_FACTOR ; /* create gears */ for ( iz = 0 ; iz < SIZE_FACTOR ; ++iz ) { center_pt.z = zero_pt.z + (double)iz * offset.z ; for ( iy = 0 ; iy < SIZE_FACTOR ; ++iy ) { center_pt.y = zero_pt.y + (double)iy * offset.y ; for ( ix = 0 ; ix < SIZE_FACTOR ; ++ix ) { center_pt.x = zero_pt.x + (double)ix * offset.x ; /* output pseudo-random gear color */ SET_COORD( gear_color , 0.01 + FRACTION( (double)(ix*3+iy*2+iz+1)*5.0/7.0 ) , 0.01 + FRACTION( (double)(iy*3+iz*2+ix+1)*3.0/7.0 ) , 0.01 + FRACTION( (double)(iz*3+ix*2+iy+1)*2.0/7.0 ) ) ; color_scale = MAX3( gear_color.x, gear_color.y, gear_color.z ) ; gear_color.x /= color_scale ; gear_color.y /= color_scale ; gear_color.z /= color_scale ; if ( ( ix*4 + iy*2 + iz ) % 5 == 0 ) { lib_output_color( &gear_color, 0.75, 0.25, 50.0, 0.95, 1.1 ) ; } else { lib_output_color( &gear_color, 1.0, 0.0, 0.0, 0.0, 0.0 ) ; } /* output gear */ angle = PI * (double)( (ix+iy+iz) % 2 ) / (double)(TEETH) ; thickness = MIN( DEPTH_RATIO, 1.0 / ( 2.0 * (double)SIZE_FACTOR ) ) ; create_gear( ¢er_pt, angle, outer_radius, (1.0 - EDGE_RATIO) * outer_radius, thickness ) ; } } } } /* Create gear */ create_gear( center, offset_angle, outer_radius, inner_radius, thickness ) COORD4 *center ; double offset_angle ; double outer_radius ; double inner_radius ; double thickness ; { COORD4 side_pts[4], gear_pts[4*TEETH], outer_pt, inner_pt ; long next_side, num_side, num_teeth ; double gear_angle, tooth_angle ; outer_pt.x = outer_radius ; outer_pt.y = 0.0 ; outer_pt.z = 0.0 ; outer_pt.w = 1.0 ; inner_pt.x = inner_radius ; inner_pt.y = 0.0 ; inner_pt.z = 0.0 ; inner_pt.w = 1.0 ; tooth_angle = 2.0 * PI / (double)TEETH ; /* output gear top */ for ( num_teeth = 0 ; num_teeth < TEETH ; ++num_teeth ) { gear_angle = offset_angle + 2.0 * PI * (double)num_teeth / (double)TEETH ; create_tooth( gear_angle , tooth_angle , center , &outer_pt , &inner_pt , &gear_pts[num_teeth*4] ) ; } lib_output_polygon( 4*TEETH, gear_pts ) ; /* output teeth */ for ( num_side = 0 ; num_side < 4 * TEETH ; ++num_side ) { next_side = ( num_side + 1 ) % ( 4 * TEETH ) ; COPY_COORD( side_pts[0], gear_pts[num_side] ) ; COPY_COORD( side_pts[1], gear_pts[num_side] ) ; side_pts[1].z -= thickness ; COPY_COORD( side_pts[2], gear_pts[next_side] ) ; side_pts[2].z -= thickness ; COPY_COORD( side_pts[3], gear_pts[next_side] ) ; lib_output_polygon( 4, side_pts ) ; } /* output gear bottom */ outer_pt.z = inner_pt.z = -thickness ; for ( num_teeth = 0 ; num_teeth < TEETH ; ++num_teeth ) { gear_angle = offset_angle - 2.0 * PI * (double)num_teeth / (double)TEETH ; create_tooth( gear_angle , -tooth_angle , center , &outer_pt , &inner_pt , &gear_pts[num_teeth*4] ) ; } lib_output_polygon( 4*TEETH, gear_pts ) ; } /* Create gear tooth */ create_tooth( gear_angle, tooth_angle, center, outer_pt, inner_pt, edge_pts ) double gear_angle ; double tooth_angle ; COORD4 *center ; COORD4 *outer_pt ; COORD4 *inner_pt ; COORD4 *edge_pts ; { MATRIX mx ; lib_create_rotate_matrix( mx , Z_AXIS , gear_angle - 0.19 * tooth_angle ) ; lib_transform_coord( &edge_pts[0], outer_pt, mx ) ; ADD2_COORD( edge_pts[0], *center ) ; lib_create_rotate_matrix( mx , Z_AXIS , gear_angle + 0.19 * tooth_angle ) ; lib_transform_coord( &edge_pts[1], outer_pt, mx ) ; ADD2_COORD( edge_pts[1], *center ) ; lib_create_rotate_matrix( mx , Z_AXIS , gear_angle + 0.3 * tooth_angle ) ; lib_transform_coord( &edge_pts[2], inner_pt, mx ) ; ADD2_COORD( edge_pts[2], *center ) ; lib_create_rotate_matrix( mx , Z_AXIS , gear_angle + 0.7 * tooth_angle ) ; lib_transform_coord( &edge_pts[3], inner_pt, mx ) ; ADD2_COORD( edge_pts[3], *center ) ; } @//E*O*F gears.c// chmod u=rw,g=r,o= gears.c echo x - mountain.c sed 's/^@//' > "mountain.c" <<'@//E*O*F mountain.c//' /* * mountain.c - creates a fractal mountain, using Carpenter's method with a * different extension to square grids. A pyramid of 4 glass spheres * is added in front of the mountain. None of the spheres are clipped. * A few of the polygons are clipped. One light source. * * Version: 2.0 (7/9/87) * Author: Eric Haines, 3D/Eye, Inc. * * SIZE_FACTOR determines the number of objects output. * Total triangular polygons = 2 * (4**SIZE_FACTOR) * * SIZE_FACTOR # triangles # spheres * 1 8 4 * 2 32 4 * 3 128 4 * * 6 8192 4 */ #include #include #include #include "definitions.h" #include "lib.h" #define OUTPUT_FORMAT OUTPUT_CURVES /* size factor determines number of polygons */ #define SIZE_FACTOR 6 /* fractal dimension - affects variance of z. Between 2 and 3 */ #define FRACTAL_DIMENSION 2.2 /* change MOUNTAIN_NO to get a different mountain */ #define MOUNTAIN_NO 21 /* lower left corner and width of mountain definitions */ #define X_CORNER -1.0 #define Y_CORNER -1.0 #define WIDTH 2.0 /* hashing function to get a seed for the random number generator */ #define hash_rand(A,B,C) ( ( ((A)<<(23-(C))) + ((B)<<(15-(C)))\ + ((A)<<(7-(C))) ) & 0xffff ) static long num_pts ; static double roughness ; main(argc,argv) int argc; char *argv[]; { COORD4 back_color, obj_color ; COORD4 center, light ; COORD4 from, at, up ; double ratio ; /* output viewpoint */ SET_COORD( from, -1.6, 1.6, 1.7 ) ; SET_COORD( at, 0.0, 0.0, 0.0 ) ; SET_COORD( up, 0.0, 0.0, 1.0 ) ; lib_output_viewpoint( &from, &at, &up, 45.0, 0.5, 512, 512 ) ; /* output background color - UNC sky blue */ SET_COORD( back_color, 0.078, 0.361, 0.753 ) ; lib_output_background_color( &back_color ) ; /* output light sources */ SET_COORD( light, -100.0, -100.0, 100.0 ) ; lib_output_light( &light ) ; /* set up crystal sphere color - clear white */ SET_COORD( obj_color, 1.0, 1.0, 1.0 ) ; lib_output_color( &obj_color, 0.1, 0.9, 100.0, 0.9, 1.5 ) ; /* output crystal spheres */ SET_COORD4( center, -0.8, 0.8, 1.00, 0.17 ) ; create_spheres( ¢er ) ; /* set up mountain color - grey */ SET_COORD( obj_color, 0.5, 0.45, 0.35 ) ; lib_output_color( &obj_color, 1.0, 0.0, 0.0, 0.0, 0.0 ) ; /* grow mountain */ num_pts = 1<w * sqrt( (double)( 3.0/2.0 ) ), 0.0 ) ; COPY_COORD( sphere, pt ) ; ADD2_COORD( sphere, *center ) ; sphere.w = center->w ; lib_output_sphere( &sphere, OUTPUT_FORMAT ) ; lib_create_arbitrary_rotate_matrix( mx, &axis, angle ) ; lib_transform_coord( &new_pt, &pt, mx ) ; for ( i = 0 ; i < 3 ; ++i ) { lib_create_rotate_matrix( mx, Z_AXIS, (double)i * 2.0 * PI / 3.0 ) ; lib_transform_coord( &sphere, &new_pt, mx ) ; ADD2_COORD( sphere, *center ) ; sphere.w = center->w ; lib_output_sphere( &sphere, OUTPUT_FORMAT ) ; } } /* * Build mountain section. If at width > 1, split quadrilateral into four * parts. Else if at width == 1, output quadrilateral as two triangles. */ grow_mountain( width, ll_x, ll_y, ll_fz, lr_fz, ur_fz, ul_fz ) long width ; long ll_x ; long ll_y ; double ll_fz ; double lr_fz ; double ur_fz ; double ul_fz ; { long half_width, iz ; double l_fx, r_fx, l_fy, u_fy ; double lower_fz, right_fz, upper_fz, left_fz, middle_fz ; long num_tri, num_tri_vert, num_vert ; double rise_height, hside_length ; COORD4 tri_vert[3] ; if ( width == 1 ) { /* calculate x and y coordinates of corners */ l_fx = X_CORNER + (double)ll_x * WIDTH / (double)num_pts ; r_fx = X_CORNER + (double)(ll_x+1) * WIDTH / (double)num_pts ; l_fy = Y_CORNER + (double)ll_y * WIDTH / (double)num_pts ; u_fy = Y_CORNER + (double)(ll_y+1) * WIDTH / (double)num_pts ; /* output two triangles for section */ for ( num_tri = 0 ; num_tri < 2 ; ++num_tri ) { for ( num_vert = 0 ; num_vert < 3 ; ++num_vert ) { num_tri_vert = ( num_vert + num_tri * 2 ) % 4 ; if ( num_tri_vert == 0 ) { SET_COORD( tri_vert[num_vert], l_fx, l_fy, ll_fz ) ; } else if ( num_tri_vert == 1 ) { SET_COORD( tri_vert[num_vert], r_fx, l_fy, lr_fz ) ; } else if ( num_tri_vert == 2 ) { SET_COORD( tri_vert[num_vert], r_fx, u_fy, ur_fz ) ; } else { SET_COORD( tri_vert[num_vert], l_fx, u_fy, ul_fz ) ; } } lib_output_polygon( 3, tri_vert ) ; } } else { /* subdivide edges and move in z direction */ half_width = width>>1 ; hside_length = (double)half_width * WIDTH / (double)num_pts ; rise_height = hside_length * roughness ; /* for each midpoint, find z */ iz = MOUNTAIN_NO + hash_rand( ll_x + half_width, ll_y, SIZE_FACTOR ) ; lower_fz = ( ll_fz + lr_fz ) / 2.0 + rise_height * lib_gauss_rand( iz ) ; iz = MOUNTAIN_NO + hash_rand( ll_x + width, ll_y + half_width, SIZE_FACTOR ) ; right_fz = ( lr_fz + ur_fz ) / 2.0 + rise_height * lib_gauss_rand( iz ) ; iz = MOUNTAIN_NO + hash_rand( ll_x + half_width, ll_y + width, SIZE_FACTOR ) ; upper_fz = ( ur_fz + ul_fz ) / 2.0 + rise_height * lib_gauss_rand( iz ) ; iz = MOUNTAIN_NO + hash_rand( ll_x, ll_y + half_width, SIZE_FACTOR ) ; left_fz = ( ul_fz + ll_fz ) / 2.0 + rise_height * lib_gauss_rand( iz ) ; iz = MOUNTAIN_NO + hash_rand( ll_x + half_width, ll_y + half_width, SIZE_FACTOR ) ; middle_fz = ( ll_fz + lr_fz + ur_fz + ul_fz ) / 4.0 + 1.4142136 * rise_height * lib_gauss_rand( iz ) ; /* check subsections for subdivision or output */ grow_mountain( half_width, ll_x, ll_y, ll_fz, lower_fz, middle_fz, left_fz ) ; grow_mountain( half_width, ll_x+half_width, ll_y, lower_fz, lr_fz, right_fz, middle_fz ) ; grow_mountain( half_width, ll_x+half_width, ll_y+half_width, middle_fz, right_fz, ur_fz, upper_fz ) ; grow_mountain( half_width, ll_x, ll_y+half_width, left_fz, middle_fz, upper_fz, ul_fz ) ; } } @//E*O*F mountain.c// chmod u=rw,g=r,o= mountain.c echo x - rings.c sed 's/^@//' > "rings.c" <<'@//E*O*F rings.c//' /* * rings.c - Create objects with 6 pentagonal rings which connect the midpoints * of the edges of a dodecahedron. A pyramid of these objects is formed, * which the viewer looks upon from the point. A plane is placed behind the * pyramid for shadows. No object is clipped. Three light sources. * * Version: 2.0 (7/9/87) * Author: Eric Haines, 3D/Eye, Inc. * * SIZE_FACTOR determines the number of objects output. * Each object has 30 cylinders and 30 spheres. * Total objects = SF*SF + (SF-1)*(SF-1) + ... + 1 plus 1 backdrop square. * formula for # of spheres or cylinders = 5*SF*(SF+1)*(2*SF+1) * * SIZE_FACTOR # spheres # cylinders # squares * 1 30 30 1 * 2 150 150 1 * 3 420 420 1 * * 7 4200 4200 1 */ #include #include #include #include "definitions.h" #include "lib.h" #define OUTPUT_FORMAT OUTPUT_CURVES #define SIZE_FACTOR 7 /* if spread out is > 1, succeeding layers spread out more */ #define SPREAD_OUT 1 main(argc,argv) int argc; char *argv[]; { COORD4 base_pt, apex_pt, offset ; COORD4 wall[4], dodec[30] ; COORD4 from, at, up ; COORD4 wvec, light ; COORD4 back_color, ring_color[6] ; long prev_elem ; long num_elem ; long num_depth, num_objx, num_objz ; double radius ; double spread, y_diff, xz_diff ; radius = 0.07412 ; /* cone and sphere radius */ /* calculate spread of objects */ spread = 1 / sin( (double)( PI/8.0 ) ) ; if ( SPREAD_OUT <= spread ) { y_diff = spread / SPREAD_OUT ; xz_diff = 1.0 ; } else { y_diff = 1.0 ; xz_diff = SPREAD_OUT / spread ; } /* output viewpoint */ SET_COORD( from, -1.0, -spread, 0.5 ) ; SET_COORD( at, from.x, from.y + 1.0, from.z ) ; SET_COORD( up, 0.0, 0.0, 1.0 ) ; lib_output_viewpoint( &from, &at, &up, 45.0, 1.0, 512, 512 ) ; /* output background color - UNC sky blue */ /* note that the background color should never be seen */ SET_COORD( back_color, 0.078, 0.361, 0.753 ) ; lib_output_background_color( &back_color ) ; /* output light source */ SET_COORD( light, 3.0, -spread, 3.0 ) ; lib_output_light( &light ) ; SET_COORD( light, -4.0, -spread, 1.0 ) ; lib_output_light( &light ) ; SET_COORD( light, 2.0, -spread, -4.0 ) ; lib_output_light( &light ) ; /* output wall polygon - white */ SET_COORD( back_color, 1.0, 1.0, 1.0 ) ; lib_output_color( &back_color, 1.0, 0.0, 0.0, 0.0, 0.0 ) ; /* just spans 45 degree view + 1% */ wvec.y = y_diff * ( SIZE_FACTOR + 1 ) ; wvec.x = wvec.z = 1.01 * ( wvec.y - from.y ) * tan( PI / 8.0 ) ; SET_COORD( wall[0], wvec.x+from.x, wvec.y, wvec.z+from.z ) ; SET_COORD( wall[1], -wvec.x+from.x, wvec.y, wvec.z+from.z ) ; SET_COORD( wall[2], -wvec.x+from.x, wvec.y, -wvec.z+from.z ) ; SET_COORD( wall[3], wvec.x+from.x, wvec.y, -wvec.z+from.z ) ; lib_output_polygon( 4, wall ) ; /* set up ring colors - RGB and complements */ SET_COORD( ring_color[0], 1.0, 0.0, 0.0 ) ; SET_COORD( ring_color[1], 0.0, 1.0, 0.0 ) ; SET_COORD( ring_color[2], 0.0, 0.0, 1.0 ) ; SET_COORD( ring_color[3], 0.0, 1.0, 1.0 ) ; SET_COORD( ring_color[4], 1.0, 0.0, 1.0 ) ; SET_COORD( ring_color[5], 1.0, 1.0, 0.0 ) ; create_dodec( radius, dodec ) ; /* radius of osculating cylinders and spheres (no derivation given) */ base_pt.w = apex_pt.w = radius ; for ( num_depth = 0 ; num_depth < SIZE_FACTOR ; ++num_depth ) { offset.y = y_diff * (double)(num_depth+1) ; for ( num_objz = 0 ; num_objz <= num_depth ; ++num_objz ) { offset.z = xz_diff * (double)(2*num_objz - num_depth) ; for ( num_objx = 0 ; num_objx <= num_depth ; ++num_objx ) { offset.x = xz_diff * (double)(2*num_objx - num_depth) ; for ( num_elem = 0 ; num_elem < 30 ; ++num_elem ) { COPY_COORD( base_pt, dodec[num_elem] ) ; ADD2_COORD( base_pt, offset ) ; if ( num_elem%5 == 0 ) { prev_elem = num_elem + 4 ; /* new ring beginning - output color */ lib_output_color( &ring_color[num_elem/5] , 0.5 , 0.5, 3.0 , 0.0, 0.0 ) ; } else { prev_elem = num_elem - 1 ; } COPY_COORD( apex_pt, dodec[prev_elem] ) ; ADD2_COORD( apex_pt, offset ) ; lib_output_cylcone( &base_pt, &apex_pt, OUTPUT_FORMAT ) ; lib_output_sphere( &base_pt, OUTPUT_FORMAT ) ; } } } } } /* Create the set of 30 points needed to generate the rings */ create_dodec( minor_radius, vertex ) double minor_radius ; COORD4 vertex[30] ; { long num_vertex, num_pentagon ; COORD4 temp_vertex ; MATRIX x_matrix, z_matrix ; double scale, x_rotation, z_rotation ; /* scale object to fit in a sphere of radius 1 */ scale = 1.0 / ( 1.0 + minor_radius ) ; /* * define one pentagon as on the XY plane, with points starting along +X and * N fifths of the way around the Z axis. */ for ( num_vertex = 0 ; num_vertex < 5 ; ++num_vertex ) { vertex[num_vertex].x = scale * cos( (double)num_vertex * 2.0*PI/5.0 ) ; vertex[num_vertex].y = scale * sin( (double)num_vertex * 2.0*PI/5.0 ) ; vertex[num_vertex].z = 0.0 ; vertex[num_vertex].w = 1.0 ; } /* * find the rotation angle (in radians) along the X axis: * angle between two adjacent dodecahedron faces. */ x_rotation = 2.0 * acos( cos( (double)(PI/3.0) ) / sin( (double)(PI/5.0) ) ) ; lib_create_rotate_matrix( x_matrix, X_AXIS, x_rotation ) ; /* * Find each of the other 5 pentagons: rotate along the X axis, * then rotate on the Z axis. */ for ( num_pentagon = 1 ; num_pentagon < 6 ; ++num_pentagon ) { /* * find the rotation angle (in radians) along the Z axis: * 1/10th plus N fifths of the way around * 2 * PI. */ z_rotation = PI*( 2.0*(double)(num_pentagon-1)+1.0 ) / 5.0 ; lib_create_rotate_matrix( z_matrix, Z_AXIS, z_rotation ) ; for ( num_vertex = 0 ; num_vertex < 5 ; ++num_vertex ) { lib_transform_coord( &temp_vertex , &vertex[num_vertex] , x_matrix ) ; lib_transform_coord( &vertex[5*num_pentagon+num_vertex] , &temp_vertex , z_matrix ) ; } } } @//E*O*F rings.c// chmod u=rw,g=r,o= rings.c echo x - tetra.c sed 's/^@//' > "tetra.c" <<'@//E*O*F tetra.c//' /* * tetra.c - Create a tetrahedral pyramid. This environment is based on the * scene used by Glassner ("Space Subdivision for Fast Ray Tracing," IEEE * CG&A, October 1984) and Kay & Kajiya ("Ray Tracing Complex Scenes," * SIGGRAPH '86 Proceedings) for testing their ray tracers. No polygons * are clipped. One light source. * * Version: 2.0 (7/9/87) * Author: Eric Haines, 3D/Eye, Inc. * * Note: the view and light positions are the same (after transformation to * a different set of world coordinates) as used by Kay & Kajiya, * courtesy of Tim Kay. For some reason, the number of shadow rays * generated is different (Kay gets 34K, I get 46K). One light source. * * SIZE_FACTOR determines the number of polygons output. * Total triangular polygons = 4**SF * * SIZE_FACTOR # triangles * 1 4 * 2 16 * 3 64 * * 6 4096 */ #include #include #include #include "definitions.h" #include "lib.h" #define SIZE_FACTOR 6 main(argc,argv) int argc; char *argv[]; { COORD4 back_color, tetra_color ; COORD4 center_pt, light ; COORD4 from, at, up ; /* output viewpoint */ SET_COORD( from, 1.022846, -3.177154, -2.174512 ) ; SET_COORD( at, -0.004103, -0.004103, 0.216539 ) ; SET_COORD( up, -0.816497, -0.816497, 0.816497 ) ; lib_output_viewpoint( &from, &at, &up, 45.0, 1.0, 512, 512 ) ; /* output background color - UNC sky blue */ SET_COORD( back_color, 0.078, 0.361, 0.753 ) ; lib_output_background_color( &back_color ) ; /* output light source */ SET_COORD( light, 1.876066, -18.123936, -5.000422 ) ; lib_output_light( &light ) ; /* output tetrahedron color - red */ SET_COORD( tetra_color, 1.0, 0.2, 0.2 ) ; lib_output_color( &tetra_color, 1.0, 0.0, 0.0, 0.0, 0.0 ) ; /* compute and output tetrahedral object */ SET_COORD4( center_pt, 0.0, 0.0, 0.0, 1.0 ) ; create_tetra( SIZE_FACTOR, ¢er_pt ) ; } /* Create tetrahedrons recursively */ create_tetra( depth, center ) long depth ; COORD4 *center ; { long num_face, num_vert ; COORD4 face_pt[3], obj_pt[4], sub_center ; long swap, vert_ord[3] ; long x_dir, y_dir, z_dir ; if ( depth <= 1 ) { /* Output tetrahedron */ /* find opposite corners of a cube which form a tetrahedron */ for ( num_vert = 0, x_dir = -1 ; x_dir <= 1 ; x_dir += 2 ) { for ( y_dir = -1 ; y_dir <= 1 ; y_dir += 2 ) { for ( z_dir = -1 ; z_dir <= 1 ; z_dir += 2 ) { if ( x_dir*y_dir*z_dir == 1 ) { obj_pt[num_vert].x = center->x + (double)x_dir * center->w ; obj_pt[num_vert].y = center->y + (double)y_dir * center->w ; obj_pt[num_vert].z = center->z + (double)z_dir * center->w ; ++num_vert ; } } } } /* find faces and output */ for ( num_face = 0 ; num_face < 4 ; ++num_face ) { /* output order: * face 0: points 0 1 2 * face 1: points 3 2 1 * face 2: points 2 3 0 * face 3: points 1 0 3 */ for ( num_vert = 0 ; num_vert < 3 ; ++num_vert ) { vert_ord[num_vert] = (num_face + num_vert) % 4 ; } if ( num_face%2 == 1 ) { swap = vert_ord[0] ; vert_ord[0] = vert_ord[2] ; vert_ord[2] = swap ; } for ( num_vert = 0 ; num_vert < 3 ; ++num_vert ) { COPY_COORD( face_pt[num_vert], obj_pt[vert_ord[num_vert]] ) ; } lib_output_polygon( 3, face_pt ) ; } } else { /* Create sub-tetrahedra */ /* find opposite corners of a cube to form sub-tetrahedra */ for ( x_dir = -1 ; x_dir <= 1 ; x_dir += 2 ) { for ( y_dir = -1 ; y_dir <= 1 ; y_dir += 2 ) { for ( z_dir = -1 ; z_dir <= 1 ; z_dir += 2 ) { if ( x_dir*y_dir*z_dir == 1 ) { sub_center.x = center->x + (double)x_dir * center->w / 2.0 ; sub_center.y = center->y + (double)y_dir * center->w / 2.0 ; sub_center.z = center->z + (double)z_dir * center->w / 2.0 ; sub_center.w = center->w / 2.0 ; create_tetra( depth-1, &sub_center ) ; } } } } } } @//E*O*F tetra.c// chmod u=rw,g=r,o= tetra.c echo x - tree.c sed 's/^@//' > "tree.c" <<'@//E*O*F tree.c//' /* * tree.c - Creates a tree using Aono & Kunii's generation method. * (See IEEE CG&A May 1984). A square polygon is placed beneath the * tree to act as a field. No tree branch is clipped. Seven light sources. * * Version: 2.0 (7/9/87) * Author: Eric Haines, 3D/Eye, Inc. * * SIZE_FACTOR determines the number of objects output. * Total objects = 2**(SF+1)-1 cones and spheres + 1 square polygon. * * SIZE_FACTOR # spheres # cones # squares * 1 3 3 1 * 2 7 7 1 * 3 15 15 1 * * 11 4095 4095 1 */ #include #include #include #include "definitions.h" #include "lib.h" #define OUTPUT_FORMAT OUTPUT_CURVES #define SIZE_FACTOR 11 /* the following affect the shape of the tree */ #define BR_ANGLE_0 40.0 #define BR_ANGLE_1 25.0 #define BR_CONTR_0 0.65 #define BR_CONTR_1 0.70 #define BR_DIAMETER 0.67 #define DIV_ANGLE 140.0 #define WIDTH_HEIGHTH_RATIO 0.15 static MATRIX rst_mx[2] ; main(argc,argv) int argc; char *argv[]; { COORD4 field[4] ; COORD4 from, at, up ; COORD4 light ; COORD4 back_color, tree_color ; /* output viewpoint */ SET_COORD( from, 4.5, 0.4, 2.0 ) ; SET_COORD( at, 0.0, 0.0, 1.5 ) ; SET_COORD( up, 0.0, 0.0, 1.0 ) ; lib_output_viewpoint( &from, &at, &up, 45.0, 1.0, 512, 512 ) ; /* output background color - UNC sky blue */ SET_COORD( back_color, 0.078, 0.361, 0.753 ) ; lib_output_background_color( &back_color ) ; /* output light source */ SET_COORD( light, -5.0, 5.0, 50.0 ) ; lib_output_light( &light ) ; SET_COORD( light, 30.0, -30.0, 30.0 ) ; lib_output_light( &light ) ; SET_COORD( light, -40.0, -30.0, 20.0 ) ; lib_output_light( &light ) ; SET_COORD( light, 10.0, 30.0, 40.0 ) ; lib_output_light( &light ) ; SET_COORD( light, -30.0, 40.0, 10.0 ) ; lib_output_light( &light ) ; SET_COORD( light, 50.0, 25.0, 20.0 ) ; lib_output_light( &light ) ; SET_COORD( light, -10.0, -60.0, 30.0 ) ; lib_output_light( &light ) ; /* output field polygon - green */ SET_COORD( back_color, 0.2, 0.7, 0.2 ) ; lib_output_color( &back_color, 1.0, 0.0, 0.0, 0.0, 0.0 ) ; SET_COORD( field[0], 50.0, 50.0, 0.0 ) ; SET_COORD( field[1], -50.0, 50.0, 0.0 ) ; SET_COORD( field[2], -50.0, -50.0, 0.0 ) ; SET_COORD( field[3], 50.0, -50.0, 0.0 ) ; lib_output_polygon( 4, field ) ; /* set up tree color - brown */ SET_COORD( tree_color, 0.55, 0.4, 0.2 ) ; lib_output_color( &tree_color, 1.0, 0.0, 0.0, 0.0, 0.0 ) ; /* create tree */ create_tree() ; } /* * Set up matrices for growth of each branch with respect to the * parent branch, then grow each branch. */ create_tree() { double branch_angle, branch_contraction, divergence ; long i ; MATRIX ident_mx, temp1_mx, temp2_mx, tempr_mx, tempst_mx ; for ( i = 0 ; i < 2 ; ++i ) { if ( i == 0 ) { branch_angle = BR_ANGLE_0 ; divergence = 90.0 ; branch_contraction = BR_CONTR_0 ; } else { branch_angle = BR_ANGLE_1 ; divergence = DIV_ANGLE + 90.0 ; branch_contraction = BR_CONTR_1 ; } /* rotate along X axis by branching angle */ lib_create_rotate_matrix( temp1_mx, X_AXIS, branch_angle*PI/180.0 ) ; /* rotate along Z axis by divergence angle */ lib_create_rotate_matrix( temp2_mx, Z_AXIS, divergence*PI/180.0 ) ; lib_matrix_multiply( tempr_mx, temp1_mx, temp2_mx ) ; /* include translation of branch, scaled */ lib_create_identity_matrix( tempst_mx ) ; tempst_mx[0][0] = tempst_mx[1][1] = tempst_mx[2][2] = branch_contraction ; tempst_mx[3][2] = 1.0 ; /* concatenate */ lib_matrix_multiply( rst_mx[i], tempr_mx, tempst_mx ) ; } /* set up initial matrix */ lib_create_identity_matrix( ident_mx ) ; grow_tree( ident_mx, 1.0, SIZE_FACTOR ) ; } /* grow tree branches recursively */ grow_tree( cur_mx, scale, depth ) MATRIX cur_mx ; double scale ; long depth ; { COORD4 apex, base, vec ; long i ; MATRIX new_mx ; /* output branch */ SET_COORD4( vec, 0.0, 0.0, 0.0, 1.0 ) ; lib_transform_coord( &base, &vec, cur_mx ) ; base.w = scale * WIDTH_HEIGHTH_RATIO ; SET_COORD4( vec, 0.0, 0.0, 1.0, 1.0 ) ; lib_transform_coord( &apex, &vec, cur_mx ) ; apex.w = base.w * BR_DIAMETER ; lib_output_cylcone( &base, &apex, OUTPUT_FORMAT ) ; lib_output_sphere( &apex, OUTPUT_FORMAT ) ; if ( depth > 0 ) { --depth ; for ( i = 0; i < 2; ++i ) { lib_matrix_multiply( new_mx, rst_mx[i], cur_mx ) ; grow_tree( new_mx, scale * BR_DIAMETER, depth ) ; } } } @//E*O*F tree.c// chmod u=rw,g=r,o= tree.c exit 0