use derive_more::From;
use glium::{self, uniform};
use strum::{EnumCount, EnumIter, FromRepr};
use vec_map::VecMap;
use math_utils as math;
use crate::{color, mesh, render, shader, vertex, Mesh, Render};
pub const MESH_GRID_DIMS : u16 = 12;
pub const DEFAULT_PIXELS_PER_UNIT : f32 = 64.0;
pub struct Draw3d {
instance_vertices : glium::VertexBuffer <vertex::Vert3dOrientationScaleColor>,
instanced_aabb_lines : std::ops::Range <u32>,
instanced_aabb_triangles : std::ops::Range <u32>,
instanced_billboards : VecMap <InstancedBillboard>,
instanced_meshes : InstancedMeshes,
pub user_buffers : VecMap <glium::VertexBuffer <vertex::Vert3dColor>>,
pub user_draw : VecMap <UserDraw>,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct UserDraw {
pub buffer_key : UserBufferKey,
pub range : std::ops::Range <u32>,
pub primitive_type : glium::index::PrimitiveType,
pub shader_program_id : shader::ProgramId,
pub draw_pass : DrawPass
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct UserBufferKey (pub u32);
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum DrawPass {
Depth,
NoDepth
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct InstancedMesh {
pub line_indices_range : std::ops::Range <u32>,
pub instances_range : std::ops::Range <u32>,
pub shader_program_id : shader::ProgramId,
pub draw_pass : DrawPass
}
pub struct InstancedBillboard {
pub texture : glium::Texture2d,
pub instances_range : std::ops::Range <u32>
}
#[derive(Default)]
pub struct InstancesInit <'a> {
pub aabb_lines : Option <&'a [vertex::Vert3dOrientationScaleColor]>,
pub aabb_triangles : Option <&'a [vertex::Vert3dOrientationScaleColor]>,
pub aabb_lines_and_triangles :
Option <&'a [vertex::Vert3dOrientationScaleColor]>,
pub meshes : VecMap <&'a [vertex::Vert3dOrientationScaleColor]>,
pub billboards : VecMap <&'a [vertex::Vert3dOrientationScaleColor]>
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, From)]
pub struct MeshKey (pub u32);
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, EnumCount, EnumIter,
FromRepr)]
#[repr(u16)]
pub enum MeshId {
Grid,
Hemisphere,
Sphere,
Capsule,
Cylinder
}
struct InstancedMeshes {
pub vertices : glium::VertexBuffer <vertex::Vert3dInstanced>,
pub line_indices : glium::IndexBuffer <u32>,
pub meshes : VecMap <InstancedMesh>,
pub capsule_vertex_id_offset : u32,
pub hemisphere_vertex_count : u32
}
struct InstancedMeshInit {
pub instanced_vertex_data : Vec <vertex::Vert3dInstanced>,
pub instanced_line_index_data : Vec <u32>,
pub line_indices_ranges : VecMap <std::ops::Range <u32>>,
pub shader_program_ids : VecMap <shader::ProgramId>,
pub draw_passes : VecMap <DrawPass>,
pub capsule_vertex_id_offset : u32,
pub hemisphere_vertex_count : u32
}
impl Draw3d {
pub fn new (glium_display : &glium::Display <glutin::surface::WindowSurface>)
-> Self
{
let instanced_aabb_lines = 0..0; let instanced_aabb_triangles = 0..0; let instanced_billboards = VecMap::new();
let instanced_meshes = InstancedMeshes::new (glium_display, vec![]);
let instance_vertices = glium::VertexBuffer::dynamic (
glium_display,
&[ vertex::Vert3dOrientationScaleColor {
position: [0.0, 0.0, 0.0],
orientation: math::Matrix3::identity().into_col_arrays(),
scale: [1.0, 1.0, 1.0],
color: color::rgba_u8_to_rgba_f32 (color::DEBUG_CHARTREUSE)
}
]
).unwrap();
let user_buffers = VecMap::new();
let user_draw = VecMap::new();
Draw3d {
instance_vertices,
instanced_aabb_lines,
instanced_aabb_triangles,
instanced_billboards,
instanced_meshes,
user_buffers,
user_draw
}
}
pub fn draw (
render : &Render <render::resource::Default>,
glium_frame : &mut glium::Frame
) {
let draw3d = &render.resource.draw3d;
for (_, viewport) in render.viewports.iter() {
if let Some (camera3d) = viewport.camera3d() {
use glium::Surface;
let draw_parameters_viewport = viewport.draw_parameters();
let draw_parameters_write_depth = glium::DrawParameters {
depth: glium::Depth {
test: glium::DepthTest::IfLess,
write: true,
.. glium::Depth::default()
},
.. draw_parameters_viewport.clone()
};
let draw_parameters_polygon_offset = glium::DrawParameters {
polygon_offset: glium::draw_parameters::PolygonOffset {
factor: 1.0,
units: 1.0 / 1024.0,
fill: true,
.. Default::default()
},
backface_culling:
glium::draw_parameters::BackfaceCullingMode::CullCounterClockwise,
.. draw_parameters_write_depth.clone()
};
let (transform_mat_world_to_view, projection_mat_perspective) =
camera3d.view_mats();
let uniforms = uniform!{
uni_transform_mat_view: transform_mat_world_to_view,
uni_projection_mat_perspective: projection_mat_perspective,
uni_pixels_per_unit: DEFAULT_PIXELS_PER_UNIT,
uni_capsule_vertex_id_offset:
draw3d.instanced_meshes.capsule_vertex_id_offset,
uni_hemisphere_vertex_count:
draw3d.instanced_meshes.hemisphere_vertex_count,
uni_color: color::rgba_u8_to_rgba_f32 (color::BLACK)
};
if !draw3d.instanced_aabb_lines.is_empty() {
let instances_range =
draw3d.instanced_aabb_lines.start as usize..
draw3d.instanced_aabb_lines.end as usize;
glium_frame.draw (
draw3d.instance_vertices.slice (instances_range).unwrap(),
glium::index::IndicesSource::NoIndices {
primitives: glium::index::PrimitiveType::Points
},
&render.resource.shader_programs [
shader::ProgramId::WorldSpace3dAabbLines as usize
],
&uniforms,
&draw_parameters_write_depth
).unwrap();
}
if !draw3d.instanced_aabb_triangles.is_empty() {
let instances_range =
draw3d.instanced_aabb_triangles.start as usize..
draw3d.instanced_aabb_triangles.end as usize;
glium_frame.draw (
draw3d.instance_vertices.slice (instances_range).unwrap(),
glium::index::IndicesSource::NoIndices {
primitives: glium::index::PrimitiveType::Points
},
&render.resource.shader_programs [
shader::ProgramId::WorldSpace3dAabbTriangles as usize
],
&uniforms,
&draw_parameters_polygon_offset
).unwrap();
}
for (_mesh_key, instanced_mesh) in draw3d.instanced_meshes.meshes.iter() {
if instanced_mesh.draw_pass != DrawPass::Depth {
continue
}
if !instanced_mesh.instances_range.is_empty() {
let (line_indices_range, instances_range) = (
instanced_mesh.line_indices_range.start as usize..
instanced_mesh.line_indices_range.end as usize,
instanced_mesh.instances_range.start as usize..
instanced_mesh.instances_range.end as usize
);
glium_frame.draw (
(&draw3d.instanced_meshes.vertices,
draw3d.instance_vertices.slice (instances_range).unwrap()
.per_instance().unwrap()
),
draw3d.instanced_meshes.line_indices.slice (line_indices_range)
.unwrap(),
&render.resource.shader_programs [instanced_mesh.shader_program_id
as usize],
&uniforms,
&draw_parameters_write_depth
).unwrap();
}
}
for user_draw in draw3d.user_draw.values() {
if user_draw.draw_pass != DrawPass::Depth {
continue
}
let vertex_buffer = draw3d.user_buffers
.get (user_draw.buffer_key.index()).unwrap();
let vertex_range =
user_draw.range.start as usize..
user_draw.range.end as usize;
let uniforms = uniform!{
uni_transform_mat_view: transform_mat_world_to_view,
uni_projection_mat_perspective: projection_mat_perspective,
uni_pixels_per_unit: DEFAULT_PIXELS_PER_UNIT,
uni_capsule_vertex_id_offset:
draw3d.instanced_meshes.capsule_vertex_id_offset,
uni_hemisphere_vertex_count:
draw3d.instanced_meshes.hemisphere_vertex_count
};
glium_frame.draw (
vertex_buffer.slice (vertex_range).unwrap(),
&glium::index::NoIndices (user_draw.primitive_type),
&render.resource.shader_programs [user_draw.shader_program_id.index()],
&uniforms,
&draw_parameters_write_depth
).unwrap();
}
for (_mesh_key, instanced_mesh) in draw3d.instanced_meshes.meshes.iter() {
if instanced_mesh.draw_pass != DrawPass::NoDepth {
continue
}
if !instanced_mesh.instances_range.is_empty() {
let (line_indices_range, instances_range) = (
instanced_mesh.line_indices_range.start as usize..
instanced_mesh.line_indices_range.end as usize,
instanced_mesh.instances_range.start as usize..
instanced_mesh.instances_range.end as usize
);
glium_frame.draw (
(&draw3d.instanced_meshes.vertices,
draw3d.instance_vertices.slice (instances_range).unwrap()
.per_instance().unwrap()
),
draw3d.instanced_meshes.line_indices.slice (line_indices_range)
.unwrap(),
&render.resource.shader_programs [instanced_mesh.shader_program_id
as usize],
&uniforms,
&draw_parameters_viewport
).unwrap();
}
}
for user_draw in draw3d.user_draw.values() {
if user_draw.draw_pass != DrawPass::NoDepth {
continue
}
let vertex_buffer = draw3d.user_buffers
.get (user_draw.buffer_key.index()).unwrap();
let vertex_range =
user_draw.range.start as usize..
user_draw.range.end as usize;
glium_frame.draw (
vertex_buffer.slice (vertex_range).unwrap(),
&glium::index::NoIndices (user_draw.primitive_type),
&render.resource.shader_programs [user_draw.shader_program_id.index()],
&uniforms,
&draw_parameters_viewport
).unwrap();
}
for (_, instanced_billboard) in draw3d.instanced_billboards.iter() {
let instances_range =
instanced_billboard.instances_range.start as usize..
instanced_billboard.instances_range.end as usize;
let uniforms = uniform!{
uni_transform_mat_view: transform_mat_world_to_view,
uni_projection_mat_perspective: projection_mat_perspective,
uni_sampler2d: instanced_billboard.texture.sampled()
.magnify_filter (glium::uniforms::MagnifySamplerFilter::Nearest),
uni_pixels_per_unit: DEFAULT_PIXELS_PER_UNIT
};
glium_frame.draw (
draw3d.instance_vertices.slice (instances_range).unwrap(),
glium::index::IndicesSource::NoIndices {
primitives: glium::index::PrimitiveType::Points
},
&render.resource.shader_programs [
shader::ProgramId::WorldSpace3dSprite as usize
],
&uniforms,
&draw_parameters_viewport
).unwrap();
}
}
} }
#[inline]
pub fn instance_vertices (&self)
-> &glium::VertexBuffer <vertex::Vert3dOrientationScaleColor>
{
&self.instance_vertices
}
#[inline]
pub fn instanced_aabb_lines (&self) -> &std::ops::Range <u32> {
&self.instanced_aabb_lines
}
#[inline]
pub fn set_instanced_aabb_lines (&mut self, range : std::ops::Range <u32>) {
debug_assert!(range.end <= self.instance_vertices.len() as u32);
self.instanced_aabb_lines = range;
}
#[inline]
pub fn instanced_aabb_triangles (&self) -> &std::ops::Range <u32> {
&self.instanced_aabb_triangles
}
#[inline]
pub fn set_instanced_aabb_triangles (&mut self, range : std::ops::Range <u32>) {
debug_assert!(range.end <= self.instance_vertices.len() as u32);
self.instanced_aabb_triangles = range;
}
#[inline]
pub fn instanced_meshes (&self) -> &VecMap <InstancedMesh> {
&self.instanced_meshes.meshes
}
#[inline]
pub fn set_instanced_mesh (&mut self,
mesh_key : MeshKey, mesh : InstancedMesh
) {
let _ = self.instanced_meshes.meshes.insert (mesh_key.index(), mesh);
}
pub fn rebuild_instanced_meshes (&mut self,
glium_display : &glium::Display <glutin::surface::WindowSurface>,
user_meshes : Vec <(MeshKey, Mesh, DrawPass)>
) {
self.instanced_meshes = InstancedMeshes::new (glium_display, user_meshes);
}
pub fn instance_vertices_set (&mut self,
glium_display : &glium::Display <glutin::surface::WindowSurface>,
instances_init : InstancesInit
) {
let mut instance_vertices =
Vec::with_capacity (instances_init.instance_count());
self.instanced_aabb_lines = 0..0;
self.instanced_aabb_triangles = 0..0;
for mesh in self.instanced_meshes.meshes.values_mut() {
mesh.instances_range = 0..0;
}
if let Some (instances) = instances_init.aabb_lines {
let start = instance_vertices.len() as u32;
instance_vertices.extend_from_slice (instances);
let end = instance_vertices.len() as u32;
self.instanced_aabb_lines = start..end;
}
if let Some (instances) = instances_init.aabb_lines_and_triangles {
let start = instance_vertices.len() as u32;
instance_vertices.extend_from_slice (instances);
let end = instance_vertices.len() as u32;
if self.instanced_aabb_lines.end != 0 {
debug_assert!(instances_init.aabb_lines.is_none());
self.instanced_aabb_lines.start = start;
}
self.instanced_aabb_lines.end = end;
self.instanced_aabb_triangles = start..end;
}
if let Some (instances) = instances_init.aabb_triangles {
let start = instance_vertices.len() as u32;
instance_vertices.extend_from_slice (instances);
let end = instance_vertices.len() as u32;
if self.instanced_aabb_triangles.end == 0 {
debug_assert!(instances_init.aabb_lines_and_triangles.is_none());
self.instanced_aabb_triangles.start = start;
}
self.instanced_aabb_triangles.end = end;
}
for (mesh_key, instances) in instances_init.meshes.into_iter() {
let start = instance_vertices.len() as u32;
instance_vertices.extend_from_slice (instances);
let end = instance_vertices.len() as u32;
self.instanced_meshes.meshes[mesh_key].instances_range = start..end;
}
for (billboard_key, instances) in instances_init.billboards.into_iter() {
let start = instance_vertices.len() as u32;
instance_vertices.extend_from_slice (instances);
let end = instance_vertices.len() as u32;
self.instanced_billboards[billboard_key].instances_range = start..end;
}
self.instance_vertices = glium::VertexBuffer::dynamic (
glium_display, instance_vertices.as_slice()
).unwrap();
}
#[inline]
pub fn instance_vertices_aabb_lines_write (&self,
vertex_data : &[vertex::Vert3dOrientationScaleColor]
) {
let range =
self.instanced_aabb_lines.start as usize..
self.instanced_aabb_lines.end as usize;
self.instance_vertices.slice (range).unwrap().write (vertex_data);
}
#[inline]
pub fn instance_vertices_aabb_triangles_write (&self,
vertex_data : &[vertex::Vert3dOrientationScaleColor]
) {
let range =
self.instanced_aabb_triangles.start as usize..
self.instanced_aabb_triangles.end as usize;
self.instance_vertices.slice (range).unwrap().write (vertex_data);
}
#[inline]
pub fn instance_vertices_billboard_write (&self,
billboard_key : usize,
vertex_data : &[vertex::Vert3dOrientationScaleColor]
) {
let range = {
let range = self.instanced_billboards[billboard_key].instances_range
.clone();
range.start as usize..range.end as usize
};
self.instance_vertices.slice (range.start as usize..range.end as usize)
.unwrap().write (vertex_data);
}
#[inline]
pub fn instance_vertices_mesh_write (&self,
mesh_key : usize,
vertex_data : &[vertex::Vert3dOrientationScaleColor]
) {
let range = {
let range = self.instanced_meshes.meshes[mesh_key].instances_range.clone();
range.start as usize..range.end as usize
};
self.instance_vertices.slice (range).unwrap().write (vertex_data);
}
pub fn tile_billboard_create (&mut self,
glium_display : &glium::Display <glutin::surface::WindowSurface>,
tileset_texture : &glium::Texture2d,
billboard_key : usize,
instances_range : std::ops::Range <u32>,
string : &str
) {
use glium::Surface;
debug_assert_eq!(0, tileset_texture.width() %16);
debug_assert_eq!(0, tileset_texture.height()%16);
let tile_width = tileset_texture.width() / 16;
let tile_height = tileset_texture.height() / 16;
let texture = glium::Texture2d::empty_with_mipmaps (
glium_display, glium::texture::MipmapsOption::NoMipmap,
tile_width * string.len() as u32, tile_height
).unwrap();
{ let source = tileset_texture.as_surface();
let mut target = texture.as_surface();
target.clear_color (1.0, 0.0, 1.0, 1.0);
for (i,ch) in string.chars().enumerate() {
let tile = ch as u32;
let source_rect = glium::Rect {
left: tile_width * (tile % 16),
bottom: tile_height * (15 - tile / 16),
width: tile_width,
height: tile_height
};
let target_rect = glium::BlitTarget {
left: 0 + i as u32 * tile_width,
bottom: 0,
width: tile_width as i32,
height: tile_height as i32
};
target.blit_from_simple_framebuffer (
&source, &source_rect, &target_rect,
glium::uniforms::MagnifySamplerFilter::Linear);
}
}
let instanced_billboard = InstancedBillboard { texture, instances_range };
assert!(self.instanced_billboards.insert (
billboard_key, instanced_billboard
).is_none());
}
}
impl <'a> InstancesInit <'a> {
pub fn instance_count (&self) -> usize {
let mut count = 0;
count += self.aabb_lines.map_or(0, |verts| verts.len());
count += self.aabb_triangles.map_or(0, |verts| verts.len());
for (_, mesh_data) in self.meshes.iter() {
count += mesh_data.len();
}
for (_, billboard_data) in self.billboards.iter() {
count += billboard_data.len();
}
count
}
}
impl InstancedMeshes {
pub fn new (
glium_display : &glium::Display <glutin::surface::WindowSurface>,
user_meshes : Vec <(MeshKey, Mesh, DrawPass)>
) -> Self {
let InstancedMeshInit {
instanced_vertex_data,
instanced_line_index_data,
line_indices_ranges,
shader_program_ids,
draw_passes,
capsule_vertex_id_offset,
hemisphere_vertex_count
} = InstancedMeshInit::new (user_meshes);
let vertices = glium::VertexBuffer::dynamic (
glium_display, instanced_vertex_data.as_slice()
).unwrap();
let line_indices = glium::IndexBuffer::dynamic (
glium_display, glium::index::PrimitiveType::LinesList,
instanced_line_index_data.as_slice()
).unwrap();
let meshes = {
let mut v = VecMap::new();
for (mesh_key, line_indices_range) in line_indices_ranges.into_iter() {
let instanced_mesh = InstancedMesh {
line_indices_range,
instances_range: 0..0, shader_program_id: shader_program_ids[mesh_key],
draw_pass: draw_passes[mesh_key]
};
assert!(v.insert (mesh_key, instanced_mesh).is_none());
}
v
};
InstancedMeshes {
vertices, line_indices, meshes, capsule_vertex_id_offset,
hemisphere_vertex_count
}
}
}
impl InstancedMeshInit {
pub fn new (user_meshes : Vec <(MeshKey, Mesh, DrawPass)>) -> Self {
const GRID_DIMS : u16 = MESH_GRID_DIMS;
const HEMISPHERE_LATITUDE_DIVS : u16 = 6;
const SPHERE_LATITUDE_DIVS : u16 = 2 * HEMISPHERE_LATITUDE_DIVS;
const LONGITUDE_DIVS : u16 = 24;
const CYLINDER_DIVS : u16 = LONGITUDE_DIVS;
let mut instanced_vertex_data = Vec::new();
let mut instanced_line_index_data = Vec::new();
let mut index_offset = 0;
let mut index_range_start = 0;
let mut line_indices_ranges = VecMap::with_capacity (MeshId::COUNT);
let mut shader_program_ids = VecMap::with_capacity (MeshId::COUNT);
let mut draw_passes = VecMap::with_capacity (MeshId::COUNT);
let mesh::Lines3d {
vertices: mut grid_vertex_data, indices: mut grid_index_data
} = mesh::Lines3d::grid (index_offset, GRID_DIMS);
assert!(line_indices_ranges.insert (
MeshId::Grid as usize,
index_range_start..index_range_start + grid_index_data.len() as u32
).is_none());
assert!(shader_program_ids.insert (
MeshId::Grid as usize,
shader::ProgramId::ModelSpace3dInstancedOrientationScaleColor
).is_none());
assert!(draw_passes.insert (MeshId::Grid as usize, DrawPass::Depth)
.is_none());
instanced_vertex_data.append (&mut grid_vertex_data);
instanced_line_index_data.append (&mut grid_index_data);
index_offset = instanced_vertex_data.len() as u32;
index_range_start = instanced_line_index_data.len() as u32;
let capsule_vertex_id_offset = index_offset; let mesh::Lines3d {
vertices: mut capsule_vertex_data,
indices: mut capsule_index_data
} = mesh::Lines3d::capsule (
index_offset, HEMISPHERE_LATITUDE_DIVS, LONGITUDE_DIVS);
let capsule_line_indices_range =
index_range_start..index_range_start + capsule_index_data.len() as u32;
assert!(line_indices_ranges.insert (
MeshId::Capsule as usize, capsule_line_indices_range.clone()
).is_none());
assert!(shader_program_ids.insert (
MeshId::Capsule as usize,
shader::ProgramId::ModelSpace3dInstancedCapsule
).is_none());
assert!(draw_passes.insert (MeshId::Capsule as usize, DrawPass::Depth)
.is_none());
instanced_vertex_data.append (&mut capsule_vertex_data);
instanced_line_index_data.append (&mut capsule_index_data);
index_offset = instanced_vertex_data.len() as u32;
index_range_start = instanced_line_index_data.len() as u32;
let (hemisphere_vertex_count, hemisphere_index_count) =
mesh::hemisphere::lines3d_vertex_index_counts (
HEMISPHERE_LATITUDE_DIVS, LONGITUDE_DIVS);
assert!(line_indices_ranges.insert (
MeshId::Hemisphere as usize,
capsule_line_indices_range.start..
capsule_line_indices_range.start + hemisphere_index_count
).is_none());
assert!(shader_program_ids.insert (
MeshId::Hemisphere as usize,
shader::ProgramId::ModelSpace3dInstancedScaleColor
).is_none());
assert!(draw_passes.insert (MeshId::Hemisphere as usize, DrawPass::Depth)
.is_none());
let (_, sphere_index_count) = mesh::sphere::lines3d_vertex_index_counts (
SPHERE_LATITUDE_DIVS, LONGITUDE_DIVS);
assert!(line_indices_ranges.insert (
MeshId::Sphere as usize,
capsule_line_indices_range.start..
capsule_line_indices_range.start + sphere_index_count
).is_none());
assert!(shader_program_ids.insert (
MeshId::Sphere as usize,
shader::ProgramId::ModelSpace3dInstancedScaleColor
).is_none());
assert!(draw_passes.insert (MeshId::Sphere as usize, DrawPass::Depth)
.is_none());
let mesh::Lines3d {
vertices: mut cylinder_vertex_data, indices: mut cylinder_index_data
} = mesh::Lines3d::cylinder (index_offset, CYLINDER_DIVS);
assert!(line_indices_ranges.insert (
MeshId::Cylinder as usize,
index_range_start..index_range_start + cylinder_index_data.len() as u32
).is_none());
assert!(shader_program_ids.insert (
MeshId::Cylinder as usize,
shader::ProgramId::ModelSpace3dInstancedScaleColor
).is_none());
assert!(draw_passes.insert (MeshId::Cylinder as usize, DrawPass::Depth)
.is_none());
instanced_vertex_data.append (&mut cylinder_vertex_data);
instanced_line_index_data.append (&mut cylinder_index_data);
let num_user_meshes = user_meshes.len();
for (mesh_key, mut mesh, draw_pass) in user_meshes {
debug_assert!(mesh_key.index() >= MeshId::COUNT);
index_offset = instanced_vertex_data.len() as u32;
index_range_start = instanced_line_index_data.len() as u32;
match mesh {
Mesh::Lines3d (mesh::Lines3d { ref mut vertices, ref mut indices }) => {
indices.iter_mut().for_each (|ix| *ix += index_offset);
assert!(line_indices_ranges.insert (
mesh_key.index(),
index_range_start..index_range_start + indices.len() as u32
).is_none());
assert!(shader_program_ids.insert (
mesh_key.index(),
shader::ProgramId::ModelSpace3dInstancedOrientationScaleColor
).is_none());
assert!(draw_passes.insert (mesh_key.index(), draw_pass).is_none());
instanced_vertex_data.append (vertices);
instanced_line_index_data.append (indices);
}
}
}
debug_assert_eq!(line_indices_ranges.len(), MeshId::COUNT + num_user_meshes);
debug_assert_eq!(shader_program_ids.len(), MeshId::COUNT + num_user_meshes);
InstancedMeshInit {
instanced_vertex_data,
instanced_line_index_data,
line_indices_ranges,
shader_program_ids,
draw_passes,
capsule_vertex_id_offset,
hemisphere_vertex_count
}
}
}
impl MeshKey {
pub fn index (self) -> usize {
self.0 as usize
}
}
impl UserBufferKey {
pub fn index (self) -> usize {
self.0 as usize
}
}