Skip to content

Commit

Permalink
collider fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
kayhhh committed Sep 4, 2024
1 parent 3c9c411 commit 28c581d
Show file tree
Hide file tree
Showing 8 changed files with 111 additions and 53 deletions.
16 changes: 15 additions & 1 deletion crates/unavi-scripting/src/api/wired/physics/collider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ use crate::{
state::StoreState,
};

use super::bindings::wired::physics::types::{HostCollider, Shape};
use super::bindings::{
types::{ShapeCylinder, Vec3},
wired::physics::types::{HostCollider, Shape},
};

#[derive(Debug)]
pub struct Collider {
Expand All @@ -32,6 +35,17 @@ impl Collider {
ref_count: RefCountCell::default(),
}
}

/// Returns the equivalent Bevy component.
pub fn component(&self) -> avian3d::prelude::Collider {
match self.shape {
Shape::Cuboid(Vec3 { x, y, z }) => avian3d::prelude::Collider::cuboid(x, y, z),
Shape::Cylinder(ShapeCylinder { height, radius }) => {
avian3d::prelude::Collider::cylinder(radius, height)
}
Shape::Sphere(radius) => avian3d::prelude::Collider::sphere(radius),
}
}
}

impl HostCollider for StoreState {
Expand Down
9 changes: 9 additions & 0 deletions crates/unavi-scripting/src/api/wired/physics/rigid_body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,15 @@ impl RigidBody {
rigid_body_type,
}
}

/// Returns the equivalent Bevy component.
pub fn component(&self) -> avian3d::prelude::RigidBody {
match self.rigid_body_type {
RigidBodyType::Dynamic => avian3d::prelude::RigidBody::Dynamic,
RigidBodyType::Fixed => avian3d::prelude::RigidBody::Static,
RigidBodyType::Kinematic => avian3d::prelude::RigidBody::Kinematic,
}
}
}

