|
|
1.1 ! root 1: /* $Header: ico.c,v 1.1 87/09/11 08:23:25 toddb Exp $ */ ! 2: /*********************************************************** ! 3: Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, ! 4: and the Massachusetts Institute of Technology, Cambridge, Massachusetts. ! 5: ! 6: All Rights Reserved ! 7: ! 8: Permission to use, copy, modify, and distribute this software and its ! 9: documentation for any purpose and without fee is hereby granted, ! 10: provided that the above copyright notice appear in all copies and that ! 11: both that copyright notice and this permission notice appear in ! 12: supporting documentation, and that the names of Digital or MIT not be ! 13: used in advertising or publicity pertaining to distribution of the ! 14: software without specific, written prior permission. ! 15: ! 16: DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ! 17: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ! 18: DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ! 19: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, ! 20: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ! 21: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS ! 22: SOFTWARE. ! 23: ! 24: ******************************************************************/ ! 25: /****************************************************************************** ! 26: * Description ! 27: * Display a wire-frame rotating icosahedron, with hidden lines removed ! 28: * ! 29: * Arguments: ! 30: * -r display on root window instead of creating a new one ! 31: * =wxh+x+y X geometry for new window (default 600x600 centered) ! 32: * host:display X display on which to run ! 33: *****************************************************************************/ ! 34: ! 35: ! 36: ! 37: #include <X11/Xlib.h> ! 38: #include <X11/Xatom.h> ! 39: #include <X11/Xutil.h> ! 40: #include <stdio.h> ! 41: ! 42: ! 43: ! 44: typedef struct ! 45: { ! 46: double x, y, z; ! 47: } Point3D; ! 48: ! 49: typedef double Transform3D[4][4]; ! 50: ! 51: ! 52: ! 53: extern GC XCreateGC(); ! 54: extern long time(); ! 55: extern long random(); ! 56: ! 57: Display *dpy; ! 58: ! 59: /****************************************************************************** ! 60: * Description ! 61: * Main routine. Process command-line arguments, then bounce a bounding ! 62: * box inside the window. Call DrawIco() to redraw the icosahedron. ! 63: *****************************************************************************/ ! 64: ! 65: main(argc, argv) ! 66: int argc; ! 67: char **argv; ! 68: { ! 69: char *display = NULL; ! 70: char *geom = NULL; ! 71: int useRoot = 0; ! 72: int fg, bg; ! 73: int invert = 0; ! 74: int dash = 0; ! 75: ! 76: Window win; ! 77: int winX, winY, winW, winH; ! 78: XSetWindowAttributes xswa; ! 79: ! 80: GC gc; ! 81: ! 82: int icoX, icoY; ! 83: int icoDeltaX, icoDeltaY; ! 84: int icoW, icoH; ! 85: ! 86: XEvent xev; ! 87: XGCValues xgcv; ! 88: ! 89: /* Process arguments: */ ! 90: ! 91: while (*++argv) ! 92: { ! 93: if (**argv == '=') ! 94: geom = *argv; ! 95: else if (index(*argv, ':')) ! 96: display = *argv; ! 97: else if (!strcmp(*argv, "-r")) ! 98: useRoot = 1; ! 99: else if (!strcmp (*argv, "-d")) ! 100: dash = atoi(*++argv); ! 101: else if (!strcmp(*argv, "-i")) ! 102: invert = 1; ! 103: } ! 104: ! 105: ! 106: if (!(dpy= XOpenDisplay(display))) ! 107: { ! 108: perror("Cannot open display\n"); ! 109: exit(-1); ! 110: } ! 111: ! 112: if (invert) ! 113: { ! 114: fg = BlackPixel(dpy, DefaultScreen(dpy)); ! 115: bg = WhitePixel(dpy, DefaultScreen(dpy)); ! 116: } ! 117: else ! 118: { ! 119: fg = WhitePixel(dpy, DefaultScreen(dpy)); ! 120: bg = BlackPixel(dpy, DefaultScreen(dpy)); ! 121: } ! 122: ! 123: /* Set up window parameters, create and map window if necessary: */ ! 124: ! 125: if (useRoot) ! 126: { ! 127: win = DefaultRootWindow(dpy); ! 128: winX = 0; ! 129: winY = 0; ! 130: winW = DisplayWidth(dpy, DefaultScreen(dpy)); ! 131: winH = DisplayHeight(dpy, DefaultScreen(dpy)); ! 132: } ! 133: else ! 134: { ! 135: winW = 600; ! 136: winH = 600; ! 137: winX = (DisplayWidth(dpy, DefaultScreen(dpy)) - winW) >> 1; ! 138: winY = (DisplayHeight(dpy, DefaultScreen(dpy)) - winH) >> 1; ! 139: if (geom) ! 140: XParseGeometry(geom, &winX, &winY, &winW, &winH); ! 141: ! 142: xswa.event_mask = 0; ! 143: xswa.background_pixel = bg; ! 144: xswa.border_pixel = fg; ! 145: win = XCreateWindow(dpy, DefaultRootWindow(dpy), ! 146: winX, winY, winW, winH, 0, ! 147: DefaultDepth(dpy, DefaultScreen(dpy)), ! 148: InputOutput, DefaultVisual(dpy, DefaultScreen(dpy)), ! 149: CWEventMask | CWBackPixel | CWBorderPixel, &xswa); ! 150: XChangeProperty(dpy, win, XA_WM_NAME, XA_STRING, 8, ! 151: PropModeReplace, "Ico", 3); ! 152: XMapWindow(dpy, win); ! 153: } ! 154: ! 155: ! 156: /* Set up a graphics context: */ ! 157: ! 158: gc = XCreateGC(dpy, win, 0, NULL); ! 159: XSetForeground(dpy, gc, fg); ! 160: XSetBackground(dpy, gc, bg); ! 161: ! 162: if (dash) ! 163: { ! 164: xgcv.line_style = LineDoubleDash; ! 165: xgcv.dashes = dash; ! 166: XChangeGC(dpy, gc, GCLineStyle | GCDashList, &xgcv); ! 167: } ! 168: ! 169: /* Get the initial position, size, and speed of the bounding-box: */ ! 170: ! 171: icoW = icoH = 150; ! 172: srandom((int) time(0) % 231); ! 173: icoX = ((winW - icoW) * (random() & 0xFF)) >> 8; ! 174: icoY = ((winH - icoH) * (random() & 0xFF)) >> 8; ! 175: icoDeltaX = 13; ! 176: icoDeltaY = 9; ! 177: ! 178: ! 179: /* Bounce the box in the window: */ ! 180: ! 181: for (;;) ! 182: { ! 183: int prevX; ! 184: int prevY; ! 185: ! 186: if (XPending(dpy)) ! 187: XNextEvent(dpy, &xev); ! 188: ! 189: prevX = icoX; ! 190: prevY = icoY; ! 191: ! 192: icoX += icoDeltaX; ! 193: if (icoX < 0 || icoX + icoW > winW) ! 194: { ! 195: icoX -= (icoDeltaX << 1); ! 196: icoDeltaX = - icoDeltaX; ! 197: } ! 198: icoY += icoDeltaY; ! 199: if (icoY < 0 || icoY + icoH > winH) ! 200: { ! 201: icoY -= (icoDeltaY << 1); ! 202: icoDeltaY = - icoDeltaY; ! 203: } ! 204: ! 205: drawIco(win, gc, icoX, icoY, icoW, icoH, prevX, prevY); ! 206: } ! 207: } ! 208: ! 209: ! 210: ! 211: /****************************************************************************** ! 212: * Description ! 213: * Undraw previous icosahedron (by erasing its bounding box). ! 214: * Rotate and draw the new icosahedron. ! 215: * ! 216: * Input ! 217: * win window on which to draw ! 218: * gc X11 graphics context to be used for drawing ! 219: * icoX, icoY position of upper left of bounding-box ! 220: * icoW, icoH size of bounding-box ! 221: * prevX, prevY position of previous bounding-box ! 222: *****************************************************************************/ ! 223: ! 224: drawIco(win, gc, icoX, icoY, icoW, icoH, prevX, prevY) ! 225: Window win; ! 226: GC gc; ! 227: int icoX, icoY, icoW, icoH; ! 228: int prevX, prevY; ! 229: { ! 230: static int initialized = 0; ! 231: static Point3D v[] = /* icosahedron vertices */ ! 232: { ! 233: { 0.00000000, 0.00000000, -0.95105650}, ! 234: { 0.00000000, 0.85065080, -0.42532537}, ! 235: { 0.80901698, 0.26286556, -0.42532537}, ! 236: { 0.50000000, -0.68819095, -0.42532537}, ! 237: {-0.50000000, -0.68819095, -0.42532537}, ! 238: {-0.80901698, 0.26286556, -0.42532537}, ! 239: { 0.50000000, 0.68819095, 0.42532537}, ! 240: { 0.80901698, -0.26286556, 0.42532537}, ! 241: { 0.00000000, -0.85065080, 0.42532537}, ! 242: {-0.80901698, -0.26286556, 0.42532537}, ! 243: {-0.50000000, 0.68819095, 0.42532537}, ! 244: { 0.00000000, 0.00000000, 0.95105650} ! 245: }; ! 246: static int f[] = /* icosahedron faces (indices in v) */ ! 247: { ! 248: 0, 2, 1, ! 249: 0, 3, 2, ! 250: 0, 4, 3, ! 251: 0, 5, 4, ! 252: 0, 1, 5, ! 253: 1, 6, 10, ! 254: 1, 2, 6, ! 255: 2, 7, 6, ! 256: 2, 3, 7, ! 257: 3, 8, 7, ! 258: 3, 4, 8, ! 259: 4, 9, 8, ! 260: 4, 5, 9, ! 261: 5, 10, 9, ! 262: 5, 1, 10, ! 263: 10, 6, 11, ! 264: 6, 7, 11, ! 265: 7, 8, 11, ! 266: 8, 9, 11, ! 267: 9, 10, 11 ! 268: }; ! 269: # define NV (sizeof(v) / sizeof(v[0])) ! 270: # define NF (sizeof(f) / (3 * sizeof(f[0]))) ! 271: ! 272: static Transform3D xform; ! 273: static Point3D xv[2][NV]; ! 274: static int buffer; ! 275: register int p0; ! 276: register int p1; ! 277: register int p2; ! 278: register XPoint *pv2; ! 279: XSegment *pe; ! 280: char drawn[NV][NV]; ! 281: register Point3D *pxv; ! 282: static double wo2, ho2; ! 283: XPoint v2[NV]; ! 284: XSegment edges[30]; ! 285: register int i; ! 286: register int *pf; ! 287: ! 288: ! 289: /* Set up points, transforms, etc.: */ ! 290: ! 291: if (!initialized) ! 292: { ! 293: Transform3D r1; ! 294: Transform3D r2; ! 295: ! 296: FormatRotateMat('x', 5 * 3.1416 / 180.0, r1); ! 297: FormatRotateMat('y', 5 * 3.1416 / 180.0, r2); ! 298: ConcatMat(r1, r2, xform); ! 299: ! 300: bcopy((char *) v, (char *) xv[0], NV * sizeof(Point3D)); ! 301: buffer = 0; ! 302: ! 303: wo2 = icoW / 2.0; ! 304: ho2 = icoH / 2.0; ! 305: ! 306: initialized = 1; ! 307: } ! 308: ! 309: ! 310: /* Switch double-buffer and rotate vertices: */ ! 311: ! 312: buffer = !buffer; ! 313: PartialNonHomTransform(NV, xform, xv[!buffer], xv[buffer]); ! 314: ! 315: ! 316: /* Convert 3D coordinates to 2D window coordinates: */ ! 317: ! 318: pxv = xv[buffer]; ! 319: pv2 = v2; ! 320: for (i = NV - 1; i >= 0; --i) ! 321: { ! 322: pv2->x = (int) ((pxv->x + 1.0) * wo2) + icoX; ! 323: pv2->y = (int) ((pxv->y + 1.0) * ho2) + icoY; ! 324: ++pxv; ! 325: ++pv2; ! 326: } ! 327: ! 328: ! 329: /* Accumulate edges to be drawn, eliminating duplicates for speed: */ ! 330: ! 331: pxv = xv[buffer]; ! 332: pv2 = v2; ! 333: pf = f; ! 334: pe = edges; ! 335: bzero(drawn, sizeof(drawn)); ! 336: for (i = NF - 1; i >= 0; --i) ! 337: { ! 338: p0 = *pf++; ! 339: p1 = *pf++; ! 340: p2 = *pf++; ! 341: ! 342: /* If facet faces away from viewer, don't consider it: */ ! 343: if (pxv[p0].z + pxv[p1].z + pxv[p2].z < 0.0) ! 344: continue; ! 345: ! 346: if (!drawn[p0][p1]) ! 347: { ! 348: drawn[p0][p1] = 1; ! 349: drawn[p1][p0] = 1; ! 350: pe->x1 = pv2[p0].x; ! 351: pe->y1 = pv2[p0].y; ! 352: pe->x2 = pv2[p1].x; ! 353: pe->y2 = pv2[p1].y; ! 354: ++pe; ! 355: } ! 356: if (!drawn[p1][p2]) ! 357: { ! 358: drawn[p1][p2] = 1; ! 359: drawn[p2][p1] = 1; ! 360: pe->x1 = pv2[p1].x; ! 361: pe->y1 = pv2[p1].y; ! 362: pe->x2 = pv2[p2].x; ! 363: pe->y2 = pv2[p2].y; ! 364: ++pe; ! 365: } ! 366: if (!drawn[p2][p0]) ! 367: { ! 368: drawn[p2][p0] = 1; ! 369: drawn[p0][p2] = 1; ! 370: pe->x1 = pv2[p2].x; ! 371: pe->y1 = pv2[p2].y; ! 372: pe->x2 = pv2[p0].x; ! 373: pe->y2 = pv2[p0].y; ! 374: ++pe; ! 375: } ! 376: } ! 377: ! 378: ! 379: /* Erase previous, draw current icosahedrons; sync for smoothness. */ ! 380: ! 381: XClearArea(dpy, win, prevX, prevY, icoW + 1, icoH + 1, 0); ! 382: XDrawSegments(dpy, win, gc, edges, pe - edges); ! 383: XSync(dpy, 0); ! 384: } ! 385: ! 386: ! 387: ! 388: /****************************************************************************** ! 389: * Description ! 390: * Concatenate two 4-by-4 transformation matrices. ! 391: * ! 392: * Input ! 393: * l multiplicand (left operand) ! 394: * r multiplier (right operand) ! 395: * ! 396: * Output ! 397: * *m Result matrix ! 398: *****************************************************************************/ ! 399: ! 400: ConcatMat(l, r, m) ! 401: register Transform3D l; ! 402: register Transform3D r; ! 403: register Transform3D m; ! 404: { ! 405: register int i; ! 406: register int j; ! 407: register int k; ! 408: ! 409: for (i = 0; i < 4; ++i) ! 410: for (j = 0; j < 4; ++j) ! 411: m[i][j] = l[i][0] * r[0][j] ! 412: + l[i][1] * r[1][j] ! 413: + l[i][2] * r[2][j] ! 414: + l[i][3] * r[3][j]; ! 415: } ! 416: ! 417: ! 418: ! 419: /****************************************************************************** ! 420: * Description ! 421: * Format a matrix that will perform a rotation transformation ! 422: * about the specified axis. The rotation angle is measured ! 423: * counterclockwise about the specified axis when looking ! 424: * at the origin from the positive axis. ! 425: * ! 426: * Input ! 427: * axis Axis ('x', 'y', 'z') about which to perform rotation ! 428: * angle Angle (in radians) of rotation ! 429: * A Pointer to rotation matrix ! 430: * ! 431: * Output ! 432: * *m Formatted rotation matrix ! 433: *****************************************************************************/ ! 434: ! 435: FormatRotateMat(axis, angle, m) ! 436: char axis; ! 437: double angle; ! 438: register Transform3D m; ! 439: { ! 440: double s, c; ! 441: double sin(), cos(); ! 442: ! 443: IdentMat(m); ! 444: ! 445: s = sin(angle); ! 446: c = cos(angle); ! 447: ! 448: switch(axis) ! 449: { ! 450: case 'x': ! 451: m[1][1] = m[2][2] = c; ! 452: m[1][2] = s; ! 453: m[2][1] = -s; ! 454: break; ! 455: case 'y': ! 456: m[0][0] = m[2][2] = c; ! 457: m[2][0] = s; ! 458: m[0][2] = -s; ! 459: break; ! 460: case 'z': ! 461: m[0][0] = m[1][1] = c; ! 462: m[0][1] = s; ! 463: m[1][0] = -s; ! 464: break; ! 465: } ! 466: } ! 467: ! 468: ! 469: ! 470: /****************************************************************************** ! 471: * Description ! 472: * Format a 4x4 identity matrix. ! 473: * ! 474: * Output ! 475: * *m Formatted identity matrix ! 476: *****************************************************************************/ ! 477: ! 478: IdentMat(m) ! 479: register Transform3D m; ! 480: { ! 481: register int i; ! 482: register int j; ! 483: ! 484: for (i = 3; i >= 0; --i) ! 485: { ! 486: for (j = 3; j >= 0; --j) ! 487: m[i][j] = 0.0; ! 488: m[i][i] = 1.0; ! 489: } ! 490: } ! 491: ! 492: ! 493: ! 494: /****************************************************************************** ! 495: * Description ! 496: * Perform a partial transform on non-homogeneous points. ! 497: * Given an array of non-homogeneous (3-coordinate) input points, ! 498: * this routine multiplies them by the 3-by-3 upper left submatrix ! 499: * of a standard 4-by-4 transform matrix. The resulting non-homogeneous ! 500: * points are returned. ! 501: * ! 502: * Input ! 503: * n number of points to transform ! 504: * m 4-by-4 transform matrix ! 505: * in array of non-homogeneous input points ! 506: * ! 507: * Output ! 508: * *out array of transformed non-homogeneous output points ! 509: *****************************************************************************/ ! 510: ! 511: PartialNonHomTransform(n, m, in, out) ! 512: int n; ! 513: register Transform3D m; ! 514: register Point3D *in; ! 515: register Point3D *out; ! 516: { ! 517: for (; n > 0; --n, ++in, ++out) ! 518: { ! 519: out->x = in->x * m[0][0] + in->y * m[1][0] + in->z * m[2][0]; ! 520: out->y = in->x * m[0][1] + in->y * m[1][1] + in->z * m[2][1]; ! 521: out->z = in->x * m[0][2] + in->y * m[1][2] + in->z * m[2][2]; ! 522: } ! 523: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.