use crate::{
core::{
algebra::{Matrix4, Vector2},
color::Color,
math::TriangleDefinition,
scope_profile,
},
engine::resource_manager::TimedEntry,
renderer::framework::{
geometry_buffer::{
AttributeDefinition, AttributeKind, BufferBuilder, ElementKind, GeometryBuffer,
GeometryBufferBuilder, GeometryBufferKind,
},
state::PipelineState,
},
};
use fxhash::FxHashMap;
use rg3d_core::algebra::Vector3;
#[repr(C)]
pub struct Vertex {
position: Vector3<f32>,
tex_coord: Vector2<f32>,
}
pub struct Mesh {
vertices: Vec<Vertex>,
triangles: Vec<TriangleDefinition>,
}
impl Mesh {
pub fn new_unit_quad() -> Self {
let vertices = vec![
Vertex {
position: Vector3::new(-0.5, 0.5, 0.0),
tex_coord: Vector2::new(1.0, 0.0),
},
Vertex {
position: Vector3::new(0.5, 0.5, 0.0),
tex_coord: Vector2::new(0.0, 0.0),
},
Vertex {
position: Vector3::new(0.5, -0.5, 0.0),
tex_coord: Vector2::new(0.0, 1.0),
},
Vertex {
position: Vector3::new(-0.5, -0.5, 0.0),
tex_coord: Vector2::new(1.0, 1.0),
},
];
let triangles = vec![TriangleDefinition([0, 1, 2]), TriangleDefinition([0, 2, 3])];
Self {
vertices,
triangles,
}
}
}
#[derive(Default)]
pub(in crate) struct GeometryCache {
map: FxHashMap<usize, TimedEntry<GeometryBuffer>>,
}
#[derive(Clone)]
#[repr(C)]
pub(in crate) struct InstanceData {
pub color: Color,
pub world_matrix: Matrix4<f32>,
}
impl GeometryCache {
pub fn get(&mut self, state: &mut PipelineState, data: &Mesh) -> &mut GeometryBuffer {
scope_profile!();
let key = (data as *const _) as usize;
let geometry_buffer = self.map.entry(key).or_insert_with(|| {
let geometry_buffer = GeometryBufferBuilder::new(ElementKind::Triangle)
.with_buffer_builder(
BufferBuilder::new(
GeometryBufferKind::StaticDraw,
Some(data.vertices.as_slice()),
)
.with_attribute(AttributeDefinition {
location: 0,
divisor: 0,
kind: AttributeKind::Float3,
normalized: false,
})
.with_attribute(AttributeDefinition {
location: 1,
divisor: 0,
kind: AttributeKind::Float2,
normalized: false,
}),
)
.with_buffer_builder(
BufferBuilder::new::<InstanceData>(GeometryBufferKind::DynamicDraw, None)
.with_attribute(AttributeDefinition {
location: 2,
kind: AttributeKind::UnsignedByte4,
normalized: true,
divisor: 1,
})
.with_attribute(AttributeDefinition {
location: 3,
kind: AttributeKind::Float4,
normalized: false,
divisor: 1,
})
.with_attribute(AttributeDefinition {
location: 4,
kind: AttributeKind::Float4,
normalized: false,
divisor: 1,
})
.with_attribute(AttributeDefinition {
location: 5,
kind: AttributeKind::Float4,
normalized: false,
divisor: 1,
})
.with_attribute(AttributeDefinition {
location: 6,
kind: AttributeKind::Float4,
normalized: false,
divisor: 1,
}),
)
.build(state)
.unwrap();
geometry_buffer.bind(state).set_triangles(&data.triangles);
TimedEntry {
value: geometry_buffer,
time_to_live: 20.0,
}
});
geometry_buffer.time_to_live = 20.0;
geometry_buffer
}
pub fn update(&mut self, dt: f32) {
scope_profile!();
for entry in self.map.values_mut() {
entry.time_to_live -= dt;
}
self.map.retain(|_, v| v.time_to_live > 0.0);
}
pub fn clear(&mut self) {
self.map.clear();
}
}