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}