/***************************************************************************** Main Program for CS480 Programming Assignment 3 ****************************************************************************** Author: Stan Sclaroff Boston University Computer Science Dept. March 22, 1995 ****************************************************************************** Description: This is the main program for the camera model and perspective projection programming assignment. It supports both monocular viewing, and stereo viewing (using red/blue anaglyphic glasses). It opens a GL window in double buffer mode, and opens a slider menu for controlling the transforms. The user interface is through a separate slider menu that controls the following things: ROTATION This menu includes three dials that control the x,y,&z rotation about a polygonal object's center point. CAMERA PARAMETERS There are separate sliders for some camera parameters. Eye distance is the distance between the eyes for stereo viewing. PRP distance is the projection reference point's distance (along Z) from the view plane. There are also two slides for controling the front and back clip planes. RED There is a slider for controlling the brightness of the red image used in red/blue anaglyphic stereo viewing. There are also four main buttons on the slider menu: STEREO: toggles monocular/stereo perspective viewing RESET: sets sliders all to default values and redraws. FLY: does the extra credit "fly through" QUIT: This button allows you to exit. In addition, there are separate reset buttons for each slider. ****************************************************************************** Comments: This program has an optional command-line argument for specifying an ascii polygon text file. For instance, typing animate vw.asc will load in the polygons contained in the OSU (Ohio State U.) file "vw.asc" ******************************************************************************/ #include #include #include #include #include #include "forms.h" #include "menu.h" #include "draw.h" #define EYE_SLIDER 0 #define PRP_SLIDER 1 #define FRONT_PLANE_SLIDER 2 #define BACK_PLANE_SLIDER 3 #define RED_SLIDER 4 #define NUM_SLIDERS 5 /* global variables !!! These are used by the menu call backs */ Polygon *figure; /* the polyline figure drawn */ Frame *frame; /* the rectangular clipping frame */ long winid; /* the drawing window id */ float umin,umax,vmin,vmax; /* the window size in the view coordinate system */ /* this globals are for the slider values */ float slider_values[5]; float slider_default_values[5]; float slider_minmax_values[5][2]; float angles[3]; int stereo_on = FALSE; short stereo_red[3]={255,0,0}; /* these globals are for the camera parameters */ float VRP[3],PRP[3]; float VPN[3]={0,0,1}; float VUP[3]={0,1,0}; /* camera tool's main program */ main(argc, argv) int argc; char **argv; { float depth; /* a polyline file can be specified as an input argument */ if(argc > 1) figure = read_osu_polygons(argv[1],RGByellow); /* if none is provided, use default: a box */ else figure = read_osu_polygons("box.asc",RGByellow); /* failed to open a polyline file, so close up */ if(figure == 0) exit(EXIT_SUCCESS); /* open the GL graphics window */ winid = open_window(SCREEN_WIDTH,SCREEN_HEIGHT,"Stereo View"); /* create the clipping frame */ frame = create_frame((float)FRAME_XMIN,(float)FRAME_YMIN,(float)FRAME_XMAX,(float)FRAME_YMAX,RGBgreen); depth = figure->max[2]-figure->min[2]; /* make the VRP on the back plane of the view volume */ VRP[0] = figure->center[0]; VRP[1] = figure->center[1]; VRP[2] = figure->min[2]; /* make the Z planes fit the entire object */ slider_default_values[FRONT_PLANE_SLIDER] = depth*1.5; slider_default_values[BACK_PLANE_SLIDER] = -depth*0.5; slider_minmax_values[FRONT_PLANE_SLIDER][0] = -depth*0.5; slider_minmax_values[FRONT_PLANE_SLIDER][1] = depth*1.5; slider_minmax_values[BACK_PLANE_SLIDER][0] = -depth*0.5; slider_minmax_values[BACK_PLANE_SLIDER][1] = depth*1.5; /* calculate the window borders in the view reference frame */ umax = (figure->max[0] - figure->min[0])*1.5; vmax = umax/frame->aspect_ratio; umin = -umax; vmin = -vmax; /* PRP distance perpendicular to view plane can vary */ PRP[2] = slider_default_values[PRP_SLIDER] = depth*5.0; PRP[0] = PRP[1] = 0.0; slider_minmax_values[PRP_SLIDER][0] = slider_default_values[FRONT_PLANE_SLIDER]; slider_minmax_values[PRP_SLIDER][1] = PRP[2]*4.0; /* inter-eye distance can also vary */ slider_default_values[EYE_SLIDER] = (1+depth)*0.0125; slider_minmax_values[EYE_SLIDER][0] = 0.0; slider_minmax_values[EYE_SLIDER][1] = slider_default_values[EYE_SLIDER]*5.0; /* red intensity varies so that it balances with blue for red/blue anaglyphic stereo viewing */ slider_default_values[RED_SLIDER] = 128.0; slider_minmax_values[RED_SLIDER][0]=64.0; slider_minmax_values[RED_SLIDER][1]=255.0; /* open the menu forms: slider window */ create_the_forms(); /* set up the sliders on the slider menu and then activate them */ setup_sliders(); activate_forms(); /* draw */ redraw(); redraw(); /* the inner loop: let the slider menu take control */ do fl_check_forms(); while(TRUE); } /* This is the top-level redraw routine. it first computes the perspective transform matrices and draws depending on whether stereo or monocular display is specified */ redraw() { float Nper[4][4],Mrotate[4][4],M1[4][4],M2[4][4]; float eye_distance; eye_distance = slider_values[EYE_SLIDER]; /* compute 3-D rotation around the figure's center point */ compute_rotation(angles,figure->center,Mrotate); /* stereo is turned on, compute left eye position */ if(stereo_on) PRP[0] -= eye_distance/2; /* compute the view-normalized perspective transform */ compute_Nper(VUP,VPN,VRP,PRP,umin,umax,vmin,vmax,frame->xmin,frame->xmax,frame->ymin,frame->ymax,Nper); /* concatenate it with the rotation */ matrix_multiply_4x4(M1,Nper,Mrotate); /* do the same for the right eye if necessary */ if(stereo_on) { PRP[0] += eye_distance; compute_Nper(VUP,VPN,VRP,PRP,umin,umax,vmin,vmax,frame->xmin,frame->xmax,frame->ymin,frame->ymax,Nper); matrix_multiply_4x4(M2,Nper,Mrotate); PRP[0] -= eye_distance/2; } /* draw the stereo pair (or monocular image) as required */ redraw_stereo(winid,figure,M1,M2,frame, slider_values[BACK_PLANE_SLIDER],slider_values[FRONT_PLANE_SLIDER], stereo_on,stereo_red,RGBblue); } /* the call back routine for extra credit routine */ /* gets called when the fly button is pushed */ void flyCB(obj,arg) FL_OBJECT *obj; long arg; { /* put your extra credit routine here */ } /* the call back routine for quiting the program */ /* gets called when the quit button is pushed */ void quitCB(obj,arg) FL_OBJECT *obj; long arg; { /* cleanup */ free_polygon_object(figure); close_window(winid); exit(EXIT_SUCCESS); } /* this is a call-back for reseting the menu */ void resetCB(obj,arg) FL_OBJECT *obj; long arg; { int i; setup_sliders(); redraw(); } /* toggle stereo display mode */ void stereoCB(obj,arg) FL_OBJECT *obj; long arg; { stereo_on = (stereo_on == TRUE) ? FALSE : TRUE; redraw(); } /* this routine sets up the sliders default and min/max values */ void setup_sliders() { int i; /* do x,y,z angle dials */ for(i=0;i<3;++i) { fl_set_dial_bounds(rotation[i],-PI,PI); fl_set_dial_value(rotation[i],0.0); angles[i]=0.0; } for(i=0;i