1extern crate cgmath;
2extern crate collision;
3extern crate rhusics_core;
4extern crate rhusics_ecs;
5extern crate shrev;
6extern crate specs;
7
8use cgmath::{Point2, Rad, Rotation2, Transform, Vector2};
9use collision::dbvt::query_ray_closest;
10use collision::Ray2;
11use shrev::EventChannel;
12use specs::prelude::{Builder, ReadExpect, System, World};
13
14use rhusics_core::{PhysicalEntity, Pose};
15use rhusics_ecs::physics2d::{
16 BodyPose2, CollisionMode, CollisionShape2, CollisionStrategy, ContactEvent2,
17 ContactResolutionSystem2, CurrentFrameUpdateSystem2, DynamicBoundingVolumeTree2, Mass2,
18 NextFrameSetupSystem2, Rectangle, SpatialCollisionSystem2, SpatialSortingSystem2, GJK2,
19};
20use rhusics_ecs::WithPhysics;
21
22struct RayCastSystem;
23
24impl<'a> System<'a> for RayCastSystem {
25 type SystemData = (ReadExpect<'a, DynamicBoundingVolumeTree2<f32>>,);
26
27 fn run(&mut self, (tree,): Self::SystemData) {
28 println!("{:?}", *tree);
29 let ray = Ray2::new(Point2::new(-4., 10.), Vector2::new(0., -1.));
30 if let Some((v, p)) = query_ray_closest(&*tree, ray) {
31 println!("hit bounding volume of {:?} at point {:?}", v.value, p);
32 }
33 }
34}
35
36pub fn main() {
37 let mut world = World::new();
38 let mut sort = SpatialSortingSystem2::<f32, BodyPose2<f32>, ()>::new();
39 let mut collide =
40 SpatialCollisionSystem2::<f32, BodyPose2<f32>, ()>::new().with_narrow_phase(GJK2::new());
41 let mut raycast = RayCastSystem;
42 let mut impulse_solver = CurrentFrameUpdateSystem2::<f32, BodyPose2<f32>>::new();
43 let mut next_frame = NextFrameSetupSystem2::<f32, BodyPose2<f32>>::new();
44 let mut contact_resolution = ContactResolutionSystem2::<f32, BodyPose2<f32>>::new();
45
46 sort.setup(&mut world.res);
47 collide.setup(&mut world.res);
48 raycast.setup(&mut world.res);
49 impulse_solver.setup(&mut world.res);
50 next_frame.setup(&mut world.res);
51 contact_resolution.setup(&mut world.res);
52
53 world
54 .create_entity()
55 .with_static_physical_entity(
56 CollisionShape2::<f32, BodyPose2<f32>, ()>::new_simple(
57 CollisionStrategy::FullResolution,
58 CollisionMode::Discrete,
59 Rectangle::new(10., 10.).into(),
60 ),
61 BodyPose2::<f32>::one(),
62 PhysicalEntity::default(),
63 Mass2::new(1.),
64 ).build();
65
66 world
67 .create_entity()
68 .with_static_physical_entity(
69 CollisionShape2::<f32, BodyPose2<f32>, ()>::new_simple(
70 CollisionStrategy::FullResolution,
71 CollisionMode::Discrete,
72 Rectangle::new(10., 10.).into(),
73 ),
74 BodyPose2::<f32>::new(Point2::new(2., 2.), Rotation2::from_angle(Rad(0.))),
75 PhysicalEntity::default(),
76 Mass2::new(1.),
77 ).build();
78
79 let mut reader_1 = world
80 .write_resource::<EventChannel<ContactEvent2<f32>>>()
81 .register_reader();
82
83 {
84 use specs::prelude::RunNow;
85 sort.run_now(&world.res);
86 collide.run_now(&world.res);
87
88 println!(
89 "Contacts: {:?}",
90 world
91 .read_resource::<EventChannel<ContactEvent2<f32>>>()
92 .read(&mut reader_1)
93 .collect::<Vec<_>>()
94 );
95
96 raycast.run_now(&world.res);
97 impulse_solver.run_now(&world.res);
98 next_frame.run_now(&world.res);
99 contact_resolution.run_now(&world.res);
100 }
101}