rhusics_ecs/collide/systems/
spatial_sort.rs1use std::collections::HashMap;
2use std::fmt::Debug;
3use std::marker::PhantomData;
4
5use cgmath::prelude::*;
6use cgmath::BaseFloat;
7use collision::dbvt::{DynamicBoundingVolumeTree, TreeValue};
8use collision::prelude::*;
9use specs::prelude::{
10 BitSet, Component, ComponentEvent, Entities, Entity, Join, ReadStorage, ReaderId, Resources,
11 System, Tracked, Write, WriteStorage,
12};
13
14use core::{CollisionShape, NextFrame, Primitive};
15
16#[derive(Debug)]
40pub struct SpatialSortingSystem<P, T, D, B, Y = ()> {
41 entities: HashMap<Entity, usize>,
42 dead: Vec<Entity>,
43 updated: BitSet,
44 removed: BitSet,
45 pose_reader: Option<ReaderId<ComponentEvent>>,
46 next_pose_reader: Option<ReaderId<ComponentEvent>>,
47 marker: PhantomData<(P, T, Y, B, D)>,
48}
49
50impl<P, T, D, B, Y> SpatialSortingSystem<P, T, D, B, Y> {
51 pub fn new() -> Self {
53 SpatialSortingSystem {
54 entities: HashMap::default(),
55 marker: PhantomData,
56 updated: BitSet::default(),
57 removed: BitSet::default(),
58 pose_reader: None,
59 next_pose_reader: None,
60 dead: Vec::default(),
61 }
62 }
63}
64
65impl<'a, P, T, Y, D, B> System<'a> for SpatialSortingSystem<P, T, D, B, Y>
66where
67 P: Primitive + ComputeBound<B> + Send + Sync + 'static,
68 B: Clone
69 + Debug
70 + Send
71 + Sync
72 + Union<B, Output = B>
73 + Bound<Point = P::Point>
74 + Contains<B>
75 + SurfaceArea<Scalar = <P::Point as EuclideanSpace>::Scalar>
76 + Send
77 + Sync
78 + 'static,
79 P::Point: Debug,
80 <P::Point as EuclideanSpace>::Scalar: BaseFloat + Send + Sync + 'static,
81 <P::Point as EuclideanSpace>::Diff: Debug + Send + Sync,
82 T: Component + Clone + Debug + Transform<P::Point> + Send + Sync,
83 T::Storage: Tracked,
84 Y: Default + Send + Sync + 'static,
85 D: Send + Sync + 'static + TreeValue<Bound = B> + From<(Entity, B)>,
86{
87 type SystemData = (
88 Entities<'a>,
89 ReadStorage<'a, T>,
90 ReadStorage<'a, NextFrame<T>>,
91 WriteStorage<'a, CollisionShape<P, T, B, Y>>,
92 Write<'a, DynamicBoundingVolumeTree<D>>,
93 );
94
95 fn run(&mut self, (entities, poses, next_poses, mut shapes, mut tree): Self::SystemData) {
96 self.updated.clear();
97 self.removed.clear();
98
99 for event in poses.channel().read(self.pose_reader.as_mut().unwrap()) {
100 match event {
101 ComponentEvent::Inserted(index) => {
102 self.updated.add(*index);
103 }
104 ComponentEvent::Modified(index) => {
105 self.updated.add(*index);
106 }
107 ComponentEvent::Removed(index) => {
108 self.updated.remove(*index);
109 self.removed.add(*index);
110 }
111 }
112 }
113
114 self.dead.clear();
116 for (entity, node_index) in &self.entities {
117 if self.removed.contains(entity.id()) {
118 tree.remove(*node_index);
119 self.dead.push(*entity);
120 }
121 }
122 for entity in &self.dead {
123 self.entities.remove(entity);
124 }
125
126 for (entity, pose, shape, _) in (&*entities, &poses, &mut shapes, &self.updated).join() {
129 shape.update(pose, None);
130
131 match self.entities.get(&entity).cloned() {
133 Some(node_index) => {
135 tree.update_node(node_index, (entity, shape.bound().clone()).into());
136 }
137 None => {
139 let node_index = tree.insert((entity, shape.bound().clone()).into());
140 self.entities.insert(entity, node_index);
141 }
142 }
143 }
144
145 self.updated.clear();
146
147 for event in next_poses
148 .channel()
149 .read(self.next_pose_reader.as_mut().unwrap())
150 {
151 match event {
152 ComponentEvent::Inserted(index) => {
153 self.updated.add(*index);
154 }
155 ComponentEvent::Modified(index) => {
156 self.updated.add(*index);
157 }
158 ComponentEvent::Removed(index) => {
159 self.updated.remove(*index);
160 }
161 }
162 }
163
164 for (entity, pose, next_pose, shape, _) in
167 (&*entities, &poses, &next_poses, &mut shapes, &self.updated).join()
168 {
169 shape.update(pose, Some(&next_pose.value));
170
171 if let Some(node_index) = self.entities.get(&entity).cloned() {
173 tree.update_node(node_index, (entity, shape.bound().clone()).into());
174 }
175 }
176
177 tree.update();
179
180 tree.do_refit();
182 }
183
184 fn setup(&mut self, res: &mut Resources) {
185 use specs::prelude::SystemData;
186 Self::SystemData::setup(res);
187 let mut poses = WriteStorage::<T>::fetch(res);
188 self.pose_reader = Some(poses.register_reader());
189 let mut next_poses = WriteStorage::<NextFrame<T>>::fetch(res);
190 self.next_pose_reader = Some(next_poses.register_reader());
191 }
192}