specs-physics

[Fork] Integration of Amethyst, SPECS and Nphysics together.
git clone https://git.jojolepro.com/specs-physics.git
Log | Files | Refs | README | LICENSE

commit 92b485cc45e09497376eff04ceddf1f47dd6ecfc
parent a75bfa674cfc78b79319643b7274165bd01d4aa6
Author: kel <distransient@protonmail.com>
Date:   Sun, 16 Dec 2018 18:58:57 -0500

Switch to property-based force application.

Diffstat:
Mexamples/amethyst.rs | 3+--
Msrc/bodies.rs | 5++++-
Dsrc/forces.rs | 113-------------------------------------------------------------------------------
Msrc/lib.rs | 1-
Msrc/systems/mod.rs | 27+++------------------------
Msrc/systems/sync_bodies_to_physics.rs | 2++
Dsrc/systems/sync_force_generators_to_physics.rs | 49-------------------------------------------------
7 files changed, 10 insertions(+), 190 deletions(-)

diff --git a/examples/amethyst.rs b/examples/amethyst.rs @@ -9,7 +9,6 @@ use amethyst::renderer::{ }; use amethyst::{Application, GameData, GameDataBuilder, SimpleState, StateData}; use nphysics_ecs_dumb::bodies::DynamicBody; -use nphysics_ecs_dumb::forces::DefaultForceGenerators; use nphysics_ecs_dumb::nphysics::math::{Point, Velocity}; use nphysics_ecs_dumb::systems::PhysicsBundle; use num_traits::identities::One; @@ -111,7 +110,7 @@ fn main() -> amethyst::Result<()> { let game_data = GameDataBuilder::default() .with_bundle(TransformBundle::new())? .with_bundle( - PhysicsBundle::<DefaultForceGenerators>::new().with_dep(&["transform_system"]), + PhysicsBundle::new().with_dep(&["transform_system"]), )? .with_bundle(RenderBundle::new(pipe, Some(display_config)))?; diff --git a/src/bodies.rs b/src/bodies.rs @@ -1,7 +1,7 @@ use amethyst::ecs::world::Index; use amethyst::ecs::{Component, FlaggedStorage}; use nalgebra::Matrix3; -use nphysics3d::math::{Point, Velocity}; +use nphysics3d::math::{Point, Velocity, Force}; use nphysics3d::object::BodyHandle; use std::collections::HashMap; @@ -37,6 +37,7 @@ impl DynamicBody { mass, angular_mass, center_of_mass, + external_forces: Force::<f32>::zero(), }) } @@ -63,6 +64,8 @@ pub struct RigidPhysicsBody { pub mass: f32, pub angular_mass: Matrix3<f32>, pub center_of_mass: Point<f32>, + + pub external_forces: Force<f32>, } /// Multipart physics body, for use in `PhysicsBody` Component. Not implemented yet. diff --git a/src/forces.rs b/src/forces.rs @@ -1,113 +0,0 @@ -use crate::bodies::DynamicsBodyRelations; -use amethyst::core::approx::AbsDiffEq; -use amethyst::ecs::{BitSet, Component, FlaggedStorage}; -use nalgebra::Unit; -use nphysics3d::force_generator::ForceGenerator; -use nphysics3d::math::{Force, Point, Vector, Velocity}; -use nphysics3d::object::{BodyHandle, BodySet}; -use nphysics3d::solver::IntegrationParameters; - -pub trait ForceGenerators: Default + Send + Sync { - type LocalForceGenerators: LocalForceGenerators; - type LinkedForceGenerators: LinkedForceGenerators; -} - -pub trait LocalForceGenerators: - ForceGenerator<f32> + Component<Storage = FlaggedStorage<Self>> -{ -} - -pub trait LinkedForceGenerators: - ForceGenerator<f32> + Component<Storage = FlaggedStorage<Self>> -{ - fn affected_bodies(&self) -> DynamicsBodyRelations; // TODO this signature is definitely wrong. -} - -#[derive(Default)] -pub struct DefaultForceGenerators; - -impl ForceGenerators for DefaultForceGenerators { - type LocalForceGenerators = DefaultLocalForceGenerators; - type LinkedForceGenerators = DefaultLinkedForceGenerators; -} - -pub enum DefaultLocalForceGenerators { - ConstantAcceleration(ConstantAcceleration), -} - -pub struct ConstantAcceleration { - pub acceleration: Velocity<f32>, -} - -impl Component for DefaultLocalForceGenerators { - type Storage = FlaggedStorage<Self>; -} - -impl ForceGenerator<f32> for DefaultLocalForceGenerators { - fn apply(&mut self, _: &IntegrationParameters<f32>, _bodies: &mut BodySet<f32>) -> bool { - false - } -} - -impl LocalForceGenerators for DefaultLocalForceGenerators {} - -pub enum DefaultLinkedForceGenerators { - Spring(Spring), -} - -pub struct Spring { - pub length: f32, - pub stiffness: f32, - pub anchor1: Point<f32>, - pub anchor2: Point<f32>, - pub handle1: BodyHandle, - pub handle2: BodyHandle, - pub links: BitSet, -} - -impl Component for DefaultLinkedForceGenerators { - type Storage = FlaggedStorage<Self>; -} - -impl LinkedForceGenerators for DefaultLinkedForceGenerators { - fn affected_bodies(&self) -> DynamicsBodyRelations { - DynamicsBodyRelations::new() - // match self { - // DefaultLinkedForceGenerators::Spring(x) => x.links - // } - } -} - -impl ForceGenerator<f32> for DefaultLinkedForceGenerators { - fn apply(&mut self, _: &IntegrationParameters<f32>, bodies: &mut BodySet<f32>) -> bool { - match self { - DefaultLinkedForceGenerators::Spring(spring) => { - if !bodies.contains(spring.handle1) || !bodies.contains(spring.handle2) { - return false; - } - - let anchor1 = bodies.body_part(spring.handle1).position() * spring.anchor1; - let anchor2 = bodies.body_part(spring.handle2).position() * spring.anchor2; - - let force_dir; - let delta_length; - - if let Some((dir, length)) = - Unit::try_new_and_get(anchor2 - anchor1, f32::default_epsilon()) - { - force_dir = dir; - delta_length = length - spring.length; - } else { - force_dir = Vector::y_axis(); - delta_length = -spring.length; - } - - let force = Force::linear(force_dir.as_ref() * delta_length * spring.stiffness); - bodies.body_part_mut(spring.handle1).apply_force(&force); - bodies.body_part_mut(spring.handle2).apply_force(&-force); - - true - } - } - } -} diff --git a/src/lib.rs b/src/lib.rs @@ -4,7 +4,6 @@ pub extern crate nphysics3d as nphysics; extern crate num_traits; pub mod bodies; -pub mod forces; pub mod systems; pub type World = self::nphysics::world::World<f32>; diff --git a/src/systems/mod.rs b/src/systems/mod.rs @@ -1,42 +1,30 @@ mod physics_stepper; mod sync_bodies_from_physics; mod sync_bodies_to_physics; -mod sync_force_generators_to_physics; mod sync_gravity_to_physics; -use crate::forces::ForceGenerators; use amethyst::core::bundle::{Result, SystemBundle}; use amethyst::core::specs::DispatcherBuilder; -use core::marker::PhantomData; pub use self::physics_stepper::PhysicsStepperSystem; pub use self::sync_bodies_from_physics::SyncBodiesFromPhysicsSystem; pub use self::sync_bodies_to_physics::SyncBodiesToPhysicsSystem; -pub use self::sync_force_generators_to_physics::SyncForceGeneratorsToPhysicsSystem; pub use self::sync_gravity_to_physics::SyncGravityToPhysicsSystem; // TODO: Implement contact events, use Entity id's instead of nphysics handles. // contact_events.iter_write(physical_world.contact_events()); -pub const SYNC_FORCE_GENERATORS_TO_PHYSICS_SYSTEM: &str = "sync_force_generators_to_physics_system"; pub const SYNC_BODIES_TO_PHYSICS_SYSTEM: &str = "sync_bodies_to_physics_system"; pub const SYNC_GRAVITY_TO_PHYSICS_SYSTEM: &str = "sync_gravity_to_physics_system"; pub const PHYSICS_STEPPER_SYSTEM: &str = "physics_stepper_system"; pub const SYNC_BODIES_FROM_PHYSICS_SYSTEM: &str = "sync_bodies_from_physics_system"; #[derive(Default)] -pub struct PhysicsBundle<'a, F> -where - F: ForceGenerators, -{ +pub struct PhysicsBundle<'a> { dep: &'a [&'a str], - phantom_force_generators: PhantomData<F>, } -impl<'a, F> PhysicsBundle<'a, F> -where - F: ForceGenerators, -{ +impl<'a> PhysicsBundle<'a> { pub fn new() -> Self { Default::default() } @@ -47,17 +35,9 @@ where } } -impl<'a, 'b, 'c, F: 'a> SystemBundle<'a, 'b> for PhysicsBundle<'c, F> -where - F: ForceGenerators, -{ +impl<'a, 'b, 'c> SystemBundle<'a, 'b> for PhysicsBundle<'c> { fn build(self, builder: &mut DispatcherBuilder<'a, 'b>) -> Result<()> { builder.add( - SyncForceGeneratorsToPhysicsSystem::<F>::new(), - SYNC_FORCE_GENERATORS_TO_PHYSICS_SYSTEM, - self.dep, - ); - builder.add( SyncBodiesToPhysicsSystem::new(), SYNC_BODIES_TO_PHYSICS_SYSTEM, self.dep, @@ -72,7 +52,6 @@ where PhysicsStepperSystem::new(), PHYSICS_STEPPER_SYSTEM, &[ - SYNC_FORCE_GENERATORS_TO_PHYSICS_SYSTEM, SYNC_BODIES_TO_PHYSICS_SYSTEM, SYNC_GRAVITY_TO_PHYSICS_SYSTEM, ], diff --git a/src/systems/sync_bodies_to_physics.rs b/src/systems/sync_bodies_to_physics.rs @@ -97,6 +97,7 @@ impl<'a> System<'a> for SyncBodiesToPhysicsSystem { .unwrap(); physical_body.set_velocity(rigid_body.velocity); + physical_body.apply_force(&rigid_body.external_forces); } DynamicBody::Multibody(_) => { // TODO @@ -112,6 +113,7 @@ impl<'a> System<'a> for SyncBodiesToPhysicsSystem { physical_body.set_position(try_convert(transform.0).unwrap()); physical_body.set_velocity(rigid_body.velocity); + physical_body.apply_force(&rigid_body.external_forces); // if you changed the mass properties at all... too bad! } diff --git a/src/systems/sync_force_generators_to_physics.rs b/src/systems/sync_force_generators_to_physics.rs @@ -1,49 +0,0 @@ -use crate::forces::{DefaultForceGenerators, ForceGenerators}; -use crate::World; -use amethyst::ecs::{ReadStorage, System, Write, WriteExpect}; -use amethyst::shrev::EventChannel; -use core::marker::PhantomData; -use ncollide3d::events::ContactEvent; - -// TODO: Synchronize force generators, tidy up api. - -pub struct SyncForceGeneratorsToPhysicsSystem<F = DefaultForceGenerators> -where - F: ForceGenerators, -{ - phantom_force_generators: PhantomData<F>, -} - -impl<F> SyncForceGeneratorsToPhysicsSystem<F> -where - F: ForceGenerators, -{ - pub fn new() -> Self { - Default::default() - } -} - -impl<F> Default for SyncForceGeneratorsToPhysicsSystem<F> -where - F: ForceGenerators, -{ - fn default() -> Self { - SyncForceGeneratorsToPhysicsSystem::<F> { - phantom_force_generators: PhantomData, - } - } -} - -impl<'a, F> System<'a> for SyncForceGeneratorsToPhysicsSystem<F> -where - F: ForceGenerators, -{ - type SystemData = ( - WriteExpect<'a, World>, - Write<'a, EventChannel<ContactEvent>>, - ReadStorage<'a, F::LocalForceGenerators>, - ReadStorage<'a, F::LinkedForceGenerators>, - ); - - fn run(&mut self, _data: Self::SystemData) {} -}