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    /// Returns the prediction scheme forced for one attribute, falling back to
77    /// the global setting and then to -1 for the encoder default.
78    ///
79    /// Upstream reads this per attribute (`GetPredictionMethodFromOptions`), and
80    /// `get_attribute_int` itself falls back to the global option, so a value
81    /// set either way is honoured. Crate-internal: callers outside can already
82    /// express both halves with `set_attribute_int` and `set_prediction_scheme`,
83    /// and a getter with no matching per-attribute setter would be a half API.
84    pub(crate) fn get_attribute_prediction_scheme(&self, att_id: i32) -> i32 {
85        self.get_attribute_int(att_id, "prediction_scheme", -1)
86    }
87
88    /// Forces a prediction scheme by numeric Draco method id.
89    pub fn set_prediction_scheme(&mut self, value: i32) {
90        self.set_global_int("prediction_scheme", value);
91    }
92
93    /// Returns the forced encoding method, if one was set.
94    pub fn get_encoding_method(&self) -> Option<i32> {
95        self.global_options.get("encoding_method").cloned()
96    }
97
98    /// Forces an encoding method by numeric Draco method id.
99    pub fn set_encoding_method(&mut self, value: i32) {
100        self.set_global_int("encoding_method", value);
101    }
102
103    /// Sets the target Draco bitstream version.
104    pub fn set_version(&mut self, major: u8, minor: u8) {
105        self.set_global_int("version_major", major as i32);
106        self.set_global_int("version_minor", minor as i32);
107    }
108
109    /// Returns the target Draco bitstream version, or `(0, 0)` for default.
110    pub fn get_version(&self) -> (u8, u8) {
111        let major = self.get_global_int("version_major", -1);
112        let minor = self.get_global_int("version_minor", -1);
113        if major == -1 || minor == -1 {
114            // Default version depends on the encoder type and method,
115            // but we'll return (0, 0) to indicate "use default".
116            (0, 0)
117        } else {
118            (major as u8, minor as u8)
119        }
120    }
121
122    /// Sets a global integer option.
123    pub fn set_global_int(&mut self, key: &str, value: i32) {
124        self.global_options.insert(key.to_string(), value);
125    }
126
127    /// Returns a global integer option or the supplied default.
128    pub fn get_global_int(&self, key: &str, default_val: i32) -> i32 {
129        *self.global_options.get(key).unwrap_or(&default_val)
130    }
131
132    /// Sets an integer option for one attribute id.
133    pub fn set_attribute_int(&mut self, att_id: i32, key: &str, value: i32) {
134        self.attribute_options
135            .entry(att_id)
136            .or_default()
137            .insert(key.to_string(), value);
138    }
139
140    /// Returns an attribute integer option, falling back to the global value.
141    pub fn get_attribute_int(&self, att_id: i32, key: &str, default_val: i32) -> i32 {
142        if let Some(opts) = self.attribute_options.get(&att_id) {
143            if let Some(val) = opts.get(key) {
144                return *val;
145            }
146        }
147        // Fallback to global options if not found for attribute?
148        // Draco C++ implementation does fallback to global options.
149        self.get_global_int(key, default_val)
150    }
151}