]> git.itanic.dy.fi Git - sdl-planets/commitdiff
Crash and burn
authorTimo Kokkonen <kaapeli@itanic.dy.fi>
Sun, 11 Apr 2010 17:38:41 +0000 (20:38 +0300)
committerTimo Kokkonen <kaapeli@itanic.dy.fi>
Sun, 11 Apr 2010 17:38:41 +0000 (20:38 +0300)
main.c
planet.c
planet.h

diff --git a/main.c b/main.c
index 8be3330f3128802b82ff307062f516478ad39196..ad9bbe6814a50b9ac0201d78ebc8f307bfc50494 100644 (file)
--- a/main.c
+++ b/main.c
@@ -218,19 +218,9 @@ static void loop(SDL_Surface *screen, int num_of_planets, double total_mass,
        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++;
                }
@@ -299,10 +289,11 @@ static void loop(SDL_Surface *screen, int num_of_planets, double total_mass,
 
                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);
 
 
index 7f39cb6d187be6b4ee6aabf9a561945396cab740..efd96ad587360ce0524318a1376c32945027f973 100644 (file)
--- a/planet.c
+++ b/planet.c
@@ -138,7 +138,8 @@ void draw_planet(SDL_Surface *screen, struct planet *p,
        }
 }
 
-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;
@@ -147,17 +148,35 @@ int gravitize_planets(struct planet *a, struct planet *b, const double time)
 
        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);
@@ -197,13 +216,62 @@ struct planet *merge_planets(struct planet *a, struct planet *b)
 {
        _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)
 {
@@ -297,6 +365,28 @@ struct planet *move_planet(struct planet *p, const double time)
        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",
index 89f232ac3d706dcc9d7f924e73f1434c40d7b5d5..8db856a79dbddd01fee8016d8d8d1cf59b7c8fb0 100644 (file)
--- a/planet.h
+++ b/planet.h
@@ -17,6 +17,7 @@ struct planet {
        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 */
@@ -41,7 +42,7 @@ void init_planet(struct planet *p);
 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);