1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
//! Base sequential attribute encoder.
//!
//! [`SequentialAttributeEncoder`] is the generic encode path that writes
//! attribute values in point order with no prediction or transform. Encode-side
//! base reused by the integer and normal encoders. Port of Draco's
//! `sequential_attribute_encoder.h`.
use crate::draco_types::DataType;
use crate::encoder_buffer::EncoderBuffer;
use crate::geometry_attribute::{GeometryAttributeType, PointAttribute};
use crate::geometry_indices::PointIndex;
use crate::point_cloud::PointCloud;
/// Which sequential encoder handles an attribute. The value is what the
/// bitstream carries: one identifier byte per attribute, which the decoder
/// turns back into a decoder in `SequentialAttributeDecodersController::
/// CreateSequentialDecoder`.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum SequentialAttributeEncoderType {
/// Raw bytes, in point order, no transform.
Generic = 0,
/// Entropy-coded integers, optionally predicted.
Integer = 1,
/// Floats quantized to integers, then encoded as integers.
Quantization = 2,
/// Normals mapped onto the octahedron, then encoded as integers.
Normals = 3,
}
/// Picks the encoder for `attribute`, as
/// `SequentialAttributeEncodersController::CreateSequentialEncoder` does.
///
/// The data type decides first and quantization only breaks the tie within
/// `Float32`: an integer-typed attribute is encoded as an integer whatever
/// quantization was requested for it, and everything upstream's switch does not
/// name -- `Float64`, the 64-bit integers, `Bool` -- falls through to the
/// generic encoder rather than being treated as an integer. `quantization_bits`
/// is the value read from the encoder options for this attribute; any
/// non-positive value means unquantized.
pub fn select_sequential_encoder(
attribute: &PointAttribute,
quantization_bits: i32,
) -> SequentialAttributeEncoderType {
match attribute.data_type() {
DataType::Uint8
| DataType::Int8
| DataType::Uint16
| DataType::Int16
| DataType::Uint32
| DataType::Int32 => SequentialAttributeEncoderType::Integer,
DataType::Float32 if quantization_bits > 0 => {
if attribute.attribute_type() == GeometryAttributeType::Normal {
SequentialAttributeEncoderType::Normals
} else {
SequentialAttributeEncoderType::Quantization
}
}
_ => SequentialAttributeEncoderType::Generic,
}
}
pub struct SequentialAttributeEncoder {
attribute_id: i32,
}
impl Default for SequentialAttributeEncoder {
fn default() -> Self {
Self::new()
}
}
impl SequentialAttributeEncoder {
pub fn new() -> Self {
Self { attribute_id: -1 }
}
pub fn attribute_id(&self) -> i32 {
self.attribute_id
}
pub fn init(&mut self, attribute_id: i32) -> bool {
self.attribute_id = attribute_id;
true
}
pub fn initialize_standalone(&mut self, _attribute: &PointAttribute) -> bool {
true
}
pub fn transform_attribute_to_portable_format(&mut self, _point_ids: &[PointIndex]) -> bool {
true
}
pub fn encode_values(
&mut self,
point_cloud: &PointCloud,
point_ids: &[PointIndex],
out_buffer: &mut EncoderBuffer,
) -> bool {
let att = point_cloud.attribute(self.attribute_id);
let entry_size = att.byte_stride() as usize;
let buffer_data = att.buffer().data();
for &p_id in point_ids {
let mapped_index = att.mapped_index(p_id).0 as usize;
let offset = mapped_index * entry_size;
if offset + entry_size > buffer_data.len() {
return false;
}
let bytes = &buffer_data[offset..offset + entry_size];
out_buffer.encode_data(bytes);
}
true
}
}