/* view_ori-mb.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" /* Globals. */ static PEXStructure model; static Display *dpy; static Window window; static PEXRenderer renderer; static Multibuffer buffers[2], cur_buf; /* The view parameters for the view table. */ static PEXViewEntry view; static unsigned int view_num = 1; static PEXLookupTable view_table; /* The view orientation parameters. */ static PEXCoord view_ref_pt; static PEXVector view_up_vec, view_plane_normal; /* Constants */ #define SPHERE_RADIUS 1.0 #define AXIS_LENGTH 0.4 #define PAN_SCALE (M_PI/500) static void set_initial_view() { PEXCoord2D view_window[2]; double view_plane, front_plane, back_plane; PEXCoord prp; PEXNPCSubVolume viewport; int err, perspective; /* Compute the view orientation transform. */ view_ref_pt.x = 0; view_ref_pt.y = 0; view_ref_pt.z = 0; view_up_vec.x = 0; view_up_vec.y = 1; view_up_vec.z = 0; view_plane_normal.x = 1; view_plane_normal.y = 1; view_plane_normal.z = 1; err = PEXViewOrientationMatrix( &view_ref_pt, &view_plane_normal, &view_up_vec, view.orientation ); /* The view mapping parameters. */ perspective = True; view_plane = 0; prp.x = 0; prp.y = 0; prp.z = 10; view_window[0].x = -1.5; view_window[1].x = 1.5; view_window[0].y = -1.5; view_window[1].y = 1.5; back_plane = -1.5; front_plane = 1.5; viewport.min.x = 0; viewport.max.x = 1; viewport.min.y = 0; viewport.max.y = 1; viewport.min.z = 0; viewport.max.z = 1; /* Compute the view mapping transform. */ err = PEXViewMappingMatrix( view_window, &viewport, perspective, &prp, view_plane, back_plane, front_plane, view.mapping ); /* The view clipping parameters. */ view.clip_flags = PEXClippingAll; view.clip_limits = viewport; /* Set the view. */ PEXSetTableEntries( dpy, view_table, view_num, 1, PEXLUTView, (PEXPointer) &view ); } void create_model() { PEXListOfCoord sphere_points; PEXCoord center; PEXStructure axes, sphere; /* Create the axes structure. */ center.x = center.y = center.z = 0; axes = ora_build_axes_struct( dpy, ¢er, AXIS_LENGTH ); /* Create the sphere structure. */ sphere = PEXCreateStructure( dpy ); ora_build_sphere( SPHERE_RADIUS, &sphere_points ); PEXPolyline( dpy, sphere, PEXOCStore, sphere_points.count, sphere_points.points ); /* Create the top-level structure. */ model = PEXCreateStructure( dpy ); /* Make all following primitives use the selected view. */ PEXSetViewIndex( dpy, model, PEXOCStore, view_num ); /* Execute the structures containing the primitives. */ PEXExecuteStructure( dpy, model, PEXOCStore, axes ); PEXExecuteStructure( dpy, model, PEXOCStore, sphere ); } static void redraw() { /* Redraw into the off-screen buffer. */ PEXBeginRendering( dpy, cur_buf, renderer ); { PEXExecuteStructure( dpy, renderer, PEXOCRender, model ); } PEXEndRendering( dpy, renderer, True ); 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 void handle_input( init_theta, init_phi ) float init_theta, init_phi; { XEvent event; int err, lastx, lasty, done = 0; float theta = init_theta, phi = init_phi; /* Read and respond to X events. */ XSelectInput( dpy, window, ButtonPressMask | Button1MotionMask | ExposureMask ); while ( !done ) { XNextEvent( dpy, &event ); switch ( event.type ) { case ButtonPress: switch ( event.xbutton.button ) { case Button1: /* Reset last X and last Y. */ lastx = event.xbutton.x; lasty = event.xbutton.y; break; default: done = 1; break; } break; case MotionNotify: /* Increment the view-plane-normal angles. */ theta += PAN_SCALE * (event.xmotion.x - lastx); phi += PAN_SCALE * (lasty - event.xmotion.y); /* Reset the view plane normal. */ view_plane_normal.x = cos( phi ) * sin( theta ); view_plane_normal.y = sin( phi ); view_plane_normal.z = cos( phi ) * cos( theta ); /* Compute the new view orientation transform. */ err = PEXViewOrientationMatrix( &view_ref_pt, &view_plane_normal, &view_up_vec, view.orientation ); /* Set the view if orientation is okay. The view */ /* mapping parameters do not need to change. */ if ( !err ) { PEXSetTableEntries( dpy, view_table, view_num, 1, PEXLUTView, (PEXPointer) &view ); lastx = event.xmotion.x; lasty = event.xmotion.y; /* Update the display. */ redraw(); } break; case Expose: /* Flush remaining Expose events, then redraw. */ while ( XCheckTypedWindowEvent( dpy, window, Expose, &event ) ) ; /* empty statement */ redraw(); break; } } } #define WIN_GEOM "500x500+50+50" main( argc, argv ) int argc; char *argv[]; { XEvent event; XVisualInfo vis_info; XStandardColormap cmap_info; PEXColorApproxEntry capx_info; PEXRendererAttributes rattrs; PEXExtensionInfo *pexinfo; XColor bkgd_color; 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. */ bkgd_color.red = bkgd_color.green = bkgd_color.blue = 0; bkgd_color.flags = DoRed | DoGreen | DoBlue; window = ora_create_window( dpy, &vis_info, &cmap_info, WIN_GEOM, &bkgd_color ); /* Create the model and set up the PEX renderer. */ if ( STRUCTURE_SPT( pexinfo ) ) { create_model( dpy ); renderer = ora_setup_renderer( dpy, window, &capx_info, &rattrs ); } else { fprintf( stderr, "Structures not supported.\n" ); exit(1); } /* 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(6); /* Initialize the view. */ view_table = rattrs.view_table; set_initial_view(); handle_input( (float)M_PI/4, (float)M_PI/4 ); XCloseDisplay( dpy ); return 0; }