| /*
* Double buffered wireframe display of rotating Klein bottle
*
* Assumes 8 plane pseudocolor visual; click on window to exit.
*
* Jim Roth, CAD/CAM Technology Center
*
* cc -o kleinbottle -O3 -f kleinbottle.c -lm -lX11
*
* $ CC/PREC=SINGLE KLEINBOTTLE.C
* $ LINK KLEINBOTTLE,SYS$INPUT:/OPTION
* SYS$SHARE:VAXCRTL/SHARE
* SYS$SHARE:DECW$XLIBSHR/SHARE
* SYS$SHARE:DECW$DWTLIBSHR/SHARE
* $ EXIT
*/
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
#include <stdio.h>
#include <math.h>
extern GC XCreateGC();
#define PI 3.1415926535897932384264338
#define NRAD 32
#define NWID 32
#define NPTS ((NRAD+1)*(NWID+1))
#define NLINES (2*(NRAD+1)*(NWID+1))
static float twopi = 2.0*PI;
static float rtd = 180.0/PI;
static float dtr = PI/180.0;
static float xpts[NPTS], ypts[NPTS], zpts[NPTS];
static long lintab[NLINES][2];
static XSegment segbuf[NLINES];
static int npts = 0;
static int nlines = 0;
static int nsubdiv = 0;
static int nrad = 32, nwid = 32;
create_bottle(float x[],
float y[],
float z[],
long lintab[][2])
{
float a, c, s, d, t, u;
float wx1, wy1, wx2, wy2;
int i, j, i1, i2, j1, j2;
float tfract, wfract;
float radius;
tfract = 1.0; /* fraction of turn to construct */
wfract = 1.0; /* fraction of width to construct */
radius = 0.3; /* ring radius */
npts = 0;
for (i = 0; i <= nrad; i++) {
u = tfract*twopi*(float)i/(float)nrad;
for (j = 0; j < nwid; j++) {
t = ((float)j-.5*(float)nwid)/(.5*(float)nwid);
t *= wfract*PI;
a = sin(t)*(cos(.5*u)+sin(.5*u)*cos(t))-2.0;
z[npts] = sin(t)*(-sin(.5*u)+cos(.5*u)*cos(t));
x[npts] = a*cos(u);
y[npts] = a*sin(u);
x[npts] *= radius;
y[npts] *= radius;
z[npts] *= radius;
npts++;
}
}
nlines = 0;
for (i1 = 0; i1 <= nrad; i1++) {
i2 = i1+1;
if (i2 > nrad) i2--;
for (j1 = 0; j1 < nwid; j1++) {
j2 = j1+1;
if (j2 == nwid) j2--;
lintab[nlines][0] = nwid*i1+j1;
lintab[nlines++][1] = nwid*i1+j2;
lintab[nlines][0] = nwid*i1+j1;
lintab[nlines++][1] = nwid*i2+j1;
}
}
}
main()
{
int status;
Display *dpy;
Window win;
Colormap cmap;
GC gc;
XSetWindowAttributes xswa;
XWindowAttributes xwa;
char *display = NULL;
char *geom = NULL;
XEvent xev;
XGCValues xgcv;
int winW, winH, winX, winY;
int winWidth, winHeight;
int fg, bg;
unsigned int planes[2];
unsigned int pixels[1];
unsigned int ncolors, nplanes;
int i, j, k;
float ai, aj;
int borderW, pixDepth;
Window root;
float a, c, s, t, u;
float ux1, uy1, ux2, uy2;
int ipts;
XColor color;
XColor frame_0_colors[4], frame_1_colors[4];
GC erase_0_gc, erase_1_gc;
GC draw_0_gc, draw_1_gc;
GC erase_gc, draw_gc;
int mask_0, mask_1;
int frame_to_write = 0;
float d = 5.0;
create_bottle(xpts, ypts, zpts, lintab);
if (!(dpy = XOpenDisplay(display)))
perror("Cannot open display\n");
winW = 800;
winH = 800;
winX = (DisplayWidth(dpy, DefaultScreen(dpy)) - winW) >> 1;
winY = (DisplayHeight(dpy, DefaultScreen(dpy)) - winH) >> 1;
if (!(cmap = XDefaultColormap(dpy, DefaultScreen(dpy))))
perror("can't get default colormap");
nplanes = 2;
ncolors = 1;
status = XAllocColorCells(dpy, cmap, 0,
planes,
nplanes,
pixels,
ncolors);
if (status == 0)
perror("can't allocate color planes");
color.pixel = pixels[0];
color.red = color.green = color.blue = 0;
color.flags = DoRed | DoGreen | DoBlue;
XStoreColor(dpy, cmap, &color);
color.pixel = pixels[0] | planes[0] | planes[1];
color.red = color.green = color.blue = 65535;
color.flags = DoRed | DoGreen | DoBlue;
XStoreColor(dpy, cmap, &color);
for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++) {
frame_0_colors[i*2+j].pixel = pixels[0] |
(i & 1 ? planes[0] : 0) |
(j & 1 ? planes[1] : 0);
frame_0_colors[i*2+j].red = i & 1 ? 65535 : 0;
frame_0_colors[i*2+j].green = i & 1 ? 65535 : 0;
frame_0_colors[i*2+j].blue = i & 1 ? 65535 : 0;
frame_0_colors[i*2+j].flags = DoRed | DoGreen | DoBlue;
frame_1_colors[i*2+j].pixel = pixels[0] |
(i & 1 ? planes[0] : 0) |
(j & 1 ? planes[1] : 0);
frame_1_colors[i*2+j].red = j & 1 ? 65535 : 0;
frame_1_colors[i*2+j].green = j & 1 ? 65535 : 0;
frame_1_colors[i*2+j].blue = j & 1 ? 65535 : 0;
frame_1_colors[i*2+j].flags = DoRed | DoGreen | DoBlue;
}
}
xswa.event_mask = 0;
xswa.background_pixel = pixels[0];
xswa.border_pixel = pixels[0] | planes[0] | planes[1];
xswa.event_mask = ButtonPressMask;
win = XCreateWindow(dpy, DefaultRootWindow(dpy),
winX, winY, winW, winH, 0,
DefaultDepth(dpy, DefaultScreen(dpy)),
InputOutput, DefaultVisual(dpy, DefaultScreen(dpy)),
CWEventMask | CWBackPixel | CWBorderPixel, &xswa);
XChangeProperty(dpy, win, XA_WM_NAME, XA_STRING, 8,
PropModeReplace, "Klein Bottle", 12);
mask_0 = ~(planes[1]);
mask_1 = ~(planes[0]);
erase_0_gc = XCreateGC(dpy, win, 0, NULL);
XSetForeground(dpy, erase_0_gc, pixels[0]);
XSetBackground(dpy, erase_0_gc, pixels[0]);
XSetPlaneMask(dpy, erase_0_gc, mask_0);
XSetFunction(dpy, erase_0_gc, GXcopy);
erase_1_gc = XCreateGC(dpy, win, 0, NULL);
XSetForeground(dpy, erase_1_gc, pixels[0]);
XSetBackground(dpy, erase_1_gc, pixels[0]);
XSetPlaneMask(dpy, erase_1_gc, mask_1);
XSetFunction(dpy, erase_1_gc, GXcopy);
draw_0_gc = XCreateGC(dpy, win, 0, NULL);
XSetBackground(dpy, draw_0_gc, pixels[0]);
XSetPlaneMask(dpy, draw_0_gc, mask_0);
XSetFunction(dpy, draw_0_gc, GXcopy);
draw_1_gc = XCreateGC(dpy, win, 0, NULL);
XSetBackground(dpy, draw_1_gc, pixels[0]);
XSetPlaneMask(dpy, draw_1_gc, mask_1);
XSetFunction(dpy, draw_1_gc, GXcopy);
XMapWindow(dpy, win);
if (XGetWindowAttributes(dpy,win,&xwa)==0)
perror("can't get window attributes (size)");
winWidth = xwa.width;
winHeight = xwa.height;
XSetWindowColormap(dpy, win, cmap);
XGetGeometry(dpy, win, &root,
&winX, &winY, &winW, &winH, &borderW, &pixDepth);
c = cos(5.0*dtr);
s = sin(5.0*dtr);
for (i = 0; i < npts; i++) {
t = ypts[i]*c - zpts[i]*s;
zpts[i] = ypts[i]*s + zpts[i]*c;
ypts[i] = t;
}
frame_to_write = 0;
XStoreColors(dpy, cmap, frame_0_colors, 4);
XFillRectangle(dpy, win, erase_0_gc, 0, 0, winW, winH);
XFillRectangle(dpy, win, erase_1_gc, 0, 0, winW, winH);
XSync(dpy, 0);
loop:
{
XEvent event;
while (XPending(dpy)) {
XNextEvent(dpy, &event);
if (event.type == ButtonPress)
exit(0);
}
}
{
float c, s;
if (frame_to_write) {
fg = pixels[0] | planes[1];
XSetForeground(dpy, draw_1_gc, fg);
erase_gc = erase_1_gc;
draw_gc = draw_1_gc;
}
else {
fg = pixels[0] | planes[0];
XSetForeground(dpy, draw_0_gc, fg);
erase_gc = erase_0_gc;
draw_gc = draw_0_gc;
}
c = cos(6.5*dtr);
s = sin(6.5*dtr);
for (i = 0; i < npts; i++) {
t = xpts[i]*c - zpts[i]*s;
zpts[i] = xpts[i]*s + zpts[i]*c;
xpts[i] = t;
}
c = cos(5.5*dtr);
s = sin(5.5*dtr);
for (i = 0; i < npts; i++) {
t = ypts[i]*c - zpts[i]*s;
zpts[i] = ypts[i]*s + zpts[i]*c;
ypts[i] = t;
}
d = 4.0;
for (i = 0; i < nlines; i++) {
float ux1 = d/(d+zpts[lintab[i][0]])*(xpts[lintab[i][0]]);
float uy1 = d/(d+zpts[lintab[i][0]])*(ypts[lintab[i][0]]);
float ux2 = d/(d+zpts[lintab[i][1]])*(xpts[lintab[i][1]]);
float uy2 = d/(d+zpts[lintab[i][1]])*(ypts[lintab[i][1]]);
segbuf[i].x1 = winX+winW*(0.5+0.5*ux1);
segbuf[i].y1 = winY+winH*(0.5+0.5*uy1);
segbuf[i].x2 = winX+winW*(0.5+0.5*ux2);
segbuf[i].y2 = winY+winH*(0.5+0.5*uy2);
}
if (frame_to_write) {
XStoreColors(dpy, cmap, frame_0_colors, 4);
}
else {
XStoreColors(dpy, cmap, frame_1_colors, 4);
}
frame_to_write = 1-frame_to_write;
XFillRectangle(dpy, win, erase_gc, 0, 0, winW, winH);
for (i = 0; i < nlines; i+= 4096) {
int n = nlines-i > 4096 ? 4096 : nlines-i;
XDrawSegments(dpy, win, draw_gc, &segbuf[i], n);
}
}
goto loop;
}
|