Consolidates free areas, attempting to improve the 'squareness' of the free regions of the atlas to improve further usage.
| 221 | //Consolidates free areas, attempting to improve the 'squareness' of the free regions of the atlas |
| 222 | //to improve further usage. |
| 223 | void Tr2TextureAtlas::ConsolidateFreeAreas() |
| 224 | { |
| 225 | CCP_STATS_ZONE( __FUNCTION__ ); |
| 226 | |
| 227 | ReleasePendingFreeAreas(); |
| 228 | |
| 229 | if( m_freeAreas.size() < 2 ) |
| 230 | { |
| 231 | return; |
| 232 | } |
| 233 | |
| 234 | struct Squareness |
| 235 | { |
| 236 | static float Metric( const Tr2Rect& a ) |
| 237 | { |
| 238 | const int w = a.right - a.left; |
| 239 | const int h = a.bottom - a.top; |
| 240 | if( w == 0 || h == 0 ) |
| 241 | return 0.f; |
| 242 | const float d = float( w - h ); |
| 243 | return d * d / float( w * h ); |
| 244 | } |
| 245 | }; |
| 246 | |
| 247 | bool restartLoop = true; |
| 248 | |
| 249 | while( restartLoop ) |
| 250 | { |
| 251 | restartLoop = false; |
| 252 | for( AreaList_t::iterator i = m_freeAreas.begin(); i != m_freeAreas.end(); ++i ) |
| 253 | { |
| 254 | const auto& rect_i = ( *i )->rect; |
| 255 | const float square_i = Squareness::Metric( rect_i ); |
| 256 | AreaList_t::iterator j = i; |
| 257 | for( ++j; j != m_freeAreas.end(); ++j ) |
| 258 | { |
| 259 | const auto& rect_j = ( *j )->rect; |
| 260 | const float square_j = Squareness::Metric( rect_j ); |
| 261 | const float squareStart = square_i + square_j; |
| 262 | |
| 263 | |
| 264 | if( rect_i.bottom == rect_i.top || |
| 265 | rect_i.top == rect_j.bottom ) |
| 266 | { |
| 267 | //areas are vertically adjacent |
| 268 | if( rect_i.right == rect_j.right && |
| 269 | rect_i.left == rect_j.left ) |
| 270 | { |
| 271 | //have an exact match, can just merge these two areas |
| 272 | Tr2Rect sum; |
| 273 | sum.left = rect_i.left; |
| 274 | sum.right = rect_i.right; |
| 275 | sum.top = std::min( rect_i.top, rect_j.top ); |
| 276 | sum.bottom = std::max( rect_i.bottom, rect_j.bottom ); |
| 277 | |
| 278 | CCP_DELETE( *j ); |
| 279 | j = m_freeAreas.erase( j ); |
| 280 | ( *i )->rect = sum; |