Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

167 lines
4.0 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=====================================================================================//
  6. #include "imagepacker.h"
  7. // NOTE: This has to be the last file included
  8. #include "tier0/memdbgon.h"
  9. float CImagePacker::GetEfficiency( void )
  10. {
  11. return ( float )m_AreaUsed / ( float )( m_MaxLightmapWidth * CeilPow2( m_MinimumHeight ) );
  12. }
  13. bool CImagePacker::Reset( int nSortId, int maxLightmapWidth, int maxLightmapHeight )
  14. {
  15. int i;
  16. Assert( maxLightmapWidth <= MAX_MAX_LIGHTMAP_WIDTH );
  17. m_MaxLightmapWidth = maxLightmapWidth;
  18. m_MaxLightmapHeight = maxLightmapHeight;
  19. m_MaxBlockWidth = maxLightmapWidth + 1;
  20. m_MaxBlockHeight = maxLightmapHeight + 1;
  21. m_nSortID = nSortId;
  22. m_AreaUsed = 0;
  23. m_MinimumHeight = -1;
  24. for( i = 0; i < m_MaxLightmapWidth; i++ )
  25. {
  26. m_pLightmapWavefront[i] = -1;
  27. }
  28. return true;
  29. }
  30. inline int CImagePacker::GetMaxYIndex( int firstX, int width )
  31. {
  32. int maxY = -1;
  33. int maxYIndex = 0;
  34. for( int x = firstX; x < firstX + width; ++x )
  35. {
  36. // NOTE: Want the equals here since we'll never be able to fit
  37. // in between the multiple instances of maxY
  38. if( m_pLightmapWavefront[x] >= maxY )
  39. {
  40. maxY = m_pLightmapWavefront[x];
  41. maxYIndex = x;
  42. }
  43. }
  44. return maxYIndex;
  45. }
  46. //#define ADD_ONE_TEXEL_BORDER
  47. bool CImagePacker::AddBlock( int width, int height,
  48. int *returnX, int *returnY )
  49. {
  50. #ifdef ADD_ONE_TEXEL_BORDER
  51. width += 2;
  52. height += 2;
  53. width = clamp( width, m_MaxLightmapWidth );
  54. height = clamp( height, m_MaxLightmapHeight );
  55. #endif
  56. // If we've already determined that a block this big couldn't fit
  57. // then blow off checking again...
  58. if ( ( width >= m_MaxBlockWidth ) && ( height >= m_MaxBlockHeight ) )
  59. return false;
  60. int bestX = -1;
  61. int maxYIdx;
  62. int outerX = 0;
  63. int outerMinY = m_MaxLightmapHeight;
  64. int lastX = m_MaxLightmapWidth - width;
  65. int lastMaxYVal = -2;
  66. while (outerX <= lastX)
  67. {
  68. // Skip all tiles that have the last Y value, these
  69. // aren't going to change our min Y value
  70. if (m_pLightmapWavefront[outerX] == lastMaxYVal)
  71. {
  72. ++outerX;
  73. continue;
  74. }
  75. maxYIdx = GetMaxYIndex( outerX, width );
  76. lastMaxYVal = m_pLightmapWavefront[maxYIdx];
  77. if (outerMinY > lastMaxYVal)
  78. {
  79. outerMinY = lastMaxYVal;
  80. bestX = outerX;
  81. // Early out for the first row...
  82. // if (outerMinY == -1)
  83. // break;
  84. }
  85. outerX = maxYIdx + 1;
  86. }
  87. if( bestX == -1 )
  88. {
  89. // If we failed to add it, remember the block size that failed
  90. // *only if both dimensions are smaller*!!
  91. // Just because a 1x10 block failed, doesn't mean a 10x1 block will fail
  92. if ( ( width <= m_MaxBlockWidth ) && ( height <= m_MaxBlockHeight ) )
  93. {
  94. m_MaxBlockWidth = width;
  95. m_MaxBlockHeight = height;
  96. }
  97. return false;
  98. }
  99. // Set the return positions for the block.
  100. *returnX = bestX;
  101. *returnY = outerMinY + 1;
  102. // Check if it actually fit height-wise.
  103. // hack
  104. // if( *returnY + height > maxLightmapHeight )
  105. if( *returnY + height >= m_MaxLightmapHeight - 1 )
  106. {
  107. if ( ( width <= m_MaxBlockWidth ) && ( height <= m_MaxBlockHeight ) )
  108. {
  109. m_MaxBlockWidth = width;
  110. m_MaxBlockHeight = height;
  111. }
  112. return false;
  113. }
  114. // It fit!
  115. // Keep up with the smallest possible size for the image so far.
  116. if( *returnY + height > m_MinimumHeight )
  117. m_MinimumHeight = *returnY + height;
  118. // Update the wavefront info.
  119. int x;
  120. for( x = bestX; x < bestX + width; x++ )
  121. {
  122. m_pLightmapWavefront[x] = outerMinY + height;
  123. }
  124. // AddBlockToLightmapImage( *returnX, *returnY, width, height );
  125. m_AreaUsed += width * height;
  126. #ifdef ADD_ONE_TEXEL_BORDER
  127. *returnX++;
  128. *returnY++;
  129. #endif
  130. return true;
  131. }
  132. void CImagePacker::GetMinimumDimensions( int *pReturnWidth, int *pReturnHeight )
  133. {
  134. *pReturnWidth = CeilPow2( m_MaxLightmapWidth );
  135. *pReturnHeight = CeilPow2( m_MinimumHeight );
  136. // int aspect = *pReturnWidth / *pReturnHeight;
  137. // if (aspect > HardwareConfig()->MaxTextureAspectRatio())
  138. // {
  139. // *pReturnHeight = *pReturnWidth / HardwareConfig()->MaxTextureAspectRatio();
  140. // }
  141. }