| | 125 | }; |
|---|
| | 126 | |
|---|
| | 127 | class bone_topology |
|---|
| | 128 | { |
|---|
| | 129 | public: |
|---|
| | 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 | |
|---|
| | 167 | private: |
|---|
| | 168 | void process_bone( const const_bone_ptr &bone ); |
|---|
| | 169 | void process_entries(); |
|---|
| | 170 | }; |
|---|
| | 171 | |
|---|
| | 172 | class topological_group_split_context : public group_split_context |
|---|
| | 173 | { |
|---|
| | 174 | public: |
|---|
| | 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 | |
|---|
| | 186 | protected: |
|---|
| | 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 | |
|---|
| | 210 | private: |
|---|
| | 211 | void initialize_for_split(); |
|---|
| | 212 | void resolve_point_reps( std::vector< index > &indices ); |
|---|
| | 416 | class bone_topology |
|---|
| | 417 | */ |
|---|
| | 418 | |
|---|
| | 419 | void 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 | |
|---|
| | 433 | void 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 | |
|---|
| | 447 | void 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 | |
|---|
| | 470 | void 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 | /* |
|---|
| | 854 | /* |
|---|
| | 855 | class topological_group_split_context |
|---|
| | 856 | */ |
|---|
| | 857 | |
|---|
| | 858 | topological_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 | |
|---|
| | 875 | void 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 | |
|---|
| | 889 | void 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 | |
|---|
| | 896 | void 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 | |
|---|
| | 922 | void 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 | |
|---|
| | 948 | void 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 | |
|---|
| | 1007 | void 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 | |
|---|
| | 1026 | void 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 | |
|---|
| | 1122 | void 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 | |
|---|
| | 1145 | |
|---|
| | 1146 | /* |
|---|
| | 1147 | class lod |
|---|
| | 1148 | */ |
|---|
| | 1149 | |
|---|
| | 1150 | void 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 | |
|---|
| | 1256 | void 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 | |
|---|
| | 1276 | void 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 |
|---|