summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 75893e9)
raw | patch | inline | side by side (parent: 75893e9)
author | Ketmar Dark <ketmar@ketmar.no-ip.org> | |
Fri, 18 Aug 2017 01:35:18 +0000 (04:35 +0300) | ||
committer | Ketmar Dark <ketmar@ketmar.no-ip.org> | |
Fri, 18 Aug 2017 18:28:51 +0000 (21:28 +0300) |
diff --git a/src/game/g_game.pas b/src/game/g_game.pas
index c575ca4e4416f685509fef8af1b61536a47eb4f1..90332cab6501a7a09ce47d03ac833625a09834c6 100644 (file)
--- a/src/game/g_game.pas
+++ b/src/game/g_game.pas
begin
case getBool(1) of
-1: begin end;
- 0: gdbg_map_use_sap_coldet := (cmd = 'sq_use_grid');
- 1: gdbg_map_use_sap_coldet := (cmd = 'sq_use_sap');
+ 0: gdbg_map_use_tree_coldet := (cmd = 'sq_use_grid');
+ 1: gdbg_map_use_tree_coldet := (cmd = 'sq_use_sap');
end;
- if gdbg_map_use_sap_coldet then g_Console_Add('coldet: sap') else g_Console_Add('coldet: grid');
+ if gdbg_map_use_tree_coldet then g_Console_Add('coldet: tree') else g_Console_Add('coldet: grid');
exit;
end;
end;
diff --git a/src/game/g_map.pas b/src/game/g_map.pas
index 55f1e4aae46348be6ac6d66fdb93f255f39bbb22..36f59f012c2f2146e7abad79408f3187b8d19c47 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
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_tree_draw: Boolean = true;
+ gdbg_map_use_tree_coldet: Boolean = false;
profMapCollision: TProfiler = nil; //WARNING: FOR DEBUGGING ONLY!
implementation
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.setXYWH(pan.X, pan.Y, pan.Width, pan.Height);
+ 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;
- 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], 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();
-
- gMapSAP.batchUpdateBegin();
+ mapTree := TDynAABBTreeMap.Create();
addPanelsToGrid(gWalls, PANEL_WALL); // and PANEL_CLOSEDOOR
addPanelsToGrid(gRenderBackgrounds, PANEL_BACK);
addPanelsToGrid(gLifts, PANEL_LIFTUP); // it doesn't matter which LIFT type is used here
addPanelsToGrid(gBlockMon, PANEL_BLOCKMON);
- gMapSAP.batchUpdateEnd();
-
gMapGrid.dumpStats();
- gMapSAP.dumpStats();
+ //gMapSAP.dumpStats();
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;
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
- 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, checkerTree);
end
else
begin
@@ -1976,10 +2000,20 @@ 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
- 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, checkerTree);
end
else
begin
@@ -2240,15 +2274,23 @@ 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
- if gdbg_map_use_sap_coldet then
+ if gdbg_map_use_tree_coldet then
begin
- gMapSAP.forEachInAABB(X, Y, Width, Height, checker);
+ mapTree.aabbQuery(X, Y, Width, Height, checkerTree);
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;
- if gdbg_map_use_sap_coldet then
+ if gdbg_map_use_tree_coldet then
begin
- gMapSAP.forEachInAABB(X, Y, Width, Height, checker);
+ mapTree.aabbQuery(X, Y, Width, Height, checkerTree);
end
else
begin
diff --git a/src/game/g_panel.pas b/src/game/g_panel.pas
index 4374cf180f3e8027b750c7f382614cdb6164c956..39237f182d1a692e481043dc90640dba4624e169 100644 (file)
--- a/src/game/g_panel.pas
+++ b/src/game/g_panel.pas
LiftType: Byte;
LastAnimLoop: Byte;
ArrIdx: Integer; // index in one of internal arrays; sorry
+ tag: Integer; // used in coldets and such; sorry
constructor Create(PanelRec: TPanelRec_1;
AddTextures: TAddTextureArray;
diff --git a/src/game/g_window.pas b/src/game/g_window.pas
index c91ff6cc555cedcf224827fcd9fac0f0f12437ea..7d9ec78b5baffe5a78bb694e1c15008af40eeb53 100644 (file)
--- a/src/game/g_window.pas
+++ b/src/game/g_window.pas
if ParamStr(idx) = '--opengl-dump-exts' then gwin_dump_extensions := true;
if ParamStr(idx) = '--twinkletwinkle' then gwin_k8_enable_light_experiments := true;
if ParamStr(idx) = '--jah' then g_profile_history_size := 100;
- if ParamStr(idx) = '--sap-draw' then gdbg_map_use_sap_draw := true;
- if ParamStr(idx) = '--grid-draw' then gdbg_map_use_sap_draw := false;
- if ParamStr(idx) = '--sap-coldet' then gdbg_map_use_sap_coldet := true;
- if ParamStr(idx) = '--grid-coldet' then gdbg_map_use_sap_coldet := false;
+ if ParamStr(idx) = '--tree-draw' then gdbg_map_use_tree_draw := true;
+ if ParamStr(idx) = '--grid-draw' then gdbg_map_use_tree_draw := false;
+ if ParamStr(idx) = '--tree-coldet' then gdbg_map_use_tree_coldet := true;
+ if ParamStr(idx) = '--grid-coldet' then gdbg_map_use_tree_coldet := false;
end;
+ if gdbg_map_use_tree_draw then e_WriteLog('using TREE renderer', MSG_NOTIFY);
+ if not gdbg_map_use_tree_draw then e_WriteLog('using GRID renderer', MSG_NOTIFY);
+
+ if gdbg_map_use_tree_coldet then e_WriteLog('using TREE coldet', MSG_NOTIFY);
+ if not gdbg_map_use_tree_coldet then e_WriteLog('using GRID coldet', MSG_NOTIFY);
+
e_WriteLog('Initializing OpenGL', MSG_NOTIFY);
InitOpenGL(gVSync);
index 91a98190c352c73f6d06dd310c9f98007ef3209d..73f02f7cac9fb8faf88f7ce753ec5def78051f33 100644 (file)
--- a/src/game/z_aabbtree.pas
+++ b/src/game/z_aabbtree.pas
+(* Copyright (C) DooM 2D:Forever Developers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *)
{$INCLUDE ../shared/a_modes.inc}
{$DEFINE aabbtree_many_asserts}
{$DEFINE aabbtree_query_count}
Float = Single;
PFloat = ^Float;
+ TTreeFlesh = TObject;
+
// ////////////////////////////////////////////////////////////////////////// //
type
// a node is either a leaf (has data) or is an internal node (has children)
children: array [0..1] of Integer; // left and right child of the node (children[0] = left child)
//TODO: `flesh` can be united with `children`
- //flesh: Integer;
+ flesh: TTreeFlesh;
// height of the node in the tree (-1 for free nodes)
height: SmallInt;
// fat axis aligned bounding box (AABB) corresponding to the node
function leaf (): Boolean; inline;
function free (): Boolean; inline;
property nextNodeId: Integer read parentId write parentId;
- property flesh: Integer read children[0] write children[0];
+ //property flesh: Integer read children[0] write children[0];
end;
TVisitCheckerCB = function (node: PTreeNode): Boolean is nested;
- TVisitVisitorCB = function (abody: Integer): Boolean is nested;
+ TVisitVisitorCB = function (abody: TTreeFlesh): Boolean is nested;
public
// return `true` to stop
- type TForEachLeafCB = function (abody: Integer; const aabb: AABB2D): Boolean is nested; // WARNING! don't modify AABB here!
+ type TForEachLeafCB = function (abody: TTreeFlesh; const aabb: AABB2D): Boolean is nested; // WARNING! don't modify AABB here!
public
// in the broad-phase collision detection (dynamic AABB tree), the AABBs are
public
// called when a overlapping node has been found during the call to forEachAABBOverlap()
// return `true` to stop
- type TQueryOverlapCB = function (abody: Integer): Boolean is nested;
- type TSegQueryCallback = function (abody: Integer; ax, ay, bx, by: Float): Float is nested; // return dist from (ax,ay) to abody
+ type TQueryOverlapCB = function (abody: TTreeFlesh): Boolean is nested;
+ type TSegQueryCallback = function (abody: TTreeFlesh; ax, ay, bx, by: Float): Float is nested; // return dist from (ax,ay) to abody
TSegmentQueryResult = record
dist: Float; // <0: nothing was hit
- flesh: Integer;
+ flesh: TTreeFlesh;
procedure reset (); inline;
function valid (): Boolean; inline;
procedure getRootAABB (var aabb: AABB2D);
function isValidId (id: Integer): Boolean; inline;
- function getNodeObjectId (nodeid: Integer): Integer; inline;
+ function getNodeObjectId (nodeid: Integer): TTreeFlesh; inline;
procedure getNodeFatAABB (var aabb: AABB2D; nodeid: Integer); inline;
// return `false` for invalid flesh
- function getFleshAABB (var aabb: AABB2D; flesh: Integer): Boolean; virtual; abstract;
+ function getFleshAABB (var aabb: AABB2D; flesh: TTreeFlesh): Boolean; virtual; abstract;
// insert an object into the tree
// this method creates a new leaf node in the tree and returns the id of the corresponding node or -1 on error
// AABB for static object will not be "fat" (simple optimization)
// WARNING! inserting the same object several times *WILL* break everything!
- function insertObject (flesh: Integer; staticObject: Boolean=false): Integer;
+ function insertObject (flesh: TTreeFlesh; staticObject: Boolean=false): Integer;
// remove an object from the tree
// WARNING: ids of removed objects can be reused on later insertions!
function updateObject (nodeId: Integer; dispX, dispY: Float; forceReinsert: Boolean=false): Boolean;
procedure aabbQuery (ax, ay, aw, ah: Float; cb: TQueryOverlapCB);
- function pointQuery (ax, ay: Float; cb: TQueryOverlapCB): Integer;
+ function pointQuery (ax, ay: Float; cb: TQueryOverlapCB): TTreeFlesh;
function segmentQuery (var qr: TSegmentQueryResult; ax, ay, bx, by: Float; cb: TSegQueryCallback): Boolean;
function computeTreeHeight (): Integer; // compute the height of the tree
// ////////////////////////////////////////////////////////////////////////// //
-procedure TDynAABBTree.TSegmentQueryResult.reset (); begin dist := -1; flesh := -1; end;
-function TDynAABBTree.TSegmentQueryResult.valid (): Boolean; begin result := (dist >= 0) and (flesh >= 0); end;
+procedure TDynAABBTree.TSegmentQueryResult.reset (); begin dist := -1; flesh := nil; end;
+function TDynAABBTree.TSegmentQueryResult.valid (): Boolean; begin result := (dist >= 0) and (flesh <> nil); end;
// ////////////////////////////////////////////////////////////////////////// //
parentId := 0;
children[0] := 0;
children[1] := 0;
- //flesh: Integer;
+ flesh := nil;
height := 0;
aabb.setX0Y0X1Y1(0, 0, 0, 0);
end;
// get object by nodeid; can return nil for invalid ids
-function TDynAABBTree.getNodeObjectId (nodeid: Integer): Integer;
+function TDynAABBTree.getNodeObjectId (nodeid: Integer): TTreeFlesh;
begin
- if (nodeid >= 0) and (nodeid < mNodeCount) and (mNodes[nodeid].leaf) then result := mNodes[nodeid].flesh else result := -1;
+ if (nodeid >= 0) and (nodeid < mNodeCount) and (mNodes[nodeid].leaf) then result := mNodes[nodeid].flesh else result := nil;
end;
// get fat object AABB by nodeid; returns random shit for invalid ids
// this method creates a new leaf node in the tree and returns the id of the corresponding node or -1 on error
// AABB for static object will not be "fat" (simple optimization)
// WARNING! inserting the same object several times *WILL* break everything!
-function TDynAABBTree.insertObject (flesh: Integer; staticObject: Boolean=false): Integer;
+function TDynAABBTree.insertObject (flesh: TTreeFlesh; staticObject: Boolean=false): Integer;
var
aabb: AABB2D;
nodeId: Integer;
end;
-// report body that contains the given point, or -1
-function TDynAABBTree.pointQuery (ax, ay: Float; cb: TQueryOverlapCB): Integer;
+// report body that contains the given point, or nil
+function TDynAABBTree.pointQuery (ax, ay: Float; cb: TQueryOverlapCB): TTreeFlesh;
var
nid: Integer;
function checker (node: PTreeNode): Boolean;
begin
nid := visit(checker, cb);
{$IFDEF aabbtree_many_asserts}assert((nid < 0) or ((nid >= 0) and (nid < mNodeCount) and (mNodes[nid].leaf)));{$ENDIF}
- if (nid >= 0) then result := mNodes[nid].flesh else result := -1;
+ if (nid >= 0) then result := mNodes[nid].flesh else result := nil;
end;
result := node.aabb.intersects(curax, curay, curbx, curby);
end;
- function visitor (flesh: Integer): Boolean;
+ function visitor (flesh: TTreeFlesh): Boolean;
var
hitFraction: Float;
begin