mirror of
https://codeberg.org/icewind/vmdl.git
synced 2026-06-03 16:44:11 +02:00
misc animation stuff
This commit is contained in:
parent
20bd028b8a
commit
ac236685ce
5 changed files with 61 additions and 46 deletions
19
src/lib.rs
19
src/lib.rs
|
|
@ -293,7 +293,7 @@ fn index_range(index: i32, count: i32, size: usize) -> impl Iterator<Item = usiz
|
||||||
.map(move |i| index as usize + i)
|
.map(move |i| index as usize + i)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_relative_iter<'a, T: ReadRelative, I: 'a + Iterator<Item = usize>>(
|
fn read_relative_iter<'a, T: ReadRelative<'a>, I: 'a + Iterator<Item = usize>>(
|
||||||
data: &'a [u8],
|
data: &'a [u8],
|
||||||
indexes: I,
|
indexes: I,
|
||||||
) -> impl Iterator<Item = Result<T, ModelError>> + 'a {
|
) -> impl Iterator<Item = Result<T, ModelError>> + 'a {
|
||||||
|
|
@ -307,14 +307,17 @@ fn read_relative_iter<'a, T: ReadRelative, I: 'a + Iterator<Item = usize>>(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_relative<T: ReadRelative, I: Iterator<Item = usize>>(
|
fn read_relative<'a, T: ReadRelative<'a>, I: Iterator<Item = usize> + 'a>(
|
||||||
data: &[u8],
|
data: &'a [u8],
|
||||||
indexes: I,
|
indexes: I,
|
||||||
) -> Result<Vec<T>, ModelError> {
|
) -> Result<Vec<T>, ModelError> {
|
||||||
read_relative_iter(data, indexes).collect()
|
read_relative_iter(data, indexes).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_single<T: ReadRelative, I: TryInto<usize>>(data: &[u8], index: I) -> Result<T, ModelError> {
|
fn read_single<'a, T: ReadRelative<'a>, I: TryInto<usize>>(
|
||||||
|
data: &'a [u8],
|
||||||
|
index: I,
|
||||||
|
) -> Result<T, ModelError> {
|
||||||
let index = index.try_into().map_err(|_| ModelError::OutOfBounds {
|
let index = index.try_into().map_err(|_| ModelError::OutOfBounds {
|
||||||
data: type_name::<T>(),
|
data: type_name::<T>(),
|
||||||
offset: usize::MAX_VALUE,
|
offset: usize::MAX_VALUE,
|
||||||
|
|
@ -340,10 +343,10 @@ impl<T: Pod> Readable for T {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait ReadRelative: Sized {
|
trait ReadRelative<'a>: Sized {
|
||||||
type Header: Readable;
|
type Header: Readable;
|
||||||
|
|
||||||
fn read(data: &[u8], header: Self::Header) -> Result<Self, ModelError>;
|
fn read(data: &'a [u8], header: Self::Header) -> Result<Self, ModelError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
trait ReadableRelative: Readable {}
|
trait ReadableRelative: Readable {}
|
||||||
|
|
@ -360,7 +363,7 @@ impl<T: ReadableRelative + Pod> ReadableRelative for [T; 2] {}
|
||||||
impl<T: ReadableRelative + Pod> ReadableRelative for [T; 3] {}
|
impl<T: ReadableRelative + Pod> ReadableRelative for [T; 3] {}
|
||||||
impl<T: ReadableRelative + Pod> ReadableRelative for [T; 4] {}
|
impl<T: ReadableRelative + Pod> ReadableRelative for [T; 4] {}
|
||||||
|
|
||||||
impl<T: ReadableRelative> ReadRelative for T {
|
impl<T: ReadableRelative> ReadRelative<'_> for T {
|
||||||
type Header = T;
|
type Header = T;
|
||||||
|
|
||||||
fn read(_data: &[u8], header: Self::Header) -> Result<Self, ModelError> {
|
fn read(_data: &[u8], header: Self::Header) -> Result<Self, ModelError> {
|
||||||
|
|
@ -368,7 +371,7 @@ impl<T: ReadableRelative> ReadRelative for T {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReadRelative for String {
|
impl ReadRelative<'_> for String {
|
||||||
type Header = ();
|
type Header = ();
|
||||||
|
|
||||||
fn read(data: &[u8], _header: Self::Header) -> Result<Self, ModelError> {
|
fn read(data: &[u8], _header: Self::Header) -> Result<Self, ModelError> {
|
||||||
|
|
|
||||||
|
|
@ -129,7 +129,7 @@ pub struct BodyPart {
|
||||||
pub models: Vec<Model>,
|
pub models: Vec<Model>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReadRelative for BodyPart {
|
impl ReadRelative<'_> for BodyPart {
|
||||||
type Header = BodyPartHeader;
|
type Header = BodyPartHeader;
|
||||||
|
|
||||||
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
||||||
|
|
@ -150,7 +150,7 @@ pub struct Model {
|
||||||
pub vertex_offset: i32,
|
pub vertex_offset: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReadRelative for Model {
|
impl ReadRelative<'_> for Model {
|
||||||
type Header = ModelHeader;
|
type Header = ModelHeader;
|
||||||
|
|
||||||
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
||||||
|
|
@ -170,7 +170,7 @@ pub struct Mesh {
|
||||||
pub vertex_offset: i32,
|
pub vertex_offset: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReadRelative for Mesh {
|
impl ReadRelative<'_> for Mesh {
|
||||||
type Header = MeshHeader;
|
type Header = MeshHeader;
|
||||||
|
|
||||||
fn read(_data: &[u8], header: Self::Header) -> Result<Self> {
|
fn read(_data: &[u8], header: Self::Header) -> Result<Self> {
|
||||||
|
|
@ -188,7 +188,7 @@ pub struct TextureInfo {
|
||||||
pub search_paths: Vec<String>,
|
pub search_paths: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReadRelative for TextureInfo {
|
impl ReadRelative<'_> for TextureInfo {
|
||||||
type Header = MeshTexture;
|
type Header = MeshTexture;
|
||||||
|
|
||||||
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
||||||
|
|
@ -212,7 +212,7 @@ pub struct StudioAttachment {
|
||||||
pub local: Transform3x4,
|
pub local: Transform3x4,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReadRelative for StudioAttachment {
|
impl ReadRelative<'_> for StudioAttachment {
|
||||||
type Header = StudioAttachmentHeader;
|
type Header = StudioAttachmentHeader;
|
||||||
|
|
||||||
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
||||||
|
|
@ -235,7 +235,7 @@ pub struct HitBoxSet {
|
||||||
pub boxes: Vec<BoundingBox>,
|
pub boxes: Vec<BoundingBox>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReadRelative for HitBoxSet {
|
impl ReadRelative<'_> for HitBoxSet {
|
||||||
type Header = HitBoxSetHeader;
|
type Header = HitBoxSetHeader;
|
||||||
|
|
||||||
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
||||||
|
|
@ -259,7 +259,7 @@ pub struct BoundingBox {
|
||||||
pub max: Vector,
|
pub max: Vector,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReadRelative for BoundingBox {
|
impl ReadRelative<'_> for BoundingBox {
|
||||||
type Header = BoundingBoxHeader;
|
type Header = BoundingBoxHeader;
|
||||||
|
|
||||||
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ pub struct PoseParameterDescription {
|
||||||
pub loop_range: f32,
|
pub loop_range: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReadRelative for PoseParameterDescription {
|
impl ReadRelative<'_> for PoseParameterDescription {
|
||||||
type Header = PoseParameterDescriptionHeader;
|
type Header = PoseParameterDescriptionHeader;
|
||||||
|
|
||||||
fn read(data: &[u8], header: Self::Header) -> Result<Self, ModelError> {
|
fn read(data: &[u8], header: Self::Header) -> Result<Self, ModelError> {
|
||||||
|
|
@ -90,7 +90,7 @@ pub struct AnimationDescription {
|
||||||
pub animations: Vec<Animation>,
|
pub animations: Vec<Animation>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReadRelative for AnimationDescription {
|
impl ReadRelative<'_> for AnimationDescription {
|
||||||
type Header = AnimationDescriptionHeader;
|
type Header = AnimationDescriptionHeader;
|
||||||
|
|
||||||
fn read(data: &[u8], header: Self::Header) -> Result<Self, ModelError> {
|
fn read(data: &[u8], header: Self::Header) -> Result<Self, ModelError> {
|
||||||
|
|
@ -166,6 +166,9 @@ struct ValueHeader {
|
||||||
valid: u8,
|
valid: u8,
|
||||||
total: u8,
|
total: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static_assertions::const_assert_eq!(size_of::<ValueHeader>(), size_of::<i16>());
|
||||||
|
|
||||||
impl ReadableRelative for ValueHeader {}
|
impl ReadableRelative for ValueHeader {}
|
||||||
|
|
||||||
fn read_animation_values(
|
fn read_animation_values(
|
||||||
|
|
@ -177,17 +180,14 @@ fn read_animation_values(
|
||||||
.0
|
.0
|
||||||
.map::<_, Result<_, ModelError>>(|base_pointer| {
|
.map::<_, Result<_, ModelError>>(|base_pointer| {
|
||||||
if base_pointer == 0 {
|
if base_pointer == 0 {
|
||||||
Ok(0.0)
|
Ok(0)
|
||||||
} else {
|
} else {
|
||||||
let header = read_single(data, base_pointer)?;
|
let values: FrameValues = read_single(data, base_pointer)?;
|
||||||
let values = FrameValues {
|
Ok(values.get(frame as u8)?)
|
||||||
header,
|
|
||||||
data: &data[base_pointer as usize..],
|
|
||||||
};
|
|
||||||
Ok(values.get(frame as u8)? as f32)
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Ok([x?, y?, z?])
|
let [x, y, z] = [x?, y?, z?];
|
||||||
|
Ok([x as f32, y as f32, z as f32])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// I hate this data structure
|
/// I hate this data structure
|
||||||
|
|
@ -206,25 +206,37 @@ struct FrameValues<'a> {
|
||||||
data: &'a [u8], // data starting at self.header
|
data: &'a [u8], // data starting at self.header
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> ReadRelative<'a> for FrameValues<'a> {
|
||||||
|
type Header = ValueHeader;
|
||||||
|
|
||||||
|
fn read(data: &'a [u8], header: Self::Header) -> Result<Self, ModelError> {
|
||||||
|
Ok(FrameValues {
|
||||||
|
header,
|
||||||
|
data: &data
|
||||||
|
.get(size_of::<ValueHeader>()..)
|
||||||
|
.ok_or(ModelError::OutOfBounds {
|
||||||
|
data: "animation frame data",
|
||||||
|
offset: size_of::<ValueHeader>(),
|
||||||
|
})?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl FrameValues<'_> {
|
impl FrameValues<'_> {
|
||||||
pub fn get(&self, index: u8) -> Result<i16, ModelError> {
|
pub fn get(&self, index: u8) -> Result<i16, ModelError> {
|
||||||
if self.header.total <= index {
|
if self.header.total <= index {
|
||||||
let offset_count = self.header.valid + 1;
|
let offset_count = self.header.valid;
|
||||||
let offset = (offset_count as usize) * size_of::<ValueHeader>();
|
let offset = (offset_count as usize) * size_of::<ValueHeader>();
|
||||||
let next_header: ValueHeader = read_single(self.data, offset)?;
|
let next: FrameValues = read_single(self.data, offset)?;
|
||||||
let next = FrameValues {
|
if next.header.total == 0 {
|
||||||
header: next_header,
|
|
||||||
data: &self.data[offset..],
|
|
||||||
};
|
|
||||||
if next_header.total == 0 {
|
|
||||||
return Ok(0);
|
return Ok(0);
|
||||||
}
|
}
|
||||||
next.get(index - self.header.total)
|
next.get(index - self.header.total)
|
||||||
} else {
|
} else {
|
||||||
let offset_count = if self.header.valid > index {
|
let offset_count = if index < self.header.valid {
|
||||||
index + 1
|
index
|
||||||
} else {
|
} else {
|
||||||
self.header.valid
|
self.header.valid - 1
|
||||||
};
|
};
|
||||||
let offset = (offset_count as usize) * size_of::<i16>();
|
let offset = (offset_count as usize) * size_of::<i16>();
|
||||||
read_single(self.data, offset)
|
read_single(self.data, offset)
|
||||||
|
|
@ -391,7 +403,7 @@ fn read_animation(
|
||||||
let value_data = &data[offset..];
|
let value_data = &data[offset..];
|
||||||
let values: Vec<RadianEuler> = (0..frames)
|
let values: Vec<RadianEuler> = (0..frames)
|
||||||
.map(|frame| read_animation_values(value_data, frame, pointers))
|
.map(|frame| read_animation_values(value_data, frame, pointers))
|
||||||
.map_ok(|[pitch, yaw, roll]| RadianEuler { roll, yaw, pitch })
|
.map_ok(|[pitch, yaw, roll]| RadianEuler { pitch, yaw, roll })
|
||||||
.collect::<Result<_, ModelError>>()?;
|
.collect::<Result<_, ModelError>>()?;
|
||||||
RotationData::from(values)
|
RotationData::from(values)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -518,7 +530,7 @@ pub struct AnimationSequence {
|
||||||
pub bone_weights: Vec<f32>,
|
pub bone_weights: Vec<f32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReadRelative for AnimationSequence {
|
impl ReadRelative<'_> for AnimationSequence {
|
||||||
type Header = AnimationSequenceHeader;
|
type Header = AnimationSequenceHeader;
|
||||||
|
|
||||||
fn read(data: &[u8], header: Self::Header) -> Result<Self, ModelError> {
|
fn read(data: &[u8], header: Self::Header) -> Result<Self, ModelError> {
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@ pub struct Bone {
|
||||||
pub contents: ContentFlags,
|
pub contents: ContentFlags,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReadRelative for Bone {
|
impl ReadRelative<'_> for Bone {
|
||||||
type Header = BoneHeader;
|
type Header = BoneHeader;
|
||||||
|
|
||||||
fn read(data: &[u8], header: Self::Header) -> Result<Self, ModelError> {
|
fn read(data: &[u8], header: Self::Header) -> Result<Self, ModelError> {
|
||||||
|
|
@ -364,7 +364,7 @@ pub struct SourceBoneTransform {
|
||||||
pub post_transform: Transform3x4,
|
pub post_transform: Transform3x4,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReadRelative for SourceBoneTransform {
|
impl ReadRelative<'_> for SourceBoneTransform {
|
||||||
type Header = SourceBoneTransformHeader;
|
type Header = SourceBoneTransformHeader;
|
||||||
|
|
||||||
fn read(data: &[u8], header: Self::Header) -> Result<Self, ModelError> {
|
fn read(data: &[u8], header: Self::Header) -> Result<Self, ModelError> {
|
||||||
|
|
@ -427,7 +427,7 @@ pub struct BoneController {
|
||||||
pub input_field: i32,
|
pub input_field: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReadRelative for BoneController {
|
impl ReadRelative<'_> for BoneController {
|
||||||
type Header = BoneControllerHeader;
|
type Header = BoneControllerHeader;
|
||||||
|
|
||||||
fn read(_data: &[u8], header: Self::Header) -> Result<Self, ModelError> {
|
fn read(_data: &[u8], header: Self::Header) -> Result<Self, ModelError> {
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ pub struct BodyPart {
|
||||||
pub models: Vec<Model>,
|
pub models: Vec<Model>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReadRelative for BodyPart {
|
impl ReadRelative<'_> for BodyPart {
|
||||||
type Header = BodyPartHeader;
|
type Header = BodyPartHeader;
|
||||||
|
|
||||||
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
||||||
|
|
@ -47,7 +47,7 @@ pub struct Model {
|
||||||
pub lods: Vec<ModelLod>,
|
pub lods: Vec<ModelLod>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReadRelative for Model {
|
impl ReadRelative<'_> for Model {
|
||||||
type Header = ModelHeader;
|
type Header = ModelHeader;
|
||||||
|
|
||||||
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
||||||
|
|
@ -63,7 +63,7 @@ pub struct ModelLod {
|
||||||
pub switch_point: f32,
|
pub switch_point: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReadRelative for ModelLod {
|
impl ReadRelative<'_> for ModelLod {
|
||||||
type Header = ModelLodHeader;
|
type Header = ModelLodHeader;
|
||||||
|
|
||||||
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
||||||
|
|
@ -80,7 +80,7 @@ pub struct Mesh {
|
||||||
pub flags: MeshFlags,
|
pub flags: MeshFlags,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReadRelative for Mesh {
|
impl ReadRelative<'_> for Mesh {
|
||||||
type Header = MeshHeader;
|
type Header = MeshHeader;
|
||||||
|
|
||||||
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
||||||
|
|
@ -100,7 +100,7 @@ pub struct StripGroup {
|
||||||
pub flags: StripGroupFlags,
|
pub flags: StripGroupFlags,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReadRelative for StripGroup {
|
impl ReadRelative<'_> for StripGroup {
|
||||||
type Header = StripGroupHeader;
|
type Header = StripGroupHeader;
|
||||||
|
|
||||||
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
||||||
|
|
@ -121,7 +121,7 @@ pub struct Strip {
|
||||||
indices: Range<usize>,
|
indices: Range<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReadRelative for Strip {
|
impl ReadRelative<'_> for Strip {
|
||||||
type Header = StripHeader;
|
type Header = StripHeader;
|
||||||
|
|
||||||
fn read(_data: &[u8], header: Self::Header) -> Result<Self> {
|
fn read(_data: &[u8], header: Self::Header) -> Result<Self> {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue