Team Fortress 2 Source Code as on 22/4/2020
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.

141 lines
3.4 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // The copyright to the contents herein is the property of Valve, L.L.C.
  4. // The contents may be used and/or copied only with the written permission of
  5. // Valve, L.L.C., or in accordance with the terms and conditions stipulated in
  6. // the agreement/contract under which the contents have been supplied.
  7. //
  8. // Purpose:
  9. //
  10. // $Workfile: $
  11. // $Date: $
  12. // $NoKeywords: $
  13. //=============================================================================
  14. #include "vrad.h"
  15. #include "imagepacker.h"
  16. bool CImagePacker::Reset( int maxLightmapWidth, int maxLightmapHeight )
  17. {
  18. int i;
  19. Assert( maxLightmapWidth <= MAX_MAX_LIGHTMAP_WIDTH );
  20. m_MaxLightmapWidth = maxLightmapWidth;
  21. m_MaxLightmapHeight = maxLightmapHeight;
  22. m_MaxBlockWidth = maxLightmapWidth + 1;
  23. m_MaxBlockHeight = maxLightmapHeight + 1;
  24. m_AreaUsed = 0;
  25. m_MinimumHeight = -1;
  26. for( i = 0; i < m_MaxLightmapWidth; i++ )
  27. {
  28. m_pLightmapWavefront[i] = -1;
  29. }
  30. return true;
  31. }
  32. inline int CImagePacker::GetMaxYIndex( int firstX, int width )
  33. {
  34. int maxY = -1;
  35. int maxYIndex = 0;
  36. for( int x = firstX; x < firstX + width; ++x )
  37. {
  38. // NOTE: Want the equals here since we'll never be able to fit
  39. // in between the multiple instances of maxY
  40. if( m_pLightmapWavefront[x] >= maxY )
  41. {
  42. maxY = m_pLightmapWavefront[x];
  43. maxYIndex = x;
  44. }
  45. }
  46. return maxYIndex;
  47. }
  48. bool CImagePacker::AddBlock( int width, int height, int *returnX, int *returnY )
  49. {
  50. // If we've already determined that a block this big couldn't fit
  51. // then blow off checking again...
  52. if ( ( width >= m_MaxBlockWidth ) && ( height >= m_MaxBlockHeight ) )
  53. return false;
  54. int bestX = -1;
  55. int maxYIdx;
  56. int outerX = 0;
  57. int outerMinY = m_MaxLightmapHeight;
  58. int lastX = m_MaxLightmapWidth - width;
  59. int lastMaxYVal = -2;
  60. while (outerX <= lastX)
  61. {
  62. // Skip all tiles that have the last Y value, these
  63. // aren't going to change our min Y value
  64. if (m_pLightmapWavefront[outerX] == lastMaxYVal)
  65. {
  66. ++outerX;
  67. continue;
  68. }
  69. maxYIdx = GetMaxYIndex( outerX, width );
  70. lastMaxYVal = m_pLightmapWavefront[maxYIdx];
  71. if (outerMinY > lastMaxYVal)
  72. {
  73. outerMinY = lastMaxYVal;
  74. bestX = outerX;
  75. }
  76. outerX = maxYIdx + 1;
  77. }
  78. if( bestX == -1 )
  79. {
  80. // If we failed to add it, remember the block size that failed
  81. // *only if both dimensions are smaller*!!
  82. // Just because a 1x10 block failed, doesn't mean a 10x1 block will fail
  83. if ( ( width <= m_MaxBlockWidth ) && ( height <= m_MaxBlockHeight ) )
  84. {
  85. m_MaxBlockWidth = width;
  86. m_MaxBlockHeight = height;
  87. }
  88. return false;
  89. }
  90. // Set the return positions for the block.
  91. *returnX = bestX;
  92. *returnY = outerMinY + 1;
  93. // Check if it actually fit height-wise.
  94. // hack
  95. // if( *returnY + height > maxLightmapHeight )
  96. if( *returnY + height >= m_MaxLightmapHeight - 1 )
  97. {
  98. if ( ( width <= m_MaxBlockWidth ) && ( height <= m_MaxBlockHeight ) )
  99. {
  100. m_MaxBlockWidth = width;
  101. m_MaxBlockHeight = height;
  102. }
  103. return false;
  104. }
  105. // It fit!
  106. // Keep up with the smallest possible size for the image so far.
  107. if( *returnY + height > m_MinimumHeight )
  108. m_MinimumHeight = *returnY + height;
  109. // Update the wavefront info.
  110. int x;
  111. for( x = bestX; x < bestX + width; x++ )
  112. {
  113. m_pLightmapWavefront[x] = outerMinY + height;
  114. }
  115. // AddBlockToLightmapImage( *returnX, *returnY, width, height );
  116. m_AreaUsed += width * height;
  117. return true;
  118. }