1use std::io::{self, Read};
14
15use flate2::read::GzDecoder;
16
17use crate::{
18 EdgeIndices, QuantizedMeshHeader, QuantizedVertices, TileMetadata, WaterMask, zigzag_decode,
19};
20
21#[derive(Debug)]
23pub enum DecodeError {
24 UnexpectedEof,
26 InvalidData(String),
28 DecompressionError(String),
30 JsonError(String),
32 IoError(io::Error),
34}
35
36impl std::fmt::Display for DecodeError {
37 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38 match self {
39 DecodeError::UnexpectedEof => write!(f, "Unexpected end of data"),
40 DecodeError::InvalidData(msg) => write!(f, "Invalid data: {msg}"),
41 DecodeError::DecompressionError(msg) => write!(f, "Decompression error: {msg}"),
42 DecodeError::JsonError(msg) => write!(f, "JSON error: {msg}"),
43 DecodeError::IoError(err) => write!(f, "IO error: {err}"),
44 }
45 }
46}
47
48impl std::error::Error for DecodeError {}
49
50impl From<io::Error> for DecodeError {
51 fn from(err: io::Error) -> Self {
52 if err.kind() == io::ErrorKind::UnexpectedEof {
53 DecodeError::UnexpectedEof
54 } else {
55 DecodeError::IoError(err)
56 }
57 }
58}
59
60pub type DecodeResult<T> = Result<T, DecodeError>;
62
63#[derive(Debug, Clone, Copy)]
73pub enum IndicesView<'a> {
74 U16(&'a [u8]),
76 U32(&'a [u8]),
78}
79
80impl<'a> IndicesView<'a> {
81 #[inline]
83 pub fn len(&self) -> usize {
84 match self {
85 Self::U16(b) => b.len() / 2,
86 Self::U32(b) => b.len() / 4,
87 }
88 }
89
90 #[inline]
92 pub fn is_empty(&self) -> bool {
93 self.len() == 0
94 }
95
96 pub fn iter_raw(&self) -> RawIndexIter<'a> {
98 match self {
99 Self::U16(b) => RawIndexIter::U16(b.chunks_exact(2)),
100 Self::U32(b) => RawIndexIter::U32(b.chunks_exact(4)),
101 }
102 }
103
104 pub fn iter(&self) -> HighWaterMarkIter<RawIndexIter<'a>> {
106 HighWaterMarkIter::new(self.iter_raw())
107 }
108
109 pub fn to_vec(&self) -> Vec<u32> {
111 let mut out = Vec::with_capacity(self.len());
112 out.extend(self.iter());
113 out
114 }
115}
116
117pub enum RawIndexIter<'a> {
119 U16(std::slice::ChunksExact<'a, u8>),
121 U32(std::slice::ChunksExact<'a, u8>),
123}
124
125impl<'a> Iterator for RawIndexIter<'a> {
126 type Item = u32;
127
128 #[inline]
129 fn next(&mut self) -> Option<u32> {
130 match self {
131 Self::U16(it) => it.next().map(|c| u16::from_le_bytes([c[0], c[1]]) as u32),
132 Self::U32(it) => it
133 .next()
134 .map(|c| u32::from_le_bytes([c[0], c[1], c[2], c[3]])),
135 }
136 }
137
138 fn size_hint(&self) -> (usize, Option<usize>) {
139 match self {
140 Self::U16(it) => it.size_hint(),
141 Self::U32(it) => it.size_hint(),
142 }
143 }
144}
145
146impl<'a> ExactSizeIterator for RawIndexIter<'a> {}
147
148pub struct ZigzagDeltaIter<'a> {
151 chunks: std::slice::ChunksExact<'a, u8>,
152 state: i32,
153}
154
155impl<'a> ZigzagDeltaIter<'a> {
156 #[inline]
159 pub fn new(bytes: &'a [u8]) -> Self {
160 Self {
161 chunks: bytes.chunks_exact(2),
162 state: 0,
163 }
164 }
165}
166
167impl<'a> Iterator for ZigzagDeltaIter<'a> {
168 type Item = u16;
169
170 #[inline]
171 fn next(&mut self) -> Option<u16> {
172 let chunk = self.chunks.next()?;
173 let enc = u16::from_le_bytes([chunk[0], chunk[1]]) as u32;
174 let delta = zigzag_decode(enc);
175 self.state = self.state.wrapping_add(delta);
176 Some(self.state as u16)
177 }
178
179 fn size_hint(&self) -> (usize, Option<usize>) {
180 self.chunks.size_hint()
181 }
182}
183
184impl<'a> ExactSizeIterator for ZigzagDeltaIter<'a> {}
185
186pub struct HighWaterMarkIter<I> {
189 inner: I,
190 highest: u32,
191}
192
193impl<I> HighWaterMarkIter<I> {
194 #[inline]
196 pub fn new(inner: I) -> Self {
197 Self { inner, highest: 0 }
198 }
199}
200
201impl<I: Iterator<Item = u32>> Iterator for HighWaterMarkIter<I> {
202 type Item = u32;
203
204 #[inline]
205 fn next(&mut self) -> Option<u32> {
206 let code = self.inner.next()?;
207 let index = self.highest.wrapping_sub(code);
208 if code == 0 {
209 self.highest = self.highest.wrapping_add(1);
210 }
211 Some(index)
212 }
213
214 fn size_hint(&self) -> (usize, Option<usize>) {
215 self.inner.size_hint()
216 }
217}
218
219impl<I: Iterator<Item = u32> + ExactSizeIterator> ExactSizeIterator for HighWaterMarkIter<I> {}
220
221#[derive(Debug, Clone, Copy)]
223pub enum WaterMaskView<'a> {
224 Uniform(u8),
226 Grid(&'a [u8; 256 * 256]),
228}
229
230impl<'a> WaterMaskView<'a> {
231 pub fn to_owned(self) -> WaterMask {
233 match self {
234 Self::Uniform(v) => WaterMask::Uniform(v),
235 Self::Grid(g) => {
236 let mut owned = Box::new([0u8; 256 * 256]);
237 owned.copy_from_slice(g.as_ref());
238 WaterMask::Grid(owned)
239 }
240 }
241 }
242}
243
244#[derive(Debug, Clone, Copy, Default)]
246pub struct ExtensionsView<'a> {
247 pub normals_oct: Option<&'a [u8]>,
250 pub water_mask: Option<WaterMaskView<'a>>,
252 pub metadata_json: Option<&'a str>,
255}
256
257impl<'a> ExtensionsView<'a> {
258 pub fn to_owned(&self) -> DecodeResult<DecodedExtensions> {
260 Ok(DecodedExtensions {
261 normals: self
262 .normals_oct
263 .map(|b| iter_oct_normals(b).collect::<Vec<_>>()),
264 water_mask: self.water_mask.map(|w| w.to_owned()),
265 metadata: self
266 .metadata_json
267 .map(serde_json::from_str::<TileMetadata>)
268 .transpose()
269 .map_err(|e| DecodeError::JsonError(e.to_string()))?,
270 })
271 }
272}
273
274pub fn iter_oct_normals(bytes: &[u8]) -> impl Iterator<Item = [f32; 3]> + '_ {
276 bytes
277 .chunks_exact(2)
278 .map(|c| oct_decode_normal([c[0], c[1]]))
279}
280
281#[derive(Debug, Clone, Copy)]
287pub struct QuantizedMeshView<'a> {
288 pub header: QuantizedMeshHeader,
290 pub vertex_count: u32,
292 pub use_32bit_indices: bool,
294 pub triangle_count: u32,
296
297 pub encoded_u_bytes: &'a [u8],
299 pub encoded_v_bytes: &'a [u8],
301 pub encoded_height_bytes: &'a [u8],
303
304 pub indices: IndicesView<'a>,
306 pub edge_west: IndicesView<'a>,
308 pub edge_south: IndicesView<'a>,
310 pub edge_east: IndicesView<'a>,
312 pub edge_north: IndicesView<'a>,
314
315 pub extensions: ExtensionsView<'a>,
317}
318
319impl<'a> QuantizedMeshView<'a> {
320 pub fn parse(data: &'a [u8]) -> DecodeResult<Self> {
322 let mut cur = Cursor::new(data);
323 let header = QuantizedMeshHeader::from_bytes(cur.take(88)?)
324 .ok_or_else(|| DecodeError::InvalidData("Invalid header".to_string()))?;
325
326 let vertex_count = cur.read_u32()?;
327 let use_32bit = vertex_count > 65535;
328 let vc = vertex_count as usize;
329
330 let encoded_u_bytes = cur.take(vc * 2)?;
331 let encoded_v_bytes = cur.take(vc * 2)?;
332 let encoded_height_bytes = cur.take(vc * 2)?;
333
334 cur.align_to(if use_32bit { 4 } else { 2 });
335
336 let triangle_count = cur.read_u32()?;
337 let index_stride = if use_32bit { 4 } else { 2 };
338 let index_bytes = cur.take(triangle_count as usize * 3 * index_stride)?;
339 let indices = if use_32bit {
340 IndicesView::U32(index_bytes)
341 } else {
342 IndicesView::U16(index_bytes)
343 };
344
345 let edge_west = read_edge_indices(&mut cur, use_32bit)?;
346 let edge_south = read_edge_indices(&mut cur, use_32bit)?;
347 let edge_east = read_edge_indices(&mut cur, use_32bit)?;
348 let edge_north = read_edge_indices(&mut cur, use_32bit)?;
349
350 let extensions = parse_extensions(&mut cur, vc)?;
351
352 Ok(Self {
353 header,
354 vertex_count,
355 use_32bit_indices: use_32bit,
356 triangle_count,
357 encoded_u_bytes,
358 encoded_v_bytes,
359 encoded_height_bytes,
360 indices,
361 edge_west,
362 edge_south,
363 edge_east,
364 edge_north,
365 extensions,
366 })
367 }
368
369 #[inline]
371 pub fn iter_u(&self) -> ZigzagDeltaIter<'a> {
372 ZigzagDeltaIter::new(self.encoded_u_bytes)
373 }
374
375 #[inline]
377 pub fn iter_v(&self) -> ZigzagDeltaIter<'a> {
378 ZigzagDeltaIter::new(self.encoded_v_bytes)
379 }
380
381 #[inline]
383 pub fn iter_height(&self) -> ZigzagDeltaIter<'a> {
384 ZigzagDeltaIter::new(self.encoded_height_bytes)
385 }
386
387 pub fn into_owned(self) -> DecodeResult<DecodedMesh> {
389 let vertices = QuantizedVertices {
390 u: self.iter_u().collect(),
391 v: self.iter_v().collect(),
392 height: self.iter_height().collect(),
393 };
394 let indices = self.indices.to_vec();
395 let edge_indices = EdgeIndices {
396 west: self.edge_west.iter_raw().collect(),
397 south: self.edge_south.iter_raw().collect(),
398 east: self.edge_east.iter_raw().collect(),
399 north: self.edge_north.iter_raw().collect(),
400 };
401 let extensions = self.extensions.to_owned()?;
402 Ok(DecodedMesh {
403 header: self.header,
404 vertices,
405 indices,
406 edge_indices,
407 extensions,
408 })
409 }
410}
411
412fn read_edge_indices<'a>(cur: &mut Cursor<'a>, use_32bit: bool) -> DecodeResult<IndicesView<'a>> {
413 let count = cur.read_u32()? as usize;
414 let stride = if use_32bit { 4 } else { 2 };
415 let bytes = cur.take(count * stride)?;
416 Ok(if use_32bit {
417 IndicesView::U32(bytes)
418 } else {
419 IndicesView::U16(bytes)
420 })
421}
422
423fn parse_extensions<'a>(
424 cur: &mut Cursor<'a>,
425 vertex_count: usize,
426) -> DecodeResult<ExtensionsView<'a>> {
427 let mut ext = ExtensionsView::default();
428 while cur.remaining() >= 5 {
429 let id = cur.read_u8()?;
430 let length = cur.read_u32()? as usize;
431 if cur.remaining() < length {
432 break;
434 }
435 let payload = cur.take(length)?;
436 match id {
437 1 => {
438 let want = vertex_count * 2;
440 let bytes = if payload.len() >= want {
441 &payload[..want]
442 } else {
443 payload
444 };
445 ext.normals_oct = Some(bytes);
446 }
447 2 => {
448 ext.water_mask = Some(match length {
449 1 => WaterMaskView::Uniform(payload[0]),
450 n if n == 256 * 256 => {
451 let arr: &[u8; 256 * 256] = payload
452 .try_into()
453 .map_err(|_| DecodeError::InvalidData("water mask size".into()))?;
454 WaterMaskView::Grid(arr)
455 }
456 _ => WaterMaskView::Uniform(0),
457 });
458 }
459 4 => {
460 if payload.len() < 4 {
461 return Err(DecodeError::UnexpectedEof);
462 }
463 let json_len =
464 u32::from_le_bytes([payload[0], payload[1], payload[2], payload[3]]) as usize;
465 if payload.len() < 4 + json_len {
466 return Err(DecodeError::UnexpectedEof);
467 }
468 let json_bytes = &payload[4..4 + json_len];
469 let json_str = std::str::from_utf8(json_bytes)
470 .map_err(|e| DecodeError::JsonError(e.to_string()))?;
471 ext.metadata_json = Some(json_str);
472 }
473 _ => {} }
475 }
476 Ok(ext)
477}
478
479#[derive(Debug, Clone, Default)]
485pub struct DecodedExtensions {
486 pub normals: Option<Vec<[f32; 3]>>,
488 pub water_mask: Option<WaterMask>,
490 pub metadata: Option<TileMetadata>,
492}
493
494#[derive(Debug, Clone)]
496pub struct DecodedMesh {
497 pub header: QuantizedMeshHeader,
499 pub vertices: QuantizedVertices,
501 pub indices: Vec<u32>,
503 pub edge_indices: EdgeIndices,
505 pub extensions: DecodedExtensions,
507}
508
509impl DecodedMesh {
510 pub fn decode(data: &[u8]) -> DecodeResult<Self> {
513 if is_gzip(data) {
514 let mut decompressed = Vec::new();
515 GzDecoder::new(data)
516 .read_to_end(&mut decompressed)
517 .map_err(|e| DecodeError::DecompressionError(e.to_string()))?;
518 QuantizedMeshView::parse(&decompressed)?.into_owned()
519 } else {
520 QuantizedMeshView::parse(data)?.into_owned()
521 }
522 }
523
524 pub fn decode_from<R: Read>(mut reader: R) -> DecodeResult<Self> {
526 let mut buf = Vec::new();
527 reader.read_to_end(&mut buf)?;
528 Self::decode(&buf)
529 }
530}
531
532#[inline]
534pub fn is_gzip(data: &[u8]) -> bool {
535 data.len() >= 2 && data[0] == 0x1f && data[1] == 0x8b
536}
537
538pub fn decompress_gzip(data: &[u8]) -> DecodeResult<Vec<u8>> {
541 if is_gzip(data) {
542 let mut out = Vec::new();
543 GzDecoder::new(data)
544 .read_to_end(&mut out)
545 .map_err(|e| DecodeError::DecompressionError(e.to_string()))?;
546 Ok(out)
547 } else {
548 Ok(data.to_vec())
549 }
550}
551
552struct Cursor<'a> {
557 data: &'a [u8],
558 offset: usize,
559}
560
561impl<'a> Cursor<'a> {
562 fn new(data: &'a [u8]) -> Self {
563 Self { data, offset: 0 }
564 }
565
566 #[inline]
567 fn remaining(&self) -> usize {
568 self.data.len().saturating_sub(self.offset)
569 }
570
571 fn take(&mut self, n: usize) -> DecodeResult<&'a [u8]> {
572 if self.remaining() < n {
573 return Err(DecodeError::UnexpectedEof);
574 }
575 let slice = &self.data[self.offset..self.offset + n];
576 self.offset += n;
577 Ok(slice)
578 }
579
580 fn read_u8(&mut self) -> DecodeResult<u8> {
581 Ok(self.take(1)?[0])
582 }
583
584 fn read_u32(&mut self) -> DecodeResult<u32> {
585 let b = self.take(4)?;
586 Ok(u32::from_le_bytes([b[0], b[1], b[2], b[3]]))
587 }
588
589 fn align_to(&mut self, alignment: usize) {
590 let rem = self.offset % alignment;
591 if rem != 0 {
592 self.offset += alignment - rem;
593 }
594 }
595}
596
597pub fn oct_decode_normal(encoded: [u8; 2]) -> [f32; 3] {
605 let mut x = (encoded[0] as f32 / 255.0) * 2.0 - 1.0;
606 let mut y = (encoded[1] as f32 / 255.0) * 2.0 - 1.0;
607 let z = 1.0 - x.abs() - y.abs();
608 if z < 0.0 {
609 let ox = x;
610 x = (1.0 - y.abs()) * if ox >= 0.0 { 1.0 } else { -1.0 };
611 y = (1.0 - ox.abs()) * if y >= 0.0 { 1.0 } else { -1.0 };
612 }
613 let len = (x * x + y * y + z * z).sqrt();
614 if len > 0.0 {
615 [x / len, y / len, z / len]
616 } else {
617 [0.0, 0.0, 1.0]
618 }
619}
620
621#[cfg(test)]
622mod tests {
623 use super::*;
624 use crate::{EncodeOptions, QuantizedMeshEncoder, oct_encode_normal};
625
626 fn sample_mesh() -> (
627 QuantizedMeshHeader,
628 QuantizedVertices,
629 Vec<u32>,
630 EdgeIndices,
631 ) {
632 let header = QuantizedMeshHeader::default();
633 let vertices = QuantizedVertices {
634 u: vec![0, 32767, 0, 32767],
635 v: vec![0, 0, 32767, 32767],
636 height: vec![0, 0, 0, 0],
637 };
638 let indices = vec![0, 1, 2, 1, 3, 2];
639 let edge_indices = EdgeIndices::from_vertices(&vertices);
640 (header, vertices, indices, edge_indices)
641 }
642
643 #[test]
644 fn test_oct_decode_normal_roundtrip() {
645 let test_normals = [
646 [0.0f32, 0.0, 1.0],
647 [0.0, 0.0, -1.0],
648 [1.0, 0.0, 0.0],
649 [0.0, 1.0, 0.0],
650 [0.577, 0.577, 0.577],
651 ];
652 for normal in test_normals {
653 let encoded = oct_encode_normal(normal);
654 let decoded = oct_decode_normal(encoded);
655 let dot = normal[0] * decoded[0] + normal[1] * decoded[1] + normal[2] * decoded[2];
656 assert!(dot > 0.95, "{normal:?} → {encoded:?} → {decoded:?}");
657 }
658 }
659
660 #[test]
661 fn view_parses_uncompressed_mesh() {
662 let (header, vertices, indices, edge_indices) = sample_mesh();
663 let encoder = QuantizedMeshEncoder::new(
664 header,
665 vertices.clone(),
666 indices.clone(),
667 edge_indices.clone(),
668 );
669 let encoded = encoder.encode_with_options(&EncodeOptions {
670 compression_level: 0,
671 ..Default::default()
672 });
673
674 let view = QuantizedMeshView::parse(&encoded).expect("parse");
675 assert_eq!(view.vertex_count as usize, vertices.u.len());
676 assert_eq!(view.triangle_count as usize * 3, indices.len());
677
678 let u: Vec<u16> = view.iter_u().collect();
679 let v: Vec<u16> = view.iter_v().collect();
680 let h: Vec<u16> = view.iter_height().collect();
681 assert_eq!(u, vertices.u);
682 assert_eq!(v, vertices.v);
683 assert_eq!(h, vertices.height);
684
685 let idx: Vec<u32> = view.indices.iter().collect();
686 assert_eq!(idx, indices);
687 }
688
689 #[test]
690 fn owned_decode_roundtrips() {
691 let (header, vertices, indices, edge_indices) = sample_mesh();
692 let encoder = QuantizedMeshEncoder::new(
693 header,
694 vertices.clone(),
695 indices.clone(),
696 edge_indices.clone(),
697 );
698 let encoded = encoder.encode_with_options(&EncodeOptions {
699 compression_level: 0,
700 ..Default::default()
701 });
702
703 let decoded = DecodedMesh::decode(&encoded).expect("decode");
704 assert_eq!(decoded.header.min_height, header.min_height);
705 assert_eq!(decoded.vertices.u, vertices.u);
706 assert_eq!(decoded.vertices.v, vertices.v);
707 assert_eq!(decoded.vertices.height, vertices.height);
708 assert_eq!(decoded.indices, indices);
709 assert_eq!(decoded.edge_indices.west, edge_indices.west);
710 assert_eq!(decoded.edge_indices.south, edge_indices.south);
711 assert_eq!(decoded.edge_indices.east, edge_indices.east);
712 assert_eq!(decoded.edge_indices.north, edge_indices.north);
713 }
714
715 #[test]
716 fn owned_decode_handles_gzip() {
717 let (header, vertices, indices, edge_indices) = sample_mesh();
718 let encoder =
719 QuantizedMeshEncoder::new(header, vertices.clone(), indices.clone(), edge_indices);
720 let encoded = encoder.encode_with_options(&EncodeOptions {
721 compression_level: 6,
722 ..Default::default()
723 });
724 assert_eq!(&encoded[0..2], &[0x1f, 0x8b]);
725
726 let decoded = DecodedMesh::decode(&encoded).expect("decode");
727 assert_eq!(decoded.vertices.u, vertices.u);
728 assert_eq!(decoded.indices, indices);
729 }
730
731 #[test]
732 fn owned_decode_with_extensions() {
733 let (header, vertices, indices, edge_indices) = sample_mesh();
734 let normals = vec![[0.0_f32, 0.0, 1.0]; 4];
735 let encoder = QuantizedMeshEncoder::new(header, vertices.clone(), indices, edge_indices);
736 let encoded = encoder.encode_with_options(&EncodeOptions {
737 compression_level: 0,
738 include_normals: true,
739 normals: Some(normals),
740 include_water_mask: true,
741 water_mask: Some(WaterMask::Uniform(128)),
742 ..Default::default()
743 });
744
745 let decoded = DecodedMesh::decode(&encoded).expect("decode");
746 let ns = decoded.extensions.normals.expect("normals");
747 assert_eq!(ns.len(), 4);
748 for n in ns {
749 assert!(n[2] > 0.9);
750 }
751 match decoded.extensions.water_mask.expect("water mask") {
752 WaterMask::Uniform(v) => assert_eq!(v, 128),
753 _ => panic!("expected uniform"),
754 }
755 }
756
757 #[test]
758 fn owned_decode_from_reader_handles_gzip() {
759 use std::io::Cursor;
760 let (header, vertices, indices, edge_indices) = sample_mesh();
761 let encoder =
762 QuantizedMeshEncoder::new(header, vertices.clone(), indices.clone(), edge_indices);
763 let encoded = encoder.encode_with_options(&EncodeOptions {
764 compression_level: 6,
765 ..Default::default()
766 });
767 let decoded = DecodedMesh::decode_from(Cursor::new(encoded)).expect("decode");
768 assert_eq!(decoded.vertices.u, vertices.u);
769 assert_eq!(decoded.indices, indices);
770 }
771}