From e80d55312d7d3bacaa3d642a83cda0c8a1026a97 Mon Sep 17 00:00:00 2001 From: Ketmar Dark Date: Mon, 21 Aug 2017 23:11:19 +0300 Subject: [PATCH] better hitscan tracer; no more level trace bitmap (but no more particles too, alas) --- src/game/g_basic.pas | 23 ++++++++++++++++++-- src/game/g_gfx.pas | 47 +++++++++++++++++++++++++++++++++++++++++ src/game/g_map.pas | 6 +++++- src/game/g_weapons.pas | 4 ++++ src/game/z_aabbtree.pas | 20 ++++++++---------- 5 files changed, 86 insertions(+), 14 deletions(-) diff --git a/src/game/g_basic.pas b/src/game/g_basic.pas index 98cebcc..8e1ae92 100644 --- a/src/game/g_basic.pas +++ b/src/game/g_basic.pas @@ -48,7 +48,7 @@ function g_CollideAround(X1, Y1: Integer; Width1, Height1: Word; X2, Y2: Integer; Width2, Height2: Word): Boolean; function g_CollidePlayer(X, Y: Integer; Width, Height: Word): Boolean; function g_PatchLength(X1, Y1, X2, Y2: Integer): Word; -function g_TraceVector(X1, Y1, X2, Y2: Integer): Boolean; +function g_TraceVector(X1, Y1, X2, Y2: Integer): Boolean; // `true`: no wall hit function g_GetAcidHit(X, Y: Integer; Width, Height: Word): Byte; function g_Look(a, b: PObj; d: TDirection): Boolean; procedure IncMax(var A: Integer; B, Max: Integer); overload; @@ -142,15 +142,21 @@ begin end; end; + function g_TraceVector(X1, Y1, X2, Y2: Integer): Boolean; var + wallHitX: Integer = 0; + wallHitY: Integer = 0; +(* i: Integer; dx, dy: Integer; Xerr, Yerr, d: LongWord; incX, incY: Integer; x, y: Integer; +*) begin - Result := False; + (* + result := False; Assert(gCollideMap <> nil, 'g_TraceVector: gCollideMap = nil'); @@ -193,8 +199,21 @@ begin end; Result := True; + *) + + if (g_Map_traceToNearestWall(x1, y1, x2, y2, @wallHitX, @wallHitY) >= 0) then + begin + // check distance + //result := ((wallHitX-x1)*(wallHitX-x1)+(wallHitY-y1)*(wallHitY-y1) > (x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)); + result := false; + end + else + begin + result := true; // no obstacles + end; end; + function g_CreateUID(UIDType: Byte): Word; var ok: Boolean; diff --git a/src/game/g_gfx.pas b/src/game/g_gfx.pas index 17bbe92..3703627 100644 --- a/src/game/g_gfx.pas +++ b/src/game/g_gfx.pas @@ -14,6 +14,7 @@ * along with this program. If not, see . *) {$INCLUDE ../shared/a_modes.inc} +{.$DEFINE HAS_COLLIDE_BITMAP} unit g_gfx; interface @@ -58,8 +59,12 @@ procedure g_Mark(x, y, Width, Height: Integer; t: Byte; st: Boolean); procedure g_GFX_Update(); procedure g_GFX_Draw(); + +{$IF DEFINED(HAS_COLLIDE_BITMAP)} var gCollideMap: Array of Array of Byte; +{$ENDIF} + implementation @@ -103,9 +108,12 @@ var CurrentParticle: Integer; procedure g_Mark(x, y, Width, Height: Integer; t: Byte; st: Boolean); +{$IF DEFINED(HAS_COLLIDE_BITMAP)} var yy, y2, xx, x2: Integer; +{$ENDIF} begin +{$IF DEFINED(HAS_COLLIDE_BITMAP)} if x < 0 then begin Width := Width + x; @@ -150,12 +158,16 @@ begin for xx := x to x2 do gCollideMap[yy][xx] := gCollideMap[yy][xx] and t; end; +{$ENDIF} end; procedure CreateCollideMap(); +{$IF DEFINED(HAS_COLLIDE_BITMAP)} var a: Integer; +{$ENDIF} begin +{$IF DEFINED(HAS_COLLIDE_BITMAP)} g_Game_SetLoadingText(_lc[I_LOAD_COLLIDE_MAP]+' 1/6', 0, False); SetLength(gCollideMap, gMapInfo.Height+1); for a := 0 to High(gCollideMap) do @@ -225,6 +237,7 @@ begin g_Mark(X, Y, Width, Height, MARK_WALL, True); end; end; +{$ENDIF} end; procedure g_GFX_Init(); @@ -248,9 +261,13 @@ begin OnceAnims := nil; end; + {$IF DEFINED(HAS_COLLIDE_BITMAP)} gCollideMap := nil; + {$ENDIF} end; + +{$IF DEFINED(HAS_COLLIDE_BITMAP)} procedure CorrectOffsets(id: Integer); begin with Particles[id] do @@ -270,14 +287,19 @@ begin offsetX := 0; end; end; +{$ENDIF} + procedure g_GFX_SparkVel(fX, fY: Integer; Count: Word; VX, VY: Integer; DevX, DevY: Byte); +{$IF DEFINED(HAS_COLLIDE_BITMAP)} var a: Integer; DevX1, DevX2, DevY1, DevY2: Byte; l: Integer; +{$ENDIF} begin +{$IF DEFINED(HAS_COLLIDE_BITMAP)} l := Length(Particles); if l = 0 then Exit; @@ -326,10 +348,12 @@ begin else CurrentParticle := CurrentParticle+1; end; +{$ENDIF} end; procedure g_GFX_Blood(fX, fY: Integer; Count: Word; vx, vy: Integer; DevX, DevY: Word; CR, CG, CB: Byte; Kind: Byte = BLOOD_NORMAL); +{$IF DEFINED(HAS_COLLIDE_BITMAP)} var a: Integer; DevX1, DevX2, @@ -337,7 +361,9 @@ var l: Integer; CRnd: Byte; CC: SmallInt; +{$ENDIF} begin +{$IF DEFINED(HAS_COLLIDE_BITMAP)} if Kind = BLOOD_SPARKS then begin g_GFX_SparkVel(fX, fY, 2 + Random(2), -VX div 2, -VY div 2, DevX, DevY); @@ -419,9 +445,11 @@ begin else CurrentParticle := CurrentParticle+1; end; +{$ENDIF} end; procedure g_GFX_Spark(fX, fY: Integer; Count: Word; Angle: SmallInt; DevX, DevY: Byte); +{$IF DEFINED(HAS_COLLIDE_BITMAP)} var a: Integer; b: Single; @@ -429,7 +457,9 @@ var DevY1, DevY2: Byte; BaseVelX, BaseVelY: Single; l: Integer; +{$ENDIF} begin +{$IF DEFINED(HAS_COLLIDE_BITMAP)} l := Length(Particles); if l = 0 then Exit; @@ -480,15 +510,19 @@ begin else CurrentParticle := CurrentParticle+1; end; +{$ENDIF} end; procedure g_GFX_Water(fX, fY: Integer; Count: Word; fVelX, fVelY: Single; DevX, DevY, Color: Byte); +{$IF DEFINED(HAS_COLLIDE_BITMAP)} var a: Integer; DevX1, DevX2, DevY1, DevY2: Byte; l: Integer; +{$ENDIF} begin +{$IF DEFINED(HAS_COLLIDE_BITMAP)} l := Length(Particles); if l = 0 then Exit; @@ -562,13 +596,17 @@ begin else CurrentParticle := CurrentParticle+1; end; +{$ENDIF} end; procedure g_GFX_SimpleWater(fX, fY: Integer; Count: Word; fVelX, fVelY: Single; DefColor, CR, CG, CB: Byte); +{$IF DEFINED(HAS_COLLIDE_BITMAP)} var a: Integer; l: Integer; +{$ENDIF} begin +{$IF DEFINED(HAS_COLLIDE_BITMAP)} l := Length(Particles); if l = 0 then Exit; @@ -647,15 +685,19 @@ begin else CurrentParticle := CurrentParticle+1; end; +{$ENDIF} end; procedure g_GFX_Bubbles(fX, fY: Integer; Count: Word; DevX, DevY: Byte); +{$IF DEFINED(HAS_COLLIDE_BITMAP)} var a: Integer; DevX1, DevX2, DevY1, DevY2: Byte; l: Integer; +{$ENDIF} begin +{$IF DEFINED(HAS_COLLIDE_BITMAP)} l := Length(Particles); if l = 0 then Exit; @@ -704,6 +746,7 @@ begin else CurrentParticle := CurrentParticle+1; end; +{$ENDIF} end; procedure g_GFX_SetMax(Count: Integer); @@ -766,12 +809,15 @@ end; procedure g_GFX_Update(); var a: Integer; +{$IF DEFINED(HAS_COLLIDE_BITMAP)} w, h: Integer; dX, dY: SmallInt; b, len: Integer; s: ShortInt; c: Byte; +{$ENDIF} begin +{$IF DEFINED(HAS_COLLIDE_BITMAP)} if Particles <> nil then begin w := gMapInfo.Width; @@ -1235,6 +1281,7 @@ begin CorrectOffsets(a); end; end; // Particles <> nil +{$ENDIF} if OnceAnims <> nil then begin diff --git a/src/game/g_map.pas b/src/game/g_map.pas index 36ac907..a73434b 100644 --- a/src/game/g_map.pas +++ b/src/game/g_map.pas @@ -286,6 +286,8 @@ end; // wall index in `gWalls` or -1 function g_Map_traceToNearestWall (x0, y0, x1, y1: Integer; hitx: PInteger=nil; hity: PInteger=nil): Integer; +var + maxDistSq: Single; function sqchecker (pan: TPanel; var ray: Ray2D): Single; var @@ -298,6 +300,7 @@ function g_Map_traceToNearestWall (x0, y0, x1, y1: Integer; hitx: PInteger=nil; if not aabb.valid then exit; if aabb.intersects(ray, @tmin) then begin + //if (tmin*tmin > maxDistSq) then exit; if (tmin >= 0.0) then begin //e_WriteLog(Format('sqchecker(%d,%d,%d,%d): panel #%d (%d,%d)-(%d,%d); tmin=%f', [x0, y0, x1, y1, pan.arrIdx, pan.X, pan.Y, pan.Width, pan.Height, tmin]), MSG_NOTIFY); @@ -315,9 +318,10 @@ var begin result := -1; if (mapTree = nil) then exit; + maxDistSq := (x1-x0)*(x1-x0)+(y1-y0)*(y1-y0); if mapTree.segmentQuery(qr, x0, y0, x1, y1, sqchecker, (GridTagWall or GridTagDoor)) then begin - if (qr.flesh <> nil) then + if (qr.flesh <> nil) and (qr.time*qr.time <= maxDistSq) then begin result := qr.flesh.arrIdx; if (hitx <> nil) or (hity <> nil) then diff --git a/src/game/g_weapons.pas b/src/game/g_weapons.pas index c55931b..d52abc5 100644 --- a/src/game/g_weapons.pas +++ b/src/game/g_weapons.pas @@ -1250,6 +1250,7 @@ begin end; +(* procedure g_Weapon_gunOld(const x, y, xd, yd, v, dmg: Integer; SpawnerUID: Word; CheckTrigger: Boolean); var a: Integer; @@ -1362,6 +1363,7 @@ begin if CheckTrigger and g_Game_IsServer then g_Triggers_PressL(X, Y, xx-xi, yy-yi, SpawnerUID, ACTIVATE_SHOT); end; +*) (* @@ -1769,11 +1771,13 @@ var stt: UInt64; {$ENDIF} begin + (* if not gwep_debug_fast_trace then begin g_Weapon_gunOld(x, y, xd, yd, v, dmg, SpawnerUID, CheckTrigger); exit; end; + *) wgunMonHash.reset(); //FIXME: clear hash on level change wgunHitHeap.clear(); diff --git a/src/game/z_aabbtree.pas b/src/game/z_aabbtree.pas index 86e0568..7220653 100644 --- a/src/game/z_aabbtree.pas +++ b/src/game/z_aabbtree.pas @@ -235,7 +235,6 @@ type chkAABB: AABB2D; // for checkers qSRes: PSegmentQueryResult; // for queries // for segment query - maxFraction: Single; curax, curay: Single; curbx, curby: Single; dirx, diry: Single; @@ -1680,8 +1679,7 @@ end; function TDynAABBTreeBase.checkerRay (node: PTreeNode): Boolean; -var - tmin: Single = 0; +//var tmin: Single = 0; begin {$IF FALSE} result := node.aabb.intersects(curax, curay, curbx, curby, @tmin); @@ -1696,7 +1694,10 @@ begin Integer(result), ]), MSG_NOTIFY); {$ELSE} - result := node.aabb.intersects(traceRay, maxFraction, @tmin); + result := false; + if (node.aabb.maxX < minSingle(curax, curbx)) or (node.aabb.maxY < minSingle(curay, curby)) then exit; + if (node.aabb.minX > maxSingle(curax, curbx)) or (node.aabb.minY > maxSingle(curay, curby)) then exit; + result := node.aabb.intersects(traceRay, qSRes.time{, @tmin}); { e_WriteLog(Format('intersect: (%f,%f)-(%f,%f) (%d,%d)-(%d,%d) tmin=%f res=%d frac=%f', [ curax, curay, curbx, curby, @@ -1704,7 +1705,7 @@ begin node.aabb.maxX, node.aabb.maxY, tmin, Integer(result), - maxFraction + qSRes.time ]), MSG_NOTIFY); } {$ENDIF} @@ -1733,9 +1734,8 @@ begin if (hitFraction > 0.0) then begin // we update the maxFraction value and the ray AABB using the new maximum fraction - if (hitFraction < maxFraction) then + if (hitFraction < qSRes.time) then begin - maxFraction := hitFraction; qSRes.time := hitFraction; qSRes.flesh := flesh; // fix curb here @@ -1751,7 +1751,6 @@ end; // segment querying method function TDynAABBTreeBase.segmentQuery (out qr: TSegmentQueryResult; ax, ay, bx, by: TreeNumber; cb: TSegQueryCallback; tagmask: Integer=-1): Boolean; var - oldmaxFraction: Single; oldcurax, oldcuray: Single; oldcurbx, oldcurby: Single; olddirx, olddiry: Single; @@ -1764,7 +1763,6 @@ begin if (ax = bx) and (ay = by) then begin result := false; exit; end; - oldmaxFraction := maxFraction; oldcurax := curax; oldcuray := curay; oldcurbx := curbx; @@ -1773,7 +1771,8 @@ begin olddiry := diry; oldray := traceRay; - maxFraction := 1.0e100; // infinity + qr.time := 1.0e100; // infinity + //qr.time := sqrt((bx-ax)*(bx-ax)+(by-ay)*(by-ay))+1.0; curax := ax; curay := ay; curbx := bx; @@ -1806,7 +1805,6 @@ begin curby := oldcurby; dirx := olddirx; diry := olddiry; - maxFraction := oldmaxFraction; traceRay := oldray; result := qr.valid; -- 2.29.2