mirror of
https://github.com/Theaninova/mhlib.git
synced 2025-12-12 12:36:17 +00:00
add lightwave parser
This commit is contained in:
7
rust/Cargo.lock
generated
7
rust/Cargo.lock
generated
@@ -242,6 +242,12 @@ dependencies = [
|
|||||||
"weezl",
|
"weezl",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "glob"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "half"
|
name = "half"
|
||||||
version = "2.2.1"
|
version = "2.2.1"
|
||||||
@@ -357,6 +363,7 @@ dependencies = [
|
|||||||
name = "mhex"
|
name = "mhex"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"glob",
|
||||||
"lightwave",
|
"lightwave",
|
||||||
"starforcelib",
|
"starforcelib",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
# LightWave 3D Rust Parser
|
# LightWave 3D Rust Parser
|
||||||
|
|
||||||
* [LWO2 Spec](http://static.lightwave3d.com/sdk/2015/html/filefmts/lwo2.html)
|
* [LWO2 Spec](http://static.lightwave3d.com/sdk/2015/html/filefmts/lwo2.html)
|
||||||
|
* Progress: about 90% (?) complete, so most things should load.
|
||||||
@@ -16,7 +16,7 @@ where
|
|||||||
R: Read + Seek,
|
R: Read + Seek,
|
||||||
{
|
{
|
||||||
let kind: u16 = reader.read_type(endian)?;
|
let kind: u16 = reader.read_type(endian)?;
|
||||||
Ok(if (kind & 0xff) != 0xff {
|
Ok(if kind < 0xff00 {
|
||||||
kind as u32
|
kind as u32
|
||||||
} else {
|
} else {
|
||||||
(((kind as u32) & 0xff) << 16) | (reader.read_type::<u16>(endian)? as u32)
|
(((kind as u32) & 0xff) << 16) | (reader.read_type::<u16>(endian)? as u32)
|
||||||
|
|||||||
146
rust/lightwave/src/lwo2/tags/image_clip.rs
Normal file
146
rust/lightwave/src/lwo2/tags/image_clip.rs
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
use crate::binrw_helpers::until_size_limit;
|
||||||
|
use crate::iff::SubChunk;
|
||||||
|
use crate::lwo2::tags::surface_definition::ValueEnvelope;
|
||||||
|
use binrw::{binread, NullString};
|
||||||
|
|
||||||
|
/// Describes an image or a sequence of images. Surface definitions specify images by referring to
|
||||||
|
/// CLIP chunks. The term "clip" is used to describe these because they can be numbered sequences
|
||||||
|
/// or animations as well as stills. The index identifies this clip uniquely and may be any non-zero
|
||||||
|
/// value less than 0x1000000. The filename and any image processing modifiers follow as a variable
|
||||||
|
/// list of subchunks, which are documented below in the Clip Subchunks section.
|
||||||
|
#[binread]
|
||||||
|
#[br(import(length: u32))]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ImageClip {
|
||||||
|
pub index: u32,
|
||||||
|
#[br(parse_with = until_size_limit(length as u64 - 4))]
|
||||||
|
pub attributes: Vec<ImageClipSubChunk>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[binread]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum ImageClipSubChunk {
|
||||||
|
#[br(magic(b"STIL"))]
|
||||||
|
StillImage(SubChunk<StillImage>),
|
||||||
|
#[br(magic(b"ISEQ"))]
|
||||||
|
ImageSequence(SubChunk<ImageSequence>),
|
||||||
|
#[br(magic(b"XREF"))]
|
||||||
|
Reference(SubChunk<Reference>),
|
||||||
|
#[br(magic(b"FLAG"))]
|
||||||
|
Flag(SubChunk<Flags>),
|
||||||
|
#[br(magic(b"STCC"))]
|
||||||
|
ColorCyclingStill(SubChunk<ColorCyclingStill>),
|
||||||
|
#[br(magic(b"TIME"))]
|
||||||
|
Time(SubChunk<Time>),
|
||||||
|
#[br(magic(b"CLRS"))]
|
||||||
|
ColorSpaceRgb(SubChunk<ColorSpace>),
|
||||||
|
#[br(magic(b"CLRA"))]
|
||||||
|
ColorSpaceAlpha(SubChunk<ColorSpace>),
|
||||||
|
#[br(magic(b"FILT"))]
|
||||||
|
ImageFiltering(SubChunk<Flags>),
|
||||||
|
#[br(magic(b"DITH"))]
|
||||||
|
ImageDithering(SubChunk<Flags>),
|
||||||
|
#[br(magic(b"CONT"))]
|
||||||
|
Contrast(SubChunk<ValueEnvelope>),
|
||||||
|
#[br(magic(b"BRIT"))]
|
||||||
|
Brightness(SubChunk<ValueEnvelope>),
|
||||||
|
#[br(magic(b"SATR"))]
|
||||||
|
Saturation(SubChunk<ValueEnvelope>),
|
||||||
|
#[br(magic(b"HUE"))] // TODO: Typo? Docs say it's just "HUE"
|
||||||
|
Hue(SubChunk<ValueEnvelope>),
|
||||||
|
#[br(magic(b"GAMM"))]
|
||||||
|
GammaCorrection(SubChunk<ValueEnvelope>),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Contains the color space of the texture. If the flag is 0, then the color space is contained
|
||||||
|
/// in the following 2 bytes. That color space is defined by the LWCOLORSPACE enum. If the flag
|
||||||
|
/// is set to 1, then the file name of the color space is save as a local string.
|
||||||
|
#[binread]
|
||||||
|
#[br(import(_length: u32))]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ColorSpace {
|
||||||
|
pub flags: u16,
|
||||||
|
pub color_space: u16,
|
||||||
|
#[br(align_after = 2)]
|
||||||
|
pub file_name: NullString,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A still image with color-cycling is a source defined by a neutral-format name and cycling
|
||||||
|
/// parameters. lo and hi are indexes into the image's color table. Within this range, the color
|
||||||
|
/// table entries are shifted over time to cycle the colors in the image. If lo is less than hi,
|
||||||
|
/// the colors cycle forward, and if hi is less than lo, they go backwards.
|
||||||
|
///
|
||||||
|
/// Except for the TIME subchunk, the subchunks after the source subchunk modify the source image
|
||||||
|
/// and are applied as filters layered on top of the source image.
|
||||||
|
#[binread]
|
||||||
|
#[br(import(_length: u32))]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ColorCyclingStill {
|
||||||
|
pub lo: i16,
|
||||||
|
pub hi: i16,
|
||||||
|
#[br(align_after = 2)]
|
||||||
|
pub name: NullString,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Defines source times for an animated clip.
|
||||||
|
#[binread]
|
||||||
|
#[br(import(_length: u32))]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Time {
|
||||||
|
pub start_time: f32,
|
||||||
|
pub duration: f32,
|
||||||
|
pub frame_rate: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// TODO: What's this?
|
||||||
|
#[binread]
|
||||||
|
#[br(import(_length: u32))]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Flags {
|
||||||
|
pub flag: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The source is a single still image referenced by a filename in neutral path format.
|
||||||
|
#[binread]
|
||||||
|
#[br(import(_length: u32))]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct StillImage {
|
||||||
|
#[br(align_after = 2)]
|
||||||
|
pub name: NullString,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The source is a numbered sequence of still image files. Each filename contains a fixed number
|
||||||
|
/// of decimal digits that specify a frame number, along with a prefix (the part before the frame
|
||||||
|
/// number, which includes the path) and a suffix (the part after the number, typically a PC-style
|
||||||
|
/// extension that identifies the file format). The prefix and suffix are the same for all files
|
||||||
|
/// in the sequence.
|
||||||
|
///
|
||||||
|
/// The flags include bits for looping and interlace. The offset is added to the current frame
|
||||||
|
/// number to obtain the digits of the filename for the current frame. The start and end values
|
||||||
|
/// define the range of frames in the sequence.
|
||||||
|
#[binread]
|
||||||
|
#[br(import(_length: u32))]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ImageSequence {
|
||||||
|
pub num_digits: u8,
|
||||||
|
pub flags: u8,
|
||||||
|
pub offset: i16,
|
||||||
|
pub reserved: u16,
|
||||||
|
pub start: i16,
|
||||||
|
pub end: i16,
|
||||||
|
#[br(align_after = 2)]
|
||||||
|
pub prefix: NullString,
|
||||||
|
#[br(align_after = 2)]
|
||||||
|
pub suffix: NullString,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The source is a copy, or instance, of another clip, given by the index. The string is a unique
|
||||||
|
/// name for this instance of the clip.
|
||||||
|
#[binread]
|
||||||
|
#[br(import(_length: u32))]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Reference {
|
||||||
|
pub index: u32,
|
||||||
|
#[br(align_after = 2)]
|
||||||
|
pub string: NullString,
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
use crate::iff::Chunk;
|
use crate::iff::Chunk;
|
||||||
use crate::lwo2::tags::bounding_box::BoundingBox;
|
use crate::lwo2::tags::bounding_box::BoundingBox;
|
||||||
use crate::lwo2::tags::discontinuous_vertex_mapping::DiscontinuousVertexMappings;
|
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::layer::Layer;
|
||||||
use crate::lwo2::tags::point_list::PointList;
|
use crate::lwo2::tags::point_list::PointList;
|
||||||
use crate::lwo2::tags::polygon_list::PolygonLists;
|
use crate::lwo2::tags::polygon_list::PolygonLists;
|
||||||
@@ -13,6 +14,7 @@ use binrw::binread;
|
|||||||
|
|
||||||
pub mod bounding_box;
|
pub mod bounding_box;
|
||||||
pub mod discontinuous_vertex_mapping;
|
pub mod discontinuous_vertex_mapping;
|
||||||
|
pub mod image_clip;
|
||||||
pub mod layer;
|
pub mod layer;
|
||||||
pub mod point_list;
|
pub mod point_list;
|
||||||
pub mod polygon_list;
|
pub mod polygon_list;
|
||||||
@@ -45,4 +47,6 @@ pub enum Tag {
|
|||||||
PolygonList(Chunk<PolygonLists>),
|
PolygonList(Chunk<PolygonLists>),
|
||||||
#[br(magic(b"SURF"))]
|
#[br(magic(b"SURF"))]
|
||||||
SurfaceDefinition(Chunk<SurfaceDefinition>),
|
SurfaceDefinition(Chunk<SurfaceDefinition>),
|
||||||
|
#[br(magic(b"CLIP"))]
|
||||||
|
ImageClip(Chunk<ImageClip>),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ use binrw::binread;
|
|||||||
///Lists (x, y, z) coordinate triples for a set of points. The number of points in the chunk is
|
///Lists (x, y, z) coordinate triples for a set of points. The number of points in the chunk is
|
||||||
/// just the chunk size divided by 12. The PNTS chunk must precede the POLS, VMAP and VMAD chunks
|
/// just the chunk size divided by 12. The PNTS chunk must precede the POLS, VMAP and VMAD chunks
|
||||||
/// that refer to it. These chunks list points using a 0-based index into PNTS.
|
/// that refer to it. These chunks list points using a 0-based index into PNTS.
|
||||||
//
|
///
|
||||||
// The LightWave® coordinate system is left-handed, with +X to the right or east, +Y upward,
|
/// The LightWave® coordinate system is left-handed, with +X to the right or east, +Y upward,
|
||||||
// and +Z forward or north. Object files don't contain explicit units, but by convention the
|
/// and +Z forward or north. Object files don't contain explicit units, but by convention the
|
||||||
// unit is meters. Coordinates in PNTS are relative to the pivot point of the layer.
|
/// unit is meters. Coordinates in PNTS are relative to the pivot point of the layer.
|
||||||
#[binread]
|
#[binread]
|
||||||
#[br(import(length: u32))]
|
#[br(import(length: u32))]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|||||||
@@ -23,35 +23,59 @@ pub struct SurfaceDefinition {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum SurfaceSubTag {
|
pub enum SurfaceSubTag {
|
||||||
#[br(magic(b"COLR"))]
|
#[br(magic(b"COLR"))]
|
||||||
BaseColor(SubChunk<BaseColor>),
|
BaseColor(SubChunk<VectorEnvelope>),
|
||||||
#[br(magic(b"DIFF"))]
|
#[br(magic(b"DIFF"))]
|
||||||
BaseShadingValueDiffuse(SubChunk<BaseShadingValues>),
|
BaseShadingValueDiffuse(SubChunk<ValueEnvelope>),
|
||||||
#[br(magic(b"LUMI"))]
|
#[br(magic(b"LUMI"))]
|
||||||
BaseShadingValueLuminosity(SubChunk<BaseShadingValues>),
|
BaseShadingValueLuminosity(SubChunk<ValueEnvelope>),
|
||||||
#[br(magic(b"SPEC"))]
|
#[br(magic(b"SPEC"))]
|
||||||
BaseShadingValueSpecular(SubChunk<BaseShadingValues>),
|
BaseShadingValueSpecular(SubChunk<ValueEnvelope>),
|
||||||
#[br(magic(b"REFL"))]
|
#[br(magic(b"REFL"))]
|
||||||
BaseShadingValueReflectivity(SubChunk<BaseShadingValues>),
|
BaseShadingValueReflectivity(SubChunk<ValueEnvelope>),
|
||||||
#[br(magic(b"TRAN"))]
|
#[br(magic(b"TRAN"))]
|
||||||
BaseShadingValueTransmission(SubChunk<BaseShadingValues>),
|
BaseShadingValueTransparency(SubChunk<ValueEnvelope>),
|
||||||
#[br(magic(b"TRNL"))] // TODO
|
#[br(magic(b"TRNL"))]
|
||||||
BaseShadingValueTrnl(SubChunk<BaseShadingValues>),
|
BaseShadingValueTranslucency(SubChunk<ValueEnvelope>),
|
||||||
#[br(magic(b"GLOS"))]
|
#[br(magic(b"GLOS"))]
|
||||||
SpecularGlossiness(SubChunk<BaseShadingValues>),
|
SpecularGlossiness(SubChunk<ValueEnvelope>),
|
||||||
#[br(magic(b"SHRP"))]
|
#[br(magic(b"SHRP"))]
|
||||||
DiffuseSharpness(SubChunk<BaseShadingValues>),
|
DiffuseSharpness(SubChunk<ValueEnvelope>),
|
||||||
#[br(magic(b"BUMP"))]
|
#[br(magic(b"BUMP"))]
|
||||||
BumpIntensity(SubChunk<BaseShadingValues>),
|
BumpIntensity(SubChunk<ValueEnvelope>),
|
||||||
#[br(magic(b"SIDE"))]
|
#[br(magic(b"SIDE"))]
|
||||||
PolygonSidedness(SubChunk<PolygonSidedness>),
|
PolygonSidedness(SubChunk<PolygonSidedness>),
|
||||||
#[br(magic(b"SMAN"))]
|
#[br(magic(b"SMAN"))]
|
||||||
MaxSmoothingAngle(SubChunk<MaxSmoothingAngle>),
|
MaxSmoothingAngle(SubChunk<MaxSmoothingAngle>),
|
||||||
|
#[br(magic(b"BLOK"))]
|
||||||
|
Blocks(SubChunk<SurfaceBlocks>),
|
||||||
|
#[br(magic(b"RFOP"))]
|
||||||
|
ReflectionOptions(SubChunk<ReflectionOptions>),
|
||||||
|
#[br(magic(b"RIMG"))]
|
||||||
|
ReflectionMapImage(SubChunk<VxReference>),
|
||||||
|
#[br(magic(b"TBLR"))]
|
||||||
|
RefractionBlurring(SubChunk<ValueEnvelope>),
|
||||||
|
#[br(magic(b"CLRH"))]
|
||||||
|
ColorHighlights(SubChunk<ValueEnvelope>),
|
||||||
|
#[br(magic(b"CLRF"))]
|
||||||
|
ColorFilter(SubChunk<ValueEnvelope>),
|
||||||
|
#[br(magic(b"ADTR"))]
|
||||||
|
AdditiveTransparency(SubChunk<ValueEnvelope>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[binread]
|
||||||
|
#[br(repr = u16, import(_length: u32))]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum ReflectionOptions {
|
||||||
|
BackdropOnly = 0,
|
||||||
|
RaytracingAndBackdrop = 1,
|
||||||
|
SphericalMap = 2,
|
||||||
|
RaytracingAndSphericalMap = 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[binread]
|
#[binread]
|
||||||
#[br(import(_length: u32))]
|
#[br(import(_length: u32))]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct BaseColor {
|
pub struct VectorEnvelope {
|
||||||
pub base_color: [f32; 3],
|
pub base_color: [f32; 3],
|
||||||
#[br(parse_with = vx)]
|
#[br(parse_with = vx)]
|
||||||
pub envelope: u32,
|
pub envelope: u32,
|
||||||
@@ -60,7 +84,7 @@ pub struct BaseColor {
|
|||||||
#[binread]
|
#[binread]
|
||||||
#[br(import(_length: u32))]
|
#[br(import(_length: u32))]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct BaseShadingValues {
|
pub struct ValueEnvelope {
|
||||||
pub value: f32,
|
pub value: f32,
|
||||||
#[br(parse_with = vx)]
|
#[br(parse_with = vx)]
|
||||||
pub envelope: u32,
|
pub envelope: u32,
|
||||||
@@ -79,3 +103,279 @@ pub struct PolygonSidedness {
|
|||||||
pub struct MaxSmoothingAngle {
|
pub struct MaxSmoothingAngle {
|
||||||
pub max_smoothing_angle: f32,
|
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<SurfaceBlockSubChunk>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[binread]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum SurfaceBlockHeader {
|
||||||
|
#[br(magic(b"IMAP"))]
|
||||||
|
ImageMapTexture(SubChunk<SurfaceBlockHeaders>),
|
||||||
|
#[br(magic(b"PROC"))]
|
||||||
|
ProceduralTexture(SubChunk<SurfaceBlockHeaders>),
|
||||||
|
#[br(magic(b"GRAD"))]
|
||||||
|
GradientTexture(SubChunk<SurfaceBlockHeaders>),
|
||||||
|
#[br(magic(b"SHDR"))]
|
||||||
|
ShaderPlugin(SubChunk<SurfaceBlockHeaders>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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<SurfaceBlockSubChunk>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[binread]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum SurfaceBlockSubChunk {
|
||||||
|
#[br(magic(b"CHAN"))]
|
||||||
|
Channel(SubChunk<Channel>),
|
||||||
|
#[br(magic(b"ENAB"))]
|
||||||
|
EnabledState(SubChunk<EnableState>),
|
||||||
|
#[br(magic(b"OPAC"))]
|
||||||
|
Opacity(SubChunk<Opacity>),
|
||||||
|
#[br(magic(b"AXIS"))]
|
||||||
|
DisplacementAxis(SubChunk<DisplacementAxis>),
|
||||||
|
#[br(magic(b"TMAP"))]
|
||||||
|
TextureMapping(SubChunk<TextureMapping>),
|
||||||
|
#[br(magic(b"NEGA"))]
|
||||||
|
Negative(SubChunk<EnableState>),
|
||||||
|
#[br(magic(b"PROJ"))]
|
||||||
|
ProjectionMode(SubChunk<ProjectionMode>),
|
||||||
|
#[br(magic(b"IMAG"))]
|
||||||
|
ImageMap(SubChunk<VxReference>),
|
||||||
|
#[br(magic(b"WRAP"))]
|
||||||
|
ImageWrapOptions(SubChunk<ImageWrapOptions>),
|
||||||
|
#[br(magic(b"WRPW"))]
|
||||||
|
ImageWrapAmountWidth(SubChunk<ImageWrapAmount>),
|
||||||
|
#[br(magic(b"WRPH"))]
|
||||||
|
ImageWrapAmountHeight(SubChunk<ImageWrapAmount>),
|
||||||
|
#[br(magic(b"VMAP"))]
|
||||||
|
UvVertexMap(SubChunk<UvMap>),
|
||||||
|
#[br(magic(b"AAST"))]
|
||||||
|
AntialiasingStrength(SubChunk<AntialiasingStrength>),
|
||||||
|
#[br(magic(b"PIXB"))]
|
||||||
|
PixelBlending(SubChunk<PixelBlending>),
|
||||||
|
#[br(magic(b"TAMP"))]
|
||||||
|
TextureAmplitude(SubChunk<ValueEnvelope>),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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<TextureMappingSubChunk>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[binread]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum TextureMappingSubChunk {
|
||||||
|
#[br(magic(b"CNTR"))]
|
||||||
|
Center(SubChunk<VectorEnvelope>),
|
||||||
|
#[br(magic(b"SIZE"))]
|
||||||
|
Size(SubChunk<VectorEnvelope>),
|
||||||
|
#[br(magic(b"ROTA"))]
|
||||||
|
Rotation(SubChunk<VectorEnvelope>),
|
||||||
|
#[br(magic(b"OREF"))]
|
||||||
|
ReferenceObject(SubChunk<ReferenceObject>),
|
||||||
|
#[br(magic(b"FALL"))]
|
||||||
|
Falloff(SubChunk<Falloff>),
|
||||||
|
#[br(magic(b"CSYS"))]
|
||||||
|
CoordinateSystem(SubChunk<CoordinateSystem>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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,
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,3 +8,4 @@ edition = "2021"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
starforcelib = {path = "../starforcelib"}
|
starforcelib = {path = "../starforcelib"}
|
||||||
lightwave = {path = "../lightwave"}
|
lightwave = {path = "../lightwave"}
|
||||||
|
glob = "0.3.1"
|
||||||
|
|||||||
@@ -1,6 +1,24 @@
|
|||||||
|
use glob::glob;
|
||||||
use lightwave::LightWaveObject;
|
use lightwave::LightWaveObject;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let obj = LightWaveObject::read_file("E:\\Games\\Moorhuhn Kart 3\\extract\\D\\Moorhuhnkart\\3dobjects_tracks\\track04_robinhood\\colreset.lwo").unwrap();
|
let mut successful = 0;
|
||||||
println!("{:#?}", obj);
|
let mut failed = 0;
|
||||||
|
|
||||||
|
for entry in glob("E:/Games/Moorhuhn Kart 3/extract/**/*.lwo").unwrap() {
|
||||||
|
let path = entry.unwrap();
|
||||||
|
println!("{:?}", path.display());
|
||||||
|
match LightWaveObject::read_file(path) {
|
||||||
|
Ok(_) => {
|
||||||
|
successful += 1;
|
||||||
|
println!("...Ok")
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
failed += 1;
|
||||||
|
eprintln!("{:?}", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Successful: {}\nFailed: {}", successful, failed);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user