Skip to main content

draco_oxide_core/attribute/
mod.rs

1use crate::safety_assert;
2use serde::Serialize;
3
4use kiddo::immutable::float::kdtree::ImmutableKdTree;
5use kiddo::SquaredEuclidean;
6
7use super::buffer;
8use crate::bit_coder::{ByteReader, ByteWriter};
9use crate::types::DataValue;
10use crate::types::{AttributeValueIdx, PointIdx, VecPointIdx, Vector};
11
12fn vector_to_f64_array<Data: Vector<N>, const N: usize>(v: &Data) -> [f64; N] {
13    let mut out = [0.0f64; N];
14    for (i, slot) in out.iter_mut().enumerate() {
15        *slot = (*v.get(i)).to_f64();
16    }
17    out
18}
19
20#[derive(Debug, thiserror::Error)]
21pub enum Err {
22    /// Invalid attribute domain id
23    #[error("Invalid attribute domain id: {0}")]
24    InvalidAttributeDomainId(u8),
25    /// Reader error
26    #[error("Reader error: {0}")]
27    ReaderError(#[from] crate::bit_coder::ReaderErr),
28    #[error("Invalid DataTypeId: {0}")]
29    InvalidDataTypeId(u8),
30}
31
32/// Represents an attribute in a mesh. An attribute can be an array of values representing potisions
33/// of vertices, or it can be an array of values representing normals of vertices or corners, or faces.
34/// Note that the struct does not have the static type information, so the attribute value can be a
35/// vector of any type of any dimension, as long as it implements the `Vector` trait. The information about
36/// the type of the attribute, component type, and the number of components is stored in dynamically.
37#[derive(Debug, Clone)]
38pub struct Attribute {
39    /// attribute id
40    id: AttributeId,
41
42    /// attribute buffer
43    buffer: buffer::attribute::AttributeBuffer,
44
45    /// attribute type
46    att_type: AttributeType,
47
48    /// attribute domain
49    domain: AttributeDomain,
50
51    /// the reference of the parent, if any
52    parents: Vec<AttributeId>,
53
54    /// The optional mapping from point index to attribute value index.
55    /// If `None`, then the attribute is defined on the point level, i.e.
56    /// the i'th element in the attribute corresponds to the i'th point in the mesh.
57    point_to_att_val_map: Option<VecPointIdx<AttributeValueIdx>>,
58
59    /// name of the attribute, if any
60    name: Option<String>,
61}
62
63impl Attribute {
64    pub fn new<Data, const N: usize>(
65        data: Vec<Data>,
66        att_type: AttributeType,
67        domain: AttributeDomain,
68        parents: Vec<AttributeId>,
69    ) -> Self
70    where
71        Data: Vector<N>,
72    {
73        let id = AttributeId::new(0); // TODO: generate unique id
74        let buffer = buffer::attribute::AttributeBuffer::from_vec(data);
75        let mut out = Self {
76            id,
77            buffer,
78            parents,
79            att_type,
80            domain,
81            point_to_att_val_map: None,
82            name: None,
83        };
84        out.remove_duplicate_values::<Data, N>();
85        out
86    }
87
88    pub fn new_empty(
89        id: AttributeId,
90        att_type: AttributeType,
91        domain: AttributeDomain,
92        component_type: ComponentDataType,
93        num_components: usize,
94    ) -> Self {
95        let buffer = buffer::attribute::AttributeBuffer::new(component_type, num_components);
96        Self {
97            id,
98            buffer,
99            parents: Vec::new(),
100            att_type,
101            domain,
102            point_to_att_val_map: None,
103            name: None,
104        }
105    }
106
107    pub fn from<Data, const N: usize>(
108        id: AttributeId,
109        data: Vec<Data>,
110        att_type: AttributeType,
111        domain: AttributeDomain,
112        parents: Vec<AttributeId>,
113    ) -> Self
114    where
115        Data: Vector<N>,
116    {
117        let buffer = buffer::attribute::AttributeBuffer::from_vec(data);
118        let mut out = Self {
119            id,
120            buffer,
121            parents,
122            att_type,
123            domain,
124            point_to_att_val_map: None,
125            name: None,
126        };
127        out.remove_duplicate_values::<Data, N>();
128        out
129    }
130
131    pub fn from_without_removing_duplicates<Data, const N: usize>(
132        id: AttributeId,
133        data: Vec<Data>,
134        att_type: AttributeType,
135        domain: AttributeDomain,
136        parents: Vec<AttributeId>,
137    ) -> Self
138    where
139        Data: Vector<N>,
140    {
141        let buffer = buffer::attribute::AttributeBuffer::from_vec(data);
142        Self {
143            id,
144            buffer,
145            parents,
146            att_type,
147            domain,
148            point_to_att_val_map: None,
149            name: None,
150        }
151    }
152
153    pub fn get<Data, const N: usize>(&self, p_idx: PointIdx) -> Data
154    where
155        Data: Vector<N>,
156        Data::Component: DataValue,
157    {
158        self.buffer.get(self.get_unique_val_idx(p_idx))
159    }
160
161    pub fn get_unique_val<Data, const N: usize>(&self, val_idx: AttributeValueIdx) -> Data
162    where
163        Data: Vector<N>,
164        Data::Component: DataValue,
165    {
166        self.buffer.get(val_idx)
167    }
168
169    pub fn get_component_type(&self) -> ComponentDataType {
170        self.buffer.get_component_type()
171    }
172
173    #[inline]
174    #[allow(unused)]
175    pub fn set_component_type(&mut self, component_type: ComponentDataType) {
176        self.buffer.set_component_type(component_type);
177    }
178
179    #[inline]
180    #[allow(unused)]
181    pub fn set_num_components(&mut self, num_components: usize) {
182        self.buffer.set_num_components(num_components);
183    }
184
185    pub fn get_data_as_bytes(&self) -> &[u8] {
186        self.buffer.as_slice_u8()
187    }
188
189    #[inline]
190    #[allow(unused)]
191    pub fn get_as_bytes(&self, i: usize) -> &[u8] {
192        &self.buffer.as_slice_u8()[i
193            * self.buffer.get_num_components()
194            * self.buffer.get_component_type().size()
195            ..(i + 1) * self.buffer.get_num_components() * self.buffer.get_component_type().size()]
196    }
197
198    pub fn set_point_to_att_val_map(
199        &mut self,
200        point_to_att_val_map: Option<VecPointIdx<AttributeValueIdx>>,
201    ) {
202        self.point_to_att_val_map = point_to_att_val_map;
203    }
204
205    pub fn take_point_to_att_val_map(self) -> Option<VecPointIdx<AttributeValueIdx>> {
206        self.point_to_att_val_map
207    }
208
209    #[inline]
210    pub fn get_id(&self) -> AttributeId {
211        self.id
212    }
213
214    #[inline]
215    pub fn get_num_components(&self) -> usize {
216        self.buffer.get_num_components()
217    }
218
219    #[inline]
220    pub fn get_attribute_type(&self) -> AttributeType {
221        self.att_type
222    }
223
224    #[inline]
225    pub fn get_domain(&self) -> AttributeDomain {
226        self.domain
227    }
228
229    #[inline]
230    pub fn get_parents(&self) -> &Vec<AttributeId> {
231        self.parents.as_ref()
232    }
233
234    /// The number of values of the attribute.
235    #[inline(always)]
236    pub fn len(&self) -> usize {
237        if let Some(f) = &self.point_to_att_val_map {
238            f.len()
239        } else {
240            self.buffer.len()
241        }
242    }
243
244    /// Returns true if the attribute has no values.
245    #[inline(always)]
246    pub fn is_empty(&self) -> bool {
247        self.len() == 0
248    }
249
250    #[inline(always)]
251    pub fn num_unique_values(&self) -> usize {
252        self.buffer.len()
253    }
254
255    /// Appends a new point whose attribute value aliases that of `src`, and
256    /// returns its index. No new unique value is stored; the new point reuses
257    /// the source's `AttributeValueIdx`. If the attribute is still on the
258    /// implicit identity `point -> value` map, that map is materialized first
259    /// so the appended entry can diverge from identity.
260    ///
261    /// This is how the encoder splits a non-manifold point, calling `mint`
262    /// on every attribute in lockstep so the point spaces stay equal.
263    pub fn mint(&mut self, src: PointIdx) -> PointIdx {
264        let src_val = self.get_unique_val_idx(src);
265        let num_unique = self.num_unique_values();
266        let map = self.point_to_att_val_map.get_or_insert_with(|| {
267            (0..num_unique)
268                .map(AttributeValueIdx::from)
269                .collect::<Vec<_>>()
270                .into()
271        });
272        let new_idx = PointIdx::from(map.len());
273        map.push(src_val);
274        new_idx
275    }
276
277    #[inline]
278    pub fn get_unique_val_idx(&self, idx: PointIdx) -> AttributeValueIdx {
279        let idx_usize = usize::from(idx);
280        assert!(
281            idx_usize < self.len(),
282            "Index out of bounds: idx = {}, len = {}",
283            idx_usize,
284            self.len()
285        );
286        if let Some(ref point_to_att_val_map) = self.point_to_att_val_map {
287            point_to_att_val_map[idx]
288        } else {
289            // otherwise, we use identity mapping
290            idx_usize.into()
291        }
292    }
293
294    #[inline]
295    pub fn set_name(&mut self, name: String) {
296        self.name = Some(name);
297    }
298
299    #[inline]
300    pub fn get_name(&self) -> Option<&String> {
301        self.name.as_ref()
302    }
303
304    /// returns the data values as a slice of values casted to the given type.
305    #[inline]
306    pub fn unique_vals_as_slice<Data>(&self) -> &[Data] {
307        assert_eq!(
308            self.buffer.get_num_components() * self.buffer.get_component_type().size(),
309            std::mem::size_of::<Data>(),
310        );
311        unsafe { self.buffer.as_slice::<Data>() }
312    }
313
314    /// returns the data values as a mutable slice of values casted to the given type.
315    #[inline]
316    pub fn unique_vals_as_slice_mut<Data>(&mut self) -> &mut [Data] {
317        assert_eq!(
318            self.buffer.get_num_components() * self.buffer.get_component_type().size(),
319            std::mem::size_of::<Data>(),
320        );
321        unsafe { self.buffer.as_slice_mut::<Data>() }
322    }
323
324    /// returns the data values as a slice of values casted to the given type.
325    /// # Safety
326    /// This function assumes that the buffer's data is properly aligned and matches the type `Data`.
327    #[inline]
328    pub unsafe fn unique_vals_as_slice_unchecked<Data>(&self) -> &[Data] {
329        // Safety: upheld
330        self.buffer.as_slice::<Data>()
331    }
332
333    /// returns the data values as a mutable slice of values casted to the given type.
334    /// # Safety
335    /// This function assumes that the buffer's data is properly aligned and matches the type `Data`.
336    #[inline]
337    pub unsafe fn unique_vals_as_slice_unchecked_mut<Data>(&mut self) -> &mut [Data] {
338        // Safety: upheld
339        self.buffer.as_slice_mut::<Data>()
340    }
341
342    /// permutes the data in the buffer according to the given indices, i.e.
343    /// `i`-th element in the buffer will be moved to `indices[i]`-th position.
344    pub fn permute(&mut self, indices: &[usize]) {
345        assert!(
346            indices.len() == self.len(),
347            "Indices length must match the buffer length: indices.len() = {}, self.len() = {}",
348            indices.len(),
349            self.len()
350        );
351        assert!(
352            indices.iter().all(|&i| i < self.len()),
353            "All indices must be within the buffer length: indices = {:?}, self.len() = {}",
354            indices,
355            self.len()
356        );
357        unsafe {
358            self.buffer.permute_unchecked(indices);
359        }
360    }
361
362    /// permutes the data in the buffer according to the given indices, i.e.
363    /// `i`-th element in the buffer will be moved to `indices[i]`-th position.
364    /// # Safety:
365    /// This function assumes that the indices are valid, i.e. they are within the bounds of the buffer.
366    pub fn permute_unchecked(&mut self, indices: &[usize]) {
367        safety_assert!(
368            indices.len() == self.len(),
369            "Indices length must match the buffer length: indices.len() = {}, self.len() = {}",
370            indices.len(),
371            self.len()
372        );
373        safety_assert!(
374            indices.iter().all(|&i| i < self.len()),
375            "All indices must be within the buffer length: indices = {:?}, self.len() = {}",
376            indices,
377            self.len()
378        );
379        unsafe {
380            self.buffer.permute_unchecked(indices);
381        }
382    }
383
384    /// swaps the elements at indices `i` and `j` in the buffer.
385    pub fn swap(&mut self, i: usize, j: usize) {
386        assert!(
387            i < self.len() && j < self.len(),
388            "Indices out of bounds: i = {}, j = {}, len = {}",
389            i,
390            j,
391            self.len()
392        );
393        unsafe {
394            self.buffer.swap_unchecked(i, j);
395        }
396    }
397
398    pub fn take_values<Data, const N: usize>(self) -> Vec<Data>
399    where
400        Data: Vector<N>,
401    {
402        assert_eq!(self.get_num_components(), N,);
403        assert_eq!(self.get_component_type(), Data::Component::get_dyn(),);
404
405        unsafe { self.buffer.into_vec_unchecked::<Data, N>() }
406    }
407
408    pub fn into_parts<Data, const N: usize>(
409        mut self,
410    ) -> (Vec<Data>, Option<VecPointIdx<AttributeValueIdx>>, Self)
411    where
412        Data: Vector<N>,
413    {
414        let num_components = self.get_num_components();
415        let component_type = self.get_component_type();
416        assert_eq!(num_components, N,);
417        assert_eq!(component_type, Data::Component::get_dyn(),);
418        let mut new_buffer = buffer::attribute::AttributeBuffer::from_vec(Vec::<Data>::new());
419        std::mem::swap(&mut self.buffer, &mut new_buffer);
420        let data = unsafe { new_buffer.into_vec_unchecked::<Data, N>() };
421
422        let mut point_to_att_val_map = None;
423        std::mem::swap(&mut point_to_att_val_map, &mut self.point_to_att_val_map);
424
425        (data, point_to_att_val_map, self)
426    }
427
428    pub fn set_values<Data, const N: usize>(&mut self, data: Vec<Data>)
429    where
430        Data: Vector<N>,
431    {
432        assert_eq!(self.get_num_components(), N,);
433        assert_eq!(self.get_component_type(), Data::Component::get_dyn(),);
434        assert_eq!(self.len(), 0);
435        self.buffer = buffer::attribute::AttributeBuffer::from_vec(data);
436    }
437
438    pub fn remove_duplicate_values<Data, const N: usize>(&mut self)
439    where
440        Data: Vector<N>,
441    {
442        let n = self.len();
443        if n <= 1 {
444            return;
445        }
446
447        let values = self.unique_vals_as_slice::<Data>();
448
449        // Convert all values to f64 arrays for the KD-tree
450        let f64_points: Vec<[f64; N]> = values.iter().map(|v| vector_to_f64_array(v)).collect();
451
452        // Build an immutable KD-tree over the f64 points
453        let tree = ImmutableKdTree::<f64, u32, N, 32>::new_from_slice(&f64_points);
454
455        // canonical_index[i] = the index of the first occurrence that i is a duplicate of,
456        // or i itself if it's not a duplicate.
457        let mut canonical_index = vec![usize::MAX; n];
458        let mut has_duplicates = false;
459
460        for i in 0..n {
461            if canonical_index[i] != usize::MAX {
462                // already marked as a duplicate of something
463                continue;
464            }
465            canonical_index[i] = i; // it's its own canonical
466
467            // Query the KD-tree for nearby points
468            let neighbors = tree.within_unsorted::<SquaredEuclidean>(&f64_points[i], f64::EPSILON);
469
470            for neighbor in &neighbors {
471                let j = neighbor.item as usize;
472                if j <= i || canonical_index[j] != usize::MAX {
473                    continue;
474                }
475                // Post-filter with exact typed equality
476                if values[i] == values[j] {
477                    canonical_index[j] = i;
478                    has_duplicates = true;
479                }
480            }
481        }
482
483        if !has_duplicates {
484            return;
485        }
486
487        // Build old_to_new mapping: assign compacted indices to non-duplicate entries
488        let mut old_to_new = vec![0usize; n];
489        let mut keep_indices = Vec::new();
490        let mut new_idx = 0;
491        for i in 0..n {
492            if canonical_index[i] == i {
493                // This is a canonical (non-duplicate) entry
494                old_to_new[i] = new_idx;
495                keep_indices.push(i);
496                new_idx += 1;
497            }
498        }
499
500        // Build the point-to-attribute-value map
501        let map_data: Vec<AttributeValueIdx> = (0..n)
502            .map(|i| old_to_new[canonical_index[i]].into())
503            .collect();
504        self.point_to_att_val_map = Some(VecPointIdx::<_>::from(map_data));
505
506        // Compact the buffer to keep only canonical entries
507        self.buffer.retain_indices(&keep_indices);
508    }
509
510    #[allow(unused)]
511    pub fn remove<Data, const N: usize>(&mut self, p_idx: PointIdx) {
512        let p_idx_usize = usize::from(p_idx);
513        assert!(
514            p_idx_usize < self.len(),
515            "Point index out of bounds: {}",
516            p_idx_usize
517        );
518        if let Some(ref mut point_to_att_val_map) = self.point_to_att_val_map {
519            // update the mapping
520            if (0..point_to_att_val_map.len())
521                .map(PointIdx::from)
522                .filter(|&p| p != p_idx)
523                .any(|p| point_to_att_val_map[p] == point_to_att_val_map[p_idx])
524            {
525                // if there are other vertices with the same value, we just remove the mapping
526                point_to_att_val_map.remove(p_idx);
527            } else {
528                let removed_unique_val_idx = point_to_att_val_map.remove(p_idx);
529                self.buffer.remove::<Data, N>(removed_unique_val_idx.into());
530                // update the mapping for the remaining vertices
531                for p in 0..point_to_att_val_map.len() {
532                    let p = PointIdx::from(p);
533                    if point_to_att_val_map[p] > removed_unique_val_idx {
534                        point_to_att_val_map[p] = (usize::from(point_to_att_val_map[p]) - 1).into();
535                    }
536                }
537            }
538        } else {
539            // no mapping, just remove the value
540            let a_idx = AttributeValueIdx::from(usize::from(p_idx));
541            self.remove_unique_val::<Data, N>(a_idx);
542        }
543    }
544
545    #[allow(unused)]
546    pub fn remove_dyn(&mut self, p_idx: PointIdx) {
547        assert!(
548            usize::from(p_idx) < self.len(),
549            "Point index out of bounds: {}",
550            usize::from(p_idx)
551        );
552        match self.get_component_type().size() * self.get_num_components() {
553            1 => self.remove::<u8, 1>(p_idx),
554            2 => self.remove::<u16, 1>(p_idx),
555            4 => self.remove::<u32, 1>(p_idx),
556            6 => self.remove::<u16, 3>(p_idx),
557            8 => self.remove::<u64, 1>(p_idx),
558            12 => self.remove::<u32, 3>(p_idx),
559            16 => self.remove::<u64, 2>(p_idx),
560            18 => self.remove::<u64, 3>(p_idx),
561            _ => panic!(
562                "Unsupported component size: {}",
563                self.get_component_type().size()
564            ),
565        }
566    }
567
568    #[allow(unused)]
569    pub fn remove_unique_val<Data, const N: usize>(&mut self, val_idx: AttributeValueIdx) {
570        let val_idx = usize::from(val_idx);
571        assert!(
572            val_idx < self.num_unique_values(),
573            "Attribute value index out of bounds: {}",
574            val_idx
575        );
576        self.buffer.remove::<Data, N>(val_idx);
577        if let Some(ref mut _point_to_att_val_map) = self.point_to_att_val_map {
578            unimplemented!();
579        }
580    }
581
582    pub fn remove_unique_val_dyn(&mut self, val_idx: usize) {
583        assert!(
584            val_idx < self.num_unique_values(),
585            "Attribute value index out of bounds: {}",
586            val_idx
587        );
588        match self.get_component_type().size() * self.get_num_components() {
589            1 => self.buffer.remove::<u8, 1>(val_idx),
590            2 => self.buffer.remove::<u16, 1>(val_idx),
591            4 => self.buffer.remove::<u32, 1>(val_idx),
592            6 => self.buffer.remove::<u16, 3>(val_idx),
593            8 => self.buffer.remove::<u64, 1>(val_idx),
594            12 => self.buffer.remove::<u32, 3>(val_idx),
595            16 => self.buffer.remove::<u64, 2>(val_idx),
596            18 => self.buffer.remove::<u64, 3>(val_idx),
597            _ => panic!(
598                "Unsupported component size: {}",
599                self.get_component_type().size()
600            ),
601        }
602    }
603
604    /// Retains only points at the given sorted indices. O(n) instead of O(n^2).
605    /// `keep_point_indices` must be sorted in ascending order.
606    pub fn retain_points_dyn(&mut self, keep_point_indices: &[usize]) {
607        if let Some(ref map) = self.point_to_att_val_map {
608            // Build new map for kept points and find which unique values survive
609            let num_unique = self.buffer.len();
610            let mut unique_val_referenced = vec![false; num_unique];
611            let mut new_map = Vec::with_capacity(keep_point_indices.len());
612
613            for &p in keep_point_indices {
614                let val_idx = map[PointIdx::from(p)];
615                unique_val_referenced[usize::from(val_idx)] = true;
616                new_map.push(val_idx);
617            }
618
619            // Build compacted index mapping for unique values
620            let mut old_unique_to_new = vec![0usize; num_unique];
621            let mut keep_unique_indices = Vec::new();
622            let mut new_unique_idx = 0;
623            for i in 0..num_unique {
624                if unique_val_referenced[i] {
625                    old_unique_to_new[i] = new_unique_idx;
626                    keep_unique_indices.push(i);
627                    new_unique_idx += 1;
628                }
629            }
630
631            // Update map indices to point to compacted positions
632            let new_map: Vec<AttributeValueIdx> = new_map
633                .iter()
634                .map(|&val_idx| old_unique_to_new[usize::from(val_idx)].into())
635                .collect();
636            self.point_to_att_val_map = Some(VecPointIdx::from(new_map));
637
638            // Compact the buffer
639            self.buffer.retain_indices(&keep_unique_indices);
640        } else {
641            // No map; buffer indices correspond directly to point indices
642            self.buffer.retain_indices(keep_point_indices);
643        }
644    }
645}
646
647#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize)]
648pub enum ComponentDataType {
649    I8,
650    U8,
651    I16,
652    U16,
653    I32,
654    U32,
655    I64,
656    U64,
657    F32,
658    F64,
659    Invalid,
660}
661
662impl ComponentDataType {
663    /// returns the size of the data type in bytes e.g. 4 for F32
664    #[inline]
665    pub fn size(self) -> usize {
666        match self {
667            ComponentDataType::F32 => 4,
668            ComponentDataType::F64 => 8,
669            ComponentDataType::U8 => 1,
670            ComponentDataType::U16 => 2,
671            ComponentDataType::U32 => 4,
672            ComponentDataType::U64 => 8,
673            ComponentDataType::I8 => 1,
674            ComponentDataType::I16 => 2,
675            ComponentDataType::I32 => 4,
676            ComponentDataType::I64 => 8,
677            ComponentDataType::Invalid => 0,
678        }
679    }
680
681    #[inline]
682    pub fn is_float(self) -> bool {
683        matches!(self, ComponentDataType::F32 | ComponentDataType::F64)
684    }
685
686    /// returns unique id for the data type.
687    #[inline]
688    pub fn get_id(self) -> u8 {
689        match self {
690            ComponentDataType::U8 => 1,
691            ComponentDataType::I8 => 2,
692            ComponentDataType::U16 => 3,
693            ComponentDataType::I16 => 4,
694            ComponentDataType::U32 => 5,
695            ComponentDataType::I32 => 6,
696            ComponentDataType::U64 => 7,
697            ComponentDataType::I64 => 8,
698            ComponentDataType::F32 => 9,
699            ComponentDataType::F64 => 10,
700            ComponentDataType::Invalid => u8::MAX, // Invalid type
701        }
702    }
703
704    /// returns the data type as a string.
705    #[inline]
706    pub fn write_to<W: ByteWriter>(self, writer: &mut W) {
707        writer.write_u8(self.get_id());
708    }
709
710    /// returns the data type from the given id, or `None` if the id is unknown.
711    #[inline]
712    pub fn from_id(id: usize) -> Option<Self> {
713        match id {
714            1 => Some(ComponentDataType::I8),
715            2 => Some(ComponentDataType::U8),
716            3 => Some(ComponentDataType::I16),
717            4 => Some(ComponentDataType::U16),
718            5 => Some(ComponentDataType::I32),
719            6 => Some(ComponentDataType::U32),
720            7 => Some(ComponentDataType::I64),
721            8 => Some(ComponentDataType::U64),
722            9 => Some(ComponentDataType::F32),
723            10 => Some(ComponentDataType::F64),
724            _ => None,
725        }
726    }
727
728    /// Reads the data type from the reader.
729    #[inline]
730    pub fn read_from<R: ByteReader>(reader: &mut R) -> Result<Self, Err> {
731        let id = reader.read_u8()?;
732        Self::from_id(id as usize).ok_or(Err::InvalidDataTypeId(id))
733    }
734}
735
736#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize)]
737pub enum AttributeType {
738    Position,
739    Normal,
740    Color,
741    TextureCoordinate,
742    Custom,
743    Tangent,
744    Material,
745    Joint,
746    Weight,
747    Invalid,
748}
749
750impl AttributeType {
751    pub fn get_minimum_dependency(&self) -> Vec<Self> {
752        match self {
753            Self::Position => Vec::new(),
754            Self::Normal => Vec::new(),
755            Self::Color => Vec::new(),
756            Self::TextureCoordinate => vec![Self::Position],
757            Self::Tangent => Vec::new(),
758            Self::Material => Vec::new(),
759            Self::Joint => Vec::new(),
760            Self::Weight => Vec::new(),
761            Self::Custom => Vec::new(),
762            Self::Invalid => Vec::new(),
763        }
764    }
765
766    /// Returns the id of the attribute type.
767    #[inline]
768    pub fn get_id(&self) -> u8 {
769        match self {
770            Self::Position => 0,
771            Self::Normal => 1,
772            Self::Color => 2,
773            Self::TextureCoordinate => 3,
774            Self::Custom => 4,
775            Self::Tangent => 5,
776            Self::Material => 6,
777            Self::Joint => 7,
778            Self::Weight => 8,
779            Self::Invalid => u8::MAX, // Invalid type
780        }
781    }
782
783    /// Returns the id of the attribute type.
784    #[inline]
785    pub fn write_to<W: ByteWriter>(&self, writer: &mut W) {
786        writer.write_u8(self.get_id());
787    }
788
789    /// Reads the attribute type from the reader.
790    #[inline]
791    pub fn from_id(id: u8) -> Result<Self, Err> {
792        match id {
793            0 => Ok(Self::Position),
794            1 => Ok(Self::Normal),
795            2 => Ok(Self::Color),
796            3 => Ok(Self::TextureCoordinate),
797            4 => Ok(Self::Custom),
798            5 => Ok(Self::Tangent),
799            6 => Ok(Self::Material),
800            7 => Ok(Self::Joint),
801            8 => Ok(Self::Weight),
802            _ => Err(Err::InvalidDataTypeId(id)),
803        }
804    }
805
806    /// Reads the attribute type from the reader.
807    #[inline]
808    pub fn read_from<R: ByteReader>(reader: &mut R) -> Result<Self, Err> {
809        let id = reader.read_u8()?;
810        Self::from_id(id)
811    }
812}
813
814/// The domain of the attribute, i.e. whether it is defined on the position or corner.
815#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)]
816pub enum AttributeDomain {
817    /// The attribute is defined on the position attribute, i.e. i'th element in the attribute is attached to the i'th position in the mesh.
818    Position,
819    /// The attribute is defined on the corner attribute, i.e. i'th element in the attribute is attached to the i'th corner in the mesh.
820    Corner,
821}
822
823impl AttributeDomain {
824    /// Writes the id of the attribute domain to the writer.
825    pub fn write_to<W: ByteWriter>(&self, writer: &mut W) {
826        match self {
827            Self::Position => writer.write_u8(0),
828            Self::Corner => writer.write_u8(1),
829        }
830    }
831
832    /// Reads the attribute domain from the reader.
833    pub fn read_from<R: ByteReader>(reader: &mut R) -> Result<Self, Err> {
834        let id = reader.read_u8()?;
835        match id {
836            0 => Ok(Self::Position),
837            1 => Ok(Self::Corner),
838            _ => Err(Err::InvalidAttributeDomainId(id)),
839        }
840    }
841}
842
843#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize)]
844pub struct AttributeId(usize);
845
846impl AttributeId {
847    pub fn new(id: usize) -> Self {
848        Self(id)
849    }
850
851    /// Returns the id of the attribute.
852    pub fn as_usize(&self) -> usize {
853        self.0
854    }
855}
856
857#[cfg(test)]
858mod tests {
859    use super::*;
860    use crate::types::NdVector;
861
862    #[test]
863    fn test_attribute() {
864        let data = vec![
865            NdVector::from([1.0f32, 2.0, 3.0]),
866            NdVector::from([4.0f32, 5.0, 6.0]),
867            NdVector::from([7.0f32, 8.0, 9.0]),
868        ];
869        let att = super::Attribute::from(
870            AttributeId::new(0),
871            data.clone(),
872            super::AttributeType::Position,
873            super::AttributeDomain::Position,
874            Vec::new(),
875        );
876        assert_eq!(att.len(), data.len());
877        assert_eq!(
878            att.get::<NdVector<3, f32>, 3>(0.into()),
879            data[0],
880            "{:b}!={:b}",
881            att.get::<NdVector<3, f32>, 3>(0.into()).get(0).to_bits(),
882            data[0].get(0).to_bits()
883        );
884        assert_eq!(att.get_component_type(), super::ComponentDataType::F32);
885        assert_eq!(att.get_num_components(), 3);
886        assert_eq!(att.get_attribute_type(), super::AttributeType::Position);
887    }
888
889    #[test]
890    fn test_attribute_remap() {
891        let positions = vec![
892            NdVector::from([0.0f32, 0.0, 0.0]), // vertex 0 (unique)
893            NdVector::from([1.0f32, 0.0, 0.0]), // vertex 1 (unique)
894            NdVector::from([0.5f32, 1.0, 0.0]), // vertex 2 (unique)
895            NdVector::from([0.0f32, 0.0, 0.0]), // vertex 3 (duplicate of vertex 0)
896            NdVector::from([1.0f32, 0.0, 0.0]), // vertex 4 (duplicate of vertex 1)
897            NdVector::from([2.0f32, 0.0, 0.0]), // vertex 5 (unique)
898        ];
899
900        let att = Attribute::new(
901            positions,
902            AttributeType::Position,
903            AttributeDomain::Position,
904            vec![],
905        );
906
907        assert_eq!(
908            att.point_to_att_val_map
909                .unwrap()
910                .into_iter()
911                .map(usize::from)
912                .collect::<Vec<_>>(),
913            vec![0, 1, 2, 0, 1, 3],
914        )
915    }
916
917    #[test]
918    fn test_remove() {
919        let positions = vec![
920            NdVector::from([0.0f32, 0.0, 0.0]), // vertex 0 (unique)
921            NdVector::from([1.0f32, 0.0, 0.0]), // vertex 1 (unique)
922            NdVector::from([2.0f32, 0.0, 0.0]), // vertex 2 (unique)
923            NdVector::from([3.0f32, 0.0, 0.0]), // vertex 3 (unique)
924            NdVector::from([2.0f32, 0.0, 0.0]), // vertex 4 (duplicate of vertex 2)
925            NdVector::from([5.0f32, 0.0, 0.0]), // vertex 5 (unique)
926        ];
927
928        let mut att = Attribute::new(
929            positions,
930            AttributeType::Position,
931            AttributeDomain::Position,
932            vec![],
933        );
934
935        assert_eq!(att.len(), 6);
936        assert_eq!(att.num_unique_values(), 5);
937        assert_eq!(
938            &att.point_to_att_val_map
939                .as_ref()
940                .unwrap()
941                .iter()
942                .map(|&i| usize::from(i))
943                .collect::<Vec<_>>(),
944            &vec![0, 1, 2, 3, 2, 4]
945        );
946        att.remove::<NdVector<3, f32>, 3>(PointIdx::from(2)); // remove vertex 2
947        assert_eq!(att.len(), 5);
948        assert_eq!(att.num_unique_values(), 5);
949        assert_eq!(
950            &att.point_to_att_val_map
951                .as_ref()
952                .unwrap()
953                .iter()
954                .map(|&i| usize::from(i))
955                .collect::<Vec<_>>(),
956            &vec![0, 1, 3, 2, 4]
957        );
958        att.remove::<NdVector<3, f32>, 3>(PointIdx::from(1)); // remove vertex 1
959        assert_eq!(att.len(), 4);
960        assert_eq!(att.num_unique_values(), 4);
961        assert_eq!(
962            &att.point_to_att_val_map
963                .as_ref()
964                .unwrap()
965                .iter()
966                .map(|&i| usize::from(i))
967                .collect::<Vec<_>>(),
968            &vec![0, 2, 1, 3]
969        );
970    }
971}