Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use isometry for position trait instead of three dimensional vector #4

Merged
merged 2 commits into from
Jun 13, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 14 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,31 +34,29 @@ All `System`s and `Component`s provided by this crate require between one and tw

`N: RealField` - [nphysics](https://www.nphysics.org/) is built upon [nalgebra](https://nalgebra.org/) and uses various types and structures from this crate. **specs-physics** builds up on this even further and utilises the same structures, which all work with any type that implements `nalgebra::RealField`. `nalgebra::RealField` is by default implemented for various standard types, such as `f32` and`f64`. `nalgebra` is re-exported under `specs_physics::math`.

`P: Component<Storage = FlaggedStorage<P, DenseVecStorage<P>>> + Position<N> + Send + Sync` - a more complex type parameter which looks a bit intimidating at first but ultimately just requires a `Component`, that also implements the `specs_physics::bodies::Position` *trait* and uses a `FlaggedStorage`. This `Position` `Component` is used to initially place a [RigidBody](https://www.nphysics.org/rigid_body_simulations_with_contacts/#rigid-bodies) in the [nphysics](https://www.nphysics.org/) world and later used to synchronise the updated positions of these bodies back into the [Specs](https://slide-rs.github.io/specs/) world.
`P: Position<N>` - a type parameter which implements the `specs_physics::bodies::Position` *trait*, requiring also a `Component` implementation with a `FlaggedStorage`. This `Position` `Component` is used to initially place a [RigidBody](https://www.nphysics.org/rigid_body_simulations_with_contacts/#rigid-bodies) in the [nphysics](https://www.nphysics.org/) world and later used to synchronise the updated translation and rotation of these bodies back into the [Specs](https://slide-rs.github.io/specs/) world.

Example for a `Position` `Component`:
Example for a `Position` `Component`, simply using the "Isometry" type (aka combined translation and rotation structure) directly:
```rust
use specs_physics::bodies::Position;
use specs::{Component, DenseVecStorage, FlaggedStorage};
use specs_physics::{
bodies::Position,
math::Isometry3,
};

struct Pos {
x: f32,
y: f32,
z: f32,
}
struct Position(Isometry3<f32>);

impl Component for Pos {
impl Component for Position {
type Storage = FlaggedStorage<Self, DenseVecStorage<Self>>;
}

impl Position<f32> for Pos {
fn position(&self) -> (f32, f32, f32) {
(self.x, self.y, self.z)
impl Position<f32> for Position {
fn as_isometry(&self) -> Isometry3<f32> {
self.0
}

fn set_position(&mut self, x: f32, y: f32, z: f32) {
self.x = x;
self.y = y;
self.z = z;
fn set_isometry(&mut self, isometry: &Isometry3<f32>) {
self.0 = isometry;
}
}
```
Expand Down
28 changes: 15 additions & 13 deletions examples/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,32 +5,34 @@ use specs::{world::Builder, Component, DenseVecStorage, FlaggedStorage, World};
use specs_physics::{
bodies::{BodyStatus, Position},
colliders::Shape,
math::Isometry3,
physics_dispatcher,
PhysicsBodyBuilder,
PhysicsColliderBuilder,
};

/// `Pos` struct for synchronisation of the position between the ECS and
/// nphysics; this has to implement both `Component` and `Position`
struct Pos {
/// `SimpleTranslation` struct for synchronisation of the position between the
/// ECS and nphysics; this has to implement both `Component` and `Position`
struct SimpleTranslation {
x: f32,
y: f32,
z: f32,
}

impl Component for Pos {
impl Component for SimpleTranslation {
type Storage = FlaggedStorage<Self, DenseVecStorage<Self>>;
}

impl Position<f32> for Pos {
fn position(&self) -> (f32, f32, f32) {
(self.x, self.y, self.z)
impl Position<f32> for SimpleTranslation {
fn as_isometry(&self) -> Isometry3<f32> {
Isometry3::translation(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 set_isometry(&mut self, isometry: &Isometry3<f32>) {
let translation = isometry.translation.vector;
self.x = translation.x;
self.y = translation.y;
self.z = translation.z;
}
}

Expand All @@ -43,13 +45,13 @@ fn main() {

// create the dispatcher containing all relevant Systems; alternatively to using
// the convenience function you can add all required Systems by hand
let mut dispatcher = physics_dispatcher::<f32, Pos>();
let mut dispatcher = physics_dispatcher::<f32, SimpleTranslation>();
dispatcher.setup(&mut world.res);

// create an Entity containing the required Components
world
.create_entity()
.with(Pos {
.with(SimpleTranslation {
x: 1.0,
y: 1.0,
z: 1.0,
Expand Down
39 changes: 20 additions & 19 deletions examples/collision.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,38 @@
extern crate log;
extern crate simple_logger;

use nalgebra::Vector3;
use specs::{world::Builder, Component, DenseVecStorage, FlaggedStorage, World};
use specs_physics::{
bodies::{BodyStatus, Position},
colliders::Shape,
math::{Isometry3, Vector3},
physics_dispatcher,
PhysicsBodyBuilder,
PhysicsColliderBuilder,
};

/// `Pos` struct for synchronisation of the position between the ECS and
/// nphysics; this has to implement both `Component` and `Position`
struct Pos {
/// `SimpleTranslation` struct for synchronisation of the position between the
/// ECS and nphysics; this has to implement both `Component` and `Position`
struct SimpleTranslation {
x: f32,
y: f32,
z: f32,
}

impl Component for Pos {
impl Component for SimpleTranslation {
type Storage = FlaggedStorage<Self, DenseVecStorage<Self>>;
}

impl Position<f32> for Pos {
fn position(&self) -> (f32, f32, f32) {
(self.x, self.y, self.z)
impl Position<f32> for SimpleTranslation {
fn as_isometry(&self) -> Isometry3<f32> {
Isometry3::translation(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 set_isometry(&mut self, isometry: &Isometry3<f32>) {
let translation = isometry.translation.vector;
self.x = translation.x;
self.y = translation.y;
self.z = translation.z;
}
}

Expand All @@ -45,13 +46,13 @@ fn main() {

// create the dispatcher containing all relevant Systems; alternatively to using
// the convenience function you can add all required Systems by hand
let mut dispatcher = physics_dispatcher::<f32, Pos>();
let mut dispatcher = physics_dispatcher::<f32, SimpleTranslation>();
dispatcher.setup(&mut world.res);

// create an Entity with a dynamic PhysicsBody component and a velocity
let entity = world
.create_entity()
.with(Pos {
.with(SimpleTranslation {
x: 1.0,
y: 1.0,
z: 1.0,
Expand All @@ -68,7 +69,7 @@ fn main() {
// one
world
.create_entity()
.with(Pos {
.with(SimpleTranslation {
x: 3.0,
y: 1.0,
z: 1.0,
Expand All @@ -80,10 +81,10 @@ fn main() {
// execute the dispatcher
dispatcher.dispatch(&world.res);

// fetch the Pos resource for the Entity with the dynamic body; the position
// should still be approx. there same
let positions = world.read_storage::<Pos>();
let pos = positions.get(entity).unwrap();
// fetch the translation component for the Entity with the dynamic body; the
// position should still be approx the same
let pos_storage = world.read_storage::<SimpleTranslation>();
let pos = pos_storage.get(entity).unwrap();

info!("updated position: x={}, y={}, z={},", pos.x, pos.y, pos.z);
}
31 changes: 16 additions & 15 deletions examples/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,39 @@
extern crate log;
extern crate simple_logger;

use nalgebra::Vector3;
use specs::{world::Builder, Component, DenseVecStorage, FlaggedStorage, World};
use specs_physics::{
bodies::{BodyStatus, Position},
colliders::Shape,
events::ContactEvents,
math::{Isometry3, Vector3},
physics_dispatcher,
PhysicsBodyBuilder,
PhysicsColliderBuilder,
};

/// `Pos` struct for synchronisation of the position between the ECS and
/// nphysics; this has to implement both `Component` and `Position`
struct Pos {
/// `SimpleTranslation` struct for synchronisation of the position between the
/// ECS and nphysics; this has to implement both `Component` and `Position`
struct SimpleTranslation {
x: f32,
y: f32,
z: f32,
}

impl Component for Pos {
impl Component for SimpleTranslation {
type Storage = FlaggedStorage<Self, DenseVecStorage<Self>>;
}

impl Position<f32> for Pos {
fn position(&self) -> (f32, f32, f32) {
(self.x, self.y, self.z)
impl Position<f32> for SimpleTranslation {
fn as_isometry(&self) -> Isometry3<f32> {
Isometry3::translation(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 set_isometry(&mut self, isometry: &Isometry3<f32>) {
let translation = isometry.translation.vector;
self.x = translation.x;
self.y = translation.y;
self.z = translation.z;
}
}

Expand All @@ -46,14 +47,14 @@ fn main() {

// create the dispatcher containing all relevant Systems; alternatively to using
// the convenience function you can add all required Systems by hand
let mut dispatcher = physics_dispatcher::<f32, Pos>();
let mut dispatcher = physics_dispatcher::<f32, SimpleTranslation>();
dispatcher.setup(&mut world.res);
let mut contact_event_reader = world.res.fetch_mut::<ContactEvents>().register_reader();

// create an Entity with a dynamic PhysicsBody component and a velocity
world
.create_entity()
.with(Pos {
.with(SimpleTranslation {
x: 1.0,
y: 1.0,
z: 1.0,
Expand All @@ -70,7 +71,7 @@ fn main() {
// one
world
.create_entity()
.with(Pos {
.with(SimpleTranslation {
x: 3.0,
y: 1.0,
z: 1.0,
Expand Down
30 changes: 16 additions & 14 deletions examples/hierarchy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,33 +5,35 @@ use specs::{world::Builder, Component, DenseVecStorage, FlaggedStorage, World};
use specs_physics::{
bodies::{BodyStatus, Position},
colliders::Shape,
math::Isometry3,
physics_dispatcher,
PhysicsBodyBuilder,
PhysicsColliderBuilder,
PhysicsParent,
};

/// `Pos` struct for synchronisation of the position between the ECS and
/// nphysics; this has to implement both `Component` and `Position`
struct Pos {
/// `SimpleTranslation` struct for synchronisation of the position between the
/// ECS and nphysics; this has to implement both `Component` and `Position`
struct SimpleTranslation {
x: f32,
y: f32,
z: f32,
}

impl Component for Pos {
impl Component for SimpleTranslation {
type Storage = FlaggedStorage<Self, DenseVecStorage<Self>>;
}

impl Position<f32> for Pos {
fn position(&self) -> (f32, f32, f32) {
(self.x, self.y, self.z)
impl Position<f32> for SimpleTranslation {
fn as_isometry(&self) -> Isometry3<f32> {
Isometry3::translation(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 set_isometry(&mut self, isometry: &Isometry3<f32>) {
let translation = isometry.translation.vector;
self.x = translation.x;
self.y = translation.y;
self.z = translation.z;
}
}

Expand All @@ -44,14 +46,14 @@ fn main() {

// create the dispatcher containing all relevant Systems; alternatively to using
// the convenience function you can add all required Systems by hand
let mut dispatcher = physics_dispatcher::<f32, Pos>();
let mut dispatcher = physics_dispatcher::<f32, SimpleTranslation>();
dispatcher.setup(&mut world.res);

// create an Entity containing the required Components; this Entity will be the
// parent
let parent = world
.create_entity()
.with(Pos {
.with(SimpleTranslation {
x: 1.0,
y: 1.0,
z: 1.0,
Expand All @@ -66,7 +68,7 @@ fn main() {
// collider will be attached to the parent
let _child = world
.create_entity()
.with(Pos {
.with(SimpleTranslation {
x: 1.0,
y: 1.0,
z: 1.0,
Expand Down
Loading