Changeset 516

Show
Ignore:
Timestamp:
02/22/08 17:30:39 (11 months ago)
Author:
phill
Message:

o Lots of animation stuff.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/morph-targets/libx42make/helpers.h

    r515 r516  
    107107        struct equal 
    108108        { 
    109                 bool operator() ( const T &a, const T &b ) 
     109                bool operator() ( const T &a, const T &b ) const 
    110110                { 
    111111                        return a == b; 
     
    116116} 
    117117 
     118template< typename T, typename Cmp > 
     119void ordered_insert( std::vector< T > &v, 
     120        const T &val, Cmp cmp, bool allow_duplicates = true ) 
     121{ 
     122        std::vector< T >::iterator pos = 
     123                std::upper_bound( v.begin(), v.end(), val, cmp ); 
     124 
     125        if( !allow_duplicates ) 
     126        { 
     127                if( pos > v.begin() ) 
     128                { 
     129                        const T &vp = pos[-1]; 
     130 
     131                        if( !cmp( vp, val ) && !cmp( val, vp ) ) 
     132                                //neither is less, they are "equal" 
     133                                return; 
     134                } 
     135        } 
     136 
     137        v.insert( pos, val ); 
     138} 
     139 
     140template< typename T > 
     141void ordered_insert( std::vector< T > &v, 
     142        const T &val, bool allow_duplicates = true ) 
     143{ 
     144        ordered_insert( v, val, std::less< T >(), allow_duplicates ); 
     145} 
     146 
     147template< typename T > 
     148std::vector< uint > gather_frame_numbers( const std::vector< anim_track_elem< T > > &track ) 
     149{ 
     150        std::vector< uint > ret( track.size() ); 
     151 
     152        for( size_t i = 0; i < track.size(); i++ ) 
     153                ret[i] = track[i].frame; 
     154 
     155        return ret; 
     156} 
     157 
    118158}; 
    119159}; 
  • branches/morph-targets/libx42make/include/x42make-modelbuilder.h

    r515 r516  
    120120        uint                            frame; 
    121121        T                                       value; 
     122 
     123        anim_track_elem() 
     124        { 
     125        } 
     126        anim_track_elem( uint frame, const T &value ) 
     127                : frame( frame ), value( value ) 
     128        { 
     129        } 
    122130}; 
    123131 
     
    175183        void require_world(); 
    176184 
     185        void offset_world( const ::x42::math::affine &offset ); 
     186        void offset_local( const ::x42::math::affine &offset ); 
     187 
     188        void resample_tracks( const std::vector< uint > &frames ); 
     189 
    177190        void clean_tracks(); 
     191 
     192        void make_scale_uniform(); 
    178193 
    179194private: 
     
    209224        animation_tolerances    tight_tolerances; 
    210225 
    211         bool                                    static_bone_hint; 
     226        bool                                    no_remove;                      //set to true to keep optimizations from deleting this bone 
     227        bool                                    static_bone_hint;       //set to true if it's known that this bone does not animate *relative to its parent* 
    212228 
    213229        bone_ptr                                parent() const { return _parent; } 
     
    233249                loose_tolerances( animation_tolerances::inherit_defaults() ), 
    234250                tight_tolerances( animation_tolerances::inherit_defaults() ), 
    235                 static_bone_hint( false ) 
     251                static_bone_hint( false ), no_remove( false ) 
    236252        { 
    237253                anim_tracks.owner = this; 
     
    315331        influence_ptr influence() const { return _influence; } 
    316332        float weight() const { return _weight; } 
     333 
     334        bool is_empty() const { return !_influence || _weight == 0; } 
    317335 
    318336private: 
     
    424442        std::string             surface_name; 
    425443        std::string             material_name; 
    426         geometry                group_geometry; 
     444        geometry                geometry; 
     445 
     446        std::vector< influence_ptr > get_influences() const; 
    427447 
    428448private: 
     
    499519        void begin_skeleton_update(); 
    500520        void end_skeleton_update(); 
     521 
     522        void apply_root_scale( const ::x42::math::vec3 &pos_ofs, const ::x42::math::quat &rot_ofs, 
     523                const ::x42::math::vec3 &inner_scale_ofs, const ::x42::math::vec3 &outer_scale_ofs ); 
    501524 
    502525        //unbinds all vertices from influence 
     
    508531        //unbinds all vertices from old_influence and binds them to new_influence with the same weight, then removes old_influence 
    509532        void rebind_and_remove_influence( const influence_ptr &old_influence, const influence_ptr &new_influence ); 
     533        //rebinds vertices such that only one influence out of each set of equivalent influences is in use 
     534        void rebind_duplicate_influences(); 
    510535 
    511536        void unbind_weak_influences( float min_weight, bool renormalize_weights = true ); 
  • branches/morph-targets/libx42make/modelbuilder-animation.cpp

    r515 r516  
    5757} 
    5858 
     59template< typename T > 
     60T sample_track( const std::vector< anim_track_elem< T > > &track, float frame ) 
     61{ 
     62        if( !track.size() ) 
     63                return T(); 
     64 
     65        if( track[0].frame > frame ) 
     66                return track[0].value; 
     67 
     68        for( uint i = 1; i < track.size(); i++ ) 
     69        { 
     70                if( track[i].frame >= frame ) 
     71                { 
     72                        const anim_track_elem< T > &s = track[i - 1]; 
     73                        const anim_track_elem< T > &e = track[i]; 
     74 
     75                        float t = (float)(frame - s.frame) / (float)(e.frame - s.frame); 
     76                        return interp_elem( s.value, e.value, t ); 
     77                } 
     78        } 
     79 
     80        return track[track.size() - 1].value; 
     81} 
     82 
     83template< typename T > 
     84std::vector< anim_track_elem< T > > resample_track( 
     85        const std::vector< anim_track_elem< T > > &track, 
     86        const std::vector< uint > &frames ) 
     87{ 
     88        std::vector< anim_track_elem< T > > ret( frames.size() ); 
     89 
     90        for( size_t i = 0; i < ret.size(); i++ ) 
     91        { 
     92                ret[i].frame = frames[i]; 
     93                ret[i].value = sample_track( track, (float)frames[i] ); 
     94        } 
     95 
     96        return ret; 
     97} 
     98 
    5999inline float compute_delta( const vec3 &s, const vec3 &e, float t, const vec3 &m ) 
    60100{ 
     
    343383} 
    344384 
     385void animation_tracks::offset_world( const affine &offset ) 
     386{ 
     387        require_world(); 
     388 
     389        for( size_t i = 0; i < world_matrices.size(); i++ ) 
     390                world_matrices[i].value = offset * world_matrices[i].value; 
     391 
     392        local_matrices.clear(); 
     393        position.clear(); 
     394        rotation.clear(); 
     395        scale.clear(); 
     396} 
     397 
     398void animation_tracks::offset_local( const affine &offset ) 
     399{ 
     400        require_local(); 
     401 
     402        for( size_t i = 0; i < local_matrices.size(); i++ ) 
     403                local_matrices[i].value = offset * local_matrices[i].value; 
     404 
     405        world_matrices.clear(); 
     406        position.clear(); 
     407        rotation.clear(); 
     408        scale.clear(); 
     409} 
     410 
     411void animation_tracks::resample_tracks( const std::vector< uint > &frames ) 
     412{ 
     413        require_tracks(); 
     414 
     415        std::vector< vec3_track_elem > new_pos = resample_track( position, frames ); 
     416        std::vector< quat_track_elem > new_rot = resample_track( rotation, frames ); 
     417        std::vector< vec3_track_elem > new_scale = resample_track( scale, frames ); 
     418 
     419        std::swap( position, new_pos ); 
     420        std::swap( rotation, new_rot ); 
     421        std::swap( scale, new_scale ); 
     422} 
     423 
    345424void animation_tracks::clean_tracks() 
    346425{ 
     
    376455} 
    377456 
     457void animation_tracks::make_scale_uniform() 
     458{ 
     459        require_tracks(); 
     460 
     461        for( size_t i = 0; i < scale.size(); i++ ) 
     462        { 
     463                vec3 &v = scale[i].value; 
     464 
     465                float mid = (v.x + v.y + v.z) / 3.0F; 
     466 
     467                v = vec3c( mid );  
     468        } 
     469} 
     470 
    378471/* 
    379472        class model_builder 
     
    401494} 
    402495 
     496void model_builder::apply_root_scale( const vec3 &pos_ofs, const quat &rot_ofs, 
     497        const vec3 &inner_scale_ofs, const vec3 &outer_scale_ofs ) 
     498{ 
     499        if( !_frame_count ) 
     500                throw error( "Frame range not initialized." ); 
     501 
     502        std::vector< uint > frames; 
     503        if( bones.size() ) 
     504        { 
     505                const animation_tracks &anim_trks = bones[0]->anim_tracks; 
     506 
     507                if( anim_trks.world_matrices.size() ) 
     508                        frames = gather_frame_numbers( anim_trks.world_matrices ); 
     509                else if( anim_trks.local_matrices.size() ) 
     510                        frames = gather_frame_numbers( anim_trks.local_matrices ); 
     511                else if( anim_trks.position.size() ) 
     512                        frames = gather_frame_numbers( anim_trks.position ); 
     513        } 
     514 
     515        if( !frames.size() ) 
     516        { 
     517                frames.resize( _frame_count ); 
     518                for( size_t i = 0; i < _frame_count; i++ ) 
     519                { 
     520                        frames[i] = (uint)i; 
     521                } 
     522        } 
     523 
     524        begin_bone_update(); 
     525 
     526        bone_ptr root = create_bone( "root-offset" ); 
     527 
     528        root->_anim_group = 0; 
     529        root->flags = bone_flags::none; 
     530        root->static_bone_hint = true; 
     531 
     532        root->anim_tracks.position.push_back( 
     533                vec3_track_elem( _frame_count - 1, pos_ofs ) ); 
     534        root->anim_tracks.rotation.push_back( 
     535                quat_track_elem( _frame_count - 1, rot_ofs ) ); 
     536        root->anim_tracks.scale.push_back( 
     537                vec3_track_elem( _frame_count - 1, inner_scale_ofs * outer_scale_ofs ) ); 
     538 
     539        root->anim_tracks.resample_tracks( frames ); 
     540 
     541        root->anim_tracks.require_world(); 
     542        const affine &offset = root->anim_tracks.world_matrices[0].value; 
     543 
     544        for( size_t i = 0; i < bones.size(); i++ ) 
     545        { 
     546                bone_ptr b = bones[i]; 
     547 
     548                if( !b->_parent ) 
     549                        b->_parent = root; 
     550 
     551                if( b->anim_tracks.world_matrices.size() ) 
     552                        b->anim_tracks.offset_world( offset ); 
     553        } 
     554 
     555        for( size_t i = 0; i < influences.size(); i++ ) 
     556        { 
     557                influence_ptr inf = influences[i]; 
     558 
     559                if( !inf->_bone ) 
     560                        inf->_bone = root; 
     561        } 
     562 
     563        affine inv_scale = 
     564        { { 
     565                { 1.0F / inner_scale_ofs.x, 0, 0 }, 
     566                { 0, 1.0F / inner_scale_ofs.y, 0 }, 
     567                { 0, 0, 1.0F / inner_scale_ofs.z }, 
     568                { 0, 0, 0 } 
     569        } }; 
     570 
     571        for( size_t i = 0; i < tags.size(); i++ ) 
     572        { 
     573                tag_ptr tag = tags[i]; 
     574 
     575                if( !tag->_bone ) 
     576                        tag->_bone = root; 
     577 
     578                tag->matrix = inv_scale * tag->matrix; 
     579        } 
     580 
     581        root->anim_tracks.require_world(); 
     582 
     583        end_bone_update(); 
     584} 
     585 
    403586}; 
    404587}; 
  • branches/morph-targets/libx42make/modelbuilder-enumerators.cpp

    r513 r516  
    150150        for( ; ; ) 
    151151        { 
    152                 if( (size_t)++cur_idx < cur_grp->group_geometry.vertex_count() ) 
     152                if( (size_t)++cur_idx < cur_grp->geometry.vertex_count() ) 
    153153                        return true; 
    154154 
     
    174174                throw error(); 
    175175 
    176         return cur_grp->group_geometry; 
     176        return cur_grp->geometry; 
    177177} 
    178178 
  • branches/morph-targets/libx42make/modelbuilder-geometry.cpp

    r514 r516  
    372372 
    373373/* 
     374        class group 
     375*/ 
     376 
     377std::vector< influence_ptr > group::get_influences() const 
     378{ 
     379        std::vector< influence_ptr > ret; 
     380 
     381        for( size_t i = 0; i < geometry.weights.size(); i++ ) 
     382        { 
     383                const vertex_weights &weights = geometry.weights[i]; 
     384 
     385                for( size_t j = 0; j < vertex_weights::max_weights; j++ ) 
     386                { 
     387                        const vertex_weight &wt = weights[i]; 
     388 
     389                        if( !wt.is_empty() ) 
     390                                ordered_insert( ret, wt.influence(), false ); 
     391                } 
     392        } 
     393 
     394        struct influence_cmp 
     395        { 
     396                bool operator() ( const influence_ptr &a, const influence_ptr &b ) const 
     397                { 
     398                        return a->index() < b->index(); 
     399                } 
     400        }; 
     401 
     402        std::sort( ret.begin(), ret.end(), influence_cmp() ); 
     403 
     404        return ret; 
     405} 
     406 
     407/* 
    374408        class model_builder 
    375409*/ 
     
    379413        for( group_enumerator iter( *this ); iter.next(); ) 
    380414        { 
    381                 iter.current()->group_geometry.optimize( opt_type ); 
     415                iter.current()->geometry.optimize( opt_type ); 
    382416        } 
    383417} 
  • branches/morph-targets/libx42make/modelbuilder-influences.cpp

    r513 r516  
    150150} 
    151151 
     152void model_builder::rebind_duplicate_influences() 
     153{ 
     154        std::vector< size_t > use_counts = count_influence_uses(); 
     155 
     156        for( size_t i = influences.size(); i--; ) 
     157        { 
     158                if( !use_counts[i] ) 
     159                        //affects nothing, don't care 
     160                        continue; 
     161 
     162                influence_ptr ii = influences[i]; 
     163 
     164                for( size_t j = i; j--; ) 
     165                { 
     166                        if( !use_counts[j] ) 
     167                                //affects nothing, don't care 
     168                                continue; 
     169 
     170                        influence_ptr ij = influences[j]; 
     171 
     172                        if( ii->_bone != ij->_bone ) 
     173                                //not equal, next 
     174                                continue; 
     175 
     176                        if( !equal( ii->matrix, ij->matrix, 1e-2F ) ) 
     177                                //not equal enough, next 
     178                                continue; 
     179 
     180                        /* 
     181                                Favor keeping the bigger one. 
     182 
     183                                ToDo: fix this code so it correctly handles cases 
     184                                where more than two influences are equivalent. 
     185                        */ 
     186 
     187                        if( use_counts[i] > use_counts[j] ) 
     188                        { 
     189                                rebind_influence( ij, ii ); 
     190 
     191                                use_counts[i] += use_counts[j]; 
     192                                use_counts[j] = 0; 
     193                        } 
     194                        else 
     195                        { 
     196                                rebind_influence( ii, ij ); 
     197 
     198                                use_counts[j] += use_counts[i]; 
     199                                use_counts[i] = 0; 
     200 
     201                                break; //stop comparing to this one 
     202                        } 
     203                } 
     204        } 
     205} 
     206 
    152207void model_builder::erase_influence( const influence_ptr &influence ) 
    153208{ 
  • branches/morph-targets/libx42make/modelbuilder-skeleton.cpp

    r513 r516  
    138138        ret->_anim_group = parent ? parent->_anim_group : 0; 
    139139 
     140        sort_bones(); 
     141 
    140142        return ret; 
    141143} 
  • branches/morph-targets/libx42pp/include/x42math-angle.h

    r303 r516  
    2929*/ 
    3030 
     31namespace x42 
     32{ 
     33namespace math 
     34{ 
     35 
    3136struct angle 
    3237{ 
     
    4853inline angle degs( float deg_val ) { angle ret = { deg_val * (3.14159265358979323846F / 180.0F) }; return ret; } 
    4954 
     55}; 
     56}; 
     57 
    5058#endif 
  • branches/morph-targets/x42view.net/Gui/DXPanel.Designer.cs

    r402 r516  
    5151                private void InitializeComponent() 
    5252                { 
    53                         this.helper = new x42view.Guil.MoveHelper(); 
     53                        this.helper = new x42view.Gui.MoveHelper(); 
    5454                        this.SuspendLayout(); 
    5555                        //  
     
    6464                #endregion 
    6565 
    66                 private x42view.Guil.MoveHelper helper; 
     66                private x42view.Gui.MoveHelper helper; 
    6767        } 
    6868} 
  • branches/morph-targets/x42view.net/Gui/MoveHelper.cs

    r402 r516  
    2626using System.Windows.Forms; 
    2727 
    28 namespace x42view.Guil 
     28namespace x42view.Gui 
    2929{ 
    3030 
  • branches/morph-targets/x42view.net/Gui/TimeControl.Designer.cs

    r479 r516  
    4848                        this.tips = new System.Windows.Forms.ToolTip( this.components ); 
    4949                        this.nudCurrTime = new System.Windows.Forms.NumericUpDown(); 
    50                         this.time = new x42view.Guil.TimeSlider(); 
     50                        this.time = new x42view.Gui.TimeSlider(); 
    5151                        this.groupBox1 = new System.Windows.Forms.GroupBox(); 
    5252                        this.nudFrameRate = new System.Windows.Forms.NumericUpDown(); 
     
    223223                #endregion 
    224224 
    225                 private x42view.Guil.TimeSlider time; 
     225                private x42view.Gui.TimeSlider time; 
    226226                private System.Windows.Forms.Timer animTime; 
    227227                private System.Windows.Forms.Button btnPlay; 
  • branches/morph-targets/x42view.net/Gui/TimeSlider.cs

    r483 r516  
    2626using System.Windows.Forms; 
    2727 
    28 namespace x42view.Guil 
     28namespace x42view.Gui 
    2929{ 
    3030