gmftools/gmflib/src/types.rs

436 lines
10 KiB
Rust

use gmfmacros::GMFElement;
use crate::machinery::{ReadResult, ReadStream, GMFElement};
#[derive(Debug)]
pub struct GMI {
pub version: u32,
pub model_type: ModelType,
pub unk1: u32,
pub unk2: u32,
pub scene: Scene,
pub materials: MaterialList,
pub objects: ObjectList,
}
impl GMI {
pub fn parse<R: std::io::Read>(r: R) -> ReadResult<Self> {
let mut r = ReadStream::new(r);
r.read("gmi")
}
}
impl GMFElement for GMI {
fn read<R: std::io::Read>(r: &mut ReadStream<R>) -> ReadResult<Self> {
if r.bytes(3)? != b"GMI".to_vec() {
return Err(r.error("invaid magic"));
}
let version: u32 = r.read("version")?;
let model_type = r.read("model_type")?;
let unk1: u32 = r.read("unk1")?;
if unk1 != 0 {
return Err(r.error("invalid unk1"));
}
let unk2: u32 = r.read("unk2")?;
if unk2 != 15 {
return Err(r.error("invalid unk2"));
}
Ok(Self {
version, model_type, unk1, unk2,
scene: r.read("scene")?,
materials: r.read("material_list")?,
objects: r.read("object_list")?,
})
}
}
#[derive(Debug,GMFElement)]
pub struct Color {
pub r: u8,
pub g: u8,
pub b: u8,
pub a: u8,
}
#[derive(Debug,GMFElement)]
pub enum MapKind {
Diffuse = 1,
SelfIllum = 5,
Opacity = 6,
}
#[derive(Debug,GMFElement)]
pub enum MapType {
Screen = 4,
}
#[derive(Debug,GMFElement)]
pub enum BitmapFilter {
Pyramidal = 0,
SAT = 1,
}
#[derive(Debug, GMFElement)]
pub enum ModelType {
BasicModel = 1,
}
#[derive(Debug,GMFElement)]
#[gmf_tagged(1,2)]
pub struct Scene {
pub filename: String,
pub first_frame: u32,
pub last_frame: u32,
pub frame_speed: u32,
pub ticks_per_frame: u32,
pub background: Color,
pub ambient: Color,
}
#[derive(Debug,GMFElement)]
#[gmf_tagged(7, 2)]
pub struct MaterialList {
pub materials: Vec<Material>,
}
#[derive(Debug,GMFElement)]
#[gmf_tagged(8, 2)]
pub struct Material {
pub ref_no: u32,
pub name: String,
pub class: String,
pub ambient: Color,
pub diffuse: Color,
pub specular: Color,
pub shine: f32,
pub shine_strength: f32,
pub wiresize: f32,
pub transparency: f32,
pub shading: Shading,
pub xp_falloff: f32,
pub selfillum: f32,
pub falloff: Falloff,
pub xp_type: XPType,
pub textures: Option<TextureList>,
pub sub: Option<MaterialList>,
}
#[derive(Debug,GMFElement)]
pub enum Shading {
Other = 0,
Blinn = 0xc,
}
#[derive(Debug, GMFElement)]
pub enum Falloff {
In = 0,
}
#[derive(Debug,GMFElement)]
pub enum XPType {
Other = 0,
Filter = 1,
}
#[derive(Debug,GMFElement)]
#[gmf_tagged(14, 2)]
pub struct TextureList {
pub textures: Vec<Texture>,
}
#[derive(Debug,GMFElement)]
#[gmf_tagged(15, 4)]
pub struct Texture {
pub name: String,
pub class: String,
pub bitmap: String,
pub amount: f32,
pub kind: MapKind,
pub map_type: MapType,
pub u_offset: f32,
pub v_offset: f32,
pub u_tiling: f32,
pub v_tiling: f32,
pub angle: f32,
pub blur: f32,
pub blur_offset: f32,
pub noise_amt: f32,
pub noise_size: f32,
pub noise_level: u32,
pub noise_phase: f32,
pub invert: u32,
pub unknown: u32,
pub filter: BitmapFilter,
pub channel: u32,
pub sub: Option<TextureList>,
}
#[derive(Debug,GMFElement)]
#[gmf_tagged(18,2)]
pub struct ObjectList {
pub objects: Vec<Object>,
}
#[derive(Debug)]
pub enum Object {
Geometry(GeometryObject),
Light(LightObject),
AttachmentPoint(AttachmentPointObject),
ConstraintSolver(ConstraintSolverObject),
Simulation(SimulationObject),
RBCollection(RBCollectionObject),
}
impl GMFElement for Object {
fn read<R: std::io::Read>(r: &mut ReadStream<R>) -> ReadResult<Self> {
let tlv = r.tlv()?;
let (res, check) = match (tlv.tag, tlv.flags) {
(2, 4) => (Object::Geometry(r.read("geometry")?), false),
(5, 3) => (Object::Light(r.read("light")?), false),
(21, 2) => (Object::AttachmentPoint(r.read("attachmentpoint")?), true),
(42, 3) => (Object::ConstraintSolver(r.read("constraintsolver")?), false),
(30, 2) => (Object::Simulation(r.read("simulation")?), false),
_ => return Err(r.error(format!("unknown object type ({}, {})", tlv.tag, tlv.flags))),
};
println!("{:#?}", res);
if check {
tlv.check(r)?;
}
Ok(res)
}
}
#[derive(Debug,GMFElement)]
pub struct GeometryObject {
pub name: String,
pub parent: String,
pub shade_verts: u8,
pub tm: TransformMatrix,
pub mesh: Mesh,
}
#[derive(Debug,GMFElement)]
#[gmf_tagged(17, 2)]
pub struct TransformMatrix {
pub name: String,
pub data: [f32; 12],
}
#[derive(Debug)]
pub struct Mesh {
pub time: u32,
pub vertex_count: u32,
pub face_count: u32,
pub tvertex_count: u32,
pub cvertex_count: u32,
pub material_ref: u32,
pub vertices: Vec<Point>,
pub faces: Vec<Face>,
pub tvertices: Vec<Point>,
pub tfaces: Vec<TFace>,
pub channels: Option<Vec<TextureChannel>>,
pub cvertices: Vec<Point>,
pub cfaces: Vec<TFace>,
pub normals: Vec<FaceNormal>,
pub backface_cull: u32,
}
impl GMFElement for Mesh {
fn read<R: std::io::Read>(r: &mut ReadStream<R>) -> ReadResult<Self> {
let tlv = r.tlv()?;
if tlv.tag != 16 || tlv.flags != 4 {
return Err(r.error("unexpected tag/flags (wanted 16/4)"));
}
let time = r.read("time")?;
let vertex_count = r.read("vertex_count")?;
let face_count = r.read("face_count")?;
let tvertex_count = r.read("tvertex_count")?;
let cvertex_count = r.read("cvertex_count")?;
let material_ref = r.read("material_ref")?;
let res = Self {
time, vertex_count, face_count, tvertex_count,
cvertex_count, material_ref,
vertices: (0..vertex_count).map(|_| r.read("vertices")).collect::<ReadResult<Vec<Point>>>()?,
faces: (0..face_count).map(|_| r.read("faces")).collect::<ReadResult<Vec<Face>>>()?,
tvertices: (0..tvertex_count).map(|_| r.read("tvertices")).collect::<ReadResult<Vec<Point>>>()?,
tfaces: if tvertex_count > 0 {
(0..face_count).map(|_| r.read("tfaces")).collect::<ReadResult<Vec<TFace>>>()?
} else {
vec![]
},
channels: r.read("channels")?,
cvertices: (0..cvertex_count).map(|_| r.read("cvertices")).collect::<ReadResult<Vec<Point>>>()?,
cfaces: if cvertex_count > 0 {
(0..face_count).map(|_| r.read("cfaces")).collect::<ReadResult<Vec<TFace>>>()?
} else {
vec![]
},
normals: (0..face_count).map(|_| r.read("normals")).collect::<ReadResult<Vec<FaceNormal>>>()?,
backface_cull: r.read("backface_cull")?,
};
// Broken for stock files.
//tlv.check(r)?;
Ok(res)
}
}
#[derive(Debug,GMFElement)]
pub struct Point {
pub x: f32,
pub y: f32,
pub z: f32,
}
#[derive(Debug,GMFElement)]
pub struct Face {
pub a: u32,
pub b: u32,
pub c: u32,
pub mtlid: u32,
}
#[derive(Debug,GMFElement)]
pub struct TFace {
pub a: u32,
pub b: u32,
pub c: u32,
}
#[derive(Debug,GMFElement)]
pub struct FaceNormal {
pub face: [f32; 3],
pub vertex: [[f32; 3]; 3],
}
#[derive(Debug)]
pub struct TextureChannel {
pub unk1: u32,
pub tvertex_count: u32,
pub unk2: u32,
pub face_count: u32,
pub unk3: u32,
pub unk4: u32,
pub tvertex_count2: u32,
pub face_count2: u32,
pub tvertices: Vec<Point>,
pub tfaces: Vec<TFace>,
}
impl GMFElement for TextureChannel {
fn read<R: std::io::Read>(r: &mut ReadStream<R>) -> ReadResult<Self> {
let unk1 = r.read("unk1")?;
let tvertex_count = r.read("tvertex_count")?;
let unk2 = r.read("unk2")?;
let face_count = r.read("face_count")?;
let unk3 = r.read("unk3")?;
let unk4 = r.read("unk4")?;
let tvertex_count2 = r.read("tvertex_count2")?;
let face_count2 = r.read("face_count2")?;
let res = Self {
unk1, tvertex_count,
unk2, face_count,
unk3, unk4,
tvertex_count2,
face_count2,
tvertices: (0..tvertex_count).map(|_| r.read("tvertices")).collect::<ReadResult<Vec<_>>>()?,
tfaces: if tvertex_count > 0 {
(0..face_count).map(|_| r.read("tfaces")).collect::<ReadResult<Vec<_>>>()?
} else {
vec![]
},
};
Ok(res)
}
}
#[derive(Debug,GMFElement)]
pub struct LightObject {
pub name: String,
pub tm: TransformMatrix,
pub target: String,
pub light_type: LightType,
pub shadows: LightShadows,
pub uselight: u32,
pub color: Color,
pub intensity: f32,
pub aspect: f32,
pub unk1: [u8; 8],
pub attn_start: f32,
pub attn_end: f32,
pub tdist: f32,
pub use_for_attn: u32,
}
#[derive(Debug,GMFElement)]
pub enum LightType {
Omni = 0,
}
#[derive(Debug,GMFElement)]
pub enum LightShadows {
Off = 0,
}
#[derive(Debug,GMFElement)]
pub struct AttachmentPointObject {
pub name: String,
pub tm: TransformMatrix,
pub user_data: String,
}
#[derive(Debug,GMFElement)]
pub struct ConstraintSolverObject {
pub name: String,
pub threshold: f32,
pub rb_collection_name: String,
pub constraints: Option<ConstraintList>,
}
#[derive(Debug,GMFElement)]
#[gmf_tagged(44, 2)]
pub struct ConstraintList {
pub constraints: Vec<Constraint>,
}
#[derive(Debug,GMFElement)]
pub enum Constraint {
Foo = 1,
}
#[derive(Debug,GMFElement)]
pub struct SimulationObject {
pub name: String,
pub gravity: Point,
pub worldscale: f32,
pub simtolerance: f32,
pub resolver: u32,
pub incl_drag: u8,
pub linear_drag: f32,
pub angular_drag: f32,
pub incl_deactivator: u8,
pub shortfreq: f32,
pub longfreq: f32,
pub last_subspace: u8,
pub updates_per_timestamp: f32,
pub collision_pairs: u32,
}
#[derive(Debug,GMFElement)]
pub struct RBCollectionObject {
pub name: String,
}