feat: spatial bounds
This commit is contained in:
@@ -14,7 +14,7 @@ use prisma::{Flatten, Lerp, Rgba};
|
|||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use stardust_xr::{schemas::flex::deserialize, values::Transform};
|
use stardust_xr::{schemas::flex::deserialize, values::Transform};
|
||||||
use std::{collections::VecDeque, sync::Arc};
|
use std::{collections::VecDeque, sync::Arc};
|
||||||
use stereokit::{Color128, LinePoint as SkLinePoint, StereoKitDraw};
|
use stereokit::{bounds_grow_to_fit_pt, Bounds, Color128, LinePoint as SkLinePoint, StereoKitDraw};
|
||||||
|
|
||||||
use super::Drawable;
|
use super::Drawable;
|
||||||
|
|
||||||
@@ -45,6 +45,16 @@ impl Lines {
|
|||||||
"Internal: Node already has a drawable attached!"
|
"Internal: Node already has a drawable attached!"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let _ = node.spatial.get().unwrap().bounding_box_calc.set(|node| {
|
||||||
|
let mut bounds = Bounds::default();
|
||||||
|
let Some(Drawable::Lines(lines)) = node.drawable.get() else {return bounds};
|
||||||
|
for point in &lines.data.lock().points {
|
||||||
|
bounds = bounds_grow_to_fit_pt(bounds, point.point);
|
||||||
|
}
|
||||||
|
|
||||||
|
bounds
|
||||||
|
});
|
||||||
|
|
||||||
let lines = LINES_REGISTRY.add(Lines {
|
let lines = LINES_REGISTRY.add(Lines {
|
||||||
enabled: node.enabled.clone(),
|
enabled: node.enabled.clone(),
|
||||||
space: node.get_aspect("Lines", "spatial", |n| &n.spatial)?.clone(),
|
space: node.get_aspect("Lines", "spatial", |n| &n.spatial)?.clone(),
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ use std::path::PathBuf;
|
|||||||
use std::sync::{Arc, Weak};
|
use std::sync::{Arc, Weak};
|
||||||
use stereokit::named_colors::WHITE;
|
use stereokit::named_colors::WHITE;
|
||||||
use stereokit::{
|
use stereokit::{
|
||||||
Color128, Material, Model as SKModel, RenderLayer, Shader, StereoKitDraw, StereoKitMultiThread,
|
Bounds, Color128, Material, Model as SKModel, RenderLayer, Shader, StereoKitDraw,
|
||||||
|
StereoKitMultiThread,
|
||||||
};
|
};
|
||||||
|
|
||||||
static MODEL_REGISTRY: Registry<Model> = Registry::new();
|
static MODEL_REGISTRY: Registry<Model> = Registry::new();
|
||||||
@@ -182,6 +183,16 @@ impl ModelPart {
|
|||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
.ok()?;
|
.ok()?;
|
||||||
|
|
||||||
|
let _ = node.spatial.get().unwrap().bounding_box_calc.set(|node| {
|
||||||
|
let Some(Drawable::ModelPart(model_part)) = node.drawable.get() else {return Bounds::default()};
|
||||||
|
let Some(sk) = SK_MULTITHREAD.get() else {return Bounds::default()};
|
||||||
|
let Some(model) = model_part.model.upgrade() else {return Bounds::default()};
|
||||||
|
let Some(sk_model) = model.sk_model.get() else {return Bounds::default()};
|
||||||
|
let Some(sk_mesh) = sk.model_node_get_mesh(sk_model, model_part.id) else {return Bounds::default()};
|
||||||
|
sk.mesh_get_bounds(sk_mesh)
|
||||||
|
});
|
||||||
|
|
||||||
let model_part = Arc::new(ModelPart {
|
let model_part = Arc::new(ModelPart {
|
||||||
id,
|
id,
|
||||||
path: part_path,
|
path: part_path,
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ pub fn make_alias(client: &Arc<Client>) -> Result<Arc<Node>> {
|
|||||||
"hmd",
|
"hmd",
|
||||||
&HMD,
|
&HMD,
|
||||||
AliasInfo {
|
AliasInfo {
|
||||||
server_signals: vec!["get_transform"],
|
server_signals: vec!["get_bounds", "get_transform"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ use std::sync::{Arc, Weak};
|
|||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref ITEM_ALIAS_LOCAL_SIGNALS: Vec<&'static str> = vec![
|
static ref ITEM_ALIAS_LOCAL_SIGNALS: Vec<&'static str> = vec![
|
||||||
|
"get_bounds",
|
||||||
"get_transform",
|
"get_transform",
|
||||||
"set_transform",
|
"set_transform",
|
||||||
"set_spatial_parent",
|
"set_spatial_parent",
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ use stardust_xr::schemas::flex::{deserialize, serialize};
|
|||||||
use stardust_xr::values::Transform;
|
use stardust_xr::values::Transform;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::sync::{Arc, Weak};
|
use std::sync::{Arc, OnceLock, Weak};
|
||||||
|
use stereokit::{bounds_grow_to_fit_box, Bounds};
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
|
|
||||||
static ZONEABLE_REGISTRY: Registry<Spatial> = Registry::new();
|
static ZONEABLE_REGISTRY: Registry<Spatial> = Registry::new();
|
||||||
@@ -28,6 +29,7 @@ pub struct Spatial {
|
|||||||
pub(super) transform: Mutex<Mat4>,
|
pub(super) transform: Mutex<Mat4>,
|
||||||
zone: Mutex<Weak<Zone>>,
|
zone: Mutex<Weak<Zone>>,
|
||||||
children: Registry<Spatial>,
|
children: Registry<Spatial>,
|
||||||
|
pub(super) bounding_box_calc: OnceLock<fn(&Node) -> Bounds>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Spatial {
|
impl Spatial {
|
||||||
@@ -41,6 +43,7 @@ impl Spatial {
|
|||||||
transform: Mutex::new(transform),
|
transform: Mutex::new(transform),
|
||||||
zone: Mutex::new(Weak::new()),
|
zone: Mutex::new(Weak::new()),
|
||||||
children: Registry::new(),
|
children: Registry::new(),
|
||||||
|
bounding_box_calc: OnceLock::default(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
pub fn add_to(
|
pub fn add_to(
|
||||||
@@ -54,6 +57,7 @@ impl Spatial {
|
|||||||
"Internal: Node already has a Spatial aspect!"
|
"Internal: Node already has a Spatial aspect!"
|
||||||
);
|
);
|
||||||
let spatial = Spatial::new(Arc::downgrade(node), parent, transform);
|
let spatial = Spatial::new(Arc::downgrade(node), parent, transform);
|
||||||
|
node.add_local_method("get_bounding_box", Spatial::get_bounding_box_flex);
|
||||||
node.add_local_method("get_transform", Spatial::get_transform_flex);
|
node.add_local_method("get_transform", Spatial::get_transform_flex);
|
||||||
node.add_local_signal("set_transform", Spatial::set_transform_flex);
|
node.add_local_signal("set_transform", Spatial::set_transform_flex);
|
||||||
node.add_local_signal("set_spatial_parent", Spatial::set_spatial_parent_flex);
|
node.add_local_signal("set_spatial_parent", Spatial::set_spatial_parent_flex);
|
||||||
@@ -83,6 +87,25 @@ impl Spatial {
|
|||||||
world_to_space_matrix * space_to_world_matrix
|
world_to_space_matrix * space_to_world_matrix
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// the output bounds are probably way bigger than they need to be
|
||||||
|
#[instrument(level = "debug")]
|
||||||
|
pub fn get_bounding_box(&self) -> Bounds {
|
||||||
|
let Some(node) = self.node() else {return Bounds::default()};
|
||||||
|
let mut bounds = self
|
||||||
|
.bounding_box_calc
|
||||||
|
.get()
|
||||||
|
.map(|b| (b)(&node))
|
||||||
|
.unwrap_or_default();
|
||||||
|
for child in self.children.get_valid_contents() {
|
||||||
|
bounds = bounds_grow_to_fit_box(
|
||||||
|
bounds,
|
||||||
|
child.get_bounding_box(),
|
||||||
|
Some(child.local_transform()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
bounds
|
||||||
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip_all)]
|
#[instrument(level = "debug", skip_all)]
|
||||||
pub fn local_transform(&self) -> Mat4 {
|
pub fn local_transform(&self) -> Mat4 {
|
||||||
*self.transform.lock()
|
*self.transform.lock()
|
||||||
@@ -206,6 +229,44 @@ impl Spatial {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_bounding_box_flex(
|
||||||
|
node: &Node,
|
||||||
|
calling_client: Arc<Client>,
|
||||||
|
data: &[u8],
|
||||||
|
) -> Result<Vec<u8>> {
|
||||||
|
let this_spatial = node
|
||||||
|
.spatial
|
||||||
|
.get()
|
||||||
|
.ok_or_else(|| eyre!("Node doesn't have a spatial?"))?;
|
||||||
|
let relative_spatial_path: Option<&str> = deserialize(data)?;
|
||||||
|
let bounds = if let Some(relative_spatial_path) = relative_spatial_path {
|
||||||
|
let relative_spatial = find_reference_space(&calling_client, relative_spatial_path)?;
|
||||||
|
let center =
|
||||||
|
Spatial::space_to_space_matrix(Some(&this_spatial), Some(&relative_spatial))
|
||||||
|
.transform_point3([0.0; 3].into());
|
||||||
|
let bounds: Bounds = Bounds {
|
||||||
|
center,
|
||||||
|
dimensions: [0.0; 3].into(),
|
||||||
|
};
|
||||||
|
bounds_grow_to_fit_box(
|
||||||
|
bounds,
|
||||||
|
this_spatial.get_bounding_box(),
|
||||||
|
Some(Spatial::space_to_space_matrix(
|
||||||
|
Some(&this_spatial),
|
||||||
|
Some(&relative_spatial),
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
this_spatial.get_bounding_box()
|
||||||
|
};
|
||||||
|
|
||||||
|
serialize((
|
||||||
|
mint::Vector3::from(bounds.center),
|
||||||
|
mint::Vector3::from(bounds.dimensions),
|
||||||
|
))
|
||||||
|
.map_err(|e| e.into())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_transform_flex(
|
pub fn get_transform_flex(
|
||||||
node: &Node,
|
node: &Node,
|
||||||
calling_client: Arc<Client>,
|
calling_client: Arc<Client>,
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ impl Zone {
|
|||||||
"set_spatial_parent",
|
"set_spatial_parent",
|
||||||
"set_spatial_parent_in_place",
|
"set_spatial_parent_in_place",
|
||||||
],
|
],
|
||||||
server_methods: vec!["get_transform"],
|
server_methods: vec!["get_bounds", "get_transform"],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user