chiark / gitweb /
3d works
authorIan Jackson <ian@davenant.relativity.greenend.org.uk>
Mon, 31 Dec 2007 01:35:59 +0000 (01:35 +0000)
committerIan Jackson <ian@davenant.relativity.greenend.org.uk>
Mon, 31 Dec 2007 01:35:59 +0000 (01:35 +0000)
project.c

index 07d5fa737bc7ba541cafc8b6e7ffc06c12a83894..0fac49952884540bf71a0c4b6a05b1546552db82 100644 (file)
--- a/project.c
+++ b/project.c
@@ -92,15 +92,21 @@ static void sort_display_list(void) {
 
 #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) {
@@ -116,13 +122,15 @@ 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=
@@ -136,21 +144,35 @@ static void mkpixmaps(void) {
   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;
@@ -160,25 +182,39 @@ static void display_prepare(void) {
 
   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) );
@@ -186,6 +222,7 @@ static void display_conformation(void) {
 }
 
 static void show(void) {
+  scale_wmindim= sizeadj.scale * wmindim;
   read_input();
   transform_coordinates();
   generate_display_list();
@@ -351,11 +388,16 @@ static void drag_rotate_delta(double dx, double dy) {
 }
 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;
 
@@ -380,7 +422,8 @@ static void event_button(XButtonEvent *e) {
     }
     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",