diff --git a/rust/lightwave/README.md b/rust/lightwave/README.md
index 4d98514..4145081 100644
--- a/rust/lightwave/README.md
+++ b/rust/lightwave/README.md
@@ -1,4 +1,161 @@
# LightWave 3D Rust Parser
-* [LWO2 Spec](http://static.lightwave3d.com/sdk/2015/html/filefmts/lwo2.html)
- * Progress: about 90% (?) complete, so most things should load.
\ No newline at end of file
+## LightWave Object (LWO2)
+
+Progress: About 90% ([LWO2 Spec](http://static.lightwave3d.com/sdk/2015/html/filefmts/lwo2.html))
+
+| Chunk | Tag | Status |
+|--------------------------------------------|--------|--------|
+| Layer | `LAYR` | ✅ |
+| Point List | `PNTS` | ✅ |
+| Vertex Mapping | `VMAP` | ✅ |
+| Polygon List | `POLS` | ✅ |
+| Tag Strings | `TAGS` | ✅ |
+| Polygon Tag Mapping | `PTAG` | ✅ |
+| Discontinuous Vertex Mapping | `VMAD` | ✅ |
+| Vertex Map Parameter | `VMPA` | ✅ |
+| [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` | ❌ |
+
+
+### 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` | ❌ |
+
+
+### Clip Subchunks
+
+| Chunk | Tag | Status |
+|----------------------|--------|--------|
+| Still Image | `STIL` | ✅ |
+| Image Sequence | `ISEQ` | ✅ |
+| Plugin Animation | `ANIM` | ❌ |
+| Reference (Clone) | `XREF` | ✅ |
+ | Flag (Undocumented) | `FLAG` | 🚧 |
+| Color-cycling Still | `STCC` | ✅ |
+| Time | `TIME` | ✅ |
+| Color Space RGB | `CLRS` | ✅ |
+| Color Space Alpha | `CLRA` | ✅ |
+| Image Filtering | `FILT` | ✅ |
+| Image Dithering | `DITH` | ✅ |
+| Contrast | `CONT` | ✅ |
+| Brightness | `BRIT` | ✅ |
+| Saturation | `SATR` | ✅ |
+| Hue | `HUE` | ✅ |
+| Gamma Correction | `GAMM` | ✅ |
+| Negative | `NEGA` | ❌ |
+| Plugin Image Filters | `IFLT` | ❌ |
+| Plugin Pixel Filters | `PFLT` | ❌ |
+
+
+### Surface Subchunks
+
+### Basic Surface Parameters
+
+| Chunk | Tag | Status |
+|-----------------------------------|----------------------------------------------------------|--------|
+| Base Color | `COLR` | ✅ |
+| Base Shading Values | `DIFF`
`LUMI`
`SPEC`
`REFL`
`TRAN`
`TRNL` | ✅ |
+| Specular Glossiness | `GLOS` | ✅ |
+| Diffuse Sharpness | `SHRP` | ✅ |
+| Bump Intensity | `BUMP` | ✅ |
+| Polygon Sidedness | `SIDE` | ✅ |
+| Max Smoothing Angle | `SMAN` | ✅ |
+| Reflection Options | `RFOP` | ✅ |
+| Reflection Map Image | `RIMG` | ✅ |
+| Reflection Map Image Seam Angle | `RSAN` | ❌ |
+| Reflection Blurring | `RBLR` | ❌ |
+| Refractive Index | `RIND` | ❌ |
+| Transparency Options | `TROP` | ❌ |
+| Refraction Map Image | `TIMG` | ❌ |
+| Refraction Blurring | `TBLR` | ✅ |
+| Color Highlights | `CLRH` | ✅ |
+| Color Filter | `CLRF` | ✅ |
+| Additive Transparency | `ADRT` | ✅ |
+| Glow Effect | `GLOW` | ❌ |
+| Render Outlines | `LINE` | ❌ |
+| Alpha Mode | `ALPH` | ❌ |
+| Vertex Color Map | `VCOL` | ❌ |
+| [Surface Blocks](#surface-blocks) | `BLOK` | 🚧 |
+
+### Surface Blocks
+
+Ordinal Strings:
+* ✅ [Image Texture Map](#image-texture-map) `IMAP`
+* ❌ [Procedural Texture](#procedural-texture) `PROC`
+* ❌ [Gradient Texture](#gradient-texture) `GRAD`
+* ❌ Shader Plugin `SHDR`
+
+#### Shared
+
+| Chunk | Tag | Status |
+|-------------------------|--------|--------|
+| Texture Channel | `CHAN` | ✅ |
+| Enable State | `ENAB` | ✅ |
+| Opacity | `OPAC` | ✅ |
+| Displacement Axis | `AXIS` | ✅ |
+| Negative (Undocumented) | `NEGA` | 🚧 |
+
+#### Texture Mapping
+
+| Chunk | Tag | Status |
+|---------------------|----------------------------|--------|
+| Positioning | `CNTR`
`SIZE`
`ROTA` | ✅ |
+| Reference Object | `OREF` | ✅ |
+| Falloff | `FALL` | ✅ |
+| Coordinate System | `CSYS` | ✅ |
+
+#### Image Texture Map
+
+| Chunk | Tag | Status |
+|-------------------------------------|------------------|--------|
+| [Texture Mapping](#texture-mapping) | `TMAP` | ✅ |
+| Projection Mode | `PROJ` | ✅ |
+| Major Axis | `AXIS` | ✅ |
+| Image Map | `IMAG` | ✅ |
+| Image Wrap Options | `WRAP` | ✅ |
+| Image Wrap Amount | `WRPW`
`WRPH` | ✅ |
+| UV Vertex Map | `VMAP` | ✅ |
+| Antialiasing Strength | `AAST` | ✅ |
+| Pixel Blending | `PIXB` | ✅ |
+| Sticky Projection | `STCK` | ✅ |
+| Texture Ampliture | `TAMP` | ✅ |
+
+#### Procedural Texture
+
+| Chunk | Tag | Status |
+|--------------------------|--------|--------|
+| Axis | `AXIS` | ❌ |
+| Basic Value | `VALU` | ❌ |
+| Algorithm and Parameters | `FUNC` | ❌ |
+
+#### Gradient Texture
+
+| Chunk | Tag | Status |
+|----------------|-------------------|--------|
+| Parameter Name | `PNAM` | ❌ |
+| Item Name | `INAM` | ❌ |
+| Gradient Range | `GRST`
`GREN` | ❌ |
+| Repeat Mode | `GRPT` | ❌ |
+| Key Values | `FKEY` | ❌ |
+| Key Parameters | `IKEY` | ❌ |
+
+#### Shaders
+
+
+| Chunk | Tag | Status |
+|------------------|--------|--------|
+| Shader Algorithm | `FUNC` | ❌ |
diff --git a/rust/lightwave/src/binrw_helpers.rs b/rust/lightwave/src/binrw_helpers.rs
index 664c6c6..3504faf 100644
--- a/rust/lightwave/src/binrw_helpers.rs
+++ b/rust/lightwave/src/binrw_helpers.rs
@@ -1,8 +1,13 @@
use crate::lwo2::vx;
-use binrw::{BinRead, BinResult, Endian};
+use binrw::{binread, BinRead, BinResult, Endian};
use std::io::{Read, Seek};
use std::iter::from_fn;
+#[binread]
+#[br(assert(false, "Not implemented yet"))]
+#[derive(Debug)]
+pub struct BinReadTodo();
+
pub fn until_size_limit(
limit: u64,
) -> impl Fn(&mut R, Endian, Arg) -> BinResult
diff --git a/rust/lightwave/src/lwo2/sub_tags/mod.rs b/rust/lightwave/src/lwo2/sub_tags/mod.rs
index f779d4f..c06d870 100644
--- a/rust/lightwave/src/lwo2/sub_tags/mod.rs
+++ b/rust/lightwave/src/lwo2/sub_tags/mod.rs
@@ -1,11 +1,49 @@
-use binrw::binread;
use crate::lwo2::sub_tags::envelope_type::EnvelopeType;
+use crate::lwo2::vx;
+use binrw::binread;
pub mod envelope_type;
+pub mod surface_block_image_texture;
+pub mod surface_blocks;
+pub mod surface_parameters;
+pub mod texture_mapping;
#[binread]
#[derive(Debug)]
pub enum SubTag {
#[br(magic(b"TYPE"))]
- EnvelopeType(EnvelopeType)
+ EnvelopeType(EnvelopeType),
+}
+
+#[binread]
+#[br(import(_length: u32))]
+#[derive(Debug)]
+pub struct VectorEnvelope {
+ pub base_color: [f32; 3],
+ #[br(parse_with = vx)]
+ pub envelope: u32,
+}
+
+#[binread]
+#[br(import(_length: u32))]
+#[derive(Debug)]
+pub struct ValueEnvelope {
+ pub value: f32,
+ #[br(parse_with = vx)]
+ pub envelope: u32,
+}
+
+#[binread]
+#[br(import(_length: u32))]
+#[derive(Debug)]
+pub struct VxReference {
+ #[br(parse_with = vx)]
+ pub texture_image: u32,
+}
+
+#[binread]
+#[br(import(_length: u32))]
+#[derive(Debug)]
+pub struct EnableState {
+ pub enable: u16,
}
diff --git a/rust/lightwave/src/lwo2/sub_tags/surface_block_image_texture.rs b/rust/lightwave/src/lwo2/sub_tags/surface_block_image_texture.rs
new file mode 100644
index 0000000..76269e4
--- /dev/null
+++ b/rust/lightwave/src/lwo2/sub_tags/surface_block_image_texture.rs
@@ -0,0 +1,108 @@
+use crate::iff::SubChunk;
+use crate::lwo2::sub_tags::texture_mapping::TextureMapping;
+use crate::lwo2::sub_tags::{ValueEnvelope, VxReference};
+use crate::lwo2::vx;
+use binrw::{binread, NullString};
+
+#[binread]
+#[derive(Debug)]
+pub enum SurfaceBlockImageTextureSubChunk {
+ #[br(magic(b"TMAP"))]
+ TextureMapping(SubChunk),
+ #[br(magic(b"PROJ"))]
+ ProjectionMode(SubChunk),
+ #[br(magic(b"AXIS"))]
+ MajorAxis(SubChunk),
+ #[br(magic(b"IMAG"))]
+ ImageMap(SubChunk),
+ #[br(magic(b"WRAP"))]
+ ImageWrapOptions(SubChunk),
+ #[br(magic(b"WRPW"))]
+ ImageWrapAmountWidth(SubChunk),
+ #[br(magic(b"WRPH"))]
+ ImageWrapAmountHeight(SubChunk),
+ #[br(magic(b"VMAP"))]
+ UvVertexMap(SubChunk),
+ #[br(magic(b"AAST"))]
+ AntialiasingStrength(SubChunk),
+ #[br(magic(b"PIXB"))]
+ PixelBlending(SubChunk),
+ #[br(magic(b"TAMP"))]
+ TextureAmplitude(SubChunk),
+}
+
+/// The major axis used for planar, cylindrical and spherical projections. The value is 0, 1 or 2
+/// for the X, Y or Z axis.
+#[binread]
+#[br(import(_length: u32))]
+#[derive(Debug)]
+pub struct MajorAxis {
+ pub texture_axis: u16,
+}
+
+/// Pixel blending enlarges the sample filter when it would otherwise be smaller than a single
+/// image map pixel. If the low-order flag bit is set, then pixel blending is enabled.
+#[binread]
+#[br(import(_length: u32))]
+#[derive(Debug)]
+pub struct PixelBlending {
+ pub flags: u16,
+}
+
+/// The low bit of the flags word is an enable flag for texture antialiasing. The antialiasing
+/// strength is proportional to the width of the sample filter, so larger values sample a larger
+/// area of the image.
+#[binread]
+#[br(import(_length: u32))]
+#[derive(Debug)]
+pub struct AntialiasingStrength {
+ pub flags: u16,
+ pub strength: f32,
+}
+
+#[binread]
+#[br(import(_length: u32))]
+#[derive(Debug)]
+pub struct UvMap {
+ #[br(align_after = 2)]
+ pub txuv_map_name: NullString,
+}
+
+#[binread]
+#[br(import(_length: u32))]
+#[derive(Debug)]
+pub struct ImageWrapAmount {
+ pub cycles: f32,
+ #[br(parse_with = vx)]
+ pub envelope: u32,
+}
+
+#[binread]
+#[br(import(_length: u32))]
+#[derive(Debug)]
+pub struct ImageWrapOptions {
+ pub width_wrap: ImageWrapType,
+ pub height_wrap: ImageWrapType,
+}
+
+#[binread]
+#[br(repr = u16)]
+#[derive(Debug)]
+pub enum ImageWrapType {
+ Reset = 0,
+ Repeat = 1,
+ Mirror = 2,
+ Edge = 3,
+}
+
+#[binread]
+#[br(repr = u16, import(_length: u32))]
+#[derive(Debug)]
+pub enum ProjectionMode {
+ Planar = 0,
+ Cylindrical = 1,
+ Spherical = 2,
+ Cubic = 3,
+ FrontProjection = 4,
+ UV = 5,
+}
diff --git a/rust/lightwave/src/lwo2/sub_tags/surface_blocks.rs b/rust/lightwave/src/lwo2/sub_tags/surface_blocks.rs
new file mode 100644
index 0000000..046b3b2
--- /dev/null
+++ b/rust/lightwave/src/lwo2/sub_tags/surface_blocks.rs
@@ -0,0 +1,122 @@
+use crate::binrw_helpers::until_size_limit;
+use crate::iff::SubChunk;
+use crate::lwo2::sub_tags::surface_block_image_texture::SurfaceBlockImageTextureSubChunk;
+use crate::lwo2::sub_tags::EnableState;
+use crate::lwo2::vx;
+use binrw::{binread, PosValue};
+
+#[binread]
+#[br(import(length: u32))]
+#[derive(Debug)]
+pub struct SurfaceBlocks {
+ #[br(temp)]
+ start_pos: PosValue<()>,
+ pub ordinal: OrdinalString,
+ pub header: SubChunk,
+ #[br(temp)]
+ end_pos: PosValue<()>,
+ #[br(if(matches!(ordinal, OrdinalString::ImageMapTexture)))]
+ #[br(parse_with = until_size_limit(length as u64 - (end_pos.pos - start_pos.pos)))]
+ pub attributes: Vec,
+}
+
+#[binread]
+#[br(import(length: u32))]
+#[derive(Debug)]
+pub struct SurfaceBlockHeader {
+ #[br(pad_before = 2)]
+ #[br(parse_with = until_size_limit(length as u64 - 4))]
+ pub block_attributes: Vec,
+}
+
+#[binread]
+#[derive(Debug)]
+pub enum SurfaceBlockHeaderSubChunk {
+ #[br(magic(b"CHAN"))]
+ Channel(SubChunk),
+ #[br(magic(b"ENAB"))]
+ EnabledState(SubChunk),
+ #[br(magic(b"OPAC"))]
+ Opacity(SubChunk),
+ #[br(magic(b"AXIS"))]
+ DisplacementAxis(SubChunk),
+ #[br(magic(b"NEGA"))]
+ Negative(SubChunk),
+}
+
+#[binread]
+#[br(import(_length: u32))]
+#[derive(Debug)]
+pub enum OrdinalString {
+ #[br(magic(b"IMAP"))]
+ ImageMapTexture,
+ #[br(magic(b"PROC"))]
+ ProceduralTexture,
+ #[br(magic(b"GRAD"))]
+ GradientTexture,
+ #[br(magic(b"SHDR"))]
+ ShaderPlugin,
+}
+
+#[binread]
+#[br(import(_length: u32))]
+#[derive(Debug)]
+pub struct DisplacementAxis {
+ pub displacement_axis: u16,
+}
+
+#[binread]
+#[br(import(_length: u32))]
+#[derive(Debug)]
+pub struct Opacity {
+ pub kind: OpacityType,
+ pub opacity: f32,
+ #[br(parse_with = vx)]
+ pub envelope: u32,
+}
+
+#[binread]
+#[br(repr = u16)]
+#[derive(Debug)]
+pub enum OpacityType {
+ Normal = 0,
+ Subtractive = 1,
+ Difference = 2,
+ Multiply = 3,
+ Divide = 4,
+ Alpha = 5,
+ TextureDisplacement = 6,
+ Additive = 7,
+}
+
+#[binread]
+#[br(import(_length: u32))]
+#[derive(Debug)]
+pub struct Channel {
+ pub texture_channel: TextureChannel,
+}
+
+#[binread]
+#[derive(Debug)]
+pub enum TextureChannel {
+ #[br(magic(b"COLR"))]
+ Color,
+ #[br(magic(b"DIFF"))]
+ Diffuse,
+ #[br(magic(b"LUMI"))]
+ Luminosity,
+ #[br(magic(b"SPEC"))]
+ Specular,
+ #[br(magic(b"GLOS"))]
+ Glossy,
+ #[br(magic(b"REFL"))]
+ Reflectivity,
+ #[br(magic(b"TRAN"))]
+ Transparency,
+ #[br(magic(b"RIND"))]
+ RefractiveIndex,
+ #[br(magic(b"TRNL"))]
+ Translucency,
+ #[br(magic(b"BUMP"))]
+ Bump,
+}
diff --git a/rust/lightwave/src/lwo2/sub_tags/surface_parameters.rs b/rust/lightwave/src/lwo2/sub_tags/surface_parameters.rs
new file mode 100644
index 0000000..1512e92
--- /dev/null
+++ b/rust/lightwave/src/lwo2/sub_tags/surface_parameters.rs
@@ -0,0 +1,71 @@
+use crate::iff::SubChunk;
+use crate::lwo2::sub_tags::surface_blocks::SurfaceBlocks;
+use crate::lwo2::sub_tags::{ValueEnvelope, VectorEnvelope, VxReference};
+use binrw::binread;
+
+#[binread]
+#[derive(Debug)]
+pub enum SurfaceParameterSubChunk {
+ #[br(magic(b"COLR"))]
+ BaseColor(SubChunk),
+ #[br(magic(b"DIFF"))]
+ BaseShadingValueDiffuse(SubChunk),
+ #[br(magic(b"LUMI"))]
+ BaseShadingValueLuminosity(SubChunk),
+ #[br(magic(b"SPEC"))]
+ BaseShadingValueSpecular(SubChunk),
+ #[br(magic(b"REFL"))]
+ BaseShadingValueReflectivity(SubChunk),
+ #[br(magic(b"TRAN"))]
+ BaseShadingValueTransparency(SubChunk),
+ #[br(magic(b"TRNL"))]
+ BaseShadingValueTranslucency(SubChunk),
+ #[br(magic(b"GLOS"))]
+ SpecularGlossiness(SubChunk),
+ #[br(magic(b"SHRP"))]
+ DiffuseSharpness(SubChunk),
+ #[br(magic(b"BUMP"))]
+ BumpIntensity(SubChunk),
+ #[br(magic(b"SIDE"))]
+ PolygonSidedness(SubChunk),
+ #[br(magic(b"SMAN"))]
+ MaxSmoothingAngle(SubChunk),
+ #[br(magic(b"BLOK"))]
+ Blocks(SubChunk),
+ #[br(magic(b"RFOP"))]
+ ReflectionOptions(SubChunk),
+ #[br(magic(b"RIMG"))]
+ ReflectionMapImage(SubChunk),
+ #[br(magic(b"TBLR"))]
+ RefractionBlurring(SubChunk),
+ #[br(magic(b"CLRH"))]
+ ColorHighlights(SubChunk),
+ #[br(magic(b"CLRF"))]
+ ColorFilter(SubChunk),
+ #[br(magic(b"ADTR"))]
+ AdditiveTransparency(SubChunk),
+}
+
+#[binread]
+#[br(repr = u16, import(_length: u32))]
+#[derive(Debug)]
+pub enum ReflectionOptions {
+ BackdropOnly = 0,
+ RaytracingAndBackdrop = 1,
+ SphericalMap = 2,
+ RaytracingAndSphericalMap = 3,
+}
+
+#[binread]
+#[br(import(_length: u32))]
+#[derive(Debug)]
+pub struct PolygonSidedness {
+ pub sidedness: u16,
+}
+
+#[binread]
+#[br(import(_length: u32))]
+#[derive(Debug)]
+pub struct MaxSmoothingAngle {
+ pub max_smoothing_angle: f32,
+}
diff --git a/rust/lightwave/src/lwo2/sub_tags/texture_mapping.rs b/rust/lightwave/src/lwo2/sub_tags/texture_mapping.rs
new file mode 100644
index 0000000..7f0ddcf
--- /dev/null
+++ b/rust/lightwave/src/lwo2/sub_tags/texture_mapping.rs
@@ -0,0 +1,67 @@
+use crate::binrw_helpers::until_size_limit;
+use crate::iff::SubChunk;
+use crate::lwo2::sub_tags::VectorEnvelope;
+use crate::lwo2::vx;
+use binrw::{binread, NullString};
+
+#[binread]
+#[br(import(length: u32))]
+#[derive(Debug)]
+pub struct TextureMapping {
+ #[br(parse_with = until_size_limit(length as u64))]
+ pub attributes: Vec,
+}
+
+#[binread]
+#[derive(Debug)]
+pub enum TextureMappingSubChunk {
+ #[br(magic(b"CNTR"))]
+ Center(SubChunk),
+ #[br(magic(b"SIZE"))]
+ Size(SubChunk),
+ #[br(magic(b"ROTA"))]
+ Rotation(SubChunk),
+ #[br(magic(b"OREF"))]
+ ReferenceObject(SubChunk),
+ #[br(magic(b"FALL"))]
+ Falloff(SubChunk),
+ #[br(magic(b"CSYS"))]
+ CoordinateSystem(SubChunk),
+}
+
+#[binread]
+#[br(repr = u16, import(_length: u32))]
+#[derive(Debug)]
+pub enum CoordinateSystem {
+ ObjectCoordinates = 0,
+ WorldCoordinates = 1,
+}
+
+#[binread]
+#[br(import(_length: u32))]
+#[derive(Debug)]
+pub struct ReferenceObject {
+ #[br(align_after = 2)]
+ pub object_name: NullString,
+}
+
+#[binread]
+#[br(import(_length: u32))]
+#[derive(Debug)]
+pub struct Falloff {
+ pub kind: FalloffType,
+ pub vector: [f32; 3],
+ #[br(parse_with = vx)]
+ pub envelope: u32,
+}
+
+#[binread]
+#[br(repr = u16)]
+#[derive(Debug)]
+pub enum FalloffType {
+ Cubic = 0,
+ Spherical = 1,
+ LinearX = 2,
+ LinearY = 3,
+ LinearZ = 4,
+}
diff --git a/rust/lightwave/src/lwo2/tags/image_clip.rs b/rust/lightwave/src/lwo2/tags/image_clip.rs
index 469c1f2..4559ecd 100644
--- a/rust/lightwave/src/lwo2/tags/image_clip.rs
+++ b/rust/lightwave/src/lwo2/tags/image_clip.rs
@@ -1,6 +1,6 @@
use crate::binrw_helpers::until_size_limit;
use crate::iff::SubChunk;
-use crate::lwo2::tags::surface_definition::ValueEnvelope;
+use crate::lwo2::sub_tags::ValueEnvelope;
use binrw::{binread, NullString};
/// Describes an image or a sequence of images. Surface definitions specify images by referring to
diff --git a/rust/lightwave/src/lwo2/tags/mod.rs b/rust/lightwave/src/lwo2/tags/mod.rs
index 26b322a..c7e102d 100644
--- a/rust/lightwave/src/lwo2/tags/mod.rs
+++ b/rust/lightwave/src/lwo2/tags/mod.rs
@@ -50,3 +50,4 @@ pub enum Tag {
#[br(magic(b"CLIP"))]
ImageClip(Chunk),
}
+
diff --git a/rust/lightwave/src/lwo2/tags/surface_definition.rs b/rust/lightwave/src/lwo2/tags/surface_definition.rs
index 112f6d0..888dd0b 100644
--- a/rust/lightwave/src/lwo2/tags/surface_definition.rs
+++ b/rust/lightwave/src/lwo2/tags/surface_definition.rs
@@ -1,6 +1,5 @@
use crate::binrw_helpers::until_size_limit;
-use crate::iff::SubChunk;
-use crate::lwo2::vx;
+use crate::lwo2::sub_tags::surface_parameters::SurfaceParameterSubChunk;
use binrw::{binread, NullString, PosValue};
#[binread]
@@ -16,366 +15,5 @@ pub struct SurfaceDefinition {
#[br(temp)]
pub end_pos: PosValue<()>,
#[br(parse_with = until_size_limit(length as u64 - (end_pos.pos - start_pos.pos)))]
- pub attributes: Vec,
-}
-
-#[binread]
-#[derive(Debug)]
-pub enum SurfaceSubTag {
- #[br(magic(b"COLR"))]
- BaseColor(SubChunk),
- #[br(magic(b"DIFF"))]
- BaseShadingValueDiffuse(SubChunk),
- #[br(magic(b"LUMI"))]
- BaseShadingValueLuminosity(SubChunk),
- #[br(magic(b"SPEC"))]
- BaseShadingValueSpecular(SubChunk),
- #[br(magic(b"REFL"))]
- BaseShadingValueReflectivity(SubChunk),
- #[br(magic(b"TRAN"))]
- BaseShadingValueTransparency(SubChunk),
- #[br(magic(b"TRNL"))]
- BaseShadingValueTranslucency(SubChunk),
- #[br(magic(b"GLOS"))]
- SpecularGlossiness(SubChunk),
- #[br(magic(b"SHRP"))]
- DiffuseSharpness(SubChunk),
- #[br(magic(b"BUMP"))]
- BumpIntensity(SubChunk),
- #[br(magic(b"SIDE"))]
- PolygonSidedness(SubChunk),
- #[br(magic(b"SMAN"))]
- MaxSmoothingAngle(SubChunk),
- #[br(magic(b"BLOK"))]
- Blocks(SubChunk),
- #[br(magic(b"RFOP"))]
- ReflectionOptions(SubChunk),
- #[br(magic(b"RIMG"))]
- ReflectionMapImage(SubChunk),
- #[br(magic(b"TBLR"))]
- RefractionBlurring(SubChunk),
- #[br(magic(b"CLRH"))]
- ColorHighlights(SubChunk),
- #[br(magic(b"CLRF"))]
- ColorFilter(SubChunk),
- #[br(magic(b"ADTR"))]
- AdditiveTransparency(SubChunk),
-}
-
-#[binread]
-#[br(repr = u16, import(_length: u32))]
-#[derive(Debug)]
-pub enum ReflectionOptions {
- BackdropOnly = 0,
- RaytracingAndBackdrop = 1,
- SphericalMap = 2,
- RaytracingAndSphericalMap = 3,
-}
-
-#[binread]
-#[br(import(_length: u32))]
-#[derive(Debug)]
-pub struct VectorEnvelope {
- pub base_color: [f32; 3],
- #[br(parse_with = vx)]
- pub envelope: u32,
-}
-
-#[binread]
-#[br(import(_length: u32))]
-#[derive(Debug)]
-pub struct ValueEnvelope {
- pub value: f32,
- #[br(parse_with = vx)]
- pub envelope: u32,
-}
-
-#[binread]
-#[br(import(_length: u32))]
-#[derive(Debug)]
-pub struct PolygonSidedness {
- pub sidedness: u16,
-}
-
-#[binread]
-#[br(import(_length: u32))]
-#[derive(Debug)]
-pub struct MaxSmoothingAngle {
- pub max_smoothing_angle: f32,
-}
-
-#[binread]
-#[br(import(length: u32))]
-#[derive(Debug)]
-pub struct SurfaceBlocks {
- #[br(temp)]
- start_pos: PosValue<()>,
- pub header: SurfaceBlockHeader,
- #[br(temp)]
- end_pos: PosValue<()>,
- #[br(parse_with = until_size_limit(length as u64 - (end_pos.pos - start_pos.pos)))]
- pub attributes: Vec,
-}
-
-#[binread]
-#[derive(Debug)]
-pub enum SurfaceBlockHeader {
- #[br(magic(b"IMAP"))]
- ImageMapTexture(SubChunk),
- #[br(magic(b"PROC"))]
- ProceduralTexture(SubChunk),
- #[br(magic(b"GRAD"))]
- GradientTexture(SubChunk),
- #[br(magic(b"SHDR"))]
- ShaderPlugin(SubChunk),
-}
-
-#[binread]
-#[br(import(length: u32))]
-#[derive(Debug)]
-pub struct SurfaceBlockHeaders {
- #[br(pad_before = 2, parse_with = until_size_limit(length as u64))]
- pub block_attributes: Vec,
-}
-
-#[binread]
-#[derive(Debug)]
-pub enum SurfaceBlockSubChunk {
- #[br(magic(b"CHAN"))]
- Channel(SubChunk),
- #[br(magic(b"ENAB"))]
- EnabledState(SubChunk),
- #[br(magic(b"OPAC"))]
- Opacity(SubChunk),
- #[br(magic(b"AXIS"))]
- DisplacementAxis(SubChunk),
- #[br(magic(b"TMAP"))]
- TextureMapping(SubChunk),
- #[br(magic(b"NEGA"))]
- Negative(SubChunk),
- #[br(magic(b"PROJ"))]
- ProjectionMode(SubChunk),
- #[br(magic(b"IMAG"))]
- ImageMap(SubChunk),
- #[br(magic(b"WRAP"))]
- ImageWrapOptions(SubChunk),
- #[br(magic(b"WRPW"))]
- ImageWrapAmountWidth(SubChunk),
- #[br(magic(b"WRPH"))]
- ImageWrapAmountHeight(SubChunk),
- #[br(magic(b"VMAP"))]
- UvVertexMap(SubChunk),
- #[br(magic(b"AAST"))]
- AntialiasingStrength(SubChunk),
- #[br(magic(b"PIXB"))]
- PixelBlending(SubChunk),
- #[br(magic(b"TAMP"))]
- TextureAmplitude(SubChunk),
-}
-
-/// Pixel blending enlarges the sample filter when it would otherwise be smaller than a single
-/// image map pixel. If the low-order flag bit is set, then pixel blending is enabled.
-#[binread]
-#[br(import(_length: u32))]
-#[derive(Debug)]
-pub struct PixelBlending {
- pub flags: u16,
-}
-
-/// The low bit of the flags word is an enable flag for texture antialiasing. The antialiasing
-/// strength is proportional to the width of the sample filter, so larger values sample a larger
-/// area of the image.
-#[binread]
-#[br(import(_length: u32))]
-#[derive(Debug)]
-pub struct AntialiasingStrength {
- pub flags: u16,
- pub strength: f32,
-}
-
-#[binread]
-#[br(import(_length: u32))]
-#[derive(Debug)]
-pub struct UvMap {
- #[br(align_after = 2)]
- pub txuv_map_name: NullString,
-}
-
-#[binread]
-#[br(import(_length: u32))]
-#[derive(Debug)]
-pub struct ImageWrapAmount {
- pub cycles: f32,
- #[br(parse_with = vx)]
- pub envelope: u32,
-}
-
-#[binread]
-#[br(import(_length: u32))]
-#[derive(Debug)]
-pub struct ImageWrapOptions {
- pub width_wrap: ImageWrapType,
- pub height_wrap: ImageWrapType,
-}
-
-#[binread]
-#[br(repr = u16)]
-#[derive(Debug)]
-pub enum ImageWrapType {
- Reset = 0,
- Repeat = 1,
- Mirror = 2,
- Edge = 3,
-}
-
-#[binread]
-#[br(repr = u16, import(_length: u32))]
-#[derive(Debug)]
-pub enum ProjectionMode {
- Planar = 0,
- Cylindrical = 1,
- Spherical = 2,
- Cubic = 3,
- FrontProjection = 4,
- UV = 5,
-}
-
-#[binread]
-#[br(import(_length: u32))]
-#[derive(Debug)]
-pub struct VxReference {
- #[br(parse_with = vx)]
- pub texture_image: u32,
-}
-
-#[binread]
-#[br(import(length: u32))]
-#[derive(Debug)]
-pub struct TextureMapping {
- #[br(parse_with = until_size_limit(length as u64))]
- pub attributes: Vec,
-}
-
-#[binread]
-#[derive(Debug)]
-pub enum TextureMappingSubChunk {
- #[br(magic(b"CNTR"))]
- Center(SubChunk),
- #[br(magic(b"SIZE"))]
- Size(SubChunk),
- #[br(magic(b"ROTA"))]
- Rotation(SubChunk),
- #[br(magic(b"OREF"))]
- ReferenceObject(SubChunk),
- #[br(magic(b"FALL"))]
- Falloff(SubChunk),
- #[br(magic(b"CSYS"))]
- CoordinateSystem(SubChunk),
-}
-
-#[binread]
-#[br(repr = u16, import(_length: u32))]
-#[derive(Debug)]
-pub enum CoordinateSystem {
- ObjectCoordinates = 0,
- WorldCoordinates = 1,
-}
-
-#[binread]
-#[br(import(_length: u32))]
-#[derive(Debug)]
-pub struct ReferenceObject {
- #[br(align_after = 2)]
- pub object_name: NullString,
-}
-
-#[binread]
-#[br(import(_length: u32))]
-#[derive(Debug)]
-pub struct Falloff {
- pub kind: FalloffType,
- pub vector: [f32; 3],
- #[br(parse_with = vx)]
- pub envelope: u32,
-}
-
-#[binread]
-#[br(repr = u16)]
-#[derive(Debug)]
-pub enum FalloffType {
- Cubic = 0,
- Spherical = 1,
- LinearX = 2,
- LinearY = 3,
- LinearZ = 4,
-}
-
-#[binread]
-#[br(import(_length: u32))]
-#[derive(Debug)]
-pub struct DisplacementAxis {
- pub displacement_axis: u16,
-}
-
-#[binread]
-#[br(import(_length: u32))]
-#[derive(Debug)]
-pub struct Opacity {
- pub kind: OpacityType,
- pub opacity: f32,
- #[br(parse_with = vx)]
- pub envelope: u32,
-}
-
-#[binread]
-#[br(repr = u16)]
-#[derive(Debug)]
-pub enum OpacityType {
- Normal = 0,
- Subtractive = 1,
- Difference = 2,
- Multiply = 3,
- Divide = 4,
- Alpha = 5,
- TextureDisplacement = 6,
- Additive = 7,
-}
-
-#[binread]
-#[br(import(_length: u32))]
-#[derive(Debug)]
-pub struct EnableState {
- pub enable: u16,
-}
-
-#[binread]
-#[br(import(_length: u32))]
-#[derive(Debug)]
-pub struct Channel {
- pub texture_channel: TextureChannel,
-}
-
-#[binread]
-#[derive(Debug)]
-pub enum TextureChannel {
- #[br(magic(b"COLR"))]
- Color,
- #[br(magic(b"DIFF"))]
- Diffuse,
- #[br(magic(b"LUMI"))]
- Luminosity,
- #[br(magic(b"SPEC"))]
- Specular,
- #[br(magic(b"GLOS"))]
- Glossy,
- #[br(magic(b"REFL"))]
- Reflectivity,
- #[br(magic(b"TRAN"))]
- Transparency,
- #[br(magic(b"RIND"))]
- RefractiveIndex,
- #[br(magic(b"TRNL"))]
- Translucency,
- #[br(magic(b"BUMP"))]
- Bump,
+ pub attributes: Vec,
}