In this introduction we’re looking at the basics of OpenGL and how transformations are working in practice. In OpenGL, a robot arm is the perfect example for excersizing with the transformation matrix.
Read also: How to draw a Simple Light in OpenGL
The idea is to break down complicated structures into simple and solvable problems. Here there are 20 arms “attached” on top of each other.
Here is the class definition of each arm.
class arm { public: float length; float x, y, z; float speed; arm(){length=1.0f; y=1.0f; x=z=0; speed=1.0f;} }; arm *arms; float angle=0.0f; int numarms = 20;
And here is how each arm is initialized. Every arm is different.
for (int i=0; i<numarms; i++) { arms[i].length = (float)(rand() % 10000) / 1000; arms[i].x=rand(); arms[i].y=rand(); arms[i].z=rand(); arms[i].speed=(float)(rand() % 1000) / 700 ; }
To draw the arms, we have a method dedicated to draw *one* arm.
void drawRoboarm(int slices, float length) { glPushMatrix(); if (slices > 2) { for (int i=0; i<slices; i++) { glRotatef(360/slices,0 ,1, 0); glBegin(GL_LINE_STRIP); glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(0.2f, length/5, 0.0f); glVertex3f(0.2f, length/5, 0.0f); glVertex3f(0.0f, length, 0.0f); glEnd(); } glBegin(GL_LINES); glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(0.0f, length, 0.0f); glEnd(); } glPopMatrix(); }
Read also: How to draw a Space Cube in OpenGL
Then we have a method calling drawRoboarm for each arm. Where we 1) draw, 2) translates, and 3) rotates for each arm.
void drawArms() { srand(GetTickCount()); glPushMatrix(); if (i < numarms) { drawRoboarm(4, arms[i].length); glTranslatef(0.0f, arms[i].length, 0.0f); glRotatef(angle*arms[i].speed, arms[i].x, arms[i].y, arms[i].z); i++; drawArms(); } glPopMatrix(); }
#include <Windows.h> #include <gl/glut.h> #include <gl/gl.h> #include <gl/glu.h> class arm { public: float length; float x, y, z; float speed; arm(){length=1.0f; y=1.0f; x=z=0; speed=1.0f;} }; arm *arms; float angle=0.0f; int numarms = 20; int i=0; void drawCoords() { ///* glPushMatrix(); glBegin(GL_LINES); // X in red... glColor3f(1.0f, 0.0f, 0.0f); glVertex3f(0, 0, 0); glVertex3f(1, 0, 0); // Y in green glColor3f(0.0f, 1.0f, 0.0f); glVertex3f(0, 0, 0); glVertex3f(0, 1, 0); // Z in blue glColor3f(0.0f, 0.0f, 1.0f); glVertex3f(0, 0, 0); glVertex3f(0, 0, 1); glColor3f(1.0f, 1.0f, 1.0f); } void drawRoboarm(int slices, float length) { glPushMatrix(); if (slices > 2) { for (int i=0; i<slices; i++) { glRotatef(360/slices,0 ,1, 0); glBegin(GL_LINE_STRIP); glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(0.2f, length/5, 0.0f); glVertex3f(0.2f, length/5, 0.0f); glVertex3f(0.0f, length, 0.0f); glEnd(); } glBegin(GL_LINES); glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(0.0f, length, 0.0f); glEnd(); } glPopMatrix(); } void drawArms() { srand(GetTickCount()); glPushMatrix(); if (i < numarms) { drawRoboarm(4, arms[i].length); glTranslatef(0.0f, arms[i].length, 0.0f); glRotatef(angle*arms[i].speed, arms[i].x, arms[i].y, arms[i].z); i++; drawArms(); } glPopMatrix(); } void draw() { angle += 1.0f; i=0; drawArms(); } void renderScene() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); gluLookAt(50.0f, 3.0f, 100.0f, 0.0f, 2.0f, 0.0f, 0.0f, 1.0f, 0.0f); drawCoords(); draw(); Sleep(10); glutSwapBuffers(); } void changeSize(int w, int h) { // Prevent a divide by zero, when window is too short // (you cant make a window of zero width). if(h == 0) h = 1; //w = w1; //h = h1; GLdouble ratio = 1.0f * w / h; // Reset the coordinate system before modifying glMatrixMode(GL_PROJECTION); glLoadIdentity(); // Set the viewport to be the entire window glViewport(0, 0, w, h); // Set the clipping volume gluPerspective(45,ratio,0.1,1000); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } int main(int argc, char **argv) { srand(GetTickCount()); arms = new arm[numarms]; for (int i=0; i<numarms; i++) { arms[i].length = (float)(rand() % 10000) / 1000; arms[i].x=rand(); arms[i].y=rand(); arms[i].z=rand(); arms[i].speed=(float)(rand() % 1000) / 700 ; } glutInit(&argc, argv); glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); glutInitWindowSize(640,480); glutCreateWindow("Do the robo baby!"); glEnable(GL_DEPTH_TEST); glutIgnoreKeyRepeat(1); glutReshapeFunc(changeSize); glutDisplayFunc(renderScene); glutIdleFunc(renderScene); glutMainLoop(); }
Professional Software Developer, doing mostly C++. Connect with Kent on Twitter.