#include #include #include #include #define OPEN_LEN 15 #define OPEN_TIM 600 static double open_s[OPEN_LEN][OPEN_LEN][OPEN_LEN][3]; static double open_c[OPEN_LEN][OPEN_LEN][OPEN_LEN][3]; static int open_t = 10; #define TORUS 6 #define DATA_SIZE 10000 #define RND_TIM 100 static double lane[DATA_SIZE][3]; static double lanecolor[DATA_SIZE][3]; static double torus[TORUS][3],torusp[TORUS][3]; static int toruslap[TORUS]; static int rndmd=1; /* 視点位置のランダムモードのスイッチ */ static int mainr=0; /* オープニング-メインのフラグ */ static int zoom=8; /* ズームのパラメーター */ static double vht=0.2; /* 視点の高さ */ static int torus_num=0; /* 視点を設定するトーラスの番号 */ static int vall=1; /* 視点の切り替えスイッチ */ static int stop=0; /* 一時停止-再開スイッチ */ static int winx,winy; /* ウィンドウのサイズ */ void quit(void) { #ifdef STEREO system("/usr/gfx/setmon -n 60HZ"); #endif exit(0); } void solv_de(u,v) /* Lorenz方程式の差分化方程式の繰り返し計算 */ double u[3],v[3]; { static double dt = 0.005; /* 時間間隔 */ v[0] = u[0] + dt * (10.0 * (u[1] - u[0])); v[1] = u[1] + dt * (28.0 * u[0] - u[1] - u[0] * u[2]); v[2] = u[2] + dt * (-2.666666667 * u[2] + u[0] * u[1]); } void project1(u,v) double u[3],v[3]; { v[0] = u[0]+u[1]; v[1] = (u[0]-u[1])/10.0; v[2] = u[2]; } void project2(u,v) double u[3],v[3]; { v[0] = (u[0]+u[1]*10.0)/2.0; v[1] = (u[0]-u[1]*10.0)/2.0; v[2] = u[2]; } o_solv_de() { int i,j,k; double u[3],v[3]; for(i=0; i 16.97) && torusp[i][2] < 27.0 && torus[i][2] > 27.0 ) toruslap[i]++; } } void init_torus(void) /* トーラスの初期位置 */ { int i; double r; for(i=0; i 0) move_torus(); glutPostRedisplay(); } void set_sight(double offset) { int i; double u1[3], ur[3], ue[3]; double rr; if (vall == 1) { /* 視点を正面遠方に固定 */ glLoadIdentity(); gluLookAt(offset,100.0,30.0, 0.0,0.0,30.0, 0.0,0.0,1.0); } else { /* 視点をトーラス後方に設定 */ for(i=0; i<3; i++) { u1[i] = torusp[torus_num][i]; ur[i] = torus[torus_num][i] - u1[i]; } rr = sqrt(ur[0]*ur[0]+ur[2]*ur[2]); ue[0] = u1[0] - (double)zoom * ur[0] / rr * cos(vht) + offset * ur[2] / rr; ue[2] = u1[2] - (double)zoom * ur[2] / rr * cos(vht) - offset * ur[0] / rr; ue[1] = u1[1] + (double)zoom * sin(vht); glLoadIdentity(); gluLookAt(ue[0],ue[1],ue[2], u1[0],u1[1],u1[2], 0.0,1.0,0.0); } } void set_light(void) { GLfloat light_ambient[] = { 0.2,0.2,0.2,1.0 }; GLfloat light_position0[] = { 17.0, 50.0, 27.0, 1.0 }; GLfloat light_position1[] = { -17.0,-50.0, 27.0, 1.0 }; GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 }; glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); glLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient); glLightfv(GL_LIGHT0, GL_POSITION, light_position0); glLightfv(GL_LIGHT1, GL_POSITION, light_position1); glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse); glEnable(GL_LIGHT0); glEnable(GL_LIGHT1); } void m_display(void) { int i; GLfloat mat_diffuse1[] = {1.0, 1.0, 1.0, 1.0}; GLfloat mat_diffuse[6][4]= {{1.0, 0.2, 0.2, 1.0}, {0.2, 1.0, 0.2, 1.0}, {0.2, 0.2, 1.0, 1.0}, {1.0, 1.0, 0.2, 1.0}, {1.0, 0.2, 1.0, 1.0}, {0.2, 1.0, 1.0, 1.0}}; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); #ifdef STEREO set_sight(0.2); glViewport(0, 0, 1280, 492); glNewList(1, GL_COMPILE_AND_EXECUTE); #else set_sight(0.0); #endif set_light(); /* 解曲線を表示 */ glBegin(GL_LINE_STRIP); for(i=0; i < DATA_SIZE; i++) { glColor3dv(lanecolor[i]); glVertex3dv (lane[i]); } glEnd(); glEnable(GL_LIGHTING); /* 解曲線上の点をトーラスで表示 */ for(i=0; i 0) { m_display(); open_t++; if (open_t == OPEN_TIM+RND_TIM) { open_t=OPEN_TIM; if (rndmd == 1) rnd_view(); } } else if(open_t < OPEN_TIM) { o_display(); open_t++; } else { mainr = 1; m_display(); glShadeModel(GL_SMOOTH); glEnable(GL_DEPTH_TEST); } } void reshape(int w, int h) { winx = w; winy = h; glViewport(0, 0, (GLsizei) w, (GLsizei) h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(40.0, (GLfloat)w/(GLfloat)h, 1.0, 3000.0); glMatrixMode(GL_MODELVIEW); } void mouse(int button, int state, int x, int y) { if (mainr == 0) return; switch(button) { case GLUT_LEFT_BUTTON: if(state == GLUT_UP && y > winy*0.2 && y < winy*0.8 && x > winx*0.2 && x < winx*0.8) { if (stop == 1) { stop = 0; glutIdleFunc(idle); } else { stop = 1; glutIdleFunc(NULL); } } if(state == GLUT_UP && vall == 0 && rndmd == 0) { if (y < winy*0.2) { vht += 0.1; if(vht > 0.75) vht = 0.8; glutPostRedisplay(); } else if (y > winy*0.8) { vht -= 0.1; if (vht < -0.75) vht = -0.8; glutPostRedisplay(); } else if (x < winx*0.2) { zoom = zoom / 2; if (zoom < 2) zoom = 2; glutPostRedisplay(); } else if (x > winx*0.8) { zoom = zoom * 2; if (zoom > 128) zoom = 128; glutPostRedisplay(); } } break; case GLUT_RIGHT_BUTTON: if(state == GLUT_UP) { if (rndmd == 1) { printf("random eye position mode off\n"); rndmd = 0; vall = 1; } else if (vall == 1) { vall = 0; torus_num = 0; printf("following the torus No.%d\n",torus_num+1); } else { torus_num++ ; if (torus_num == TORUS) { rndmd = 1; printf("random eye position mode on\n"); } else printf("following the torus No.%d\n",torus_num+1); } glutPostRedisplay(); } break; } } void keyboard(unsigned char key, int x, int y) { if (mainr > 0) { switch(key) { case 27: /* [ESC] プログラムの終了 */ case 'q': quit(); break; case 's': /* アニメーション一時停止 */ stop = 1; glutIdleFunc(NULL); break; case 'g': /* アニメーション開始 */ stop = 0; glutIdleFunc(idle); break; case ' ': /* (停止時に)1コマ進める */ idle(); break; case '0': /* 視点を上方遠方にする */ rndmd = 0; vall = 1; glutPostRedisplay(); break; case '1': /* 視点を1番の車にする */ rndmd = 0; vall = 0; torus_num = 0; glutPostRedisplay(); break; case '2': /* 視点を2番の車にする */ rndmd = 0; vall = 0; torus_num = 1; glutPostRedisplay(); break; case '3': /* 視点を3番の車にする */ rndmd = 0; vall = 0; torus_num = 2; glutPostRedisplay(); break; case '4': /* 視点を4番の車にする */ rndmd = 0; vall = 0; torus_num = 3; glutPostRedisplay(); break; case '5': /* 視点を5番の車にする */ rndmd = 0; vall = 0; torus_num = 4; glutPostRedisplay(); break; case '6': /* 視点を6番の車にする */ rndmd = 0; vall = 0; torus_num = 5; glutPostRedisplay(); break; case 'u': /* 視点を上にずらす */ if (vall == 0 && rndmd == 0) { vht += 0.1; if(vht > 0.75) vht = 0.8; glutPostRedisplay(); } break; case 'd': /* 視点を下にずらす */ if (vall == 0 && rndmd == 0) { vht -= 0.1; if (vht < -0.75) vht = -0.8; glutPostRedisplay(); } break; case '+': /* ズームイン */ if (vall == 0 && rndmd == 0) { zoom = zoom / 2; if (zoom < 2) zoom = 2; glutPostRedisplay(); } break; case '-': /* ズームアウト */ if (vall == 0 && rndmd == 0) { zoom = zoom * 2; if (zoom > 128) zoom = 128; glutPostRedisplay(); } break; case 'r': /* 視点のランダムモード切替 */ rndmd = 1; break; } } } void main(int argc, char *argv[]) { #ifdef STEREO system("/usr/gfx/setmon -n STR_RECT"); #endif glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH); glutInitWindowSize(480,360); glutInitWindowPosition(50,50); glutCreateWindow("Lorenz Attractor"); init(); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glutMouseFunc(mouse); glutIdleFunc(idle); #ifdef STEREO glutFullScreen(); #endif glutMainLoop(); }