pub struct EncoderOptions { /* private fields */ }encoder only.Expand description
Integer option bag used to configure Draco encoding.
Options mirror the C++ Draco encoder style: global options apply to the whole geometry, while attribute options override a value for one attribute id and fall back to the global value when unset.
Common keys include quantization_bits (per-attribute precision),
encoding_speed/decoding_speed, encoding_method, and
prediction_scheme. Keys without an explicit setter are read and written
with get_global_int /
set_global_int.
§Examples
use draco_core::EncoderOptions;
let mut options = EncoderOptions::new();
options.set_global_int("quantization_bits", 14); // default for all attributes
options.set_attribute_int(0, "quantization_bits", 10); // override attribute 0
assert_eq!(options.get_attribute_int(0, "quantization_bits", 0), 10);
// Attribute 1 has no override, so it falls back to the global value.
assert_eq!(options.get_attribute_int(1, "quantization_bits", 0), 14);Implementations§
Source§impl EncoderOptions
impl EncoderOptions
Sourcepub fn get_encoding_speed(&self) -> i32
pub fn get_encoding_speed(&self) -> i32
Returns the configured encoding speed, defaulting to 5.
Sourcepub fn get_decoding_speed(&self) -> i32
pub fn get_decoding_speed(&self) -> i32
Returns the configured decoding speed target, defaulting to 5.
Sourcepub fn get_speed(&self) -> i32
pub fn get_speed(&self) -> i32
Returns the maximum speed for both encoding/decoding. Matches C++ ExpertEncoder::GetSpeed() behavior.
Sourcepub fn set_compression_level(&mut self, level: i32)
pub fn set_compression_level(&mut self, level: i32)
Sets both speeds from a draco_encoder-style compression level.
The CLI’s -cl runs 0 (least compression) to 10 (most), the opposite
sense of encoding_speed/decoding_speed, and converts with
speed = 10 - compression_level before calling the same
SetSpeedOptions this crate mirrors; this method does the same
conversion and nothing else. level is not range-checked, matching
the CLI, which passes an out-of-range -cl straight through the same
subtraction rather than rejecting it.
Sourcepub fn get_compression_level(&self) -> i32
pub fn get_compression_level(&self) -> i32
Returns 10 - get_speed(), the CLI’s compression
level for the speed this instance currently carries.
A fresh EncoderOptions reports 5 here, not the CLI’s own default of
7 — the two tools default to different speeds (5 here, 3 there), and
this getter reads what is actually set rather than what the CLI would
have chosen.
Sourcepub fn set_attribute_quantization(
&mut self,
att_id: i32,
quantization_bits: i32,
)
pub fn set_attribute_quantization( &mut self, att_id: i32, quantization_bits: i32, )
Sets quantization_bits for one attribute id.
Equivalent to ExpertEncoder::SetAttributeQuantization and to what the
CLI’s -qp/-qt/-qn/-qg resolve to once they have picked an
attribute id for POSITION/TEX_COORD/NORMAL/GENERIC; this method takes
the id directly rather than a geometry attribute type.
Sourcepub fn get_attribute_quantization(&self, att_id: i32) -> i32
pub fn get_attribute_quantization(&self, att_id: i32) -> i32
Returns the quantization_bits set for one attribute id, or -1 if
none was set for it or globally.
Sourcepub fn get_prediction_scheme(&self) -> i32
pub fn get_prediction_scheme(&self) -> i32
Returns the forced prediction scheme, or -1 for the encoder default.
Sourcepub fn set_prediction_scheme(&mut self, value: i32)
pub fn set_prediction_scheme(&mut self, value: i32)
Forces a prediction scheme by numeric Draco method id.
Sourcepub fn prediction_search(&self) -> bool
pub fn prediction_search(&self) -> bool
Whether the encoder may choose a point-cloud attribute’s prediction scheme by estimating the cost of each candidate.
Sourcepub fn set_prediction_search(&mut self, enabled: bool)
pub fn set_prediction_search(&mut self, enabled: bool)
Lets the encoder choose each attribute’s prediction scheme by the estimated cost of the candidates rather than by upstream’s fixed rule.
Off by default, and deliberately: the automatic choice is upstream’s, and this crate’s output is byte-identical to C++ Draco’s for the same input. Searching produces a different — smaller — stream, so it is a thing a caller asks for rather than a thing that happens to them.
What it buys, and why it exists at all: the automatic choice for a
point-cloud attribute is always Difference, and differencing costs
more than it saves whenever consecutive values do not correlate.
Spherical-harmonic coefficients in a Gaussian splat are the case that
prompted this: predicted, they cost more bits than coded directly. The
opposite case is just as real: on smoothly varying data, turning
prediction off makes a file much larger. Neither is knowable from the
attribute’s type, so this looks at its values.
It is worth turning on only for data of that shape, and the honest version of “that shape” is narrow. On a photogrammetry capture carrying position and colour the search finds nothing at all: both attributes are well served by differencing, and coding either directly is worse. Attributes whose values do not follow their neighbours are what this is for, and a scanned surface is the opposite of that.
The cost is encode time and nothing else. The candidates are ranked by
the same bit estimate the symbol coder uses to choose its own scheme,
which is an entropy pass over each candidate’s symbols, not a second
encode, and the winner’s estimate is what the coder is then handed
rather than working it out again. On a cloud of many attributes the
encode still takes noticeably longer. Decoding is unaffected, and every stream this can produce is one an ordinary decoder
reads: the scheme is a byte the bitstream has always carried,
PREDICTION_NONE included.
An attribute with an explicit prediction_scheme is left alone; a
caller who named a scheme has already made this choice.
Sourcepub fn spatial_point_order(&self) -> bool
pub fn spatial_point_order(&self) -> bool
Whether a point cloud’s points may be reordered spatially before being encoded.
Sourcepub fn set_spatial_point_order(&mut self, enabled: bool)
pub fn set_spatial_point_order(&mut self, enabled: bool)
Lets the encoder emit a point cloud’s points in a spatial order rather than in the order they were handed in.
Which spatial order is the encoder’s choice and not part of this option’s contract: today it is a Hilbert curve, which writes fewer bytes than a Morton curve for the same encode time, and a later version may use a better one. Every such stream decodes the same way; only the order of the decoded points and the size differ.
A point cloud’s point order carries no meaning: no connectivity refers to it, every attribute is read through the same point index, and a decoder reconstructs whatever order the stream has. So an encoder may choose it, and choosing it spatially is what makes the difference predictor predict from a neighbour instead of from whatever the exporter happened to write next.
This is the general one of the two. It was written for Gaussian splats, and it does more on ordinary captured geometry: a photogrammetry point cloud of coloured points gains a larger share than a splat does. Any cloud whose attributes vary through space rather than along its file order gains from it.
The curve is laid over a grid as fine as the positions’ own
quantization_bits, up to 21 bits an axis. Both halves of that are
measured: a coarser grid puts points the stream will distinguish into
one cell, where their order is whatever the sort left them in, and a
finer one sorts by differences the quantization discards.
Off by default for the same reason the prediction search is: the output differs, byte for byte, from what upstream C++ Draco writes for the same input, and this crate’s default is to match it.
This reorders the decoded points. Anything outside the file that
indexes into it by point number — a sidecar array, an index written by
another tool — will be pointing at different points afterwards. Nothing
inside a .drc does, which is why this is expressible at all, but a
caller who has such a thing is the one who knows.
It can also make a file bigger, and unlike the prediction search it
does not check. The gain comes from attributes that vary through space;
an attribute that varies along the order it was handed in — an index, a
timestamp, anything written in sequence — is scrambled by the reorder
and costs more afterwards: a cloud of positions plus a running integer
tag grows. It is not checked because the option is a
statement about the order, not about the size: a caller who wants
spatial locality in the decoded cloud wants it whether or not it also
happens to compress better. Whoever wants only the smaller file wants
set_point_order_search instead, which
checks, and is allowed to trade locality for size.
Applies to the sequential coder. The kd-tree coder chooses its own point order and this leaves it alone. A point cloud with no position attribute has nothing to sort by and is also left alone.
Sourcepub fn point_order_search(&self) -> bool
pub fn point_order_search(&self) -> bool
Whether the encoder may search for the order of a point cloud’s points that makes the stream smallest.
Sourcepub fn set_point_order_search(&mut self, enabled: bool)
pub fn set_point_order_search(&mut self, enabled: bool)
Lets the encoder search for the order of a point cloud’s points that makes the stream smallest, and leave the order alone where it finds the one it was handed already better.
The sequential coder writes each attribute as the difference between a point and the one before it, so the order decides how large those differences are. A spatial order makes neighbours in space neighbours in the stream; this strings the points along a Hilbert curve and then repairs it where the other attributes disagree with the positions, which they do in a Gaussian splat, where the position is a small part of each point’s bytes.
Against set_spatial_point_order at
the same encoding speed it gains the most on clouds like that, and more
the lower the speed. Photogrammetry scans and lidar captures gain less.
The stream is an ordinary one. Only the order of the points in it
differs.
It costs encode time, several times the encode in file order, and
more the lower the speed. The search runs on as many threads as
set_threads allows, writing the same order on any
number. And some decode time: in the order it finds, neighbours
agree well enough that the encoder picks the more compact schemes,
differences over values as they are and the raw coder over the tagged
one, and those take a little longer to undo.
It can decline. Each order it could write – the one it was handed, the curve, and the curve repaired – is priced by the symbol coder’s own plan of what it would write for a sample of the cloud, and an order replaces another only if it undercuts it by 1%. The repair is tried on a sample of the path’s blocks first, one in sixteen on a large cloud, and finished only if the trial pays. A scan or a rotating-lidar capture written along its scan lines is already in an order no curve improves on, and comes out exactly as it would without this, where a spatial order would have made it larger.
The effort follows encoding_speed, the way it does elsewhere:
speed 9 and 10 write the curve and nothing more, 7 and 8 count the 8
dearest attribute columns over a window of 8 points, 5 and 6 (the
default) 16 over 16, 3 and 4 32 over 32, and 0 to 2 the 64 dearest over
64.
Off by default for the reason the prediction search is: it changes the bytes, and this crate’s default is to match upstream C++ Draco.
This reorders the decoded points, and unlike
set_spatial_point_order it makes no
promise that they are spatially near one another: a point may sit
beside one that looks like it rather than one that is close. If the
search keeps the order it was handed and set_spatial_point_order is
also on, the spatial order is what is written.
Applies to the sequential coder, like the order option does.
Sourcepub fn get_threads(&self) -> i32
pub fn get_threads(&self) -> i32
The threads asked of this encode: 1, the default, is the calling thread alone, 0 is as many as the machine has, and no count is taken past sixteen.
Sourcepub fn set_threads(&mut self, threads: i32)
pub fn set_threads(&mut self, threads: i32)
Caps the threads an encode may use; 1, the default, keeps everything
on the calling thread and 0 takes as many as the machine has. Neither
a count asked for nor the machine’s is taken past sixteen.
One by default because a library cannot see what its caller already runs: a server encoding on a pool of its own, or a converter working through files side by side, would have every encode multiply its threads by up to sixteen. A caller with the cores to spare, encoding a large cloud at a time, asks for them.
A sequential point cloud’s attributes are encoded side by side, each into a buffer of its own that is appended in order, and an attribute of a million values or more also cuts its own passes – quantization, the gather, the prediction, the symbol plan – into pieces; only the rANS write stays one chain. The point order search and the spatial curve run on the same threads. A large cloud of many attributes, a Gaussian splat for one, encodes several times faster on many threads. Below 2^17 values in all, counted as points times attributes, no thread is started.
Only work that splits into pieces independent of one another is run on threads, and each piece’s result is the same whichever thread works it, so the stream does not depend on this. The calling thread is one of them, and a thread the system refuses to start is one fewer rather than an error: the encode finishes on those that did. On WebAssembly there are no threads and the value is ignored.
Sourcepub fn get_encoding_method(&self) -> Option<i32>
pub fn get_encoding_method(&self) -> Option<i32>
Returns the forced encoding method, if one was set.
Sourcepub fn set_encoding_method(&mut self, value: i32)
pub fn set_encoding_method(&mut self, value: i32)
Forces an encoding method by numeric Draco method id.
Sourcepub fn set_version(&mut self, major: u8, minor: u8)
pub fn set_version(&mut self, major: u8, minor: u8)
Sets the target Draco bitstream version.
Sourcepub fn get_version(&self) -> (u8, u8)
pub fn get_version(&self) -> (u8, u8)
Returns the target Draco bitstream version, or (0, 0) for default.
Sourcepub fn set_global_int(&mut self, key: &str, value: i32)
pub fn set_global_int(&mut self, key: &str, value: i32)
Sets a global integer option.
Sourcepub fn get_global_int(&self, key: &str, default_val: i32) -> i32
pub fn get_global_int(&self, key: &str, default_val: i32) -> i32
Returns a global integer option or the supplied default.
Sourcepub fn set_attribute_int(&mut self, att_id: i32, key: &str, value: i32)
pub fn set_attribute_int(&mut self, att_id: i32, key: &str, value: i32)
Sets an integer option for one attribute id.