impl RefCount for RigidBody {
Expand Down
82 changes: 57 additions & 25 deletions crates/unavi-scripting/src/api/wired/scene/gltf/node.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::cell::Cell;

use avian3d::prelude::MassPropertiesBundle;
use bevy::{
prelude::{Transform as BTransform, *},
utils::HashMap,
Expand All @@ -12,9 +13,12 @@ use crate::{
utils::{RefCount, RefCountCell, RefResource},
wired::{
input::{bindings::InputHandler, input_handler::InputHandlerSender},
math::bindings::types::{Transform, Vec3},
physics::bindings::types::{Collider, RigidBody, RigidBodyType, Shape, ShapeCylinder},
scene::bindings::node::{Host, HostNode},
math::bindings::types::Transform,
physics::bindings::types::{Collider, RigidBody},
scene::bindings::{
node::{Host, HostNode},
scene::Node,
},
},
},
state::{MaterialState, PrimitiveState, StoreState},
Expand Down Expand Up @@ -309,14 +313,25 @@ impl HostNode for StoreState {
let node = self.table.get_mut(&self_)?;
node.transform = value.into();

self.node_insert(
self_.rep(),
BTransform {
translation: value.translation.into(),
rotation: value.rotation.into(),
scale: value.scale.into(),
},
);
let mut transform = BTransform {
translation: value.translation.into(),
rotation: value.rotation.into(),
scale: value.scale.into(),
};

// parry3d (used in avian physics) panics when scale is 0
const ALMOST_ZERO: f32 = 10e-10;
if transform.scale.x == 0.0 {
transform.scale.x = ALMOST_ZERO;
}
if transform.scale.y == 0.0 {
transform.scale.y = ALMOST_ZERO;
}
if transform.scale.z == 0.0 {
transform.scale.z = ALMOST_ZERO;
}

self.node_insert(self_.rep(), transform);

Ok(())
}
Expand Down Expand Up @@ -346,21 +361,16 @@ impl HostNode for StoreState {
let collider = match &value {
Some(value) => {
let collider = self.table.get(value)?;
let collider = match collider.shape {
Shape::Cuboid(Vec3 { x, y, z }) => avian3d::prelude::Collider::cuboid(x, y, z),
Shape::Cylinder(ShapeCylinder { height, radius }) => {
avian3d::prelude::Collider::cylinder(radius, height)
}
Shape::Sphere(radius) => avian3d::prelude::Collider::sphere(radius),
};
Some(collider)
Some(collider.component())
}
None => None,
};

let node = self.table.get_mut(&self_)?;
node.collider = value;

compute_mass_properties(&self_, self)?;

self.node_insert_option(self_.rep(), collider);

Ok(())
Expand All @@ -385,19 +395,16 @@ impl HostNode for StoreState {
let rigid_body = match &value {
Some(value) => {
let rigid_body = self.table.get(value)?;
let rigid_body = match rigid_body.rigid_body_type {
RigidBodyType::Dynamic => avian3d::prelude::RigidBody::Dynamic,
RigidBodyType::Fixed => avian3d::prelude::RigidBody::Static,
RigidBodyType::Kinematic => avian3d::prelude::RigidBody::Kinematic,
};
Some(rigid_body)
Some(rigid_body.component())
}
None => None,
};

let node = self.table.get_mut(&self_)?;
node.rigid_body = value;

compute_mass_properties(&self_, self)?;

self.node_insert_option(self_.rep(), rigid_body);

Ok(())
Expand Down Expand Up @@ -457,6 +464,31 @@ impl HostNode for StoreState {

impl Host for StoreState {}

fn compute_mass_properties(
node_res: &Resource<Node>,
state: &mut StoreState,
) -> Result<(), ResourceTableError> {
let rep = node_res.rep();
let node = state.table.get(node_res)?;

if node.rigid_body.is_some() {
if let Some(collider) = &node.collider {
let collider = state.table.get(collider)?;

state.node_insert(
rep,
MassPropertiesBundle::new_computed(&collider.component(), 1.0),
);
} else {
state.node_insert(rep, MassPropertiesBundle::default());
}
} else {
state.node_remove::<avian3d::prelude::MassPropertiesBundle>(rep)
}

Ok(())
}

fn calc_global_transform(
transform: BTransform,
node: &NodeRes,
Expand Down
24 changes: 11 additions & 13 deletions crates/unavi-scripting/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,21 +74,9 @@ impl StoreState {
T::from_res(res, &self.table)
}

/// Inserts a component into the given node.
pub fn node_insert<T: Component>(&mut self, node: u32, value: T) {
let nodes = self.entities.nodes.clone();

self.commands.push(move |world: &mut World| {
let nodes = nodes.read().unwrap();
let entity = nodes.get(&node).unwrap();
let mut entity = world.entity_mut(*entity);
entity.insert(value);
});
}

/// Inserts a component into the given node if the value is `Some`.
/// If the value is `None`, removes the component from the entity.
pub fn node_insert_option<T: Component>(&mut self, node: u32, value: Option<T>) {
pub fn node_insert_option<T: Bundle>(&mut self, node: u32, value: Option<T>) {
let nodes = self.entities.nodes.clone();

self.commands.push(move |world: &mut World| {
Expand All @@ -103,6 +91,16 @@ impl StoreState {
}
});
}

/// Inserts a component into the given node.
pub fn node_insert<T: Bundle>(&mut self, node: u32, value: T) {
self.node_insert_option(node, Some(value))
}

/// Removes a component from the given node.
pub fn node_remove<T: Bundle>(&mut self, node: u32) {
self.node_insert_option::<T>(node, None)
}
}

#[derive(Default)]
Expand Down
5 changes: 0 additions & 5 deletions wasm/example-unavi-shapes/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,34 +19,29 @@ impl GuestScript for Script {

{
let cuboid = Cuboid::new(Vec3::new(1.0, 0.5, 1.5)).to_physics_node();
assert!(cuboid.collider().is_some());
cuboid.set_transform(Transform::from_translation(Vec3::new(3.0, 0.0, 0.0)));
scene.add_node(&cuboid);
}

{
let sphere = Sphere::new_ico(0.5).to_physics_node();
assert!(sphere.collider().is_some());
sphere.set_transform(Transform::from_translation(Vec3::new(1.5, 0.0, 2.0)));
scene.add_node(&sphere);
}

{
let sphere = Sphere::new_uv(0.5).to_physics_node();
assert!(sphere.collider().is_some());
sphere.set_transform(Transform::from_translation(Vec3::new(1.5, 0.0, 0.0)));
scene.add_node(&sphere);
}

{
let cylinder = Cylinder::new(0.5, 1.0).to_physics_node();
assert!(cylinder.collider().is_some());
scene.add_node(&cylinder);
}

{
let rectangle = Rectangle::new(Vec2::splat(1.0)).to_physics_node();
assert!(rectangle.collider().is_some());
rectangle.set_transform(Transform::from_translation(Vec3::new(-1.5, 0.0, 0.0)));
scene.add_node(&rectangle);
}
Expand Down
5 changes: 2 additions & 3 deletions wasm/test-wired-scene/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ mod scene;
mod wired_math_impls;
mod wired_scene_impls;

#[derive(Default)]
struct Script {}
struct Script;

impl GuestScript for Script {
fn new() -> Self {
Expand All @@ -24,7 +23,7 @@ impl GuestScript for Script {
node::test_node_api();
scene::test_scene_api();

Script::default()
Script
}

fn update(&self, _delta: f32) {
Expand Down
17 changes: 16 additions & 1 deletion wasm/test-wired-scene/src/node.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use crate::{
bindings::wired::{
log::api::{log, LogLevel},
physics::types::{Collider, RigidBodyType, Shape},
scene::{
gltf::Gltf,
mesh::Mesh,
node::{Node, Transform},
node::{Node, RigidBody, Transform},
},
},
panic_log,
Expand Down Expand Up @@ -106,4 +107,18 @@ pub fn test_node_api() {
);
panic_log(&err);
}

let collider = Collider::new(Shape::Sphere(0.5));
node.set_collider(Some(&collider));
assert!(node.collider().is_some());

let rigid_body = RigidBody::new(RigidBodyType::Dynamic);
node.set_rigid_body(Some(&rigid_body));
assert!(node.rigid_body().is_some());

node.set_collider(None);
assert!(node.collider().is_none());

node.set_rigid_body(None);
assert!(node.rigid_body().is_none());
}
6 changes: 1 addition & 5 deletions wasm/unavi-shapes/src/shapes/rectangle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ use crate::bindings::{
},
};

const COLLIDER_DEPTH: f32 = 0.0001;

pub struct Rectangle {
size: RefCell<Vec2>,
}
Expand Down Expand Up @@ -41,9 +39,7 @@ impl GuestRectangle for Rectangle {
let node = self.to_node();
let size = self.size();
node.set_collider(Some(&Collider::new(Shape::Cuboid(Vec3::new(
size.x,
size.y,
COLLIDER_DEPTH,
size.x, size.y, 0.0,
)))));
node
}
Expand Down

0 comments on commit 28c581d

Please sign in to comment.