1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
mod parser;

use glam::Vec3;
pub use parser::parse;
use serde::Deserialize;

pub struct OpdFile {
    pub header: OpdHeader,
    pub centroids: Vec<Centroid>,
    pub frames: Frames,
}

#[derive(Deserialize, Debug)]
pub struct OpdHeader {
    pub version: String,
    #[serde(rename = "type")]
    pub ty: String,
    pub directive: OpdHeaderDirective,
}

#[derive(Clone)]
pub struct Frame<T> {
    pub time: f32,
    pub data: Vec<T>,
}

impl<T: Copy> Frame<T> {
    pub fn frame_as_vec3a(&self) -> impl Iterator<Item = Vec3> + '_
    where
        T: Into<f32>,
    {
        let iter = self.data.iter();
        FrameIterator { iter }
    }
}
pub struct FrameIterator<'a, T> {
    iter: std::slice::Iter<'a, T>,
}
impl<'a, T: Copy> Iterator for FrameIterator<'a, T>
where
    T: Into<f32>,
{
    type Item = Vec3;
    fn next(&mut self) -> Option<Self::Item> {
        let max_value: usize = (1 << (std::mem::size_of::<T>() * 8 - 1)) - 1;
        let max_value = max_value as f32;
        let arr: [f32; 3] = [
            match self.iter.next() {
                Some(a) => (*a).into() / max_value,
                None => return None,
            },
            match self.iter.next() {
                Some(a) => (*a).into() / max_value,
                None => return None,
            },
            match self.iter.next() {
                Some(a) => (*a).into() / max_value,
                None => return None,
            },
        ];
        Some(arr.into())
    }
}

#[derive(Clone)]
pub enum Frames {
    I8(Vec<Frame<i8>>),
    I16(Vec<Frame<i16>>),
    I32(Vec<Frame<i32>>),
    I64(Vec<Frame<i64>>),
}

#[derive(Deserialize, Debug)]
pub struct FrameMeta {
    pub time: f32,
    pub offset: usize,
}

#[derive(Deserialize, Debug)]
pub struct OpdHeaderDirective {
    pub version: String,
    pub meta: OpdHeaderDirectiveMeta,

    #[serde(rename = "numCentroids")]
    pub num_centroids: usize,

    pub origin: OpdHeaderDirectiveOrigin,

    pub precision: usize,
    pub scale: Vec3,
    pub frames: Vec<FrameMeta>,
}

#[derive(Deserialize, Debug)]
pub struct OpdHeaderDirectiveOrigin {
    pub x: f32,
    pub y: f32,
    pub z: f32,
}
impl From<OpdHeaderDirectiveOrigin> for Vec3 {
    fn from(value: OpdHeaderDirectiveOrigin) -> Self {
        Vec3 {
            x: value.x,
            y: value.y,
            z: value.z,
        }
    }
}

#[derive(Deserialize, Debug)]
pub struct OpdHeaderDirectiveMeta {
    #[serde(rename = "projectId")]
    pub project_id: String,

    #[serde(rename = "projectName")]
    pub project_name: String,
}

pub struct Centroid {
    pub parent_id: u32,

    /// Relative to origin defined in header
    pub offset: Vec3,
}