1use crate::INVALID_INDEX;
4
5use std::io::{Read, Write};
6
7use super::{decode_v_byte, encode_v_byte, read_byte, write_byte, DecodeError, IndexEncodingVersion};
8
9const INDEX_HEADER: u8 = 0xe0;
10
11type VertexFifo = [u32; 16];
12
13const DEFAULT_VERTEX_FIFO: VertexFifo = [INVALID_INDEX; 16];
14
15type EdgeFifo = [[u32; 2]; 16];
16
17const DEFAULT_EDGE_FIFO: EdgeFifo = [[INVALID_INDEX; 2]; 16];
18
19const TRIANGLE_INDEX_ORDER: [[usize; 3]; 3] = [[0, 1, 2], [1, 2, 0], [2, 0, 1]];
20
21const CODE_AUX_ENCODING_TABLE: [u8; 16] = [
22 0x00, 0x76, 0x87, 0x56, 0x67, 0x78, 0xa9, 0x86, 0x65, 0x89, 0x68, 0x98, 0x01, 0x69, 0,
23 0, ];
25
26fn rotate_triangle(b: u32, c: u32, next: u32) -> i32 {
27 if b == next {
28 1
29 } else {
30 if c == next {
31 2
32 } else {
33 0
34 }
35 }
36}
37
38fn get_edge_fifo(fifo: &EdgeFifo, a: u32, b: u32, c: u32, offset: usize) -> i32 {
39 for i in 0..16 {
40 let index = (offset.wrapping_sub(i + 1)) & 15;
41
42 let e0 = fifo[index][0];
43 let e1 = fifo[index][1];
44
45 if e0 == a && e1 == b {
46 return ((i << 2) | 0) as i32;
47 }
48
49 if e0 == b && e1 == c {
50 return ((i << 2) | 1) as i32;
51 }
52
53 if e0 == c && e1 == a {
54 return ((i << 2) | 2) as i32;
55 }
56 }
57
58 -1
59}
60
61#[inline(always)]
62fn push_edge_fifo(fifo: &mut EdgeFifo, a: u32, b: u32, offset: &mut usize) {
63 fifo[*offset][0] = a;
64 fifo[*offset][1] = b;
65 *offset = (*offset + 1) & 15;
66}
67
68fn get_vertex_fifo(fifo: &VertexFifo, v: u32, offset: usize) -> i32 {
69 for i in 0..16 {
70 let index = (offset.wrapping_sub(i + 1)) & 15;
71
72 if fifo[index] == v {
73 return i as i32;
74 }
75 }
76
77 -1
78}
79
80#[inline(always)]
81fn push_vertex_fifo(fifo: &mut VertexFifo, v: u32, offset: &mut usize, cond: Option<bool>) {
82 fifo[*offset] = v;
83 *offset = (*offset + cond.unwrap_or(true) as usize) & 15;
84}
85
86fn encode_index<W: Write>(data: &mut W, index: u32, last: u32) {
87 let d = index.wrapping_sub(last);
88 let v = (d << 1) ^ (((d as i32) >> 31) as u32);
89
90 encode_v_byte(data, v);
91}
92
93fn decode_index<R: Read>(data: &mut R, last: u32) -> u32 {
94 let v = decode_v_byte(data);
95 let d = (v >> 1) ^ (-((v & 1) as i32) as u32);
96
97 last.wrapping_add(d)
98}
99
100fn get_code_aux_index(v: u8, table: &[u8]) -> i32 {
101 table[0..16]
102 .iter()
103 .position(|t| *t == v)
104 .map(|t| t as i32)
105 .unwrap_or(-1)
106}
107
108fn write_triangle<T>(destination: &mut [T], a: u32, b: u32, c: u32)
109where
110 T: Copy + From<u32>,
111{
112 destination.copy_from_slice(&[T::from(a), T::from(b), T::from(c)]);
113}
114
115pub fn encode_index_buffer(mut buffer: &mut [u8], indices: &[u32], version: IndexEncodingVersion) -> Option<usize> {
127 assert!(indices.len() % 3 == 0);
128
129 let buffer_len = buffer.len();
130
131 if buffer_len < 1 + indices.len() / 3 + 16 {
133 return None;
134 }
135
136 let version: u8 = version.into();
137
138 write_byte(&mut buffer, INDEX_HEADER | version);
139
140 let mut edgefifo = DEFAULT_EDGE_FIFO;
141 let mut vertexfifo = DEFAULT_VERTEX_FIFO;
142
143 let mut edgefifooffset = 0;
144 let mut vertexfifooffset = 0;
145
146 let mut next = 0;
147 let mut last = 0;
148
149 let (mut code, mut data) = buffer.split_at_mut(indices.len() / 3);
150
151 let fecmax = if version >= 1 { 13 } else { 15 };
152
153 let codeaux_table = CODE_AUX_ENCODING_TABLE;
156
157 for i in (0..indices.len()).step_by(3) {
158 if data.len() < 16 {
162 return None;
163 }
164
165 let fer = get_edge_fifo(
166 &edgefifo,
167 indices[i + 0],
168 indices[i + 1],
169 indices[i + 2],
170 edgefifooffset,
171 );
172
173 if fer >= 0 && (fer >> 2) < 15 {
174 let order = TRIANGLE_INDEX_ORDER[(fer & 3) as usize];
175
176 let a = indices[i + order[0]];
177 let b = indices[i + order[1]];
178 let c = indices[i + order[2]];
179
180 let fe = fer >> 2;
182 let fc = get_vertex_fifo(&vertexfifo, c, vertexfifooffset);
183
184 let mut fec = if fc >= 1 && fc < fecmax {
185 fc
186 } else {
187 if c == next {
188 next += 1;
189 0
190 } else {
191 15
192 }
193 };
194
195 if fec == 15 && version >= 1 {
196 if c + 1 == last {
198 fec = 13;
199 last = c;
200 }
201 if c == last + 1 {
202 fec = 14;
203 last = c;
204 }
205 }
206
207 write_byte(&mut code, ((fe << 4) | fec) as u8);
208
209 if fec == 15 {
211 encode_index(&mut data, c, last);
212 last = c;
213 }
214
215 if fec == 0 || fec >= fecmax {
217 push_vertex_fifo(&mut vertexfifo, c, &mut vertexfifooffset, None);
218 }
219
220 push_edge_fifo(&mut edgefifo, c, b, &mut edgefifooffset);
222 push_edge_fifo(&mut edgefifo, a, c, &mut edgefifooffset);
223 } else {
224 let rotation = rotate_triangle(indices[i + 1], indices[i + 2], next);
225 let order = TRIANGLE_INDEX_ORDER[rotation as usize];
226
227 let a = indices[i + order[0]];
228 let b = indices[i + order[1]];
229 let c = indices[i + order[2]];
230
231 let mut reset = false;
233
234 if a == 0 && b == 1 && c == 2 && next > 0 && version >= 1 {
235 reset = true;
236 next = 0;
237
238 vertexfifo = DEFAULT_VERTEX_FIFO;
241 }
242
243 let fb = get_vertex_fifo(&vertexfifo, b, vertexfifooffset);
244 let fc = get_vertex_fifo(&vertexfifo, c, vertexfifooffset);
245
246 let fea = if a == next {
248 next += 1;
249 0
250 } else {
251 15
252 };
253 let feb = if fb >= 0 && fb < 14 {
254 fb + 1
255 } else {
256 if b == next {
257 next += 1;
258 0
259 } else {
260 15
261 }
262 };
263 let fec = if fc >= 0 && fc < 14 {
264 fc + 1
265 } else {
266 if c == next {
267 next += 1;
268 0
269 } else {
270 15
271 }
272 };
273
274 let codeaux = ((feb << 4) | fec) as u8;
276 let codeauxindex = get_code_aux_index(codeaux, &codeaux_table);
277
278 if fea == 0 && codeauxindex >= 0 && codeauxindex < 14 && !reset {
280 write_byte(&mut code, ((15 << 4) | codeauxindex) as u8);
281 } else {
282 write_byte(&mut code, ((15 << 4) | 14 | fea) as u8);
283 write_byte(&mut data, codeaux);
284 }
285
286 if fea == 15 {
288 encode_index(&mut data, a, last);
289 last = a;
290 }
291
292 if feb == 15 {
293 encode_index(&mut data, b, last);
294 last = b;
295 }
296
297 if fec == 15 {
298 encode_index(&mut data, c, last);
299 last = c;
300 }
301
302 if fea == 0 || fea == 15 {
304 push_vertex_fifo(&mut vertexfifo, a, &mut vertexfifooffset, None);
305 }
306
307 if feb == 0 || feb == 15 {
308 push_vertex_fifo(&mut vertexfifo, b, &mut vertexfifooffset, None);
309 }
310
311 if fec == 0 || fec == 15 {
312 push_vertex_fifo(&mut vertexfifo, c, &mut vertexfifooffset, None);
313 }
314
315 push_edge_fifo(&mut edgefifo, b, a, &mut edgefifooffset);
317 push_edge_fifo(&mut edgefifo, c, b, &mut edgefifooffset);
318 push_edge_fifo(&mut edgefifo, a, c, &mut edgefifooffset);
319 }
320 }
321
322 if data.len() < 16 {
324 return None;
325 }
326
327 for value in &codeaux_table {
331 assert!((value & 0xf) != 0xf && (value >> 4) != 0xf);
333
334 write_byte(&mut data, *value);
335 }
336
337 assert_eq!(codeaux_table[0], 0);
339
340 Some(buffer_len - data.len())
344}
345
346pub fn encode_index_buffer_bound(index_count: usize, vertex_count: usize) -> usize {
348 assert_eq!(index_count % 3, 0);
349
350 let mut vertex_bits = 1;
352
353 while vertex_bits < 32 && vertex_count > (1 << vertex_bits) {
354 vertex_bits += 1;
355 }
356
357 let vertex_groups = (vertex_bits + 1 + 6) / 7;
359
360 1 + (index_count / 3) * (2 + 3 * vertex_groups) + 16
361}
362
363pub fn decode_index_buffer<T>(destination: &mut [T], buffer: &[u8]) -> Result<(), DecodeError>
372where
373 T: Copy + From<u32>,
374{
375 assert_eq!(destination.len() % 3, 0);
376 if buffer.len() < 1 + destination.len() / 3 + 16 {
380 return Err(DecodeError::UnexpectedEof);
381 }
382
383 if (buffer[0] & 0xf0) != INDEX_HEADER {
384 return Err(DecodeError::InvalidHeader);
385 }
386
387 let version = buffer[0] & 0x0f;
388 if version > 1 {
389 return Err(DecodeError::UnsupportedVersion);
390 }
391
392 let mut edgefifo = DEFAULT_EDGE_FIFO;
393 let mut vertexfifo = DEFAULT_VERTEX_FIFO;
394
395 let mut edgefifooffset: usize = 0;
396 let mut vertexfifooffset: usize = 0;
397
398 let mut next: u32 = 0;
399 let mut last: u32 = 0;
400
401 let fecmax = if version >= 1 { 13 } else { 15 };
402
403 let (mut code, mut data, codeaux_table, data_safe_end) = {
405 let (code, data) = buffer[1..].split_at(destination.len() / 3);
406 let data_safe_end = data.len() - 16;
407 let codeaux_table = &data[data_safe_end..];
408 (code, std::io::Cursor::new(data), codeaux_table, data_safe_end)
409 };
410
411 for dst in destination.chunks_exact_mut(3) {
412 if data.position() > data_safe_end as u64 {
416 return Err(DecodeError::UnexpectedEof);
417 }
418
419 let codetri = read_byte(&mut code) as usize;
420
421 if codetri < 0xf0 {
422 let fe = codetri >> 4;
423
424 let a = edgefifo[(edgefifooffset.wrapping_sub(fe + 1)) & 15][0];
426 let b = edgefifo[(edgefifooffset.wrapping_sub(fe + 1)) & 15][1];
427
428 let fec = codetri & 15;
429
430 if fec < fecmax {
433 let cf = vertexfifo[(vertexfifooffset.wrapping_sub(fec + 1)) & 15];
435 let c = if fec == 0 { next } else { cf };
436
437 let fec0 = fec == 0;
438 next += fec0 as u32;
439
440 write_triangle(dst, a, b, c);
442
443 push_vertex_fifo(&mut vertexfifo, c, &mut vertexfifooffset, Some(fec0));
445
446 push_edge_fifo(&mut edgefifo, c, b, &mut edgefifooffset);
447 push_edge_fifo(&mut edgefifo, a, c, &mut edgefifooffset);
448 } else {
449 let c = if fec != 15 {
452 last.wrapping_add((fec.wrapping_sub(fec ^ 3)) as u32)
453 } else {
454 decode_index(&mut data, last)
455 };
456 last = c;
457
458 write_triangle(dst, a, b, c);
460
461 push_vertex_fifo(&mut vertexfifo, c, &mut vertexfifooffset, None);
463
464 push_edge_fifo(&mut edgefifo, c, b, &mut edgefifooffset);
465 push_edge_fifo(&mut edgefifo, a, c, &mut edgefifooffset);
466 }
467 } else {
468 if codetri < 0xfe {
470 let codeaux = codeaux_table[codetri & 15];
471
472 let feb = codeaux >> 4;
474 let fec = codeaux & 15;
475
476 let a = next;
479 next += 1;
480
481 let bf = vertexfifo[(vertexfifooffset.wrapping_sub(feb as usize)) & 15];
482 let b = if feb == 0 { next } else { bf };
483
484 let feb0 = feb == 0;
485 next += feb0 as u32;
486
487 let cf = vertexfifo[(vertexfifooffset.wrapping_sub(fec as usize)) & 15];
488 let c = if fec == 0 { next } else { cf };
489
490 let fec0 = fec == 0;
491 next += fec0 as u32;
492
493 write_triangle(dst, a, b, c);
495
496 push_vertex_fifo(&mut vertexfifo, a, &mut vertexfifooffset, None);
498 push_vertex_fifo(&mut vertexfifo, b, &mut vertexfifooffset, Some(feb0));
499 push_vertex_fifo(&mut vertexfifo, c, &mut vertexfifooffset, Some(fec0));
500
501 push_edge_fifo(&mut edgefifo, b, a, &mut edgefifooffset);
502 push_edge_fifo(&mut edgefifo, c, b, &mut edgefifooffset);
503 push_edge_fifo(&mut edgefifo, a, c, &mut edgefifooffset);
504 } else {
505 let codeaux = read_byte(&mut data);
507
508 let fea = if codetri == 0xfe { 0 } else { 15 };
509 let feb = codeaux >> 4;
510 let fec = codeaux & 15;
511
512 if codeaux == 0 {
514 next = 0;
515 }
516
517 let mut a = if fea == 0 {
520 let n = next;
521 next += 1;
522 n
523 } else {
524 0
525 };
526 let mut b = if feb == 0 {
527 let n = next;
528 next += 1;
529 n
530 } else {
531 vertexfifo[(vertexfifooffset.wrapping_sub(feb as usize)) & 15]
532 };
533 let mut c = if fec == 0 {
534 let n = next;
535 next += 1;
536 n
537 } else {
538 vertexfifo[(vertexfifooffset.wrapping_sub(fec as usize)) & 15]
539 };
540
541 if fea == 15 {
543 a = decode_index(&mut data, last);
544 last = a;
545 }
546
547 if feb == 15 {
548 b = decode_index(&mut data, last);
549 last = b;
550 }
551
552 if fec == 15 {
553 c = decode_index(&mut data, last);
554 last = c;
555 }
556
557 write_triangle(dst, a, b, c);
559
560 push_vertex_fifo(&mut vertexfifo, a, &mut vertexfifooffset, None);
562 push_vertex_fifo(
563 &mut vertexfifo,
564 b,
565 &mut vertexfifooffset,
566 Some((feb == 0) | (feb == 15)),
567 );
568 push_vertex_fifo(
569 &mut vertexfifo,
570 c,
571 &mut vertexfifooffset,
572 Some((fec == 0) | (fec == 15)),
573 );
574
575 push_edge_fifo(&mut edgefifo, b, a, &mut edgefifooffset);
576 push_edge_fifo(&mut edgefifo, c, b, &mut edgefifooffset);
577 push_edge_fifo(&mut edgefifo, a, c, &mut edgefifooffset);
578 }
579 }
580 }
581
582 if data.position() == data_safe_end as u64 {
583 Ok(())
584 } else {
585 Err(DecodeError::ExtraBytes)
587 }
588}
589
590#[cfg(test)]
591mod test {
592 use super::*;
593
594 const INDEX_BUFFER: [u32; 12] = [0, 1, 2, 2, 1, 3, 4, 6, 5, 7, 8, 9];
598
599 const INDEX_DATA_V0: [u8; 27] = [
600 0xe0, 0xf0, 0x10, 0xfe, 0xff, 0xf0, 0x0c, 0xff, 0x02, 0x02, 0x02, 0x00, 0x76, 0x87, 0x56, 0x67, 0x78, 0xa9,
601 0x86, 0x65, 0x89, 0x68, 0x98, 0x01, 0x69, 0x00, 0x00,
602 ];
603
604 const INDEX_BUFFER_TRICKY: [u32; 15] = [0, 1, 2, 2, 1, 3, 0, 1, 2, 2, 1, 5, 2, 1, 4];
606
607 const INDEX_DATA_V1: [u8; 24] = [
608 0xe1, 0xf0, 0x10, 0xfe, 0x1f, 0x3d, 0x00, 0x0a, 0x00, 0x76, 0x87, 0x56, 0x67, 0x78, 0xa9, 0x86, 0x65, 0x89,
609 0x68, 0x98, 0x01, 0x69, 0x00, 0x00,
610 ];
611
612 #[test]
613 fn test_decode_index_v0() {
614 let mut decoded: [u32; INDEX_BUFFER.len()] = Default::default();
615
616 assert!(decode_index_buffer(&mut decoded, &INDEX_DATA_V0).is_ok());
617 assert_eq!(decoded, INDEX_BUFFER);
618 }
619
620 #[test]
621 fn test_decode_index_v1() {
622 let mut decoded: [u32; INDEX_BUFFER_TRICKY.len()] = Default::default();
623
624 assert!(decode_index_buffer(&mut decoded, &INDEX_DATA_V1).is_ok());
625 assert_eq!(decoded, INDEX_BUFFER_TRICKY);
626 }
627
628 #[test]
629 fn test_decode_index_16() {
630 let buffer = encode_test_index();
631
632 #[derive(Clone, Copy, Default)]
633 struct U16(u16);
634
635 impl From<u32> for U16 {
636 fn from(index: u32) -> Self {
637 Self { 0: index as u16 }
638 }
639 }
640
641 let mut decoded = [U16::default(); INDEX_BUFFER.len()];
642 assert!(decode_index_buffer(&mut decoded, &buffer).is_ok());
643
644 assert!(decoded.iter().enumerate().all(|(i, v)| v.0 as u32 == INDEX_BUFFER[i]));
645 }
646
647 #[test]
648 fn test_encode_index_memory_safe() {
649 let mut buffer = encode_test_index();
650
651 for i in 0..=buffer.len() {
653 let result = encode_index_buffer(&mut buffer[0..i], &INDEX_BUFFER, IndexEncodingVersion::default());
654
655 if i == buffer.len() {
656 assert_eq!(result, Some(buffer.len()));
657 } else {
658 assert_eq!(result, None);
659 }
660 }
661 }
662
663 fn encode_test_index() -> Vec<u8> {
664 let mut buffer = vec![0; encode_index_buffer_bound(INDEX_BUFFER.len(), 10)];
665
666 let written = encode_index_buffer(&mut buffer, &INDEX_BUFFER, IndexEncodingVersion::default()).unwrap();
667 buffer.resize_with(written, Default::default);
668
669 buffer
670 }
671
672 #[test]
673 fn test_decode_index_memory_safe() {
674 let buffer = encode_test_index();
675
676 let mut decoded: [u32; INDEX_BUFFER.len()] = Default::default();
678
679 for i in 0..=buffer.len() {
680 let result = decode_index_buffer(&mut decoded, &buffer[0..i]);
681
682 if i == buffer.len() {
683 assert!(result.is_ok());
684 } else {
685 assert!(result.is_err());
686 }
687 }
688 }
689
690 #[test]
691 fn test_decode_index_reject_extra_bytes() {
692 let mut buffer = encode_test_index();
693
694 buffer.push(0);
696
697 let mut decoded: [u32; INDEX_BUFFER.len()] = Default::default();
698 assert!(decode_index_buffer(&mut decoded, &buffer).is_err());
699 }
700
701 #[test]
702 fn test_decode_index_reject_malformed_headers() {
703 let mut buffer = encode_test_index();
704
705 buffer[0] = 0;
707
708 let mut decoded: [u32; INDEX_BUFFER.len()] = Default::default();
709 assert!(decode_index_buffer(&mut decoded, &buffer).is_err());
710 }
711
712 #[test]
713 fn test_decode_index_reject_invalid_version() {
714 let mut buffer = encode_test_index();
715
716 buffer[0] |= 0x0f;
718
719 let mut decoded: [u32; INDEX_BUFFER.len()] = Default::default();
720 assert!(decode_index_buffer(&mut decoded, &buffer).is_err());
721 }
722
723 #[test]
724 fn test_roundtrip_index_tricky() {
725 let mut buffer = Vec::new();
726 buffer.resize_with(
727 encode_index_buffer_bound(INDEX_BUFFER_TRICKY.len(), 6),
728 Default::default,
729 );
730
731 let written = encode_index_buffer(&mut buffer, &INDEX_BUFFER_TRICKY, IndexEncodingVersion::default()).unwrap();
732 buffer.resize_with(written, Default::default);
733
734 let mut decoded: [u32; INDEX_BUFFER_TRICKY.len()] = Default::default();
735 assert!(decode_index_buffer(&mut decoded, &buffer).is_ok());
736 assert_eq!(decoded, INDEX_BUFFER_TRICKY);
737 }
738
739 #[test]
740 fn test_encode_index_empty() {
741 let mut buffer = Vec::new();
742 buffer.resize_with(encode_index_buffer_bound(0, 0), Default::default);
743
744 let written = encode_index_buffer(&mut buffer, &[], IndexEncodingVersion::default()).unwrap();
745 buffer.resize_with(written, Default::default);
746
747 assert!(decode_index_buffer::<u32>(&mut [], &buffer).is_ok());
748 }
749}