while (1) {
planets = 0;
- list_for_each_entry(pl1, &planet->list, list) {
- pl2 = list_to_planet(pl1->list.next);
- list_for_each_entry_from(pl2, &planet->list, list) {
- struct planet *ptmp;
- if (!gravitize_planets(pl1, pl2,
- step_time))
- continue;
-
- ptmp = list_to_planet(pl2->list.prev);
- merge_planets(pl1, pl2);
- pl2 = ptmp;
- }
+ gravitize_planet_tree(planet, step_time);
+ list_for_each_entry(pl1, &planet_root->list, list) {
planet_root = move_planet(pl1, step_time);
planets++;
}
printf(" \rfps: %.2f, steps/s: %.2f, planets: %d"
", scale %.2f, zoom %.2f, step %ld, visible %d,"
- " depth %ld, c:%ld",
+ " depth %ld, c:%ld, mass %.f, area: %.f",
last_fps, last_sps, planets, status.time_scale,
camera.zoom, step_count, visible_planets,
- planet_root->tree.depth, planet_root->tree.children);
+ planet_root->tree.depth, planet_root->tree.children,
+ planet_root->tree_mass, planet_root->tree_area);
fflush(stdout);
}
}
-int gravitize_planets(struct planet *a, struct planet *b, const double time)
+int gravitize_planet_with_planet(struct planet *a, struct planet *b,
+ const double time)
{
struct vector distance, sum;
double dist, f, acc;
dist = vector_abs(&distance);
- /* Return true in case of a collision */
- if (dist < (a->radius + b->radius))
+ if (dist < (a->radius + b->radius)) {
+ merge_planets(a, b);
+ }
return 1;
vector_div(&distance, dist, &distance);
f = a->mass * b->mass / (dist * dist) * time;
- acc = f / b->mass;
+ acc = f / a->mass;
vector_scale(&distance, acc, &sum);
- vector_add(&b->speed, &sum, &b->speed);
+ vector_sub(&a->speed, &sum, &a->speed);
+
+ return 0;
+}
+
+int gravitize_planet_with_tree(struct planet *a, struct planet *b,
+ const double time)
+{
+ struct vector distance, sum;
+ double dist, f, acc;
+
+ vector_sub(&a->pos, &b->pos, &distance);
+
+ dist = vector_abs(&distance);
+
+ vector_div(&distance, dist, &distance);
+
+ f = a->mass * b->tree_mass / (dist * dist) * time;
acc = f / a->mass;
vector_scale(&distance, acc, &sum);
{
_merge_planets(a, b);
- list_del(&b->list);
- quadtree_del(&b->tree, &planet_ops);
+ //list_del(&b->list);
+ //quadtree_del(&b->tree, &planet_ops);
- free(b);
+ //free(b);
+ b->to_be_deleted = 1;
return a;
}
+static void gravitize_planet(struct planet *p, struct planet *pt, double time)
+{
+ struct vector vect;
+ float dist;
+ int i;
+
+ vector_sub(&p->pos, &pt->pos, &vect);
+ dist = vector_abs(&vect);
+
+ if (p != pt)
+ gravitize_planet_with_planet(p, pt, time);
+
+ if (dist > pt->tree_area * 2) {
+ /*
+ * OK, the node is far enough. We can approximate the
+ * entire tree as a single entity.
+ */
+ gravitize_planet_with_tree(p, pt, time);
+ return;
+ }
+
+ /* Otherwise, gravitize with each of the child */
+ for (i = 0; i < 4; i++) {
+ if (!pt->tree.child[i])
+ continue;
+
+ gravitize_planet(p, tree_to_planet(pt->tree.child[i]),
+ time);
+ }
+}
+
+void gravitize_planet_tree(struct planet *p, double time)
+{
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ if (!p->tree.child[i])
+ continue;
+
+ gravitize_planet_tree(tree_to_planet(p->tree.child[i]),
+ time);
+ }
+
+ gravitize_planet(p,
+ tree_to_planet(quadtree_find_parent(&p->tree)),
+ time);
+}
+
static int planet_search_when_moving(struct quadtree *node,
struct quadtree_iterator *itr)
{
return tree_to_planet(quadtree_find_parent(&p->tree));
}
+struct planet *prune_planet_tree(struct planet *p)
+{
+ struct quadtree *tree_parent;
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ if (!p->tree.child[i])
+ continue;
+
+ prune_planet_tree(tree_to_planet(p->tree.child[i]));
+ }
+
+ if (p->to_be_deleted) {
+ list_del(&p->list);
+ tree_parent = quadtree_del(&p->tree, &planet_ops);
+ free(p);
+ return tree_to_planet(tree_parent);
+ }
+
+ return tree_to_planet(quadtree_find_parent(&p->tree));
+}
+
void print_planet(const struct planet *p)
{
printf("pos: (%f,%f), speed: (%f,%f), mass: %f, radius %f\n",
double mass;
float radius;
unsigned char r, g, b;
+ int to_be_deleted;
/* info about the planets in sub branches */
float tree_area; /* total area occupied by the tree */
void create_planets(struct planet *p, int num, double total_mass,
double radius);
void draw_planet(SDL_Surface *screen, struct planet *p, const struct camera *);
-int gravitize_planets(struct planet *a, struct planet *b, const double time);
+void gravitize_planet_tree(struct planet *p, double time);
struct planet *merge_planets(struct planet *a, struct planet *b);
struct planet *move_planet(struct planet *p, const double time);
void print_planet(const struct planet *p);