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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
// Copyright (c) 2023 Xu Shaohua <shaohua@biofan.org>. All rights reserved.
// Use of this source is governed by Lesser General Public License that can be found
// in the LICENSE file.
use bitflags::bitflags;
use std::mem::size_of;
use crate::core::color::Color;
use crate::core::point::Point;
use crate::core::rect::Rect;
#[repr(u8)]
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub enum VertexMode {
Triangles,
TriangleStrip,
TriangleFan,
}
#[derive(Debug, Clone, PartialEq)]
pub(crate) struct Desc {
pub mode: VertexMode,
pub vertex_count: i32,
pub index_count: i32,
pub has_tex_coords: bool,
pub has_colors: bool,
}
#[derive(Debug, Clone, PartialEq)]
pub(crate) struct Sizes {
/// size of entire Vertices allocation (obj + arrays)
pub total: usize,
/// size of all the data arrays (V + D + T + C + I)
pub arrays: usize,
pub vex_size: usize,
pub texs_size: usize,
pub color_size: usize,
pub indices_size: usize,
/// For indexed tri-fans this is the number of amount of space fo indices
/// needed in the builder before conversion to indexed triangles
/// (or zero if not indexed or not a triangle fan).
pub builder_tri_fan_indices_size: usize,
}
impl Sizes {
#[allow(clippy::cast_sign_loss)]
#[allow(clippy::cast_lossless)]
pub fn from_desc(desc: &Desc) -> Option<Self> {
// TODO(Shaohua): Check overflow.
let vex_size: usize = desc.vertex_count as usize * size_of::<Point>();
let texs_size: usize = if desc.has_tex_coords {
desc.vertex_count as usize * size_of::<Point>()
} else {
0
};
let color_size: usize = if desc.has_colors {
desc.vertex_count as usize * size_of::<Color>()
} else {
0
};
let mut builder_tri_fan_indices_size: usize = 0;
let mut indices_size: usize = desc.index_count as usize * size_of::<u16>();
if desc.mode == VertexMode::TriangleFan {
let num_fan_tris;
if desc.index_count > 0 {
builder_tri_fan_indices_size = indices_size;
num_fan_tris = desc.index_count - 2;
} else {
num_fan_tris = desc.vertex_count - 2;
// By forcing this to become indexed we are adding a constraint to the maximum
// number of vertices.
if desc.vertex_count > (u16::MAX as i32 + 1) {
return None;
}
}
if num_fan_tris <= 0 {
return None;
}
indices_size = num_fan_tris as usize * (3 * size_of::<u16>());
}
let total = size_of::<Vertices>() + vex_size + texs_size + color_size + indices_size;
// just the sum of the arrays
let arrays = vex_size + texs_size + color_size + indices_size;
Some(Self {
total,
arrays,
vex_size,
texs_size,
color_size,
indices_size,
builder_tri_fan_indices_size,
})
}
#[must_use]
pub const fn is_valid(&self) -> bool {
self.total != 0
}
}
/// An immutable set of vertex data that can be used with `Canvas::draw_vertices()`.
pub struct Vertices {
unique_id: u32,
// these point inside our allocation, so none of these can be "freed"
positions: Vec<Point>, // vertex_count
indices: Vec<u16>, // index_count or empty
texs: Vec<Point>, // vertex_count or empty
colors: Vec<Color>, // vertex_count or empty
// computed to be the union of the positions[]
bounds: Rect,
vertex_count: i32,
index_count: i32,
mode: VertexMode,
}
impl Vertices {
#[must_use]
fn new() -> Self {
unimplemented!()
}
/// Create a vertices by copying the specified arrays.
///
/// texs, colors may be empty.
#[must_use]
pub fn from(
_mode: VertexMode,
_vertex_count: i32,
_points: &[Point],
_texs: &[Point],
_colors: &[Color],
_indices: &[u16],
) -> Self {
unimplemented!()
}
#[must_use]
pub const fn unique_id(&self) -> u32 {
self.unique_id
}
#[must_use]
pub const fn bounds(&self) -> &Rect {
&self.bounds
}
/// returns approximate byte size of the vertices object
#[must_use]
pub const fn approximate_size(&self) -> usize {
unimplemented!()
}
#[must_use]
pub(crate) const fn get_sizes() -> Sizes {
unimplemented!()
}
#[must_use]
pub const fn is_empty(&self) -> bool {
self.vertex_count == 0
}
}
bitflags! {
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub struct BuilderFlags : u8 {
const HasTexCoords = 1 << 0;
const HasColors = 1 << 1;
}
}
pub struct Builder {
/// holds a partially complete object. only completed in detach()
vertices: Vertices,
/// Extra storage for intermediate vertices in the case where the client specifies indexed
/// triangle fans.
///
/// These get converted to indexed triangles when the Builder is finalized.
intermediate_fan_indices: Vec<u8>,
}
impl Builder {
#[must_use]
pub fn new(
_mode: VertexMode,
_vertex_count: i32,
_index_count: i32,
_flags: BuilderFlags,
) -> Self {
unimplemented!()
}
#[must_use]
pub const fn is_valid(&self) -> bool {
!self.vertices.is_empty()
}
pub fn positions(&mut self) -> &mut [Point] {
unimplemented!()
}
/// Returns empty slice if there are no indices
pub fn indices(&mut self) -> &mut [u16] {
unimplemented!()
}
/// Returns empty slice if there are no `tex_coords`
///
/// If we have custom attributes, it will always be empty.
pub fn tex_coords(&mut self) -> &mut [Point] {
unimplemented!()
}
/// Returns empty slice if there are no colors.
///
/// If we have custom attributes, it will always be empty.
pub fn colors(&mut self) -> &mut [Color] {
unimplemented!()
}
/// Detach the built vertices object.
///
/// After the first call, this will always return null.
#[must_use]
#[allow(clippy::missing_const_for_fn)]
pub fn finish(self) -> Vertices {
self.vertices
}
pub(crate) fn from_desc(desc: &Desc) -> Self {
let mut flags = BuilderFlags::empty();
if desc.has_tex_coords {
flags |= BuilderFlags::HasTexCoords;
}
if desc.has_colors {
flags |= BuilderFlags::HasColors;
}
Self::new(desc.mode, desc.vertex_count, desc.index_count, flags)
}
}