#include #include #include #include #include #include #include #include #include #ifdef DEBUG #define DEBUGlog(f, args...) \ fprintf(stderr, "in %s: "f, __FUNCTION__, ## args) #else #define DEBUGlog(f, args...) ; #endif #define W_HEIGHT 480 #define W_WIDTH 640 /* N body problem */ /* parameters */ static int NUM_BODY = 3; static float Gravitation = 100.0f; // ? static float delta = 0.05f; // 0.01 ~ 100 ? static const float eps = 15.0f; /* * だいたい、平均距離をn倍にするんだったら、Gravitationoはn^2倍、 * epsはn倍 */ /* for OpenGL Utility. */ GLUquadricObj **sphere; float DefDistance = 300.0f; typedef struct { /* star's parameter. */ float weight; float a[3]; /* acceleration */ float v[3]; /* velocity */ float r[3]; /* position */ /* for SDL. */ //SDL_Rect rect; } body; body *stars_old, *stars_new; void start(void); __code initialize(int num); __code randomInit(SDL_Surface *screen, int num); __code starsInit(SDL_Surface *screen, int num); __code loop(int count, SDL_Surface *screen, int num); __code compute(int count, SDL_Surface *screen, int num); __code nextTurn(int count, SDL_Surface *screen, int num); __code drawStars(SDL_Surface *screen, int num); __code AdjustLooking(float distance, int count, SDL_Surface *screen, int num); int main(int argc, char **argv) { int ch; while ((ch = getopt(argc, argv, "s:g:")) != -1) { switch (ch) { case 's': delta = atof(optarg); break; case 'g': Gravitation = atof(optarg); break; case '?': default: break; } } start(); return 0; } void start() { goto initialize(NUM_BODY); } __code finish(int ret, int num) { int i; DEBUGlog("Gravity = %e\n", Gravitation); DEBUGlog("FLT_MAX = %e\n", FLT_MAX); DEBUGlog("FLT_MAX_EXP = %d\n", FLT_MAX_EXP); DEBUGlog("FLT_MIN = %e\n", FLT_MIN); DEBUGlog("FLT_MIN_EXP = %d\n", FLT_MIN_EXP); DEBUGlog("FLT_EPSILON = %e\n", FLT_EPSILON); free(stars_old); free(stars_new); for( i=0; iw,screen->h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective( 60.0, (float)screen->w/(float)screen->h, 1.0, 1000.0); gluLookAt( 300.0,300.0,300.0, 0.0,0.0,0.0, 1.0,0.0,0.0); glClearColor(0.0, 0.0, 0.0, 0.0); glMatrixMode(GL_MODELVIEW); for( i=0; i+----------+ +-------------+ back to loop */ __code loop(int count, SDL_Surface *screen, int num) { SDL_Event event; usleep(1000); /* check SDL event. */ while(SDL_PollEvent(&event)){ //Poll events switch(event.type){ //Check event type case SDL_QUIT: //User hit the X (or equivelent) goto finish(1, num); case SDL_KEYDOWN: if (event.key.state==SDL_PRESSED){ switch(event.key.keysym.sym){ case SDLK_UP: goto AdjustLooking(DefDistance/=1.2, count, screen, num); case SDLK_DOWN: goto AdjustLooking(DefDistance*=1.2, count, screen, num); case SDLK_l: goto AdjustLooking(DefDistance, count, screen, num); case SDLK_q: goto finish(0, num); default: break; } } break; default: break; } //Finished with current event } //Done with all events for now if ( countw/(float)screen->h, 1.0, distance*2.5); gluLookAt( distance,distance,distance, 0.0,0.0,0.0, 1.0,0.0,0.0); glClearColor(0.0, 0.0, 0.0, 0.0); glMatrixMode(GL_MODELVIEW); goto loop(0, screen, num); } /* * COMPUTING ROUTINs * * next x = x+dx * dx = v*dt => dx/dt = v * dv = a*dt => dv/dt = a * a = F/m; * F = F1 + F2 + ... + Fn * Fi = G m1m2/r^2 | +-----v-----+ | compute | +-----+-----+ |<----------+ +-----v---------+ | i++ | computeForce +-+ +-----+---------+ i=num) goto compute_out(count, screen, num); /* skip compute with itself. */ else if (i==count) goto computeForce(i+1, count, screen, num); /* compute distance between two i-th planet and itself. */ d0 = stars_old[i].r[0] - stars_old[count].r[0]; d1 = stars_old[i].r[1] - stars_old[count].r[1]; d2 = stars_old[i].r[2] - stars_old[count].r[2]; d = ( d0*d0+d1*d1+d2*d2+eps*eps ); /* compute force it receive from i-th planet. */ //F = Gravitation * stars_old[i].weight * stars_old[count].weight / d; /* and accel. */ //a = F/stars_old[count].weight; a = Gravitation/d * stars_old[i].weight ; stars_old[count].a[0] += a*d0/sqrtf(d); stars_old[count].a[1] += a*d1/sqrtf(d); stars_old[count].a[2] += a*d2/sqrtf(d); DEBUGlog("a=%e, d=%e, d0=%e\n", a, d, d0); DEBUGlog("g*w=%e\n", Gravitation*stars_old[i].weight); goto computeForce( i+1, count, screen, num); } __code compute_out(int count, SDL_Surface *screen, int num) { stars_new[count].v[0] = stars_old[count].v[0]+stars_old[count].a[0]*delta; stars_new[count].v[1] = stars_old[count].v[1]+stars_old[count].a[1]*delta; stars_new[count].v[2] = stars_old[count].v[2]+stars_old[count].a[2]*delta; stars_new[count].r[0] = stars_old[count].r[0]+stars_new[count].v[0]*delta/*+stars_old[count].a[0]*delta*delta/2.0*/; stars_new[count].r[1] = stars_old[count].r[1]+stars_new[count].v[1]*delta/*+stars_old[count].a[1]*delta*delta/2.0*/; stars_new[count].r[2] = stars_old[count].r[2]+stars_new[count].v[2]*delta/*+stars_old[count].a[2]*delta*delta/2.0*/; DEBUGlog("x = %e\n", stars_new[count].r[0]); DEBUGlog("y = %e\n", stars_new[count].r[1]); DEBUGlog("z = %e\n", stars_new[count].r[2]); DEBUGlog("vx = %e\n", stars_new[count].v[0]); DEBUGlog("vy = %e\n", stars_new[count].v[1]); DEBUGlog("vz = %e\n", stars_new[count].v[2]); DEBUGlog("a0=%e,a1=%e,a2=%e\n", stars_new[count].a[0], stars_new[count].a[1], stars_new[count].a[2]); goto loop(1+count, screen, num); } /* it is executed after all bodies parameter is computed. */ __code nextTurn(int count, SDL_Surface *screen, int num) { body *tmp; tmp = stars_old; stars_old = stars_new; stars_new = tmp; //SDL_UpdateRect(screen, 0, 0, 0, 0); goto drawStars(screen, num); } /* * DRAWING ROUTINs * | +----+------+ | drawStars | +----+------+ |<--------+ +----v-----+ | count++ | drawStar +---+ +----+-----+ count