use super::payload::{bytes, invalid, row_count};
use crate::DatasetError;
use std::sync::Arc;
#[derive(Clone, Debug)]
pub struct MeshChunkPayload {
positions: Arc<[[f32; 3]]>,
normals: Arc<[[f32; 3]]>,
colors: Arc<[[u8; 4]]>,
indices: Arc<[u32]>,
}
impl MeshChunkPayload {
pub fn new(
positions: Arc<[[f32; 3]]>,
normals: Arc<[[f32; 3]]>,
colors: Arc<[[u8; 4]]>,
indices: Arc<[u32]>,
) -> Result<Self, DatasetError> {
let vertices = row_count(positions.len())?;
if vertices == 0
|| normals.len() != positions.len()
|| colors.len() != positions.len()
|| indices.is_empty()
|| !indices.len().is_multiple_of(3)
{
return Err(invalid(
"mesh columns must be aligned and contain triangles",
));
}
if positions
.iter()
.chain(normals.iter())
.flatten()
.any(|value| !value.is_finite())
|| indices.iter().any(|index| *index >= vertices)
{
return Err(invalid(
"mesh values must be finite and indices chunk-local",
));
}
Ok(Self {
positions,
normals,
colors,
indices,
})
}
#[must_use]
pub fn positions(&self) -> &Arc<[[f32; 3]]> {
&self.positions
}
#[must_use]
pub fn normals(&self) -> &Arc<[[f32; 3]]> {
&self.normals
}
#[must_use]
pub fn colors(&self) -> &Arc<[[u8; 4]]> {
&self.colors
}
#[must_use]
pub fn indices(&self) -> &Arc<[u32]> {
&self.indices
}
pub(super) fn minimum_host_bytes(&self) -> Result<u64, DatasetError> {
let positions = bytes(self.positions.len(), 12)?;
let normals = bytes(self.normals.len(), 12)?;
let colors = bytes(self.colors.len(), 4)?;
let indices = bytes(self.indices.len(), 4)?;
positions
.checked_add(normals)
.and_then(|value| value.checked_add(colors))
.and_then(|value| value.checked_add(indices))
.ok_or(DatasetError::PayloadByteSizeOverflow)
}
}
#[derive(Clone, Debug)]
pub struct ProxyChunkPayload {
centers: Arc<[[f32; 3]]>,
radii: Arc<[f32]>,
colors: Arc<[[u8; 4]]>,
}
impl ProxyChunkPayload {
pub fn new(
centers: Arc<[[f32; 3]]>,
radii: Arc<[f32]>,
colors: Arc<[[u8; 4]]>,
) -> Result<Self, DatasetError> {
row_count(centers.len())?;
if centers.is_empty() || radii.len() != centers.len() || colors.len() != centers.len() {
return Err(invalid("proxy columns must be non-empty and aligned"));
}
if centers.iter().flatten().any(|value| !value.is_finite())
|| radii
.iter()
.any(|radius| !radius.is_finite() || *radius < 0.0)
{
return Err(invalid("proxy centers and radii must be finite"));
}
Ok(Self {
centers,
radii,
colors,
})
}
#[must_use]
pub fn centers(&self) -> &Arc<[[f32; 3]]> {
&self.centers
}
#[must_use]
pub fn radii(&self) -> &Arc<[f32]> {
&self.radii
}
#[must_use]
pub fn colors(&self) -> &Arc<[[u8; 4]]> {
&self.colors
}
pub(super) fn minimum_host_bytes(&self) -> Result<u64, DatasetError> {
let centers = bytes(self.centers.len(), 12)?;
let radii = bytes(self.radii.len(), 4)?;
let colors = bytes(self.colors.len(), 4)?;
centers
.checked_add(radii)
.and_then(|value| value.checked_add(colors))
.ok_or(DatasetError::PayloadByteSizeOverflow)
}
}