Skip to content

Commit

Permalink
Attempt at force generators
Browse files Browse the repository at this point in the history
  • Loading branch information
distransient committed Dec 16, 2018
1 parent beb2c22 commit 17e6fb9
Show file tree
Hide file tree
Showing 2 changed files with 145 additions and 15 deletions.
63 changes: 56 additions & 7 deletions src/forces.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ 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::force_generator::{ForceGenerator, ForceGeneratorHandle};
use nphysics3d::math::{Force, Point, Vector, Velocity};
use nphysics3d::object::{BodyHandle, BodySet};
use nphysics3d::solver::IntegrationParameters;
Expand All @@ -12,17 +12,23 @@ pub trait ForceGenerators: Default + Send + Sync {
type LinkedForceGenerators: LinkedForceGenerators;
}

pub trait LocalForceGenerators:
ForceGenerator<f32> + Component<Storage = FlaggedStorage<Self>>
{
}
pub trait LocalForceGenerators: ForceGeneratorComponent { }

pub trait LinkedForceGenerators:
ForceGenerator<f32> + Component<Storage = FlaggedStorage<Self>>
pub trait LinkedForceGenerators: ForceGeneratorComponent
{
fn affected_bodies(&self) -> DynamicsBodyRelations; // TODO this signature is definitely wrong.
}

pub trait ForceGeneratorComponent: ForceGenerator<f32> + HasForceGeneratorHandle + Component<Storage = FlaggedStorage<Self>> {

}

pub trait HasForceGeneratorHandle {
fn set_handle(&mut self, handle: ForceGeneratorHandle);

fn get_handle(&self) -> Option<ForceGeneratorHandle>;
}

#[derive(Default)]
pub struct DefaultForceGenerators;

Expand All @@ -37,6 +43,7 @@ pub enum DefaultLocalForceGenerators {

pub struct ConstantAcceleration {
pub acceleration: Velocity<f32>,
pub handle: Option<ForceGeneratorHandle>,
}

impl Component for DefaultLocalForceGenerators {
Expand All @@ -50,6 +57,25 @@ impl ForceGenerator<f32> for DefaultLocalForceGenerators {
}

impl LocalForceGenerators for DefaultLocalForceGenerators {}
impl ForceGeneratorComponent for DefaultLocalForceGenerators {}

impl HasForceGeneratorHandle for DefaultLocalForceGenerators {
fn set_handle(&mut self, handle: ForceGeneratorHandle) {
match self {
DefaultLocalForceGenerators::ConstantAcceleration(ref mut constant_acceleration) => {
constant_acceleration.handle = Some(handle);
}
}
}

fn get_handle(&self) -> Option<ForceGeneratorHandle> {
match self {
DefaultLocalForceGenerators::ConstantAcceleration(ref constant_acceleration) => {
constant_acceleration.handle
}
}
}
}

pub enum DefaultLinkedForceGenerators {
Spring(Spring),
Expand All @@ -63,6 +89,7 @@ pub struct Spring {
pub handle1: BodyHandle,
pub handle2: BodyHandle,
pub links: BitSet,
pub handle: Option<ForceGeneratorHandle>,
}

impl Component for DefaultLinkedForceGenerators {
Expand All @@ -78,6 +105,10 @@ impl LinkedForceGenerators for DefaultLinkedForceGenerators {
}
}

impl ForceGeneratorComponent for DefaultLinkedForceGenerators {

}

impl ForceGenerator<f32> for DefaultLinkedForceGenerators {
fn apply(&mut self, _: &IntegrationParameters<f32>, bodies: &mut BodySet<f32>) -> bool {
match self {
Expand Down Expand Up @@ -111,3 +142,21 @@ impl ForceGenerator<f32> for DefaultLinkedForceGenerators {
}
}
}

impl HasForceGeneratorHandle for DefaultLinkedForceGenerators {
fn set_handle(&mut self, handle: ForceGeneratorHandle) {
match self {
DefaultLinkedForceGenerators::Spring(ref mut spring) => {
spring.handle = Some(handle);
}
}
}

fn get_handle(&self) -> Option<ForceGeneratorHandle> {
match self {
DefaultLinkedForceGenerators::Spring(ref spring) => {
spring.handle
}
}
}
}
97 changes: 89 additions & 8 deletions src/systems/sync_force_generators_to_physics.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
use crate::forces::{DefaultForceGenerators, ForceGenerators};
use crate::forces::{DefaultForceGenerators, ForceGenerators, ForceGeneratorComponent};
use crate::World;
use amethyst::ecs::{ReadStorage, System, Write, WriteExpect};
use amethyst::shrev::EventChannel;
use amethyst::ecs::{System, WriteExpect, ReaderId, Entities, Tracked, Storage, SystemData, Resources, WriteStorage};
use amethyst::ecs::storage::{ComponentEvent, MaskedStorage};
use core::marker::PhantomData;
use ncollide3d::events::ContactEvent;
use core::ops::Deref;

// TODO: Synchronize force generators, tidy up api.

pub struct SyncForceGeneratorsToPhysicsSystem<F = DefaultForceGenerators>
where
F: ForceGenerators,
{
local_generators_reader_id: Option<ReaderId<ComponentEvent>>,
linked_generators_reader_id: Option<ReaderId<ComponentEvent>>,

phantom_force_generators: PhantomData<F>,
}

Expand All @@ -29,6 +32,8 @@ where
{
fn default() -> Self {
SyncForceGeneratorsToPhysicsSystem::<F> {
local_generators_reader_id: None,
linked_generators_reader_id: None,
phantom_force_generators: PhantomData,
}
}
Expand All @@ -39,11 +44,87 @@ where
F: ForceGenerators,
{
type SystemData = (
Entities<'a>,
WriteExpect<'a, World>,
Write<'a, EventChannel<ContactEvent>>,
ReadStorage<'a, F::LocalForceGenerators>,
ReadStorage<'a, F::LinkedForceGenerators>,
WriteStorage<'a, F::LocalForceGenerators>,
WriteStorage<'a, F::LinkedForceGenerators>,
);

fn run(&mut self, _data: Self::SystemData) {}
fn run(&mut self, data: Self::SystemData) {
let (
entities,
mut physics_world,
mut local_force_generators,
mut linked_force_generators,
) = data;

iterate_events(
&local_force_generators,
self.local_generators_reader_id.as_mut().unwrap(),
&mut physics_world,
&entities);

iterate_events(
&linked_force_generators,
self.linked_generators_reader_id.as_mut().unwrap(),
&mut physics_world,
&entities);
}

fn setup(&mut self, res: &mut Resources) {
Self::SystemData::setup(res);

let mut local_generator_storage: WriteStorage<'_, F::LocalForceGenerators> = SystemData::fetch(&res);
self.local_generators_reader_id = Some(local_generator_storage.register_reader());

let mut linked_generator_storage: WriteStorage<'_, F::LinkedForceGenerators> = SystemData::fetch(&res);
self.linked_generators_reader_id = Some(linked_generator_storage.register_reader());
}
}

fn iterate_events<'a, T, D>(
tracked_storage: &Storage<'_, T, D>,
reader: &mut ReaderId<ComponentEvent>,
world: &mut World,
entities: &Entities<'_>,
) where
T: ForceGeneratorComponent,
T::Storage: Tracked,
D: Deref<Target = MaskedStorage<T>>,
{
let events = tracked_storage.channel().read(reader);

for event in events {
match event {
ComponentEvent::Modified(id) => { /* Do nothing */ },
ComponentEvent::Inserted(id) => {
match tracked_storage.get(entities.entity(*id)) {
Some(ref mut component) => {
let handle = world.add_force_generator(**component);
component.set_handle(handle);
},
None => {
// TODO: Log missing body
}
}
},
ComponentEvent::Removed(id) => {
match tracked_storage.get(entities.entity(*id)) {
Some(body) => {
match body.get_handle() {
Some(handle) => {
world.remove_force_generator(handle);
}
None => {
// TODO: Log missing handle
}
};
}
None => {
// TODO: Log missing body
}
};
}
};
}
}

0 comments on commit 17e6fb9

Please sign in to comment.