mirror of
https://codeberg.org/icewind/vmdl.git
synced 2026-06-03 08:34:23 +02:00
more anim work
This commit is contained in:
parent
1e599c380a
commit
226d085211
4 changed files with 73 additions and 41 deletions
12
src/lib.rs
12
src/lib.rs
|
|
@ -211,14 +211,14 @@ impl Model {
|
|||
.map(|(_, weight)| weight.weight)
|
||||
.sum();
|
||||
|
||||
let pose_to_bone = animated_bone.pos.into();
|
||||
let pose_to_bone: Matrix4<f32> = animated_bone.pose_to_bone.into();
|
||||
let bone_to_pose: Matrix4<f32> = pose_to_bone.inverse_transform().unwrap();
|
||||
let bone_rotation: Matrix4<f32> = animated_bone.rot.into();
|
||||
|
||||
let bone_rotation = Matrix4::from(animated_bone.rot);
|
||||
if weight > 0.0 {
|
||||
position -= pose_to_bone;
|
||||
let transform = (animation.transform(frame)) * bone_rotation;
|
||||
position = transform.transform_vector(position);
|
||||
position += pose_to_bone;
|
||||
let transform =
|
||||
bone_to_pose * animation.transform(frame) * bone_rotation * pose_to_bone;
|
||||
position = transform.transform_point(position);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -155,10 +155,22 @@ bitflags! {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Zeroable, Pod, Copy, Clone, Debug)]
|
||||
#[repr(C)]
|
||||
struct AnimationValuePointer([u16; 3]);
|
||||
impl ReadableRelative for AnimationValuePointer {}
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
struct AnimationValuePointers<'a> {
|
||||
offsets: [u16; 3],
|
||||
data: &'a [u8],
|
||||
}
|
||||
|
||||
impl<'a> ReadRelative<'a> for AnimationValuePointers<'a> {
|
||||
type Header = [u16; 3];
|
||||
|
||||
fn read(data: &'a [u8], header: Self::Header) -> Result<Self, ModelError> {
|
||||
Ok(AnimationValuePointers {
|
||||
offsets: header,
|
||||
data,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Zeroable, Pod, Copy, Clone, Debug, Default)]
|
||||
#[repr(C)]
|
||||
|
|
@ -172,17 +184,16 @@ static_assertions::const_assert_eq!(size_of::<ValueHeader>(), size_of::<i16>());
|
|||
impl ReadableRelative for ValueHeader {}
|
||||
|
||||
fn read_animation_values(
|
||||
data: &[u8], // data starting at the AnimationValuePointer
|
||||
frame: usize,
|
||||
base_pointers: AnimationValuePointer,
|
||||
animation_value_pointers: AnimationValuePointers,
|
||||
) -> Result<[f32; 3], ModelError> {
|
||||
let [x, y, z] = base_pointers
|
||||
.0
|
||||
.map::<_, Result<_, ModelError>>(|base_pointer| {
|
||||
if base_pointer == 0 {
|
||||
let [x, y, z] = animation_value_pointers
|
||||
.offsets
|
||||
.map::<_, Result<_, ModelError>>(|offset| {
|
||||
if offset == 0 {
|
||||
Ok(0)
|
||||
} else {
|
||||
let values: FrameValues = read_single(data, base_pointer)?;
|
||||
let values: FrameValues = read_single(animation_value_pointers.data, offset)?;
|
||||
Ok(values.get(frame as u8)?)
|
||||
}
|
||||
});
|
||||
|
|
@ -291,7 +302,9 @@ impl RotationData {
|
|||
match self {
|
||||
RotationData::Quaternion48(_) => size_of::<Quaternion48>(),
|
||||
RotationData::Quaternion64(_) => size_of::<Quaternion64>(),
|
||||
RotationData::Animated(_) => size_of::<AnimationValuePointer>(),
|
||||
RotationData::Animated(_) => {
|
||||
size_of::<<AnimationValuePointers<'_> as ReadRelative>::Header>()
|
||||
}
|
||||
RotationData::None => 0,
|
||||
}
|
||||
}
|
||||
|
|
@ -332,7 +345,10 @@ impl PositionData {
|
|||
pub fn position(&self, frame: usize) -> Vector {
|
||||
match self {
|
||||
PositionData::Vector48(vector) => Vector::from(*vector),
|
||||
PositionData::PositionValues(values) => values.get(frame).copied().unwrap_or_default(),
|
||||
PositionData::PositionValues(values) => values
|
||||
.get(frame)
|
||||
.copied()
|
||||
.unwrap_or_else(|| values.last().copied().unwrap_or_default()),
|
||||
PositionData::None => Vector::default(),
|
||||
}
|
||||
}
|
||||
|
|
@ -364,12 +380,13 @@ impl Animation {
|
|||
self.rotation_data.rotation(frame)
|
||||
}
|
||||
|
||||
pub fn position(&self, frame: usize) -> Vector {
|
||||
pub fn translation(&self, frame: usize) -> Vector {
|
||||
self.position_data.position(frame)
|
||||
}
|
||||
|
||||
pub fn transform(&self, frame: usize) -> Matrix4<f32> {
|
||||
Matrix4::from_translation(self.position(frame).into()) * Matrix4::from(self.rotation(frame))
|
||||
Matrix4::from(self.rotation(frame))
|
||||
* Matrix4::from_translation(self.translation(frame).into())
|
||||
}
|
||||
|
||||
pub(crate) fn apply_bone_data(&mut self, bone: &Bone) {
|
||||
|
|
@ -399,10 +416,9 @@ fn read_animation(
|
|||
} else if header.flags.contains(AnimationFlags::STUDIO_ANIM_RAWROT2) {
|
||||
RotationData::from(read_single::<Quaternion64, _>(data, offset)?)
|
||||
} else if header.flags.contains(AnimationFlags::STUDIO_ANIM_ANIMROT) {
|
||||
let pointers: AnimationValuePointer = read_single(data, offset)?;
|
||||
let value_data = &data[offset..];
|
||||
let pointers: AnimationValuePointers = read_single(data, offset)?;
|
||||
let values: Vec<RadianEuler> = (0..frames)
|
||||
.map(|frame| read_animation_values(value_data, frame, pointers))
|
||||
.map(|frame| read_animation_values(frame, pointers))
|
||||
.map_ok(|[pitch, yaw, roll]| RadianEuler { pitch, yaw, roll })
|
||||
.collect::<Result<_, ModelError>>()?;
|
||||
RotationData::from(values)
|
||||
|
|
@ -414,10 +430,9 @@ fn read_animation(
|
|||
let position_data = if header.flags.contains(AnimationFlags::STUDIO_ANIM_RAWPOS) {
|
||||
PositionData::Vector48(read_single(data, position_offset)?)
|
||||
} else if header.flags.contains(AnimationFlags::STUDIO_ANIM_ANIMPOS) {
|
||||
let pointers: AnimationValuePointer = read_single(data, position_offset)?;
|
||||
let value_data = &data[position_offset..];
|
||||
let pointers: AnimationValuePointers = read_single(data, position_offset)?;
|
||||
let values = (0..frames)
|
||||
.map(|frame| read_animation_values(value_data, frame, pointers))
|
||||
.map(|frame| read_animation_values(frame, pointers))
|
||||
.map_ok(Vector::from)
|
||||
.collect::<Result<_, ModelError>>()?;
|
||||
PositionData::PositionValues(values)
|
||||
|
|
|
|||
|
|
@ -41,6 +41,12 @@ impl Display for BoneId {
|
|||
}
|
||||
}
|
||||
|
||||
impl PartialEq<u8> for BoneId {
|
||||
fn eq(&self, other: &u8) -> bool {
|
||||
self.0 == *other
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Zeroable, Pod)]
|
||||
#[repr(C)]
|
||||
pub struct BoneHeader {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{ModelError, StringError};
|
||||
use arrayvec::ArrayString;
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
use cgmath::{Angle, Deg, Euler, InnerSpace, Matrix3, Matrix4, Rad, Rotation3, Transform, Vector3};
|
||||
use cgmath::{Deg, Euler, Matrix3, Matrix4, Point3, Rad, Rotation3, Transform, Vector3};
|
||||
use std::f32::consts::PI;
|
||||
use std::fmt;
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
|
@ -35,6 +35,26 @@ impl From<Vector3<f32>> for Vector {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<Vector> for Point3<f32> {
|
||||
fn from(v: Vector) -> Self {
|
||||
Self {
|
||||
x: v.x,
|
||||
y: v.y,
|
||||
z: v.z,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Point3<f32>> for Vector {
|
||||
fn from(v: Point3<f32>) -> Self {
|
||||
Self {
|
||||
x: v.x,
|
||||
y: v.y,
|
||||
z: v.z,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Vector {
|
||||
pub fn iter(&self) -> impl Iterator<Item = f32> {
|
||||
[self.x, self.y, self.z].into_iter()
|
||||
|
|
@ -321,23 +341,15 @@ impl Transform3x4 {
|
|||
mapped_rotation.into()
|
||||
}
|
||||
|
||||
pub fn transform(&self, vec: Vector) -> Vector {
|
||||
let vec: Vector3<f32> = [vec.y, vec.z, vec.x].into();
|
||||
let z = vec.dot(self.x()) + self.transform[0][3];
|
||||
let x = vec.dot(self.y()) + self.transform[1][3];
|
||||
let y = vec.dot(self.z()) + self.transform[2][3];
|
||||
Vector { x, y, z }
|
||||
}
|
||||
|
||||
pub fn rotation(&self) -> Quaternion {
|
||||
cgmath::Quaternion::from(self.rotation_matrix()).into()
|
||||
}
|
||||
|
||||
pub fn translate(&self) -> Vector {
|
||||
[
|
||||
self.transform[2][3],
|
||||
self.transform[0][3],
|
||||
self.transform[1][3],
|
||||
self.transform[2][3],
|
||||
]
|
||||
.into()
|
||||
}
|
||||
|
|
@ -345,9 +357,8 @@ impl Transform3x4 {
|
|||
|
||||
impl From<Transform3x4> for Matrix4<f32> {
|
||||
fn from(value: Transform3x4) -> Self {
|
||||
let translate = value.translate();
|
||||
let rotate = value.rotation_matrix();
|
||||
let rotate = Matrix4::from(rotate);
|
||||
rotate * Matrix4::from_translation(translate.into())
|
||||
let translate = Matrix4::from_translation(value.translate().into());
|
||||
let rotate = Matrix4::from(value.rotation_matrix());
|
||||
rotate * translate
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue