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)
|
||||
}
|
||||
|
||||
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],
|
||||
indexes: I,
|
||||
) -> 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>>(
|
||||
data: &[u8],
|
||||
fn read_relative<'a, T: ReadRelative<'a>, I: Iterator<Item = usize> + 'a>(
|
||||
data: &'a [u8],
|
||||
indexes: I,
|
||||
) -> Result<Vec<T>, ModelError> {
|
||||
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 {
|
||||
data: type_name::<T>(),
|
||||
offset: usize::MAX_VALUE,
|
||||
|
|
@ -340,10 +343,10 @@ impl<T: Pod> Readable for T {
|
|||
}
|
||||
}
|
||||
|
||||
trait ReadRelative: Sized {
|
||||
trait ReadRelative<'a>: Sized {
|
||||
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 {}
|
||||
|
|
@ -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; 4] {}
|
||||
|
||||
impl<T: ReadableRelative> ReadRelative for T {
|
||||
impl<T: ReadableRelative> ReadRelative<'_> for T {
|
||||
type Header = T;
|
||||
|
||||
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 = ();
|
||||
|
||||
fn read(data: &[u8], _header: Self::Header) -> Result<Self, ModelError> {
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ pub struct BodyPart {
|
|||
pub models: Vec<Model>,
|
||||
}
|
||||
|
||||
impl ReadRelative for BodyPart {
|
||||
impl ReadRelative<'_> for BodyPart {
|
||||
type Header = BodyPartHeader;
|
||||
|
||||
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
||||
|
|
@ -150,7 +150,7 @@ pub struct Model {
|
|||
pub vertex_offset: i32,
|
||||
}
|
||||
|
||||
impl ReadRelative for Model {
|
||||
impl ReadRelative<'_> for Model {
|
||||
type Header = ModelHeader;
|
||||
|
||||
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
||||
|
|
@ -170,7 +170,7 @@ pub struct Mesh {
|
|||
pub vertex_offset: i32,
|
||||
}
|
||||
|
||||
impl ReadRelative for Mesh {
|
||||
impl ReadRelative<'_> for Mesh {
|
||||
type Header = MeshHeader;
|
||||
|
||||
fn read(_data: &[u8], header: Self::Header) -> Result<Self> {
|
||||
|
|
@ -188,7 +188,7 @@ pub struct TextureInfo {
|
|||
pub search_paths: Vec<String>,
|
||||
}
|
||||
|
||||
impl ReadRelative for TextureInfo {
|
||||
impl ReadRelative<'_> for TextureInfo {
|
||||
type Header = MeshTexture;
|
||||
|
||||
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
||||
|
|
@ -212,7 +212,7 @@ pub struct StudioAttachment {
|
|||
pub local: Transform3x4,
|
||||
}
|
||||
|
||||
impl ReadRelative for StudioAttachment {
|
||||
impl ReadRelative<'_> for StudioAttachment {
|
||||
type Header = StudioAttachmentHeader;
|
||||
|
||||
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
||||
|
|
@ -235,7 +235,7 @@ pub struct HitBoxSet {
|
|||
pub boxes: Vec<BoundingBox>,
|
||||
}
|
||||
|
||||
impl ReadRelative for HitBoxSet {
|
||||
impl ReadRelative<'_> for HitBoxSet {
|
||||
type Header = HitBoxSetHeader;
|
||||
|
||||
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
||||
|
|
@ -259,7 +259,7 @@ pub struct BoundingBox {
|
|||
pub max: Vector,
|
||||
}
|
||||
|
||||
impl ReadRelative for BoundingBox {
|
||||
impl ReadRelative<'_> for BoundingBox {
|
||||
type Header = BoundingBoxHeader;
|
||||
|
||||
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ pub struct PoseParameterDescription {
|
|||
pub loop_range: f32,
|
||||
}
|
||||
|
||||
impl ReadRelative for PoseParameterDescription {
|
||||
impl ReadRelative<'_> for PoseParameterDescription {
|
||||
type Header = PoseParameterDescriptionHeader;
|
||||
|
||||
fn read(data: &[u8], header: Self::Header) -> Result<Self, ModelError> {
|
||||
|
|
@ -90,7 +90,7 @@ pub struct AnimationDescription {
|
|||
pub animations: Vec<Animation>,
|
||||
}
|
||||
|
||||
impl ReadRelative for AnimationDescription {
|
||||
impl ReadRelative<'_> for AnimationDescription {
|
||||
type Header = AnimationDescriptionHeader;
|
||||
|
||||
fn read(data: &[u8], header: Self::Header) -> Result<Self, ModelError> {
|
||||
|
|
@ -166,6 +166,9 @@ struct ValueHeader {
|
|||
valid: u8,
|
||||
total: u8,
|
||||
}
|
||||
|
||||
static_assertions::const_assert_eq!(size_of::<ValueHeader>(), size_of::<i16>());
|
||||
|
||||
impl ReadableRelative for ValueHeader {}
|
||||
|
||||
fn read_animation_values(
|
||||
|
|
@ -177,17 +180,14 @@ fn read_animation_values(
|
|||
.0
|
||||
.map::<_, Result<_, ModelError>>(|base_pointer| {
|
||||
if base_pointer == 0 {
|
||||
Ok(0.0)
|
||||
Ok(0)
|
||||
} else {
|
||||
let header = read_single(data, base_pointer)?;
|
||||
let values = FrameValues {
|
||||
header,
|
||||
data: &data[base_pointer as usize..],
|
||||
};
|
||||
Ok(values.get(frame as u8)? as f32)
|
||||
let values: FrameValues = read_single(data, base_pointer)?;
|
||||
Ok(values.get(frame as u8)?)
|
||||
}
|
||||
});
|
||||
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
|
||||
|
|
@ -206,25 +206,37 @@ struct FrameValues<'a> {
|
|||
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<'_> {
|
||||
pub fn get(&self, index: u8) -> Result<i16, ModelError> {
|
||||
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 next_header: ValueHeader = read_single(self.data, offset)?;
|
||||
let next = FrameValues {
|
||||
header: next_header,
|
||||
data: &self.data[offset..],
|
||||
};
|
||||
if next_header.total == 0 {
|
||||
let next: FrameValues = read_single(self.data, offset)?;
|
||||
if next.header.total == 0 {
|
||||
return Ok(0);
|
||||
}
|
||||
next.get(index - self.header.total)
|
||||
} else {
|
||||
let offset_count = if self.header.valid > index {
|
||||
index + 1
|
||||
let offset_count = if index < self.header.valid {
|
||||
index
|
||||
} else {
|
||||
self.header.valid
|
||||
self.header.valid - 1
|
||||
};
|
||||
let offset = (offset_count as usize) * size_of::<i16>();
|
||||
read_single(self.data, offset)
|
||||
|
|
@ -391,7 +403,7 @@ fn read_animation(
|
|||
let value_data = &data[offset..];
|
||||
let values: Vec<RadianEuler> = (0..frames)
|
||||
.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>>()?;
|
||||
RotationData::from(values)
|
||||
} else {
|
||||
|
|
@ -518,7 +530,7 @@ pub struct AnimationSequence {
|
|||
pub bone_weights: Vec<f32>,
|
||||
}
|
||||
|
||||
impl ReadRelative for AnimationSequence {
|
||||
impl ReadRelative<'_> for AnimationSequence {
|
||||
type Header = AnimationSequenceHeader;
|
||||
|
||||
fn read(data: &[u8], header: Self::Header) -> Result<Self, ModelError> {
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ pub struct Bone {
|
|||
pub contents: ContentFlags,
|
||||
}
|
||||
|
||||
impl ReadRelative for Bone {
|
||||
impl ReadRelative<'_> for Bone {
|
||||
type Header = BoneHeader;
|
||||
|
||||
fn read(data: &[u8], header: Self::Header) -> Result<Self, ModelError> {
|
||||
|
|
@ -364,7 +364,7 @@ pub struct SourceBoneTransform {
|
|||
pub post_transform: Transform3x4,
|
||||
}
|
||||
|
||||
impl ReadRelative for SourceBoneTransform {
|
||||
impl ReadRelative<'_> for SourceBoneTransform {
|
||||
type Header = SourceBoneTransformHeader;
|
||||
|
||||
fn read(data: &[u8], header: Self::Header) -> Result<Self, ModelError> {
|
||||
|
|
@ -427,7 +427,7 @@ pub struct BoneController {
|
|||
pub input_field: i32,
|
||||
}
|
||||
|
||||
impl ReadRelative for BoneController {
|
||||
impl ReadRelative<'_> for BoneController {
|
||||
type Header = BoneControllerHeader;
|
||||
|
||||
fn read(_data: &[u8], header: Self::Header) -> Result<Self, ModelError> {
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ pub struct BodyPart {
|
|||
pub models: Vec<Model>,
|
||||
}
|
||||
|
||||
impl ReadRelative for BodyPart {
|
||||
impl ReadRelative<'_> for BodyPart {
|
||||
type Header = BodyPartHeader;
|
||||
|
||||
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
||||
|
|
@ -47,7 +47,7 @@ pub struct Model {
|
|||
pub lods: Vec<ModelLod>,
|
||||
}
|
||||
|
||||
impl ReadRelative for Model {
|
||||
impl ReadRelative<'_> for Model {
|
||||
type Header = ModelHeader;
|
||||
|
||||
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
||||
|
|
@ -63,7 +63,7 @@ pub struct ModelLod {
|
|||
pub switch_point: f32,
|
||||
}
|
||||
|
||||
impl ReadRelative for ModelLod {
|
||||
impl ReadRelative<'_> for ModelLod {
|
||||
type Header = ModelLodHeader;
|
||||
|
||||
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
||||
|
|
@ -80,7 +80,7 @@ pub struct Mesh {
|
|||
pub flags: MeshFlags,
|
||||
}
|
||||
|
||||
impl ReadRelative for Mesh {
|
||||
impl ReadRelative<'_> for Mesh {
|
||||
type Header = MeshHeader;
|
||||
|
||||
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
||||
|
|
@ -100,7 +100,7 @@ pub struct StripGroup {
|
|||
pub flags: StripGroupFlags,
|
||||
}
|
||||
|
||||
impl ReadRelative for StripGroup {
|
||||
impl ReadRelative<'_> for StripGroup {
|
||||
type Header = StripGroupHeader;
|
||||
|
||||
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
||||
|
|
@ -121,7 +121,7 @@ pub struct Strip {
|
|||
indices: Range<usize>,
|
||||
}
|
||||
|
||||
impl ReadRelative for Strip {
|
||||
impl ReadRelative<'_> for Strip {
|
||||
type Header = StripHeader;
|
||||
|
||||
fn read(_data: &[u8], header: Self::Header) -> Result<Self> {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue