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 buffer.encode_data(b"DRACO");
276
277 buffer.encode_u8(major);
278 buffer.encode_u8(minor);
279 buffer.set_version(major, minor);
280 buffer.encode_u8(self.get_geometry_type() as u8);
281
282 let method_int = self.options.get_global_int("encoding_method", -1);
284 let method = if method_int == -1 {
285 if self.options.get_speed() == 10 {
286 0
287 } else {
288 1
289 }
290 } else if method_int == 1 {
291 1
292 } else {
293 0
294 };
295 buffer.encode_u8(method);
296
297 let flags = if has_metadata { METADATA_FLAG_MASK } else { 0 };
302 buffer.encode_u16(flags);
303 Ok(())
304 }
305
306 fn encode_geometry_data(&mut self, out_buffer: &mut EncoderBuffer) -> Status {
307 self.encode_connectivity(out_buffer)?;
309
310 if self
312 .options
313 .get_global_int("store_number_of_encoded_faces", 0)
314 != 0
315 {
316 self.compute_number_of_encoded_faces();
317 }
318
319 self.encode_attributes(out_buffer)?;
321 self.build_encoded_mesh_info()?;
322
323 Ok(())
324 }
325
326 fn encode_connectivity(&mut self, out_buffer: &mut EncoderBuffer) -> Status {
327 let mesh = self
328 .mesh
329 .as_ref()
330 .expect("mesh must be set before encoding");
331
332 let method_int = self.options.get_global_int("encoding_method", -1);
334 let method = if method_int == -1 {
335 if self.options.get_speed() == 10 {
336 MeshEncodingMethod::MeshSequentialEncoding
337 } else {
338 MeshEncodingMethod::MeshEdgebreakerEncoding
339 }
340 } else if method_int == 1 {
341 MeshEncodingMethod::MeshEdgebreakerEncoding
342 } else {
343 MeshEncodingMethod::MeshSequentialEncoding
344 };
345 self.method = if method == MeshEncodingMethod::MeshEdgebreakerEncoding {
346 1
347 } else {
348 0
349 };
350
351 let speed = self.options.get_speed();
354 let split_on_seams_explicit = self.options.get_global_int("split_mesh_on_seams", -1);
356 let use_single_connectivity = if split_on_seams_explicit >= 0 {
357 split_on_seams_explicit != 0
358 } else {
359 speed >= 6
360 };
361
362 if method == MeshEncodingMethod::MeshEdgebreakerEncoding {
364 let (faces, point_to_vertex_map) = if use_single_connectivity {
365 let faces: Vec<[crate::geometry_indices::VertexIndex; 3]> = (0..mesh.num_faces())
367 .map(|i| {
368 let face = mesh.face(FaceIndex(i as u32));
369 [
370 crate::geometry_indices::VertexIndex(face[0].0),
371 crate::geometry_indices::VertexIndex(face[1].0),
372 crate::geometry_indices::VertexIndex(face[2].0),
373 ]
374 })
375 .collect();
376 let point_to_vertex: Vec<u32> = (0..mesh.num_points() as u32).collect();
378 (faces, point_to_vertex)
379 } else {
380 self.create_corner_table_from_position_attribute(mesh)
382 };
383
384 let mut corner_table = CornerTable::new(0);
386 corner_table.init(&faces);
387
388 self.corner_table = Some(corner_table);
389 self.point_to_vertex_map = Some(point_to_vertex_map);
390 self.edgebreaker_attribute_connectivity.clear();
391 if !use_single_connectivity {
392 if let Some(ref ct) = self.corner_table {
393 for i in 0..mesh.num_attributes() {
394 let att = mesh.attribute(i);
395 if att.attribute_type() != GeometryAttributeType::Position {
396 self.edgebreaker_attribute_connectivity
397 .push(EdgebreakerAttributeConnectivity::build(mesh, ct, i));
398 }
399 }
400 }
401 }
402 } else {
403 let point_to_vertex: Vec<u32> = (0..mesh.num_points() as u32).collect();
405 self.point_to_vertex_map = Some(point_to_vertex);
406 self.edgebreaker_attribute_connectivity.clear();
407 }
408 self.use_single_connectivity = use_single_connectivity;
409
410 match method {
411 MeshEncodingMethod::MeshSequentialEncoding => {
412 self.encode_sequential_connectivity(out_buffer)
413 }
414 MeshEncodingMethod::MeshEdgebreakerEncoding => {
415 self.encode_edgebreaker_connectivity(out_buffer)
416 }
417 }
418 }
419
420 fn encode_edgebreaker_connectivity(&mut self, out_buffer: &mut EncoderBuffer) -> Status {
421 let mesh = self
422 .mesh
423 .as_ref()
424 .expect("mesh must be set before encoding");
425 let corner_table = self
426 .corner_table
427 .as_ref()
428 .expect("corner_table must be set before edgebreaker encoding");
429
430 let mut encoder = MeshEdgebreakerEncoder::new(mesh.num_faces(), mesh.num_points());
431 #[cfg(feature = "legacy_bitstream_encode")]
434 encoder.set_force_predictive(
435 self.options.get_global_int("force_predictive_traversal", 0) == 1,
436 );
437 let (point_ids, data_to_corner_map, vertex_to_data_map) = encoder.encode_connectivity(
438 mesh,
439 corner_table,
440 &self.edgebreaker_attribute_connectivity,
441 out_buffer,
442 self.options.get_speed() as usize,
443 )?;
444 #[cfg(feature = "debug_logs")]
445 {
446 debug_log!("DEBUG: encode_edgebreaker_connectivity: point_ids.len()={}, data_to_corner_map.len()={}, vertex_to_data_map.len()={}",
447 point_ids.len(), data_to_corner_map.len(), vertex_to_data_map.len());
448 }
449 self.point_ids = point_ids;
450
451 self.data_to_corner_map = Some(data_to_corner_map);
453 self.vertex_to_data_map = Some(vertex_to_data_map);
454
455 Ok(())
456 }
457
458 fn create_corner_table_from_position_attribute(
464 &self,
465 mesh: &Mesh,
466 ) -> (Vec<[crate::geometry_indices::VertexIndex; 3]>, Vec<u32>) {
467 use crate::geometry_attribute::GeometryAttributeType;
468
469 let pos_att_id = mesh.named_attribute_id(GeometryAttributeType::Position);
470 if pos_att_id < 0 {
471 let faces: Vec<[crate::geometry_indices::VertexIndex; 3]> = (0..mesh.num_faces())
473 .map(|i| {
474 let face = mesh.face(FaceIndex(i as u32));
475 [
476 crate::geometry_indices::VertexIndex(face[0].0),
477 crate::geometry_indices::VertexIndex(face[1].0),
478 crate::geometry_indices::VertexIndex(face[2].0),
479 ]
480 })
481 .collect();
482 let point_to_vertex: Vec<u32> = (0..mesh.num_points() as u32).collect();
483 return (faces, point_to_vertex);
484 }
485
486 let pos_att = mesh.attribute(pos_att_id);
487 let _buffer = pos_att.buffer();
488 let num_components = pos_att.num_components() as usize;
489 let _byte_stride = match pos_att.data_type() {
490 crate::draco_types::DataType::Float32 => num_components * 4,
491 crate::draco_types::DataType::Float64 => num_components * 8,
492 crate::draco_types::DataType::Int8 | crate::draco_types::DataType::Uint8 => {
493 num_components
494 }
495 crate::draco_types::DataType::Int16 | crate::draco_types::DataType::Uint16 => {
496 num_components * 2
497 }
498 crate::draco_types::DataType::Int32 | crate::draco_types::DataType::Uint32 => {
499 num_components * 4
500 }
501 crate::draco_types::DataType::Int64 | crate::draco_types::DataType::Uint64 => {
502 num_components * 8
503 }
504 _ => num_components * 4, };
506
507 let mut point_to_vertex: Vec<u32> = vec![0; mesh.num_points()];
510 for i in 0..mesh.num_points() {
511 let pt = PointIndex(i as u32);
512 let val_idx = pos_att.mapped_index(pt);
513 point_to_vertex[i] = val_idx.0;
514 }
515
516 let faces: Vec<[crate::geometry_indices::VertexIndex; 3]> = (0..mesh.num_faces())
518 .map(|i| {
519 let face = mesh.face(FaceIndex(i as u32));
520 [
521 crate::geometry_indices::VertexIndex(point_to_vertex[face[0].0 as usize]),
522 crate::geometry_indices::VertexIndex(point_to_vertex[face[1].0 as usize]),
523 crate::geometry_indices::VertexIndex(point_to_vertex[face[2].0 as usize]),
524 ]
525 })
526 .collect();
527
528 #[cfg(feature = "debug_logs")]
529 {
530 debug_log!(
531 "Rust created faces (first 12): {:?}",
532 faces
533 .iter()
534 .take(12)
535 .map(|f| [f[0].0, f[1].0, f[2].0])
536 .collect::<Vec<_>>()
537 );
538 debug_log!(
539 "Rust point_to_vertex (first 25): {:?}",
540 point_to_vertex.iter().take(25).cloned().collect::<Vec<_>>()
541 );
542 }
543 (faces, point_to_vertex)
544 }
545
546 fn encode_sequential_connectivity(&mut self, out_buffer: &mut EncoderBuffer) -> Status {
547 let mesh = self
548 .mesh
549 .as_ref()
550 .expect("mesh must be set before encoding");
551
552 let major = out_buffer.version_major();
555 let minor = out_buffer.version_minor();
556 if !uses_varint_encoding(major, minor) {
557 out_buffer.encode_u32(mesh.num_faces() as u32);
558 out_buffer.encode_u32(mesh.num_points() as u32);
559 } else {
560 out_buffer.encode_varint(mesh.num_faces() as u64);
561 out_buffer.encode_varint(mesh.num_points() as u64);
562 }
563
564 if mesh.num_faces() > 0 && mesh.num_points() > 0 {
565 out_buffer.encode_u8(1); if mesh.num_points() < 256 {
567 for face_id in 0..mesh.num_faces() {
568 let face = mesh.face(FaceIndex(face_id as u32));
569 for i in 0..3 {
570 out_buffer.encode_u8(face[i].0 as u8);
571 }
572 }
573 } else if mesh.num_points() < 65536 {
574 for face_id in 0..mesh.num_faces() {
575 let face = mesh.face(FaceIndex(face_id as u32));
576 for i in 0..3 {
577 out_buffer.encode_u16(face[i].0 as u16);
578 }
579 }
580 } else if mesh.num_points() < (1 << 21) {
581 for face_id in 0..mesh.num_faces() {
584 let face = mesh.face(FaceIndex(face_id as u32));
585 for i in 0..3 {
586 out_buffer.encode_varint(face[i].0 as u64);
587 }
588 }
589 } else {
590 for face_id in 0..mesh.num_faces() {
592 let face = mesh.face(FaceIndex(face_id as u32));
593 for i in 0..3 {
594 out_buffer.encode_u32(face[i].0);
595 }
596 }
597 }
598 }
599
600 self.point_ids = (0..mesh.num_points())
602 .map(|i| PointIndex(i as u32))
603 .collect();
604
605 Ok(())
606 }
607
608 fn encode_attributes(&mut self, out_buffer: &mut EncoderBuffer) -> Status {
609 let mesh = self
615 .mesh
616 .as_ref()
617 .expect("mesh must be set before encoding");
618
619 let method_int = self.options.get_global_int("encoding_method", -1);
620 let is_edgebreaker = if method_int == -1 {
623 self.options.get_speed() != 10
624 } else {
625 method_int == 1
626 };
627
628 if is_edgebreaker && !self.use_single_connectivity {
629 return self.encode_edgebreaker_attributes_split(out_buffer);
630 }
631
632 let num_attributes = mesh.num_attributes();
637 let num_encoders = if num_attributes > 0 { 1 } else { 0 };
638 let major = out_buffer.version_major();
640 let minor = out_buffer.version_minor();
641
642 out_buffer.encode_u8(num_encoders as u8);
643
644 if num_encoders > 0 && is_edgebreaker {
647 out_buffer.encode_u8((-1i8) as u8); out_buffer.encode_u8(0); if crate::version::bitstream_version(major, minor) >= 0x0102 {
655 let encoding_speed = self.options.get_speed();
658 let traversal_method: u8 = if encoding_speed == 0 { 1 } else { 0 };
659 out_buffer.encode_u8(traversal_method);
660 }
661 }
662 let mut decoder_types: Vec<u8> = Vec::with_capacity(mesh.num_attributes() as usize);
665
666 if num_encoders > 0 {
673 if !uses_varint_encoding(major, minor) {
676 out_buffer.encode_u32(mesh.num_attributes() as u32);
677 } else {
678 out_buffer.encode_varint(mesh.num_attributes() as u64);
679 }
680
681 for i in 0..mesh.num_attributes() {
683 let att = mesh.attribute(i);
684
685 #[cfg(feature = "debug_logs")]
686 {
687 debug_log!("DEBUG: Encoder encoding attribute {} metadata. Type: {:?}, Components: {}, Data: {:?}", i, att.attribute_type(), att.num_components(), att.data_type());
688 }
689 out_buffer.encode_u8(att.attribute_type() as u8);
690 out_buffer.encode_u8(att.data_type() as u8);
691 out_buffer.encode_u8(att.num_components());
692 out_buffer.encode_u8(if att.normalized() { 1 } else { 0 });
693
694 if !uses_varint_unique_id(major, minor) {
695 out_buffer.encode_u16(att.unique_id() as u16);
696 } else {
697 out_buffer.encode_varint(att.unique_id() as u64);
698 }
699 }
700
701 for i in 0..mesh.num_attributes() {
703 let att = mesh.attribute(i);
704 let quantization_bits = self.options.get_attribute_int(i, "quantization_bits", -1);
705 let is_quantized = quantization_bits > 0
706 && (att.data_type() == DataType::Float32
707 || att.data_type() == DataType::Float64);
708 let is_normal = att.attribute_type() == GeometryAttributeType::Normal;
709
710 let decoder_type: u8 = if is_quantized {
711 if is_normal {
712 3
713 } else {
714 2
715 }
716 } else if att.data_type() != DataType::Float32 {
717 1
718 } else {
719 0
720 };
721 out_buffer.encode_u8(decoder_type);
722 decoder_types.push(decoder_type);
723 }
724 }
725
726 let mut quantization_transforms: Vec<Option<AttributeQuantizationTransform>> = Vec::new();
731 let mut portable_attributes: Vec<Option<PointAttribute>> = Vec::new();
732 let mut normal_encoders: Vec<Option<SequentialNormalAttributeEncoder>> = Vec::new();
733
734 for i in 0..mesh.num_attributes() {
736 let att = mesh.attribute(i);
737 let decoder_type = decoder_types[i as usize];
738 let quantization_bits = self.options.get_attribute_int(i, "quantization_bits", -1);
739
740 match decoder_type {
741 3 => {
742 let mut encoder = SequentialNormalAttributeEncoder::new();
744 if !encoder.init(
745 self.point_cloud().expect("point_cloud set"),
746 i,
747 &self.options,
748 ) {
749 return Err(DracoError::DracoError(
750 "Failed to init normal encoder".to_string(),
751 ));
752 }
753 if !encoder.encode_values(
754 self.point_cloud().expect("point_cloud set"),
755 &self.point_ids,
756 out_buffer,
757 &self.options,
758 self,
759 ) {
760 return Err(DracoError::DracoError(
761 "Failed to encode normal values".to_string(),
762 ));
763 }
764 normal_encoders.push(Some(encoder));
765 quantization_transforms.push(None);
766 portable_attributes.push(None);
767 }
768 2 => {
769 let mut q_transform = AttributeQuantizationTransform::new();
771 if !q_transform.compute_parameters(att, quantization_bits) {
772 return Err(DracoError::DracoError(
773 "Failed to compute quantization parameters".to_string(),
774 ));
775 }
776 let mut portable = PointAttribute::default();
777 if !q_transform.transform_attribute(att, &self.point_ids, &mut portable) {
778 return Err(DracoError::DracoError(
779 "Failed to quantize attribute".to_string(),
780 ));
781 }
782
783 let mut att_encoder = SequentialIntegerAttributeEncoder::new();
784 att_encoder.init(i);
785 if !att_encoder.encode_values(
786 mesh as &PointCloud,
787 &self.point_ids,
788 out_buffer,
789 &self.options,
790 self,
791 Some(&portable),
792 true,
793 ) {
794 return Err(DracoError::DracoError(format!(
795 "Failed to encode attribute {}",
796 i
797 )));
798 }
799
800 quantization_transforms.push(Some(q_transform));
801 portable_attributes.push(Some(portable));
802 normal_encoders.push(None);
803 }
804 1 => {
805 let mut att_encoder = SequentialIntegerAttributeEncoder::new();
807 att_encoder.init(i);
808 if !att_encoder.encode_values(
809 mesh as &PointCloud,
810 &self.point_ids,
811 out_buffer,
812 &self.options,
813 self,
814 None,
815 true,
816 ) {
817 return Err(DracoError::DracoError(format!(
818 "Failed to encode attribute {}",
819 i
820 )));
821 }
822 quantization_transforms.push(None);
823 portable_attributes.push(None);
824 normal_encoders.push(None);
825 }
826 0 => {
827 let mut att_encoder = SequentialAttributeEncoder::new();
829 att_encoder.init(i);
830 if !att_encoder.encode_values(mesh as &PointCloud, &self.point_ids, out_buffer)
831 {
832 return Err(DracoError::DracoError(format!(
833 "Failed to encode attribute {}",
834 i
835 )));
836 }
837 quantization_transforms.push(None);
838 portable_attributes.push(None);
839 normal_encoders.push(None);
840 }
841 _ => {
842 return Err(DracoError::DracoError(format!(
843 "Unsupported encoder type {}",
844 decoder_type
845 )));
846 }
847 }
848 }
849
850 for i in 0..mesh.num_attributes() {
852 let decoder_type = decoder_types[i as usize];
853
854 match decoder_type {
855 3 => {
856 let bitstream_version = crate::version::bitstream_version(major, minor);
858 if bitstream_version != 0 && bitstream_version < 0x0200 {
859 continue;
860 }
861 if let Some(ref encoder) = normal_encoders[i as usize] {
862 if !encoder.encode_data_needed_by_portable_transform(out_buffer) {
863 return Err(DracoError::DracoError(
864 "Failed to encode normal transform data".to_string(),
865 ));
866 }
867 }
868 }
869 2 => {
870 if let Some(ref q_transform) = quantization_transforms[i as usize] {
872 if !q_transform.encode_parameters(out_buffer) {
873 return Err(DracoError::DracoError(
874 "Failed to encode quantization parameters".to_string(),
875 ));
876 }
877 }
878 }
879 1 | 0 => {
880 }
882 _ => {}
883 }
884 }
885
886 Ok(())
887 }
888
889 fn encode_edgebreaker_attributes_split(&mut self, out_buffer: &mut EncoderBuffer) -> Status {
890 let mesh = self
891 .mesh
892 .as_ref()
893 .expect("mesh must be set before encoding");
894 let mut groups: Vec<(i8, Vec<i32>)> = Vec::new();
895 let mut position_attrs = Vec::new();
896 for i in 0..mesh.num_attributes() {
897 if mesh.attribute(i).attribute_type() == GeometryAttributeType::Position {
898 position_attrs.push(i);
899 }
900 }
901 if !position_attrs.is_empty() {
902 groups.push((-1, position_attrs));
903 }
904 for (data_id, attr_conn) in self.edgebreaker_attribute_connectivity.iter().enumerate() {
905 groups.push((data_id as i8, vec![attr_conn.attribute_id]));
906 }
907
908 out_buffer.encode_u8(groups.len() as u8);
909
910 let major = out_buffer.version_major();
911 let minor = out_buffer.version_minor();
912 let writes_traversal_method = crate::version::bitstream_version(major, minor) >= 0x0102;
913 let traversal_method: u8 = if self.options.get_speed() == 0 { 1 } else { 0 };
914 for (att_data_id, _) in &groups {
915 out_buffer.encode_u8(*att_data_id as u8);
916 let element_type = if *att_data_id >= 0
917 && !self.edgebreaker_attribute_connectivity[*att_data_id as usize].no_interior_seams
918 {
919 1 } else {
921 0 };
923 out_buffer.encode_u8(element_type);
924 if writes_traversal_method {
925 out_buffer.encode_u8(traversal_method);
926 }
927 }
928
929 let mut decoder_types_by_group: Vec<Vec<u8>> = Vec::with_capacity(groups.len());
930
931 for (_, attr_ids) in &groups {
932 if !uses_varint_encoding(major, minor) {
933 out_buffer.encode_u32(attr_ids.len() as u32);
934 } else {
935 out_buffer.encode_varint(attr_ids.len() as u64);
936 }
937
938 for &att_id in attr_ids {
939 let att = mesh.attribute(att_id);
940 out_buffer.encode_u8(att.attribute_type() as u8);
941 out_buffer.encode_u8(att.data_type() as u8);
942 out_buffer.encode_u8(att.num_components());
943 out_buffer.encode_u8(if att.normalized() { 1 } else { 0 });
944 if !uses_varint_unique_id(major, minor) {
945 out_buffer.encode_u16(att.unique_id() as u16);
946 } else {
947 out_buffer.encode_varint(att.unique_id() as u64);
948 }
949 }
950
951 let mut decoder_types = Vec::with_capacity(attr_ids.len());
952 for &att_id in attr_ids {
953 let decoder_type = self.decoder_type_for_attribute(att_id);
954 out_buffer.encode_u8(decoder_type);
955 decoder_types.push(decoder_type);
956 }
957 decoder_types_by_group.push(decoder_types);
958 }
959
960 for (group_i, (att_data_id, attr_ids)) in groups.iter().enumerate() {
961 let point_ids = if *att_data_id >= 0 {
962 self.prepare_active_attribute_connectivity(*att_data_id as usize)?
963 } else {
964 self.active_corner_table = None;
965 self.active_data_to_corner_map = None;
966 self.active_vertex_to_data_map = None;
967 self.point_ids.clone()
968 };
969
970 self.encode_attribute_group_values(
971 attr_ids,
972 &decoder_types_by_group[group_i],
973 &point_ids,
974 out_buffer,
975 )?;
976 }
977
978 self.active_corner_table = None;
979 self.active_data_to_corner_map = None;
980 self.active_vertex_to_data_map = None;
981 Ok(())
982 }
983
984 fn decoder_type_for_attribute(&self, att_id: i32) -> u8 {
985 let mesh = self
986 .mesh
987 .as_ref()
988 .expect("mesh must be set before encoding");
989 let att = mesh.attribute(att_id);
990 let quantization_bits = self
991 .options
992 .get_attribute_int(att_id, "quantization_bits", -1);
993 let is_quantized = quantization_bits > 0
994 && (att.data_type() == DataType::Float32 || att.data_type() == DataType::Float64);
995 let is_normal = att.attribute_type() == GeometryAttributeType::Normal;
996
997 if is_quantized {
998 if is_normal {
999 3
1000 } else {
1001 2
1002 }
1003 } else if att.data_type() != DataType::Float32 {
1004 1
1005 } else {
1006 0
1007 }
1008 }
1009
1010 fn prepare_active_attribute_connectivity(
1011 &mut self,
1012 data_id: usize,
1013 ) -> Result<Vec<PointIndex>, DracoError> {
1014 let mesh = self
1015 .mesh
1016 .as_ref()
1017 .expect("mesh must be set before encoding");
1018 let base_ct = self
1019 .corner_table
1020 .as_ref()
1021 .ok_or_else(|| DracoError::DracoError("corner_table must be set".to_string()))?;
1022 let attr_conn = self
1023 .edgebreaker_attribute_connectivity
1024 .get(data_id)
1025 .ok_or_else(|| {
1026 DracoError::DracoError("Invalid attribute connectivity id".to_string())
1027 })?;
1028
1029 if attr_conn.no_interior_seams {
1030 self.active_corner_table = None;
1031 self.active_data_to_corner_map = None;
1032 self.active_vertex_to_data_map = None;
1033 return Ok(self.point_ids.clone());
1034 }
1035
1036 let mut attr_ct = base_ct.clone();
1037 for c_idx in 0..attr_conn.seam_edges.len() {
1038 if !attr_conn.seam_edges[c_idx] {
1039 continue;
1040 }
1041 let c = crate::geometry_indices::CornerIndex(c_idx as u32);
1042 let opp = attr_ct.opposite(c);
1043 if opp != crate::geometry_indices::INVALID_CORNER_INDEX {
1044 attr_ct.set_opposite(c, crate::geometry_indices::INVALID_CORNER_INDEX);
1045 attr_ct.set_opposite(opp, crate::geometry_indices::INVALID_CORNER_INDEX);
1046 }
1047 }
1048 let base_num_vertices = attr_ct.num_vertices();
1049 if !attr_ct.compute_vertex_corners(base_num_vertices) {
1050 return Err(DracoError::DracoError(
1051 "Failed to compute attribute seam corner table".to_string(),
1052 ));
1053 }
1054
1055 let mut point_ids = Vec::with_capacity(attr_ct.vertex_corners.len());
1056 let mut data_to_corner_map = Vec::with_capacity(attr_ct.vertex_corners.len());
1057 let mut vertex_to_data_map = vec![-1i32; attr_ct.num_vertices()];
1058 for (data_id, &corner) in attr_ct.vertex_corners.iter().enumerate() {
1059 if corner == crate::geometry_indices::INVALID_CORNER_INDEX {
1060 point_ids.push(PointIndex(0));
1061 data_to_corner_map.push(crate::geometry_indices::INVALID_CORNER_INDEX.0);
1062 continue;
1063 }
1064 let face = mesh.face(FaceIndex(corner.0 / 3));
1065 let point_id = face[(corner.0 % 3) as usize];
1066 point_ids.push(point_id);
1067 data_to_corner_map.push(corner.0);
1068 let vertex = attr_ct.vertex(corner);
1069 if vertex != crate::geometry_indices::INVALID_VERTEX_INDEX
1070 && (vertex.0 as usize) < vertex_to_data_map.len()
1071 {
1072 vertex_to_data_map[vertex.0 as usize] = data_id as i32;
1073 }
1074 }
1075
1076 self.active_corner_table = Some(attr_ct);
1077 self.active_data_to_corner_map = Some(data_to_corner_map);
1078 self.active_vertex_to_data_map = Some(vertex_to_data_map);
1079 Ok(point_ids)
1080 }
1081
1082 fn encode_attribute_group_values(
1083 &mut self,
1084 attr_ids: &[i32],
1085 decoder_types: &[u8],
1086 point_ids: &[PointIndex],
1087 out_buffer: &mut EncoderBuffer,
1088 ) -> Status {
1089 let mesh = self
1090 .mesh
1091 .as_ref()
1092 .expect("mesh must be set before encoding");
1093 let mut quantization_transforms: Vec<Option<AttributeQuantizationTransform>> = Vec::new();
1094 let mut normal_encoders: Vec<Option<SequentialNormalAttributeEncoder>> = Vec::new();
1095
1096 for (local_i, &att_id) in attr_ids.iter().enumerate() {
1097 let att = mesh.attribute(att_id);
1098 let decoder_type = decoder_types[local_i];
1099 let quantization_bits = self
1100 .options
1101 .get_attribute_int(att_id, "quantization_bits", -1);
1102
1103 match decoder_type {
1104 3 => {
1105 let mut encoder = SequentialNormalAttributeEncoder::new();
1106 if !encoder.init(
1107 self.point_cloud().expect("point_cloud set"),
1108 att_id,
1109 &self.options,
1110 ) {
1111 return Err(DracoError::DracoError(
1112 "Failed to init normal encoder".to_string(),
1113 ));
1114 }
1115 if !encoder.encode_values(
1116 self.point_cloud().expect("point_cloud set"),
1117 point_ids,
1118 out_buffer,
1119 &self.options,
1120 self,
1121 ) {
1122 return Err(DracoError::DracoError(
1123 "Failed to encode normal values".to_string(),
1124 ));
1125 }
1126 normal_encoders.push(Some(encoder));
1127 quantization_transforms.push(None);
1128 }
1129 2 => {
1130 let mut q_transform = AttributeQuantizationTransform::new();
1131 if !q_transform.compute_parameters(att, quantization_bits) {
1132 return Err(DracoError::DracoError(
1133 "Failed to compute quantization parameters".to_string(),
1134 ));
1135 }
1136 let mut portable = PointAttribute::default();
1137 if !q_transform.transform_attribute(att, point_ids, &mut portable) {
1138 return Err(DracoError::DracoError(
1139 "Failed to quantize attribute".to_string(),
1140 ));
1141 }
1142
1143 let mut att_encoder = SequentialIntegerAttributeEncoder::new();
1144 att_encoder.init(att_id);
1145 if !att_encoder.encode_values(
1146 mesh as &PointCloud,
1147 point_ids,
1148 out_buffer,
1149 &self.options,
1150 self,
1151 Some(&portable),
1152 true,
1153 ) {
1154 return Err(DracoError::DracoError(format!(
1155 "Failed to encode attribute {}",
1156 att_id
1157 )));
1158 }
1159 quantization_transforms.push(Some(q_transform));
1160 normal_encoders.push(None);
1161 }
1162 1 => {
1163 let mut att_encoder = SequentialIntegerAttributeEncoder::new();
1164 att_encoder.init(att_id);
1165 if !att_encoder.encode_values(
1166 mesh as &PointCloud,
1167 point_ids,
1168 out_buffer,
1169 &self.options,
1170 self,
1171 None,
1172 true,
1173 ) {
1174 return Err(DracoError::DracoError(format!(
1175 "Failed to encode attribute {}",
1176 att_id
1177 )));
1178 }
1179 quantization_transforms.push(None);
1180 normal_encoders.push(None);
1181 }
1182 0 => {
1183 let mut att_encoder = SequentialAttributeEncoder::new();
1184 att_encoder.init(att_id);
1185 if !att_encoder.encode_values(mesh as &PointCloud, point_ids, out_buffer) {
1186 return Err(DracoError::DracoError(format!(
1187 "Failed to encode attribute {}",
1188 att_id
1189 )));
1190 }
1191 quantization_transforms.push(None);
1192 normal_encoders.push(None);
1193 }
1194 _ => {
1195 return Err(DracoError::DracoError(format!(
1196 "Unsupported encoder type {}",
1197 decoder_type
1198 )));
1199 }
1200 }
1201 }
1202
1203 for (local_i, &decoder_type) in decoder_types.iter().enumerate() {
1204 match decoder_type {
1205 3 => {
1206 let major = out_buffer.version_major();
1207 let minor = out_buffer.version_minor();
1208 let bitstream_version = crate::version::bitstream_version(major, minor);
1209 if bitstream_version != 0 && bitstream_version < 0x0200 {
1210 continue;
1211 }
1212 if let Some(ref encoder) = normal_encoders[local_i] {
1213 if !encoder.encode_data_needed_by_portable_transform(out_buffer) {
1214 return Err(DracoError::DracoError(
1215 "Failed to encode normal transform data".to_string(),
1216 ));
1217 }
1218 }
1219 }
1220 2 => {
1221 if let Some(ref q_transform) = quantization_transforms[local_i] {
1222 if !q_transform.encode_parameters(out_buffer) {
1223 return Err(DracoError::DracoError(
1224 "Failed to encode quantization parameters".to_string(),
1225 ));
1226 }
1227 }
1228 }
1229 1 | 0 => {}
1230 _ => {}
1231 }
1232 }
1233
1234 Ok(())
1235 }
1236
1237 fn compute_number_of_encoded_faces(&mut self) {
1238 if let Some(ref mesh) = self.mesh {
1239 self.num_encoded_faces = mesh.num_faces();
1240 }
1241 }
1242
1243 fn build_encoded_mesh_info(&mut self) -> Status {
1244 let num_attributes = self
1245 .mesh
1246 .as_ref()
1247 .expect("mesh must be set before encoding")
1248 .num_attributes();
1249 let mut attributes = Vec::with_capacity(num_attributes as usize);
1250 let mut encoded_num_points = self.point_ids.len();
1251
1252 for att_id in 0..num_attributes {
1253 let point_ids = self.encoded_point_ids_for_attribute(att_id)?;
1254 let num_encoded_values = point_ids.len();
1255 encoded_num_points = encoded_num_points.max(num_encoded_values);
1256
1257 let (position_min, position_max) =
1258 self.position_bounds_for_attribute(att_id, &point_ids)?;
1259 let att = self
1260 .mesh
1261 .as_ref()
1262 .expect("mesh must be set before encoding")
1263 .attribute(att_id);
1264 attributes.push(EncodedAttributeInfo {
1265 source_attribute_id: att_id,
1266 attribute_type: att.attribute_type(),
1267 data_type: att.data_type(),
1268 num_components: att.num_components(),
1269 normalized: att.normalized(),
1270 unique_id: att.unique_id(),
1271 num_encoded_values,
1272 position_min,
1273 position_max,
1274 });
1275 }
1276
1277 let (source_num_points, num_faces) = self
1278 .mesh
1279 .as_ref()
1280 .map(|mesh| (mesh.num_points(), mesh.num_faces()))
1281 .expect("mesh must be set before encoding");
1282 if self.method == 0 {
1283 encoded_num_points = source_num_points;
1284 } else {
1285 encoded_num_points = self.encoded_num_points_for_mesh(encoded_num_points)?;
1286 }
1287
1288 self.active_corner_table = None;
1289 self.active_data_to_corner_map = None;
1290 self.active_vertex_to_data_map = None;
1291 self.encoded_mesh_info = Some(EncodedMeshInfo {
1292 encoding_method: self.method,
1293 num_encoded_faces: num_faces,
1294 num_encoded_points: encoded_num_points,
1295 attributes,
1296 });
1297 Ok(())
1298 }
1299
1300 fn encoded_point_ids_for_attribute(
1301 &mut self,
1302 att_id: i32,
1303 ) -> Result<Vec<PointIndex>, DracoError> {
1304 if self.method == 0 || self.use_single_connectivity {
1305 return Ok(self.point_ids.clone());
1306 }
1307
1308 if let Some(data_id) = self
1309 .edgebreaker_attribute_connectivity
1310 .iter()
1311 .position(|connectivity| connectivity.attribute_id == att_id)
1312 {
1313 return self.prepare_active_attribute_connectivity(data_id);
1314 }
1315
1316 Ok(self.point_ids.clone())
1317 }
1318
1319 fn encoded_num_points_for_mesh(&mut self, base_num_points: usize) -> Result<usize, DracoError> {
1320 if self.method == 0 || self.use_single_connectivity {
1321 return Ok(base_num_points);
1322 }
1323
1324 let mut num_points = base_num_points;
1325 for data_id in 0..self.edgebreaker_attribute_connectivity.len() {
1326 if self.edgebreaker_attribute_connectivity[data_id].no_interior_seams {
1327 continue;
1328 }
1329 let point_ids = self.prepare_active_attribute_connectivity(data_id)?;
1330 num_points = num_points.max(point_ids.len());
1331 }
1332 self.active_corner_table = None;
1333 self.active_data_to_corner_map = None;
1334 self.active_vertex_to_data_map = None;
1335 Ok(num_points)
1336 }
1337
1338 fn position_bounds_for_attribute(
1339 &self,
1340 att_id: i32,
1341 point_ids: &[PointIndex],
1342 ) -> Result<PositionBounds, DracoError> {
1343 let mesh = self
1344 .mesh
1345 .as_ref()
1346 .expect("mesh must be set before encoding");
1347 let att = mesh.attribute(att_id);
1348 if att.attribute_type() != GeometryAttributeType::Position {
1349 return Ok((None, None));
1350 }
1351 if att.num_components() != 3 || att.data_type() != DataType::Float32 {
1352 return Ok((None, None));
1353 }
1354
1355 if self.decoder_type_for_attribute(att_id) == 2 {
1356 let quantization_bits = self
1357 .options
1358 .get_attribute_int(att_id, "quantization_bits", -1);
1359 let mut q_transform = AttributeQuantizationTransform::new();
1360 if !q_transform.compute_parameters(att, quantization_bits) {
1361 return Err(DracoError::DracoError(
1362 "Failed to compute position quantization parameters".to_string(),
1363 ));
1364 }
1365
1366 let mut portable = PointAttribute::default();
1367 if !q_transform.transform_attribute(att, point_ids, &mut portable) {
1368 return Err(DracoError::DracoError(
1369 "Failed to quantize position attribute for encoded mesh info".to_string(),
1370 ));
1371 }
1372
1373 let mut dequantized = PointAttribute::new();
1374 dequantized.try_init(
1375 GeometryAttributeType::Position,
1376 3,
1377 DataType::Float32,
1378 false,
1379 portable.size(),
1380 )?;
1381 if !q_transform.inverse_transform_attribute(&portable, &mut dequantized) {
1382 return Err(DracoError::DracoError(
1383 "Failed to dequantize position attribute for encoded mesh info".to_string(),
1384 ));
1385 }
1386
1387 return Self::position_bounds_from_attribute(&dequantized, &[]);
1388 }
1389
1390 Self::position_bounds_from_attribute(att, point_ids)
1391 }
1392
1393 fn position_bounds_from_attribute(
1394 att: &PointAttribute,
1395 point_ids: &[PointIndex],
1396 ) -> Result<PositionBounds, DracoError> {
1397 let count = if point_ids.is_empty() {
1398 att.size()
1399 } else {
1400 point_ids.len()
1401 };
1402 if count == 0 {
1403 return Ok((None, None));
1404 }
1405
1406 let stride = usize::try_from(att.byte_stride()).map_err(|_| {
1407 DracoError::DracoError("Position attribute has invalid byte stride".to_string())
1408 })?;
1409 let bytes = att.buffer().data();
1410 let mut min = [f32::INFINITY; 3];
1411 let mut max = [f32::NEG_INFINITY; 3];
1412
1413 for i in 0..count {
1414 let point = if point_ids.is_empty() {
1415 PointIndex(i as u32)
1416 } else {
1417 point_ids[i]
1418 };
1419 let value_index = att.mapped_index(point);
1420 if value_index == INVALID_ATTRIBUTE_VALUE_INDEX {
1421 return Err(DracoError::DracoError(
1422 "Position attribute point map contains an invalid entry".to_string(),
1423 ));
1424 }
1425
1426 let value_offset = (value_index.0 as usize)
1427 .checked_mul(stride)
1428 .ok_or_else(|| {
1429 DracoError::DracoError("Position attribute offset overflow".to_string())
1430 })?;
1431 for component in 0..3 {
1432 let offset = value_offset
1433 .checked_add(component * DataType::Float32.byte_length())
1434 .ok_or_else(|| {
1435 DracoError::DracoError("Position attribute offset overflow".to_string())
1436 })?;
1437 let end = offset
1438 .checked_add(DataType::Float32.byte_length())
1439 .ok_or_else(|| {
1440 DracoError::DracoError("Position attribute offset overflow".to_string())
1441 })?;
1442 let Some(component_bytes) = bytes.get(offset..end) else {
1443 return Err(DracoError::DracoError(
1444 "Position attribute buffer is shorter than metadata".to_string(),
1445 ));
1446 };
1447 let value = f32::from_le_bytes([
1448 component_bytes[0],
1449 component_bytes[1],
1450 component_bytes[2],
1451 component_bytes[3],
1452 ]);
1453 min[component] = min[component].min(value);
1454 max[component] = max[component].max(value);
1455 }
1456 }
1457
1458 Ok((
1459 Some(min.into_iter().map(f64::from).collect()),
1460 Some(max.into_iter().map(f64::from).collect()),
1461 ))
1462 }
1463}
1464
1465impl Default for MeshEncoder {
1466 fn default() -> Self {
1467 Self::new()
1468 }
1469}