DEADSOFTWARE

render: hide gib textures within render
[d2df-sdl.git] / src / game / opengl / r_playermodel.pas
index 0914bd007798e7991277bddd9ee3c43cae32b4cc..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);
@@ -119,7 +207,7 @@ implementation
         prefix := PlayerModelsArray[i].FileName + ':TEXTURES\';
         for b := A_STAND to A_LAST do
         begin
-          aname := PlayerModelsArray[i].Info.Name + '_RIGHTANIM' + IntToStr(b);
+          aname := PlayerModelsArray[i].Name + '_RIGHTANIM' + IntToStr(b);
           with PlayerModelsArray[i].Anim[TDirection.D_RIGHT, b] do
           begin
             if not (g_Frames_CreateWAD(@ID1, aname, prefix + Resource, 64, 64, Frames, Back) and
@@ -127,7 +215,7 @@ implementation
             begin
               if b > A_LASTBASE then
               begin
-                ExtAnimFromBaseAnim(PlayerModelsArray[i].Info.Name, b);
+                ExtAnimFromBaseAnim(PlayerModelsArray[i].Name, b);
                 continue
               end
             end;
@@ -138,13 +226,35 @@ implementation
           begin
             if (Resource <> '') and (Mask <> '') then
             begin
-              aname := PlayerModelsArray[i].Info.Name + '_LEFTANIM' + IntToStr(b);
+              aname := PlayerModelsArray[i].Name + '_LEFTANIM' + IntToStr(b);
               g_Frames_CreateWAD(@ID1, aname, prefix + Resource, 64, 64, Frames, Back);
               g_Frames_CreateWAD(@ID2, aname + '_MASK', prefix + Mask, 64, 64, Frames, Back);
               Models[i].Frames[TDirection.D_LEFT, b].base := ID1;
               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
@@ -162,22 +272,13 @@ implementation
       begin
         for a := A_STAND to A_LAST do
         begin
-          g_Frames_DeleteByName(Info.Name+'_LEFTANIM'+IntToStr(a));
-          g_Frames_DeleteByName(Info.Name+'_LEFTANIM'+IntToStr(a)+'_MASK');
-          g_Frames_DeleteByName(Info.Name+'_RIGHTANIM'+IntToStr(a));
-          g_Frames_DeleteByName(Info.Name+'_RIGHTANIM'+IntToStr(a)+'_MASK');
+          g_Frames_DeleteByName(Name + '_LEFTANIM' + IntToStr(a));
+          g_Frames_DeleteByName(Name + '_LEFTANIM' + IntToStr(a) + '_MASK');
+          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
@@ -232,7 +333,7 @@ begin
   else
     Mirror := TMirrorType.Horizontal;
 
-  if PlayerModelsArray[pm.id].Info.HaveWeapon and (not (pm.CurrentAnimation in [A_DIE1, A_DIE2, A_PAIN])) and  (pm.CurrentWeapon in [WP_FIRST + 1..WP_LAST]) then
+  if PlayerModelsArray[pm.id].HaveWeapon and (not (pm.CurrentAnimation in [A_DIE1, A_DIE2, A_PAIN])) and  (pm.CurrentWeapon in [WP_FIRST + 1..WP_LAST]) then
   begin
     if pm.CurrentAnimation in [A_SEEUP, A_ATTACKUP] then
       pos := W_POS_UP
@@ -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.