feat: instant model loading

This commit is contained in:
Nova
2023-05-10 20:10:31 -04:00
parent 5a6e7e02ca
commit 6773fe2cf3
2 changed files with 37 additions and 49 deletions

View File

@@ -20,11 +20,11 @@ use std::path::PathBuf;
use std::process::Command; use std::process::Command;
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use stereokit::DisplayBlend;
use stereokit::{ use stereokit::{
named_colors::BLACK, DepthMode, DisplayMode, Handed, LogLevel, StereoKitMultiThread, named_colors::BLACK, DepthMode, DisplayMode, Handed, LogLevel, StereoKitMultiThread,
TextureFormat, TextureType, TextureFormat, TextureType,
}; };
use stereokit::{DisplayBlend, Sk};
use tokio::{runtime::Handle, sync::oneshot}; use tokio::{runtime::Handle, sync::oneshot};
use tracing::{debug_span, error, info}; use tracing::{debug_span, error, info};
use tracing_subscriber::{fmt, prelude::*, EnvFilter}; use tracing_subscriber::{fmt, prelude::*, EnvFilter};
@@ -50,6 +50,7 @@ struct CliArgs {
} }
static STARDUST_INSTANCE: OnceCell<String> = OnceCell::new(); static STARDUST_INSTANCE: OnceCell<String> = OnceCell::new();
static SK_MULTITHREAD: OnceCell<Sk> = OnceCell::new();
struct EventLoopInfo { struct EventLoopInfo {
tokio_handle: Handle, tokio_handle: Handle,
@@ -100,6 +101,7 @@ fn main() -> Result<()> {
} }
.init() .init()
.expect("StereoKit failed to initialize"); .expect("StereoKit failed to initialize");
let _ = SK_MULTITHREAD.set(sk.multithreaded());
info!("Init StereoKit"); info!("Init StereoKit");
sk.material_set_shader( sk.material_set_shader(

View File

@@ -1,11 +1,11 @@
use super::Node; use super::Node;
use crate::core::client::Client; use crate::core::client::Client;
use crate::core::destroy_queue;
use crate::core::node_collections::LifeLinkedNodeMap; use crate::core::node_collections::LifeLinkedNodeMap;
use crate::core::registry::Registry; use crate::core::registry::Registry;
use crate::core::resource::ResourceID; use crate::core::resource::ResourceID;
use crate::nodes::drawable::Drawable; use crate::nodes::drawable::Drawable;
use crate::nodes::spatial::{find_spatial_parent, parse_transform, Spatial}; use crate::nodes::spatial::{find_spatial_parent, parse_transform, Spatial};
use crate::SK_MULTITHREAD;
use color_eyre::eyre::{bail, ensure, eyre, Result}; use color_eyre::eyre::{bail, ensure, eyre, Result};
use glam::Mat4; use glam::Mat4;
use mint::{ColumnMatrix4, Vector2, Vector3, Vector4}; use mint::{ColumnMatrix4, Vector2, Vector3, Vector4};
@@ -18,7 +18,6 @@ use serde::Deserialize;
use stardust_xr::schemas::flex::deserialize; use stardust_xr::schemas::flex::deserialize;
use stardust_xr::values::Transform; use stardust_xr::values::Transform;
use std::ffi::OsStr; use std::ffi::OsStr;
use std::fmt::Error;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::{Arc, Weak}; use std::sync::{Arc, Weak};
use stereokit::named_colors::WHITE; use stereokit::named_colors::WHITE;
@@ -124,7 +123,7 @@ pub struct ModelPart {
pending_material_replacement: Mutex<Option<Arc<SendWrapper<Material>>>>, pending_material_replacement: Mutex<Option<Arc<SendWrapper<Material>>>>,
} }
impl ModelPart { impl ModelPart {
fn create_for_model(sk: &impl StereoKitDraw, model: &Arc<Model>, sk_model: &SKModel) { fn create_for_model(sk: &impl StereoKitMultiThread, model: &Arc<Model>, sk_model: &SKModel) {
let first_root_part = sk.model_node_get_root(sk_model); let first_root_part = sk.model_node_get_root(sk_model);
let mut current_option_part = Some(first_root_part); let mut current_option_part = Some(first_root_part);
@@ -148,7 +147,7 @@ impl ModelPart {
} }
fn create( fn create(
sk: &impl StereoKitDraw, sk: &impl StereoKitMultiThread,
model: &Arc<Model>, model: &Arc<Model>,
sk_model: &SKModel, sk_model: &SKModel,
id: i32, id: i32,
@@ -225,27 +224,23 @@ impl ModelPart {
fn update(&self, sk: &impl StereoKitDraw) { fn update(&self, sk: &impl StereoKitDraw) {
let Some(model) = self.model.upgrade() else {return}; let Some(model) = self.model.upgrade() else {return};
let Some(sk_model) = model.sk_model.get() else {return};
let Some(node) = model.space.node() else {return}; let Some(node) = model.space.node() else {return};
let Some(client) = node.get_client() else {return}; let Some(client) = node.get_client() else {return};
let Some(sk_model) = model.sk_model.get() else {return};
if let Some(material_replacement) = self.pending_material_replacement.lock().take() { if let Some(material_replacement) = self.pending_material_replacement.lock().take() {
sk.model_node_set_material( sk.model_node_set_material(sk_model, self.id, material_replacement.as_ref().as_ref());
sk_model.as_ref(),
self.id,
material_replacement.as_ref().as_ref(),
);
} }
let mut material_parameters = self.pending_material_parameters.lock(); let mut material_parameters = self.pending_material_parameters.lock();
for (parameter_name, parameter_value) in material_parameters.drain() { for (parameter_name, parameter_value) in material_parameters.drain() {
let Some(material) = sk.model_node_get_material(sk_model.as_ref(), self.id) else {continue}; let Some(material) = sk.model_node_get_material(sk_model, self.id) else {continue};
let new_material = sk.material_copy(material); let new_material = sk.material_copy(material);
parameter_value.apply_to_material(&client, sk, &new_material, parameter_name.as_str()); parameter_value.apply_to_material(&client, sk, &new_material, parameter_name.as_str());
sk.model_node_set_material(sk_model.as_ref(), self.id, &new_material); sk.model_node_set_material(sk_model, self.id, &new_material);
} }
sk.model_node_set_transform_model( sk.model_node_set_transform_model(
sk_model.as_ref(), sk_model,
self.id, self.id,
Spatial::space_to_space_matrix(Some(&self.space), Some(&model.space)), Spatial::space_to_space_matrix(Some(&self.space), Some(&model.space)),
); );
@@ -256,11 +251,12 @@ pub struct Model {
self_ref: Weak<Model>, self_ref: Weak<Model>,
enabled: Arc<AtomicBool>, enabled: Arc<AtomicBool>,
space: Arc<Spatial>, space: Arc<Spatial>,
resource_id: ResourceID, _resource_id: ResourceID,
pending_model_path: OnceCell<PathBuf>, sk_model: OnceCell<SKModel>,
sk_model: OnceCell<SendWrapper<SKModel>>,
parts: LifeLinkedNodeMap<i32>, parts: LifeLinkedNodeMap<i32>,
} }
unsafe impl Send for Model {}
unsafe impl Sync for Model {}
impl Model { impl Model {
pub fn add_to(node: &Arc<Node>, resource_id: ResourceID) -> Result<Arc<Model>> { pub fn add_to(node: &Arc<Node>, resource_id: ResourceID) -> Result<Arc<Model>> {
@@ -272,54 +268,47 @@ impl Model {
node.drawable.get().is_none(), node.drawable.get().is_none(),
"Internal: Node already has a drawable attached!" "Internal: Node already has a drawable attached!"
); );
let pending_model_path = resource_id
.get_file(
&node
.get_client()
.ok_or_else(|| eyre!("Client not found"))?
.base_resource_prefixes
.lock()
.clone(),
&[OsStr::new("glb"), OsStr::new("gltf")],
)
.ok_or_else(|| eyre!("Resource not found"))?;
let model = Arc::new_cyclic(|self_ref| Model { let model = Arc::new_cyclic(|self_ref| Model {
self_ref: self_ref.clone(), self_ref: self_ref.clone(),
enabled: node.enabled.clone(), enabled: node.enabled.clone(),
space: node.spatial.get().unwrap().clone(), space: node.spatial.get().unwrap().clone(),
resource_id, _resource_id: resource_id,
pending_model_path: OnceCell::new(),
sk_model: OnceCell::new(), sk_model: OnceCell::new(),
parts: LifeLinkedNodeMap::default(), parts: LifeLinkedNodeMap::default(),
}); });
MODEL_REGISTRY.add_raw(&model); MODEL_REGISTRY.add_raw(&model);
let _ = model.pending_model_path.set(
model let sk = SK_MULTITHREAD.get().unwrap();
.resource_id let sk_model =
.get_file( sk.model_create_file(pending_model_path.to_str().unwrap(), None::<Shader>)?;
&node ModelPart::create_for_model(sk, &model.self_ref.upgrade().unwrap(), &sk_model);
.get_client() let _ = model.sk_model.set(sk_model);
.ok_or_else(|| eyre!("Client not found"))?
.base_resource_prefixes
.lock()
.clone(),
&[OsStr::new("glb"), OsStr::new("gltf")],
)
.ok_or_else(|| eyre!("Resource not found"))?,
);
let _ = node.drawable.set(Drawable::Model(model.clone())); let _ = node.drawable.set(Drawable::Model(model.clone()));
Ok(model) Ok(model)
} }
fn draw(&self, sk: &impl StereoKitDraw) { fn draw(&self, sk: &impl StereoKitDraw) {
let Ok(sk_model) = self let Some(sk_model) = self.sk_model.get() else {return};
.sk_model
.get_or_try_init(|| -> color_eyre::eyre::Result<SendWrapper<SKModel>> {
let pending_model_path = self.pending_model_path.get().ok_or(Error)?;
let model =
sk.model_create_file(pending_model_path.to_str().unwrap(), None::<Shader>)?;
ModelPart::create_for_model(sk, &self.self_ref.upgrade().unwrap(), &model);
Ok(SendWrapper::new(sk.model_copy(model)))
}) else {return};
for model_node_node in self.parts.nodes() { for model_node_node in self.parts.nodes() {
let Some(Drawable::ModelPart(model_node)) = model_node_node.drawable.get() else {continue}; let Some(Drawable::ModelPart(model_node)) = model_node_node.drawable.get() else {continue};
model_node.update(sk); model_node.update(sk);
} }
sk.model_draw( sk.model_draw(
sk_model.as_ref(), sk_model,
self.space.global_transform(), self.space.global_transform(),
WHITE, WHITE,
RenderLayer::LAYER0, RenderLayer::LAYER0,
@@ -329,9 +318,6 @@ impl Model {
impl Drop for Model { impl Drop for Model {
fn drop(&mut self) { fn drop(&mut self) {
if let Some(model) = self.sk_model.take() {
destroy_queue::add(model);
}
MODEL_REGISTRY.remove(self); MODEL_REGISTRY.remove(self);
} }
} }