X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=moebius2.git;a=blobdiff_plain;f=project.c;h=266237f90b222be270b723c5845007ff85330e36;hp=07d5fa737bc7ba541cafc8b6e7ffc06c12a83894;hb=456ce271eea85ff5acfe6a4416fa6c085d998c64;hpb=bb0e48bffe4373fabc17a954bbae651bf41def2d diff --git a/project.c b/project.c index 07d5fa7..266237f 100644 --- 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 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",