commit 3e1c4906aa2f024e4e1bb5e1654f1131dcebb6dd
parent 12a2119f665af696f39da207c5dfc62fc2c01a50
Author: bamlin <b.amling@tarent.de>
Date: Fri, 31 May 2019 14:57:22 +0200
added gravity resource and system for synchronisation; the gravity resource is optional
Diffstat:
7 files changed, 136 insertions(+), 71 deletions(-)
diff --git a/Cargo.toml b/Cargo.toml
@@ -18,5 +18,5 @@ nphysics3d = "0.11.1"
simple_logger = "1.2.0"
[[example]]
-name = "example"
-path = "examples/main.rs"-
\ No newline at end of file
+name = "basic"
+path = "examples/basic.rs"+
\ No newline at end of file
diff --git a/examples/basic.rs b/examples/basic.rs
@@ -0,0 +1,63 @@
+extern crate log;
+extern crate simple_logger;
+
+use specs::{world::Builder, Component, DenseVecStorage, FlaggedStorage, World};
+use specs_physics::{
+ body::{BodyStatus, Position},
+ dispatcher,
+ PhysicsBodyBuilder,
+ PhysicsColliderBuilder,
+ Shape,
+};
+
+/// `Pos` struct for synchronisation of the position between the ECS and
+/// nphysics; this has to implement both `Component` and `Position`
+struct Pos {
+ x: f32,
+ y: f32,
+ z: f32,
+}
+
+impl Component for Pos {
+ type Storage = FlaggedStorage<Self, DenseVecStorage<Self>>;
+}
+
+impl Position<f32> for Pos {
+ fn position(&self) -> (f32, f32, f32) {
+ (self.x, self.y, self.z)
+ }
+
+ fn set_position(&mut self, x: f32, y: f32, z: f32) {
+ self.x = x;
+ self.y = y;
+ self.z = z;
+ }
+}
+
+fn main() {
+ // initialise the logger for system logs
+ simple_logger::init().unwrap();
+
+ // initialise the Specs world; this will contain our Resources and Entities
+ let mut world = World::new();
+
+ // create the dispatcher containing all relevant Systems; alternatively to using
+ // the convenience function you can add all required Systems by hand
+ let mut dispatcher = dispatcher::<f32, Pos>();
+ dispatcher.setup(&mut world.res);
+
+ // create an Entity containing the required Components
+ world
+ .create_entity()
+ .with(Pos {
+ x: 1.0,
+ y: 1.0,
+ z: 1.0,
+ })
+ .with(PhysicsBodyBuilder::<f32>::from(BodyStatus::Dynamic).build())
+ .with(PhysicsColliderBuilder::<f32>::from(Shape::Rectangle(1.0, 1.0, 1.0)).build())
+ .build();
+
+ // execute the dispatcher
+ dispatcher.dispatch(&world.res);
+}
diff --git a/examples/main.rs b/examples/main.rs
@@ -1,63 +0,0 @@
-extern crate log;
-extern crate simple_logger;
-
-use specs::{world::Builder, Component, DenseVecStorage, FlaggedStorage, World};
-use specs_physics::{
- body::{BodyStatus, Position},
- dispatcher,
- PhysicsBodyBuilder,
- PhysicsColliderBuilder,
- Shape,
-};
-
-/// `Pos` struct for synchronisation of the position between the ECS and
-/// nphysics; this has to implement both `Component` and `Position`
-struct Pos {
- x: f32,
- y: f32,
- z: f32,
-}
-
-impl Component for Pos {
- type Storage = FlaggedStorage<Self, DenseVecStorage<Self>>;
-}
-
-impl Position<f32> for Pos {
- fn position(&self) -> (f32, f32, f32) {
- (self.x, self.y, self.z)
- }
-
- fn set_position(&mut self, x: f32, y: f32, z: f32) {
- self.x = x;
- self.y = y;
- self.z = z;
- }
-}
-
-fn main() {
- // initialise the logger for system logs
- simple_logger::init().unwrap();
-
- // initialise the Specs world; this will contain our Resources and Entities
- let mut world = World::new();
-
- // create the dispatcher containing all relevant Systems; alternatively to using
- // the convenience function you can add all required Systems by hand
- let mut dispatcher = dispatcher::<f32, Pos>();
- dispatcher.setup(&mut world.res);
-
- // create an Entity containing the required Components
- world
- .create_entity()
- .with(Pos {
- x: 1.0,
- y: 1.0,
- z: 1.0,
- })
- .with(PhysicsBodyBuilder::<f32>::from(BodyStatus::Static).build())
- .with(PhysicsColliderBuilder::<f32>::from(Shape::Rectangle(1.0, 1.0, 1.0)).build())
- .build();
-
- // execute the dispatcher
- dispatcher.dispatch(&world.res);
-}
diff --git a/src/body.rs b/src/body.rs
@@ -71,7 +71,7 @@ impl<N: RealField> From<BodyStatus> for PhysicsBodyBuilder<N> {
Self {
gravity_enabled: false,
body_status,
- velocity: Vector3::new(N::zero(), N::zero(), N::zero()),
+ velocity: Vector3::repeat(N::zero()),
angular_inertia: Matrix3::zeros(),
mass: N::from_f32(1.2).unwrap(),
local_center_of_mass: Point3::new(N::zero(), N::zero(), N::zero()),
diff --git a/src/lib.rs b/src/lib.rs
@@ -6,7 +6,7 @@ extern crate nphysics3d as nphysics;
use std::collections::HashMap;
pub use nalgebra as math;
-use nalgebra::RealField;
+use nalgebra::{RealField, Scalar};
use nphysics::{
object::{BodyHandle, ColliderHandle},
world::World,
@@ -26,6 +26,7 @@ use self::{
systems::{
sync_bodies_to_physics::SyncBodiesToPhysicsSystem,
sync_colliders_to_physics::SyncCollidersToPhysicsSystem,
+ sync_gravity_to_physics::SyncGravityToPhysicsSystem,
},
};
@@ -54,9 +55,17 @@ impl<N: RealField> Default for Physics<N> {
}
}
-/// `Gravity` is a type alias for `Vector3<f32>`. It represents a constant
-/// acceleration affecting all physical objects in the scene.
-pub type Gravity<N> = Vector3<N>;
+///// `Gravity` is a type alias for `Vector3`. It represents a constant
+///// acceleration affecting all physical objects in the scene.
+//pub type Gravity<N> = Vector3<N>;
+
+pub struct Gravity<N: RealField + Scalar>(Vector3<N>);
+
+impl<N: RealField + Scalar> Default for Gravity<N> {
+ fn default() -> Self {
+ Self(Vector3::repeat(N::zero()))
+ }
+}
/// The `PhysicsParent` `Component` is used to represent a parent/child
/// relationship between physics based `Entity`s.
@@ -101,5 +110,14 @@ where
&["sync_bodies_to_physics_system"],
);
+ // add SyncGravityToPhysicsSystem; this System can be added at any point in time
+ // as it merely handles the gravity value of the nphysics World, thus it has no
+ // other dependencies
+ dispatcher_builder.add(
+ SyncGravityToPhysicsSystem::<N>::default(),
+ "sync_gravity_to_physics_system",
+ &[],
+ );
+
dispatcher_builder.build()
}
diff --git a/src/systems/mod.rs b/src/systems/mod.rs
@@ -10,6 +10,7 @@ use std::ops::Deref;
pub mod sync_bodies_to_physics;
pub mod sync_colliders_to_physics;
+pub mod sync_gravity_to_physics;
/// Iterated over the `ComponentEvent::Inserted`s of a given, tracked `Storage`
/// and returns the results in a `BitSet`.
diff --git a/src/systems/sync_gravity_to_physics.rs b/src/systems/sync_gravity_to_physics.rs
@@ -0,0 +1,46 @@
+use nalgebra::RealField;
+use specs::{Read, Resources, System, SystemData, WriteExpect};
+
+use crate::{Gravity, Physics};
+use std::marker::PhantomData;
+
+/// The `SyncGravityToPhysicsSystem` synchronises the `Gravity` values with the
+/// nphysics `World`s gravity. This way the gravity can be affected on demand.
+///
+/// The `Gravity` `Resource` is treated as *optional* and needs to be registered
+/// in order to change affect the `World`s gravity.
+pub struct SyncGravityToPhysicsSystem<N> {
+ n_marker: PhantomData<N>,
+}
+
+impl<'s, N: RealField> System<'s> for SyncGravityToPhysicsSystem<N> {
+ type SystemData = (Option<Read<'s, Gravity<N>>>, WriteExpect<'s, Physics<N>>);
+
+ fn run(&mut self, data: Self::SystemData) {
+ let (gravity, mut physics) = data;
+
+ // if a Gravity resource exists, synchronise its values with the nphysics World
+ if let Some(gravity) = gravity {
+ physics.world.set_gravity(gravity.0);
+ }
+ }
+
+ fn setup(&mut self, res: &mut Resources) {
+ info!("SyncGravityToPhysicsSystem.setup");
+ Self::SystemData::setup(res);
+
+ // initialise required resources
+ res.entry::<Physics<N>>().or_insert_with(Physics::default);
+ }
+}
+
+impl<N> Default for SyncGravityToPhysicsSystem<N>
+where
+ N: RealField,
+{
+ fn default() -> Self {
+ Self {
+ n_marker: PhantomData,
+ }
+ }
+}