1use crate::color::conv::IntoLinSrgba;
2use crate::draw::mesh::vertex::{self, Point, TexCoords, Vertex};
3use crate::draw::primitive::Primitive;
4use crate::draw::properties::spatial::{orientation, position};
5use crate::draw::properties::{ColorScalar, LinSrgba, SetColor, SetOrientation, SetPosition};
6use crate::draw::{self, Drawing};
7use crate::geom;
8use crate::wgpu;
9use std::ops;
10
11#[derive(Clone, Debug, Default)]
13pub struct Vertexless;
14
15#[derive(Clone, Debug)]
17pub struct Mesh {
18 position: position::Properties,
19 orientation: orientation::Properties,
20 vertex_range: ops::Range<usize>,
21 index_range: ops::Range<usize>,
22 vertex_mode: draw::renderer::VertexMode,
23 fill_color: Option<FillColor>,
24 texture_view: Option<wgpu::TextureView>,
25}
26
27#[derive(Clone, Debug, Default)]
28struct FillColor(Option<LinSrgba>);
29
30struct FlattenIndices<I> {
32 iter: I,
33 index: usize,
34 vertex_start_index: usize,
35 current: [usize; 3],
36}
37
38pub type DrawingMesh<'a> = Drawing<'a, Mesh>;
39
40impl Vertexless {
41 pub fn points_textured<I, P, T>(
48 self,
49 inner_mesh: &mut draw::Mesh,
50 texture_view: &dyn wgpu::ToTextureView,
51 points: I,
52 ) -> Mesh
53 where
54 I: IntoIterator<Item = (P, T)>,
55 P: Into<Point>,
56 T: Into<TexCoords>,
57 {
58 let points = points.into_iter().map(|(p, t)| {
59 let point = p.into();
60 let color = vertex::DEFAULT_VERTEX_COLOR;
61 let tex_coords = t.into();
62 ((point, color), tex_coords).into()
63 });
64 let vertex_mode = draw::renderer::VertexMode::Texture;
65 self.points_inner(
66 inner_mesh,
67 points,
68 vertex_mode,
69 Some(texture_view.to_texture_view()),
70 )
71 }
72
73 pub fn points_colored<I, P, C>(self, inner_mesh: &mut draw::Mesh, points: I) -> Mesh
79 where
80 I: IntoIterator<Item = (P, C)>,
81 P: Into<Point>,
82 C: IntoLinSrgba<ColorScalar>,
83 {
84 let vertices = points.into_iter().map(|(p, c)| {
85 let point = p.into();
86 let color = c.into_lin_srgba();
87 let tex_coords = vertex::default_tex_coords();
88 ((point, color), tex_coords).into()
89 });
90 let vertex_mode = draw::renderer::VertexMode::Color;
91 self.points_inner(inner_mesh, vertices, vertex_mode, None)
92 }
93
94 pub fn points<I>(self, inner_mesh: &mut draw::Mesh, points: I) -> Mesh
102 where
103 I: IntoIterator,
104 I::Item: Into<Point>,
105 {
106 let vertices = points.into_iter().map(|p| {
107 let point = p.into();
108 let color = vertex::DEFAULT_VERTEX_COLOR;
109 let tex_coords = vertex::default_tex_coords();
110 ((point, color), tex_coords).into()
111 });
112 let vertex_mode = draw::renderer::VertexMode::Color;
113 let mut mesh = self.points_inner(inner_mesh, vertices, vertex_mode, None);
114 mesh.fill_color = Some(FillColor(None));
115 mesh
116 }
117
118 fn points_inner<I>(
119 self,
120 inner_mesh: &mut draw::Mesh,
121 vertices: I,
122 vertex_mode: draw::renderer::VertexMode,
123 texture_view: Option<wgpu::TextureView>,
124 ) -> Mesh
125 where
126 I: Iterator<Item = Vertex>,
127 {
128 let v_start = inner_mesh.points().len();
129 let i_start = inner_mesh.indices().len();
130 for (i, vertex) in vertices.enumerate() {
131 inner_mesh.push_vertex(vertex);
132 inner_mesh.push_index((v_start + i) as u32);
133 }
134 let v_end = inner_mesh.points().len();
135 let i_end = inner_mesh.indices().len();
136 Mesh::new(v_start..v_end, i_start..i_end, vertex_mode, texture_view)
137 }
138
139 pub fn tris_textured<I, P, T>(
146 self,
147 inner_mesh: &mut draw::Mesh,
148 texture_view: &dyn wgpu::ToTextureView,
149 tris: I,
150 ) -> Mesh
151 where
152 I: IntoIterator<Item = geom::Tri<(P, T)>>,
153 P: Into<Point>,
154 T: Into<TexCoords>,
155 {
156 let points = tris
157 .into_iter()
158 .map(|t| t.map_vertices(|(p, t)| (p.into(), t.into())))
159 .flat_map(geom::Tri::vertices);
160 self.points_textured(inner_mesh, texture_view, points)
161 }
162
163 pub fn tris_colored<I, P, C>(self, inner_mesh: &mut draw::Mesh, tris: I) -> Mesh
169 where
170 I: IntoIterator<Item = geom::Tri<(P, C)>>,
171 P: Into<Point>,
172 C: IntoLinSrgba<ColorScalar>,
173 {
174 let points = tris
175 .into_iter()
176 .map(|t| t.map_vertices(|(p, c)| (p.into(), c.into_lin_srgba())))
177 .flat_map(geom::Tri::vertices);
178 self.points_colored(inner_mesh, points)
179 }
180
181 pub fn tris<I, V>(self, inner_mesh: &mut draw::Mesh, tris: I) -> Mesh
190 where
191 I: IntoIterator<Item = geom::Tri<V>>,
192 V: Into<Point>,
193 {
194 let points = tris
195 .into_iter()
196 .map(|t| t.map_vertices(Into::into))
197 .flat_map(geom::Tri::vertices);
198 self.points(inner_mesh, points)
199 }
200
201 pub fn indexed_textured<V, I, P, T>(
210 self,
211 inner_mesh: &mut draw::Mesh,
212 texture_view: &dyn wgpu::ToTextureView,
213 points: V,
214 indices: I,
215 ) -> Mesh
216 where
217 V: IntoIterator<Item = (P, T)>,
218 I: IntoIterator<Item = usize>,
219 P: Into<Point>,
220 T: Into<TexCoords>,
221 {
222 let vertices = points.into_iter().map(|(p, t)| {
223 let point = p.into();
224 let color = vertex::DEFAULT_VERTEX_COLOR;
225 let tex_coords = t.into();
226 ((point, color), tex_coords).into()
227 });
228 let vertex_mode = draw::renderer::VertexMode::Texture;
229 self.indexed_inner(
230 inner_mesh,
231 vertices,
232 indices,
233 vertex_mode,
234 Some(texture_view.to_texture_view()),
235 )
236 }
237
238 pub fn indexed_colored<V, I, P, C>(
246 self,
247 inner_mesh: &mut draw::Mesh,
248 points: V,
249 indices: I,
250 ) -> Mesh
251 where
252 V: IntoIterator<Item = (P, C)>,
253 I: IntoIterator<Item = usize>,
254 P: Into<Point>,
255 C: IntoLinSrgba<ColorScalar>,
256 {
257 let vertices = points.into_iter().map(|(p, c)| {
258 let point = p.into();
259 let color = c.into_lin_srgba();
260 let tex_coords = vertex::default_tex_coords();
261 ((point, color), tex_coords).into()
262 });
263 let vertex_mode = draw::renderer::VertexMode::Color;
264 self.indexed_inner(inner_mesh, vertices, indices, vertex_mode, None)
265 }
266
267 pub fn indexed<V, I>(self, inner_mesh: &mut draw::Mesh, points: V, indices: I) -> Mesh
273 where
274 V: IntoIterator,
275 V::Item: Into<Point>,
276 I: IntoIterator<Item = usize>,
277 {
278 let vertices = points.into_iter().map(|p| {
279 let point = p.into();
280 let color = vertex::DEFAULT_VERTEX_COLOR;
281 let tex_coords = vertex::default_tex_coords();
282 ((point, color), tex_coords).into()
283 });
284 let vertex_mode = draw::renderer::VertexMode::Color;
285 let mut mesh = self.indexed_inner(inner_mesh, vertices, indices, vertex_mode, None);
286 mesh.fill_color = Some(FillColor(None));
287 mesh
288 }
289
290 fn indexed_inner<V, I>(
291 self,
292 inner_mesh: &mut draw::Mesh,
293 vertices: V,
294 indices: I,
295 vertex_mode: draw::renderer::VertexMode,
296 texture_view: Option<wgpu::TextureView>,
297 ) -> Mesh
298 where
299 V: IntoIterator<Item = Vertex>,
300 I: IntoIterator<Item = usize>,
301 {
302 let v_start = inner_mesh.points().len();
303 let i_start = inner_mesh.indices().len();
304 inner_mesh.extend_vertices(vertices);
305 inner_mesh.extend_indices(indices.into_iter().map(|ix| ix as u32));
306 let v_end = inner_mesh.points().len();
307 let i_end = inner_mesh.indices().len();
308 Mesh::new(v_start..v_end, i_start..i_end, vertex_mode, texture_view)
309 }
310}
311
312impl Mesh {
313 fn new(
315 vertex_range: ops::Range<usize>,
316 index_range: ops::Range<usize>,
317 vertex_mode: draw::renderer::VertexMode,
318 texture_view: Option<wgpu::TextureView>,
319 ) -> Self {
320 let orientation = Default::default();
321 let position = Default::default();
322 let fill_color = None;
323 Mesh {
324 orientation,
325 position,
326 vertex_range,
327 index_range,
328 vertex_mode,
329 fill_color,
330 texture_view,
331 }
332 }
333}
334
335impl<'a> Drawing<'a, Vertexless> {
336 pub fn points<I>(self, points: I) -> DrawingMesh<'a>
344 where
345 I: IntoIterator,
346 I::Item: Into<Point>,
347 {
348 self.map_ty_with_context(|ty, ctxt| ty.points(ctxt.mesh, points))
349 }
350
351 pub fn points_colored<I, P, C>(self, points: I) -> DrawingMesh<'a>
357 where
358 I: IntoIterator<Item = (P, C)>,
359 P: Into<Point>,
360 C: IntoLinSrgba<ColorScalar>,
361 {
362 self.map_ty_with_context(|ty, ctxt| ty.points_colored(ctxt.mesh, points))
363 }
364
365 pub fn points_textured<I, P, T>(
372 self,
373 view: &dyn wgpu::ToTextureView,
374 points: I,
375 ) -> DrawingMesh<'a>
376 where
377 I: IntoIterator<Item = (P, T)>,
378 P: Into<Point>,
379 T: Into<TexCoords>,
380 {
381 self.map_ty_with_context(|ty, ctxt| ty.points_textured(ctxt.mesh, view, points))
382 }
383
384 pub fn tris<I, V>(self, tris: I) -> DrawingMesh<'a>
393 where
394 I: IntoIterator<Item = geom::Tri<V>>,
395 V: Into<Point>,
396 {
397 self.map_ty_with_context(|ty, ctxt| ty.tris(ctxt.mesh, tris))
398 }
399
400 pub fn tris_colored<I, P, C>(self, tris: I) -> DrawingMesh<'a>
406 where
407 I: IntoIterator<Item = geom::Tri<(P, C)>>,
408 P: Into<Point>,
409 C: IntoLinSrgba<ColorScalar>,
410 {
411 self.map_ty_with_context(|ty, ctxt| ty.tris_colored(ctxt.mesh, tris))
412 }
413
414 pub fn tris_textured<I, P, T>(self, view: &dyn wgpu::ToTextureView, tris: I) -> DrawingMesh<'a>
421 where
422 I: IntoIterator<Item = geom::Tri<(P, T)>>,
423 P: Into<Point>,
424 T: Into<TexCoords>,
425 {
426 self.map_ty_with_context(|ty, ctxt| ty.tris_textured(ctxt.mesh, view, tris))
427 }
428
429 pub fn indexed<V, I>(self, points: V, indices: I) -> DrawingMesh<'a>
435 where
436 V: IntoIterator,
437 V::Item: Into<Point>,
438 I: IntoIterator<Item = usize>,
439 {
440 self.map_ty_with_context(|ty, ctxt| ty.indexed(ctxt.mesh, points, indices))
441 }
442
443 pub fn indexed_colored<V, I, P, C>(self, points: V, indices: I) -> DrawingMesh<'a>
451 where
452 V: IntoIterator<Item = (P, C)>,
453 I: IntoIterator<Item = usize>,
454 P: Into<Point>,
455 C: IntoLinSrgba<ColorScalar>,
456 {
457 self.map_ty_with_context(|ty, ctxt| ty.indexed_colored(ctxt.mesh, points, indices))
458 }
459
460 pub fn indexed_textured<V, I, P, T>(
469 self,
470 view: &dyn wgpu::ToTextureView,
471 points: V,
472 indices: I,
473 ) -> DrawingMesh<'a>
474 where
475 V: IntoIterator<Item = (P, T)>,
476 I: IntoIterator<Item = usize>,
477 P: Into<Point>,
478 T: Into<TexCoords>,
479 {
480 self.map_ty_with_context(|ty, ctxt| ty.indexed_textured(ctxt.mesh, view, points, indices))
481 }
482}
483
484impl draw::renderer::RenderPrimitive for Mesh {
485 fn render_primitive(
486 self,
487 ctxt: draw::renderer::RenderContext,
488 mesh: &mut draw::Mesh,
489 ) -> draw::renderer::PrimitiveRender {
490 let Mesh {
491 orientation,
492 position,
493 vertex_range,
494 index_range,
495 vertex_mode,
496 fill_color,
497 texture_view,
498 } = self;
499
500 let global_transform = *ctxt.transform;
502 let local_transform = position.transform() * orientation.transform();
503 let transform = global_transform * local_transform;
504
505 let old_mesh_vertex_start = vertex_range.start as u32;
507 let new_mesh_vertex_start = mesh.raw_vertex_count() as u32;
508 let indices = index_range
509 .map(|i| ctxt.intermediary_mesh.indices()[i])
510 .map(|i| new_mesh_vertex_start + i - old_mesh_vertex_start);
511
512 let transform_point = |p: geom::Point3| -> geom::Point3 { transform.transform_point3(p) };
514
515 match fill_color {
517 Some(fill) => {
518 let theme_prim = draw::theme::Primitive::Mesh;
519 let color = fill
520 .0
521 .unwrap_or_else(|| ctxt.theme.fill_lin_srgba(&theme_prim));
522 let vertices = vertex_range.map(|i| {
523 let point = transform_point(ctxt.intermediary_mesh.points()[i]);
524 let tex_coords = ctxt.intermediary_mesh.tex_coords()[i];
525 ((point, color), tex_coords).into()
526 });
527 mesh.extend(vertices, indices);
528 }
529 None => {
530 let vertices = vertex_range.map(|i| {
531 let point = transform_point(ctxt.intermediary_mesh.points()[i]);
532 let color = ctxt.intermediary_mesh.colors()[i];
533 let tex_coords = ctxt.intermediary_mesh.tex_coords()[i];
534 ((point, color), tex_coords).into()
535 });
536 mesh.extend(vertices, indices);
537 }
538 }
539
540 draw::renderer::PrimitiveRender {
541 texture_view,
542 vertex_mode,
543 }
544 }
545}
546
547impl<I> Iterator for FlattenIndices<I>
548where
549 I: Iterator<Item = [usize; 3]>,
550{
551 type Item = usize;
552 fn next(&mut self) -> Option<Self::Item> {
553 loop {
554 if self.index < self.current.len() {
555 let ix = self.current[self.index];
556 self.index += 1;
557 return Some(self.vertex_start_index + ix);
558 }
559 match self.iter.next() {
560 None => return None,
561 Some(trio) => {
562 self.current = trio;
563 self.index = 0;
564 }
565 }
566 }
567 }
568}
569
570impl SetOrientation for Mesh {
571 fn properties(&mut self) -> &mut orientation::Properties {
572 SetOrientation::properties(&mut self.orientation)
573 }
574}
575
576impl SetPosition for Mesh {
577 fn properties(&mut self) -> &mut position::Properties {
578 SetPosition::properties(&mut self.position)
579 }
580}
581
582impl SetColor<ColorScalar> for Mesh {
583 fn rgba_mut(&mut self) -> &mut Option<LinSrgba> {
584 &mut self.fill_color.get_or_insert_with(Default::default).0
585 }
586}
587
588impl From<Vertexless> for Primitive {
589 fn from(prim: Vertexless) -> Self {
590 Primitive::MeshVertexless(prim)
591 }
592}
593
594impl From<Mesh> for Primitive {
595 fn from(prim: Mesh) -> Self {
596 Primitive::Mesh(prim)
597 }
598}
599
600impl Into<Option<Vertexless>> for Primitive {
601 fn into(self) -> Option<Vertexless> {
602 match self {
603 Primitive::MeshVertexless(prim) => Some(prim),
604 _ => None,
605 }
606 }
607}
608
609impl Into<Option<Mesh>> for Primitive {
610 fn into(self) -> Option<Mesh> {
611 match self {
612 Primitive::Mesh(prim) => Some(prim),
613 _ => None,
614 }
615 }
616}