/* tenseg2gl.c structures in three dimensions with tension members */ /* This tensegrety structure has six thin cylinders of length 1 * Label them A through F with ends A1, A2, through F1, F2 * There are 24 strings labeled 1 through 24 with ends 1-1, 1-2, 2-1 etc. * 8 strings of length 1/2, 16 strings of length 0.6125 * * The connections are four string ends to each cylinder end: * length * A1 1-1 4-2 9-2 17-2 1/2 .6125 * B1 1-2 2-1 13-2 18-2 1/2 .6125 * C1 2-2 3-1 14-2 21-2 1/2 .6125 * D1 3-2 4-1 10-2 22-2 1/2 .6125 * E1 9-1 10-1 11-1 12-1 .6125 * F1 17-1 18-1 19-1 20-1 .6125 * A2 5-1 8-2 9-2 19-2 1/2 .6125 * B2 5-2 6-1 15-2 20-2 1/2 .6125 * C2 6-2 7-1 16-2 23-2 1/2 .6125 * D2 7-2 8-1 11-2 24-2 1/2 .6125 * E2 13-1 14-1 15-1 16-1 .6125 * F2 21-1 22-1 23-1 24-1 .6125 * * In order to "anchor" the 3D structure: * Place A1 at 0, 0, 0 * Place B1 at 1/2, 0, 0 * Place C1 at 1/2, 1/2, 0 * Place D1 at 0, 1/2, 0 * Place A2 at 0, 0, 1 * Place B2 at 1/2, 0, 1 * Place C2 at 1/2, 1/2, 1 * Place D2 at 0, 1/2, 1 * Place E1 at -1/4, 1/4, 1/2 * Place E2 at 3/4, 1/4, 1/2 * Place F1 at 1/4, -1/4, 1/2 * Place F2 At 1/4, 3/4, 1/2 */ /* Mouse buttons control axis of rotation */ /* "O" and "o" make centroid offset bigger and smaller */ /* "C" and "c" make color distinct or same */ /* "F" and "f" make rotation faster or slower */ /* "S" and "s" scale larger or smaller */ #include #include #include #define sumcent(A) {centroid[0]+=A[0];centroid[1]+=A[1];centroid[2]+=A[2];} static GLfloat A1[3] = { 0.00, 0.00, 0.00}; static GLfloat A2[3] = { 0.00, 0.00, 1.00}; static GLfloat B1[3] = { 0.50, 0.00, 0.00}; static GLfloat B2[3] = { 0.50, 0.00, 1.00}; static GLfloat C1[3] = { 0.50, 0.50, 0.00}; static GLfloat C2[3] = { 0.50, 0.50, 1.00}; static GLfloat D1[3] = { 0.00, 0.50, 0.00}; static GLfloat D2[3] = { 0.00, 0.50, 1.00}; static GLfloat E1[3] = { -0.25, 0.25, 0.50}; static GLfloat E2[3] = { 0.75, 0.25, 0.50}; static GLfloat F1[3] = { 0.25, -0.25, 0.50}; static GLfloat F2[3] = { 0.25, 0.75, 0.50}; GLfloat colors[][3] = {{1.0,0.0,0.0}, {1.0,1.0,0.0}, {0.0,1.0,0.0}, {0.0,0.0,1.0}, {1.0,0.0,1.0}, {0.0,1.0,1.0}, {0.5,0.5,0.5}}; static GLfloat theta[] = {0.0,0.0,0.0}; static GLint axis = 2; static int colorset = 1; /* 'C' or 'c' */ static double rotation = 1.0; /* 'F' or 'f' */ static GLfloat myScale = 0.5; /* 'S' or 's' */ static GLfloat centroid[3]= { 0.0, 0.0, 0.0}; /* 'O' or 'o' */ static int winWidth = 500; static int winHeight = 500; /* internal functions */ static void myInit(void); static void drawString(int color, GLfloat *A, GLfloat *B); static void drawCylinder(int color, GLfloat *A, GLfloat *B); static void draw_tenseg(void); static void display(void); static void drawText(void); static void spin_tenseg(void); static void mouse(int btn, int state, int x, int y); static void keyboard(unsigned char key, int x, int y); static void myReshape(int w, int h); static GLUquadricObj *c1, *c2, *c3; /* for cylinder */ static void myInit(void) { c1 = gluNewQuadric(); /* for cylinder */ c2 = gluNewQuadric(); c3 = gluNewQuadric(); /* compute centroid, average of vertices */ centroid[0] = 0.5; centroid[1] = 0.5; centroid[2] = 0.5; } static void drawString(int color, GLfloat *A, GLfloat *B) { GLfloat Ac[3], Bc[3]; int i, lcolor; lcolor=color; if(colorset==0) lcolor=1; for(i=0; i<3; i++) { Ac[i] = A[i]-centroid[i]; Bc[i] = B[i]-centroid[i]; } glLineWidth(1.0/myScale); glBegin(GL_LINES); glColor3fv(colors[lcolor]); glVertex3fv(Ac); glVertex3fv(Bc); glEnd(); } static void drawCylinder(int color, GLfloat *A, GLfloat *B) { GLfloat Ac[3], Bc[3]; int i, lcolor; lcolor=color; if(colorset==0) lcolor=1; for(i=0; i<3; i++) { Ac[i] = A[i]-centroid[i]; Bc[i] = B[i]-centroid[i]; } /* draw a cylinder (just a line)*/ glLineWidth(6.0/myScale); glBegin(GL_LINES); glColor3fv(colors[lcolor]); glVertex3fv(Ac); glVertex3fv(Bc); glEnd(); /* glPushMatrix(); glLoadIdentity(); glRotatef(-90.0, 0.0, 0.0, 0.0); gluCylinder(c1, 0.03, 0.03, 0.5, 12, 12); glPopMatrix(); glPushMatrix(); glLoadIdentity(); glRotatef(0.0, 60.0, 0.0, 0.0); gluCylinder(c2, 0.04, 0.04, 0.6, 12, 12); glPopMatrix(); glPushMatrix(); glLoadIdentity(); glRotatef(0.0, 0.0, 0.0, 0.0); gluCylinder(c3, 0.08, 0.08, 0.4, 12, 12); */ glPopMatrix(); } static void draw_tenseg(void) { /* 24 strings and 6 cylinders */ drawString(0, A1, B1); drawString(0, B1, C1); drawString(0, C1, D1); drawString(0, D1, A1); drawString(0, A2, B2); drawString(0, B2, C2); drawString(0, C2, D2); drawString(0, D2, A2); drawString(1, E1, A1); drawString(1, E1, D1); drawString(1, E1, A2); drawString(1, E1, D2); drawString(2, E2, B1); drawString(2, E2, C1); drawString(2, E2, B2); drawString(2, E2, C2); drawString(4, F1, A1); drawString(4, F1, B1); drawString(4, F1, A2); drawString(4, F1, B2); drawString(5, F2, C1); drawString(5, F2, D1); drawString(5, F2, C2); drawString(5, F2, D2); drawCylinder(3, A1, A2); drawCylinder(3, B1, B2); drawCylinder(3, C1, C2); drawCylinder(3, D1, D2); drawCylinder(3, E1, E2); drawCylinder(3, F1, F2); } static void display(void) { /* display callback, clear frame buffer and z buffer, */ /* rotate tenseg and draw, swap buffers */ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glRotatef(theta[0], 1.0, 0.0, 0.0); glRotatef(theta[1], 0.0, 1.0, 0.0); glRotatef(theta[2], 0.0, 0.0, 1.0); draw_tenseg(); drawText(); glFlush(); glutSwapBuffers(); } static void drawText(void) { char msg1[] = "'S' or 's' for size, 'F' or 'f' for rotation speed"; char msg2[] = "'O' or 'o' to offset, 'C' or 'c' for color"; char msg3[] = "mouse button for rotation axis change"; int i, len; /* Draw text */ glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0, winWidth, 0, winHeight, -1, 1); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glColor3f(1.0f, 1.0f, 0.0f); glRasterPos2i(10, 10); len = strlen(msg1); for (i=0; i 360.0) theta[axis] = theta[axis] - 360.0; /* display(); */ glutPostRedisplay(); } static void mouse(int btn, int state, int x, int y) { /* mouse callback, selects 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; } static void keyboard(unsigned char key, int x, int y) { switch (key) { case 'O': centroid[0] *= 1.25; /* increase by 25% each press */ centroid[1] *= 1.25; centroid[2] *= 1.25; break; case 'o': centroid[0] /= 1.25; centroid[1] /= 1.25; centroid[2] /= 1.25; break; case 'C': colorset=1; break; case 'c': colorset=0; break; case 'F': rotation=rotation+0.25; if(rotation>5.0) rotation=5.0; break; case 'f': rotation=rotation-0.25; if(rotation<0.0) rotation=0.0; break; case 's': myScale *= 1.25; /* decrease size by 25% */ myReshape(winWidth, winHeight); break; case 'S': myScale /= 1.25; /* increase size by 25% */ myReshape(winWidth, winHeight); break; } } static void myReshape(int w, int h) { winWidth = w; winHeight = h; glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if(w <= h) glOrtho(-2.0*myScale, 2.0*myScale, -2.0*myScale * (GLfloat)h / (GLfloat)w, 2.0*myScale * (GLfloat)h / (GLfloat)w, -10.0*myScale, 10.0*myScale); else glOrtho(-2.0*myScale * (GLfloat)w / (GLfloat)h, 2.0*myScale * (GLfloat)w / (GLfloat)h, -2.0*myScale, 2.0*myScale, -10.0, 10.0); glMatrixMode(GL_MODELVIEW); } int main(int argc, char *argv[]) { glutInit(&argc, argv); /* need both double buffering and z buffer */ glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(winWidth, winHeight); glutCreateWindow(argv[0]); glutReshapeFunc(myReshape); glutDisplayFunc(display); /* draws screen */ glutIdleFunc(spin_tenseg); /* "spin_tenseg" setup */ glutMouseFunc(mouse); /* "mouse" setup */ glutKeyboardFunc(keyboard); /* "keyboard" setup */ glEnable(GL_DEPTH_TEST); /* Enable hidden--surface--removal */ myInit(); glutMainLoop(); return 0; }