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 :
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