Skip to content

Commit

Permalink
feat(fields): use new field ref and field types
Browse files Browse the repository at this point in the history
  • Loading branch information
technobaboo committed Jun 21, 2024
1 parent eba317a commit 02bf210
Show file tree
Hide file tree
Showing 20 changed files with 193 additions and 387 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 7 additions & 1 deletion codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,11 @@ fn generate_handler(member: &Member) -> TokenStream {
quote!(let (#argument_names): (#argument_types) = stardust_xr::schemas::flex::deserialize(_message.as_ref())?;)
})
.unwrap_or_default();
let serialize = generate_argument_serialize(
"result",
&member.return_type.clone().unwrap_or(ArgumentType::Empty),
false,
);
let argument_uses = member
.arguments
.iter()
Expand All @@ -399,7 +404,8 @@ fn generate_handler(member: &Member) -> TokenStream {
node.add_local_method(#opcode, |_node, _calling_client, _message, _method_response| {
_method_response.wrap_async(async move {
#deserialize
Ok((Self::#member_name_ident(_node, _calling_client.clone(), #argument_uses).await?, Vec::new()))
let result = Self::#member_name_ident(_node, _calling_client.clone(), #argument_uses).await?;
Ok((#serialize, Vec::new()))
});
});
},
Expand Down
2 changes: 1 addition & 1 deletion src/nodes/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ impl PulseSender {
.get_aspect::<PulseReceiver>()
.unwrap()
.field
.spatial_ref()
.spatial
.node()
.unwrap(),
&tx_client,
Expand Down
241 changes: 119 additions & 122 deletions src/nodes/fields/mod.rs → src/nodes/fields.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,4 @@
pub mod r#box;
mod cylinder;
mod sphere;
mod torus;

use self::cylinder::CylinderField;
use self::r#box::BoxField;
use self::sphere::SphereField;
use self::torus::TorusField;

use super::alias::AliasInfo;
use super::alias::{Alias, AliasInfo};
use super::spatial::{
Spatial, SPATIAL_REF_GET_LOCAL_BOUNDING_BOX_SERVER_OPCODE,
SPATIAL_REF_GET_RELATIVE_BOUNDING_BOX_SERVER_OPCODE, SPATIAL_REF_GET_TRANSFORM_SERVER_OPCODE,
Expand All @@ -19,11 +9,12 @@ use crate::create_interface;
use crate::nodes::spatial::Transform;
use crate::nodes::spatial::SPATIAL_ASPECT_ALIAS_INFO;
use crate::nodes::spatial::SPATIAL_REF_ASPECT_ALIAS_INFO;
use color_eyre::eyre::Result;
use glam::{vec2, vec3a, Mat4, Vec3, Vec3A};
use mint::Vector3;
use color_eyre::eyre::{OptionExt, Result};
use glam::{vec2, vec3, vec3a, Vec3, Vec3A, Vec3Swizzles};
use once_cell::sync::Lazy;
use std::ops::Deref;
use parking_lot::Mutex;
use rustc_hash::FxHashMap;
use stardust_xr::values::Vector3;
use std::sync::Arc;

// TODO: get SDFs working properly with non-uniform scale and so on, output distance relative to the spatial it's compared against
Expand All @@ -33,16 +24,20 @@ pub static FIELD_ALIAS_INFO: Lazy<AliasInfo> = Lazy::new(|| AliasInfo {
SPATIAL_REF_GET_TRANSFORM_SERVER_OPCODE,
SPATIAL_REF_GET_LOCAL_BOUNDING_BOX_SERVER_OPCODE,
SPATIAL_REF_GET_RELATIVE_BOUNDING_BOX_SERVER_OPCODE,
FIELD_DISTANCE_SERVER_OPCODE,
FIELD_NORMAL_SERVER_OPCODE,
FIELD_CLOSEST_POINT_SERVER_OPCODE,
FIELD_RAY_MARCH_SERVER_OPCODE,
FIELD_REF_DISTANCE_SERVER_OPCODE,
FIELD_REF_NORMAL_SERVER_OPCODE,
FIELD_REF_CLOSEST_POINT_SERVER_OPCODE,
FIELD_REF_RAY_MARCH_SERVER_OPCODE,
],
..Default::default()
});

stardust_xr_server_codegen::codegen_field_protocol!();

lazy_static::lazy_static! {
pub static ref EXPORTED_FIELDS: Mutex<FxHashMap<u64, Arc<Node>>> = Mutex::new(FxHashMap::default());
}

pub trait FieldTrait: Send + Sync + 'static {
fn spatial_ref(&self) -> &Spatial;

Expand Down Expand Up @@ -122,167 +117,169 @@ pub trait FieldTrait: Send + Sync + 'static {
result
}
}
impl<Fi: FieldTrait + 'static> FieldAspect for Fi {

pub struct Ray {
pub origin: Vec3,
pub direction: Vec3,
pub space: Arc<Spatial>,
}

// const MIN_RAY_STEPS: u32 = 0;
const MAX_RAY_STEPS: u32 = 1000;

const MIN_RAY_MARCH: f32 = 0.001_f32;
const MAX_RAY_MARCH: f32 = f32::MAX;

// const MIN_RAY_LENGTH: f32 = 0_f32;
const MAX_RAY_LENGTH: f32 = 1000_f32;

pub struct Field {
pub spatial: Arc<Spatial>,
pub shape: Mutex<Shape>,
}
impl Field {
pub fn add_to(node: &Arc<Node>, shape: Shape) -> Result<()> {
let spatial = node.get_aspect::<Spatial>()?;
let field = Field {
spatial,
shape: Mutex::new(shape),
};
node.add_aspect(field);
Ok(())
}
}
impl Aspect for Field {
const NAME: &'static str = "Field";
}
impl FieldRefAspect for Field {
async fn distance(
node: Arc<Node>,
_calling_client: Arc<Client>,
space: Arc<Node>,
point: mint::Vector3<f32>,
point: Vector3<f32>,
) -> Result<f32> {
let reference_space = space.get_aspect::<Spatial>()?;
let this_field = node.get_aspect::<Field>()?;
Ok((*this_field).distance(reference_space.as_ref(), point.into()))
let field = node.get_aspect::<Field>()?;
Ok(field.distance(&reference_space, point.into()).into())
}

async fn normal(
node: Arc<Node>,
_calling_client: Arc<Client>,
space: Arc<Node>,
point: mint::Vector3<f32>,
point: Vector3<f32>,
) -> Result<Vector3<f32>> {
let reference_space = space.get_aspect::<Spatial>()?;
let this_field = node.get_aspect::<Field>()?;
Ok(this_field
.normal(reference_space.as_ref(), point.into(), 0.001)
.into())
let field = node.get_aspect::<Field>()?;
Ok(field.normal(&reference_space, point.into(), 0.0001).into())
}

async fn closest_point(
node: Arc<Node>,
_calling_client: Arc<Client>,
space: Arc<Node>,
point: mint::Vector3<f32>,
point: Vector3<f32>,
) -> Result<Vector3<f32>> {
let reference_space = space.get_aspect::<Spatial>()?;
let this_field = node.get_aspect::<Field>()?;
Ok(this_field
.closest_point(reference_space.as_ref(), point.into(), 0.001)
let field = node.get_aspect::<Field>()?;
Ok(field
.closest_point(&reference_space, point.into(), 0.0001)
.into())
}

async fn ray_march(
node: Arc<Node>,
_calling_client: Arc<Client>,
space: Arc<Node>,
ray_origin: mint::Vector3<f32>,
ray_direction: mint::Vector3<f32>,
ray_origin: Vector3<f32>,
ray_direction: Vector3<f32>,
) -> Result<RayMarchResult> {
let reference_space = space.get_aspect::<Spatial>()?;
let this_field = node.get_aspect::<Field>()?;
Ok(this_field.ray_march(Ray {
let space = space.get_aspect::<Spatial>()?;
let field = node.get_aspect::<Field>()?;
Ok(field.ray_march(Ray {
origin: ray_origin.into(),
direction: ray_direction.into(),
space: reference_space.clone(),
space,
}))
}
}
impl FieldAspect for Field {
fn set_shape(node: Arc<Node>, _calling_client: Arc<Client>, shape: Shape) -> Result<()> {
let field = node.get_aspect::<Field>()?;
*field.shape.lock() = shape;
Ok(())
}

pub struct Ray {
pub origin: Vec3,
pub direction: Vec3,
pub space: Arc<Spatial>,
}

// const MIN_RAY_STEPS: u32 = 0;
const MAX_RAY_STEPS: u32 = 1000;

const MIN_RAY_MARCH: f32 = 0.001_f32;
const MAX_RAY_MARCH: f32 = f32::MAX;

// const MIN_RAY_LENGTH: f32 = 0_f32;
const MAX_RAY_LENGTH: f32 = 1000_f32;

pub enum Field {
Box(BoxField),
Cylinder(CylinderField),
Sphere(SphereField),
Torus(TorusField),
}
impl Aspect for Field {
const NAME: &'static str = "Field";
async fn export_field(node: Arc<Node>, _calling_client: Arc<Client>) -> Result<u64> {
let id = rand::random();
EXPORTED_FIELDS.lock().insert(id, node);
Ok(id)
}
}
impl Deref for Field {
type Target = dyn FieldTrait;
fn deref(&self) -> &Self::Target {
match self {
Field::Box(field) => field,
Field::Cylinder(field) => field,
Field::Sphere(field) => field,
Field::Torus(field) => field,
impl FieldTrait for Field {
fn spatial_ref(&self) -> &Spatial {
&self.spatial
}
fn local_distance(&self, p: Vec3A) -> f32 {
match self.shape.lock().clone() {
Shape::Box(size) => {
let q = vec3(
p.x.abs() - (size.x * 0.5_f32),
p.y.abs() - (size.y * 0.5_f32),
p.z.abs() - (size.z * 0.5_f32),
);
let v = vec3a(q.x.max(0_f32), q.y.max(0_f32), q.z.max(0_f32));
v.length() + q.x.max(q.y.max(q.z)).min(0_f32)
}
Shape::Cylinder(CylinderShape { length, radius }) => {
let d = vec2(p.xy().length().abs() - radius, p.z.abs() - (length * 0.5));
d.x.max(d.y).min(0.0) + d.max(vec2(0.0, 0.0)).length()
}
Shape::Sphere(radius) => p.length() - radius,
Shape::Torus(TorusShape { radius_a, radius_b }) => {
let q = vec2(p.xz().length() - radius_a, p.y);
q.length() - radius_b
}
}
}
}

create_interface!(FieldInterface);
pub struct FieldInterface;
impl InterfaceAspect for FieldInterface {
fn create_box_field(
async fn import_field_ref(
_node: Arc<Node>,
calling_client: Arc<Client>,
id: u64,
parent: Arc<Node>,
transform: Transform,
size: mint::Vector3<f32>,
) -> Result<()> {
let transform = transform.to_mat4(true, true, false);
let parent = parent.get_aspect::<Spatial>()?;
let node = Node::from_id(&calling_client, id, true).add_to_scenegraph()?;
Spatial::add_to(&node, Some(parent.clone()), transform, false);
BoxField::add_to(&node, size);
Ok(())
}

fn create_cylinder_field(
_node: Arc<Node>,
calling_client: Arc<Client>,
id: u64,
parent: Arc<Node>,
transform: Transform,
length: f32,
radius: f32,
) -> Result<()> {
let transform = transform.to_mat4(true, true, false);
let parent = parent.get_aspect::<Spatial>()?;
let node = Node::from_id(&calling_client, id, true).add_to_scenegraph()?;
Spatial::add_to(&node, Some(parent.clone()), transform, false);
CylinderField::add_to(&node, length, radius);
Ok(())
}

fn create_sphere_field(
_node: Arc<Node>,
calling_client: Arc<Client>,
id: u64,
parent: Arc<Node>,
position: mint::Vector3<f32>,
radius: f32,
) -> Result<()> {
let parent = parent.get_aspect::<Spatial>()?;
let node = Node::from_id(&calling_client, id, true).add_to_scenegraph()?;
Spatial::add_to(
&node,
Some(parent.clone()),
Mat4::from_translation(position.into()),
false,
);
SphereField::add_to(&node, radius);
Ok(())
uid: u64,
) -> Result<Arc<Node>> {
EXPORTED_FIELDS
.lock()
.get(&uid)
.map(|s| {
Alias::create(
s,
&calling_client,
FIELD_REF_ASPECT_ALIAS_INFO.clone(),
None,
)
.unwrap()
})
.ok_or_eyre("Couldn't find spatial with that ID")
}

fn create_torus_field(
fn create_field(
_node: Arc<Node>,
calling_client: Arc<Client>,
id: u64,
parent: Arc<Node>,
transform: Transform,
radius_a: f32,
radius_b: f32,
shape: Shape,
) -> Result<()> {
let transform = transform.to_mat4(true, true, false);
let parent = parent.get_aspect::<Spatial>()?;
let node = Node::from_id(&calling_client, id, true).add_to_scenegraph()?;
Spatial::add_to(&node, Some(parent.clone()), transform, false);
TorusField::add_to(&node, radius_a, radius_b);
Field::add_to(&node, shape)?;
Ok(())
}
}
Loading

0 comments on commit 02bf210

Please sign in to comment.