X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fgame%2Fopengl%2Fr_map.pas;h=a35980d798eb0b9f5f301152f515435f31832a3f;hb=a0269440c6b9e8f1f0f578f26864804f9a412b13;hp=eed9df907f484bceb2b6ff27c27c13bb573fc70c;hpb=fdec2c22a805354084c745fd93a535b66d8e3475;p=d2df-sdl.git diff --git a/src/game/opengl/r_map.pas b/src/game/opengl/r_map.pas index eed9df9..a35980d 100644 --- a/src/game/opengl/r_map.pas +++ b/src/game/opengl/r_map.pas @@ -17,25 +17,195 @@ unit r_map; interface - uses MAPDEF; // TDFColor + uses g_panel, MAPDEF, binheap; // TPanel, TDFColor + + procedure r_Map_Initialize; + procedure r_Map_Finalize; + + procedure r_Map_Load; + procedure r_Map_Free; + + procedure r_Map_LoadTextures; + procedure r_Map_FreeTextures; + + procedure r_Map_Update; - procedure r_Map_DrawBack (dx, dy: Integer); procedure r_Map_DrawPanels (PanelType: Word; hasAmbient: Boolean; constref ambColor: TDFColor); // unaccelerated procedure r_Map_CollectDrawPanels (x0, y0, wdt, hgt: Integer); procedure r_Map_DrawPanelShadowVolumes (lightX: Integer; lightY: Integer; radius: Integer); procedure r_Map_DrawFlags; + procedure r_Panel_Draw (constref p: TPanel; hasAmbient: Boolean; constref ambColor: TDFColor); + procedure r_Panel_DrawShadowVolume (constref p: TPanel; lightX, lightY: Integer; radius: Integer); + + type + TBinHeapPanelDrawCmp = class + public + class function less (const a, b: TPanel): Boolean; inline; + end; + + TBinHeapPanelDraw = specialize TBinaryHeapBase; + + var + gDrawPanelList: TBinHeapPanelDraw = nil; // binary heap of all walls we have to render, populated by `g_Map_CollectDrawPanels()` + implementation uses {$INCLUDE ../nogl/noGLuses.inc} - SysUtils, Classes, Math, - r_graphics, - g_basic, g_game, g_options, - g_panel, g_map, - r_panel + SysUtils, Classes, Math, e_log, wadreader, CONFIG, utils, g_language, + r_graphics, r_animations, r_textures, g_animations, + g_base, g_basic, g_game, g_options, + g_map ; + var + RenTextures: array of record + ID: DWORD; + Width, Height: WORD; + Anim: Boolean; + end; + FlagFrames: array [FLAG_RED..FLAG_BLUE] of DWORD; + FlagAnim: TAnimState; + + class function TBinHeapPanelDrawCmp.less (const a, b: TPanel): Boolean; inline; + begin + if (a.tag < b.tag) then begin result := true; exit; end; + if (a.tag > b.tag) then begin result := false; exit; end; + result := (a.arrIdx < b.arrIdx); + end; + + procedure r_Map_Initialize; + begin + FlagAnim := TAnimState.Create(True, 8, 5); + end; + + procedure r_Map_Finalize; + begin + FlagAnim.Invalidate; + end; + + procedure r_Map_Load; + begin + g_Frames_CreateWAD(@FlagFrames[FLAG_RED], 'FRAMES_FLAG_RED', GameWAD + ':TEXTURES\FLAGRED', 64, 64, 5, False); + g_Frames_CreateWAD(@FlagFrames[FLAG_BLUE], 'FRAMES_FLAG_BLUE', GameWAD + ':TEXTURES\FLAGBLUE', 64, 64, 5, False); + end; + + procedure r_Map_Free; + begin + g_Frames_DeleteByName('FRAMES_FLAG_RED'); + g_Frames_DeleteByName('FRAMES_FLAG_BLUE'); + end; + + procedure r_Map_LoadTextures; + const + log = True; + var + i, n: Integer; + WadName, ResName: String; + WAD, WADZ: TWADFile; + ResData, ReszData: Pointer; + ResLen, ReszLen: Integer; + cfg: TConfig; + TextureResource: String; + Width, Height: Integer; + FramesCount: Integer; + BackAnim: Boolean; + begin + if Textures <> nil then + begin + n := Length(Textures); + SetLength(RenTextures, n); + for i := 0 to n - 1 do + begin + // e_LogWritefln('r_Map_LoadTextures: -> [%s] :: [%s]', [Textures[i].FullName, Textures[i].TextureName]); + RenTextures[i].ID := LongWord(TEXTURE_NONE); + RenTextures[i].Width := 0; + RenTextures[i].Height := 0; + RenTextures[i].Anim := False; + case Textures[i].TextureName of + TEXTURE_NAME_WATER: RenTextures[i].ID := LongWord(TEXTURE_SPECIAL_WATER); + TEXTURE_NAME_ACID1: RenTextures[i].ID := LongWord(TEXTURE_SPECIAL_ACID1); + TEXTURE_NAME_ACID2: RenTextures[i].ID := LongWord(TEXTURE_SPECIAL_ACID2); + else + WadName := g_ExtractWadName(Textures[i].FullName); + ResName := g_ExtractFilePathName(Textures[i].FullName); + WAD := TWADFile.Create(); + if WAD.ReadFile(WadName) then + begin + if WAD.GetResource(ResName, ResData, ResLen, log) then + begin + if IsWadData(ResData, ResLen) then + begin + WADz := TWADFile.Create(); + if WADz.ReadMemory(ResData, ResLen) then + begin + if WADz.GetResource('TEXT/ANIM', ReszData, ReszLen) then + begin + cfg := TConfig.CreateMem(ReszData, ReszLen); + FreeMem(ReszData); + if cfg <> nil then + begin + TextureResource := cfg.ReadStr('', 'resource', ''); + Width := cfg.ReadInt('', 'framewidth', 0); + Height := cfg.ReadInt('', 'frameheight', 0); + FramesCount := cfg.ReadInt('', 'framecount', 0); + // Speed := cfg.ReadInt('', 'waitcount', 0); + BackAnim := cfg.ReadBool('', 'backanimation', False); + RenTextures[i].Width := Width; + RenTextures[i].Height := Height; + if TextureResource <> '' then + begin + if WADz.GetResource('TEXTURES/' + TextureResource, ReszData, ReszLen) then + begin + if g_Frames_CreateMemory(@RenTextures[i].ID, '', ReszData, ReszLen, Width, Height, FramesCount, BackAnim) then + RenTextures[i].Anim := True + else + e_LogWritefln('r_Map_LoadTextures: failed to create frames object (%s)', [Textures[i].FullName]); + FreeMem(ReszData) + end + else + e_LogWritefln('r_Map_LoadTextures: failed to open animation resources (%s)', [Textures[i].FullName]) + end + else + e_LogWritefln('r_Map_LoadTextures: failed to animation has no texture resource string (%s)', [Textures[i].FullName]); + cfg.Free + end + else + e_LogWritefln('r_Map_LoadTextures: failed to parse animation description (%s)', [Textures[i].FullName]) + end + else + e_LogWritefln('r_Map_LoadTextures: failed to open animation description (%s)', [Textures[i].FullName]) + end + else + e_LogWritefln('r_Map_LoadTextures: failed to open animation (%s)', [Textures[i].FullName]); + WADz.Free + end + else + begin + if e_CreateTextureMem(ResData, ResLen, RenTextures[i].ID) then + e_GetTextureSize(RenTextures[i].ID, @RenTextures[i].Width, @RenTextures[i].Height) + else + e_LogWritefln('r_Map_LoadTextures: failed to create texture (%s)', [Textures[i].FullName]) + end; + FreeMem(ResData); + end + else + e_LogWritefln('r_Map_LoadTextures: failed to open (%s)', [Textures[i].FullName]) + end + else + e_LogWritefln('r_Map_LoadTextures: failed to open %s', [WadName]); + WAD.Free; + end + end + end + end; + + procedure r_Map_FreeTextures; + begin + // TODO + end; + procedure dplClear (); begin if (gDrawPanelList = nil) then gDrawPanelList := TBinHeapPanelDraw.Create() else gDrawPanelList.clear(); @@ -95,54 +265,157 @@ begin it.release(); end; -procedure r_Map_DrawBack(dx, dy: Integer); -begin - if gDrawBackGround and (BackID <> DWORD(-1)) then - e_DrawSize(BackID, dx, dy, 0, False, False, gBackSize.X, gBackSize.Y) - else - e_Clear(GL_COLOR_BUFFER_BIT, 0, 0, 0); -end; + procedure r_Map_DrawFlags; + var i, dx, tx, ty: Integer; Mirror: TMirrorType; f: PFlag; + begin + if gGameSettings.GameMode = GM_CTF then + begin + for i := FLAG_RED to FLAG_BLUE do + begin + f := @gFlags[i]; + if not (f.State in [FLAG_STATE_NONE, FLAG_STATE_CAPTURED]) then + begin + f.Obj.lerp(gLerpFactor, tx, ty); + if f.Direction = TDirection.D_LEFT then + Mirror := TMirrorType.Horizontal + else + Mirror := TMirrorType.None; + dx := IfThen(f.Direction = TDirection.D_LEFT, -1, +1); + r_AnimState_Draw(FlagFrames[i], FlagAnim, tx + dx, ty + 1, 0, Mirror, False); + if g_debug_Frames then + e_DrawQuad(tx + f.Obj.Rect.X, ty + f.Obj.Rect.Y, tx + f.Obj.Rect.X + f.Obj.Rect.Width - 1, ty + f.Obj.Rect.Y + f.Obj.Rect.Height - 1, 0, 255, 0) + end + end + end + end; -procedure r_Map_DrawFlags(); -var - i, dx: Integer; - tx, ty: Integer; - Mirror: TMirrorType; -begin - if gGameSettings.GameMode <> GM_CTF then - Exit; + procedure Panel_Lerp (p: TPanel; t: Single; out tX, tY, tW, tH: Integer); + begin + if p.movingActive then + begin + tX := nlerp(p.OldX, p.X, t); + tY := nlerp(p.OldY, p.Y, t); + tW := nlerp(p.OldWidth, p.Width, t); + tH := nlerp(p.OldHeight, p.Height, t); + end + else + begin + tX := p.X; + tY := p.Y; + tW := p.Width; + tH := p.Height; + end; + end; - for i := FLAG_RED to FLAG_BLUE do - with gFlags[i] do - if State <> FLAG_STATE_CAPTURED then + procedure r_Panel_Draw (constref p: TPanel; hasAmbient: Boolean; constref ambColor: TDFColor); + var tx, ty, tw, th, xx, yy: Integer; NoTextureID, TextureID, FramesID: DWORD; NW, NH: Word; Texture: Cardinal; IsAnim: Boolean; w, h: Integer; + begin + if {p.Enabled and} (p.FCurTexture >= 0) and (p.Width > 0) and (p.Height > 0) and (p.Alpha < 255) {and g_Collide(X, Y, Width, Height, sX, sY, sWidth, sHeight)} then + begin + Panel_Lerp(p, gLerpFactor, tx, ty, tw, th); + Texture := p.TextureIDs[p.FCurTexture].Texture; + IsAnim := RenTextures[Texture].Anim; + if IsAnim then begin - if State = FLAG_STATE_NONE then - continue; + if p.TextureIDs[p.FCurTexture].AnTex.IsValid() then + begin + FramesID := RenTextures[Texture].ID; + w := RenTextures[Texture].Width; + h := RenTextures[Texture].Height; + for xx := 0 to tw div w - 1 do + for yy := 0 to th div h - 1 do + r_AnimState_Draw(FramesID, p.TextureIDs[p.FCurTexture].AnTex, tx + xx * w, ty + yy * h, p.Alpha, TMirrorType.None, p.Blending); + end + end + else + begin + TextureID := RenTextures[Texture].ID; + w := RenTextures[Texture].Width; + h := RenTextures[Texture].Height; + case TextureID of + LongWord(TEXTURE_SPECIAL_WATER): e_DrawFillQuad(tx, ty, tx + tw - 1, ty + th - 1, 0, 0, 255, 0, TBlending.Filter); + LongWord(TEXTURE_SPECIAL_ACID1): e_DrawFillQuad(tx, ty, tx + tw - 1, ty + th - 1, 0, 230, 0, 0, TBlending.Filter); + LongWord(TEXTURE_SPECIAL_ACID2): e_DrawFillQuad(tx, ty, tx + tw - 1, ty + th - 1, 230, 0, 0, 0, TBlending.Filter); + LongWord(TEXTURE_NONE): + if g_Texture_Get('NOTEXTURE', NoTextureID) then + begin + e_GetTextureSize(NoTextureID, @NW, @NH); + e_DrawFill(NoTextureID, tx, ty, tw div NW, th div NH, 0, False, False); + end + else + begin + xx := tx + (tw div 2); + yy := ty + (th div 2); + e_DrawFillQuad(tx, ty, xx, yy, 255, 0, 255, 0); + e_DrawFillQuad(xx, ty, tx + tw - 1, yy, 255, 255, 0, 0); + e_DrawFillQuad(tx, yy, xx, ty + th - 1, 255, 255, 0, 0); + e_DrawFillQuad(xx, yy, tx + tw - 1, ty + th - 1, 255, 0, 255, 0); + end; + else + if not p.movingActive then + e_DrawFill(TextureID, tx, ty, tw div w, th div h, p.Alpha, True, p.Blending, hasAmbient) + else + e_DrawFillX(TextureID, tx, ty, tw, th, p.Alpha, True, p.Blending, g_dbg_scale, hasAmbient); + if hasAmbient then + e_AmbientQuad(tx, ty, tw, th, ambColor.r, ambColor.g, ambColor.b, ambColor.a); + end + end + end + end; - Obj.lerp(gLerpFactor, tx, ty); + procedure r_Panel_DrawShadowVolume (constref p: TPanel; lightX, lightY: Integer; radius: Integer); + var tx, ty, tw, th: Integer; Texture: Cardinal; - if Direction = TDirection.D_LEFT then - begin - Mirror := TMirrorType.Horizontal; - dx := -1; - end - else - begin - Mirror := TMirrorType.None; - dx := 1; - end; + procedure extrude (x: Integer; y: Integer); + begin + glVertex2i(x + (x - lightX) * 500, y + (y - lightY) * 500); + //e_WriteLog(Format(' : (%d,%d)', [x + (x - lightX) * 300, y + (y - lightY) * 300]), MSG_WARNING); + end; - Animation.Draw(tx + dx, ty + 1, Mirror); + procedure drawLine (x0: Integer; y0: Integer; x1: Integer; y1: Integer); + begin + // does this side facing the light? + if ((x1 - x0) * (lightY - y0) - (lightX - x0) * (y1 - y0) >= 0) then exit; + //e_WriteLog(Format('lightpan: (%d,%d)-(%d,%d)', [x0, y0, x1, y1]), MSG_WARNING); + // this edge is facing the light, extrude and draw it + glVertex2i(x0, y0); + glVertex2i(x1, y1); + extrude(x1, y1); + extrude(x0, y0); + end; - if g_debug_Frames then - begin - e_DrawQuad(Obj.X+Obj.Rect.X, - Obj.Y+Obj.Rect.Y, - Obj.X+Obj.Rect.X+Obj.Rect.Width-1, - Obj.Y+Obj.Rect.Y+Obj.Rect.Height-1, - 0, 255, 0); + begin + if radius < 4 then exit; + if p.Enabled and (p.FCurTexture >= 0) and (p.Width > 0) and (p.Height > 0) and (p.Alpha < 255) {and g_Collide(X, Y, tw, th, sX, sY, sWidth, sHeight)} then + begin + Panel_Lerp(p, gLerpFactor, tx, ty, tw, th); + Texture := p.TextureIDs[p.FCurTexture].Texture; + if not RenTextures[Texture].Anim then + begin + case RenTextures[Texture].ID of + LongWord(TEXTURE_SPECIAL_WATER): exit; + LongWord(TEXTURE_SPECIAL_ACID1): exit; + LongWord(TEXTURE_SPECIAL_ACID2): exit; + LongWord(TEXTURE_NONE): exit; end; end; -end; + if (tx + tw < lightX - radius) then exit; + if (ty + th < lightY - radius) then exit; + if (tx > lightX + radius) then exit; + if (ty > lightY + radius) then exit; + //e_DrawFill(TextureIDs[FCurTexture].Tex, X, Y, tw div TextureWidth, th div TextureHeight, Alpha, True, Blending); + glBegin(GL_QUADS); + drawLine(tx, ty, tx + tw, ty); // top + drawLine(tx + tw, ty, tx + tw, ty + th); // right + drawLine(tx + tw, ty + th, tx, ty + th); // bottom + drawLine(tx, ty + th, tx, ty); // left + glEnd; + end + end; + + procedure r_Map_Update; + begin + FlagAnim.Update + end; end.