source: trunk/src/gfx/texture_atlas.cc @ 533

Last change on this file since 533 was 533, checked in by epyon, 8 years ago
  • getting rid of size_t
  • datatypes now restricted to uint32 size
  • 64-bit compatibility
  • copyright updates where modified
File size: 2.7 KB
RevLine 
[395]1// Copyright (C) 2012-2015 ChaosForge Ltd
[11]2// http://chaosforge.org/
3//
[395]4// This file is part of Nova libraries.
5// For conditions of distribution and use, see copying.txt file in root folder.
[11]6
[89]7#include "nv/gfx/texture_atlas.hh"
[11]8
[319]9#include "nv/core/logging.hh"
[13]10
[11]11using namespace nv;
12
[533]13texture_atlas::texture_atlas( ivec2 size, uint32 depth, uint32 border /*= 1*/ )
[145]14        : image( size, depth ), m_used( 0 ), m_border( border )
[11]15{
[398]16        m_nodes.push_back( ivec3( m_border, m_border, m_size.x - 2 * static_cast<int>( m_border ) ) );
[11]17        fill( 0 );
18}
19
[398]20region texture_atlas::get_region( ivec2 size )
[11]21{
[398]22        region r ( ivec2(0,0), size );
[11]23
[471]24        int best_height = nv::limits::si_max;
[27]25        int best_index  = -1;
[471]26        int best_width  = nv::limits::si_max;
[29]27
[533]28        for( uint32 i=0; i < m_nodes.size(); ++i )
[11]29        {
[27]30                int y = fit( i, size );
[145]31                if ( y >= 0 )
[11]32                {
[398]33                        ivec3 node = m_nodes[ i ];
[11]34                        if ( ( (y + size.y) < best_height ) ||
[27]35                                ( ((y + size.y) == best_height) && (node.z < best_width)) )
[11]36                        {
37                                best_height = y + size.y;
[121]38                                best_index = static_cast<int>( i );
[11]39                                best_width = node.z;
[13]40                                r.pos.x = node.x;
41                                r.pos.y = y;
[11]42                        }
[27]43                }
44        }
[11]45   
[27]46        if ( best_index == -1 )
47        {
[398]48                return region( ivec2( -1, -1 ), ivec2( 0, 0 ) );
[27]49        }
[11]50
[398]51        m_nodes.insert( m_nodes.begin() + best_index, ivec3( r.pos.x, r.pos.y + size.y, size.x ) );
[11]52
[533]53        for( uint32 i = static_cast<uint32>( best_index )+1; i < m_nodes.size(); ++i )
[27]54        {
[398]55                ivec3 node = m_nodes[ i ];
56                ivec3 prev = m_nodes[ i-1 ];
[11]57
[145]58                if ( node.x < prev.x + prev.z )
[27]59                {
60                        int shrink = prev.x + prev.z - node.x;
[11]61                        m_nodes[ i ].x += shrink;
62                        m_nodes[ i ].z -= shrink;
63
[145]64                        if ( m_nodes[ i ].z <= 0 )
[27]65                        {
[121]66                                m_nodes.erase( m_nodes.begin() + static_cast<int>(i) );
[27]67                                --i;
68                        }
69                        else
70                        {
71                                break;
72                        }
73                }
74                else
75                {
76                        break;
77                }
78        }
79        merge();
[142]80        m_used += static_cast<uint32>(size.x * size.y);
[27]81        return r;
[11]82}
83
[533]84int texture_atlas::fit( uint32 index, ivec2 size )
[11]85{
[398]86        ivec3 node = m_nodes[ index ];
[11]87
[146]88        if ( node.x + size.x > m_size.x - static_cast<int>( m_border ) )
[11]89        {
90                return -1;
91        }
92
93        int y     = node.y;
94        int wleft = size.x;
95
[145]96        while ( wleft > 0 )
[11]97        {
[27]98                node = m_nodes[ index ];
[145]99                if ( node.y > y )
[27]100                {
101                        y = node.y;
102                }
[146]103                if ( y + size.y > m_size.y - static_cast<int>( m_border ) )
[27]104                {
[11]105                        return -1;
[27]106                }
[11]107                wleft -= node.z;
[27]108                ++index;
[11]109        }
110        return y;
111}
112
113void texture_atlas::merge()
114{
[533]115        for ( uint32 i=0; i < m_nodes.size()-1; ++i )
[11]116    {
[145]117                if ( m_nodes[ i ].y == m_nodes[ i+1 ].y )
[11]118                {
119                        m_nodes[ i ].z += m_nodes[ i+1 ].z;
[121]120            m_nodes.erase( m_nodes.begin()+static_cast<int>(i+1) );
[11]121                        --i;
122                }
123    }
124}
125
126void texture_atlas::clear()
127{
128        m_nodes.clear();
129        m_used = 0;
[398]130        m_nodes.push_back( ivec3( 1, 1, m_size.x - 2 ) );
[11]131        fill( 0 );
132}
Note: See TracBrowser for help on using the repository browser.