DEADSOFTWARE

render: hide gib textures within render
authorDeaDDooMER <deaddoomer@deadsoftware.ru>
Sun, 16 Jan 2022 19:46:01 +0000 (22:46 +0300)
committerDeaDDooMER <deaddoomer@deadsoftware.ru>
Fri, 9 Jun 2023 07:51:59 +0000 (10:51 +0300)
src/game/g_player.pas
src/game/g_playermodel.pas
src/game/opengl/r_game.pas
src/game/opengl/r_player.pas
src/game/opengl/r_playermodel.pas

index 9552d30d2b111a22e1307dcf6001dfc9840f4e25..5a0d7d7cb525a27b2cd189e55c1ba8226efc592b 100644 (file)
@@ -23,7 +23,7 @@ uses
   {$IFDEF USE_MEMPOOL}mempool,{$ENDIF}
   g_base, g_playermodel, g_basic, g_textures,
   g_weapons, g_phys, g_sound, g_saveload, MAPDEF,
-  g_panel;
+  g_panel, r_playermodel;
 
 const
   KEY_LEFT       = 1;
@@ -523,12 +523,13 @@ type
   PGib = ^TGib;
   TGib = record
     alive:    Boolean;
-    ID:       DWORD;
-    MaskID:   DWORD;
     RAngle:   Integer;
     Color:    TRGB;
     Obj:      TObj;
 
+    ModelID: Integer;
+    GibID: Integer;
+
     procedure getMapBox (out x, y, w, h: Integer); inline;
     procedure moveBy (dx, dy: Integer); inline;
 
@@ -1594,27 +1595,30 @@ end;
 
 procedure g_Player_CreateGibs(fX, fY: Integer; ModelName: string; fColor: TRGB);
 var
-  a: Integer;
+  a, mid: Integer;
   GibsArray: TGibsArray;
   Blood: TModelBlood;
 begin
   if (gGibs = nil) or (Length(gGibs) = 0) then
     Exit;
-  if not g_PlayerModel_GetGibs(ModelName, GibsArray) then
+  mid := g_PlayerModel_GetIndex(ModelName);
+  if mid = -1 then
+    Exit;
+  if not g_PlayerModel_GetGibs(mid, GibsArray) then
     Exit;
-  Blood := g_PlayerModel_GetBlood(ModelName);
+  Blood := PlayerModelsArray[mid].Blood;
 
   for a := 0 to High(GibsArray) do
     with gGibs[CurrentGib] do
     begin
+      ModelID := mid;
+      GibID := GibsArray[a];
       Color := fColor;
-      ID := GibsArray[a].ID;
-      MaskID := GibsArray[a].MaskID;
       alive := True;
       g_Obj_Init(@Obj);
-      Obj.Rect := GibsArray[a].Rect;
-      Obj.X := fX-GibsArray[a].Rect.X-(GibsArray[a].Rect.Width div 2);
-      Obj.Y := fY-GibsArray[a].Rect.Y-(GibsArray[a].Rect.Height div 2);
+      Obj.Rect := r_PlayerModel_GetGibRect(ModelID, GibID);
+      Obj.X := fX - Obj.Rect.X - (Obj.Rect.Width div 2);
+      Obj.Y := fY - Obj.Rect.Y - (Obj.Rect.Height div 2);
       g_Obj_PushA(@Obj, 25 + Random(10), Random(361));
       positionChanged(); // this updates spatial accelerators
       RAngle := Random(360);
index ca4b6dc6c4fc92ae6e1ef9eab5f6171cc5c36cd4..820c7c5c52ad72bcfa0e5a49dfef8afb19e2381b 100644 (file)
@@ -85,15 +85,9 @@ type
     Level: Byte;
   end;
 
-  TGibSprite = record
-    ID: DWORD;
-    MaskID: DWORD;
-    Rect: TRectWH;
-    OnlyOne: Boolean;
-  end;
-
   TModelSoundArray = Array of TModelSound;
-  TGibsArray = Array of TGibSprite;
+
+  TGibsArray = Array of Integer;
 
   TPlayerModel = class{$IFDEF USE_MEMPOOL}(TPoolObject){$ENDIF}
   private
