1#[macro_use]
6extern crate bitflags;
7#[macro_use]
8extern crate failure;
9extern crate memchr;
10
11mod de;
12mod model;
13mod read;
14
15pub use model::*;
16pub use failure::Error;
17
18use read::{BufReadExact, IoReader, SliceReader};
19
20use memchr::memchr;
21
22use std::io;
23use std::{mem, ptr, str, u8};
24use std::path::PathBuf;
25
26pub type Result<T> = std::result::Result<T, Error>;
27
28struct Reader<R: BufReadExact> {
29 rdr: R,
30}
31
32impl<R: io::Read> Reader<IoReader<R>> {
33 fn from_io_reader(rdr: R) -> Self {
34 Reader { rdr: IoReader::new(rdr) }
35 }
36}
37
38impl<'a> Reader<SliceReader<'a>> {
39 fn from_slice(slice: &'a [u8]) -> Self {
40 Reader { rdr: SliceReader::new(slice) }
41 }
42}
43
44impl<R: BufReadExact> Reader<R> {
45 fn read_model(&mut self) -> Result<Model> {
46 let header = self.read_header()?;
47 let vertices = self.read_vertices()?;
48 let triangles = self.read_triangles()?;
49 let groups = self.read_groups()?;
50 let materials = self.read_materials()?;
51 let key_frame_data = self.read_key_frame_data()?;
52 let joints = self.read_joints()?;
53 let comments = self.read_comments()?;
54 let vertex_ex_info = self.read_vertex_ex_info(vertices.len())?;
55 let joint_ex_info = self.read_joint_ex_info(joints.len())?;
56 let model_ex_info = self.read_model_ex_info()?;
57
58 Ok(Model {
59 header,
60 vertices,
61 triangles,
62 groups,
63 materials,
64 key_frame_data,
65 joints,
66 comments,
67 vertex_ex_info,
68 joint_ex_info,
69 model_ex_info,
70 })
71 }
72
73 fn read_header(&mut self) -> Result<Header> {
74 let de::Header { id, version } = unsafe { self.read_type()? };
75 ensure!(id == "MS3D000000".as_bytes(), "invalid header");
76 ensure!(version == 4, "unsupported version {}", version);
77 Ok(Header { version })
78 }
79
80 fn read_vertices(&mut self) -> Result<Vec<Vertex>> {
81 let len = self.read_u16()? as usize;
82 self.read_vec(len, Self::read_vertex)
83 }
84
85 fn read_vertex(&mut self) -> Result<Vertex> {
86 let de::Vertex {
87 flags,
88 vertex,
89 bone_id,
90 reference_count,
91 } = unsafe { self.read_type()? };
92 let flags = convert_flags(flags, Vertex::ALLOWED_FLAGS)?;
93 Ok(Vertex {
94 flags,
95 vertex,
96 bone_id,
97 reference_count,
98 })
99 }
100
101 fn read_triangles(&mut self) -> Result<Vec<Triangle>> {
102 let len = self.read_u16()? as usize;
103 self.read_vec(len, Self::read_triangle)
104 }
105
106 fn read_triangle(&mut self) -> Result<Triangle> {
107 let de::Triangle {
108 flags,
109 vertex_indices,
110 vertex_normals,
111 s,
112 t,
113 smoothing_group,
114 group_index,
115 } = unsafe { self.read_type()? };
116 let flags = convert_flags(flags as u8, Triangle::ALLOWED_FLAGS)?;
117 Ok(Triangle {
118 flags,
119 vertex_indices,
120 vertex_normals,
121 s,
122 t,
123 smoothing_group,
124 group_index,
125 })
126 }
127
128 fn read_groups(&mut self) -> Result<Vec<Group>> {
129 let len = self.read_u16()? as usize;
130 self.read_vec(len, Self::read_group)
131 }
132
133 fn read_group(&mut self) -> Result<Group> {
134 let de::GroupPrefix {
135 flags,
136 name,
137 num_triangles,
138 } = unsafe { self.read_type()? };
139
140 let flags = convert_flags(flags, Group::ALLOWED_FLAGS)?;
141 let name = convert_string(&name)?;
142 let triangle_indices = self.read_vec(num_triangles as usize, Self::read_u16)?;
143
144 let de::GroupSuffix { material_index } = unsafe { self.read_type()? };
145
146 Ok(Group {
147 flags,
148 name,
149 triangle_indices,
150 material_index,
151 })
152 }
153
154 fn read_materials(&mut self) -> Result<Vec<Material>> {
155 let len = self.read_u16()? as usize;
156 self.read_vec(len, Self::read_material)
157 }
158
159 fn read_material(&mut self) -> Result<Material> {
160 let de::Material {
161 name,
162 ambient,
163 diffuse,
164 specular,
165 emissive,
166 shininess,
167 transparency,
168 mode,
169 texture,
170 alphamap,
171 } = unsafe { self.read_type()? };
172
173 let name = convert_string(&name)?;
174 let texture = convert_path(&texture)?;
175 let alphamap = convert_path(&alphamap)?;
176
177 Ok(Material {
178 name,
179 ambient,
180 diffuse,
181 specular,
182 emissive,
183 shininess,
184 transparency,
185 mode,
186 texture,
187 alphamap,
188 })
189 }
190
191 fn read_key_frame_data(&mut self) -> Result<KeyFrameData> {
192 let de::KeyFrameData {
193 animation_fps,
194 current_time,
195 total_frames,
196 } = unsafe { self.read_type()? };
197 Ok(KeyFrameData {
198 animation_fps,
199 current_time,
200 total_frames,
201 })
202 }
203
204 fn read_joints(&mut self) -> Result<Vec<Joint>> {
205 let len = self.read_u16()? as usize;
206 self.read_vec(len, Self::read_joint)
207 }
208
209 fn read_joint(&mut self) -> Result<Joint> {
210 let de::JointPrefix {
211 flags,
212 name,
213 parent_name,
214 rotation,
215 position,
216 num_key_frames_rot,
217 num_key_frames_trans,
218 } = unsafe { self.read_type()? };
219
220 let flags = convert_flags(flags, Joint::ALLOWED_FLAGS)?;
221 let name = convert_string(&name)?;
222 let parent_name = convert_string(&parent_name)?;
223
224 let key_frames_rot = self.read_vec(num_key_frames_rot as usize, Self::read_key_frame_rot)?;
225 let key_frames_trans =
226 self.read_vec(num_key_frames_trans as usize, Self::read_key_frame_pos)?;
227
228 Ok(Joint {
229 flags,
230 name,
231 parent_name,
232 rotation,
233 position,
234 key_frames_rot,
235 key_frames_trans,
236 })
237 }
238
239 fn read_key_frame_rot(&mut self) -> Result<KeyFrameRot> {
240 let de::KeyFrameRot { time, rotation } = unsafe { self.read_type()? };
241 Ok(KeyFrameRot { time, rotation })
242 }
243
244 fn read_key_frame_pos(&mut self) -> Result<KeyFramePos> {
245 let de::KeyFramePos { time, position } = unsafe { self.read_type()? };
246 Ok(KeyFramePos { time, position })
247 }
248
249 fn read_comments(&mut self) -> Result<Comments> {
250 let sub_version = self.read_i32()?;
251 ensure!(
252 sub_version == 1,
253 "unsupported comment sub-version {}",
254 sub_version
255 );
256 let len = self.read_u32()? as usize;
257 let group_comments = self.read_vec(len, Self::read_comment)?;
258 let len = self.read_i32()? as usize;
259 let material_comments = self.read_vec(len, Self::read_comment)?;
260 let len = self.read_i32()? as usize;
261 let joint_comments = self.read_vec(len, Self::read_comment)?;
262 let len = self.read_i32()? as usize;
263 let model_comment = match len {
264 0 => None,
265 1 => Some(self.read_comment()?),
266 _ => bail!("invalid number of model comments"),
267 };
268
269 Ok(Comments {
270 sub_version,
271 group_comments,
272 material_comments,
273 joint_comments,
274 model_comment,
275 })
276 }
277
278 fn read_comment(&mut self) -> Result<Comment> {
279 let de::CommentPrefix {
280 index,
281 comment_length,
282 } = unsafe { self.read_type()? };
283 let comment = self.read_string(comment_length as usize)?;
284 Ok(Comment { index, comment })
285 }
286
287 fn read_vertex_ex_info(&mut self, len: usize) -> Result<VertexExInfo> {
288 use VertexExInfo::*;
289
290 let sub_version = self.read_i32()?;
291 match sub_version {
292 1 => Ok(SubVersion1(self.read_vec(len, Self::read_vertex_ex_1)?)),
293 2 => Ok(SubVersion2(self.read_vec(len, Self::read_vertex_ex_2)?)),
294 3 => Ok(SubVersion3(self.read_vec(len, Self::read_vertex_ex_3)?)),
295 v => bail!("unsupported vertex ex sub-version {}", v),
296 }
297 }
298
299 fn read_vertex_ex_1(&mut self) -> Result<VertexEx1> {
300 let de::VertexEx1 { bone_ids, weights } = unsafe { self.read_type()? };
301 Ok(VertexEx1 { bone_ids, weights })
302 }
303
304 fn read_vertex_ex_2(&mut self) -> Result<VertexEx2> {
305 let de::VertexEx2 {
306 bone_ids,
307 weights,
308 extra,
309 } = unsafe { self.read_type()? };
310 Ok(VertexEx2 {
311 bone_ids,
312 weights,
313 extra,
314 })
315 }
316
317 fn read_vertex_ex_3(&mut self) -> Result<VertexEx3> {
318 let de::VertexEx3 {
319 bone_ids,
320 weights,
321 extra,
322 } = unsafe { self.read_type()? };
323 Ok(VertexEx3 {
324 bone_ids,
325 weights,
326 extra,
327 })
328 }
329
330 fn read_joint_ex_info(&mut self, len: usize) -> Result<JointExInfo> {
331 let sub_version = self.read_i32()?;
332 ensure!(
333 sub_version == 1,
334 "unsupported joint ex sub-version {}",
335 sub_version
336 );
337 let joint_ex = self.read_vec(len, Self::read_joint_ex)?;
338 Ok(JointExInfo {
339 sub_version,
340 joint_ex,
341 })
342 }
343
344 fn read_joint_ex(&mut self) -> Result<JointEx> {
345 let de::JointEx { color } = unsafe { self.read_type()? };
346 Ok(JointEx { color })
347 }
348
349 fn read_model_ex_info(&mut self) -> Result<ModelExInfo> {
350 let sub_version = self.read_i32()?;
351 ensure!(
352 sub_version == 1,
353 "unsupported model ex sub-version {}",
354 sub_version
355 );
356 let model_ex = self.read_model_ex()?;
357 Ok(ModelExInfo {
358 sub_version,
359 model_ex,
360 })
361 }
362
363 fn read_model_ex(&mut self) -> Result<ModelEx> {
364 let de::ModelEx {
365 joint_size,
366 transparency_mode,
367 alpha_ref,
368 } = unsafe { self.read_type()? };
369 Ok(ModelEx {
370 joint_size,
371 transparency_mode,
372 alpha_ref,
373 })
374 }
375
376 fn read_string(&mut self, len: usize) -> Result<String> {
377 Ok(str::from_utf8(self.rdr.buf_read_exact(len)?)?.to_owned())
378 }
379
380 fn read_vec<T, F>(&mut self, len: usize, f: F) -> Result<Vec<T>>
381 where
382 F: Fn(&mut Self) -> Result<T>,
383 {
384 (0..len).map(|_| f(self)).collect()
385 }
386
387 fn read_u16(&mut self) -> Result<u16> {
388 unsafe { self.read_type() }
389 }
390
391 fn read_u32(&mut self) -> Result<u32> {
392 unsafe { self.read_type() }
393 }
394
395 fn read_i32(&mut self) -> Result<i32> {
396 unsafe { self.read_type() }
397 }
398
399 unsafe fn read_type<T>(&mut self) -> Result<T> {
400 Ok(ptr::read_unaligned(
401 self.rdr.buf_read_exact(mem::size_of::<T>())? as *const [u8] as *const T,
402 ))
403 }
404}
405
406fn convert_string(bytes: &[u8]) -> Result<String> {
407 let vec = if let Some(i) = memchr(0, bytes) {
408 bytes[..i].to_owned()
409 } else {
410 bytes.to_owned()
411 };
412 Ok(String::from_utf8(vec)?)
413}
414
415fn convert_path(bytes: &[u8]) -> Result<PathBuf> {
416 convert_string(bytes).map(Into::into)
417}
418
419fn convert_flags(bits: u8, allowed: Flags) -> Result<Flags> {
420 if let Some(flags) = Flags::from_bits(bits) {
421 if allowed.contains(flags) {
422 return Ok(flags);
423 }
424 }
425 Err(format_err!("invalid flags {}", bits))
426}