1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
use std::path::PathBuf;
use std::io;

use super::{Reader, Result};

/// Represents an ms3d model file.
#[derive(Clone, Debug)]
pub struct Model {
    pub header: Header,
    pub vertices: Vec<Vertex>,
    pub triangles: Vec<Triangle>,
    pub groups: Vec<Group>,
    pub materials: Vec<Material>,
    pub key_frame_data: KeyFrameData,
    pub joints: Vec<Joint>,
    pub comments: Comments,
    pub vertex_ex_info: VertexExInfo,
    pub joint_ex_info: JointExInfo,
    pub model_ex_info: ModelExInfo,
}

impl Model {
    /// Read an ms3d model file from a reader.
    pub fn from_reader<R: io::Read>(rdr: R) -> Result<Self> {
        Reader::from_io_reader(rdr).read_model()
    }

    /// Read an ms3d model file from a slice of bytes.
    pub fn from_bytes(bytes: &[u8]) -> Result<Self> {
        Reader::from_slice(bytes).read_model()
    }
}

#[derive(Clone, Debug)]
pub struct Header {
    pub version: i32,
}

bitflags! {
    pub struct Flags: u8 {
        const SELECTED = 1;
        const HIDDEN = 2;
        const SELECTED2 = 4;
        const DIRTY = 8;
    }
}

#[derive(Clone, Debug)]
pub struct Vertex {
    pub flags: Flags,
    pub vertex: [f32; 3],
    pub bone_id: i8,
    pub reference_count: u8,
}

impl Vertex {
    pub(crate) const ALLOWED_FLAGS: Flags = Flags {
        bits: Flags::SELECTED.bits | Flags::SELECTED2.bits | Flags::HIDDEN.bits,
    };
}

#[derive(Clone, Debug)]
pub struct Triangle {
    pub flags: Flags,
    pub vertex_indices: [u16; 3],
    pub vertex_normals: [[f32; 3]; 3],
    pub s: [f32; 3],
    pub t: [f32; 3],
    pub smoothing_group: u8,
    pub group_index: u8,
}

impl Triangle {
    pub(crate) const ALLOWED_FLAGS: Flags = Flags {
        bits: Flags::SELECTED.bits | Flags::SELECTED2.bits | Flags::HIDDEN.bits,
    };
}

#[derive(Clone, Debug)]
pub struct Group {
    pub flags: Flags,
    pub name: String,
    pub triangle_indices: Vec<u16>,
    pub material_index: i8,
}

impl Group {
    pub(crate) const ALLOWED_FLAGS: Flags = Flags {
        bits: Flags::SELECTED.bits | Flags::HIDDEN.bits,
    };
}

#[derive(Clone, Debug)]
pub struct Material {
    pub name: String,
    pub ambient: [f32; 4],
    pub diffuse: [f32; 4],
    pub specular: [f32; 4],
    pub emissive: [f32; 4],
    pub shininess: f32,
    pub transparency: f32,
    pub mode: u8,
    pub texture: PathBuf,
    pub alphamap: PathBuf,
}

#[derive(Clone, Debug)]
pub struct KeyFrameData {
    pub animation_fps: f32,
    pub current_time: f32,
    pub total_frames: i32,
}

#[derive(Clone, Debug)]
pub struct KeyFrameRot {
    pub time: f32,
    pub rotation: [f32; 3],
}

#[derive(Clone, Debug)]
pub struct KeyFramePos {
    pub time: f32,
    pub position: [f32; 3],
}

#[derive(Clone, Debug)]
pub struct Joint {
    pub flags: Flags,
    pub name: String,
    pub parent_name: String,
    pub rotation: [f32; 3],
    pub position: [f32; 3],
    pub key_frames_rot: Vec<KeyFrameRot>,
    pub key_frames_trans: Vec<KeyFramePos>,
}

impl Joint {
    pub(crate) const ALLOWED_FLAGS: Flags = Flags {
        bits: Flags::SELECTED.bits | Flags::DIRTY.bits,
    };
}

#[derive(Clone, Debug)]
pub struct Comment {
    pub index: i32,
    pub comment: String,
}

#[derive(Clone, Debug)]
pub struct Comments {
    pub sub_version: i32,
    pub group_comments: Vec<Comment>,
    pub material_comments: Vec<Comment>,
    pub joint_comments: Vec<Comment>,
    pub model_comment: Option<Comment>,
}

#[derive(Clone, Debug)]
pub enum VertexExInfo {
    SubVersion1(Vec<VertexEx1>),
    SubVersion2(Vec<VertexEx2>),
    SubVersion3(Vec<VertexEx3>),
}

#[derive(Clone, Debug)]
pub struct VertexEx1 {
    pub bone_ids: [i8; 3],
    pub weights: [u8; 3],
}

#[derive(Clone, Debug)]
pub struct VertexEx2 {
    pub bone_ids: [i8; 3],
    pub weights: [u8; 3],
    pub extra: u32,
}

#[derive(Clone, Debug)]
pub struct VertexEx3 {
    pub bone_ids: [i8; 3],
    pub weights: [u8; 3],
    pub extra: [u32; 2],
}

#[derive(Clone, Debug)]
pub struct JointExInfo {
    pub sub_version: i32,
    pub joint_ex: Vec<JointEx>,
}

#[derive(Clone, Debug)]
pub struct JointEx {
    pub color: [f32; 3],
}

#[derive(Clone, Debug)]
pub struct ModelExInfo {
    pub sub_version: i32,
    pub model_ex: ModelEx,
}

#[derive(Clone, Debug)]
pub struct ModelEx {
    pub joint_size: f32,
    pub transparency_mode: i32,
    pub alpha_ref: f32,
}