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