+void randomize_parameters(jigglystruct *js) {
+ do_tetrahedron = random() & 1;
+ js->do_wireframe = !(random() & 3);
+ js->color_style = random() % 5;
+ if(js->color_style == COLOR_STYLE_NORMAL
+ || js->color_style == COLOR_STYLE_CYCLE) {
+ js->jiggly_color[0] = ((float)random()) / REAL_RAND_MAX * 0.5 + 0.5;
+ js->jiggly_color[1] = ((float)random()) / REAL_RAND_MAX * 0.5 + 0.5;
+ js->jiggly_color[2] = ((float)random()) / REAL_RAND_MAX * 0.5 + 0.5;
+ js->jiggly_color[3] = 1.0f;
+ if(js->color_style == COLOR_STYLE_CYCLE) {
+ js->color_dir[0] = ((float)random()) / REAL_RAND_MAX / 100.0;
+ js->color_dir[1] = ((float)random()) / REAL_RAND_MAX / 100.0;
+ js->color_dir[2] = ((float)random()) / REAL_RAND_MAX / 100.0;
+ }
+ }
+ if((js->color_style != COLOR_STYLE_CHROME) && (random() & 1))
+ js->spooky = (random() % 6) + 4;
+ else
+ js->spooky = 0;
+ js->shininess = random() % 200;
+ speed = (random() % 700) + 50;
+ /* It' kind of dull if this is too high when it starts as a sphere */
+ spherism = do_tetrahedron ? (random() % 500) + 20 : (random() % 100) + 10;
+ hold = (random() % 800) + 100;
+ distance = (random() % 500) + 100;
+ damping = (random() % 800) + 50;
+}
+
+void calculate_parameters(jigglystruct *js, int subdivs) {
+ /* try to compensate for the inherent instability at
+ * low complexity. */
+ float dist_factor = (subdivs == 6) ? 2 : (subdivs == 5) ? 1 : 0.5;
+
+ js->stable_distance = ((float)distance / 500.0)
+ * (STABLE_DISTANCE / dist_factor);
+ js->hold_strength = (float)hold / 10000.0;
+ js->spherify_strength = (float)spherism / 10000.0;
+ js->damping_velocity = (float)damping / 100000.0;
+ js->damping_factor =
+ 0.001/max(js->hold_strength, js->spherify_strength);
+
+ js->speed = (float)speed / 1000.0;
+}
+
+/* The screenhack related functions begin here */
+
+Bool jigglypuff_handle_event(ModeInfo *mi, XEvent *event)
+{
+ jigglystruct *js = &jss[MI_SCREEN(mi)];
+
+ if(event->xany.type == ButtonPress &&
+ event->xbutton.button & Button1) {
+ js->button_down = 1;
+ gltrackball_start(js->trackball, event->xbutton.x, event->xbutton.y,
+ MI_WIDTH(mi), MI_HEIGHT(mi));
+ return True;
+ }
+ else if(event->xany.type == ButtonRelease &&
+ event->xbutton.button & Button1) {
+ js->button_down = 0;
+ return True;
+ }
+ else if(event->xany.type == MotionNotify && js->button_down) {
+ gltrackball_track(js->trackball, event->xmotion.x, event->xmotion.y,
+ MI_WIDTH(mi), MI_HEIGHT(mi));
+ return True;
+ }
+ return False;
+}
+
+void reshape_jigglypuff(ModeInfo *mi, int width, int height)
+{
+ GLfloat aspect = (GLfloat)width / (GLfloat)height;
+
+ glViewport(0, 0, width, height);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glFrustum(-0.5*aspect, 0.5*aspect, -0.5, 0.5, 1, 20);
+/* glTranslatef(0, 0, -10);*/
+}
+
+void draw_jigglypuff(ModeInfo *mi)
+{
+ jigglystruct *js = &jss[MI_SCREEN(mi)];
+
+ glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(js->glx_context));
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glTranslatef(0,0,-10);