@@ -141,9 +135,8 @@ function  g_PlayerModel_GetNames(): SSArray;
 function  g_PlayerModel_GetBlood(ModelName: String): TModelBlood;
 function  g_PlayerModel_Get(ModelName: String): TPlayerModel;
 function  g_PlayerModel_GetAnim(ModelName: String; AnimTyp: Byte; var _Anim, _Mask: TAnimation): Boolean;
-function  g_PlayerModel_GetGibs(ModelName: String; var Gibs: TGibsArray): Boolean;
-
-function g_PlayerModel_GetIndex (ModelName: String): Integer;
+function  g_PlayerModel_GetGibs (ModelID: Integer; var Gibs: TGibsArray): Boolean;
+function  g_PlayerModel_GetIndex (ModelName: String): Integer;
 
 (* --- private data --- *)
 
@@ -157,7 +150,6 @@ function g_PlayerModel_GetIndex (ModelName: String): Integer;
       FlagPoint:    TDFPoint;
       FlagAngle:    SmallInt;
       WeaponPoints: TWeaponPoints;
-      Gibs:         TGibsArray; // !!! move to render
       PainSounds:   TModelSoundArray;
       DieSounds:    TModelSoundArray;
       SlopSound:    Byte;
@@ -368,10 +360,10 @@ end;
 function g_PlayerModel_Load(FileName: string): Boolean;
 var
   ID: DWORD;
-  a, b, len, lenpd, lenpd2, aa, bb, f: Integer;
+  a, b, len, aa, bb, f: Integer;
   cc: TDirection;
   config: TConfig;
-  pData, pData2: Pointer;
+  pData: Pointer;
   WAD: TWADFile;
   s: string;
   prefix: string;
@@ -508,26 +500,6 @@ begin
     GibsMask := config.ReadStr('Gibs', 'mask', 'GIBSMASK');
     GibsOnce := config.ReadInt('Gibs', 'once', -1);
 
-    SetLength(Gibs, GibsCount); // !!! remove load
-    if (Gibs <> nil) and
-       (WAD.GetResource('TEXTURES/' + GibsResource, pData, lenpd)) and
-       (WAD.GetResource('TEXTURES/' + GibsMask, pData2, lenpd2)) then
-    begin
-      for a := 0 to High(Gibs) do
-        if e_CreateTextureMemEx(pData, lenpd, Gibs[a].ID, a*32, 0, 32, 32) and
-          e_CreateTextureMemEx(pData2, lenpd2, Gibs[a].MaskID, a*32, 0, 32, 32) then
-        begin
-          //Gibs[a].Rect := e_GetTextureSize2(Gibs[a].ID);
-          Gibs[a].Rect := g_PlayerModel_CalcGibSize(pData, lenpd, a*32, 0, 32, 32);
-          with Gibs[a].Rect do
-            if Height > 3 then Height := Height-1-Random(2);
-          Gibs[a].OnlyOne := GibsOnce = a + 1;
-        end;
-
-      FreeMem(pData);
-      FreeMem(pData2);
-    end;
-
     ok := True;
     for aa := WP_FIRST + 1 to WP_LAST do
       for bb := A_STAND to A_LAST do
@@ -693,44 +665,34 @@ begin
   Result := True;
 end;
 
-function g_PlayerModel_GetGibs(ModelName: string; var Gibs: TGibsArray): Boolean;
-var
-  a, i, b: Integer;
-  c: Boolean;
-begin
-  Result := False;
-
-  if PlayerModelsArray = nil then Exit;
-  if gGibsCount = 0 then Exit;
-
-  c := False;
-
-  SetLength(Gibs, gGibsCount);
+  function g_PlayerModel_GetGibs (ModelID: Integer; var Gibs: TGibsArray): Boolean;
+    var i, b: Integer; c: Boolean;
+  begin
+    Gibs := nil;
+    Result := False;
+    if (PlayerModelsArray = nil) or (gGibsCount = 0) then
+      Exit;
 
-  for a := 0 to High(PlayerModelsArray) do
-    if PlayerModelsArray[a].Name = ModelName then
+    c := False;
+    SetLength(Gibs, gGibsCount);
+    for i := 0 to High(Gibs) do
     begin
-      for i := 0 to High(Gibs) do
+      if c and (PlayerModelsArray[ModelID].GibsCount = 1) then
       begin
