From 51420f985c7642cda726ec6e333b4283d3bebd22 Mon Sep 17 00:00:00 2001 From: Ketmar Dark Date: Fri, 18 Aug 2017 04:35:18 +0300 Subject: [PATCH] tree can render things (buggy) --- src/game/g_game.pas | 6 +-- src/game/g_map.pas | 96 +++++++++++++++++++++++++++++++---------- src/game/g_panel.pas | 1 + src/game/g_window.pas | 14 ++++-- src/game/z_aabbtree.pas | 59 ++++++++++++++++--------- 5 files changed, 125 insertions(+), 51 deletions(-) diff --git a/src/game/g_game.pas b/src/game/g_game.pas index c575ca4..90332ca 100644 --- a/src/game/g_game.pas +++ b/src/game/g_game.pas @@ -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; diff --git a/src/game/g_map.pas b/src/game/g_map.pas index 55f1e4a..36f59f0 100644 --- a/src/game/g_map.pas +++ b/src/game/g_map.pas @@ -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 diff --git a/src/game/g_panel.pas b/src/game/g_panel.pas index 4374cf1..39237f1 100644 --- a/src/game/g_panel.pas +++ b/src/game/g_panel.pas @@ -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; diff --git a/src/game/g_window.pas b/src/game/g_window.pas index c91ff6c..7d9ec78 100644 --- a/src/game/g_window.pas +++ b/src/game/g_window.pas @@ -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); diff --git a/src/game/z_aabbtree.pas b/src/game/z_aabbtree.pas index 91a9819..73f02f7 100644 --- a/src/game/z_aabbtree.pas +++ b/src/game/z_aabbtree.pas @@ -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 . + *) {$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 -- 2.29.2