1mod parser;
2
3pub use parser::parse;
4
5use serde::{Deserialize, Serialize};
6
7pub struct OpdFile {
8 pub header: OpdHeader,
9 pub centroids: Vec<Centroid>,
10 pub frames: Frames,
11}
12
13#[derive(Deserialize, Debug, Serialize)]
14pub struct OpdHeader {
15 pub version: String,
16 pub compressed: Option<String>,
17 #[serde(rename = "type")]
18 pub ty: String,
19 pub directive: OpdHeaderDirective,
20}
21
22#[derive(Clone)]
23pub struct Frame<T> {
24 pub time: f32,
25 pub data: Vec<T>,
26}
27
28impl<'a, T> IntoIterator for &'a Frame<T>
29where
30 T: Copy + Into<f32>,
31{
32 type IntoIter = FrameIterator<'a, T>;
33 type Item = [f32; 3];
34
35 fn into_iter(self) -> Self::IntoIter {
36 FrameIterator {
37 iter: self.data.iter(),
38 }
39 }
40}
41
42pub struct FrameIterator<'a, T> {
43 iter: std::slice::Iter<'a, T>,
44}
45
46impl<'a, T: Copy> Iterator for FrameIterator<'a, T>
47where
48 T: Into<f32>,
49{
50 type Item = [f32; 3];
51
52 fn next(&mut self) -> Option<Self::Item> {
53 let max_value: usize = (1 << (std::mem::size_of::<T>() * 8 - 1)) - 1;
54 let max_value = max_value as f32;
55 let arr: [f32; 3] = [
56 match self.iter.next() {
57 Some(a) => (*a).into() / max_value,
58 None => return None,
59 },
60 match self.iter.next() {
61 Some(a) => (*a).into() / max_value,
62 None => return None,
63 },
64 match self.iter.next() {
65 Some(a) => (*a).into() / max_value,
66 None => return None,
67 },
68 ];
69 Some(arr)
70 }
71}
72
73#[derive(Clone)]
74pub enum Frames {
75 I8(Vec<Frame<i8>>),
76 I16(Vec<Frame<i16>>),
77 I32(Vec<Frame<i32>>),
78 I64(Vec<Frame<i64>>),
79}
80
81#[derive(Deserialize, Debug, Serialize, Clone)]
82pub struct FrameMeta {
83 pub time: f32,
84 pub offset: usize,
85}
86
87#[derive(Deserialize, Debug, Serialize)]
88pub struct OpdHeaderDirective {
89 pub version: String,
90 pub meta: OpdHeaderDirectiveMeta,
91
92 #[serde(rename = "numCentroids")]
93 pub num_centroids: Option<usize>,
94 #[serde(rename = "hasCentroidVolumes")]
95 pub has_centroid_volumes: Option<bool>,
96
97 #[serde(rename = "numPoints")]
98 pub num_points: Option<usize>,
99
100 pub origin: OpdHeaderDirectiveOrigin,
101
102 pub precision: usize,
103 pub scale: [f32; 3],
104 pub frames: Vec<FrameMeta>,
105
106 pub index: Option<bool>,
107 #[serde(rename = "subCentroids")]
108 pub sub_centroids: Option<bool>,
109
110 #[serde(rename = "lastFrameCorrected")]
111 pub last_frame_corrected: Option<bool>,
112}
113
114#[derive(Deserialize, Debug, Serialize)]
115pub struct OpdHeaderDirectiveOrigin {
116 pub x: f64,
117 pub y: f64,
118 pub z: f64,
119}
120
121impl From<OpdHeaderDirectiveOrigin> for [f64; 3] {
122 fn from(value: OpdHeaderDirectiveOrigin) -> Self {
123 [value.x, value.y, value.z]
124 }
125}
126
127#[derive(Deserialize, Debug, Serialize)]
128pub struct OpdHeaderDirectiveMeta {
129 #[serde(rename = "projectId")]
130 pub project_id: String,
131
132 #[serde(rename = "projectName")]
133 pub project_name: String,
134}
135
136pub struct Centroid {
137 pub parent_id: u32,
138
139 pub offset: [f32; 3],
141}