diff --git a/Cargo.toml b/Cargo.toml index 2732ea6..b1e5e3a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ mint = "0.5.9" mio = {version = "0.8.3", features = ["net", "os-poll", "os-ext"]} nanoid = "0.4.0" parking_lot = "0.12.1" +portable-atomic = {version = "0.3.0", features = ["float", "std"]} rccell = "0.1.3" rustc-hash = "1.1.0" slab = "0.4.6" diff --git a/src/nodes/core.rs b/src/nodes/core.rs index 80954df..94b8647 100644 --- a/src/nodes/core.rs +++ b/src/nodes/core.rs @@ -26,8 +26,8 @@ pub struct Node<'a> { destroyable: bool, alias: Option>, - pub spatial: Option>, - pub field: Option>, + pub spatial: Option>, + pub field: Option>, pub pulse_sender: Option>, } diff --git a/src/nodes/field.rs b/src/nodes/field.rs index d6a9989..43d2a6f 100644 --- a/src/nodes/field.rs +++ b/src/nodes/field.rs @@ -5,10 +5,13 @@ use anyhow::{anyhow, ensure, Result}; use glam::{swizzles::*, vec2, vec3, vec3a, Mat4, Vec3, Vec3A}; use libstardustxr::fusion::flex::FlexBuffable; use libstardustxr::{flex_to_quat, flex_to_vec3}; +use parking_lot::Mutex; +use portable_atomic::AtomicF32; use rccell::RcCell; -use std::cell::Cell; use std::ops::Deref; use std::rc::Rc; +use std::sync::atomic::Ordering; +use std::sync::Arc; pub trait FieldTrait { fn local_distance(&self, p: Vec3A) -> f32; @@ -149,8 +152,8 @@ impl Deref for Field { } pub struct BoxField { - space: Rc, - size: Cell, + space: Arc, + size: Mutex, } impl BoxField { @@ -165,17 +168,17 @@ impl BoxField { ); let box_field = BoxField { space: node.borrow().spatial.as_ref().unwrap().clone(), - size: Cell::new(size), + size: Mutex::new(size), }; box_field.add_field_methods(node); node.borrow_mut() .add_local_signal("setSize", BoxField::set_size_flex); - node.borrow_mut().field = Some(Rc::new(Field::Box(box_field))); + node.borrow_mut().field = Some(Arc::new(Field::Box(box_field))); Ok(()) } pub fn set_size(&self, size: Vec3) { - self.size.set(size); + *self.size.lock() = size; } pub fn set_size_flex(node: &Node, _calling_client: Rc, data: &[u8]) -> Result<()> { @@ -194,7 +197,7 @@ impl BoxField { impl FieldTrait for BoxField { fn local_distance(&self, p: Vec3A) -> f32 { - let size = self.size.get(); + let size = self.size.lock(); let q = vec3( p.x.abs() - (size.x * 0.5_f32), p.y.abs() - (size.y * 0.5_f32), @@ -209,9 +212,9 @@ impl FieldTrait for BoxField { } pub struct CylinderField { - space: Rc, - length: Cell, - radius: Cell, + space: Arc, + length: AtomicF32, + radius: AtomicF32, } impl CylinderField { @@ -226,19 +229,19 @@ impl CylinderField { ); let cylinder_field = CylinderField { space: node.borrow().spatial.as_ref().unwrap().clone(), - length: Cell::new(length), - radius: Cell::new(radius), + length: AtomicF32::new(length), + radius: AtomicF32::new(radius), }; cylinder_field.add_field_methods(node); node.borrow_mut() .add_local_signal("setSize", CylinderField::set_size_flex); - node.borrow_mut().field = Some(Rc::new(Field::Cylinder(cylinder_field))); + node.borrow_mut().field = Some(Arc::new(Field::Cylinder(cylinder_field))); Ok(()) } pub fn set_size(&self, length: f32, radius: f32) { - self.length.set(length); - self.radius.set(radius); + self.length.store(length, Ordering::Relaxed); + self.radius.store(radius, Ordering::Relaxed); } pub fn set_size_flex(node: &Node, _calling_client: Rc, data: &[u8]) -> Result<()> { @@ -259,10 +262,8 @@ impl CylinderField { impl FieldTrait for CylinderField { fn local_distance(&self, p: Vec3A) -> f32 { - let d = vec2( - p.xy().length().abs() - self.radius.get(), - p.z.abs() - (self.length.get() * 0.5), - ); + let radius = self.length.load(Ordering::Relaxed); + let d = vec2(p.xy().length().abs() - radius, p.z.abs() - (radius * 0.5)); d.x.max(d.y).min(0_f32) + (if d.x >= 0_f32 && d.y >= 0_f32 { @@ -277,8 +278,8 @@ impl FieldTrait for CylinderField { } pub struct SphereField { - space: Rc, - radius: Cell, + space: Arc, + radius: AtomicF32, } impl SphereField { @@ -293,17 +294,17 @@ impl SphereField { ); let sphere_field = SphereField { space: node.borrow().spatial.as_ref().unwrap().clone(), - radius: Cell::new(radius), + radius: AtomicF32::new(radius), }; sphere_field.add_field_methods(node); node.borrow_mut() .add_local_signal("setRadius", SphereField::set_radius_flex); - node.borrow_mut().field = Some(Rc::new(Field::Sphere(sphere_field))); + node.borrow_mut().field = Some(Arc::new(Field::Sphere(sphere_field))); Ok(()) } pub fn set_radius(&self, radius: f32) { - self.radius.set(radius); + self.radius.store(radius, Ordering::Relaxed); } pub fn set_radius_flex(node: &Node, _calling_client: Rc, data: &[u8]) -> Result<()> { @@ -321,13 +322,13 @@ impl SphereField { impl FieldTrait for SphereField { fn local_distance(&self, p: Vec3A) -> f32 { - p.length() - self.radius.get() + p.length() - self.radius.load(Ordering::Relaxed) } fn local_normal(&self, p: Vec3A, _r: f32) -> Vec3A { -p.normalize() } fn local_closest_point(&self, p: Vec3A, _r: f32) -> Vec3A { - p.normalize() * self.radius.get() + p.normalize() * self.radius.load(Ordering::Relaxed) } fn spatial_ref(&self) -> &Spatial { self.space.as_ref() diff --git a/src/nodes/spatial.rs b/src/nodes/spatial.rs index 938749f..c607df8 100644 --- a/src/nodes/spatial.rs +++ b/src/nodes/spatial.rs @@ -5,38 +5,40 @@ use glam::{Mat4, Quat, Vec3}; use libstardustxr::flex::flexbuffer_from_vector_arguments; use libstardustxr::push_to_vec; use libstardustxr::{flex_to_quat, flex_to_vec3}; +use parking_lot::RwLock; use rccell::RcCell; -use std::cell::{Cell, RefCell}; +use std::cell::RefCell; use std::rc::Rc; +use std::sync::Arc; pub struct Spatial { // node: WeakCell>, - parent: RefCell>>, - transform: Cell, + parent: RwLock>>, + transform: RwLock, } impl Spatial { pub fn add_to( node: &RcCell, - parent: Option>, + parent: Option>, transform: Mat4, - ) -> Result> { + ) -> Result> { ensure!( node.borrow_mut().spatial.is_none(), "Internal: Node already has a Spatial aspect!" ); let spatial = Spatial { // node: node.downgrade(), - parent: RefCell::new(parent), - transform: Cell::new(transform), + parent: RwLock::new(parent), + transform: RwLock::new(transform), }; node.borrow_mut() .add_local_method("getTransform", Spatial::get_transform_flex); node.borrow_mut() .add_local_signal("setTransform", Spatial::set_transform_flex); - let spatial_rc = Rc::new(spatial); - node.borrow_mut().spatial = Some(spatial_rc.clone()); - Ok(spatial_rc) + let spatial_arc = Arc::new(spatial); + node.borrow_mut().spatial = Some(spatial_arc.clone()); + Ok(spatial_arc) } pub fn space_to_space_matrix(from: Option<&Spatial>, to: Option<&Spatial>) -> Mat4 { @@ -46,16 +48,16 @@ impl Spatial { } pub fn local_transform(&self) -> Mat4 { - self.transform.get() + *self.transform.read() } pub fn global_transform(&self) -> Mat4 { - match self.parent.borrow().clone() { - Some(value) => value.global_transform() * self.transform.get(), - None => self.transform.get(), + match self.parent.read().clone() { + Some(value) => value.global_transform() * *self.transform.read(), + None => *self.transform.read(), } } pub fn set_local_transform(&self, transform: Mat4) { - self.transform.set(transform); + *self.transform.write() = transform; } pub fn set_local_transform_components( &self, @@ -65,7 +67,7 @@ impl Spatial { scl: Option, ) { let reference_to_parent_transform = - Spatial::space_to_space_matrix(reference_space, self.parent.borrow().as_deref()); + Spatial::space_to_space_matrix(reference_space, self.parent.read().as_deref()); let mut local_transform_in_reference_space = reference_to_parent_transform.inverse() * self.local_transform(); let (mut reference_space_scl, mut reference_space_rot, mut reference_space_pos) =