e2rcore/implement/file/
md5comp.rs

1extern crate mazth;
2
3use std::str;
4use std::f32;
5
6use self::mazth::{ mat::Mat3x1, quat::Quat };
7
8use interface::i_md5::compute::*;
9use interface::i_md5::rig::{ PoseCollection, PoseJoints };
10use interface::i_md5::mesh::Md5MeshRoot;
11
12pub fn process( pc: & PoseCollection, m: & Md5MeshRoot, pose_index_start: u64, pose_index_end: u64, interp: f32 ) -> Result< ComputeCollection, & 'static str > {
13    if pose_index_start >= pc._frames.len() as u64 {
14        return Err( "pose_index_start out of bounds." )
15    }
16    if pose_index_end >= pc._frames.len() as u64 {
17        return Err( "pose_index_start out of bounds." )
18    }
19    let interp_clamped = if 0f32 > interp {
20                             0f32
21                         } else { if 1f32 < interp {
22                             1f32
23                         }else{
24                             interp
25                         } };
26    let start = &pc._frames[ pose_index_start as usize ];
27    let end = &pc._frames[ pose_index_end as usize ];
28    interpolate( m, start, end, interp_clamped )
29}
30
31pub fn interpolate( m: & Md5MeshRoot, pose_start: & PoseJoints, pose_end: & PoseJoints, interp: f32 ) -> Result< ComputeCollection, & 'static str > {
32    let mut cc = ComputeCollection {
33        // _meshcomputes: vec![],
34        _bbox_lower: [0f32;3],
35        _bbox_upper: [0f32;3],
36        _batch_vert: vec![],
37        _batch_normal: vec![],
38        _batch_tc: vec![],
39    };
40
41    let mut max_pos = [0., 0., 0.];
42    let mut min_pos = [0., 0., 0.];
43    
44    for i in &m._meshes {
45        let mut mc = MeshCompute {
46            _verts: vec![],
47            // _tris: vec![],
48        };
49        mc._verts.reserve_exact( i._verts.len() );
50            
51        for j in &i._verts {
52            let mut vc = VertCompute {
53                _pos: [0f32;3],
54                _normal: [0f32;3],
55                _tc: j._tex_coords,
56            };
57            for k in 0..j._weight_count {
58                let weight_index = j._weight_start + k;
59
60                let w = &i._weights[ weight_index as usize ];
61                let joint_index = w._joint_index;
62                if joint_index >= pose_start._joints.len() as u64 {
63                    return Err( "joint index out of bounds in pose_start." )
64                }
65                if joint_index >= pose_end._joints.len() as u64 {
66                    return Err( "joint index out of bounds in pose_start." )
67                }
68                let pose_start_rigjoint = & pose_start._joints[ joint_index as usize ];
69                let pose_end_rigjoint = & pose_end._joints[ joint_index as usize ];
70                //get position of the weight after transformation with joint orientation
71                let pos_quat = Quat::<f32>::init_from_vals_raw( w._pos[0], w._pos[1], w._pos[2], 0f32 );
72                let orient_interp = Quat::<f32>::interpolate_slerp( pose_start_rigjoint._orient, pose_end_rigjoint._orient, interp );
73                let orient_inv = orient_interp.inverse().normalize();
74                let pos_transform = pose_start_rigjoint._orient.mul( pos_quat ).mul( orient_inv );
75                //sum comtribution of weights for vertex position and vertex normal
76                vc._pos[0] += ( pose_start_rigjoint._pos[0] + pos_transform._x ) * w._weight_bias;
77                vc._pos[1] += ( pose_start_rigjoint._pos[1] + pos_transform._y ) * w._weight_bias;
78                vc._pos[2] += ( pose_start_rigjoint._pos[2] + pos_transform._z ) * w._weight_bias;
79            }
80
81            for h in 0..3 {
82                if vc._pos[h] > max_pos[h] {
83                    max_pos[h] = vc._pos[h];
84                } else if vc._pos[h] < min_pos[h] {
85                    min_pos[h] = vc._pos[h];
86                }
87            }
88
89            mc._verts.push( vc );
90        }
91        //calculate vertex normal via cross product
92        for j in &i._tris {
93            let v0_index = j._vert_indices[ 0 ];
94            let v1_index = j._vert_indices[ 1 ];
95            let v2_index = j._vert_indices[ 2 ];
96            if v0_index >= mc._verts.len() as u64 {
97                return Err( "vert0 index out of bounds" )
98            }
99            if v1_index >= mc._verts.len() as u64 {
100                return Err( "vert1 index out of bounds" )
101            }
102            if v2_index >= mc._verts.len() as u64 {
103                return Err( "vert2 index out of bounds" )
104            }
105            let v0 = Mat3x1 {
106                _val: mc._verts[ v0_index as usize ]._pos,
107            };
108            let v1 = Mat3x1 {
109                _val: mc._verts[ v1_index as usize ]._pos,
110            };
111            let v2 = Mat3x1 {
112                _val: mc._verts[ v2_index as usize ]._pos,
113            };
114
115            let tc0 = mc._verts[ v2_index as usize ]._tc;
116            let tc1 = mc._verts[ v2_index as usize ]._tc;
117            let tc2 = mc._verts[ v2_index as usize ]._tc;
118            
119            let v01 = v1.minus( &v0 ).unwrap();
120            let v02 = v2.minus( &v0 ).unwrap();
121            let n = v02.cross( &v01 ).expect("cross product for vertex normal invalid")
122                .normalize().expect("normalize for vertex normal invalid");
123
124            //don't need to save these
125            // for k in 0..3 {
126            //     mc._verts[ v0_index as usize ]._normal[ k ] = n._val[ k ];
127            //     mc._verts[ v1_index as usize ]._normal[ k ] = n._val[ k ];
128            //     mc._verts[ v2_index as usize ]._normal[ k ] = n._val[ k ];
129            // }
130            
131            cc._batch_vert.extend_from_slice( &v0._val[..] );
132            cc._batch_vert.extend_from_slice( &v1._val[..] );
133            cc._batch_vert.extend_from_slice( &v2._val[..] );
134            let ns = n._val.into_iter().cycle().cloned().take(9).collect::<Vec<f32>>();
135            cc._batch_normal.extend_from_slice( &ns[..] );
136            // cc._batch_tc.extend_from_slice( &[0., 0., 0., 0., 0., 0.] );
137            cc._batch_tc.extend_from_slice( &[ tc0[0], tc0[1],
138                                               tc1[0], tc1[1],
139                                               tc2[0], tc2[1] ] );
140        }
141        //don't need to save these
142        // mc._tris.extend_from_slice( &i._tris[..] );
143        // cc._meshcomputes.push( mc );
144    }
145    
146    cc._bbox_lower = min_pos;
147    cc._bbox_upper = max_pos;
148    Ok( cc )
149}