#include #include #include #define DATA_SIZE 8000 #define DELAY 12 /* 2台の移動物体の距離: 4以上 */ static double de_sol[DATA_SIZE][3]; /* (解)軌道 */ static double pl_p[DELAY][3]; /* 移動物体の位置 */ static double pl_v[DELAY][3]; /* 移動物体の進む方向 */ static double pl_n[DELAY][3]; /* 移動物体のattractiveな方向 */ static double pl_e[DELAY][3]; /* 移動物体のexpandingな方向 */ static int repeat=1; /* デモの反復(スイッチ) */ static int sws=0; /* 視点の位置(スイッチ) */ static double vang=0.2; /* 視点の角度 */ static int zoom=8; /* 拡大率 */ static int lane=1; /* 軌道の表示(スイッチ) */ static int car=1; /* 移動物体の表示(スイッチ) */ void quit(void) { #ifdef STEREO system("/usr/gfx/setmon -n 60HZ"); #endif exit(0); } void normalize(u,v) double u[3],v[3]; { double r; int i; r = u[0]*u[0]+u[1]*u[1]+u[2]*u[2]; for (i=0; i<3; i++) v[i] = u[i]/sqrt(r); } void ext_prod(v1,v2,nv) double v1[3],v2[3],nv[3]; { int i; for(i=0; i<3; i++) { nv[i] = v1[(i+1)%3]*v2[(i+2)%3] - v1[(i+2)%3]*v2[(i+1)%3]; } } void solv_de(u,v) double u[3],v[3]; { double dt = 0.02; /* 時間間隔 */ v[0] = u[0] + dt * (-u[1]-u[2]*20.0); v[1] = u[1] + dt * (u[0]+0.2*u[1]); v[2] = u[2] + dt * (0.01+u[2]*(u[0]-6.6)); } void make_lane() { double v1[3], v2[3]; int h,i; v1[0]= 5.0; /* 初期値 */ v1[1]= 5.0; v1[2]= 0.0; /* 差分方程式の繰り返し計算 */ /* 初期の空回し */ for(i=0; i<100; i++) { solv_de(v1,v2); for(h=0; h<3; h++) v1[h] = v2[h]; } /* データを計算して保存 */ for(i=0 ; i < DATA_SIZE ; i++) { solv_de(v1,v2); for(h=0; h<3; h++) de_sol[i][h] = v1[h] = v2[h]; } } void move_car(void) { int i,j; double u2[3],v1[3],v2[3]; double w1[3],w2[3],w3[3],w4[3]; for(i=0; i<3; i++) { for(j=DELAY-2; j>=0; j--) { pl_p[j+1][i] = pl_p[j][i]; pl_v[j+1][i] = pl_v[j][i]; pl_n[j+1][i] = pl_n[j][i]; pl_e[j+1][i] = pl_e[j][i]; } v1[i]=pl_p[0][i]+0.1*pl_e[0][i]; } solv_de(pl_p[0],u2); solv_de(v1,v2); for(i=0; i<3; i++) { w1[i] = u2[i]-pl_p[0][i]; w2[i] = v2[i]-u2[i]; } ext_prod(w1,w2,w3); ext_prod(w3,w1,w4); normalize(w1,pl_v[0]); normalize(w3,pl_n[0]); normalize(w4,pl_e[0]); for(i=0; i<3; i++) pl_p[0][i]=u2[i]; } void init_car(void) { int i; pl_p[0][0]=4.0; pl_p[0][1]=4.0; pl_p[0][2]=0.0; pl_e[0][0]=1.0; pl_e[0][1]=0.0; pl_e[0][2]=0.0; pl_n[0][0]=0.0; pl_n[0][1]=1.0; pl_n[0][2]=0.0; pl_v[0][0]=0.0; pl_v[0][1]=0.0; pl_v[0][2]=1.0; for(i=0; i<200; i++) move_car(); } void init_light(void) { GLfloat light_diffuse[] = {0.5, 0.5, 0.5, 1.0}; GLfloat light_ambient[] = {0.3, 0.3, 0.3, 1.0}; GLfloat light_specular[] = {0.5, 0.5, 0.5, 1.0}; glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse); glLightfv(GL_LIGHT2, GL_DIFFUSE, light_diffuse); glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); glLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient); glLightfv(GL_LIGHT2, GL_AMBIENT, light_ambient); glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular); glLightfv(GL_LIGHT2, GL_SPECULAR, light_specular); } void set_light(void) { GLfloat light_position0[] = {-20.0, 0.0, 10.0, 1.0}; GLfloat light_position1[] = { 20.0, 0.0,-10.0, 1.0}; /* GLfloat light_position2[] = { 0.0, 0.0, 1.0, 1.0}; */ glLightfv(GL_LIGHT0, GL_POSITION, light_position0); glLightfv(GL_LIGHT1, GL_POSITION, light_position1); /* glLightfv(GL_LIGHT2, GL_POSITION, light_position2); */ glEnable(GL_LIGHT0); glEnable(GL_LIGHT1); /* glEnable(GL_LIGHT2); */ } void set_sight(double offset) { int h; double u1[3], u2[3], u3[3], ue[3]; if (sws == 1) { /* 移動物体の斜後方 */ for(h=0; h<3; h++) ue[h] = pl_p[DELAY-1][h] - pl_v[DELAY-1][h]*(double)(zoom) * cos(vang) + pl_n[DELAY-1][h]*(double)(zoom) * sin(vang) + pl_e[DELAY-1][h]*offset; glLoadIdentity(); gluLookAt(ue[0],ue[1],ue[2], pl_p[DELAY-1][0], pl_p[DELAY-1][1], pl_p[DELAY-1][2], pl_n[DELAY-1][0], pl_n[DELAY-1][1], pl_n[DELAY-1][2]); } else if (sws == 2) { /* 移動物体の斜前方 */ for(h=0; h<3; h++) ue[h] = pl_p[0][h] + pl_v[0][h]*(double)(zoom) * cos(vang) + pl_n[0][h]*(double)(zoom) * sin(vang) - pl_e[0][h]*offset; glLoadIdentity(); gluLookAt(ue[0],ue[1],ue[2], pl_p[0][0], pl_p[0][1], pl_p[0][2], pl_n[0][0], pl_n[0][1], pl_n[0][2]); } else if (sws == 3) { /* 中心から外 */ glLoadIdentity(); u1[0]=0.0; u1[1]=0.0; u1[2]=1.0; ext_prod (u1,pl_v[2],u2); normalize(u2,u3); for(h=0; h<3; h++) ue[h] = pl_p[2][h] + u3[h]*(double)(zoom) * cos(vang) + u1[h]*(double)(zoom) * sin(vang) + pl_v[2][h]*offset; gluLookAt(ue[0], ue[1], ue[2], pl_p[2][0], pl_p[2][1], pl_p[2][2], 0.0, 0.0, 1.0); } else if (sws == 4) { /* 外から中心 */ glLoadIdentity(); u1[0]=0.0; u1[1]=0.0; u1[2]=1.0; ext_prod (pl_v[2],u1,u2); normalize(u2,u3); for(h=0; h<3; h++) ue[h] = pl_p[2][h] + u3[h]*(double)(zoom) * cos(vang) + u1[h]*(double)(zoom) * sin(vang) - pl_v[2][h]*offset; gluLookAt(ue[0], ue[1], ue[2], pl_p[2][0], pl_p[2][1], pl_p[2][2], 0.0, 0.0, 1.0); } else { /* 上方固定 */ glLoadIdentity(); gluLookAt(offset, -2.0, 50.0, 0.0, -2.0, 0.0, 0.0, 1.0, 0.0); } } void display_lane(void) { int i,j; GLdouble c1,c2,c3; double v1[3],v2[3],v3[3],v4[3]; glBegin(GL_LINE_STRIP); for(i=0; i 0) vang += 0.2; if (vang > 1.0) vang = 1.0; glutPostRedisplay(); break; case 'd': /* 視点の角度を下げる */ if (sws > 0) vang -= 0.2; if (vang < -1.0) vang = -1.0; glutPostRedisplay(); break; case '+': /* ズームイン */ if (sws > 0) zoom = zoom/2; if (zoom < 2) zoom = 2; glutPostRedisplay(); break; case '-': /* ズームアウト */ if (sws > 0) zoom = zoom*2; if (zoom > 64) zoom = 64; glutPostRedisplay(); break; case 'l': /* 軌道の表示スイッチ */ lane = 1-lane; glutPostRedisplay(); break; case 'c': /* 移動物体の表示スイッチ */ car = 1-car; glutPostRedisplay(); break; default: break; } } int main(int argc, char *argv[]) { #ifdef STEREO system("/usr/gfx/setmon -n STR_RECT"); #endif glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(480,360); glutInitWindowPosition(100,100); glutCreateWindow("Rossler Attracter"); init(); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glutIdleFunc(idle); #ifdef STEREO glutFullScreen(); #endif glutMainLoop(); return 0; }