- Removed TVector2D

- Added screen buffer (in)validation
- Moved distance calculations to RebuildScreenBuffer
- Added tile drawing to the Render method
- Added DrawQuad precalculation to the post processing of the screen buffer
- Renamed the members of TScreenState
- Changed the DrawQuad to consist of TGLfloats for direct pointer passing
- Fixed the while loop condition in TScreenBuffer.Store
This commit is contained in:
Andreas Schneider 2009-05-18 00:33:59 +02:00
parent 561104a924
commit 0d6c151c5f
4 changed files with 121 additions and 54 deletions

View File

@ -21,7 +21,7 @@
* CDDL HEADER END
*
*
* Portions Copyright 2008 Andreas Schneider
* Portions Copyright 2009 Andreas Schneider
*)
program CentrED;

View File

@ -152,14 +152,12 @@ type
APrioritySolver: Integer);
end;
TScreenState = (tsNormal, tsFiltered, tsGhost);
PDrawQuad = ^TDrawQuad;
TDrawQuad = array[0..3] of TVector2D;
TScreenState = (ssNormal, ssFiltered, ssGhost);
PBlockInfo = ^TBlockInfo;
TBlockInfo = record
ScreenRect: TRect;
DrawQuad: PDrawQuad;
DrawQuad: array[0..3,0..1] of TGLfloat;
Item: TWorldItem;
HighRes: TMaterial;
LowRes: TMaterial;
@ -1042,7 +1040,6 @@ begin
if last <> nil then last^.Next := current^.Next;
if current^.Normals <> nil then Dispose(current^.Normals);
if current^.DrawQuad <> nil then Dispose(current^.DrawQuad);
Dispose(current);
next := nil;
@ -1073,7 +1070,6 @@ begin
current^.Item.Locked := False;
current^.Item.OnDestroy.UnregisterEvent(@OnTileRemoved);
if current^.Normals <> nil then Dispose(current^.Normals);
if current^.DrawQuad <> nil then Dispose(current^.DrawQuad);
Dispose(current);
current := next;
end;
@ -1091,7 +1087,7 @@ begin
current := FFirst;
while (current <> nil) and (Result = nil) do
begin
if (current^.State = tsNormal) and
if (current^.State = ssNormal) and
PtInRect(current^.ScreenRect, AScreenPosition) and
current^.LowRes.HitTest(AScreenPosition.x - current^.ScreenRect.Left,
AScreenPosition.y - current^.ScreenRect.Top) then
@ -1116,11 +1112,10 @@ begin
AItem.Locked := True;
AItem.OnDestroy.RegisterEvent(@OnTileRemoved);
Result^.Item := AItem;
Result^.DrawQuad := nil;
Result^.HighRes := nil;
Result^.LowRes := nil;
Result^.Normals := nil;
Result^.State := tsNormal;
Result^.State := ssNormal;
if (FFirst = nil) or (CompareWorldItems(AItem, FFirst) > 0) then
begin
@ -1131,7 +1126,7 @@ begin
end else
begin
current := FFirst;
while (current^.Next = nil) and
while (current^.Next <> nil) and
(CompareWorldItems(AItem, current^.Next^.Item) > 0) do
begin
current := current^.Next;

View File

