sph_plugin/
components.rs

1use bevy::prelude::*;
2
3#[derive(Component)]
4pub struct FluidParticle {
5    pub velocity: Vec2,
6    pub density: f32,
7    pub pressure: f32,
8}
9
10impl Default for FluidParticle {
11    fn default() -> Self {
12        Self {
13            velocity: Vec2::ZERO,
14            density: 1.225,
15            pressure: 0.0,
16        }
17    }
18}
19
20#[derive(Component)]
21pub struct SolidBoundary {
22    pub points: Vec<Vec2>,
23    pub normals: Vec<Vec2>,
24}
25
26impl SolidBoundary {
27    pub fn new_airfoil(chord: f32, position: Vec2, angle_of_attack: f32) -> Self {
28        let num_points = 50;
29        let mut points = Vec::with_capacity(num_points);
30        let mut normals = Vec::with_capacity(num_points);
31
32        for i in 0..num_points {
33            let x = (i as f32) / (num_points as f32 - 1.0);
34            let t = 0.12; // maximum thickness
35            let y = 5.0
36                * t
37                * chord
38                * (0.2969 * x.sqrt() - 0.1260 * x - 0.3516 * x.powi(2) + 0.2843 * x.powi(3)
39                    - 0.1015 * x.powi(4));
40
41            let point = Vec2::new(x * chord - chord / 2.0, y);
42
43            points.push(crate::math::rotate_point(point, angle_of_attack) + position);
44            points.push(
45                crate::math::rotate_point(Vec2::new(point.x, -point.y), angle_of_attack) + position,
46            );
47
48            let dx = 0.01;
49            let dy = if i < num_points - 1 {
50                let next_y = 5.0
51                    * t
52                    * chord
53                    * (0.2969 * (x + dx).sqrt() - 0.1260 * (x + dx) - 0.3516 * (x + dx).powi(2)
54                        + 0.2843 * (x + dx).powi(3)
55                        - 0.1015 * (x + dx).powi(4));
56                (next_y - y) / dx
57            } else {
58                let prev_x = x - dx;
59                let prev_y = 5.0
60                    * t
61                    * chord
62                    * (0.2969 * prev_x.sqrt() - 0.1260 * prev_x - 0.3516 * prev_x.powi(2)
63                        + 0.2843 * prev_x.powi(3)
64                        - 0.1015 * prev_x.powi(4));
65                (y - prev_y) / dx
66            };
67
68            let normal = Vec2::new(-dy, 1.0).normalize();
69            normals.push(crate::math::rotate_vector(normal, angle_of_attack));
70            normals.push(crate::math::rotate_vector(
71                Vec2::new(-dy, -1.0).normalize(),
72                angle_of_attack,
73            ));
74        }
75
76        Self { points, normals }
77    }
78
79    pub fn new_wind_tunnel(box_size: Vec2) -> Self {
80        let half_width = box_size.x / 2.0;
81        let half_height = box_size.y / 2.0;
82
83        let points = vec![
84            Vec2::new(-half_width, half_height),
85            Vec2::new(half_width, half_height),
86            Vec2::new(-half_width, -half_height),
87            Vec2::new(half_width, -half_height),
88        ];
89
90        let normals = vec![
91            Vec2::new(0.0, -1.0),
92            Vec2::new(0.0, -1.0),
93            Vec2::new(0.0, 1.0),
94            Vec2::new(0.0, 1.0),
95        ];
96
97        Self { points, normals }
98    }
99}