feat: field
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
use super::field::Field;
|
||||
use crate::core::client::Client;
|
||||
use crate::nodes::spatial::Spatial;
|
||||
use anyhow::{anyhow, Result};
|
||||
@@ -16,6 +17,7 @@ pub struct Node<'a> {
|
||||
destroyable: bool,
|
||||
|
||||
pub spatial: Option<Rc<Spatial>>,
|
||||
pub field: Option<Rc<Box<dyn Field>>>,
|
||||
}
|
||||
|
||||
impl<'a> Node<'a> {
|
||||
@@ -44,6 +46,7 @@ impl<'a> Node<'a> {
|
||||
local_methods: HashMap::new(),
|
||||
destroyable,
|
||||
spatial: None,
|
||||
field: None,
|
||||
};
|
||||
node.add_local_signal("destroy", Node::destroy_flex);
|
||||
node
|
||||
|
||||
140
src/nodes/field.rs
Normal file
140
src/nodes/field.rs
Normal file
@@ -0,0 +1,140 @@
|
||||
use super::core::Node;
|
||||
use super::spatial::Spatial;
|
||||
use anyhow::{anyhow, ensure, Result};
|
||||
use glam::{vec2, vec3a, Vec3, Vec3A};
|
||||
use libstardustxr::flex_to_vec3;
|
||||
use libstardustxr::fusion::flex::FlexBuffable;
|
||||
use rccell::RcCell;
|
||||
use std::boxed::Box;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub trait Field {
|
||||
fn local_distance(&self, p: Vec3A) -> f32;
|
||||
fn local_normal(&self, p: Vec3A, r: f32) -> Vec3A {
|
||||
let d = self.local_distance(p);
|
||||
let e = vec2(r, 0_f32);
|
||||
|
||||
let n = vec3a(d, d, d)
|
||||
- vec3a(
|
||||
self.local_distance(vec3a(e.x, e.y, e.y)),
|
||||
self.local_distance(vec3a(e.y, e.x, e.y)),
|
||||
self.local_distance(vec3a(e.y, e.y, e.x)),
|
||||
);
|
||||
|
||||
n.normalize()
|
||||
}
|
||||
fn local_closest_point(&self, p: Vec3A, r: f32) -> Vec3A {
|
||||
p - (self.local_normal(p, r) * self.local_distance(p))
|
||||
}
|
||||
|
||||
fn distance(&self, local_space: &Spatial, reference_space: &Spatial, p: Vec3A) -> f32 {
|
||||
let reference_to_local_space =
|
||||
Spatial::space_to_space_matrix(Some(reference_space), Some(local_space));
|
||||
let local_p = reference_to_local_space.transform_point3a(p);
|
||||
self.local_distance(local_p)
|
||||
}
|
||||
fn normal(&self, local_space: &Spatial, reference_space: &Spatial, p: Vec3A, r: f32) -> Vec3A {
|
||||
let reference_to_local_space =
|
||||
Spatial::space_to_space_matrix(Some(reference_space), Some(local_space));
|
||||
let local_p = reference_to_local_space.transform_point3a(p);
|
||||
reference_to_local_space
|
||||
.inverse()
|
||||
.transform_vector3a(self.local_normal(local_p, r))
|
||||
}
|
||||
fn closest_point(
|
||||
&self,
|
||||
local_space: &Spatial,
|
||||
reference_space: &Spatial,
|
||||
p: Vec3A,
|
||||
r: f32,
|
||||
) -> Vec3A {
|
||||
let reference_to_local_space =
|
||||
Spatial::space_to_space_matrix(Some(reference_space), Some(local_space));
|
||||
let local_p = reference_to_local_space.transform_point3a(p);
|
||||
reference_to_local_space
|
||||
.inverse()
|
||||
.transform_point3a(self.local_closest_point(local_p, r))
|
||||
}
|
||||
|
||||
fn add_field_methods(&self, node: &RcCell<Node>) {
|
||||
node.borrow_mut()
|
||||
.add_local_method("distance", |node, calling_client, data| {
|
||||
let root = flexbuffers::Reader::get_root(data)?;
|
||||
let flex_vec = root.get_vector()?;
|
||||
let reference_space_path = flex_vec.idx(0).as_str();
|
||||
let reference_space = calling_client
|
||||
.get_scenegraph()
|
||||
.get_node(reference_space_path)
|
||||
.ok_or_else(|| anyhow!("Reference space node does not exist"))?
|
||||
.borrow()
|
||||
.spatial
|
||||
.as_ref()
|
||||
.ok_or_else(|| anyhow!("Reference space node does not have a spatial"))?
|
||||
.clone();
|
||||
let point =
|
||||
flex_to_vec3!(flex_vec.idx(1)).ok_or_else(|| anyhow!("Point is invalid"))?;
|
||||
|
||||
let field = node
|
||||
.field
|
||||
.as_ref()
|
||||
.ok_or_else(|| anyhow!("Node does not have a field!"))?;
|
||||
let spatial = field.spatial_ref();
|
||||
let distance = field.distance(spatial, reference_space.as_ref(), point.into());
|
||||
Ok(FlexBuffable::from(distance).build_singleton())
|
||||
});
|
||||
node.borrow_mut()
|
||||
.add_local_method("normal", |node, calling_client, data| {
|
||||
let root = flexbuffers::Reader::get_root(data)?;
|
||||
let flex_vec = root.get_vector()?;
|
||||
let reference_space_path = flex_vec.idx(0).as_str();
|
||||
let reference_space = calling_client
|
||||
.get_scenegraph()
|
||||
.get_node(reference_space_path)
|
||||
.ok_or_else(|| anyhow!("Reference space node does not exist"))?
|
||||
.borrow()
|
||||
.spatial
|
||||
.as_ref()
|
||||
.ok_or_else(|| anyhow!("Reference space node does not have a spatial"))?
|
||||
.clone();
|
||||
let point =
|
||||
flex_to_vec3!(flex_vec.idx(1)).ok_or_else(|| anyhow!("Point is invalid"))?;
|
||||
|
||||
let field = node
|
||||
.field
|
||||
.as_ref()
|
||||
.ok_or_else(|| anyhow!("Node does not have a field!"))?;
|
||||
let spatial = field.spatial_ref();
|
||||
let normal =
|
||||
field.normal(spatial, reference_space.as_ref(), point.into(), 0.001_f32);
|
||||
Ok(FlexBuffable::from(mint::Vector3::from(normal)).build_singleton())
|
||||
});
|
||||
node.borrow_mut()
|
||||
.add_local_method("closest_point", |node, calling_client, data| {
|
||||
let root = flexbuffers::Reader::get_root(data)?;
|
||||
let flex_vec = root.get_vector()?;
|
||||
let reference_space_path = flex_vec.idx(0).as_str();
|
||||
let reference_space = calling_client
|
||||
.get_scenegraph()
|
||||
.get_node(reference_space_path)
|
||||
.ok_or_else(|| anyhow!("Reference space node does not exist"))?
|
||||
.borrow()
|
||||
.spatial
|
||||
.as_ref()
|
||||
.ok_or_else(|| anyhow!("Reference space node does not have a spatial"))?
|
||||
.clone();
|
||||
let point =
|
||||
flex_to_vec3!(flex_vec.idx(1)).ok_or_else(|| anyhow!("Point is invalid"))?;
|
||||
|
||||
let field = node
|
||||
.field
|
||||
.as_ref()
|
||||
.ok_or_else(|| anyhow!("Node does not have a field!"))?;
|
||||
let spatial = field.spatial_ref();
|
||||
let closest_point =
|
||||
field.closest_point(spatial, reference_space.as_ref(), point.into(), 0.001_f32);
|
||||
Ok(FlexBuffable::from(mint::Vector3::from(closest_point)).build_singleton())
|
||||
});
|
||||
}
|
||||
|
||||
fn spatial_ref(&self) -> &Spatial;
|
||||
}
|
||||
@@ -1,2 +1,3 @@
|
||||
pub mod core;
|
||||
pub mod field;
|
||||
pub mod spatial;
|
||||
|
||||
Reference in New Issue
Block a user