/* orbit.c 1.1 */ /* Copyright 1992, 1993 O'Reilly and Associates, Inc. Permission to use, copy, and modify this program is hereby granted, as long as this copyright notice appears in each copy of the program source code. */ #include "book_utils.h" static Display *dpy; static Window window; static PEXRenderer renderer; /* The structure ids. */ static PEXStructure system, star, planet, moon, circle; #define STAR_RADIUS 0.12 #define PLANET_RADIUS 0.05 #define MOON_RADIUS 0.02 #define PLANET_ORBIT (2.5 * STAR_RADIUS + PLANET_RADIUS) #define MOON_ORBIT (1.25 * PLANET_RADIUS + MOON_RADIUS) #define NUM_CIRCLE_FACETS 6 void create_model() { PEXCoord2D circle_points[NUM_CIRCLE_FACETS+1]; PEXColor color; PEXMatrix3x3 xform; PEXVector2D shift, scale; double angle, incr; int i; /* Make the unit circle for the generic heavenly body. */ angle = 0; incr = (2*M_PI) / NUM_CIRCLE_FACETS; for ( i = 0; i <= NUM_CIRCLE_FACETS; i++ ) { circle_points[i].x = cos( angle ); circle_points[i].y = sin( angle ); angle += incr; } /* Create the circle structure. */ circle = PEXCreateStructure( dpy ); PEXFillArea2D( dpy, circle, PEXOCStore, PEXShapeConvex, True, NUM_CIRCLE_FACETS + 1, circle_points ); /* Create the moon structure. */ moon = PEXCreateStructure( dpy ); SET_COLOR( 1, 1, 1, color ) PEXSetSurfaceColor( dpy, moon, PEXOCStore, PEXColorTypeRGB, &color ); /* Scale and instance the circle for the moon. */ scale.x = scale.y = MOON_RADIUS; PEXScale2D( &scale, xform ); PEXSetLocalTransform2D( dpy, moon, PEXOCStore, PEXReplace, xform ); PEXExecuteStructure( dpy, moon, PEXOCStore, circle ); /* Create the planet structure. */ planet = PEXCreateStructure( dpy ); SET_COLOR( 0, 1, 0, color ) PEXSetSurfaceColor( dpy, planet, PEXOCStore, PEXColorTypeRGB, &color ); /* Scale and instance the circle for the planet. */ scale.x = scale.y = PLANET_RADIUS; PEXScale2D( &scale, xform ); PEXSetLocalTransform2D( dpy, planet, PEXOCStore, PEXReplace, xform ); PEXExecuteStructure( dpy, planet, PEXOCStore, circle ); /* Position and instance the moon. */ PEXRotate2D( 0.0, xform ); PEXSetLocalTransform2D( dpy, planet, PEXOCStore, PEXReplace, xform ); shift.x = MOON_ORBIT; shift.y = 0.0; PEXTranslate2D( &shift, xform ); PEXSetLocalTransform2D( dpy, planet, PEXOCStore, PEXPreConcatenate, xform ); PEXExecuteStructure( dpy, planet, PEXOCStore, moon ); /* Create the star structure. */ star = PEXCreateStructure( dpy ); SET_COLOR( 1, 1, 0, color ) PEXSetSurfaceColor( dpy, star, PEXOCStore, PEXColorTypeRGB, &color ); /* Scale and instance the circle for the star. */ scale.x = scale.y = STAR_RADIUS; PEXScale2D( &scale, xform ); PEXSetLocalTransform2D( dpy, star, PEXOCStore, PEXReplace, xform ); PEXExecuteStructure( dpy, star, PEXOCStore, circle ); /* Position and instance the planet. */ PEXRotate2D( 0.0, xform ); PEXSetLocalTransform2D( dpy, star, PEXOCStore, PEXReplace, xform ); shift.x = PLANET_ORBIT; shift.y = 0.0; PEXTranslate2D( &shift, xform ); PEXSetLocalTransform2D( dpy, star, PEXOCStore, PEXPreConcatenate, xform ); PEXExecuteStructure( dpy, star, PEXOCStore, planet ); /* Create the top-level structure. */ system = PEXCreateStructure( dpy ); /* Center the whole system in the default viewing plane. */ shift.x = shift.y = 0.5; PEXTranslate2D( &shift, xform ); PEXSetGlobalTransform2D( dpy, system, PEXOCStore, xform ); /* Invoke the star, and thus the whole hierarchy. */ PEXExecuteStructure( dpy, system, PEXOCStore, star ); } static void redraw() { XClearWindow( dpy, window ); PEXRenderNetwork( dpy, window, renderer, system ); XFlush( dpy ); } #define NUM_INCREMENTS 40 static void rotate() { double angle = 0, incr = (2*M_PI) / NUM_INCREMENTS; PEXMatrix3x3 xform; int i; PEXSetEditingMode( dpy, star, PEXStructureReplace ); PEXSetEditingMode( dpy, planet, PEXStructureReplace ); for ( i = 0; i <= NUM_INCREMENTS; i++, angle += incr ) { /* Compute and apply the planet's transform for this angle. */ PEXRotate2D( angle, xform ); PEXSetElementPtr( dpy, star, PEXBeginning, 4 ); PEXSetLocalTransform2D( dpy, star, PEXOCStore, PEXReplace, xform ); /* Compute and apply the moon's transform for this angle. */ PEXRotate2D( 2 * angle, xform ); PEXSetElementPtr( dpy, planet, PEXBeginning, 4 ); PEXSetLocalTransform2D( dpy, planet, PEXOCStore, PEXReplace, xform ); redraw(); sleep( 1 ); } } #define WIN_GEOM "500x500+50+50" main( argc, argv ) int argc; char *argv[]; { XEvent event; XVisualInfo vis_info; XColor bkgd_color; XStandardColormap cmap_info; PEXColorApproxEntry capx_info; PEXRendererAttributes rattrs; PEXExtensionInfo *pexinfo; int done = 0; /* Open a display and initialize PEX. */ dpy = ora_init_pex( argv, &pexinfo ); if ( !dpy ) exit(1); /* Determine the best visual to use. */ ora_find_best_visual( dpy, &vis_info ); /* Get a standard colormap for the visual. */ if ( !ora_get_standard_colormap( dpy, &vis_info, &cmap_info ) ) { fprintf ( stderr, "Cannot find a standard colormap\n" ); exit(1); } ora_set_stdcmap_approx( &vis_info, &cmap_info, &capx_info ); /* Create the window, giving it a gray background. */ bkgd_color.red = bkgd_color.green = bkgd_color.blue = 0x5555; bkgd_color.flags = DoRed | DoGreen | DoBlue; window = ora_create_window( dpy, &vis_info, &cmap_info, WIN_GEOM, &bkgd_color ); if ( STRUCTURE_SPT( pexinfo ) ) { renderer = ora_setup_renderer( dpy, window, &capx_info, &rattrs ); create_model( dpy ); } else { fprintf( stderr, "Structures not supported.\n" ); exit(1); } /* Read and respond to X events. */ XSelectInput( dpy, window, ExposureMask | ButtonPressMask ); while ( !done ) { XNextEvent( dpy, &event ); switch ( event.type ) { case Expose: /* Flush remaining Expose events, then redraw. */ while ( XCheckTypedWindowEvent( dpy, window, Expose, &event ) ) ; /* empty statement */ redraw(); break; case ButtonPress: switch( event.xbutton.button ) { case Button1: rotate(); break; default: done = 1; break; } break; } } XCloseDisplay( dpy ); return 0; }