CommonUtils.pas
上传用户:ctlcnc
上传日期:2021-12-10
资源大小:4933k
文件大小:9k
源码类别:

2D图形编程

开发平台:

Delphi

  1. unit CommonUtils;
  2. //---------------------------------------------------------------------------
  3. interface
  4. //---------------------------------------------------------------------------
  5. uses
  6.  Types, Classes, SysUtils, Math;
  7. //---------------------------------------------------------------------------
  8. // Returns the next power of two of the specified value.
  9. //---------------------------------------------------------------------------
  10. function NextPowerOfTwo(Value: Integer): Integer;
  11. //---------------------------------------------------------------------------
  12. // The routines 'IsPowerOfTwo', 'CeilPowerOfTwo' and 'FloorPowerOfTwo' are
  13. // converted from published code on FlipCode.com by Sebastian Schuberth.
  14. //---------------------------------------------------------------------------
  15. //---------------------------------------------------------------------------
  16. // Determines whether the specified value is a power of two.
  17. //---------------------------------------------------------------------------
  18. function IsPowerOfTwo(Value: Integer): Boolean;
  19. //---------------------------------------------------------------------------
  20. // The least power of two greater than or equal to the specified value.
  21. // Note that for Value = 0 and for Value > 2147483648 the result is 0.
  22. //---------------------------------------------------------------------------
  23. function CeilPowerOfTwo(Value: Integer): Integer;
  24. //---------------------------------------------------------------------------
  25. // The greatest power of two less than or equal to the specified value.
  26. // Note that for Value = 0 the result is 0.
  27. //---------------------------------------------------------------------------
  28. function FloorPowerOfTwo(Value: Integer): Integer;
  29. //---------------------------------------------------------------------------
  30. // Retreives a string representing quanity in kibibytes or mebibytes.
  31. //---------------------------------------------------------------------------
  32. function SizeToStr(Value: Integer): string;
  33. //---------------------------------------------------------------------------
  34. // Retreives the size of the specified file in bytes.
  35. //---------------------------------------------------------------------------
  36. function FileSize(Filename: string): Integer;
  37. //---------------------------------------------------------------------------
  38. // Determines the total size of bytes of the specified file list.
  39. //---------------------------------------------------------------------------
  40. function SizeOfFiles(List: TStrings): Integer;
  41. //---------------------------------------------------------------------------
  42. // Determines how many pixels are wasted if the specific number of patterns
  43. // is placed onto one or several textures with the given size.
  44. //---------------------------------------------------------------------------
  45. function TexWastedSpace(const PatternSize, TextureSize: TPoint;
  46.  PatternCount: Integer; out TextureCount: Integer): Integer;
  47. //---------------------------------------------------------------------------
  48. // Attempts to find the best texture size to match the specified pattern
  49. // amount and dimensions. The heuristics try to optimize for performance
  50. // first, then minimize waste and finally, gives preference to textures
  51. // with less anisotropy (likes square textures).
  52. //---------------------------------------------------------------------------
  53. procedure BestTexSize(const PatternSize: TPoint; PatternCount: Integer;
  54.  out TextureSize: TPoint);
  55. //---------------------------------------------------------------------------
  56. implementation
  57. //---------------------------------------------------------------------------
  58. function NextPowerOfTwo(Value: Integer): Integer;
  59. begin
  60.  Result:= 1;
  61.  asm
  62.   xor ecx, ecx
  63.   bsr ecx, Value
  64.   inc ecx
  65.   shl Result, cl
  66.  end;
  67. end;
  68. //---------------------------------------------------------------------------
  69. function IsPowerOfTwo(Value: Integer): Boolean;
  70. begin
  71.  Result:= (Value >= 1)and((Value and (Value - 1)) = 0);
  72. end;
  73. //---------------------------------------------------------------------------
  74. function CeilPowerOfTwo(Value: Integer): Integer; register;
  75. asm
  76.  mov ecx, eax
  77.  xor eax, eax
  78.  dec ecx
  79.  bsr ecx, ecx
  80.  cmovz ecx, eax
  81.  setnz al
  82.  inc eax
  83.  shl eax, cl
  84. end;
  85. //---------------------------------------------------------------------------
  86. function FloorPowerOfTwo(Value: Integer): Integer;
  87. asm
  88.  xor eax, eax
  89.  bsr ecx, ecx
  90.  setnz al
  91.  shl eax, cl
  92. end;
  93. //---------------------------------------------------------------------------
  94. function SizeToStr(Value: Integer): string;
  95. var
  96.  v: Real;
  97. begin
  98.  if (Value < 1024) then
  99.   begin
  100.    Result:= IntToStr(Value) + ' bytes';
  101.    Exit;
  102.   end;
  103.  v:= Value / 1024.0;
  104.  if (v < 8192) then
  105.   begin
  106.    Result:= FormatFloat('#,#.#', v) + ' KiB';
  107.    Exit;
  108.   end;
  109.  v:= v / 1024.0;
  110.  Result:= FormatFloat('#,#.#', v) + ' MiB';
  111. end;
  112. //---------------------------------------------------------------------------
  113. function FileSize(Filename: string): Integer;
  114. var
  115.  Stream: TFileStream;
  116. begin
  117.  Result:= 0;
  118.  try
  119.   Stream:= TFileStream.Create(Filename, fmOpenRead or fmShareDenyNone);
  120.  except
  121.   Exit;
  122.  end;
  123.  try
  124.   Result:= Stream.Size;
  125.  finally
  126.   Stream.Free();
  127.  end;
  128. end;
  129. //---------------------------------------------------------------------------
  130. function SizeOfFiles(List: TStrings): Integer;
  131. var
  132.  i, Size: Integer;
  133. begin
  134.  Size:= 0;
  135.  for i:= 0 to List.Count - 1 do
  136.   Inc(Size, FileSize(List[i]));
  137.  Result:= Size; 
  138. end;
  139. //---------------------------------------------------------------------------
  140. function TexWastedSpace(const PatternSize, TextureSize: TPoint;
  141.  PatternCount: Integer; out TextureCount: Integer): Integer;
  142. var
  143.  UsedWidth        : Integer;
  144.  UsedHeight       : Integer;
  145.  AvailablePatterns: Integer;
  146.  PatternsInTexture: Integer;
  147.  Wasted           : Integer;
  148.  WastedWidth      : Integer;
  149.  WastedHeight     : Integer;
  150.  WastedCorner     : Integer;
  151.  WastedPatterns   : Integer;
  152. begin
  153.  UsedWidth := (TextureSize.X div PatternSize.X) * PatternSize.X;
  154.  UsedHeight:= (TextureSize.Y div PatternSize.Y) * PatternSize.Y;
  155.  // how many patterns fit in one texture?
  156.  PatternsInTexture:= ((TextureSize.X div PatternSize.X) *
  157.   (TextureSize.Y div PatternSize.Y));
  158.  // how many textures are needed to hold all patterns
  159.  if (PatternsInTexture > 0) then
  160.   TextureCount:= Ceil(PatternCount / PatternsInTexture)
  161.    else TextureCount:= 0;
  162.  // patterns in these textures
  163.  AvailablePatterns:= TextureCount * PatternsInTexture;
  164.  WastedWidth   := (TextureSize.X - UsedWidth) * TextureSize.Y;
  165.  WastedHeight  := (TextureSize.Y - UsedHeight) * TextureSize.X;
  166.  WastedCorner  := (TextureSize.X - UsedWidth) * (TextureSize.Y - UsedHeight);
  167.  WastedPatterns:= (AvailablePatterns - PatternCount) * PatternSize.X * PatternSize.Y;
  168.  // space wasted in ONE texture
  169.  Wasted:= WastedWidth + WastedHeight - WastedCorner;
  170.  // space wasted in ALL textures and missing patterns
  171.  Result:= (Wasted * TextureCount) + WastedPatterns;
  172. end;
  173. //---------------------------------------------------------------------------
  174. procedure BestTexSize(const PatternSize: TPoint; PatternCount: Integer;
  175.  out TextureSize: TPoint);
  176. const
  177.  MaxSize: TPoint = (X: 512; Y: 512);
  178. var
  179.  MinSize: TPoint;
  180.  Wasted : Integer;
  181.  Attempt: TPoint;
  182.  TexCount: Integer;
  183.  NewCount: Integer;
  184.  NewWaste: Integer;
  185.  Delta   : Integer;
  186.  NewDelta: Integer;
  187. begin
  188.  // (1) Minimal texture size.
  189.  MinSize:= PatternSize;
  190.  if (not IsPowerOfTwo(MinSize.X)) then
  191.   MinSize.X:= NextPowerOfTwo(PatternSize.X);
  192.  if (not IsPowerOfTwo(MinSize.Y)) then
  193.   MinSize.Y:= NextPowerOfTwo(PatternSize.Y);
  194.  // (2) If it's not within limits -> just use the minimal size.
  195.  if (MinSize.X > MaxSize.X)or(MinSize.Y > MaxSize.Y) then
  196.   begin
  197.    TextureSize:= MinSize;
  198.    Exit;
  199.   end;
  200.  // (3) Assume we are using maximum texture size.
  201.  Wasted:= TexWastedSpace(PatternSize, MaxSize, PatternCount, TexCount);
  202.  TextureSize:= MaxSize;
  203.  Delta:= Abs(MaxSize.X - MaxSize.Y);
  204.  Attempt.Y:= MaxSize.Y;
  205.  while (Attempt.Y >= MinSize.Y) do
  206.   begin
  207.    Attempt.X:= MaxSize.X;
  208.    while (Attempt.X >= MinSize.X) do
  209.     begin
  210.      NewWaste:= TexWastedSpace(PatternSize, Attempt, PatternCount, NewCount);
  211.      NewDelta:= Abs(Attempt.X - Attempt.Y);
  212.      if (NewCount < TexCount)or((NewCount = TexCount)and(NewWaste < Wasted))or
  213.       ((NewCount = TexCount)and(NewWaste = Wasted)and(NewDelta < Delta)) then
  214.       begin
  215.        TextureSize:= Attempt;
  216.        Wasted  := NewWaste;
  217.        TexCount:= NewCount;
  218.        Delta   := NewDelta;
  219.       end;
  220.      Attempt.X:= Attempt.X div 2;
  221.     end;
  222.    Attempt.Y:= Attempt.Y div 2;
  223.   end;
  224. end;
  225. //---------------------------------------------------------------------------
  226. end.