rustial_engine/models/
instance.rs1use rustial_math::GeoCoord;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
7pub enum AltitudeMode {
8 #[default]
10 Absolute,
11 RelativeToGround,
13 ClampToGround,
15}
16
17#[derive(Debug, Clone)]
19pub struct ModelMesh {
20 pub positions: Vec<[f32; 3]>,
22 pub normals: Vec<[f32; 3]>,
24 pub uvs: Vec<[f32; 2]>,
26 pub indices: Vec<u32>,
28}
29
30#[derive(Debug, Clone)]
32pub struct ModelInstance {
33 pub position: GeoCoord,
35 pub altitude_mode: AltitudeMode,
37 pub heading: f64,
39 pub pitch: f64,
41 pub roll: f64,
43 pub scale: f64,
45 pub mesh: ModelMesh,
47}
48
49impl ModelInstance {
50 pub fn new(position: GeoCoord, mesh: ModelMesh) -> Self {
52 Self {
53 position,
54 altitude_mode: AltitudeMode::default(),
55 heading: 0.0,
56 pitch: 0.0,
57 roll: 0.0,
58 scale: 1.0,
59 mesh,
60 }
61 }
62
63 pub fn resolve_altitude(&self, terrain_elevation: Option<f64>) -> f64 {
65 match self.altitude_mode {
66 AltitudeMode::Absolute => self.position.alt,
67 AltitudeMode::RelativeToGround => {
68 let ground = terrain_elevation.unwrap_or(0.0);
69 ground + self.position.alt
70 }
71 AltitudeMode::ClampToGround => terrain_elevation.unwrap_or(0.0),
72 }
73 }
74}
75
76#[cfg(test)]
77mod tests {
78 use super::*;
79
80 fn dummy_mesh() -> ModelMesh {
81 ModelMesh {
82 positions: vec![[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0]],
83 normals: vec![[0.0, 0.0, 1.0]; 3],
84 uvs: vec![[0.0, 0.0], [1.0, 0.0], [0.0, 1.0]],
85 indices: vec![0, 1, 2],
86 }
87 }
88
89 #[test]
90 fn altitude_absolute() {
91 let inst = ModelInstance {
92 position: GeoCoord::new(0.0, 0.0, 500.0),
93 altitude_mode: AltitudeMode::Absolute,
94 ..ModelInstance::new(GeoCoord::default(), dummy_mesh())
95 };
96 assert!((inst.resolve_altitude(Some(100.0)) - 500.0).abs() < 1e-6);
97 }
98
99 #[test]
100 fn altitude_relative() {
101 let inst = ModelInstance {
102 position: GeoCoord::new(0.0, 0.0, 50.0),
103 altitude_mode: AltitudeMode::RelativeToGround,
104 ..ModelInstance::new(GeoCoord::default(), dummy_mesh())
105 };
106 assert!((inst.resolve_altitude(Some(100.0)) - 150.0).abs() < 1e-6);
107 }
108
109 #[test]
110 fn altitude_clamp() {
111 let inst = ModelInstance {
112 position: GeoCoord::new(0.0, 0.0, 999.0),
113 altitude_mode: AltitudeMode::ClampToGround,
114 ..ModelInstance::new(GeoCoord::default(), dummy_mesh())
115 };
116 assert!((inst.resolve_altitude(Some(200.0)) - 200.0).abs() < 1e-6);
117 }
118}