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
// SPDX-License-Identifier: ISC
use crate::point::Point3;
use crate::value::GroupValue;
use alloc::vec::Vec;
/// A WIPEOUT entity — an opaque polygonal mask.
///
/// The clip boundary is defined in normalized coordinates relative to the
/// image frame. To convert a clip vertex `(u, v)` to world coordinates:
///
/// ```text
/// world = insertion_point + u_vector * (u + 0.5) + v_vector * (v + 0.5)
/// ```
#[derive(Debug, Clone, Default)]
pub struct Wipeout {
/// Frame insertion point.
pub insertion_point: Point3,
/// U-axis vector defining frame width and direction.
pub u_vector: Point3,
/// V-axis vector defining frame height and direction.
pub v_vector: Point3,
/// Clip boundary type.
///
/// | Value | Meaning |
/// |------:|-------------|
/// | 1 | Rectangular |
/// | 2 | Polygonal |
pub clip_type: i16,
/// Clip boundary vertices in normalized image-space coordinates.
pub clip_vertices: Vec<(f64, f64)>,
/// In-progress clip vertex being accumulated.
current_u: Option<f64>,
}
impl Wipeout {
pub(crate) fn feed(&mut self, code: u16, val: &GroupValue) {
match code {
71 => {
if let Some(v) = val.as_i16() {
self.clip_type = v;
}
}
14 => {
if let Some(u) = val.as_f64() {
self.current_u = Some(u);
}
}
24 => {
if let Some(v) = val.as_f64() {
if let Some(u) = self.current_u.take() {
self.clip_vertices.push((u, v));
}
}
}
_ => {
if let Some(f) = val.as_f64() {
match code {
10 => self.insertion_point.x = f,
20 => self.insertion_point.y = f,
30 => self.insertion_point.z = f,
11 => self.u_vector.x = f,
21 => self.u_vector.y = f,
31 => self.u_vector.z = f,
12 => self.v_vector.x = f,
22 => self.v_vector.y = f,
32 => self.v_vector.z = f,
_ => {}
}
}
}
}
}
}