pub use gltf::json::accessor::ComponentType;
use std::{cell::RefCell, rc::Rc};
use crate::graph::{AccessorArray, AccessorData, ElementType, GltfGraph, GraphData, GraphNode};
use petgraph::graph::NodeIndex;
pub struct Accessor {
pub(crate) node: GraphNode,
}
impl Accessor {
pub fn new(graph: Rc<RefCell<GltfGraph>>, index: NodeIndex) -> Self {
Self {
node: GraphNode::new(graph, index),
}
}
fn data(&self) -> AccessorData {
match self.node.data() {
GraphData::Accessor(data) => data,
_ => panic!("data is not an accessor"),
}
}
fn set_data(&mut self, data: AccessorData) {
self.node.set_data(GraphData::Accessor(data));
}
pub fn name(&self) -> Option<String> {
self.data().name
}
pub fn set_name(&mut self, name: Option<String>) {
let mut data = self.data();
data.name = name;
self.set_data(data);
}
pub fn array(&self) -> AccessorArray {
self.data().array
}
pub fn set_array(&mut self, array: AccessorArray) {
let mut data = self.data();
data.array = array;
self.set_data(data);
}
pub fn element_type(&self) -> ElementType {
self.data().element_type
}
pub fn set_element_type(&mut self, element_type: ElementType) {
let mut data = self.data();
data.element_type = element_type;
self.set_data(data);
}
pub fn normalized(&self) -> bool {
self.data().normalized
}
pub fn set_normalized(&mut self, normalized: bool) {
let mut data = self.data();
data.normalized = normalized;
self.set_data(data);
}
pub fn byte_length(&self) -> usize {
self.data().array.len() * self.component_size()
}
pub fn component_type(&self) -> ComponentType {
match self.data().array {
AccessorArray::I8(_) => ComponentType::I8,
AccessorArray::U8(_) => ComponentType::U8,
AccessorArray::I16(_) => ComponentType::I16,
AccessorArray::U16(_) => ComponentType::U16,
AccessorArray::U32(_) => ComponentType::U32,
AccessorArray::F32(_) => ComponentType::F32,
}
}
pub fn component_size(&self) -> usize {
match self.component_type() {
ComponentType::I8 => 1,
ComponentType::U8 => 1,
ComponentType::I16 => 2,
ComponentType::U16 => 2,
ComponentType::U32 => 4,
ComponentType::F32 => 4,
}
}
pub fn count(&self) -> usize {
let len = self.data().array.len();
let element_size = self.element_size();
len / element_size
}
pub fn element_size(&self) -> usize {
self.data().element_type.size()
}
pub fn max(&self) -> AccessorArray {
let element_size = self.element_size();
match self.data().array {
AccessorArray::I8(array) => get_max(&array, element_size).into(),
AccessorArray::U8(array) => get_max(&array, element_size).into(),
AccessorArray::I16(array) => get_max(&array, element_size).into(),
AccessorArray::U16(array) => get_max(&array, element_size).into(),
AccessorArray::U32(array) => get_max(&array, element_size).into(),
AccessorArray::F32(array) => get_max(&array, element_size).into(),
}
}
pub fn min(&self) -> AccessorArray {
let element_size = self.element_size();
match self.data().array {
AccessorArray::I8(array) => get_min(&array, element_size).into(),
AccessorArray::U8(array) => get_min(&array, element_size).into(),
AccessorArray::I16(array) => get_min(&array, element_size).into(),
AccessorArray::U16(array) => get_min(&array, element_size).into(),
AccessorArray::U32(array) => get_min(&array, element_size).into(),
AccessorArray::F32(array) => get_min(&array, element_size).into(),
}
}
}
fn get_max<T>(array: &[T], element_size: usize) -> Vec<T>
where
T: Copy + PartialOrd,
{
array
.chunks(element_size)
.fold(Vec::with_capacity(element_size), |max: Vec<T>, chunk| {
max.iter()
.zip(chunk.iter())
.map(|(a, b)| if a > b { *a } else { *b })
.collect()
})
}
fn get_min<T>(array: &[T], element_size: usize) -> Vec<T>
where
T: Copy + PartialOrd,
{
array
.chunks(element_size)
.fold(Vec::with_capacity(element_size), |min: Vec<T>, chunk| {
min.iter()
.zip(chunk.iter())
.map(|(a, b)| if a < b { *a } else { *b })
.collect()
})
}