// Wireframe Drawing Program Version 2 // Last Update: Dec. 7th, 2003 // Thanks to Ch. Tronche for getting me started with X11 // Programmed by Mark Longridge /* GPL license */ /* gcc poly_w2.c -lm -lX11 -o poly_w2 */ #include #include #include #include // Every Xlib program must include this #include #include #include #include #include #include // I include this to test return values the lazy way #include // So we got the profile for 10 seconds #include #define NIL (0) // A name for the void pointer #define TRUE 1 #define FALSE 0 char text[20]; /* vertex number */ char textp[100]; /* window properties */ char est[30]; /* filename */ int types, points, *sides, *poly; int total_sides, total_edges, max_poly; int num_col; int ScreenSizeX, ScreenSizeY; /* The program will find the lowest number which refers to a set * of vertices and will count that as the first set * * For example, if the lowest number is 41001 then all counting * starts from 41001. Similarly the program will work for any * integer from zero up to 9,999,999 */ int start_flag; Display *dpy; Window w, w2; Pixmap m; GC gc; KeySym ks; int xp, yp; int flag; int a, te; int whiteColor, blackColor, thescreen; int x_offset, y_offset; double x,y,t; double x2, y2; double cx, cy, holdy, holdx; double perspective, distance, inc; double mag; double **n; /* Position of points for real 3d */ typedef struct { double x; double y; double z; } pt; pt *point; /* Holds current angle of rotation for x,y,z */ double xt, yt, zt; /* Holds the position of points for screen 2d */ XPoint *spoint; XPoint *vtx; /* Holds vertices for faces */ int ***face; XColor *col; XColor white, blue, orange, red, yellow, green, grey; XColor purple, brown, pink, cyan, beige, magenta; XColor darkgreen, darkred, darkblue, darkgrey; XColor violet, gold, lightgreen, turquoise; Colormap thecolormap; void drawit(int z); void rotate_x() { for (a=1; a<=points; a++) { holdy = point[a].y; point[a].y = point[a].y * cos(t) - point[a].z * sin(t); point[a].z = holdy * sin(t) + point[a].z * cos(t); } xt = xt + t; } void rotate_y() { for (a=1; a<=points; a++) { holdx = point[a].x; point[a].x = point[a].x * cos(t) - point[a].z * sin(t); point[a].z = holdx * sin(t) + point[a].z * cos(t); } yt = yt + t; } void rotate_z() { for (a=1; a<=points; a++) { holdx = point[a].x; point[a].x = point[a].x * cos(t) - point[a].y * sin(t); point[a].y = holdx * sin(t) + point[a].y * cos(t); } zt = zt + t; } void map_to_screen() { int x, z, r; double sum,zz; cx = ScreenSizeX / 2.0; cy = ScreenSizeY / 2.0; zz = point[a].z + perspective; x2 = cx + ( ((point[a].x*ScreenSizeX)/zz)); y2 = cy + ( ((point[a].y*ScreenSizeX)/zz)); } void drawit(int z) { int x, l, r; for (a=1; a<=points; a++) { map_to_screen(); spoint[a].x = (int) x2 + x_offset; spoint[a].y = (int) y2 + y_offset; } if (z == 1) { XSetForeground (dpy, gc, grey.pixel); XFillRectangle (dpy, m, gc, 0, 0, ScreenSizeX, ScreenSizeY); for (r=0; r<=types; r++) { for (l=1; l<=sides[r]; l++) { /* if (n[l][r] > 0.0) */ if (1) { for (x=0; x<=poly[r]-1; x++) { vtx[x+1] = spoint[face[l-1][x][r]-(start_flag-1)]; } if (r > 0) XSetForeground (dpy, gc, col[l+sides[0]].pixel); else XSetForeground (dpy, gc, col[l].pixel); /* XFillPolygon (dpy, m, gc, vtx+1, poly[r], Convex, CoordModeOrigin); */ XSetForeground (dpy, gc, blackColor); for (a=1; a<=poly[r]-1; a++) { XDrawLine (dpy, m, gc, vtx[a].x, vtx[a].y, vtx[a+1].x, vtx[a+1].y); } XDrawLine (dpy, m, gc, vtx[poly[r]].x, vtx[poly[r]].y, vtx[1].x, vtx[1].y); if (te == 1) { XSetForeground (dpy, gc, red.pixel); for (x=0; x<=poly[r]-1; x++) { sprintf (text, "%d", face[l-1][x][r]-(start_flag-1)); XDrawString (dpy, m, gc, vtx[x+1].x, vtx[x+1].y, text, strlen(text)); } } } } } } XCopyArea (dpy, m, w, gc, 0, 0, ScreenSizeX, ScreenSizeY, 0, 0); XFlush(dpy); } void init_x() { int x; // Open the display x=0; dpy = XOpenDisplay(NIL); assert(dpy); // Get some colors blackColor = BlackPixel(dpy, DefaultScreen(dpy)); whiteColor = WhitePixel(dpy, DefaultScreen(dpy)); // Create the window w = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0, ScreenSizeX, ScreenSizeY, 0, blackColor, blackColor); sprintf (textp, "%s Vertices %d Edges %d Faces %d ", est, points, total_edges, total_sides); XSetStandardProperties(dpy,w, textp,"Hi",None,NULL,0,NULL); // We want to get MapNotify events XSelectInput(dpy, w, StructureNotifyMask | ExposureMask | KeyPressMask); // "Map" the window (that is, make it appear on the screen) XClearWindow (dpy, w); XMapWindow(dpy, w); // Create a "Graphics Context" gc = XCreateGC(dpy, w, 0, NIL); thescreen = DefaultScreen(dpy); thecolormap = DefaultColormap(dpy,thescreen); m = XCreatePixmap (dpy, w, ScreenSizeX, ScreenSizeY, DefaultDepth(dpy, thescreen)); XSetLineAttributes (dpy, gc, 2, LineSolid, CapNotLast, JoinMiter ); XAllocNamedColor(dpy, thecolormap, "grey", &grey, &col[0]); XAllocNamedColor(dpy, thecolormap, "white", &white, &col[1]); XAllocNamedColor(dpy, thecolormap, "red", &red, &col[2]); XAllocNamedColor(dpy, thecolormap, "blue", &blue, &col[3]); XAllocNamedColor(dpy, thecolormap, "orange", &orange, &col[4]); XAllocNamedColor(dpy, thecolormap, "green", &green, &col[5]); XAllocNamedColor(dpy, thecolormap, "yellow", &yellow, &col[6]); XAllocNamedColor(dpy, thecolormap, "purple", &purple, &col[7]); XAllocNamedColor(dpy, thecolormap, "beige", &beige, &col[8]); XAllocNamedColor(dpy, thecolormap, "cyan", &cyan, &col[9]); XAllocNamedColor(dpy, thecolormap, "pink", &pink, &col[10]); XAllocNamedColor(dpy, thecolormap, "brown", &brown, &col[11]); XAllocNamedColor(dpy, thecolormap, "magenta", &magenta, &col[12]); XAllocNamedColor(dpy, thecolormap, "darkgreen", &darkgreen, &col[13]); XAllocNamedColor(dpy, thecolormap, "darkred", &darkred, &col[14]); XAllocNamedColor(dpy, thecolormap, "darkgrey", &darkgrey, &col[15]); XAllocNamedColor(dpy, thecolormap, "gold", &gold, &col[16]); XAllocNamedColor(dpy, thecolormap, "violet", &violet, &col[17]); XAllocNamedColor(dpy, thecolormap, "turquoise", &turquoise, &col[18]); XAllocNamedColor(dpy, thecolormap, "lightgreen", &lightgreen, &col[19]); XAllocNamedColor(dpy, thecolormap, "magenta", &magenta, &col[20]); XSetFont (dpy, gc, XLoadFont (dpy, "fixed")); x=1; if (total_sides > num_col) { while (x <= total_sides-num_col) { col[num_col+x] = col[x]; x++; } } } int init_cube(int mem) { int rc, x, r, s; int low_val; double high_x, low_x; char test1[15], test2[15], test3[15]; FILE *fp_in; te=1; high_x = 0; low_x = 0; low_val = 999999; fp_in = fopen (est,"r"); if (fp_in == NULL) { printf ("\nNo input file %s\n",est); return(-1); } /* Set up points */ a = 0; max_poly = 0; points = 0; rc = 0; while (points == 0 && rc != EOF) { /* If points is zero, treat this as a comment */ rc = fscanf (fp_in, "%s", test1); points = atoi (test1); } if (points == 0 ) { printf ("\nInvalid data\n"); return(-1); } rc = fscanf (fp_in, "%s", test1); types = atoi (test1); if (mem == 0) sides = (int *) calloc (types+1, sizeof(int)); if (sides == NULL) exit(0); if (mem == 0) poly = (int *) calloc (types+1, sizeof(int)); if (poly == NULL) exit(0); printf ("\nPoints %d Types %d", points, types); if (mem == 0) point = (pt *) calloc (points+1, sizeof(pt)); if (point == NULL) exit(0); /* Allocate 2d screen points */ if (mem == 0) spoint = (XPoint *) calloc (points+1, sizeof(XPoint)); if (spoint == NULL) exit(0); if (mem == 0) vtx = (XPoint *) calloc (points+1, sizeof(XPoint)); if (vtx == NULL) exit(0); for (r=0; r<=types-1; r++) { rc = fscanf (fp_in, "%s %s", test1, test2); sides[r] = atoi (test1); poly[r] = atoi (test2); total_sides = total_sides + sides[r]; total_edges = total_edges + (sides[r] * poly[r] /2); if (max_poly < poly[r]) max_poly = poly[r]; printf ("\nSides: %d Poly: %d", sides[r], poly[r]); } printf ("\nMax poly: %d", max_poly); /* Allocate 20 colours or total_sides colours, whatever is bigger */ if (mem == 0) { if (total_sides <= 20) col = (XColor *) calloc (20+1, sizeof(XColor)); else col = (XColor *) calloc (total_sides+1, sizeof(XColor)); } if (col == NULL) exit(0); /* Dynamically allocate memory for double dimensional array n */ if (mem == 0) { n = (double **) calloc (total_sides+1, sizeof(double)); for (r=0; r<=total_sides+1; r++) n[r] = (double *) calloc (types+1, sizeof(double)); /* Dynamically allocate memory for triple dimensional array face */ face = (int ***) calloc (total_sides+1, sizeof(int)); for (r=0; r<=total_sides+1; r++) { face[r] = (int **) calloc (max_poly+1, sizeof(int)); for (s=0; s<=max_poly+1; s++) { face[r][s] = (int *) calloc (types+1, sizeof(int)); } } } while (a < points) { rc = fscanf (fp_in, "%s %s %s", test1, test2, test3); if (rc < 1) { break; } a++; point[a].x = strtod (test1,(char **)NULL); if (point[a].x > high_x) high_x = point[a].x; if (point[a].x < low_x) low_x = point[a].x; point[a].y = strtod (test2,(char **)NULL); point[a].z = strtod (test3,(char **)NULL); /* printf ("\n%1.14f %1.14f %1.14f", point[a].x, point[a].y, point[a].z); */ } perspective = (high_x + fabs(low_x)) * 3; inc = perspective / 20; printf ("\nHigh x: %f", high_x); printf ("\nLow x: %f", low_x); printf ("\nPerspective: %f", perspective); start_flag = 0; for (r=0; r<=types; r++) { a = 0; while (a < sides[r]) { for (x=0; x<=poly[r]-1; x++) { rc = fscanf (fp_in, "%s", test1); if (rc == -1) break; face[a][x][r] = atoi (test1); if (face[a][x][r] < low_val) { low_val = face[a][x][r]; start_flag = low_val; } } if (rc == -1) { printf ("\nCould not read at: %d\n", a); break; } a++; } } printf ("\nLow Value: %d", low_val); printf ("\n"); fclose (fp_in); return(1); } int main(int argc, char **argv) { int z, rc; z=1; num_col = 20; x_offset = 0; y_offset = 0; ScreenSizeX = 800; ScreenSizeY = ScreenSizeX * .75; if (argc > 2) { ScreenSizeX = atoi (argv[2]); ScreenSizeY = ScreenSizeX * .75; } if (argc > 1) strcpy (est, argv[1]); else { printf ("\nUsage: poly_w2 file [screensize]\n"); return(0); } /* Set up the attributes of the polyhedra */ rc = init_cube(0); if (rc == -1) return(-1); /* Set up the attributes of the window */ init_x(); flag = 0; t = .02; xt = 0; yt = 0; zt = 0; /* Wait for the MapNotify event */ while (flag == 0) { XEvent e; XNextEvent(dpy, &e); switch (e.type) { case Expose: drawit(1); break; case MapNotify: break; case KeyPress: ks = XKeycodeToKeysym (dpy, e.xkey.keycode, 0); switch (ks) { case XK_x: rotate_x(); drawit(1); break; case XK_y: rotate_y(); drawit(1); break; case XK_z: rotate_z(); drawit(1); break; case XK_r: init_cube(1); drawit(1); break; case XK_equal: perspective = perspective + inc; drawit(1); break; case XK_minus: perspective = perspective - inc; drawit(1); break; case XK_t: t = t * -1.0; break; case XK_m: x_offset = x_offset - 1; drawit(1); break; case XK_n: y_offset = y_offset + 1; drawit(1); break; case XK_comma: x_offset = x_offset + 1; drawit(1); break; case XK_h: y_offset = y_offset - 1; drawit(1); break; case XK_1: te = te * -1; drawit(1); break; case XK_q: flag=1; printf ("\n"); break; } } } /* Free Window and Pixmap and exit */ XDestroyWindow (dpy, w); XFreePixmap (dpy, m); XCloseDisplay(dpy); }