wow_m2/particles/
particle.rs1#[derive(Debug, Clone, Default)]
5pub struct Particle {
6 pub age: f32,
8 pub lifespan: f32,
10 pub color: [f32; 4],
12 pub scale: [f32; 2],
14 pub tex_coord_head: [f32; 2],
16 pub tex_coord_tail: [f32; 2],
18 pub position: [f32; 3],
20 pub velocity: [f32; 3],
22}
23
24impl Particle {
25 pub fn new(position: [f32; 3], velocity: [f32; 3], lifespan: f32) -> Self {
27 Self {
28 age: 0.0,
29 lifespan,
30 color: [1.0, 1.0, 1.0, 1.0],
31 scale: [1.0, 1.0],
32 tex_coord_head: [0.0, 0.0],
33 tex_coord_tail: [0.0, 0.0],
34 position,
35 velocity,
36 }
37 }
38
39 #[inline]
41 pub fn is_alive(&self) -> bool {
42 self.age < self.lifespan
43 }
44
45 #[inline]
47 pub fn age_percent(&self) -> f32 {
48 if self.lifespan > 0.0 {
49 (self.age / self.lifespan).clamp(0.0, 1.0)
50 } else {
51 1.0
52 }
53 }
54
55 pub fn update_physics(&mut self, dt: f32, force: [f32; 3], drag: f32) {
62 self.velocity[0] += force[0] * dt;
64 self.velocity[1] += force[1] * dt;
65 self.velocity[2] += force[2] * dt;
66
67 if drag > 0.0 {
69 let drag_factor = (1.0 - drag).powf(dt);
70 self.velocity[0] *= drag_factor;
71 self.velocity[1] *= drag_factor;
72 self.velocity[2] *= drag_factor;
73 }
74
75 self.position[0] += self.velocity[0] * dt;
77 self.position[1] += self.velocity[1] * dt;
78 self.position[2] += self.velocity[2] * dt;
79 }
80}
81
82#[cfg(test)]
83mod tests {
84 use super::*;
85
86 #[test]
87 fn test_particle_new() {
88 let p = Particle::new([1.0, 2.0, 3.0], [0.1, 0.2, 0.3], 5.0);
89 assert_eq!(p.position, [1.0, 2.0, 3.0]);
90 assert_eq!(p.velocity, [0.1, 0.2, 0.3]);
91 assert_eq!(p.lifespan, 5.0);
92 assert_eq!(p.age, 0.0);
93 assert!(p.is_alive());
94 }
95
96 #[test]
97 fn test_particle_age_percent() {
98 let mut p = Particle::new([0.0, 0.0, 0.0], [0.0, 0.0, 0.0], 10.0);
99 assert_eq!(p.age_percent(), 0.0);
100
101 p.age = 5.0;
102 assert_eq!(p.age_percent(), 0.5);
103
104 p.age = 10.0;
105 assert_eq!(p.age_percent(), 1.0);
106
107 p.age = 15.0; assert_eq!(p.age_percent(), 1.0); }
110
111 #[test]
112 fn test_particle_is_alive() {
113 let mut p = Particle::new([0.0, 0.0, 0.0], [0.0, 0.0, 0.0], 5.0);
114 assert!(p.is_alive());
115
116 p.age = 4.9;
117 assert!(p.is_alive());
118
119 p.age = 5.0;
120 assert!(!p.is_alive());
121
122 p.age = 6.0;
123 assert!(!p.is_alive());
124 }
125
126 #[test]
127 fn test_particle_physics() {
128 let mut p = Particle::new([0.0, 0.0, 0.0], [1.0, 0.0, 0.0], 10.0);
129
130 p.update_physics(1.0, [0.0, 0.0, -9.8], 0.0);
132
133 assert!((p.velocity[2] - (-9.8)).abs() < 0.001);
135
136 assert!((p.position[0] - 1.0).abs() < 0.001);
138 }
139
140 #[test]
141 fn test_particle_drag() {
142 let mut p = Particle::new([0.0, 0.0, 0.0], [10.0, 0.0, 0.0], 10.0);
143
144 p.update_physics(1.0, [0.0, 0.0, 0.0], 0.5);
146
147 assert!(p.velocity[0] < 10.0);
149 assert!(p.velocity[0] > 0.0);
150 }
151}