diff --git a/README.md b/README.md index 6a0f7e1..7c40d8b 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ The library supports almost all runtime features supported by C++ version ozz, i - Multi-threading - SIMD (SSE2 + NEON) - WASM +- Serialization (rkyv & serde) The following functions are not supported yet: - Baked physic simulation (no plan) @@ -50,8 +51,8 @@ use std::cell::RefCell; use std::rc::Rc; // Load resources -let skeleton = Rc::new(Skeleton::from_path("./resource/skeleton.ozz").unwrap()); -let animation = Rc::new(Animation::from_path("./resource/animation.ozz").unwrap()); +let skeleton = Rc::new(Skeleton::from_path("./resource/playback/skeleton.ozz").unwrap()); +let animation = Rc::new(Animation::from_path("./resource/playback/animation.ozz").unwrap()); // Init sample job (Rc style) let mut sample_job: SamplingJobRc = SamplingJob::default(); @@ -90,6 +91,15 @@ In theory, ozz-animation-rs supports all platforms supported by rust. But I only Maybe you can run cross-platform deterministic test cases under [./tests](https://github.com/SlimeYummy/ozz-animation-rs/tree/master/tests) on your target platform. +### Compatibility + +With the release of ozz-animation versions, .ozz files and some APIs will also be upgraded. Therefore ozz-animation-rs remains compatible with the corresponding version of ozz-animation, as shown in the following table: + +|ozz-animation-rs|ozz-animation(C++)| +|--|--| +|0.10.x|0.15.x| +|0.9.x|0.14.x| + ### Why not fixed-point? Initially, I tried to implement similar functionality using fixed point numbers. But fixed-point performance is worse, and it is difficult to be compatible with other libraries. diff --git a/src/animation.rs b/src/animation.rs index f8b95bd..d207ffb 100644 --- a/src/animation.rs +++ b/src/animation.rs @@ -299,16 +299,23 @@ pub(crate) struct AnimationRaw { impl Animation { /// `Animation` resource file version for `Archive`. - const VERSION: u32 = 7; + #[inline] + pub fn tag() -> &'static str { + "ozz-animation" + } + /// `Animation` resource file tag for `Archive`. - const TAG: &'static str = "ozz-animation"; + #[inline] + pub fn version() -> u32 { + 7 + } /// Reads an `AnimationMeta` from an `Archive`. pub fn read_meta(archive: &mut Archive) -> Result { - if archive.tag() != Self::TAG { + if archive.tag() != Self::tag() { return Err(OzzError::InvalidTag); } - if archive.version() != Self::VERSION { + if archive.version() != Self::version() { return Err(OzzError::InvalidVersion); } @@ -416,7 +423,7 @@ impl Animation { pub(crate) fn from_raw(raw: &AnimationRaw) -> Animation { let meta = AnimationMeta { - version: Animation::VERSION, + version: Animation::version(), duration: raw.duration, num_tracks: raw.num_tracks, name: raw.name.clone(), @@ -992,7 +999,7 @@ const _: () = { fn deserialize(&self, _: &mut D) -> Result { let archived = from_archived!(self); let mut animation = Animation::new(AnimationMeta { - version: Animation::VERSION, + version: Animation::version(), duration: archived.duration, num_tracks: archived.num_tracks, name: archived.name.to_string(), diff --git a/src/archive.rs b/src/archive.rs index eb5a40c..94f0b35 100644 --- a/src/archive.rs +++ b/src/archive.rs @@ -151,25 +151,15 @@ macro_rules! primitive_reader { impl ArchiveRead<$type> for $type { #[inline] fn read(archive: &mut Archive) -> Result<$type, OzzError> { - let mut val = Default::default(); + let mut val: $type = Default::default(); let size = mem::size_of::<$type>(); let ptr = &mut val as *mut $type as *mut u8; - - if size == 1 { - // Special case for u8 and i8 - archive - .read - .read_exact(unsafe { slice::from_raw_parts_mut(ptr, 1) })?; - } else { - archive - .read - .read_exact(unsafe { slice::from_raw_parts_mut(ptr, size) })?; - } - - if !archive.endian_swap { - Ok(val) - } else { - Ok(val.swap_endian()) + archive + .read + .read_exact(unsafe { slice::from_raw_parts_mut(ptr, size) })?; + match archive.endian_swap { + true => Ok(val.swap_endian()), + false => Ok(val), } } } @@ -257,5 +247,7 @@ mod tests { fn test_archive_new() { let archive = Archive::from_path("./resource/playback/animation.ozz").unwrap(); assert!(!archive.endian_swap); + assert_eq!(archive.tag, "ozz-animation"); + assert_eq!(archive.version, 7); } } diff --git a/src/math.rs b/src/math.rs index 13c9d65..097b3c0 100644 --- a/src/math.rs +++ b/src/math.rs @@ -24,7 +24,6 @@ pub(crate) const TWO: f32x4 = f32x4::from_array([2.0; 4]); pub(crate) const THREE: f32x4 = f32x4::from_array([3.0; 4]); pub(crate) const NEG_ONE: f32x4 = f32x4::from_array([-1.0; 4]); pub(crate) const FRAC_1_2: f32x4 = f32x4::from_array([0.5; 4]); -pub(crate) const PI: f32x4 = f32x4::from_array([core::f32::consts::PI; 4]); pub(crate) const FRAC_2_PI: f32x4 = f32x4::from_array([core::f32::consts::FRAC_2_PI; 4]); pub(crate) const FRAC_PI_2: f32x4 = f32x4::from_array([core::f32::consts::FRAC_PI_2; 4]); @@ -113,15 +112,6 @@ impl SoaVec3 { } } - #[inline] - pub fn component_mul(&self, other: &SoaVec3) -> SoaVec3 { - SoaVec3 { - x: self.x * other.x, - y: self.y * other.y, - z: self.z * other.z, - } - } - #[inline] pub fn mul_num(&self, f: f32x4) -> SoaVec3 { SoaVec3 { @@ -1435,10 +1425,6 @@ mod tests { assert!(mc < 2.5e-5); } - fn approx_eq(a: f32x4, b: f32, epsilon: f32) -> bool { - (a - f32x4::splat(b)).abs().simd_lt(f32x4::splat(epsilon)).all() - } - #[test] #[wasm_bindgen_test] fn test_asin() { diff --git a/src/sampling_job.rs b/src/sampling_job.rs index 448059a..05ce152 100644 --- a/src/sampling_job.rs +++ b/src/sampling_job.rs @@ -1240,24 +1240,23 @@ where #[inline] fn track_forward(cache: &[u32], previouses: &[u16], key: usize, last_track: usize, num_tracks: usize) -> usize { - let target = key.saturating_sub(previouses[key] as usize); - - if let Some((entry, _)) = cache - .iter() - .enumerate() - .skip(last_track) - .take(num_tracks - last_track) - .find(|&(_, &value)| value as usize == target) - { - return entry; - } + #![allow(clippy::needless_range_loop)] // to keep same style with track_backward + assert!(key < previouses.len()); + assert!(last_track < num_tracks); - cache - .iter() - .enumerate() - .take(last_track) - .find(|&(_, &value)| value as usize == target) - .map_or(0, |(entry, _)| entry) + let target = key - previouses[key] as usize; + for entry in last_track..num_tracks { + if (cache[entry] as usize) == target { + return entry; + } + } + for entry in 0..num_tracks { + if (cache[entry] as usize) == target { + return entry; + } + assert!(entry < last_track); + } + 0 } #[inline] diff --git a/src/skeleton.rs b/src/skeleton.rs index 14e8739..cd34082 100644 --- a/src/skeleton.rs +++ b/src/skeleton.rs @@ -72,8 +72,8 @@ impl Skeleton { "ozz-skeleton" } - #[inline] /// `Skeleton` resource file version for `Archive`. + #[inline] pub fn version() -> u32 { 2 } @@ -503,7 +503,7 @@ mod tests { assert_eq!(skeleton.joint_parents(), skeleton2.joint_parents()); assert_eq!(skeleton.joint_names(), skeleton2.joint_names()); } - + #[cfg(feature = "serde")] #[test] #[wasm_bindgen_test] @@ -513,7 +513,7 @@ mod tests { let skeleton = Skeleton::from_path("./resource/blend/skeleton.ozz").unwrap(); let josn = serde_json::to_vec(&skeleton).unwrap(); let skeleton2: Skeleton = serde_json::from_slice(&josn).unwrap(); - + assert_eq!(skeleton.joint_rest_poses(), skeleton2.joint_rest_poses()); assert_eq!(skeleton.joint_parents(), skeleton2.joint_parents()); assert_eq!(skeleton.joint_names(), skeleton2.joint_names());