- Added screen buffer pre processing (prepare materials and normals)
- Added 2D Vector to store the points for drawing terrain - Added additional GetNormals function to TLandscape to fill an existing array
This commit is contained in:
parent
fee66eada8
commit
561104a924
|
@ -43,7 +43,7 @@ type
|
||||||
PRadarBlock = ^TRadarBlock;
|
PRadarBlock = ^TRadarBlock;
|
||||||
TRadarBlock = array[0..7, 0..7] of Word;
|
TRadarBlock = array[0..7, 0..7] of Word;
|
||||||
|
|
||||||
{ TMaterial }
|
{ TMaterial } //TODO : add ref counting
|
||||||
|
|
||||||
TMaterial = class(TObject)
|
TMaterial = class(TObject)
|
||||||
constructor Create(AWidth, AHeight: Integer; AGraphic: TSingleImage);
|
constructor Create(AWidth, AHeight: Integer; AGraphic: TSingleImage);
|
||||||
|
@ -145,6 +145,7 @@ type
|
||||||
ANoDraw: Boolean; AStaticsFilter: TStaticFilter);
|
ANoDraw: Boolean; AStaticsFilter: TStaticFilter);
|
||||||
function GetEffectiveAltitude(ATile: TMapCell): ShortInt;
|
function GetEffectiveAltitude(ATile: TMapCell): ShortInt;
|
||||||
function GetLandAlt(AX, AY: Word; ADefault: ShortInt): ShortInt;
|
function GetLandAlt(AX, AY: Word; ADefault: ShortInt): ShortInt;
|
||||||
|
procedure GetNormals(AX, AY: Word; var ANormals: TNormals);
|
||||||
procedure MoveStatic(AStatic: TStaticItem; AX, AY: Word);
|
procedure MoveStatic(AStatic: TStaticItem; AX, AY: Word);
|
||||||
procedure PrepareBlocks(AX1, AY1, AX2, AY2: Word);
|
procedure PrepareBlocks(AX1, AY1, AX2, AY2: Word);
|
||||||
procedure UpdateStaticsPriority(AStaticItem: TStaticItem;
|
procedure UpdateStaticsPriority(AStaticItem: TStaticItem;
|
||||||
|
@ -152,10 +153,13 @@ type
|
||||||
end;
|
end;
|
||||||
|
|
||||||
TScreenState = (tsNormal, tsFiltered, tsGhost);
|
TScreenState = (tsNormal, tsFiltered, tsGhost);
|
||||||
|
PDrawQuad = ^TDrawQuad;
|
||||||
|
TDrawQuad = array[0..3] of TVector2D;
|
||||||
|
|
||||||
PBlockInfo = ^TBlockInfo;
|
PBlockInfo = ^TBlockInfo;
|
||||||
TBlockInfo = record
|
TBlockInfo = record
|
||||||
ScreenRect: TRect;
|
ScreenRect: TRect;
|
||||||
|
DrawQuad: PDrawQuad;
|
||||||
Item: TWorldItem;
|
Item: TWorldItem;
|
||||||
HighRes: TMaterial;
|
HighRes: TMaterial;
|
||||||
LowRes: TMaterial;
|
LowRes: TMaterial;
|
||||||
|
@ -429,85 +433,8 @@ begin
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TLandscape.GetNormals(AX, AY: Word): TNormals;
|
function TLandscape.GetNormals(AX, AY: Word): TNormals;
|
||||||
var
|
|
||||||
cells: array[0..2, 0..2] of TNormals;
|
|
||||||
north, west, south, east: TVector;
|
|
||||||
i, j: Integer;
|
|
||||||
|
|
||||||
function GetPlainNormals(X, Y: SmallInt): TNormals;
|
|
||||||
var
|
|
||||||
cell: TMapCell;
|
|
||||||
north, west, south, east: ShortInt;
|
|
||||||
u, v: TVector;
|
|
||||||
begin
|
begin
|
||||||
cell := GetMapCell(X, Y);
|
GetNormals(AX, AY, Result);
|
||||||
if Assigned(cell) then
|
|
||||||
begin
|
|
||||||
north := cell.Altitude;
|
|
||||||
west := GetLandAlt(cell.X, cell.Y + 1, north);
|
|
||||||
south := GetLandAlt(cell.X + 1, cell.Y + 1, north);
|
|
||||||
east := GetLandAlt(cell.X + 1, cell.Y, north);
|
|
||||||
end else
|
|
||||||
begin
|
|
||||||
north := 0;
|
|
||||||
west := 0;
|
|
||||||
east := 0;
|
|
||||||
south := 0;
|
|
||||||
end;
|
|
||||||
|
|
||||||
if (north = west) and (west = east) and (north = south) then
|
|
||||||
begin
|
|
||||||
Result[0] := Vector(0, 0, 1);
|
|
||||||
Result[1] := Vector(0, 0, 1);
|
|
||||||
Result[2] := Vector(0, 0, 1);
|
|
||||||
Result[3] := Vector(0, 0, 1);
|
|
||||||
end else
|
|
||||||
begin
|
|
||||||
u := Vector(-22, 22, (north - east) * 4);
|
|
||||||
v := Vector(-22, -22, (west - north) * 4);
|
|
||||||
Result[0] := VectorNorm(VectorCross(u, v));
|
|
||||||
|
|
||||||
u := Vector(22, 22, (east - south) * 4);
|
|
||||||
v := Vector(-22, 22, (north - east) * 4);
|
|
||||||
Result[1] := VectorNorm(VectorCross(u, v));
|
|
||||||
|
|
||||||
u := Vector(22, -22, (south - west) * 4);
|
|
||||||
v := Vector(22, 22, (east - south) * 4);
|
|
||||||
Result[2] := VectorNorm(VectorCross(u, v));
|
|
||||||
|
|
||||||
u := Vector(-22, -22, (west - north) * 4);
|
|
||||||
v := Vector(22, -22, (south - west) * 4);
|
|
||||||
Result[3] := VectorNorm(VectorCross(u, v));
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
begin
|
|
||||||
for i := 0 to 2 do
|
|
||||||
for j := 0 to 2 do
|
|
||||||
cells[i, j] := GetPlainNormals(AX - 1 + i, AY - 1 + j);
|
|
||||||
|
|
||||||
north := cells[0, 0][2];
|
|
||||||
west := cells[0, 1][1];
|
|
||||||
east := cells[1, 0][3];
|
|
||||||
south := cells[1, 1][0];
|
|
||||||
Result[0] := VectorNorm(VectorAdd(VectorAdd(VectorAdd(north, west), east), south));
|
|
||||||
|
|
||||||
north := cells[1, 0][2];
|
|
||||||
west := cells[1, 1][1];
|
|
||||||
east := cells[2, 0][3];
|
|
||||||
south := cells[2, 1][0];
|
|
||||||
Result[1] := VectorNorm(VectorAdd(VectorAdd(VectorAdd(north, west), east), south));
|
|
||||||
|
|
||||||
north := cells[1, 1][2];
|
|
||||||
west := cells[1, 2][1];
|
|
||||||
east := cells[2, 1][3];
|
|
||||||
south := cells[2, 2][0];
|
|
||||||
Result[2] := VectorNorm(VectorAdd(VectorAdd(VectorAdd(north, west), east), south));
|
|
||||||
|
|
||||||
north := cells[0, 1][2];
|
|
||||||
west := cells[0, 2][1];
|
|
||||||
east := cells[1, 1][3];
|
|
||||||
south := cells[1, 2][0];
|
|
||||||
Result[3] := VectorNorm(VectorAdd(VectorAdd(VectorAdd(north, west), east), south));
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TLandscape.GetStaticBlock(AX, AY: Word): TSeperatedStaticBlock;
|
function TLandscape.GetStaticBlock(AX, AY: Word): TSeperatedStaticBlock;
|
||||||
|
@ -591,6 +518,7 @@ begin
|
||||||
cell.TileID := ABuffer.ReadWord;
|
cell.TileID := ABuffer.ReadWord;
|
||||||
if Assigned(FOnChange) then FOnChange;
|
if Assigned(FOnChange) then FOnChange;
|
||||||
end;
|
end;
|
||||||
|
//TODO : update surrounding normals
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TLandscape.OnInsertStaticPacket(ABuffer: TEnhancedMemoryStream);
|
procedure TLandscape.OnInsertStaticPacket(ABuffer: TEnhancedMemoryStream);
|
||||||
|
@ -838,6 +766,88 @@ begin
|
||||||
Result := ADefault;
|
Result := ADefault;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TLandscape.GetNormals(AX, AY: Word; var ANormals: TNormals);
|
||||||
|
var
|
||||||
|
cells: array[0..2, 0..2] of TNormals;
|
||||||
|
north, west, south, east: TVector;
|
||||||
|
i, j: Integer;
|
||||||
|
|
||||||
|
function GetPlainNormals(X, Y: SmallInt): TNormals;
|
||||||
|
var
|
||||||
|
cell: TMapCell;
|
||||||
|
north, west, south, east: ShortInt;
|
||||||
|
u, v: TVector;
|
||||||
|
begin
|
||||||
|
cell := GetMapCell(X, Y);
|
||||||
|
if Assigned(cell) then
|
||||||
|
begin
|
||||||
|
north := cell.Altitude;
|
||||||
|
west := GetLandAlt(cell.X, cell.Y + 1, north);
|
||||||
|
south := GetLandAlt(cell.X + 1, cell.Y + 1, north);
|
||||||
|
east := GetLandAlt(cell.X + 1, cell.Y, north);
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
north := 0;
|
||||||
|
west := 0;
|
||||||
|
east := 0;
|
||||||
|
south := 0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if (north = west) and (west = east) and (north = south) then
|
||||||
|
begin
|
||||||
|
ANormals[0] := Vector(0, 0, 1);
|
||||||
|
ANormals[1] := Vector(0, 0, 1);
|
||||||
|
ANormals[2] := Vector(0, 0, 1);
|
||||||
|
ANormals[3] := Vector(0, 0, 1);
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
u := Vector(-22, 22, (north - east) * 4);
|
||||||
|
v := Vector(-22, -22, (west - north) * 4);
|
||||||
|
ANormals[0] := VectorNorm(VectorCross(u, v));
|
||||||
|
|
||||||
|
u := Vector(22, 22, (east - south) * 4);
|
||||||
|
v := Vector(-22, 22, (north - east) * 4);
|
||||||
|
ANormals[1] := VectorNorm(VectorCross(u, v));
|
||||||
|
|
||||||
|
u := Vector(22, -22, (south - west) * 4);
|
||||||
|
v := Vector(22, 22, (east - south) * 4);
|
||||||
|
ANormals[2] := VectorNorm(VectorCross(u, v));
|
||||||
|
|
||||||
|
u := Vector(-22, -22, (west - north) * 4);
|
||||||
|
v := Vector(22, -22, (south - west) * 4);
|
||||||
|
ANormals[3] := VectorNorm(VectorCross(u, v));
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
begin
|
||||||
|
for i := 0 to 2 do
|
||||||
|
for j := 0 to 2 do
|
||||||
|
cells[i, j] := GetPlainNormals(AX - 1 + i, AY - 1 + j);
|
||||||
|
|
||||||
|
north := cells[0, 0][2];
|
||||||
|
west := cells[0, 1][1];
|
||||||
|
east := cells[1, 0][3];
|
||||||
|
south := cells[1, 1][0];
|
||||||
|
ANormals[0] := VectorNorm(VectorAdd(VectorAdd(VectorAdd(north, west), east), south));
|
||||||
|
|
||||||
|
north := cells[1, 0][2];
|
||||||
|
west := cells[1, 1][1];
|
||||||
|
east := cells[2, 0][3];
|
||||||
|
south := cells[2, 1][0];
|
||||||
|
ANormals[1] := VectorNorm(VectorAdd(VectorAdd(VectorAdd(north, west), east), south));
|
||||||
|
|
||||||
|
north := cells[1, 1][2];
|
||||||
|
west := cells[1, 2][1];
|
||||||
|
east := cells[2, 1][3];
|
||||||
|
south := cells[2, 2][0];
|
||||||
|
ANormals[2] := VectorNorm(VectorAdd(VectorAdd(VectorAdd(north, west), east), south));
|
||||||
|
|
||||||
|
north := cells[0, 1][2];
|
||||||
|
west := cells[0, 2][1];
|
||||||
|
east := cells[1, 1][3];
|
||||||
|
south := cells[1, 2][0];
|
||||||
|
ANormals[3] := VectorNorm(VectorAdd(VectorAdd(VectorAdd(north, west), east), south));
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TLandscape.MoveStatic(AStatic: TStaticItem; AX, AY: Word);
|
procedure TLandscape.MoveStatic(AStatic: TStaticItem; AX, AY: Word);
|
||||||
var
|
var
|
||||||
sourceBlock, targetBlock: TSeperatedStaticBlock;
|
sourceBlock, targetBlock: TSeperatedStaticBlock;
|
||||||
|
@ -1031,8 +1041,8 @@ begin
|
||||||
if FLastBlock = current then FLastBlock := last;
|
if FLastBlock = current then FLastBlock := last;
|
||||||
if last <> nil then last^.Next := current^.Next;
|
if last <> nil then last^.Next := current^.Next;
|
||||||
|
|
||||||
if current^.Normals <> nil then
|
if current^.Normals <> nil then Dispose(current^.Normals);
|
||||||
Dispose(current^.Normals);
|
if current^.DrawQuad <> nil then Dispose(current^.DrawQuad);
|
||||||
|
|
||||||
Dispose(current);
|
Dispose(current);
|
||||||
next := nil;
|
next := nil;
|
||||||
|
@ -1062,8 +1072,8 @@ begin
|
||||||
next := current^.Next;
|
next := current^.Next;
|
||||||
current^.Item.Locked := False;
|
current^.Item.Locked := False;
|
||||||
current^.Item.OnDestroy.UnregisterEvent(@OnTileRemoved);
|
current^.Item.OnDestroy.UnregisterEvent(@OnTileRemoved);
|
||||||
if current^.Normals <> nil then
|
if current^.Normals <> nil then Dispose(current^.Normals);
|
||||||
Dispose(current^.Normals);
|
if current^.DrawQuad <> nil then Dispose(current^.DrawQuad);
|
||||||
Dispose(current);
|
Dispose(current);
|
||||||
current := next;
|
current := next;
|
||||||
end;
|
end;
|
||||||
|
@ -1106,6 +1116,7 @@ begin
|
||||||
AItem.Locked := True;
|
AItem.Locked := True;
|
||||||
AItem.OnDestroy.RegisterEvent(@OnTileRemoved);
|
AItem.OnDestroy.RegisterEvent(@OnTileRemoved);
|
||||||
Result^.Item := AItem;
|
Result^.Item := AItem;
|
||||||
|
Result^.DrawQuad := nil;
|
||||||
Result^.HighRes := nil;
|
Result^.HighRes := nil;
|
||||||
Result^.LowRes := nil;
|
Result^.LowRes := nil;
|
||||||
Result^.Normals := nil;
|
Result^.Normals := nil;
|
||||||
|
|
|
@ -34,7 +34,7 @@ uses
|
||||||
ComCtrls, OpenGLContext, GL, GLU, UGameResources, ULandscape, ExtCtrls,
|
ComCtrls, OpenGLContext, GL, GLU, UGameResources, ULandscape, ExtCtrls,
|
||||||
StdCtrls, Spin, UEnums, VirtualTrees, Buttons, UMulBlock, UWorldItem, math,
|
StdCtrls, Spin, UEnums, VirtualTrees, Buttons, UMulBlock, UWorldItem, math,
|
||||||
LCLIntf, UOverlayUI, UStatics, UEnhancedMemoryStream, ActnList,
|
LCLIntf, UOverlayUI, UStatics, UEnhancedMemoryStream, ActnList,
|
||||||
ImagingClasses, dateutils, UPlatformTypes;
|
ImagingClasses, dateutils, UPlatformTypes, UVector;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
||||||
|
@ -1656,7 +1656,6 @@ var
|
||||||
z: ShortInt;
|
z: ShortInt;
|
||||||
mat: TMaterial;
|
mat: TMaterial;
|
||||||
cell: TMapCell;
|
cell: TMapCell;
|
||||||
west, south, east: Single;
|
|
||||||
drawX, drawY: Single;
|
drawX, drawY: Single;
|
||||||
staticItem: TStaticItem;
|
staticItem: TStaticItem;
|
||||||
normals: TNormals;
|
normals: TNormals;
|
||||||
|
@ -1996,6 +1995,16 @@ begin
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TfrmMain.RebuildScreenBuffer;
|
procedure TfrmMain.RebuildScreenBuffer;
|
||||||
|
var
|
||||||
|
blockInfo: PBlockInfo;
|
||||||
|
item: TWorldItem;
|
||||||
|
drawX, drawY: Single;
|
||||||
|
west, south, east: Single;
|
||||||
|
z: SmallInt;
|
||||||
|
drawQuad: PDrawQuad;
|
||||||
|
staticItem: TStaticItem;
|
||||||
|
hue: THue;
|
||||||
|
staticTiledata: TStaticTiledata;
|
||||||
begin
|
begin
|
||||||
FLandscape.PrepareBlocks((FX + FLowOffsetX) div 8, (FY + FLowOffsetY) div 8, (FX + FHighOffsetX) div 8 + 1, (FY + FHighOffsetY) div 8 + 1);
|
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);
|
PrepareVirtualLayer(FDrawDistance * 2 + 1, FDrawDistance * 2 + 1);
|
||||||
|
@ -2007,6 +2016,63 @@ begin
|
||||||
frmBoundaries.tbMaxZ.Position, tbTerrain.Down, tbStatics.Down,
|
frmBoundaries.tbMaxZ.Position, tbTerrain.Down, tbStatics.Down,
|
||||||
acNoDraw.Checked, nil); //TODO : statics filter
|
acNoDraw.Checked, nil); //TODO : statics filter
|
||||||
//TODO : ghost tile
|
//TODO : ghost tile
|
||||||
|
|
||||||
|
//Pre-process the buffer - add normals to map tiles and materials where possible
|
||||||
|
blockInfo := nil;
|
||||||
|
while FScreenBuffer.Iterate(blockInfo) do
|
||||||
|
begin
|
||||||
|
item := blockInfo^.Item;
|
||||||
|
|
||||||
|
if acFlat.Checked then
|
||||||
|
z := 0
|
||||||
|
else
|
||||||
|
z := item.Z;
|
||||||
|
|
||||||
|
if item is TMapCell then
|
||||||
|
begin
|
||||||
|
if not acFlat.Checked then
|
||||||
|
begin
|
||||||
|
west := FLandscape.GetLandAlt(item.X, item.Y + 1, z);
|
||||||
|
south := FLandscape.GetLandAlt(item.X + 1, item.Y + 1, z);
|
||||||
|
east := FLandscape.GetLandAlt(item.X + 1, item.Y, z);
|
||||||
|
|
||||||
|
if (west <> z) or (south <> z) or (east <> z) then
|
||||||
|
begin
|
||||||
|
blockInfo^.HighRes := FTextureManager.GetTexMaterial(item.TileID);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
|
||||||
|
staticTiledata := ResMan.Tiledata.StaticTiles[staticItem.TileID];
|
||||||
|
if staticItem.Hue > 0 then
|
||||||
|
hue := ResMan.Hue.Hues[staticItem.Hue - 1]
|
||||||
|
else
|
||||||
|
hue := nil;
|
||||||
|
|
||||||
|
blockInfo^.LowRes := FTextureManager.GetArtMaterial($4000 + staticItem.TileID, hue, (staticTileData.Flags and tdfPartialHue) = tdfPartialHue);
|
||||||
|
blockInfo^.ScreenRect := Bounds(Trunc(drawX - blockInfo^.LowRes.RealWidth div 2),
|
||||||
|
Trunc(drawY + 44 - blockInfo^.LowRes.RealHeight - z * 4),
|
||||||
|
blockInfo^.LowRes.RealWidth,
|
||||||
|
Trunc(blockInfo^.LowRes.RealHeight));
|
||||||
|
end;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TfrmMain.UpdateCurrentTile;
|
procedure TfrmMain.UpdateCurrentTile;
|
||||||
|
|
13
UVector.pas
13
UVector.pas
|
@ -21,7 +21,7 @@
|
||||||
* CDDL HEADER END
|
* CDDL HEADER END
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* Portions Copyright 2007 Andreas Schneider
|
* Portions Copyright 2009 Andreas Schneider
|
||||||
*)
|
*)
|
||||||
unit UVector;
|
unit UVector;
|
||||||
|
|
||||||
|
@ -36,8 +36,13 @@ type
|
||||||
Y: Real;
|
Y: Real;
|
||||||
Z: Real;
|
Z: Real;
|
||||||
end;
|
end;
|
||||||
|
TVector2D = record
|
||||||
|
X: Single;
|
||||||
|
Y: Single;
|
||||||
|
end;
|
||||||
|
|
||||||
function Vector(AX, AY, AZ: Real): TVector;
|
function Vector(AX, AY, AZ: Real): TVector;
|
||||||
|
function Vector(AX, AY: Single): TVector2D;
|
||||||
function VectorAdd(AVector1, AVector2: TVector): TVector;
|
function VectorAdd(AVector1, AVector2: TVector): TVector;
|
||||||
function VectorDot(AVector1, AVector2: TVector): TVector;
|
function VectorDot(AVector1, AVector2: TVector): TVector;
|
||||||
function VectorCross(AVector1, AVector2: TVector): TVector;
|
function VectorCross(AVector1, AVector2: TVector): TVector;
|
||||||
|
@ -52,6 +57,12 @@ begin
|
||||||
Result.Z := AZ;
|
Result.Z := AZ;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function Vector(AX, AY: Single): TVector2D;
|
||||||
|
begin
|
||||||
|
Result.X := AX;
|
||||||
|
Result.Y := AY;
|
||||||
|
end;
|
||||||
|
|
||||||
function VectorAdd(AVector1, AVector2: TVector): TVector;
|
function VectorAdd(AVector1, AVector2: TVector): TVector;
|
||||||
begin
|
begin
|
||||||
Result.X := AVector1.X + AVector2.X;
|
Result.X := AVector1.X + AVector2.X;
|
||||||
|
|
Loading…
Reference in New Issue