1use std::io::{self, Write};
4
5use flate2::Compression;
6use flate2::write::GzEncoder;
7
8use crate::{
9 EdgeIndices, ExtensionId, QuantizedMeshHeader, QuantizedVertices, TileMetadata, WaterMask,
10};
11
12#[inline]
21pub fn zigzag_encode(value: i32) -> u32 {
22 ((value << 1) ^ (value >> 31)) as u32
23}
24
25#[inline]
27pub fn zigzag_decode(value: u32) -> i32 {
28 ((value >> 1) as i32) ^ (-((value & 1) as i32))
29}
30
31pub fn encode_zigzag_delta(values: &[u16]) -> Vec<u16> {
35 let mut result = Vec::with_capacity(values.len());
36 let mut prev = 0i32;
37
38 for &value in values {
39 let current = value as i32;
40 let delta = current - prev;
41 result.push(zigzag_encode(delta) as u16);
42 prev = current;
43 }
44
45 result
46}
47
48pub fn decode_zigzag_delta(encoded: &[u16]) -> Vec<u16> {
50 let mut result = Vec::with_capacity(encoded.len());
51 let mut value = 0i32;
52
53 for &enc in encoded {
54 let delta = zigzag_decode(enc as u32);
55 value += delta;
56 result.push(value as u16);
57 }
58
59 result
60}
61
62pub fn encode_high_water_mark(indices: &[u32]) -> Vec<u32> {
66 let mut result = Vec::with_capacity(indices.len());
67 let mut highest = 0u32;
68
69 for &index in indices {
70 let code = if index == highest {
71 highest += 1;
72 0
73 } else {
74 highest - index
75 };
76 result.push(code);
77 }
78
79 result
80}
81
82pub fn decode_high_water_mark(encoded: &[u32]) -> Vec<u32> {
84 let mut result = Vec::with_capacity(encoded.len());
85 let mut highest = 0u32;
86
87 for &code in encoded {
88 let index = highest - code;
89 if code == 0 {
90 highest += 1;
91 }
92 result.push(index);
93 }
94
95 result
96}
97
98pub fn oct_encode_normal(normal: [f32; 3]) -> [u8; 2] {
102 let [mut x, mut y, z] = normal;
103
104 let inv_l1 = 1.0 / (x.abs() + y.abs() + z.abs());
106 x *= inv_l1;
107 y *= inv_l1;
108
109 if z < 0.0 {
111 let ox = x;
112 x = (1.0 - y.abs()) * if ox >= 0.0 { 1.0 } else { -1.0 };
113 y = (1.0 - ox.abs()) * if y >= 0.0 { 1.0 } else { -1.0 };
114 }
115
116 let encode = |v: f32| -> u8 { ((v * 0.5 + 0.5) * 255.0).clamp(0.0, 255.0) as u8 };
118
119 [encode(x), encode(y)]
120}
121
122#[derive(Debug, Clone, Default)]
124pub struct EncodeOptions {
125 pub include_normals: bool,
127 pub normals: Option<Vec<[f32; 3]>>,
129 pub include_water_mask: bool,
131 pub water_mask: Option<WaterMask>,
133 pub include_metadata: bool,
135 pub metadata: Option<TileMetadata>,
137 pub compression_level: u32,
139}
140
141pub struct QuantizedMeshEncoder {
145 header: QuantizedMeshHeader,
146 vertices: QuantizedVertices,
147 indices: Vec<u32>,
148 edge_indices: EdgeIndices,
149}
150
151impl QuantizedMeshEncoder {
152 pub fn new(
154 header: QuantizedMeshHeader,
155 vertices: QuantizedVertices,
156 indices: Vec<u32>,
157 edge_indices: EdgeIndices,
158 ) -> Self {
159 Self {
160 header,
161 vertices,
162 indices,
163 edge_indices,
164 }
165 }
166
167 pub fn encode(&self) -> Vec<u8> {
169 self.encode_with_options(&EncodeOptions::default())
170 }
171
172 pub fn encode_with_options(&self, options: &EncodeOptions) -> Vec<u8> {
174 let mut output = Vec::new();
175 self.encode_to_with_options(&mut output, options)
176 .expect("Failed to encode to Vec");
177 output
178 }
179
180 pub fn encode_to<W: Write>(&self, writer: W) -> io::Result<()> {
182 self.encode_to_with_options(writer, &EncodeOptions::default())
183 }
184
185 pub fn encode_to_with_options<W: Write>(
187 &self,
188 mut writer: W,
189 options: &EncodeOptions,
190 ) -> io::Result<()> {
191 if options.compression_level == 0 {
192 self.encode_uncompressed_to(&mut writer, options)
193 } else {
194 let mut encoder = GzEncoder::new(writer, Compression::new(options.compression_level));
196 self.encode_uncompressed_to(&mut encoder, options)?;
197 encoder.finish()?;
198 Ok(())
199 }
200 }
201
202 fn encode_uncompressed_to<W: Write>(
204 &self,
205 writer: &mut W,
206 options: &EncodeOptions,
207 ) -> io::Result<()> {
208 let vertex_count = self.vertices.len();
209 let use_32bit = vertex_count > 65535;
210
211 writer.write_all(&self.header.to_bytes())?;
213
214 writer.write_all(&(vertex_count as u32).to_le_bytes())?;
216
217 let encoded_u = encode_zigzag_delta(&self.vertices.u);
219 let encoded_v = encode_zigzag_delta(&self.vertices.v);
220 let encoded_height = encode_zigzag_delta(&self.vertices.height);
221
222 for &u in &encoded_u {
223 writer.write_all(&u.to_le_bytes())?;
224 }
225 for &v in &encoded_v {
226 writer.write_all(&v.to_le_bytes())?;
227 }
228 for &h in &encoded_height {
229 writer.write_all(&h.to_le_bytes())?;
230 }
231
232 let current_pos = 88 + 4 + vertex_count * 6;
235
236 if use_32bit {
238 let padding = (4 - (current_pos % 4)) % 4;
240 for _ in 0..padding {
241 writer.write_all(&[0])?;
242 }
243 } else {
244 let padding = (2 - (current_pos % 2)) % 2;
246 for _ in 0..padding {
247 writer.write_all(&[0])?;
248 }
249 }
250
251 let triangle_count = self.indices.len() / 3;
253 writer.write_all(&(triangle_count as u32).to_le_bytes())?;
254
255 let encoded_indices = encode_high_water_mark(&self.indices);
257 if use_32bit {
258 for &idx in &encoded_indices {
259 writer.write_all(&idx.to_le_bytes())?;
260 }
261 } else {
262 for &idx in &encoded_indices {
263 writer.write_all(&(idx as u16).to_le_bytes())?;
264 }
265 }
266
267 self.write_edge_indices_to(writer, &self.edge_indices.west, use_32bit)?;
269 self.write_edge_indices_to(writer, &self.edge_indices.south, use_32bit)?;
270 self.write_edge_indices_to(writer, &self.edge_indices.east, use_32bit)?;
271 self.write_edge_indices_to(writer, &self.edge_indices.north, use_32bit)?;
272
273 if options.include_normals
275 && let Some(normals) = &options.normals
276 {
277 self.write_normals_extension_to(writer, normals)?;
278 }
279
280 if options.include_water_mask {
281 let water_mask = options.water_mask.as_ref().cloned().unwrap_or_default();
282 self.write_water_mask_extension_to(writer, &water_mask)?;
283 }
284
285 if options.include_metadata
286 && let Some(metadata) = &options.metadata
287 {
288 self.write_metadata_extension_to(writer, metadata)?;
289 }
290
291 Ok(())
292 }
293
294 fn write_edge_indices_to<W: Write>(
295 &self,
296 writer: &mut W,
297 indices: &[u32],
298 use_32bit: bool,
299 ) -> io::Result<()> {
300 writer.write_all(&(indices.len() as u32).to_le_bytes())?;
301 if use_32bit {
302 for &idx in indices {
303 writer.write_all(&idx.to_le_bytes())?;
304 }
305 } else {
306 for &idx in indices {
307 writer.write_all(&(idx as u16).to_le_bytes())?;
308 }
309 }
310 Ok(())
311 }
312
313 fn write_normals_extension_to<W: Write>(
314 &self,
315 writer: &mut W,
316 normals: &[[f32; 3]],
317 ) -> io::Result<()> {
318 writer.write_all(&[ExtensionId::OctEncodedVertexNormals as u8])?;
320 let length = (normals.len() * 2) as u32;
321 writer.write_all(&length.to_le_bytes())?;
322
323 for &normal in normals {
325 let encoded = oct_encode_normal(normal);
326 writer.write_all(&encoded)?;
327 }
328 Ok(())
329 }
330
331 fn write_water_mask_extension_to<W: Write>(
332 &self,
333 writer: &mut W,
334 water_mask: &WaterMask,
335 ) -> io::Result<()> {
336 writer.write_all(&[ExtensionId::WaterMask as u8])?;
337
338 match water_mask {
339 WaterMask::Uniform(value) => {
340 writer.write_all(&1u32.to_le_bytes())?;
341 writer.write_all(&[*value])?;
342 }
343 WaterMask::Grid(grid) => {
344 writer.write_all(&(256 * 256u32).to_le_bytes())?;
345 writer.write_all(grid.as_ref())?;
346 }
347 }
348 Ok(())
349 }
350
351 fn write_metadata_extension_to<W: Write>(
352 &self,
353 writer: &mut W,
354 metadata: &TileMetadata,
355 ) -> io::Result<()> {
356 let json = serde_json::to_string(metadata)
358 .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
359 let json_bytes = json.as_bytes();
360
361 writer.write_all(&[ExtensionId::Metadata as u8])?;
363
364 let extension_length = 4 + json_bytes.len() as u32;
366 writer.write_all(&extension_length.to_le_bytes())?;
367
368 writer.write_all(&(json_bytes.len() as u32).to_le_bytes())?;
370
371 writer.write_all(json_bytes)?;
373 Ok(())
374 }
375}
376
377#[cfg(test)]
378mod tests {
379 use super::*;
380
381 #[test]
382 fn test_zigzag_encode() {
383 assert_eq!(zigzag_encode(0), 0);
384 assert_eq!(zigzag_encode(-1), 1);
385 assert_eq!(zigzag_encode(1), 2);
386 assert_eq!(zigzag_encode(-2), 3);
387 assert_eq!(zigzag_encode(2), 4);
388 }
389
390 #[test]
391 fn test_zigzag_roundtrip() {
392 for i in -1000..1000 {
393 assert_eq!(zigzag_decode(zigzag_encode(i)), i);
394 }
395 }
396
397 #[test]
398 fn test_zigzag_delta_roundtrip() {
399 let values: Vec<u16> = vec![0, 100, 50, 200, 150, 32767, 0];
400 let encoded = encode_zigzag_delta(&values);
401 let decoded = decode_zigzag_delta(&encoded);
402 assert_eq!(values, decoded);
403 }
404
405 #[test]
406 fn test_high_water_mark_simple() {
407 let indices = vec![0, 1, 2, 3, 4, 5];
409 let encoded = encode_high_water_mark(&indices);
410 assert_eq!(encoded, vec![0, 0, 0, 0, 0, 0]);
412 }
413
414 #[test]
415 fn test_high_water_mark_roundtrip() {
416 let indices = vec![0, 1, 2, 1, 3, 2, 0, 4, 3];
417 let encoded = encode_high_water_mark(&indices);
418 let decoded = decode_high_water_mark(&encoded);
419 assert_eq!(indices, decoded);
420 }
421
422 #[test]
423 fn test_oct_encode_normal() {
424 let up = [0.0f32, 0.0, 1.0];
426 let encoded = oct_encode_normal(up);
427 assert!((encoded[0] as i32 - 127).abs() < 2);
429 assert!((encoded[1] as i32 - 127).abs() < 2);
430
431 let down = [0.0f32, 0.0, -1.0];
433 let encoded = oct_encode_normal(down);
434 assert!(encoded[0] == 0 || encoded[0] == 255);
436 }
437
438 #[test]
439 fn test_encoder_basic() {
440 let header = QuantizedMeshHeader::default();
441 let vertices = QuantizedVertices {
442 u: vec![0, 32767, 0, 32767],
443 v: vec![0, 0, 32767, 32767],
444 height: vec![0, 0, 0, 0],
445 };
446 let indices = vec![0, 1, 2, 1, 3, 2];
447 let edge_indices = EdgeIndices::from_vertices(&vertices);
448
449 let encoder = QuantizedMeshEncoder::new(header, vertices, indices, edge_indices);
450 let data = encoder.encode_with_options(&EncodeOptions {
451 compression_level: 0,
452 ..Default::default()
453 });
454
455 assert!(data.len() > 88);
457
458 let parsed_header = QuantizedMeshHeader::from_bytes(&data).unwrap();
460 assert_eq!(parsed_header.min_height, 0.0);
461 }
462
463 #[test]
464 fn test_encoder_with_compression() {
465 let header = QuantizedMeshHeader::default();
466 let vertices = QuantizedVertices {
467 u: vec![0, 32767, 0, 32767],
468 v: vec![0, 0, 32767, 32767],
469 height: vec![0, 0, 0, 0],
470 };
471 let indices = vec![0, 1, 2, 1, 3, 2];
472 let edge_indices = EdgeIndices::from_vertices(&vertices);
473
474 let encoder = QuantizedMeshEncoder::new(header, vertices, indices, edge_indices);
475
476 let _uncompressed = encoder.encode_with_options(&EncodeOptions {
477 compression_level: 0,
478 ..Default::default()
479 });
480
481 let compressed = encoder.encode_with_options(&EncodeOptions {
482 compression_level: 6,
483 ..Default::default()
484 });
485
486 assert_eq!(&compressed[0..2], &[0x1f, 0x8b]); }
489
490 #[test]
491 fn test_encoder_with_extensions() {
492 let header = QuantizedMeshHeader::default();
493 let vertices = QuantizedVertices {
494 u: vec![0, 32767, 0, 32767],
495 v: vec![0, 0, 32767, 32767],
496 height: vec![0, 0, 0, 0],
497 };
498 let indices = vec![0, 1, 2, 1, 3, 2];
499 let edge_indices = EdgeIndices::from_vertices(&vertices);
500
501 let encoder = QuantizedMeshEncoder::new(header, vertices, indices, edge_indices);
502
503 let normals = vec![[0.0, 0.0, 1.0]; 4];
504
505 let data = encoder.encode_with_options(&EncodeOptions {
506 compression_level: 0,
507 include_normals: true,
508 normals: Some(normals),
509 include_water_mask: true,
510 water_mask: Some(WaterMask::Uniform(0)),
511 ..Default::default()
512 });
513
514 let without_ext = encoder.encode_with_options(&EncodeOptions {
516 compression_level: 0,
517 ..Default::default()
518 });
519
520 assert!(data.len() > without_ext.len());
521 }
522
523 #[test]
524 fn test_encode_to_writer() {
525 let header = QuantizedMeshHeader::default();
526 let vertices = QuantizedVertices {
527 u: vec![0, 32767, 0, 32767],
528 v: vec![0, 0, 32767, 32767],
529 height: vec![0, 0, 0, 0],
530 };
531 let indices = vec![0, 1, 2, 1, 3, 2];
532 let edge_indices = EdgeIndices::from_vertices(&vertices);
533
534 let encoder = QuantizedMeshEncoder::new(header, vertices, indices, edge_indices);
535
536 let data_vec = encoder.encode_with_options(&EncodeOptions {
538 compression_level: 0,
539 ..Default::default()
540 });
541
542 let mut data_writer = Vec::new();
544 encoder
545 .encode_to_with_options(
546 &mut data_writer,
547 &EncodeOptions {
548 compression_level: 0,
549 ..Default::default()
550 },
551 )
552 .expect("Failed to encode to writer");
553
554 assert_eq!(data_vec, data_writer);
556 }
557
558 #[test]
559 fn test_encode_to_writer_compressed() {
560 let header = QuantizedMeshHeader::default();
561 let vertices = QuantizedVertices {
562 u: vec![0, 32767, 0, 32767],
563 v: vec![0, 0, 32767, 32767],
564 height: vec![0, 0, 0, 0],
565 };
566 let indices = vec![0, 1, 2, 1, 3, 2];
567 let edge_indices = EdgeIndices::from_vertices(&vertices);
568
569 let encoder = QuantizedMeshEncoder::new(header, vertices, indices, edge_indices);
570
571 let mut data_writer = Vec::new();
573 encoder
574 .encode_to_with_options(
575 &mut data_writer,
576 &EncodeOptions {
577 compression_level: 6,
578 ..Default::default()
579 },
580 )
581 .expect("Failed to encode to writer");
582
583 assert_eq!(&data_writer[0..2], &[0x1f, 0x8b]);
585 }
586}