-        if c and (Length(PlayerModelsArray[a].Gibs) = 1) then
-        begin
-          SetLength(Gibs, i);
-          Break;
-        end;
-
-        repeat
-          b := Random(Length(PlayerModelsArray[a].Gibs));
-        until not (PlayerModelsArray[a].Gibs[b].OnlyOne and c);
+        SetLength(Gibs, i);
+        Break;
+      end;
 
-        Gibs[i] := PlayerModelsArray[a].Gibs[b];
+      repeat
+        b := Random(PlayerModelsArray[ModelID].GibsCount);
+      until not ((PlayerModelsArray[ModelID].GibsOnce = b + 1) and c);
 
-        if Gibs[i].OnlyOne then c := True;
-      end;
+      Gibs[i] := b;
 
-      Result := True;
-      Break;
+      c := PlayerModelsArray[ModelID].GibsOnce = b + 1;
     end;
-end;
+    Result := True;
+  end;
 
 function g_PlayerModel_GetNames(): SSArray;
 var
index 8396f14a48065e03ba95f2337a6973f186efc289..931769c8fd2fee7ba6fe2631d5c1a4c1a258f511 100644 (file)
@@ -35,7 +35,8 @@ implementation
     e_input, e_sound,
     g_language, g_console, g_menu, g_triggers, g_player, g_options, g_monsters, g_map, g_panel,
     g_items, g_weapons, g_gfx, g_phys, g_net, g_gui, g_netmaster,
-    g_game, r_console, r_gfx, r_items, r_map, r_panel, r_monsters, r_weapons, r_netmaster, r_player, r_textures
+    g_game, r_console, r_gfx, r_items, r_map, r_panel, r_monsters, r_weapons, r_netmaster, r_player, r_textures,
+    r_playermodel
   ;
 
   var
@@ -1304,6 +1305,7 @@ begin
   drawOther('weapons', @r_Weapon_Draw);
   drawOther('shells', @r_Player_DrawShells);
   drawOther('drawall', @r_Player_DrawAll);
+  drawOther('gibs', @r_PlayerModel_DrawGibs);
   drawOther('corpses', @r_Player_DrawCorpses);
   drawPanelType('*wall', PANEL_WALL, g_rlayer_wall);
   drawOther('monsters', @r_Monsters_Draw);
index a4be8f8b1e03aa71fb5a0675710d138e0d288103..6306e171713a69eff076b9e77bddfa3908abcc8c 100644 (file)
@@ -97,38 +97,14 @@ begin
     end;
 end;
 
-procedure r_Player_DrawCorpses;
-var
-  i, fX, fY: Integer;
-  a: TDFPoint;
-begin
-  if gGibs <> nil then
-    for i := 0 to High(gGibs) do
-      if gGibs[i].alive then
-        with gGibs[i] do
-        begin
-          if not g_Obj_Collide(sX, sY, sWidth, sHeight, @Obj) then
-            Continue;
-
-          Obj.lerp(gLerpFactor, fX, fY);
-
-          a.X := Obj.Rect.X+(Obj.Rect.Width div 2);
-          a.y := Obj.Rect.Y+(Obj.Rect.Height div 2);
-
-          e_DrawAdv(ID, fX, fY, 0, True, False, RAngle, @a, TMirrorType.None);
-
-          e_Colors := Color;
-          e_DrawAdv(MaskID, fX, fY, 0, True, False, RAngle, @a, TMirrorType.None);
-          e_Colors.R := 255;
-          e_Colors.G := 255;
-          e_Colors.B := 255;
-        end;
-
-  if gCorpses <> nil then
-    for i := 0 to High(gCorpses) do
-      if gCorpses[i] <> nil then
-        r_Player_DrawCorpse(gCorpses[i])
-end;
+  procedure r_Player_DrawCorpses;
+    var i: Integer;
+  begin
+    if gCorpses <> nil then
+      for i := 0 to High(gCorpses) do
+        if gCorpses[i] <> nil then
+          r_Player_DrawCorpse(gCorpses[i])
+  end;
 
 procedure r_Player_DrawShells;
 var
index f17be32d3e1ed99f8a1a6e9cd70761cb9ba0f0ac..c4fe391680359245ceb2fa49000a899ed6e60774 100644 (file)
@@ -17,7 +17,7 @@ unit r_playermodel;
 
 interface
 
