From a80ddf501dea28ff918ce615c3960ef4e0a9bec6 Mon Sep 17 00:00:00 2001 From: Nova Date: Mon, 26 Sep 2022 00:39:56 -0400 Subject: [PATCH] feat(drawable): set sky --- src/core/resource.rs | 2 +- src/main.rs | 38 ++++++++---------------- src/nodes/drawable/mod.rs | 59 +++++++++++++++++++++++++++++++------ src/nodes/drawable/model.rs | 18 ++++++----- 4 files changed, 74 insertions(+), 43 deletions(-) diff --git a/src/core/resource.rs b/src/core/resource.rs index 0d9c588..0fbe552 100644 --- a/src/core/resource.rs +++ b/src/core/resource.rs @@ -2,7 +2,7 @@ use std::path::PathBuf; pub type ResourceID = Box; -pub trait ResourceIDTrait { +pub trait ResourceIDTrait: Send + Sync { fn get_file(&self, prefixes: &[PathBuf]) -> Option; } diff --git a/src/main.rs b/src/main.rs index a62b758..e223909 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,9 +4,7 @@ mod objects; mod wayland; use crate::core::destroy_queue; -use crate::nodes::drawable::model::MODELS_TO_DROP; -use crate::nodes::drawable::DRAWABLE_REGISTRY; -use crate::nodes::{hmd, input}; +use crate::nodes::{drawable, hmd, input}; use crate::objects::input::mouse_pointer::MousePointer; use crate::objects::input::sk_hand::SkHand; use crate::wayland::Wayland; @@ -36,12 +34,11 @@ struct CliArgs { } fn main() -> Result<()> { + let project_dirs = ProjectDirs::from("", "", "stardust").unwrap(); let cli_args = Arc::new(CliArgs::parse()); let log = ::slog::Logger::root(::slog_stdlog::StdLog.fuse(), slog::o!()); slog_stdlog::init()?; - let project_dirs = ProjectDirs::from("", "", "stardust").unwrap(); - let mut stereokit = Settings::default() .app_name("Stardust XR") .overlay_app(cli_args.overlay) @@ -56,18 +53,12 @@ fn main() -> Result<()> { .expect("StereoKit failed to initialize"); println!("Init StereoKit"); + // Skytex/light stuff { let skytex_path = project_dirs.config_dir().join("skytex.hdr"); if let Some((tex, light)) = skytex_path .exists() - .then(|| { - Texture::from_cubemap_equirectangular( - &stereokit, - skytex_path.to_str().unwrap(), - true, - 100, - ) - }) + .then(|| Texture::from_cubemap_equirectangular(&stereokit, &skytex_path, true, 100)) .flatten() { stereokit.set_skytex(&tex); @@ -104,29 +95,26 @@ fn main() -> Result<()> { let mut wayland = Wayland::new(log)?; println!("Stardust ready!"); stereokit.run( - |draw_ctx| { - hmd::frame(&stereokit); - wayland.frame(&stereokit); + |sk, draw_ctx| { + hmd::frame(sk); + wayland.frame(sk); destroy_queue::clear(); - nodes::root::Root::logic_step(stereokit.time_elapsed()); - for drawable in DRAWABLE_REGISTRY.get_valid_contents() { - drawable.draw(&stereokit, draw_ctx); - } - MODELS_TO_DROP.lock().clear(); + nodes::root::Root::logic_step(sk.time_elapsed()); + drawable::draw(sk, draw_ctx); if let Some(mouse_pointer) = &mouse_pointer { - mouse_pointer.update(&stereokit); + mouse_pointer.update(sk); } if let Some(hands) = &mut hands { - hands[0].update(&stereokit); - hands[1].update(&stereokit); + hands[0].update(sk); + hands[1].update(sk); } input::process_input(); wayland.make_context_current(); }, - || { + |_| { println!("Cleanly shut down StereoKit"); }, ); diff --git a/src/nodes/drawable/mod.rs b/src/nodes/drawable/mod.rs index 35d1186..999d561 100644 --- a/src/nodes/drawable/mod.rs +++ b/src/nodes/drawable/mod.rs @@ -1,19 +1,60 @@ pub mod model; use super::Node; -use crate::core::{client::Client, registry::Registry}; -use std::sync::Arc; -use stereokit::{lifecycle::DrawContext, StereoKit}; - -pub trait Drawable: Send + Sync { - fn draw(&self, sk: &StereoKit, draw_ctx: &DrawContext); -} - -pub static DRAWABLE_REGISTRY: Registry = Registry::new(); +use crate::core::client::Client; +use anyhow::Result; +use parking_lot::Mutex; +use std::{path::PathBuf, str::FromStr, sync::Arc}; +use stereokit::{lifecycle::DrawContext, texture::Texture, StereoKit}; pub fn create_interface(client: &Arc) { let node = Node::create(client, "", "drawable", false); node.add_local_signal("createModelFromFile", model::create_from_file); node.add_local_signal("createModelFromResource", model::create_from_resource); + node.add_local_signal("setSkyFile", set_sky_file_flex); node.add_to_scenegraph(); } + +pub fn draw(sk: &mut StereoKit, draw_ctx: &DrawContext) { + model::draw_all(sk, draw_ctx); + + let new_skytex = QUEUED_SKYTEX.lock().take(); + let mut new_skylight = QUEUED_SKYLIGHT.lock().take(); + let same_file = new_skytex == new_skylight; + + if let Some(skytex) = new_skytex { + if let Some((skytex, skylight)) = + Texture::from_cubemap_equirectangular(sk, &skytex, true, i32::MAX) + { + sk.set_skytex(&skytex); + if same_file { + sk.set_skylight(&skylight); + new_skylight = None; + } + } + } + if let Some(skylight) = new_skylight { + if let Some((_, skylight)) = + Texture::from_cubemap_equirectangular(sk, &skylight, true, i32::MAX) + { + sk.set_skylight(&skylight); + } + } +} + +static QUEUED_SKYLIGHT: Mutex> = Mutex::new(None); +static QUEUED_SKYTEX: Mutex> = Mutex::new(None); + +fn set_sky_file_flex(_node: &Node, _calling_client: Arc, data: &[u8]) -> Result<()> { + let flex_vec = flexbuffers::Reader::get_root(data)?.get_vector()?; + let path = PathBuf::from_str(flex_vec.index(0)?.get_str()?)?; + path.metadata()?; + if flex_vec.idx(1).as_bool() { + QUEUED_SKYTEX.lock().replace(path.clone()); + } + if flex_vec.idx(2).as_bool() { + QUEUED_SKYLIGHT.lock().replace(path); + } + + Ok(()) +} diff --git a/src/nodes/drawable/model.rs b/src/nodes/drawable/model.rs index 02e9b72..f4baa10 100644 --- a/src/nodes/drawable/model.rs +++ b/src/nodes/drawable/model.rs @@ -1,8 +1,7 @@ -use super::{Drawable, Node}; +use super::Node; use crate::core::client::Client; use crate::core::registry::Registry; use crate::core::resource::{NamespacedResourceID, ResourceID}; -use crate::nodes::drawable::DRAWABLE_REGISTRY; use crate::nodes::spatial::{get_spatial_parent_flex, Spatial}; use anyhow::{anyhow, bail, ensure, Result}; use flexbuffers::FlexBufferType; @@ -24,9 +23,9 @@ use stereokit::render::RenderLayer; use stereokit::texture::Texture; use stereokit::StereoKit; -pub static MODEL_REGISTRY: Registry = Registry::new(); +static MODEL_REGISTRY: Registry = Registry::new(); lazy_static! { - pub static ref MODELS_TO_DROP: Mutex>> = Default::default(); + static ref MODELS_TO_DROP: Mutex>> = Default::default(); } pub enum MaterialParameter { @@ -62,7 +61,6 @@ impl Model { }; node.add_local_signal("setMaterialParameter", Model::set_material_parameter); let model_arc = MODEL_REGISTRY.add(model); - DRAWABLE_REGISTRY.add_raw(&(model_arc.clone() as Arc)); let _ = model_arc.pending_model_path.set( model_arc .resource_id @@ -104,8 +102,7 @@ impl Model { Ok(()) } -} -impl Drawable for Model { + fn draw(&self, sk: &StereoKit, draw_ctx: &DrawContext) { let sk_model = self .sk_model @@ -162,7 +159,12 @@ impl Drop for Model { MODELS_TO_DROP.lock().push(model); } MODEL_REGISTRY.remove(self); - DRAWABLE_REGISTRY.remove(self); + } +} + +pub fn draw_all(sk: &StereoKit, draw_ctx: &DrawContext) { + for model in MODEL_REGISTRY.get_valid_contents() { + model.draw(sk, draw_ctx); } }