1use derive_more::From;
2use glium::{self, uniform};
3use strum::{EnumCount, EnumIter, FromRepr};
4use vec_map::VecMap;
5
6use math_utils as math;
7
8use crate::{color, mesh, render, shader, vertex, Mesh, Render};
9
10pub const MESH_GRID_DIMS : u16 = 12;
11pub const DEFAULT_PIXELS_PER_UNIT : f32 = 64.0;
13
14pub struct Draw3d {
20 instance_vertices : glium::VertexBuffer <vertex::Vert3dOrientationScaleColor>,
23
24 instanced_aabb_lines : std::ops::Range <u32>,
27 instanced_aabb_triangles : std::ops::Range <u32>,
29 instanced_billboards : VecMap <InstancedBillboard>,
30 instanced_meshes : InstancedMeshes,
31 pub user_buffers : VecMap <glium::VertexBuffer <vertex::Vert3dColor>>,
32 pub user_draw : VecMap <UserDraw>,
33}
34
35#[derive(Clone, Debug, Eq, PartialEq)]
36pub struct UserDraw {
37 pub buffer_key : UserBufferKey,
38 pub range : std::ops::Range <u32>,
40 pub primitive_type : glium::index::PrimitiveType,
41 pub shader_program_id : shader::ProgramId,
42 pub draw_pass : DrawPass
43}
44
45#[derive(Clone, Copy, Debug, Eq, PartialEq)]
46pub struct UserBufferKey (pub u32);
47
48#[derive(Clone, Copy, Debug, Eq, PartialEq)]
49pub enum DrawPass {
50 Depth,
51 NoDepth
52}
53
54#[derive(Clone, Debug, Eq, PartialEq)]
56pub struct InstancedMesh {
57 pub line_indices_range : std::ops::Range <u32>,
61 pub instances_range : std::ops::Range <u32>,
64 pub shader_program_id : shader::ProgramId,
65 pub draw_pass : DrawPass
66}
67
68pub struct InstancedBillboard {
70 pub texture : glium::Texture2d,
71 pub instances_range : std::ops::Range <u32>
73}
74
75#[derive(Default)]
77pub struct InstancesInit <'a> {
78 pub aabb_lines : Option <&'a [vertex::Vert3dOrientationScaleColor]>,
79 pub aabb_triangles : Option <&'a [vertex::Vert3dOrientationScaleColor]>,
80 pub aabb_lines_and_triangles :
81 Option <&'a [vertex::Vert3dOrientationScaleColor]>,
82 pub meshes : VecMap <&'a [vertex::Vert3dOrientationScaleColor]>,
83 pub billboards : VecMap <&'a [vertex::Vert3dOrientationScaleColor]>
84}
85
86#[derive(Clone, Copy, Debug, Eq, PartialEq, From)]
87pub struct MeshKey (pub u32);
88
89#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, EnumCount, EnumIter,
90 FromRepr)]
91#[repr(u16)]
92pub enum MeshId {
93 Grid,
94 Hemisphere,
95 Sphere,
96 Capsule,
97 Cylinder
98}
99
100struct InstancedMeshes {
105 pub vertices : glium::VertexBuffer <vertex::Vert3dInstanced>,
110 pub line_indices : glium::IndexBuffer <u32>,
116 pub meshes : VecMap <InstancedMesh>,
119 pub capsule_vertex_id_offset : u32,
121 pub hemisphere_vertex_count : u32
122}
123
124struct InstancedMeshInit {
125 pub instanced_vertex_data : Vec <vertex::Vert3dInstanced>,
126 pub instanced_line_index_data : Vec <u32>,
127 pub line_indices_ranges : VecMap <std::ops::Range <u32>>,
128 pub shader_program_ids : VecMap <shader::ProgramId>,
129 pub draw_passes : VecMap <DrawPass>,
130 pub capsule_vertex_id_offset : u32,
131 pub hemisphere_vertex_count : u32
132}
133
134impl Draw3d {
139 pub fn new (glium_display : &glium::Display <glutin::surface::WindowSurface>)
140 -> Self
141 {
142 let instanced_aabb_lines = 0..0; let instanced_aabb_triangles = 0..0; let instanced_billboards = VecMap::new();
145 let instanced_meshes = InstancedMeshes::new (glium_display, vec![]);
146 let instance_vertices = glium::VertexBuffer::dynamic (
147 glium_display,
148 &[ vertex::Vert3dOrientationScaleColor {
150 position: [0.0, 0.0, 0.0],
151 orientation: math::Matrix3::identity().into_col_arrays(),
152 scale: [1.0, 1.0, 1.0],
153 color: color::rgba_u8_to_rgba_f32 (color::DEBUG_CHARTREUSE)
154 }
155 ]
156 ).unwrap();
157 let user_buffers = VecMap::new();
158 let user_draw = VecMap::new();
159 Draw3d {
160 instance_vertices,
161 instanced_aabb_lines,
162 instanced_aabb_triangles,
163 instanced_billboards,
164 instanced_meshes,
165 user_buffers,
166 user_draw
167 }
168 }
169
170 pub fn draw (
171 render : &Render <render::resource::Default>,
172 glium_frame : &mut glium::Frame
173 ) {
174 let draw3d = &render.resource.draw3d;
175 for (_, viewport) in render.viewports.iter() {
177 if let Some (camera3d) = viewport.camera3d() {
178 use glium::Surface;
179 let draw_parameters_viewport = viewport.draw_parameters();
181 let draw_parameters_write_depth = glium::DrawParameters {
183 depth: glium::Depth {
184 test: glium::DepthTest::IfLess,
185 write: true,
186 .. glium::Depth::default()
187 },
188 .. draw_parameters_viewport.clone()
189 };
190 let draw_parameters_polygon_offset = glium::DrawParameters {
192 polygon_offset: glium::draw_parameters::PolygonOffset {
193 factor: 1.0,
194 units: 1.0 / 1024.0,
195 fill: true,
196 .. Default::default()
197 },
198 backface_culling:
199 glium::draw_parameters::BackfaceCullingMode::CullCounterClockwise,
200 .. draw_parameters_write_depth.clone()
201 };
202 let (transform_mat_world_to_view, projection_mat_perspective) =
204 camera3d.view_mats();
205 let uniforms = uniform!{
206 uni_transform_mat_view: transform_mat_world_to_view,
207 uni_projection_mat_perspective: projection_mat_perspective,
208 uni_pixels_per_unit: DEFAULT_PIXELS_PER_UNIT,
210 uni_capsule_vertex_id_offset:
211 draw3d.instanced_meshes.capsule_vertex_id_offset,
212 uni_hemisphere_vertex_count:
213 draw3d.instanced_meshes.hemisphere_vertex_count,
214 uni_color: color::rgba_u8_to_rgba_f32 (color::BLACK)
215 };
216
217 if !draw3d.instanced_aabb_lines.is_empty() {
219 let instances_range =
220 draw3d.instanced_aabb_lines.start as usize..
221 draw3d.instanced_aabb_lines.end as usize;
222 glium_frame.draw (
223 draw3d.instance_vertices.slice (instances_range).unwrap(),
224 glium::index::IndicesSource::NoIndices {
225 primitives: glium::index::PrimitiveType::Points
226 },
227 &render.resource.shader_programs [
228 shader::ProgramId::WorldSpace3dAabbLines as usize
229 ],
230 &uniforms,
231 &draw_parameters_write_depth
232 ).unwrap();
233 }
234
235 if !draw3d.instanced_aabb_triangles.is_empty() {
237 let instances_range =
238 draw3d.instanced_aabb_triangles.start as usize..
239 draw3d.instanced_aabb_triangles.end as usize;
240 glium_frame.draw (
241 draw3d.instance_vertices.slice (instances_range).unwrap(),
242 glium::index::IndicesSource::NoIndices {
243 primitives: glium::index::PrimitiveType::Points
244 },
245 &render.resource.shader_programs [
246 shader::ProgramId::WorldSpace3dAabbTriangles as usize
247 ],
248 &uniforms,
249 &draw_parameters_polygon_offset
250 ).unwrap();
251 }
252
253 for (_mesh_key, instanced_mesh) in draw3d.instanced_meshes.meshes.iter() {
255 if instanced_mesh.draw_pass != DrawPass::Depth {
256 continue
257 }
258 if !instanced_mesh.instances_range.is_empty() {
259 let (line_indices_range, instances_range) = (
260 instanced_mesh.line_indices_range.start as usize..
261 instanced_mesh.line_indices_range.end as usize,
262 instanced_mesh.instances_range.start as usize..
263 instanced_mesh.instances_range.end as usize
264 );
265 glium_frame.draw (
266 (&draw3d.instanced_meshes.vertices,
267 draw3d.instance_vertices.slice (instances_range).unwrap()
268 .per_instance().unwrap()
269 ),
270 draw3d.instanced_meshes.line_indices.slice (line_indices_range)
271 .unwrap(),
272 &render.resource.shader_programs [instanced_mesh.shader_program_id
273 as usize],
274 &uniforms,
275 &draw_parameters_write_depth
276 ).unwrap();
277 }
278 }
279
280 for user_draw in draw3d.user_draw.values() {
282 if user_draw.draw_pass != DrawPass::Depth {
283 continue
284 }
285 let vertex_buffer = draw3d.user_buffers
286 .get (user_draw.buffer_key.index()).unwrap();
287 let vertex_range =
288 user_draw.range.start as usize..
289 user_draw.range.end as usize;
290 let uniforms = uniform!{
291 uni_transform_mat_view: transform_mat_world_to_view,
292 uni_projection_mat_perspective: projection_mat_perspective,
293 uni_pixels_per_unit: DEFAULT_PIXELS_PER_UNIT,
295 uni_capsule_vertex_id_offset:
296 draw3d.instanced_meshes.capsule_vertex_id_offset,
297 uni_hemisphere_vertex_count:
298 draw3d.instanced_meshes.hemisphere_vertex_count
299 };
300 glium_frame.draw (
301 vertex_buffer.slice (vertex_range).unwrap(),
302 glium::index::NoIndices (user_draw.primitive_type),
303 &render.resource.shader_programs [user_draw.shader_program_id.index()],
304 &uniforms,
305 &draw_parameters_write_depth
306 ).unwrap();
307 }
308
309 for (_mesh_key, instanced_mesh) in draw3d.instanced_meshes.meshes.iter() {
311 if instanced_mesh.draw_pass != DrawPass::NoDepth {
312 continue
313 }
314 if !instanced_mesh.instances_range.is_empty() {
315 let (line_indices_range, instances_range) = (
316 instanced_mesh.line_indices_range.start as usize..
317 instanced_mesh.line_indices_range.end as usize,
318 instanced_mesh.instances_range.start as usize..
319 instanced_mesh.instances_range.end as usize
320 );
321 glium_frame.draw (
322 (&draw3d.instanced_meshes.vertices,
323 draw3d.instance_vertices.slice (instances_range).unwrap()
324 .per_instance().unwrap()
325 ),
326 draw3d.instanced_meshes.line_indices.slice (line_indices_range)
327 .unwrap(),
328 &render.resource.shader_programs [instanced_mesh.shader_program_id
329 as usize],
330 &uniforms,
331 &draw_parameters_viewport
332 ).unwrap();
333 }
334 }
335
336 for user_draw in draw3d.user_draw.values() {
338 if user_draw.draw_pass != DrawPass::NoDepth {
339 continue
340 }
341 let vertex_buffer = draw3d.user_buffers
342 .get (user_draw.buffer_key.index()).unwrap();
343 let vertex_range =
344 user_draw.range.start as usize..
345 user_draw.range.end as usize;
346 glium_frame.draw (
347 vertex_buffer.slice (vertex_range).unwrap(),
348 glium::index::NoIndices (user_draw.primitive_type),
349 &render.resource.shader_programs [user_draw.shader_program_id.index()],
350 &uniforms,
351 &draw_parameters_viewport
352 ).unwrap();
353 }
354
355 for (_, instanced_billboard) in draw3d.instanced_billboards.iter() {
358 let instances_range =
359 instanced_billboard.instances_range.start as usize..
360 instanced_billboard.instances_range.end as usize;
361 let uniforms = uniform!{
362 uni_transform_mat_view: transform_mat_world_to_view,
363 uni_projection_mat_perspective: projection_mat_perspective,
364 uni_sampler2d: instanced_billboard.texture.sampled()
365 .magnify_filter (glium::uniforms::MagnifySamplerFilter::Nearest),
366 uni_pixels_per_unit: DEFAULT_PIXELS_PER_UNIT
368 };
369 glium_frame.draw (
370 draw3d.instance_vertices.slice (instances_range).unwrap(),
371 glium::index::IndicesSource::NoIndices {
372 primitives: glium::index::PrimitiveType::Points
373 },
374 &render.resource.shader_programs [
375 shader::ProgramId::WorldSpace3dSprite as usize
376 ],
377 &uniforms,
378 &draw_parameters_viewport
379 ).unwrap();
380 }
381 }
382 } } #[inline]
386 pub fn instance_vertices (&self)
387 -> &glium::VertexBuffer <vertex::Vert3dOrientationScaleColor>
388 {
389 &self.instance_vertices
390 }
391
392 #[inline]
393 pub fn instanced_aabb_lines (&self) -> &std::ops::Range <u32> {
394 &self.instanced_aabb_lines
395 }
396
397 #[inline]
398 pub fn set_instanced_aabb_lines (&mut self, range : std::ops::Range <u32>) {
399 debug_assert!(range.end <= self.instance_vertices.len() as u32);
400 self.instanced_aabb_lines = range;
401 }
402
403 #[inline]
404 pub fn instanced_aabb_triangles (&self) -> &std::ops::Range <u32> {
405 &self.instanced_aabb_triangles
406 }
407
408 #[inline]
409 pub fn set_instanced_aabb_triangles (&mut self, range : std::ops::Range <u32>) {
410 debug_assert!(range.end <= self.instance_vertices.len() as u32);
411 self.instanced_aabb_triangles = range;
412 }
413
414 #[inline]
415 pub fn instanced_meshes (&self) -> &VecMap <InstancedMesh> {
416 &self.instanced_meshes.meshes
417 }
418
419 #[inline]
420 pub fn set_instanced_mesh (&mut self,
421 mesh_key : MeshKey, mesh : InstancedMesh
422 ) {
423 let _ = self.instanced_meshes.meshes.insert (mesh_key.index(), mesh);
424 }
425
426 pub fn rebuild_instanced_meshes (&mut self,
430 glium_display : &glium::Display <glutin::surface::WindowSurface>,
431 user_meshes : Vec <(MeshKey, Mesh, DrawPass)>
432 ) {
433 self.instanced_meshes = InstancedMeshes::new (glium_display, user_meshes);
434 }
435
436 pub fn instance_vertices_set (&mut self,
440 glium_display : &glium::Display <glutin::surface::WindowSurface>,
441 instances_init : InstancesInit
442 ) {
443 let mut instance_vertices =
444 Vec::with_capacity (instances_init.instance_count());
445
446 self.instanced_aabb_lines = 0..0;
447 self.instanced_aabb_triangles = 0..0;
448 for mesh in self.instanced_meshes.meshes.values_mut() {
449 mesh.instances_range = 0..0;
450 }
451 if let Some (instances) = instances_init.aabb_lines {
455 let start = instance_vertices.len() as u32;
457 instance_vertices.extend_from_slice (instances);
458 let end = instance_vertices.len() as u32;
459 self.instanced_aabb_lines = start..end;
460 }
461 if let Some (instances) = instances_init.aabb_lines_and_triangles {
462 let start = instance_vertices.len() as u32;
464 instance_vertices.extend_from_slice (instances);
465 let end = instance_vertices.len() as u32;
466 if self.instanced_aabb_lines.end != 0 {
467 debug_assert!(instances_init.aabb_lines.is_none());
468 self.instanced_aabb_lines.start = start;
469 }
470 self.instanced_aabb_lines.end = end;
471 self.instanced_aabb_triangles = start..end;
472 }
473 if let Some (instances) = instances_init.aabb_triangles {
474 let start = instance_vertices.len() as u32;
476 instance_vertices.extend_from_slice (instances);
477 let end = instance_vertices.len() as u32;
478 if self.instanced_aabb_triangles.end == 0 {
479 debug_assert!(instances_init.aabb_lines_and_triangles.is_none());
480 self.instanced_aabb_triangles.start = start;
481 }
482 self.instanced_aabb_triangles.end = end;
483 }
484
485 for (mesh_key, instances) in instances_init.meshes.into_iter() {
487 let start = instance_vertices.len() as u32;
488 instance_vertices.extend_from_slice (instances);
489 let end = instance_vertices.len() as u32;
490 self.instanced_meshes.meshes[mesh_key].instances_range = start..end;
491 }
492
493 for (billboard_key, instances) in instances_init.billboards.into_iter() {
495 let start = instance_vertices.len() as u32;
496 instance_vertices.extend_from_slice (instances);
497 let end = instance_vertices.len() as u32;
498 self.instanced_billboards[billboard_key].instances_range = start..end;
499 }
500
501 self.instance_vertices = glium::VertexBuffer::dynamic (
503 glium_display, instance_vertices.as_slice()
504 ).unwrap();
505 }
506
507 #[inline]
508 pub fn instance_vertices_aabb_lines_write (&self,
509 vertex_data : &[vertex::Vert3dOrientationScaleColor]
510 ) {
511 let range =
512 self.instanced_aabb_lines.start as usize..
513 self.instanced_aabb_lines.end as usize;
514 self.instance_vertices.slice (range).unwrap().write (vertex_data);
515 }
516
517 #[inline]
518 pub fn instance_vertices_aabb_triangles_write (&self,
519 vertex_data : &[vertex::Vert3dOrientationScaleColor]
520 ) {
521 let range =
522 self.instanced_aabb_triangles.start as usize..
523 self.instanced_aabb_triangles.end as usize;
524 self.instance_vertices.slice (range).unwrap().write (vertex_data);
525 }
526
527 #[inline]
528 pub fn instance_vertices_billboard_write (&self,
529 billboard_key : usize,
530 vertex_data : &[vertex::Vert3dOrientationScaleColor]
531 ) {
532 let range = {
533 let range = self.instanced_billboards[billboard_key].instances_range
534 .clone();
535 range.start as usize..range.end as usize
536 };
537 self.instance_vertices.slice (range.start..range.end)
538 .unwrap().write (vertex_data);
539 }
540
541 #[inline]
542 pub fn instance_vertices_mesh_write (&self,
543 mesh_key : usize,
544 vertex_data : &[vertex::Vert3dOrientationScaleColor]
545 ) {
546 let range = {
547 let range = self.instanced_meshes.meshes[mesh_key].instances_range.clone();
548 range.start as usize..range.end as usize
549 };
550 self.instance_vertices.slice (range).unwrap().write (vertex_data);
551 }
552
553 pub fn tile_billboard_create (&mut self,
558 glium_display : &glium::Display <glutin::surface::WindowSurface>,
559 tileset_texture : &glium::Texture2d,
560 billboard_key : usize,
561 instances_range : std::ops::Range <u32>,
562 string : &str
563 ) {
564 use glium::Surface;
565 debug_assert_eq!(0, tileset_texture.width() %16);
566 debug_assert_eq!(0, tileset_texture.height()%16);
567 let tile_width = tileset_texture.width() / 16;
568 let tile_height = tileset_texture.height() / 16;
569 let texture = glium::Texture2d::empty_with_mipmaps (
570 glium_display, glium::texture::MipmapsOption::NoMipmap,
571 tile_width * string.len() as u32, tile_height
572 ).unwrap();
573 { let source = tileset_texture.as_surface();
575 let mut target = texture.as_surface();
576 target.clear_color (1.0, 0.0, 1.0, 1.0);
577 for (i,ch) in string.chars().enumerate() {
578 let tile = ch as u32;
579 let source_rect = glium::Rect {
581 left: tile_width * (tile % 16),
582 bottom: tile_height * (15 - tile / 16),
583 width: tile_width,
584 height: tile_height
585 };
586 #[allow(clippy::identity_op)]
587 let target_rect = glium::BlitTarget {
588 left: 0 + i as u32 * tile_width,
589 bottom: 0,
590 width: tile_width as i32,
591 height: tile_height as i32
592 };
593 target.blit_from_simple_framebuffer (
594 &source, &source_rect, &target_rect,
595 glium::uniforms::MagnifySamplerFilter::Linear);
596 }
597 }
598 let instanced_billboard = InstancedBillboard { texture, instances_range };
599 assert!(self.instanced_billboards.insert (
600 billboard_key, instanced_billboard
601 ).is_none());
602 }
603}
604
605impl <'a> InstancesInit <'a> {
606 pub fn instance_count (&self) -> usize {
607 let mut count = 0;
608 count += self.aabb_lines.map_or(0, |verts| verts.len());
609 count += self.aabb_triangles.map_or(0, |verts| verts.len());
610 for (_, mesh_data) in self.meshes.iter() {
611 count += mesh_data.len();
612 }
613 for (_, billboard_data) in self.billboards.iter() {
614 count += billboard_data.len();
615 }
616 count
617 }
618}
619
620impl InstancedMeshes {
621 pub fn new (
622 glium_display : &glium::Display <glutin::surface::WindowSurface>,
623 user_meshes : Vec <(MeshKey, Mesh, DrawPass)>
624 ) -> Self {
625 let InstancedMeshInit {
626 instanced_vertex_data,
627 instanced_line_index_data,
628 line_indices_ranges,
629 shader_program_ids,
630 draw_passes,
631 capsule_vertex_id_offset,
632 hemisphere_vertex_count
633 } = InstancedMeshInit::new (user_meshes);
634 let vertices = glium::VertexBuffer::dynamic (
635 glium_display, instanced_vertex_data.as_slice()
636 ).unwrap();
637 let line_indices = glium::IndexBuffer::dynamic (
638 glium_display, glium::index::PrimitiveType::LinesList,
639 instanced_line_index_data.as_slice()
640 ).unwrap();
641 let meshes = {
642 let mut v = VecMap::new();
643 for (mesh_key, line_indices_range) in line_indices_ranges.into_iter() {
644 let instanced_mesh = InstancedMesh {
645 line_indices_range,
646 instances_range: 0..0, shader_program_id: shader_program_ids[mesh_key],
648 draw_pass: draw_passes[mesh_key]
649 };
650 assert!(v.insert (mesh_key, instanced_mesh).is_none());
651 }
652 v
653 };
654 InstancedMeshes {
655 vertices, line_indices, meshes, capsule_vertex_id_offset,
656 hemisphere_vertex_count
657 }
658 }
659}
660
661impl InstancedMeshInit {
662 pub fn new (user_meshes : Vec <(MeshKey, Mesh, DrawPass)>) -> Self {
663 const GRID_DIMS : u16 = MESH_GRID_DIMS;
664 const HEMISPHERE_LATITUDE_DIVS : u16 = 6;
665 const SPHERE_LATITUDE_DIVS : u16 = 2 * HEMISPHERE_LATITUDE_DIVS;
666 const LONGITUDE_DIVS : u16 = 24;
667 const CYLINDER_DIVS : u16 = LONGITUDE_DIVS;
668 let mut instanced_vertex_data = Vec::new();
669 let mut instanced_line_index_data = Vec::new();
670 let mut index_offset = 0;
672 let mut index_range_start = 0;
674
675 let mut line_indices_ranges = VecMap::with_capacity (MeshId::COUNT);
676 let mut shader_program_ids = VecMap::with_capacity (MeshId::COUNT);
677 let mut draw_passes = VecMap::with_capacity (MeshId::COUNT);
678
679 let mesh::Lines3d {
681 vertices: mut grid_vertex_data, indices: mut grid_index_data
682 } = mesh::Lines3d::grid (index_offset, GRID_DIMS);
683 assert!(line_indices_ranges.insert (
684 MeshId::Grid as usize,
685 index_range_start..index_range_start + grid_index_data.len() as u32
686 ).is_none());
687 assert!(shader_program_ids.insert (
688 MeshId::Grid as usize,
689 shader::ProgramId::ModelSpace3dInstancedOrientationScaleColor
690 ).is_none());
691 assert!(draw_passes.insert (MeshId::Grid as usize, DrawPass::Depth)
692 .is_none());
693 instanced_vertex_data.append (&mut grid_vertex_data);
694 instanced_line_index_data.append (&mut grid_index_data);
695 index_offset = instanced_vertex_data.len() as u32;
696 index_range_start = instanced_line_index_data.len() as u32;
697
698 let capsule_vertex_id_offset = index_offset; let mesh::Lines3d {
702 vertices: mut capsule_vertex_data,
703 indices: mut capsule_index_data
704 } = mesh::Lines3d::capsule (
705 index_offset, HEMISPHERE_LATITUDE_DIVS, LONGITUDE_DIVS);
706 let capsule_line_indices_range =
707 index_range_start..index_range_start + capsule_index_data.len() as u32;
708 assert!(line_indices_ranges.insert (
709 MeshId::Capsule as usize, capsule_line_indices_range.clone()
710 ).is_none());
711 assert!(shader_program_ids.insert (
712 MeshId::Capsule as usize,
713 shader::ProgramId::ModelSpace3dInstancedCapsule
714 ).is_none());
715 assert!(draw_passes.insert (MeshId::Capsule as usize, DrawPass::Depth)
716 .is_none());
717 instanced_vertex_data.append (&mut capsule_vertex_data);
718 instanced_line_index_data.append (&mut capsule_index_data);
719
720 index_offset = instanced_vertex_data.len() as u32;
721 index_range_start = instanced_line_index_data.len() as u32;
722
723 let (hemisphere_vertex_count, hemisphere_index_count) =
726 mesh::hemisphere::lines3d_vertex_index_counts (
727 HEMISPHERE_LATITUDE_DIVS, LONGITUDE_DIVS);
728 assert!(line_indices_ranges.insert (
729 MeshId::Hemisphere as usize,
730 capsule_line_indices_range.start..
731 capsule_line_indices_range.start + hemisphere_index_count
732 ).is_none());
733 assert!(shader_program_ids.insert (
734 MeshId::Hemisphere as usize,
735 shader::ProgramId::ModelSpace3dInstancedScaleColor
736 ).is_none());
737 assert!(draw_passes.insert (MeshId::Hemisphere as usize, DrawPass::Depth)
738 .is_none());
739
740 let (_, sphere_index_count) = mesh::sphere::lines3d_vertex_index_counts (
743 SPHERE_LATITUDE_DIVS, LONGITUDE_DIVS);
744 assert!(line_indices_ranges.insert (
745 MeshId::Sphere as usize,
746 capsule_line_indices_range.start..
747 capsule_line_indices_range.start + sphere_index_count
748 ).is_none());
749 assert!(shader_program_ids.insert (
750 MeshId::Sphere as usize,
751 shader::ProgramId::ModelSpace3dInstancedScaleColor
752 ).is_none());
753 assert!(draw_passes.insert (MeshId::Sphere as usize, DrawPass::Depth)
754 .is_none());
755
756 let mesh::Lines3d {
758 vertices: mut cylinder_vertex_data, indices: mut cylinder_index_data
759 } = mesh::Lines3d::cylinder (index_offset, CYLINDER_DIVS);
760 assert!(line_indices_ranges.insert (
761 MeshId::Cylinder as usize,
762 index_range_start..index_range_start + cylinder_index_data.len() as u32
763 ).is_none());
764 assert!(shader_program_ids.insert (
765 MeshId::Cylinder as usize,
766 shader::ProgramId::ModelSpace3dInstancedScaleColor
767 ).is_none());
768 assert!(draw_passes.insert (MeshId::Cylinder as usize, DrawPass::Depth)
769 .is_none());
770 instanced_vertex_data.append (&mut cylinder_vertex_data);
771 instanced_line_index_data.append (&mut cylinder_index_data);
772
773 let num_user_meshes = user_meshes.len();
780 for (mesh_key, mut mesh, draw_pass) in user_meshes {
781 debug_assert!(mesh_key.index() >= MeshId::COUNT);
782 index_offset = instanced_vertex_data.len() as u32;
783 index_range_start = instanced_line_index_data.len() as u32;
784 match mesh {
785 Mesh::Lines3d (mesh::Lines3d { ref mut vertices, ref mut indices }) => {
786 indices.iter_mut().for_each (|ix| *ix += index_offset);
787 assert!(line_indices_ranges.insert (
788 mesh_key.index(),
789 index_range_start..index_range_start + indices.len() as u32
790 ).is_none());
791 assert!(shader_program_ids.insert (
792 mesh_key.index(),
793 shader::ProgramId::ModelSpace3dInstancedOrientationScaleColor
794 ).is_none());
795 assert!(draw_passes.insert (mesh_key.index(), draw_pass).is_none());
796 instanced_vertex_data.append (vertices);
797 instanced_line_index_data.append (indices);
798 }
799 }
800 }
801
802 debug_assert_eq!(line_indices_ranges.len(), MeshId::COUNT + num_user_meshes);
803 debug_assert_eq!(shader_program_ids.len(), MeshId::COUNT + num_user_meshes);
804
805 InstancedMeshInit {
806 instanced_vertex_data,
807 instanced_line_index_data,
808 line_indices_ranges,
809 shader_program_ids,
810 draw_passes,
811 capsule_vertex_id_offset,
812 hemisphere_vertex_count
813 }
814 }
815}
816
817impl MeshKey {
818 pub fn index (self) -> usize {
819 self.0 as usize
820 }
821}
822
823impl UserBufferKey {
824 pub fn index (self) -> usize {
825 self.0 as usize
826 }
827}