/* night-time.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" #include "mbx.h" static Display *dpy; static Window window; static PEXRenderer renderer; static Multibuffer buffers[2], cur_buf; #define INIT_ANGLE (5 * M_PI/7) #define END_ANGLE (1 * M_PI/7) #define NUM_SEGMENTS 16 #define RADIUS 0.05 static PEXCoord moon_pts[NUM_SEGMENTS], moon_pos = {1.3,0,.1}; static PEXStructure background, tree, house; static void redraw( angle ) double angle; { PEXColor color; PEXMatrix xform; static PEXCoord center = {.5,0,.1}; static PEXVector shift = {0,0,0}, scale = {1,1,1}; /* Redraw into the off-screen buffer. */ PEXBeginRendering( dpy, cur_buf, renderer ); { /* Draw the background scene. */ PEXExecuteStructure( dpy, renderer, PEXOCRender, background ); PEXExecuteStructure( dpy, renderer, PEXOCRender, tree ); PEXExecuteStructure( dpy, renderer, PEXOCRender, house ); /* Build the transform for the new moon angle. */ PEXBuildTransform( ¢er, &shift, 0., 0., angle, &scale, xform ); PEXSetLocalTransform( dpy, renderer, PEXOCRender, PEXReplace, xform ); /* Draw the moon in its new position. */ PEXSetInteriorStyle( dpy, renderer, PEXOCRender, PEXInteriorStyleSolid ); SET_COLOR( 0.9, 0.9, 0.9, color ); /* white */ PEXSetSurfaceColor( dpy, renderer, PEXOCRender, PEXColorTypeRGB, &color ); PEXFillArea( dpy, renderer, PEXOCRender, PEXShapeConvex, True, NUM_SEGMENTS, moon_pts ); } PEXEndRendering( dpy, renderer, True ); /* Display the buffer. */ XmbufDisplayBuffers( dpy, 1, &cur_buf, 0, 0 ); XFlush( dpy ); /* Make the undisplayed buffer the drawing buffer. */ cur_buf = (cur_buf == buffers[0] ? buffers[1] : buffers[0]); } static PEXCoord grass_pts[] = {{ 0, 0, 0},{ 1, 0, 0},{ 1, .3, 0},{ 0,.3,0}}, sky_pts[] = {{ 0, .3, 0},{ 1, .3, 0},{ 1, 1, 0},{ 0, 1,0}}, tree_pts[] = {{.3, .2,.4},{.4, .2,.4},{.35, .4,.4}}, house_pts[] = {{.6,.15,.5},{.8,.15,.5},{ .8, .4,.5}, {.7, .5,.5},{.6, .4,.5}}, chimney_pts[] = {{.75,.45,.5},{.8, .4,.5},{ .8,.53,.5}, {.75,.53,.5}}, mountn_pts[] = {{.1, .3, .2},{.9, .3,.2},{ .6, .9, .2}, {.4, .5, .2},{.3, .6,.2}}; void create_structures() { PEXColor red, yellow, blue, green, dark_green, brown; /* Define the colors we'll use. */ SET_COLOR( 1.0, 0.0, 0.0, red ) SET_COLOR( 1.0, 1.0, 0.0, yellow ) SET_COLOR( 0.0, 0.0, 1.0, blue ) SET_COLOR( 0.0, 1.0, 0.0, green ) SET_COLOR( 0.0, 0.7, 0.0, dark_green ) SET_COLOR( 0.6, 0.2, 0.2, brown ) /* Create the background structure. */ background = PEXCreateStructure( dpy ); PEXSetInteriorStyle( dpy, background, PEXOCStore, PEXInteriorStyleSolid ); PEXSetSurfaceColor( dpy, background, PEXOCStore, PEXColorTypeRGB, &blue ); PEXFillArea( dpy, background, PEXOCStore, PEXShapeConvex, True, 4, sky_pts ); PEXSetSurfaceColor( dpy, background, PEXOCStore, PEXColorTypeRGB, &dark_green ); PEXFillArea( dpy, background, PEXOCStore, PEXShapeConvex, True, 4, grass_pts ); PEXSetSurfaceColor( dpy, background, PEXOCStore, PEXColorTypeRGB, &brown ); PEXFillArea( dpy, background, PEXOCStore, PEXShapeNonConvex, True, 5, mountn_pts ); /* Create the tree. */ tree = PEXCreateStructure( dpy ); PEXSetInteriorStyle( dpy, tree, PEXOCStore, PEXInteriorStyleSolid ); PEXSetSurfaceColor( dpy, tree, PEXOCStore, PEXColorTypeRGB, &green ); PEXFillArea( dpy, tree, PEXOCStore, PEXShapeConvex, True, 3, tree_pts ); /* Create the house. */ house = PEXCreateStructure( dpy ); PEXSetInteriorStyle( dpy, house, PEXOCStore, PEXInteriorStyleSolid ); PEXSetSurfaceColor( dpy, house, PEXOCStore, PEXColorTypeRGB, &yellow ); PEXFillArea( dpy, house, PEXOCStore, PEXShapeConvex, True, 5, house_pts ); PEXSetSurfaceColor( dpy, house, PEXOCStore, PEXColorTypeRGB, &red ); PEXFillArea( dpy, house, PEXOCStore, PEXShapeConvex, True, 4, chimney_pts ); } static void circle( center, points ) PEXCoord *center; PEXCoord *points; { double delta, ang; int i; delta = 2 * M_PI / NUM_SEGMENTS; for ( i = 0, ang = 0; i < NUM_SEGMENTS; i++, ang += delta ) { points[i].x = center->x + RADIUS * cos( ang ); points[i].y = center->y + RADIUS * sin( ang ); points[i].z = center->z; } } #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; double angle = INIT_ANGLE; /* 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 ); /* Create the structures and moon. Set up the renderer. */ if ( STRUCTURE_SPT( pexinfo ) ) { create_structures( dpy ); circle( &moon_pos, moon_pts ); renderer = ora_setup_renderer( dpy, window, &capx_info, &rattrs ); } else { fprintf( stderr, "Structures not supported.\n" ); exit(1); } /* See if Z-buffer HLHSR mode is available. */ if ( !ora_enum_type_supported( dpy, window, PEXETHLHSRMode, PEXHLHSRZBuffer ) ) { fprintf( stderr, "Z-buffering HLHSR mode not supported.\n" ); exit(1); } /* Set the renderer's HLHSR mode. */ rattrs.hlhsr_mode = PEXHLHSRZBuffer; PEXChangeRenderer( dpy, renderer, PEXRAHLHSRMode, &rattrs ); /* Create the MBX buffers. */ if ( ora_create_mbx_buffers( dpy, window, 2, buffers ) ) /* Set the current buffer to buffer 1. */ cur_buf = buffers[1]; else 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( angle ); break; case ButtonPress: switch( event.xbutton.button ) { case Button1: /* Rotate. */ for ( angle = INIT_ANGLE; angle > END_ANGLE; angle -= M_PI/500 ) { redraw( angle ); } break; default: done = 1; break; } break; } } XmbufDestroyBuffers( dpy, window ); XCloseDisplay( dpy ); return 0; }