-  uses g_playermodel; // TPlayerModel
+  uses g_playermodel, g_base; // TPlayerModel, TRectWH
 
   procedure r_PlayerModel_Initialize;
   procedure r_PlayerModel_Finalize;
@@ -25,15 +25,18 @@ interface
   procedure r_PlayerModel_Free;
   procedure r_PlayerModel_Update;
   procedure r_PlayerModel_Draw (pm: TPlayerModel; X, Y: Integer; Alpha: Byte = 0);
+  procedure r_PlayerModel_DrawGibs;
+
+  function r_PlayerModel_GetGibRect (m, id: Integer): TRectWH;
 
 implementation
 
   uses
     SysUtils, Classes, Math,
-    MAPDEF, utils,
+    MAPDEF, utils, e_log, wadreader,
     ImagingTypes, Imaging, ImagingUtility,
     r_graphics, g_options, r_animations, r_textures,
-    g_base, g_basic, g_map, g_weapons, g_textures
+    g_basic, g_map, g_weapons, g_textures, g_player, g_phys, g_game
   ;
 
   const
@@ -50,11 +53,21 @@ implementation
         base: DWORD;
         mask: DWORD;
       end;
+      Gibs: Array of record
+        base: DWORD;
+        mask: DWORD;
+        rect: TRectWH;
+      end;
     end;
     RedFlagFrames: DWORD;
     BlueFlagFrames: DWORD;
     FlagAnimState: TAnimationState;
 
+  function r_PlayerModel_GetGibRect (m, id: Integer): TRectWH;
+  begin
+    Result := Models[m].Gibs[id].rect
+  end;
+
   procedure r_PlayerModel_Initialize;
   begin
     FlagAnimState := TAnimationState.Create(True, 8, 5);
@@ -96,8 +109,83 @@ implementation
     end;
   end;
 
+  procedure r_PlayerModel_LoadResource (resource: AnsiString; var pData: Pointer; var len: Integer);
+    var WAD: TWADFile;
+  begin
+    pData := nil;
+    len := 0;
+    WAD := TWADFile.Create;
+    WAD.ReadFile(g_ExtractWadName(resource));
+    WAD.GetResource(g_ExtractFilePathName(resource), pData, len);
+    WAD.Free;
+  end;
+
+  function g_PlayerModel_CalcGibSize (pData: Pointer; dataSize, x, y, w, h: Integer): TRectWH;
+    var i, j: Integer; done: Boolean; img: TImageData;
+
+    function IsVoid (i, j: Integer): Boolean;
+    begin
+      result := Byte((PByte(img.bits) + (y+j)*img.width*4 + (x+i)*4 + 3)^) = 0
+    end;
+
+  begin
+    InitImage(img);
+    assert(LoadImageFromMemory(pData, dataSize, img));
+
+    (* trace x from right to left *)
+    done := false; i := 0;
+    while not done and (i < w) do
+    begin
+      j := 0;
+      while (j < h) and IsVoid(i, j) do inc(j);
+      done := (j < h) and (IsVoid(i, j) = false);
+      result.x := i;
+      inc(i);
+    end;
+
+    (* trace y from up to down *)
+    done := false; j := 0;
+    while not done and (j < h) do
+    begin
+      i := 0;
+      while (i < w) and IsVoid(i, j) do inc(i);
+      done := (i < w) and (IsVoid(i, j) = false);
+      result.y := j;
+      inc(j);
+    end;
+
+    (* trace x from right to left *)
+    done := false; i := w - 1;
+    while not done and (i >= 0) do
+    begin
+      j := 0;
+      while (j < h) and IsVoid(i, j) do inc(j);
+      done := (j < h) and (IsVoid(i, j) = false);
+      result.width := i - result.x + 1;
+      dec(i);
+    end;
+
+    (* trace y from down to up *)
+    done := false; j := h - 1;
+    while not done and (j >= 0) do
+    begin
+      i := 0;
+      while (i < w) and IsVoid(i, j) do inc(i);
+      done := (i < w) and (IsVoid(i, j) = false);
+      result.height := j - result.y + 1;
+      dec(j);
+    end;
+
+    FreeImage(img);
+  end;
+
   procedure r_PlayerModel_Load;
