extern crate nalgebra;
extern crate collisions;
use self::nalgebra::{Vector2, Vector3, Norm};
use self::collisions::collidable::{Collidable, CollidableShape};
#[derive(Clone, Debug)]
pub struct Physical
{
pub collidable: Collidable,
pub velocity: Vector2<f32>,
pub angular_velocity: f32,
pub centre_of_mass: Vector2<f32>,
pub restitution: f32,
pub inertia: f32,
}
#[derive(Clone, Debug)]
pub struct Resolution
{
pub trans_impulse_a: Vector2<f32>,
pub ang_impulse_a: f32,
pub trans_impulse_b: Vector2<f32>,
pub ang_impulse_b: f32,
}
pub fn resolve_poly_with_any(poly: &Physical, other: &Physical, face: usize, support: Vector2<f32>) -> Resolution
{
let relative_velocity = other.velocity - poly.velocity;
let normal = nalgebra::normalize(&Vector2::new(poly.collidable.normx[face], poly.collidable.normy[face]));
let velocity_along_normal = nalgebra::dot(&relative_velocity, &normal);
if velocity_along_normal <= 0.0 {
let e = poly.restitution * other.restitution;
let j = -(e + 1.0) * velocity_along_normal;
let poly_impulse = -normal * j * (other.inertia / (other.inertia + poly.inertia));
let poly_h = poly.centre_of_mass - support;
if poly_impulse.norm() > 0.0 && poly_h.norm() > 0.0
{
let poly_trans_impulse = poly_impulse * nalgebra::dot(&nalgebra::normalize(&poly_h), &nalgebra::normalize(&poly_impulse));
let poly_ha = nalgebra::normalize(&Vector3::new(poly_h.x, poly_h.y, 0.0));
let poly_ia = nalgebra::normalize(&Vector3::new(poly_impulse.x, poly_impulse.y, 0.0));
let poly_ang_impulse = -(nalgebra::cross(&poly_ha, &poly_ia)).z / poly_impulse.norm() / poly_h.norm();
let other_impulse = -normal * j * (poly.inertia / (poly.inertia + other.inertia));
let other_h = other.centre_of_mass - support;
if other_impulse.norm() > 0.0 && other_h.norm() > 0.0
{
let other_trans_impulse = other_impulse * nalgebra::dot(&nalgebra::normalize(&other_h), &nalgebra::normalize(&other_impulse));
let other_ha = nalgebra::normalize(&Vector3::new(other_h.x, other_h.y, 0.0));
let other_ia = nalgebra::normalize(&Vector3::new(other_impulse.x, other_impulse.y, 0.0));
let other_ang_impulse = -(nalgebra::cross(&other_ha, &other_ia)).z / other_impulse.norm() / other_h.norm();
return Resolution {
trans_impulse_a: poly_trans_impulse,
ang_impulse_a: poly_ang_impulse,
trans_impulse_b: other_trans_impulse,
ang_impulse_b: other_ang_impulse,
};
}
}
}
return Resolution {
trans_impulse_a: nalgebra::zero(),
ang_impulse_a: 0.0,
trans_impulse_b: nalgebra::zero(),
ang_impulse_b: 0.0,
}
}
pub fn resolve_circle_with_circle(a: &Physical, b: &Physical, face: usize, support: Vector2<f32>) -> Resolution
{
let relative_velocity = b.velocity - a.velocity;
let normal = nalgebra::normalize(&(b.centre_of_mass - a.centre_of_mass));
let velocity_along_normal = nalgebra::dot(&relative_velocity, &normal);
if velocity_along_normal <= 0.0 {
let e = a.restitution * b.restitution;
let j = -(e + 1.0) * velocity_along_normal;
let a_impulse = -normal * j * (b.inertia / (b.inertia + a.inertia));
let a_h = a.centre_of_mass - support;
let a_trans_impulse = a_impulse * nalgebra::dot(&nalgebra::normalize(&a_h), &nalgebra::normalize(&a_impulse));
let b_impulse = -normal * j * (a.inertia / (a.inertia + b.inertia));
let b_h = b.centre_of_mass - support;
let b_trans_impulse = b_impulse * nalgebra::dot(&nalgebra::normalize(&b_h), &nalgebra::normalize(&b_impulse));
Resolution {
trans_impulse_a: a_trans_impulse,
ang_impulse_a: 0.0,
trans_impulse_b: b_trans_impulse,
ang_impulse_b: 0.0,
}
}
else
{
Resolution {
trans_impulse_a: nalgebra::zero(),
ang_impulse_a: 0.0,
trans_impulse_b: nalgebra::zero(),
ang_impulse_b: 0.0,
}
}
}
#[test]
fn test_resolve_poly_with_any()
{
let a = Physical {
collidable: Collidable {
collidable_type: 2,
collidable_shape: CollidableShape::Polygon,
collidable_id: 0,
centrex: 0.0,
centrey: 0.0,
radius: 0.0,
nvert: 4,
vertx: vec![
15.0,
30.0,
30.0,
15.0
],
verty: vec![
-10.0,
-10.0,
15.0,
15.0
],
normx: vec![
0.0,
25.0,
0.0,
-25.0
],
normy: vec![
-15.0,
0.0,
15.0,
0.0
]
},
velocity: Vector2 {
x: 0.0,
y: 0.0
},
angular_velocity: 0.0,
centre_of_mass: Vector2 {
x: 15.0,
y: -10.0
} - (Vector2 {
x: 15.0,
y: 25.0
}/2.0),
restitution: 0.1,
inertia: 100000.0,
};
let b = Physical {
collidable: Collidable {
collidable_type: 1,
collidable_shape: CollidableShape::Circle,
collidable_id: 1,
centrex: 13.925043,
centrey: -0.6393018,
radius: 1.6666667,
nvert: 0,
vertx: vec![],
verty: vec![],
normx: vec![],
normy: vec![]
},
velocity: Vector2 {
x: -0.5088411,
y: -0.5892709
},
angular_velocity: 0.0,
centre_of_mass: Vector2 {
x: 13.925043,
y: -0.6393018
},
restitution: 0.1,
inertia: 1.6666667,
};
let face = 3;
let supp = Vector2 {
x: 15.0,
y: -0.6294794
};
let res = resolve_poly_with_any(&a, &b, face, supp);
println!("{:#?}", res);
}