FINAL PROJECT: Explorations in the Superformula and Hexany using OpenGL

Ryan McGee | MAT 594CM | Spring 2009

THE SUPERFORMULA

updated video: better sounding FM synthesis and audio waveform visualization added: Perhaps attracted by the formula’s name as well as its ability to create highly complex 3D shapes with only a few adjustable parameters, I decided to focus my efforts on visualizing and sonifying the Superformula rather than my initial exploration of Hexany.  Implementing the Superformula in OpenGL exposed me to working with the spherical coordinate system in OpenGL for the first time.  Animating morphing of the resulting shapes from one to another required use of the GLUT timer function.

The Superformula Code Implementation

 void superForm(){  // draw the superformula using sphereical coordinates         if(drawMethod == 1){  // choose drawing mode       glBegin(GL_QUAD_STRIP);     }     else if (drawMethod == 2){       glBegin(GL_LINE_STRIP);     }     else if (drawMethod == 3){       glBegin(GL_TRIANGLE_STRIP);     }     else if (drawMethod == 4){       glBegin(GL_POINTS);     }     else if (drawMethod == 5){       glBegin(GL_POLYGON);     }         float x, y, z;  // cartesian coordinates         for(float thetaDeg = 0; thetaDeg < 360; thetaDeg+=1){ // compute by theta             float theta = (thetaDeg/180.0)*3.1459; // calc. theta in radians             for(float phiDeg = 0; phiDeg < 180; phiDeg+=1){ // compute by phi                         float phi = (phiDeg/180.0)*3.1459;  // calc. phi in radians                         r = 1* (pow((pow((cos(m*phi/4)/a), (n2)) + pow((sin(m*phi/4)/b), (n3))), (-1.0/n1)));  // superformula               x = r * cos(phi)*sin(theta); // convert from spherical to cartesian coordinates             y = r * sin(phi)*sin(theta);             z = r * cos(theta);               glVertex3f(x, y, z);       }     }         glEnd();             }

By modifying m, n1, n2, and n3 one can create several shapes that are all elliptical in their boundary (as the superformula is an extension of the superellipse equation).  Modifying a and b allows one to change the height and width of the “super ellipse”.  I was introduced to the glutTimer function, which I used to animate morphing between various shapes by generating random parameters with the c++ rand function.  The user can change the drawing mode (point, line, triangle, quad, or polygon) at any time. Using a simple FM synthesis equation in the RT Audio callback function, I mapped n1, n2, and n3 to modulation indices for sonify the superformula.  Parameter m was used as a multiplier for the carrier frequency and a and b were used to specify the gain for the left and right channels respectively. The user can also change the root pitch of the sonification at runtime.

Morphing Function

 void morphTimer(int value){         double inc = ((double)value/100);         m = oldM + inc*(newM-oldM);     n1 = oldN1 + inc*(newN1-oldN1);     n2 = oldN2 + inc*(newN2-oldN2);     n3 = oldN3 + inc*(newN3-oldN3);     a = oldA + inc*(newA-oldA);     b = oldB + inc*(newB-oldB);         superR = oldSR + inc*(newSR - oldSR);     superG = oldSG + inc*(newSG - oldSG);     superB = oldSB + inc*(newSB - oldSB);         value++;     if(value <= 100){  // has the timer been called less than 100 times?       glutTimerFunc(5, morphTimer, value); // recall timer function     }     // if timer has been called 100 times then exit }   void morph(int v){       //store old parameter values     oldM = m;     oldN1 = n1;     oldN2 = n2;     oldN3 = n3;     oldA = a;     oldB = b;         //store old color values     oldSR = superR;     oldSG = superG;     oldSB = superB;         //compute new parameter and color values     newM = oldM + (double)(rand()%41);     newN1 = oldN1 + (double)(rand()%41);     newN2= oldN2 + (double)(rand()%41);     newN3= oldN3 + (double)(rand()%41);     newA = oldA + (double)(rand()%6);     newB = oldB + (double)(rand()%6);         newSR = (float)(rand()%2566)/100;;     newSG = (float)(rand()%2566)/100;;     newSB = (float)(rand()%2566)/100;;         glutTimerFunc(5, morphTimer, v);  // call the timer function to start morphing     }

The result is a system of generative visuals and sound all based on the superformula.  By repeatedly calling the morph function the user can create some very cool stuttering visual and audio effects.  Using camera controls to zoom and pan allows one to explore all aspects of each shape.  In, the future the program could be made more aesthetically pleasing by adding texturing to the shapes and using more advanced audio synthesis routines.

Example Output: