From aa6158cb24785871b21e60eed378e3205d1be0b6 Mon Sep 17 00:00:00 2001 From: metamuffin Date: Mon, 17 Feb 2025 22:19:46 +0100 Subject: import particles --- shared/src/resources.rs | 42 ++++++++++++++++++++++++++++++++++++++++++ world/src/main.rs | 48 ++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 86 insertions(+), 4 deletions(-) diff --git a/shared/src/resources.rs b/shared/src/resources.rs index 76e52f8..19ce6b2 100644 --- a/shared/src/resources.rs +++ b/shared/src/resources.rs @@ -31,6 +31,7 @@ pub struct Prefab { pub collision: Vec<(Affine3A, Resource)>, pub light: Vec<(Vec3A, Resource)>, pub armature: Vec>, + pub particles: Vec<(Affine3A, Resource)>, pub environment: Option>, } @@ -47,6 +48,16 @@ pub struct EnvironmentPart { pub sun: Option<(Vec3A, Vec3A)>, } +#[derive(Debug, Default, Clone)] +pub struct ParticlesPart { + pub sprite: Option>, + pub density: Option, + pub lifetime: Option, + pub lifetime_spread: Option, + pub velocity: Option, + pub velocity_spread: Option, +} + #[derive(Debug, Default, Clone)] pub struct MeshPart { pub name: Option, @@ -209,6 +220,9 @@ impl ReadWrite for Prefab { for x in &self.armature { write_kv_opt(w, b"armature", &Some(x.clone()))?; } + for x in &self.particles { + write_kv_opt(w, b"particles", &Some(x.clone()))?; + } write_kv_opt(w, b"environment", &self.environment)?; Ok(()) } @@ -220,6 +234,7 @@ impl ReadWrite for Prefab { b"collision" => Ok(s.collision.push(read_slice(v)?)), b"light" => Ok(s.light.push(read_slice(v)?)), b"armature" => Ok(s.armature.push(read_slice(v)?)), + b"particles" => Ok(s.particles.push(read_slice(v)?)), b"environment" => Ok(s.environment = Some(read_slice(v)?)), x => Ok(warn!( "unknown prefab key: {:?}", @@ -270,6 +285,33 @@ impl ReadWrite for EnvironmentPart { Ok(s) } } +impl ReadWrite for ParticlesPart { + fn write(&self, w: &mut dyn Write) -> Result<()> { + write_kv_opt(w, b"density", &self.density)?; + write_kv_opt(w, b"sprite", &self.sprite)?; + write_kv_opt(w, b"lifetime", &self.lifetime)?; + write_kv_opt(w, b"lifetime_spread", &self.lifetime_spread)?; + write_kv_opt(w, b"velocity", &self.velocity)?; + write_kv_opt(w, b"velocity_spread", &self.velocity_spread)?; + Ok(()) + } + fn read(r: &mut dyn Read) -> Result { + let mut s = Self::default(); + read_kv_iter(r, |k, v| match k { + b"density" => Ok(s.density = Some(read_slice(v)?)), + b"sprite" => Ok(s.sprite = Some(read_slice(v)?)), + b"lifetime" => Ok(s.lifetime = Some(read_slice(v)?)), + b"lifetime_spread" => Ok(s.lifetime_spread = Some(read_slice(v)?)), + b"velocity" => Ok(s.velocity = Some(read_slice(v)?)), + b"velocity_spread" => Ok(s.velocity_spread = Some(read_slice(v)?)), + x => Ok(warn!( + "unknown environment part key: {:?}", + String::from_utf8_lossy(x) + )), + })?; + Ok(s) + } +} impl ReadWrite for MeshPart { fn write(&self, w: &mut dyn Write) -> Result<()> { write_kv_opt(w, b"name", &self.name)?; diff --git a/world/src/main.rs b/world/src/main.rs index 7552dde..1931fdb 100644 --- a/world/src/main.rs +++ b/world/src/main.rs @@ -20,7 +20,7 @@ pub mod mesh; pub mod physics; pub mod vrm; -use anyhow::{Result, anyhow}; +use anyhow::{Context, Result, anyhow}; use clap::Parser; use gltf::{Gltf, Node, image::Source, import_buffers, scene::Transform}; use humansize::BINARY; @@ -30,6 +30,8 @@ use mesh::import_mesh; use physics::import_physics; use rand::random; use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; +use serde::Deserialize; +use serde_json::Value; use std::{ borrow::Cow, collections::{BTreeMap, HashMap}, @@ -47,7 +49,7 @@ use weareshared::{ Affine3A, Vec3A, helper::ReadWrite, packets::{Data, Object, Packet, Resource}, - resources::{ArmaturePart, EnvironmentPart, Image, LightPart, Prefab}, + resources::{ArmaturePart, EnvironmentPart, Image, LightPart, ParticlesPart, Prefab}, store::ResourceStore, vec3a, }; @@ -230,7 +232,14 @@ fn main() -> Result<()> { // eprintln!("{:?}", node.extensions()); // eprintln!("{:?}", node.extras()); // } - if !node.name().unwrap_or_default().ends_with("-collider") { + let name = node.name().unwrap_or_default(); + let extras: Value = node + .extras() + .to_owned() + .map(|v| serde_json::from_str(v.get()).unwrap()) + .unwrap_or(Value::Object(Default::default())); + + if !name.ends_with("-collider") { if let Some(mesh) = node.mesh() { import_mesh( mesh, @@ -248,7 +257,36 @@ fn main() -> Result<()> { )?; } } - let (position, _, _) = node.transform().decomposed(); + if extras.get("particles") == Some(&Value::Bool(true)) { + #[derive(Deserialize)] + struct ParticlesAttr { + density: Option, + lifetime: Option, + lifetime_spread: Option, + velocity: Option, + velocity_spread: Option, + } + // let sprite = extras + // .get("sprite") + // .ok_or(anyhow!("particle volume is missing sprite"))?; + + let attr: ParticlesAttr = + serde_json::from_value(extras).context("particles attributes")?; + + info!("adding particles part"); + prefab.particles.push(( + transform_to_affine(node.transform()), + store.set(&ParticlesPart { + sprite: None, + density: attr.density, + lifetime: attr.lifetime, + lifetime_spread: attr.lifetime_spread, + velocity: attr.velocity, + velocity_spread: attr.velocity_spread, + })?, + )); + } + if let Some(light) = node.light() { let name = node.name().map(|e| e.to_owned()); if let Some(name) = &name { @@ -260,6 +298,7 @@ fn main() -> Result<()> { if let Some(e) = emission { debug!("emission is {e}"); } + let (position, _, _) = node.transform().decomposed(); prefab.light.push(( Vec3A::from_array(position), store.set(&LightPart { @@ -280,6 +319,7 @@ fn main() -> Result<()> { a.collision.extend(b.collision); a.mesh.extend(b.mesh); a.light.extend(b.light); + a.particles.extend(b.particles); a.environment = a.environment.or(b.environment); a.name = a.name.or(b.name); Ok(a) -- cgit v1.2.3-70-g09d2