re_types/archetypes/
mesh3d.rs

1// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/rust/api.rs
2// Based on "crates/store/re_types/definitions/rerun/archetypes/mesh3d.fbs".
3
4#![allow(unused_braces)]
5#![allow(unused_imports)]
6#![allow(unused_parens)]
7#![allow(clippy::clone_on_copy)]
8#![allow(clippy::cloned_instead_of_copied)]
9#![allow(clippy::map_flatten)]
10#![allow(clippy::needless_question_mark)]
11#![allow(clippy::new_without_default)]
12#![allow(clippy::redundant_closure)]
13#![allow(clippy::too_many_arguments)]
14#![allow(clippy::too_many_lines)]
15
16use ::re_types_core::SerializationResult;
17use ::re_types_core::try_serialize_field;
18use ::re_types_core::{ComponentBatch as _, SerializedComponentBatch};
19use ::re_types_core::{ComponentDescriptor, ComponentType};
20use ::re_types_core::{DeserializationError, DeserializationResult};
21
22/// **Archetype**: A 3D triangle mesh as specified by its per-mesh and per-vertex properties.
23///
24/// See also [`archetypes::Asset3D`][crate::archetypes::Asset3D].
25///
26/// If there are multiple [`archetypes::InstancePoses3D`][crate::archetypes::InstancePoses3D] instances logged to the same entity as a mesh,
27/// an instance of the mesh will be drawn for each transform.
28///
29/// The viewer draws meshes always two-sided. However, for transparency ordering
30/// front faces are assumed to those with counter clockwise triangle winding order (this is the same as in the GLTF specification).
31///
32/// ## Examples
33///
34/// ### Simple indexed 3D mesh
35/// ```ignore
36/// fn main() -> Result<(), Box<dyn std::error::Error>> {
37///     let rec = rerun::RecordingStreamBuilder::new("rerun_example_mesh3d_indexed").spawn()?;
38///
39///     rec.log(
40///         "triangle",
41///         &rerun::Mesh3D::new([[0.0, 1.0, 0.0], [1.0, 0.0, 0.0], [0.0, 0.0, 0.0]])
42///             .with_vertex_normals([[0.0, 0.0, 1.0]])
43///             .with_vertex_colors([0x0000FFFF, 0x00FF00FF, 0xFF0000FF])
44///             .with_triangle_indices([[2, 1, 0]]),
45///     )?;
46///
47///     Ok(())
48/// }
49/// ```
50/// <center>
51/// <picture>
52///   <source media="(max-width: 480px)" srcset="https://static.rerun.io/mesh3d_indexed/57c70dc992e6dc0bd9c5222ca084f5b6240cea75/480w.png">
53///   <source media="(max-width: 768px)" srcset="https://static.rerun.io/mesh3d_indexed/57c70dc992e6dc0bd9c5222ca084f5b6240cea75/768w.png">
54///   <source media="(max-width: 1024px)" srcset="https://static.rerun.io/mesh3d_indexed/57c70dc992e6dc0bd9c5222ca084f5b6240cea75/1024w.png">
55///   <source media="(max-width: 1200px)" srcset="https://static.rerun.io/mesh3d_indexed/57c70dc992e6dc0bd9c5222ca084f5b6240cea75/1200w.png">
56///   <img src="https://static.rerun.io/mesh3d_indexed/57c70dc992e6dc0bd9c5222ca084f5b6240cea75/full.png" width="640">
57/// </picture>
58/// </center>
59///
60/// ### 3D mesh with instancing
61/// ```ignore
62/// fn main() -> Result<(), Box<dyn std::error::Error>> {
63///     let rec = rerun::RecordingStreamBuilder::new("rerun_example_mesh3d_instancing").spawn()?;
64///
65///     rec.set_time_sequence("frame", 0);
66///     rec.log(
67///         "shape",
68///         &rerun::Mesh3D::new([
69///             [1.0, 1.0, 1.0],
70///             [-1.0, -1.0, 1.0],
71///             [-1.0, 1.0, -1.0],
72///             [1.0, -1.0, -1.0],
73///         ])
74///         .with_triangle_indices([[0, 2, 1], [0, 3, 1], [0, 3, 2], [1, 3, 2]])
75///         .with_vertex_colors([0xFF0000FF, 0x00FF00FF, 0x00000FFFF, 0xFFFF00FF]),
76///     )?;
77///     // This box will not be affected by its parent's instance poses!
78///     rec.log(
79///         "shape/box",
80///         &rerun::Boxes3D::from_half_sizes([[5.0, 5.0, 5.0]]),
81///     )?;
82///
83///     for i in 0..100 {
84///         rec.set_time_sequence("frame", i);
85///         rec.log(
86///             "shape",
87///             &rerun::InstancePoses3D::new()
88///                 .with_translations([
89///                     [2.0, 0.0, 0.0],
90///                     [0.0, 2.0, 0.0],
91///                     [0.0, -2.0, 0.0],
92///                     [-2.0, 0.0, 0.0],
93///                 ])
94///                 .with_rotation_axis_angles([rerun::RotationAxisAngle::new(
95///                     [0.0, 0.0, 1.0],
96///                     rerun::Angle::from_degrees(i as f32 * 2.0),
97///                 )]),
98///         )?;
99///     }
100///
101///     Ok(())
102/// }
103/// ```
104/// <center>
105/// <picture>
106///   <source media="(max-width: 480px)" srcset="https://static.rerun.io/mesh3d_leaf_transforms3d/c2d0ee033129da53168f5705625a9b033f3a3d61/480w.png">
107///   <source media="(max-width: 768px)" srcset="https://static.rerun.io/mesh3d_leaf_transforms3d/c2d0ee033129da53168f5705625a9b033f3a3d61/768w.png">
108///   <source media="(max-width: 1024px)" srcset="https://static.rerun.io/mesh3d_leaf_transforms3d/c2d0ee033129da53168f5705625a9b033f3a3d61/1024w.png">
109///   <source media="(max-width: 1200px)" srcset="https://static.rerun.io/mesh3d_leaf_transforms3d/c2d0ee033129da53168f5705625a9b033f3a3d61/1200w.png">
110///   <img src="https://static.rerun.io/mesh3d_leaf_transforms3d/c2d0ee033129da53168f5705625a9b033f3a3d61/full.png" width="640">
111/// </picture>
112/// </center>
113#[derive(Clone, Debug, PartialEq, Default)]
114pub struct Mesh3D {
115    /// The positions of each vertex.
116    ///
117    /// If no `triangle_indices` are specified, then each triplet of positions is interpreted as a triangle.
118    pub vertex_positions: Option<SerializedComponentBatch>,
119
120    /// Optional indices for the triangles that make up the mesh.
121    pub triangle_indices: Option<SerializedComponentBatch>,
122
123    /// An optional normal for each vertex.
124    pub vertex_normals: Option<SerializedComponentBatch>,
125
126    /// An optional color for each vertex.
127    ///
128    /// The alpha channel is ignored.
129    pub vertex_colors: Option<SerializedComponentBatch>,
130
131    /// An optional uv texture coordinate for each vertex.
132    pub vertex_texcoords: Option<SerializedComponentBatch>,
133
134    /// A color multiplier applied to the whole mesh.
135    ///
136    /// Alpha channel governs the overall mesh transparency.
137    pub albedo_factor: Option<SerializedComponentBatch>,
138
139    /// Optional albedo texture.
140    ///
141    /// Used with the [`components::Texcoord2D`][crate::components::Texcoord2D] of the mesh.
142    ///
143    /// Currently supports only sRGB(A) textures, ignoring alpha.
144    /// (meaning that the tensor must have 3 or 4 channels and use the `u8` format)
145    ///
146    /// The alpha channel is ignored.
147    pub albedo_texture_buffer: Option<SerializedComponentBatch>,
148
149    /// The format of the `albedo_texture_buffer`, if any.
150    pub albedo_texture_format: Option<SerializedComponentBatch>,
151
152    /// Optional class Ids for the vertices.
153    ///
154    /// The [`components::ClassId`][crate::components::ClassId] provides colors and labels if not specified explicitly.
155    pub class_ids: Option<SerializedComponentBatch>,
156}
157
158impl Mesh3D {
159    /// Returns the [`ComponentDescriptor`] for [`Self::vertex_positions`].
160    ///
161    /// The corresponding component is [`crate::components::Position3D`].
162    #[inline]
163    pub fn descriptor_vertex_positions() -> ComponentDescriptor {
164        ComponentDescriptor {
165            archetype: Some("rerun.archetypes.Mesh3D".into()),
166            component: "Mesh3D:vertex_positions".into(),
167            component_type: Some("rerun.components.Position3D".into()),
168        }
169    }
170
171    /// Returns the [`ComponentDescriptor`] for [`Self::triangle_indices`].
172    ///
173    /// The corresponding component is [`crate::components::TriangleIndices`].
174    #[inline]
175    pub fn descriptor_triangle_indices() -> ComponentDescriptor {
176        ComponentDescriptor {
177            archetype: Some("rerun.archetypes.Mesh3D".into()),
178            component: "Mesh3D:triangle_indices".into(),
179            component_type: Some("rerun.components.TriangleIndices".into()),
180        }
181    }
182
183    /// Returns the [`ComponentDescriptor`] for [`Self::vertex_normals`].
184    ///
185    /// The corresponding component is [`crate::components::Vector3D`].
186    #[inline]
187    pub fn descriptor_vertex_normals() -> ComponentDescriptor {
188        ComponentDescriptor {
189            archetype: Some("rerun.archetypes.Mesh3D".into()),
190            component: "Mesh3D:vertex_normals".into(),
191            component_type: Some("rerun.components.Vector3D".into()),
192        }
193    }
194
195    /// Returns the [`ComponentDescriptor`] for [`Self::vertex_colors`].
196    ///
197    /// The corresponding component is [`crate::components::Color`].
198    #[inline]
199    pub fn descriptor_vertex_colors() -> ComponentDescriptor {
200        ComponentDescriptor {
201            archetype: Some("rerun.archetypes.Mesh3D".into()),
202            component: "Mesh3D:vertex_colors".into(),
203            component_type: Some("rerun.components.Color".into()),
204        }
205    }
206
207    /// Returns the [`ComponentDescriptor`] for [`Self::vertex_texcoords`].
208    ///
209    /// The corresponding component is [`crate::components::Texcoord2D`].
210    #[inline]
211    pub fn descriptor_vertex_texcoords() -> ComponentDescriptor {
212        ComponentDescriptor {
213            archetype: Some("rerun.archetypes.Mesh3D".into()),
214            component: "Mesh3D:vertex_texcoords".into(),
215            component_type: Some("rerun.components.Texcoord2D".into()),
216        }
217    }
218
219    /// Returns the [`ComponentDescriptor`] for [`Self::albedo_factor`].
220    ///
221    /// The corresponding component is [`crate::components::AlbedoFactor`].
222    #[inline]
223    pub fn descriptor_albedo_factor() -> ComponentDescriptor {
224        ComponentDescriptor {
225            archetype: Some("rerun.archetypes.Mesh3D".into()),
226            component: "Mesh3D:albedo_factor".into(),
227            component_type: Some("rerun.components.AlbedoFactor".into()),
228        }
229    }
230
231    /// Returns the [`ComponentDescriptor`] for [`Self::albedo_texture_buffer`].
232    ///
233    /// The corresponding component is [`crate::components::ImageBuffer`].
234    #[inline]
235    pub fn descriptor_albedo_texture_buffer() -> ComponentDescriptor {
236        ComponentDescriptor {
237            archetype: Some("rerun.archetypes.Mesh3D".into()),
238            component: "Mesh3D:albedo_texture_buffer".into(),
239            component_type: Some("rerun.components.ImageBuffer".into()),
240        }
241    }
242
243    /// Returns the [`ComponentDescriptor`] for [`Self::albedo_texture_format`].
244    ///
245    /// The corresponding component is [`crate::components::ImageFormat`].
246    #[inline]
247    pub fn descriptor_albedo_texture_format() -> ComponentDescriptor {
248        ComponentDescriptor {
249            archetype: Some("rerun.archetypes.Mesh3D".into()),
250            component: "Mesh3D:albedo_texture_format".into(),
251            component_type: Some("rerun.components.ImageFormat".into()),
252        }
253    }
254
255    /// Returns the [`ComponentDescriptor`] for [`Self::class_ids`].
256    ///
257    /// The corresponding component is [`crate::components::ClassId`].
258    #[inline]
259    pub fn descriptor_class_ids() -> ComponentDescriptor {
260        ComponentDescriptor {
261            archetype: Some("rerun.archetypes.Mesh3D".into()),
262            component: "Mesh3D:class_ids".into(),
263            component_type: Some("rerun.components.ClassId".into()),
264        }
265    }
266}
267
268static REQUIRED_COMPONENTS: std::sync::LazyLock<[ComponentDescriptor; 1usize]> =
269    std::sync::LazyLock::new(|| [Mesh3D::descriptor_vertex_positions()]);
270
271static RECOMMENDED_COMPONENTS: std::sync::LazyLock<[ComponentDescriptor; 2usize]> =
272    std::sync::LazyLock::new(|| {
273        [
274            Mesh3D::descriptor_triangle_indices(),
275            Mesh3D::descriptor_vertex_normals(),
276        ]
277    });
278
279static OPTIONAL_COMPONENTS: std::sync::LazyLock<[ComponentDescriptor; 6usize]> =
280    std::sync::LazyLock::new(|| {
281        [
282            Mesh3D::descriptor_vertex_colors(),
283            Mesh3D::descriptor_vertex_texcoords(),
284            Mesh3D::descriptor_albedo_factor(),
285            Mesh3D::descriptor_albedo_texture_buffer(),
286            Mesh3D::descriptor_albedo_texture_format(),
287            Mesh3D::descriptor_class_ids(),
288        ]
289    });
290
291static ALL_COMPONENTS: std::sync::LazyLock<[ComponentDescriptor; 9usize]> =
292    std::sync::LazyLock::new(|| {
293        [
294            Mesh3D::descriptor_vertex_positions(),
295            Mesh3D::descriptor_triangle_indices(),
296            Mesh3D::descriptor_vertex_normals(),
297            Mesh3D::descriptor_vertex_colors(),
298            Mesh3D::descriptor_vertex_texcoords(),
299            Mesh3D::descriptor_albedo_factor(),
300            Mesh3D::descriptor_albedo_texture_buffer(),
301            Mesh3D::descriptor_albedo_texture_format(),
302            Mesh3D::descriptor_class_ids(),
303        ]
304    });
305
306impl Mesh3D {
307    /// The total number of components in the archetype: 1 required, 2 recommended, 6 optional
308    pub const NUM_COMPONENTS: usize = 9usize;
309}
310
311impl ::re_types_core::Archetype for Mesh3D {
312    #[inline]
313    fn name() -> ::re_types_core::ArchetypeName {
314        "rerun.archetypes.Mesh3D".into()
315    }
316
317    #[inline]
318    fn display_name() -> &'static str {
319        "Mesh 3D"
320    }
321
322    #[inline]
323    fn required_components() -> ::std::borrow::Cow<'static, [ComponentDescriptor]> {
324        REQUIRED_COMPONENTS.as_slice().into()
325    }
326
327    #[inline]
328    fn recommended_components() -> ::std::borrow::Cow<'static, [ComponentDescriptor]> {
329        RECOMMENDED_COMPONENTS.as_slice().into()
330    }
331
332    #[inline]
333    fn optional_components() -> ::std::borrow::Cow<'static, [ComponentDescriptor]> {
334        OPTIONAL_COMPONENTS.as_slice().into()
335    }
336
337    #[inline]
338    fn all_components() -> ::std::borrow::Cow<'static, [ComponentDescriptor]> {
339        ALL_COMPONENTS.as_slice().into()
340    }
341
342    #[inline]
343    fn from_arrow_components(
344        arrow_data: impl IntoIterator<Item = (ComponentDescriptor, arrow::array::ArrayRef)>,
345    ) -> DeserializationResult<Self> {
346        re_tracing::profile_function!();
347        use ::re_types_core::{Loggable as _, ResultExt as _};
348        let arrays_by_descr: ::nohash_hasher::IntMap<_, _> = arrow_data.into_iter().collect();
349        let vertex_positions = arrays_by_descr
350            .get(&Self::descriptor_vertex_positions())
351            .map(|array| {
352                SerializedComponentBatch::new(array.clone(), Self::descriptor_vertex_positions())
353            });
354        let triangle_indices = arrays_by_descr
355            .get(&Self::descriptor_triangle_indices())
356            .map(|array| {
357                SerializedComponentBatch::new(array.clone(), Self::descriptor_triangle_indices())
358            });
359        let vertex_normals = arrays_by_descr
360            .get(&Self::descriptor_vertex_normals())
361            .map(|array| {
362                SerializedComponentBatch::new(array.clone(), Self::descriptor_vertex_normals())
363            });
364        let vertex_colors = arrays_by_descr
365            .get(&Self::descriptor_vertex_colors())
366            .map(|array| {
367                SerializedComponentBatch::new(array.clone(), Self::descriptor_vertex_colors())
368            });
369        let vertex_texcoords = arrays_by_descr
370            .get(&Self::descriptor_vertex_texcoords())
371            .map(|array| {
372                SerializedComponentBatch::new(array.clone(), Self::descriptor_vertex_texcoords())
373            });
374        let albedo_factor = arrays_by_descr
375            .get(&Self::descriptor_albedo_factor())
376            .map(|array| {
377                SerializedComponentBatch::new(array.clone(), Self::descriptor_albedo_factor())
378            });
379        let albedo_texture_buffer = arrays_by_descr
380            .get(&Self::descriptor_albedo_texture_buffer())
381            .map(|array| {
382                SerializedComponentBatch::new(
383                    array.clone(),
384                    Self::descriptor_albedo_texture_buffer(),
385                )
386            });
387        let albedo_texture_format = arrays_by_descr
388            .get(&Self::descriptor_albedo_texture_format())
389            .map(|array| {
390                SerializedComponentBatch::new(
391                    array.clone(),
392                    Self::descriptor_albedo_texture_format(),
393                )
394            });
395        let class_ids = arrays_by_descr
396            .get(&Self::descriptor_class_ids())
397            .map(|array| {
398                SerializedComponentBatch::new(array.clone(), Self::descriptor_class_ids())
399            });
400        Ok(Self {
401            vertex_positions,
402            triangle_indices,
403            vertex_normals,
404            vertex_colors,
405            vertex_texcoords,
406            albedo_factor,
407            albedo_texture_buffer,
408            albedo_texture_format,
409            class_ids,
410        })
411    }
412}
413
414impl ::re_types_core::AsComponents for Mesh3D {
415    #[inline]
416    fn as_serialized_batches(&self) -> Vec<SerializedComponentBatch> {
417        use ::re_types_core::Archetype as _;
418        [
419            self.vertex_positions.clone(),
420            self.triangle_indices.clone(),
421            self.vertex_normals.clone(),
422            self.vertex_colors.clone(),
423            self.vertex_texcoords.clone(),
424            self.albedo_factor.clone(),
425            self.albedo_texture_buffer.clone(),
426            self.albedo_texture_format.clone(),
427            self.class_ids.clone(),
428        ]
429        .into_iter()
430        .flatten()
431        .collect()
432    }
433}
434
435impl ::re_types_core::ArchetypeReflectionMarker for Mesh3D {}
436
437impl Mesh3D {
438    /// Create a new `Mesh3D`.
439    #[inline]
440    pub fn new(
441        vertex_positions: impl IntoIterator<Item = impl Into<crate::components::Position3D>>,
442    ) -> Self {
443        Self {
444            vertex_positions: try_serialize_field(
445                Self::descriptor_vertex_positions(),
446                vertex_positions,
447            ),
448            triangle_indices: None,
449            vertex_normals: None,
450            vertex_colors: None,
451            vertex_texcoords: None,
452            albedo_factor: None,
453            albedo_texture_buffer: None,
454            albedo_texture_format: None,
455            class_ids: None,
456        }
457    }
458
459    /// Update only some specific fields of a `Mesh3D`.
460    #[inline]
461    pub fn update_fields() -> Self {
462        Self::default()
463    }
464
465    /// Clear all the fields of a `Mesh3D`.
466    #[inline]
467    pub fn clear_fields() -> Self {
468        use ::re_types_core::Loggable as _;
469        Self {
470            vertex_positions: Some(SerializedComponentBatch::new(
471                crate::components::Position3D::arrow_empty(),
472                Self::descriptor_vertex_positions(),
473            )),
474            triangle_indices: Some(SerializedComponentBatch::new(
475                crate::components::TriangleIndices::arrow_empty(),
476                Self::descriptor_triangle_indices(),
477            )),
478            vertex_normals: Some(SerializedComponentBatch::new(
479                crate::components::Vector3D::arrow_empty(),
480                Self::descriptor_vertex_normals(),
481            )),
482            vertex_colors: Some(SerializedComponentBatch::new(
483                crate::components::Color::arrow_empty(),
484                Self::descriptor_vertex_colors(),
485            )),
486            vertex_texcoords: Some(SerializedComponentBatch::new(
487                crate::components::Texcoord2D::arrow_empty(),
488                Self::descriptor_vertex_texcoords(),
489            )),
490            albedo_factor: Some(SerializedComponentBatch::new(
491                crate::components::AlbedoFactor::arrow_empty(),
492                Self::descriptor_albedo_factor(),
493            )),
494            albedo_texture_buffer: Some(SerializedComponentBatch::new(
495                crate::components::ImageBuffer::arrow_empty(),
496                Self::descriptor_albedo_texture_buffer(),
497            )),
498            albedo_texture_format: Some(SerializedComponentBatch::new(
499                crate::components::ImageFormat::arrow_empty(),
500                Self::descriptor_albedo_texture_format(),
501            )),
502            class_ids: Some(SerializedComponentBatch::new(
503                crate::components::ClassId::arrow_empty(),
504                Self::descriptor_class_ids(),
505            )),
506        }
507    }
508
509    /// Partitions the component data into multiple sub-batches.
510    ///
511    /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s
512    /// instead, via [`SerializedComponentBatch::partitioned`].
513    ///
514    /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun.
515    ///
516    /// The specified `lengths` must sum to the total length of the component batch.
517    ///
518    /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn]
519    #[inline]
520    pub fn columns<I>(
521        self,
522        _lengths: I,
523    ) -> SerializationResult<impl Iterator<Item = ::re_types_core::SerializedComponentColumn>>
524    where
525        I: IntoIterator<Item = usize> + Clone,
526    {
527        let columns = [
528            self.vertex_positions
529                .map(|vertex_positions| vertex_positions.partitioned(_lengths.clone()))
530                .transpose()?,
531            self.triangle_indices
532                .map(|triangle_indices| triangle_indices.partitioned(_lengths.clone()))
533                .transpose()?,
534            self.vertex_normals
535                .map(|vertex_normals| vertex_normals.partitioned(_lengths.clone()))
536                .transpose()?,
537            self.vertex_colors
538                .map(|vertex_colors| vertex_colors.partitioned(_lengths.clone()))
539                .transpose()?,
540            self.vertex_texcoords
541                .map(|vertex_texcoords| vertex_texcoords.partitioned(_lengths.clone()))
542                .transpose()?,
543            self.albedo_factor
544                .map(|albedo_factor| albedo_factor.partitioned(_lengths.clone()))
545                .transpose()?,
546            self.albedo_texture_buffer
547                .map(|albedo_texture_buffer| albedo_texture_buffer.partitioned(_lengths.clone()))
548                .transpose()?,
549            self.albedo_texture_format
550                .map(|albedo_texture_format| albedo_texture_format.partitioned(_lengths.clone()))
551                .transpose()?,
552            self.class_ids
553                .map(|class_ids| class_ids.partitioned(_lengths.clone()))
554                .transpose()?,
555        ];
556        Ok(columns.into_iter().flatten())
557    }
558
559    /// Helper to partition the component data into unit-length sub-batches.
560    ///
561    /// This is semantically similar to calling [`Self::columns`] with `std::iter::take(1).repeat(n)`,
562    /// where `n` is automatically guessed.
563    #[inline]
564    pub fn columns_of_unit_batches(
565        self,
566    ) -> SerializationResult<impl Iterator<Item = ::re_types_core::SerializedComponentColumn>> {
567        let len_vertex_positions = self.vertex_positions.as_ref().map(|b| b.array.len());
568        let len_triangle_indices = self.triangle_indices.as_ref().map(|b| b.array.len());
569        let len_vertex_normals = self.vertex_normals.as_ref().map(|b| b.array.len());
570        let len_vertex_colors = self.vertex_colors.as_ref().map(|b| b.array.len());
571        let len_vertex_texcoords = self.vertex_texcoords.as_ref().map(|b| b.array.len());
572        let len_albedo_factor = self.albedo_factor.as_ref().map(|b| b.array.len());
573        let len_albedo_texture_buffer = self.albedo_texture_buffer.as_ref().map(|b| b.array.len());
574        let len_albedo_texture_format = self.albedo_texture_format.as_ref().map(|b| b.array.len());
575        let len_class_ids = self.class_ids.as_ref().map(|b| b.array.len());
576        let len = None
577            .or(len_vertex_positions)
578            .or(len_triangle_indices)
579            .or(len_vertex_normals)
580            .or(len_vertex_colors)
581            .or(len_vertex_texcoords)
582            .or(len_albedo_factor)
583            .or(len_albedo_texture_buffer)
584            .or(len_albedo_texture_format)
585            .or(len_class_ids)
586            .unwrap_or(0);
587        self.columns(std::iter::repeat_n(1, len))
588    }
589
590    /// The positions of each vertex.
591    ///
592    /// If no `triangle_indices` are specified, then each triplet of positions is interpreted as a triangle.
593    #[inline]
594    pub fn with_vertex_positions(
595        mut self,
596        vertex_positions: impl IntoIterator<Item = impl Into<crate::components::Position3D>>,
597    ) -> Self {
598        self.vertex_positions =
599            try_serialize_field(Self::descriptor_vertex_positions(), vertex_positions);
600        self
601    }
602
603    /// Optional indices for the triangles that make up the mesh.
604    #[inline]
605    pub fn with_triangle_indices(
606        mut self,
607        triangle_indices: impl IntoIterator<Item = impl Into<crate::components::TriangleIndices>>,
608    ) -> Self {
609        self.triangle_indices =
610            try_serialize_field(Self::descriptor_triangle_indices(), triangle_indices);
611        self
612    }
613
614    /// An optional normal for each vertex.
615    #[inline]
616    pub fn with_vertex_normals(
617        mut self,
618        vertex_normals: impl IntoIterator<Item = impl Into<crate::components::Vector3D>>,
619    ) -> Self {
620        self.vertex_normals =
621            try_serialize_field(Self::descriptor_vertex_normals(), vertex_normals);
622        self
623    }
624
625    /// An optional color for each vertex.
626    ///
627    /// The alpha channel is ignored.
628    #[inline]
629    pub fn with_vertex_colors(
630        mut self,
631        vertex_colors: impl IntoIterator<Item = impl Into<crate::components::Color>>,
632    ) -> Self {
633        self.vertex_colors = try_serialize_field(Self::descriptor_vertex_colors(), vertex_colors);
634        self
635    }
636
637    /// An optional uv texture coordinate for each vertex.
638    #[inline]
639    pub fn with_vertex_texcoords(
640        mut self,
641        vertex_texcoords: impl IntoIterator<Item = impl Into<crate::components::Texcoord2D>>,
642    ) -> Self {
643        self.vertex_texcoords =
644            try_serialize_field(Self::descriptor_vertex_texcoords(), vertex_texcoords);
645        self
646    }
647
648    /// A color multiplier applied to the whole mesh.
649    ///
650    /// Alpha channel governs the overall mesh transparency.
651    #[inline]
652    pub fn with_albedo_factor(
653        mut self,
654        albedo_factor: impl Into<crate::components::AlbedoFactor>,
655    ) -> Self {
656        self.albedo_factor = try_serialize_field(Self::descriptor_albedo_factor(), [albedo_factor]);
657        self
658    }
659
660    /// This method makes it possible to pack multiple [`crate::components::AlbedoFactor`] in a single component batch.
661    ///
662    /// This only makes sense when used in conjunction with [`Self::columns`]. [`Self::with_albedo_factor`] should
663    /// be used when logging a single row's worth of data.
664    #[inline]
665    pub fn with_many_albedo_factor(
666        mut self,
667        albedo_factor: impl IntoIterator<Item = impl Into<crate::components::AlbedoFactor>>,
668    ) -> Self {
669        self.albedo_factor = try_serialize_field(Self::descriptor_albedo_factor(), albedo_factor);
670        self
671    }
672
673    /// Optional albedo texture.
674    ///
675    /// Used with the [`components::Texcoord2D`][crate::components::Texcoord2D] of the mesh.
676    ///
677    /// Currently supports only sRGB(A) textures, ignoring alpha.
678    /// (meaning that the tensor must have 3 or 4 channels and use the `u8` format)
679    ///
680    /// The alpha channel is ignored.
681    #[inline]
682    pub fn with_albedo_texture_buffer(
683        mut self,
684        albedo_texture_buffer: impl Into<crate::components::ImageBuffer>,
685    ) -> Self {
686        self.albedo_texture_buffer = try_serialize_field(
687            Self::descriptor_albedo_texture_buffer(),
688            [albedo_texture_buffer],
689        );
690        self
691    }
692
693    /// This method makes it possible to pack multiple [`crate::components::ImageBuffer`] in a single component batch.
694    ///
695    /// This only makes sense when used in conjunction with [`Self::columns`]. [`Self::with_albedo_texture_buffer`] should
696    /// be used when logging a single row's worth of data.
697    #[inline]
698    pub fn with_many_albedo_texture_buffer(
699        mut self,
700        albedo_texture_buffer: impl IntoIterator<Item = impl Into<crate::components::ImageBuffer>>,
701    ) -> Self {
702        self.albedo_texture_buffer = try_serialize_field(
703            Self::descriptor_albedo_texture_buffer(),
704            albedo_texture_buffer,
705        );
706        self
707    }
708
709    /// The format of the `albedo_texture_buffer`, if any.
710    #[inline]
711    pub fn with_albedo_texture_format(
712        mut self,
713        albedo_texture_format: impl Into<crate::components::ImageFormat>,
714    ) -> Self {
715        self.albedo_texture_format = try_serialize_field(
716            Self::descriptor_albedo_texture_format(),
717            [albedo_texture_format],
718        );
719        self
720    }
721
722    /// This method makes it possible to pack multiple [`crate::components::ImageFormat`] in a single component batch.
723    ///
724    /// This only makes sense when used in conjunction with [`Self::columns`]. [`Self::with_albedo_texture_format`] should
725    /// be used when logging a single row's worth of data.
726    #[inline]
727    pub fn with_many_albedo_texture_format(
728        mut self,
729        albedo_texture_format: impl IntoIterator<Item = impl Into<crate::components::ImageFormat>>,
730    ) -> Self {
731        self.albedo_texture_format = try_serialize_field(
732            Self::descriptor_albedo_texture_format(),
733            albedo_texture_format,
734        );
735        self
736    }
737
738    /// Optional class Ids for the vertices.
739    ///
740    /// The [`components::ClassId`][crate::components::ClassId] provides colors and labels if not specified explicitly.
741    #[inline]
742    pub fn with_class_ids(
743        mut self,
744        class_ids: impl IntoIterator<Item = impl Into<crate::components::ClassId>>,
745    ) -> Self {
746        self.class_ids = try_serialize_field(Self::descriptor_class_ids(), class_ids);
747        self
748    }
749}
750
751impl ::re_byte_size::SizeBytes for Mesh3D {
752    #[inline]
753    fn heap_size_bytes(&self) -> u64 {
754        self.vertex_positions.heap_size_bytes()
755            + self.triangle_indices.heap_size_bytes()
756            + self.vertex_normals.heap_size_bytes()
757            + self.vertex_colors.heap_size_bytes()
758            + self.vertex_texcoords.heap_size_bytes()
759            + self.albedo_factor.heap_size_bytes()
760            + self.albedo_texture_buffer.heap_size_bytes()
761            + self.albedo_texture_format.heap_size_bytes()
762            + self.class_ids.heap_size_bytes()
763    }
764}