1use crate::attribute_quantization_transform::AttributeQuantizationTransform;
2use crate::attribute_transform::AttributeTransform;
3use crate::compression_config::EncodedGeometryType;
4use crate::compression_config::MeshEncodingMethod;
5use crate::corner_table::CornerTable;
6use crate::draco_types::DataType;
7use crate::encoder_buffer::EncoderBuffer;
8use crate::encoder_options::EncoderOptions;
9use crate::geometry_attribute::{GeometryAttributeType, PointAttribute};
10use crate::geometry_indices::{FaceIndex, PointIndex, INVALID_ATTRIBUTE_VALUE_INDEX};
11use crate::mesh::Mesh;
12use crate::mesh_edgebreaker_encoder::{EdgebreakerAttributeConnectivity, MeshEdgebreakerEncoder};
13use crate::metadata::METADATA_FLAG_MASK;
14use crate::point_cloud::PointCloud;
15use crate::point_cloud_encoder::GeometryEncoder;
16use crate::sequential_attribute_encoder::SequentialAttributeEncoder;
17use crate::sequential_integer_attribute_encoder::SequentialIntegerAttributeEncoder;
18use crate::sequential_normal_attribute_encoder::SequentialNormalAttributeEncoder;
19use crate::status::{DracoError, Status};
20use crate::version::{
21 has_header_flags, uses_varint_encoding, uses_varint_unique_id, DEFAULT_MESH_VERSION,
22};
23
24type PositionBounds = (Option<Vec<f64>>, Option<Vec<f64>>);
26
27pub struct MeshEncoder {
74 mesh: Option<Mesh>,
75 options: EncoderOptions,
76 num_encoded_faces: usize,
77 corner_table: Option<CornerTable>,
78 point_ids: Vec<PointIndex>,
79 data_to_corner_map: Option<Vec<u32>>,
80 vertex_to_data_map: Option<Vec<i32>>,
81 edgebreaker_attribute_connectivity: Vec<EdgebreakerAttributeConnectivity>,
82 active_corner_table: Option<CornerTable>,
83 active_data_to_corner_map: Option<Vec<u32>>,
84 active_vertex_to_data_map: Option<Vec<i32>>,
85 method: i32,
86 point_to_vertex_map: Option<Vec<u32>>,
89 use_single_connectivity: bool,
91 encoded_mesh_info: Option<EncodedMeshInfo>,
92}
93
94#[derive(Debug, Clone, PartialEq)]
96pub struct EncodedMeshInfo {
97 pub encoding_method: i32,
99 pub num_encoded_faces: usize,
101 pub num_encoded_points: usize,
103 pub attributes: Vec<EncodedAttributeInfo>,
105}
106
107#[derive(Debug, Clone, PartialEq)]
109pub struct EncodedAttributeInfo {
110 pub source_attribute_id: i32,
112 pub attribute_type: GeometryAttributeType,
114 pub data_type: DataType,
116 pub num_components: u8,
118 pub normalized: bool,
120 pub unique_id: u32,
122 pub num_encoded_values: usize,
124 pub position_min: Option<Vec<f64>>,
126 pub position_max: Option<Vec<f64>>,
128}
129
130impl GeometryEncoder for MeshEncoder {
131 fn point_cloud(&self) -> Option<&PointCloud> {
132 self.mesh.as_ref().map(|m| m as &PointCloud)
133 }
134
135 fn mesh(&self) -> Option<&Mesh> {
136 self.mesh.as_ref()
137 }
138
139 fn corner_table(&self) -> Option<&CornerTable> {
140 self.active_corner_table
141 .as_ref()
142 .or(self.corner_table.as_ref())
143 }
144
145 fn options(&self) -> &EncoderOptions {
146 &self.options
147 }
148
149 fn get_geometry_type(&self) -> EncodedGeometryType {
150 EncodedGeometryType::TriangularMesh
151 }
152
153 fn get_encoding_method(&self) -> Option<i32> {
154 Some(self.method)
155 }
156
157 fn get_data_to_corner_map(&self) -> Option<&[u32]> {
158 self.active_data_to_corner_map
159 .as_deref()
160 .or(self.data_to_corner_map.as_deref())
161 }
162
163 fn get_vertex_to_data_map(&self) -> Option<&[i32]> {
164 self.active_vertex_to_data_map
165 .as_deref()
166 .or(self.vertex_to_data_map.as_deref())
167 }
168}
169
170impl MeshEncoder {
171 pub fn new() -> Self {
173 Self {
174 mesh: None,
175 options: EncoderOptions::default(),
176 num_encoded_faces: 0,
177 corner_table: None,
178 point_ids: Vec::new(),
179 data_to_corner_map: None,
180 vertex_to_data_map: None,
181 edgebreaker_attribute_connectivity: Vec::new(),
182 active_corner_table: None,
183 active_data_to_corner_map: None,
184 active_vertex_to_data_map: None,
185 method: 0,
186 point_to_vertex_map: None,
187 use_single_connectivity: false,
188 encoded_mesh_info: None,
189 }
190 }
191
192 pub fn set_mesh(&mut self, mesh: Mesh) {
194 self.mesh = Some(mesh);
195 }
196
197 pub fn mesh(&self) -> Option<&Mesh> {
199 self.mesh.as_ref()
200 }
201
202 pub fn num_encoded_faces(&self) -> usize {
204 self.num_encoded_faces
205 }
206
207 pub fn corner_table(&self) -> Option<&CornerTable> {
209 self.corner_table.as_ref()
210 }
211
212 pub fn encoded_mesh_info(&self) -> Option<&EncodedMeshInfo> {
214 self.encoded_mesh_info.as_ref()
215 }
216
217 pub fn encode(&mut self, options: &EncoderOptions, out_buffer: &mut EncoderBuffer) -> Status {
228 self.options = options.clone();
229 self.encoded_mesh_info = None;
230
231 if self.mesh.is_none() {
232 return Err(DracoError::DracoError("Mesh not set".to_string()));
233 }
234
235 self.encode_header(out_buffer)?;
237 self.encode_metadata(out_buffer)?;
238
239 self.encode_geometry_data(out_buffer)?;
241
242 Ok(())
243 }
244
245 fn encode_metadata(&self, buffer: &mut EncoderBuffer) -> Status {
246 if let Some(metadata) = self
247 .mesh
248 .as_ref()
249 .and_then(|mesh| mesh.metadata())
250 .filter(|metadata| !metadata.is_empty())
251 {
252 metadata.encode(buffer)?;
253 }
254 Ok(())
255 }
256
257 fn encode_header(&self, buffer: &mut EncoderBuffer) -> Status {
258 let (mut major, mut minor) = self.options.get_version();
259 if major == 0 && minor == 0 {
260 (major, minor) = DEFAULT_MESH_VERSION;
262 }
263 let has_metadata = self
264 .mesh
265 .as_ref()
266 .and_then(|mesh| mesh.metadata())
267 .is_some_and(|metadata| !metadata.is_empty());
268
269 if has_metadata && !has_header_flags(major, minor) {
270 return Err(DracoError::UnsupportedVersion(
271 "Metadata requires Draco bitstream version 1.3 or newer".to_string(),
272 ));
273 }
274
275 let method_int = self.options.get_global_int("encoding_method", -1);
277 let method = if method_int == -1 {
278 if self.options.get_speed() == 10 {
279 0
280 } else {
281 1
282 }
283 } else if method_int == 1 {
284 1
285 } else {
286 0
287 };
288
289 #[cfg(not(feature = "legacy_bitstream_encode"))]
290 if method == 1 {
291 let bitstream_version = crate::version::bitstream_version(major, minor);
292 if bitstream_version < 0x0202 {
293 return Err(DracoError::UnsupportedVersion(
294 "EdgeBreaker mesh encoding before bitstream 2.2 requires the \
295 legacy_bitstream_encode feature"
296 .to_string(),
297 ));
298 }
299 if self.options.get_global_int("force_predictive_traversal", 0) != 0 {
300 return Err(DracoError::UnsupportedFeature(
301 "force_predictive_traversal requires the legacy_bitstream_encode feature"
302 .to_string(),
303 ));
304 }
305 }
306 #[cfg(not(feature = "legacy_bitstream_encode"))]
307 match self.options.get_prediction_scheme() {
308 2 | 3 => {
309 return Err(DracoError::UnsupportedFeature(
310 "legacy prediction schemes require the legacy_bitstream_encode feature"
311 .to_string(),
312 ));
313 }
314 _ => {}
315 }
316
317 buffer.encode_data(b"DRACO");
318
319 buffer.encode_u8(major);
320 buffer.encode_u8(minor);
321 buffer.set_version(major, minor);
322 buffer.encode_u8(self.get_geometry_type() as u8);
323 buffer.encode_u8(method);
324
325 let flags = if has_metadata { METADATA_FLAG_MASK } else { 0 };
330 buffer.encode_u16(flags);
331 Ok(())
332 }
333
334 fn encode_geometry_data(&mut self, out_buffer: &mut EncoderBuffer) -> Status {
335 self.encode_connectivity(out_buffer)?;
337
338 if self
340 .options
341 .get_global_int("store_number_of_encoded_faces", 0)
342 != 0
343 {
344 self.compute_number_of_encoded_faces();
345 }
346
347 self.encode_attributes(out_buffer)?;
349 self.build_encoded_mesh_info()?;
350
351 Ok(())
352 }
353
354 fn encode_connectivity(&mut self, out_buffer: &mut EncoderBuffer) -> Status {
355 let mesh = self
356 .mesh
357 .as_ref()
358 .expect("mesh must be set before encoding");
359
360 let method_int = self.options.get_global_int("encoding_method", -1);
362 let method = if method_int == -1 {
363 if self.options.get_speed() == 10 {
364 MeshEncodingMethod::MeshSequentialEncoding
365 } else {
366 MeshEncodingMethod::MeshEdgebreakerEncoding
367 }
368 } else if method_int == 1 {
369 MeshEncodingMethod::MeshEdgebreakerEncoding
370 } else {
371 MeshEncodingMethod::MeshSequentialEncoding
372 };
373 self.method = if method == MeshEncodingMethod::MeshEdgebreakerEncoding {
374 1
375 } else {
376 0
377 };
378
379 let speed = self.options.get_speed();
382 let split_on_seams_explicit = self.options.get_global_int("split_mesh_on_seams", -1);
384 let use_single_connectivity = if split_on_seams_explicit >= 0 {
385 split_on_seams_explicit != 0
386 } else {
387 speed >= 6
388 };
389
390 if method == MeshEncodingMethod::MeshEdgebreakerEncoding {
392 let (faces, point_to_vertex_map) = if use_single_connectivity {
393 let faces: Vec<[crate::geometry_indices::VertexIndex; 3]> = (0..mesh.num_faces())
395 .map(|i| {
396 let face = mesh.face(FaceIndex(i as u32));
397 [
398 crate::geometry_indices::VertexIndex(face[0].0),
399 crate::geometry_indices::VertexIndex(face[1].0),
400 crate::geometry_indices::VertexIndex(face[2].0),
401 ]
402 })
403 .collect();
404 let point_to_vertex: Vec<u32> = (0..mesh.num_points() as u32).collect();
406 (faces, point_to_vertex)
407 } else {
408 self.create_corner_table_from_position_attribute(mesh)
410 };
411
412 let mut corner_table = CornerTable::new(0);
414 corner_table.init(&faces);
415
416 self.corner_table = Some(corner_table);
417 self.point_to_vertex_map = Some(point_to_vertex_map);
418 self.edgebreaker_attribute_connectivity.clear();
419 if !use_single_connectivity {
420 if let Some(ref ct) = self.corner_table {
421 for i in 0..mesh.num_attributes() {
422 let att = mesh.attribute(i);
423 if att.attribute_type() != GeometryAttributeType::Position {
424 self.edgebreaker_attribute_connectivity
425 .push(EdgebreakerAttributeConnectivity::build(mesh, ct, i));
426 }
427 }
428 }
429 }
430 } else {
431 let point_to_vertex: Vec<u32> = (0..mesh.num_points() as u32).collect();
433 self.point_to_vertex_map = Some(point_to_vertex);
434 self.edgebreaker_attribute_connectivity.clear();
435 }
436 self.use_single_connectivity = use_single_connectivity;
437
438 match method {
439 MeshEncodingMethod::MeshSequentialEncoding => {
440 self.encode_sequential_connectivity(out_buffer)
441 }
442 MeshEncodingMethod::MeshEdgebreakerEncoding => {
443 self.encode_edgebreaker_connectivity(out_buffer)
444 }
445 }
446 }
447
448 fn encode_edgebreaker_connectivity(&mut self, out_buffer: &mut EncoderBuffer) -> Status {
449 let mesh = self
450 .mesh
451 .as_ref()
452 .expect("mesh must be set before encoding");
453 let corner_table = self
454 .corner_table
455 .as_ref()
456 .expect("corner_table must be set before edgebreaker encoding");
457
458 let mut encoder = MeshEdgebreakerEncoder::new(mesh.num_faces(), mesh.num_points());
459 #[cfg(feature = "legacy_bitstream_encode")]
462 encoder.set_force_predictive(
463 self.options.get_global_int("force_predictive_traversal", 0) == 1,
464 );
465 let (point_ids, data_to_corner_map, vertex_to_data_map) = encoder.encode_connectivity(
466 mesh,
467 corner_table,
468 &self.edgebreaker_attribute_connectivity,
469 out_buffer,
470 self.options.get_speed() as usize,
471 )?;
472 #[cfg(feature = "debug_logs")]
473 {
474 debug_log!("DEBUG: encode_edgebreaker_connectivity: point_ids.len()={}, data_to_corner_map.len()={}, vertex_to_data_map.len()={}",
475 point_ids.len(), data_to_corner_map.len(), vertex_to_data_map.len());
476 }
477 self.point_ids = point_ids;
478
479 self.data_to_corner_map = Some(data_to_corner_map);
481 self.vertex_to_data_map = Some(vertex_to_data_map);
482
483 Ok(())
484 }
485
486 fn create_corner_table_from_position_attribute(
492 &self,
493 mesh: &Mesh,
494 ) -> (Vec<[crate::geometry_indices::VertexIndex; 3]>, Vec<u32>) {
495 use crate::geometry_attribute::GeometryAttributeType;
496
497 let pos_att_id = mesh.named_attribute_id(GeometryAttributeType::Position);
498 if pos_att_id < 0 {
499 let faces: Vec<[crate::geometry_indices::VertexIndex; 3]> = (0..mesh.num_faces())
501 .map(|i| {
502 let face = mesh.face(FaceIndex(i as u32));
503 [
504 crate::geometry_indices::VertexIndex(face[0].0),
505 crate::geometry_indices::VertexIndex(face[1].0),
506 crate::geometry_indices::VertexIndex(face[2].0),
507 ]
508 })
509 .collect();
510 let point_to_vertex: Vec<u32> = (0..mesh.num_points() as u32).collect();
511 return (faces, point_to_vertex);
512 }
513
514 let pos_att = mesh.attribute(pos_att_id);
515 let _buffer = pos_att.buffer();
516 let num_components = pos_att.num_components() as usize;
517 let _byte_stride = match pos_att.data_type() {
518 crate::draco_types::DataType::Float32 => num_components * 4,
519 crate::draco_types::DataType::Float64 => num_components * 8,
520 crate::draco_types::DataType::Int8 | crate::draco_types::DataType::Uint8 => {
521 num_components
522 }
523 crate::draco_types::DataType::Int16 | crate::draco_types::DataType::Uint16 => {
524 num_components * 2
525 }
526 crate::draco_types::DataType::Int32 | crate::draco_types::DataType::Uint32 => {
527 num_components * 4
528 }
529 crate::draco_types::DataType::Int64 | crate::draco_types::DataType::Uint64 => {
530 num_components * 8
531 }
532 _ => num_components * 4, };
534
535 let mut point_to_vertex: Vec<u32> = vec![0; mesh.num_points()];
538 for i in 0..mesh.num_points() {
539 let pt = PointIndex(i as u32);
540 let val_idx = pos_att.mapped_index(pt);
541 point_to_vertex[i] = val_idx.0;
542 }
543
544 let faces: Vec<[crate::geometry_indices::VertexIndex; 3]> = (0..mesh.num_faces())
546 .map(|i| {
547 let face = mesh.face(FaceIndex(i as u32));
548 [
549 crate::geometry_indices::VertexIndex(point_to_vertex[face[0].0 as usize]),
550 crate::geometry_indices::VertexIndex(point_to_vertex[face[1].0 as usize]),
551 crate::geometry_indices::VertexIndex(point_to_vertex[face[2].0 as usize]),
552 ]
553 })
554 .collect();
555
556 #[cfg(feature = "debug_logs")]
557 {
558 debug_log!(
559 "Rust created faces (first 12): {:?}",
560 faces
561 .iter()
562 .take(12)
563 .map(|f| [f[0].0, f[1].0, f[2].0])
564 .collect::<Vec<_>>()
565 );
566 debug_log!(
567 "Rust point_to_vertex (first 25): {:?}",
568 point_to_vertex.iter().take(25).cloned().collect::<Vec<_>>()
569 );
570 }
571 (faces, point_to_vertex)
572 }
573
574 fn encode_sequential_connectivity(&mut self, out_buffer: &mut EncoderBuffer) -> Status {
575 let mesh = self
576 .mesh
577 .as_ref()
578 .expect("mesh must be set before encoding");
579
580 let major = out_buffer.version_major();
583 let minor = out_buffer.version_minor();
584 if !uses_varint_encoding(major, minor) {
585 out_buffer.encode_u32(mesh.num_faces() as u32);
586 out_buffer.encode_u32(mesh.num_points() as u32);
587 } else {
588 out_buffer.encode_varint(mesh.num_faces() as u64);
589 out_buffer.encode_varint(mesh.num_points() as u64);
590 }
591
592 if mesh.num_faces() > 0 && mesh.num_points() > 0 {
593 out_buffer.encode_u8(1); if mesh.num_points() < 256 {
595 for face_id in 0..mesh.num_faces() {
596 let face = mesh.face(FaceIndex(face_id as u32));
597 for i in 0..3 {
598 out_buffer.encode_u8(face[i].0 as u8);
599 }
600 }
601 } else if mesh.num_points() < 65536 {
602 for face_id in 0..mesh.num_faces() {
603 let face = mesh.face(FaceIndex(face_id as u32));
604 for i in 0..3 {
605 out_buffer.encode_u16(face[i].0 as u16);
606 }
607 }
608 } else if mesh.num_points() < (1 << 21) {
609 for face_id in 0..mesh.num_faces() {
612 let face = mesh.face(FaceIndex(face_id as u32));
613 for i in 0..3 {
614 out_buffer.encode_varint(face[i].0 as u64);
615 }
616 }
617 } else {
618 for face_id in 0..mesh.num_faces() {
620 let face = mesh.face(FaceIndex(face_id as u32));
621 for i in 0..3 {
622 out_buffer.encode_u32(face[i].0);
623 }
624 }
625 }
626 }
627
628 self.point_ids = (0..mesh.num_points())
630 .map(|i| PointIndex(i as u32))
631 .collect();
632
633 Ok(())
634 }
635
636 fn encode_attributes(&mut self, out_buffer: &mut EncoderBuffer) -> Status {
637 let mesh = self
643 .mesh
644 .as_ref()
645 .expect("mesh must be set before encoding");
646
647 let method_int = self.options.get_global_int("encoding_method", -1);
648 let is_edgebreaker = if method_int == -1 {
651 self.options.get_speed() != 10
652 } else {
653 method_int == 1
654 };
655
656 if is_edgebreaker && !self.use_single_connectivity {
657 return self.encode_edgebreaker_attributes_split(out_buffer);
658 }
659
660 let num_attributes = mesh.num_attributes();
665 let num_encoders = if num_attributes > 0 { 1 } else { 0 };
666 let major = out_buffer.version_major();
668 let minor = out_buffer.version_minor();
669
670 out_buffer.encode_u8(num_encoders as u8);
671
672 if num_encoders > 0 && is_edgebreaker {
675 out_buffer.encode_u8((-1i8) as u8); out_buffer.encode_u8(0); if crate::version::bitstream_version(major, minor) >= 0x0102 {
683 let encoding_speed = self.options.get_speed();
686 let traversal_method: u8 = if encoding_speed == 0 { 1 } else { 0 };
687 out_buffer.encode_u8(traversal_method);
688 }
689 }
690 let mut decoder_types: Vec<u8> = Vec::with_capacity(mesh.num_attributes() as usize);
693
694 if num_encoders > 0 {
701 if !uses_varint_encoding(major, minor) {
704 out_buffer.encode_u32(mesh.num_attributes() as u32);
705 } else {
706 out_buffer.encode_varint(mesh.num_attributes() as u64);
707 }
708
709 for i in 0..mesh.num_attributes() {
711 let att = mesh.attribute(i);
712
713 #[cfg(feature = "debug_logs")]
714 {
715 debug_log!("DEBUG: Encoder encoding attribute {} metadata. Type: {:?}, Components: {}, Data: {:?}", i, att.attribute_type(), att.num_components(), att.data_type());
716 }
717 out_buffer.encode_u8(att.attribute_type() as u8);
718 out_buffer.encode_u8(att.data_type() as u8);
719 out_buffer.encode_u8(att.num_components());
720 out_buffer.encode_u8(if att.normalized() { 1 } else { 0 });
721
722 if !uses_varint_unique_id(major, minor) {
723 out_buffer.encode_u16(att.unique_id() as u16);
724 } else {
725 out_buffer.encode_varint(att.unique_id() as u64);
726 }
727 }
728
729 for i in 0..mesh.num_attributes() {
731 let att = mesh.attribute(i);
732 let quantization_bits = self.options.get_attribute_int(i, "quantization_bits", -1);
733 let is_quantized = quantization_bits > 0
734 && (att.data_type() == DataType::Float32
735 || att.data_type() == DataType::Float64);
736 let is_normal = att.attribute_type() == GeometryAttributeType::Normal;
737
738 let decoder_type: u8 = if is_quantized {
739 if is_normal {
740 3
741 } else {
742 2
743 }
744 } else if att.data_type() != DataType::Float32 {
745 1
746 } else {
747 0
748 };
749 out_buffer.encode_u8(decoder_type);
750 decoder_types.push(decoder_type);
751 }
752 }
753
754 let mut quantization_transforms: Vec<Option<AttributeQuantizationTransform>> = Vec::new();
759 let mut portable_attributes: Vec<Option<PointAttribute>> = Vec::new();
760 let mut normal_encoders: Vec<Option<SequentialNormalAttributeEncoder>> = Vec::new();
761
762 for i in 0..mesh.num_attributes() {
764 let att = mesh.attribute(i);
765 let decoder_type = decoder_types[i as usize];
766 let quantization_bits = self.options.get_attribute_int(i, "quantization_bits", -1);
767
768 match decoder_type {
769 3 => {
770 let mut encoder = SequentialNormalAttributeEncoder::new();
772 if !encoder.init(
773 self.point_cloud().expect("point_cloud set"),
774 i,
775 &self.options,
776 ) {
777 return Err(DracoError::DracoError(
778 "Failed to init normal encoder".to_string(),
779 ));
780 }
781 if !encoder.encode_values(
782 self.point_cloud().expect("point_cloud set"),
783 &self.point_ids,
784 out_buffer,
785 &self.options,
786 self,
787 ) {
788 return Err(DracoError::DracoError(
789 "Failed to encode normal values".to_string(),
790 ));
791 }
792 normal_encoders.push(Some(encoder));
793 quantization_transforms.push(None);
794 portable_attributes.push(None);
795 }
796 2 => {
797 let mut q_transform = AttributeQuantizationTransform::new();
799 if !q_transform.compute_parameters(att, quantization_bits) {
800 return Err(DracoError::DracoError(
801 "Failed to compute quantization parameters".to_string(),
802 ));
803 }
804 let mut portable = PointAttribute::default();
805 if !q_transform.transform_attribute(att, &self.point_ids, &mut portable) {
806 return Err(DracoError::DracoError(
807 "Failed to quantize attribute".to_string(),
808 ));
809 }
810
811 let mut att_encoder = SequentialIntegerAttributeEncoder::new();
812 att_encoder.init(i);
813 if !att_encoder.encode_values(
814 mesh as &PointCloud,
815 &self.point_ids,
816 out_buffer,
817 &self.options,
818 self,
819 Some(&portable),
820 true,
821 ) {
822 return Err(DracoError::DracoError(format!(
823 "Failed to encode attribute {}",
824 i
825 )));
826 }
827
828 quantization_transforms.push(Some(q_transform));
829 portable_attributes.push(Some(portable));
830 normal_encoders.push(None);
831 }
832 1 => {
833 let mut att_encoder = SequentialIntegerAttributeEncoder::new();
835 att_encoder.init(i);
836 if !att_encoder.encode_values(
837 mesh as &PointCloud,
838 &self.point_ids,
839 out_buffer,
840 &self.options,
841 self,
842 None,
843 true,
844 ) {
845 return Err(DracoError::DracoError(format!(
846 "Failed to encode attribute {}",
847 i
848 )));
849 }
850 quantization_transforms.push(None);
851 portable_attributes.push(None);
852 normal_encoders.push(None);
853 }
854 0 => {
855 let mut att_encoder = SequentialAttributeEncoder::new();
857 att_encoder.init(i);
858 if !att_encoder.encode_values(mesh as &PointCloud, &self.point_ids, out_buffer)
859 {
860 return Err(DracoError::DracoError(format!(
861 "Failed to encode attribute {}",
862 i
863 )));
864 }
865 quantization_transforms.push(None);
866 portable_attributes.push(None);
867 normal_encoders.push(None);
868 }
869 _ => {
870 return Err(DracoError::DracoError(format!(
871 "Unsupported encoder type {}",
872 decoder_type
873 )));
874 }
875 }
876 }
877
878 for i in 0..mesh.num_attributes() {
880 let decoder_type = decoder_types[i as usize];
881
882 match decoder_type {
883 3 => {
884 let bitstream_version = crate::version::bitstream_version(major, minor);
886 if bitstream_version != 0 && bitstream_version < 0x0200 {
887 continue;
888 }
889 if let Some(ref encoder) = normal_encoders[i as usize] {
890 if !encoder.encode_data_needed_by_portable_transform(out_buffer) {
891 return Err(DracoError::DracoError(
892 "Failed to encode normal transform data".to_string(),
893 ));
894 }
895 }
896 }
897 2 => {
898 if let Some(ref q_transform) = quantization_transforms[i as usize] {
900 if !q_transform.encode_parameters(out_buffer) {
901 return Err(DracoError::DracoError(
902 "Failed to encode quantization parameters".to_string(),
903 ));
904 }
905 }
906 }
907 1 | 0 => {
908 }
910 _ => {}
911 }
912 }
913
914 Ok(())
915 }
916
917 fn encode_edgebreaker_attributes_split(&mut self, out_buffer: &mut EncoderBuffer) -> Status {
918 let mesh = self
919 .mesh
920 .as_ref()
921 .expect("mesh must be set before encoding");
922 let mut groups: Vec<(i8, Vec<i32>)> = Vec::new();
923 let mut position_attrs = Vec::new();
924 for i in 0..mesh.num_attributes() {
925 if mesh.attribute(i).attribute_type() == GeometryAttributeType::Position {
926 position_attrs.push(i);
927 }
928 }
929 if !position_attrs.is_empty() {
930 groups.push((-1, position_attrs));
931 }
932 for (data_id, attr_conn) in self.edgebreaker_attribute_connectivity.iter().enumerate() {
933 groups.push((data_id as i8, vec![attr_conn.attribute_id]));
934 }
935
936 out_buffer.encode_u8(groups.len() as u8);
937
938 let major = out_buffer.version_major();
939 let minor = out_buffer.version_minor();
940 let writes_traversal_method = crate::version::bitstream_version(major, minor) >= 0x0102;
941 let traversal_method: u8 = if self.options.get_speed() == 0 { 1 } else { 0 };
942 for (att_data_id, _) in &groups {
943 out_buffer.encode_u8(*att_data_id as u8);
944 let element_type = if *att_data_id >= 0
945 && !self.edgebreaker_attribute_connectivity[*att_data_id as usize].no_interior_seams
946 {
947 1 } else {
949 0 };
951 out_buffer.encode_u8(element_type);
952 if writes_traversal_method {
953 out_buffer.encode_u8(traversal_method);
954 }
955 }
956
957 let mut decoder_types_by_group: Vec<Vec<u8>> = Vec::with_capacity(groups.len());
958
959 for (_, attr_ids) in &groups {
960 if !uses_varint_encoding(major, minor) {
961 out_buffer.encode_u32(attr_ids.len() as u32);
962 } else {
963 out_buffer.encode_varint(attr_ids.len() as u64);
964 }
965
966 for &att_id in attr_ids {
967 let att = mesh.attribute(att_id);
968 out_buffer.encode_u8(att.attribute_type() as u8);
969 out_buffer.encode_u8(att.data_type() as u8);
970 out_buffer.encode_u8(att.num_components());
971 out_buffer.encode_u8(if att.normalized() { 1 } else { 0 });
972 if !uses_varint_unique_id(major, minor) {
973 out_buffer.encode_u16(att.unique_id() as u16);
974 } else {
975 out_buffer.encode_varint(att.unique_id() as u64);
976 }
977 }
978
979 let mut decoder_types = Vec::with_capacity(attr_ids.len());
980 for &att_id in attr_ids {
981 let decoder_type = self.decoder_type_for_attribute(att_id);
982 out_buffer.encode_u8(decoder_type);
983 decoder_types.push(decoder_type);
984 }
985 decoder_types_by_group.push(decoder_types);
986 }
987
988 for (group_i, (att_data_id, attr_ids)) in groups.iter().enumerate() {
989 let point_ids = if *att_data_id >= 0 {
990 self.prepare_active_attribute_connectivity(*att_data_id as usize)?
991 } else {
992 self.active_corner_table = None;
993 self.active_data_to_corner_map = None;
994 self.active_vertex_to_data_map = None;
995 self.point_ids.clone()
996 };
997
998 self.encode_attribute_group_values(
999 attr_ids,
1000 &decoder_types_by_group[group_i],
1001 &point_ids,
1002 out_buffer,
1003 )?;
1004 }
1005
1006 self.active_corner_table = None;
1007 self.active_data_to_corner_map = None;
1008 self.active_vertex_to_data_map = None;
1009 Ok(())
1010 }
1011
1012 fn decoder_type_for_attribute(&self, att_id: i32) -> u8 {
1013 let mesh = self
1014 .mesh
1015 .as_ref()
1016 .expect("mesh must be set before encoding");
1017 let att = mesh.attribute(att_id);
1018 let quantization_bits = self
1019 .options
1020 .get_attribute_int(att_id, "quantization_bits", -1);
1021 let is_quantized = quantization_bits > 0
1022 && (att.data_type() == DataType::Float32 || att.data_type() == DataType::Float64);
1023 let is_normal = att.attribute_type() == GeometryAttributeType::Normal;
1024
1025 if is_quantized {
1026 if is_normal {
1027 3
1028 } else {
1029 2
1030 }
1031 } else if att.data_type() != DataType::Float32 {
1032 1
1033 } else {
1034 0
1035 }
1036 }
1037
1038 fn prepare_active_attribute_connectivity(
1039 &mut self,
1040 data_id: usize,
1041 ) -> Result<Vec<PointIndex>, DracoError> {
1042 let mesh = self
1043 .mesh
1044 .as_ref()
1045 .expect("mesh must be set before encoding");
1046 let base_ct = self
1047 .corner_table
1048 .as_ref()
1049 .ok_or_else(|| DracoError::DracoError("corner_table must be set".to_string()))?;
1050 let attr_conn = self
1051 .edgebreaker_attribute_connectivity
1052 .get(data_id)
1053 .ok_or_else(|| {
1054 DracoError::DracoError("Invalid attribute connectivity id".to_string())
1055 })?;
1056
1057 if attr_conn.no_interior_seams {
1058 self.active_corner_table = None;
1059 self.active_data_to_corner_map = None;
1060 self.active_vertex_to_data_map = None;
1061 return Ok(self.point_ids.clone());
1062 }
1063
1064 let mut attr_ct = base_ct.clone();
1065 for c_idx in 0..attr_conn.seam_edges.len() {
1066 if !attr_conn.seam_edges[c_idx] {
1067 continue;
1068 }
1069 let c = crate::geometry_indices::CornerIndex(c_idx as u32);
1070 let opp = attr_ct.opposite(c);
1071 if opp != crate::geometry_indices::INVALID_CORNER_INDEX {
1072 attr_ct.set_opposite(c, crate::geometry_indices::INVALID_CORNER_INDEX);
1073 attr_ct.set_opposite(opp, crate::geometry_indices::INVALID_CORNER_INDEX);
1074 }
1075 }
1076 let base_num_vertices = attr_ct.num_vertices();
1077 if !attr_ct.compute_vertex_corners(base_num_vertices) {
1078 return Err(DracoError::DracoError(
1079 "Failed to compute attribute seam corner table".to_string(),
1080 ));
1081 }
1082
1083 let mut point_ids = Vec::with_capacity(attr_ct.vertex_corners.len());
1084 let mut data_to_corner_map = Vec::with_capacity(attr_ct.vertex_corners.len());
1085 let mut vertex_to_data_map = vec![-1i32; attr_ct.num_vertices()];
1086 for (data_id, &corner) in attr_ct.vertex_corners.iter().enumerate() {
1087 if corner == crate::geometry_indices::INVALID_CORNER_INDEX {
1088 point_ids.push(PointIndex(0));
1089 data_to_corner_map.push(crate::geometry_indices::INVALID_CORNER_INDEX.0);
1090 continue;
1091 }
1092 let face = mesh.face(FaceIndex(corner.0 / 3));
1093 let point_id = face[(corner.0 % 3) as usize];
1094 point_ids.push(point_id);
1095 data_to_corner_map.push(corner.0);
1096 let vertex = attr_ct.vertex(corner);
1097 if vertex != crate::geometry_indices::INVALID_VERTEX_INDEX
1098 && (vertex.0 as usize) < vertex_to_data_map.len()
1099 {
1100 vertex_to_data_map[vertex.0 as usize] = data_id as i32;
1101 }
1102 }
1103
1104 self.active_corner_table = Some(attr_ct);
1105 self.active_data_to_corner_map = Some(data_to_corner_map);
1106 self.active_vertex_to_data_map = Some(vertex_to_data_map);
1107 Ok(point_ids)
1108 }
1109
1110 fn encode_attribute_group_values(
1111 &mut self,
1112 attr_ids: &[i32],
1113 decoder_types: &[u8],
1114 point_ids: &[PointIndex],
1115 out_buffer: &mut EncoderBuffer,
1116 ) -> Status {
1117 let mesh = self
1118 .mesh
1119 .as_ref()
1120 .expect("mesh must be set before encoding");
1121 let mut quantization_transforms: Vec<Option<AttributeQuantizationTransform>> = Vec::new();
1122 let mut normal_encoders: Vec<Option<SequentialNormalAttributeEncoder>> = Vec::new();
1123
1124 for (local_i, &att_id) in attr_ids.iter().enumerate() {
1125 let att = mesh.attribute(att_id);
1126 let decoder_type = decoder_types[local_i];
1127 let quantization_bits = self
1128 .options
1129 .get_attribute_int(att_id, "quantization_bits", -1);
1130
1131 match decoder_type {
1132 3 => {
1133 let mut encoder = SequentialNormalAttributeEncoder::new();
1134 if !encoder.init(
1135 self.point_cloud().expect("point_cloud set"),
1136 att_id,
1137 &self.options,
1138 ) {
1139 return Err(DracoError::DracoError(
1140 "Failed to init normal encoder".to_string(),
1141 ));
1142 }
1143 if !encoder.encode_values(
1144 self.point_cloud().expect("point_cloud set"),
1145 point_ids,
1146 out_buffer,
1147 &self.options,
1148 self,
1149 ) {
1150 return Err(DracoError::DracoError(
1151 "Failed to encode normal values".to_string(),
1152 ));
1153 }
1154 normal_encoders.push(Some(encoder));
1155 quantization_transforms.push(None);
1156 }
1157 2 => {
1158 let mut q_transform = AttributeQuantizationTransform::new();
1159 if !q_transform.compute_parameters(att, quantization_bits) {
1160 return Err(DracoError::DracoError(
1161 "Failed to compute quantization parameters".to_string(),
1162 ));
1163 }
1164 let mut portable = PointAttribute::default();
1165 if !q_transform.transform_attribute(att, point_ids, &mut portable) {
1166 return Err(DracoError::DracoError(
1167 "Failed to quantize attribute".to_string(),
1168 ));
1169 }
1170
1171 let mut att_encoder = SequentialIntegerAttributeEncoder::new();
1172 att_encoder.init(att_id);
1173 if !att_encoder.encode_values(
1174 mesh as &PointCloud,
1175 point_ids,
1176 out_buffer,
1177 &self.options,
1178 self,
1179 Some(&portable),
1180 true,
1181 ) {
1182 return Err(DracoError::DracoError(format!(
1183 "Failed to encode attribute {}",
1184 att_id
1185 )));
1186 }
1187 quantization_transforms.push(Some(q_transform));
1188 normal_encoders.push(None);
1189 }
1190 1 => {
1191 let mut att_encoder = SequentialIntegerAttributeEncoder::new();
1192 att_encoder.init(att_id);
1193 if !att_encoder.encode_values(
1194 mesh as &PointCloud,
1195 point_ids,
1196 out_buffer,
1197 &self.options,
1198 self,
1199 None,
1200 true,
1201 ) {
1202 return Err(DracoError::DracoError(format!(
1203 "Failed to encode attribute {}",
1204 att_id
1205 )));
1206 }
1207 quantization_transforms.push(None);
1208 normal_encoders.push(None);
1209 }
1210 0 => {
1211 let mut att_encoder = SequentialAttributeEncoder::new();
1212 att_encoder.init(att_id);
1213 if !att_encoder.encode_values(mesh as &PointCloud, point_ids, out_buffer) {
1214 return Err(DracoError::DracoError(format!(
1215 "Failed to encode attribute {}",
1216 att_id
1217 )));
1218 }
1219 quantization_transforms.push(None);
1220 normal_encoders.push(None);
1221 }
1222 _ => {
1223 return Err(DracoError::DracoError(format!(
1224 "Unsupported encoder type {}",
1225 decoder_type
1226 )));
1227 }
1228 }
1229 }
1230
1231 for (local_i, &decoder_type) in decoder_types.iter().enumerate() {
1232 match decoder_type {
1233 3 => {
1234 let major = out_buffer.version_major();
1235 let minor = out_buffer.version_minor();
1236 let bitstream_version = crate::version::bitstream_version(major, minor);
1237 if bitstream_version != 0 && bitstream_version < 0x0200 {
1238 continue;
1239 }
1240 if let Some(ref encoder) = normal_encoders[local_i] {
1241 if !encoder.encode_data_needed_by_portable_transform(out_buffer) {
1242 return Err(DracoError::DracoError(
1243 "Failed to encode normal transform data".to_string(),
1244 ));
1245 }
1246 }
1247 }
1248 2 => {
1249 if let Some(ref q_transform) = quantization_transforms[local_i] {
1250 if !q_transform.encode_parameters(out_buffer) {
1251 return Err(DracoError::DracoError(
1252 "Failed to encode quantization parameters".to_string(),
1253 ));
1254 }
1255 }
1256 }
1257 1 | 0 => {}
1258 _ => {}
1259 }
1260 }
1261
1262 Ok(())
1263 }
1264
1265 fn compute_number_of_encoded_faces(&mut self) {
1266 if let Some(ref mesh) = self.mesh {
1267 self.num_encoded_faces = mesh.num_faces();
1268 }
1269 }
1270
1271 fn build_encoded_mesh_info(&mut self) -> Status {
1272 let num_attributes = self
1273 .mesh
1274 .as_ref()
1275 .expect("mesh must be set before encoding")
1276 .num_attributes();
1277 let mut attributes = Vec::with_capacity(num_attributes as usize);
1278 let mut encoded_num_points = self.point_ids.len();
1279
1280 for att_id in 0..num_attributes {
1281 let point_ids = self.encoded_point_ids_for_attribute(att_id)?;
1282 let num_encoded_values = point_ids.len();
1283 encoded_num_points = encoded_num_points.max(num_encoded_values);
1284
1285 let (position_min, position_max) =
1286 self.position_bounds_for_attribute(att_id, &point_ids)?;
1287 let att = self
1288 .mesh
1289 .as_ref()
1290 .expect("mesh must be set before encoding")
1291 .attribute(att_id);
1292 attributes.push(EncodedAttributeInfo {
1293 source_attribute_id: att_id,
1294 attribute_type: att.attribute_type(),
1295 data_type: att.data_type(),
1296 num_components: att.num_components(),
1297 normalized: att.normalized(),
1298 unique_id: att.unique_id(),
1299 num_encoded_values,
1300 position_min,
1301 position_max,
1302 });
1303 }
1304
1305 let (source_num_points, num_faces) = self
1306 .mesh
1307 .as_ref()
1308 .map(|mesh| (mesh.num_points(), mesh.num_faces()))
1309 .expect("mesh must be set before encoding");
1310 if self.method == 0 {
1311 encoded_num_points = source_num_points;
1312 } else {
1313 encoded_num_points = self.encoded_num_points_for_mesh(encoded_num_points)?;
1314 }
1315
1316 self.active_corner_table = None;
1317 self.active_data_to_corner_map = None;
1318 self.active_vertex_to_data_map = None;
1319 self.encoded_mesh_info = Some(EncodedMeshInfo {
1320 encoding_method: self.method,
1321 num_encoded_faces: num_faces,
1322 num_encoded_points: encoded_num_points,
1323 attributes,
1324 });
1325 Ok(())
1326 }
1327
1328 fn encoded_point_ids_for_attribute(
1329 &mut self,
1330 att_id: i32,
1331 ) -> Result<Vec<PointIndex>, DracoError> {
1332 if self.method == 0 || self.use_single_connectivity {
1333 return Ok(self.point_ids.clone());
1334 }
1335
1336 if let Some(data_id) = self
1337 .edgebreaker_attribute_connectivity
1338 .iter()
1339 .position(|connectivity| connectivity.attribute_id == att_id)
1340 {
1341 return self.prepare_active_attribute_connectivity(data_id);
1342 }
1343
1344 Ok(self.point_ids.clone())
1345 }
1346
1347 fn encoded_num_points_for_mesh(&mut self, base_num_points: usize) -> Result<usize, DracoError> {
1348 if self.method == 0 || self.use_single_connectivity {
1349 return Ok(base_num_points);
1350 }
1351
1352 let mut num_points = base_num_points;
1353 for data_id in 0..self.edgebreaker_attribute_connectivity.len() {
1354 if self.edgebreaker_attribute_connectivity[data_id].no_interior_seams {
1355 continue;
1356 }
1357 let point_ids = self.prepare_active_attribute_connectivity(data_id)?;
1358 num_points = num_points.max(point_ids.len());
1359 }
1360 self.active_corner_table = None;
1361 self.active_data_to_corner_map = None;
1362 self.active_vertex_to_data_map = None;
1363 Ok(num_points)
1364 }
1365
1366 fn position_bounds_for_attribute(
1367 &self,
1368 att_id: i32,
1369 point_ids: &[PointIndex],
1370 ) -> Result<PositionBounds, DracoError> {
1371 let mesh = self
1372 .mesh
1373 .as_ref()
1374 .expect("mesh must be set before encoding");
1375 let att = mesh.attribute(att_id);
1376 if att.attribute_type() != GeometryAttributeType::Position {
1377 return Ok((None, None));
1378 }
1379 if att.num_components() != 3 || att.data_type() != DataType::Float32 {
1380 return Ok((None, None));
1381 }
1382
1383 if self.decoder_type_for_attribute(att_id) == 2 {
1384 let quantization_bits = self
1385 .options
1386 .get_attribute_int(att_id, "quantization_bits", -1);
1387 let mut q_transform = AttributeQuantizationTransform::new();
1388 if !q_transform.compute_parameters(att, quantization_bits) {
1389 return Err(DracoError::DracoError(
1390 "Failed to compute position quantization parameters".to_string(),
1391 ));
1392 }
1393
1394 let mut portable = PointAttribute::default();
1395 if !q_transform.transform_attribute(att, point_ids, &mut portable) {
1396 return Err(DracoError::DracoError(
1397 "Failed to quantize position attribute for encoded mesh info".to_string(),
1398 ));
1399 }
1400
1401 let mut dequantized = PointAttribute::new();
1402 dequantized.try_init(
1403 GeometryAttributeType::Position,
1404 3,
1405 DataType::Float32,
1406 false,
1407 portable.size(),
1408 )?;
1409 if !q_transform.inverse_transform_attribute(&portable, &mut dequantized) {
1410 return Err(DracoError::DracoError(
1411 "Failed to dequantize position attribute for encoded mesh info".to_string(),
1412 ));
1413 }
1414
1415 return Self::position_bounds_from_attribute(&dequantized, &[]);
1416 }
1417
1418 Self::position_bounds_from_attribute(att, point_ids)
1419 }
1420
1421 fn position_bounds_from_attribute(
1422 att: &PointAttribute,
1423 point_ids: &[PointIndex],
1424 ) -> Result<PositionBounds, DracoError> {
1425 let count = if point_ids.is_empty() {
1426 att.size()
1427 } else {
1428 point_ids.len()
1429 };
1430 if count == 0 {
1431 return Ok((None, None));
1432 }
1433
1434 let stride = usize::try_from(att.byte_stride()).map_err(|_| {
1435 DracoError::DracoError("Position attribute has invalid byte stride".to_string())
1436 })?;
1437 let bytes = att.buffer().data();
1438 let mut min = [f32::INFINITY; 3];
1439 let mut max = [f32::NEG_INFINITY; 3];
1440
1441 for i in 0..count {
1442 let point = if point_ids.is_empty() {
1443 PointIndex(i as u32)
1444 } else {
1445 point_ids[i]
1446 };
1447 let value_index = att.mapped_index(point);
1448 if value_index == INVALID_ATTRIBUTE_VALUE_INDEX {
1449 return Err(DracoError::DracoError(
1450 "Position attribute point map contains an invalid entry".to_string(),
1451 ));
1452 }
1453
1454 let value_offset = (value_index.0 as usize)
1455 .checked_mul(stride)
1456 .ok_or_else(|| {
1457 DracoError::DracoError("Position attribute offset overflow".to_string())
1458 })?;
1459 for component in 0..3 {
1460 let offset = value_offset
1461 .checked_add(component * DataType::Float32.byte_length())
1462 .ok_or_else(|| {
1463 DracoError::DracoError("Position attribute offset overflow".to_string())
1464 })?;
1465 let end = offset
1466 .checked_add(DataType::Float32.byte_length())
1467 .ok_or_else(|| {
1468 DracoError::DracoError("Position attribute offset overflow".to_string())
1469 })?;
1470 let Some(component_bytes) = bytes.get(offset..end) else {
1471 return Err(DracoError::DracoError(
1472 "Position attribute buffer is shorter than metadata".to_string(),
1473 ));
1474 };
1475 let value = f32::from_le_bytes([
1476 component_bytes[0],
1477 component_bytes[1],
1478 component_bytes[2],
1479 component_bytes[3],
1480 ]);
1481 min[component] = min[component].min(value);
1482 max[component] = max[component].max(value);
1483 }
1484 }
1485
1486 Ok((
1487 Some(min.into_iter().map(f64::from).collect()),
1488 Some(max.into_iter().map(f64::from).collect()),
1489 ))
1490 }
1491}
1492
1493impl Default for MeshEncoder {
1494 fn default() -> Self {
1495 Self::new()
1496 }
1497}