draco_oxide/core/attribute/
mod.rs

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