1#![allow(dead_code)]
3
4#[allow(dead_code)]
8#[derive(Debug, Clone, Copy)]
9pub struct InstanceTransform {
10 pub cols: [[f32; 4]; 4],
11}
12
13impl Default for InstanceTransform {
14 fn default() -> Self {
15 Self {
17 cols: [
18 [1.0, 0.0, 0.0, 0.0],
19 [0.0, 1.0, 0.0, 0.0],
20 [0.0, 0.0, 1.0, 0.0],
21 [0.0, 0.0, 0.0, 1.0],
22 ],
23 }
24 }
25}
26
27#[allow(dead_code)]
29#[derive(Debug, Clone)]
30pub struct BatchInstance {
31 pub id: u32,
32 pub transform: InstanceTransform,
33 pub color_tint: [f32; 4],
34 pub lod_level: u8,
35 pub visible: bool,
36}
37
38#[allow(dead_code)]
40#[derive(Debug, Clone, Default)]
41pub struct InstanceBatch {
42 pub mesh_id: u32,
43 instances: Vec<BatchInstance>,
44}
45
46#[allow(dead_code)]
47pub fn new_instance_batch(mesh_id: u32) -> InstanceBatch {
48 InstanceBatch {
49 mesh_id,
50 instances: Vec::new(),
51 }
52}
53
54#[allow(dead_code)]
55pub fn ib_add(batch: &mut InstanceBatch, id: u32, transform: InstanceTransform) {
56 batch.instances.push(BatchInstance {
57 id,
58 transform,
59 color_tint: [1.0, 1.0, 1.0, 1.0],
60 lod_level: 0,
61 visible: true,
62 });
63}
64
65#[allow(dead_code)]
66pub fn ib_remove(batch: &mut InstanceBatch, id: u32) {
67 batch.instances.retain(|i| i.id != id);
68}
69
70#[allow(dead_code)]
71pub fn ib_set_visible(batch: &mut InstanceBatch, id: u32, vis: bool) {
72 for inst in batch.instances.iter_mut() {
73 if inst.id == id {
74 inst.visible = vis;
75 }
76 }
77}
78
79#[allow(dead_code)]
80pub fn ib_set_tint(batch: &mut InstanceBatch, id: u32, tint: [f32; 4]) {
81 for inst in batch.instances.iter_mut() {
82 if inst.id == id {
83 inst.color_tint = tint;
84 }
85 }
86}
87
88#[allow(dead_code)]
89pub fn ib_count(batch: &InstanceBatch) -> usize {
90 batch.instances.len()
91}
92
93#[allow(dead_code)]
94pub fn ib_visible_count(batch: &InstanceBatch) -> usize {
95 batch.instances.iter().filter(|i| i.visible).count()
96}
97
98#[allow(dead_code)]
99pub fn ib_clear(batch: &mut InstanceBatch) {
100 batch.instances.clear();
101}
102
103#[allow(dead_code)]
105pub fn ib_visible_transforms(batch: &InstanceBatch) -> Vec<InstanceTransform> {
106 batch
107 .instances
108 .iter()
109 .filter(|i| i.visible)
110 .map(|i| i.transform)
111 .collect()
112}
113
114#[allow(dead_code)]
116pub fn ib_memory_bytes(batch: &InstanceBatch) -> usize {
117 batch.instances.len() * 64
118}
119
120#[allow(dead_code)]
121pub fn ib_to_json(batch: &InstanceBatch) -> String {
122 format!(
123 "{{\"mesh_id\":{},\"count\":{},\"visible\":{}}}",
124 batch.mesh_id,
125 ib_count(batch),
126 ib_visible_count(batch)
127 )
128}
129
130#[allow(dead_code)]
132pub fn ib_translation(tx: f32, ty: f32, tz: f32) -> InstanceTransform {
133 let mut t = InstanceTransform::default();
134 t.cols[3] = [tx, ty, tz, 1.0];
135 t
136}
137
138#[cfg(test)]
139mod tests {
140 use super::*;
141
142 #[test]
143 fn empty_batch() {
144 let b = new_instance_batch(1);
145 assert_eq!(ib_count(&b), 0);
146 }
147
148 #[test]
149 fn add_increments_count() {
150 let mut b = new_instance_batch(1);
151 ib_add(&mut b, 1, InstanceTransform::default());
152 assert_eq!(ib_count(&b), 1);
153 }
154
155 #[test]
156 fn remove_by_id() {
157 let mut b = new_instance_batch(1);
158 ib_add(&mut b, 1, InstanceTransform::default());
159 ib_remove(&mut b, 1);
160 assert_eq!(ib_count(&b), 0);
161 }
162
163 #[test]
164 fn set_invisible_reduces_visible_count() {
165 let mut b = new_instance_batch(1);
166 ib_add(&mut b, 1, InstanceTransform::default());
167 ib_set_visible(&mut b, 1, false);
168 assert_eq!(ib_visible_count(&b), 0);
169 }
170
171 #[test]
172 fn visible_transforms_filters() {
173 let mut b = new_instance_batch(1);
174 ib_add(&mut b, 1, InstanceTransform::default());
175 ib_add(&mut b, 2, InstanceTransform::default());
176 ib_set_visible(&mut b, 1, false);
177 assert_eq!(ib_visible_transforms(&b).len(), 1);
178 }
179
180 #[test]
181 fn clear_empties() {
182 let mut b = new_instance_batch(1);
183 ib_add(&mut b, 1, InstanceTransform::default());
184 ib_clear(&mut b);
185 assert_eq!(ib_count(&b), 0);
186 }
187
188 #[test]
189 fn memory_bytes_per_instance() {
190 let mut b = new_instance_batch(1);
191 ib_add(&mut b, 1, InstanceTransform::default());
192 assert_eq!(ib_memory_bytes(&b), 64);
193 }
194
195 #[test]
196 fn translation_sets_last_column() {
197 let t = ib_translation(1.0, 2.0, 3.0);
198 assert!((t.cols[3][0] - 1.0).abs() < 1e-6);
199 assert!((t.cols[3][1] - 2.0).abs() < 1e-6);
200 }
201
202 #[test]
203 fn json_has_mesh_id() {
204 let b = new_instance_batch(42);
205 assert!(ib_to_json(&b).contains("42"));
206 }
207
208 #[test]
209 fn tint_set() {
210 let mut b = new_instance_batch(1);
211 ib_add(&mut b, 1, InstanceTransform::default());
212 ib_set_tint(&mut b, 1, [1.0, 0.0, 0.0, 1.0]);
213 assert!((b.instances[0].color_tint[0] - 1.0).abs() < 1e-6);
214 }
215}