From: Ketmar Dark Date: Fri, 18 Aug 2017 17:36:17 +0000 (+0300) Subject: cosmetix X-Git-Url: http://deadsoftware.ru/gitweb?a=commitdiff_plain;h=46bfd9c48fe4cb640e507ceb88116eb2396579fa;p=d2df-sdl.git cosmetix --- diff --git a/src/game/g_map.pas b/src/game/g_map.pas index b448103..3a97ef4 100644 --- a/src/game/g_map.pas +++ b/src/game/g_map.pas @@ -156,16 +156,16 @@ const 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; @@ -1005,7 +1005,7 @@ var 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 + mapTree.insertObject(panels[idx], tag, true); // as static object end; end; @@ -1898,8 +1898,8 @@ var 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; @@ -1912,18 +1912,6 @@ 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; @@ -1960,7 +1948,7 @@ begin begin if gdbg_map_use_tree_draw then begin - mapTree.aabbQuery(x0, y0, wdt, hgt, checkerTree); + mapTree.aabbQuery(x0, y0, wdt, hgt, checker, ptag); end else begin @@ -2003,20 +1991,10 @@ 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_tree_draw then begin - mapTree.aabbQuery(lightX-radius, lightY-radius, radius*2, radius*2, checkerTree); + mapTree.aabbQuery(lightX-radius, lightY-radius, radius*2, radius*2, checker, GridTagWallDoor); end else begin @@ -2277,14 +2255,6 @@ 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'); @@ -2293,7 +2263,7 @@ begin begin if gdbg_map_use_tree_coldet then begin - result := mapTree.aabbQuery(X, Y, Width, Height, checkerTree); + result := (mapTree.aabbQuery(X, Y, Width, Height, checker, (GridTagWallDoor or GridTagWater or GridTagAcid1 or GridTagAcid2 or GridTagStep or GridTagLift or GridTagBlockMon)) <> nil); { if (mapTree.nodesVisited <> 0) then begin @@ -2328,6 +2298,7 @@ var 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 @@ -2362,15 +2333,6 @@ var end; end; - function checkerTree (obj: TObject): Boolean; - var - pan: TPanel; - begin - result := false; - pan := (obj as TPanel); - if (pan.tag = GridTagWater) or (pan.tag = GridTagAcid1) or (pan.tag = GridTagAcid2) then result := checker(obj, pan.tag); - end; - {var cctype1: Integer = 3; // priority: 0: water, 1: acid1, 2: acid2; 3: others (nothing) texid1: DWORD;} @@ -2383,7 +2345,7 @@ begin texid := TEXTURE_NONE; if gdbg_map_use_tree_coldet then begin - mapTree.aabbQuery(X, Y, Width, Height, checkerTree); + mapTree.aabbQuery(X, Y, Width, Height, checker); { cctype1 := cctype; texid1 := texid; diff --git a/src/game/z_aabbtree.pas b/src/game/z_aabbtree.pas index 4f3e993..19a5c74 100644 --- a/src/game/z_aabbtree.pas +++ b/src/game/z_aabbtree.pas @@ -153,6 +153,7 @@ type height: SmallInt; // fat axis aligned bounding box (AABB) corresponding to the node aabb: AABB2D; + tag: Integer; // just a user-defined tag public // return true if the node is a leaf of the tree procedure clear (); inline; @@ -163,7 +164,7 @@ type end; TVisitCheckerCB = function (node: PTreeNode): Boolean is nested; - TVisitVisitorCB = function (abody: TTreeFlesh): Boolean is nested; + //TVisitVisitorCB = function (abody: TTreeFlesh; atag: Integer): Boolean is nested; public // return `true` to stop @@ -186,6 +187,20 @@ type // without triggering a large modification of the tree which can be costly mExtraGap: Float; + public + // called when a overlapping node has been found during the call to forEachAABBOverlap() + // return `true` to stop + type TQueryOverlapCB = function (abody: TTreeFlesh; atag: Integer): 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: TTreeFlesh; + + procedure reset (); inline; + function valid (): Boolean; inline; + end; + private function allocateNode (): Integer; procedure releaseNode (nodeId: Integer); @@ -195,27 +210,13 @@ type function computeHeight (nodeId: Integer): Integer; function insertObjectInternal (var aabb: AABB2D; staticObject: Boolean): Integer; procedure setup (); - function visit (checker: TVisitCheckerCB; visitor: TVisitVisitorCB): Integer; + function visit (checker: TVisitCheckerCB; visitor: TQueryOverlapCB; tagmask: Integer=-1): Integer; public {$IFDEF aabbtree_query_count} mNodesVisited, mNodesDeepVisited: Integer; {$ENDIF} - public - // called when a overlapping node has been found during the call to forEachAABBOverlap() - // return `true` to stop - 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: TTreeFlesh; - - procedure reset (); inline; - function valid (): Boolean; inline; - end; - public constructor Create (extraAABBGap: Float=0.0); destructor Destroy (); override; @@ -237,7 +238,7 @@ type // 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: TTreeFlesh; staticObject: Boolean=false): Integer; + function insertObject (flesh: TTreeFlesh; tag: Integer; staticObject: Boolean=false): Integer; // remove an object from the tree // WARNING: ids of removed objects can be reused on later insertions! @@ -260,7 +261,7 @@ type *) function updateObject (nodeId: Integer; dispX, dispY: Float; forceReinsert: Boolean=false): Boolean; - function aabbQuery (ax, ay, aw, ah: Float; cb: TQueryOverlapCB): Boolean; + function aabbQuery (ax, ay, aw, ah: Float; cb: TQueryOverlapCB; tagmask: Integer=-1): TTreeFlesh; function pointQuery (ax, ay: Float; cb: TQueryOverlapCB): TTreeFlesh; function segmentQuery (var qr: TSegmentQueryResult; ax, ay, bx, by: Float; cb: TSegQueryCallback): Boolean; @@ -524,6 +525,7 @@ begin children[0] := 0; children[1] := 0; flesh := nil; + tag := 0; height := 0; aabb.minX := 0; aabb.minY := 0; @@ -1105,7 +1107,7 @@ end; // return `true` from visitor to stop immediately // checker should check if this node should be considered to further checking // returns tree node if visitor says stop or -1 -function TDynAABBTree.visit (checker: TVisitCheckerCB; visitor: TVisitVisitorCB): Integer; +function TDynAABBTree.visit (checker: TVisitCheckerCB; visitor: TQueryOverlapCB; tagmask: Integer=-1): Integer; var stack: array [0..255] of Integer; // stack with the nodes to visit bigstack: array of Integer = nil; @@ -1206,9 +1208,9 @@ begin begin // call visitor on it {$IFDEF aabbtree_query_count}Inc(mNodesDeepVisited);{$ENDIF} - if assigned(visitor) then + if ((node.tag and tagmask) <> 0) and assigned(visitor) then begin - if (visitor(node.flesh)) then begin result := nodeId; exit; end; + if (visitor(node.flesh, node.tag)) then begin result := nodeId; exit; end; end; end else @@ -1287,7 +1289,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: TTreeFlesh; staticObject: Boolean=false): Integer; +function TDynAABBTree.insertObject (flesh: TTreeFlesh; tag: Integer; staticObject: Boolean=false): Integer; var aabb: AABB2D; nodeId: Integer; @@ -1310,6 +1312,7 @@ begin nodeId := insertObjectInternal(aabb, staticObject); {$IFDEF aabbtree_many_asserts}assert(mNodes[nodeId].leaf);{$ENDIF} mNodes[nodeId].flesh := flesh; + mNodes[nodeId].tag := tag; result := nodeId; end; @@ -1378,29 +1381,33 @@ end; // report all shapes overlapping with the AABB given in parameter -function TDynAABBTree.aabbQuery (ax, ay, aw, ah: Float; cb: TQueryOverlapCB): Boolean; +function TDynAABBTree.aabbQuery (ax, ay, aw, ah: Float; cb: TQueryOverlapCB; tagmask: Integer=-1): TTreeFlesh; var caabb: AABB2D; function checker (node: PTreeNode): Boolean; begin result := caabb.overlaps(node.aabb); end; +var + nid: Integer; begin + result := nil; if not assigned(cb) then exit; if (aw < 1) or (ah < 1) then exit; caabb := AABB2D.Create(ax, ay, ax+aw, ay+ah); - result := (visit(checker, cb) <> -1); + nid := visit(checker, cb, tagmask); + if (nid >= 0) then result := mNodes[nid].flesh else result := nil; end; // 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 result := node.aabb.contains(ax, ay); end; +var + nid: Integer; begin nid := visit(checker, cb); {$IFDEF aabbtree_many_asserts}assert((nid < 0) or ((nid >= 0) and (nid < mNodeCount) and (mNodes[nid].leaf)));{$ENDIF} @@ -1422,7 +1429,7 @@ var result := node.aabb.intersects(curax, curay, curbx, curby); end; - function visitor (flesh: TTreeFlesh): Boolean; + function visitor (flesh: TTreeFlesh; tag: Integer): Boolean; var hitFraction: Float; begin