#define WSZ 400
+typedef struct { GC fillgc, linegc; } DrawingMode;
+
static Display *display;
static Pixmap pixmap, doublebuffers[2];
static Window window;
-static GC linegc, fillgc;
+
+static DrawingMode dmred, dmblue, dmwhite;
+static const DrawingMode *dmcurrent;
static int wwidth=WSZ, wheight=WSZ, wmindim=WSZ, wmaxdim=WSZ;
static int ncut, currentbuffer, x11depth, x11screen;
+XVisualInfo visinfo;
-static double scale= 0.3;
-static double eye_z= -10, eye_x= 0;
+static struct { double scale, eyes_apart; } sizeadj= { 0.3, 0.0 };
+static double scale_wmindim;
+static double eye_z= -10, eye_x=0;
static double cut_z= -9;
static void drawtriangle(const Triangle *t) {
if (z < cut_z) { ncut++; return; }
double zezezp= eye_z / (eye_z - z);
- points[i].x= scale * wmindim * (zezezp * (x - eye_x) + eye_x) + wwidth/2;
- points[i].y= scale * wmindim * (zezezp * y ) + wheight/2;
+ points[i].x= scale_wmindim * (zezezp * (x - eye_x) + eye_x) + wwidth/2;
+ points[i].y= scale_wmindim * (zezezp * y ) + wheight/2;
}
points[3]= points[0];
- XA( XFillPolygon(display,pixmap,fillgc, points,3,Convex,CoordModeOrigin) );
- XA( XDrawLines(display,pixmap,linegc,points, 4,CoordModeOrigin) );
+ XA( XFillPolygon(display,pixmap, dmcurrent->fillgc,
+ points,3,Convex,CoordModeOrigin) );
+ XA( XDrawLines(display,pixmap, dmcurrent->linegc,
+ points, 4,CoordModeOrigin) );
}
static const unsigned long core_event_mask=
currentbuffer= 0;
}
-static void display_prepare(void) {
+static void mkgcs(DrawingMode *dm, unsigned long planes) {
XGCValues gcv;
+
+ gcv.function= GXcopy;
+ gcv.foreground= WhitePixel(display,x11screen);
+ gcv.plane_mask= planes;
+ dm->linegc= XCreateGC(display,pixmap,
+ GCFunction|GCForeground|GCPlaneMask,
+ &gcv);
+
+ gcv.function= GXclear;
+ dm->fillgc= XCreateGC(display,pixmap,
+ GCFunction|GCPlaneMask,
+ &gcv);
+}
+
+static void display_prepare(void) {
XSetWindowAttributes wa;
- XVisualInfo vinfo;
XSizeHints hints;
XA( display= XOpenDisplay(0) );
x11screen= DefaultScreen(display);
x11depth= DefaultDepth(display,x11screen);
- XA( XMatchVisualInfo(display,x11screen,x11depth, TrueColor,&vinfo) );
+ XA( XMatchVisualInfo(display,x11screen,x11depth, TrueColor,&visinfo) );
wa.event_mask= core_event_mask;
XA( window= XCreateWindow(display, DefaultRootWindow(display),
0,0, wwidth,wheight, 0,x11depth,
- InputOutput, vinfo.visual,
+ InputOutput, visinfo.visual,
CWEventMask, &wa) );
hints.flags= USPosition;
mkpixmaps();
- gcv.function= GXcopy;
- gcv.plane_mask= ~0UL;
- gcv.foreground= WhitePixel(display,x11screen);
- linegc= XCreateGC(display,pixmap, GCFunction|GCPlaneMask|GCForeground, &gcv);
-
- gcv.function= GXclear;
- gcv.plane_mask= ~0UL;
- fillgc= XCreateGC(display,pixmap, GCFunction|GCPlaneMask, &gcv);
+ mkgcs(&dmwhite, AllPlanes);
+ mkgcs(&dmblue, visinfo.blue_mask);
+ mkgcs(&dmred, visinfo.red_mask);
}
-static void display_conformation(void) {
+static void drawtriangles(const DrawingMode *dm) {
Triangle *const *t;
int i;
-
- pixmap= doublebuffers[currentbuffer];
- XA( XFillRectangle(display,pixmap,fillgc,0,0,wwidth,wheight) );
+
+ dmcurrent= dm;
for (i=0, t=displaylist, ncut=0; i<ntris; i++, t++)
drawtriangle(*t);
- printf("shown, %d/%d triangles cut\n", ncut, ntris);
+}
+
+static void display_conformation(void) {
+ pixmap= doublebuffers[currentbuffer];
+
+ XA( XFillRectangle(display,pixmap,dmwhite.fillgc,0,0,wwidth,wheight) );
+
+ if (sizeadj.eyes_apart > 0) {
+ const double preferred=100, beyond=200;
+
+ eye_x= sizeadj.eyes_apart < preferred ? sizeadj.eyes_apart :
+ sizeadj.eyes_apart < beyond ? preferred :
+ sizeadj.eyes_apart - (beyond - preferred);
+ eye_x /= scale_wmindim;
+ drawtriangles(&dmblue);
+ eye_x= -eye_x;
+ drawtriangles(&dmred);
+ } else {
+ drawtriangles(&dmwhite);
+ printf("shown, %d/%d triangles cut\n", ncut, ntris);
+ }
XA( XSetWindowBackgroundPixmap(display,window,pixmap) );
XA( XClearWindow(display,window) );
}
static void show(void) {
+ scale_wmindim= sizeadj.scale * wmindim;
read_input();
transform_coordinates();
generate_display_list();
}
DRAG_SAVING(rotate, transform);
-static void drag_scale_delta(double dx, double dy) {
- scale *= pow(3.0, dy);
+static void drag_sizeadj_delta(double dx, double dy) {
+ const double min_eyes_apart= -200;
+ sizeadj.scale *= pow(3.0, dy);
+
+ sizeadj.eyes_apart += dx * wmaxdim;
+ if (sizeadj.eyes_apart < min_eyes_apart) sizeadj.eyes_apart= min_eyes_apart;
+ printf("sizeadj eyes_apart %g\n", sizeadj.eyes_apart);
show();
}
-DRAG_SAVING(scale, scale);
+DRAG_SAVING(sizeadj, sizeadj);
static const Drag *drag= &drag_none;
}
switch (e->button) {
case Button1: drag= &drag_rotate; break;
- case Button2: drag= &drag_scale; break;
+ case Button2: drag= &drag_sizeadj; break;
+ case Button3: drag= &drag_3d; break;
default: printf("unknown drag start %d\n", e->button);
}
printf("drag=%s press button=%lu start %d,%d\n",