/* Bruce A. Maxwell CS 351 Computer Graphics Spring 2018 This creates an X Window and shows how to put an image into the Window. It allows for real time animation with your graphics package. You must have X-windows installed on your system. Compile command: gcc -o xdisp -I../include -I/opt/local/include xdisplay.c -L../lib -L/opt/local/lib -limageIO -lX11 -lm */ #include #include #include #include #include #include #include #include #include "graphics.h" #define LCL_DEFAULT_ROWS 480 #define LCL_DEFAULT_COLS 640 /* Global Variables determining window and display */ Display *curDisplay; Window curWindow; GC curGC; /* graphics context */ XImage **ximp = NULL; char *ximd = NULL; int ximrows = 0; int ximcols = 0; int defdepth; int bytesPerPixel; Pixmap gblPixmap; /* Global Variables for userland stuff */ int waitingForImage = 0; int initWindow(void); int initWindow(void) { int defScreen; XSetWindowAttributes wAttr; XGCValues gcValues; char buffer[64] = "Live Rendering"; XTextProperty xtp = {(unsigned char*)buffer, 125, 8, strlen(buffer)}; /* * connect to the X server. uses the server specified in the * DISPLAY environment variable */ curDisplay = XOpenDisplay((char *) NULL); if ((Display *) NULL == curDisplay) { fprintf(stderr, "dispipc: could not open display.\n"); exit(-1); } /* * begin to create a window */ printf("creating window\n"); defdepth = DefaultDepth(curDisplay,0); bytesPerPixel = defdepth/8; bytesPerPixel = bytesPerPixel == 3 ? 4 : bytesPerPixel; printf("default depth %d\n", defdepth); defScreen = DefaultScreen(curDisplay); printf("Default screen %d\n", defScreen); curWindow = XCreateWindow(curDisplay, DefaultRootWindow(curDisplay), 10, 10, LCL_DEFAULT_COLS, LCL_DEFAULT_ROWS, 0, defdepth, InputOutput, DefaultVisual(curDisplay, defScreen), 0, &wAttr); printf("Using depth %d\n", DefaultDepth(curDisplay, 0)); /* * request mouse button and keypress events */ wAttr.event_mask = ButtonPressMask | KeyPressMask | ExposureMask; XChangeWindowAttributes(curDisplay, curWindow, CWEventMask, &wAttr); /* * force it to appear on the screen */ XSetWMName(curDisplay, curWindow, &xtp); XMapWindow(curDisplay, curWindow); /* * create a graphics context. this stores a drawing state; stuff like * current color and line width. this gc is for drawing into our * window. */ printf("creating graphics context\n"); curGC = XCreateGC(curDisplay, curWindow, 0, &gcValues); printf("setting color map to default\n"); XSetWindowColormap(curDisplay, curWindow, DefaultColormapOfScreen(DefaultScreenOfDisplay(curDisplay))); /* * create an XImage for holding image data */ printf("exiting init window\n"); return(bytesPerPixel); } void refreshWindow(void); void refreshWindow(void) { // refresh the window here if( *ximp != NULL ) XPutImage(curDisplay, curWindow, curGC, *ximp, 0, 0, 0, 0, ximcols, ximrows); return; } void closeWindow(void); void closeWindow(void) { // XDestroyImage( *ximp ); XCloseDisplay(curDisplay); if(ximd) free(ximd); if(ximp) free(ximp); return; } /* Moves the contents of an Image into the XWindow to be displayed */ void image2window(Image *src, XImage **lclximp); void image2window(Image *src, XImage **lclximp) { long i, j; if( (src->rows != ximrows || src->cols != ximcols) && *lclximp != NULL ) { printf(" Freeing ximp\n"); free( *lclximp ); *lclximp = NULL; } if( *lclximp == NULL ) { int defdepth, bytesPerPixel, bitmap_pad; int defScreen; printf("Allocating XImage memory\n"); defdepth = DefaultDepth(curDisplay,0); // lies defScreen = DefaultScreen(curDisplay); printf("%d %d\n", defdepth, defScreen); bytesPerPixel = defdepth/8; bytesPerPixel = bytesPerPixel == 3 ? 4 : bytesPerPixel; bitmap_pad = defdepth == 24 ? 32 : defdepth; printf(" default depth %d\n", defdepth); ximd = (char *)malloc(bytesPerPixel * src->cols * src->rows); memset( ximd, 0, bytesPerPixel * src->cols * src->rows ); printf(" resizing window\n"); XResizeWindow(curDisplay, curWindow, src->cols, src->rows); printf(" xcreateimage\n"); *lclximp = XCreateImage(curDisplay, DefaultVisual(curDisplay, defScreen), defdepth, ZPixmap, 0, (char *)ximd, src->cols, src->rows, bitmap_pad, 0); ximrows = src->rows; ximcols = src->cols; } // copy the Image into the lclximp (which is using the memory in ximd) for(i=0;irows;i++) { for(j=0;jcols;j++) { switch( bytesPerPixel ) { case 1: case 2: // not handled break; case 4: // ordering is BGRA ximd[4*(i*src->cols + j) + 2] = (unsigned char)( 255 * image_getc(src, i, j, 0)); ximd[4*(i*src->cols + j) + 1] = (unsigned char)( 255 * image_getc(src, i, j, 1)); ximd[4*(i*src->cols + j) + 0] = (unsigned char)( 255 * image_getc(src, i, j, 2)); break; default: break; } } } XPutImage(curDisplay, curWindow, curGC, *lclximp, 0, 0, 0, 0, ximcols, ximrows); return; } int main(int argc, char *argv[]) { Bool done = False; XEvent curEvent; char c; long event_mask = 0xFFFFFFFF; // user variables Image *src; int frame = 0; int freeze = 0; // initialize variables src = image_create( 480, 640 ); /* initialize the window and video device */ initWindow(); // ximp is a pointer to a pointer ximp = (XImage **)malloc( sizeof( XImage *) ); *ximp = NULL; printf("Starting main loop\n"); while(!done) { // sleep for a certain amount of time (100Hz) usleep(10); // generate the image to display here image_reset(src); { // replace this block of code with your own, or use it to test your cube Module *cube; Color Grey = {{0.6, 0.62, 0.64}}; Color Green = {{0.2, 0.7, 0.2}}; DrawState *ds; View3D view; Matrix VTM; Matrix GTM; float angle; // set up a view matrix_identity( &VTM ); matrix_identity( >M ); point_set3D( &(view.vrp), 3, 3, -7.0 ); vector_set( &(view.vpn), -3, -3, 7); vector_set( &(view.vup), 0.0, 1.0, 0.0); view.d = 2.0; view.du = 1.6; view.dv = src->rows * view.du / src->cols; view.f = 0.0; view.b = 15; view.screenx = src->cols; view.screeny = src->rows; matrix_setView3D( &VTM, &view ); // set up a cube cube = module_create(); module_color( cube, &Green ); module_scale( cube, 3, 1, 2 ); module_cube( cube, 1 ); // set up a drawstate ds = drawstate_create(); drawstate_setColor( ds, Grey ); // adjust the angle of the cube based on frame number angle = (frame % 500) * M_PI / 500.0; matrix_rotateY( >M, cos(angle), sin(angle) ); // draw the module module_draw( cube, &VTM, >M, ds, NULL, src ); } // set the image to the XWindow image2window( src, ximp ); // check for events if(XCheckWindowEvent(curDisplay, curWindow, event_mask, &curEvent)) { switch (curEvent.type) { case ButtonPress: /* access button by curEvent.xbutton.button (1,2,3) access position by curEvent.xbutton.x and .y */ if(curEvent.xbutton.button == 1) { // do something if the user clicks button 1 printf("Button 1\n"); } else if(curEvent.xbutton.button == 2) { // do something if the user clicks button 2 printf("Button 2\n"); } else if(curEvent.xbutton.button == 3) { // right button printf("Button 3\n"); } break; case KeyPress: /* access string using XLookupString(*event,*char,numChars,NULL,NULL) */ if(XLookupString((XKeyEvent *)&curEvent, &c, 1, NULL, NULL) == 1) { switch(c) { case 'q': // user pressed a 'q' done = True; break; case ' ': freeze = !freeze; break; default: break; } } break; case Expose: refreshWindow(); default: // some other unhandled event break; } } // increment the frame number if(!freeze) frame++; } closeWindow(); image_free(src); return(0); }