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