-    var ID1, ID2: DWORD; i, a, b: Integer; prefix, aname: String;
+    var
+      ID1, ID2: DWORD;
+      i, a, b: Integer;
+      prefix, aname: String;
+      base, mask: Pointer;
+      baseLen, maskLen: Integer;
   begin
     g_Frames_CreateWAD(@RedFlagFrames, 'FRAMES_FLAG_RED', GameWAD + ':TEXTURES\FLAGRED', 64, 64, 5, False);
     g_Frames_CreateWAD(@BlueFlagFrames, 'FRAMES_FLAG_BLUE', GameWAD + ':TEXTURES\FLAGBLUE', 64, 64, 5, False);
@@ -145,6 +233,28 @@ implementation
               Models[i].Frames[TDirection.D_LEFT, b].mask := ID2;
             end
           end
+        end;
+        SetLength(Models[i].Gibs, PlayerModelsArray[i].GibsCount);
+        if PlayerModelsArray[i].GibsCount > 0 then
+        begin
+          r_PlayerModel_LoadResource(prefix + PlayerModelsArray[i].GibsResource, base, baseLen);
+          r_PlayerModel_LoadResource(prefix + PlayerModelsArray[i].GibsMask, mask, maskLen);
+          if (base <> nil) and (mask <> nil) then
+          begin
+            for a := 0 to PlayerModelsArray[i].GibsCount - 1 do
+            begin
+              if e_CreateTextureMemEx(base, baseLen, Models[i].Gibs[a].base, a * 32, 0, 32, 32) and
+                 e_CreateTextureMemEx(mask, maskLen, Models[i].Gibs[a].mask, a * 32, 0, 32, 32) then
+              begin
+                Models[i].Gibs[a].rect := g_PlayerModel_CalcGibSize(base, baseLen, a * 32, 0, 32, 32);
+                with Models[i].Gibs[a].Rect do
+                  if Height > 3 then
+                    Height := Height - 1 - Random(2); // ???
+              end
+            end
+          end;
+          FreeMem(mask);
+          FreeMem(base);
         end
       end
     end
@@ -167,17 +277,8 @@ implementation
           g_Frames_DeleteByName(Name + '_RIGHTANIM' + IntToStr(a));
           g_Frames_DeleteByName(Name + '_RIGHTANIM' + IntToStr(a) + '_MASK');
         end;
-        if Gibs <> nil then
-        begin
-          for a := 0 to High(Gibs) do
-          begin
-            e_DeleteTexture(Gibs[a].ID);
-            e_DeleteTexture(Gibs[a].MaskID);
-            Gibs[a].ID := DWORD(-1);
-            Gibs[a].MaskID := DWORD(-1);
-          end
-        end
       end
+      // !!! delete gibs textures here
     end;
     for a := WP_FIRST + 1 to WP_LAST do
       for b := W_POS_NORMAL to W_POS_DOWN do
@@ -294,4 +395,32 @@ begin
   e_Colors.B := 255;
 end;
 
+  procedure r_PlayerModel_DrawGibs;
+    var i, fX, fY, m, id: Integer; a: TDFPoint; pobj: ^TObj;
+  begin
+    if gGibs <> nil then
+    begin
+      for i := 0 to High(gGibs) do
+      begin
+        if gGibs[i].alive then
+        begin
+          pobj := @gGibs[i].Obj;
+          if not g_Obj_Collide(sX, sY, sWidth, sHeight, pobj) then
+            Continue;
+          pobj.lerp(gLerpFactor, fX, fY);
+          a.X := pobj.Rect.X + (pobj.Rect.Width div 2);
+          a.y := pobj.Rect.Y + (pobj.Rect.Height div 2);
+          m := gGibs[i].ModelID;
+          id := gGibs[i].GibID;
+          e_DrawAdv(Models[m].Gibs[id].base, fX, fY, 0, True, False, gGibs[i].RAngle, @a, TMirrorType.None);
+          e_Colors := gGibs[i].Color;
+          e_DrawAdv(Models[m].Gibs[id].mask, fX, fY, 0, True, False, gGibs[i].RAngle, @a, TMirrorType.None);
+          e_Colors.R := 255;
+          e_Colors.G := 255;
+          e_Colors.B := 255;
+        end
+      end
+    end
+  end;
+
 end.