diff --git a/src/game/g_map.pas b/src/game/g_map.pas
index 29750c92009aeb5a36a4bb13fd2601bf22c521ff..11a7d79459680c945d174ca81c4bb45c4618d279 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, md5, xprofiler;
+ g_phys, wadreader, BinEditor, g_panel, g_grid, z_aabbtree, md5, xprofiler;
type
TMapInfo = record
gdbg_map_use_grid_render: Boolean = true;
gdbg_map_use_grid_coldet: Boolean = true;
+ gdbg_map_use_tree_draw: Boolean = true;
+ gdbg_map_use_tree_coldet: Boolean = false;
profMapCollision: TProfiler = nil; //WARNING: FOR DEBUGGING ONLY!
implementation
GL, GLExt, g_weapons, g_game, g_sound, e_sound, CONFIG,
g_options, MAPREADER, g_triggers, g_player, MAPDEF,
Math, g_monsters, g_saveload, g_language, g_netmsg,
- utils, sfs,
+ utils, sfs, binheap,
ImagingTypes, Imaging, ImagingUtility,
ImagingGif, ImagingNetworkGraphics;
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
+ pan := (flesh as TPanel);
+ aabb.setDims(pan.X, pan.Y, pan.X+pan.Width-1, pan.Y+pan.Height-1);
+ result := true;
+end;
+
var
PanelById: array of TPanelID;
Textures: TLevelTextureArray;
FlagPoints: Array [FLAG_RED..FLAG_BLUE] of PFlagPoint;
//DOMFlagPoints: Array of TFlagPoint;
gMapGrid: TBodyGrid = 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);
+ mapTree.insertObject(panels[idx], true); // as static object
end;
end;
begin
gMapGrid.Free();
gMapGrid := nil;
+ mapTree.Free();
+ mapTree := nil;
fixMinMax(gWalls);
fixMinMax(gRenderBackgrounds);
end;
gMapGrid := TBodyGrid.Create(mapX0, mapY0, mapX1-mapX0+1, mapY1-mapY0+1);
+ mapTree := TDynAABBTreeMap.Create();
addPanelsToGrid(gWalls, PANEL_WALL); // and PANEL_CLOSEDOOR
addPanelsToGrid(gRenderBackgrounds, PANEL_BACK);
addPanelsToGrid(gBlockMon, PANEL_BLOCKMON);
gMapGrid.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;
+ mapTree.Free();
+ mapTree := nil;
Result := False;
gMapInfo.Map := Res;
dplAddPanel(pan);
end;
+ function checkerTree (obj: TObject): Boolean;
+ var
+ pan: TPanel;
+ begin
+ result := false; // don't stop, ever
+ pan := (obj as TPanel);
+ if (pan.tag <> ptag) then exit;
+ if (PanelType = PANEL_CLOSEDOOR) then begin if not pan.Door then exit; end else begin if pan.Door then exit; end;
+ //e_WriteLog(Format(' body hit: (%d,%d)-(%dx%d) tag: %d; qtag:%d', [pan.X, pan.Y, pan.Width, pan.Height, tag, PanelType]), MSG_NOTIFY);
+ dplAddPanel(pan);
+ end;
+
procedure DrawPanels (stp: Integer; var panels: TPanelArray; drawDoors: Boolean=False);
var
idx: Integer;
if gdbg_map_use_grid_render then
begin
- gMapGrid.forEachInAABB(x0, y0, wdt, hgt, checker);
+ if gdbg_map_use_tree_draw then
+ begin
+ mapTree.aabbQuery(x0, y0, wdt, hgt, checkerTree);
+ end
+ else
+ begin
+ gMapGrid.forEachInAABB(x0, y0, wdt, hgt, checker);
+ end;
// sort and draw the list (we need to sort it, or rendering is fucked)
while gDrawPanelList.count > 0 do
begin
@@ -1955,8 +2001,25 @@ procedure g_Map_DrawPanelShadowVolumes(lightX: Integer; lightY: Integer; radius:
pan.DrawShadowVolume(lightX, lightY, radius);
end;
+ function checkerTree (obj: TObject): Boolean;
+ var
+ pan: TPanel;
+ begin
+ result := false; // don't stop, ever
+ pan := (obj as TPanel);
+ if (pan.tag <> GridTagWallDoor) then exit; // only walls
+ pan.DrawShadowVolume(lightX, lightY, radius);
+ end;
+
begin
- gMapGrid.forEachInAABB(lightX-radius, lightY-radius, radius*2, radius*2, checker);
+ if gdbg_map_use_tree_draw then
+ begin
+ mapTree.aabbQuery(lightX-radius, lightY-radius, radius*2, radius*2, checkerTree);
+ end
+ else
+ begin
+ gMapGrid.forEachInAABB(lightX-radius, lightY-radius, radius*2, radius*2, checker);
+ end;
end;
@@ -2212,13 +2275,28 @@ function g_Map_CollidePanel(X, Y: Integer; Width, Height: Word; PanelType: Word;
end;
end;
+ function checkerTree (obj: TObject): Boolean;
+ var
+ pan: TPanel;
+ begin
+ pan := (obj as TPanel);
+ result := checker(obj, pan.tag);
+ end;
+
begin
//TODO: detailed profile
if (profMapCollision <> nil) then profMapCollision.sectionBeginAccum('wall coldet');
try
if gdbg_map_use_grid_coldet then
begin
- result := gMapGrid.forEachInAABB(X, Y, Width, Height, checker);
+ if gdbg_map_use_tree_coldet then
+ begin
+ mapTree.aabbQuery(X, Y, Width, Height, checkerTree);
+ end
+ else
+ begin
+ result := gMapGrid.forEachInAABB(X, Y, Width, Height, checker);
+ end;
end
else
begin
end;
end;
+ function checkerTree (obj: TObject): Boolean;
+ var
+ pan: TPanel;
+ begin
+ pan := (obj as TPanel);
+ result := checker(obj, pan.tag);
+ end;
+
begin
//TODO: detailed profile?
if (profMapCollision <> nil) then profMapCollision.sectionBeginAccum('liquid coldet');
if gdbg_map_use_grid_coldet then
begin
texid := TEXTURE_NONE;
- gMapGrid.forEachInAABB(X, Y, Width, Height, checker);
+ if gdbg_map_use_tree_coldet then
+ begin
+ mapTree.aabbQuery(X, Y, Width, Height, checkerTree);
+ end
+ else
+ begin
+ gMapGrid.forEachInAABB(X, Y, Width, Height, checker);
+ end;
result := texid;
end
else