1use super::*;
4use crate::source::{InputKind, SourceReader, ST, XYZ};
5
6pub trait UrlResolver<'a, T> {
10 type Error;
12
13 fn resolve(&self, url: &UrlRef<T>) -> Result<&'a T, Self::Error>;
15}
16
17impl<'a, T> UrlResolver<'a, T> for LocalMap<'a, T> {
18 type Error = ();
19 fn resolve(&self, url: &UrlRef<T>) -> Result<&'a T, Self::Error> {
20 self.get(url).ok_or(())
21 }
22}
23
24impl<'a, T: HasId> UrlResolver<'a, T> for LocalMaps<'a> {
25 type Error = ();
26 fn resolve(&self, url: &UrlRef<T>) -> Result<&'a T, Self::Error> {
27 self.get(url).ok_or(())
28 }
29}
30
31#[derive(Clone, Debug, Default)]
34pub struct VertexImporter<'a> {
35 position: Option<SourceReader<'a, XYZ>>,
36 normal: Option<SourceReader<'a, XYZ>>,
37 texcoord: Option<SourceReader<'a, ST>>,
38}
39
40impl<'a> VertexImporter<'a> {
41 pub fn position_importer(&self) -> Option<&SourceReader<'a, XYZ>> {
43 self.position.as_ref()
44 }
45
46 pub fn normal_importer(&self) -> Option<&SourceReader<'a, XYZ>> {
48 self.normal.as_ref()
49 }
50
51 pub fn texcoord_importer(&self) -> Option<&SourceReader<'a, ST>> {
53 self.texcoord.as_ref()
54 }
55}
56
57fn load<'a, K: InputKind + Default, R: UrlResolver<'a, Source>>(
58 res: &R,
59 input: &Input,
60) -> Result<SourceReader<'a, K>, R::Error> {
61 let src = res.resolve(input.source_as_source())?;
62 Ok(src.reader(K::default()).unwrap())
63}
64
65impl Vertices {
66 pub fn importer<'a, R: UrlResolver<'a, Source>>(
69 &'a self,
70 res: &R,
71 ) -> Result<VertexImporter<'a>, R::Error> {
72 let mut imp = VertexImporter::default();
73 for input in &self.inputs {
74 match input.semantic {
75 Semantic::Position => imp.position = Some(load(res, input)?),
76 Semantic::Normal => imp.normal = Some(load(res, input)?),
77 Semantic::TexCoord => imp.texcoord = Some(load(res, input)?),
78 _ => unimplemented!(),
79 }
80 }
81 Ok(imp)
82 }
83}
84
85#[derive(Clone, Debug)]
86enum Instruction<'a> {
87 Normal(SourceReader<'a, XYZ>),
88 TexCoord(SourceReader<'a, ST>, Option<u32>),
89 }
91
92#[derive(Clone, Debug, Default)]
95pub struct Importer<'a> {
96 vimp: VertexImporter<'a>,
97 vtx_offset: usize,
98 stride: usize,
99 insts: Vec<(usize, Instruction<'a>)>,
100}
101
102impl<T> Geom<T> {
103 pub fn importer<'a, R: UrlResolver<'a, Source>>(
105 &'a self,
106 res: &R,
107 vimp: VertexImporter<'a>,
108 ) -> Result<Importer<'a>, R::Error> {
109 let mut insts = vec![];
110 let vtx_offset = self
111 .inputs
112 .iter()
113 .find(|p| p.semantic == Semantic::Vertex)
114 .expect("no VERTEX input found")
115 .offset as usize;
116 for i in &*self.inputs {
117 match i.semantic {
118 Semantic::Normal => {
119 insts.push((i.offset as usize, Instruction::Normal(load(res, i)?)))
120 }
121 Semantic::TexCoord => insts.push((
122 i.offset as usize,
123 Instruction::TexCoord(load(res, i)?, i.set),
124 )),
125 _ => {}
126 }
127 }
128 Ok(Importer {
129 vimp,
130 vtx_offset,
131 stride: self.inputs.stride,
132 insts,
133 })
134 }
135}
136
137pub trait VertexLoad<'a, C: ?Sized = ()>: Clone {
142 fn position(ctx: &C, reader: &SourceReader<'a, XYZ>, index: u32) -> Self;
147
148 fn add_normal(&mut self, ctx: &C, reader: &SourceReader<'a, XYZ>, index: u32);
153
154 fn add_texcoord(
159 &mut self,
160 ctx: &C,
161 reader: &SourceReader<'a, ST>,
162 index: u32,
163 set: Option<u32>,
164 );
165}
166
167impl<'a> Importer<'a> {
168 pub fn build_vertex<C: ?Sized, V: VertexLoad<'a, C>>(&self, ctx: &C, data: &[u32]) -> V {
172 let vtx_data = data[self.vtx_offset];
173 let mut vtx = V::position(ctx, self.vimp.position.as_ref().unwrap(), vtx_data);
174 if let Some(ref reader) = self.vimp.normal {
175 vtx.add_normal(ctx, reader, vtx_data)
176 }
177 if let Some(ref reader) = self.vimp.texcoord {
178 vtx.add_texcoord(ctx, reader, vtx_data, None)
179 }
180 for inst in &self.insts {
181 match *inst {
182 (off, Instruction::Normal(ref reader)) => vtx.add_normal(ctx, reader, data[off]),
183 (off, Instruction::TexCoord(ref reader, set)) => {
184 vtx.add_texcoord(ctx, reader, data[off], set)
185 }
186 }
187 }
188 vtx
189 }
190
191 pub fn normal_importer(&self) -> Option<&SourceReader<'a, XYZ>> {
193 let mut importer = self.vimp.normal_importer();
194 for inst in &self.insts {
195 if let Instruction::Normal(imp) = &inst.1 {
196 importer = Some(imp)
197 }
198 }
199 importer
200 }
201
202 pub fn texcoord_importer(&self, set: u32) -> Option<&SourceReader<'a, ST>> {
204 let mut importer = self.vimp.texcoord_importer();
205 for inst in &self.insts {
206 if let Instruction::TexCoord(imp, i) = &inst.1 {
207 if i.map_or(true, |i| i == set) {
208 importer = Some(imp)
209 }
210 }
211 }
212 importer
213 }
214
215 pub fn read<'b, C: ?Sized, V: VertexLoad<'a, C>>(
225 &'b self,
226 ctx: &'b C,
227 array: &'a [u32],
228 ) -> ArrayIter<'a, 'b, C, V> {
229 assert!(self.stride != 0);
230 let len = array.len() / self.stride;
231 assert!(len * self.stride == array.len());
232 ArrayIter {
233 imp: self,
234 ctx,
235 len,
236 array,
237 _mark: PhantomData,
238 }
239 }
240}
241
242#[derive(Clone, Debug)]
244pub struct ArrayIter<'a, 'b, C: ?Sized, V> {
245 imp: &'b Importer<'a>,
246 ctx: &'b C,
247 len: usize,
248 array: &'a [u32],
249 _mark: PhantomData<V>,
250}
251
252impl<'a, 'b, C: ?Sized, V: VertexLoad<'a, C>> ArrayIter<'a, 'b, C, V> {
253 pub fn slice(&self, i: usize) -> &'a [u32] {
257 &self.array[i * self.imp.stride..][..self.imp.stride]
258 }
259
260 pub fn get(&self, i: usize) -> V {
262 self.imp.build_vertex(self.ctx, self.slice(i))
263 }
264
265 pub fn advance_by(&mut self, n: usize) -> Result<(), usize> {
267 if n <= self.len {
268 self.array = &self.array[n * self.imp.stride..];
269 Ok(())
270 } else {
271 Err(self.len)
272 }
273 }
274
275 pub fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
278 if n <= self.len {
279 self.array = &self.array[..self.array.len() - n * self.imp.stride];
280 Ok(())
281 } else {
282 Err(self.len)
283 }
284 }
285}
286
287impl<'a, 'b, C: ?Sized, V: VertexLoad<'a, C>> ExactSizeIterator for ArrayIter<'a, 'b, C, V> {
288 fn len(&self) -> usize {
289 self.len
290 }
291}
292
293impl<'a, 'b, C: ?Sized, V: VertexLoad<'a, C>> DoubleEndedIterator for ArrayIter<'a, 'b, C, V> {
294 fn next_back(&mut self) -> Option<Self::Item> {
295 self.len = self.len.checked_sub(1)?;
296 let (left, right) = self.array.split_at(self.len);
297 self.array = left;
298 Some(self.imp.build_vertex(self.ctx, right))
299 }
300
301 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
302 self.advance_back_by(n).ok()?;
303 self.next_back()
304 }
305}
306
307impl<'a, 'b, C: ?Sized, V: VertexLoad<'a, C>> Iterator for ArrayIter<'a, 'b, C, V> {
308 type Item = V;
309
310 fn next(&mut self) -> Option<Self::Item> {
311 self.len = self.len.checked_sub(1)?;
312 let (left, right) = self.array.split_at(self.imp.stride);
313 self.array = right;
314 Some(self.imp.build_vertex(self.ctx, left))
315 }
316
317 fn size_hint(&self) -> (usize, Option<usize>) {
318 (self.len, Some(self.len))
319 }
320
321 fn count(self) -> usize {
322 self.len
323 }
324
325 fn last(mut self) -> Option<Self::Item> {
326 self.next_back()
327 }
328
329 fn nth(&mut self, n: usize) -> Option<Self::Item> {
330 self.advance_by(n).ok()?;
331 self.next()
332 }
333}