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:


additional screen captures:

 

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

::final screen shots:932649147ef032f63b06bafbd22d2554.png 

 

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:

 


 

Download Source