- Fixed TAnimMaterial to cache the textures

- Fixed texture size calculation in TMaterial
This commit is contained in:
Andreas Schneider 2009-12-10 14:16:46 +01:00
parent 80412fa867
commit 222abd54fd
1 changed files with 88 additions and 40 deletions

View File

@ -52,10 +52,11 @@ type
FHeight: Integer; FHeight: Integer;
FRealWidth: Integer; FRealWidth: Integer;
FRealHeight: Integer; FRealHeight: Integer;
FTexture: TGLuint;
FGraphic: TMultiImage; FGraphic: TMultiImage;
function GetTexture: GLuint; virtual; procedure CalculateTextureDimensions(ACaps: TGLTextureCaps; ARealWidth,
procedure UpdateTexture; ARealHeight: Integer; out AWidth, AHeight: Integer);
function GenerateTexture(AImage: TBaseImage): TGLuint;
function GetTexture: GLuint; virtual; abstract;
public public
property Width: Integer read FWidth; property Width: Integer read FWidth;
property Height: Integer read FHeight; property Height: Integer read FHeight;
@ -70,6 +71,10 @@ type
TSimpleMaterial = class(TMaterial) TSimpleMaterial = class(TMaterial)
constructor Create(AGraphic: TBaseImage); constructor Create(AGraphic: TBaseImage);
destructor Destroy; override;
protected
FTexture: TGLuint;
function GetTexture: GLuint; override;
end; end;
{ TAnimMaterial } { TAnimMaterial }
@ -77,9 +82,12 @@ type
TAnimMaterial = class(TMaterial) TAnimMaterial = class(TMaterial)
constructor Create(ABaseID: Word; AAnimData: TAnimData; AHue: THue = nil; constructor Create(ABaseID: Word; AAnimData: TAnimData; AHue: THue = nil;
APartialHue: Boolean = False); APartialHue: Boolean = False);
destructor Destroy; override;
protected protected
FActiveFrame: Byte;
FNextChange: DWord; FNextChange: DWord;
FAnimData: TAnimData; FAnimData: TAnimData;
FTextures: array of TGLuint;
function GetTexture: GLuint; override; function GetTexture: GLuint; override;
end; end;
@ -1188,23 +1196,35 @@ end;
destructor TMaterial.Destroy; destructor TMaterial.Destroy;
begin begin
if FTexture <> 0 then glDeleteTextures(1, @FTexture);
FreeAndNil(FGraphic); FreeAndNil(FGraphic);
inherited Destroy; inherited Destroy;
end; end;
function TMaterial.GetTexture: GLuint; procedure TMaterial.CalculateTextureDimensions(ACaps: TGLTextureCaps;
ARealWidth, ARealHeight: Integer; out AWidth, AHeight: Integer);
begin begin
Result := FTexture; if ACaps.NonPowerOfTwo then
begin
AWidth := ARealWidth;
AHeight := ARealHeight;
end else
begin
if IsPow2(ARealWidth) then
AWidth := ARealWidth
else
AWidth := NextPow2(ARealWidth);
if IsPow2(ARealHeight) then
AHeight := ARealHeight
else
AHeight := NextPow2(ARealHeight);
end;
end; end;
procedure TMaterial.UpdateTexture; function TMaterial.GenerateTexture(AImage: TBaseImage): TGLuint;
begin begin
if FTexture <> 0 then glDeleteTextures(1, @FTexture); Result := CreateGLTextureFromImage(AImage.ImageDataPointer^);
glBindTexture(GL_TEXTURE_2D, Result);
FTexture := CreateGLTextureFromImage(FGraphic.ImageDataPointer^, 0, 0, False,
ifUnknown, @FWidth, @FHeight);
glBindTexture(GL_TEXTURE_2D, FTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
@ -1559,12 +1579,29 @@ end;
{ TSimpleMaterial } { TSimpleMaterial }
constructor TSimpleMaterial.Create(AGraphic: TBaseImage); constructor TSimpleMaterial.Create(AGraphic: TBaseImage);
var
caps: TGLTextureCaps;
begin begin
inherited Create; inherited Create;
FGraphic := TMultiImage.CreateFromImage(AGraphic); FRealWidth := AGraphic.Width;
FRealWidth := FGraphic.Width; FRealHeight := AGraphic.Height;
FRealHeight := FGraphic.Height;
UpdateTexture; GetGLTextureCaps(caps);
CalculateTextureDimensions(caps, FRealWidth, FRealHeight, FWidth, FHeight);
FGraphic := TMultiImage.CreateFromParams(FWidth, FHeight, ifA8R8G8B8, 1);
AGraphic.CopyTo(0, 0, FRealWidth, FRealHeight, FGraphic, 0, 0);
FTexture := GenerateTexture(FGraphic);
end;
destructor TSimpleMaterial.Destroy;
begin
if FTexture <> 0 then glDeleteTextures(1, @FTexture);
inherited Destroy;
end;
function TSimpleMaterial.GetTexture: GLuint;
begin
Result := FTexture;
end; end;
{ TAnimMaterial } { TAnimMaterial }
@ -1573,56 +1610,67 @@ constructor TAnimMaterial.Create(ABaseID: Word; AAnimData: TAnimData;
AHue: THue = nil; APartialHue: Boolean = False); AHue: THue = nil; APartialHue: Boolean = False);
var var
i: Integer; i: Integer;
art: TArt; art: array of TArt;
caps: TGLTextureCaps;
begin begin
//Logger.EnterMethod([lcLandscape, lcClient, lcDebug], 'TAnimMaterial.Create');
FAnimData := AAnimData; FAnimData := AAnimData;
FGraphic := TMultiImage.Create;
FRealWidth := 0; FRealWidth := 0;
FRealHeight := 0; FRealHeight := 0;
SetLength(FTextures, AAnimData.FrameCount);
SetLength(art, AAnimData.FrameCount);
for i := 0 to AAnimData.FrameCount - 1 do for i := 0 to AAnimData.FrameCount - 1 do
begin begin
{Logger.Send([lcLandscape, lcClient, lcDebug], 'Processing frame', i); art[i] := ResMan.Art.GetArt(ABaseID + AAnimData.FrameData[i], 0, AHue,
Logger.Send([lcLandscape, lcClient, lcDebug], 'FrameData', AAnimData.FrameData[i]);}
art := ResMan.Art.GetArt(ABaseID + AAnimData.FrameData[i], 0, AHue,
APartialHue); APartialHue);
if (art.Graphic.Width > FRealWidth) or if art[i].Graphic.Width > FRealWidth then
(art.Graphic.Height > FRealHeight) then FRealWidth := art[i].Graphic.Width;
if art[i].Graphic.Height > FRealHeight then
FRealHeight := art[i].Graphic.Height;
end;
GetGLTextureCaps(caps);
CalculateTextureDimensions(caps, FRealWidth, FRealHeight, FWidth, FHeight);
FGraphic := TMultiImage.CreateFromParams(FWidth, FHeight, ifA8R8G8B8,
AAnimData.FrameCount);
for i := 0 to AAnimData.FrameCount - 1 do
begin begin
FRealWidth := art.Graphic.Width; FGraphic.ActiveImage := i;
FRealHeight := art.Graphic.Height; art[i].Graphic.CopyTo(0, 0, art[i].Graphic.Width, art[i].Graphic.Height,
FGraphic, 0, 0);
FTextures[i] := GenerateTexture(FGraphic);
art[i].Free;
end; end;
FGraphic.AddImage(art.Graphic);
art.Free;
end;
FGraphic.DeleteImage(0); //Delete the image that was created during TMultiImage.Create
FGraphic.ActiveImage := 0; FGraphic.ActiveImage := 0;
FActiveFrame := 0;
FNextChange := GetTickCount + AAnimData.FrameStart * 100; FNextChange := GetTickCount + AAnimData.FrameStart * 100;
UpdateTexture; end;
//Logger.ExitMethod([lcLandscape, lcClient, lcDebug], 'TAnimMaterial.Create');
destructor TAnimMaterial.Destroy;
begin
glDeleteTextures(Length(FTextures), @FTextures[0]);
inherited Destroy;
end; end;
function TAnimMaterial.GetTexture: GLuint; function TAnimMaterial.GetTexture: GLuint;
begin begin
if FNextChange <= GetTickCount then if FNextChange <= GetTickCount then
begin begin
FGraphic.ActiveImage := (FGraphic.ActiveImage + 1) mod FAnimData.FrameCount; FActiveFrame := (FActiveFrame + 1) mod FAnimData.FrameCount;
if FGraphic.ActiveImage = 0 then FGraphic.ActiveImage := FActiveFrame;
if FActiveFrame = 0 then
FNextChange := GetTickCount + FAnimData.FrameStart * 100 FNextChange := GetTickCount + FAnimData.FrameStart * 100
else else
FNextChange:= GetTickCount + FAnimData.FrameInterval * 100; FNextChange:= GetTickCount + FAnimData.FrameInterval * 100;
UpdateTexture;
end; end;
Result := FTexture; Result := FTextures[FActiveFrame];
end; end;
end. end.