From 66c2f9462a91ba1d9a0910b4e085c202358a80a7 Mon Sep 17 00:00:00 2001 From: DeaDDooMER Date: Sun, 16 Jan 2022 22:46:01 +0300 Subject: [PATCH] render: hide gib textures within render --- src/game/g_player.pas | 26 ++--- src/game/g_playermodel.pas | 92 +++++------------ src/game/opengl/r_game.pas | 4 +- src/game/opengl/r_player.pas | 40 ++------ src/game/opengl/r_playermodel.pas | 157 +++++++++++++++++++++++++++--- 5 files changed, 196 insertions(+), 123 deletions(-) diff --git a/src/game/g_player.pas b/src/game/g_player.pas index 9552d30..5a0d7d7 100644 --- a/src/game/g_player.pas +++ b/src/game/g_player.pas @@ -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); diff --git a/src/game/g_playermodel.pas b/src/game/g_playermodel.pas index ca4b6dc..820c7c5 100644 --- a/src/game/g_playermodel.pas +++ b/src/game/g_playermodel.pas @@ -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 diff --git a/src/game/opengl/r_game.pas b/src/game/opengl/r_game.pas index 8396f14..931769c 100644 --- a/src/game/opengl/r_game.pas +++ b/src/game/opengl/r_game.pas @@ -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); diff --git a/src/game/opengl/r_player.pas b/src/game/opengl/r_player.pas index a4be8f8..6306e17 100644 --- a/src/game/opengl/r_player.pas +++ b/src/game/opengl/r_player.pas @@ -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 diff --git a/src/game/opengl/r_playermodel.pas b/src/game/opengl/r_playermodel.pas index f17be32..c4fe391 100644 --- a/src/game/opengl/r_playermodel.pas +++ b/src/game/opengl/r_playermodel.pas @@ -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. -- 2.29.2