1#![allow(non_snake_case)]
2#![allow(unused_variables)]
3
4extern crate pretty_env_logger;
5extern crate nom;
6
7use std::str;
8use std::str::FromStr;
9
10use self::nom::digit;
11
12use interface::i_md5::mesh::*;
13use interface::i_file::IParseStr;
14
15named!( shader_path< &str, String >,
16 do_parse!(
17 ws!( tag!("shader") ) >>
18 path: delimited!(
19 tag!("\""),
20 take_until!("\""),
21 tag!("\"")
22 ) >>
23 ( path.to_string() )
24 )
25);
26
27named!( md5mesh_weight< &str, Md5Weight >,
29 do_parse!(
30 ws!( tag!("weight") ) >>
31 idx: map_res!( ws!(digit), FromStr::from_str ) >>
32 joint_idx: map_res!( ws!(digit), FromStr::from_str ) >>
33 weight_bias: ws!(nom::float_s) >>
34 ws!(tag!("(")) >>
35 pos0: ws!(nom::float_s) >>
36 pos1: ws!(nom::float_s) >>
37 pos2: ws!(nom::float_s) >>
38 ws!(tag!(")")) >>
39 (
40 Md5Weight {
41 _index: idx,
42 _joint_index: joint_idx,
43 _weight_bias: weight_bias,
44 _pos: [ pos0, pos1, pos2 ],
45 }
46 )
47 )
48);
49
50named!( md5mesh_weights< &str, Vec<Md5Weight> >,
51 do_parse!(
52 ws!( tag!("numweights") ) >>
53 count_weights: map_res!( ws!(digit), FromStr::from_str ) >>
54 weights: count!(
55 md5mesh_weight
56 ,count_weights ) >>
57 ( weights )
58 )
59);
60
61named!( md5mesh_vert< &str, Md5Vert >,
62 do_parse!(
63 ws!( tag!("vert") ) >>
64 idx: map_res!( ws!(digit), FromStr::from_str ) >>
65 ws!(tag!("(")) >>
66 v0: ws!(nom::float_s) >>
67 v1: ws!(nom::float_s) >>
68 ws!(tag!(")")) >>
69 v2: map_res!( ws!(digit), FromStr::from_str ) >>
70 v3: map_res!( ws!(digit), FromStr::from_str ) >>
71 (
72 Md5Vert {
73 _index: idx,
74 _tex_coords: [ v0, v1 ],
75 _weight_start: v2,
76 _weight_count: v3,
77 _normal: [0f32;3],
78 _pos: [0f32;3],
79 }
80 )
81 )
82);
83
84named!( md5mesh_verts< &str, Vec<Md5Vert> >,
85 do_parse!(
86 ws!( tag!("numverts") ) >>
87 count_verts: map_res!( ws!(digit), FromStr::from_str ) >>
88 verts: count!(
89 md5mesh_vert
90 ,count_verts ) >>
91 ( verts )
92 )
93);
94
95named!( md5mesh_tri< &str, Md5Tri >,
96 do_parse!(
97 ws!( tag!("tri") ) >>
98 idx: map_res!( ws!(digit), FromStr::from_str ) >>
99 v0: map_res!( ws!(digit), FromStr::from_str ) >>
100 v1: map_res!( ws!(digit), FromStr::from_str ) >>
101 v2: map_res!( ws!(digit), FromStr::from_str ) >>
102 (
103 Md5Tri {
104 _index: idx,
105 _vert_indices: [ v0, v1, v2 ]
106 }
107 )
108 )
109);
110
111named!( md5mesh_tris< &str, Vec< Md5Tri > >,
112 do_parse!(
113 ws!( tag!("numtris") ) >>
114 count_tris: map_res!( ws!(digit), FromStr::from_str ) >>
115 tris: count!(
116 md5mesh_tri
117 ,count_tris ) >>
118 ( tris )
119 )
120);
121
122named!( md5mesh_parse_opening< &str, () >,
123 do_parse!(
124 ws!( tag!("mesh") ) >>
125 ws!( tag!("{") ) >>
126 ()
127 )
128);
129named!( md5mesh_parse_closing< &str, () >,
130 do_parse!(
131 ws!( tag!("}") ) >>
132 ()
133 )
134);
135
136named!( peek_shader< &str, &str >,
137 peek!(
138 ws!( tag!("shader") )
139 )
140);
141
142named!( peek_verts< &str, &str >,
143 peek!(
144 ws!( tag!("numverts") )
145 )
146);
147
148named!( peek_tris< &str, &str >,
149 peek!(
150 ws!( tag!("numtris") )
151 )
152);
153
154named!( peek_weights< &str, &str >,
155 peek!(
156 ws!( tag!("numweights") )
157 )
158);
159
160named!( peek_version< &str, &str >,
161 peek!(
162 ws!( tag!("MD5Version") )
163 )
164);
165
166named!( md5_version< &str, isize >,
167 do_parse!(
168 ws!( tag!("MD5Version") ) >>
169 version: map_res!( ws!(digit), FromStr::from_str ) >>
170 ( version )
171 )
172);
173
174named!( peek_commandline< &str, &str >,
175 peek!(
176 ws!( tag!("commandline") )
177 )
178);
179
180named!( md5_commandline< &str, String >,
181 do_parse!(
182 ws!( tag!("commandline") ) >>
183 cmd: delimited!(
184 tag!("\""),
185 take_until!("\""),
186 tag!("\"")
187 ) >>
188 ( cmd.to_string() )
189 )
190);
191
192named!( peek_numJoints< &str, &str >,
193 peek!(
194 ws!( tag!("numJoints") )
195 )
196);
197
198named!( md5_numJoints< &str, isize >,
199 do_parse!(
200 ws!( tag!("numJoints") ) >>
201 num: map_res!( ws!(digit), FromStr::from_str ) >>
202 ( num )
203 )
204);
205
206named!( peek_numMeshes< &str, &str >,
207 peek!(
208 ws!( tag!("numMeshes") )
209 )
210);
211
212named!( md5_numMeshes< &str, isize >,
213 do_parse!(
214 ws!( tag!("numMeshes") ) >>
215 num: map_res!( ws!(digit), FromStr::from_str ) >>
216 ( num )
217 )
218);
219
220named!( peek_joints< &str, &str >,
221 peek!(
222 ws!( tag!("joints") )
223 )
224);
225
226
227named!( signed_num< &str, &str >,
228 recognize!(
229 do_parse!(
230 sgn: alt!( tag!("+") | tag!("-") | tag!("") ) >>
231 d: digit >> ()
232 )
233 )
234);
235
236named!( md5mesh_joint< &str, Md5Joint >,
237 do_parse!(
238 name: ws!(delimited!(
239 tag!("\""),
240 take_until!("\""),
241 tag!("\"")
242 ) ) >>
243 idx: map_res!(ws!(signed_num), <isize as FromStr>::from_str ) >>
244 ws!(tag!("(")) >>
245 p0: ws!(nom::float_s) >>
246 p1: ws!(nom::float_s) >>
247 p2: ws!(nom::float_s) >>
248 ws!(tag!(")")) >>
249 ws!(tag!("(")) >>
250 o0: ws!(nom::float_s) >>
251 o1: ws!(nom::float_s) >>
252 o2: ws!(nom::float_s) >>
253 ws!(tag!(")")) >>
254 (
255 Md5Joint {
256 _name: name.to_string(),
257 _parent_index: idx as i64,
258 _pos: [ p0, p1, p2 ],
259 _orient: [ o0, o1, o2 ],
260 _rot: Default::default(),
261 }
262 )
263 )
264);
265
266named!( md5mesh_joints_opening< &str, &str >,
267 do_parse!(
268 ws!( tag!("joints") ) >>
269 a: ws!( tag!("{") ) >>
270 ( a )
271 )
272);
273
274named!( md5mesh_joints_closing< &str, () >,
275 do_parse!(
276 ws!( tag!("}") ) >>
277 ()
278 )
279);
280
281named!( peek_comments< &str, &str >,
282 peek!(
283 ws!( tag!("//") )
284 )
285);
286
287named!( consume_comments_start< &str, () >,
288 do_parse!(
289 take_until_either!( "\n\r" ) >>
290 tag!("//") >>
291 ()
292 )
293);
294
295named!( consume_comments< &str, &str >,
296 take_until_either!( "\n\r" )
297);
298
299named!( consume_newline< &str, &str >,
300 not!( take_until_and_consume!( "\n\r" ) )
301);
302
303fn parse_mesh( input: & str ) -> Result< ( & str, Md5Mesh ), & 'static str > {
304
305 let mut buf = input;
306
307 match md5mesh_parse_opening( buf ) {
308 nom::IResult::Done( i, _ ) => {
309 buf = i;
310 },
311 other => {
312 return Err( "no mesh opening token found" )
313 }
314 };
315
316 let mut shader : Option< String > = None;
317 let mut verts : Option< Vec< Md5Vert > > = None;
318 let mut tris : Option< Vec< Md5Tri > > = None;
319 let mut weights : Option< Vec< Md5Weight > > = None;
320
321 loop {
322
323 let mut progress = false;
324
325 match peek_and_consume_comments( buf ) {
326 Some(x) => {
327 buf = x;
328 progress = true;
329 },
330 _ => {},
331 }
332
333 match peek_shader( buf ) {
334 nom::IResult::Done( _, _ ) => {
335 match shader_path( buf ) {
336 nom::IResult::Done( i, o ) => {
337 shader = Some( o );
338 buf = i;
339 progress = true;
340 },
341 _ => {},
342 }
343 },
344 _ => {},
345 }
346
347 match peek_verts( buf ) {
348 nom::IResult::Done( _, _ ) => {
349 match md5mesh_verts( buf ) {
350 nom::IResult::Done( i, o ) => {
351 verts = Some( o );
352 buf = i;
353 progress = true;
354 },
355 _ => {},
356 }
357 },
358 _ => {},
359 }
360
361 match peek_tris( buf ) {
362 nom::IResult::Done( _, _ ) => {
363 match md5mesh_tris( buf ) {
364 nom::IResult::Done( i, o ) => {
365 tris = Some( o );
366 buf = i;
367 progress = true;
368 },
369 _ => {},
370 }
371 },
372 _ => {},
373 }
374
375 match peek_weights( buf ) {
376 nom::IResult::Done( _, _ ) => {
377 match md5mesh_weights( buf ) {
378 nom::IResult::Done( i, o ) => {
379 weights = Some( o );
380 buf = i;
381 progress = true;
382 },
383 _ => {},
384 }
385 },
386 _ => {},
387 }
388
389 if !progress {
390 break;
391 }
392 }
393
394 match md5mesh_parse_closing( buf ) {
395 nom::IResult::Done( i, _ ) => {
396 buf = i;
397 },
398 _ => { return Err("mesh closing token not found") },
399 }
400
401 match ( shader, verts, tris, weights ) {
402 ( Some(s), Some(v), Some(t), Some(w) ) => {
403 Ok( ( buf, Md5Mesh {
404 _shader: s,
405 _numverts: v.len() as u64,
406 _numtris: t.len() as u64,
407 _numweights: w.len() as u64,
408 _verts: v,
409 _tris: t,
410 _weights: w,
411 } ) )
412 },
413 _ => {
414 Err( "Mesh parse unsuccessful" )
415 }
416 }
417}
418
419fn peek_and_consume_comments( mut input: & str ) -> Option< & str > {
420 match peek_comments( input ) {
421 nom::IResult::Done( i, o ) => {
422 match consume_comments_start( i ) {
423 nom::IResult::Done( j, o ) => {
424 input = j;
425 },
426 _ => {},
427 }
428 match consume_comments( input ) {
429 nom::IResult::Done( j, o ) => {
430 input = j;
431 },
432 _ => {},
433 }
434 match consume_newline( input ) {
435 nom::IResult::Done( k, o ) => {
436 input = k;
437 },
438 _ => {},
439 }
440 return Some( input )
441 },
442 _ => {},
443 }
444 None
445}
446
447pub struct Md5MeshParser {}
448
449impl IParseStr for Md5MeshParser {
450 type output = Md5MeshRoot;
451
452 fn parse( file_content: &str ) -> Result< Self::output, & 'static str > {
453
454 let mut buf = file_content;
457
458 let mut version = None;
459 let mut cmdline = None;
460 let mut num_joints = None;
461 let mut num_meshes = None;
462
463 let mut joints : Vec< Md5Joint > = vec![];
464 let mut meshes : Vec< Md5Mesh > = vec![];
465
466 loop {
467
468 let mut progress = false;
469
470 match peek_version( buf ) {
471 nom::IResult::Done( _, _ ) => {
472 match md5_version( buf ) {
473 nom::IResult::Done( i, o ) => {
474 version = Some( o );
475 buf = i;
476 progress = true;
477 },
478 _ => {},
479 }
480 },
481 _ => {},
482 }
483
484 match peek_commandline( buf ) {
485 nom::IResult::Done( _, _ ) => {
486 match md5_commandline( buf ) {
487 nom::IResult::Done( i, o ) => {
488 cmdline = Some( o );
489 buf = i;
490 progress = true;
491 },
492 _ => {},
493 }
494 },
495 _ => {},
496 }
497
498 match peek_numJoints( buf ) {
499 nom::IResult::Done( _, _ ) => {
500 match md5_numJoints( buf ) {
501 nom::IResult::Done( i, o ) => {
502 debug!( "num joints: {:?}", o );
503 num_joints = Some( o );
504 buf = i;
505 progress = true;
506 },
507 _ => {},
508 }
509 },
510 _ => {},
511 }
512
513 match peek_numMeshes( buf ) {
514 nom::IResult::Done( _, _ ) => {
515 match md5_numMeshes( buf ) {
516 nom::IResult::Done( i, o ) => {
517 debug!( "num meshes: {:?}", o );
518 num_meshes = Some( o );
519 buf = i;
520 progress = true;
521 },
522 _ => {},
523 }
524 },
525 _ => {},
526 }
527
528 match peek_joints( buf ) {
529 nom::IResult::Done( _, _ ) => {
530 match md5mesh_joints_opening( buf ) {
531 nom::IResult::Done( i, o ) => {
532 progress = true;
533 buf = i;
534 },
535 _ => {
536 return Err( "joint opening token not found" )
537 },
538 }
539 match num_joints {
540 None => {
541 return Err( "num joints not specified at point of joint parsing" )
542 },
543 _ => {},
544 }
545
546 let n = num_joints.unwrap();
547 let mut count = 0;
548 while count < n {
549 match peek_and_consume_comments( buf ) {
550 Some(x) => {
551 progress = true;
552 buf = x;
553 continue;
554 },
555 _ => {}
556 }
557 match md5mesh_joint( buf ) {
558 nom::IResult::Done( i, o ) => {
559 buf = i;
560 progress = true;
561 joints.push( o );
562 },
563 _ => {
564 return Err("joint parse unsuccessful")
565 },
566 }
567
568 count += 1;
569 }
570
571 match peek_and_consume_comments( buf ) {
572 Some(x) => {
573 buf = x;
574 },
575 _ => {}
576 }
577
578 match md5mesh_joints_closing( buf ) {
579 nom::IResult::Done( i, o ) => {
580 progress = true;
581 buf = i;
582 },
583 _ => {},
584 }
585 },
586 _ => {},
587 }
588
589 if !progress {
590 break;
591 }
592 }
593
594 match peek_and_consume_comments( buf ) {
595 Some(x) => { buf = x; },
596 _ => {},
597 }
598
599 match num_meshes {
600 None => {
601 return Err( "num meshes not present" );
602 },
603 _ => {},
604 }
605
606 for _ in 0..num_meshes.unwrap() {
607 match parse_mesh( buf ) {
608 Ok( ( b, m ) ) => {
609 buf = b;
610 meshes.push( m );
611 },
612 Err(e) => {
613 return Err(e)
614 }
615 };
616 }
617
618 debug!("num joints: {:?}", joints.len() );
619 debug!("num meshes: {:?}", meshes.len() );
620
621 if let None = version {
622 return Err( "version not present" );
623 }
624 if let None = cmdline {
625 return Err( "cmdline not present" );
626 }
627 match num_joints {
628 Some(x) => {
629 if x != joints.len() as isize {
630 assert_eq!( x, joints.len() as isize );
631 }
632 }
633 _ => {
634 return Err( "num joints not present" );
635 },
636 }
637
638 assert_eq!( num_meshes.unwrap(), meshes.len() as isize );
639
640 Ok( Md5MeshRoot {
641 _md5ver: version.unwrap() as u64,
642 _cmdline: cmdline.unwrap(),
643 _numjoints: num_joints.unwrap() as u64,
644 _nummeshes: num_meshes.unwrap() as u64,
645 _joints: joints,
646 _meshes: meshes,
647 } )
648 }
649}