lightwave_3d/lib.rs
1use crate::lwo2::tags::Tag;
2use binrw::{binread, until_eof, BinRead, BinResult};
3use std::fs::File;
4use std::io::{Read, Seek};
5use std::path::Path;
6
7mod binrw_helpers;
8pub mod iff;
9pub mod lwo2;
10
11/// The data in LightWave 3D® object files comprise the points, polygons and surfaces that describe
12/// the geometry and appearance of an object. "Polygons" here means any of several geometric
13/// elements (faces, curves or patches, for example) defined by an ordered list of points, and
14/// "surfaces" refers to the collection of attributes, sometimes called materials, that define
15/// the visual surface properties of polygons.
16///
17/// Object files can contain multiple layers, or parts, and each part can be a single connected mesh
18/// or several disjoint meshes. They may also contain one or more surface definitions with no points
19/// or polygons at all. Surface definitions can include references to other files (images, for
20/// example), plug-ins, and envelopes containing parameter values that vary over time.
21///
22/// This document outlines the object file format and provides a detailed reference for each of the
23/// components. The component descriptions include both a regular expression defining the syntax and
24/// a discussion of the contents. See also the Examples supplement, a more conversational
25/// introduction to the format that includes annotated listings of file contents as well as
26/// several sample files.
27/// Informally, object files start with the four bytes "FORM" followed by a four-byte integer giving
28/// the length of the file (minus 8) and the four byte ID "LWO2". The remainder of the data is a
29/// collection of chunks, some of which will contain subchunks.
30///
31/// To be read, IFF files must be parsed. The order in which chunks can occur in a file isn't fixed.
32/// Some chunks, however, contain data that depends on the contents of other chunks, and this fixes
33/// a relative order for the chunks involved. Chunks and subchunks also depend on context for their
34/// meaning. The CHAN subchunk in an envelope chunk isn't the same thing as the CHAN subchunk in a
35/// surface block. And you may encounter chunks that aren't defined here, which you should be
36/// prepared to skip gracefully if you don't understand them. You can do this by using the chunk
37/// size to seek to the next chunk.
38#[binread]
39#[br(big, magic(b"FORM"))]
40#[derive(Debug)]
41pub struct LightWaveObject {
42 pub file_size: u32,
43 #[br(magic(b"LWO2"), parse_with = until_eof)]
44 pub data: Vec<Tag>,
45}
46
47impl LightWaveObject {
48 pub fn read_file<P: AsRef<Path>>(path: P) -> std::io::Result<LightWaveObject> {
49 let mut reader = File::open(path)?;
50 Self::read(&mut reader)
51 .map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidData, err))
52 }
53
54 pub fn read<R>(reader: &mut R) -> BinResult<LightWaveObject>
55 where
56 R: Read + Seek,
57 {
58 BinRead::read(reader)
59 }
60}