use crate::{
components::{
camera::*, mesh_instance::*, transform::*, visibility::*, volume::*, volume_visibility::*,
},
ha_renderer::HaRenderer,
math::*,
};
use core::ecs::{components::Tag, Comp, Universe, WorldRef};
#[derive(Debug, Default)]
pub struct HaVolumeVisibilitySystemCache {
temp_tag_volumes: Vec<(&'static str, BoundsVolume)>,
}
pub type HaVolumeVisibilitySystemResources<'a> = (
WorldRef,
&'a HaRenderer,
&'a mut HaVolumeVisibilitySystemCache,
Comp<&'a Tag>,
Comp<&'a HaTransform>,
Comp<&'a HaVolume>,
Comp<&'a HaVolumeVisibility>,
Comp<&'a mut HaVisibility>,
Comp<&'a HaMeshInstance>,
Comp<&'a HaCamera>,
);
pub fn ha_volume_visibility_system(universe: &mut Universe) {
let (world, renderer, mut cache, ..) =
universe.query_resources::<HaVolumeVisibilitySystemResources>();
cache.temp_tag_volumes.clear();
cache.temp_tag_volumes.extend(
world
.query::<(&Tag, &HaTransform, &HaVolume)>()
.iter()
.filter_map(|(_, (tag, transform, volume))| {
let bounds = match volume {
HaVolume::Sphere(r) => BoundsVolume::from_sphere(Default::default(), *r),
HaVolume::Box(he) => BoundsVolume::from_box(Default::default(), *he),
};
let bounds = bounds.transformed(transform.world_matrix())?;
let tag = unsafe { std::mem::transmute(tag.0.as_ref()) };
Some((tag, bounds))
}),
);
for (_, (visibility, transform, volume, mesh)) in world
.query::<(
&mut HaVisibility,
&HaTransform,
&HaVolumeVisibility,
&HaMeshInstance,
)>()
.iter()
{
let mesh_id = match mesh.reference.id() {
Some(mesh_id) => *mesh_id,
None => continue,
};
let mesh = match renderer.mesh(mesh_id) {
Some(mesh) => mesh,
None => continue,
};
let bounds = match mesh.bounds() {
Some(bounds) => bounds,
None => continue,
};
let bounds = match bounds.transformed(transform.world_matrix()) {
Some(bounds) => bounds,
None => continue,
};
visibility.0 = cache.temp_tag_volumes.iter().any(|(t, b)| {
if volume.filters.validate_tag(t) {
match volume.mode {
HaVolumeVisibilityMode::Sphere => return bounds.overlap_spheres(b),
HaVolumeVisibilityMode::Box => return bounds.overlap_boxes(b),
}
}
false
});
}
cache.temp_tag_volumes.clear();
}