X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=hacks%2Fglx%2Fpinion.c;h=7f741e7f644aa6fbd5510c140a90c860720ce2ad;hp=413fc1a94db290f295329a09ae61edfc045cc247;hb=2d04c4f22466851aedb6ed0f2919d148f726b889;hpb=bc7b7a8eb122206d239ec0e693676bcce31be1aa diff --git a/hacks/glx/pinion.c b/hacks/glx/pinion.c index 413fc1a9..7f741e7f 100644 --- a/hacks/glx/pinion.c +++ b/hacks/glx/pinion.c @@ -44,7 +44,9 @@ extern XtAppContext app; #define BELLRAND(n) ((frand((n)) + frand((n)) + frand((n))) / 3) #include "xlockmore.h" +#include "normals.h" #include "gltrackball.h" +#include "glxfonts.h" #include #ifdef USE_GL /* whole file */ @@ -81,6 +83,7 @@ typedef struct { int coax_p; /* whether this is one of a pair of bound gears. 1 for first, 2 for second. */ double coax_thickness; /* thickness of the other gear in the pair */ + enum { SMALL, MEDIUM, LARGE } size; /* Controls complexity of mesh. */ GLfloat color[4]; GLfloat color2[4]; @@ -146,180 +149,20 @@ static argtype vars[] = { ModeSpecOpt sws_opts = {countof(opts), opts, countof(vars), vars, NULL}; - -/* Computing normal vectors - */ - -typedef struct { - double x,y,z; -} XYZ; - -/* Calculate the unit normal at p given two other points p1,p2 on the - surface. The normal points in the direction of p1 crossproduct p2 - */ -static XYZ -calc_normal (XYZ p, XYZ p1, XYZ p2) -{ - XYZ n, pa, pb; - pa.x = p1.x - p.x; - pa.y = p1.y - p.y; - pa.z = p1.z - p.z; - pb.x = p2.x - p.x; - pb.y = p2.y - p.y; - pb.z = p2.z - p.z; - n.x = pa.y * pb.z - pa.z * pb.y; - n.y = pa.z * pb.x - pa.x * pb.z; - n.z = pa.x * pb.y - pa.y * pb.x; - return (n); -} - -static void -do_normal(GLfloat x1, GLfloat y1, GLfloat z1, - GLfloat x2, GLfloat y2, GLfloat z2, - GLfloat x3, GLfloat y3, GLfloat z3) -{ - XYZ p1, p2, p3, p; - p1.x = x1; p1.y = y1; p1.z = z1; - p2.x = x2; p2.y = y2; p2.z = z2; - p3.x = x3; p3.y = y3; p3.z = z3; - p = calc_normal (p1, p2, p3); - glNormal3f (p.x, p.y, p.z); -} - /* Font stuff */ -static void -load_font (ModeInfo *mi, char *res, XFontStruct **fontP, GLuint *dlistP) -{ - const char *font = get_string_resource (res, "Font"); - XFontStruct *f; - Font id; - int first, last; - - if (!font) font = "-*-times-bold-r-normal-*-180-*"; - - f = XLoadQueryFont(mi->dpy, font); - if (!f) f = XLoadQueryFont(mi->dpy, "fixed"); - - id = f->fid; - first = f->min_char_or_byte2; - last = f->max_char_or_byte2; - - clear_gl_error (); - *dlistP = glGenLists ((GLuint) last+1); - check_gl_error ("glGenLists"); - glXUseXFont(id, first, last-first+1, *dlistP + first); - check_gl_error ("glXUseXFont"); - - *fontP = f; -} - - static void load_fonts (ModeInfo *mi) { pinion_configuration *pp = &pps[MI_SCREEN(mi)]; - load_font (mi, "titleFont", &pp->xfont1, &pp->font1_dlist); - load_font (mi, "titleFont2", &pp->xfont2, &pp->font2_dlist); - load_font (mi, "titleFont3", &pp->xfont3, &pp->font3_dlist); + load_font (mi->dpy, "titleFont", &pp->xfont1, &pp->font1_dlist); + load_font (mi->dpy, "titleFont2", &pp->xfont2, &pp->font2_dlist); + load_font (mi->dpy, "titleFont3", &pp->xfont3, &pp->font3_dlist); } -static int -string_width (XFontStruct *f, const char *c) -{ - int w = 0; - while (*c) - { - int cc = *((unsigned char *) c); - w += (f->per_char - ? f->per_char[cc-f->min_char_or_byte2].rbearing - : f->min_bounds.rbearing); - c++; - } - return w; -} - -static void -print_title_string (ModeInfo *mi, const char *string, - GLfloat x, GLfloat y, - XFontStruct *font, int font_dlist) -{ - GLfloat line_height = font->ascent + font->descent; - GLfloat sub_shift = (line_height * 0.3); - int cw = string_width (font, "m"); - int tabs = cw * 7; - - y -= line_height; - - glPushAttrib (GL_TRANSFORM_BIT | /* for matrix contents */ - GL_ENABLE_BIT); /* for various glDisable calls */ - glDisable (GL_LIGHTING); - glDisable (GL_DEPTH_TEST); - { - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - { - glLoadIdentity(); - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - { - int i; - int x2 = x; - Bool sub_p = False; - glLoadIdentity(); - - gluOrtho2D (0, mi->xgwa.width, 0, mi->xgwa.height); - - glColor3f (0.8, 0.8, 0); - - glRasterPos2f (x, y); - for (i = 0; i < strlen(string); i++) - { - char c = string[i]; - if (c == '\n') - { - glRasterPos2f (x, (y -= line_height)); - x2 = x; - } - else if (c == '\t') - { - x2 -= x; - x2 = ((x2 + tabs) / tabs) * tabs; /* tab to tab stop */ - x2 += x; - glRasterPos2f (x2, y); - } - else if (c == '[' && (isdigit (string[i+1]))) - { - sub_p = True; - glRasterPos2f (x2, (y -= sub_shift)); - } - else if (c == ']' && sub_p) - { - sub_p = False; - glRasterPos2f (x2, (y += sub_shift)); - } - else - { - glCallList (font_dlist + (int)(c)); - x2 += (font->per_char - ? font->per_char[c - font->min_char_or_byte2].width - : font->min_bounds.width); - } - } - } - glPopMatrix(); - } - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - } - glPopAttrib(); - - glMatrixMode(GL_MODELVIEW); -} static void rpm_string (double rpm, char *s); @@ -345,6 +188,12 @@ new_label (ModeInfo *mi) { sprintf (label, "%d teeth\n", g->nteeth); rpm_string (g->rpm, label + strlen(label)); + if (debug_p) + sprintf (label + strlen (label), "\nPolys: %d\nModel: %s (%.2f)\n", + g->polygons, + (g->size == SMALL ? "small" : g->size == MEDIUM ? "medium" + : "large"), + g->tooth_h * MI_HEIGHT(mi)); } glNewList (pp->title_list, GL_COMPILE); @@ -359,9 +208,11 @@ new_label (ModeInfo *mi) else f = pp->xfont3, fl = pp->font3_dlist; /* tiny font */ - print_title_string (mi, label, - 10, mi->xgwa.height - 10, - f, fl); + glColor3f (0.8, 0.8, 0); + print_gl_string (mi->dpy, f, fl, + mi->xgwa.width, mi->xgwa.height, + 10, mi->xgwa.height - 10, + label); } glEndList (); } @@ -483,7 +334,6 @@ biggest_ring (gear *g, double *posP, double *sizeP, double *heightP) static gear * new_gear (ModeInfo *mi, gear *parent, Bool coaxial_p) { - /* pinion_configuration *pp = &pps[MI_SCREEN(mi)]; */ gear *g = (gear *) calloc (1, sizeof (*g)); int loop_count = 0; static unsigned long id = 0; @@ -640,6 +490,15 @@ new_gear (ModeInfo *mi, gear *parent, Bool coaxial_p) if (g->inner_r2 > g->inner_r) abort(); if (g->inner_r > g->r) abort(); + /* Decide how complex the polygon model should be. + */ + { + double pix = g->tooth_h * MI_HEIGHT(mi); /* approx. tooth size in pixels */ + if (pix <= 2.5) g->size = SMALL; + else if (pix <= 3.5) g->size = MEDIUM; + else g->size = LARGE; + } + g->base_p = !parent; return g; @@ -1212,6 +1071,7 @@ scroll_gears (ModeInfo *mi) else break; i++; + if (debug_one_gear_p) break; } /* @@ -1250,6 +1110,7 @@ static void ffwd (ModeInfo *mi) { pinion_configuration *pp = &pps[MI_SCREEN(mi)]; + if (debug_one_gear_p) return; while (1) { gear *g = farthest_gear (mi, True); @@ -1358,8 +1219,8 @@ draw_disc (ModeInfo *mi, int segments, if (wire_p || ra != 0) glVertex3f (cth * ra, sth * ra, z); glVertex3f (cth * rb, sth * rb, z); - polys++; } + polys += segments; glEnd(); return polys; } @@ -1489,7 +1350,7 @@ draw_gear_nubs (ModeInfo *mi, gear *g) Bool wire_p = MI_IS_WIREFRAME(mi); int polys = 0; int i; - int steps = 20; + int steps = (g->size != LARGE ? 5 : 20); double r, size, height; GLfloat *cc; int which; @@ -1514,7 +1375,8 @@ draw_gear_nubs (ModeInfo *mi, gear *g) glTranslatef (cos(th) * r, sin(th) * r, 0); if (wire_p && !wire_all_p) - polys += draw_ring (mi, steps/2, size, 0, 0, False); + polys += draw_ring (mi, (g->size == LARGE ? steps/2 : steps), + size, 0, 0, False); else { polys += draw_disc (mi, steps, 0, size, -height, True); @@ -1576,7 +1438,8 @@ draw_gear_interior (ModeInfo *mi, gear *g) int steps = g->nteeth * 2; if (steps < 10) steps = 10; - if (wire_p && !wire_all_p) steps /= 2; + if ((wire_p && !wire_all_p) || g->size != LARGE) steps /= 2; + if (g->size != LARGE && steps > 16) steps = 16; /* ring 1 (facing in) is done in draw_gear_teeth */ @@ -1584,8 +1447,8 @@ draw_gear_interior (ModeInfo *mi, gear *g) */ if (g->inner_r2) { - GLfloat ra = g->inner_r; - GLfloat rb = g->inner_r2; + GLfloat ra = g->inner_r * 1.04; /* slightly larger than inner_r */ + GLfloat rb = g->inner_r2; /* since the points don't line up */ GLfloat za = -g->thickness2/2; GLfloat zb = g->thickness2/2; @@ -1659,10 +1522,10 @@ draw_gear_interior (ModeInfo *mi, gear *g) } -/* Computes the vertices and normals of the teeth of a gear. - This is the heavy lifting: there are a ton of polygons around the - perimiter of a gear, and the normals are difficult (not radial - or right angles.) +/* gear_teeth_geometry computes the vertices and normals of the teeth + of a gear. This is the heavy lifting: there are a ton of polygons + around the perimiter of a gear, and the normals are difficult (not + radial or right angles.) It would be nice if we could cache this, but the numbers are different for essentially every gear: @@ -1679,26 +1542,59 @@ draw_gear_interior (ModeInfo *mi, gear *g) us -- we only compute all these normals once per gear, instead of once per gear per frame. */ + +typedef struct { + int npoints; + XYZ *points; + XYZ *fnormals; /* face normals */ + XYZ *pnormals; /* point normals */ +} tooth_face; + + static void -gear_teeth_geometry (ModeInfo *mi, gear *g, - int *points_per_tooth_ret, - XYZ **points_ret, - XYZ **normals_ret) +tooth_normals (tooth_face *f) { int i; - int ppt = 15; /* points per tooth */ + /* Compute the face normals for each facet. */ + for (i = 0; i < f->npoints; i++) + { + XYZ p1, p2, p3; + int a = i; + int b = (i == f->npoints-1 ? 0 : i+1); + p1 = f->points[a]; + p2 = f->points[b]; + p3 = p1; + p3.z++; + f->fnormals[i] = calc_normal (p1, p2, p3); + } + + /* From the face normals, compute the vertex normals + (by averaging the normals of adjascent faces.) + */ + for (i = 0; i < f->npoints; i++) + { + int a = (i == 0 ? f->npoints-1 : i-1); + int b = i; + XYZ n1 = f->fnormals[a]; /* normal of [i-1 - i] face */ + XYZ n2 = f->fnormals[b]; /* normal of [i - i+1] face */ + f->pnormals[i].x = (n1.x + n2.x) / 2; + f->pnormals[i].y = (n1.y + n2.y) / 2; + f->pnormals[i].z = (n1.z + n2.z) / 2; + } +} - GLfloat width = M_PI * 2 / g->nteeth; +static void +gear_teeth_geometry (ModeInfo *mi, gear *g, + tooth_face *orim, /* outer rim (the teeth) */ + tooth_face *irim) /* inner rim (the hole) */ +{ + int i; + int ppt = 9; /* max points per tooth */ + GLfloat width = M_PI * 2 / g->nteeth; GLfloat rh = g->tooth_h; GLfloat tw = width; - GLfloat fudge = (g->nteeth >= 5 ? 0 : 0.04); /* reshape small ones a bit */ - - XYZ *points = (XYZ *) calloc (ppt * g->nteeth + 1, sizeof(*points)); - XYZ *fnormals = (XYZ *) calloc (ppt * g->nteeth + 1, sizeof(*points)); - XYZ *pnormals = (XYZ *) calloc (ppt * g->nteeth + 1, sizeof(*points)); - int npoints = 0; /* Approximate shape of an "involute" gear tooth. @@ -1725,37 +1621,45 @@ gear_teeth_geometry (ModeInfo *mi, gear *g, r4 ......__:_____________________________:________________ */ - GLfloat R = g->r; - GLfloat r[20]; GLfloat th[20]; + GLfloat R = g->r; r[0] = R + (rh * 0.5); r[1] = R + (rh * 0.25); - r[2] = R - (rh * 0.25); - r[3] = R - (rh * 0.5); + r[2] = R - (r[1]-R); + r[3] = R - (r[0]-R); r[4] = g->inner_r; - th[0] = -tw * 0.45; + th[0] = -tw * (g->size == SMALL ? 0.5 : g->size == MEDIUM ? 0.41 : 0.45); th[1] = -tw * 0.30; - th[2] = -tw *(0.16 - fudge); - th[3] = -tw * 0.04; + th[2] = -tw * (g->nteeth >= 5 ? 0.16 : 0.12); + th[3] = -tw * (g->size == MEDIUM ? 0.1 : 0.04); th[4] = 0; - th[5] = tw * 0.04; - th[6] = tw *(0.16 - fudge); - th[7] = tw * 0.30; - th[8] = tw * 0.45; + th[5] = -th[3]; + th[6] = -th[2]; + th[7] = -th[1]; + th[8] = -th[0]; th[9] = width / 2; th[10]= th[0] + width; - if (!points || !fnormals || !pnormals) + orim->npoints = 0; + orim->points = (XYZ *) calloc(ppt * g->nteeth+1, sizeof(*orim->points)); + orim->fnormals = (XYZ *) calloc(ppt * g->nteeth+1, sizeof(*orim->fnormals)); + orim->pnormals = (XYZ *) calloc(ppt * g->nteeth+1, sizeof(*orim->pnormals)); + + irim->npoints = 0; + irim->points = (XYZ *) calloc(ppt * g->nteeth+1, sizeof(*irim->points)); + irim->fnormals = (XYZ *) calloc(ppt * g->nteeth+1, sizeof(*irim->fnormals)); + irim->pnormals = (XYZ *) calloc(ppt * g->nteeth+1, sizeof(*irim->pnormals)); + + if (!orim->points || !orim->pnormals || !orim->fnormals || + !irim->points || !irim->pnormals || !irim->fnormals) { fprintf (stderr, "%s: out of memory\n", progname); exit (1); } - npoints = 0; - /* First, compute the coordinates of every point used for every tooth. */ for (i = 0; i < g->nteeth; i++) @@ -1763,97 +1667,47 @@ gear_teeth_geometry (ModeInfo *mi, gear *g, GLfloat TH = (i * width) + (width/4); # undef PUSH -# define PUSH(PR,PTH) \ - points[npoints].x = cos(TH+th[(PTH)]) * r[(PR)]; \ - points[npoints].y = sin(TH+th[(PTH)]) * r[(PR)]; \ - npoints++ - - /* start1 = npoints; */ - - PUSH(3, 0); /* tooth left 1 */ - PUSH(2, 1); /* tooth left 2 */ - PUSH(1, 2); /* tooth left 3 */ - PUSH(0, 3); /* tooth top 1 */ - PUSH(0, 5); /* tooth top 2 */ - PUSH(1, 6); /* tooth right 1 */ - PUSH(2, 7); /* tooth right 2 */ - PUSH(3, 8); /* tooth right 3 */ - PUSH(3, 10); /* gap top */ - - /* end1 = npoints; */ - - PUSH(4, 8); /* gap interior */ - - /* start2 = npoints; */ - - PUSH(4, 10); /* tooth interior 1 */ - PUSH(4, 8); /* tooth interior 2 */ - PUSH(4, 4); /* tooth bottom 1 */ - PUSH(4, 0); /* tooth bottom 2 */ - - /* end2 = npoints; */ - - PUSH(3, 4); /* midpoint */ - - /* mid = npoints-1; */ - - if (i == 0 && npoints != ppt) abort(); /* go update "ppt"! */ +# define PUSH(OPR,IPR,PTH) \ + orim->points[orim->npoints].x = cos(TH+th[(PTH)]) * r[(OPR)]; \ + orim->points[orim->npoints].y = sin(TH+th[(PTH)]) * r[(OPR)]; \ + orim->npoints++; \ + irim->points[irim->npoints].x = cos(TH+th[(PTH)]) * r[(IPR)]; \ + irim->points[irim->npoints].y = sin(TH+th[(PTH)]) * r[(IPR)]; \ + irim->npoints++ + + if (g->size == SMALL) + { + PUSH(3, 4, 0); /* tooth left 1 */ + PUSH(0, 4, 4); /* tooth top middle */ + } + else if (g->size == MEDIUM) + { + PUSH(3, 4, 0); /* tooth left 1 */ + PUSH(0, 4, 3); /* tooth top left */ + PUSH(0, 4, 5); /* tooth top right */ + PUSH(3, 4, 8); /* tooth right 3 */ + } + else if (g->size == LARGE) + { + PUSH(3, 4, 0); /* tooth left 1 */ + PUSH(2, 4, 1); /* tooth left 2 */ + PUSH(1, 4, 2); /* tooth left 3 */ + PUSH(0, 4, 3); /* tooth top left */ + PUSH(0, 4, 5); /* tooth top right */ + PUSH(1, 4, 6); /* tooth right 1 */ + PUSH(2, 4, 7); /* tooth right 2 */ + PUSH(3, 4, 8); /* tooth right 3 */ + PUSH(3, 4, 9); /* gap top */ + } + else + abort(); # undef PUSH - } - - /* Now compute the face normals for each facet on the tooth rim. - */ - for (i = 0; i < npoints; i++) - { - XYZ p1, p2, p3; - p1 = points[i]; - p2 = points[i+1]; - p3 = p1; - p3.z++; - fnormals[i] = calc_normal (p1, p2, p3); + if (i == 0 && orim->npoints > ppt) abort(); /* go update "ppt"! */ } - - /* From the face normals, compute the vertex normals (by averaging - the normals of adjascent faces.) - */ - for (i = 0; i < npoints; i++) - { - int a = (i == 0 ? npoints-1 : i-1); - int b = i; - - /* Kludge to fix the normal on the last top point: since the - faces go all the way around, this normal pointed clockwise - instead of radially out. */ - int start1 = (i / ppt) * ppt; - int end1 = start1 + 9; - XYZ n1, n2; - - if (b == end1-1) - b = (start1 + ppt == npoints ? 0 : start1 + ppt); - - n1 = fnormals[a]; /* normal of [i-1 - i] face */ - n2 = fnormals[b]; /* normal of [i - i+1] face */ - pnormals[i].x = (n1.x + n2.x) / 2; - pnormals[i].y = (n1.y + n2.y) / 2; - pnormals[i].z = (n1.z + n2.z) / 2; - } - - free (fnormals); - - if (points_ret) - *points_ret = points; - else - free (points); - - if (normals_ret) - *normals_ret = pnormals; - else - free (pnormals); - - if (points_per_tooth_ret) - *points_per_tooth_ret = ppt; + tooth_normals (orim); + tooth_normals (irim); } @@ -1863,147 +1717,171 @@ static int draw_gear_teeth (ModeInfo *mi, gear *g) { Bool wire_p = MI_IS_WIREFRAME(mi); + Bool show_normals_p = False; int polys = 0; int i; GLfloat z1 = -g->thickness/2; GLfloat z2 = g->thickness/2; - int ppt; - XYZ *points, *pnormals; - - gear_teeth_geometry (mi, g, &ppt, &points, &pnormals); + tooth_face orim, irim; + gear_teeth_geometry (mi, g, &orim, &irim); glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, g->color); - for (i = 0; i < g->nteeth; i++) + /* Draw the outer rim (the teeth) + (In wire mode, this draws just the upright lines.) + */ + glFrontFace (GL_CW); + glBegin (wire_p ? GL_LINES : GL_QUAD_STRIP); + for (i = 0; i < orim.npoints; i++) { - int j; - GLfloat z; + glNormal3f (orim.pnormals[i].x, orim.pnormals[i].y, orim.pnormals[i].z); + glVertex3f (orim.points[i].x, orim.points[i].y, z1); + glVertex3f (orim.points[i].x, orim.points[i].y, z2); - int start1 = i * ppt; - int end1 = start1 + 9; - int start2 = end1 + 1; - int end2 = start2 + 4; - int mid = end2; + /* Show the face normal vectors */ + if (wire_p && show_normals_p) + { + XYZ n = orim.fnormals[i]; + int a = i; + int b = (i == orim.npoints-1 ? 0 : i+1); + GLfloat x = (orim.points[a].x + orim.points[b].x) / 2; + GLfloat y = (orim.points[a].y + orim.points[b].y) / 2; + GLfloat z = (z1 + z2) / 2; + glVertex3f (x, y, z); + glVertex3f (x + n.x, y + n.y, z); + } - /* Outside rim of the tooth - */ - glFrontFace (GL_CW); - glBegin (wire_p ? GL_LINES : GL_QUAD_STRIP); - for (j = start1; j < end1; j++) + /* Show the vertex normal vectors */ + if (wire_p && show_normals_p) { - glNormal3f (pnormals[j].x, pnormals[j].y, pnormals[j].z); - glVertex3f (points[j].x, points[j].y, z1); - glVertex3f (points[j].x, points[j].y, z2); - polys++; + XYZ n = orim.pnormals[i]; + GLfloat x = orim.points[i].x; + GLfloat y = orim.points[i].y; + GLfloat z = (z1 + z2) / 2; + glVertex3f (x, y, z); + glVertex3f (x + n.x, y + n.y, z); + } + } -# if 0 - /* Show the face normal vectors */ - if (wire_p) - { - XYZ n = fnormals[j]; - GLfloat x = (points[j].x + points[j+1].x) / 2; - GLfloat y = (points[j].y + points[j+1].y) / 2; - GLfloat z = (z1 + z2) / 2; - glVertex3f (x, y, z); - glVertex3f (x + n.x, y + n.y, z); - } + if (!wire_p) /* close the quad loop */ + { + glNormal3f (orim.pnormals[0].x, orim.pnormals[0].y, orim.pnormals[0].z); + glVertex3f (orim.points[0].x, orim.points[0].y, z1); + glVertex3f (orim.points[0].x, orim.points[0].y, z2); + } + polys += orim.npoints; + glEnd(); - /* Show the vertex normal vectors */ - if (wire_p) - { - XYZ n = pnormals[j]; - GLfloat x = points[j].x; - GLfloat y = points[j].y; - GLfloat z = (z1 + z2) / 2; - glVertex3f (x, y, z); - glVertex3f (x + n.x, y + n.y, z); - } -# endif /* 0 */ - } + /* Draw the outer rim circles, in wire mode */ + if (wire_p) + { + glBegin (GL_LINE_LOOP); + for (i = 0; i < orim.npoints; i++) + glVertex3f (orim.points[i].x, orim.points[i].y, z1); glEnd(); + glBegin (GL_LINE_LOOP); + for (i = 0; i < orim.npoints; i++) + glVertex3f (orim.points[i].x, orim.points[i].y, z2); + glEnd(); + } - /* Some more lines for the outside rim of the tooth... - */ - if (wire_p) + + /* Draw the inner rim (the hole) + (In wire mode, this draws just the upright lines.) + */ + glFrontFace (GL_CCW); + glBegin (wire_p ? GL_LINES : GL_QUAD_STRIP); + for (i = 0; i < irim.npoints; i++) + { + glNormal3f(-irim.pnormals[i].x, -irim.pnormals[i].y,-irim.pnormals[i].z); + glVertex3f (irim.points[i].x, irim.points[i].y, z1); + glVertex3f (irim.points[i].x, irim.points[i].y, z2); + + /* Show the face normal vectors */ + if (wire_p && show_normals_p) { - glBegin (GL_LINE_STRIP); - for (j = start1; j < end1; j++) - glVertex3f (points[j].x, points[j].y, z1); - glEnd(); - glBegin (GL_LINE_STRIP); - for (j = start1; j < end1; j++) - glVertex3f (points[j].x, points[j].y, z2); - glEnd(); + XYZ n = irim.fnormals[i]; + int a = i; + int b = (i == irim.npoints-1 ? 0 : i+1); + GLfloat x = (irim.points[a].x + irim.points[b].x) / 2; + GLfloat y = (irim.points[a].y + irim.points[b].y) / 2; + GLfloat z = (z1 + z2) / 2; + glVertex3f (x, y, z); + glVertex3f (x - n.x, y - n.y, z); } - /* Inside rim behind the tooth - */ - glFrontFace (GL_CW); - glBegin (wire_p ? GL_LINES : GL_QUAD_STRIP); - for (j = start2; j < end2; j++) + /* Show the vertex normal vectors */ + if (wire_p && show_normals_p) { - glNormal3f (-points[j].x, -points[j].y, 0); - glVertex3f ( points[j].x, points[j].y, z1); - glVertex3f ( points[j].x, points[j].y, z2); - polys++; + XYZ n = irim.pnormals[i]; + GLfloat x = irim.points[i].x; + GLfloat y = irim.points[i].y; + GLfloat z = (z1 + z2) / 2; + glVertex3f (x, y, z); + glVertex3f (x - n.x, y - n.y, z); } + } + + if (!wire_p) /* close the quad loop */ + { + glNormal3f (-irim.pnormals[0].x,-irim.pnormals[0].y,-irim.pnormals[0].z); + glVertex3f (irim.points[0].x, irim.points[0].y, z1); + glVertex3f (irim.points[0].x, irim.points[0].y, z2); + } + polys += irim.npoints; + glEnd(); + + /* Draw the inner rim circles, in wire mode + */ + if (wire_p) + { + glBegin (GL_LINE_LOOP); + for (i = 0; i < irim.npoints; i++) + glVertex3f (irim.points[i].x, irim.points[i].y, z1); + glEnd(); + glBegin (GL_LINE_LOOP); + for (i = 0; i < irim.npoints; i++) + glVertex3f (irim.points[i].x, irim.points[i].y, z2); glEnd(); + } - /* Some more lines for the inside rim... - */ - if (wire_p) + + /* Draw the side (the flat bit) + */ + if (!wire_p || wire_all_p) + { + GLfloat z; + if (irim.npoints != orim.npoints) abort(); + for (z = z1; z <= z2; z += z2-z1) { - glBegin (GL_LINE_STRIP); - for (j = start2; j < end2; j++) - glVertex3f (points[j].x, points[j].y, z1); - glEnd(); - glBegin (GL_LINE_STRIP); - for (j = start2; j < end2; j++) - glVertex3f (points[j].x, points[j].y, z2); + glFrontFace (z == z1 ? GL_CCW : GL_CW); + glNormal3f (0, 0, z); + glBegin (wire_p ? GL_LINES : GL_QUAD_STRIP); + for (i = 0; i < orim.npoints; i++) + { + glVertex3f (orim.points[i].x, orim.points[i].y, z); + glVertex3f (irim.points[i].x, irim.points[i].y, z); + } + if (!wire_p) /* close the quad loop */ + { + glVertex3f (orim.points[0].x, orim.points[0].y, z); + glVertex3f (irim.points[0].x, irim.points[0].y, z); + } + polys += orim.npoints; glEnd(); } + } - /* All top and bottom facets. We can skip all of these in wire mode. - */ - if (!wire_p || wire_all_p) - for (z = z1; z <= z2; z += z2-z1) - { - /* Flat edge of the tooth - */ - glFrontFace (z == z1 ? GL_CW : GL_CCW); - glBegin (wire_p ? GL_LINES : GL_TRIANGLE_FAN); - glNormal3f (0, 0, z); - for (j = start1; j < end2; j++) - { - if (j == end1-1 || j == end1 || j == start2) - continue; /* kludge... skip these... */ + free (irim.points); + free (irim.fnormals); + free (irim.pnormals); - if (wire_p || j == start1) - glVertex3f (points[mid].x, points[mid].y, z); - glVertex3f (points[j].x, points[j].y, z); - polys++; - } - glVertex3f (points[start1].x, points[start1].y, z); - glEnd(); - - /* Flat edge between teeth - */ - glFrontFace (z == z1 ? GL_CW : GL_CCW); - glBegin (wire_p ? GL_LINES : GL_QUADS); - glNormal3f (0, 0, z); - glVertex3f (points[end1-1 ].x, points[end1-1 ].y, z); - glVertex3f (points[start2 ].x, points[start2 ].y, z); - glVertex3f (points[start2+1].x, points[start2+1].y, z); - glVertex3f (points[end1-2 ].x, points[end1-2 ].y, z); - polys++; - glEnd(); - } - } + free (orim.points); + free (orim.fnormals); + free (orim.pnormals); - free (points); - free (pnormals); return polys; } @@ -2279,7 +2157,7 @@ pinion_handle_event (ModeInfo *mi, XEvent *event) pinion_configuration *pp = &pps[MI_SCREEN(mi)]; if (event->xany.type == ButtonPress && - event->xbutton.button & Button1) + event->xbutton.button == Button1) { pp->button_down_p = True; gltrackball_start (pp->trackball, @@ -2288,11 +2166,19 @@ pinion_handle_event (ModeInfo *mi, XEvent *event) return True; } else if (event->xany.type == ButtonRelease && - event->xbutton.button & Button1) + event->xbutton.button == Button1) { pp->button_down_p = False; return True; } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5)) + { + gltrackball_mousewheel (pp->trackball, event->xbutton.button, 5, + !!event->xbutton.state); + return True; + } else if (event->xany.type == MotionNotify && pp->button_down_p) {