DEADSOFTWARE

tree can render things (buggy)
authorKetmar Dark <ketmar@ketmar.no-ip.org>
Fri, 18 Aug 2017 01:35:18 +0000 (04:35 +0300)
committerKetmar Dark <ketmar@ketmar.no-ip.org>
Fri, 18 Aug 2017 18:28:51 +0000 (21:28 +0300)
src/game/g_game.pas
src/game/g_map.pas
src/game/g_panel.pas
src/game/g_window.pas
src/game/z_aabbtree.pas

index c575ca4e4416f685509fef8af1b61536a47eb4f1..90332cab6501a7a09ce47d03ac833625a09834c6 100644 (file)
@@ -5062,10 +5062,10 @@ begin
   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;
index 55f1e4aae46348be6ac6d66fdb93f255f39bbb22..36f59f012c2f2146e7abad79408f3187b8d19c47 100644 (file)
@@ -20,7 +20,7 @@ interface
 
 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
@@ -136,8 +136,8 @@ var
 
   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
@@ -191,6 +191,20 @@ type
     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;
@@ -198,7 +212,7 @@ var
   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 ();
@@ -430,6 +444,7 @@ begin
 
   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;
 
@@ -986,16 +1001,17 @@ var
     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);
@@ -1014,9 +1030,7 @@ begin
   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);
@@ -1028,10 +1042,8 @@ begin
   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;
@@ -1068,8 +1080,8 @@ var
 begin
   gMapGrid.Free();
   gMapGrid := nil;
-  gMapSAP.Free();
-  gMapSAP := nil;
+  mapTree.Free();
+  mapTree := nil;
 
   Result := False;
   gMapInfo.Map := Res;
@@ -1897,6 +1909,18 @@ var
     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;
@@ -1931,9 +1955,9 @@ begin
 
   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
@@ -2311,6 +2353,14 @@ var
     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');
@@ -2318,9 +2368,9 @@ begin
     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
index 4374cf180f3e8027b750c7f382614cdb6164c956..39237f182d1a692e481043dc90640dba4624e169 100644 (file)
@@ -55,6 +55,7 @@ type
     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;
index c91ff6cc555cedcf224827fcd9fac0f0f12437ea..7d9ec78b5baffe5a78bb694e1c15008af40eeb53 100644 (file)
@@ -709,12 +709,18 @@ begin
     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)
@@ -1,3 +1,18 @@
+(* 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}
@@ -10,6 +25,8 @@ type
   Float = Single;
   PFloat = ^Float;
 
+  TTreeFlesh = TObject;
+
 
 // ////////////////////////////////////////////////////////////////////////// //
 type
@@ -147,7 +164,7 @@ 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
@@ -158,15 +175,15 @@ type
         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
@@ -204,12 +221,12 @@ type
   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;
@@ -226,17 +243,17 @@ type
     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!
@@ -260,7 +277,7 @@ type
     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
@@ -481,8 +498,8 @@ end;
 
 
 // ////////////////////////////////////////////////////////////////////////// //
-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;
 
 
 // ////////////////////////////////////////////////////////////////////////// //
@@ -494,7 +511,7 @@ begin
   parentId := 0;
   children[0] := 0;
   children[1] := 0;
-  //flesh: Integer;
+  flesh := nil;
   height := 0;
   aabb.setX0Y0X1Y1(0, 0, 0, 0);
 end;
@@ -1225,9 +1242,9 @@ 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
@@ -1241,7 +1258,7 @@ end;
 // 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;
@@ -1331,8 +1348,8 @@ begin
 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;
@@ -1342,7 +1359,7 @@ var
 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;
 
 
@@ -1360,7 +1377,7 @@ var
     result := node.aabb.intersects(curax, curay, curbx, curby);
   end;
 
-  function visitor (flesh: Integer): Boolean;
+  function visitor (flesh: TTreeFlesh): Boolean;
   var
     hitFraction: Float;
   begin