vector_add(&pa, &pb, &p);
mass = a->mass + b->mass;
- if (a->mass < b->mass) {
- rem = a;
- nr = a;
- } else {
- rem = b;
- nr = a;
- }
-
- nr->r = (a->r * a->mass + b->r * b->mass) / mass;
- nr->g = (a->g * a->mass + b->g * b->mass) / mass;
- nr->b = (a->b * a->mass + b->b * b->mass) / mass;
+ if (a->mass < b->mass)
+ parent = quadtree_move(&a->tree, b->tree.pos, &planet_ops);
- a->r = (a->r * a->mass + b->r * b->mass) / mass;
- a->g = (a->g * a->mass + b->g * b->mass) / mass;
- a->b = (a->b * a->mass + b->b * b->mass) / mass;
+ nr->mass = mass;
+ reshape_planet(nr);
+ vector_div(&p, nr->mass, &nr->speed);
- return rem;
+ a->mass = mass;
+ reshape_planet(a);
+ vector_div(&p, a->mass, &a->speed);
+
+ return tree_to_planet(quadtree_find_parent(parent));
}
/*
*/
struct planet *merge_planets(struct planet *a, struct planet *b)
{
- struct planet *r;
-
- r = _merge_planets(a, b);
+ struct quadtree *p;
+ _merge_planets(a, b);
- //list_del(&b->list);
- //quadtree_del(&b->tree, &planet_ops);
+ list_del(&b->list);
+ p = quadtree_del(&b->tree, &planet_ops);
- //free(b);
- if (r == a)
- a->to_be_deleted = 1;
- else
- b->to_be_deleted = 1;
-
- return r;
+ free(b);
+ return tree_to_planet(p);
}
- static int planet_search_when_moving(struct quadtree *node,
- struct quadtree_iterator *itr)
- {
- struct planet *p = tree_to_planet(node);
- struct planet_search_iterator *it = qt_itr_to_planet_itr(itr);
- int direction = 0, i;
- int up = 0, left = 0, right = 0, down = 0;
-
- for (i = 0; i < 2; i++) {
- if (it->limit[i].x < p->tree.pos.x)
- left = 1;
- else
- right = 1;
- if (it->limit[i].y < p->tree.pos.y)
- up = 1;
- else
- down = 1;
- }
-
- if (left || up)
- direction |= QUADTREE_UPLEFT;
- if (right || up)
- direction |= QUADTREE_UPRIGHT;
- if (left || down)
- direction |= QUADTREE_DOWNLEFT;
- if (right || down)
- direction |= QUADTREE_DOWNRIGHT;
- if ((left && right) || (up && down))
- direction |= QUADTREE_SELF;
-
- return direction;
- }
-
- void planet_move_iterator(struct quadtree *node, struct quadtree_iterator *it)
- {
- struct planet_search_iterator *itr = qt_itr_to_planet_itr(it);
- if (node == it->head)
- return;
-
- /*
- parent = quadtree_del(node, &planet_ops);
- quadtree_add(parent, node, &planet_ops);
- */
- itr->modify++;
- }
-
+static void gravitize_planet(struct planet *p, struct planet *pt, double time)
+{
+ struct vector vect;
+ float dist;
+ int i;
+
+ vector_sub(&p->tree.pos, &pt->tree.pos, &vect);
+ dist = vector_abs(&vect);
+
+ if (p != pt)
+ gravitize_planet_with_planet(p, pt, time);
+
+ if (dist > pt->tree_area * 8) {
+ /*
+ * OK, the node is far enough. We can approximate the
+ * entire tree as a single entity.
+ */
+ optimizations += pt->tree.children;
+ 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);
+}
+
struct planet *move_planet(struct planet *p, const double time)
{
struct vector tmp, new_pos;
vector_scale(&p->speed, time, &tmp);
vector_add(&p->tree.pos, &tmp, &new_pos);
- /* Check if we have crossed any of the parents */
- parent = p->tree.parent;
- while (parent) {
- pa = tree_to_planet(parent);
- if (p->tree.pos.x < pa->tree.pos.x && new_pos.x > pa->tree.pos.x)
- modify = 1;
- if (p->tree.pos.x > pa->tree.pos.x && new_pos.x < pa->tree.pos.x)
- modify = 1;
- if (p->tree.pos.y < pa->tree.pos.y && new_pos.y > pa->tree.pos.y)
- modify = 1;
- if (p->tree.pos.y > pa->tree.pos.y && new_pos.y < pa->tree.pos.y)
- modify = 1;
-
- if (!modify) {
- parent = parent->parent;
- continue;
- }
-
- tree_parent = quadtree_del(&p->tree, &planet_ops);
- p->tree.pos = new_pos;
- quadtree_add(tree_parent, &p->tree, &planet_ops);
- return tree_to_planet(tree_parent);
- }
-
- if(p->tree.children) {
- /*
- * Now, search the subtree for any crossed children and move
- * them into correct place within the tree.
- */
- it.qt_iterator.head = &p->tree;
- it.limit[0] = p->tree.pos;
- it.limit[1] = new_pos;
- it.qt_iterator.direction = planet_search_when_moving;
- it.qt_iterator.callback = planet_move_iterator;
- walk_quadtree(&it.qt_iterator);
- }
-
- if (it.modify) {
- tree_parent = quadtree_del(&p->tree, &planet_ops);
- p->tree.pos = new_pos;
- quadtree_add(tree_parent, &p->tree, &planet_ops);
- goto out;
- }
-
- p->tree.pos = new_pos;
- tree_parent = quadtree_find_parent(&p->tree);
- out:
- quadtree_validate_tree(&p->tree);
- return tree_to_planet(tree_parent);
+ return tree_to_planet(quadtree_move(&p->tree, new_pos, &planet_ops));
}
+int propagate_tree_movement(struct planet *p)
+{
+ int i, count = 1;
+
+ for (i = 0; i < 4; i++) {
+ if (!p->tree.child[i])
+ continue;
+
+ vector_add(&tree_to_planet(p->tree.child[i])->speed,
+ &p->tree_speed,
+ &tree_to_planet(p->tree.child[i])->speed);
+
+ count += propagate_tree_movement(
+ tree_to_planet(p->tree.child[i]));
+ }
+
+ vector_add(&p->tree_speed, &p->speed, &p->speed);
+
+ p->tree_speed.x = 0;
+ p->tree_speed.y = 0;
+
+ return count;
+}
+
+struct planet *prune_planet_tree(struct planet *p)
+{
+ struct quadtree *tree_parent = &p->tree;
+ int i;
+/*
+ while (head != start) {
+ p = list_to_planet(head);
+ if (p->to_be_deleted) {
+ if (head == start)
+ start = head->next;
+ list_del(&p->list);
+ tree_parent = quadtree_del(&p->tree, &planet_ops);
+ head = head->next;
+ free(p);
+ continue;
+ }
+
+ head = head->next;
+ }
+
+ return tree_to_planet(tree_parent);
+*/
+ 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);
+ }
+
+ planet_ops.recalculate_stats(&p->tree);
+
+ 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",