+/* Set normal vector in xz plane, based on rotation around center. */
+static void setNormalV(glhcfg *glhanoi, GLfloat theta, int y1, int y2, int r1) {
+ if (y1 == y2) /* up/down */
+ glNormal3f(0.0, y1 ? 1.0 : -1.0, 0.0);
+ else if (!r1) /* inward */
+ glNormal3f(-cos(theta), 0.0, -sin(theta));
+ else /* outward */
+ glNormal3f(cos(theta), 0.0, sin(theta));
+}
+
+/* y1, r1, y2, r2 are indices into y, r, beg, end */
+static int drawBaseStrip(glhcfg *glhanoi, int y1, int r1, int y2, int r2,
+ GLfloat y[2], GLfloat r[2], GLfloat beg[2][2], GLfloat end[2][2]) {
+ int i;
+ GLfloat theta, costh, sinth, x[2], z[2];
+ GLfloat theta1 = (M_PI * 2) / (glhanoi->numberOfPoles + 1);
+
+ glBegin(GL_QUAD_STRIP);
+
+ /* beginning edge */
+ glVertex3f(beg[r1][0], y[y1], beg[r1][1]);
+ glVertex3f(beg[r2][0], y[y2], beg[r2][1]);
+ setNormalV(glhanoi, theta1, y1, y2, r1);
+
+ for (i = 1; i < glhanoi->numberOfPoles; i++) {
+ theta = theta1 * (i + 0.5);
+ costh = cos(theta);
+ sinth = sin(theta);
+ x[0] = costh * r[0];
+ x[1] = costh * r[1];
+ z[0] = sinth * r[0];
+ z[1] = sinth * r[1];
+
+ glVertex3f(x[r1], y[y1], z[r1]);
+ glVertex3f(x[r2], y[y2], z[r2]);
+
+ setNormalV(glhanoi, theta1 * (i + 1), y1, y2, r1);
+ }
+
+ /* end edge */
+ glVertex3f(end[r1][0], y[y1], end[r1][1]);
+ glVertex3f(end[r2][0], y[y2], end[r2][1]);
+ setNormalV(glhanoi, glhanoi->numberOfPoles, y1, y2, r1);
+
+ glEnd();
+ return glhanoi->numberOfPoles;
+}
+
+/* Draw base such that poles are distributed around a regular polygon. */
+static int drawRoundBase(glhcfg *glhanoi) {
+ int polys = 0;
+ GLfloat theta, sinth, costh;
+
+ /*
+ r[0] = (minimum) inner radius of base at vertices
+ r[1] = (minimum) outer radius of base at vertices
+ y[0] = bottom of base
+ y[1] = top of base */
+ GLfloat r[2], y[2];
+ /* positions of end points: beginning, end.
+ beg[0] is inner corner of beginning of base, beg[1] is outer corner.
+ beg[i][0] is x, [i][1] is z. */
+ GLfloat beg[2][2], end[2][2], begNorm, endNorm;
+ /* ratio of radius at base vertices to ratio at poles */
+ GLfloat longer = 1.0 / cos(M_PI / (glhanoi->numberOfPoles + 1));
+
+ r[0] = (glhanoi->poleDist - glhanoi->maxDiskRadius) * longer;
+ r[1] = (glhanoi->poleDist + glhanoi->maxDiskRadius) * longer;
+ y[0] = 0;
+ y[1] = glhanoi->baseHeight;
+
+ /* compute beg, end. Make the ends square. */
+ theta = M_PI * 2 / (glhanoi->numberOfPoles + 1);
+
+ costh = cos(theta);
+ sinth = sin(theta);
+ beg[0][0] = (glhanoi->poleDist - glhanoi->maxDiskRadius) * costh +
+ glhanoi->maxDiskRadius * sinth;
+ beg[1][0] = (glhanoi->poleDist + glhanoi->maxDiskRadius) * costh +
+ glhanoi->maxDiskRadius * sinth;
+ beg[0][1] = (glhanoi->poleDist - glhanoi->maxDiskRadius) * sinth -
+ glhanoi->maxDiskRadius * costh;
+ beg[1][1] = (glhanoi->poleDist + glhanoi->maxDiskRadius) * sinth -
+ glhanoi->maxDiskRadius * costh;
+ begNorm = theta - M_PI * 0.5;
+
+ theta = M_PI * 2 * glhanoi->numberOfPoles / (glhanoi->numberOfPoles + 1);
+
+ costh = cos(theta);
+ sinth = sin(theta);
+ end[0][0] = (glhanoi->poleDist - glhanoi->maxDiskRadius) * costh -
+ glhanoi->maxDiskRadius * sinth;
+ end[1][0] = (glhanoi->poleDist + glhanoi->maxDiskRadius) * costh -
+ glhanoi->maxDiskRadius * sinth;
+ end[0][1] = (glhanoi->poleDist - glhanoi->maxDiskRadius) * sinth +
+ glhanoi->maxDiskRadius * costh;
+ end[1][1] = (glhanoi->poleDist + glhanoi->maxDiskRadius) * sinth +
+ glhanoi->maxDiskRadius * costh;
+ endNorm = theta + M_PI * 0.5;
+
+ /* bottom: never seen
+ polys = drawBaseStrip(glhanoi, 0, 0, 0, 1, y, r, beg, end); */
+ /* outside edge */
+ polys += drawBaseStrip(glhanoi, 0, 1, 1, 1, y, r, beg, end);
+ /* top */
+ polys += drawBaseStrip(glhanoi, 1, 1, 1, 0, y, r, beg, end);
+ /* inside edge */
+ polys += drawBaseStrip(glhanoi, 1, 0, 0, 0, y, r, beg, end);
+
+ /* Draw ends */
+ glBegin(GL_QUADS);
+
+ glVertex3f(beg[0][0], y[1], beg[0][1]);
+ glVertex3f(beg[1][0], y[1], beg[1][1]);
+ glVertex3f(beg[1][0], y[0], beg[1][1]);
+ glVertex3f(beg[0][0], y[0], beg[0][1]);
+ glNormal3f(cos(begNorm), 0, sin(begNorm));
+
+ glVertex3f(end[0][0], y[0], end[0][1]);
+ glVertex3f(end[1][0], y[0], end[1][1]);
+ glVertex3f(end[1][0], y[1], end[1][1]);
+ glVertex3f(end[0][0], y[1], end[0][1]);
+ glNormal3f(cos(endNorm), 0, sin(endNorm));
+
+ polys += 2;
+
+ glEnd();
+
+ return polys;
+}
+
+static int drawDisks(glhcfg *glhanoi)