From fa608ea5bf886397e66873b1d3b72cdceb5be3fb Mon Sep 17 00:00:00 2001 From: DeaDDooMER Date: Thu, 9 Jun 2022 16:45:23 +0300 Subject: [PATCH] gl: draw gibs --- src/game/g_gibs.pas | 6 +- src/game/renders/opengl/r_draw.pas | 19 ++- src/game/renders/opengl/r_map.pas | 94 +++++++++++--- src/game/renders/opengl/r_render.pas | 5 +- src/game/renders/opengl/r_textures.pas | 163 +++++++++++++++++++++++-- 5 files changed, 251 insertions(+), 36 deletions(-) diff --git a/src/game/g_gibs.pas b/src/game/g_gibs.pas index d190384..69e5ca8 100644 --- a/src/game/g_gibs.pas +++ b/src/game/g_gibs.pas @@ -22,6 +22,7 @@ interface const DefaultGibsCount = 32; DefaultGibsMax = 150; + DefaultGibSize: TRectWH = (X: 8; Y: 8; Width: 16; Height: 16); type PGib = ^TGib; @@ -163,10 +164,7 @@ implementation {$IFDEF ENABLE_RENDER} Obj.Rect := r_Render_GetGibRect(ModelID, GibID); {$ELSE} - Obj.Rect.X := 16; - Obj.Rect.Y := 16; - Obj.Rect.Width := 16; - Obj.Rect.Height := 16; + Obj.Rect := DefaultGibSize; {$ENDIF} Obj.X := fX - Obj.Rect.X - (Obj.Rect.Width div 2); Obj.Y := fY - Obj.Rect.Y - (Obj.Rect.Height div 2); diff --git a/src/game/renders/opengl/r_draw.pas b/src/game/renders/opengl/r_draw.pas index ef2a38b..e836b30 100644 --- a/src/game/renders/opengl/r_draw.pas +++ b/src/game/renders/opengl/r_draw.pas @@ -24,6 +24,7 @@ interface procedure r_Draw_Texture (img: TGLTexture; x, y, w, h: Integer; flip: Boolean; r, g, b, a: Byte; blend: Boolean); procedure r_Draw_TextureRepeat (img: TGLTexture; x, y, w, h: Integer; flip: Boolean; r, g, b, a: Byte; blend: Boolean); + procedure r_Draw_TextureRepeatRotate (img: TGLTexture; x, y, w, h: Integer; flip: Boolean; r, g, b, a: Byte; blend: Boolean; rx, ry, angle: Integer); procedure r_Draw_MultiTextureRepeat (m: TGLMultiTexture; const anim: TAnimState; x, y, w, h: Integer; flip: Boolean; r, g, b, a: Byte; blend: Boolean); procedure r_Draw_MultiTextureRepeatRotate (m: TGLMultiTexture; const anim: TAnimState; x, y, w, h: Integer; flip: Boolean; r, g, b, a: Byte; blend: Boolean; rx, ry, angle: Integer); @@ -148,6 +149,23 @@ implementation r_Draw_Texture(img, x + i * img.width, y + j * img.height, img.width, img.height, flip, r, g, b, a, blend); end; + procedure r_Draw_TextureRepeatRotate (img: TGLTexture; x, y, w, h: Integer; flip: Boolean; r, g, b, a: Byte; blend: Boolean; rx, ry, angle: Integer); + begin + ASSERT(w >= 0); + ASSERT(h >= 0); + if a <> 0 then + begin + glPushMatrix; + glTranslatef(x + rx, y + ry, 0); + glRotatef(angle, 0, 0, 1); + glTranslatef(-(x + rx), -(y + ry), 0); + r_Draw_TextureRepeat(img, x, y, w, h, flip, r, g, b, a, blend); + glPopMatrix; + end + else + r_Draw_TextureRepeat(img, x, y, w, h, flip, r, g, b, a, blend); + end; + procedure r_Draw_MultiTextureRepeat (m: TGLMultiTexture; const anim: TAnimState; x, y, w, h: Integer; flip: Boolean; r, g, b, a: Byte; blend: Boolean); var img: TGLTexture; cur, total, i: Integer; begin @@ -170,7 +188,6 @@ implementation end; procedure r_Draw_MultiTextureRepeatRotate (m: TGLMultiTexture; const anim: TAnimState; x, y, w, h: Integer; flip: Boolean; r, g, b, a: Byte; blend: Boolean; rx, ry, angle: Integer); - var i, j: Integer; begin ASSERT(w >= 0); ASSERT(h >= 0); diff --git a/src/game/renders/opengl/r_map.pas b/src/game/renders/opengl/r_map.pas index 8438e2d..9c25806 100644 --- a/src/game/renders/opengl/r_map.pas +++ b/src/game/renders/opengl/r_map.pas @@ -17,6 +17,8 @@ unit r_map; interface + uses g_base; // TRectWH + procedure r_Map_Initialize; procedure r_Map_Finalize; @@ -26,7 +28,12 @@ interface procedure r_Map_LoadTextures; procedure r_Map_FreeTextures; +{$IFDEF ENABLE_GFX} procedure r_Map_NewGFX (typ, x, y: Integer); +{$ENDIF} +{$IFDEF ENABLE_GIBS} + function r_Map_GetGibSize (m, i: Integer): TRectWH; +{$ENDIF} procedure r_Map_Update; @@ -43,11 +50,14 @@ implementation {$ENDIF} e_log, binheap, MAPDEF, utils, - g_options, g_textures, g_basic, g_base, g_phys, + g_options, g_textures, g_basic, g_phys, g_game, g_map, g_panel, g_items, g_monsters, g_playermodel, g_player, g_weapons, {$IFDEF ENABLE_CORPSES} g_corpses, {$ENDIF} + {$IFDEF ENABLE_GIBS} + g_gibs, + {$ENDIF} {$IFDEF ENABLE_GFX} g_gfx, {$ENDIF} @@ -175,14 +185,12 @@ implementation anim: array [TDirection, 0..A_LAST] of record base, mask: TGLMultiTexture; end; -(* - {$IFDEF ENABLE_GIBS} - gibs: array of record - base, mask: TGLTexture; - rect: TRectWH; - end; - {$ENDIF} -*) +{$IFDEF ENABLE_GIBS} + gibs: record + base, mask: TGLTextureArray; + rect: TRectArray; + end; +{$ENDIF} end; StubShotAnim: TAnimState; @@ -224,6 +232,8 @@ implementation procedure r_Map_LoadModel (i: Integer); var prefix: AnsiString; a: Integer; d: TDirection; m: ^TPlayerModelInfo; begin + ASSERT(i < Length(Models)); + ASSERT(i < Length(PlayerModelsArray)); m := @PlayerModelsArray[i]; prefix := m.FileName + ':TEXTURES/'; for d := TDirection.D_LEFT to TDirection.D_RIGHT do @@ -238,18 +248,30 @@ implementation Models[i].anim[d, a].mask := r_Textures_LoadMultiFromFileAndInfo(prefix + m.anim[d, a].mask, 64, 64, m.anim[d, a].frames, m.anim[d, a].back, true); end end; -(* {$IFDEF ENABLE_GIBS} - Models[i].gibs := nil; + Models[i].gibs.base := nil; + Models[i].gibs.mask := nil; + Models[i].gibs.rect := nil; if m.GibsCount > 0 then begin - SetLength(Models[i].gibs, m.GibsCount); + SetLength(Models[i].gibs.base, m.GibsCount); + SetLength(Models[i].gibs.mask, m.GibsCount); + SetLength(Models[i].gibs.rect, m.GibsCount); + for a := 0 to m.GibsCount - 1 do + Models[i].gibs.rect[a] := DefaultGibSize; + if r_Textures_LoadStreamFromFile(prefix + m.GibsResource, 32, 32, m.GibsCount, Models[i].gibs.base, Models[i].gibs.rect) then + begin + if r_Textures_LoadStreamFromFile(prefix + m.GibsMask, 32, 32, m.GibsCount, Models[i].gibs.mask, nil) then + begin + // ok + end; + end; + for a := 0 to m.GibsCount - 1 do + e_logwritefln('model %s gib %s: %sx%s:%sx%s', [i, a, Models[i].gibs.rect[a].x, Models[i].gibs.rect[a].y, Models[i].gibs.rect[a].width, Models[i].gibs.rect[a].height]); end; {$ENDIF} -*) end; - procedure r_Map_Load; const WeapName: array [0..WP_LAST] of AnsiString = ('', 'CSAW', 'HGUN', 'SG', 'SSG', 'MGUN', 'RKT', 'PLZ', 'BFG', 'SPL', 'FLM'); @@ -750,6 +772,46 @@ implementation r_Map_DrawPlayer(gPlayers[i]); end; +{$IFDEF ENABLE_GIBS} + function r_Map_GetGibSize (m, i: Integer): TRectWH; + begin + result := Models[m].gibs.rect[i]; + end; + + procedure r_Map_DrawGibs (x, y, w, h: Integer); + var i, fx, fy, m, id, rx, ry, ra: Integer; p: PObj; t: TGLTexture; + begin + if gGibs <> nil then + begin + for i := 0 to High(gGibs) do + begin + if gGibs[i].alive then + begin + p := @gGibs[i].Obj; + if g_Obj_Collide(x, y, w, h, p) then + begin + p.Lerp(gLerpFactor, fx, fy); + id := gGibs[i].GibID; + m := gGibs[i].ModelID; + t := Models[m].gibs.base[id]; + if t <> nil then + begin + rx := p.Rect.X + p.Rect.Width div 2; + ry := p.Rect.Y + p.Rect.Height div 2; + ra := gGibs[i].RAngle; + r_Draw_TextureRepeatRotate(t, fx, fy, t.width, t.height, false, 255, 255, 255, 255, false, rx, ry, ra); + t := Models[m].gibs.mask[id]; + if t <> nil then + r_Draw_TextureRepeatRotate(t, fx, fy, t.width, t.height, false, gGibs[i].Color.R, gGibs[i].Color.G, gGibs[i].Color.B, 255, false, rx, ry, ra); + // r_Draw_TextureRepeatRotate(nil, fx + p.Rect.X, fy + p.Rect.Y, p.Rect.Width, p.Rect.Height, false, 255, 255, 255, 255, false, p.Rect.Width div 2, p.Rect.Height div 2, ra); + end; + end; + end; + end; + end; + end; +{$ENDIF} + {$IFDEF ENABLE_CORPSES} procedure r_Map_DrawCorpses (x, y, w, h: Integer); var i, fX, fY: Integer; p: TCorpse; @@ -971,7 +1033,9 @@ implementation r_Map_DrawShots(xx, yy, ww, hh); // TODO draw shells r_Map_DrawPlayers(xx, yy, ww, hh); - // TODO draw gibs + {$IFDEF ENABLE_GIBS} + r_Map_DrawGibs(xx, yy, ww, hh); + {$ENDIF} {$IFDEF ENABLE_CORPSES} r_Map_DrawCorpses(xx, yy, ww, hh); {$ENDIF} diff --git a/src/game/renders/opengl/r_render.pas b/src/game/renders/opengl/r_render.pas index e40b600..c5b2c30 100644 --- a/src/game/renders/opengl/r_render.pas +++ b/src/game/renders/opengl/r_render.pas @@ -251,10 +251,7 @@ implementation {$IFDEF ENABLE_GIBS} function r_Render_GetGibRect (m, id: Integer): TRectWH; begin - Result.X := 16; - Result.Y := 16; - Result.Width := 16; - Result.Height := 16; + result := r_Map_GetGibSize(m, id); end; {$ENDIF} diff --git a/src/game/renders/opengl/r_textures.pas b/src/game/renders/opengl/r_textures.pas index d24c2ac..ce71ebc 100644 --- a/src/game/renders/opengl/r_textures.pas +++ b/src/game/renders/opengl/r_textures.pas @@ -23,8 +23,9 @@ interface {$ELSE} GL, GLEXT, {$ENDIF} - r_atlas, - utils // SSArray + g_base, // TRectHW + utils, + r_atlas ; type @@ -97,12 +98,17 @@ interface property backAnim: Boolean read mBackanim; (* this property must be located at TAnimState? *) end; + TGLTextureArray = array of TGLTexture; + + TRectArray = array of TRectWH; + procedure r_Textures_Initialize; procedure r_Textures_Finalize; function r_Textures_LoadFromFile (const filename: AnsiString; log: Boolean = True): TGLTexture; function r_Textures_LoadMultiFromFile (const filename: AnsiString; log: Boolean = True): TGLMultiTexture; function r_Textures_LoadMultiFromFileAndInfo (const filename: AnsiString; w, h, count: Integer; backanim: Boolean; log: Boolean = True): TGLMultiTexture; + function r_Textures_LoadStreamFromFile (const filename: AnsiString; w, h, count: Integer; st: TGLTextureArray; rs: TRectArray; log: Boolean = True): Boolean; implementation @@ -115,7 +121,6 @@ implementation var maxTileSize: Integer; atl: array of TGLAtlas; -// tex: array of TGLTexture; (* --------- TGLAtlasNode --------- *) @@ -360,6 +365,14 @@ implementation end; end; + function r_Textures_FixImageData (var img: TImageData): Boolean; + begin + result := false; + if ConvertImage(img, TImageFormat.ifA8R8G8B8) then + if SwapChannels(img, ChannelRed, ChannelBlue) then // wtf + result := true; + end; + function r_Textures_LoadFromImage (var img: TImageData): TGLTexture; var t: TGLTexture; n: TGLAtlasNode; c: TDynImageDataArray; cw, ch, i, j: LongInt; begin @@ -396,9 +409,8 @@ implementation InitImage(img); try if LoadImageFromMemory(data, size, img) then - if ConvertImage(img, TImageFormat.ifA8R8G8B8) then - if SwapChannels(img, ChannelRed, ChannelBlue) then // wth - result := r_Textures_LoadFromImage(img) + if r_Textures_FixImageData(img) then + result := r_Textures_LoadFromImage(img) except end; FreeImage(img); @@ -459,9 +471,8 @@ implementation InitImage(img); try if LoadImageFromMemory(data, size, img) then - if ConvertImage(img, TImageFormat.ifA8R8G8B8) then - if SwapChannels(img, ChannelRed, ChannelBlue) then // wtf - result := r_Textures_LoadMultiFromImageAndInfo(img, w, h, c, b) + if r_Textures_FixImageData(img) then + result := r_Textures_LoadMultiFromImageAndInfo(img, w, h, c, b) except end; FreeImage(img); @@ -491,9 +502,8 @@ implementation InitImage(img); try if LoadImageFromMemory(data, size, img) then - if ConvertImage(img, TImageFormat.ifA8R8G8B8) then - if SwapChannels(img, ChannelRed, ChannelBlue) then // wtf - result := r_Textures_LoadMultiFromImageAndInfo(img, w, h, c, b) + if r_Textures_FixImageData(img) then + result := r_Textures_LoadMultiFromImageAndInfo(img, w, h, c, b) finally FreeMem(data); end; @@ -571,4 +581,133 @@ implementation end end; + function r_Textures_GetRect (var img: TImageData): TRectWH; + var i, j, w, h: Integer; done: Boolean; + + function IsVoid (i, j: Integer): Boolean; inline; + begin + result := GetPixel32(img, i, j).Channels[3] = 0 + end; + + begin + w := img.Width; + h := img.Height; + + (* 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; + end; + + function r_Textures_LoadStreamFromImage (var img: TImageData; w, h, c: Integer; st: TGLTextureArray; rs: TRectArray): Boolean; + var i: Integer; t: TImageData; + begin + ASSERT(w >= 0); + ASSERT(h >= 0); + ASSERT(c >= 1); + ASSERT((st <> nil) and (Length(st) >= c)); + ASSERT((rs = nil) or (Length(rs) >= c)); + result := true; + for i := 0 to c - 1 do + begin + InitImage(t); + st[i] := nil; + if NewImage(w, h, img.Format, t) then + begin + if CopyRect(img, w * i, 0, w, h, t, 0, 0) then + begin + if rs <> nil then + rs[i] := r_Textures_GetRect(t); + st[i] := r_Textures_LoadFromImage(t); + end; + end; + ASSERT(st[i] <> nil); + FreeImage(t); + end; + end; + + function r_Textures_LoadStreamFromMemory (data: Pointer; size: LongInt; w, h, c: Integer; st: TGLTextureArray; rs: TRectArray): Boolean; + var img: TImageData; + begin + ASSERT(w >= 0); + ASSERT(h >= 0); + ASSERT(c >= 1); + ASSERT((st <> nil) and (Length(st) >= c)); + ASSERT((rs = nil) or (Length(rs) >= c)); + result := false; + if (data <> nil) and (size > 0) then + begin + InitImage(img); + try + if LoadImageFromMemory(data, size, img) then + if r_Textures_FixImageData(img) then + result := r_Textures_LoadStreamFromImage(img, w, h, c, st, rs) + except + end; + FreeImage(img); + end; + end; + + function r_Textures_LoadStreamFromFile (const filename: AnsiString; w, h, count: Integer; st: TGLTextureArray; rs: TRectArray; log: Boolean = True): Boolean; + var wad: TWADFile; wadName, resName: AnsiString; data: Pointer; size: Integer; + begin + ASSERT(w > 0); + ASSERT(h > 0); + ASSERT(count >= 1); + ASSERT((st <> nil) and (Length(st) >= count)); + ASSERT((rs = nil) or (Length(rs) >= count)); + result := false; + wadName := g_ExtractWadName(filename); + wad := TWADFile.Create(); + if wad.ReadFile(wadName) then + begin + resName := g_ExtractFilePathName(filename); + if wad.GetResource(resName, data, size, log) then + begin + result := r_Textures_LoadStreamFromMemory(data, size, w, h, count, st, rs); + FreeMem(data); + end; + wad.Free + end + end; + end. -- 2.29.2