Ignore:
Timestamp:
05/22/14 01:19:08 (11 years ago)
Author:
epyon
Message:
  • significant simplification of the md5 code
  • proper instancing for both md5 animations and meshes
  • transform_vectors
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/formats/md5_loader.cc

    r240 r241  
    7575                        for ( size_t i = 0; i < m_num_joints; ++i )
    7676                        {
    77                                 sstream >> joint.name >> joint.parent_id;
     77                                int parent_id;
     78                                sstream >> joint.name >> parent_id;
    7879                                discard( sstream, "(" );
    7980                                sstream >> joint.pos.x >> joint.pos.y >> joint.pos.z;
     
    290291        , m_anim_duration( 0 )
    291292        , m_frame_duration( 0 )
    292         , m_anim_time( 0 )
    293293{
    294294
     
    302302bool md5_animation::load_animation( stream& source )
    303303{
    304         m_joint_infos.clear();
    305         m_bounds.clear();
    306         m_base_frames.clear();
    307         m_frames.clear();
    308         m_animated_skeleton.joints.clear();
     304        std::vector<md5_joint_info> joint_infos;
     305        std::vector<transform>      base_frames;
    309306        m_num_frames = 0;
    310307
     
    332329                {
    333330                        sstream >> m_num_joints;
     331                        m_joints.reserve( m_num_joints );
    334332                        next_line( sstream );
    335333                }
     
    352350                                sstream >> joint.name >> joint.parent_id >> joint.flags >> joint.start_index;
    353351                                remove_quotes( joint.name );
    354                                 m_joint_infos.push_back( joint );
     352                                joint_infos.push_back( joint );
     353                                m_joints.push_back( md5_joint( joint.parent_id, m_num_frames ) );
    355354                                next_line( sstream );
    356355                        }
     
    363362                        for ( size_t i = 0; i < m_num_frames; ++i )
    364363                        {
    365                                 md5_bound bound;
     364//                              vec3 min;
     365//                              vec3 max;
     366//                              discard( sstream, "(" );
     367//                              sstream >> min.x >> min.y >> min.z;
     368//                              discard( sstream, ")" );
     369//                              discard( sstream, "(" );
     370//                              sstream >> max.x >> max.y >> max.z;
     371//                              m_bounds.push_back( bound );
     372                                next_line( sstream );
     373                        }
     374
     375                        discard( sstream, "}" );
     376                        next_line( sstream );
     377                }
     378                else if ( command == "baseframe" )
     379                {
     380                        discard( sstream, "{" );
     381                        next_line( sstream );
     382
     383                        for ( size_t i = 0; i < m_num_joints; ++i )
     384                        {
     385                                transform base_frame;
     386                                vec3 pos;
     387                                quat orient;
    366388                                discard( sstream, "(" );
    367                                 sstream >> bound.min.x >> bound.min.y >> bound.min.z;
     389                                sstream >> pos.x >> pos.y >> pos.z;
    368390                                discard( sstream, ")" );
    369391                                discard( sstream, "(" );
    370                                 sstream >> bound.max.x >> bound.max.y >> bound.max.z;
    371 
    372                                 m_bounds.push_back( bound );
    373 
     392                                sstream >> orient.x >> orient.y >> orient.z;
    374393                                next_line( sstream );
    375                         }
    376 
    377                         discard( sstream, "}" );
    378                         next_line( sstream );
    379                 }
    380                 else if ( command == "baseframe" )
    381                 {
    382                         discard( sstream, "{" );
    383                         next_line( sstream );
    384 
    385                         for ( size_t i = 0; i < m_num_joints; ++i )
    386                         {
    387                                 md5_base_frame base_frame;
    388                                 discard( sstream, "(" );
    389                                 sstream >> base_frame.pos.x >> base_frame.pos.y >> base_frame.pos.z;
    390                                 discard( sstream, ")" );
    391                                 discard( sstream, "(" );
    392                                 sstream >> base_frame.orient.x >> base_frame.orient.y >> base_frame.orient.z;
    393                                 next_line( sstream );
    394 
    395                                 m_base_frames.push_back( base_frame );
     394
     395                                base_frames.emplace_back( pos, orient );
    396396                        }
    397397                        discard( sstream, "}" );
     
    400400                else if ( command == "frame" )
    401401                {
    402                         md5_frame_data frame;
    403                         sstream >> frame.frame_id;
     402                        std::vector<float> frame;
     403                        int frame_id;
     404                        sstream >> frame_id;
    404405                        discard( sstream, "{" );
    405406                        next_line( sstream );
    406407
    407                         frame.frame_data.reserve( m_num_animated_components );
     408                        frame.reserve( m_num_animated_components );
    408409                        char buf[50];
    409410                        for ( size_t i = 0; i < m_num_animated_components; ++i )
    410411                        {
    411412                                sstream >> buf;
    412                                 frame.frame_data.push_back((float)atof(buf));
     413                                frame.push_back((float)atof(buf));
    413414                        }
    414415
    415                         m_frames.push_back(frame);
    416 
    417                         build_frame_skeleton( m_skeletons, m_joint_infos, m_base_frames, frame );
     416                        build_frame_skeleton( joint_infos, base_frames, frame );
    418417
    419418                        discard( sstream, "}" );
     
    424423        }
    425424
    426         m_animated_skeleton.joints.assign( m_num_joints, md5_skeleton_joint() );
    427425
    428426        m_frame_duration = 1.0f / (float)m_frame_rate;
    429427        m_anim_duration = ( m_frame_duration * (float)m_num_frames );
    430         m_anim_time = 0.0f;
    431 
    432         assert( m_joint_infos.size() == m_num_joints );
    433         assert( m_bounds.size()      == m_num_frames );
    434         assert( m_base_frames.size() == m_num_joints );
    435         assert( m_frames.size()      == m_num_frames );
    436         assert( m_skeletons.size()   == m_num_frames );
    437428
    438429        return true;
    439430}
    440431
    441 void md5_animation::update( float delta_time )
    442 {
    443         if ( m_num_frames < 1 ) return;
    444 
    445         m_anim_time += delta_time;
    446 
    447         while ( m_anim_time > m_anim_duration ) m_anim_time -= m_anim_duration;
    448         while ( m_anim_time < 0.0f ) m_anim_time += m_anim_duration;
    449 
    450         float frame_num = m_anim_time * (float)m_frame_rate;
     432
     433void nv::md5_animation::update_skeleton( std::vector<transform>& skeleton, float anim_time ) const
     434{
     435        NV_ASSERT( skeleton.size() == m_num_joints, "Incompatible skeleton passed!" );
     436        anim_time = glm::clamp( anim_time, 0.0f, m_anim_duration );
     437        float frame_num = anim_time * (float)m_frame_rate;
    451438        size_t frame0 = (size_t)floorf( frame_num );
    452439        size_t frame1 = (size_t)ceilf( frame_num );
     
    454441        frame1 = frame1 % m_num_frames;
    455442
    456         float interpolate = fmodf( m_anim_time, m_frame_duration ) / m_frame_duration;
    457 
    458         interpolate_skeletons( m_animated_skeleton, m_skeletons[frame0], m_skeletons[frame1], interpolate );
    459 }
    460 
    461 void md5_animation::build_frame_skeleton( md5_frame_skeleton_list& skeletons, const md5_joint_info_list& joint_infos, const md5_base_frame_list& base_frames, const md5_frame_data& frame_data )
    462 {
    463         md5_frame_skeleton skeleton;
    464 
     443        float interpolation = fmodf( anim_time, m_frame_duration ) / m_frame_duration;
     444
     445        for ( size_t i = 0; i < m_num_joints; ++i )
     446        {
     447                const transform_vector& keys = m_joints[i].keys;
     448                skeleton[i] = interpolate( keys.get(frame0), keys.get(frame1), interpolation );
     449        }
     450}
     451
     452void md5_animation::build_frame_skeleton( const std::vector<md5_joint_info>& joint_infos, const std::vector<transform>& base_frames, const std::vector<float>& frame_data )
     453{
     454        size_t index = m_joints[0].keys.size();
    465455        for ( unsigned int i = 0; i < joint_infos.size(); ++i )
    466456        {
     
    468458
    469459                const md5_joint_info& jinfo = joint_infos[i];
    470                 md5_skeleton_joint animated_joint = base_frames[i];
    471 
    472                 animated_joint.parent = jinfo.parent_id;
    473 
    474                 if ( jinfo.flags & 1 )  animated_joint.pos.x    = frame_data.frame_data[ jinfo.start_index + j++ ];
    475                 if ( jinfo.flags & 2 )  animated_joint.pos.y    = frame_data.frame_data[ jinfo.start_index + j++ ];
    476                 if ( jinfo.flags & 4 )  animated_joint.pos.z    = frame_data.frame_data[ jinfo.start_index + j++ ];
    477                 if ( jinfo.flags & 8 )  animated_joint.orient.x = frame_data.frame_data[ jinfo.start_index + j++ ];
    478                 if ( jinfo.flags & 16 ) animated_joint.orient.y = frame_data.frame_data[ jinfo.start_index + j++ ];
    479                 if ( jinfo.flags & 32 ) animated_joint.orient.z = frame_data.frame_data[ jinfo.start_index + j++ ];
    480 
    481                 unit_quat_w( animated_joint.orient );
    482 
    483                 if ( animated_joint.parent >= 0 ) // Has a parent joint
    484                 {
    485                         md5_skeleton_joint& pjoint = skeleton.joints[static_cast< size_t >( animated_joint.parent ) ];
    486                         glm::vec3 rot_pos = pjoint.orient * animated_joint.pos;
    487 
    488                         animated_joint.pos    = pjoint.pos + rot_pos;
    489                         animated_joint.orient = pjoint.orient * animated_joint.orient;
    490 
    491                         animated_joint.orient = glm::normalize( animated_joint.orient );
    492                 }
    493 
    494                 skeleton.joints.push_back( animated_joint );
    495         }
    496 
    497         skeletons.push_back( skeleton );
    498 }
    499 
    500 void md5_animation::interpolate_skeletons( md5_frame_skeleton& final_skeleton, const md5_frame_skeleton& skeleton0, const md5_frame_skeleton& skeleton1, float interpolate )
    501 {
    502         for ( size_t i = 0; i < m_num_joints; ++i )
    503         {
    504                 md5_skeleton_joint& final_joint = final_skeleton.joints[i];
    505                 const md5_skeleton_joint& joint0 = skeleton0.joints[i];
    506                 const md5_skeleton_joint& joint1 = skeleton1.joints[i];
    507 
    508                 final_joint.parent = joint0.parent;
    509 
    510                 final_joint.orient = glm::slerp( joint0.orient, joint1.orient, interpolate );
    511                 final_joint.pos    = glm::mix( joint0.pos, joint1.pos, interpolate );
    512         }
    513 }
    514 
    515 bool md5_loader::check_animation( const md5_animation& animation ) const
    516 {
    517         if ( m_num_joints != animation.get_num_joints() )
    518         {
    519                 return false;
    520         }
    521 
    522         for ( uint32 i = 0; i < m_joints.size(); ++i )
    523         {
    524                 const md5_joint& mjoint = m_joints[i];
    525                 const md5_animation::md5_joint_info& ajoint = animation.get_joint_info( i );
    526 
    527                 if ( mjoint.name != ajoint.name || mjoint.parent_id != ajoint.parent_id )
    528                 {
    529                         return false;
    530                 }
    531         }
    532 
    533         return true;
     460
     461
     462                int parent_id = jinfo.parent_id;
     463
     464                vec3 pos    = base_frames[i].get_position();
     465                quat orient = base_frames[i].get_orientation();
     466                if ( jinfo.flags & 1 )  pos.x    = frame_data[ jinfo.start_index + j++ ];
     467                if ( jinfo.flags & 2 )  pos.y    = frame_data[ jinfo.start_index + j++ ];
     468                if ( jinfo.flags & 4 )  pos.z    = frame_data[ jinfo.start_index + j++ ];
     469                if ( jinfo.flags & 8 )  orient.x = frame_data[ jinfo.start_index + j++ ];
     470                if ( jinfo.flags & 16 ) orient.y = frame_data[ jinfo.start_index + j++ ];
     471                if ( jinfo.flags & 32 ) orient.z = frame_data[ jinfo.start_index + j++ ];
     472                unit_quat_w( orient );
     473
     474                if ( parent_id >= 0 ) // Has a parent joint
     475                {
     476                        const transform_vector& ptv = m_joints[ size_t( parent_id ) ].keys;
     477                        transform ptr;
     478                        if ( ptv.size() > index ) ptr = ptv.get( index );
     479                        glm::vec3 rot_pos = ptr.get_orientation() * pos;
     480
     481                        pos    = ptr.get_position() + rot_pos;
     482                        orient = ptr.get_orientation() * orient;
     483
     484                        orient = glm::normalize( orient );
     485                }
     486
     487                m_joints[i].keys.insert( transform( pos, orient ) );
     488        }
    534489}
    535490
     
    541496}
    542497
    543 void nv::md5_mesh_data::apply( const md5_animation& animation )
    544 {
    545         const md5_animation::md5_frame_skeleton& skeleton = animation.get_skeleton();
    546 
    547         for ( unsigned int i = 0; i < m_vtx_data.size(); ++i )
    548         {
    549                 const md5_vtx_data& vert = m_vtx_data[i];
     498md5_mesh_instance* nv::md5_mesh_data::spawn() const
     499{
     500        return new md5_mesh_instance( this );
     501}
     502
     503nv::md5_loader::~md5_loader()
     504{
     505        for ( auto m : m_meshes ) { if (m) delete m; }
     506}
     507
     508nv::md5_mesh_instance::md5_mesh_instance( const md5_mesh_data* a_data )
     509        : m_data( a_data ), m_size( 0 ), m_indices( 0 ), m_pntdata( nullptr )
     510{
     511        m_size = m_data->m_vtx_data.size();
     512        m_indices = m_data->get_count();
     513        m_pntdata = new md5_vtx_pnt[ m_size ];
     514        std::copy_n( m_data->m_pntdata, m_size, m_pntdata );
     515}
     516
     517void nv::md5_mesh_instance::apply( const std::vector< transform >& skeleton )
     518{
     519        for ( unsigned int i = 0; i < m_size; ++i )
     520        {
     521                const md5_vtx_data& vert = m_data->m_vtx_data[i];
    550522                md5_vtx_pnt& result = m_pntdata[i];
    551523
     
    556528                for ( size_t j = 0; j < vert.weight_count; ++j )
    557529                {
    558                         const md5_weight& weight = m_weights[vert.start_weight + j];
    559                         const md5_animation::md5_skeleton_joint& joint = skeleton.joints[weight.joint_id];
    560 
    561                         glm::vec3 rot_pos = joint.orient * weight.pos;
    562                         result.position += ( joint.pos + rot_pos ) * weight.bias;
    563 
    564                         result.normal  += ( joint.orient * vert.normal  ) * weight.bias;
    565                         result.tangent += ( joint.orient * vert.tangent ) * weight.bias;
    566                 }
    567         }
    568 }
    569 
    570 nv::md5_loader::~md5_loader()
    571 {
    572         for ( auto m : m_meshes ) { if (m) delete m; }
    573 }
     530                        const md5_weight& weight = m_data->m_weights[vert.start_weight + j];
     531                        const transform& joint = skeleton[weight.joint_id];
     532
     533                        glm::vec3 rot_pos = joint.get_orientation() * weight.pos;
     534                        result.position += ( joint.get_position() + rot_pos ) * weight.bias;
     535
     536                        result.normal  += ( joint.get_orientation() * vert.normal  ) * weight.bias;
     537                        result.tangent += ( joint.get_orientation() * vert.tangent ) * weight.bias;
     538                }
     539        }
     540}
Note: See TracChangeset for help on using the changeset viewer.