1use crate::compression_config::EncodedGeometryType;
2#[cfg(feature = "point_cloud_decode")]
3use crate::decoder_buffer::DecoderBuffer;
4#[cfg(feature = "point_cloud_decode")]
5use crate::draco_types::DataType;
6#[cfg(feature = "point_cloud_decode")]
7use crate::geometry_attribute::{GeometryAttributeType, PointAttribute};
8#[cfg(feature = "point_cloud_decode")]
9use crate::kd_tree_attributes_decoder::KdTreeAttributesDecoder;
10#[cfg(feature = "point_cloud_decode")]
11use crate::point_cloud::PointCloud;
12#[cfg(feature = "point_cloud_decode")]
13use crate::prediction_scheme::EntryToPointIdMap;
14#[cfg(feature = "point_cloud_decode")]
15use crate::sequential_integer_attribute_decoder::{
16 PortableExtent, SequentialIntegerAttributeDecoder,
17};
18#[cfg(feature = "point_cloud_decode")]
19use crate::status::{DracoError, Status};
20
21#[cfg(feature = "point_cloud_decode")]
22use crate::attribute_octahedron_transform::AttributeOctahedronTransform;
23#[cfg(feature = "point_cloud_decode")]
24use crate::attribute_quantization_transform::AttributeQuantizationTransform;
25#[cfg(feature = "point_cloud_decode")]
26use crate::attribute_transform::AttributeTransform;
27#[cfg(feature = "point_cloud_decode")]
28use crate::sequential_generic_attribute_decoder::SequentialGenericAttributeDecoder;
29#[cfg(feature = "point_cloud_decode")]
30use crate::sequential_normal_attribute_decoder::SequentialNormalAttributeDecoder;
31#[cfg(feature = "point_cloud_decode")]
32use crate::sequential_quantization_attribute_decoder::SequentialQuantizationAttributeDecoder;
33#[cfg(feature = "point_cloud_decode")]
34use crate::version::{version_at_least, VERSION_FLAGS_INTRODUCED};
35
36#[cfg(feature = "legacy_bitstream_decode")]
54pub(crate) fn carries_transform_byte(method_byte: u8) -> bool {
55 method_byte != 0xFF && method_byte != 0xFE
56}
57
58pub struct PointCloudDecoder {
67 geometry_type: EncodedGeometryType,
68 #[cfg(feature = "point_cloud_decode")]
69 method: u8,
70 #[cfg(feature = "point_cloud_decode")]
71 flags: u16,
72 version_major: u8,
76 version_minor: u8,
77}
78
79impl Default for PointCloudDecoder {
80 fn default() -> Self {
81 Self::new()
82 }
83}
84
85#[cfg(feature = "point_cloud_decode")]
86fn validate_num_attributes_in_decoder(
87 num_attributes_in_decoder: usize,
88 remaining_bytes: usize,
89) -> Result<(), DracoError> {
90 const MIN_ATTRIBUTE_BYTES: usize = 6;
94 if num_attributes_in_decoder == 0
95 || num_attributes_in_decoder > remaining_bytes / MIN_ATTRIBUTE_BYTES
96 {
97 return Err(DracoError::general(
98 "Invalid number of attributes".to_string(),
99 ));
100 }
101 Ok(())
102}
103
104#[cfg(feature = "point_cloud_decode")]
105fn validate_num_components(num_components: u8) -> Result<(), DracoError> {
106 if num_components == 0 {
107 return Err(DracoError::general(
108 "Invalid attribute component count".to_string(),
109 ));
110 }
111 Ok(())
112}
113
114impl PointCloudDecoder {
115 pub fn new() -> Self {
117 Self {
118 geometry_type: EncodedGeometryType::PointCloud,
119 #[cfg(feature = "point_cloud_decode")]
120 method: 0,
121 #[cfg(feature = "point_cloud_decode")]
122 flags: 0,
123 version_major: 0,
124 version_minor: 0,
125 }
126 }
127
128 pub(crate) fn bitstream_version(&self) -> u16 {
134 crate::version::bitstream_version(self.version_major, self.version_minor)
135 }
136
137 pub(crate) fn set_bitstream_version(&mut self, major: u8, minor: u8) {
144 self.version_major = major;
145 self.version_minor = minor;
146 }
147
148 #[cfg(feature = "point_cloud_decode")]
149 pub fn decode(&mut self, in_buffer: &mut DecoderBuffer, out_pc: &mut PointCloud) -> Status {
161 out_pc.clear();
162
163 self.decode_header(in_buffer)?;
165
166 if version_at_least(
167 self.version_major,
168 self.version_minor,
169 VERSION_FLAGS_INTRODUCED,
170 ) && (self.flags & crate::metadata::METADATA_FLAG_MASK) != 0
171 {
172 let metadata = crate::metadata::GeometryMetadata::decode(in_buffer)
173 .map_err(|_| DracoError::general("Failed to decode metadata".to_string()))?;
174 out_pc.set_metadata(Some(metadata));
175 }
176
177 self.decode_geometry_data(in_buffer, out_pc)
179 }
180
181 #[cfg(feature = "point_cloud_decode")]
184 pub fn decode_after_header(
185 &mut self,
186 version_major: u8,
187 version_minor: u8,
188 method: u8,
189 buffer: &mut DecoderBuffer,
190 out_pc: &mut PointCloud,
191 ) -> Status {
192 self.version_major = version_major;
193 self.version_minor = version_minor;
194 self.method = method;
195 self.flags = 0;
196 self.geometry_type = EncodedGeometryType::PointCloud;
197 self.decode_geometry_data(buffer, out_pc)
198 }
199
200 #[cfg(feature = "point_cloud_decode")]
201 fn decode_header(&mut self, buffer: &mut DecoderBuffer) -> Status {
202 let mut magic = [0u8; 5];
203 buffer.decode_bytes(&mut magic)?;
204 if &magic != b"DRACO" {
205 return Err(DracoError::general("Invalid magic".to_string()));
206 }
207
208 self.version_major = buffer.decode_u8()?;
209 self.version_minor = buffer.decode_u8()?;
210 buffer.set_version(self.version_major, self.version_minor);
211
212 let g_type = buffer.decode_u8()?;
213 self.geometry_type = match g_type {
214 0 => EncodedGeometryType::PointCloud,
215 1 => EncodedGeometryType::TriangularMesh,
216 _ => return Err(DracoError::general("Invalid geometry type".to_string())),
217 };
218 if self.geometry_type != EncodedGeometryType::PointCloud {
219 return Err(DracoError::general(
220 "PointCloudDecoder cannot decode mesh bitstreams".to_string(),
221 ));
222 }
223
224 self.method = buffer.decode_u8()?;
225
226 self.flags = buffer
228 .decode_u16()
229 .map_err(|_| DracoError::general("Failed to decode flags".to_string()))?;
230
231 Ok(())
232 }
233
234 #[cfg(feature = "point_cloud_decode")]
235 fn decode_geometry_data(&mut self, buffer: &mut DecoderBuffer, pc: &mut PointCloud) -> Status {
236 let bitstream_version: u16 =
237 crate::version::bitstream_version(self.version_major, self.version_minor);
238 let declared_points = buffer.decode_u32()? as i32;
256 if declared_points < 0 {
257 return Err(DracoError::general(format!(
258 "Point cloud declares {declared_points} points"
259 )));
260 }
261 let num_points: usize = declared_points as usize;
262 buffer.check_points(num_points)?;
263 pc.set_num_points(num_points);
264
265 let num_attributes_decoders = buffer.decode_u8()? as usize;
266
267 if self.method == 1 {
268 for _ in 0..num_attributes_decoders {
270 let mut att_decoder = KdTreeAttributesDecoder::new(0);
271 att_decoder
272 .decode_attributes_decoder_data(pc, buffer)
273 .map_err(|err| err.context("Failed to decode attribute metadata"))?;
274 att_decoder
275 .decode_attributes(pc, buffer)
276 .map_err(|err| err.context("Failed to decode attributes"))?;
277 }
278 } else {
279 struct PendingQuant {
281 att_id: i32,
282 portable: PointAttribute,
283 transform: AttributeQuantizationTransform,
284 }
285
286 struct PendingNormal {
287 att_id: i32,
288 portable: PointAttribute,
289 quantization_bits: u8,
290 }
291
292 struct AttributeSpec {
293 att_type: GeometryAttributeType,
294 data_type: DataType,
295 num_components: u8,
296 normalized: bool,
297 unique_id: u32,
298 }
299
300 for _ in 0..num_attributes_decoders {
301 let num_attributes_in_decoder: usize = if bitstream_version < 0x0200 {
302 buffer.decode_u32()? as usize
303 } else {
304 buffer.decode_varint()? as usize
305 };
306 if num_attributes_in_decoder == 0 {
307 return Err(DracoError::general(
308 "Invalid number of attributes".to_string(),
309 ));
310 }
311 validate_num_attributes_in_decoder(
312 num_attributes_in_decoder,
313 buffer.remaining_size(),
314 )?;
315
316 let mut attribute_specs: Vec<AttributeSpec> =
317 Vec::with_capacity(num_attributes_in_decoder);
318 let mut att_ids: Vec<i32> = Vec::with_capacity(num_attributes_in_decoder);
319 let mut decoder_types: Vec<u8> = Vec::with_capacity(num_attributes_in_decoder);
320 let mut pending_quant: Vec<PendingQuant> = Vec::new();
321 let mut pending_normals: Vec<PendingNormal> = Vec::new();
322
323 for _ in 0..num_attributes_in_decoder {
324 let att_type_val = buffer.decode_u8()?;
325 let att_type = GeometryAttributeType::try_from(att_type_val)?;
326
327 let data_type_val = buffer.decode_u8()?;
328 let data_type = DataType::try_from(data_type_val)?;
329
330 let num_components = buffer.decode_u8()?;
331 validate_num_components(num_components)?;
332 let normalized = buffer.decode_u8()? != 0;
333 let unique_id: u32 = if bitstream_version < 0x0103 {
334 buffer.decode_u16()? as u32
335 } else {
336 buffer.decode_varint()? as u32
337 };
338
339 attribute_specs.push(AttributeSpec {
340 att_type,
341 data_type,
342 num_components,
343 normalized,
344 unique_id,
345 });
346 }
347
348 for _ in 0..num_attributes_in_decoder {
349 decoder_types.push(buffer.decode_u8()?);
350 }
351
352 for (local_i, spec) in attribute_specs.iter().enumerate() {
353 if decoder_types[local_i] == 0 {
354 let entry_size =
355 spec.num_components as usize * spec.data_type.byte_length();
356 let bytes_needed = entry_size.checked_mul(num_points).ok_or_else(|| {
357 DracoError::general(
358 "Raw point cloud attribute byte count overflow".to_string(),
359 )
360 })?;
361 if buffer.remaining_size() < bytes_needed {
362 return Err(DracoError::general(
363 "Not enough data for raw point cloud attribute values".to_string(),
364 ));
365 }
366 }
367
368 buffer.charge_decoded_bytes(
369 (spec.num_components as usize)
370 .saturating_mul(spec.data_type.byte_length())
371 .saturating_mul(num_points),
372 )?;
373 let mut att = PointAttribute::new();
374 att.init_deferred(
385 spec.att_type,
386 spec.num_components,
387 spec.data_type,
388 spec.normalized,
389 num_points,
390 )?;
391 att.set_unique_id(spec.unique_id);
392 let att_id = pc.add_attribute_preserve_unique_id(att);
393 att_ids.push(att_id);
394 }
395
396 let point_ids = if decoder_types.iter().any(|&decoder_type| decoder_type != 0) {
402 Some(EntryToPointIdMap::identity(num_points))
403 } else {
404 None
405 };
406
407 for (local_i, &att_id) in att_ids.iter().enumerate() {
408 let decoder_type = decoder_types[local_i];
409 match decoder_type {
410 1 => {
411 let point_ids = point_ids.ok_or_else(|| {
412 DracoError::general(
413 "Point ids missing for integer attribute decoder".to_string(),
414 )
415 })?;
416 let mut att_decoder = SequentialIntegerAttributeDecoder::new();
417 att_decoder.init(self, att_id);
418 att_decoder.decode_values(
419 pc, point_ids, buffer, None, None, None, None, None, None,
420 )?;
421 }
422 2 => {
423 let mut att_decoder = SequentialQuantizationAttributeDecoder::new();
424 att_decoder.init(self, pc, att_id)?;
425 let portable = att_decoder.decode_values(
426 pc,
427 point_ids.ok_or_else(|| {
428 DracoError::general(
429 "Point ids missing for quantized attribute decoder"
430 .to_string(),
431 )
432 })?,
433 buffer,
434 bitstream_version,
435 PortableExtent::Declared(num_points),
436 None,
437 None,
438 None,
439 None,
440 )?;
441 pending_quant.push(PendingQuant {
442 att_id,
443 portable,
444 transform: att_decoder.into_transform(),
445 });
446 }
447 3 => {
448 let mut att_decoder = SequentialNormalAttributeDecoder::new();
449 att_decoder.init(self, pc, att_id)?;
450 let portable = att_decoder.decode_values(
451 pc,
452 point_ids.ok_or_else(|| {
453 DracoError::general(
454 "Point ids missing for normal attribute decoder"
455 .to_string(),
456 )
457 })?,
458 buffer,
459 bitstream_version,
460 PortableExtent::Declared(num_points),
461 None,
462 None,
463 None,
464 None,
465 )?;
466 pending_normals.push(PendingNormal {
467 att_id,
468 portable,
469 quantization_bits: att_decoder.quantization_bits(),
470 });
471 }
472 0 => {
473 let mut att_decoder = SequentialGenericAttributeDecoder::new();
479 att_decoder.init(self, att_id);
480 att_decoder.decode_values(
481 pc,
482 EntryToPointIdMap::identity(num_points),
483 buffer,
484 )?;
485 }
486 _ => {
487 return Err(DracoError::general(format!(
488 "Unsupported sequential decoder type: {}",
489 decoder_type
490 )));
491 }
492 }
493 }
494
495 for (local_i, &att_id) in att_ids.iter().enumerate() {
496 match decoder_types[local_i] {
497 2 if bitstream_version >= 0x0200 => {
498 let idx = pending_quant
499 .iter()
500 .position(|p| p.att_id == att_id)
501 .ok_or_else(|| {
502 DracoError::general(
503 "Missing pending quantized attribute transform".to_string(),
504 )
505 })?;
506 let original = pc.try_attribute(att_id)?;
507 pending_quant[idx]
508 .transform
509 .decode_parameters(original, buffer)
510 .map_err(|e| {
511 DracoError::general(format!(
512 "Failed to decode quantization parameters: {e}"
513 ))
514 })?;
515 }
516 3 if bitstream_version >= 0x0200 => {
517 let idx = pending_normals
518 .iter()
519 .position(|p| p.att_id == att_id)
520 .ok_or_else(|| {
521 DracoError::general(
522 "Missing pending normal attribute transform".to_string(),
523 )
524 })?;
525 let quantization_bits = buffer.decode_u8()?;
526 if !AttributeOctahedronTransform::is_valid_quantization_bits(
527 quantization_bits as i32,
528 ) {
529 return Err(DracoError::general(
530 "Invalid normal quantization bits".to_string(),
531 ));
532 }
533 pending_normals[idx].quantization_bits = quantization_bits;
534 }
535 _ => {}
536 }
537 }
538
539 for q in pending_quant {
540 let dst = pc.try_attribute_mut(q.att_id)?;
541 q.transform
542 .inverse_transform_attribute(&q.portable, dst)
543 .map_err(|e| {
544 DracoError::general(format!("Failed to dequantize attribute: {e}"))
545 })?;
546 }
547 for n in pending_normals {
548 let mut oct = AttributeOctahedronTransform::new(-1);
549 oct.set_parameters(n.quantization_bits as i32)?;
550 let dst = pc.try_attribute_mut(n.att_id)?;
551 oct.inverse_transform_attribute_with_legacy_octahedron(
552 &n.portable,
553 dst,
554 bitstream_version < 0x0200,
555 )
556 .map_err(|e| DracoError::general(format!("Failed to decode normals: {e}")))?;
557 }
558 }
559 }
560
561 Ok(())
562 }
563
564 pub fn get_geometry_type(&self) -> EncodedGeometryType {
566 self.geometry_type
567 }
568}