/* 3dfaces.c CS 411 - Jeff Absher assignment 3 Usage: 3dfaces.exe [filename] where filename is a file in cwd. three filenames are hardcoded with the keystrokes 1,2,and 3 pixa.dat, pixb.dat and pixc.dat respectively. Have fun. -Jeff The internal model of 2D lines is ^+y | | +x |____> it is translated to the windows-style representation ______> | +x | | V +y prior to BLTing to the window with SetPixel() Displayed pixels are stored as a LONG linked list of Pixels, only one list is needed because there is no optimization when drawing to screen The "scene" struct is really a polygon list. ...low cohesion and high coupling, the sign of a quality programmer :) I think that I have all the leaks plugged, but still never hurts to warn too much mucking around could segfault if I missed a memleak note that 'C' or 'c' not only centers the window, but it resets all rotation too and rereads the input file, as rotation carries over through input file reads. the 3d Xforms are pretty much verbatim from zed3d in equation form.. I'd like to matte around the viewport, but didn't have time also note that aspect ratio gets really screwed up when you resize a viewport that is sitting near the edge of the screen. I try to zoom as much as I can, but to zoom so that the viewport goes off the screen breaks the rules. therefore aspect ratio had to go. */ #include #include #include #include #include #include #include #define HEIGHT 600 #define WIDTH 800 #define MAXLINE HEIGHT + WIDTH //not used with stack implementation #define ROT_STEP_DEG 10 #define BASECOLOR 0x00000000 #define MATTECOLOR 0x00888888 //not figured out yet, wanted to matte, but drew frame instead. #define PI 3.1415926535 #define E 2.7182818284 #define STEPPERCENT 10 //percent of each step #define COLORCYCLELEVEL 1 //higher is less color changes per pixel drawn #define DELTACOLOR 3 //higher is starker contrast between adjacent colors #define SCENEEXTENTSX 4000 #define SCENEEXTENTSY 4000 #define SCENEEXTENTSZ 4000 #define INFILE1 "pixa.dat" #define INFILE2 "pixb.dat" #define INFILE3 "pixc.dat" LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM ); int red; int green; int blue; int zbuff[WIDTH][HEIGHT]; float xrot = 0.0; float yrot = 0.0; float zrot = 0.0; float windowwidth = SCENEEXTENTSX ; float windowheight = SCENEEXTENTSY; float windowcenterx = SCENEEXTENTSX / 2 ; float windowcentery = SCENEEXTENTSY / 2 ; float windowcenterz = SCENEEXTENTSZ / 2 ; int vpcenterx = WIDTH / 2; int vpcentery = HEIGHT / 2; int vpsizex = WIDTH / 2; int vpsizey = HEIGHT / 2; char currfile[64]; struct point *border = NULL; struct point { int x; int y; int z; struct point *next; }; struct scene //actually it is a list of polygons. { struct point *polygon; int r; int g; int b; struct scene *next; }; void freepoints( struct point *inpoint) {//free a list of points struct point *stepper; stepper = inpoint; while( inpoint && stepper ) { if( inpoint->next ) inpoint = inpoint->next; else inpoint = NULL; free( stepper ); stepper = inpoint; } } void makeborder(); void movevp( int x, int y ) //moves veiwport, prevents vp from moving outside of "screen" { if( vpcenterx + x + vpsizex / 2 < WIDTH && vpcentery + y + vpsizey / 2 < HEIGHT && vpcenterx + x - vpsizex / 2 > 0 && vpcentery + y - vpsizey / 2 > 0 ) { vpcenterx += x; vpcentery += y; } makeborder(); return; } struct point *translate( struct point *inpoint ) {// handles 3dxforms and window to viewport mapping struct point *retval; float tempx; float tempy; float tempz; float tempx2; float tempy2; float tempz2; retval = ( struct point * ) malloc( sizeof( struct point )); //xlate to origin tempx = inpoint->x - SCENEEXTENTSX/2; tempy = inpoint->y - SCENEEXTENTSY/2; tempz = inpoint->z - SCENEEXTENTSZ/2; //rotate about x tempx2 = tempx; tempy2 = cos( xrot ) * tempy - sin( xrot ) * tempz; tempz2 = sin( xrot ) * tempy + cos( xrot ) * tempz; tempx = tempx2; tempy = tempy2; tempz = tempz2; //rotate about y tempx2 = cos( yrot )* tempx - sin( yrot ) * tempz; tempy2 = tempy; tempz2 = sin( yrot ) * tempx + cos( yrot ) * tempz; tempx = tempx2; tempy = tempy2; tempz = tempz2; //rotate about z tempx2 = cos( zrot ) * tempx - sin( zrot ) * tempy; tempy2 = sin( zrot ) * tempx + cos( zrot ) * tempy; tempz2 = tempz; tempx = tempx2; tempy = tempy2; tempz = tempz2; //undo xlate tempx += SCENEEXTENTSX/2; tempy += SCENEEXTENTSY/2; tempz += SCENEEXTENTSZ/2; tempx = tempx - (windowcenterx - SCENEEXTENTSX/2); tempy = tempy - (windowcentery - SCENEEXTENTSY/2); tempz = tempz - (windowcenterz - SCENEEXTENTSZ/2); retval->x = (int) tempx * vpsizex/windowwidth + vpcenterx - vpsizex/2; retval->y = (int) tempy * vpsizey/windowheight + vpcentery - vpsizey/2; retval->z = (int) tempz; retval->next = NULL; return( retval ); } struct scene *TheScene = NULL; struct scene *TheScene2 = NULL; struct scene *projscene = NULL; void movewindow( int x, int y, int z ) { if( windowcenterx + x > 0 && windowcentery + y > 0 && windowcenterz + z > 0 && windowcenterx + x < SCENEEXTENTSX && windowcentery + y < SCENEEXTENTSY && windowcenterz + z < SCENEEXTENTSZ ) { windowcenterx += x; windowcentery += y; windowcenterz += z; } return; } void changecolor( void ) { red = rand() % 256; green = rand() % 256; blue = rand() % 256; // blue = 16 * (blue % 16); // red = 16 * (red % 16); // green = 16 * (green % 16); } /*float gaussian( float a, float d ) {//a is the mean, d is the deviation static float t = 0.0; float x,v1,v2,r; if (t == 0){ do { v1 = ( float ) 2.0 * ( float ) rand()/RAND_MAX - ( float ) 1.0; v2 = ( float ) 2.0 * ( float ) rand()/RAND_MAX - ( float ) 1.0; r = v1 * v1 + v2 * v2; }while (r>=1.0); r = ( float ) sqrt((-2.0*log(r))/r); t = v2*r; return(a+v1*r*d); } else { x = t; t = 0.0; return(a+x*d); } } */ struct point *pointstack = NULL; //stack of points that make up endpoints struct point *origset = NULL; struct point *makepoint( int x, int y, int z, struct point *inpoint ) {//makes a new point struct point *retval; retval = ( struct point * ) malloc( sizeof( struct point )); retval->x = x; retval->y = y; retval->z = z; retval->next = inpoint; return( retval ); } struct point *windowXlate( struct point *inpoint ) {//translate to Windows-style coordinates from normal coords 2D only return( makepoint( inpoint->x, HEIGHT - inpoint->y, inpoint->z, NULL )); } struct scene *readfile( char infile[] ) {//reads input file and checks for J at beginning, appends if J is missing. //as we never really got the spec for input files. I hope this is OK. struct scene *retval = NULL; FILE *fp; fp = fopen( infile, "r" ); while( !feof( fp )) { char lookahead; lookahead = fgetc( fp ); if( lookahead == 'j' || lookahead == 'J' || ftell( fp ) == 1 ) { struct scene *rvtemp; rvtemp = retval; retval = ( struct scene * ) malloc( sizeof( struct scene )); retval->next = rvtemp; retval->polygon = NULL; if( !ftell( fp )) ungetc( lookahead, fp ); } else { int a, b, c; ungetc( lookahead, fp ); fscanf( fp, "%d %d %d", &a, &b, &c ); lookahead = 0; retval->polygon = makepoint( a + SCENEEXTENTSX / 2, b + SCENEEXTENTSY / 2, c + SCENEEXTENTSZ / 2, retval->polygon ); retval->r = 255; retval->g = 255; retval->b = 255; while( lookahead != '\n' && !feof( fp ) ) lookahead = getc( fp ); } } fclose( fp ); return( retval ); } void delscene( struct scene *inscene ) {//destructor for a scene (list of polygons) struct scene *stepper; stepper = inscene; while( stepper ) { stepper = inscene->next; if( inscene->polygon ) freepoints( inscene->polygon ); free( inscene ); inscene = stepper; } } /*void paintstack( struct point *instack, HDC hdc ) {//takes a stack of points and paints it on the screen struct point *temppoint2 = instack; int i = 0; while( temppoint2 ) { struct point *temppoint; //clipping to viewport if( temppoint2->x < vpcenterx + vpsizex / 2 && temppoint2->x > vpcenterx - vpsizex / 2 && temppoint2->y < vpcentery + vpsizey / 2 && temppoint2->y > vpcentery - vpsizey / 2 && temppoint2->z < zbuff[temppoint2->x][temppoint2->y]) { temppoint = windowXlate( temppoint2 ); zbuff[temppoint2->x][temppoint2->y] = temppoint2->z; SetPixel( hdc, temppoint->x, temppoint->y, RGB( temppoint->r, temppoint->g, temppoint->b )); free( temppoint ); } temppoint2 = temppoint2->next; } return; }*/ void paintstackcolor( struct point *instack, HDC hdc, int red, int green, int blue ) { struct point *temppoint2 = instack; int i = 0; while( temppoint2 ) { struct point *temppoint; if( temppoint2->z < zbuff[temppoint2->x][temppoint2->y] ) { zbuff[temppoint2->x][temppoint2->y]=temppoint2->z; } temppoint2 = temppoint2->next; } temppoint2 = instack; while( temppoint2 ) { struct point *temppoint; //clipping to viewport if(( temppoint2->x < vpcenterx + vpsizex / 2 )&& (temppoint2->x > vpcenterx - vpsizex / 2 )&& (temppoint2->y < vpcentery + vpsizey / 2 )&& (temppoint2->y > vpcentery - vpsizey / 2 )&& (temppoint2->z == zbuff[temppoint2->x][temppoint2->y]) ) { int tempz = 256 * temppoint2->z / SCENEEXTENTSZ; temppoint = windowXlate( temppoint2 ); SetPixel( hdc, temppoint->x, temppoint->y, RGB( red, green, blue )); free( temppoint ); } temppoint2 = temppoint2->next; } return; } void paintstackcolornoclip( struct point *instack, HDC hdc, int red, int green, int blue ) { struct point *temppoint2 = instack; int i = 0; while( temppoint2 ) { struct point *temppoint; if(temppoint2->z < zbuff[temppoint2->x][temppoint2->y] ) zbuff[temppoint2->x][temppoint2->y] = temppoint2->z; temppoint = windowXlate( temppoint2 ); SetPixelV( hdc, temppoint->x, temppoint->y, RGB( 127, 127, 127 )); free( temppoint ); temppoint2 = temppoint2->next; } return; } float reduce( float inTheta ) { //try not to let the radians get too big if( inTheta < ( 2 * PI )) return( inTheta ); else return( reduce( inTheta - (2 * PI ))); } struct point *createline( struct point *start, struct point *end, struct point *instack ) {//model a line between 2 points using Bresenham //note that Windows includes a LineTo optimized routine to actually //draw lines, but I figured in the spirit of learning that I should //generate the points in the line myself in my own representation //and the books Midpoint alg is lousy, Mine creates a box and //uses the corners to draw the line, and doesn't care about which //quadrant it is in. //algorithm stolen from http://intranet.ca/~sshah/waste/art7.html //with a few of my own changes. struct point *retval = instack; struct point *tpoint = NULL; struct point *endpoint = NULL; int X = start->x; int Y = start->y; int Z = start->z; int Zrange = start->z - end->z; int xstep = start->x - end->x; int ystep = start->y - end->y; int i = 0; int Error = 0; int XChange; int YChange; int ZChange; if( xstep < 0 ) { XChange = -1; xstep = 0 - xstep; } else XChange = 1; if( ystep < 0 ) { YChange = -1; ystep = 0 - ystep; } else YChange = 1; if( xstep < ystep ) {//best to move along Y int Length = ystep + 1; ZChange = Zrange/max(Length,1); while( i < Length ) { Y = Y - YChange; Z = Z - ZChange; Error = Error + xstep; if( Error > ystep ) { X = X - XChange; Error = Error - ystep; } retval = makepoint( X, Y, Z , retval ); i = i + 1; } } else {//best to move along X int Length = xstep + 1; ZChange = Zrange/max(Length,1); while( i < Length ) { X = X - XChange; Z = Z - ZChange; Error = Error + ystep; if( Error > xstep ) { Y = Y - YChange; Error = Error - xstep; } retval = makepoint( X, Y, Z, retval ); i=i + 1; } } /* tpoint = retval; while( tpoint ) {//move the whole damn line to the back tpoint = tpoint->next; } endpoint = tpoint; //now move the line back out toward viewer tpoint = retval; if(abs(endpoint->x - tpoint->x) >= abs(endpoint->y - tpoint->y) ) {//best to step along x int ender = endpoint->x; int beginner = tpoint->x; if while(tpoint) { tpoint->z = zbottom + Zrange /max(1,abs(ender - beginner))*/ return( retval ); } void makeborder() {//create the line structures for the border around viewport struct point *p1; struct point *p2; struct point *p3; struct point *p4; p1 = ( struct point * ) malloc( sizeof( struct point )); p2 = ( struct point * ) malloc( sizeof( struct point )); p3 = ( struct point * ) malloc( sizeof( struct point )); p4 = ( struct point * ) malloc( sizeof( struct point )); if( border ) freepoints( border ); border = NULL; p1->x = vpcenterx + vpsizex / 2; p1->y = vpcentery + vpsizey / 2; p1->z = 0; p1->next = NULL; p2->x = vpcenterx - vpsizex / 2; p2->y = vpcentery + vpsizey / 2; p2->z = 0; p2->next = NULL; p3->x = vpcenterx - vpsizex / 2; p3->y = vpcentery - vpsizey / 2; p3->z = 0; p3->next = NULL; p4->x = vpcenterx + vpsizex / 2; p4->y = vpcentery - vpsizey / 2; p4->z = 0; p4->next = NULL; border = createline(p1, p2, NULL) ; border = createline(p2, p3, border ); border = createline(p3, p4, border ); border = createline(p4, p1, border ); return; } int minx( struct point *inlist ) {//return min int found in xvals in a list of points int curr = WIDTH; while( inlist ) { if( inlist->x < curr ) curr = inlist->x; inlist = inlist->next; } return( curr ); } int maxx( struct point *inlist ) {//return max int found in xvals in a list of points int curr = 0; while( inlist ) { if( inlist->x > curr ) curr = inlist->x; inlist = inlist->next; } return( curr ); } struct point *minyat( struct point *inlist, int inint ) {//return min int found in yvals given an xval in a list of points int curr = HEIGHT; struct point *current = NULL; while( inlist ) { if( inlist->x == inint && inlist->y < curr ) { current = inlist; curr = inlist->y; } inlist = inlist->next; } return( current ); } struct point *maxyat( struct point *inlist, int inint ) {//return min int found in yvals given an xval in a list of points int curr = 0; struct point *current = NULL; while( inlist ) { if( inlist->x == inint && inlist->y > curr ) { current = inlist; curr = inlist->y; } inlist = inlist->next; } return( current ); } void clearZ() { int xstep, ystep; for( xstep = 0; xstep < WIDTH; xstep ++) { for( ystep = 0; ystep < HEIGHT; ystep++ ) { zbuff[xstep][ystep]=SCENEEXTENTSZ; } } } struct scene *project() {//returns a list of points to light up based on current position, //actually translate does the work, this just steps thru the various //polygons and "flattens" out the data. struct scene *retval = NULL; struct point *retval2 = NULL; struct scene *scenestepper = TheScene; struct point *polygstepper = NULL; struct point *polygstepper2 = NULL; struct point *walker = NULL; int colorchange = 0; freepoints( pointstack ); while( scenestepper && scenestepper->polygon) { struct scene *tempscene; struct point *fillstepper; struct point *retval3 = NULL; int fillint = 0; int tempminx, tempminy, tempmaxx, tempmaxy; polygstepper = scenestepper->polygon; polygstepper2 = scenestepper->polygon->next; retval2 = NULL; while( polygstepper && polygstepper2 ) {//projects polygon lines onto viewport coords //maintains z-depth data with each projected endpoint retval2 = createline( translate( polygstepper ), translate( polygstepper->next ), retval2 ); polygstepper = polygstepper2; polygstepper2 = polygstepper2->next; } polygstepper = scenestepper->polygon; polygstepper2 = scenestepper->polygon->next; //now create lines to fill polygon //fill by x-to-x coords retval3 = NULL; fillint = 0; tempminx = minx( retval2 ); tempmaxx = maxx( retval2 ); for( fillint = tempminx; fillint < tempmaxx; fillint++ ) { struct point *tempstartpoint; struct point *tempendpoint; tempstartpoint = maxyat( retval2, fillint ); tempendpoint = minyat( retval2, fillint ); retval3 = createline( tempstartpoint, tempendpoint, retval3 ); } walker = retval2; while( walker && walker->next ) { walker = walker->next; } walker->next = retval3; walker = NULL; tempscene = ( struct scene * ) malloc( sizeof( struct scene )); tempscene->next = retval; retval = tempscene; retval->polygon = retval2; /* colorchange = rand() % 6; if( colorchange == 0) retval->r += DELTACOLOR ; if( colorchange == 1) retval->g += DELTACOLOR ; if( colorchange == 2) retval->b += DELTACOLOR ; if( colorchange == 3) retval->b -= DELTACOLOR ; if( colorchange == 4) retval->g -= DELTACOLOR ; if( colorchange == 5) retval->r -= DELTACOLOR; retval->r = min( 224, max( retval->r, 24)); retval->g = min( 224, max( retval->g, 24)); retval->b = min( 224, max( retval->b, 24));*/ scenestepper = scenestepper->next; } return( retval ); } int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow ) { static char szAppName[] = "MP2"; HWND hwnd; MSG msg; WNDCLASSEX wndclass; //argc wndclass.cbSize = sizeof( wndclass ); wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon( NULL, IDI_APPLICATION ); wndclass.hCursor = LoadCursor( NULL, IDC_ARROW ); wndclass.hbrBackground= ( HBRUSH ) GetStockObject( BLACK_BRUSH ); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = szAppName; wndclass.hIconSm = LoadIcon( NULL, IDI_APPLICATION ); strcpy( currfile, INFILE1 ); if( szCmdLine[0] ) strcpy( currfile, szCmdLine ); RegisterClassEx( &wndclass ); hwnd = CreateWindowEx( 0x180 | WS_EX_APPWINDOW, //hexval grabbed from Spy++ //0x118 | WS_EX_APPWINDOW, szAppName, NULL, 0x94CC1000 & !WS_SIZEBOX, //hexval grabbed from Spy ++ //0x14840000 | SS_LEFTNOWORDWRAP, 0, 0, WIDTH, HEIGHT, NULL, NULL, hInstance, NULL ); ShowWindow( hwnd, iCmdShow ); UpdateWindow( hwnd ); while( GetMessage( &msg, NULL, 0, 0 )) { TranslateMessage( &msg ); DispatchMessage( &msg ); } return msg.wParam; } /*struct point flatten( struct scene *inscene ) { struct point *retval = NULL; while( inscene ) { retval = inscene->polygon; inscene = inscene->next; }*/ LRESULT CALLBACK WndProc( HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam ) { static int cxClient, cyClient, cxChar, cxCaps, cyChar, windthird; struct scene *TheScene3= NULL; HDC hdc; PAINTSTRUCT ps; switch( iMsg ) { case WM_CREATE: { int z = 0; hdc = GetDC( hwnd ); TheScene=readfile( currfile ); clearZ(); TheScene2 = project(); TheScene3 = TheScene2; clearZ(); while( TheScene3 ) { paintstackcolor( TheScene3->polygon, hdc, red, green, blue ); TheScene3 = TheScene3->next; changecolor(); } makeborder(); paintstackcolornoclip( border, hdc, red, green, blue ); //delscene( TheScene ); delscene( TheScene2 ); //crop here. ReleaseDC( hwnd, hdc ); return( 0 ); } case WM_PAINT : hdc = BeginPaint( hwnd, &ps); TheScene=readfile( currfile ); clearZ(); TheScene2 = project(); TheScene3 = TheScene2; clearZ(); while( TheScene3 ) { paintstackcolor( TheScene3->polygon, hdc, red ,green, blue ); TheScene3 = TheScene3->next; changecolor(); } makeborder(); paintstackcolornoclip( border, hdc, 127, 127, 127 ); //delscene( TheScene ); delscene( TheScene2 ); EndPaint( hwnd, &ps ); return( 0 ); case WM_CHAR: //basically everything from here on is keyboard processing //I did not do it correctly because I found out about the WM_CHAR //message halfway thru coding, will get around to fixing eventually. if( wParam == 0x7E)//~ { vpsizex -= vpsizex * STEPPERCENT / 100; vpsizey -= vpsizey * STEPPERCENT / 100; makeborder(); InvalidateRect( hwnd, NULL, TRUE ); return( 0 ); break; } if( wParam == 0x5A )//Z { zrot += ROT_STEP_DEG * 2 * PI / 360; zrot = reduce( zrot ); InvalidateRect( hwnd, NULL, TRUE ); return( 0 ); break; } if( wParam == 0x59 )//Y { yrot += ROT_STEP_DEG * 2 * PI / 360; yrot = reduce( yrot ); InvalidateRect( hwnd, NULL, TRUE ); return( 0 ); break; } if( wParam == 0x58 )//X { xrot += ROT_STEP_DEG * 2 * PI / 360; xrot = reduce( xrot ); InvalidateRect( hwnd, NULL, TRUE ); return( 0 ); break; } if( wParam == 0x7A )//z { zrot += 2 * PI / 360 - ROT_STEP_DEG * 2 * PI / 360; zrot = reduce(zrot); InvalidateRect( hwnd, NULL, TRUE ); return( 0 ); break; } if( wParam == 0x79 )//y { yrot += 2 * PI / 360 - ROT_STEP_DEG * 2 * PI / 360; yrot = reduce(yrot); InvalidateRect( hwnd, NULL, TRUE ); return( 0 ); break; } if( wParam == 0x78 )//x { xrot += 2 * PI / 360 - ROT_STEP_DEG * 2 * PI / 360; xrot = reduce(xrot); InvalidateRect( hwnd, NULL, TRUE ); return( 0 ); break; } if( wParam == 0x2B )//+ { windowwidth = min( SCENEEXTENTSX, windowwidth + windowwidth * STEPPERCENT / 100 ); windowheight = min( SCENEEXTENTSY, windowheight + windowheight * STEPPERCENT / 100 ); InvalidateRect( hwnd, NULL, TRUE ); return( 0 ); break; } if( wParam == 0x2D )//- { windowwidth -= windowwidth * STEPPERCENT / 100 ; windowheight -= windowheight * STEPPERCENT / 100 ; InvalidateRect( hwnd, NULL, TRUE ); return( 0 ); break; } if( wParam == 0x43 || wParam == 0x63 ) //c { xrot = 0.0; yrot = 0.0; zrot = 0.0; windowwidth = SCENEEXTENTSX; windowheight = SCENEEXTENTSY; windowcenterx = SCENEEXTENTSX / 2 ; windowcentery = SCENEEXTENTSY / 2 ; windowcenterz = SCENEEXTENTSZ / 2 ; vpcenterx = WIDTH / 2; vpcentery = HEIGHT / 2; vpsizex = WIDTH / 2; vpsizey = HEIGHT / 2; makeborder(); InvalidateRect( hwnd, NULL, TRUE ); return( 0 ); break; } return(0); break; case WM_KEYUP: if( wParam == VK_ESCAPE ) { SendMessage( hwnd, WM_DESTROY, 0L, 0L ); return( 0 ); break; } if( wParam == 49 || wParam == VK_NUMPAD1 ) //1 { strcpy( currfile, INFILE1 ); } if(( wParam == 50 && GetKeyState( VK_SHIFT ) >= 0)|| wParam == VK_NUMPAD2 ) //2 { strcpy( currfile, INFILE2 ); } if( wParam == 51 || wParam == VK_NUMPAD3 ) //3 { strcpy( currfile, INFILE3 ); } if( wParam == 49 || wParam == VK_NUMPAD1 || (wParam == 50 && GetKeyState( VK_SHIFT ) >= 0)|| wParam == VK_NUMPAD2 || wParam == 51 || wParam == VK_NUMPAD3 ) { delscene( TheScene ); TheScene=readfile( currfile ); } if( wParam == 68 ) //D { if( GetKeyState( VK_SHIFT ) < 0 ) //uppercase { movewindow( 0, -windowheight/10 ,0 ); } else { movevp( 0, -vpsizey/10 ); } } if( wParam == 76 ) //L { if( GetKeyState( VK_SHIFT ) < 0 ) //uppercase { movewindow( -windowwidth/10, 0,0 ); } else { movevp( -vpsizex/10, 0 ); } } if( wParam == 82 ) //R { if( GetKeyState( VK_SHIFT ) < 0 ) //uppercase { movewindow( windowwidth/10, 0,0 ); } else { movevp( vpsizex/10, 0 ); } } if( wParam == 85 ) //U { if( GetKeyState( VK_SHIFT ) < 0 ) //uppercase { movewindow( 0, windowheight/10 ,0 ); } else { movevp( 0, vpsizey/10 ); } } if( wParam == 50 && GetKeyState( VK_SHIFT ) < 0 ) {//this is bad, it allows you to make a window the size of the "screen" //even if vpsizex = min( vpsizex * ( 100 + STEPPERCENT ) / 100, min( 2 * ( WIDTH - vpcenterx ), 2 * vpcenterx )); vpsizey = min( vpsizey * ( 100 + STEPPERCENT ) / 100, min( 2 * ( HEIGHT - vpcentery), 2 * vpcentery )); makeborder(); } if( wParam == 68 || wParam == 82 || wParam == 76 || wParam == 85 || wParam == 49 || wParam == VK_NUMPAD1 || wParam == 50 || wParam == VK_NUMPAD2 || wParam == 51 || wParam == VK_NUMPAD3) InvalidateRect( hwnd, NULL, TRUE ); return( 0 ); break; case WM_DESTROY: freepoints( pointstack ); freepoints( border ); PostQuitMessage( 0 ); return( 0 ); default: return DefWindowProc( hwnd, iMsg, wParam, lParam ); } }