+
+
+ gp->gear_outer = glGenLists(1);
+ glNewList(gp->gear_outer, GL_COMPILE);
+ if (wire) {
+ if (mono)
+ glColor4fv(white);
+ else
+ glColor4fv(blue);
+ } else {
+ if (mono)
+ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, gray);
+ else
+ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
+ }
+ gear(5.7, 7.0, 2.0, 36, 0.7, wire, True);
+
+ /* put some nubs on the outer ring, so we can tell how it's moving */
+ glPushMatrix();
+ glTranslatef(7.0, 0, 0);
+ glRotatef(90, 0, 1, 0);
+
+ ctube(0.5, 0.5, wire); /* nub 1 */
+ glPopMatrix();
+
+ glPushMatrix();
+ glRotatef(120, 0, 0, 1);
+ glTranslatef(7.0, 0, 0);
+ glRotatef(90, 0, 1, 0);
+ ctube(0.5, 0.5, wire); /* nub 2 */
+ glPopMatrix();
+
+ glPushMatrix();
+ glRotatef(240, 0, 0, 1);
+ glTranslatef(7.0, 0, 0);
+ glRotatef(90, 0, 1, 0);
+ ctube(0.5, 0.5, wire); /* nub 3 */
+ glPopMatrix();
+
+
+ glEndList();
+ if (!wire)
+ glEnable(GL_NORMALIZE);
+
+ gp->armature = glGenLists(1);
+ glNewList(gp->armature, GL_COMPILE);
+ if (wire) {
+ if (mono)
+ glColor4fv(white);
+ else
+ glColor4fv(blue);
+ } else {
+ if (mono)
+ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, gray);
+ else
+ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, gray);
+ }
+
+ glTranslatef(0, 0, 1.5);
+ ctube(0.5, 10, wire); /* center axle */
+
+ glPushMatrix();
+ glTranslatef(0.0, 4.2, -1);
+ ctube(0.5, 3, wire); /* axle 1 */
+ glTranslatef(0, 0, 1.8);
+ ctube(0.7, 0.7, wire);
+ glPopMatrix();
+
+ glPushMatrix();
+ glRotatef(120, 0.0, 0.0, 1.0);
+ glTranslatef(0.0, 4.2, -1);
+ ctube(0.5, 3, wire); /* axle 2 */
+ glTranslatef(0, 0, 1.8);
+ ctube(0.7, 0.7, wire);
+ glPopMatrix();
+
+ glPushMatrix();
+ glRotatef(240, 0.0, 0.0, 1.0);
+ glTranslatef(0.0, 4.2, -1);
+ ctube(0.5, 3, wire); /* axle 3 */
+ glTranslatef(0, 0, 1.8);
+ ctube(0.7, 0.7, wire);
+ glPopMatrix();
+
+ glTranslatef(0, 0, 1.5); /* center disk */
+ ctube(1.5, 2, wire);
+
+ glPushMatrix();
+ glRotatef(270, 0, 0, 1);
+ glRotatef(-10, 0, 1, 0);
+ glTranslatef(-2.2, 0, 0);
+ arm(4.0, 1.0, 0.5, 2.0, 1.0, wire); /* arm 1 */
+ glPopMatrix();
+
+ glPushMatrix();
+ glRotatef(30, 0, 0, 1);
+ glRotatef(-10, 0, 1, 0);
+ glTranslatef(-2.2, 0, 0);
+ arm(4.0, 1.0, 0.5, 2.0, 1.0, wire); /* arm 2 */
+ glPopMatrix();
+
+ glPushMatrix();
+ glRotatef(150, 0, 0, 1);
+ glRotatef(-10, 0, 1, 0);
+ glTranslatef(-2.2, 0, 0);
+ arm(4.0, 1.0, 0.5, 2.0, 1.0, wire); /* arm 3 */
+ glPopMatrix();
+
+ glEndList();
+ if (!wire)
+ glEnable(GL_NORMALIZE);
+ }
+}
+
+
+/* lifted from lament.c */
+#define RAND(n) ((long) ((random() & 0x7fffffff) % ((long) (n))))
+#define RANDSIGN() ((random() & 1) ? 1 : -1)
+
+static void
+rotate(GLfloat *pos, GLfloat *v, GLfloat *dv, GLfloat max_v)
+{
+ double ppos = *pos;
+
+ /* tick position */
+ if (ppos < 0)
+ ppos = -(ppos + *v);
+ else
+ ppos += *v;
+
+ if (ppos > 1.0)
+ ppos -= 1.0;
+ else if (ppos < 0)
+ ppos += 1.0;
+
+ if (ppos < 0) abort();
+ if (ppos > 1.0) abort();
+ *pos = (*pos > 0 ? ppos : -ppos);
+
+ /* accelerate */
+ *v += *dv;
+
+ /* clamp velocity */
+ if (*v > max_v || *v < -max_v)
+ {
+ *dv = -*dv;
+ }
+ /* If it stops, start it going in the other direction. */
+ else if (*v < 0)
+ {
+ if (random() % 4)
+ {
+ *v = 0;
+
+ /* keep going in the same direction */
+ if (random() % 2)
+ *dv = 0;
+ else if (*dv < 0)
+ *dv = -*dv;
+ }
+ else
+ {
+ /* reverse gears */
+ *v = -*v;
+ *dv = -*dv;
+ *pos = -*pos;
+ }
+ }
+
+ /* Alter direction of rotational acceleration randomly. */
+ if (! (random() % 120))
+ *dv = -*dv;
+
+ /* Change acceleration very occasionally. */
+ if (! (random() % 200))
+ {
+ if (*dv == 0)
+ *dv = 0.00001;
+ else if (random() & 1)
+ *dv *= 1.2;
+ else
+ *dv *= 0.8;
+ }