Skip to main content

draco_core/
encoder_options.rs

1use std::collections::HashMap;
2
3/// Integer option bag used to configure Draco encoding.
4///
5/// Options mirror the C++ Draco encoder style: global options apply to the
6/// whole geometry, while attribute options override a value for one attribute
7/// id and fall back to the global value when unset.
8///
9/// Common keys include `quantization_bits` (per-attribute precision),
10/// `encoding_speed`/`decoding_speed`, `encoding_method`, and
11/// `prediction_scheme`. Keys without an explicit setter are read and written
12/// with [`get_global_int`](EncoderOptions::get_global_int) /
13/// [`set_global_int`](EncoderOptions::set_global_int).
14///
15/// # Examples
16///
17/// ```
18/// use draco_core::EncoderOptions;
19///
20/// let mut options = EncoderOptions::new();
21/// options.set_global_int("quantization_bits", 14); // default for all attributes
22/// options.set_attribute_int(0, "quantization_bits", 10); // override attribute 0
23///
24/// assert_eq!(options.get_attribute_int(0, "quantization_bits", 0), 10);
25/// // Attribute 1 has no override, so it falls back to the global value.
26/// assert_eq!(options.get_attribute_int(1, "quantization_bits", 0), 14);
27/// ```
28#[derive(Debug, Clone, Default)]
29pub struct EncoderOptions {
30    global_options: HashMap<String, i32>,
31    attribute_options: HashMap<i32, HashMap<String, i32>>,
32}
33
34impl EncoderOptions {
35    /// Creates options with Draco-compatible defaults.
36    pub fn new() -> Self {
37        Self::default()
38    }
39
40    /// Returns the configured encoding speed, defaulting to 5.
41    pub fn get_encoding_speed(&self) -> i32 {
42        self.get_global_int("encoding_speed", 5)
43    }
44
45    /// Returns the configured decoding speed target, defaulting to 5.
46    pub fn get_decoding_speed(&self) -> i32 {
47        self.get_global_int("decoding_speed", 5)
48    }
49
50    /// Returns the maximum speed for both encoding/decoding.
51    /// Matches C++ ExpertEncoder::GetSpeed() behavior.
52    pub fn get_speed(&self) -> i32 {
53        let encoding_speed = self
54            .global_options
55            .get("encoding_speed")
56            .copied()
57            .unwrap_or(-1);
58        let decoding_speed = self
59            .global_options
60            .get("decoding_speed")
61            .copied()
62            .unwrap_or(-1);
63        let max_speed = encoding_speed.max(decoding_speed);
64        if max_speed == -1 {
65            5 // Default value
66        } else {
67            max_speed
68        }
69    }
70
71    /// Returns the forced prediction scheme, or -1 for the encoder default.
72    pub fn get_prediction_scheme(&self) -> i32 {
73        self.get_global_int("prediction_scheme", -1)
74    }
75
76    /// Forces a prediction scheme by numeric Draco method id.
77    pub fn set_prediction_scheme(&mut self, value: i32) {
78        self.set_global_int("prediction_scheme", value);
79    }
80
81    /// Returns the forced encoding method, if one was set.
82    pub fn get_encoding_method(&self) -> Option<i32> {
83        self.global_options.get("encoding_method").cloned()
84    }
85
86    /// Forces an encoding method by numeric Draco method id.
87    pub fn set_encoding_method(&mut self, value: i32) {
88        self.set_global_int("encoding_method", value);
89    }
90
91    /// Sets the target Draco bitstream version.
92    pub fn set_version(&mut self, major: u8, minor: u8) {
93        self.set_global_int("version_major", major as i32);
94        self.set_global_int("version_minor", minor as i32);
95    }
96
97    /// Returns the target Draco bitstream version, or `(0, 0)` for default.
98    pub fn get_version(&self) -> (u8, u8) {
99        let major = self.get_global_int("version_major", -1);
100        let minor = self.get_global_int("version_minor", -1);
101        if major == -1 || minor == -1 {
102            // Default version depends on the encoder type and method,
103            // but we'll return (0, 0) to indicate "use default".
104            (0, 0)
105        } else {
106            (major as u8, minor as u8)
107        }
108    }
109
110    /// Sets a global integer option.
111    pub fn set_global_int(&mut self, key: &str, value: i32) {
112        self.global_options.insert(key.to_string(), value);
113    }
114
115    /// Returns a global integer option or the supplied default.
116    pub fn get_global_int(&self, key: &str, default_val: i32) -> i32 {
117        *self.global_options.get(key).unwrap_or(&default_val)
118    }
119
120    /// Sets an integer option for one attribute id.
121    pub fn set_attribute_int(&mut self, att_id: i32, key: &str, value: i32) {
122        self.attribute_options
123            .entry(att_id)
124            .or_default()
125            .insert(key.to_string(), value);
126    }
127
128    /// Returns an attribute integer option, falling back to the global value.
129    pub fn get_attribute_int(&self, att_id: i32, key: &str, default_val: i32) -> i32 {
130        if let Some(opts) = self.attribute_options.get(&att_id) {
131            if let Some(val) = opts.get(key) {
132                return *val;
133            }
134        }
135        // Fallback to global options if not found for attribute?
136        // Draco C++ implementation does fallback to global options.
137        self.get_global_int(key, default_val)
138    }
139}