Changeset 545

Show
Ignore:
Timestamp:
03/12/08 19:40:44 (10 months ago)
Author:
phill
Message:

o So much to batch, so little time...

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/morph-targets/libx42make/include/x42make-modelbuilder.h

    r536 r545  
    119119        class group_split_target; 
    120120        class group_split_context; 
     121        class topological_group_split_context; 
    121122 
    122123        class model_data_builder; 
     
    378379        vertex_weight& operator[] ( size_t index ) { if( index >= max_weights ) throw error(); return _weights[index]; } 
    379380        const vertex_weight& operator[] ( size_t index ) const { if( index >= max_weights ) throw error(); return _weights[index]; } 
     381 
     382        float find_weight( const influence_ptr &influence ) const; 
    380383 
    381384        bool operator == ( const vertex_weights &other ) const; 
     
    470473        std::vector< index > get_list_indices() const; 
    471474 
     475        std::vector< index > get_point_reps( float pos_tol = 1e-5F, float wt_tol = 1e-5F ) const; 
     476 
    472477        X42_DECLARE_ENUM( optimize_type ) 
    473478                match_current, 
     
    510515 
    511516private: 
    512         group() { } 
     517        model_builder                           *owner; 
     518 
     519        explicit group( model_builder *owner ) 
     520                : owner( owner ) 
     521        { 
     522        } 
    513523 
    514524        friend class lod; 
     
    516526        friend class _impl::group_split_target; 
    517527        friend class _impl::group_split_context; 
     528        friend class _impl::topological_group_split_context; 
    518529        friend group_ptr _impl::merge_groups( group_ptr a, group_ptr b ); 
    519530}; 
    520531 
    521532class group_enumerator; 
     533 
     534X42_DECLARE_ENUM( group_split_type ) 
     535        greedy, 
     536        topological, 
     537X42_END_ENUM( group_split_type ); 
     538 
     539struct group_split_limits 
     540{ 
     541        static const size_t default_max_verts = 10000; 
     542        static const size_t default_max_prims = 10000; 
     543        static const size_t default_max_influences = 30; 
     544 
     545        size_t max_verts; 
     546        size_t max_prims; 
     547        size_t max_influences; 
     548 
     549        group_split_limits() 
     550                : max_verts( default_max_verts ), 
     551                max_prims( default_max_prims ), 
     552                max_influences( default_max_influences ) 
     553        { 
     554        } 
     555}; 
    522556 
    523557class lod : public ref_obj 
     
    530564        group_ptr create_group( const std::string &surface_name = std::string(), 
    531565                const std::string &material_name = std::string() ); 
     566 
     567        void split_large_groups( 
     568                const group_split_limits &limits = group_split_limits(), 
     569                group_split_type preferred_split_type = group_split_type::topological );  
     570        void split_by_weight_count( 
     571                float up_merge_limit_factor = 0.5F, 
     572                const group_split_limits &limits = group_split_limits() ); 
     573        void merge_small_groups( 
     574                float merge_limit_factor = 0.5F, 
     575                const group_split_limits &limits = group_split_limits() ); 
    532576 
    533577private: 
     
    630674        void compute_culling_info( uint frame_sample_stride = 1 ); 
    631675 
     676        void split_large_groups( 
     677                const group_split_limits &limits = group_split_limits(), 
     678                group_split_type preferred_split_type = group_split_type::topological );  
     679        void split_groups_by_weight_count( 
     680                float up_merge_limit_factor = 0.5F, 
     681                const group_split_limits &limits = group_split_limits() ); 
     682        void merge_small_groups( 
     683                float merge_limit_factor = 0.5F, 
     684                const group_split_limits &limits = group_split_limits() ); 
     685 
    632686        model to_model( void ) const; 
    633687 
  • branches/morph-targets/libx42make/modelbuilder-batch.cpp

    r539 r545  
    8585        std::vector< group_split_target_ptr > target_groups; 
    8686 
    87         group_split_context( const_group_ptr source ); 
     87        group_split_context( const const_group_ptr &source ); 
    8888        group_split_target_ptr create_target(); 
    8989 
     
    9494 
    9595        void split_by_weight_count(); 
    96         void greedy_split( size_t max_verts, size_t max_prims, size_t max_influences ); 
    97         void topological_split_from_root( size_t max_verts, size_t max_prims, size_t max_influences ); 
    98         void topological_split_from_leaves( size_t max_verts, size_t max_prims, size_t max_influences ); 
    99  
    100         void cost_ordered_merge( size_t max_verts, float up_merge_limit_factor ); 
    101  
    102 private: 
     96        void greedy_split( const group_split_limits &limits ); 
     97 
     98        void cost_ordered_merge( const group_split_limits &limits, float up_merge_limit_factor ); 
     99 
     100protected: 
    103101        group_split_target_ptr internal_merge_groups( group_split_target_ptr a, group_split_target_ptr b ); 
    104102}; 
     
    125123        std::vector< adj_entry > entries; 
    126124        std::vector< size_t > values; 
     125}; 
     126 
     127class bone_topology 
     128{ 
     129public: 
     130        struct entry 
     131        { 
     132                const_bone_ptr                                  bone; 
     133 
     134                const_bone_ptr                                  parent; 
     135                std::vector< const_bone_ptr >   children; 
     136 
     137                const_bone_ptr                                  local_root; 
     138                size_t                                                  distance_to_local_root; 
     139 
     140                const_bone_ptr                                  nearest_leaf; 
     141                const_bone_ptr                                  path_to_nearest_leaf; 
     142                size_t                                                  distance_to_nearest_leaf; 
     143 
     144                bool is_root() const { return !parent; } 
     145                bool is_leaf() const { return !children.size(); } 
     146                size_t neighbor_count() const 
     147                { 
     148                        return (is_root() ? 0 : 1) + children.size(); 
     149                } 
     150        }; 
     151 
     152        std::vector< entry >                    entries; 
     153        std::vector< const_bone_ptr >   roots; 
     154        std::vector< const_bone_ptr >   leaves; 
     155 
     156        bone_topology() 
     157        { 
     158        } 
     159 
     160        void initialize( const std::vector< bone_ptr > &bones ); 
     161        void initialize( const std::vector< const_bone_ptr > &bones ); 
     162 
     163        size_t size() const { return entries.size(); } 
     164        const entry& operator [] ( size_t index ) const { return entries[index]; } 
     165        const entry& operator [] ( const const_bone_ptr &bone ) const { return entries[bone->index()]; } 
     166 
     167private: 
     168        void process_bone( const const_bone_ptr &bone ); 
     169        void process_entries(); 
     170}; 
     171 
     172class topological_group_split_context : public group_split_context 
     173{ 
     174public: 
     175        topological_group_split_context( const const_group_ptr &source ); 
     176 
     177        group_split_target_ptr target_group() const { return target_groups[0]; } 
     178        group_split_target_ptr spillover_group() const { return target_groups[1]; } 
     179 
     180        void set_split_limits( size_t max_verts, size_t max_prims, 
     181                size_t max_influences ); 
     182 
     183        void split_from_root( const group_split_limits &limits ); 
     184        void split_from_leaves( const group_split_limits &limits ); 
     185 
     186protected: 
     187        struct triangle 
     188        { 
     189                size_t  index; 
     190                size_t  inf_cost; 
     191                size_t  vert_cost; 
     192                bool    visited; 
     193 
     194                triangle() 
     195                        : visited( false ) 
     196                { 
     197                } 
     198        }; 
     199 
     200        adjacency adjacency; 
     201        bone_topology topology; 
     202        std::vector< triangle > triangles; 
     203 
     204        void internal_add_sets( std::vector< const_bone_ptr > &to_visit, 
     205                bool favor_root, const group_split_limits &limits ); 
     206        void add_adjacency_set( size_t start_tri, const group_split_limits &limits ); 
     207        void add_triangle( triangle &tri, const group_split_limits &limits ); 
     208        void update_tri_list(); 
     209 
     210private: 
     211        void initialize_for_split(); 
     212        void resolve_point_reps( std::vector< index > &indices ); 
    127213}; 
    128214 
     
    214300group_ptr merge_groups( group_ptr a, group_ptr b ) 
    215301{ 
    216         group_ptr ret( new group() ); 
     302        group_ptr ret( new group( a->owner ) ); 
    217303 
    218304        if( a == b ) 
     
    328414 
    329415/* 
     416        class bone_topology 
     417*/ 
     418 
     419void bone_topology::initialize( const std::vector< bone_ptr > &bones ) 
     420{ 
     421        entries.clear(); 
     422        entries.resize( bones.size() ); 
     423 
     424        roots.clear(); 
     425        leaves.clear(); 
     426 
     427        for( size_t i = 0; i < bones.size(); i++ ) 
     428                process_bone( bones[i] ); 
     429         
     430        process_entries(); 
     431} 
     432 
     433void bone_topology::initialize( const std::vector< const_bone_ptr > &bones ) 
     434{ 
     435        entries.clear(); 
     436        entries.resize( bones.size() ); 
     437 
     438        roots.clear(); 
     439        leaves.clear(); 
     440 
     441        for( size_t i = 0; i < bones.size(); i++ ) 
     442                process_bone( bones[i] ); 
     443         
     444        process_entries(); 
     445} 
     446 
     447void bone_topology::process_bone( const const_bone_ptr &bone ) 
     448{ 
     449        entry &ent = entries[bone->index()]; 
     450 
     451        ent.bone = bone; 
     452        ent.parent = bone->parent(); 
     453 
     454        if( ent.parent ) 
     455        { 
     456                entry &parent_ent = entries[ent.parent->index()]; 
     457 
     458                parent_ent.children.push_back( bone ); 
     459 
     460                ent.local_root = parent_ent.local_root; 
     461                ent.distance_to_local_root = parent_ent.distance_to_local_root + 1; 
     462        } 
     463        else 
     464        { 
     465                ent.local_root = bone; 
     466                ent.distance_to_local_root = 0; 
     467        } 
     468} 
     469 
     470void bone_topology::process_entries() 
     471{ 
     472        for( size_t i = 0; i < entries.size(); i++ ) 
     473        { 
     474                if( entries[i].is_root() ) 
     475                        roots.push_back( entries[i].bone ); 
     476        } 
     477 
     478        for( size_t i = 0; i < entries.size(); i++ ) 
     479        { 
     480                if( entries[i].is_leaf() ) 
     481                        leaves.push_back( entries[i].bone ); 
     482        } 
     483 
     484        for( size_t i = 0; i < entries.size(); i++ ) 
     485        { 
     486                entry &ent = entries[i]; 
     487 
     488                if( ent.is_leaf() ) 
     489                { 
     490                        ent.nearest_leaf = ent.bone; 
     491                        ent.distance_to_nearest_leaf = 0; 
     492                        continue; 
     493                } 
     494 
     495                ent.distance_to_nearest_leaf = size_t_traits::max_val; 
     496 
     497                for( size_t j = 0; j < ent.children.size(); j++ ) 
     498                { 
     499                        entry &child = entries[ent.children[i]->index()]; 
     500 
     501                        if( child.distance_to_nearest_leaf + 1 < ent.distance_to_nearest_leaf ) 
     502                        { 
     503                                ent.distance_to_nearest_leaf = child.distance_to_nearest_leaf + 1; 
     504                                ent.nearest_leaf = child.nearest_leaf; 
     505                                ent.path_to_nearest_leaf = child.bone; 
     506                        } 
     507                } 
     508        } 
     509} 
     510 
     511/* 
    330512        class group_split_target 
    331513*/ 
     
    333515group_split_target::group_split_target( group_split_context *owner ) 
    334516        : owner( owner ), 
    335         source_group( owner->source ), target_group( new group() ), 
     517        source_group( owner->source ), target_group( new group( owner->source->owner ) ), 
    336518        src_to_dst_vert_map( owner->source->geometry.vertex_count(), invalid_index ), 
    337519        prim_count( 0 ), max_infs_per_vert( 0 ) 
     
    342524group_split_target::group_split_target( const group_split_target &src ) 
    343525        : owner( src.owner ), 
    344         source_group( src.source_group ), target_group( new group() ), 
     526        source_group( src.source_group ), target_group( new group( src.source_group->owner ) ), 
    345527        src_to_dst_vert_map( src.src_to_dst_vert_map ), dst_to_src_vert_map( src.dst_to_src_vert_map ),\ 
    346528        influences( src.influences ), prim_count( src.prim_count ), 
     
    451633        inf_cost = 0; 
    452634 
     635        std::vector< influence_ptr > temp_infs( influences ); 
    453636        for( size_t i = 0; i < owner->elems_per_prim; i++ ) 
    454637        { 
     
    461644                vert_cost++; 
    462645                 
    463                 size_t vert_inf_cost; 
    464                 compute_append_vert_cost( src_idx, vert_inf_cost ); 
    465                 inf_cost += vert_inf_cost; 
     646                const vertex_weights &wts = source_group->geometry.weights[src_idx]; 
     647                for( size_t j = 0; j < vertex_weights::max_weights; j++ ) 
     648                { 
     649                        const vertex_weight &w = wts[j]; 
     650 
     651                        if( std::find( temp_infs.begin(), temp_infs.end(), 
     652                                w.influence() ) == temp_infs.end() ) 
     653                        { 
     654                                temp_infs.push_back( w.influence() ); //don't count this again 
     655                                inf_cost++; 
     656                        } 
     657                } 
    466658        } 
    467659} 
     
    492684*/ 
    493685 
    494 group_split_context::group_split_context( const_group_ptr source ) 
     686group_split_context::group_split_context( const const_group_ptr &source ) 
    495687        : source( source ), prim_count( source->geometry.primitive_count() ), 
    496688        elems_per_prim( source->geometry.prim_type.elems_per_prim() ), 
     
    537729} 
    538730 
    539 void group_split_context::greedy_split( size_t max_verts, 
    540         size_t max_prims, size_t max_influences ) 
     731void group_split_context::greedy_split( const group_split_limits &limits ) 
    541732{ 
    542733        target_groups.clear(); 
     
    547738                 
    548739                group_split_target_ptr target; 
    549                 size_t target_vert_cost, target_inf_cost
     740                size_t target_vert_cost = 0, target_inf_cost = 0
    550741 
    551742                for( size_t j = 0; j < target_groups.size(); j++ ) 
     
    554745                         
    555746                        //see if this candidate even has room for the insert 
    556                         if( candidate->prim_count + 1 > max_prims ) 
     747                        if( candidate->prim_count + 1 > limits.max_prims ) 
    557748                                continue; 
    558749 
     
    560751                        candidate->compute_append_prim_cost( i_prim, vert_cost, inf_cost ); 
    561752 
    562                         if( candidate->vertex_count() + vert_cost > max_verts ) 
     753                        if( candidate->vertex_count() + vert_cost > limits.max_verts ) 
    563754                                continue; 
    564                         if( candidate->influences.size() + inf_cost > max_influences ) 
     755                        if( candidate->influences.size() + inf_cost > limits.max_influences ) 
    565756                                continue; 
    566757 
     
    582773} 
    583774 
    584 void group_split_context::topological_split_from_leaves( size_t max_verts, 
    585         size_t max_prims, size_t max_influences ) 
    586 { 
    587         if( elems_per_prim != 3 ) 
    588                 throw error( "Topological split only works on triangles." ); 
    589  
    590  
    591 } 
    592  
    593 void group_split_context::topological_split_from_root( size_t max_verts, 
    594         size_t max_prims, size_t max_influences ) 
    595 { 
    596         if( elems_per_prim != 3 ) 
    597                 throw error( "Topological split only works on triangles." ); 
    598  
    599  
    600 } 
    601  
    602775group_split_target_ptr group_split_context::internal_merge_groups( 
    603776        group_split_target_ptr a, group_split_target_ptr b ) 
     
    615788} 
    616789 
    617 void group_split_context::cost_ordered_merge( size_t max_verts, float up_merge_limit_factor ) 
     790void group_split_context::cost_ordered_merge( const group_split_limits &limits, 
     791        float up_merge_limit_factor ) 
    618792{ 
    619793        std::vector< group_split_target_ptr > src( target_groups ); 
     
    640814                } 
    641815 
    642                 size_t size_sum = ag.vertex_count() + bg.vertex_count(); 
    643  
    644                 if( size_sum < max_verts && 
     816                size_t verts_sum = ag.vertex_count() + bg.vertex_count(); 
     817                size_t prims_sum = ag.primitive_count() + bg.primitive_count(); 
     818                 
     819                size_t infs_sum = ga->influences.size(); 
     820                for( size_t i = 0; i < gb->influences.size(); i++ ) 
     821                { 
     822                        if( std::find( ga->influences.begin(), ga->influences.end(), 
     823                                gb->influences[i] ) == ga->influences.end() ) 
     824                                infs_sum++; 
     825                } 
     826 
     827                if( verts_sum < limits.max_verts && prims_sum < limits.max_prims && infs_sum < limits.max_influences && 
    645828                        ag.vertex_count() < (size_t)(bg.vertex_count() * up_merge_limit_factor) ) 
    646829                { 
     
    669852} 
    670853 
     854/* 
     855        class topological_group_split_context 
     856*/ 
     857 
     858topological_group_split_context::topological_group_split_context( const const_group_ptr &source ) 
     859        : group_split_context( source ) 
     860{ 
     861        if( elems_per_prim != 3 ) 
     862                throw error( "Topological split only works on triangles." ); 
     863 
     864        std::vector< index > adjacency_indices( list_indices ); 
     865        resolve_point_reps( adjacency_indices ); 
     866        adjacency.initialize( adjacency_indices ); 
     867 
     868        triangles.resize( prim_count ); 
     869        for( size_t i = 0; i < triangles.size(); i++ ) 
     870                triangles[i].index = i; 
     871 
     872        topology.initialize( source->owner->bones ); 
     873} 
     874 
     875void topological_group_split_context::initialize_for_split() 
     876{ 
     877        target_groups.clear(); 
     878        create_target(); //create good target 
     879        create_target(); //create spillover target 
     880 
     881        for( size_t i = 0; i < triangles.size(); i++ ) 
     882        { 
     883                triangle &tri = triangles[i]; 
     884 
     885                tri.visited = false; 
     886        } 
     887} 
     888 
     889void topological_group_split_context::resolve_point_reps( std::vector< index > &indices ) 
     890{ 
     891        std::vector< index > point_reps = source->geometry.get_point_reps(); 
     892        for( size_t i = 0; i < indices.size(); i++ ) 
     893                indices[i] = point_reps[indices[i]]; 
     894} 
     895 
     896void topological_group_split_context::split_from_leaves( const group_split_limits &limits ) 
     897{ 
     898        initialize_for_split(); 
     899 
     900        struct leaf_sort 
     901        { 
     902        public: 
     903                leaf_sort( const bone_topology &topology ) 
     904                        : topology( &topology ) { } 
     905 
     906                bool operator () ( const const_bone_ptr &a, const const_bone_ptr &b ) const 
     907                { 
     908                        return (*topology)[a].distance_to_local_root < 
     909                                (*topology)[b].distance_to_local_root; 
     910                } 
     911 
     912        private: 
     913                const bone_topology *topology; 
     914        }; 
     915 
     916        std::vector< const_bone_ptr > to_visit( topology.leaves ); 
     917        std::sort( to_visit.begin(), to_visit.end(), leaf_sort( topology ) ); 
     918 
     919        internal_add_sets( to_visit, false, limits ); 
     920} 
     921 
     922void topological_group_split_context::split_from_root( const group_split_limits &limits ) 
     923{ 
     924        initialize_for_split(); 
     925 
     926        struct root_sort 
     927        { 
     928        public: 
     929                root_sort( const bone_topology &topology ) 
     930                        : topology( &topology ) { } 
     931 
     932                bool operator () ( const const_bone_ptr &a, const const_bone_ptr &b ) const 
     933                { 
     934                        return (*topology)[a].distance_to_local_root > 
     935                                (*topology)[b].distance_to_local_root; 
     936                } 
     937 
     938        private: 
     939                const bone_topology *topology; 
     940        }; 
     941 
     942        std::vector< const_bone_ptr > to_visit( topology.leaves ); 
     943        std::sort( to_visit.begin(), to_visit.end(), root_sort( topology ) ); 
     944 
     945        internal_add_sets( to_visit, false, limits ); 
     946} 
     947 
     948void topological_group_split_context::internal_add_sets( std::vector< const_bone_ptr > &to_visit, 
     949                bool favor_root, const group_split_limits &limits ) 
     950{ 
     951        std::vector< bool > visited_bones( topology.size(), false ); 
     952 
     953        while( to_visit.size() ) 
     954        { 
     955                const_bone_ptr &bone = to_visit.back(); 
     956                to_visit.pop_back(); 
     957 
     958                if( visited_bones[bone->index()] ) 
     959                        continue; 
     960                visited_bones[bone->index()] = true; 
     961 
     962                const bone_topology::entry &bone_ent = topology[bone]; 
     963 
     964                if( favor_root ) 
     965                { 
     966                        to_visit.insert( to_visit.end(), bone_ent.children.begin(), bone_ent.children.end() ); 
     967                        if( !bone_ent.is_root() ) 
     968                                to_visit.push_back( bone_ent.parent ); 
     969                } 
     970                else 
     971                { 
     972                        if( !bone_ent.is_root() ) 
     973                                to_visit.push_back( bone_ent.parent ); 
     974                        to_visit.insert( to_visit.end(), bone_ent.children.begin(), bone_ent.children.end() ); 
     975                } 
     976 
     977                for( size_t i = 0; i < influences.size(); i++ ) 
     978                { 
     979                        const influence_ptr &inf = influences[i]; 
     980 
     981                        if( inf->bone() != bone ) 
     982                                continue; 
     983 
     984                        size_t candidate_tri = size_t_traits::max_val; 
     985                        for( size_t i = 0; i < list_indices.size(); i++ ) 
     986                        { 
     987                                index src_idx = list_indices[i]; 
     988                                if( source->geometry.weights[src_idx].find_weight( inf ) > 0 ) 
     989                                { 
     990                                        candidate_tri = i / 3; 
     991                                        break; 
     992                                } 
     993                        } 
     994 
     995                        if( candidate_tri != size_t_traits::max_val ) 
     996                                add_adjacency_set( candidate_tri, limits ); 
     997                } 
     998        } 
     999 
     1000        for( size_t i = 0; i < triangles.size(); i++ ) 
     1001        { 
     1002                if( !triangles[i].visited ) 
     1003                        add_adjacency_set( i, limits ); 
     1004        } 
     1005} 
     1006 
     1007void topological_group_split_context::update_tri_list() 
     1008{ 
     1009        for( size_t i = 0; i < triangles.size(); i++ ) 
     1010        { 
     1011                triangle &tri = triangles[i]; 
     1012 
     1013                if( tri.visited ) 
     1014                { 
     1015                        //force it to sort to the back 
     1016                        tri.inf_cost = size_t_traits::max_val; 
     1017                        tri.vert_cost = size_t_traits::max_val; 
     1018                        continue; 
     1019                } 
     1020 
     1021                target_group()->compute_append_prim_cost( tri.index, 
     1022                        tri.vert_cost, tri.inf_cost ); 
     1023        } 
     1024} 
     1025 
     1026void topological_group_split_context::add_adjacency_set( size_t start_tri, 
     1027        const group_split_limits &limits ) 
     1028{ 
     1029        struct tri_cmp 
     1030        { 
     1031        public: 
     1032                tri_cmp( topological_group_split_context *owner ) 
     1033                        : owner( owner ) { } 
     1034 
     1035                bool operator () ( size_t ia, size_t ib ) 
     1036                { 
     1037                        const triangle &a = owner->triangles[ia]; 
     1038                        const triangle &b = owner->triangles[ib]; 
     1039 
     1040                        if( a.inf_cost > b.inf_cost ) 
     1041                                return true; 
     1042                        if( a.inf_cost < b.inf_cost ) 
     1043                                return false; 
     1044 
     1045                        return a.vert_cost > b.vert_cost; 
     1046                } 
     1047 
     1048        private: 
     1049                topological_group_split_context *owner; 
     1050        }; 
     1051 
     1052        std::vector< size_t > to_visit, next_visit; 
     1053        to_visit.push_back( start_tri ); 
     1054 
     1055        size_t prev_prims = target_group()->prim_count + 1; 
     1056        while( to_visit.size() && prev_prims != target_group()->prim_count ) 
     1057        { 
     1058                prev_prims = target_group()->prim_count; 
     1059 
     1060                update_tri_list(); 
     1061                std::sort( to_visit.begin(), to_visit.end(), tri_cmp( this ) ); 
     1062 
     1063                size_t i; 
     1064 
     1065                //add any triangles we can sneak in nearly free 
     1066                for( i = 0; i < to_visit.size(); i++ ) 
     1067                { 
     1068                        triangle &tri = triangles[to_visit[i]]; 
     1069 
     1070                        if( tri.visited ) 
     1071                                continue; 
     1072 
     1073                        if( tri.inf_cost != 0 ) 
     1074                                break; 
     1075 
     1076                        tri.visited = true; 
     1077 
     1078                        size_t num_adjacent = adjacency.adj_len( tri.index ); 
     1079                        for( size_t j = 0; j < num_adjacent;  j++ ) 
     1080                        { 
     1081                                size_t adj = adjacency.adj_idx( tri.index, j ); 
     1082                                if( !triangles[adj].visited ) 
     1083                                        next_visit.push_back( adj ); 
     1084                        } 
     1085 
     1086                        add_triangle( tri, limits ); 
     1087                } 
     1088 
     1089                if( i ) 
     1090                { 
     1091                        //have added triangles, merge next_visit with to_visit and continue from there 
     1092                        to_visit.assign( next_visit.begin(), next_visit.end() ); 
     1093                        std::sort( to_visit.begin(), to_visit.end(), tri_cmp( this ) ); 
     1094                        next_visit.clear(); 
     1095                } 
     1096 
     1097                for( i = 0; i < to_visit.size(); i++ ) 
     1098                { 
     1099                        triangle &tri = triangles[to_visit[i]]; 
     1100 
     1101                        if( tri.visited ) 
     1102                                continue; 
     1103 
     1104                        tri.visited = true; 
     1105 
     1106                        size_t num_adjacent = adjacency.adj_len( tri.index ); 
     1107                        for( size_t j = 0; j < num_adjacent;  j++ ) 
     1108                        { 
     1109                                size_t adj = adjacency.adj_idx( tri.index, j ); 
     1110                                if( !triangles[adj].visited ) 
     1111                                        next_visit.push_back( adj ); 
     1112                        } 
     1113 
     1114                        add_triangle( tri, limits ); 
     1115                } 
     1116 
     1117                to_visit.clear(); 
     1118                std::swap( next_visit, to_visit ); 
     1119        } 
     1120} 
     1121 
     1122void topological_group_split_context::add_triangle( triangle &tri, 
     1123        const group_split_limits &limits ) 
     1124{ 
     1125        group_split_target_ptr good_group = target_group(); 
     1126        group_split_target_ptr spill_group = spillover_group(); 
     1127 
     1128        group_split_target_ptr target; 
     1129 
     1130        if( good_group->prim_count + 1 <= limits.max_prims && 
     1131                good_group->vertex_count() + tri.vert_cost <= limits.max_verts && 
     1132                good_group->influences.size() + tri.inf_cost <= limits.max_influences ) 
     1133        { 
     1134                target = good_group; 
     1135        } 
     1136        else 
     1137        { 
     1138                target = spill_group; 
     1139        } 
     1140 
     1141        target->append_prim( tri.index ); 
     1142} 
     1143 
    6711144}; 
     1145 
     1146/* 
     1147        class lod 
     1148*/ 
     1149 
     1150void lod::split_large_groups( 
     1151        const group_split_limits &limits, 
     1152        group_split_type preferred_split_type ) 
     1153{ 
     1154        for( size_t i = 0; i < groups.size(); i++ ) 
     1155        { 
     1156                group_ptr g = groups[i]; 
     1157 
     1158                if( g->geometry.primitive_count() <= limits.max_prims && 
     1159                        g->geometry.vertex_count() <= limits.max_verts && 
     1160                        g->get_influences().size() <= limits.max_influences ) 
     1161                        continue; 
     1162 
     1163                if( preferred_split_type == group_split_type::topological && 
     1164                        g->geometry.prim_type.to_list_type() == primitive_type::triangle_list ) 
     1165                { 
     1166                        group_ptr sg; 
     1167                        std::vector< group_ptr > split_from_leaves, split_from_roots; 
     1168 
     1169                        sg = g; 
     1170                        while( 
     1171                                sg->geometry.primitive_count() > limits.max_prims || 
     1172                                sg->geometry.vertex_count() > limits.max_verts || 
     1173                                sg->get_influences().size() > limits.max_influences ) 
     1174                        { 
     1175                                _impl::topological_group_split_context splitter( sg ); 
     1176                                splitter.split_from_leaves( limits ); 
     1177 
     1178 
     1179                                split_from_leaves.push_back( splitter.target_group()->target_group ); 
     1180                                sg = splitter.spillover_group()->target_group; 
     1181                        } 
     1182 
     1183                        sg = g; 
     1184                        while( 
     1185                                sg->geometry.primitive_count() > limits.max_prims || 
     1186                                sg->geometry.vertex_count() > limits.max_verts || 
     1187                                sg->get_influences().size() > limits.max_influences ) 
     1188                        { 
     1189                                _impl::topological_group_split_context splitter( sg ); 
     1190                                splitter.split_from_root( limits ); 
     1191 
     1192 
     1193                                split_from_roots.push_back( splitter.target_group()->target_group ); 
     1194                                sg = splitter.spillover_group()->target_group; 
     1195                        } 
     1196 
     1197                        std::vector< group_ptr > *best = 0; 
     1198                        if( split_from_roots.size() < split_from_leaves.size() ) 
     1199                                best = &split_from_roots; 
     1200                        else if( split_from_leaves.size() < split_from_roots.size() ) 
     1201                                best = &split_from_leaves; 
     1202 
     1203                        if( !best ) 
     1204                        { 
     1205                                size_t leaf_uploads = 0; 
     1206                                for( size_t i = 0; i < split_from_leaves.size(); i++ ) 
     1207                                { 
     1208                                        leaf_uploads += split_from_leaves[i]->get_influences().size(); 
     1209                                } 
     1210 
     1211                                size_t root_uploads = 0; 
     1212                                for( size_t i = 0; i < split_from_roots.size(); i++ ) 
     1213                                { 
     1214                                        root_uploads += split_from_roots[i]->get_influences().size(); 
     1215                                } 
     1216 
     1217                                if( root_uploads < leaf_uploads ) 
     1218                                        best = &split_from_roots; 
     1219                                else if( leaf_uploads < root_uploads ) 
     1220                                        best = &split_from_leaves; 
     1221                        } 
     1222 
     1223                        if( !best ) 
     1224                                best = &split_from_leaves; 
     1225 
     1226                        if( best->size() == 1 ) 
     1227                                //didn't actually split (for whatever reason...should this be an error?) 
     1228                                continue; 
     1229 
     1230                        groups.erase( groups.begin() + i ); 
     1231                        groups.insert( groups.begin() + i, best->begin(), best->end() ); 
     1232 
     1233                        i += best->size() - 1; //skip over what we just added 
     1234                } 
     1235                else 
     1236                { 
     1237                        _impl::group_split_context splitter( g ); 
     1238                        splitter.greedy_split( limits ); 
     1239 
     1240                        if( splitter.target_groups.size() == 1 ) 
     1241                                //didn't actually split (for whatever reason...should this be an error?) 
     1242                                continue; 
     1243 
     1244                        groups.erase( groups.begin() + i ); 
     1245                        for( size_t j = 0; j < splitter.target_groups.size(); j++ ) 
     1246                        { 
     1247                                groups.insert( groups.begin() + i + j, 
     1248                                        splitter.target_groups[i]->target_group ); 
     1249                        } 
     1250 
     1251                        i += splitter.target_groups.size() - 1; //skip over what we just added 
     1252                } 
     1253        } 
     1254} 
     1255 
     1256void lod::split_by_weight_count( 
     1257        float up_merge_limit_factor, 
     1258        const group_split_limits &limits ) 
     1259{ 
     1260        for( size_t i = groups.size(); i--; ) 
     1261        { 
     1262                _impl::group_split_context splitter( groups[i] ); 
     1263 
     1264                splitter.split_by_weight_count(); 
     1265                splitter.cost_ordered_merge( limits, up_merge_limit_factor ); 
     1266 
     1267                groups.erase( groups.begin() + i ); 
     1268                for( size_t j = splitter.target_groups.size(); j--; ) 
     1269                { 
     1270                        groups.insert( groups.begin() + i, 
     1271                                splitter.target_groups[j]->target_group ); 
     1272                } 
     1273        } 
     1274} 
     1275 
     1276void lod::merge_small_groups( 
     1277        float merge_limit_factor, 
     1278        const group_split_limits &limits ) 
     1279{ 
     1280        for( size_t ia = 0; ia < groups.size(); ia++ ) 
     1281        { 
     1282                group_ptr ga = groups[ia]; 
     1283                 
     1284                if( ga->geometry.primitive_count() >= limits.max_prims && 
    &nbs