diff --git a/src/game/g_map.pas b/src/game/g_map.pas
index 3c380f9bb0a15ea2efba4516bc78d5f2b6bcefbd..e439d17db2b9643ea8451966dc98354690f15be7 100644 (file)
--- a/src/game/g_map.pas
+++ b/src/game/g_map.pas
uses
e_graphics, g_basic, MAPSTRUCT, g_textures, Classes,
- g_phys, wadreader, BinEditor, g_panel, g_grid, g_sap, md5, xprofiler;
+ g_phys, wadreader, BinEditor, g_panel, g_grid, z_aabbtree, md5, xprofiler;
type
TMapInfo = record
BackID: DWORD = DWORD(-1);
gExternalResources: TStringList;
- gdbg_map_use_grid_render: Boolean = true;
- gdbg_map_use_grid_coldet: Boolean = true;
- gdbg_map_use_sap_draw: Boolean = true;
- gdbg_map_use_sap_coldet: Boolean = false;
+ gdbg_map_use_accel_render: Boolean = true;
+ gdbg_map_use_accel_coldet: Boolean = true;
+ gdbg_map_use_tree_draw: Boolean = false;
+ gdbg_map_use_tree_coldet: Boolean = false;
+ gdbg_map_dump_coldet_tree_queries: Boolean = false;
profMapCollision: TProfiler = nil; //WARNING: FOR DEBUGGING ONLY!
implementation
MUSIC_SIGNATURE = $4953554D; // 'MUSI'
FLAG_SIGNATURE = $47414C46; // 'FLAG'
- GridTagInvalid = -1;
- GridTagWallDoor = 0;
- GridTagBack = 1;
- GridTagFore = 2;
- GridTagWater = 3;
- GridTagAcid1 = 4;
- GridTagAcid2 = 5;
- GridTagStep = 6;
- GridTagLift = 7;
- GridTagBlockMon = 8;
+ GridTagInvalid = 0;
+ GridTagWallDoor = $0001;
+ GridTagBack = $0002;
+ GridTagFore = $0004;
+ GridTagWater = $0008;
+ GridTagAcid1 = $0010;
+ GridTagAcid2 = $0020;
+ GridTagStep = $0040;
+ GridTagLift = $0080;
+ GridTagBlockMon = $0100;
function panelTypeToTag (panelType: Word): Integer;
PArrID: Integer;
end;
+type
+ TDynAABBTreeMap = class(TDynAABBTree)
+ function getFleshAABB (var aabb: AABB2D; flesh: TTreeFlesh): Boolean; override;
+ end;
+
+function TDynAABBTreeMap.getFleshAABB (var aabb: AABB2D; flesh: TTreeFlesh): Boolean;
+var
+ pan: TPanel;
+begin
+ result := false;
+ if (flesh = nil) then begin aabb := AABB2D.Create(0, 0, 0, 0); exit; end;
+ pan := (flesh as TPanel);
+ aabb := AABB2D.Create(pan.X, pan.Y, pan.X+pan.Width, pan.Y+pan.Height);
+ if (pan.Width < 1) or (pan.Height < 1) then exit;
+ //if (pan.Width = 1) then aabb.maxX += 1;
+ //if (pan.Height = 1) then aabb.maxY += 1;
+ if not aabb.valid then raise Exception.Create('wutafuuuuuuu?!');
+ result := aabb.valid;
+end;
+
var
PanelById: array of TPanelID;
Textures: TLevelTextureArray;
FlagPoints: Array [FLAG_RED..FLAG_BLUE] of PFlagPoint;
//DOMFlagPoints: Array of TFlagPoint;
gMapGrid: TBodyGrid = nil;
- gMapSAP: TSweepAndPrune = nil;
+ mapTree: TDynAABBTree = nil;
procedure g_Map_ProfilersBegin ();
panels^[len] := TPanel.Create(PanelRec, AddTextures, CurTex, Textures);
panels^[len].ArrIdx := len;
+ panels^[len].tag := panelTypeToTag(PanelRec.PanelType);
if sav then
panels^[len].SaveIt := True;
tag := panelTypeToTag(tag);
for idx := High(panels) downto 0 do
begin
+ panels[idx].tag := tag;
gMapGrid.insertBody(panels[idx], panels[idx].X, panels[idx].Y, panels[idx].Width, panels[idx].Height, tag);
- gMapSAP.insertBody(panels[idx], panels[idx].X, panels[idx].Y, panels[idx].Width, panels[idx].Height, tag);
+ mapTree.insertObject(panels[idx], tag, true); // as static object
end;
end;
begin
gMapGrid.Free();
gMapGrid := nil;
- gMapSAP.Free();
- gMapSAP := nil;
+ mapTree.Free();
+ mapTree := nil;
fixMinMax(gWalls);
fixMinMax(gRenderBackgrounds);
end;
gMapGrid := TBodyGrid.Create(mapX0, mapY0, mapX1-mapX0+1, mapY1-mapY0+1);
- gMapSAP := TSweepAndPrune.Create();
+ mapTree := TDynAABBTreeMap.Create();
addPanelsToGrid(gWalls, PANEL_WALL); // and PANEL_CLOSEDOOR
addPanelsToGrid(gRenderBackgrounds, PANEL_BACK);
addPanelsToGrid(gBlockMon, PANEL_BLOCKMON);
gMapGrid.dumpStats();
- gMapSAP.dumpStats();
+ e_WriteLog(Format('tree depth: %d; %d nodes used, %d nodes allocated', [mapTree.computeTreeHeight, mapTree.nodeCount, mapTree.nodeAlloced]), MSG_NOTIFY);
+ mapTree.forEachLeaf(nil);
end;
function g_Map_Load(Res: String): Boolean;
begin
gMapGrid.Free();
gMapGrid := nil;
- gMapSAP.Free();
- gMapSAP := nil;
+ mapTree.Free();
+ mapTree := nil;
Result := False;
gMapInfo.Map := Res;
pan: TPanel;
begin
result := false; // don't stop, ever
+ //e_WriteLog(Format(' *body: tag:%d; ptag:%d; pantype=%d', [tag, ptag, PanelType]), MSG_NOTIFY);
if (tag <> ptag) then exit;
- //e_WriteLog(Format(' *body: tag:%d; qtag:%d', [tag, PanelType]), MSG_NOTIFY);
if obj = nil then begin e_WriteLog(Format(' !bodyFUUUUU0: tag:%d; qtag:%d', [tag, PanelType]), MSG_NOTIFY); exit; end;
if not (obj is TPanel) then begin e_WriteLog(Format(' !bodyFUUUUU1: tag:%d; qtag:%d', [tag, PanelType]), MSG_NOTIFY); exit; end;
dplClear();
ptag := panelTypeToTag(PanelType);
- if gdbg_map_use_grid_render then
+ if gdbg_map_use_accel_render then
begin
- if gdbg_map_use_sap_draw then
+ if gdbg_map_use_tree_draw then
begin
- gMapSAP.forEachInAABB(x0, y0, wdt, hgt, checker);
+ mapTree.aabbQuery(x0, y0, wdt, hgt, checker, ptag);
end
else
begin
- gMapGrid.forEachInAABB(x0, y0, wdt, hgt, checker);
+ gMapGrid.forEachInAABB(x0, y0, wdt, hgt, checker, ptag);
end;
// sort and draw the list (we need to sort it, or rendering is fucked)
while gDrawPanelList.count > 0 do
@@ -1973,13 +1997,13 @@ procedure g_Map_DrawPanelShadowVolumes(lightX: Integer; lightY: Integer; radius:
end;
begin
- if gdbg_map_use_sap_draw then
+ if gdbg_map_use_tree_draw then
begin
- gMapSAP.forEachInAABB(lightX-radius, lightY-radius, radius*2, radius*2, checker);
+ mapTree.aabbQuery(lightX-radius, lightY-radius, radius*2, radius*2, checker, GridTagWallDoor);
end
else
begin
- gMapGrid.forEachInAABB(lightX-radius, lightY-radius, radius*2, radius*2, checker);
+ gMapGrid.forEachInAABB(lightX-radius, lightY-radius, radius*2, radius*2, checker, GridTagWallDoor);
end;
end;
@@ -2239,25 +2263,27 @@ function g_Map_CollidePanel(X, Y: Integer; Width, Height: Word; PanelType: Word;
begin
//TODO: detailed profile
if (profMapCollision <> nil) then profMapCollision.sectionBeginAccum('wall coldet');
- try
- if gdbg_map_use_grid_coldet then
+ if gdbg_map_use_accel_coldet then
+ begin
+ if gdbg_map_use_tree_coldet then
begin
- if gdbg_map_use_sap_coldet then
+ result := (mapTree.aabbQuery(X, Y, Width, Height, checker, (GridTagWallDoor or GridTagWater or GridTagAcid1 or GridTagAcid2 or GridTagStep or GridTagLift or GridTagBlockMon)) <> nil);
+ if (gdbg_map_dump_coldet_tree_queries) and (mapTree.nodesVisited <> 0) then
begin
- gMapSAP.forEachInAABB(X, Y, Width, Height, checker);
- end
- else
- begin
- result := gMapGrid.forEachInAABB(X, Y, Width, Height, checker);
+ //e_WriteLog(Format('map collision: %d nodes visited (%d deep)', [mapTree.nodesVisited, mapTree.nodesDeepVisited]), MSG_NOTIFY);
+ g_Console_Add(Format('map collision: %d nodes visited (%d deep)', [mapTree.nodesVisited, mapTree.nodesDeepVisited]));
end;
end
else
begin
- result := g_Map_CollidePanelOld(X, Y, Width, Height, PanelType, b1x3);
+ result := gMapGrid.forEachInAABB(X, Y, Width, Height, checker, (GridTagWallDoor or GridTagWater or GridTagAcid1 or GridTagAcid2 or GridTagStep or GridTagLift or GridTagBlockMon));
end;
- finally
- if (profMapCollision <> nil) then profMapCollision.sectionEnd();
+ end
+ else
+ begin
+ result := g_Map_CollidePanelOld(X, Y, Width, Height, PanelType, b1x3);
end;
+ if (profMapCollision <> nil) then profMapCollision.sectionEnd();
end;
a: Integer;
begin
result := false; // don't stop, ever
+ if (tag <> GridTagWater) and (tag <> GridTagAcid1) and (tag <> GridTagAcid2) then exit;
pan := (obj as TPanel);
a := pan.ArrIdx;
// water
begin
//TODO: detailed profile?
if (profMapCollision <> nil) then profMapCollision.sectionBeginAccum('liquid coldet');
- try
- if gdbg_map_use_grid_coldet then
+ if gdbg_map_use_accel_coldet then
+ begin
+ texid := TEXTURE_NONE;
+ if gdbg_map_use_tree_coldet then
begin
- texid := TEXTURE_NONE;
- if gdbg_map_use_sap_coldet then
- begin
- gMapSAP.forEachInAABB(X, Y, Width, Height, checker);
- end
- else
- begin
- gMapGrid.forEachInAABB(X, Y, Width, Height, checker);
- end;
- result := texid;
+ mapTree.aabbQuery(X, Y, Width, Height, checker, (GridTagWater or GridTagAcid1 or GridTagAcid2));
end
else
begin
- result := g_Map_CollideLiquid_TextureOld(X, Y, Width, Height);
+ gMapGrid.forEachInAABB(X, Y, Width, Height, checker, (GridTagWater or GridTagAcid1 or GridTagAcid2));
end;
- finally
- if (profMapCollision <> nil) then profMapCollision.sectionEnd();
+ result := texid;
+ end
+ else
+ begin
+ result := g_Map_CollideLiquid_TextureOld(X, Y, Width, Height);
end;
+ if (profMapCollision <> nil) then profMapCollision.sectionEnd();
end;
procedure g_Map_EnableWall(ID: DWORD);