diff --git a/src/gen.rs b/src/gen.rs index 4de5e64..1a76b24 100644 --- a/src/gen.rs +++ b/src/gen.rs @@ -2,24 +2,36 @@ use bevy::{prelude::*, render::render_resource::PrimitiveTopology}; use opensimplex_noise_rs::OpenSimplexNoise; use rand::Rng; +/// Générer une planète pub fn planet() -> Mesh { + // Initialiser l'aléatoire let mut rng = rand::thread_rng(); let simplex = OpenSimplexNoise::new(Some(rng.gen())); + + // Créer un mesh vide let mut mesh = Mesh::new(PrimitiveTopology::TriangleList); + let perimeter: u32 = 1000; + + // Ajouter des points dans le mesh mesh.insert_attribute( Mesh::ATTRIBUTE_POSITION, (0..perimeter) .map(|i| { + // Rayon let mut r = simplex.eval_2d(i as f64 * 0.02, 0.) as f32 * 20.0 + 100.0; r += simplex.eval_2d(i as f64 * 0.05, 10.) as f32 * 10.0; r += simplex.eval_2d(i as f64 * 0.2, 10.) as f32 * 4.0; + // Angle let a = std::f32::consts::TAU * i as f32 / perimeter as f32; + // Coordonnées du point [r * a.cos(), r * a.sin(), 0.] }) .chain([[0., 0., 0.]]) .collect::>(), ); + + // Ajouter des triangles en indiquant quels points (de ceux définis juste avant) doivent être reliés let mut triangles = Vec::new(); for i in 0..perimeter { triangles.extend_from_slice(&[i, perimeter, (i + 1) % perimeter]); diff --git a/src/quadtree.rs b/src/quadtree.rs index 99bd481..cb4cf97 100644 --- a/src/quadtree.rs +++ b/src/quadtree.rs @@ -40,37 +40,14 @@ pub enum Node { /// Ajoutons des fonctions aux nœuds impl Node { - /// Création d'un nouveau nœud + /// Création d'un nouveau nœud vide pub fn new(pos: (Vec2, Vec2)) -> Self { Node::Leaf { body: None, pos } - // let center = (pos.1 - pos.0) / 2.0; - // Node::Branch { - // nodes: [ - // Box::new(Node::Leaf { - // body: None, - // pos: (pos.0, center), - // }), - // Box::new(Node::Leaf { - // body: None, - // pos: (Vec2::new(center.x, pos.0.y), Vec2::new(pos.1.x, center.y)), - // }), - // Box::new(Node::Leaf { - // body: None, - // pos: (Vec2::new(pos.0.x, center.y), Vec2::new(center.x, pos.1.y)), - // }), - // Box::new(Node::Leaf { - // body: None, - // pos: (center, pos.1), - // }), - // ], - // center, - // mass: 0.0, - // center_of_mass: center, - // width: pos.1.x - pos.0.x, - // } } + /// Ajouter un corps dans le nœud pub fn add_body(&mut self, new_body: L) { match self { + // Si le nœud est une branche... Node::Branch { nodes, center, @@ -80,9 +57,11 @@ impl Node { } => { let new_body_pos = new_body.pos(); let new_body_mass = new_body.mass(); + // Calculer le centre de masse des corps dans la branche plus le nouveau corps *center_of_mass = (*center_of_mass * *mass + new_body_mass * new_body_pos) / (*mass + new_body_mass); *mass += new_body_mass; + // Trouver le bon cadrant où ajouter le corps nodes[if new_body_pos.x < center.x { if new_body_pos.y < center.y { 0 @@ -98,8 +77,12 @@ impl Node { }] .add_body(new_body) } + // Si le nœud est une feuille... Node::Leaf { body, pos } => { + // Si la feuille contient un corps... if let Some(mut body) = body.take() { + // Si les deux corps sont très proches, on évite de créer plein de branches ce qui ferait tout planter. + // Dans ce cas on fusionne les deux if body.pos().distance_squared(new_body.pos()) < 1.0 { body.add_mass(new_body.mass()); *self = Node::Leaf { @@ -108,7 +91,10 @@ impl Node { }; return; } + // Cette feuille va devenir une branche. + // On calcule donc son centre. let center = (pos.0 + pos.1) / 2.0; + // Et on la remplace par une branche, pour l'instant avec ses 4 cadrants vides. *self = Node::Branch { nodes: Box::new([ Node::Leaf { @@ -133,17 +119,23 @@ impl Node { center_of_mass: center, width: pos.1.x - pos.0.x, }; + + // On ajoute les deux corps dans la branche. self.add_body(body); self.add_body(new_body) } else { + // Ici est le cas où la feuille était vide, alors on met juste le nouveau corps dedans. *body = Some(new_body); } } } } + /// Calculer la force de gravité s'appliquant sur le point `on` + /// `theta` est un nombre entre 0.0 et 1.0, qui détermine si on veut plus de précision ou plus de rapidité. pub fn apply(&self, on: Vec2, theta: f32) -> Vec2 { match self { + // Si le nœud est une branche... Node::Branch { nodes, mass, @@ -152,26 +144,34 @@ impl Node { .. } => { if on == *center_of_mass { + // Dans ce cas la distance est nulle, donc on évite de diviser par zéro. return Vec2::ZERO; } let dist = on.distance(*center_of_mass); if width / dist < theta { + // On est dans le cas où on est assez loin pour pouvoir faire une approximation. + // On fait comme si le nœud était un gros corps, la fusion de tous les corps qu'il contient. *mass * (*center_of_mass - on) / (dist * dist * dist) } else { + // On est dans le cas où on est trop près pour faire l'approximation. + // On applique alors récursivement pour chaque sous-nœud. nodes[0].apply(on, theta) + nodes[1].apply(on, theta) + nodes[2].apply(on, theta) + nodes[3].apply(on, theta) } } + // Si le nœud est une feuille... Node::Leaf { body, .. } => { if let Some(body) = body { + // La feuille contient un corps. if on == body.pos() { return Vec2::ZERO; } let dist = on.distance(body.pos()); body.mass() * (body.pos() - on) / (dist * dist * dist) } else { + // La feuille est vide. Vec2::ZERO } }