diff options
Diffstat (limited to 'world/src/main.rs')
-rw-r--r-- | world/src/main.rs | 144 |
1 files changed, 72 insertions, 72 deletions
diff --git a/world/src/main.rs b/world/src/main.rs index 16ed941..cfe2361 100644 --- a/world/src/main.rs +++ b/world/src/main.rs @@ -16,22 +16,18 @@ */ #![feature(iter_array_chunks)] #![allow(clippy::too_many_arguments, clippy::type_complexity)] +pub mod animation; pub mod mesh; pub mod physics; pub mod vrm; +use animation::import_animation; use anyhow::{Context, Result, anyhow}; use clap::Parser; -use gltf::{ - Gltf, Node, - animation::{Property, util::ReadOutputs}, - image::Source, - import_buffers, - scene::Transform, -}; +use gltf::{Gltf, Node, image::Source, import_buffers, scene::Transform}; use humansize::BINARY; use image::{ImageReader, codecs::webp::WebPEncoder}; -use log::{debug, info}; +use log::{debug, info, warn}; use mesh::import_mesh; use physics::import_physics; use rand::random; @@ -41,7 +37,7 @@ use serde_json::Value; use std::{ borrow::Cow, collections::{BTreeMap, HashMap}, - fs::File, + fs::{File, read_to_string}, io::{Cursor, Read, Write}, marker::PhantomData, net::{SocketAddr, TcpStream}, @@ -56,8 +52,7 @@ use weareshared::{ helper::ReadWrite, packets::{Data, Object, Packet, Resource}, resources::{ - AnimationChannel, AnimationPart, ArmaturePart, AvatarInfoPart, EnvironmentPart, Image, - LightPart, ParticlesPart, Prefab, + ArmaturePart, AvatarInfoPart, EnvironmentPart, Image, LightPart, ParticlesPart, Prefab, }, store::ResourceStore, vec3a, @@ -100,6 +95,11 @@ pub struct Args { #[arg(short = 'S', long)] with_default_sun: bool, + #[arg(long)] + animation: Option<PathBuf>, + #[arg(long)] + animation_bone_map: Option<PathBuf>, + /// Spins the object #[arg(long)] debug_spin: bool, @@ -117,7 +117,7 @@ pub struct Args { fn main() -> Result<()> { env_logger::init_from_env("LOG"); - let args = Args::parse(); + let mut args = Args::parse(); let store = if args.use_cache { ResourceStore::new_env()? @@ -166,6 +166,7 @@ fn main() -> Result<()> { let mut skin_index_to_arm_index = BTreeMap::new(); let mut joint_index_to_arm_index = BTreeMap::new(); + let joint_name_to_arm_index: BTreeMap<String, usize>; let armature = { let mut name = Vec::new(); let mut parent_pre_map = Vec::new(); @@ -227,6 +228,13 @@ fn main() -> Result<()> { } } + joint_name_to_arm_index = name + .iter() + .cloned() + .enumerate() + .map(|(a, b)| (b, a)) + .collect(); + ArmaturePart { name: Some(name), parent: Some(parent), @@ -373,75 +381,67 @@ fn main() -> Result<()> { let mut prefab = prefab.into_inner().unwrap(); let node_to_meshes = node_to_meshes.into_inner().unwrap(); - for a in gltf.animations() { - let mut max_time = 0f32; - let mut channels = Vec::new(); - for c in a.channels() { - let node = c.target().node().index(); - let reader = c.reader(|i| Some(&buffers[i.index()].0)); - let inputs: Vec<f32> = reader.read_inputs().unwrap().collect::<Vec<f32>>(); - let outputs: Vec<f32> = match reader.read_outputs().unwrap() { - ReadOutputs::Translations(iter) => iter.flatten().collect(), - ReadOutputs::Rotations(iter) => iter.into_f32().flatten().collect(), - ReadOutputs::Scales(iter) => iter.flatten().collect(), - ReadOutputs::MorphTargetWeights(iter) => iter.into_f32().collect(), - }; - for x in &inputs { - max_time = max_time.max(*x) - } - let time = store.set(&inputs)?; - let value = store.set(&outputs)?; + if let Some(apath) = args.animation.take() { + let path_base = apath.parent().unwrap(); + let mut gltf = Gltf::from_reader_without_validation(File::open(&apath)?) + .context("gltf parsing")?; + let blob = gltf.blob.take(); + let buffers = + import_buffers(&gltf, Some(path_base), blob).context("importing buffers")?; - if let Some(&m) = joint_index_to_arm_index.get(&node) { - let a = 0; // TODO - let mut ch = AnimationChannel::default(); - match c.target().property() { - Property::Translation => ch.t_joint_translation = Some((a, m as u32)), - Property::Rotation => ch.t_joint_rotation = Some((a, m as u32)), - Property::Scale => ch.t_joint_scale = Some((a, m as u32)), - Property::MorphTargetWeights => continue, + let anim_name_map = if let Some(ref map_path) = args.animation_bone_map { + let mut map = BTreeMap::new(); + for l in read_to_string(map_path)?.lines() { + if !l.trim().is_empty() { + let (a, b) = l.split_once("=").unwrap(); + map.insert(a.to_string(), b.to_string()); } - ch.time = Some(time.clone()); - ch.value = Some(value.clone()); - debug!( - "animation channel {:?} of joint {m} of armature {a} with {} time and {} component values", - c.target().property(), - inputs.len(), - outputs.len() - ); - channels.push(ch); } - if let Some(meshes) = node_to_meshes.get(&node) { - for &m in meshes { - let mut ch = AnimationChannel::default(); - match c.target().property() { - Property::Translation => ch.t_mesh_translation = Some(m as u32), - Property::Rotation => ch.t_mesh_rotation = Some(m as u32), - Property::Scale => ch.t_mesh_scale = Some(m as u32), - Property::MorphTargetWeights => continue, - } - ch.time = Some(time.clone()); - ch.value = Some(value.clone()); - debug!( - "animation channel {:?} of mesh {m} with {} time and {} component values", - c.target().property(), - inputs.len(), - outputs.len() - ); - channels.push(ch); + Some(map) + } else { + None + }; + + let mut anim_joint_index_to_arm_index = BTreeMap::new(); + for n in gltf.nodes() { + if let Some(name) = n.name() { + let Some(vrm_name) = (if let Some(map) = &anim_name_map { + map.get(name).cloned() + } else { + Some(name.to_string()) + }) else { + continue; + }; + let anim_node_index = n.index(); + if let Some(scene_arm_index) = joint_name_to_arm_index.get(&vrm_name) { + anim_joint_index_to_arm_index.insert(anim_node_index, *scene_arm_index); } } } - if !args.no_animations { - info!("adding animation with {} channels", channels.len()); - prefab.animation.push(store.set(&AnimationPart { - name: a.name().map(|n| n.to_string()), - channel: channels, - duration: Some(max_time), - })?); + + for a in gltf.animations() { + prefab.animation.push(import_animation( + a, + &store, + &anim_joint_index_to_arm_index, + &BTreeMap::new(), + &buffers, + )?); } } + for a in gltf.animations() { + if !args.no_animations { + prefab.animation.push(import_animation( + a, + &store, + &joint_index_to_arm_index, + &node_to_meshes, + &buffers, + )?); + }; + } + if vrm.camera_mount.is_some() || vrm.camera_mount_offset.is_some() || !vrm.bone_node_names.is_empty() |