|
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <math.h> |
|
#include <getopt.h> |
|
#include "vec.h" |
|
#include "random.h" |
|
|
|
/* Parameters. */ |
|
char *progname = ""; |
|
unsigned num_stars = 2; |
|
double G = 10.0; |
|
unsigned num_frames = 0; |
|
int quiet = 0; |
|
double galaxy_radius = 100.0; |
|
double initial_velocity = 0.0; |
|
|
|
typedef struct { |
|
vec3 pos, vel, acc; |
|
double mass; |
|
} star; |
|
|
|
star *create_galaxy(unsigned count, double radius) |
|
{ |
|
star *stars = calloc(count, sizeof(star)); |
|
unsigned i; |
|
vec3 up = {1.0, 0, 0}; |
|
for (i = 0; i < count; i++) { |
|
stars[i].pos.x = r_normal() * radius; |
|
stars[i].pos.y = r_normal() * radius; |
|
stars[i].pos.z = r_normal() * radius; |
|
stars[i].mass = r_normal() / 10.0 + 1.0; |
|
if (stars[i].mass <= 0.1) stars[i].mass = 0.1; |
|
stars[i].vel = norm(cross(stars[i].pos, up)); |
|
double v = r_normal() * initial_velocity / 10.0 + initial_velocity; |
|
stars[i].vel = vmul(stars[i].vel, v); |
|
} |
|
return stars; |
|
} |
|
|
|
int main(int argc, char **argv) |
|
{ |
|
int c; |
|
while ((c = getopt (argc, argv, "n:r:v:G:s:f:q")) != -1) { |
|
switch (c) { |
|
case 'n': |
|
num_stars = atoi(optarg); |
|
break; |
|
case 'r': |
|
galaxy_radius = atof(optarg); |
|
break; |
|
case 'v': |
|
initial_velocity = atof(optarg); |
|
break; |
|
case 'G': |
|
G = atof(optarg); |
|
break; |
|
case 's': |
|
srand(atoi(optarg)); |
|
break; |
|
case 'f': |
|
num_frames = atoi(optarg); |
|
break; |
|
case 'q': |
|
quiet = 1; |
|
break; |
|
default: |
|
abort(); |
|
} |
|
} |
|
|
|
star *stars = create_galaxy(num_stars, galaxy_radius); |
|
unsigned frame = 0; |
|
while (num_frames == 0 || frame < num_frames) { |
|
unsigned i, j; |
|
/* Update velocity. */ |
|
for (i = 0; i < num_stars; i++) { |
|
for (j = i + 1; j < num_stars; j++) { |
|
double r = dist(&stars[i].pos, &stars[j].pos); |
|
vec3 dir = norm(vdiff(stars[j].pos, stars[i].pos)); |
|
vec3 g = vmul(dir, G / (r * r)); |
|
stars[i].acc = vsum(stars[i].acc, vmul(g, stars[j].mass)); |
|
stars[j].acc = vsum(stars[j].acc, vmul(g, -stars[i].mass)); |
|
} |
|
} |
|
/* Update position. */ |
|
for (i = 0; i < num_stars; i++) { |
|
stars[i].vel.x += stars[i].acc.x; |
|
stars[i].vel.y += stars[i].acc.y; |
|
stars[i].vel.z += stars[i].acc.z; |
|
stars[i].pos.x += stars[i].vel.x; |
|
stars[i].pos.y += stars[i].vel.y; |
|
stars[i].pos.z += stars[i].vel.z; |
|
stars[i].acc = ZERO; |
|
printf("%f, %f, %f%s", |
|
stars[i].pos.x, stars[i].pos.y, stars[i].pos.z, |
|
i == num_stars - 1 ? "\n" : ", "); |
|
} |
|
if (!quiet) |
|
fprintf(stderr, "frame: %u\n", frame); |
|
frame++; |
|
} |
|
|
|
return 0; |
|
} |