home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
gondwana.ecr.mu.oz.au/pub/
/
Graphics.tar
/
Graphics
/
SPD.3.0.shar.gz
/
SPD.3.0.shar
/
rings.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-01-13
|
6KB
|
198 lines
/*
* 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. Three light sources.
*
* Author: Eric Haines, 3D/Eye, Inc.
*
* SizeFactor 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)
*
* SizeFactor # spheres # cylinders # squares
* 1 30 30 1
* 2 150 150 1
* 3 420 420 1
*
* 7 4200 4200 1
*/
#include <stdio.h>
#include <math.h>
#include "def.h"
#include "lib.h"
static int SizeFactor = 7 ;
#define OUTPUT_FORMAT OUTPUT_CURVES
/* if spread out is > 1, succeeding layers spread out more */
#define SPREAD_OUT 1
main(argc,argv)
int argc ;
char *argv[] ;
{
int prev_elem, num_elem, num_depth, num_objx, num_objz ;
double radius, spread, y_diff, xz_diff ;
COORD4 base_pt, apex_pt ;
COORD3 from, at, up ;
COORD3 wvec, light ;
COORD3 back_color, ring_color[6] ;
COORD3 wall[4], offset, dodec[30] ;
if ( !lib_get_size( argc, argv, &SizeFactor ) ) {
fprintf( stderr, "usage: %s [size]\n", *argv ) ;
exit(EXIT_FAIL) ;
}
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_COORD3( from, -1.0, -spread, 0.5 ) ;
SET_COORD3( at, from[X], from[Y] + 1.0, from[Z] ) ;
SET_COORD3( 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_COORD3( back_color, 0.078, 0.361, 0.753 ) ;
lib_output_background_color( back_color ) ;
/* output light source */
SET_COORD3( light, 3.0, -spread, 3.0 ) ;
lib_output_light( light ) ;
SET_COORD3( light, -4.0, -spread, 1.0 ) ;
lib_output_light( light ) ;
SET_COORD3( light, 2.0, -spread, -4.0 ) ;
lib_output_light( light ) ;
/* output wall polygon - white */
SET_COORD3( 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 * ( SizeFactor + 1 ) ;
wvec[X] = wvec[Z] = 1.01 * ( wvec[Y] - from[Y] ) * tan( PI / 8.0 ) ;
SET_COORD3( wall[0], wvec[X]+from[X], wvec[Y], wvec[Z]+from[Z] ) ;
SET_COORD3( wall[1], -wvec[X]+from[X], wvec[Y], wvec[Z]+from[Z] ) ;
SET_COORD3( wall[2], -wvec[X]+from[X], wvec[Y], -wvec[Z]+from[Z] ) ;
SET_COORD3( 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_COORD3( ring_color[0], 1.0, 0.0, 0.0 ) ;
SET_COORD3( ring_color[1], 0.0, 1.0, 0.0 ) ;
SET_COORD3( ring_color[2], 0.0, 0.0, 1.0 ) ;
SET_COORD3( ring_color[3], 0.0, 1.0, 1.0 ) ;
SET_COORD3( ring_color[4], 1.0, 0.0, 1.0 ) ;
SET_COORD3( 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 < SizeFactor ; ++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_COORD3( base_pt, dodec[num_elem] ) ;
ADD2_COORD3( 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_COORD3( apex_pt, dodec[prev_elem] ) ;
ADD2_COORD3( apex_pt, offset ) ;
lib_output_cylcone( base_pt, apex_pt, OUTPUT_FORMAT ) ;
lib_output_sphere( base_pt, OUTPUT_FORMAT ) ;
}
}
}
}
exit(EXIT_SUCCESS) ;
}
/* Create the set of 30 points needed to generate the rings */
create_dodec( minor_radius, vertex )
double minor_radius ;
COORD3 vertex[30] ;
{
int num_vertex, num_pentagon ;
double scale, x_rotation, z_rotation ;
COORD3 temp_vertex ;
MATRIX x_matrix, z_matrix ;
/* 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_point( temp_vertex
, vertex[num_vertex]
, x_matrix
) ;
lib_transform_point( vertex[5*num_pentagon+num_vertex]
, temp_vertex
, z_matrix
) ;
}
}
}