diff options
-rw-r--r-- | world/src/animation.rs | 66 | ||||
-rw-r--r-- | world/src/main.rs | 39 |
2 files changed, 65 insertions, 40 deletions
diff --git a/world/src/animation.rs b/world/src/animation.rs index 3473371..ee6028e 100644 --- a/world/src/animation.rs +++ b/world/src/animation.rs @@ -15,7 +15,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ use anyhow::Result; -use glam::Quat; +use glam::{Quat, vec3a}; use gltf::{ Animation, animation::{Property, util::ReadOutputs}, @@ -33,6 +33,7 @@ use weareshared::{ pub fn import_animation<'a>( a: Animation<'a>, store: &ResourceStore, + transform: Affine3A, joint_index_to_ibm: &BTreeMap<usize, Affine3A>, joint_index_to_arm_index: &BTreeMap<usize, usize>, node_to_meshes: &BTreeMap<usize, Vec<usize>>, @@ -44,36 +45,39 @@ pub fn import_animation<'a>( 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> = if let Some(ibm) = joint_index_to_ibm.get(&node) { - debug!("pre-applying inverse bind matricies"); - let ibm = ibm.inverse(); - // eprintln!("{:#?}", ibm); - let (_, ibm_rot, _) = ibm.to_scale_rotation_translation(); - match reader.read_outputs().unwrap() { - // ReadOutputs::Translations(iter) => iter - // .flat_map(|[x, y, z]| (ibm.matrix3 * vec3a(x, y, z)).to_array()) - // .collect(), - ReadOutputs::Rotations(iter) => iter - .into_f32() - .map(Quat::from_array) - .map(|q| ibm_rot.mul_quat(q)) - .map(|q| q.to_array()) - .flatten() - .collect(), - // ReadOutputs::Scales(iter) => iter - // .flat_map(|[x, y, z]| (ibm.matrix3 * vec3a(x, y, z)).to_array()) - // .collect(), - ReadOutputs::MorphTargetWeights(iter) => iter.into_f32().collect(), - _ => continue, - } - } else { - 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(), - } - }; + let outputs: Vec<f32> = + if joint_index_to_ibm.contains_key(&node) || transform != Affine3A::IDENTITY { + let t = transform + * joint_index_to_ibm + .get(&node) + .copied() + .unwrap_or_default() + .inverse(); + let (_, rot, _) = t.to_scale_rotation_translation(); + match reader.read_outputs().unwrap() { + ReadOutputs::Translations(iter) => iter + .flat_map(|[x, y, z]| (t.matrix3 * vec3a(x, y, z)).to_array()) + .collect(), + ReadOutputs::Rotations(iter) => iter + .into_f32() + .map(Quat::from_array) + .map(|q| rot.mul_quat(q)) + .map(|q| q.to_array()) + .flatten() + .collect(), + ReadOutputs::Scales(iter) => iter + .flat_map(|[x, y, z]| (t.matrix3 * vec3a(x, y, z)).to_array()) + .collect(), + ReadOutputs::MorphTargetWeights(iter) => iter.into_f32().collect(), + } + } else { + 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) } diff --git a/world/src/main.rs b/world/src/main.rs index 14a4477..695b4aa 100644 --- a/world/src/main.rs +++ b/world/src/main.rs @@ -24,6 +24,7 @@ pub mod vrm; use animation::import_animation; use anyhow::{Context, Result, anyhow}; use clap::Parser; +use glam::Vec3; use gltf::{Gltf, Node, image::Source, import_buffers, scene::Transform}; use humansize::BINARY; use image::{ImageReader, codecs::webp::WebPEncoder}; @@ -99,6 +100,12 @@ pub struct Args { animation: Option<PathBuf>, #[arg(long)] animation_bone_map: Option<PathBuf>, + #[arg(long)] + animation_rotation_y: Option<f32>, + #[arg(long)] + animation_scale: Option<f32>, + #[arg(long)] + animation_apply_ibm: bool, /// Spins the object #[arg(long)] @@ -392,7 +399,7 @@ fn main() -> Result<()> { 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() { + if !l.trim().is_empty() && !l.starts_with(";") { let (a, b) = l.split_once("=").unwrap(); map.insert(a.to_string(), b.to_string()); } @@ -423,21 +430,34 @@ fn main() -> Result<()> { } } } - for s in gltf.skins() { - let reader = s.reader(|buf| Some(&buffers[buf.index()])); - if let Some(ibms) = reader.read_inverse_bind_matrices() { - for (jn, ibm) in s.joints().zip(ibms) { - joint_index_to_ibm.insert( - jn.index(), - transform_to_affine(Transform::Matrix { matrix: ibm }), - ); + if args.animation_apply_ibm { + for s in gltf.skins() { + let reader = s.reader(|buf| Some(&buffers[buf.index()])); + if let Some(ibms) = reader.read_inverse_bind_matrices() { + for (jn, ibm) in s.joints().zip(ibms) { + joint_index_to_ibm.insert( + jn.index(), + transform_to_affine(Transform::Matrix { matrix: ibm }), + ); + } } } + debug!("{} joint IBMs found", joint_index_to_ibm.len()); } + let transform = args + .animation_rotation_y + .map(Affine3A::from_rotation_y) + .unwrap_or_default() + * args + .animation_scale + .map(Vec3::splat) + .map(Affine3A::from_scale) + .unwrap_or_default(); for a in gltf.animations() { prefab.animation.push(import_animation( a, &store, + transform, &joint_index_to_ibm, &anim_joint_index_to_arm_index, &BTreeMap::new(), @@ -451,6 +471,7 @@ fn main() -> Result<()> { prefab.animation.push(import_animation( a, &store, + Affine3A::IDENTITY, &BTreeMap::new(), &joint_index_to_arm_index, &node_to_meshes, |