mirror of
https://github.com/Theaninova/mhlib.git
synced 2025-12-11 03:56:18 +00:00
implement envelope
This commit is contained in:
@@ -26,26 +26,26 @@ Progress: About 90% ([LWO2 Spec](http://static.lightwave3d.com/sdk/2015/html/fil
|
||||
| Polygon Tag Mapping | `PTAG` | ✅ |
|
||||
| Discontinuous Vertex Mapping | `VMAD` | ✅ |
|
||||
| Vertex Map Parameter | `VMPA` | ✅ |
|
||||
| [Envelope Definition](#envelope-subchunks) | `ENVL` | ❌ |
|
||||
| [Envelope Definition](#envelope-subchunks) | `ENVL` | ✅ |
|
||||
| [Image (-Sequence)](#clip-subchunks) | `CLIP` | 🚧 |
|
||||
| [Surface Definition](#surface-subchunks) | `SURF` | 🚧 |
|
||||
| Bounding Box | `BBOX` | ✅ |
|
||||
| Description Line | `DESC` | ❌ |
|
||||
| Commentary Text | `TEXT` | ❌ |
|
||||
| Thumbnail Icon Image | `ICON` | ❌ |
|
||||
| Description Line | `DESC` | ✅ |
|
||||
| Commentary Text | `TEXT` | ✅ |
|
||||
| Thumbnail Icon Image | `ICON` | ✅ |
|
||||
|
||||
|
||||
### Envelope Subchunks
|
||||
|
||||
| Chunk | Tag | Status |
|
||||
|--------------------------|--------|--------|
|
||||
| Envelope Type | `TYPE` | ❌ |
|
||||
| Pre-Behavior | `PRE` | ❌ |
|
||||
| Post-Behavior | `POST` | ❌ |
|
||||
| Keyframe Time and Value | `KEY` | ❌ |
|
||||
| Interval Interpolation | `SPAN` | ❌ |
|
||||
| Plugin Channel Modifiers | `CHAN` | ❌ |
|
||||
| Channel Name | `NAME` | ❌ |
|
||||
| Envelope Type | `TYPE` | ✅ |
|
||||
| Pre-Behavior | `PRE` | ✅ |
|
||||
| Post-Behavior | `POST` | ✅ |
|
||||
| Keyframe Time and Value | `KEY` | ✅ |
|
||||
| Interval Interpolation | `SPAN` | ✅ |
|
||||
| Plugin Channel Modifiers | `CHAN` | ✅ |
|
||||
| Channel Name | `NAME` | ✅ |
|
||||
|
||||
|
||||
### Clip Subchunks
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
use binrw::binread;
|
||||
|
||||
/// The type subchunk records the format in which the envelope is displayed to the user and a type
|
||||
/// code that identifies the components of certain predefined envelope triples. The user format has
|
||||
/// no effect on the actual values, only the way they're presented in LightWave®'s interface.
|
||||
#[binread]
|
||||
#[br(import(_length: u32))]
|
||||
#[derive(Debug)]
|
||||
pub struct EnvelopeType {
|
||||
pub user_format: UserFormat,
|
||||
pub kind: EnvelopeKind,
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[br(repr = u8)]
|
||||
#[derive(Debug)]
|
||||
pub enum UserFormat {
|
||||
Float = 2,
|
||||
Distance = 3,
|
||||
Percent = 4,
|
||||
Angle = 5,
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[br(repr = u8)]
|
||||
#[derive(Debug)]
|
||||
pub enum EnvelopeKind {
|
||||
PositionX = 0x1,
|
||||
PositionY = 0x2,
|
||||
PositionZ = 0x3,
|
||||
RotHeading = 0x4,
|
||||
RotPitch = 0x5,
|
||||
RotBank = 0x6,
|
||||
ScaleX = 0x7,
|
||||
ScaleY = 0x8,
|
||||
ScaleZ = 0x9,
|
||||
ColorR = 0xa,
|
||||
ColorG = 0xb,
|
||||
ColorB = 0xc,
|
||||
FalloffX = 0xd,
|
||||
FalloffY = 0xe,
|
||||
FalloffZ = 0xf,
|
||||
}
|
||||
@@ -1,18 +1,9 @@
|
||||
use crate::lwo2::sub_tags::envelope_type::EnvelopeType;
|
||||
use crate::lwo2::vx;
|
||||
use binrw::binread;
|
||||
|
||||
pub mod blocks;
|
||||
pub mod envelope_type;
|
||||
pub mod surface_parameters;
|
||||
|
||||
#[binread]
|
||||
#[derive(Debug)]
|
||||
pub enum SubTag {
|
||||
#[br(magic(b"TYPE"))]
|
||||
EnvelopeType(EnvelopeType),
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[br(import(_length: u32))]
|
||||
#[derive(Debug)]
|
||||
|
||||
165
rust/lightwave/src/lwo2/tags/envelope.rs
Normal file
165
rust/lightwave/src/lwo2/tags/envelope.rs
Normal file
@@ -0,0 +1,165 @@
|
||||
use crate::binrw_helpers::until_size_limit;
|
||||
use crate::iff::SubChunk;
|
||||
use crate::lwo2::vx;
|
||||
use binrw::{binread, NullString, PosValue};
|
||||
|
||||
#[binread]
|
||||
#[br(import(length: u32))]
|
||||
#[derive(Debug)]
|
||||
pub struct EnvelopeDefinition {
|
||||
#[br(temp)]
|
||||
pos_start: PosValue<()>,
|
||||
#[br(parse_with = vx)]
|
||||
pub index: u32,
|
||||
#[br(temp)]
|
||||
pos_end: PosValue<()>,
|
||||
#[br(parse_with = until_size_limit(length as u64 - (pos_end.pos - pos_start.pos)))]
|
||||
pub attributes: Vec<EnvelopeSubChunk>,
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[derive(Debug)]
|
||||
pub enum EnvelopeSubChunk {
|
||||
#[br(magic(b"TYPE"))]
|
||||
EnvelopeType(SubChunk<EnvelopeType>),
|
||||
#[br(magic(b"PRE"))]
|
||||
PreBehavior(SubChunk<Behavior>),
|
||||
#[br(magic(b"POST"))]
|
||||
PostBehavior(SubChunk<Behavior>),
|
||||
#[br(magic(b"KEY"))]
|
||||
KeyframeTimeAndValue(SubChunk<KeyframeTimeAndValue>),
|
||||
#[br(magic(b"SPAN"))]
|
||||
IntervalInterpolation(SubChunk<IntervalInterpolation>),
|
||||
#[br(magic(b"CHAN"))]
|
||||
PluginChannelModifiers(SubChunk<PluginChannelModifiers>),
|
||||
#[br(magic(b"NAME"))]
|
||||
ChannelName(SubChunk<PluginChannelName>),
|
||||
}
|
||||
|
||||
/// An optional name for the envelope. LightWave® itself ignores the names of surface envelopes,
|
||||
/// but plug-ins can browse the envelope database by name.
|
||||
#[binread]
|
||||
#[br(import(_length: u32))]
|
||||
#[derive(Debug)]
|
||||
pub struct PluginChannelName {
|
||||
#[br(align_after = 2)]
|
||||
pub channel_name: NullString,
|
||||
}
|
||||
|
||||
/// Channel modifiers can be associated with an envelope. Each channel chunk contains the name of
|
||||
/// the plug-in and some flag bits. Only the first flag bit is defined; if set, the plug-in is
|
||||
/// disabled. The data that follows this, if any, is owned by the plug-in.
|
||||
#[binread]
|
||||
#[br(import(length: u32))]
|
||||
#[derive(Debug)]
|
||||
pub struct PluginChannelModifiers {
|
||||
#[br(temp)]
|
||||
start_pos: PosValue<()>,
|
||||
#[br(align_after = 2)]
|
||||
pub server_name: NullString,
|
||||
pub flags: u16,
|
||||
#[br(temp)]
|
||||
end_pos: PosValue<()>,
|
||||
#[br(count = length as u64 - (end_pos.pos - start_pos.pos))]
|
||||
pub parameters: Vec<u8>,
|
||||
}
|
||||
|
||||
/// Defines the interpolation between the most recent KEY chunk and the KEY immediately before it in
|
||||
/// time. The type identifies the interpolation algorithm and can be STEP, LINE, TCB
|
||||
/// (Kochanek-Bartels), HERM (Hermite), BEZI (1D Bezier) or BEZ2 (2D Bezier).
|
||||
/// Different parameters are stored for each of these.
|
||||
#[binread]
|
||||
#[br(import(length: u32))]
|
||||
#[derive(Debug)]
|
||||
pub struct IntervalInterpolation {
|
||||
pub kind: IntervalInterpolationType,
|
||||
#[br(count = (length - 4) / 4)]
|
||||
pub parameters: Vec<f32>,
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[derive(Debug)]
|
||||
pub enum IntervalInterpolationType {
|
||||
#[br(magic(b"STEP"))]
|
||||
Step,
|
||||
#[br(magic(b"LINE"))]
|
||||
Line,
|
||||
#[br(magic(b"TCB\0"))]
|
||||
KochanekBartels,
|
||||
#[br(magic(b"HERM"))]
|
||||
Hermite,
|
||||
#[br(magic(b"BEZI"))]
|
||||
Bezier1D,
|
||||
#[br(magic(b"BEZ2"))]
|
||||
Bezier2D,
|
||||
}
|
||||
|
||||
/// The value of the envelope at the specified time in seconds. The signal value between keyframes
|
||||
/// is interpolated. The time of a keyframe isn't restricted to integer frames.
|
||||
#[binread]
|
||||
#[br(import(_length: u32))]
|
||||
#[derive(Debug)]
|
||||
pub struct KeyframeTimeAndValue {
|
||||
pub time: f32,
|
||||
pub value: f32,
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[br(repr = u16, import(_length: u32))]
|
||||
#[derive(Debug)]
|
||||
pub enum Behavior {
|
||||
/// Sets the value to 0.0.
|
||||
Reset = 0,
|
||||
/// Sets the value to the value at the nearest key.
|
||||
Constant = 1,
|
||||
/// Repeats the interval between the first and last keys (the primary interval).
|
||||
Repeat = 2,
|
||||
/// Like Repeat, but alternating copies of the primary interval are time-reversed.
|
||||
Oscillate = 3,
|
||||
/// Like Repeat, but offset by the difference between the values of the first and last keys.
|
||||
OffsetRepeat = 4,
|
||||
/// Linearly extrapolates the value based on the tangent at the nearest key.
|
||||
Linear = 5,
|
||||
}
|
||||
|
||||
/// The type subchunk records the format in which the envelope is displayed to the user and a type
|
||||
/// code that identifies the components of certain predefined envelope triples. The user format has
|
||||
/// no effect on the actual values, only the way they're presented in LightWave®'s interface.
|
||||
#[binread]
|
||||
#[br(import(_length: u32))]
|
||||
#[derive(Debug)]
|
||||
pub struct EnvelopeType {
|
||||
pub user_format: UserFormat,
|
||||
pub kind: EnvelopeKind,
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[br(repr = u8)]
|
||||
#[derive(Debug)]
|
||||
pub enum UserFormat {
|
||||
Float = 2,
|
||||
Distance = 3,
|
||||
Percent = 4,
|
||||
Angle = 5,
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[br(repr = u8)]
|
||||
#[derive(Debug)]
|
||||
pub enum EnvelopeKind {
|
||||
PositionX = 0x1,
|
||||
PositionY = 0x2,
|
||||
PositionZ = 0x3,
|
||||
RotHeading = 0x4,
|
||||
RotPitch = 0x5,
|
||||
RotBank = 0x6,
|
||||
ScaleX = 0x7,
|
||||
ScaleY = 0x8,
|
||||
ScaleZ = 0x9,
|
||||
ColorR = 0xa,
|
||||
ColorG = 0xb,
|
||||
ColorB = 0xc,
|
||||
FalloffX = 0xd,
|
||||
FalloffY = 0xe,
|
||||
FalloffZ = 0xf,
|
||||
}
|
||||
35
rust/lightwave/src/lwo2/tags/meta.rs
Normal file
35
rust/lightwave/src/lwo2/tags/meta.rs
Normal file
@@ -0,0 +1,35 @@
|
||||
use binrw::{binread, NullString};
|
||||
|
||||
/// Store an object description. Optional. This should be a simple line of upper and lowercase
|
||||
/// characters, punctuation and spaces which describes the contents of the object file. There
|
||||
/// should be no control characters in this text string and it should generally be kept short.
|
||||
#[binread]
|
||||
#[br(import(_length: u32))]
|
||||
#[derive(Debug)]
|
||||
pub struct DescriptionLine {
|
||||
#[br(align_after = 2)]
|
||||
pub description_line: NullString,
|
||||
}
|
||||
|
||||
/// An iconic or thumbnail image for the object which can be used when viewing the file in a
|
||||
/// browser. Currently the only suported encoding is 0, meaning uncompressed RGB byte triples.
|
||||
/// The width is the number of pixels in each row of the image, and the height (number of rows)
|
||||
/// is (chunkSize - 4)/width. This chunk is optional.
|
||||
#[binread]
|
||||
#[br(import(length: u32))]
|
||||
#[derive(Debug)]
|
||||
pub struct ThumbnailIconImage {
|
||||
pub encoding: ThumbnailImageEncoding,
|
||||
pub width: u16,
|
||||
#[br(calc = (length as u16 - 4) / width)]
|
||||
pub height: u16,
|
||||
#[br(count = length - 4)]
|
||||
pub data: Vec<u8>,
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[br(repr = u16)]
|
||||
#[derive(Debug)]
|
||||
pub enum ThumbnailImageEncoding {
|
||||
UncompressedRgb = 0,
|
||||
}
|
||||
@@ -3,6 +3,7 @@ use crate::lwo2::tags::bounding_box::BoundingBox;
|
||||
use crate::lwo2::tags::discontinuous_vertex_mapping::DiscontinuousVertexMappings;
|
||||
use crate::lwo2::tags::image_clip::ImageClip;
|
||||
use crate::lwo2::tags::layer::Layer;
|
||||
use crate::lwo2::tags::meta::{DescriptionLine, ThumbnailIconImage};
|
||||
use crate::lwo2::tags::point_list::PointList;
|
||||
use crate::lwo2::tags::polygon_list::PolygonLists;
|
||||
use crate::lwo2::tags::polygon_tag_mapping::PolygonTagMappings;
|
||||
@@ -14,8 +15,10 @@ use binrw::binread;
|
||||
|
||||
pub mod bounding_box;
|
||||
pub mod discontinuous_vertex_mapping;
|
||||
pub mod envelope;
|
||||
pub mod image_clip;
|
||||
pub mod layer;
|
||||
pub mod meta;
|
||||
pub mod point_list;
|
||||
pub mod polygon_list;
|
||||
pub mod polygon_tag_mapping;
|
||||
@@ -43,6 +46,12 @@ pub enum Tag {
|
||||
VertexMapParameter(Chunk<VertexMapParameter>),
|
||||
#[br(magic(b"BBOX"))]
|
||||
BoundingBox(Chunk<BoundingBox>),
|
||||
#[br(magic(b"DESC"))]
|
||||
DescriptionLine(Chunk<DescriptionLine>),
|
||||
#[br(magic(b"TEXT"))]
|
||||
CommentaryText(Chunk<DescriptionLine>),
|
||||
#[br(magic(b"ICON"))]
|
||||
ThumbnailIconImage(Chunk<ThumbnailIconImage>),
|
||||
#[br(magic(b"POLS"))]
|
||||
PolygonList(Chunk<PolygonLists>),
|
||||
#[br(magic(b"SURF"))]
|
||||
@@ -50,4 +59,3 @@ pub enum Tag {
|
||||
#[br(magic(b"CLIP"))]
|
||||
ImageClip(Chunk<ImageClip>),
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user