Skip to content

Commit

Permalink
Enable reading sparse accessor without buffer view
Browse files Browse the repository at this point in the history
When `accessor.bufferView` is unset the sparse iterator should
use T::zero() for `accessor.count` items as base. Then possibly
overwriting them with the values in specified by the accessor.sparse
section.

The sparse iterator is passed `accessor.count` here, so that it knows
when it should stop generating items. Before it continued until
the end of times.
  • Loading branch information
derwiath committed Jan 8, 2024
1 parent c7ddcfe commit 77111c1
Showing 1 changed file with 22 additions and 11 deletions.
33 changes: 22 additions & 11 deletions src/accessor/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@ pub struct SparseIter<'a, T: Item> {
/// This can be `None` if the base buffer view is not set. In this case the base values are all zero.
base: Option<ItemIter<'a, T>>,

/// Number of values in the base accessor
///
/// Valid even when `base` is not set.
base_count: usize,

/// Sparse indices iterator.
indices: iter::Peekable<SparseIndicesIter<'a>>,

Expand All @@ -110,11 +115,13 @@ impl<'a, T: Item> SparseIter<'a, T> {
/// Here `base` is allowed to be `None` when the base buffer view is not explicitly specified.
pub fn new(
base: Option<ItemIter<'a, T>>,
base_count: usize,
indices: SparseIndicesIter<'a>,
values: ItemIter<'a, T>,
) -> Self {
SparseIter {
base,
base_count,
indices: indices.peekable(),
values,
counter: 0,
Expand All @@ -125,11 +132,17 @@ impl<'a, T: Item> SparseIter<'a, T> {
impl<'a, T: Item> Iterator for SparseIter<'a, T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
let mut next_value = self
.base
.as_mut()
.map(|iter| iter.next())
.unwrap_or_else(|| Some(T::zero()))?;
let mut next_value = if let Some(base) = self.base.as_mut() {
// If accessor.bufferView is set we let base decide when we have reached the end
// of the iteration sequence.
base.next()?
} else if (self.counter as usize) < self.base_count {
// Else, we continue iterating until we have generated the number of items
// specified by accessor.count
T::zero()
} else {
return None;
};

let next_sparse_index = self.indices.peek();
if let Some(index) = next_sparse_index {
Expand All @@ -145,11 +158,8 @@ impl<'a, T: Item> Iterator for SparseIter<'a, T> {
}

fn size_hint(&self) -> (usize, Option<usize>) {
if let Some(base) = self.base.as_ref() {
base.size_hint()
} else {
self.values.size_hint()
}
let hint = self.base_count - (self.counter as usize).min(self.base_count);
(hint, Some(hint))
}
}

Expand Down Expand Up @@ -303,6 +313,7 @@ impl<'a, 's, T: Item> Iter<'s, T> {
} else {
None
};
let base_count = accessor.count();

let indices = sparse.indices();
let values = sparse.values();
Expand Down Expand Up @@ -344,7 +355,7 @@ impl<'a, 's, T: Item> Iter<'s, T> {
};

Some(Iter::Sparse(SparseIter::new(
base_iter, index_iter, value_iter,
base_iter, base_count, index_iter, value_iter,
)))
}
None => {
Expand Down

0 comments on commit 77111c1

Please sign in to comment.