Skip to main content

quantized_mesh/
decoding.rs

1//! Decoding functions and main decoder for quantized-mesh format.
2
3use std::io::{self, BufReader, Read};
4
5use flate2::read::GzDecoder;
6
7use crate::{
8    EdgeIndices, QuantizedMeshHeader, QuantizedVertices, TileMetadata, WaterMask,
9    decode_high_water_mark, decode_zigzag_delta,
10};
11
12/// Error type for quantized-mesh decoding.
13#[derive(Debug)]
14pub enum DecodeError {
15    /// Input data is too short.
16    UnexpectedEof,
17    /// Invalid or corrupted data.
18    InvalidData(String),
19    /// Gzip decompression failed.
20    DecompressionError(String),
21    /// JSON parsing failed for metadata extension.
22    JsonError(String),
23    /// IO error.
24    IoError(io::Error),
25}
26
27impl std::fmt::Display for DecodeError {
28    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29        match self {
30            DecodeError::UnexpectedEof => write!(f, "Unexpected end of data"),
31            DecodeError::InvalidData(msg) => write!(f, "Invalid data: {}", msg),
32            DecodeError::DecompressionError(msg) => write!(f, "Decompression error: {}", msg),
33            DecodeError::JsonError(msg) => write!(f, "JSON error: {}", msg),
34            DecodeError::IoError(err) => write!(f, "IO error: {}", err),
35        }
36    }
37}
38
39impl std::error::Error for DecodeError {}
40
41impl From<io::Error> for DecodeError {
42    fn from(err: io::Error) -> Self {
43        if err.kind() == io::ErrorKind::UnexpectedEof {
44            DecodeError::UnexpectedEof
45        } else {
46            DecodeError::IoError(err)
47        }
48    }
49}
50
51/// Result type for quantized-mesh decoding.
52pub type DecodeResult<T> = Result<T, DecodeError>;
53
54/// Decoded extensions from quantized-mesh format.
55#[derive(Debug, Clone, Default)]
56pub struct DecodedExtensions {
57    /// Oct-decoded per-vertex normals (if present).
58    pub normals: Option<Vec<[f32; 3]>>,
59    /// Water mask (if present).
60    pub water_mask: Option<WaterMask>,
61    /// Metadata (if present).
62    pub metadata: Option<TileMetadata>,
63}
64
65/// Decoded quantized-mesh data.
66#[derive(Debug, Clone)]
67pub struct DecodedMesh {
68    /// Header with tile metadata.
69    pub header: QuantizedMeshHeader,
70    /// Quantized vertex data.
71    pub vertices: QuantizedVertices,
72    /// Triangle indices.
73    pub indices: Vec<u32>,
74    /// Edge indices for skirt generation.
75    pub edge_indices: EdgeIndices,
76    /// Decoded extensions.
77    pub extensions: DecodedExtensions,
78}
79
80/// Quantized mesh decoder.
81///
82/// Decodes terrain mesh data from the quantized-mesh-1.0 format.
83pub struct QuantizedMeshDecoder<'a> {
84    data: &'a [u8],
85    offset: usize,
86}
87
88impl<'a> QuantizedMeshDecoder<'a> {
89    /// Create a new decoder from raw bytes.
90    ///
91    /// Automatically detects and handles gzip compression.
92    pub fn new(data: &'a [u8]) -> Self {
93        Self { data, offset: 0 }
94    }
95
96    /// Decode the quantized-mesh data from a byte slice.
97    ///
98    /// If the data is gzip compressed, it will be decompressed first.
99    pub fn decode(data: &[u8]) -> DecodeResult<DecodedMesh> {
100        // Check for gzip magic number
101        let decompressed: Vec<u8>;
102        let data = if data.len() >= 2 && data[0] == 0x1f && data[1] == 0x8b {
103            // Gzip compressed
104            let mut decoder = GzDecoder::new(data);
105            decompressed = Vec::new();
106            let mut buf = decompressed;
107            decoder
108                .read_to_end(&mut buf)
109                .map_err(|e| DecodeError::DecompressionError(e.to_string()))?;
110            buf
111        } else {
112            data.to_vec()
113        };
114
115        let mut decoder = QuantizedMeshDecoder::new(&data);
116        decoder.decode_internal()
117    }
118
119    /// Decode the quantized-mesh data from a reader.
120    ///
121    /// If the data is gzip compressed, it will be decompressed first.
122    /// The reader will be read to the end.
123    pub fn decode_from<R: Read>(reader: R) -> DecodeResult<DecodedMesh> {
124        let mut reader = BufReader::new(reader);
125
126        // Read first two bytes to check for gzip magic
127        let mut magic = [0u8; 2];
128        reader.read_exact(&mut magic)?;
129
130        // Read the rest of the data
131        let mut rest = Vec::new();
132        reader.read_to_end(&mut rest)?;
133
134        // Prepend magic bytes
135        let mut data = magic.to_vec();
136        data.extend(rest);
137
138        // Check for gzip magic number
139        let decompressed = if magic[0] == 0x1f && magic[1] == 0x8b {
140            // Gzip compressed
141            let mut decoder = GzDecoder::new(data.as_slice());
142            let mut buf = Vec::new();
143            decoder
144                .read_to_end(&mut buf)
145                .map_err(|e| DecodeError::DecompressionError(e.to_string()))?;
146            buf
147        } else {
148            data
149        };
150
151        let mut decoder = QuantizedMeshDecoder::new(&decompressed);
152        decoder.decode_internal()
153    }
154
155    fn decode_internal(&mut self) -> DecodeResult<DecodedMesh> {
156        // Read header (88 bytes)
157        let header = self.read_header()?;
158
159        // Read vertex count
160        let vertex_count = self.read_u32()? as usize;
161        let use_32bit = vertex_count > 65535;
162
163        // Read encoded vertex data
164        let encoded_u = self.read_u16_array(vertex_count)?;
165        let encoded_v = self.read_u16_array(vertex_count)?;
166        let encoded_height = self.read_u16_array(vertex_count)?;
167
168        // Decode vertices
169        let u = decode_zigzag_delta(&encoded_u);
170        let v = decode_zigzag_delta(&encoded_v);
171        let height = decode_zigzag_delta(&encoded_height);
172
173        let vertices = QuantizedVertices { u, v, height };
174
175        // Align for index reading
176        if use_32bit {
177            self.align_to(4);
178        } else {
179            self.align_to(2);
180        }
181
182        // Read triangle count
183        let triangle_count = self.read_u32()? as usize;
184        let index_count = triangle_count * 3;
185
186        // Read encoded indices
187        let encoded_indices = if use_32bit {
188            self.read_u32_array(index_count)?
189        } else {
190            self.read_u16_array(index_count)?
191                .into_iter()
192                .map(|x| x as u32)
193                .collect()
194        };
195
196        // Decode indices
197        let indices = decode_high_water_mark(&encoded_indices);
198
199        // Read edge indices
200        let west = self.read_edge_indices(use_32bit)?;
201        let south = self.read_edge_indices(use_32bit)?;
202        let east = self.read_edge_indices(use_32bit)?;
203        let north = self.read_edge_indices(use_32bit)?;
204
205        let edge_indices = EdgeIndices {
206            west,
207            south,
208            east,
209            north,
210        };
211
212        // Read extensions (if any remaining data)
213        let extensions = self.read_extensions(vertex_count)?;
214
215        Ok(DecodedMesh {
216            header,
217            vertices,
218            indices,
219            edge_indices,
220            extensions,
221        })
222    }
223
224    fn read_header(&mut self) -> DecodeResult<QuantizedMeshHeader> {
225        if self.remaining() < 88 {
226            return Err(DecodeError::UnexpectedEof);
227        }
228
229        let header = QuantizedMeshHeader::from_bytes(&self.data[self.offset..])
230            .ok_or_else(|| DecodeError::InvalidData("Invalid header".to_string()))?;
231
232        self.offset += 88;
233        Ok(header)
234    }
235
236    fn read_u16(&mut self) -> DecodeResult<u16> {
237        if self.remaining() < 2 {
238            return Err(DecodeError::UnexpectedEof);
239        }
240        let value = u16::from_le_bytes([self.data[self.offset], self.data[self.offset + 1]]);
241        self.offset += 2;
242        Ok(value)
243    }
244
245    fn read_u32(&mut self) -> DecodeResult<u32> {
246        if self.remaining() < 4 {
247            return Err(DecodeError::UnexpectedEof);
248        }
249        let value = u32::from_le_bytes([
250            self.data[self.offset],
251            self.data[self.offset + 1],
252            self.data[self.offset + 2],
253            self.data[self.offset + 3],
254        ]);
255        self.offset += 4;
256        Ok(value)
257    }
258
259    fn read_u16_array(&mut self, count: usize) -> DecodeResult<Vec<u16>> {
260        let byte_count = count * 2;
261        if self.remaining() < byte_count {
262            return Err(DecodeError::UnexpectedEof);
263        }
264
265        let mut result = Vec::with_capacity(count);
266        for _ in 0..count {
267            result.push(self.read_u16()?);
268        }
269        Ok(result)
270    }
271
272    fn read_u32_array(&mut self, count: usize) -> DecodeResult<Vec<u32>> {
273        let byte_count = count * 4;
274        if self.remaining() < byte_count {
275            return Err(DecodeError::UnexpectedEof);
276        }
277
278        let mut result = Vec::with_capacity(count);
279        for _ in 0..count {
280            result.push(self.read_u32()?);
281        }
282        Ok(result)
283    }
284
285    fn read_edge_indices(&mut self, use_32bit: bool) -> DecodeResult<Vec<u32>> {
286        let count = self.read_u32()? as usize;
287        if use_32bit {
288            self.read_u32_array(count)
289        } else {
290            Ok(self
291                .read_u16_array(count)?
292                .into_iter()
293                .map(|x| x as u32)
294                .collect())
295        }
296    }
297
298    fn read_extensions(&mut self, vertex_count: usize) -> DecodeResult<DecodedExtensions> {
299        let mut extensions = DecodedExtensions::default();
300
301        while self.remaining() >= 5 {
302            // At least extension ID (1) + length (4)
303            let extension_id = self.data[self.offset];
304            self.offset += 1;
305
306            let length = self.read_u32()? as usize;
307            if self.remaining() < length {
308                // Not enough data for this extension, skip
309                break;
310            }
311
312            match extension_id {
313                1 => {
314                    // OctEncodedVertexNormals
315                    extensions.normals = Some(self.read_normals(vertex_count)?);
316                }
317                2 => {
318                    // WaterMask
319                    extensions.water_mask = Some(self.read_water_mask(length)?);
320                }
321                4 => {
322                    // Metadata
323                    extensions.metadata = Some(self.read_metadata()?);
324                }
325                _ => {
326                    // Unknown extension, skip
327                    self.offset += length;
328                }
329            }
330        }
331
332        Ok(extensions)
333    }
334
335    fn read_normals(&mut self, vertex_count: usize) -> DecodeResult<Vec<[f32; 3]>> {
336        let mut normals = Vec::with_capacity(vertex_count);
337        for _ in 0..vertex_count {
338            if self.remaining() < 2 {
339                return Err(DecodeError::UnexpectedEof);
340            }
341            let encoded = [self.data[self.offset], self.data[self.offset + 1]];
342            self.offset += 2;
343            normals.push(oct_decode_normal(encoded));
344        }
345        Ok(normals)
346    }
347
348    fn read_water_mask(&mut self, length: usize) -> DecodeResult<WaterMask> {
349        if length == 1 {
350            if self.remaining() < 1 {
351                return Err(DecodeError::UnexpectedEof);
352            }
353            let value = self.data[self.offset];
354            self.offset += 1;
355            Ok(WaterMask::Uniform(value))
356        } else if length == 256 * 256 {
357            if self.remaining() < 256 * 256 {
358                return Err(DecodeError::UnexpectedEof);
359            }
360            let mut grid = Box::new([0u8; 256 * 256]);
361            grid.copy_from_slice(&self.data[self.offset..self.offset + 256 * 256]);
362            self.offset += 256 * 256;
363            Ok(WaterMask::Grid(grid))
364        } else {
365            // Unknown water mask format, skip
366            self.offset += length;
367            Ok(WaterMask::Uniform(0))
368        }
369    }
370
371    fn read_metadata(&mut self) -> DecodeResult<TileMetadata> {
372        let json_length = self.read_u32()? as usize;
373        if self.remaining() < json_length {
374            return Err(DecodeError::UnexpectedEof);
375        }
376
377        let json_bytes = &self.data[self.offset..self.offset + json_length];
378        self.offset += json_length;
379
380        let json_str =
381            std::str::from_utf8(json_bytes).map_err(|e| DecodeError::JsonError(e.to_string()))?;
382
383        serde_json::from_str(json_str).map_err(|e| DecodeError::JsonError(e.to_string()))
384    }
385
386    fn align_to(&mut self, alignment: usize) {
387        let remainder = self.offset % alignment;
388        if remainder != 0 {
389            self.offset += alignment - remainder;
390        }
391    }
392
393    fn remaining(&self) -> usize {
394        self.data.len().saturating_sub(self.offset)
395    }
396}
397
398/// Decode oct-encoded normal to unit vector.
399///
400/// Reverses the octahedron encoding used for normal compression.
401pub fn oct_decode_normal(encoded: [u8; 2]) -> [f32; 3] {
402    // Map from [0, 255] to [-1, 1]
403    let mut x = (encoded[0] as f32 / 255.0) * 2.0 - 1.0;
404    let mut y = (encoded[1] as f32 / 255.0) * 2.0 - 1.0;
405
406    // Reconstruct z from octahedron
407    let z = 1.0 - x.abs() - y.abs();
408
409    // Fold lower hemisphere
410    if z < 0.0 {
411        let ox = x;
412        x = (1.0 - y.abs()) * if ox >= 0.0 { 1.0 } else { -1.0 };
413        y = (1.0 - ox.abs()) * if y >= 0.0 { 1.0 } else { -1.0 };
414    }
415
416    // Normalize
417    let len = (x * x + y * y + z * z).sqrt();
418    if len > 0.0 {
419        [x / len, y / len, z / len]
420    } else {
421        [0.0, 0.0, 1.0]
422    }
423}
424
425#[cfg(test)]
426mod tests {
427    use super::*;
428    use crate::{EncodeOptions, QuantizedMeshEncoder, oct_encode_normal};
429
430    #[test]
431    fn test_oct_decode_normal_roundtrip() {
432        let test_normals = [
433            [0.0f32, 0.0, 1.0],    // Up
434            [0.0, 0.0, -1.0],      // Down
435            [1.0, 0.0, 0.0],       // Right
436            [0.0, 1.0, 0.0],       // Forward
437            [0.577, 0.577, 0.577], // Diagonal (roughly normalized)
438        ];
439
440        for normal in test_normals {
441            let encoded = oct_encode_normal(normal);
442            let decoded = oct_decode_normal(encoded);
443
444            // Check that decoded is close to original (with some precision loss)
445            let dot = normal[0] * decoded[0] + normal[1] * decoded[1] + normal[2] * decoded[2];
446            assert!(
447                dot > 0.95,
448                "Normal roundtrip failed: {:?} -> {:?} -> {:?}, dot = {}",
449                normal,
450                encoded,
451                decoded,
452                dot
453            );
454        }
455    }
456
457    #[test]
458    fn test_decode_simple_mesh() {
459        // Create a simple mesh
460        let header = QuantizedMeshHeader::default();
461        let vertices = QuantizedVertices {
462            u: vec![0, 32767, 0, 32767],
463            v: vec![0, 0, 32767, 32767],
464            height: vec![0, 0, 0, 0],
465        };
466        let indices = vec![0, 1, 2, 1, 3, 2];
467        let edge_indices = EdgeIndices::from_vertices(&vertices);
468
469        // Encode
470        let encoder = QuantizedMeshEncoder::new(
471            header,
472            vertices.clone(),
473            indices.clone(),
474            edge_indices.clone(),
475        );
476        let encoded = encoder.encode_with_options(&EncodeOptions {
477            compression_level: 0,
478            ..Default::default()
479        });
480
481        // Decode
482        let decoded = QuantizedMeshDecoder::decode(&encoded).expect("Decoding failed");
483
484        // Verify
485        assert_eq!(decoded.header.min_height, header.min_height);
486        assert_eq!(decoded.header.max_height, header.max_height);
487        assert_eq!(decoded.vertices.u, vertices.u);
488        assert_eq!(decoded.vertices.v, vertices.v);
489        assert_eq!(decoded.vertices.height, vertices.height);
490        assert_eq!(decoded.indices, indices);
491        assert_eq!(decoded.edge_indices.west, edge_indices.west);
492        assert_eq!(decoded.edge_indices.south, edge_indices.south);
493        assert_eq!(decoded.edge_indices.east, edge_indices.east);
494        assert_eq!(decoded.edge_indices.north, edge_indices.north);
495    }
496
497    #[test]
498    fn test_decode_compressed_mesh() {
499        // Create a simple mesh
500        let header = QuantizedMeshHeader::default();
501        let vertices = QuantizedVertices {
502            u: vec![0, 32767, 0, 32767],
503            v: vec![0, 0, 32767, 32767],
504            height: vec![0, 0, 0, 0],
505        };
506        let indices = vec![0, 1, 2, 1, 3, 2];
507        let edge_indices = EdgeIndices::from_vertices(&vertices);
508
509        // Encode with compression
510        let encoder = QuantizedMeshEncoder::new(
511            header,
512            vertices.clone(),
513            indices.clone(),
514            edge_indices.clone(),
515        );
516        let encoded = encoder.encode_with_options(&EncodeOptions {
517            compression_level: 6,
518            ..Default::default()
519        });
520
521        // Verify it's gzip compressed
522        assert_eq!(&encoded[0..2], &[0x1f, 0x8b]);
523
524        // Decode
525        let decoded = QuantizedMeshDecoder::decode(&encoded).expect("Decoding failed");
526
527        // Verify
528        assert_eq!(decoded.vertices.u, vertices.u);
529        assert_eq!(decoded.vertices.v, vertices.v);
530        assert_eq!(decoded.indices, indices);
531    }
532
533    #[test]
534    fn test_decode_with_extensions() {
535        let header = QuantizedMeshHeader::default();
536        let vertices = QuantizedVertices {
537            u: vec![0, 32767, 0, 32767],
538            v: vec![0, 0, 32767, 32767],
539            height: vec![0, 0, 0, 0],
540        };
541        let indices = vec![0, 1, 2, 1, 3, 2];
542        let edge_indices = EdgeIndices::from_vertices(&vertices);
543        let normals = vec![[0.0, 0.0, 1.0]; 4];
544
545        // Encode with extensions
546        let encoder = QuantizedMeshEncoder::new(header, vertices.clone(), indices, edge_indices);
547        let encoded = encoder.encode_with_options(&EncodeOptions {
548            compression_level: 0,
549            include_normals: true,
550            normals: Some(normals),
551            include_water_mask: true,
552            water_mask: Some(WaterMask::Uniform(128)),
553            ..Default::default()
554        });
555
556        // Decode
557        let decoded = QuantizedMeshDecoder::decode(&encoded).expect("Decoding failed");
558
559        // Verify extensions
560        assert!(decoded.extensions.normals.is_some());
561        assert!(decoded.extensions.water_mask.is_some());
562
563        let decoded_normals = decoded.extensions.normals.unwrap();
564        assert_eq!(decoded_normals.len(), 4);
565        // Check that normals point roughly upward
566        for normal in decoded_normals {
567            assert!(normal[2] > 0.9);
568        }
569
570        match decoded.extensions.water_mask.unwrap() {
571            WaterMask::Uniform(v) => assert_eq!(v, 128),
572            _ => panic!("Expected uniform water mask"),
573        }
574    }
575
576    #[test]
577    fn test_decode_from_reader() {
578        use std::io::Cursor;
579
580        // Create a simple mesh
581        let header = QuantizedMeshHeader::default();
582        let vertices = QuantizedVertices {
583            u: vec![0, 32767, 0, 32767],
584            v: vec![0, 0, 32767, 32767],
585            height: vec![0, 0, 0, 0],
586        };
587        let indices = vec![0, 1, 2, 1, 3, 2];
588        let edge_indices = EdgeIndices::from_vertices(&vertices);
589
590        // Encode
591        let encoder = QuantizedMeshEncoder::new(
592            header,
593            vertices.clone(),
594            indices.clone(),
595            edge_indices.clone(),
596        );
597        let encoded = encoder.encode_with_options(&EncodeOptions {
598            compression_level: 0,
599            ..Default::default()
600        });
601
602        // Decode from reader
603        let reader = Cursor::new(encoded);
604        let decoded =
605            QuantizedMeshDecoder::decode_from(reader).expect("Decoding from reader failed");
606
607        // Verify
608        assert_eq!(decoded.vertices.u, vertices.u);
609        assert_eq!(decoded.vertices.v, vertices.v);
610        assert_eq!(decoded.indices, indices);
611    }
612
613    #[test]
614    fn test_decode_from_reader_compressed() {
615        use std::io::Cursor;
616
617        // Create a simple mesh
618        let header = QuantizedMeshHeader::default();
619        let vertices = QuantizedVertices {
620            u: vec![0, 32767, 0, 32767],
621            v: vec![0, 0, 32767, 32767],
622            height: vec![0, 0, 0, 0],
623        };
624        let indices = vec![0, 1, 2, 1, 3, 2];
625        let edge_indices = EdgeIndices::from_vertices(&vertices);
626
627        // Encode with compression
628        let encoder = QuantizedMeshEncoder::new(
629            header,
630            vertices.clone(),
631            indices.clone(),
632            edge_indices.clone(),
633        );
634        let encoded = encoder.encode_with_options(&EncodeOptions {
635            compression_level: 6,
636            ..Default::default()
637        });
638
639        // Decode from reader
640        let reader = Cursor::new(encoded);
641        let decoded =
642            QuantizedMeshDecoder::decode_from(reader).expect("Decoding from reader failed");
643
644        // Verify
645        assert_eq!(decoded.vertices.u, vertices.u);
646        assert_eq!(decoded.vertices.v, vertices.v);
647        assert_eq!(decoded.indices, indices);
648    }
649}