chiark / gitweb /
before abolish oee_edgemap in favour of something weirder
[moebius2.git] / project.c
index 07d5fa7..266237f 100644 (file)
--- a/project.c
+++ b/project.c
@@ -76,10 +76,14 @@ static void generate_display_list(void) {
 }    
 
 static int dl_compare(const void *tav, const void *tbv) {
+  int i;
   const Triangle *const *tap= tav, *ta= *tap;
   const Triangle *const *tbp= tbp, *tb= *tbp;
-  double za= ta->vertex[0][2];
-  double zb= tb->vertex[0][2];
+  double za=0, zb=0;
+  for (i=0; i<3; i++) {
+    za += ta->vertex[i][2];
+    zb += tb->vertex[i][2];
+  }
   return za > zb ? -1 :
          za < zb ? +1 : 0;
 }
@@ -92,15 +96,20 @@ 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 double sizeadj_scale= 0.3, eyes_apart, scale_wmindim;
+static double eye_z= -10, eye_x=0;
 static double cut_z= -9;
 
 static void drawtriangle(const Triangle *t) {
@@ -116,13 +125,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 +147,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 +185,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 (eyes_apart > 0) {
+    const double preferred=0.05, beyond=0.07;
+
+    eye_x= eyes_apart < preferred ? eyes_apart :
+           eyes_apart < beyond ? preferred :
+           eyes_apart - (beyond - preferred);
+    eye_x /= sizeadj_scale;
+    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 +225,7 @@ static void display_conformation(void) {
 }
 
 static void show(void) {
+  scale_wmindim= sizeadj_scale * wmindim;
   read_input();
   transform_coordinates();
   generate_display_list();
@@ -351,11 +391,20 @@ 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) {
+  sizeadj_scale *= pow(3.0, -dy);
+  show();
+}
+DRAG_SAVING(sizeadj, sizeadj_scale);
+
+static void drag_3d_delta(double dx, double dy) {
+  const double min_eyes_apart= -0.02;
+  eyes_apart += dx * 0.1;
+  if (eyes_apart < min_eyes_apart) eyes_apart= min_eyes_apart;
+  printf("sizeadj eyes_apart %g\n", eyes_apart);
   show();
 }
-DRAG_SAVING(scale, scale);
+DRAG_SAVING(3d, eyes_apart);
 
 static const Drag *drag= &drag_none;
 
@@ -380,7 +429,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",