Sunday 10 May 2015

OpenGL : Making cool SpiroGraph visualization



Spirograph is a geometric drawing toy that produces mathematical roulette curves of the variety technically known as hypotrochoidsand epitrochoids.

Here are some snippets how the completed code executes :


 













How to proceed ?
Its simple beacuse spirographs actually do have mathematical equations for their locus on the graph. So the code almost get simplified to two equations for x and y coordinates and can be plotted easily using OpenGL.

Prerequisites : 
An IDE for developing and running OpenGL code.

Equations :
Here x and y are the coordinates of the locus of the spirograph. You can find more infromation about these equations on Wikipedia.

Next Steps :

Now after getting the equations we just have to randomize the variables so that we can get a visualization effect.

Code in OpenGL (C++)  :

#include<stdlib.h>

#include<math.h>

#include<GL/glut.h>



int speed = 1;

static GLfloat theta = 0.0, theta2 = 0.0;

int axis = 1;

float translate_x = 0, translate_y = 0;

float Rg = 1.0, rg = 0.7, rhog = 0.3 , speed2 = 0.1;

float trig = 0.001;

float r_C=1.0f, g_C=1.0f, b_C=1.0f;

void DrawSpiro(float R, float r, float rho)

{

 float t = 0.0;

 float x = 0.0f, y = 0.0f , x1 = 0.0f, y1 = 0.0f;

 int count = 100;

 glBegin(GL_LINES);



 r_C = (rand() % 100 + 10)*0.01;

 g_C = (rand() % 100 + 10)*0.01;

 b_C = (rand() % 100 + 10)*0.01;

 x1 = (R - r)*cos(t) + rho*cos(((R - r) / r)*t);

 y1 = (R - r)*sin(t) + rho*sin(((R - r) / r)*t);

 for (int i = 0; i < 1000; i++)

 {

  /*if (count == 0)

  {

   r_C = (rand() % 100 + 10)*0.01;

   g_C = (rand() % 100 + 10)*0.01;

   b_C = (rand() % 100 + 10)*0.01;

  }*/

  t = i*speed2;

  x = (R - r)*cos(t) + rho*cos(((R - r) / r)*t);

  y = (R - r)*sin(t) + rho*sin(((R - r) / r)*t);

  //count++;

  glColor3f(r_C, g_C, b_C);

  glVertex2f(x1, y1);

  glVertex2f(x , y);

  x1 = x;

  y1 = y;

 }



 glEnd();

}





void display(void)

{

 // display callback , clear frame buffer an Z buffer ,rotate cube and draw , swap buffer.

 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

 glLoadIdentity();

 glRotatef(theta, 0.0, 0.0, 1.0);

 DrawSpiro(Rg, rg, rhog);

 glutSwapBuffers();

}

void spinCube()

{

 // idle callback,spin cube 2 degreees about selected axis

 

 theta += (0.001*speed);

 theta2 += 0.002*speed;

 if (theta>360.0)

  theta -= 360.0;



 if (theta2>360.0)

  theta2 -= 360.0;



 if (axis == 1)

 {

  if (Rg <= -2.0)

  {

   trig = 0.0001;

  }

  if (Rg >= 2.0)

  {

   trig = -0.0001;

  }

  Rg += trig;

 }

 else if (axis == 2)

 {

  if (rg <= -2.0)

  {

   trig = 0.0001;

  }

  if (rg >= 2.0)

  {

   trig = -0.0001;

  }

  rg += trig;



 }

 else

 {

  if (rhog <= -2.0)

  {

   trig = 0.01;

  }

  if (rhog >= 2.0)

  {

   trig = -0.01;

  }

  rhog += trig;



 }

 glutPostRedisplay();

}

void mouse(int btn, int state, int x, int y)

{

 //mouse calback ,select an axis about which to rotate

 if (btn == GLUT_LEFT_BUTTON && state == GLUT_DOWN) axis = 0;

 if (btn == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN) axis = 1;

 if (btn == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) axis = 2;



}





void processKeys(unsigned char key, int x, int y) {



 switch (key)

 {

 case 'w': speed += 1; break;

 case 's': speed -= 1; break;

 case 'c': axis = 1; break;

 case 'v': axis = 2; break;

 case 'b': axis = 3; break;

 }

}





void myReshape(int w, int h)

{

 glViewport(0, 0, w, h);

 glMatrixMode(GL_PROJECTION);

 glLoadIdentity();

 glOrtho(-2.0, 2.0, -2.0, 2.0, -10.0, 10.0);

 glMatrixMode(GL_MODELVIEW);

}

int main(int argc, char** argv)

{

 glutInit(&argc, argv);

 //need both double buffering and Zbuffer

 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);

 glutInitWindowSize(800, 800);

 glutCreateWindow("Rotating a color cube ");

 glutReshapeFunc(myReshape);

 glutDisplayFunc(display);

 glutIdleFunc(spinCube);

 glutMouseFunc(mouse);

 glutKeyboardFunc(processKeys);

 glEnable(GL_DEPTH_TEST);  //Enable hidden surface removal

 glutMainLoop();

 return 0;

}


For this program Keys W and S are responsible for increasing and decreasing the speed and keys C, V and B are responsible for changing parameters R , r and rho of the program


No comments:

Post a Comment