@ -279,6 +279,7 @@ type
FLandscape: TLandscape;
FTextureManager: TLandTextureManager;
FScreenBuffer: TScreenBuffer;
FScreenBufferValid: Boolean;
FCurrentTile: TWorldItem;
FSelectedTile: TWorldItem;
FGhostTile: TWorldItem;
@ -294,11 +295,12 @@ type
function CanBeModified(ATile: TWorldItem): Boolean;
function ConfirmAction: Boolean;
procedure GetDrawOffset(ARelativeX, ARelativeY: Integer; out DrawX,
DrawY: Single);
DrawY: Single); inline;
function GetInternalTileID(ATile: TWorldItem): Word;
function GetSelectedRect: TRect;
procedure InitRender;
procedure InitSize;
procedure InvalidateScreenBuffer;
procedure PrepareVirtualLayer(AWidth, AHeight: Word);
procedure ProcessToolState;
procedure ProcessAccessLevel;
@ -721,6 +723,7 @@ begin
FLandscape.OnChange := @OnLandscapeChanged;
FTextureManager := TLandTextureManager.Create;
FScreenBuffer := TScreenBuffer.Create;
FScreenBufferValid := False;
X := 0;
Y := 0;
edX.MaxValue := FLandscape.CellWidth;
@ -1166,17 +1169,7 @@ end;
procedure TfrmMain.oglGameWindowResize(Sender: TObject);
begin
FDrawDistance := Trunc(Sqrt(oglGameWindow.Width * oglGameWindow.Width + oglGamewindow.Height * oglGamewindow.Height) / 44);
{$HINTS off}{$WARNINGS off}
if FX - FDrawDistance < 0 then FLowOffsetX := -FX else FLowOffsetX := -FDrawDistance;
if FY - FDrawDistance < 0 then FLowOffsetY := -FY else FLowOffsetY := -FDrawDistance;
if FX + FDrawDistance >= FLandscape.Width * 8 then FHighOffsetX := FLandscape.Width * 8 - FX - 1 else FHighOffsetX := FDrawDistance;
if FY + FDrawDistance >= FLandscape.Height * 8 then FHighOffsetY := FLandscape.Height * 8 - FY - 1 else FHighOffsetY := FDrawDistance;
{$HINTS on}{$WARNINGS on}
FRangeX := FHighOffsetX - FLowOffsetX;
FRangeY := FHighOffsetY - FLowOffsetY;
InvalidateScreenBuffer;
end;
procedure TfrmMain.pmGrabTileInfoPopup(Sender: TObject);
@ -1546,6 +1539,7 @@ begin
FY := AY;
edY.Value := FY;
dmNetwork.Send(TUpdateClientPosPacket.Create(AX, AY));
InvalidateScreenBuffer;
Repaint;
if frmRadarMap <> nil then frmRadarMap.Repaint;
end;
@ -1651,14 +1645,16 @@ begin
glLoadIdentity;
end;
procedure TfrmMain.InvalidateScreenBuffer;
begin
FScreenBufferValid := False;
end;
procedure TfrmMain.Render;
var
z: ShortInt;
mat: TMaterial;
cell: TMapCell;
drawX, drawY: Single;
staticItem: TStaticItem;
normals: TNormals;
staticTileData: TStaticTileData;
hue: THue;
highlight, singleTarget, multiTarget: Boolean;
@ -1673,6 +1669,7 @@ var
begin
tileRect := GetSelectedRect;
if not FScreenBufferValid then
RebuildScreenBuffer;
{if acFilter.Checked then
@ -1683,9 +1680,56 @@ begin
blockInfo := nil;
while FScreenBuffer.Iterate(blockInfo) do
begin
if blockInfo^.State = ssFiltered then
Continue;
item := blockInfo^.Item;
{GetMapDrawOffset(item.X - FX, item.Y - FY, drawX, drawY);
intensity := 1.0;
SetNormalLights;
glColor4f(intensity, intensity, intensity, 1.0);
if item is TMapCell then
begin
if blockInfo^.HighRes <> nil then
begin
glBindTexture(GL_TEXTURE_2D, blockInfo^.HighRes.Texture);
glBegin(GL_TRIANGLES);
glNormal3fv(@blockInfo^.Normals^[3]);
glTexCoord2f(0, 1); glVertex2fv(@blockInfo^.DrawQuad[3]);
glNormal3fv(@blockInfo^.Normals^[0]);
glTexCoord2f(0, 0); glVertex2fv(@blockInfo^.DrawQuad[0]);
glNormal3fv(@blockInfo^.Normals^[1]);
glTexCoord2f(1, 0); glVertex2fv(@blockInfo^.DrawQuad[1]);
glNormal3fv(@blockInfo^.Normals^[1]);
glTexCoord2f(1, 0); glVertex2fv(@blockInfo^.DrawQuad[1]);
glNormal3fv(@blockInfo^.Normals^[2]);
glTexCoord2f(1, 1); glVertex2fv(@blockInfo^.DrawQuad[2]);
glNormal3fv(@blockInfo^.Normals^[3]);
glTexCoord2f(0, 1); glVertex2fv(@blockInfo^.DrawQuad[3]);
glEnd;
end else
begin
glBindTexture(GL_TEXTURE_2D, blockInfo^.LowRes.Texture);
glBegin(GL_QUADS);
glTexCoord2f(0, 0); glVertex2fv(@blockInfo^.DrawQuad[0]);
glTexCoord2f(1, 0); glVertex2fv(@blockInfo^.DrawQuad[1]);
glTexCoord2f(1, 1); glVertex2fv(@blockInfo^.DrawQuad[2]);
glTexCoord2f(0, 1); glVertex2fv(@blockInfo^.DrawQuad[3]);
glEnd;
end;
end else
begin
glBindTexture(GL_TEXTURE_2D, blockInfo^.LowRes.Texture);
glBegin(GL_QUADS);
glTexCoord2f(0, 0); glVertex2fv(@blockInfo^.DrawQuad[0]);
glTexCoord2f(1, 0); glVertex2fv(@blockInfo^.DrawQuad[1]);
glTexCoord2f(1, 1); glVertex2fv(@blockInfo^.DrawQuad[2]);
glTexCoord2f(0, 1); glVertex2fv(@blockInfo^.DrawQuad[3]);
glEnd;
end;
{GetDrawOffset(item.X - FX, item.Y - FY, drawX, drawY);
singleTarget := (CurrentTile <> nil) and
(item.X = CurrentTile.X) and
@ -2001,11 +2045,22 @@ var
drawX, drawY: Single;
west, south, east: Single;
z: SmallInt;
drawQuad: PDrawQuad;
staticItem: TStaticItem;
hue: THue;
staticTiledata: TStaticTiledata;
begin
FDrawDistance := Trunc(Sqrt(oglGameWindow.Width * oglGameWindow.Width + oglGamewindow.Height * oglGamewindow.Height) / 44);
{$HINTS off}{$WARNINGS off}
if FX - FDrawDistance < 0 then FLowOffsetX := -FX else FLowOffsetX := -FDrawDistance;
if FY - FDrawDistance < 0 then FLowOffsetY := -FY else FLowOffsetY := -FDrawDistance;
if FX + FDrawDistance >= FLandscape.Width * 8 then FHighOffsetX := FLandscape.Width * 8 - FX - 1 else FHighOffsetX := FDrawDistance;
if FY + FDrawDistance >= FLandscape.Height * 8 then FHighOffsetY := FLandscape.Height * 8 - FY - 1 else FHighOffsetY := FDrawDistance;
{$HINTS on}{$WARNINGS on}
FRangeX := FHighOffsetX - FLowOffsetX;
FRangeY := FHighOffsetY - FLowOffsetY;
FLandscape.PrepareBlocks((FX + FLowOffsetX) div 8, (FY + FLowOffsetY) div 8, (FX + FHighOffsetX) div 8 + 1, (FY + FHighOffsetY) div 8 + 1);
PrepareVirtualLayer(FDrawDistance * 2 + 1, FDrawDistance * 2 + 1);
@ -2023,6 +2078,8 @@ begin
begin
item := blockInfo^.Item;
GetDrawOffset(item.X - FX, item.Y - FY, drawX, drawY);
if acFlat.Checked then
z := 0
else
@ -2042,20 +2099,32 @@ begin
end;
end;
blockInfo^.LowRes := FTextureManager.GetArtMaterial(item.TileID);
blockInfo^.ScreenRect := Bounds(Trunc(drawX - 22), Trunc(drawY - z * 4), 44, 44);
if blockInfo^.HighRes <> nil then
begin
New(blockInfo^.Normals);
FLandscape.GetNormals(item.X, item.Y, blockInfo^.Normals^);
New(blockInfo^.DrawQuad);
drawQuad := blockInfo^.DrawQuad;
drawQuad^[0] := Vector(drawX, drawY - z * 4);
drawQuad^[1] := Vector(drawX + 22, drawY + 22 - east * 4);
drawQuad^[2] := Vector(drawX, drawY + 44 - south * 4);
drawQuad^[3] := Vector(drawX - 22, drawY + 22 - west * 4);
blockInfo^.DrawQuad[0][0] := drawX;
blockInfo^.DrawQuad[0][1] := drawY - z * 4;
blockInfo^.DrawQuad[1][0] := drawX + 22;
blockInfo^.DrawQuad[1][1] := drawY + 22 - east * 4;
blockInfo^.DrawQuad[2][0] := drawX;
blockInfo^.DrawQuad[2][1] := drawY + 44 - south * 4;
blockInfo^.DrawQuad[3][0] := drawX - 22;
blockInfo^.DrawQuad[3][1] := drawY + 22 - west * 4;
end else
begin
blockInfo^.DrawQuad[0][0] := drawX - 22;
blockInfo^.DrawQuad[0][1] := drawY - z * 4;
blockInfo^.DrawQuad[1][0] := drawX - 22 + blockInfo^.LowRes.Width;
blockInfo^.DrawQuad[1][1] := drawY - z * 4;
blockInfo^.DrawQuad[2][0] := drawX - 22 + blockInfo^.LowRes.Width;
blockInfo^.DrawQuad[2][1] := drawY + blockInfo^.LowRes.Height - z * 4;
blockInfo^.DrawQuad[3][0] := drawX - 22;
blockInfo^.DrawQuad[3][1] := drawY + blockInfo^.LowRes.Height - z * 4;
end;
blockInfo^.LowRes := FTextureManager.GetArtMaterial(item.TileID);
blockInfo^.ScreenRect := Bounds(Trunc(drawX - 22), Trunc(drawY - z * 4), 44, 44);
end else
begin
staticItem := TStaticItem(item);
@ -2071,8 +2140,22 @@ begin
Trunc(drawY + 44 - blockInfo^.LowRes.RealHeight - z * 4),
blockInfo^.LowRes.RealWidth,
Trunc(blockInfo^.LowRes.RealHeight));
south := blockInfo^.LowRes.RealHeight;
east := blockInfo^.LowRes.RealWidth div 2;
blockInfo^.DrawQuad[0][0] := drawX - east;
blockInfo^.DrawQuad[0][1] := drawY + 44 - south - z * 4;
blockInfo^.DrawQuad[1][0] := drawX - east + blockInfo^.LowRes.Width;
blockInfo^.DrawQuad[1][1] := drawY + 44 - south - z * 4;
blockInfo^.DrawQuad[2][0] := drawX - east + blockInfo^.LowRes.Width;
blockInfo^.DrawQuad[2][1] := drawY + 44 - south + blockInfo^.LowRes.Height - z * 4;
blockInfo^.DrawQuad[3][0] := drawX - east;
blockInfo^.DrawQuad[3][1] := drawY + 44 - south + blockInfo^.LowRes.Height - z * 4;
end;
end;
FScreenBufferValid := True;
end;
procedure TfrmMain.UpdateCurrentTile;
@ -2310,7 +2393,7 @@ begin
end;
procedure TfrmMain.GetDrawOffset(ARelativeX, ARelativeY: Integer; out DrawX,
DrawY: Single);
DrawY: Single); inline;
begin
DrawX := (oglGameWindow.Width div 2) + (ARelativeX - ARelativeY) * 22;
DrawY := (oglGamewindow.Height div 2) + (ARelativeX + ARelativeY) * 22;

View File

@ -31,18 +31,13 @@ uses
Classes;
type
TVector = record
X: Real;
Y: Real;
Z: Real;
end;
TVector2D = record
TVector = packed record
X: Single;
Y: Single;
Z: Single;
end;
function Vector(AX, AY, AZ: Real): TVector;
function Vector(AX, AY: Single): TVector2D;
function Vector(AX, AY, AZ: Single): TVector;
function VectorAdd(AVector1, AVector2: TVector): TVector;
function VectorDot(AVector1, AVector2: TVector): TVector;
function VectorCross(AVector1, AVector2: TVector): TVector;
@ -50,19 +45,13 @@ function VectorNorm(AVector: TVector): TVector;
implementation
function Vector(AX, AY, AZ: Real): TVector;
function Vector(AX, AY, AZ: Single): TVector;
begin
Result.X := AX;
Result.Y := AY;
Result.Z := AZ;
end;
function Vector(AX, AY: Single): TVector2D;
begin
Result.X := AX;
Result.Y := AY;
end;
function VectorAdd(AVector1, AVector2: TVector): TVector;
begin
Result.X := AVector1.X + AVector2.X;