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:
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) {}
-}